tar: fix verbose output with extract-to-stdout
No binary (build failed)
gcc -Wp,-MD,applets/.usage.d -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -Iinclude -Iinclude -o applets/usage applets/usage.c
(log yok)
| @@ -194,8 +194,9 @@ static int write_ar_archive(archive_handle_t *handle) | |
| } | |
| #endif /* FEATURE_AR_CREATE */ | |
| - | static void FAST_FUNC header_verbose_list_ar(const file_header_t *file_header) |
| + | static void FAST_FUNC header_verbose_list_ar(archive_handle_t *archive_handle) |
| { | |
| + | const file_header_t *file_header = archive_handle->file_header; |
| char mode[12]; | |
| char *mtime; | |
| @@ -124,7 +124,7 @@ char FAST_FUNC get_header_ar(archive_handle_t *archive_handle) | |
| typed->name[strcspn(typed->name, " /")] = '\0'; | |
| if (archive_handle->filter(archive_handle) == EXIT_SUCCESS) { | |
| - | archive_handle->action_header(typed); |
| + | archive_handle->action_header(archive_handle); |
| #if ENABLE_DPKG || ENABLE_DPKG_DEB | |
| if (archive_handle->dpkg__sub_archive) { | |
| struct archive_handle_t *sa = archive_handle->dpkg__sub_archive; | |
| @@ -125,7 +125,7 @@ char FAST_FUNC get_header_cpio(archive_handle_t *archive_handle) | |
| //cpio: etc/hosts not created: newer or same age file exists | |
| //etc/hosts <-- should NOT show it | |
| //2 blocks <-- should say "0 blocks" | |
| - | archive_handle->action_header(file_header); |
| + | archive_handle->action_header(archive_handle); |
| } else { | |
| data_skip(archive_handle); | |
| } | |
| @@ -469,7 +469,7 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle) | |
| cp = last_char_is(file_header->name, '/'); | |
| if (archive_handle->filter(archive_handle) == EXIT_SUCCESS) { | |
| - | archive_handle->action_header(/*archive_handle->*/ file_header); |
| + | archive_handle->action_header(archive_handle); |
| /* Note that we kill the '/' only after action_header() */ | |
| /* (like GNU tar 1.15.1: verbose mode outputs "dir/dir/") */ | |
| if (cp) | |
| @@ -5,8 +5,13 @@ | |
| #include "libbb.h" | |
| #include "bb_archive.h" | |
| - | void FAST_FUNC header_list(const file_header_t *file_header) |
| + | void FAST_FUNC header_list(archive_handle_t *archive_handle) |
| { | |
| //TODO: cpio -vp DIR should output "DIR/NAME", not just "NAME" */ | |
| - | puts(printable_string(file_header->name)); |
| + | |
| + | const file_header_t *file_header = archive_handle->file_header; |
| + | /* "tar xvOf TARFILE >OUTFILE" should use stderr for file list output: */ |
| + | FILE *fp = (archive_handle->action_data == data_extract_to_stdout) ? stderr : stdout; |
| + | |
| + | fprintf(fp, "%s\n", printable_string(file_header->name)); |
| } | |
| @@ -5,6 +5,6 @@ | |
| #include "libbb.h" | |
| #include "bb_archive.h" | |
| - | void FAST_FUNC header_skip(const file_header_t *file_header UNUSED_PARAM) |
| + | void FAST_FUNC header_skip(archive_handle_t *archive_handle UNUSED_PARAM) |
| { | |
| } | |
| @@ -5,11 +5,14 @@ | |
| #include "libbb.h" | |
| #include "bb_archive.h" | |
| - | void FAST_FUNC header_verbose_list(const file_header_t *file_header) |
| + | void FAST_FUNC header_verbose_list(archive_handle_t *archive_handle) |
| { | |
| + | const file_header_t *file_header = archive_handle->file_header; |
| struct tm tm_time; | |
| struct tm *ptm = &tm_time; //localtime(&file_header->mtime); | |
| char modestr[12]; | |
| + | /* "tar xvvOf TARFILE >OUTFILE" should use stderr for file list output: */ |
| + | FILE *fp = (archive_handle->action_data == data_extract_to_stdout) ? stderr : stdout; |
| #if ENABLE_FEATURE_TAR_UNAME_GNAME | |
| char uid[sizeof(int)*3 + 2]; | |
| @@ -29,7 +32,7 @@ void FAST_FUNC header_verbose_list(const file_header_t *file_header) | |
| /*sprintf(gid, "%u", (unsigned)file_header->gid);*/ | |
| group = utoa(file_header->gid); | |
| } | |
| - | printf("%s %s/%s %9"OFF_FMT"u %4u-%02u-%02u %02u:%02u:%02u %s", |
| + | fprintf(fp, "%s %s/%s %9"OFF_FMT"u %4u-%02u-%02u %02u:%02u:%02u %s", |
| bb_mode_string(modestr, file_header->mode), | |
| user, | |
| group, | |
| @@ -40,13 +43,13 @@ void FAST_FUNC header_verbose_list(const file_header_t *file_header) | |
| ptm->tm_hour, | |
| ptm->tm_min, | |
| ptm->tm_sec, | |
| - | file_header->name); |
| + | printable_string(file_header->name)); |
| #else /* !FEATURE_TAR_UNAME_GNAME */ | |
| localtime_r(&file_header->mtime, ptm); | |
| - | printf("%s %u/%u %9"OFF_FMT"u %4u-%02u-%02u %02u:%02u:%02u %s", |
| + | fprintf(fp, "%s %u/%u %9"OFF_FMT"u %4u-%02u-%02u %02u:%02u:%02u %s", |
| bb_mode_string(modestr, file_header->mode), | |
| (unsigned)file_header->uid, | |
| (unsigned)file_header->gid, | |
| @@ -63,7 +66,7 @@ void FAST_FUNC header_verbose_list(const file_header_t *file_header) | |
| /* NB: GNU tar shows "->" for symlinks and "link to" for hardlinks */ | |
| if (file_header->link_target) { | |
| - | printf(" -> %s", printable_string(file_header->link_target)); |
| + | fprintf(fp, " -> %s", printable_string(file_header->link_target)); |
| } | |
| - | bb_putchar('\n'); |
| + | putc('\n', fp); |
| } | |
| @@ -68,7 +68,7 @@ typedef struct archive_handle_t { | |
| llist_t *link_placeholders; | |
| /* Process the header component, e.g. tar -t */ | |
| - | void FAST_FUNC (*action_header)(const file_header_t *); |
| + | void FAST_FUNC (*action_header)(struct archive_handle_t *); |
| /* Process the data component, e.g. extract to filesystem */ | |
| void FAST_FUNC (*action_data)(struct archive_handle_t *); | |
| @@ -187,9 +187,9 @@ void data_extract_all(archive_handle_t *archive_handle) FAST_FUNC; | |
| void data_extract_to_stdout(archive_handle_t *archive_handle) FAST_FUNC; | |
| void data_extract_to_command(archive_handle_t *archive_handle) FAST_FUNC; | |
| - | void header_skip(const file_header_t *file_header) FAST_FUNC; |
| - | void header_list(const file_header_t *file_header) FAST_FUNC; |
| - | void header_verbose_list(const file_header_t *file_header) FAST_FUNC; |
| + | void header_skip(archive_handle_t *archive_handle) FAST_FUNC; |
| + | void header_list(archive_handle_t *archive_handle) FAST_FUNC; |
| + | void header_verbose_list(archive_handle_t *archive_handle) FAST_FUNC; |
| char get_header_ar(archive_handle_t *archive_handle) FAST_FUNC; | |
| char get_header_cpio(archive_handle_t *archive_handle) FAST_FUNC; | |
| @@ -205,6 +205,30 @@ SKIP= | |
| } | |
| cd .. || exit 1; rm -rf tar.tempdir 2>/dev/null | |
| + | mkdir tar.tempdir && cd tar.tempdir || exit 1 |
| + | optional FEATURE_TAR_CREATE |
| + | testing "tar xvO sends file list to stderr" '\ |
| + | echo "data1" >file1.txt |
| + | echo "data2" >file2.txt |
| + | echo "data3" >file3.txt |
| + | tar cf test.tar file1.txt file2.txt file3.txt |
| + | tar xvOf test.tar >out 2>err |
| + | echo OUT:; cat out |
| + | echo ERR:; cat err |
| + | ' "\ |
| + | OUT: |
| + | data1 |
| + | data2 |
| + | data3 |
| + | ERR: |
| + | file1.txt |
| + | file2.txt |
| + | file3.txt |
| + | " \ |
| + | "" "" |
| + | SKIP= |
| + | cd .. || exit 1; rm -rf tar.tempdir 2>/dev/null |
| + | |
| mkdir tar.tempdir && cd tar.tempdir || exit 1 | |
| # Had a bug where on extract autodetect first "switched off" -z | |
| # and then failed to recognize .tgz extension | |