Lots of bugfixes, enhancements, and corrections due to the work on
authorRyan C. Gordon <icculus@icculus.org>
Mon, 16 Jul 2001 14:36:02 +0000
changeset 39 bc29e1ee7ef6
parent 38 feb16343f44c
child 40 8cc16df4bada
Lots of bugfixes, enhancements, and corrections due to the work on test_physfs exposing problems.
archivers/grp.c
archivers/zip.c
physfs.c
physfs.h
physfs_internal.h
platform/unix.c
--- a/archivers/grp.c	Mon Jul 16 10:32:12 2001 +0000
+++ b/archivers/grp.c	Mon Jul 16 14:36:02 2001 +0000
@@ -222,7 +222,7 @@
         buf[12] = '\0';  /* FILENAME.EXT is all you get. */
 
         l = (LinkedStringList *) malloc(sizeof (LinkedStringList));
-        if (l != NULL)
+        if (l == NULL)
             break;
 
         l->str = (char *) malloc(strlen(buf) + 1);
@@ -232,6 +232,8 @@
             break;
         } /* if */
 
+        strcpy(l->str, buf);
+
         if (retval == NULL)
             retval = l;
         else
--- a/archivers/zip.c	Mon Jul 16 10:32:12 2001 +0000
+++ b/archivers/zip.c	Mon Jul 16 14:36:02 2001 +0000
@@ -162,7 +162,7 @@
         } /* else */
 
         l = (LinkedStringList *) malloc(sizeof (LinkedStringList));
-        if (l != NULL)
+        if (l == NULL)
             break;
 
         l->str = (char *) malloc(strlen(ptr) + 1);
@@ -172,6 +172,8 @@
             break;
         } /* if */
 
+        strcpy(l->str, ptr);
+
         if (retval == NULL)
             retval = l;
         else
--- a/physfs.c	Mon Jul 16 10:32:12 2001 +0000
+++ b/physfs.c	Mon Jul 16 14:36:02 2001 +0000
@@ -11,7 +11,11 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
 #include <unistd.h>
+#include <errno.h>
 #include <assert.h>
 #include "physfs.h"
 
@@ -303,7 +307,6 @@
     const char *dirsep = PHYSFS_getDirSeparator();
     char *retval;
     char *ptr;
-    int allocSize = 0;
 
     /*
      * See if the platform driver wants to handle this for us...
@@ -337,35 +340,34 @@
     /*
      * Last ditch effort: it's the current working directory. (*shrug*)
      */
-    do
-    {
-        allocSize += 100;
-        ptr = (char *) realloc(retval, allocSize);
-        if (ptr == NULL)
-        {
-            if (retval != NULL)
-                free(retval);
-            BAIL_IF_MACRO(1, ERR_OUT_OF_MEMORY, NULL);
-        } /* if */
-
-        retval = ptr;
-        ptr = getcwd(retval, allocSize);
-    } while (ptr == NULL);
-
-    return(retval);
+    return(__PHYSFS_platformCurrentDir());
 } /* calculateBaseDir */
 
 
 int PHYSFS_init(const char *argv0)
 {
+    char *ptr;
+
     BAIL_IF_MACRO(initialized, ERR_IS_INITIALIZED, 0);
     BAIL_IF_MACRO(argv0 == NULL, ERR_INVALID_ARGUMENT, 0);
 
     baseDir = calculateBaseDir(argv0);
     BAIL_IF_MACRO(baseDir == NULL, NULL, 0);
+    ptr = __PHYSFS_platformRealPath(baseDir);
+    free(baseDir);
+    BAIL_IF_MACRO(ptr == NULL, NULL, 0);
+    baseDir = ptr;
+
     BAIL_IF_MACRO(!appendDirSep(&baseDir), NULL, 0);
 
     userDir = calculateUserDir();
+    if (userDir != NULL)
+    {
+        ptr = __PHYSFS_platformRealPath(userDir);
+        free(userDir);
+        userDir = ptr;
+    } /* if */
+
     if ((userDir == NULL) || (!appendDirSep(&userDir)))
     {
         free(baseDir);
@@ -624,15 +626,30 @@
     const char *userdir = PHYSFS_getUserDir();
     const char *dirsep = PHYSFS_getDirSeparator();
     char *str;
-    int rc;
 
         /* set write dir... */
     str = malloc(strlen(userdir) + (strlen(appName) * 2) +
                  (strlen(dirsep) * 2) + 2);
     BAIL_IF_MACRO(str == NULL, ERR_OUT_OF_MEMORY, 0);
-    sprintf(str, "%s%s.%s", userdir, dirsep, appName);
-    rc = PHYSFS_setWriteDir(str);
-    BAIL_IF_MACRO(!rc, NULL, 0);
+    sprintf(str, "%s.%s", userdir, appName);
+
+    if (!PHYSFS_setWriteDir(str))
+    {
+        if ( (!PHYSFS_setWriteDir(userdir)) ||
+             (!PHYSFS_mkdir(str + strlen(userdir))) )
+        {
+            PHYSFS_setWriteDir(NULL);
+            free(str);
+            BAIL_IF_MACRO(1, ERR_CANT_SET_WRITE_DIR, 0);
+        } /* if */
+    } /* if */
+
+    if (!PHYSFS_setWriteDir(str))
+    {
+        PHYSFS_setWriteDir(NULL);
+        free(str);
+        BAIL_IF_MACRO(1, ERR_CANT_SET_WRITE_DIR, 0);
+    } /* if */
 
         /* Put write dir related dirs on search path... */
     PHYSFS_addToSearchPath(str, 1);
@@ -648,7 +665,7 @@
                  (strlen(dirsep) * 2) + 2);
     if (str != NULL)
     {
-        sprintf(str, "%s%s.%s", basedir, dirsep, appName);
+        sprintf(str, "%s.%s", basedir, appName);
         PHYSFS_addToSearchPath(str, 1);
         free(str);
     } /* if */
@@ -725,6 +742,9 @@
     char *i2;
     size_t allocSize;
 
+    while (*dirName == '/')
+        dirName++;
+
     allocSize = strlen(dirName) + 1;
     if (prepend != NULL)
         allocSize += strlen(prepend) + sepsize;
@@ -836,7 +856,12 @@
     int retval = 0;
 
     BAIL_IF_MACRO(writeDir == NULL, ERR_NO_WRITE_DIR, 0);
+
     h = writeDir->dirHandle;
+
+    while (*dirName == '/')
+        dirName++;
+
     BAIL_IF_MACRO(h->funcs->mkdir == NULL, ERR_NOT_SUPPORTED, 0);
     BAIL_IF_MACRO(!__PHYSFS_verifySecurity(h, dirName), NULL, 0);
 
@@ -872,6 +897,10 @@
     BAIL_IF_MACRO(writeDir == NULL, ERR_NO_WRITE_DIR, 0);
     h = writeDir->dirHandle;
     BAIL_IF_MACRO(h->funcs->remove == NULL, ERR_NOT_SUPPORTED, 0);
+
+    while (*fname == '/')
+        fname++;
+
     BAIL_IF_MACRO(!__PHYSFS_verifySecurity(h, fname), NULL, 0);
     return(h->funcs->remove(h, fname));
 } /* PHYSFS_delete */
