git subrepo pull --force deps/lightrec
[pcsx_rearmed.git] / deps / libretro-common / include / file / file_path.h
CommitLineData
3719602c
PC
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
36RETRO_BEGIN_DECLS
37
38#define PATH_REQUIRED_VFS_VERSION 3
39
40void 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) */
44enum
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
54struct 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**/
64struct path_linked_list* path_linked_list_new(void);
65
66/* Free the entire linked list */
67void 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**/
74void 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 **/
84bool 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 **/
112const 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 **/
127const 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 **/
141char *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 */
160char *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 **/
174const 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 **/
188const 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 **/
197void 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 **/
208void 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 **/
227char *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 **/
245size_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 **/
256bool 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 */
286size_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 **/
307size_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 **/
333size_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 **/
350char *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 **/
374size_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 **/
391size_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 **/
407void 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 **/
425bool 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 **/
443void 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 **/
458void 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 **/
482size_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 **/
508size_t fill_pathname_join_special(char *out_path,
509 const char *dir, const char *path, size_t size);
510
511size_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 **/
532size_t fill_pathname_join_delim(char *out_path, const char *dir,
533 const char *path, const char delim, size_t size);
534
535size_t fill_pathname_expand_special(char *out_path,
536 const char *in_path, size_t size);
537
538size_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 **/
553size_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 **/
566void 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 **/
577void 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 **/
586void 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 **/
630void fill_pathname_slash(char *path, size_t size);
631
632#if !defined(RARCH_CONSOLE) && defined(RARCH_INTERNAL)
633void fill_pathname_application_path(char *buf, size_t size);
634void fill_pathname_application_dir(char *buf, size_t size);
635void 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 **/
655bool 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 */
665bool path_is_directory(const char *path);
666
667/* Time format strings with AM-PM designation require special
668 * handling due to platform dependence */
669void strftime_am_pm(char *s, size_t len, const char* format,
670 const void* timeptr);
671
672bool path_is_character_special(const char *path);
673
674int path_stat(const char *path);
675
676bool path_is_valid(const char *path);
677
678int32_t path_get_size(const char *path);
679
680bool is_path_accessible_using_standard_io(const char *path);
681
682RETRO_END_DECLS
683
684#endif