From cccbd5aa139b8e0cac233f317cb3e7252daae0d9 Mon Sep 17 00:00:00 2001 From: David Oberhollenzer Date: Thu, 1 Aug 2019 16:03:59 +0200 Subject: Add ability to write_tar_header to embedd extended attributes This commit patches the tar writer to generate a PAX header with SCHILY xattr key/value pairs if requested. The Schily format is used for two reasons: - It is simple - It is apparently more widely supported than the libarchive format Signed-off-by: David Oberhollenzer --- lib/tar/write_header.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/tar/write_header.c b/lib/tar/write_header.c index e4d4d38..d3a184a 100644 --- a/lib/tar/write_header.c +++ b/lib/tar/write_header.c @@ -112,13 +112,64 @@ static int write_gnu_header(int fd, const struct stat *orig, return padd_file(fd, payload_len, 512); } +static size_t num_digits(size_t num) +{ + size_t i = 1; + + while (num > 10) { + num /= 10; + ++i; + } + + return i; +} + +static int write_schily_xattr(int fd, const struct stat *orig, + const char *name, const tar_xattr_t *xattr) +{ + static const char *prefix = "SCHILY.xattr."; + size_t len, total_size = 0; + const tar_xattr_t *it; + struct stat sb; + + for (it = xattr; it != NULL; it = it->next) { + len = strlen(prefix) + strlen(it->key) + strlen(it->value) + 2; + + total_size += num_digits(len) + 1 + len; + } + + sb = *orig; + sb.st_mode = S_IFREG | 0644; + sb.st_size = total_size; + + if (write_header(fd, &sb, name, NULL, TAR_TYPE_PAX)) + return -1; + + for (it = xattr; it != NULL; it = it->next) { + len = strlen(prefix) + strlen(it->key) + strlen(it->value) + 2; + len += num_digits(len) + 1; + + dprintf(fd, "%zu %s%s=%s\n", len, prefix, it->key, it->value); + } + + return padd_file(fd, total_size, 512); +} + int write_tar_header(int fd, const struct stat *sb, const char *name, - const char *slink_target, unsigned int counter) + const char *slink_target, const tar_xattr_t *xattr, + unsigned int counter) { const char *reason; char buffer[64]; int type; + if (xattr != NULL) { + sprintf(buffer, "pax/xattr%u", counter); + + if (write_schily_xattr(fd, sb, buffer, xattr)) + return -1; + } + if (!S_ISLNK(sb->st_mode)) slink_target = NULL; -- cgit v1.2.3