Refactor out buggy 'in-line' path handling.

This commit is contained in:
Themaister 2012-11-18 17:08:28 +01:00
parent 6e6dbe2ab4
commit 86e21686f7
8 changed files with 98 additions and 105 deletions

View File

@ -28,6 +28,7 @@ OBJ = retroarch.o \
JOYCONFIG_OBJ = tools/retroarch-joyconfig.o \ JOYCONFIG_OBJ = tools/retroarch-joyconfig.o \
conf/config_file.o \ conf/config_file.o \
file_path.o \
compat/compat.o \ compat/compat.o \
input/input_common.o input/input_common.o

View File

@ -23,6 +23,7 @@
#include "../compat/strl.h" #include "../compat/strl.h"
#include "../compat/posix_string.h" #include "../compat/posix_string.h"
#include "../msvc/msvc_compat.h" #include "../msvc/msvc_compat.h"
#include "../file.h"
#if !defined(_WIN32) && !defined(__CELLOS_LV2__) && !defined(_XBOX) #if !defined(_WIN32) && !defined(__CELLOS_LV2__) && !defined(_XBOX)
#include <sys/param.h> // PATH_MAX #include <sys/param.h> // PATH_MAX
@ -196,55 +197,21 @@ static void add_sub_conf(config_file_t *conf, char *line)
return; return;
add_include_list(conf, path); add_include_list(conf, path);
char real_path[PATH_MAX]; char real_path[PATH_MAX];
#ifdef _WIN32 #ifdef _WIN32
// Accomodate POSIX systems on Win32. fill_pathname_resolve_relative(real_path, conf->path, path, sizeof(real_path));
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));
}
#else #else
if (*path == '/')
strlcpy(real_path, path, sizeof(real_path));
#ifndef __CELLOS_LV2__ #ifndef __CELLOS_LV2__
else if (*path == '~') if (*path == '~')
{ {
const char *home = getenv("HOME"); 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)); strlcat(real_path, path + 1, sizeof(real_path));
} }
else
#endif #endif
else fill_pathname_resolve_relative(real_path, conf->path, path, sizeof(real_path));
{
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 #endif
config_file_t *sub_conf = config_file_new_internal(real_path, conf->include_depth + 1); config_file_t *sub_conf = config_file_new_internal(real_path, conf->include_depth + 1);

21
file.h
View File

@ -69,6 +69,14 @@ bool path_is_directory(const char *path);
bool path_file_exists(const char *path); bool path_file_exists(const char *path);
const char *path_get_extension(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. // Path-name operations.
// If any of these operation are detected to overflow, the application will be terminated. // 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. // 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. // If no '.' is present, in_path and replace will simply be concatenated.
// 'size' is buffer size of 'out_path'. // '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" // E.g.: 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 = "" => out_path = "/foo/bar/baz/boo"
void fill_pathname(char *out_path, const char *in_path, const char *replace, size_t size); 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'. // 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. // 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. // If in_basename has no '/' or '\\', the whole 'in_basename' will be used.
// 'size' is buffer size of 'in_dir'. // '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" // 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); 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); void fill_pathname_base(char *out_path, const char *in_path, size_t size);
// Copies base directory of in_path into out_path. // 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); 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_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); size_t convert_wchar_to_char(char *out_char, const wchar_t *in_wchar, size_t size);

View File

@ -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) void fill_pathname_basedir(char *out_dir, const char *in_path, size_t size)
{ {
rarch_assert(strlcpy(out_dir, in_path, size) < size); rarch_assert(strlcpy(out_dir, in_path, size) < size);
path_basedir(out_dir);
}
char *base = strrchr(out_dir, '/'); void path_basedir(char *path)
if (!base) {
base = strrchr(out_dir, '\\'); if (strlen(path) < 2)
return;
if (base) char *last = strrchr(path, '/');
*base = '\0'; #ifdef _WIN32
else if (size >= 2) if (!last)
last = strrchr(path, '\\');
#endif
if (last)
last[1] = '\0';
else
{ {
out_dir[0] = '.'; path[0] = '.';
out_dir[1] = '\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);
} }
} }

View File

@ -708,8 +708,9 @@ static inline void rarch_sleep(unsigned msec)
#endif #endif
} }
#define rarch_assert(cond) \ #define rarch_assert(cond) do { \
if (!(cond)) { RARCH_ERR("Assertion failed at %s:%d.\n", __FILE__, __LINE__); exit(2); } 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) static inline void rarch_fail(int error_code, const char *error)
{ {

View File

@ -28,6 +28,7 @@
#include "image.h" #include "image.h"
#include "../dynamic.h" #include "../dynamic.h"
#include "../compat/posix_string.h" #include "../compat/posix_string.h"
#include "../file.h"
#ifdef HAVE_CONFIGFILE #ifdef HAVE_CONFIGFILE
#include "state_tracker.h" #include "state_tracker.h"
@ -533,7 +534,7 @@ static void load_texture_data(GLuint *obj, const struct texture_image *img, bool
free(img->pixels); 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; bool ret = true;
char *textures = NULL; 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)) if (!config_get_bool(conf, id_absolute, &absolute))
absolute = false; absolute = false;
char image_path[512]; char image_path[PATH_MAX];
if (absolute) fill_pathname_resolve_relative(image_path, cgp_path, path, sizeof(image_path));
print_buf(image_path, "%s", path);
else
print_buf(image_path, "%s%s", dir_path, path);
RARCH_LOG("Loading image from: \"%s\".\n", image_path); RARCH_LOG("Loading image from: \"%s\".\n", image_path);
struct texture_image img; struct texture_image img;
@ -596,7 +594,7 @@ end:
return ret; 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; bool ret = true;
char *imports = NULL; char *imports = NULL;
@ -744,9 +742,7 @@ static bool load_imports(const char *dir_path, config_file_t *conf)
#ifdef HAVE_PYTHON #ifdef HAVE_PYTHON
if (config_get_string(conf, "import_script", &script)) if (config_get_string(conf, "import_script", &script))
{ {
strlcpy(script_path, dir_path, sizeof(script_path)); fill_pathname_resolve_relative(script_path, cgp_path, script, sizeof(script_path));
strlcat(script_path, script, sizeof(script_path));
tracker_info.script = script_path; tracker_info.script = script_path;
} }
if (config_get_string(conf, "import_script_class", &script_class)) if (config_get_string(conf, "import_script_class", &script_class))
@ -772,7 +768,7 @@ end:
} }
#endif #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 *shader_path = NULL;
char attr_buf[64]; 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); print_buf(attr_buf, "shader%u", i);
if (config_get_string(conf, attr_buf, &shader_path)) if (config_get_string(conf, attr_buf, &shader_path))
{ {
strlcpy(path_buf, dir_path, sizeof(path_buf)); fill_pathname_resolve_relative(path_buf, cgp_path, shader_path, sizeof(path_buf));
strlcat(path_buf, shader_path, sizeof(path_buf));
free(shader_path); free(shader_path);
} }
else else
@ -945,9 +940,6 @@ static bool load_preset(const char *path)
return false; return false;
int shaders = 0; int shaders = 0;
// Basedir.
char dir_path[PATH_MAX];
char *ptr = NULL;
RARCH_LOG("Loading Cg meta-shader: %s\n", path); RARCH_LOG("Loading Cg meta-shader: %s\n", path);
config_file_t *conf = config_file_new(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; 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++) for (int i = 0; i < shaders; i++)
{ {
if (!load_shader_params(i, conf)) if (!load_shader_params(i, conf))
@ -1011,7 +995,7 @@ static bool load_preset(const char *path)
goto end; goto end;
} }
if (!load_shader(dir_path, i, conf)) if (!load_shader(path, i, conf))
{ {
RARCH_ERR("Failed to load shaders ...\n"); RARCH_ERR("Failed to load shaders ...\n");
ret = false; 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"); RARCH_ERR("Failed to load lookup textures ...\n");
ret = false; ret = false;
goto end; goto end;
} }
if (!load_imports(dir_path, conf)) if (!load_imports(path, conf))
{ {
RARCH_ERR("Failed to load imports ...\n"); RARCH_ERR("Failed to load imports ...\n");
ret = false; ret = false;

View File

@ -21,6 +21,7 @@
#include "../compat/posix_string.h" #include "../compat/posix_string.h"
#include "state_tracker.h" #include "state_tracker.h"
#include "../dynamic.h" #include "../dynamic.h"
#include "../file.h"
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include "../config.h" #include "../config.h"
@ -424,7 +425,6 @@ static bool get_texture_image(const char *shader_path, xmlNodePtr ptr)
xmlChar *filename = xmlGetProp(ptr, (const xmlChar*)"file"); xmlChar *filename = xmlGetProp(ptr, (const xmlChar*)"file");
xmlChar *filter = xmlGetProp(ptr, (const xmlChar*)"filter"); xmlChar *filter = xmlGetProp(ptr, (const xmlChar*)"filter");
xmlChar *id = xmlGetProp(ptr, (const xmlChar*)"id"); xmlChar *id = xmlGetProp(ptr, (const xmlChar*)"id");
char *last = NULL;
struct texture_image img; struct texture_image img;
if (!id) if (!id)
@ -443,13 +443,7 @@ static bool get_texture_image(const char *shader_path, xmlNodePtr ptr)
linear = false; linear = false;
char tex_path[PATH_MAX]; char tex_path[PATH_MAX];
strlcpy(tex_path, shader_path, sizeof(tex_path)); fill_pathname_resolve_relative(tex_path, shader_path, (const char*)filename, 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));
RARCH_LOG("Loading texture image from: \"%s\" ...\n", tex_path); RARCH_LOG("Loading texture image from: \"%s\" ...\n", tex_path);
if (!texture_image_load(tex_path, &img)) 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"); xmlChar *src = xmlGetProp(ptr, (const xmlChar*)"src");
if (src) if (src)
{ {
strlcpy(gl_tracker_script, path, sizeof(gl_tracker_script)); fill_pathname_resolve_relative(gl_tracker_script, path, (const char*)src, 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));
xmlFree(src); xmlFree(src);
} }
else else

View File

@ -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)); fill_pathname_noext(g_extern.xml_name, g_extern.basename, ".xml", sizeof(g_extern.xml_name));
#ifdef HAVE_SCREENSHOTS #ifdef HAVE_SCREENSHOTS
if (!(*g_settings.screenshot_directory)) if (!*g_settings.screenshot_directory)
{ fill_pathname_basedir(g_settings.screenshot_directory, g_extern.basename, sizeof(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';
}
#endif #endif
} }
} }