r880 - in trunk: . extras
DONOTREPLY at icculus.org
DONOTREPLY at icculus.org
Sat Mar 31 02:34:51 EDT 2007
Author: icculus
Date: 2007-03-31 02:34:51 -0400 (Sat, 31 Mar 2007)
New Revision: 880
Added:
trunk/extras/physfsunpack.c
Modified:
trunk/CHANGELOG.txt
Log:
Added a simple unpacker example.
Modified: trunk/CHANGELOG.txt
===================================================================
--- trunk/CHANGELOG.txt 2007-03-29 05:39:16 UTC (rev 879)
+++ trunk/CHANGELOG.txt 2007-03-31 06:34:51 UTC (rev 880)
@@ -2,6 +2,7 @@
* CHANGELOG.
*/
+03312007 - Added a quick'n'dirty unpack utility to the extras directory.
03282007 - Logic bug in MVL/HOG/GRP archivers: only enumerated files when
looking in a directory other than the root, instead of enumerating
only for the root (thanks, Chris!). Minor fix for compilers that
Added: trunk/extras/physfsunpack.c
===================================================================
--- trunk/extras/physfsunpack.c (rev 0)
+++ trunk/extras/physfsunpack.c 2007-03-31 06:34:51 UTC (rev 880)
@@ -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 ... */
+
More information about the physfs-commits
mailing list