physfs.c
changeset 145 d6385584f6c4
parent 132 b53fa5093749
child 150 221f15a7cb08
equal deleted inserted replaced
144:819455c581e5 145:d6385584f6c4
    83 };
    83 };
    84 
    84 
    85 
    85 
    86 
    86 
    87 /* General PhysicsFS state ... */
    87 /* General PhysicsFS state ... */
    88 
       
    89 static int initialized = 0;
    88 static int initialized = 0;
    90 static ErrMsg *errorMessages = NULL;
    89 static ErrMsg *errorMessages = NULL;
    91 static DirInfo *searchPath = NULL;
    90 static DirInfo *searchPath = NULL;
    92 static DirInfo *writeDir = NULL;
    91 static DirInfo *writeDir = NULL;
    93 static FileHandleList *openWriteList = NULL;
    92 static FileHandleList *openWriteList = NULL;
    94 static FileHandleList *openReadList = NULL;
    93 static FileHandleList *openReadList = NULL;
    95 static char *baseDir = NULL;
    94 static char *baseDir = NULL;
    96 static char *userDir = NULL;
    95 static char *userDir = NULL;
    97 static int allowSymLinks = 0;
    96 static int allowSymLinks = 0;
    98 
    97 
       
    98 /* mutexes ... */
       
    99 static void *errorLock = NULL;     /* protects error message list.        */
       
   100 static void *stateLock = NULL;     /* protects other PhysFS static state. */
    99 
   101 
   100 
   102 
   101 /* functions ... */
   103 /* functions ... */
   102 
   104 
   103 static ErrMsg *findErrorForCurrentThread(void)
   105 static ErrMsg *findErrorForCurrentThread(void)
   104 {
   106 {
   105     ErrMsg *i;
   107     ErrMsg *i;
   106     int tid;
   108     int tid;
   107 
   109 
       
   110     __PHYSFS_platformGrabMutex(errorLock);
   108     if (errorMessages != NULL)
   111     if (errorMessages != NULL)
   109     {
   112     {
   110         tid = __PHYSFS_platformGetThreadID();
   113         tid = __PHYSFS_platformGetThreadID();
   111 
   114 
   112         for (i = errorMessages; i != NULL; i = i->next)
   115         for (i = errorMessages; i != NULL; i = i->next)
   113         {
   116         {
   114             if (i->tid == tid)
   117             if (i->tid == tid)
       
   118             {
       
   119                 __PHYSFS_platformReleaseMutex(errorLock);
   115                 return(i);
   120                 return(i);
       
   121             } /* if */
   116         } /* for */
   122         } /* for */
   117     } /* if */
   123     } /* if */
       
   124     __PHYSFS_platformReleaseMutex(errorLock);
   118 
   125 
   119     return(NULL);   /* no error available. */
   126     return(NULL);   /* no error available. */
   120 } /* findErrorForCurrentThread */
   127 } /* findErrorForCurrentThread */
   121 
   128 
   122 
   129 
   135         if (err == NULL)
   142         if (err == NULL)
   136             return;   /* uhh...? */
   143             return;   /* uhh...? */
   137 
   144 
   138         memset((void *) err, '\0', sizeof (ErrMsg));
   145         memset((void *) err, '\0', sizeof (ErrMsg));
   139         err->tid = __PHYSFS_platformGetThreadID();
   146         err->tid = __PHYSFS_platformGetThreadID();
       
   147 
       
   148         __PHYSFS_platformGrabMutex(errorLock);
   140         err->next = errorMessages;
   149         err->next = errorMessages;
   141         errorMessages = err;
   150         errorMessages = err;
       
   151         __PHYSFS_platformReleaseMutex(errorLock);
   142     } /* if */
   152     } /* if */
   143 
   153 
   144     err->errorAvailable = 1;
   154     err->errorAvailable = 1;
   145     strncpy(err->errorString, str, sizeof (err->errorString));
   155     strncpy(err->errorString, str, sizeof (err->errorString));
   146     err->errorString[sizeof (err->errorString) - 1] = '\0';
   156     err->errorString[sizeof (err->errorString) - 1] = '\0';
   147 } /* __PHYSFS_setError */
   157 } /* __PHYSFS_setError */
   148 
   158 
   149 
   159 
   150 static void freeErrorMessages(void)
       
   151 {
       
   152     ErrMsg *i;
       
   153     ErrMsg *next;
       
   154 
       
   155     for (i = errorMessages; i != NULL; i = next)
       
   156     {
       
   157         next = i->next;
       
   158         free(i);
       
   159     } /* for */
       
   160 } /* freeErrorMessages */
       
   161 
       
   162 
       
   163 const char *PHYSFS_getLastError(void)
   160 const char *PHYSFS_getLastError(void)
   164 {
   161 {
   165     ErrMsg *err = findErrorForCurrentThread();
   162     ErrMsg *err = findErrorForCurrentThread();
   166 
   163 
   167     if ((err == NULL) || (!err->errorAvailable))
   164     if ((err == NULL) || (!err->errorAvailable))
   170     err->errorAvailable = 0;
   167     err->errorAvailable = 0;
   171     return(err->errorString);
   168     return(err->errorString);
   172 } /* PHYSFS_getLastError */
   169 } /* PHYSFS_getLastError */
   173 
   170 
   174 
   171 
       
   172 /* MAKE SURE that errorLock is held before calling this! */
       
   173 static void freeErrorMessages(void)
       
   174 {
       
   175     ErrMsg *i;
       
   176     ErrMsg *next;
       
   177 
       
   178     for (i = errorMessages; i != NULL; i = next)
       
   179     {
       
   180         next = i->next;
       
   181         free(i);
       
   182     } /* for */
       
   183 } /* freeErrorMessages */
       
   184 
       
   185 
   175 void PHYSFS_getLinkedVersion(PHYSFS_Version *ver)
   186 void PHYSFS_getLinkedVersion(PHYSFS_Version *ver)
   176 {
   187 {
   177     if (ver != NULL)
   188     if (ver != NULL)
   178     {
   189     {
   179         ver->major = PHYSFS_VER_MAJOR;
   190         ver->major = PHYSFS_VER_MAJOR;
   210     dirHandle = openDirectory(newDir, forWriting);
   221     dirHandle = openDirectory(newDir, forWriting);
   211     BAIL_IF_MACRO(dirHandle == NULL, NULL, 0);
   222     BAIL_IF_MACRO(dirHandle == NULL, NULL, 0);
   212 
   223 
   213     di = (DirInfo *) malloc(sizeof (DirInfo));
   224     di = (DirInfo *) malloc(sizeof (DirInfo));
   214     if (di == NULL)
   225     if (di == NULL)
       
   226     {
   215         dirHandle->funcs->dirClose(dirHandle);
   227         dirHandle->funcs->dirClose(dirHandle);
   216     BAIL_IF_MACRO(di == NULL, ERR_OUT_OF_MEMORY, 0);
   228         BAIL_IF_MACRO(di == NULL, ERR_OUT_OF_MEMORY, 0);
       
   229     } /* if */
   217 
   230 
   218     di->dirName = (char *) malloc(strlen(newDir) + 1);
   231     di->dirName = (char *) malloc(strlen(newDir) + 1);
   219     if (di->dirName == NULL)
   232     if (di->dirName == NULL)
   220     {
   233     {
   221         free(di);
   234         free(di);
   222         dirHandle->funcs->dirClose(dirHandle);
   235         dirHandle->funcs->dirClose(dirHandle);
   223         __PHYSFS_setError(ERR_OUT_OF_MEMORY);
   236         BAIL_MACRO(ERR_OUT_OF_MEMORY, 0);
   224         return(0);
       
   225     } /* if */
   237     } /* if */
   226 
   238 
   227     di->next = NULL;
   239     di->next = NULL;
   228     di->dirHandle = dirHandle;
   240     di->dirHandle = dirHandle;
   229     strcpy(di->dirName, newDir);
   241     strcpy(di->dirName, newDir);
   230     return(di);
   242     return(di);
   231 } /* buildDirInfo */
   243 } /* buildDirInfo */
   232 
   244 
   233 
   245 
       
   246 /* MAKE SURE you've got the stateLock held before calling this! */
   234 static int freeDirInfo(DirInfo *di, FileHandleList *openList)
   247 static int freeDirInfo(DirInfo *di, FileHandleList *openList)
   235 {
   248 {
   236     FileHandleList *i;
   249     FileHandleList *i;
   237 
   250 
   238     if (di == NULL)
   251     if (di == NULL)
   241     for (i = openList; i != NULL; i = i->next)
   254     for (i = openList; i != NULL; i = i->next)
   242     {
   255     {
   243         const DirHandle *h = ((FileHandle *) &(i->handle.opaque))->dirHandle;
   256         const DirHandle *h = ((FileHandle *) &(i->handle.opaque))->dirHandle;
   244         BAIL_IF_MACRO(h == di->dirHandle, ERR_FILES_STILL_OPEN, 0);
   257         BAIL_IF_MACRO(h == di->dirHandle, ERR_FILES_STILL_OPEN, 0);
   245     } /* for */
   258     } /* for */
   246 
   259     
   247     di->dirHandle->funcs->dirClose(di->dirHandle);
   260     di->dirHandle->funcs->dirClose(di->dirHandle);
   248     free(di->dirName);
   261     free(di->dirName);
   249     free(di);
   262     free(di);
   250     return(1);
   263     return(1);
   251 } /* freeDirInfo */
   264 } /* freeDirInfo */
   354     strcpy(retval, dirsep);
   367     strcpy(retval, dirsep);
   355     return(retval);
   368     return(retval);
   356 } /* calculateBaseDir */
   369 } /* calculateBaseDir */
   357 
   370 
   358 
   371 
       
   372 static int initializeMutexes(void)
       
   373 {
       
   374     errorLock = __PHYSFS_platformCreateMutex();
       
   375     if (errorLock == NULL)
       
   376         goto initializeMutexes_failed;
       
   377 
       
   378     stateLock = __PHYSFS_platformCreateMutex();
       
   379     if (stateLock == NULL)
       
   380         goto initializeMutexes_failed;
       
   381 
       
   382     return(1);  /* success. */
       
   383 
       
   384 initializeMutexes_failed:
       
   385     if (errorLock != NULL)
       
   386         __PHYSFS_platformDestroyMutex(errorLock);
       
   387 
       
   388     if (stateLock != NULL)
       
   389         __PHYSFS_platformDestroyMutex(stateLock);
       
   390 
       
   391     errorLock = stateLock = NULL;
       
   392     return(0);  /* failed. */
       
   393 } /* initializeMutexes */
       
   394 
       
   395 
   359 int PHYSFS_init(const char *argv0)
   396 int PHYSFS_init(const char *argv0)
   360 {
   397 {
   361     char *ptr;
   398     char *ptr;
   362 
   399 
   363     BAIL_IF_MACRO(initialized, ERR_IS_INITIALIZED, 0);
   400     BAIL_IF_MACRO(initialized, ERR_IS_INITIALIZED, 0);
   364     BAIL_IF_MACRO(argv0 == NULL, ERR_INVALID_ARGUMENT, 0);
   401     BAIL_IF_MACRO(argv0 == NULL, ERR_INVALID_ARGUMENT, 0);
   365     BAIL_IF_MACRO(!__PHYSFS_platformInit(), NULL, 0);
   402     BAIL_IF_MACRO(!__PHYSFS_platformInit(), NULL, 0);
       
   403 
       
   404     BAIL_IF_MACRO(!initializeMutexes(), NULL, 0);
   366 
   405 
   367     baseDir = calculateBaseDir(argv0);
   406     baseDir = calculateBaseDir(argv0);
   368     BAIL_IF_MACRO(baseDir == NULL, NULL, 0);
   407     BAIL_IF_MACRO(baseDir == NULL, NULL, 0);
   369     ptr = __PHYSFS_platformRealPath(baseDir);
   408     ptr = __PHYSFS_platformRealPath(baseDir);
   370     free(baseDir);
   409     free(baseDir);
   391     initialized = 1;
   430     initialized = 1;
   392     return(1);
   431     return(1);
   393 } /* PHYSFS_init */
   432 } /* PHYSFS_init */
   394 
   433 
   395 
   434 
       
   435 /* MAKE SURE you hold stateLock before calling this! */
   396 static int closeFileHandleList(FileHandleList **list)
   436 static int closeFileHandleList(FileHandleList **list)
   397 {
   437 {
   398     FileHandleList *i;
   438     FileHandleList *i;
   399     FileHandleList *next = NULL;
   439     FileHandleList *next = NULL;
   400     FileHandle *h;
   440     FileHandle *h;
   415     *list = NULL;
   455     *list = NULL;
   416     return(1);
   456     return(1);
   417 } /* closeFileHandleList */
   457 } /* closeFileHandleList */
   418 
   458 
   419 
   459 
       
   460 /* MAKE SURE you hold the stateLock before calling this! */
   420 static void freeSearchPath(void)
   461 static void freeSearchPath(void)
   421 {
   462 {
   422     DirInfo *i;
   463     DirInfo *i;
   423     DirInfo *next = NULL;
   464     DirInfo *next = NULL;
   424 
   465 
   459         userDir = NULL;
   500         userDir = NULL;
   460     } /* if */
   501     } /* if */
   461 
   502 
   462     allowSymLinks = 0;
   503     allowSymLinks = 0;
   463     initialized = 0;
   504     initialized = 0;
       
   505 
       
   506     __PHYSFS_platformDestroyMutex(errorLock);
       
   507     __PHYSFS_platformDestroyMutex(stateLock);
       
   508 
       
   509     errorLock = stateLock = NULL;
   464     return(1);
   510     return(1);
   465 } /* PHYSFS_deinit */
   511 } /* PHYSFS_deinit */
   466 
   512 
   467 
   513 
   468 const PHYSFS_ArchiveInfo **PHYSFS_supportedArchiveTypes(void)
   514 const PHYSFS_ArchiveInfo **PHYSFS_supportedArchiveTypes(void)
   505 } /* PHYSFS_getUserDir */
   551 } /* PHYSFS_getUserDir */
   506 
   552 
   507 
   553 
   508 const char *PHYSFS_getWriteDir(void)
   554 const char *PHYSFS_getWriteDir(void)
   509 {
   555 {
   510     if (writeDir == NULL)
   556     const char *retval = NULL;
   511         return(NULL);
   557 
   512 
   558     __PHYSFS_platformGrabMutex(stateLock);
   513     return(writeDir->dirName);
   559     if (writeDir != NULL)
       
   560         retval = writeDir->dirName;
       
   561     __PHYSFS_platformReleaseMutex(stateLock);
       
   562 
       
   563     return(retval);
   514 } /* PHYSFS_getWriteDir */
   564 } /* PHYSFS_getWriteDir */
   515 
   565 
   516 
   566 
   517 int PHYSFS_setWriteDir(const char *newDir)
   567 int PHYSFS_setWriteDir(const char *newDir)
   518 {
   568 {
       
   569     int retval = 1;
       
   570 
       
   571     __PHYSFS_platformGrabMutex(stateLock);
       
   572 
   519     if (writeDir != NULL)
   573     if (writeDir != NULL)
   520     {
   574     {
   521         BAIL_IF_MACRO(!freeDirInfo(writeDir, openWriteList), NULL, 0);
   575         BAIL_IF_MACRO_MUTEX(!freeDirInfo(writeDir, openWriteList), NULL, 
       
   576                             stateLock, 0);
   522         writeDir = NULL;
   577         writeDir = NULL;
   523     } /* if */
   578     } /* if */
   524 
   579 
   525     if (newDir != NULL)
   580     if (newDir != NULL)
   526     {
   581     {
   527         writeDir = buildDirInfo(newDir, 1);
   582         writeDir = buildDirInfo(newDir, 1);
   528         return(writeDir != NULL);
   583         retval = (writeDir != NULL);
   529     } /* if */
   584     } /* if */
   530 
   585 
   531     return(1);
   586     __PHYSFS_platformReleaseMutex(stateLock);
       
   587 
       
   588     return(retval);
   532 } /* PHYSFS_setWriteDir */
   589 } /* PHYSFS_setWriteDir */
   533 
   590 
   534 
   591 
   535 int PHYSFS_addToSearchPath(const char *newDir, int appendToPath)
   592 int PHYSFS_addToSearchPath(const char *newDir, int appendToPath)
   536 {
   593 {
   537     DirInfo *di;
   594     DirInfo *di;
   538     DirInfo *i = searchPath;
       
   539     DirInfo *prev = NULL;
   595     DirInfo *prev = NULL;
   540 
   596     DirInfo *i;
   541     while (i != NULL)
   597 
   542     {
   598     __PHYSFS_platformGrabMutex(stateLock);
   543         if (strcmp(newDir, i->dirName) == 0)  /* already in search path. */
   599 
   544             return(1);
   600     for (i = searchPath; i != NULL; i = i->next)
   545 
   601     {
       
   602         /* already in search path? */
       
   603         BAIL_IF_MACRO_MUTEX(strcmp(newDir, i->dirName)==0, NULL, stateLock, 1);
   546         prev = i;
   604         prev = i;
   547         i = i->next;
   605     } /* for */
   548     } /* while */
       
   549 
   606 
   550     di = buildDirInfo(newDir, 0);
   607     di = buildDirInfo(newDir, 0);
   551 
   608     BAIL_IF_MACRO_MUTEX(di == NULL, NULL, stateLock, 0);
   552     BAIL_IF_MACRO(di == NULL, NULL, 0);
       
   553 
   609 
   554     if (appendToPath)
   610     if (appendToPath)
   555     {
   611     {
   556         di->next = NULL;
   612         di->next = NULL;
   557         if (prev == NULL)
   613         if (prev == NULL)
   563     {
   619     {
   564         di->next = searchPath;
   620         di->next = searchPath;
   565         searchPath = di;
   621         searchPath = di;
   566     } /* else */
   622     } /* else */
   567 
   623 
       
   624     __PHYSFS_platformReleaseMutex(stateLock);
   568     return(1);
   625     return(1);
   569 } /* PHYSFS_addToSearchPath */
   626 } /* PHYSFS_addToSearchPath */
   570 
   627 
   571 
   628 
   572 int PHYSFS_removeFromSearchPath(const char *oldDir)
   629 int PHYSFS_removeFromSearchPath(const char *oldDir)
   575     DirInfo *prev = NULL;
   632     DirInfo *prev = NULL;
   576     DirInfo *next = NULL;
   633     DirInfo *next = NULL;
   577 
   634 
   578     BAIL_IF_MACRO(oldDir == NULL, ERR_INVALID_ARGUMENT, 0);
   635     BAIL_IF_MACRO(oldDir == NULL, ERR_INVALID_ARGUMENT, 0);
   579 
   636 
       
   637     __PHYSFS_platformGrabMutex(stateLock);
   580     for (i = searchPath; i != NULL; i = i->next)
   638     for (i = searchPath; i != NULL; i = i->next)
   581     {
   639     {
   582         if (strcmp(i->dirName, oldDir) == 0)
   640         if (strcmp(i->dirName, oldDir) == 0)
   583         {
   641         {
   584             next = i->next;
   642             next = i->next;
   585             BAIL_IF_MACRO(!freeDirInfo(i, openReadList), NULL, 0);
   643             BAIL_IF_MACRO_MUTEX(!freeDirInfo(i, openReadList), NULL,
       
   644                                 stateLock, 0);
   586 
   645 
   587             if (prev == NULL)
   646             if (prev == NULL)
   588                 searchPath = next;
   647                 searchPath = next;
   589             else
   648             else
   590                 prev->next = next;
   649                 prev->next = next;
   591 
   650 
   592             return(1);
   651             BAIL_MACRO_MUTEX(NULL, stateLock, 1);
   593         } /* if */
   652         } /* if */
   594         prev = i;
   653         prev = i;
   595     } /* for */
   654     } /* for */
   596 
   655 
   597     __PHYSFS_setError(ERR_NOT_IN_SEARCH_PATH);
   656     BAIL_MACRO_MUTEX(ERR_NOT_IN_SEARCH_PATH, stateLock, 0);
   598     return(0);
       
   599 } /* PHYSFS_removeFromSearchPath */
   657 } /* PHYSFS_removeFromSearchPath */
   600 
   658 
   601 
   659 
   602 char **PHYSFS_getSearchPath(void)
   660 char **PHYSFS_getSearchPath(void)
   603 {
   661 {
   604     int count = 1;
   662     int count = 1;
   605     int x;
   663     int x;
   606     DirInfo *i;
   664     DirInfo *i;
   607     char **retval;
   665     char **retval;
   608 
   666 
       
   667     __PHYSFS_platformGrabMutex(stateLock);
       
   668 
   609     for (i = searchPath; i != NULL; i = i->next)
   669     for (i = searchPath; i != NULL; i = i->next)
   610         count++;
   670         count++;
   611 
   671 
   612     retval = (char **) malloc(sizeof (char *) * count);
   672     retval = (char **) malloc(sizeof (char *) * count);
   613     BAIL_IF_MACRO(!retval, ERR_OUT_OF_MEMORY, NULL);
   673     BAIL_IF_MACRO_MUTEX(!retval, ERR_OUT_OF_MEMORY, stateLock, NULL);
   614     count--;
   674     count--;
   615     retval[count] = NULL;
   675     retval[count] = NULL;
   616 
   676 
   617     for (i = searchPath, x = 0; x < count; i = i->next, x++)
   677     for (i = searchPath, x = 0; x < count; i = i->next, x++)
   618     {
   678     {
   624                 x--;
   684                 x--;
   625                 free(retval[x]);
   685                 free(retval[x]);
   626             } /* while */
   686             } /* while */
   627 
   687 
   628             free(retval);
   688             free(retval);
   629             __PHYSFS_setError(ERR_OUT_OF_MEMORY);
   689             BAIL_MACRO_MUTEX(ERR_OUT_OF_MEMORY, stateLock, NULL);
   630             return(NULL);
       
   631         } /* if */
   690         } /* if */
   632 
   691 
   633         strcpy(retval[x], i->dirName);
   692         strcpy(retval[x], i->dirName);
   634     } /* for */
   693     } /* for */
   635 
   694 
       
   695     __PHYSFS_platformReleaseMutex(stateLock);
   636     return(retval);
   696     return(retval);
   637 } /* PHYSFS_getSearchPath */
   697 } /* PHYSFS_getSearchPath */
   638 
   698 
   639 
   699 
   640 int PHYSFS_setSaneConfig(const char *organization, const char *appName,
   700 int PHYSFS_setSaneConfig(const char *organization, const char *appName,
   643 {
   703 {
   644     const char *basedir = PHYSFS_getBaseDir();
   704     const char *basedir = PHYSFS_getBaseDir();
   645     const char *userdir = PHYSFS_getUserDir();
   705     const char *userdir = PHYSFS_getUserDir();
   646     const char *dirsep = PHYSFS_getDirSeparator();
   706     const char *dirsep = PHYSFS_getDirSeparator();
   647     char *str;
   707     char *str;
       
   708 
       
   709     BAIL_IF_MACRO(!initialized, ERR_NOT_INITIALIZED, 0);
   648 
   710 
   649         /* set write dir... */
   711         /* set write dir... */
   650     str = malloc(strlen(userdir) + (strlen(organization) * 2) +
   712     str = malloc(strlen(userdir) + (strlen(organization) * 2) +
   651                  (strlen(appName) * 2) + (strlen(dirsep) * 3) + 2);
   713                  (strlen(appName) * 2) + (strlen(dirsep) * 3) + 2);
   652     BAIL_IF_MACRO(str == NULL, ERR_OUT_OF_MEMORY, 0);
   714     BAIL_IF_MACRO(str == NULL, ERR_OUT_OF_MEMORY, 0);
   738 /* string manipulation in C makes my ass itch. */
   800 /* string manipulation in C makes my ass itch. */
   739 char * __PHYSFS_convertToDependent(const char *prepend,
   801 char * __PHYSFS_convertToDependent(const char *prepend,
   740                                               const char *dirName,
   802                                               const char *dirName,
   741                                               const char *append)
   803                                               const char *append)
   742 {
   804 {
   743     const char *dirsep = PHYSFS_getDirSeparator();
   805     const char *dirsep = __PHYSFS_platformDirSeparator;
   744     size_t sepsize = strlen(dirsep);
   806     size_t sepsize = strlen(dirsep);
   745     char *str;
   807     char *str;
   746     char *i1;
   808     char *i1;
   747     char *i2;
   809     char *i2;
   748     size_t allocSize;
   810     size_t allocSize;
   850     free(str);
   912     free(str);
   851     return(retval);
   913     return(retval);
   852 } /* __PHYSFS_verifySecurity */
   914 } /* __PHYSFS_verifySecurity */
   853 
   915 
   854 
   916 
   855 int PHYSFS_mkdir(const char *dirName)
   917 int PHYSFS_mkdir(const char *dname)
   856 {
   918 {
   857     DirHandle *h;
   919     DirHandle *h;
   858     char *str;
   920     char *str;
   859     char *start;
   921     char *start;
   860     char *end;
   922     char *end;
   861     int retval = 0;
   923     int retval = 0;
   862 
   924 
   863     BAIL_IF_MACRO(writeDir == NULL, ERR_NO_WRITE_DIR, 0);
   925     BAIL_IF_MACRO(dname == NULL, ERR_INVALID_ARGUMENT, 0);
   864 
   926     while (*dname == '/')
       
   927         dname++;
       
   928 
       
   929     __PHYSFS_platformGrabMutex(stateLock);
       
   930     BAIL_IF_MACRO_MUTEX(writeDir == NULL, ERR_NO_WRITE_DIR, stateLock, 0);
   865     h = writeDir->dirHandle;
   931     h = writeDir->dirHandle;
   866 
   932     BAIL_IF_MACRO_MUTEX(!h->funcs->mkdir, ERR_NOT_SUPPORTED, stateLock, 0);
   867     while (*dirName == '/')
   933     BAIL_IF_MACRO_MUTEX(!__PHYSFS_verifySecurity(h, dname), NULL, stateLock, 0);
   868         dirName++;
   934     start = str = malloc(strlen(dname) + 1);
   869 
   935     BAIL_IF_MACRO_MUTEX(str == NULL, ERR_OUT_OF_MEMORY, stateLock, 0);
   870     BAIL_IF_MACRO(h->funcs->mkdir == NULL, ERR_NOT_SUPPORTED, 0);
   936     strcpy(str, dname);
   871     BAIL_IF_MACRO(!__PHYSFS_verifySecurity(h, dirName), NULL, 0);
       
   872 
       
   873     start = str = malloc(strlen(dirName) + 1);
       
   874     BAIL_IF_MACRO(str == NULL, ERR_OUT_OF_MEMORY, 0);
       
   875     strcpy(str, dirName);
       
   876 
   937 
   877     while (1)
   938     while (1)
   878     {
   939     {
   879         end = strchr(start, '/');
   940         end = strchr(start, '/');
   880         if (end != NULL)
   941         if (end != NULL)
   889 
   950 
   890         *end = '/';
   951         *end = '/';
   891         start = end + 1;
   952         start = end + 1;
   892     } /* while */
   953     } /* while */
   893 
   954 
       
   955     __PHYSFS_platformReleaseMutex(stateLock);
       
   956 
   894     free(str);
   957     free(str);
   895     return(retval);
   958     return(retval);
   896 } /* PHYSFS_mkdir */
   959 } /* PHYSFS_mkdir */
   897 
   960 
   898 
   961 
   899 int PHYSFS_delete(const char *fname)
   962 int PHYSFS_delete(const char *fname)
   900 {
   963 {
       
   964     int retval;
   901     DirHandle *h;
   965     DirHandle *h;
   902     BAIL_IF_MACRO(writeDir == NULL, ERR_NO_WRITE_DIR, 0);
   966 
   903     h = writeDir->dirHandle;
   967     BAIL_IF_MACRO(fname == NULL, ERR_INVALID_ARGUMENT, 0);
   904     BAIL_IF_MACRO(h->funcs->remove == NULL, ERR_NOT_SUPPORTED, 0);
       
   905 
       
   906     while (*fname == '/')
   968     while (*fname == '/')
   907         fname++;
   969         fname++;
   908 
   970 
   909     BAIL_IF_MACRO(!__PHYSFS_verifySecurity(h, fname), NULL, 0);
   971     __PHYSFS_platformGrabMutex(stateLock);
   910     return(h->funcs->remove(h, fname));
   972 
       
   973     BAIL_IF_MACRO_MUTEX(writeDir == NULL, ERR_NO_WRITE_DIR, stateLock, 0);
       
   974     h = writeDir->dirHandle;
       
   975     BAIL_IF_MACRO_MUTEX(!h->funcs->remove, ERR_NOT_SUPPORTED, stateLock, 0);
       
   976     BAIL_IF_MACRO_MUTEX(!__PHYSFS_verifySecurity(h, fname), NULL, stateLock, 0);
       
   977     retval = h->funcs->remove(h, fname);
       
   978 
       
   979     __PHYSFS_platformReleaseMutex(stateLock);
       
   980     return(retval);
   911 } /* PHYSFS_delete */
   981 } /* PHYSFS_delete */
   912 
   982 
   913 
   983 
   914 const char *PHYSFS_getRealDir(const char *filename)
   984 const char *PHYSFS_getRealDir(const char *filename)
   915 {
   985 {
   916     DirInfo *i;
   986     DirInfo *i;
   917 
   987 
   918     while (*filename == '/')
   988     while (*filename == '/')
   919         filename++;
   989         filename++;
   920 
   990 
       
   991     __PHYSFS_platformGrabMutex(stateLock);
   921     for (i = searchPath; i != NULL; i = i->next)
   992     for (i = searchPath; i != NULL; i = i->next)
   922     {
   993     {
   923         DirHandle *h = i->dirHandle;
   994         DirHandle *h = i->dirHandle;
   924         if (__PHYSFS_verifySecurity(h, filename))
   995         if (__PHYSFS_verifySecurity(h, filename))
   925         {
   996         {
   926             if (h->funcs->exists(h, filename))
   997             if (h->funcs->exists(h, filename))
       
   998             {
       
   999                 __PHYSFS_platformReleaseMutex(stateLock);
   927                 return(i->dirName);
  1000                 return(i->dirName);
       
  1001             } /* if */
   928         } /* if */
  1002         } /* if */
   929     } /* for */
  1003     } /* for */
       
  1004     __PHYSFS_platformReleaseMutex(stateLock);
   930 
  1005 
   931     return(NULL);
  1006     return(NULL);
   932 } /* PHYSFS_getRealDir */
  1007 } /* PHYSFS_getRealDir */
   933 
  1008 
   934 
  1009 
  1027     char **retval = NULL;
  1102     char **retval = NULL;
  1028     LinkedStringList *rc;
  1103     LinkedStringList *rc;
  1029     LinkedStringList *finalList = NULL;
  1104     LinkedStringList *finalList = NULL;
  1030     int omitSymLinks = !allowSymLinks;
  1105     int omitSymLinks = !allowSymLinks;
  1031 
  1106 
       
  1107     BAIL_IF_MACRO(path == NULL, ERR_INVALID_ARGUMENT, NULL);
  1032     while (*path == '/')
  1108     while (*path == '/')
  1033         path++;
  1109         path++;
  1034 
  1110 
       
  1111     __PHYSFS_platformGrabMutex(stateLock);
  1035     for (i = searchPath; i != NULL; i = i->next)
  1112     for (i = searchPath; i != NULL; i = i->next)
  1036     {
  1113     {
  1037         DirHandle *h = i->dirHandle;
  1114         DirHandle *h = i->dirHandle;
  1038         if (__PHYSFS_verifySecurity(h, path))
  1115         if (__PHYSFS_verifySecurity(h, path))
  1039         {
  1116         {
  1040             rc = h->funcs->enumerateFiles(h, path, omitSymLinks);
  1117             rc = h->funcs->enumerateFiles(h, path, omitSymLinks);
  1041             interpolateStringLists(&finalList, rc);
  1118             interpolateStringLists(&finalList, rc);
  1042         } /* if */
  1119         } /* if */
  1043     } /* for */
  1120     } /* for */
       
  1121     __PHYSFS_platformReleaseMutex(stateLock);
  1044 
  1122 
  1045     retval = convertStringListToPhysFSList(finalList);
  1123     retval = convertStringListToPhysFSList(finalList);
  1046     return(retval);
  1124     return(retval);
  1047 } /* PHYSFS_enumerateFiles */
  1125 } /* PHYSFS_enumerateFiles */
  1048 
  1126 
  1049 
  1127 
  1050 int PHYSFS_exists(const char *fname)
  1128 int PHYSFS_exists(const char *fname)
  1051 {
  1129 {
       
  1130     BAIL_IF_MACRO(fname == NULL, ERR_INVALID_ARGUMENT, 0);
  1052     while (*fname == '/')
  1131     while (*fname == '/')
  1053         fname++;
  1132         fname++;
  1054 
  1133 
  1055     return(PHYSFS_getRealDir(fname) != NULL);
  1134     return(PHYSFS_getRealDir(fname) != NULL);
  1056 } /* PHYSFS_exists */
  1135 } /* PHYSFS_exists */
  1058 
  1137 
  1059 int PHYSFS_isDirectory(const char *fname)
  1138 int PHYSFS_isDirectory(const char *fname)
  1060 {
  1139 {
  1061     DirInfo *i;
  1140     DirInfo *i;
  1062 
  1141 
       
  1142     BAIL_IF_MACRO(fname == NULL, ERR_INVALID_ARGUMENT, 0);
  1063     while (*fname == '/')
  1143     while (*fname == '/')
  1064         fname++;
  1144         fname++;
  1065 
  1145 
  1066     if (*fname == '\0')
  1146     if (*fname == '\0')
  1067         return(1);
  1147         return(1);
  1068 
  1148 
       
  1149     __PHYSFS_platformGrabMutex(stateLock);
  1069     for (i = searchPath; i != NULL; i = i->next)
  1150     for (i = searchPath; i != NULL; i = i->next)
  1070     {
  1151     {
  1071         DirHandle *h = i->dirHandle;
  1152         DirHandle *h = i->dirHandle;
  1072         if (__PHYSFS_verifySecurity(h, fname))
  1153         if (__PHYSFS_verifySecurity(h, fname))
  1073         {
  1154         {
  1074             if (h->funcs->exists(h, fname))
  1155             if (h->funcs->exists(h, fname))
  1075                 return(h->funcs->isDirectory(h, fname));
  1156             {
       
  1157                 int retval = h->funcs->isDirectory(h, fname);
       
  1158                 __PHYSFS_platformReleaseMutex(stateLock);
       
  1159                 return(retval);
       
  1160             } /* if */
  1076         } /* if */
  1161         } /* if */
  1077     } /* for */
  1162     } /* for */
       
  1163     __PHYSFS_platformReleaseMutex(stateLock);
  1078 
  1164 
  1079     return(0);
  1165     return(0);
  1080 } /* PHYSFS_isDirectory */
  1166 } /* PHYSFS_isDirectory */
  1081 
  1167 
  1082 
  1168 
  1085     DirInfo *i;
  1171     DirInfo *i;
  1086 
  1172 
  1087     if (!allowSymLinks)
  1173     if (!allowSymLinks)
  1088         return(0);
  1174         return(0);
  1089 
  1175 
       
  1176     BAIL_IF_MACRO(fname == NULL, ERR_INVALID_ARGUMENT, 0);
  1090     while (*fname == '/')
  1177     while (*fname == '/')
  1091         fname++;
  1178         fname++;
  1092 
  1179 
       
  1180     __PHYSFS_platformGrabMutex(stateLock);
  1093     for (i = searchPath; i != NULL; i = i->next)
  1181     for (i = searchPath; i != NULL; i = i->next)
  1094     {
  1182     {
  1095         DirHandle *h = i->dirHandle;
  1183         DirHandle *h = i->dirHandle;
  1096         if (__PHYSFS_verifySecurity(h, fname))
  1184         if (__PHYSFS_verifySecurity(h, fname))
  1097         {
  1185         {
  1098             if (h->funcs->exists(h, fname))
  1186             if (h->funcs->exists(h, fname))
  1099                 return(h->funcs->isSymLink(h, fname));
  1187             {
       
  1188                 int retval = h->funcs->isSymLink(h, fname);
       
  1189                 __PHYSFS_platformReleaseMutex(stateLock);
       
  1190                 return(retval);
       
  1191             } /* if */
  1100         } /* if */
  1192         } /* if */
  1101     } /* for */
  1193     } /* for */
       
  1194 
       
  1195 /* !!! FIXME: setError ERR_FILE_NOT_FOUND? */
       
  1196     __PHYSFS_platformReleaseMutex(stateLock);
  1102 
  1197 
  1103     return(0);
  1198     return(0);
  1104 } /* PHYSFS_isSymbolicLink */
  1199 } /* PHYSFS_isSymbolicLink */
  1105 
  1200 
  1106 
  1201 
  1107 static PHYSFS_file *doOpenWrite(const char *fname, int appending)
  1202 static PHYSFS_file *doOpenWrite(const char *fname, int appending)
  1108 {
  1203 {
  1109     PHYSFS_file *retval = NULL;
  1204     PHYSFS_file *retval = NULL;
  1110     FileHandle *rc = NULL;
  1205     FileHandle *rc = NULL;
  1111     DirHandle *h = (writeDir == NULL) ? NULL : writeDir->dirHandle;
  1206     DirHandle *h;
  1112     const DirFunctions *f = (h == NULL) ? NULL : h->funcs;
  1207     const DirFunctions *f;
  1113     FileHandleList *list;
  1208     FileHandleList *list;
  1114 
  1209 
       
  1210     BAIL_IF_MACRO(fname == NULL, ERR_INVALID_ARGUMENT, NULL);
  1115     while (*fname == '/')
  1211     while (*fname == '/')
  1116         fname++;
  1212         fname++;
  1117 
  1213 
  1118     BAIL_IF_MACRO(!h, ERR_NO_WRITE_DIR, NULL);
  1214     __PHYSFS_platformGrabMutex(stateLock);
  1119     BAIL_IF_MACRO(!__PHYSFS_verifySecurity(h, fname), NULL, NULL);
  1215     h = (writeDir == NULL) ? NULL : writeDir->dirHandle;
       
  1216     BAIL_IF_MACRO_MUTEX(!h, ERR_NO_WRITE_DIR, stateLock, NULL);
       
  1217     BAIL_IF_MACRO_MUTEX(!__PHYSFS_verifySecurity(h, fname), NULL,
       
  1218                         stateLock, NULL);
  1120 
  1219 
  1121     list = (FileHandleList *) malloc(sizeof (FileHandleList));
  1220     list = (FileHandleList *) malloc(sizeof (FileHandleList));
  1122     BAIL_IF_MACRO(!list, ERR_OUT_OF_MEMORY, NULL);
  1221     BAIL_IF_MACRO_MUTEX(!list, ERR_OUT_OF_MEMORY, stateLock, NULL);
  1123 
  1222 
       
  1223     f = h->funcs;
  1124     rc = (appending) ? f->openAppend(h, fname) : f->openWrite(h, fname);
  1224     rc = (appending) ? f->openAppend(h, fname) : f->openWrite(h, fname);
  1125     if (rc == NULL)
  1225     if (rc == NULL)
  1126         free(list);
  1226         free(list);
  1127     else
  1227     else
  1128     {
  1228     {
  1130         list->next = openWriteList;
  1230         list->next = openWriteList;
  1131         openWriteList = list;
  1231         openWriteList = list;
  1132         retval = &(list->handle);
  1232         retval = &(list->handle);
  1133     } /* else */
  1233     } /* else */
  1134 
  1234 
       
  1235     __PHYSFS_platformReleaseMutex(stateLock);
  1135     return(retval);
  1236     return(retval);
  1136 } /* doOpenWrite */
  1237 } /* doOpenWrite */
  1137 
  1238 
  1138 
  1239 
  1139 PHYSFS_file *PHYSFS_openWrite(const char *filename)
  1240 PHYSFS_file *PHYSFS_openWrite(const char *filename)
  1148 } /* PHYSFS_openAppend */
  1249 } /* PHYSFS_openAppend */
  1149 
  1250 
  1150 
  1251 
  1151 PHYSFS_file *PHYSFS_openRead(const char *fname)
  1252 PHYSFS_file *PHYSFS_openRead(const char *fname)
  1152 {
  1253 {
       
  1254     PHYSFS_file *retval;
  1153     FileHandle *rc = NULL;
  1255     FileHandle *rc = NULL;
  1154     FileHandleList *list;
  1256     FileHandleList *list;
  1155     DirInfo *i;
  1257     DirInfo *i;
  1156 
  1258 
       
  1259     BAIL_IF_MACRO(fname == NULL, ERR_INVALID_ARGUMENT, NULL);
  1157     while (*fname == '/')
  1260     while (*fname == '/')
  1158         fname++;
  1261         fname++;
  1159 
  1262 
       
  1263     __PHYSFS_platformGrabMutex(stateLock);
  1160     for (i = searchPath; i != NULL; i = i->next)
  1264     for (i = searchPath; i != NULL; i = i->next)
  1161     {
  1265     {
  1162         DirHandle *h = i->dirHandle;
  1266         DirHandle *h = i->dirHandle;
  1163         if (__PHYSFS_verifySecurity(h, fname))
  1267         if (__PHYSFS_verifySecurity(h, fname))
  1164         {
  1268         {
  1166             if (rc != NULL)
  1270             if (rc != NULL)
  1167                 break;
  1271                 break;
  1168         } /* if */
  1272         } /* if */
  1169     } /* for */
  1273     } /* for */
  1170 
  1274 
  1171     if (rc == NULL)
  1275     BAIL_IF_MACRO_MUTEX(rc == NULL, NULL, stateLock, NULL);
  1172         return(NULL);
       
  1173 
  1276 
  1174     list = (FileHandleList *) malloc(sizeof (FileHandleList));
  1277     list = (FileHandleList *) malloc(sizeof (FileHandleList));
  1175     BAIL_IF_MACRO(!list, ERR_OUT_OF_MEMORY, NULL);
  1278     BAIL_IF_MACRO(!list, ERR_OUT_OF_MEMORY, NULL);
  1176     list->handle.opaque = (void *) rc;
  1279     list->handle.opaque = (void *) rc;
  1177     list->next = openReadList;
  1280     list->next = openReadList;
  1178     openReadList = list;
  1281     openReadList = list;
  1179 
  1282     retval = &(list->handle);
  1180     return(&(list->handle));
  1283 
       
  1284     __PHYSFS_platformReleaseMutex(stateLock);
       
  1285     return(retval);
  1181 } /* PHYSFS_openRead */
  1286 } /* PHYSFS_openRead */
  1182 
  1287 
  1183 
  1288 
  1184 static int closeHandleInOpenList(FileHandleList **list, PHYSFS_file *handle)
  1289 static int closeHandleInOpenList(FileHandleList **list, PHYSFS_file *handle)
  1185 {
  1290 {
  1213 
  1318 
  1214 int PHYSFS_close(PHYSFS_file *handle)
  1319 int PHYSFS_close(PHYSFS_file *handle)
  1215 {
  1320 {
  1216     int rc;
  1321     int rc;
  1217 
  1322 
       
  1323     __PHYSFS_platformGrabMutex(stateLock);
       
  1324 
  1218     /* -1 == close failure. 0 == not found. 1 == success. */
  1325     /* -1 == close failure. 0 == not found. 1 == success. */
  1219     rc = closeHandleInOpenList(&openReadList, handle);
  1326     rc = closeHandleInOpenList(&openReadList, handle);
  1220     BAIL_IF_MACRO(rc == -1, NULL, 0);
  1327     BAIL_IF_MACRO_MUTEX(rc == -1, NULL, stateLock, 0);
  1221     if (!rc)
  1328     if (!rc)
  1222     {
  1329     {
  1223         rc = closeHandleInOpenList(&openWriteList, handle);
  1330         rc = closeHandleInOpenList(&openWriteList, handle);
  1224         BAIL_IF_MACRO(rc == -1, NULL, 0);
  1331         BAIL_IF_MACRO_MUTEX(rc == -1, NULL, stateLock, 0);
  1225     } /* if */
  1332     } /* if */
  1226 
  1333 
  1227     if (!rc)
  1334     __PHYSFS_platformReleaseMutex(stateLock);
  1228         __PHYSFS_setError(ERR_NOT_A_HANDLE);
  1335     BAIL_IF_MACRO(!rc, ERR_NOT_A_HANDLE, 0);
  1229 
  1336     return(1);
  1230     return(rc);
       
  1231 } /* PHYSFS_close */
  1337 } /* PHYSFS_close */
  1232 
  1338 
  1233 
  1339 
  1234 PHYSFS_sint64 PHYSFS_read(PHYSFS_file *handle, void *buffer,
  1340 PHYSFS_sint64 PHYSFS_read(PHYSFS_file *handle, void *buffer,
  1235                           PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)
  1341                           PHYSFS_uint32 objSize, PHYSFS_uint32 objCount)