Clean up the error handling in the

write path.  In particular, this should
solve some problems people have seen with
bsdtar not exiting on various write errors.
This commit is contained in:
Tim Kientzle 2004-11-05 05:26:30 +00:00
parent 9fb9f10286
commit 3ede53f3e1
9 changed files with 213 additions and 133 deletions

View File

@ -190,6 +190,7 @@ Build and write a header using the data in the provided
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
@ -321,20 +322,19 @@ and
.Fn archive_error_string
functions will return appropriate values.
Note that if the client-provided write callback function
returns -1, that error will be propagated back to the caller
returns a non-zero value, 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 .
In such a case, the
The client callback can call
.Fn archive_set_error
to provide values that can then be retrieved by
.Fn archive_errno
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.
and
.Fn archive_error_string .
.Sh SEE ALSO
.Xr tar 1 ,
.Xr libarchive 3 ,

View File

@ -215,9 +215,12 @@ archive_write_header(struct archive *a, struct archive_entry *entry)
/*
* Note that the compressor is responsible for blocking.
*/
/* Should be "ssize_t", but that breaks the ABI. <sigh> */
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);
return (a->format_write_data(a, buff, s));
ret = (a->format_write_data)(a, buff, s);
return (ret == ARCHIVE_OK ? (ssize_t)s : -1);
}

View File

