Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / 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 }