Rewrite archive utility (command line parsing, C++)
[tennix.git] / src / archivetool.cc
blob69b9a8e6bf9b46d1aaf95041b53304dc26a24068
2 /**
4 * Tennix Archive File Format
5 * Copyright (C) 2009-2010 Thomas Perl <thp@thpinfo.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
20 * MA 02110-1301, USA.
22 **/
24 #include "tennix.h"
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <libgen.h>
29 #include <sys/stat.h>
31 #include "archive.h"
33 static int
34 extract_file(TennixArchive *tnxar, bool verbose)
36 char *data = tnxar->getItemBytes();
38 if (verbose) {
39 printf("%s\n", tnxar->getItemFilename());
42 FILE *fp = fopen(tnxar->getItemFilename(), "wb");
43 if (fp == NULL) {
44 return 1;
46 fwrite(data, tnxar->getItemSize(), 1, fp);
47 fclose(fp);
49 free(data);
51 return 0;
55 class ArchiveTool {
56 public:
57 ArchiveTool(int argc, char **argv);
59 int run();
61 private:
62 int usage();
64 int create(bool verbose);
65 int test(bool verbose);
66 int extract(bool verbose);
68 int argc;
69 char **argv;
72 ArchiveTool::ArchiveTool(int argc, char **argv)
73 : argc(argc)
74 , argv(argv)
78 int
79 ArchiveTool::run()
81 bool do_create = false;
82 bool do_test = false;
83 bool do_extract = false;
84 bool verbose = false;
86 if (argc < 2) {
87 return usage();
90 char *opts = argv[1];
91 if (*opts == '-') opts++;
93 while (*opts) {
94 switch (*opts) {
95 case 'c':
96 do_create = true;
97 break;
98 case 't':
99 do_test = true;
100 break;
101 case 'x':
102 do_extract = true;
103 break;
104 case 'v':
105 verbose = true;
106 break;
107 case 'f':
108 if (opts[1]) {
109 return usage();
111 break;
112 default:
113 return usage();
114 break;
116 opts++;
119 if (do_create && !do_test && !do_extract && argc > 3) {
120 return create(verbose);
121 } else if (do_test && !do_create && !do_extract && argc > 2) {
122 return test(verbose);
123 } else if (do_extract && !do_create && !do_test && argc > 2) {
124 return extract(verbose);
127 return usage();
131 ArchiveTool::create(bool verbose)
133 if (argc < 4) {
134 fprintf(stderr, "Refusing to create an empty archive.\n");
135 return 1;
138 char *archive = argv[2];
139 if (strcmp(".tnx", archive + strlen(archive) - 4) != 0) {
140 fprintf(stderr, "Wrong file extension: %s\n", archive);
141 return 1;
144 TennixArchive tnxar;
145 for (int i=3; i<argc; i++) {
146 FILE *fp = fopen(argv[i], "rb");
147 fseek(fp, 0, SEEK_END);
148 size_t len = ftell(fp);
149 fseek(fp, 0, SEEK_SET);
150 char *data = (char*)malloc(len);
151 tnx_assert(fread(data, len, 1, fp) == 1);
152 fclose(fp);
153 char *filename = strdup(basename(argv[i]));
154 if (verbose) {
155 printf("%s\n", filename);
157 tnxar.appendItem(filename, data, len);
159 tnxar.buildFile(archive);
160 return 0;
164 ArchiveTool::test(bool verbose)
166 TennixArchive tnxar(argv[2]);
168 while (!tnxar.endOfFile()) {
169 if (verbose) {
170 printf("%ld %s\n", tnxar.getItemSize(), tnxar.getItemFilename());
171 } else {
172 printf("%s\n", tnxar.getItemFilename());
174 tnxar.next();
177 return 0;
181 ArchiveTool::extract(bool verbose)
183 TennixArchive tnxar(argv[2]);
185 if (argc == 3) {
186 while (!tnxar.endOfFile()) {
187 if (extract_file(&tnxar, verbose) != 0) {
188 printf("Error extracting file\n");
189 return 1;
191 tnxar.next();
193 return 0;
196 for (int i=3; i<argc; i++) {
197 if (tnxar.setItemFilename(argv[i])) {
198 if (extract_file(&tnxar, verbose) != 0) {
199 printf("Error extracting file: %s\n", argv[i]);
200 return 1;
202 } else {
203 fprintf(stderr, "File not in archive: %s\n", argv[i]);
204 return 1;
208 return 0;
212 ArchiveTool::usage()
214 fprintf(stderr, "Usage: %s [-ctxvf] <archive.tnx> file1 ...\n", argv[0]);
215 fprintf(stderr, " -c ... Create archive\n");
216 fprintf(stderr, " -t ... Test archive (list contents)\n");
217 fprintf(stderr, " -x ... Extract archive\n");
218 fprintf(stderr, " -v ... Verbose output\n");
219 fprintf(stderr, " -f ... Filename of archive (optional)\n");
220 return 1;
224 main(int argc, char **argv)
226 ArchiveTool tool(argc, argv);
227 return tool.run();