diff options
author | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2019-08-01 16:03:59 +0200 |
---|---|---|
committer | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2019-08-01 16:23:07 +0200 |
commit | cccbd5aa139b8e0cac233f317cb3e7252daae0d9 (patch) | |
tree | d46867fe3bf78a3371ef3c6bbebcdab1d65435f7 /lib | |
parent | acfef038be1db770c33476bbb33b53558ddabc91 (diff) |
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 <david.oberhollenzer@sigma-star.at>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/tar/write_header.c | 53 |
1 files changed, 52 insertions, 1 deletions
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; |