xref: /openbmc/linux/fs/hfs/attr.c (revision 9a87ffc99ec8eb8d35eed7c4f816d75f5cc9662e)
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