X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=archival%2Far.c;h=983b5ae2cd8ef965fdb5af7f27737b369b0a3043;hb=999af20d3e025741197b8aebea9aeb4e435c9ebf;hp=253f3348a51dec812717133ce7bd705816ae7095;hpb=86ab8a32bd63b2f2a73bdcead8e2bb037589e175;p=oweals%2Fbusybox.git diff --git a/archival/ar.c b/archival/ar.c index 253f3348a..983b5ae2c 100644 --- a/archival/ar.c +++ b/archival/ar.c @@ -1,9 +1,9 @@ /* vi: set sw=4 ts=4: */ /* - * Mini ar implementation for busybox + * Mini ar implementation for busybox * * Copyright (C) 2000 by Glenn McGrath - * Written by Glenn McGrath 1 June 2000 + * Written by Glenn McGrath 1 June 2000 * * Based in part on BusyBox tar, Debian dpkg-deb and GNU ar. * @@ -21,257 +21,92 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * + * There is no single standard to adhere to so ar may not portable + * between different systems + * http://www.unix-systems.org/single_unix_specification_v2/xcu/ar.html */ - -#include #include -#include -#include -#include "internal.h" - -#define AR_BLOCK_SIZE 60 -#define BB_DECLARE_EXTERN -#define bb_need_io_error -#include "messages.c" - -struct ArHeader { /* Byte Offset */ - char ar_name[16]; /* 0-15 */ - char ar_date[12]; /* 16-27 */ - char ar_uid[6], ar_gid[6]; /* 28-39 */ - char ar_mode[8]; /* 40-47 */ - char ar_size[10]; /* 48-57 */ - char ar_fmag[2]; /* 58-59 */ -}; -typedef struct ArHeader ArHeader; - -struct ArInfo { - char name[17]; /* File name */ - time_t date; /* long int, No of seconds since epoch */ - uid_t uid; /* unsigned int, Numeric UID */ - gid_t gid; /* unsigned int, Numeric GID */ - mode_t mode; /* unsigned int, Unix mode */ - size_t size; /* int, Size of the file */ -}; -typedef struct ArInfo ArInfo; +#include +#include +#include +#include +#include +#include -static const char ar_usage[] = "ar [optxvV] archive [filenames] \n" -#ifndef BB_FEATURE_TRIVIAL_HELP - "\nExtract or list files from an ar archive.\n\n" - "Options:\n" - "\to\t\tpreserve original dates\n" - "\tp\t\textract to stdout\n" - "\tt\t\tlist\n" - "\tx\t\textract\n" - "\tv\t\tverbosely list files processed\n" -#endif - ; +#include "unarchive.h" +#include "busybox.h" -static void displayContents(struct ArInfo *entry, int funct) +static void header_verbose_list_ar(const file_header_t *file_header) { - /* TODO convert mode to string */ - if ((funct & 2) == 2) - printf("%i %i/%i %6i %s ", entry->mode, entry->uid, entry->gid, - entry->size, timeString(entry->date)); - printf("%s\n", entry->name); + const char *mode = bb_mode_string(file_header->mode); + char *mtime; + + mtime = ctime(&file_header->mtime); + mtime[16] = ' '; + memmove(&mtime[17], &mtime[20], 4); + mtime[21] = '\0'; + printf("%s %d/%d%7d %s %s\n", &mode[1], file_header->uid, file_header->gid, (int) file_header->size, &mtime[4], file_header->name); } -/* Converts to new typed struct */ -static int readArHeader(struct ArHeader *rawHeader, struct ArInfo *header) -{ - int count2; - int count; +#define AR_CTX_PRINT 0x01 +#define AR_CTX_LIST 0x02 +#define AR_CTX_EXTRACT 0x04 +#define AR_OPT_PRESERVE_DATE 0x08 +#define AR_OPT_VERBOSE 0x10 +#define AR_OPT_CREATE 0x20 +#define AR_OPT_INSERT 0x40 - for (count = 0; count < 16; count++) { - if (rawHeader->ar_name[count] == ' ') { - for (count2 = count; count2 < 16; count2++) - if (!isspace(rawHeader->ar_name[count2])) - break; - if (count2 >= 16) - break; - } - if (rawHeader->ar_name[count] == '/') - break; - header->name[count] = rawHeader->ar_name[count]; - } - header->name[count] = '\0'; - header->date = atoi(rawHeader->ar_date); - header->uid = atoi(rawHeader->ar_uid); - header->gid = atoi(rawHeader->ar_gid); - header->mode = atoi(rawHeader->ar_mode); - header->size = atoi(rawHeader->ar_size); - return (TRUE); -} - -/* - * Copy size bytes from current position if srcFd to current position in dstFd - * taken from tarExtractRegularFile in tar.c - * could be used for ar, tar and copyFile . - */ -static int copySubFile(int srcFd, int dstFd, int copySize) +extern int ar_main(int argc, char **argv) { - int readSize, writeSize, doneSize; - char buffer[BUFSIZ]; - - while (copySize > 0) { - if (copySize > BUFSIZ) - readSize = BUFSIZ; - else - readSize = copySize; - writeSize = fullRead(srcFd, buffer, readSize); - if (writeSize <= 0) { - errorMsg(io_error, "copySubFile :", strerror(errno)); - return (FALSE); - } - doneSize = fullWrite(dstFd, buffer, writeSize); - if (doneSize <= 0) { - errorMsg(io_error, "copySubFile :", strerror(errno)); - return (FALSE); - } - copySize -= doneSize; + archive_handle_t *archive_handle; + unsigned long opt; + static const char msg_unsupported_err[] = + "Archive %s not supported. Install binutils 'ar'."; + char magic[8]; + + archive_handle = init_handle(); + + /* Prepend '-' to the first argument if required */ + bb_opt_complementally = "--:p:t:x:-1:?:p--tx:t--px:x--pt"; + opt = bb_getopt_ulflags(argc, argv, "ptxovcr"); + + if (opt & AR_CTX_PRINT) { + archive_handle->action_data = data_extract_to_stdout; } - return (TRUE); -} - -/* - * Need to add checks, stat newfile before creation,change mode from 0777 - * extract to current dir - * dstStat.st_size copied from current position of file pointed to by srcFd - */ -static int extractToFile(int srcFd, const char *path, const char *name, - int size) -{ - int dstFd, temp; - struct stat tmpStat; - char *pathname = NULL; - - if ((temp = isDirectory(path, TRUE, &tmpStat)) != TRUE) { - if (!createPath(path, 0777)) { - fatalError("Cannot extract to specified path"); - return (FALSE); - } + if (opt & AR_CTX_LIST) { + archive_handle->action_header = header_list; } - temp = (strlen(path) + 16); - pathname = (char *) xmalloc(temp); - pathname = strcpy(pathname, path); - pathname = strcat(pathname, &name[0]); - dstFd = device_open(pathname, O_WRONLY | O_CREAT); - pathname = NULL; - temp = copySubFile(srcFd, dstFd, size); - close(dstFd); - return (TRUE); -} - -/* Step through the ar file entries */ -static int readArFile(char **fileNames, int argc, int funct) -{ - int arFd = 0; - int pdates = 0; - int verbose = 0; - int display = 0; - int extract = 0; - int extToStdout = 0; - int status = 0; - int found = 0; - ArHeader rawArHeader; - ArInfo arEntry; - char arVersion[8]; - char *arName; - char *selName[argc - 2]; - int i; - - if ((funct & 1) == 1) - pdates = 1; - if ((funct & 2) == 2) - verbose = 1; - if ((funct & 4) == 4) - display = 1; - if ((funct & 16) == 16) { /* extract to stdout */ - extract = 1; - extToStdout = 1; + if (opt & AR_CTX_EXTRACT) { + archive_handle->action_data = data_extract_all; } - if ((funct & 8) == 8) { /* extract to file */ - extract = 1; + if (opt & AR_OPT_PRESERVE_DATE) { + archive_handle->flags |= ARCHIVE_PRESERVE_DATE; } - arName = fileNames[2]; - for (i = 0; i < (argc - 3); i++) - selName[i] = fileNames[i + 3]; - arFd = open(arName, O_RDONLY); - if (arFd < 0) { - errorMsg("Error opening '%s': %s\n", arName, strerror(errno)); - return (FALSE); + if (opt & AR_OPT_VERBOSE) { + archive_handle->action_header = header_verbose_list_ar; } - if (fullRead(arFd, arVersion, 8) <= 0) { - errorMsg("ar: Unexpected EOF in archive\n"); - return (FALSE); + if (opt & AR_OPT_CREATE) { + bb_error_msg_and_die(msg_unsupported_err, "creation"); } - if (strncmp(arVersion, "!", 7) != 0) { - errorMsg("ar header fails check "); - return (FALSE); + if (opt & AR_OPT_INSERT) { + bb_error_msg_and_die(msg_unsupported_err, "insertion"); } - while ((status = fullRead(arFd, (char *) &rawArHeader, AR_BLOCK_SIZE)) - == AR_BLOCK_SIZE) { - readArHeader(&rawArHeader, &arEntry); - if (display == 1) { - displayContents(&arEntry, funct); - } - if (argc == 3) - found = 1; - else { - found = 0; - for (i = 0; i < (argc - 3); i++) { - if ((status = (strcmp(selName[i], arEntry.name))) == 0) - found = 1; - } - } - if ((extract == 1) && (found == 1)) { - if (extToStdout == 1) { - copySubFile(arFd, fileno(stdout), arEntry.size); - } else { - extractToFile(arFd, "./", arEntry.name, arEntry.size); - } - } else - lseek(arFd, arEntry.size, SEEK_CUR); + archive_handle->src_fd = bb_xopen(argv[optind++], O_RDONLY); + + while (optind < argc) { + archive_handle->filter = filter_accept_list; + archive_handle->accept = llist_add_to(archive_handle->accept, argv[optind++]); } - return (0); -} -extern int ar_main(int argc, char **argv) -{ - int ret = 0; - char *opt_ptr; - char c; - int funct = 0; + archive_xread_all(archive_handle, magic, 7); + if (strncmp(magic, "!", 7) != 0) { + bb_error_msg_and_die("Invalid ar magic"); + } + archive_handle->offset += 7; - if (argc < 2) - usage(ar_usage); + while (get_header_ar(archive_handle) == EXIT_SUCCESS); - opt_ptr = argv[1]; - if (*opt_ptr == '-') - ++opt_ptr; - while ((c = *opt_ptr++) != '\0') { - switch (c) { - case 'o': /* preserver original dates */ - funct = funct | 1; - break; - case 'p': /* extract to stdout */ - funct = funct | 16; - break; - case 't': /* display contents */ - funct = funct | 4; - break; - case 'x': /* extract contents of archive */ - funct = funct | 8; - break; - case 'v': /* be verbose */ - funct = funct | 2; - break; - default: - usage(ar_usage); - } - } - if (funct > 3) - ret = readArFile(argv, argc, funct); - return (ret); + return EXIT_SUCCESS; }