File indexing completed on 2024-06-16 07:42:24

0001 /*
0002     SPDX-FileCopyrightText: 2006-2009 Sebastian Trueg <trueg@k3b.org>
0003     SPDX-FileCopyrightText: 1998-2009 Sebastian Trueg <trueg@k3b.org>
0004 
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 #include "k3bactivepipe.h"
0009 
0010 #include <QDebug>
0011 #include <QIODevice>
0012 #include <QThread>
0013 
0014 
0015 class K3b::ActivePipe::Private : public QThread
0016 {
0017 public:
0018     Private( K3b::ActivePipe* pipe ) :
0019         m_pipe( pipe ),
0020         sourceIODevice(0),
0021         sinkIODevice(0),
0022         closeSinkIODevice( false ),
0023         closeSourceIODevice( false ) {
0024     }
0025 
0026     void run() override {
0027         qDebug() << "(K3b::ActivePipe) writing from" << sourceIODevice << "to" << sinkIODevice;
0028 
0029         bytesRead = bytesWritten = 0;
0030         buffer.resize( 10*2048 );
0031 
0032         bool fail = false;
0033         qint64 r = 0;
0034         while( !fail && ( r = m_pipe->readData( buffer.data(), buffer.size() ) ) > 0 ) {
0035             bytesRead += r;
0036 
0037             ssize_t w = 0;
0038             ssize_t ww = 0;
0039             while( w < r ) {
0040                 if( ( ww = m_pipe->write( buffer.data()+w, r-w ) ) > 0 ) {
0041                     w += ww;
0042                     bytesWritten += ww;
0043                 }
0044                 else {
0045                     qDebug() << "write failed." << sinkIODevice->errorString();
0046                     fail = true;
0047                     break;
0048                 }
0049             }
0050         }
0051 
0052         if ( r < 0 ) {
0053             qDebug() << "Read failed:" << sourceIODevice->errorString();
0054         }
0055 
0056         qDebug() << "Done:"
0057                  << ( fail ? QLatin1String( "write failed" ) : QLatin1String( "write success" ) )
0058                  << ( r != 0 ? QLatin1String( "read failed" ) : QLatin1String( "read success" ) )
0059                  << "(total bytes read/written:" << bytesRead << "/" << bytesWritten << ")";
0060     }
0061 
0062     void _k3b_close() {
0063         qDebug();
0064         if ( closeWhenDone )
0065             m_pipe->close();
0066     }
0067 
0068 private:
0069     K3b::ActivePipe* m_pipe;
0070 
0071 public:
0072     QIODevice* sourceIODevice;
0073     QIODevice* sinkIODevice;
0074 
0075     bool closeWhenDone;
0076     bool closeSinkIODevice;
0077     bool closeSourceIODevice;
0078 
0079     QByteArray buffer;
0080 
0081     quint64 bytesRead;
0082     quint64 bytesWritten;
0083 };
0084 
0085 
0086 K3b::ActivePipe::ActivePipe()
0087 {
0088     d = new Private( this );
0089     connect( d, SIGNAL(finished()), this, SLOT(_k3b_close()) );
0090 }
0091 
0092 
0093 K3b::ActivePipe::~ActivePipe()
0094 {
0095     delete d;
0096 }
0097 
0098 
0099 bool K3b::ActivePipe::open( OpenMode mode )
0100 {
0101     return QIODevice::open( mode );
0102 }
0103 
0104 
0105 bool K3b::ActivePipe::open( bool closeWhenDone )
0106 {
0107     if( d->isRunning() )
0108         return false;
0109 
0110     QIODevice::open( ReadWrite|Unbuffered );
0111 
0112     d->closeWhenDone = closeWhenDone;
0113 
0114     if( d->sourceIODevice && !d->sourceIODevice->isOpen() ) {
0115         qDebug() << "Need to open source device:" << d->sourceIODevice;
0116         if( !d->sourceIODevice->open( QIODevice::ReadOnly ) )
0117             return false;
0118     }
0119 
0120     if( d->sinkIODevice && !d->sinkIODevice->isOpen()  ) {
0121         qDebug() << "Need to open sink device:" << d->sinkIODevice;
0122         if( !d->sinkIODevice->open( QIODevice::WriteOnly ) )
0123             return false;
0124     }
0125 
0126     qDebug() << "(K3b::ActivePipe) successfully opened pipe.";
0127 
0128     // we only do active piping if both devices are set.
0129     // Otherwise we only work as a conduit
0130     if ( d->sourceIODevice && d->sinkIODevice ) {
0131         d->start();
0132     }
0133 
0134     return true;
0135 }
0136 
0137 
0138 void K3b::ActivePipe::close()
0139 {
0140     qDebug();
0141     if( d->sourceIODevice && d->closeSourceIODevice )
0142         d->sourceIODevice->close();
0143     if( d->sinkIODevice && d->closeSinkIODevice )
0144         d->sinkIODevice->close();
0145     d->wait();
0146 }
0147 
0148 
0149 void K3b::ActivePipe::readFrom( QIODevice* dev, bool close )
0150 {
0151     d->sourceIODevice = dev;
0152     d->closeSourceIODevice = close;
0153 }
0154 
0155 
0156 void K3b::ActivePipe::writeTo( QIODevice* dev, bool close )
0157 {
0158     d->sinkIODevice = dev;
0159     d->closeSinkIODevice = close;
0160 }
0161 
0162 
0163 qint64 K3b::ActivePipe::readData( char* data, qint64 max )
0164 {
0165     if( d->sourceIODevice ) {
0166         return d->sourceIODevice->read( data, max );
0167     }
0168 
0169     return -1;
0170 }
0171 
0172 
0173 qint64 K3b::ActivePipe::writeData( const char* data, qint64 max )
0174 {
0175     if( d->sinkIODevice ) {
0176         return d->sinkIODevice->write( data, max );
0177     }
0178     else
0179         return -1;
0180 }
0181 
0182 
0183 quint64 K3b::ActivePipe::bytesRead() const
0184 {
0185     return d->bytesRead;
0186 }
0187 
0188 
0189 quint64 K3b::ActivePipe::bytesWritten() const
0190 {
0191     return d->bytesWritten;
0192 }
0193 
0194 #include "moc_k3bactivepipe.cpp"