1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-23 17:34:34 +03:00

r24304: patch from Bjoern JAcke <bj@SerNet.DE>:

attached patches add EA support for Solaris. If no one disagrees, can
someone check this in please?

metze
This commit is contained in:
Stefan Metzmacher 2007-08-10 09:44:13 +00:00 committed by Gerald (Jerry) Carter
parent 30f9171cca
commit 81e5afc363
3 changed files with 254 additions and 0 deletions

View File

@ -1747,6 +1747,14 @@ case "$host_os" in
;;
esac
########################################################
# Check if attropen() is present if this is Solaris
case "$host_os" in
*solaris*)
AC_CHECK_FUNCS(attropen)
;;
esac
########################################################
# Do xattr functions take additional options like on Darwin?
if test x"$ac_cv_func_getxattr" = x"yes" ; then

View File

@ -224,6 +224,10 @@ typedef int ber_int_t;
#include <sys/attributes.h>
#endif
#ifndef ENOATTR
#define ENOATTR ENODATA
#endif
/* mutually exclusive (SuSE 8.2) */
#if HAVE_ATTR_XATTR_H
#include <attr/xattr.h>

View File

@ -4,6 +4,7 @@
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
@ -1682,6 +1683,17 @@ int sys_dup2(int oldfd, int newfd)
SAFE_FREE(msgbuf);
}
/******** Solaris EA helper function prototypes ********/
#ifdef HAVE_ATTROPEN
#define SOLARIS_ATTRMODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP
int solaris_write_xattr(int attrfd, const char *value, size_t size);
ssize_t solaris_read_xattr(int attrfd, void *value, size_t size);
ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size);
int solaris_unlinkat(int attrdirfd, const char *name);
int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode);
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.
@ -1730,6 +1742,14 @@ ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t si
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;
@ -1773,6 +1793,14 @@ ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t s
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;
@ -1818,6 +1846,14 @@ ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size)
retval = attr_getf(filedes, attrname, (char *)value, &valuelength, flags);
return retval ? retval : valuelength;
#elif defined(HAVE_ATTROPEN)
ssize_t ret = -1;
int attrfd = solaris_openat(filedes, name, O_RDONLY|O_XATTR, 0);
if (attrfd >= 0) {
ret = solaris_read_xattr(attrfd, value, size);
close(attrfd);
}
return ret;
#else
errno = ENOSYS;
return -1;
@ -2002,6 +2038,14 @@ ssize_t sys_listxattr (const char *path, char *list, size_t size)
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;
@ -2023,6 +2067,14 @@ ssize_t sys_llistxattr (const char *path, char *list, size_t size)
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;
@ -2046,6 +2098,14 @@ ssize_t sys_flistxattr (int filedes, char *list, size_t size)
return bsd_attr_list(2, arg, list, size);
#elif defined(HAVE_ATTR_LISTF)
return irix_attr_list(NULL, filedes, list, size, 0);
#elif defined(HAVE_ATTROPEN)
ssize_t ret = -1;
int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
if (attrdirfd >= 0) {
ret = solaris_list_xattr(attrdirfd, list, size);
close(attrdirfd);
}
return ret;
#else
errno = ENOSYS;
return -1;
@ -2077,6 +2137,14 @@ int sys_removexattr (const char *path, const char *name)
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;
@ -2106,6 +2174,14 @@ int sys_lremovexattr (const char *path, const char *name)
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;
@ -2137,6 +2213,14 @@ int sys_fremovexattr (int filedes, const char *name)
if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
return attr_removef(filedes, attrname, flags);
#elif defined(HAVE_ATTROPEN)
int ret = -1;
int attrdirfd = solaris_openat(filedes, ".", O_RDONLY|O_XATTR, 0);
if (attrdirfd >= 0) {
ret = solaris_unlinkat(attrdirfd, name);
close(attrdirfd);
}
return ret;
#else
errno = ENOSYS;
return -1;
@ -2195,6 +2279,17 @@ int sys_setxattr (const char *path, const char *name, const void *value, size_t
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;
if (flags & XATTR_CREATE) myflags |= O_EXCL;
if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
int 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;
@ -2247,6 +2342,17 @@ int sys_lsetxattr (const char *path, const char *name, const void *value, size_t
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;
if (flags & XATTR_CREATE) myflags |= O_EXCL;
if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
int 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;
@ -2300,12 +2406,148 @@ int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size
if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
return attr_setf(filedes, attrname, (const char *)value, size, myflags);
#elif defined(HAVE_ATTROPEN)
int ret = -1;
int myflags = O_RDWR | O_XATTR;
if (flags & XATTR_CREATE) myflags |= O_EXCL;
if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
int attrfd = solaris_openat(filedes, 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) {
errno = ENOATTR;
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) {
errno = ERANGE;
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 = strlen(de->d_name);
if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) {
/* we don't want "." and ".." here: */
DEBUG(10,("skipped EA %s\n",de->d_name));
continue;
}
if (size == 0) {
/* return the current size of the list of extended attribute names*/
len += listlen + 1;
} else {
/* check size and copy entrieѕ + nul into list. */
if ((len + listlen + 1) > size) {
errno = ERANGE;
len = -1;
break;
} else {
safe_strcpy(list + len, de->d_name, listlen);
pstrcpy(list + len, de->d_name);
len += listlen;
list[len] = '\0';
++len;
}
}
}
if (closedir(dirp) == -1) {
DEBUG(0,("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) {
if (errno == ENOENT) {
errno = ENOATTR;
}
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) {
DEBUG(10,("attropen FAILED: path: %s, name: %s, errno: %s\n",path,attrpath,strerror(errno)));
if (errno == EINVAL) {
errno = ENOTSUP;
} else {
errno = ENOATTR;
}
}
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) {
DEBUG(10,("openat FAILED: fd: %s, path: %s, errno: %s\n",filedes,path,strerror(errno)));
if (errno == EINVAL) {
errno = ENOTSUP;
} else {
errno = ENOATTR;
}
}
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 {
DEBUG(10,("solaris_write_xattr FAILED!\n"));
return -1;
}
}
#endif /*HAVE_ATTROPEN*/
/****************************************************************************
Return the major devicenumber for UNIX extensions.
****************************************************************************/