Merge branch 'tizen_qemu_2.0' into tizen
[sdk/emulator/qemu.git] / hw / 9pfs / virtio-9p-posix-acl.c
1 /*
2  * Virtio 9p system.posix* 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 <sys/types.h>
15 #include "qemu/xattr.h"
16 #include "hw/virtio/virtio.h"
17 #include "virtio-9p.h"
18 #include "fsdev/file-op-9p.h"
19 #include "virtio-9p-xattr.h"
20
21 #define MAP_ACL_ACCESS "user.virtfs.system.posix_acl_access"
22 #define MAP_ACL_DEFAULT "user.virtfs.system.posix_acl_default"
23 #define ACL_ACCESS "system.posix_acl_access"
24 #define ACL_DEFAULT "system.posix_acl_default"
25
26 static ssize_t mp_pacl_getxattr(FsContext *ctx, const char *path,
27                                 const char *name, void *value, size_t size)
28 {
29     char *buffer;
30     ssize_t ret;
31
32     buffer = rpath(ctx, path);
33 #ifdef CONFIG_LINUX
34     ret = lgetxattr(buffer, MAP_ACL_ACCESS, value, size);
35 #else
36     ret = getxattr(buffer, MAP_ACL_ACCESS, value, size, 0, XATTR_NOFOLLOW);
37 #endif
38     g_free(buffer);
39     return ret;
40 }
41
42 static ssize_t mp_pacl_listxattr(FsContext *ctx, const char *path,
43                                  char *name, void *value, size_t osize)
44 {
45     ssize_t len = sizeof(ACL_ACCESS);
46
47     if (!value) {
48         return len;
49     }
50
51     if (osize < len) {
52         errno = ERANGE;
53         return -1;
54     }
55
56     /* len includes the trailing NUL */
57     memcpy(value, ACL_ACCESS, len);
58     return 0;
59 }
60
61 static int mp_pacl_setxattr(FsContext *ctx, const char *path, const char *name,
62                             void *value, size_t size, int flags)
63 {
64     char *buffer;
65     int ret;
66
67     buffer = rpath(ctx, path);
68     ret = lsetxattr(buffer, MAP_ACL_ACCESS, value, size, flags);
69
70 #ifdef CONFIG_LINUX
71     ret = lsetxattr(buffer, MAP_ACL_ACCESS, value, size, flags);
72 #else
73     ret = setxattr(buffer, MAP_ACL_ACCESS, value, size, 0, flags | XATTR_NOFOLLOW);
74 #endif
75
76     g_free(buffer);
77     return ret;
78 }
79
80 static int mp_pacl_removexattr(FsContext *ctx,
81                                const char *path, const char *name)
82 {
83     int ret;
84     char *buffer;
85
86     buffer = rpath(ctx, path);
87
88 #ifdef CONFIG_LINUX
89     ret  = lremovexattr(buffer, MAP_ACL_ACCESS);
90 #else
91     ret  = removexattr(buffer, MAP_ACL_ACCESS, XATTR_NOFOLLOW);
92 #endif
93     if (ret == -1 && errno == ENODATA) {
94         /*
95          * We don't get ENODATA error when trying to remove a
96          * posix acl that is not present. So don't throw the error
97          * even in case of mapped security model
98          */
99         errno = 0;
100         ret = 0;
101     }
102     g_free(buffer);
103     return ret;
104 }
105
106 static ssize_t mp_dacl_getxattr(FsContext *ctx, const char *path,
107                                 const char *name, void *value, size_t size)
108 {
109     char *buffer;
110     ssize_t ret;
111
112     buffer = rpath(ctx, path);
113 #ifdef CONFIG_LINUX
114     ret = lgetxattr(buffer, MAP_ACL_DEFAULT, value, size);
115 #else
116     ret = getxattr(buffer, MAP_ACL_DEFAULT, value, size, 0, XATTR_NOFOLLOW);
117 #endif
118     g_free(buffer);
119     return ret;
120 }
121
122 static ssize_t mp_dacl_listxattr(FsContext *ctx, const char *path,
123                                  char *name, void *value, size_t osize)
124 {
125     ssize_t len = sizeof(ACL_DEFAULT);
126
127     if (!value) {
128         return len;
129     }
130
131     if (osize < len) {
132         errno = ERANGE;
133         return -1;
134     }
135
136     /* len includes the trailing NUL */
137     memcpy(value, ACL_ACCESS, len);
138     return 0;
139 }
140
141 static int mp_dacl_setxattr(FsContext *ctx, const char *path, const char *name,
142                             void *value, size_t size, int flags)
143 {
144     char *buffer;
145     int ret;
146
147     buffer = rpath(ctx, path);
148 #ifdef CONFIG_LINUX
149     return lsetxattr(buffer, MAP_ACL_DEFAULT, value,
150             size, flags);
151 #else
152     return setxattr(buffer, MAP_ACL_DEFAULT, value,
153             size, 0, flags | XATTR_NOFOLLOW);
154 #endif
155     g_free(buffer);
156     return ret;
157 }
158
159 static int mp_dacl_removexattr(FsContext *ctx,
160                                const char *path, const char *name)
161 {
162     int ret;
163     char *buffer;
164
165     buffer = rpath(ctx, path);
166 #ifdef CONFIG_LINUX
167     ret  = lremovexattr(buffer, MAP_ACL_DEFAULT);
168 #else
169     ret  = removexattr(buffer, MAP_ACL_DEFAULT, XATTR_NOFOLLOW);
170 #endif
171     if (ret == -1 && errno == ENODATA) {
172         /*
173          * We don't get ENODATA error when trying to remove a
174          * posix acl that is not present. So don't throw the error
175          * even in case of mapped security model
176          */
177         errno = 0;
178         ret = 0;
179     }
180     g_free(buffer);
181     return ret;
182 }
183
184
185 XattrOperations mapped_pacl_xattr = {
186     .name = "system.posix_acl_access",
187     .getxattr = mp_pacl_getxattr,
188     .setxattr = mp_pacl_setxattr,
189     .listxattr = mp_pacl_listxattr,
190     .removexattr = mp_pacl_removexattr,
191 };
192
193 XattrOperations mapped_dacl_xattr = {
194     .name = "system.posix_acl_default",
195     .getxattr = mp_dacl_getxattr,
196     .setxattr = mp_dacl_setxattr,
197     .listxattr = mp_dacl_listxattr,
198     .removexattr = mp_dacl_removexattr,
199 };
200
201 XattrOperations passthrough_acl_xattr = {
202     .name = "system.posix_acl_",
203     .getxattr = pt_getxattr,
204     .setxattr = pt_setxattr,
205     .listxattr = pt_listxattr,
206     .removexattr = pt_removexattr,
207 };
208
209 XattrOperations none_acl_xattr = {
210     .name = "system.posix_acl_",
211     .getxattr = notsup_getxattr,
212     .setxattr = notsup_setxattr,
213     .listxattr = notsup_listxattr,
214     .removexattr = notsup_removexattr,
215 };