opencv

Форк
0
/
gzwrite.c 
526 строк · 15.7 Кб
1
/* gzwrite.c -- zlib functions for 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 <stdarg.h>
9
#include "gzguts.h"
10

11
/* Local functions */
12
static int gz_init(gz_state *);
13
static int gz_comp(gz_state *, int);
14
static int gz_zero(gz_state *, z_off64_t);
15
static size_t gz_write(gz_state *, void const *, size_t);
16

17
/* Initialize state for writing a gzip file.  Mark initialization by setting
18
   state->size to non-zero.  Return -1 on a memory allocation failure, or 0 on
19
   success. */
20
static int gz_init(gz_state *state) {
21
    int ret;
22
    PREFIX3(stream) *strm = &(state->strm);
23

24
    /* allocate input buffer (double size for gzprintf) */
25
    state->in = (unsigned char *)zng_alloc(state->want << 1);
26
    if (state->in == NULL) {
27
        gz_error(state, Z_MEM_ERROR, "out of memory");
28
        return -1;
29
    }
30
    memset(state->in, 0, state->want << 1);
31

32
    /* only need output buffer and deflate state if compressing */
33
    if (!state->direct) {
34
        /* allocate output buffer */
35
        state->out = (unsigned char *)zng_alloc(state->want);
36
        if (state->out == NULL) {
37
            zng_free(state->in);
38
            gz_error(state, Z_MEM_ERROR, "out of memory");
39
            return -1;
40
        }
41

42
        /* allocate deflate memory, set up for gzip compression */
43
        strm->zalloc = NULL;
44
        strm->zfree = NULL;
45
        strm->opaque = NULL;
46
        ret = PREFIX(deflateInit2)(strm, state->level, Z_DEFLATED, MAX_WBITS + 16, DEF_MEM_LEVEL, state->strategy);
47
        if (ret != Z_OK) {
48
            zng_free(state->out);
49
            zng_free(state->in);
50
            gz_error(state, Z_MEM_ERROR, "out of memory");
51
            return -1;
52
        }
53
        strm->next_in = NULL;
54
    }
55

56
    /* mark state as initialized */
57
    state->size = state->want;
58

59
    /* initialize write buffer if compressing */
60
    if (!state->direct) {
61
        strm->avail_out = state->size;
62
        strm->next_out = state->out;
63
        state->x.next = strm->next_out;
64
    }
65
    return 0;
66
}
67

68
/* Compress whatever is at avail_in and next_in and write to the output file.
69
   Return -1 if there is an error writing to the output file or if gz_init()
70
   fails to allocate memory, otherwise 0.  flush is assumed to be a valid
71
   deflate() flush value.  If flush is Z_FINISH, then the deflate() state is
72
   reset to start a new gzip stream.  If gz->direct is true, then simply write
73
   to the output file without compressing, and ignore flush. */
74
static int gz_comp(gz_state *state, int flush) {
75
    int ret;
76
    ssize_t got;
77
    unsigned have;
78
    PREFIX3(stream) *strm = &(state->strm);
79

80
    /* allocate memory if this is the first time through */
81
    if (state->size == 0 && gz_init(state) == -1)
82
        return -1;
83

84
    /* write directly if requested */
85
    if (state->direct) {
86
        got = write(state->fd, strm->next_in, strm->avail_in);
87
        if (got < 0 || (unsigned)got != strm->avail_in) {
88
            gz_error(state, Z_ERRNO, zstrerror());
89
            return -1;
90
        }
91
        strm->avail_in = 0;
92
        return 0;
93
    }
94

95
    /* check for a pending reset */
96
    if (state->reset) {
97
        /* don't start a new gzip member unless there is data to write */
98
        if (strm->avail_in == 0)
99
            return 0;
100
        PREFIX(deflateReset)(strm);
101
        state->reset = 0;
102
    }
103

104
    /* run deflate() on provided input until it produces no more output */
105
    ret = Z_OK;
106
    do {
107
        /* write out current buffer contents if full, or if flushing, but if
108
           doing Z_FINISH then don't write until we get to Z_STREAM_END */
109
        if (strm->avail_out == 0 || (flush != Z_NO_FLUSH && (flush != Z_FINISH || ret == Z_STREAM_END))) {
110
            have = (unsigned)(strm->next_out - state->x.next);
111
            if (have && ((got = write(state->fd, state->x.next, (unsigned long)have)) < 0 || (unsigned)got != have)) {
112
                gz_error(state, Z_ERRNO, zstrerror());
113
                return -1;
114
            }
115
            if (strm->avail_out == 0) {
116
                strm->avail_out = state->size;
117
                strm->next_out = state->out;
118
                state->x.next = state->out;
119
            }
120
            state->x.next = strm->next_out;
121
        }
122

123
        /* compress */
124
        have = strm->avail_out;
125
        ret = PREFIX(deflate)(strm, flush);
126
        if (ret == Z_STREAM_ERROR) {
127
            gz_error(state, Z_STREAM_ERROR, "internal error: deflate stream corrupt");
128
            return -1;
129
        }
130
        have -= strm->avail_out;
131
    } while (have);
132

133
    /* if that completed a deflate stream, allow another to start */
134
    if (flush == Z_FINISH)
135
        state->reset = 1;
136
    /* all done, no errors */
137
    return 0;
138
}
139

