diff options
author | Glenn L McGrath <bug1@ihug.co.nz> | 2001-06-13 07:26:39 +0000 |
---|---|---|
committer | Glenn L McGrath <bug1@ihug.co.nz> | 2001-06-13 07:26:39 +0000 |
commit | 9aff9036035fbed074e8e711b96c5c934e668884 (patch) | |
tree | 4db8fdd4b9f429b416d068794c79bfc0df844e20 | |
parent | dab3d46b9d35e0a0279b3700fe411f876bb25781 (diff) | |
download | busybox-w32-9aff9036035fbed074e8e711b96c5c934e668884.tar.gz busybox-w32-9aff9036035fbed074e8e711b96c5c934e668884.tar.bz2 busybox-w32-9aff9036035fbed074e8e711b96c5c934e668884.zip |
Reorganise archive extraction code
-rw-r--r-- | Makefile | 28 | ||||
-rw-r--r-- | ar.c | 88 | ||||
-rw-r--r-- | archival/ar.c | 88 | ||||
-rw-r--r-- | archival/dpkg.c | 25 | ||||
-rw-r--r-- | archival/dpkg_deb.c | 105 | ||||
-rw-r--r-- | dpkg.c | 25 | ||||
-rw-r--r-- | dpkg_deb.c | 105 | ||||
-rw-r--r-- | include/libbb.h | 51 | ||||
-rw-r--r-- | libbb/deb_extract.c | 96 | ||||
-rw-r--r-- | libbb/get_ar_headers.c | 15 | ||||
-rw-r--r-- | libbb/libbb.h | 51 |
11 files changed, 332 insertions, 345 deletions
@@ -236,21 +236,21 @@ endif | |||
236 | 236 | ||
237 | LIBBB = libbb | 237 | LIBBB = libbb |
238 | LIBBB_LIB = libbb.a | 238 | LIBBB_LIB = libbb.a |
239 | LIBBB_CSRC= ask_confirmation.c chomp.c \ | 239 | LIBBB_CSRC= append_archive_list.c add_from_archive_list.c ask_confirmation.c \ |
240 | concat_path_file.c copy_file.c copy_file_chunk.c create_path.c \ | 240 | chomp.c concat_path_file.c copy_file.c copy_file_chunk.c create_path.c \ |
241 | daemon.c deb_extract.c device_open.c error_msg.c error_msg_and_die.c \ | 241 | daemon.c deb_extract.c device_open.c error_msg.c error_msg_and_die.c \ |
242 | find_mount_point.c find_pid_by_name.c find_root_device.c full_read.c \ | 242 | extract_archive.c fgets_str.c find_mount_point.c find_pid_by_name.c \ |
243 | full_write.c get_ar_headers.c get_console.c get_last_path_component.c \ | 243 | find_root_device.c full_read.c full_write.c get_ar_headers.c get_console.c \ |
244 | get_line_from_file.c gz_open.c human_readable.c isdirectory.c \ | 244 | get_last_path_component.c get_line_from_file.c get_tar_headers.c \ |
245 | kernel_version.c loop.c mode_string.c module_syscalls.c mtab.c mtab_file.c \ | 245 | get_tar_gz_headers.c gz_open.c human_readable.c isdirectory.c kernel_version.c \ |
246 | my_getgrnam.c my_getgrgid.c my_getpwnam.c my_getpwnamegid.c my_getpwuid.c \ | 246 | loop.c mode_string.c module_syscalls.c mtab.c mtab_file.c my_getgrnam.c \ |
247 | parse_mode.c parse_number.c perror_msg.c perror_msg_and_die.c print_file.c \ | 247 | my_getgrgid.c my_getpwnam.c my_getpwnamegid.c my_getpwuid.c parse_mode.c \ |
248 | process_escape_sequence.c read_package_field.c read_text_file_to_buffer.c \ | 248 | parse_number.c perror_msg.c perror_msg_and_die.c print_file.c \ |
249 | recursive_action.c safe_read.c safe_strncpy.c seek_ared_file.c syscalls.c \ | 249 | process_escape_sequence.c read_package_field.c recursive_action.c safe_read.c \ |
250 | syslog_msg_with_name.c time_string.c trim.c untar.c unzip.c vdprintf.c \ | 250 | safe_strncpy.c syscalls.c syslog_msg_with_name.c time_string.c \ |
251 | verror_msg.c vperror_msg.c wfopen.c xfuncs.c xgetcwd.c xreadlink.c \ | 251 | trim.c unzip.c vdprintf.c verror_msg.c vperror_msg.c wfopen.c xfuncs.c \ |
252 | xregcomp.c interface.c remove_file.c last_char_is.c copyfd.c \ | 252 | xgetcwd.c xreadlink.c xregcomp.c interface.c remove_file.c last_char_is.c \ |
253 | vherror_msg.c herror_msg.c herror_msg_and_die.c xgethostbyname.c | 253 | copyfd.c vherror_msg.c herror_msg.c herror_msg_and_die.c xgethostbyname.c |
254 | LIBBB_OBJS=$(patsubst %.c,$(LIBBB)/%.o, $(LIBBB_CSRC)) | 254 | LIBBB_OBJS=$(patsubst %.c,$(LIBBB)/%.o, $(LIBBB_CSRC)) |
255 | LIBBB_CFLAGS = -I$(LIBBB) | 255 | LIBBB_CFLAGS = -I$(LIBBB) |
256 | ifneq ($(strip $(BB_SRC_DIR)),) | 256 | ifneq ($(strip $(BB_SRC_DIR)),) |
@@ -30,36 +30,27 @@ | |||
30 | 30 | ||
31 | extern int ar_main(int argc, char **argv) | 31 | extern int ar_main(int argc, char **argv) |
32 | { | 32 | { |
33 | const int preserve_date = 1; /* preserve original dates */ | 33 | FILE *src_stream = NULL; |
34 | const int verbose = 2; /* be verbose */ | 34 | int extract_function = 0, opt = 0; |
35 | const int display = 4; /* display contents */ | 35 | file_headers_t *head; |
36 | const int extract_to_file = 8; /* extract contents of archive */ | 36 | file_headers_t *ar_extract_list = NULL; |
37 | const int extract_to_stdout = 16; /* extract to stdout */ | ||
38 | |||
39 | FILE *src_file = NULL, *dst_file = NULL; | ||
40 | int funct = 0, opt=0; | ||
41 | |||
42 | ar_headers_t *head, *ar_extract_list=NULL; | ||
43 | |||
44 | ar_extract_list = (ar_headers_t *) xcalloc(1, sizeof(ar_headers_t)); | ||
45 | head = (ar_headers_t *) xcalloc(1, sizeof(ar_headers_t)); | ||
46 | 37 | ||
47 | while ((opt = getopt(argc, argv, "ovtpx")) != -1) { | 38 | while ((opt = getopt(argc, argv, "ovtpx")) != -1) { |
48 | switch (opt) { | 39 | switch (opt) { |
49 | case 'o': | 40 | case 'o': |
50 | funct |= preserve_date; | 41 | extract_function |= extract_preserve_date; |
51 | break; | 42 | break; |
52 | case 'v': | 43 | case 'v': |
53 | funct |= verbose; | 44 | extract_function |= extract_verbose_list; |
54 | break; | 45 | break; |
55 | case 't': | 46 | case 't': |
56 | funct |= display; | 47 | extract_function |= extract_list; |
57 | break; | 48 | break; |
58 | case 'p': | 49 | case 'p': |
59 | funct |= extract_to_stdout; | 50 | extract_function |= extract_to_stdout; |
60 | break; | 51 | break; |
61 | case 'x': | 52 | case 'x': |
62 | funct |= extract_to_file; | 53 | extract_function |= extract_all_to_fs; |
63 | break; | 54 | break; |
64 | default: | 55 | default: |
65 | show_usage(); | 56 | show_usage(); |
@@ -71,57 +62,28 @@ extern int ar_main(int argc, char **argv) | |||
71 | show_usage(); | 62 | show_usage(); |
72 | } | 63 | } |
73 | 64 | ||
74 | if ( (src_file = wfopen(argv[optind], "r")) < 0) { | 65 | src_stream = xfopen(argv[optind++], "r"); |
75 | error_msg_and_die("Cannot read %s", argv[optind]); | 66 | head = get_ar_headers(src_stream); |
76 | } | ||
77 | 67 | ||
78 | optind++; | ||
79 | head = get_ar_headers(src_file); | ||
80 | /* find files to extract or display */ | 68 | /* find files to extract or display */ |
81 | /* search through argv and build extract list */ | 69 | /* search through argv and build extract list */ |
82 | for (;optind < argc; optind++) { | 70 | ar_extract_list = (file_headers_t *) xcalloc(1, sizeof(file_headers_t)); |
83 | ar_headers_t *ar_entry; | 71 | if (optind < argc) { |
84 | ar_entry = (ar_headers_t *) xcalloc(1, sizeof(ar_headers_t)); | 72 | while (optind < argc) { |
85 | ar_entry = head; | 73 | ar_extract_list = add_from_archive_list(head, ar_extract_list, argv[optind]); |
86 | while (ar_entry->next != NULL) { | 74 | optind++; |
87 | if (strcmp(argv[optind], ar_entry->name) == 0) { | ||
88 | ar_headers_t *tmp; | ||
89 | tmp = (ar_headers_t *) xmalloc(sizeof(ar_headers_t)); | ||
90 | *tmp = *ar_extract_list; | ||
91 | *ar_extract_list = *ar_entry; | ||
92 | ar_extract_list->next = tmp; | ||
93 | break; | ||
94 | } | ||
95 | ar_entry=ar_entry->next; | ||
96 | } | 75 | } |
97 | } | 76 | } else { |
98 | |||
99 | /* if individual files not found extract all files */ | ||
100 | if (ar_extract_list->next==NULL) { | ||
101 | ar_extract_list = head; | 77 | ar_extract_list = head; |
102 | } | 78 | } |
103 | 79 | ||
104 | /* find files to extract or display */ | 80 | /* If there isnt even one possible entry then abort */ |
105 | while (ar_extract_list->next != NULL) { | 81 | if (ar_extract_list->name == NULL) { |
106 | if (funct & extract_to_file) { | 82 | error_msg_and_die("No files to extract"); |
107 | dst_file = wfopen(ar_extract_list->name, "w"); | 83 | } |
108 | } | 84 | |
109 | else if (funct & extract_to_stdout) { | 85 | fseek(src_stream, 0, SEEK_SET); |
110 | dst_file = stdout; | 86 | extract_archive(src_stream, stdout, ar_extract_list, extract_function, "./"); |
111 | } | 87 | |
112 | if ((funct & extract_to_file) || (funct & extract_to_stdout)) { | ||
113 | fseek(src_file, ar_extract_list->offset, SEEK_SET); | ||
114 | copy_file_chunk(src_file, dst_file, ar_extract_list->size); | ||
115 | } | ||
116 | if (funct & verbose) { | ||
117 | printf("%s %d/%d %8d %s ", mode_string(ar_extract_list->mode), | ||
118 | ar_extract_list->uid, ar_extract_list->gid, | ||
119 | (int) ar_extract_list->size, time_string(ar_extract_list->mtime)); | ||
120 | } | ||
121 | if ((funct & display) || (funct & verbose)){ | ||
122 | puts(ar_extract_list->name); | ||
123 | } | ||
124 | ar_extract_list = ar_extract_list->next; | ||
125 | } | ||
126 | return EXIT_SUCCESS; | 88 | return EXIT_SUCCESS; |
127 | } | 89 | } |
diff --git a/archival/ar.c b/archival/ar.c index 08cd5c501..7359f4910 100644 --- a/archival/ar.c +++ b/archival/ar.c | |||
@@ -30,36 +30,27 @@ | |||
30 | 30 | ||
31 | extern int ar_main(int argc, char **argv) | 31 | extern int ar_main(int argc, char **argv) |
32 | { | 32 | { |
33 | const int preserve_date = 1; /* preserve original dates */ | 33 | FILE *src_stream = NULL; |
34 | const int verbose = 2; /* be verbose */ | 34 | int extract_function = 0, opt = 0; |
35 | const int display = 4; /* display contents */ | 35 | file_headers_t *head; |
36 | const int extract_to_file = 8; /* extract contents of archive */ | 36 | file_headers_t *ar_extract_list = NULL; |
37 | const int extract_to_stdout = 16; /* extract to stdout */ | ||
38 | |||
39 | FILE *src_file = NULL, *dst_file = NULL; | ||
40 | int funct = 0, opt=0; | ||
41 | |||
42 | ar_headers_t *head, *ar_extract_list=NULL; | ||
43 | |||
44 | ar_extract_list = (ar_headers_t *) xcalloc(1, sizeof(ar_headers_t)); | ||
45 | head = (ar_headers_t *) xcalloc(1, sizeof(ar_headers_t)); | ||
46 | 37 | ||
47 | while ((opt = getopt(argc, argv, "ovtpx")) != -1) { | 38 | while ((opt = getopt(argc, argv, "ovtpx")) != -1) { |
48 | switch (opt) { | 39 | switch (opt) { |
49 | case 'o': | 40 | case 'o': |
50 | funct |= preserve_date; | 41 | extract_function |= extract_preserve_date; |
51 | break; | 42 | break; |
52 | case 'v': | 43 | case 'v': |
53 | funct |= verbose; | 44 | extract_function |= extract_verbose_list; |
54 | break; | 45 | break; |
55 | case 't': | 46 | case 't': |
56 | funct |= display; | 47 | extract_function |= extract_list; |
57 | break; | 48 | break; |
58 | case 'p': | 49 | case 'p': |
59 | funct |= extract_to_stdout; | 50 | extract_function |= extract_to_stdout; |
60 | break; | 51 | break; |
61 | case 'x': | 52 | case 'x': |
62 | funct |= extract_to_file; | 53 | extract_function |= extract_all_to_fs; |
63 | break; | 54 | break; |
64 | default: | 55 | default: |
65 | show_usage(); | 56 | show_usage(); |
@@ -71,57 +62,28 @@ extern int ar_main(int argc, char **argv) | |||
71 | show_usage(); | 62 | show_usage(); |
72 | } | 63 | } |
73 | 64 | ||
74 | if ( (src_file = wfopen(argv[optind], "r")) < 0) { | 65 | src_stream = xfopen(argv[optind++], "r"); |
75 | error_msg_and_die("Cannot read %s", argv[optind]); | 66 | head = get_ar_headers(src_stream); |
76 | } | ||
77 | 67 | ||
78 | optind++; | ||
79 | head = get_ar_headers(src_file); | ||
80 | /* find files to extract or display */ | 68 | /* find files to extract or display */ |
81 | /* search through argv and build extract list */ | 69 | /* search through argv and build extract list */ |
82 | for (;optind < argc; optind++) { | 70 | ar_extract_list = (file_headers_t *) xcalloc(1, sizeof(file_headers_t)); |
83 | ar_headers_t *ar_entry; | 71 | if (optind < argc) { |
84 | ar_entry = (ar_headers_t *) xcalloc(1, sizeof(ar_headers_t)); | 72 | while (optind < argc) { |
85 | ar_entry = head; | 73 | ar_extract_list = add_from_archive_list(head, ar_extract_list, argv[optind]); |
86 | while (ar_entry->next != NULL) { | 74 | optind++; |
87 | if (strcmp(argv[optind], ar_entry->name) == 0) { | ||
88 | ar_headers_t *tmp; | ||
89 | tmp = (ar_headers_t *) xmalloc(sizeof(ar_headers_t)); | ||
90 | *tmp = *ar_extract_list; | ||
91 | *ar_extract_list = *ar_entry; | ||
92 | ar_extract_list->next = tmp; | ||
93 | break; | ||
94 | } | ||
95 | ar_entry=ar_entry->next; | ||
96 | } | 75 | } |
97 | } | 76 | } else { |
98 | |||
99 | /* if individual files not found extract all files */ | ||
100 | if (ar_extract_list->next==NULL) { | ||
101 | ar_extract_list = head; | 77 | ar_extract_list = head; |
102 | } | 78 | } |
103 | 79 | ||
104 | /* find files to extract or display */ | 80 | /* If there isnt even one possible entry then abort */ |
105 | while (ar_extract_list->next != NULL) { | 81 | if (ar_extract_list->name == NULL) { |
106 | if (funct & extract_to_file) { | 82 | error_msg_and_die("No files to extract"); |
107 | dst_file = wfopen(ar_extract_list->name, "w"); | 83 | } |
108 | } | 84 | |
109 | else if (funct & extract_to_stdout) { | 85 | fseek(src_stream, 0, SEEK_SET); |
110 | dst_file = stdout; | 86 | extract_archive(src_stream, stdout, ar_extract_list, extract_function, "./"); |
111 | } | 87 | |
112 | if ((funct & extract_to_file) || (funct & extract_to_stdout)) { | ||
113 | fseek(src_file, ar_extract_list->offset, SEEK_SET); | ||
114 | copy_file_chunk(src_file, dst_file, ar_extract_list->size); | ||
115 | } | ||
116 | if (funct & verbose) { | ||
117 | printf("%s %d/%d %8d %s ", mode_string(ar_extract_list->mode), | ||
118 | ar_extract_list->uid, ar_extract_list->gid, | ||
119 | (int) ar_extract_list->size, time_string(ar_extract_list->mtime)); | ||
120 | } | ||
121 | if ((funct & display) || (funct & verbose)){ | ||
122 | puts(ar_extract_list->name); | ||
123 | } | ||
124 | ar_extract_list = ar_extract_list->next; | ||
125 | } | ||
126 | return EXIT_SUCCESS; | 88 | return EXIT_SUCCESS; |
127 | } | 89 | } |
diff --git a/archival/dpkg.c b/archival/dpkg.c index 0010df537..4224672ec 100644 --- a/archival/dpkg.c +++ b/archival/dpkg.c | |||
@@ -13,7 +13,6 @@ | |||
13 | 13 | ||
14 | #include "busybox.h" | 14 | #include "busybox.h" |
15 | 15 | ||
16 | |||
17 | #define DEPENDSMAX 64 /* maximum number of depends we can handle */ | 16 | #define DEPENDSMAX 64 /* maximum number of depends we can handle */ |
18 | 17 | ||
19 | /* Should we do full dependency checking? */ | 18 | /* Should we do full dependency checking? */ |
@@ -487,7 +486,7 @@ static void *status_read(void) | |||
487 | return(NULL); | 486 | return(NULL); |
488 | } | 487 | } |
489 | 488 | ||
490 | while ( (package_control_buffer = read_text_file_to_buffer(f)) != NULL) { | 489 | while ( (package_control_buffer = fgets_str(f, "\n\n")) != NULL) { |
491 | m = (package_t *)xcalloc(1, sizeof(package_t)); | 490 | m = (package_t *)xcalloc(1, sizeof(package_t)); |
492 | fill_package_struct(m, package_control_buffer); | 491 | fill_package_struct(m, package_control_buffer); |
493 | if (m->package) { | 492 | if (m->package) { |
@@ -650,24 +649,26 @@ static int dpkg_doconfigure(package_t *pkg) | |||
650 | 649 | ||
651 | static int dpkg_dounpack(package_t *pkg) | 650 | static int dpkg_dounpack(package_t *pkg) |
652 | { | 651 | { |
653 | int r = 0; | 652 | FILE *out_stream; |
653 | char *info_prefix; | ||
654 | int status = TRUE; | 654 | int status = TRUE; |
655 | char *lst_path; | 655 | int r = 0; |
656 | 656 | ||
657 | DPRINTF("Unpacking %s\n", pkg->package); | 657 | DPRINTF("Unpacking %s\n", pkg->package); |
658 | 658 | ||
659 | /* extract the data file */ | 659 | /* extract the data file */ |
660 | deb_extract(pkg->filename, extract_extract, "/", NULL); | 660 | deb_extract(pkg->filename, stdout, (extract_data_tar_gz | extract_all_to_fs), "/", NULL); |
661 | 661 | ||
662 | /* extract the control files */ | 662 | /* extract the control files */ |
663 | deb_extract(pkg->filename, extract_control, infodir, pkg->package); | 663 | info_prefix = (char *) malloc(strlen(pkg->package) + strlen(infodir) + 2 + 5 + 1); |
664 | sprintf(info_prefix, "%s/%s.", infodir, pkg->package); | ||
665 | deb_extract(pkg->package, stdout, (extract_control_tar_gz | extract_all_to_fs), info_prefix, NULL); | ||
664 | 666 | ||
665 | /* Create the list file */ | 667 | /* Create the list file */ |
666 | lst_path = xmalloc(strlen(infodir) + strlen(pkg->package) + 6); | 668 | strcat(info_prefix, "list"); |
667 | strcpy(lst_path, infodir); | 669 | out_stream = wfopen(info_prefix, "w"); |
668 | strcat(lst_path, pkg->package); | 670 | deb_extract(pkg->package, out_stream, (extract_data_tar_gz | extract_list), NULL, NULL); |
669 | strcat(lst_path, ".list"); | 671 | fclose(out_stream); |
670 | deb_extract(pkg->filename, extract_contents_to_file, lst_path, NULL); | ||
671 | 672 | ||
672 | pkg->state_want = state_want_install; | 673 | pkg->state_want = state_want_install; |
673 | pkg->state_flag = state_flag_ok; | 674 | pkg->state_flag = state_flag_ok; |
@@ -692,7 +693,7 @@ static int dpkg_read_control(package_t *pkg) | |||
692 | if ((pkg_file = wfopen(pkg->filename, "r")) == NULL) { | 693 | if ((pkg_file = wfopen(pkg->filename, "r")) == NULL) { |
693 | return EXIT_FAILURE; | 694 | return EXIT_FAILURE; |
694 | } | 695 | } |
695 | control_buffer = deb_extract(pkg->filename, extract_field, NULL, NULL); | 696 | control_buffer = deb_extract(pkg->filename, stdout, (extract_control_tar_gz | extract_one_to_buffer), NULL, "./control"); |
696 | fill_package_struct(pkg, control_buffer); | 697 | fill_package_struct(pkg, control_buffer); |
697 | return EXIT_SUCCESS; | 698 | return EXIT_SUCCESS; |
698 | } | 699 | } |
diff --git a/archival/dpkg_deb.c b/archival/dpkg_deb.c index 17b5476d0..400f2385a 100644 --- a/archival/dpkg_deb.c +++ b/archival/dpkg_deb.c | |||
@@ -21,33 +21,54 @@ | |||
21 | 21 | ||
22 | extern int dpkg_deb_main(int argc, char **argv) | 22 | extern int dpkg_deb_main(int argc, char **argv) |
23 | { | 23 | { |
24 | char *argument = NULL; | 24 | char *prefix = NULL; |
25 | char *filename = NULL; | ||
25 | char *output_buffer = NULL; | 26 | char *output_buffer = NULL; |
26 | int opt = 0; | 27 | int opt = 0; |
27 | int optflag = 0; | 28 | int arg_type = 0; |
29 | int deb_extract_funct = 0; | ||
28 | 30 | ||
31 | const int arg_type_prefix = 1; | ||
32 | const int arg_type_field = 2; | ||
33 | const int arg_type_filename = 4; | ||
34 | // const int arg_type_un_ar_gz = 8; | ||
35 | |||
29 | while ((opt = getopt(argc, argv, "ceftXxI")) != -1) { | 36 | while ((opt = getopt(argc, argv, "ceftXxI")) != -1) { |
30 | switch (opt) { | 37 | switch (opt) { |
31 | case 'c': | 38 | case 'c': |
32 | optflag |= extract_contents; | 39 | deb_extract_funct |= extract_data_tar_gz; |
40 | deb_extract_funct |= extract_verbose_list; | ||
33 | break; | 41 | break; |
34 | case 'e': | 42 | case 'e': |
35 | optflag |= extract_control; | 43 | arg_type = arg_type_prefix; |
44 | deb_extract_funct |= extract_control_tar_gz; | ||
45 | deb_extract_funct |= extract_all_to_fs; | ||
36 | break; | 46 | break; |
37 | case 'f': | 47 | case 'f': |
38 | optflag |= extract_field; | 48 | arg_type = arg_type_field; |
49 | deb_extract_funct |= extract_control_tar_gz; | ||
50 | deb_extract_funct |= extract_one_to_buffer; | ||
51 | filename = xstrdup("./control"); | ||
39 | break; | 52 | break; |
40 | case 't': | 53 | case 't': /* --fsys-tarfile, i just made up this short name */ |
41 | optflag |= extract_fsys_tarfile; | 54 | /* Integrate the functionality needed with some code from ar.c */ |
55 | error_msg_and_die("Option disabled"); | ||
56 | // arg_type = arg_type_un_ar_gz; | ||
42 | break; | 57 | break; |
43 | case 'X': | 58 | case 'X': |
44 | optflag |= extract_verbose_extract; | 59 | arg_type = arg_type_prefix; |
45 | break; | 60 | deb_extract_funct |= extract_data_tar_gz; |
61 | deb_extract_funct |= extract_all_to_fs; | ||
62 | deb_extract_funct |= extract_list; | ||
46 | case 'x': | 63 | case 'x': |
47 | optflag |= extract_extract; | 64 | arg_type = arg_type_prefix; |
65 | deb_extract_funct |= extract_data_tar_gz; | ||
66 | deb_extract_funct |= extract_all_to_fs; | ||
48 | break; | 67 | break; |
49 | case 'I': | 68 | case 'I': |
50 | optflag |= extract_info; | 69 | arg_type = arg_type_filename; |
70 | deb_extract_funct |= extract_control_tar_gz; | ||
71 | deb_extract_funct |= extract_one_to_buffer; | ||
51 | break; | 72 | break; |
52 | default: | 73 | default: |
53 | show_usage(); | 74 | show_usage(); |
@@ -58,48 +79,42 @@ extern int dpkg_deb_main(int argc, char **argv) | |||
58 | show_usage(); | 79 | show_usage(); |
59 | } | 80 | } |
60 | 81 | ||
61 | switch (optflag) { | 82 | /* Workout where to extract the files */ |
62 | case (extract_control): | 83 | if (arg_type == arg_type_prefix) { |
63 | case (extract_extract): | 84 | /* argument is a dir name */ |
64 | case (extract_verbose_extract): | 85 | if ((optind + 1) == argc ) { |
65 | /* argument is a dir name */ | 86 | prefix = xstrdup("./DEBIAN/"); |
66 | if ( (optind + 1) == argc ) { | 87 | } else { |
67 | argument = xstrdup("DEBIAN"); | 88 | prefix = (char *) xmalloc(strlen(argv[optind + 1]) + 2); |
68 | } else { | 89 | strcpy(prefix, argv[optind + 1]); |
69 | argument = xstrdup(argv[optind + 1]); | 90 | /* Make sure the directory has a trailing '/' */ |
70 | } | 91 | if (last_char_is(prefix, '/') == NULL) { |
71 | break; | 92 | strcat(prefix, "/"); |
72 | case (extract_field): | ||
73 | /* argument is a control field name */ | ||
74 | if ((optind + 1) != argc) { | ||
75 | argument = xstrdup(argv[optind + 1]); | ||
76 | } | ||
77 | break; | ||
78 | case (extract_info): | ||
79 | /* argument is a control field name */ | ||
80 | if ((optind + 1) != argc) { | ||
81 | argument = xstrdup(argv[optind + 1]); | ||
82 | break; | ||
83 | } else { | ||
84 | error_msg("-I currently requires a filename to be specifies"); | ||
85 | return(EXIT_FAILURE); | ||
86 | } | 93 | } |
87 | /* argument is a filename */ | 94 | } |
88 | default: | ||
89 | } | 95 | } |
90 | 96 | ||
91 | output_buffer = deb_extract(argv[optind], optflag, argument, NULL); | 97 | if (arg_type == arg_type_filename) { |
98 | if ((optind + 1) != argc) { | ||
99 | filename = xstrdup(argv[optind + 1]); | ||
100 | } else { | ||
101 | error_msg_and_die("-I currently requires a filename to be specified"); | ||
102 | } | ||
103 | } | ||
92 | 104 | ||
93 | if (optflag & extract_field) { | 105 | output_buffer = deb_extract(argv[optind], stdout, deb_extract_funct, prefix, filename); |
106 | |||
107 | if ((arg_type == arg_type_filename) && (output_buffer != NULL)) { | ||
108 | puts(output_buffer); | ||
109 | } | ||
110 | else if (arg_type == arg_type_field) { | ||
94 | char *field = NULL; | 111 | char *field = NULL; |
95 | int field_length = 0; | ||
96 | int field_start = 0; | 112 | int field_start = 0; |
97 | 113 | ||
98 | while ((field = read_package_field(&output_buffer[field_start])) != NULL) { | 114 | while ((field = read_package_field(&output_buffer[field_start])) != NULL) { |
99 | field_length = strlen(field); | 115 | field_start += (strlen(field) + 1); |
100 | field_start += (field_length + 1); | 116 | if (strstr(field, argv[optind + 1]) == field) { |
101 | if (strstr(field, argument) == field) { | 117 | puts(field + strlen(argv[optind + 1]) + 2); |
102 | puts(field + strlen(argument) + 2); | ||
103 | } | 118 | } |
104 | free(field); | 119 | free(field); |
105 | } | 120 | } |
@@ -13,7 +13,6 @@ | |||
13 | 13 | ||
14 | #include "busybox.h" | 14 | #include "busybox.h" |
15 | 15 | ||
16 | |||
17 | #define DEPENDSMAX 64 /* maximum number of depends we can handle */ | 16 | #define DEPENDSMAX 64 /* maximum number of depends we can handle */ |
18 | 17 | ||
19 | /* Should we do full dependency checking? */ | 18 | /* Should we do full dependency checking? */ |
@@ -487,7 +486,7 @@ static void *status_read(void) | |||
487 | return(NULL); | 486 | return(NULL); |
488 | } | 487 | } |
489 | 488 | ||
490 | while ( (package_control_buffer = read_text_file_to_buffer(f)) != NULL) { | 489 | while ( (package_control_buffer = fgets_str(f, "\n\n")) != NULL) { |
491 | m = (package_t *)xcalloc(1, sizeof(package_t)); | 490 | m = (package_t *)xcalloc(1, sizeof(package_t)); |
492 | fill_package_struct(m, package_control_buffer); | 491 | fill_package_struct(m, package_control_buffer); |
493 | if (m->package) { | 492 | if (m->package) { |
@@ -650,24 +649,26 @@ static int dpkg_doconfigure(package_t *pkg) | |||
650 | 649 | ||
651 | static int dpkg_dounpack(package_t *pkg) | 650 | static int dpkg_dounpack(package_t *pkg) |
652 | { | 651 | { |
653 | int r = 0; | 652 | FILE *out_stream; |
653 | char *info_prefix; | ||
654 | int status = TRUE; | 654 | int status = TRUE; |
655 | char *lst_path; | 655 | int r = 0; |
656 | 656 | ||
657 | DPRINTF("Unpacking %s\n", pkg->package); | 657 | DPRINTF("Unpacking %s\n", pkg->package); |
658 | 658 | ||
659 | /* extract the data file */ | 659 | /* extract the data file */ |
660 | deb_extract(pkg->filename, extract_extract, "/", NULL); | 660 | deb_extract(pkg->filename, stdout, (extract_data_tar_gz | extract_all_to_fs), "/", NULL); |
661 | 661 | ||
662 | /* extract the control files */ | 662 | /* extract the control files */ |
663 | deb_extract(pkg->filename, extract_control, infodir, pkg->package); | 663 | info_prefix = (char *) malloc(strlen(pkg->package) + strlen(infodir) + 2 + 5 + 1); |
664 | sprintf(info_prefix, "%s/%s.", infodir, pkg->package); | ||
665 | deb_extract(pkg->package, stdout, (extract_control_tar_gz | extract_all_to_fs), info_prefix, NULL); | ||
664 | 666 | ||
665 | /* Create the list file */ | 667 | /* Create the list file */ |
666 | lst_path = xmalloc(strlen(infodir) + strlen(pkg->package) + 6); | 668 | strcat(info_prefix, "list"); |
667 | strcpy(lst_path, infodir); | 669 | out_stream = wfopen(info_prefix, "w"); |
668 | strcat(lst_path, pkg->package); | 670 | deb_extract(pkg->package, out_stream, (extract_data_tar_gz | extract_list), NULL, NULL); |
669 | strcat(lst_path, ".list"); | 671 | fclose(out_stream); |
670 | deb_extract(pkg->filename, extract_contents_to_file, lst_path, NULL); | ||
671 | 672 | ||
672 | pkg->state_want = state_want_install; | 673 | pkg->state_want = state_want_install; |
673 | pkg->state_flag = state_flag_ok; | 674 | pkg->state_flag = state_flag_ok; |
@@ -692,7 +693,7 @@ static int dpkg_read_control(package_t *pkg) | |||
692 | if ((pkg_file = wfopen(pkg->filename, "r")) == NULL) { | 693 | if ((pkg_file = wfopen(pkg->filename, "r")) == NULL) { |
693 | return EXIT_FAILURE; | 694 | return EXIT_FAILURE; |
694 | } | 695 | } |
695 | control_buffer = deb_extract(pkg->filename, extract_field, NULL, NULL); | 696 | control_buffer = deb_extract(pkg->filename, stdout, (extract_control_tar_gz | extract_one_to_buffer), NULL, "./control"); |
696 | fill_package_struct(pkg, control_buffer); | 697 | fill_package_struct(pkg, control_buffer); |
697 | return EXIT_SUCCESS; | 698 | return EXIT_SUCCESS; |
698 | } | 699 | } |
diff --git a/dpkg_deb.c b/dpkg_deb.c index 17b5476d0..400f2385a 100644 --- a/dpkg_deb.c +++ b/dpkg_deb.c | |||
@@ -21,33 +21,54 @@ | |||
21 | 21 | ||
22 | extern int dpkg_deb_main(int argc, char **argv) | 22 | extern int dpkg_deb_main(int argc, char **argv) |
23 | { | 23 | { |
24 | char *argument = NULL; | 24 | char *prefix = NULL; |
25 | char *filename = NULL; | ||
25 | char *output_buffer = NULL; | 26 | char *output_buffer = NULL; |
26 | int opt = 0; | 27 | int opt = 0; |
27 | int optflag = 0; | 28 | int arg_type = 0; |
29 | int deb_extract_funct = 0; | ||
28 | 30 | ||
31 | const int arg_type_prefix = 1; | ||
32 | const int arg_type_field = 2; | ||
33 | const int arg_type_filename = 4; | ||
34 | // const int arg_type_un_ar_gz = 8; | ||
35 | |||
29 | while ((opt = getopt(argc, argv, "ceftXxI")) != -1) { | 36 | while ((opt = getopt(argc, argv, "ceftXxI")) != -1) { |
30 | switch (opt) { | 37 | switch (opt) { |
31 | case 'c': | 38 | case 'c': |
32 | optflag |= extract_contents; | 39 | deb_extract_funct |= extract_data_tar_gz; |
40 | deb_extract_funct |= extract_verbose_list; | ||
33 | break; | 41 | break; |
34 | case 'e': | 42 | case 'e': |
35 | optflag |= extract_control; | 43 | arg_type = arg_type_prefix; |
44 | deb_extract_funct |= extract_control_tar_gz; | ||
45 | deb_extract_funct |= extract_all_to_fs; | ||
36 | break; | 46 | break; |
37 | case 'f': | 47 | case 'f': |
38 | optflag |= extract_field; | 48 | arg_type = arg_type_field; |
49 | deb_extract_funct |= extract_control_tar_gz; | ||
50 | deb_extract_funct |= extract_one_to_buffer; | ||
51 | filename = xstrdup("./control"); | ||
39 | break; | 52 | break; |
40 | case 't': | 53 | case 't': /* --fsys-tarfile, i just made up this short name */ |
41 | optflag |= extract_fsys_tarfile; | 54 | /* Integrate the functionality needed with some code from ar.c */ |
55 | error_msg_and_die("Option disabled"); | ||
56 | // arg_type = arg_type_un_ar_gz; | ||
42 | break; | 57 | break; |
43 | case 'X': | 58 | case 'X': |
44 | optflag |= extract_verbose_extract; | 59 | arg_type = arg_type_prefix; |
45 | break; | 60 | deb_extract_funct |= extract_data_tar_gz; |
61 | deb_extract_funct |= extract_all_to_fs; | ||
62 | deb_extract_funct |= extract_list; | ||
46 | case 'x': | 63 | case 'x': |
47 | optflag |= extract_extract; | 64 | arg_type = arg_type_prefix; |
65 | deb_extract_funct |= extract_data_tar_gz; | ||
66 | deb_extract_funct |= extract_all_to_fs; | ||
48 | break; | 67 | break; |
49 | case 'I': | 68 | case 'I': |
50 | optflag |= extract_info; | 69 | arg_type = arg_type_filename; |
70 | deb_extract_funct |= extract_control_tar_gz; | ||
71 | deb_extract_funct |= extract_one_to_buffer; | ||
51 | break; | 72 | break; |
52 | default: | 73 | default: |
53 | show_usage(); | 74 | show_usage(); |
@@ -58,48 +79,42 @@ extern int dpkg_deb_main(int argc, char **argv) | |||
58 | show_usage(); | 79 | show_usage(); |
59 | } | 80 | } |
60 | 81 | ||
61 | switch (optflag) { | 82 | /* Workout where to extract the files */ |
62 | case (extract_control): | 83 | if (arg_type == arg_type_prefix) { |
63 | case (extract_extract): | 84 | /* argument is a dir name */ |
64 | case (extract_verbose_extract): | 85 | if ((optind + 1) == argc ) { |
65 | /* argument is a dir name */ | 86 | prefix = xstrdup("./DEBIAN/"); |
66 | if ( (optind + 1) == argc ) { | 87 | } else { |
67 | argument = xstrdup("DEBIAN"); | 88 | prefix = (char *) xmalloc(strlen(argv[optind + 1]) + 2); |
68 | } else { | 89 | strcpy(prefix, argv[optind + 1]); |
69 | argument = xstrdup(argv[optind + 1]); | 90 | /* Make sure the directory has a trailing '/' */ |
70 | } | 91 | if (last_char_is(prefix, '/') == NULL) { |
71 | break; | 92 | strcat(prefix, "/"); |
72 | case (extract_field): | ||
73 | /* argument is a control field name */ | ||
74 | if ((optind + 1) != argc) { | ||
75 | argument = xstrdup(argv[optind + 1]); | ||
76 | } | ||
77 | break; | ||
78 | case (extract_info): | ||
79 | /* argument is a control field name */ | ||
80 | if ((optind + 1) != argc) { | ||
81 | argument = xstrdup(argv[optind + 1]); | ||
82 | break; | ||
83 | } else { | ||
84 | error_msg("-I currently requires a filename to be specifies"); | ||
85 | return(EXIT_FAILURE); | ||
86 | } | 93 | } |
87 | /* argument is a filename */ | 94 | } |
88 | default: | ||
89 | } | 95 | } |
90 | 96 | ||
91 | output_buffer = deb_extract(argv[optind], optflag, argument, NULL); | 97 | if (arg_type == arg_type_filename) { |
98 | if ((optind + 1) != argc) { | ||
99 | filename = xstrdup(argv[optind + 1]); | ||
100 | } else { | ||
101 | error_msg_and_die("-I currently requires a filename to be specified"); | ||
102 | } | ||
103 | } | ||
92 | 104 | ||
93 | if (optflag & extract_field) { | 105 | output_buffer = deb_extract(argv[optind], stdout, deb_extract_funct, prefix, filename); |
106 | |||
107 | if ((arg_type == arg_type_filename) && (output_buffer != NULL)) { | ||
108 | puts(output_buffer); | ||
109 | } | ||
110 | else if (arg_type == arg_type_field) { | ||
94 | char *field = NULL; | 111 | char *field = NULL; |
95 | int field_length = 0; | ||
96 | int field_start = 0; | 112 | int field_start = 0; |
97 | 113 | ||
98 | while ((field = read_package_field(&output_buffer[field_start])) != NULL) { | 114 | while ((field = read_package_field(&output_buffer[field_start])) != NULL) { |
99 | field_length = strlen(field); | 115 | field_start += (strlen(field) + 1); |
100 | field_start += (field_length + 1); | 116 | if (strstr(field, argv[optind + 1]) == field) { |
101 | if (strstr(field, argument) == field) { | 117 | puts(field + strlen(argv[optind + 1]) + 2); |
102 | puts(field + strlen(argument) + 2); | ||
103 | } | 118 | } |
104 | free(field); | 119 | free(field); |
105 | } | 120 | } |
diff --git a/include/libbb.h b/include/libbb.h index f99d25780..f24a38109 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
@@ -213,36 +213,41 @@ char *xreadlink(const char *path); | |||
213 | char *concat_path_file(const char *path, const char *filename); | 213 | char *concat_path_file(const char *path, const char *filename); |
214 | char *last_char_is(const char *s, int c); | 214 | char *last_char_is(const char *s, int c); |
215 | 215 | ||
216 | typedef struct ar_headers_s { | 216 | typedef struct file_headers_s { |
217 | char *name; | 217 | char *name; |
218 | char *link_name; | ||
218 | off_t size; | 219 | off_t size; |
219 | uid_t uid; | 220 | uid_t uid; |
220 | gid_t gid; | 221 | gid_t gid; |
221 | mode_t mode; | 222 | mode_t mode; |
222 | time_t mtime; | 223 | time_t mtime; |
223 | off_t offset; | 224 | off_t offset; |
224 | struct ar_headers_s *next; | 225 | dev_t device; |
225 | } ar_headers_t; | 226 | struct file_headers_s *next; |
226 | extern ar_headers_t *get_ar_headers(FILE *in_file); | 227 | } file_headers_t; |
227 | extern int seek_ared_file(FILE *in_file, ar_headers_t *headers, const char *tar_gz_file); | 228 | file_headers_t *get_ar_headers(FILE *in_file); |
228 | 229 | file_headers_t *get_tar_headers(FILE *tar_stream); | |
229 | typedef enum extract_function_e { | 230 | file_headers_t *get_tar_gz_headers(FILE *compressed_stream); |
230 | extract_contents = 1, | 231 | file_headers_t *append_archive_list(file_headers_t *head, file_headers_t *tail_entry); |
231 | extract_control = 2, | 232 | file_headers_t *add_from_archive_list(file_headers_t *master_list, file_headers_t *new_list, const char *name); |
232 | extract_info = 4, | 233 | |
233 | extract_extract = 8, | 234 | enum extract_functions_e { |
234 | extract_verbose_extract = 16, | 235 | extract_verbose_list = 1, |
235 | extract_list = 32, | 236 | extract_list = 2, |
236 | extract_fsys_tarfile = 64, | 237 | extract_one_to_buffer = 4, |
237 | extract_field = 128, | 238 | extract_to_stdout = 8, |
238 | extract_contents_to_file = 256 | 239 | extract_all_to_fs = 16, |
239 | } extract_function_t; | 240 | extract_preserve_date = 32, |
240 | extern char *deb_extract(const char *package_filename, int function, | 241 | extract_data_tar_gz = 64, |
241 | const char *argument, const char *argument2); | 242 | extract_control_tar_gz = 128, |
242 | extern char *untar(FILE *src_tar_file, FILE *output, int untar_function, | 243 | extract_unzip_only = 256 |
243 | const char *argument, const char *file_prefix); | 244 | }; |
244 | extern char *read_text_file_to_buffer(FILE *src_file); | 245 | char *extract_archive(FILE *src_stream, FILE *out_stream, file_headers_t *extract_headers, int function, const char *prefix); |
245 | extern char *read_package_field(const char *package_buffer); | 246 | char *deb_extract(const char *package_filename, FILE *out_stream, const int function, |
247 | const char *prefix, const char *filename); | ||
248 | char *read_package_field(const char *package_buffer); | ||
249 | int seek_sub_file(FILE *in_file, file_headers_t *headers, const char *tar_gz_file); | ||
250 | char *fgets_str(FILE *file, const char *terminating_string); | ||
246 | 251 | ||
247 | extern int unzip(FILE *l_in_file, FILE *l_out_file); | 252 | extern int unzip(FILE *l_in_file, FILE *l_out_file); |
248 | extern void gz_close(int gunzip_pid); | 253 | extern void gz_close(int gunzip_pid); |
diff --git a/libbb/deb_extract.c b/libbb/deb_extract.c index 36cebfa51..f64193970 100644 --- a/libbb/deb_extract.c +++ b/libbb/deb_extract.c | |||
@@ -27,71 +27,97 @@ | |||
27 | #include <unistd.h> | 27 | #include <unistd.h> |
28 | #include <stdlib.h> | 28 | #include <stdlib.h> |
29 | #include <string.h> | 29 | #include <string.h> |
30 | #include <signal.h> | ||
31 | #include "libbb.h" | 30 | #include "libbb.h" |
32 | 31 | ||
32 | int seek_sub_file(FILE *in_file, file_headers_t *headers, const char *tar_gz_file) | ||
33 | { | ||
34 | /* find the headers for the specified .tar.gz file */ | ||
35 | while (headers != NULL) { | ||
36 | if (strcmp(headers->name, tar_gz_file) == 0) { | ||
37 | fseek(in_file, headers->offset, SEEK_SET); | ||
38 | return(EXIT_SUCCESS); | ||
39 | } | ||
40 | headers = headers->next; | ||
41 | } | ||
42 | |||
43 | return(EXIT_FAILURE); | ||
44 | } | ||
45 | |||
33 | /* | 46 | /* |
34 | * The contents of argument depend on the value of function. | 47 | * The contents of argument depend on the value of function. |
35 | * It is either a dir name or a control file or field name(see dpkg_deb.c) | 48 | * It is either a dir name or a control file or field name(see dpkg_deb.c) |
36 | */ | 49 | */ |
37 | extern char *deb_extract(const char *package_filename, const int function, const char *argument, const char *argument2) | 50 | char *deb_extract(const char *package_filename, FILE *out_stream, const int extract_function, |
51 | const char *prefix, const char *filename) | ||
38 | { | 52 | { |
53 | FILE *deb_stream, *uncompressed_stream; | ||
54 | file_headers_t *ar_headers = NULL; | ||
55 | file_headers_t *tar_headers = NULL; | ||
56 | file_headers_t *list_ptr; | ||
57 | file_headers_t *deb_extract_list = (file_headers_t *) calloc(1, sizeof(file_headers_t)); | ||
39 | 58 | ||
40 | FILE *deb_file, *uncompressed_file; | ||
41 | ar_headers_t *headers = NULL; | ||
42 | char *ared_file = NULL; | 59 | char *ared_file = NULL; |
43 | char *output_buffer = NULL; | 60 | char *output_buffer = NULL; |
44 | int gunzip_pid; | 61 | int gunzip_pid; |
45 | 62 | ||
46 | switch (function) { | 63 | if (extract_function & extract_control_tar_gz) { |
47 | case (extract_info): | 64 | ared_file = xstrdup("control.tar.gz"); |
48 | case (extract_control): | 65 | } |
49 | case (extract_field): | 66 | else if (extract_function & extract_data_tar_gz) { |
50 | ared_file = xstrdup("control.tar.gz"); | 67 | ared_file = xstrdup("data.tar.gz"); |
51 | break; | ||
52 | default: | ||
53 | ared_file = xstrdup("data.tar.gz"); | ||
54 | break; | ||
55 | } | 68 | } |
56 | 69 | ||
57 | /* open the debian package to be worked on */ | 70 | /* open the debian package to be worked on */ |
58 | deb_file = wfopen(package_filename, "r"); | 71 | deb_stream = wfopen(package_filename, "r"); |
59 | 72 | ||
60 | headers = (ar_headers_t *) xmalloc(sizeof(ar_headers_t)); | 73 | ar_headers = (file_headers_t *) xmalloc(sizeof(file_headers_t)); |
61 | 74 | ||
62 | /* get a linked list of all ar entries */ | 75 | /* get a linked list of all ar entries */ |
63 | if ((headers = get_ar_headers(deb_file)) == NULL) { | 76 | ar_headers = get_ar_headers(deb_stream); |
77 | if (ar_headers == NULL) { | ||
64 | error_msg("Couldnt get ar headers\n"); | 78 | error_msg("Couldnt get ar headers\n"); |
65 | return(NULL); | 79 | return(NULL); |
66 | } | 80 | } |
67 | 81 | ||
68 | /* seek to the start of the .tar.gz file within the ar file*/ | 82 | /* seek to the start of the .tar.gz file within the ar file*/ |
69 | if (seek_ared_file(deb_file, headers, ared_file) == EXIT_FAILURE) { | 83 | fseek(deb_stream, 0, SEEK_SET); |
70 | error_msg("Couldnt seek to ar file"); | 84 | if (seek_sub_file(deb_stream, ar_headers, ared_file) == EXIT_FAILURE) { |
85 | error_msg("Couldnt seek to file %s", ared_file); | ||
71 | } | 86 | } |
72 | 87 | ||
73 | /* open a stream of decompressed data */ | 88 | /* get a linked list of all tar entries */ |
74 | uncompressed_file = fdopen(gz_open(deb_file, &gunzip_pid), "r"); | 89 | tar_headers = get_tar_gz_headers(deb_stream); |
75 | 90 | if (tar_headers == NULL) { | |
76 | if (function & extract_fsys_tarfile) { | 91 | error_msg("Couldnt get tar headers\n"); |
77 | copy_file_chunk(uncompressed_file, stdout, -1); | 92 | return(NULL); |
78 | } else { | 93 | } |
79 | FILE *output; | ||
80 | 94 | ||
81 | if (function & extract_contents_to_file) { | 95 | if (extract_function & extract_one_to_buffer) { |
82 | output = wfopen(argument, "w"); | 96 | list_ptr = tar_headers; |
83 | } else { | 97 | while (list_ptr != NULL) { |
84 | output = stdout; | 98 | if (strcmp(filename, list_ptr->name) == 0) { |
99 | deb_extract_list = append_archive_list(deb_extract_list, list_ptr); | ||
100 | break; | ||
101 | } | ||
102 | list_ptr = list_ptr->next; | ||
85 | } | 103 | } |
104 | } else { | ||
105 | deb_extract_list = tar_headers; | ||
106 | } | ||
86 | 107 | ||
87 | output_buffer = untar(uncompressed_file, output, function, argument, argument2); | 108 | /* seek to the start of the .tar.gz file within the ar file*/ |
88 | if (output != stdout) { | 109 | if (seek_sub_file(deb_stream, ar_headers, ared_file) == EXIT_FAILURE) { |
89 | fclose(output); | 110 | error_msg("Couldnt seek to ar file"); |
90 | } | ||
91 | } | 111 | } |
112 | |||
113 | /* open a stream of decompressed data */ | ||
114 | uncompressed_stream = fdopen(gz_open(deb_stream, &gunzip_pid), "r"); | ||
115 | |||
116 | output_buffer = extract_archive(uncompressed_stream, out_stream, deb_extract_list, extract_function, prefix); | ||
117 | |||
92 | gz_close(gunzip_pid); | 118 | gz_close(gunzip_pid); |
93 | fclose(deb_file); | 119 | fclose(deb_stream); |
94 | fclose(uncompressed_file); | 120 | fclose(uncompressed_stream); |
95 | free(ared_file); | 121 | free(ared_file); |
96 | 122 | ||
97 | return(output_buffer); | 123 | return(output_buffer); |
diff --git a/libbb/get_ar_headers.c b/libbb/get_ar_headers.c index 151caafe1..414498b4f 100644 --- a/libbb/get_ar_headers.c +++ b/libbb/get_ar_headers.c | |||
@@ -30,7 +30,7 @@ | |||
30 | #include <unistd.h> | 30 | #include <unistd.h> |
31 | #include "libbb.h" | 31 | #include "libbb.h" |
32 | 32 | ||
33 | extern ar_headers_t *get_ar_headers(FILE *in_file) | 33 | file_headers_t *get_ar_headers(FILE *in_file) |
34 | { | 34 | { |
35 | typedef struct raw_ar_header_s { /* Byte Offset */ | 35 | typedef struct raw_ar_header_s { /* Byte Offset */ |
36 | char name[16]; /* 0-15 */ | 36 | char name[16]; /* 0-15 */ |
@@ -44,7 +44,7 @@ extern ar_headers_t *get_ar_headers(FILE *in_file) | |||
44 | 44 | ||
45 | raw_ar_header_t raw_ar_header; | 45 | raw_ar_header_t raw_ar_header; |
46 | 46 | ||
47 | ar_headers_t *ar_list, *ar_tmp, *ar_entry; | 47 | file_headers_t *ar_list, *ar_entry; |
48 | char ar_magic[8]; | 48 | char ar_magic[8]; |
49 | char *long_name=NULL; | 49 | char *long_name=NULL; |
50 | 50 | ||
@@ -59,10 +59,10 @@ extern ar_headers_t *get_ar_headers(FILE *in_file) | |||
59 | return(NULL); | 59 | return(NULL); |
60 | } | 60 | } |
61 | 61 | ||
62 | ar_list = (ar_headers_t *) xcalloc(1, sizeof(ar_headers_t)); | 62 | ar_list = (file_headers_t *) xcalloc(1, sizeof(file_headers_t)); |
63 | 63 | ||
64 | while (fread((char *) &raw_ar_header, 1, 60, in_file) == 60) { | 64 | while (fread((char *) &raw_ar_header, 1, 60, in_file) == 60) { |
65 | ar_entry = (ar_headers_t *) xcalloc(1, sizeof(ar_headers_t)); | 65 | ar_entry = (file_headers_t *) xcalloc(1, sizeof(file_headers_t)); |
66 | /* check the end of header markers are valid */ | 66 | /* check the end of header markers are valid */ |
67 | if ((raw_ar_header.fmag[0] != '`') || (raw_ar_header.fmag[1] != '\n')) { | 67 | if ((raw_ar_header.fmag[0] != '`') || (raw_ar_header.fmag[1] != '\n')) { |
68 | char newline; | 68 | char newline; |
@@ -113,12 +113,7 @@ extern ar_headers_t *get_ar_headers(FILE *in_file) | |||
113 | 113 | ||
114 | fseek(in_file, (off_t) ar_entry->size, SEEK_CUR); | 114 | fseek(in_file, (off_t) ar_entry->size, SEEK_CUR); |
115 | 115 | ||
116 | ar_tmp = (ar_headers_t *) xcalloc(1, sizeof(ar_headers_t)); | 116 | ar_list = append_archive_list(ar_list, ar_entry); |
117 | *ar_tmp = *ar_list; | ||
118 | *ar_list = *ar_entry; | ||
119 | free(ar_entry); | ||
120 | ar_list->next = ar_tmp; | ||
121 | } | 117 | } |
122 | |||
123 | return(ar_list); | 118 | return(ar_list); |
124 | } | 119 | } |
diff --git a/libbb/libbb.h b/libbb/libbb.h index f99d25780..f24a38109 100644 --- a/libbb/libbb.h +++ b/libbb/libbb.h | |||
@@ -213,36 +213,41 @@ char *xreadlink(const char *path); | |||
213 | char *concat_path_file(const char *path, const char *filename); | 213 | char *concat_path_file(const char *path, const char *filename); |
214 | char *last_char_is(const char *s, int c); | 214 | char *last_char_is(const char *s, int c); |
215 | 215 | ||
216 | typedef struct ar_headers_s { | 216 | typedef struct file_headers_s { |
217 | char *name; | 217 | char *name; |
218 | char *link_name; | ||
218 | off_t size; | 219 | off_t size; |
219 | uid_t uid; | 220 | uid_t uid; |
220 | gid_t gid; | 221 | gid_t gid; |
221 | mode_t mode; | 222 | mode_t mode; |
222 | time_t mtime; | 223 | time_t mtime; |
223 | off_t offset; | 224 | off_t offset; |
224 | struct ar_headers_s *next; | 225 | dev_t device; |
225 | } ar_headers_t; | 226 | struct file_headers_s *next; |
226 | extern ar_headers_t *get_ar_headers(FILE *in_file); | 227 | } file_headers_t; |
227 | extern int seek_ared_file(FILE *in_file, ar_headers_t *headers, const char *tar_gz_file); | 228 | file_headers_t *get_ar_headers(FILE *in_file); |
228 | 229 | file_headers_t *get_tar_headers(FILE *tar_stream); | |
229 | typedef enum extract_function_e { | 230 | file_headers_t *get_tar_gz_headers(FILE *compressed_stream); |
230 | extract_contents = 1, | 231 | file_headers_t *append_archive_list(file_headers_t *head, file_headers_t *tail_entry); |
231 | extract_control = 2, | 232 | file_headers_t *add_from_archive_list(file_headers_t *master_list, file_headers_t *new_list, const char *name); |
232 | extract_info = 4, | 233 | |
233 | extract_extract = 8, | 234 | enum extract_functions_e { |
234 | extract_verbose_extract = 16, | 235 | extract_verbose_list = 1, |
235 | extract_list = 32, | 236 | extract_list = 2, |
236 | extract_fsys_tarfile = 64, | 237 | extract_one_to_buffer = 4, |
237 | extract_field = 128, | 238 | extract_to_stdout = 8, |
238 | extract_contents_to_file = 256 | 239 | extract_all_to_fs = 16, |
239 | } extract_function_t; | 240 | extract_preserve_date = 32, |
240 | extern char *deb_extract(const char *package_filename, int function, | 241 | extract_data_tar_gz = 64, |
241 | const char *argument, const char *argument2); | 242 | extract_control_tar_gz = 128, |
242 | extern char *untar(FILE *src_tar_file, FILE *output, int untar_function, | 243 | extract_unzip_only = 256 |
243 | const char *argument, const char *file_prefix); | 244 | }; |
244 | extern char *read_text_file_to_buffer(FILE *src_file); | 245 | char *extract_archive(FILE *src_stream, FILE *out_stream, file_headers_t *extract_headers, int function, const char *prefix); |
245 | extern char *read_package_field(const char *package_buffer); | 246 | char *deb_extract(const char *package_filename, FILE *out_stream, const int function, |
247 | const char *prefix, const char *filename); | ||
248 | char *read_package_field(const char *package_buffer); | ||
249 | int seek_sub_file(FILE *in_file, file_headers_t *headers, const char *tar_gz_file); | ||
250 | char *fgets_str(FILE *file, const char *terminating_string); | ||
246 | 251 | ||
247 | extern int unzip(FILE *l_in_file, FILE *l_out_file); | 252 | extern int unzip(FILE *l_in_file, FILE *l_out_file); |
248 | extern void gz_close(int gunzip_pid); | 253 | extern void gz_close(int gunzip_pid); |