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
This commit is contained in:
~d6 2024-09-17 20:32:03 -04:00 committed by d6
parent c3023a4a71
commit 0b974d8997
1 changed files with 25 additions and 23 deletions

View File

@ -8,27 +8,30 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
#ifdef _WIN32
#include <direct.h>
#include <libiberty/libiberty.h>
#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 #ifndef PATH_MAX
#define PATH_MAX 4096 #define PATH_MAX 4096
#endif #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 <direct.h>
#include <libiberty/libiberty.h>
#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 "../uxn.h"
#include "file.h" #include "file.h"
@ -140,20 +143,19 @@ retry_realpath(const char *file_name)
return NULL; return NULL;
} }
if(notdriveroot(file_name)) { 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 */ /* if a relative path, prepend cwd */
getcwd(p, sizeof(p)); getcwd(p, sizeof(p));
if(strlen(p) + strlen(DIR_SEP_STR) + fnlen >= PATH_MAX) { if(strlen(p) + strlen(DIR_SEP_STR) + fnlen >= PATH_MAX) {
errno = ENAMETOOLONG; errno = ENAMETOOLONG;
return NULL; 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); strcat(p, file_name);
while((r = realpath(p, NULL)) == NULL) { while((r = realpath(p, NULL)) == NULL) {
if(errno != ENOENT) if(errno != ENOENT)
return NULL; return NULL;
x = strrchr(p, DIR_SEP_CHAR); /* TODO: path delimiter macro */ x = strrchr(p, DIR_SEP_CHAR);
if(x) if(x)
*x = '\0'; *x = '\0';
else else
@ -217,19 +219,19 @@ is_dir_path(char *p)
{ {
char c; char c;
int saw_slash = 0; int saw_slash = 0;
while (c = *p++) while ((c = *p++))
saw_slash = c == DIR_SEP_CHAR; saw_slash = c == DIR_SEP_CHAR;
return saw_slash; return saw_slash;
} }
int static int
dir_exists(char *p) dir_exists(char *p)
{ {
struct stat st; struct stat st;
return stat(p, &st) == 0 && S_ISDIR(st.st_mode); return stat(p, &st) == 0 && S_ISDIR(st.st_mode);
} }
int static int
ensure_parent_dirs(char *p) ensure_parent_dirs(char *p)
{ {
int ok = 1; int ok = 1;