archiver_slb.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. /*
  2. * SLB support routines for PhysicsFS.
  3. *
  4. * This driver handles SLB archives ("slab files"). This uncompressed format
  5. * is used in I-War / Independence War and Independence War: Defiance.
  6. *
  7. * The format begins with four zero bytes (version?), the file count and the
  8. * location of the table of contents. Each ToC entry contains a 64-byte buffer
  9. * containing a zero-terminated filename, the offset of the data, and its size.
  10. * All the filenames begin with the separator character '\'.
  11. *
  12. * Please see the file LICENSE.txt in the source's root directory.
  13. *
  14. * This file written by Aleksi Nurmi, based on the GRP archiver by
  15. * Ryan C. Gordon.
  16. */
  17. #define __PHYSICSFS_INTERNAL__
  18. #include "physfs_internal.h"
  19. #if PHYSFS_SUPPORTS_SLB
  20. static UNPKentry *slbLoadEntries(PHYSFS_Io *io, PHYSFS_uint32 fileCount)
  21. {
  22. UNPKentry *entries = NULL;
  23. UNPKentry *entry = NULL;
  24. entries = (UNPKentry *) allocator.Malloc(sizeof (UNPKentry) * fileCount);
  25. BAIL_IF(entries == NULL, PHYSFS_ERR_OUT_OF_MEMORY, NULL);
  26. for (entry = entries; fileCount > 0; fileCount--, entry++)
  27. {
  28. char *ptr;
  29. /* don't include the '\' in the beginning */
  30. char backslash;
  31. GOTO_IF_ERRPASS(!__PHYSFS_readAll(io, &backslash, 1), failed);
  32. GOTO_IF_ERRPASS(backslash != '\\', failed);
  33. /* read the rest of the buffer, 63 bytes */
  34. GOTO_IF_ERRPASS(!__PHYSFS_readAll(io, &entry->name, 63), failed);
  35. entry->name[63] = '\0'; /* in case the name lacks the null terminator */
  36. /* convert backslashes */
  37. for (ptr = entry->name; *ptr; ptr++)
  38. {
  39. if (*ptr == '\\')
  40. *ptr = '/';
  41. } /* for */
  42. GOTO_IF_ERRPASS(!__PHYSFS_readAll(io, &entry->startPos, 4), failed);
  43. entry->startPos = PHYSFS_swapULE32(entry->startPos);
  44. GOTO_IF_ERRPASS(!__PHYSFS_readAll(io, &entry->size, 4), failed);
  45. entry->size = PHYSFS_swapULE32(entry->size);
  46. } /* for */
  47. return entries;
  48. failed:
  49. allocator.Free(entries);
  50. return NULL;
  51. } /* slbLoadEntries */
  52. static void *SLB_openArchive(PHYSFS_Io *io, const char *name, int forWriting)
  53. {
  54. PHYSFS_uint32 version;
  55. PHYSFS_uint32 count = 0;
  56. PHYSFS_uint32 tocPos = 0;
  57. UNPKentry *entries = NULL;
  58. assert(io != NULL); /* shouldn't ever happen. */
  59. BAIL_IF(forWriting, PHYSFS_ERR_READ_ONLY, NULL);
  60. BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, &version, sizeof(version)), NULL);
  61. version = PHYSFS_swapULE32(version);
  62. BAIL_IF(version != 0, PHYSFS_ERR_UNSUPPORTED, NULL);
  63. BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, &count, sizeof(count)), NULL);
  64. count = PHYSFS_swapULE32(count);
  65. /* offset of the table of contents */
  66. BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, &tocPos, sizeof(tocPos)), NULL);
  67. tocPos = PHYSFS_swapULE32(tocPos);
  68. /* seek to the table of contents */
  69. BAIL_IF_ERRPASS(!io->seek(io, tocPos), NULL);
  70. entries = slbLoadEntries(io, count);
  71. BAIL_IF_ERRPASS(!entries, NULL);
  72. return UNPK_openArchive(io, entries, count);
  73. } /* SLB_openArchive */
  74. const PHYSFS_Archiver __PHYSFS_Archiver_SLB =
  75. {
  76. CURRENT_PHYSFS_ARCHIVER_API_VERSION,
  77. {
  78. "SLB",
  79. "I-War / Independence War Slab file",
  80. "Aleksi Nurmi <aleksi.nurmi@gmail.com>",
  81. "https://bitbucket.org/ahnurmi/",
  82. 0, /* supportsSymlinks */
  83. },
  84. SLB_openArchive,
  85. UNPK_enumerateFiles,
  86. UNPK_openRead,
  87. UNPK_openWrite,
  88. UNPK_openAppend,
  89. UNPK_remove,
  90. UNPK_mkdir,
  91. UNPK_stat,
  92. UNPK_closeArchive
  93. };
  94. #endif /* defined PHYSFS_SUPPORTS_SLB */
  95. /* end of archiver_slb.c ... */