opencv

Форк
0
525 строк · 14.5 Кб
1
/* gzlib.c -- zlib functions common to reading and writing gzip files
2
 * Copyright (C) 2004-2019 Mark Adler
3
 * For conditions of distribution and use, see copyright notice in zlib.h
4
 */
5

6
#include "zbuild.h"
7
#include "zutil_p.h"
8
#include "gzguts.h"
9

10
#if defined(_WIN32)
11
#  define LSEEK _lseeki64
12
#else
13
#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
14
#  define LSEEK lseek64
15
#else
16
#  define LSEEK lseek
17
#endif
18
#endif
19

20
/* Local functions */
21
static void gz_reset(gz_state *);
22
static gzFile gz_open(const void *, int, const char *);
23

24
/* Reset gzip file state */
25
static void gz_reset(gz_state *state) {
26
    state->x.have = 0;              /* no output data available */
27
    if (state->mode == GZ_READ) {   /* for reading ... */
28
        state->eof = 0;             /* not at end of file */
29
        state->past = 0;            /* have not read past end yet */
30
        state->how = LOOK;          /* look for gzip header */
31
    }
32
    else                            /* for writing ... */
33
        state->reset = 0;           /* no deflateReset pending */
34
    state->seek = 0;                /* no seek request pending */
35
    gz_error(state, Z_OK, NULL);    /* clear error */
36
    state->x.pos = 0;               /* no uncompressed data yet */
37
    state->strm.avail_in = 0;       /* no input data yet */
38
}
39

40
/* Open a gzip file either by name or file descriptor. */
41
static gzFile gz_open(const void *path, int fd, const char *mode) {
42
    gz_state *state;
43
    size_t len;
44
    int oflag;
45
#ifdef O_CLOEXEC
46
    int cloexec = 0;
47
#endif
48
#ifdef O_EXCL
49
    int exclusive = 0;
50
#endif
51

52
    /* check input */
53
    if (path == NULL)
54
        return NULL;
55

56
    /* allocate gzFile structure to return */
57
    state = (gz_state *)zng_alloc(sizeof(gz_state));
58
    if (state == NULL)
59
        return NULL;
60
    state->size = 0;            /* no buffers allocated yet */
61
    state->want = GZBUFSIZE;    /* requested buffer size */
62
    state->msg = NULL;          /* no error message yet */
63

64
    /* interpret mode */
65
    state->mode = GZ_NONE;
66
    state->level = Z_DEFAULT_COMPRESSION;
67
    state->strategy = Z_DEFAULT_STRATEGY;
68
    state->direct = 0;
69
    while (*mode) {
70
        if (*mode >= '0' && *mode <= '9') {
71
            state->level = *mode - '0';
72
        } else {
73
            switch (*mode) {
74
            case 'r':
75
                state->mode = GZ_READ;
76
                break;
77
#ifndef NO_GZCOMPRESS
78
            case 'w':
79
                state->mode = GZ_WRITE;
80
                break;
81
            case 'a':
82
                state->mode = GZ_APPEND;
83
                break;
84
#endif
85
            case '+':       /* can't read and write at the same time */
86
                zng_free(state);
87
                return NULL;
88
            case 'b':       /* ignore -- will request binary anyway */
89
                break;
90
#ifdef O_CLOEXEC
91
            case 'e':
92
                cloexec = 1;
93
                break;
94
#endif
95
#ifdef O_EXCL
96
            case 'x':
97
                exclusive = 1;
98
                break;
99
#endif
100
            case 'f':
101
                state->strategy = Z_FILTERED;
102
                break;
103
            case 'h':
104
                state->strategy = Z_HUFFMAN_ONLY;
105
                break;
106
            case 'R':
107
                state->strategy = Z_RLE;
108
                break;
109
            case 'F':
110
                state->strategy = Z_FIXED;
111
                break;
112
            case 'T':
113
                state->direct = 1;
114
                break;
115
            default:        /* could consider as an error, but just ignore */
116
                {}
117
            }
118
        }
119
        mode++;
120
    }
121

122
    /* must provide an "r", "w", or "a" */
123
    if (state->mode == GZ_NONE) {
124
        zng_free(state);
125
        return NULL;
126
    }
127

128
    /* can't force transparent read */
129
    if (state->mode == GZ_READ) {
130
        if (state->direct) {
131
            zng_free(state);
132
            return NULL;
133
        }
134
        state->direct = 1;      /* for empty file */
135
    }
136

137
    /* save the path name for error messages */
138
#ifdef WIDECHAR
139
    if (fd == -2) {
140
        len = wcstombs(NULL, (const wchar_t *)path, 0);
141
        if (len == (size_t)-1)
142
            len = 0;
143
    } else
144
#endif
145
        len = strlen((const char *)path);
146
    state->path = (char *)malloc(len + 1);
147
    if (state->path == NULL) {
148
        zng_free(state);
149
        return NULL;
150
    }
151
#ifdef WIDECHAR
152
    if (fd == -2)
153
        if (len) {
154
            wcstombs(state->path, (const wchar_t *)path, len + 1);
155
        } else {
156
            *(state->path) = 0;
157
        }
158
    else
159
#endif
160
        (void)snprintf(state->path, len + 1, "%s", (const char *)path);
161

162
    /* compute the flags for open() */
163
    oflag =
164
#ifdef O_LARGEFILE
165
        O_LARGEFILE |
166
#endif
167
#ifdef O_BINARY
168
        O_BINARY |
169
#endif
170
#ifdef O_CLOEXEC
171
        (cloexec ? O_CLOEXEC : 0) |
172
#endif
173
        (state->mode == GZ_READ ?
174
         O_RDONLY :
175
         (O_WRONLY | O_CREAT |
176
#ifdef O_EXCL
177
          (exclusive ? O_EXCL : 0) |
178
#endif
179
          (state->mode == GZ_WRITE ?
180
           O_TRUNC :
181
           O_APPEND)));
182

183
    /* open the file with the appropriate flags (or just use fd) */
184
    state->fd = fd > -1 ? fd : (
185
#if defined(_WIN32)
186
        fd == -2 ? _wopen((const wchar_t *)path, oflag, 0666) :
187
#elif __CYGWIN__
188
        fd == -2 ? open(state->path, oflag, 0666) :
189
#endif
190
        open((const char *)path, oflag, 0666));
191
    if (state->fd == -1) {
192
        free(state->path);
193
        zng_free(state);
194
        return NULL;
195
    }
196
    if (state->mode == GZ_APPEND) {
197
        LSEEK(state->fd, 0, SEEK_END);  /* so gzoffset() is correct */
198
        state->mode = GZ_WRITE;         /* simplify later checks */
199
    }
200

201
    /* save the current position for rewinding (only if reading) */
202
    if (state->mode == GZ_READ) {
203
        state->start = LSEEK(state->fd, 0, SEEK_CUR);
204
        if (state->start == -1) state->start = 0;
205
    }
206

207
    /* initialize stream */
208
    gz_reset(state);
209

210
    /* return stream */
211
    return (gzFile)state;
212
}
213

