Merge branch 'upstream' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/misc-2.6
[linux-2.6] / fs / hfs / attr.c
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
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
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
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 }