Author: metze
Date: 2007-08-10 09:44:13 +0000 (Fri, 10 Aug 2007)
New Revision: 24304

WebSVN: 
http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=24304

Log:
patch from Bjoern JAcke <[EMAIL PROTECTED]>:

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

metze
Modified:
   branches/SAMBA_3_2/source/configure.in
   branches/SAMBA_3_2/source/include/includes.h
   branches/SAMBA_3_2/source/lib/system.c


Changeset:
Modified: branches/SAMBA_3_2/source/configure.in
===================================================================
--- branches/SAMBA_3_2/source/configure.in      2007-08-10 09:13:06 UTC (rev 
24303)
+++ branches/SAMBA_3_2/source/configure.in      2007-08-10 09:44:13 UTC (rev 
24304)
@@ -1748,6 +1748,14 @@
 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
        AC_CACHE_CHECK([whether xattr interface takes additional options], 
smb_attr_cv_xattr_add_opt, [

Modified: branches/SAMBA_3_2/source/include/includes.h
===================================================================
--- branches/SAMBA_3_2/source/include/includes.h        2007-08-10 09:13:06 UTC 
(rev 24303)
+++ branches/SAMBA_3_2/source/include/includes.h        2007-08-10 09:44:13 UTC 
(rev 24304)
@@ -224,6 +224,10 @@
 #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>

Modified: branches/SAMBA_3_2/source/lib/system.c
===================================================================
--- branches/SAMBA_3_2/source/lib/system.c      2007-08-10 09:13:06 UTC (rev 
24303)
+++ branches/SAMBA_3_2/source/lib/system.c      2007-08-10 09:44:13 UTC (rev 
24304)
@@ -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 @@
        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 @@
        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 @@
        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 @@
        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 @@
        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 @@
        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 @@
        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 @@
        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 @@
        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 @@
        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 @@
        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 @@
        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 @@
        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.
 ****************************************************************************/

Reply via email to