diff options
author | Tim Kientzle <kientzle@gmail.com> | 2010-11-10 00:59:05 -0500 |
---|---|---|
committer | Tim Kientzle <kientzle@gmail.com> | 2010-11-10 00:59:05 -0500 |
commit | 67d3cc9dee9b55b2fc5b1031ab36e27361406d74 (patch) | |
tree | 9e61dbf57be730e5903ae0b28f050d1ba5518d39 /libarchive/archive_write_set_format_cpio_newc.c | |
parent | d6855a5790a51e8acfb082e77fa99aadcaeb3764 (diff) | |
download | libarchive-67d3cc9dee9b55b2fc5b1031ab36e27361406d74.tar.gz |
Issue 113: When writing headers, return ARCHIVE_FAILED
on various problems:
* Missing name
* Missing size (except for hardlinks)
* Missing filetype
* Size too large for format
SVN-Revision: 2782
Diffstat (limited to 'libarchive/archive_write_set_format_cpio_newc.c')
-rw-r--r-- | libarchive/archive_write_set_format_cpio_newc.c | 57 |
1 files changed, 44 insertions, 13 deletions
diff --git a/libarchive/archive_write_set_format_cpio_newc.c b/libarchive/archive_write_set_format_cpio_newc.c index 3bda1879..fff26489 100644 --- a/libarchive/archive_write_set_format_cpio_newc.c +++ b/libarchive/archive_write_set_format_cpio_newc.c @@ -52,6 +52,7 @@ static int archive_write_newc_header(struct archive_write *, struct archive_entry *); static int format_hex(int64_t, void *, int); static int64_t format_hex_recursive(int64_t, char *, int); +static int write_header(struct archive_write *, struct archive_entry *); struct cpio { uint64_t entry_bytes_remaining; @@ -115,15 +116,39 @@ archive_write_set_format_cpio_newc(struct archive *_a) static int archive_write_newc_header(struct archive_write *a, struct archive_entry *entry) { + const char *path; + + if (archive_entry_filetype(entry) == 0) { + archive_set_error(&a->archive, -1, "Filetype required"); + return (ARCHIVE_FAILED); + } + + path = archive_entry_pathname(entry); + if (path == NULL || path[0] == '\0') { + archive_set_error(&a->archive, -1, "Pathname required"); + return (ARCHIVE_FAILED); + } + + if (archive_entry_hardlink(entry) == NULL + && (!archive_entry_size_is_set(entry) || archive_entry_size(entry) < 0)) { + archive_set_error(&a->archive, -1, "Size required"); + return (ARCHIVE_FAILED); + } + return write_header(a, entry); +} + +static int +write_header(struct archive_write *a, struct archive_entry *entry) +{ int64_t ino; struct cpio *cpio; const char *p, *path; - int pathlength, ret, ret2; + int pathlength, ret, ret_final; struct cpio_header_newc h; int pad; cpio = (struct cpio *)a->format_data; - ret2 = ARCHIVE_OK; + ret_final = ARCHIVE_OK; path = archive_entry_pathname(entry); pathlength = (int)strlen(path) + 1; /* Include trailing null. */ @@ -139,9 +164,10 @@ archive_write_newc_header(struct archive_write *a, struct archive_entry *entry) if (ino > 0xffffffff) { archive_set_error(&a->archive, ERANGE, "large inode number truncated"); - ret2 = ARCHIVE_WARN; + ret_final = ARCHIVE_WARN; } + /* TODO: Set ret_final to ARCHIVE_WARN if any of these overflow. */ format_hex(ino & 0xffffffff, &h.c_ino, sizeof(h.c_ino)); format_hex(archive_entry_mode(entry), &h.c_mode, sizeof(h.c_mode)); format_hex(archive_entry_uid(entry), &h.c_uid, sizeof(h.c_uid)); @@ -167,9 +193,12 @@ archive_write_newc_header(struct archive_write *a, struct archive_entry *entry) p = archive_entry_symlink(entry); if (p != NULL && *p != '\0') format_hex(strlen(p), &h.c_filesize, sizeof(h.c_filesize)); - else - format_hex(archive_entry_size(entry), + else { + ret = format_hex(archive_entry_size(entry), &h.c_filesize, sizeof(h.c_filesize)); + if (ret) + return (ARCHIVE_FAILED); + } ret = __archive_write_output(a, &h, sizeof(h)); if (ret != ARCHIVE_OK) @@ -180,10 +209,11 @@ archive_write_newc_header(struct archive_write *a, struct archive_entry *entry) if (ret != ARCHIVE_OK) return (ARCHIVE_FATAL); pad = PAD4(pathlength + sizeof(struct cpio_header_newc)); - if (pad) + if (pad) { ret = __archive_write_output(a, "\0\0\0", pad); - if (ret != ARCHIVE_OK) - return (ARCHIVE_FATAL); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); + } cpio->entry_bytes_remaining = archive_entry_size(entry); cpio->padding = PAD4(cpio->entry_bytes_remaining); @@ -195,11 +225,10 @@ archive_write_newc_header(struct archive_write *a, struct archive_entry *entry) return (ARCHIVE_FATAL); pad = PAD4(strlen(p)); ret = __archive_write_output(a, "\0\0\0", pad); + if (ret != ARCHIVE_OK) + return (ARCHIVE_FATAL); } - - if (ret == ARCHIVE_OK) - ret = ret2; - return (ret); + return (ret_final); } static ssize_t @@ -258,8 +287,10 @@ archive_write_newc_close(struct archive_write *a) trailer = archive_entry_new(); archive_entry_set_nlink(trailer, 1); + archive_entry_set_size(trailer, 0); archive_entry_set_pathname(trailer, "TRAILER!!!"); - er = archive_write_newc_header(a, trailer); + /* Bypass the required data checks. */ + er = write_header(a, trailer); archive_entry_free(trailer); return (er); } |