214
/* -- see zlib.h -- */
215
gzFile Z_EXPORT PREFIX(gzopen)(const char *path, const char *mode) {
216
    return gz_open(path, -1, mode);
217
}
218

219
#ifdef ZLIB_COMPAT
220
gzFile Z_EXPORT PREFIX4(gzopen)(const char *path, const char *mode) {
221
    return gz_open(path, -1, mode);
222
}
223
#endif
224

225
/* -- see zlib.h -- */
226
gzFile Z_EXPORT PREFIX(gzdopen)(int fd, const char *mode) {
227
    char *path;         /* identifier for error messages */
228
    gzFile gz;
229

230
    if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL)
231
        return NULL;
232
    (void)snprintf(path, 7 + 3 * sizeof(int), "<fd:%d>", fd); /* for debugging */
233
    gz = gz_open(path, fd, mode);
234
    free(path);
235
    return gz;
236
}
237

238
/* -- see zlib.h -- */
239
#ifdef WIDECHAR
240
gzFile Z_EXPORT PREFIX(gzopen_w)(const wchar_t *path, const char *mode) {
241
    return gz_open(path, -2, mode);
242
}
243
#endif
244

245
int Z_EXPORT PREFIX(gzclose)(gzFile file) {
246
#ifndef NO_GZCOMPRESS
247
    gz_state *state;
248

249
    if (file == NULL)
250
        return Z_STREAM_ERROR;
251
    state = (gz_state *)file;
252

253
    return state->mode == GZ_READ ? PREFIX(gzclose_r)(file) : PREFIX(gzclose_w)(file);
254
#else
255
    return PREFIX(gzclose_r)(file);
256
#endif
257
}
258

