2 * Copyright (c) 2008-2012 Zmanda, Inc. All Rights Reserved.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 * Contact information: Zmanda Inc., 465 S. Mathilda Ave., Suite 300
19 * Sunnyvale, CA 94085, 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");
45 error_exit(const char *action, GError *error)
47 const char *msg = error->message? error->message : "(unknown)";
48 g_fprintf(stderr, "%s: %s\n", action, msg);
53 do_create(char *opt_file, int opt_verbose, int argc, char **argv)
55 FILE *output = stdout;
58 amar_attr_t *attribute;
63 if (opt_file != NULL && strcmp(opt_file,"-") != 0) {
64 fd_out = open(opt_file, O_CREAT|O_WRONLY|O_TRUNC, 0660);
66 error("open of '%s' failed: %s\n", opt_file, strerror(errno));
69 fd_out = fileno(stdout);
72 archive = amar_new(fd_out, O_WRONLY, &error);
74 error_exit("amar_new", error);
78 fd_in = open(argv[i], O_RDONLY);
80 g_fprintf(stderr, "open of '%s' failed: %s\n", argv[i], strerror(errno));
85 file = amar_new_file(archive, argv[i], strlen(argv[i]), NULL, &error);
87 error_exit("amar_new_file", error);
88 attribute = amar_new_attr(file, AMAR_ATTR_GENERIC_DATA, &error);
90 error_exit("amar_new_attr", error);
92 filesize += amar_attr_add_data_fd(attribute, fd_in, 1, &error);
94 error_exit("amar_attr_add_data_fd", error);
96 if (!amar_attr_close(attribute, &error))
97 error_exit("amar_attr_close", error);
98 if (!amar_file_close(file, &error))
99 error_exit("amar_file_close", error);
101 if (opt_verbose == 1) {
102 g_fprintf(output,"%s\n", argv[i]);
103 } else if (opt_verbose > 1) {
104 g_fprintf(output,"%llu %s\n", (unsigned long long)filesize, argv[i]);
110 if (!amar_close(archive, &error))
111 error_exit("amar_close", error);
115 struct read_user_data {
122 extract_file_start_cb(
124 uint16_t filenum G_GNUC_UNUSED,
125 gpointer filename_buf,
127 gboolean *ignore G_GNUC_UNUSED,
130 struct read_user_data *ud = user_data;
133 /* keep the filename for later */
134 *file_data = g_strndup(filename_buf, filename_len);
138 for (i = 0; i < ud->argc; i++) {
139 if (strlen(ud->argv[i]) == filename_len
140 && 0 == strcmp(ud->argv[i], *file_data))
149 extract_file_finish_cb(
150 gpointer user_data G_GNUC_UNUSED,
151 uint16_t filenum G_GNUC_UNUSED,
156 g_fprintf(stderr, _("Data for '%s' may have been truncated\n"),
166 gpointer user_data G_GNUC_UNUSED,
167 uint16_t filenum G_GNUC_UNUSED,
170 gpointer attrid_data G_GNUC_UNUSED,
177 struct read_user_data *ud = user_data;
178 int fd = GPOINTER_TO_INT(*attr_data);
181 char *filename = g_strdup_printf("%s.%d", (char *)file_data, attrid);
182 fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0660);
184 g_fprintf(stderr, _("Could not open '%s' for writing: %s"),
185 filename, strerror(errno));
188 g_fprintf(stderr, "%s\n", filename);
190 *attr_data = GINT_TO_POINTER(fd);
193 if (full_write(fd, data, datasize) != datasize) {
194 g_fprintf(stderr, _("while writing '%s.%d': %s"),
195 (char *)file_data, attrid, strerror(errno));
201 g_fprintf(stderr, _("'%s.%d' may be truncated\n"),
202 (char *)file_data, attrid);
218 GError *error = NULL;
220 amar_attr_handling_t handling[] = {
221 { 0, 0, extract_frag_cb, NULL },
223 struct read_user_data ud;
227 ud.verbose = opt_verbose;
229 if (opt_file && strcmp(opt_file,"-") != 0) {
230 fd_in = open(opt_file, O_RDONLY);
232 error("open of '%s' failed: %s\n", opt_file, strerror(errno));
235 fd_in = fileno(stdin);
238 archive = amar_new(fd_in, O_RDONLY, &error);
240 error_exit("amar_new", error);
242 if (!amar_read(archive, &ud, handling, extract_file_start_cb,
243 extract_file_finish_cb, &error)) {
245 error_exit("amar_read", error);
247 /* one of the callbacks already printed an error message */
254 gpointer user_data G_GNUC_UNUSED,
255 uint16_t filenum G_GNUC_UNUSED,
256 gpointer filename_buf,
259 gpointer *file_data G_GNUC_UNUSED)
261 g_printf("%.*s\n", (int)filename_len, (char *)filename_buf);
269 int opt_verbose G_GNUC_UNUSED)
272 GError *error = NULL;
274 amar_attr_handling_t handling[] = {
275 { 0, 0, NULL, NULL },
278 if (opt_file && strcmp(opt_file,"-") != 0) {
279 fd_in = open(opt_file, O_RDONLY);
281 error("open of '%s' failed: %s\n", opt_file, strerror(errno));
284 fd_in = fileno(stdin);
287 archive = amar_new(fd_in, O_RDONLY, &error);
289 error_exit("amar_new", error);
291 if (!amar_read(archive, NULL, handling, list_file_start_cb,
294 error_exit("amar_read", error);
296 /* one of the callbacks already printed an error message */
309 char *opt_file = NULL;
312 int option_index = 0;
313 int c = getopt_long (argc, argv, "", long_options, &option_index);
318 case 1: opt_create = 1;
320 case 2: opt_extract = 1;
322 case 3: opt_list = 1;
324 case 4: opt_verbose += 1;
326 case 5: opt_file = stralloc(optarg);
328 case 6: printf("amarchiver %s\n", VERSION);
336 /* check those arguments */
337 if (opt_create + opt_extract + opt_list == 0) {
338 g_fprintf(stderr,"--create, --list or --extract must be provided\n");
341 if (opt_create + opt_extract + opt_list > 1) {
342 g_fprintf(stderr,"Only one of --create, --list or --extract must be provided\n");
347 do_create(opt_file, opt_verbose, argc, argv);
348 else if (opt_extract > 0)
349 do_extract(opt_file, opt_verbose, argc, argv);
350 else if (opt_list > 0)
351 do_list(opt_file, opt_verbose);