Coverage Report

Created: 2026-02-14 07:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/minizip-ng/mz_strm_os_posix.c
Line
Count
Source
1
/* mz_strm_posix.c -- Stream for filesystem access for posix/linux
2
   part of the minizip-ng project
3
4
   Copyright (C) Nathan Moinvaziri
5
     https://github.com/zlib-ng/minizip-ng
6
   Modifications for Zip64 support
7
     Copyright (C) 2009-2010 Mathias Svensson
8
     http://result42.com
9
   Copyright (C) 1998-2010 Gilles Vollant
10
     https://www.winimage.com/zLibDll/minizip.html
11
12
   This program is distributed under the terms of the same license as zlib.
13
   See the accompanying LICENSE file for the full text of the license.
14
*/
15
16
#include "mz.h"
17
#include "mz_strm.h"
18
#include "mz_strm_os.h"
19
20
#include <stdio.h> /* fopen, fread, ... */
21
#include <errno.h>
22
#include <sys/stat.h> /* S_IRUSR, S_IWUSR, ... */
23
#include <unistd.h>   /* open, close, ... */
24
#include <fcntl.h>    /* O_NOFOLLOW, ... */
25
26
/***************************************************************************/
27
28
#define fopen64 fopen
29
#ifndef MZ_FILE32_API
30
#  ifndef NO_FSEEKO
31
0
#    define ftello64 ftello
32
0
#    define fseeko64 fseeko
33
#  elif defined(_MSC_VER) && (_MSC_VER >= 1400)
34
#    define ftello64 _ftelli64
35
#    define fseeko64 _fseeki64
36
#  endif
37
#endif
38
#ifndef ftello64
39
#  define ftello64 ftell
40
#endif
41
#ifndef fseeko64
42
#  define fseeko64 fseek
43
#endif
44
45
/***************************************************************************/
46
47
static mz_stream_vtbl mz_stream_os_vtbl = {mz_stream_os_open,
48
                                           mz_stream_os_is_open,
49
                                           mz_stream_os_read,
50
                                           mz_stream_os_write,
51
                                           mz_stream_os_tell,
52
                                           mz_stream_os_seek,
53
                                           mz_stream_os_close,
54
                                           mz_stream_os_error,
55
                                           mz_stream_os_create,
56
                                           mz_stream_os_delete,
57
                                           NULL,
58
                                           NULL};
