diff options
Diffstat (limited to 'archival/dpkg_deb.c')
-rw-r--r-- | archival/dpkg_deb.c | 139 |
1 files changed, 60 insertions, 79 deletions
diff --git a/archival/dpkg_deb.c b/archival/dpkg_deb.c index 29692f7d7..06a810cc1 100644 --- a/archival/dpkg_deb.c +++ b/archival/dpkg_deb.c | |||
@@ -13,119 +13,100 @@ | |||
13 | * along with this program; if not, write to the Free Software | 13 | * along with this program; if not, write to the Free Software |
14 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | 14 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
15 | */ | 15 | */ |
16 | 16 | #include <fcntl.h> | |
17 | #include <stdlib.h> | 17 | #include <stdlib.h> |
18 | #include <string.h> | 18 | #include <string.h> |
19 | #include <unistd.h> | ||
19 | #include <getopt.h> | 20 | #include <getopt.h> |
20 | #include "unarchive.h" | 21 | #include "unarchive.h" |
21 | #include "busybox.h" | 22 | #include "busybox.h" |
22 | 23 | ||
23 | extern int dpkg_deb_main(int argc, char **argv) | 24 | extern int dpkg_deb_main(int argc, char **argv) |
24 | { | 25 | { |
25 | char *prefix = NULL; | 26 | archive_handle_t *ar_archive; |
26 | char *filename = NULL; | 27 | archive_handle_t *tar_gz_archive; |
27 | char *output_buffer = NULL; | ||
28 | int opt = 0; | 28 | int opt = 0; |
29 | int arg_type = 0; | 29 | #ifndef CONFIG_FEATURE_DPKG_DEB_EXTRACT_ONLY |
30 | int deb_extract_funct = extract_create_leading_dirs | extract_unconditional; | 30 | const llist_t *control_tar_gz_llist = add_to_list(NULL, "control.tar.gz"); |
31 | #endif | ||
32 | #ifndef CONFIG_AR | ||
33 | char magic[7]; | ||
34 | #endif | ||
35 | |||
36 | /* a .deb file is an ar archive that contain three files, | ||
37 | * data.tar.gz, control.tar.gz and debian | ||
38 | */ | ||
31 | 39 | ||
32 | const int arg_type_prefix = 1; | 40 | /* Setup the tar archive handle */ |
33 | const int arg_type_field = 2; | 41 | tar_gz_archive = init_handle(); |
34 | const int arg_type_filename = 4; | ||
35 | // const int arg_type_un_ar_gz = 8; | ||
36 | 42 | ||
37 | while ((opt = getopt(argc, argv, "ceftXxI")) != -1) { | 43 | /* Setup an ar archive handle that refers to the gzip sub archive */ |
44 | ar_archive = init_handle(); | ||
45 | ar_archive->action_data_subarchive = get_header_tar_gz; | ||
46 | ar_archive->sub_archive = tar_gz_archive; | ||
47 | ar_archive->filter = filter_accept_list; | ||
48 | ar_archive->accept = add_to_list(NULL, "data.tar.gz"); | ||
49 | |||
50 | #ifndef CONFIG_FEATURE_DPKG_DEB_EXTRACT_ONLY | ||
51 | while ((opt = getopt(argc, argv, "cefXx")) != -1) { | ||
52 | #else | ||
53 | while ((opt = getopt(argc, argv, "x")) != -1) { | ||
54 | #endif | ||
38 | switch (opt) { | 55 | switch (opt) { |
56 | #ifndef CONFIG_FEATURE_DPKG_DEB_EXTRACT_ONLY | ||
39 | case 'c': | 57 | case 'c': |
40 | deb_extract_funct |= extract_data_tar_gz; | 58 | tar_gz_archive->action_header = header_verbose_list; |
41 | deb_extract_funct |= extract_verbose_list; | ||
42 | break; | 59 | break; |
43 | case 'e': | 60 | case 'e': |
44 | arg_type = arg_type_prefix; | 61 | ar_archive->accept = control_tar_gz_llist; |
45 | deb_extract_funct |= extract_control_tar_gz; | 62 | tar_gz_archive->action_data = data_extract_all; |
46 | deb_extract_funct |= extract_all_to_fs; | ||
47 | break; | 63 | break; |
48 | case 'f': | 64 | case 'f': |
49 | arg_type = arg_type_field; | 65 | /* Print the entire control file |
50 | deb_extract_funct |= extract_control_tar_gz; | 66 | * it should accept a second argument which specifies a |
51 | deb_extract_funct |= extract_one_to_buffer; | 67 | * specific field to print */ |
52 | filename = xstrdup("./control"); | 68 | ar_archive->accept = control_tar_gz_llist; |
53 | break; | 69 | tar_gz_archive->accept = add_to_list(NULL, "./control");; |
54 | case 't': /* --fsys-tarfile, i just made up this short name */ | 70 | tar_gz_archive->filter = filter_accept_list; |
55 | /* Integrate the functionality needed with some code from ar.c */ | 71 | tar_gz_archive->action_data = data_extract_to_stdout; |
56 | error_msg_and_die("Option disabled"); | ||
57 | // arg_type = arg_type_un_ar_gz; | ||
58 | break; | 72 | break; |
59 | case 'X': | 73 | case 'X': |
60 | arg_type = arg_type_prefix; | 74 | tar_gz_archive->action_header = header_list; |
61 | deb_extract_funct |= extract_data_tar_gz; | 75 | #endif |
62 | deb_extract_funct |= extract_all_to_fs; | ||
63 | deb_extract_funct |= extract_list; | ||
64 | case 'x': | 76 | case 'x': |
65 | arg_type = arg_type_prefix; | 77 | tar_gz_archive->action_data = data_extract_all; |
66 | deb_extract_funct |= extract_data_tar_gz; | ||
67 | deb_extract_funct |= extract_all_to_fs; | ||
68 | break; | ||
69 | case 'I': | ||
70 | arg_type = arg_type_filename; | ||
71 | deb_extract_funct |= extract_control_tar_gz; | ||
72 | deb_extract_funct |= extract_one_to_buffer; | ||
73 | break; | 78 | break; |
74 | default: | 79 | default: |
75 | show_usage(); | 80 | show_usage(); |
76 | } | 81 | } |
77 | } | 82 | } |
78 | 83 | ||
79 | if (optind == argc) { | 84 | if (optind + 2 < argc) { |
80 | show_usage(); | 85 | show_usage(); |
81 | } | 86 | } |
82 | 87 | ||
88 | tar_gz_archive->src_fd = ar_archive->src_fd = xopen(argv[optind++], O_RDONLY); | ||
89 | |||
83 | /* Workout where to extract the files */ | 90 | /* Workout where to extract the files */ |
84 | if (arg_type == arg_type_prefix) { | 91 | /* 2nd argument is a dir name */ |
85 | /* argument is a dir name */ | 92 | mkdir(argv[optind], 0777); |
86 | if ((optind + 1) == argc ) { | 93 | chdir(argv[optind]); |
87 | prefix = xstrdup("./DEBIAN/"); | ||
88 | } else { | ||
89 | prefix = (char *) xmalloc(strlen(argv[optind + 1]) + 2); | ||
90 | strcpy(prefix, argv[optind + 1]); | ||
91 | /* Make sure the directory has a trailing '/' */ | ||
92 | if (last_char_is(prefix, '/') == NULL) { | ||
93 | strcat(prefix, "/"); | ||
94 | } | ||
95 | } | ||
96 | mkdir(prefix, 0777); | ||
97 | } | ||
98 | 94 | ||
99 | if (arg_type == arg_type_filename) { | 95 | #ifdef CONFIG_AR |
100 | if ((optind + 1) != argc) { | 96 | unpack_ar_archive(ar_archive); |
101 | filename = xstrdup(argv[optind + 1]); | 97 | #else |
102 | } else { | 98 | xread_all(ar_archive->src_fd, magic, 7); |
103 | error_msg_and_die("-I currently requires a filename to be specified"); | 99 | if (strncmp(magic, "!<arch>", 7) != 0) { |
104 | } | 100 | error_msg_and_die("Invalid ar magic"); |
105 | } | 101 | } |
102 | ar_archive->offset += 7; | ||
106 | 103 | ||
107 | output_buffer = deb_extract(argv[optind], stdout, deb_extract_funct, prefix, filename); | 104 | while (get_header_ar(ar_archive) == EXIT_SUCCESS); |
105 | #endif | ||
108 | 106 | ||
109 | if ((arg_type == arg_type_filename) && (output_buffer != NULL)) { | 107 | /* Cleanup */ |
110 | puts(output_buffer); | 108 | close (ar_archive->src_fd); |
111 | } | ||
112 | else if (arg_type == arg_type_field) { | ||
113 | char *field = NULL; | ||
114 | char *name; | ||
115 | char *value; | ||
116 | int field_start = 0; | ||
117 | |||
118 | while (1) { | ||
119 | field_start += read_package_field(&output_buffer[field_start], &name, &value); | ||
120 | if (name == NULL) { | ||
121 | break; | ||
122 | } | ||
123 | if (strcmp(name, argv[optind + 1]) == 0) { | ||
124 | puts(value); | ||
125 | } | ||
126 | free(field); | ||
127 | } | ||
128 | } | ||
129 | 109 | ||
130 | return(EXIT_SUCCESS); | 110 | return(EXIT_SUCCESS); |
131 | } | 111 | } |
112 | |||