Fix typos
[platform/upstream/libzypp.git] / zypp / base / GzStream.cc
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
34 ///////////////////////////////////////////////////////////////////
35 namespace zypp
36 { /////////////////////////////////////////////////////////////////
37   ///////////////////////////////////////////////////////////////////
38   namespace gzstream_detail
39   { /////////////////////////////////////////////////////////////////
40
41
42     ///////////////////////////////////////////////////////////////////
43     //
44     //  CLASS NAME : ZlibError
45     //
46     ///////////////////////////////////////////////////////////////////
47
48     ///////////////////////////////////////////////////////////////////
49     //
50     //  METHOD NAME : ZlibError::strerror
51     //  METHOD TYPE : std::string
52     //
53     std::string
54     ZlibError::strerror() const
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
62     ///////////////////////////////////////////////////////////////////
63     //
64     //  CLASS NAME : fgzstreambuf
65     //
66     ///////////////////////////////////////////////////////////////////
67
68     ///////////////////////////////////////////////////////////////////
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
114     ///////////////////////////////////////////////////////////////////
115     //
116     //  METHOD NAME : fgzstreambuf::close
117     //  METHOD TYPE : fgzstreambuf *
118     //
119     fgzstreambuf *
120     fgzstreambuf::close()
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
150     ///////////////////////////////////////////////////////////////////
151     //
152     //  METHOD NAME : fgzstreambuf::sync
153     //  METHOD TYPE : int
154     //
155     int
156     fgzstreambuf::sync()
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
167     ///////////////////////////////////////////////////////////////////
168     //
169     //  METHOD NAME : fgzstreambuf::overflow
170     //  METHOD TYPE : fgzstreambuf::int_type
171     //
172     fgzstreambuf::int_type
173     fgzstreambuf::overflow( int_type c )
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
196     ///////////////////////////////////////////////////////////////////
197     //
198     //  METHOD NAME : fgzstreambuf::underflow
199     //  METHOD TYPE : fgzstreambuf::int_type
200     //
201     fgzstreambuf::int_type
202     fgzstreambuf::underflow()
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[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
226     ///////////////////////////////////////////////////////////////////
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
240     ///////////////////////////////////////////////////////////////////
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
257     ///////////////////////////////////////////////////////////////////
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
271     ///////////////////////////////////////////////////////////////////
272     //
273     //  METHOD NAME : fgzstreambuf::zTell
274     //  METHOD TYPE : fgzstreambuf::pos_type
275     //
276     fgzstreambuf::pos_type
277     fgzstreambuf::zTell()
278     {
279       z_off_t ret = gztell( _file );
280       if ( ret == -1 )
281         setZError();
282       return ret;
283     }
284
285     ///////////////////////////////////////////////////////////////////
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
352     fgzstreambuf::compressed_tell() const
353     {
354         off_t pos = lseek (_fd, 0, SEEK_CUR);
355         // hopefully the conversion is ok
356         return pos;
357     }
358
359     /////////////////////////////////////////////////////////////////
360   } // namespace gzstream_detail
361   ///////////////////////////////////////////////////////////////////
362   /////////////////////////////////////////////////////////////////
363 } // namespace zypp
364 ///////////////////////////////////////////////////////////////////
365