1 /*---------------------------------------------------------------------\
3 | __ __ ____ _____ ____ |
4 | \ \ / /_ _/ ___|_ _|___ \ |
5 | \ V / _` \___ \ | | __) | |
6 | | | (_| |___) || | / __/ |
7 | |_|\__,_|____/ |_| |_____| |
10 | (C) SuSE Linux Products GmbH |
11 \----------------------------------------------------------------------/
15 Author: Michael Andres <ma@suse.de>
16 Maintainer: Michael Andres <ma@suse.de>
18 Purpose: Streams reading and writing gzip files.
24 #include "zypp/base/LogControl.h"
25 #include "zypp/base/LogTools.h"
28 #include "zypp/base/GzStream.h"
30 #include <sys/types.h>
34 ///////////////////////////////////////////////////////////////////
36 { /////////////////////////////////////////////////////////////////
37 ///////////////////////////////////////////////////////////////////
38 namespace gzstream_detail
39 { /////////////////////////////////////////////////////////////////
42 ///////////////////////////////////////////////////////////////////
44 // CLASS NAME : ZlibError
46 ///////////////////////////////////////////////////////////////////
48 ///////////////////////////////////////////////////////////////////
50 // METHOD NAME : ZlibError::strerror
51 // METHOD TYPE : std::string
54 ZlibError::strerror() const
56 std::string ret = ( _zError ? ::zError( _zError ) : "OK" );
57 if ( _zError == Z_ERRNO )
58 ret += std::string("(") + ::strerror( _errno ) + ")";
62 ///////////////////////////////////////////////////////////////////
64 // CLASS NAME : fgzstreambuf
66 ///////////////////////////////////////////////////////////////////
68 ///////////////////////////////////////////////////////////////////
70 // METHOD NAME : fgzstreambuf::open
71 // METHOD TYPE : fgzstreambuf *
74 fgzstreambuf::open( const char * name_r, std::ios_base::openmode mode_r )
76 fgzstreambuf * ret = NULL;
79 // we expect gzdopen to handle errors of ::open
80 if ( mode_r == std::ios_base::in )
82 _fd = ::open( name_r, O_RDONLY | O_CLOEXEC );
83 _file = gzdopen( _fd, "rb" );
85 else if ( mode_r == std::ios_base::out )
87 _fd = ::open( name_r, O_WRONLY|O_CREAT|O_CLOEXEC, 0666 );
88 _file = gzdopen( _fd, "wb" );
90 // else: not supported
94 // Store mode and initialize the internal buffer.
99 setg( &(_buffer[0]), &(_buffer[0]), &(_buffer[0]) );
103 setp( &(_buffer[0]), &(_buffer[_buffer.size()-1]) );
104 setg( NULL, NULL, NULL );
114 ///////////////////////////////////////////////////////////////////
116 // METHOD NAME : fgzstreambuf::close
117 // METHOD TYPE : fgzstreambuf *
120 fgzstreambuf::close()
122 fgzstreambuf * ret = NULL;
128 // it also closes _fd, fine
129 int r = gzclose( _file );
133 // DONT call setZError() here, as _file is no longer valid
135 _error._errno = errno;
141 _mode = std::ios_base::openmode(0);
143 setg( NULL, NULL, NULL );
150 ///////////////////////////////////////////////////////////////////
152 // METHOD NAME : fgzstreambuf::sync
159 if ( pbase() < pptr() ) {
160 const int_type res = overflow();
161 if ( traits_type::eq_int_type( res, traits_type::eof() ) )
167 ///////////////////////////////////////////////////////////////////
169 // METHOD NAME : fgzstreambuf::overflow
170 // METHOD TYPE : fgzstreambuf::int_type
172 fgzstreambuf::int_type
173 fgzstreambuf::overflow( int_type c )
175 int_type ret = traits_type::eof();
178 if ( ! traits_type::eq_int_type( c, traits_type::eof() ) )
180 *pptr() = traits_type::to_char_type( c );
183 if ( pbase() <= pptr() )
185 if ( zWriteFrom( pbase(), pptr() - pbase() ) )
187 setp( &(_buffer[0]), &(_buffer[_buffer.size()-1]) );
188 ret = traits_type::not_eof( c );
190 // else: error writing the file
196 ///////////////////////////////////////////////////////////////////
198 // METHOD NAME : fgzstreambuf::underflow
199 // METHOD TYPE : fgzstreambuf::int_type
201 fgzstreambuf::int_type
202 fgzstreambuf::underflow()
204 int_type ret = traits_type::eof();
207 if ( gptr() < egptr() )
208 return traits_type::to_int_type( *gptr() );
210 const std::streamsize got = zReadTo( &(_buffer[0]), _buffer.size() );
213 setg( &(_buffer[0]), &(_buffer[0]), &(_buffer[got]) );
214 ret = traits_type::to_int_type( *gptr() );
219 setg( &(_buffer[0]), &(_buffer[0]), &(_buffer[0]) );
221 // else: error reading the file
226 ///////////////////////////////////////////////////////////////////
228 // METHOD NAME : fgzstreambuf::zReadTo
229 // METHOD TYPE : std::streamsize
232 fgzstreambuf::zReadTo( char * buffer_r, std::streamsize maxcount_r )
234 int read = gzread( _file, buffer_r, maxcount_r );
240 ///////////////////////////////////////////////////////////////////
242 // METHOD NAME : fgzstreambuf::zWriteFrom
243 // METHOD TYPE : bool
246 fgzstreambuf::zWriteFrom( const char * buffer_r, std::streamsize count_r )
251 if ( (written = gzwrite( _file, buffer_r, count_r )) == 0 )
254 return( written == count_r );
257 ///////////////////////////////////////////////////////////////////
259 // METHOD NAME : fgzstreambuf::zSeekTo
260 // METHOD TYPE : fgzstreambuf::pos_type
262 fgzstreambuf::pos_type
263 fgzstreambuf::zSeekTo( off_type off_r, std::ios_base::seekdir way_r )
265 z_off_t ret = gzseek( _file, off_r, way_r );
271 ///////////////////////////////////////////////////////////////////
273 // METHOD NAME : fgzstreambuf::zTell
274 // METHOD TYPE : fgzstreambuf::pos_type
276 fgzstreambuf::pos_type
277 fgzstreambuf::zTell()
279 z_off_t ret = gztell( _file );
285 ///////////////////////////////////////////////////////////////////
287 // METHOD NAME : fgzstreambuf::seekTo
288 // METHOD TYPE : fgzstreambuf::pos_type
290 fgzstreambuf::pos_type
291 fgzstreambuf::seekTo( off_type off_r, std::ios_base::seekdir way_r )
293 pos_type ret = pos_type(off_type(-1));
299 ret = zSeekTo( off_r, way_r );
303 off_type zegptr = zTell();
304 if ( zegptr != off_type(-1) )
306 if ( way_r == std::ios_base::end )
308 // Invalidate buffer and seek.
309 // XXX improve by transformation into ios_base::beg
310 // to see whether we stay inside the buffer.
311 setg( &(_buffer[0]), &(_buffer[0]), &(_buffer[0]) );
312 ret = zSeekTo( off_r, way_r );
316 // Transform into ios_base::beg and seek.
317 off_type zeback = zegptr - ( egptr() - eback() );
318 off_type zgptr = zegptr - ( egptr() - gptr() );
319 off_type zngptr = off_r;
320 if ( way_r == std::ios_base::cur )
323 way_r = std::ios_base::beg;
326 if ( way_r == std::ios_base::beg )
328 if ( zeback <= zngptr && zngptr <= zegptr )
330 // Still inside buffer, adjust gptr and
331 // calculate new position.
333 eback() + (zngptr-zeback),
335 ret = pos_type(zngptr);
339 // Invalidate buffer and seek.
340 setg( &(_buffer[0]), &(_buffer[0]), &(_buffer[0]) );
341 ret = zSeekTo( off_r, way_r );
351 fgzstreambuf::pos_type
352 fgzstreambuf::compressed_tell() const
354 off_t pos = lseek (_fd, 0, SEEK_CUR);
355 // hopefully the conversion is ok
359 /////////////////////////////////////////////////////////////////
360 } // namespace gzstream_detail
361 ///////////////////////////////////////////////////////////////////
362 /////////////////////////////////////////////////////////////////
364 ///////////////////////////////////////////////////////////////////