]>
Commit | Line | Data |
---|---|---|
b2441318 | 1 | // SPDX-License-Identifier: GPL-2.0 |
1da177e4 LT |
2 | /* |
3 | * linux/fs/hfs/attr.c | |
4 | * | |
5 | * (C) 2003 Ardis Technologies <[email protected]> | |
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 | ||
b8020eff AG |
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) | |
1da177e4 | 24 | { |
1da177e4 LT |
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 | ||
b8020eff AG |
44 | switch (type) { |
45 | case HFS_TYPE: | |
1da177e4 LT |
46 | if (size == 4) |
47 | memcpy(&file->UsrWds.fdType, value, 4); | |
48 | else | |
49 | res = -ERANGE; | |
b8020eff AG |
50 | break; |
51 | ||
52 | case HFS_CREATOR: | |
1da177e4 LT |
53 | if (size == 4) |
54 | memcpy(&file->UsrWds.fdCreator, value, 4); | |
55 | else | |
56 | res = -ERANGE; | |
b8020eff AG |
57 | break; |
58 | } | |
59 | ||
1da177e4 LT |
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 | ||
b8020eff AG |
68 | static ssize_t __hfs_getxattr(struct inode *inode, enum hfs_xattr_type type, |
69 | void *value, size_t size) | |
1da177e4 | 70 | { |
1da177e4 LT |
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 | ||
b8020eff AG |
92 | switch (type) { |
93 | case HFS_TYPE: | |
1da177e4 LT |
94 | if (size >= 4) { |
95 | memcpy(value, &file->UsrWds.fdType, 4); | |
96 | res = 4; | |
97 | } else | |
98 | res = size ? -ERANGE : 4; | |
b8020eff AG |
99 | break; |
100 | ||
101 | case HFS_CREATOR: | |
1da177e4 LT |
102 | if (size >= 4) { |
103 | memcpy(value, &file->UsrWds.fdCreator, 4); | |
104 | res = 4; | |
105 | } else | |
106 | res = size ? -ERANGE : 4; | |
b8020eff AG |
107 | break; |
108 | } | |
109 | ||
1da177e4 LT |
110 | out: |
111 | if (size) | |
112 | hfs_find_exit(&fd); | |
113 | return res; | |
114 | } | |
115 | ||
b8020eff AG |
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) | |
1da177e4 | 119 | { |
b8020eff AG |
120 | return __hfs_getxattr(inode, handler->flags, value, size); |
121 | } | |
1da177e4 | 122 | |
b8020eff AG |
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) | |
1da177e4 LT |
129 | return -EOPNOTSUPP; |
130 | ||
b8020eff | 131 | return __hfs_setxattr(inode, handler->flags, value, size, flags); |
1da177e4 | 132 | } |
b8020eff AG |
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 | }; |