summaryrefslogtreecommitdiffstats
path: root/bin/ls
diff options
context:
space:
mode:
authortrasz <trasz@FreeBSD.org>2009-08-31 20:53:01 +0000
committertrasz <trasz@FreeBSD.org>2009-08-31 20:53:01 +0000
commitb7c21fe6efd5d26f96542e9e7975331d318d08d7 (patch)
treea5831a566612fbae9a816111b5a92e7e79fd3c3a /bin/ls
parent0f8cdc57c03ba9bb42e588c68e6e8115775b620b (diff)
downloadFreeBSD-src-b7c21fe6efd5d26f96542e9e7975331d318d08d7.zip
FreeBSD-src-b7c21fe6efd5d26f96542e9e7975331d318d08d7.tar.gz
Add NFSv4 ACL support to ls(1).
Diffstat (limited to 'bin/ls')
-rw-r--r--bin/ls/print.c106
1 files changed, 54 insertions, 52 deletions
diff --git a/bin/ls/print.c b/bin/ls/print.c
index 4825d2e..2eb636e 100644
--- a/bin/ls/print.c
+++ b/bin/ls/print.c
@@ -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.
- */
- 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.
+ * XXX: ACLs are not supported on whiteouts and device files
+ * residing on UFS.
*/
- 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);
}
OpenPOWER on IntegriCloud