1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * linux/fs/hfs/attr.c 4 * 5 * (C) 2003 Ardis Technologies <roman@ardistech.com> 6 * 7 * Export hfs data via xattr 8 */ 9 10 11 #include <linux/fs.h> 12 #include <linux/xattr.h> 13 14 #include "hfs_fs.h" 15 #include "btree.h" 16 17 enum hfs_xattr_type { 18 HFS_TYPE, 19 HFS_CREATOR, 20 }; 21 22 static int __hfs_setxattr(struct inode *inode, enum hfs_xattr_type type, 23 const void *value, size_t size, int flags) 24 { 25 struct hfs_find_data fd; 26 hfs_cat_rec rec; 27 struct hfs_cat_file *file; 28 int res; 29 30 if (!S_ISREG(inode->i_mode) || HFS_IS_RSRC(inode)) 31 return -EOPNOTSUPP; 32 33 res = hfs_find_init(HFS_SB(inode->i_sb)->cat_tree, &fd); 34 if (res) 35 return res; 36 fd.search_key->cat = HFS_I(inode)->cat_key; 37 res = hfs_brec_find(&fd); 38 if (res) 39 goto out; 40 hfs_bnode_read(fd.bnode, &rec, fd.entryoffset, 41 sizeof(struct hfs_cat_file)); 42 file = &rec.file; 43 44 switch (type) { 45 case HFS_TYPE: 46 if (size == 4) 47 memcpy(&file->UsrWds.fdType, value, 4); 48 else 49 res = -ERANGE; 50 break; 51 52 case HFS_CREATOR: 53 if (size == 4) 54 memcpy(&file->UsrWds.fdCreator, value, 4); 55 else 56 res = -ERANGE; 57 break; 58 } 59 60 if (!res) 61 hfs_bnode_write(fd.bnode, &rec, fd.entryoffset, 62 sizeof(struct hfs_cat_file)); 63 out: 64 hfs_find_exit(&fd); 65 return res; 66 } 67 68 static ssize_t __hfs_getxattr(struct inode *inode, enum hfs_xattr_type type, 69 void *value, size_t size) 70 { 71 struct hfs_find_data fd; 72 hfs_cat_rec rec; 73 struct hfs_cat_file *file; 74 ssize_t res = 0; 75 76 if (!S_ISREG(inode->i_mode) || HFS_IS_RSRC(inode)) 77 return -EOPNOTSUPP; 78 79 if (size) { 80 res = hfs_find_init(HFS_SB(inode->i_sb)->cat_tree, &fd); 81 if (res) 82 return res; 83 fd.search_key->cat = HFS_I(inode)->cat_key; 84 res = hfs_brec_find(&fd); 85 if (res) 86 goto out; 87 hfs_bnode_read(fd.bnode, &rec, fd.entryoffset, 88 sizeof(struct hfs_cat_file)); 89 } 90 file = &rec.file; 91 92 switch (type) { 93 case HFS_TYPE: 94 if (size >= 4) { 95 memcpy(value, &file->UsrWds.fdType, 4); 96 res = 4; 97 } else 98 res = size ? -ERANGE : 4; 99 break; 100 101 case HFS_CREATOR: 102 if (size >= 4) { 103 memcpy(value, &file->UsrWds.fdCreator, 4); 104 res = 4; 105 } else 106 res = size ? -ERANGE : 4; 107 break; 108 } 109 110 out: 111 if (size) 112 hfs_find_exit(&fd); 113 return res; 114 } 115 116 static int hfs_xattr_get(const struct xattr_handler *handler, 117 struct dentry *unused, struct inode *inode, 118 const char *name, void *value, size_t size) 119 { 120 return __hfs_getxattr(inode, handler->flags, value, size); 121 } 122 123 static int hfs_xattr_set(const struct xattr_handler *handler, 124 struct dentry *unused, struct inode *inode, 125 const char *name, const void *value, size_t size, 126 int flags) 127 { 128 if (!value) 129 return -EOPNOTSUPP; 130 131 return __hfs_setxattr(inode, handler->flags, value, size, flags); 132 } 133 134 static const struct xattr_handler hfs_creator_handler = { 135 .name = "hfs.creator", 136 .flags = HFS_CREATOR, 137 .get = hfs_xattr_get, 138 .set = hfs_xattr_set, 139 }; 140 141 static const struct xattr_handler hfs_type_handler = { 142 .name = "hfs.type", 143 .flags = HFS_TYPE, 144 .get = hfs_xattr_get, 145 .set = hfs_xattr_set, 146 }; 147 148 const struct xattr_handler *hfs_xattr_handlers[] = { 149 &hfs_creator_handler, 150 &hfs_type_handler, 151 NULL 152 }; 153