Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * FUSE: Filesystem in Userspace
0003  * Copyright (C) 2001-2016  Miklos Szeredi <miklos@szeredi.hu>
0004  *
0005  * This program can be distributed under the terms of the GNU GPL.
0006  * See the file COPYING.
0007  */
0008 
0009 #include "fuse_i.h"
0010 
0011 #include <linux/xattr.h>
0012 #include <linux/posix_acl_xattr.h>
0013 
0014 int fuse_setxattr(struct inode *inode, const char *name, const void *value,
0015           size_t size, int flags, unsigned int extra_flags)
0016 {
0017     struct fuse_mount *fm = get_fuse_mount(inode);
0018     FUSE_ARGS(args);
0019     struct fuse_setxattr_in inarg;
0020     int err;
0021 
0022     if (fm->fc->no_setxattr)
0023         return -EOPNOTSUPP;
0024 
0025     memset(&inarg, 0, sizeof(inarg));
0026     inarg.size = size;
0027     inarg.flags = flags;
0028     inarg.setxattr_flags = extra_flags;
0029 
0030     args.opcode = FUSE_SETXATTR;
0031     args.nodeid = get_node_id(inode);
0032     args.in_numargs = 3;
0033     args.in_args[0].size = fm->fc->setxattr_ext ?
0034         sizeof(inarg) : FUSE_COMPAT_SETXATTR_IN_SIZE;
0035     args.in_args[0].value = &inarg;
0036     args.in_args[1].size = strlen(name) + 1;
0037     args.in_args[1].value = name;
0038     args.in_args[2].size = size;
0039     args.in_args[2].value = value;
0040     err = fuse_simple_request(fm, &args);
0041     if (err == -ENOSYS) {
0042         fm->fc->no_setxattr = 1;
0043         err = -EOPNOTSUPP;
0044     }
0045     if (!err)
0046         fuse_update_ctime(inode);
0047 
0048     return err;
0049 }
0050 
0051 ssize_t fuse_getxattr(struct inode *inode, const char *name, void *value,
0052               size_t size)
0053 {
0054     struct fuse_mount *fm = get_fuse_mount(inode);
0055     FUSE_ARGS(args);
0056     struct fuse_getxattr_in inarg;
0057     struct fuse_getxattr_out outarg;
0058     ssize_t ret;
0059 
0060     if (fm->fc->no_getxattr)
0061         return -EOPNOTSUPP;
0062 
0063     memset(&inarg, 0, sizeof(inarg));
0064     inarg.size = size;
0065     args.opcode = FUSE_GETXATTR;
0066     args.nodeid = get_node_id(inode);
0067     args.in_numargs = 2;
0068     args.in_args[0].size = sizeof(inarg);
0069     args.in_args[0].value = &inarg;
0070     args.in_args[1].size = strlen(name) + 1;
0071     args.in_args[1].value = name;
0072     /* This is really two different operations rolled into one */
0073     args.out_numargs = 1;
0074     if (size) {
0075         args.out_argvar = true;
0076         args.out_args[0].size = size;
0077         args.out_args[0].value = value;
0078     } else {
0079         args.out_args[0].size = sizeof(outarg);
0080         args.out_args[0].value = &outarg;
0081     }
0082     ret = fuse_simple_request(fm, &args);
0083     if (!ret && !size)
0084         ret = min_t(ssize_t, outarg.size, XATTR_SIZE_MAX);
0085     if (ret == -ENOSYS) {
0086         fm->fc->no_getxattr = 1;
0087         ret = -EOPNOTSUPP;
0088     }
0089     return ret;
0090 }
0091 
0092 static int fuse_verify_xattr_list(char *list, size_t size)
0093 {
0094     size_t origsize = size;
0095 
0096     while (size) {
0097         size_t thislen = strnlen(list, size);
0098 
0099         if (!thislen || thislen == size)
0100             return -EIO;
0101 
0102         size -= thislen + 1;
0103         list += thislen + 1;
0104     }
0105 
0106     return origsize;
0107 }
0108 
0109 ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
0110 {
0111     struct inode *inode = d_inode(entry);
0112     struct fuse_mount *fm = get_fuse_mount(inode);
0113     FUSE_ARGS(args);
0114     struct fuse_getxattr_in inarg;
0115     struct fuse_getxattr_out outarg;
0116     ssize_t ret;
0117 
0118     if (fuse_is_bad(inode))
0119         return -EIO;
0120 
0121     if (!fuse_allow_current_process(fm->fc))
0122         return -EACCES;
0123 
0124     if (fm->fc->no_listxattr)
0125         return -EOPNOTSUPP;
0126 
0127     memset(&inarg, 0, sizeof(inarg));
0128     inarg.size = size;
0129     args.opcode = FUSE_LISTXATTR;
0130     args.nodeid = get_node_id(inode);
0131     args.in_numargs = 1;
0132     args.in_args[0].size = sizeof(inarg);
0133     args.in_args[0].value = &inarg;
0134     /* This is really two different operations rolled into one */
0135     args.out_numargs = 1;
0136     if (size) {
0137         args.out_argvar = true;
0138         args.out_args[0].size = size;
0139         args.out_args[0].value = list;
0140     } else {
0141         args.out_args[0].size = sizeof(outarg);
0142         args.out_args[0].value = &outarg;
0143     }
0144     ret = fuse_simple_request(fm, &args);
0145     if (!ret && !size)
0146         ret = min_t(ssize_t, outarg.size, XATTR_LIST_MAX);
0147     if (ret > 0 && size)
0148         ret = fuse_verify_xattr_list(list, ret);
0149     if (ret == -ENOSYS) {
0150         fm->fc->no_listxattr = 1;
0151         ret = -EOPNOTSUPP;
0152     }
0153     return ret;
0154 }
0155 
0156 int fuse_removexattr(struct inode *inode, const char *name)
0157 {
0158     struct fuse_mount *fm = get_fuse_mount(inode);
0159     FUSE_ARGS(args);
0160     int err;
0161 
0162     if (fm->fc->no_removexattr)
0163         return -EOPNOTSUPP;
0164 
0165     args.opcode = FUSE_REMOVEXATTR;
0166     args.nodeid = get_node_id(inode);
0167     args.in_numargs = 1;
0168     args.in_args[0].size = strlen(name) + 1;
0169     args.in_args[0].value = name;
0170     err = fuse_simple_request(fm, &args);
0171     if (err == -ENOSYS) {
0172         fm->fc->no_removexattr = 1;
0173         err = -EOPNOTSUPP;
0174     }
0175     if (!err)
0176         fuse_update_ctime(inode);
0177 
0178     return err;
0179 }
0180 
0181 static int fuse_xattr_get(const struct xattr_handler *handler,
0182              struct dentry *dentry, struct inode *inode,
0183              const char *name, void *value, size_t size)
0184 {
0185     if (fuse_is_bad(inode))
0186         return -EIO;
0187 
0188     return fuse_getxattr(inode, name, value, size);
0189 }
0190 
0191 static int fuse_xattr_set(const struct xattr_handler *handler,
0192               struct user_namespace *mnt_userns,
0193               struct dentry *dentry, struct inode *inode,
0194               const char *name, const void *value, size_t size,
0195               int flags)
0196 {
0197     if (fuse_is_bad(inode))
0198         return -EIO;
0199 
0200     if (!value)
0201         return fuse_removexattr(inode, name);
0202 
0203     return fuse_setxattr(inode, name, value, size, flags, 0);
0204 }
0205 
0206 static bool no_xattr_list(struct dentry *dentry)
0207 {
0208     return false;
0209 }
0210 
0211 static int no_xattr_get(const struct xattr_handler *handler,
0212             struct dentry *dentry, struct inode *inode,
0213             const char *name, void *value, size_t size)
0214 {
0215     return -EOPNOTSUPP;
0216 }
0217 
0218 static int no_xattr_set(const struct xattr_handler *handler,
0219             struct user_namespace *mnt_userns,
0220             struct dentry *dentry, struct inode *nodee,
0221             const char *name, const void *value,
0222             size_t size, int flags)
0223 {
0224     return -EOPNOTSUPP;
0225 }
0226 
0227 static const struct xattr_handler fuse_xattr_handler = {
0228     .prefix = "",
0229     .get    = fuse_xattr_get,
0230     .set    = fuse_xattr_set,
0231 };
0232 
0233 const struct xattr_handler *fuse_xattr_handlers[] = {
0234     &fuse_xattr_handler,
0235     NULL
0236 };
0237 
0238 const struct xattr_handler *fuse_acl_xattr_handlers[] = {
0239     &posix_acl_access_xattr_handler,
0240     &posix_acl_default_xattr_handler,
0241     &fuse_xattr_handler,
0242     NULL
0243 };
0244 
0245 static const struct xattr_handler fuse_no_acl_access_xattr_handler = {
0246     .name  = XATTR_NAME_POSIX_ACL_ACCESS,
0247     .flags = ACL_TYPE_ACCESS,
0248     .list  = no_xattr_list,
0249     .get   = no_xattr_get,
0250     .set   = no_xattr_set,
0251 };
0252 
0253 static const struct xattr_handler fuse_no_acl_default_xattr_handler = {
0254     .name  = XATTR_NAME_POSIX_ACL_DEFAULT,
0255     .flags = ACL_TYPE_ACCESS,
0256     .list  = no_xattr_list,
0257     .get   = no_xattr_get,
0258     .set   = no_xattr_set,
0259 };
0260 
0261 const struct xattr_handler *fuse_no_acl_xattr_handlers[] = {
0262     &fuse_no_acl_access_xattr_handler,
0263     &fuse_no_acl_default_xattr_handler,
0264     &fuse_xattr_handler,
0265     NULL
0266 };