Merge tag 'uniphier-fixes-v4.9' of git://git.kernel.org/pub/scm/linux/kernel/git...
[cascardo/linux.git] / 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 enum hfs_xattr_type {
17         HFS_TYPE,
18         HFS_CREATOR,
19 };
20
21 static int __hfs_setxattr(struct inode *inode, enum hfs_xattr_type type,
22                           const void *value, size_t size, int flags)
23 {
24         struct hfs_find_data fd;
25         hfs_cat_rec rec;
26         struct hfs_cat_file *file;
27         int res;
28
29         if (!S_ISREG(inode->i_mode) || HFS_IS_RSRC(inode))
30                 return -EOPNOTSUPP;
31
32         res = hfs_find_init(HFS_SB(inode->i_sb)->cat_tree, &fd);
33         if (res)
34                 return res;
35         fd.search_key->cat = HFS_I(inode)->cat_key;
36         res = hfs_brec_find(&fd);
37         if (res)
38                 goto out;
39         hfs_bnode_read(fd.bnode, &rec, fd.entryoffset,
40                         sizeof(struct hfs_cat_file));
41         file = &rec.file;
42
43         switch (type) {
44         case HFS_TYPE:
45                 if (size == 4)
46                         memcpy(&file->UsrWds.fdType, value, 4);
47                 else
48                         res = -ERANGE;
49                 break;
50
51         case HFS_CREATOR:
52                 if (size == 4)
53                         memcpy(&file->UsrWds.fdCreator, value, 4);
54                 else
55                         res = -ERANGE;
56                 break;
57         }
58
59         if (!res)
60                 hfs_bnode_write(fd.bnode, &rec, fd.entryoffset,
61                                 sizeof(struct hfs_cat_file));
62 out:
63         hfs_find_exit(&fd);
64         return res;
65 }
66
67 static ssize_t __hfs_getxattr(struct inode *inode, enum hfs_xattr_type type,
68                               void *value, size_t size)
69 {
70         struct hfs_find_data fd;
71         hfs_cat_rec rec;
72         struct hfs_cat_file *file;
73         ssize_t res = 0;
74
75         if (!S_ISREG(inode->i_mode) || HFS_IS_RSRC(inode))
76                 return -EOPNOTSUPP;
77
78         if (size) {
79                 res = hfs_find_init(HFS_SB(inode->i_sb)->cat_tree, &fd);
80                 if (res)
81                         return res;
82                 fd.search_key->cat = HFS_I(inode)->cat_key;
83                 res = hfs_brec_find(&fd);
84                 if (res)
85                         goto out;
86                 hfs_bnode_read(fd.bnode, &rec, fd.entryoffset,
87                                 sizeof(struct hfs_cat_file));
88         }
89         file = &rec.file;
90
91         switch (type) {
92         case HFS_TYPE:
93                 if (size >= 4) {
94                         memcpy(value, &file->UsrWds.fdType, 4);
95                         res = 4;
96                 } else
97                         res = size ? -ERANGE : 4;
98                 break;
99
100         case HFS_CREATOR:
101                 if (size >= 4) {
102                         memcpy(value, &file->UsrWds.fdCreator, 4);
103                         res = 4;
104                 } else
105                         res = size ? -ERANGE : 4;
106                 break;
107         }
108
109 out:
110         if (size)
111                 hfs_find_exit(&fd);
112         return res;
113 }
114
115 static int hfs_xattr_get(const struct xattr_handler *handler,
116                          struct dentry *unused, struct inode *inode,
117                          const char *name, void *value, size_t size)
118 {
119         return __hfs_getxattr(inode, handler->flags, value, size);
120 }
121
122 static int hfs_xattr_set(const struct xattr_handler *handler,
123                          struct dentry *unused, struct inode *inode,
124                          const char *name, const void *value, size_t size,
125                          int flags)
126 {
127         if (!value)
128                 return -EOPNOTSUPP;
129
130         return __hfs_setxattr(inode, handler->flags, value, size, flags);
131 }
132
133 static const struct xattr_handler hfs_creator_handler = {
134         .name = "hfs.creator",
135         .flags = HFS_CREATOR,
136         .get = hfs_xattr_get,
137         .set = hfs_xattr_set,
138 };
139
140 static const struct xattr_handler hfs_type_handler = {
141         .name = "hfs.type",
142         .flags = HFS_TYPE,
143         .get = hfs_xattr_get,
144         .set = hfs_xattr_set,
145 };
146
147 const struct xattr_handler *hfs_xattr_handlers[] = {
148         &hfs_creator_handler,
149         &hfs_type_handler,
150         NULL
151 };