X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=archival%2Far.c;h=fd7f8e4dba28c0d23410e49ea5fe98bc7cec8b79;hb=4928f3b90b3925e6f3cc234df48e46f88fc5689b;hp=bd54bb6b869b5806cb2ab710d8cfc1ab70a9f49c;hpb=4f1b0124c73ba30ba6cd97840b6fff0df90ad40c;p=oweals%2Fbusybox.git diff --git a/archival/ar.c b/archival/ar.c index bd54bb6b8..fd7f8e4db 100644 --- a/archival/ar.c +++ b/archival/ar.c @@ -1,219 +1,88 @@ /* 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 - * - * Based in part on BusyBox tar, Debian dpkg-deb and GNU ar. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. + * Based in part on BusyBox tar, Debian dpkg-deb and GNU ar. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. * + * 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 "busybox.h" -typedef struct ar_headers_s { - char *name; - size_t size; - uid_t uid; - gid_t gid; - mode_t mode; - time_t mtime; - off_t offset; - struct ar_headers_s *next; -} ar_headers_t; +#include "libbb.h" +#include "unarchive.h" -/* - * return the headerL_t struct for the filename descriptor - */ -static ar_headers_t get_headers(int srcFd) +static void FAST_FUNC header_verbose_list_ar(const file_header_t *file_header) { - typedef struct raw_ar_header_s { /* Byte Offset */ - char name[16]; /* 0-15 */ - char date[12]; /* 16-27 */ - char uid[6]; - char gid[6]; /* 28-39 */ - char mode[8]; /* 40-47 */ - char size[10]; /* 48-57 */ - char fmag[2]; /* 58-59 */ - } raw_ar_header_t; - raw_ar_header_t raw_ar_header; + const char *mode = bb_mode_string(file_header->mode); + char *mtime; - ar_headers_t *head, *entry; - char ar_magic[8]; - char *long_name=NULL; - - head = (ar_headers_t *) xmalloc(sizeof(ar_headers_t)); - entry = (ar_headers_t *) xmalloc(sizeof(ar_headers_t)); - - /* check ar magic */ - if (full_read(srcFd, ar_magic, 8) != 8) - error_msg_and_die("cannot read magic\n"); - if (strncmp(ar_magic,"!",7) != 0) - error_msg_and_die("invalid magic\n"); - - while (full_read(srcFd, (char *) &raw_ar_header, 60)==60) { - /* check the end of header markers are valid */ - if ((raw_ar_header.fmag[0]!='`') || (raw_ar_header.fmag[1]!='\n')) { - char newline[1]; - if (raw_ar_header.fmag[1]!='`') { - break; - } - /* some version of ar, have an extra '\n' after each entry */ - read(srcFd, newline, 1); - if (newline[0]!='\n') { - break; - } - /* fix up the header, we started reading 1 byte too early due to a '\n' */ - memmove((char *) &raw_ar_header, (char *)&raw_ar_header+1, 59); - /* dont worry about adding the last '\n', we dont need it now */ - } - - entry->size = (size_t) atoi(raw_ar_header.size); - /* long filenames have '/' as the first character */ - if (raw_ar_header.name[0] == '/') { - if (raw_ar_header.name[1] == '/') { - /* multiple long filenames are stored as data in one entry */ - long_name = (char *) xrealloc(long_name, entry->size); - full_read(srcFd, long_name, entry->size); - continue; - } - else { - /* The number after the '/' indicates the offset in the ar data section - (saved in variable long_name) that conatains the real filename */ - const int long_name_offset = (int) atoi((char *) &raw_ar_header.name[1]); - entry->name = xmalloc(strlen(&long_name[long_name_offset])); - strcpy(entry->name, &long_name[long_name_offset]); - } - } - else { - /* short filenames */ - entry->name = xmalloc(16); - strncpy(entry->name, raw_ar_header.name, 16); - } - entry->name[strcspn(entry->name, " /")]='\0'; - - /* convert the rest of the now valid char header to its typed struct */ - parse_mode(raw_ar_header.mode, &entry->mode); - entry->mtime = atoi(raw_ar_header.date); - entry->uid = atoi(raw_ar_header.uid); - entry->gid = atoi(raw_ar_header.gid); - entry->offset = lseek(srcFd, 0, SEEK_CUR); - - /* add this entries header to our combined list */ - entry->next = (ar_headers_t *) xmalloc(sizeof(ar_headers_t)); - *entry->next = *head; - *head = *entry; - lseek(srcFd, (off_t) entry->size, SEEK_CUR); - } - return(*head); + 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); } -extern int ar_main(int argc, char **argv) +#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 + +int ar_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; +int ar_main(int argc UNUSED_PARAM, char **argv) { - const int preserve_date = 1; /* preserve original dates */ - const int verbose = 2; /* be verbose */ - const int display = 4; /* display contents */ - const int extract_to_file = 8; /* extract contents of archive */ - const int extract_to_stdout = 16; /* extract to stdout */ + static const char msg_unsupported_err[] ALIGN1 = + "archive %s is not supported"; - int funct = 0, opt=0; - int srcFd=0, dstFd=0; + archive_handle_t *archive_handle; + unsigned opt; - ar_headers_t head, *extract_list=NULL; + archive_handle = init_handle(); - extract_list = (ar_headers_t *) xmalloc(sizeof(ar_headers_t)); + /* Prepend '-' to the first argument if required */ + opt_complementary = "--:p:t:x:-1:p--tx:t--px:x--pt"; + opt = getopt32(argv, "ptxovcr"); + argv += optind; - while ((opt = getopt(argc, argv, "ovtpx")) != -1) { - switch (opt) { - case 'o': - funct |= preserve_date; - break; - case 'v': - funct |= verbose; - break; - case 't': - funct |= display; - break; - case 'p': - funct |= extract_to_stdout; - break; - case 'x': - funct |= extract_to_file; - break; - default: - usage(ar_usage); - } + if (opt & AR_CTX_PRINT) { + archive_handle->action_data = data_extract_to_stdout; + } + if (opt & AR_CTX_LIST) { + archive_handle->action_header = header_list; + } + if (opt & AR_CTX_EXTRACT) { + archive_handle->action_data = data_extract_all; + } + if (opt & AR_OPT_PRESERVE_DATE) { + archive_handle->ah_flags |= ARCHIVE_RESTORE_DATE; + } + if (opt & AR_OPT_VERBOSE) { + archive_handle->action_header = header_verbose_list_ar; + } + if (opt & AR_OPT_CREATE) { + bb_error_msg_and_die(msg_unsupported_err, "creation"); + } + if (opt & AR_OPT_INSERT) { + bb_error_msg_and_die(msg_unsupported_err, "insertion"); } - - /* check the src filename was specified */ - if (optind == argc) - usage(ar_usage); - - if ( (srcFd = open(argv[optind], O_RDONLY)) < 0) - error_msg_and_die("Cannot read %s\n", argv[optind]); - optind++; - head = get_headers(srcFd); + archive_handle->src_fd = xopen(*argv++, O_RDONLY); - /* find files to extract or display */ - /* search through argv and build extract list */ - for (;optindnext != NULL) { - if (strcmp(argv[optind], ar_entry->name) == 0) { - ar_headers_t *tmp; - tmp = (ar_headers_t *) xmalloc(sizeof(ar_headers_t)); - *tmp = *extract_list; - *extract_list = *ar_entry; - extract_list->next = tmp; - break; - } - ar_entry=ar_entry->next; - } + while (*argv) { + archive_handle->filter = filter_accept_list; + llist_add_to(&archive_handle->accept, *argv++); } - /* if individual files not found extract all files */ - if (extract_list->next==NULL) { - extract_list = &head; - } - - /* find files to extract or display */ - while (extract_list->next != NULL) { - if (funct & extract_to_file) { - dstFd = open(extract_list->name, O_WRONLY | O_CREAT, extract_list->mode); - } - else if (funct & extract_to_stdout) { - dstFd = fileno(stdout); - } - if ((funct & extract_to_file) || (funct & extract_to_stdout)) { - lseek(srcFd, extract_list->offset, SEEK_SET); - copy_file_chunk(srcFd, dstFd, (size_t) extract_list->size); - } - if (funct & verbose) { - printf("%s %d/%d %8d %s ", mode_string(extract_list->mode), - extract_list->uid, extract_list->gid, - extract_list->size, time_string(extract_list->mtime)); - } - if ((funct & display) || (funct & verbose)){ - printf("%s\n", extract_list->name); - } - extract_list=extract_list->next; - } + unpack_ar_archive(archive_handle); + return EXIT_SUCCESS; }