0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/fs.h>
0012 #include <linux/xattr.h>
0013
0014 #include "hfs_fs.h"
0015 #include "btree.h"
0016
0017 enum hfs_xattr_type {
0018 HFS_TYPE,
0019 HFS_CREATOR,
0020 };
0021
0022 static int __hfs_setxattr(struct inode *inode, enum hfs_xattr_type type,
0023 const void *value, size_t size, int flags)
0024 {
0025 struct hfs_find_data fd;
0026 hfs_cat_rec rec;
0027 struct hfs_cat_file *file;
0028 int res;
0029
0030 if (!S_ISREG(inode->i_mode) || HFS_IS_RSRC(inode))
0031 return -EOPNOTSUPP;
0032
0033 res = hfs_find_init(HFS_SB(inode->i_sb)->cat_tree, &fd);
0034 if (res)
0035 return res;
0036 fd.search_key->cat = HFS_I(inode)->cat_key;
0037 res = hfs_brec_find(&fd);
0038 if (res)
0039 goto out;
0040 hfs_bnode_read(fd.bnode, &rec, fd.entryoffset,
0041 sizeof(struct hfs_cat_file));
0042 file = &rec.file;
0043
0044 switch (type) {
0045 case HFS_TYPE:
0046 if (size == 4)
0047 memcpy(&file->UsrWds.fdType, value, 4);
0048 else
0049 res = -ERANGE;
0050 break;
0051
0052 case HFS_CREATOR:
0053 if (size == 4)
0054 memcpy(&file->UsrWds.fdCreator, value, 4);
0055 else
0056 res = -ERANGE;
0057 break;
0058 }
0059
0060 if (!res)
0061 hfs_bnode_write(fd.bnode, &rec, fd.entryoffset,
0062 sizeof(struct hfs_cat_file));
0063 out:
0064 hfs_find_exit(&fd);
0065 return res;
0066 }
0067
0068 static ssize_t __hfs_getxattr(struct inode *inode, enum hfs_xattr_type type,
0069 void *value, size_t size)
0070 {
0071 struct hfs_find_data fd;
0072 hfs_cat_rec rec;
0073 struct hfs_cat_file *file;
0074 ssize_t res = 0;
0075
0076 if (!S_ISREG(inode->i_mode) || HFS_IS_RSRC(inode))
0077 return -EOPNOTSUPP;
0078
0079 if (size) {
0080 res = hfs_find_init(HFS_SB(inode->i_sb)->cat_tree, &fd);
0081 if (res)
0082 return res;
0083 fd.search_key->cat = HFS_I(inode)->cat_key;
0084 res = hfs_brec_find(&fd);
0085 if (res)
0086 goto out;
0087 hfs_bnode_read(fd.bnode, &rec, fd.entryoffset,
0088 sizeof(struct hfs_cat_file));
0089 }
0090 file = &rec.file;
0091
0092 switch (type) {
0093 case HFS_TYPE:
0094 if (size >= 4) {
0095 memcpy(value, &file->UsrWds.fdType, 4);
0096 res = 4;
0097 } else
0098 res = size ? -ERANGE : 4;
0099 break;
0100
0101 case HFS_CREATOR:
0102 if (size >= 4) {
0103 memcpy(value, &file->UsrWds.fdCreator, 4);
0104 res = 4;
0105 } else
0106 res = size ? -ERANGE : 4;
0107 break;
0108 }
0109
0110 out:
0111 if (size)
0112 hfs_find_exit(&fd);
0113 return res;
0114 }
0115
0116 static int hfs_xattr_get(const struct xattr_handler *handler,
0117 struct dentry *unused, struct inode *inode,
0118 const char *name, void *value, size_t size)
0119 {
0120 return __hfs_getxattr(inode, handler->flags, value, size);
0121 }
0122
0123 static int hfs_xattr_set(const struct xattr_handler *handler,
0124 struct user_namespace *mnt_userns,
0125 struct dentry *unused, struct inode *inode,
0126 const char *name, const void *value, size_t size,
0127 int flags)
0128 {
0129 if (!value)
0130 return -EOPNOTSUPP;
0131
0132 return __hfs_setxattr(inode, handler->flags, value, size, flags);
0133 }
0134
0135 static const struct xattr_handler hfs_creator_handler = {
0136 .name = "hfs.creator",
0137 .flags = HFS_CREATOR,
0138 .get = hfs_xattr_get,
0139 .set = hfs_xattr_set,
0140 };
0141
0142 static const struct xattr_handler hfs_type_handler = {
0143 .name = "hfs.type",
0144 .flags = HFS_TYPE,
0145 .get = hfs_xattr_get,
0146 .set = hfs_xattr_set,
0147 };
0148
0149 const struct xattr_handler *hfs_xattr_handlers[] = {
0150 &hfs_creator_handler,
0151 &hfs_type_handler,
0152 NULL
0153 };