00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <cerrno>
00023 #include <iostream>
00024 #include <zypp/base/LogControl.h>
00025 #include <zypp/base/LogTools.h>
00026 using std::endl;
00027
00028 #include "zypp/base/GzStream.h"
00029
00030 #include <sys/types.h>
00031 #include <sys/stat.h>
00032 #include <fcntl.h>
00033
00035 namespace zypp
00036 {
00037
00038 namespace gzstream_detail
00039 {
00040
00041
00043
00044
00045
00047
00049
00050
00051
00052
00053 std::string
00054 ZlibError::strerror() const
00055 {
00056 std::string ret = ( _zError ? ::zError( _zError ) : "OK" );
00057 if ( _zError == Z_ERRNO )
00058 ret += std::string("(") + ::strerror( _errno ) + ")";
00059 return ret;
00060 }
00061
00063
00064
00065
00067
00069
00070
00071
00072
00073 fgzstreambuf *
00074 fgzstreambuf::open( const char * name_r, std::ios_base::openmode mode_r )
00075 {
00076 fgzstreambuf * ret = NULL;
00077 if ( ! isOpen() )
00078 {
00079
00080 if ( mode_r == std::ios_base::in )
00081 {
00082 _fd = ::open( name_r, O_RDONLY );
00083 _file = gzdopen( _fd, "rb" );
00084 }
00085 else if ( mode_r == std::ios_base::out )
00086 {
00087 _fd = ::open( name_r, O_WRONLY|O_CREAT, 0666 );
00088 _file = gzdopen( _fd, "wb" );
00089 }
00090
00091
00092 if ( isOpen() )
00093 {
00094
00095 _mode = mode_r;
00096 if ( inReadMode() )
00097 {
00098 setp( NULL, NULL );
00099 setg( &(_buffer[0]), &(_buffer[0]), &(_buffer[0]) );
00100 }
00101 else
00102 {
00103 setp( &(_buffer[0]), &(_buffer[_buffer.size()-1]) );
00104 setg( NULL, NULL, NULL );
00105 }
00106 ret = this;
00107 }
00108 else
00109 setZError();
00110 }
00111 return ret;
00112 }
00113
00115
00116
00117
00118
00119 fgzstreambuf *
00120 fgzstreambuf::close()
00121 {
00122 fgzstreambuf * ret = NULL;
00123 if ( isOpen() )
00124 {
00125 bool failed = false;
00126 if ( sync() != 0 )
00127 failed = true;
00128
00129 int r = gzclose( _file );
00130 if ( r != Z_OK )
00131 {
00132 failed = true;
00133
00134 _error._zError = r;
00135 _error._errno = errno;
00136 }
00137
00138
00139 _fd = -1;
00140 _file = NULL;
00141 _mode = std::ios_base::openmode(0);
00142 setp( NULL, NULL );
00143 setg( NULL, NULL, NULL );
00144 if ( ! failed )
00145 ret = this;
00146 }
00147 return ret;
00148 }
00149
00151
00152
00153
00154
00155 int
00156 fgzstreambuf::sync()
00157 {
00158 int ret = 0;
00159 if ( pbase() < pptr() ) {
00160 const int_type res = overflow();
00161 if ( traits_type::eq_int_type( res, traits_type::eof() ) )
00162 ret = -1;
00163 }
00164 return ret;
00165 }
00166
00168
00169
00170
00171
00172 fgzstreambuf::int_type
00173 fgzstreambuf::overflow( int_type c )
00174 {
00175 int_type ret = traits_type::eof();
00176 if ( inWriteMode() )
00177 {
00178 if ( ! traits_type::eq_int_type( c, traits_type::eof() ) )
00179 {
00180 *pptr() = traits_type::to_char_type( c );
00181 pbump(1);
00182 }
00183 if ( pbase() <= pptr() )
00184 {
00185 if ( zWriteFrom( pbase(), pptr() - pbase() ) )
00186 {
00187 setp( &(_buffer[0]), &(_buffer[_buffer.size()-1]) );
00188 ret = traits_type::not_eof( c );
00189 }
00190
00191 }
00192 }
00193 return ret;
00194 }
00195
00197
00198
00199
00200
00201 fgzstreambuf::int_type
00202 fgzstreambuf::underflow()
00203 {
00204 int_type ret = traits_type::eof();
00205 if ( inReadMode() )
00206 {
00207 if ( gptr() < egptr() )
00208 return traits_type::to_int_type( *gptr() );
00209
00210 const std::streamsize got = zReadTo( &(_buffer[0]), _buffer.size() );
00211 if ( got > 0 )
00212 {
00213 setg( &(_buffer[0]), &(_buffer[0]), &(_buffer[got]) );
00214 ret = traits_type::to_int_type( *gptr() );
00215 }
00216 else if ( got == 0 )
00217 {
00218
00219 setg( &(_buffer[0]), &(_buffer[0]), &(_buffer[0]) );
00220 }
00221
00222 }
00223 return ret;
00224 }
00225
00227
00228
00229
00230
00231 std::streamsize
00232 fgzstreambuf::zReadTo( char * buffer_r, std::streamsize maxcount_r )
00233 {
00234 int read = gzread( _file, buffer_r, maxcount_r );
00235 if ( read < 0 )
00236 setZError();
00237 return read;
00238 }
00239
00241
00242
00243
00244
00245 bool
00246 fgzstreambuf::zWriteFrom( const char * buffer_r, std::streamsize count_r )
00247 {
00248 int written = 0;
00249 if ( count_r )
00250 {
00251 if ( (written = gzwrite( _file, buffer_r, count_r )) == 0 )
00252 setZError();
00253 }
00254 return( written == count_r );
00255 }
00256
00258
00259
00260
00261
00262 fgzstreambuf::pos_type
00263 fgzstreambuf::zSeekTo( off_type off_r, std::ios_base::seekdir way_r )
00264 {
00265 z_off_t ret = gzseek( _file, off_r, way_r );
00266 if ( ret == -1 )
00267 setZError();
00268 return ret;
00269 }
00270
00272
00273
00274
00275
00276 fgzstreambuf::pos_type
00277 fgzstreambuf::zTell()
00278 {
00279 z_off_t ret = gztell( _file );
00280 if ( ret == -1 )
00281 setZError();
00282 return ret;
00283 }
00284
00286
00287
00288
00289
00290 fgzstreambuf::pos_type
00291 fgzstreambuf::seekTo( off_type off_r, std::ios_base::seekdir way_r )
00292 {
00293 pos_type ret = pos_type(off_type(-1));
00294 if ( isOpen() )
00295 {
00296 if ( inWriteMode() )
00297 {
00298 if ( sync() == 0 )
00299 ret = zSeekTo( off_r, way_r );
00300 }
00301 else
00302 {
00303 off_type zegptr = zTell();
00304 if ( zegptr != off_type(-1) )
00305 {
00306 if ( way_r == std::ios_base::end )
00307 {
00308
00309
00310
00311 setg( &(_buffer[0]), &(_buffer[0]), &(_buffer[0]) );
00312 ret = zSeekTo( off_r, way_r );
00313 }
00314 else
00315 {
00316
00317 off_type zeback = zegptr - ( egptr() - eback() );
00318 off_type zgptr = zegptr - ( egptr() - gptr() );
00319 off_type zngptr = off_r;
00320 if ( way_r == std::ios_base::cur )
00321 {
00322 zngptr += zgptr;
00323 way_r = std::ios_base::beg;
00324 }
00325
00326 if ( way_r == std::ios_base::beg )
00327 {
00328 if ( zeback <= zngptr && zngptr <= zegptr )
00329 {
00330
00331
00332 setg( eback(),
00333 eback() + (zngptr-zeback),
00334 egptr() );
00335 ret = pos_type(zngptr);
00336 }
00337 else
00338 {
00339
00340 setg( &(_buffer[0]), &(_buffer[0]), &(_buffer[0]) );
00341 ret = zSeekTo( off_r, way_r );
00342 }
00343 }
00344 }
00345 }
00346 }
00347 }
00348 return ret;
00349 }
00350
00351 fgzstreambuf::pos_type
00352 fgzstreambuf::compressed_tell() const
00353 {
00354 off_t pos = lseek (_fd, 0, SEEK_CUR);
00355
00356 return pos;
00357 }
00358
00360 }
00363 }
00365