]> git.saurik.com Git - apple/file_cmds.git/blobdiff - ls/print.c
file_cmds-272.201.1.tar.gz
[apple/file_cmds.git] / ls / print.c
index 4962a95dea06f89f3b50f9729983d12f022a881b..de04bf300661fa22f064666e4514377aa5847b74 100644 (file)
@@ -44,12 +44,24 @@ __RCSID("$FreeBSD: src/bin/ls/print.c,v 1.57 2002/08/29 14:29:09 keramida Exp $"
 
 #include <sys/param.h>
 #include <sys/stat.h>
+#ifdef __APPLE__
+#include <sys/acl.h>
+#include <sys/xattr.h>
+#include <sys/types.h>
+#include <grp.h>
+#include <pwd.h>
+#include <TargetConditionals.h>
+#include <membership.h>
+#include <membershipPriv.h>
+#include <uuid/uuid.h>
+#endif
 
 #include <err.h>
 #include <errno.h>
 #include <fts.h>
 #include <math.h>
 #include <langinfo.h>
+#include <libutil.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -60,6 +72,13 @@ __RCSID("$FreeBSD: src/bin/ls/print.c,v 1.57 2002/08/29 14:29:09 keramida Exp $"
 #include <termcap.h>
 #include <signal.h>
 #endif
+#include <stdint.h>            /* intmax_t */
+#include <assert.h>
+#ifdef __APPLE__ 
+#include <get_compat.h>
+#else 
+#define COMPAT_MODE(a,b) (1)
+#endif /* __APPLE__ */
 
 #include "ls.h"
 #include "extern.h"
@@ -76,27 +95,6 @@ static int   colortype(mode_t);
 
 #define        IS_NOPRINT(p)   ((p)->fts_number == NO_PRINT)
 
-#define KILO_SZ(n) (n)
-#define MEGA_SZ(n) ((n) * (n))
-#define GIGA_SZ(n) ((n) * (n) * (n))
-#define TERA_SZ(n) ((n) * (n) * (n) * (n))
-#define PETA_SZ(n) ((n) * (n) * (n) * (n) * (n))
-
-#define KILO_2_SZ (KILO_SZ(1024ULL))
-#define MEGA_2_SZ (MEGA_SZ(1024ULL))
-#define GIGA_2_SZ (GIGA_SZ(1024ULL))
-#define TERA_2_SZ (TERA_SZ(1024ULL))
-#define PETA_2_SZ (PETA_SZ(1024ULL))
-
-static u_int64_t vals_base2[] = {1, KILO_2_SZ, MEGA_2_SZ, GIGA_2_SZ, TERA_2_SZ, PETA_2_SZ};
-
-typedef enum {
-       NONE, KILO, MEGA, GIGA, TERA, PETA, UNIT_MAX
-} unit_t;
-static unit_t unit_adjust(off_t *);
-
-static int unitp[] = {NONE, KILO, MEGA, GIGA, TERA, PETA};
-
 #ifdef COLORLS
 /* Most of these are taken from <sys/stat.h> */
 typedef enum Colors {
@@ -130,6 +128,12 @@ printscol(DISPLAY *dp)
 {
        FTSENT *p;
 
+       assert(dp);
+       if (COMPAT_MODE("bin/ls", "Unix2003") && (dp->list != NULL)) {
+               if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size))
+                       (void)printf("total %qu\n", (u_int64_t)howmany(dp->btotal, blocksize));
+       }
+
        for (p = dp->list; p; p = p->fts_link) {
                if (IS_NOPRINT(p))
                        continue;
@@ -149,7 +153,161 @@ printname(const char *name)
        else if (f_nonprint)
                return prn_printable(name);
        else
-               return printf("%s", name);
+               return prn_normal(name);
+}
+
+/*
+ * print access control list
+ */
+static struct {
+       acl_perm_t      perm;
+       char            *name;
+       int             flags;
+#define ACL_PERM_DIR   (1<<0)
+#define ACL_PERM_FILE  (1<<1)
+} acl_perms[] = {
+       {ACL_READ_DATA,         "read",         ACL_PERM_FILE},
+       {ACL_LIST_DIRECTORY,    "list",         ACL_PERM_DIR},
+       {ACL_WRITE_DATA,        "write",        ACL_PERM_FILE},
+       {ACL_ADD_FILE,          "add_file",     ACL_PERM_DIR},
+       {ACL_EXECUTE,           "execute",      ACL_PERM_FILE},
+       {ACL_SEARCH,            "search",       ACL_PERM_DIR},
+       {ACL_DELETE,            "delete",       ACL_PERM_FILE | ACL_PERM_DIR},
+       {ACL_APPEND_DATA,       "append",       ACL_PERM_FILE},
+       {ACL_ADD_SUBDIRECTORY,  "add_subdirectory", ACL_PERM_DIR},
+       {ACL_DELETE_CHILD,      "delete_child", ACL_PERM_DIR},
+       {ACL_READ_ATTRIBUTES,   "readattr",     ACL_PERM_FILE | ACL_PERM_DIR},
+       {ACL_WRITE_ATTRIBUTES,  "writeattr",    ACL_PERM_FILE | ACL_PERM_DIR},
+       {ACL_READ_EXTATTRIBUTES, "readextattr", ACL_PERM_FILE | ACL_PERM_DIR},
+       {ACL_WRITE_EXTATTRIBUTES, "writeextattr", ACL_PERM_FILE | ACL_PERM_DIR},
+       {ACL_READ_SECURITY,     "readsecurity", ACL_PERM_FILE | ACL_PERM_DIR},
+       {ACL_WRITE_SECURITY,    "writesecurity", ACL_PERM_FILE | ACL_PERM_DIR},
+       {ACL_CHANGE_OWNER,      "chown",        ACL_PERM_FILE | ACL_PERM_DIR},
+       {0, NULL, 0}
+};
+
+static struct {
+       acl_flag_t      flag;
+       char            *name;
+       int             flags;
+} acl_flags[] = {
+       {ACL_ENTRY_FILE_INHERIT,        "file_inherit",         ACL_PERM_DIR},
+       {ACL_ENTRY_DIRECTORY_INHERIT,   "directory_inherit",    ACL_PERM_DIR},
+       {ACL_ENTRY_LIMIT_INHERIT,       "limit_inherit",        ACL_PERM_FILE | ACL_PERM_DIR},
+       {ACL_ENTRY_ONLY_INHERIT,        "only_inherit",         ACL_PERM_DIR},
+       {0, NULL, 0}
+};
+
+static char *
+uuid_to_name(uuid_t *uu) 
+{
+       int type;
+       char *name = NULL;
+       char *recname = NULL;
+       
+#define MAXNAMETAG (MAXLOGNAME + 6) /* + strlen("group:") */
+       name = (char *) malloc(MAXNAMETAG);
+       
+       if (NULL == name) {
+               err(1, "malloc");
+       }
+       
+       if (f_numericonly) {
+               goto errout;
+       }
+       
+       if (mbr_identifier_translate(ID_TYPE_UUID, *uu, sizeof(*uu), ID_TYPE_NAME, (void **) &recname, &type)) {
+               goto errout;
+       }
+       
+       snprintf(name, MAXNAMETAG, "%s:%s", (type == MBR_REC_TYPE_USER ? "user" : "group"), recname);
+       free(recname);
+       
+       return name;
+errout:
+       uuid_unparse_upper(*uu, name);
+       
+       return name;
+}
+
+static void
+printxattr(DISPLAY *dp, int count, char *buf, int sizes[])
+{
+       for (int i = 0; i < count; i++) {
+               putchar('\t');
+               printname(buf);
+               putchar('\t');
+               printsize(dp->s_size, sizes[i]);
+               putchar('\n');
+               buf += strlen(buf) + 1;
+       }
+}
+
+static void
+printacl(acl_t acl, int isdir)
+{
+       acl_entry_t     entry = NULL;
+       int             index;
+       uuid_t          *applicable;
+       char            *name = NULL;
+       acl_tag_t       tag;
+       acl_flagset_t   flags;
+       acl_permset_t   perms;
+       char            *type;
+       int             i, first;
+       
+
+       for (index = 0;
+            acl_get_entry(acl, entry == NULL ? ACL_FIRST_ENTRY : ACL_NEXT_ENTRY, &entry) == 0;
+            index++) {
+               if (acl_get_tag_type(entry, &tag) != 0)
+                       continue;
+               if (acl_get_flagset_np(entry, &flags) != 0)
+                       continue;
+               if (acl_get_permset(entry, &perms) != 0)
+                       continue;
+               if ((applicable = (uuid_t *) acl_get_qualifier(entry)) == NULL)
+                       continue;
+               name = uuid_to_name(applicable);
+               acl_free(applicable);
+               switch(tag) {
+               case ACL_EXTENDED_ALLOW:
+                       type = "allow";
+                       break;
+               case ACL_EXTENDED_DENY:
+                       type = "deny";
+                       break;
+               default:
+                       type = "unknown";
+               }
+
+               (void)printf(" %d: %s%s %s ",
+                   index,
+                   name,
+                   acl_get_flag_np(flags, ACL_ENTRY_INHERITED) ? " inherited" : "",
+                   type);
+
+               if (name)
+                       free(name);
+
+               for (i = 0, first = 0; acl_perms[i].name != NULL; i++) {
+                       if (acl_get_perm_np(perms, acl_perms[i].perm) == 0)
+                               continue;
+                       if (!(acl_perms[i].flags & (isdir ? ACL_PERM_DIR : ACL_PERM_FILE)))
+                               continue;
+                       (void)printf("%s%s", first++ ? "," : "", acl_perms[i].name);
+               }
+               for (i = 0; acl_flags[i].name != NULL; i++) {
+                       if (acl_get_flag_np(flags, acl_flags[i].flag) == 0)
+                               continue;
+                       if (!(acl_flags[i].flags & (isdir ? ACL_PERM_DIR : ACL_PERM_FILE)))
+                               continue;
+                       (void)printf("%s%s", first++ ? "," : "", acl_flags[i].name);
+               }
+                       
+               (void)putchar('\n');
+       }
+
 }
 
 void
@@ -170,22 +328,61 @@ printlong(DISPLAY *dp)
                if (IS_NOPRINT(p))
                        continue;
                sp = p->fts_statp;
-               if (f_inode)
+               if (f_inode) 
+#if _DARWIN_FEATURE_64_BIT_INODE
+                       (void)printf("%*llu ", dp->s_inode, (u_quad_t)sp->st_ino);
+#else
                        (void)printf("%*lu ", dp->s_inode, (u_long)sp->st_ino);
+#endif
                if (f_size)
                        (void)printf("%*qu ",
                            dp->s_block, (u_int64_t)howmany(sp->st_blocks, blocksize));
                strmode(sp->st_mode, buf);
                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,
-                   np->group);
+#ifdef __APPLE__
+               buf[10] = '\0'; /* make +/@ abut the mode */
+               char str[2] = { np->mode_suffix, '\0' };
+#endif /* __APPLE__ */
+               if (f_group && f_owner) {       /* means print neither */
+#ifdef __APPLE__
+                       (void)printf("%s%s %*u   ", buf, str, dp->s_nlink,
+                                    sp->st_nlink);
+#else  /* ! __APPLE__ */
+                       (void)printf("%s %*u   ", buf, dp->s_nlink,
+                                    sp->st_nlink);
+#endif /* __APPLE__ */
+               }
+               else if (f_group) {
+#ifdef __APPLE__
+                       (void)printf("%s%s %*u %-*s  ", buf, str, dp->s_nlink,
+                                    sp->st_nlink, dp->s_group, np->group);
+#else  /* ! __APPLE__ */
+                       (void)printf("%s %*u %-*s  ", buf, dp->s_nlink,
+                                    sp->st_nlink, dp->s_group, np->group);
+#endif /* __APPLE__ */
+               }
+               else if (f_owner) {
+#ifdef __APPLE__
+                       (void)printf("%s%s %*u %-*s  ", buf, str, dp->s_nlink,
+                                    sp->st_nlink, dp->s_user, np->user);
+#else  /* ! __APPLE__ */
+                       (void)printf("%s %*u %-*s  ", buf, dp->s_nlink,
+                                    sp->st_nlink, dp->s_user, np->user);
+#endif /* __APPLE__ */
+               }
+               else {
+#ifdef __APPLE__
+                       (void)printf("%s%s %*u %-*s  %-*s  ", buf, str, dp->s_nlink,
+                                    sp->st_nlink, dp->s_user, np->user, dp->s_group,
+                                    np->group);
+#else  /* ! __APPLE__ */
+                       (void)printf("%s %*u %-*s  %-*s  ", buf, dp->s_nlink,
+                                    sp->st_nlink, dp->s_user, np->user, dp->s_group,
+                                    np->group);
+#endif /* ! __APPLE__ */
+               }
                if (f_flags)
                        (void)printf("%-*s ", dp->s_flags, np->flags);
