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
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
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
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 mHaveQProcess( qobject_cast<QProcess*>( io.get() ) )
00140 {
00141 assert( mIO );
00142 }
00143
00144 QIODeviceDataProvider::~QIODeviceDataProvider() {}
00145
00146 bool QIODeviceDataProvider::isSupported( Operation op ) const {
00147 switch ( op ) {
00148 case Read: return mIO->isReadable();
00149 case Write: return mIO->isWritable();
00150 case Seek: return !mIO->isSequential();
00151 case Release: return true;
00152 default: return false;
00153 }
00154 }
00155
00156 static qint64 blocking_read( const boost::shared_ptr<QIODevice> & io, char * buffer, qint64 maxSize ) {
00157 while ( !io->bytesAvailable() ) {
00158 if ( !io->waitForReadyRead( -1 ) ) {
00159 if ( const QProcess * const p = qobject_cast<QProcess*>( io.get() ) ) {
00160 if ( p->error() == QProcess::UnknownError &&
00161 p->exitStatus() == QProcess::NormalExit &&
00162 p->exitCode() == 0 ) {
00163 return 0;
00164 } else {
00165 return errno = EIO, -1;
00166 }
00167 } else {
00168 return 0;
00169 }
00170 }
00171 }
00172 return io->read( buffer, maxSize );
00173 }
00174
00175 ssize_t QIODeviceDataProvider::read( void * buffer, size_t bufSize ) {
00176 #ifndef NDEBUG
00177
00178 #endif
00179 if ( bufSize == 0 )
00180 return 0;
00181 if ( !buffer ) {
00182 errno = EINVAL;
00183 return -1;
00184 }
00185 const qint64 numRead = mHaveQProcess
00186 ? blocking_read( mIO, static_cast<char*>(buffer), bufSize )
00187 : mIO->read( static_cast<char*>(buffer), bufSize ) ;
00188
00189
00190
00191
00192 ssize_t rc = numRead;
00193 if ( numRead < 0 && errno == 0 ) {
00194 if ( mErrorOccurred )
00195 errno = EIO;
00196 else
00197 rc = 0;
00198 }
00199 if ( numRead < 0 )
00200 mErrorOccurred = true;
00201 return rc;
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
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
00251 #endif
00252 mIO->close();
00253 }