git subrepo pull --force deps/lightrec
[pcsx_rearmed.git] / deps / libretro-common / include / file / file_path.h
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 struct path_linked_list
55 {
56    char *path;
57    struct path_linked_list *next;
58 };
59
60 /**
61  * Create a new linked list with one item in it
62  * The path on this item will be set to NULL
63 **/
64 struct path_linked_list* path_linked_list_new(void);
65
66 /* Free the entire linked list */
67 void path_linked_list_free(struct path_linked_list *in_path_linked_list);
68
69 /**
70  * Add a node to the linked list with this path
71  * If the first node's path if it's not yet set, 
72  * set this instead
73 **/
74 void path_linked_list_add_path(struct path_linked_list *in_path_linked_list, char *path);
75
76 /**
77  * path_is_compressed_file:
78  * @path               : path
79  *
80  * Checks if path is a compressed file.
81  *
82  * Returns: true (1) if path is a compressed file, otherwise false (0).
83  **/
84 bool path_is_compressed_file(const char *path);
85
86 /**
87  * path_contains_compressed_file:
88  * @path               : path
89  *
90  * Checks if path contains a compressed file.
91  *
92  * Currently we only check for hash symbol (#) inside the pathname.
93  * If path is ever expanded to a general URI, we should check for that here.
94  *
95  * Example:  Somewhere in the path there might be a compressed file
96  * E.g.: /path/to/file.7z#mygame.img
97  *
98  * Returns: true (1) if path contains compressed file, otherwise false (0).
99  **/
100 #define path_contains_compressed_file(path) (path_get_archive_delim((path)) != NULL)
101
102 /**
103  * path_get_archive_delim:
104  * @path               : path
105  *
106  * Find delimiter of an archive file. Only the first '#'
107  * after a compression extension is considered.
108  *
109  * @return pointer to the delimiter in the path if it contains
110  * a path inside a compressed file, otherwise NULL.
111  **/
112 const char *path_get_archive_delim(const char *path);
113
114 /**
115  * path_get_extension:
116  * @path               : path
117  *
118  * Gets extension of file. Only '.'s
119  * after the last slash are considered.
120  *
121  * Hidden non-leaf function cost:
122  * - calls string_is_empty()
123  * - calls strrchr
124  *
125  * @return extension part from the path.
126  **/
127 const char *path_get_extension(const char *path);
128
129 /**
130  * path_get_extension_mutable:
131  * @path               : path
132  *
133  * Specialized version of path_get_extension(). Return
134  * value is mutable.
135  *
136  * Gets extension of file. Only '.'s
137  * after the last slash are considered.
138  *
139  * @return extension part from the path.
140  **/
141 char *path_get_extension_mutable(const char *path);
142
143 /**
144  * path_remove_extension:
145  * @path               : path
146  *
147  * Mutates path by removing its extension. Removes all
148  * text after and including the last '.'.
149  * Only '.'s after the last slash are considered.
150  *
151  * Hidden non-leaf function cost:
152  * - calls strrchr
153  *
154  * @return
155  * 1) If path has an extension, returns path with the
156  *    extension removed.
157  * 2) If there is no extension, returns NULL.
158  * 3) If path is empty or NULL, returns NULL
159  */
160 char *path_remove_extension(char *path);
161
162 /**
163  * path_basename:
164  * @path               : path
165  *
166  * Get basename from @path.
167  *
168  * Hidden non-leaf function cost:
169  * - Calls path_get_archive_delim()
170  *   - can call find_last_slash() once if it returns NULL
171  *
172  * @return basename from path.
173  **/
174 const char *path_basename(const char *path);
175
176 /**
177  * path_basename_nocompression:
178  * @path               : path
179  *
180  * Specialized version of path_basename().
181  * Get basename from @path.
182  *
183  * Hidden non-leaf function cost:
184  * - Calls find_last_slash()
185  *
186  * @return basename from path.
187  **/
188 const char *path_basename_nocompression(const char *path);
189
190 /**
191  * path_basedir:
192  * @path               : path
193  *
194  * Extracts base directory by mutating path.
195  * Keeps trailing '/'.
196  **/
197 void path_basedir(char *path);
198
199 /**
200  * path_parent_dir:
201  * @path               : path
202  * @len                : length of @path
203  *
204  * Extracts parent directory by mutating path.
205  * Assumes that path is a directory. Keeps trailing '/'.
206  * If the path was already at the root directory, returns empty string
207  **/
208 void path_parent_dir(char *path, size_t len);
209
210 /**
211  * path_resolve_realpath:
212  * @buf                : input and output buffer for path
213  * @size               : size of buffer
214  * @resolve_symlinks   : whether to resolve symlinks or not
215  *
216  * Resolves use of ".", "..", multiple slashes etc in absolute paths.
217  *
218  * Relative paths are rebased on the current working dir.
219  *
220  * @return @buf if successful, NULL otherwise.
221  * Note: Not implemented on consoles
222  * Note: Symlinks are only resolved on Unix-likes
223  * Note: The current working dir might not be what you expect,
224  *       e.g. on Android it is "/"
225  *       Use of fill_pathname_resolve_relative() should be prefered
226  **/
227 char *path_resolve_realpath(char *buf, size_t size, bool resolve_symlinks);
228
229 /**
230  * path_relative_to:
231  * @out                : buffer to write the relative path to
232  * @path               : path to be expressed relatively
233  * @base               : relative to this
234  * @size               : size of output buffer
235  *
236  * Turns @path into a path relative to @base and writes it to @out.
237  *
238  * @base is assumed to be a base directory, i.e. a path ending with '/' or '\'.
239  * Both @path and @base are assumed to be absolute paths without "." or "..".
240  *
241  * E.g. path /a/b/e/f.cgp with base /a/b/c/d/ turns into ../../e/f.cgp
242  *
243  * @return Length of the string copied into @out
244  **/
245 size_t path_relative_to(char *out, const char *path, const char *base,
246       size_t size);
247
248 /**
249  * path_is_absolute:
250  * @path               : path
251  *
252  * Checks if @path is an absolute path or a relative path.
253  *
254  * @return true if path is absolute, false if path is relative.
255  **/
256 bool path_is_absolute(const char *path);
257
258 /**
259  * fill_pathname:
260  * @out_path           : output path
261  * @in_path            : input  path
262  * @replace            : what to replace
263  * @size               : buffer size of output path
264  *
265  * FIXME: Verify
266  *
267  * Replaces filename extension with 'replace' and outputs result to out_path.
268  * The extension here is considered to be the string from the last '.'
269  * to the end.
270  *
271  * Only '.'s after the last slash are considered as extensions.
272  * If no '.' is present, in_path and replace will simply be concatenated.
273  * 'size' is buffer size of 'out_path'.
274  * E.g.: in_path = "/foo/bar/baz/boo.c", replace = ".asm" =>
275  * out_path = "/foo/bar/baz/boo.asm"
276  * E.g.: in_path = "/foo/bar/baz/boo.c", replace = ""     =>
277  * out_path = "/foo/bar/baz/boo"
278  *
279  * Hidden non-leaf function cost:
280  * - calls strlcpy 2x
281  * - calls strrchr
282  * - calls strlcat
283  *
284  * @return Length of the string copied into @out
285  */
286 size_t fill_pathname(char *out_path, const char *in_path,
287       const char *replace, size_t size);
288
289 /**
290  * fill_dated_filename:
291  * @out_filename       : output filename
292  * @ext                : extension of output filename
293  * @size               : buffer size of output filename
294  *
295  * Creates a 'dated' filename prefixed by 'RetroArch', and
296  * concatenates extension (@ext) to it.
297  *
298  * E.g.:
299  * out_filename = "RetroArch-{month}{day}-{Hours}{Minutes}.{@ext}"
300  *
301  * Hidden non-leaf function cost:
302  * - Calls rtime_localtime()
303  * - Calls strftime
304  * - Calls strlcat
305  *
306  **/
307 size_t fill_dated_filename(char *out_filename,
308       const char *ext, size_t size);
309
310 /**
311  * fill_str_dated_filename:
312  * @out_filename       : output filename
313  * @in_str             : input string
314  * @ext                : extension of output filename
315  * @size               : buffer size of output filename
316  *
317  * Creates a 'dated' filename prefixed by the string @in_str, and
318  * concatenates extension (@ext) to it.
319  *
320  * E.g.:
321  * out_filename = "RetroArch-{year}{month}{day}-{Hour}{Minute}{Second}.{@ext}"
322  *
323  * Hidden non-leaf function cost:
324  * - Calls time
325  * - Calls rtime_localtime()
326  * - Calls strlcpy
327  * - Calls string_is_empty()
328  * - Calls strftime
329  * - Calls strlcat at least 2x
330  *
331  * @return Length of the string copied into @out_path
332  **/
333 size_t fill_str_dated_filename(char *out_filename,
334       const char *in_str, const char *ext, size_t size);
335
336 /**
337  * find_last_slash:
338  * @str                : path
339  * @size               : size of path
340  *
341  * Find last slash in path. Tries to find
342  * a backslash on Windows too which takes precedence
343  * over regular slash.
344
345  * Hidden non-leaf function cost: 
346  * - calls strrchr
347  *
348  * @return pointer to last slash/backslash found in @str.
349  **/
350 char *find_last_slash(const char *str);
351
352 /**
353  * fill_pathname_dir:
354  * @in_dir             : input directory path
355  * @in_basename        : input basename to be appended to @in_dir
356  * @replace            : replacement to be appended to @in_basename
357  * @size               : size of buffer
358  *
359  * Appends basename of 'in_basename', to 'in_dir', along with 'replace'.
360  * Basename of in_basename is the string after the last '/' or '\\',
361  * i.e the filename without directories.
362  *
363  * If in_basename has no '/' or '\\', the whole 'in_basename' will be used.
364  * 'size' is buffer size of 'in_dir'.
365  *
366  * E.g..: in_dir = "/tmp/some_dir", in_basename = "/some_content/foo.c",
367  * replace = ".asm" => in_dir = "/tmp/some_dir/foo.c.asm"
368  *
369  * Hidden non-leaf function cost:
370  * - Calls fill_pathname_slash()
371  * - Calls path_basename()
372  * - Calls strlcat 2x
373  **/
374 size_t fill_pathname_dir(char *in_dir, const char *in_basename,
375       const char *replace, size_t size);
376
377 /**
378  * fill_pathname_base:
379  * @out                : output path
380  * @in_path            : input path
381  * @size               : size of output path
382  *
383  * Copies basename of @in_path into @out_path.
384  *
385  * Hidden non-leaf function cost:
386  * - Calls path_basename()
387  * - Calls strlcpy
388  *
389  * @return length of the string copied into @out
390  **/
391 size_t fill_pathname_base(char *out_path, const char *in_path, size_t size);
392
393 /**
394  * fill_pathname_basedir:
395  * @out_dir            : output directory
396  * @in_path            : input path
397  * @size               : size of output directory
398  *
399  * Copies base directory of @in_path into @out_path.
400  * If in_path is a path without any slashes (relative current directory),
401  * @out_path will get path "./".
402  *
403  * Hidden non-leaf function cost:
404  * - Calls strlcpy
405  * - Calls path_basedir()
406  **/
407 void fill_pathname_basedir(char *out_path, const char *in_path, size_t size);
408
409 /**
410  * fill_pathname_parent_dir_name:
411  * @out_dir            : output directory
412  * @in_dir             : input directory
413  * @size               : size of output directory
414  *
415  * Copies only the parent directory name of @in_dir into @out_dir.
416  * The two buffers must not overlap. Removes trailing '/'.
417  *
418  * Hidden non-leaf function cost:
419  * - Calls strdup
420  * - Calls find_last_slash() x times
421  * - Can call strlcpy
422  *
423  * @return true on success, false if a slash was not found in the path.
424  **/
425 bool fill_pathname_parent_dir_name(char *out_dir,
426       const char *in_dir, size_t size);
427
428 /**
429  * fill_pathname_parent_dir:
430  * @out_dir            : output directory
431  * @in_dir             : input directory
432  * @size               : size of output directory
433  *
434  * Copies parent directory of @in_dir into @out_dir.
435  * Assumes @in_dir is a directory. Keeps trailing '/'.
436  * If the path was already at the root directory, @out_dir will be an empty string.
437  *
438  * Hidden non-leaf function cost:
439  * - Can call strlcpy if (@out_dir != @in_dir)
440  * - Calls strlen if (@out_dir == @in_dir)
441  * - Calls path_parent_dir()
442  **/
443 void fill_pathname_parent_dir(char *out_dir,
444       const char *in_dir, size_t size);
445
446 /**
447  * fill_pathname_resolve_relative:
448  * @out_path           : output path
449  * @in_refpath         : input reference path
450  * @in_path            : input path
451  * @size               : size of @out_path
452  *
453  * Joins basedir of @in_refpath together with @in_path.
454  * If @in_path is an absolute path, out_path = in_path.
455  * E.g.: in_refpath = "/foo/bar/baz.a", in_path = "foobar.cg",
456  * out_path = "/foo/bar/foobar.cg".
457  **/
458 void fill_pathname_resolve_relative(char *out_path, const char *in_refpath,
459       const char *in_path, size_t size);
460
461 /**
462  * fill_pathname_join:
463  * @out_path           : output path
464  * @dir                : directory
465  * @path               : path
466  * @size               : size of output path
467  *
468  * Joins a directory (@dir) and path (@path) together.
469  * Makes sure not to get two consecutive slashes
470  * between directory and path.
471  * 
472  * Hidden non-leaf function cost: 
473  * - calls strlcpy
474  * - calls fill_pathname_slash()
475  * - calls strlcat
476  *
477  * Deprecated. Use fill_pathname_join_special() instead
478  * if you can ensure @dir != @out_path
479  *
480  * @return Length of the string copied into @out_path
481  **/
482 size_t fill_pathname_join(char *out_path, const char *dir,
483       const char *path, size_t size);
484
485 /**
486  * fill_pathname_join_special:
487  * @out_path           : output path
488  * @dir                : directory. Cannot be identical to @out_path
489  * @path               : path
490  * @size               : size of output path
491  *
492  *
493  * Specialized version of fill_pathname_join.
494  * Unlike fill_pathname_join(),
495  * @dir and @out_path CANNOT be identical.
496  *
497  * Joins a directory (@dir) and path (@path) together.
498  * Makes sure not to get two consecutive slashes
499  * between directory and path.
500  *
501  * Hidden non-leaf function cost: 
502  * - calls strlcpy
503  * - calls find_last_slash()
504  * - calls strlcat
505  *
506  * @return Length of the string copied into @out_path
507  **/
508 size_t fill_pathname_join_special(char *out_path,
509       const char *dir, const char *path, size_t size);
510
511 size_t fill_pathname_join_special_ext(char *out_path,
512       const char *dir,  const char *path,
513       const char *last, const char *ext,
514       size_t size);
515
516 /**
517  * fill_pathname_join_delim:
518  * @out_path           : output path
519  * @dir                : directory
520  * @path               : path
521  * @delim              : delimiter
522  * @size               : size of output path
523  *
524  * Joins a directory (@dir) and path (@path) together
525  * using the given delimiter (@delim).
526  *
527  * Hidden non-leaf function cost: 
528  * - can call strlen
529  * - can call strlcpy
530  * - can call strlcat
531  **/
532 size_t fill_pathname_join_delim(char *out_path, const char *dir,
533       const char *path, const char delim, size_t size);
534
535 size_t fill_pathname_expand_special(char *out_path,
536       const char *in_path, size_t size);
537
538 size_t fill_pathname_abbreviate_special(char *out_path,
539       const char *in_path, size_t size);
540
541 /**
542  * fill_pathname_abbreviated_or_relative:
543  *
544  * Fills the supplied path with either the abbreviated path or 
545  * the relative path, which ever one has less depth / number of slashes
546  * 
547  * If lengths of abbreviated and relative paths are the same,
548  * the relative path will be used
549  * @in_path can be an absolute, relative or abbreviated path
550  *
551  * @return Length of the string copied into @out_path
552  **/
553 size_t fill_pathname_abbreviated_or_relative(char *out_path,
554                 const char *in_refpath, const char *in_path, size_t size);
555
556 /**
557  * pathname_conform_slashes_to_os:
558  *
559  * @path               : path
560  * 
561  * Leaf function.
562  *
563  * Changes the slashes to the correct kind for the os 
564  * So forward slash on linux and backslash on Windows
565  **/
566 void pathname_conform_slashes_to_os(char *path);
567
568 /**
569  * pathname_make_slashes_portable:
570  * @path               : path
571  *
572  * Leaf function.
573  *
574  * Change all slashes to forward so they are more 
575  * portable between Windows and Linux
576  **/
577 void pathname_make_slashes_portable(char *path);
578
579 /**
580  * path_basedir:
581  * @path               : path
582  *
583  * Extracts base directory by mutating path.
584  * Keeps trailing '/'.
585  **/
586 void path_basedir_wrapper(char *path);
587
588 /**
589  * path_char_is_slash:
590  * @c                  : character
591  *
592  * Checks if character (@c) is a slash.
593  *
594  * @return true if character is a slash, otherwise false.
595  **/
596 #ifdef _WIN32
597 #define PATH_CHAR_IS_SLASH(c) (((c) == '/') || ((c) == '\\'))
598 #else
599 #define PATH_CHAR_IS_SLASH(c) ((c) == '/')
600 #endif
601
602 /**
603  * path_default_slash and path_default_slash_c:
604  *
605  * Gets the default slash separator.
606  *
607  * @return default slash separator.
608  **/
609 #ifdef _WIN32
610 #define PATH_DEFAULT_SLASH() "\\"
611 #define PATH_DEFAULT_SLASH_C() '\\'
612 #else
613 #define PATH_DEFAULT_SLASH() "/"
614 #define PATH_DEFAULT_SLASH_C() '/'
615 #endif
616
617 /**
618  * fill_pathname_slash:
619  * @path               : path
620  * @size               : size of path
621  *
622  * Assumes path is a directory. Appends a slash
623  * if not already there.
624
625  * Hidden non-leaf function cost: 
626  * - calls find_last_slash()
627  *   - can call strlcat once if it returns false
628  * - calls strlen
629  **/
630 void fill_pathname_slash(char *path, size_t size);
631
632 #if !defined(RARCH_CONSOLE) && defined(RARCH_INTERNAL)
633 void fill_pathname_application_path(char *buf, size_t size);
634 void fill_pathname_application_dir(char *buf, size_t size);
635 void fill_pathname_home_dir(char *buf, size_t size);
636 #endif
637
638 /**
639  * path_mkdir:
640  * @dir                : directory
641  *
642  * Create directory on filesystem.
643  *
644  * Recursive function.
645  *
646  * Hidden non-leaf function cost:
647  * - Calls strdup
648  * - Calls path_parent_dir()
649  * - Calls strcmp
650  * - Calls path_is_directory()
651  * - Calls path_mkdir()
652  *
653  * @return true if directory could be created, otherwise false.
654  **/
655 bool path_mkdir(const char *dir);
656
657 /**
658  * path_is_directory:
659  * @path               : path
660  *
661  * Checks if path is a directory.
662  *
663  * @return true if path is a directory, otherwise false.
664  */
665 bool path_is_directory(const char *path);
666
667 /* Time format strings with AM-PM designation require special
668  * handling due to platform dependence */
669 void strftime_am_pm(char *s, size_t len, const char* format,
670       const void* timeptr);
671
672 bool path_is_character_special(const char *path);
673
674 int path_stat(const char *path);
675
676 bool path_is_valid(const char *path);
677
678 int32_t path_get_size(const char *path);
679
680 bool is_path_accessible_using_standard_io(const char *path);
681
682 RETRO_END_DECLS
683
684 #endif