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 Samba 3.0.28, modified for netatalk.
24 $Id: ad_ea.c,v 1.1 2009-11-13 06:36:05 didg Exp $
34 #define HAVE_ATTR_XATTR_H 1
35 #define HAVE_FGETXATTR 1
36 #define HAVE_FLISTXATTR 1
37 #define HAVE_FREMOVEXATTR 1
38 #define HAVE_FSETXATTR 1
39 #define HAVE_GETXATTR 1
40 #define HAVE_LGETXATTR 1
41 #define HAVE_LISTXATTR 1
42 #define HAVE_LLISTXATTR 1
43 #define HAVE_LREMOVEXATTR 1
44 #define HAVE_LSETXATTR 1
45 #define HAVE_REMOVEXATTR 1
46 #define HAVE_SETXATTR 1
47 #define HAVE_SYS_XATTR_H 1
50 #include <sys/types.h>
53 #include <attr/xattr.h>
54 #elif HAVE_SYS_XATTR_H
55 #include <sys/xattr.h>
62 #ifdef HAVE_SYS_EXTATTR_H
63 #include <sys/extattr.h>
66 #include <atalk/adouble.h>
67 #include <atalk/logger.h>
69 /******** Solaris EA helper function prototypes ********/
71 #define SOLARIS_ATTRMODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP
72 static int solaris_write_xattr(int attrfd, const char *value, size_t size);
73 static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size);
74 static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size);
75 static int solaris_unlinkat(int attrdirfd, const char *name);
76 static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode);
77 static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode);
80 /**************************************************************************
81 Wrappers for extented attribute calls. Based on the Linux package with
82 support for IRIX and (Net|Free)BSD also. Expand as other systems have them.
83 ****************************************************************************/
85 ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t size)
87 #if defined(HAVE_GETXATTR)
89 return getxattr(path, name, value, size);
92 return getxattr(path, name, value, size, 0, options);
94 #elif defined(HAVE_GETEA)
95 return getea(path, name, value, size);
96 #elif defined(HAVE_EXTATTR_GET_FILE)
99 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
100 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
101 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
103 * The BSD implementation has a nasty habit of silently truncating
104 * the returned value to the size of the buffer, so we have to check
105 * that the buffer is large enough to fit the returned value.
107 if((retval=extattr_get_file(path, attrnamespace, attrname, NULL, 0)) >= 0) {
112 if((retval=extattr_get_file(path, attrnamespace, attrname, value, size)) >= 0)
116 LOG(log_maxdebug, logtype_default, "sys_getxattr: extattr_get_file() failed with: %s\n", strerror(errno));
118 #elif defined(HAVE_ATTR_GET)
119 int retval, flags = 0;
120 int valuelength = (int)size;
121 char *attrname = strchr(name,'.') + 1;
123 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
125 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
127 return retval ? retval : valuelength;
128 #elif defined(HAVE_ATTROPEN)
130 int attrfd = solaris_attropen(path, name, O_RDONLY, 0);
132 ret = solaris_read_xattr(attrfd, value, size);
142 ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t size)
144 #if defined(HAVE_LGETXATTR)
145 return lgetxattr(path, name, value, size);
146 #elif defined(HAVE_GETXATTR) && defined(XATTR_ADD_OPT)
147 int options = XATTR_NOFOLLOW;
148 return getxattr(path, name, value, size, 0, options);
149 #elif defined(HAVE_LGETEA)
150 return lgetea(path, name, value, size);
151 #elif defined(HAVE_EXTATTR_GET_LINK)
154 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
155 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
156 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
158 if((retval=extattr_get_link(path, attrnamespace, attrname, NULL, 0)) >= 0) {
163 if((retval=extattr_get_link(path, attrnamespace, attrname, value, size)) >= 0)
167 LOG(log_maxdebug, logtype_default, "sys_lgetxattr: extattr_get_link() failed with: %s\n", strerror(errno));
169 #elif defined(HAVE_ATTR_GET)
170 int retval, flags = ATTR_DONTFOLLOW;
171 int valuelength = (int)size;
172 char *attrname = strchr(name,'.') + 1;
174 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
176 retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
178 return retval ? retval : valuelength;
179 #elif defined(HAVE_ATTROPEN)
181 int attrfd = solaris_attropen(path, name, O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
183 ret = solaris_read_xattr(attrfd, value, size);
193 ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size)
195 #if defined(HAVE_FGETXATTR)
196 #ifndef XATTR_ADD_OPT
197 return fgetxattr(filedes, name, value, size);
200 return fgetxattr(filedes, name, value, size, 0, options);
202 #elif defined(HAVE_FGETEA)
203 return fgetea(filedes, name, value, size);
204 #elif defined(HAVE_EXTATTR_GET_FD)
207 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
208 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
209 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
211 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0)) >= 0) {
216 if((retval=extattr_get_fd(filedes, attrnamespace, attrname, value, size)) >= 0)
220 LOG(log_maxdebug, logtype_default, "sys_fgetxattr: extattr_get_fd() failed with: %s\n", strerror(errno));
222 #elif defined(HAVE_ATTR_GETF)
223 int retval, flags = 0;
224 int valuelength = (int)size;
225 char *attrname = strchr(name,'.') + 1;
227 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
229 retval = attr_getf(filedes, attrname, (char *)value, &valuelength, flags);
231 return retval ? retval : valuelength;
232 #elif defined(HAVE_ATTROPEN)
234 int attrfd = solaris_openat(filedes, name, O_RDONLY|O_XATTR, 0);
236 ret = solaris_read_xattr(attrfd, value, size);
246 #if defined(HAVE_EXTATTR_LIST_FILE)
248 #define EXTATTR_PREFIX(s) (s), (sizeof((s))-1)
256 { EXTATTR_NAMESPACE_SYSTEM, EXTATTR_PREFIX("system.") },
257 { EXTATTR_NAMESPACE_USER, EXTATTR_PREFIX("user.") },
265 static ssize_t bsd_attr_list (int type, extattr_arg arg, char *list, size_t size)
267 ssize_t list_size, total_size = 0;
270 /* Iterate through extattr(2) namespaces */
271 for(t = 0; t < (sizeof(extattr)/sizeof(extattr[0])); t++) {
273 #if defined(HAVE_EXTATTR_LIST_FILE)
275 list_size = extattr_list_file(arg.path, extattr[t].space, list, size);
278 #if defined(HAVE_EXTATTR_LIST_LINK)
280 list_size = extattr_list_link(arg.path, extattr[t].space, list, size);
283 #if defined(HAVE_EXTATTR_LIST_FD)
285 list_size = extattr_list_fd(arg.filedes, extattr[t].space, list, size);
292 /* Some error happend. Errno should be set by the previous call */
298 /* XXX: Call with an empty buffer may be used to calculate
299 necessary buffer size. Unfortunately, we can't say, how
300 many attributes were returned, so here is the potential
301 problem with the emulation.
304 /* Take the worse case of one char attribute names -
305 two bytes per name plus one more for sanity.
307 total_size += list_size + (list_size/2 + 1)*extattr[t].len;
310 /* Count necessary offset to fit namespace prefixes */
312 for(i = 0; i < list_size; i += list[i] + 1)
313 len += extattr[t].len;
315 total_size += list_size + len;
316 /* Buffer is too small to fit the results */
317 if(total_size > size) {
321 /* Shift results back, so we can prepend prefixes */
322 buf = memmove(list + len, list, list_size);
324 for(i = 0; i < list_size; i += len + 1) {
326 strncpy(list, extattr[t].name, extattr[t].len + 1);
327 list += extattr[t].len;
328 strncpy(list, buf + i + 1, len);
339 #if defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
340 static char attr_buffer[ATTR_MAX_VALUELEN];
342 static ssize_t irix_attr_list(const char *path, int filedes, char *list, size_t size, int flags)
344 int retval = 0, index;
345 attrlist_cursor_t *cursor = 0;
347 attrlist_t * al = (attrlist_t *)attr_buffer;
349 size_t ent_size, left = size;
354 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
356 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
358 for (index = 0; index < al->al_count; index++) {
359 ae = ATTR_ENTRY(attr_buffer, index);
360 ent_size = strlen(ae->a_name) + sizeof("user.");
361 if (left >= ent_size) {
362 strncpy(bp, "user.", sizeof("user."));
363 strncat(bp, ae->a_name, ent_size - sizeof("user."));
371 total_size += ent_size;
373 if (al->al_more == 0) break;
380 retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
382 retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
384 for (index = 0; index < al->al_count; index++) {
385 ae = ATTR_ENTRY(attr_buffer, index);
386 ent_size = strlen(ae->a_name) + sizeof("system.");
387 if (left >= ent_size) {
388 strncpy(bp, "system.", sizeof("system."));
389 strncat(bp, ae->a_name, ent_size - sizeof("system."));
397 total_size += ent_size;
399 if (al->al_more == 0) break;
402 return (ssize_t)(retval ? retval : total_size);
407 ssize_t sys_listxattr (const char *path, char *list, size_t size)
409 #if defined(HAVE_LISTXATTR)
410 #ifndef XATTR_ADD_OPT
411 return listxattr(path, list, size);
414 return listxattr(path, list, size, options);
416 #elif defined(HAVE_LISTEA)
417 return listea(path, list, size);
418 #elif defined(HAVE_EXTATTR_LIST_FILE)
421 return bsd_attr_list(0, arg, list, size);
422 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
423 return irix_attr_list(path, 0, list, size, 0);
424 #elif defined(HAVE_ATTROPEN)
426 int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
427 if (attrdirfd >= 0) {
428 ret = solaris_list_xattr(attrdirfd, list, size);
438 ssize_t sys_llistxattr (const char *path, char *list, size_t size)
440 #if defined(HAVE_LLISTXATTR)
441 return llistxattr(path, list, size);
442 #elif defined(HAVE_LISTXATTR) && defined(XATTR_ADD_OPT)
443 int options = XATTR_NOFOLLOW;
444 return listxattr(path, list, size, options);
445 #elif defined(HAVE_LLISTEA)
446 return llistea(path, list, size);
447 #elif defined(HAVE_EXTATTR_LIST_LINK)
450 return bsd_attr_list(1, arg, list, size);
451 #elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
452 return irix_attr_list(path, 0, list, size, ATTR_DONTFOLLOW);
453 #elif defined(HAVE_ATTROPEN)
455 int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
456 if (attrdirfd >= 0) {
457 ret = solaris_list_xattr(attrdirfd, list, size);
467 ssize_t sys_flistxattr (int filedes, char *list, size_t size)
469 #if defined(HAVE_FLISTXATTR)
470 #ifndef XATTR_ADD_OPT
471 return flistxattr(filedes, list, size);
474 return flistxattr(filedes, list, size, options);
476 #elif defined(HAVE_FLISTEA)
477 return flistea(filedes, list, size);
478 #elif defined(HAVE_EXTATTR_LIST_FD)
480 arg.filedes = filedes;
481 return bsd_attr_list(2, arg, list, size);
482 #elif defined(HAVE_ATTR_LISTF)
483 return irix_attr_list(NULL, filedes, list, size, 0);
484 #elif defined(HAVE_ATTROPEN)
486 int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
487 if (attrdirfd >= 0) {
488 ret = solaris_list_xattr(attrdirfd, list, size);
498 int sys_removexattr (const char *path, const char *name)
500 #if defined(HAVE_REMOVEXATTR)
501 #ifndef XATTR_ADD_OPT
502 return removexattr(path, name);
505 return removexattr(path, name, options);
507 #elif defined(HAVE_REMOVEEA)
508 return removeea(path, name);
509 #elif defined(HAVE_EXTATTR_DELETE_FILE)
511 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
512 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
513 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
515 return extattr_delete_file(path, attrnamespace, attrname);
516 #elif defined(HAVE_ATTR_REMOVE)
518 char *attrname = strchr(name,'.') + 1;
520 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
522 return attr_remove(path, attrname, flags);
523 #elif defined(HAVE_ATTROPEN)
525 int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
526 if (attrdirfd >= 0) {
527 ret = solaris_unlinkat(attrdirfd, name);
537 int sys_lremovexattr (const char *path, const char *name)
539 #if defined(HAVE_LREMOVEXATTR)
540 return lremovexattr(path, name);
541 #elif defined(HAVE_REMOVEXATTR) && defined(XATTR_ADD_OPT)
542 int options = XATTR_NOFOLLOW;
543 return removexattr(path, name, options);
544 #elif defined(HAVE_LREMOVEEA)
545 return lremoveea(path, name);
546 #elif defined(HAVE_EXTATTR_DELETE_LINK)
548 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
549 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
550 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
552 return extattr_delete_link(path, attrnamespace, attrname);
553 #elif defined(HAVE_ATTR_REMOVE)
554 int flags = ATTR_DONTFOLLOW;
555 char *attrname = strchr(name,'.') + 1;
557 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
559 return attr_remove(path, attrname, flags);
560 #elif defined(HAVE_ATTROPEN)
562 int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
563 if (attrdirfd >= 0) {
564 ret = solaris_unlinkat(attrdirfd, name);
574 int sys_fremovexattr (int filedes, const char *name)
576 #if defined(HAVE_FREMOVEXATTR)
577 #ifndef XATTR_ADD_OPT
578 return fremovexattr(filedes, name);
581 return fremovexattr(filedes, name, options);
583 #elif defined(HAVE_FREMOVEEA)
584 return fremoveea(filedes, name);
585 #elif defined(HAVE_EXTATTR_DELETE_FD)
587 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
588 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
589 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
591 return extattr_delete_fd(filedes, attrnamespace, attrname);
592 #elif defined(HAVE_ATTR_REMOVEF)
594 char *attrname = strchr(name,'.') + 1;
596 if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
598 return attr_removef(filedes, attrname, flags);
599 #elif defined(HAVE_ATTROPEN)
601 int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
602 if (attrdirfd >= 0) {
603 ret = solaris_unlinkat(attrdirfd, name);
613 #if !defined(HAVE_SETXATTR)
614 #define XATTR_CREATE 0x1 /* set value, fail if attr already exists */
615 #define XATTR_REPLACE 0x2 /* set value, fail if attr does not exist */
618 int sys_setxattr (const char *path, const char *name, const void *value, size_t size, int flags)
620 #if defined(HAVE_SETXATTR)
621 #ifndef XATTR_ADD_OPT
622 return setxattr(path, name, value, size, flags);
625 return setxattr(path, name, value, size, 0, options);
627 #elif defined(HAVE_SETEA)
628 return setea(path, name, value, size, flags);
629 #elif defined(HAVE_EXTATTR_SET_FILE)
632 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
633 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
634 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
636 /* Check attribute existence */
637 retval = extattr_get_file(path, attrnamespace, attrname, NULL, 0);
639 /* REPLACE attribute, that doesn't exist */
640 if (flags & XATTR_REPLACE && errno == ENOATTR) {
644 /* Ignore other errors */
647 /* CREATE attribute, that already exists */
648 if (flags & XATTR_CREATE) {
654 retval = extattr_set_file(path, attrnamespace, attrname, value, size);
655 return (retval < 0) ? -1 : 0;
656 #elif defined(HAVE_ATTR_SET)
658 char *attrname = strchr(name,'.') + 1;
660 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
661 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
662 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
664 return attr_set(path, attrname, (const char *)value, size, myflags);
665 #elif defined(HAVE_ATTROPEN)
667 int myflags = O_RDWR;
669 if (flags & XATTR_CREATE) myflags |= O_EXCL;
670 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
671 attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
673 ret = solaris_write_xattr(attrfd, value, size);
683 int sys_lsetxattr (const char *path, const char *name, const void *value, size_t size, int flags)
685 #if defined(HAVE_LSETXATTR)
686 return lsetxattr(path, name, value, size, flags);
687 #elif defined(HAVE_SETXATTR) && defined(XATTR_ADD_OPT)
688 int options = XATTR_NOFOLLOW;
689 return setxattr(path, name, value, size, 0, options);
690 #elif defined(LSETEA)
691 return lsetea(path, name, value, size, flags);
692 #elif defined(HAVE_EXTATTR_SET_LINK)
695 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
696 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
697 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
699 /* Check attribute existence */
700 retval = extattr_get_link(path, attrnamespace, attrname, NULL, 0);
702 /* REPLACE attribute, that doesn't exist */
703 if (flags & XATTR_REPLACE && errno == ENOATTR) {
707 /* Ignore other errors */
710 /* CREATE attribute, that already exists */
711 if (flags & XATTR_CREATE) {
718 retval = extattr_set_link(path, attrnamespace, attrname, value, size);
719 return (retval < 0) ? -1 : 0;
720 #elif defined(HAVE_ATTR_SET)
721 int myflags = ATTR_DONTFOLLOW;
722 char *attrname = strchr(name,'.') + 1;
724 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
725 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
726 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
728 return attr_set(path, attrname, (const char *)value, size, myflags);
729 #elif defined(HAVE_ATTROPEN)
731 int myflags = O_RDWR | AT_SYMLINK_NOFOLLOW;
733 if (flags & XATTR_CREATE) myflags |= O_EXCL;
734 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
735 attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
737 ret = solaris_write_xattr(attrfd, value, size);
747 int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags)
749 #if defined(HAVE_FSETXATTR)
750 #ifndef XATTR_ADD_OPT
751 return fsetxattr(filedes, name, value, size, flags);
754 return fsetxattr(filedes, name, value, size, 0, options);
756 #elif defined(HAVE_FSETEA)
757 return fsetea(filedes, name, value, size, flags);
758 #elif defined(HAVE_EXTATTR_SET_FD)
761 int attrnamespace = (strncmp(name, "system", 6) == 0) ?
762 EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
763 const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
765 /* Check attribute existence */
766 retval = extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0);
768 /* REPLACE attribute, that doesn't exist */
769 if (flags & XATTR_REPLACE && errno == ENOATTR) {
773 /* Ignore other errors */
776 /* CREATE attribute, that already exists */
777 if (flags & XATTR_CREATE) {
783 retval = extattr_set_fd(filedes, attrnamespace, attrname, value, size);
784 return (retval < 0) ? -1 : 0;
785 #elif defined(HAVE_ATTR_SETF)
787 char *attrname = strchr(name,'.') + 1;
789 if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
790 if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
791 if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
793 return attr_setf(filedes, attrname, (const char *)value, size, myflags);
794 #elif defined(HAVE_ATTROPEN)
796 int myflags = O_RDWR | O_XATTR;
798 if (flags & XATTR_CREATE) myflags |= O_EXCL;
799 if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
800 attrfd = solaris_openat(filedes, name, myflags, (mode_t) SOLARIS_ATTRMODE);
802 ret = solaris_write_xattr(attrfd, value, size);
812 /**************************************************************************
813 helper functions for Solaris' EA support
814 ****************************************************************************/
816 static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size)
820 if (fstat(attrfd, &sbuf) == -1) {
825 /* This is to return the current size of the named extended attribute */
830 /* check size and read xattr */
831 if (sbuf.st_size > size) {
836 return read(attrfd, value, sbuf.st_size);
839 static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size)
845 int newfd = dup(attrdirfd);
846 /* CAUTION: The originating file descriptor should not be
847 used again following the call to fdopendir().
848 For that reason we dup() the file descriptor
849 here to make things more clear. */
850 dirp = fdopendir(newfd);
852 while ((de = readdir(dirp))) {
853 size_t listlen = strlen(de->d_name);
854 if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) {
855 /* we don't want "." and ".." here: */
856 LOG(log_maxdebug, logtype_default, "skipped EA %s\n",de->d_name);
861 /* return the current size of the list of extended attribute names*/
864 /* check size and copy entry + nul into list. */
865 if ((len + listlen + 1) > size) {
870 safe_strcpy(list + len, de->d_name, listlen);
871 pstrcpy(list + len, de->d_name);
879 if (closedir(dirp) == -1) {
880 LOG(log_debug, logtype_default, "closedir dirp failed: %s\n",strerror(errno));
886 static int solaris_unlinkat(int attrdirfd, const char *name)
888 if (unlinkat(attrdirfd, name, 0) == -1) {
889 if (errno == ENOENT) {
897 static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode)
899 int filedes = attropen(path, attrpath, oflag, mode);
901 LOG(log_maxdebug, logtype_default, "attropen FAILED: path: %s, name: %s, errno: %s\n",path,attrpath,strerror(errno));
902 if (errno == EINVAL) {
911 static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode)
913 int filedes = openat(fildes, path, oflag, mode);
915 LOG(log_maxdebug, logtype_default, "openat FAILED: fd: %s, path: %s, errno: %s\n",filedes,path,strerror(errno));
916 if (errno == EINVAL) {
925 static int solaris_write_xattr(int attrfd, const char *value, size_t size)
927 if ((ftruncate(attrfd, 0) == 0) && (write(attrfd, value, size) == size)) {
930 LOG(log_maxdebug, logtype_default, "solaris_write_xattr FAILED!\n");
934 #endif /*HAVE_ATTROPEN*/