summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/audio/oal/stream.cpp12
-rw-r--r--src/core/CdStreamPosix.cpp16
-rw-r--r--src/core/FileMgr.cpp37
-rw-r--r--src/fakerw/fake.cpp62
-rw-r--r--src/skel/crossplatform.cpp129
-rw-r--r--src/skel/crossplatform.h6
6 files changed, 132 insertions, 130 deletions
diff --git a/src/audio/oal/stream.cpp b/src/audio/oal/stream.cpp
index 1ffe941e..9fad47a9 100644
--- a/src/audio/oal/stream.cpp
+++ b/src/audio/oal/stream.cpp
@@ -203,15 +203,11 @@ CStream::CStream(char *filename, ALuint &source, ALuint (&buffers)[NUM_STREAMBUF
{
// Be case-insensitive on linux (from https://github.com/OneSadCookie/fcaseopen/)
#if !defined(_WIN32)
- FILE *test = fopen(filename, "r");
- if (!test) {
- char *r = (char*)alloca(strlen(filename) + 4);
- if (casepath(filename, r))
- {
- strcpy(m_aFilename, r);
- }
+ char *real = casepath(filename);
+ if (real) {
+ strcpy(m_aFilename, real);
+ free(real);
} else {
- fclose(test);
#else
{
#endif
diff --git a/src/core/CdStreamPosix.cpp b/src/core/CdStreamPosix.cpp
index 073ba909..45fd9832 100644
--- a/src/core/CdStreamPosix.cpp
+++ b/src/core/CdStreamPosix.cpp
@@ -189,10 +189,11 @@ GetGTA3ImgSize(void)
realpath(gImgNames[0], path);
if (stat(path, &statbuf) == -1) {
// Try case-insensitivity
- char *r = (char*)alloca(strlen(gImgNames[0]) + 4);
- if (casepath(gImgNames[0], r))
+ char* real = casepath(gImgNames[0], false);
+ if (real)
{
- realpath(r, path);
+ realpath(real, path);
+ free(real);
if (stat(path, &statbuf) != -1)
goto ok;
}
@@ -210,7 +211,6 @@ CdStreamShutdown(void)
{
// Destroying semaphores and free(gpReadInfo) will be done at threads
#ifndef ONE_THREAD_PER_CHANNEL
- free(gChannelRequestQ.items);
gCdStreamThreadStatus = 2;
sem_post(&gCdStreamSema);
#endif
@@ -442,6 +442,7 @@ void *CdStreamThread(void *param)
sem_destroy(&gpReadInfo[i].pDoneSemaphore);
}
sem_destroy(&gCdStreamSema);
+ free(gChannelRequestQ.items);
#else
sem_destroy(&gpReadInfo[channel].pStartSemaphore);
sem_destroy(&gpReadInfo[channel].pDoneSemaphore);
@@ -460,10 +461,11 @@ CdStreamAddImage(char const *path)
// Fix case sensitivity and backslashes.
if (gImgFiles[gNumImages] == -1) {
- char *r = (char*)alloca(strlen(path) + 4);
- if (casepath(path, r))
+ char* real = casepath(path, false);
+ if (real)
{
- gImgFiles[gNumImages] = open(r, _gdwCdStreamFlags);
+ gImgFiles[gNumImages] = open(real, _gdwCdStreamFlags);
+ free(real);
}
}
diff --git a/src/core/FileMgr.cpp b/src/core/FileMgr.cpp
index 618874fa..ac51f8de 100644
--- a/src/core/FileMgr.cpp
+++ b/src/core/FileMgr.cpp
@@ -4,6 +4,7 @@
#include <direct.h>
#endif
#include "common.h"
+#include "crossplatform.h"
#include "FileMgr.h"
@@ -31,19 +32,16 @@ static myFILE myfiles[NUMFILES];
#include <dirent.h>
#include <errno.h>
#include <unistd.h>
-#include "crossplatform.h"
#define _getcwd getcwd
// Case-insensitivity on linux (from https://github.com/OneSadCookie/fcaseopen)
void mychdir(char const *path)
{
- char *r = (char*)alloca(strlen(path) + 4);
- if (casepath(path, r))
- {
+ char* r = casepath(path, false);
+ if (r) {
chdir(r);
- }
- else
- {
+ free(r);
+ } else {
errno = ENOENT;
}
}
@@ -73,30 +71,7 @@ found:
*p++ = 'b';
*p = '\0';
-#if !defined(_WIN32)
- char *newPath = strdup(filename);
- // Normally casepath() fixes backslashes, but if the mode is sth other than r/rb it will create new file with backslashes on linux, so fix backslashes here
- char *nextBs;
- while(nextBs = strstr(newPath, "\\")){
- *nextBs = '/';
- }
-#else
- const char *newPath = filename;
-#endif
-
- myfiles[fd].file = fopen(newPath, realmode);
-// Be case-insensitive on linux (from https://github.com/OneSadCookie/fcaseopen/)
-#if !defined(_WIN32)
- if (!myfiles[fd].file) {
- char *r = (char*)alloca(strlen(newPath) + 4);
- if (casepath(newPath, r))
- {
- myfiles[fd].file = fopen(r, realmode);
- }
- }
-
- free(newPath);
-#endif
+ myfiles[fd].file = fcaseopen(filename, realmode);
if(myfiles[fd].file == nil)
return 0;
return fd;
diff --git a/src/fakerw/fake.cpp b/src/fakerw/fake.cpp
index d4417a7f..7d563d77 100644
--- a/src/fakerw/fake.cpp
+++ b/src/fakerw/fake.cpp
@@ -375,23 +375,19 @@ RwStream *RwStreamOpen(RwStreamType type, RwStreamAccessType accessType, const v
file = rwNewT(StreamFile, 1, 0);
memcpy(file, &fakefile, sizeof(StreamFile));
#ifndef _WIN32
- // Be case-insensitive and fix backslashes (from https://github.com/OneSadCookie/fcaseopen/)
- FILE* first = fopen((char*)pData, "r");
- char *r;
- if (!first) {
- r = (char*)alloca(strlen((char*)pData) + 4);
- // Use default path(and pass error handling to librw) if we can't find any match
- if (!casepath((char*)pData, r))
- r = (char*)pData;
+ char *r = casepath((char*)pData);
+ if (r) {
+ if (file->open((char*)r, mode)) {
+ free(r);
+ return file;
+ }
+ free(r);
} else
- fclose(first);
-
- if(file->open((char*)r, mode))
- return file;
-#else
- if(file->open((char*)pData, mode))
- return file;
#endif
+ {
+ if (file->open((char*)pData, mode))
+ return file;
+ }
rwFree(file);
return nil;
}
@@ -859,15 +855,14 @@ RwImage *
RtBMPImageWrite(RwImage *image, const RwChar *imageName)
{
#ifndef _WIN32
- char *r = nil;
- FILE *valid = fopen((char *)imageName, "r");
- if(!valid) {
- char *r = (char *)alloca(strlen((char *)imageName) + 4);
- // Use default path(and pass error handling to librw) if we can't find any match
- if(!casepath((char *)imageName, r)) r = (char *)imageName;
- } else
- fclose(valid);
- rw::writeBMP(image, r);
+ char *r = casepath(imageName);
+ if (r) {
+ rw::writeBMP(image, r);
+ free(r);
+ } else {
+ rw::writeBMP(image, imageName);
+ }
+
#else
rw::writeBMP(image, imageName);
#endif
@@ -877,15 +872,16 @@ RwImage *
RtBMPImageRead(const RwChar *imageName)
{
#ifndef _WIN32
- char *r = nil;
- FILE *valid = fopen((char *)imageName, "r");
- if(!valid) {
- r = (char *)alloca(strlen((char *)imageName) + 4);
- // Use default path(and pass error handling to librw) if we can't find any match
- if(!casepath((char *)imageName, r)) r = (char *)imageName;
- } else
- fclose(valid);
- return rw::readBMP(r);
+ RwImage *image;
+ char *r = casepath(imageName);
+ if (r) {
+ image = rw::readBMP(r);
+ free(r);
+ } else {
+ image = rw::readBMP(imageName);
+ }
+ return image;
+
#else
return rw::readBMP(imageName);
#endif
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
diff --git a/src/skel/crossplatform.h b/src/skel/crossplatform.h
index 268eedff..69600385 100644
--- a/src/skel/crossplatform.h
+++ b/src/skel/crossplatform.h
@@ -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