summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/fstree.h2
-rw-r--r--lib/fstree/fstree_from_dir.c79
-rw-r--r--mkfs/mkfs.c3
-rw-r--r--mkfs/mkfs.h1
-rw-r--r--mkfs/options.c20
5 files changed, 102 insertions, 3 deletions
diff --git a/include/fstree.h b/include/fstree.h
index 9f47f76..cbd3c9c 100644
--- a/include/fstree.h
+++ b/include/fstree.h
@@ -39,6 +39,8 @@ enum {
DIR_SCAN_KEEP_TIME = 0x01,
DIR_SCAN_ONE_FILESYSTEM = 0x02,
+
+ DIR_SCAN_READ_XATTR = 0x04,
};
/* Encapsulates a set of key-value pairs attached to a tree_node_t */
diff --git a/lib/fstree/fstree_from_dir.c b/lib/fstree/fstree_from_dir.c
index 7301d91..4b89272 100644
--- a/lib/fstree/fstree_from_dir.c
+++ b/lib/fstree/fstree_from_dir.c
@@ -10,6 +10,9 @@
#include "util.h"
#include <sys/types.h>
+#ifdef HAVE_SYS_XATTR_H
+#include <sys/xattr.h>
+#endif
#include <dirent.h>
#include <unistd.h>
#include <string.h>
@@ -52,6 +55,75 @@ fail:
return NULL;
}
+#ifdef HAVE_SYS_XATTR_H
+static int populate_xattr(fstree_t *fs, tree_node_t *node)
+{
+ char *key, *value = NULL, *buffer = NULL;
+ ssize_t buflen, vallen, keylen;
+
+ buflen = listxattr(node->name, NULL, 0);
+
+ if (buflen < 0) {
+ perror("listxattr");
+ return -1;
+ }
+
+ if (buflen == 0)
+ return 0;
+
+ buffer = malloc(buflen);
+ if (buffer == NULL) {
+ perror("xattr name buffer");
+ return -1;
+ }
+
+ buflen = listxattr(node->name, buffer, buflen);
+ if (buflen == -1) {
+ perror("listxattr");
+ goto fail;
+ }
+
+ key = buffer;
+ while (buflen > 0) {
+ vallen = getxattr(node->name, key, NULL, 0);
+ if (vallen == -1)
+ goto fail;
+
+ if (vallen > 0) {
+ value = calloc(1, vallen + 1);
+ if (value == NULL) {
+ perror("xattr value buffer");
+ goto fail;
+ }
+
+ vallen = getxattr(node->name, key, value, vallen);
+ if (vallen == -1) {
+ perror("getxattr");
+ goto fail;
+ }
+
+ value[vallen] = 0;
+ if (fstree_add_xattr(fs, node, key, value))
+ goto fail;
+
+ free(value);
+ value = NULL;
+ }
+
+ keylen = strlen(key) + 1;
+ buflen -= keylen;
+ key += keylen;
+ }
+
+ free(buffer);
+ return 0;
+fail:
+ free(value);
+ free(buffer);
+ return -1;
+}
+#endif
+
static int populate_dir(fstree_t *fs, tree_node_t *root, dev_t devstart,
unsigned int flags)
{
@@ -115,6 +187,13 @@ static int populate_dir(fstree_t *fs, tree_node_t *root, dev_t devstart,
goto fail;
}
+#ifdef HAVE_SYS_XATTR_H
+ if (flags & DIR_SCAN_READ_XATTR) {
+ if (populate_xattr(fs, n))
+ return -1;
+ }
+#endif
+
free(extra);
extra = NULL;
}
diff --git a/mkfs/mkfs.c b/mkfs/mkfs.c
index f0d1e73..b11dce0 100644
--- a/mkfs/mkfs.c
+++ b/mkfs/mkfs.c
@@ -81,6 +81,9 @@ static int read_fstree(fstree_t *fs, options_t *opt)
if (opt->one_filesystem)
flags |= DIR_SCAN_ONE_FILESYSTEM;
+ if (opt->keep_xattr)
+ flags |= DIR_SCAN_READ_XATTR;
+
return fstree_from_dir(fs, opt->packdir, flags);
}
diff --git a/mkfs/mkfs.h b/mkfs/mkfs.h
index c7c327c..e02c248 100644
--- a/mkfs/mkfs.h
+++ b/mkfs/mkfs.h
@@ -36,6 +36,7 @@ typedef struct {
int blksz;
int devblksz;
bool keep_time;
+ bool keep_xattr;
bool one_filesystem;
bool exportable;
bool quiet;
diff --git a/mkfs/options.c b/mkfs/options.c
index 340cb81..2778a9e 100644
--- a/mkfs/options.c
+++ b/mkfs/options.c
@@ -15,6 +15,9 @@ static struct option long_opts[] = {
{ "pack-file", required_argument, NULL, 'F' },
{ "pack-dir", required_argument, NULL, 'D' },
{ "keep-time", no_argument, NULL, 'k' },
+#ifdef HAVE_SYS_XATTR_H
+ { "keep-xattr", no_argument, NULL, 'x' },
+#endif
{ "one-file-system", no_argument, NULL, 'o' },
{ "exportable", no_argument, NULL, 'e' },
{ "force", no_argument, NULL, 'f' },
@@ -26,11 +29,14 @@ static struct option long_opts[] = {
{ "help", no_argument, NULL, 'h' },
};
+static const char *short_opts = "F:D:X:c:b:B:d:kxoefqhV"
#ifdef WITH_SELINUX
-static const char *short_opts = "s:F:D:X:c:b:B:d:koefqhV";
-#else
-static const char *short_opts = "F:D:X:c:b:B:d:koefqhV";
+"s:"
+#endif
+#ifdef HAVE_SYS_XATTR_H
+"x"
#endif
+;
extern char *__progname;
@@ -77,6 +83,8 @@ static const char *help_string =
" --keep-time, -k When using --pack-dir only, use the timestamps\n"
" from the input files instead of setting\n"
" defaults on all input paths.\n"
+" --keep-xattr, -x When using --pack-dir only, read and pack the\n"
+" extended attributes from the input files.\n"
" --one-file-system, -o When using --pack-dir only, stay in local file\n"
" system and do not cross mount points.\n"
" --exportable, -e Generate an export table for NFS support.\n"
@@ -139,6 +147,7 @@ void process_command_line(options_t *opt, int argc, char **argv)
opt->compressor = compressor_get_default();
opt->blksz = SQFS_DEFAULT_BLOCK_SIZE;
opt->devblksz = SQFS_DEVBLK_SIZE;
+ opt->keep_xattr = false;
opt->keep_time = false;
opt->one_filesystem = false;
opt->exportable = false;
@@ -188,6 +197,11 @@ void process_command_line(options_t *opt, int argc, char **argv)
case 'k':
opt->keep_time = true;
break;
+#ifdef HAVE_SYS_XATTR_H
+ case 'x':
+ opt->keep_xattr = true;
+ break;
+#endif
case 'o':
opt->one_filesystem = true;
break;