Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

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