From f97faa279e9c1b29ed95d60b2fc945fbe9883f43 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Sun, 8 Jul 2001 13:57:28 +0000 Subject: [PATCH] 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 | 8 ++-- physfs.c | 101 +++++++++++++++++++++++++++++++++++++++++----- physfs.h | 3 ++ physfs_internal.h | 2 +- platform/unix.c | 57 +++++++++++++++++++++++--- 5 files changed, 151 insertions(+), 20 deletions(-) diff --git a/archivers/dir.c b/archivers/dir.c index 59393b2f..65df3268 100644 --- a/archivers/dir.c +++ b/archivers/dir.c @@ -107,7 +107,7 @@ static int DIR_isArchive(const char *filename, int forWriting) 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 @@ static DirHandle *DIR_openArchive(const char *name, int forWriting) 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 @@ static FileHandle *doOpen(DirHandle *h, const char *name, const char *mode) 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 @@ static FileHandle *doOpen(DirHandle *h, const char *name, const char *mode) if (!rc) { free(retval); - BAIL_IF_MACRO(0, str, NULL); + BAIL_IF_MACRO(1, str, NULL); } /* if */ retval->opaque = (void *) rc; diff --git a/physfs.c b/physfs.c index d6c6e3ab..41ac0df4 100644 --- a/physfs.c +++ b/physfs.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include "physfs.h" @@ -276,9 +277,82 @@ static char *calculateUserDir(void) } /* 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 @@ int PHYSFS_init(const char *argv0) 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; @@ -449,23 +524,26 @@ int PHYSFS_addToSearchPath(const char *newDir, int appendToPath) BAIL_IF_MACRO(di == NULL, NULL, 0); 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_openAppend(const char *filename) 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) { diff --git a/physfs.h b/physfs.h index 17b70095..4d0e5f87 100644 --- a/physfs.h +++ b/physfs.h @@ -200,6 +200,9 @@ void PHYSFS_getLinkedVersion(PHYSFS_Version *ver); * 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(). diff --git a/physfs_internal.h b/physfs_internal.h index 3f7d3752..24175e7c 100644 --- a/physfs_internal.h +++ b/physfs_internal.h @@ -316,7 +316,7 @@ char **__PHYSFS_platformDetectAvailableCDs(void); * 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. diff --git a/platform/unix.c b/platform/unix.c index fd69911e..5941ab0c 100644 --- a/platform/unix.c +++ b/platform/unix.c @@ -57,12 +57,6 @@ char **__PHYSFS_platformDetectAvailableCDs(void) } /* __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 @@ static char *copyEnvironmentVariable(const char *varname) } /* 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();