Blame tools/getfacl.c

rpm-build 0a0c83
/*
rpm-build 0a0c83
  File: getfacl.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 modify
rpm-build 0a0c83
  it 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 (at
rpm-build 0a0c83
  your option) any later version.
rpm-build 0a0c83
rpm-build 0a0c83
  This program is distributed in the hope that it will be useful, but
rpm-build 0a0c83
  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
  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 library; if not, write to the Free Software
rpm-build 0a0c83
  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
rpm-build 0a0c83
  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 <limits.h>
rpm-build 0a0c83
#include <stdlib.h>
rpm-build 0a0c83
#include <unistd.h>
rpm-build 0a0c83
#include <string.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 "user_group.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
#if !POSIXLY_CORRECT
rpm-build 0a0c83
#  define CMD_LINE_OPTIONS "aceEsRLPtpndvh"
rpm-build 0a0c83
#endif
rpm-build 0a0c83
#define POSIXLY_CMD_LINE_OPTIONS "d"
rpm-build 0a0c83
rpm-build 0a0c83
struct option long_options[] = {
rpm-build 0a0c83
#if !POSIXLY_CORRECT
rpm-build 0a0c83
	{ "access",	0, 0, 'a' },
rpm-build 0a0c83
	{ "omit-header",	0, 0, 'c' },
rpm-build 0a0c83
	{ "all-effective",	0, 0, 'e' },
rpm-build 0a0c83
	{ "no-effective",	0, 0, 'E' },
rpm-build 0a0c83
	{ "skip-base",	0, 0, 's' },
rpm-build 0a0c83
	{ "recursive",	0, 0, 'R' },
rpm-build 0a0c83
	{ "logical",	0, 0, 'L' },
rpm-build 0a0c83
	{ "physical",	0, 0, 'P' },
rpm-build 0a0c83
	{ "tabular",	0, 0, 't' },
rpm-build 0a0c83
	{ "absolute-names",	0, 0, 'p' },
rpm-build 0a0c83
	{ "numeric",	0, 0, 'n' },
rpm-build 0a0c83
#endif
rpm-build 0a0c83
	{ "default",	0, 0, 'd' },
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;
rpm-build 0a0c83
rpm-build 0a0c83
int walk_flags = WALK_TREE_DEREFERENCE_TOPLEVEL;
rpm-build 0a0c83
int opt_print_acl;
rpm-build 0a0c83
int opt_print_default_acl;
rpm-build 0a0c83
int opt_strip_leading_slash = 1;
rpm-build 0a0c83
int opt_comments = 1;  /* include comments */
rpm-build 0a0c83
int opt_skip_base;  /* skip files that only have the base entries */
rpm-build 0a0c83
int opt_tabular;  /* tabular output format (alias `showacl') */
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 had_errors;
rpm-build 0a0c83
int absolute_warning;  /* Absolute path warning was issued */
rpm-build 0a0c83
int print_options = TEXT_SOME_EFFECTIVE;
rpm-build 0a0c83
int opt_numeric;  /* don't convert id's to symbolic names */
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
struct name_list {
rpm-build 0a0c83
	struct name_list *next;
rpm-build 0a0c83
	char name[0];
rpm-build 0a0c83
};
rpm-build 0a0c83
rpm-build 0a0c83
void free_list(struct name_list *names)
rpm-build 0a0c83
{
rpm-build 0a0c83
	struct name_list *next;
rpm-build 0a0c83
rpm-build 0a0c83
	while (names) {
rpm-build 0a0c83
		next = names->next;
rpm-build 0a0c83
		free(names);
rpm-build 0a0c83
		names = next;
rpm-build 0a0c83
	}
rpm-build 0a0c83
}
rpm-build 0a0c83
rpm-build 0a0c83
struct name_list *get_list(const struct stat *st, acl_t acl)
rpm-build 0a0c83
{
rpm-build 0a0c83
	struct name_list *first = NULL, *last = NULL;
rpm-build 0a0c83
	acl_entry_t ent;
rpm-build 0a0c83
	int ret = 0;
rpm-build 0a0c83
rpm-build 0a0c83
	if (acl != NULL)
rpm-build 0a0c83
		ret = acl_get_entry(acl, ACL_FIRST_ENTRY, &ent;;
rpm-build 0a0c83
	if (ret != 1)
rpm-build 0a0c83
		return NULL;
rpm-build 0a0c83
	while (ret > 0) {
rpm-build 0a0c83
		acl_tag_t e_type;
rpm-build 0a0c83
		id_t *id_p;
rpm-build 0a0c83
		const char *name = "";
rpm-build 0a0c83
		int len;
rpm-build 0a0c83
rpm-build 0a0c83
		acl_get_tag_type(ent, &e_type);
rpm-build 0a0c83
		switch(e_type) {
rpm-build 0a0c83
			case ACL_USER_OBJ:
rpm-build 0a0c83
				name = user_name(st->st_uid, opt_numeric);
rpm-build 0a0c83
				break;
rpm-build 0a0c83
rpm-build 0a0c83
			case ACL_USER:
rpm-build 0a0c83
				id_p = acl_get_qualifier(ent);
rpm-build 0a0c83
				if (id_p != NULL) {
rpm-build 0a0c83
					name = user_name(*id_p, opt_numeric);
rpm-build 0a0c83
					acl_free(id_p);
rpm-build 0a0c83
				}
rpm-build 0a0c83
				break;
rpm-build 0a0c83
rpm-build 0a0c83
			case ACL_GROUP_OBJ:
rpm-build 0a0c83
				name = group_name(st->st_gid, opt_numeric);
rpm-build 0a0c83
				break;
rpm-build 0a0c83
rpm-build 0a0c83
			case ACL_GROUP:
rpm-build 0a0c83
				id_p = acl_get_qualifier(ent);
rpm-build 0a0c83
				if (id_p != NULL) {
rpm-build 0a0c83
					name = group_name(*id_p, opt_numeric);
rpm-build 0a0c83
					acl_free(id_p);
rpm-build 0a0c83
				}
rpm-build 0a0c83
				break;
rpm-build 0a0c83
		}
rpm-build 0a0c83
		name = xquote(name, "\t\n\r");
rpm-build 0a0c83
		len = strlen(name);
rpm-build 0a0c83
		if (last == NULL) {
rpm-build 0a0c83
			first = last = (struct name_list *)
rpm-build 0a0c83
				malloc(sizeof(struct name_list) + len + 1);
rpm-build 0a0c83
		} else {
rpm-build 0a0c83
			last->next = (struct name_list *)
rpm-build 0a0c83
				malloc(sizeof(struct name_list) + len + 1);
rpm-build 0a0c83
			last = last->next;
rpm-build 0a0c83
		}
rpm-build 0a0c83
		if (last == NULL) {
rpm-build 0a0c83
			free_list(first);
rpm-build 0a0c83
			return NULL;
rpm-build 0a0c83
		}
rpm-build 0a0c83
		last->next = NULL;
rpm-build 0a0c83
		strcpy(last->name, name);
rpm-build 0a0c83
rpm-build 0a0c83
		ret = acl_get_entry(acl, ACL_NEXT_ENTRY, &ent;;
rpm-build 0a0c83
	}
rpm-build 0a0c83
	return first;
rpm-build 0a0c83
}
rpm-build 0a0c83
rpm-build 0a0c83
int max_name_length(struct name_list *names)
rpm-build 0a0c83
{
rpm-build 0a0c83
	int max_len = 0;
rpm-build 0a0c83
	while (names != NULL) {
rpm-build 0a0c83
		struct name_list *next = names->next;
rpm-build 0a0c83
		int len = strlen(names->name);
rpm-build 0a0c83
rpm-build 0a0c83
		if (len > max_len)
rpm-build 0a0c83
			max_len = len;
rpm-build 0a0c83
		names = next;
rpm-build 0a0c83
	}
rpm-build 0a0c83
	return max_len;
rpm-build 0a0c83
}
rpm-build 0a0c83
rpm-build 0a0c83
int names_width;
rpm-build 0a0c83
rpm-build 0a0c83
struct acl_perm_def {
rpm-build 0a0c83
	acl_tag_t	tag;
rpm-build 0a0c83
	char		c;
rpm-build 0a0c83
};
rpm-build 0a0c83
rpm-build 0a0c83
struct acl_perm_def acl_perm_defs[] = {
rpm-build 0a0c83
	{ ACL_READ,	'r' },
rpm-build 0a0c83
	{ ACL_WRITE,	'w' },
rpm-build 0a0c83
	{ ACL_EXECUTE,	'x' },
rpm-build 0a0c83
	{ 0, 0 }
rpm-build 0a0c83
};
rpm-build 0a0c83
rpm-build 0a0c83
#define ACL_PERMS (sizeof(acl_perm_defs) / sizeof(struct acl_perm_def) - 1)
rpm-build 0a0c83
rpm-build 0a0c83
void acl_perm_str(acl_entry_t entry, char *str)
rpm-build 0a0c83
{
rpm-build 0a0c83
	acl_permset_t permset;
rpm-build 0a0c83
	int n;
rpm-build 0a0c83
rpm-build 0a0c83
	acl_get_permset(entry, &permset);
rpm-build 0a0c83
	for (n = 0; n < (int) ACL_PERMS; n++) {
rpm-build 0a0c83
		str[n] = (acl_get_perm(permset, acl_perm_defs[n].tag) ?
rpm-build 0a0c83
		          acl_perm_defs[n].c : '-');
rpm-build 0a0c83
	}
rpm-build 0a0c83
	str[n] = '\0';
rpm-build 0a0c83
}
rpm-build 0a0c83
rpm-build 0a0c83
void acl_mask_perm_str(acl_t acl, char *str)
rpm-build 0a0c83
{
rpm-build 0a0c83
	acl_entry_t entry;
rpm-build 0a0c83
rpm-build 0a0c83
	str[0] = '\0';
rpm-build 0a0c83
	if (acl_get_entry(acl, ACL_FIRST_ENTRY, &entry) != 1)
rpm-build 0a0c83
		return;
rpm-build 0a0c83
	for(;;) {
rpm-build 0a0c83
		acl_tag_t tag;
rpm-build 0a0c83
rpm-build 0a0c83
		acl_get_tag_type(entry, &tag;;
rpm-build 0a0c83
		if (tag == ACL_MASK) {
rpm-build 0a0c83
			acl_perm_str(entry, str);
rpm-build 0a0c83
			return;
rpm-build 0a0c83
		}
rpm-build 0a0c83
		if (acl_get_entry(acl, ACL_NEXT_ENTRY, &entry) != 1)
rpm-build 0a0c83
			return;
rpm-build 0a0c83
	}
rpm-build 0a0c83
}
rpm-build 0a0c83
rpm-build 0a0c83
void apply_mask(char *perm, const char *mask)
rpm-build 0a0c83
{
rpm-build 0a0c83
	while (*perm) {
rpm-build 0a0c83
		if (*mask == '-' && *perm >= 'a' && *perm <= 'z')
rpm-build 0a0c83
			*perm = *perm - 'a' + 'A';
rpm-build 0a0c83
		perm++;
rpm-build 0a0c83
		if (*mask)
rpm-build 0a0c83
			mask++;
rpm-build 0a0c83
	}
rpm-build 0a0c83
}
rpm-build 0a0c83
rpm-build 0a0c83
int show_line(FILE *stream, struct name_list **acl_names,  acl_t acl,
rpm-build 0a0c83
              acl_entry_t *acl_ent, const char *acl_mask,
rpm-build 0a0c83
              struct name_list **dacl_names, acl_t dacl,
rpm-build 0a0c83
	      acl_entry_t *dacl_ent, const char *dacl_mask)
rpm-build 0a0c83
{
rpm-build 0a0c83
	acl_tag_t tag_type;
rpm-build 0a0c83
	const char *tag, *name;
rpm-build 0a0c83
	char acl_perm[ACL_PERMS+1], dacl_perm[ACL_PERMS+1];
rpm-build 0a0c83
rpm-build 0a0c83
	if (acl) {
rpm-build 0a0c83
		acl_get_tag_type(*acl_ent, &tag_type);
rpm-build 0a0c83
		name = (*acl_names)->name;
rpm-build 0a0c83
	} else {
rpm-build 0a0c83
		acl_get_tag_type(*dacl_ent, &tag_type);
rpm-build 0a0c83
		name = (*dacl_names)->name;
rpm-build 0a0c83
	}
rpm-build 0a0c83
rpm-build 0a0c83
	switch(tag_type) {
rpm-build 0a0c83
		case ACL_USER_OBJ:
rpm-build 0a0c83
			tag = "USER";
rpm-build 0a0c83
			break;
rpm-build 0a0c83
		case ACL_USER:
rpm-build 0a0c83
			tag = "user";
rpm-build 0a0c83
			break;
rpm-build 0a0c83
		case ACL_GROUP_OBJ:
rpm-build 0a0c83
			tag = "GROUP";
rpm-build 0a0c83
			break;
rpm-build 0a0c83
		case ACL_GROUP:
rpm-build 0a0c83
			tag = "group";
rpm-build 0a0c83
			break;
rpm-build 0a0c83
		case ACL_MASK:
rpm-build 0a0c83
			tag = "mask";
rpm-build 0a0c83
			break;
rpm-build 0a0c83
		case ACL_OTHER:
rpm-build 0a0c83
			tag = "other";
rpm-build 0a0c83
			break;
rpm-build 0a0c83
		default:
rpm-build 0a0c83
			return -1;
rpm-build 0a0c83
	}
rpm-build 0a0c83
rpm-build 0a0c83
	memset(acl_perm, ' ', ACL_PERMS);
rpm-build 0a0c83
	acl_perm[ACL_PERMS] = '\0';
rpm-build 0a0c83
	if (acl_ent) {
rpm-build 0a0c83
		acl_perm_str(*acl_ent, acl_perm);
rpm-build 0a0c83
		if (tag_type != ACL_USER_OBJ && tag_type != ACL_OTHER &&
rpm-build 0a0c83
		    tag_type != ACL_MASK)
rpm-build 0a0c83
			apply_mask(acl_perm, acl_mask);
rpm-build 0a0c83
	}
rpm-build 0a0c83
	memset(dacl_perm, ' ', ACL_PERMS);
rpm-build 0a0c83
	dacl_perm[ACL_PERMS] = '\0';
rpm-build 0a0c83
	if (dacl_ent) {
rpm-build 0a0c83
		acl_perm_str(*dacl_ent, dacl_perm);
rpm-build 0a0c83
		if (tag_type != ACL_USER_OBJ && tag_type != ACL_OTHER &&
rpm-build 0a0c83
		    tag_type != ACL_MASK)
rpm-build 0a0c83
			apply_mask(dacl_perm, dacl_mask);
rpm-build 0a0c83
	}
rpm-build 0a0c83
rpm-build 0a0c83
	fprintf(stream, "%-5s  %*s  %*s  %*s\n",
rpm-build 0a0c83
	        tag, -names_width, name,
rpm-build 0a0c83
	        -(int)ACL_PERMS, acl_perm,
rpm-build 0a0c83
		-(int)ACL_PERMS, dacl_perm);
rpm-build 0a0c83
rpm-build 0a0c83
	if (acl_names) {
rpm-build 0a0c83
		acl_get_entry(acl, ACL_NEXT_ENTRY, acl_ent);
rpm-build 0a0c83
		(*acl_names) = (*acl_names)->next;
rpm-build 0a0c83
	}
rpm-build 0a0c83
	if (dacl_names) {
rpm-build 0a0c83
		acl_get_entry(dacl, ACL_NEXT_ENTRY, dacl_ent);
rpm-build 0a0c83
		(*dacl_names) = (*dacl_names)->next;
rpm-build 0a0c83
	}
rpm-build 0a0c83
	return 0;
rpm-build 0a0c83
}
rpm-build 0a0c83
rpm-build 0a0c83
int do_show(FILE *stream, const char *path_p, const struct stat *st,
rpm-build 0a0c83
            acl_t acl, acl_t dacl)
rpm-build 0a0c83
{
rpm-build 0a0c83
	struct name_list *acl_names = get_list(st, acl),
rpm-build 0a0c83
	                 *first_acl_name = acl_names;
rpm-build 0a0c83
	struct name_list *dacl_names = get_list(st, dacl),
rpm-build 0a0c83
	                 *first_dacl_name = dacl_names;
rpm-build 0a0c83
	
rpm-build 0a0c83
	int acl_names_width = max_name_length(acl_names);
rpm-build 0a0c83
	int dacl_names_width = max_name_length(dacl_names);
rpm-build 0a0c83
	acl_entry_t acl_ent;
rpm-build 0a0c83
	acl_entry_t dacl_ent;
rpm-build 0a0c83
	char acl_mask[ACL_PERMS+1], dacl_mask[ACL_PERMS+1];
rpm-build 0a0c83
	int ret;
rpm-build 0a0c83
rpm-build 0a0c83
	names_width = 8;
rpm-build 0a0c83
	if (acl_names_width > names_width)
rpm-build 0a0c83
		names_width = acl_names_width;
rpm-build 0a0c83
	if (dacl_names_width > names_width)
rpm-build 0a0c83
		names_width = dacl_names_width;
rpm-build 0a0c83
rpm-build 0a0c83
	acl_mask[0] = '\0';
rpm-build 0a0c83
	if (acl) {
rpm-build 0a0c83
		acl_mask_perm_str(acl, acl_mask);
rpm-build 0a0c83
		ret = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_ent);
rpm-build 0a0c83
		if (ret == 0)
rpm-build 0a0c83
			acl = NULL;
rpm-build 0a0c83
		if (ret < 0)
rpm-build 0a0c83
			return ret;
rpm-build 0a0c83
	}
rpm-build 0a0c83
	dacl_mask[0] = '\0';
rpm-build 0a0c83
	if (dacl) {
rpm-build 0a0c83
		acl_mask_perm_str(dacl, dacl_mask);
rpm-build 0a0c83
		ret = acl_get_entry(dacl, ACL_FIRST_ENTRY, &dacl_ent);
rpm-build 0a0c83
		if (ret == 0)
rpm-build 0a0c83
			dacl = NULL;
rpm-build 0a0c83
		if (ret < 0)
rpm-build 0a0c83
			return ret;
rpm-build 0a0c83
	}
rpm-build 0a0c83
	fprintf(stream, "# file: %s\n", xquote(path_p, "\n\r"));
rpm-build 0a0c83
	while (acl_names != NULL || dacl_names != NULL) {
rpm-build 0a0c83
		acl_tag_t acl_tag, dacl_tag;
rpm-build 0a0c83
rpm-build 0a0c83
		if (acl)
rpm-build 0a0c83
			acl_get_tag_type(acl_ent, &acl_tag);
rpm-build 0a0c83
		if (dacl)
rpm-build 0a0c83
			acl_get_tag_type(dacl_ent, &dacl_tag);
rpm-build 0a0c83
rpm-build 0a0c83
		if (acl && (!dacl || acl_tag < dacl_tag)) {
rpm-build 0a0c83
			show_line(stream, &acl_names, acl, &acl_ent, acl_mask,
rpm-build 0a0c83
			          NULL, NULL, NULL, NULL);
rpm-build 0a0c83
			continue;
rpm-build 0a0c83
		} else if (dacl && (!acl || dacl_tag < acl_tag)) {
rpm-build 0a0c83
			show_line(stream, NULL, NULL, NULL, NULL,
rpm-build 0a0c83
			          &dacl_names, dacl, &dacl_ent, dacl_mask);
rpm-build 0a0c83
			continue;
rpm-build 0a0c83
		} else {
rpm-build 0a0c83
			if (acl_tag == ACL_USER || acl_tag == ACL_GROUP) {
rpm-build 0a0c83
				int id_cmp = 0;
rpm-build 0a0c83
rpm-build 0a0c83
				if (acl_ent && dacl_ent) {
rpm-build 0a0c83
					id_t *acl_id_p = acl_get_qualifier(acl_ent);
rpm-build 0a0c83
					id_t *dacl_id_p = acl_get_qualifier(dacl_ent);
rpm-build 0a0c83
rpm-build 0a0c83
					id_cmp = (*acl_id_p > *dacl_id_p) -
rpm-build 0a0c83
						 (*acl_id_p < *dacl_id_p);
rpm-build 0a0c83
					acl_free(acl_id_p);
rpm-build 0a0c83
					acl_free(dacl_id_p);
rpm-build 0a0c83
				}
rpm-build 0a0c83
				
rpm-build 0a0c83
				if (acl && (!dacl || id_cmp < 0)) {
rpm-build 0a0c83
					show_line(stream, &acl_names, acl,
rpm-build 0a0c83
					          &acl_ent, acl_mask,
rpm-build 0a0c83
						  NULL, NULL, NULL, NULL);
rpm-build 0a0c83
					continue;
rpm-build 0a0c83
				} else if (dacl && (!acl || id_cmp > 0)) {
rpm-build 0a0c83
					show_line(stream, NULL, NULL, NULL,
rpm-build 0a0c83
					          NULL, &dacl_names, dacl,
rpm-build 0a0c83
						  &dacl_ent, dacl_mask);
rpm-build 0a0c83
					continue;
rpm-build 0a0c83
				}
rpm-build 0a0c83
			}
rpm-build 0a0c83
			show_line(stream, &acl_names,  acl,  &acl_ent, acl_mask,
rpm-build 0a0c83
				  &dacl_names, dacl, &dacl_ent, dacl_mask);
rpm-build 0a0c83
		}
rpm-build 0a0c83
	}
rpm-build 0a0c83
rpm-build 0a0c83
	free_list(first_acl_name);
rpm-build 0a0c83
	free_list(first_dacl_name);
rpm-build 0a0c83
rpm-build 0a0c83
	return 0;
rpm-build 0a0c83
}
rpm-build 0a0c83
rpm-build 0a0c83
/*
rpm-build 0a0c83
 * Create an ACL from the file permission bits
rpm-build 0a0c83
 * of the file PATH_P.
rpm-build 0a0c83
 */
rpm-build 0a0c83
static acl_t
rpm-build 0a0c83
acl_get_file_mode(const char *path_p)
rpm-build 0a0c83
{
rpm-build 0a0c83
	struct stat st;
rpm-build 0a0c83
rpm-build 0a0c83
	if (stat(path_p, &st) != 0)
rpm-build 0a0c83
		return NULL;
rpm-build 0a0c83
	return acl_from_mode(st.st_mode);
rpm-build 0a0c83
}
rpm-build 0a0c83
rpm-build 0a0c83
static const char *
rpm-build 0a0c83
flagstr(mode_t mode)
rpm-build 0a0c83
{
rpm-build 0a0c83
	static char str[4];
rpm-build 0a0c83
rpm-build 0a0c83
	str[0] = (mode & S_ISUID) ? 's' : '-';
rpm-build 0a0c83
	str[1] = (mode & S_ISGID) ? 's' : '-';
rpm-build 0a0c83
	str[2] = (mode & S_ISVTX) ? 't' : '-';
rpm-build 0a0c83
	str[3] = '\0';
rpm-build 0a0c83
	return str;
rpm-build 0a0c83
}
rpm-build 0a0c83
rpm-build 0a0c83
int do_print(const char *path_p, const struct stat *st, int walk_flags, void *unused)
rpm-build 0a0c83
{
rpm-build 0a0c83
	const char *default_prefix = NULL;
rpm-build 0a0c83
	acl_t acl = NULL, default_acl = NULL;
rpm-build 0a0c83
	int error = 0;
rpm-build 0a0c83
rpm-build 0a0c83
	if (walk_flags & WALK_TREE_FAILED) {
rpm-build 0a0c83
		fprintf(stderr, "%s: %s: %s\n", progname, xquote(path_p, "\n\r"),
rpm-build 0a0c83
			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
	if (opt_print_acl) {
rpm-build 0a0c83
		acl = acl_get_file(path_p, ACL_TYPE_ACCESS);
rpm-build 0a0c83
		if (acl == NULL && (errno == ENOSYS || errno == ENOTSUP))
rpm-build 0a0c83
			acl = acl_get_file_mode(path_p);
rpm-build 0a0c83
		if (acl == NULL)
rpm-build 0a0c83
			goto fail;
rpm-build 0a0c83
	}
rpm-build 0a0c83
rpm-build 0a0c83
	if (opt_print_default_acl && S_ISDIR(st->st_mode)) {
rpm-build 0a0c83
		default_acl = acl_get_file(path_p, ACL_TYPE_DEFAULT);
rpm-build 0a0c83
		if (default_acl == NULL) {
rpm-build 0a0c83
			if (errno != ENOSYS && errno != ENOTSUP)
rpm-build 0a0c83
				goto fail;
rpm-build 0a0c83
		} else if (acl_entries(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
rpm-build 0a0c83
	if (opt_skip_base &&
rpm-build 0a0c83
	    (!acl || acl_equiv_mode(acl, NULL) == 0) && !default_acl)
rpm-build 0a0c83
		goto cleanup;
rpm-build 0a0c83
rpm-build 0a0c83
	if (opt_print_acl && opt_print_default_acl)
rpm-build 0a0c83
		default_prefix = "default:";
rpm-build 0a0c83
rpm-build 0a0c83
	if (opt_strip_leading_slash) {
rpm-build 0a0c83
		if (*path_p == '/') {
rpm-build 0a0c83
			if (!absolute_warning) {
rpm-build 0a0c83
				fprintf(stderr, _("%s: Removing leading "
rpm-build 0a0c83
					"'/' from absolute path names\n"),
rpm-build 0a0c83
				        progname);
rpm-build 0a0c83
				absolute_warning = 1;
rpm-build 0a0c83
			}
rpm-build 0a0c83
			while (*path_p == '/')
rpm-build 0a0c83
				path_p++;
rpm-build 0a0c83
		} else if (*path_p == '.' && *(path_p+1) == '/')
rpm-build 0a0c83
			while (*++path_p == '/')
rpm-build 0a0c83
				/* nothing */ ;
rpm-build 0a0c83
		if (*path_p == '\0')
rpm-build 0a0c83
			path_p = ".";
rpm-build 0a0c83
	}
rpm-build 0a0c83
rpm-build 0a0c83
	if (opt_tabular)  {
rpm-build 0a0c83
		if (do_show(stdout, path_p, st, acl, default_acl) != 0)
rpm-build 0a0c83
			goto fail;
rpm-build 0a0c83
	} else {
rpm-build 0a0c83
		if (opt_comments) {
rpm-build 0a0c83
			printf("# file: %s\n", xquote(path_p, "\n\r"));
rpm-build 0a0c83
			printf("# owner: %s\n",
rpm-build 0a0c83
			       xquote(user_name(st->st_uid, opt_numeric), " \t\n\r"));
rpm-build 0a0c83
			printf("# group: %s\n",
rpm-build 0a0c83
			       xquote(group_name(st->st_gid, opt_numeric), " \t\n\r"));
rpm-build 0a0c83
			if ((st->st_mode & (S_ISVTX | S_ISUID | S_ISGID)) && !posixly_correct)
rpm-build 0a0c83
				printf("# flags: %s\n", flagstr(st->st_mode));
rpm-build 0a0c83
		}
rpm-build 0a0c83
		if (acl != NULL) {
rpm-build 0a0c83
			char *acl_text = acl_to_any_text(acl, NULL, '\n',
rpm-build 0a0c83
							 print_options);
rpm-build 0a0c83
			if (!acl_text)
rpm-build 0a0c83
				goto fail;
rpm-build 0a0c83
			if (puts(acl_text) < 0) {
rpm-build 0a0c83
				acl_free(acl_text);
rpm-build 0a0c83
				goto fail;
rpm-build 0a0c83
			}
rpm-build 0a0c83
			acl_free(acl_text);
rpm-build 0a0c83
		}
rpm-build 0a0c83
		if (default_acl != NULL) {
rpm-build 0a0c83
			char *acl_text = acl_to_any_text(default_acl, 
rpm-build 0a0c83
							 default_prefix, '\n',
rpm-build 0a0c83
							 print_options);
rpm-build 0a0c83
			if (!acl_text)
rpm-build 0a0c83
				goto fail;
rpm-build 0a0c83
			if (puts(acl_text) < 0) {
rpm-build 0a0c83
				acl_free(acl_text);
rpm-build 0a0c83
				goto fail;
rpm-build 0a0c83
			}
rpm-build 0a0c83
			acl_free(acl_text);
rpm-build 0a0c83
		}
rpm-build 0a0c83
	}
rpm-build 0a0c83
	if (acl || default_acl || opt_comments)
rpm-build 0a0c83
		printf("\n");
rpm-build 0a0c83
rpm-build 0a0c83
cleanup:
rpm-build 0a0c83
	if (acl)
rpm-build 0a0c83
		acl_free(acl);
rpm-build 0a0c83
	if (default_acl)
rpm-build 0a0c83
		acl_free(default_acl);
rpm-build 0a0c83
	return error;
rpm-build 0a0c83
rpm-build 0a0c83
fail:
rpm-build 0a0c83
	fprintf(stderr, "%s: %s: %s\n", progname, xquote(path_p, "\n\r"),
rpm-build 0a0c83
		strerror(errno));
rpm-build 0a0c83
	error = -1;
rpm-build 0a0c83
	goto cleanup;
rpm-build 0a0c83
}
rpm-build 0a0c83
rpm-build 0a0c83
rpm-build 0a0c83
void help(void)
rpm-build 0a0c83
{
rpm-build 0a0c83
	printf(_("%s %s -- get file access control lists\n"),
rpm-build 0a0c83
	       progname, VERSION);
rpm-build 0a0c83
	printf(_("Usage: %s [-%s] file ...\n"),
rpm-build 0a0c83
	         progname, cmd_line_options);
rpm-build 0a0c83
#if !POSIXLY_CORRECT
rpm-build 0a0c83
	if (posixly_correct) {
rpm-build 0a0c83
#endif
rpm-build 0a0c83
		printf(_(
rpm-build 0a0c83
"  -d, --default           display the default access control list\n"));
rpm-build 0a0c83
#if !POSIXLY_CORRECT
rpm-build 0a0c83
	} else {
rpm-build 0a0c83
		printf(_(
rpm-build 0a0c83
"  -a,  --access           display the file access control list only\n"
rpm-build 0a0c83
"  -d, --default           display the default access control list only\n"
rpm-build 0a0c83
"  -c, --omit-header       do not display the comment header\n"
rpm-build 0a0c83
"  -e, --all-effective     print all effective rights\n"
rpm-build 0a0c83
"  -E, --no-effective      print no effective rights\n"
rpm-build 0a0c83
"  -s, --skip-base         skip files that only have the base entries\n"
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
"  -t, --tabular           use tabular output format\n"
rpm-build 0a0c83
"  -n, --numeric           print numeric user/group identifiers\n"
rpm-build 0a0c83
"  -p, --absolute-names    don't strip leading '/' in pathnames\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
int main(int argc, char *argv[])
rpm-build 0a0c83
{
rpm-build 0a0c83
	int opt;
rpm-build 0a0c83
	char *line;
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
#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
	else
rpm-build 0a0c83
		cmd_line_options = POSIXLY_CMD_LINE_OPTIONS;
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
	/* Align `#effective:' comments to column 40 for tty's */
rpm-build 0a0c83
	if (!posixly_correct && isatty(fileno(stdout)))
rpm-build 0a0c83
		print_options |= TEXT_SMART_INDENT;
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
		switch (opt) {
rpm-build 0a0c83
			case 'a':  /* acl only */
rpm-build 0a0c83
				if (posixly_correct)
rpm-build 0a0c83
					goto synopsis;
rpm-build 0a0c83
				opt_print_acl = 1;
rpm-build 0a0c83
				break;
rpm-build 0a0c83
rpm-build 0a0c83
			case 'd':  /* default acl only */
rpm-build 0a0c83
				opt_print_default_acl = 1;
rpm-build 0a0c83
				break;
rpm-build 0a0c83
rpm-build 0a0c83
			case 'c':  /* no comments */
rpm-build 0a0c83
				if (posixly_correct)
rpm-build 0a0c83
					goto synopsis;
rpm-build 0a0c83
				opt_comments = 0;
rpm-build 0a0c83
				break;
rpm-build 0a0c83
rpm-build 0a0c83
			case 'e':  /* all #effective comments */
rpm-build 0a0c83
				if (posixly_correct)
rpm-build 0a0c83
					goto synopsis;
rpm-build 0a0c83
				print_options |= TEXT_ALL_EFFECTIVE;
rpm-build 0a0c83
				break;
rpm-build 0a0c83
rpm-build 0a0c83
			case 'E':  /* no #effective comments */
rpm-build 0a0c83
				if (posixly_correct)
rpm-build 0a0c83
					goto synopsis;
rpm-build 0a0c83
				print_options &= ~(TEXT_SOME_EFFECTIVE |
rpm-build 0a0c83
				                   TEXT_ALL_EFFECTIVE);
rpm-build 0a0c83
				break;
rpm-build 0a0c83
rpm-build 0a0c83
			case 'R':  /* recursive */
rpm-build 0a0c83
				if (posixly_correct)
rpm-build 0a0c83
					goto synopsis;
rpm-build 0a0c83
				walk_flags |= WALK_TREE_RECURSIVE;
rpm-build 0a0c83
				break;
rpm-build 0a0c83
rpm-build 0a0c83
			case 'L':  /* follow all symlinks */
rpm-build 0a0c83
				if (posixly_correct)
rpm-build 0a0c83
					goto synopsis;
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':  /* skip all symlinks */
rpm-build 0a0c83
				if (posixly_correct)
rpm-build 0a0c83
					goto synopsis;
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 's':  /* skip files with only base entries */
rpm-build 0a0c83
				if (posixly_correct)
rpm-build 0a0c83
					goto synopsis;
rpm-build 0a0c83
				opt_skip_base = 1;
rpm-build 0a0c83
				break;
rpm-build 0a0c83
rpm-build 0a0c83
			case 'p':
rpm-build 0a0c83
				if (posixly_correct)
rpm-build 0a0c83
					goto synopsis;
rpm-build 0a0c83
				opt_strip_leading_slash = 0;
rpm-build 0a0c83
				break;
rpm-build 0a0c83
rpm-build 0a0c83
			case 't':
rpm-build 0a0c83
				if (posixly_correct)
rpm-build 0a0c83
					goto synopsis;
rpm-build 0a0c83
				opt_tabular = 1;
rpm-build 0a0c83
				break;
rpm-build 0a0c83
rpm-build 0a0c83
			case 'n':  /* numeric */
rpm-build 0a0c83
				opt_numeric = 1;
rpm-build 0a0c83
				print_options |= TEXT_NUMERIC_IDS;
rpm-build 0a0c83
				break;
rpm-build 0a0c83
rpm-build 0a0c83
			case 'v':  /* print version */
rpm-build 0a0c83
				printf("%s " VERSION "\n", progname);
rpm-build 0a0c83
				return 0;
rpm-build 0a0c83
rpm-build 0a0c83
			case 'h':  /* help */
rpm-build 0a0c83
				help();
rpm-build 0a0c83
				return 0;
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
	}
rpm-build 0a0c83
rpm-build 0a0c83
	if (!(opt_print_acl || opt_print_default_acl)) {
rpm-build 0a0c83
		opt_print_acl = 1;
rpm-build 0a0c83
		if (!posixly_correct)
rpm-build 0a0c83
			opt_print_default_acl = 1;
rpm-build 0a0c83
	}
rpm-build 0a0c83
		
rpm-build 0a0c83
	if ((optind == argc) && !posixly_correct)
rpm-build 0a0c83
		goto synopsis;
rpm-build 0a0c83
rpm-build 0a0c83
	do {
rpm-build 0a0c83
		if (optind == argc ||
rpm-build 0a0c83
		    strcmp(argv[optind], "-") == 0) {
rpm-build 0a0c83
			while ((line = __acl_next_line(stdin)) != NULL) {
rpm-build 0a0c83
				if (*line == '\0')
rpm-build 0a0c83
					continue;
rpm-build 0a0c83
rpm-build 0a0c83
				had_errors += walk_tree(line, walk_flags, 0,
rpm-build 0a0c83
							do_print, NULL);
rpm-build 0a0c83
			}
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
				had_errors++;
rpm-build 0a0c83
			}
rpm-build 0a0c83
		} else
rpm-build 0a0c83
			had_errors += walk_tree(argv[optind], walk_flags, 0,
rpm-build 0a0c83
						do_print, NULL);
rpm-build 0a0c83
		optind++;
rpm-build 0a0c83
	} while (optind < argc);
rpm-build 0a0c83
rpm-build 0a0c83
	return had_errors ? 1 : 0;
rpm-build 0a0c83
rpm-build 0a0c83
synopsis:
rpm-build 0a0c83
	fprintf(stderr, _("Usage: %s [-%s] file ...\n"),
rpm-build 0a0c83
	        progname, cmd_line_options);
rpm-build 0a0c83
	fprintf(stderr, _("Try `%s --help' for more information.\n"),
rpm-build 0a0c83
		progname);
rpm-build 0a0c83
	return 2;
rpm-build 0a0c83
}
rpm-build 0a0c83