-#ifndef __APPLE__
-               if (f_lomac)
-                       (void)printf("%-*s ", dp->s_lattr, np->lattr);
-#endif /* __APPLE__ */
                if (S_ISCHR(sp->st_mode) || S_ISBLK(sp->st_mode))
                        if (minor(sp->st_rdev) > 255 || minor(sp->st_rdev) < 0)
                                (void)printf("%3d, 0x%08x ",
@@ -203,6 +400,8 @@ printlong(DISPLAY *dp)
                        printtime(sp->st_atime);
                else if (f_statustime)
                        printtime(sp->st_ctime);
+               else if (f_birthtime) 
+                       printtime(sp->st_birthtime);
                else
                        printtime(sp->st_mtime);
 #ifdef COLORLS
@@ -219,6 +418,14 @@ printlong(DISPLAY *dp)
                if (S_ISLNK(sp->st_mode))
                        printlink(p);
                (void)putchar('\n');
+#ifdef __APPLE__
+               if (np->xattr_count && f_xattr) {
+                       printxattr(dp, np->xattr_count, np->xattr_names, np->xattr_sizes);
+               }
+                if (np->acl != NULL && f_acl) {
+                       printacl(np->acl, S_ISDIR(sp->st_mode));
+               }
+#endif /* __APPLE__ */
        }
 }
 
