Coverage Report

Created: 2025-07-11 06:45

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