2 * Copyright (c) Zmanda, Inc. All Rights Reserved.
4 * This library is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License version 2.1
6 * as published by the Free Software Foundation.
8 * This library is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
11 * License for more details.
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this library; if not, write to the Free Software Foundation,
15 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
17 * Contact information: Zmanda Inc., 465 S Mathlida Ave, Suite 300
18 * Sunnyvale, CA 94086, USA, or: http://www.zmanda.com
26 static struct option long_options[] = {
27 {"create" , 0, NULL, 1},
28 {"extract" , 0, NULL, 2},
29 {"list" , 0, NULL, 3},
30 {"verbose" , 0, NULL, 4},
31 {"file" , 1, NULL, 5},
32 {"version" , 0, NULL, 6},
39 printf("Usage: amarchiver [--version|--create|--list|--extract] [--verbose]* [--file file]\n");
40 printf(" [filename]*\n");
44 error_exit(const char *action, GError *error)
46 const char *msg = error->message? error->message : "(unknown)";
47 g_fprintf(stderr, "%s: %s\n", action, msg);
52 do_create(char *opt_file, int opt_verbose, int argc, char **argv)
54 FILE *output = stdout;
57 amar_attr_t *attribute;
62 if (opt_file != NULL && strcmp(opt_file,"-") != 0) {
63 fd_out = open(opt_file, O_CREAT|O_WRONLY|O_TRUNC, 0660);
65 error("open of '%s' failed: %s\n", opt_file, strerror(errno));
68 fd_out = fileno(stdout);
71 archive = amar_new(fd_out, O_WRONLY, &error);
73 error_exit("amar_new", error);
77 fd_in = open(argv[i], O_RDONLY);
79 g_fprintf(stderr, "open of '%s' failed: %s\n", argv[i], strerror(errno));
84 file = amar_new_file(archive, argv[i], strlen(argv[i]), NULL, &error);
86 error_exit("amar_new_file", error);
87 attribute = amar_new_attr(file, AMAR_ATTR_GENERIC_DATA, &error);
89 error_exit("amar_new_attr", error);
91 filesize += amar_attr_add_data_fd(attribute, fd_in, 1, &error);
93 error_exit("amar_attr_add_data_fd", error);
95 if (!amar_attr_close(attribute, &error))
96 error_exit("amar_attr_close", error);
97 if (!amar_file_close(file, &error))
98 error_exit("amar_file_close", error);
100 if (opt_verbose == 1) {
101 g_fprintf(output,"%s\n", argv[i]);
102 } else if (opt_verbose > 1) {
103 g_fprintf(output,"%llu %s\n", (unsigned long long)filesize, argv[i]);
109 if (!amar_close(archive, &error))
110 error_exit("amar_close", error);
114 struct read_user_data {
121 extract_file_start_cb(
123 uint16_t filenum G_GNUC_UNUSED,
124 gpointer filename_buf,
126 gboolean *ignore G_GNUC_UNUSED,
129 struct read_user_data *ud = user_data;
132 /* keep the filename for later */
133 *file_data = g_strndup(filename_buf, filename_len);
137 for (i = 0; i < ud->argc; i++) {
138 if (strlen(ud->argv[i]) == filename_len
139 && 0 == strcmp(ud->argv[i], *file_data))
148 extract_file_finish_cb(
149 gpointer user_data G_GNUC_UNUSED,
150 uint16_t filenum G_GNUC_UNUSED,
155 g_fprintf(stderr, _("Data for '%s' may have been truncated\n"),
165 gpointer user_data G_GNUC_UNUSED,
166 uint16_t filenum G_GNUC_UNUSED,
169 gpointer attrid_data G_GNUC_UNUSED,
176 struct read_user_data *ud = user_data;
177 int fd = GPOINTER_TO_INT(*attr_data);
180 char *filename = g_strdup_printf("%s.%d", (char *)file_data, attrid);
181 fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0660);
183 g_fprintf(stderr, _("Could not open '%s' for writing: %s"),
184 filename, strerror(errno));
187 g_fprintf(stderr, "%s\n", filename);
189 *attr_data = GINT_TO_POINTER(fd);
192 if (full_write(fd, data, datasize) != datasize) {
193 g_fprintf(stderr, _("while writing '%s.%d': %s"),
194 (char *)file_data, attrid, strerror(errno));
200 g_fprintf(stderr, _("'%s.%d' may be truncated\n"),
201 (char *)file_data, attrid);
217 GError *error = NULL;
219 amar_attr_handling_t handling[] = {
220 { 0, 0, extract_frag_cb, NULL },
222 struct read_user_data ud;
226 ud.verbose = opt_verbose;
228 if (opt_file && strcmp(opt_file,"-") != 0) {
229 fd_in = open(opt_file, O_RDONLY);
231 error("open of '%s' failed: %s\n", opt_file, strerror(errno));
234 fd_in = fileno(stdin);
237 archive = amar_new(fd_in, O_RDONLY, &error);
239 error_exit("amar_new", error);
241 if (!amar_read(archive, &ud, handling, extract_file_start_cb,
242 extract_file_finish_cb, &error)) {
244 error_exit("amar_read", error);
246 /* one of the callbacks already printed an error message */
253 gpointer user_data G_GNUC_UNUSED,
254 uint16_t filenum G_GNUC_UNUSED,
255 gpointer filename_buf,
258 gpointer *file_data G_GNUC_UNUSED)
260 g_printf("%.*s\n", (int)filename_len, (char *)filename_buf);
268 int opt_verbose G_GNUC_UNUSED)
271 GError *error = NULL;
273 amar_attr_handling_t handling[] = {
274 { 0, 0, NULL, NULL },
277 if (opt_file && strcmp(opt_file,"-") != 0) {
278 fd_in = open(opt_file, O_RDONLY);
280 error("open of '%s' failed: %s\n", opt_file, strerror(errno));
283 fd_in = fileno(stdin);
286 archive = amar_new(fd_in, O_RDONLY, &error);
288 error_exit("amar_new", error);
290 if (!amar_read(archive, NULL, handling, list_file_start_cb,
293 error_exit("amar_read", error);
295 /* one of the callbacks already printed an error message */
308 char *opt_file = NULL;
311 int option_index = 0;
312 int c = getopt_long (argc, argv, "", long_options, &option_index);
317 case 1: opt_create = 1;
319 case 2: opt_extract = 1;
321 case 3: opt_list = 1;
323 case 4: opt_verbose += 1;
325 case 5: opt_file = stralloc(optarg);
327 case 6: printf("amarchiver %s\n", version());
335 /* check those arguments */
336 if (opt_create + opt_extract + opt_list == 0) {
337 g_fprintf(stderr,"--create, --list or --extract must be provided\n");
340 if (opt_create + opt_extract + opt_list > 1) {
341 g_fprintf(stderr,"Only one of --create, --list or --extract must be provided\n");
346 g_fprintf(stderr, "--list does not take any additional filenames\n");
352 do_create(opt_file, opt_verbose, argc, argv);
353 else if (opt_extract > 0)
354 do_extract(opt_file, opt_verbose, argc, argv);
355 else if (opt_list > 0)
356 do_list(opt_file, opt_verbose);