summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2019-07-04 13:26:27 +0200
committerDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2019-07-04 13:42:06 +0200
commit2ed6658bbce90e89f0a4e3aba41704944f10b1f1 (patch)
treee8b60a37ab1e310a6c65c2e84b30cfc15eb8a1c5
parent6623b1fe4df1e2fceb27eff286a86cf36809b2bc (diff)
tar2sqfs: repack extended attributes into squashfs filesystem
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
-rw-r--r--README2
-rw-r--r--doc/tar2sqfs.114
-rw-r--r--include/squashfs.h4
-rw-r--r--lib/sqfs/write_xattr.c10
-rw-r--r--tar/tar2sqfs.c43
5 files changed, 66 insertions, 7 deletions
diff --git a/README b/README
index f9f9058..0ffd74d 100644
--- a/README
+++ b/README
@@ -51,7 +51,7 @@ At the moment, the following things still require some work:
- more testing (extensive unit testing for libsqfs still needed)
- extended attributes
- gensquashfs supports SELinux labeling only
- - rdsquashfs, sqfs2tar and tar2sqfs ignore them entirely
+ - rdsquashfs and sqfs2tar ignore them entirely
- entire key value blocks are deduplicated, but individual value
deduplication ("out of line" storage) isn't implemented.
- hard links (not implemented; tar2sqfs turns them into symlinks)
diff --git a/doc/tar2sqfs.1 b/doc/tar2sqfs.1
index c1cb619..3279794 100644
--- a/doc/tar2sqfs.1
+++ b/doc/tar2sqfs.1
@@ -51,6 +51,10 @@ mtime=<value>;0
.TE
.TP
.TP
+\fB\-\-no\-xattr\fR, \fB\-s\fR
+Do not copy extended attributes from archive. Default behaviour is to copy all
+extended attributes and skip the ones that cannot be encoded in SquashFS.
+.TP
\fB\-\-no\-skip\fR, \fB\-s\fR
Abort if a tar record cannot be read instead of skipping it.
.TP
@@ -76,9 +80,13 @@ older, legacy headers are not supported) and extensions like sparse files.
Hard links are currently not supported and silently converted to symlinks.
Furthermore, none of the various xattr extensions are currently implemented.
-If any unsupported section is encountered in an archive a warning message is
-written to stderr. If the \fB\-\-no\-skip\fR option is set, processing aborts.
-By default, the unknown section is simply skipped after issuing a warning.
+Extended attributes are supported through the SCHILY.xattr PAX extension
+(favoured by GNU tar and star) or through the LIBARCHIVE.xattr PAX extension.
+
+If any unsupported section or extended attribute key is encountered in an
+archive a warning message is written to stderr. If the \fB\-\-no\-skip\fR
+option is set, processing aborts. By default, unknown sections and unsupported
+extended attributes are simply skipped after issuing a warning.
.SH EXAMPLES
.TP
Turn an uncompressed tar archive into a squashfs image:
diff --git a/include/squashfs.h b/include/squashfs.h
index ed3fd38..6e2214b 100644
--- a/include/squashfs.h
+++ b/include/squashfs.h
@@ -2,6 +2,7 @@
#ifndef SQUASHFS_H
#define SQUASHFS_H
+#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
@@ -250,4 +251,7 @@ int sqfs_super_write(sqfs_super_t *super, int fd);
/* Returns 0 on success. Prints error messages to stderr on failure. */
int sqfs_super_read(sqfs_super_t *super, int fd);
+/* Check if a given xattr key can be encoded in squashfs at all. */
+bool sqfs_has_xattr(const char *key);
+
#endif /* SQUASHFS_H */
diff --git a/lib/sqfs/write_xattr.c b/lib/sqfs/write_xattr.c
index b6198b4..ab2e28c 100644
--- a/lib/sqfs/write_xattr.c
+++ b/lib/sqfs/write_xattr.c
@@ -30,10 +30,14 @@ static int get_prefix(const char *key)
}
}
- fprintf(stderr, "unknown xattr key '%s'\n", key);
return -1;
}
+bool sqfs_has_xattr(const char *key)
+{
+ return get_prefix(key) >= 0;
+}
+
static int write_pair(meta_writer_t *mw, const char *key, const char *value)
{
sqfs_xattr_entry_t kent;
@@ -41,8 +45,10 @@ static int write_pair(meta_writer_t *mw, const char *key, const char *value)
int type;
type = get_prefix(key);
- if (type < 0)
+ if (type < 0) {
+ fprintf(stderr, "unsupported xattr key '%s'\n", key);
return -1;
+ }
key = strchr(key, '.');
assert(key != NULL);
diff --git a/tar/tar2sqfs.c b/tar/tar2sqfs.c
index e239acd..0dad73a 100644
--- a/tar/tar2sqfs.c
+++ b/tar/tar2sqfs.c
@@ -25,13 +25,14 @@ static struct option long_opts[] = {
{ "defaults", required_argument, NULL, 'd' },
{ "comp-extra", required_argument, NULL, 'X' },
{ "no-skip", no_argument, NULL, 's' },
+ { "no-xattr", no_argument, NULL, 'x' },
{ "force", no_argument, NULL, 'f' },
{ "quiet", no_argument, NULL, 'q' },
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, 'V' },
};
-static const char *short_opts = "c:b:B:d:X:sfqhV";
+static const char *short_opts = "c:b:B:d:X:sxfqhV";
static const char *usagestr =
"Usage: tar2sqfs [OPTIONS...] <sqfsfile>\n"
@@ -61,6 +62,7 @@ static const char *usagestr =
"\n"
" --no-skip, -s Abort if a tar record cannot be read instead\n"
" of skipping it.\n"
+" --no-xattr, -x Do not copy extended attributes from archive.\n"
" --force, -f Overwrite the output file if it exists.\n"
" --quiet, -q Do not print out progress reports.\n"
" --help, -h Print help text and exit.\n"
@@ -82,6 +84,7 @@ static E_SQFS_COMPRESSOR comp_id;
static char *comp_extra = NULL;
static char *fs_defaults = NULL;
static bool dont_skip = false;
+static bool no_xattr = false;
static void process_args(int argc, char **argv)
{
@@ -128,6 +131,9 @@ static void process_args(int argc, char **argv)
case 'd':
fs_defaults = optarg;
break;
+ case 'x':
+ no_xattr = true;
+ break;
case 's':
dont_skip = true;
break;
@@ -192,6 +198,31 @@ static int write_file(tar_header_decoded_t *hdr, file_info_t *fi,
return skip_padding(STDIN_FILENO, fi->size);
}
+static int copy_xattr(fstree_t *fs, tree_node_t *node,
+ tar_header_decoded_t *hdr)
+{
+ tar_xattr_t *xattr;
+
+ for (xattr = hdr->xattr; xattr != NULL; xattr = xattr->next) {
+ if (!sqfs_has_xattr(xattr->key)) {
+ if (dont_skip) {
+ fprintf(stderr, "Cannot encode xattr key '%s' "
+ "in squashfs\n", xattr->key);
+ return -1;
+ }
+
+ fprintf(stderr, "WARNING: squashfs does not "
+ "support xattr prefix of %s\n", xattr->key);
+ continue;
+ }
+
+ if (fstree_add_xattr(fs, node, xattr->key, xattr->value))
+ return -1;
+ }
+
+ return 0;
+}
+
static int create_node_and_repack_data(tar_header_decoded_t *hdr, fstree_t *fs,
data_writer_t *data)
{
@@ -204,6 +235,11 @@ static int create_node_and_repack_data(tar_header_decoded_t *hdr, fstree_t *fs,
if (!quiet)
printf("Packing %s\n", hdr->name);
+ if (!no_xattr) {
+ if (copy_xattr(fs, node, hdr))
+ return -1;
+ }
+
if (S_ISREG(hdr->sb.st_mode))
return write_file(hdr, node->data.file, data);
@@ -346,6 +382,8 @@ int main(int argc, char **argv)
super.inode_count = fs.inode_tbl_size - 2;
+ fstree_xattr_deduplicate(&fs);
+
if (sqfs_serialize_fstree(outfd, &super, &fs, cmp, &idtbl))
goto out;
@@ -355,6 +393,9 @@ int main(int argc, char **argv)
if (id_table_write(&idtbl, outfd, &super, cmp))
goto out;
+ if (write_xattr(outfd, &fs, &super, cmp))
+ goto out_data;
+
if (sqfs_super_write(&super, outfd))
goto out;