Subversion Repositories Games.Descent

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 pmbaty 1
#include <stdio.h>
2
#include <stdlib.h>
3
#include <string.h>
4
#include <time.h>
5
 
6
#include "physfs.h"
7
 
8
 
9
static int failure = 0;
10
 
11
static void modTimeToStr(PHYSFS_sint64 modtime, char *modstr, size_t strsize)
12
{
13
    const char *str = "unknown modtime";
14
    if (modtime != -1)
15
    {
16
        time_t t = (time_t) modtime;
17
        str = ctime(&t);
18
    } /* if */
19
 
20
    strncpy(modstr, str, strsize);
21
    modstr[strsize-1] = '\0';
22
    strsize = strlen(modstr);
23
    while ((modstr[strsize-1] == '\n') || (modstr[strsize-1] == '\r'))
24
        modstr[--strsize] = '\0';
25
} /* modTimeToStr */
26
 
27
 
28
static void fail(const char *what, const char *why)
29
{
30
    if (why == NULL)
31
        why = PHYSFS_getLastError();
32
    fprintf(stderr, "%s failed: %s\n", what, why);
33
    failure = 1;
34
} /* fail */
35
 
36
 
37
static void dumpFile(const char *fname)
38
{
39
    const int origfailure = failure;
40
    PHYSFS_File *out = NULL;
41
    PHYSFS_File *in = NULL;
42
 
43
    failure = 0;
44
 
45
    if ((in = PHYSFS_openRead(fname)) == NULL)
46
        fail("\nPHYSFS_openRead", NULL);
47
    else if ((out = PHYSFS_openWrite(fname)) == NULL)
48
        fail("\nPHYSFS_openWrite", NULL);
49
    else
50
    {
51
        char modstr[64];
52
        PHYSFS_sint64 size = PHYSFS_fileLength(in);
53
 
54
        printf("(");
55
        if (size == -1)
56
            printf("?");
57
        else
58
            printf("%lld", (long long) size);
59
        printf(" bytes");
60
 
61
        modTimeToStr(PHYSFS_getLastModTime(fname), modstr, sizeof (modstr));
62
        printf(", %s)\n", modstr);
63
 
64
        while ( (!failure) && (!PHYSFS_eof(in)) )
65
        {
66
            static char buf[64 * 1024];
67
            PHYSFS_sint64 br = PHYSFS_read(in, buf, 1, sizeof (buf));
68
            if (br == -1)
69
                fail("PHYSFS_read", NULL);
70
            else
71
            {
72
                PHYSFS_sint64 bw = PHYSFS_write(out, buf, 1, br);
73
                if (bw != br)
74
                    fail("PHYSFS_write", NULL);
75
                else
76
                    size -= bw;
77
            } /* else */
78
        } /* while */
79
 
80
        if ((!failure) && (size != 0))
81
            fail("PHYSFS_eof", "BUG! eof != PHYSFS_fileLength bytes!");
82
    } /* else */
83
 
84
    if (in != NULL)
85
        PHYSFS_close(in);
86
 
87
    if (out != NULL)
88
    {
89
        if (!PHYSFS_close(out))
90
            fail("PHYSFS_close", NULL);
91
    } /* if */
92
 
93
    if (failure)
94
        PHYSFS_delete(fname);
95
    else
96
        failure = origfailure;
97
} /* dumpFile */
98
 
99
 
100
static void unpackCallback(void *_depth, const char *origdir, const char *str)
101
{
102
    int depth = *((int *) _depth);
103
    const int len = strlen(origdir) + strlen(str) + 2;
104
    char *fname = (char *) malloc(len);
105
    if (fname == NULL)
106
        fail("malloc", "Out of memory!");
107
    else
108
    {
109
        if (strcmp(origdir, "/") == 0)
110
            origdir = "";
111
 
112
        snprintf(fname, len, "%s/%s", origdir, str);
113
 
114
        printf("%s ", fname);
115
        if (PHYSFS_isDirectory(fname))
116
        {
117
            depth++;
118
            printf("(directory)\n");
119
            if (!PHYSFS_mkdir(fname))
120
                fail("PHYSFS_mkdir", NULL);
121
            else
122
                PHYSFS_enumerateFilesCallback(fname, unpackCallback, &depth);
123
        } /* if */
124
 
125
        else if (PHYSFS_isSymbolicLink(fname))
126
        {
127
            printf("(symlink)\n");
128
            /* !!! FIXME: ?  if (!symlink(fname, */
129
        } /* else if */
130
 
131
        else  /* ...file. */
132
        {
133
            dumpFile(fname);
134
        } /* else */
135
 
136
        free(fname);
137
    } /* else */
138
} /* unpackCallback */
139
 
140
 
141
int main(int argc, char **argv)
142
{
143
    int zero = 0;
144
 
145
    if (argc != 3)
146
    {
147
        fprintf(stderr, "USAGE: %s <archive> <unpackDirectory>\n", argv[0]);
148
        return 1;
149
    } /* if */
150
 
151
    if (!PHYSFS_init(argv[0]))
152
    {
153
        fprintf(stderr, "PHYSFS_init() failed: %s\n", PHYSFS_getLastError());
154
        return 2;
155
    } /* if */
156
 
157
    if (!PHYSFS_setWriteDir(argv[2]))
158
    {
159
        fprintf(stderr, "PHYSFS_setWriteDir('%s') failed: %s\n",
160
                argv[2], PHYSFS_getLastError());
161
        return 3;
162
    } /* if */
163
 
164
    if (!PHYSFS_mount(argv[1], NULL, 1))
165
    {
166
        fprintf(stderr, "PHYSFS_mount('%s') failed: %s\n",
167
                argv[1], PHYSFS_getLastError());
168
        return 4;
169
    } /* if */
170
 
171
    PHYSFS_permitSymbolicLinks(1);
172
    PHYSFS_enumerateFilesCallback("/", unpackCallback, &zero);
173
    PHYSFS_deinit();
174
    if (failure)
175
        return 5;
176
 
177
    return 0;
178
} /* main */
179
 
180
/* end of physfsunpack.c ... */
181