~ubuntu-branches/ubuntu/feisty/clamav/feisty

« back to all changes in this revision

Viewing changes to win32/3rdparty/zlib/gzlib.c

  • Committer: Bazaar Package Importer
  • Author(s): Kees Cook
  • Date: 2007-02-20 10:33:44 UTC
  • mto: This revision was merged to the branch mainline in revision 16.
  • Revision ID: james.westby@ubuntu.com-20070220103344-zgcu2psnx9d98fpa
Tags: upstream-0.90
ImportĀ upstreamĀ versionĀ 0.90

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* gzlib.c -- zlib functions common to reading and writing gzip files
2
 
 * Copyright (C) 2004, 2010 Mark Adler
3
 
 * For conditions of distribution and use, see copyright notice in zlib.h
4
 
 */
5
 
 
6
 
#include "gzguts.h"
7
 
 
8
 
#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
9
 
#  define LSEEK lseek64
10
 
#else
11
 
#  define LSEEK lseek
12
 
#endif
13
 
 
14
 
/* Local functions */
15
 
local void gz_reset OF((gz_statep));
16
 
local gzFile gz_open OF((const char *, int, const char *));
17
 
 
18
 
#if defined UNDER_CE
19
 
 
20
 
/* Map the Windows error number in ERROR to a locale-dependent error message
21
 
   string and return a pointer to it.  Typically, the values for ERROR come
22
 
   from GetLastError.
23
 
 
24
 
   The string pointed to shall not be modified by the application, but may be
25
 
   overwritten by a subsequent call to gz_strwinerror
26
 
 
27
 
   The gz_strwinerror function does not change the current setting of
28
 
   GetLastError. */
29
 
char ZLIB_INTERNAL *gz_strwinerror (error)
30
 
     DWORD error;
31
 
{
32
 
    static char buf[1024];
33
 
 
34
 
    wchar_t *msgbuf;
35
 
    DWORD lasterr = GetLastError();
36
 
    DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
37
 
        | FORMAT_MESSAGE_ALLOCATE_BUFFER,
38
 
        NULL,
39
 
        error,
40
 
        0, /* Default language */
41
 
        (LPVOID)&msgbuf,
42
 
        0,
43
 
        NULL);
44
 
    if (chars != 0) {
45
 
        /* If there is an \r\n appended, zap it.  */
46
 
        if (chars >= 2
47
 
            && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') {
48
 
            chars -= 2;
49
 
            msgbuf[chars] = 0;
50
 
        }
51
 
 
52
 
        if (chars > sizeof (buf) - 1) {
53
 
            chars = sizeof (buf) - 1;
54
 
            msgbuf[chars] = 0;
55
 
        }
56
 
 
57
 
        wcstombs(buf, msgbuf, chars + 1);
58
 
        LocalFree(msgbuf);
59
 
    }
60
 
    else {
61
 
        sprintf(buf, "unknown win32 error (%ld)", error);
62
 
    }
63
 
 
64
 
    SetLastError(lasterr);
65
 
    return buf;
66
 
}
67
 
 
68
 
#endif /* UNDER_CE */
69
 
 
70
 
/* Reset gzip file state */
71
 
local void gz_reset(state)
72
 
    gz_statep state;
73
 
{
74
 
    if (state->mode == GZ_READ) {   /* for reading ... */
75
 
        state->have = 0;            /* no output data available */
76
 
        state->eof = 0;             /* not at end of file */
77
 
        state->how = LOOK;          /* look for gzip header */
78
 
        state->direct = 1;          /* default for empty file */
79
 
    }
80
 
    state->seek = 0;                /* no seek request pending */
81
 
    gz_error(state, Z_OK, NULL);    /* clear error */
82
 
    state->pos = 0;                 /* no uncompressed data yet */
83
 
    state->strm.avail_in = 0;       /* no input data yet */
84
 
}
85
 
 
86
 
/* Open a gzip file either by name or file descriptor. */
87
 
local gzFile gz_open(path, fd, mode)
88
 
    const char *path;
89
 
    int fd;
90
 
    const char *mode;
