Author: trasz
Date: Mon Aug 31 20:53:01 2009
New Revision: 196712
URL: http://svn.freebsd.org/changeset/base/196712

Log:
  Add NFSv4 ACL support to ls(1).

Modified:
  head/bin/ls/print.c

Modified: head/bin/ls/print.c
==============================================================================
--- head/bin/ls/print.c Mon Aug 31 20:42:07 2009        (r196711)
+++ head/bin/ls/print.c Mon Aug 31 20:53:01 2009        (r196712)
@@ -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);
 }
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to