259
/* -- see zlib.h -- */
260
int Z_EXPORT PREFIX(gzbuffer)(gzFile file, unsigned size) {
261
    gz_state *state;
262

263
    /* get internal structure and check integrity */
264
    if (file == NULL)
265
        return -1;
266
    state = (gz_state *)file;
267
    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
268
        return -1;
269

270
    /* make sure we haven't already allocated memory */
271
    if (state->size != 0)
272
        return -1;
273

274
    /* check and set requested size */
275
    if ((size << 1) < size)
276
        return -1;              /* need to be able to double it */
277
    if (size < 8)
278
        size = 8;               /* needed to behave well with flushing */
279
    state->want = size;
280
    return 0;
281
}
282

283
/* -- see zlib.h -- */
284
int Z_EXPORT PREFIX(gzrewind)(gzFile file) {
285
    gz_state *state;
286

287
    /* get internal structure */
288
    if (file == NULL)
289
        return -1;
290
    state = (gz_state *)file;
291

292
    /* check that we're reading and that there's no error */
293
    if (state->mode != GZ_READ || (state->err != Z_OK && state->err != Z_BUF_ERROR))
294
        return -1;
295

296
    /* back up and start over */
297
    if (LSEEK(state->fd, state->start, SEEK_SET) == -1)
298
        return -1;
299
    gz_reset(state);
300
    return 0;
301
}
302

303
/* -- see zlib.h -- */
304
z_off64_t Z_EXPORT PREFIX4(gzseek)(gzFile file, z_off64_t offset, int whence) {
305
    unsigned n;
306
    z_off64_t ret;
307
    gz_state *state;
308

309
    /* get internal structure and check integrity */
310
    if (file == NULL)
311
        return -1;
312
    state = (gz_state *)file;
313
    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
314
        return -1;
315

316
    /* check that there's no error */
317
    if (state->err != Z_OK && state->err != Z_BUF_ERROR)
318
        return -1;
319

320
    /* can only seek from start or relative to current position */
321
    if (whence != SEEK_SET && whence != SEEK_CUR)
322
        return -1;
323

324
    /* normalize offset to a SEEK_CUR specification */
325
    if (whence == SEEK_SET)
326
        offset -= state->x.pos;
327
    else if (state->seek)
328
        offset += state->skip;
329
    state->seek = 0;
330

331
    /* if within raw area while reading, just go there */
332
    if (state->mode == GZ_READ && state->how == COPY && state->x.pos + offset >= 0) {
333
        ret = LSEEK(state->fd, offset - (z_off64_t)state->x.have, SEEK_CUR);
334
        if (ret == -1)
335
            return -1;
336
        state->x.have = 0;
337
        state->eof = 0;
338
        state->past = 0;
339
        state->seek = 0;
340
        gz_error(state, Z_OK, NULL);
341
        state->strm.avail_in = 0;
342
        state->x.pos += offset;
343
        return state->x.pos;
344
    }
345

346
    /* calculate skip amount, rewinding if needed for back seek when reading */
347
    if (offset < 0) {
348
        if (state->mode != GZ_READ)         /* writing -- can't go backwards */
349
            return -1;
350
        offset += state->x.pos;
351
        if (offset < 0)                     /* before start of file! */
352
            return -1;
353
        if (PREFIX(gzrewind)(file) == -1)   /* rewind, then skip to offset */
354
            return -1;
355
    }
356

357
    /* if reading, skip what's in output buffer (one less gzgetc() check) */
358
    if (state->mode == GZ_READ) {
359
        n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ? (unsigned)offset : state->x.have;
360
        state->x.have -= n;
361
        state->x.next += n;
362
        state->x.pos += n;
363
        offset -= n;
364
    }
365

366
    /* request skip (if not zero) */
367
    if (offset) {
368
        state->seek = 1;
369
        state->skip = offset;
370
    }
371
    return state->x.pos + offset;
372
}
373

374
/* -- see zlib.h -- */
375
#ifdef ZLIB_COMPAT
376
z_off_t Z_EXPORT PREFIX(gzseek)(gzFile file, z_off_t offset, int whence) {
377
    z_off64_t ret;
378

379
    ret = PREFIX4(gzseek)(file, (z_off64_t)offset, whence);
380
    return ret == (z_off_t)ret ? (z_off_t)ret : -1;
381
}
382
#endif
383

384
/* -- see zlib.h -- */
385
z_off64_t Z_EXPORT PREFIX4(gztell)(gzFile file) {
386
    gz_state *state;
387

388
    /* get internal structure and check integrity */
389
    if (file == NULL)
390
        return -1;
391
    state = (gz_state *)file;
392
    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
393
        return -1;
394

395
    /* return position */
396
    return state->x.pos + (state->seek ? state->skip : 0);
397
}
398

