Ignore:
Timestamp:
Dec 20, 2016, 4:07:32 PM (7 years ago)
Author:
Bruno Cornec
Message:

New 3?3 banch for incorporation of latest busybox 1.25. Changing minor version to handle potential incompatibilities.

Location:
branches/3.3
Files:
1 edited
1 copied

Legend:

Unmodified
Added
Removed
  • branches/3.3/mindi-busybox/archival/libarchive/open_transformer.c

    r3232 r3621  
    77#include "bb_archive.h"
    88
    9 void FAST_FUNC init_transformer_aux_data(transformer_aux_data_t *aux)
    10 {
    11     memset(aux, 0, sizeof(*aux));
    12 }
    13 
    14 int FAST_FUNC check_signature16(transformer_aux_data_t *aux, int src_fd, unsigned magic16)
    15 {
    16     if (aux && aux->check_signature) {
     9void FAST_FUNC init_transformer_state(transformer_state_t *xstate)
     10{
     11    memset(xstate, 0, sizeof(*xstate));
     12}
     13
     14int FAST_FUNC check_signature16(transformer_state_t *xstate, unsigned magic16)
     15{
     16    if (!xstate->signature_skipped) {
    1717        uint16_t magic2;
    18         if (full_read(src_fd, &magic2, 2) != 2 || magic2 != magic16) {
     18        if (full_read(xstate->src_fd, &magic2, 2) != 2 || magic2 != magic16) {
    1919            bb_error_msg("invalid magic");
    20 #if 0 /* possible future extension */
    21             if (aux->check_signature > 1)
    22                 xfunc_die();
    23 #endif
    2420            return -1;
    2521        }
     22        xstate->signature_skipped = 2;
    2623    }
    2724    return 0;
     25}
     26
     27ssize_t FAST_FUNC transformer_write(transformer_state_t *xstate, const void *buf, size_t bufsize)
     28{
     29    ssize_t nwrote;
     30
     31    if (xstate->mem_output_size_max != 0) {
     32        size_t pos = xstate->mem_output_size;
     33        size_t size;
     34
     35        size = (xstate->mem_output_size += bufsize);
     36        if (size > xstate->mem_output_size_max) {
     37            free(xstate->mem_output_buf);
     38            xstate->mem_output_buf = NULL;
     39            bb_perror_msg("buffer %u too small", (unsigned)xstate->mem_output_size_max);
     40            nwrote = -1;
     41            goto ret;
     42        }
     43        xstate->mem_output_buf = xrealloc(xstate->mem_output_buf, size + 1);
     44        memcpy(xstate->mem_output_buf + pos, buf, bufsize);
     45        xstate->mem_output_buf[size] = '\0';
     46        nwrote = bufsize;
     47    } else {
     48        nwrote = full_write(xstate->dst_fd, buf, bufsize);
     49        if (nwrote != (ssize_t)bufsize) {
     50            bb_perror_msg("write");
     51            nwrote = -1;
     52            goto ret;
     53        }
     54    }
     55 ret:
     56    return nwrote;
     57}
     58
     59ssize_t FAST_FUNC xtransformer_write(transformer_state_t *xstate, const void *buf, size_t bufsize)
     60{
     61    ssize_t nwrote = transformer_write(xstate, buf, bufsize);
     62    if (nwrote != (ssize_t)bufsize) {
     63        xfunc_die();
     64    }
     65    return nwrote;
    2866}
    2967
     
    3573        /* block waiting for any child */
    3674        if (wait(&status) < 0)
     75//FIXME: check EINTR?
    3776            return; /* probably there are no children */
    3877        goto check_status;
     
    4281    for (;;) {
    4382        if (wait_any_nohang(&status) < 0)
     83//FIXME: check EINTR?
    4484            /* wait failed?! I'm confused... */
    4585            return;
    4686 check_status:
    47         if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
     87        /*if (WIFEXITED(status) && WEXITSTATUS(status) == 0)*/
     88        /* On Linux, the above can be checked simply as: */
     89        if (status == 0)
    4890            /* this child exited with 0 */
    4991            continue;
    50         /* Cannot happen?
    51         if (!WIFSIGNALED(status) && !WIFEXITED(status)) ???; */
     92        /* Cannot happen:
     93        if (!WIFSIGNALED(status) && !WIFEXITED(status)) ???;
     94         */
    5295        bb_got_signal = 1;
    5396    }
     
    5699/* transformer(), more than meets the eye */
    57100#if BB_MMU
    58 void FAST_FUNC open_transformer(int fd,
    59     int check_signature,
    60     IF_DESKTOP(long long) int FAST_FUNC (*transformer)(transformer_aux_data_t *aux, int src_fd, int dst_fd)
     101void FAST_FUNC fork_transformer(int fd,
     102    int signature_skipped,
     103    IF_DESKTOP(long long) int FAST_FUNC (*transformer)(transformer_state_t *xstate)
    61104)
    62105#else
    63 void FAST_FUNC open_transformer(int fd, const char *transform_prog)
     106void FAST_FUNC fork_transformer(int fd, const char *transform_prog)
    64107#endif
    65108{
     
    75118#if BB_MMU
    76119        {
    77             transformer_aux_data_t aux;
    78             init_transformer_aux_data(&aux);
    79             aux.check_signature = check_signature;
    80             transformer(&aux, fd, fd_pipe.wr);
     120            IF_DESKTOP(long long) int r;
     121            transformer_state_t xstate;
     122            init_transformer_state(&xstate);
     123            xstate.signature_skipped = signature_skipped;
     124            xstate.src_fd = fd;
     125            xstate.dst_fd = fd_pipe.wr;
     126            r = transformer(&xstate);
    81127            if (ENABLE_FEATURE_CLEAN_UP) {
    82128                close(fd_pipe.wr); /* send EOF */
     
    84130            }
    85131            /* must be _exit! bug was actually seen here */
    86             _exit(EXIT_SUCCESS);
     132            _exit(/*error if:*/ r < 0);
    87133        }
    88134#else
     
    113159 * thus we can't guess the format from filename's extension.
    114160 */
    115 int FAST_FUNC setup_unzip_on_fd(int fd, int fail_if_not_detected)
     161static transformer_state_t *setup_transformer_on_fd(int fd, int fail_if_not_compressed)
    116162{
    117163    union {
     
    120166        uint32_t b32[1];
    121167    } magic;
    122     int offset = -2;
    123     USE_FOR_MMU(IF_DESKTOP(long long) int FAST_FUNC (*xformer)(transformer_aux_data_t *aux, int src_fd, int dst_fd);)
    124     USE_FOR_NOMMU(const char *xformer_prog;)
     168    transformer_state_t *xstate;
     169
     170    xstate = xzalloc(sizeof(*xstate));
     171    xstate->src_fd = fd;
     172    xstate->signature_skipped = 2;
    125173
    126174    /* .gz and .bz2 both have 2-byte signature, and their
     
    130178     && magic.b16[0] == GZIP_MAGIC
    131179    ) {
    132         USE_FOR_MMU(xformer = unpack_gz_stream;)
    133         USE_FOR_NOMMU(xformer_prog = "gunzip";)
     180        xstate->xformer = unpack_gz_stream;
     181        USE_FOR_NOMMU(xstate->xformer_prog = "gunzip";)
     182        goto found_magic;
     183    }
     184    if (ENABLE_FEATURE_SEAMLESS_Z
     185     && magic.b16[0] == COMPRESS_MAGIC
     186    ) {
     187        xstate->xformer = unpack_Z_stream;
     188        USE_FOR_NOMMU(xstate->xformer_prog = "uncompress";)
    134189        goto found_magic;
    135190    }
     
    137192     && magic.b16[0] == BZIP2_MAGIC
    138193    ) {
    139         USE_FOR_MMU(xformer = unpack_bz2_stream;)
    140         USE_FOR_NOMMU(xformer_prog = "bunzip2";)
     194        xstate->xformer = unpack_bz2_stream;
     195        USE_FOR_NOMMU(xstate->xformer_prog = "bunzip2";)
    141196        goto found_magic;
    142197    }
     
    144199     && magic.b16[0] == XZ_MAGIC1
    145200    ) {
    146         offset = -6;
     201        xstate->signature_skipped = 6;
    147202        xread(fd, magic.b32, sizeof(magic.b32[0]));
    148203        if (magic.b32[0] == XZ_MAGIC2) {
    149             USE_FOR_MMU(xformer = unpack_xz_stream;)
    150             USE_FOR_NOMMU(xformer_prog = "unxz";)
     204            xstate->xformer = unpack_xz_stream;
     205            USE_FOR_NOMMU(xstate->xformer_prog = "unxz";)
    151206            goto found_magic;
    152207        }
     
    154209
    155210    /* No known magic seen */
    156     if (fail_if_not_detected)
     211    if (fail_if_not_compressed)
    157212        bb_error_msg_and_die("no gzip"
    158213            IF_FEATURE_SEAMLESS_BZ2("/bzip2")
    159214            IF_FEATURE_SEAMLESS_XZ("/xz")
    160215            " magic");
    161     xlseek(fd, offset, SEEK_CUR);
    162     return 1;
     216
     217    /* Some callers expect this function to "consume" fd
     218     * even if data is not compressed. In this case,
     219     * we return a state with trivial transformer.
     220     */
     221//  USE_FOR_MMU(xstate->xformer = copy_stream;)
     222//  USE_FOR_NOMMU(xstate->xformer_prog = "cat";)
    163223
    164224 found_magic:
     225    return xstate;
     226}
     227
     228/* Used by e.g. rpm which gives us a fd without filename,
     229 * thus we can't guess the format from filename's extension.
     230 */
     231int FAST_FUNC setup_unzip_on_fd(int fd, int fail_if_not_compressed)
     232{
     233    transformer_state_t *xstate = setup_transformer_on_fd(fd, fail_if_not_compressed);
     234
     235    if (!xstate || !xstate->xformer) {
     236        free(xstate);
     237        return 1;
     238    }
     239
    165240# if BB_MMU
    166     open_transformer_with_no_sig(fd, xformer);
     241    fork_transformer_with_no_sig(xstate->src_fd, xstate->xformer);
    167242# else
    168     /* NOMMU version of open_transformer execs
     243    /* NOMMU version of fork_transformer execs
    169244     * an external unzipper that wants
    170      * file position at the start of the file */
    171     xlseek(fd, offset, SEEK_CUR);
    172     open_transformer_with_sig(fd, xformer, xformer_prog);
     245     * file position at the start of the file.
     246     */
     247    xlseek(fd, - xstate->signature_skipped, SEEK_CUR);
     248    xstate->signature_skipped = 0;
     249    fork_transformer_with_sig(xstate->src_fd, xstate->xformer, xstate->xformer_prog);
    173250# endif
     251    free(xstate);
    174252    return 0;
    175253}
    176254
    177 int FAST_FUNC open_zipped(const char *fname)
    178 {
    179     char *sfx;
     255static transformer_state_t *open_transformer(const char *fname, int fail_if_not_compressed)
     256{
     257    transformer_state_t *xstate;
    180258    int fd;
    181259
    182260    fd = open(fname, O_RDONLY);
    183261    if (fd < 0)
    184         return fd;
    185 
    186     sfx = strrchr(fname, '.');
    187     if (sfx) {
    188         sfx++;
    189         if (ENABLE_FEATURE_SEAMLESS_LZMA && strcmp(sfx, "lzma") == 0)
    190             /* .lzma has no header/signature, just trust it */
    191             open_transformer_with_sig(fd, unpack_lzma_stream, "unlzma");
    192         else
    193         if ((ENABLE_FEATURE_SEAMLESS_GZ && strcmp(sfx, "gz") == 0)
    194          || (ENABLE_FEATURE_SEAMLESS_BZ2 && strcmp(sfx, "bz2") == 0)
    195          || (ENABLE_FEATURE_SEAMLESS_XZ && strcmp(sfx, "xz") == 0)
    196         ) {
    197             setup_unzip_on_fd(fd, /*fail_if_not_detected:*/ 1);
    198         }
    199     }
    200 
     262        return NULL;
     263
     264    if (ENABLE_FEATURE_SEAMLESS_LZMA) {
     265        /* .lzma has no header/signature, can only detect it by extension */
     266        char *sfx = strrchr(fname, '.');
     267        if (sfx && strcmp(sfx+1, "lzma") == 0) {
     268            xstate = xzalloc(sizeof(*xstate));
     269            xstate->src_fd = fd;
     270            xstate->xformer = unpack_lzma_stream;
     271            USE_FOR_NOMMU(xstate->xformer_prog = "unlzma";)
     272            return xstate;
     273        }
     274    }
     275
     276    xstate = setup_transformer_on_fd(fd, fail_if_not_compressed);
     277
     278    return xstate;
     279}
     280
     281int FAST_FUNC open_zipped(const char *fname, int fail_if_not_compressed)
     282{
     283    int fd;
     284    transformer_state_t *xstate;
     285
     286    xstate = open_transformer(fname, fail_if_not_compressed);
     287    if (!xstate)
     288        return -1;
     289
     290    fd = xstate->src_fd;
     291# if BB_MMU
     292    if (xstate->xformer) {
     293        fork_transformer_with_no_sig(fd, xstate->xformer);
     294    } else {
     295        /* the file is not compressed */
     296        xlseek(fd, - xstate->signature_skipped, SEEK_CUR);
     297        xstate->signature_skipped = 0;
     298    }
     299# else
     300    /* NOMMU can't avoid the seek :( */
     301    xlseek(fd, - xstate->signature_skipped, SEEK_CUR);
     302    xstate->signature_skipped = 0;
     303    if (xstate->xformer) {
     304        fork_transformer_with_sig(fd, xstate->xformer, xstate->xformer_prog);
     305    } /* else: the file is not compressed */
     306# endif
     307
     308    free(xstate);
    201309    return fd;
    202310}
    203311
    204 #endif /* SEAMLESS_COMPRESSION */
    205 
    206312void* FAST_FUNC xmalloc_open_zipped_read_close(const char *fname, size_t *maxsz_p)
    207313{
     314# if 1
     315    transformer_state_t *xstate;
     316    char *image;
     317
     318    xstate = open_transformer(fname, /*fail_if_not_compressed:*/ 0);
     319    if (!xstate) /* file open error */
     320        return NULL;
     321
     322    image = NULL;
     323    if (xstate->xformer) {
     324        /* In-memory decompression */
     325        xstate->mem_output_size_max = maxsz_p ? *maxsz_p : (size_t)(INT_MAX - 4095);
     326        xstate->xformer(xstate);
     327        if (xstate->mem_output_buf) {
     328            image = xstate->mem_output_buf;
     329            if (maxsz_p)
     330                *maxsz_p = xstate->mem_output_size;
     331        }
     332    } else {
     333        /* File is not compressed */
     334//FIXME: avoid seek
     335        xlseek(xstate->src_fd, - xstate->signature_skipped, SEEK_CUR);
     336        xstate->signature_skipped = 0;
     337        image = xmalloc_read(xstate->src_fd, maxsz_p);
     338    }
     339
     340    if (!image)
     341        bb_perror_msg("read error from '%s'", fname);
     342    close(xstate->src_fd);
     343    free(xstate);
     344    return image;
     345# else
     346    /* This version forks a subprocess - much more expensive */
    208347    int fd;
    209348    char *image;
    210349
    211     fd = open_zipped(fname);
     350    fd = open_zipped(fname, /*fail_if_not_compressed:*/ 0);
    212351    if (fd < 0)
    213352        return NULL;
     
    217356        bb_perror_msg("read error from '%s'", fname);
    218357    close(fd);
    219 
    220358    return image;
    221 }
     359# endif
     360}
     361
     362#endif /* SEAMLESS_COMPRESSION */
Note: See TracChangeset for help on using the changeset viewer.