59
60
/***************************************************************************/
61
62
typedef struct mz_stream_posix_s {
63
    mz_stream stream;
64
    int32_t error;
65
    FILE *handle;
66
} mz_stream_posix;
67
68
/***************************************************************************/
69
70
0
int32_t mz_stream_os_open(void *stream, const char *path, int32_t mode) {
71
0
    mz_stream_posix *posix = (mz_stream_posix *)stream;
72
0
    const char *mode_fopen = NULL;
73
0
    int mode_open = 0;
74
0
    int fd;
75
76
0
    if (!path)
77
0
        return MZ_PARAM_ERROR;
78
79
0
    if ((mode & MZ_OPEN_MODE_READWRITE) == MZ_OPEN_MODE_READ) {
80
0
        mode_fopen = "r";
81
0
        mode_open = O_RDONLY;
82
0
    } else if (mode & MZ_OPEN_MODE_APPEND) {
83
0
        mode_fopen = "r+";
84
0
        mode_open = O_RDWR;
85
0
    } else if (mode & MZ_OPEN_MODE_CREATE) {
86
0
        mode_fopen = "w";
87
0
        mode_open = O_WRONLY | O_CREAT | O_TRUNC;
88
0
    } else
89
0
        return MZ_OPEN_ERROR;
90
91
0
    if (mode & MZ_OPEN_MODE_NOFOLLOW)
92
0
        mode_open |= O_NOFOLLOW;
93
94
0
    fd = open(path, mode_open, S_IRUSR | S_IWUSR | S_IRGRP);
95
0
    if (fd != -1) {
96
0
        posix->handle = fdopen(fd, mode_fopen);
97
0
        if (!posix->handle)
98
0
            close(fd);
99
0
    }
100
0
    if (!posix->handle) {
101
0
        posix->error = errno;
102
0
        return MZ_OPEN_ERROR;
103
0
    }
104
105
0
    if (mode & MZ_OPEN_MODE_APPEND)
106
0
        return mz_stream_os_seek(stream, 0, MZ_SEEK_END);
107
108
0
    return MZ_OK;
109
0
}
110
111
0
int32_t mz_stream_os_is_open(void *stream) {
112
0
    mz_stream_posix *posix = (mz_stream_posix *)stream;
113
0
    if (!posix->handle)
114
0
        return MZ_OPEN_ERROR;
115
0
    return MZ_OK;
116
0
}
117
118
0
int32_t mz_stream_os_read(void *stream, void *buf, int32_t size) {
119
0
    mz_stream_posix *posix = (mz_stream_posix *)stream;
120
0
    int32_t read = (int32_t)fread(buf, 1, (size_t)size, posix->handle);
121
0
    if (read < size && ferror(posix->handle)) {
122
0
        posix->error = errno;
123
0
        return MZ_READ_ERROR;
124
0
    }
125
0
    return read;
126
0
}
127
128
0
int32_t mz_stream_os_write(void *stream, const void *buf, int32_t size) {
129
0
    mz_stream_posix *posix = (mz_stream_posix *)stream;
130
0
    int32_t written = (int32_t)fwrite(buf, 1, (size_t)size, posix->handle);
131
0
    if (written < size && ferror(posix->handle)) {
132
0
        posix->error = errno;
133
0
        return MZ_WRITE_ERROR;
134
0
    }
135
0
    return written;
136
0
}
137
138
0
int64_t mz_stream_os_tell(void *stream) {
139
0
    mz_stream_posix *posix = (mz_stream_posix *)stream;
140
0
    int64_t position = ftello64(posix->handle);
141
0
    if (position == -1) {
142
0
        posix->error = errno;
143
0
        return MZ_TELL_ERROR;
144
0
    }
145
0
    return position;
146
0
}
147
148
0
int32_t mz_stream_os_seek(void *stream, int64_t offset, int32_t origin) {
149
0
    mz_stream_posix *posix = (mz_stream_posix *)stream;
150
0
    int32_t fseek_origin = 0;
151
152
0
    switch (origin) {
153
0
    case MZ_SEEK_CUR:
154
0
        fseek_origin = SEEK_CUR;
155
0
        break;
156
0
    case MZ_SEEK_END:
157
0
        fseek_origin = SEEK_END;
158
0
        break;
159
0
    case MZ_SEEK_SET:
160
0
        fseek_origin = SEEK_SET;
161
0
        break;
162
0
    default:
163
0
        return MZ_SEEK_ERROR;
164
0
    }
165
166
0
    if (fseeko64(posix->handle, offset, fseek_origin) != 0) {
167
0
        posix->error = errno;
168
0
        return MZ_SEEK_ERROR;
169
0
    }
170
171
0
    return MZ_OK;
172
0
}
173
174
0
int32_t mz_stream_os_close(void *stream) {
175
0
    mz_stream_posix *posix = (mz_stream_posix *)stream;
176
0
    int32_t closed = 0;
177
0
    if (posix->handle) {
178
0
        closed = fclose(posix->handle);
179
0
        posix->handle = NULL;
180
0
    }
181
0
    if (closed != 0) {
182
0
        posix->error = errno;
183
0
        return MZ_CLOSE_ERROR;
184
0
    }
185
0
    return MZ_OK;
186
0
}
187
188
0
int32_t mz_stream_os_error(void *stream) {
189
0
    mz_stream_posix *posix = (mz_stream_posix *)stream;
190
0
    return posix->error;
191
0
}
192
193
0
void *mz_stream_os_create(void) {
194
0
    mz_stream_posix *posix = (mz_stream_posix *)calloc(1, sizeof(mz_stream_posix));
195
0
    if (posix)
196
0
        posix->stream.vtbl = &mz_stream_os_vtbl;
197
0
    return posix;
198
0
}
199
200
0
void mz_stream_os_delete(void **stream) {
201
0
    mz_stream_posix *posix = NULL;
202
0
    if (!stream)
203
0
        return;
204
0
    posix = (mz_stream_posix *)*stream;
205
0
    free(posix);
206
0
    *stream = NULL;
207
0
}
208
209
0
void *mz_stream_os_get_interface(void) {
210
0
    return (void *)&mz_stream_os_vtbl;
211
0
}