From db9f3de5e094fb0c8899abfb5077b4fa2e4c1738 Mon Sep 17 00:00:00 2001 From: Mimi Zohar Date: Wed, 9 Mar 2011 14:23:34 -0500 Subject: [PATCH] --- yaml --- r: 264479 b: refs/heads/master c: 1601fbad2b14e0b8d4dbb55e749bfe31e972818a h: refs/heads/master i: 264477: e57348303e6a7d8918916192eb0cc0f602b15351 264475: 00dd51e91856a216a529a58534b1abf548ec71a2 264471: 140cdca60d5ab8575cdd19fab8ace810a02971cb 264463: c83c7ea622b810c6fbd5b16f0f1d2f7b10bbba2f 264447: fdfc63b7ab56caad357bc64309ca42ac9e3e56e7 v: v3 --- [refs] | 2 +- trunk/fs/xattr.c | 58 +++++++++++++++++++++++++++++++++++++ trunk/include/linux/xattr.h | 5 +++- 3 files changed, 63 insertions(+), 2 deletions(-) diff --git a/[refs] b/[refs] index ef08f138e756..7dea720875ae 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: f381c272224f5f158f5cff64f8f3481fa0eee8b3 +refs/heads/master: 1601fbad2b14e0b8d4dbb55e749bfe31e972818a diff --git a/trunk/fs/xattr.c b/trunk/fs/xattr.c index f060663ab70c..851808c92b30 100644 --- a/trunk/fs/xattr.c +++ b/trunk/fs/xattr.c @@ -166,6 +166,64 @@ xattr_getsecurity(struct inode *inode, const char *name, void *value, } EXPORT_SYMBOL_GPL(xattr_getsecurity); +/* + * vfs_getxattr_alloc - allocate memory, if necessary, before calling getxattr + * + * Allocate memory, if not already allocated, or re-allocate correct size, + * before retrieving the extended attribute. + * + * Returns the result of alloc, if failed, or the getxattr operation. + */ +ssize_t +vfs_getxattr_alloc(struct dentry *dentry, const char *name, char **xattr_value, + size_t xattr_size, gfp_t flags) +{ + struct inode *inode = dentry->d_inode; + char *value = *xattr_value; + int error; + + error = xattr_permission(inode, name, MAY_READ); + if (error) + return error; + + if (!inode->i_op->getxattr) + return -EOPNOTSUPP; + + error = inode->i_op->getxattr(dentry, name, NULL, 0); + if (error < 0) + return error; + + if (!value || (error > xattr_size)) { + value = krealloc(*xattr_value, error + 1, flags); + if (!value) + return -ENOMEM; + memset(value, 0, error + 1); + } + + error = inode->i_op->getxattr(dentry, name, value, error); + *xattr_value = value; + return error; +} + +/* Compare an extended attribute value with the given value */ +int vfs_xattr_cmp(struct dentry *dentry, const char *xattr_name, + const char *value, size_t size, gfp_t flags) +{ + char *xattr_value = NULL; + int rc; + + rc = vfs_getxattr_alloc(dentry, xattr_name, &xattr_value, 0, flags); + if (rc < 0) + return rc; + + if ((rc != size) || (memcmp(xattr_value, value, rc) != 0)) + rc = -EINVAL; + else + rc = 0; + kfree(xattr_value); + return rc; +} + ssize_t vfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size) { diff --git a/trunk/include/linux/xattr.h b/trunk/include/linux/xattr.h index 7a378662ddff..4703f6bd1f53 100644 --- a/trunk/include/linux/xattr.h +++ b/trunk/include/linux/xattr.h @@ -84,7 +84,10 @@ ssize_t generic_getxattr(struct dentry *dentry, const char *name, void *buffer, ssize_t generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size); int generic_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags); int generic_removexattr(struct dentry *dentry, const char *name); - +ssize_t vfs_getxattr_alloc(struct dentry *dentry, const char *name, + char **xattr_value, size_t size, gfp_t flags); +int vfs_xattr_cmp(struct dentry *dentry, const char *xattr_name, + const char *value, size_t size, gfp_t flags); #endif /* __KERNEL__ */ #endif /* _LINUX_XATTR_H */