r24304: patch from Bjoern JAcke <bj@SerNet.DE>:
authorStefan Metzmacher <metze@samba.org>
Fri, 10 Aug 2007 09:44:13 +0000 (09:44 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 17:29:25 +0000 (12:29 -0500)
attached patches add EA support for Solaris. If no one disagrees, can
someone check this in please?

metze
(This used to be commit 81e5afc363e1f0bdc4768c0f5c696f4152fe5b44)

source3/configure.in
source3/include/includes.h
source3/lib/system.c

index 4029a0a10c0f3efa84e8ac593f5abccf3d81a01e..0d0fdb1394582ac82f4958432d065ded5e71295d 100644 (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
index 238612a4383030e49862167d5a4ffe26d9856b82..7747f9797052fa00ed6822c9b54d41a588027037 100644 (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>
index 9bca41d978bddfe4551e31af3d954a28dfc25405..33633d93ed5c434fd369315dbb978940755c79a5 100644 (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.
 ****************************************************************************/