1 /* Copyright (C) 2010-2017 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 <retro_common_api.h> 32 33 #include <boolean.h> 34 35 RETRO_BEGIN_DECLS 36 37 /* Order in this enum is equivalent to negative sort order in filelist 38 * (i.e. DIRECTORY is on top of PLAIN_FILE) */ 39 enum 40 { 41 RARCH_FILETYPE_UNSET, 42 RARCH_PLAIN_FILE, 43 RARCH_COMPRESSED_FILE_IN_ARCHIVE, 44 RARCH_COMPRESSED_ARCHIVE, 45 RARCH_DIRECTORY, 46 RARCH_FILE_UNSUPPORTED 47 }; 48 49 50 /** 51 * path_is_compressed_file: 52 * @path : path 53 * 54 * Checks if path is a compressed file. 55 * 56 * Returns: true (1) if path is a compressed file, otherwise false (0). 57 **/ 58 bool path_is_compressed_file(const char *path); 59 60 /** 61 * path_contains_compressed_file: 62 * @path : path 63 * 64 * Checks if path contains a compressed file. 65 * 66 * Currently we only check for hash symbol (#) inside the pathname. 67 * If path is ever expanded to a general URI, we should check for that here. 68 * 69 * Example: Somewhere in the path there might be a compressed file 70 * E.g.: /path/to/file.7z#mygame.img 71 * 72 * Returns: true (1) if path contains compressed file, otherwise false (0). 73 **/ 74 #define path_contains_compressed_file(path) (path_get_archive_delim((path)) != NULL) 75 76 /** 77 * path_file_exists: 78 * @path : path 79 * 80 * Checks if a file already exists at the specified path (@path). 81 * 82 * Returns: true (1) if file already exists, otherwise false (0). 83 */ 84 bool path_file_exists(const char *path); 85 86 /** 87 * path_get_archive_delim: 88 * @path : path 89 * 90 * Gets delimiter of an archive file. Only the first '#' 91 * after a compression extension is considered. 92 * 93 * Returns: pointer to the delimiter in the path if it contains 94 * a compressed file, otherwise NULL. 95 */ 96 const char *path_get_archive_delim(const char *path); 97 98 /** 99 * path_get_extension: 100 * @path : path 101 * 102 * Gets extension of file. Only '.'s 103 * after the last slash are considered. 104 * 105 * Returns: extension part from the path. 106 */ 107 const char *path_get_extension(const char *path); 108 109 /** 110 * path_remove_extension: 111 * @path : path 112 * 113 * Removes the extension from the path and returns the result. 114 * Removes all text after and including the last '.'. 115 * Only '.'s after the last slash are considered. 116 * 117 * Returns: path with the extension part removed. 118 */ 119 char *path_remove_extension(char *path); 120 121 /** 122 * path_basename: 123 * @path : path 124 * 125 * Get basename from @path. 126 * 127 * Returns: basename from path. 128 **/ 129 const char *path_basename(const char *path); 130 131 /** 132 * path_basedir: 133 * @path : path 134 * 135 * Extracts base directory by mutating path. 136 * Keeps trailing '/'. 137 **/ 138 void path_basedir(char *path); 139 140 /** 141 * path_parent_dir: 142 * @path : path 143 * 144 * Extracts parent directory by mutating path. 145 * Assumes that path is a directory. Keeps trailing '/'. 146 **/ 147 void path_parent_dir(char *path); 148 149 /** 150 * path_resolve_realpath: 151 * @buf : buffer for path 152 * @size : size of buffer 153 * 154 * Turns relative paths into absolute path. 155 * If relative, rebases on current working dir. 156 **/ 157 void path_resolve_realpath(char *buf, size_t size); 158 159 /** 160 * path_is_absolute: 161 * @path : path 162 * 163 * Checks if @path is an absolute path or a relative path. 164 * 165 * Returns: true if path is absolute, false if path is relative. 166 **/ 167 bool path_is_absolute(const char *path); 168 169 /** 170 * fill_pathname: 171 * @out_path : output path 172 * @in_path : input path 173 * @replace : what to replace 174 * @size : buffer size of output path 175 * 176 * FIXME: Verify 177 * 178 * Replaces filename extension with 'replace' and outputs result to out_path. 179 * The extension here is considered to be the string from the last '.' 180 * to the end. 181 * 182 * Only '.'s after the last slash are considered as extensions. 183 * If no '.' is present, in_path and replace will simply be concatenated. 184 * 'size' is buffer size of 'out_path'. 185 * E.g.: in_path = "/foo/bar/baz/boo.c", replace = ".asm" => 186 * out_path = "/foo/bar/baz/boo.asm" 187 * E.g.: in_path = "/foo/bar/baz/boo.c", replace = "" => 188 * out_path = "/foo/bar/baz/boo" 189 */ 190 void fill_pathname(char *out_path, const char *in_path, 191 const char *replace, size_t size); 192 193 /** 194 * fill_dated_filename: 195 * @out_filename : output filename 196 * @ext : extension of output filename 197 * @size : buffer size of output filename 198 * 199 * Creates a 'dated' filename prefixed by 'RetroArch', and 200 * concatenates extension (@ext) to it. 201 * 202 * E.g.: 203 * out_filename = "RetroArch-{month}{day}-{Hours}{Minutes}.{@ext}" 204 **/ 205 void fill_dated_filename(char *out_filename, 206 const char *ext, size_t size); 207 208 /** 209 * fill_str_dated_filename: 210 * @out_filename : output filename 211 * @in_str : input string 212 * @ext : extension of output filename 213 * @size : buffer size of output filename 214 * 215 * Creates a 'dated' filename prefixed by the string @in_str, and 216 * concatenates extension (@ext) to it. 217 * 218 * E.g.: 219 * out_filename = "RetroArch-{year}{month}{day}-{Hour}{Minute}{Second}.{@ext}" 220 **/ 221 void fill_str_dated_filename(char *out_filename, 222 const char *in_str, const char *ext, size_t size); 223 224 /** 225 * fill_pathname_noext: 226 * @out_path : output path 227 * @in_path : input path 228 * @replace : what to replace 229 * @size : buffer size of output path 230 * 231 * Appends a filename extension 'replace' to 'in_path', and outputs 232 * result in 'out_path'. 233 * 234 * Assumes in_path has no extension. If an extension is still 235 * present in 'in_path', it will be ignored. 236 * 237 */ 238 void fill_pathname_noext(char *out_path, const char *in_path, 239 const char *replace, size_t size); 240 241 /** 242 * find_last_slash: 243 * @str : input path 244 * 245 * Gets a pointer to the last slash in the input path. 246 * 247 * Returns: a pointer to the last slash in the input path. 248 **/ 249 char *find_last_slash(const char *str); 250 251 /** 252 * fill_pathname_dir: 253 * @in_dir : input directory path 254 * @in_basename : input basename to be appended to @in_dir 255 * @replace : replacement to be appended to @in_basename 256 * @size : size of buffer 257 * 258 * Appends basename of 'in_basename', to 'in_dir', along with 'replace'. 259 * Basename of in_basename is the string after the last '/' or '\\', 260 * i.e the filename without directories. 261 * 262 * If in_basename has no '/' or '\\', the whole 'in_basename' will be used. 263 * 'size' is buffer size of 'in_dir'. 264 * 265 * E.g..: in_dir = "/tmp/some_dir", in_basename = "/some_content/foo.c", 266 * replace = ".asm" => in_dir = "/tmp/some_dir/foo.c.asm" 267 **/ 268 void fill_pathname_dir(char *in_dir, const char *in_basename, 269 const char *replace, size_t size); 270 271 /** 272 * fill_pathname_base: 273 * @out : output path 274 * @in_path : input path 275 * @size : size of output path 276 * 277 * Copies basename of @in_path into @out_path. 278 **/ 279 void fill_pathname_base(char *out_path, const char *in_path, size_t size); 280 281 void fill_pathname_base_noext(char *out_dir, 282 const char *in_path, size_t size); 283 284 void fill_pathname_base_ext(char *out, 285 const char *in_path, const char *ext, 286 size_t size); 287 288 /** 289 * fill_pathname_basedir: 290 * @out_dir : output directory 291 * @in_path : input path 292 * @size : size of output directory 293 * 294 * Copies base directory of @in_path into @out_path. 295 * If in_path is a path without any slashes (relative current directory), 296 * @out_path will get path "./". 297 **/ 298 void fill_pathname_basedir(char *out_path, const char *in_path, size_t size); 299 300 void fill_pathname_basedir_noext(char *out_dir, 301 const char *in_path, size_t size); 302 303 /** 304 * fill_pathname_parent_dir: 305 * @out_dir : output directory 306 * @in_dir : input directory 307 * @size : size of output directory 308 * 309 * Copies parent directory of @in_dir into @out_dir. 310 * Assumes @in_dir is a directory. Keeps trailing '/'. 311 **/ 312 void fill_pathname_parent_dir(char *out_dir, 313 const char *in_dir, size_t size); 314 315 /** 316 * fill_pathname_resolve_relative: 317 * @out_path : output path 318 * @in_refpath : input reference path 319 * @in_path : input path 320 * @size : size of @out_path 321 * 322 * Joins basedir of @in_refpath together with @in_path. 323 * If @in_path is an absolute path, out_path = in_path. 324 * E.g.: in_refpath = "/foo/bar/baz.a", in_path = "foobar.cg", 325 * out_path = "/foo/bar/foobar.cg". 326 **/ 327 void fill_pathname_resolve_relative(char *out_path, const char *in_refpath, 328 const char *in_path, size_t size); 329 330 /** 331 * fill_pathname_join: 332 * @out_path : output path 333 * @dir : directory 334 * @path : path 335 * @size : size of output path 336 * 337 * Joins a directory (@dir) and path (@path) together. 338 * Makes sure not to get two consecutive slashes 339 * between directory and path. 340 **/ 341 void fill_pathname_join(char *out_path, const char *dir, 342 const char *path, size_t size); 343 344 void fill_pathname_join_special_ext(char *out_path, 345 const char *dir, const char *path, 346 const char *last, const char *ext, 347 size_t size); 348 349 void fill_pathname_join_concat(char *out_path, 350 const char *dir, const char *path, 351 const char *concat, 352 size_t size); 353 354 void fill_pathname_join_noext(char *out_path, 355 const char *dir, const char *path, size_t size); 356 357 /** 358 * fill_pathname_join_delim: 359 * @out_path : output path 360 * @dir : directory 361 * @path : path 362 * @delim : delimiter 363 * @size : size of output path 364 * 365 * Joins a directory (@dir) and path (@path) together 366 * using the given delimiter (@delim). 367 **/ 368 void fill_pathname_join_delim(char *out_path, const char *dir, 369 const char *path, const char delim, size_t size); 370 371 void fill_pathname_join_delim_concat(char *out_path, const char *dir, 372 const char *path, const char delim, const char *concat, 373 size_t size); 374 375 /** 376 * fill_short_pathname_representation: 377 * @out_rep : output representation 378 * @in_path : input path 379 * @size : size of output representation 380 * 381 * Generates a short representation of path. It should only 382 * be used for displaying the result; the output representation is not 383 * binding in any meaningful way (for a normal path, this is the same as basename) 384 * In case of more complex URLs, this should cut everything except for 385 * the main image file. 386 * 387 * E.g.: "/path/to/game.img" -> game.img 388 * "/path/to/myarchive.7z#folder/to/game.img" -> game.img 389 */ 390 void fill_short_pathname_representation(char* out_rep, 391 const char *in_path, size_t size); 392 393 void fill_short_pathname_representation_noext(char* out_rep, 394 const char *in_path, size_t size); 395 396 void fill_pathname_expand_special(char *out_path, 397 const char *in_path, size_t size); 398 399 void fill_pathname_abbreviate_special(char *out_path, 400 const char *in_path, size_t size); 401 402 /** 403 * path_char_is_slash: 404 * @c : character 405 * 406 * Checks if character (@c) is a slash. 407 * 408 * Returns: true (1) if character is a slash, otherwise false (0). 409 */ 410 #ifdef _WIN32 411 #define path_char_is_slash(c) (((c) == '/') || ((c) == '\\')) 412 #else 413 #define path_char_is_slash(c) ((c) == '/') 414 #endif 415 416 /** 417 * path_default_slash: 418 * 419 * Gets the default slash separator. 420 * 421 * Returns: default slash separator. 422 */ 423 #ifdef _WIN32 424 #define path_default_slash() "\\" 425 #else 426 #define path_default_slash() "/" 427 #endif 428 429 /** 430 * fill_pathname_slash: 431 * @path : path 432 * @size : size of path 433 * 434 * Assumes path is a directory. Appends a slash 435 * if not already there. 436 **/ 437 void fill_pathname_slash(char *path, size_t size); 438 439 #ifndef RARCH_CONSOLE 440 void fill_pathname_application_path(char *buf, size_t size); 441 #endif 442 443 /** 444 * path_mkdir: 445 * @dir : directory 446 * 447 * Create directory on filesystem. 448 * 449 * Returns: true (1) if directory could be created, otherwise false (0). 450 **/ 451 bool path_mkdir(const char *dir); 452 453 /** 454 * path_is_directory: 455 * @path : path 456 * 457 * Checks if path is a directory. 458 * 459 * Returns: true (1) if path is a directory, otherwise false (0). 460 */ 461 bool path_is_directory(const char *path); 462 463 bool path_is_character_special(const char *path); 464 465 bool path_is_valid(const char *path); 466 467 int32_t path_get_size(const char *path); 468 469 RETRO_END_DECLS 470 471 #endif 472