/*
- * $Id: volume.c,v 1.102 2009-11-13 00:27:36 didg Exp $
+ * $Id: volume.c,v 1.103 2009-11-17 12:33:29 franklahm Exp $
*
* Copyright (c) 1990,1993 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
} else if (optionok(tmp, "ea:", val)) {
if (strcasecmp(val + 1, "ad") == 0) /* the default anyway */
options[VOLOPT_EA_VFS].i_value = AFPVOL_EA_AD;
- else if (strcasecmp(val + 1, "solaris") == 0)
- options[VOLOPT_EA_VFS].i_value = AFPVOL_EA_SOLARIS;
+ else if (strcasecmp(val + 1, "sys") == 0)
+ options[VOLOPT_EA_VFS].i_value = AFPVOL_EA_SYS;
} else {
/* ignore unknown options */
/*
- $Id: ea.h,v 1.7 2009-11-17 11:41:37 franklahm Exp $
+ $Id: ea.h,v 1.8 2009-11-17 12:33:30 franklahm Exp $
Copyright (c) 2009 Frank Lahm <franklahm@gmail.com>
This program is free software; you can redistribute it and/or modify
extern int ea_chmod_file(VFS_FUNC_ARGS_SETFILEMODE);
extern int ea_chmod_dir(VFS_FUNC_ARGS_SETDIRUNIXMODE);
-/* Solaris native EAs */
-extern int sol_get_easize(VFS_FUNC_ARGS_EA_GETSIZE);
-extern int sol_get_eacontent(VFS_FUNC_ARGS_EA_GETCONTENT);
-extern int sol_list_eas(VFS_FUNC_ARGS_EA_LIST);
-extern int sol_set_ea(VFS_FUNC_ARGS_EA_SET);
-extern int sol_remove_ea(VFS_FUNC_ARGS_EA_REMOVE);
+/* native EAs */
+extern int sys_get_easize(VFS_FUNC_ARGS_EA_GETSIZE);
+extern int sys_get_eacontent(VFS_FUNC_ARGS_EA_GETCONTENT);
+extern int sys_list_eas(VFS_FUNC_ARGS_EA_LIST);
+extern int sys_set_ea(VFS_FUNC_ARGS_EA_SET);
+extern int sys_remove_ea(VFS_FUNC_ARGS_EA_REMOVE);
#endif /* ATALK_EA_H */
/*
- * $Id: volume.h,v 1.6 2009-11-13 00:27:38 didg Exp $
+ * $Id: volume.h,v 1.7 2009-11-17 12:33:30 franklahm Exp $
*
* Copyright (c) 1990,1994 Regents of The University of Michigan.
* All Rights Reserved. See COPYRIGHT.
/* Extended Attributes vfs indirection */
#define AFPVOL_EA_AD 0 /* Store them in adouble files. Default. */
-#define AFPVOL_EA_SOLARIS 1 /* Store them in native Solaris EAs */
+#define AFPVOL_EA_SYS 1 /* Store them in native EAs */
/* FPGetSrvrParms options */
#define AFPSRVR_CONFIGINFO (1 << 0)
noinst_LTLIBRARIES = libadouble.la
libadouble_la_SOURCES = ad_open.c ad_flush.c ad_read.c ad_write.c ad_size.c \
- ad_mmap.c ad_lock.c ad_date.c ad_attr.c ad_sendfile.c ad_ea.c
+ ad_mmap.c ad_lock.c ad_date.c ad_attr.c ad_sendfile.c
noinst_HEADERS = ad_private.h
+++ /dev/null
-/*
- Unix SMB/CIFS implementation.
- Samba system utilities
- Copyright (C) Andrew Tridgell 1992-1998
- Copyright (C) Jeremy Allison 1998-2005
- Copyright (C) Timur Bakeyev 2005
- Copyright (C) Bjoern Jacke 2006-2007
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- Samba 3.0.28, modified for netatalk.
- $Id: ad_ea.c,v 1.6 2009-11-17 11:41:37 franklahm Exp $
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <string.h>
-#include <sys/types.h>
-#include <errno.h>
-
-#if HAVE_ATTR_XATTR_H
-#include <attr/xattr.h>
-#elif HAVE_SYS_XATTR_H
-#include <sys/xattr.h>
-#endif
-
-#ifdef HAVE_SYS_EA_H
-#include <sys/ea.h>
-#endif
-
-#ifdef HAVE_ATTROPEN
-
-#include <dirent.h>
-#endif
-
-#ifdef HAVE_SYS_EXTATTR_H
-#include <sys/extattr.h>
-#endif
-
-#include <atalk/adouble.h>
-#include <atalk/util.h>
-#include <atalk/logger.h>
-#include <atalk/ea.h>
-
-/******** Solaris EA helper function prototypes ********/
-#ifdef HAVE_ATTROPEN
-#define SOLARIS_ATTRMODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP
-static int solaris_write_xattr(int attrfd, const char *value, size_t size);
-static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size);
-static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size);
-static int solaris_unlinkat(int attrdirfd, const char *name);
-static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode);
-static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode);
-#endif
-
-/**************************************************************************
- Wrappers for extented attribute calls. Based on the Linux package with
- support for IRIX and (Net|Free)BSD also. Expand as other systems have them.
-****************************************************************************/
-static char attr_name[256 +5] = "user.";
-
-static const char *prefix(const char *uname)
-{
-#if defined(HAVE_ATTROPEN)
- return uname;
-#else
- strlcpy(attr_name +5, uname, 256);
- return attr_name;
-#endif
-}
-
-ssize_t sys_getxattr (const char *path, const char *uname, void *value, size_t size)
-{
- const char *name = prefix(uname);
-
-#if defined(HAVE_GETXATTR)
-#ifndef XATTR_ADD_OPT
- return getxattr(path, name, value, size);
-#else
- int options = 0;
- return getxattr(path, name, value, size, 0, options);
-#endif
-#elif defined(HAVE_GETEA)
- return getea(path, name, value, size);
-#elif defined(HAVE_EXTATTR_GET_FILE)
- char *s;
- ssize_t retval;
- int attrnamespace = (strncmp(name, "system", 6) == 0) ?
- EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
- const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
- /*
- * The BSD implementation has a nasty habit of silently truncating
- * the returned value to the size of the buffer, so we have to check
- * that the buffer is large enough to fit the returned value.
- */
- if((retval=extattr_get_file(path, attrnamespace, attrname, NULL, 0)) >= 0) {
- if(retval > size) {
- errno = ERANGE;
- return -1;
- }
- if((retval=extattr_get_file(path, attrnamespace, attrname, value, size)) >= 0)
- return retval;
- }
-
- LOG(log_maxdebug, logtype_default, "sys_getxattr: extattr_get_file() failed with: %s\n", strerror(errno));
- return -1;
-#elif defined(HAVE_ATTR_GET)
- int retval, flags = 0;
- int valuelength = (int)size;
- char *attrname = strchr(name,'.') + 1;
-
- if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
-
- retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
-
- return retval ? retval : valuelength;
-#elif defined(HAVE_ATTROPEN)
- ssize_t ret = -1;
- int attrfd = solaris_attropen(path, name, O_RDONLY, 0);
- if (attrfd >= 0) {
- ret = solaris_read_xattr(attrfd, value, size);
- close(attrfd);
- }
- return ret;
-#else
- errno = ENOSYS;
- return -1;
-#endif
-}
-
-ssize_t sys_lgetxattr (const char *path, const char *uname, void *value, size_t size)
-{
- const char *name = prefix(uname);
-
-#if defined(HAVE_LGETXATTR)
- return lgetxattr(path, name, value, size);
-#elif defined(HAVE_GETXATTR) && defined(XATTR_ADD_OPT)
- int options = XATTR_NOFOLLOW;
- return getxattr(path, name, value, size, 0, options);
-#elif defined(HAVE_LGETEA)
- return lgetea(path, name, value, size);
-#elif defined(HAVE_EXTATTR_GET_LINK)
- char *s;
- ssize_t retval;
- int attrnamespace = (strncmp(name, "system", 6) == 0) ?
- EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
- const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
-
- if((retval=extattr_get_link(path, attrnamespace, attrname, NULL, 0)) >= 0) {
- if(retval > size) {
- errno = ERANGE;
- return -1;
- }
- if((retval=extattr_get_link(path, attrnamespace, attrname, value, size)) >= 0)
- return retval;
- }
-
- LOG(log_maxdebug, logtype_default, "sys_lgetxattr: extattr_get_link() failed with: %s\n", strerror(errno));
- return -1;
-#elif defined(HAVE_ATTR_GET)
- int retval, flags = ATTR_DONTFOLLOW;
- int valuelength = (int)size;
- char *attrname = strchr(name,'.') + 1;
-
- if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
-
- retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
-
- return retval ? retval : valuelength;
-#elif defined(HAVE_ATTROPEN)
- ssize_t ret = -1;
- int attrfd = solaris_attropen(path, name, O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
- if (attrfd >= 0) {
- ret = solaris_read_xattr(attrfd, value, size);
- close(attrfd);
- }
- return ret;
-#else
- errno = ENOSYS;
- return -1;
-#endif
-}
-
-#if defined(HAVE_EXTATTR_LIST_FILE)
-
-#define EXTATTR_PREFIX(s) (s), (sizeof((s))-1)
-
-static struct {
- int space;
- const char *name;
- size_t len;
-}
-extattr[] = {
- { EXTATTR_NAMESPACE_SYSTEM, EXTATTR_PREFIX("system.") },
- { EXTATTR_NAMESPACE_USER, EXTATTR_PREFIX("user.") },
-};
-
-typedef union {
- const char *path;
- int filedes;
-} extattr_arg;
-
-static ssize_t bsd_attr_list (int type, extattr_arg arg, char *list, size_t size)
-{
- ssize_t list_size, total_size = 0;
- int i, t, len;
- char *buf;
- /* Iterate through extattr(2) namespaces */
- for(t = 0; t < (sizeof(extattr)/sizeof(extattr[0])); t++) {
- switch(type) {
-#if defined(HAVE_EXTATTR_LIST_FILE)
- case 0:
- list_size = extattr_list_file(arg.path, extattr[t].space, list, size);
- break;
-#endif
-#if defined(HAVE_EXTATTR_LIST_LINK)
- case 1:
- list_size = extattr_list_link(arg.path, extattr[t].space, list, size);
- break;
-#endif
-#if defined(HAVE_EXTATTR_LIST_FD)
- case 2:
- list_size = extattr_list_fd(arg.filedes, extattr[t].space, list, size);
- break;
-#endif
- default:
- errno = ENOSYS;
- return -1;
- }
- /* Some error happend. Errno should be set by the previous call */
- if(list_size < 0)
- return -1;
- /* No attributes */
- if(list_size == 0)
- continue;
- /* XXX: Call with an empty buffer may be used to calculate
- necessary buffer size. Unfortunately, we can't say, how
- many attributes were returned, so here is the potential
- problem with the emulation.
- */
- if(list == NULL) {
- /* Take the worse case of one char attribute names -
- two bytes per name plus one more for sanity.
- */
- total_size += list_size + (list_size/2 + 1)*extattr[t].len;
- continue;
- }
- /* Count necessary offset to fit namespace prefixes */
- len = 0;
- for(i = 0; i < list_size; i += list[i] + 1)
- len += extattr[t].len;
-
- total_size += list_size + len;
- /* Buffer is too small to fit the results */
- if(total_size > size) {
- errno = ERANGE;
- return -1;
- }
- /* Shift results back, so we can prepend prefixes */
- buf = memmove(list + len, list, list_size);
-
- for(i = 0; i < list_size; i += len + 1) {
- len = buf[i];
- strncpy(list, extattr[t].name, extattr[t].len + 1);
- list += extattr[t].len;
- strncpy(list, buf + i + 1, len);
- list[len] = '\0';
- list += len + 1;
- }
- size -= total_size;
- }
- return total_size;
-}
-
-#endif
-
-#if defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
-static char attr_buffer[ATTR_MAX_VALUELEN];
-
-static ssize_t irix_attr_list(const char *path, int filedes, char *list, size_t size, int flags)
-{
- int retval = 0, index;
- attrlist_cursor_t *cursor = 0;
- int total_size = 0;
- attrlist_t * al = (attrlist_t *)attr_buffer;
- attrlist_ent_t *ae;
- size_t ent_size, left = size;
- char *bp = list;
-
- while (True) {
- if (filedes)
- retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
- else
- retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
- if (retval) break;
- for (index = 0; index < al->al_count; index++) {
- ae = ATTR_ENTRY(attr_buffer, index);
- ent_size = strlen(ae->a_name) + sizeof("user.");
- if (left >= ent_size) {
- strncpy(bp, "user.", sizeof("user."));
- strncat(bp, ae->a_name, ent_size - sizeof("user."));
- bp += ent_size;
- left -= ent_size;
- } else if (size) {
- errno = ERANGE;
- retval = -1;
- break;
- }
- total_size += ent_size;
- }
- if (al->al_more == 0) break;
- }
- if (retval == 0) {
- flags |= ATTR_ROOT;
- cursor = 0;
- while (True) {
- if (filedes)
- retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
- else
- retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
- if (retval) break;
- for (index = 0; index < al->al_count; index++) {
- ae = ATTR_ENTRY(attr_buffer, index);
- ent_size = strlen(ae->a_name) + sizeof("system.");
- if (left >= ent_size) {
- strncpy(bp, "system.", sizeof("system."));
- strncat(bp, ae->a_name, ent_size - sizeof("system."));
- bp += ent_size;
- left -= ent_size;
- } else if (size) {
- errno = ERANGE;
- retval = -1;
- break;
- }
- total_size += ent_size;
- }
- if (al->al_more == 0) break;
- }
- }
- return (ssize_t)(retval ? retval : total_size);
-}
-
-#endif
-
-#if defined(HAVE_LISTXATTR)
-static ssize_t remove_user(ssize_t ret, char *list, size_t size)
-{
- size_t len;
- char *ptr;
- char *ptr1;
- ssize_t ptrsize;
-
- if (ret <= 0 || size == 0)
- return ret;
- ptrsize = ret;
- ptr = ptr1 = list;
- while (ptrsize > 0) {
- len = strlen(ptr1) +1;
- ptrsize -= len;
- if (strncmp(ptr1, "user.",5)) {
- ptr1 += len;
- continue;
- }
- memmove(ptr, ptr1 +5, len -5);
- ptr += len -5;
- ptr1 += len;
- }
- return ptr -list;
-}
-#endif
-
-ssize_t sys_listxattr (const char *path, char *list, size_t size)
-{
-#if defined(HAVE_LISTXATTR)
- ssize_t ret;
-
-#ifndef XATTR_ADD_OPT
- ret = listxattr(path, list, size);
-#else
- int options = 0;
- ret = listxattr(path, list, size, options);
-#endif
- return remove_user(ret, list, size);
-
-#elif defined(HAVE_LISTEA)
- return listea(path, list, size);
-#elif defined(HAVE_EXTATTR_LIST_FILE)
- extattr_arg arg;
- arg.path = path;
- return bsd_attr_list(0, arg, list, size);
-#elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
- return irix_attr_list(path, 0, list, size, 0);
-#elif defined(HAVE_ATTROPEN)
- ssize_t ret = -1;
- int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
- if (attrdirfd >= 0) {
- ret = solaris_list_xattr(attrdirfd, list, size);
- close(attrdirfd);
- }
- return ret;
-#else
- errno = ENOSYS;
- return -1;
-#endif
-}
-
-ssize_t sys_llistxattr (const char *path, char *list, size_t size)
-{
-#if defined(HAVE_LLISTXATTR)
- ssize_t ret;
-
- ret = llistxattr(path, list, size);
- return remove_user(ret, list, size);
-#elif defined(HAVE_LISTXATTR) && defined(XATTR_ADD_OPT)
- ssize_t ret;
- int options = XATTR_NOFOLLOW;
-
- ret = listxattr(path, list, size, options);
- return remove_user(ret, list, size);
-
-#elif defined(HAVE_LLISTEA)
- return llistea(path, list, size);
-#elif defined(HAVE_EXTATTR_LIST_LINK)
- extattr_arg arg;
- arg.path = path;
- return bsd_attr_list(1, arg, list, size);
-#elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
- return irix_attr_list(path, 0, list, size, ATTR_DONTFOLLOW);
-#elif defined(HAVE_ATTROPEN)
- ssize_t ret = -1;
- int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
- if (attrdirfd >= 0) {
- ret = solaris_list_xattr(attrdirfd, list, size);
- close(attrdirfd);
- }
- return ret;
-#else
- errno = ENOSYS;
- return -1;
-#endif
-}
-
-int sys_removexattr (const char *path, const char *uname)
-{
- const char *name = prefix(uname);
-#if defined(HAVE_REMOVEXATTR)
-#ifndef XATTR_ADD_OPT
- return removexattr(path, name);
-#else
- int options = 0;
- return removexattr(path, name, options);
-#endif
-#elif defined(HAVE_REMOVEEA)
- return removeea(path, name);
-#elif defined(HAVE_EXTATTR_DELETE_FILE)
- char *s;
- int attrnamespace = (strncmp(name, "system", 6) == 0) ?
- EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
- const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
-
- return extattr_delete_file(path, attrnamespace, attrname);
-#elif defined(HAVE_ATTR_REMOVE)
- int flags = 0;
- char *attrname = strchr(name,'.') + 1;
-
- if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
-
- return attr_remove(path, attrname, flags);
-#elif defined(HAVE_ATTROPEN)
- int ret = -1;
- int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
- if (attrdirfd >= 0) {
- ret = solaris_unlinkat(attrdirfd, name);
- close(attrdirfd);
- }
- return ret;
-#else
- errno = ENOSYS;
- return -1;
-#endif
-}
-
-int sys_lremovexattr (const char *path, const char *uname)
-{
- const char *name = prefix(uname);
-#if defined(HAVE_LREMOVEXATTR)
- return lremovexattr(path, name);
-#elif defined(HAVE_REMOVEXATTR) && defined(XATTR_ADD_OPT)
- int options = XATTR_NOFOLLOW;
- return removexattr(path, name, options);
-#elif defined(HAVE_LREMOVEEA)
- return lremoveea(path, name);
-#elif defined(HAVE_EXTATTR_DELETE_LINK)
- char *s;
- int attrnamespace = (strncmp(name, "system", 6) == 0) ?
- EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
- const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
-
- return extattr_delete_link(path, attrnamespace, attrname);
-#elif defined(HAVE_ATTR_REMOVE)
- int flags = ATTR_DONTFOLLOW;
- char *attrname = strchr(name,'.') + 1;
-
- if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
-
- return attr_remove(path, attrname, flags);
-#elif defined(HAVE_ATTROPEN)
- int ret = -1;
- int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
- if (attrdirfd >= 0) {
- ret = solaris_unlinkat(attrdirfd, name);
- close(attrdirfd);
- }
- return ret;
-#else
- errno = ENOSYS;
- return -1;
-#endif
-}
-
-int sys_setxattr (const char *path, const char *uname, const void *value, size_t size, int flags)
-{
- const char *name = prefix(uname);
-#if defined(HAVE_SETXATTR)
-#ifndef XATTR_ADD_OPT
- return setxattr(path, name, value, size, flags);
-#else
- int options = 0;
- return setxattr(path, name, value, size, 0, options);
-#endif
-#elif defined(HAVE_SETEA)
- return setea(path, name, value, size, flags);
-#elif defined(HAVE_EXTATTR_SET_FILE)
- char *s;
- int retval = 0;
- int attrnamespace = (strncmp(name, "system", 6) == 0) ?
- EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
- const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
- if (flags) {
- /* Check attribute existence */
- retval = extattr_get_file(path, attrnamespace, attrname, NULL, 0);
- if (retval < 0) {
- /* REPLACE attribute, that doesn't exist */
- if (flags & XATTR_REPLACE && errno == ENOATTR) {
- errno = ENOATTR;
- return -1;
- }
- /* Ignore other errors */
- }
- else {
- /* CREATE attribute, that already exists */
- if (flags & XATTR_CREATE) {
- errno = EEXIST;
- return -1;
- }
- }
- }
- retval = extattr_set_file(path, attrnamespace, attrname, value, size);
- return (retval < 0) ? -1 : 0;
-#elif defined(HAVE_ATTR_SET)
- int myflags = 0;
- char *attrname = strchr(name,'.') + 1;
-
- if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
- if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
- if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
-
- return attr_set(path, attrname, (const char *)value, size, myflags);
-#elif defined(HAVE_ATTROPEN)
- int ret = -1;
- int myflags = O_RDWR;
- int attrfd;
- if (flags & XATTR_CREATE) myflags |= O_EXCL;
- if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
- attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
- if (attrfd >= 0) {
- ret = solaris_write_xattr(attrfd, value, size);
- close(attrfd);
- }
- return ret;
-#else
- errno = ENOSYS;
- return -1;
-#endif
-}
-
-int sys_lsetxattr (const char *path, const char *uname, const void *value, size_t size, int flags)
-{
- const char *name = prefix(uname);
-#if defined(HAVE_LSETXATTR)
- return lsetxattr(path, name, value, size, flags);
-#elif defined(HAVE_SETXATTR) && defined(XATTR_ADD_OPT)
- int options = XATTR_NOFOLLOW;
- return setxattr(path, name, value, size, 0, options);
-#elif defined(LSETEA)
- return lsetea(path, name, value, size, flags);
-#elif defined(HAVE_EXTATTR_SET_LINK)
- char *s;
- int retval = 0;
- int attrnamespace = (strncmp(name, "system", 6) == 0) ?
- EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
- const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
- if (flags) {
- /* Check attribute existence */
- retval = extattr_get_link(path, attrnamespace, attrname, NULL, 0);
- if (retval < 0) {
- /* REPLACE attribute, that doesn't exist */
- if (flags & XATTR_REPLACE && errno == ENOATTR) {
- errno = ENOATTR;
- return -1;
- }
- /* Ignore other errors */
- }
- else {
- /* CREATE attribute, that already exists */
- if (flags & XATTR_CREATE) {
- errno = EEXIST;
- return -1;
- }
- }
- }
-
- retval = extattr_set_link(path, attrnamespace, attrname, value, size);
- return (retval < 0) ? -1 : 0;
-#elif defined(HAVE_ATTR_SET)
- int myflags = ATTR_DONTFOLLOW;
- char *attrname = strchr(name,'.') + 1;
-
- if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
- if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
- if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
-
- return attr_set(path, attrname, (const char *)value, size, myflags);
-#elif defined(HAVE_ATTROPEN)
- int ret = -1;
- int myflags = O_RDWR | AT_SYMLINK_NOFOLLOW;
- int attrfd;
- if (flags & XATTR_CREATE) myflags |= O_EXCL;
- if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
- attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
- if (attrfd >= 0) {
- ret = solaris_write_xattr(attrfd, value, size);
- close(attrfd);
- }
- return ret;
-#else
- errno = ENOSYS;
- return -1;
-#endif
-}
-
-/**************************************************************************
- helper functions for Solaris' EA support
-****************************************************************************/
-#ifdef HAVE_ATTROPEN
-static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size)
-{
- struct stat sbuf;
-
- if (fstat(attrfd, &sbuf) == -1) {
- return -1;
- }
-
- /* This is to return the current size of the named extended attribute */
- if (size == 0) {
- return sbuf.st_size;
- }
-
- /* check size and read xattr */
- if (sbuf.st_size > size) {
- return -1;
- }
-
- return read(attrfd, value, sbuf.st_size);
-}
-
-static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size)
-{
- ssize_t len = 0;
- int stop = 0;
- DIR *dirp;
- struct dirent *de;
- int newfd = dup(attrdirfd);
- /* CAUTION: The originating file descriptor should not be
- used again following the call to fdopendir().
- For that reason we dup() the file descriptor
- here to make things more clear. */
- dirp = fdopendir(newfd);
-
- while ((de = readdir(dirp))) {
- size_t listlen;
- if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..") ||
- !strcmp(de->d_name, "SUNWattr_ro") || !strcmp(de->d_name, "SUNWattr_rw"))
- {
- /* we don't want "." and ".." here: */
- LOG(log_maxdebug, logtype_default, "skipped EA %s\n",de->d_name);
- continue;
- }
-
- listlen = strlen(de->d_name);
- if (size == 0) {
- /* return the current size of the list of extended attribute names*/
- len += listlen + 1;
- } else {
- /* check size and copy entry + nul into list. */
- if ((len + listlen + 1) > size) {
- errno = ERANGE;
- len = -1;
- break;
- } else {
- strcpy(list + len, de->d_name);
- len += listlen;
- list[len] = '\0';
- ++len;
- }
- }
- }
-
- if (closedir(dirp) == -1) {
- LOG(log_debug, logtype_default, "closedir dirp failed: %s\n",strerror(errno));
- return -1;
- }
- return len;
-}
-
-static int solaris_unlinkat(int attrdirfd, const char *name)
-{
- if (unlinkat(attrdirfd, name, 0) == -1) {
- return -1;
- }
- return 0;
-}
-
-static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode)
-{
- int filedes = attropen(path, attrpath, oflag, mode);
- if (filedes == -1) {
- LOG(log_maxdebug, logtype_default, "attropen FAILED: path: %s, name: %s, errno: %s\n",path,attrpath,strerror(errno));
- }
- return filedes;
-}
-
-static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode)
-{
- int filedes = openat(fildes, path, oflag, mode);
- if (filedes == -1) {
- LOG(log_maxdebug, logtype_default, "openat FAILED: fd: %s, path: %s, errno: %s\n",filedes,path,strerror(errno));
- }
- return filedes;
-}
-
-static int solaris_write_xattr(int attrfd, const char *value, size_t size)
-{
- if ((ftruncate(attrfd, 0) == 0) && (write(attrfd, value, size) == size)) {
- return 0;
- } else {
- LOG(log_maxdebug, logtype_default, "solaris_write_xattr FAILED!\n");
- return -1;
- }
-}
-#endif /*HAVE_ATTROPEN*/
-
+
# Makefile.am for libatalk/adouble/
noinst_LTLIBRARIES = libvfs.la
-libvfs_la_SOURCES = vfs.c unix.c ea.c
+libvfs_la_SOURCES = vfs.c unix.c ea.c sys_ea.c ea_sys.c
if USE_NFSv4_ACLS
libvfs_la_SOURCES += acl.c
endif
-
-libvfs_la_SOURCES += ea_solaris.c
+++ /dev/null
-/*
- $Id: ea_solaris.c,v 1.4 2009-11-13 13:03:29 didg Exp $
- Copyright (c) 2009 Frank Lahm <franklahm@gmail.com>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-*/
-
-/* According to man fsattr.5 we must define _ATFILE_SOURCE */
-#define _ATFILE_SOURCE
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif /* HAVE_CONFIG_H */
-
-#include <unistd.h>
-#include <stdint.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <dirent.h>
-
-#if HAVE_ATTR_XATTR_H
-#include <attr/xattr.h>
-#elif HAVE_SYS_XATTR_H
-#include <sys/xattr.h>
-#endif
-
-#ifdef HAVE_SYS_EA_H
-#include <sys/ea.h>
-#endif
-
-#ifdef HAVE_SYS_EXTATTR_H
-#include <sys/extattr.h>
-#endif
-
-#include <atalk/adouble.h>
-#include <atalk/ea.h>
-#include <atalk/afp.h>
-#include <atalk/logger.h>
-#include <atalk/volume.h>
-#include <atalk/vfs.h>
-#include <atalk/util.h>
-#include <atalk/unix.h>
-
-
-/**********************************************************************************
- * Solaris EA VFS funcs
- **********************************************************************************/
-
-/*
- * Function: sol_get_easize
- *
- * Purpose: get size of an EA on Solaris native EA
- *
- * Arguments:
- *
- * vol (r) current volume
- * rbuf (w) DSI reply buffer
- * rbuflen (rw) current length of data in reply buffer
- * uname (r) filename
- * oflag (r) link and create flag
- * attruname (r) name of attribute
- *
- * Returns: AFP code: AFP_OK on success or appropiate AFP error code
- *
- * Effects:
- *
- * Copies EA size into rbuf in network order. Increments *rbuflen +4.
- */
-int sol_get_easize(VFS_FUNC_ARGS_EA_GETSIZE)
-{
- ssize_t ret;
- uint32_t attrsize;
-
- LOG(log_debug7, logtype_afpd, "sol_getextattr_size(%s): attribute: \"%s\"", uname, attruname);
-
- if ((oflag & O_NOFOLLOW) ) {
- ret = sys_lgetxattr(uname, attruname, rbuf +4, 0);
- }
- else {
- ret = sys_getxattr(uname, attruname, rbuf +4, 0);
- }
-
- if (ret == -1) switch(errno) {
- case ELOOP:
- /* its a symlink and client requested O_NOFOLLOW */
- LOG(log_debug, logtype_afpd, "sol_getextattr_size(%s): encountered symlink with kXAttrNoFollow", uname);
-
- memset(rbuf, 0, 4);
- *rbuflen += 4;
-
- return AFP_OK;
- default:
- LOG(log_error, logtype_afpd, "sol_getextattr_size: error: %s", strerror(errno));
- return AFPERR_MISC;
- }
-
- if (ret > MAX_EA_SIZE)
- ret = MAX_EA_SIZE;
-
- /* Start building reply packet */
- LOG(log_debug7, logtype_afpd, "sol_getextattr_size(%s): attribute: \"%s\", size: %u", uname, attruname, ret);
-
- /* length of attribute data */
- attrsize = htonl((uint32_t)ret);
- memcpy(rbuf, &attrsize, 4);
- *rbuflen += 4;
-
- ret = AFP_OK;
- return ret;
-}
-
-/*
- * Function: sol_get_eacontent
- *
- * Purpose: copy Solaris native EA into rbuf
- *
- * Arguments:
- *
- * vol (r) current volume
- * rbuf (w) DSI reply buffer
- * rbuflen (rw) current length of data in reply buffer
- * uname (r) filename
- * oflag (r) link and create flag
- * attruname (r) name of attribute
- * maxreply (r) maximum EA size as of current specs/real-life
- *
- * Returns: AFP code: AFP_OK on success or appropiate AFP error code
- *
- * Effects:
- *
- * Copies EA into rbuf. Increments *rbuflen accordingly.
- */
-int sol_get_eacontent(VFS_FUNC_ARGS_EA_GETCONTENT)
-{
- ssize_t ret;
- uint32_t attrsize;
-
- /* Start building reply packet */
-
- maxreply -= MAX_REPLY_EXTRA_BYTES;
-
- if (maxreply > MAX_EA_SIZE)
- maxreply = MAX_EA_SIZE;
-
- LOG(log_debug7, logtype_afpd, "sol_getextattr_content(%s): attribute: \"%s\", size: %u", uname, attruname, maxreply);
-
- if ((oflag & O_NOFOLLOW) ) {
- ret = sys_lgetxattr(uname, attruname, rbuf +4, maxreply);
- }
- else {
- ret = sys_getxattr(uname, attruname, rbuf +4, maxreply);
- }
-
- if (ret == -1) switch(errno) {
- case ELOOP:
- /* its a symlink and client requested O_NOFOLLOW */
- LOG(log_debug, logtype_afpd, "sol_getextattr_content(%s): encountered symlink with kXAttrNoFollow", uname);
-
- memset(rbuf, 0, 4);
- *rbuflen += 4;
-
- return AFP_OK;
- default:
- LOG(log_error, logtype_afpd, "sol_getextattr_content(%s): error: %s", attruname, strerror(errno));
- return AFPERR_MISC;
- }
-
- /* remember where we must store length of attribute data in rbuf */
- *rbuflen += 4 +ret;
-
- attrsize = htonl((uint32_t)ret);
- memcpy(rbuf, &attrsize, 4);
-
- return AFP_OK;
-}
-
-/*
- * Function: sol_list_eas
- *
- * Purpose: copy names of Solaris native EA into attrnamebuf
- *
- * Arguments:
- *
- * vol (r) current volume
- * attrnamebuf (w) store names a consecutive C strings here
- * buflen (rw) length of names in attrnamebuf
- * uname (r) filename
- * oflag (r) link and create flag
- *
- * Returns: AFP code: AFP_OK on success or appropiate AFP error code
- *
- * Effects:
- *
- * Copies names of all EAs of uname as consecutive C strings into rbuf.
- * Increments *rbuflen accordingly.
- */
-int sol_list_eas(VFS_FUNC_ARGS_EA_LIST)
-{
- ssize_t attrbuflen = *buflen;
- int ret, len, nlen;
- char *buf;
- char *ptr;
-
- buf = malloc(ATTRNAMEBUFSIZ);
- if (!buf)
- return AFPERR_MISC;
-
- if ((oflag & O_NOFOLLOW)) {
- ret = sys_llistxattr(uname, buf, ATTRNAMEBUFSIZ);
- }
- else {
- ret = sys_listxattr(uname, buf, ATTRNAMEBUFSIZ);
- }
-
- if (ret == -1) switch(errno) {
- case ELOOP:
- /* its a symlink and client requested O_NOFOLLOW */
- ret = AFPERR_BADTYPE;
- default:
- LOG(log_error, logtype_afpd, "sol_list_extattr(%s): error opening atttribute dir: %s", uname, strerror(errno));
- ret= AFPERR_MISC;
- }
-
- ptr = buf;
- while (ret > 0) {
- len = strlen(ptr);
-
- /* Convert name to CH_UTF8_MAC and directly store in in the reply buffer */
- if ( 0 >= ( nlen = convert_string(vol->v_volcharset, CH_UTF8_MAC, ptr, len, attrnamebuf + attrbuflen, 256)) ) {
- ret = AFPERR_MISC;
- goto exit;
- }
-
- LOG(log_debug7, logtype_afpd, "sol_list_extattr(%s): attribute: %s", uname, ptr);
-
- attrbuflen += nlen + 1;
- if (attrbuflen > (ATTRNAMEBUFSIZ - 256)) {
- /* Next EA name could overflow, so bail out with error.
- FIXME: evantually malloc/memcpy/realloc whatever.
- Is it worth it ? */
- LOG(log_warning, logtype_afpd, "sol_list_extattr(%s): running out of buffer for EA names", uname);
- ret = AFPERR_MISC;
- goto exit;
- }
- ret -= len +1;
- ptr += len +1;
- }
-
- ret = AFP_OK;
-
-exit:
- free(buf);
- *buflen = attrbuflen;
- return ret;
-}
-
-/*
- * Function: sol_set_ea
- *
- * Purpose: set a native EA
- *
- * Arguments:
- *
- * vol (r) current volume
- * uname (r) filename
- * attruname (r) EA name
- * ibuf (r) buffer with EA content
- * attrsize (r) length EA in ibuf
- * oflag (r) link and create flag
- *
- * Returns: AFP code: AFP_OK on success or appropiate AFP error code
- *
- * Effects:
- *
- */
-int sol_set_ea(VFS_FUNC_ARGS_EA_SET)
-{
- int attr_flag;
- int ret;
-
- attr_flag = 0;
- if ((oflag & O_CREAT) )
- attr_flag |= XATTR_CREATE;
-
- else if ((oflag & O_TRUNC) )
- attr_flag |= XATTR_REPLACE;
-
- if ((oflag & O_NOFOLLOW) ) {
- ret = sys_lsetxattr(uname, attruname, ibuf, attrsize,attr_flag);
- }
- else {
- ret = sys_setxattr(uname, attruname, ibuf, attrsize, attr_flag);
- }
-
- if (ret == -1) switch(errno) {
- case ELOOP:
- /* its a symlink and client requested O_NOFOLLOW */
- LOG(log_debug, logtype_afpd, "afp_setextattr(%s): encountered symlink with kXAttrNoFollow", uname);
- return AFP_OK;
- default:
- LOG(log_error, logtype_afpd, "afp_setextattr(%s): read error: %s", attruname, strerror(errno));
- return AFPERR_MISC;
- }
-
- return AFP_OK;
-}
-
-/*
- * Function: sol_remove_ea
- *
- * Purpose: remove a native EA
- *
- * Arguments:
- *
- * vol (r) current volume
- * uname (r) filename
- * attruname (r) EA name
- * oflag (r) link and create flag
- *
- * Returns: AFP code: AFP_OK on success or appropiate AFP error code
- *
- * Effects:
- *
- * Removes EA attruname from file uname.
- */
-int sol_remove_ea(VFS_FUNC_ARGS_EA_REMOVE)
-{
- int ret;
-
- if ((oflag & O_NOFOLLOW) ) {
- ret = sys_lremovexattr(uname, attruname);
- }
- else {
- ret = sys_removexattr(uname, attruname);
- }
-
- if (ret == -1) switch(errno) {
- case ELOOP:
- /* its a symlink and client requested O_NOFOLLOW */
- LOG(log_debug, logtype_afpd, "afp_remextattr(%s): encountered symlink with kXAttrNoFollow", uname);
- return AFP_OK;
- case EACCES:
- LOG(log_debug, logtype_afpd, "afp_remextattr(%s): unlinkat error: %s", uname, strerror(errno));
- return AFPERR_ACCESS;
- default:
- LOG(log_error, logtype_afpd, "afp_remextattr(%s): attropen error: %s", uname, strerror(errno));
- return AFPERR_MISC;
- }
- return AFP_OK;
-}
--- /dev/null
+/*
+ $Id: ea_sys.c,v 1.1 2009-11-17 12:33:30 franklahm Exp $
+ Copyright (c) 2009 Frank Lahm <franklahm@gmail.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+#include <unistd.h>
+#include <stdint.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <dirent.h>
+
+#if HAVE_ATTR_XATTR_H
+#include <attr/xattr.h>
+#elif HAVE_SYS_XATTR_H
+#include <sys/xattr.h>
+#endif
+
+#ifdef HAVE_SYS_EA_H
+#include <sys/ea.h>
+#endif
+
+#ifdef HAVE_SYS_EXTATTR_H
+#include <sys/extattr.h>
+#endif
+
+#include <atalk/adouble.h>
+#include <atalk/ea.h>
+#include <atalk/afp.h>
+#include <atalk/logger.h>
+#include <atalk/volume.h>
+#include <atalk/vfs.h>
+#include <atalk/util.h>
+#include <atalk/unix.h>
+
+
+/**********************************************************************************
+ * EA VFS funcs for storing EAs in nativa filesystem EAs
+ **********************************************************************************/
+
+/*
+ * Function: sys_get_easize
+ *
+ * Purpose: get size of a native EA
+ *
+ * Arguments:
+ *
+ * vol (r) current volume
+ * rbuf (w) DSI reply buffer
+ * rbuflen (rw) current length of data in reply buffer
+ * uname (r) filename
+ * oflag (r) link and create flag
+ * attruname (r) name of attribute
+ *
+ * Returns: AFP code: AFP_OK on success or appropiate AFP error code
+ *
+ * Effects:
+ *
+ * Copies EA size into rbuf in network order. Increments *rbuflen +4.
+ */
+int sys_get_easize(VFS_FUNC_ARGS_EA_GETSIZE)
+{
+ ssize_t ret;
+ uint32_t attrsize;
+
+ LOG(log_debug7, logtype_afpd, "sys_getextattr_size(%s): attribute: \"%s\"", uname, attruname);
+
+ if ((oflag & O_NOFOLLOW) ) {
+ ret = sys_lgetxattr(uname, attruname, rbuf +4, 0);
+ }
+ else {
+ ret = sys_getxattr(uname, attruname, rbuf +4, 0);
+ }
+
+ if (ret == -1) {
+ switch(errno) {
+ case ELOOP:
+ /* its a symlink and client requested O_NOFOLLOW */
+ LOG(log_debug, logtype_afpd, "sys_getextattr_size(%s): encountered symlink with kXAttrNoFollow", uname);
+
+ memset(rbuf, 0, 4);
+ *rbuflen += 4;
+
+ return AFP_OK;
+ default:
+ LOG(log_error, logtype_afpd, "sys_getextattr_size: error: %s", strerror(errno));
+ return AFPERR_MISC;
+ }
+ }
+
+ if (ret > MAX_EA_SIZE)
+ ret = MAX_EA_SIZE;
+
+ /* Start building reply packet */
+ LOG(log_debug7, logtype_afpd, "sys_getextattr_size(%s): attribute: \"%s\", size: %u", uname, attruname, ret);
+
+ /* length of attribute data */
+ attrsize = htonl((uint32_t)ret);
+ memcpy(rbuf, &attrsize, 4);
+ *rbuflen += 4;
+
+ ret = AFP_OK;
+ return ret;
+}
+
+/*
+ * Function: sys_get_eacontent
+ *
+ * Purpose: copy native EA into rbuf
+ *
+ * Arguments:
+ *
+ * vol (r) current volume
+ * rbuf (w) DSI reply buffer
+ * rbuflen (rw) current length of data in reply buffer
+ * uname (r) filename
+ * oflag (r) link and create flag
+ * attruname (r) name of attribute
+ * maxreply (r) maximum EA size as of current specs/real-life
+ *
+ * Returns: AFP code: AFP_OK on success or appropiate AFP error code
+ *
+ * Effects:
+ *
+ * Copies EA into rbuf. Increments *rbuflen accordingly.
+ */
+int sys_get_eacontent(VFS_FUNC_ARGS_EA_GETCONTENT)
+{
+ ssize_t ret;
+ uint32_t attrsize;
+
+ /* Start building reply packet */
+
+ maxreply -= MAX_REPLY_EXTRA_BYTES;
+
+ if (maxreply > MAX_EA_SIZE)
+ maxreply = MAX_EA_SIZE;
+
+ LOG(log_debug7, logtype_afpd, "sys_getextattr_content(%s): attribute: \"%s\", size: %u", uname, attruname, maxreply);
+
+ if ((oflag & O_NOFOLLOW) ) {
+ ret = sys_lgetxattr(uname, attruname, rbuf +4, maxreply);
+ }
+ else {
+ ret = sys_getxattr(uname, attruname, rbuf +4, maxreply);
+ }
+
+ if (ret == -1) switch(errno) {
+ case ELOOP:
+ /* its a symlink and client requested O_NOFOLLOW */
+ LOG(log_debug, logtype_afpd, "sys_getextattr_content(%s): encountered symlink with kXAttrNoFollow", uname);
+
+ memset(rbuf, 0, 4);
+ *rbuflen += 4;
+
+ return AFP_OK;
+ default:
+ LOG(log_error, logtype_afpd, "sys_getextattr_content(%s): error: %s", attruname, strerror(errno));
+ return AFPERR_MISC;
+ }
+
+ /* remember where we must store length of attribute data in rbuf */
+ *rbuflen += 4 +ret;
+
+ attrsize = htonl((uint32_t)ret);
+ memcpy(rbuf, &attrsize, 4);
+
+ return AFP_OK;
+}
+
+/*
+ * Function: sys_list_eas
+ *
+ * Purpose: copy names of native EAs into attrnamebuf
+ *
+ * Arguments:
+ *
+ * vol (r) current volume
+ * attrnamebuf (w) store names a consecutive C strings here
+ * buflen (rw) length of names in attrnamebuf
+ * uname (r) filename
+ * oflag (r) link and create flag
+ *
+ * Returns: AFP code: AFP_OK on success or appropiate AFP error code
+ *
+ * Effects:
+ *
+ * Copies names of all EAs of uname as consecutive C strings into rbuf.
+ * Increments *rbuflen accordingly.
+ */
+int sys_list_eas(VFS_FUNC_ARGS_EA_LIST)
+{
+ ssize_t attrbuflen = *buflen;
+ int ret, len, nlen;
+ char *buf;
+ char *ptr;
+
+ buf = malloc(ATTRNAMEBUFSIZ);
+ if (!buf)
+ return AFPERR_MISC;
+
+ if ((oflag & O_NOFOLLOW)) {
+ ret = sys_llistxattr(uname, buf, ATTRNAMEBUFSIZ);
+ }
+ else {
+ ret = sys_listxattr(uname, buf, ATTRNAMEBUFSIZ);
+ }
+
+ if (ret == -1) switch(errno) {
+ case ELOOP:
+ /* its a symlink and client requested O_NOFOLLOW */
+ ret = AFPERR_BADTYPE;
+ default:
+ LOG(log_error, logtype_afpd, "sys_list_extattr(%s): error opening atttribute dir: %s", uname, strerror(errno));
+ ret= AFPERR_MISC;
+ }
+
+ ptr = buf;
+ while (ret > 0) {
+ len = strlen(ptr);
+
+ /* Convert name to CH_UTF8_MAC and directly store in in the reply buffer */
+ if ( 0 >= ( nlen = convert_string(vol->v_volcharset, CH_UTF8_MAC, ptr, len, attrnamebuf + attrbuflen, 256)) ) {
+ ret = AFPERR_MISC;
+ goto exit;
+ }
+
+ LOG(log_debug7, logtype_afpd, "sys_list_extattr(%s): attribute: %s", uname, ptr);
+
+ attrbuflen += nlen + 1;
+ if (attrbuflen > (ATTRNAMEBUFSIZ - 256)) {
+ /* Next EA name could overflow, so bail out with error.
+ FIXME: evantually malloc/memcpy/realloc whatever.
+ Is it worth it ? */
+ LOG(log_warning, logtype_afpd, "sys_list_extattr(%s): running out of buffer for EA names", uname);
+ ret = AFPERR_MISC;
+ goto exit;
+ }
+ ret -= len +1;
+ ptr += len +1;
+ }
+
+ ret = AFP_OK;
+
+exit:
+ free(buf);
+ *buflen = attrbuflen;
+ return ret;
+}
+
+/*
+ * Function: sys_set_ea
+ *
+ * Purpose: set a native EA
+ *
+ * Arguments:
+ *
+ * vol (r) current volume
+ * uname (r) filename
+ * attruname (r) EA name
+ * ibuf (r) buffer with EA content
+ * attrsize (r) length EA in ibuf
+ * oflag (r) link and create flag
+ *
+ * Returns: AFP code: AFP_OK on success or appropiate AFP error code
+ *
+ * Effects:
+ *
+ */
+int sys_set_ea(VFS_FUNC_ARGS_EA_SET)
+{
+ int attr_flag;
+ int ret;
+
+ attr_flag = 0;
+ if ((oflag & O_CREAT) )
+ attr_flag |= XATTR_CREATE;
+
+ else if ((oflag & O_TRUNC) )
+ attr_flag |= XATTR_REPLACE;
+
+ if ((oflag & O_NOFOLLOW) ) {
+ ret = sys_lsetxattr(uname, attruname, ibuf, attrsize,attr_flag);
+ }
+ else {
+ ret = sys_setxattr(uname, attruname, ibuf, attrsize, attr_flag);
+ }
+
+ if (ret == -1) {
+ switch(errno) {
+ case ELOOP:
+ /* its a symlink and client requested O_NOFOLLOW */
+ LOG(log_debug, logtype_afpd, "sys_set_ea(%s/%s): encountered symlink with kXAttrNoFollow",
+ uname, attruname);
+ return AFP_OK;
+ default:
+ LOG(log_error, logtype_afpd, "sys_set_ea(%s/%s): error: %s", uname, attruname, strerror(errno));
+ return AFPERR_MISC;
+ }
+ }
+
+ return AFP_OK;
+}
+
+/*
+ * Function: sys_remove_ea
+ *
+ * Purpose: remove a native EA
+ *
+ * Arguments:
+ *
+ * vol (r) current volume
+ * uname (r) filename
+ * attruname (r) EA name
+ * oflag (r) link and create flag
+ *
+ * Returns: AFP code: AFP_OK on success or appropiate AFP error code
+ *
+ * Effects:
+ *
+ * Removes EA attruname from file uname.
+ */
+int sys_remove_ea(VFS_FUNC_ARGS_EA_REMOVE)
+{
+ int ret;
+
+ if ((oflag & O_NOFOLLOW) ) {
+ ret = sys_lremovexattr(uname, attruname);
+ }
+ else {
+ ret = sys_removexattr(uname, attruname);
+ }
+
+ if (ret == -1) {
+ switch(errno) {
+ case ELOOP:
+ /* its a symlink and client requested O_NOFOLLOW */
+ LOG(log_debug, logtype_afpd, "sys_remove_ea(%s/%s): encountered symlink with kXAttrNoFollow", uname);
+ return AFP_OK;
+ case EACCES:
+ LOG(log_debug, logtype_afpd, "sys_remove_ea(%s/%s): error: %s", uname, attruname, strerror(errno));
+ return AFPERR_ACCESS;
+ default:
+ LOG(log_error, logtype_afpd, "sys_remove_ea(%s/%s): error: %s", uname, attruname, strerror(errno));
+ return AFPERR_MISC;
+ }
+ }
+
+ return AFP_OK;
+}
--- /dev/null
+/*
+ Unix SMB/CIFS implementation.
+ Samba system utilities
+ Copyright (C) Andrew Tridgell 1992-1998
+ Copyright (C) Jeremy Allison 1998-2005
+ Copyright (C) Timur Bakeyev 2005
+ Copyright (C) Bjoern Jacke 2006-2007
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Samba 3.0.28, modified for netatalk.
+ $Id: sys_ea.c,v 1.1 2009-11-17 12:33:30 franklahm Exp $
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include <sys/types.h>
+#include <errno.h>
+
+#if HAVE_ATTR_XATTR_H
+#include <attr/xattr.h>
+#elif HAVE_SYS_XATTR_H
+#include <sys/xattr.h>
+#endif
+
+#ifdef HAVE_SYS_EA_H
+#include <sys/ea.h>
+#endif
+
+#ifdef HAVE_ATTROPEN
+
+#include <dirent.h>
+#endif
+
+#ifdef HAVE_SYS_EXTATTR_H
+#include <sys/extattr.h>
+#endif
+
+#include <atalk/adouble.h>
+#include <atalk/util.h>
+#include <atalk/logger.h>
+#include <atalk/ea.h>
+
+/******** Solaris EA helper function prototypes ********/
+#ifdef HAVE_ATTROPEN
+#define SOLARIS_ATTRMODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP
+static int solaris_write_xattr(int attrfd, const char *value, size_t size);
+static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size);
+static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size);
+static int solaris_unlinkat(int attrdirfd, const char *name);
+static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode);
+static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode);
+#endif
+
+/**************************************************************************
+ Wrappers for extented attribute calls. Based on the Linux package with
+ support for IRIX and (Net|Free)BSD also. Expand as other systems have them.
+****************************************************************************/
+static char attr_name[256 +5] = "user.";
+
+static const char *prefix(const char *uname)
+{
+#if defined(HAVE_ATTROPEN)
+ return uname;
+#else
+ strlcpy(attr_name +5, uname, 256);
+ return attr_name;
+#endif
+}
+
+ssize_t sys_getxattr (const char *path, const char *uname, void *value, size_t size)
+{
+ const char *name = prefix(uname);
+
+#if defined(HAVE_GETXATTR)
+#ifndef XATTR_ADD_OPT
+ return getxattr(path, name, value, size);
+#else
+ int options = 0;
+ return getxattr(path, name, value, size, 0, options);
+#endif
+#elif defined(HAVE_GETEA)
+ return getea(path, name, value, size);
+#elif defined(HAVE_EXTATTR_GET_FILE)
+ char *s;
+ ssize_t retval;
+ int attrnamespace = (strncmp(name, "system", 6) == 0) ?
+ EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
+ const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
+ /*
+ * The BSD implementation has a nasty habit of silently truncating
+ * the returned value to the size of the buffer, so we have to check
+ * that the buffer is large enough to fit the returned value.
+ */
+ if((retval=extattr_get_file(path, attrnamespace, attrname, NULL, 0)) >= 0) {
+ if(retval > size) {
+ errno = ERANGE;
+ return -1;
+ }
+ if((retval=extattr_get_file(path, attrnamespace, attrname, value, size)) >= 0)
+ return retval;
+ }
+
+ LOG(log_maxdebug, logtype_default, "sys_getxattr: extattr_get_file() failed with: %s\n", strerror(errno));
+ return -1;
+#elif defined(HAVE_ATTR_GET)
+ int retval, flags = 0;
+ int valuelength = (int)size;
+ char *attrname = strchr(name,'.') + 1;
+
+ if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
+
+ retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
+
+ return retval ? retval : valuelength;
+#elif defined(HAVE_ATTROPEN)
+ ssize_t ret = -1;
+ int attrfd = solaris_attropen(path, name, O_RDONLY, 0);
+ if (attrfd >= 0) {
+ ret = solaris_read_xattr(attrfd, value, size);
+ close(attrfd);
+ }
+ return ret;
+#else
+ errno = ENOSYS;
+ return -1;
+#endif
+}
+
+ssize_t sys_lgetxattr (const char *path, const char *uname, void *value, size_t size)
+{
+ const char *name = prefix(uname);
+
+#if defined(HAVE_LGETXATTR)
+ return lgetxattr(path, name, value, size);
+#elif defined(HAVE_GETXATTR) && defined(XATTR_ADD_OPT)
+ int options = XATTR_NOFOLLOW;
+ return getxattr(path, name, value, size, 0, options);
+#elif defined(HAVE_LGETEA)
+ return lgetea(path, name, value, size);
+#elif defined(HAVE_EXTATTR_GET_LINK)
+ char *s;
+ ssize_t retval;
+ int attrnamespace = (strncmp(name, "system", 6) == 0) ?
+ EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
+ const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
+
+ if((retval=extattr_get_link(path, attrnamespace, attrname, NULL, 0)) >= 0) {
+ if(retval > size) {
+ errno = ERANGE;
+ return -1;
+ }
+ if((retval=extattr_get_link(path, attrnamespace, attrname, value, size)) >= 0)
+ return retval;
+ }
+
+ LOG(log_maxdebug, logtype_default, "sys_lgetxattr: extattr_get_link() failed with: %s\n", strerror(errno));
+ return -1;
+#elif defined(HAVE_ATTR_GET)
+ int retval, flags = ATTR_DONTFOLLOW;
+ int valuelength = (int)size;
+ char *attrname = strchr(name,'.') + 1;
+
+ if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
+
+ retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
+
+ return retval ? retval : valuelength;
+#elif defined(HAVE_ATTROPEN)
+ ssize_t ret = -1;
+ int attrfd = solaris_attropen(path, name, O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
+ if (attrfd >= 0) {
+ ret = solaris_read_xattr(attrfd, value, size);
+ close(attrfd);
+ }
+ return ret;
+#else
+ errno = ENOSYS;
+ return -1;
+#endif
+}
+
+#if defined(HAVE_EXTATTR_LIST_FILE)
+
+#define EXTATTR_PREFIX(s) (s), (sizeof((s))-1)
+
+static struct {
+ int space;
+ const char *name;
+ size_t len;
+}
+extattr[] = {
+ { EXTATTR_NAMESPACE_SYSTEM, EXTATTR_PREFIX("system.") },
+ { EXTATTR_NAMESPACE_USER, EXTATTR_PREFIX("user.") },
+};
+
+typedef union {
+ const char *path;
+ int filedes;
+} extattr_arg;
+
+static ssize_t bsd_attr_list (int type, extattr_arg arg, char *list, size_t size)
+{
+ ssize_t list_size, total_size = 0;
+ int i, t, len;
+ char *buf;
+ /* Iterate through extattr(2) namespaces */
+ for(t = 0; t < (sizeof(extattr)/sizeof(extattr[0])); t++) {
+ switch(type) {
+#if defined(HAVE_EXTATTR_LIST_FILE)
+ case 0:
+ list_size = extattr_list_file(arg.path, extattr[t].space, list, size);
+ break;
+#endif
+#if defined(HAVE_EXTATTR_LIST_LINK)
+ case 1:
+ list_size = extattr_list_link(arg.path, extattr[t].space, list, size);
+ break;
+#endif
+#if defined(HAVE_EXTATTR_LIST_FD)
+ case 2:
+ list_size = extattr_list_fd(arg.filedes, extattr[t].space, list, size);
+ break;
+#endif
+ default:
+ errno = ENOSYS;
+ return -1;
+ }
+ /* Some error happend. Errno should be set by the previous call */
+ if(list_size < 0)
+ return -1;
+ /* No attributes */
+ if(list_size == 0)
+ continue;
+ /* XXX: Call with an empty buffer may be used to calculate
+ necessary buffer size. Unfortunately, we can't say, how
+ many attributes were returned, so here is the potential
+ problem with the emulation.
+ */
+ if(list == NULL) {
+ /* Take the worse case of one char attribute names -
+ two bytes per name plus one more for sanity.
+ */
+ total_size += list_size + (list_size/2 + 1)*extattr[t].len;
+ continue;
+ }
+ /* Count necessary offset to fit namespace prefixes */
+ len = 0;
+ for(i = 0; i < list_size; i += list[i] + 1)
+ len += extattr[t].len;
+
+ total_size += list_size + len;
+ /* Buffer is too small to fit the results */
+ if(total_size > size) {
+ errno = ERANGE;
+ return -1;
+ }
+ /* Shift results back, so we can prepend prefixes */
+ buf = memmove(list + len, list, list_size);
+
+ for(i = 0; i < list_size; i += len + 1) {
+ len = buf[i];
+ strncpy(list, extattr[t].name, extattr[t].len + 1);
+ list += extattr[t].len;
+ strncpy(list, buf + i + 1, len);
+ list[len] = '\0';
+ list += len + 1;
+ }
+ size -= total_size;
+ }
+ return total_size;
+}
+
+#endif
+
+#if defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
+static char attr_buffer[ATTR_MAX_VALUELEN];
+
+static ssize_t irix_attr_list(const char *path, int filedes, char *list, size_t size, int flags)
+{
+ int retval = 0, index;
+ attrlist_cursor_t *cursor = 0;
+ int total_size = 0;
+ attrlist_t * al = (attrlist_t *)attr_buffer;
+ attrlist_ent_t *ae;
+ size_t ent_size, left = size;
+ char *bp = list;
+
+ while (True) {
+ if (filedes)
+ retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
+ else
+ retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
+ if (retval) break;
+ for (index = 0; index < al->al_count; index++) {
+ ae = ATTR_ENTRY(attr_buffer, index);
+ ent_size = strlen(ae->a_name) + sizeof("user.");
+ if (left >= ent_size) {
+ strncpy(bp, "user.", sizeof("user."));
+ strncat(bp, ae->a_name, ent_size - sizeof("user."));
+ bp += ent_size;
+ left -= ent_size;
+ } else if (size) {
+ errno = ERANGE;
+ retval = -1;
+ break;
+ }
+ total_size += ent_size;
+ }
+ if (al->al_more == 0) break;
+ }
+ if (retval == 0) {
+ flags |= ATTR_ROOT;
+ cursor = 0;
+ while (True) {
+ if (filedes)
+ retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
+ else
+ retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
+ if (retval) break;
+ for (index = 0; index < al->al_count; index++) {
+ ae = ATTR_ENTRY(attr_buffer, index);
+ ent_size = strlen(ae->a_name) + sizeof("system.");
+ if (left >= ent_size) {
+ strncpy(bp, "system.", sizeof("system."));
+ strncat(bp, ae->a_name, ent_size - sizeof("system."));
+ bp += ent_size;
+ left -= ent_size;
+ } else if (size) {
+ errno = ERANGE;
+ retval = -1;
+ break;
+ }
+ total_size += ent_size;
+ }
+ if (al->al_more == 0) break;
+ }
+ }
+ return (ssize_t)(retval ? retval : total_size);
+}
+
+#endif
+
+#if defined(HAVE_LISTXATTR)
+static ssize_t remove_user(ssize_t ret, char *list, size_t size)
+{
+ size_t len;
+ char *ptr;
+ char *ptr1;
+ ssize_t ptrsize;
+
+ if (ret <= 0 || size == 0)
+ return ret;
+ ptrsize = ret;
+ ptr = ptr1 = list;
+ while (ptrsize > 0) {
+ len = strlen(ptr1) +1;
+ ptrsize -= len;
+ if (strncmp(ptr1, "user.",5)) {
+ ptr1 += len;
+ continue;
+ }
+ memmove(ptr, ptr1 +5, len -5);
+ ptr += len -5;
+ ptr1 += len;
+ }
+ return ptr -list;
+}
+#endif
+
+ssize_t sys_listxattr (const char *path, char *list, size_t size)
+{
+#if defined(HAVE_LISTXATTR)
+ ssize_t ret;
+
+#ifndef XATTR_ADD_OPT
+ ret = listxattr(path, list, size);
+#else
+ int options = 0;
+ ret = listxattr(path, list, size, options);
+#endif
+ return remove_user(ret, list, size);
+
+#elif defined(HAVE_LISTEA)
+ return listea(path, list, size);
+#elif defined(HAVE_EXTATTR_LIST_FILE)
+ extattr_arg arg;
+ arg.path = path;
+ return bsd_attr_list(0, arg, list, size);
+#elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
+ return irix_attr_list(path, 0, list, size, 0);
+#elif defined(HAVE_ATTROPEN)
+ ssize_t ret = -1;
+ int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
+ if (attrdirfd >= 0) {
+ ret = solaris_list_xattr(attrdirfd, list, size);
+ close(attrdirfd);
+ }
+ return ret;
+#else
+ errno = ENOSYS;
+ return -1;
+#endif
+}
+
+ssize_t sys_llistxattr (const char *path, char *list, size_t size)
+{
+#if defined(HAVE_LLISTXATTR)
+ ssize_t ret;
+
+ ret = llistxattr(path, list, size);
+ return remove_user(ret, list, size);
+#elif defined(HAVE_LISTXATTR) && defined(XATTR_ADD_OPT)
+ ssize_t ret;
+ int options = XATTR_NOFOLLOW;
+
+ ret = listxattr(path, list, size, options);
+ return remove_user(ret, list, size);
+
+#elif defined(HAVE_LLISTEA)
+ return llistea(path, list, size);
+#elif defined(HAVE_EXTATTR_LIST_LINK)
+ extattr_arg arg;
+ arg.path = path;
+ return bsd_attr_list(1, arg, list, size);
+#elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
+ return irix_attr_list(path, 0, list, size, ATTR_DONTFOLLOW);
+#elif defined(HAVE_ATTROPEN)
+ ssize_t ret = -1;
+ int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
+ if (attrdirfd >= 0) {
+ ret = solaris_list_xattr(attrdirfd, list, size);
+ close(attrdirfd);
+ }
+ return ret;
+#else
+ errno = ENOSYS;
+ return -1;
+#endif
+}
+
+int sys_removexattr (const char *path, const char *uname)
+{
+ const char *name = prefix(uname);
+#if defined(HAVE_REMOVEXATTR)
+#ifndef XATTR_ADD_OPT
+ return removexattr(path, name);
+#else
+ int options = 0;
+ return removexattr(path, name, options);
+#endif
+#elif defined(HAVE_REMOVEEA)
+ return removeea(path, name);
+#elif defined(HAVE_EXTATTR_DELETE_FILE)
+ char *s;
+ int attrnamespace = (strncmp(name, "system", 6) == 0) ?
+ EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
+ const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
+
+ return extattr_delete_file(path, attrnamespace, attrname);
+#elif defined(HAVE_ATTR_REMOVE)
+ int flags = 0;
+ char *attrname = strchr(name,'.') + 1;
+
+ if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
+
+ return attr_remove(path, attrname, flags);
+#elif defined(HAVE_ATTROPEN)
+ int ret = -1;
+ int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
+ if (attrdirfd >= 0) {
+ ret = solaris_unlinkat(attrdirfd, name);
+ close(attrdirfd);
+ }
+ return ret;
+#else
+ errno = ENOSYS;
+ return -1;
+#endif
+}
+
+int sys_lremovexattr (const char *path, const char *uname)
+{
+ const char *name = prefix(uname);
+#if defined(HAVE_LREMOVEXATTR)
+ return lremovexattr(path, name);
+#elif defined(HAVE_REMOVEXATTR) && defined(XATTR_ADD_OPT)
+ int options = XATTR_NOFOLLOW;
+ return removexattr(path, name, options);
+#elif defined(HAVE_LREMOVEEA)
+ return lremoveea(path, name);
+#elif defined(HAVE_EXTATTR_DELETE_LINK)
+ char *s;
+ int attrnamespace = (strncmp(name, "system", 6) == 0) ?
+ EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
+ const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
+
+ return extattr_delete_link(path, attrnamespace, attrname);
+#elif defined(HAVE_ATTR_REMOVE)
+ int flags = ATTR_DONTFOLLOW;
+ char *attrname = strchr(name,'.') + 1;
+
+ if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
+
+ return attr_remove(path, attrname, flags);
+#elif defined(HAVE_ATTROPEN)
+ int ret = -1;
+ int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
+ if (attrdirfd >= 0) {
+ ret = solaris_unlinkat(attrdirfd, name);
+ close(attrdirfd);
+ }
+ return ret;
+#else
+ errno = ENOSYS;
+ return -1;
+#endif
+}
+
+int sys_setxattr (const char *path, const char *uname, const void *value, size_t size, int flags)
+{
+ const char *name = prefix(uname);
+#if defined(HAVE_SETXATTR)
+#ifndef XATTR_ADD_OPT
+ return setxattr(path, name, value, size, flags);
+#else
+ int options = 0;
+ return setxattr(path, name, value, size, 0, options);
+#endif
+#elif defined(HAVE_SETEA)
+ return setea(path, name, value, size, flags);
+#elif defined(HAVE_EXTATTR_SET_FILE)
+ char *s;
+ int retval = 0;
+ int attrnamespace = (strncmp(name, "system", 6) == 0) ?
+ EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
+ const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
+ if (flags) {
+ /* Check attribute existence */
+ retval = extattr_get_file(path, attrnamespace, attrname, NULL, 0);
+ if (retval < 0) {
+ /* REPLACE attribute, that doesn't exist */
+ if (flags & XATTR_REPLACE && errno == ENOATTR) {
+ errno = ENOATTR;
+ return -1;
+ }
+ /* Ignore other errors */
+ }
+ else {
+ /* CREATE attribute, that already exists */
+ if (flags & XATTR_CREATE) {
+ errno = EEXIST;
+ return -1;
+ }
+ }
+ }
+ retval = extattr_set_file(path, attrnamespace, attrname, value, size);
+ return (retval < 0) ? -1 : 0;
+#elif defined(HAVE_ATTR_SET)
+ int myflags = 0;
+ char *attrname = strchr(name,'.') + 1;
+
+ if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
+ if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
+ if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
+
+ return attr_set(path, attrname, (const char *)value, size, myflags);
+#elif defined(HAVE_ATTROPEN)
+ int ret = -1;
+ int myflags = O_RDWR;
+ int attrfd;
+ if (flags & XATTR_CREATE) myflags |= O_EXCL;
+ if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
+ attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
+ if (attrfd >= 0) {
+ ret = solaris_write_xattr(attrfd, value, size);
+ close(attrfd);
+ }
+ return ret;
+#else
+ errno = ENOSYS;
+ return -1;
+#endif
+}
+
+int sys_lsetxattr (const char *path, const char *uname, const void *value, size_t size, int flags)
+{
+ const char *name = prefix(uname);
+#if defined(HAVE_LSETXATTR)
+ return lsetxattr(path, name, value, size, flags);
+#elif defined(HAVE_SETXATTR) && defined(XATTR_ADD_OPT)
+ int options = XATTR_NOFOLLOW;
+ return setxattr(path, name, value, size, 0, options);
+#elif defined(LSETEA)
+ return lsetea(path, name, value, size, flags);
+#elif defined(HAVE_EXTATTR_SET_LINK)
+ char *s;
+ int retval = 0;
+ int attrnamespace = (strncmp(name, "system", 6) == 0) ?
+ EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
+ const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
+ if (flags) {
+ /* Check attribute existence */
+ retval = extattr_get_link(path, attrnamespace, attrname, NULL, 0);
+ if (retval < 0) {
+ /* REPLACE attribute, that doesn't exist */
+ if (flags & XATTR_REPLACE && errno == ENOATTR) {
+ errno = ENOATTR;
+ return -1;
+ }
+ /* Ignore other errors */
+ }
+ else {
+ /* CREATE attribute, that already exists */
+ if (flags & XATTR_CREATE) {
+ errno = EEXIST;
+ return -1;
+ }
+ }
+ }
+
+ retval = extattr_set_link(path, attrnamespace, attrname, value, size);
+ return (retval < 0) ? -1 : 0;
+#elif defined(HAVE_ATTR_SET)
+ int myflags = ATTR_DONTFOLLOW;
+ char *attrname = strchr(name,'.') + 1;
+
+ if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
+ if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
+ if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
+
+ return attr_set(path, attrname, (const char *)value, size, myflags);
+#elif defined(HAVE_ATTROPEN)
+ int ret = -1;
+ int myflags = O_RDWR | AT_SYMLINK_NOFOLLOW;
+ int attrfd;
+ if (flags & XATTR_CREATE) myflags |= O_EXCL;
+ if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
+ attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
+ if (attrfd >= 0) {
+ ret = solaris_write_xattr(attrfd, value, size);
+ close(attrfd);
+ }
+ return ret;
+#else
+ errno = ENOSYS;
+ return -1;
+#endif
+}
+
+/**************************************************************************
+ helper functions for Solaris' EA support
+****************************************************************************/
+#ifdef HAVE_ATTROPEN
+static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size)
+{
+ struct stat sbuf;
+
+ if (fstat(attrfd, &sbuf) == -1) {
+ return -1;
+ }
+
+ /* This is to return the current size of the named extended attribute */
+ if (size == 0) {
+ return sbuf.st_size;
+ }
+
+ /* check size and read xattr */
+ if (sbuf.st_size > size) {
+ return -1;
+ }
+
+ return read(attrfd, value, sbuf.st_size);
+}
+
+static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size)
+{
+ ssize_t len = 0;
+ int stop = 0;
+ DIR *dirp;
+ struct dirent *de;
+ int newfd = dup(attrdirfd);
+ /* CAUTION: The originating file descriptor should not be
+ used again following the call to fdopendir().
+ For that reason we dup() the file descriptor
+ here to make things more clear. */
+ dirp = fdopendir(newfd);
+
+ while ((de = readdir(dirp))) {
+ size_t listlen;
+ if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..") ||
+ !strcmp(de->d_name, "SUNWattr_ro") || !strcmp(de->d_name, "SUNWattr_rw"))
+ {
+ /* we don't want "." and ".." here: */
+ LOG(log_maxdebug, logtype_default, "skipped EA %s\n",de->d_name);
+ continue;
+ }
+
+ listlen = strlen(de->d_name);
+ if (size == 0) {
+ /* return the current size of the list of extended attribute names*/
+ len += listlen + 1;
+ } else {
+ /* check size and copy entry + nul into list. */
+ if ((len + listlen + 1) > size) {
+ errno = ERANGE;
+ len = -1;
+ break;
+ } else {
+ strcpy(list + len, de->d_name);
+ len += listlen;
+ list[len] = '\0';
+ ++len;
+ }
+ }
+ }
+
+ if (closedir(dirp) == -1) {
+ LOG(log_debug, logtype_default, "closedir dirp failed: %s\n",strerror(errno));
+ return -1;
+ }
+ return len;
+}
+
+static int solaris_unlinkat(int attrdirfd, const char *name)
+{
+ if (unlinkat(attrdirfd, name, 0) == -1) {
+ return -1;
+ }
+ return 0;
+}
+
+static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode)
+{
+ int filedes = attropen(path, attrpath, oflag, mode);
+ if (filedes == -1) {
+ LOG(log_maxdebug, logtype_default, "attropen FAILED: path: %s, name: %s, errno: %s\n",path,attrpath,strerror(errno));
+ }
+ return filedes;
+}
+
+static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode)
+{
+ int filedes = openat(fildes, path, oflag, mode);
+ if (filedes == -1) {
+ LOG(log_maxdebug, logtype_default, "openat FAILED: fd: %s, path: %s, errno: %s\n",filedes,path,strerror(errno));
+ }
+ return filedes;
+}
+
+static int solaris_write_xattr(int attrfd, const char *value, size_t size)
+{
+ if ((ftruncate(attrfd, 0) == 0) && (write(attrfd, value, size) == size)) {
+ return 0;
+ } else {
+ LOG(log_maxdebug, logtype_default, "solaris_write_xattr FAILED!\n");
+ return -1;
+ }
+}
+#endif /*HAVE_ATTROPEN*/
+
/* vfs_remove */ remove_ea
};
-static struct vfs_ops netatalk_ea_solaris = {
+static struct vfs_ops netatalk_ea_sys = {
/* validupath: */ NULL,
/* rf_chown: */ NULL,
/* rf_renamedir: */ NULL,
/* vfs_copyfile: */ NULL,
/* rf_acl: */ NULL,
/* rf_remove_acl */ NULL,
- /* ea_getsize */ sol_get_easize,
- /* ea_getcontent */ sol_get_eacontent,
- /* ea_list */ sol_list_eas,
- /* ea_set */ sol_set_ea,
- /* ea_remove */ sol_remove_ea
+ /* ea_getsize */ sys_get_easize,
+ /* ea_getcontent */ sys_get_eacontent,
+ /* ea_list */ sys_list_eas,
+ /* ea_set */ sys_set_ea,
+ /* ea_remove */ sys_remove_ea
};
/*
}
/* Extended Attributes */
- if (vol->v_vfs_ea == AFPVOL_EA_SOLARIS) {
-
+ if (vol->v_vfs_ea == AFPVOL_EA_SYS) {
LOG(log_debug, logtype_afpd, "initvol_vfs: Enabling EA support with native EAs.");
- vol->vfs_modules[1] = &netatalk_ea_solaris;
+ vol->vfs_modules[1] = &netatalk_ea_sys;
} else {
/* default: AFPVOL_EA_AD */
LOG(log_debug, logtype_afpd, "initvol_vfs: Enabling EA support with adouble files.");