This isnt used anymore, replaced by seek_sub_file() in ./libbb/deb_extract.c
[oweals/busybox.git] / libbb / extract_archive.c
1 /* 
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.
6  *
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.
11  *
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.
15  */
16
17 #include <stdlib.h>
18 #include <string.h>
19 #include <time.h>
20 #include <unistd.h>
21 #include <utime.h>
22 #include "libbb.h"
23
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 
27  *
28  * prefix doesnt have to be just a directory, it may prefix the filename as well.
29  *
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
33  *
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 
36  */
37
38 char *extract_archive(FILE *src_stream, FILE *out_stream, file_headers_t *extract_headers, int function, const char *prefix)
39 {
40         FILE *dst_stream = NULL;
41         char *full_name = NULL;
42         char *buffer = NULL;
43         size_t uncompressed_count = 0;
44         struct utimbuf t;
45
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 */
50                 if (prefix != NULL) {
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;
55                         } else {
56                                 tmp_str++;
57                         }
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);
62                 } else {
63                         full_name = extract_headers->name;
64                 }
65
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) {
69                         fgetc(src_stream);
70                         uncompressed_count++;
71                 }
72
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;
77                         }
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;
82                                 fclose(dst_stream);
83                         }
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);
87                                 break;
88                         }
89                 }
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); 
95                                         return NULL;
96                                 }
97                         }
98                 }
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); 
103                                         return NULL;
104                                 }
105                         }
106                 }
107 #endif
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));
112                 }
113
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);
117                 }
118
119                 if (function & extract_preserve_date) {
120                         t.actime = extract_headers->mtime;
121                         t.modtime = extract_headers->mtime;
122                         utime(full_name, &t);
123                 }
124                 chmod(full_name, extract_headers->mode);
125                 free(full_name);
126
127                 extract_headers = extract_headers->next;
128         }
129
130         return(buffer);
131 }
132