diff options
Diffstat (limited to 'lib/libarchive/archive_write_set_format_ustar.c')
-rw-r--r-- | lib/libarchive/archive_write_set_format_ustar.c | 89 |
1 files changed, 48 insertions, 41 deletions
diff --git a/lib/libarchive/archive_write_set_format_ustar.c b/lib/libarchive/archive_write_set_format_ustar.c index 2829ea6..87fc16a 100644 --- a/lib/libarchive/archive_write_set_format_ustar.c +++ b/lib/libarchive/archive_write_set_format_ustar.c @@ -50,11 +50,11 @@ __FBSDID("$FreeBSD$"); #include "archive.h" #include "archive_entry.h" #include "archive_private.h" +#include "archive_write_private.h" struct ustar { uint64_t entry_bytes_remaining; uint64_t entry_padding; - char written; }; /* @@ -150,38 +150,40 @@ static const char template_header[] = { 0,0,0,0,0,0,0,0, 0,0,0,0 }; -static ssize_t archive_write_ustar_data(struct archive *a, const void *buff, +static ssize_t archive_write_ustar_data(struct archive_write *a, const void *buff, size_t s); -static int archive_write_ustar_finish(struct archive *); -static int archive_write_ustar_finish_entry(struct archive *); -static int archive_write_ustar_header(struct archive *, +static int archive_write_ustar_destroy(struct archive_write *); +static int archive_write_ustar_finish(struct archive_write *); +static int archive_write_ustar_finish_entry(struct archive_write *); +static int archive_write_ustar_header(struct archive_write *, struct archive_entry *entry); static int format_256(int64_t, char *, int); static int format_number(int64_t, char *, int size, int max, int strict); static int format_octal(int64_t, char *, int); -static int write_nulls(struct archive *a, size_t); +static int write_nulls(struct archive_write *a, size_t); /* * Set output format to 'ustar' format. */ int -archive_write_set_format_ustar(struct archive *a) +archive_write_set_format_ustar(struct archive *_a) { + struct archive_write *a = (struct archive_write *)_a; struct ustar *ustar; /* If someone else was already registered, unregister them. */ - if (a->format_finish != NULL) - (a->format_finish)(a); + if (a->format_destroy != NULL) + (a->format_destroy)(a); /* Basic internal sanity test. */ if (sizeof(template_header) != 512) { - archive_set_error(a, ARCHIVE_ERRNO_MISC, "Internal: template_header wrong size: %d should be 512", sizeof(template_header)); + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Internal: template_header wrong size: %d should be 512", sizeof(template_header)); return (ARCHIVE_FATAL); } ustar = (struct ustar *)malloc(sizeof(*ustar)); if (ustar == NULL) { - archive_set_error(a, ENOMEM, "Can't allocate ustar data"); + archive_set_error(&a->archive, ENOMEM, "Can't allocate ustar data"); return (ARCHIVE_FATAL); } memset(ustar, 0, sizeof(*ustar)); @@ -191,6 +193,7 @@ archive_write_set_format_ustar(struct archive *a) a->format_write_header = archive_write_ustar_header; a->format_write_data = archive_write_ustar_data; a->format_finish = archive_write_ustar_finish; + a->format_destroy = archive_write_ustar_destroy; a->format_finish_entry = archive_write_ustar_finish_entry; a->archive_format = ARCHIVE_FORMAT_TAR_USTAR; a->archive_format_name = "POSIX ustar"; @@ -198,14 +201,13 @@ archive_write_set_format_ustar(struct archive *a) } static int -archive_write_ustar_header(struct archive *a, struct archive_entry *entry) +archive_write_ustar_header(struct archive_write *a, struct archive_entry *entry) { char buff[512]; int ret; struct ustar *ustar; ustar = (struct ustar *)a->format_data; - ustar->written = 1; /* Only regular files (not hardlinks) have data. */ if (archive_entry_hardlink(entry) != NULL || @@ -236,7 +238,7 @@ archive_write_ustar_header(struct archive *a, struct archive_entry *entry) * This is exported so that other 'tar' formats can use it. */ int -__archive_write_format_header_ustar(struct archive *a, char h[512], +__archive_write_format_header_ustar(struct archive_write *a, char h[512], struct archive_entry *entry, int tartype, int strict) { unsigned int checksum; @@ -272,11 +274,11 @@ __archive_write_format_header_ustar(struct archive *a, char h[512], * remaining name are too large, return an error. */ if (!p) { - archive_set_error(a, ENAMETOOLONG, + archive_set_error(&a->archive, ENAMETOOLONG, "Pathname too long"); ret = ARCHIVE_WARN; } else if (p > pp + USTAR_prefix_size) { - archive_set_error(a, ENAMETOOLONG, + archive_set_error(&a->archive, ENAMETOOLONG, "Pathname too long"); ret = ARCHIVE_WARN; } else { @@ -294,7 +296,7 @@ __archive_write_format_header_ustar(struct archive *a, char h[512], if (p != NULL && p[0] != '\0') { copy_length = strlen(p); if (copy_length > USTAR_linkname_size) { - archive_set_error(a, ENAMETOOLONG, + archive_set_error(&a->archive, ENAMETOOLONG, "Link contents too long"); ret = ARCHIVE_WARN; copy_length = USTAR_linkname_size; @@ -306,7 +308,7 @@ __archive_write_format_header_ustar(struct archive *a, char h[512], if (p != NULL && p[0] != '\0') { copy_length = strlen(p); if (copy_length > USTAR_uname_size) { - archive_set_error(a, ARCHIVE_ERRNO_MISC, + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Username too long"); ret = ARCHIVE_WARN; copy_length = USTAR_uname_size; @@ -318,7 +320,7 @@ __archive_write_format_header_ustar(struct archive *a, char h[512], if (p != NULL && p[0] != '\0') { copy_length = strlen(p); if (strlen(p) > USTAR_gname_size) { - archive_set_error(a, ARCHIVE_ERRNO_MISC, + archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Group name too long"); ret = ARCHIVE_WARN; copy_length = USTAR_gname_size; @@ -329,27 +331,27 @@ __archive_write_format_header_ustar(struct archive *a, char h[512], st = archive_entry_stat(entry); if (format_number(st->st_mode & 07777, h + USTAR_mode_offset, USTAR_mode_size, USTAR_mode_max_size, strict)) { - archive_set_error(a, ERANGE, "Numeric mode too large"); + archive_set_error(&a->archive, ERANGE, "Numeric mode too large"); ret = ARCHIVE_WARN; } if (format_number(st->st_uid, h + USTAR_uid_offset, USTAR_uid_size, USTAR_uid_max_size, strict)) { - archive_set_error(a, ERANGE, "Numeric user ID too large"); + archive_set_error(&a->archive, ERANGE, "Numeric user ID too large"); ret = ARCHIVE_WARN; } if (format_number(st->st_gid, h + USTAR_gid_offset, USTAR_gid_size, USTAR_gid_max_size, strict)) { - archive_set_error(a, ERANGE, "Numeric group ID too large"); + archive_set_error(&a->archive, ERANGE, "Numeric group ID too large"); ret = ARCHIVE_WARN; } if (format_number(st->st_size, h + USTAR_size_offset, USTAR_size_size, USTAR_size_max_size, strict)) { - archive_set_error(a, ERANGE, "File size out of range"); + archive_set_error(&a->archive, ERANGE, "File size out of range"); ret = ARCHIVE_WARN; } if (format_number(st->st_mtime, h + USTAR_mtime_offset, USTAR_mtime_size, USTAR_mtime_max_size, strict)) { - archive_set_error(a, ERANGE, + archive_set_error(&a->archive, ERANGE, "File modification time too large"); ret = ARCHIVE_WARN; } @@ -357,14 +359,14 @@ __archive_write_format_header_ustar(struct archive *a, char h[512], if (S_ISBLK(st->st_mode) || S_ISCHR(st->st_mode)) { if (format_number(major(st->st_rdev), h + USTAR_rdevmajor_offset, USTAR_rdevmajor_size, USTAR_rdevmajor_max_size, strict)) { - archive_set_error(a, ERANGE, + archive_set_error(&a->archive, ERANGE, "Major device number too large"); ret = ARCHIVE_WARN; } if (format_number(minor(st->st_rdev), h + USTAR_rdevminor_offset, USTAR_rdevminor_size, USTAR_rdevminor_max_size, strict)) { - archive_set_error(a, ERANGE, + archive_set_error(&a->archive, ERANGE, "Minor device number too large"); ret = ARCHIVE_WARN; } @@ -383,12 +385,12 @@ __archive_write_format_header_ustar(struct archive *a, char h[512], case S_IFDIR: h[USTAR_typeflag_offset] = '5' ; break; case S_IFIFO: h[USTAR_typeflag_offset] = '6' ; break; case S_IFSOCK: - archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT, + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "tar format cannot archive socket"); ret = ARCHIVE_WARN; break; default: - archive_set_error(a, ARCHIVE_ERRNO_FILE_FORMAT, + archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "tar format cannot archive this (mode=0%lo)", (unsigned long)st->st_mode); ret = ARCHIVE_WARN; @@ -486,27 +488,32 @@ format_octal(int64_t v, char *p, int s) } static int -archive_write_ustar_finish(struct archive *a) +archive_write_ustar_finish(struct archive_write *a) { struct ustar *ustar; int r; - r = ARCHIVE_OK; + if (a->compression_write == NULL) + return (ARCHIVE_OK); + + ustar = (struct ustar *)a->format_data; + r = write_nulls(a, 512*2); + return (r); +} + +static int +archive_write_ustar_destroy(struct archive_write *a) +{ + struct ustar *ustar; + ustar = (struct ustar *)a->format_data; - /* - * Suppress end-of-archive if nothing else was ever written. - * This fixes a problem where setting one format, then another - * ends up writing a gratuitous end-of-archive marker. - */ - if (ustar->written && a->compression_write != NULL) - r = write_nulls(a, 512*2); free(ustar); a->format_data = NULL; - return (r); + return (ARCHIVE_OK); } static int -archive_write_ustar_finish_entry(struct archive *a) +archive_write_ustar_finish_entry(struct archive_write *a) { struct ustar *ustar; int ret; @@ -519,7 +526,7 @@ archive_write_ustar_finish_entry(struct archive *a) } static int -write_nulls(struct archive *a, size_t padding) +write_nulls(struct archive_write *a, size_t padding) { int ret, to_write; @@ -534,7 +541,7 @@ write_nulls(struct archive *a, size_t padding) } static ssize_t -archive_write_ustar_data(struct archive *a, const void *buff, size_t s) +archive_write_ustar_data(struct archive_write *a, const void *buff, size_t s) { struct ustar *ustar; int ret; |