Blame tools/setfacl.c

rpm-build 0a0c83
/*
rpm-build 0a0c83
  File: setfacl.c
rpm-build 0a0c83
  (Linux Access Control List Management)
rpm-build 0a0c83
rpm-build 0a0c83
  Copyright (C) 1999-2002
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 <limits.h>
rpm-build 0a0c83
#include <stdio.h>
rpm-build 0a0c83
#include <string.h>
rpm-build 0a0c83
#include <unistd.h>
rpm-build 0a0c83
#include <errno.h>
rpm-build 0a0c83
#include <sys/stat.h>
rpm-build 0a0c83
#include <dirent.h>
rpm-build 0a0c83
#include <libgen.h>
rpm-build 0a0c83
#include <getopt.h>
rpm-build 0a0c83
#include "misc.h"
rpm-build 0a0c83
#include "sequence.h"
rpm-build 0a0c83
#include "parse.h"
rpm-build 0a0c83
#include "do_set.h"
rpm-build 0a0c83
#include "walk_tree.h"
rpm-build 0a0c83
rpm-build 0a0c83
#define POSIXLY_CORRECT_STR "POSIXLY_CORRECT"
rpm-build 0a0c83
rpm-build 0a0c83
/* '-' stands for `process non-option arguments in loop' */
rpm-build 0a0c83
#if !POSIXLY_CORRECT
rpm-build 0a0c83
#  define CMD_LINE_OPTIONS "-:bkndvhm:M:x:X:RLP"
rpm-build 0a0c83
#  define CMD_LINE_SPEC "[-bkndRLP] { -m|-M|-x|-X ... } file ..."
rpm-build 0a0c83
#endif
rpm-build 0a0c83
#define POSIXLY_CMD_LINE_OPTIONS "-:bkndvhm:M:x:X:"
rpm-build 0a0c83
#define POSIXLY_CMD_LINE_SPEC "[-bknd] {-m|-M|-x|-X ... } file ..."
rpm-build 0a0c83
rpm-build 0a0c83
struct option long_options[] = {
rpm-build 0a0c83
#if !POSIXLY_CORRECT
rpm-build 0a0c83
	{ "set",		1, 0, 's' },
rpm-build 0a0c83
	{ "set-file",		1, 0, 'S' },
rpm-build 0a0c83
rpm-build 0a0c83
	{ "mask",		0, 0, 'r' },
rpm-build 0a0c83
	{ "recursive",		0, 0, 'R' },
rpm-build 0a0c83
	{ "logical",		0, 0, 'L' },
rpm-build 0a0c83
	{ "physical",		0, 0, 'P' },
rpm-build 0a0c83
	{ "restore",		1, 0, 'B' },
rpm-build 0a0c83
	{ "test",		0, 0, 't' },
rpm-build 0a0c83
#endif
rpm-build 0a0c83
	{ "modify",		1, 0, 'm' },
rpm-build 0a0c83
	{ "modify-file",	1, 0, 'M' },
rpm-build 0a0c83
	{ "remove",		1, 0, 'x' },
rpm-build 0a0c83
	{ "remove-file",	1, 0, 'X' },
rpm-build 0a0c83
rpm-build 0a0c83
	{ "default",		0, 0, 'd' },
rpm-build 0a0c83
	{ "no-mask",		0, 0, 'n' },
rpm-build 0a0c83
	{ "remove-all",		0, 0, 'b' },
rpm-build 0a0c83
	{ "remove-default",	0, 0, 'k' },
rpm-build 0a0c83
	{ "version",		0, 0, 'v' },
rpm-build 0a0c83
	{ "help",		0, 0, 'h' },
rpm-build 0a0c83
	{ NULL,			0, 0, 0   },
rpm-build 0a0c83
};
rpm-build 0a0c83
rpm-build 0a0c83
const char *progname;
rpm-build 0a0c83
const char *cmd_line_options, *cmd_line_spec;
rpm-build 0a0c83
rpm-build 0a0c83
int walk_flags = WALK_TREE_DEREFERENCE_TOPLEVEL;
rpm-build 0a0c83
int opt_recalculate;  /* recalculate mask entry (0=default, 1=yes, -1=no) */
rpm-build 0a0c83
int opt_promote;  /* promote access ACL to default ACL */
rpm-build 0a0c83
int opt_test;  /* do not write to the file system.
rpm-build 0a0c83
                      Print what would happen instead. */
