int setacl(const char *pathp, int size, aclent_t *aclpbuf) { acl_t acl = NULL, default_acl = NULL, *current; acl_entry_t entry; acl_permset_t permset; int i, result, default_count = 0; struct stat st; if (stat(pathp, &st) != 0) { return -1; } for (i = 0; i < size; i++) { if (aclpbuf[i].a_type & ACL_DEFAULT) { default_count++; } } acl = acl_init(size - default_count); if (default_count > 0) { default_acl = acl_init(default_count); } for (i = 0; i < size; i++) { if (aclpbuf[i].a_type & ACL_DEFAULT) { current = &default_acl; } else { current = &acl; } acl_create_entry(current, &entry); acl_get_permset(entry, &permset); setmode(&permset, aclpbuf[i].a_perm); acl_set_tag_type(entry, aclpbuf[i].a_type & ~ACL_DEFAULT); acl_set_qualifier(entry, &aclpbuf[i].a_id); acl_free(entry); } result = acl_set_file(pathp, ACL_TYPE_ACCESS, acl); if (result != 0 && (errno == ENOSYS || errno == ENOTSUP)) { if (default_acl != NULL) { return result; } mode_t mode; if (acl_equiv_mode(acl, &mode) == 0) { result = chmod(pathp, mode); } } else if ((result == 0) && S_ISDIR(st.st_mode)) { if (default_acl == NULL) { result = acl_delete_def_file(pathp); } else { result = acl_set_file(pathp, ACL_TYPE_DEFAULT, default_acl); acl_free(default_acl); } } acl_free(acl); return result; }
/* * deletes an access acl or directory default acl if one exists */ static int acl_delete_file(const char *path, acl_type_t type) { int error = 0; /* converts access ACL to a minimal ACL */ if (type == ACL_TYPE_ACCESS) { acl_t acl; acl_entry_t entry; acl_tag_t tag; acl = acl_get_file(path, ACL_TYPE_ACCESS); if (!acl) return -1; error = acl_get_entry(acl, ACL_FIRST_ENTRY, &entry); while (error == 1) { acl_get_tag_type(entry, &tag); switch(tag) { case ACL_USER: case ACL_GROUP: case ACL_MASK: acl_delete_entry(acl, entry); break; } error = acl_get_entry(acl, ACL_NEXT_ENTRY, &entry); } if (!error) error = acl_set_file(path, ACL_TYPE_ACCESS, acl); } else error = acl_delete_def_file(path); return(error); }
/* Set the access control list of path to the permissions defined by mode. */ static int set_acl (char const *path, mode_t mode, struct error_context *ctx) { int ret = 0; #if defined(HAVE_ACL_FROM_MODE) && defined(HAVE_ACL_SET_FILE) /* POSIX 1003.1e draft 17 (abandoned) specific version. */ acl_t acl = acl_from_mode (mode); if (!acl) { error (ctx, ""); return -1; } if (acl_set_file (path, ACL_TYPE_ACCESS, acl) != 0) { ret = -1; if (errno == ENOTSUP || errno == ENOSYS) { (void) acl_free (acl); goto chmod_only; } else { const char *qpath = quote (ctx, path); error (ctx, _("setting permissions for %s"), qpath); quote_free (ctx, qpath); } } (void) acl_free (acl); if (ret == 0 && S_ISDIR (mode)) { # if defined(HAVE_ACL_DELETE_DEF_FILE) ret = acl_delete_def_file (path); # else acl = acl_init (0); ret = acl_set_file (path, ACL_TYPE_DEFAULT, acl); (void) acl_free (acl); # endif if (ret != 0) { const char *qpath = quote (ctx, path); error (ctx, _( "setting permissions for %s"), qpath); quote_free (ctx, qpath); } } return ret; #endif chmod_only: ret = chmod (path, mode); if (ret != 0) { const char *qpath = quote (ctx, path); error (ctx, _("setting permissions for %s"), qpath); quote_free (ctx, qpath); } return ret; }
int qset_acl (char const *name, int desc, mode_t mode) { #if USE_ACL # if HAVE_ACL_GET_FILE /* POSIX 1003.1e draft 17 (abandoned) specific version. */ /* Linux, FreeBSD, MacOS X, IRIX, Tru64 */ # if !HAVE_ACL_TYPE_EXTENDED /* Linux, FreeBSD, IRIX, Tru64 */ /* We must also have acl_from_text and acl_delete_def_file. (acl_delete_def_file could be emulated with acl_init followed by acl_set_file, but acl_set_file with an empty acl is unspecified.) */ # ifndef HAVE_ACL_FROM_TEXT # error Must have acl_from_text (see POSIX 1003.1e draft 17). # endif # ifndef HAVE_ACL_DELETE_DEF_FILE # error Must have acl_delete_def_file (see POSIX 1003.1e draft 17). # endif acl_t acl; int ret; if (HAVE_ACL_FROM_MODE) /* Linux */ { acl = acl_from_mode (mode); if (!acl) return -1; } else /* FreeBSD, IRIX, Tru64 */ { /* If we were to create the ACL using the functions acl_init(), acl_create_entry(), acl_set_tag_type(), acl_set_qualifier(), acl_get_permset(), acl_clear_perm[s](), acl_add_perm(), we would need to create a qualifier. I don't know how to do this. So create it using acl_from_text(). */ # if HAVE_ACL_FREE_TEXT /* Tru64 */ char acl_text[] = "u::---,g::---,o::---,"; # else /* FreeBSD, IRIX */ char acl_text[] = "u::---,g::---,o::---"; # endif if (mode & S_IRUSR) acl_text[ 3] = 'r'; if (mode & S_IWUSR) acl_text[ 4] = 'w'; if (mode & S_IXUSR) acl_text[ 5] = 'x'; if (mode & S_IRGRP) acl_text[10] = 'r'; if (mode & S_IWGRP) acl_text[11] = 'w'; if (mode & S_IXGRP) acl_text[12] = 'x'; if (mode & S_IROTH) acl_text[17] = 'r'; if (mode & S_IWOTH) acl_text[18] = 'w'; if (mode & S_IXOTH) acl_text[19] = 'x'; acl = acl_from_text (acl_text); if (!acl) return -1; } if (HAVE_ACL_SET_FD && desc != -1) ret = acl_set_fd (desc, acl); else ret = acl_set_file (name, ACL_TYPE_ACCESS, acl); if (ret != 0) { int saved_errno = errno; acl_free (acl); if (ACL_NOT_WELL_SUPPORTED (errno)) return chmod_or_fchmod (name, desc, mode); else { errno = saved_errno; return -1; } } else acl_free (acl); if (S_ISDIR (mode) && acl_delete_def_file (name)) return -1; if (!MODE_INSIDE_ACL || (mode & (S_ISUID | S_ISGID | S_ISVTX))) { /* We did not call chmod so far, and either the mode and the ACL are separate or special bits are to be set which don't fit into ACLs. */ return chmod_or_fchmod (name, desc, mode); } return 0; # else /* HAVE_ACL_TYPE_EXTENDED */ /* MacOS X */ /* On MacOS X, acl_get_file (name, ACL_TYPE_ACCESS) and acl_get_file (name, ACL_TYPE_DEFAULT) always return NULL / EINVAL. You have to use acl_get_file (name, ACL_TYPE_EXTENDED) or acl_get_fd (open (name, ...)) to retrieve an ACL. On the other hand, acl_set_file (name, ACL_TYPE_ACCESS, acl) and acl_set_file (name, ACL_TYPE_DEFAULT, acl) have the same effect as acl_set_file (name, ACL_TYPE_EXTENDED, acl): Each of these calls sets the file's ACL. */ acl_t acl; int ret; /* Remove the ACL if the file has ACLs. */ if (HAVE_ACL_GET_FD && desc != -1) acl = acl_get_fd (desc); else acl = acl_get_file (name, ACL_TYPE_EXTENDED); if (acl) { acl_free (acl); acl = acl_init (0); if (acl) { if (HAVE_ACL_SET_FD && desc != -1) ret = acl_set_fd (desc, acl); else ret = acl_set_file (name, ACL_TYPE_EXTENDED, acl); if (ret != 0) { int saved_errno = errno; acl_free (acl); if (ACL_NOT_WELL_SUPPORTED (saved_errno)) return chmod_or_fchmod (name, desc, mode); else { errno = saved_errno; return -1; } } acl_free (acl); } } /* Since !MODE_INSIDE_ACL, we have to call chmod explicitly. */ return chmod_or_fchmod (name, desc, mode); # endif # elif HAVE_FACL && defined GETACLCNT /* Solaris, Cygwin, not HP-UX */ int done_setacl = 0; # ifdef ACE_GETACL /* Solaris also has a different variant of ACLs, used in ZFS and NFSv4 file systems (whereas the other ones are used in UFS file systems). */ /* The flags in the ace_t structure changed in a binary incompatible way when ACL_NO_TRIVIAL etc. were introduced in <sys/acl.h> version 1.15. How to distinguish the two conventions at runtime? We fetch the existing ACL. In the old convention, usually three ACEs have a_flags = ACE_OWNER / ACE_GROUP / ACE_OTHER, in the range 0x0100..0x0400. In the new convention, these values are not used. */ int convention; { int count; ace_t *entries; for (;;) { if (desc != -1) count = facl (desc, ACE_GETACLCNT, 0, NULL); else count = acl (name, ACE_GETACLCNT, 0, NULL); if (count <= 0) { convention = -1; break; } entries = (ace_t *) malloc (count * sizeof (ace_t)); if (entries == NULL) { errno = ENOMEM; return -1; } if ((desc != -1 ? facl (desc, ACE_GETACL, count, entries) : acl (name, ACE_GETACL, count, entries)) == count) { int i; convention = 0; for (i = 0; i < count; i++) if (entries[i].a_flags & (OLD_ACE_OWNER | OLD_ACE_GROUP | OLD_ACE_OTHER)) { convention = 1; break; } free (entries); break; } /* Huh? The number of ACL entries changed since the last call. Repeat. */ free (entries); } } if (convention >= 0) { ace_t entries[6]; int count; int ret; if (convention) { /* Running on Solaris 10. */ entries[0].a_type = OLD_ALLOW; entries[0].a_flags = OLD_ACE_OWNER; entries[0].a_who = 0; /* irrelevant */ entries[0].a_access_mask = (mode >> 6) & 7; entries[1].a_type = OLD_ALLOW; entries[1].a_flags = OLD_ACE_GROUP; entries[1].a_who = 0; /* irrelevant */ entries[1].a_access_mask = (mode >> 3) & 7; entries[2].a_type = OLD_ALLOW; entries[2].a_flags = OLD_ACE_OTHER; entries[2].a_who = 0; entries[2].a_access_mask = mode & 7; count = 3; } else {
int do_setfacl(const char *path, const char *options, const char *textacl) { int r; int type; acl_t acl; int dob; int dok; int dom; struct stat st; char textmode[30]; r = 0; dob = strchr(options,'b') != (char*)NULL; dok = strchr(options,'k') != (char*)NULL; dom = strchr(options,'m') != (char*)NULL; if ((dom && !textacl) || (!dom && (textacl || (!dok && !dob) || strchr(options,'d')))) { errno = EBADRQC; /* "bad request" */ r = -1; } else { if (dob || dok) { r = acl_delete_def_file(path); } if (dob && !r) { if (!stat(path,&st)) { sprintf(textmode,"u::%c%c%c,g::%c%c%c,o::%c%c%c", (st.st_mode & 0400 ? 'r' : '-'), (st.st_mode & 0200 ? 'w' : '-'), (st.st_mode & 0100 ? 'x' : '-'), (st.st_mode & 0040 ? 'r' : '-'), (st.st_mode & 0020 ? 'w' : '-'), (st.st_mode & 0010 ? 'x' : '-'), (st.st_mode & 004 ? 'r' : '-'), (st.st_mode & 002 ? 'w' : '-'), (st.st_mode & 001 ? 'x' : '-')); acl = acl_from_text(textmode); if (acl) { r = acl_set_file(path,ACL_TYPE_ACCESS,acl); acl_free(acl); } else r = -1; } else r = -1; } if (!r && dom) { if (strchr(options,'d')) type = ACL_TYPE_DEFAULT; else type = ACL_TYPE_ACCESS; acl = acl_from_text(textacl); if (acl) { r = acl_set_file(path,type,acl); acl_free(acl); } else r = -1; } } if (r) r = -errno; return (r); }
/* Copy the permissions of src_path to dst_path. This includes the file mode permission bits and ACLs. File ownership is not copied. */ int perm_copy_file (const char *src_path, const char *dst_path, struct error_context *ctx) { #if defined(HAVE_ACL_GET_FILE) && defined(HAVE_ACL_SET_FILE) acl_t acl; #endif struct stat st; int ret = 0; ret = stat(src_path, &st); if (ret != 0) { const char *qpath = quote (ctx, src_path); error (ctx, "%s", qpath); quote_free (ctx, qpath); return -1; } #if defined(HAVE_ACL_GET_FILE) && defined(HAVE_ACL_SET_FILE) /* POSIX 1003.1e draft 17 (abandoned) specific version. */ acl = acl_get_file (src_path, ACL_TYPE_ACCESS); if (acl == NULL) { ret = -1; if (errno == ENOSYS || errno == ENOTSUP) ret = set_acl (dst_path, st.st_mode, ctx); else { const char *qpath = quote (ctx, src_path); error (ctx, "%s", qpath); quote_free (ctx, qpath); } return ret; } if (acl_set_file (dst_path, ACL_TYPE_ACCESS, acl) != 0) { int saved_errno = errno; __apply_mask_to_mode(&st.st_mode, acl); ret = chmod (dst_path, st.st_mode); if ((errno != ENOSYS && errno != ENOTSUP) || acl_entries (acl) != 3) { const char *qpath = quote (ctx, dst_path); errno = saved_errno; error (ctx, _("preserving permissions for %s"), qpath); quote_free (ctx, qpath); ret = -1; } } (void) acl_free (acl); if (ret == 0 && S_ISDIR (st.st_mode)) { acl = acl_get_file (src_path, ACL_TYPE_DEFAULT); if (acl == NULL) { const char *qpath = quote (ctx, src_path); error (ctx, "%s", qpath); quote_free (ctx, qpath); return -1; } # if defined(HAVE_ACL_DELETE_DEF_FILE) if (acl_entries(acl) == 0) ret = acl_delete_def_file(dst_path); else ret = acl_set_file (dst_path, ACL_TYPE_DEFAULT, acl); # else ret = acl_set_file (dst_path, ACL_TYPE_DEFAULT, acl); # endif if (ret != 0) { const char *qpath = quote (ctx, dst_path); error (ctx, _("preserving permissions for %s"), qpath); quote_free (ctx, qpath); } (void) acl_free(acl); } return ret; #else /* POSIX.1 version. */ ret = chmod (dst_path, st.st_mode); if (ret != 0) { const char *qpath = quote (ctx, dst_path); error (ctx, _("setting permissions for %s"), qpath); quote_free (ctx, qpath); } return ret; #endif }
int set_acl (char const *name, int desc, mode_t mode) { #if USE_ACL && HAVE_ACL_SET_FILE && HAVE_ACL_FREE /* POSIX 1003.1e draft 17 (abandoned) specific version. */ /* We must also have have_acl_from_text and acl_delete_def_file. (acl_delete_def_file could be emulated with acl_init followed by acl_set_file, but acl_set_file with an empty acl is unspecified.) */ # ifndef HAVE_ACL_FROM_TEXT # error Must have acl_from_text (see POSIX 1003.1e draft 17). # endif # ifndef HAVE_ACL_DELETE_DEF_FILE # error Must have acl_delete_def_file (see POSIX 1003.1e draft 17). # endif acl_t acl; int ret; if (HAVE_ACL_FROM_MODE) { acl = acl_from_mode (mode); if (!acl) { error (0, errno, "%s", quote (name)); return -1; } } else { char acl_text[] = "u::---,g::---,o::---"; if (mode & S_IRUSR) acl_text[ 3] = 'r'; if (mode & S_IWUSR) acl_text[ 4] = 'w'; if (mode & S_IXUSR) acl_text[ 5] = 'x'; if (mode & S_IRGRP) acl_text[10] = 'r'; if (mode & S_IWGRP) acl_text[11] = 'w'; if (mode & S_IXGRP) acl_text[12] = 'x'; if (mode & S_IROTH) acl_text[17] = 'r'; if (mode & S_IWOTH) acl_text[18] = 'w'; if (mode & S_IXOTH) acl_text[19] = 'x'; acl = acl_from_text (acl_text); if (!acl) { error (0, errno, "%s", quote (name)); return -1; } } if (HAVE_ACL_SET_FD && desc != -1) ret = acl_set_fd (desc, acl); else ret = acl_set_file (name, ACL_TYPE_ACCESS, acl); if (ret != 0) { int saved_errno = errno; acl_free (acl); if (ACL_NOT_WELL_SUPPORTED (errno)) { if (chmod_or_fchmod (name, desc, mode) != 0) saved_errno = errno; else return 0; } error (0, saved_errno, _("setting permissions for %s"), quote (name)); return -1; } else acl_free (acl); if (S_ISDIR (mode) && acl_delete_def_file (name)) { error (0, errno, _("setting permissions for %s"), quote (name)); return -1; } if (mode & (S_ISUID | S_ISGID | S_ISVTX)) { /* We did not call chmod so far, so the special bits have not yet been set. */ if (chmod_or_fchmod (name, desc, mode)) { error (0, errno, _("preserving permissions for %s"), quote (name)); return -1; } } return 0; #else int ret = chmod_or_fchmod (name, desc, mode); if (ret) error (0, errno, _("setting permissions for %s"), quote (name)); return ret; #endif }
int do_set( const char *path_p, const struct stat *st, const seq_t seq) { acl_t old_acl = NULL, old_default_acl = NULL; acl_t acl = NULL, default_acl = NULL; acl_t *xacl, *old_xacl; acl_entry_t ent; cmd_t cmd; int which_entry; int errors = 0, error; char *acl_text; int acl_modified = 0, default_acl_modified = 0; int acl_mask_provided = 0, default_acl_mask_provided = 0; /* Execute the commands in seq (read ACLs on demand) */ error = seq_get_cmd(seq, SEQ_FIRST_CMD, &cmd); if (error == 0) return 0; while (error == 1) { if (cmd->c_type == ACL_TYPE_ACCESS) { xacl = &acl; old_xacl = &old_acl; acl_modified = 1; if (cmd->c_tag == ACL_MASK) acl_mask_provided = 1; } else { xacl = &default_acl; old_xacl = &old_default_acl; default_acl_modified = 1; if (cmd->c_tag == ACL_MASK) default_acl_mask_provided = 1; } RETRIEVE_ACL(cmd->c_type); /* Check for `X', and replace with `x' as appropriate. */ if (cmd->c_perm & CMD_PERM_COND_EXECUTE) { cmd->c_perm &= ~CMD_PERM_COND_EXECUTE; if (S_ISDIR(st->st_mode) || has_execute_perms(*xacl)) cmd->c_perm |= CMD_PERM_EXECUTE; } switch(cmd->c_cmd) { case CMD_ENTRY_REPLACE: ent = find_entry(*xacl, cmd->c_tag, cmd->c_id); if (!ent) { if (acl_create_entry(xacl, &ent) != 0) goto fail; acl_set_tag_type(ent, cmd->c_tag); if (cmd->c_id != ACL_UNDEFINED_ID) acl_set_qualifier(ent, &cmd->c_id); } set_perm(ent, cmd->c_perm, ~cmd->c_perm); break; case CMD_ENTRY_ADD: ent = find_entry(*xacl, cmd->c_tag, cmd->c_id); if (ent) set_perm(ent, cmd->c_perm, 0); break; case CMD_ENTRY_SUBTRACT: ent = find_entry(*xacl, cmd->c_tag, cmd->c_id); if (ent) set_perm(ent, 0, cmd->c_perm); break; case CMD_REMOVE_ENTRY: ent = find_entry(*xacl, cmd->c_tag, cmd->c_id); if (ent) acl_delete_entry(*xacl, ent); else /* ignore */; break; case CMD_REMOVE_EXTENDED_ACL: remove_extended_entries(acl); break; case CMD_REMOVE_ACL: acl_free(*xacl); *xacl = acl_init(5); if (!*xacl) goto fail; break; default: errno = EINVAL; goto fail; } error = seq_get_cmd(seq, SEQ_NEXT_CMD, &cmd); } if (error < 0) goto fail; /* Try to fill in missing entries */ if (default_acl && acl_entries(default_acl) != 0) { xacl = &acl; old_xacl = &old_acl; if (!find_entry(default_acl, ACL_USER_OBJ, ACL_UNDEFINED_ID)) { if (!acl) RETRIEVE_ACL(ACL_TYPE_ACCESS); clone_entry(acl, ACL_USER_OBJ, &default_acl, ACL_USER_OBJ); } if (!find_entry(default_acl, ACL_GROUP_OBJ, ACL_UNDEFINED_ID)) { if (!acl) RETRIEVE_ACL(ACL_TYPE_ACCESS); clone_entry(acl, ACL_GROUP_OBJ, &default_acl, ACL_GROUP_OBJ); } if (!find_entry(default_acl, ACL_OTHER, ACL_UNDEFINED_ID)) { if (!acl) RETRIEVE_ACL(ACL_TYPE_ACCESS); clone_entry(acl, ACL_OTHER, &default_acl, ACL_OTHER); } } /* update mask entries and check if ACLs are valid */ if (acl && acl_modified) { if (acl_equiv_mode(acl, NULL) != 0) { if (!acl_mask_provided && !find_entry(acl, ACL_MASK, ACL_UNDEFINED_ID)) clone_entry(acl, ACL_GROUP_OBJ, &acl, ACL_MASK); if (opt_recalculate != -1 && (!acl_mask_provided || opt_recalculate == 1)) acl_calc_mask(&acl); } error = acl_check(acl, &which_entry); if (error < 0) goto fail; if (error > 0) { acl_text = acl_to_any_text(acl, NULL, ',', 0); fprintf(stderr, gettext("%s: %s: Malformed access ACL " "`%s': %s at entry %d\n"), progname, path_p, acl_text, acl_error(error), which_entry+1); acl_free(acl_text); errors++; goto cleanup; } } if (default_acl && acl_entries(default_acl) != 0 && default_acl_modified) { if (acl_equiv_mode(default_acl, NULL) != 0) { if (!default_acl_mask_provided && !find_entry(default_acl,ACL_MASK,ACL_UNDEFINED_ID)) clone_entry(default_acl, ACL_GROUP_OBJ, &default_acl, ACL_MASK); if (opt_recalculate != -1 && (!default_acl_mask_provided || opt_recalculate == 1)) acl_calc_mask(&default_acl); } error = acl_check(default_acl, &which_entry); if (error < 0) goto fail; if (error > 0) { acl_text = acl_to_any_text(default_acl, NULL, ',', 0); fprintf(stderr, gettext("%s: %s: Malformed default ACL " "`%s': %s at entry %d\n"), progname, path_p, acl_text, acl_error(error), which_entry+1); acl_free(acl_text); errors++; goto cleanup; } } /* Only directores can have default ACLs */ if (default_acl && !S_ISDIR(st->st_mode) && opt_recursive) { /* In recursive mode, ignore default ACLs for files */ acl_free(default_acl); default_acl = NULL; } /* check which ACLs have changed */ if (acl && old_acl && acl_cmp(old_acl, acl) == 0) { acl_free(acl); acl = NULL; } if ((default_acl && old_default_acl && acl_cmp(old_default_acl, default_acl) == 0)) { acl_free(default_acl); default_acl = NULL; } /* update the file system */ if (opt_test) { print_test(stdout, path_p, st, acl, default_acl); goto cleanup; } if (acl) { if (acl_set_file(path_p, ACL_TYPE_ACCESS, acl) != 0) { if (errno == ENOSYS || errno == ENOTSUP) { int saved_errno = errno; mode_t mode; if (acl_equiv_mode(acl, &mode) != 0) { errno = saved_errno; goto fail; } else if (chmod(path_p, mode) != 0) goto fail; } else goto fail; } } if (default_acl) { if (S_ISDIR(st->st_mode)) { if (acl_entries(default_acl) == 0) { if (acl_delete_def_file(path_p) != 0 && errno != ENOSYS && errno != ENOTSUP) goto fail; } else { if (acl_set_file(path_p, ACL_TYPE_DEFAULT, default_acl) != 0) goto fail; } } else { if (acl_entries(default_acl) != 0) { fprintf(stderr, gettext( "%s: %s: Only directories " "can have default ACLs\n"), progname, path_p); errors++; goto cleanup; } } } error = 0; cleanup: if (acl) acl_free(acl); if (old_acl) acl_free(old_acl); if (default_acl) acl_free(default_acl); if (old_default_acl) acl_free(old_default_acl); return errors; fail: fprintf(stderr, "%s: %s: %s\n", progname, path_p, strerror(errno)); errors++; goto cleanup; }
int main(int argc, char *argv[]) { Boolean recalcMask, useDefaultACL; Boolean modifyACL, removeACL, removeDefaultACL, checkValidity; int optCnt, j, opt, numEntries, en; acl_type_t type; char *aclSpec; acl_t acl; acl_entry_t entry; struct AccessControlEntry aclist[MAX_ENTRIES]; if (argc < 2 || strcmp(argv[1], "--help") == 0) usageError(argv[0], NULL, FALSE); /* Parse command-line options */ recalcMask = TRUE; useDefaultACL = FALSE; modifyACL = FALSE; removeACL = FALSE; checkValidity = FALSE; removeDefaultACL = FALSE; optCnt = 0; while ((opt = getopt(argc, argv, "m:x:kdnV:")) != -1) { switch (opt) { case 'm': modifyACL = TRUE; aclSpec = optarg; optCnt++; break; case 'x': removeACL = TRUE; aclSpec = optarg; optCnt++; break; case 'k': removeDefaultACL = TRUE; optCnt++; break; case 'V': checkValidity = TRUE; aclSpec = optarg; optCnt++; break; case 'd': useDefaultACL = TRUE; break; case 'n': recalcMask = FALSE; break; default: usageError(argv[0], "Bad option\n", TRUE); break; } } if (optCnt != 1) usageError(argv[0], "Specify exactly one of -m, -x, -k, or -V\n", TRUE); if (checkValidity && useDefaultACL) usageError(argv[0], "Can't specify -d with -V\n", TRUE); if (checkValidity) { if (parseACL(aclSpec, aclist, TRUE) == -1) { fatal("Bad ACL entry specification"); } else { printf("ACL is valid\n"); exit(EXIT_SUCCESS); } } if (modifyACL || removeACL) { numEntries = parseACL(aclSpec, aclist, modifyACL); if (numEntries == -1) usageError(argv[0], "Bad ACL specification\n", TRUE); } type = useDefaultACL ? ACL_TYPE_DEFAULT : ACL_TYPE_ACCESS; /* Perform the operation on each file argument */ for (j = optind; j < argc; j++) { if (removeDefaultACL) { if (acl_delete_def_file(argv[j]) == -1) errExit("acl_delete_def_file: %s", argv[j]); } else if (modifyACL || removeACL) { acl = acl_get_file(argv[j], type); if (acl == NULL) errExit("acl_get_file"); /* Apply each of the entries in 'aclist' to the current file */ for (en = 0; en < numEntries; en++) { entry = findEntry(acl, aclist[en].tag, aclist[en].qual); if (removeACL) { if (entry != NULL) if (acl_delete_entry(acl, entry) == -1) errExit("acl_delete_entry"); } else { /* modifyACL */ if (entry == NULL) { /* Entry didn't exist in ACL -- create a new entry with required tag and qualifier */ if (acl_create_entry(&acl, &entry) == -1) errExit("acl_create_entry"); if (acl_set_tag_type(entry, aclist[en].tag) == -1) errExit("acl_set_tag_type"); if (aclist[en].tag == ACL_USER || aclist[en].tag == ACL_GROUP) if (acl_set_qualifier(entry, &aclist[en].qual) == -1) errExit("acl_set_qualifier"); } setPerms(entry, aclist[en].perms); } /* Recalculate the mask entry if requested */ if (recalcMask) if (acl_calc_mask(&acl) == -1) errExit("acl_calc_mask"); /* Update the file ACL */ if (acl_valid(acl) == -1) errExit("acl_valid"); if (acl_set_file(argv[j], type, acl) == -1) errExit("acl_set_file"); } if (acl_free(acl) == -1) errExit("acl_free"); } else { fatal("Bad logic!"); } } exit(EXIT_SUCCESS); }
int posixacl_sys_acl_delete_def_file(vfs_handle_struct *handle, const char *path) { return acl_delete_def_file(path); }