libarchive: fix xmalloc_open_zipped_read_close() on NOMMU
The somewhat new "unpack in memory" code was broken for xmalloc_open_zipped_read_close() on NOMMU: we seek back over signature, but then expect it to be already consumed. Stop seeking back in this case. Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
ecf25cb5bc
commit
984b0a613a
@ -121,7 +121,7 @@ int FAST_FUNC bbunpack(char **argv,
|
|||||||
|
|
||||||
if (!(option_mask32 & SEAMLESS_MAGIC)) {
|
if (!(option_mask32 & SEAMLESS_MAGIC)) {
|
||||||
init_transformer_state(&xstate);
|
init_transformer_state(&xstate);
|
||||||
xstate.check_signature = 1;
|
xstate.signature_skipped = 0;
|
||||||
/*xstate.src_fd = STDIN_FILENO; - already is */
|
/*xstate.src_fd = STDIN_FILENO; - already is */
|
||||||
xstate.dst_fd = STDOUT_FILENO;
|
xstate.dst_fd = STDOUT_FILENO;
|
||||||
status = unpacker(&xstate);
|
status = unpacker(&xstate);
|
||||||
|
@ -1201,7 +1201,7 @@ unpack_gz_stream(transformer_state_t *xstate)
|
|||||||
if (check_signature16(xstate, GZIP_MAGIC))
|
if (check_signature16(xstate, GZIP_MAGIC))
|
||||||
return -1;
|
return -1;
|
||||||
#else
|
#else
|
||||||
if (xstate->check_signature) {
|
if (!xstate->signature_skipped) {
|
||||||
uint16_t magic2;
|
uint16_t magic2;
|
||||||
|
|
||||||
if (full_read(xstate->src_fd, &magic2, 2) != 2) {
|
if (full_read(xstate->src_fd, &magic2, 2) != 2) {
|
||||||
@ -1210,7 +1210,7 @@ unpack_gz_stream(transformer_state_t *xstate)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (magic2 == COMPRESS_MAGIC) {
|
if (magic2 == COMPRESS_MAGIC) {
|
||||||
xstate->check_signature = 0;
|
xstate->signature_skipped = 2;
|
||||||
return unpack_Z_stream(xstate);
|
return unpack_Z_stream(xstate);
|
||||||
}
|
}
|
||||||
if (magic2 != GZIP_MAGIC)
|
if (magic2 != GZIP_MAGIC)
|
||||||
|
@ -55,7 +55,7 @@ unpack_xz_stream(transformer_state_t *xstate)
|
|||||||
iobuf.out = membuf + BUFSIZ;
|
iobuf.out = membuf + BUFSIZ;
|
||||||
iobuf.out_size = BUFSIZ;
|
iobuf.out_size = BUFSIZ;
|
||||||
|
|
||||||
if (!xstate || xstate->check_signature == 0) {
|
if (!xstate || xstate->signature_skipped) {
|
||||||
/* Preload XZ file signature */
|
/* Preload XZ file signature */
|
||||||
strcpy((char*)membuf, HEADER_MAGIC);
|
strcpy((char*)membuf, HEADER_MAGIC);
|
||||||
iobuf.in_size = HEADER_MAGIC_SIZE;
|
iobuf.in_size = HEADER_MAGIC_SIZE;
|
||||||
|
@ -13,16 +13,13 @@ void FAST_FUNC init_transformer_state(transformer_state_t *xstate)
|
|||||||
|
|
||||||
int FAST_FUNC check_signature16(transformer_state_t *xstate, unsigned magic16)
|
int FAST_FUNC check_signature16(transformer_state_t *xstate, unsigned magic16)
|
||||||
{
|
{
|
||||||
if (xstate->check_signature) {
|
if (!xstate->signature_skipped) {
|
||||||
uint16_t magic2;
|
uint16_t magic2;
|
||||||
if (full_read(xstate->src_fd, &magic2, 2) != 2 || magic2 != magic16) {
|
if (full_read(xstate->src_fd, &magic2, 2) != 2 || magic2 != magic16) {
|
||||||
bb_error_msg("invalid magic");
|
bb_error_msg("invalid magic");
|
||||||
#if 0 /* possible future extension */
|
|
||||||
if (xstate->check_signature > 1)
|
|
||||||
xfunc_die();
|
|
||||||
#endif
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
xstate->signature_skipped = 2;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -102,7 +99,7 @@ void check_errors_in_children(int signo)
|
|||||||
/* transformer(), more than meets the eye */
|
/* transformer(), more than meets the eye */
|
||||||
#if BB_MMU
|
#if BB_MMU
|
||||||
void FAST_FUNC fork_transformer(int fd,
|
void FAST_FUNC fork_transformer(int fd,
|
||||||
int check_signature,
|
int signature_skipped,
|
||||||
IF_DESKTOP(long long) int FAST_FUNC (*transformer)(transformer_state_t *xstate)
|
IF_DESKTOP(long long) int FAST_FUNC (*transformer)(transformer_state_t *xstate)
|
||||||
)
|
)
|
||||||
#else
|
#else
|
||||||
@ -123,7 +120,7 @@ void FAST_FUNC fork_transformer(int fd, const char *transform_prog)
|
|||||||
IF_DESKTOP(long long) int r;
|
IF_DESKTOP(long long) int r;
|
||||||
transformer_state_t xstate;
|
transformer_state_t xstate;
|
||||||
init_transformer_state(&xstate);
|
init_transformer_state(&xstate);
|
||||||
xstate.check_signature = check_signature;
|
xstate.signature_skipped = signature_skipped;
|
||||||
xstate.src_fd = fd;
|
xstate.src_fd = fd;
|
||||||
xstate.dst_fd = fd_pipe.wr;
|
xstate.dst_fd = fd_pipe.wr;
|
||||||
r = transformer(&xstate);
|
r = transformer(&xstate);
|
||||||
@ -168,12 +165,11 @@ static transformer_state_t *setup_transformer_on_fd(int fd, int fail_if_not_comp
|
|||||||
uint16_t b16[2];
|
uint16_t b16[2];
|
||||||
uint32_t b32[1];
|
uint32_t b32[1];
|
||||||
} magic;
|
} magic;
|
||||||
int offset;
|
|
||||||
transformer_state_t *xstate;
|
transformer_state_t *xstate;
|
||||||
|
|
||||||
offset = -2;
|
|
||||||
xstate = xzalloc(sizeof(*xstate));
|
xstate = xzalloc(sizeof(*xstate));
|
||||||
xstate->src_fd = fd;
|
xstate->src_fd = fd;
|
||||||
|
xstate->signature_skipped = 2;
|
||||||
|
|
||||||
/* .gz and .bz2 both have 2-byte signature, and their
|
/* .gz and .bz2 both have 2-byte signature, and their
|
||||||
* unpack_XXX_stream wants this header skipped. */
|
* unpack_XXX_stream wants this header skipped. */
|
||||||
@ -202,7 +198,7 @@ static transformer_state_t *setup_transformer_on_fd(int fd, int fail_if_not_comp
|
|||||||
if (ENABLE_FEATURE_SEAMLESS_XZ
|
if (ENABLE_FEATURE_SEAMLESS_XZ
|
||||||
&& magic.b16[0] == XZ_MAGIC1
|
&& magic.b16[0] == XZ_MAGIC1
|
||||||
) {
|
) {
|
||||||
offset = -6;
|
xstate->signature_skipped = 6;
|
||||||
xread(fd, magic.b32, sizeof(magic.b32[0]));
|
xread(fd, magic.b32, sizeof(magic.b32[0]));
|
||||||
if (magic.b32[0] == XZ_MAGIC2) {
|
if (magic.b32[0] == XZ_MAGIC2) {
|
||||||
xstate->xformer = unpack_xz_stream;
|
xstate->xformer = unpack_xz_stream;
|
||||||
@ -226,16 +222,7 @@ static transformer_state_t *setup_transformer_on_fd(int fd, int fail_if_not_comp
|
|||||||
// USE_FOR_NOMMU(xstate->xformer_prog = "cat";)
|
// USE_FOR_NOMMU(xstate->xformer_prog = "cat";)
|
||||||
/* fall through to seeking bck over bytes we read earlier */
|
/* fall through to seeking bck over bytes we read earlier */
|
||||||
|
|
||||||
USE_FOR_NOMMU(found_magic:)
|
found_magic:
|
||||||
/* NOMMU version of fork_transformer execs
|
|
||||||
* an external unzipper that wants
|
|
||||||
* file position at the start of the file.
|
|
||||||
*/
|
|
||||||
xlseek(fd, offset, SEEK_CUR);
|
|
||||||
|
|
||||||
USE_FOR_MMU(found_magic:)
|
|
||||||
/* In MMU case, if magic was found, seeking back is not necessary */
|
|
||||||
|
|
||||||
return xstate;
|
return xstate;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -254,6 +241,12 @@ int FAST_FUNC setup_unzip_on_fd(int fd, int fail_if_not_compressed)
|
|||||||
# if BB_MMU
|
# if BB_MMU
|
||||||
fork_transformer_with_no_sig(xstate->src_fd, xstate->xformer);
|
fork_transformer_with_no_sig(xstate->src_fd, xstate->xformer);
|
||||||
# else
|
# else
|
||||||
|
/* NOMMU version of fork_transformer execs
|
||||||
|
* an external unzipper that wants
|
||||||
|
* file position at the start of the file.
|
||||||
|
*/
|
||||||
|
xlseek(fd, - xstate->signature_skipped, SEEK_CUR);
|
||||||
|
xstate->signature_skipped = 0;
|
||||||
fork_transformer_with_sig(xstate->src_fd, xstate->xformer, xstate->xformer_prog);
|
fork_transformer_with_sig(xstate->src_fd, xstate->xformer, xstate->xformer_prog);
|
||||||
# endif
|
# endif
|
||||||
free(xstate);
|
free(xstate);
|
||||||
@ -300,6 +293,8 @@ int FAST_FUNC open_zipped(const char *fname, int fail_if_not_compressed)
|
|||||||
# if BB_MMU
|
# if BB_MMU
|
||||||
fork_transformer_with_no_sig(xstate->src_fd, xstate->xformer);
|
fork_transformer_with_no_sig(xstate->src_fd, xstate->xformer);
|
||||||
# else
|
# else
|
||||||
|
xlseek(fd, - xstate->signature_skipped, SEEK_CUR);
|
||||||
|
xstate->signature_skipped = 0;
|
||||||
fork_transformer_with_sig(xstate->src_fd, xstate->xformer, xstate->xformer_prog);
|
fork_transformer_with_sig(xstate->src_fd, xstate->xformer, xstate->xformer_prog);
|
||||||
# endif
|
# endif
|
||||||
}
|
}
|
||||||
|
@ -211,7 +211,7 @@ void dealloc_bunzip(bunzip_data *bd) FAST_FUNC;
|
|||||||
|
|
||||||
/* Meaning and direction (input/output) of the fields are transformer-specific */
|
/* Meaning and direction (input/output) of the fields are transformer-specific */
|
||||||
typedef struct transformer_state_t {
|
typedef struct transformer_state_t {
|
||||||
smallint check_signature; /* most often referenced member */
|
smallint signature_skipped; /* most often referenced member */
|
||||||
|
|
||||||
IF_DESKTOP(long long) int FAST_FUNC (*xformer)(struct transformer_state_t *xstate);
|
IF_DESKTOP(long long) int FAST_FUNC (*xformer)(struct transformer_state_t *xstate);
|
||||||
USE_FOR_NOMMU(const char *xformer_prog;)
|
USE_FOR_NOMMU(const char *xformer_prog;)
|
||||||
@ -252,11 +252,11 @@ int bbunpack(char **argv,
|
|||||||
void check_errors_in_children(int signo);
|
void check_errors_in_children(int signo);
|
||||||
#if BB_MMU
|
#if BB_MMU
|
||||||
void fork_transformer(int fd,
|
void fork_transformer(int fd,
|
||||||
int check_signature,
|
int signature_skipped,
|
||||||
IF_DESKTOP(long long) int FAST_FUNC (*transformer)(transformer_state_t *xstate)
|
IF_DESKTOP(long long) int FAST_FUNC (*transformer)(transformer_state_t *xstate)
|
||||||
) FAST_FUNC;
|
) FAST_FUNC;
|
||||||
#define fork_transformer_with_sig(fd, transformer, transform_prog) fork_transformer((fd), 1, (transformer))
|
#define fork_transformer_with_sig(fd, transformer, transform_prog) fork_transformer((fd), 0, (transformer))
|
||||||
#define fork_transformer_with_no_sig(fd, transformer) fork_transformer((fd), 0, (transformer))
|
#define fork_transformer_with_no_sig(fd, transformer) fork_transformer((fd), 1, (transformer))
|
||||||
#else
|
#else
|
||||||
void fork_transformer(int fd, const char *transform_prog) FAST_FUNC;
|
void fork_transformer(int fd, const char *transform_prog) FAST_FUNC;
|
||||||
#define fork_transformer_with_sig(fd, transformer, transform_prog) fork_transformer((fd), (transform_prog))
|
#define fork_transformer_with_sig(fd, transformer, transform_prog) fork_transformer((fd), (transform_prog))
|
||||||
|
Loading…
Reference in New Issue
Block a user