bsdtar doesn't detect end of tape
Tim Kientzle
kientzle at freebsd.org
Thu Sep 23 08:24:34 PDT 2004
Oliver Lehmann wrote:
> Hi,
>
> I can store more files on tape with bsdtar than I'm able to read back.
>
> root at nudel dds2> tar -c -b 64 -v -f /dev/sa3 .
> [writes more files than the tape can handle - w/o an error!!]
> root at 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 at 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.
-------------- next part --------------
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 <errno.h>
-#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
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 <errno.h>
-#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <bzlib.h>
@@ -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);
More information about the freebsd-current
mailing list