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