src/archiver_slb.c
author Ryan C. Gordon <icculus@icculus.org>
Wed, 28 Nov 2012 01:36:13 -0500
changeset 1322 5476917b8ddf
parent 1320 c1da17c10a41
child 1324 d12c1c033a7d
permissions -rw-r--r--
Allow application-supplied archivers. This lets an application supply its own archivers, where they will work like any built-in archiver. This allows abstract directory interfaces the same way that PHYSFS_Io allows stream implementations. This is a work in progress still. The API is still changing, and will remain at version 0 until it is finalized (a theoretical future version 1 will be for when the final public interface changes, not when we evolve the initial API design).
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
1315
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
     1
/*
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
     2
 * SLB support routines for PhysicsFS.
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
     3
 *
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
     4
 * This driver handles SLB archives ("slab files"). This uncompressed format
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
     5
 * is used in I-War / Independence War and Independence War: Defiance.
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
     6
 *
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
     7
 * The format begins with four zero bytes (version?), the file count and the
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
     8
 * location of the table of contents. Each ToC entry contains a 64-byte buffer
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
     9
 * containing a zero-terminated filename, the offset of the data, and its size.
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    10
 * All the filenames begin with the separator character '\'. 
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    11
 *
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    12
 * Please see the file LICENSE.txt in the source's root directory.
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    13
 *
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    14
 * This file written by Aleksi Nurmi, based on the GRP archiver by
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    15
 * Ryan C. Gordon.
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    16
 */
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    17
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    18
#define __PHYSICSFS_INTERNAL__
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    19
#include "physfs_internal.h"
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    20
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    21
#if PHYSFS_SUPPORTS_SLB
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    22
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    23
static UNPKentry *slbLoadEntries(PHYSFS_Io *io, PHYSFS_uint32 fileCount)
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    24
{
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    25
    UNPKentry *entries = NULL;
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    26
    UNPKentry *entry = NULL;
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    27
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    28
    entries = (UNPKentry *) allocator.Malloc(sizeof (UNPKentry) * fileCount);
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    29
    BAIL_IF_MACRO(entries == NULL, PHYSFS_ERR_OUT_OF_MEMORY, NULL);
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    30
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    31
    for (entry = entries; fileCount > 0; fileCount--, entry++)
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    32
    {
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    33
        char *ptr;
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    34
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    35
        /* don't include the '\' in the beginning */
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    36
        char backslash;
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    37
        GOTO_IF_MACRO(!__PHYSFS_readAll(io, &backslash, 1), ERRPASS, failed);
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    38
        GOTO_IF_MACRO(backslash != '\\', ERRPASS, failed);
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    39
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    40
        /* read the rest of the buffer, 63 bytes */
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    41
        GOTO_IF_MACRO(!__PHYSFS_readAll(io, &entry->name, 63), ERRPASS, failed);
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    42
        entry->name[63] = '\0'; /* in case the name lacks the null terminator */
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    43
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    44
        /* convert backslashes */
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    45
        for (ptr = entry->name; *ptr; ptr++)
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    46
        {
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    47
            if (*ptr == '\\')
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    48
                *ptr = '/';
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    49
        } /* for */
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    50
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    51
        GOTO_IF_MACRO(!__PHYSFS_readAll(io, &entry->startPos, 4),
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    52
                      ERRPASS, failed);
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    53
        entry->startPos = PHYSFS_swapULE32(entry->startPos);
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    54
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    55
        GOTO_IF_MACRO(!__PHYSFS_readAll(io, &entry->size, 4), ERRPASS, failed);
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    56
        entry->size = PHYSFS_swapULE32(entry->size);
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    57
    } /* for */
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    58
    
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    59
    return entries;
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    60
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    61
failed:
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    62
    allocator.Free(entries);
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    63
    return NULL;
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    64
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    65
} /* slbLoadEntries */
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    66
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    67
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    68
static void *SLB_openArchive(PHYSFS_Io *io, const char *name, int forWriting)
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    69
{
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    70
    PHYSFS_uint32 version;
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    71
    PHYSFS_uint32 count = 0;
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    72
    PHYSFS_uint32 tocPos = 0;
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    73
    UNPKentry *entries = NULL;
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    74
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    75
    assert(io != NULL);  /* shouldn't ever happen. */
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    76
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    77
    BAIL_IF_MACRO(forWriting, PHYSFS_ERR_READ_ONLY, NULL);
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    78
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    79
    BAIL_IF_MACRO(!__PHYSFS_readAll(io, &version, sizeof(version)),
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    80
                  ERRPASS, NULL);
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    81
    version = PHYSFS_swapULE32(version);
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    82
    BAIL_IF_MACRO(version != 0, ERRPASS, NULL);
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    83
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    84
    BAIL_IF_MACRO(!__PHYSFS_readAll(io, &count, sizeof(count)), ERRPASS, NULL);
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    85
    count = PHYSFS_swapULE32(count);
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    86
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    87
    /* offset of the table of contents */
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    88
    BAIL_IF_MACRO(!__PHYSFS_readAll(io, &tocPos, sizeof(tocPos)),
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    89
                  ERRPASS, NULL);
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    90
    tocPos = PHYSFS_swapULE32(tocPos);
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    91
    
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    92
    /* seek to the table of contents */
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    93
    BAIL_IF_MACRO(!io->seek(io, tocPos), ERRPASS, NULL);
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    94
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    95
    entries = slbLoadEntries(io, count);
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    96
    BAIL_IF_MACRO(!entries, ERRPASS, NULL);
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    97
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    98
    return UNPK_openArchive(io, entries, count);
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
    99
} /* SLB_openArchive */
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
   100
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
   101
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
   102
const PHYSFS_Archiver __PHYSFS_Archiver_SLB =
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
   103
{
1322
5476917b8ddf Allow application-supplied archivers.
Ryan C. Gordon <icculus@icculus.org>
parents: 1320
diff changeset
   104
    CURRENT_PHYSFS_ARCHIVER_API_VERSION,
1315
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
   105
    {
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
   106
        "SLB",
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
   107
        "I-War / Independence War Slab file",
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
   108
        "Aleksi Nurmi <aleksi.nurmi@gmail.com>",
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
   109
        "http://bitbucket.org/ahnurmi/",
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
   110
    },
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
   111
    SLB_openArchive,        /* openArchive() method    */
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
   112
    UNPK_enumerateFiles,    /* enumerateFiles() method */
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
   113
    UNPK_openRead,          /* openRead() method       */
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
   114
    UNPK_openWrite,         /* openWrite() method      */
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
   115
    UNPK_openAppend,        /* openAppend() method     */
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
   116
    UNPK_remove,            /* remove() method         */
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
   117
    UNPK_mkdir,             /* mkdir() method          */
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
   118
    UNPK_closeArchive,      /* closeArchive() method   */
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
   119
    UNPK_stat               /* stat() method           */
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
   120
};
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
   121
c686e4f84ab5 SLB archiver
Aleksi Nurmi <aleksi.nurmi@gmail.com>
parents:
diff changeset
   122
#endif  /* defined PHYSFS_SUPPORTS_SLB */
1320
c1da17c10a41 Cleaned up some simple comments.
Ryan C. Gordon <icculus@icculus.org>
parents: 1315
diff changeset
   123
c1da17c10a41 Cleaned up some simple comments.
Ryan C. Gordon <icculus@icculus.org>
parents: 1315
diff changeset
   124
/* end of archiver_slb.c ... */
c1da17c10a41 Cleaned up some simple comments.
Ryan C. Gordon <icculus@icculus.org>
parents: 1315
diff changeset
   125