aboutsummaryrefslogtreecommitdiff
path: root/libarchive/archive_read_support_filter_uu.c
diff options
context:
space:
mode:
Diffstat (limited to 'libarchive/archive_read_support_filter_uu.c')
-rw-r--r--libarchive/archive_read_support_filter_uu.c53
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);