diff options
Diffstat (limited to 'libbb/deb_extract.c')
-rw-r--r-- | libbb/deb_extract.c | 96 |
1 files changed, 61 insertions, 35 deletions
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); |