X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=archival%2Ftar.c;h=5d9e870fa3dab3e0c794bb65ffe4c0f66db606dd;hb=03721973851afbe02bbc1cdc56ee6002631c4df6;hp=ab4d1f26626e29b3ed1377c1d50a443310839ff2;hpb=c1ef7bdd8d002ae0889efcf883d0e1b7faa938d4;p=oweals%2Fbusybox.git diff --git a/archival/tar.c b/archival/tar.c index ab4d1f266..5d9e870fa 100644 --- a/archival/tar.c +++ b/archival/tar.c @@ -19,36 +19,20 @@ * * Based in part on the tar implementation from busybox-0.28 * Copyright (C) 1995 Bruce Perens - * This is free software under the GNU General Public License. * - * Licensed under GPL v2 (or later), see file LICENSE in this tarball. + * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include /* major() and minor() */ -#include "unarchive.h" #include "busybox.h" +#include "unarchive.h" +#include +#include #ifdef CONFIG_FEATURE_TAR_CREATE /* Tar file constants */ -# define TAR_MAGIC "ustar" /* ustar and a null */ -# define TAR_VERSION " " /* Be compatable with GNU tar format */ #define TAR_BLOCK_SIZE 512 -#define TAR_MAGIC_LEN 6 -#define TAR_VERSION_LEN 2 /* POSIX tar Header Block, from POSIX 1003.1-1990 */ #define NAME_SIZE 100 @@ -89,7 +73,6 @@ struct HardLinkInfo { /* Some info to be carried along when creating a new tarball */ struct TarBallInfo { - char *fileName; /* File name of the tarball */ int tarFd; /* Open-for-write file descriptor for the tarball */ struct stat statBuf; /* Stat info for the tarball, letting @@ -120,20 +103,20 @@ enum TarFileType { typedef enum TarFileType TarFileType; /* Might be faster (and bigger) if the dev/ino were stored in numeric order;) */ -static inline void addHardLinkInfo(HardLinkInfo ** hlInfoHeadPtr, +static void addHardLinkInfo(HardLinkInfo ** hlInfoHeadPtr, struct stat *statbuf, - const char *name) + const char *fileName) { /* Note: hlInfoHeadPtr can never be NULL! */ HardLinkInfo *hlInfo; - hlInfo = (HardLinkInfo *) xmalloc(sizeof(HardLinkInfo) + strlen(name)); + hlInfo = xmalloc(sizeof(HardLinkInfo) + strlen(fileName)); hlInfo->next = *hlInfoHeadPtr; *hlInfoHeadPtr = hlInfo; hlInfo->dev = statbuf->st_dev; hlInfo->ino = statbuf->st_ino; hlInfo->linkCount = statbuf->st_nlink; - strcpy(hlInfo->name, name); + strcpy(hlInfo->name, fileName); } static void freeHardLinkInfo(HardLinkInfo ** hlInfoHeadPtr) @@ -154,14 +137,14 @@ static void freeHardLinkInfo(HardLinkInfo ** hlInfoHeadPtr) } /* Might be faster (and bigger) if the dev/ino were stored in numeric order;) */ -static inline HardLinkInfo *findHardLinkInfo(HardLinkInfo * hlInfo, struct stat *statbuf) +static HardLinkInfo *findHardLinkInfo(HardLinkInfo * hlInfo, struct stat *statbuf) { while (hlInfo) { if ((statbuf->st_ino == hlInfo->ino) && (statbuf->st_dev == hlInfo->dev)) break; hlInfo = hlInfo->next; } - return (hlInfo); + return hlInfo; } /* Put an octal string into the specified buffer. @@ -199,25 +182,24 @@ static int putOctal(char *cp, int len, long value) } /* Write out a tar header for the specified file/directory/whatever */ -static inline int writeTarHeader(struct TarBallInfo *tbInfo, - const char *header_name, const char *real_name, struct stat *statbuf) +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); - memset(&header, 0, size); + bzero(&header, size); - strncpy(header.name, header_name, sizeof(header.name)); + safe_strncpy(header.name, header_name, sizeof(header.name)); putOctal(header.mode, sizeof(header.mode), statbuf->st_mode); 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 */ putOctal(header.mtime, sizeof(header.mtime), statbuf->st_mtime); - strncpy(header.magic, TAR_MAGIC TAR_VERSION, - TAR_MAGIC_LEN + TAR_VERSION_LEN); + strcpy(header.magic, "ustar "); /* Enter the user and group names (default to root if it fails) */ if (bb_getpwuid(header.uname, statbuf->st_uid, sizeof(header.uname)) == NULL) @@ -231,10 +213,10 @@ static inline int writeTarHeader(struct TarBallInfo *tbInfo, strncpy(header.linkname, tbInfo->hlInfo->name, sizeof(header.linkname)); } else if (S_ISLNK(statbuf->st_mode)) { - char *lpath = xreadlink(real_name); + char *lpath = xreadlink(fileName); if (!lpath) /* Already printed err msg inside xreadlink() */ - return (FALSE); + return FALSE; header.typeflag = SYMTYPE; strncpy(header.linkname, lpath, sizeof(header.linkname)); free(lpath); @@ -259,8 +241,8 @@ static inline int writeTarHeader(struct TarBallInfo *tbInfo, header.typeflag = REGTYPE; putOctal(header.size, sizeof(header.size), statbuf->st_size); } else { - bb_error_msg("%s: Unknown file type", real_name); - return (FALSE); + bb_error_msg("%s: unknown file type", fileName); + return FALSE; } /* Calculate and store the checksum (i.e., the sum of all of the bytes of @@ -275,16 +257,8 @@ static inline int writeTarHeader(struct TarBallInfo *tbInfo, putOctal(header.chksum, 7, chksum); /* Now write the header out to disk */ - if ((size = - bb_full_write(tbInfo->tarFd, (char *) &header, - sizeof(struct TarHeader))) < 0) { - bb_error_msg(bb_msg_io_error, real_name); - return (FALSE); - } - /* Pad the header up to the tar block size */ - for (; size < TAR_BLOCK_SIZE; size++) { - write(tbInfo->tarFd, "\0", 1); - } + xwrite(tbInfo->tarFd, &header, sizeof(struct TarHeader)); + /* Now do the verbose thing (or not) */ if (tbInfo->verboseFlag) { @@ -296,11 +270,11 @@ static inline int writeTarHeader(struct TarBallInfo *tbInfo, fprintf(vbFd, "%s\n", header.name); } - return (TRUE); + return TRUE; } # ifdef CONFIG_FEATURE_TAR_FROM -static inline int exclude_file(const llist_t *excluded_files, const char *file) +static int exclude_file(const llist_t *excluded_files, const char *file) { while (excluded_files) { if (excluded_files->data[0] == '/') { @@ -334,11 +308,11 @@ static int writeFileToTarball(const char *fileName, struct stat *statbuf, int inputFileFd = -1; /* - ** Check to see if we are dealing with a hard link. - ** If so - - ** Treat the first occurance of a given dev/inode as a file while - ** treating any additional occurances as hard links. This is done - ** by adding the file information to the HardLinkInfo linked list. + * Check to see if we are dealing with a hard link. + * If so - + * Treat the first occurance of a given dev/inode as a file while + * treating any additional occurances as hard links. This is done + * by adding the file information to the HardLinkInfo linked list. */ tbInfo->hlInfo = NULL; if (statbuf->st_nlink > 1) { @@ -350,7 +324,7 @@ static int writeFileToTarball(const char *fileName, struct stat *statbuf, /* It is against the rules to archive a socket */ if (S_ISSOCK(statbuf->st_mode)) { bb_error_msg("%s: socket ignored", fileName); - return (TRUE); + return TRUE; } /* It is a bad idea to store the archive we are in the process of creating, @@ -359,7 +333,7 @@ static int writeFileToTarball(const char *fileName, struct stat *statbuf, if (tbInfo->statBuf.st_dev == statbuf->st_dev && tbInfo->statBuf.st_ino == statbuf->st_ino) { bb_error_msg("%s: file is the archive; skipping", fileName); - return (TRUE); + return TRUE; } header_name = fileName; @@ -367,7 +341,7 @@ static int writeFileToTarball(const char *fileName, struct stat *statbuf, static int alreadyWarned = FALSE; if (alreadyWarned == FALSE) { - bb_error_msg("Removing leading '/' from member names"); + bb_error_msg("removing leading '/' from member names"); alreadyWarned = TRUE; } header_name++; @@ -375,7 +349,7 @@ 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); - return (TRUE); + return TRUE; } if (header_name[0] == '\0') @@ -388,21 +362,20 @@ static int writeFileToTarball(const char *fileName, struct stat *statbuf, /* Is this a regular file? */ 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) { - bb_perror_msg("%s: Cannot open", fileName); - return (FALSE); + bb_perror_msg("%s: cannot open", fileName); + return FALSE; } } /* Add an entry to the tarball */ if (writeTarHeader(tbInfo, header_name, fileName, statbuf) == FALSE) { - return (FALSE); + return FALSE; } /* If it was a regular file, write out the body */ - if (inputFileFd >= 0 ) { + if (inputFileFd >= 0) { ssize_t readSize = 0; /* write the file to the archive */ @@ -410,21 +383,20 @@ static int writeFileToTarball(const char *fileName, struct stat *statbuf, close(inputFileFd); /* Pad the file up to the tar block size */ - for (; (readSize % TAR_BLOCK_SIZE) != 0; readSize++) - write(tbInfo->tarFd, "\0", 1); + readSize = (TAR_BLOCK_SIZE - readSize) & (TAR_BLOCK_SIZE-1); + bzero(bb_common_bufsiz1, readSize); + xwrite(tbInfo->tarFd, bb_common_bufsiz1, readSize); } - return (TRUE); + return TRUE; } -static inline int writeTarFile(const int tar_fd, const int verboseFlag, +static int writeTarFile(const int tar_fd, const int verboseFlag, const unsigned long dereferenceFlag, const llist_t *include, const llist_t *exclude, const int gzip) { pid_t gzipPid = 0; - int errorFlag = FALSE; - ssize_t size; struct TarBallInfo tbInfo; tbInfo.hlInfoHead = NULL; @@ -436,7 +408,7 @@ static inline int writeTarFile(const int tar_fd, const int verboseFlag, /* Store the stat info for the tarball's file, so * can avoid including the tarball into itself.... */ if (fstat(tbInfo.tarFd, &tbInfo.statBuf) < 0) - bb_perror_msg_and_die("Couldnt stat tar file"); + bb_perror_msg_and_die("cannot stat tar file"); if ((ENABLE_FEATURE_TAR_GZIP || ENABLE_FEATURE_TAR_BZIP2) && gzip) { int gzipDataPipe[2] = { -1, -1 }; @@ -446,7 +418,7 @@ static inline int writeTarFile(const int tar_fd, const int verboseFlag, if (pipe(gzipDataPipe) < 0 || pipe(gzipStatusPipe) < 0) - bb_perror_msg_and_die("create pipe"); + bb_perror_msg_and_die("pipe"); signal(SIGPIPE, SIG_IGN); /* we only want EPIPE on errors */ @@ -481,7 +453,7 @@ static inline int writeTarFile(const int tar_fd, const int verboseFlag, while (1) { char buf; - int n = bb_full_read(gzipStatusPipe[0], &buf, 1); + int n = full_read(gzipStatusPipe[0], &buf, 1); if (n == 0 && vfork_exec_errno != 0) { errno = vfork_exec_errno; @@ -508,8 +480,8 @@ static inline int writeTarFile(const int tar_fd, const int verboseFlag, include = include->link; } /* Write two empty blocks to the end of the archive */ - for (size = 0; size < (2 * TAR_BLOCK_SIZE); size++) - write(tbInfo.tarFd, "\0", 1); + bzero(bb_common_bufsiz1, 2*TAR_BLOCK_SIZE); + xwrite(tbInfo.tarFd, bb_common_bufsiz1, 2*TAR_BLOCK_SIZE); /* To be pedantically correct, we would check if the tarball * is smaller than 20 tar blocks, and pad it if it was smaller, @@ -547,12 +519,16 @@ static llist_t *append_file_list_to_list(llist_t *list) llist_t *newlist = NULL; while (cur) { - src_stream = bb_xfopen(cur->data, "r"); + src_stream = xfopen(cur->data, "r"); tmp = cur; cur = cur->link; free(tmp); - while ((line = bb_get_chomped_line_from_file(src_stream)) != NULL) - newlist = llist_add_to(newlist, line); + while ((line = bb_get_chomped_line_from_file(src_stream)) != NULL) { + char *filename_ptr = last_char_is(line, '/'); + if (filename_ptr > line) + *filename_ptr = '\0'; + llist_add_to(&newlist, line); + } fclose(src_stream); } return newlist; @@ -568,15 +544,16 @@ static char get_header_tar_Z(archive_handle_t *archive_handle) archive_handle->seek = seek_by_char; /* do the decompression, and cleanup */ - if (bb_xread_char(archive_handle->src_fd) != 0x1f || - bb_xread_char(archive_handle->src_fd) != 0x9d) + if (xread_char(archive_handle->src_fd) != 0x1f || + xread_char(archive_handle->src_fd) != 0x9d) { - bb_error_msg_and_die("Invalid magic"); + bb_error_msg_and_die("invalid magic"); } archive_handle->src_fd = open_transformer(archive_handle->src_fd, uncompress); archive_handle->offset = 0; - while (get_header_tar(archive_handle) == EXIT_SUCCESS); + while (get_header_tar(archive_handle) == EXIT_SUCCESS) + /* nothing */; /* Can only do one file at a time */ return(EXIT_FAILURE); @@ -597,7 +574,7 @@ static char get_header_tar_Z(archive_handle_t *archive_handle) #define TAR_OPT_AFTER_START 8 #define CTX_CREATE (1 << (TAR_OPT_AFTER_START)) -#define TAR_OPT_DEREFERNCE (1 << (TAR_OPT_AFTER_START + 1)) +#define TAR_OPT_DEREFERENCE (1 << (TAR_OPT_AFTER_START + 1)) #ifdef CONFIG_FEATURE_TAR_CREATE # define TAR_OPT_STR_CREATE "ch" # define TAR_OPT_AFTER_CREATE TAR_OPT_AFTER_START + 2 @@ -801,7 +778,7 @@ int tar_main(int argc, char **argv) if (filename_ptr > argv[optind]) *filename_ptr = '\0'; - tar_handle->accept = llist_add_to(tar_handle->accept, argv[optind]); + llist_add_to(&(tar_handle->accept), argv[optind]); optind++; } @@ -830,12 +807,12 @@ int tar_main(int argc, char **argv) tar_handle->src_fd = fileno(tar_stream); tar_handle->seek = seek_by_char; } else { - tar_handle->src_fd = bb_xopen(tar_filename, flags); + tar_handle->src_fd = xopen3(tar_filename, flags, 0666); } } - if ((base_dir) && (chdir(base_dir))) - bb_perror_msg_and_die("Couldnt chdir to %s", base_dir); + if (base_dir) + xchdir(base_dir); /* create an archive */ if (ENABLE_FEATURE_TAR_CREATE && (opt & CTX_CREATE)) { @@ -852,17 +829,19 @@ int tar_main(int argc, char **argv) { verboseFlag = TRUE; } - writeTarFile(tar_handle->src_fd, verboseFlag, opt & TAR_OPT_DEREFERNCE, tar_handle->accept, + writeTarFile(tar_handle->src_fd, verboseFlag, opt & TAR_OPT_DEREFERENCE, + tar_handle->accept, tar_handle->reject, zipMode); } else { - while (get_header_ptr(tar_handle) == EXIT_SUCCESS); + while (get_header_ptr(tar_handle) == EXIT_SUCCESS) + /* nothing */; /* 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); + bb_error_msg_and_die("%s: not found in archive", tar_handle->accept->data); } tar_handle->accept = tar_handle->accept->link; }