diff options
| author | Roland McGrath <[email protected]> | 2009-01-06 00:54:49 -0800 |
|---|---|---|
| committer | Roland McGrath <[email protected]> | 2009-01-06 00:54:49 -0800 |
| commit | a6ef1dcb1d8b2c9e7f929d352c6f40a95520cc36 (patch) | |
| tree | 5dd575a7d9669189b35516be7184daf1584cb9d6 /libdwfl/gzip.c | |
| parent | 60205c962289f2e3a1545f18711f2ae4ea53ab96 (diff) | |
Fix decompression logic.
Diffstat (limited to 'libdwfl/gzip.c')
| -rw-r--r-- | libdwfl/gzip.c | 33 |
1 files changed, 22 insertions, 11 deletions
diff --git a/libdwfl/gzip.c b/libdwfl/gzip.c index effde5f1..ed602a66 100644 --- a/libdwfl/gzip.c +++ b/libdwfl/gzip.c @@ -52,6 +52,7 @@ #include <unistd.h> #ifdef BZLIB +# define inflate_groks_header true # include <bzlib.h> # define unzip __libdw_bunzip2 # define DWFL_E_ZLIB DWFL_E_BZLIB @@ -66,6 +67,7 @@ # define gzread BZ2_bzread # define gzclose BZ2_bzclose #else +# define inflate_groks_header false # include <zlib.h> # define unzip __libdw_gunzip # define MAGIC "\037\213" @@ -115,19 +117,25 @@ unzip (int fd, off64_t start_offset, return failure; } - if (mapped != NULL) + /* If the file is already mapped in, look at the header. */ + if (mapped != NULL + && (mapped_size <= sizeof MAGIC + || memcmp (mapped, MAGIC, sizeof MAGIC - 1))) + /* Not a compressed file. */ + return DWFL_E_BADELF; + + if (mapped != NULL && inflate_groks_header) { - /* The file is already mapped in. Look at the header. */ - if (mapped_size <= sizeof MAGIC || memcmp (mapped, MAGIC, sizeof MAGIC)) - /* Not a compressed file. */ - return DWFL_E_CB; + /* This style actually only works with bzlib. + The stupid zlib interface has nothing to grok the + gzip file headers except the slow gzFile interface. */ z_stream z = { .next_in = mapped, .avail_in = mapped_size }; int result = inflateInit (&z); if (result != Z (OK)) return zlib_fail (result); - while ((result = inflate (&z, Z_SYNC_FLUSH)) == Z (OK)) + do { ptrdiff_t pos = (void *) z.next_out - buffer; if (!bigger_buffer (z.avail_in)) @@ -138,6 +146,7 @@ unzip (int fd, off64_t start_offset, z.next_out = buffer + pos; z.avail_out = size - pos; } + while ((result = inflate (&z, Z_SYNC_FLUSH)) == Z (OK)); #ifdef BZLIB uint64_t total_out = (((uint64_t) z.total_out_hi32 << 32) @@ -154,16 +163,18 @@ unzip (int fd, off64_t start_offset, } else { + /* Let the decompression library read the file directly. */ + int d = dup (fd); if (unlikely (d < 0)) - return DWFL_E_CB; + return DWFL_E_BADELF; if (start_offset != 0) { off64_t off = lseek (d, start_offset, SEEK_SET); if (off != start_offset) { close (d); - return DWFL_E_CB; + return DWFL_E_BADELF; } } gzFile zf = gzdopen (d, "r"); @@ -179,7 +190,7 @@ unzip (int fd, off64_t start_offset, if (gzdirect (zf)) { gzclose (zf); - return DWFL_E_CB; + return DWFL_E_BADELF; } #endif @@ -201,7 +212,7 @@ unzip (int fd, off64_t start_offset, { gzclose (zf); free (buffer); - return DWFL_E_CB; + return DWFL_E_BADELF; } #endif gzclose (zf); @@ -219,5 +230,5 @@ unzip (int fd, off64_t start_offset, *whole = buffer; *whole_size = size; -return DWFL_E_NOERROR; + return DWFL_E_NOERROR; } |
