summaryrefslogtreecommitdiffstats
path: root/src/skel/crossplatform.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/skel/crossplatform.cpp')
-rw-r--r--src/skel/crossplatform.cpp129
1 files changed, 80 insertions, 49 deletions
diff --git a/src/skel/crossplatform.cpp b/src/skel/crossplatform.cpp
index 40f4f053..6188992d 100644
--- a/src/skel/crossplatform.cpp
+++ b/src/skel/crossplatform.cpp
@@ -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;
}
+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)
-// r must have strlen(path) + 2 bytes
-int casepath(char const *path, char *r)
+// 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)
+
+ out[rl] = '/';
+ rl += 1;
+ out[rl] = 0;
+
+ if (cantProceed)
{
- closedir(d);
- return 0;
+ strcpy(out + rl, c);
+ rl += strlen(c);
+ continue;
}
-
- r[rl] = '/';
- rl += 1;
- r[rl] = 0;
-
- struct dirent *e = readdir(d);
- while (e)
+
+ 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