Added a simple unpacker example.
This commit is contained in:
parent
0e3233a205
commit
a8de53670d
|
@ -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
|
||||
|
|
|
@ -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 ... */
|
||||
|
Loading…
Reference in New Issue