physfs_archiver_dir.c 4.6 KB

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