From 292e1ce9dbfc287fb2f114882878c7342078b886 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Sat, 30 Jan 2021 11:43:53 +0100 Subject: [PATCH] Custom implementation of Realpath() --- src/io.h | 1 + src/realpath.c | 59 +++++++++++++++++++++++++++++++++++++++++++++- src/tests/testio.c | 22 +++++++++++++++++ 3 files changed, 81 insertions(+), 1 deletion(-) diff --git a/src/io.h b/src/io.h index 8f6eb26e..08f38b94 100644 --- a/src/io.h +++ b/src/io.h @@ -37,6 +37,7 @@ #define IO_H__ #include +#include "struct.h" /** @defgroup io File input/output diff --git a/src/realpath.c b/src/realpath.c index 6861e4e5..340aadcf 100644 --- a/src/realpath.c +++ b/src/realpath.c @@ -16,10 +16,67 @@ #endif #if defined(__AROS__) || defined(__BEOS__) || defined(__MORPHOS__) || defined(__GP2X__) || defined(__WIZ__) || defined(__CAANOO__) || defined(__amigaos__) || defined(__SWITCH__) + +#include "io.h" +#include "gfx2log.h" +#include "gfx2mem.h" // These platforms don't have realpath(). +// Our custom implementation uses chdir() and relies on +// errno == ENOTDIR when trying to change directory to a file char *Realpath(const char *_path) { - return strdup(_path); + char * rpath = NULL; + char * current_dir_save; + + // backup current directory + current_dir_save = Get_current_directory(NULL, NULL, 0); + if (current_dir_save == NULL) { + // error + return NULL; + } + + if (chdir(_path) < 0) { + if (errno == ENOTDIR) { + const char * position; + const char * filename; + char * directory; + position = Find_last_separator(_path); + if (position != NULL) { + size_t dirlen = position - _path; + filename = position + 1; + directory = GFX2_malloc(dirlen); + if (directory != NULL) { + memcpy(directory, _path, dirlen); + directory[dirlen] = '\0'; + GFX2_Log(GFX2_DEBUG, "Directory : \"%s\", filename : \"%s\"\n", directory, filename); + if (chdir(directory) == 0) { + char * dirpart = Get_current_directory(NULL, NULL, 0); + if (dirpart != NULL) { + size_t len = strlen(dirpart) + strlen(filename) + 2; + rpath = GFX2_malloc(len); + if (rpath != NULL) { + snprintf(rpath, len, "%s%s%s", dirpart, PATH_SEPARATOR, filename); + } + free(dirpart); + } + } else { + GFX2_Log(GFX2_ERROR, "chdir(\"%s\") : %s\n", directory, strerror(errno)); + } + free(directory); + } + } + } else { + GFX2_Log(GFX2_ERROR, "chdir(\"%s\") : %s\n", _path, strerror(errno)); + } + } else { + // _path is a directory + rpath = Get_current_directory(NULL, NULL, 0); + } + + // "restore" current directory + chdir(current_dir_save); + free(current_dir_save); + return rpath; } #elif defined(__WIN32__) || defined(WIN32) diff --git a/src/tests/testio.c b/src/tests/testio.c index 84d4f0fa..98f46ee2 100644 --- a/src/tests/testio.c +++ b/src/tests/testio.c @@ -306,8 +306,11 @@ int Test_File_exists(char * errmsg) int Test_Realpath(char * errmsg) { + char filepath[256]; char * path; + FILE * f; + // Directory test path = Realpath(tmpdir); if (path == NULL) { @@ -316,6 +319,25 @@ int Test_Realpath(char * errmsg) } GFX2_Log(GFX2_DEBUG, "Realpath(\"%s\") returned \"%s\"\n", tmpdir, path); free(path); + + // File test + snprintf(filepath, sizeof(filepath), "%s/tempfile.txt", tmpdir); + f = fopen(filepath, "w"); + if (f == NULL) { + snprintf(errmsg, ERRMSG_LENGTH, "Failed to create \"%s\"", filepath); + return 0; + } + fputs("TEST\n", f); + fclose(f); + path = Realpath(filepath); + Remove_path(filepath); + if (path == NULL) + { + snprintf(errmsg, ERRMSG_LENGTH, "Realpath(\"%s\") returned NULL", filepath); + return 0; + } + GFX2_Log(GFX2_DEBUG, "Realpath(\"%s\") returned \"%s\"\n", filepath, path); + free(path); return 1; }