1 /* mz_strm_posix.c -- Stream for filesystem access for posix/linux
2 Version 2.8.1, December 1, 2018
3 part of the MiniZip project
4
5 Copyright (C) 2010-2018 Nathan Moinvaziri
6 https://github.com/nmoinvaz/minizip
7 Modifications for Zip64 support
8 Copyright (C) 2009-2010 Mathias Svensson
9 http://result42.com
10 Copyright (C) 1998-2010 Gilles Vollant
11 https://www.winimage.com/zLibDll/minizip.html
12
13 This program is distributed under the terms of the same license as zlib.
14 See the accompanying LICENSE file for the full text of the license.
15 */
16
17
18 #include "mz.h"
19 #include "mz_strm.h"
20 #include "mz_strm_os.h"
21
22 #include <stdio.h> /* fopen, fread.. */
23 #include <errno.h>
24
25 /***************************************************************************/
26
27 #define fopen64 fopen
28 #ifndef MZ_FILE32_API
29 # ifndef NO_FSEEKO
30 # define ftello64 ftello
31 # 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 = {
47 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
63 typedef struct mz_stream_posix_s
64 {
65 mz_stream stream;
66 int32_t error;
67 FILE *handle;
68 } mz_stream_posix;
69
70 /***************************************************************************/
71
mz_stream_os_open(void * stream,const char * path,int32_t mode)72 int32_t mz_stream_os_open(void *stream, const char *path, int32_t mode)
73 {
74 mz_stream_posix *posix = (mz_stream_posix *)stream;
75 const char *mode_fopen = NULL;
76
77 if (path == NULL)
78 return MZ_PARAM_ERROR;
79
80 if ((mode & MZ_OPEN_MODE_READWRITE) == MZ_OPEN_MODE_READ)
81 mode_fopen = "rb";
82 else if (mode & MZ_OPEN_MODE_APPEND)
83 mode_fopen = "r+b";
84 else if (mode & MZ_OPEN_MODE_CREATE)
85 mode_fopen = "wb";
86 else
87 return MZ_OPEN_ERROR;
88
89 posix->handle = fopen64(path, mode_fopen);
90 if (posix->handle == NULL)
91 {
92 posix->error = errno;
93 return MZ_OPEN_ERROR;
94 }
95
96 if (mode & MZ_OPEN_MODE_APPEND)
97 return mz_stream_os_seek(stream, 0, MZ_SEEK_END);
98
99 return MZ_OK;
100 }
101
mz_stream_os_is_open(void * stream)102 int32_t mz_stream_os_is_open(void *stream)
103 {
104 mz_stream_posix *posix = (mz_stream_posix*)stream;
105 if (posix->handle == NULL)
106 return MZ_OPEN_ERROR;
107 return MZ_OK;
108 }
109
mz_stream_os_read(void * stream,void * buf,int32_t size)110 int32_t mz_stream_os_read(void *stream, void *buf, int32_t size)
111 {
112 mz_stream_posix *posix = (mz_stream_posix*)stream;
113 int32_t read = (int32_t)fread(buf, 1, (size_t)size, posix->handle);
114 if (read < size && ferror(posix->handle))
115 {
116 posix->error = errno;
117 return MZ_READ_ERROR;
118 }
119 return read;
120 }
121
mz_stream_os_write(void * stream,const void * buf,int32_t size)122 int32_t mz_stream_os_write(void *stream, const void *buf, int32_t size)
123 {
124 mz_stream_posix *posix = (mz_stream_posix*)stream;
125 int32_t written = (int32_t)fwrite(buf, 1, (size_t)size, posix->handle);
126 if (written < size && ferror(posix->handle))
127 {
128 posix->error = errno;
129 return MZ_WRITE_ERROR;
130 }
131 return written;
132 }
133
mz_stream_os_tell(void * stream)134 int64_t mz_stream_os_tell(void *stream)
135 {
136 mz_stream_posix *posix = (mz_stream_posix*)stream;
137 int64_t position = ftello64(posix->handle);
138 if (position == -1)
139 {
140 posix->error = errno;
141 return MZ_TELL_ERROR;
142 }
143 return position;
144 }
145
mz_stream_os_seek(void * stream,int64_t offset,int32_t origin)146 int32_t mz_stream_os_seek(void *stream, int64_t offset, int32_t origin)
147 {
148 mz_stream_posix *posix = (mz_stream_posix*)stream;
149 int32_t fseek_origin = 0;
150
151 switch (origin)
152 {
153 case MZ_SEEK_CUR:
154 fseek_origin = SEEK_CUR;
155 break;
156 case MZ_SEEK_END:
157 fseek_origin = SEEK_END;
158 break;
159 case MZ_SEEK_SET:
160 fseek_origin = SEEK_SET;
161 break;
162 default:
163 return MZ_SEEK_ERROR;
164 }
165
166 if (fseeko64(posix->handle, offset, fseek_origin) != 0)
167 {
168 posix->error = errno;
169 return MZ_SEEK_ERROR;
170 }
171
172 return MZ_OK;
173 }
174
mz_stream_os_close(void * stream)175 int32_t mz_stream_os_close(void *stream)
176 {
177 mz_stream_posix *posix = (mz_stream_posix*)stream;
178 int32_t closed = 0;
179 if (posix->handle != NULL)
180 {
181 closed = fclose(posix->handle);
182 posix->handle = NULL;
183 }
184 if (closed != 0)
185 {
186 posix->error = errno;
187 return MZ_CLOSE_ERROR;
188 }
189 return MZ_OK;
190 }
191
mz_stream_os_error(void * stream)192 int32_t mz_stream_os_error(void *stream)
193 {
194 mz_stream_posix *posix = (mz_stream_posix*)stream;
195 return posix->error;
196 }
197
mz_stream_os_create(void ** stream)198 void *mz_stream_os_create(void **stream)
199 {
200 mz_stream_posix *posix = NULL;
201
202 posix = (mz_stream_posix *)MZ_ALLOC(sizeof(mz_stream_posix));
203 if (posix != NULL)
204 {
205 memset(posix, 0, sizeof(mz_stream_posix));
206 posix->stream.vtbl = &mz_stream_os_vtbl;
207 }
208 if (stream != NULL)
209 *stream = posix;
210
211 return posix;
212 }
213
mz_stream_os_delete(void ** stream)214 void mz_stream_os_delete(void **stream)
215 {
216 mz_stream_posix *posix = NULL;
217 if (stream == NULL)
218 return;
219 posix = (mz_stream_posix *)*stream;
220 if (posix != NULL)
221 MZ_FREE(posix);
222 *stream = NULL;
223 }
224
mz_stream_os_get_interface(void)225 void *mz_stream_os_get_interface(void)
226 {
227 return (void *)&mz_stream_os_vtbl;
228 }
229