Changeset View
Changeset View
Standalone View
Standalone View
head/sys/fs/fuse/fuse_vnops.c
Show First 20 Lines • Show All 2,041 Lines • ▼ Show 20 Lines | fuse_vnop_getextattr(struct vop_getextattr_args *ap) | ||||
get_xattr_in = fdi.indata; | get_xattr_in = fdi.indata; | ||||
/* | /* | ||||
* Check to see whether we're querying the available size or | * Check to see whether we're querying the available size or | ||||
* issuing the actual request. If we pass in 0, we get back struct | * issuing the actual request. If we pass in 0, we get back struct | ||||
* fuse_getxattr_out. If we pass in a non-zero size, we get back | * fuse_getxattr_out. If we pass in a non-zero size, we get back | ||||
* that much data, without the struct fuse_getxattr_out header. | * that much data, without the struct fuse_getxattr_out header. | ||||
*/ | */ | ||||
if (ap->a_size != NULL) | if (uio == NULL) | ||||
get_xattr_in->size = 0; | get_xattr_in->size = 0; | ||||
else | else | ||||
get_xattr_in->size = uio->uio_resid; | get_xattr_in->size = uio->uio_resid; | ||||
attr_str = (char *)fdi.indata + sizeof(*get_xattr_in); | attr_str = (char *)fdi.indata + sizeof(*get_xattr_in); | ||||
snprintf(attr_str, len, "%s%c%s", prefix, extattr_namespace_separator, | snprintf(attr_str, len, "%s%c%s", prefix, extattr_namespace_separator, | ||||
ap->a_name); | ap->a_name); | ||||
err = fdisp_wait_answ(&fdi); | err = fdisp_wait_answ(&fdi); | ||||
if (err != 0) { | if (err != 0) { | ||||
if (err == ENOSYS) | if (err == ENOSYS) | ||||
fsess_set_notimpl(mp, FUSE_GETXATTR); | fsess_set_notimpl(mp, FUSE_GETXATTR); | ||||
debug_printf("getxattr: got err=%d from daemon\n", err); | debug_printf("getxattr: got err=%d from daemon\n", err); | ||||
goto out; | goto out; | ||||
} | } | ||||
/* | |||||
* If we get to this point (i.e. no error), we should have a valid | |||||
* answer of some sort. i.e. non-zero iosize and a valid pointer. | |||||
*/ | |||||
if ((fdi.answ == NULL) || (fdi.iosize == 0)) { | |||||
debug_printf("getxattr: err = 0, but answ = %p, iosize = %zu\n", | |||||
fdi.answ, fdi.iosize); | |||||
err = EINVAL; | |||||
goto out; | |||||
} | |||||
get_xattr_out = fdi.answ; | get_xattr_out = fdi.answ; | ||||
if (ap->a_size != NULL) { | if (ap->a_size != NULL) | ||||
*ap->a_size = get_xattr_out->size; | *ap->a_size = get_xattr_out->size; | ||||
} else if (fdi.iosize > 0) { | |||||
if (uio != NULL) | |||||
err = uiomove(fdi.answ, fdi.iosize, uio); | err = uiomove(fdi.answ, fdi.iosize, uio); | ||||
} else { | |||||
err = EINVAL; | |||||
} | |||||
out: | out: | ||||
fdisp_destroy(&fdi); | fdisp_destroy(&fdi); | ||||
return (err); | return (err); | ||||
} | } | ||||
/* | /* | ||||
struct vop_setextattr_args { | struct vop_setextattr_args { | ||||
▲ Show 20 Lines • Show All 133 Lines • ▼ Show 20 Lines | /* | ||||
}; | }; | ||||
*/ | */ | ||||
static int | static int | ||||
fuse_vnop_listextattr(struct vop_listextattr_args *ap) | fuse_vnop_listextattr(struct vop_listextattr_args *ap) | ||||
{ | { | ||||
struct vnode *vp = ap->a_vp; | struct vnode *vp = ap->a_vp; | ||||
struct uio *uio = ap->a_uio; | struct uio *uio = ap->a_uio; | ||||
struct fuse_dispatcher fdi = {0}; | struct fuse_dispatcher fdi = {0}; | ||||
struct fuse_getxattr_in *get_xattr_in; | struct fuse_listxattr_in *list_xattr_in; | ||||
struct fuse_getxattr_out *get_xattr_out; | struct fuse_listxattr_out *list_xattr_out; | ||||
struct mount *mp = vnode_mount(vp); | struct mount *mp = vnode_mount(vp); | ||||
size_t len; | size_t len; | ||||
char *prefix; | char *prefix; | ||||
char *attr_str; | char *attr_str; | ||||
char *bsd_list = NULL; | char *bsd_list = NULL; | ||||
char *linux_list; | |||||
int bsd_list_len; | int bsd_list_len; | ||||
int linux_list_len; | |||||
struct thread *td = ap->a_td; | struct thread *td = ap->a_td; | ||||
struct ucred *cred = ap->a_cred; | struct ucred *cred = ap->a_cred; | ||||
int err = 0; | int err = 0; | ||||
fuse_trace_printf_vnop(); | fuse_trace_printf_vnop(); | ||||
if (fuse_isdeadfs(vp)) | if (fuse_isdeadfs(vp)) | ||||
return ENXIO; | return ENXIO; | ||||
/* | /* | ||||
* Add space for a NUL and the period separator if enabled. | * Add space for a NUL and the period separator if enabled. | ||||
* Default to looking for user attributes. | * Default to looking for user attributes. | ||||
*/ | */ | ||||
if (ap->a_attrnamespace == EXTATTR_NAMESPACE_SYSTEM) | if (ap->a_attrnamespace == EXTATTR_NAMESPACE_SYSTEM) | ||||
prefix = EXTATTR_NAMESPACE_SYSTEM_STRING; | prefix = EXTATTR_NAMESPACE_SYSTEM_STRING; | ||||
else | else | ||||
prefix = EXTATTR_NAMESPACE_USER_STRING; | prefix = EXTATTR_NAMESPACE_USER_STRING; | ||||
len = strlen(prefix) + sizeof(extattr_namespace_separator) + 1; | len = strlen(prefix) + sizeof(extattr_namespace_separator) + 1; | ||||
fdisp_init(&fdi, sizeof(*get_xattr_in) + len); | fdisp_init(&fdi, sizeof(*list_xattr_in) + len); | ||||
fdisp_make_vp(&fdi, FUSE_LISTXATTR, vp, td, cred); | fdisp_make_vp(&fdi, FUSE_LISTXATTR, vp, td, cred); | ||||
get_xattr_in = fdi.indata; | /* | ||||
if (ap->a_size != NULL) | * Retrieve Linux / FUSE compatible list size. | ||||
get_xattr_in->size = 0; | */ | ||||
else | list_xattr_in = fdi.indata; | ||||
get_xattr_in->size = uio->uio_resid + sizeof(*get_xattr_out); | list_xattr_in->size = 0; | ||||
attr_str = (char *)fdi.indata + sizeof(*list_xattr_in); | |||||
attr_str = (char *)fdi.indata + sizeof(*get_xattr_in); | |||||
snprintf(attr_str, len, "%s%c", prefix, extattr_namespace_separator); | snprintf(attr_str, len, "%s%c", prefix, extattr_namespace_separator); | ||||
err = fdisp_wait_answ(&fdi); | err = fdisp_wait_answ(&fdi); | ||||
if (err != 0) { | if (err != 0) { | ||||
if (err == ENOSYS) | if (err == ENOSYS) | ||||
fsess_set_notimpl(mp, FUSE_LISTXATTR); | fsess_set_notimpl(mp, FUSE_LISTXATTR); | ||||
debug_printf("listextattr: got err=%d from daemon\n", err); | debug_printf("listextattr: got err=%d from daemon\n", err); | ||||
goto out; | goto out; | ||||
} | } | ||||
if ((fdi.answ == NULL) || (fdi.iosize == 0)) { | list_xattr_out = fdi.answ; | ||||
err = EINVAL; | linux_list_len = list_xattr_out->size; | ||||
if (linux_list_len == 0) { | |||||
if (ap->a_size != NULL) | |||||
*ap->a_size = linux_list_len; | |||||
goto out; | goto out; | ||||
} | } | ||||
get_xattr_out = fdi.answ; | |||||
if (ap->a_size != NULL) { | |||||
*ap->a_size = get_xattr_out->size; | |||||
} else if (fdi.iosize > 0) { | |||||
/* | /* | ||||
* Retrieve Linux / FUSE compatible list values. | |||||
*/ | |||||
fdisp_make_vp(&fdi, FUSE_LISTXATTR, vp, td, cred); | |||||
list_xattr_in = fdi.indata; | |||||
list_xattr_in->size = linux_list_len + sizeof(*list_xattr_out); | |||||
attr_str = (char *)fdi.indata + sizeof(*list_xattr_in); | |||||
snprintf(attr_str, len, "%s%c", prefix, extattr_namespace_separator); | |||||
err = fdisp_wait_answ(&fdi); | |||||
if (err != 0) | |||||
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 | * The Linux / FUSE attribute list format isn't the same | ||||
* as FreeBSD's format. So we need to transform it into | * as FreeBSD's format. So we need to transform it into | ||||
* FreeBSD's format before giving it to the user. | * FreeBSD's format before giving it to the user. | ||||
*/ | */ | ||||
bsd_list = malloc(fdi.iosize, M_TEMP, M_WAITOK); | bsd_list = malloc(linux_list_len, M_TEMP, M_WAITOK); | ||||
err = fuse_xattrlist_convert(prefix, fdi.answ, fdi.iosize, | err = fuse_xattrlist_convert(prefix, linux_list, linux_list_len, | ||||
bsd_list, &bsd_list_len); | bsd_list, &bsd_list_len); | ||||
if (err != 0) | if (err != 0) | ||||
goto out; | goto out; | ||||
if (ap->a_size != NULL) | |||||
*ap->a_size = bsd_list_len; | |||||
if (uio != NULL) | |||||
err = uiomove(bsd_list, bsd_list_len, uio); | 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; | |||||
} | |||||
out: | out: | ||||
free(bsd_list, M_TEMP); | free(bsd_list, M_TEMP); | ||||
fdisp_destroy(&fdi); | fdisp_destroy(&fdi); | ||||
return (err); | return (err); | ||||
} | } | ||||
/* | /* | ||||
▲ Show 20 Lines • Show All 71 Lines • Show Last 20 Lines |