Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
182 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,181 @@ | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <string.h> | ||
#include <time.h> | ||
|
||
#include "physfs.h" | ||
|
||
|
||
static int failure = 0; | ||
|
||
static void modTimeToStr(PHYSFS_sint64 modtime, char *modstr, size_t strsize) | ||
{ | ||
const char *str = "unknown modtime"; | ||
if (modtime != -1) | ||
{ | ||
time_t t = (time_t) modtime; | ||
str = ctime(&t); | ||
} /* if */ | ||
|
||
strncpy(modstr, str, strsize); | ||
modstr[strsize-1] = '\0'; | ||
strsize = strlen(modstr); | ||
while ((modstr[strsize-1] == '\n') || (modstr[strsize-1] == '\r')) | ||
modstr[--strsize] = '\0'; | ||
} /* modTimeToStr */ | ||
|
||
|
||
static void fail(const char *what, const char *why) | ||
{ | ||
if (why == NULL) | ||
why = PHYSFS_getLastError(); | ||
fprintf(stderr, "%s failed: %s\n", what, why); | ||
failure = 1; | ||
} /* fail */ | ||
|
||
|
||
static void dumpFile(const char *fname) | ||
{ | ||
const int origfailure = failure; | ||
PHYSFS_File *out = NULL; | ||
PHYSFS_File *in = NULL; | ||
|
||
failure = 0; | ||
|
||
if ((in = PHYSFS_openRead(fname)) == NULL) | ||
fail("\nPHYSFS_openRead", NULL); | ||
else if ((out = PHYSFS_openWrite(fname)) == NULL) | ||
fail("\nPHYSFS_openWrite", NULL); | ||
else | ||
{ | ||
char modstr[64]; | ||
PHYSFS_sint64 size = PHYSFS_fileLength(in); | ||
|
||
printf("("); | ||
if (size == -1) | ||
printf("?"); | ||
else | ||
printf("%lld", (long long) size); | ||
printf(" bytes"); | ||
|
||
modTimeToStr(PHYSFS_getLastModTime(fname), modstr, sizeof (modstr)); | ||
printf(", %s)\n", modstr); | ||
|
||
while ( (!failure) && (!PHYSFS_eof(in)) ) | ||
{ | ||
static char buf[64 * 1024]; | ||
PHYSFS_sint64 br = PHYSFS_read(in, buf, 1, sizeof (buf)); | ||
if (br == -1) | ||
fail("PHYSFS_read", NULL); | ||
else | ||
{ | ||
PHYSFS_sint64 bw = PHYSFS_write(out, buf, 1, br); | ||
if (bw != br) | ||
fail("PHYSFS_write", NULL); | ||
else | ||
size -= bw; | ||
} /* else */ | ||
} /* while */ | ||
|
||
if ((!failure) && (size != 0)) | ||
fail("PHYSFS_eof", "BUG! eof != PHYSFS_fileLength bytes!"); | ||
} /* else */ | ||
|
||
if (in != NULL) | ||
PHYSFS_close(in); | ||
|
||
if (out != NULL) | ||
{ | ||
if (!PHYSFS_close(out)) | ||
fail("PHYSFS_close", NULL); | ||
} /* if */ | ||
|
||
if (failure) | ||
PHYSFS_delete(fname); | ||
else | ||
failure = origfailure; | ||
} /* dumpFile */ | ||
|
||
|
||
static void unpackCallback(void *_depth, const char *origdir, const char *str) | ||
{ | ||
int depth = *((int *) _depth); | ||
const int len = strlen(origdir) + strlen(str) + 2; | ||
char *fname = (char *) malloc(len); | ||
if (fname == NULL) | ||
fail("malloc", "Out of memory!"); | ||
else | ||
{ | ||
if (strcmp(origdir, "/") == 0) | ||
origdir = ""; | ||
|
||
snprintf(fname, len, "%s/%s", origdir, str); | ||
|
||
printf("%s ", fname); | ||
if (PHYSFS_isDirectory(fname)) | ||
{ | ||
depth++; | ||
printf("(directory)\n"); | ||
if (!PHYSFS_mkdir(fname)) | ||
fail("PHYSFS_mkdir", NULL); | ||
else | ||
PHYSFS_enumerateFilesCallback(fname, unpackCallback, &depth); | ||
} /* if */ | ||
|
||
else if (PHYSFS_isSymbolicLink(fname)) | ||
{ | ||
printf("(symlink)\n"); | ||
/* !!! FIXME: ? if (!symlink(fname, */ | ||
} /* else if */ | ||
|
||
else /* ...file. */ | ||
{ | ||
dumpFile(fname); | ||
} /* else */ | ||
|
||
free(fname); | ||
} /* else */ | ||
} /* unpackCallback */ | ||
|
||
|
||
int main(int argc, char **argv) | ||
{ | ||
int zero = 0; | ||
|
||
if (argc != 3) | ||
{ | ||
fprintf(stderr, "USAGE: %s <archive> <unpackDirectory>\n", argv[0]); | ||
return 1; | ||
} /* if */ | ||
|
||
if (!PHYSFS_init(argv[0])) | ||
{ | ||
fprintf(stderr, "PHYSFS_init() failed: %s\n", PHYSFS_getLastError()); | ||
return 2; | ||
} /* if */ | ||
|
||
if (!PHYSFS_setWriteDir(argv[2])) | ||
{ | ||
fprintf(stderr, "PHYSFS_setWriteDir('%s') failed: %s\n", | ||
argv[2], PHYSFS_getLastError()); | ||
return 3; | ||
} /* if */ | ||
|
||
if (!PHYSFS_mount(argv[1], NULL, 1)) | ||
{ | ||
fprintf(stderr, "PHYSFS_mount('%s') failed: %s\n", | ||
argv[1], PHYSFS_getLastError()); | ||
return 4; | ||
} /* if */ | ||
|
||
PHYSFS_permitSymbolicLinks(1); | ||
PHYSFS_enumerateFilesCallback("/", unpackCallback, &zero); | ||
PHYSFS_deinit(); | ||
if (failure) | ||
return 5; | ||
|
||
return 0; | ||
} /* main */ | ||
|
||
/* end of physfsunpack.c ... */ | ||
|