Line | Count | Source (jump to first uncovered line) |
1 | | /* mz_os.c -- System functions |
2 | | part of the minizip-ng project |
3 | | |
4 | | Copyright (C) Nathan Moinvaziri |
5 | | https://github.com/zlib-ng/minizip-ng |
6 | | Copyright (C) 1998-2010 Gilles Vollant |
7 | | https://www.winimage.com/zLibDll/minizip.html |
8 | | |
9 | | This program is distributed under the terms of the same license as zlib. |
10 | | See the accompanying LICENSE file for the full text of the license. |
11 | | */ |
12 | | |
13 | | #include "mz.h" |
14 | | #include "mz_crypt.h" |
15 | | #include "mz_os.h" |
16 | | #include "mz_strm.h" |
17 | | #include "mz_strm_os.h" |
18 | | |
19 | | #include <ctype.h> /* tolower */ |
20 | | #include <string.h> |
21 | | |
22 | | /***************************************************************************/ |
23 | | |
24 | 0 | int32_t mz_path_combine(char *path, const char *join, int32_t max_path) { |
25 | 0 | int32_t path_len = 0; |
26 | |
|
27 | 0 | if (!path || !join || !max_path) |
28 | 0 | return MZ_PARAM_ERROR; |
29 | | |
30 | 0 | path_len = (int32_t)strlen(path); |
31 | |
|
32 | 0 | if (path_len == 0) { |
33 | 0 | strncpy(path, join, max_path - 1); |
34 | 0 | path[max_path - 1] = 0; |
35 | 0 | } else { |
36 | 0 | mz_path_append_slash(path, max_path, MZ_PATH_SLASH_PLATFORM); |
37 | 0 | path_len = (int32_t)strlen(path); |
38 | 0 | if (max_path > path_len) |
39 | 0 | strncat(path, join, max_path - path_len - 1); |
40 | 0 | } |
41 | |
|
42 | 0 | return MZ_OK; |
43 | 0 | } |
44 | | |
45 | 0 | int32_t mz_path_append_slash(char *path, int32_t max_path, char slash) { |
46 | 0 | int32_t path_len = (int32_t)strlen(path); |
47 | 0 | if ((path_len + 2) >= max_path) |
48 | 0 | return MZ_BUF_ERROR; |
49 | 0 | if (!mz_os_is_dir_separator(path[path_len - 1])) { |
50 | 0 | path[path_len] = slash; |
51 | 0 | path[path_len + 1] = 0; |
52 | 0 | } |
53 | 0 | return MZ_OK; |
54 | 0 | } |
55 | | |
56 | 0 | int32_t mz_path_remove_slash(char *path) { |
57 | 0 | int32_t path_len = (int32_t)strlen(path); |
58 | 0 | while (path_len > 0) { |
59 | 0 | if (mz_os_is_dir_separator(path[path_len - 1])) |
60 | 0 | path[path_len - 1] = 0; |
61 | 0 | else |
62 | 0 | break; |
63 | | |
64 | 0 | path_len -= 1; |
65 | 0 | } |
66 | 0 | return MZ_OK; |
67 | 0 | } |
68 | | |
69 | 0 | int32_t mz_path_has_slash(const char *path) { |
70 | 0 | int32_t path_len = (int32_t)strlen(path); |
71 | 0 | if (path_len > 0 && !mz_os_is_dir_separator(path[path_len - 1])) |
72 | 0 | return MZ_EXIST_ERROR; |
73 | 0 | return MZ_OK; |
74 | 0 | } |
75 | | |
76 | 0 | int32_t mz_path_convert_slashes(char *path, char slash) { |
77 | 0 | int32_t i = 0; |
78 | |
|
79 | 0 | for (i = 0; i < (int32_t)strlen(path); i += 1) { |
80 | 0 | if (mz_os_is_dir_separator(path[i])) |
81 | 0 | path[i] = slash; |
82 | 0 | } |
83 | 0 | return MZ_OK; |
84 | 0 | } |
85 | | |
86 | 0 | int32_t mz_path_compare_wc(const char *path, const char *wildcard, uint8_t ignore_case) { |
87 | 0 | while (*path != 0) { |
88 | 0 | switch (*wildcard) { |
89 | 0 | case '*': |
90 | |
|
91 | 0 | if (*(wildcard + 1) == 0) |
92 | 0 | return MZ_OK; |
93 | | |
94 | 0 | while (*path != 0) { |
95 | 0 | if (mz_path_compare_wc(path, (wildcard + 1), ignore_case) == MZ_OK) |
96 | 0 | return MZ_OK; |
97 | | |
98 | 0 | path += 1; |
99 | 0 | } |
100 | | |
101 | 0 | return MZ_EXIST_ERROR; |
102 | | |
103 | 0 | default: |
104 | | /* Ignore differences in path slashes on platforms */ |
105 | 0 | if ((*path == '\\' && *wildcard == '/') || (*path == '/' && *wildcard == '\\')) |
106 | 0 | break; |
107 | | |
108 | 0 | if (ignore_case) { |
109 | 0 | if (tolower(*path) != tolower(*wildcard)) |
110 | 0 | return MZ_EXIST_ERROR; |
111 | 0 | } else { |
112 | 0 | if (*path != *wildcard) |
113 | 0 | return MZ_EXIST_ERROR; |
114 | 0 | } |
115 | | |
116 | 0 | break; |
117 | 0 | } |
118 | | |
119 | 0 | path += 1; |
120 | 0 | wildcard += 1; |
121 | 0 | } |
122 | | |
123 | 0 | if ((*wildcard != 0) && (*wildcard != '*')) |
124 | 0 | return MZ_EXIST_ERROR; |
125 | | |
126 | 0 | return MZ_OK; |
127 | 0 | } |
128 | | |
129 | 0 | int32_t mz_path_resolve(const char *path, char *output, int32_t max_output) { |
130 | 0 | const char *source = path; |
131 | 0 | const char *check = output; |
132 | 0 | char *target = output; |
133 | |
|
134 | 0 | if (max_output <= 0) |
135 | 0 | return MZ_PARAM_ERROR; |
136 | | |
137 | 0 | while (*source != 0 && max_output > 1) { |
138 | 0 | check = source; |
139 | 0 | if (mz_os_is_dir_separator(*check)) |
140 | 0 | check += 1; |
141 | |
|
142 | 0 | if (source == path || target == output || check != source) { |
143 | | /* Skip double paths */ |
144 | 0 | if (mz_os_is_dir_separator(*check)) { |
145 | 0 | source += 1; |
146 | 0 | continue; |
147 | 0 | } |
148 | 0 | if (*check == '.') { |
149 | 0 | check += 1; |
150 | | |
151 | | /* Remove . if at end of string and not at the beginning */ |
152 | 0 | if (*check == 0 && source != path && target != output) { |
153 | | /* Copy last slash */ |
154 | 0 | *target = *source; |
155 | 0 | target += 1; |
156 | 0 | max_output -= 1; |
157 | 0 | source += (check - source); |
158 | 0 | continue; |
159 | 0 | } |
160 | | /* Remove . if not at end of string */ |
161 | 0 | else if (mz_os_is_dir_separator(*check)) { |
162 | 0 | source += (check - source); |
163 | | /* Skip slash if at beginning of string */ |
164 | 0 | if (target == output && *source != 0) |
165 | 0 | source += 1; |
166 | 0 | continue; |
167 | 0 | } |
168 | | /* Go to parent directory .. */ |
169 | 0 | else if (*check == '.') { |
170 | 0 | check += 1; |
171 | 0 | if (*check == 0 || mz_os_is_dir_separator(*check)) { |
172 | 0 | source += (check - source); |
173 | | |
174 | | /* Search backwards for previous slash or the start of the output string */ |
175 | 0 | if (target != output) { |
176 | 0 | target -= 1; |
177 | 0 | do { |
178 | 0 | if (target == output || mz_os_is_dir_separator(*target)) |
179 | 0 | break; |
180 | | |
181 | 0 | target -= 1; |
182 | 0 | max_output += 1; |
183 | 0 | } while (target > output); |
184 | 0 | } |
185 | | |
186 | 0 | if ((target == output) && *source != 0) |
187 | 0 | source += 1; |
188 | 0 | if (mz_os_is_dir_separator(*target) && *source == 0) |
189 | 0 | target += 1; |
190 | |
|
191 | 0 | *target = 0; |
192 | 0 | continue; |
193 | 0 | } |
194 | 0 | } |
195 | 0 | } |
196 | 0 | } |
197 | | |
198 | 0 | *target = *source; |
199 | |
|
200 | 0 | source += 1; |
201 | 0 | target += 1; |
202 | 0 | max_output -= 1; |
203 | 0 | } |
204 | |
|
205 | 0 | *target = 0; |
206 | |
|
207 | 0 | if (*path == 0) |
208 | 0 | return MZ_INTERNAL_ERROR; |
209 | | |
210 | 0 | return MZ_OK; |
211 | 0 | } |
212 | | |
213 | 0 | int32_t mz_path_remove_filename(char *path) { |
214 | 0 | char *path_ptr = NULL; |
215 | |
|
216 | 0 | if (!path) |
217 | 0 | return MZ_PARAM_ERROR; |
218 | | |
219 | 0 | path_ptr = path + strlen(path) - 1; |
220 | |
|
221 | 0 | while (path_ptr > path) { |
222 | 0 | if (mz_os_is_dir_separator(*path_ptr)) { |
223 | 0 | *path_ptr = 0; |
224 | 0 | break; |
225 | 0 | } |
226 | | |
227 | 0 | path_ptr -= 1; |
228 | 0 | } |
229 | |
|
230 | 0 | if (path_ptr == path) |
231 | 0 | *path_ptr = 0; |
232 | |
|
233 | 0 | return MZ_OK; |
234 | 0 | } |
235 | | |
236 | 0 | int32_t mz_path_remove_extension(char *path) { |
237 | 0 | char *path_ptr = NULL; |
238 | |
|
239 | 0 | if (!path) |
240 | 0 | return MZ_PARAM_ERROR; |
241 | | |
242 | 0 | path_ptr = path + strlen(path) - 1; |
243 | |
|
244 | 0 | while (path_ptr > path) { |
245 | 0 | if (mz_os_is_dir_separator(*path_ptr)) |
246 | 0 | break; |
247 | 0 | if (*path_ptr == '.') { |
248 | 0 | *path_ptr = 0; |
249 | 0 | break; |
250 | 0 | } |
251 | | |
252 | 0 | path_ptr -= 1; |
253 | 0 | } |
254 | |
|
255 | 0 | if (path_ptr == path) |
256 | 0 | *path_ptr = 0; |
257 | |
|
258 | 0 | return MZ_OK; |
259 | 0 | } |
260 | | |
261 | 0 | int32_t mz_path_get_filename(const char *path, const char **filename) { |
262 | 0 | const char *match = NULL; |
263 | |
|
264 | 0 | if (!path || !filename) |
265 | 0 | return MZ_PARAM_ERROR; |
266 | | |
267 | 0 | *filename = NULL; |
268 | |
|
269 | 0 | for (match = path; *match != 0; match += 1) { |
270 | 0 | if (mz_os_is_dir_separator(*match)) |
271 | 0 | *filename = match + 1; |
272 | 0 | } |
273 | |
|
274 | 0 | if (!*filename) |
275 | 0 | return MZ_EXIST_ERROR; |
276 | | |
277 | 0 | return MZ_OK; |
278 | 0 | } |
279 | | |
280 | 0 | int32_t mz_dir_make(const char *path) { |
281 | 0 | int32_t err = MZ_OK; |
282 | 0 | char *current_dir = NULL; |
283 | 0 | char *match = NULL; |
284 | 0 | char hold = 0; |
285 | |
|
286 | 0 | if (!*path) |
287 | 0 | return MZ_OK; |
288 | | |
289 | 0 | current_dir = strdup(path); |
290 | 0 | if (!current_dir) |
291 | 0 | return MZ_MEM_ERROR; |
292 | | |
293 | 0 | mz_path_remove_slash(current_dir); |
294 | |
|
295 | 0 | err = mz_os_make_dir(current_dir); |
296 | 0 | if (err != MZ_OK) { |
297 | 0 | match = current_dir + 1; |
298 | 0 | while (1) { |
299 | 0 | while (*match != 0 && !mz_os_is_dir_separator(*match)) |
300 | 0 | match += 1; |
301 | 0 | hold = *match; |
302 | 0 | *match = 0; |
303 | |
|
304 | 0 | err = mz_os_make_dir(current_dir); |
305 | 0 | if (err != MZ_OK) |
306 | 0 | break; |
307 | 0 | if (hold == 0) |
308 | 0 | break; |
309 | | |
310 | 0 | *match = hold; |
311 | 0 | match += 1; |
312 | 0 | } |
313 | 0 | } |
314 | |
|
315 | 0 | free(current_dir); |
316 | 0 | return err; |
317 | 0 | } |
318 | | |
319 | 0 | int32_t mz_file_get_crc(const char *path, uint32_t *result_crc) { |
320 | 0 | void *stream = NULL; |
321 | 0 | uint32_t crc32 = 0; |
322 | 0 | int32_t read = 0; |
323 | 0 | int32_t err = MZ_OK; |
324 | 0 | uint8_t buf[16384]; |
325 | |
|
326 | 0 | stream = mz_stream_os_create(); |
327 | 0 | if (!stream) |
328 | 0 | return MZ_MEM_ERROR; |
329 | | |
330 | 0 | err = mz_stream_os_open(stream, path, MZ_OPEN_MODE_READ); |
331 | 0 | if (err == MZ_OK) { |
332 | 0 | do { |
333 | 0 | read = mz_stream_os_read(stream, buf, sizeof(buf)); |
334 | |
|
335 | 0 | if (read < 0) { |
336 | 0 | err = read; |
337 | 0 | break; |
338 | 0 | } |
339 | | |
340 | 0 | crc32 = mz_crypt_crc32_update(crc32, buf, read); |
341 | 0 | } while ((err == MZ_OK) && (read > 0)); |
342 | | |
343 | 0 | mz_stream_os_close(stream); |
344 | 0 | } |
345 | | |
346 | 0 | *result_crc = crc32; |
347 | |
|
348 | 0 | mz_stream_os_delete(&stream); |
349 | |
|
350 | 0 | return err; |
351 | 0 | } |
352 | | |
353 | | /***************************************************************************/ |