1 /* Copyright (C) 2010-2020 The RetroArch team
3 * ---------------------------------------------------------------------------------------
4 * The following license statement only applies to this file (file_path.h).
5 * ---------------------------------------------------------------------------------------
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:
13 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
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.
23 #ifndef __LIBRETRO_SDK_FILE_PATH_H
24 #define __LIBRETRO_SDK_FILE_PATH_H
29 #include <sys/types.h>
32 #include <retro_common_api.h>
38 #define PATH_REQUIRED_VFS_VERSION 3
40 void path_vfs_init(const struct retro_vfs_interface_info* vfs_info);
42 /* Order in this enum is equivalent to negative sort order in filelist
43 * (i.e. DIRECTORY is on top of PLAIN_FILE) */
48 RARCH_COMPRESSED_FILE_IN_ARCHIVE,
49 RARCH_COMPRESSED_ARCHIVE,
51 RARCH_FILE_UNSUPPORTED
54 struct path_linked_list
57 struct path_linked_list *next;
61 * Create a new linked list with one item in it
62 * The path on this item will be set to NULL
64 struct path_linked_list* path_linked_list_new(void);
66 /* Free the entire linked list */
67 void path_linked_list_free(struct path_linked_list *in_path_linked_list);
70 * Add a node to the linked list with this path
71 * If the first node's path if it's not yet set,
74 void path_linked_list_add_path(struct path_linked_list *in_path_linked_list, char *path);
77 * path_is_compressed_file:
80 * Checks if path is a compressed file.
82 * Returns: true (1) if path is a compressed file, otherwise false (0).
84 bool path_is_compressed_file(const char *path);
87 * path_contains_compressed_file:
90 * Checks if path contains a compressed file.
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.
95 * Example: Somewhere in the path there might be a compressed file
96 * E.g.: /path/to/file.7z#mygame.img
98 * Returns: true (1) if path contains compressed file, otherwise false (0).
100 #define path_contains_compressed_file(path) (path_get_archive_delim((path)) != NULL)
103 * path_get_archive_delim:
106 * Find delimiter of an archive file. Only the first '#'
107 * after a compression extension is considered.
109 * @return pointer to the delimiter in the path if it contains
110 * a path inside a compressed file, otherwise NULL.
112 const char *path_get_archive_delim(const char *path);
115 * path_get_extension:
118 * Gets extension of file. Only '.'s
119 * after the last slash are considered.
121 * Hidden non-leaf function cost:
122 * - calls string_is_empty()
125 * @return extension part from the path.
127 const char *path_get_extension(const char *path);
130 * path_get_extension_mutable:
133 * Specialized version of path_get_extension(). Return
136 * Gets extension of file. Only '.'s
137 * after the last slash are considered.
139 * @return extension part from the path.
141 char *path_get_extension_mutable(const char *path);
144 * path_remove_extension:
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.
151 * Hidden non-leaf function cost:
155 * 1) If path has an extension, returns path with the
157 * 2) If there is no extension, returns NULL.
158 * 3) If path is empty or NULL, returns NULL
160 char *path_remove_extension(char *path);
166 * Get basename from @path.
168 * Hidden non-leaf function cost:
169 * - Calls path_get_archive_delim()
170 * - can call find_last_slash() once if it returns NULL
172 * @return basename from path.
174 const char *path_basename(const char *path);
177 * path_basename_nocompression:
180 * Specialized version of path_basename().
181 * Get basename from @path.
183 * Hidden non-leaf function cost:
184 * - Calls find_last_slash()
186 * @return basename from path.
188 const char *path_basename_nocompression(const char *path);
194 * Extracts base directory by mutating path.
195 * Keeps trailing '/'.
197 void path_basedir(char *path);
202 * @len : length of @path
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
208 void path_parent_dir(char *path, size_t len);
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
216 * Resolves use of ".", "..", multiple slashes etc in absolute paths.
218 * Relative paths are rebased on the current working dir.
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
227 char *path_resolve_realpath(char *buf, size_t size, bool resolve_symlinks);
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
236 * Turns @path into a path relative to @base and writes it to @out.
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 "..".
241 * E.g. path /a/b/e/f.cgp with base /a/b/c/d/ turns into ../../e/f.cgp
243 * @return Length of the string copied into @out
245 size_t path_relative_to(char *out, const char *path, const char *base,
252 * Checks if @path is an absolute path or a relative path.
254 * @return true if path is absolute, false if path is relative.
256 bool path_is_absolute(const char *path);
260 * @out_path : output path
261 * @in_path : input path
262 * @replace : what to replace
263 * @size : buffer size of output path
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 '.'
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"
279 * Hidden non-leaf function cost:
284 * @return Length of the string copied into @out
286 size_t fill_pathname(char *out_path, const char *in_path,
287 const char *replace, size_t size);
290 * fill_dated_filename:
291 * @out_filename : output filename
292 * @ext : extension of output filename
293 * @size : buffer size of output filename
295 * Creates a 'dated' filename prefixed by 'RetroArch', and
296 * concatenates extension (@ext) to it.
299 * out_filename = "RetroArch-{month}{day}-{Hours}{Minutes}.{@ext}"
301 * Hidden non-leaf function cost:
302 * - Calls rtime_localtime()
307 size_t fill_dated_filename(char *out_filename,
308 const char *ext, size_t size);
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
317 * Creates a 'dated' filename prefixed by the string @in_str, and
318 * concatenates extension (@ext) to it.
321 * out_filename = "RetroArch-{year}{month}{day}-{Hour}{Minute}{Second}.{@ext}"
323 * Hidden non-leaf function cost:
325 * - Calls rtime_localtime()
327 * - Calls string_is_empty()
329 * - Calls strlcat at least 2x
331 * @return Length of the string copied into @out_path
333 size_t fill_str_dated_filename(char *out_filename,
334 const char *in_str, const char *ext, size_t size);
339 * @size : size of path
341 * Find last slash in path. Tries to find
342 * a backslash on Windows too which takes precedence
343 * over regular slash.
345 * Hidden non-leaf function cost:
348 * @return pointer to last slash/backslash found in @str.
350 char *find_last_slash(const char *str);
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
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.
363 * If in_basename has no '/' or '\\', the whole 'in_basename' will be used.
364 * 'size' is buffer size of 'in_dir'.
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"
369 * Hidden non-leaf function cost:
370 * - Calls fill_pathname_slash()
371 * - Calls path_basename()
374 size_t fill_pathname_dir(char *in_dir, const char *in_basename,
375 const char *replace, size_t size);
378 * fill_pathname_base:
380 * @in_path : input path
381 * @size : size of output path
383 * Copies basename of @in_path into @out_path.
385 * Hidden non-leaf function cost:
386 * - Calls path_basename()
389 * @return length of the string copied into @out
391 size_t fill_pathname_base(char *out_path, const char *in_path, size_t size);
394 * fill_pathname_basedir:
395 * @out_dir : output directory
396 * @in_path : input path
397 * @size : size of output directory
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 "./".
403 * Hidden non-leaf function cost:
405 * - Calls path_basedir()
407 void fill_pathname_basedir(char *out_path, const char *in_path, size_t size);
410 * fill_pathname_parent_dir_name:
411 * @out_dir : output directory
412 * @in_dir : input directory
413 * @size : size of output directory
415 * Copies only the parent directory name of @in_dir into @out_dir.
416 * The two buffers must not overlap. Removes trailing '/'.
418 * Hidden non-leaf function cost:
420 * - Calls find_last_slash() x times
423 * @return true on success, false if a slash was not found in the path.
425 bool fill_pathname_parent_dir_name(char *out_dir,
426 const char *in_dir, size_t size);
429 * fill_pathname_parent_dir:
430 * @out_dir : output directory
431 * @in_dir : input directory
432 * @size : size of output directory
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.
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()
443 void fill_pathname_parent_dir(char *out_dir,
444 const char *in_dir, size_t size);
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
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".
458 void fill_pathname_resolve_relative(char *out_path, const char *in_refpath,
459 const char *in_path, size_t size);
462 * fill_pathname_join:
463 * @out_path : output path
466 * @size : size of output path
468 * Joins a directory (@dir) and path (@path) together.
469 * Makes sure not to get two consecutive slashes
470 * between directory and path.
472 * Hidden non-leaf function cost:
474 * - calls fill_pathname_slash()
477 * Deprecated. Use fill_pathname_join_special() instead
478 * if you can ensure @dir != @out_path
480 * @return Length of the string copied into @out_path
482 size_t fill_pathname_join(char *out_path, const char *dir,
483 const char *path, size_t size);
486 * fill_pathname_join_special:
487 * @out_path : output path
488 * @dir : directory. Cannot be identical to @out_path
490 * @size : size of output path
493 * Specialized version of fill_pathname_join.
494 * Unlike fill_pathname_join(),
495 * @dir and @out_path CANNOT be identical.
497 * Joins a directory (@dir) and path (@path) together.
498 * Makes sure not to get two consecutive slashes
499 * between directory and path.
501 * Hidden non-leaf function cost:
503 * - calls find_last_slash()
506 * @return Length of the string copied into @out_path
508 size_t fill_pathname_join_special(char *out_path,
509 const char *dir, const char *path, size_t size);
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,
517 * fill_pathname_join_delim:
518 * @out_path : output path
522 * @size : size of output path
524 * Joins a directory (@dir) and path (@path) together
525 * using the given delimiter (@delim).
527 * Hidden non-leaf function cost:
532 size_t fill_pathname_join_delim(char *out_path, const char *dir,
533 const char *path, const char delim, size_t size);
535 size_t fill_pathname_expand_special(char *out_path,
536 const char *in_path, size_t size);
538 size_t fill_pathname_abbreviate_special(char *out_path,
539 const char *in_path, size_t size);
542 * fill_pathname_abbreviated_or_relative:
544 * Fills the supplied path with either the abbreviated path or
545 * the relative path, which ever one has less depth / number of slashes
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
551 * @return Length of the string copied into @out_path
553 size_t fill_pathname_abbreviated_or_relative(char *out_path,
554 const char *in_refpath, const char *in_path, size_t size);
557 * pathname_conform_slashes_to_os:
563 * Changes the slashes to the correct kind for the os
564 * So forward slash on linux and backslash on Windows
566 void pathname_conform_slashes_to_os(char *path);
569 * pathname_make_slashes_portable:
574 * Change all slashes to forward so they are more
575 * portable between Windows and Linux
577 void pathname_make_slashes_portable(char *path);
583 * Extracts base directory by mutating path.
584 * Keeps trailing '/'.
586 void path_basedir_wrapper(char *path);
589 * path_char_is_slash:
592 * Checks if character (@c) is a slash.
594 * @return true if character is a slash, otherwise false.
597 #define PATH_CHAR_IS_SLASH(c) (((c) == '/') || ((c) == '\\'))
599 #define PATH_CHAR_IS_SLASH(c) ((c) == '/')
603 * path_default_slash and path_default_slash_c:
605 * Gets the default slash separator.
607 * @return default slash separator.
610 #define PATH_DEFAULT_SLASH() "\\"
611 #define PATH_DEFAULT_SLASH_C() '\\'
613 #define PATH_DEFAULT_SLASH() "/"
614 #define PATH_DEFAULT_SLASH_C() '/'
618 * fill_pathname_slash:
620 * @size : size of path
622 * Assumes path is a directory. Appends a slash
623 * if not already there.
625 * Hidden non-leaf function cost:
626 * - calls find_last_slash()
627 * - can call strlcat once if it returns false
630 void fill_pathname_slash(char *path, size_t size);
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);
642 * Create directory on filesystem.
644 * Recursive function.
646 * Hidden non-leaf function cost:
648 * - Calls path_parent_dir()
650 * - Calls path_is_directory()
651 * - Calls path_mkdir()
653 * @return true if directory could be created, otherwise false.
655 bool path_mkdir(const char *dir);
661 * Checks if path is a directory.
663 * @return true if path is a directory, otherwise false.
665 bool path_is_directory(const char *path);
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);
672 bool path_is_character_special(const char *path);
674 int path_stat(const char *path);
676 bool path_is_valid(const char *path);
678 int32_t path_get_size(const char *path);
680 bool is_path_accessible_using_standard_io(const char *path);