X-Git-Url: https://git.jsancho.org/?a=blobdiff_plain;f=Source%2FMacCompatibility.cpp;h=d95664c8b348a6bf2239861cda44d9ab469c45bf;hb=3c8f67c3c66a86fc9e45469ce2fed4222d486c9f;hp=b05d2b91bc27541fbc6ebec0459dce6a648b6685;hpb=68db9594c12cd81dd246c2c0c511a499ac04b2fd;p=lugaru.git diff --git a/Source/MacCompatibility.cpp b/Source/MacCompatibility.cpp index b05d2b9..d95664c 100644 --- a/Source/MacCompatibility.cpp +++ b/Source/MacCompatibility.cpp @@ -16,6 +16,7 @@ #if PLATFORM_UNIX #include #include +#include #include typedef long long __int64; typedef __int64 LARGE_INTEGER; @@ -122,9 +123,13 @@ Duration AbsoluteDeltaToDuration( AbsoluteTime& a, AbsoluteTime& b) #if PLATFORM_UNIX #include +#include +#include +#include #include -// public domain code from PhysicsFS: http://icculus.org/physfs/ +// some but not all of this is code from PhysicsFS: http://icculus.org/physfs/ +// the zlib license on physfs allows this cut-and-pasting. static int locateOneElement(char *buf) { char *ptr; @@ -167,34 +172,97 @@ static int locateOneElement(char *buf) } /* locateOneElement */ -static inline int PHYSFSEXT_locateCorrectCase(char *buf) +static inline const char *getUserDirByUID(void) +{ + struct passwd *pw = getpwuid(getuid()); + if (pw != NULL) + return(pw->pw_dir); + return(NULL); +} /* getUserDirByUID */ + + +static inline const char *getPrefPath(void) +{ + static char *prefpath = NULL; + if (prefpath == NULL) + { + const char *homedir = getenv("HOME"); + if (homedir == NULL) + homedir = getUserDirByUID(); + if (homedir == NULL) + homedir = "."; // oh well. + +#if (defined(__APPLE__) && defined(__MACH__)) + const char *PREFPATHNAME = "Library/Application Support/Lugaru"; +#else + const char *PREFPATHNAME = ".lugaru"; +#endif + size_t len = strlen(homedir) + strlen(PREFPATHNAME) + 2; + prefpath = new char[len]; + snprintf(prefpath, len, "%s/%s", homedir, PREFPATHNAME); + } + return(prefpath); +} + +static int locateCorrectCase(char *buf, bool makedirs) { int rc; char *ptr; char *prevptr; ptr = prevptr = buf; - if (*ptr == '\0') - return(0); /* Uh...I guess that's success. */ - while (ptr = strchr(ptr + 1, '/')) { *ptr = '\0'; /* block this path section off */ rc = locateOneElement(buf); - *ptr = '/'; /* restore path separator */ if (!rc) - return(-2); /* missing element in path. */ + { + if (makedirs) /* normal if we're writing; build dirs! */ + mkdir(buf, S_IRWXU); + else + { + *ptr = '/'; /* restore path separator */ + return(-2); /* missing element in path. */ + } /* else */ + } /* if */ + *ptr = '/'; /* restore path separator */ } /* while */ /* check final element... */ return(locateOneElement(buf) ? 0 : -1); -} /* PHYSFSEXT_locateCorrectCase */ +} + + +static int locateCorrectFile(char *buf, const char *mode) +{ + if (*buf == '\0') + return(0); /* Uh...I guess that's failure. */ + + assert((mode[0] == 'w') || (mode[0] == 'r')); + + bool iswriting = (mode[0] == 'w'); + const char *prefpath = getPrefPath(); + size_t len = strlen(buf) + strlen(prefpath) + 2; + char *prefpathfile = (char *) alloca(len); + snprintf(prefpathfile, len, "%s/%s", prefpath, buf); + + int rc = locateCorrectCase(prefpathfile, iswriting); /* favor prefpath. */ + if ( (rc == 0) || ((rc == -1) && (iswriting)) ) // found or create? + strcpy(buf, prefpathfile); + else if ((rc < 0) && (!iswriting)) /* not writing? Try game dir... */ + rc = locateCorrectCase(buf, iswriting); + + return(rc); +} /* locateCorrectFile */ #endif -static char g_filename[ 256]; -char* ConvertFileName( const char* orgfilename) +static char g_filename[4096]; +char* ConvertFileName( const char* orgfilename, const char *mode) { + if (orgfilename == g_filename) // recursion? + return g_filename; + // translate filename into proper path name if (orgfilename[ 0] == ':') orgfilename++; @@ -204,10 +272,13 @@ char* ConvertFileName( const char* orgfilename) { if (g_filename[ n] == ':') g_filename[ n] = '/'; + + else if (g_filename[ n] == '\\') + g_filename[ n] = '/'; } #if PLATFORM_UNIX - PHYSFSEXT_locateCorrectCase(g_filename); + locateCorrectFile(g_filename, mode); #endif return g_filename;