archiver_dir.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  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,
  12. char *buf, const size_t buflen)
  13. {
  14. BAIL_IF(buf == NULL, PHYSFS_ERR_OUT_OF_MEMORY, NULL);
  15. snprintf(buf, buflen, "%s%s", prepend ? prepend : "", path);
  16. if (__PHYSFS_platformDirSeparator != '/')
  17. {
  18. char *p;
  19. for (p = strchr(buf, '/'); p != NULL; p = strchr(p + 1, '/'))
  20. *p = __PHYSFS_platformDirSeparator;
  21. } /* if */
  22. return buf;
  23. } /* cvtToDependent */
  24. #define CVT_TO_DEPENDENT(buf, pre, dir) { \
  25. const size_t len = ((pre) ? strlen((char *) pre) : 0) + strlen(dir) + 1; \
  26. buf = cvtToDependent((char*)pre,dir,(char*)__PHYSFS_smallAlloc(len),len); \
  27. }
  28. static void *DIR_openArchive(PHYSFS_Io *io, const char *name, int forWriting)
  29. {
  30. PHYSFS_Stat st;
  31. const char dirsep = __PHYSFS_platformDirSeparator;
  32. char *retval = NULL;
  33. const size_t namelen = strlen(name);
  34. const size_t seplen = 1;
  35. assert(io == NULL); /* shouldn't create an Io for these. */
  36. BAIL_IF_ERRPASS(!__PHYSFS_platformStat(name, &st), NULL);
  37. if (st.filetype != PHYSFS_FILETYPE_DIRECTORY)
  38. BAIL(PHYSFS_ERR_UNSUPPORTED, NULL);
  39. retval = allocator.Malloc(namelen + seplen + 1);
  40. BAIL_IF(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, const int mode)
  63. {
  64. PHYSFS_Io *io = NULL;
  65. char *f = NULL;
  66. CVT_TO_DEPENDENT(f, opaque, name);
  67. BAIL_IF_ERRPASS(!f, NULL);
  68. io = __PHYSFS_createNativeIo(f, mode);
  69. if (io == NULL)
  70. {
  71. const PHYSFS_ErrorCode err = PHYSFS_getLastErrorCode();
  72. PHYSFS_Stat statbuf;
  73. __PHYSFS_platformStat(f, &statbuf);
  74. PHYSFS_setErrorCode(err);
  75. } /* if */
  76. __PHYSFS_smallFree(f);
  77. return io;
  78. } /* doOpen */
  79. static PHYSFS_Io *DIR_openRead(void *opaque, const char *filename)
  80. {
  81. return doOpen(opaque, filename, 'r');
  82. } /* DIR_openRead */
  83. static PHYSFS_Io *DIR_openWrite(void *opaque, const char *filename)
  84. {
  85. return doOpen(opaque, filename, 'w');
  86. } /* DIR_openWrite */
  87. static PHYSFS_Io *DIR_openAppend(void *opaque, const char *filename)
  88. {
  89. return doOpen(opaque, filename, 'a');
  90. } /* DIR_openAppend */
  91. static int DIR_remove(void *opaque, const char *name)
  92. {
  93. int retval;
  94. char *f;
  95. CVT_TO_DEPENDENT(f, opaque, name);
  96. BAIL_IF_ERRPASS(!f, 0);
  97. retval = __PHYSFS_platformDelete(f);
  98. __PHYSFS_smallFree(f);
  99. return retval;
  100. } /* DIR_remove */
  101. static int DIR_mkdir(void *opaque, const char *name)
  102. {
  103. int retval;
  104. char *f;
  105. CVT_TO_DEPENDENT(f, opaque, name);
  106. BAIL_IF_ERRPASS(!f, 0);
  107. retval = __PHYSFS_platformMkDir(f);
  108. __PHYSFS_smallFree(f);
  109. return retval;
  110. } /* DIR_mkdir */
  111. static void DIR_closeArchive(void *opaque)
  112. {
  113. allocator.Free(opaque);
  114. } /* DIR_closeArchive */
  115. static int DIR_stat(void *opaque, const char *name, PHYSFS_Stat *stat)
  116. {
  117. int retval = 0;
  118. char *d;
  119. CVT_TO_DEPENDENT(d, opaque, name);
  120. BAIL_IF_ERRPASS(!d, 0);
  121. retval = __PHYSFS_platformStat(d, stat);
  122. __PHYSFS_smallFree(d);
  123. return retval;
  124. } /* DIR_stat */
  125. const PHYSFS_Archiver __PHYSFS_Archiver_DIR =
  126. {
  127. CURRENT_PHYSFS_ARCHIVER_API_VERSION,
  128. {
  129. "",
  130. "Non-archive, direct filesystem I/O",
  131. "Ryan C. Gordon <icculus@icculus.org>",
  132. "https://icculus.org/physfs/",
  133. 1, /* supportsSymlinks */
  134. },
  135. DIR_openArchive,
  136. DIR_enumerateFiles,
  137. DIR_openRead,
  138. DIR_openWrite,
  139. DIR_openAppend,
  140. DIR_remove,
  141. DIR_mkdir,
  142. DIR_stat,
  143. DIR_closeArchive
  144. };
  145. /* end of archiver_dir.c ... */