rpm-build 0a0c83
#if POSIXLY_CORRECT
rpm-build 0a0c83
const int posixly_correct = 1;  /* Posix compatible behavior! */
rpm-build 0a0c83
#else
rpm-build 0a0c83
int posixly_correct;  /* Posix compatible behavior? */
rpm-build 0a0c83
#endif
rpm-build 0a0c83
int chown_error;
rpm-build 0a0c83
int promote_warning;
rpm-build 0a0c83
rpm-build 0a0c83
rpm-build 0a0c83
static const char *xquote(const char *str, const char *quote_chars)
rpm-build 0a0c83
{
rpm-build 0a0c83
	const char *q = __acl_quote(str, quote_chars);
rpm-build 0a0c83
	if (q == NULL) {
rpm-build 0a0c83
		fprintf(stderr, "%s: %s\n", progname, strerror(errno));
rpm-build 0a0c83
		exit(1);
rpm-build 0a0c83
	}
rpm-build 0a0c83
	return q;
rpm-build 0a0c83
}
rpm-build 0a0c83
rpm-build 0a0c83
int
rpm-build 0a0c83
has_any_of_type(
rpm-build 0a0c83
	cmd_t cmd,
rpm-build 0a0c83
	acl_type_t acl_type)
rpm-build 0a0c83
{
rpm-build 0a0c83
	while (cmd) {
rpm-build 0a0c83
		if (cmd->c_type == acl_type)
rpm-build 0a0c83
			return 1;
rpm-build 0a0c83
		cmd = cmd->c_next;
rpm-build 0a0c83
	}
rpm-build 0a0c83
	return 0;
rpm-build 0a0c83
}
rpm-build 0a0c83
	
rpm-build 0a0c83
rpm-build 0a0c83
#if !POSIXLY_CORRECT
rpm-build 0a0c83
int
rpm-build 0a0c83
restore(
rpm-build 0a0c83
	FILE *file,
rpm-build 0a0c83
	const char *filename)
