2 * Helper functions to handle compression via zlib
4 * Copyright (C) 2007-2008 Julian Brown
5 * Copyright (C) 2008 Mike Frysinger
7 * Licensed under the GPL-2 or later.
18 /* Open an (uncompressed) file as a stream. Return 0 on success, 1 on
20 NOTE: The MODE argument must remain valid for the lifetime of the stream,
21 because it is referred to by reopen_stream_compressed() if it is called.
22 String constants work fine. */
25 fopen_stream_u(stream *fp, const char *path, const char *mode)
27 fp->u.filep = fopen(path, mode);
28 fp->type = (fp->u.filep) ? UNCOMPRESSED : INVALID;
30 return (fp->u.filep) ? 0 : 1;
33 /* Read from stream. Return number of elements read. */
36 fread_stream(void *ptr, size_t size, size_t nmemb, stream *str)
42 read = fread(ptr, size, nmemb, str->u.filep);
46 read = gzread(str->u.gzfilep, ptr, size * nmemb) / size;
56 /* Write to stream. Return number of elements written. */
59 fwrite_stream(const void *ptr, size_t size, size_t nmemb, stream *str)
65 written = fwrite(ptr, size, nmemb, str->u.filep);
69 written = gzwrite(str->u.gzfilep, ptr, size * nmemb) / size;
82 fclose_stream(stream *str)
86 return fclose(str->u.filep);
89 return gzclose(str->u.gzfilep);
99 ferror_stream(stream *str)
103 return ferror(str->u.filep);
110 err = gzerror(str->u.gzfilep, &errno);
111 if (errno == Z_OK || errno == Z_STREAM_END)
113 else if (errno == Z_ERRNO)
116 fprintf(stderr, "%s\n", err);
130 fseek_stream(stream *str, long offset, int whence)
134 return fseek(str->u.filep, offset, whence);
137 return gzseek(str->u.gzfilep, offset, whence);
144 /* Reopen a stream at the current file position. */
147 reopen_stream_compressed(stream *str)
150 long offset, roffset;
152 /* Already a compressed stream, return immediately */
153 if (str->type == COMPRESSED)
156 if (str->type == INVALID)
159 fd = fileno(str->u.filep);
160 /* Get current (buffered) file position. */
161 offset = ftell(str->u.filep);
163 /* Make sure there's nothing left in buffers. */
164 fflush(str->u.filep);
166 /* Reposition underlying FD. (Might be unnecessary?) */
167 roffset = lseek(fd, offset, SEEK_SET);
169 assert(roffset == offset);
171 /* Reopen as compressed stream. */
172 str->u.gzfilep = gzdopen(fd, str->mode);
173 gzsetparams(str->u.gzfilep, 9, Z_DEFAULT_STRATEGY);
174 str->type = COMPRESSED;
178 transfer(stream *ifp, stream *ofp, int count)
183 while (count == -1 || count > 0) {
184 if (count == -1 || count > sizeof(cmd))
188 n = fread_stream(cmd, 1, num, ifp);
191 if (fwrite_stream(cmd, n, 1, ofp) != 1)
192 fatal_perror("Write failed :-(\n");
197 fatal("Failed to transfer %d bytes\n", count);