2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU Library General Public License for more details.
12 * You should have received a copy of the GNU General Public License
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.
24 /* Extract files in the linear linked list 'extract_headers' to either
25 * filesystem, stdout or buffer depending on the value of 'function' which is
26 * described in extract_files.h
28 * prefix doesnt have to be just a directory, it may prefix the filename as well.
30 * e.g. '/var/lib/dpkg/info/dpkg.' will extract all files to the base bath
31 * '/var/lib/dpkg/info/' and all files/dirs created in that dir will have
32 * 'dpkg.' as their prefix
34 * For this reason if prefix does point to a dir then it must end with a
35 * trailing '/' or else the last dir will be assumed to be the file prefix
38 char *extract_archive(FILE *src_stream, FILE *out_stream, file_headers_t *extract_headers, int function, const char *prefix)
40 FILE *dst_stream = NULL;
41 char *full_name = NULL;
43 size_t uncompressed_count = 0;
46 /* find files to extract or display */
47 while (extract_headers != NULL) {
48 /* prefix doesnt have to be a proper path it may prepend
49 * the filename as well */
51 /* strip leading '/' in filename to extract as prefix may not be dir */
52 char *tmp_str = strchr(extract_headers->name, '/');
53 if (tmp_str == NULL) {
54 tmp_str = extract_headers->name;
58 /* Cant use concat_path_file here as prefix might not be a directory */
59 full_name = xmalloc(strlen(prefix) + strlen(tmp_str) + 1);
60 strcpy(full_name, prefix);
61 strcat(full_name, tmp_str);
63 full_name = extract_headers->name;
66 /* Seek to start of file, have to use fgetc as src_stream may be a pipe
67 * you cant [lf]seek on pipes */
68 while (uncompressed_count < extract_headers->offset) {
73 if (S_ISREG(extract_headers->mode)) {
74 if (function & extract_to_stdout) {
75 copy_file_chunk(src_stream, out_stream, extract_headers->size);
76 uncompressed_count += extract_headers->size;
78 else if (function & extract_all_to_fs) {
79 dst_stream = wfopen(full_name, "w");
80 copy_file_chunk(src_stream, dst_stream, extract_headers->size);
81 uncompressed_count += extract_headers->size;
84 else if (function & extract_one_to_buffer) {
85 buffer = (char *) xmalloc(extract_headers->size + 1);
86 fread(buffer, 1, extract_headers->size, src_stream);
90 #if defined BB_DPKG | defined BB_DPKG_DEB
91 else if (S_ISDIR(extract_headers->mode)) {
92 if (function & extract_all_to_fs) {
93 if (create_path(full_name, extract_headers->mode) == FALSE) {
94 perror_msg("Cannot mkdir %s", extract_headers->name);
99 else if (S_ISLNK(extract_headers->mode)) {
100 if (function & extract_all_to_fs) {
101 if (symlink(extract_headers->link_name, full_name) < 0) {
102 perror_msg("Cannot create hard link from %s to '%s'", extract_headers->name, extract_headers->link_name);
108 if (function & extract_verbose_list) {
109 fprintf(out_stream, "%s %d/%d %8d %s ", mode_string(extract_headers->mode),
110 extract_headers->uid, extract_headers->gid,
111 (int) extract_headers->size, time_string(extract_headers->mtime));
114 if ((function & extract_list) || (function & extract_verbose_list)){
115 /* fputs doesnt add a trailing \n, so use fprintf */
116 fprintf(out_stream, "%s\n", extract_headers->name);
119 if (function & extract_preserve_date) {
120 t.actime = extract_headers->mtime;
121 t.modtime = extract_headers->mtime;
122 utime(full_name, &t);
124 chmod(full_name, extract_headers->mode);
127 extract_headers = extract_headers->next;