Changeset 2725 in MondoRescue for branches/2.2.9/mindi-busybox/archival/ar.c


Ignore:
Timestamp:
Feb 25, 2011, 9:26:54 PM (13 years ago)
Author:
Bruno Cornec
Message:
  • Update mindi-busybox to 1.18.3 to avoid problems with the tar command which is now failing on recent versions with busybox 1.7.3
File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/2.2.9/mindi-busybox/archival/ar.c

    r1765 r2725  
    44 *
    55 * Copyright (C) 2000 by Glenn McGrath
    6  * Written by Glenn McGrath <bug1@iinet.net.au> 1 June 2000
    76 *
    87 * Based in part on BusyBox tar, Debian dpkg-deb and GNU ar.
    98 *
    10  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     9 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
     10 *
     11 * Archive creation support:
     12 * Copyright (C) 2010 Nokia Corporation. All rights reserved.
     13 * Written by Alexander Shishkin.
    1114 *
    1215 * There is no single standard to adhere to so ar may not portable
     
    1619
    1720#include "libbb.h"
    18 #include "unarchive.h"
    19 
    20 static void header_verbose_list_ar(const file_header_t *file_header)
     21#include "archive.h"
     22#include "ar.h"
     23
     24#if ENABLE_FEATURE_AR_CREATE
     25/* filter out entries with same names as specified on the command line */
     26static char FAST_FUNC filter_replaceable(archive_handle_t *handle)
     27{
     28    if (find_list_entry(handle->accept, handle->file_header->name))
     29        return EXIT_FAILURE;
     30
     31    return EXIT_SUCCESS;
     32}
     33
     34static void output_ar_header(archive_handle_t *handle)
     35{
     36    /* GNU ar 2.19.51.0.14 creates malformed archives
     37     * if input files are >10G. It also truncates files >4GB
     38     * (uses "size mod 4G"). We abort in this case:
     39     * We could add support for up to 10G files, but this is unlikely to be useful.
     40     * Note that unpacking side limits all fields to "unsigned int" data type,
     41     * and treats "all ones" as an error indicator. Thus max we allow here is UINT_MAX-1.
     42     */
     43    enum {
     44        /* for 2nd field: mtime */
     45        MAX11CHARS = UINT_MAX > 0xffffffff ? (unsigned)99999999999 : UINT_MAX-1,
     46        /* for last field: filesize */
     47        MAX10CHARS = UINT_MAX > 0xffffffff ? (unsigned)9999999999 : UINT_MAX-1,
     48    };
     49
     50    struct file_header_t *fh = handle->file_header;
     51
     52    if (handle->offset & 1) {
     53        xwrite(handle->src_fd, "\n", 1);
     54        handle->offset++;
     55    }
     56
     57    /* Careful! The widths should be exact. Fields must be separated */
     58    if (sizeof(off_t) > 4 && fh->size > (off_t)MAX10CHARS) {
     59        bb_error_msg_and_die("'%s' is bigger than ar can handle", fh->name);
     60    }
     61    fdprintf(handle->src_fd, "%-16.16s%-12lu%-6u%-6u%-8o%-10"OFF_FMT"u`\n",
     62            fh->name,
     63            (sizeof(time_t) > 4 && fh->mtime > MAX11CHARS) ? (long)0 : (long)fh->mtime,
     64            fh->uid > 99999 ? 0 : (int)fh->uid,
     65            fh->gid > 99999 ? 0 : (int)fh->gid,
     66            (int)fh->mode & 07777777,
     67            fh->size
     68    );
     69
     70    handle->offset += AR_HEADER_LEN;
     71}
     72
     73/*
     74 * when replacing files in an existing archive, copy from the the
     75 * original archive those files that are to be left intact
     76 */
     77static void FAST_FUNC copy_data(archive_handle_t *handle)
     78{
     79    archive_handle_t *out_handle = handle->ar__out;
     80    struct file_header_t *fh = handle->file_header;
     81
     82    out_handle->file_header = fh;
     83    output_ar_header(out_handle);
     84
     85    bb_copyfd_exact_size(handle->src_fd, out_handle->src_fd, fh->size);
     86    out_handle->offset += fh->size;
     87}
     88
     89static int write_ar_header(archive_handle_t *handle)
     90{
     91    char *fn;
     92    char fn_h[17]; /* 15 + "/" + NUL */
     93    struct stat st;
     94    int fd;
     95
     96    fn = llist_pop(&handle->accept);
     97    if (!fn)
     98        return -1;
     99
     100    xstat(fn, &st);
     101
     102    handle->file_header->mtime = st.st_mtime;
     103    handle->file_header->uid = st.st_uid;
     104    handle->file_header->gid = st.st_gid;
     105    handle->file_header->mode = st.st_mode;
     106    handle->file_header->size = st.st_size;
     107    handle->file_header->name = fn_h;
     108//TODO: if ENABLE_FEATURE_AR_LONG_FILENAMES...
     109    sprintf(fn_h, "%.15s/", bb_basename(fn));
     110
     111    output_ar_header(handle);
     112
     113    fd = xopen(fn, O_RDONLY);
     114    bb_copyfd_exact_size(fd, handle->src_fd, st.st_size);
     115    close(fd);
     116    handle->offset += st.st_size;
     117
     118    return 0;
     119}
     120
     121static int write_ar_archive(archive_handle_t *handle)
     122{
     123    struct stat st;
     124    archive_handle_t *out_handle;
     125
     126    xfstat(handle->src_fd, &st, handle->ar__name);
     127
     128    /* if archive exists, create a new handle for output.
     129     * we create it in place of the old one.
     130     */
     131    if (st.st_size != 0) {
     132        out_handle = init_handle();
     133        xunlink(handle->ar__name);
     134        out_handle->src_fd = xopen(handle->ar__name, O_WRONLY | O_CREAT | O_TRUNC);
     135        out_handle->accept = handle->accept;
     136    } else {
     137        out_handle = handle;
     138    }
     139
     140    handle->ar__out = out_handle;
     141
     142    xwrite(out_handle->src_fd, AR_MAGIC "\n", AR_MAGIC_LEN + 1);
     143    out_handle->offset += AR_MAGIC_LEN + 1;
     144
     145    /* skip to the end of the archive if we have to append stuff */
     146    if (st.st_size != 0) {
     147        handle->filter = filter_replaceable;
     148        handle->action_data = copy_data;
     149        unpack_ar_archive(handle);
     150    }
     151
     152    while (write_ar_header(out_handle) == 0)
     153        continue;
     154
     155    /* optional, since we exit right after we return */
     156    if (ENABLE_FEATURE_CLEAN_UP) {
     157        close(handle->src_fd);
     158        if (out_handle->src_fd != handle->src_fd)
     159            close(out_handle->src_fd);
     160    }
     161
     162    return EXIT_SUCCESS;
     163}
     164#endif /* FEATURE_AR_CREATE */
     165
     166static void FAST_FUNC header_verbose_list_ar(const file_header_t *file_header)
    21167{
    22168    const char *mode = bb_mode_string(file_header->mode);
     
    27173    memmove(&mtime[17], &mtime[20], 4);
    28174    mtime[21] = '\0';
    29     printf("%s %d/%d%7d %s %s\n", &mode[1], file_header->uid, file_header->gid,
    30             (int) file_header->size, &mtime[4], file_header->name);
    31 }
    32 
    33 #define AR_CTX_PRINT        0x01
    34 #define AR_CTX_LIST     0x02
    35 #define AR_CTX_EXTRACT      0x04
    36 #define AR_OPT_PRESERVE_DATE    0x08
    37 #define AR_OPT_VERBOSE      0x10
    38 #define AR_OPT_CREATE       0x20
    39 #define AR_OPT_INSERT       0x40
    40 
    41 int ar_main(int argc, char **argv);
    42 int ar_main(int argc, char **argv)
    43 {
    44     static const char msg_unsupported_err[] ALIGN1 =
    45         "archive %s is not supported";
    46 
     175    printf("%s %u/%u%7"OFF_FMT"u %s %s\n", &mode[1],
     176            (int)file_header->uid, (int)file_header->gid,
     177            file_header->size,
     178            &mtime[4], file_header->name
     179    );
     180}
     181
     182#define AR_OPT_VERBOSE          (1 << 0)
     183#define AR_OPT_PRESERVE_DATE    (1 << 1)
     184/* "ar r" implies create, but warns about it. c suppresses warning.
     185 * bbox accepts but ignores it: */
     186#define AR_OPT_CREATE           (1 << 2)
     187
     188#define AR_CMD_PRINT            (1 << 3)
     189#define FIRST_CMD               AR_CMD_PRINT
     190#define AR_CMD_LIST             (1 << 4)
     191#define AR_CMD_EXTRACT          (1 << 5)
     192#define AR_CMD_INSERT           (1 << 6)
     193
     194int ar_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     195int ar_main(int argc UNUSED_PARAM, char **argv)
     196{
    47197    archive_handle_t *archive_handle;
    48     unsigned opt;
    49     char magic[8];
     198    unsigned opt, t;
    50199
    51200    archive_handle = init_handle();
    52201
    53     /* Prepend '-' to the first argument if required */
    54     opt_complementary = "--:p:t:x:-1:p--tx:t--px:x--pt";
    55     opt = getopt32(argv, "ptxovcr");
    56 
    57     if (opt & AR_CTX_PRINT) {
     202    /* --: prepend '-' to the first argument if required */
     203    /* -1: at least one param is reqd */
     204    /* one of p,t,x[,r] is required */
     205    opt_complementary = "--:-1:p:t:x"IF_FEATURE_AR_CREATE(":r");
     206    opt = getopt32(argv, "voc""ptx"IF_FEATURE_AR_CREATE("r"));
     207    argv += optind;
     208
     209    t = opt / FIRST_CMD;
     210    if (t & (t-1)) /* more than one of p,t,x[,r] are specified */
     211        bb_show_usage();
     212
     213    if (opt & AR_CMD_PRINT) {
    58214        archive_handle->action_data = data_extract_to_stdout;
    59215    }
    60     if (opt & AR_CTX_LIST) {
     216    if (opt & AR_CMD_LIST) {
    61217        archive_handle->action_header = header_list;
    62218    }
    63     if (opt & AR_CTX_EXTRACT) {
     219    if (opt & AR_CMD_EXTRACT) {
    64220        archive_handle->action_data = data_extract_all;
    65221    }
    66222    if (opt & AR_OPT_PRESERVE_DATE) {
    67         archive_handle->flags |= ARCHIVE_PRESERVE_DATE;
     223        archive_handle->ah_flags |= ARCHIVE_RESTORE_DATE;
    68224    }
    69225    if (opt & AR_OPT_VERBOSE) {
    70226        archive_handle->action_header = header_verbose_list_ar;
    71227    }
    72     if (opt & AR_OPT_CREATE) {
    73         bb_error_msg_and_die(msg_unsupported_err, "creation");
    74     }
    75     if (opt & AR_OPT_INSERT) {
    76         bb_error_msg_and_die(msg_unsupported_err, "insertion");
    77     }
    78 
    79     archive_handle->src_fd = xopen(argv[optind++], O_RDONLY);
    80 
    81     while (optind < argc) {
     228#if ENABLE_FEATURE_AR_CREATE
     229    archive_handle->ar__name = *argv;
     230#endif
     231    archive_handle->src_fd = xopen(*argv++,
     232            (opt & AR_CMD_INSERT)
     233                ? O_RDWR | O_CREAT
     234                : O_RDONLY
     235    );
     236
     237    if (*argv)
    82238        archive_handle->filter = filter_accept_list;
    83         llist_add_to(&(archive_handle->accept), argv[optind++]);
    84     }
    85 
    86     xread(archive_handle->src_fd, magic, 7);
    87     if (strncmp(magic, "!<arch>", 7) != 0) {
    88         bb_error_msg_and_die("invalid ar magic");
    89     }
    90     archive_handle->offset += 7;
    91 
    92     while (get_header_ar(archive_handle) == EXIT_SUCCESS)
    93         continue;
     239    while (*argv) {
     240        llist_add_to_end(&archive_handle->accept, *argv++);
     241    }
     242
     243#if ENABLE_FEATURE_AR_CREATE
     244    if (opt & AR_CMD_INSERT)
     245        return write_ar_archive(archive_handle);
     246#endif
     247
     248    unpack_ar_archive(archive_handle);
    94249
    95250    return EXIT_SUCCESS;
Note: See TracChangeset for help on using the changeset viewer.