diff --git a/tools/pak/pak.c b/tools/pak/pak.c index 4048b69bc..37cdb200c 100644 --- a/tools/pak/pak.c +++ b/tools/pak/pak.c @@ -22,8 +22,9 @@ main (int argc, char **argv) int c; const char *pack_file = 0; int verbose = 0; + int pad = 0; - while ((c = getopt_long (argc, argv, "cf:tv", long_options, 0)) != -1) { + while ((c = getopt_long (argc, argv, "cf:ptvx", long_options, 0)) != -1) { switch (c) { case 'f': pack_file = optarg; @@ -34,9 +35,15 @@ main (int argc, char **argv) case 'c': mode = mo_create; break; + case 'x': + mode = mo_extract; + break; case 'v': verbose = 1; break; + case 'p': + pad = 1; + break; } } @@ -46,15 +53,32 @@ main (int argc, char **argv) } switch (mode) { + case mo_extract: + pack = pack_open (pack_file); + if (!pack) { + fprintf (stderr, "error opening %s\n", pack_file); + return 1; + } + for (i = 0; i < pack->numfiles; i++) { + if (verbose) + fprintf (stderr, "%s\n", pack->files[i].name); + pack_extract (pack, &pack->files[i]); + } + pack_close (pack); + break; case mo_test: pack = pack_open (pack_file); if (!pack) { fprintf (stderr, "error opening %s\n", pack_file); return 1; } - for (i = 0; i < pack->numfiles; i++) - printf ("%6d %s\n", pack->files[i].filelen, - pack->files[i].name); + for (i = 0; i < pack->numfiles; i++) { + if (verbose) + printf ("%6d %s\n", pack->files[i].filelen, + pack->files[i].name); + else + printf ("%s\n", pack->files[i].name); + } pack_close (pack); break; case mo_create: @@ -63,8 +87,12 @@ main (int argc, char **argv) fprintf (stderr, "error creating %s\n", pack_file); return 1; } - while (optind < argc) + pack->pad = pad; + while (optind < argc) { + if (verbose) + fprintf (stderr, "%s\n", argv[optind]); pack_add (pack, argv[optind++]); + } pack_close (pack); break; default: diff --git a/tools/pak/pakfile.c b/tools/pak/pakfile.c index 7d82ad478..0510004cf 100644 --- a/tools/pak/pakfile.c +++ b/tools/pak/pakfile.c @@ -1,7 +1,12 @@ +#include +#include #include #include #include #include +#include +#include +#include #include @@ -196,7 +201,7 @@ pack_add (pack_t *pack, const char *filename) pf->filelen += bytes; } fclose (file); - if (pf->filelen & 3) { + if (pack->pad && pf->filelen & 3) { static char buf[4]; fwrite (buf, 1, 4 - (pf->filelen & 3), pack->handle); } @@ -204,11 +209,48 @@ pack_add (pack_t *pack, const char *filename) return 0; } +static int +make_parents (const char *_path) +{ + char *path; + char *d, *p, t; + + path = (char *) alloca (strlen (_path) + 1); + strcpy (path, _path); + for (p = path; *p && (d = strchr (p, '/')); p = d + 1) { + t = *d; + *d = 0; + if (mkdir (path, 0777) < 0) + if (errno != EEXIST) + return -1; + *d = t; + } + return 0; +} + int pack_extract (pack_t *pack, dpackfile_t *pf) { - //const char *name = pf->name; + const char *name = pf->name; + int count; + int len; + FILE *file; + char buffer[16384]; - //fseek (pack->handle, pf->filepos, SEEK_SET); + if (make_parents (name) == -1) + return -1; + if (!(file = fopen (name, "wb"))) + return -1; + fseek (pack->handle, pf->filepos, SEEK_SET); + len = pf->filelen; + while (len) { + count = len; + if (count > sizeof (buffer)) + count = sizeof (buffer); + count = fread (buffer, 1, count, pack->handle); + fwrite (buffer, 1, count, file); + len -= count; + } + fclose (file); return 0; } diff --git a/tools/pak/pakfile.h b/tools/pak/pakfile.h index fe086b6e6..6d077581b 100644 --- a/tools/pak/pakfile.h +++ b/tools/pak/pakfile.h @@ -15,6 +15,7 @@ typedef struct pack_s { int modified; int old_numfiles; + int pad; } pack_t; pack_t *pack_new (const char *name); @@ -23,3 +24,4 @@ pack_t *pack_open (const char *name); void pack_close (pack_t *pack); pack_t *pack_create (const char *name); int pack_add (pack_t *pack, const char *filename); +int pack_extract (pack_t *pack, dpackfile_t *pf);