X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;ds=sidebyside;f=ar.c;h=7f3396c8cf9af0fc8f17096eb59191b1359622ed;hb=51ded05b3bf4df6f126420d39a40d27ea0728aa9;hp=253f3348a51dec812717133ce7bd705816ae7095;hpb=86ab8a32bd63b2f2a73bdcead8e2bb037589e175;p=oweals%2Fbusybox.git diff --git a/ar.c b/ar.c index 253f3348a..7f3396c8c 100644 --- a/ar.c +++ b/ar.c @@ -3,8 +3,8 @@ * 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. * * This program is free software; you can redistribute it and/or modify @@ -22,256 +22,68 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ - - -#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; - -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 +#include +#include +#include +#include "busybox.h" -static void displayContents(struct ArInfo *entry, int funct) -{ - /* 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); -} - -/* Converts to new typed struct */ -static int readArHeader(struct ArHeader *rawHeader, struct ArInfo *header) +extern int ar_main(int argc, char **argv) { - int count2; - int count; - - 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] == '/') + FILE *src_stream = NULL; + char **extract_names = NULL; + char ar_magic[8]; + int extract_function = extract_unconditional; + int opt; + int num_of_entries = 0; + extern off_t archive_offset; + + while ((opt = getopt(argc, argv, "ovtpx")) != -1) { + switch (opt) { + case 'o': + extract_function |= extract_preserve_date; 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) -{ - 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); + case 'v': + extract_function |= extract_verbose_list; + break; + case 't': + extract_function |= extract_list; + break; + case 'p': + extract_function |= extract_to_stdout; + break; + case 'x': + extract_function |= extract_all_to_fs; + break; + default: + show_usage(); } - copySize -= doneSize; } - 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); - } + + /* check the src filename was specified */ + if (optind == argc) { + show_usage(); } - 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; + src_stream = xfopen(argv[optind++], "r"); - 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 ((funct & 8) == 8) { /* extract to file */ - extract = 1; - } - 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 (fullRead(arFd, arVersion, 8) <= 0) { - errorMsg("ar: Unexpected EOF in archive\n"); - return (FALSE); + /* check ar magic */ + fread(ar_magic, 1, 8, src_stream); + archive_offset = 8; + if (strncmp(ar_magic,"!",7) != 0) { + error_msg_and_die("invalid magic"); } - if (strncmp(arVersion, "!", 7) != 0) { - errorMsg("ar header fails check "); - return (FALSE); - } - 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); + /* Create a list of files to extract */ + while (optind < argc) { + extract_names = xrealloc(extract_names, sizeof(char *) * (num_of_entries + 2)); + extract_names[num_of_entries] = xstrdup(argv[optind]); + num_of_entries++; + extract_names[num_of_entries] = NULL; + optind++; } - return (0); -} - -extern int ar_main(int argc, char **argv) -{ - int ret = 0; - char *opt_ptr; - char c; - int funct = 0; - if (argc < 2) - usage(ar_usage); - - 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); + unarchive(src_stream, stdout, &get_header_ar, extract_function, "./", extract_names); + return EXIT_SUCCESS; }