1 /*
2 * pakx.c -- pack file extraction tool.
3 * $Id: pakx.c 5787 2017-01-03 22:22:34Z sezero $
4 *
5 * Copyright (C) 1996-2001 Id Software, Inc.
6 * Copyright (C) 2010 Ozkan Sezer <sezero@users.sourceforge.net>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or (at
11 * your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16 *
17 * See the GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24 #include "q_stdinc.h"
25 #include "compiler.h"
26 #include "arch_def.h"
27 #include "cmdlib.h"
28 #include "util_io.h"
29 #include "byteordr.h"
30 #include "pathutil.h"
31 #include "pakfile.h"
32 #include "pak.h"
33 #include "filenames.h"
34
35 //======================================================================
36
ExtractFile(pack_t * pak,const char * filename,const char * destdir)37 static void ExtractFile (pack_t *pak, const char *filename, const char *destdir)
38 {
39 char dest[1024], *dptr;
40 int i;
41
42 if (!destdir || !*destdir)
43 {
44 dptr = dest;
45 }
46 else
47 {
48 strcpy (dest, destdir);
49 i = strlen (destdir);
50 if (!IS_DIR_SEPARATOR(dest[i - 1]))
51 {
52 dest[i] = DIR_SEPARATOR_CHAR;
53 dest[i + 1] = '\0';
54 }
55 dptr = strchr(dest, '\0');
56 }
57
58 for (i = 0; i < pak->numfiles; i++)
59 {
60 if (!filename)
61 {
62 fseek (pak->handle, pak->files[i].filepos, SEEK_SET);
63 strcpy (dptr, pak->files[i].name);
64 dest[sizeof(dest) - 1] = '\0';
65 printf ("%s --> %s\n", pak->files[i].name, dest);
66 if (Q_WriteFileFromHandle(pak->handle, dest, pak->files[i].filelen) != 0)
67 COM_Error ("I/O errors during copy.");
68 continue;
69 }
70 if (!strcmp (pak->files[i].name, filename))
71 {
72 fseek (pak->handle, pak->files[i].filepos, SEEK_SET);
73 strcpy (dptr, pak->files[i].name);
74 dest[sizeof(dest) - 1] = '\0';
75 printf ("%s --> %s\n", pak->files[i].name, dest);
76 if (Q_WriteFileFromHandle(pak->handle, dest, pak->files[i].filelen) != 0)
77 COM_Error ("I/O errors during copy.");
78 break;
79 }
80 }
81 if (filename != NULL && i == pak->numfiles)
82 fprintf (stderr, "** %s not in %s\n", filename, pak->filename);
83 }
84
usage(int ret)85 FUNC_NORETURN static void usage (int ret) {
86 printf ("Usage: pakx [-outdir <destdir>] <pakfile> [file [file ....]]\n");
87 printf (" pakx -h to display this help message.\n");
88 printf ("<destdir> : Optional. Output directory to extract the files into.\n");
89 printf ("Without the [file] arguments, all pak file contents get extracted.\n");
90 printf ("\n");
91 exit (ret);
92 }
93
main(int argc,char ** argv)94 int main (int argc, char **argv)
95 {
96 pack_t *pak;
97 const char *destdir;
98 int i;
99
100 if (argc < 2)
101 usage (1);
102
103 for (i = 1; i < argc; i++)
104 {
105 if (!strcmp(argv[i], "-h"))
106 usage (0);
107 }
108
109 if (!strcmp(argv[1], "-outdir"))
110 {
111 if (argc < 4)
112 usage (1);
113 i = 3;
114 destdir = argv[2];
115 }
116 else
117 {
118 i = 1;
119 destdir = NULL;
120 }
121
122 ValidateByteorder ();
123
124 pak = LoadPackFile (argv[i]);
125 if (!pak)
126 COM_Error ("Unable to open file %s", argv[i]);
127 printf ("Opened %s (%i files)\n", pak->filename, pak->numfiles);
128 if (!pak->numfiles)
129 COM_Error ("%s has no files.", pak->filename);
130 if (++i >= argc)
131 ExtractFile (pak, NULL, destdir);
132 else
133 {
134 for ( ; i < argc; i++)
135 ExtractFile (pak, argv[i], destdir);
136 }
137
138 return 0;
139 }
140
141