summaryrefslogtreecommitdiffstats
path: root/usr.bin/tar
diff options
context:
space:
mode:
authorkientzle <kientzle@FreeBSD.org>2007-02-08 07:25:53 +0000
committerkientzle <kientzle@FreeBSD.org>2007-02-08 07:25:53 +0000
commit64e5ae3e30d0bb2d9cdd02df0032f22d366f13ad (patch)
tree341cbbc54016287dc84be5eaa070194070ccbcdb /usr.bin/tar
parent5101ea24dc992d716e41ebe5a2360d0e9af10968 (diff)
downloadFreeBSD-src-64e5ae3e30d0bb2d9cdd02df0032f22d366f13ad.zip
FreeBSD-src-64e5ae3e30d0bb2d9cdd02df0032f22d366f13ad.tar.gz
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.
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 b9c854b..09016dd 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,
OpenPOWER on IntegriCloud