void print_test( FILE *file, const char *path_p, const struct stat *st, const acl_t acl, const acl_t default_acl) { char *acl_text, *default_acl_text; acl_text = acl_to_any_text(acl, NULL, ',', TEXT_ABBREVIATE); default_acl_text = acl_to_any_text(default_acl, "d:", ',', TEXT_ABBREVIATE); fprintf(file, "%s: %s,%s\n", path_p, acl_text ? acl_text : "*", default_acl_text ? default_acl_text : "*"); acl_free(acl_text); acl_free(default_acl_text); }
/* * lists the acl for a file/dir in short text form * return 0 on failure * return 1 on success */ static int list_acl(char *file) { acl_t acl = NULL; acl_t dacl = NULL; char *acl_text, *dacl_text = NULL; if ((acl = acl_get_file(file, ACL_TYPE_ACCESS)) == NULL) { fprintf(stderr, _("%s: cannot get access ACL on '%s': %s\n"), program, file, strerror(errno)); return 0; } if ((dacl = acl_get_file(file, ACL_TYPE_DEFAULT)) == NULL && (errno != EACCES)) { /* EACCES given if not a directory */ fprintf(stderr, _("%s: cannot get default ACL on '%s': %s\n"), program, file, strerror(errno)); return 0; } acl_text = acl_to_any_text(acl, NULL, ',', TEXT_ABBREVIATE); if (acl_text == NULL) { fprintf(stderr, _("%s: cannot get access ACL text on " "'%s': %s\n"), program, file, strerror(errno)); return 0; } if (acl_entries(dacl) > 0) { dacl_text = acl_to_any_text(dacl, NULL, ',', TEXT_ABBREVIATE); if (dacl_text == NULL) { fprintf(stderr, _("%s: cannot get default ACL text on " "'%s': %s\n"), program, file, strerror(errno)); return 0; } } if (dacl_text) { printf("%s [%s/%s]\n", file, acl_text, dacl_text); acl_free(dacl_text); } else printf("%s [%s]\n", file, acl_text); acl_free(acl_text); acl_free(acl); acl_free(dacl); return 1; }
int main(int argc, char **argv) { int c; char *file; char *acl_text; int getaccess = 0; int getdefault = 0; int usefd = 0; int fd = -1; acl_t acl; prog = basename(argv[0]); while ((c = getopt(argc, argv, "adf")) != -1) { switch (c) { case 'a': getaccess = 1; break; case 'd': getdefault = 1; break; case 'f': usefd = 1; break; case '?': usage(); return 1; } } if (getdefault && usefd) { fprintf(stderr, "%s: -f and -d are not compatible\n", prog); return 1; } /* need path */ if (optind == argc) { usage(); exit(1); } else { file = argv[optind]; } if (usefd) { fd = open(file, O_RDONLY); if (fd < 0) { fprintf (stderr, "%s: error opening \"%s\": %s\n", prog, file, strerror(errno)); usage(); return 1; } } if (getaccess) { if (usefd) { acl = acl_get_fd(fd); } else { acl = acl_get_file(file, ACL_TYPE_ACCESS); } if (acl == NULL) { fprintf(stderr, "%s: error getting access ACL on \"%s\": %s\n", prog, file, strerror(errno)); return 0; } acl_text = acl_to_any_text(acl, NULL, ',', TEXT_ABBREVIATE); if (acl_text == NULL) { fprintf(stderr, "%s: cannot get access ACL text on '%s': %s\n", prog, file, strerror(errno)); return 0; } printf("%s: access %s", file, acl_text); acl_free(acl_text); acl_free(acl); } if (getdefault) { acl = acl_get_file(file, ACL_TYPE_DEFAULT); if (acl == NULL) { fprintf(stderr, "%s: error getting default ACL on \"%s\": %s\n", prog, file, strerror(errno)); return 0; } acl_text = acl_to_any_text(acl, NULL, ',', TEXT_ABBREVIATE); if (acl_text == NULL) { fprintf(stderr, "%s: cannot get default ACL text on '%s': %s\n", prog, file, strerror(errno)); return 0; } printf("%s: default %s", file, acl_text); acl_free(acl_text); acl_free(acl); } return 0; }
int do_print(const char *path_p, const struct stat *st, int walk_flags, void *unused) { const char *default_prefix = NULL; acl_t acl = NULL, default_acl = NULL; int error = 0; if (walk_flags & WALK_TREE_FAILED) { fprintf(stderr, "%s: %s: %s\n", progname, xquote(path_p, "\n\r"), strerror(errno)); return 1; } /* * Symlinks can never have ACLs, so when doing a physical walk, we * skip symlinks altogether, and when doing a half-logical walk, we * skip all non-toplevel symlinks. */ if ((walk_flags & WALK_TREE_SYMLINK) && ((walk_flags & WALK_TREE_PHYSICAL) || !(walk_flags & (WALK_TREE_TOPLEVEL | WALK_TREE_LOGICAL)))) return 0; if (opt_print_acl) { acl = acl_get_file(path_p, ACL_TYPE_ACCESS); if (acl == NULL && (errno == ENOSYS || errno == ENOTSUP)) acl = acl_get_file_mode(path_p); if (acl == NULL) goto fail; } if (opt_print_default_acl && S_ISDIR(st->st_mode)) { default_acl = acl_get_file(path_p, ACL_TYPE_DEFAULT); if (default_acl == NULL) { if (errno != ENOSYS && errno != ENOTSUP) goto fail; } else if (acl_entries(default_acl) == 0) { acl_free(default_acl); default_acl = NULL; } } if (opt_skip_base && (!acl || acl_equiv_mode(acl, NULL) == 0) && !default_acl) return 0; if (opt_print_acl && opt_print_default_acl) default_prefix = "default:"; if (opt_strip_leading_slash) { if (*path_p == '/') { if (!absolute_warning) { fprintf(stderr, _("%s: Removing leading " "'/' from absolute path names\n"), progname); absolute_warning = 1; } while (*path_p == '/') path_p++; } else if (*path_p == '.' && *(path_p+1) == '/') while (*++path_p == '/') /* nothing */ ; if (*path_p == '\0') path_p = "."; } if (opt_tabular) { if (do_show(stdout, path_p, st, acl, default_acl) != 0) goto fail; } else { if (opt_comments) { printf("# file: %s\n", xquote(path_p, "\n\r")); printf("# owner: %s\n", xquote(user_name(st->st_uid, opt_numeric), " \t\n\r")); printf("# group: %s\n", xquote(group_name(st->st_gid, opt_numeric), " \t\n\r")); if ((st->st_mode & (S_ISVTX | S_ISUID | S_ISGID)) && !posixly_correct) printf("# flags: %s\n", flagstr(st->st_mode)); } if (acl != NULL) { char *acl_text = acl_to_any_text(acl, NULL, '\n', print_options); if (!acl_text) goto fail; if (puts(acl_text) < 0) { acl_free(acl_text); goto fail; } acl_free(acl_text); } if (default_acl != NULL) { char *acl_text = acl_to_any_text(default_acl, default_prefix, '\n', print_options); if (!acl_text) goto fail; if (puts(acl_text) < 0) { acl_free(acl_text); goto fail; } acl_free(acl_text); } } if (acl || default_acl || opt_comments) printf("\n"); cleanup: if (acl) acl_free(acl); if (default_acl) acl_free(default_acl); return error; fail: fprintf(stderr, "%s: %s: %s\n", progname, xquote(path_p, "\n\r"), strerror(errno)); error = -1; goto cleanup; }
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; }