Blame tools/chacl.c

rpm-build 0a0c83
/*
rpm-build 0a0c83
 * Copyright (c) 2001-2002 Silicon Graphics, Inc.
rpm-build 0a0c83
 * All Rights Reserved.
rpm-build 0a0c83
 *
rpm-build 0a0c83
 * This program is free software; you can redistribute it and/or modify it
rpm-build 0a0c83
 * under the terms of the GNU General Public License as published by
rpm-build 0a0c83
 * the Free Software Foundation, either version 2 of the License, or
rpm-build 0a0c83
 * (at your option) any later version.
rpm-build 0a0c83
 *
rpm-build 0a0c83
 * This program is distributed in the hope that it would 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
rpm-build 0a0c83
 * GNU General Public License for more details.
rpm-build 0a0c83
 *
rpm-build 0a0c83
 * You should have received a copy of the GNU General Public License
rpm-build 0a0c83
 * along with this program; if not, write the Free Software Foundation,
rpm-build 0a0c83
 * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
rpm-build 0a0c83
 */
rpm-build 0a0c83
rpm-build 0a0c83
#include "config.h"
rpm-build 0a0c83
#include <stdlib.h>
rpm-build 0a0c83
#include <string.h>
rpm-build 0a0c83
#include <unistd.h>
rpm-build 0a0c83
#include <getopt.h>
rpm-build 0a0c83
#include <libgen.h>
rpm-build 0a0c83
#include <stdio.h>
rpm-build 0a0c83
#include <errno.h>
rpm-build 0a0c83
#include <dirent.h>
rpm-build 0a0c83
#include <sys/types.h>
rpm-build 0a0c83
#include <sys/stat.h>
rpm-build 0a0c83
#include <sys/acl.h>
rpm-build 0a0c83
#include <acl/libacl.h>
rpm-build 0a0c83
#include "misc.h"
rpm-build 0a0c83
rpm-build 0a0c83
static int acl_delete_file (const char * path, acl_type_t type);
rpm-build 0a0c83
static int list_acl(char *file);
rpm-build 0a0c83
static int set_acl(acl_t acl, acl_t dacl, const char *fname);
rpm-build 0a0c83
static int walk_dir(acl_t acl, acl_t dacl, const char *fname);
rpm-build 0a0c83
rpm-build 0a0c83
static char *program;
rpm-build 0a0c83
static int rflag;
rpm-build 0a0c83
rpm-build 0a0c83
static void
rpm-build 0a0c83
usage(void)
rpm-build 0a0c83
{
rpm-build 0a0c83
	fprintf(stderr, _("Usage:\n"));
rpm-build 0a0c83
	fprintf(stderr, _("\t%s acl pathname...\n"), program);
rpm-build 0a0c83
	fprintf(stderr, _("\t%s -b acl dacl pathname...\n"), program);
rpm-build 0a0c83
	fprintf(stderr, _("\t%s -d dacl pathname...\n"), program);
rpm-build 0a0c83
	fprintf(stderr, _("\t%s -R pathname...\n"), program);
rpm-build 0a0c83
	fprintf(stderr, _("\t%s -D pathname...\n"), program);
rpm-build 0a0c83
	fprintf(stderr, _("\t%s -B pathname...\n"), program);
rpm-build 0a0c83
	fprintf(stderr, _("\t%s -l pathname...\t[not IRIX compatible]\n"),
rpm-build 0a0c83
			program);
rpm-build 0a0c83
	fprintf(stderr, _("\t%s -r pathname...\t[not IRIX compatible]\n"),
rpm-build 0a0c83
			program);
rpm-build 0a0c83
	exit(1);
rpm-build 0a0c83
}
rpm-build 0a0c83
rpm-build 0a0c83
int
rpm-build 0a0c83
main(int argc, char *argv[])
rpm-build 0a0c83
{
rpm-build 0a0c83
	char *file;
rpm-build 0a0c83
	int switch_flag = 0;            /* ensure only one switch is used */
rpm-build 0a0c83
	int args_required = 2;	
rpm-build 0a0c83
	int failed = 0;			/* exit status */
rpm-build 0a0c83
	int c;				/* For use by getopt(3) */
rpm-build 0a0c83
	int dflag = 0;			/* a Default ACL is desired */
rpm-build 0a0c83
	int bflag = 0;			/* a both ACLs are desired */
rpm-build 0a0c83
	int Rflag = 0;			/* set to true to remove an acl */
rpm-build 0a0c83
	int Dflag = 0;			/* set to true to remove default acls */
rpm-build 0a0c83
	int Bflag = 0;			/* set to true to remove both acls */
rpm-build 0a0c83
	int lflag = 0;			/* set to true to list acls */
rpm-build 0a0c83
	acl_t acl = NULL;		/* File ACL */
rpm-build 0a0c83
	acl_t dacl = NULL;		/* Directory Default ACL */
rpm-build 0a0c83
rpm-build 0a0c83
	program = basename(argv[0]);
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
	/* parse arguments */
rpm-build 0a0c83
	while ((c = getopt(argc, argv, "bdlRDBr")) != -1) {
rpm-build 0a0c83
		if (switch_flag) 
rpm-build 0a0c83
			usage();
rpm-build 0a0c83
		switch_flag = 1;
rpm-build 0a0c83
rpm-build 0a0c83
		switch (c) {
rpm-build 0a0c83
			case 'b':
rpm-build 0a0c83
				bflag = 1;
rpm-build 0a0c83
				args_required = 3;
rpm-build 0a0c83
				break;
rpm-build 0a0c83
			case 'd':
rpm-build 0a0c83
				dflag = 1;
rpm-build 0a0c83
				args_required = 2;
rpm-build 0a0c83
				break;
rpm-build 0a0c83
			case 'R':
rpm-build 0a0c83
				Rflag = 1;
rpm-build 0a0c83
				args_required = 1;
rpm-build 0a0c83
				break;
rpm-build 0a0c83
			case 'D':
rpm-build 0a0c83
				Dflag = 1;
rpm-build 0a0c83
				args_required = 1;
rpm-build 0a0c83
				break;
rpm-build 0a0c83
			case 'B':
rpm-build 0a0c83
				Bflag = 1;
rpm-build 0a0c83
				args_required = 1;
rpm-build 0a0c83
				break;
rpm-build 0a0c83
			case 'l':
rpm-build 0a0c83
				lflag = 1;
rpm-build 0a0c83
				args_required = 1;
rpm-build 0a0c83
				break;
rpm-build 0a0c83
			case 'r':
rpm-build 0a0c83
				rflag = 1;
rpm-build 0a0c83
				args_required = 1;
rpm-build 0a0c83
				break;
rpm-build 0a0c83
			default:
rpm-build 0a0c83
				usage();
rpm-build 0a0c83
				break;
rpm-build 0a0c83
		}
rpm-build 0a0c83
	}
rpm-build 0a0c83
rpm-build 0a0c83
	/* if not enough arguments quit */
rpm-build 0a0c83
	if ((argc - optind) < args_required)
rpm-build 0a0c83
		usage();
rpm-build 0a0c83
rpm-build 0a0c83
        /* list the acls */
rpm-build 0a0c83
	if (lflag) {
rpm-build 0a0c83
		for (; optind < argc; optind++) {	
rpm-build 0a0c83
			file = argv[optind];
rpm-build 0a0c83
			if (!list_acl(file))
rpm-build 0a0c83
				failed++;
rpm-build 0a0c83
		}
rpm-build 0a0c83
		return(failed);
rpm-build 0a0c83
	}
rpm-build 0a0c83
rpm-build 0a0c83
	/* remove the acls */
rpm-build 0a0c83
	if (Rflag || Dflag || Bflag) {
rpm-build 0a0c83
		for (; optind < argc; optind++) {	
rpm-build 0a0c83
			file = argv[optind];
rpm-build 0a0c83
			if (!Dflag &&
rpm-build 0a0c83
			    (acl_delete_file(file, ACL_TYPE_ACCESS) == -1)) {
rpm-build 0a0c83
				fprintf(stderr, _(
rpm-build 0a0c83
			"%s: error removing access acl on \"%s\": %s\n"),
rpm-build 0a0c83
					program, file, strerror(errno));
rpm-build 0a0c83
				failed++;
rpm-build 0a0c83
			}
rpm-build 0a0c83
			if (!Rflag &&
rpm-build 0a0c83
			    (acl_delete_file(file, ACL_TYPE_DEFAULT) == -1)) {
rpm-build 0a0c83
				fprintf(stderr, _(
rpm-build 0a0c83
			"%s: error removing default acl on \"%s\": %s\n"),
rpm-build 0a0c83
					program, file, strerror(errno));
rpm-build 0a0c83
				failed++;
rpm-build 0a0c83
			}
rpm-build 0a0c83
		}
rpm-build 0a0c83
		return(failed);
rpm-build 0a0c83
	}
rpm-build 0a0c83
rpm-build 0a0c83
	/* file access acl */
rpm-build 0a0c83
	if (! dflag) { 
rpm-build 0a0c83
		acl = acl_from_text(argv[optind]);
rpm-build 0a0c83
		failed = acl_check(acl, &c);
rpm-build 0a0c83
		if (failed < 0) {
rpm-build 0a0c83
			fprintf(stderr, "%s: %s - %s\n",
rpm-build 0a0c83
				program, argv[optind], strerror(errno));
rpm-build 0a0c83
			return 1;
rpm-build 0a0c83
		}
rpm-build 0a0c83
		else if (failed > 0) {
rpm-build 0a0c83
			fprintf(stderr, _(
rpm-build 0a0c83
				"%s: access ACL '%s': %s at entry %d\n"),
rpm-build 0a0c83
				program, argv[optind], acl_error(failed), c);
rpm-build 0a0c83
			return 1;
rpm-build 0a0c83
		}
rpm-build 0a0c83
		optind++;
rpm-build 0a0c83
	}
rpm-build 0a0c83
rpm-build 0a0c83
rpm-build 0a0c83
	/* directory default acl */
rpm-build 0a0c83
	if (bflag || dflag) {
rpm-build 0a0c83
		dacl = acl_from_text(argv[optind]);
rpm-build 0a0c83
		failed = acl_check(dacl, &c);
rpm-build 0a0c83
		if (failed < 0) {
rpm-build 0a0c83
			fprintf(stderr, "%s: %s - %s\n",
rpm-build 0a0c83
				program, argv[optind], strerror(errno));
rpm-build 0a0c83
			return 1;
rpm-build 0a0c83
		}
rpm-build 0a0c83
		else if (failed > 0) {
rpm-build 0a0c83
			fprintf(stderr, _(
rpm-build 0a0c83
				"%s: access ACL '%s': %s at entry %d\n"),
rpm-build 0a0c83
				program, argv[optind], acl_error(failed), c);
rpm-build 0a0c83
			return 1;
rpm-build 0a0c83
		}
rpm-build 0a0c83
		optind++;
rpm-build 0a0c83
	}
rpm-build 0a0c83
rpm-build 0a0c83
	/* place acls on files */
rpm-build 0a0c83
	for (; optind < argc; optind++)
rpm-build 0a0c83
		failed += set_acl(acl, dacl, argv[optind]);
rpm-build 0a0c83
rpm-build 0a0c83
	if (acl)
rpm-build 0a0c83
		acl_free(acl);
rpm-build 0a0c83
	if (dacl)
rpm-build 0a0c83
		acl_free(dacl);
rpm-build 0a0c83
rpm-build 0a0c83
	return(failed);
rpm-build 0a0c83
}
rpm-build 0a0c83
rpm-build 0a0c83
/* 
rpm-build 0a0c83
 *   deletes an access acl or directory default acl if one exists
rpm-build 0a0c83
 */ 
