#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;
} /* if */
modstr[strsize-1] = '\0';
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);
if (size == -1)
else
printf("%lld", (long long) size
);
modTimeToStr(PHYSFS_getLastModTime(fname), modstr, sizeof (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);
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
);
if (PHYSFS_isDirectory(fname))
{
depth++;
if (!PHYSFS_mkdir(fname))
fail("PHYSFS_mkdir", NULL);
else
PHYSFS_enumerateFilesCallback(fname, unpackCallback, &depth);
} /* if */
else if (PHYSFS_isSymbolicLink(fname))
{
/* !!! FIXME: ? if (!symlink(fname, */
} /* else if */
else /* ...file. */
{
dumpFile(fname);
} /* else */
} /* 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 ... */