archiver_dir.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  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(void *opaque, const char *dname,
  51. 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, cb, origdir, callbackdata);
  59. __PHYSFS_smallFree(d);
  60. } /* if */
  61. } /* DIR_enumerateFiles */
  62. static PHYSFS_Io *doOpen(void *opaque, const char *name,
  63. const int mode, int *fileExists)
  64. {
  65. char *f;
  66. PHYSFS_Io *io = NULL;
  67. int existtmp = 0;
  68. CVT_TO_DEPENDENT(f, opaque, name);
  69. BAIL_IF_MACRO(!f, ERRPASS, NULL);
  70. if (fileExists == NULL)
  71. fileExists = &existtmp;
  72. io = __PHYSFS_createNativeIo(f, mode);
  73. if (io == NULL)
  74. {
  75. const PHYSFS_ErrorCode err = PHYSFS_getLastErrorCode();
  76. PHYSFS_Stat statbuf;
  77. __PHYSFS_platformStat(f, fileExists, &statbuf);
  78. __PHYSFS_setError(err);
  79. } /* if */
  80. else
  81. {
  82. *fileExists = 1;
  83. } /* else */
  84. __PHYSFS_smallFree(f);
  85. return io;
  86. } /* doOpen */
  87. static PHYSFS_Io *DIR_openRead(void *opaque, const char *fnm, int *exist)
  88. {
  89. return doOpen(opaque, fnm, 'r', exist);
  90. } /* DIR_openRead */
  91. static PHYSFS_Io *DIR_openWrite(void *opaque, const char *filename)
  92. {
  93. return doOpen(opaque, filename, 'w', NULL);
  94. } /* DIR_openWrite */
  95. static PHYSFS_Io *DIR_openAppend(void *opaque, const char *filename)
  96. {
  97. return doOpen(opaque, filename, 'a', NULL);
  98. } /* DIR_openAppend */
  99. static int DIR_remove(void *opaque, const char *name)
  100. {
  101. int retval;
  102. char *f;
  103. CVT_TO_DEPENDENT(f, opaque, name);
  104. BAIL_IF_MACRO(!f, ERRPASS, 0);
  105. retval = __PHYSFS_platformDelete(f);
  106. __PHYSFS_smallFree(f);
  107. return retval;
  108. } /* DIR_remove */
  109. static int DIR_mkdir(void *opaque, const char *name)
  110. {
  111. int retval;
  112. char *f;
  113. CVT_TO_DEPENDENT(f, opaque, name);
  114. BAIL_IF_MACRO(!f, ERRPASS, 0);
  115. retval = __PHYSFS_platformMkDir(f);
  116. __PHYSFS_smallFree(f);
  117. return retval;
  118. } /* DIR_mkdir */
  119. static void DIR_closeArchive(void *opaque)
  120. {
  121. allocator.Free(opaque);
  122. } /* DIR_closeArchive */
  123. static int DIR_stat(void *opaque, const char *name,
  124. int *exists, PHYSFS_Stat *stat)
  125. {
  126. int retval = 0;
  127. char *d;
  128. CVT_TO_DEPENDENT(d, opaque, name);
  129. BAIL_IF_MACRO(!d, ERRPASS, 0);
  130. retval = __PHYSFS_platformStat(d, exists, stat);
  131. __PHYSFS_smallFree(d);
  132. return retval;
  133. } /* DIR_stat */
  134. const PHYSFS_Archiver __PHYSFS_Archiver_DIR =
  135. {
  136. CURRENT_PHYSFS_ARCHIVER_API_VERSION,
  137. {
  138. "",
  139. "Non-archive, direct filesystem I/O",
  140. "Ryan C. Gordon <icculus@icculus.org>",
  141. "http://icculus.org/physfs/",
  142. 1, /* supportsSymlinks */
  143. },
  144. DIR_openArchive, /* openArchive() method */
  145. DIR_enumerateFiles, /* enumerateFiles() method */
  146. DIR_openRead, /* openRead() method */
  147. DIR_openWrite, /* openWrite() method */
  148. DIR_openAppend, /* openAppend() method */
  149. DIR_remove, /* remove() method */
  150. DIR_mkdir, /* mkdir() method */
  151. DIR_closeArchive, /* closeArchive() method */
  152. DIR_stat /* stat() method */
  153. };
  154. /* end of archiver_dir.c ... */