Author: jra
Date: 2005-10-28 22:22:30 +0000 (Fri, 28 Oct 2005)
New Revision: 11384

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

Log:
Patch from Alex Masterov <[EMAIL PROTECTED]> to fix
XATTR calls on *BSD systems (bug #3218).
Jeremy.

Modified:
   trunk/source/lib/system.c


Changeset:
Modified: trunk/source/lib/system.c
===================================================================
--- trunk/source/lib/system.c   2005-10-28 22:22:23 UTC (rev 11383)
+++ trunk/source/lib/system.c   2005-10-28 22:22:30 UTC (rev 11384)
@@ -1367,7 +1367,7 @@
 
 /**************************************************************************
  Wrappers for extented attribute calls. Based on the Linux package with
- support for IRIX also. Expand as other systems have them.
+ support for IRIX and (Net|Free)BSD also. Expand as other systems have them.
 ****************************************************************************/
 
 ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t 
size)
@@ -1376,10 +1376,22 @@
        return getxattr(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.
+        */
+       retval = extattr_get_file(path, attrnamespace, attrname, NULL, 0);
 
+       if(retval > size) {
+               errno = ERANGE;
+               return -1;
+       }
+
        return extattr_get_file(path, attrnamespace, attrname, value, size);
 #elif defined(HAVE_ATTR_GET)
        int retval, flags = 0;
@@ -1403,10 +1415,18 @@
        return lgetxattr(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;
 
+       retval = extattr_get_link(path, attrnamespace, attrname, NULL, 0);
+
+       if(retval > size) {
+               errno = ERANGE;
+               return -1;
+       }
+
        return extattr_get_link(path, attrnamespace, attrname, value, size);
 #elif defined(HAVE_ATTR_GET)
        int retval, flags = ATTR_DONTFOLLOW;
@@ -1430,10 +1450,18 @@
        return fgetxattr(filedes, name, value, size);
 #elif defined(HAVE_EXTATTR_GET_FD)
        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;
 
+       retval = extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0);
+
+       if(retval > size) {
+               errno = ERANGE;
+               return -1;
+       }
+
        return extattr_get_fd(filedes, attrnamespace, attrname, value, size);
 #elif defined(HAVE_ATTR_GETF)
        int retval, flags = 0;
@@ -1747,7 +1775,24 @@
        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;
+                       }
+               }
+               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)
@@ -1775,6 +1820,24 @@
        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;
+                       }
+               }
+               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;
@@ -1803,7 +1866,24 @@
        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_fd(filedes, attrnamespace, attrname, NULL, 
0);
+               if (retval < 0) {
+                       /* REPLACE attribute, that doesn't exist */
+                       if (flags & XATTR_REPLACE && errno == ENOATTR) {
+                               errno = ENOATTR;
+                               return -1;
+                       }
+               }
+               else {
+                       /* CREATE attribute, that already exists */
+                       if (flags & XATTR_CREATE) {
+                               errno = EEXIST;
+                               return -1;
+                       }
+               }
+       }
        retval = extattr_set_fd(filedes, attrnamespace, attrname, value, size);
        return (retval < 0) ? -1 : 0;
 #elif defined(HAVE_ATTR_SETF)

Reply via email to