Subversion Repositories Games.Descent

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * GRP support routines for PhysicsFS.
  3.  *
  4.  * This driver handles BUILD engine archives ("groupfiles"). This format
  5.  *  (but not this driver) was put together by Ken Silverman.
  6.  *
  7.  * The format is simple enough. In Ken's words:
  8.  *
  9.  *    What's the .GRP file format?
  10.  *
  11.  *     The ".grp" file format is just a collection of a lot of files stored
  12.  *     into 1 big one. I tried to make the format as simple as possible: The
  13.  *     first 12 bytes contains my name, "KenSilverman". The next 4 bytes is
  14.  *     the number of files that were compacted into the group file. Then for
  15.  *     each file, there is a 16 byte structure, where the first 12 bytes are
  16.  *     the filename, and the last 4 bytes are the file's size. The rest of
  17.  *     the group file is just the raw data packed one after the other in the
  18.  *     same order as the list of files.
  19.  *
  20.  * (That info is from http://www.advsys.net/ken/build.htm ...)
  21.  *
  22.  * Please see the file LICENSE.txt in the source's root directory.
  23.  *
  24.  *  This file written by Ryan C. Gordon.
  25.  */
  26.  
  27. #define __PHYSICSFS_INTERNAL__
  28. #include "physfs_internal.h"
  29.  
  30. #if PHYSFS_SUPPORTS_GRP
  31.  
  32. static int grpLoadEntries(PHYSFS_Io *io, const PHYSFS_uint32 count, void *arc)
  33. {
  34.     PHYSFS_uint32 pos = 16 + (16 * count);  /* past sig+metadata. */
  35.     PHYSFS_uint32 i;
  36.  
  37.     for (i = 0; i < count; i++)
  38.     {
  39.         char *ptr;
  40.         char name[13];
  41.         PHYSFS_uint32 size;
  42.         BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, name, 12), 0);
  43.         BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, &size, 4), 0);
  44.  
  45.         name[12] = '\0';  /* name isn't null-terminated in file. */
  46.         if ((ptr = strchr(name, ' ')) != NULL)
  47.             *ptr = '\0';  /* trim extra spaces. */
  48.  
  49.         size = PHYSFS_swapULE32(size);
  50.         BAIL_IF_ERRPASS(!UNPK_addEntry(arc, name, 0, -1, -1, pos, size), 0);
  51.  
  52.         pos += size;
  53.     } /* for */
  54.  
  55.     return 1;
  56. } /* grpLoadEntries */
  57.  
  58.  
  59. static void *GRP_openArchive(PHYSFS_Io *io, const char *name,
  60.                              int forWriting, int *claimed)
  61. {
  62.     PHYSFS_uint8 buf[12];
  63.     PHYSFS_uint32 count = 0;
  64.     void *unpkarc = NULL;
  65.  
  66.     assert(io != NULL);  /* shouldn't ever happen. */
  67.  
  68.     BAIL_IF(forWriting, PHYSFS_ERR_READ_ONLY, NULL);
  69.  
  70.     BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, buf, sizeof (buf)), NULL);
  71.     if (memcmp(buf, "KenSilverman", sizeof (buf)) != 0)
  72.         BAIL(PHYSFS_ERR_UNSUPPORTED, NULL);
  73.  
  74.     *claimed = 1;
  75.  
  76.     BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, &count, sizeof(count)), NULL);
  77.     count = PHYSFS_swapULE32(count);
  78.  
  79.     unpkarc = UNPK_openArchive(io);
  80.     BAIL_IF_ERRPASS(!unpkarc, NULL);
  81.  
  82.     if (!grpLoadEntries(io, count, unpkarc))
  83.     {
  84.         UNPK_abandonArchive(unpkarc);
  85.         return NULL;
  86.     } /* if */
  87.  
  88.     return unpkarc;
  89. } /* GRP_openArchive */
  90.  
  91.  
  92. const PHYSFS_Archiver __PHYSFS_Archiver_GRP =
  93. {
  94.     CURRENT_PHYSFS_ARCHIVER_API_VERSION,
  95.     {
  96.         "GRP",
  97.         "Build engine Groupfile format",
  98.         "Ryan C. Gordon <icculus@icculus.org>",
  99.         "https://icculus.org/physfs/",
  100.         0,  /* supportsSymlinks */
  101.     },
  102.     GRP_openArchive,
  103.     UNPK_enumerate,
  104.     UNPK_openRead,
  105.     UNPK_openWrite,
  106.     UNPK_openAppend,
  107.     UNPK_remove,
  108.     UNPK_mkdir,
  109.     UNPK_stat,
  110.     UNPK_closeArchive
  111. };
  112.  
  113. #endif  /* defined PHYSFS_SUPPORTS_GRP */
  114.  
  115. /* end of physfs_archiver_grp.c ... */
  116.  
  117.