libzypp  17.14.0
GzStream.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | |
3 | __ __ ____ _____ ____ |
4 | \ \ / /_ _/ ___|_ _|___ \ |
5 | \ V / _` \___ \ | | __) | |
6 | | | (_| |___) || | / __/ |
7 | |_|\__,_|____/ |_| |_____| |
8 | |
9 | core system |
10 | (C) SuSE Linux Products GmbH |
11 \----------------------------------------------------------------------/
12 
13  File: GzStream.cc
14 
15  Author: Michael Andres <ma@suse.de>
16  Maintainer: Michael Andres <ma@suse.de>
17 
18  Purpose: Streams reading and writing gzip files.
19 
20 /-*/
21 
22 #include <cerrno>
23 #include <iostream>
24 #include "zypp/base/LogControl.h"
25 #include "zypp/base/LogTools.h"
26 using std::endl;
27 
28 #include "zypp/base/GzStream.h"
29 
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <fcntl.h>
33 
35 namespace zypp
36 {
37  namespace gzstream_detail
39  {
40 
41 
43  //
44  // CLASS NAME : ZlibError
45  //
47 
49  //
50  // METHOD NAME : ZlibError::strerror
51  // METHOD TYPE : std::string
52  //
53  std::string
55  {
56  std::string ret = ( _zError ? ::zError( _zError ) : "OK" );
57  if ( _zError == Z_ERRNO )
58  ret += std::string("(") + ::strerror( _errno ) + ")";
59  return ret;
60  }
61 
63  //
64  // CLASS NAME : fgzstreambuf
65  //
67 
69  //
70  // METHOD NAME : fgzstreambuf::open
71  // METHOD TYPE : fgzstreambuf *
72  //
73  fgzstreambuf *
74  fgzstreambuf::open( const char * name_r, std::ios_base::openmode mode_r )
75  {
76  fgzstreambuf * ret = NULL;
77  if ( ! isOpen() )
78  {
79  // we expect gzdopen to handle errors of ::open
80  if ( mode_r == std::ios_base::in )
81  {
82  _fd = ::open( name_r, O_RDONLY | O_CLOEXEC );
83  _file = gzdopen( _fd, "rb" );
84  }
85  else if ( mode_r == std::ios_base::out )
86  {
87  _fd = ::open( name_r, O_WRONLY|O_CREAT|O_CLOEXEC, 0666 );
88  _file = gzdopen( _fd, "wb" );
89  }
90  // else: not supported
91 
92  if ( isOpen() )
93  {
94  // Store mode and initialize the internal buffer.
95  _mode = mode_r;
96  if ( inReadMode() )
97  {
98  setp( NULL, NULL );
99  setg( &(_buffer[0]), &(_buffer[0]), &(_buffer[0]) );
100  }
101  else
102  {
103  setp( &(_buffer[0]), &(_buffer[_buffer.size()-1]) );
104  setg( NULL, NULL, NULL );
105  }
106  ret = this;
107  }
108  else
109  setZError();
110  }
111  return ret;
112  }
113 
115  //
116  // METHOD NAME : fgzstreambuf::close
117  // METHOD TYPE : fgzstreambuf *
118  //
119  fgzstreambuf *
121  {
122  fgzstreambuf * ret = NULL;
123  if ( isOpen() )
124  {
125  bool failed = false;
126  if ( sync() != 0 )
127  failed = true;
128  // it also closes _fd, fine
129  int r = gzclose( _file );
130  if ( r != Z_OK )
131  {
132  failed = true;
133  // DONT call setZError() here, as _file is no longer valid
134  _error._zError = r;
135  _error._errno = errno;
136  }
137 
138  // Reset everything
139  _fd = -1;
140  _file = NULL;
141  _mode = std::ios_base::openmode(0);
142  setp( NULL, NULL );
143  setg( NULL, NULL, NULL );
144  if ( ! failed )
145  ret = this;
146  }
147  return ret;
148  }
149 
151  //
152  // METHOD NAME : fgzstreambuf::sync
153  // METHOD TYPE : int
154  //
155  int
157  {
158  int ret = 0;
159  if ( pbase() < pptr() ) {
160  const int_type res = overflow();
161  if ( traits_type::eq_int_type( res, traits_type::eof() ) )
162  ret = -1;
163  }
164  return ret;
165  }
166 
168  //
169  // METHOD NAME : fgzstreambuf::overflow
170  // METHOD TYPE : fgzstreambuf::int_type
171  //
172  fgzstreambuf::int_type
174  {
175  int_type ret = traits_type::eof();
176  if ( inWriteMode() )
177  {
178  if ( ! traits_type::eq_int_type( c, traits_type::eof() ) )
179  {
180  *pptr() = traits_type::to_char_type( c );
181  pbump(1);
182  }
183  if ( pbase() <= pptr() )
184  {
185  if ( zWriteFrom( pbase(), pptr() - pbase() ) )
186  {
187  setp( &(_buffer[0]), &(_buffer[_buffer.size()-1]) );
188  ret = traits_type::not_eof( c );
189  }
190  // else: error writing the file
191  }
192  }
193  return ret;
194  }
195 
197  //
198  // METHOD NAME : fgzstreambuf::underflow
199  // METHOD TYPE : fgzstreambuf::int_type
200  //
201  fgzstreambuf::int_type
203  {
204  int_type ret = traits_type::eof();
205  if ( inReadMode() )
206  {
207  if ( gptr() < egptr() )
208  return traits_type::to_int_type( *gptr() );
209 
210  const std::streamsize got = zReadTo( &(_buffer[0]), _buffer.size() );
211  if ( got > 0 )
212  {
213  setg( &(_buffer[0]), &(_buffer[0]), &(_buffer.data()[got]) );
214  ret = traits_type::to_int_type( *gptr() );
215  }
216  else if ( got == 0 )
217  {
218  // EOF
219  setg( &(_buffer[0]), &(_buffer[0]), &(_buffer[0]) );
220  }
221  // else: error reading the file
222  }
223  return ret;
224  }
225 
227  //
228  // METHOD NAME : fgzstreambuf::zReadTo
229  // METHOD TYPE : std::streamsize
230  //
231  std::streamsize
232  fgzstreambuf::zReadTo( char * buffer_r, std::streamsize maxcount_r )
233  {
234  int read = gzread( _file, buffer_r, maxcount_r );
235  if ( read < 0 )
236  setZError();
237  return read;
238  }
239 
241  //
242  // METHOD NAME : fgzstreambuf::zWriteFrom
243  // METHOD TYPE : bool
244  //
245  bool
246  fgzstreambuf::zWriteFrom( const char * buffer_r, std::streamsize count_r )
247  {
248  int written = 0;
249  if ( count_r )
250  {
251  if ( (written = gzwrite( _file, buffer_r, count_r )) == 0 )
252  setZError();
253  }
254  return( written == count_r );
255  }
256 
258  //
259  // METHOD NAME : fgzstreambuf::zSeekTo
260  // METHOD TYPE : fgzstreambuf::pos_type
261  //
262  fgzstreambuf::pos_type
263  fgzstreambuf::zSeekTo( off_type off_r, std::ios_base::seekdir way_r )
264  {
265  z_off_t ret = gzseek( _file, off_r, way_r );
266  if ( ret == -1 )
267  setZError();
268  return ret;
269  }
270 
272  //
273  // METHOD NAME : fgzstreambuf::zTell
274  // METHOD TYPE : fgzstreambuf::pos_type
275  //
276  fgzstreambuf::pos_type
278  {
279  z_off_t ret = gztell( _file );
280  if ( ret == -1 )
281  setZError();
282  return ret;
283  }
284 
286  //
287  // METHOD NAME : fgzstreambuf::seekTo
288  // METHOD TYPE : fgzstreambuf::pos_type
289  //
290  fgzstreambuf::pos_type
291  fgzstreambuf::seekTo( off_type off_r, std::ios_base::seekdir way_r )
292  {
293  pos_type ret = pos_type(off_type(-1));
294  if ( isOpen() )
295  {
296  if ( inWriteMode() )
297  {
298  if ( sync() == 0 )
299  ret = zSeekTo( off_r, way_r );
300  }
301  else
302  {
303  off_type zegptr = zTell();
304  if ( zegptr != off_type(-1) )
305  {
306  if ( way_r == std::ios_base::end )
307  {
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 );
313  }
314  else
315  {
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 )
321  {
322  zngptr += zgptr;
323  way_r = std::ios_base::beg;
324  }
325 
326  if ( way_r == std::ios_base::beg )
327  {
328  if ( zeback <= zngptr && zngptr <= zegptr )
329  {
330  // Still inside buffer, adjust gptr and
331  // calculate new position.
332  setg( eback(),
333  eback() + (zngptr-zeback),
334  egptr() );
335  ret = pos_type(zngptr);
336  }
337  else
338  {
339  // Invalidate buffer and seek.
340  setg( &(_buffer[0]), &(_buffer[0]), &(_buffer[0]) );
341  ret = zSeekTo( off_r, way_r );
342  }
343  }
344  }
345  }
346  }
347  }
348  return ret;
349  }
350 
351  fgzstreambuf::pos_type
353  {
354  off_t pos = lseek (_fd, 0, SEEK_CUR);
355  // hopefully the conversion is ok
356  return pos;
357  }
358 
360  } // namespace gzstream_detail
363 } // namespace zypp
365 
pos_type zSeekTo(off_type off_r, std::ios_base::seekdir way_r)
Definition: GzStream.cc:263
bool zWriteFrom(const char *buffer_r, std::streamsize count_r)
Definition: GzStream.cc:246
int _errno
errno, valid if zError is Z_ERRNO
Definition: GzStream.h:53
map< string, string > read(const Pathname &_path)
Read sysconfig file path_r and return (key,valye) pairs.
Definition: Sysconfig.cc:34
int _fd
file descriptor of the compressed file
Definition: GzStream.h:154
pos_type seekTo(off_type off_r, std::ios_base::seekdir way_r)
Definition: GzStream.cc:291
std::ios_base::openmode _mode
Definition: GzStream.h:158
virtual int_type overflow(int_type c=traits_type::eof())
Definition: GzStream.cc:173
std::streamsize zReadTo(char *buffer_r, std::streamsize maxcount_r)
Definition: GzStream.cc:232
pos_type compressed_tell() const
Tell the file position in the compressed file.
Definition: GzStream.cc:352
int _zError
The zlib error code.
Definition: GzStream.h:48
std::string strerror() const
Return string describing the zlib error code.
Definition: GzStream.cc:54
Easy-to use interface to the ZYPP dependency resolver.
Definition: CodePitfalls.doc:1
Streambuffer reading or writing gzip files.
Definition: GzStream.h:86
fgzstreambuf * open(const char *name_r, std::ios_base::openmode mode_r=std::ios_base::in)
Definition: GzStream.cc:74