diff options
Diffstat (limited to 'libarchive/archive_read_support_filter_uu.c')
-rw-r--r-- | libarchive/archive_read_support_filter_uu.c | 53 |
1 files changed, 50 insertions, 3 deletions
diff --git a/libarchive/archive_read_support_filter_uu.c b/libarchive/archive_read_support_filter_uu.c index 209b2a1593a0..689ceb8f8760 100644 --- a/libarchive/archive_read_support_filter_uu.c +++ b/libarchive/archive_read_support_filter_uu.c @@ -24,7 +24,6 @@ */ #include "archive_platform.h" -__FBSDID("$FreeBSD$"); #ifdef HAVE_ERRNO_H #include <errno.h> @@ -37,6 +36,7 @@ __FBSDID("$FreeBSD$"); #endif #include "archive.h" +#include "archive_entry.h" #include "archive_private.h" #include "archive_read_private.h" @@ -57,12 +57,17 @@ struct uudecode { #define ST_UUEND 2 #define ST_READ_BASE64 3 #define ST_IGNORE 4 + mode_t mode; + int mode_set; + char *name; }; static int uudecode_bidder_bid(struct archive_read_filter_bidder *, struct archive_read_filter *filter); static int uudecode_bidder_init(struct archive_read_filter *); +static int uudecode_read_header(struct archive_read_filter *, + struct archive_entry *entry); static ssize_t uudecode_filter_read(struct archive_read_filter *, const void **); static int uudecode_filter_close(struct archive_read_filter *); @@ -355,6 +360,7 @@ static const struct archive_read_filter_vtable uudecode_reader_vtable = { .read = uudecode_filter_read, .close = uudecode_filter_close, + .read_header = uudecode_read_header }; static int @@ -367,7 +373,7 @@ uudecode_bidder_init(struct archive_read_filter *self) self->code = ARCHIVE_FILTER_UU; self->name = "uu"; - uudecode = (struct uudecode *)calloc(sizeof(*uudecode), 1); + uudecode = (struct uudecode *)calloc(1, sizeof(*uudecode)); out_buff = malloc(OUT_BUFF_SIZE); in_buff = malloc(IN_BUFF_SIZE); if (uudecode == NULL || out_buff == NULL || in_buff == NULL) { @@ -385,6 +391,8 @@ uudecode_bidder_init(struct archive_read_filter *self) uudecode->in_allocated = IN_BUFF_SIZE; uudecode->out_buff = out_buff; uudecode->state = ST_FIND_HEAD; + uudecode->mode_set = 0; + uudecode->name = NULL; self->vtable = &uudecode_reader_vtable; return (ARCHIVE_OK); @@ -430,6 +438,22 @@ ensure_in_buff_size(struct archive_read_filter *self, return (ARCHIVE_OK); } +static int +uudecode_read_header(struct archive_read_filter *self, struct archive_entry *entry) +{ + + struct uudecode *uudecode; + uudecode = (struct uudecode *)self->data; + + if (uudecode->mode_set != 0) + archive_entry_set_mode(entry, S_IFREG | uudecode->mode); + + if (uudecode->name != NULL) + archive_entry_set_pathname(entry, uudecode->name); + + return (ARCHIVE_OK); +} + static ssize_t uudecode_filter_read(struct archive_read_filter *self, const void **buff) { @@ -439,7 +463,7 @@ uudecode_filter_read(struct archive_read_filter *self, const void **buff) ssize_t avail_in, ravail; ssize_t used; ssize_t total; - ssize_t len, llen, nl; + ssize_t len, llen, nl, namelen; uudecode = (struct uudecode *)self->data; @@ -544,6 +568,28 @@ read_more: uudecode->state = ST_READ_UU; else uudecode->state = ST_READ_BASE64; + uudecode->mode = (mode_t)( + ((int)(b[l] - '0') * 64) + + ((int)(b[l+1] - '0') * 8) + + (int)(b[l+2] - '0')); + uudecode->mode_set = 1; + namelen = len - nl - 4 - l; + if (namelen > 1) { + if (uudecode->name != NULL) + free(uudecode->name); + uudecode->name = malloc(namelen + 1); + if (uudecode->name == NULL) { + archive_set_error( + &self->archive->archive, + ENOMEM, + "Can't allocate data for uudecode"); + return (ARCHIVE_FATAL); + } + strncpy(uudecode->name, + (const char *)(b + l + 4), + namelen); + uudecode->name[namelen] = '\0'; + } } break; case ST_READ_UU: @@ -676,6 +722,7 @@ uudecode_filter_close(struct archive_read_filter *self) uudecode = (struct uudecode *)self->data; free(uudecode->in_buff); free(uudecode->out_buff); + free(uudecode->name); free(uudecode); return (ARCHIVE_OK); |