From: Tim Kientzle Date: Thu, 15 May 2008 22:11:25 +0000 (-0400) Subject: Failing to write a header is not just a "WARN" problem, X-Git-Tag: v2.6.0~235 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=ec50ba5e1f8fa89704fa4c65379bb4f96341c9f5;p=thirdparty%2Flibarchive.git Failing to write a header is not just a "WARN" problem, it's a "FAILED" operation. In particular, this fixes a relatively obscure problem writing ustar archives with bsdtar. Prior to this, bsdtar would report additional bogus errors because it kept trying to write the body even after the header failed. SVN-Revision: 57 --- diff --git a/libarchive/archive_write_set_format_ustar.c b/libarchive/archive_write_set_format_ustar.c index e7f652d1d..970fee8db 100644 --- a/libarchive/archive_write_set_format_ustar.c +++ b/libarchive/archive_write_set_format_ustar.c @@ -195,7 +195,7 @@ static int archive_write_ustar_header(struct archive_write *a, struct archive_entry *entry) { char buff[512]; - int ret; + int ret, ret2; struct ustar *ustar; ustar = (struct ustar *)a->format_data; @@ -229,15 +229,17 @@ archive_write_ustar_header(struct archive_write *a, struct archive_entry *entry) } ret = __archive_write_format_header_ustar(a, buff, entry, -1, 1); - if (ret != ARCHIVE_OK) - return (ret); - ret = (a->compressor.write)(a, buff, 512); - if (ret != ARCHIVE_OK) + if (ret < ARCHIVE_WARN) return (ret); + ret2 = (a->compressor.write)(a, buff, 512); + if (ret2 < ARCHIVE_WARN) + return (ret2); + if (ret2 < ret) + ret = ret2; ustar->entry_bytes_remaining = archive_entry_size(entry); ustar->entry_padding = 0x1ff & (-(int64_t)ustar->entry_bytes_remaining); - return (ARCHIVE_OK); + return (ret); } /* @@ -293,7 +295,7 @@ __archive_write_format_header_ustar(struct archive_write *a, char h[512], /* No separator. */ archive_set_error(&a->archive, ENAMETOOLONG, "Pathname too long"); - ret = ARCHIVE_WARN; + ret = ARCHIVE_FAILED; } else if (p[1] == '\0') { /* * The only feasible separator is a final '/'; @@ -303,12 +305,12 @@ __archive_write_format_header_ustar(struct archive_write *a, char h[512], */ archive_set_error(&a->archive, ENAMETOOLONG, "Pathname too long"); - ret = ARCHIVE_WARN; + ret = ARCHIVE_FAILED; } else if (p > pp + USTAR_prefix_size) { /* Prefix is too long. */ archive_set_error(&a->archive, ENAMETOOLONG, "Pathname too long"); - ret = ARCHIVE_WARN; + ret = ARCHIVE_FAILED; } else { /* Copy prefix and remainder to appropriate places */ memcpy(h + USTAR_prefix_offset, pp, p - pp); @@ -326,7 +328,7 @@ __archive_write_format_header_ustar(struct archive_write *a, char h[512], if (copy_length > USTAR_linkname_size) { archive_set_error(&a->archive, ENAMETOOLONG, "Link contents too long"); - ret = ARCHIVE_WARN; + ret = ARCHIVE_FAILED; copy_length = USTAR_linkname_size; } memcpy(h + USTAR_linkname_offset, p, copy_length); @@ -338,7 +340,7 @@ __archive_write_format_header_ustar(struct archive_write *a, char h[512], if (copy_length > USTAR_uname_size) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Username too long"); - ret = ARCHIVE_WARN; + ret = ARCHIVE_FAILED; copy_length = USTAR_uname_size; } memcpy(h + USTAR_uname_offset, p, copy_length); @@ -350,7 +352,7 @@ __archive_write_format_header_ustar(struct archive_write *a, char h[512], if (strlen(p) > USTAR_gname_size) { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Group name too long"); - ret = ARCHIVE_WARN; + ret = ARCHIVE_FAILED; copy_length = USTAR_gname_size; } memcpy(h + USTAR_gname_offset, p, copy_length); @@ -358,28 +360,28 @@ __archive_write_format_header_ustar(struct archive_write *a, char h[512], if (format_number(archive_entry_mode(entry) & 07777, h + USTAR_mode_offset, USTAR_mode_size, USTAR_mode_max_size, strict)) { archive_set_error(&a->archive, ERANGE, "Numeric mode too large"); - ret = ARCHIVE_WARN; + ret = ARCHIVE_FAILED; } if (format_number(archive_entry_uid(entry), h + USTAR_uid_offset, USTAR_uid_size, USTAR_uid_max_size, strict)) { archive_set_error(&a->archive, ERANGE, "Numeric user ID too large"); - ret = ARCHIVE_WARN; + ret = ARCHIVE_FAILED; } if (format_number(archive_entry_gid(entry), h + USTAR_gid_offset, USTAR_gid_size, USTAR_gid_max_size, strict)) { archive_set_error(&a->archive, ERANGE, "Numeric group ID too large"); - ret = ARCHIVE_WARN; + ret = ARCHIVE_FAILED; } if (format_number(archive_entry_size(entry), h + USTAR_size_offset, USTAR_size_size, USTAR_size_max_size, strict)) { archive_set_error(&a->archive, ERANGE, "File size out of range"); - ret = ARCHIVE_WARN; + ret = ARCHIVE_FAILED; } if (format_number(archive_entry_mtime(entry), h + USTAR_mtime_offset, USTAR_mtime_size, USTAR_mtime_max_size, strict)) { archive_set_error(&a->archive, ERANGE, "File modification time too large"); - ret = ARCHIVE_WARN; + ret = ARCHIVE_FAILED; } if (archive_entry_filetype(entry) == AE_IFBLK @@ -388,14 +390,14 @@ __archive_write_format_header_ustar(struct archive_write *a, char h[512], USTAR_rdevmajor_size, USTAR_rdevmajor_max_size, strict)) { archive_set_error(&a->archive, ERANGE, "Major device number too large"); - ret = ARCHIVE_WARN; + ret = ARCHIVE_FAILED; } if (format_number(archive_entry_rdevminor(entry), h + USTAR_rdevminor_offset, USTAR_rdevminor_size, USTAR_rdevminor_max_size, strict)) { archive_set_error(&a->archive, ERANGE, "Minor device number too large"); - ret = ARCHIVE_WARN; + ret = ARCHIVE_FAILED; } } @@ -415,7 +417,7 @@ __archive_write_format_header_ustar(struct archive_write *a, char h[512], archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "tar format cannot archive this (mode=0%lo)", (unsigned long)archive_entry_mode(entry)); - ret = ARCHIVE_WARN; + ret = ARCHIVE_FAILED; } } diff --git a/libarchive/test/test_ustar_filenames.c b/libarchive/test/test_ustar_filenames.c index ff65c8a2e..88b4b2c4a 100644 --- a/libarchive/test/test_ustar_filenames.c +++ b/libarchive/test/test_ustar_filenames.c @@ -72,7 +72,7 @@ test_filename(const char *prefix, int dlen, int flen) archive_entry_set_mode(ae, S_IFREG | 0755); failure("dlen=%d, flen=%d", dlen, flen); if (flen > 100) { - assertEqualIntA(a, ARCHIVE_WARN, archive_write_header(a, ae)); + assertEqualIntA(a, ARCHIVE_FAILED, archive_write_header(a, ae)); } else { assertEqualIntA(a, 0, archive_write_header(a, ae)); } @@ -86,7 +86,7 @@ test_filename(const char *prefix, int dlen, int flen) archive_entry_set_mode(ae, S_IFDIR | 0755); failure("dlen=%d, flen=%d", dlen, flen); if (flen >= 100) { - assertEqualIntA(a, ARCHIVE_WARN, archive_write_header(a, ae)); + assertEqualIntA(a, ARCHIVE_FAILED, archive_write_header(a, ae)); } else { assertEqualIntA(a, 0, archive_write_header(a, ae)); } @@ -103,7 +103,7 @@ test_filename(const char *prefix, int dlen, int flen) archive_entry_set_mode(ae, S_IFDIR | 0755); failure("dlen=%d, flen=%d", dlen, flen); if (flen >= 100) { - assertEqualIntA(a, ARCHIVE_WARN, archive_write_header(a, ae)); + assertEqualIntA(a, ARCHIVE_FAILED, archive_write_header(a, ae)); } else { assertEqualIntA(a, 0, archive_write_header(a, ae)); }