HPCToolkit
compress_zlib.c
Go to the documentation of this file.
1 // -*-Mode: C++;-*-
2 
3 // * BeginRiceCopyright *****************************************************
4 //
5 // $HeadURL$
6 // $Id$
7 //
8 // --------------------------------------------------------------------------
9 // Part of HPCToolkit (hpctoolkit.org)
10 //
11 // Information about sources of support for research and development of
12 // HPCToolkit is at 'hpctoolkit.org' and in 'README.Acknowledgments'.
13 // --------------------------------------------------------------------------
14 //
15 // Copyright ((c)) 2002-2019, Rice University
16 // All rights reserved.
17 //
18 // Redistribution and use in source and binary forms, with or without
19 // modification, are permitted provided that the following conditions are
20 // met:
21 //
22 // * Redistributions of source code must retain the above copyright
23 // notice, this list of conditions and the following disclaimer.
24 //
25 // * Redistributions in binary form must reproduce the above copyright
26 // notice, this list of conditions and the following disclaimer in the
27 // documentation and/or other materials provided with the distribution.
28 //
29 // * Neither the name of Rice University (RICE) nor the names of its
30 // contributors may be used to endorse or promote products derived from
31 // this software without specific prior written permission.
32 //
33 // This software is provided by RICE and contributors "as is" and any
34 // express or implied warranties, including, but not limited to, the
35 // implied warranties of merchantability and fitness for a particular
36 // purpose are disclaimed. In no event shall RICE or contributors be
37 // liable for any direct, indirect, incidental, special, exemplary, or
38 // consequential damages (including, but not limited to, procurement of
39 // substitute goods or services; loss of use, data, or profits; or
40 // business interruption) however caused and on any theory of liability,
41 // whether in contract, strict liability, or tort (including negligence
42 // or otherwise) arising in any way out of the use of this software, even
43 // if advised of the possibility of such damage.
44 //
45 // ******************************************************* EndRiceCopyright *
46 
47 //***************************************************************************
48 //
49 // File:
50 // $HeadURL$
51 //
52 // Purpose:
53 // [The purpose of this file]
54 //
55 // Description:
56 // [The set of functions, macros, etc. defined in the file]
57 //
58 //***************************************************************************
59 
60 
61 #include "compress.h"
62 
63 #include <stdio.h>
64 #include <string.h>
65 #include <assert.h>
66 #include "zlib.h"
67 
68 
69 #if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__)
70 # include <fcntl.h>
71 # include <io.h>
72 # define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
73 #else
74 # define SET_BINARY_MODE(file)
75 #endif
76 
77 #define CHUNK 16384
78 
79 /* Compress from file source to file dest until EOF on source.
80 It returns:
81  COMPRESS_OK on success,
82  COMPRESS_FAIL if the inflate data is invalid or the version is
83  incorrect,
84  COMPRESS_IO_ERROR is there is an error reading or writing the file
85 
86  The compression level must be Z_DEFAULT_COMPRESSION,
87  or between 0 and 9: 1 gives best speed, 9 gives best compression,
88  0 gives no compression at all (the input data is simply copied a
89  block at a time). Z_DEFAULT_COMPRESSION requests a default compromise
90  between speed and compression (currently equivalent to level 6).
91  */
92 enum compress_e
93 compress_deflate(FILE *source, FILE *dest, int level)
94 {
95  int ret, flush;
96  unsigned have;
97  z_stream strm;
98  unsigned char in[CHUNK];
99  unsigned char out[CHUNK];
100 
101  /* allocate deflate state */
102  strm.zalloc = Z_NULL;
103  strm.zfree = Z_NULL;
104  strm.opaque = Z_NULL;
105  ret = deflateInit(&strm, level);
106  if (ret != Z_OK)
107  return ret;
108 
109  /* compress until end of file */
110  do {
111  strm.avail_in = fread(in, 1, CHUNK, source);
112  if (ferror(source)) {
113  (void)deflateEnd(&strm);
114  return COMPRESS_FAIL;
115  }
116  flush = feof(source) ? Z_FINISH : Z_NO_FLUSH;
117  strm.next_in = in;
118 
119  /* run deflate() on input until output buffer not full, finish
120  compression if all of source has been read in */
121  do {
122  strm.avail_out = CHUNK;
123  strm.next_out = out;
124  ret = deflate(&strm, flush); /* no bad return value */
125  assert(ret != Z_STREAM_ERROR); /* state not clobbered */
126  have = CHUNK - strm.avail_out;
127  if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
128  (void)deflateEnd(&strm);
129  return COMPRESS_IO_ERROR;
130  }
131  } while (strm.avail_out == 0);
132  assert(strm.avail_in == 0); /* all input will be used */
133 
134  /* done when last data in file processed */
135  } while (flush != Z_FINISH);
136  assert(ret == Z_STREAM_END); /* stream will be complete */
137 
138  /* clean up and return */
139  (void)deflateEnd(&strm);
140  return COMPRESS_OK;
141 }
142 
143 
144 /* Decompress from file source to file dest until stream ends or EOF.
145  It returns:
146  COMPRESS_OK on success,
147  COMPRESS_FAIL if the deflate data is invalid or the version is
148  incorrect,
149  COMPRESS_IO_ERROR is there is an error reading or writing the file
150  COMPRESS_NONE if decompression is not needed.
151  */
152 enum compress_e
153 compress_inflate(FILE *source, FILE *dest)
154 {
155  int ret;
156  unsigned have;
157  z_stream strm;
158  unsigned char in[CHUNK];
159  unsigned char out[CHUNK];
160 
161  /* allocate inflate state */
162  strm.zalloc = Z_NULL;
163  strm.zfree = Z_NULL;
164  strm.opaque = Z_NULL;
165  strm.avail_in = 0;
166  strm.next_in = Z_NULL;
167  ret = inflateInit(&strm);
168  if (ret != Z_OK)
169  return COMPRESS_FAIL;
170 
171  /* decompress until deflate stream ends or end of file */
172  do {
173  strm.avail_in = fread(in, 1, CHUNK, source);
174  if (ferror(source)) {
175  (void)inflateEnd(&strm);
176  return COMPRESS_IO_ERROR;
177  }
178  if (strm.avail_in == 0)
179  break;
180  strm.next_in = in;
181 
182  /* run inflate() on input until output buffer not full */
183  do {
184  strm.avail_out = CHUNK;
185  strm.next_out = out;
186  ret = inflate(&strm, Z_NO_FLUSH);
187  assert(ret != Z_STREAM_ERROR); /* state not clobbered */
188  switch (ret) {
189  case Z_NEED_DICT:
190  ret = Z_DATA_ERROR; /* and fall through */
191  case Z_DATA_ERROR:
192  case Z_MEM_ERROR:
193  (void)inflateEnd(&strm);
194  return COMPRESS_FAIL;
195  }
196  have = CHUNK - strm.avail_out;
197  if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
198  (void)inflateEnd(&strm);
199  return COMPRESS_IO_ERROR;
200  }
201  } while (strm.avail_out == 0);
202 
203  /* done when inflate() says it's done */
204  } while (ret != Z_STREAM_END);
205 
206  /* clean up and return */
207  (void)inflateEnd(&strm);
208  return ret == Z_STREAM_END ? COMPRESS_OK : COMPRESS_IO_ERROR;
209 }
210 
211 #ifdef __UNIT_TEST_COMPRESS__
212 #include <errno.h>
213 #include <unistd.h>
214 #include <stdlib.h>
215 int main(int argc, char *argv[])
216 {
217  if (argc < 3) {
218  printf("syntax: %s input_compressed_file output_file\n", argv[0]);
219  exit(0);
220  }
221  FILE *fp_in = fopen(argv[1], "r");
222  FILE *fp_out = fopen(argv[2], "wx");
223 
224  if (fp_in == NULL || fp_out == NULL) {
225  perror("fail to open file:");
226  }
227  // test 1: compressing file
228  int ret = compress_deflate(fp_in, fp_out, 1);
229  if (ret != COMPRESS_OK) {
230  printf("cannot compress %s into %s\n", argv[1], argv[2]);
231  perror("compress fail:");
232  }
233  fclose(fp_in);
234  fclose(fp_out);
235 
236  // test 2: decompressing file
237  fp_out = fopen(argv[2], "r");
238  FILE *fp_def = tmpfile();
239  ret = compress_inflate(fp_out, fp_def);
240  if (ret != COMPRESS_OK) {
241  printf("cannot decompress %s\n", argv[2]);
242  perror("compress fail:");
243  }
244 
245  // testing the output
246  char buffer[11];
247  fseek(fp_def, 0, SEEK_SET);
248  fgets(buffer, 10, fp_def);
249  buffer[10] = '\0';
250  printf("file: '%s'\n", buffer);
251 
252  fclose(fp_out);
253  fclose(fp_def);
254 
255 }
256 #endif
enum compress_e compress_inflate(FILE *source, FILE *dest)
enum compress_e compress_deflate(FILE *source, FILE *dest, int level)
Definition: compress_zlib.c:93
exit
Definition: names.cpp:1
size_t MONITOR_EXT_WRAP_NAME() fread(void *ptr, size_t size, size_t count, FILE *stream)
Definition: io-over.c:226
int main(int argc, char *argv[])
Definition: main.cpp:125
#define CHUNK
Definition: compress_zlib.c:77
#define NULL
Definition: ElfHelper.cpp:85
size_t MONITOR_EXT_WRAP_NAME() fwrite(const void *ptr, size_t size, size_t count, FILE *stream)
Definition: io-over.c:260
compress_e
Definition: compress.h:73