Make sure base dir always has a dirsep at the end of it.
authorRyan C. Gordon <icculus@icculus.org>
Fri, 23 Mar 2012 04:14:01 -0400
changeset 1264 03715ba4603d
parent 1263 3d5ed1d03b34
child 1265 d4098b3aa37d
Make sure base dir always has a dirsep at the end of it. Now the higher level doesn't have to check for this and realloc the string.
docs/TODO.txt
src/physfs.c
src/physfs_internal.h
src/platform_beos.cpp
src/platform_macosx.c
src/platform_unix.c
src/platform_windows.c
--- a/docs/TODO.txt	Fri Mar 23 03:30:16 2012 -0400
+++ b/docs/TODO.txt	Fri Mar 23 04:14:01 2012 -0400
@@ -75,7 +75,6 @@
 - bzip2 support in zip archiver?
 - rewrite 7zip archiver.
 - ryanify iso9660 code.
-- Cache basedir/userdir results (do we do this already?)
 - Reduce the BAIL and GOTO macro use. A lot of these don't add anything.
 
 Probably other stuff. Requests and recommendations are welcome.
--- a/src/physfs.c	Fri Mar 23 03:30:16 2012 -0400
+++ b/src/physfs.c	Fri Mar 23 04:14:01 2012 -0400
@@ -1147,7 +1147,7 @@
     ptr = strrchr(argv0, dirsep);
     if (ptr != NULL)
     {
-        const size_t size = (size_t) (ptr - argv0);
+        const size_t size = ((size_t) (ptr - argv0)) + 1;
         retval = (char *) allocator.Malloc(size + 1);
         BAIL_IF_MACRO(!retval, PHYSFS_ERR_OUT_OF_MEMORY, NULL);
         memcpy(retval, argv0, size);
@@ -1203,7 +1203,8 @@
     baseDir = calculateBaseDir(argv0);
     BAIL_IF_MACRO(!baseDir, ERRPASS, 0);
 
-    BAIL_IF_MACRO(!appendDirSep(&baseDir), ERRPASS, 0);
+    /* Platform layer is required to append a dirsep. */
+    assert(baseDir[strlen(baseDir) - 1] == __PHYSFS_platformDirSeparator);
 
     userDir = __PHYSFS_platformCalcUserDir();
     if ((!userDir) || (!appendDirSep(&userDir)))
--- a/src/physfs_internal.h	Fri Mar 23 03:30:16 2012 -0400
+++ b/src/physfs_internal.h	Fri Mar 23 04:14:01 2012 -0400
@@ -634,6 +634,7 @@
  * Calculate the base dir, if your platform needs special consideration.
  *  Just return NULL if the standard routines will suffice. (see
  *  calculateBaseDir() in physfs.c ...)
+ * Your string must end with a dir separator if you don't return NULL.
  *  Caller will allocator.Free() the retval if it's not NULL.
  */
 char *__PHYSFS_platformCalcBaseDir(const char *argv0);
--- a/src/platform_beos.cpp	Fri Mar 23 03:30:16 2012 -0400
+++ b/src/platform_beos.cpp	Fri Mar 23 04:14:01 2012 -0400
@@ -176,9 +176,10 @@
     assert(rc == B_OK);
     const char *str = path.Path();
     assert(str != NULL);
-    char *retval = (char *) allocator.Malloc(strlen(str) + 1);
+    char *retval = (char *) allocator.Malloc(strlen(str) + 2);
     BAIL_IF_MACRO(!retval, PHYSFS_ERR_OUT_OF_MEMORY, NULL);
     strcpy(retval, str);
+    strcat(retval, "/");
     return retval;
 } /* __PHYSFS_platformCalcBaseDir */
 
--- a/src/platform_macosx.c	Fri Mar 23 03:30:16 2012 -0400
+++ b/src/platform_macosx.c	Fri Mar 23 04:14:01 2012 -0400
@@ -268,18 +268,23 @@
             return NULL;
         } /* if */
 
