summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorkientzle <kientzle@FreeBSD.org>2008-08-31 07:21:46 +0000
committerkientzle <kientzle@FreeBSD.org>2008-08-31 07:21:46 +0000
commitfe3cf0e14f5d3626c61231a9bc8e9ca6ba3e4812 (patch)
tree9248378ba27f4626b1fb450b136823599152972c /lib
parentede0c9fe5ce3b4965f70ddd1f83e6eabc439446d (diff)
downloadFreeBSD-src-fe3cf0e14f5d3626c61231a9bc8e9ca6ba3e4812.zip
FreeBSD-src-fe3cf0e14f5d3626c61231a9bc8e9ca6ba3e4812.tar.gz
New mtree writer, thanks to Joerg Sonnenberger.
Obtained from: Joerg Sonnenberger
Diffstat (limited to 'lib')
-rw-r--r--lib/libarchive/Makefile1
-rw-r--r--lib/libarchive/archive.h1
-rw-r--r--lib/libarchive/archive_write_set_format.c1
-rw-r--r--lib/libarchive/archive_write_set_format_by_name.c1
-rw-r--r--lib/libarchive/archive_write_set_format_mtree.c259
5 files changed, 263 insertions, 0 deletions
diff --git a/lib/libarchive/Makefile b/lib/libarchive/Makefile
index 0d10500..d41e456 100644
--- a/lib/libarchive/Makefile
+++ b/lib/libarchive/Makefile
@@ -65,6 +65,7 @@ SRCS= archive_check_magic.c \
archive_write_set_format_by_name.c \
archive_write_set_format_cpio.c \
archive_write_set_format_cpio_newc.c \
+ archive_write_set_format_mtree.c \
archive_write_set_format_pax.c \
archive_write_set_format_shar.c \
archive_write_set_format_ustar.c \
diff --git a/lib/libarchive/archive.h b/lib/libarchive/archive.h
index 791da1d..d383ab5 100644
--- a/lib/libarchive/archive.h
+++ b/lib/libarchive/archive.h
@@ -465,6 +465,7 @@ __LA_DECL int archive_write_set_format_ar_bsd(struct archive *);
__LA_DECL int archive_write_set_format_ar_svr4(struct archive *);
__LA_DECL int archive_write_set_format_cpio(struct archive *);
__LA_DECL int archive_write_set_format_cpio_newc(struct archive *);
+__LA_DECL int archive_write_set_format_mtree(struct archive *);
/* TODO: int archive_write_set_format_old_tar(struct archive *); */
__LA_DECL int archive_write_set_format_pax(struct archive *);
__LA_DECL int archive_write_set_format_pax_restricted(struct archive *);
diff --git a/lib/libarchive/archive_write_set_format.c b/lib/libarchive/archive_write_set_format.c
index 5b879bd..369f2c9 100644
--- a/lib/libarchive/archive_write_set_format.c
+++ b/lib/libarchive/archive_write_set_format.c
@@ -44,6 +44,7 @@ struct { int code; int (*setter)(struct archive *); } codes[] =
{ ARCHIVE_FORMAT_CPIO, archive_write_set_format_cpio },
{ ARCHIVE_FORMAT_CPIO_SVR4_NOCRC, archive_write_set_format_cpio_newc },
{ ARCHIVE_FORMAT_CPIO_POSIX, archive_write_set_format_cpio },
+ { ARCHIVE_FORMAT_MTREE, archive_write_set_format_mtree },
{ ARCHIVE_FORMAT_SHAR, archive_write_set_format_shar },
{ ARCHIVE_FORMAT_SHAR_BASE, archive_write_set_format_shar },
{ ARCHIVE_FORMAT_SHAR_DUMP, archive_write_set_format_shar_dump },
diff --git a/lib/libarchive/archive_write_set_format_by_name.c b/lib/libarchive/archive_write_set_format_by_name.c
index 00f7242..6daa51c 100644
--- a/lib/libarchive/archive_write_set_format_by_name.c
+++ b/lib/libarchive/archive_write_set_format_by_name.c
@@ -49,6 +49,7 @@ struct { const char *name; int (*setter)(struct archive *); } names[] =
{ "argnu", archive_write_set_format_ar_svr4 },
{ "arsvr4", archive_write_set_format_ar_svr4 },
{ "cpio", archive_write_set_format_cpio },
+ { "mtree", archive_write_set_format_mtree },
{ "newc", archive_write_set_format_cpio_newc },
{ "odc", archive_write_set_format_cpio },
{ "pax", archive_write_set_format_pax },
diff --git a/lib/libarchive/archive_write_set_format_mtree.c b/lib/libarchive/archive_write_set_format_mtree.c
new file mode 100644
index 0000000..ff01aa1
--- /dev/null
+++ b/lib/libarchive/archive_write_set_format_mtree.c
@@ -0,0 +1,259 @@
+/*-
+ * Copyright (c) 2008 Joerg Sonnenberger
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "archive_platform.h"
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "archive.h"
+#include "archive_entry.h"
+#include "archive_private.h"
+#include "archive_write_private.h"
+
+struct mtree_writer {
+ struct archive_entry *entry;
+ struct archive_string buf;
+ int first;
+};
+
+static int
+mtree_safe_char(char c)
+{
+ if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
+ return 1;
+ if (c >= '0' && c <= '9')
+ return 1;
+ if (c == 35 || c == 61 || c == 92)
+ return 0; /* #, = and \ are always quoted */
+
+ if (c >= 33 && c <= 47) /* !"$%&'()*+,-./ */
+ return 1;
+ if (c >= 58 && c <= 64) /* :;<>?@ */
+ return 1;
+ if (c >= 91 && c <= 96) /* []^_` */
+ return 1;
+ if (c >= 123 && c <= 126) /* {|}~ */
+ return 1;
+ return 0;
+}
+
+static void
+mtree_quote(struct mtree_writer *mtree, const char *str)
+{
+ const char *start;
+ char buf[4];
+ unsigned char c;
+
+ for (start = str; *str != '\0'; ++str) {
+ if (mtree_safe_char(*str))
+ continue;
+ if (start != str)
+ archive_strncat(&mtree->buf, start, str - start);
+ c = (unsigned char)*str;
+ buf[0] = '\\';
+ buf[1] = (c / 64) + '0';
+ buf[2] = (c / 8 % 8) + '0';
+ buf[3] = (c % 8) + '0';
+ archive_strncat(&mtree->buf, buf, 4);
+ start = str + 1;
+ }
+
+ if (start != str)
+ archive_strncat(&mtree->buf, start, str - start);
+}
+
+static int
+archive_write_mtree_header(struct archive_write *a,
+ struct archive_entry *entry)
+{
+ struct mtree_writer *mtree= a->format_data;
+ const char *path;
+
+ mtree->entry = archive_entry_clone(entry);
+ path = archive_entry_pathname(mtree->entry);
+
+ if (mtree->first) {
+ mtree->first = 0;
+ archive_strcat(&mtree->buf, "#mtree\n");
+ }
+
+ mtree_quote(mtree, path);
+
+ return (ARCHIVE_OK);
+}
+
+static int
+archive_write_mtree_finish_entry(struct archive_write *a)
+{
+ struct mtree_writer *mtree = a->format_data;
+ struct archive_entry *entry;
+ const char *name;
+ int ret;
+
+ entry = mtree->entry;
+ if (entry == NULL) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
+ "Finished entry without being open first.");
+ return (ARCHIVE_FATAL);
+ }
+ mtree->entry = NULL;
+
+ if (archive_entry_nlink(entry) != 1 &&
+ archive_entry_filetype(entry) != AE_IFDIR)
+ archive_string_sprintf(&mtree->buf,
+ " nlink=%u", archive_entry_nlink(entry));
+
+ if ((name = archive_entry_gname(entry)) != NULL) {
+ archive_strcat(&mtree->buf, " gname=");
+ mtree_quote(mtree, name);
+ }
+ if ((name = archive_entry_uname(entry)) != NULL) {
+ archive_strcat(&mtree->buf, " uname=");
+ mtree_quote(mtree, name);
+ }
+ if ((name = archive_entry_fflags_text(entry)) != NULL) {
+ archive_strcat(&mtree->buf, " flags=");
+ mtree_quote(mtree, name);
+ }
+
+ archive_string_sprintf(&mtree->buf,
+ " time=%jd mode=%o gid=%jd uid=%jd",
+ (intmax_t)archive_entry_mtime(entry),
+ archive_entry_mode(entry) & 07777,
+ (intmax_t)archive_entry_gid(entry),
+ (intmax_t)archive_entry_uid(entry));
+
+ switch (archive_entry_filetype(entry)) {
+ case AE_IFLNK:
+ archive_strcat(&mtree->buf, " type=link link=");
+ mtree_quote(mtree, archive_entry_symlink(entry));
+ archive_strcat(&mtree->buf, "\n");
+ break;
+ case AE_IFSOCK:
+ archive_strcat(&mtree->buf, " type=socket\n");
+ break;
+ case AE_IFCHR:
+ archive_string_sprintf(&mtree->buf,
+ " type=char device=native,%d,%d\n",
+ archive_entry_rdevmajor(entry),
+ archive_entry_rdevminor(entry));
+ break;
+ case AE_IFBLK:
+ archive_string_sprintf(&mtree->buf,
+ " type=block device=native,%d,%d\n",
+ archive_entry_rdevmajor(entry),
+ archive_entry_rdevminor(entry));
+ break;
+ case AE_IFDIR:
+ archive_strcat(&mtree->buf, " type=dir\n");
+ break;
+ case AE_IFIFO:
+ archive_strcat(&mtree->buf, " type=fifo\n");
+ break;
+ case AE_IFREG:
+ default: /* Handle unknown file types as regular files. */
+ archive_string_sprintf(&mtree->buf, " type=file size=%jd\n",
+ (intmax_t)archive_entry_size(entry));
+ break;
+ }
+
+ archive_entry_free(entry);
+
+ if (mtree->buf.length > 32768) {
+ ret = (a->compressor.write)(a, mtree->buf.s, mtree->buf.length);
+ archive_string_empty(&mtree->buf);
+ } else
+ ret = ARCHIVE_OK;
+
+ return (ret == ARCHIVE_OK ? ret : ARCHIVE_FATAL);
+}
+
+static int
+archive_write_mtree_finish(struct archive_write *a)
+{
+ struct mtree_writer *mtree= a->format_data;
+
+ archive_write_set_bytes_in_last_block(&a->archive, 1);
+
+ return (a->compressor.write)(a, mtree->buf.s, mtree->buf.length);
+}
+
+static ssize_t
+archive_write_mtree_data(struct archive_write *a, const void *buff, size_t n)
+{
+ (void)a; /* UNUSED */
+ (void)buff; /* UNUSED */
+ return n;
+}
+
+static int
+archive_write_mtree_destroy(struct archive_write *a)
+{
+ struct mtree_writer *mtree= a->format_data;
+
+ if (mtree == NULL)
+ return (ARCHIVE_OK);
+
+ archive_entry_free(mtree->entry);
+ archive_string_free(&mtree->buf);
+ free(mtree);
+ a->format_data = NULL;
+ return (ARCHIVE_OK);
+}
+
+int
+archive_write_set_format_mtree(struct archive *_a)
+{
+ struct archive_write *a = (struct archive_write *)_a;
+ struct mtree_writer *mtree;
+
+ if (a->format_destroy != NULL)
+ (a->format_destroy)(a);
+
+ if ((mtree = malloc(sizeof(*mtree))) == NULL) {
+ archive_set_error(&a->archive, ENOMEM,
+ "Can't allocate mtree data");
+ return (ARCHIVE_FATAL);
+ }
+
+ mtree->entry = NULL;
+ mtree->first = 1;
+ archive_string_init(&mtree->buf);
+ a->format_data = mtree;
+ a->format_destroy = archive_write_mtree_destroy;
+
+ a->pad_uncompressed = 0;
+ a->format_write_header = archive_write_mtree_header;
+ a->format_finish = archive_write_mtree_finish;
+ a->format_write_data = archive_write_mtree_data;
+ a->format_finish_entry = archive_write_mtree_finish_entry;
+ a->archive.archive_format = ARCHIVE_FORMAT_MTREE;
+ a->archive.archive_format_name = "mtree";
+
+ return (ARCHIVE_OK);
+}
OpenPOWER on IntegriCloud