diff options
Diffstat (limited to 'tar.c')
-rw-r--r-- | tar.c | 96 |
1 files changed, 74 insertions, 22 deletions
@@ -52,6 +52,11 @@ | |||
52 | #include <sys/sysmacros.h> | 52 | #include <sys/sysmacros.h> |
53 | #include <getopt.h> | 53 | #include <getopt.h> |
54 | 54 | ||
55 | #ifdef BB_FEATURE_TAR_GZIP | ||
56 | extern int unzip(int in, int out); | ||
57 | extern int gunzip_init(); | ||
58 | #endif | ||
59 | |||
55 | /* Tar file constants */ | 60 | /* Tar file constants */ |
56 | #ifndef MAJOR | 61 | #ifndef MAJOR |
57 | #define MAJOR(dev) (((dev)>>8)&0xff) | 62 | #define MAJOR(dev) (((dev)>>8)&0xff) |
@@ -129,29 +134,64 @@ struct TarInfo | |||
129 | typedef struct TarInfo TarInfo; | 134 | typedef struct TarInfo TarInfo; |
130 | 135 | ||
131 | /* Local procedures to restore files from a tar file. */ | 136 | /* Local procedures to restore files from a tar file. */ |
132 | static int readTarFile(const char* tarName, int extractFlag, int listFlag, | 137 | static int readTarFile(int tarFd, int extractFlag, int listFlag, |
133 | int tostdoutFlag, int verboseFlag, char** extractList, | 138 | int tostdoutFlag, int verboseFlag, char** extractList, |
134 | char** excludeList); | 139 | char** excludeList); |
135 | 140 | ||
136 | |||
137 | |||
138 | #ifdef BB_FEATURE_TAR_CREATE | 141 | #ifdef BB_FEATURE_TAR_CREATE |
139 | /* Local procedures to save files into a tar file. */ | 142 | /* Local procedures to save files into a tar file. */ |
140 | static int writeTarFile(const char* tarName, int verboseFlag, char **argv, | 143 | static int writeTarFile(const char* tarName, int verboseFlag, char **argv, |
141 | char** excludeList); | 144 | char** excludeList); |
142 | #endif | 145 | #endif |
143 | 146 | ||
147 | #ifdef BB_FEATURE_TAR_GZIP | ||
148 | /* Signal handler for when child gzip process dies... */ | ||
149 | void child_died() | ||
150 | { | ||
151 | fflush(stdout); | ||
152 | fflush(stderr); | ||
153 | exit(EXIT_FAILURE); | ||
154 | } | ||
155 | |||
156 | static int tar_unzip_init(int tarFd) | ||
157 | { | ||
158 | int child_pid; | ||
159 | static int unzip_pipe[2]; | ||
160 | /* Cope if child dies... Otherwise we block forever in read()... */ | ||
161 | signal(SIGCHLD, child_died); | ||
162 | |||
163 | if (pipe(unzip_pipe)!=0) | ||
164 | error_msg_and_die("pipe error\n"); | ||
165 | |||
166 | if ( (child_pid = fork()) == -1) | ||
167 | error_msg_and_die("fork failure\n"); | ||
168 | |||
169 | if (child_pid==0) { | ||
170 | /* child process */ | ||
171 | gunzip_init(); | ||
172 | unzip(tarFd, unzip_pipe[1]); | ||
173 | exit(EXIT_SUCCESS); | ||
174 | } | ||
175 | else | ||
176 | /* return fd of uncompressed data to parent process */ | ||
177 | return(unzip_pipe[0]); | ||
178 | } | ||
179 | #endif | ||
180 | |||
144 | extern int tar_main(int argc, char **argv) | 181 | extern int tar_main(int argc, char **argv) |
145 | { | 182 | { |
146 | char** excludeList=NULL; | 183 | char** excludeList=NULL; |
147 | char** extractList=NULL; | 184 | char** extractList=NULL; |
185 | const char *tarName="-"; | ||
148 | #if defined BB_FEATURE_TAR_EXCLUDE | 186 | #if defined BB_FEATURE_TAR_EXCLUDE |
149 | int excludeListSize=0; | 187 | int excludeListSize=0; |
150 | char *excludeFileName ="-"; | 188 | char *excludeFileName ="-"; |
151 | FILE *fileList; | 189 | FILE *fileList; |
152 | char file[256]; | 190 | char file[256]; |
191 | #endif | ||
192 | #if defined BB_FEATURE_TAR_GZIP | ||
193 | int unzipFlag = FALSE; | ||
153 | #endif | 194 | #endif |
154 | const char *tarName="-"; | ||
155 | int listFlag = FALSE; | 195 | int listFlag = FALSE; |
156 | int extractFlag = FALSE; | 196 | int extractFlag = FALSE; |
157 | int createFlag = FALSE; | 197 | int createFlag = FALSE; |
@@ -160,7 +200,6 @@ extern int tar_main(int argc, char **argv) | |||
160 | int status = FALSE; | 200 | int status = FALSE; |
161 | int firstOpt = TRUE; | 201 | int firstOpt = TRUE; |
162 | int stopIt; | 202 | int stopIt; |
163 | |||
164 | 203 | ||
165 | if (argc <= 1) | 204 | if (argc <= 1) |
166 | usage(tar_usage); | 205 | usage(tar_usage); |
@@ -185,6 +224,11 @@ extern int tar_main(int argc, char **argv) | |||
185 | goto flagError; | 224 | goto flagError; |
186 | listFlag = TRUE; | 225 | listFlag = TRUE; |
187 | break; | 226 | break; |
227 | #ifdef BB_FEATURE_TAR_GZIP | ||
228 | case 'z': | ||
229 | unzipFlag = TRUE; | ||
230 | break; | ||
231 | #endif | ||
188 | case 'v': | 232 | case 'v': |
189 | verboseFlag = TRUE; | 233 | verboseFlag = TRUE; |
190 | break; | 234 | break; |
@@ -255,13 +299,31 @@ extern int tar_main(int argc, char **argv) | |||
255 | #ifndef BB_FEATURE_TAR_CREATE | 299 | #ifndef BB_FEATURE_TAR_CREATE |
256 | error_msg_and_die( "This version of tar was not compiled with tar creation support.\n"); | 300 | error_msg_and_die( "This version of tar was not compiled with tar creation support.\n"); |
257 | #else | 301 | #else |
302 | #ifdef BB_FEATURE_TAR_GZIP | ||
303 | if (unzipFlag==TRUE) | ||
304 | error_msg_and_die("Creation of compressed not internally support by tar, pipe to busybox gunzip\n"); | ||
305 | #endif | ||
258 | status = writeTarFile(tarName, verboseFlag, argv, excludeList); | 306 | status = writeTarFile(tarName, verboseFlag, argv, excludeList); |
259 | #endif | 307 | #endif |
260 | } | 308 | } |
261 | if (listFlag == TRUE || extractFlag == TRUE) { | 309 | if (listFlag == TRUE || extractFlag == TRUE) { |
310 | int tarFd; | ||
262 | if (*argv) | 311 | if (*argv) |
263 | extractList = argv; | 312 | extractList = argv; |
264 | status = readTarFile(tarName, extractFlag, listFlag, tostdoutFlag, | 313 | /* Open the tar file for reading. */ |
314 | if (!strcmp(tarName, "-")) | ||
315 | tarFd = fileno(stdin); | ||
316 | else | ||
317 | tarFd = open(tarName, O_RDONLY); | ||
318 | if (tarFd < 0) | ||
319 | error_msg_and_die( "Error opening '%s': %s\n", tarName, strerror(errno)); | ||
320 | |||
321 | #ifdef BB_FEATURE_TAR_GZIP | ||
322 | /* unzip tarFd in a seperate process */ | ||
323 | if (unzipFlag == TRUE) | ||
324 | tarFd = tar_unzip_init(tarFd); | ||
325 | #endif | ||
326 | status = readTarFile(tarFd, extractFlag, listFlag, tostdoutFlag, | ||
265 | verboseFlag, extractList, excludeList); | 327 | verboseFlag, extractList, excludeList); |
266 | } | 328 | } |
267 | 329 | ||
@@ -521,27 +583,17 @@ readTarHeader(struct TarHeader *rawHeader, struct TarInfo *header) | |||
521 | * Read a tar file and extract or list the specified files within it. | 583 | * Read a tar file and extract or list the specified files within it. |
522 | * If the list is empty than all files are extracted or listed. | 584 | * If the list is empty than all files are extracted or listed. |
523 | */ | 585 | */ |
524 | static int readTarFile(const char* tarName, int extractFlag, int listFlag, | 586 | extern int readTarFile(int tarFd, int extractFlag, int listFlag, |
525 | int tostdoutFlag, int verboseFlag, char** extractList, | 587 | int tostdoutFlag, int verboseFlag, char** extractList, |
526 | char** excludeList) | 588 | char** excludeList) |
527 | { | 589 | { |
528 | int status, tarFd=-1; | 590 | int status; |
529 | int errorFlag=FALSE; | 591 | int errorFlag=FALSE; |
530 | int skipNextHeaderFlag=FALSE; | 592 | int skipNextHeaderFlag=FALSE; |
531 | TarHeader rawHeader; | 593 | TarHeader rawHeader; |
532 | TarInfo header; | 594 | TarInfo header; |
533 | char** tmpList; | 595 | char** tmpList; |
534 | 596 | ||
535 | /* Open the tar file for reading. */ | ||
536 | if (!strcmp(tarName, "-")) | ||
537 | tarFd = fileno(stdin); | ||
538 | else | ||
539 | tarFd = open(tarName, O_RDONLY); | ||
540 | if (tarFd < 0) { | ||
541 | error_msg( "Error opening '%s': %s\n", tarName, strerror(errno)); | ||
542 | return ( FALSE); | ||
543 | } | ||
544 | |||
545 | /* Set the umask for this process so it doesn't | 597 | /* Set the umask for this process so it doesn't |
546 | * screw up permission setting for us later. */ | 598 | * screw up permission setting for us later. */ |
547 | umask(0); | 599 | umask(0); |
@@ -739,7 +791,7 @@ static int readTarFile(const char* tarName, int extractFlag, int listFlag, | |||
739 | close(tarFd); | 791 | close(tarFd); |
740 | if (status > 0) { | 792 | if (status > 0) { |
741 | /* Bummer - we read a partial header */ | 793 | /* Bummer - we read a partial header */ |
742 | error_msg( "Error reading '%s': %s\n", tarName, strerror(errno)); | 794 | error_msg( "Error reading tar file: %s\n", strerror(errno)); |
743 | return ( FALSE); | 795 | return ( FALSE); |
744 | } | 796 | } |
745 | else if (errorFlag==TRUE) { | 797 | else if (errorFlag==TRUE) { |