226a5691 |
1 | /* Copyright (C) 2010-2020 The RetroArch team |
2 | * |
3 | * --------------------------------------------------------------------------------------- |
4 | * The following license statement only applies to this file (file_path.h). |
5 | * --------------------------------------------------------------------------------------- |
6 | * |
7 | * Permission is hereby granted, free of charge, |
8 | * to any person obtaining a copy of this software and associated documentation files (the "Software"), |
9 | * to deal in the Software without restriction, including without limitation the rights to |
10 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, |
11 | * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: |
12 | * |
13 | * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. |
14 | * |
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, |
16 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
18 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
19 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
21 | */ |
22 | |
23 | #ifndef __LIBRETRO_SDK_FILE_PATH_H |
24 | #define __LIBRETRO_SDK_FILE_PATH_H |
25 | |
26 | #include <stdio.h> |
27 | #include <stdint.h> |
28 | #include <stddef.h> |
29 | #include <sys/types.h> |
30 | |
31 | #include <libretro.h> |
32 | #include <retro_common_api.h> |
33 | |
34 | #include <boolean.h> |
35 | |
36 | RETRO_BEGIN_DECLS |
37 | |
38 | #define PATH_REQUIRED_VFS_VERSION 3 |
39 | |
40 | void path_vfs_init(const struct retro_vfs_interface_info* vfs_info); |
41 | |
42 | /* Order in this enum is equivalent to negative sort order in filelist |
43 | * (i.e. DIRECTORY is on top of PLAIN_FILE) */ |
44 | enum |
45 | { |
46 | RARCH_FILETYPE_UNSET, |
47 | RARCH_PLAIN_FILE, |
48 | RARCH_COMPRESSED_FILE_IN_ARCHIVE, |
49 | RARCH_COMPRESSED_ARCHIVE, |
50 | RARCH_DIRECTORY, |
51 | RARCH_FILE_UNSUPPORTED |
52 | }; |
53 | |
54 | /** |
55 | * path_is_compressed_file: |
56 | * @path : path |
57 | * |
58 | * Checks if path is a compressed file. |
59 | * |
60 | * Returns: true (1) if path is a compressed file, otherwise false (0). |
61 | **/ |
62 | bool path_is_compressed_file(const char *path); |
63 | |
64 | /** |
65 | * path_contains_compressed_file: |
66 | * @path : path |
67 | * |
68 | * Checks if path contains a compressed file. |
69 | * |
70 | * Currently we only check for hash symbol (#) inside the pathname. |
71 | * If path is ever expanded to a general URI, we should check for that here. |
72 | * |
73 | * Example: Somewhere in the path there might be a compressed file |
74 | * E.g.: /path/to/file.7z#mygame.img |
75 | * |
76 | * Returns: true (1) if path contains compressed file, otherwise false (0). |
77 | **/ |
78 | #define path_contains_compressed_file(path) (path_get_archive_delim((path)) != NULL) |
79 | |
80 | /** |
81 | * path_get_archive_delim: |
82 | * @path : path |
83 | * |
84 | * Gets delimiter of an archive file. Only the first '#' |
85 | * after a compression extension is considered. |
86 | * |
87 | * Returns: pointer to the delimiter in the path if it contains |
88 | * a compressed file, otherwise NULL. |
89 | */ |
90 | const char *path_get_archive_delim(const char *path); |
91 | |
92 | /** |
93 | * path_get_extension: |
94 | * @path : path |
95 | * |
96 | * Gets extension of file. Only '.'s |
97 | * after the last slash are considered. |
98 | * |
99 | * Returns: extension part from the path. |
100 | */ |
101 | const char *path_get_extension(const char *path); |
102 | |
103 | /** |
104 | * path_remove_extension: |
105 | * @path : path |
106 | * |
107 | * Mutates path by removing its extension. Removes all |
108 | * text after and including the last '.'. |
109 | * Only '.'s after the last slash are considered. |
110 | * |
111 | * Returns: |
112 | * 1) If path has an extension, returns path with the |
113 | * extension removed. |
114 | * 2) If there is no extension, returns NULL. |
115 | * 3) If path is empty or NULL, returns NULL |
116 | */ |
117 | char *path_remove_extension(char *path); |
118 | |
119 | /** |
120 | * path_basename: |
121 | * @path : path |
122 | * |
123 | * Get basename from @path. |
124 | * |
125 | * Returns: basename from path. |
126 | **/ |
127 | const char *path_basename(const char *path); |
128 | |
129 | /** |
130 | * path_basedir: |
131 | * @path : path |
132 | * |
133 | * Extracts base directory by mutating path. |
134 | * Keeps trailing '/'. |
135 | **/ |
136 | void path_basedir(char *path); |
137 | |
138 | /** |
139 | * path_parent_dir: |
140 | * @path : path |
141 | * |
142 | * Extracts parent directory by mutating path. |
143 | * Assumes that path is a directory. Keeps trailing '/'. |
144 | * If the path was already at the root directory, returns empty string |
145 | **/ |
146 | void path_parent_dir(char *path); |
147 | |
148 | /** |
149 | * path_resolve_realpath: |
150 | * @buf : input and output buffer for path |
151 | * @size : size of buffer |
152 | * @resolve_symlinks : whether to resolve symlinks or not |
153 | * |
154 | * Resolves use of ".", "..", multiple slashes etc in absolute paths. |
155 | * |
156 | * Relative paths are rebased on the current working dir. |
157 | * |
158 | * Returns: @buf if successful, NULL otherwise. |
159 | * Note: Not implemented on consoles |
160 | * Note: Symlinks are only resolved on Unix-likes |
161 | * Note: The current working dir might not be what you expect, |
162 | * e.g. on Android it is "/" |
163 | * Use of fill_pathname_resolve_relative() should be prefered |
164 | **/ |
165 | char *path_resolve_realpath(char *buf, size_t size, bool resolve_symlinks); |
166 | |
167 | /** |
168 | * path_relative_to: |
169 | * @out : buffer to write the relative path to |
170 | * @path : path to be expressed relatively |
171 | * @base : relative to this |
172 | * @size : size of output buffer |
173 | * |
174 | * Turns @path into a path relative to @base and writes it to @out. |
175 | * |
176 | * @base is assumed to be a base directory, i.e. a path ending with '/' or '\'. |
177 | * Both @path and @base are assumed to be absolute paths without "." or "..". |
178 | * |
179 | * E.g. path /a/b/e/f.cgp with base /a/b/c/d/ turns into ../../e/f.cgp |
180 | **/ |
181 | size_t path_relative_to(char *out, const char *path, const char *base, size_t size); |
182 | |
183 | /** |
184 | * path_is_absolute: |
185 | * @path : path |
186 | * |
187 | * Checks if @path is an absolute path or a relative path. |
188 | * |
189 | * Returns: true if path is absolute, false if path is relative. |
190 | **/ |
191 | bool path_is_absolute(const char *path); |
192 | |
193 | /** |
194 | * fill_pathname: |
195 | * @out_path : output path |
196 | * @in_path : input path |
197 | * @replace : what to replace |
198 | * @size : buffer size of output path |
199 | * |
200 | * FIXME: Verify |
201 | * |
202 | * Replaces filename extension with 'replace' and outputs result to out_path. |
203 | * The extension here is considered to be the string from the last '.' |
204 | * to the end. |
205 | * |
206 | * Only '.'s after the last slash are considered as extensions. |
207 | * If no '.' is present, in_path and replace will simply be concatenated. |
208 | * 'size' is buffer size of 'out_path'. |
209 | * E.g.: in_path = "/foo/bar/baz/boo.c", replace = ".asm" => |
210 | * out_path = "/foo/bar/baz/boo.asm" |
211 | * E.g.: in_path = "/foo/bar/baz/boo.c", replace = "" => |
212 | * out_path = "/foo/bar/baz/boo" |
213 | */ |
214 | void fill_pathname(char *out_path, const char *in_path, |
215 | const char *replace, size_t size); |
216 | |
217 | /** |
218 | * fill_dated_filename: |
219 | * @out_filename : output filename |
220 | * @ext : extension of output filename |
221 | * @size : buffer size of output filename |
222 | * |
223 | * Creates a 'dated' filename prefixed by 'RetroArch', and |
224 | * concatenates extension (@ext) to it. |
225 | * |
226 | * E.g.: |
227 | * out_filename = "RetroArch-{month}{day}-{Hours}{Minutes}.{@ext}" |
228 | **/ |
229 | size_t fill_dated_filename(char *out_filename, |
230 | const char *ext, size_t size); |
231 | |
232 | /** |
233 | * fill_str_dated_filename: |
234 | * @out_filename : output filename |
235 | * @in_str : input string |
236 | * @ext : extension of output filename |
237 | * @size : buffer size of output filename |
238 | * |
239 | * Creates a 'dated' filename prefixed by the string @in_str, and |
240 | * concatenates extension (@ext) to it. |
241 | * |
242 | * E.g.: |
243 | * out_filename = "RetroArch-{year}{month}{day}-{Hour}{Minute}{Second}.{@ext}" |
244 | **/ |
245 | void fill_str_dated_filename(char *out_filename, |
246 | const char *in_str, const char *ext, size_t size); |
247 | |
248 | /** |
249 | * fill_pathname_noext: |
250 | * @out_path : output path |
251 | * @in_path : input path |
252 | * @replace : what to replace |
253 | * @size : buffer size of output path |
254 | * |
255 | * Appends a filename extension 'replace' to 'in_path', and outputs |
256 | * result in 'out_path'. |
257 | * |
258 | * Assumes in_path has no extension. If an extension is still |
259 | * present in 'in_path', it will be ignored. |
260 | * |
261 | */ |
262 | size_t fill_pathname_noext(char *out_path, const char *in_path, |
263 | const char *replace, size_t size); |
264 | |
265 | /** |
266 | * find_last_slash: |
267 | * @str : input path |
268 | * |
269 | * Gets a pointer to the last slash in the input path. |
270 | * |
271 | * Returns: a pointer to the last slash in the input path. |
272 | **/ |
273 | char *find_last_slash(const char *str); |
274 | |
275 | /** |
276 | * fill_pathname_dir: |
277 | * @in_dir : input directory path |
278 | * @in_basename : input basename to be appended to @in_dir |
279 | * @replace : replacement to be appended to @in_basename |
280 | * @size : size of buffer |
281 | * |
282 | * Appends basename of 'in_basename', to 'in_dir', along with 'replace'. |
283 | * Basename of in_basename is the string after the last '/' or '\\', |
284 | * i.e the filename without directories. |
285 | * |
286 | * If in_basename has no '/' or '\\', the whole 'in_basename' will be used. |
287 | * 'size' is buffer size of 'in_dir'. |
288 | * |
289 | * E.g..: in_dir = "/tmp/some_dir", in_basename = "/some_content/foo.c", |
290 | * replace = ".asm" => in_dir = "/tmp/some_dir/foo.c.asm" |
291 | **/ |
292 | size_t fill_pathname_dir(char *in_dir, const char *in_basename, |
293 | const char *replace, size_t size); |
294 | |
295 | /** |
296 | * fill_pathname_base: |
297 | * @out : output path |
298 | * @in_path : input path |
299 | * @size : size of output path |
300 | * |
301 | * Copies basename of @in_path into @out_path. |
302 | **/ |
303 | size_t fill_pathname_base(char *out_path, const char *in_path, size_t size); |
304 | |
305 | void fill_pathname_base_noext(char *out_dir, |
306 | const char *in_path, size_t size); |
307 | |
308 | size_t fill_pathname_base_ext(char *out, |
309 | const char *in_path, const char *ext, |
310 | size_t size); |
311 | |
312 | /** |
313 | * fill_pathname_basedir: |
314 | * @out_dir : output directory |
315 | * @in_path : input path |
316 | * @size : size of output directory |
317 | * |
318 | * Copies base directory of @in_path into @out_path. |
319 | * If in_path is a path without any slashes (relative current directory), |
320 | * @out_path will get path "./". |
321 | **/ |
322 | void fill_pathname_basedir(char *out_path, const char *in_path, size_t size); |
323 | |
324 | void fill_pathname_basedir_noext(char *out_dir, |
325 | const char *in_path, size_t size); |
326 | |
327 | /** |
328 | * fill_pathname_parent_dir_name: |
329 | * @out_dir : output directory |
330 | * @in_dir : input directory |
331 | * @size : size of output directory |
332 | * |
333 | * Copies only the parent directory name of @in_dir into @out_dir. |
334 | * The two buffers must not overlap. Removes trailing '/'. |
335 | * Returns true on success, false if a slash was not found in the path. |
336 | **/ |
337 | bool fill_pathname_parent_dir_name(char *out_dir, |
338 | const char *in_dir, size_t size); |
339 | |
340 | /** |
341 | * fill_pathname_parent_dir: |
342 | * @out_dir : output directory |
343 | * @in_dir : input directory |
344 | * @size : size of output directory |
345 | * |
346 | * Copies parent directory of @in_dir into @out_dir. |
347 | * Assumes @in_dir is a directory. Keeps trailing '/'. |
348 | * If the path was already at the root directory, @out_dir will be an empty string. |
349 | **/ |
350 | void fill_pathname_parent_dir(char *out_dir, |
351 | const char *in_dir, size_t size); |
352 | |
353 | /** |
354 | * fill_pathname_resolve_relative: |
355 | * @out_path : output path |
356 | * @in_refpath : input reference path |
357 | * @in_path : input path |
358 | * @size : size of @out_path |
359 | * |
360 | * Joins basedir of @in_refpath together with @in_path. |
361 | * If @in_path is an absolute path, out_path = in_path. |
362 | * E.g.: in_refpath = "/foo/bar/baz.a", in_path = "foobar.cg", |
363 | * out_path = "/foo/bar/foobar.cg". |
364 | **/ |
365 | void fill_pathname_resolve_relative(char *out_path, const char *in_refpath, |
366 | const char *in_path, size_t size); |
367 | |
368 | /** |
369 | * fill_pathname_join: |
370 | * @out_path : output path |
371 | * @dir : directory |
372 | * @path : path |
373 | * @size : size of output path |
374 | * |
375 | * Joins a directory (@dir) and path (@path) together. |
376 | * Makes sure not to get two consecutive slashes |
377 | * between directory and path. |
378 | **/ |
379 | size_t fill_pathname_join(char *out_path, const char *dir, |
380 | const char *path, size_t size); |
381 | |
382 | size_t fill_pathname_join_special_ext(char *out_path, |
383 | const char *dir, const char *path, |
384 | const char *last, const char *ext, |
385 | size_t size); |
386 | |
387 | size_t fill_pathname_join_concat_noext(char *out_path, |
388 | const char *dir, const char *path, |
389 | const char *concat, |
390 | size_t size); |
391 | |
392 | size_t fill_pathname_join_concat(char *out_path, |
393 | const char *dir, const char *path, |
394 | const char *concat, |
395 | size_t size); |
396 | |
397 | void fill_pathname_join_noext(char *out_path, |
398 | const char *dir, const char *path, size_t size); |
399 | |
400 | /** |
401 | * fill_pathname_join_delim: |
402 | * @out_path : output path |
403 | * @dir : directory |
404 | * @path : path |
405 | * @delim : delimiter |
406 | * @size : size of output path |
407 | * |
408 | * Joins a directory (@dir) and path (@path) together |
409 | * using the given delimiter (@delim). |
410 | **/ |
411 | size_t fill_pathname_join_delim(char *out_path, const char *dir, |
412 | const char *path, const char delim, size_t size); |
413 | |
414 | size_t fill_pathname_join_delim_concat(char *out_path, const char *dir, |
415 | const char *path, const char delim, const char *concat, |
416 | size_t size); |
417 | |
418 | /** |
419 | * fill_short_pathname_representation: |
420 | * @out_rep : output representation |
421 | * @in_path : input path |
422 | * @size : size of output representation |
423 | * |
424 | * Generates a short representation of path. It should only |
425 | * be used for displaying the result; the output representation is not |
426 | * binding in any meaningful way (for a normal path, this is the same as basename) |
427 | * In case of more complex URLs, this should cut everything except for |
428 | * the main image file. |
429 | * |
430 | * E.g.: "/path/to/game.img" -> game.img |
431 | * "/path/to/myarchive.7z#folder/to/game.img" -> game.img |
432 | */ |
433 | size_t fill_short_pathname_representation(char* out_rep, |
434 | const char *in_path, size_t size); |
435 | |
436 | void fill_short_pathname_representation_noext(char* out_rep, |
437 | const char *in_path, size_t size); |
438 | |
439 | void fill_pathname_expand_special(char *out_path, |
440 | const char *in_path, size_t size); |
441 | |
442 | void fill_pathname_abbreviate_special(char *out_path, |
443 | const char *in_path, size_t size); |
444 | |
445 | /** |
446 | * path_basedir: |
447 | * @path : path |
448 | * |
449 | * Extracts base directory by mutating path. |
450 | * Keeps trailing '/'. |
451 | **/ |
452 | void path_basedir_wrapper(char *path); |
453 | |
454 | /** |
455 | * path_char_is_slash: |
456 | * @c : character |
457 | * |
458 | * Checks if character (@c) is a slash. |
459 | * |
460 | * Returns: true (1) if character is a slash, otherwise false (0). |
461 | */ |
462 | #ifdef _WIN32 |
463 | #define PATH_CHAR_IS_SLASH(c) (((c) == '/') || ((c) == '\\')) |
464 | #else |
465 | #define PATH_CHAR_IS_SLASH(c) ((c) == '/') |
466 | #endif |
467 | |
468 | /** |
469 | * path_default_slash and path_default_slash_c: |
470 | * |
471 | * Gets the default slash separator. |
472 | * |
473 | * Returns: default slash separator. |
474 | */ |
475 | #ifdef _WIN32 |
476 | #define PATH_DEFAULT_SLASH() "\\" |
477 | #define PATH_DEFAULT_SLASH_C() '\\' |
478 | #else |
479 | #define PATH_DEFAULT_SLASH() "/" |
480 | #define PATH_DEFAULT_SLASH_C() '/' |
481 | #endif |
482 | |
483 | /** |
484 | * fill_pathname_slash: |
485 | * @path : path |
486 | * @size : size of path |
487 | * |
488 | * Assumes path is a directory. Appends a slash |
489 | * if not already there. |
490 | **/ |
491 | void fill_pathname_slash(char *path, size_t size); |
492 | |
493 | #if !defined(RARCH_CONSOLE) && defined(RARCH_INTERNAL) |
494 | void fill_pathname_application_path(char *buf, size_t size); |
495 | void fill_pathname_application_dir(char *buf, size_t size); |
496 | void fill_pathname_home_dir(char *buf, size_t size); |
497 | #endif |
498 | |
499 | /** |
500 | * path_mkdir: |
501 | * @dir : directory |
502 | * |
503 | * Create directory on filesystem. |
504 | * |
505 | * Returns: true (1) if directory could be created, otherwise false (0). |
506 | **/ |
507 | bool path_mkdir(const char *dir); |
508 | |
509 | /** |
510 | * path_is_directory: |
511 | * @path : path |
512 | * |
513 | * Checks if path is a directory. |
514 | * |
515 | * Returns: true (1) if path is a directory, otherwise false (0). |
516 | */ |
517 | bool path_is_directory(const char *path); |
518 | |
519 | bool path_is_character_special(const char *path); |
520 | |
521 | int path_stat(const char *path); |
522 | |
523 | bool path_is_valid(const char *path); |
524 | |
525 | int32_t path_get_size(const char *path); |
526 | |
527 | bool is_path_accessible_using_standard_io(const char *path); |
528 | |
529 | RETRO_END_DECLS |
530 | |
531 | #endif |