physfs.c
changeset 39 bc29e1ee7ef6
parent 28 529214f57d1b
child 41 ff60d39d0862
equal deleted inserted replaced
38:feb16343f44c 39:bc29e1ee7ef6
     9  */
     9  */
    10 
    10 
    11 #include <stdio.h>
    11 #include <stdio.h>
    12 #include <stdlib.h>
    12 #include <stdlib.h>
    13 #include <string.h>
    13 #include <string.h>
       
    14 #include <sys/stat.h>
       
    15 #include <sys/types.h>
       
    16 #include <fcntl.h>
    14 #include <unistd.h>
    17 #include <unistd.h>
       
    18 #include <errno.h>
    15 #include <assert.h>
    19 #include <assert.h>
    16 #include "physfs.h"
    20 #include "physfs.h"
    17 
    21 
    18 #define __PHYSICSFS_INTERNAL__
    22 #define __PHYSICSFS_INTERNAL__
    19 #include "physfs_internal.h"
    23 #include "physfs_internal.h"
   301 static char *calculateBaseDir(const char *argv0)
   305 static char *calculateBaseDir(const char *argv0)
   302 {
   306 {
   303     const char *dirsep = PHYSFS_getDirSeparator();
   307     const char *dirsep = PHYSFS_getDirSeparator();
   304     char *retval;
   308     char *retval;
   305     char *ptr;
   309     char *ptr;
   306     int allocSize = 0;
       
   307 
   310 
   308     /*
   311     /*
   309      * See if the platform driver wants to handle this for us...
   312      * See if the platform driver wants to handle this for us...
   310      */
   313      */
   311     retval = __PHYSFS_platformCalcBaseDir(argv0);
   314     retval = __PHYSFS_platformCalcBaseDir(argv0);
   335     } /* if */
   338     } /* if */
   336 
   339 
   337     /*
   340     /*
   338      * Last ditch effort: it's the current working directory. (*shrug*)
   341      * Last ditch effort: it's the current working directory. (*shrug*)
   339      */
   342      */
   340     do
   343     return(__PHYSFS_platformCurrentDir());
   341     {
       
   342         allocSize += 100;
       
   343         ptr = (char *) realloc(retval, allocSize);
       
   344         if (ptr == NULL)
       
   345         {
       
   346             if (retval != NULL)
       
   347                 free(retval);
       
   348             BAIL_IF_MACRO(1, ERR_OUT_OF_MEMORY, NULL);
       
   349         } /* if */
       
   350 
       
   351         retval = ptr;
       
   352         ptr = getcwd(retval, allocSize);
       
   353     } while (ptr == NULL);
       
   354 
       
   355     return(retval);
       
   356 } /* calculateBaseDir */
   344 } /* calculateBaseDir */
   357 
   345 
   358 
   346 
   359 int PHYSFS_init(const char *argv0)
   347 int PHYSFS_init(const char *argv0)
   360 {
   348 {
       
   349     char *ptr;
       
   350 
   361     BAIL_IF_MACRO(initialized, ERR_IS_INITIALIZED, 0);
   351     BAIL_IF_MACRO(initialized, ERR_IS_INITIALIZED, 0);
   362     BAIL_IF_MACRO(argv0 == NULL, ERR_INVALID_ARGUMENT, 0);
   352     BAIL_IF_MACRO(argv0 == NULL, ERR_INVALID_ARGUMENT, 0);
   363 
   353 
   364     baseDir = calculateBaseDir(argv0);
   354     baseDir = calculateBaseDir(argv0);
   365     BAIL_IF_MACRO(baseDir == NULL, NULL, 0);
   355     BAIL_IF_MACRO(baseDir == NULL, NULL, 0);
       
   356     ptr = __PHYSFS_platformRealPath(baseDir);
       
   357     free(baseDir);
       
   358     BAIL_IF_MACRO(ptr == NULL, NULL, 0);
       
   359     baseDir = ptr;
       
   360 
   366     BAIL_IF_MACRO(!appendDirSep(&baseDir), NULL, 0);
   361     BAIL_IF_MACRO(!appendDirSep(&baseDir), NULL, 0);
   367 
   362 
   368     userDir = calculateUserDir();
   363     userDir = calculateUserDir();
       
   364     if (userDir != NULL)
       
   365     {
       
   366         ptr = __PHYSFS_platformRealPath(userDir);
       
   367         free(userDir);
       
   368         userDir = ptr;
       
   369     } /* if */
       
   370 
   369     if ((userDir == NULL) || (!appendDirSep(&userDir)))
   371     if ((userDir == NULL) || (!appendDirSep(&userDir)))
   370     {
   372     {
   371         free(baseDir);
   373         free(baseDir);
   372         baseDir = NULL;
   374         baseDir = NULL;
   373         return(0);
   375         return(0);
   622 {
   624 {
   623     const char *basedir = PHYSFS_getBaseDir();
   625     const char *basedir = PHYSFS_getBaseDir();
   624     const char *userdir = PHYSFS_getUserDir();
   626     const char *userdir = PHYSFS_getUserDir();
   625     const char *dirsep = PHYSFS_getDirSeparator();
   627     const char *dirsep = PHYSFS_getDirSeparator();
   626     char *str;
   628     char *str;
   627     int rc;
       
   628 
   629 
   629         /* set write dir... */
   630         /* set write dir... */
   630     str = malloc(strlen(userdir) + (strlen(appName) * 2) +
   631     str = malloc(strlen(userdir) + (strlen(appName) * 2) +
   631                  (strlen(dirsep) * 2) + 2);
   632                  (strlen(dirsep) * 2) + 2);
   632     BAIL_IF_MACRO(str == NULL, ERR_OUT_OF_MEMORY, 0);
   633     BAIL_IF_MACRO(str == NULL, ERR_OUT_OF_MEMORY, 0);
   633     sprintf(str, "%s%s.%s", userdir, dirsep, appName);
   634     sprintf(str, "%s.%s", userdir, appName);
   634     rc = PHYSFS_setWriteDir(str);
   635 
   635     BAIL_IF_MACRO(!rc, NULL, 0);
   636     if (!PHYSFS_setWriteDir(str))
       
   637     {
       
   638         if ( (!PHYSFS_setWriteDir(userdir)) ||
       
   639              (!PHYSFS_mkdir(str + strlen(userdir))) )
       
   640         {
       
   641             PHYSFS_setWriteDir(NULL);
       
   642             free(str);
       
   643             BAIL_IF_MACRO(1, ERR_CANT_SET_WRITE_DIR, 0);
       
   644         } /* if */
       
   645     } /* if */
       
   646 
       
   647     if (!PHYSFS_setWriteDir(str))
       
   648     {
       
   649         PHYSFS_setWriteDir(NULL);
       
   650         free(str);
       
   651         BAIL_IF_MACRO(1, ERR_CANT_SET_WRITE_DIR, 0);
       
   652     } /* if */
   636 
   653 
   637         /* Put write dir related dirs on search path... */
   654         /* Put write dir related dirs on search path... */
   638     PHYSFS_addToSearchPath(str, 1);
   655     PHYSFS_addToSearchPath(str, 1);
   639     PHYSFS_mkdir(appName); /* don't care if this fails. */
   656     PHYSFS_mkdir(appName); /* don't care if this fails. */
   640     strcat(str, dirsep);
   657     strcat(str, dirsep);
   646     PHYSFS_addToSearchPath(basedir, 1);
   663     PHYSFS_addToSearchPath(basedir, 1);
   647     str = malloc(strlen(basedir) + (strlen(appName) * 2) +
   664     str = malloc(strlen(basedir) + (strlen(appName) * 2) +
   648                  (strlen(dirsep) * 2) + 2);
   665                  (strlen(dirsep) * 2) + 2);
   649     if (str != NULL)
   666     if (str != NULL)
   650     {
   667     {
   651         sprintf(str, "%s%s.%s", basedir, dirsep, appName);
   668         sprintf(str, "%s.%s", basedir, appName);
   652         PHYSFS_addToSearchPath(str, 1);
   669         PHYSFS_addToSearchPath(str, 1);
   653         free(str);
   670         free(str);
   654     } /* if */
   671     } /* if */
   655 
   672 
   656         /* handle CD-ROMs... */
   673         /* handle CD-ROMs... */
   723     char *str;
   740     char *str;
   724     char *i1;
   741     char *i1;
   725     char *i2;
   742     char *i2;
   726     size_t allocSize;
   743     size_t allocSize;
   727 
   744 
       
   745     while (*dirName == '/')
       
   746         dirName++;
       
   747 
   728     allocSize = strlen(dirName) + 1;
   748     allocSize = strlen(dirName) + 1;
   729     if (prepend != NULL)
   749     if (prepend != NULL)
   730         allocSize += strlen(prepend) + sepsize;
   750         allocSize += strlen(prepend) + sepsize;
   731     if (append != NULL)
   751     if (append != NULL)
   732         allocSize += strlen(append) + sepsize;
   752         allocSize += strlen(append) + sepsize;
   834     char *start;
   854     char *start;
   835     char *end;
   855     char *end;
   836     int retval = 0;
   856     int retval = 0;
   837 
   857 
   838     BAIL_IF_MACRO(writeDir == NULL, ERR_NO_WRITE_DIR, 0);
   858     BAIL_IF_MACRO(writeDir == NULL, ERR_NO_WRITE_DIR, 0);
       
   859 
   839     h = writeDir->dirHandle;
   860     h = writeDir->dirHandle;
       
   861 
       
   862     while (*dirName == '/')
       
   863         dirName++;
       
   864 
   840     BAIL_IF_MACRO(h->funcs->mkdir == NULL, ERR_NOT_SUPPORTED, 0);
   865     BAIL_IF_MACRO(h->funcs->mkdir == NULL, ERR_NOT_SUPPORTED, 0);
   841     BAIL_IF_MACRO(!__PHYSFS_verifySecurity(h, dirName), NULL, 0);
   866     BAIL_IF_MACRO(!__PHYSFS_verifySecurity(h, dirName), NULL, 0);
   842 
   867 
   843     start = str = malloc(strlen(dirName) + 1);
   868     start = str = malloc(strlen(dirName) + 1);
   844     BAIL_IF_MACRO(str == NULL, ERR_OUT_OF_MEMORY, 0);
   869     BAIL_IF_MACRO(str == NULL, ERR_OUT_OF_MEMORY, 0);
   870 {
   895 {
   871     DirHandle *h;
   896     DirHandle *h;
   872     BAIL_IF_MACRO(writeDir == NULL, ERR_NO_WRITE_DIR, 0);
   897     BAIL_IF_MACRO(writeDir == NULL, ERR_NO_WRITE_DIR, 0);
   873     h = writeDir->dirHandle;
   898     h = writeDir->dirHandle;
   874     BAIL_IF_MACRO(h->funcs->remove == NULL, ERR_NOT_SUPPORTED, 0);
   899     BAIL_IF_MACRO(h->funcs->remove == NULL, ERR_NOT_SUPPORTED, 0);
       
   900 
       
   901     while (*fname == '/')
       
   902         fname++;
       
   903 
   875     BAIL_IF_MACRO(!__PHYSFS_verifySecurity(h, fname), NULL, 0);
   904     BAIL_IF_MACRO(!__PHYSFS_verifySecurity(h, fname), NULL, 0);
   876     return(h->funcs->remove(h, fname));
   905     return(h->funcs->remove(h, fname));
   877 } /* PHYSFS_delete */
   906 } /* PHYSFS_delete */
   878 
   907 
   879 
   908 
   880 const char *PHYSFS_getRealDir(const char *filename)
   909 const char *PHYSFS_getRealDir(const char *filename)
   881 {
   910 {
   882     DirInfo *i;
   911     DirInfo *i;
   883 
   912 
       
   913     while (*filename == '/')
       
   914         filename++;
       
   915 
   884     for (i = searchPath; i != NULL; i = i->next)
   916     for (i = searchPath; i != NULL; i = i->next)
   885     {
   917     {
   886         DirHandle *h = i->dirHandle;
   918         DirHandle *h = i->dirHandle;
   887         if (__PHYSFS_verifySecurity(h, filename))
   919         if (__PHYSFS_verifySecurity(h, filename))
   888         {
   920         {
   897 
   929 
   898 static int countList(LinkedStringList *list)
   930 static int countList(LinkedStringList *list)
   899 {
   931 {
   900     int retval = 0;
   932     int retval = 0;
   901     LinkedStringList *i;
   933     LinkedStringList *i;
   902 
       
   903     assert(list != NULL);
       
   904 
   934 
   905     for (i = list; i != NULL; i = i->next)
   935     for (i = list; i != NULL; i = i->next)
   906         retval++;
   936         retval++;
   907 
   937 
   908     return(retval);
   938     return(retval);
   945     int rc;
   975     int rc;
   946 
   976 
   947     for (i = *final; i != NULL; i = i->next)
   977     for (i = *final; i != NULL; i = i->next)
   948     {
   978     {
   949         rc = strcmp(i->str, item->str);
   979         rc = strcmp(i->str, item->str);
   950         if (rc == 0)      /* already in list. */
   980         if (rc > 0)  /* insertion point. */
       
   981             break;
       
   982         else if (rc == 0)      /* already in list. */
   951         {
   983         {
   952             free(item->str);
   984             free(item->str);
   953             free(item);
   985             free(item);
   954             return;
   986             return;
   955         } /* if */
       
   956         else if (rc > 0)  /* insertion point. */
       
   957         {
       
   958             if (prev == NULL)
       
   959                 *final = item;
       
   960             else
       
   961                 prev->next = item;
       
   962             item->next = i;
       
   963             return;
       
   964         } /* else if */
   987         } /* else if */
   965         prev = i;
   988         prev = i;
   966     } /* for */
   989     } /* for */
       
   990 
       
   991         /*
       
   992          * If we are here, we are either at the insertion point.
       
   993          *  This may be the end of the list, or the list may be empty, too.
       
   994          */
       
   995     if (prev == NULL)
       
   996         *final = item;
       
   997     else
       
   998         prev->next = item;
       
   999 
       
  1000     item->next = i;
   967 } /* insertStringListItem */
  1001 } /* insertStringListItem */
   968 
  1002 
   969 
  1003 
   970 /* if we run out of memory anywhere in here, we give back what we can. */
  1004 /* if we run out of memory anywhere in here, we give back what we can. */
   971 static void interpolateStringLists(LinkedStringList **final,
  1005 static void interpolateStringLists(LinkedStringList **final,
   987     DirInfo *i;
  1021     DirInfo *i;
   988     char **retval = NULL;
  1022     char **retval = NULL;
   989     LinkedStringList *rc;
  1023     LinkedStringList *rc;
   990     LinkedStringList *finalList = NULL;
  1024     LinkedStringList *finalList = NULL;
   991 
  1025 
       
  1026     while (*path == '/')
       
  1027         path++;
       
  1028 
   992     for (i = searchPath; i != NULL; i = i->next)
  1029     for (i = searchPath; i != NULL; i = i->next)
   993     {
  1030     {
   994         DirHandle *h = i->dirHandle;
  1031         DirHandle *h = i->dirHandle;
   995         if (__PHYSFS_verifySecurity(h, path))
  1032         if (__PHYSFS_verifySecurity(h, path))
   996         {
  1033         {
  1004 } /* PHYSFS_enumerateFiles */
  1041 } /* PHYSFS_enumerateFiles */
  1005 
  1042 
  1006 
  1043 
  1007 int PHYSFS_exists(const char *fname)
  1044 int PHYSFS_exists(const char *fname)
  1008 {
  1045 {
       
  1046     while (*fname == '/')
       
  1047         fname++;
       
  1048 
  1009     return(PHYSFS_getRealDir(fname) != NULL);
  1049     return(PHYSFS_getRealDir(fname) != NULL);
  1010 } /* PHYSFS_exists */
  1050 } /* PHYSFS_exists */
  1011 
  1051 
  1012 
  1052 
  1013 int PHYSFS_isDirectory(const char *fname)
  1053 int PHYSFS_isDirectory(const char *fname)
  1014 {
  1054 {
  1015     DirInfo *i;
  1055     DirInfo *i;
       
  1056 
       
  1057     while (*fname == '/')
       
  1058         fname++;
  1016 
  1059 
  1017     for (i = searchPath; i != NULL; i = i->next)
  1060     for (i = searchPath; i != NULL; i = i->next)
  1018     {
  1061     {
  1019         DirHandle *h = i->dirHandle;
  1062         DirHandle *h = i->dirHandle;
  1020         if (__PHYSFS_verifySecurity(h, fname))
  1063         if (__PHYSFS_verifySecurity(h, fname))
  1032 {
  1075 {
  1033     DirInfo *i;
  1076     DirInfo *i;
  1034 
  1077 
  1035     if (!allowSymLinks)
  1078     if (!allowSymLinks)
  1036         return(0);
  1079         return(0);
       
  1080 
       
  1081     while (*fname == '/')
       
  1082         fname++;
  1037 
  1083 
  1038     for (i = searchPath; i != NULL; i = i->next)
  1084     for (i = searchPath; i != NULL; i = i->next)
  1039     {
  1085     {
  1040         DirHandle *h = i->dirHandle;
  1086         DirHandle *h = i->dirHandle;
  1041         if (__PHYSFS_verifySecurity(h, fname))
  1087         if (__PHYSFS_verifySecurity(h, fname))
  1055     FileHandle *rc = NULL;
  1101     FileHandle *rc = NULL;
  1056     DirHandle *h = (writeDir == NULL) ? NULL : writeDir->dirHandle;
  1102     DirHandle *h = (writeDir == NULL) ? NULL : writeDir->dirHandle;
  1057     const DirFunctions *f = (h == NULL) ? NULL : h->funcs;
  1103     const DirFunctions *f = (h == NULL) ? NULL : h->funcs;
  1058     FileHandleList *list;
  1104     FileHandleList *list;
  1059 
  1105 
       
  1106     while (*fname == '/')
       
  1107         fname++;
       
  1108 
  1060     BAIL_IF_MACRO(!h, ERR_NO_WRITE_DIR, NULL);
  1109     BAIL_IF_MACRO(!h, ERR_NO_WRITE_DIR, NULL);
  1061     BAIL_IF_MACRO(!__PHYSFS_verifySecurity(h, fname), NULL, NULL);
  1110     BAIL_IF_MACRO(!__PHYSFS_verifySecurity(h, fname), NULL, NULL);
  1062 
  1111 
  1063     list = (FileHandleList *) malloc(sizeof (FileHandleList));
  1112     list = (FileHandleList *) malloc(sizeof (FileHandleList));
  1064     BAIL_IF_MACRO(!list, ERR_OUT_OF_MEMORY, NULL);
  1113     BAIL_IF_MACRO(!list, ERR_OUT_OF_MEMORY, NULL);
  1094 {
  1143 {
  1095     PHYSFS_file *retval = NULL;
  1144     PHYSFS_file *retval = NULL;
  1096     FileHandle *rc = NULL;
  1145     FileHandle *rc = NULL;
  1097     FileHandleList *list;
  1146     FileHandleList *list;
  1098     DirInfo *i;
  1147     DirInfo *i;
       
  1148 
       
  1149     while (*fname == '/')
       
  1150         fname++;
  1099 
  1151 
  1100     list = (FileHandleList *) malloc(sizeof (FileHandleList));
  1152     list = (FileHandleList *) malloc(sizeof (FileHandleList));
  1101     BAIL_IF_MACRO(!list, ERR_OUT_OF_MEMORY, NULL);
  1153     BAIL_IF_MACRO(!list, ERR_OUT_OF_MEMORY, NULL);
  1102 
  1154 
  1103     for (i = searchPath; i != NULL; i = i->next)
  1155     for (i = searchPath; i != NULL; i = i->next)