Blame tools/do_set.c

rpm-build 0a0c83
/*
rpm-build 0a0c83
  File: do_set.c
rpm-build 0a0c83
  (Linux Access Control List Management)
rpm-build 0a0c83
rpm-build 0a0c83
  Copyright (C) 1999, 2000
rpm-build 0a0c83
  Andreas Gruenbacher, <a.gruenbacher@bestbits.at>
rpm-build 0a0c83
 	
rpm-build 0a0c83
  This program is free software; you can redistribute it and/or
rpm-build 0a0c83
  modify it under the terms of the GNU Lesser General Public
rpm-build 0a0c83
  License as published by the Free Software Foundation; either
rpm-build 0a0c83
  version 2.1 of the License, or (at your option) any later version.
rpm-build 0a0c83
rpm-build 0a0c83
  This program is distributed in the hope that it will be useful,
rpm-build 0a0c83
  but WITHOUT ANY WARRANTY; without even the implied warranty of
rpm-build 0a0c83
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
rpm-build 0a0c83
  Lesser General Public License for more details.
rpm-build 0a0c83
rpm-build 0a0c83
  You should have received a copy of the GNU Lesser General Public
rpm-build 0a0c83
  License along with this library; if not, write to the Free Software
rpm-build 0a0c83
  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
rpm-build 0a0c83
*/
rpm-build 0a0c83
rpm-build 0a0c83
#include "config.h"
rpm-build 0a0c83
#include <stdio.h>
rpm-build 0a0c83
#include <errno.h>
rpm-build 0a0c83
#include <sys/acl.h>
rpm-build 0a0c83
#include <acl/libacl.h>
rpm-build 0a0c83
rpm-build 0a0c83
#include <stdlib.h>
rpm-build 0a0c83
#include <string.h>
rpm-build 0a0c83
#include <getopt.h>
rpm-build 0a0c83
#include <sys/types.h>
rpm-build 0a0c83
#include <sys/stat.h>
rpm-build 0a0c83
#include <unistd.h>
rpm-build 0a0c83
#include <dirent.h>
rpm-build 0a0c83
#include <ftw.h>
rpm-build 0a0c83
#include "misc.h"
rpm-build 0a0c83
#include "sequence.h"
rpm-build 0a0c83
#include "do_set.h"
rpm-build 0a0c83
#include "parse.h"
rpm-build 0a0c83
#include "walk_tree.h"
rpm-build 0a0c83
rpm-build 0a0c83
rpm-build 0a0c83
extern const char *progname;
rpm-build 0a0c83
extern int opt_recalculate;
rpm-build 0a0c83
extern int opt_test;
rpm-build 0a0c83
extern int print_options;
rpm-build 0a0c83
rpm-build 0a0c83
acl_entry_t
rpm-build 0a0c83
find_entry(
rpm-build 0a0c83
	acl_t acl,
rpm-build 0a0c83
	acl_tag_t type,
rpm-build 0a0c83
	id_t id)
rpm-build 0a0c83
{
rpm-build 0a0c83
	acl_entry_t ent;
rpm-build 0a0c83
	acl_tag_t e_type;
rpm-build 0a0c83
	id_t *e_id_p;
rpm-build 0a0c83
rpm-build 0a0c83
	if (acl_get_entry(acl, ACL_FIRST_ENTRY, &ent) != 1)
rpm-build 0a0c83
		return NULL;
rpm-build 0a0c83
rpm-build 0a0c83
	for(;;) {
rpm-build 0a0c83
		acl_get_tag_type(ent, &e_type);
rpm-build 0a0c83
		if (type == e_type) {
rpm-build 0a0c83
			if (id != ACL_UNDEFINED_ID) {
rpm-build 0a0c83
				e_id_p = acl_get_qualifier(ent);
rpm-build 0a0c83
				if (e_id_p == NULL)
rpm-build 0a0c83
					return NULL;
rpm-build 0a0c83
				if (*e_id_p == id) {
rpm-build 0a0c83
					acl_free(e_id_p);
rpm-build 0a0c83
					return ent;
rpm-build 0a0c83
				}
rpm-build 0a0c83
				acl_free(e_id_p);
rpm-build 0a0c83
			} else {
rpm-build 0a0c83
				return ent;
rpm-build 0a0c83
			}
rpm-build 0a0c83
		}
rpm-build 0a0c83
		if (acl_get_entry(acl, ACL_NEXT_ENTRY, &ent) != 1)
rpm-build 0a0c83
			return NULL;
rpm-build 0a0c83
	}
rpm-build 0a0c83
}
rpm-build 0a0c83
rpm-build 0a0c83
int
rpm-build 0a0c83
has_execute_perms(
rpm-build 0a0c83
	acl_t acl)
