From owner-freebsd-current@FreeBSD.ORG Thu Sep 23 15:24:34 2004 Return-Path: Delivered-To: freebsd-current@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id CFD1516A4CE for ; Thu, 23 Sep 2004 15:24:34 +0000 (GMT) Received: from kientzle.com (h-66-166-149-50.snvacaid.covad.net [66.166.149.50]) by mx1.FreeBSD.org (Postfix) with ESMTP id 8675143D1D for ; Thu, 23 Sep 2004 15:24:33 +0000 (GMT) (envelope-from kientzle@freebsd.org) Received: from freebsd.org (p54.kientzle.com [66.166.149.54]) by kientzle.com (8.12.9/8.12.9) with ESMTP id i8NFOT90092189; Thu, 23 Sep 2004 08:24:30 -0700 (PDT) (envelope-from kientzle@freebsd.org) Message-ID: <4152EAA5.30807@freebsd.org> Date: Thu, 23 Sep 2004 08:24:21 -0700 From: Tim Kientzle User-Agent: Mozilla/5.0 (X11; U; FreeBSD i386; en-US; rv:1.4) Gecko/20031006 X-Accept-Language: en-us, en MIME-Version: 1.0 To: Oliver Lehmann References: <20040923062411.7b5a70d7.lehmann@ans-netz.de> In-Reply-To: <20040923062411.7b5a70d7.lehmann@ans-netz.de> Content-Type: multipart/mixed; boundary="------------030803060908090105000500" cc: freebsd-current@freebsd.org Subject: Re: bsdtar doesn't detect end of tape X-BeenThere: freebsd-current@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: Discussions about the use of FreeBSD-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 23 Sep 2004 15:24:34 -0000 This is a multi-part message in MIME format. --------------030803060908090105000500 Content-Type: text/plain; charset=us-ascii; format=flowed Content-Transfer-Encoding: 7bit Oliver Lehmann wrote: > Hi, > > I can store more files on tape with bsdtar than I'm able to read back. > > root@nudel dds2> tar -c -b 64 -v -f /dev/sa3 . > [writes more files than the tape can handle - w/o an error!!] > root@nudel dds2> tar -x -b 64 -v -f /dev/sa3 > [...] > x nudel/pics/selftreffen_2001.tar.bz2 > x nudel/pics/selftreffen_2002.tar.bz2: (null) > tar: (null) > Exit 1 > root@nudel dds2> Oliver, The libarchive in 5.3 does have a bug where it fails to correctly propagate write errors back to the caller. In this case, bsdtar never sees the write error and keeps going beyond end-of-tape. Try the attached patch to src/lib/libarchive, rebuild libarchive and bsdtar and let me know if it fixes it for you. My current plan is to put this into 6-CURRENT just after 5.3 gets released and MFC them a few weeks later. If there's enough demand, I'll reconsider this plan. Tim P.S. This is a hastily-done diff between the 5-stable version of libarchive and my current development version, which has a bit more than just the write error fix. It would take me a day or so to separate it out into the two different patches it really should be. --------------030803060908090105000500 Content-Type: text/plain; name="archive_write_error.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="archive_write_error.patch" diff -u -x Makefile -x archive_check_magic.c -x CVS -I FreeBSD -r libarchive/archive.h.in libarchive-stable/archive.h.in --- libarchive/archive.h.in Tue Aug 31 22:14:10 2004 +++ libarchive-stable/archive.h.in Sat Aug 7 12:22:50 2004 @@ -291,7 +291,7 @@ */ int archive_write_header(struct archive *, struct archive_entry *); -ssize_t archive_write_data(struct archive *, const void *, size_t); +int archive_write_data(struct archive *, const void *, size_t); int archive_write_close(struct archive *); void archive_write_finish(struct archive *); diff -u -x Makefile -x archive_check_magic.c -x CVS -I FreeBSD -r libarchive/archive_read_extract.c libarchive-stable/archive_read_extract.c --- libarchive/archive_read_extract.c Fri Aug 27 22:29:47 2004 +++ libarchive-stable/archive_read_extract.c Wed Sep 1 21:00:12 2004 @@ -488,7 +488,6 @@ if (extract->pst != NULL) { extract->pst = &extract->st; - /* If dir already exists, don't reset permissions. */ if (S_ISDIR(extract->pst->st_mode)) return (ARCHIVE_OK); /* It exists but isn't a dir. */ diff -u -x Makefile -x archive_check_magic.c -x CVS -I FreeBSD -r libarchive/archive_read_support_compression_bzip2.c libarchive-stable/archive_read_support_compression_bzip2.c --- libarchive/archive_read_support_compression_bzip2.c Mon Aug 30 21:42:13 2004 +++ libarchive-stable/archive_read_support_compression_bzip2.c Fri Aug 13 20:45:45 2004 @@ -29,7 +29,6 @@ __FBSDID("$FreeBSD: src/lib/libarchive/archive_read_support_compression_bzip2.c,v 1.6 2004/08/14 03:45:45 kientzle Exp $"); #include -#include #include #include #include diff -u -x Makefile -x archive_check_magic.c -x CVS -I FreeBSD -r libarchive/archive_read_support_compression_compress.c libarchive-stable/archive_read_support_compression_compress.c --- libarchive/archive_read_support_compression_compress.c Fri Aug 13 21:12:55 2004 +++ libarchive-stable/archive_read_support_compression_compress.c Fri Aug 13 20:45:45 2004 @@ -295,10 +295,8 @@ read_avail++; } else { ret = next_code(a, state); - if (ret == ARCHIVE_EOF) + if (ret) state->end_of_stream = ret; - else if (ret != ARCHIVE_OK) - return (ret); } } } @@ -348,8 +346,7 @@ /* * Process the next code and fill the stack with the expansion - * of the code. Returns ARCHIVE_FATAL if there is a fatal I/O or - * format error, ARCHIVE_EOF if we hit end of data, ARCHIVE_OK otherwise. + * of the code. Returns TRUE if we hit the end of the data. */ static int next_code(struct archive *a, struct private_data *state) @@ -394,11 +391,9 @@ return (next_code(a, state)); } - if (code > state->free_ent) { - /* An invalid code is a fatal error. */ - archive_set_error(a, -1, "Invalid compressed data"); - return (ARCHIVE_FATAL); - } + if (code > state->free_ent) + /* XXX invalid code? This is fatal. XXX */ + return (1); /* Special case for KwKwK string. */ if (code >= state->free_ent) { @@ -431,7 +426,7 @@ /* Remember previous code. */ state->oldcode = newcode; - return (ARCHIVE_OK); + return (0); } /* diff -u -x Makefile -x archive_check_magic.c -x CVS -I FreeBSD -r libarchive/archive_read_support_format_tar.c libarchive-stable/archive_read_support_format_tar.c --- libarchive/archive_read_support_format_tar.c Sat Sep 4 13:59:40 2004 +++ libarchive-stable/archive_read_support_format_tar.c Thu Sep 9 21:30:24 2004 @@ -534,7 +534,6 @@ } } --tar->header_recursion_depth; - return (err); } diff -u -x Makefile -x archive_check_magic.c -x CVS -I FreeBSD -r libarchive/archive_string.c libarchive-stable/archive_string.c --- libarchive/archive_string.c Fri Aug 27 21:46:36 2004 +++ libarchive-stable/archive_string.c Fri Aug 13 20:45:45 2004 @@ -96,18 +96,3 @@ { return (__archive_string_append(as, &c, 1)); } - -struct archive_string * -__archive_strappend_int(struct archive_string *as, int d, int base) -{ - static const char *digits = "0123457890abcdef"; - - if (d < 0) { - __archive_strappend_char(as, '-'); - d = -d; - } - if (d >= base) - __archive_strappend_int(as, d/base, base); - __archive_strappend_char(as, digits[d % base]); - return (as); -} diff -u -x Makefile -x archive_check_magic.c -x CVS -I FreeBSD -r libarchive/archive_string.h libarchive-stable/archive_string.h --- libarchive/archive_string.h Fri Aug 27 21:47:20 2004 +++ libarchive-stable/archive_string.h Sun May 2 18:40:34 2004 @@ -64,10 +64,6 @@ __archive_strappend_char_UTF8(struct archive_string *, int); #define archive_strappend_char_UTF8 __archive_strappend_char_UTF8 -/* Append an integer in the specified base (2 <= base <= 16). */ -struct archive_string * -__archive_strappend_int(struct archive_string *as, int d, int base); - /* Basic append operation. */ struct archive_string * __archive_string_append(struct archive_string *as, const char *p, size_t s); @@ -107,5 +103,10 @@ void __archive_string_vsprintf(struct archive_string *, const char *, va_list); #define archive_string_vsprintf __archive_string_vsprintf + +/* Like 'sprintf', but resizes the underlying string as necessary. */ +void __archive_string_sprintf(struct archive_string *, const char *, ...); +#define archive_string_sprintf __archive_string_sprintf + #endif diff -u -x Makefile -x archive_check_magic.c -x CVS -I FreeBSD -r libarchive/archive_string_sprintf.c libarchive-stable/archive_string_sprintf.c --- libarchive/archive_string_sprintf.c Sun Aug 29 12:53:34 2004 +++ libarchive-stable/archive_string_sprintf.c Mon Aug 30 22:10:36 2004 @@ -46,56 +46,34 @@ __archive_string_vsprintf(struct archive_string *as, const char *fmt, va_list ap) { - int long_flag, d; - long l; - const char *p, *s; - - __archive_string_ensure(as, 64); + size_t l; + va_list ap1; if (fmt == NULL) { as->s[0] = 0; return; } - long_flag = 0; - for (p = fmt; *p != '\0'; p++) { - if (*p != '%') { - archive_strappend_char(as, *p); - continue; - } - - p++; - - switch(*p) { - case 'l': - long_flag = 1; - p++; - break; - } - - switch (*p) { - case 's': - s = va_arg(ap, char *); - archive_strcat(as, s); - break; - case 'd': - if (long_flag) { - l = va_arg(ap, long); - __archive_strappend_int(as, l, 10); - } else { - d = va_arg(ap, int); - __archive_strappend_int(as, d, 10); - } - break; - case 'o': - if (long_flag) { - l = va_arg(ap, long); - __archive_strappend_int(as, l, 8); - } else { - d = va_arg(ap, int); - __archive_strappend_int(as, d, 8); - } - break; - } + va_copy(ap1, ap); + l = vsnprintf(as->s, as->buffer_length, fmt, ap); + /* If output is bigger than the buffer, resize and try again. */ + if (l+1 >= as->buffer_length) { + __archive_string_ensure(as, l + 1); + l = vsnprintf(as->s, as->buffer_length, fmt, ap1); } + as->length = l; + va_end(ap1); +} + +/* + * Corresponding 'sprintf' interface. + */ +void +__archive_string_sprintf(struct archive_string *as, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + __archive_string_vsprintf(as, fmt, ap); + va_end(ap); } diff -u -x Makefile -x archive_check_magic.c -x CVS -I FreeBSD -r libarchive/archive_write.3 libarchive-stable/archive_write.3 --- libarchive/archive_write.3 Tue Aug 31 22:17:02 2004 +++ libarchive-stable/archive_write.3 Sat Aug 7 12:22:50 2004 @@ -80,7 +80,7 @@ .Fn archive_write_open_file "struct archive *" "const char *filename" .Ft int .Fn archive_write_header "struct archive *" -.Ft ssize_t +.Ft int .Fn archive_write_data "struct archive *" "const void *" "size_t" .Ft int .Fn archive_write_close "struct archive *" @@ -190,7 +190,6 @@ structure. .It Fn archive_write_data Write data corresponding to the header just written. -Returns number of bytes written or -1 on error. .It Fn archive_write_close Complete the archive and invoke the close callback. .It Fn archive_write_finish @@ -322,19 +321,20 @@ .Fn archive_error_string functions will return appropriate values. Note that if the client-provided write callback function -returns a non-zero value, that error will be propagated back to the caller +returns -1, that error will be propagated back to the caller through whatever API function resulted in that call, which may include .Fn archive_write_header , .Fn archive_write_data , or .Fn archive_write_close . -The client callback can call -.Fn archive_set_error -to provide values that can then be retrieved by +In such a case, the .Fn archive_errno -and -.Fn archive_error_string . +or +.Fn archive_error_string +fields will not return useful information; you should use +client-private data to return error information +back to your mainline code. .Sh SEE ALSO .Xr tar 1 , .Xr libarchive 3 , diff -u -x Makefile -x archive_check_magic.c -x CVS -I FreeBSD -r libarchive/archive_write.c libarchive-stable/archive_write.c --- libarchive/archive_write.c Sat Sep 4 13:45:22 2004 +++ libarchive-stable/archive_write.c Fri Aug 13 20:43:35 2004 @@ -215,11 +215,9 @@ /* * Note that the compressor is responsible for blocking. */ -ssize_t +int archive_write_data(struct archive *a, const void *buff, size_t s) { - int ret; archive_check_magic(a, ARCHIVE_WRITE_MAGIC, ARCHIVE_STATE_DATA); - ret = (a->format_write_data)(a, buff, s); - return (ret == ARCHIVE_OK ? (ssize_t)s : -1); + return (a->format_write_data(a, buff, s)); } diff -u -x Makefile -x archive_check_magic.c -x CVS -I FreeBSD -r libarchive/archive_write_set_compression_bzip2.c libarchive-stable/archive_write_set_compression_bzip2.c --- libarchive/archive_write_set_compression_bzip2.c Mon Aug 30 21:42:00 2004 +++ libarchive-stable/archive_write_set_compression_bzip2.c Thu Jul 29 21:14:47 2004 @@ -32,7 +32,6 @@ __FBSDID("$FreeBSD: src/lib/libarchive/archive_write_set_compression_bzip2.c,v 1.5 2004/07/30 04:14:47 kientzle Exp $"); #include -#include #include #include #include @@ -154,17 +153,15 @@ /* * Write data to the compressed stream. - * - * Returns ARCHIVE_OK if all data written, error otherwise. */ -static int +static ssize_t archive_compressor_bzip2_write(struct archive *a, const void *buff, size_t length) { struct private_data *state; state = a->compression_data; - if (a->client_writer == NULL) { + if (!a->client_writer) { archive_set_error(a, ARCHIVE_ERRNO_PROGRAMMER, "No write callback is registered? " "This is probably an internal programming error."); @@ -178,9 +175,9 @@ SET_NEXT_IN(state, buff); state->stream.avail_in = length; if (drive_compressor(a, state, 0)) - return (ARCHIVE_FATAL); + return (-1); a->file_position += length; - return (ARCHIVE_OK); + return (length); } @@ -194,7 +191,6 @@ int ret; struct private_data *state; ssize_t target_block_length; - ssize_t bytes_written; unsigned tocopy; state = a->compression_data; @@ -250,16 +246,12 @@ } /* Write the last block */ - bytes_written = (a->client_writer)(a, a->client_data, - state->compressed, block_length); + ret = (a->client_writer)(a, a->client_data, state->compressed, + block_length); - /* TODO: Handle short write of final block. */ - if (bytes_written <= 0) - ret = ARCHIVE_FATAL; - else { - a->raw_position += ret; - ret = ARCHIVE_OK; - } + a->raw_position += ret; + if (ret != 0) + goto cleanup; /* Cleanup: shut down compressor, release memory, etc. */ cleanup: @@ -292,28 +284,27 @@ static int drive_compressor(struct archive *a, struct private_data *state, int finishing) { - size_t bytes_written; - int ret; + size_t ret; for (;;) { if (state->stream.avail_out == 0) { - bytes_written = (a->client_writer)(a, a->client_data, + ret = (a->client_writer)(a, a->client_data, state->compressed, state->compressed_buffer_size); - if (bytes_written <= 0) { + if (ret <= 0) { /* TODO: Handle this write failure */ return (ARCHIVE_FATAL); - } else if (bytes_written < state->compressed_buffer_size) { + } else if (ret < state->compressed_buffer_size) { /* Short write: Move remainder to * front and keep filling */ memmove(state->compressed, - state->compressed + bytes_written, - state->compressed_buffer_size - bytes_written); + state->compressed + ret, + state->compressed_buffer_size - ret); } - a->raw_position += bytes_written; + a->raw_position += ret; state->stream.next_out = state->compressed + - state->compressed_buffer_size - bytes_written; - state->stream.avail_out = bytes_written; + state->compressed_buffer_size - ret; + state->stream.avail_out = ret; } ret = BZ2_bzCompress(&(state->stream), diff -u -x Makefile -x archive_check_magic.c -x CVS -I FreeBSD -r libarchive/archive_write_set_compression_gzip.c libarchive-stable/archive_write_set_compression_gzip.c --- libarchive/archive_write_set_compression_gzip.c Sat Aug 21 12:31:03 2004 +++ libarchive-stable/archive_write_set_compression_gzip.c Sat Aug 7 12:21:18 2004 @@ -179,7 +179,7 @@ /* * Write data to the compressed stream. */ -static int +static ssize_t archive_compressor_gzip_write(struct archive *a, const void *buff, size_t length) { @@ -187,7 +187,7 @@ int ret; state = a->compression_data; - if (a->client_writer == NULL) { + if (!a->client_writer) { archive_set_error(a, ARCHIVE_ERRNO_PROGRAMMER, "No write callback is registered? " "This is probably an internal programming error."); @@ -205,7 +205,7 @@ return (ret); a->file_position += length; - return (ARCHIVE_OK); + return (length); } @@ -215,7 +215,7 @@ static int archive_compressor_gzip_finish(struct archive *a) { - ssize_t block_length, target_block_length, bytes_written; + ssize_t block_length, target_block_length; int ret; struct private_data *state; unsigned tocopy; @@ -273,13 +273,9 @@ /* If it overflowed, flush and start a new block. */ if (tocopy < 8) { - bytes_written = (a->client_writer)(a, a->client_data, - state->compressed, state->compressed_buffer_size); - if (bytes_written <= 0) { - ret = ARCHIVE_FATAL; - goto cleanup; - } - a->raw_position += bytes_written; + ret = (a->client_writer)(a, a->client_data, state->compressed, + state->compressed_buffer_size); + a->raw_position += ret; state->stream.next_out = state->compressed; state->stream.avail_out = state->compressed_buffer_size; memcpy(state->stream.next_out, trailer + tocopy, 8-tocopy); @@ -310,13 +306,9 @@ } /* Write the last block */ - bytes_written = (a->client_writer)(a, a->client_data, - state->compressed, block_length); - if (bytes_written <= 0) { - ret = ARCHIVE_FATAL; - goto cleanup; - } - a->raw_position += bytes_written; + ret = (a->client_writer)(a, a->client_data, state->compressed, + block_length); + a->raw_position += ret; /* Cleanup: shut down compressor, release memory, etc. */ cleanup: @@ -348,28 +340,27 @@ static int drive_compressor(struct archive *a, struct private_data *state, int finishing) { - size_t bytes_written; - int ret; + size_t ret; for (;;) { if (state->stream.avail_out == 0) { - bytes_written = (a->client_writer)(a, a->client_data, + ret = (a->client_writer)(a, a->client_data, state->compressed, state->compressed_buffer_size); - if (bytes_written <= 0) { + if (ret <= 0) { /* TODO: Handle this write failure */ return (ARCHIVE_FATAL); - } else if (bytes_written < state->compressed_buffer_size) { + } else if (ret < state->compressed_buffer_size) { /* Short write: Move remaining to * front of block and keep filling */ memmove(state->compressed, - state->compressed + bytes_written, - state->compressed_buffer_size - bytes_written); + state->compressed + ret, + state->compressed_buffer_size - ret); } - a->raw_position += bytes_written; + a->raw_position += ret; state->stream.next_out = state->compressed + - state->compressed_buffer_size - bytes_written; - state->stream.avail_out = bytes_written; + state->compressed_buffer_size - ret; + state->stream.avail_out = ret; } ret = deflate(&(state->stream), diff -u -x Makefile -x archive_check_magic.c -x CVS -I FreeBSD -r libarchive/archive_write_set_compression_none.c libarchive-stable/archive_write_set_compression_none.c --- libarchive/archive_write_set_compression_none.c Sat Aug 21 12:29:08 2004 +++ libarchive-stable/archive_write_set_compression_none.c Sat Aug 7 12:21:18 2004 @@ -104,13 +104,13 @@ /* * Write data to the stream. */ -static int +static ssize_t archive_compressor_none_write(struct archive *a, const void *vbuff, size_t length) { const char *buff; ssize_t remaining, to_copy; - ssize_t bytes_written; + int ret; struct archive_none *state; state = a->compression_data; @@ -129,12 +129,10 @@ * output buffer. */ if (state->avail == 0) { - bytes_written = (a->client_writer)(a, a->client_data, + ret = (a->client_writer)(a, a->client_data, state->buffer, state->buffer_size); - if (bytes_written <= 0) - return (ARCHIVE_FATAL); - /* XXX TODO: if bytes_written < state->buffer_size */ - a->raw_position += bytes_written; + /* XXX TODO: if ret < state->buffer_size XXX */ + a->raw_position += ret; state->next = state->buffer; state->avail = state->buffer_size; } @@ -149,7 +147,7 @@ remaining -= to_copy; } a->file_position += length; - return (ARCHIVE_OK); + return (length); } @@ -161,7 +159,6 @@ { ssize_t block_length; ssize_t target_block_length; - ssize_t bytes_written; int ret; int ret2; struct archive_none *state; @@ -196,14 +193,9 @@ target_block_length - block_length); block_length = target_block_length; } - bytes_written = (a->client_writer)(a, a->client_data, - state->buffer, block_length); - if (bytes_written <= 0) - ret = ARCHIVE_FATAL; - else { - a->raw_position += bytes_written; - ret = ARCHIVE_OK; - } + ret = (a->client_writer)(a, a->client_data, state->buffer, + block_length); + a->raw_position += ret; } /* Close the output */ diff -u -x Makefile -x archive_check_magic.c -x CVS -I FreeBSD -r libarchive/archive_write_set_format_cpio.c libarchive-stable/archive_write_set_format_cpio.c --- libarchive/archive_write_set_format_cpio.c Sat Aug 21 13:42:49 2004 +++ libarchive-stable/archive_write_set_format_cpio.c Tue Apr 13 16:45:37 2004 @@ -99,7 +99,7 @@ { struct cpio *cpio; const char *p, *path; - int pathlength, ret; + int pathlength, ret, written; const struct stat *st; struct cpio_header h; @@ -142,19 +142,19 @@ else format_octal(st->st_size, &h.c_filesize, sizeof(h.c_filesize)); - ret = (a->compression_write)(a, &h, sizeof(h)); - if (ret != ARCHIVE_OK) + written = (a->compression_write)(a, &h, sizeof(h)); + if (written < (int)sizeof(h)) return (ARCHIVE_FATAL); - ret = (a->compression_write)(a, path, pathlength); - if (ret != ARCHIVE_OK) + written = (a->compression_write)(a, path, pathlength); + if (written < (int)pathlength) return (ARCHIVE_FATAL); cpio->entry_bytes_remaining = st->st_size; /* Write the symlink now. */ if (p != NULL && *p != '\0') - ret = (a->compression_write)(a, p, strlen(p)); + (a->compression_write)(a, p, strlen(p)); return (ret); } @@ -233,13 +233,13 @@ int to_write, ret; cpio = a->format_data; - ret = ARCHIVE_OK; + ret = 0; while (cpio->entry_bytes_remaining > 0) { to_write = cpio->entry_bytes_remaining < a->null_length ? cpio->entry_bytes_remaining : a->null_length; ret = (a->compression_write)(a, a->nulls, to_write); - if (ret != ARCHIVE_OK) - return (ret); + if (ret < to_write) + return (-1); cpio->entry_bytes_remaining -= to_write; } return (ret); diff -u -x Makefile -x archive_check_magic.c -x CVS -I FreeBSD -r libarchive/archive_write_set_format_pax.c libarchive-stable/archive_write_set_format_pax.c --- libarchive/archive_write_set_format_pax.c Sat Aug 21 13:32:37 2004 +++ libarchive-stable/archive_write_set_format_pax.c Mon Sep 20 20:38:06 2004 @@ -414,7 +414,7 @@ } /* If numeric GID is too large, add 'gid' to pax extended attrs. */ - if (st_main->st_gid >= (1 << 20)) { + if (st_main->st_gid >= (1 << 18)) { add_pax_attr_int(&(pax->pax_header), "gid", st_main->st_gid); need_extension = 1; } @@ -429,7 +429,7 @@ } /* If numeric UID is too large, add 'uid' to pax extended attrs. */ - if (st_main->st_uid >= (1 << 20)) { + if (st_main->st_uid >= (1 << 18)) { add_pax_attr_int(&(pax->pax_header), "uid", st_main->st_uid); need_extension = 1; } @@ -622,7 +622,7 @@ __archive_write_format_header_ustar(a, ustarbuff, entry_main, -1, 0); /* If we built any extended attributes, write that entry first. */ - ret = ARCHIVE_OK; + ret = 0; if (archive_strlen(&(pax->pax_header)) > 0) { struct stat st; struct archive_entry *pax_attr_entry; @@ -636,7 +636,11 @@ archive_entry_set_pathname(pax_attr_entry, pax_attr_name); st.st_size = archive_strlen(&(pax->pax_header)); st.st_uid = st_main->st_uid; + if (st.st_uid >= 1 << 18) + st.st_uid = (1 << 18) - 1; st.st_gid = st_main->st_gid; + if (st.st_gid >= 1 << 18) + st.st_gid = (1 << 18) - 1; st.st_mode = st_main->st_mode; archive_entry_copy_stat(pax_attr_entry, &st); @@ -659,7 +663,7 @@ exit(1); } r = (a->compression_write)(a, paxbuff, 512); - if (r != ARCHIVE_OK) { + if (r < 512) { pax->entry_bytes_remaining = 0; pax->entry_padding = 0; return (ARCHIVE_FATAL); @@ -673,7 +677,7 @@ r = archive_write_data(a, pax->pax_header.s, archive_strlen(&(pax->pax_header))); a->state = oldstate; - if (r != ARCHIVE_OK) { + if (r < (int)archive_strlen(&(pax->pax_header))) { /* If a write fails, we're pretty much toast. */ return (ARCHIVE_FATAL); } @@ -683,8 +687,8 @@ /* Write the header for main entry. */ r = (a->compression_write)(a, ustarbuff, 512); - if (r != ARCHIVE_OK) - return (r); + if (ret != ARCHIVE_OK) + ret = (r < 512) ? ARCHIVE_FATAL : ARCHIVE_OK; /* * Inform the client of the on-disk size we're using, so @@ -835,9 +839,9 @@ while (padding > 0) { to_write = padding < a->null_length ? padding : a->null_length; ret = (a->compression_write)(a, a->nulls, to_write); - if (ret != ARCHIVE_OK) - return (ret); - padding -= to_write; + if (ret <= 0) + return (ARCHIVE_FATAL); + padding -= ret; } return (ARCHIVE_OK); } diff -u -x Makefile -x archive_check_magic.c -x CVS -I FreeBSD -r libarchive/archive_write_set_format_shar.c libarchive-stable/archive_write_set_format_shar.c --- libarchive/archive_write_set_format_shar.c Fri Aug 27 22:36:36 2004 +++ libarchive-stable/archive_write_set_format_shar.c Sun Jun 27 11:38:13 2004 @@ -50,7 +50,8 @@ int uuavail; char uubuffer[3]; int wrote_header; - struct archive_string work; + char *work; + size_t work_len; }; static int archive_write_shar_finish(struct archive *); @@ -69,13 +70,23 @@ { struct shar *shar; va_list ap; + int required; int ret; shar = a->format_data; + if (shar->work_len <= 0) { + shar->work_len = 1024; + shar->work = malloc(shar->work_len); + } + va_start(ap, fmt); - archive_string_empty(&(shar->work)); - archive_string_vsprintf(&(shar->work), fmt, ap); - ret = ((a->compression_write)(a, shar->work.s, strlen(shar->work.s))); + required = vsnprintf(shar->work, shar->work_len, fmt, ap); + if ((size_t)required >= shar->work_len) { + shar->work_len = required + 256; + realloc(shar->work, shar->work_len); + required = vsnprintf(shar->work, shar->work_len, fmt, ap); + } + ret = ((a->compression_write)(a, shar->work, strlen(shar->work))); va_end(ap); return (ret); } @@ -138,16 +149,11 @@ char *p, *pp; struct shar *shar; const struct stat *st; - int ret; shar = a->format_data; if (!shar->wrote_header) { - ret = shar_printf(a, "#!/bin/sh\n"); - if (ret != ARCHIVE_OK) - return (ret); - ret = shar_printf(a, "# This is a shell archive\n"); - if (ret != ARCHIVE_OK) - return (ret); + shar_printf(a, "#!/bin/sh\n"); + shar_printf(a, "# This is a shell archive\n"); shar->wrote_header = 1; } @@ -186,9 +192,7 @@ } /* Stock preparation for all file types. */ - ret = shar_printf(a, "echo x %s\n", name); - if (ret != ARCHIVE_OK) - return (ret); + shar_printf(a, "echo x %s\n", name); if (!S_ISDIR(st->st_mode)) { /* Try to create the dir. */ @@ -202,10 +206,8 @@ if (strcmp(p, ".") == 0) { /* Don't try to "mkdir ." */ } else if (shar->last_dir == NULL) { - ret = shar_printf(a, + shar_printf(a, "mkdir -p %s > /dev/null 2>&1\n", p); - if (ret != ARCHIVE_OK) - return (ret); shar->last_dir = p; } else if (strcmp(p, shar->last_dir) == 0) { /* We've already created this exact dir. */ @@ -215,10 +217,8 @@ /* We've already created a subdir. */ free(p); } else { - ret = shar_printf(a, + shar_printf(a, "mkdir -p %s > /dev/null 2>&1\n", p); - if (ret != ARCHIVE_OK) - return (ret); free(shar->last_dir); shar->last_dir = p; } @@ -227,40 +227,27 @@ /* Handle file-type specific issues. */ shar->has_data = 0; - if ((linkname = archive_entry_hardlink(entry)) != NULL) { - ret = shar_printf(a, "ln -f %s %s\n", linkname, name); - if (ret != ARCHIVE_OK) - return (ret); - } else if ((linkname = archive_entry_symlink(entry)) != NULL) { - ret = shar_printf(a, "ln -fs %s %s\n", linkname, name); - if (ret != ARCHIVE_OK) - return (ret); - } else { + if ((linkname = archive_entry_hardlink(entry)) != NULL) + shar_printf(a, "ln -f %s %s\n", linkname, name); + else if ((linkname = archive_entry_symlink(entry)) != NULL) + shar_printf(a, "ln -fs %s %s\n", linkname, name); + else { switch(st->st_mode & S_IFMT) { case S_IFREG: - if (archive_entry_size(entry) == 0) { - ret = shar_printf(a, "touch %s\n", name); - if (ret != ARCHIVE_OK) - return (ret); - } else { + if (archive_entry_size(entry) == 0) + shar_printf(a, "touch %s\n", name); + else { if (shar->dump) { - ret = shar_printf(a, + shar_printf(a, "uudecode -o %s << 'SHAR_END'\n", name); - if (ret != ARCHIVE_OK) - return (ret); - ret = shar_printf(a, "begin %o %s\n", + shar_printf(a, "begin %o %s\n", archive_entry_mode(entry) & 0777, name); - if (ret != ARCHIVE_OK) - return (ret); - } else { - ret = shar_printf(a, + } else + shar_printf(a, "sed 's/^X//' > %s << 'SHAR_END'\n", name); - if (ret != ARCHIVE_OK) - return (ret); - } shar->has_data = 1; shar->end_of_line = 1; shar->outpos = 0; @@ -268,10 +255,7 @@ } break; case S_IFDIR: - ret = shar_printf(a, "mkdir -p %s > /dev/null 2>&1\n", - name); - if (ret != ARCHIVE_OK) - return (ret); + shar_printf(a, "mkdir -p %s > /dev/null 2>&1\n", name); /* Record that we just created this directory. */ if (shar->last_dir != NULL) free(shar->last_dir); @@ -287,23 +271,17 @@ */ break; case S_IFIFO: - ret = shar_printf(a, "mkfifo %s\n", name); - if (ret != ARCHIVE_OK) - return (ret); + shar_printf(a, "mkfifo %s\n", name); break; case S_IFCHR: - ret = shar_printf(a, "mknod %s c %d %d\n", name, + shar_printf(a, "mknod %s c %d %d\n", name, archive_entry_rdevmajor(entry), archive_entry_rdevminor(entry)); - if (ret != ARCHIVE_OK) - return (ret); break; case S_IFBLK: - ret = shar_printf(a, "mknod %s b %d %d\n", name, + shar_printf(a, "mknod %s b %d %d\n", name, archive_entry_rdevmajor(entry), archive_entry_rdevminor(entry)); - if (ret != ARCHIVE_OK) - return (ret); break; default: return (ARCHIVE_WARN); @@ -315,18 +293,18 @@ /* XXX TODO: This could be more efficient XXX */ static int -archive_write_shar_data_sed(struct archive *a, const void *buff, size_t n) +archive_write_shar_data_sed(struct archive *a, const void *buff, size_t length) { struct shar *shar; const char *src; - int ret; + size_t n; shar = a->format_data; if (!shar->has_data) return (0); src = buff; - ret = ARCHIVE_OK; + n = length; shar->outpos = 0; while (n-- > 0) { if (shar->end_of_line) { @@ -338,17 +316,14 @@ shar->outbuff[shar->outpos++] = *src++; if (shar->outpos > sizeof(shar->outbuff) - 2) { - ret = (a->compression_write)(a, shar->outbuff, - shar->outpos); - if (ret != ARCHIVE_OK) - return (ret); + (a->compression_write)(a, shar->outbuff, shar->outpos); shar->outpos = 0; } } if (shar->outpos > 0) - ret = (a->compression_write)(a, shar->outbuff, shar->outpos); - return (ret); + (a->compression_write)(a, shar->outbuff, shar->outpos); + return (length); } #define UUENC(c) (((c)!=0) ? ((c) & 077) + ' ': '`') @@ -382,7 +357,6 @@ struct shar *shar; const char *src; size_t n; - int ret; shar = a->format_data; if (!shar->has_data) @@ -393,10 +367,8 @@ if (shar->uuavail == 3) uuencode_group(shar); if (shar->outpos >= 60) { - ret = shar_printf(a, "%c%s\n", UUENC(shar->outbytes), + shar_printf(a, "%c%s\n", UUENC(shar->outbytes), shar->outbuff); - if (ret != ARCHIVE_OK) - return (ret); shar->outpos = 0; shar->outbytes = 0; } @@ -404,7 +376,7 @@ shar->uubuffer[shar->uuavail++] = *src++; shar->outbytes++; } - return (ARCHIVE_OK); + return (length); } static int @@ -412,7 +384,6 @@ { const char *g, *p, *u; struct shar *shar; - int ret; shar = a->format_data; if (shar->entry == NULL) @@ -424,51 +395,37 @@ if (shar->uuavail > 0) uuencode_group(shar); if (shar->outpos > 0) { - ret = shar_printf(a, "%c%s\n", - UUENC(shar->outbytes), shar->outbuff); - if (ret != ARCHIVE_OK) - return (ret); + shar_printf(a, "%c%s\n", UUENC(shar->outbytes), + shar->outbuff); shar->outpos = 0; shar->uuavail = 0; shar->outbytes = 0; } - ret = shar_printf(a, "%c\n", UUENC(0)); - if (ret != ARCHIVE_OK) - return (ret); - ret = shar_printf(a, "end\n", UUENC(0)); - if (ret != ARCHIVE_OK) - return (ret); - ret = shar_printf(a, "SHAR_END\n"); - if (ret != ARCHIVE_OK) - return (ret); + shar_printf(a, "%c\n", UUENC(0)); + shar_printf(a, "end\n", UUENC(0)); + shar_printf(a, "SHAR_END\n"); } /* Restore file mode, owner, flags. */ /* * TODO: Don't immediately restore mode for * directories; defer that to end of script. */ - ret = shar_printf(a, "chmod %o %s\n", + shar_printf(a, "chmod %o %s\n", archive_entry_mode(shar->entry) & 07777, archive_entry_pathname(shar->entry)); - if (ret != ARCHIVE_OK) - return (ret); u = archive_entry_uname(shar->entry); g = archive_entry_gname(shar->entry); if (u != NULL || g != NULL) { - ret = shar_printf(a, "chown %s%s%s %s\n", + shar_printf(a, "chown %s%s%s %s\n", (u != NULL) ? u : "", (g != NULL) ? ":" : "", (g != NULL) ? g : "", archive_entry_pathname(shar->entry)); - if (ret != ARCHIVE_OK) - return (ret); } if ((p = archive_entry_fflags_text(shar->entry)) != NULL) { - ret = shar_printf(a, "chflags %s %s\n", p, + shar_printf(a, "chflags %s %s\n", p, archive_entry_pathname(shar->entry)); - if (ret != ARCHIVE_OK) - return (ret); } /* TODO: restore ACLs */ @@ -476,14 +433,9 @@ } else { if (shar->has_data) { /* Finish sed-encoded data: ensure last line ends. */ - if (!shar->end_of_line) { - ret = shar_printf(a, "\n"); - if (ret != ARCHIVE_OK) - return (ret); - } - ret = shar_printf(a, "SHAR_END\n"); - if (ret != ARCHIVE_OK) - return (ret); + if (!shar->end_of_line) + shar_printf(a, "\n"); + shar_printf(a, "SHAR_END\n"); } } @@ -496,7 +448,6 @@ archive_write_shar_finish(struct archive *a) { struct shar *shar; - int ret; /* * TODO: Accumulate list of directory names/modes and @@ -512,9 +463,7 @@ * shar_finish to free the format-specific data). */ if (shar->wrote_header) { - ret = shar_printf(a, "exit\n"); - if (ret != ARCHIVE_OK) - return (ret); + shar_printf(a, "exit\n"); /* Shar output is never padded. */ archive_write_set_bytes_in_last_block(a, 1); /* @@ -526,7 +475,8 @@ archive_entry_free(shar->entry); if (shar->last_dir != NULL) free(shar->last_dir); - archive_string_free(&(shar->work)); + if (shar->work != NULL) + free(shar->work); free(shar); a->format_data = NULL; return (ARCHIVE_OK); diff -u -x Makefile -x archive_check_magic.c -x CVS -I FreeBSD -r libarchive/archive_write_set_format_ustar.c libarchive-stable/archive_write_set_format_ustar.c --- libarchive/archive_write_set_format_ustar.c Sat Aug 21 13:41:49 2004 +++ libarchive-stable/archive_write_set_format_ustar.c Fri Aug 6 19:24:20 2004 @@ -157,8 +157,8 @@ if (ret != ARCHIVE_OK) return (ret); ret = (a->compression_write)(a, buff, 512); - if (ret != ARCHIVE_OK) - return (ret); + if (ret < 512) + return (ARCHIVE_FATAL); ustar->entry_bytes_remaining = archive_entry_size(entry); ustar->entry_padding = 0x1ff & (- ustar->entry_bytes_remaining); --------------030803060908090105000500--