/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#ifndef lint
static char sccsid[] = "%Z%%M% %I% %E% SMI";
#endif
/*
* getfacl [-ad] file ...
* This command displays discretionary information for a file or files.
* display format:
* # file: filename
* # owner: uid
* # group: gid
* user::perm
* user:uid:perm
* group::perm
* group:gid:perm
* mask:perm
* other:perm
* default:user::perm
* default:user:uid:perm
* default:group::perm
* default:group:gid:perm
* default:mask:perm
* default:other:perm
*/
#include <stdlib.h>
#include <stdio.h>
#include <pwd.h>
#include <grp.h>
#include <locale.h>
#include <sys/acl.h>
#include <errno.h>
static char *pruname(uid_t);
static char *prgname(gid_t);
static char *display(int);
static void usage();
int
main(int argc, char *argv[])
{
int c;
int aflag = 0;
int dflag = 0;
int errflag = 0;
int savecnt;
int aclcnt;
int mask;
aclent_t *aclp;
aclent_t *tp;
char *permp;
(void) setlocale(LC_ALL, "");
(void) textdomain(TEXT_DOMAIN);
if (argc < 2)
usage();
while ((c = getopt(argc, argv, "ad")) != EOF) {
switch (c) {
case 'a':
aflag++;
break;
case 'd':
dflag++;
break;
case '?':
errflag++;
break;
}
}
if (errflag)
usage();
if (optind >= argc)
usage();
for (; optind < argc; optind++) {
register char *filep;
filep = argv[optind];
/* Get ACL info of the files */
errno = 0;
if ((aclcnt = acl(filep, GETACLCNT, 0, NULL)) < 0) {
if (errno == ENOSYS) {
(void) fprintf(stderr,
gettext("File system doesn't support "
"aclent_t style ACL's.\n"
"See acl(5) for more information on "
"Solaris ACL support.\n"));
exit(2);
}
perror(filep);
exit(2);
}
if (aclcnt < MIN_ACL_ENTRIES) {
(void) fprintf(stderr,
gettext("%d: acl count too small from %s\n"),
aclcnt, filep);
exit(2);
}
if ((aclp = (aclent_t *)malloc(sizeof (aclent_t) * aclcnt))
== NULL) {
(void) fprintf(stderr,
gettext("Insufficient memory\n"));
exit(1);
}
errno = 0;
if (acl(filep, GETACL, aclcnt, aclp) < 0) {
perror(filep);
exit(2);
}
/* display ACL: assume it is sorted. */
(void) printf("\n# file: %s\n", filep);
savecnt = aclcnt;
for (tp = aclp; aclcnt--; tp++) {
if (tp->a_type == USER_OBJ)
(void) printf("# owner: %s\n",
pruname(tp->a_id));
if (tp->a_type == GROUP_OBJ)
(void) printf("# group: %s\n",
prgname(tp->a_id));
if (tp->a_type == CLASS_OBJ)
mask = tp->a_perm;
}
aclcnt = savecnt;
for (tp = aclp; aclcnt--; tp++) {
switch (tp->a_type) {
case USER:
if (!dflag) {
permp = display(tp->a_perm);
(void) printf("user:%s:%s\t\t",
pruname(tp->a_id), permp);
free(permp);
permp = display(tp->a_perm & mask);
(void) printf(
"#effective:%s\n", permp);
free(permp);
}
break;
case USER_OBJ:
if (!dflag) {
/* no need to display uid */
permp = display(tp->a_perm);
(void) printf("user::%s\n", permp);
free(permp);
}
break;
case GROUP:
if (!dflag) {
permp = display(tp->a_perm);
(void) printf("group:%s:%s\t\t",
prgname(tp->a_id), permp);
free(permp);
permp = display(tp->a_perm & mask);
(void) printf(
"#effective:%s\n", permp);
free(permp);
}
break;
case GROUP_OBJ:
if (!dflag) {
permp = display(tp->a_perm);
(void) printf("group::%s\t\t", permp);
free(permp);
permp = display(tp->a_perm & mask);
(void) printf(
"#effective:%s\n", permp);
free(permp);
}
break;
case CLASS_OBJ:
if (!dflag) {
permp = display(tp->a_perm);
(void) printf("mask:%s\n", permp);
free(permp);
}
break;
case OTHER_OBJ:
if (!dflag) {
permp = display(tp->a_perm);
(void) printf("other:%s\n", permp);
free(permp);
}
break;
case DEF_USER:
if (!aflag) {
permp = display(tp->a_perm);
(void) printf("default:user:%s:%s\n",
pruname(tp->a_id), permp);
free(permp);
}
break;
case DEF_USER_OBJ:
if (!aflag) {
permp = display(tp->a_perm);
(void) printf("default:user::%s\n",
permp);
free(permp);
}
break;
case DEF_GROUP:
if (!aflag) {
permp = display(tp->a_perm);
(void) printf("default:group:%s:%s\n",
prgname(tp->a_id), permp);
free(permp);
}
break;
case DEF_GROUP_OBJ:
if (!aflag) {
permp = display(tp->a_perm);
(void) printf("default:group::%s\n",
permp);
free(permp);
}
break;
case DEF_CLASS_OBJ:
if (!aflag) {
permp = display(tp->a_perm);
(void) printf("default:mask:%s\n",
permp);
free(permp);
}
break;
case DEF_OTHER_OBJ:
if (!aflag) {
permp = display(tp->a_perm);
(void) printf("default:other:%s\n",
permp);
free(permp);
}
break;
default:
(void) fprintf(stderr,
gettext("unrecognized entry\n"));
break;
}
}
free(aclp);
}
return (0);
}
static char *
display(int perm)
{
char *buf;
buf = malloc(4);
if (buf == NULL) {
(void) fprintf(stderr, gettext("Insufficient memory\n"));
exit(1);
}
if (perm & 4)
buf[0] = 'r';
else
buf[0] = '-';
if (perm & 2)
buf[1] = 'w';
else
buf[1] = '-';
if (perm & 1)
buf[2] = 'x';
else
buf[2] = '-';
buf[3] = '\0';
return (buf);
}
static char *
pruname(uid_t uid)
{
struct passwd *passwdp;
static char uidp[10]; /* big enough */
passwdp = getpwuid(uid);
if (passwdp == (struct passwd *)NULL) {
/* could not get passwd information: display uid instead */
(void) sprintf(uidp, "%u", uid);
return (uidp);
} else
return (passwdp->pw_name);
}
static char *
prgname(gid_t gid)
{
struct group *groupp;
static char gidp[10]; /* big enough */
groupp = getgrgid(gid);
if (groupp == (struct group *)NULL) {
/* could not get group information: display gid instead */
(void) sprintf(gidp, "%u", gid);
return (gidp);
} else
return (groupp->gr_name);
}
static void
usage()
{
(void) fprintf(stderr,
gettext("usage: getfacl [-ad] file ... \n"));
exit(1);
}