CernVM-FS  2.12.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 #include "cvmfs_config.h"
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 {
49  int ret, flush;
50  unsigned have;
51  z_stream strm;
52  unsigned char in[CHUNK];
53  unsigned char out[CHUNK];
54 
55  /* allocate deflate state */
56  strm.zalloc = Z_NULL;
57  strm.zfree = Z_NULL;
58  strm.opaque = Z_NULL;
59  ret = deflateInit(&strm, level);
60  if (ret != Z_OK)
61  return ret;
62 
63  /* compress until end of file */
64  do {
65  strm.avail_in = fread(in, 1, CHUNK, source);
66  if (ferror(source)) {
67  (void)deflateEnd(&strm);
68  return Z_ERRNO;
69  }
70  flush = feof(source) ? Z_FINISH : Z_NO_FLUSH;
71  strm.next_in = in;
72 
73  /* run deflate() on input until output buffer not full, finish
74  compression if all of source has been read in */
75  do {
76  strm.avail_out = CHUNK;
77  strm.next_out = out;
78  ret = deflate(&strm, flush); /* no bad return value */
79  assert(ret != Z_STREAM_ERROR); /* state not clobbered */
80  have = CHUNK - strm.avail_out;
81  if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
82  (void)deflateEnd(&strm);
83  return Z_ERRNO;
84  }
85  } while (strm.avail_out == 0);
86  assert(strm.avail_in == 0); /* all input will be used */
87 
88  /* done when last data in file processed */
89  } while (flush != Z_FINISH);
90  assert(ret == Z_STREAM_END); /* stream will be complete */
91 
92  /* clean up and return */
93  (void)deflateEnd(&strm);
94  return Z_OK;
95 }
96 
97 /* Decompress from file source to file dest until stream ends or EOF.
98  inf() returns Z_OK on success, Z_MEM_ERROR if memory could not be
99  allocated for processing, Z_DATA_ERROR if the deflate data is
100  invalid or incomplete, Z_VERSION_ERROR if the version of zlib.h and
101  the version of the library linked do not match, or Z_ERRNO if there
102  is an error reading or writing the files. */
103 int inf(FILE *source, FILE *dest)
104 {
105  int ret;
106  unsigned have;
107  z_stream strm;
108  unsigned char in[CHUNK];
109  unsigned char out[CHUNK];
110 
111  /* allocate inflate state */
112  strm.zalloc = Z_NULL;
113  strm.zfree = Z_NULL;
114  strm.opaque = Z_NULL;
115  strm.avail_in = 0;
116  strm.next_in = Z_NULL;
117  ret = inflateInit(&strm);
118  if (ret != Z_OK)
119  return ret;
120 
121  /* decompress until deflate stream ends or end of file */
122  do {
123  strm.avail_in = fread(in, 1, CHUNK, source);
124  if (ferror(source)) {
125  (void)inflateEnd(&strm);
126  return Z_ERRNO;
127  }
128  if (strm.avail_in == 0)
129  break;
130  strm.next_in = in;
131 
132  /* run inflate() on input until output buffer not full */
133  do {
134  strm.avail_out = CHUNK;
135  strm.next_out = out;
136  ret = inflate(&strm, Z_NO_FLUSH);
137  assert(ret != Z_STREAM_ERROR); /* state not clobbered */
138  switch (ret) {
139  case Z_NEED_DICT:
140  ret = Z_DATA_ERROR; /* and fall through */
141  case Z_DATA_ERROR:
142  case Z_MEM_ERROR:
143  (void)inflateEnd(&strm);
144  return ret;
145  }
146  have = CHUNK - strm.avail_out;
147  if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
148  (void)inflateEnd(&strm);
149  return Z_ERRNO;
150  }
151  } while (strm.avail_out == 0);
152 
153  /* done when inflate() says it's done */
154  } while (ret != Z_STREAM_END);
155 
156  /* clean up and return */
157  (void)inflateEnd(&strm);
158  return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
159 }
160 
161 /* report a zlib or i/o error */
162 void zerr(int ret)
163 {
164  fputs("zpipe: ", stderr);
165  switch (ret) {
166  case Z_ERRNO:
167  if (ferror(stdin))
168  fputs("error reading stdin\n", stderr);
169  if (ferror(stdout))
170  fputs("error writing stdout\n", stderr);
171  break;
172  case Z_STREAM_ERROR:
173  fputs("invalid compression level\n", stderr);
174  break;
175  case Z_DATA_ERROR:
176  fputs("invalid or incomplete deflate data\n", stderr);
177  break;
178  case Z_MEM_ERROR:
179  fputs("out of memory\n", stderr);
180  break;
181  case Z_VERSION_ERROR:
182  fputs("zlib version mismatch!\n", stderr);
183  }
184 }
185 
186 /* compress or decompress from stdin to stdout */
187 int publish::CmdZpipe::Main(const Options &options) {
188  int ret;
189 
190  /* avoid end-of-line conversions */
191  SET_BINARY_MODE(stdin);
192  SET_BINARY_MODE(stdout);
193 
194  /* do compression if no arguments */
195  if (!options.Has("decompress")) {
196  ret = def(stdin, stdout, Z_DEFAULT_COMPRESSION);
197  if (ret != Z_OK)
198  zerr(ret);
199  return ret;
200  } else {
201  /* do decompression if -d specified */
202  ret = inf(stdin, stdout);
203  if (ret != Z_OK)
204  zerr(ret);
205  return ret;
206  }
207 }
bool Has(const std::string &key) const
Definition: command.h:114
#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:162
virtual int Main(const Options &options)
Definition: cmd_zpipe.cc:187
int inf(FILE *source, FILE *dest)
Definition: cmd_zpipe.cc:103