]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - fs/xfs/xfs_xattr.c
xfs: remove unused transaction callback variables
[mirror_ubuntu-artful-kernel.git] / fs / xfs / xfs_xattr.c
CommitLineData
f9e09f09
LM
1/*
2 * Copyright (C) 2008 Christoph Hellwig.
3 * Portions Copyright (C) 2000-2008 Silicon Graphics, Inc.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19#include "xfs.h"
69432832 20#include "xfs_log_format.h"
57062787
DC
21#include "xfs_log.h"
22#include "xfs_trans.h"
23#include "xfs_sb.h"
24#include "xfs_ag.h"
25#include "xfs_mount.h"
26#include "xfs_da_format.h"
f9e09f09
LM
27#include "xfs_bmap_btree.h"
28#include "xfs_inode.h"
29#include "xfs_attr.h"
30#include "xfs_attr_leaf.h"
31#include "xfs_acl.h"
f9e09f09
LM
32
33#include <linux/posix_acl_xattr.h>
34#include <linux/xattr.h>
35
36
f9e09f09 37static int
431547b3 38xfs_xattr_get(struct dentry *dentry, const char *name,
f9e09f09
LM
39 void *value, size_t size, int xflags)
40{
431547b3 41 struct xfs_inode *ip = XFS_I(dentry->d_inode);
f9e09f09
LM
42 int error, asize = size;
43
44 if (strcmp(name, "") == 0)
45 return -EINVAL;
46
47 /* Convert Linux syscall to XFS internal ATTR flags */
48 if (!size) {
49 xflags |= ATTR_KERNOVAL;
50 value = NULL;
51 }
52
a9273ca5 53 error = -xfs_attr_get(ip, (unsigned char *)name, value, &asize, xflags);
f9e09f09
LM
54 if (error)
55 return error;
56 return asize;
57}
58
59static int
431547b3 60xfs_xattr_set(struct dentry *dentry, const char *name, const void *value,
f9e09f09
LM
61 size_t size, int flags, int xflags)
62{
431547b3 63 struct xfs_inode *ip = XFS_I(dentry->d_inode);
f9e09f09
LM
64
65 if (strcmp(name, "") == 0)
66 return -EINVAL;
67
68 /* Convert Linux syscall to XFS internal ATTR flags */
69 if (flags & XATTR_CREATE)
70 xflags |= ATTR_CREATE;
71 if (flags & XATTR_REPLACE)
72 xflags |= ATTR_REPLACE;
73
74 if (!value)
a9273ca5
DC
75 return -xfs_attr_remove(ip, (unsigned char *)name, xflags);
76 return -xfs_attr_set(ip, (unsigned char *)name,
77 (void *)value, size, xflags);
f9e09f09
LM
78}
79
46e58764 80static const struct xattr_handler xfs_xattr_user_handler = {
f9e09f09 81 .prefix = XATTR_USER_PREFIX,
431547b3
CH
82 .flags = 0, /* no flags implies user namespace */
83 .get = xfs_xattr_get,
84 .set = xfs_xattr_set,
f9e09f09
LM
85};
86
46e58764 87static const struct xattr_handler xfs_xattr_trusted_handler = {
f9e09f09 88 .prefix = XATTR_TRUSTED_PREFIX,
431547b3
CH
89 .flags = ATTR_ROOT,
90 .get = xfs_xattr_get,
91 .set = xfs_xattr_set,
f9e09f09
LM
92};
93
46e58764 94static const struct xattr_handler xfs_xattr_security_handler = {
f9e09f09 95 .prefix = XATTR_SECURITY_PREFIX,
431547b3
CH
96 .flags = ATTR_SECURE,
97 .get = xfs_xattr_get,
98 .set = xfs_xattr_set,
f9e09f09
LM
99};
100
46e58764 101const struct xattr_handler *xfs_xattr_handlers[] = {
f9e09f09
LM
102 &xfs_xattr_user_handler,
103 &xfs_xattr_trusted_handler,
104 &xfs_xattr_security_handler,
ef14f0c1 105#ifdef CONFIG_XFS_POSIX_ACL
431547b3
CH
106 &xfs_xattr_acl_access_handler,
107 &xfs_xattr_acl_default_handler,
ef14f0c1 108#endif
f9e09f09
LM
109 NULL
110};
111
112static unsigned int xfs_xattr_prefix_len(int flags)
113{
114 if (flags & XFS_ATTR_SECURE)
115 return sizeof("security");
116 else if (flags & XFS_ATTR_ROOT)
117 return sizeof("trusted");
118 else
119 return sizeof("user");
120}
121
122static const char *xfs_xattr_prefix(int flags)
123{
124 if (flags & XFS_ATTR_SECURE)
125 return xfs_xattr_security_handler.prefix;
126 else if (flags & XFS_ATTR_ROOT)
127 return xfs_xattr_trusted_handler.prefix;
128 else
129 return xfs_xattr_user_handler.prefix;
130}
131
132static int
a9273ca5
DC
133xfs_xattr_put_listent(
134 struct xfs_attr_list_context *context,
135 int flags,
136 unsigned char *name,
137 int namelen,
138 int valuelen,
139 unsigned char *value)
f9e09f09
LM
140{
141 unsigned int prefix_len = xfs_xattr_prefix_len(flags);
142 char *offset;
143 int arraytop;
144
145 ASSERT(context->count >= 0);
146
147 /*
148 * Only show root namespace entries if we are actually allowed to
149 * see them.
150 */
151 if ((flags & XFS_ATTR_ROOT) && !capable(CAP_SYS_ADMIN))
152 return 0;
153
154 arraytop = context->count + prefix_len + namelen + 1;
155 if (arraytop > context->firstu) {
156 context->count = -1; /* insufficient space */
157 return 1;
158 }
159 offset = (char *)context->alist + context->count;
160 strncpy(offset, xfs_xattr_prefix(flags), prefix_len);
161 offset += prefix_len;
a9273ca5 162 strncpy(offset, (char *)name, namelen); /* real name */
f9e09f09
LM
163 offset += namelen;
164 *offset = '\0';
165 context->count += prefix_len + namelen + 1;
166 return 0;
167}
168
169static int
a9273ca5
DC
170xfs_xattr_put_listent_sizes(
171 struct xfs_attr_list_context *context,
172 int flags,
173 unsigned char *name,
174 int namelen,
175 int valuelen,
176 unsigned char *value)
f9e09f09
LM
177{
178 context->count += xfs_xattr_prefix_len(flags) + namelen + 1;
179 return 0;
180}
181
182static int
183list_one_attr(const char *name, const size_t len, void *data,
184 size_t size, ssize_t *result)
185{
186 char *p = data + *result;
187
188 *result += len;
189 if (!size)
190 return 0;
191 if (*result > size)
192 return -ERANGE;
193
194 strcpy(p, name);
195 return 0;
196}
197
198ssize_t
199xfs_vn_listxattr(struct dentry *dentry, char *data, size_t size)
200{
201 struct xfs_attr_list_context context;
202 struct attrlist_cursor_kern cursor = { 0 };
203 struct inode *inode = dentry->d_inode;
204 int error;
205
206 /*
207 * First read the regular on-disk attributes.
208 */
209 memset(&context, 0, sizeof(context));
210 context.dp = XFS_I(inode);
211 context.cursor = &cursor;
212 context.resynch = 1;
213 context.alist = data;
214 context.bufsize = size;
215 context.firstu = context.bufsize;
216
217 if (size)
218 context.put_listent = xfs_xattr_put_listent;
219 else
220 context.put_listent = xfs_xattr_put_listent_sizes;
221
222 xfs_attr_list_int(&context);
223 if (context.count < 0)
224 return -ERANGE;
225
226 /*
227 * Then add the two synthetic ACL attributes.
228 */
ef14f0c1 229 if (posix_acl_access_exists(inode)) {
f9e09f09
LM
230 error = list_one_attr(POSIX_ACL_XATTR_ACCESS,
231 strlen(POSIX_ACL_XATTR_ACCESS) + 1,
232 data, size, &context.count);
233 if (error)
234 return error;
235 }
236
ef14f0c1 237 if (posix_acl_default_exists(inode)) {
f9e09f09
LM
238 error = list_one_attr(POSIX_ACL_XATTR_DEFAULT,
239 strlen(POSIX_ACL_XATTR_DEFAULT) + 1,
240 data, size, &context.count);
241 if (error)
242 return error;
243 }
244
245 return context.count;
246}