91
 
{
92
 
    gz_statep state;
93
 
 
94
 
    /* allocate gzFile structure to return */
95
 
    state = malloc(sizeof(gz_state));
96
 
    if (state == NULL)
97
 
        return NULL;
98
 
    state->size = 0;            /* no buffers allocated yet */
99
 
    state->want = GZBUFSIZE;    /* requested buffer size */
100
 
    state->msg = NULL;          /* no error message yet */
101
 
 
102
 
    /* interpret mode */
103
 
    state->mode = GZ_NONE;
104
 
    state->level = Z_DEFAULT_COMPRESSION;
105
 
    state->strategy = Z_DEFAULT_STRATEGY;
106
 
    while (*mode) {
107
 
        if (*mode >= '0' && *mode <= '9')
108
 
            state->level = *mode - '0';
109
 
        else
110
 
            switch (*mode) {
111
 
            case 'r':
112
 
                state->mode = GZ_READ;
113
 
                break;
114
 
#ifndef NO_GZCOMPRESS
115
 
            case 'w':
116
 
                state->mode = GZ_WRITE;
117
 
                break;
118
 
            case 'a':
119
 
                state->mode = GZ_APPEND;
120
 
                break;
121
 
#endif
122
 
            case '+':       /* can't read and write at the same time */
123
 
                free(state);
124
 
                return NULL;
125
 
            case 'b':       /* ignore -- will request binary anyway */
126
 
                break;
127
 
            case 'f':
128
 
                state->strategy = Z_FILTERED;
129
 
                break;
130
 
            case 'h':
131
 
                state->strategy = Z_HUFFMAN_ONLY;
132
 
                break;
133
 
            case 'R':
134
 
                state->strategy = Z_RLE;
135
 
                break;
136
 
            case 'F':
137
 
                state->strategy = Z_FIXED;
138
 
            default:        /* could consider as an error, but just ignore */
139
 
                ;
140
 
            }
141
 
        mode++;
142
 
    }
143
 
 
144
 
    /* must provide an "r", "w", or "a" */
145
 
    if (state->mode == GZ_NONE) {
146
 
        free(state);
147
 
        return NULL;
148
 
    }
149
 
 
150
 
    /* save the path name for error messages */
151
 
    state->path = malloc(strlen(path) + 1);
152
 
    if (state->path == NULL) {
153
 
        free(state);
154
 
        return NULL;
155
 
    }
156
 
    strcpy(state->path, path);
157
 
 
158
 
    /* open the file with the appropriate mode (or just use fd) */
159
 
    state->fd = fd != -1 ? fd :
160
 
        open(path,
161
 
#ifdef O_LARGEFILE
162
 
            O_LARGEFILE |
163
 
#endif
164
 
#ifdef O_BINARY
165
 
            O_BINARY |
166
 
#endif
167
 
            (state->mode == GZ_READ ?
168
 
                O_RDONLY :
169
 
                (O_WRONLY | O_CREAT | (
170
 
                    state->mode == GZ_WRITE ?
171
 
                        O_TRUNC :
172
 
                        O_APPEND))),
173
 
            0666);
174
 
    if (state->fd == -1) {
175
 
        free(state->path);
176
 
        free(state);
177
 
        return NULL;
178
 
    }
179
 
    if (state->mode == GZ_APPEND)
180
 
        state->mode = GZ_WRITE;         /* simplify later checks */
181
 
 
182
 
    /* save the current position for rewinding (only if reading) */
183
 
    if (state->mode == GZ_READ) {
184
 
        state->start = LSEEK(state->fd, 0, SEEK_CUR);
185
 
        if (state->start == -1) state->start = 0;
186
 
    }
187
 
 
188
 
    /* initialize stream */
189
 
    gz_reset(state);
190
 
 
191
 
    /* return stream */
192
 
    return (gzFile)state;
193
 
}
194
 
 
195
 
/* -- see zlib.h -- */
196
 
gzFile ZEXPORT gzopen(path, mode)
197
 
    const char *path;
198
 
    const char *mode;
199
 
