diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2006-11-24 17:55:23 +0300 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2006-11-24 17:55:23 +0300 |
commit | 4fbb584a0e6ee086d6b30936c7124c687b3e977f (patch) | |
tree | 279f3ff5c1a47d36ad4eec248240f11c7ef8d438 | |
parent | 0b35470d9b5e75a7a1df2e6860b48831e7920353 (diff) |
tar: cry murder and bail out if file shrinks under us while we tar it up
-rw-r--r-- | archival/tar.c | 14 | ||||
-rw-r--r-- | libbb/copyfd.c | 3 |
2 files changed, 13 insertions, 4 deletions
diff --git a/archival/tar.c b/archival/tar.c index 6aaa42273..99c4adb6a 100644 --- a/archival/tar.c +++ b/archival/tar.c @@ -59,7 +59,7 @@ struct TarHeader { /* byte offset */ typedef struct TarHeader TarHeader; /* -** writeTarFile(), writeFileToTarball(), and writeTarHeader() are +** writeTarFile(), writeFileToTarball(), and writeTarHeader() are ** the only functions that deal with the HardLinkInfo structure. ** Even these functions use the xxxHardLinkInfo() functions. */ @@ -397,7 +397,17 @@ static int writeFileToTarball(const char *fileName, struct stat *statbuf, off_t readSize = 0; /* write the file to the archive */ - readSize = bb_copyfd_eof(inputFileFd, tbInfo->tarFd); + readSize = bb_copyfd_size(inputFileFd, tbInfo->tarFd, statbuf->st_size); + if (readSize != statbuf->st_size) { + /* Deadly. We record size into header first, */ + /* and then write out file. If file shrinks in between, */ + /* tar will be corrupted. So bail out. */ + /* NB: GNU tar 1.16 warns and pads with zeroes */ + /* or even seeks back and updates header */ + bb_error_msg_and_die("short read from %s", fileName); + } + /* Check that file did not grow in between? */ + /* if (safe_read(inputFileFd,1) == 1) warn but continue? */ close(inputFileFd); /* Pad the file up to the tar block size */ diff --git a/libbb/copyfd.c b/libbb/copyfd.c index 87126eb72..601c51ce4 100644 --- a/libbb/copyfd.c +++ b/libbb/copyfd.c @@ -46,8 +46,7 @@ static off_t bb_full_fd_action(int src_fd, int dst_fd, off_t size) } else if (rd < 0) { bb_perror_msg(bb_msg_read_error); break; - } else if (rd == 0) { - /* All done. */ + } else { /* eof - all done. */ status = 0; break; } |