]>
Commit | Line | Data |
---|---|---|
fc22118d | 1 | /* |
267ae092 | 2 | * 9p xattr callback |
fc22118d AK |
3 | * |
4 | * Copyright IBM, Corp. 2010 | |
5 | * | |
6 | * Authors: | |
7 | * Aneesh Kumar K.V <[email protected]> | |
8 | * | |
9 | * This work is licensed under the terms of the GNU GPL, version 2. See | |
10 | * the COPYING file in the top-level directory. | |
11 | * | |
12 | */ | |
13 | ||
ebe74f8b | 14 | #include "9p.h" |
353ac78d | 15 | #include "fsdev/file-op-9p.h" |
267ae092 | 16 | #include "9p-xattr.h" |
fc22118d AK |
17 | |
18 | ||
19 | static XattrOperations *get_xattr_operations(XattrOperations **h, | |
20 | const char *name) | |
21 | { | |
22 | XattrOperations *xops; | |
23 | for (xops = *(h)++; xops != NULL; xops = *(h)++) { | |
24 | if (!strncmp(name, xops->name, strlen(xops->name))) { | |
25 | return xops; | |
26 | } | |
27 | } | |
28 | return NULL; | |
29 | } | |
30 | ||
31 | ssize_t v9fs_get_xattr(FsContext *ctx, const char *path, | |
32 | const char *name, void *value, size_t size) | |
33 | { | |
34 | XattrOperations *xops = get_xattr_operations(ctx->xops, name); | |
35 | if (xops) { | |
36 | return xops->getxattr(ctx, path, name, value, size); | |
37 | } | |
8af00205 | 38 | errno = EOPNOTSUPP; |
fc22118d AK |
39 | return -1; |
40 | } | |
41 | ||
42 | ssize_t pt_listxattr(FsContext *ctx, const char *path, | |
43 | char *name, void *value, size_t size) | |
44 | { | |
45 | int name_size = strlen(name) + 1; | |
46 | if (!value) { | |
47 | return name_size; | |
48 | } | |
49 | ||
50 | if (size < name_size) { | |
51 | errno = ERANGE; | |
52 | return -1; | |
53 | } | |
54 | ||
9238c209 JM |
55 | /* no need for strncpy: name_size is strlen(name)+1 */ |
56 | memcpy(value, name, name_size); | |
fc22118d AK |
57 | return name_size; |
58 | } | |
59 | ||
60 | ||
61 | /* | |
62 | * Get the list and pass to each layer to find out whether | |
63 | * to send the data or not | |
64 | */ | |
65 | ssize_t v9fs_list_xattr(FsContext *ctx, const char *path, | |
66 | void *value, size_t vsize) | |
67 | { | |
68 | ssize_t size = 0; | |
4fa4ce71 | 69 | char *buffer; |
fc22118d AK |
70 | void *ovalue = value; |
71 | XattrOperations *xops; | |
72 | char *orig_value, *orig_value_start; | |
73 | ssize_t xattr_len, parsed_len = 0, attr_len; | |
74 | ||
75 | /* Get the actual len */ | |
4fa4ce71 CG |
76 | buffer = rpath(ctx, path); |
77 | xattr_len = llistxattr(buffer, value, 0); | |
0562c674 | 78 | if (xattr_len <= 0) { |
4fa4ce71 | 79 | g_free(buffer); |
0562c674 KK |
80 | return xattr_len; |
81 | } | |
fc22118d AK |
82 | |
83 | /* Now fetch the xattr and find the actual size */ | |
7267c094 | 84 | orig_value = g_malloc(xattr_len); |
4fa4ce71 CG |
85 | xattr_len = llistxattr(buffer, orig_value, xattr_len); |
86 | g_free(buffer); | |
fc22118d AK |
87 | |
88 | /* store the orig pointer */ | |
89 | orig_value_start = orig_value; | |
90 | while (xattr_len > parsed_len) { | |
91 | xops = get_xattr_operations(ctx->xops, orig_value); | |
92 | if (!xops) { | |
93 | goto next_entry; | |
94 | } | |
95 | ||
96 | if (!value) { | |
97 | size += xops->listxattr(ctx, path, orig_value, value, vsize); | |
98 | } else { | |
99 | size = xops->listxattr(ctx, path, orig_value, value, vsize); | |
100 | if (size < 0) { | |
101 | goto err_out; | |
102 | } | |
103 | value += size; | |
104 | vsize -= size; | |
105 | } | |
106 | next_entry: | |
107 | /* Got the next entry */ | |
108 | attr_len = strlen(orig_value) + 1; | |
109 | parsed_len += attr_len; | |
110 | orig_value += attr_len; | |
111 | } | |
112 | if (value) { | |
113 | size = value - ovalue; | |
114 | } | |
115 | ||
116 | err_out: | |
7267c094 | 117 | g_free(orig_value_start); |
fc22118d AK |
118 | return size; |
119 | } | |
120 | ||
121 | int v9fs_set_xattr(FsContext *ctx, const char *path, const char *name, | |
122 | void *value, size_t size, int flags) | |
123 | { | |
124 | XattrOperations *xops = get_xattr_operations(ctx->xops, name); | |
125 | if (xops) { | |
126 | return xops->setxattr(ctx, path, name, value, size, flags); | |
127 | } | |
8af00205 | 128 | errno = EOPNOTSUPP; |
fc22118d AK |
129 | return -1; |
130 | ||
131 | } | |
132 | ||
133 | int v9fs_remove_xattr(FsContext *ctx, | |
134 | const char *path, const char *name) | |
135 | { | |
136 | XattrOperations *xops = get_xattr_operations(ctx->xops, name); | |
137 | if (xops) { | |
138 | return xops->removexattr(ctx, path, name); | |
139 | } | |
8af00205 | 140 | errno = EOPNOTSUPP; |
fc22118d AK |
141 | return -1; |
142 | ||
143 | } | |
144 | ||
145 | XattrOperations *mapped_xattr_ops[] = { | |
146 | &mapped_user_xattr, | |
70fc55eb AK |
147 | &mapped_pacl_xattr, |
148 | &mapped_dacl_xattr, | |
fc22118d AK |
149 | NULL, |
150 | }; | |
151 | ||
152 | XattrOperations *passthrough_xattr_ops[] = { | |
153 | &passthrough_user_xattr, | |
70fc55eb | 154 | &passthrough_acl_xattr, |
fc22118d AK |
155 | NULL, |
156 | }; | |
157 | ||
158 | /* for .user none model should be same as passthrough */ | |
159 | XattrOperations *none_xattr_ops[] = { | |
160 | &passthrough_user_xattr, | |
70fc55eb | 161 | &none_acl_xattr, |
fc22118d AK |
162 | NULL, |
163 | }; |