{
200
 
    return gz_open(path, -1, mode);
201
 
}
202
 
 
203
 
/* -- see zlib.h -- */
204
 
gzFile ZEXPORT gzopen64(path, mode)
205
 
    const char *path;
206
 
    const char *mode;
207
 
{
208
 
    return gz_open(path, -1, mode);
209
 
}
210
 
 
211
 
/* -- see zlib.h -- */
212
 
gzFile ZEXPORT gzdopen(fd, mode)
213
 
    int fd;
214
 
    const char *mode;
215
 
{
216
 
    char *path;         /* identifier for error messages */
217
 
    gzFile gz;
218
 
 
219
 
    if (fd == -1 || (path = malloc(7 + 3 * sizeof(int))) == NULL)
220
 
        return NULL;
221
 
    sprintf(path, "<fd:%d>", fd);   /* for debugging */
222
 
    gz = gz_open(path, fd, mode);
223
 
    free(path);
224
 
    return gz;
225
 
}
226
 
 
227
 
/* -- see zlib.h -- */
228
 
int ZEXPORT gzbuffer(file, size)
229
 
    gzFile file;
230
 
    unsigned size;
231
 
{
232
 
    gz_statep state;
233
 
 
234
 
    /* get internal structure and check integrity */
235
 
    if (file == NULL)
236
 
        return -1;
237
 
    state = (gz_statep)file;
238
 
    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
239
 
        return -1;
240
 
 
241
 
    /* make sure we haven't already allocated memory */
242
 
    if (state->size != 0)
243
 
        return -1;
244
 
 
245
 
    /* check and set requested size */
246
 
    if (size == 0)
247
 
        return -1;
248
 
    state->want = size;
249
 
    return 0;
250
 
}
251
 
 
252
 
/* -- see zlib.h -- */
253
 
int ZEXPORT gzrewind(file)
254
 
    gzFile file;
255
 
{
256
 
    gz_statep state;
257
 
 
258
 
    /* get internal structure */
259
 
    if (file == NULL)
260
 
        return -1;
261
 
    state = (gz_statep)file;
262
 
 
263
 
    /* check that we're reading and that there's no error */
264
 
    if (state->mode != GZ_READ || state->err != Z_OK)
265
 
        return -1;
266
 
 
267
 
    /* back up and start over */
268
 
    if (LSEEK(state->fd, state->start, SEEK_SET) == -1)
269
 
        return -1;
270
 
    gz_reset(state);
271
 
    return 0;
272
 
}
273
 
 
274
 
/* -- see zlib.h -- */
275
 
z_off64_t ZEXPORT gzseek64(file, offset, whence)
276
 
    gzFile file;
277
 
    z_off64_t offset;
278
 
    int whence;
279
 
{
280
 
    unsigned n;
281
 
    z_off64_t ret;
282
 
    gz_statep state;
283
 
 
284
 
    /* get internal structure and check integrity */
285
 
    if (file == NULL)
286
 
        return -1;
287
 
    state = (gz_statep)file;
288
 
    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
289
 
        return -1;
290
 
 
291
 
    /* check that there's no error */
292
 
    if (state->err != Z_OK)
293
 
        return -1;
294
 
 
295
 
    /* can only seek from start or relative to current position */
296
 
    if (whence != SEEK_SET && whence != SEEK_CUR)
297
 
        return -1;
298
 
 
299
 
    /* normalize offset to a SEEK_CUR specification */
300
 
    if (whence == SEEK_SET)
301
 
        offset -= state->pos;
302
 
    else if (state->seek)
303
 
        offset += state->skip;
304
 
    state->seek = 0;
305
 
 
306
 
    /* if within raw area while reading, just go there */
307
 
    if (state->mode == GZ_READ && state->how == COPY &&
308
 
        state->pos + offset >= state->raw) {
309
 
        ret = LSEEK(state->fd, offset - state->have, SEEK_CUR);
310
 
        if (ret == -1)
311
 
            return -1;
312
 
        state->have = 0;
313
 
        state->eof = 0;
314
 
        state->seek = 0;
315
 
        gz_error(state, Z_OK, NULL);
316
 
        state->strm.avail_in = 0;
317
 
        state->pos += offset;
318
 
        return state->pos;
319
 
    }
320
 
 
321
 
    /* calculate skip amount, rewinding if needed for back seek when reading */
322
 
    if (offset < 0) {
323
 
        if (state->mode != GZ_READ)         /* writing -- can't go backwards */
324
 
            return -1;
325
 
        offset += state->pos;
326
 
        if (offset < 0)                     /* before start of file! */
327
 
            return -1;
328
 
        if (gzrewind(file) == -1)           /* rewind, then skip to offset */
329
 
            return -1;
330
 
    }
331
 
 
332
 
    /* if reading, skip what's in output buffer (one less gzgetc() check) */
333
 
    if (state->mode == GZ_READ) {
334
 
        n = GT_OFF(state->have) || (z_off64_t)state->have > offset ?
335
 
            (unsigned)offset : state->have;
336
 
        state->have -= n;
337
 
        state->next += n;
338
 
        state->pos += n;
339
 
        offset -= n;
340
 
    }
341
 
 
342
 
    /* request skip (if not zero) */
343
 
    if (offset) {
344
 
        state->seek = 1;
345
 
        state->skip = offset;
346
 
    }
347
 
    return state->pos + offset;
348
 
}
349
 
 
350
 
