archiver_dir.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. /*
  2. * Standard directory I/O support routines for PhysicsFS.
  3. *
  4. * Please see the file LICENSE.txt in the source's root directory.
  5. *
  6. * This file written by Ryan C. Gordon.
  7. */
  8. #define __PHYSICSFS_INTERNAL__
  9. #include "physfs_internal.h"
  10. /* There's no PHYSFS_Io interface here. Use __PHYSFS_createNativeIo(). */
  11. static char *cvtToDependent(const char *prepend, const char *path, char *buf)
  12. {
  13. BAIL_IF_MACRO(buf == NULL, PHYSFS_ERR_OUT_OF_MEMORY, NULL);
  14. sprintf(buf, "%s%s", prepend ? prepend : "", path);
  15. if (__PHYSFS_platformDirSeparator != '/')
  16. {
  17. char *p;
  18. for (p = strchr(buf, '/'); p != NULL; p = strchr(p + 1, '/'))
  19. *p = __PHYSFS_platformDirSeparator;
  20. } /* if */
  21. return buf;
  22. } /* cvtToDependent */
  23. #define CVT_TO_DEPENDENT(buf, pre, dir) { \
  24. const size_t len = ((pre) ? strlen((char *) pre) : 0) + strlen(dir) + 1; \
  25. buf = cvtToDependent((char*)pre,dir,(char*)__PHYSFS_smallAlloc(len)); \
  26. }
  27. static void *DIR_openArchive(PHYSFS_Io *io, const char *name, int forWriting)
  28. {
  29. PHYSFS_Stat st;
  30. const char dirsep = __PHYSFS_platformDirSeparator;
  31. char *retval = NULL;
  32. const size_t namelen = strlen(name);
  33. const size_t seplen = 1;
  34. int exists = 0;
  35. assert(io == NULL); /* shouldn't create an Io for these. */
  36. BAIL_IF_MACRO(!__PHYSFS_platformStat(name, &exists, &st), ERRPASS, NULL);
  37. if (st.filetype != PHYSFS_FILETYPE_DIRECTORY)
  38. BAIL_MACRO(PHYSFS_ERR_UNSUPPORTED, NULL);
  39. retval = allocator.Malloc(namelen + seplen + 1);
  40. BAIL_IF_MACRO(retval == NULL, PHYSFS_ERR_OUT_OF_MEMORY, NULL);
  41. strcpy(retval, name);
  42. /* make sure there's a dir separator at the end of the string */
  43. if (retval[namelen - 1] != dirsep)
  44. {
  45. retval[namelen] = dirsep;
  46. retval[namelen + 1] = '\0';
  47. } /* if */
  48. return retval;
  49. } /* DIR_openArchive */
  50. static void DIR_enumerateFiles(dvoid *opaque, const char *dname,
  51. int omitSymLinks, PHYSFS_EnumFilesCallback cb,
  52. const char *origdir, void *callbackdata)
  53. {
  54. char *d;
  55. CVT_TO_DEPENDENT(d, opaque, dname);
  56. if (d != NULL)
  57. {
  58. __PHYSFS_platformEnumerateFiles(d, omitSymLinks, cb,
  59. origdir, callbackdata);
  60. __PHYSFS_smallFree(d);
  61. } /* if */
  62. } /* DIR_enumerateFiles */
  63. static PHYSFS_Io *doOpen(dvoid *opaque, const char *name,
  64. const int mode, int *fileExists)
  65. {
  66. char *f;
  67. PHYSFS_Io *io = NULL;
  68. int existtmp = 0;
  69. CVT_TO_DEPENDENT(f, opaque, name);
  70. BAIL_IF_MACRO(!f, ERRPASS, NULL);
  71. if (fileExists == NULL)
  72. fileExists = &existtmp;
  73. io = __PHYSFS_createNativeIo(f, mode);
  74. if (io == NULL)
  75. {
  76. const PHYSFS_ErrorCode err = PHYSFS_getLastErrorCode();
  77. PHYSFS_Stat statbuf;
  78. __PHYSFS_platformStat(f, fileExists, &statbuf);
  79. __PHYSFS_setError(err);
  80. } /* if */
  81. else
  82. {
  83. *fileExists = 1;
  84. } /* else */
  85. __PHYSFS_smallFree(f);
  86. return io;
  87. } /* doOpen */
  88. static PHYSFS_Io *DIR_openRead(dvoid *opaque, const char *fnm, int *exist)
  89. {
  90. return doOpen(opaque, fnm, 'r', exist);
  91. } /* DIR_openRead */
  92. static PHYSFS_Io *DIR_openWrite(dvoid *opaque, const char *filename)
  93. {
  94. return doOpen(opaque, filename, 'w', NULL);
  95. } /* DIR_openWrite */
  96. static PHYSFS_Io *DIR_openAppend(dvoid *opaque, const char *filename)
  97. {
  98. return doOpen(opaque, filename, 'a', NULL);
  99. } /* DIR_openAppend */
  100. static int DIR_remove(dvoid *opaque, const char *name)
  101. {
  102. int retval;
  103. char *f;
  104. CVT_TO_DEPENDENT(f, opaque, name);
  105. BAIL_IF_MACRO(!f, ERRPASS, 0);
  106. retval = __PHYSFS_platformDelete(f);
  107. __PHYSFS_smallFree(f);
  108. return retval;
  109. } /* DIR_remove */
  110. static int DIR_mkdir(dvoid *opaque, const char *name)
  111. {
  112. int retval;
  113. char *f;
  114. CVT_TO_DEPENDENT(f, opaque, name);
  115. BAIL_IF_MACRO(!f, ERRPASS, 0);
  116. retval = __PHYSFS_platformMkDir(f);
  117. __PHYSFS_smallFree(f);
  118. return retval;
  119. } /* DIR_mkdir */
  120. static void DIR_dirClose(dvoid *opaque)
  121. {
  122. allocator.Free(opaque);
  123. } /* DIR_dirClose */
  124. static int DIR_stat(dvoid *opaque, const char *name, int *exists,
  125. PHYSFS_Stat *stat)
  126. {
  127. int retval = 0;
  128. char *d;
  129. CVT_TO_DEPENDENT(d, opaque, name);
  130. BAIL_IF_MACRO(!d, ERRPASS, 0);
  131. retval = __PHYSFS_platformStat(d, exists, stat);
  132. __PHYSFS_smallFree(d);
  133. return retval;
  134. } /* DIR_stat */
  135. const PHYSFS_ArchiveInfo __PHYSFS_ArchiveInfo_DIR =
  136. {
  137. "",
  138. DIR_ARCHIVE_DESCRIPTION,
  139. "Ryan C. Gordon <icculus@icculus.org>",
  140. "http://icculus.org/physfs/",
  141. };
  142. const PHYSFS_Archiver __PHYSFS_Archiver_DIR =
  143. {
  144. &__PHYSFS_ArchiveInfo_DIR,
  145. DIR_openArchive, /* openArchive() method */
  146. DIR_enumerateFiles, /* enumerateFiles() method */
  147. DIR_openRead, /* openRead() method */
  148. DIR_openWrite, /* openWrite() method */
  149. DIR_openAppend, /* openAppend() method */
  150. DIR_remove, /* remove() method */
  151. DIR_mkdir, /* mkdir() method */
  152. DIR_dirClose, /* dirClose() method */
  153. DIR_stat /* stat() method */
  154. };
  155. /* end of dir.c ... */