]> Git Repo - qemu.git/blob - hw/9pfs/9p-xattr.c
9pfs: local: lgetxattr: don't follow symlinks
[qemu.git] / hw / 9pfs / 9p-xattr.c
1 /*
2  * 9p  xattr callback
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
14 #include "qemu/osdep.h"
15 #include "9p.h"
16 #include "fsdev/file-op-9p.h"
17 #include "9p-xattr.h"
18 #include "9p-util.h"
19 #include "9p-local.h"
20
21
22 static XattrOperations *get_xattr_operations(XattrOperations **h,
23                                              const char *name)
24 {
25     XattrOperations *xops;
26     for (xops = *(h)++; xops != NULL; xops = *(h)++) {
27         if (!strncmp(name, xops->name, strlen(xops->name))) {
28             return xops;
29         }
30     }
31     return NULL;
32 }
33
34 ssize_t v9fs_get_xattr(FsContext *ctx, const char *path,
35                        const char *name, void *value, size_t size)
36 {
37     XattrOperations *xops = get_xattr_operations(ctx->xops, name);
38     if (xops) {
39         return xops->getxattr(ctx, path, name, value, size);
40     }
41     errno = EOPNOTSUPP;
42     return -1;
43 }
44
45 ssize_t pt_listxattr(FsContext *ctx, const char *path,
46                      char *name, void *value, size_t size)
47 {
48     int name_size = strlen(name) + 1;
49     if (!value) {
50         return name_size;
51     }
52
53     if (size < name_size) {
54         errno = ERANGE;
55         return -1;
56     }
57
58     /* no need for strncpy: name_size is strlen(name)+1 */
59     memcpy(value, name, name_size);
60     return name_size;
61 }
62
63
64 /*
65  * Get the list and pass to each layer to find out whether
66  * to send the data or not
67  */
68 ssize_t v9fs_list_xattr(FsContext *ctx, const char *path,
69                         void *value, size_t vsize)
70 {
71     ssize_t size = 0;
72     char *buffer;
73     void *ovalue = value;
74     XattrOperations *xops;
75     char *orig_value, *orig_value_start;
76     ssize_t xattr_len, parsed_len = 0, attr_len;
77
78     /* Get the actual len */
79     buffer = rpath(ctx, path);
80     xattr_len = llistxattr(buffer, value, 0);
81     if (xattr_len <= 0) {
82         g_free(buffer);
83         return xattr_len;
84     }
85
86     /* Now fetch the xattr and find the actual size */
87     orig_value = g_malloc(xattr_len);
88     xattr_len = llistxattr(buffer, orig_value, xattr_len);
89     g_free(buffer);
90
91     /* store the orig pointer */
92     orig_value_start = orig_value;
93     while (xattr_len > parsed_len) {
94         xops = get_xattr_operations(ctx->xops, orig_value);
95         if (!xops) {
96             goto next_entry;
97         }
98
99         if (!value) {
100             size += xops->listxattr(ctx, path, orig_value, value, vsize);
101         } else {
102             size = xops->listxattr(ctx, path, orig_value, value, vsize);
103             if (size < 0) {
104                 goto err_out;
105             }
106             value += size;
107             vsize -= size;
108         }
109 next_entry:
110         /* Got the next entry */
111         attr_len = strlen(orig_value) + 1;
112         parsed_len += attr_len;
113         orig_value += attr_len;
114     }
115     if (value) {
116         size = value - ovalue;
117     }
118
119 err_out:
120     g_free(orig_value_start);
121     return size;
122 }
123
124 int v9fs_set_xattr(FsContext *ctx, const char *path, const char *name,
125                    void *value, size_t size, int flags)
126 {
127     XattrOperations *xops = get_xattr_operations(ctx->xops, name);
128     if (xops) {
129         return xops->setxattr(ctx, path, name, value, size, flags);
130     }
131     errno = EOPNOTSUPP;
132     return -1;
133
134 }
135
136 int v9fs_remove_xattr(FsContext *ctx,
137                       const char *path, const char *name)
138 {
139     XattrOperations *xops = get_xattr_operations(ctx->xops, name);
140     if (xops) {
141         return xops->removexattr(ctx, path, name);
142     }
143     errno = EOPNOTSUPP;
144     return -1;
145
146 }
147
148 ssize_t local_getxattr_nofollow(FsContext *ctx, const char *path,
149                                 const char *name, void *value, size_t size)
150 {
151     char *dirpath = g_path_get_dirname(path);
152     char *filename = g_path_get_basename(path);
153     int dirfd;
154     ssize_t ret = -1;
155
156     dirfd = local_opendir_nofollow(ctx, dirpath);
157     if (dirfd == -1) {
158         goto out;
159     }
160
161     ret = fgetxattrat_nofollow(dirfd, filename, name, value, size);
162     close_preserve_errno(dirfd);
163 out:
164     g_free(dirpath);
165     g_free(filename);
166     return ret;
167 }
168
169 ssize_t pt_getxattr(FsContext *ctx, const char *path, const char *name,
170                     void *value, size_t size)
171 {
172     return local_getxattr_nofollow(ctx, path, name, value, size);
173 }
174
175 int pt_setxattr(FsContext *ctx, const char *path, const char *name, void *value,
176                 size_t size, int flags)
177 {
178     char *buffer;
179     int ret;
180
181     buffer = rpath(ctx, path);
182     ret = lsetxattr(buffer, name, value, size, flags);
183     g_free(buffer);
184     return ret;
185 }
186
187 int pt_removexattr(FsContext *ctx, const char *path, const char *name)
188 {
189     char *buffer;
190     int ret;
191
192     buffer = rpath(ctx, path);
193     ret = lremovexattr(path, name);
194     g_free(buffer);
195     return ret;
196 }
197
198 ssize_t notsup_getxattr(FsContext *ctx, const char *path, const char *name,
199                         void *value, size_t size)
200 {
201     errno = ENOTSUP;
202     return -1;
203 }
204
205 int notsup_setxattr(FsContext *ctx, const char *path, const char *name,
206                     void *value, size_t size, int flags)
207 {
208     errno = ENOTSUP;
209     return -1;
210 }
211
212 ssize_t notsup_listxattr(FsContext *ctx, const char *path, char *name,
213                          void *value, size_t size)
214 {
215     return 0;
216 }
217
218 int notsup_removexattr(FsContext *ctx, const char *path, const char *name)
219 {
220     errno = ENOTSUP;
221     return -1;
222 }
223
224 XattrOperations *mapped_xattr_ops[] = {
225     &mapped_user_xattr,
226     &mapped_pacl_xattr,
227     &mapped_dacl_xattr,
228     NULL,
229 };
230
231 XattrOperations *passthrough_xattr_ops[] = {
232     &passthrough_user_xattr,
233     &passthrough_acl_xattr,
234     NULL,
235 };
236
237 /* for .user none model should be same as passthrough */
238 XattrOperations *none_xattr_ops[] = {
239     &passthrough_user_xattr,
240     &none_acl_xattr,
241     NULL,
242 };
This page took 0.036752 seconds and 4 git commands to generate.