rpm-build 0a0c83
static int 
rpm-build 0a0c83
acl_delete_file(const char *path, acl_type_t type)
rpm-build 0a0c83
{
rpm-build 0a0c83
	int error = 0;
rpm-build 0a0c83
rpm-build 0a0c83
	/* converts access ACL to a minimal ACL */
rpm-build 0a0c83
	if (type == ACL_TYPE_ACCESS) {
rpm-build 0a0c83
		acl_t acl;
rpm-build 0a0c83
		acl_entry_t entry;
rpm-build 0a0c83
		acl_tag_t tag;
rpm-build 0a0c83
rpm-build 0a0c83
		acl = acl_get_file(path, ACL_TYPE_ACCESS);
rpm-build 0a0c83
		if (!acl)
rpm-build 0a0c83
			return -1;
rpm-build 0a0c83
		error = acl_get_entry(acl, ACL_FIRST_ENTRY, &entry);
rpm-build 0a0c83
		while (error == 1) {
rpm-build 0a0c83
			acl_get_tag_type(entry, &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, entry);
rpm-build 0a0c83
					break;
rpm-build 0a0c83
			 }
rpm-build 0a0c83
			error = acl_get_entry(acl, ACL_NEXT_ENTRY, &entry);
rpm-build 0a0c83
		}
rpm-build 0a0c83
		if (!error)
rpm-build 0a0c83
			error = acl_set_file(path, ACL_TYPE_ACCESS, acl);
rpm-build 0a0c83
	} else
