source: libwandio/ior-zlib.c @ 525d09d

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivelibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 525d09d was 525d09d, checked in by Shane Alcock <salcock@…>, 6 years ago

Better detection of truncation in libwandio zlib

Previously, we were returning "success" when reading from a truncated
gzip file and simply returning all bytes that we could successfully
decompress. This is not consistent with other gzip tools, which at least
alert that the file was not complete or the gzip integrity check was missing.

Now we will return an error if we hit an EOF in the gzip stream that is
not immediately preceded by a Z_STREAM_END marker and write an error message
to stderr so the user can know what has occurred.

  • Property mode set to 100644
File size: 5.2 KB
Line 
1/*
2 * This file is part of libtrace
3 *
4 * Copyright (c) 2007,2008,2009,2010 The University of Waikato, Hamilton,
5 * New Zealand.
6 *
7 * Authors: Daniel Lawson
8 *          Perry Lorier
9 *          Shane Alcock
10 *         
11 * All rights reserved.
12 *
13 * This code has been developed by the University of Waikato WAND
14 * research group. For further information please see http://www.wand.net.nz/
15 *
16 * libtrace is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * libtrace is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with libtrace; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
29 *
30 * $Id$
31 *
32 */
33
34
35#include "wandio.h"
36#include <zlib.h>
37#include <sys/types.h>
38#include <sys/stat.h>
39#include <fcntl.h>
40#include <stdlib.h>
41#include <string.h>
42#include <errno.h>
43
44/* Libtrace IO module implementing a zlib reader */
45
46enum err_t {
47        ERR_OK  = 1,
48        ERR_EOF = 0,
49        ERR_ERROR = -1
50};
51
52struct zlib_t {
53        Bytef inbuff[1024*1024]; /* bytef is what zlib uses for buffer pointers */
54        z_stream strm;
55        io_t *parent;
56        int outoffset;
57        enum err_t err;
58        size_t sincelastend;
59};
60
61
62extern io_source_t zlib_source; 
63
64#define DATA(io) ((struct zlib_t *)((io)->data))
65#define min(a,b) ((a)<(b) ? (a) : (b))
66
67io_t *zlib_open(io_t *parent)
68{
69        io_t *io;
70        if (!parent)
71                return NULL;
72        io = malloc(sizeof(io_t));
73        io->source = &zlib_source;
74        io->data = malloc(sizeof(struct zlib_t));
75
76        DATA(io)->parent = parent;
77
78        DATA(io)->strm.next_in = NULL;
79        DATA(io)->strm.avail_in = 0;
80        DATA(io)->strm.next_out = NULL;
81        DATA(io)->strm.avail_out = 0;
82        DATA(io)->strm.zalloc = Z_NULL;
83        DATA(io)->strm.zfree = Z_NULL;
84        DATA(io)->strm.opaque = NULL;
85        DATA(io)->err = ERR_OK;
86        DATA(io)->sincelastend = 1;
87
88        inflateInit2(&DATA(io)->strm, 15 | 32);
89
90        return io;
91}
92
93
94static off_t zlib_read(io_t *io, void *buffer, off_t len)
95{
96        if (DATA(io)->err == ERR_EOF)
97                return 0; /* EOF */
98        if (DATA(io)->err == ERR_ERROR) {
99                errno=EIO;
100                return -1; /* ERROR! */
101        }
102
103        DATA(io)->strm.avail_out = len;
104        DATA(io)->strm.next_out = (Bytef*)buffer;
105
106        while (DATA(io)->err == ERR_OK && DATA(io)->strm.avail_out > 0) {
107                while (DATA(io)->strm.avail_in <= 0) {
108                        int bytes_read = wandio_read(DATA(io)->parent, 
109                                (char*)DATA(io)->inbuff,
110                                sizeof(DATA(io)->inbuff));
111                        if (bytes_read == 0) {
112                                /* If we get EOF immediately after a
113                                 * Z_STREAM_END, then we assume we've reached
114                                 * the end of the file. If there was data
115                                 * between the Z_STREAM_END and the EOF, the
116                                 * file has more likely been truncated.
117                                 */
118                                if (DATA(io)->sincelastend > 0) {
119                                        fprintf(stderr, "Unexpected EOF while reading compressed file -- file is probably incomplete\n");
120                                        errno = EIO;
121                                        DATA(io)->err = ERR_ERROR;
122                                        return -1;
123                                }
124
125                                /* EOF */
126                                if (DATA(io)->strm.avail_out == (uint32_t)len) {
127                                        DATA(io)->err = ERR_EOF;
128                                        return 0;
129                                }
130                                /* Return how much data we've managed to read so far. */
131                                return len-DATA(io)->strm.avail_out;
132                        }
133                        if (bytes_read < 0) { /* Error */
134                                /* errno should be set */
135                                DATA(io)->err = ERR_ERROR;
136                                /* Return how much data we managed to read ok */
137                                if (DATA(io)->strm.avail_out != (uint32_t)len) {
138                                        return len-DATA(io)->strm.avail_out;
139                                }
140                                /* Now return error */
141                                return -1;
142                        }
143                        DATA(io)->strm.next_in = DATA(io)->inbuff;
144                        DATA(io)->strm.avail_in = bytes_read;
145                        DATA(io)->sincelastend += bytes_read;
146                }
147                /* Decompress some data into the output buffer */
148                int err=inflate(&DATA(io)->strm, 0);
149                switch(err) {
150                        case Z_OK:
151                                DATA(io)->err = ERR_OK;
152                                break;
153                        case Z_STREAM_END:
154                                /* You would think that an "EOF" on the stream would mean we'd
155                                 * want to pass on an EOF?  Nope.  Some tools (*cough* corel *cough*)
156                                 * annoyingly close and reopen the gzip stream leaving Z_STREAM_END
157                                 * mines for us to find.
158                                 */
159                                inflateEnd(&DATA(io)->strm);
160                                inflateInit2(&DATA(io)->strm, 15 | 32);
161                                DATA(io)->err = ERR_OK;
162                                DATA(io)->sincelastend = 0;
163                                break;
164                        default:
165                                errno=EIO;
166                                DATA(io)->err = ERR_ERROR;
167                }
168        }
169        /* Return the number of bytes decompressed */
170        return len-DATA(io)->strm.avail_out;
171}
172
173static void zlib_close(io_t *io)
174{
175        inflateEnd(&DATA(io)->strm);
176        wandio_destroy(DATA(io)->parent);
177        free(io->data);
178        free(io);
179}
180
181io_source_t zlib_source = {
182        "zlib",
183        zlib_read,
184        NULL,   /* peek */
185        NULL,   /* tell */
186        NULL,   /* seek */
187        zlib_close
188};
189
Note: See TracBrowser for help on using the repository browser.