@@ -275,14 +482,15 @@ printcol(DISPLAY *dp)
         * Have to do random access in the linked list -- build a table
         * of pointers.
         */
-       if (dp->entries > lastentries) {
+       if ((lastentries == -1) || (dp->entries > lastentries)) {
                lastentries = dp->entries;
-               if ((array =
-                   realloc(array, dp->entries * sizeof(FTSENT *))) == NULL) {
+               if ((array = realloc(array, dp->entries * sizeof(FTSENT *))) == NULL) {
                        warn(NULL);
                        printscol(dp);
+                       return;
                }
        }
+       memset(array, 0, dp->entries * sizeof(FTSENT *));
        for (p = dp->list, num = 0; p; p = p->fts_link)
                if (p->fts_number != NO_PRINT)
                        array[num++] = p;
@@ -305,6 +513,7 @@ printcol(DISPLAY *dp)
        if (num % numcols)
                ++numrows;
 
+       assert(dp->list);
        if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size))
                (void)printf("total %qu\n", (u_int64_t)howmany(dp->btotal, blocksize));
 
@@ -314,8 +523,8 @@ printcol(DISPLAY *dp)
                if (!f_sortacross)
                        base = row;
                for (col = 0, chcnt = 0; col < numcols; ++col) {
-                       chcnt += printaname(array[base], dp->s_inode,
-                           dp->s_block);
+                       assert(base < dp->entries);
+                       chcnt += printaname(array[base], dp->s_inode, dp->s_block);
                        if (f_sortacross)
                                base++;
                        else
@@ -351,7 +560,11 @@ printaname(FTSENT *p, u_long inodefield, u_long sizefield)
        sp = p->fts_statp;
        chcnt = 0;
        if (f_inode)
+#if _DARWIN_FEATURE_64_BIT_INODE
+               chcnt += printf("%*llu ", (int)inodefield, (u_quad_t)sp->st_ino);
+#else
                chcnt += printf("%*lu ", (int)inodefield, (u_long)sp->st_ino);
+#endif
        if (f_size)
                chcnt += printf("%*qu ",
                    (int)sizefield, (u_int64_t)howmany(sp->st_blocks, blocksize));
@@ -386,6 +599,14 @@ printtime(time_t ftime)
        if (f_sectime)
                /* mmm dd hh:mm:ss yyyy || dd mmm hh:mm:ss yyyy */
                format = d_first ? "%e %b %T %Y " : "%b %e %T %Y ";
+       else if (COMPAT_MODE("bin/ls", "Unix2003")) {
+               if (ftime + SIXMONTHS > now && ftime <= now)
+                       /* mmm dd hh:mm || dd mmm hh:mm */
+                       format = d_first ? "%e %b %R " : "%b %e %R ";
+               else
+                       /* mmm dd  yyyy || dd mmm  yyyy */
+                       format = d_first ? "%e %b  %Y " : "%b %e  %Y ";
+       }
        else if (ftime + SIXMONTHS > now && ftime < now + SIXMONTHS)
                /* mmm dd hh:mm || dd mmm hh:mm */
                format = d_first ? "%e %b %R " : "%b %e %R ";
@@ -604,43 +825,13 @@ printlink(FTSENT *p)
 static void
 printsize(size_t width, off_t bytes)
 {
-       unit_t unit;
-
-       if (f_humanval) {
-               unit = unit_adjust(&bytes);
-
-               if (bytes == 0)
-                       (void)printf("%*s ", width, "0B");
-               else
-                       (void)printf("%*lld%c ", width - 1, bytes,
-                           "BKMGTPE"[unit]);
-       } else
-               (void)printf("%*lld ", width, bytes);
-}
 
-/*
- * Output in "human-readable" format.  Uses 3 digits max and puts
- * unit suffixes at the end.  Makes output compact and easy to read,
- * especially on huge disks.
- *
- */
-unit_t
-unit_adjust(off_t *val)
-{
-       double abval;
-       unit_t unit;
-       unsigned int unit_sz;
-
-       abval = fabs((double)*val);
-
-       unit_sz = abval ? ilogb(abval) / 10 : 0;
-
-       if (unit_sz >= UNIT_MAX) {
-               unit = NONE;
-       } else {
-               unit = unitp[unit_sz];
-               *val /= (double)vals_base2[unit_sz];
-       }
+  if (f_humanval) {
+    char buf[5];
 
-       return (unit);
+    humanize_number(buf, sizeof(buf), (int64_t)bytes, "",
+                   HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
+    (void)printf("%5s ", buf);
+  } else
+    (void)printf("%*jd ", (u_int)width, (intmax_t)bytes);
 }