1/* vi: set sw=4 ts=4: */
2/*
3 * Mini ar implementation for busybox
4 *
5 * Copyright (C) 2000 by Glenn McGrath
6 * Written by Glenn McGrath <bug1@iinet.net.au> 1 June 2000
7 *
8 * Based in part on BusyBox tar, Debian dpkg-deb and GNU ar.
9 *
10 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
11 *
12 * There is no single standard to adhere to so ar may not portable
13 * between different systems
14 * http://www.unix-systems.org/single_unix_specification_v2/xcu/ar.html
15 */
16
17#include "libbb.h"
18#include "unarchive.h"
19
20static void header_verbose_list_ar(const file_header_t *file_header)
21{
22	const char *mode = bb_mode_string(file_header->mode);
23	char *mtime;
24
25	mtime = ctime(&file_header->mtime);
26	mtime[16] = ' ';
27	memmove(&mtime[17], &mtime[20], 4);
28	mtime[21] = '\0';
29	printf("%s %d/%d%7d %s %s\n", &mode[1], file_header->uid, file_header->gid,
30			(int) file_header->size, &mtime[4], file_header->name);
31}
32
33#define AR_CTX_PRINT		0x01
34#define AR_CTX_LIST		0x02
35#define AR_CTX_EXTRACT		0x04
36#define AR_OPT_PRESERVE_DATE	0x08
37#define AR_OPT_VERBOSE		0x10
38#define AR_OPT_CREATE		0x20
39#define AR_OPT_INSERT		0x40
40
41int ar_main(int argc, char **argv);
42int ar_main(int argc, char **argv)
43{
44	static const char msg_unsupported_err[] ALIGN1 =
45		"archive %s is not supported";
46
47	archive_handle_t *archive_handle;
48	unsigned opt;
49	char magic[8];
50
51	archive_handle = init_handle();
52
53	/* Prepend '-' to the first argument if required */
54	opt_complementary = "--:p:t:x:-1:p--tx:t--px:x--pt";
55	opt = getopt32(argv, "ptxovcr");
56
57	if (opt & AR_CTX_PRINT) {
58		archive_handle->action_data = data_extract_to_stdout;
59	}
60	if (opt & AR_CTX_LIST) {
61		archive_handle->action_header = header_list;
62	}
63	if (opt & AR_CTX_EXTRACT) {
64		archive_handle->action_data = data_extract_all;
65	}
66	if (opt & AR_OPT_PRESERVE_DATE) {
67		archive_handle->flags |= ARCHIVE_PRESERVE_DATE;
68	}
69	if (opt & AR_OPT_VERBOSE) {
70		archive_handle->action_header = header_verbose_list_ar;
71	}
72	if (opt & AR_OPT_CREATE) {
73		bb_error_msg_and_die(msg_unsupported_err, "creation");
74	}
75	if (opt & AR_OPT_INSERT) {
76		bb_error_msg_and_die(msg_unsupported_err, "insertion");
77	}
78
79	archive_handle->src_fd = xopen(argv[optind++], O_RDONLY);
80
81	while (optind < argc) {
82		archive_handle->filter = filter_accept_list;
83		llist_add_to(&(archive_handle->accept), argv[optind++]);
84	}
85
86	xread(archive_handle->src_fd, magic, 7);
87	if (strncmp(magic, "!<arch>", 7) != 0) {
88		bb_error_msg_and_die("invalid ar magic");
89	}
90	archive_handle->offset += 7;
91
92	while (get_header_ar(archive_handle) == EXIT_SUCCESS)
93		continue;
94
95	return EXIT_SUCCESS;
96}
97