Преглед на файлове

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.
Ryan C. Gordon преди 14 години
родител
ревизия
9d01a645ed
променени са 7 файла, в които са добавени 30 реда и са изтрити 11 реда
  1. 0 1
      docs/TODO.txt
  2. 3 2
      src/physfs.c
  3. 1 0
      src/physfs_internal.h
  4. 2 1
      src/platform_beos.cpp
  5. 7 2
      src/platform_macosx.c
  6. 7 3
      src/platform_unix.c
  7. 10 2
      src/platform_windows.c

+ 0 - 1
docs/TODO.txt

@@ -75,7 +75,6 @@ Other stuff I thought of...
 - 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.

+ 3 - 2
src/physfs.c

@@ -1147,7 +1147,7 @@ static char *calculateBaseDir(const char *argv0)
     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 @@ int PHYSFS_init(const char *argv0)
     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)))

+ 1 - 0
src/physfs_internal.h

@@ -634,6 +634,7 @@ void __PHYSFS_platformDetectAvailableCDs(PHYSFS_StringCallback cb, void *data);
  * 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);

+ 2 - 1
src/platform_beos.cpp

@@ -176,9 +176,10 @@ char *__PHYSFS_platformCalcBaseDir(const char *argv0)
     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 */
 

+ 7 - 2
src/platform_macosx.c

@@ -268,18 +268,23 @@ char *__PHYSFS_platformCalcBaseDir(const char *argv0)
             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);

+ 7 - 3
src/platform_unix.c

@@ -167,11 +167,14 @@ static char *findBinaryInPath(const char *bin, char *envr)
     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 @@ static char *findBinaryInPath(const char *bin, char *envr)
 
         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 *__PHYSFS_platformCalcBaseDir(const char *argv0)
     {
         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);

+ 10 - 2
src/platform_windows.c

@@ -372,7 +372,7 @@ char *__PHYSFS_platformCalcBaseDir(const char *argv0)
             __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 @@ char *__PHYSFS_platformCalcUserDir(void)
         (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 */