Coverage Report

Created: 2026-05-27 06:16

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_config.h"
18
#include "mz_strm.h"
19
#include "mz_strm_os.h"
20
21
#include <stdio.h> /* fopen, fread, ... */
22
#include <errno.h>
23
#include <sys/stat.h> /* S_IRUSR, S_IWUSR, ... */
24
#include <unistd.h>   /* open, close, ... */
25
#include <fcntl.h>    /* O_NOFOLLOW, ... */
26
27
/***************************************************************************/
28
29
#define fopen64 fopen
30
#ifndef MZ_FILE32_API
31
#  if HAVE_FSEEKO
32
0
#    define ftello64 ftello
33
0
#    define fseeko64 fseeko
34
#  elif defined(_MSC_VER) && (_MSC_VER >= 1400)
35
#    define ftello64 _ftelli64
36
#    define fseeko64 _fseeki64
37
#  endif
38
#endif
39
#ifndef ftello64
40
#  define ftello64 ftell
41
#endif
42
#ifndef fseeko64
43
#  define fseeko64 fseek
44
#endif
45
46
/***************************************************************************/
47
48
static mz_stream_vtbl mz_stream_os_vtbl = {mz_stream_os_open,
49
                                           mz_stream_os_is_open,
50
                                           mz_stream_os_read,
51
                                           mz_stream_os_write,
52
                                           mz_stream_os_tell,
53
                                           mz_stream_os_seek,
54
                                           mz_stream_os_close,
55
                                           mz_stream_os_error,
56
                                           mz_stream_os_create,
57
                                           mz_stream_os_delete,
58
                                           NULL,
59
                                           NULL};
