From 0b974d8997ca89cc5760d81534741f290c32380b Mon Sep 17 00:00:00 2001 From: d_m Date: Tue, 17 Sep 2024 20:32:03 -0400 Subject: [PATCH] Standardize on using / for all paths. Without this change there is no cross-platform way to create a directory on Windows, since the previous code checked for the path delimiter as the final character, which was OS-dependent. Seems to work on Windows based on tbsp's testing. This change also fixes realpath on Windows. Suggested by tbsp, based on: https://stackoverflow.com/questions/45124869/cross-platform-alternative-to-this-realpath-definition/72492046#72492046 --- src/devices/file.c | 48 ++++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/src/devices/file.c b/src/devices/file.c index a7487d4..6683c35 100644 --- a/src/devices/file.c +++ b/src/devices/file.c @@ -8,27 +8,30 @@ #include #include -#ifdef _WIN32 -#include -#include -#define realpath(s, dummy) lrealpath(s) -#define DIR_SEP_CHAR '\\' -#define DIR_SEP_STR "\\" -#define pathcmp(path1, path2, length) strncasecmp(path1, path2, length) /* strncasecmp provided by libiberty */ -#define notdriveroot(file_name) (file_name[0] != DIR_SEP_CHAR && ((strlen(file_name) > 2 && file_name[1] != ':') || strlen(file_name) <= 2)) -#define mkdir(file_name) (_mkdir(file_name) == 0) -#else -#define DIR_SEP_CHAR '/' -#define DIR_SEP_STR "/" -#define pathcmp(path1, path2, length) strncmp(path1, path2, length) -#define notdriveroot(file_name) (file_name[0] != DIR_SEP_CHAR) -#define mkdir(file_name) (mkdir(file_name, 0755) == 0) -#endif - #ifndef PATH_MAX #define PATH_MAX 4096 #endif +/* Windows devices can handle relative paths like "abc/def.txt" and + absolute paths like "/foo/bar/baz.txt" so cross-platform ROMs + should just use forward slash unconditionally and let the emulator + worry about how to find the files in the filesystem. */ + +#ifdef _WIN32 +#include +#include +#define realpath(s, dummy) _fullpath((dummy), (s), PATH_MAX) +#define pathcmp(path1, path2, length) strncasecmp(path1, path2, length) +#define mkdir(file_name) (_mkdir(file_name) == 0) +#else +#define pathcmp(path1, path2, length) strncmp(path1, path2, length) +#define mkdir(file_name) (mkdir(file_name, 0755) == 0) +#endif + +#define DIR_SEP_CHAR '/' +#define DIR_SEP_STR "/" +#define notdriveroot(file_name) (file_name[0] != DIR_SEP_CHAR) + #include "../uxn.h" #include "file.h" @@ -140,20 +143,19 @@ retry_realpath(const char *file_name) return NULL; } if(notdriveroot(file_name)) { - /* TODO: use a macro instead of '/' for absolute path first character so that other systems can work */ /* if a relative path, prepend cwd */ getcwd(p, sizeof(p)); if(strlen(p) + strlen(DIR_SEP_STR) + fnlen >= PATH_MAX) { errno = ENAMETOOLONG; return NULL; } - strcat(p, DIR_SEP_STR); /* TODO: use a macro instead of '/' for the path delimiter */ + strcat(p, DIR_SEP_STR); } strcat(p, file_name); while((r = realpath(p, NULL)) == NULL) { if(errno != ENOENT) return NULL; - x = strrchr(p, DIR_SEP_CHAR); /* TODO: path delimiter macro */ + x = strrchr(p, DIR_SEP_CHAR); if(x) *x = '\0'; else @@ -217,19 +219,19 @@ is_dir_path(char *p) { char c; int saw_slash = 0; - while (c = *p++) + while ((c = *p++)) saw_slash = c == DIR_SEP_CHAR; return saw_slash; } -int +static int dir_exists(char *p) { struct stat st; return stat(p, &st) == 0 && S_ISDIR(st.st_mode); } -int +static int ensure_parent_dirs(char *p) { int ok = 1;