physfs_archiver_pod.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. /*
  2. * POD support routines for PhysicsFS.
  3. *
  4. * This driver handles Terminal Velocity POD archives.
  5. *
  6. * The POD format is as follows:
  7. *
  8. * While there is no known signature, the file starts with an
  9. * unsigned 32-bit integer with the file count, followed by
  10. * an 80-character, null-padded string with a description of
  11. * the pod file. The file entries follow, and are as such:
  12. *
  13. * struct {
  14. * char file_path[32]; // Full file path, IE: "ART\VGA.ACT"
  15. * uint32_t file_size; // filesize in bytes
  16. * uint32_t offset; // The offset of the data.
  17. * } fileEntry_t; // Once per file. The file data itself is at offset after all entries.
  18. *
  19. * (This info is from: https://moddingwiki.shikadi.net/wiki/POD_Format)
  20. *
  21. * There are other POD file formats, but they haven't been implemented yet.
  22. *
  23. * Please see the file LICENSE.txt in the source's root directory.
  24. *
  25. * This file written by Jordon Moss.
  26. */
  27. #define __PHYSICSFS_INTERNAL__
  28. #include "physfs_internal.h"
  29. #if PHYSFS_SUPPORTS_POD
  30. static int readui32(PHYSFS_Io *io, PHYSFS_uint32 *val)
  31. {
  32. PHYSFS_uint32 v;
  33. BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, &v, sizeof (v)), 0);
  34. *val = PHYSFS_swapULE32(v);
  35. return 1;
  36. } /* readui32 */
  37. static void replaceChar(char* str, char oldChar, char newChar)
  38. {
  39. int i = 0;
  40. while (str[i] != '\0')
  41. { // Iterate until the null terminator is found
  42. if (str[i] == oldChar)
  43. {
  44. str[i] = newChar; // Replace the character
  45. }
  46. i++;
  47. }
  48. }
  49. static int pod1LoadEntries(PHYSFS_Io *io, void *arc)
  50. {
  51. PHYSFS_uint32 numfiles;
  52. PHYSFS_uint32 i;
  53. BAIL_IF_ERRPASS(!readui32(io, &numfiles), 0);
  54. BAIL_IF_ERRPASS(!io->seek(io, 84), 0); /* skip past description */
  55. for (i = 0; i < numfiles; i++) {
  56. char name[33];
  57. PHYSFS_uint32 size;
  58. PHYSFS_uint32 offset;
  59. BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, name, 32), 0);
  60. BAIL_IF_ERRPASS(!readui32(io, &size), 0);
  61. BAIL_IF_ERRPASS(!readui32(io, &offset), 0);
  62. name[32] = '\0'; /* just in case */
  63. replaceChar(name, '\\', '/');
  64. BAIL_IF_ERRPASS(!UNPK_addEntry(arc, name, 0, -1, -1, offset, size), 0);
  65. }
  66. return 1;
  67. } /* pod1LoadEntries */
  68. static void *POD_openArchive(PHYSFS_Io *io, const char *name,
  69. int forWriting, int *claimed)
  70. {
  71. void *unpkarc = NULL;
  72. PHYSFS_uint32 dummy;
  73. char description[80];
  74. assert(io != NULL); /* shouldn't ever happen. */
  75. BAIL_IF(forWriting, PHYSFS_ERR_READ_ONLY, NULL);
  76. BAIL_IF_ERRPASS(!readui32(io, &dummy), 0);
  77. BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, description, 80), NULL);
  78. if ((description[0] == 0) || (description[79] != 0)) // Check if we're lacking a description or last char isn't a null terminator.
  79. return NULL;
  80. io->seek(io, 0);
  81. *claimed = 1;
  82. unpkarc = UNPK_openArchive(io, 0, 1);
  83. BAIL_IF_ERRPASS(!unpkarc, NULL);
  84. if (!(pod1LoadEntries(io, unpkarc)))
  85. {
  86. UNPK_abandonArchive(unpkarc);
  87. return NULL;
  88. } /* if */
  89. return unpkarc;
  90. } /* POD_openArchive */
  91. const PHYSFS_Archiver __PHYSFS_Archiver_POD =
  92. {
  93. CURRENT_PHYSFS_ARCHIVER_API_VERSION,
  94. {
  95. "POD",
  96. "Terminal Reality POD file format",
  97. "Jordon Moss <mossj32@gmail.com>",
  98. "https://icculus.org/physfs/",
  99. 0, /* supportsSymlinks */
  100. },
  101. POD_openArchive,
  102. UNPK_enumerate,
  103. UNPK_openRead,
  104. UNPK_openWrite,
  105. UNPK_openAppend,
  106. UNPK_remove,
  107. UNPK_mkdir,
  108. UNPK_stat,
  109. UNPK_closeArchive
  110. };
  111. #endif /* defined PHYSFS_SUPPORTS_POD */
  112. /* end of physfs_archiver_pod.c ... */