1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds * linux/fs/hfs/attr.c
41da177e4SLinus Torvalds *
51da177e4SLinus Torvalds * (C) 2003 Ardis Technologies <roman@ardistech.com>
61da177e4SLinus Torvalds *
71da177e4SLinus Torvalds * Export hfs data via xattr
81da177e4SLinus Torvalds */
91da177e4SLinus Torvalds
101da177e4SLinus Torvalds
111da177e4SLinus Torvalds #include <linux/fs.h>
121da177e4SLinus Torvalds #include <linux/xattr.h>
131da177e4SLinus Torvalds
141da177e4SLinus Torvalds #include "hfs_fs.h"
151da177e4SLinus Torvalds #include "btree.h"
161da177e4SLinus Torvalds
17b8020effSAndreas Gruenbacher enum hfs_xattr_type {
18b8020effSAndreas Gruenbacher HFS_TYPE,
19b8020effSAndreas Gruenbacher HFS_CREATOR,
20b8020effSAndreas Gruenbacher };
21b8020effSAndreas Gruenbacher
__hfs_setxattr(struct inode * inode,enum hfs_xattr_type type,const void * value,size_t size,int flags)22b8020effSAndreas Gruenbacher static int __hfs_setxattr(struct inode *inode, enum hfs_xattr_type type,
23b8020effSAndreas Gruenbacher const void *value, size_t size, int flags)
241da177e4SLinus Torvalds {
251da177e4SLinus Torvalds struct hfs_find_data fd;
261da177e4SLinus Torvalds hfs_cat_rec rec;
271da177e4SLinus Torvalds struct hfs_cat_file *file;
281da177e4SLinus Torvalds int res;
291da177e4SLinus Torvalds
301da177e4SLinus Torvalds if (!S_ISREG(inode->i_mode) || HFS_IS_RSRC(inode))
311da177e4SLinus Torvalds return -EOPNOTSUPP;
321da177e4SLinus Torvalds
331da177e4SLinus Torvalds res = hfs_find_init(HFS_SB(inode->i_sb)->cat_tree, &fd);
341da177e4SLinus Torvalds if (res)
351da177e4SLinus Torvalds return res;
361da177e4SLinus Torvalds fd.search_key->cat = HFS_I(inode)->cat_key;
371da177e4SLinus Torvalds res = hfs_brec_find(&fd);
381da177e4SLinus Torvalds if (res)
391da177e4SLinus Torvalds goto out;
401da177e4SLinus Torvalds hfs_bnode_read(fd.bnode, &rec, fd.entryoffset,
411da177e4SLinus Torvalds sizeof(struct hfs_cat_file));
421da177e4SLinus Torvalds file = &rec.file;
431da177e4SLinus Torvalds
44b8020effSAndreas Gruenbacher switch (type) {
45b8020effSAndreas Gruenbacher case HFS_TYPE:
461da177e4SLinus Torvalds if (size == 4)
471da177e4SLinus Torvalds memcpy(&file->UsrWds.fdType, value, 4);
481da177e4SLinus Torvalds else
491da177e4SLinus Torvalds res = -ERANGE;
50b8020effSAndreas Gruenbacher break;
51b8020effSAndreas Gruenbacher
52b8020effSAndreas Gruenbacher case HFS_CREATOR:
531da177e4SLinus Torvalds if (size == 4)
541da177e4SLinus Torvalds memcpy(&file->UsrWds.fdCreator, value, 4);
551da177e4SLinus Torvalds else
561da177e4SLinus Torvalds res = -ERANGE;
57b8020effSAndreas Gruenbacher break;
58b8020effSAndreas Gruenbacher }
59b8020effSAndreas Gruenbacher
601da177e4SLinus Torvalds if (!res)
611da177e4SLinus Torvalds hfs_bnode_write(fd.bnode, &rec, fd.entryoffset,
621da177e4SLinus Torvalds sizeof(struct hfs_cat_file));
631da177e4SLinus Torvalds out:
641da177e4SLinus Torvalds hfs_find_exit(&fd);
651da177e4SLinus Torvalds return res;
661da177e4SLinus Torvalds }
671da177e4SLinus Torvalds
__hfs_getxattr(struct inode * inode,enum hfs_xattr_type type,void * value,size_t size)68b8020effSAndreas Gruenbacher static ssize_t __hfs_getxattr(struct inode *inode, enum hfs_xattr_type type,
69b8020effSAndreas Gruenbacher void *value, size_t size)
701da177e4SLinus Torvalds {
711da177e4SLinus Torvalds struct hfs_find_data fd;
721da177e4SLinus Torvalds hfs_cat_rec rec;
731da177e4SLinus Torvalds struct hfs_cat_file *file;
741da177e4SLinus Torvalds ssize_t res = 0;
751da177e4SLinus Torvalds
761da177e4SLinus Torvalds if (!S_ISREG(inode->i_mode) || HFS_IS_RSRC(inode))
771da177e4SLinus Torvalds return -EOPNOTSUPP;
781da177e4SLinus Torvalds
791da177e4SLinus Torvalds if (size) {
801da177e4SLinus Torvalds res = hfs_find_init(HFS_SB(inode->i_sb)->cat_tree, &fd);
811da177e4SLinus Torvalds if (res)
821da177e4SLinus Torvalds return res;
831da177e4SLinus Torvalds fd.search_key->cat = HFS_I(inode)->cat_key;
841da177e4SLinus Torvalds res = hfs_brec_find(&fd);
851da177e4SLinus Torvalds if (res)
861da177e4SLinus Torvalds goto out;
871da177e4SLinus Torvalds hfs_bnode_read(fd.bnode, &rec, fd.entryoffset,
881da177e4SLinus Torvalds sizeof(struct hfs_cat_file));
891da177e4SLinus Torvalds }
901da177e4SLinus Torvalds file = &rec.file;
911da177e4SLinus Torvalds
92b8020effSAndreas Gruenbacher switch (type) {
93b8020effSAndreas Gruenbacher case HFS_TYPE:
941da177e4SLinus Torvalds if (size >= 4) {
951da177e4SLinus Torvalds memcpy(value, &file->UsrWds.fdType, 4);
961da177e4SLinus Torvalds res = 4;
971da177e4SLinus Torvalds } else
981da177e4SLinus Torvalds res = size ? -ERANGE : 4;
99b8020effSAndreas Gruenbacher break;
100b8020effSAndreas Gruenbacher
101b8020effSAndreas Gruenbacher case HFS_CREATOR:
1021da177e4SLinus Torvalds if (size >= 4) {
1031da177e4SLinus Torvalds memcpy(value, &file->UsrWds.fdCreator, 4);
1041da177e4SLinus Torvalds res = 4;
1051da177e4SLinus Torvalds } else
1061da177e4SLinus Torvalds res = size ? -ERANGE : 4;
107b8020effSAndreas Gruenbacher break;
108b8020effSAndreas Gruenbacher }
109b8020effSAndreas Gruenbacher
1101da177e4SLinus Torvalds out:
1111da177e4SLinus Torvalds if (size)
1121da177e4SLinus Torvalds hfs_find_exit(&fd);
1131da177e4SLinus Torvalds return res;
1141da177e4SLinus Torvalds }
1151da177e4SLinus Torvalds
hfs_xattr_get(const struct xattr_handler * handler,struct dentry * unused,struct inode * inode,const char * name,void * value,size_t size)116b8020effSAndreas Gruenbacher static int hfs_xattr_get(const struct xattr_handler *handler,
117b8020effSAndreas Gruenbacher struct dentry *unused, struct inode *inode,
118b8020effSAndreas Gruenbacher const char *name, void *value, size_t size)
1191da177e4SLinus Torvalds {
120b8020effSAndreas Gruenbacher return __hfs_getxattr(inode, handler->flags, value, size);
121b8020effSAndreas Gruenbacher }
1221da177e4SLinus Torvalds
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)123b8020effSAndreas Gruenbacher static int hfs_xattr_set(const struct xattr_handler *handler,
124*39f60c1cSChristian Brauner struct mnt_idmap *idmap,
125b8020effSAndreas Gruenbacher struct dentry *unused, struct inode *inode,
126b8020effSAndreas Gruenbacher const char *name, const void *value, size_t size,
127b8020effSAndreas Gruenbacher int flags)
128b8020effSAndreas Gruenbacher {
129b8020effSAndreas Gruenbacher if (!value)
1301da177e4SLinus Torvalds return -EOPNOTSUPP;
1311da177e4SLinus Torvalds
132b8020effSAndreas Gruenbacher return __hfs_setxattr(inode, handler->flags, value, size, flags);
1331da177e4SLinus Torvalds }
134b8020effSAndreas Gruenbacher
135b8020effSAndreas Gruenbacher static const struct xattr_handler hfs_creator_handler = {
136b8020effSAndreas Gruenbacher .name = "hfs.creator",
137b8020effSAndreas Gruenbacher .flags = HFS_CREATOR,
138b8020effSAndreas Gruenbacher .get = hfs_xattr_get,
139b8020effSAndreas Gruenbacher .set = hfs_xattr_set,
140b8020effSAndreas Gruenbacher };
141b8020effSAndreas Gruenbacher
142b8020effSAndreas Gruenbacher static const struct xattr_handler hfs_type_handler = {
143b8020effSAndreas Gruenbacher .name = "hfs.type",
144b8020effSAndreas Gruenbacher .flags = HFS_TYPE,
145b8020effSAndreas Gruenbacher .get = hfs_xattr_get,
146b8020effSAndreas Gruenbacher .set = hfs_xattr_set,
147b8020effSAndreas Gruenbacher };
148b8020effSAndreas Gruenbacher
149b8020effSAndreas Gruenbacher const struct xattr_handler *hfs_xattr_handlers[] = {
150b8020effSAndreas Gruenbacher &hfs_creator_handler,
151b8020effSAndreas Gruenbacher &hfs_type_handler,
152b8020effSAndreas Gruenbacher NULL
153b8020effSAndreas Gruenbacher };
154