Page MenuHomeFreeBSD

D13528.id37622.diff
No OneTemporary

D13528.id37622.diff

Index: sys/fs/fuse/fuse_vnops.c
===================================================================
--- sys/fs/fuse/fuse_vnops.c
+++ sys/fs/fuse/fuse_vnops.c
@@ -2049,7 +2049,7 @@
* fuse_getxattr_out. If we pass in a non-zero size, we get back
* that much data, without the struct fuse_getxattr_out header.
*/
- if (ap->a_size != NULL)
+ if (uio == NULL)
get_xattr_in->size = 0;
else
get_xattr_in->size = uio->uio_resid;
@@ -2079,13 +2079,11 @@
}
get_xattr_out = fdi.answ;
- if (ap->a_size != NULL) {
+ if (ap->a_size != NULL)
*ap->a_size = get_xattr_out->size;
- } else if (fdi.iosize > 0) {
+
+ if (uio != NULL)
err = uiomove(fdi.answ, fdi.iosize, uio);
- } else {
- err = EINVAL;
- }
out:
fdisp_destroy(&fdi);
@@ -2242,7 +2240,9 @@
char *prefix;
char *attr_str;
char *bsd_list = NULL;
+ char *linux_list;
int bsd_list_len;
+ int linux_list_len;
struct thread *td = ap->a_td;
struct ucred *cred = ap->a_cred;
int err = 0;
@@ -2266,13 +2266,11 @@
fdisp_init(&fdi, sizeof(*get_xattr_in) + len);
fdisp_make_vp(&fdi, FUSE_LISTXATTR, vp, td, cred);
+ /*
+ * Retrieve Linux / FUSE compatible list size.
+ */
get_xattr_in = fdi.indata;
- if (ap->a_size != NULL)
- get_xattr_in->size = 0;
- else
- get_xattr_in->size = uio->uio_resid + sizeof(*get_xattr_out);
-
-
+ get_xattr_in->size = 0;
attr_str = (char *)fdi.indata + sizeof(*get_xattr_in);
snprintf(attr_str, len, "%s%c", prefix, extattr_namespace_separator);
@@ -2284,33 +2282,51 @@
goto out;
}
- if ((fdi.answ == NULL) || (fdi.iosize == 0)) {
- err = EINVAL;
+ get_xattr_out = fdi.answ;
+ linux_list_len = get_xattr_out->size;
+ if (linux_list_len == 0) {
+ if (ap->a_size != NULL)
+ *ap->a_size = linux_list_len;
goto out;
}
- get_xattr_out = fdi.answ;
- if (ap->a_size != NULL) {
- *ap->a_size = get_xattr_out->size;
- } else if (fdi.iosize > 0) {
- /*
- * The Linux / FUSE attribute list format isn't the same
- * as FreeBSD's format. So we need to transform it into
- * FreeBSD's format before giving it to the user.
- */
- bsd_list = malloc(fdi.iosize, M_TEMP, M_WAITOK);
- err = fuse_xattrlist_convert(prefix, fdi.answ, fdi.iosize,
- bsd_list, &bsd_list_len);
- if (err != 0)
- goto out;
+ /*
+ * Retrieve Linux / FUSE compatible list values.
+ */
+ fdisp_make_vp(&fdi, FUSE_LISTXATTR, vp, td, cred);
+ get_xattr_in = fdi.indata;
+ get_xattr_in->size = linux_list_len + sizeof(*get_xattr_out);
+ attr_str = (char *)fdi.indata + sizeof(*get_xattr_in);
+ snprintf(attr_str, len, "%s%c", prefix, extattr_namespace_separator);
- err = uiomove(bsd_list, bsd_list_len, uio);
- } else {
- debug_printf("listextattr: returned iosize %zu for %s attribute list is "
- "too small\n", fdi.iosize, prefix);
- err = EINVAL;
+ err = fdisp_wait_answ(&fdi);
+ if (err != 0) {
+ if (err == ENOSYS)
+ fsess_set_notimpl(mp, FUSE_LISTXATTR);
+ goto out;
}
+ linux_list = fdi.answ;
+ linux_list_len = fdi.iosize;
+
+ /*
+ * Retrieve the BSD compatible list values.
+ * The Linux / FUSE attribute list format isn't the same
+ * as FreeBSD's format. So we need to transform it into
+ * FreeBSD's format before giving it to the user.
+ */
+ bsd_list = malloc(linux_list_len, M_TEMP, M_WAITOK);
+ err = fuse_xattrlist_convert(prefix, linux_list, linux_list_len,
+ bsd_list, &bsd_list_len);
+ if (err != 0)
+ goto out;
+
+ if (ap->a_size != NULL)
+ *ap->a_size = bsd_list_len;
+
+ if (uio != NULL)
+ err = uiomove(bsd_list, bsd_list_len, uio);
+
out:
free(bsd_list, M_TEMP);
fdisp_destroy(&fdi);

File Metadata

Mime Type
text/plain
Expires
Thu, Mar 19, 4:38 AM (15 h, 35 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29946945
Default Alt Text
D13528.id37622.diff (3 KB)

Event Timeline