tar: cry murder and bail out if file shrinks under us while we tar it up
authorDenis Vlasenko <vda.linux@googlemail.com>
Fri, 24 Nov 2006 14:55:23 +0000 (14:55 -0000)
committerDenis Vlasenko <vda.linux@googlemail.com>
Fri, 24 Nov 2006 14:55:23 +0000 (14:55 -0000)
archival/tar.c
libbb/copyfd.c

index 6aaa4227393d26284008f0b713f3404d88b919bb..99c4adb6a2fee01523b0a0b5cce60b99995828d9 100644 (file)
@@ -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 */
index 87126eb72123ce70347dc663e6fa04dbfe47711b..601c51ce4d5fa930eeba4095329fbb91a592d25a 100644 (file)
@@ -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;
                }