mirror of
https://github.com/halpz/re3.git
synced 2025-06-28 17:16:19 +00:00
Fix casepath chaos
This commit is contained in:
@ -87,7 +87,7 @@ void FileTimeToSystemTime(time_t* writeTime, SYSTEMTIME* out) {
|
||||
// Funcs/features from Windows that we need on other platforms
|
||||
#ifndef _WIN32
|
||||
char *strupr(char *s) {
|
||||
char* tmp = s;
|
||||
char* tmp = s;
|
||||
|
||||
for (;*tmp;++tmp) {
|
||||
*tmp = toupper((unsigned char) *tmp);
|
||||
@ -96,7 +96,7 @@ char *strupr(char *s) {
|
||||
return s;
|
||||
}
|
||||
char *strlwr(char *s) {
|
||||
char* tmp = s;
|
||||
char* tmp = s;
|
||||
|
||||
for (;*tmp;++tmp) {
|
||||
*tmp = tolower((unsigned char) *tmp);
|
||||
@ -116,86 +116,117 @@ char *trim(char *s) {
|
||||
return s;
|
||||
}
|
||||
|
||||
// Case-insensitivity on linux (from https://github.com/OneSadCookie/fcaseopen)
|
||||
// r must have strlen(path) + 2 bytes
|
||||
int casepath(char const *path, char *r)
|
||||
FILE* _fcaseopen(char const* filename, char const* mode)
|
||||
{
|
||||
FILE* result;
|
||||
char* real = casepath(filename);
|
||||
if (!real)
|
||||
result = fopen(filename, mode);
|
||||
else {
|
||||
result = fopen(real, mode);
|
||||
free(real);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Case-insensitivity on linux (from https://github.com/OneSadCookie/fcaseopen)
|
||||
// Returned string should freed manually (if exists)
|
||||
char* casepath(char const* path, bool checkPathFirst)
|
||||
{
|
||||
if (checkPathFirst && access(path, F_OK) != -1) {
|
||||
// File path is correct
|
||||
return nil;
|
||||
}
|
||||
|
||||
size_t l = strlen(path);
|
||||
char *p = (char*)alloca(l + 1);
|
||||
char* p = (char*)alloca(l + 1);
|
||||
char* out = (char*)malloc(l + 3); // for extra ./
|
||||
strcpy(p, path);
|
||||
|
||||
// my addon: change \'s with /
|
||||
char *nextBs;
|
||||
while(nextBs = strstr(p, "\\")){
|
||||
*nextBs = '/';
|
||||
}
|
||||
|
||||
// my addon: linux doesn't handle filenames with spaces at the end nicely
|
||||
p = trim(p);
|
||||
// my addon: linux doesn't handle filenames with spaces at the end nicely
|
||||
p = trim(p);
|
||||
|
||||
size_t rl = 0;
|
||||
|
||||
DIR *d;
|
||||
if (p[0] == '/')
|
||||
|
||||
DIR* d;
|
||||
if (p[0] == '/' || p[0] == '\\')
|
||||
{
|
||||
d = opendir("/");
|
||||
p = p + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
d = opendir(".");
|
||||
r[0] = '.';
|
||||
r[1] = 0;
|
||||
out[0] = '.';
|
||||
out[1] = 0;
|
||||
rl = 1;
|
||||
}
|
||||
|
||||
int last = 0;
|
||||
char *c = strsep(&p, "/");
|
||||
while (c)
|
||||
|
||||
bool cantProceed = false; // just convert slashes in what's left in string, not case sensitivity
|
||||
bool mayBeTrailingSlash = false;
|
||||
char* c;
|
||||
while (c = strsep(&p, "/\\"))
|
||||
{
|
||||
if (!d)
|
||||
// May be trailing slash(allow), slash at the start(avoid), or multiple slashes(avoid)
|
||||
if (*c == '\0')
|
||||
{
|
||||
return 0;
|
||||
mayBeTrailingSlash = true;
|
||||
continue;
|
||||
} else {
|
||||
mayBeTrailingSlash = false;
|
||||
}
|
||||
|
||||
if (last)
|
||||
{
|
||||
closedir(d);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r[rl] = '/';
|
||||
|
||||
out[rl] = '/';
|
||||
rl += 1;
|
||||
r[rl] = 0;
|
||||
|
||||
struct dirent *e = readdir(d);
|
||||
while (e)
|
||||
out[rl] = 0;
|
||||
|
||||
if (cantProceed)
|
||||
{
|
||||
strcpy(out + rl, c);
|
||||
rl += strlen(c);
|
||||
continue;
|
||||
}
|
||||
|
||||
struct dirent* e;
|
||||
while (e = readdir(d))
|
||||
{
|
||||
if (strcasecmp(c, e->d_name) == 0)
|
||||
{
|
||||
strcpy(r + rl, e->d_name);
|
||||
rl += strlen(e->d_name);
|
||||
strcpy(out + rl, e->d_name);
|
||||
int reportedLen = (int)strlen(e->d_name);
|
||||
rl += reportedLen;
|
||||
assert(reportedLen == strlen(c) && "casepath: This is not good at all");
|
||||
|
||||
closedir(d);
|
||||
d = opendir(r);
|
||||
|
||||
d = opendir(out);
|
||||
|
||||
// Either it wasn't a folder, or permission error, I/O error etc.
|
||||
if (!d) {
|
||||
cantProceed = true;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
e = readdir(d);
|
||||
}
|
||||
|
||||
|
||||
if (!e)
|
||||
{
|
||||
strcpy(r + rl, c);
|
||||
printf("casepath couldn't find dir/file \"%s\", full path was %s\n", c, path);
|
||||
// No match, add original name and continue converting further slashes.
|
||||
strcpy(out + rl, c);
|
||||
rl += strlen(c);
|
||||
last = 1;
|
||||
cantProceed = true;
|
||||
}
|
||||
|
||||
c = strsep(&p, "/");
|
||||
}
|
||||
|
||||
|
||||
if (d) closedir(d);
|
||||
return 1;
|
||||
if (mayBeTrailingSlash) {
|
||||
out[rl] = '/'; rl += 1;
|
||||
out[rl] = '\0';
|
||||
}
|
||||
|
||||
if (rl > l + 2) {
|
||||
printf("\n\ncasepath: Corrected path length is longer then original+2:\n\tOriginal: %s (%d chars)\n\tCorrected: %s (%d chars)\n\n", path, l, out, rl);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
#endif
|
||||
|
@ -23,7 +23,7 @@ enum eWinVersion
|
||||
#include "win.h"
|
||||
#endif
|
||||
extern DWORD _dwOperatingSystemVersion;
|
||||
|
||||
#define fcaseopen fopen
|
||||
#else
|
||||
char *strupr(char *str);
|
||||
char *strlwr(char *str);
|
||||
@ -43,7 +43,9 @@ enum {
|
||||
};
|
||||
|
||||
extern long _dwOperatingSystemVersion;
|
||||
int casepath(char const *path, char *r);
|
||||
char *casepath(char const *path, bool checkPathFirst = true);
|
||||
FILE *_fcaseopen(char const *filename, char const *mode);
|
||||
#define fcaseopen _fcaseopen
|
||||
#endif
|
||||
|
||||
#ifdef RW_GL3
|
||||
|
Reference in New Issue
Block a user