|
|
10436e |
From 052549a055bbedc402418bc52bcbfa3bfcb97952 Mon Sep 17 00:00:00 2001
|
|
|
10436e |
From: "Richard W.M. Jones" <rjones@redhat.com>
|
|
|
10436e |
Date: Thu, 12 Mar 2020 13:57:06 +0000
|
|
|
10436e |
Subject: [PATCH] daemon: xattr: Refactor code which splits attr names from the
|
|
|
10436e |
kernel.
|
|
|
10436e |
|
|
|
10436e |
The kernel returns xattr names in a slightly peculiar format. We
|
|
|
10436e |
parsed this format several times in the code. Refactor this parsing
|
|
|
10436e |
so we only do it in one place.
|
|
|
10436e |
|
|
|
10436e |
(cherry picked from commit 5c175fe73264bbf1d3ef79bb066dfb6aff902ad1)
|
|
|
10436e |
---
|
|
|
10436e |
daemon/xattr.c | 127 ++++++++++++++++++++++++++++++-------------------
|
|
|
10436e |
1 file changed, 79 insertions(+), 48 deletions(-)
|
|
|
10436e |
|
|
|
10436e |
diff --git a/daemon/xattr.c b/daemon/xattr.c
|
|
|
10436e |
index bc5c2df97..3e1144963 100644
|
|
|
10436e |
--- a/daemon/xattr.c
|
|
|
10436e |
+++ b/daemon/xattr.c
|
|
|
10436e |
@@ -89,6 +89,36 @@ do_lremovexattr (const char *xattr, const char *path)
|
|
|
10436e |
return _removexattr (xattr, path, lremovexattr);
|
|
|
10436e |
}
|
|
|
10436e |
|
|
|
10436e |
+/**
|
|
|
10436e |
+ * L<listxattr(2)> returns the string C<"foo\0bar\0baz"> of length
|
|
|
10436e |
+ * C<len>. (The last string in the list is \0-terminated but the \0
|
|
|
10436e |
+ * is not included in C<len>).
|
|
|
10436e |
+ *
|
|
|
10436e |
+ * This function splits it into a regular list of strings.
|
|
|
10436e |
+ *
|
|
|
10436e |
+ * B<Note> that the returned list contains pointers to the original
|
|
|
10436e |
+ * strings in C<buf> so be careful that you do not double-free them.
|
|
|
10436e |
+ */
|
|
|
10436e |
+static char **
|
|
|
10436e |
+split_attr_names (char *buf, size_t len)
|
|
|
10436e |
+{
|
|
|
10436e |
+ size_t i;
|
|
|
10436e |
+ DECLARE_STRINGSBUF (ret);
|
|
|
10436e |
+
|
|
|
10436e |
+ for (i = 0; i < len; i += strlen (&buf[i]) + 1) {
|
|
|
10436e |
+ if (add_string_nodup (&ret, &buf[i]) == -1) {
|
|
|
10436e |
+ free (ret.argv);
|
|
|
10436e |
+ return NULL;
|
|
|
10436e |
+ }
|
|
|
10436e |
+ }
|
|
|
10436e |
+ if (end_stringsbuf (&ret) == -1) {
|
|
|
10436e |
+ free (ret.argv);
|
|
|
10436e |
+ return NULL;
|
|
|
10436e |
+ }
|
|
|
10436e |
+
|
|
|
10436e |
+ return take_stringsbuf (&ret;;
|
|
|
10436e |
+}
|
|
|
10436e |
+
|
|
|
10436e |
static int
|
|
|
10436e |
compare_xattrs (const void *vxa1, const void *vxa2)
|
|
|
10436e |
{
|
|
|
10436e |
@@ -106,7 +136,8 @@ getxattrs (const char *path,
|
|
|
10436e |
{
|
|
|
10436e |
ssize_t len, vlen;
|
|
|
10436e |
CLEANUP_FREE char *buf = NULL;
|
|
|
10436e |
- size_t i, j;
|
|
|
10436e |
+ CLEANUP_FREE /* not string list */ char **names = NULL;
|
|
|
10436e |
+ size_t i;
|
|
|
10436e |
guestfs_int_xattr_list *r = NULL;
|
|
|
10436e |
|
|
|
10436e |
buf = _listxattrs (path, listxattr, &len;;
|
|
|
10436e |
@@ -114,18 +145,17 @@ getxattrs (const char *path,
|
|
|
10436e |
/* _listxattrs issues reply_with_perror already. */
|
|
|
10436e |
goto error;
|
|
|
10436e |
|
|
|
10436e |
+ names = split_attr_names (buf, len);
|
|
|
10436e |
+ if (names == NULL)
|
|
|
10436e |
+ goto error;
|
|
|
10436e |
+
|
|
|
10436e |
r = calloc (1, sizeof (*r));
|
|
|
10436e |
if (r == NULL) {
|
|
|
10436e |
reply_with_perror ("calloc");
|
|
|
10436e |
goto error;
|
|
|
10436e |
}
|
|
|
10436e |
|
|
|
10436e |
- /* What we get from the kernel is a string "foo\0bar\0baz" of length
|
|
|
10436e |
- * len. First count the strings.
|
|
|
10436e |
- */
|
|
|
10436e |
- r->guestfs_int_xattr_list_len = 0;
|
|
|
10436e |
- for (i = 0; i < (size_t) len; i += strlen (&buf[i]) + 1)
|
|
|
10436e |
- r->guestfs_int_xattr_list_len++;
|
|
|
10436e |
+ r->guestfs_int_xattr_list_len = guestfs_int_count_strings (names);
|
|
|
10436e |
|
|
|
10436e |
r->guestfs_int_xattr_list_val =
|
|
|
10436e |
calloc (r->guestfs_int_xattr_list_len, sizeof (guestfs_int_xattr));
|
|
|
10436e |
@@ -134,34 +164,34 @@ getxattrs (const char *path,
|
|
|
10436e |
goto error;
|
|
|
10436e |
}
|
|
|
10436e |
|
|
|
10436e |
- for (i = 0, j = 0; i < (size_t) len; i += strlen (&buf[i]) + 1, ++j) {
|
|
|
10436e |
+ for (i = 0; names[i] != NULL; ++i) {
|
|
|
10436e |
CHROOT_IN;
|
|
|
10436e |
- vlen = getxattr (path, &buf[i], NULL, 0);
|
|
|
10436e |
+ vlen = getxattr (path, names[i], NULL, 0);
|
|
|
10436e |
CHROOT_OUT;
|
|
|
10436e |
if (vlen == -1) {
|
|
|
10436e |
- reply_with_perror ("getxattr");
|
|
|
10436e |
+ reply_with_perror ("getxattr: %s", names[i]);
|
|
|
10436e |
goto error;
|
|
|
10436e |
}
|
|
|
10436e |
|
|
|
10436e |
if (vlen > XATTR_SIZE_MAX) {
|
|
|
10436e |
/* The next call to getxattr will fail anyway, so ... */
|
|
|
10436e |
- reply_with_error ("extended attribute is too large");
|
|
|
10436e |
+ reply_with_error ("%s: extended attribute is too large", names[i]);
|
|
|
10436e |
goto error;
|
|
|
10436e |
}
|
|
|
10436e |
|
|
|
10436e |
- r->guestfs_int_xattr_list_val[j].attrname = strdup (&buf[i]);
|
|
|
10436e |
- r->guestfs_int_xattr_list_val[j].attrval.attrval_val = malloc (vlen);
|
|
|
10436e |
- r->guestfs_int_xattr_list_val[j].attrval.attrval_len = vlen;
|
|
|
10436e |
+ r->guestfs_int_xattr_list_val[i].attrname = strdup (names[i]);
|
|
|
10436e |
+ r->guestfs_int_xattr_list_val[i].attrval.attrval_val = malloc (vlen);
|
|
|
10436e |
+ r->guestfs_int_xattr_list_val[i].attrval.attrval_len = vlen;
|
|
|
10436e |
|
|
|
10436e |
- if (r->guestfs_int_xattr_list_val[j].attrname == NULL ||
|
|
|
10436e |
- r->guestfs_int_xattr_list_val[j].attrval.attrval_val == NULL) {
|
|
|
10436e |
+ if (r->guestfs_int_xattr_list_val[i].attrname == NULL ||
|
|
|
10436e |
+ r->guestfs_int_xattr_list_val[i].attrval.attrval_val == NULL) {
|
|
|
10436e |
reply_with_perror ("malloc");
|
|
|
10436e |
goto error;
|
|
|
10436e |
}
|
|
|
10436e |
|
|
|
10436e |
CHROOT_IN;
|
|
|
10436e |
- vlen = getxattr (path, &buf[i],
|
|
|
10436e |
- r->guestfs_int_xattr_list_val[j].attrval.attrval_val,
|
|
|
10436e |
+ vlen = getxattr (path, names[i],
|
|
|
10436e |
+ r->guestfs_int_xattr_list_val[i].attrval.attrval_val,
|
|
|
10436e |
vlen);
|
|
|
10436e |
CHROOT_OUT;
|
|
|
10436e |
if (vlen == -1) {
|
|
|
10436e |
@@ -276,7 +306,7 @@ guestfs_int_xattr_list *
|
|
|
10436e |
do_internal_lxattrlist (const char *path, char *const *names)
|
|
|
10436e |
{
|
|
|
10436e |
guestfs_int_xattr_list *ret = NULL;
|
|
|
10436e |
- size_t i, j;
|
|
|
10436e |
+ size_t i;
|
|
|
10436e |
size_t k, m, nr_attrs;
|
|
|
10436e |
ssize_t len, vlen;
|
|
|
10436e |
|
|
|
10436e |
@@ -293,6 +323,7 @@ do_internal_lxattrlist (const char *path, char *const *names)
|
|
|
10436e |
void *newptr;
|
|
|
10436e |
CLEANUP_FREE char *pathname = NULL;
|
|
|
10436e |
CLEANUP_FREE char *buf = NULL;
|
|
|
10436e |
+ CLEANUP_FREE /* not string list */ char **attrnames = NULL;
|
|
|
10436e |
|
|
|
10436e |
/* Be careful in this loop about which errors cause the whole call
|
|
|
10436e |
* to abort, and which errors allow us to continue processing
|
|
|
10436e |
@@ -350,12 +381,10 @@ do_internal_lxattrlist (const char *path, char *const *names)
|
|
|
10436e |
if (len == -1)
|
|
|
10436e |
continue; /* not fatal */
|
|
|
10436e |
|
|
|
10436e |
- /* What we get from the kernel is a string "foo\0bar\0baz" of length
|
|
|
10436e |
- * len. First count the strings.
|
|
|
10436e |
- */
|
|
|
10436e |
- nr_attrs = 0;
|
|
|
10436e |
- for (i = 0; i < (size_t) len; i += strlen (&buf[i]) + 1)
|
|
|
10436e |
- nr_attrs++;
|
|
|
10436e |
+ attrnames = split_attr_names (buf, len);
|
|
|
10436e |
+ if (attrnames == NULL)
|
|
|
10436e |
+ goto error;
|
|
|
10436e |
+ nr_attrs = guestfs_int_count_strings (attrnames);
|
|
|
10436e |
|
|
|
10436e |
newptr =
|
|
|
10436e |
realloc (ret->guestfs_int_xattr_list_val,
|
|
|
10436e |
@@ -378,36 +407,36 @@ do_internal_lxattrlist (const char *path, char *const *names)
|
|
|
10436e |
entry[m].attrval.attrval_val = NULL;
|
|
|
10436e |
}
|
|
|
10436e |
|
|
|
10436e |
- for (i = 0, j = 0; i < (size_t) len; i += strlen (&buf[i]) + 1, ++j) {
|
|
|
10436e |
+ for (i = 0; attrnames[i] != NULL; ++i) {
|
|
|
10436e |
CHROOT_IN;
|
|
|
10436e |
- vlen = lgetxattr (pathname, &buf[i], NULL, 0);
|
|
|
10436e |
+ vlen = lgetxattr (pathname, attrnames[i], NULL, 0);
|
|
|
10436e |
CHROOT_OUT;
|
|
|
10436e |
if (vlen == -1) {
|
|
|
10436e |
- reply_with_perror ("getxattr");
|
|
|
10436e |
+ reply_with_perror ("getxattr: %s", attrnames[i]);
|
|
|
10436e |
goto error;
|
|
|
10436e |
}
|
|
|
10436e |
|
|
|
10436e |
if (vlen > XATTR_SIZE_MAX) {
|
|
|
10436e |
- reply_with_error ("extended attribute is too large");
|
|
|
10436e |
+ reply_with_error ("%s: extended attribute is too large", attrnames[i]);
|
|
|
10436e |
goto error;
|
|
|
10436e |
}
|
|
|
10436e |
|
|
|
10436e |
- entry[j+1].attrname = strdup (&buf[i]);
|
|
|
10436e |
- entry[j+1].attrval.attrval_val = malloc (vlen);
|
|
|
10436e |
- entry[j+1].attrval.attrval_len = vlen;
|
|
|
10436e |
+ entry[i+1].attrname = strdup (attrnames[i]);
|
|
|
10436e |
+ entry[i+1].attrval.attrval_val = malloc (vlen);
|
|
|
10436e |
+ entry[i+1].attrval.attrval_len = vlen;
|
|
|
10436e |
|
|
|
10436e |
- if (entry[j+1].attrname == NULL ||
|
|
|
10436e |
- entry[j+1].attrval.attrval_val == NULL) {
|
|
|
10436e |
+ if (entry[i+1].attrname == NULL ||
|
|
|
10436e |
+ entry[i+1].attrval.attrval_val == NULL) {
|
|
|
10436e |
reply_with_perror ("malloc");
|
|
|
10436e |
goto error;
|
|
|
10436e |
}
|
|
|
10436e |
|
|
|
10436e |
CHROOT_IN;
|
|
|
10436e |
- vlen = lgetxattr (pathname, &buf[i],
|
|
|
10436e |
- entry[j+1].attrval.attrval_val, vlen);
|
|
|
10436e |
+ vlen = lgetxattr (pathname, attrnames[i],
|
|
|
10436e |
+ entry[i+1].attrval.attrval_val, vlen);
|
|
|
10436e |
CHROOT_OUT;
|
|
|
10436e |
if (vlen == -1) {
|
|
|
10436e |
- reply_with_perror ("getxattr");
|
|
|
10436e |
+ reply_with_perror ("getxattr: %s", attrnames[i]);
|
|
|
10436e |
goto error;
|
|
|
10436e |
}
|
|
|
10436e |
}
|
|
|
10436e |
@@ -510,6 +539,7 @@ copy_xattrs (const char *src, const char *dest)
|
|
|
10436e |
{
|
|
|
10436e |
ssize_t len, vlen, ret, attrval_len = 0;
|
|
|
10436e |
CLEANUP_FREE char *buf = NULL, *attrval = NULL;
|
|
|
10436e |
+ CLEANUP_FREE /* not string list */ char **names = NULL;
|
|
|
10436e |
size_t i;
|
|
|
10436e |
|
|
|
10436e |
buf = _listxattrs (src, listxattr, &len;;
|
|
|
10436e |
@@ -517,21 +547,22 @@ copy_xattrs (const char *src, const char *dest)
|
|
|
10436e |
/* _listxattrs issues reply_with_perror already. */
|
|
|
10436e |
goto error;
|
|
|
10436e |
|
|
|
10436e |
- /* What we get from the kernel is a string "foo\0bar\0baz" of length
|
|
|
10436e |
- * len.
|
|
|
10436e |
- */
|
|
|
10436e |
- for (i = 0; i < (size_t) len; i += strlen (&buf[i]) + 1) {
|
|
|
10436e |
+ names = split_attr_names (buf, len);
|
|
|
10436e |
+ if (names == NULL)
|
|
|
10436e |
+ goto error;
|
|
|
10436e |
+
|
|
|
10436e |
+ for (i = 0; names[i] != NULL; ++i) {
|
|
|
10436e |
CHROOT_IN;
|
|
|
10436e |
- vlen = getxattr (src, &buf[i], NULL, 0);
|
|
|
10436e |
+ vlen = getxattr (src, names[i], NULL, 0);
|
|
|
10436e |
CHROOT_OUT;
|
|
|
10436e |
if (vlen == -1) {
|
|
|
10436e |
- reply_with_perror ("getxattr: %s, %s", src, &buf[i]);
|
|
|
10436e |
+ reply_with_perror ("getxattr: %s, %s", src, names[i]);
|
|
|
10436e |
goto error;
|
|
|
10436e |
}
|
|
|
10436e |
|
|
|
10436e |
if (vlen > XATTR_SIZE_MAX) {
|
|
|
10436e |
/* The next call to getxattr will fail anyway, so ... */
|
|
|
10436e |
- reply_with_error ("extended attribute is too large");
|
|
|
10436e |
+ reply_with_error ("%s: extended attribute is too large", names[i]);
|
|
|
10436e |
goto error;
|
|
|
10436e |
}
|
|
|
10436e |
|
|
|
10436e |
@@ -546,18 +577,18 @@ copy_xattrs (const char *src, const char *dest)
|
|
|
10436e |
}
|
|
|
10436e |
|
|
|
10436e |
CHROOT_IN;
|
|
|
10436e |
- vlen = getxattr (src, &buf[i], attrval, vlen);
|
|
|
10436e |
+ vlen = getxattr (src, names[i], attrval, vlen);
|
|
|
10436e |
CHROOT_OUT;
|
|
|
10436e |
if (vlen == -1) {
|
|
|
10436e |
- reply_with_perror ("getxattr: %s, %s", src, &buf[i]);
|
|
|
10436e |
+ reply_with_perror ("getxattr: %s, %s", src, names[i]);
|
|
|
10436e |
goto error;
|
|
|
10436e |
}
|
|
|
10436e |
|
|
|
10436e |
CHROOT_IN;
|
|
|
10436e |
- ret = setxattr (dest, &buf[i], attrval, vlen, 0);
|
|
|
10436e |
+ ret = setxattr (dest, names[i], attrval, vlen, 0);
|
|
|
10436e |
CHROOT_OUT;
|
|
|
10436e |
if (ret == -1) {
|
|
|
10436e |
- reply_with_perror ("setxattr: %s, %s", dest, &buf[i]);
|
|
|
10436e |
+ reply_with_perror ("setxattr: %s, %s", dest, names[i]);
|
|
|
10436e |
goto error;
|
|
|
10436e |
}
|
|
|
10436e |
}
|
|
|
10436e |
--
|
|
|
10436e |
2.26.2
|
|
|
10436e |
|