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.
17 /* Open an (uncompressed) file as a stream. Return 0 on success, 1 on
19 NOTE: The MODE argument must remain valid for the lifetime of the stream,
20 because it is referred to by reopen_stream_compressed() if it is called.
21 String constants work fine. */
24 fopen_stream_u(stream *fp, const char *path, const char *mode)
26 fp->u.filep = fopen(path, mode);
27 fp->type = (fp->u.filep) ? UNCOMPRESSED : INVALID;
29 return (fp->u.filep) ? 0 : 1;
32 /* Read from stream. Return number of elements read. */
35 fread_stream(void *ptr, size_t size, size_t nmemb, stream *str)
41 read = fread(ptr, size, nmemb, str->u.filep);
45 read = gzread(str->u.gzfilep, ptr, size * nmemb) / size;
55 /* Write to stream. Return number of elements written. */
58 fwrite_stream(const void *ptr, size_t size, size_t nmemb, stream *str)
64 written = fwrite(ptr, size, nmemb, str->u.filep);
68 written = gzwrite(str->u.gzfilep, ptr, size * nmemb) / size;
81 fclose_stream(stream *str)
85 return fclose(str->u.filep);
88 return gzclose(str->u.gzfilep);
98 ferror_stream(stream *str)
102 return ferror(str->u.filep);
109 err = gzerror(str->u.gzfilep, &errno);
110 if (errno == Z_OK || errno == Z_STREAM_END)
112 else if (errno == Z_ERRNO)
115 fprintf(stderr, "%s\n", err);
129 fseek_stream(stream *str, long offset, int whence)
133 return fseek(str->u.filep, offset, whence);
136 return gzseek(str->u.gzfilep, offset, whence);
143 /* Reopen a stream at the current file position. */
146 reopen_stream_compressed(stream *str)
149 long offset, roffset;
151 /* Already a compressed stream, return immediately */
152 if (str->type == COMPRESSED)
155 if (str->type == INVALID)
158 fd = fileno(str->u.filep);
159 /* Get current (buffered) file position. */
160 offset = ftell(str->u.filep);
162 /* Make sure there's nothing left in buffers. */
163 fflush(str->u.filep);
165 /* Reposition underlying FD. (Might be unnecessary?) */
166 roffset = lseek(fd, offset, SEEK_SET);
168 assert(roffset == offset);
170 /* Reopen as compressed stream. */
171 str->u.gzfilep = gzdopen(fd, str->mode);
172 gzsetparams(str->u.gzfilep, 9, Z_DEFAULT_STRATEGY);
173 str->type = COMPRESSED;
177 transfer(stream *ifp, stream *ofp, int count)
182 while (count == -1 || count > 0) {
183 if (count == -1 || count > sizeof(cmd))
187 n = fread_stream(cmd, 1, num, ifp);
190 if (fwrite_stream(cmd, n, 1, ofp) != 1) {
191 fprintf(stderr, "Write failed :-(\n");
198 fprintf(stderr, "Failed to transfer %d bytes\n", count);