2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Jeremy Allison 1998-2005
6 Copyright (C) Timur Bakeyev 2005
7 Copyright (C) Bjoern Jacke 2006-2007
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 sys_copyxattr modified from LGPL2.1 libattr copyright
24 Copyright (C) 2001-2002 Silicon Graphics, Inc. All Rights Reserved.
25 Copyright (C) 2001 Andreas Gruenbacher.
27 Samba 3.0.28, modified for netatalk.
36 #include <sys/types.h>
40 #include <attr/xattr.h>
41 #elif HAVE_SYS_XATTR_H
42 #include <sys/xattr.h>
54 #ifdef HAVE_SYS_EXTATTR_H
55 #include <sys/extattr.h>
58 #include <atalk/adouble.h>
59 #include <atalk/util.h>
60 #include <atalk/logger.h>
62 #include <atalk/compat.h>
63 #include <atalk/errchk.h>
65 /******** Solaris EA helper function prototypes ********/
67 #define SOLARIS_ATTRMODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH
68 static int solaris_write_xattr(int attrfd, const char *value, size_t size);
69 static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size);
70 static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size);
71 static int solaris_unlinkat(int attrdirfd, const char *name);
72 static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode);
73 static int solaris_attropenat(int filedes, const char *path, const char *attrpath, int oflag, mode_t mode);
74 static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode);
77 /**************************************************************************
78 Wrappers for extented attribute calls. Based on the Linux package with
79 support for IRIX and (Net|Free)BSD also. Expand as other systems have them.
80 ****************************************************************************/
81 static char attr_name[256 +5] = "user.";
83 static const char *prefix(const char *uname)
85 #if defined(HAVE_ATTROPEN)
88 strlcpy(attr_name +5, uname, 256);
93 int sys_getxattrfd(int fd, const char *uname, int oflag, ...)
95 #if defined HAVE_ATTROPEN
100 if (oflag & O_CREAT) {
101 va_start(args, oflag);
102 mode = va_arg(args, mode_t);
107 eafd = solaris_openat(fd, uname, oflag | O_XATTR, mode);
109 eafd = solaris_openat(fd, uname, oflag | O_XATTR, mode);
118 ssize_t sys_getxattr (const char *path, const char *uname, void *value, size_t size)
120 const char *name = prefix(uname);
122 #if defined(HAVE_GETXATTR)
123 #ifndef XATTR_ADD_OPT
124 return getxattr(path, name, value, size);
127 return getxattr(path, name, value, size, 0, options);
129 #elif defined(HAVE_GETEA)
130 return getea(path, name, value, size);
131 #elif defined(HAVE_EXTATTR_GET_FILE)
134 * The BSD implementation has a nasty habit of silently truncating
135 * the returned value to the size of the buffer, so we have to check
136 * that the buffer is large enough to fit the returned value.
138 if((retval = extattr_get_file(path, EXTATTR_NAMESPACE_USER, uname, NULL, 0)) >= 0) {
140 /* size == 0 means only return size */
146 if ((retval = extattr_get_file(path, EXTATTR_NAMESPACE_USER, uname, value, size)) >= 0)
150 LOG(log_maxdebug, logtype_default, "sys_getxattr: extattr_get_file() failed with: %s\n", strerror(errno));
152 #elif defined(HAVE_ATTR_GET)
153 int retval, flags = 0;
154 int valuelength = (int)size;
155 char *attrname = strchr(name,'.') + 1;
157 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
159 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
161 return retval ? retval : valuelength;
162 #elif defined(HAVE_ATTROPEN)
164 int attrfd = solaris_attropen(path, name, O_RDONLY, 0);
166 ret = solaris_read_xattr(attrfd, value, size);
176 ssize_t sys_fgetxattr (int filedes, const char *uname, void *value, size_t size)
178 const char *name = prefix(uname);
180 #if defined(HAVE_FGETXATTR)
181 #ifndef XATTR_ADD_OPT
182 return fgetxattr(filedes, name, value, size);
185 return fgetxattr(filedes, name, value, size, 0, options);
187 #elif defined(HAVE_FGETEA)
188 return fgetea(filedes, name, value, size);
189 #elif defined(HAVE_EXTATTR_GET_FD)
192 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
193 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
194 const char *attrname = ((s=strchr(name, '.')) == NULL) ? name : s + 1;
196 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0)) >= 0) {
201 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, value, size)) >= 0)
205 LOG(log_debug, logtype_default, "sys_fgetxattr: extattr_get_fd(): %s", strerror(errno));
207 #elif defined(HAVE_ATTR_GETF)
208 int retval, flags = 0;
209 int valuelength = (int)size;
210 char *attrname = strchr(name,'.') + 1;
212 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
214 retval = attr_getf(filedes, attrname, (char *)value, &valuelength, flags);
216 return retval ? retval : valuelength;
217 #elif defined(HAVE_ATTROPEN)
219 int attrfd = solaris_openat(filedes, name, O_RDONLY|O_XATTR, 0);
221 ret = solaris_read_xattr(attrfd, value, size);
231 ssize_t sys_lgetxattr (const char *path, const char *uname, void *value, size_t size)
233 const char *name = prefix(uname);
235 #if defined(HAVE_LGETXATTR)
236 return lgetxattr(path, name, value, size);
237 #elif defined(HAVE_GETXATTR) && defined(XATTR_ADD_OPT)
238 int options = XATTR_NOFOLLOW;
239 return getxattr(path, name, value, size, 0, options);
240 #elif defined(HAVE_LGETEA)
241 return lgetea(path, name, value, size);
242 #elif defined(HAVE_EXTATTR_GET_LINK)
245 retval = extattr_get_link(path, EXTATTR_NAMESPACE_USER, uname, NULL, 0);
247 LOG(log_maxdebug, logtype_default, "extattr_get_link(): %s",
252 /* Only interested in size of xattr */
258 return extattr_get_link(path, EXTATTR_NAMESPACE_USER, uname, value, size);
260 #elif defined(HAVE_ATTR_GET)
261 int retval, flags = ATTR_DONTFOLLOW;
262 int valuelength = (int)size;
263 char *attrname = strchr(name,'.') + 1;
265 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
267 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
269 return retval ? retval : valuelength;
270 #elif defined(HAVE_ATTROPEN)
272 int attrfd = solaris_attropen(path, name, O_RDONLY | O_NOFOLLOW, 0);
274 ret = solaris_read_xattr(attrfd, value, size);
284 #if defined(HAVE_EXTATTR_LIST_FILE)
286 #define EXTATTR_PREFIX(s) (s), (sizeof((s))-1)
294 { EXTATTR_NAMESPACE_SYSTEM, EXTATTR_PREFIX("") },
295 { EXTATTR_NAMESPACE_USER, EXTATTR_PREFIX("") },
303 static ssize_t bsd_attr_list (int type, extattr_arg arg, char *list, size_t size)
309 #if defined(HAVE_EXTATTR_LIST_FILE)
311 list_size = extattr_list_file(arg.path, EXTATTR_NAMESPACE_USER, list, size);
314 #if defined(HAVE_EXTATTR_LIST_LINK)
316 list_size = extattr_list_link(arg.path, EXTATTR_NAMESPACE_USER, list, size);
319 #if defined(HAVE_EXTATTR_LIST_FD)
321 list_size = extattr_list_fd(arg.filedes, EXTATTR_NAMESPACE_USER, list, size);
329 /* Some error happend. Errno should be set by the previous call */
337 /* XXX: Call with an empty buffer may be used to calculate
338 necessary buffer size. Unfortunately, we can't say, how
339 many attributes were returned, so here is the potential
340 problem with the emulation.
345 /* Buffer is too small to fit the results */
346 if(list_size > size) {
351 /* Convert from pascal strings to C strings */
353 memmove(list, list + 1, list_size);
355 for(i = len; i < list_size; ) {
356 LOG(log_maxdebug, logtype_afpd, "len: %d, i: %d", len, i);
368 #if defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
369 static char attr_buffer[ATTR_MAX_VALUELEN];
371 static ssize_t irix_attr_list(const char *path, int filedes, char *list, size_t size, int flags)
373 int retval = 0, index;
374 attrlist_cursor_t *cursor = 0;
376 attrlist_t * al = (attrlist_t *)attr_buffer;
378 size_t ent_size, left = size;
383 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
385 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
387 for (index = 0; index < al->al_count; index++) {
388 ae = ATTR_ENTRY(attr_buffer, index);
389 ent_size = strlen(ae->a_name) + sizeof("user.");
390 if (left >= ent_size) {
391 strncpy(bp, "user.", sizeof("user."));
392 strncat(bp, ae->a_name, ent_size - sizeof("user."));
400 total_size += ent_size;
402 if (al->al_more == 0) break;
409 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
411 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
413 for (index = 0; index < al->al_count; index++) {
414 ae = ATTR_ENTRY(attr_buffer, index);
415 ent_size = strlen(ae->a_name) + sizeof("system.");
416 if (left >= ent_size) {
417 strncpy(bp, "system.", sizeof("system."));
418 strncat(bp, ae->a_name, ent_size - sizeof("system."));
426 total_size += ent_size;
428 if (al->al_more == 0) break;
431 return (ssize_t)(retval ? retval : total_size);
436 #if defined(HAVE_LISTXATTR)
437 static ssize_t remove_user(ssize_t ret, char *list, size_t size)
444 if (ret <= 0 || size == 0)
448 while (ptrsize > 0) {
449 len = strlen(ptr1) +1;
451 if (strncmp(ptr1, "user.",5)) {
455 memmove(ptr, ptr1 +5, len -5);
463 ssize_t sys_listxattr (const char *path, char *list, size_t size)
465 #if defined(HAVE_LISTXATTR)
468 #ifndef XATTR_ADD_OPT
469 ret = listxattr(path, list, size);
472 ret = listxattr(path, list, size, options);
474 return remove_user(ret, list, size);
476 #elif defined(HAVE_LISTEA)
477 return listea(path, list, size);
478 #elif defined(HAVE_EXTATTR_LIST_FILE)
481 return bsd_attr_list(0, arg, list, size);
482 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
483 return irix_attr_list(path, 0, list, size, 0);
484 #elif defined(HAVE_ATTROPEN)
486 int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
487 if (attrdirfd >= 0) {
488 ret = solaris_list_xattr(attrdirfd, list, size);
498 ssize_t sys_flistxattr (int filedes, const char *path, char *list, size_t size)
500 #if defined(HAVE_LISTXATTR)
503 #ifndef XATTR_ADD_OPT
504 ret = listxattr(path, list, size);
507 ret = listxattr(path, list, size, options);
509 return remove_user(ret, list, size);
511 #elif defined(HAVE_LISTEA)
512 return listea(path, list, size);
513 #elif defined(HAVE_EXTATTR_LIST_FILE)
516 return bsd_attr_list(0, arg, list, size);
517 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
518 return irix_attr_list(path, 0, list, size, 0);
519 #elif defined(HAVE_ATTROPEN)
521 int attrdirfd = solaris_attropenat(filedes, path, ".", O_RDONLY, 0);
522 if (attrdirfd >= 0) {
523 ret = solaris_list_xattr(attrdirfd, list, size);
533 ssize_t sys_llistxattr (const char *path, char *list, size_t size)
535 #if defined(HAVE_LLISTXATTR)
538 ret = llistxattr(path, list, size);
539 return remove_user(ret, list, size);
540 #elif defined(HAVE_LISTXATTR) && defined(XATTR_ADD_OPT)
542 int options = XATTR_NOFOLLOW;
544 ret = listxattr(path, list, size, options);
545 return remove_user(ret, list, size);
547 #elif defined(HAVE_LLISTEA)
548 return llistea(path, list, size);
549 #elif defined(HAVE_EXTATTR_LIST_LINK)
552 return bsd_attr_list(1, arg, list, size);
553 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
554 return irix_attr_list(path, 0, list, size, ATTR_DONTFOLLOW);
555 #elif defined(HAVE_ATTROPEN)
557 int attrdirfd = solaris_attropen(path, ".", O_RDONLY | O_NOFOLLOW, 0);
558 if (attrdirfd >= 0) {
559 ret = solaris_list_xattr(attrdirfd, list, size);
569 int sys_removexattr (const char *path, const char *uname)
571 const char *name = prefix(uname);
572 #if defined(HAVE_REMOVEXATTR)
573 #ifndef XATTR_ADD_OPT
574 return removexattr(path, name);
577 return removexattr(path, name, options);
579 #elif defined(HAVE_REMOVEEA)
580 return removeea(path, name);
581 #elif defined(HAVE_EXTATTR_DELETE_FILE)
582 return extattr_delete_file(path, EXTATTR_NAMESPACE_USER, uname);
583 #elif defined(HAVE_ATTR_REMOVE)
585 char *attrname = strchr(name,'.') + 1;
587 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
589 return attr_remove(path, attrname, flags);
590 #elif defined(HAVE_ATTROPEN)
592 int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
593 if (attrdirfd >= 0) {
594 ret = solaris_unlinkat(attrdirfd, name);
604 int sys_fremovexattr (int filedes, const char *path, const char *uname)
606 const char *name = prefix(uname);
607 #if defined(HAVE_REMOVEXATTR)
608 #ifndef XATTR_ADD_OPT
609 return removexattr(path, name);
612 return removexattr(path, name, options);
614 #elif defined(HAVE_REMOVEEA)
615 return removeea(path, name);
616 #elif defined(HAVE_EXTATTR_DELETE_FILE)
617 return extattr_delete_file(path, EXTATTR_NAMESPACE_USER, uname);
618 #elif defined(HAVE_ATTR_REMOVE)
620 char *attrname = strchr(name,'.') + 1;
622 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
624 return attr_remove(path, attrname, flags);
625 #elif defined(HAVE_ATTROPEN)
627 int attrdirfd = solaris_attropenat(filedes, path, ".", O_RDONLY, 0);
628 if (attrdirfd >= 0) {
629 ret = solaris_unlinkat(attrdirfd, name);
639 int sys_lremovexattr (const char *path, const char *uname)
641 const char *name = prefix(uname);
642 #if defined(HAVE_LREMOVEXATTR)
643 return lremovexattr(path, name);
644 #elif defined(HAVE_REMOVEXATTR) && defined(XATTR_ADD_OPT)
645 int options = XATTR_NOFOLLOW;
646 return removexattr(path, name, options);
647 #elif defined(HAVE_LREMOVEEA)
648 return lremoveea(path, name);
649 #elif defined(HAVE_EXTATTR_DELETE_LINK)
650 return extattr_delete_link(path, EXTATTR_NAMESPACE_USER, uname);
651 #elif defined(HAVE_ATTR_REMOVE)
652 int flags = ATTR_DONTFOLLOW;
653 char *attrname = strchr(name,'.') + 1;
655 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
657 return attr_remove(path, attrname, flags);
658 #elif defined(HAVE_ATTROPEN)
660 int attrdirfd = solaris_attropen(path, ".", O_RDONLY | O_NOFOLLOW, 0);
661 if (attrdirfd >= 0) {
662 ret = solaris_unlinkat(attrdirfd, name);
672 int sys_setxattr (const char *path, const char *uname, const void *value, size_t size, int flags)
674 const char *name = prefix(uname);
675 #if defined(HAVE_SETXATTR)
676 #ifndef XATTR_ADD_OPT
677 return setxattr(path, name, value, size, flags);
680 return setxattr(path, name, value, size, 0, options);
682 #elif defined(HAVE_SETEA)
683 return setea(path, name, value, size, flags);
684 #elif defined(HAVE_EXTATTR_SET_FILE)
687 /* Check attribute existence */
688 retval = extattr_get_file(path, EXTATTR_NAMESPACE_USER, uname, NULL, 0);
690 /* REPLACE attribute, that doesn't exist */
691 if (flags & XATTR_REPLACE && errno == ENOATTR) {
695 /* Ignore other errors */
698 /* CREATE attribute, that already exists */
699 if (flags & XATTR_CREATE) {
705 retval = extattr_set_file(path, EXTATTR_NAMESPACE_USER, uname, value, size);
706 return (retval < 0) ? -1 : 0;
707 #elif defined(HAVE_ATTR_SET)
709 char *attrname = strchr(name,'.') + 1;
711 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
712 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
713 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
715 return attr_set(path, attrname, (const char *)value, size, myflags);
716 #elif defined(HAVE_ATTROPEN)
718 int myflags = O_RDWR;
720 if (flags & XATTR_CREATE) myflags |= O_EXCL;
721 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
722 attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
724 ret = solaris_write_xattr(attrfd, value, size);
734 int sys_fsetxattr (int filedes, const char *uname, const void *value, size_t size, int flags)
736 const char *name = prefix(uname);
738 #if defined(HAVE_FSETXATTR)
739 #ifndef XATTR_ADD_OPT
740 return fsetxattr(filedes, name, value, size, flags);
743 return fsetxattr(filedes, name, value, size, 0, options);
745 #elif defined(HAVE_FSETEA)
746 return fsetea(filedes, name, value, size, flags);
747 #elif defined(HAVE_EXTATTR_SET_FD)
750 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
751 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
752 const char *attrname = ((s=strchr(name, '.')) == NULL) ? name : s + 1;
754 /* Check attribute existence */
755 retval = extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0);
757 /* REPLACE attribute, that doesn't exist */
758 if (flags & XATTR_REPLACE && errno == ENOATTR) {
762 /* Ignore other errors */
765 if (flags & XATTR_CREATE) {
771 retval = extattr_set_fd(filedes, attrnamespace, attrname, value, size);
772 return (retval < 0) ? -1 : 0;
773 #elif defined(HAVE_ATTR_SETF)
775 char *attrname = strchr(name,'.') + 1;
777 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
778 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
779 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
781 return attr_setf(filedes, attrname, (const char *)value, size, myflags);
782 #elif defined(HAVE_ATTROPEN)
784 int myflags = O_RDWR | O_XATTR;
786 if (flags & XATTR_CREATE) myflags |= O_EXCL;
787 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
788 attrfd = solaris_openat(filedes, name, myflags, (mode_t) SOLARIS_ATTRMODE);
790 ret = solaris_write_xattr(attrfd, value, size);
800 int sys_lsetxattr (const char *path, const char *uname, const void *value, size_t size, int flags)
802 const char *name = prefix(uname);
803 #if defined(HAVE_LSETXATTR)
804 return lsetxattr(path, name, value, size, flags);
805 #elif defined(HAVE_SETXATTR) && defined(XATTR_ADD_OPT)
806 int options = XATTR_NOFOLLOW;
807 return setxattr(path, name, value, size, 0, options);
808 #elif defined(LSETEA)
809 return lsetea(path, name, value, size, flags);
810 #elif defined(HAVE_EXTATTR_SET_LINK)
813 /* Check attribute existence */
814 retval = extattr_get_link(path, EXTATTR_NAMESPACE_USER, uname, NULL, 0);
816 /* REPLACE attribute, that doesn't exist */
817 if (flags & XATTR_REPLACE && errno == ENOATTR) {
821 /* Ignore other errors */
824 /* CREATE attribute, that already exists */
825 if (flags & XATTR_CREATE) {
832 retval = extattr_set_link(path, EXTATTR_NAMESPACE_USER, uname, value, size);
833 return (retval < 0) ? -1 : 0;
834 #elif defined(HAVE_ATTR_SET)
835 int myflags = ATTR_DONTFOLLOW;
836 char *attrname = strchr(name,'.') + 1;
838 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
839 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
840 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
842 return attr_set(path, attrname, (const char *)value, size, myflags);
843 #elif defined(HAVE_ATTROPEN)
845 int myflags = O_RDWR | O_NOFOLLOW;
847 if (flags & XATTR_CREATE) myflags |= O_EXCL;
848 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
849 attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
851 ret = solaris_write_xattr(attrfd, value, size);
861 /**************************************************************************
862 helper functions for Solaris' EA support
863 ****************************************************************************/
865 static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size)
869 if (fstat(attrfd, &sbuf) == -1) {
873 /* This is to return the current size of the named extended attribute */
878 /* check size and read xattr */
879 if (sbuf.st_size > size) {
883 return read(attrfd, value, sbuf.st_size);
886 static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size)
891 int newfd = dup(attrdirfd);
892 /* CAUTION: The originating file descriptor should not be
893 used again following the call to fdopendir().
894 For that reason we dup() the file descriptor
895 here to make things more clear. */
896 dirp = fdopendir(newfd);
898 while ((de = readdir(dirp))) {
900 if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..") ||
901 !strcmp(de->d_name, "SUNWattr_ro") || !strcmp(de->d_name, "SUNWattr_rw"))
903 /* we don't want "." and ".." here: */
904 LOG(log_maxdebug, logtype_default, "skipped EA %s\n",de->d_name);
908 listlen = strlen(de->d_name);
910 /* return the current size of the list of extended attribute names*/
913 /* check size and copy entry + nul into list. */
914 if ((len + listlen + 1) > size) {
919 strcpy(list + len, de->d_name);
927 if (closedir(dirp) == -1) {
928 LOG(log_error, logtype_default, "closedir dirp: %s",strerror(errno));
934 static int solaris_unlinkat(int attrdirfd, const char *name)
936 if (unlinkat(attrdirfd, name, 0) == -1) {
942 static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode)
945 int filedes = -1, eafd = -1;
947 if ((filedes = open(path, O_RDONLY | (oflag & O_NOFOLLOW), mode)) == -1) {
951 case OPEN_NOFOLLOW_ERRNO:
954 LOG(log_debug, logtype_default, "open(\"%s\"): %s", fullpathname(path), strerror(errno));
959 if ((eafd = openat(filedes, attrpath, oflag | O_XATTR, mode)) == -1) {
965 LOG(log_debug, logtype_default, "openat(\"%s\"): %s", fullpathname(path), strerror(errno));
981 static int solaris_attropenat(int filedes, const char *path, const char *attrpath, int oflag, mode_t mode)
986 if ((eafd = openat(filedes, attrpath, oflag | O_XATTR, mode)) == -1) {
992 LOG(log_debug, logtype_default, "openat(\"%s\"): %s", fullpathname(path), strerror(errno));
1007 static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode)
1011 if ((filedes = openat(fildes, path, oflag, mode)) == -1) {
1018 LOG(log_debug, logtype_default, "openat(\"%s\"): %s",
1019 path, strerror(errno));
1027 static int solaris_write_xattr(int attrfd, const char *value, size_t size)
1029 if ((ftruncate(attrfd, 0) == 0) && (write(attrfd, value, size) == size)) {
1032 LOG(log_error, logtype_default, "solaris_write_xattr: %s",
1038 #endif /*HAVE_ATTROPEN*/