physfs_archiver_dir.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  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_STANDARD_DIRSEP
  17. assert(__PHYSFS_platformDirSeparator != '/');
  18. {
  19. char *p;
  20. for (p = strchr(buf, '/'); p != NULL; p = strchr(p + 1, '/'))
  21. *p = __PHYSFS_platformDirSeparator;
  22. } /* if */
  23. #endif
  24. return buf;
  25. } /* cvtToDependent */
  26. #define CVT_TO_DEPENDENT(buf, pre, dir) { \
  27. const size_t len = ((pre) ? strlen((char *) pre) : 0) + strlen(dir) + 1; \
  28. buf = cvtToDependent((char*)pre,dir,(char*)__PHYSFS_smallAlloc(len),len); \
  29. }
  30. static void *DIR_openArchive(PHYSFS_Io *io, const char *name,
  31. int forWriting, int *claimed)
  32. {
  33. PHYSFS_Stat st;
  34. const char dirsep = __PHYSFS_platformDirSeparator;
  35. char *retval = NULL;
  36. const size_t namelen = strlen(name);
  37. const size_t seplen = 1;
  38. assert(io == NULL); /* shouldn't create an Io for these. */
  39. BAIL_IF_ERRPASS(!__PHYSFS_platformStat(name, &st, 1), NULL);
  40. if (st.filetype != PHYSFS_FILETYPE_DIRECTORY)
  41. BAIL(PHYSFS_ERR_UNSUPPORTED, NULL);
  42. *claimed = 1;
  43. retval = allocator.Malloc(namelen + seplen + 1);
  44. BAIL_IF(retval == NULL, PHYSFS_ERR_OUT_OF_MEMORY, NULL);
  45. strcpy(retval, name);
  46. /* make sure there's a dir separator at the end of the string */
  47. if (retval[namelen - 1] != dirsep)
  48. {
  49. retval[namelen] = dirsep;
  50. retval[namelen + 1] = '\0';
  51. } /* if */
  52. return retval;
  53. } /* DIR_openArchive */
  54. static PHYSFS_EnumerateCallbackResult DIR_enumerate(void *opaque,
  55. const char *dname, PHYSFS_EnumerateCallback cb,
  56. const char *origdir, void *callbackdata)
  57. {
  58. char *d;
  59. PHYSFS_EnumerateCallbackResult retval;
  60. CVT_TO_DEPENDENT(d, opaque, dname);
  61. BAIL_IF_ERRPASS(!d, PHYSFS_ENUM_ERROR);
  62. retval = __PHYSFS_platformEnumerate(d, cb, origdir, callbackdata);
  63. __PHYSFS_smallFree(d);
  64. return retval;
  65. } /* DIR_enumerate */
  66. static PHYSFS_Io *doOpen(void *opaque, const char *name, const int mode)
  67. {
  68. PHYSFS_Io *io = NULL;
  69. char *f = NULL;
  70. CVT_TO_DEPENDENT(f, opaque, name);
  71. BAIL_IF_ERRPASS(!f, NULL);
  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, &statbuf, 0); /* !!! FIXME: why are we stating here? */
  78. PHYSFS_setErrorCode(err);
  79. } /* if */
  80. __PHYSFS_smallFree(f);
  81. return io;
  82. } /* doOpen */
  83. static PHYSFS_Io *DIR_openRead(void *opaque, const char *filename)
  84. {
  85. return doOpen(opaque, filename, 'r');
  86. } /* DIR_openRead */
  87. static PHYSFS_Io *DIR_openWrite(void *opaque, const char *filename)
  88. {
  89. return doOpen(opaque, filename, 'w');
  90. } /* DIR_openWrite */
  91. static PHYSFS_Io *DIR_openAppend(void *opaque, const char *filename)
  92. {
  93. return doOpen(opaque, filename, 'a');
  94. } /* DIR_openAppend */
  95. static int DIR_remove(void *opaque, const char *name)
  96. {
  97. int retval;
  98. char *f;
  99. CVT_TO_DEPENDENT(f, opaque, name);
  100. BAIL_IF_ERRPASS(!f, 0);
  101. retval = __PHYSFS_platformDelete(f);
  102. __PHYSFS_smallFree(f);
  103. return retval;
  104. } /* DIR_remove */
  105. static int DIR_mkdir(void *opaque, const char *name)
  106. {
  107. int retval;
  108. char *f;
  109. CVT_TO_DEPENDENT(f, opaque, name);
  110. BAIL_IF_ERRPASS(!f, 0);
  111. retval = __PHYSFS_platformMkDir(f);
  112. __PHYSFS_smallFree(f);
  113. return retval;
  114. } /* DIR_mkdir */
  115. static void DIR_closeArchive(void *opaque)
  116. {
  117. allocator.Free(opaque);
  118. } /* DIR_closeArchive */
  119. static int DIR_stat(void *opaque, const char *name, PHYSFS_Stat *stat)
  120. {
  121. int retval = 0;
  122. char *d;
  123. CVT_TO_DEPENDENT(d, opaque, name);
  124. BAIL_IF_ERRPASS(!d, 0);
  125. retval = __PHYSFS_platformStat(d, stat, 0);
  126. __PHYSFS_smallFree(d);
  127. return retval;
  128. } /* DIR_stat */
  129. const PHYSFS_Archiver __PHYSFS_Archiver_DIR =
  130. {
  131. CURRENT_PHYSFS_ARCHIVER_API_VERSION,
  132. {
  133. "",
  134. "Non-archive, direct filesystem I/O",
  135. "Ryan C. Gordon <icculus@icculus.org>",
  136. "https://icculus.org/physfs/",
  137. 1, /* supportsSymlinks */
  138. },
  139. DIR_openArchive,
  140. DIR_enumerate,
  141. DIR_openRead,
  142. DIR_openWrite,
  143. DIR_openAppend,
  144. DIR_remove,
  145. DIR_mkdir,
  146. DIR_stat,
  147. DIR_closeArchive
  148. };
  149. /* end of physfs_archiver_dir.c ... */