1 /*
2  *  linux/fs/hfs/attr.c
3  *
4  * (C) 2003 Ardis Technologies <roman@ardistech.com>
5  *
6  * Export hfs data via xattr
7  */
8 
9 
10 #include <linux/fs.h>
11 #include <linux/xattr.h>
12 
13 #include "hfs_fs.h"
14 #include "btree.h"
15 
hfs_setxattr(struct dentry * dentry,const char * name,const void * value,size_t size,int flags)16 int hfs_setxattr(struct dentry *dentry, const char *name,
17 		 const void *value, size_t size, int flags)
18 {
19 	struct inode *inode = dentry->d_inode;
20 	struct hfs_find_data fd;
21 	hfs_cat_rec rec;
22 	struct hfs_cat_file *file;
23 	int res;
24 
25 	if (!S_ISREG(inode->i_mode) || HFS_IS_RSRC(inode))
26 		return -EOPNOTSUPP;
27 
28 	res = hfs_find_init(HFS_SB(inode->i_sb)->cat_tree, &fd);
29 	if (res)
30 		return res;
31 	fd.search_key->cat = HFS_I(inode)->cat_key;
32 	res = hfs_brec_find(&fd);
33 	if (res)
34 		goto out;
35 	hfs_bnode_read(fd.bnode, &rec, fd.entryoffset,
36 			sizeof(struct hfs_cat_file));
37 	file = &rec.file;
38 
39 	if (!strcmp(name, "hfs.type")) {
40 		if (size == 4)
41 			memcpy(&file->UsrWds.fdType, value, 4);
42 		else
43 			res = -ERANGE;
44 	} else if (!strcmp(name, "hfs.creator")) {
45 		if (size == 4)
46 			memcpy(&file->UsrWds.fdCreator, value, 4);
47 		else
48 			res = -ERANGE;
49 	} else
50 		res = -EOPNOTSUPP;
51 	if (!res)
52 		hfs_bnode_write(fd.bnode, &rec, fd.entryoffset,
53 				sizeof(struct hfs_cat_file));
54 out:
55 	hfs_find_exit(&fd);
56 	return res;
57 }
58 
hfs_getxattr(struct dentry * dentry,const char * name,void * value,size_t size)59 ssize_t hfs_getxattr(struct dentry *dentry, const char *name,
60 			 void *value, size_t size)
61 {
62 	struct inode *inode = dentry->d_inode;
63 	struct hfs_find_data fd;
64 	hfs_cat_rec rec;
65 	struct hfs_cat_file *file;
66 	ssize_t res = 0;
67 
68 	if (!S_ISREG(inode->i_mode) || HFS_IS_RSRC(inode))
69 		return -EOPNOTSUPP;
70 
71 	if (size) {
72 		res = hfs_find_init(HFS_SB(inode->i_sb)->cat_tree, &fd);
73 		if (res)
74 			return res;
75 		fd.search_key->cat = HFS_I(inode)->cat_key;
76 		res = hfs_brec_find(&fd);
77 		if (res)
78 			goto out;
79 		hfs_bnode_read(fd.bnode, &rec, fd.entryoffset,
80 				sizeof(struct hfs_cat_file));
81 	}
82 	file = &rec.file;
83 
84 	if (!strcmp(name, "hfs.type")) {
85 		if (size >= 4) {
86 			memcpy(value, &file->UsrWds.fdType, 4);
87 			res = 4;
88 		} else
89 			res = size ? -ERANGE : 4;
90 	} else if (!strcmp(name, "hfs.creator")) {
91 		if (size >= 4) {
92 			memcpy(value, &file->UsrWds.fdCreator, 4);
93 			res = 4;
94 		} else
95 			res = size ? -ERANGE : 4;
96 	} else
97 		res = -ENODATA;
98 out:
99 	if (size)
100 		hfs_find_exit(&fd);
101 	return res;
102 }
103 
104 #define HFS_ATTRLIST_SIZE (sizeof("hfs.creator")+sizeof("hfs.type"))
105 
hfs_listxattr(struct dentry * dentry,char * buffer,size_t size)106 ssize_t hfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
107 {
108 	struct inode *inode = dentry->d_inode;
109 
110 	if (!S_ISREG(inode->i_mode) || HFS_IS_RSRC(inode))
111 		return -EOPNOTSUPP;
112 
113 	if (!buffer || !size)
114 		return HFS_ATTRLIST_SIZE;
115 	if (size < HFS_ATTRLIST_SIZE)
116 		return -ERANGE;
117 	strcpy(buffer, "hfs.type");
118 	strcpy(buffer + sizeof("hfs.type"), "hfs.creator");
119 
120 	return HFS_ATTRLIST_SIZE;
121 }
122