Coverage Report

Created: 2025-04-11 06:10

/src/minizip-ng/mz_strm.c
Line
Count
Source (jump to first uncovered line)
1
/* mz_strm.c -- Stream interface
2
   part of the minizip-ng project
3
4
   Copyright (C) Nathan Moinvaziri
5
     https://github.com/zlib-ng/minizip-ng
6
7
   This program is distributed under the terms of the same license as zlib.
8
   See the accompanying LICENSE file for the full text of the license.
9
*/
10
11
#include "mz.h"
12
#include "mz_strm.h"
13
14
/***************************************************************************/
15
16
0
#define MZ_STREAM_FIND_SIZE (1024)
17
18
/***************************************************************************/
19
20
736
int32_t mz_stream_open(void *stream, const char *path, int32_t mode) {
21
736
    mz_stream *strm = (mz_stream *)stream;
22
736
    if (!strm || !strm->vtbl || !strm->vtbl->open)
23
0
        return MZ_STREAM_ERROR;
24
736
    return strm->vtbl->open(strm, path, mode);
25
736
}
26
27
31.4k
int32_t mz_stream_is_open(void *stream) {
28
31.4k
    mz_stream *strm = (mz_stream *)stream;
29
31.4k
    if (!strm || !strm->vtbl || !strm->vtbl->is_open)
30
0
        return MZ_STREAM_ERROR;
31
31.4k
    return strm->vtbl->is_open(strm);
32
31.4k
}
33
34
2.79k
int32_t mz_stream_read(void *stream, void *buf, int32_t size) {
35
2.79k
    mz_stream *strm = (mz_stream *)stream;
36
2.79k
    if (!strm || !strm->vtbl || !strm->vtbl->read)
37
0
        return MZ_PARAM_ERROR;
38
2.79k
    if (mz_stream_is_open(stream) != MZ_OK)
39
0
        return MZ_STREAM_ERROR;
40
2.79k
    return strm->vtbl->read(strm, buf, size);
41
2.79k
}
42
43
2.42k
static int32_t mz_stream_read_value(void *stream, uint64_t *value, int32_t len) {
44
2.42k
    uint8_t buf[8];
45
2.42k
    int32_t n = 0;
46
2.42k
    int32_t i = 0;
47
48
2.42k
    *value = 0;
49
2.42k
    if (mz_stream_read(stream, buf, len) == len) {
50
4.83k
        for (n = 0; n < len; n += 1, i += 8)
51
2.64k
            *value += ((uint64_t)buf[n]) << i;
52
2.19k
    } else if (mz_stream_error(stream))
53
0
        return MZ_STREAM_ERROR;
54
234
    else
55
234
        return MZ_END_OF_STREAM;
56
57
2.19k
    return MZ_OK;
58
2.42k
}
59
60
1.95k
int32_t mz_stream_read_uint8(void *stream, uint8_t *value) {
61
1.95k
    int32_t err = MZ_OK;
62
1.95k
    uint64_t value64 = 0;
63
64
1.95k
    *value = 0;
65
1.95k
    err = mz_stream_read_value(stream, &value64, sizeof(uint8_t));
66
1.95k
    if (err == MZ_OK)
67
1.74k
        *value = (uint8_t)value64;
68
1.95k
    return err;
69
1.95k
}
70
71
471
int32_t mz_stream_read_uint16(void *stream, uint16_t *value) {
72
471
    int32_t err = MZ_OK;
73
471
    uint64_t value64 = 0;
74
75
471
    *value = 0;
76
471
    err = mz_stream_read_value(stream, &value64, sizeof(uint16_t));
77
471
    if (err == MZ_OK)
78
449
        *value = (uint16_t)value64;
79
471
    return err;
80
471
}
81
82
0
int32_t mz_stream_read_uint32(void *stream, uint32_t *value) {
83
0
    int32_t err = MZ_OK;
84
0
    uint64_t value64 = 0;
85
86
0
    *value = 0;
87
0
    err = mz_stream_read_value(stream, &value64, sizeof(uint32_t));
88
0
    if (err == MZ_OK)
89
0
        *value = (uint32_t)value64;
90
0
    return err;
91
0
}
92
93
0
int32_t mz_stream_read_int64(void *stream, int64_t *value) {
94
0
    return mz_stream_read_value(stream, (uint64_t *)value, sizeof(uint64_t));
95
0
}
96
97
0
int32_t mz_stream_read_uint64(void *stream, uint64_t *value) {
98
0
    return mz_stream_read_value(stream, value, sizeof(uint64_t));
99
0
}
100
101
22.3k
int32_t mz_stream_write(void *stream, const void *buf, int32_t size) {
102
22.3k
    mz_stream *strm = (mz_stream *)stream;
103
22.3k
    if (size == 0)
104
913
        return size;
105
21.4k
    if (!strm || !strm->vtbl || !strm->vtbl->write)
106
0
        return MZ_PARAM_ERROR;
107
21.4k
    if (mz_stream_is_open(stream) != MZ_OK)
108
0
        return MZ_STREAM_ERROR;
109
21.4k
    return strm->vtbl->write(strm, buf, size);
110
21.4k
}
111
112
18.0k
static int32_t mz_stream_write_value(void *stream, uint64_t value, int32_t len) {
113
18.0k
    uint8_t buf[8];
114
18.0k
    int32_t n = 0;
115
116
73.8k
    for (n = 0; n < len; n += 1) {
117
55.7k
        buf[n] = (uint8_t)(value & 0xff);
118
55.7k
        value >>= 8;
119
55.7k
    }
120
121
18.0k
    if (value != 0) {
122
        /* Data overflow - hack for ZIP64 (X Roche) */
123
0
        for (n = 0; n < len; n += 1)
124
0
            buf[n] = 0xff;
125
0
    }
126
127
18.0k
    if (mz_stream_write(stream, buf, len) != len)
128
0
        return MZ_STREAM_ERROR;
129
130
18.0k
    return MZ_OK;
131
18.0k
}
132
133
1.84k
int32_t mz_stream_write_uint8(void *stream, uint8_t value) {
134
1.84k
    return mz_stream_write_value(stream, value, sizeof(uint8_t));
135
1.84k
}
136
137
8.18k
int32_t mz_stream_write_uint16(void *stream, uint16_t value) {
138
8.18k
    return mz_stream_write_value(stream, value, sizeof(uint16_t));
139
8.18k
}
140
141
6.60k
int32_t mz_stream_write_uint32(void *stream, uint32_t value) {
142
6.60k
    return mz_stream_write_value(stream, value, sizeof(uint32_t));
143
6.60k
}
144
145
1.39k
int32_t mz_stream_write_int64(void *stream, int64_t value) {
146
1.39k
    return mz_stream_write_value(stream, (uint64_t)value, sizeof(uint64_t));
147
1.39k
}
148
149
0
int32_t mz_stream_write_uint64(void *stream, uint64_t value) {
150
0
    return mz_stream_write_value(stream, value, sizeof(uint64_t));
151
0
}
152
153
460
int32_t mz_stream_copy(void *target, void *source, int32_t len) {
154
460
    return mz_stream_copy_stream(target, NULL, source, NULL, len);
155
460
}
156
157
0
int32_t mz_stream_copy_to_end(void *target, void *source) {
158
0
    return mz_stream_copy_stream_to_end(target, NULL, source, NULL);
159
0
}
160
161
int32_t mz_stream_copy_stream(void *target, mz_stream_write_cb write_cb, void *source, mz_stream_read_cb read_cb,
162
460
                              int32_t len) {
163
460
    uint8_t buf[16384];
164
460
    int32_t bytes_to_copy = 0;
165
460
    int32_t read = 0;
166
460
    int32_t written = 0;
167
168
460
    if (!write_cb)
169
460
        write_cb = mz_stream_write;
170
460
    if (!read_cb)
171
460
        read_cb = mz_stream_read;
172
173
828
    while (len > 0) {
174
368
        bytes_to_copy = len;
175
368
        if (bytes_to_copy > (int32_t)sizeof(buf))
176
0
            bytes_to_copy = sizeof(buf);
177
368
        read = read_cb(source, buf, bytes_to_copy);
178
368
        if (read <= 0)
179
0
            return MZ_STREAM_ERROR;
180
368
        written = write_cb(target, buf, read);
181
368
        if (written != read)
182
0
            return MZ_STREAM_ERROR;
183
368
        len -= read;
184
368
    }
185
186
460
    return MZ_OK;
187
460
}
188
189
int32_t mz_stream_copy_stream_to_end(void *target, mz_stream_write_cb write_cb, void *source,
190
0
                                     mz_stream_read_cb read_cb) {
191
0
    uint8_t buf[16384];
192
0
    int32_t read = 0;
193
0
    int32_t written = 0;
194
195
0
    if (!write_cb)
196
0
        write_cb = mz_stream_write;
197
0
    if (!read_cb)
198
0
        read_cb = mz_stream_read;
199
200
0
    read = read_cb(source, buf, sizeof(buf));
201
0
    while (read > 0) {
202
0
        written = write_cb(target, buf, read);
203
0
        if (written != read)
204
0
            return MZ_STREAM_ERROR;
205
0
        read = read_cb(source, buf, sizeof(buf));
206
0
    }
207
208
0
    if (read < 0)
209
0
        return MZ_STREAM_ERROR;
210
211
0
    return MZ_OK;
212
0
}
213
214
3.58k
int64_t mz_stream_tell(void *stream) {
215
3.58k
    mz_stream *strm = (mz_stream *)stream;
216
3.58k
    if (!strm || !strm->vtbl || !strm->vtbl->tell)
217
0
        return MZ_PARAM_ERROR;
218
3.58k
    if (mz_stream_is_open(stream) != MZ_OK)
219
0
        return MZ_STREAM_ERROR;
220
3.58k
    return strm->vtbl->tell(strm);
221
3.58k
}
222
223
1.38k
int32_t mz_stream_seek(void *stream, int64_t offset, int32_t origin) {
224
1.38k
    mz_stream *strm = (mz_stream *)stream;
225
1.38k
    if (!strm || !strm->vtbl || !strm->vtbl->seek)
226
0
        return MZ_PARAM_ERROR;
227
1.38k
    if (mz_stream_is_open(stream) != MZ_OK)
228
0
        return MZ_STREAM_ERROR;
229
1.38k
    if (origin == MZ_SEEK_SET && offset < 0)
230
0
        return MZ_SEEK_ERROR;
231
1.38k
    return strm->vtbl->seek(strm, offset, origin);
232
1.38k
}
233
234
0
int32_t mz_stream_find(void *stream, const void *find, int32_t find_size, int64_t max_seek, int64_t *position) {
235
0
    uint8_t buf[MZ_STREAM_FIND_SIZE];
236
0
    int32_t buf_pos = 0;
237
0
    int32_t read_size = sizeof(buf);
238
0
    int32_t read = 0;
239
0
    int64_t read_pos = 0;
240
0
    int64_t start_pos = 0;
241
0
    int64_t disk_pos = 0;
242
0
    int32_t i = 0;
243
0
    uint8_t first = 1;
244
0
    int32_t err = MZ_OK;
245
246
0
    if (!stream || !find || !position)
247
0
        return MZ_PARAM_ERROR;
248
0
    if (find_size < 0 || find_size >= (int32_t)sizeof(buf))
249
0
        return MZ_PARAM_ERROR;
250
251
0
    *position = -1;
252
253
0
    start_pos = mz_stream_tell(stream);
254
255
0
    while (read_pos < max_seek) {
256
0
        if (read_size > (int32_t)(max_seek - read_pos - buf_pos) &&
257
0
            (max_seek - read_pos - buf_pos) < (int64_t)sizeof(buf)) {
258
0
            read_size = (int32_t)(max_seek - read_pos - buf_pos);
259
0
        }
260
261
0
        read = mz_stream_read(stream, buf + buf_pos, read_size);
262
0
        if ((read <= 0) || (read + buf_pos < find_size))
263
0
            break;
264
265
0
        for (i = 0; i <= read + buf_pos - find_size; i += 1) {
266
0
            if (memcmp(&buf[i], find, find_size) != 0)
267
0
                continue;
268
269
0
            disk_pos = mz_stream_tell(stream);
270
271
            /* Seek to position on disk where the data was found */
272
0
            err = mz_stream_seek(stream, disk_pos - ((int64_t)read + buf_pos - i), MZ_SEEK_SET);
273
0
            if (err != MZ_OK)
274
0
                return MZ_EXIST_ERROR;
275
276
0
            *position = start_pos + read_pos + i;
277
0
            return MZ_OK;
278
0
        }
279
280
0
        if (first) {
281
0
            read -= find_size;
282
0
            read_size -= find_size;
283
0
            buf_pos = find_size;
284
0
            first = 0;
285
0
        }
286
287
0
        memmove(buf, buf + read, find_size);
288
0
        read_pos += read;
289
0
    }
290
291
0
    return MZ_EXIST_ERROR;
292
0
}
293
294
0
int32_t mz_stream_find_reverse(void *stream, const void *find, int32_t find_size, int64_t max_seek, int64_t *position) {
295
0
    uint8_t buf[MZ_STREAM_FIND_SIZE];
296
0
    int32_t buf_pos = 0;
297
0
    int32_t read_size = MZ_STREAM_FIND_SIZE;
298
0
    int64_t read_pos = 0;
299
0
    int32_t read = 0;
300
0
    int64_t start_pos = 0;
301
0
    int64_t disk_pos = 0;
302
0
    uint8_t first = 1;
303
0
    int32_t i = 0;
304
0
    int32_t err = MZ_OK;
305
306
0
    if (!stream || !find || !position)
307
0
        return MZ_PARAM_ERROR;
308
0
    if (find_size < 0 || find_size >= (int32_t)sizeof(buf))
309
0
        return MZ_PARAM_ERROR;
310
311
0
    *position = -1;
312
313
0
    start_pos = mz_stream_tell(stream);
314
315
0
    while (read_pos < max_seek) {
316
0
        if (read_size > (int32_t)(max_seek - read_pos) && (max_seek - read_pos) < (int64_t)sizeof(buf))
317
0
            read_size = (int32_t)(max_seek - read_pos);
318
319
0
        if (mz_stream_seek(stream, start_pos - (read_pos + read_size), MZ_SEEK_SET) != MZ_OK)
320
0
            break;
321
0
        read = mz_stream_read(stream, buf, read_size);
322
0
        if ((read <= 0) || (read + buf_pos < find_size))
323
0
            break;
324
0
        if (read + buf_pos < MZ_STREAM_FIND_SIZE)
325
0
            memmove(buf + MZ_STREAM_FIND_SIZE - (read + buf_pos), buf, read);
326
327
0
        for (i = find_size; i <= (read + buf_pos); i += 1) {
328
0
            if (memcmp(&buf[MZ_STREAM_FIND_SIZE - i], find, find_size) != 0)
329
0
                continue;
330
331
0
            disk_pos = mz_stream_tell(stream);
332
333
            /* Seek to position on disk where the data was found */
334
0
            err = mz_stream_seek(stream, disk_pos + buf_pos - i, MZ_SEEK_SET);
335
0
            if (err != MZ_OK)
336
0
                return MZ_EXIST_ERROR;
337
338
0
            *position = start_pos - (read_pos - buf_pos + i);
339
0
            return MZ_OK;
340
0
        }
341
342
0
        if (first) {
343
0
            read -= find_size;
344
0
            read_size -= find_size;
345
0
            buf_pos = find_size;
346
0
            first = 0;
347
0
        }
348
349
0
        if (read == 0)
350
0
            break;
351
352
0
        memmove(buf + read_size, buf, find_size);
353
0
        read_pos += read;
354
0
    }
355
356
0
    return MZ_EXIST_ERROR;
357
0
}
358
359
1.02k
int32_t mz_stream_close(void *stream) {
360
1.02k
    mz_stream *strm = (mz_stream *)stream;
361
1.02k
    if (!strm || !strm->vtbl || !strm->vtbl->close)
362
0
        return MZ_PARAM_ERROR;
363
1.02k
    if (mz_stream_is_open(stream) != MZ_OK)
364
0
        return MZ_STREAM_ERROR;
365
1.02k
    return strm->vtbl->close(strm);
366
1.02k
}
367
368
234
int32_t mz_stream_error(void *stream) {
369
234
    mz_stream *strm = (mz_stream *)stream;
370
234
    if (!strm || !strm->vtbl || !strm->vtbl->error)
371
0
        return MZ_PARAM_ERROR;
372
234
    return strm->vtbl->error(strm);
373
234
}
374
375
930
int32_t mz_stream_set_base(void *stream, void *base) {
376
930
    mz_stream *strm = (mz_stream *)stream;
377
930
    strm->base = (mz_stream *)base;
378
930
    return MZ_OK;
379
930
}
380
381
0
void *mz_stream_get_interface(void *stream) {
382
0
    mz_stream *strm = (mz_stream *)stream;
383
0
    if (!strm || !strm->vtbl)
384
0
        return NULL;
385
0
    return (void *)strm->vtbl;
386
0
}
387
388
2.31k
int32_t mz_stream_get_prop_int64(void *stream, int32_t prop, int64_t *value) {
389
2.31k
    mz_stream *strm = (mz_stream *)stream;
390
2.31k
    if (!strm || !strm->vtbl || !strm->vtbl->get_prop_int64)
391
1.38k
        return MZ_PARAM_ERROR;
392
930
    return strm->vtbl->get_prop_int64(stream, prop, value);
393
2.31k
}
394
395
828
int32_t mz_stream_set_prop_int64(void *stream, int32_t prop, int64_t value) {
396
828
    mz_stream *strm = (mz_stream *)stream;
397
828
    if (!strm || !strm->vtbl || !strm->vtbl->set_prop_int64)
398
460
        return MZ_PARAM_ERROR;
399
368
    return strm->vtbl->set_prop_int64(stream, prop, value);
400
828
}
401
402
0
void *mz_stream_create(mz_stream_vtbl *vtbl) {
403
0
    if (!vtbl || !vtbl->create)
404
0
        return NULL;
405
0
    return vtbl->create();
406
0
}
407
408
1.19k
void mz_stream_delete(void **stream) {
409
1.19k
    mz_stream *strm = NULL;
410
1.19k
    if (!stream)
411
0
        return;
412
1.19k
    strm = (mz_stream *)*stream;
413
1.19k
    if (strm && strm->vtbl && strm->vtbl->destroy)
414
1.19k
        strm->vtbl->destroy(stream);
415
1.19k
    *stream = NULL;
416
1.19k
}
417
418
/***************************************************************************/
419
420
typedef struct mz_stream_raw_s {
421
    mz_stream stream;
422
    int64_t total_in;
423
    int64_t total_out;
424
    int64_t max_total_in;
425
} mz_stream_raw;
426
427
/***************************************************************************/
428
429
542
int32_t mz_stream_raw_open(void *stream, const char *path, int32_t mode) {
430
542
    MZ_UNUSED(stream);
431
542
    MZ_UNUSED(path);
432
542
    MZ_UNUSED(mode);
433
434
542
    return MZ_OK;
435
542
}
436
437
1.02k
int32_t mz_stream_raw_is_open(void *stream) {
438
1.02k
    mz_stream_raw *raw = (mz_stream_raw *)stream;
439
1.02k
    return mz_stream_is_open(raw->stream.base);
440
1.02k
}
441
442
0
int32_t mz_stream_raw_read(void *stream, void *buf, int32_t size) {
443
0
    mz_stream_raw *raw = (mz_stream_raw *)stream;
444
0
    int32_t bytes_to_read = size;
445
0
    int32_t read = 0;
446
447
0
    if (raw->max_total_in > 0) {
448
0
        if ((int64_t)bytes_to_read > (raw->max_total_in - raw->total_in))
449
0
            bytes_to_read = (int32_t)(raw->max_total_in - raw->total_in);
450
0
    }
451
452
0
    read = mz_stream_read(raw->stream.base, buf, bytes_to_read);
453
454
0
    if (read > 0) {
455
0
        raw->total_in += read;
456
0
        raw->total_out += read;
457
0
    }
458
459
0
    return read;
460
0
}
461
462
382
int32_t mz_stream_raw_write(void *stream, const void *buf, int32_t size) {
463
382
    mz_stream_raw *raw = (mz_stream_raw *)stream;
464
382
    int32_t written = 0;
465
466
382
    written = mz_stream_write(raw->stream.base, buf, size);
467
468
382
    if (written > 0) {
469
382
        raw->total_out += written;
470
382
        raw->total_in += written;
471
382
    }
472
473
382
    return written;
474
382
}
475
476
0
int64_t mz_stream_raw_tell(void *stream) {
477
0
    mz_stream_raw *raw = (mz_stream_raw *)stream;
478
0
    return mz_stream_tell(raw->stream.base);
479
0
}
480
481
0
int32_t mz_stream_raw_seek(void *stream, int64_t offset, int32_t origin) {
482
0
    mz_stream_raw *raw = (mz_stream_raw *)stream;
483
0
    return mz_stream_seek(raw->stream.base, offset, origin);
484
0
}
485
486
368
int32_t mz_stream_raw_close(void *stream) {
487
368
    MZ_UNUSED(stream);
488
368
    return MZ_OK;
489
368
}
490
491
0
int32_t mz_stream_raw_error(void *stream) {
492
0
    mz_stream_raw *raw = (mz_stream_raw *)stream;
493
0
    return mz_stream_error(raw->stream.base);
494
0
}
495
496
736
int32_t mz_stream_raw_get_prop_int64(void *stream, int32_t prop, int64_t *value) {
497
736
    mz_stream_raw *raw = (mz_stream_raw *)stream;
498
736
    switch (prop) {
499
368
    case MZ_STREAM_PROP_TOTAL_IN:
500
368
        *value = raw->total_in;
501
368
        return MZ_OK;
502
368
    case MZ_STREAM_PROP_TOTAL_OUT:
503
368
        *value = raw->total_out;
504
368
        return MZ_OK;
505
736
    }
506
0
    return MZ_EXIST_ERROR;
507
736
}
508
509
368
int32_t mz_stream_raw_set_prop_int64(void *stream, int32_t prop, int64_t value) {
510
368
    mz_stream_raw *raw = (mz_stream_raw *)stream;
511
368
    switch (prop) {
512
0
    case MZ_STREAM_PROP_TOTAL_IN_MAX:
513
0
        raw->max_total_in = value;
514
0
        return MZ_OK;
515
368
    }
516
368
    return MZ_EXIST_ERROR;
517
368
}
518
519
/***************************************************************************/
520
521
static mz_stream_vtbl mz_stream_raw_vtbl = {
522
    mz_stream_raw_open,   mz_stream_raw_is_open, mz_stream_raw_read,           mz_stream_raw_write,
523
    mz_stream_raw_tell,   mz_stream_raw_seek,    mz_stream_raw_close,          mz_stream_raw_error,
524
    mz_stream_raw_create, mz_stream_raw_delete,  mz_stream_raw_get_prop_int64, mz_stream_raw_set_prop_int64};
525
526
/***************************************************************************/
527
528
542
void *mz_stream_raw_create(void) {
529
542
    mz_stream_raw *raw = (mz_stream_raw *)calloc(1, sizeof(mz_stream_raw));
530
542
    if (raw)
531
542
        raw->stream.vtbl = &mz_stream_raw_vtbl;
532
542
    return raw;
533
542
}
534
535
542
void mz_stream_raw_delete(void **stream) {
536
542
    mz_stream_raw *raw = NULL;
537
542
    if (!stream)
538
0
        return;
539
542
    raw = (mz_stream_raw *)*stream;
540
542
    free(raw);
541
542
    *stream = NULL;
542
542
}