rpm-build 0a0c83
{
rpm-build 0a0c83
	char *path_p;
rpm-build 0a0c83
	struct stat st;
rpm-build 0a0c83
	uid_t uid;
rpm-build 0a0c83
	gid_t gid;
rpm-build 0a0c83
	mode_t mask, flags;
rpm-build 0a0c83
	struct do_set_args args = { };
rpm-build 0a0c83
	int lineno = 0, backup_line;
rpm-build 0a0c83
	int error, status = 0;
rpm-build 0a0c83
	int chmod_required = 0;
rpm-build 0a0c83
rpm-build 0a0c83
	memset(&st, 0, sizeof(st));
rpm-build 0a0c83
rpm-build 0a0c83
	for(;;) {
rpm-build 0a0c83
		backup_line = lineno;
rpm-build 0a0c83
		error = read_acl_comments(file, &lineno, &path_p, &uid, &gid,
rpm-build 0a0c83
					  &flags);
rpm-build 0a0c83
		if (error < 0) {
rpm-build 0a0c83
			error = -error;
rpm-build 0a0c83
			goto fail;
rpm-build 0a0c83
		}
rpm-build 0a0c83
		if (error == 0)
rpm-build 0a0c83
			return status;
rpm-build 0a0c83
rpm-build 0a0c83
		if (path_p == NULL) {
rpm-build 0a0c83
			if (filename) {
rpm-build 0a0c83
				fprintf(stderr, _("%s: %s: No filename found "
rpm-build 0a0c83
						  "in line %d, aborting\n"),
rpm-build 0a0c83
					progname, xquote(filename, "\n\r"),
rpm-build 0a0c83
					backup_line);
rpm-build 0a0c83
			} else {
rpm-build 0a0c83
				fprintf(stderr, _("%s: No filename found in "
rpm-build 0a0c83
						 "line %d of standard input, "
rpm-build 0a0c83
						 "aborting\n"),
rpm-build 0a0c83
					progname, backup_line);
rpm-build 0a0c83
			}
rpm-build 0a0c83
			status = 1;
rpm-build 0a0c83
			goto getout;
rpm-build 0a0c83
		}
rpm-build 0a0c83
rpm-build 0a0c83
		if (!(args.seq = seq_init()))
rpm-build 0a0c83
			goto fail_errno;
rpm-build 0a0c83
		if (seq_append_cmd(args.seq, CMD_REMOVE_ACL, ACL_TYPE_ACCESS) ||
rpm-build 0a0c83
		    seq_append_cmd(args.seq, CMD_REMOVE_ACL, ACL_TYPE_DEFAULT))
rpm-build 0a0c83
			goto fail_errno;
rpm-build 0a0c83
rpm-build 0a0c83
		error = read_acl_seq(file, args.seq, CMD_ENTRY_REPLACE,
rpm-build 0a0c83
		                     SEQ_PARSE_WITH_PERM |
rpm-build 0a0c83
				     SEQ_PARSE_DEFAULT |
rpm-build 0a0c83
				     SEQ_PARSE_MULTI,
rpm-build 0a0c83
				     &lineno, NULL);
rpm-build 0a0c83
		if (error != 0) {
rpm-build 0a0c83
			fprintf(stderr, _("%s: %s: %s in line %d\n"),
rpm-build 0a0c83
			        progname, xquote(filename, "\n\r"), strerror(errno),
rpm-build 0a0c83
				lineno);
rpm-build 0a0c83
			status = 1;
rpm-build 0a0c83
			goto getout;
rpm-build 0a0c83
		}
rpm-build 0a0c83
rpm-build 0a0c83
		error = stat(path_p, &st);
rpm-build 0a0c83
		if (opt_test && error != 0) {
rpm-build 0a0c83
			fprintf(stderr, "%s: %s: %s\n", progname,
rpm-build 0a0c83
				xquote(path_p, "\n\r"), strerror(errno));
rpm-build 0a0c83
			status = 1;
rpm-build 0a0c83
		}
rpm-build 0a0c83
rpm-build 0a0c83
		args.mode = 0;
rpm-build 0a0c83
		error = do_set(path_p, &st, 0, &args);
rpm-build 0a0c83
		if (error != 0) {
rpm-build 0a0c83
			status = 1;
rpm-build 0a0c83
			goto resume;
rpm-build 0a0c83
		}
rpm-build 0a0c83
rpm-build 0a0c83
		if (uid != ACL_UNDEFINED_ID && uid != st.st_uid)
rpm-build 0a0c83
			st.st_uid = uid;
rpm-build 0a0c83
		else
rpm-build 0a0c83
			st.st_uid = -1;
rpm-build 0a0c83
		if (gid != ACL_UNDEFINED_ID && gid != st.st_gid)
rpm-build 0a0c83
			st.st_gid = gid;
rpm-build 0a0c83
		else
rpm-build 0a0c83
			st.st_gid = -1;
rpm-build 0a0c83
		if (!opt_test &&
rpm-build 0a0c83
		    (st.st_uid != -1 || st.st_gid != -1)) {
rpm-build 0a0c83
			if (chown(path_p, st.st_uid, st.st_gid) != 0) {
rpm-build 0a0c83
				fprintf(stderr, _("%s: %s: Cannot change "
rpm-build 0a0c83
					          "owner/group: %s\n"),
rpm-build 0a0c83
					progname, xquote(path_p, "\n\r"),
rpm-build 0a0c83
					strerror(errno));
rpm-build 0a0c83
				status = 1;
rpm-build 0a0c83
			}
rpm-build 0a0c83
rpm-build 0a0c83
			/* chown() clears setuid/setgid so force a chmod if
rpm-build 0a0c83
			 * S_ISUID/S_ISGID was expected */
rpm-build 0a0c83
			if ((st.st_mode & flags) & (S_ISUID | S_ISGID))
rpm-build 0a0c83
				chmod_required = 1;
rpm-build 0a0c83
		}
rpm-build 0a0c83
rpm-build 0a0c83
		mask = S_ISUID | S_ISGID | S_ISVTX;
rpm-build 0a0c83
		if (chmod_required || ((st.st_mode & mask) != (flags & mask))) {
rpm-build 0a0c83
			if (!args.mode)
rpm-build 0a0c83
				args.mode = st.st_mode;
rpm-build 0a0c83
			args.mode &= (S_IRWXU | S_IRWXG | S_IRWXO);
rpm-build 0a0c83
			if (chmod(path_p, flags | args.mode) != 0) {
rpm-build 0a0c83
				fprintf(stderr, _("%s: %s: Cannot change "
rpm-build 0a0c83
					          "mode: %s\n"),
rpm-build 0a0c83
					progname, xquote(path_p, "\n\r"),
rpm-build 0a0c83
					strerror(errno));
rpm-build 0a0c83
				status = 1;
rpm-build 0a0c83
			}
rpm-build 0a0c83
		}
rpm-build 0a0c83
resume:
rpm-build 0a0c83
		if (path_p) {
rpm-build 0a0c83
			free(path_p);
rpm-build 0a0c83
			path_p = NULL;
rpm-build 0a0c83
		}
rpm-build 0a0c83
		if (args.seq) {
rpm-build 0a0c83
			seq_free(args.seq);
rpm-build 0a0c83
			args.seq = NULL;
rpm-build 0a0c83
		}
rpm-build 0a0c83
	}
rpm-build 0a0c83
rpm-build 0a0c83
getout:
rpm-build 0a0c83
	if (path_p) {
rpm-build 0a0c83
		free(path_p);
rpm-build 0a0c83
		path_p = NULL;
rpm-build 0a0c83
	}
rpm-build 0a0c83
	if (args.seq) {
rpm-build 0a0c83
		seq_free(args.seq);
rpm-build 0a0c83
		args.seq = NULL;
rpm-build 0a0c83
	}
rpm-build 0a0c83
	return status;
rpm-build 0a0c83
rpm-build 0a0c83
fail_errno:
rpm-build 0a0c83
	error = errno;
rpm-build 0a0c83
fail:
rpm-build 0a0c83
	fprintf(stderr, "%s: %s: %s\n", progname, xquote(filename, "\n\r"),
rpm-build 0a0c83
		strerror(error));
rpm-build 0a0c83
	status = 1;
rpm-build 0a0c83
	goto getout;
rpm-build 0a0c83
}
rpm-build 0a0c83
#endif
rpm-build 0a0c83
rpm-build 0a0c83
rpm-build 0a0c83
void help(void)
rpm-build 0a0c83
{
rpm-build 0a0c83
	printf(_("%s %s -- set file access control lists\n"),
rpm-build 0a0c83
		progname, VERSION);
rpm-build 0a0c83
	printf(_("Usage: %s %s\n"),
rpm-build 0a0c83
		progname, cmd_line_spec);
rpm-build 0a0c83
	printf(_(
rpm-build 0a0c83
"  -m, --modify=acl        modify the current ACL(s) of file(s)\n"
rpm-build 0a0c83
"  -M, --modify-file=file  read ACL entries to modify from file\n"
rpm-build 0a0c83
"  -x, --remove=acl        remove entries from the ACL(s) of file(s)\n"
rpm-build 0a0c83
"  -X, --remove-file=file  read ACL entries to remove from file\n"
rpm-build 0a0c83
"  -b, --remove-all        remove all extended ACL entries\n"
rpm-build 0a0c83
"  -k, --remove-default    remove the default ACL\n"));
rpm-build 0a0c83
#if !POSIXLY_CORRECT
rpm-build 0a0c83
	if (!posixly_correct) {
rpm-build 0a0c83
		printf(_(
rpm-build 0a0c83
"      --set=acl           set the ACL of file(s), replacing the current ACL\n"
rpm-build 0a0c83
"      --set-file=file     read ACL entries to set from file\n"
rpm-build 0a0c83
"      --mask              do recalculate the effective rights mask\n"));
rpm-build 0a0c83
	}
rpm-build 0a0c83
#endif
rpm-build 0a0c83
  	printf(_(
rpm-build 0a0c83
"  -n, --no-mask           don't recalculate the effective rights mask\n"
rpm-build 0a0c83
"  -d, --default           operations apply to the default ACL\n"));
rpm-build 0a0c83
#if !POSIXLY_CORRECT
rpm-build 0a0c83
	if (!posixly_correct) {
rpm-build 0a0c83
		printf(_(
rpm-build 0a0c83
"  -R, --recursive         recurse into subdirectories\n"
rpm-build 0a0c83
"  -L, --logical           logical walk, follow symbolic links\n"
rpm-build 0a0c83
"  -P, --physical          physical walk, do not follow symbolic links\n"
rpm-build 0a0c83
"      --restore=file      restore ACLs (inverse of `getfacl -R')\n"
rpm-build 0a0c83
"      --test              test mode (ACLs are not modified)\n"));
rpm-build 0a0c83
	}
rpm-build 0a0c83
#endif
rpm-build 0a0c83
	printf(_(
rpm-build 0a0c83
"  -v, --version           print version and exit\n"
rpm-build 0a0c83
"  -h, --help              this help text\n"));
rpm-build 0a0c83
}
rpm-build 0a0c83
rpm-build 0a0c83
rpm-build 0a0c83
int next_file(const char *arg, seq_t seq)
rpm-build 0a0c83
{
rpm-build 0a0c83
	char *line;
rpm-build 0a0c83
	int errors = 0;
rpm-build 0a0c83
	struct do_set_args args;
rpm-build 0a0c83
rpm-build 0a0c83
	args.seq = seq;
rpm-build 0a0c83
rpm-build 0a0c83
	if (strcmp(arg, "-") == 0) {
rpm-build 0a0c83
		while ((line = __acl_next_line(stdin)))
rpm-build 0a0c83
			errors = walk_tree(line, walk_flags, 0, do_set, &args);
rpm-build 0a0c83
		if (!feof(stdin)) {
rpm-build 0a0c83
			fprintf(stderr, _("%s: Standard input: %s\n"),
rpm-build 0a0c83
				progname, strerror(errno));
rpm-build 0a0c83
			errors = 1;
rpm-build 0a0c83
		}
rpm-build 0a0c83
	} else {
rpm-build 0a0c83
		errors = walk_tree(arg, walk_flags, 0, do_set, &args);
rpm-build 0a0c83
	}
rpm-build 0a0c83
	return errors ? 1 : 0;
rpm-build 0a0c83
}
rpm-build 0a0c83
rpm-build 0a0c83
rpm-build 0a0c83
#define ERRNO_ERROR(s) \
rpm-build 0a0c83
	({status = (s); goto errno_error; })
