Add NFSv4 ACL support to ls(1).

This commit is contained in:
Edward Tomasz Napierala 2009-08-31 20:53:01 +00:00
parent c5cb1e51b4
commit f7b8687a93
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=196712

View File

@ -70,7 +70,7 @@ static void printsize(size_t, off_t);
static void endcolor(int);
static int colortype(mode_t);
#endif
static void aclmode(char *, const FTSENT *, int *);
static void aclmode(char *, const FTSENT *);
#define IS_NOPRINT(p) ((p)->fts_number == NO_PRINT)
@ -139,16 +139,12 @@ printlong(const DISPLAY *dp)
#ifdef COLORLS
int color_printed = 0;
#endif
int haveacls;
dev_t prevdev;
if ((dp->list == NULL || dp->list->fts_level != FTS_ROOTLEVEL) &&
(f_longform || f_size)) {
(void)printf("total %lu\n", howmany(dp->btotal, blocksize));
}
haveacls = 1;
prevdev = (dev_t)-1;
for (p = dp->list; p; p = p->fts_link) {
if (IS_NOPRINT(p))
continue;
@ -159,14 +155,7 @@ printlong(const DISPLAY *dp)
(void)printf("%*jd ",
dp->s_block, howmany(sp->st_blocks, blocksize));
strmode(sp->st_mode, buf);
/*
* Cache whether or not the filesystem supports ACL's to
* avoid expensive syscalls. Try again when we change devices.
*/
if (haveacls || sp->st_dev != prevdev) {
aclmode(buf, p, &haveacls);
prevdev = sp->st_dev;
}
aclmode(buf, p);
np = p->fts_pointer;
(void)printf("%s %*u %-*s %-*s ", buf, dp->s_nlink,
sp->st_nlink, dp->s_user, np->user, dp->s_group,
@ -612,56 +601,69 @@ printsize(size_t width, off_t bytes)
(void)printf("%*jd ", (u_int)width, bytes);
}
/*
* Add a + after the standard rwxrwxrwx mode if the file has an
* ACL. strmode() reserves space at the end of the string.
*/
static void
aclmode(char *buf, const FTSENT *p, int *haveacls)
aclmode(char *buf, const FTSENT *p)
{
char name[MAXPATHLEN + 1];
int entries, ret;
int ret, trivial;
static dev_t previous_dev = NODEV;
static int supports_acls = -1;
static int type = ACL_TYPE_ACCESS;
acl_t facl;
acl_entry_t ae;
/*
* Add a + after the standard rwxrwxrwx mode if the file has an
* extended ACL. strmode() reserves space at the end of the string.
* XXX: ACLs are not supported on whiteouts and device files
* residing on UFS.
*/
if (p->fts_level == FTS_ROOTLEVEL)
snprintf(name, sizeof(name), "%s", p->fts_name);
else
snprintf(name, sizeof(name), "%s/%s",
p->fts_parent->fts_accpath, p->fts_name);
/*
* We have no way to tell whether a symbolic link has an ACL since
* pathconf() and acl_get_file() both follow them. They also don't
* support whiteouts.
*/
if (S_ISLNK(p->fts_statp->st_mode) || S_ISWHT(p->fts_statp->st_mode)) {
*haveacls = 1;
if (S_ISCHR(p->fts_statp->st_mode) || S_ISBLK(p->fts_statp->st_mode) ||
S_ISWHT(p->fts_statp->st_mode))
return;
}
if ((ret = pathconf(name, _PC_ACL_EXTENDED)) <= 0) {
if (ret < 0 && errno != EINVAL)
warn("%s", name);
if (previous_dev != p->fts_statp->st_dev) {
previous_dev = p->fts_statp->st_dev;
supports_acls = 0;
if (p->fts_level == FTS_ROOTLEVEL)
snprintf(name, sizeof(name), "%s", p->fts_name);
else
*haveacls = 0;
snprintf(name, sizeof(name), "%s/%s",
p->fts_parent->fts_accpath, p->fts_name);
ret = lpathconf(name, _PC_ACL_NFS4);
if (ret > 0) {
type = ACL_TYPE_NFS4;
supports_acls = 1;
} else if (ret < 0 && errno != EINVAL) {
warn("%s", name);
return;
}
if (supports_acls == 0) {
ret = lpathconf(name, _PC_ACL_EXTENDED);
if (ret > 0) {
type = ACL_TYPE_ACCESS;
supports_acls = 1;
} else if (ret < 0 && errno != EINVAL) {
warn("%s", name);
return;
}
}
}
if (supports_acls == 0)
return;
facl = acl_get_link_np(name, type);
if (facl == NULL) {
warn("%s", name);
return;
}
*haveacls = 1;
if ((facl = acl_get_file(name, ACL_TYPE_ACCESS)) != NULL) {
if (acl_get_entry(facl, ACL_FIRST_ENTRY, &ae) == 1) {
entries = 1;
while (acl_get_entry(facl, ACL_NEXT_ENTRY, &ae) == 1)
if (++entries > 3)
break;
/*
* POSIX.1e requires that ACLs of type ACL_TYPE_ACCESS
* must have at least three entries (owner, group,
* and other). So anything with more than 3 ACLs looks
* interesting to us.
*/
if (entries > 3)
buf[10] = '+';
}
if (acl_is_trivial_np(facl, &trivial)) {
acl_free(facl);
} else
warn("%s", name);
return;
}
if (!trivial)
buf[10] = '+';
acl_free(facl);
}