xref: /qemu/hw/9pfs/9p-xattr.c (revision 56fc494b)
1267ae092SWei Liu /*
2267ae092SWei Liu  * 9p  xattr callback
3267ae092SWei Liu  *
4267ae092SWei Liu  * Copyright IBM, Corp. 2010
5267ae092SWei Liu  *
6267ae092SWei Liu  * Authors:
7267ae092SWei Liu  * Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
8267ae092SWei Liu  *
9267ae092SWei Liu  * This work is licensed under the terms of the GNU GPL, version 2.  See
10267ae092SWei Liu  * the COPYING file in the top-level directory.
11267ae092SWei Liu  *
12267ae092SWei Liu  */
13267ae092SWei Liu 
14fbc04127SPeter Maydell #include "qemu/osdep.h"
15ebe74f8bSWei Liu #include "9p.h"
16267ae092SWei Liu #include "fsdev/file-op-9p.h"
17267ae092SWei Liu #include "9p-xattr.h"
18267ae092SWei Liu 
19267ae092SWei Liu 
20267ae092SWei Liu static XattrOperations *get_xattr_operations(XattrOperations **h,
21267ae092SWei Liu                                              const char *name)
22267ae092SWei Liu {
23267ae092SWei Liu     XattrOperations *xops;
24267ae092SWei Liu     for (xops = *(h)++; xops != NULL; xops = *(h)++) {
25267ae092SWei Liu         if (!strncmp(name, xops->name, strlen(xops->name))) {
26267ae092SWei Liu             return xops;
27267ae092SWei Liu         }
28267ae092SWei Liu     }
29267ae092SWei Liu     return NULL;
30267ae092SWei Liu }
31267ae092SWei Liu 
32267ae092SWei Liu ssize_t v9fs_get_xattr(FsContext *ctx, const char *path,
33267ae092SWei Liu                        const char *name, void *value, size_t size)
34267ae092SWei Liu {
35267ae092SWei Liu     XattrOperations *xops = get_xattr_operations(ctx->xops, name);
36267ae092SWei Liu     if (xops) {
37267ae092SWei Liu         return xops->getxattr(ctx, path, name, value, size);
38267ae092SWei Liu     }
39267ae092SWei Liu     errno = EOPNOTSUPP;
40267ae092SWei Liu     return -1;
41267ae092SWei Liu }
42267ae092SWei Liu 
43267ae092SWei Liu ssize_t pt_listxattr(FsContext *ctx, const char *path,
44267ae092SWei Liu                      char *name, void *value, size_t size)
45267ae092SWei Liu {
46267ae092SWei Liu     int name_size = strlen(name) + 1;
47267ae092SWei Liu     if (!value) {
48267ae092SWei Liu         return name_size;
49267ae092SWei Liu     }
50267ae092SWei Liu 
51267ae092SWei Liu     if (size < name_size) {
52267ae092SWei Liu         errno = ERANGE;
53267ae092SWei Liu         return -1;
54267ae092SWei Liu     }
55267ae092SWei Liu 
56267ae092SWei Liu     /* no need for strncpy: name_size is strlen(name)+1 */
57267ae092SWei Liu     memcpy(value, name, name_size);
58267ae092SWei Liu     return name_size;
59267ae092SWei Liu }
60267ae092SWei Liu 
61267ae092SWei Liu 
62267ae092SWei Liu /*
63267ae092SWei Liu  * Get the list and pass to each layer to find out whether
64267ae092SWei Liu  * to send the data or not
65267ae092SWei Liu  */
66267ae092SWei Liu ssize_t v9fs_list_xattr(FsContext *ctx, const char *path,
67267ae092SWei Liu                         void *value, size_t vsize)
68267ae092SWei Liu {
69267ae092SWei Liu     ssize_t size = 0;
70267ae092SWei Liu     char *buffer;
71267ae092SWei Liu     void *ovalue = value;
72267ae092SWei Liu     XattrOperations *xops;
73267ae092SWei Liu     char *orig_value, *orig_value_start;
74267ae092SWei Liu     ssize_t xattr_len, parsed_len = 0, attr_len;
75267ae092SWei Liu 
76267ae092SWei Liu     /* Get the actual len */
77267ae092SWei Liu     buffer = rpath(ctx, path);
78267ae092SWei Liu     xattr_len = llistxattr(buffer, value, 0);
79267ae092SWei Liu     if (xattr_len <= 0) {
80267ae092SWei Liu         g_free(buffer);
81267ae092SWei Liu         return xattr_len;
82267ae092SWei Liu     }
83267ae092SWei Liu 
84267ae092SWei Liu     /* Now fetch the xattr and find the actual size */
85267ae092SWei Liu     orig_value = g_malloc(xattr_len);
86267ae092SWei Liu     xattr_len = llistxattr(buffer, orig_value, xattr_len);
87267ae092SWei Liu     g_free(buffer);
88267ae092SWei Liu 
89267ae092SWei Liu     /* store the orig pointer */
90267ae092SWei Liu     orig_value_start = orig_value;
91267ae092SWei Liu     while (xattr_len > parsed_len) {
92267ae092SWei Liu         xops = get_xattr_operations(ctx->xops, orig_value);
93267ae092SWei Liu         if (!xops) {
94267ae092SWei Liu             goto next_entry;
95267ae092SWei Liu         }
96267ae092SWei Liu 
97267ae092SWei Liu         if (!value) {
98267ae092SWei Liu             size += xops->listxattr(ctx, path, orig_value, value, vsize);
99267ae092SWei Liu         } else {
100267ae092SWei Liu             size = xops->listxattr(ctx, path, orig_value, value, vsize);
101267ae092SWei Liu             if (size < 0) {
102267ae092SWei Liu                 goto err_out;
103267ae092SWei Liu             }
104267ae092SWei Liu             value += size;
105267ae092SWei Liu             vsize -= size;
106267ae092SWei Liu         }
107267ae092SWei Liu next_entry:
108267ae092SWei Liu         /* Got the next entry */
109267ae092SWei Liu         attr_len = strlen(orig_value) + 1;
110267ae092SWei Liu         parsed_len += attr_len;
111267ae092SWei Liu         orig_value += attr_len;
112267ae092SWei Liu     }
113267ae092SWei Liu     if (value) {
114267ae092SWei Liu         size = value - ovalue;
115267ae092SWei Liu     }
116267ae092SWei Liu 
117267ae092SWei Liu err_out:
118267ae092SWei Liu     g_free(orig_value_start);
119267ae092SWei Liu     return size;
120267ae092SWei Liu }
121267ae092SWei Liu 
122267ae092SWei Liu int v9fs_set_xattr(FsContext *ctx, const char *path, const char *name,
123267ae092SWei Liu                    void *value, size_t size, int flags)
124267ae092SWei Liu {
125267ae092SWei Liu     XattrOperations *xops = get_xattr_operations(ctx->xops, name);
126267ae092SWei Liu     if (xops) {
127267ae092SWei Liu         return xops->setxattr(ctx, path, name, value, size, flags);
128267ae092SWei Liu     }
129267ae092SWei Liu     errno = EOPNOTSUPP;
130267ae092SWei Liu     return -1;
131267ae092SWei Liu 
132267ae092SWei Liu }
133267ae092SWei Liu 
134267ae092SWei Liu int v9fs_remove_xattr(FsContext *ctx,
135267ae092SWei Liu                       const char *path, const char *name)
136267ae092SWei Liu {
137267ae092SWei Liu     XattrOperations *xops = get_xattr_operations(ctx->xops, name);
138267ae092SWei Liu     if (xops) {
139267ae092SWei Liu         return xops->removexattr(ctx, path, name);
140267ae092SWei Liu     }
141267ae092SWei Liu     errno = EOPNOTSUPP;
142267ae092SWei Liu     return -1;
143267ae092SWei Liu 
144267ae092SWei Liu }
145267ae092SWei Liu 
146*56fc494bSGreg Kurz ssize_t pt_getxattr(FsContext *ctx, const char *path, const char *name,
147*56fc494bSGreg Kurz                     void *value, size_t size)
148*56fc494bSGreg Kurz {
149*56fc494bSGreg Kurz     char *buffer;
150*56fc494bSGreg Kurz     ssize_t ret;
151*56fc494bSGreg Kurz 
152*56fc494bSGreg Kurz     buffer = rpath(ctx, path);
153*56fc494bSGreg Kurz     ret = lgetxattr(buffer, name, value, size);
154*56fc494bSGreg Kurz     g_free(buffer);
155*56fc494bSGreg Kurz     return ret;
156*56fc494bSGreg Kurz }
157*56fc494bSGreg Kurz 
158*56fc494bSGreg Kurz int pt_setxattr(FsContext *ctx, const char *path, const char *name, void *value,
159*56fc494bSGreg Kurz                 size_t size, int flags)
160*56fc494bSGreg Kurz {
161*56fc494bSGreg Kurz     char *buffer;
162*56fc494bSGreg Kurz     int ret;
163*56fc494bSGreg Kurz 
164*56fc494bSGreg Kurz     buffer = rpath(ctx, path);
165*56fc494bSGreg Kurz     ret = lsetxattr(buffer, name, value, size, flags);
166*56fc494bSGreg Kurz     g_free(buffer);
167*56fc494bSGreg Kurz     return ret;
168*56fc494bSGreg Kurz }
169*56fc494bSGreg Kurz 
170*56fc494bSGreg Kurz int pt_removexattr(FsContext *ctx, const char *path, const char *name)
171*56fc494bSGreg Kurz {
172*56fc494bSGreg Kurz     char *buffer;
173*56fc494bSGreg Kurz     int ret;
174*56fc494bSGreg Kurz 
175*56fc494bSGreg Kurz     buffer = rpath(ctx, path);
176*56fc494bSGreg Kurz     ret = lremovexattr(path, name);
177*56fc494bSGreg Kurz     g_free(buffer);
178*56fc494bSGreg Kurz     return ret;
179*56fc494bSGreg Kurz }
180*56fc494bSGreg Kurz 
181*56fc494bSGreg Kurz ssize_t notsup_getxattr(FsContext *ctx, const char *path, const char *name,
182*56fc494bSGreg Kurz                         void *value, size_t size)
183*56fc494bSGreg Kurz {
184*56fc494bSGreg Kurz     errno = ENOTSUP;
185*56fc494bSGreg Kurz     return -1;
186*56fc494bSGreg Kurz }
187*56fc494bSGreg Kurz 
188*56fc494bSGreg Kurz int notsup_setxattr(FsContext *ctx, const char *path, const char *name,
189*56fc494bSGreg Kurz                     void *value, size_t size, int flags)
190*56fc494bSGreg Kurz {
191*56fc494bSGreg Kurz     errno = ENOTSUP;
192*56fc494bSGreg Kurz     return -1;
193*56fc494bSGreg Kurz }
194*56fc494bSGreg Kurz 
195*56fc494bSGreg Kurz ssize_t notsup_listxattr(FsContext *ctx, const char *path, char *name,
196*56fc494bSGreg Kurz                          void *value, size_t size)
197*56fc494bSGreg Kurz {
198*56fc494bSGreg Kurz     return 0;
199*56fc494bSGreg Kurz }
200*56fc494bSGreg Kurz 
201*56fc494bSGreg Kurz int notsup_removexattr(FsContext *ctx, const char *path, const char *name)
202*56fc494bSGreg Kurz {
203*56fc494bSGreg Kurz     errno = ENOTSUP;
204*56fc494bSGreg Kurz     return -1;
205*56fc494bSGreg Kurz }
206*56fc494bSGreg Kurz 
207267ae092SWei Liu XattrOperations *mapped_xattr_ops[] = {
208267ae092SWei Liu     &mapped_user_xattr,
209267ae092SWei Liu     &mapped_pacl_xattr,
210267ae092SWei Liu     &mapped_dacl_xattr,
211267ae092SWei Liu     NULL,
212267ae092SWei Liu };
213267ae092SWei Liu 
214267ae092SWei Liu XattrOperations *passthrough_xattr_ops[] = {
215267ae092SWei Liu     &passthrough_user_xattr,
216267ae092SWei Liu     &passthrough_acl_xattr,
217267ae092SWei Liu     NULL,
218267ae092SWei Liu };
219267ae092SWei Liu 
220267ae092SWei Liu /* for .user none model should be same as passthrough */
221267ae092SWei Liu XattrOperations *none_xattr_ops[] = {
222267ae092SWei Liu     &passthrough_user_xattr,
223267ae092SWei Liu     &none_acl_xattr,
224267ae092SWei Liu     NULL,
225267ae092SWei Liu };
226