summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2019-08-01 16:03:59 +0200
committerDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2019-08-01 16:23:07 +0200
commitcccbd5aa139b8e0cac233f317cb3e7252daae0d9 (patch)
treed46867fe3bf78a3371ef3c6bbebcdab1d65435f7
parentacfef038be1db770c33476bbb33b53558ddabc91 (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>
-rw-r--r--include/tar.h3
-rw-r--r--lib/tar/write_header.c53
-rw-r--r--tar/sqfs2tar.c2
3 files changed, 55 insertions, 3 deletions
diff --git a/include/tar.h b/include/tar.h
index cb56ff0..44db5fe 100644
--- a/include/tar.h
+++ b/include/tar.h
@@ -113,7 +113,8 @@ typedef struct {
headers need to be generated.
*/
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);
/* calcuate and skip the zero padding */
int skip_padding(int fd, uint64_t size);
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;
diff --git a/tar/sqfs2tar.c b/tar/sqfs2tar.c
index 13a2339..07be2b4 100644
--- a/tar/sqfs2tar.c
+++ b/tar/sqfs2tar.c
@@ -211,7 +211,7 @@ static int write_tree_dfs(fstree_t *fs, tree_node_t *n, data_reader_t *data)
fstree_node_stat(fs, n, &sb);
target = S_ISLNK(sb.st_mode) ? n->data.slink_target : NULL;
- ret = write_tar_header(STDOUT_FILENO, &sb, name, target,
+ ret = write_tar_header(STDOUT_FILENO, &sb, name, target, NULL,
record_counter++);
if (ret > 0) {