2
* Copyright (C) 2008 Christoph Hellwig.
3
* Portions Copyright (C) 2000-2008 Silicon Graphics, Inc.
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.
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.
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
20
#include "xfs_da_btree.h"
21
#include "xfs_bmap_btree.h"
22
#include "xfs_inode.h"
24
#include "xfs_attr_leaf.h"
26
#include "xfs_vnodeops.h"
28
#include <linux/posix_acl_xattr.h>
29
#include <linux/xattr.h>
33
xfs_xattr_get(struct dentry *dentry, const char *name,
34
void *value, size_t size, int xflags)
36
struct xfs_inode *ip = XFS_I(dentry->d_inode);
37
int error, asize = size;
39
if (strcmp(name, "") == 0)
42
/* Convert Linux syscall to XFS internal ATTR flags */
44
xflags |= ATTR_KERNOVAL;
48
error = -xfs_attr_get(ip, (unsigned char *)name, value, &asize, xflags);
55
xfs_xattr_set(struct dentry *dentry, const char *name, const void *value,
56
size_t size, int flags, int xflags)
58
struct xfs_inode *ip = XFS_I(dentry->d_inode);
60
if (strcmp(name, "") == 0)
63
/* Convert Linux syscall to XFS internal ATTR flags */
64
if (flags & XATTR_CREATE)
65
xflags |= ATTR_CREATE;
66
if (flags & XATTR_REPLACE)
67
xflags |= ATTR_REPLACE;
70
return -xfs_attr_remove(ip, (unsigned char *)name, xflags);
71
return -xfs_attr_set(ip, (unsigned char *)name,
72
(void *)value, size, xflags);
75
static const struct xattr_handler xfs_xattr_user_handler = {
76
.prefix = XATTR_USER_PREFIX,
77
.flags = 0, /* no flags implies user namespace */
82
static const struct xattr_handler xfs_xattr_trusted_handler = {
83
.prefix = XATTR_TRUSTED_PREFIX,
89
static const struct xattr_handler xfs_xattr_security_handler = {
90
.prefix = XATTR_SECURITY_PREFIX,
96
const struct xattr_handler *xfs_xattr_handlers[] = {
97
&xfs_xattr_user_handler,
98
&xfs_xattr_trusted_handler,
99
&xfs_xattr_security_handler,
100
#ifdef CONFIG_XFS_POSIX_ACL
101
&xfs_xattr_acl_access_handler,
102
&xfs_xattr_acl_default_handler,
107
static unsigned int xfs_xattr_prefix_len(int flags)
109
if (flags & XFS_ATTR_SECURE)
110
return sizeof("security");
111
else if (flags & XFS_ATTR_ROOT)
112
return sizeof("trusted");
114
return sizeof("user");
117
static const char *xfs_xattr_prefix(int flags)
119
if (flags & XFS_ATTR_SECURE)
120
return xfs_xattr_security_handler.prefix;
121
else if (flags & XFS_ATTR_ROOT)
122
return xfs_xattr_trusted_handler.prefix;
124
return xfs_xattr_user_handler.prefix;
128
xfs_xattr_put_listent(
129
struct xfs_attr_list_context *context,
134
unsigned char *value)
136
unsigned int prefix_len = xfs_xattr_prefix_len(flags);
140
ASSERT(context->count >= 0);
143
* Only show root namespace entries if we are actually allowed to
146
if ((flags & XFS_ATTR_ROOT) && !capable(CAP_SYS_ADMIN))
149
arraytop = context->count + prefix_len + namelen + 1;
150
if (arraytop > context->firstu) {
151
context->count = -1; /* insufficient space */
154
offset = (char *)context->alist + context->count;
155
strncpy(offset, xfs_xattr_prefix(flags), prefix_len);
156
offset += prefix_len;
157
strncpy(offset, (char *)name, namelen); /* real name */
160
context->count += prefix_len + namelen + 1;
165
xfs_xattr_put_listent_sizes(
166
struct xfs_attr_list_context *context,
171
unsigned char *value)
173
context->count += xfs_xattr_prefix_len(flags) + namelen + 1;
178
list_one_attr(const char *name, const size_t len, void *data,
179
size_t size, ssize_t *result)
181
char *p = data + *result;
194
xfs_vn_listxattr(struct dentry *dentry, char *data, size_t size)
196
struct xfs_attr_list_context context;
197
struct attrlist_cursor_kern cursor = { 0 };
198
struct inode *inode = dentry->d_inode;
202
* First read the regular on-disk attributes.
204
memset(&context, 0, sizeof(context));
205
context.dp = XFS_I(inode);
206
context.cursor = &cursor;
208
context.alist = data;
209
context.bufsize = size;
210
context.firstu = context.bufsize;
213
context.put_listent = xfs_xattr_put_listent;
215
context.put_listent = xfs_xattr_put_listent_sizes;
217
xfs_attr_list_int(&context);
218
if (context.count < 0)
222
* Then add the two synthetic ACL attributes.
224
if (posix_acl_access_exists(inode)) {
225
error = list_one_attr(POSIX_ACL_XATTR_ACCESS,
226
strlen(POSIX_ACL_XATTR_ACCESS) + 1,
227
data, size, &context.count);
232
if (posix_acl_default_exists(inode)) {
233
error = list_one_attr(POSIX_ACL_XATTR_DEFAULT,
234
strlen(POSIX_ACL_XATTR_DEFAULT) + 1,
235
data, size, &context.count);
240
return context.count;