rpm-build 0a0c83
{
rpm-build 0a0c83
	acl_entry_t ent;
rpm-build 0a0c83
rpm-build 0a0c83
	if (acl_get_entry(acl, ACL_FIRST_ENTRY, &ent) != 1)
rpm-build 0a0c83
		return 0;
rpm-build 0a0c83
rpm-build 0a0c83
	for(;;) {
rpm-build 0a0c83
		acl_permset_t permset;
rpm-build 0a0c83
rpm-build 0a0c83
		acl_get_permset(ent, &permset);
rpm-build 0a0c83
		if (acl_get_perm(permset, ACL_EXECUTE) != 0)
rpm-build 0a0c83
			return 1;
rpm-build 0a0c83
rpm-build 0a0c83
		if (acl_get_entry(acl, ACL_NEXT_ENTRY, &ent) != 1)
rpm-build 0a0c83
			return 0;
rpm-build 0a0c83
	}
rpm-build 0a0c83
}
rpm-build 0a0c83
rpm-build 0a0c83
int
rpm-build 0a0c83
clone_entry(
rpm-build 0a0c83
	acl_t from_acl,
rpm-build 0a0c83
	acl_tag_t from_type,
rpm-build 0a0c83
	acl_t *to_acl,
rpm-build 0a0c83
	acl_tag_t to_type)
rpm-build 0a0c83
{
rpm-build 0a0c83
	acl_entry_t from_entry, to_entry;
rpm-build 0a0c83
	from_entry = find_entry(from_acl, from_type, ACL_UNDEFINED_ID);
rpm-build 0a0c83
	if (from_entry) {
rpm-build 0a0c83
		if (acl_create_entry(to_acl, &to_entry) != 0)
rpm-build 0a0c83
			return -1;
rpm-build 0a0c83
		acl_copy_entry(to_entry, from_entry);
rpm-build 0a0c83
		acl_set_tag_type(to_entry, to_type);
rpm-build 0a0c83
		return 0;
rpm-build 0a0c83
	} else {
rpm-build 0a0c83
		return 1;
rpm-build 0a0c83
	}
rpm-build 0a0c83
}
rpm-build 0a0c83
rpm-build 0a0c83
rpm-build 0a0c83
void
rpm-build 0a0c83
print_test(
rpm-build 0a0c83
	FILE *file,
rpm-build 0a0c83
	const char *path_p,
rpm-build 0a0c83
	const struct stat *st,
rpm-build 0a0c83
	const acl_t acl,
rpm-build 0a0c83
	const acl_t default_acl)
rpm-build 0a0c83
{
rpm-build 0a0c83
	char *acl_text, *default_acl_text;
rpm-build 0a0c83
rpm-build 0a0c83
	acl_text = acl_to_any_text(acl, NULL, ',', TEXT_ABBREVIATE);
rpm-build 0a0c83
	default_acl_text =
rpm-build 0a0c83
		acl_to_any_text(default_acl, "d:", ',', TEXT_ABBREVIATE);
rpm-build 0a0c83
	fprintf(file, "%s: %s,%s\n", path_p,
rpm-build 0a0c83
		acl_text ? acl_text : "*",
rpm-build 0a0c83
		default_acl_text ? default_acl_text : "*");
rpm-build 0a0c83
	acl_free(acl_text);
rpm-build 0a0c83
	acl_free(default_acl_text);
rpm-build 0a0c83
}
rpm-build 0a0c83
rpm-build 0a0c83
rpm-build 0a0c83
static void
rpm-build 0a0c83
set_perm(
rpm-build 0a0c83
	acl_entry_t ent,
rpm-build 0a0c83
	mode_t perm)