rpm-build 0a0c83
rpm-build 0a0c83
rpm-build 0a0c83
int main(int argc, char *argv[])
rpm-build 0a0c83
{
rpm-build 0a0c83
	int opt;
rpm-build 0a0c83
	int saw_files = 0;
rpm-build 0a0c83
	int status = 0;
rpm-build 0a0c83
	FILE *file;
rpm-build 0a0c83
	int which;
rpm-build 0a0c83
	int lineno;
rpm-build 0a0c83
	int error;
rpm-build 0a0c83
	seq_t seq;
rpm-build 0a0c83
	int seq_cmd, parse_mode;
rpm-build 0a0c83
	
rpm-build 0a0c83
	progname = basename(argv[0]);
rpm-build 0a0c83
rpm-build 0a0c83
#if POSIXLY_CORRECT
rpm-build 0a0c83
	cmd_line_options = POSIXLY_CMD_LINE_OPTIONS;
rpm-build 0a0c83
	cmd_line_spec = _(POSIXLY_CMD_LINE_SPEC);
rpm-build 0a0c83
#else
rpm-build 0a0c83
	if (getenv(POSIXLY_CORRECT_STR))
rpm-build 0a0c83
		posixly_correct = 1;
rpm-build 0a0c83
	if (!posixly_correct) {
rpm-build 0a0c83
		cmd_line_options = CMD_LINE_OPTIONS;
rpm-build 0a0c83
		cmd_line_spec = _(CMD_LINE_SPEC);
rpm-build 0a0c83
	} else {
rpm-build 0a0c83
		cmd_line_options = POSIXLY_CMD_LINE_OPTIONS;
rpm-build 0a0c83
		cmd_line_spec = _(POSIXLY_CMD_LINE_SPEC);
rpm-build 0a0c83
	}
rpm-build 0a0c83
#endif
rpm-build 0a0c83
rpm-build 0a0c83
	setlocale(LC_CTYPE, "");
rpm-build 0a0c83
	setlocale(LC_MESSAGES, "");
rpm-build 0a0c83
	bindtextdomain(PACKAGE, LOCALEDIR);
rpm-build 0a0c83
	textdomain(PACKAGE);
rpm-build 0a0c83
rpm-build 0a0c83
	seq = seq_init();
rpm-build 0a0c83
	if (!seq)
rpm-build 0a0c83
		ERRNO_ERROR(1);
rpm-build 0a0c83
rpm-build 0a0c83
	while ((opt = getopt_long(argc, argv, cmd_line_options,
rpm-build 0a0c83
		                  long_options, NULL)) != -1) {
rpm-build 0a0c83
		/* we remember the two REMOVE_ACL commands of the set
rpm-build 0a0c83
		   operations because we may later need to delete them.  */
rpm-build 0a0c83
		cmd_t seq_remove_default_acl_cmd = NULL;
rpm-build 0a0c83
		cmd_t seq_remove_acl_cmd = NULL;
rpm-build 0a0c83
rpm-build 0a0c83
		if (opt != '\1' && saw_files) {
rpm-build 0a0c83
			seq_free(seq);
rpm-build 0a0c83
			seq = seq_init();
rpm-build 0a0c83
			if (!seq)
rpm-build 0a0c83
				ERRNO_ERROR(1);
rpm-build 0a0c83
			saw_files = 0;
rpm-build 0a0c83
		}
rpm-build 0a0c83
rpm-build 0a0c83
		switch (opt) {
rpm-build 0a0c83
			case 'b':  /* remove all extended entries */
rpm-build 0a0c83
				if (seq_append_cmd(seq, CMD_REMOVE_EXTENDED_ACL,
rpm-build 0a0c83
				                        ACL_TYPE_ACCESS) ||
rpm-build 0a0c83
				    seq_append_cmd(seq, CMD_REMOVE_ACL,
rpm-build 0a0c83
				                        ACL_TYPE_DEFAULT))
rpm-build 0a0c83
					ERRNO_ERROR(1);
rpm-build 0a0c83
				break;
rpm-build 0a0c83
rpm-build 0a0c83
			case 'k':  /* remove default ACL */
rpm-build 0a0c83
				if (seq_append_cmd(seq, CMD_REMOVE_ACL,
rpm-build 0a0c83
				                        ACL_TYPE_DEFAULT))
rpm-build 0a0c83
					ERRNO_ERROR(1);
rpm-build 0a0c83
				break;
rpm-build 0a0c83
rpm-build 0a0c83
			case 'n':  /* do not recalculate mask */
rpm-build 0a0c83
				opt_recalculate = -1;
rpm-build 0a0c83
				break;
rpm-build 0a0c83
rpm-build 0a0c83
			case 'r':  /* force recalculate mask */
rpm-build 0a0c83
				opt_recalculate = 1;
rpm-build 0a0c83
				break;
rpm-build 0a0c83
rpm-build 0a0c83
			case 'd':  /*  operations apply to default ACL */
rpm-build 0a0c83
				opt_promote = 1;
rpm-build 0a0c83
				break;
rpm-build 0a0c83
rpm-build 0a0c83
			case 's':  /* set */
rpm-build 0a0c83
				if (seq_append_cmd(seq, CMD_REMOVE_ACL,
rpm-build 0a0c83
					                ACL_TYPE_ACCESS))
rpm-build 0a0c83
					ERRNO_ERROR(1);
rpm-build 0a0c83
				seq_remove_acl_cmd = seq->s_last;
rpm-build 0a0c83
				if (seq_append_cmd(seq, CMD_REMOVE_ACL,
rpm-build 0a0c83
				                        ACL_TYPE_DEFAULT))
rpm-build 0a0c83
					ERRNO_ERROR(1);
rpm-build 0a0c83
				seq_remove_default_acl_cmd = seq->s_last;
rpm-build 0a0c83
rpm-build 0a0c83
				seq_cmd = CMD_ENTRY_REPLACE;
rpm-build 0a0c83
				parse_mode = SEQ_PARSE_WITH_PERM;
rpm-build 0a0c83
				goto set_modify_delete;
rpm-build 0a0c83
rpm-build 0a0c83
			case 'm':  /* modify */
rpm-build 0a0c83
				seq_cmd = CMD_ENTRY_REPLACE;
rpm-build 0a0c83
				parse_mode = SEQ_PARSE_WITH_PERM;
rpm-build 0a0c83
				goto set_modify_delete;
rpm-build 0a0c83
rpm-build 0a0c83
			case 'x':  /* delete */
rpm-build 0a0c83
				seq_cmd = CMD_REMOVE_ENTRY;
rpm-build 0a0c83
#if POSIXLY_CORRECT
rpm-build 0a0c83
				parse_mode = SEQ_PARSE_ANY_PERM;
rpm-build 0a0c83
#else
rpm-build 0a0c83
				if (posixly_correct)
rpm-build 0a0c83
					parse_mode = SEQ_PARSE_ANY_PERM;
rpm-build 0a0c83
				else
rpm-build 0a0c83
					parse_mode = SEQ_PARSE_NO_PERM;
rpm-build 0a0c83
#endif
rpm-build 0a0c83
				goto set_modify_delete;
rpm-build 0a0c83
rpm-build 0a0c83
			set_modify_delete:
rpm-build 0a0c83
				if (!posixly_correct)
rpm-build 0a0c83
					parse_mode |= SEQ_PARSE_DEFAULT;
rpm-build 0a0c83
				if (opt_promote)
rpm-build 0a0c83
					parse_mode |= SEQ_PROMOTE_ACL;
rpm-build 0a0c83
				if (parse_acl_seq(seq, optarg, &which,
rpm-build 0a0c83
				                  seq_cmd, parse_mode) != 0) {
rpm-build 0a0c83
					if (which < 0 ||
rpm-build 0a0c83
					    (size_t) which >= strlen(optarg)) {
rpm-build 0a0c83
						fprintf(stderr, _(
rpm-build 0a0c83
							"%s: Option "
rpm-build 0a0c83
						        "-%c incomplete\n"),
rpm-build 0a0c83
							progname, opt);
rpm-build 0a0c83
					} else {
rpm-build 0a0c83
						fprintf(stderr, _(
rpm-build 0a0c83
							"%s: Option "
rpm-build 0a0c83
						        "-%c: %s near "
rpm-build 0a0c83
							"character %d\n"),
rpm-build 0a0c83
							progname, opt,
rpm-build 0a0c83
							strerror(errno),
rpm-build 0a0c83
							which+1);
rpm-build 0a0c83
					}
rpm-build 0a0c83
					status = 2;
rpm-build 0a0c83
					goto cleanup;
rpm-build 0a0c83
				}
rpm-build 0a0c83
				break;
rpm-build 0a0c83
rpm-build 0a0c83
			case 'S':  /* set from file */
rpm-build 0a0c83
				if (seq_append_cmd(seq, CMD_REMOVE_ACL,
rpm-build 0a0c83
					                ACL_TYPE_ACCESS))
rpm-build 0a0c83
					ERRNO_ERROR(1);
rpm-build 0a0c83
				seq_remove_acl_cmd = seq->s_last;
rpm-build 0a0c83
				if (seq_append_cmd(seq, CMD_REMOVE_ACL,
rpm-build 0a0c83
				                        ACL_TYPE_DEFAULT))
rpm-build 0a0c83
					ERRNO_ERROR(1);
rpm-build 0a0c83
				seq_remove_default_acl_cmd = seq->s_last;
rpm-build 0a0c83
rpm-build 0a0c83
				seq_cmd = CMD_ENTRY_REPLACE;
rpm-build 0a0c83
				parse_mode = SEQ_PARSE_WITH_PERM;
rpm-build 0a0c83
				goto set_modify_delete_from_file;
rpm-build 0a0c83
rpm-build 0a0c83
			case 'M':  /* modify from file */
rpm-build 0a0c83
				seq_cmd = CMD_ENTRY_REPLACE;
rpm-build 0a0c83
				parse_mode = SEQ_PARSE_WITH_PERM;
rpm-build 0a0c83
				goto set_modify_delete_from_file;
rpm-build 0a0c83
rpm-build 0a0c83
			case 'X':  /* delete from file */
rpm-build 0a0c83
				seq_cmd = CMD_REMOVE_ENTRY;
rpm-build 0a0c83
#if POSIXLY_CORRECT
rpm-build 0a0c83
				parse_mode = SEQ_PARSE_ANY_PERM;
rpm-build 0a0c83
#else
rpm-build 0a0c83
				if (posixly_correct)
rpm-build 0a0c83
					parse_mode = SEQ_PARSE_ANY_PERM;
rpm-build 0a0c83
				else
rpm-build 0a0c83
					parse_mode = SEQ_PARSE_NO_PERM;
rpm-build 0a0c83
#endif
rpm-build 0a0c83
				goto set_modify_delete_from_file;
rpm-build 0a0c83
rpm-build 0a0c83
			set_modify_delete_from_file:
rpm-build 0a0c83
				if (!posixly_correct)
rpm-build 0a0c83
					parse_mode |= SEQ_PARSE_DEFAULT;
rpm-build 0a0c83
				if (opt_promote)
rpm-build 0a0c83
					parse_mode |= SEQ_PROMOTE_ACL;
rpm-build 0a0c83
				if (strcmp(optarg, "-") == 0) {
rpm-build 0a0c83
					file = stdin;
rpm-build 0a0c83
				} else {
rpm-build 0a0c83
					file = fopen(optarg, "r");
rpm-build 0a0c83
					if (file == NULL) {
rpm-build 0a0c83
						fprintf(stderr, "%s: %s: %s\n",
rpm-build 0a0c83
							progname,
rpm-build 0a0c83
							xquote(optarg, "\n\r"),
rpm-build 0a0c83
							strerror(errno));
rpm-build 0a0c83
						status = 2;
rpm-build 0a0c83
						goto cleanup;
rpm-build 0a0c83
					}
rpm-build 0a0c83
				}
rpm-build 0a0c83
rpm-build 0a0c83
				lineno = 0;
rpm-build 0a0c83
				error = read_acl_seq(file, seq, seq_cmd,
rpm-build 0a0c83
				                     parse_mode, &lineno, NULL);
rpm-build 0a0c83
				
rpm-build 0a0c83
				if (file != stdin) {
rpm-build 0a0c83
					fclose(file);
rpm-build 0a0c83
				}
rpm-build 0a0c83
rpm-build 0a0c83
				if (error) {
rpm-build 0a0c83
					if (!errno)
rpm-build 0a0c83
						errno = EINVAL;
rpm-build 0a0c83
rpm-build 0a0c83
					if (file != stdin) {
rpm-build 0a0c83
						fprintf(stderr, _(
rpm-build 0a0c83
							"%s: %s in line "
rpm-build 0a0c83
						        "%d of file %s\n"),
rpm-build 0a0c83
							progname,
rpm-build 0a0c83
							strerror(errno),
rpm-build 0a0c83
							lineno,
rpm-build 0a0c83
							xquote(optarg, "\n\r"));
rpm-build 0a0c83
					} else {
rpm-build 0a0c83
						fprintf(stderr, _(
rpm-build 0a0c83
							"%s: %s in line "
rpm-build 0a0c83
						        "%d of standard "
rpm-build 0a0c83
							"input\n"), progname,
rpm-build 0a0c83
							strerror(errno),
rpm-build 0a0c83
							lineno);
rpm-build 0a0c83
					}
rpm-build 0a0c83
					status = 2;
rpm-build 0a0c83
					goto cleanup;
rpm-build 0a0c83
				}
rpm-build 0a0c83
				break;
rpm-build 0a0c83
rpm-build 0a0c83
rpm-build 0a0c83
			case '\1':  /* file argument */
rpm-build 0a0c83
				if (seq_empty(seq))
rpm-build 0a0c83
					goto synopsis;
rpm-build 0a0c83
				saw_files = 1;
rpm-build 0a0c83
rpm-build 0a0c83
				status = next_file(optarg, seq);
rpm-build 0a0c83
				break;
rpm-build 0a0c83
rpm-build 0a0c83
			case 'B':  /* restore ACL backup */
rpm-build 0a0c83
				saw_files = 1;
rpm-build 0a0c83
rpm-build 0a0c83
				if (strcmp(optarg, "-") == 0)
rpm-build 0a0c83
					file = stdin;
rpm-build 0a0c83
				else {
rpm-build 0a0c83
					file = fopen(optarg, "r");
rpm-build 0a0c83
					if (file == NULL) {
rpm-build 0a0c83
						fprintf(stderr, "%s: %s: %s\n",
rpm-build 0a0c83
							progname,
rpm-build 0a0c83
							xquote(optarg, "\n\r"),
rpm-build 0a0c83
							strerror(errno));
rpm-build 0a0c83
						status = 2;
rpm-build 0a0c83
						goto cleanup;
rpm-build 0a0c83
					}
rpm-build 0a0c83
				}
rpm-build 0a0c83
rpm-build 0a0c83
				status = restore(file,
rpm-build 0a0c83
				               (file == stdin) ? NULL : optarg);
rpm-build 0a0c83
rpm-build 0a0c83
				if (file != stdin)
rpm-build 0a0c83
					fclose(file);
rpm-build 0a0c83
				if (status != 0)
rpm-build 0a0c83
					goto cleanup;
rpm-build 0a0c83
				break;
rpm-build 0a0c83
rpm-build 0a0c83
			case 'R':  /* recursive */
rpm-build 0a0c83
				walk_flags |= WALK_TREE_RECURSIVE;
rpm-build 0a0c83
				break;
rpm-build 0a0c83
rpm-build 0a0c83
			case 'L':  /* follow symlinks */
rpm-build 0a0c83
				walk_flags |= WALK_TREE_LOGICAL | WALK_TREE_DEREFERENCE;
rpm-build 0a0c83
				walk_flags &= ~WALK_TREE_PHYSICAL;
rpm-build 0a0c83
				break;
rpm-build 0a0c83
rpm-build 0a0c83
			case 'P':  /* do not follow symlinks */
rpm-build 0a0c83
				walk_flags |= WALK_TREE_PHYSICAL;
rpm-build 0a0c83
				walk_flags &= ~(WALK_TREE_LOGICAL | WALK_TREE_DEREFERENCE |
rpm-build 0a0c83
						WALK_TREE_DEREFERENCE_TOPLEVEL);
rpm-build 0a0c83
				break;
rpm-build 0a0c83
rpm-build 0a0c83
			case 't':  /* test mode */
rpm-build 0a0c83
				opt_test = 1;
rpm-build 0a0c83
				break;
rpm-build 0a0c83
rpm-build 0a0c83
			case 'v':  /* print version and exit */
rpm-build 0a0c83
				printf("%s " VERSION "\n", progname);
rpm-build 0a0c83
				status = 0;
rpm-build 0a0c83
				goto cleanup;
rpm-build 0a0c83
rpm-build 0a0c83
			case 'h':  /* help! */
rpm-build 0a0c83
				help();
rpm-build 0a0c83
				status = 0;
rpm-build 0a0c83
				goto cleanup;
rpm-build 0a0c83
rpm-build 0a0c83
			case ':':  /* option missing */
rpm-build 0a0c83
			case '?':  /* unknown option */
rpm-build 0a0c83
			default:
rpm-build 0a0c83
				goto synopsis;
rpm-build 0a0c83
		}
rpm-build 0a0c83
		if (seq_remove_acl_cmd) {
rpm-build 0a0c83
			/* This was a set operation. Check if there are
rpm-build 0a0c83
			   actually entries of ACL_TYPE_ACCESS; if there
rpm-build 0a0c83
			   are none, we need to remove this command! */
rpm-build 0a0c83
			if (!has_any_of_type(seq_remove_acl_cmd->c_next,
rpm-build 0a0c83
				            ACL_TYPE_ACCESS))
rpm-build 0a0c83
				seq_delete_cmd(seq, seq_remove_acl_cmd);
rpm-build 0a0c83
		}
rpm-build 0a0c83
		if (seq_remove_default_acl_cmd) {
rpm-build 0a0c83
			/* This was a set operation. Check if there are
rpm-build 0a0c83
			   actually entries of ACL_TYPE_DEFAULT; if there
rpm-build 0a0c83
			   are none, we need to remove this command! */
rpm-build 0a0c83
			if (!has_any_of_type(seq_remove_default_acl_cmd->c_next,
rpm-build 0a0c83
				            ACL_TYPE_DEFAULT))
rpm-build 0a0c83
				seq_delete_cmd(seq, seq_remove_default_acl_cmd);
rpm-build 0a0c83
		}
rpm-build 0a0c83
	}
rpm-build 0a0c83
	while (optind < argc) {
rpm-build 0a0c83
		if(!seq)
rpm-build 0a0c83
			goto synopsis;
rpm-build 0a0c83
		if (seq_empty(seq))
rpm-build 0a0c83
			goto synopsis;
rpm-build 0a0c83
		saw_files = 1;
rpm-build 0a0c83
rpm-build 0a0c83
		status = next_file(argv[optind++], seq);
rpm-build 0a0c83
	}
rpm-build 0a0c83
	if (!saw_files)
rpm-build 0a0c83
		goto synopsis;
rpm-build 0a0c83
rpm-build 0a0c83
	goto cleanup;
rpm-build 0a0c83
rpm-build 0a0c83
synopsis:
rpm-build 0a0c83
	fprintf(stderr, _("Usage: %s %s\n"),
rpm-build 0a0c83
		progname, cmd_line_spec);
rpm-build 0a0c83
	fprintf(stderr, _("Try `%s --help' for more information.\n"),
rpm-build 0a0c83
		progname);
rpm-build 0a0c83
	status = 2;
rpm-build 0a0c83
	goto cleanup;
rpm-build 0a0c83
rpm-build 0a0c83
errno_error:
rpm-build 0a0c83
	fprintf(stderr, "%s: %s\n", progname, strerror(errno));
rpm-build 0a0c83
	goto cleanup;
rpm-build 0a0c83
rpm-build 0a0c83
cleanup:
rpm-build 0a0c83
	if (seq)
rpm-build 0a0c83
		seq_free(seq);
rpm-build 0a0c83
	return status;
rpm-build 0a0c83
}
rpm-build 0a0c83