qgpgme
dataprovider.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <qgpgme/dataprovider.h>
00024
00025 #include <QIODevice>
00026 #include <QProcess>
00027
00028 #include <stdio.h>
00029 #include <string.h>
00030 #include <errno.h>
00031 #include <assert.h>
00032
00033 using namespace QGpgME;
00034
00035
00036
00037
00038
00039
00040
00041 static bool resizeAndInit( QByteArray & ba, size_t newSize ) {
00042 const size_t oldSize = ba.size();
00043 ba.resize( newSize );
00044 const bool ok = ( newSize == static_cast<size_t>( ba.size() ) );
00045 if ( ok )
00046 memset( ba.data() + oldSize, 0, newSize - oldSize );
00047 return ok;
00048 }
00049
00050 QByteArrayDataProvider::QByteArrayDataProvider()
00051 : GpgME::DataProvider(), mOff( 0 ) {}
00052
00053 QByteArrayDataProvider::QByteArrayDataProvider( const QByteArray & initialData )
00054 : GpgME::DataProvider(), mArray( initialData ), mOff( 0 ) {}
00055
00056 QByteArrayDataProvider::~QByteArrayDataProvider() {}
00057
00058 ssize_t QByteArrayDataProvider::read( void * buffer, size_t bufSize ) {
00059 #ifndef NDEBUG
00060
00061 #endif
00062 if ( bufSize == 0 )
00063 return 0;
00064 if ( !buffer ) {
00065 errno = EINVAL;
00066 return -1;
00067 }
00068 if ( mOff >= mArray.size() )
00069 return 0;
00070 size_t amount = qMin( bufSize, static_cast<size_t>( mArray.size() - mOff ) );
00071 assert( amount > 0 );
00072 memcpy( buffer, mArray.data() + mOff, amount );
00073 mOff += amount;
00074 return amount;
00075 }
00076
00077 ssize_t QByteArrayDataProvider::write( const void * buffer, size_t bufSize ) {
00078 #ifndef NDEBUG
00079 qDebug( "QByteArrayDataProvider::write( %p, %lu )", buffer, static_cast<unsigned long>( bufSize ) );
00080 #endif
00081 if ( bufSize == 0 )
00082 return 0;
00083 if ( !buffer ) {
00084 errno = EINVAL;
00085 return -1;
00086 }
00087 if ( mOff >= mArray.size() )
00088 resizeAndInit( mArray, mOff + bufSize );
00089 if ( mOff >= mArray.size() ) {
00090 errno = EIO;
00091 return -1;
00092 }
00093 assert( bufSize <= static_cast<size_t>(mArray.size()) - mOff );
00094 memcpy( mArray.data() + mOff, buffer, bufSize );
00095 mOff += bufSize;
00096 return bufSize;
00097 }
00098
00099 off_t QByteArrayDataProvider::seek( off_t offset, int whence ) {
00100 #ifndef NDEBUG
00101 qDebug( "QByteArrayDataProvider::seek( %d, %d )", int(offset), whence );
00102 #endif
00103 int newOffset = mOff;
00104 switch ( whence ) {
00105 case SEEK_SET:
00106 newOffset = offset;
00107 break;
00108 case SEEK_CUR:
00109 newOffset += offset;
00110 break;
00111 case SEEK_END:
00112 newOffset = mArray.size() + offset;
00113 break;
00114 default:
00115 errno = EINVAL;
00116 return (off_t)-1;
00117 }
00118 return mOff = newOffset;
00119 }
00120
00121 void QByteArrayDataProvider::release() {
00122 #ifndef NDEBUG
00123 qDebug( "QByteArrayDataProvider::release()" );
00124 #endif
00125 mArray = QByteArray();
00126 }
00127
00128
00129
00130
00131
00132
00133
00134
00135 QIODeviceDataProvider::QIODeviceDataProvider( const boost::shared_ptr<QIODevice> & io )
00136 : GpgME::DataProvider(),
00137 mIO( io ),
00138 mErrorOccurred( false )
00139 {
00140 assert( mIO );
00141 }
00142
00143 QIODeviceDataProvider::~QIODeviceDataProvider() {}
00144
00145 bool QIODeviceDataProvider::isSupported( Operation op ) const {
00146 switch ( op ) {
00147 case Read: return mIO->isReadable();
00148 case Write: return mIO->isWritable();
00149 case Seek: return !mIO->isSequential();
00150 case Release: return true;
00151 default: return false;
00152 }
00153 }
00154
00155 namespace {
00156 struct Enabler {
00157 explicit Enabler( bool* b_ ) : b( b_) {}
00158 ~Enabler() { if ( b ) *b = true; }
00159 bool* const b;
00160 };
00161 }
00162
00163 static qint64 blocking_read( const boost::shared_ptr<QIODevice> & io, char * buffer, qint64 maxSize ) {
00164 while ( !io->bytesAvailable() )
00165 if ( !io->waitForReadyRead( -1 ) )
00166 if ( const QProcess * const p = qobject_cast<QProcess*>( io.get() ) )
00167 if ( p->error() == QProcess::UnknownError &&
00168 p->exitStatus() == QProcess::NormalExit &&
00169 p->exitCode() == 0 )
00170 return 0;
00171 else
00172 return errno = EIO, -1;
00173 else
00174 return 0;
00175
00176 return io->read( buffer, maxSize );
00177 }
00178
00179 ssize_t QIODeviceDataProvider::read( void * buffer, size_t bufSize ) {
00180 #ifndef NDEBUG
00181
00182 #endif
00183 if ( bufSize == 0 )
00184 return 0;
00185 if ( !buffer ) {
00186 errno = EINVAL;
00187 return -1;
00188 }
00189
00190
00191
00192 const qint64 numRead = blocking_read( mIO, static_cast<char*>(buffer), bufSize );
00193
00194 Enabler en( numRead < 0 ? &mErrorOccurred : 0 );
00195 if ( numRead < 0 && errno == 0 ) {
00196 if ( mErrorOccurred )
00197 errno = EIO;
00198 else
00199 return 0;
00200 }
00201 return numRead;
00202 }
00203
00204 ssize_t QIODeviceDataProvider::write( const void * buffer, size_t bufSize ) {
00205 #ifndef NDEBUG
00206
00207 #endif
00208 if ( bufSize == 0 )
00209 return 0;
00210 if ( !buffer ) {
00211 errno = EINVAL;
00212 return -1;
00213 }
00214
00215 return mIO->write( static_cast<const char*>(buffer), bufSize );
00216 }
00217
00218 off_t QIODeviceDataProvider::seek( off_t offset, int whence ) {
00219 #ifndef NDEBUG
00220 qDebug( "QIODeviceDataProvider::seek( %d, %d )", int(offset), whence );
00221 #endif
00222 if ( mIO->isSequential() ) {
00223 errno = ESPIPE;
00224 return (off_t)-1;
00225 }
00226 qint64 newOffset = mIO->pos();
00227 switch ( whence ) {
00228 case SEEK_SET:
00229 newOffset = offset;
00230 break;
00231 case SEEK_CUR:
00232 newOffset += offset;
00233 break;
00234 case SEEK_END:
00235 newOffset = mIO->size() + offset;
00236 break;
00237 default:
00238 errno = EINVAL;
00239 return (off_t)-1;
00240 }
00241 if ( !mIO->seek( newOffset ) ) {
00242 errno = EINVAL;
00243 return (off_t)-1;
00244 }
00245 return newOffset;
00246 }
00247
00248 void QIODeviceDataProvider::release() {
00249 #ifndef NDEBUG
00250 qDebug( "QIODeviceDataProvider::release()" );
00251 #endif
00252 mIO->close();
00253 }