Notes on portability, and on when #include <linux/blah> is appropriate.
[oweals/busybox.git] / archival / dpkg_deb.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * dpkg-deb packs, unpacks and provides information about Debian archives.
4  *
5  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
6  */
7 #include <fcntl.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <unistd.h>
11
12 #include "unarchive.h"
13 #include "busybox.h"
14
15 #define DPKG_DEB_OPT_CONTENTS   1
16 #define DPKG_DEB_OPT_CONTROL    2
17 #define DPKG_DEB_OPT_FIELD      4
18 #define DPKG_DEB_OPT_EXTRACT    8
19 #define DPKG_DEB_OPT_EXTRACT_VERBOSE    16
20
21 int dpkg_deb_main(int argc, char **argv)
22 {
23         archive_handle_t *ar_archive;
24         archive_handle_t *tar_archive;
25         llist_t *control_tar_llist = NULL;
26         unsigned long opt;
27         char *extract_dir = NULL;
28         short argcount = 1;
29
30         /* Setup the tar archive handle */
31         tar_archive = init_handle();
32
33         /* Setup an ar archive handle that refers to the gzip sub archive */
34         ar_archive = init_handle();
35         ar_archive->sub_archive = tar_archive;
36         ar_archive->filter = filter_accept_list_reassign;
37
38 #ifdef CONFIG_FEATURE_DEB_TAR_GZ
39         ar_archive->accept = llist_add_to(NULL, "data.tar.gz");
40         control_tar_llist = llist_add_to(NULL, "control.tar.gz");
41 #endif
42
43 #ifdef CONFIG_FEATURE_DEB_TAR_BZ2
44         ar_archive->accept = llist_add_to(ar_archive->accept, "data.tar.bz2");
45         control_tar_llist = llist_add_to(control_tar_llist, "control.tar.bz2");
46 #endif
47
48         bb_opt_complementally = "?c--efXx:e--cfXx:f--ceXx:X--cefx:x--cefX";
49         opt = bb_getopt_ulflags(argc, argv, "cefXx");
50
51         if (opt & DPKG_DEB_OPT_CONTENTS) {
52                 tar_archive->action_header = header_verbose_list;
53         }
54         if (opt & DPKG_DEB_OPT_CONTROL) {
55                 ar_archive->accept = control_tar_llist;
56                 tar_archive->action_data = data_extract_all;
57                 if (optind + 1 == argc) {
58                         extract_dir = "./DEBIAN";
59                 } else {
60                         argcount++;
61                 }
62         }
63         if (opt & DPKG_DEB_OPT_FIELD) {
64                 /* Print the entire control file
65                  * it should accept a second argument which specifies a
66                  * specific field to print */
67                 ar_archive->accept = control_tar_llist;
68                 tar_archive->accept = llist_add_to(NULL, "./control");
69                 tar_archive->filter = filter_accept_list;
70                 tar_archive->action_data = data_extract_to_stdout;
71         }
72         if (opt & DPKG_DEB_OPT_EXTRACT) {
73                 tar_archive->action_header = header_list;
74         }
75         if (opt & (DPKG_DEB_OPT_EXTRACT_VERBOSE | DPKG_DEB_OPT_EXTRACT)) {
76                 tar_archive->action_data = data_extract_all;
77                 argcount = 2;
78         }
79
80         if ((optind + argcount) != argc) {
81                 bb_show_usage();
82         }
83
84         tar_archive->src_fd = ar_archive->src_fd = bb_xopen(argv[optind++], O_RDONLY);
85
86         /* Workout where to extract the files */
87         /* 2nd argument is a dir name */
88         if (argv[optind]) {
89                 extract_dir = argv[optind];
90         }
91         if (extract_dir) {
92                 mkdir(extract_dir, 0777);
93                 chdir(extract_dir); /* error check? */
94         }
95         unpack_ar_archive(ar_archive);
96
97         /* Cleanup */
98         close (ar_archive->src_fd);
99
100         return(EXIT_SUCCESS);
101 }