From 376ce1e775a97a01f1c454497fbe34d326043328 Mon Sep 17 00:00:00 2001 From: Denis Vlasenko Date: Fri, 24 Nov 2006 14:51:01 +0000 Subject: [PATCH] tar: * 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 | 167 ++++++++++-------- archival/tar.c | 232 ++++++++++++++----------- include/libbb.h | 1 - libbb/messages.c | 1 - 4 files changed, 220 insertions(+), 181 deletions(-) diff --git a/archival/libunarchive/get_header_tar.c b/archival/libunarchive/get_header_tar.c index f78377e28..b5cae9f12 100644 --- a/archival/libunarchive/get_header_tar.c +++ b/archival/libunarchive/get_header_tar.c @@ -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; diff --git a/archival/tar.c b/archival/tar.c index db812e0f4..911c2d35e 100644 --- a/archival/tar.c +++ b/archival/tar.c @@ -35,25 +35,26 @@ #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; } diff --git a/include/libbb.h b/include/libbb.h index c96ef6f94..2ccb6e7bb 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -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[]; diff --git a/libbb/messages.c b/libbb/messages.c index e3c0faf95..c640faf5b 100644 --- a/libbb/messages.c +++ b/libbb/messages.c @@ -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?)"; -- 2.25.1