aboutsummaryrefslogtreecommitdiff
path: root/usr.bin/tar
diff options
context:
space:
mode:
authorTim Kientzle <kientzle@FreeBSD.org>2007-02-08 07:25:53 +0000
committerTim Kientzle <kientzle@FreeBSD.org>2007-02-08 07:25:53 +0000
commitd00914ea854a67962f482efb4f97c434e226026f (patch)
tree341cbbc54016287dc84be5eaa070194070ccbcdb /usr.bin/tar
parent261667c97c56a71287659a66213812edbc1aa71b (diff)
downloadsrc-d00914ea854a67962f482efb4f97c434e226026f.tar.gz
src-d00914ea854a67962f482efb4f97c434e226026f.zip
Update -r handling:
* Create file if it doesn't exist. * If archive is "empty", then append to it with pax restricted * If user specified a format, use that if it's compatible with the existing format.
Notes
Notes: svn path=/head/; revision=166563
Diffstat (limited to 'usr.bin/tar')
-rw-r--r--usr.bin/tar/write.c52
1 files changed, 40 insertions, 12 deletions
diff --git a/usr.bin/tar/write.c b/usr.bin/tar/write.c
index b9c854bfec91..09016ddc76a5 100644
--- a/usr.bin/tar/write.c
+++ b/usr.bin/tar/write.c
@@ -203,8 +203,8 @@ tar_mode_c(struct bsdtar *bsdtar)
}
/*
- * Same as 'c', except we only support tar formats in uncompressed
- * files on disk.
+ * Same as 'c', except we only support tar or empty formats in
+ * uncompressed files on disk.
*/
void
tar_mode_r(struct bsdtar *bsdtar)
@@ -213,13 +213,14 @@ tar_mode_r(struct bsdtar *bsdtar)
int format;
struct archive *a;
struct archive_entry *entry;
+ int r;
/* Sanity-test some arguments and the file. */
test_for_append(bsdtar);
format = ARCHIVE_FORMAT_TAR_PAX_RESTRICTED;
- bsdtar->fd = open(bsdtar->filename, O_RDWR);
+ bsdtar->fd = open(bsdtar->filename, O_RDWR | O_CREAT, 0666);
if (bsdtar->fd < 0)
bsdtar_errc(bsdtar, 1, errno,
"Cannot open %s", bsdtar->filename);
@@ -228,7 +229,11 @@ tar_mode_r(struct bsdtar *bsdtar)
archive_read_support_compression_all(a);
archive_read_support_format_tar(a);
archive_read_support_format_gnutar(a);
- archive_read_open_fd(a, bsdtar->fd, 10240);
+ r = archive_read_open_fd(a, bsdtar->fd, 10240);
+ if (r != ARCHIVE_OK)
+ bsdtar_errc(bsdtar, 1, archive_errno(a),
+ "Can't read archive %s: %s", bsdtar->filename,
+ archive_error_string(a));
while (0 == archive_read_next_header(a, &entry)) {
if (archive_compression(a) != ARCHIVE_COMPRESSION_NONE) {
archive_read_finish(a);
@@ -247,13 +252,37 @@ tar_mode_r(struct bsdtar *bsdtar)
a = archive_write_new();
archive_write_set_compression_none(a);
/*
- * Set format to same one auto-detected above, except use
- * ustar for appending to GNU tar, since the library doesn't
- * write GNU tar format.
+ * Set the format to be used for writing. To allow people to
+ * extend empty files, we need to allow them to specify the format,
+ * which opens the possibility that they will specify a format that
+ * doesn't match the existing format. Hence, the following bit
+ * of arcane ugliness.
*/
- if (format == ARCHIVE_FORMAT_TAR_GNUTAR)
- format = ARCHIVE_FORMAT_TAR_USTAR;
- archive_write_set_format(a, format);
+
+ if (bsdtar->create_format != NULL) {
+ /* If the user requested a format, use that, but ... */
+ archive_write_set_format_by_name(a,
+ bsdtar->create_format);
+ /* ... complain if it's not compatible. */
+ format &= ARCHIVE_FORMAT_BASE_MASK;
+ if (format != (int)(archive_format(a) & ARCHIVE_FORMAT_BASE_MASK)
+ && format != ARCHIVE_FORMAT_EMPTY) {
+ bsdtar_errc(bsdtar, 1, 0,
+ "Format %s is incompatible with the archive %s.",
+ bsdtar->create_format, bsdtar->filename);
+ }
+ } else {
+ /*
+ * Just preserve the current format, with a little care
+ * for formats that libarchive can't write.
+ */
+ if (format == ARCHIVE_FORMAT_TAR_GNUTAR)
+ /* TODO: When gtar supports pax, use pax restricted. */
+ format = ARCHIVE_FORMAT_TAR_USTAR;
+ if (format == ARCHIVE_FORMAT_EMPTY)
+ format = ARCHIVE_FORMAT_TAR_PAX_RESTRICTED;
+ archive_write_set_format(a, format);
+ }
lseek(bsdtar->fd, end_offset, SEEK_SET); /* XXX check return val XXX */
archive_write_open_fd(a, bsdtar->fd); /* XXX check return val XXX */
@@ -1433,8 +1462,7 @@ test_for_append(struct bsdtar *bsdtar)
"Cannot append to %s with compression", bsdtar->filename);
if (stat(bsdtar->filename, &s) != 0)
- bsdtar_errc(bsdtar, 1, errno,
- "Cannot stat %s", bsdtar->filename);
+ return;
if (!S_ISREG(s.st_mode))
bsdtar_errc(bsdtar, 1, 0,