]> git.proxmox.com Git - ceph.git/blob - ceph/src/common/xattr.c
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / common / xattr.c
1 /*
2 * Ceph - scalable distributed file system
3 *
4 * Copyright (C) 2011 Stanislav Sedov <stas@FreeBSD.org>
5 *
6 * This is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License version 2.1, as published by the Free Software
9 * Foundation. See file COPYING.
10 */
11
12 #if defined(__FreeBSD__)
13 #include <errno.h>
14 #include <stdint.h>
15 #include <stdlib.h>
16 #include <strings.h>
17 #include <sys/types.h>
18 #include <sys/extattr.h>
19 #elif defined(__linux__)
20 #include <sys/types.h>
21 #include <sys/xattr.h>
22 #elif defined(__APPLE__)
23 #include <errno.h>
24 #include <sys/xattr.h>
25 #else
26 #error "Your system is not supported!"
27 #endif
28
29 #include "common/xattr.h"
30
31 /*
32 * Sets extended attribute on a file.
33 * Returns 0 on success, -1 on failure.
34 */
35 int
36 ceph_os_setxattr(const char *path, const char *name,
37 const void *value, size_t size)
38 {
39 int error = -1;
40
41 #if defined(__FreeBSD__)
42 error = extattr_set_file(path, EXTATTR_NAMESPACE_USER, name, value,
43 size);
44 if (error > 0)
45 error = 0;
46 #elif defined(__linux__)
47 error = setxattr(path, name, value, size, 0);
48 #elif defined(__APPLE__)
49 error = setxattr(path, name, value, size, 0 /* position */, 0);
50 #endif
51
52 return (error);
53 }
54
55 int
56 ceph_os_fsetxattr(int fd, const char *name, const void *value,
57 size_t size)
58 {
59 int error = -1;
60
61 #if defined(__FreeBSD__)
62 error = extattr_set_fd(fd, EXTATTR_NAMESPACE_USER, name, value, size);
63 if (error > 0)
64 error = 0;
65 #elif defined(__linux__)
66 error = fsetxattr(fd, name, value, size, 0);
67 #elif defined(__APPLE__)
68 error = fsetxattr(fd, name, value, size, 0, 0 /* no options should be identical to Linux */ );
69 #endif
70
71 return (error);
72 }
73
74 ssize_t
75 ceph_os_getxattr(const char *path, const char *name,
76 void *value, size_t size)
77 {
78 ssize_t error = -1;
79
80 #if defined(__FreeBSD__)
81 if (value == NULL || size == 0) {
82 error = extattr_get_file(path, EXTATTR_NAMESPACE_USER, name, value,
83 size);
84 } else {
85 error = extattr_get_file(path, EXTATTR_NAMESPACE_USER, name, NULL,
86 0);
87 if (error > 0) {
88 if (error > size) {
89 errno = ERANGE;
90 error = -1;
91 } else {
92 error = extattr_get_file(path, EXTATTR_NAMESPACE_USER,
93 name, value, size);
94 }
95 }
96 }
97 #elif defined(__linux__)
98 error = getxattr(path, name, value, size);
99 #elif defined(__APPLE__)
100 error = getxattr(path, name, value, size, 0 /* position */, 0);
101 /* ENOATTR and ENODATA have different values */
102 if (error < 0 && errno == ENOATTR)
103 errno = ENODATA;
104 #endif
105
106 return (error);
107 }
108
109 ssize_t
110 ceph_os_fgetxattr(int fd, const char *name, void *value,
111 size_t size)
112 {
113 ssize_t error = -1;
114
115 #if defined(__FreeBSD__)
116 if (value == NULL || size == 0) {
117 error = extattr_get_fd(fd, EXTATTR_NAMESPACE_USER, name, value,
118 size);
119 } else {
120 error = extattr_get_fd(fd, EXTATTR_NAMESPACE_USER, name, NULL,
121 0);
122 if (error > 0) {
123 if (error > size) {
124 errno = ERANGE;
125 error = -1;
126 } else {
127 error = extattr_get_fd(fd, EXTATTR_NAMESPACE_USER,
128 name, value, size);
129 }
130 }
131 }
132 #elif defined(__linux__)
133 error = fgetxattr(fd, name, value, size);
134 #elif defined(__APPLE__)
135 error = fgetxattr(fd, name, value, size, 0, 0 /* no options */);
136 /* ENOATTR and ENODATA have different values */
137 if (error < 0 && errno == ENOATTR)
138 errno = ENODATA;
139 #endif
140
141 return (error);
142 }
143
144 ssize_t
145 ceph_os_listxattr(const char *path, char *list, size_t size)
146 {
147 ssize_t error = -1;
148
149 #if defined(__FreeBSD__)
150 /*
151 * XXX. The format of the list FreeBSD returns differs
152 * from the Linux ones. We have to perform the conversion. :-(
153 */
154 char *newlist, *p, *p1;
155
156 if (size != 0) {
157 newlist = malloc(size);
158 if (newlist != NULL) {
159 error = extattr_list_file(path, EXTATTR_NAMESPACE_USER,
160 newlist, size);
161 if (error > 0) {
162 p = newlist;
163 p1 = list;
164 while ((p - newlist) < error) {
165 uint8_t len = *(uint8_t *)p;
166 p++;
167 if ((p + len - newlist) > error)
168 break;
169 if (len > 0) {
170 bcopy(p, p1, len);
171 p += len;
172 p1 += len;
173 *p1++ = '\0';
174 }
175 }
176 error = p1 - list;
177 }
178 free(newlist);
179 }
180 } else {
181 error = extattr_list_file(path, EXTATTR_NAMESPACE_USER,
182 list, size);
183 }
184 #elif defined(__linux__)
185 error = listxattr(path, list, size);
186 #elif defined(__APPLE__)
187 error = listxattr(path, list, size, 0);
188 #endif
189
190 return (error);
191 }
192
193 ssize_t
194 ceph_os_flistxattr(int fd, char *list, size_t size)
195 {
196 ssize_t error = -1;
197
198 #if defined(__FreeBSD__)
199 /*
200 * XXX. The format of the list FreeBSD returns differs
201 * from the Linux ones. We have to perform the conversion. :-(
202 */
203 char *newlist, *p, *p1;
204
205 if (size != 0) {
206 newlist = malloc(size);
207 if (newlist != NULL) {
208 error = extattr_list_fd(fd, EXTATTR_NAMESPACE_USER,
209 newlist, size);
210 if (error > 0) {
211 p = newlist;
212 p1 = list;
213 while ((p - newlist) < error) {
214 uint8_t len = *(uint8_t *)p;
215 p++;
216 if ((p + len - newlist) > error)
217 break;
218 if (len > 0) {
219 bcopy(p, p1, len);
220 p += len;
221 p1 += len;
222 *p1++ = '\0';
223 }
224 }
225 error = p1 - list;
226 }
227 free(newlist);
228 }
229 } else {
230 error = extattr_list_fd(fd, EXTATTR_NAMESPACE_USER,
231 list, size);
232 }
233 #elif defined(__linux__)
234 error = flistxattr(fd, list, size);
235 #elif defined(__APPLE__)
236 error = flistxattr(fd, list, size, 0);
237 #endif
238
239 return (error);
240 }
241
242 int
243 ceph_os_removexattr(const char *path, const char *name)
244 {
245 int error = -1;
246
247 #if defined(__FreeBSD__)
248 error = extattr_delete_file(path, EXTATTR_NAMESPACE_USER, name);
249 #elif defined(__linux__)
250 error = removexattr(path, name);
251 #elif defined(__APPLE__)
252 error = removexattr(path, name, 0);
253 /* ENOATTR and ENODATA have different values */
254 if (error < 0 && errno == ENOATTR)
255 errno = ENODATA;
256 #endif
257
258 return (error);
259 }
260
261 int
262 ceph_os_fremovexattr(int fd, const char *name)
263 {
264 int error = -1;
265
266 #if defined(__FreeBSD__)
267 error = extattr_delete_fd(fd, EXTATTR_NAMESPACE_USER, name);
268 #elif defined(__linux__)
269 error = fremovexattr(fd, name);
270 #elif defined(__APPLE__)
271 error = fremovexattr(fd, name, 0);
272 /* ENOATTR and ENODATA have different values */
273 if (error < 0 && errno == ENOATTR)
274 errno = ENODATA;
275 #endif
276
277 return (error);
278 }