/* -- see zlib.h -- */
351
 
z_off_t ZEXPORT gzseek(file, offset, whence)
352
 
    gzFile file;
353
 
    z_off_t offset;
354
 
    int whence;
355
 
{
356
 
    z_off64_t ret;
357
 
 
358
 
    ret = gzseek64(file, (z_off64_t)offset, whence);
359
 
    return ret == (z_off_t)ret ? (z_off_t)ret : -1;
360
 
}
361
 
 
362
 
/* -- see zlib.h -- */
363
 
z_off64_t ZEXPORT gztell64(file)
364
 
    gzFile file;
365
 
{
366
 
    gz_statep state;
367
 
 
368
 
    /* get internal structure and check integrity */
369
 
    if (file == NULL)
370
 
        return -1;
371
 
    state = (gz_statep)file;
372
 
    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
373
 
        return -1;
374
 
 
375
 
    /* return position */
376
 
    return state->pos + (state->seek ? state->skip : 0);
377
 
}
378
 
 
379
 
/* -- see zlib.h -- */
380
 
z_off_t ZEXPORT gztell(file)
381
 
    gzFile file;
382
 
{
383
 
    z_off64_t ret;
384
 
 
385
 
    ret = gztell64(file);
386
 
    return ret == (z_off_t)ret ? (z_off_t)ret : -1;
387
 
}
388
 
 
389
 
/* -- see zlib.h -- */
390
 
z_off64_t ZEXPORT gzoffset64(file)
391
 
    gzFile file;
392
 
{
393
 
    z_off64_t offset;
394
 
    gz_statep state;
395
 
 
396
 
    /* get internal structure and check integrity */
397
 
    if (file == NULL)
398
 
        return -1;
399
 
    state = (gz_statep)file;
400
 
    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
401
 
        return -1;
402
 
 
403
 
    /* compute and return effective offset in file */
404
 
    offset = LSEEK(state->fd, 0, SEEK_CUR);
405
 
    if (offset == -1)
406
 
        return -1;
407
 
    if (state->mode == GZ_READ)             /* reading */
408
 
        offset -= state->strm.avail_in;     /* don't count buffered input */
409
 
    return offset;
410
 
}
411
 
 
412
 
/* -- see zlib.h -- */
413
 
z_off_t ZEXPORT gzoffset(file)
414
 
    gzFile file;
415
 
{
416
 
    z_off64_t ret;
417
 
 
418
 
    ret = gzoffset64(file);
419
 
    return ret == (z_off_t)ret ? (z_off_t)ret : -1;
420
 
}
421
 
 
422
 
/* -- see zlib.h -- */
423
 
int ZEXPORT gzeof(file)
424
 
    gzFile file;
425
 
