1 /*
2 SPDX-FileCopyrightText: 2006-2009 Sebastian Trueg <trueg@k3b.org>
3 SPDX-FileCopyrightText: 1998-2009 Sebastian Trueg <trueg@k3b.org>
4
5 SPDX-License-Identifier: GPL-2.0-or-later
6 */
7
8 #include "k3bactivepipe.h"
9
10 #include <QDebug>
11 #include <QIODevice>
12 #include <QThread>
13
14
15 class K3b::ActivePipe::Private : public QThread
16 {
17 public:
Private(K3b::ActivePipe * pipe)18 Private( K3b::ActivePipe* pipe ) :
19 m_pipe( pipe ),
20 sourceIODevice(0),
21 sinkIODevice(0),
22 closeSinkIODevice( false ),
23 closeSourceIODevice( false ) {
24 }
25
run()26 void run() override {
27 qDebug() << "(K3b::ActivePipe) writing from" << sourceIODevice << "to" << sinkIODevice;
28
29 bytesRead = bytesWritten = 0;
30 buffer.resize( 10*2048 );
31
32 bool fail = false;
33 qint64 r = 0;
34 while( !fail && ( r = m_pipe->readData( buffer.data(), buffer.size() ) ) > 0 ) {
35 bytesRead += r;
36
37 ssize_t w = 0;
38 ssize_t ww = 0;
39 while( w < r ) {
40 if( ( ww = m_pipe->write( buffer.data()+w, r-w ) ) > 0 ) {
41 w += ww;
42 bytesWritten += ww;
43 }
44 else {
45 qDebug() << "write failed." << sinkIODevice->errorString();
46 fail = true;
47 break;
48 }
49 }
50 }
51
52 if ( r < 0 ) {
53 qDebug() << "Read failed:" << sourceIODevice->errorString();
54 }
55
56 qDebug() << "Done:"
57 << ( fail ? QLatin1String( "write failed" ) : QLatin1String( "write success" ) )
58 << ( r != 0 ? QLatin1String( "read failed" ) : QLatin1String( "read success" ) )
59 << "(total bytes read/written:" << bytesRead << "/" << bytesWritten << ")";
60 }
61
_k3b_close()62 void _k3b_close() {
63 qDebug();
64 if ( closeWhenDone )
65 m_pipe->close();
66 }
67
68 private:
69 K3b::ActivePipe* m_pipe;
70
71 public:
72 QIODevice* sourceIODevice;
73 QIODevice* sinkIODevice;
74
75 bool closeWhenDone;
76 bool closeSinkIODevice;
77 bool closeSourceIODevice;
78
79 QByteArray buffer;
80
81 quint64 bytesRead;
82 quint64 bytesWritten;
83 };
84
85
ActivePipe()86 K3b::ActivePipe::ActivePipe()
87 {
88 d = new Private( this );
89 connect( d, SIGNAL(finished()), this, SLOT(_k3b_close()) );
90 }
91
92
~ActivePipe()93 K3b::ActivePipe::~ActivePipe()
94 {
95 delete d;
96 }
97
98
open(OpenMode mode)99 bool K3b::ActivePipe::open( OpenMode mode )
100 {
101 return QIODevice::open( mode );
102 }
103
104
open(bool closeWhenDone)105 bool K3b::ActivePipe::open( bool closeWhenDone )
106 {
107 if( d->isRunning() )
108 return false;
109
110 QIODevice::open( ReadWrite|Unbuffered );
111
112 d->closeWhenDone = closeWhenDone;
113
114 if( d->sourceIODevice && !d->sourceIODevice->isOpen() ) {
115 qDebug() << "Need to open source device:" << d->sourceIODevice;
116 if( !d->sourceIODevice->open( QIODevice::ReadOnly ) )
117 return false;
118 }
119
120 if( d->sinkIODevice && !d->sinkIODevice->isOpen() ) {
121 qDebug() << "Need to open sink device:" << d->sinkIODevice;
122 if( !d->sinkIODevice->open( QIODevice::WriteOnly ) )
123 return false;
124 }
125
126 qDebug() << "(K3b::ActivePipe) successfully opened pipe.";
127
128 // we only do active piping if both devices are set.
129 // Otherwise we only work as a conduit
130 if ( d->sourceIODevice && d->sinkIODevice ) {
131 d->start();
132 }
133
134 return true;
135 }
136
137
close()138 void K3b::ActivePipe::close()
139 {
140 qDebug();
141 if( d->sourceIODevice && d->closeSourceIODevice )
142 d->sourceIODevice->close();
143 if( d->sinkIODevice && d->closeSinkIODevice )
144 d->sinkIODevice->close();
145 d->wait();
146 }
147
148
readFrom(QIODevice * dev,bool close)149 void K3b::ActivePipe::readFrom( QIODevice* dev, bool close )
150 {
151 d->sourceIODevice = dev;
152 d->closeSourceIODevice = close;
153 }
154
155
writeTo(QIODevice * dev,bool close)156 void K3b::ActivePipe::writeTo( QIODevice* dev, bool close )
157 {
158 d->sinkIODevice = dev;
159 d->closeSinkIODevice = close;
160 }
161
162
readData(char * data,qint64 max)163 qint64 K3b::ActivePipe::readData( char* data, qint64 max )
164 {
165 if( d->sourceIODevice ) {
166 return d->sourceIODevice->read( data, max );
167 }
168
169 return -1;
170 }
171
172
writeData(const char * data,qint64 max)173 qint64 K3b::ActivePipe::writeData( const char* data, qint64 max )
174 {
175 if( d->sinkIODevice ) {
176 return d->sinkIODevice->write( data, max );
177 }
178 else
179 return -1;
180 }
181
182
bytesRead() const183 quint64 K3b::ActivePipe::bytesRead() const
184 {
185 return d->bytesRead;
186 }
187
188
bytesWritten() const189 quint64 K3b::ActivePipe::bytesWritten() const
190 {
191 return d->bytesWritten;
192 }
193
194 #include "moc_k3bactivepipe.cpp"
195