]> git.saurik.com Git - apple/file_cmds.git/blobdiff - chmod/chmod_acl.c
file_cmds-321.100.10.0.1.tar.gz
[apple/file_cmds.git] / chmod / chmod_acl.c
index 16ed9f27178cf6a53d02c13651d98a2b02acfa0e..5ac4c177c04dd179c684c96f1053c35179c547b7 100644 (file)
@@ -100,31 +100,22 @@ static struct {
 
 uuid_t *
 name_to_uuid(char *tok, int nametype) {
-       struct passwd *tpass = NULL;
-       struct group *tgrp = NULL;
        uuid_t *entryg = NULL;
+       size_t len = strlen(tok);
 
-       if ((entryg = (uuid_t *) calloc(1,sizeof(uuid_t))) == NULL)
-               err(1, "Unable to allocate a uuid");
-
-       if (nametype & NAME_USER)
-               tpass = getpwnam(tok);
-
-       if (NULL == tpass && (nametype & NAME_GROUP))
-               tgrp = getgrnam(tok);
+       if ((entryg = (uuid_t *) calloc(1, sizeof(uuid_t))) == NULL) {
+               errx(1, "Unable to allocate a uuid");
+       }
 
-       if (tpass) {
-               if (0 != mbr_uid_to_uuid(tpass->pw_uid, *entryg)) {
-                       errx(1, "mbr_uid_to_uuid(): Unable to translate uid %d", tpass->pw_uid);
-               }
-       } else if (tgrp) {
-               if (0 != mbr_gid_to_uuid(tgrp->gr_gid, *entryg)) {
-                       errx(1, "mbr_gid_to_uuid(): Unable to translate gid %d", tgrp->gr_gid);
-               }
-       } else {
-               errx(1, "Unable to translate '%s' to a UID/GID", tok);
+       if ((nametype & NAME_USER) && mbr_identifier_to_uuid(ID_TYPE_USERNAME, tok, len, *entryg) == 0) {
+               return entryg;
+       }
+       
+       if ((nametype & NAME_GROUP) && mbr_identifier_to_uuid(ID_TYPE_GROUPNAME, tok, len, *entryg) == 0) {
+               return entryg;
        }
-       return entryg;
+       
+       errx(1, "Unable to translate '%s' to a UUID", tok);
 }
 
 /* Convert an acl entry in string form to an acl_entry_t */
@@ -341,7 +332,7 @@ compare_acl_permsets(acl_permset_t aperms, acl_permset_t bperms)
        return MATCH_EXACT;
 }
 
-int
+static int
 compare_acl_flagsets(acl_flagset_t aflags, acl_flagset_t bflags)
 {
        int i;
@@ -362,9 +353,16 @@ compare_acl_entries(acl_entry_t a, acl_entry_t b)
        acl_permset_t aperms, bperms;
        acl_flagset_t aflags, bflags;
        int pcmp = 0, fcmp = 0;
+       void *aqual, *bqual;
 
-       if (0 != compare_acl_qualifiers(acl_get_qualifier(a), 
-                                       acl_get_qualifier(b)))
+       aqual = acl_get_qualifier(a);
+       bqual = acl_get_qualifier(b);
+
+       int compare = compare_acl_qualifiers(aqual, bqual);
+       acl_free(aqual);
+       acl_free(bqual);
+
+       if (compare != 0)
                return MATCH_NONE;
 
        if (0 != acl_get_tag_type(a, &atag))
@@ -531,7 +529,7 @@ subtract_from_entry(acl_entry_t rentry, acl_entry_t  modifier, int* valid_perms)
        return 0;
 }
 /* Add the perms specified in modifier to rentry */
-int
+static int
 merge_entry_perms(acl_entry_t rentry, acl_entry_t  modifier)
 {
        acl_permset_t rperms, mperms;
@@ -672,13 +670,13 @@ ma_exit:
 }
 
 int
-modify_file_acl(unsigned int optflags, const char *path, acl_t modifier, int position, int inheritance_level) {
+modify_file_acl(unsigned int optflags, const char *path, acl_t modifier, int position, int inheritance_level, int follow) {
        
        acl_t oacl = NULL;
        unsigned aindex  = 0, flag_new_acl = 0;
        acl_entry_t newent = NULL;
        acl_entry_t entry = NULL;
-       unsigned retval = 0 ;
+       unsigned retval = 0;
 
        extern int fflag;
 
@@ -701,26 +699,52 @@ modify_file_acl(unsigned int optflags, const char *path, acl_t modifier, int pos
 
        if (optflags & ACL_CLEAR_FLAG) {
                filesec_t fsec = filesec_init();
-               if (fsec == NULL)
+               if (fsec == NULL) {
                        err(1, "filesec_init() failed");
-               if (filesec_set_property(fsec, FILESEC_ACL,
-                                        _FILESEC_REMOVE_ACL) != 0)
+               }
+               if (filesec_set_property(fsec, FILESEC_ACL, _FILESEC_REMOVE_ACL) != 0) {
                        err(1, "filesec_set_property() failed");
-               if (chmodx_np(path, fsec) != 0) {
-                       if (!fflag)
-                               warn("Failed to clear ACL on file %s", path);
-                       retval = 1;
-               } else
-                       retval = 0;
+                }
+               if (follow) {
+                       if (chmodx_np(path, fsec) != 0) {
+                                if (!fflag) {
+                                       warn("Failed to clear ACL on file %s", path);
+                               }
+                               retval = 1;
+                       }
+               } else {
+                       int fd = open(path, O_SYMLINK);
+                       if (fd != -1) {
+                               if (fchmodx_np(fd, fsec) != 0) {
+                                       if (!fflag) {
+                                               warn("Failed to clear ACL on file %s", path);
+                                       }
+                                       retval = 1;
+                               }
+                               close(fd);
+                       } else {
+                               if (!fflag) {
+                                       warn("Failed to open file %s", path);
+                               }
+                               retval = 1;
+                       }
+               }
                filesec_free(fsec);
                return (retval);
        }
 
-       if (optflags & ACL_FROM_STDIN)
+       if (optflags & ACL_FROM_STDIN) {
                oacl = acl_dup(modifier);
-       else {
-               oacl = acl_get_file(path, ACL_TYPE_EXTENDED);
-               
+       } else {
+               if (follow) {
+                       oacl = acl_get_file(path, ACL_TYPE_EXTENDED);
+               } else {
+                       int fd = open(path, O_SYMLINK);
+                       if (fd != -1) {
+                               oacl = acl_get_fd_np(fd, ACL_TYPE_EXTENDED);
+                               close(fd);
+                       }
+               }
                if ((oacl == NULL) ||
                    (acl_get_entry(oacl,ACL_FIRST_ENTRY, &newent) != 0)) {
                        if ((oacl = acl_init(1)) == NULL)
@@ -807,11 +831,23 @@ modify_file_acl(unsigned int optflags, const char *path, acl_t modifier, int pos
  * "changeset" mechanism, common locking  strategy, or kernel
  * supplied reservation mechanism to prevent this race.
  */
-       if (!(optflags & (ACL_TO_STDOUT|ACL_CHECK_CANONICITY)) && 
-           (0 != acl_set_file(path, ACL_TYPE_EXTENDED, oacl))){
-               if (!fflag)
-                       warn("Failed to set ACL on file '%s'", path);
-               retval = 1;
+       if (!(optflags & (ACL_TO_STDOUT|ACL_CHECK_CANONICITY))) {
+               int status = -1;
+               if (follow) {
+                       status = acl_set_file(path, ACL_TYPE_EXTENDED, oacl);
+               } else {
+                       int fd = open(path, O_SYMLINK);
+                       if (fd != -1) {
+                               status = acl_set_fd_np(fd, oacl,
+                                                       ACL_TYPE_EXTENDED);
+                               close(fd);
+                       }
+               }
+               if (status != 0) {
+                       if (!fflag)
+                               warn("Failed to set ACL on file '%s'", path);
+                       retval = 1;
+               }
        }
        
        if (oacl)