rpm-build 0a0c83
		error = acl_delete_def_file(path);
rpm-build 0a0c83
	return(error);
rpm-build 0a0c83
}
rpm-build 0a0c83
rpm-build 0a0c83
/*
rpm-build 0a0c83
 *    lists the acl for a file/dir in short text form
rpm-build 0a0c83
 *    return 0 on failure
rpm-build 0a0c83
 *    return 1 on success
rpm-build 0a0c83
 */
rpm-build 0a0c83
static int
rpm-build 0a0c83
list_acl(char *file)
rpm-build 0a0c83
{
rpm-build 0a0c83
	acl_t acl = NULL;
rpm-build 0a0c83
	acl_t dacl = NULL;
rpm-build 0a0c83
	char *acl_text, *dacl_text = NULL;
rpm-build 0a0c83
rpm-build 0a0c83
	if ((acl = acl_get_file(file, ACL_TYPE_ACCESS)) == NULL) {
rpm-build 0a0c83
		fprintf(stderr, _("%s: cannot get access ACL on '%s': %s\n"),
rpm-build 0a0c83
			program, file, strerror(errno));
rpm-build 0a0c83
		return 0;
rpm-build 0a0c83
	}
rpm-build 0a0c83
	if ((dacl = acl_get_file(file, ACL_TYPE_DEFAULT)) == NULL &&
rpm-build 0a0c83
	    (errno != EACCES)) {	/* EACCES given if not a directory */
rpm-build 0a0c83
		fprintf(stderr, _("%s: cannot get default ACL on '%s': %s\n"),
rpm-build 0a0c83
			program, file, strerror(errno));
rpm-build 0a0c83
		return 0;
rpm-build 0a0c83
	}
rpm-build 0a0c83
	acl_text = acl_to_any_text(acl, NULL, ',', TEXT_ABBREVIATE);
rpm-build 0a0c83
	if (acl_text == NULL) {
rpm-build 0a0c83
		fprintf(stderr, _("%s: cannot get access ACL text on "
rpm-build 0a0c83
			"'%s': %s\n"), program, file, strerror(errno));
rpm-build 0a0c83
		return 0;
rpm-build 0a0c83
	}
rpm-build 0a0c83
	if (acl_entries(dacl) > 0) {
rpm-build 0a0c83
		dacl_text = acl_to_any_text(dacl, NULL, ',', TEXT_ABBREVIATE);
rpm-build 0a0c83
		if (dacl_text == NULL) {
rpm-build 0a0c83
			fprintf(stderr, _("%s: cannot get default ACL text on "
rpm-build 0a0c83
				"'%s': %s\n"), program, file, strerror(errno));
rpm-build 0a0c83
			return 0;
rpm-build 0a0c83
		}
rpm-build 0a0c83
	}
rpm-build 0a0c83
	if (dacl_text) {
rpm-build 0a0c83
		printf("%s [%s/%s]\n", file, acl_text, dacl_text);
rpm-build 0a0c83
		acl_free(dacl_text);
rpm-build 0a0c83
	} else
rpm-build 0a0c83
		printf("%s [%s]\n", file, acl_text);
rpm-build 0a0c83
	acl_free(acl_text);
rpm-build 0a0c83
	acl_free(acl);
rpm-build 0a0c83
	acl_free(dacl);
rpm-build 0a0c83
	return 1;
rpm-build 0a0c83
}
rpm-build 0a0c83
rpm-build 0a0c83
static int
rpm-build 0a0c83
set_acl(acl_t acl, acl_t dacl, const char *fname)
rpm-build 0a0c83
{
rpm-build 0a0c83
	int failed = 0;
rpm-build 0a0c83
rpm-build 0a0c83
	if (rflag)
rpm-build 0a0c83
		failed += walk_dir(acl, dacl, fname);
rpm-build 0a0c83
rpm-build 0a0c83
	/* set regular acl */
rpm-build 0a0c83
	if (acl && acl_set_file(fname, ACL_TYPE_ACCESS, acl) == -1) {
rpm-build 0a0c83
		fprintf(stderr, _("%s: cannot set access acl on \"%s\": %s\n"),
rpm-build 0a0c83
			program, fname, strerror(errno));
rpm-build 0a0c83
		failed++;
rpm-build 0a0c83
	}
rpm-build 0a0c83
	/* set default acl */
rpm-build 0a0c83
	if (dacl && acl_set_file(fname, ACL_TYPE_DEFAULT, dacl) == -1) {
rpm-build 0a0c83
		fprintf(stderr, _("%s: cannot set default acl on \"%s\": %s\n"),
rpm-build 0a0c83
			program, fname, strerror(errno));
rpm-build 0a0c83
		failed++;
rpm-build 0a0c83
	}
rpm-build 0a0c83
rpm-build 0a0c83
	return(failed);
rpm-build 0a0c83
}
rpm-build 0a0c83
rpm-build 0a0c83
static int
rpm-build 0a0c83
walk_dir(acl_t acl, acl_t dacl, const char *fname)
rpm-build 0a0c83
{
rpm-build 0a0c83
	int failed = 0;
rpm-build 0a0c83
	DIR *dir;
rpm-build 0a0c83
	struct dirent64 *d;
rpm-build 0a0c83
	char *name;
rpm-build 0a0c83
rpm-build 0a0c83
	if ((dir = opendir(fname)) == NULL) {
rpm-build 0a0c83
		if (errno != ENOTDIR) {
rpm-build 0a0c83
			fprintf(stderr, _("%s: opendir failed: %s\n"),
rpm-build 0a0c83
				program, strerror(errno));
rpm-build 0a0c83
			return(1);
rpm-build 0a0c83
		}
rpm-build 0a0c83
		return(0);	/* got a file, not an error */
rpm-build 0a0c83
	}
rpm-build 0a0c83
rpm-build 0a0c83
	while ((d = readdir64(dir)) != NULL) {
rpm-build 0a0c83
		/* skip "." and ".." entries */
rpm-build 0a0c83
		if (strcmp(d->d_name, ".") == 0 || strcmp(d->d_name, "..") == 0)
rpm-build 0a0c83
			continue;
rpm-build 0a0c83
		
rpm-build 0a0c83
		name = malloc(strlen(fname) + strlen(d->d_name) + 2);
rpm-build 0a0c83
		if (name == NULL) {
rpm-build 0a0c83
			fprintf(stderr, _("%s: malloc failed: %s\n"),
rpm-build 0a0c83
				program, strerror(errno));
rpm-build 0a0c83
			exit(1);
rpm-build 0a0c83
		}
rpm-build 0a0c83
		sprintf(name, "%s/%s", fname, d->d_name);
rpm-build 0a0c83
rpm-build 0a0c83
		failed += set_acl(acl, dacl, name);
rpm-build 0a0c83
		free(name);
rpm-build 0a0c83
	}
rpm-build 0a0c83
	closedir(dir);
rpm-build 0a0c83
rpm-build 0a0c83
	return(failed);
rpm-build 0a0c83
}