60
61
/***************************************************************************/
62
63
typedef struct mz_stream_posix_s {
64
    mz_stream stream;
65
    int32_t error;
66
    FILE *handle;
67
} mz_stream_posix;
68
69
/***************************************************************************/
70
71
0
int32_t mz_stream_os_open(void *stream, const char *path, int32_t mode) {
72
0
    mz_stream_posix *posix = (mz_stream_posix *)stream;
73
0
    const char *mode_fopen = NULL;
74
0
    int mode_open = 0;
75
0
    int fd;
76
77
0
    if (!path)
78
0
        return MZ_PARAM_ERROR;
79
80
0
    if ((mode & MZ_OPEN_MODE_READWRITE) == MZ_OPEN_MODE_READ) {
81
0
        mode_fopen = "r";
82
0
        mode_open = O_RDONLY;
83
0
    } else if (mode & MZ_OPEN_MODE_APPEND) {
84
0
        mode_fopen = "r+";
85
0
        mode_open = O_RDWR;
86
0
    } else if (mode & MZ_OPEN_MODE_CREATE) {
87
0
        mode_fopen = "w";
88
0
        mode_open = O_WRONLY | O_CREAT | O_TRUNC;
89
0
    } else
90
0
        return MZ_OPEN_ERROR;
91
92
0
    if (mode & MZ_OPEN_MODE_NOFOLLOW)
93
0
        mode_open |= O_NOFOLLOW;
94
95
0
    fd = open(path, mode_open, S_IRUSR | S_IWUSR | S_IRGRP);
96
0
    if (fd != -1) {
97
0
        posix->handle = fdopen(fd, mode_fopen);
98
0
        if (!posix->handle)
99
0
            close(fd);
100
0
    }
101
0
    if (!posix->handle) {
102
0
        posix->error = errno;
103
0
        return MZ_OPEN_ERROR;
104
0
    }
105
106
0
    if (mode & MZ_OPEN_MODE_APPEND)
107
0
        return mz_stream_os_seek(stream, 0, MZ_SEEK_END);
108
109
0
    return MZ_OK;
110
0
}
111
112
0
int32_t mz_stream_os_is_open(void *stream) {
113
0
    mz_stream_posix *posix = (mz_stream_posix *)stream;
114
0
    if (!posix->handle)
115
0
        return MZ_OPEN_ERROR;
116
0
    return MZ_OK;
117
0
}
118
119
0
int32_t mz_stream_os_read(void *stream, void *buf, int32_t size) {
120
0
    mz_stream_posix *posix = (mz_stream_posix *)stream;
121
0
    int32_t read = (int32_t)fread(buf, 1, (size_t)size, posix->handle);
122
0
    if (read < size && ferror(posix->handle)) {
123
0
        posix->error = errno;
124
0
        return MZ_READ_ERROR;
125
0
    }
126
0
    return read;
127
0
}
128
129
0
int32_t mz_stream_os_write(void *stream, const void *buf, int32_t size) {
130
0
    mz_stream_posix *posix = (mz_stream_posix *)stream;
131
0
    int32_t written = (int32_t)fwrite(buf, 1, (size_t)size, posix->handle);
132
0
    if (written < size && ferror(posix->handle)) {
133
0
        posix->error = errno;
134
0
        return MZ_WRITE_ERROR;
135
0
    }
136
0
    return written;
137
0
}
138
139
0
int64_t mz_stream_os_tell(void *stream) {
140
0
    mz_stream_posix *posix = (mz_stream_posix *)stream;
141
0
    int64_t position = ftello64(posix->handle);
142
0
    if (position == -1) {
143
0
        posix->error = errno;
144
0
        return MZ_TELL_ERROR;
145
0
    }
146
0
    return position;
147
0
}
148
149
0
int32_t mz_stream_os_seek(void *stream, int64_t offset, int32_t origin) {
150
0
    mz_stream_posix *posix = (mz_stream_posix *)stream;
151
0
    int32_t fseek_origin = 0;
152
153
0
    switch (origin) {
154
0
    case MZ_SEEK_CUR:
155
0
        fseek_origin = SEEK_CUR;
156
0
        break;
157
0
    case MZ_SEEK_END:
158
0
        fseek_origin = SEEK_END;
159
0
        break;
160
0
    case MZ_SEEK_SET:
161
0
        fseek_origin = SEEK_SET;
162
0
        break;
163
0
    default:
164
0
        return MZ_SEEK_ERROR;
165
0
    }
166
167
0
    if (fseeko64(posix->handle, offset, fseek_origin) != 0) {
168
0
        posix->error = errno;
169
0
        return MZ_SEEK_ERROR;
170
0
    }
171
172
0
    return MZ_OK;
173
0
}
174
175
0
int32_t mz_stream_os_close(void *stream) {
176
0
    mz_stream_posix *posix = (mz_stream_posix *)stream;
177
0
    int32_t closed = 0;
178
0
    if (posix->handle) {
179
0
        closed = fclose(posix->handle);
180
0
        posix->handle = NULL;
181
0
    }
182
0
    if (closed != 0) {
183
0
        posix->error = errno;
184
0
        return MZ_CLOSE_ERROR;
185
0
    }
186
0
    return MZ_OK;
187
0
}
188
189
0
int32_t mz_stream_os_error(void *stream) {
190
0
    mz_stream_posix *posix = (mz_stream_posix *)stream;
191
0
    return posix->error;
192
0
}
193
194
0
void *mz_stream_os_create(void) {
195
0
    mz_stream_posix *posix = (mz_stream_posix *)calloc(1, sizeof(mz_stream_posix));
196
0
    if (posix)
197
0
        posix->stream.vtbl = &mz_stream_os_vtbl;
198
0
    return posix;
199
0
}
200
201
0
void mz_stream_os_delete(void **stream) {
202
0
    mz_stream_posix *posix = NULL;
203
0
    if (!stream)
204
0
        return;
205
0
    posix = (mz_stream_posix *)*stream;
206
0
    free(posix);
207
0
    *stream = NULL;
208
0
}
209
210
0
void *mz_stream_os_get_interface(void) {
211
0
    return (void *)&mz_stream_os_vtbl;
212
0
}