~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/fs/fuse/xattr.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * FUSE: Filesystem in Userspace
  3  * Copyright (C) 2001-2016  Miklos Szeredi <miklos@szeredi.hu>
  4  *
  5  * This program can be distributed under the terms of the GNU GPL.
  6  * See the file COPYING.
  7  */
  8 
  9 #include "fuse_i.h"
 10 
 11 #include <linux/xattr.h>
 12 #include <linux/posix_acl_xattr.h>
 13 
 14 int fuse_setxattr(struct inode *inode, const char *name, const void *value,
 15                   size_t size, int flags, unsigned int extra_flags)
 16 {
 17         struct fuse_mount *fm = get_fuse_mount(inode);
 18         FUSE_ARGS(args);
 19         struct fuse_setxattr_in inarg;
 20         int err;
 21 
 22         if (fm->fc->no_setxattr)
 23                 return -EOPNOTSUPP;
 24 
 25         memset(&inarg, 0, sizeof(inarg));
 26         inarg.size = size;
 27         inarg.flags = flags;
 28         inarg.setxattr_flags = extra_flags;
 29 
 30         args.opcode = FUSE_SETXATTR;
 31         args.nodeid = get_node_id(inode);
 32         args.in_numargs = 3;
 33         args.in_args[0].size = fm->fc->setxattr_ext ?
 34                 sizeof(inarg) : FUSE_COMPAT_SETXATTR_IN_SIZE;
 35         args.in_args[0].value = &inarg;
 36         args.in_args[1].size = strlen(name) + 1;
 37         args.in_args[1].value = name;
 38         args.in_args[2].size = size;
 39         args.in_args[2].value = value;
 40         err = fuse_simple_request(fm, &args);
 41         if (err == -ENOSYS) {
 42                 fm->fc->no_setxattr = 1;
 43                 err = -EOPNOTSUPP;
 44         }
 45         if (!err)
 46                 fuse_update_ctime(inode);
 47 
 48         return err;
 49 }
 50 
 51 ssize_t fuse_getxattr(struct inode *inode, const char *name, void *value,
 52                       size_t size)
 53 {
 54         struct fuse_mount *fm = get_fuse_mount(inode);
 55         FUSE_ARGS(args);
 56         struct fuse_getxattr_in inarg;
 57         struct fuse_getxattr_out outarg;
 58         ssize_t ret;
 59 
 60         if (fm->fc->no_getxattr)
 61                 return -EOPNOTSUPP;
 62 
 63         memset(&inarg, 0, sizeof(inarg));
 64         inarg.size = size;
 65         args.opcode = FUSE_GETXATTR;
 66         args.nodeid = get_node_id(inode);
 67         args.in_numargs = 2;
 68         args.in_args[0].size = sizeof(inarg);
 69         args.in_args[0].value = &inarg;
 70         args.in_args[1].size = strlen(name) + 1;
 71         args.in_args[1].value = name;
 72         /* This is really two different operations rolled into one */
 73         args.out_numargs = 1;
 74         if (size) {
 75                 args.out_argvar = true;
 76                 args.out_args[0].size = size;
 77                 args.out_args[0].value = value;
 78         } else {
 79                 args.out_args[0].size = sizeof(outarg);
 80                 args.out_args[0].value = &outarg;
 81         }
 82         ret = fuse_simple_request(fm, &args);
 83         if (!ret && !size)
 84                 ret = min_t(size_t, outarg.size, XATTR_SIZE_MAX);
 85         if (ret == -ENOSYS) {
 86                 fm->fc->no_getxattr = 1;
 87                 ret = -EOPNOTSUPP;
 88         }
 89         return ret;
 90 }
 91 
 92 static int fuse_verify_xattr_list(char *list, size_t size)
 93 {
 94         size_t origsize = size;
 95 
 96         while (size) {
 97                 size_t thislen = strnlen(list, size);
 98 
 99                 if (!thislen || thislen == size)
100                         return -EIO;
101 
102                 size -= thislen + 1;
103                 list += thislen + 1;
104         }
105 
106         return origsize;
107 }
108 
109 ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
110 {
111         struct inode *inode = d_inode(entry);
112         struct fuse_mount *fm = get_fuse_mount(inode);
113         FUSE_ARGS(args);
114         struct fuse_getxattr_in inarg;
115         struct fuse_getxattr_out outarg;
116         ssize_t ret;
117 
118         if (fuse_is_bad(inode))
119                 return -EIO;
120 
121         if (!fuse_allow_current_process(fm->fc))
122                 return -EACCES;
123 
124         if (fm->fc->no_listxattr)
125                 return -EOPNOTSUPP;
126 
127         memset(&inarg, 0, sizeof(inarg));
128         inarg.size = size;
129         args.opcode = FUSE_LISTXATTR;
130         args.nodeid = get_node_id(inode);
131         args.in_numargs = 1;
132         args.in_args[0].size = sizeof(inarg);
133         args.in_args[0].value = &inarg;
134         /* This is really two different operations rolled into one */
135         args.out_numargs = 1;
136         if (size) {
137                 args.out_argvar = true;
138                 args.out_args[0].size = size;
139                 args.out_args[0].value = list;
140         } else {
141                 args.out_args[0].size = sizeof(outarg);
142                 args.out_args[0].value = &outarg;
143         }
144         ret = fuse_simple_request(fm, &args);
145         if (!ret && !size)
146                 ret = min_t(size_t, outarg.size, XATTR_LIST_MAX);
147         if (ret > 0 && size)
148                 ret = fuse_verify_xattr_list(list, ret);
149         if (ret == -ENOSYS) {
150                 fm->fc->no_listxattr = 1;
151                 ret = -EOPNOTSUPP;
152         }
153         return ret;
154 }
155 
156 int fuse_removexattr(struct inode *inode, const char *name)
157 {
158         struct fuse_mount *fm = get_fuse_mount(inode);
159         FUSE_ARGS(args);
160         int err;
161 
162         if (fm->fc->no_removexattr)
163                 return -EOPNOTSUPP;
164 
165         args.opcode = FUSE_REMOVEXATTR;
166         args.nodeid = get_node_id(inode);
167         args.in_numargs = 1;
168         args.in_args[0].size = strlen(name) + 1;
169         args.in_args[0].value = name;
170         err = fuse_simple_request(fm, &args);
171         if (err == -ENOSYS) {
172                 fm->fc->no_removexattr = 1;
173                 err = -EOPNOTSUPP;
174         }
175         if (!err)
176                 fuse_update_ctime(inode);
177 
178         return err;
179 }
180 
181 static int fuse_xattr_get(const struct xattr_handler *handler,
182                          struct dentry *dentry, struct inode *inode,
183                          const char *name, void *value, size_t size)
184 {
185         if (fuse_is_bad(inode))
186                 return -EIO;
187 
188         return fuse_getxattr(inode, name, value, size);
189 }
190 
191 static int fuse_xattr_set(const struct xattr_handler *handler,
192                           struct mnt_idmap *idmap,
193                           struct dentry *dentry, struct inode *inode,
194                           const char *name, const void *value, size_t size,
195                           int flags)
196 {
197         if (fuse_is_bad(inode))
198                 return -EIO;
199 
200         if (!value)
201                 return fuse_removexattr(inode, name);
202 
203         return fuse_setxattr(inode, name, value, size, flags, 0);
204 }
205 
206 static const struct xattr_handler fuse_xattr_handler = {
207         .prefix = "",
208         .get    = fuse_xattr_get,
209         .set    = fuse_xattr_set,
210 };
211 
212 const struct xattr_handler * const fuse_xattr_handlers[] = {
213         &fuse_xattr_handler,
214         NULL
215 };
216 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php