@@ -881,6 +910,9 @@
 {
     DirInfo *i;
 
+    while (*filename == '/')
+        filename++;
+
     for (i = searchPath; i != NULL; i = i->next)
     {
         DirHandle *h = i->dirHandle;
@@ -900,8 +932,6 @@
     int retval = 0;
     LinkedStringList *i;
 
-    assert(list != NULL);
-
     for (i = list; i != NULL; i = i->next)
         retval++;
 
@@ -947,23 +977,27 @@
     for (i = *final; i != NULL; i = i->next)
     {
         rc = strcmp(i->str, item->str);
-        if (rc == 0)      /* already in list. */
+        if (rc > 0)  /* insertion point. */
+            break;
+        else if (rc == 0)      /* already in list. */
         {
             free(item->str);
             free(item);
             return;
-        } /* if */
-        else if (rc > 0)  /* insertion point. */
-        {
-            if (prev == NULL)
-                *final = item;
-            else
-                prev->next = item;
-            item->next = i;
-            return;
         } /* else if */
         prev = i;
     } /* for */
+
+        /*
+         * If we are here, we are either at the insertion point.
+         *  This may be the end of the list, or the list may be empty, too.
+         */
+    if (prev == NULL)
+        *final = item;
+    else
+        prev->next = item;
+
+    item->next = i;
 } /* insertStringListItem */
 
 
@@ -989,6 +1023,9 @@
     LinkedStringList *rc;
     LinkedStringList *finalList = NULL;
 
+    while (*path == '/')
+        path++;
+
     for (i = searchPath; i != NULL; i = i->next)
     {
         DirHandle *h = i->dirHandle;
@@ -1006,6 +1043,9 @@
 
 int PHYSFS_exists(const char *fname)
 {
+    while (*fname == '/')
+        fname++;
+
     return(PHYSFS_getRealDir(fname) != NULL);
 } /* PHYSFS_exists */
 
@@ -1014,6 +1054,9 @@
 {
     DirInfo *i;
 
+    while (*fname == '/')
+        fname++;
+
     for (i = searchPath; i != NULL; i = i->next)
     {
         DirHandle *h = i->dirHandle;
@@ -1035,6 +1078,9 @@
     if (!allowSymLinks)
         return(0);
 
+    while (*fname == '/')
+        fname++;
+
     for (i = searchPath; i != NULL; i = i->next)
     {
         DirHandle *h = i->dirHandle;
@@ -1057,6 +1103,9 @@
     const DirFunctions *f = (h == NULL) ? NULL : h->funcs;
     FileHandleList *list;
 
+    while (*fname == '/')
+        fname++;
+
     BAIL_IF_MACRO(!h, ERR_NO_WRITE_DIR, NULL);
     BAIL_IF_MACRO(!__PHYSFS_verifySecurity(h, fname), NULL, NULL);
 
@@ -1097,6 +1146,9 @@
     FileHandleList *list;
     DirInfo *i;
 
+    while (*fname == '/')
+        fname++;
+
     list = (FileHandleList *) malloc(sizeof (FileHandleList));
     BAIL_IF_MACRO(!list, ERR_OUT_OF_MEMORY, NULL);
 
--- a/physfs.h	Mon Jul 16 10:32:12 2001 +0000
+++ b/physfs.h	Mon Jul 16 14:36:02 2001 +0000
@@ -313,6 +313,10 @@
  *  unless you feel there's a specific danger in allowing them, you should
  *  permit them.
  *
+ * Symlinks are only explicitly checked when dealing with filenames
+ *  in platform-independent notation. That is, when setting up your
+ *  search and write paths, etc, symlinks are never checked for.
+ *
  * Symbolic link permission can be enabled or disabled at any time, and is
  *  disabled by default.
  *
--- a/physfs_internal.h	Mon Jul 16 10:32:12 2001 +0000
+++ b/physfs_internal.h	Mon Jul 16 14:36:02 2001 +0000
@@ -249,6 +249,8 @@
 #define ERR_PAST_EOF             "Past end of file"
 #define ERR_ARC_IS_READ_ONLY     "Archive is read-only"
 #define ERR_IO_ERROR             "I/O error"
+#define ERR_CANT_SET_WRITE_DIR   "Can't set write directory."
+
 
 /*
  * Call this to set the message returned by PHYSFS_getLastError().
@@ -417,6 +419,29 @@
 int __PHYSFS_platformFileLength(FILE *handle);
 
 
+/*
+ * Get the current working directory. The return value should be an
+ *  absolute path in platform-dependent notation. The caller will deallocate
+ *  the return value with the standard C runtime free() function when it
+ *  is done with it.
+ * On error, return NULL and set the error message.
+ */
+char *__PHYSFS_platformCurrentDir(void);
+
+
+/*
+ * Get the real physical path to a file. (path) is specified in
+ *  platform-dependent notation, as should your return value be.
+ *  All relative paths should be removed, leaving you with an absolute
+ *  path. Symlinks should be resolved, too, so that the returned value is
+ *  the most direct path to a file.
+ * The return value will be deallocated with the standard C runtime free()
+ *  function when the caller is done with it.
+ * On error, return NULL and set the error message.
+ */
+char *__PHYSFS_platformRealPath(const char *path);
+
+
 #ifdef __cplusplus
 extern "C" {
 #endif
--- a/platform/unix.c	Mon Jul 16 10:32:12 2001 +0000
+++ b/platform/unix.c	Mon Jul 16 14:36:02 2001 +0000
@@ -35,6 +35,7 @@
 #include <sys/types.h>
 #include <pwd.h>
 #include <sys/stat.h>
+#include <sys/param.h>
 #include <dirent.h>
 #include <time.h>
 #include <errno.h>
@@ -303,8 +304,14 @@
         if (ent == NULL)   /* we're done. */
             break;
 
+        if (strcmp(ent->d_name, ".") == 0)
+            continue;
+
+        if (strcmp(ent->d_name, "..") == 0)
+            continue;
+
         l = (LinkedStringList *) malloc(sizeof (LinkedStringList));
-        if (l != NULL)
+        if (l == NULL)
             break;
 
         l->str = (char *) malloc(strlen(ent->d_name) + 1);
@@ -314,6 +321,8 @@
             break;
         } /* if */
 
+        strcpy(l->str, ent->d_name);
+
         if (retval == NULL)
             retval = l;
         else
@@ -337,5 +346,43 @@
 } /* __PHYSFS_platformFileLength */
 
 
+char *__PHYSFS_platformCurrentDir(void)
+{
+    int allocSize = 0;
+    char *retval = NULL;
+    char *ptr;
+
+    do
+    {
+        allocSize += 100;
+        ptr = (char *) realloc(retval, allocSize);
+        if (ptr == NULL)
+        {
+            if (retval != NULL)
+                free(retval);
+            BAIL_IF_MACRO(1, ERR_OUT_OF_MEMORY, NULL);
+        } /* if */
+
+        retval = ptr;
+        ptr = getcwd(retval, allocSize);
+    } while (ptr == NULL);
+
+    return(retval);
+} /* __PHYSFS_platformCurrentDir */
+
+
+char *__PHYSFS_platformRealPath(const char *path)
+{
+    char resolved_path[MAXPATHLEN];
+    char *retval = NULL;
+
+    errno = 0;
+    BAIL_IF_MACRO(!realpath(path, resolved_path), strerror(errno), NULL);
+    retval = malloc(strlen(resolved_path) + 1);
+    BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
+    strcpy(retval, resolved_path);
+    return(retval);
+} /* __PHYSFS_platformRealPath */
+
 /* end of unix.c ... */