]> arthur.barton.de Git - netatalk.git/blobdiff - libatalk/vfs/extattr.c
afpd: Solaris locking problem, bug #559
[netatalk.git] / libatalk / vfs / extattr.c
index 26da70636ff1a683c19d124a631105798f0d0541..9e45bb8bea0b27c71a17d218a48481fd20bba753 100644 (file)
@@ -70,6 +70,7 @@ 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_attropenat(int filedes, 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
 
@@ -240,17 +241,22 @@ ssize_t sys_lgetxattr (const char *path, const char *uname, void *value, size_t
        return lgetea(path, name, value, size);
 #elif defined(HAVE_EXTATTR_GET_LINK)
        ssize_t retval;
-       if((retval=extattr_get_link(path, EXTATTR_NAMESPACE_USER, uname, NULL, 0)) >= 0) {
-               if(retval > size) {
-                       errno = ERANGE;
-                       return -1;
-               }
-               if((retval=extattr_get_link(path, EXTATTR_NAMESPACE_USER, uname, value, size)) >= 0)
-                       return retval;
-       }
-       
-       LOG(log_maxdebug, logtype_default, "sys_lgetxattr: extattr_get_link() failed with: %s\n", strerror(errno));
-       return -1;
+
+       retval = extattr_get_link(path, EXTATTR_NAMESPACE_USER, uname, NULL, 0);
+    if (retval == -1) {
+        LOG(log_maxdebug, logtype_default, "extattr_get_link(): %s",
+            strerror(errno));
+        return -1;
+    }
+    if (size == 0)
+        /* Only interested in size of xattr */
+        return retval;
+    if (retval > size) {
+        errno = ERANGE;
+        return -1;
+    }
+    return extattr_get_link(path, EXTATTR_NAMESPACE_USER, uname, value, size);
+
 #elif defined(HAVE_ATTR_GET)
        int retval, flags = ATTR_DONTFOLLOW;
        int valuelength = (int)size;
@@ -489,6 +495,41 @@ ssize_t sys_listxattr (const char *path, char *list, size_t size)
 #endif
 }
 
+ssize_t sys_flistxattr (int filedes, 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_attropenat(filedes, 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)
@@ -560,6 +601,41 @@ int sys_removexattr (const char *path, const char *uname)
 #endif
 }
 
+int sys_fremovexattr (int filedes, 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)
+       return extattr_delete_file(path, EXTATTR_NAMESPACE_USER, uname);
+#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_attropenat(filedes, 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);
@@ -876,7 +952,6 @@ static int solaris_attropen(const char *path, const char *attrpath, int oflag, m
             EC_FAIL;
         default:
             LOG(log_debug, logtype_default, "open(\"%s\"): %s", fullpathname(path), strerror(errno));
-            errno = ENOATTR;
             EC_FAIL;
         }
        }
@@ -888,7 +963,6 @@ static int solaris_attropen(const char *path, const char *attrpath, int oflag, m
             EC_FAIL;
         default:
             LOG(log_debug, logtype_default, "openat(\"%s\"): %s", fullpathname(path), strerror(errno));
-            errno = ENOATTR;
             EC_FAIL;
         }
        }
@@ -904,6 +978,32 @@ EC_CLEANUP:
     return eafd;
 }
 
+static int solaris_attropenat(int filedes, const char *path, const char *attrpath, int oflag, mode_t mode)
+{
+    EC_INIT;
+       int eafd = -1;
+
+       if ((eafd = openat(filedes, attrpath, oflag | O_XATTR, mode)) == -1) {
+        switch (errno) {
+        case ENOENT:
+        case EEXIST:
+            EC_FAIL;
+        default:
+            LOG(log_debug, logtype_default, "openat(\"%s\"): %s", fullpathname(path), strerror(errno));
+            EC_FAIL;
+        }
+       }
+
+EC_CLEANUP:
+    if (ret != 0) {
+        if (eafd != -1)
+            close(eafd);
+        eafd = -1;
+    }
+    return eafd;
+}
+
+
 static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode)
 {
        int filedes;
@@ -912,6 +1012,7 @@ static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode)
         switch (errno) {
         case ENOENT:
         case EEXIST:
+        case EACCES:
             break;
         default:
             LOG(log_debug, logtype_default, "openat(\"%s\"): %s",