399
/* -- see zlib.h -- */
400
#ifdef ZLIB_COMPAT
401
z_off_t Z_EXPORT PREFIX(gztell)(gzFile file) {
402

403
    z_off64_t ret;
404

405
    ret = PREFIX4(gztell)(file);
406
    return ret == (z_off_t)ret ? (z_off_t)ret : -1;
407
}
408
#endif
409

410
/* -- see zlib.h -- */
411
z_off64_t Z_EXPORT PREFIX4(gzoffset)(gzFile file) {
412
    z_off64_t offset;
413
    gz_state *state;
414

415
    /* get internal structure and check integrity */
416
    if (file == NULL)
417
        return -1;
418
    state = (gz_state *)file;
419
    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
420
        return -1;
421

422
    /* compute and return effective offset in file */
423
    offset = LSEEK(state->fd, 0, SEEK_CUR);
424
    if (offset == -1)
425
        return -1;
426
    if (state->mode == GZ_READ)             /* reading */
427
        offset -= state->strm.avail_in;     /* don't count buffered input */
428
    return offset;
429
}
430

431
/* -- see zlib.h -- */
432
#ifdef ZLIB_COMPAT
433
z_off_t Z_EXPORT PREFIX(gzoffset)(gzFile file) {
434
    z_off64_t ret;
435

436
    ret = PREFIX4(gzoffset)(file);
437
    return ret == (z_off_t)ret ? (z_off_t)ret : -1;
438
}
439
#endif
440

441
/* -- see zlib.h -- */
442
int Z_EXPORT PREFIX(gzeof)(gzFile file) {
443
    gz_state *state;
444

445
    /* get internal structure and check integrity */
446
    if (file == NULL)
447
        return 0;
448
    state = (gz_state *)file;
449
    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
450
        return 0;
451

452
    /* return end-of-file state */
453
    return state->mode == GZ_READ ? state->past : 0;
454
}
455

456
/* -- see zlib.h -- */
457
const char * Z_EXPORT PREFIX(gzerror)(gzFile file, int *errnum) {
458
    gz_state *state;
459

460
    /* get internal structure and check integrity */
461
    if (file == NULL)
462
        return NULL;
463
    state = (gz_state *)file;
464
    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
465
        return NULL;
466

467
    /* return error information */
468
    if (errnum != NULL)
469
        *errnum = state->err;
470
    return state->err == Z_MEM_ERROR ? "out of memory" : (state->msg == NULL ? "" : state->msg);
471
}
472

473
/* -- see zlib.h -- */
474
void Z_EXPORT PREFIX(gzclearerr)(gzFile file) {
475
    gz_state *state;
476

477
    /* get internal structure and check integrity */
478
    if (file == NULL)
479
        return;
480
    state = (gz_state *)file;
481
    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
482
        return;
483

484
    /* clear error and end-of-file */
485
    if (state->mode == GZ_READ) {
486
        state->eof = 0;
487
        state->past = 0;
488
    }
489
    gz_error(state, Z_OK, NULL);
490
}
491

492
/* Create an error message in allocated memory and set state->err and
493
   state->msg accordingly.  Free any previous error message already there.  Do
494
   not try to free or allocate space if the error is Z_MEM_ERROR (out of
495
   memory).  Simply save the error message as a static string.  If there is an
496
   allocation failure constructing the error message, then convert the error to
497
   out of memory. */
498
void Z_INTERNAL gz_error(gz_state *state, int err, const char *msg) {
499
    /* free previously allocated message and clear */
500
    if (state->msg != NULL) {
501
        if (state->err != Z_MEM_ERROR)
502
            free(state->msg);
503
        state->msg = NULL;
504
    }
505

506
    /* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */
507
    if (err != Z_OK && err != Z_BUF_ERROR)
508
        state->x.have = 0;
509

510
    /* set error code, and if no message, then done */
511
    state->err = err;
512
    if (msg == NULL)
513
        return;
514

515
    /* for an out of memory error, return literal string when requested */
516
    if (err == Z_MEM_ERROR)
517
        return;
518

519
    /* construct error message with path */
520
    if ((state->msg = (char *)malloc(strlen(state->path) + strlen(msg) + 3)) == NULL) {
521
        state->err = Z_MEM_ERROR;
522
        return;
523
    }
524
    (void)snprintf(state->msg, strlen(state->path) + strlen(msg) + 3, "%s%s%s", state->path, ": ", msg);
525
}
526

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.