1 /* 2ooM: The Master of Orion II Reverse Engineering Project
2 * Simple command-line tool to extract LBX archive files.
3 * Copyright (C) 2006-2008 Nick Bowler
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
29 static void printusage(void)
31 puts("usage: lbxtool [-l|-x] [-v] [-f path] [file ...]");
34 static void printhelp(void)
37 puts("For now, see the man page for detailed help.");
40 static const char *progname;
41 #define errmsg(fmt, ...) (\
42 fprintf(stderr, "%s: " fmt, progname, __VA_ARGS__)\
51 int filematch(char **argv, const char *name)
55 for (i = 0; argv[i]; i++) {
56 switch(fnmatch(argv[i], name, 0)) {
62 errmsg("error matching glob: %s.\n", argv[i]);
70 int list(FILE *f, const char *name, int verbose, char **argv) {
75 lbx = lbx_fopen(f, name);
77 errmsg("failed to open archive: %s.\n", lbx_strerror());
81 nfiles = lbx_numfiles(lbx);
83 printf("Files in archive: %zu\n", nfiles);
86 for (i = 0; i < nfiles; i++) {
87 struct lbx_statbuf stat;
89 lbx_stat(lbx, i, &stat);
91 switch (filematch(argv, stat.name)) {
97 printf("%s", stat.name);
99 printf(" size=%zu bytes", stat.size);
112 int extract(FILE *f, const char *name, int verbose, char **argv) {
117 lbx = lbx_fopen(f, name);
119 errmsg("failed to open archive: %s.\n", lbx_strerror());
123 nfiles = lbx_numfiles(lbx);
125 printf("Files in archive: %zu\n", nfiles);
128 for (i = 0; i < nfiles; i++) {
129 struct lbx_statbuf stat;
134 lbx_stat(lbx, i, &stat);
136 switch (filematch(argv, stat.name)) {
142 of = fopen(stat.name, "wbx");
144 errmsg("failed to create output file %s: %m.\n",
149 if (verbose) printf("extracting %s...\n", stat.name);
150 rc = lbx_extract(lbx, i, of);
151 if (rc < stat.size) {
152 if (rc == 0) remove(stat.name);
153 errmsg("error extracting %s: %s.\n",
154 stat.name, lbx_strerror());
157 if (verbose) printf("wrote %zu bytes.\n", rc);
167 int main(int argc, char **argv)
169 int mode = MODE_NONE, verbose = 0;
170 const char *name = "stdin";
174 static const char *sopts = "lxf:i:vV";
175 static const struct option lopts[] = {
176 { "list", 0, NULL, 'l' },
177 { "extract", 0, NULL, 'x' },
179 { "file", 1, NULL, 'f' },
180 { "index", 1, NULL, 'i' },
182 { "verbose", 0, NULL, 'v' },
184 { "version", 0, NULL, 'V' },
185 { "usage", 0, NULL, 'U' },
186 { "help", 0, NULL, 'H' },
191 progname = "lbxtool"; /* argv[0]; */
192 while ((opt = getopt_long(argc, argv, sopts, lopts, NULL)) != -1) {
201 if (strcmp(optarg, "-") == 0)
204 name = strrchr(optarg, '/');
205 name = name ? name+1 : optarg;
207 f = fopen(optarg, "rb");
209 errmsg("failed to open file %s: %m\n", optarg);
214 /* FIXME: Add index file support. */
220 puts(VERSION_BOILERPLATE("lbxtool"));
235 return list(f, name, verbose, &argv[optind]);
237 return extract(f, name, verbose, &argv[optind]);
240 fprintf(stderr, "%s: you must specify a mode.\n", progname);