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 \
conf/config_file.o \
file_path.o \
compat/compat.o \
input/input_common.o

View File

@ -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 <sys/param.h> // 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);

21
file.h
View File

@ -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);

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)
{
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);
}
}

View File

@ -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)
{

View File

@ -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;

View File

@ -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

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));
#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
}
}