]> arthur.barton.de Git - netatalk.git/blobdiff - libatalk/acl/unix.c
Rename all iniparser API function
[netatalk.git] / libatalk / acl / unix.c
index 31027abe581da133c0de503b479c2ccb301142ff..cc69d8ade3299bd20fbced73d3c5485b0f4f8132 100644 (file)
@@ -33,6 +33,7 @@
 #include <atalk/afp.h>
 #include <atalk/util.h>
 #include <atalk/acl.h>
+#include <atalk/unix.h>
 
 #ifdef HAVE_SOLARIS_ACLS
 
@@ -47,7 +48,7 @@ int get_nfsv4_acl(const char *name, ace_t **retAces)
     *retAces = NULL;
     /* Only call acl() for regular files and directories, otherwise just return 0 */
     if (lstat(name, &st) != 0) {
-        LOG(log_warning, logtype_afpd, "get_nfsv4_acl(\"%s/%s\"): %s", getcwdpath(), name, strerror(errno));
+        LOG(log_debug, logtype_afpd, "get_nfsv4_acl(\"%s/%s\"): %s", getcwdpath(), name, strerror(errno));
         return -1;
     }
 
@@ -56,17 +57,17 @@ int get_nfsv4_acl(const char *name, ace_t **retAces)
         return 0;
 
     if ( ! (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode))) {
-        LOG(log_warning, logtype_afpd, "get_nfsv4_acl(\"%s/%s\"): special", getcwdpath(), name);
+        LOG(log_debug, logtype_afpd, "get_nfsv4_acl(\"%s/%s\"): special", getcwdpath(), name);
         return 0;
     }
 
     if ((ace_count = acl(name, ACE_GETACLCNT, 0, NULL)) == 0) {
-        LOG(log_warning, logtype_afpd, "get_nfsv4_acl(\"%s/%s\"): 0 ACEs", getcwdpath(), name);
+        LOG(log_debug, logtype_afpd, "get_nfsv4_acl(\"%s/%s\"): 0 ACEs", getcwdpath(), name);
         return 0;
     }
 
     if (ace_count == -1) {
-        LOG(log_error, logtype_afpd, "get_nfsv4_acl: acl('%s/%s', ACE_GETACLCNT): ace_count %i, error: %s",
+        LOG(log_debug, logtype_afpd, "get_nfsv4_acl: acl('%s/%s', ACE_GETACLCNT): ace_count %i, error: %s",
             getcwdpath(), name, ace_count, strerror(errno));
         return -1;
     }
@@ -205,10 +206,10 @@ int strip_nontrivial_aces(ace_t **saces, int sacecount)
  * Change mode of file preserving existing explicit ACEs
  *
  * nfsv4_chmod
- * (1) reads objects ACL (acl1)
+ * (1) reads objects ACL (acl1), may return 0 or -1 NFSv4 ACEs on eg UFS fs
  * (2) removes all trivial ACEs from the ACL by calling strip_trivial_aces(), possibly
  *     leaving 0 ACEs in the ACL if there were only trivial ACEs as mapped from the mode
- * (3) calls chmod() with mode
+ * (3) calls chmod() with mode, we're done if step (1) returned 0 for noaces
  * (4) reads the changed ACL (acl2) which
  *     a) might still contain explicit ACEs (up to onnv132)
  *     b) will have any explicit ACE removed (starting with onnv145/Openindiana)
@@ -225,16 +226,25 @@ int nfsv4_chmod(char *name, mode_t mode)
     LOG(log_debug, logtype_afpd, "nfsv4_chmod(\"%s/%s\", %04o)",
         getcwdpath(), name, mode);
 
-    if ((noaces = get_nfsv4_acl(name, &oacl)) == -1) /* (1) */
-        goto exit;
+    if ((noaces = get_nfsv4_acl(name, &oacl)) < 1) /* (1) */
+        return chmod(name, mode);
+
     if ((noaces = strip_trivial_aces(&oacl, noaces)) == -1) /* (2) */
         goto exit;
 
     if (chmod(name, mode) != 0) /* (3) */
         goto exit;
 
-    if ((nnaces = get_nfsv4_acl(name, &nacl)) == -1) /* (4) */
-        goto exit;
+    if ((nnaces = get_nfsv4_acl(name, &nacl)) == -1) {/* (4) */
+        if (errno != EACCES)
+            goto exit;
+        become_root();
+        nnaces = get_nfsv4_acl(name, &nacl);
+        unbecome_root();
+        if (nnaces == -1)
+            goto exit;
+    }
+
     if ((nnaces = strip_nontrivial_aces(&nacl, nnaces)) == -1) /* (5) */
         goto exit;
 
@@ -242,8 +252,17 @@ int nfsv4_chmod(char *name, mode_t mode)
         goto exit;
 
     if ((ret = acl(name, ACE_SETACL, noaces + nnaces, cacl)) != 0) {
-        LOG(log_error, logtype_afpd, "nfsv4_chmod: error setting acl: %s", strerror(errno));
-        goto exit;
+        if (errno != EACCES) {
+            LOG(log_error, logtype_afpd, "nfsv4_chmod: error setting acl: %s", strerror(errno));
+            goto exit;
+        }
+        become_root();
+        ret = acl(name, ACE_SETACL, noaces + nnaces, cacl);
+        unbecome_root();
+        if (ret != 0) {
+            LOG(log_error, logtype_afpd, "nfsv4_chmod: error setting acl: %s", strerror(errno));
+            goto exit;
+        }
     }
 
 exit:
@@ -251,7 +270,7 @@ exit:
     if (nacl) free(nacl);
     if (cacl) free(cacl);
 
-    LOG(log_debug, logtype_afpd, "nfsv4_chmod(\"%s/%s\", %04o): result: %u",
+    LOG(log_debug, logtype_afpd, "nfsv4_chmod(\"%s/%s\", %04o): result: %d",
         getcwdpath(), name, mode, ret);
 
     return ret;
@@ -283,11 +302,20 @@ int posix_chmod(const char *name, mode_t mode) {
     acl_t acl;
     u_char not_found = (SEARCH_GROUP_OBJ|SEARCH_MASK); /* used as flags */
 
-    LOG(log_maxdebug, logtype_afpd, "posix_chmod: %s mode: 0x%08x", name, mode);
+    LOG(log_maxdebug, logtype_afpd, "posix_chmod(\"%s\", mode: %04o) BEGIN",
+        fullpathname(name), mode);
 
     /* Call chmod() first because there might be some special bits to be set which
      * aren't related to access control.
      */
+#ifdef BSD4_4
+    /*
+     * On FreeBSD chmod_acl() ends up in here too, but on
+     * FreeBSD sine ~9.1 with ZFS doesn't allow setting the g+s bit.
+     * Fixes PR #491.
+     */
+    mode &= 0777;
+#endif
     ret = chmod(name, mode);
 
     if (ret)
@@ -373,7 +401,8 @@ cleanup:
         acl_free(acl);
     }
 done:
-    LOG(log_maxdebug, logtype_afpd, "posix_chmod: %d", ret);
+    LOG(log_maxdebug, logtype_afpd, "posix_chmod(\"%s\", mode: %04o): END: %d",
+        fullpathname(name), mode, ret);
     return ret;
 }