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
);
128 /* Reopen a stream at the current file position. */
131 reopen_stream_compressed(stream
*str
)
134 long offset
, roffset
;
136 /* Already a compressed stream, return immediately */
137 if (str
->type
== COMPRESSED
)
140 if (str
->type
== INVALID
)
143 fd
= fileno(str
->u
.filep
);
144 /* Get current (buffered) file position. */
145 offset
= ftell(str
->u
.filep
);
147 /* Make sure there's nothing left in buffers. */
148 fflush(str
->u
.filep
);
150 /* Reposition underlying FD. (Might be unnecessary?) */
151 roffset
= lseek(fd
, offset
, SEEK_SET
);
153 assert(roffset
== offset
);
155 /* Reopen as compressed stream. */
156 str
->u
.gzfilep
= gzdopen(fd
, str
->mode
);
157 gzsetparams(str
->u
.gzfilep
, 9, Z_DEFAULT_STRATEGY
);
158 str
->type
= COMPRESSED
;
162 transfer(stream
*ifp
, stream
*ofp
, int count
)
167 while (count
== -1 || count
> 0) {
168 if (count
== -1 || count
> sizeof(cmd
))
172 n
= fread_stream(cmd
, 1, num
, ifp
);
175 if (fwrite_stream(cmd
, n
, 1, ofp
) != 1) {
176 fprintf(stderr
, "Write failed :-(\n");
183 fprintf(stderr
, "Failed to transfer %d bytes\n", count
);