{
426
 
    gz_statep state;
427
 
 
428
 
    /* get internal structure and check integrity */
429
 
    if (file == NULL)
430
 
        return 0;
431
 
    state = (gz_statep)file;
432
 
    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
433
 
        return 0;
434
 
 
435
 
    /* return end-of-file state */
436
 
    return state->mode == GZ_READ ?
437
 
        (state->eof && state->strm.avail_in == 0 && state->have == 0) : 0;
438
 
}
439
 
 
440
 
/* -- see zlib.h -- */
441
 
const char * ZEXPORT gzerror(file, errnum)
442
 
    gzFile file;
443
 
    int *errnum;
444
 
{
445
 
    gz_statep state;
446
 
 
447
 
    /* get internal structure and check integrity */
448
 
    if (file == NULL)
449
 
        return NULL;
450
 
    state = (gz_statep)file;
451
 
    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
452
 
        return NULL;
453
 
 
454
 
    /* return error information */
455
 
    if (errnum != NULL)
456
 
        *errnum = state->err;
457
 
    return state->msg == NULL ? "" : state->msg;
458
 
}
459
 
 
460
 
/* -- see zlib.h -- */
461
 
void ZEXPORT gzclearerr(file)
462
 
    gzFile file;
463
 
{
464
 
    gz_statep state;
465
 
 
466
 
    /* get internal structure and check integrity */
467
 
    if (file == NULL)
468
 
        return;
469
 
    state = (gz_statep)file;
470
 
    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
471
 
        return;
472
 
 
473
 
    /* clear error and end-of-file */
474
 
    if (state->mode == GZ_READ)
475
 
        state->eof = 0;
476
 
    gz_error(state, Z_OK, NULL);
477
 
}
478
 
 
479
 
/* Create an error message in allocated memory and set state->err and
480
 
   state->msg accordingly.  Free any previous error message already there.  Do
481
 
   not try to free or allocate space if the error is Z_MEM_ERROR (out of
482
 
   memory).  Simply save the error message as a static string.  If there is an
483
 
   allocation failure constructing the error message, then convert the error to
484
 
   out of memory. */
485
 
void ZLIB_INTERNAL gz_error(state, err, msg)
486
 
    gz_statep state;
487
 
    int err;
488
 
    const char *msg;
489
 
{
490
 
    /* free previously allocated message and clear */
491
 
    if (state->msg != NULL) {
492
 
        if (state->err != Z_MEM_ERROR)
493
 
            free(state->msg);
494
 
        state->msg = NULL;
495
 
    }
496
 
 
497
 
    /* set error code, and if no message, then done */
498
 
    state->err = err;
499
 
    if (msg == NULL)
500
 
        return;
501
 
 
502
 
    /* for an out of memory error, save as static string */
503
 
    if (err == Z_MEM_ERROR) {
504
 
        state->msg = (char *)msg;
505
 
        return;
506
 
    }
507
 
 
508
 
    /* construct error message with path */
509
 
    if ((state->msg = malloc(strlen(state->path) + strlen(msg) + 3)) == NULL) {
510
 
        state->err = Z_MEM_ERROR;
511
 
        state->msg = (char *)"out of memory";
512
 
        return;
513
 
    }
514
 
    strcpy(state->msg, state->path);
515
 
    strcat(state->msg, ": ");
516
 
    strcat(state->msg, msg);
517
 
    return;
518
 
}
519
 
 
520
 
#ifndef INT_MAX
521
 
/* portably return maximum value for an int (when limits.h presumed not
522
 
   available) -- we need to do this to cover cases where 2's complement not
523
 
   used, since C standard permits 1's complement and sign-bit representations,
524
 
   otherwise we could just use ((unsigned)-1) >> 1 */
525
 
unsigned ZLIB_INTERNAL gz_intmax()
526
 
{
527
 
    unsigned p, q;
528
 
 
529
 
    p = 1;
530
 
    do {
531
 
        q = p;
532
 
        p <<= 1;
533
 
        p++;
534
 
    } while (p > q);
535
 
    return q >> 1;
536
 
}
537
 
#endif