Imported Upstream version 17.22.0
[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 : gzstreambufimpl::openImpl
71     //  METHOD TYPE : bool
72     //
73     bool
74     gzstreambufimpl::openImpl(const char *name_r, std::ios_base::openmode mode_r)
75     {
76       bool ret = false;
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
95           _mode = mode_r;
96           ret   = true;
97         }
98         else
99           setZError();
100       }
101       return ret;
102     }
103
104     ///////////////////////////////////////////////////////////////////
105     //
106     //  METHOD NAME : gzstreambufimpl::closeImpl
107     //  METHOD TYPE : bool
108     //
109     bool
110     gzstreambufimpl::closeImpl()
111     {
112       bool ret = false;
113       if ( isOpen() )
114         {
115           bool failed = false;
116
117           // it also closes _fd, fine
118           int r = gzclose( _file );
119           if ( r != Z_OK )
120             {
121               failed = true;
122               // DONT call setZError() here, as _file is no longer valid
123               _error._zError = r;
124               _error._errno = errno;
125             }
126
127           // Reset everything
128           _fd = -1;
129           _file = NULL;
130           _mode = std::ios_base::openmode(0);
131           if ( ! failed )
132             ret = true;
133         }
134       return ret;
135     }
136
137     ///////////////////////////////////////////////////////////////////
138     //
139     //  METHOD NAME : gzstreambufimpl::readData
140     //  METHOD TYPE : std::streamsize
141     //
142     std::streamsize
143     gzstreambufimpl::readData( char * buffer_r, std::streamsize maxcount_r )
144     {
145       int read = gzread( _file, buffer_r, maxcount_r );
146       if ( read < 0 )
147         setZError();
148       return read;
149     }
150
151     ///////////////////////////////////////////////////////////////////
152     //
153     //  METHOD NAME : gzstreambufimpl::writeData
154     //  METHOD TYPE : bool
155     //
156     bool
157     gzstreambufimpl::writeData( const char * buffer_r, std::streamsize count_r )
158     {
159       int written = 0;
160       if ( count_r )
161         {
162           if ( (written = gzwrite( _file, buffer_r, count_r )) == 0 )
163             setZError();
164         }
165       return( written == count_r );
166     }
167
168     ///////////////////////////////////////////////////////////////////
169     //
170     //  METHOD NAME : gzstreambufimpl::seekTo
171     //  METHOD TYPE : off_t
172     //
173     off_t
174     gzstreambufimpl::seekTo( off_t off_r, std::ios_base::seekdir way_r, std::ios_base::openmode )
175     {
176       z_off_t ret = gzseek( _file, off_r, way_r );
177       if ( ret == -1 )
178         setZError();
179       return ret;
180     }
181
182     ///////////////////////////////////////////////////////////////////
183     //
184     //  METHOD NAME : gzstreambufimpl::tell
185     //  METHOD TYPE : off_t
186     //
187     off_t
188     gzstreambufimpl::tell() const
189     {
190       z_off_t ret = gztell( _file );
191       if ( ret == -1 )
192         setZError();
193       return ret;
194     }
195
196     off_t
197     gzstreambufimpl::compressed_tell() const
198     {
199         off_t pos = lseek (_fd, 0, SEEK_CUR);
200         // hopefully the conversion is ok
201         return pos;
202     }
203
204     /////////////////////////////////////////////////////////////////
205   } // namespace gzstream_detail
206   ///////////////////////////////////////////////////////////////////
207   /////////////////////////////////////////////////////////////////
208 } // namespace zypp
209 ///////////////////////////////////////////////////////////////////
210