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