]> git.jsancho.org Git - lugaru.git/blobdiff - Source/MacCompatibility.cpp
Oops, Initial forward slash needs to be removed in POSIX file paths
[lugaru.git] / Source / MacCompatibility.cpp
index fa28ba02799049b18a4465a34f7395f718757f7e..4260bddcabf1ad58bbe6b3241a2fbf35a87d87b7 100644 (file)
@@ -1,3 +1,24 @@
+/*
+Copyright (C) 2003, 2010 - Wolfire Games
+
+This file is part of Lugaru.
+
+Lugaru is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*/
+
 #if !PLATFORM_MACOSX
 
 /**> HEADER FILES <**/
@@ -16,6 +37,7 @@
 #if PLATFORM_UNIX
 #include <unistd.h>
 #include <sys/time.h>
+#include <sys/stat.h>
 #include <assert.h>
 typedef long long __int64;
 typedef __int64 LARGE_INTEGER;
@@ -120,9 +142,148 @@ Duration AbsoluteDeltaToDuration( AbsoluteTime& a, AbsoluteTime& b)
 }
 
 
-static char g_filename[ 256];
-char* ConvertFileName( const char* orgfilename)
+#if PLATFORM_UNIX
+#include <sys/types.h>
+#include <pwd.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <dirent.h>
+
+// 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;
+    char **rc;
+    char **i;
+    DIR *dirp;
+
+    //if (PHYSFS_exists(buf))
+    if (access(buf, F_OK) == 0)
+        return(1);  /* quick rejection: exists in current case. */
+
+    ptr = strrchr(buf, '/');  /* find entry at end of path. */
+    if (ptr == NULL)
+    {
+        dirp = opendir(".");
+        ptr = buf;
+    } /* if */
+    else
+    {
+        *ptr = '\0';
+        dirp = opendir(buf);
+        *ptr = '/';
+        ptr++;  /* point past dirsep to entry itself. */
+    } /* else */
+
+    struct dirent *dent;
+    while ((dent = readdir(dirp)) != NULL)
+    {
+        if (strcasecmp(dent->d_name, ptr) == 0)
+        {
+            strcpy(ptr, dent->d_name); /* found a match. Overwrite with this case. */
+            closedir(dirp);
+            return(1);
+        } /* if */
+    } /* for */
+
+    /* no match at all... */
+    closedir(dirp);
+    return(0);
+} /* locateOneElement */
+
+
+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;
+    while (ptr = strchr(ptr + 1, '/'))
+    {
+        *ptr = '\0';  /* block this path section off */
+        rc = locateOneElement(buf);
+        if (!rc)
+        {
+            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);
+}
+
+
+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
+
+// Dummified the function
+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++;
@@ -132,8 +293,15 @@ char* ConvertFileName( const char* orgfilename)
        {
                if (g_filename[ n] == ':')
                        g_filename[ n] = '/';
+
+               else if (g_filename[ n] == '\\')
+                       g_filename[ n] = '/';
        }
 
+    #if PLATFORM_UNIX
+    locateCorrectFile(g_filename, mode);
+    #endif
+
        return g_filename;
 }