#include #include #include #include #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 \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 ... */