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