Custom implementation of Realpath()

This commit is contained in:
Thomas Bernard 2021-01-30 11:43:53 +01:00
parent b9806bfbf3
commit 292e1ce9db
No known key found for this signature in database
GPG Key ID: DB511043A31ACAAF
3 changed files with 81 additions and 1 deletions

View File

@ -37,6 +37,7 @@
#define IO_H__
#include <stdio.h>
#include "struct.h"
/** @defgroup io File input/output

View File

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

View File

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