--- daemon/xattr.c | 41 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/daemon/xattr.c b/daemon/xattr.c index 482df9af0..82fb0ebc8 100644 --- a/daemon/xattr.c +++ b/daemon/xattr.c @@ -118,6 +118,29 @@ split_attr_names (const char *buf, size_t len) return take_stringsbuf (&ret); } +/* We hide one extended attribute automatically. This is used by NTFS + * to store the compressed contents of a file when using "CompactOS" + * (per-file compression). I justify this by: + * + * (1) The attribute is only used internally by NTFS. The actual file + * contents are still available. + * + * (2) It's probably not valid to copy this attribute when copying the + * other attributes of a file. ntfs-3g-system-compression doesn't + * support writing compressed files. + * + * (3) This file isn't readable by the Linux kernel. Reading it will + * always return -E2BIG (RHBZ#1811539). So we can't read it even if + * we wanted to. + * + * (4) The Linux kernel itself hides other attributes. + */ +static int +not_hidden_xattr (const char *attrname) +{ + return STRNEQ (attrname, "user.WofCompressedData"); +} + static int compare_xattrs (const void *vxa1, const void *vxa2) { @@ -135,6 +158,7 @@ getxattrs (const char *path, { ssize_t len, vlen; CLEANUP_FREE char *buf = NULL; + CLEANUP_FREE_STRING_LIST char **names_unfiltered = NULL; CLEANUP_FREE_STRING_LIST char **names = NULL; size_t i; guestfs_int_xattr_list *r = NULL; @@ -144,7 +168,10 @@ getxattrs (const char *path, /* _listxattrs issues reply_with_perror already. */ goto error; - names = split_attr_names (buf, len); + names_unfiltered = split_attr_names (buf, len); + if (names_unfiltered == NULL) + goto error; + names = filter_list (not_hidden_xattr, names_unfiltered); if (names == NULL) goto error; @@ -322,6 +349,7 @@ do_internal_lxattrlist (const char *path, char *const *names) void *newptr; CLEANUP_FREE char *pathname = NULL; CLEANUP_FREE char *buf = NULL; + CLEANUP_FREE_STRING_LIST char **attrnames_unfiltered = NULL; CLEANUP_FREE_STRING_LIST char **attrnames = NULL; /* Be careful in this loop about which errors cause the whole call @@ -380,7 +408,10 @@ do_internal_lxattrlist (const char *path, char *const *names) if (len == -1) continue; /* not fatal */ - attrnames = split_attr_names (buf, len); + attrnames_unfiltered = split_attr_names (buf, len); + if (attrnames_unfiltered == NULL) + goto error; + attrnames = filter_list (not_hidden_xattr, attrnames_unfiltered); if (attrnames == NULL) goto error; nr_attrs = guestfs_int_count_strings (attrnames); @@ -538,6 +569,7 @@ copy_xattrs (const char *src, const char *dest) { ssize_t len, vlen, ret, attrval_len = 0; CLEANUP_FREE char *buf = NULL, *attrval = NULL; + CLEANUP_FREE_STRING_LIST char **names_unfiltered = NULL; CLEANUP_FREE_STRING_LIST char **names = NULL; size_t i; @@ -546,7 +578,10 @@ copy_xattrs (const char *src, const char *dest) /* _listxattrs issues reply_with_perror already. */ goto error; - names = split_attr_names (buf, len); + names_unfiltered = split_attr_names (buf, len); + if (names_unfiltered == NULL) + goto error; + names = filter_list (not_hidden_xattr, names_unfiltered); if (names == NULL) goto error; -- 2.25.0