Rewrote __PHYSFS_platformRealPath() to be Cygwin AND Visual C friendly. I hope.
authorRyan C. Gordon <icculus@icculus.org>
Sat, 01 Sep 2001 23:40:22 +0000
changeset 87 be2efecec922
parent 86 934663982ca9
child 88 1b035d52f000
Rewrote __PHYSFS_platformRealPath() to be Cygwin AND Visual C friendly. I hope. :).
platform/win32.c
--- a/platform/win32.c	Sat Sep 01 23:38:11 2001 +0000
+++ b/platform/win32.c	Sat Sep 01 23:40:22 2001 +0000
@@ -320,16 +320,138 @@
     DWORD buflen = 0;
 
     buflen = GetCurrentDirectory(buflen, NULL);
-    retval = (LPTSTR) malloc(buflen);
+    retval = (LPTSTR) malloc(sizeof (TCHAR) * (buflen + 2));
+    BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
     GetCurrentDirectory(buflen, retval);
+
+    if (retval[buflen - 2] != '\\')
+        strcat(retval, "\\");
+
     return((char *) retval);
 } /* __PHYSFS_platformCurrentDir */
 
 
+/* this could probably use a cleanup. */
 char *__PHYSFS_platformRealPath(const char *path)
 {
-    /* !!! FIXME: This isn't supported on CygWin! */
-    return(_fullpath(NULL, path, MAX_PATH));
+    char *retval = NULL;
+    char *p = NULL;
+
+    BAIL_IF_MACRO(path == NULL, ERR_INVALID_ARGUMENT, NULL);
+    BAIL_IF_MACRO(*path == '\0', ERR_INVALID_ARGUMENT, NULL);
+
+    retval = (char *) malloc(MAX_PATH);
+    BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
+
+        /*
+         * If in \\server\path format, it's already an absolute path.
+         *  We'll need to check for "." and ".." dirs, though, just in case.
+         */
+    if ((path[0] == '\\') && (path[1] == '\\'))
+    {
+        BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
+        strcpy(retval, path);
+    } /* if */
+
+    else
+    {
+        char *currentDir = __PHYSFS_platformCurrentDir();
+        if (currentDir == NULL)
+        {
+            free(retval);
+            BAIL_MACRO(ERR_OUT_OF_MEMORY, NULL);
+        } /* if */
+
+        if (path[1] == ':')   /* drive letter specified? */
+        {
+            /*
+             * Apparently, "D:mypath" is the same as "D:\\mypath" if
+             *  D: is not the current drive. However, if D: is the
+             *  current drive, then "D:mypath" is a relative path. Ugh.
+             */
+            if (path[2] == '\\')  /* maybe an absolute path? */
+                strcpy(retval, path);
+            else  /* definitely an absolute path. */
+            {
+                if (path[0] == currentDir[0]) /* current drive; relative. */
+                {
+                    strcpy(retval, currentDir);
+                    strcat(retval, path + 2);
+                } /* if */
+
+                else  /* not current drive; absolute. */
+                {
+                    retval[0] = path[0];
+                    retval[1] = ':';
+                    retval[2] = '\\';
+                    strcpy(retval + 3, path + 2);
+                } /* else */
+            } /* else */
+        } /* if */
+
+        else  /* no drive letter specified. */
+        {
+            if (path[0] == '\\')  /* absolute path. */
+            {
+                retval[0] = currentDir[0];
+                retval[1] = ':';
+                strcpy(retval + 2, path);
+            } /* if */
+            else
+            {
+                strcpy(retval, currentDir);
+                strcat(retval, path);
+            } /* else */
+        } /* else */
+
+        free(currentDir);
+    } /* else */
+
+    /* (whew.) Ok, now take out "." and ".." path entries... */
+
+    p = retval;
+    while ( (p = strstr(p, "\\.")) != NULL)
+    {
+            /* it's a "." entry that doesn't end the string. */
+        if (p[2] == '\\')
+            memmove(p + 1, p + 3, strlen(p + 3) + 1);
+
+            /* it's a "." entry that ends the string. */
+        else if (p[2] == '\0')
+            p[0] = '\0';
+
+            /* it's a ".." entry. */
+        else if (p[2] == '.')
+        {
+            char *prevEntry = p - 1;
+            while ((prevEntry != retval) && (*prevEntry != '\\'))
+                prevEntry--;
+
+            if (prevEntry == retval)  /* make it look like a "." entry. */
+                memmove(p + 1, p + 2, strlen(p + 2) + 1);
+            else
+            {
+                if (p[3] != '\0') /* doesn't end string. */
+                    *prevEntry = '\0';
+                else /* ends string. */
+                    memmove(prevEntry + 1, p + 4, strlen(p + 4) + 1);
+
+                p = prevEntry;
+            } /* else */
+        } /* else if */
+
+        else
+        {
+            p++;  /* look past current char. */
+        } /* else */
+    } /* while */
+
+        /* shrink the retval's memory block if possible... */
+    p = (char *) realloc(retval, strlen(retval) + 1);
+    if (p != NULL)
+        retval = p;
+
+    return(retval);
 } /* __PHYSFS_platformRealPath */