rpm-build 0a0c83
{
rpm-build 0a0c83
	acl_permset_t set;
rpm-build 0a0c83
rpm-build 0a0c83
	acl_get_permset(ent, &set);
rpm-build 0a0c83
	if (perm & CMD_PERM_READ)
rpm-build 0a0c83
		acl_add_perm(set, ACL_READ);
rpm-build 0a0c83
	else
rpm-build 0a0c83
		acl_delete_perm(set, ACL_READ);
rpm-build 0a0c83
	if (perm & CMD_PERM_WRITE)
rpm-build 0a0c83
		acl_add_perm(set, ACL_WRITE);
rpm-build 0a0c83
	else
rpm-build 0a0c83
		acl_delete_perm(set, ACL_WRITE);
rpm-build 0a0c83
	if (perm & CMD_PERM_EXECUTE)
rpm-build 0a0c83
		acl_add_perm(set, ACL_EXECUTE);
rpm-build 0a0c83
	else
rpm-build 0a0c83
		acl_delete_perm(set, ACL_EXECUTE);
rpm-build 0a0c83
}
rpm-build 0a0c83
rpm-build 0a0c83
rpm-build 0a0c83
static int
rpm-build 0a0c83
retrieve_acl(
rpm-build 0a0c83
	const char *path_p,
rpm-build 0a0c83
	acl_type_t type,
rpm-build 0a0c83
	const struct stat *st,
rpm-build 0a0c83
	acl_t *old_acl,
rpm-build 0a0c83
	acl_t *acl)
rpm-build 0a0c83
{
rpm-build 0a0c83
	if (*acl)
rpm-build 0a0c83
		return 0;
rpm-build 0a0c83
	*acl = NULL;
rpm-build 0a0c83
	if (type == ACL_TYPE_ACCESS || S_ISDIR(st->st_mode)) {
rpm-build 0a0c83
		*old_acl = acl_get_file(path_p, type);
rpm-build 0a0c83
		if (*old_acl == NULL && (errno == ENOSYS || errno == ENOTSUP)) {
rpm-build 0a0c83
			if (type == ACL_TYPE_DEFAULT)
rpm-build 0a0c83
				*old_acl = acl_init(0);
rpm-build 0a0c83
			else
rpm-build 0a0c83
				*old_acl = acl_from_mode(st->st_mode);
rpm-build 0a0c83
		}
rpm-build 0a0c83
	} else
rpm-build 0a0c83
		*old_acl = acl_init(0);
rpm-build 0a0c83
	if (*old_acl == NULL)
rpm-build 0a0c83
		return -1;
rpm-build 0a0c83
	*acl = acl_dup(*old_acl);
rpm-build 0a0c83
	if (*acl == NULL)
rpm-build 0a0c83
		return -1;
rpm-build 0a0c83
	return 0;
rpm-build 0a0c83
}
rpm-build 0a0c83
rpm-build 0a0c83
rpm-build 0a0c83
static int
rpm-build 0a0c83
remove_extended_entries(
rpm-build 0a0c83
	acl_t acl)
