From 7d90c12f744678e4d6ad053ba9f86cbfd6883e79 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Mon, 16 Jul 2001 14:36:02 +0000 Subject: [PATCH] Lots of bugfixes, enhancements, and corrections due to the work on test_physfs exposing problems. --- archivers/grp.c | 4 +- archivers/zip.c | 4 +- physfs.c | 120 +++++++++++++++++++++++++++++++++------------- physfs.h | 4 ++ physfs_internal.h | 25 ++++++++++ platform/unix.c | 49 ++++++++++++++++++- 6 files changed, 169 insertions(+), 37 deletions(-) diff --git a/archivers/grp.c b/archivers/grp.c index 276e6dd6..dc96de55 100644 --- a/archivers/grp.c +++ b/archivers/grp.c @@ -222,7 +222,7 @@ static LinkedStringList *GRP_enumerateFiles(DirHandle *h, const char *dirname) 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 @@ static LinkedStringList *GRP_enumerateFiles(DirHandle *h, const char *dirname) break; } /* if */ + strcpy(l->str, buf); + if (retval == NULL) retval = l; else diff --git a/archivers/zip.c b/archivers/zip.c index 20c7a113..09b252e1 100644 --- a/archivers/zip.c +++ b/archivers/zip.c @@ -162,7 +162,7 @@ static LinkedStringList *ZIP_enumerateFiles(DirHandle *h, const char *dirname) } /* else */ l = (LinkedStringList *) malloc(sizeof (LinkedStringList)); - if (l != NULL) + if (l == NULL) break; l->str = (char *) malloc(strlen(ptr) + 1); @@ -172,6 +172,8 @@ static LinkedStringList *ZIP_enumerateFiles(DirHandle *h, const char *dirname) break; } /* if */ + strcpy(l->str, ptr); + if (retval == NULL) retval = l; else diff --git a/physfs.c b/physfs.c index 8d068ada..8c70ce53 100644 --- a/physfs.c +++ b/physfs.c @@ -11,7 +11,11 @@ #include #include #include +#include +#include +#include #include +#include #include #include "physfs.h" @@ -303,7 +307,6 @@ static char *calculateBaseDir(const char *argv0) 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 @@ static char *calculateBaseDir(const char *argv0) /* * 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 @@ int PHYSFS_setSaneConfig(const char *appName, const char *archiveExt, 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 @@ int PHYSFS_setSaneConfig(const char *appName, const char *archiveExt, (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 *__PHYSFS_convertToDependent(const char *prepend, char *i2; size_t allocSize; + while (*dirName == '/') + dirName++; + allocSize = strlen(dirName) + 1; if (prepend != NULL) allocSize += strlen(prepend) + sepsize; @@ -836,7 +856,12 @@ int PHYSFS_mkdir(const char *dirName) 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 @@ int PHYSFS_delete(const char *fname) 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 @@ const char *PHYSFS_getRealDir(const char *filename) { DirInfo *i; + while (*filename == '/') + filename++; + for (i = searchPath; i != NULL; i = i->next) { DirHandle *h = i->dirHandle; @@ -900,8 +932,6 @@ static int countList(LinkedStringList *list) int retval = 0; LinkedStringList *i; - assert(list != NULL); - for (i = list; i != NULL; i = i->next) retval++; @@ -947,23 +977,27 @@ static void insertStringListItem(LinkedStringList **final, 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 @@ char **PHYSFS_enumerateFiles(const char *path) LinkedStringList *rc; LinkedStringList *finalList = NULL; + while (*path == '/') + path++; + for (i = searchPath; i != NULL; i = i->next) { DirHandle *h = i->dirHandle; @@ -1006,6 +1043,9 @@ char **PHYSFS_enumerateFiles(const char *path) int PHYSFS_exists(const char *fname) { + while (*fname == '/') + fname++; + return(PHYSFS_getRealDir(fname) != NULL); } /* PHYSFS_exists */ @@ -1014,6 +1054,9 @@ int PHYSFS_isDirectory(const char *fname) { DirInfo *i; + while (*fname == '/') + fname++; + for (i = searchPath; i != NULL; i = i->next) { DirHandle *h = i->dirHandle; @@ -1035,6 +1078,9 @@ int PHYSFS_isSymbolicLink(const char *fname) if (!allowSymLinks) return(0); + while (*fname == '/') + fname++; + for (i = searchPath; i != NULL; i = i->next) { DirHandle *h = i->dirHandle; @@ -1057,6 +1103,9 @@ static PHYSFS_file *doOpenWrite(const char *fname, int appending) 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 @@ PHYSFS_file *PHYSFS_openRead(const char *fname) FileHandleList *list; DirInfo *i; + while (*fname == '/') + fname++; + list = (FileHandleList *) malloc(sizeof (FileHandleList)); BAIL_IF_MACRO(!list, ERR_OUT_OF_MEMORY, NULL); diff --git a/physfs.h b/physfs.h index fc86ed0c..55990ee6 100644 --- a/physfs.h +++ b/physfs.h @@ -313,6 +313,10 @@ const char *PHYSFS_getDirSeparator(void); * 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. * diff --git a/physfs_internal.h b/physfs_internal.h index 0282e2ab..38e86289 100644 --- a/physfs_internal.h +++ b/physfs_internal.h @@ -249,6 +249,8 @@ typedef struct __PHYSFS_DIRFUNCTIONS__ #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 @@ LinkedStringList *__PHYSFS_platformEnumerateFiles(const char *dirname); 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 diff --git a/platform/unix.c b/platform/unix.c index 2e77bf68..549db270 100644 --- a/platform/unix.c +++ b/platform/unix.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -303,8 +304,14 @@ LinkedStringList *__PHYSFS_platformEnumerateFiles(const char *dirname) 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 @@ LinkedStringList *__PHYSFS_platformEnumerateFiles(const char *dirname) break; } /* if */ + strcpy(l->str, ent->d_name); + if (retval == NULL) retval = l; else @@ -337,5 +346,43 @@ int __PHYSFS_platformFileLength(FILE *handle) } /* __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 ... */