diff options
author | bug1 <bug1@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2001-06-13 07:26:39 +0000 |
---|---|---|
committer | bug1 <bug1@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2001-06-13 07:26:39 +0000 |
commit | 534e65a38bad53ef1681872f872260330be9a636 (patch) | |
tree | 4db8fdd4b9f429b416d068794c79bfc0df844e20 /libbb | |
parent | e9de4f7d085f52dc1c10e1df59d932b803e63ba8 (diff) | |
download | busybox-w32-534e65a38bad53ef1681872f872260330be9a636.tar.gz busybox-w32-534e65a38bad53ef1681872f872260330be9a636.tar.bz2 busybox-w32-534e65a38bad53ef1681872f872260330be9a636.zip |
Reorganise archive extraction code
git-svn-id: svn://busybox.net/trunk/busybox@2823 69ca8d6d-28ef-0310-b511-8ec308f3f277
Diffstat (limited to 'libbb')
-rw-r--r-- | libbb/deb_extract.c | 96 | ||||
-rw-r--r-- | libbb/get_ar_headers.c | 15 | ||||
-rw-r--r-- | libbb/libbb.h | 51 |
3 files changed, 94 insertions, 68 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); |
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); |