-        /* chop the "/exename" from the end of the path string... */
+        /* chop the "exename" from the end of the path string (leave '/')... */
+        cfrange.location++;
         cfrange.length = CFStringGetLength(cfmutstr) - cfrange.location;
         CFStringDelete(cfmutstr, cfrange);
 
         /* If we're an Application Bundle, chop everything but the base. */
-        cfrange = CFStringFind(cfmutstr, CFSTR("/Contents/MacOS"),
+        cfrange = CFStringFind(cfmutstr, CFSTR("/Contents/MacOS/"),
                                kCFCompareCaseInsensitive |
                                kCFCompareBackwards |
                                kCFCompareAnchored);
 
         if (cfrange.location != kCFNotFound)
+        {
+            cfrange.location++;  /* leave the trailing '/' char ... */
+            cfrange.length--;
             CFStringDelete(cfmutstr, cfrange);  /* chop that, too. */
+        } /* if */
     } /* if */
 
     retval = convertCFString(cfmutstr);
--- a/src/platform_unix.c	Fri Mar 23 03:30:16 2012 -0400
+++ b/src/platform_unix.c	Fri Mar 23 04:14:01 2012 -0400
@@ -167,11 +167,14 @@
     do
     {
         size_t size;
+        size_t binlen;
+
         ptr = strchr(start, ':');  /* find next $PATH separator. */
         if (ptr)
             *ptr = '\0';
 
-        size = strlen(start) + strlen(bin) + 2;
+        binlen = strlen(bin);
+        size = strlen(start) + binlen + 2;
         if (size > alloc_size)
         {
             char *x = (char *) allocator.Realloc(exe, size);
@@ -194,7 +197,7 @@
 
         if (access(exe, X_OK) == 0)  /* Exists as executable? We're done. */
         {
-            strcpy(exe, start);  /* i'm lazy. piss off. */
+            exe[size - binlen] = '\0'; /* chop off filename, leave '/' */
             return exe;
         } /* if */
 
@@ -269,12 +272,13 @@
     {
         char *ptr = strrchr(retval, '/');
         if (ptr != NULL)
-            *ptr = '\0';
+            *(ptr+1) = '\0';
     } /* if */
 
     if ((retval == NULL) && (argv0 != NULL))
     {
         /* If there's no dirsep on argv0, then look through $PATH for it. */
+        /* !!! FIXME: smallAlloc? */
         envr = __PHYSFS_platformCopyEnvironmentVariable("PATH");
         BAIL_IF_MACRO(!envr, ERRPASS, NULL);
         retval = findBinaryInPath(argv0, envr);
--- a/src/platform_windows.c	Fri Mar 23 03:30:16 2012 -0400
+++ b/src/platform_windows.c	Fri Mar 23 04:14:01 2012 -0400
@@ -372,7 +372,7 @@
             __PHYSFS_setError(PHYSFS_ERR_OTHER_ERROR);  /* oh well. */
         else
         {
-            *(ptr + 1) = '\0';  /* chop off filename. */
+            *(ptr+1) = '\0';  /* chop off filename. */
             retval = unicodeToUtf8Heap(modpath);
         } /* else */
     } /* else */
@@ -448,11 +448,19 @@
         (void) rc;
 
         /* Allocate memory for the profile directory */
-        wstr = (LPWSTR) __PHYSFS_smallAlloc(psize * sizeof (WCHAR));
+        wstr = (LPWSTR) __PHYSFS_smallAlloc((psize + 1) * sizeof (WCHAR));
         if (wstr != NULL)
         {
             if (pGetDir(accessToken, wstr, &psize))
+            {
+                /* Make sure it ends in a dirsep. We allocated +1 for this. */
+                if (wstr[psize - 2] != '\\')
+                {
+                    wstr[psize - 1] = '\\';
+                    wstr[psize - 0] = '\0';
+                } /* if */
                 retval = unicodeToUtf8Heap(wstr);
+            } /* if */
             __PHYSFS_smallFree(wstr);
         } /* if */