tar:
authorDenis Vlasenko <vda.linux@googlemail.com>
Fri, 24 Nov 2006 14:51:01 +0000 (14:51 -0000)
committerDenis Vlasenko <vda.linux@googlemail.com>
Fri, 24 Nov 2006 14:51:01 +0000 (14:51 -0000)
* unpack: handle tar header fields which are not NUL terminated
* pack: handle 4+GB files correctly
* pack: refuse to store 101+ softlinks (was truncating link
  target name)
* pack: mask mode with 07777

archival/libunarchive/get_header_tar.c
archival/tar.c
include/libbb.h
libbb/messages.c

index f78377e28a68485e9eed1029614440228e5e8f8d..b5cae9f125d61bcc098420ccb3b562d45aa246af 100644 (file)
@@ -19,49 +19,69 @@ static char *longname = NULL;
 static char *linkname = NULL;
 #endif
 
+/* NB: _DESTROYS_ str[len] character! */
+static unsigned long long getOctal(char *str, int len)
+{
+       unsigned long long v;
+       /* Actually, tar header allows leading spaces also.
+        * Oh well, we will be liberal and skip this...
+        * The only downside probably is that we allow "-123" too :)
+       if (*str < '0' || *str > '7')
+               bb_error_msg_and_die("corrupted octal value in tar header");
+       */
+       str[len] = '\0';
+       v = strtoull(str, &str, 8);
+       if (*str)
+               bb_error_msg_and_die("corrupted octal value in tar header");
+       return v;
+}
+
+void BUG_tar_header_size(void);
 char get_header_tar(archive_handle_t *archive_handle)
 {
+       static int end = 0;
+
        file_header_t *file_header = archive_handle->file_header;
-       union {
+       struct {
                /* ustar header, Posix 1003.1 */
-               unsigned char raw[512];
-               struct {
-                       char name[100]; /*   0-99 */
-                       char mode[8];   /* 100-107 */
-                       char uid[8];    /* 108-115 */
-                       char gid[8];    /* 116-123 */
-                       char size[12];  /* 124-135 */
-                       char mtime[12]; /* 136-147 */
-                       char chksum[8]; /* 148-155 */
-                       char typeflag;  /* 156-156 */
-                       char linkname[100];     /* 157-256 */
-                       char magic[6];  /* 257-262 */
-                       char version[2];        /* 263-264 */
-                       char uname[32]; /* 265-296 */
-                       char gname[32]; /* 297-328 */
-                       char devmajor[8];       /* 329-336 */
-                       char devminor[8];       /* 337-344 */
-                       char prefix[155];       /* 345-499 */
-                       char padding[12];       /* 500-512 */
-               } formatted;
+               char name[100];     /*   0-99 */
+               char mode[8];       /* 100-107 */
+               char uid[8];        /* 108-115 */
+               char gid[8];        /* 116-123 */
+               char size[12];      /* 124-135 */
+               char mtime[12];     /* 136-147 */
+               char chksum[8];     /* 148-155 */
+               char typeflag;      /* 156-156 */
+               char linkname[100]; /* 157-256 */
+               char magic[6];      /* 257-262 */
+               char version[2];    /* 263-264 */
+               char uname[32];     /* 265-296 */
+               char gname[32];     /* 297-328 */
+               char devmajor[8];   /* 329-336 */
+               char devminor[8];   /* 337-344 */
+               char prefix[155];   /* 345-499 */
+               char padding[12];   /* 500-512 */
        } tar;
-       long sum = 0;
-       long i;
-       static int end = 0;
+       char *cp;
+       int sum, i;
+
+       if (sizeof(tar) != 512)
+               BUG_tar_header_size();
 
        /* Align header */
        data_align(archive_handle, 512);
 
-       xread(archive_handle->src_fd, tar.raw, 512);
+       xread(archive_handle->src_fd, &tar, 512);
        archive_handle->offset += 512;
 
        /* If there is no filename its an empty header */
-       if (tar.formatted.name[0] == 0) {
+       if (tar.name[0] == 0) {
                if (end) {
                        /* This is the second consecutive empty header! End of archive!
                         * Read until the end to empty the pipe from gz or bz2
                         */
-                       while (full_read(archive_handle->src_fd, tar.raw, 512) == 512);
+                       while (full_read(archive_handle->src_fd, &tar, 512) == 512)
+                               /* repeat */;
                        return EXIT_FAILURE;
                }
                end = 1;
@@ -72,21 +92,22 @@ char get_header_tar(archive_handle_t *archive_handle)
        /* Check header has valid magic, "ustar" is for the proper tar
         * 0's are for the old tar format
         */
-       if (strncmp(tar.formatted.magic, "ustar", 5) != 0) {
+       if (strncmp(tar.magic, "ustar", 5) != 0) {
 #ifdef CONFIG_FEATURE_TAR_OLDGNU_COMPATIBILITY
-               if (memcmp(tar.formatted.magic, "\0\0\0\0", 5) != 0)
+               if (memcmp(tar.magic, "\0\0\0\0", 5) != 0)
 #endif
                        bb_error_msg_and_die("invalid tar magic");
        }
        /* Do checksum on headers */
+       sum = ' ' * sizeof(tar.chksum);
        for (i = 0; i < 148 ; i++) {
-               sum += tar.raw[i];
+               sum += ((char*)&tar)[i];
        }
-       sum += ' ' * 8;
        for (i = 156; i < 512 ; i++) {
-               sum += tar.raw[i];
+               sum += ((char*)&tar)[i];
        }
-       if (sum != xstrtoul(tar.formatted.chksum, 8)) {
+       /* This field does not need special treatment (getOctal) */
+       if (sum != xstrtoul(tar.chksum, 8)) {
                bb_error_msg_and_die("invalid tar header checksum");
        }
 
@@ -101,30 +122,34 @@ char get_header_tar(archive_handle_t *archive_handle)
        } else
 #endif
        {
-               file_header->name = xstrndup(tar.formatted.name, 100);
-               if (tar.formatted.prefix[0]) {
+               file_header->name = xstrndup(tar.name, sizeof(tar.name));
+               if (tar.prefix[0]) {
                        char *temp = file_header->name;
-                       file_header->name = concat_path_file(tar.formatted.prefix, temp);
+                       file_header->name = concat_path_file(tar.prefix, temp);
                        free(temp);
                }
        }
 
-       file_header->uid = xstrtoul(tar.formatted.uid, 8);
-       file_header->gid = xstrtoul(tar.formatted.gid, 8);
-       file_header->size = XSTRTOUOFF(tar.formatted.size, 8);
-       file_header->mtime = xstrtoul(tar.formatted.mtime, 8);
-       file_header->link_name = tar.formatted.linkname[0] ?
-                                xstrdup(tar.formatted.linkname) : NULL;
-       if (tar.formatted.devmajor[0]) {
-               file_header->device = makedev(xstrtoul(tar.formatted.devmajor, 8),
-                                             xstrtoul(tar.formatted.devminor, 8));
+       /* getOctal trashes subsequent field, therefore we call it
+        * on fields in reverse order */
+#define GET_OCTAL(a) getOctal((a), sizeof(a))
+       if (tar.devmajor[0]) {
+               unsigned minor = GET_OCTAL(tar.devminor);
+               unsigned major = GET_OCTAL(tar.devmajor);
+               file_header->device = makedev(major, minor);
        }
-
+       file_header->mtime = GET_OCTAL(tar.mtime);
+       file_header->size = GET_OCTAL(tar.size);
+       file_header->gid = GET_OCTAL(tar.gid);
+       file_header->uid = GET_OCTAL(tar.uid);
+       file_header->link_name = !tar.linkname[0] ? NULL :
+                       xstrndup(tar.linkname, sizeof(tar.linkname));
        /* Set bits 0-11 of the files mode */
-       file_header->mode = 07777 & xstrtoul(tar.formatted.mode, 8);
+       file_header->mode = 07777 & GET_OCTAL(tar.mode);
+#undef GET_OCTAL
 
        /* Set bits 12-15 of the files mode */
-       switch (tar.formatted.typeflag) {
+       switch (tar.typeflag) {
        /* busybox identifies hard links as being regular files with 0 size and a link name */
        case '1':
                file_header->mode |= S_IFREG;
@@ -138,7 +163,7 @@ char get_header_tar(archive_handle_t *archive_handle)
                        file_header->mode |= S_IFDIR;
                } else
 #endif
-                       file_header->mode |= S_IFREG;
+               file_header->mode |= S_IFREG;
                break;
        case '2':
                file_header->mode |= S_IFLNK;
@@ -156,42 +181,36 @@ char get_header_tar(archive_handle_t *archive_handle)
                file_header->mode |= S_IFIFO;
                break;
 #ifdef CONFIG_FEATURE_TAR_GNU_EXTENSIONS
-       case 'L': {
-                       longname = xzalloc(file_header->size + 1);
-                       xread(archive_handle->src_fd, longname, file_header->size);
-                       archive_handle->offset += file_header->size;
-
-                       return get_header_tar(archive_handle);
-               }
-       case 'K': {
-                       linkname = xzalloc(file_header->size + 1);
-                       xread(archive_handle->src_fd, linkname, file_header->size);
-                       archive_handle->offset += file_header->size;
-
-                       file_header->name = linkname;
-                       return get_header_tar(archive_handle);
-               }
+       case 'L':
+               longname = xzalloc(file_header->size + 1);
+               xread(archive_handle->src_fd, longname, file_header->size);
+               archive_handle->offset += file_header->size;
+               return get_header_tar(archive_handle);
+       case 'K':
+               linkname = xzalloc(file_header->size + 1);
+               xread(archive_handle->src_fd, linkname, file_header->size);
+               archive_handle->offset += file_header->size;
+               file_header->name = linkname;
+               return get_header_tar(archive_handle);
        case 'D':       /* GNU dump dir */
-       case 'M':       /* Continuation of multi volume archive*/
+       case 'M':       /* Continuation of multi volume archive */
        case 'N':       /* Old GNU for names > 100 characters */
        case 'S':       /* Sparse file */
        case 'V':       /* Volume header */
 #endif
        case 'g':       /* pax global header */
        case 'x':       /* pax extended header */
-               bb_error_msg("ignoring extension type %c", tar.formatted.typeflag);
+               bb_error_msg("ignoring extension type %c", tar.typeflag);
                break;
        default:
-               bb_error_msg("unknown typeflag: 0x%x", tar.formatted.typeflag);
-       }
-       {       /* Strip trailing '/' in directories */
-               /* Must be done after mode is set as '/' is used to check if its a directory */
-               char *tmp = last_char_is(file_header->name, '/');
-               if (tmp) {
-                       *tmp = '\0';
-               }
+               bb_error_msg("unknown typeflag: 0x%x", tar.typeflag);
        }
 
+       /* Strip trailing '/' in directories */
+       /* Must be done after mode is set as '/' is used to check if its a directory */
+       cp = last_char_is(file_header->name, '/');
+       if (cp) *cp = '\0';
+
        if (archive_handle->filter(archive_handle) == EXIT_SUCCESS) {
                archive_handle->action_header(archive_handle->file_header);
                archive_handle->flags |= ARCHIVE_EXTRACT_QUIET;
index db812e0f4ff14f5d7ac3ee3ff193ed4da162400b..911c2d35e8e1cbee8fa4e9f933d5ba6e97d0b9fd 100644 (file)
 #define TAR_BLOCK_SIZE         512
 
 /* POSIX tar Header Block, from POSIX 1003.1-1990  */
-#define NAME_SIZE                      100
-struct TarHeader {             /* byte offset */
-       char name[NAME_SIZE];   /*   0-99 */
-       char mode[8];           /* 100-107 */
-       char uid[8];            /* 108-115 */
-       char gid[8];            /* 116-123 */
-       char size[12];          /* 124-135 */
-       char mtime[12];         /* 136-147 */
-       char chksum[8];         /* 148-155 */
-       char typeflag;          /* 156-156 */
-       char linkname[NAME_SIZE];       /* 157-256 */
-       char magic[6];          /* 257-262 */
-       char version[2];        /* 263-264 */
-       char uname[32];         /* 265-296 */
-       char gname[32];         /* 297-328 */
-       char devmajor[8];       /* 329-336 */
-       char devminor[8];       /* 337-344 */
-       char prefix[155];       /* 345-499 */
-       char padding[12];       /* 500-512 (pad to exactly the TAR_BLOCK_SIZE) */
+#define NAME_SIZE      100
+#define NAME_SIZE_STR "100"
+struct TarHeader {               /* byte offset */
+       char name[NAME_SIZE];     /*   0-99 */
+       char mode[8];             /* 100-107 */
+       char uid[8];              /* 108-115 */
+       char gid[8];              /* 116-123 */
+       char size[12];            /* 124-135 */
+       char mtime[12];           /* 136-147 */
+       char chksum[8];           /* 148-155 */
+       char typeflag;            /* 156-156 */
+       char linkname[NAME_SIZE]; /* 157-256 */
+       char magic[6];            /* 257-262 */
+       char version[2];          /* 263-264 */
+       char uname[32];           /* 265-296 */
+       char gname[32];           /* 297-328 */
+       char devmajor[8];         /* 329-336 */
+       char devminor[8];         /* 337-344 */
+       char prefix[155];         /* 345-499 */
+       char padding[12];         /* 500-512 (pad to exactly the TAR_BLOCK_SIZE) */
 };
 typedef struct TarHeader TarHeader;
 
@@ -121,8 +122,8 @@ static void addHardLinkInfo(HardLinkInfo ** hlInfoHeadPtr,
 
 static void freeHardLinkInfo(HardLinkInfo ** hlInfoHeadPtr)
 {
-       HardLinkInfo *hlInfo = NULL;
-       HardLinkInfo *hlInfoNext = NULL;
+       HardLinkInfo *hlInfo;
+       HardLinkInfo *hlInfoNext;
 
        if (hlInfoHeadPtr) {
                hlInfo = *hlInfoHeadPtr;
@@ -148,60 +149,70 @@ static HardLinkInfo *findHardLinkInfo(HardLinkInfo * hlInfo, struct stat *statbu
 }
 
 /* Put an octal string into the specified buffer.
- * The number is zero and space padded and possibly null padded.
- * Returns TRUE if successful.  */
-static int putOctal(char *cp, int len, long value)
+ * The number is zero padded and possibly null terminated.
+ * Returns TRUE if successful. - DISABLED (no caller ever checked)  */
+static void putOctal(char *cp, int len, long long value)
 {
        int tempLength;
-       char tempBuffer[32];
+       /* long long for the sake of storing lengths of 4Gb+ files */
+       /* (we are bust anyway after 64Gb: it doesn't fit into the field) */
+       char tempBuffer[sizeof(long long)*3+1];
        char *tempString = tempBuffer;
 
-       /* Create a string of the specified length with an initial space,
+       /* Create a string of the specified length with
         * leading zeroes and the octal number, and a trailing null.  */
-       sprintf(tempString, "%0*lo", len - 1, value);
-
-       /* If the string is too large, suppress the leading space.  */
-       tempLength = strlen(tempString) + 1;
-       if (tempLength > len) {
-               tempLength--;
-               tempString++;
+       tempLength = sprintf(tempBuffer, "%0*llo", len - 1, value);
+
+       /* If the string is too large, suppress leading 0's.  */
+       /* If that is not enough, drop trailing null.  */
+       tempLength -= len; /* easier to do checks */
+       while (tempLength >= 0) {
+               if (tempString[0] != '0') {
+                       if (!tempLength) {
+                               /* 1234 barely fits in 4 chars (w/o EOL '\0') */
+                               break;
+                       }
+                       /* 12345 doesn't fit into 4 chars */
+                       return /*FALSE*/;
+               }
+               tempLength--; /* still have leading '0', */
+               tempString++; /* can afford to drop it but retain EOL '\0' */
        }
 
-       /* If the string is still too large, suppress the trailing null.  */
-       if (tempLength > len)
-               tempLength--;
-
-       /* If the string is still too large, fail.  */
-       if (tempLength > len)
-               return FALSE;
-
        /* Copy the string to the field.  */
        memcpy(cp, tempString, len);
-
-       return TRUE;
+       /*return TRUE;*/
 }
 
 /* Write out a tar header for the specified file/directory/whatever */
+void BUG_tar_header_size(void);
 static int writeTarHeader(struct TarBallInfo *tbInfo,
                const char *header_name, const char *fileName, struct stat *statbuf)
 {
-       long chksum = 0;
        struct TarHeader header;
-       const unsigned char *cp = (const unsigned char *) &header;
-       ssize_t size = sizeof(struct TarHeader);
+       const unsigned char *cp;
+       int chksum;
+       int size;
 
-       bzero(&header, size);
+       if (sizeof(header) != 512)
+               BUG_tar_header_size();
+
+       bzero(&header, sizeof(struct TarHeader));
 
        safe_strncpy(header.name, header_name, sizeof(header.name));
 
-       putOctal(header.mode, sizeof(header.mode), statbuf->st_mode);
+       /* POSIX says to mask mode with 07777. */
+       putOctal(header.mode, sizeof(header.mode), statbuf->st_mode & 07777);
        putOctal(header.uid, sizeof(header.uid), statbuf->st_uid);
        putOctal(header.gid, sizeof(header.gid), statbuf->st_gid);
-       putOctal(header.size, sizeof(header.size), 0);  /* Regular file size is handled later */
+       if (sizeof(header.size) != sizeof("00000000000"))
+               BUG_tar_header_size();
+       strcpy(header.size, "00000000000"); /* Regular file size is handled later */
        putOctal(header.mtime, sizeof(header.mtime), statbuf->st_mtime);
        strcpy(header.magic, "ustar  ");
 
        /* Enter the user and group names (default to root if it fails) */
+//cache!!!
        if (bb_getpwuid(header.uname, statbuf->st_uid, sizeof(header.uname)) == NULL)
                strcpy(header.uname, "root");
        if (bb_getgrgid(header.gname, statbuf->st_gid, sizeof(header.gname)) == NULL)
@@ -214,11 +225,18 @@ static int writeTarHeader(struct TarBallInfo *tbInfo,
                                sizeof(header.linkname));
        } else if (S_ISLNK(statbuf->st_mode)) {
                char *lpath = xreadlink(fileName);
-
                if (!lpath)             /* Already printed err msg inside xreadlink() */
                        return FALSE;
                header.typeflag = SYMTYPE;
                strncpy(header.linkname, lpath, sizeof(header.linkname));
+               /* If it is larger than 100 bytes, bail out */
+               if (header.linkname[sizeof(header.linkname)-1] /* at least 100? */
+                && lpath[sizeof(header.linkname)] /* and 101th is also not zero */
+               ) {
+                       free(lpath);
+                       bb_error_msg("names longer than "NAME_SIZE_STR" chars not supported");
+                       return FALSE;
+               }
                free(lpath);
        } else if (S_ISDIR(statbuf->st_mode)) {
                header.typeflag = DIRTYPE;
@@ -252,9 +270,10 @@ static int writeTarHeader(struct TarBallInfo *tbInfo,
         * digits, followed by a null like the other fields... */
        memset(header.chksum, ' ', sizeof(header.chksum));
        cp = (const unsigned char *) &header;
-       while (size-- > 0)
-               chksum += *cp++;
-       putOctal(header.chksum, 7, chksum);
+       chksum = 0;
+       size = sizeof(struct TarHeader);
+       do { chksum += *cp++; } while (--size);
+       putOctal(header.chksum, sizeof(header.chksum)-1, chksum);
 
        /* Now write the header out to disk */
        xwrite(tbInfo->tarFd, &header, sizeof(struct TarHeader));
@@ -348,22 +367,21 @@ static int writeFileToTarball(const char *fileName, struct stat *statbuf,
        }
 
        if (strlen(fileName) >= NAME_SIZE) {
-               bb_error_msg(bb_msg_name_longer_than_foo, NAME_SIZE);
+               bb_error_msg("names longer than "NAME_SIZE_STR" chars not supported");
                return TRUE;
        }
 
        if (header_name[0] == '\0')
                return TRUE;
 
-       if (ENABLE_FEATURE_TAR_FROM &&
-                       exclude_file(tbInfo->excludeList, header_name)) {
+       if (exclude_file(tbInfo->excludeList, header_name))
                return SKIP;
-       }
 
        /* Is this a regular file? */
-       if ((tbInfo->hlInfo == NULL) && (S_ISREG(statbuf->st_mode))) {
+       if (tbInfo->hlInfo == NULL && S_ISREG(statbuf->st_mode)) {
                /* open the file we want to archive, and make sure all is well */
-               if ((inputFileFd = open(fileName, O_RDONLY)) < 0) {
+               inputFileFd = open(fileName, O_RDONLY);
+               if (inputFileFd < 0) {
                        bb_perror_msg("%s: cannot open", fileName);
                        return FALSE;
                }
@@ -383,7 +401,8 @@ static int writeFileToTarball(const char *fileName, struct stat *statbuf,
                close(inputFileFd);
 
                /* Pad the file up to the tar block size */
-               readSize = (TAR_BLOCK_SIZE - readSize) & (TAR_BLOCK_SIZE-1);
+               /* (a few tricks here in the name of code size) */
+               readSize = (-(int)readSize) & (TAR_BLOCK_SIZE-1);
                bzero(bb_common_bufsiz1, readSize);
                xwrite(tbInfo->tarFd, bb_common_bufsiz1, readSize);
        }
@@ -423,10 +442,10 @@ static int writeTarFile(const int tar_fd, const int verboseFlag,
                signal(SIGPIPE, SIG_IGN);       /* we only want EPIPE on errors */
 
 # if __GNUC__
-                       /* Avoid vfork clobbering */
-                       (void) &include;
-                       (void) &errorFlag;
-                       (void) &zip_exec;
+               /* Avoid vfork clobbering */
+               (void) &include;
+               (void) &errorFlag;
+               (void) &zip_exec;
 # endif
 
                gzipPid = vfork();
@@ -498,8 +517,8 @@ static int writeTarFile(const int tar_fd, const int verboseFlag,
        if (errorFlag)
                bb_error_msg("error exit delayed from previous errors");
 
-       if (gzipPid && waitpid(gzipPid, NULL, 0)==-1)
-               bb_error_msg("cannot wait");
+       if (gzipPid && waitpid(gzipPid, NULL, 0) == -1)
+               bb_error_msg("waitpid failed");
 
        return !errorFlag;
 }
@@ -634,7 +653,7 @@ static char get_header_tar_Z(archive_handle_t *archive_handle)
 #define TAR_OPT_STR_NOPRESERVE            "\203\213"
 #define TAR_OPT_AFTER_NOPRESERVE          TAR_OPT_AFTER_COMPRESS + 2
 
-static const char tar_options[]="txC:f:Opvk" \
+static const char tar_options[] = "txC:f:Opvk" \
        TAR_OPT_STR_CREATE \
        TAR_OPT_STR_BZIP2 \
        TAR_OPT_STR_LZMA \
@@ -645,38 +664,38 @@ static const char tar_options[]="txC:f:Opvk" \
 
 #ifdef CONFIG_FEATURE_TAR_LONG_OPTIONS
 static const struct option tar_long_options[] = {
-       { "list",                               0,      NULL,   't' },
-       { "extract",                    0,      NULL,   'x' },
-       { "directory",                  1,      NULL,   'C' },
-       { "file",                               1,      NULL,   'f' },
-       { "to-stdout",                  0,      NULL,   'O' },
-       { "same-permissions",   0,      NULL,   'p' },
-       { "verbose",                    0,      NULL,   'v' },
-       { "keep-old",                   0,      NULL,   'k' },
-       { "no-same-owner",              0,      NULL,   '\203' },
-       { "no-same-permissions",0,      NULL,   '\213' },
+       { "list",               0,  NULL,   't' },
+       { "extract",            0,  NULL,   'x' },
+       { "directory",          1,  NULL,   'C' },
+       { "file",               1,  NULL,   'f' },
+       { "to-stdout",          0,  NULL,   'O' },
+       { "same-permissions",   0,  NULL,   'p' },
+       { "verbose",            0,  NULL,   'v' },
+       { "keep-old",           0,  NULL,   'k' },
+       { "no-same-owner",      0,  NULL,   '\203' },
+       { "no-same-permissions",0,  NULL,   '\213' },
 # ifdef CONFIG_FEATURE_TAR_CREATE
-       { "create",                             0,      NULL,   'c' },
-       { "dereference",                0,      NULL,   'h' },
+       { "create",             0,  NULL,   'c' },
+       { "dereference",        0,  NULL,   'h' },
 # endif
 # ifdef CONFIG_FEATURE_TAR_BZIP2
-       { "bzip2",                              0,      NULL,   'j' },
+       { "bzip2",              0,  NULL,   'j' },
 # endif
 # ifdef CONFIG_FEATURE_TAR_LZMA
-       { "lzma",                               0,      NULL,   'a' },
+       { "lzma",               0,  NULL,   'a' },
 # endif
 # ifdef CONFIG_FEATURE_TAR_FROM
-       { "files-from",                 1,      NULL,   'T' },
-       { "exclude-from",               1,      NULL,   'X' },
-       { "exclude",                    1,      NULL,   '\n' },
+       { "files-from",         1,  NULL,   'T' },
+       { "exclude-from",       1,  NULL,   'X' },
+       { "exclude",            1,  NULL,   '\n' },
 # endif
 # ifdef CONFIG_FEATURE_TAR_GZIP
-       { "gzip",                               0,      NULL,   'z' },
+       { "gzip",               0,  NULL,   'z' },
 # endif
 # ifdef CONFIG_FEATURE_TAR_COMPRESS
-       { "compress",                   0,      NULL,   'Z' },
+       { "compress",           0,  NULL,   'Z' },
 # endif
-       { 0,                                    0, 0, 0 }
+       { 0,                    0, 0, 0 }
 };
 #else
 #define tar_long_options       0
@@ -712,22 +731,23 @@ int tar_main(int argc, char **argv)
                                );
 
        if (opt & CTX_TEST) {
-               if ((tar_handle->action_header == header_list) ||
-                       (tar_handle->action_header == header_verbose_list))
-               {
+               if (tar_handle->action_header == header_list
+                || tar_handle->action_header == header_verbose_list
+               {
                        tar_handle->action_header = header_verbose_list;
-               } else tar_handle->action_header = header_list;
+               } else
+                       tar_handle->action_header = header_list;
        }
-       if((opt & CTX_EXTRACT) && tar_handle->action_data != data_extract_to_stdout)
+       if ((opt & CTX_EXTRACT) && tar_handle->action_data != data_extract_to_stdout)
                tar_handle->action_data = data_extract_all;
 
        if (opt & TAR_OPT_2STDOUT)
                tar_handle->action_data = data_extract_to_stdout;
 
        if (opt & TAR_OPT_VERBOSE) {
-               if ((tar_handle->action_header == header_list) ||
-                       (tar_handle->action_header == header_verbose_list))
-               {
+               if (tar_handle->action_header == header_list
+                || tar_handle->action_header == header_verbose_list
+               {
                        tar_handle->action_header = header_verbose_list;
                } else
                        tar_handle->action_header = header_list;
@@ -782,7 +802,7 @@ int tar_main(int argc, char **argv)
                optind++;
        }
 
-       if ((tar_handle->accept) || (tar_handle->reject))
+       if (tar_handle->accept || tar_handle->reject)
                tar_handle->filter = filter_accept_reject_list;
 
        /* Open the tar file */
@@ -796,8 +816,9 @@ int tar_main(int argc, char **argv)
                                bb_error_msg_and_die("empty archive");
 
                        tar_stream = stdout;
-                       flags = O_WRONLY | O_CREAT | O_EXCL;
-                       unlink(tar_filename);
+                       /* Mimicking GNU tar 1.15.1: */
+                       flags = O_WRONLY|O_CREAT|O_TRUNC;
+               /* was doing unlink; open(O_WRONLY|O_CREAT|O_EXCL); why? */
                } else {
                        tar_stream = stdin;
                        flags = O_RDONLY;
@@ -824,9 +845,9 @@ int tar_main(int argc, char **argv)
                if (ENABLE_FEATURE_TAR_BZIP2 && get_header_ptr == get_header_tar_bz2)
                        zipMode = 2;
 
-               if ((tar_handle->action_header == header_list) ||
-                               (tar_handle->action_header == header_verbose_list))
-               {
+               if (tar_handle->action_header == header_list
+                || tar_handle->action_header == header_verbose_list
+               {
                        verboseFlag = TRUE;
                }
                writeTarFile(tar_handle->src_fd, verboseFlag, opt & TAR_OPT_DEREFERENCE,
@@ -839,9 +860,10 @@ int tar_main(int argc, char **argv)
                /* Check that every file that should have been extracted was */
                while (tar_handle->accept) {
                        if (!find_list_entry(tar_handle->reject, tar_handle->accept->data)
-                               && !find_list_entry(tar_handle->passed, tar_handle->accept->data))
-                       {
-                               bb_error_msg_and_die("%s: not found in archive", tar_handle->accept->data);
+                        && !find_list_entry(tar_handle->passed, tar_handle->accept->data)
+                       ) {
+                               bb_error_msg_and_die("%s: not found in archive",
+                                       tar_handle->accept->data);
                        }
                        tar_handle->accept = tar_handle->accept->link;
                }
@@ -850,5 +872,5 @@ int tar_main(int argc, char **argv)
        if (ENABLE_FEATURE_CLEAN_UP && tar_handle->src_fd != STDIN_FILENO)
                close(tar_handle->src_fd);
 
-       return(EXIT_SUCCESS);
+       return EXIT_SUCCESS;
 }
index c96ef6f946ad23deae555b34ac3ac7f552d2a0e5..2ccb6e7bb699c3b95747f74d2acc6a02683867b5 100644 (file)
@@ -610,7 +610,6 @@ extern const char bb_msg_memory_exhausted[];
 extern const char bb_msg_invalid_date[];
 extern const char bb_msg_read_error[];
 extern const char bb_msg_write_error[];
-extern const char bb_msg_name_longer_than_foo[];
 extern const char bb_msg_unknown[];
 extern const char bb_msg_can_not_create_raw_socket[];
 extern const char bb_msg_perm_denied_are_you_root[];
index e3c0faf9522925f452a86db212449996a81ca5bf..c640faf5b4a96ca661bf916c23afe3d7bce3042e 100644 (file)
@@ -19,7 +19,6 @@ const char bb_msg_memory_exhausted[] = "memory exhausted";
 const char bb_msg_invalid_date[] = "invalid date '%s'";
 const char bb_msg_write_error[] = "write error";
 const char bb_msg_read_error[] = "read error";
-const char bb_msg_name_longer_than_foo[] = "names longer than %d chars not supported";
 const char bb_msg_unknown[] = "(unknown)";
 const char bb_msg_can_not_create_raw_socket[] = "can't create raw socket";
 const char bb_msg_perm_denied_are_you_root[] = "permission denied. (are you root?)";