1 /*---------------------------------------------------------------------------*
2 Project: archiver extractor for Revolution dvd
3 File: extract.c
4
5 Copyright (C) 2001-2006 Nintendo. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain
8 proprietary information of Nintendo of America Inc. and/or Nintendo
9 Company Ltd., and are protected by Federal copyright law. They may
10 not be disclosed to third parties or copied or duplicated in any form,
11 in whole or in part, without the prior written consent of Nintendo.
12
13 $Log: extract.c,v $
14 Revision 1.1 2006/04/20 01:41:22 hiratsu
15 Initial check-in.
16
17
18 1 7/02/01 11:34p Hashida
19 Initial revision.
20
21 $NoKeywords: $
22 *---------------------------------------------------------------------------*/
23
24 #include "darch.h"
25
26 struct DirInfo_t
27 {
28 struct DirInfo_t* child;
29 struct DirInfo_t* parent;
30 char fullPath[FILENAME_MAX];
31 int nextEntry;
32
33 };
34
35 typedef struct DirInfo_t DirInfo;
36
37
38
39 static DirInfo RootDir;
40 static DirInfo* CurrDir = &RootDir;
41
42
OpenArc(char * fileName)43 DarchHandle* OpenArc(char* fileName)
44 {
45 ARCHeader header;
46 DarchHandle* handle;
47 int fstLength;
48
49 if ( NULL == (handle = malloc(sizeof(DarchHandle))) )
50 {
51 fprintf(stderr, "malloc failed\n");
52 exit(1);
53 }
54
55 strcpy(handle->name, fileName);
56
57 if( (handle->fid = open(fileName, O_BINARY | O_RDONLY)) == -1 )
58 {
59 fprintf(stderr, "error opening %s\n", fileName);
60 exit(1);
61 }
62
63 if (sizeof(ARCHeader) != read(handle->fid, &header, sizeof(ARCHeader)))
64 {
65 fprintf(stderr, "error reading %s\n", fileName);
66 exit(1);
67 }
68
69 if (header.magic != REV32(DARCH_MAGIC))
70 {
71 fprintf(stderr, "%s is not an archive\n", fileName);
72 exit(1);
73 }
74
75 fstLength = REV32(header.fstSize);
76 handle->fileStart = REV32(header.fileStart);
77
78 if ( NULL == (handle->fst = malloc(fstLength)) )
79 {
80 fprintf(stderr, "malloc failed\n");
81 exit(1);
82 }
83
84 if ( -1 == lseek(handle->fid, REV32(header.fstStart), SEEK_SET) )
85 {
86 fprintf(stderr, "lseek failed on %s\n", fileName);
87 exit(1);
88 }
89
90 if (fstLength != read(handle->fid, handle->fst, fstLength))
91 {
92 fprintf(stderr, "error reading %s\n", fileName);
93 exit(1);
94 }
95
96 handle->entryNum = nextDir(handle->fst);
97 handle->stringStartOffset = handle->entryNum * sizeof(FSTEntry);
98
99 if (debugMode)
100 {
101 fprintf(stderr, "entry num is %d\n", handle->entryNum);
102 fprintf(stderr, "fst length is %d\n", fstLength);
103 }
104
105 handle->currEntry = 0;
106
107 RootDir.child = NULL;
108 RootDir.parent = NULL;
109 RootDir.fullPath[0] = '\0';
110 RootDir.nextEntry = handle->entryNum;
111
112 return handle;
113 }
114
GetName(DarchHandle * handle,FSTEntry * entry)115 static char* GetName(DarchHandle* handle, FSTEntry* entry)
116 {
117 char* stringStart;
118
119 stringStart = (char*)handle->fst + handle->stringStartOffset;
120
121 return stringStart + stringOff(entry);
122
123 }
124
GetNextEntry(DarchHandle * handle,FSTEntryInfo * entryInfo)125 BOOL GetNextEntry(DarchHandle* handle, FSTEntryInfo* entryInfo)
126 {
127 FSTEntry* fstEntry;
128 DirInfo* dirInfo;
129
130 handle->currEntry++;
131
132 if (handle->currEntry >= handle->entryNum)
133 {
134 return FALSE;
135 }
136
137 fstEntry = &handle->fst[handle->currEntry];
138
139 // determine current directory
140 while(CurrDir->nextEntry == handle->currEntry)
141 {
142 CurrDir = CurrDir->parent;
143
144 free(CurrDir->child);
145 CurrDir->child = NULL;
146 }
147
148 entryInfo->next = NULL;
149 entryInfo->entryNum = handle->currEntry;
150 strcpy(entryInfo->pathName, CurrDir->fullPath);
151 entryInfo->nameOffset = strlen(entryInfo->pathName);
152 entryInfo->name = (char*)entryInfo->pathName + entryInfo->nameOffset;
153 strcat(entryInfo->pathName, GetName(handle, fstEntry));
154
155 if (debugMode)
156 {
157 fprintf(stderr, "full path name is %s\n", entryInfo->pathName);
158 fprintf(stderr, "name is %s\n", entryInfo->name);
159 }
160
161 if (entryIsDir(fstEntry))
162 {
163 if (debugMode)
164 {
165 fprintf(stderr, "entry is directory\n");
166 }
167
168 entryInfo->isDir = TRUE;
169 entryInfo->parentEntry = parentDir(fstEntry);
170 entryInfo->nextEntry = nextDir(fstEntry);
171 entryInfo->filePosition = 0;
172 entryInfo->fileLength = 0;
173
174 if ( NULL == (dirInfo = malloc(sizeof(DirInfo))) )
175 {
176 fprintf(stderr, "malloc failed\n");
177 exit(1);
178 }
179
180 CurrDir->child = dirInfo;
181 dirInfo->child = NULL;
182 dirInfo->parent = CurrDir;
183 strcpy(dirInfo->fullPath, entryInfo->pathName);
184 strcat(dirInfo->fullPath, "/");
185 dirInfo->nextEntry = entryInfo->nextEntry;
186
187 CurrDir = dirInfo;
188
189 }
190 else
191 {
192 entryInfo->isDir = FALSE;
193 entryInfo->parentEntry = 0;
194 entryInfo->nextEntry = 0;
195 entryInfo->filePosition = filePosition(fstEntry);
196 entryInfo->fileLength = fileLength(fstEntry);
197 }
198
199 return TRUE;
200 }
201
CloseArc(DarchHandle * handle)202 BOOL CloseArc(DarchHandle* handle)
203 {
204 free(handle->fst);
205
206 if (close(handle->fid) == -1)
207 {
208 fprintf(stderr, "error closing %s\n", handle->name);
209 exit(1);
210 }
211
212 free(handle);
213
214 return TRUE;
215 }
216
217
Diff(int fid,FSTEntryInfo * entryInfo)218 void Diff(int fid, FSTEntryInfo* entryInfo)
219 {
220 struct stat sb;
221 int fileLength;
222 int fidB;
223
224 if(stat(entryInfo->pathName, &sb))
225 {
226 if (entryInfo->isDir)
227 {
228 fprintf(stdout, "%s: Directory does not exist\n", entryInfo->pathName);
229 }
230 else
231 {
232 fprintf(stdout, "%s: File does not exist\n", entryInfo->pathName);
233 }
234 return;
235 }
236
237 if (entryInfo->isDir)
238 {
239 if ( !(sb.st_mode & _S_IFDIR) )
240 {
241 fprintf(stdout, "%s: No longer a directory\n", entryInfo->pathName);
242 return;
243 }
244 }
245 else
246 {
247 fileLength = entryInfo->fileLength;
248
249 if ( sb.st_mode & _S_IFDIR )
250 {
251 fprintf(stdout, "%s: Not a regular file\n", entryInfo->pathName);
252 return;
253 }
254
255 // Check size
256 if (sb.st_size != fileLength)
257 {
258 fprintf(stdout, "%s: Size differs\n", entryInfo->pathName);
259 return;
260 }
261
262 if( (fidB = open(entryInfo->pathName, O_BINARY | O_RDONLY)) == -1 )
263 {
264 fprintf(stderr, "%s: Error opening %s\n", progName, entryInfo->pathName);
265 exit(1);
266 }
267
268 if (DiffUtility(fid, entryInfo->filePosition, fidB, 0, fileLength))
269 {
270 if (verbose)
271 {
272 fprintf(stdout, "%s: Same\n", entryInfo->pathName);
273 }
274 }
275 else
276 {
277 fprintf(stdout, "%s: Data differs\n", entryInfo->pathName);
278 }
279
280 close(fidB);
281 return;
282 }
283
284 }
285
286
Extract(int fid,FSTEntryInfo * entryInfo)287 void Extract(int fid, FSTEntryInfo* entryInfo)
288 {
289 int outid;
290 int filePosition;
291 int fileLength;
292
293 if (entryInfo->isDir)
294 {
295 CreateDirectory(entryInfo->pathName, NULL);
296 }
297 else
298 {
299 filePosition = entryInfo->filePosition;
300 fileLength = entryInfo->fileLength;
301
302 if( (outid = open(entryInfo->pathName, O_BINARY | O_TRUNC | O_CREAT | O_WRONLY, 0666)) == -1 )
303 {
304 fprintf(stderr, "Cannot open %s\n", entryInfo->pathName);
305 exit(1);
306 }
307
308 CopyUtility(fid, filePosition, outid, 0, fileLength);
309
310 close(outid);
311 }
312 }
313
314
ListArc(char * name)315 void ListArc(char* name)
316 {
317 DarchHandle* handle;
318 FSTEntryInfo entryInfo;
319
320 handle = OpenArc(name);
321
322 if (verbose)
323 {
324 fprintf(stdout, " Position Length name\n");
325 fprintf(stdout, "-----------------------\n");
326 }
327
328 while(GetNextEntry(handle, &entryInfo))
329 {
330 if (verbose)
331 {
332 fprintf(stdout, "%s ", entryInfo.isDir? "d" : "-");
333 fprintf(stdout, "%7d %7d ", entryInfo.filePosition,
334 entryInfo.fileLength);
335 }
336
337 fprintf(stdout, "%s", entryInfo.pathName);
338 if (entryInfo.isDir)
339 {
340 fprintf(stdout, "/\n");
341 }
342 else
343 {
344 fprintf(stdout, "\n");
345 }
346 }
347
348 CloseArc(handle);
349 }
350
351
CreateExtractDir(char * extract)352 static void CreateExtractDir(char* extract)
353 {
354 if (CreateDirectory(extract, NULL) == 0)
355 {
356 if (GetLastError() == ERROR_ALREADY_EXISTS)
357 {
358 fprintf(stderr, "%s: Directory %s already exists. Can't extract.\n",
359 progName, extract);
360 exit(1);
361 }
362 else
363 {
364 fprintf(stderr, "%s: Failed to create directory %s\n", progName,
365 extract);
366 fprintf(stderr, "last error: %d\n", GetLastError());
367 exit(1);
368 }
369 }
370 }
371
ExtractArc(char * name,char * root)372 void ExtractArc(char* name, char* root)
373 {
374 DarchHandle* handle;
375 FSTEntryInfo entryInfo;
376
377 handle = OpenArc(name);
378
379 CreateExtractDir(root);
380
381 if (SetCurrentDirectory(root) == 0)
382 {
383 fprintf(stderr, "%s: Cannot change directory to %s\n", progName,
384 root);
385 fprintf(stderr, "%s: Error code is %d\n", progName, GetLastError()); exit(1);
386 }
387
388 fprintf(stdout, " Position Length name\n");
389 fprintf(stdout, "-----------------------\n");
390 while(GetNextEntry(handle, &entryInfo))
391 {
392 fprintf(stdout, "%s ", entryInfo.isDir? "d" : "-");
393 fprintf(stdout, "%7d %7d ", entryInfo.filePosition,
394 entryInfo.fileLength);
395 fprintf(stdout, "%s", entryInfo.pathName);
396 if (entryInfo.isDir)
397 {
398 fprintf(stdout, "/\n");
399 }
400 else
401 {
402 fprintf(stdout, "\n");
403 }
404
405 Extract(handle->fid, &entryInfo);
406 }
407
408 CloseArc(handle);
409 }
410
411
DiffArc(char * name,char * root)412 void DiffArc(char* name, char* root)
413 {
414 DarchHandle* handle;
415 FSTEntryInfo entryInfo;
416
417 handle = OpenArc(name);
418
419 if (SetCurrentDirectory(root) == 0)
420 {
421 fprintf(stderr, "%s: Cannot change directory to %s\n", progName,
422 root);
423 fprintf(stderr, "%s: Error code is %d\n", progName, GetLastError());
424 exit(1);
425 }
426
427 while(GetNextEntry(handle, &entryInfo))
428 {
429 fprintf(stdout, "%s", entryInfo.pathName);
430 if (entryInfo.isDir)
431 {
432 fprintf(stdout, "/\n");
433 }
434 else
435 {
436 fprintf(stdout, "\n");
437 }
438
439 Diff(handle->fid, &entryInfo);
440 }
441
442 CloseArc(handle);
443 }
444
445
446