From 6a2e7a0f796cd08d7f211b897846dd5df769800c Mon Sep 17 00:00:00 2001 From: Frank Lahm Date: Tue, 19 Oct 2010 17:04:01 +0200 Subject: [PATCH] chmod wrapper for onnv145+ to preserve ACL --- etc/afpd/filedir.c | 3 +- etc/afpd/unix.c | 1 + etc/cnid_dbd/cmd_dbd_scanvol.c | 1 + etc/cnid_dbd/usockfd.c | 3 ++ include/atalk/acl.h | 3 ++ libatalk/acl/unix.c | 95 +++++++++++++++++++++++----------- libatalk/vfs/unix.c | 1 + 7 files changed, 74 insertions(+), 33 deletions(-) diff --git a/etc/afpd/filedir.c b/etc/afpd/filedir.c index 3e5cb2f5..8b47cba7 100644 --- a/etc/afpd/filedir.c +++ b/etc/afpd/filedir.c @@ -1,6 +1,4 @@ /* - * $Id: filedir.c,v 1.73 2010-03-12 15:16:49 franklahm Exp $ - * * Copyright (c) 1990,1993 Regents of The University of Michigan. * All Rights Reserved. See COPYRIGHT. */ @@ -39,6 +37,7 @@ char *strchr (), *strrchr (); #include #include #include +#include #include "directory.h" #include "desktop.h" diff --git a/etc/afpd/unix.c b/etc/afpd/unix.c index 57491a71..0df7ee54 100644 --- a/etc/afpd/unix.c +++ b/etc/afpd/unix.c @@ -38,6 +38,7 @@ char *strchr (), *strrchr (); #include #include #include +#include #include "auth.h" #include "directory.h" diff --git a/etc/cnid_dbd/cmd_dbd_scanvol.c b/etc/cnid_dbd/cmd_dbd_scanvol.c index edc15bb4..45d67ae1 100644 --- a/etc/cnid_dbd/cmd_dbd_scanvol.c +++ b/etc/cnid_dbd/cmd_dbd_scanvol.c @@ -33,6 +33,7 @@ #include #include #include +#include #include "cmd_dbd.h" #include "dbif.h" diff --git a/etc/cnid_dbd/usockfd.c b/etc/cnid_dbd/usockfd.c index 6c97fe73..cdacb71f 100644 --- a/etc/cnid_dbd/usockfd.c +++ b/etc/cnid_dbd/usockfd.c @@ -67,6 +67,9 @@ int usockfd_create(char *usock_fn, mode_t mode, int backlog) return -1; } +#ifdef chmod +#undef chmod +#endif if (chmod(usock_fn, mode) < 0) { LOG(log_error, logtype_cnid, "error changing permissions for %s: %s", usock_fn, strerror(errno)); diff --git a/include/atalk/acl.h b/include/atalk/acl.h index 44ea9655..c49ed0f4 100644 --- a/include/atalk/acl.h +++ b/include/atalk/acl.h @@ -26,6 +26,9 @@ /* Solaris NFSv4 ACL stuff */ #ifdef HAVE_NFSv4_ACLS + +#define chmod nfsv4_chmod + extern int get_nfsv4_acl(const char *name, ace_t **retAces); extern int remove_acl(const char *name); extern int strip_trivial_aces(ace_t **saces, int sacecount); diff --git a/libatalk/acl/unix.c b/libatalk/acl/unix.c index 63b7dfdd..b075ec6e 100644 --- a/libatalk/acl/unix.c +++ b/libatalk/acl/unix.c @@ -75,6 +75,37 @@ int get_nfsv4_acl(const char *name, ace_t **retAces) return ace_count; } +/* + Concatenate ACEs +*/ +ace_t *concat_aces(ace_t *aces1, int ace1count, ace_t *aces2, int ace2count) +{ + ace_t *new_aces; + int i, j; + + /* malloc buffer for new ACL */ + if ((new_aces = malloc((ace1count + ace2count) * sizeof(ace_t))) == NULL) { + LOG(log_error, logtype_afpd, "combine_aces: malloc %s", strerror(errno)); + return NULL; + } + + /* Copy ACEs from buf1 */ + for (i=0; i < ace1count; ) { + memcpy(&new_aces[i], &aces1[i], sizeof(ace_t)); + i++; + } + + j = i; + + /* Copy ACEs from buf2 */ + for (i=0; i < ace2count; ) { + memcpy(&new_aces[j], &aces2[i], sizeof(ace_t)); + i++; + j++; + } + return new_aces; +} + /* Remove any trivial ACE "in-place". Returns no of non-trivial ACEs */ @@ -85,6 +116,9 @@ int strip_trivial_aces(ace_t **saces, int sacecount) ace_t *aces = *saces; ace_t *new_aces; + if (aces == NULL || sacecount <= 0) + return 0; + /* Count non-trivial ACEs */ for (i=0; i < sacecount; ) { if ( ! (aces[i].a_flags & (ACE_OWNER | ACE_GROUP | ACE_EVERYONE))) @@ -114,37 +148,6 @@ int strip_trivial_aces(ace_t **saces, int sacecount) return nontrivaces; } -/* - Concatenate ACEs -*/ -ace_t *concat_aces(ace_t *aces1, int ace1count, ace_t *aces2, int ace2count) -{ - ace_t *new_aces; - int i, j; - - /* malloc buffer for new ACL */ - if ((new_aces = malloc((ace1count + ace2count) * sizeof(ace_t))) == NULL) { - LOG(log_error, logtype_afpd, "combine_aces: malloc %s", strerror(errno)); - return NULL; - } - - /* Copy ACEs from buf1 */ - for (i=0; i < ace1count; ) { - memcpy(&new_aces[i], &aces1[i], sizeof(ace_t)); - i++; - } - - j = i; - - /* Copy ACEs from buf2 */ - for (i=0; i < ace2count; ) { - memcpy(&new_aces[j], &aces2[i], sizeof(ace_t)); - i++; - j++; - } - return new_aces; -} - /* Remove non-trivial ACEs "in-place". Returns no of trivial ACEs. */ @@ -201,7 +204,37 @@ int strip_nontrivial_aces(ace_t **saces, int sacecount) */ int nfsv4_chmod(char *name, mode_t mode) { + int ret = -1; + int noaces, nnaces; + ace_t *oacl = NULL, *nacl = NULL, *cacl; + + if ((noaces = get_nfsv4_acl(name, &oacl)) == -1) /* (1) */ + goto exit; + 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 = strip_nontrivial_aces(&nacl, nnaces)) == -1) /* (5) */ + goto exit; + + if ((cacl = concat_aces(oacl, noaces, nacl, nnaces)) == NULL) /* (6) */ + 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; + } + +exit: + if (oacl) free(oacl); + if (nacl) free(nacl); + if (cacl) free(cacl); + + return ret; } #if 0 diff --git a/libatalk/vfs/unix.c b/libatalk/vfs/unix.c index 4812e964..a60b08a4 100644 --- a/libatalk/vfs/unix.c +++ b/libatalk/vfs/unix.c @@ -24,6 +24,7 @@ #include #include #include +#include /* ----------------------------- a dropbox is a folder where w is set but not r eg: -- 2.39.2