Initial debugging: dropped PhysicsFS routines into the Build engine,
authorRyan C. Gordon <icculus@icculus.org>
Sun, 08 Jul 2001 13:57:28 +0000
changeset 23 bd6ba9c8717c
parent 22 49f6101707b4
child 24 b050804123a3
Initial debugging: dropped PhysicsFS routines into the Build engine, replacing Ken's groupfile management. Not finished, but lots of initial debugging is complete. More bugs, likely in OUR groupfile code, are waiting to be fixed, but the KenBuild editor runs without crashing (er...but the palette doesn't seem to be loading... :) ) --ryan.
archivers/dir.c
physfs.c
physfs.h
physfs_internal.h
platform/unix.c
--- a/archivers/dir.c	Sun Jul 08 10:58:10 2001 +0000
+++ b/archivers/dir.c	Sun Jul 08 13:57:28 2001 +0000
@@ -107,7 +107,7 @@
 
 static DirHandle *DIR_openArchive(const char *name, int forWriting)
 {
-    const char *dirsep = __PHYSFS_platformDirSeparator;
+    const char *dirsep = PHYSFS_getDirSeparator();
     DirHandle *retval = NULL;
     int namelen = strlen(name);
     int seplen = strlen(dirsep);
@@ -121,7 +121,7 @@
     if (retval->opaque == NULL)
     {
         free(retval);
-        BAIL_IF_MACRO(0, ERR_OUT_OF_MEMORY, NULL);
+        BAIL_IF_MACRO(1, ERR_OUT_OF_MEMORY, NULL);
     } /* if */
 
         /* make sure there's a dir separator at the end of the string */
@@ -195,7 +195,7 @@
     if (!retval)
     {
         free(f);
-        BAIL_IF_MACRO(0, ERR_OUT_OF_MEMORY, NULL);
+        BAIL_IF_MACRO(1, ERR_OUT_OF_MEMORY, NULL);
     } /* if */
 
     errno = 0;
@@ -206,7 +206,7 @@
     if (!rc)
     {
         free(retval);
-        BAIL_IF_MACRO(0, str, NULL);
+        BAIL_IF_MACRO(1, str, NULL);
     } /* if */
 
     retval->opaque = (void *) rc;
--- a/physfs.c	Sun Jul 08 10:58:10 2001 +0000
+++ b/physfs.c	Sun Jul 08 13:57:28 2001 +0000
@@ -11,6 +11,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
 #include <assert.h>
 #include "physfs.h"
 
@@ -276,9 +277,82 @@
 } /* calculateUserDir */
 
 
