• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-WNDR4500v2-V1.0.0.60_1.0.38/ap/gpl/timemachine/netatalk-2.2.5/libatalk/vfs/
1/*
2   Unix SMB/CIFS implementation.
3   Samba system utilities
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
8
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.
13
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.
18
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.
22
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.
26
27   Samba 3.0.28, modified for netatalk.
28   $Id: sys_ea.c,v 1.6 2009-12-04 10:26:10 franklahm Exp $
29
30*/
31
32#ifdef HAVE_CONFIG_H
33#include "config.h"
34#endif
35
36#include <stdlib.h>
37#include <string.h>
38#include <sys/types.h>
39#include <errno.h>
40
41#if HAVE_ATTR_XATTR_H
42#include <attr/xattr.h>
43#elif HAVE_SYS_XATTR_H
44#include <sys/xattr.h>
45#endif
46
47#ifdef HAVE_SYS_EA_H
48#include <sys/ea.h>
49#endif
50
51#ifdef HAVE_ATTROPEN
52
53#include <dirent.h>
54#endif
55
56#ifdef HAVE_SYS_EXTATTR_H
57#include <sys/extattr.h>
58#endif
59
60#include <atalk/adouble.h>
61#include <atalk/util.h>
62#include <atalk/logger.h>
63#include <atalk/ea.h>
64
65#ifndef ENOATTR
66#define ENOATTR ENODATA
67#endif
68
69/******** Solaris EA helper function prototypes ********/
70#ifdef HAVE_ATTROPEN
71#define SOLARIS_ATTRMODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP
72static int solaris_write_xattr(int attrfd, const char *value, size_t size);
73static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size);
74static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size);
75static int solaris_unlinkat(int attrdirfd, const char *name);
76static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode);
77static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode);
78#endif
79
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****************************************************************************/
84static char attr_name[256 +5] = "user.";
85
86static const char *prefix(const char *uname)
87{
88#if defined(HAVE_ATTROPEN)
89	return uname;
90#else
91	strlcpy(attr_name +5, uname, 256);
92	return attr_name;
93#endif
94}
95
96ssize_t sys_getxattr (const char *path, const char *uname, void *value, size_t size)
97{
98	const char *name = prefix(uname);
99
100#if defined(HAVE_GETXATTR)
101#ifndef XATTR_ADD_OPT
102	return getxattr(path, name, value, size);
103#else
104	int options = 0;
105	return getxattr(path, name, value, size, 0, options);
106#endif
107#elif defined(HAVE_GETEA)
108	return getea(path, name, value, size);
109#elif defined(HAVE_EXTATTR_GET_FILE)
110	ssize_t retval;
111	/*
112	 * The BSD implementation has a nasty habit of silently truncating
113	 * the returned value to the size of the buffer, so we have to check
114	 * that the buffer is large enough to fit the returned value.
115	 */
116	if((retval = extattr_get_file(path, EXTATTR_NAMESPACE_USER, uname, NULL, 0)) >= 0) {
117        if (size == 0)
118            /* size == 0 means only return size */
119            return retval;
120		if (retval > size) {
121			errno = ERANGE;
122			return -1;
123		}
124		if ((retval = extattr_get_file(path, EXTATTR_NAMESPACE_USER, uname, value, size)) >= 0)
125			return retval;
126	}
127
128	LOG(log_maxdebug, logtype_default, "sys_getxattr: extattr_get_file() failed with: %s\n", strerror(errno));
129	return -1;
130#elif defined(HAVE_ATTR_GET)
131	int retval, flags = 0;
132	int valuelength = (int)size;
133	char *attrname = strchr(name,'.') + 1;
134
135	if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
136
137	retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
138
139	return retval ? retval : valuelength;
140#elif defined(HAVE_ATTROPEN)
141	ssize_t ret = -1;
142	int attrfd = solaris_attropen(path, name, O_RDONLY, 0);
143	if (attrfd >= 0) {
144		ret = solaris_read_xattr(attrfd, value, size);
145		close(attrfd);
146	}
147	return ret;
148#else
149	errno = ENOSYS;
150	return -1;
151#endif
152}
153
154ssize_t sys_lgetxattr (const char *path, const char *uname, void *value, size_t size)
155{
156	const char *name = prefix(uname);
157
158#if defined(HAVE_LGETXATTR)
159	return lgetxattr(path, name, value, size);
160#elif defined(HAVE_GETXATTR) && defined(XATTR_ADD_OPT)
161	int options = XATTR_NOFOLLOW;
162	return getxattr(path, name, value, size, 0, options);
163#elif defined(HAVE_LGETEA)
164	return lgetea(path, name, value, size);
165#elif defined(HAVE_EXTATTR_GET_LINK)
166	ssize_t retval;
167	if((retval=extattr_get_link(path, EXTATTR_NAMESPACE_USER, uname, NULL, 0)) >= 0) {
168		if(retval > size) {
169			errno = ERANGE;
170			return -1;
171		}
172		if((retval=extattr_get_link(path, EXTATTR_NAMESPACE_USER, uname, value, size)) >= 0)
173			return retval;
174	}
175
176	LOG(log_maxdebug, logtype_default, "sys_lgetxattr: extattr_get_link() failed with: %s\n", strerror(errno));
177	return -1;
178#elif defined(HAVE_ATTR_GET)
179	int retval, flags = ATTR_DONTFOLLOW;
180	int valuelength = (int)size;
181	char *attrname = strchr(name,'.') + 1;
182
183	if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
184
185	retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
186
187	return retval ? retval : valuelength;
188#elif defined(HAVE_ATTROPEN)
189	ssize_t ret = -1;
190	int attrfd = solaris_attropen(path, name, O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
191	if (attrfd >= 0) {
192		ret = solaris_read_xattr(attrfd, value, size);
193		close(attrfd);
194	}
195	return ret;
196#else
197	errno = ENOSYS;
198	return -1;
199#endif
200}
201
202#if defined(HAVE_EXTATTR_LIST_FILE)
203
204#define EXTATTR_PREFIX(s)	(s), (sizeof((s))-1)
205
206static struct {
207        int space;
208	const char *name;
209	size_t len;
210}
211extattr[] = {
212	{ EXTATTR_NAMESPACE_SYSTEM, EXTATTR_PREFIX("") },
213        { EXTATTR_NAMESPACE_USER, EXTATTR_PREFIX("") },
214};
215
216typedef union {
217	const char *path;
218	int filedes;
219} extattr_arg;
220
221static ssize_t bsd_attr_list (int type, extattr_arg arg, char *list, size_t size)
222{
223	ssize_t list_size;
224	int i, len;
225
226    switch(type) {
227#if defined(HAVE_EXTATTR_LIST_FILE)
228    case 0:
229        list_size = extattr_list_file(arg.path, EXTATTR_NAMESPACE_USER, list, size);
230        break;
231#endif
232#if defined(HAVE_EXTATTR_LIST_LINK)
233    case 1:
234        list_size = extattr_list_link(arg.path, EXTATTR_NAMESPACE_USER, list, size);
235        break;
236#endif
237#if defined(HAVE_EXTATTR_LIST_FD)
238    case 2:
239        list_size = extattr_list_fd(arg.filedes, EXTATTR_NAMESPACE_USER, list, size);
240        break;
241#endif
242    default:
243        errno = ENOSYS;
244        return -1;
245    }
246
247    /* Some error happend. Errno should be set by the previous call */
248    if(list_size < 0)
249        return -1;
250
251    /* No attributes */
252    if(list_size == 0)
253        return 0;
254
255    /* XXX: Call with an empty buffer may be used to calculate
256       necessary buffer size. Unfortunately, we can't say, how
257       many attributes were returned, so here is the potential
258       problem with the emulation.
259    */
260    if(list == NULL)
261        return list_size;
262
263    /* Buffer is too small to fit the results */
264    if(list_size > size) {
265        errno = ERANGE;
266        return -1;
267    }
268
269    /* Convert from pascal strings to C strings */
270    len = list[0];
271    memmove(list, list + 1, list_size);
272
273    for(i = len; i < list_size; ) {
274        LOG(log_maxdebug, logtype_afpd, "len: %d, i: %d", len, i);
275
276        len = list[i];
277        list[i] = '\0';
278        i += len + 1;
279    }
280
281	return list_size;
282}
283
284#endif
285
286#if defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
287static char attr_buffer[ATTR_MAX_VALUELEN];
288
289static ssize_t irix_attr_list(const char *path, int filedes, char *list, size_t size, int flags)
290{
291	int retval = 0, index;
292	attrlist_cursor_t *cursor = 0;
293	int total_size = 0;
294	attrlist_t * al = (attrlist_t *)attr_buffer;
295	attrlist_ent_t *ae;
296	size_t ent_size, left = size;
297	char *bp = list;
298
299	while (True) {
300	    if (filedes)
301		retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
302	    else
303		retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
304	    if (retval) break;
305	    for (index = 0; index < al->al_count; index++) {
306		ae = ATTR_ENTRY(attr_buffer, index);
307		ent_size = strlen(ae->a_name) + sizeof("user.");
308		if (left >= ent_size) {
309		    strncpy(bp, "user.", sizeof("user."));
310		    strncat(bp, ae->a_name, ent_size - sizeof("user."));
311		    bp += ent_size;
312		    left -= ent_size;
313		} else if (size) {
314		    errno = ERANGE;
315		    retval = -1;
316		    break;
317		}
318		total_size += ent_size;
319	    }
320	    if (al->al_more == 0) break;
321	}
322	if (retval == 0) {
323	    flags |= ATTR_ROOT;
324	    cursor = 0;
325	    while (True) {
326		if (filedes)
327		    retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
328		else
329		    retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
330		if (retval) break;
331		for (index = 0; index < al->al_count; index++) {
332		    ae = ATTR_ENTRY(attr_buffer, index);
333		    ent_size = strlen(ae->a_name) + sizeof("system.");
334		    if (left >= ent_size) {
335			strncpy(bp, "system.", sizeof("system."));
336			strncat(bp, ae->a_name, ent_size - sizeof("system."));
337			bp += ent_size;
338			left -= ent_size;
339		    } else if (size) {
340			errno = ERANGE;
341			retval = -1;
342			break;
343		    }
344		    total_size += ent_size;
345		}
346		if (al->al_more == 0) break;
347	    }
348	}
349	return (ssize_t)(retval ? retval : total_size);
350}
351
352#endif
353
354#if defined(HAVE_LISTXATTR)
355static ssize_t remove_user(ssize_t ret, char *list, size_t size)
356{
357	size_t len;
358	char *ptr;
359	char *ptr1;
360	ssize_t ptrsize;
361
362	if (ret <= 0 || size == 0)
363		return ret;
364	ptrsize = ret;
365	ptr = ptr1 = list;
366	while (ptrsize > 0) {
367		len = strlen(ptr1) +1;
368		ptrsize -= len;
369		if (strncmp(ptr1, "user.",5)) {
370			ptr1 += len;
371			continue;
372		}
373		memmove(ptr, ptr1 +5, len -5);
374		ptr += len -5;
375		ptr1 += len;
376	}
377	return ptr -list;
378}
379#endif
380
381ssize_t sys_listxattr (const char *path, char *list, size_t size)
382{
383#if defined(HAVE_LISTXATTR)
384	ssize_t ret;
385
386#ifndef XATTR_ADD_OPT
387	ret = listxattr(path, list, size);
388#else
389	int options = 0;
390	ret = listxattr(path, list, size, options);
391#endif
392	return remove_user(ret, list, size);
393
394#elif defined(HAVE_LISTEA)
395	return listea(path, list, size);
396#elif defined(HAVE_EXTATTR_LIST_FILE)
397	extattr_arg arg;
398	arg.path = path;
399	return bsd_attr_list(0, arg, list, size);
400#elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
401	return irix_attr_list(path, 0, list, size, 0);
402#elif defined(HAVE_ATTROPEN)
403	ssize_t ret = -1;
404	int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
405	if (attrdirfd >= 0) {
406		ret = solaris_list_xattr(attrdirfd, list, size);
407		close(attrdirfd);
408	}
409	return ret;
410#else
411	errno = ENOSYS;
412	return -1;
413#endif
414}
415
416ssize_t sys_llistxattr (const char *path, char *list, size_t size)
417{
418#if defined(HAVE_LLISTXATTR)
419	ssize_t ret;
420
421	ret = llistxattr(path, list, size);
422	return remove_user(ret, list, size);
423#elif defined(HAVE_LISTXATTR) && defined(XATTR_ADD_OPT)
424	ssize_t ret;
425	int options = XATTR_NOFOLLOW;
426
427	ret = listxattr(path, list, size, options);
428	return remove_user(ret, list, size);
429
430#elif defined(HAVE_LLISTEA)
431	return llistea(path, list, size);
432#elif defined(HAVE_EXTATTR_LIST_LINK)
433	extattr_arg arg;
434	arg.path = path;
435	return bsd_attr_list(1, arg, list, size);
436#elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
437	return irix_attr_list(path, 0, list, size, ATTR_DONTFOLLOW);
438#elif defined(HAVE_ATTROPEN)
439	ssize_t ret = -1;
440	int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
441	if (attrdirfd >= 0) {
442		ret = solaris_list_xattr(attrdirfd, list, size);
443		close(attrdirfd);
444	}
445	return ret;
446#else
447	errno = ENOSYS;
448	return -1;
449#endif
450}
451
452int sys_removexattr (const char *path, const char *uname)
453{
454	const char *name = prefix(uname);
455#if defined(HAVE_REMOVEXATTR)
456#ifndef XATTR_ADD_OPT
457	return removexattr(path, name);
458#else
459	int options = 0;
460	return removexattr(path, name, options);
461#endif
462#elif defined(HAVE_REMOVEEA)
463	return removeea(path, name);
464#elif defined(HAVE_EXTATTR_DELETE_FILE)
465	return extattr_delete_file(path, EXTATTR_NAMESPACE_USER, uname);
466#elif defined(HAVE_ATTR_REMOVE)
467	int flags = 0;
468	char *attrname = strchr(name,'.') + 1;
469
470	if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
471
472	return attr_remove(path, attrname, flags);
473#elif defined(HAVE_ATTROPEN)
474	int ret = -1;
475	int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
476	if (attrdirfd >= 0) {
477		ret = solaris_unlinkat(attrdirfd, name);
478		close(attrdirfd);
479	}
480	return ret;
481#else
482	errno = ENOSYS;
483	return -1;
484#endif
485}
486
487int sys_lremovexattr (const char *path, const char *uname)
488{
489	const char *name = prefix(uname);
490#if defined(HAVE_LREMOVEXATTR)
491	return lremovexattr(path, name);
492#elif defined(HAVE_REMOVEXATTR) && defined(XATTR_ADD_OPT)
493	int options = XATTR_NOFOLLOW;
494	return removexattr(path, name, options);
495#elif defined(HAVE_LREMOVEEA)
496	return lremoveea(path, name);
497#elif defined(HAVE_EXTATTR_DELETE_LINK)
498	return extattr_delete_link(path, EXTATTR_NAMESPACE_USER, uname);
499#elif defined(HAVE_ATTR_REMOVE)
500	int flags = ATTR_DONTFOLLOW;
501	char *attrname = strchr(name,'.') + 1;
502
503	if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
504
505	return attr_remove(path, attrname, flags);
506#elif defined(HAVE_ATTROPEN)
507	int ret = -1;
508	int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
509	if (attrdirfd >= 0) {
510		ret = solaris_unlinkat(attrdirfd, name);
511		close(attrdirfd);
512	}
513	return ret;
514#else
515	errno = ENOSYS;
516	return -1;
517#endif
518}
519
520int sys_setxattr (const char *path, const char *uname, const void *value, size_t size, int flags)
521{
522	const char *name = prefix(uname);
523#if defined(HAVE_SETXATTR)
524#ifndef XATTR_ADD_OPT
525	return setxattr(path, name, value, size, flags);
526#else
527	int options = 0;
528	return setxattr(path, name, value, size, 0, options);
529#endif
530#elif defined(HAVE_SETEA)
531	return setea(path, name, value, size, flags);
532#elif defined(HAVE_EXTATTR_SET_FILE)
533	int retval = 0;
534	if (flags) {
535		/* Check attribute existence */
536		retval = extattr_get_file(path, EXTATTR_NAMESPACE_USER, uname, NULL, 0);
537		if (retval < 0) {
538			/* REPLACE attribute, that doesn't exist */
539			if (flags & XATTR_REPLACE && errno == ENOATTR) {
540				errno = ENOATTR;
541				return -1;
542			}
543			/* Ignore other errors */
544		}
545		else {
546			/* CREATE attribute, that already exists */
547			if (flags & XATTR_CREATE) {
548				errno = EEXIST;
549				return -1;
550			}
551		}
552	}
553	retval = extattr_set_file(path, EXTATTR_NAMESPACE_USER, uname, value, size);
554	return (retval < 0) ? -1 : 0;
555#elif defined(HAVE_ATTR_SET)
556	int myflags = 0;
557	char *attrname = strchr(name,'.') + 1;
558
559	if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
560	if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
561	if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
562
563	return attr_set(path, attrname, (const char *)value, size, myflags);
564#elif defined(HAVE_ATTROPEN)
565	int ret = -1;
566	int myflags = O_RDWR;
567	int attrfd;
568	if (flags & XATTR_CREATE) myflags |= O_EXCL;
569	if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
570	attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
571	if (attrfd >= 0) {
572		ret = solaris_write_xattr(attrfd, value, size);
573		close(attrfd);
574	}
575	return ret;
576#else
577	errno = ENOSYS;
578	return -1;
579#endif
580}
581
582int sys_lsetxattr (const char *path, const char *uname, const void *value, size_t size, int flags)
583{
584	const char *name = prefix(uname);
585#if defined(HAVE_LSETXATTR)
586	return lsetxattr(path, name, value, size, flags);
587#elif defined(HAVE_SETXATTR) && defined(XATTR_ADD_OPT)
588	int options = XATTR_NOFOLLOW;
589	return setxattr(path, name, value, size, 0, options);
590#elif defined(LSETEA)
591	return lsetea(path, name, value, size, flags);
592#elif defined(HAVE_EXTATTR_SET_LINK)
593	int retval = 0;
594	if (flags) {
595		/* Check attribute existence */
596		retval = extattr_get_link(path, EXTATTR_NAMESPACE_USER, uname, NULL, 0);
597		if (retval < 0) {
598			/* REPLACE attribute, that doesn't exist */
599			if (flags & XATTR_REPLACE && errno == ENOATTR) {
600				errno = ENOATTR;
601				return -1;
602			}
603			/* Ignore other errors */
604		}
605		else {
606			/* CREATE attribute, that already exists */
607			if (flags & XATTR_CREATE) {
608				errno = EEXIST;
609				return -1;
610			}
611		}
612	}
613
614	retval = extattr_set_link(path, EXTATTR_NAMESPACE_USER, uname, value, size);
615	return (retval < 0) ? -1 : 0;
616#elif defined(HAVE_ATTR_SET)
617	int myflags = ATTR_DONTFOLLOW;
618	char *attrname = strchr(name,'.') + 1;
619
620	if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
621	if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
622	if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
623
624	return attr_set(path, attrname, (const char *)value, size, myflags);
625#elif defined(HAVE_ATTROPEN)
626	int ret = -1;
627	int myflags = O_RDWR | AT_SYMLINK_NOFOLLOW;
628	int attrfd;
629	if (flags & XATTR_CREATE) myflags |= O_EXCL;
630	if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
631	attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
632	if (attrfd >= 0) {
633		ret = solaris_write_xattr(attrfd, value, size);
634		close(attrfd);
635	}
636	return ret;
637#else
638	errno = ENOSYS;
639	return -1;
640#endif
641}
642
643/**************************************************************************
644 helper functions for Solaris' EA support
645****************************************************************************/
646#ifdef HAVE_ATTROPEN
647static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size)
648{
649	struct stat sbuf;
650
651	if (fstat(attrfd, &sbuf) == -1) {
652		return -1;
653	}
654
655	/* This is to return the current size of the named extended attribute */
656	if (size == 0) {
657		return sbuf.st_size;
658	}
659
660	/* check size and read xattr */
661	if (sbuf.st_size > size) {
662		return -1;
663	}
664
665	return read(attrfd, value, sbuf.st_size);
666}
667
668static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size)
669{
670	ssize_t len = 0;
671	DIR *dirp;
672	struct dirent *de;
673	int newfd = dup(attrdirfd);
674	/* CAUTION: The originating file descriptor should not be
675	            used again following the call to fdopendir().
676	            For that reason we dup() the file descriptor
677		    here to make things more clear. */
678	dirp = fdopendir(newfd);
679
680	while ((de = readdir(dirp))) {
681		size_t listlen;
682		if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..") ||
683		     !strcmp(de->d_name, "SUNWattr_ro") || !strcmp(de->d_name, "SUNWattr_rw"))
684		{
685			/* we don't want "." and ".." here: */
686			LOG(log_maxdebug, logtype_default, "skipped EA %s\n",de->d_name);
687			continue;
688		}
689
690		listlen = strlen(de->d_name);
691		if (size == 0) {
692			/* return the current size of the list of extended attribute names*/
693			len += listlen + 1;
694		} else {
695			/* check size and copy entry + nul into list. */
696			if ((len + listlen + 1) > size) {
697				errno = ERANGE;
698				len = -1;
699				break;
700			} else {
701				strcpy(list + len, de->d_name);
702				len += listlen;
703				list[len] = '\0';
704				++len;
705			}
706		}
707	}
708
709	if (closedir(dirp) == -1) {
710		LOG(log_error, logtype_default, "closedir dirp: %s",strerror(errno));
711		return -1;
712	}
713	return len;
714}
715
716static int solaris_unlinkat(int attrdirfd, const char *name)
717{
718	if (unlinkat(attrdirfd, name, 0) == -1) {
719		return -1;
720	}
721	return 0;
722}
723
724static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode)
725{
726	return attropen(path, attrpath, oflag, mode);
727}
728
729static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode)
730{
731	int filedes = openat(fildes, path, oflag, mode);
732	if (filedes == -1) {
733		LOG(log_error, logtype_default, "openat(\"%s\"): %s",
734            path, strerror(errno));
735	}
736	return filedes;
737}
738
739static int solaris_write_xattr(int attrfd, const char *value, size_t size)
740{
741	if ((ftruncate(attrfd, 0) == 0) && (write(attrfd, value, size) == size)) {
742		return 0;
743	} else {
744		LOG(log_error, logtype_default, "solaris_write_xattr: %s",
745            strerror(errno));
746		return -1;
747	}
748}
749
750#endif /*HAVE_ATTROPEN*/
751
752