@ -32,6 +32,7 @@
__FBSDID("$FreeBSD$");
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <bzlib.h>
@ -153,15 +154,17 @@ archive_compressor_bzip2_init(struct archive *a)
/*
* Write data to the compressed stream.
*
* Returns ARCHIVE_OK if all data written, error otherwise.
*/
static ssize_t
static int
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) {
if (a->client_writer == NULL) {
archive_set_error(a, ARCHIVE_ERRNO_PROGRAMMER,
"No write callback is registered? "
"This is probably an internal programming error.");
@ -175,9 +178,9 @@ archive_compressor_bzip2_write(struct archive *a, const void *buff,
SET_NEXT_IN(state, buff);
state->stream.avail_in = length;
if (drive_compressor(a, state, 0))
return (-1);
return (ARCHIVE_FATAL);
a->file_position += length;
return (length);
return (ARCHIVE_OK);
}
@ -191,6 +194,7 @@ archive_compressor_bzip2_finish(struct archive *a)
int ret;
struct private_data *state;
ssize_t target_block_length;
ssize_t bytes_written;
unsigned tocopy;
state = a->compression_data;
@ -246,12 +250,16 @@ archive_compressor_bzip2_finish(struct archive *a)
}
/* Write the last block */
ret = (a->client_writer)(a, a->client_data, state->compressed,
block_length);
bytes_written = (a->client_writer)(a, a->client_data,
state->compressed, block_length);
a->raw_position += ret;
if (ret != 0)
goto cleanup;
/* TODO: Handle short write of final block. */
if (bytes_written <= 0)
ret = ARCHIVE_FATAL;
else {
a->raw_position += ret;
ret = ARCHIVE_OK;
}
/* Cleanup: shut down compressor, release memory, etc. */
cleanup:
@ -284,27 +292,28 @@ cleanup:
static int
drive_compressor(struct archive *a, struct private_data *state, int finishing)
{
size_t ret;
ssize_t bytes_written;
int ret;
for (;;) {
if (state->stream.avail_out == 0) {
ret = (a->client_writer)(a, a->client_data,
bytes_written = (a->client_writer)(a, a->client_data,
state->compressed, state->compressed_buffer_size);
if (ret <= 0) {
if (bytes_written <= 0) {
/* TODO: Handle this write failure */
return (ARCHIVE_FATAL);
} else if (ret < state->compressed_buffer_size) {
} else if ((size_t)bytes_written < state->compressed_buffer_size) {
/* Short write: Move remainder to
* front and keep filling */
memmove(state->compressed,
state->compressed + ret,
state->compressed_buffer_size - ret);
state->compressed + bytes_written,
state->compressed_buffer_size - bytes_written);
}
a->raw_position += ret;
a->raw_position += bytes_written;
state->stream.next_out = state->compressed +
state->compressed_buffer_size - ret;
state->stream.avail_out = ret;
state->compressed_buffer_size - bytes_written;
state->stream.avail_out = bytes_written;
}
ret = BZ2_bzCompress(&(state->stream),

View File

@ -179,7 +179,7 @@ archive_compressor_gzip_init(struct archive *a)
/*
* Write data to the compressed stream.
*/
static ssize_t
static int
archive_compressor_gzip_write(struct archive *a, const void *buff,
size_t length)
{
@ -187,7 +187,7 @@ archive_compressor_gzip_write(struct archive *a, const void *buff,
int ret;
state = a->compression_data;
if (!a->client_writer) {
if (a->client_writer == NULL) {
archive_set_error(a, ARCHIVE_ERRNO_PROGRAMMER,
"No write callback is registered? "
"This is probably an internal programming error.");
@ -205,7 +205,7 @@ archive_compressor_gzip_write(struct archive *a, const void *buff,
return (ret);
a->file_position += length;
return (length);
return (ARCHIVE_OK);
}
@ -215,7 +215,7 @@ archive_compressor_gzip_write(struct archive *a, const void *buff,
static int
archive_compressor_gzip_finish(struct archive *a)
{
ssize_t block_length, target_block_length;
ssize_t block_length, target_block_length, bytes_written;
int ret;
struct private_data *state;
unsigned tocopy;
@ -273,9 +273,13 @@ archive_compressor_gzip_finish(struct archive *a)
/* If it overflowed, flush and start a new block. */
if (tocopy < 8) {
ret = (a->client_writer)(a, a->client_data, state->compressed,
state->compressed_buffer_size);
a->raw_position += ret;
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;
state->stream.next_out = state->compressed;
state->stream.avail_out = state->compressed_buffer_size;
memcpy(state->stream.next_out, trailer + tocopy, 8-tocopy);
@ -306,9 +310,13 @@ archive_compressor_gzip_finish(struct archive *a)
}
/* Write the last block */
ret = (a->client_writer)(a, a->client_data, state->compressed,
block_length);
a->raw_position += ret;
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;
/* Cleanup: shut down compressor, release memory, etc. */
cleanup:
@ -340,27 +348,28 @@ cleanup:
static int
drive_compressor(struct archive *a, struct private_data *state, int finishing)
{
size_t ret;
ssize_t bytes_written;
int ret;
for (;;) {
if (state->stream.avail_out == 0) {
ret = (a->client_writer)(a, a->client_data,
bytes_written = (a->client_writer)(a, a->client_data,
state->compressed, state->compressed_buffer_size);
if (ret <= 0) {
if (bytes_written <= 0) {
/* TODO: Handle this write failure */
return (ARCHIVE_FATAL);
} else if (ret < state->compressed_buffer_size) {
} else if ((size_t)bytes_written < state->compressed_buffer_size) {
/* Short write: Move remaining to
* front of block and keep filling */
memmove(state->compressed,
state->compressed + ret,
state->compressed_buffer_size - ret);
state->compressed + bytes_written,
state->compressed_buffer_size - bytes_written);
}
a->raw_position += ret;
a->raw_position += bytes_written;
state->stream.next_out
= state->compressed +
state->compressed_buffer_size - ret;
state->stream.avail_out = ret;
state->compressed_buffer_size - bytes_written;
state->stream.avail_out = bytes_written;
}
ret = deflate(&(state->stream),

View File

@ -104,13 +104,13 @@ archive_compressor_none_init(struct archive *a)
/*
* Write data to the stream.
*/
static ssize_t
static int
archive_compressor_none_write(struct archive *a, const void *vbuff,
size_t length)
{
const char *buff;
ssize_t remaining, to_copy;
int ret;
ssize_t bytes_written;
struct archive_none *state;
state = a->compression_data;
@ -129,10 +129,12 @@ archive_compressor_none_write(struct archive *a, const void *vbuff,
* output buffer.
*/
if (state->avail == 0) {
ret = (a->client_writer)(a, a->client_data,
bytes_written = (a->client_writer)(a, a->client_data,
state->buffer, state->buffer_size);
/* XXX TODO: if ret < state->buffer_size XXX */
a->raw_position += ret;
if (bytes_written <= 0)
return (ARCHIVE_FATAL);
/* XXX TODO: if bytes_written < state->buffer_size */
a->raw_position += bytes_written;
state->next = state->buffer;
state->avail = state->buffer_size;
}
@ -147,7 +149,7 @@ archive_compressor_none_write(struct archive *a, const void *vbuff,
remaining -= to_copy;
}
a->file_position += length;
return (length);
return (ARCHIVE_OK);
}
@ -159,6 +161,7 @@ archive_compressor_none_finish(struct archive *a)
{
ssize_t block_length;
ssize_t target_block_length;
ssize_t bytes_written;
int ret;
int ret2;
struct archive_none *state;
@ -193,9 +196,14 @@ archive_compressor_none_finish(struct archive *a)
target_block_length - block_length);
block_length = target_block_length;
}
ret = (a->client_writer)(a, a->client_data, state->buffer,
block_length);
a->raw_position += ret;
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;
}
}
/* Close the output */

View File

@ -99,7 +99,7 @@ archive_write_cpio_header(struct archive *a, struct archive_entry *entry)
{
struct cpio *cpio;
const char *p, *path;
int pathlength, ret, written;
int pathlength, ret;
const struct stat *st;
struct cpio_header h;
@ -142,19 +142,19 @@ archive_write_cpio_header(struct archive *a, struct archive_entry *entry)
else
format_octal(st->st_size, &h.c_filesize, sizeof(h.c_filesize));
written = (a->compression_write)(a, &h, sizeof(h));
if (written < (int)sizeof(h))
ret = (a->compression_write)(a, &h, sizeof(h));
if (ret != ARCHIVE_OK)
return (ARCHIVE_FATAL);
written = (a->compression_write)(a, path, pathlength);
if (written < (int)pathlength)
ret = (a->compression_write)(a, path, pathlength);
if (ret != ARCHIVE_OK)
return (ARCHIVE_FATAL);
cpio->entry_bytes_remaining = st->st_size;
/* Write the symlink now. */
if (p != NULL && *p != '\0')
(a->compression_write)(a, p, strlen(p));
ret = (a->compression_write)(a, p, strlen(p));
return (ret);
}
@ -233,13 +233,13 @@ archive_write_cpio_finish_entry(struct archive *a)
int to_write, ret;
cpio = a->format_data;
ret = 0;
ret = ARCHIVE_OK;
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 < to_write)
return (-1);
if (ret != ARCHIVE_OK)
return (ret);
cpio->entry_bytes_remaining -= to_write;
}
return (ret);

View File

@ -622,7 +622,7 @@ archive_write_pax_header(struct archive *a,
__archive_write_format_header_ustar(a, ustarbuff, entry_main, -1, 0);
/* If we built any extended attributes, write that entry first. */
ret = 0;
ret = ARCHIVE_OK;
if (archive_strlen(&(pax->pax_header)) > 0) {
struct stat st;
struct archive_entry *pax_attr_entry;
@ -663,7 +663,7 @@ archive_write_pax_header(struct archive *a,
exit(1);
}
r = (a->compression_write)(a, paxbuff, 512);
if (r < 512) {
if (r != ARCHIVE_OK) {
pax->entry_bytes_remaining = 0;
pax->entry_padding = 0;
return (ARCHIVE_FATAL);
@ -677,7 +677,7 @@ archive_write_pax_header(struct archive *a,
r = archive_write_data(a, pax->pax_header.s,
archive_strlen(&(pax->pax_header)));
a->state = oldstate;
if (r < (int)archive_strlen(&(pax->pax_header))) {
if (r != ARCHIVE_OK) {
/* If a write fails, we're pretty much toast. */
return (ARCHIVE_FATAL);
}
@ -687,8 +687,8 @@ archive_write_pax_header(struct archive *a,
/* Write the header for main entry. */
r = (a->compression_write)(a, ustarbuff, 512);
if (ret != ARCHIVE_OK)
ret = (r < 512) ? ARCHIVE_FATAL : ARCHIVE_OK;
if (r != ARCHIVE_OK)
return (r);
/*
* Inform the client of the on-disk size we're using, so
@ -839,9 +839,9 @@ write_nulls(struct archive *a, size_t padding)
while (padding > 0) {
to_write = padding < a->null_length ? padding : a->null_length;
ret = (a->compression_write)(a, a->nulls, to_write);
if (ret <= 0)
return (ARCHIVE_FATAL);
padding -= ret;
if (ret != ARCHIVE_OK)
return (ret);
padding -= to_write;
}
return (ARCHIVE_OK);
}

View File

@ -50,8 +50,7 @@ struct shar {
int uuavail;
char uubuffer[3];
int wrote_header;
char *work;
size_t work_len;
struct archive_string work;
};
static int archive_write_shar_finish(struct archive *);
@ -70,23 +69,13 @@ shar_printf(struct archive *a, const char *fmt, ...)
{
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);
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)));
archive_string_empty(&(shar->work));
archive_string_vsprintf(&(shar->work), fmt, ap);
ret = ((a->compression_write)(a, shar->work.s, strlen(shar->work.s)));
va_end(ap);
return (ret);
}
@ -149,11 +138,16 @@ archive_write_shar_header(struct archive *a, struct archive_entry *entry)
char *p, *pp;
struct shar *shar;
const struct stat *st;
int ret;
shar = a->format_data;
if (!shar->wrote_header) {
shar_printf(a, "#!/bin/sh\n");
shar_printf(a, "# This is a shell archive\n");
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->wrote_header = 1;
}
@ -192,7 +186,9 @@ archive_write_shar_header(struct archive *a, struct archive_entry *entry)
}
/* Stock preparation for all file types. */
shar_printf(a, "echo x %s\n", name);
ret = shar_printf(a, "echo x %s\n", name);
if (ret != ARCHIVE_OK)
return (ret);
if (!S_ISDIR(st->st_mode)) {
/* Try to create the dir. */
@ -206,8 +202,10 @@ archive_write_shar_header(struct archive *a, struct archive_entry *entry)
if (strcmp(p, ".") == 0) {
/* Don't try to "mkdir ." */
} else if (shar->last_dir == NULL) {
shar_printf(a,
ret = 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. */
@ -217,8 +215,10 @@ archive_write_shar_header(struct archive *a, struct archive_entry *entry)
/* We've already created a subdir. */
free(p);
} else {
shar_printf(a,
ret = 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,27 +227,41 @@ archive_write_shar_header(struct archive *a, struct archive_entry *entry)
/* Handle file-type specific issues. */
shar->has_data = 0;
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 {
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 {
switch(st->st_mode & S_IFMT) {
case S_IFREG:
if (archive_entry_size(entry) == 0)
shar_printf(a, "touch %s\n", name);
else {
if (archive_entry_size(entry) == 0) {
/* More portable than "touch." */
ret = shar_printf(a, "test -e \"%s\" || :> \"%s\"\n", name, name);
if (ret != ARCHIVE_OK)
return (ret);
} else {
if (shar->dump) {
shar_printf(a,
ret = shar_printf(a,
"uudecode -o %s << 'SHAR_END'\n",
name);
shar_printf(a, "begin %o %s\n",
if (ret != ARCHIVE_OK)
return (ret);
ret = shar_printf(a, "begin %o %s\n",
archive_entry_mode(entry) & 0777,
name);
} else
shar_printf(a,
if (ret != ARCHIVE_OK)
return (ret);
} else {
ret = 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;
@ -255,7 +269,10 @@ archive_write_shar_header(struct archive *a, struct archive_entry *entry)
}
break;
case S_IFDIR:
shar_printf(a, "mkdir -p %s > /dev/null 2>&1\n", name);
ret = shar_printf(a, "mkdir -p %s > /dev/null 2>&1\n",
name);
if (ret != ARCHIVE_OK)
return (ret);
/* Record that we just created this directory. */
if (shar->last_dir != NULL)
free(shar->last_dir);
@ -271,17 +288,23 @@ archive_write_shar_header(struct archive *a, struct archive_entry *entry)
*/
break;
case S_IFIFO:
shar_printf(a, "mkfifo %s\n", name);
ret = shar_printf(a, "mkfifo %s\n", name);
if (ret != ARCHIVE_OK)
return (ret);
break;
case S_IFCHR:
shar_printf(a, "mknod %s c %d %d\n", name,
ret = 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:
shar_printf(a, "mknod %s b %d %d\n", name,
ret = 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);
@ -293,18 +316,18 @@ archive_write_shar_header(struct archive *a, struct archive_entry *entry)
/* XXX TODO: This could be more efficient XXX */
static int
archive_write_shar_data_sed(struct archive *a, const void *buff, size_t length)
archive_write_shar_data_sed(struct archive *a, const void *buff, size_t n)
{
struct shar *shar;
const char *src;
size_t n;
int ret;
shar = a->format_data;
if (!shar->has_data)
return (0);
src = buff;
n = length;
ret = ARCHIVE_OK;
shar->outpos = 0;
while (n-- > 0) {
if (shar->end_of_line) {
@ -316,14 +339,17 @@ archive_write_shar_data_sed(struct archive *a, const void *buff, size_t length)
shar->outbuff[shar->outpos++] = *src++;
if (shar->outpos > sizeof(shar->outbuff) - 2) {
(a->compression_write)(a, shar->outbuff, shar->outpos);
ret = (a->compression_write)(a, shar->outbuff,
shar->outpos);
if (ret != ARCHIVE_OK)
return (ret);
shar->outpos = 0;
}
}
if (shar->outpos > 0)
(a->compression_write)(a, shar->outbuff, shar->outpos);
return (length);
ret = (a->compression_write)(a, shar->outbuff, shar->outpos);
return (ret);
}
#define UUENC(c) (((c)!=0) ? ((c) & 077) + ' ': '`')
@ -357,6 +383,7 @@ archive_write_shar_data_uuencode(struct archive *a, const void *buff,
struct shar *shar;
const char *src;
size_t n;
int ret;
shar = a->format_data;
if (!shar->has_data)
@ -367,8 +394,10 @@ archive_write_shar_data_uuencode(struct archive *a, const void *buff,
if (shar->uuavail == 3)
uuencode_group(shar);
if (shar->outpos >= 60) {
shar_printf(a, "%c%s\n", UUENC(shar->outbytes),
ret = shar_printf(a, "%c%s\n", UUENC(shar->outbytes),
shar->outbuff);
if (ret != ARCHIVE_OK)
return (ret);
shar->outpos = 0;
shar->outbytes = 0;
}
@ -376,7 +405,7 @@ archive_write_shar_data_uuencode(struct archive *a, const void *buff,
shar->uubuffer[shar->uuavail++] = *src++;
shar->outbytes++;
}
return (length);
return (ARCHIVE_OK);
}
static int
@ -384,6 +413,7 @@ archive_write_shar_finish_entry(struct archive *a)
{
const char *g, *p, *u;
struct shar *shar;
int ret;
shar = a->format_data;
if (shar->entry == NULL)
@ -395,37 +425,51 @@ archive_write_shar_finish_entry(struct archive *a)
if (shar->uuavail > 0)
uuencode_group(shar);
if (shar->outpos > 0) {
shar_printf(a, "%c%s\n", UUENC(shar->outbytes),
shar->outbuff);
ret = shar_printf(a, "%c%s\n",
UUENC(shar->outbytes), shar->outbuff);
if (ret != ARCHIVE_OK)
return (ret);
shar->outpos = 0;
shar->uuavail = 0;
shar->outbytes = 0;
}
shar_printf(a, "%c\n", UUENC(0));
shar_printf(a, "end\n", UUENC(0));
shar_printf(a, "SHAR_END\n");
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);
}
/* Restore file mode, owner, flags. */
/*
* TODO: Don't immediately restore mode for
* directories; defer that to end of script.
*/
shar_printf(a, "chmod %o %s\n",
ret = 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) {
shar_printf(a, "chown %s%s%s %s\n",
ret = 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) {
shar_printf(a, "chflags %s %s\n", p,
ret = shar_printf(a, "chflags %s %s\n", p,
archive_entry_pathname(shar->entry));
if (ret != ARCHIVE_OK)
return (ret);
}
/* TODO: restore ACLs */
@ -433,9 +477,14 @@ archive_write_shar_finish_entry(struct archive *a)
} else {
if (shar->has_data) {
/* Finish sed-encoded data: ensure last line ends. */
if (!shar->end_of_line)
shar_printf(a, "\n");
shar_printf(a, "SHAR_END\n");
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);
}
}
@ -448,6 +497,7 @@ static int
archive_write_shar_finish(struct archive *a)
{
struct shar *shar;
int ret;
/*
* TODO: Accumulate list of directory names/modes and
@ -463,7 +513,9 @@ archive_write_shar_finish(struct archive *a)
* shar_finish to free the format-specific data).
*/
if (shar->wrote_header) {
shar_printf(a, "exit\n");
ret = shar_printf(a, "exit\n");
if (ret != ARCHIVE_OK)
return (ret);
/* Shar output is never padded. */
archive_write_set_bytes_in_last_block(a, 1);
/*
@ -475,8 +527,7 @@ archive_write_shar_finish(struct archive *a)
archive_entry_free(shar->entry);
if (shar->last_dir != NULL)
free(shar->last_dir);
if (shar->work != NULL)
free(shar->work);
archive_string_free(&(shar->work));
free(shar);
a->format_data = NULL;
return (ARCHIVE_OK);

View File

@ -157,8 +157,8 @@ archive_write_ustar_header(struct archive *a, struct archive_entry *entry)
if (ret != ARCHIVE_OK)
return (ret);
ret = (a->compression_write)(a, buff, 512);
if (ret < 512)
return (ARCHIVE_FATAL);
if (ret != ARCHIVE_OK)
return (ret);
ustar->entry_bytes_remaining = archive_entry_size(entry);
ustar->entry_padding = 0x1ff & (- ustar->entry_bytes_remaining);
@ -469,8 +469,8 @@ write_nulls(struct archive *a, size_t padding)
while (padding > 0) {
to_write = padding < a->null_length ? padding : a->null_length;
ret = (a->compression_write)(a, a->nulls, to_write);
if (ret < to_write)
return (ARCHIVE_FATAL);
if (ret != ARCHIVE_OK)
return (ret);
padding -= to_write;
}
return (ARCHIVE_OK);