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
modTimeToStr(PHYSFS_sint64 modtime,char * modstr,size_t strsize)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
fail(const char * what,const char * why)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
dumpFile(const char * fname)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
unpackCallback(void * _depth,const char * origdir,const char * str)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
main(int argc,char ** argv)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
182