140
/* Compress len zeros to output.  Return -1 on a write error or memory
141
   allocation failure by gz_comp(), or 0 on success. */
142
static int gz_zero(gz_state *state, z_off64_t len) {
143
    int first;
144
    unsigned n;
145
    PREFIX3(stream) *strm = &(state->strm);
146

147
    /* consume whatever's left in the input buffer */
148
    if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
149
        return -1;
150

151
    /* compress len zeros (len guaranteed > 0) */
152
    first = 1;
153
    while (len) {
154
        n = GT_OFF(state->size) || (z_off64_t)state->size > len ? (unsigned)len : state->size;
155
        if (first) {
156
            memset(state->in, 0, n);
157
            first = 0;
158
        }
159
        strm->avail_in = n;
160
        strm->next_in = state->in;
161
        state->x.pos += n;
162
        if (gz_comp(state, Z_NO_FLUSH) == -1)
163
            return -1;
164
        len -= n;
165
    }
166
    return 0;
167
}
168

169
/* Write len bytes from buf to file.  Return the number of bytes written.  If
170
   the returned value is less than len, then there was an error. */
171
static size_t gz_write(gz_state *state, void const *buf, size_t len) {
172
    size_t put = len;
173

174
    /* if len is zero, avoid unnecessary operations */
175
    if (len == 0)
176
        return 0;
177

178
    /* allocate memory if this is the first time through */
179
    if (state->size == 0 && gz_init(state) == -1)
180
        return 0;
181

182
    /* check for seek request */
183
    if (state->seek) {
184
        state->seek = 0;
185
        if (gz_zero(state, state->skip) == -1)
186
            return 0;
187
    }
188

189
    /* for small len, copy to input buffer, otherwise compress directly */
190
    if (len < state->size) {
191
        /* copy to input buffer, compress when full */
192
        do {
193
            unsigned have, copy;
194

195
            if (state->strm.avail_in == 0)
196
                state->strm.next_in = state->in;
197
            have = (unsigned)((state->strm.next_in + state->strm.avail_in) -
198
                              state->in);
199
            copy = state->size - have;
200
            if (copy > len)
201
                copy = (unsigned)len;
202
            memcpy(state->in + have, buf, copy);
203
            state->strm.avail_in += copy;
204
            state->x.pos += copy;
205
            buf = (const char *)buf + copy;
206
            len -= copy;
207
            if (len && gz_comp(state, Z_NO_FLUSH) == -1)
208
                return 0;
209
        } while (len);
210
    } else {
211
        /* consume whatever's left in the input buffer */
212
        if (state->strm.avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
213
            return 0;
214

215
        /* directly compress user buffer to file */
216
        state->strm.next_in = (z_const unsigned char *) buf;
217
        do {
218
            unsigned n = (unsigned)-1;
219
            if (n > len)
220
                n = (unsigned)len;
221
            state->strm.avail_in = n;
222
            state->x.pos += n;
223
            if (gz_comp(state, Z_NO_FLUSH) == -1)
224
                return 0;
225
            len -= n;
226
        } while (len);
227
    }
228

229
    /* input was all buffered or compressed */
230
    return put;
231
}
232

233
/* -- see zlib.h -- */
234
int Z_EXPORT PREFIX(gzwrite)(gzFile file, void const *buf, unsigned len) {
235
    gz_state *state;
236

237
    /* get internal structure */
238
    if (file == NULL)
239
        return 0;
240
    state = (gz_state *)file;
241

242
    /* check that we're writing and that there's no error */
243
    if (state->mode != GZ_WRITE || state->err != Z_OK)
244
        return 0;
245

246
    /* since an int is returned, make sure len fits in one, otherwise return
247
       with an error (this avoids a flaw in the interface) */
248
    if ((int)len < 0) {
249
        gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
250
        return 0;
251
    }
252

253
    /* write len bytes from buf (the return value will fit in an int) */
254
    return (int)gz_write(state, buf, len);
255
}
256

257
/* -- see zlib.h -- */
258
size_t Z_EXPORT PREFIX(gzfwrite)(void const *buf, size_t size, size_t nitems, gzFile file) {
259
    size_t len;
260
    gz_state *state;
261

262
    /* Exit early if size is zero, also prevents potential division by zero */
263
    if (size == 0)
264
        return 0;
265

266
    /* get internal structure */
267
    if (file == NULL)
268
        return 0;
269
    state = (gz_state *)file;
270

271
    /* check that we're writing and that there's no error */
272
    if (state->mode != GZ_WRITE || state->err != Z_OK)
273
        return 0;
274

275
    /* compute bytes to read -- error on overflow */
276
    len = nitems * size;
277
    if (len / size != nitems) {
278
        gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t");
279
        return 0;
280
    }
281

282
    /* write len bytes to buf, return the number of full items written */
283
    return len ? gz_write(state, buf, len) / size : 0;
284
}
285

286
/* -- see zlib.h -- */
287
int Z_EXPORT PREFIX(gzputc)(gzFile file, int c) {
288
    unsigned have;
289
    unsigned char buf[1];
290
    gz_state *state;
291
    PREFIX3(stream) *strm;
292

293
    /* get internal structure */
294
    if (file == NULL)
295
        return -1;
296
    state = (gz_state *)file;
297
    strm = &(state->strm);
298

299
    /* check that we're writing and that there's no error */
300
    if (state->mode != GZ_WRITE || state->err != Z_OK)
301
        return -1;
302

303
    /* check for seek request */
304
    if (state->seek) {
305
        state->seek = 0;
306
        if (gz_zero(state, state->skip) == -1)
307
            return -1;
308
    }
309

310
    /* try writing to input buffer for speed (state->size == 0 if buffer not
311
       initialized) */
312
    if (state->size) {
313
        if (strm->avail_in == 0)
314
            strm->next_in = state->in;
315
        have = (unsigned)((strm->next_in + strm->avail_in) - state->in);
316
        if (have < state->size) {
317
            state->in[have] = (unsigned char)c;
318
            strm->avail_in++;
319
            state->x.pos++;
320
            return c & 0xff;
321
        }
322
    }
323

324
    /* no room in buffer or not initialized, use gz_write() */
325
    buf[0] = (unsigned char)c;
326
    if (gz_write(state, buf, 1) != 1)
327
        return -1;
328
    return c & 0xff;
329
}
330

331
/* -- see zlib.h -- */
332
int Z_EXPORT PREFIX(gzputs)(gzFile file, const char *s) {
333
    size_t len, put;
334
    gz_state *state;
335

336
    /* get internal structure */
337
    if (file == NULL)
338
        return -1;
339
    state = (gz_state *)file;
340

341
    /* check that we're writing and that there's no error */
342
    if (state->mode != GZ_WRITE || state->err != Z_OK)
343
        return -1;
344

345
    /* write string */
346
    len = strlen(s);
347
    if ((int)len < 0 || (unsigned)len != len) {
348
        gz_error(state, Z_STREAM_ERROR, "string length does not fit in int");
349
        return -1;
350
    }
351
    put = gz_write(state, s, len);
352
    return put < len ? -1 : (int)len;
353
}
354

355
/* -- see zlib.h -- */
356
int Z_EXPORTVA PREFIX(gzvprintf)(gzFile file, const char *format, va_list va) {
357
    int len;
358
    unsigned left;
359
    char *next;
360
    gz_state *state;
361
    PREFIX3(stream) *strm;
362

363
    /* get internal structure */
364
    if (file == NULL)
365
        return Z_STREAM_ERROR;
366
    state = (gz_state *)file;
367
    strm = &(state->strm);
368

369
    /* check that we're writing and that there's no error */
370
    if (state->mode != GZ_WRITE || state->err != Z_OK)
371
        return Z_STREAM_ERROR;
372

373
    /* make sure we have some buffer space */
374
    if (state->size == 0 && gz_init(state) == -1)
375
        return state->err;
376

377
    /* check for seek request */
378
    if (state->seek) {
379
        state->seek = 0;
380
        if (gz_zero(state, state->skip) == -1)
381
            return state->err;
382
    }
383

384
    /* do the printf() into the input buffer, put length in len -- the input
385
       buffer is double-sized just for this function, so there is guaranteed to
386
       be state->size bytes available after the current contents */
387
    if (strm->avail_in == 0)
388
        strm->next_in = state->in;
389
    next = (char *)(state->in + (strm->next_in - state->in) + strm->avail_in);
390
    next[state->size - 1] = 0;
391
    len = vsnprintf(next, state->size, format, va);
392

393
    /* check that printf() results fit in buffer */
394
    if (len == 0 || (unsigned)len >= state->size || next[state->size - 1] != 0)
395
        return 0;
396

397
    /* update buffer and position, compress first half if past that */
398
    strm->avail_in += (unsigned)len;
399
    state->x.pos += len;
400
    if (strm->avail_in >= state->size) {
401
        left = strm->avail_in - state->size;
402
        strm->avail_in = state->size;
403
        if (gz_comp(state, Z_NO_FLUSH) == -1)
404
            return state->err;
405
        memmove(state->in, state->in + state->size, left);
406
        strm->next_in = state->in;
407
        strm->avail_in = left;
408
    }
409
    return len;
410
}
411

412
int Z_EXPORTVA PREFIX(gzprintf)(gzFile file, const char *format, ...) {
413
    va_list va;
414
    int ret;
415

416
    va_start(va, format);
417
    ret = PREFIX(gzvprintf)(file, format, va);
418
    va_end(va);
419
    return ret;
420
}
421

422
/* -- see zlib.h -- */
423
int Z_EXPORT PREFIX(gzflush)(gzFile file, int flush) {
424
    gz_state *state;
425

426
    /* get internal structure */
427
    if (file == NULL)
428
        return Z_STREAM_ERROR;
429
    state = (gz_state *)file;
430

431
    /* check that we're writing and that there's no error */
432
    if (state->mode != GZ_WRITE || state->err != Z_OK)
433
        return Z_STREAM_ERROR;
434

435
    /* check flush parameter */
436
    if (flush < 0 || flush > Z_FINISH)
437
        return Z_STREAM_ERROR;
438

439
    /* check for seek request */
440
    if (state->seek) {
441
        state->seek = 0;
442
        if (gz_zero(state, state->skip) == -1)
443
            return state->err;
444
    }
445

446
    /* compress remaining data with requested flush */
447
    (void)gz_comp(state, flush);
448
    return state->err;
449
}
450

451
/* -- see zlib.h -- */
452
int Z_EXPORT PREFIX(gzsetparams)(gzFile file, int level, int strategy) {
453
    gz_state *state;
454
    PREFIX3(stream) *strm;
455

456
    /* get internal structure */
457
    if (file == NULL)
458
        return Z_STREAM_ERROR;
459
    state = (gz_state *)file;
460
    strm = &(state->strm);
461

462
    /* check that we're writing and that there's no error */
463
    if (state->mode != GZ_WRITE || state->err != Z_OK || state->direct)
464
        return Z_STREAM_ERROR;
465

466
    /* if no change is requested, then do nothing */
467
    if (level == state->level && strategy == state->strategy)
468
        return Z_OK;
469

470
    /* check for seek request */
471
    if (state->seek) {
472
        state->seek = 0;
473
        if (gz_zero(state, state->skip) == -1)
474
            return state->err;
475
    }
476

477
    /* change compression parameters for subsequent input */
478
    if (state->size) {
479
        /* flush previous input with previous parameters before changing */
480
        if (strm->avail_in && gz_comp(state, Z_BLOCK) == -1)
481
            return state->err;
482
        PREFIX(deflateParams)(strm, level, strategy);
483
    }
484
    state->level = level;
485
    state->strategy = strategy;
486
    return Z_OK;
487
}
488

489
/* -- see zlib.h -- */
490
int Z_EXPORT PREFIX(gzclose_w)(gzFile file) {
491
    int ret = Z_OK;
492
    gz_state *state;
493

494
    /* get internal structure */
495
    if (file == NULL)
496
        return Z_STREAM_ERROR;
497
    state = (gz_state *)file;
498

499
    /* check that we're writing */
500
    if (state->mode != GZ_WRITE)
501
        return Z_STREAM_ERROR;
502

503
    /* check for seek request */
504
    if (state->seek) {
505
        state->seek = 0;
506
        if (gz_zero(state, state->skip) == -1)
507
            ret = state->err;
508
    }
509

510
    /* flush, free memory, and close file */
511
    if (gz_comp(state, Z_FINISH) == -1)
512
        ret = state->err;
513
    if (state->size) {
514
        if (!state->direct) {
515
            (void)PREFIX(deflateEnd)(&(state->strm));
516
            zng_free(state->out);
517
        }
518
        zng_free(state->in);
519
    }
520
    gz_error(state, Z_OK, NULL);
521
    free(state->path);
522
    if (close(state->fd) == -1)
523
        ret = Z_ERRNO;
524
    zng_free(state);
525
    return ret;
526
}
527

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

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

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

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