aboutsummaryrefslogtreecommitdiff
path: root/archival/dpkg_deb.c
diff options
context:
space:
mode:
Diffstat (limited to 'archival/dpkg_deb.c')
-rw-r--r--archival/dpkg_deb.c139
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
23extern int dpkg_deb_main(int argc, char **argv) 24extern 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