]>
Commit | Line | Data |
---|---|---|
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 | ||
14 | #include "hw/virtio.h" | |
15 | #include "virtio-9p.h" | |
16 | #include "fsdev/file-op-9p.h" | |
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 | } | |
39 | errno = -EOPNOTSUPP; | |
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 | ||
56 | strncpy(value, name, name_size); | |
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; | |
69 | char buffer[PATH_MAX]; | |
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 */ | |
76 | xattr_len = llistxattr(rpath(ctx, path, buffer), value, 0); | |
77 | if (xattr_len <= 0) { | |
78 | return xattr_len; | |
79 | } | |
80 | ||
81 | /* Now fetch the xattr and find the actual size */ | |
82 | orig_value = g_malloc(xattr_len); | |
83 | xattr_len = llistxattr(rpath(ctx, path, buffer), orig_value, xattr_len); | |
84 | ||
85 | /* store the orig pointer */ | |
86 | orig_value_start = orig_value; | |
87 | while (xattr_len > parsed_len) { | |
88 | xops = get_xattr_operations(ctx->xops, orig_value); | |
89 | if (!xops) { | |
90 | goto next_entry; | |
91 | } | |
92 | ||
93 | if (!value) { | |
94 | size += xops->listxattr(ctx, path, orig_value, value, vsize); | |
95 | } else { | |
96 | size = xops->listxattr(ctx, path, orig_value, value, vsize); | |
97 | if (size < 0) { | |
98 | goto err_out; | |
99 | } | |
100 | value += size; | |
101 | vsize -= size; | |
102 | } | |
103 | next_entry: | |
104 | /* Got the next entry */ | |
105 | attr_len = strlen(orig_value) + 1; | |
106 | parsed_len += attr_len; | |
107 | orig_value += attr_len; | |
108 | } | |
109 | if (value) { | |
110 | size = value - ovalue; | |
111 | } | |
112 | ||
113 | err_out: | |
114 | g_free(orig_value_start); | |
115 | return size; | |
116 | } | |
117 | ||
118 | int v9fs_set_xattr(FsContext *ctx, const char *path, const char *name, | |
119 | void *value, size_t size, int flags) | |
120 | { | |
121 | XattrOperations *xops = get_xattr_operations(ctx->xops, name); | |
122 | if (xops) { | |
123 | return xops->setxattr(ctx, path, name, value, size, flags); | |
124 | } | |
125 | errno = -EOPNOTSUPP; | |
126 | return -1; | |
127 | ||
128 | } | |
129 | ||
130 | int v9fs_remove_xattr(FsContext *ctx, | |
131 | const char *path, const char *name) | |
132 | { | |
133 | XattrOperations *xops = get_xattr_operations(ctx->xops, name); | |
134 | if (xops) { | |
135 | return xops->removexattr(ctx, path, name); | |
136 | } | |
137 | errno = -EOPNOTSUPP; | |
138 | return -1; | |
139 | ||
140 | } | |
141 | ||
142 | XattrOperations *mapped_xattr_ops[] = { | |
143 | &mapped_user_xattr, | |
144 | &mapped_pacl_xattr, | |
145 | &mapped_dacl_xattr, | |
146 | NULL, | |
147 | }; | |
148 | ||
149 | XattrOperations *passthrough_xattr_ops[] = { | |
150 | &passthrough_user_xattr, | |
151 | &passthrough_acl_xattr, | |
152 | NULL, | |
153 | }; | |
154 | ||
155 | /* for .user none model should be same as passthrough */ | |
156 | XattrOperations *none_xattr_ops[] = { | |
157 | &passthrough_user_xattr, | |
158 | &none_acl_xattr, | |
159 | NULL, | |
160 | }; |