rpm-build 0a0c83
{
rpm-build 0a0c83
	acl_entry_t ent, group_obj;
rpm-build 0a0c83
	acl_permset_t mask_permset, group_obj_permset;
rpm-build 0a0c83
	acl_tag_t tag;
rpm-build 0a0c83
	int error;
rpm-build 0a0c83
	
rpm-build 0a0c83
	/*
rpm-build 0a0c83
	 * Removing the ACL_MASK entry from the ACL results in
rpm-build 0a0c83
	 * increased permissions for the owning group if the
rpm-build 0a0c83
	 * ACL_GROUP_OBJ entry contains permissions not contained
rpm-build 0a0c83
	 * in the ACL_MASK entry. We remove these permissions from
rpm-build 0a0c83
	 * the ACL_GROUP_OBJ entry to avoid that.
rpm-build 0a0c83
	 *
rpm-build 0a0c83
	 * After removing the ACL, the file owner and the owning group
rpm-build 0a0c83
	 * therefore have the same permissions as before.
rpm-build 0a0c83
	 */
rpm-build 0a0c83
rpm-build 0a0c83
	ent = find_entry(acl, ACL_MASK, ACL_UNDEFINED_ID);
rpm-build 0a0c83
	group_obj = find_entry(acl, ACL_GROUP_OBJ, ACL_UNDEFINED_ID);
rpm-build 0a0c83
	if (ent && group_obj) {
rpm-build 0a0c83
		if (!acl_get_permset(ent, &mask_permset) &&
rpm-build 0a0c83
		    !acl_get_permset(group_obj, &group_obj_permset)) {
rpm-build 0a0c83
			if (!acl_get_perm(mask_permset, ACL_READ))
rpm-build 0a0c83
				acl_delete_perm(group_obj_permset, ACL_READ);
rpm-build 0a0c83
			if (!acl_get_perm(mask_permset, ACL_WRITE))
rpm-build 0a0c83
				acl_delete_perm(group_obj_permset, ACL_WRITE);
rpm-build 0a0c83
			if (!acl_get_perm(mask_permset, ACL_EXECUTE))
rpm-build 0a0c83
				acl_delete_perm(group_obj_permset, ACL_EXECUTE);
rpm-build 0a0c83
		}
rpm-build 0a0c83
	}
rpm-build 0a0c83
rpm-build 0a0c83
	error = acl_get_entry(acl, ACL_FIRST_ENTRY, &ent;;
rpm-build 0a0c83
	while (error == 1) {
rpm-build 0a0c83
		acl_get_tag_type(ent, &tag;;
rpm-build 0a0c83
		switch(tag) {
rpm-build 0a0c83
			case ACL_USER:
rpm-build 0a0c83
			case ACL_GROUP:
rpm-build 0a0c83
			case ACL_MASK:
rpm-build 0a0c83
				acl_delete_entry(acl, ent);
rpm-build 0a0c83
				break;
rpm-build 0a0c83
			default:
rpm-build 0a0c83
				break;
rpm-build 0a0c83
		}
rpm-build 0a0c83
	
rpm-build 0a0c83
		error = acl_get_entry(acl, ACL_NEXT_ENTRY, &ent;;
rpm-build 0a0c83
	}
rpm-build 0a0c83
	if (error < 0)
rpm-build 0a0c83
		return -1;
rpm-build 0a0c83
	return 0;
rpm-build 0a0c83
}
rpm-build 0a0c83
rpm-build 0a0c83
rpm-build 0a0c83
#define RETRIEVE_ACL(type) do { \
rpm-build 0a0c83
	error = retrieve_acl(path_p, type, st, old_xacl, xacl); \
rpm-build 0a0c83
	if (error) \
rpm-build 0a0c83
		goto fail; \
rpm-build 0a0c83
	} while(0)
rpm-build 0a0c83
rpm-build 0a0c83
int
rpm-build 0a0c83
do_set(
rpm-build 0a0c83
	const char *path_p,
rpm-build 0a0c83
	const struct stat *st,
rpm-build 0a0c83
	int walk_flags,
rpm-build 0a0c83
	void *arg)
rpm-build 0a0c83
{
rpm-build 0a0c83
	struct do_set_args *args = arg;
rpm-build 0a0c83
	acl_t old_acl = NULL, old_default_acl = NULL;
rpm-build 0a0c83
	acl_t acl = NULL, default_acl = NULL;
rpm-build 0a0c83
	acl_t *xacl, *old_xacl;
rpm-build 0a0c83
	acl_entry_t ent;
rpm-build 0a0c83
	cmd_t cmd;
rpm-build 0a0c83
	int which_entry;
rpm-build 0a0c83
	int errors = 0, error;
rpm-build 0a0c83
	char *acl_text;
rpm-build 0a0c83
	int acl_modified = 0, default_acl_modified = 0;
rpm-build 0a0c83
	int acl_mask_provided = 0, default_acl_mask_provided = 0;
rpm-build 0a0c83
rpm-build 0a0c83
	if (walk_flags & WALK_TREE_FAILED) {
rpm-build 0a0c83
		fprintf(stderr, "%s: %s: %s\n", progname, path_p, strerror(errno));
rpm-build 0a0c83
		return 1;
rpm-build 0a0c83
	}
rpm-build 0a0c83
rpm-build 0a0c83
	/*
rpm-build 0a0c83
	 * Symlinks can never have ACLs, so when doing a physical walk, we
rpm-build 0a0c83
	 * skip symlinks altogether, and when doing a half-logical walk, we
rpm-build 0a0c83
	 * skip all non-toplevel symlinks. 
rpm-build 0a0c83
	 */
rpm-build 0a0c83
	if ((walk_flags & WALK_TREE_SYMLINK) &&
rpm-build 0a0c83
	    ((walk_flags & WALK_TREE_PHYSICAL) ||
rpm-build 0a0c83
	     !(walk_flags & (WALK_TREE_TOPLEVEL | WALK_TREE_LOGICAL))))
rpm-build 0a0c83
		return 0;
rpm-build 0a0c83
rpm-build 0a0c83
	/* Execute the commands in seq (read ACLs on demand) */
rpm-build 0a0c83
	error = seq_get_cmd(args->seq, SEQ_FIRST_CMD, &cmd);
rpm-build 0a0c83
	if (error == 0)
rpm-build 0a0c83
		return 0;
rpm-build 0a0c83
	while (error == 1) {
rpm-build 0a0c83
		mode_t perm = cmd->c_perm;
rpm-build 0a0c83
rpm-build 0a0c83
		if (cmd->c_type == ACL_TYPE_ACCESS) {
rpm-build 0a0c83
			xacl = &acl;
rpm-build 0a0c83
			old_xacl = &old_acl;
rpm-build 0a0c83
			acl_modified = 1;
rpm-build 0a0c83
			if (cmd->c_tag == ACL_MASK)
rpm-build 0a0c83
				acl_mask_provided = 1;
rpm-build 0a0c83
		} else {
rpm-build 0a0c83
			xacl = &default_acl;
rpm-build 0a0c83
			old_xacl = &old_default_acl;
rpm-build 0a0c83
			default_acl_modified = 1;
rpm-build 0a0c83
			if (cmd->c_tag == ACL_MASK)
rpm-build 0a0c83
				default_acl_mask_provided = 1;
rpm-build 0a0c83
		}
rpm-build 0a0c83
rpm-build 0a0c83
		RETRIEVE_ACL(cmd->c_type);
rpm-build 0a0c83
rpm-build 0a0c83
		/* Check for `X', and replace with `x' as appropriate. */
rpm-build 0a0c83
		if (perm & CMD_PERM_COND_EXECUTE) {
rpm-build 0a0c83
			perm &= ~CMD_PERM_COND_EXECUTE;
rpm-build 0a0c83
			if (S_ISDIR(st->st_mode) || has_execute_perms(*xacl))
rpm-build 0a0c83
				perm |= CMD_PERM_EXECUTE;
rpm-build 0a0c83
		}
rpm-build 0a0c83
rpm-build 0a0c83
		switch(cmd->c_cmd) {
rpm-build 0a0c83
			case CMD_ENTRY_REPLACE:
rpm-build 0a0c83
				ent = find_entry(*xacl, cmd->c_tag, cmd->c_id);
rpm-build 0a0c83
				if (!ent) {
rpm-build 0a0c83
					if (acl_create_entry(xacl, &ent) != 0)
rpm-build 0a0c83
						goto fail;
rpm-build 0a0c83
					acl_set_tag_type(ent, cmd->c_tag);
rpm-build 0a0c83
					if (cmd->c_id != ACL_UNDEFINED_ID)
rpm-build 0a0c83
						acl_set_qualifier(ent,
rpm-build 0a0c83
								  &cmd->c_id);
rpm-build 0a0c83
				}
rpm-build 0a0c83
				set_perm(ent, perm);
rpm-build 0a0c83
				break;
rpm-build 0a0c83
rpm-build 0a0c83
			case CMD_REMOVE_ENTRY:
rpm-build 0a0c83
				ent = find_entry(*xacl, cmd->c_tag, cmd->c_id);
rpm-build 0a0c83
				if (ent)
rpm-build 0a0c83
					acl_delete_entry(*xacl, ent);
rpm-build 0a0c83
				else
rpm-build 0a0c83
					/* ignore */;
rpm-build 0a0c83
				break;
rpm-build 0a0c83
rpm-build 0a0c83
			case CMD_REMOVE_EXTENDED_ACL:
rpm-build 0a0c83
				remove_extended_entries(acl);
rpm-build 0a0c83
				break;
rpm-build 0a0c83
rpm-build 0a0c83
			case CMD_REMOVE_ACL:
rpm-build 0a0c83
				acl_free(*xacl);
rpm-build 0a0c83
				*xacl = acl_init(5);
rpm-build 0a0c83
				if (!*xacl)
rpm-build 0a0c83
					goto fail;
rpm-build 0a0c83
				break;
rpm-build 0a0c83
rpm-build 0a0c83
			default:
rpm-build 0a0c83
				errno = EINVAL;
rpm-build 0a0c83
				goto fail;
rpm-build 0a0c83
		}
rpm-build 0a0c83
rpm-build 0a0c83
		error = seq_get_cmd(args->seq, SEQ_NEXT_CMD, &cmd);
rpm-build 0a0c83
	}
rpm-build 0a0c83
rpm-build 0a0c83
	if (error < 0)
rpm-build 0a0c83
		goto fail;
rpm-build 0a0c83
rpm-build 0a0c83
	/* Try to fill in missing entries */
rpm-build 0a0c83
	if (default_acl && acl_entries(default_acl) != 0) {
rpm-build 0a0c83
		xacl = &acl;
rpm-build 0a0c83
		old_xacl = &old_acl;
rpm-build 0a0c83
	
rpm-build 0a0c83
		if (!find_entry(default_acl, ACL_USER_OBJ, ACL_UNDEFINED_ID)) {
rpm-build 0a0c83
			if (!acl)
rpm-build 0a0c83
				RETRIEVE_ACL(ACL_TYPE_ACCESS);
rpm-build 0a0c83
			clone_entry(acl, ACL_USER_OBJ,
rpm-build 0a0c83
			            &default_acl, ACL_USER_OBJ);
rpm-build 0a0c83
		}
rpm-build 0a0c83
		if (!find_entry(default_acl, ACL_GROUP_OBJ, ACL_UNDEFINED_ID)) {
rpm-build 0a0c83
			if (!acl)
rpm-build 0a0c83
				RETRIEVE_ACL(ACL_TYPE_ACCESS);
rpm-build 0a0c83
			clone_entry(acl, ACL_GROUP_OBJ,
rpm-build 0a0c83
			            &default_acl, ACL_GROUP_OBJ);
rpm-build 0a0c83
		}
rpm-build 0a0c83
		if (!find_entry(default_acl, ACL_OTHER, ACL_UNDEFINED_ID)) {
rpm-build 0a0c83
			if (!acl)
rpm-build 0a0c83
				RETRIEVE_ACL(ACL_TYPE_ACCESS);
rpm-build 0a0c83
			clone_entry(acl, ACL_OTHER,
rpm-build 0a0c83
			            &default_acl, ACL_OTHER);
rpm-build 0a0c83
		}
rpm-build 0a0c83
	}
rpm-build 0a0c83
rpm-build 0a0c83
	/* update mask entries and check if ACLs are valid */
rpm-build 0a0c83
	if (acl && acl_modified) {
rpm-build 0a0c83
		if (acl_equiv_mode(acl, NULL) != 0) {
rpm-build 0a0c83
			if (!acl_mask_provided &&
rpm-build 0a0c83
			    !find_entry(acl, ACL_MASK, ACL_UNDEFINED_ID))
rpm-build 0a0c83
				clone_entry(acl, ACL_GROUP_OBJ,
rpm-build 0a0c83
				            &acl, ACL_MASK);
rpm-build 0a0c83
			if (opt_recalculate != -1 &&
rpm-build 0a0c83
			    (!acl_mask_provided || opt_recalculate == 1))
rpm-build 0a0c83
				acl_calc_mask(&acl;;
rpm-build 0a0c83
		}
rpm-build 0a0c83
rpm-build 0a0c83
		error = acl_check(acl, &which_entry);
rpm-build 0a0c83
		if (error < 0)
rpm-build 0a0c83
			goto fail;
rpm-build 0a0c83
		if (error > 0) {
rpm-build 0a0c83
			acl_text = acl_to_any_text(acl, NULL, ',', 0);
rpm-build 0a0c83
			fprintf(stderr, _("%s: %s: Malformed access ACL "
rpm-build 0a0c83
				"`%s': %s at entry %d\n"), progname, path_p,
rpm-build 0a0c83
				acl_text, acl_error(error), which_entry+1);
rpm-build 0a0c83
			acl_free(acl_text);
rpm-build 0a0c83
			errors++;
rpm-build 0a0c83
			goto cleanup;
rpm-build 0a0c83
		}
rpm-build 0a0c83
	}
rpm-build 0a0c83
rpm-build 0a0c83
	if (default_acl && acl_entries(default_acl) != 0 &&
rpm-build 0a0c83
	    default_acl_modified) {
rpm-build 0a0c83
		if (acl_equiv_mode(default_acl, NULL) != 0) {
rpm-build 0a0c83
			if (!default_acl_mask_provided &&
rpm-build 0a0c83
			    !find_entry(default_acl,ACL_MASK,ACL_UNDEFINED_ID))
rpm-build 0a0c83
				clone_entry(default_acl, ACL_GROUP_OBJ,
rpm-build 0a0c83
				            &default_acl, ACL_MASK);
rpm-build 0a0c83
			if (opt_recalculate != -1 &&
rpm-build 0a0c83
			    (!default_acl_mask_provided ||
rpm-build 0a0c83
			     opt_recalculate == 1))
rpm-build 0a0c83
				acl_calc_mask(&default_acl);
rpm-build 0a0c83
		}
rpm-build 0a0c83
rpm-build 0a0c83
		error = acl_check(default_acl, &which_entry);
rpm-build 0a0c83
		if (error < 0)
rpm-build 0a0c83
			goto fail;
rpm-build 0a0c83
		if (error > 0) {
rpm-build 0a0c83
			acl_text = acl_to_any_text(default_acl, NULL, ',', 0);
rpm-build 0a0c83
			fprintf(stderr, _("%s: %s: Malformed default ACL "
rpm-build 0a0c83
			                  "`%s': %s at entry %d\n"),
rpm-build 0a0c83
				progname, path_p, acl_text,
rpm-build 0a0c83
				acl_error(error), which_entry+1);
rpm-build 0a0c83
			acl_free(acl_text);
rpm-build 0a0c83
			errors++;
rpm-build 0a0c83
			goto cleanup;
rpm-build 0a0c83
		}
rpm-build 0a0c83
	}
rpm-build 0a0c83
rpm-build 0a0c83
	/* Only directores can have default ACLs */
rpm-build 0a0c83
	if (default_acl && !S_ISDIR(st->st_mode) && (walk_flags & WALK_TREE_RECURSIVE)) {
rpm-build 0a0c83
		/* In recursive mode, ignore default ACLs for files */
rpm-build 0a0c83
		acl_free(default_acl);
rpm-build 0a0c83
		default_acl = NULL;
rpm-build 0a0c83
	}
rpm-build 0a0c83
rpm-build 0a0c83
	/* check which ACLs have changed */
rpm-build 0a0c83
	if (acl && old_acl && acl_cmp(old_acl, acl) == 0) {
rpm-build 0a0c83
		acl_free(acl);
rpm-build 0a0c83
		acl = NULL;
rpm-build 0a0c83
	}
rpm-build 0a0c83
	if ((default_acl && old_default_acl &&
rpm-build 0a0c83
	    acl_cmp(old_default_acl, default_acl) == 0)) {
rpm-build 0a0c83
		acl_free(default_acl);
rpm-build 0a0c83
		default_acl = NULL;
rpm-build 0a0c83
	}
rpm-build 0a0c83
rpm-build 0a0c83
	/* update the file system */
rpm-build 0a0c83
	if (opt_test) {
rpm-build 0a0c83
		print_test(stdout, path_p, st,
rpm-build 0a0c83
		           acl, default_acl);
rpm-build 0a0c83
		goto cleanup;
rpm-build 0a0c83
	}
rpm-build 0a0c83
	if (acl) {
rpm-build 0a0c83
		int equiv_mode;
rpm-build 0a0c83
		mode_t mode = 0;
rpm-build 0a0c83
rpm-build 0a0c83
		equiv_mode = acl_equiv_mode(acl, &mode);
rpm-build 0a0c83
rpm-build 0a0c83
		if (acl_set_file(path_p, ACL_TYPE_ACCESS, acl) != 0) {
rpm-build 0a0c83
			if (errno == ENOSYS || errno == ENOTSUP) {
rpm-build 0a0c83
				if (equiv_mode != 0)
rpm-build 0a0c83
					goto fail;
rpm-build 0a0c83
				else {
rpm-build 0a0c83
					struct stat st;
rpm-build 0a0c83
rpm-build 0a0c83
					if (stat(path_p, &st) != 0)
rpm-build 0a0c83
						goto fail;
rpm-build 0a0c83
					mode |= st.st_mode & 07000;
rpm-build 0a0c83
					if (chmod(path_p, mode) != 0)
rpm-build 0a0c83
						goto fail;
rpm-build 0a0c83
				}
rpm-build 0a0c83
			} else
rpm-build 0a0c83
				goto fail;
rpm-build 0a0c83
		}
rpm-build 0a0c83
		args->mode = mode;
rpm-build 0a0c83
	}
rpm-build 0a0c83
	if (default_acl) {
rpm-build 0a0c83
		if (S_ISDIR(st->st_mode)) {
rpm-build 0a0c83
			if (acl_entries(default_acl) == 0) {
rpm-build 0a0c83
				if (acl_delete_def_file(path_p) != 0 &&
rpm-build 0a0c83
				    errno != ENOSYS && errno != ENOTSUP)
rpm-build 0a0c83
					goto fail;
rpm-build 0a0c83
			} else {
rpm-build 0a0c83
				if (acl_set_file(path_p, ACL_TYPE_DEFAULT,
rpm-build 0a0c83
						 default_acl) != 0)
rpm-build 0a0c83
					goto fail;
rpm-build 0a0c83
			}
rpm-build 0a0c83
		} else {
rpm-build 0a0c83
			if (acl_entries(default_acl) != 0) {
rpm-build 0a0c83
				fprintf(stderr, _("%s: %s: Only directories "
rpm-build 0a0c83
						"can have default ACLs\n"),
rpm-build 0a0c83
					progname, path_p);
rpm-build 0a0c83
				errors++;
rpm-build 0a0c83
				goto cleanup;
rpm-build 0a0c83
			}
rpm-build 0a0c83
		}
rpm-build 0a0c83
	}
rpm-build 0a0c83
rpm-build 0a0c83
	error = 0;
rpm-build 0a0c83
rpm-build 0a0c83
cleanup:
rpm-build 0a0c83
	if (acl)
rpm-build 0a0c83
		acl_free(acl);
rpm-build 0a0c83
	if (old_acl)
rpm-build 0a0c83
		acl_free(old_acl);
rpm-build 0a0c83
	if (default_acl)
rpm-build 0a0c83
		acl_free(default_acl);
rpm-build 0a0c83
	if (old_default_acl)
rpm-build 0a0c83
		acl_free(old_default_acl);
rpm-build 0a0c83
	return errors;
rpm-build 0a0c83
	
rpm-build 0a0c83
fail:
rpm-build 0a0c83
	fprintf(stderr, "%s: %s: %s\n", progname, path_p, strerror(errno));
rpm-build 0a0c83
	errors++;
rpm-build 0a0c83
	goto cleanup;
rpm-build 0a0c83
}
rpm-build 0a0c83