diff options
-rw-r--r-- | archival/tar.c | 118 | ||||
-rw-r--r-- | libbb/recursive_action.c | 12 |
2 files changed, 71 insertions, 59 deletions
diff --git a/archival/tar.c b/archival/tar.c index 0b5720f3b..91232bcf3 100644 --- a/archival/tar.c +++ b/archival/tar.c | |||
@@ -84,7 +84,6 @@ struct HardLinkInfo { | |||
84 | 84 | ||
85 | /* Some info to be carried along when creating a new tarball */ | 85 | /* Some info to be carried along when creating a new tarball */ |
86 | struct TarBallInfo { | 86 | struct TarBallInfo { |
87 | char *fileName; /* File name of the tarball */ | ||
88 | int tarFd; /* Open-for-write file descriptor | 87 | int tarFd; /* Open-for-write file descriptor |
89 | for the tarball */ | 88 | for the tarball */ |
90 | struct stat statBuf; /* Stat info for the tarball, letting | 89 | struct stat statBuf; /* Stat info for the tarball, letting |
@@ -117,18 +116,18 @@ typedef enum TarFileType TarFileType; | |||
117 | /* Might be faster (and bigger) if the dev/ino were stored in numeric order;) */ | 116 | /* Might be faster (and bigger) if the dev/ino were stored in numeric order;) */ |
118 | static void addHardLinkInfo(HardLinkInfo ** hlInfoHeadPtr, | 117 | static void addHardLinkInfo(HardLinkInfo ** hlInfoHeadPtr, |
119 | struct stat *statbuf, | 118 | struct stat *statbuf, |
120 | const char *name) | 119 | const char *fileName) |
121 | { | 120 | { |
122 | /* Note: hlInfoHeadPtr can never be NULL! */ | 121 | /* Note: hlInfoHeadPtr can never be NULL! */ |
123 | HardLinkInfo *hlInfo; | 122 | HardLinkInfo *hlInfo; |
124 | 123 | ||
125 | hlInfo = (HardLinkInfo *) xmalloc(sizeof(HardLinkInfo) + strlen(name)); | 124 | hlInfo = xmalloc(sizeof(HardLinkInfo) + strlen(fileName)); |
126 | hlInfo->next = *hlInfoHeadPtr; | 125 | hlInfo->next = *hlInfoHeadPtr; |
127 | *hlInfoHeadPtr = hlInfo; | 126 | *hlInfoHeadPtr = hlInfo; |
128 | hlInfo->dev = statbuf->st_dev; | 127 | hlInfo->dev = statbuf->st_dev; |
129 | hlInfo->ino = statbuf->st_ino; | 128 | hlInfo->ino = statbuf->st_ino; |
130 | hlInfo->linkCount = statbuf->st_nlink; | 129 | hlInfo->linkCount = statbuf->st_nlink; |
131 | strcpy(hlInfo->name, name); | 130 | strcpy(hlInfo->name, fileName); |
132 | } | 131 | } |
133 | 132 | ||
134 | static void freeHardLinkInfo(HardLinkInfo ** hlInfoHeadPtr) | 133 | static void freeHardLinkInfo(HardLinkInfo ** hlInfoHeadPtr) |
@@ -156,7 +155,7 @@ static HardLinkInfo *findHardLinkInfo(HardLinkInfo * hlInfo, struct stat *statbu | |||
156 | break; | 155 | break; |
157 | hlInfo = hlInfo->next; | 156 | hlInfo = hlInfo->next; |
158 | } | 157 | } |
159 | return (hlInfo); | 158 | return hlInfo; |
160 | } | 159 | } |
161 | 160 | ||
162 | /* Put an octal string into the specified buffer. | 161 | /* Put an octal string into the specified buffer. |
@@ -193,9 +192,29 @@ static int putOctal(char *cp, int len, long value) | |||
193 | return TRUE; | 192 | return TRUE; |
194 | } | 193 | } |
195 | 194 | ||
195 | /* Pad file to TAR_BLOCK_SIZE with zeros */ | ||
196 | static void block_write_zeroes(int fd, size_t size) | ||
197 | { | ||
198 | char zerobuf[TAR_BLOCK_SIZE]; | ||
199 | memset(zerobuf, 0, size); | ||
200 | /* No point in trying to continue on error */ | ||
201 | if (full_write(fd, zerobuf, size) < 0) | ||
202 | bb_perror_msg_and_die("write"); | ||
203 | } | ||
204 | |||
205 | static size_t pad_block_write(int fd, size_t size) | ||
206 | { | ||
207 | size_t rem = (TAR_BLOCK_SIZE - size) & (TAR_BLOCK_SIZE-1); | ||
208 | if (rem) { | ||
209 | block_write_zeroes(fd, rem); | ||
210 | size += rem; | ||
211 | } | ||
212 | return size; | ||
213 | } | ||
214 | |||
196 | /* Write out a tar header for the specified file/directory/whatever */ | 215 | /* Write out a tar header for the specified file/directory/whatever */ |
197 | static int writeTarHeader(struct TarBallInfo *tbInfo, | 216 | static int writeTarHeader(struct TarBallInfo *tbInfo, |
198 | const char *header_name, const char *real_name, struct stat *statbuf) | 217 | const char *header_name, const char *fileName, struct stat *statbuf) |
199 | { | 218 | { |
200 | long chksum = 0; | 219 | long chksum = 0; |
201 | struct TarHeader header; | 220 | struct TarHeader header; |
@@ -225,10 +244,10 @@ static int writeTarHeader(struct TarBallInfo *tbInfo, | |||
225 | strncpy(header.linkname, tbInfo->hlInfo->name, | 244 | strncpy(header.linkname, tbInfo->hlInfo->name, |
226 | sizeof(header.linkname)); | 245 | sizeof(header.linkname)); |
227 | } else if (S_ISLNK(statbuf->st_mode)) { | 246 | } else if (S_ISLNK(statbuf->st_mode)) { |
228 | char *lpath = xreadlink(real_name); | 247 | char *lpath = xreadlink(fileName); |
229 | 248 | ||
230 | if (!lpath) /* Already printed err msg inside xreadlink() */ | 249 | if (!lpath) /* Already printed err msg inside xreadlink() */ |
231 | return (FALSE); | 250 | return FALSE; |
232 | header.typeflag = SYMTYPE; | 251 | header.typeflag = SYMTYPE; |
233 | strncpy(header.linkname, lpath, sizeof(header.linkname)); | 252 | strncpy(header.linkname, lpath, sizeof(header.linkname)); |
234 | free(lpath); | 253 | free(lpath); |
@@ -253,8 +272,8 @@ static int writeTarHeader(struct TarBallInfo *tbInfo, | |||
253 | header.typeflag = REGTYPE; | 272 | header.typeflag = REGTYPE; |
254 | putOctal(header.size, sizeof(header.size), statbuf->st_size); | 273 | putOctal(header.size, sizeof(header.size), statbuf->st_size); |
255 | } else { | 274 | } else { |
256 | bb_error_msg("%s: Unknown file type", real_name); | 275 | bb_error_msg("%s: unknown file type", fileName); |
257 | return (FALSE); | 276 | return FALSE; |
258 | } | 277 | } |
259 | 278 | ||
260 | /* Calculate and store the checksum (i.e., the sum of all of the bytes of | 279 | /* Calculate and store the checksum (i.e., the sum of all of the bytes of |
@@ -269,16 +288,15 @@ static int writeTarHeader(struct TarBallInfo *tbInfo, | |||
269 | putOctal(header.chksum, 7, chksum); | 288 | putOctal(header.chksum, 7, chksum); |
270 | 289 | ||
271 | /* Now write the header out to disk */ | 290 | /* Now write the header out to disk */ |
272 | if ((size = full_write(tbInfo->tarFd, (char *) &header, | 291 | size = full_write(tbInfo->tarFd, (char *) &header, |
273 | sizeof(struct TarHeader))) < 0) | 292 | sizeof(struct TarHeader)); |
274 | { | 293 | if (size < 0) { |
275 | bb_error_msg(bb_msg_io_error, real_name); | 294 | bb_error_msg(bb_msg_io_error, fileName); |
276 | return (FALSE); | 295 | return FALSE; |
277 | } | 296 | } |
278 | /* Pad the header up to the tar block size */ | 297 | /* Pad the header up to the tar block size */ |
279 | for (; size < TAR_BLOCK_SIZE; size++) { | 298 | size = pad_block_write(tbInfo->tarFd, size); |
280 | write(tbInfo->tarFd, "\0", 1); | 299 | |
281 | } | ||
282 | /* Now do the verbose thing (or not) */ | 300 | /* Now do the verbose thing (or not) */ |
283 | 301 | ||
284 | if (tbInfo->verboseFlag) { | 302 | if (tbInfo->verboseFlag) { |
@@ -290,7 +308,7 @@ static int writeTarHeader(struct TarBallInfo *tbInfo, | |||
290 | fprintf(vbFd, "%s\n", header.name); | 308 | fprintf(vbFd, "%s\n", header.name); |
291 | } | 309 | } |
292 | 310 | ||
293 | return (TRUE); | 311 | return TRUE; |
294 | } | 312 | } |
295 | 313 | ||
296 | # ifdef CONFIG_FEATURE_TAR_FROM | 314 | # ifdef CONFIG_FEATURE_TAR_FROM |
@@ -328,11 +346,11 @@ static int writeFileToTarball(const char *fileName, struct stat *statbuf, | |||
328 | int inputFileFd = -1; | 346 | int inputFileFd = -1; |
329 | 347 | ||
330 | /* | 348 | /* |
331 | ** Check to see if we are dealing with a hard link. | 349 | * Check to see if we are dealing with a hard link. |
332 | ** If so - | 350 | * If so - |
333 | ** Treat the first occurance of a given dev/inode as a file while | 351 | * Treat the first occurance of a given dev/inode as a file while |
334 | ** treating any additional occurances as hard links. This is done | 352 | * treating any additional occurances as hard links. This is done |
335 | ** by adding the file information to the HardLinkInfo linked list. | 353 | * by adding the file information to the HardLinkInfo linked list. |
336 | */ | 354 | */ |
337 | tbInfo->hlInfo = NULL; | 355 | tbInfo->hlInfo = NULL; |
338 | if (statbuf->st_nlink > 1) { | 356 | if (statbuf->st_nlink > 1) { |
@@ -344,7 +362,7 @@ static int writeFileToTarball(const char *fileName, struct stat *statbuf, | |||
344 | /* It is against the rules to archive a socket */ | 362 | /* It is against the rules to archive a socket */ |
345 | if (S_ISSOCK(statbuf->st_mode)) { | 363 | if (S_ISSOCK(statbuf->st_mode)) { |
346 | bb_error_msg("%s: socket ignored", fileName); | 364 | bb_error_msg("%s: socket ignored", fileName); |
347 | return (TRUE); | 365 | return TRUE; |
348 | } | 366 | } |
349 | 367 | ||
350 | /* It is a bad idea to store the archive we are in the process of creating, | 368 | /* It is a bad idea to store the archive we are in the process of creating, |
@@ -353,7 +371,7 @@ static int writeFileToTarball(const char *fileName, struct stat *statbuf, | |||
353 | if (tbInfo->statBuf.st_dev == statbuf->st_dev && | 371 | if (tbInfo->statBuf.st_dev == statbuf->st_dev && |
354 | tbInfo->statBuf.st_ino == statbuf->st_ino) { | 372 | tbInfo->statBuf.st_ino == statbuf->st_ino) { |
355 | bb_error_msg("%s: file is the archive; skipping", fileName); | 373 | bb_error_msg("%s: file is the archive; skipping", fileName); |
356 | return (TRUE); | 374 | return TRUE; |
357 | } | 375 | } |
358 | 376 | ||
359 | header_name = fileName; | 377 | header_name = fileName; |
@@ -361,7 +379,7 @@ static int writeFileToTarball(const char *fileName, struct stat *statbuf, | |||
361 | static int alreadyWarned = FALSE; | 379 | static int alreadyWarned = FALSE; |
362 | 380 | ||
363 | if (alreadyWarned == FALSE) { | 381 | if (alreadyWarned == FALSE) { |
364 | bb_error_msg("Removing leading '/' from member names"); | 382 | bb_error_msg("removing leading '/' from member names"); |
365 | alreadyWarned = TRUE; | 383 | alreadyWarned = TRUE; |
366 | } | 384 | } |
367 | header_name++; | 385 | header_name++; |
@@ -369,7 +387,7 @@ static int writeFileToTarball(const char *fileName, struct stat *statbuf, | |||
369 | 387 | ||
370 | if (strlen(fileName) >= NAME_SIZE) { | 388 | if (strlen(fileName) >= NAME_SIZE) { |
371 | bb_error_msg(bb_msg_name_longer_than_foo, NAME_SIZE); | 389 | bb_error_msg(bb_msg_name_longer_than_foo, NAME_SIZE); |
372 | return (TRUE); | 390 | return TRUE; |
373 | } | 391 | } |
374 | 392 | ||
375 | if (header_name[0] == '\0') | 393 | if (header_name[0] == '\0') |
@@ -382,21 +400,20 @@ static int writeFileToTarball(const char *fileName, struct stat *statbuf, | |||
382 | 400 | ||
383 | /* Is this a regular file? */ | 401 | /* Is this a regular file? */ |
384 | if ((tbInfo->hlInfo == NULL) && (S_ISREG(statbuf->st_mode))) { | 402 | if ((tbInfo->hlInfo == NULL) && (S_ISREG(statbuf->st_mode))) { |
385 | |||
386 | /* open the file we want to archive, and make sure all is well */ | 403 | /* open the file we want to archive, and make sure all is well */ |
387 | if ((inputFileFd = open(fileName, O_RDONLY)) < 0) { | 404 | if ((inputFileFd = open(fileName, O_RDONLY)) < 0) { |
388 | bb_perror_msg("%s: Cannot open", fileName); | 405 | bb_perror_msg("%s: cannot open", fileName); |
389 | return (FALSE); | 406 | return FALSE; |
390 | } | 407 | } |
391 | } | 408 | } |
392 | 409 | ||
393 | /* Add an entry to the tarball */ | 410 | /* Add an entry to the tarball */ |
394 | if (writeTarHeader(tbInfo, header_name, fileName, statbuf) == FALSE) { | 411 | if (writeTarHeader(tbInfo, header_name, fileName, statbuf) == FALSE) { |
395 | return (FALSE); | 412 | return FALSE; |
396 | } | 413 | } |
397 | 414 | ||
398 | /* If it was a regular file, write out the body */ | 415 | /* If it was a regular file, write out the body */ |
399 | if (inputFileFd >= 0 ) { | 416 | if (inputFileFd >= 0) { |
400 | ssize_t readSize = 0; | 417 | ssize_t readSize = 0; |
401 | 418 | ||
402 | /* write the file to the archive */ | 419 | /* write the file to the archive */ |
@@ -404,11 +421,10 @@ static int writeFileToTarball(const char *fileName, struct stat *statbuf, | |||
404 | close(inputFileFd); | 421 | close(inputFileFd); |
405 | 422 | ||
406 | /* Pad the file up to the tar block size */ | 423 | /* Pad the file up to the tar block size */ |
407 | for (; (readSize % TAR_BLOCK_SIZE) != 0; readSize++) | 424 | readSize = pad_block_write(tbInfo->tarFd, readSize); |
408 | write(tbInfo->tarFd, "\0", 1); | ||
409 | } | 425 | } |
410 | 426 | ||
411 | return (TRUE); | 427 | return TRUE; |
412 | } | 428 | } |
413 | 429 | ||
414 | static int writeTarFile(const int tar_fd, const int verboseFlag, | 430 | static int writeTarFile(const int tar_fd, const int verboseFlag, |
@@ -416,9 +432,7 @@ static int writeTarFile(const int tar_fd, const int verboseFlag, | |||
416 | const llist_t *exclude, const int gzip) | 432 | const llist_t *exclude, const int gzip) |
417 | { | 433 | { |
418 | pid_t gzipPid = 0; | 434 | pid_t gzipPid = 0; |
419 | |||
420 | int errorFlag = FALSE; | 435 | int errorFlag = FALSE; |
421 | ssize_t size; | ||
422 | struct TarBallInfo tbInfo; | 436 | struct TarBallInfo tbInfo; |
423 | 437 | ||
424 | tbInfo.hlInfoHead = NULL; | 438 | tbInfo.hlInfoHead = NULL; |
@@ -430,7 +444,7 @@ static int writeTarFile(const int tar_fd, const int verboseFlag, | |||
430 | /* Store the stat info for the tarball's file, so | 444 | /* Store the stat info for the tarball's file, so |
431 | * can avoid including the tarball into itself.... */ | 445 | * can avoid including the tarball into itself.... */ |
432 | if (fstat(tbInfo.tarFd, &tbInfo.statBuf) < 0) | 446 | if (fstat(tbInfo.tarFd, &tbInfo.statBuf) < 0) |
433 | bb_perror_msg_and_die("Couldnt stat tar file"); | 447 | bb_perror_msg_and_die("cannot stat tar file"); |
434 | 448 | ||
435 | if ((ENABLE_FEATURE_TAR_GZIP || ENABLE_FEATURE_TAR_BZIP2) && gzip) { | 449 | if ((ENABLE_FEATURE_TAR_GZIP || ENABLE_FEATURE_TAR_BZIP2) && gzip) { |
436 | int gzipDataPipe[2] = { -1, -1 }; | 450 | int gzipDataPipe[2] = { -1, -1 }; |
@@ -440,7 +454,7 @@ static int writeTarFile(const int tar_fd, const int verboseFlag, | |||
440 | 454 | ||
441 | 455 | ||
442 | if (pipe(gzipDataPipe) < 0 || pipe(gzipStatusPipe) < 0) | 456 | if (pipe(gzipDataPipe) < 0 || pipe(gzipStatusPipe) < 0) |
443 | bb_perror_msg_and_die("create pipe"); | 457 | bb_perror_msg_and_die("pipe"); |
444 | 458 | ||
445 | signal(SIGPIPE, SIG_IGN); /* we only want EPIPE on errors */ | 459 | signal(SIGPIPE, SIG_IGN); /* we only want EPIPE on errors */ |
446 | 460 | ||
@@ -502,8 +516,8 @@ static int writeTarFile(const int tar_fd, const int verboseFlag, | |||
502 | include = include->link; | 516 | include = include->link; |
503 | } | 517 | } |
504 | /* Write two empty blocks to the end of the archive */ | 518 | /* Write two empty blocks to the end of the archive */ |
505 | for (size = 0; size < (2 * TAR_BLOCK_SIZE); size++) | 519 | block_write_zeroes(tbInfo.tarFd, TAR_BLOCK_SIZE); |
506 | write(tbInfo.tarFd, "\0", 1); | 520 | block_write_zeroes(tbInfo.tarFd, TAR_BLOCK_SIZE); |
507 | 521 | ||
508 | /* To be pedantically correct, we would check if the tarball | 522 | /* To be pedantically correct, we would check if the tarball |
509 | * is smaller than 20 tar blocks, and pad it if it was smaller, | 523 | * is smaller than 20 tar blocks, and pad it if it was smaller, |
@@ -546,10 +560,10 @@ static llist_t *append_file_list_to_list(llist_t *list) | |||
546 | cur = cur->link; | 560 | cur = cur->link; |
547 | free(tmp); | 561 | free(tmp); |
548 | while ((line = bb_get_chomped_line_from_file(src_stream)) != NULL) { | 562 | while ((line = bb_get_chomped_line_from_file(src_stream)) != NULL) { |
549 | char *filename_ptr = last_char_is(line, '/'); | 563 | char *filename_ptr = last_char_is(line, '/'); |
550 | if (filename_ptr > line) | 564 | if (filename_ptr > line) |
551 | *filename_ptr = '\0'; | 565 | *filename_ptr = '\0'; |
552 | llist_add_to(&newlist, line); | 566 | llist_add_to(&newlist, line); |
553 | } | 567 | } |
554 | fclose(src_stream); | 568 | fclose(src_stream); |
555 | } | 569 | } |
@@ -569,12 +583,13 @@ static char get_header_tar_Z(archive_handle_t *archive_handle) | |||
569 | if (xread_char(archive_handle->src_fd) != 0x1f || | 583 | if (xread_char(archive_handle->src_fd) != 0x1f || |
570 | xread_char(archive_handle->src_fd) != 0x9d) | 584 | xread_char(archive_handle->src_fd) != 0x9d) |
571 | { | 585 | { |
572 | bb_error_msg_and_die("Invalid magic"); | 586 | bb_error_msg_and_die("invalid magic"); |
573 | } | 587 | } |
574 | 588 | ||
575 | archive_handle->src_fd = open_transformer(archive_handle->src_fd, uncompress); | 589 | archive_handle->src_fd = open_transformer(archive_handle->src_fd, uncompress); |
576 | archive_handle->offset = 0; | 590 | archive_handle->offset = 0; |
577 | while (get_header_tar(archive_handle) == EXIT_SUCCESS); | 591 | while (get_header_tar(archive_handle) == EXIT_SUCCESS) |
592 | /* nothing */; | ||
578 | 593 | ||
579 | /* Can only do one file at a time */ | 594 | /* Can only do one file at a time */ |
580 | return(EXIT_FAILURE); | 595 | return(EXIT_FAILURE); |
@@ -828,7 +843,7 @@ int tar_main(int argc, char **argv) | |||
828 | tar_handle->src_fd = fileno(tar_stream); | 843 | tar_handle->src_fd = fileno(tar_stream); |
829 | tar_handle->seek = seek_by_char; | 844 | tar_handle->seek = seek_by_char; |
830 | } else { | 845 | } else { |
831 | tar_handle->src_fd = xopen(tar_filename, flags); | 846 | tar_handle->src_fd = xopen3(tar_filename, flags, 0666); |
832 | } | 847 | } |
833 | } | 848 | } |
834 | 849 | ||
@@ -854,14 +869,15 @@ int tar_main(int argc, char **argv) | |||
854 | tar_handle->accept, | 869 | tar_handle->accept, |
855 | tar_handle->reject, zipMode); | 870 | tar_handle->reject, zipMode); |
856 | } else { | 871 | } else { |
857 | while (get_header_ptr(tar_handle) == EXIT_SUCCESS); | 872 | while (get_header_ptr(tar_handle) == EXIT_SUCCESS) |
873 | /* nothing */; | ||
858 | 874 | ||
859 | /* Check that every file that should have been extracted was */ | 875 | /* Check that every file that should have been extracted was */ |
860 | while (tar_handle->accept) { | 876 | while (tar_handle->accept) { |
861 | if (!find_list_entry(tar_handle->reject, tar_handle->accept->data) | 877 | if (!find_list_entry(tar_handle->reject, tar_handle->accept->data) |
862 | && !find_list_entry(tar_handle->passed, tar_handle->accept->data)) | 878 | && !find_list_entry(tar_handle->passed, tar_handle->accept->data)) |
863 | { | 879 | { |
864 | bb_error_msg_and_die("%s: Not found in archive", tar_handle->accept->data); | 880 | bb_error_msg_and_die("%s: not found in archive", tar_handle->accept->data); |
865 | } | 881 | } |
866 | tar_handle->accept = tar_handle->accept->link; | 882 | tar_handle->accept = tar_handle->accept->link; |
867 | } | 883 | } |
diff --git a/libbb/recursive_action.c b/libbb/recursive_action.c index d491b781b..28a493403 100644 --- a/libbb/recursive_action.c +++ b/libbb/recursive_action.c | |||
@@ -23,14 +23,10 @@ | |||
23 | * is so stinking huge. | 23 | * is so stinking huge. |
24 | */ | 24 | */ |
25 | int recursive_action(const char *fileName, | 25 | int recursive_action(const char *fileName, |
26 | int recurse, int followLinks, int depthFirst, | 26 | int recurse, int followLinks, int depthFirst, |
27 | int (*fileAction) (const char *fileName, | 27 | int (*fileAction) (const char *fileName, struct stat * statbuf, void* userData), |
28 | struct stat * statbuf, | 28 | int (*dirAction) (const char *fileName, struct stat * statbuf, void* userData), |
29 | void* userData), | 29 | void* userData) |
30 | int (*dirAction) (const char *fileName, | ||
31 | struct stat * statbuf, | ||
32 | void* userData), | ||
33 | void* userData) | ||
34 | { | 30 | { |
35 | int status; | 31 | int status; |
36 | struct stat statbuf; | 32 | struct stat statbuf; |