From dd9aaeb0f7d41b68213fba48f22ec64104601b09 Mon Sep 17 00:00:00 2001 From: "Tim J. Robbins" Date: Sun, 3 Nov 2002 07:29:08 +0000 Subject: [PATCH] Print a `+' character after the standard UNIX permission fields in long listings if the file has an extended ACL (more than the required 3 entries). This is what Solaris and IRIX do, and what the withdrawn POSIX.2c standard required. Reviewed by: rwatson (an earlier version of the patch) --- bin/ls/ls.1 | 22 +++++++++++++++++++-- bin/ls/print.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 2 deletions(-) diff --git a/bin/ls/ls.1 b/bin/ls/ls.1 index 45f677988bc7..cd1023f66395 100644 --- a/bin/ls/ls.1 +++ b/bin/ls/ls.1 @@ -417,6 +417,20 @@ or .Xr sticky 8 . ) .El .El +.Pp +The next field contains a +plus +.Pq Sq Li + +character if the file has an ACL, or a +space +.Pq Sq Li " " +if it does not. +The +.Nm +utility does not show the actual ACL; +use +.Xr getfacl 1 +to do this. .Sh EXAMPLES The following is how to do an .Nm @@ -618,21 +632,25 @@ The group field is now automatically included in the long listing for files in order to be compatible with the .St -p1003.2 specification. -KLD -.El .Sh SEE ALSO .Xr chflags 1 , .Xr chmod 1 , +.Xr getfacl 1 , .Xr sort 1 , .Xr xterm 1 , .Xr termcap 5 , .Xr symlink 7 , +.Xr getfmac 8 , .Xr sticky 8 .Sh STANDARDS The .Nm utility conforms to .St -p1003.1-2001 . +.Pp +.No The ACL support is compatible with IEEE\ Std\ 1003.2c\ ( Ns Dq "POSIX.2c" Ns ) +Draft\ 17 +(withdrawn). .Sh HISTORY An .Nm diff --git a/bin/ls/print.c b/bin/ls/print.c index 99aa732b1778..c09e1d6ad289 100644 --- a/bin/ls/print.c +++ b/bin/ls/print.c @@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include @@ -73,6 +74,7 @@ static void printsize(size_t, off_t); static void endcolor(int); static int colortype(mode_t); #endif +static void aclmode(char *, FTSENT *, int *); #define IS_NOPRINT(p) ((p)->fts_number == NO_PRINT) @@ -162,10 +164,14 @@ printlong(DISPLAY *dp) #ifdef COLORLS int color_printed = 0; #endif + int haveacls; + dev_t prevdev; if (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; @@ -176,6 +182,14 @@ printlong(DISPLAY *dp) (void)printf("%*lld ", 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; + } 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, @@ -644,3 +658,42 @@ unit_adjust(double *val) return (unit); } + +static void +aclmode(char *buf, FTSENT *p, int *haveacls) +{ + char name[MAXPATHLEN + 1]; + int entries, ret; + 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); + if ((ret = pathconf(name, _PC_ACL_EXTENDED)) <= 0) { + if (ret < 0 && errno != EINVAL) + warn("%s", name); + else + *haveacls = 0; + return; + } + *haveacls = 1; + if ((facl = acl_get_file(name, ACL_TYPE_ACCESS)) != NULL) { + if (acl_get_entry(facl, ACL_FIRST_ENTRY, &ae) == 1) { + entries = 0; + do + entries++; + while (acl_get_entry(facl, ACL_NEXT_ENTRY, &ae) == 1); + if (entries != 3) + buf[10] = '+'; + } + acl_free(facl); + } else + warn("%s", name); +}