+static int appendDirSep(char **dir)
+{
+    const char *dirsep = PHYSFS_getDirSeparator();
+    char *ptr;
+
+    if (strcmp((*dir + strlen(*dir)) - strlen(dirsep), dirsep) == 0)
+        return(1);
+
+    ptr = realloc(*dir, strlen(*dir) + strlen(dirsep) + 1);
+    if (!ptr)
+    {
+        free(*dir);
+        return(0);
+    } /* if */
+
+    strcat(ptr, dirsep);
+    *dir = ptr;
+    return(1);
+} /* appendDirSep */
+
+
 static char *calculateBaseDir(const char *argv0)
 {
-assert(0); return(NULL);
+    const char *dirsep = PHYSFS_getDirSeparator();
+    char *retval;
+    char *ptr;
+    int allocSize = 0;
+
+    /*
+     * See if the platform driver wants to handle this for us...
+     */
+    retval = __PHYSFS_platformCalcBaseDir(argv0);
+    if (retval != NULL)
+        return(retval);
+
+    /*
+     * Determine if there's a path on argv0. If there is, that's the base dir.
+     */
+    ptr = strstr(argv0, dirsep);
+    if (ptr != NULL)
+    {
+        char *p = ptr;
+        size_t size;
+        while (p != NULL)
+        {
+            ptr = p;
+            p = strstr(p + 1, dirsep);
+        } /* while */
+
+        size = (size_t) (ptr - argv0);  /* !!! is this portable? */
+        retval = (char *) malloc(size + 1);
+        BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
+        memcpy(retval, argv0, size);
+        retval[size] = '\0';
+        return(retval);
+    } /* if */
+
+    /*
+     * 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);
 } /* calculateBaseDir */
 
 
@@ -289,9 +363,10 @@
 
     baseDir = calculateBaseDir(argv0);
     BAIL_IF_MACRO(baseDir == NULL, NULL, 0);
+    BAIL_IF_MACRO(!appendDirSep(&baseDir), NULL, 0);
 
     userDir = calculateUserDir();
-    if (userDir == NULL)
+    if ((userDir == NULL) || (!appendDirSep(&userDir)))
     {
         free(baseDir);
         baseDir = NULL;
@@ -450,22 +525,25 @@
 
     if (appendToPath)
     {
-        di->next = searchPath;
-        searchPath = di;
-    } /* if */
-    else
-    {
         DirInfo *i = searchPath;
         DirInfo *prev = NULL;
 
         di->next = NULL;
         while (i != NULL)
+        {
             prev = i;
+            i = i->next;
+        } /* while */
 
         if (prev == NULL)
             searchPath = di;
         else
             prev->next = di;
+    } /* if */
+    else
+    {
+        di->next = searchPath;
+        searchPath = di;
     } /* else */
 
     return(1);
@@ -1020,14 +1098,19 @@
 
 PHYSFS_file *PHYSFS_openRead(const char *fname)
 {
-    PHYSFS_file *retval = (PHYSFS_file *) malloc(sizeof (PHYSFS_file));
+    PHYSFS_file *retval;
     FileHandle *rc = NULL;
     FileHandleList *list;
     DirInfo *i;
 
+    retval = (PHYSFS_file *) malloc(sizeof (PHYSFS_file));
     BAIL_IF_MACRO(!retval, ERR_OUT_OF_MEMORY, NULL);
     list = (FileHandleList *) malloc(sizeof (FileHandleList));
-    BAIL_IF_MACRO(!list, ERR_OUT_OF_MEMORY, NULL);
+    if (!list)
+    {
+        free(retval);
+        BAIL_IF_MACRO(1, ERR_OUT_OF_MEMORY, NULL);
+    } /* if */
 
     for (i = searchPath; i != NULL; i = i->next)
     {
--- a/physfs.h	Sun Jul 08 10:58:10 2001 +0000
+++ b/physfs.h	Sun Jul 08 13:57:28 2001 +0000
@@ -200,6 +200,9 @@
  * Initialize PhysicsFS. This must be called before any other PhysicsFS
  *  function.
  *
+ * This should be called prior to any attempts to change your process's
+ *  current working directory.
+ *
  *   @param argv0 the argv[0] string passed to your program's mainline.
  *  @return nonzero on success, zero on error. Specifics of the error can be
  *          gleaned from PHYSFS_getLastError().
--- a/physfs_internal.h	Sun Jul 08 10:58:10 2001 +0000
+++ b/physfs_internal.h	Sun Jul 08 13:57:28 2001 +0000
@@ -316,7 +316,7 @@
  *  calculateBaseDir() in physfs.c ...)
  *  Caller will free() the retval if it's not NULL.
  */
-char *__PHYSFS_platformCalcBaseDir(char *argv0);
+char *__PHYSFS_platformCalcBaseDir(const char *argv0);
 
 /*
  * Get the platform-specific user name.
--- a/platform/unix.c	Sun Jul 08 10:58:10 2001 +0000
+++ b/platform/unix.c	Sun Jul 08 13:57:28 2001 +0000
@@ -57,12 +57,6 @@
 } /* __PHYSFS_detectAvailableCDs */
 
 
-char *__PHYSFS_platformCalcBaseDir(char *argv0)
-{
-    return(NULL);  /* default PhysicsFS behaviour is acceptable. */
-} /* __PHYSFS_platformCalcBaseDir */
-
-
 static char *copyEnvironmentVariable(const char *varname)
 {
     const char *envr = getenv(varname);
@@ -79,6 +73,57 @@
 } /* copyEnvironmentVariable */
 
 
+/* !!! this is ugly. */
+char *__PHYSFS_platformCalcBaseDir(const char *argv0)
+{
+    /* If there isn't a path on argv0, then look through the $PATH for it. */
+
+    char *retval = NULL;
+    char *envr;
+    char *start;
+    char *ptr;
+    char *exe;
+
+    if (strchr(argv0, '/') != NULL)   /* default behaviour can handle this. */
+        return(NULL);
+
+    envr = copyEnvironmentVariable("PATH");
+    BAIL_IF_MACRO(!envr, NULL, NULL);
+
+    start = envr;
+    do
+    {
+        ptr = strchr(start, ':');
+        if (ptr)
+            *ptr = '\0';
+
+        exe = (char *) malloc(strlen(start) + strlen(argv0) + 2);
+        if (!exe)
+        {
+            free(envr);
+            BAIL_IF_MACRO(1, ERR_OUT_OF_MEMORY, NULL);
+        } /* if */
+        strcpy(exe, start);
+        if (start[strlen(start) - 1] != '/')
+            strcat(start, "/");
+        strcat(start, argv0);
+        if (access(exe, X_OK) != 0)
+            free(exe);
+        else
+        {
+            retval = exe;
+            strcpy(retval, start);  /* i'm lazy. piss off. */
+            break;
+        } /* else */
+
+        start = ptr + 1;
+    } while (ptr != NULL);
+
+    free(envr);
+    return(retval);
+} /* __PHYSFS_platformCalcBaseDir */
+
+
 static char *getUserNameByUID(void)
 {
     uid_t uid = getuid();