nsswitch/winbind_nss_aix: reimplement fetching the SID of a user
[Samba.git] / lib / replace / xattr.c
blob2420ee1f808f959b1338449d83f888b0d0004f83
1 /*
2 Unix SMB/CIFS implementation.
3 replacement routines for xattr implementations
4 Copyright (C) Jeremy Allison 1998-2005
5 Copyright (C) Timur Bakeyev 2005
6 Copyright (C) Bjoern Jacke 2006-2007
7 Copyright (C) Herb Lewis 2003
8 Copyright (C) Andrew Bartlett 2012
10 ** NOTE! The following LGPL license applies to the replace
11 ** library. This does NOT imply that all of Samba is released
12 ** under the LGPL
14 This library is free software; you can redistribute it and/or
15 modify it under the terms of the GNU Lesser General Public
16 License as published by the Free Software Foundation; either
17 version 3 of the License, or (at your option) any later version.
19 This library is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 Lesser General Public License for more details.
24 You should have received a copy of the GNU Lesser General Public
25 License along with this library; if not, see <http://www.gnu.org/licenses/>.
28 #define UID_WRAPPER_NOT_REPLACE
29 #include "replace.h"
30 #include "system/filesys.h"
31 #include "system/dir.h"
33 /******** Solaris EA helper function prototypes ********/
34 #ifdef HAVE_ATTROPEN
35 #define SOLARIS_ATTRMODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP
36 static int solaris_write_xattr(int attrfd, const char *value, size_t size);
37 static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size);
38 static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size);
39 static int solaris_unlinkat(int attrdirfd, const char *name);
40 static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode);
41 static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode);
42 #endif
44 /**************************************************************************
45 Wrappers for extented attribute calls. Based on the Linux package with
46 support for IRIX and (Net|Free)BSD also. Expand as other systems have them.
47 ****************************************************************************/
49 ssize_t rep_getxattr (const char *path, const char *name, void *value, size_t size)
51 #if defined(HAVE_XATTR_XATTR)
52 #ifndef XATTR_ADDITIONAL_OPTIONS
53 return getxattr(path, name, value, size);
54 #else
56 /* So that we do not recursivly call this function */
57 #undef getxattr
58 int options = 0;
59 return getxattr(path, name, value, size, 0, options);
60 #endif
61 #elif defined(HAVE_XATTR_EA)
62 return getea(path, name, value, size);
63 #elif defined(HAVE_XATTR_EXTATTR)
64 ssize_t retval;
65 int attrnamespace;
66 const char *attrname;
68 if (strncmp(name, "system.", 7) == 0) {
69 attrnamespace = EXTATTR_NAMESPACE_SYSTEM;
70 attrname = name + 7;
71 } else if (strncmp(name, "user.", 5) == 0) {
72 attrnamespace = EXTATTR_NAMESPACE_USER;
73 attrname = name + 5;
74 } else {
75 errno = EINVAL;
76 return -1;
80 * The BSD implementation has a nasty habit of silently truncating
81 * the returned value to the size of the buffer, so we have to check
82 * that the buffer is large enough to fit the returned value.
84 if((retval=extattr_get_file(path, attrnamespace, attrname, NULL, 0)) >= 0) {
85 if (size == 0) {
86 return retval;
87 } else if (retval > size) {
88 errno = ERANGE;
89 return -1;
91 if((retval=extattr_get_file(path, attrnamespace, attrname, value, size)) >= 0)
92 return retval;
95 return -1;
96 #elif defined(HAVE_XATTR_ATTR)
97 int retval, flags = 0;
98 int valuelength = (int)size;
99 char *attrname = strchr(name,'.') + 1;
101 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
103 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
104 if (size == 0 && retval == -1 && errno == E2BIG) {
105 return valuelength;
108 return retval ? retval : valuelength;
109 #elif defined(HAVE_ATTROPEN)
110 ssize_t ret = -1;
111 int attrfd = solaris_attropen(path, name, O_RDONLY, 0);
112 if (attrfd >= 0) {
113 ret = solaris_read_xattr(attrfd, value, size);
114 close(attrfd);
116 return ret;
117 #else
118 errno = ENOSYS;
119 return -1;
120 #endif
123 ssize_t rep_fgetxattr (int filedes, const char *name, void *value, size_t size)
125 #if defined(HAVE_XATTR_XATTR)
126 #ifndef XATTR_ADDITIONAL_OPTIONS
127 return fgetxattr(filedes, name, value, size);
128 #else
130 /* So that we do not recursivly call this function */
131 #undef fgetxattr
132 int options = 0;
133 return fgetxattr(filedes, name, value, size, 0, options);
134 #endif
135 #elif defined(HAVE_XATTR_EA)
136 return fgetea(filedes, name, value, size);
137 #elif defined(HAVE_XATTR_EXTATTR)
138 ssize_t retval;
139 int attrnamespace;
140 const char *attrname;
142 if (strncmp(name, "system.", 7) == 0) {
143 attrnamespace = EXTATTR_NAMESPACE_SYSTEM;
144 attrname = name + 7;
145 } else if (strncmp(name, "user.", 5) == 0) {
146 attrnamespace = EXTATTR_NAMESPACE_USER;
147 attrname = name + 5;
148 } else {
149 errno = EINVAL;
150 return -1;
153 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0)) >= 0) {
154 if (size == 0) {
155 return retval;
156 } else if (retval > size) {
157 errno = ERANGE;
158 return -1;
160 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, value, size)) >= 0)
161 return retval;
164 return -1;
165 #elif defined(HAVE_XATTR_ATTR)
166 int retval, flags = 0;
167 int valuelength = (int)size;
168 char *attrname = strchr(name,'.') + 1;
170 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
172 retval = attr_getf(filedes, attrname, (char *)value, &valuelength, flags);
173 if (size == 0 && retval == -1 && errno == E2BIG) {
174 return valuelength;
176 return retval ? retval : valuelength;
177 #elif defined(HAVE_ATTROPEN)
178 ssize_t ret = -1;
179 int attrfd = solaris_openat(filedes, name, O_RDONLY|O_XATTR, 0);
180 if (attrfd >= 0) {
181 ret = solaris_read_xattr(attrfd, value, size);
182 close(attrfd);
184 return ret;
185 #else
186 errno = ENOSYS;
187 return -1;
188 #endif
191 #if defined(HAVE_XATTR_EXTATTR)
193 #define EXTATTR_PREFIX(s) (s), (sizeof((s))-1)
195 static struct {
196 int space;
197 const char *name;
198 size_t len;
200 extattr[] = {
201 { EXTATTR_NAMESPACE_SYSTEM, EXTATTR_PREFIX("system.") },
202 { EXTATTR_NAMESPACE_USER, EXTATTR_PREFIX("user.") },
205 typedef union {
206 const char *path;
207 int filedes;
208 } extattr_arg;
210 static ssize_t bsd_attr_list (int type, extattr_arg arg, char *list, size_t size)
212 ssize_t list_size, total_size = 0;
213 int i, t, len;
214 char *buf;
215 /* Iterate through extattr(2) namespaces */
216 for(t = 0; t < ARRAY_SIZE(extattr); t++) {
217 if (t != EXTATTR_NAMESPACE_USER && geteuid() != 0) {
218 /* ignore all but user namespace when we are not root, see bug 10247 */
219 continue;
221 switch(type) {
222 case 0:
223 list_size = extattr_list_file(arg.path, extattr[t].space, list, size);
224 break;
225 case 1:
226 list_size = extattr_list_link(arg.path, extattr[t].space, list, size);
227 break;
228 case 2:
229 list_size = extattr_list_fd(arg.filedes, extattr[t].space, list, size);
230 break;
231 default:
232 errno = ENOSYS;
233 return -1;
235 /* Some error happend. Errno should be set by the previous call */
236 if(list_size < 0)
237 return -1;
238 /* No attributes */
239 if(list_size == 0)
240 continue;
241 /* XXX: Call with an empty buffer may be used to calculate
242 necessary buffer size. Unfortunately, we can't say, how
243 many attributes were returned, so here is the potential
244 problem with the emulation.
246 if(list == NULL) {
247 /* Take the worse case of one char attribute names -
248 two bytes per name plus one more for sanity.
250 total_size += list_size + (list_size/2 + 1)*extattr[t].len;
251 continue;
253 /* Count necessary offset to fit namespace prefixes */
254 len = 0;
255 for(i = 0; i < list_size; i += list[i] + 1)
256 len += extattr[t].len;
258 total_size += list_size + len;
259 /* Buffer is too small to fit the results */
260 if(total_size > size) {
261 errno = ERANGE;
262 return -1;
264 /* Shift results back, so we can prepend prefixes */
265 buf = (char *)memmove(list + len, list, list_size);
267 for(i = 0; i < list_size; i += len + 1) {
268 len = buf[i];
269 strncpy(list, extattr[t].name, extattr[t].len + 1);
270 list += extattr[t].len;
271 strncpy(list, buf + i + 1, len);
272 list[len] = '\0';
273 list += len + 1;
275 size -= total_size;
277 return total_size;
280 #endif
282 #if defined(HAVE_XATTR_ATTR) && (defined(HAVE_SYS_ATTRIBUTES_H) || defined(HAVE_ATTR_ATTRIBUTES_H))
283 static char attr_buffer[ATTR_MAX_VALUELEN];
285 static ssize_t irix_attr_list(const char *path, int filedes, char *list, size_t size, int flags)
287 int retval = 0, index;
288 attrlist_cursor_t *cursor = 0;
289 int total_size = 0;
290 attrlist_t * al = (attrlist_t *)attr_buffer;
291 attrlist_ent_t *ae;
292 size_t ent_size, left = size;
293 char *bp = list;
295 while (true) {
296 if (filedes)
297 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
298 else
299 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
300 if (retval) break;
301 for (index = 0; index < al->al_count; index++) {
302 ae = ATTR_ENTRY(attr_buffer, index);
303 ent_size = strlen(ae->a_name) + sizeof("user.");
304 if (left >= ent_size) {
305 strncpy(bp, "user.", sizeof("user."));
306 strncat(bp, ae->a_name, ent_size - sizeof("user."));
307 bp += ent_size;
308 left -= ent_size;
309 } else if (size) {
310 errno = ERANGE;
311 retval = -1;
312 break;
314 total_size += ent_size;
316 if (al->al_more == 0) break;
318 if (retval == 0) {
319 flags |= ATTR_ROOT;
320 cursor = 0;
321 while (true) {
322 if (filedes)
323 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
324 else
325 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
326 if (retval) break;
327 for (index = 0; index < al->al_count; index++) {
328 ae = ATTR_ENTRY(attr_buffer, index);
329 ent_size = strlen(ae->a_name) + sizeof("system.");
330 if (left >= ent_size) {
331 strncpy(bp, "system.", sizeof("system."));
332 strncat(bp, ae->a_name, ent_size - sizeof("system."));
333 bp += ent_size;
334 left -= ent_size;
335 } else if (size) {
336 errno = ERANGE;
337 retval = -1;
338 break;
340 total_size += ent_size;
342 if (al->al_more == 0) break;
345 return (ssize_t)(retval ? retval : total_size);
348 #endif
350 ssize_t rep_listxattr (const char *path, char *list, size_t size)
352 #if defined(HAVE_XATTR_XATTR)
353 #ifndef XATTR_ADDITIONAL_OPTIONS
354 return listxattr(path, list, size);
355 #else
356 /* So that we do not recursivly call this function */
357 #undef listxattr
358 int options = 0;
359 return listxattr(path, list, size, options);
360 #endif
361 #elif defined(HAVE_XATTR_EA)
362 return listea(path, list, size);
363 #elif defined(HAVE_XATTR_EXTATTR)
364 extattr_arg arg;
365 arg.path = path;
366 return bsd_attr_list(0, arg, list, size);
367 #elif defined(HAVE_XATTR_ATTR) && defined(HAVE_SYS_ATTRIBUTES_H)
368 return irix_attr_list(path, 0, list, size, 0);
369 #elif defined(HAVE_ATTROPEN)
370 ssize_t ret = -1;
371 int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
372 if (attrdirfd >= 0) {
373 ret = solaris_list_xattr(attrdirfd, list, size);
374 close(attrdirfd);
376 return ret;
377 #else
378 errno = ENOSYS;
379 return -1;
380 #endif
383 ssize_t rep_flistxattr (int filedes, char *list, size_t size)
385 #if defined(HAVE_XATTR_XATTR)
386 #ifndef XATTR_ADDITIONAL_OPTIONS
387 return flistxattr(filedes, list, size);
388 #else
389 /* So that we do not recursivly call this function */
390 #undef flistxattr
391 int options = 0;
392 return flistxattr(filedes, list, size, options);
393 #endif
394 #elif defined(HAVE_XATTR_EA)
395 return flistea(filedes, list, size);
396 #elif defined(HAVE_XATTR_EXTATTR)
397 extattr_arg arg;
398 arg.filedes = filedes;
399 return bsd_attr_list(2, arg, list, size);
400 #elif defined(HAVE_XATTR_ATTR)
401 return irix_attr_list(NULL, filedes, list, size, 0);
402 #elif defined(HAVE_ATTROPEN)
403 ssize_t ret = -1;
404 int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
405 if (attrdirfd >= 0) {
406 ret = solaris_list_xattr(attrdirfd, list, size);
407 close(attrdirfd);
409 return ret;
410 #else
411 errno = ENOSYS;
412 return -1;
413 #endif
416 int rep_removexattr (const char *path, const char *name)
418 #if defined(HAVE_XATTR_XATTR)
419 #ifndef XATTR_ADDITIONAL_OPTIONS
420 return removexattr(path, name);
421 #else
422 /* So that we do not recursivly call this function */
423 #undef removexattr
424 int options = 0;
425 return removexattr(path, name, options);
426 #endif
427 #elif defined(HAVE_XATTR_EA)
428 return removeea(path, name);
429 #elif defined(HAVE_XATTR_EXTATTR)
430 int attrnamespace;
431 const char *attrname;
433 if (strncmp(name, "system.", 7) == 0) {
434 attrnamespace = EXTATTR_NAMESPACE_SYSTEM;
435 attrname = name + 7;
436 } else if (strncmp(name, "user.", 5) == 0) {
437 attrnamespace = EXTATTR_NAMESPACE_USER;
438 attrname = name + 5;
439 } else {
440 errno = EINVAL;
441 return -1;
444 return extattr_delete_file(path, attrnamespace, attrname);
445 #elif defined(HAVE_XATTR_ATTR)
446 int flags = 0;
447 char *attrname = strchr(name,'.') + 1;
449 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
451 return attr_remove(path, attrname, flags);
452 #elif defined(HAVE_ATTROPEN)
453 int ret = -1;
454 int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
455 if (attrdirfd >= 0) {
456 ret = solaris_unlinkat(attrdirfd, name);
457 close(attrdirfd);
459 return ret;
460 #else
461 errno = ENOSYS;
462 return -1;
463 #endif
466 int rep_fremovexattr (int filedes, const char *name)
468 #if defined(HAVE_XATTR_XATTR)
469 #ifndef XATTR_ADDITIONAL_OPTIONS
470 return fremovexattr(filedes, name);
471 #else
472 /* So that we do not recursivly call this function */
473 #undef fremovexattr
474 int options = 0;
475 return fremovexattr(filedes, name, options);
476 #endif
477 #elif defined(HAVE_XATTR_EA)
478 return fremoveea(filedes, name);
479 #elif defined(HAVE_XATTR_EXTATTR)
480 int attrnamespace;
481 const char *attrname;
483 if (strncmp(name, "system.", 7) == 0) {
484 attrnamespace = EXTATTR_NAMESPACE_SYSTEM;
485 attrname = name + 7;
486 } else if (strncmp(name, "user.", 5) == 0) {
487 attrnamespace = EXTATTR_NAMESPACE_USER;
488 attrname = name + 5;
489 } else {
490 errno = EINVAL;
491 return -1;
494 return extattr_delete_fd(filedes, attrnamespace, attrname);
495 #elif defined(HAVE_XATTR_ATTR)
496 int flags = 0;
497 char *attrname = strchr(name,'.') + 1;
499 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
501 return attr_removef(filedes, attrname, flags);
502 #elif defined(HAVE_ATTROPEN)
503 int ret = -1;
504 int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
505 if (attrdirfd >= 0) {
506 ret = solaris_unlinkat(attrdirfd, name);
507 close(attrdirfd);
509 return ret;
510 #else
511 errno = ENOSYS;
512 return -1;
513 #endif
516 int rep_setxattr (const char *path, const char *name, const void *value, size_t size, int flags)
518 #if defined(HAVE_XATTR_XATTR)
519 #ifndef XATTR_ADDITIONAL_OPTIONS
520 return setxattr(path, name, value, size, flags);
521 #else
522 /* So that we do not recursivly call this function */
523 #undef setxattr
524 int options = 0;
525 return setxattr(path, name, value, size, 0, options);
526 #endif
527 #elif defined(HAVE_XATTR_EA)
528 return setea(path, name, value, size, flags);
529 #elif defined(HAVE_XATTR_EXTATTR)
530 int retval = 0;
531 int attrnamespace;
532 const char *attrname;
534 if (strncmp(name, "system.", 7) == 0) {
535 attrnamespace = EXTATTR_NAMESPACE_SYSTEM;
536 attrname = name + 7;
537 } else if (strncmp(name, "user.", 5) == 0) {
538 attrnamespace = EXTATTR_NAMESPACE_USER;
539 attrname = name + 5;
540 } else {
541 errno = EINVAL;
542 return -1;
545 if (flags) {
546 /* Check attribute existence */
547 retval = extattr_get_file(path, attrnamespace, attrname, NULL, 0);
548 if (retval < 0) {
549 /* REPLACE attribute, that doesn't exist */
550 if (flags & XATTR_REPLACE && errno == ENOATTR) {
551 errno = ENOATTR;
552 return -1;
554 /* Ignore other errors */
556 else {
557 /* CREATE attribute, that already exists */
558 if (flags & XATTR_CREATE) {
559 errno = EEXIST;
560 return -1;
564 retval = extattr_set_file(path, attrnamespace, attrname, value, size);
565 return (retval < 0) ? -1 : 0;
566 #elif defined(HAVE_XATTR_ATTR)
567 int myflags = 0;
568 char *attrname = strchr(name,'.') + 1;
570 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
571 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
572 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
574 return attr_set(path, attrname, (const char *)value, size, myflags);
575 #elif defined(HAVE_ATTROPEN)
576 int ret = -1;
577 int myflags = O_RDWR;
578 int attrfd;
579 if (flags & XATTR_CREATE) myflags |= O_EXCL;
580 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
581 attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
582 if (attrfd >= 0) {
583 ret = solaris_write_xattr(attrfd, value, size);
584 close(attrfd);
586 return ret;
587 #else
588 errno = ENOSYS;
589 return -1;
590 #endif
593 int rep_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags)
595 #if defined(HAVE_XATTR_XATTR)
596 #ifndef XATTR_ADDITIONAL_OPTIONS
597 return fsetxattr(filedes, name, value, size, flags);
598 #else
599 /* So that we do not recursivly call this function */
600 #undef fsetxattr
601 int options = 0;
602 return fsetxattr(filedes, name, value, size, 0, options);
603 #endif
604 #elif defined(HAVE_XATTR_EA)
605 return fsetea(filedes, name, value, size, flags);
606 #elif defined(HAVE_XATTR_EXTATTR)
607 int retval = 0;
608 int attrnamespace;
609 const char *attrname;
611 if (strncmp(name, "system.", 7) == 0) {
612 attrnamespace = EXTATTR_NAMESPACE_SYSTEM;
613 attrname = name + 7;
614 } else if (strncmp(name, "user.", 5) == 0) {
615 attrnamespace = EXTATTR_NAMESPACE_USER;
616 attrname = name + 5;
617 } else {
618 errno = EINVAL;
619 return -1;
622 if (flags) {
623 /* Check attribute existence */
624 retval = extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0);
625 if (retval < 0) {
626 /* REPLACE attribute, that doesn't exist */
627 if (flags & XATTR_REPLACE && errno == ENOATTR) {
628 errno = ENOATTR;
629 return -1;
631 /* Ignore other errors */
633 else {
634 /* CREATE attribute, that already exists */
635 if (flags & XATTR_CREATE) {
636 errno = EEXIST;
637 return -1;
641 retval = extattr_set_fd(filedes, attrnamespace, attrname, value, size);
642 return (retval < 0) ? -1 : 0;
643 #elif defined(HAVE_XATTR_ATTR)
644 int myflags = 0;
645 char *attrname = strchr(name,'.') + 1;
647 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
648 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
649 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
651 return attr_setf(filedes, attrname, (const char *)value, size, myflags);
652 #elif defined(HAVE_ATTROPEN)
653 int ret = -1;
654 int myflags = O_RDWR | O_XATTR;
655 int attrfd;
656 if (flags & XATTR_CREATE) myflags |= O_EXCL;
657 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
658 attrfd = solaris_openat(filedes, name, myflags, (mode_t) SOLARIS_ATTRMODE);
659 if (attrfd >= 0) {
660 ret = solaris_write_xattr(attrfd, value, size);
661 close(attrfd);
663 return ret;
664 #else
665 errno = ENOSYS;
666 return -1;
667 #endif
670 /**************************************************************************
671 helper functions for Solaris' EA support
672 ****************************************************************************/
673 #ifdef HAVE_ATTROPEN
674 static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size)
676 struct stat sbuf;
678 if (fstat(attrfd, &sbuf) == -1) {
679 errno = ENOATTR;
680 return -1;
683 /* This is to return the current size of the named extended attribute */
684 if (size == 0) {
685 return sbuf.st_size;
688 /* check size and read xattr */
689 if (sbuf.st_size > size) {
690 errno = ERANGE;
691 return -1;
694 return read(attrfd, value, sbuf.st_size);
697 static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size)
699 ssize_t len = 0;
700 DIR *dirp;
701 struct dirent *de;
702 int newfd = dup(attrdirfd);
703 /* CAUTION: The originating file descriptor should not be
704 used again following the call to fdopendir().
705 For that reason we dup() the file descriptor
706 here to make things more clear. */
707 dirp = fdopendir(newfd);
709 while ((de = readdir(dirp))) {
710 size_t listlen = strlen(de->d_name) + 1;
711 if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) {
712 /* we don't want "." and ".." here: */
713 continue;
716 if (size == 0) {
717 /* return the current size of the list of extended attribute names*/
718 len += listlen;
719 } else {
720 /* check size and copy entrieѕ + nul into list. */
721 if ((len + listlen) > size) {
722 errno = ERANGE;
723 len = -1;
724 break;
725 } else {
726 strlcpy(list + len, de->d_name, listlen);
727 len += listlen;
732 if (closedir(dirp) == -1) {
733 return -1;
735 return len;
738 static int solaris_unlinkat(int attrdirfd, const char *name)
740 if (unlinkat(attrdirfd, name, 0) == -1) {
741 if (errno == ENOENT) {
742 errno = ENOATTR;
744 return -1;
746 return 0;
749 static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode)
751 int filedes = attropen(path, attrpath, oflag, mode);
752 if (filedes == -1) {
753 if (errno == EINVAL) {
754 errno = ENOTSUP;
755 } else {
756 errno = ENOATTR;
759 return filedes;
762 static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode)
764 int filedes = openat(fildes, path, oflag, mode);
765 if (filedes == -1) {
766 if (errno == EINVAL) {
767 errno = ENOTSUP;
768 } else {
769 errno = ENOATTR;
772 return filedes;
775 static int solaris_write_xattr(int attrfd, const char *value, size_t size)
777 if ((ftruncate(attrfd, 0) == 0) && (write(attrfd, value, size) == size)) {
778 return 0;
779 } else {
780 return -1;
783 #endif /*HAVE_ATTROPEN*/