From 86e21686f7dad37f0b0aa722901951a35804221a Mon Sep 17 00:00:00 2001 From: Themaister Date: Sun, 18 Nov 2012 17:08:28 +0100 Subject: [PATCH] Refactor out buggy 'in-line' path handling. --- Makefile | 1 + conf/config_file.c | 45 +++++----------------------------- file.h | 21 +++++++++++++--- file_path.c | 61 ++++++++++++++++++++++++++++++++++++++++------ general.h | 5 ++-- gfx/shader_cg.c | 38 +++++++++-------------------- gfx/shader_glsl.c | 21 ++++------------ retroarch.c | 11 ++------- 8 files changed, 98 insertions(+), 105 deletions(-) diff --git a/Makefile b/Makefile index bf160a9624..a1af4094a6 100644 --- a/Makefile +++ b/Makefile @@ -28,6 +28,7 @@ OBJ = retroarch.o \ JOYCONFIG_OBJ = tools/retroarch-joyconfig.o \ conf/config_file.o \ + file_path.o \ compat/compat.o \ input/input_common.o diff --git a/conf/config_file.c b/conf/config_file.c index b8172ba688..eaa8b5ebb1 100644 --- a/conf/config_file.c +++ b/conf/config_file.c @@ -23,6 +23,7 @@ #include "../compat/strl.h" #include "../compat/posix_string.h" #include "../msvc/msvc_compat.h" +#include "../file.h" #if !defined(_WIN32) && !defined(__CELLOS_LV2__) && !defined(_XBOX) #include // PATH_MAX @@ -196,55 +197,21 @@ static void add_sub_conf(config_file_t *conf, char *line) return; add_include_list(conf, path); - char real_path[PATH_MAX]; #ifdef _WIN32 - // Accomodate POSIX systems on Win32. - bool is_full_path = *path == '/'; - - if (is_full_path) - strlcpy(real_path, path, sizeof(real_path)); - else - { - // Workaround GetFullPathName not existing on XDK. - // : is not a valid element in a path name. (NTFS streams?) - if (strchr(path, ':') == NULL) - { - strlcpy(real_path, conf->path, sizeof(real_path)); - char *split = strrchr(real_path, '/'); - if (!split) - split = strrchr(real_path, '\\'); - - split[1] = '\0'; - strlcat(real_path, path, sizeof(real_path)); - } - else - strlcpy(real_path, path, sizeof(real_path)); - } + fill_pathname_resolve_relative(real_path, conf->path, path, sizeof(real_path)); #else - if (*path == '/') - strlcpy(real_path, path, sizeof(real_path)); #ifndef __CELLOS_LV2__ - else if (*path == '~') + if (*path == '~') { const char *home = getenv("HOME"); - strlcpy(real_path, home ? home : "/", sizeof(real_path)); + strlcpy(real_path, home ? home : "", sizeof(real_path)); strlcat(real_path, path + 1, sizeof(real_path)); } -#endif else - { - strlcpy(real_path, conf->path, sizeof(real_path)); - char *split = strrchr(real_path, '/'); - if (split) - { - split[1] = '\0'; - strlcat(real_path, path, sizeof(real_path)); - } - else - strlcpy(real_path, path, sizeof(real_path)); - } +#endif + fill_pathname_resolve_relative(real_path, conf->path, path, sizeof(real_path)); #endif config_file_t *sub_conf = config_file_new_internal(real_path, conf->include_depth + 1); diff --git a/file.h b/file.h index 2379d83440..1cbaaaf5ce 100644 --- a/file.h +++ b/file.h @@ -69,6 +69,14 @@ bool path_is_directory(const char *path); bool path_file_exists(const char *path); const char *path_get_extension(const char *path); +// Returns basename from path. +const char *path_basename(const char *path); + +// Extracts base directory by mutating path. Keeps trailing '/'. +void path_basedir(char *path); + +bool path_is_absolute(const char *path); + // Path-name operations. // If any of these operation are detected to overflow, the application will be terminated. @@ -76,8 +84,8 @@ const char *path_get_extension(const char *path); // The extension here is considered to be the string from the last '.' to the end. // If no '.' is present, in_path and replace will simply be concatenated. // 'size' is buffer size of 'out_path'. -// I.e.: in_path = "/foo/bar/baz/boo.c", replace = ".asm" => out_path = "/foo/bar/baz/boo.asm" -// I.e.: in_path = "/foo/bar/baz/boo.c", replace = "" => out_path = "/foo/bar/baz/boo" +// E.g.: in_path = "/foo/bar/baz/boo.c", replace = ".asm" => out_path = "/foo/bar/baz/boo.asm" +// E.g.: in_path = "/foo/bar/baz/boo.c", replace = "" => out_path = "/foo/bar/baz/boo" void fill_pathname(char *out_path, const char *in_path, const char *replace, size_t size); // Appends a filename extension 'replace' to 'in_path', and outputs result in 'out_path'. @@ -89,7 +97,7 @@ void fill_pathname_noext(char *out_path, const char *in_path, const char *replac // Basename of in_basename is the string after the last '/' or '\\', i.e the filename without directories. // If in_basename has no '/' or '\\', the whole 'in_basename' will be used. // 'size' is buffer size of 'in_dir'. -// I.e.: in_dir = "/tmp/some_dir", in_basename = "/some_roms/foo.c", replace = ".asm" => +// E.g..: in_dir = "/tmp/some_dir", in_basename = "/some_roms/foo.c", replace = ".asm" => // in_dir = "/tmp/some_dir/foo.c.asm" void fill_pathname_dir(char *in_dir, const char *in_basename, const char *replace, size_t size); @@ -97,9 +105,14 @@ void fill_pathname_dir(char *in_dir, const char *in_basename, const char *replac void fill_pathname_base(char *out_path, const char *in_path, size_t size); // Copies base directory of in_path into out_path. -// If in_path is a path without any slashes (relative current directory), out_path will get path ".". +// If in_path is a path without any slashes (relative current directory), out_path will get path "./". void fill_pathname_basedir(char *out_path, const char *in_path, size_t size); +// Joins basedir of in_refpath together with in_path. +// If in_path is an absolute path, out_path = in_path. +// E.g.: in_refpath = "/foo/bar/baz.a", in_path = "foobar.cg", out_path = "/foo/bar/foobar.cg". +void fill_pathname_resolve_relative(char *out_path, const char *in_refpath, const char *in_path, size_t size); + size_t convert_char_to_wchar(wchar_t *out_wchar, const char *in_char, size_t size); size_t convert_wchar_to_char(char *out_char, const wchar_t *in_wchar, size_t size); diff --git a/file_path.c b/file_path.c index 582d3345c5..9cde2b15f3 100644 --- a/file_path.c +++ b/file_path.c @@ -410,17 +410,62 @@ void fill_pathname_base(char *out, const char *in_path, size_t size) void fill_pathname_basedir(char *out_dir, const char *in_path, size_t size) { rarch_assert(strlcpy(out_dir, in_path, size) < size); + path_basedir(out_dir); +} - char *base = strrchr(out_dir, '/'); - if (!base) - base = strrchr(out_dir, '\\'); +void path_basedir(char *path) +{ + if (strlen(path) < 2) + return; - if (base) - *base = '\0'; - else if (size >= 2) + char *last = strrchr(path, '/'); +#ifdef _WIN32 + if (!last) + last = strrchr(path, '\\'); +#endif + + if (last) + last[1] = '\0'; + else { - out_dir[0] = '.'; - out_dir[1] = '\0'; + path[0] = '.'; + path[1] = '/'; + path[2] = '\0'; + } +} + +const char *path_basename(const char *path) +{ + const char *last = strrchr(path, '/'); +#ifdef _WIN32 + if (!last) + last = strrchr(path, '\\'); +#endif + + if (last) + return last + 1; + else + return path; +} + +bool path_is_absolute(const char *path) +{ +#ifdef _WIN32 + return path[0] == '/' || strstr(path, ":/") || strstr(path, ":\\"); +#else + return path[0] == '/'; +#endif +} + +void fill_pathname_resolve_relative(char *out_path, const char *in_refpath, const char *in_path, size_t size) +{ + if (path_is_absolute(in_path)) + rarch_assert(strlcpy(out_path, in_path, size) < size); + else + { + rarch_assert(strlcpy(out_path, in_refpath, size) < size); + path_basedir(out_path); + rarch_assert(strlcat(out_path, in_path, size) < size); } } diff --git a/general.h b/general.h index bcdfd841fb..5b6dc415e9 100644 --- a/general.h +++ b/general.h @@ -708,8 +708,9 @@ static inline void rarch_sleep(unsigned msec) #endif } -#define rarch_assert(cond) \ - if (!(cond)) { RARCH_ERR("Assertion failed at %s:%d.\n", __FILE__, __LINE__); exit(2); } +#define rarch_assert(cond) do { \ + if (!(cond)) { RARCH_ERR("Assertion failed at %s:%d.\n", __FILE__, __LINE__); exit(2); } \ +} while(0) static inline void rarch_fail(int error_code, const char *error) { diff --git a/gfx/shader_cg.c b/gfx/shader_cg.c index f0066832ec..f1875666bd 100644 --- a/gfx/shader_cg.c +++ b/gfx/shader_cg.c @@ -28,6 +28,7 @@ #include "image.h" #include "../dynamic.h" #include "../compat/posix_string.h" +#include "../file.h" #ifdef HAVE_CONFIGFILE #include "state_tracker.h" @@ -533,7 +534,7 @@ static void load_texture_data(GLuint *obj, const struct texture_image *img, bool free(img->pixels); } -static bool load_textures(const char *dir_path, config_file_t *conf) +static bool load_textures(const char *cgp_path, config_file_t *conf) { bool ret = true; char *textures = NULL; @@ -566,11 +567,8 @@ static bool load_textures(const char *dir_path, config_file_t *conf) if (!config_get_bool(conf, id_absolute, &absolute)) absolute = false; - char image_path[512]; - if (absolute) - print_buf(image_path, "%s", path); - else - print_buf(image_path, "%s%s", dir_path, path); + char image_path[PATH_MAX]; + fill_pathname_resolve_relative(image_path, cgp_path, path, sizeof(image_path)); RARCH_LOG("Loading image from: \"%s\".\n", image_path); struct texture_image img; @@ -596,7 +594,7 @@ end: return ret; } -static bool load_imports(const char *dir_path, config_file_t *conf) +static bool load_imports(const char *cgp_path, config_file_t *conf) { bool ret = true; char *imports = NULL; @@ -744,9 +742,7 @@ static bool load_imports(const char *dir_path, config_file_t *conf) #ifdef HAVE_PYTHON if (config_get_string(conf, "import_script", &script)) { - strlcpy(script_path, dir_path, sizeof(script_path)); - strlcat(script_path, script, sizeof(script_path)); - + fill_pathname_resolve_relative(script_path, cgp_path, script, sizeof(script_path)); tracker_info.script = script_path; } if (config_get_string(conf, "import_script_class", &script_class)) @@ -772,7 +768,7 @@ end: } #endif -static bool load_shader(const char *dir_path, unsigned i, config_file_t *conf) +static bool load_shader(const char *cgp_path, unsigned i, config_file_t *conf) { char *shader_path = NULL; char attr_buf[64]; @@ -781,8 +777,7 @@ static bool load_shader(const char *dir_path, unsigned i, config_file_t *conf) print_buf(attr_buf, "shader%u", i); if (config_get_string(conf, attr_buf, &shader_path)) { - strlcpy(path_buf, dir_path, sizeof(path_buf)); - strlcat(path_buf, shader_path, sizeof(path_buf)); + fill_pathname_resolve_relative(path_buf, cgp_path, shader_path, sizeof(path_buf)); free(shader_path); } else @@ -945,9 +940,6 @@ static bool load_preset(const char *path) return false; int shaders = 0; - // Basedir. - char dir_path[PATH_MAX]; - char *ptr = NULL; RARCH_LOG("Loading Cg meta-shader: %s\n", path); config_file_t *conf = config_file_new(path); @@ -994,14 +986,6 @@ static bool load_preset(const char *path) fbo_smooth[i + 1] = smooth ? FILTER_LINEAR : FILTER_NEAREST; } - strlcpy(dir_path, path, sizeof(dir_path)); - ptr = strrchr(dir_path, '/'); - if (!ptr) ptr = strrchr(dir_path, '\\'); - if (ptr) - ptr[1] = '\0'; - else // No directory. - dir_path[0] = '\0'; - for (int i = 0; i < shaders; i++) { if (!load_shader_params(i, conf)) @@ -1011,7 +995,7 @@ static bool load_preset(const char *path) goto end; } - if (!load_shader(dir_path, i, conf)) + if (!load_shader(path, i, conf)) { RARCH_ERR("Failed to load shaders ...\n"); ret = false; @@ -1019,14 +1003,14 @@ static bool load_preset(const char *path) } } - if (!load_textures(dir_path, conf)) + if (!load_textures(path, conf)) { RARCH_ERR("Failed to load lookup textures ...\n"); ret = false; goto end; } - if (!load_imports(dir_path, conf)) + if (!load_imports(path, conf)) { RARCH_ERR("Failed to load imports ...\n"); ret = false; diff --git a/gfx/shader_glsl.c b/gfx/shader_glsl.c index d5c258e310..0d35a62c7e 100644 --- a/gfx/shader_glsl.c +++ b/gfx/shader_glsl.c @@ -21,6 +21,7 @@ #include "../compat/posix_string.h" #include "state_tracker.h" #include "../dynamic.h" +#include "../file.h" #ifdef HAVE_CONFIG_H #include "../config.h" @@ -422,9 +423,8 @@ static bool get_texture_image(const char *shader_path, xmlNodePtr ptr) bool linear = true; xmlChar *filename = xmlGetProp(ptr, (const xmlChar*)"file"); - xmlChar *filter = xmlGetProp(ptr, (const xmlChar*)"filter"); - xmlChar *id = xmlGetProp(ptr, (const xmlChar*)"id"); - char *last = NULL; + xmlChar *filter = xmlGetProp(ptr, (const xmlChar*)"filter"); + xmlChar *id = xmlGetProp(ptr, (const xmlChar*)"id"); struct texture_image img; if (!id) @@ -443,13 +443,7 @@ static bool get_texture_image(const char *shader_path, xmlNodePtr ptr) linear = false; char tex_path[PATH_MAX]; - strlcpy(tex_path, shader_path, sizeof(tex_path)); - - last = strrchr(tex_path, '/'); - if (!last) last = strrchr(tex_path, '\\'); - if (last) last[1] = '\0'; - - strlcat(tex_path, (const char*)filename, sizeof(tex_path)); + fill_pathname_resolve_relative(tex_path, shader_path, (const char*)filename, sizeof(tex_path)); RARCH_LOG("Loading texture image from: \"%s\" ...\n", tex_path); if (!texture_image_load(tex_path, &img)) @@ -529,12 +523,7 @@ static bool get_script(const char *path, xmlNodePtr ptr) xmlChar *src = xmlGetProp(ptr, (const xmlChar*)"src"); if (src) { - strlcpy(gl_tracker_script, path, sizeof(gl_tracker_script)); - char *dir_ptr = strrchr(gl_tracker_script, '/'); - if (!dir_ptr) dir_ptr = strrchr(gl_tracker_script, '\\'); - if (dir_ptr) dir_ptr[1] = '\0'; - strlcat(gl_tracker_script, (const char*)src, sizeof(gl_tracker_script)); - + fill_pathname_resolve_relative(gl_tracker_script, path, (const char*)src, sizeof(gl_tracker_script)); xmlFree(src); } else diff --git a/retroarch.c b/retroarch.c index 55c9973dab..acb552da81 100644 --- a/retroarch.c +++ b/retroarch.c @@ -1810,15 +1810,8 @@ static void fill_pathnames(void) fill_pathname_noext(g_extern.xml_name, g_extern.basename, ".xml", sizeof(g_extern.xml_name)); #ifdef HAVE_SCREENSHOTS - if (!(*g_settings.screenshot_directory)) - { - strlcpy(g_settings.screenshot_directory, g_extern.basename, sizeof(g_settings.screenshot_directory)); - char *dir = strrchr(g_settings.screenshot_directory, '/'); - if (!dir) - dir = strrchr(g_settings.screenshot_directory, '\\'); - if (dir) - *dir = '\0'; - } + if (!*g_settings.screenshot_directory) + fill_pathname_basedir(g_settings.screenshot_directory, g_extern.basename, sizeof(g_settings.screenshot_directory)); #endif } }