CernVM-FS  2.13.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
cmd_zpipe.cc
Go to the documentation of this file.
1 
7 /* zpipe.c: example of proper use of zlib's inflate() and deflate()
8  Not copyrighted -- provided to the public domain
9  Version 1.4 11 December 2005 Mark Adler */
10 
11 /* Version history:
12  1.0 30 Oct 2004 First version
13  1.1 8 Nov 2004 Add void casting for unused return values
14  Use switch statement for inflate() return values
15  1.2 9 Nov 2004 Add assertions to document zlib guarantees
16  1.3 6 Apr 2005 Remove incorrect assertion in inf()
17  1.4 11 Dec 2005 Add hack to avoid MSDOS end-of-line conversions
18  Avoid some compiler warnings for input and output buffers
19  */
20 
21 
22 #include "cmd_zpipe.h"
23 
24 #include <stdio.h>
25 
26 #include <cassert>
27 #include <cstring>
28 
29 #include "duplex_zlib.h"
30 
31 #if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__)
32 #include <fcntl.h>
33 #include <io.h>
34 #define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
35 #else
36 #define SET_BINARY_MODE(file)
37 #endif
38 
39 #define CHUNK 16384
40 
41 /* Compress from file source to file dest until EOF on source.
42  def() returns Z_OK on success, Z_MEM_ERROR if memory could not be
43  allocated for processing, Z_STREAM_ERROR if an invalid compression
44  level is supplied, Z_VERSION_ERROR if the version of zlib.h and the
45  version of the library linked do not match, or Z_ERRNO if there is
46  an error reading or writing the files. */
47 int def(FILE *source, FILE *dest, int level) {
48  int ret, flush;
49  unsigned have;
50  z_stream strm;
51  unsigned char in[CHUNK];
52  unsigned char out[CHUNK];
53 
54  /* allocate deflate state */
55  strm.zalloc = Z_NULL;
56  strm.zfree = Z_NULL;
57  strm.opaque = Z_NULL;
58  ret = deflateInit(&strm, level);
59  if (ret != Z_OK)
60  return ret;
61 
62  /* compress until end of file */
63  do {
64  strm.avail_in = fread(in, 1, CHUNK, source);
65  if (ferror(source)) {
66  (void)deflateEnd(&strm);
67  return Z_ERRNO;
68  }
69  flush = feof(source) ? Z_FINISH : Z_NO_FLUSH;
70  strm.next_in = in;
71 
72  /* run deflate() on input until output buffer not full, finish
73  compression if all of source has been read in */
74  do {
75  strm.avail_out = CHUNK;
76  strm.next_out = out;
77  ret = deflate(&strm, flush); /* no bad return value */
78  assert(ret != Z_STREAM_ERROR); /* state not clobbered */
79  have = CHUNK - strm.avail_out;
80  if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
81  (void)deflateEnd(&strm);
82  return Z_ERRNO;
83  }
84  } while (strm.avail_out == 0);
85  assert(strm.avail_in == 0); /* all input will be used */
86 
87  /* done when last data in file processed */
88  } while (flush != Z_FINISH);
89  assert(ret == Z_STREAM_END); /* stream will be complete */
90 
91  /* clean up and return */
92  (void)deflateEnd(&strm);
93  return Z_OK;
94 }
95 
96 /* Decompress from file source to file dest until stream ends or EOF.
97  inf() returns Z_OK on success, Z_MEM_ERROR if memory could not be
98  allocated for processing, Z_DATA_ERROR if the deflate data is
99  invalid or incomplete, Z_VERSION_ERROR if the version of zlib.h and
100  the version of the library linked do not match, or Z_ERRNO if there
101  is an error reading or writing the files. */
102 int inf(FILE *source, FILE *dest) {
103  int ret;
104  unsigned have;
105  z_stream strm;
106  unsigned char in[CHUNK];
107  unsigned char out[CHUNK];
108 
109  /* allocate inflate state */
110  strm.zalloc = Z_NULL;
111  strm.zfree = Z_NULL;
112  strm.opaque = Z_NULL;
113  strm.avail_in = 0;
114  strm.next_in = Z_NULL;
115  ret = inflateInit(&strm);
116  if (ret != Z_OK)
117  return ret;
118 
119  /* decompress until deflate stream ends or end of file */
120  do {
121  strm.avail_in = fread(in, 1, CHUNK, source);
122  if (ferror(source)) {
123  (void)inflateEnd(&strm);
124  return Z_ERRNO;
125  }
126  if (strm.avail_in == 0)
127  break;
128  strm.next_in = in;
129 
130  /* run inflate() on input until output buffer not full */
131  do {
132  strm.avail_out = CHUNK;
133  strm.next_out = out;
134  ret = inflate(&strm, Z_NO_FLUSH);
135  assert(ret != Z_STREAM_ERROR); /* state not clobbered */
136  switch (ret) {
137  case Z_NEED_DICT:
138  ret = Z_DATA_ERROR; /* and fall through */
139  case Z_DATA_ERROR:
140  case Z_MEM_ERROR:
141  (void)inflateEnd(&strm);
142  return ret;
143  }
144  have = CHUNK - strm.avail_out;
145  if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
146  (void)inflateEnd(&strm);
147  return Z_ERRNO;
148  }
149  } while (strm.avail_out == 0);
150 
151  /* done when inflate() says it's done */
152  } while (ret != Z_STREAM_END);
153 
154  /* clean up and return */
155  (void)inflateEnd(&strm);
156  return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
157 }
158 
159 /* report a zlib or i/o error */
160 void zerr(int ret) {
161  fputs("zpipe: ", stderr);
162  switch (ret) {
163  case Z_ERRNO:
164  if (ferror(stdin))
165  fputs("error reading stdin\n", stderr);
166  if (ferror(stdout))
167  fputs("error writing stdout\n", stderr);
168  break;
169  case Z_STREAM_ERROR:
170  fputs("invalid compression level\n", stderr);
171  break;
172  case Z_DATA_ERROR:
173  fputs("invalid or incomplete deflate data\n", stderr);
174  break;
175  case Z_MEM_ERROR:
176  fputs("out of memory\n", stderr);
177  break;
178  case Z_VERSION_ERROR:
179  fputs("zlib version mismatch!\n", stderr);
180  }
181 }
182 
183 /* compress or decompress from stdin to stdout */
184 int publish::CmdZpipe::Main(const Options &options) {
185  int ret;
186 
187  /* avoid end-of-line conversions */
188  SET_BINARY_MODE(stdin);
189  SET_BINARY_MODE(stdout);
190 
191  /* do compression if no arguments */
192  if (!options.Has("decompress")) {
193  ret = def(stdin, stdout, Z_DEFAULT_COMPRESSION);
194  if (ret != Z_OK)
195  zerr(ret);
196  return ret;
197  } else {
198  /* do decompression if -d specified */
199  ret = inf(stdin, stdout);
200  if (ret != Z_OK)
201  zerr(ret);
202  return ret;
203  }
204 }
bool Has(const std::string &key) const
Definition: command.h:108
CVMFS_EXPORT const LogSource source
Definition: exception.h:33
#define SET_BINARY_MODE(file)
Definition: cmd_zpipe.cc:36
#define CHUNK
Definition: cmd_zpipe.cc:39
assert((mem||(size==0))&&"Out Of Memory")
int def(FILE *source, FILE *dest, int level)
Definition: cmd_zpipe.cc:47
void zerr(int ret)
Definition: cmd_zpipe.cc:160
virtual int Main(const Options &options)
Definition: cmd_zpipe.cc:184
int inf(FILE *source, FILE *dest)
Definition: cmd_zpipe.cc:102