Subversion Repositories Games.Descent

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 pmbaty 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
 
18
#define __PHYSICSFS_INTERNAL__
19
#include "physfs_internal.h"
20
 
21
#if PHYSFS_SUPPORTS_SLB
22
 
23
static int slbLoadEntries(PHYSFS_Io *io, const PHYSFS_uint32 count, void *arc)
24
{
25
    PHYSFS_uint32 i;
26
    for (i = 0; i < count; i++)
27
    {
28
        PHYSFS_uint32 pos;
29
        PHYSFS_uint32 size;
30
        char name[64];
31
        char backslash;
32
        char *ptr;
33
 
34
        /* don't include the '\' in the beginning */
35
        BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, &backslash, 1), 0);
36
        BAIL_IF(backslash != '\\', PHYSFS_ERR_CORRUPT, 0);
37
 
38
        /* read the rest of the buffer, 63 bytes */
39
        BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, &name, 63), 0);
40
        name[63] = '\0'; /* in case the name lacks the null terminator */
41
 
42
        /* convert backslashes */
43
        for (ptr = name; *ptr; ptr++)
44
        {
45
            if (*ptr == '\\')
46
                *ptr = '/';
47
        } /* for */
48
 
49
        BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, &pos, 4), 0);
50
        pos = PHYSFS_swapULE32(pos);
51
 
52
        BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, &size, 4), 0);
53
        size = PHYSFS_swapULE32(size);
54
 
55
        BAIL_IF_ERRPASS(!UNPK_addEntry(arc, name, 0, -1, -1, pos, size), 0);
56
    } /* for */
57
 
58
    return 1;
59
} /* slbLoadEntries */
60
 
61
 
62
static void *SLB_openArchive(PHYSFS_Io *io, const char *name,
63
                             int forWriting, int *claimed)
64
{
65
    PHYSFS_uint32 version;
66
    PHYSFS_uint32 count;
67
    PHYSFS_uint32 tocPos;
68
    void *unpkarc;
69
 
70
    /* There's no identifier on an SLB file, so we assume it's _not_ if the
71
       file count or tocPos is zero. Beyond that, we'll assume it's
72
       bogus/corrupt if the entries' filenames don't start with '\' or the
73
       tocPos is past the end of the file (seek will fail). This probably
74
       covers all meaningful cases where we would accidentally accept a non-SLB
75
       file with this archiver. */
76
 
77
    assert(io != NULL);  /* shouldn't ever happen. */
78
 
79
    BAIL_IF(forWriting, PHYSFS_ERR_READ_ONLY, NULL);
80
 
81
    BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, &version, sizeof (version)), NULL);
82
    version = PHYSFS_swapULE32(version);
83
    BAIL_IF(version != 0, PHYSFS_ERR_UNSUPPORTED, NULL);
84
 
85
    BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, &count, sizeof (count)), NULL);
86
    count = PHYSFS_swapULE32(count);
87
    BAIL_IF(!count, PHYSFS_ERR_UNSUPPORTED, NULL);
88
 
89
    /* offset of the table of contents */
90
    BAIL_IF_ERRPASS(!__PHYSFS_readAll(io, &tocPos, sizeof (tocPos)), NULL);
91
    tocPos = PHYSFS_swapULE32(tocPos);
92
    BAIL_IF(!tocPos, PHYSFS_ERR_UNSUPPORTED, NULL);
93
 
94
    /* seek to the table of contents */
95
    BAIL_IF_ERRPASS(!io->seek(io, tocPos), NULL);
96
 
97
    unpkarc = UNPK_openArchive(io);
98
    BAIL_IF_ERRPASS(!unpkarc, NULL);
99
 
100
    if (!slbLoadEntries(io, count, unpkarc))
101
    {
102
        UNPK_abandonArchive(unpkarc);
103
        return NULL;
104
    } /* if */
105
 
106
    *claimed = 1;  /* oh well. */
107
 
108
    return unpkarc;
109
} /* SLB_openArchive */
110
 
111
 
112
const PHYSFS_Archiver __PHYSFS_Archiver_SLB =
113
{
114
    CURRENT_PHYSFS_ARCHIVER_API_VERSION,
115
    {
116
        "SLB",
117
        "I-War / Independence War Slab file",
118
        "Aleksi Nurmi <aleksi.nurmi@gmail.com>",
119
        "https://bitbucket.org/ahnurmi/",
120
        0,  /* supportsSymlinks */
121
    },
122
    SLB_openArchive,
123
    UNPK_enumerate,
124
    UNPK_openRead,
125
    UNPK_openWrite,
126
    UNPK_openAppend,
127
    UNPK_remove,
128
    UNPK_mkdir,
129
    UNPK_stat,
130
    UNPK_closeArchive
131
};
132
 
133
#endif  /* defined PHYSFS_SUPPORTS_SLB */
134
 
135
/* end of physfs_archiver_slb.c ... */