misc/physfs/src/archiver_hog.c
branchphysfslayer
changeset 7768 13e2037ebc79
equal deleted inserted replaced
7767:d1ea9b3f543e 7768:13e2037ebc79
       
     1 /*
       
     2  * HOG support routines for PhysicsFS.
       
     3  *
       
     4  * This driver handles Descent I/II HOG archives.
       
     5  *
       
     6  * The format is very simple:
       
     7  *
       
     8  *   The file always starts with the 3-byte signature "DHF" (Descent
       
     9  *   HOG file). After that the files of a HOG are just attached after
       
    10  *   another, divided by a 17 bytes header, which specifies the name
       
    11  *   and length (in bytes) of the forthcoming file! So you just read
       
    12  *   the header with its information of how big the following file is,
       
    13  *   and then skip exact that number of bytes to get to the next file
       
    14  *   in that HOG.
       
    15  *
       
    16  *    char sig[3] = {'D', 'H', 'F'}; // "DHF"=Descent HOG File
       
    17  *
       
    18  *    struct {
       
    19  *     char file_name[13]; // Filename, padded to 13 bytes with 0s
       
    20  *     int file_size; // filesize in bytes
       
    21  *     char data[file_size]; // The file data
       
    22  *    } FILE_STRUCT; // Repeated until the end of the file.
       
    23  *
       
    24  * (That info is from http://www.descent2.com/ddn/specs/hog/)
       
    25  *
       
    26  * Please see the file LICENSE.txt in the source's root directory.
       
    27  *
       
    28  *  This file written by Bradley Bell.
       
    29  *  Based on grp.c by Ryan C. Gordon.
       
    30  */
       
    31 
       
    32 #define __PHYSICSFS_INTERNAL__
       
    33 #include "physfs_internal.h"
       
    34 
       
    35 #if PHYSFS_SUPPORTS_HOG
       
    36 
       
    37 static UNPKentry *hogLoadEntries(PHYSFS_Io *io, PHYSFS_uint32 *_entCount)
       
    38 {
       
    39     const PHYSFS_uint64 iolen = io->length(io);
       
    40     PHYSFS_uint32 entCount = 0;
       
    41     void *ptr = NULL;
       
    42     UNPKentry *entries = NULL;
       
    43     UNPKentry *entry = NULL;
       
    44     PHYSFS_uint32 size = 0;
       
    45     PHYSFS_uint32 pos = 3;
       
    46 
       
    47     while (pos < iolen)
       
    48     {
       
    49         entCount++;
       
    50         ptr = allocator.Realloc(ptr, sizeof (UNPKentry) * entCount);
       
    51         GOTO_IF_MACRO(ptr == NULL, PHYSFS_ERR_OUT_OF_MEMORY, failed);
       
    52         entries = (UNPKentry *) ptr;
       
    53         entry = &entries[entCount-1];
       
    54 
       
    55         GOTO_IF_MACRO(!__PHYSFS_readAll(io, &entry->name, 13), ERRPASS, failed);
       
    56         pos += 13;
       
    57         GOTO_IF_MACRO(!__PHYSFS_readAll(io, &size, 4), ERRPASS, failed);
       
    58         pos += 4;
       
    59 
       
    60         entry->size = PHYSFS_swapULE32(size);
       
    61         entry->startPos = pos;
       
    62         pos += size;
       
    63 
       
    64         /* skip over entry */
       
    65         GOTO_IF_MACRO(!io->seek(io, pos), ERRPASS, failed);
       
    66     } /* while */
       
    67 
       
    68     *_entCount = entCount;
       
    69     return entries;
       
    70 
       
    71 failed:
       
    72     allocator.Free(entries);
       
    73     return NULL;
       
    74 } /* hogLoadEntries */
       
    75 
       
    76 
       
    77 static void *HOG_openArchive(PHYSFS_Io *io, const char *name, int forWriting)
       
    78 {
       
    79     PHYSFS_uint8 buf[3];
       
    80     PHYSFS_uint32 count = 0;
       
    81     UNPKentry *entries = NULL;
       
    82 
       
    83     assert(io != NULL);  /* shouldn't ever happen. */
       
    84     BAIL_IF_MACRO(forWriting, PHYSFS_ERR_READ_ONLY, NULL);
       
    85     BAIL_IF_MACRO(!__PHYSFS_readAll(io, buf, 3), ERRPASS, NULL);
       
    86     BAIL_IF_MACRO(memcmp(buf, "DHF", 3) != 0, PHYSFS_ERR_UNSUPPORTED, NULL);
       
    87 
       
    88     entries = hogLoadEntries(io, &count);
       
    89     BAIL_IF_MACRO(!entries, ERRPASS, NULL);
       
    90     return UNPK_openArchive(io, entries, count);
       
    91 } /* HOG_openArchive */
       
    92 
       
    93 
       
    94 const PHYSFS_Archiver __PHYSFS_Archiver_HOG =
       
    95 {
       
    96     {
       
    97         "HOG",
       
    98         "Descent I/II HOG file format",
       
    99         "Bradley Bell <btb@icculus.org>",
       
   100         "http://icculus.org/physfs/",
       
   101     },
       
   102     HOG_openArchive,         /* openArchive() method    */
       
   103     UNPK_enumerateFiles,     /* enumerateFiles() method */
       
   104     UNPK_openRead,           /* openRead() method       */
       
   105     UNPK_openWrite,          /* openWrite() method      */
       
   106     UNPK_openAppend,         /* openAppend() method     */
       
   107     UNPK_remove,             /* remove() method         */
       
   108     UNPK_mkdir,              /* mkdir() method          */
       
   109     UNPK_closeArchive,       /* closeArchive() method   */
       
   110     UNPK_stat                /* stat() method           */
       
   111 };
       
   112 
       
   113 #endif  /* defined PHYSFS_SUPPORTS_HOG */
       
   114 
       
   115 /* end of hog.c ... */
       
   116