17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 52236845bSakaplan * Common Development and Distribution License (the "License"). 62236845bSakaplan * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22575bd8a2Smarks * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 277c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate /* Copyright (c) 1987, 1988 Microsoft Corporation */ 307c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 317c478bd9Sstevel@tonic-gate 327c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 337c478bd9Sstevel@tonic-gate 347c478bd9Sstevel@tonic-gate /* 357c478bd9Sstevel@tonic-gate * List files or directories 367c478bd9Sstevel@tonic-gate */ 377c478bd9Sstevel@tonic-gate 387c478bd9Sstevel@tonic-gate #include <sys/param.h> 397c478bd9Sstevel@tonic-gate #include <sys/types.h> 407c478bd9Sstevel@tonic-gate #include <sys/mkdev.h> 417c478bd9Sstevel@tonic-gate #include <sys/stat.h> 427c478bd9Sstevel@tonic-gate #include <sys/acl.h> 437c478bd9Sstevel@tonic-gate 447c478bd9Sstevel@tonic-gate #include <wchar.h> 457c478bd9Sstevel@tonic-gate #include <stdio.h> 467c478bd9Sstevel@tonic-gate #include <ctype.h> 477c478bd9Sstevel@tonic-gate #include <dirent.h> 487c478bd9Sstevel@tonic-gate #include <string.h> 497c478bd9Sstevel@tonic-gate #include <locale.h> 507c478bd9Sstevel@tonic-gate #include <curses.h> 517c478bd9Sstevel@tonic-gate #include <termios.h> 527c478bd9Sstevel@tonic-gate #include <stdlib.h> 537c478bd9Sstevel@tonic-gate #include <widec.h> 547c478bd9Sstevel@tonic-gate #include <locale.h> 557c478bd9Sstevel@tonic-gate #include <wctype.h> 567c478bd9Sstevel@tonic-gate #include <pwd.h> 577c478bd9Sstevel@tonic-gate #include <grp.h> 587c478bd9Sstevel@tonic-gate #include <limits.h> 597c478bd9Sstevel@tonic-gate #include <fcntl.h> 607c478bd9Sstevel@tonic-gate #include <unistd.h> 617c478bd9Sstevel@tonic-gate #include <libgen.h> 627c478bd9Sstevel@tonic-gate #include <errno.h> 63fa9e4066Sahrens #include <aclutils.h> 64da6c28aaSamw #include <libnvpair.h> 65da6c28aaSamw #include <libcmdutils.h> 66da6c28aaSamw #include <attr.h> 677c478bd9Sstevel@tonic-gate 687c478bd9Sstevel@tonic-gate #ifndef STANDALONE 697c478bd9Sstevel@tonic-gate #define TERMINFO 707c478bd9Sstevel@tonic-gate #endif 717c478bd9Sstevel@tonic-gate 727c478bd9Sstevel@tonic-gate /* 737c478bd9Sstevel@tonic-gate * -DNOTERMINFO can be defined on the cc command line to prevent 747c478bd9Sstevel@tonic-gate * the use of terminfo. This should be done on systems not having 75da6c28aaSamw * the terminfo feature(pre 6.0 systems ?). 767c478bd9Sstevel@tonic-gate * As a result, columnar listings assume 80 columns for output, 777c478bd9Sstevel@tonic-gate * unless told otherwise via the COLUMNS environment variable. 787c478bd9Sstevel@tonic-gate */ 797c478bd9Sstevel@tonic-gate #ifdef NOTERMINFO 807c478bd9Sstevel@tonic-gate #undef TERMINFO 817c478bd9Sstevel@tonic-gate #endif 827c478bd9Sstevel@tonic-gate 837c478bd9Sstevel@tonic-gate #include <term.h> 847c478bd9Sstevel@tonic-gate 857c478bd9Sstevel@tonic-gate #define BFSIZE 16 867c478bd9Sstevel@tonic-gate /* this bit equals 1 in lflags of structure lbuf if *namep is to be used */ 877c478bd9Sstevel@tonic-gate #define ISARG 0100000 887c478bd9Sstevel@tonic-gate 897c478bd9Sstevel@tonic-gate /* 907c478bd9Sstevel@tonic-gate * this flag has been added to manipulate the display of S instead of 'l' when 917c478bd9Sstevel@tonic-gate * the file is not a regular file and when group execution bit is off 927c478bd9Sstevel@tonic-gate */ 937c478bd9Sstevel@tonic-gate #define LS_NOTREG 010000 947c478bd9Sstevel@tonic-gate 957c478bd9Sstevel@tonic-gate 967c478bd9Sstevel@tonic-gate /* 977c478bd9Sstevel@tonic-gate * Date and time formats 987c478bd9Sstevel@tonic-gate * 997c478bd9Sstevel@tonic-gate * b --- abbreviated month name 1007c478bd9Sstevel@tonic-gate * e --- day number 1017c478bd9Sstevel@tonic-gate * Y --- year in the form ccyy 1027c478bd9Sstevel@tonic-gate * H --- hour(24-hour version) 1037c478bd9Sstevel@tonic-gate * M --- minute 1047c478bd9Sstevel@tonic-gate * F --- yyyy-mm-dd 1057c478bd9Sstevel@tonic-gate * T --- hh:mm:ss 1067c478bd9Sstevel@tonic-gate * z --- time zone as hours displacement from UTC 1077c478bd9Sstevel@tonic-gate * note that %F and %z are from the ISO C99 standard and are 1087c478bd9Sstevel@tonic-gate * not present in older C libraries 1097c478bd9Sstevel@tonic-gate */ 1107c478bd9Sstevel@tonic-gate #define FORMAT1 " %b %e %Y " 1117c478bd9Sstevel@tonic-gate #define FORMAT2 " %b %e %H:%M " 1127c478bd9Sstevel@tonic-gate #define FORMAT3 " %b %e %T %Y " 1137c478bd9Sstevel@tonic-gate #define FORMAT4 " %%F %%T.%.09ld %%z " 1147c478bd9Sstevel@tonic-gate 1157c478bd9Sstevel@tonic-gate #undef BUFSIZ 1167c478bd9Sstevel@tonic-gate #define BUFSIZ 4096 1177c478bd9Sstevel@tonic-gate #define NUMBER_WIDTH 40 1187c478bd9Sstevel@tonic-gate #define FMTSIZE 50 1197c478bd9Sstevel@tonic-gate 1207c478bd9Sstevel@tonic-gate struct ditem { 1217c478bd9Sstevel@tonic-gate dev_t dev; /* directory items device number */ 1227c478bd9Sstevel@tonic-gate ino_t ino; /* directory items inode number */ 1237c478bd9Sstevel@tonic-gate struct ditem *parent; /* dir items ptr to its parent's info */ 1247c478bd9Sstevel@tonic-gate }; 125da6c28aaSamw /* Holds boolean extended system attributes */ 126da6c28aaSamw struct attrb { 127da6c28aaSamw char *name; 128da6c28aaSamw }; 129da6c28aaSamw /* Holds timestamp extended system attributes */ 130da6c28aaSamw struct attrtm { 131da6c28aaSamw char *name; 132da6c28aaSamw uint64_t stm; 133da6c28aaSamw uint64_t nstm; 134da6c28aaSamw }; 1357c478bd9Sstevel@tonic-gate 1367c478bd9Sstevel@tonic-gate struct lbuf { 1377c478bd9Sstevel@tonic-gate union { 1387c478bd9Sstevel@tonic-gate char lname[MAXNAMLEN]; /* used for filename in a directory */ 1397c478bd9Sstevel@tonic-gate char *namep; /* for name in ls-command; */ 1407c478bd9Sstevel@tonic-gate } ln; 1417c478bd9Sstevel@tonic-gate char ltype; /* filetype */ 1427c478bd9Sstevel@tonic-gate ino_t lnum; /* inode number of file */ 1437c478bd9Sstevel@tonic-gate mode_t lflags; /* 0777 bits used as r,w,x permissions */ 1447c478bd9Sstevel@tonic-gate nlink_t lnl; /* number of links to file */ 1457c478bd9Sstevel@tonic-gate uid_t luid; 1467c478bd9Sstevel@tonic-gate gid_t lgid; 1477c478bd9Sstevel@tonic-gate off_t lsize; /* filesize or major/minor dev numbers */ 1487c478bd9Sstevel@tonic-gate blkcnt_t lblocks; /* number of file blocks */ 1497c478bd9Sstevel@tonic-gate timestruc_t lmtime; 150da6c28aaSamw timestruc_t lat; 151da6c28aaSamw timestruc_t lct; 152da6c28aaSamw timestruc_t lmt; 1537c478bd9Sstevel@tonic-gate char *flinkto; /* symbolic link contents */ 1547c478bd9Sstevel@tonic-gate char acl; /* indicate there are additional acl entries */ 1557c478bd9Sstevel@tonic-gate int cycle; /* cycle detected flag */ 1567c478bd9Sstevel@tonic-gate struct ditem *ancinfo; /* maintains ancestor info */ 157fa9e4066Sahrens acl_t *aclp; /* ACL if present */ 158da6c28aaSamw struct attrb *exttr; /* boolean extended system attributes */ 159da6c28aaSamw struct attrtm *extm; /* timestamp extended system attributes */ 1607c478bd9Sstevel@tonic-gate }; 1617c478bd9Sstevel@tonic-gate 1627c478bd9Sstevel@tonic-gate struct dchain { 1637c478bd9Sstevel@tonic-gate char *dc_name; /* path name */ 1647c478bd9Sstevel@tonic-gate int cycle_detected; /* cycle detected visiting this directory */ 1657c478bd9Sstevel@tonic-gate struct ditem *myancinfo; /* this directory's ancestry info */ 1667c478bd9Sstevel@tonic-gate struct dchain *dc_next; /* next directory in the chain */ 1677c478bd9Sstevel@tonic-gate }; 1687c478bd9Sstevel@tonic-gate 1697c478bd9Sstevel@tonic-gate /* 1707c478bd9Sstevel@tonic-gate * A numbuf_t is used when converting a number to a string representation 1717c478bd9Sstevel@tonic-gate */ 1727c478bd9Sstevel@tonic-gate typedef char numbuf_t[NUMBER_WIDTH]; 1737c478bd9Sstevel@tonic-gate 1747c478bd9Sstevel@tonic-gate static struct dchain *dfirst; /* start of the dir chain */ 1757c478bd9Sstevel@tonic-gate static struct dchain *cdfirst; /* start of the current dir chain */ 1767c478bd9Sstevel@tonic-gate static struct dchain *dtemp; /* temporary - used for linking */ 1777c478bd9Sstevel@tonic-gate static char *curdir; /* the current directory */ 1787c478bd9Sstevel@tonic-gate 1797c478bd9Sstevel@tonic-gate static int first = 1; /* true if first line is not yet printed */ 1807c478bd9Sstevel@tonic-gate static int nfiles = 0; /* number of flist entries in current use */ 1817c478bd9Sstevel@tonic-gate static int nargs = 0; /* number of flist entries used for arguments */ 1827c478bd9Sstevel@tonic-gate static int maxfils = 0; /* number of flist/lbuf entries allocated */ 1837c478bd9Sstevel@tonic-gate static int maxn = 0; /* number of flist entries with lbufs asigned */ 1847c478bd9Sstevel@tonic-gate static int quantn = 64; /* allocation growth quantum */ 1857c478bd9Sstevel@tonic-gate 1867c478bd9Sstevel@tonic-gate static struct lbuf *nxtlbf; /* ptr to next lbuf to be assigned */ 1877c478bd9Sstevel@tonic-gate static struct lbuf **flist; /* ptr to list of lbuf pointers */ 1887c478bd9Sstevel@tonic-gate static struct lbuf *gstat(char *, int, struct ditem *); 1897c478bd9Sstevel@tonic-gate static char *getname(uid_t); 1907c478bd9Sstevel@tonic-gate static char *getgroup(gid_t); 1917c478bd9Sstevel@tonic-gate static char *makename(char *, char *); 1927c478bd9Sstevel@tonic-gate static void pentry(struct lbuf *); 1937c478bd9Sstevel@tonic-gate static void column(void); 1947c478bd9Sstevel@tonic-gate static void pmode(mode_t aflag); 1957c478bd9Sstevel@tonic-gate static void selection(int *); 1967c478bd9Sstevel@tonic-gate static void new_line(void); 1977c478bd9Sstevel@tonic-gate static void rddir(char *, struct ditem *); 1987c478bd9Sstevel@tonic-gate static int strcol(unsigned char *); 1997c478bd9Sstevel@tonic-gate static void pem(struct lbuf **, struct lbuf **, int); 2007c478bd9Sstevel@tonic-gate static void pdirectory(char *, int, int, int, struct ditem *); 2017c478bd9Sstevel@tonic-gate static struct cachenode *findincache(struct cachenode **, long); 2027c478bd9Sstevel@tonic-gate static void csi_pprintf(unsigned char *); 2037c478bd9Sstevel@tonic-gate static void pprintf(char *, char *); 2047c478bd9Sstevel@tonic-gate static int compar(struct lbuf **pp1, struct lbuf **pp2); 2057c478bd9Sstevel@tonic-gate static char *number_to_scaled_string(numbuf_t buf, 2067c478bd9Sstevel@tonic-gate unsigned long long number, 2077c478bd9Sstevel@tonic-gate long scale); 2087c478bd9Sstevel@tonic-gate static void record_ancestry(char *, struct stat *, struct lbuf *, 2097c478bd9Sstevel@tonic-gate int, struct ditem *); 2107c478bd9Sstevel@tonic-gate 2117c478bd9Sstevel@tonic-gate static int aflg; 2127c478bd9Sstevel@tonic-gate static int atflg; 2137c478bd9Sstevel@tonic-gate static int bflg; 2147c478bd9Sstevel@tonic-gate static int cflg; 2157c478bd9Sstevel@tonic-gate static int dflg; 2167c478bd9Sstevel@tonic-gate static int eflg; 2177c478bd9Sstevel@tonic-gate static int fflg; 2187c478bd9Sstevel@tonic-gate static int gflg; 2197c478bd9Sstevel@tonic-gate static int hflg; 2207c478bd9Sstevel@tonic-gate static int iflg; 2217c478bd9Sstevel@tonic-gate static int lflg; 2227c478bd9Sstevel@tonic-gate static int mflg; 2237c478bd9Sstevel@tonic-gate static int nflg; 2247c478bd9Sstevel@tonic-gate static int oflg; 2257c478bd9Sstevel@tonic-gate static int pflg; 2267c478bd9Sstevel@tonic-gate static int qflg; 2277c478bd9Sstevel@tonic-gate static int rflg = 1; /* init to 1 for special use in compar */ 2287c478bd9Sstevel@tonic-gate static int sflg; 2297c478bd9Sstevel@tonic-gate static int tflg; 2307c478bd9Sstevel@tonic-gate static int uflg; 2317c478bd9Sstevel@tonic-gate static int xflg; 2327c478bd9Sstevel@tonic-gate static int Aflg; 2337c478bd9Sstevel@tonic-gate static int Cflg; 2347c478bd9Sstevel@tonic-gate static int Eflg; 2357c478bd9Sstevel@tonic-gate static int Fflg; 2367c478bd9Sstevel@tonic-gate static int Hflg; 2377c478bd9Sstevel@tonic-gate static int Lflg; 2387c478bd9Sstevel@tonic-gate static int Rflg; 2397c478bd9Sstevel@tonic-gate static int Sflg; 240fa9e4066Sahrens static int vflg; 2415a5eeccaSmarks static int Vflg; 242da6c28aaSamw static int saflg; /* boolean extended system attr. */ 243da6c28aaSamw static int sacnt; /* number of extended system attr. */ 244da6c28aaSamw static int copt; 245da6c28aaSamw static int vopt; 246da6c28aaSamw static int tmflg; /* create time ext. system attr. */ 247da6c28aaSamw static int ctm; 248da6c28aaSamw static int atm; 249da6c28aaSamw static int mtm; 250da6c28aaSamw static int crtm; 251da6c28aaSamw static int alltm; 2527c478bd9Sstevel@tonic-gate static long hscale; 2537c478bd9Sstevel@tonic-gate static mode_t flags; 2547c478bd9Sstevel@tonic-gate static int err = 0; /* Contains return code */ 2557c478bd9Sstevel@tonic-gate 2567c478bd9Sstevel@tonic-gate static uid_t lastuid = (uid_t)-1; 2577c478bd9Sstevel@tonic-gate static gid_t lastgid = (gid_t)-1; 2587c478bd9Sstevel@tonic-gate static char *lastuname = NULL; 2597c478bd9Sstevel@tonic-gate static char *lastgname = NULL; 2607c478bd9Sstevel@tonic-gate 2617c478bd9Sstevel@tonic-gate /* statreq > 0 if any of sflg, (n)lflg, tflg, Sflg are on */ 2627c478bd9Sstevel@tonic-gate static int statreq; 2637c478bd9Sstevel@tonic-gate 2647c478bd9Sstevel@tonic-gate static char *dotp = "."; 2657c478bd9Sstevel@tonic-gate 2667c478bd9Sstevel@tonic-gate static u_longlong_t tblocks; /* number of blocks of files in a directory */ 2677c478bd9Sstevel@tonic-gate static time_t year, now; 2687c478bd9Sstevel@tonic-gate 2697c478bd9Sstevel@tonic-gate static int num_cols = 80; 2707c478bd9Sstevel@tonic-gate static int colwidth; 2717c478bd9Sstevel@tonic-gate static int filewidth; 2727c478bd9Sstevel@tonic-gate static int fixedwidth; 2737c478bd9Sstevel@tonic-gate static int nomocore; 2747c478bd9Sstevel@tonic-gate static int curcol; 2757c478bd9Sstevel@tonic-gate 2767c478bd9Sstevel@tonic-gate static struct winsize win; 2777c478bd9Sstevel@tonic-gate 278da6c28aaSamw static char time_buf[FMTSIZE]; /* array to hold day and time */ 2797c478bd9Sstevel@tonic-gate 2807c478bd9Sstevel@tonic-gate #define NOTWORKINGDIR(d, l) (((l) < 2) || \ 2817c478bd9Sstevel@tonic-gate (strcmp((d) + (l) - 2, "/.") != 0)) 2827c478bd9Sstevel@tonic-gate 2837c478bd9Sstevel@tonic-gate #define NOTPARENTDIR(d, l) (((l) < 3) || \ 2847c478bd9Sstevel@tonic-gate (strcmp((d) + (l) - 3, "/..") != 0)) 285da6c28aaSamw /* Extended system attributes support */ 286da6c28aaSamw static int get_sysxattr(char *, struct lbuf *); 287da6c28aaSamw static void set_sysattrb_display(char *, boolean_t, struct lbuf *); 288da6c28aaSamw static void set_sysattrtm_display(char *, struct lbuf *); 289da6c28aaSamw static void format_time(const char *, time_t); 290da6c28aaSamw static void format_etime(const char *, time_t, time_t); 291da6c28aaSamw static void print_time(struct lbuf *); 292da6c28aaSamw static void format_attrtime(struct lbuf *); 293da6c28aaSamw static void *xmalloc(size_t, struct lbuf *); 294da6c28aaSamw static void free_sysattr(struct lbuf *); 295da6c28aaSamw static nvpair_t *pair; 296da6c28aaSamw static nvlist_t *response; 297*56798e90Sbasabi static int acl_err; 2987c478bd9Sstevel@tonic-gate 2997c478bd9Sstevel@tonic-gate int 3007c478bd9Sstevel@tonic-gate main(int argc, char *argv[]) 3017c478bd9Sstevel@tonic-gate { 3027c478bd9Sstevel@tonic-gate int c; 3037c478bd9Sstevel@tonic-gate int i; 3047c478bd9Sstevel@tonic-gate int width; 3057c478bd9Sstevel@tonic-gate int amino = 0; 3067c478bd9Sstevel@tonic-gate int opterr = 0; 3077c478bd9Sstevel@tonic-gate struct lbuf *ep; 3087c478bd9Sstevel@tonic-gate struct lbuf lb; 3097c478bd9Sstevel@tonic-gate struct ditem *myinfo; 3107c478bd9Sstevel@tonic-gate 3117c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 3127c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 3137c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */ 3147c478bd9Sstevel@tonic-gate #endif 3157c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 3167c478bd9Sstevel@tonic-gate #ifdef STANDALONE 3177c478bd9Sstevel@tonic-gate if (argv[0][0] == '\0') 3187c478bd9Sstevel@tonic-gate argc = getargv("ls", &argv, 0); 3197c478bd9Sstevel@tonic-gate #endif 3207c478bd9Sstevel@tonic-gate 3217c478bd9Sstevel@tonic-gate lb.lmtime.tv_sec = time(NULL); 3227c478bd9Sstevel@tonic-gate lb.lmtime.tv_nsec = 0; 3237c478bd9Sstevel@tonic-gate year = lb.lmtime.tv_sec - 6L*30L*24L*60L*60L; /* 6 months ago */ 3247c478bd9Sstevel@tonic-gate now = lb.lmtime.tv_sec + 60; 3257c478bd9Sstevel@tonic-gate if (isatty(1)) { 3267c478bd9Sstevel@tonic-gate Cflg = 1; 3277c478bd9Sstevel@tonic-gate mflg = 0; 3287c478bd9Sstevel@tonic-gate } 3297c478bd9Sstevel@tonic-gate 3307c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, 331da6c28aaSamw "aAbcCdeEfFghHilLmnopqrRsStux1@vV/:%:")) != EOF) 3327c478bd9Sstevel@tonic-gate switch (c) { 3337c478bd9Sstevel@tonic-gate case 'a': 3347c478bd9Sstevel@tonic-gate aflg++; 3357c478bd9Sstevel@tonic-gate continue; 3367c478bd9Sstevel@tonic-gate case 'A': 3377c478bd9Sstevel@tonic-gate Aflg++; 3387c478bd9Sstevel@tonic-gate continue; 3397c478bd9Sstevel@tonic-gate case 'b': 3407c478bd9Sstevel@tonic-gate bflg = 1; 3417c478bd9Sstevel@tonic-gate qflg = 0; 3427c478bd9Sstevel@tonic-gate continue; 3437c478bd9Sstevel@tonic-gate case 'c': 3447c478bd9Sstevel@tonic-gate uflg = 0; 345da6c28aaSamw atm = 0; 346da6c28aaSamw ctm = 0; 347da6c28aaSamw mtm = 0; 348da6c28aaSamw crtm = 0; 3497c478bd9Sstevel@tonic-gate cflg++; 3507c478bd9Sstevel@tonic-gate continue; 3517c478bd9Sstevel@tonic-gate case 'C': 3527c478bd9Sstevel@tonic-gate Cflg = 1; 3537c478bd9Sstevel@tonic-gate mflg = 0; 3547c478bd9Sstevel@tonic-gate #ifdef XPG4 3557c478bd9Sstevel@tonic-gate lflg = 0; 3567c478bd9Sstevel@tonic-gate #endif 3577c478bd9Sstevel@tonic-gate continue; 3587c478bd9Sstevel@tonic-gate case 'd': 3597c478bd9Sstevel@tonic-gate dflg++; 3607c478bd9Sstevel@tonic-gate continue; 3617c478bd9Sstevel@tonic-gate case 'e': 3627c478bd9Sstevel@tonic-gate eflg++; 3637c478bd9Sstevel@tonic-gate lflg++; 3647c478bd9Sstevel@tonic-gate statreq++; 3657c478bd9Sstevel@tonic-gate Eflg = 0; 3667c478bd9Sstevel@tonic-gate continue; 3677c478bd9Sstevel@tonic-gate case 'E': 3687c478bd9Sstevel@tonic-gate Eflg++; 3697c478bd9Sstevel@tonic-gate lflg++; 3707c478bd9Sstevel@tonic-gate statreq++; 3717c478bd9Sstevel@tonic-gate eflg = 0; 3727c478bd9Sstevel@tonic-gate continue; 3737c478bd9Sstevel@tonic-gate case 'f': 3747c478bd9Sstevel@tonic-gate fflg++; 3757c478bd9Sstevel@tonic-gate continue; 3767c478bd9Sstevel@tonic-gate case 'F': 3777c478bd9Sstevel@tonic-gate Fflg++; 3787c478bd9Sstevel@tonic-gate statreq++; 3797c478bd9Sstevel@tonic-gate continue; 3807c478bd9Sstevel@tonic-gate case 'g': 3817c478bd9Sstevel@tonic-gate gflg++; 3827c478bd9Sstevel@tonic-gate lflg++; 3837c478bd9Sstevel@tonic-gate statreq++; 3847c478bd9Sstevel@tonic-gate continue; 3857c478bd9Sstevel@tonic-gate case 'h': 3867c478bd9Sstevel@tonic-gate hflg++; 3877c478bd9Sstevel@tonic-gate hscale = 1024; 3887c478bd9Sstevel@tonic-gate continue; 3897c478bd9Sstevel@tonic-gate case 'H': 3907c478bd9Sstevel@tonic-gate Hflg++; 3917c478bd9Sstevel@tonic-gate /* -H and -L are mutually exclusive */ 3927c478bd9Sstevel@tonic-gate Lflg = 0; 3937c478bd9Sstevel@tonic-gate continue; 3947c478bd9Sstevel@tonic-gate case 'i': 3957c478bd9Sstevel@tonic-gate iflg++; 3967c478bd9Sstevel@tonic-gate continue; 3977c478bd9Sstevel@tonic-gate case 'l': 3987c478bd9Sstevel@tonic-gate lflg++; 3997c478bd9Sstevel@tonic-gate statreq++; 4007c478bd9Sstevel@tonic-gate Cflg = 0; 4017c478bd9Sstevel@tonic-gate xflg = 0; 4027c478bd9Sstevel@tonic-gate mflg = 0; 4037c478bd9Sstevel@tonic-gate atflg = 0; 4047c478bd9Sstevel@tonic-gate continue; 4057c478bd9Sstevel@tonic-gate case 'L': 4067c478bd9Sstevel@tonic-gate Lflg++; 4077c478bd9Sstevel@tonic-gate /* -H and -L are mutually exclusive */ 4087c478bd9Sstevel@tonic-gate Hflg = 0; 4097c478bd9Sstevel@tonic-gate continue; 4107c478bd9Sstevel@tonic-gate case 'm': 4117c478bd9Sstevel@tonic-gate Cflg = 0; 4127c478bd9Sstevel@tonic-gate mflg = 1; 4137c478bd9Sstevel@tonic-gate #ifdef XPG4 4147c478bd9Sstevel@tonic-gate lflg = 0; 4157c478bd9Sstevel@tonic-gate #endif 4167c478bd9Sstevel@tonic-gate continue; 4177c478bd9Sstevel@tonic-gate case 'n': 4187c478bd9Sstevel@tonic-gate nflg++; 4197c478bd9Sstevel@tonic-gate lflg++; 4207c478bd9Sstevel@tonic-gate statreq++; 4217c478bd9Sstevel@tonic-gate Cflg = 0; 4227c478bd9Sstevel@tonic-gate xflg = 0; 4237c478bd9Sstevel@tonic-gate mflg = 0; 4247c478bd9Sstevel@tonic-gate atflg = 0; 4257c478bd9Sstevel@tonic-gate continue; 4267c478bd9Sstevel@tonic-gate case 'o': 4277c478bd9Sstevel@tonic-gate oflg++; 4287c478bd9Sstevel@tonic-gate lflg++; 4297c478bd9Sstevel@tonic-gate statreq++; 4307c478bd9Sstevel@tonic-gate continue; 4317c478bd9Sstevel@tonic-gate case 'p': 4327c478bd9Sstevel@tonic-gate pflg++; 4337c478bd9Sstevel@tonic-gate statreq++; 4347c478bd9Sstevel@tonic-gate continue; 4357c478bd9Sstevel@tonic-gate case 'q': 4367c478bd9Sstevel@tonic-gate qflg = 1; 4377c478bd9Sstevel@tonic-gate bflg = 0; 4387c478bd9Sstevel@tonic-gate continue; 4397c478bd9Sstevel@tonic-gate case 'r': 4407c478bd9Sstevel@tonic-gate rflg = -1; 4417c478bd9Sstevel@tonic-gate continue; 4427c478bd9Sstevel@tonic-gate case 'R': 4437c478bd9Sstevel@tonic-gate Rflg++; 4447c478bd9Sstevel@tonic-gate statreq++; 4457c478bd9Sstevel@tonic-gate continue; 4467c478bd9Sstevel@tonic-gate case 's': 4477c478bd9Sstevel@tonic-gate sflg++; 4487c478bd9Sstevel@tonic-gate statreq++; 4497c478bd9Sstevel@tonic-gate continue; 4507c478bd9Sstevel@tonic-gate case 'S': 4517c478bd9Sstevel@tonic-gate tflg = 0; 4527c478bd9Sstevel@tonic-gate Sflg++; 4537c478bd9Sstevel@tonic-gate statreq++; 4547c478bd9Sstevel@tonic-gate continue; 4557c478bd9Sstevel@tonic-gate case 't': 4567c478bd9Sstevel@tonic-gate Sflg = 0; 4577c478bd9Sstevel@tonic-gate tflg++; 4587c478bd9Sstevel@tonic-gate statreq++; 4597c478bd9Sstevel@tonic-gate continue; 4607c478bd9Sstevel@tonic-gate case 'u': 4617c478bd9Sstevel@tonic-gate cflg = 0; 462da6c28aaSamw atm = 0; 463da6c28aaSamw ctm = 0; 464da6c28aaSamw mtm = 0; 465da6c28aaSamw crtm = 0; 4667c478bd9Sstevel@tonic-gate uflg++; 4677c478bd9Sstevel@tonic-gate continue; 4685a5eeccaSmarks case 'V': 4695a5eeccaSmarks Vflg++; 4705a5eeccaSmarks /*FALLTHROUGH*/ 471fa9e4066Sahrens case 'v': 472fa9e4066Sahrens vflg++; 473fa9e4066Sahrens #if !defined(XPG4) 474fa9e4066Sahrens if (lflg) 475fa9e4066Sahrens continue; 476fa9e4066Sahrens #endif 477fa9e4066Sahrens lflg++; 478fa9e4066Sahrens statreq++; 479fa9e4066Sahrens Cflg = 0; 480fa9e4066Sahrens xflg = 0; 481fa9e4066Sahrens mflg = 0; 482fa9e4066Sahrens continue; 4837c478bd9Sstevel@tonic-gate case 'x': 4847c478bd9Sstevel@tonic-gate xflg = 1; 4857c478bd9Sstevel@tonic-gate Cflg = 1; 4867c478bd9Sstevel@tonic-gate mflg = 0; 4877c478bd9Sstevel@tonic-gate #ifdef XPG4 4887c478bd9Sstevel@tonic-gate lflg = 0; 4897c478bd9Sstevel@tonic-gate #endif 4907c478bd9Sstevel@tonic-gate continue; 4917c478bd9Sstevel@tonic-gate case '1': 4927c478bd9Sstevel@tonic-gate Cflg = 0; 4937c478bd9Sstevel@tonic-gate continue; 4947c478bd9Sstevel@tonic-gate case '@': 4957c478bd9Sstevel@tonic-gate #if !defined(XPG4) 4967c478bd9Sstevel@tonic-gate /* 4977c478bd9Sstevel@tonic-gate * -l has precedence over -@ 4987c478bd9Sstevel@tonic-gate */ 4997c478bd9Sstevel@tonic-gate if (lflg) 5007c478bd9Sstevel@tonic-gate continue; 5017c478bd9Sstevel@tonic-gate #endif 5027c478bd9Sstevel@tonic-gate atflg++; 5037c478bd9Sstevel@tonic-gate lflg++; 5047c478bd9Sstevel@tonic-gate statreq++; 5057c478bd9Sstevel@tonic-gate Cflg = 0; 5067c478bd9Sstevel@tonic-gate xflg = 0; 5077c478bd9Sstevel@tonic-gate mflg = 0; 5087c478bd9Sstevel@tonic-gate continue; 509da6c28aaSamw case '/': 510da6c28aaSamw saflg++; 511da6c28aaSamw if (optarg != NULL) { 512da6c28aaSamw if (strcmp(optarg, "c") == 0) { 513da6c28aaSamw copt++; 514da6c28aaSamw vopt = 0; 515da6c28aaSamw } else if (strcmp(optarg, "v") == 0) { 516da6c28aaSamw vopt++; 517da6c28aaSamw copt = 0; 518da6c28aaSamw } else 519da6c28aaSamw opterr++; 520da6c28aaSamw } else 521da6c28aaSamw opterr++; 522da6c28aaSamw lflg++; 523da6c28aaSamw statreq++; 524da6c28aaSamw Cflg = 0; 525da6c28aaSamw xflg = 0; 526da6c28aaSamw mflg = 0; 527da6c28aaSamw continue; 528da6c28aaSamw case '%': 529da6c28aaSamw tmflg++; 530da6c28aaSamw if (optarg != NULL) { 531da6c28aaSamw if (strcmp(optarg, "ctime") == 0) { 532da6c28aaSamw ctm++; 533da6c28aaSamw atm = 0; 534da6c28aaSamw mtm = 0; 535da6c28aaSamw crtm = 0; 536da6c28aaSamw } else if (strcmp(optarg, "atime") == 0) { 537da6c28aaSamw atm++; 538da6c28aaSamw ctm = 0; 539da6c28aaSamw mtm = 0; 540da6c28aaSamw crtm = 0; 541da6c28aaSamw uflg = 0; 542da6c28aaSamw cflg = 0; 543da6c28aaSamw } else if (strcmp(optarg, "mtime") == 0) { 544da6c28aaSamw mtm++; 545da6c28aaSamw atm = 0; 546da6c28aaSamw ctm = 0; 547da6c28aaSamw crtm = 0; 548da6c28aaSamw uflg = 0; 549da6c28aaSamw cflg = 0; 550da6c28aaSamw } else if (strcmp(optarg, "crtime") == 0) { 551da6c28aaSamw crtm++; 552da6c28aaSamw atm = 0; 553da6c28aaSamw ctm = 0; 554da6c28aaSamw mtm = 0; 555da6c28aaSamw uflg = 0; 556da6c28aaSamw cflg = 0; 557da6c28aaSamw } else if (strcmp(optarg, "all") == 0) { 558da6c28aaSamw alltm++; 559da6c28aaSamw atm = 0; 560da6c28aaSamw ctm = 0; 561da6c28aaSamw mtm = 0; 562da6c28aaSamw crtm = 0; 563da6c28aaSamw } else 564da6c28aaSamw opterr++; 565da6c28aaSamw } else 566da6c28aaSamw opterr++; 567da6c28aaSamw 568da6c28aaSamw Sflg = 0; 569da6c28aaSamw statreq++; 570da6c28aaSamw mflg = 0; 571da6c28aaSamw continue; 5727c478bd9Sstevel@tonic-gate case '?': 5737c478bd9Sstevel@tonic-gate opterr++; 5747c478bd9Sstevel@tonic-gate continue; 5757c478bd9Sstevel@tonic-gate } 5767c478bd9Sstevel@tonic-gate if (opterr) { 5777c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 578da6c28aaSamw "usage: ls -aAbcCdeEfFghHilLmnopqrRsStuxvV1@/%[c | v]" 579da6c28aaSamw "%%[atime | crtime | ctime | mtime | all]" 580da6c28aaSamw " [files]\n")); 5817c478bd9Sstevel@tonic-gate exit(2); 5827c478bd9Sstevel@tonic-gate } 5837c478bd9Sstevel@tonic-gate 5847c478bd9Sstevel@tonic-gate if (fflg) { 5857c478bd9Sstevel@tonic-gate aflg++; 5867c478bd9Sstevel@tonic-gate lflg = 0; 5877c478bd9Sstevel@tonic-gate sflg = 0; 5887c478bd9Sstevel@tonic-gate tflg = 0; 5897c478bd9Sstevel@tonic-gate Sflg = 0; 5907c478bd9Sstevel@tonic-gate statreq = 0; 5917c478bd9Sstevel@tonic-gate } 5927c478bd9Sstevel@tonic-gate 5937c478bd9Sstevel@tonic-gate fixedwidth = 2; 5947c478bd9Sstevel@tonic-gate if (pflg || Fflg) 5957c478bd9Sstevel@tonic-gate fixedwidth++; 5967c478bd9Sstevel@tonic-gate if (iflg) 5977c478bd9Sstevel@tonic-gate fixedwidth += 11; 5987c478bd9Sstevel@tonic-gate if (sflg) 5997c478bd9Sstevel@tonic-gate fixedwidth += 5; 6007c478bd9Sstevel@tonic-gate 6017c478bd9Sstevel@tonic-gate if (lflg) { 6027c478bd9Sstevel@tonic-gate if (!gflg && !oflg) 6037c478bd9Sstevel@tonic-gate gflg = oflg = 1; 6047c478bd9Sstevel@tonic-gate else 6057c478bd9Sstevel@tonic-gate if (gflg && oflg) 6067c478bd9Sstevel@tonic-gate gflg = oflg = 0; 6077c478bd9Sstevel@tonic-gate Cflg = mflg = 0; 6087c478bd9Sstevel@tonic-gate } 6097c478bd9Sstevel@tonic-gate 6107c478bd9Sstevel@tonic-gate if (Cflg || mflg) { 6117c478bd9Sstevel@tonic-gate char *clptr; 6127c478bd9Sstevel@tonic-gate if ((clptr = getenv("COLUMNS")) != NULL) 6137c478bd9Sstevel@tonic-gate num_cols = atoi(clptr); 6147c478bd9Sstevel@tonic-gate #ifdef TERMINFO 6157c478bd9Sstevel@tonic-gate else { 6167c478bd9Sstevel@tonic-gate if (ioctl(1, TIOCGWINSZ, &win) != -1) 6177c478bd9Sstevel@tonic-gate num_cols = (win.ws_col == 0 ? 80 : win.ws_col); 6187c478bd9Sstevel@tonic-gate } 6197c478bd9Sstevel@tonic-gate #endif 6207c478bd9Sstevel@tonic-gate if (num_cols < 20 || num_cols > 1000) 6217c478bd9Sstevel@tonic-gate /* assume it is an error */ 6227c478bd9Sstevel@tonic-gate num_cols = 80; 6237c478bd9Sstevel@tonic-gate } 6247c478bd9Sstevel@tonic-gate 6257c478bd9Sstevel@tonic-gate /* allocate space for flist and the associated */ 6267c478bd9Sstevel@tonic-gate /* data structures (lbufs) */ 6277c478bd9Sstevel@tonic-gate maxfils = quantn; 6287c478bd9Sstevel@tonic-gate if (((flist = malloc(maxfils * sizeof (struct lbuf *))) == NULL) || 6297c478bd9Sstevel@tonic-gate ((nxtlbf = malloc(quantn * sizeof (struct lbuf))) == NULL)) { 6307c478bd9Sstevel@tonic-gate perror("ls"); 6317c478bd9Sstevel@tonic-gate exit(2); 6327c478bd9Sstevel@tonic-gate } 6337c478bd9Sstevel@tonic-gate if ((amino = (argc-optind)) == 0) { 6347c478bd9Sstevel@tonic-gate /* 6357c478bd9Sstevel@tonic-gate * case when no names are given 6367c478bd9Sstevel@tonic-gate * in ls-command and current 6377c478bd9Sstevel@tonic-gate * directory is to be used 6387c478bd9Sstevel@tonic-gate */ 6397c478bd9Sstevel@tonic-gate argv[optind] = dotp; 6407c478bd9Sstevel@tonic-gate } 6417c478bd9Sstevel@tonic-gate 6427c478bd9Sstevel@tonic-gate for (i = 0; i < (amino ? amino : 1); i++) { 6437c478bd9Sstevel@tonic-gate 6447c478bd9Sstevel@tonic-gate /* 6457c478bd9Sstevel@tonic-gate * If we are recursing, we need to make sure we don't 6467c478bd9Sstevel@tonic-gate * get into an endless loop. To keep track of the inodes 6477c478bd9Sstevel@tonic-gate * (actually, just the directories) visited, we 6487c478bd9Sstevel@tonic-gate * maintain a directory ancestry list for a file 6497c478bd9Sstevel@tonic-gate * hierarchy. As we go deeper into the hierarchy, 6507c478bd9Sstevel@tonic-gate * a parent directory passes its directory list 6517c478bd9Sstevel@tonic-gate * info (device id, inode number, and a pointer to 6527c478bd9Sstevel@tonic-gate * its parent) to each of its children. As we 6537c478bd9Sstevel@tonic-gate * process a child that is a directory, we save 6547c478bd9Sstevel@tonic-gate * its own personal directory list info. We then 6557c478bd9Sstevel@tonic-gate * check to see if the child has already been 6567c478bd9Sstevel@tonic-gate * processed by comparing its device id and inode 6577c478bd9Sstevel@tonic-gate * number from its own personal directory list info 6587c478bd9Sstevel@tonic-gate * to that of each of its ancestors. If there is a 6597c478bd9Sstevel@tonic-gate * match, then we know we've detected a cycle. 6607c478bd9Sstevel@tonic-gate */ 6617c478bd9Sstevel@tonic-gate if (Rflg) { 6627c478bd9Sstevel@tonic-gate /* 6637c478bd9Sstevel@tonic-gate * This is the first parent in this lineage 6647c478bd9Sstevel@tonic-gate * (first in a directory hierarchy), so 6657c478bd9Sstevel@tonic-gate * this parent's parent doesn't exist. We 6667c478bd9Sstevel@tonic-gate * only initialize myinfo when we are 6677c478bd9Sstevel@tonic-gate * recursing, otherwise it's not used. 6687c478bd9Sstevel@tonic-gate */ 6697c478bd9Sstevel@tonic-gate if ((myinfo = (struct ditem *)malloc( 6707c478bd9Sstevel@tonic-gate sizeof (struct ditem))) == NULL) { 6717c478bd9Sstevel@tonic-gate perror("ls"); 6727c478bd9Sstevel@tonic-gate exit(2); 6737c478bd9Sstevel@tonic-gate } else { 6747c478bd9Sstevel@tonic-gate myinfo->dev = 0; 6757c478bd9Sstevel@tonic-gate myinfo->ino = 0; 6767c478bd9Sstevel@tonic-gate myinfo->parent = NULL; 6777c478bd9Sstevel@tonic-gate } 6787c478bd9Sstevel@tonic-gate } 6797c478bd9Sstevel@tonic-gate 6807c478bd9Sstevel@tonic-gate if (Cflg || mflg) { 6817c478bd9Sstevel@tonic-gate width = strcol((unsigned char *)argv[optind]); 6827c478bd9Sstevel@tonic-gate if (width > filewidth) 6837c478bd9Sstevel@tonic-gate filewidth = width; 6847c478bd9Sstevel@tonic-gate } 6857c478bd9Sstevel@tonic-gate if ((ep = gstat((*argv[optind] ? argv[optind] : dotp), 6867c478bd9Sstevel@tonic-gate 1, myinfo)) == NULL) { 6877c478bd9Sstevel@tonic-gate if (nomocore) 6887c478bd9Sstevel@tonic-gate exit(2); 6897c478bd9Sstevel@tonic-gate err = 2; 6907c478bd9Sstevel@tonic-gate optind++; 6917c478bd9Sstevel@tonic-gate continue; 6927c478bd9Sstevel@tonic-gate } 6937c478bd9Sstevel@tonic-gate ep->ln.namep = (*argv[optind] ? argv[optind] : dotp); 6947c478bd9Sstevel@tonic-gate ep->lflags |= ISARG; 6957c478bd9Sstevel@tonic-gate optind++; 6967c478bd9Sstevel@tonic-gate nargs++; /* count good arguments stored in flist */ 697*56798e90Sbasabi if (acl_err) 698*56798e90Sbasabi err = 2; 6997c478bd9Sstevel@tonic-gate } 7007c478bd9Sstevel@tonic-gate colwidth = fixedwidth + filewidth; 7017c478bd9Sstevel@tonic-gate qsort(flist, (unsigned)nargs, sizeof (struct lbuf *), 7027c478bd9Sstevel@tonic-gate (int (*)(const void *, const void *))compar); 7037c478bd9Sstevel@tonic-gate for (i = 0; i < nargs; i++) { 7047c478bd9Sstevel@tonic-gate if (flist[i]->ltype == 'd' && dflg == 0 || fflg) 7057c478bd9Sstevel@tonic-gate break; 7067c478bd9Sstevel@tonic-gate } 7077c478bd9Sstevel@tonic-gate pem(&flist[0], &flist[i], 0); 7087c478bd9Sstevel@tonic-gate for (; i < nargs; i++) { 7097c478bd9Sstevel@tonic-gate pdirectory(flist[i]->ln.namep, Rflg || 7107c478bd9Sstevel@tonic-gate (amino > 1), nargs, 0, flist[i]->ancinfo); 7117c478bd9Sstevel@tonic-gate if (nomocore) 7127c478bd9Sstevel@tonic-gate exit(2); 7137c478bd9Sstevel@tonic-gate /* -R: print subdirectories found */ 7147c478bd9Sstevel@tonic-gate while (dfirst || cdfirst) { 7157c478bd9Sstevel@tonic-gate /* Place direct subdirs on front in right order */ 7167c478bd9Sstevel@tonic-gate while (cdfirst) { 7177c478bd9Sstevel@tonic-gate /* reverse cdfirst onto front of dfirst */ 7187c478bd9Sstevel@tonic-gate dtemp = cdfirst; 7197c478bd9Sstevel@tonic-gate cdfirst = cdfirst -> dc_next; 7207c478bd9Sstevel@tonic-gate dtemp -> dc_next = dfirst; 7217c478bd9Sstevel@tonic-gate dfirst = dtemp; 7227c478bd9Sstevel@tonic-gate } 7237c478bd9Sstevel@tonic-gate /* take off first dir on dfirst & print it */ 7247c478bd9Sstevel@tonic-gate dtemp = dfirst; 7257c478bd9Sstevel@tonic-gate dfirst = dfirst->dc_next; 7267c478bd9Sstevel@tonic-gate pdirectory(dtemp->dc_name, 1, nargs, 7277c478bd9Sstevel@tonic-gate dtemp->cycle_detected, dtemp->myancinfo); 7287c478bd9Sstevel@tonic-gate if (nomocore) 7297c478bd9Sstevel@tonic-gate exit(2); 7307c478bd9Sstevel@tonic-gate free(dtemp->dc_name); 7317c478bd9Sstevel@tonic-gate free(dtemp); 7327c478bd9Sstevel@tonic-gate } 7337c478bd9Sstevel@tonic-gate } 7347c478bd9Sstevel@tonic-gate return (err); 7357c478bd9Sstevel@tonic-gate } 7367c478bd9Sstevel@tonic-gate 7377c478bd9Sstevel@tonic-gate /* 7387c478bd9Sstevel@tonic-gate * pdirectory: print the directory name, labelling it if title is 7397c478bd9Sstevel@tonic-gate * nonzero, using lp as the place to start reading in the dir. 7407c478bd9Sstevel@tonic-gate */ 7417c478bd9Sstevel@tonic-gate static void 7427c478bd9Sstevel@tonic-gate pdirectory(char *name, int title, int lp, int cdetect, struct ditem *myinfo) 7437c478bd9Sstevel@tonic-gate { 7447c478bd9Sstevel@tonic-gate struct dchain *dp; 7457c478bd9Sstevel@tonic-gate struct lbuf *ap; 7467c478bd9Sstevel@tonic-gate char *pname; 7477c478bd9Sstevel@tonic-gate int j; 7487c478bd9Sstevel@tonic-gate 7497c478bd9Sstevel@tonic-gate filewidth = 0; 7507c478bd9Sstevel@tonic-gate curdir = name; 7517c478bd9Sstevel@tonic-gate if (title) { 7527c478bd9Sstevel@tonic-gate if (!first) 7537c478bd9Sstevel@tonic-gate (void) putc('\n', stdout); 7547c478bd9Sstevel@tonic-gate pprintf(name, ":"); 7557c478bd9Sstevel@tonic-gate new_line(); 7567c478bd9Sstevel@tonic-gate } 7577c478bd9Sstevel@tonic-gate /* 7587c478bd9Sstevel@tonic-gate * If there was a cycle detected, then notify and don't report 7597c478bd9Sstevel@tonic-gate * further. 7607c478bd9Sstevel@tonic-gate */ 7617c478bd9Sstevel@tonic-gate if (cdetect) { 7627c478bd9Sstevel@tonic-gate if (lflg || sflg) { 7637c478bd9Sstevel@tonic-gate curcol += printf(gettext("total %d"), 0); 7647c478bd9Sstevel@tonic-gate new_line(); 7657c478bd9Sstevel@tonic-gate } 7667c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 7677c478bd9Sstevel@tonic-gate "ls: cycle detected for %s\n"), name); 7687c478bd9Sstevel@tonic-gate return; 7697c478bd9Sstevel@tonic-gate } 7707c478bd9Sstevel@tonic-gate 7717c478bd9Sstevel@tonic-gate nfiles = lp; 7727c478bd9Sstevel@tonic-gate rddir(name, myinfo); 7737c478bd9Sstevel@tonic-gate if (nomocore) 7747c478bd9Sstevel@tonic-gate return; 7757c478bd9Sstevel@tonic-gate if (fflg == 0) 7767c478bd9Sstevel@tonic-gate qsort(&flist[lp], (unsigned)(nfiles - lp), 7777c478bd9Sstevel@tonic-gate sizeof (struct lbuf *), 7787c478bd9Sstevel@tonic-gate (int (*)(const void *, const void *))compar); 7797c478bd9Sstevel@tonic-gate if (Rflg) { 7807c478bd9Sstevel@tonic-gate for (j = nfiles - 1; j >= lp; j--) { 7817c478bd9Sstevel@tonic-gate ap = flist[j]; 7827c478bd9Sstevel@tonic-gate if (ap->ltype == 'd' && strcmp(ap->ln.lname, ".") && 7837c478bd9Sstevel@tonic-gate strcmp(ap->ln.lname, "..")) { 7847c478bd9Sstevel@tonic-gate dp = malloc(sizeof (struct dchain)); 7857c478bd9Sstevel@tonic-gate if (dp == NULL) { 7867c478bd9Sstevel@tonic-gate perror("ls"); 7877c478bd9Sstevel@tonic-gate exit(2); 7887c478bd9Sstevel@tonic-gate } 7897c478bd9Sstevel@tonic-gate pname = makename(curdir, ap->ln.lname); 7907c478bd9Sstevel@tonic-gate if ((dp->dc_name = strdup(pname)) == NULL) { 7917c478bd9Sstevel@tonic-gate perror("ls"); 7927c478bd9Sstevel@tonic-gate exit(2); 7937c478bd9Sstevel@tonic-gate } 7947c478bd9Sstevel@tonic-gate dp->cycle_detected = ap->cycle; 7957c478bd9Sstevel@tonic-gate dp->myancinfo = ap->ancinfo; 7967c478bd9Sstevel@tonic-gate dp->dc_next = dfirst; 7977c478bd9Sstevel@tonic-gate dfirst = dp; 7987c478bd9Sstevel@tonic-gate } 7997c478bd9Sstevel@tonic-gate } 8007c478bd9Sstevel@tonic-gate } 8017c478bd9Sstevel@tonic-gate if (lflg || sflg) { 8027c478bd9Sstevel@tonic-gate curcol += printf(gettext("total %llu"), tblocks); 8037c478bd9Sstevel@tonic-gate new_line(); 8047c478bd9Sstevel@tonic-gate } 8057c478bd9Sstevel@tonic-gate pem(&flist[lp], &flist[nfiles], lflg||sflg); 8067c478bd9Sstevel@tonic-gate } 8077c478bd9Sstevel@tonic-gate 8087c478bd9Sstevel@tonic-gate /* 8097c478bd9Sstevel@tonic-gate * pem: print 'em. Print a list of files (e.g. a directory) bounded 8107c478bd9Sstevel@tonic-gate * by slp and lp. 8117c478bd9Sstevel@tonic-gate */ 8127c478bd9Sstevel@tonic-gate static void 8137c478bd9Sstevel@tonic-gate pem(struct lbuf **slp, struct lbuf **lp, int tot_flag) 8147c478bd9Sstevel@tonic-gate { 8157c478bd9Sstevel@tonic-gate long row, nrows, i; 8167c478bd9Sstevel@tonic-gate int col, ncols; 8177c478bd9Sstevel@tonic-gate struct lbuf **ep; 8187c478bd9Sstevel@tonic-gate 8197c478bd9Sstevel@tonic-gate if (Cflg || mflg) { 8207c478bd9Sstevel@tonic-gate if (colwidth > num_cols) { 8217c478bd9Sstevel@tonic-gate ncols = 1; 8227c478bd9Sstevel@tonic-gate } else { 8237c478bd9Sstevel@tonic-gate ncols = num_cols / colwidth; 8247c478bd9Sstevel@tonic-gate } 8257c478bd9Sstevel@tonic-gate } 8267c478bd9Sstevel@tonic-gate 8277c478bd9Sstevel@tonic-gate if (ncols == 1 || mflg || xflg || !Cflg) { 8287c478bd9Sstevel@tonic-gate for (ep = slp; ep < lp; ep++) 8297c478bd9Sstevel@tonic-gate pentry(*ep); 8307c478bd9Sstevel@tonic-gate new_line(); 8317c478bd9Sstevel@tonic-gate return; 8327c478bd9Sstevel@tonic-gate } 8337c478bd9Sstevel@tonic-gate /* otherwise print -C columns */ 8347c478bd9Sstevel@tonic-gate if (tot_flag) { 8357c478bd9Sstevel@tonic-gate slp--; 8367c478bd9Sstevel@tonic-gate row = 1; 8377c478bd9Sstevel@tonic-gate } 8387c478bd9Sstevel@tonic-gate else 8397c478bd9Sstevel@tonic-gate row = 0; 8407c478bd9Sstevel@tonic-gate 8417c478bd9Sstevel@tonic-gate nrows = (lp - slp - 1) / ncols + 1; 8427c478bd9Sstevel@tonic-gate for (i = 0; i < nrows; i++, row++) { 8437c478bd9Sstevel@tonic-gate for (col = 0; col < ncols; col++) { 8447c478bd9Sstevel@tonic-gate ep = slp + (nrows * col) + row; 8457c478bd9Sstevel@tonic-gate if (ep < lp) 8467c478bd9Sstevel@tonic-gate pentry(*ep); 8477c478bd9Sstevel@tonic-gate } 8487c478bd9Sstevel@tonic-gate new_line(); 8497c478bd9Sstevel@tonic-gate } 8507c478bd9Sstevel@tonic-gate } 8517c478bd9Sstevel@tonic-gate 8527c478bd9Sstevel@tonic-gate /* 8537c478bd9Sstevel@tonic-gate * print one output entry; 8547c478bd9Sstevel@tonic-gate * if uid/gid is not found in the appropriate 8557c478bd9Sstevel@tonic-gate * file(passwd/group), then print uid/gid instead of 8567c478bd9Sstevel@tonic-gate * user/group name; 8577c478bd9Sstevel@tonic-gate */ 8587c478bd9Sstevel@tonic-gate static void 8597c478bd9Sstevel@tonic-gate pentry(struct lbuf *ap) 8607c478bd9Sstevel@tonic-gate { 8617c478bd9Sstevel@tonic-gate struct lbuf *p; 8627c478bd9Sstevel@tonic-gate numbuf_t hbuf; 8637c478bd9Sstevel@tonic-gate char buf[BUFSIZ]; 8647c478bd9Sstevel@tonic-gate char *dmark = ""; /* Used if -p or -F option active */ 8657c478bd9Sstevel@tonic-gate char *cp; 8667c478bd9Sstevel@tonic-gate 8677c478bd9Sstevel@tonic-gate p = ap; 8687c478bd9Sstevel@tonic-gate column(); 8697c478bd9Sstevel@tonic-gate if (iflg) 8707c478bd9Sstevel@tonic-gate if (mflg && !lflg) 8717c478bd9Sstevel@tonic-gate curcol += printf("%llu ", (long long)p->lnum); 8727c478bd9Sstevel@tonic-gate else 8737c478bd9Sstevel@tonic-gate curcol += printf("%10llu ", (long long)p->lnum); 8747c478bd9Sstevel@tonic-gate if (sflg) 8757c478bd9Sstevel@tonic-gate curcol += printf((mflg && !lflg) ? "%lld " : 8767c478bd9Sstevel@tonic-gate (p->lblocks < 10000) ? "%4lld " : "%lld ", 8777c478bd9Sstevel@tonic-gate (p->ltype != 'b' && p->ltype != 'c') ? 8787c478bd9Sstevel@tonic-gate p->lblocks : 0LL); 8797c478bd9Sstevel@tonic-gate if (lflg) { 8807c478bd9Sstevel@tonic-gate (void) putchar(p->ltype); 8817c478bd9Sstevel@tonic-gate curcol++; 8827c478bd9Sstevel@tonic-gate pmode(p->lflags); 8837c478bd9Sstevel@tonic-gate 8847c478bd9Sstevel@tonic-gate /* ACL: additional access mode flag */ 8857c478bd9Sstevel@tonic-gate (void) putchar(p->acl); 8867c478bd9Sstevel@tonic-gate curcol++; 8877c478bd9Sstevel@tonic-gate 8887c478bd9Sstevel@tonic-gate curcol += printf("%3lu ", (ulong_t)p->lnl); 8897c478bd9Sstevel@tonic-gate if (oflg) 8907c478bd9Sstevel@tonic-gate if (!nflg) { 8917c478bd9Sstevel@tonic-gate cp = getname(p->luid); 8927c478bd9Sstevel@tonic-gate curcol += printf("%-8s ", cp); 8937c478bd9Sstevel@tonic-gate } else 8947c478bd9Sstevel@tonic-gate curcol += printf("%-8lu ", (ulong_t)p->luid); 8957c478bd9Sstevel@tonic-gate if (gflg) 8967c478bd9Sstevel@tonic-gate if (!nflg) { 8977c478bd9Sstevel@tonic-gate cp = getgroup(p->lgid); 8987c478bd9Sstevel@tonic-gate curcol += printf("%-8s ", cp); 8997c478bd9Sstevel@tonic-gate } else 9007c478bd9Sstevel@tonic-gate curcol += printf("%-8lu ", (ulong_t)p->lgid); 9017c478bd9Sstevel@tonic-gate if (p->ltype == 'b' || p->ltype == 'c') { 9027c478bd9Sstevel@tonic-gate curcol += printf("%3u, %2u", 9037c478bd9Sstevel@tonic-gate (uint_t)major((dev_t)p->lsize), 9047c478bd9Sstevel@tonic-gate (uint_t)minor((dev_t)p->lsize)); 9057c478bd9Sstevel@tonic-gate } else if (hflg && (p->lsize >= hscale)) { 9067c478bd9Sstevel@tonic-gate curcol += printf("%7s", 9077c478bd9Sstevel@tonic-gate number_to_scaled_string(hbuf, p->lsize, hscale)); 9087c478bd9Sstevel@tonic-gate } else { 9097c478bd9Sstevel@tonic-gate curcol += printf((p->lsize < (off_t)10000000) ? 9107c478bd9Sstevel@tonic-gate "%7lld" : "%lld", p->lsize); 9117c478bd9Sstevel@tonic-gate } 912da6c28aaSamw if (eflg) 913da6c28aaSamw format_time(FORMAT3, p->lmtime.tv_sec); 914da6c28aaSamw else if (Eflg) 9157c478bd9Sstevel@tonic-gate /* fill in nanoseconds first */ 916da6c28aaSamw format_etime(FORMAT4, p->lmtime.tv_sec, 917da6c28aaSamw p->lmtime.tv_nsec); 918da6c28aaSamw else { 9197c478bd9Sstevel@tonic-gate if ((p->lmtime.tv_sec < year) || 920da6c28aaSamw (p->lmtime.tv_sec > now)) 921da6c28aaSamw format_time(FORMAT1, p->lmtime.tv_sec); 922da6c28aaSamw else 923da6c28aaSamw format_time(FORMAT2, p->lmtime.tv_sec); 9247c478bd9Sstevel@tonic-gate } 925da6c28aaSamw /* format extended system attribute time */ 926da6c28aaSamw if (tmflg && crtm) 927da6c28aaSamw format_attrtime(p); 9287c478bd9Sstevel@tonic-gate 929da6c28aaSamw curcol += printf("%s", time_buf); 930da6c28aaSamw 931da6c28aaSamw } 9327c478bd9Sstevel@tonic-gate /* 9337c478bd9Sstevel@tonic-gate * prevent both "->" and trailing marks 9347c478bd9Sstevel@tonic-gate * from appearing 9357c478bd9Sstevel@tonic-gate */ 9367c478bd9Sstevel@tonic-gate 9377c478bd9Sstevel@tonic-gate if (pflg && p->ltype == 'd') 9387c478bd9Sstevel@tonic-gate dmark = "/"; 9397c478bd9Sstevel@tonic-gate 9407c478bd9Sstevel@tonic-gate if (Fflg && !(lflg && p->flinkto)) { 9417c478bd9Sstevel@tonic-gate if (p->ltype == 'd') 9427c478bd9Sstevel@tonic-gate dmark = "/"; 9437c478bd9Sstevel@tonic-gate else if (p->ltype == 'D') 9447c478bd9Sstevel@tonic-gate dmark = ">"; 9457c478bd9Sstevel@tonic-gate else if (p->ltype == 'p') 9467c478bd9Sstevel@tonic-gate dmark = "|"; 9477c478bd9Sstevel@tonic-gate else if (p->ltype == 'l') 9487c478bd9Sstevel@tonic-gate dmark = "@"; 9497c478bd9Sstevel@tonic-gate else if (p->ltype == 's') 9507c478bd9Sstevel@tonic-gate dmark = "="; 9517c478bd9Sstevel@tonic-gate else if (p->lflags & (S_IXUSR|S_IXGRP|S_IXOTH)) 9527c478bd9Sstevel@tonic-gate dmark = "*"; 9537c478bd9Sstevel@tonic-gate else 9547c478bd9Sstevel@tonic-gate dmark = ""; 9557c478bd9Sstevel@tonic-gate } 9567c478bd9Sstevel@tonic-gate 9577c478bd9Sstevel@tonic-gate if (lflg && p->flinkto) { 9587c478bd9Sstevel@tonic-gate (void) strncpy(buf, " -> ", 4); 9597c478bd9Sstevel@tonic-gate (void) strcpy(buf + 4, p->flinkto); 9607c478bd9Sstevel@tonic-gate dmark = buf; 9617c478bd9Sstevel@tonic-gate } 9627c478bd9Sstevel@tonic-gate if (p->lflags & ISARG) { 9637c478bd9Sstevel@tonic-gate if (qflg || bflg) 9647c478bd9Sstevel@tonic-gate pprintf(p->ln.namep, dmark); 9657c478bd9Sstevel@tonic-gate else { 9667c478bd9Sstevel@tonic-gate (void) printf("%s%s", p->ln.namep, dmark); 9677c478bd9Sstevel@tonic-gate curcol += strcol((unsigned char *)p->ln.namep); 9687c478bd9Sstevel@tonic-gate curcol += strcol((unsigned char *)dmark); 9697c478bd9Sstevel@tonic-gate } 9707c478bd9Sstevel@tonic-gate } else { 9717c478bd9Sstevel@tonic-gate if (qflg || bflg) 9727c478bd9Sstevel@tonic-gate pprintf(p->ln.lname, dmark); 9737c478bd9Sstevel@tonic-gate else { 9747c478bd9Sstevel@tonic-gate (void) printf("%s%s", p->ln.lname, dmark); 9757c478bd9Sstevel@tonic-gate curcol += strcol((unsigned char *)p->ln.lname); 9767c478bd9Sstevel@tonic-gate curcol += strcol((unsigned char *)dmark); 9777c478bd9Sstevel@tonic-gate } 9787c478bd9Sstevel@tonic-gate } 979fa9e4066Sahrens 980da6c28aaSamw /* Display extended system attributes */ 981da6c28aaSamw if (saflg) { 982da6c28aaSamw int i; 983da6c28aaSamw 984da6c28aaSamw new_line(); 985da6c28aaSamw (void) printf(" \t{"); 986da6c28aaSamw if (p->exttr != NULL) { 987da6c28aaSamw int k = 0; 988da6c28aaSamw for (i = 0; i < sacnt; i++) { 989da6c28aaSamw if (p->exttr[i].name != NULL) 990da6c28aaSamw k++; 991da6c28aaSamw } 992da6c28aaSamw for (i = 0; i < sacnt; i++) { 993da6c28aaSamw if (p->exttr[i].name != NULL) { 994da6c28aaSamw (void) printf("%s", p->exttr[i].name); 995da6c28aaSamw k--; 996da6c28aaSamw if (vopt && (k != 0)) 997da6c28aaSamw (void) printf(","); 998da6c28aaSamw } 999da6c28aaSamw } 1000da6c28aaSamw } 1001da6c28aaSamw (void) printf("}\n"); 1002da6c28aaSamw } 1003da6c28aaSamw /* Display file timestamps and extended system attribute timestamps */ 1004da6c28aaSamw if (tmflg && alltm) { 1005da6c28aaSamw new_line(); 1006da6c28aaSamw print_time(p); 1007da6c28aaSamw new_line(); 1008da6c28aaSamw } 1009fa9e4066Sahrens if (vflg) { 1010fa9e4066Sahrens new_line(); 1011fa9e4066Sahrens if (p->aclp) { 10125a5eeccaSmarks acl_printacl(p->aclp, num_cols, Vflg); 1013fa9e4066Sahrens } 1014fa9e4066Sahrens } 1015da6c28aaSamw /* Free extended system attribute lists */ 1016da6c28aaSamw if (saflg || tmflg) 1017da6c28aaSamw free_sysattr(p); 10187c478bd9Sstevel@tonic-gate } 10197c478bd9Sstevel@tonic-gate 10207c478bd9Sstevel@tonic-gate /* print various r,w,x permissions */ 10217c478bd9Sstevel@tonic-gate static void 10227c478bd9Sstevel@tonic-gate pmode(mode_t aflag) 10237c478bd9Sstevel@tonic-gate { 10247c478bd9Sstevel@tonic-gate /* these arrays are declared static to allow initializations */ 10257c478bd9Sstevel@tonic-gate static int m0[] = { 1, S_IRUSR, 'r', '-' }; 10267c478bd9Sstevel@tonic-gate static int m1[] = { 1, S_IWUSR, 'w', '-' }; 10277c478bd9Sstevel@tonic-gate static int m2[] = { 3, S_ISUID|S_IXUSR, 's', S_IXUSR, 10287c478bd9Sstevel@tonic-gate 'x', S_ISUID, 'S', '-' }; 10297c478bd9Sstevel@tonic-gate static int m3[] = { 1, S_IRGRP, 'r', '-' }; 10307c478bd9Sstevel@tonic-gate static int m4[] = { 1, S_IWGRP, 'w', '-' }; 10317c478bd9Sstevel@tonic-gate static int m5[] = { 4, S_ISGID|S_IXGRP, 's', S_IXGRP, 10327c478bd9Sstevel@tonic-gate 'x', S_ISGID|LS_NOTREG, 'S', 10337c478bd9Sstevel@tonic-gate #ifdef XPG4 10347c478bd9Sstevel@tonic-gate S_ISGID, 'L', '-'}; 10357c478bd9Sstevel@tonic-gate #else 10367c478bd9Sstevel@tonic-gate S_ISGID, 'l', '-'}; 10377c478bd9Sstevel@tonic-gate #endif 10387c478bd9Sstevel@tonic-gate static int m6[] = { 1, S_IROTH, 'r', '-' }; 10397c478bd9Sstevel@tonic-gate static int m7[] = { 1, S_IWOTH, 'w', '-' }; 10407c478bd9Sstevel@tonic-gate static int m8[] = { 3, S_ISVTX|S_IXOTH, 't', S_IXOTH, 10417c478bd9Sstevel@tonic-gate 'x', S_ISVTX, 'T', '-'}; 10427c478bd9Sstevel@tonic-gate 10437c478bd9Sstevel@tonic-gate static int *m[] = { m0, m1, m2, m3, m4, m5, m6, m7, m8}; 10447c478bd9Sstevel@tonic-gate 10457c478bd9Sstevel@tonic-gate int **mp; 10467c478bd9Sstevel@tonic-gate 10477c478bd9Sstevel@tonic-gate flags = aflag; 10487c478bd9Sstevel@tonic-gate for (mp = &m[0]; mp < &m[sizeof (m) / sizeof (m[0])]; mp++) 10497c478bd9Sstevel@tonic-gate selection(*mp); 10507c478bd9Sstevel@tonic-gate } 10517c478bd9Sstevel@tonic-gate 10527c478bd9Sstevel@tonic-gate static void 10537c478bd9Sstevel@tonic-gate selection(int *pairp) 10547c478bd9Sstevel@tonic-gate { 10557c478bd9Sstevel@tonic-gate int n; 10567c478bd9Sstevel@tonic-gate 10577c478bd9Sstevel@tonic-gate n = *pairp++; 10587c478bd9Sstevel@tonic-gate while (n-->0) { 10597c478bd9Sstevel@tonic-gate if ((flags & *pairp) == *pairp) { 10607c478bd9Sstevel@tonic-gate pairp++; 10617c478bd9Sstevel@tonic-gate break; 10627c478bd9Sstevel@tonic-gate } else { 10637c478bd9Sstevel@tonic-gate pairp += 2; 10647c478bd9Sstevel@tonic-gate } 10657c478bd9Sstevel@tonic-gate } 10667c478bd9Sstevel@tonic-gate (void) putchar(*pairp); 10677c478bd9Sstevel@tonic-gate curcol++; 10687c478bd9Sstevel@tonic-gate } 10697c478bd9Sstevel@tonic-gate 10707c478bd9Sstevel@tonic-gate /* 10717c478bd9Sstevel@tonic-gate * column: get to the beginning of the next column. 10727c478bd9Sstevel@tonic-gate */ 10737c478bd9Sstevel@tonic-gate static void 10747c478bd9Sstevel@tonic-gate column(void) 10757c478bd9Sstevel@tonic-gate { 10767c478bd9Sstevel@tonic-gate if (curcol == 0) 10777c478bd9Sstevel@tonic-gate return; 10787c478bd9Sstevel@tonic-gate if (mflg) { 10797c478bd9Sstevel@tonic-gate (void) putc(',', stdout); 10807c478bd9Sstevel@tonic-gate curcol++; 10817c478bd9Sstevel@tonic-gate if (curcol + colwidth + 2 > num_cols) { 10827c478bd9Sstevel@tonic-gate (void) putc('\n', stdout); 10837c478bd9Sstevel@tonic-gate curcol = 0; 10847c478bd9Sstevel@tonic-gate return; 10857c478bd9Sstevel@tonic-gate } 10867c478bd9Sstevel@tonic-gate (void) putc(' ', stdout); 10877c478bd9Sstevel@tonic-gate curcol++; 10887c478bd9Sstevel@tonic-gate return; 10897c478bd9Sstevel@tonic-gate } 10907c478bd9Sstevel@tonic-gate if (Cflg == 0) { 10917c478bd9Sstevel@tonic-gate (void) putc('\n', stdout); 10927c478bd9Sstevel@tonic-gate curcol = 0; 10937c478bd9Sstevel@tonic-gate return; 10947c478bd9Sstevel@tonic-gate } 10957c478bd9Sstevel@tonic-gate if ((curcol / colwidth + 2) * colwidth > num_cols) { 10967c478bd9Sstevel@tonic-gate (void) putc('\n', stdout); 10977c478bd9Sstevel@tonic-gate curcol = 0; 10987c478bd9Sstevel@tonic-gate return; 10997c478bd9Sstevel@tonic-gate } 11007c478bd9Sstevel@tonic-gate do { 11017c478bd9Sstevel@tonic-gate (void) putc(' ', stdout); 11027c478bd9Sstevel@tonic-gate curcol++; 11037c478bd9Sstevel@tonic-gate } while (curcol % colwidth); 11047c478bd9Sstevel@tonic-gate } 11057c478bd9Sstevel@tonic-gate 11067c478bd9Sstevel@tonic-gate static void 11077c478bd9Sstevel@tonic-gate new_line(void) 11087c478bd9Sstevel@tonic-gate { 11097c478bd9Sstevel@tonic-gate if (curcol) { 11107c478bd9Sstevel@tonic-gate first = 0; 11117c478bd9Sstevel@tonic-gate (void) putc('\n', stdout); 11127c478bd9Sstevel@tonic-gate curcol = 0; 11137c478bd9Sstevel@tonic-gate } 11147c478bd9Sstevel@tonic-gate } 11157c478bd9Sstevel@tonic-gate 11167c478bd9Sstevel@tonic-gate /* 11177c478bd9Sstevel@tonic-gate * read each filename in directory dir and store its 11187c478bd9Sstevel@tonic-gate * status in flist[nfiles] 11197c478bd9Sstevel@tonic-gate * use makename() to form pathname dir/filename; 11207c478bd9Sstevel@tonic-gate */ 11217c478bd9Sstevel@tonic-gate static void 11227c478bd9Sstevel@tonic-gate rddir(char *dir, struct ditem *myinfo) 11237c478bd9Sstevel@tonic-gate { 11247c478bd9Sstevel@tonic-gate struct dirent *dentry; 11257c478bd9Sstevel@tonic-gate DIR *dirf; 11267c478bd9Sstevel@tonic-gate int j; 11277c478bd9Sstevel@tonic-gate struct lbuf *ep; 11287c478bd9Sstevel@tonic-gate int width; 11297c478bd9Sstevel@tonic-gate 11307c478bd9Sstevel@tonic-gate if ((dirf = opendir(dir)) == NULL) { 11317c478bd9Sstevel@tonic-gate (void) fflush(stdout); 11327c478bd9Sstevel@tonic-gate perror(dir); 11337c478bd9Sstevel@tonic-gate err = 2; 11347c478bd9Sstevel@tonic-gate return; 11357c478bd9Sstevel@tonic-gate } else { 11367c478bd9Sstevel@tonic-gate tblocks = 0; 11377c478bd9Sstevel@tonic-gate for (;;) { 11387c478bd9Sstevel@tonic-gate errno = 0; 11397c478bd9Sstevel@tonic-gate if ((dentry = readdir(dirf)) == NULL) 11407c478bd9Sstevel@tonic-gate break; 11417c478bd9Sstevel@tonic-gate if (aflg == 0 && dentry->d_name[0] == '.' && 11427c478bd9Sstevel@tonic-gate (Aflg == 0 || 11437c478bd9Sstevel@tonic-gate dentry->d_name[1] == '\0' || 11447c478bd9Sstevel@tonic-gate dentry->d_name[1] == '.' && 11457c478bd9Sstevel@tonic-gate dentry->d_name[2] == '\0')) 11467c478bd9Sstevel@tonic-gate /* 11477c478bd9Sstevel@tonic-gate * check for directory items '.', '..', 11487c478bd9Sstevel@tonic-gate * and items without valid inode-number; 11497c478bd9Sstevel@tonic-gate */ 11507c478bd9Sstevel@tonic-gate continue; 11517c478bd9Sstevel@tonic-gate 11527c478bd9Sstevel@tonic-gate if (Cflg || mflg) { 11537c478bd9Sstevel@tonic-gate width = strcol((unsigned char *)dentry->d_name); 11547c478bd9Sstevel@tonic-gate if (width > filewidth) 11557c478bd9Sstevel@tonic-gate filewidth = width; 11567c478bd9Sstevel@tonic-gate } 11577c478bd9Sstevel@tonic-gate ep = gstat(makename(dir, dentry->d_name), 0, myinfo); 11587c478bd9Sstevel@tonic-gate if (ep == NULL) { 11597c478bd9Sstevel@tonic-gate if (nomocore) 1160da6c28aaSamw exit(2); 11617c478bd9Sstevel@tonic-gate continue; 11627c478bd9Sstevel@tonic-gate } else { 11637c478bd9Sstevel@tonic-gate ep->lnum = dentry->d_ino; 11647c478bd9Sstevel@tonic-gate for (j = 0; dentry->d_name[j] != '\0'; j++) 11657c478bd9Sstevel@tonic-gate ep->ln.lname[j] = dentry->d_name[j]; 11667c478bd9Sstevel@tonic-gate ep->ln.lname[j] = '\0'; 11677c478bd9Sstevel@tonic-gate } 11687c478bd9Sstevel@tonic-gate } 11697c478bd9Sstevel@tonic-gate if (errno) { 11707c478bd9Sstevel@tonic-gate int sav_errno = errno; 11717c478bd9Sstevel@tonic-gate 11727c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 11737c478bd9Sstevel@tonic-gate gettext("ls: error reading directory %s: %s\n"), 11747c478bd9Sstevel@tonic-gate dir, strerror(sav_errno)); 11757c478bd9Sstevel@tonic-gate } 11767c478bd9Sstevel@tonic-gate (void) closedir(dirf); 11777c478bd9Sstevel@tonic-gate colwidth = fixedwidth + filewidth; 11787c478bd9Sstevel@tonic-gate } 11797c478bd9Sstevel@tonic-gate } 11807c478bd9Sstevel@tonic-gate 11817c478bd9Sstevel@tonic-gate /* 11827c478bd9Sstevel@tonic-gate * Attaching a link to an inode's ancestors. Search 11837c478bd9Sstevel@tonic-gate * through the ancestors to check for cycles (an inode which 11847c478bd9Sstevel@tonic-gate * we have already tracked in this inodes ancestry). If a cycle 11857c478bd9Sstevel@tonic-gate * is detected, set the exit code and record the fact so that 11867c478bd9Sstevel@tonic-gate * it is reported at the right time when printing the directory. 11877c478bd9Sstevel@tonic-gate * In addition, set the exit code. Note: If the -a flag was 11887c478bd9Sstevel@tonic-gate * specified, we don't want to check for cycles for directories 11897c478bd9Sstevel@tonic-gate * ending in '/.' or '/..' unless they were specified on the 11907c478bd9Sstevel@tonic-gate * command line. 11917c478bd9Sstevel@tonic-gate */ 11927c478bd9Sstevel@tonic-gate static void 11937c478bd9Sstevel@tonic-gate record_ancestry(char *file, struct stat *pstatb, struct lbuf *rep, 11947c478bd9Sstevel@tonic-gate int argfl, struct ditem *myparent) 11957c478bd9Sstevel@tonic-gate { 11967c478bd9Sstevel@tonic-gate size_t file_len; 11977c478bd9Sstevel@tonic-gate struct ditem *myinfo; 11987c478bd9Sstevel@tonic-gate struct ditem *tptr; 11997c478bd9Sstevel@tonic-gate 12007c478bd9Sstevel@tonic-gate file_len = strlen(file); 12017c478bd9Sstevel@tonic-gate if (!aflg || argfl || (NOTWORKINGDIR(file, file_len) && 12027c478bd9Sstevel@tonic-gate NOTPARENTDIR(file, file_len))) { 12037c478bd9Sstevel@tonic-gate /* 12047c478bd9Sstevel@tonic-gate * Add this inode's ancestry 12057c478bd9Sstevel@tonic-gate * info and insert it into the 12067c478bd9Sstevel@tonic-gate * ancestry list by pointing 12077c478bd9Sstevel@tonic-gate * back to its parent. We save 12087c478bd9Sstevel@tonic-gate * it (in rep) with the other info 12097c478bd9Sstevel@tonic-gate * we're gathering for this inode. 12107c478bd9Sstevel@tonic-gate */ 12117c478bd9Sstevel@tonic-gate if ((myinfo = malloc( 12127c478bd9Sstevel@tonic-gate sizeof (struct ditem))) == NULL) { 12137c478bd9Sstevel@tonic-gate perror("ls"); 12147c478bd9Sstevel@tonic-gate exit(2); 12157c478bd9Sstevel@tonic-gate } 12167c478bd9Sstevel@tonic-gate myinfo->dev = pstatb->st_dev; 12177c478bd9Sstevel@tonic-gate myinfo->ino = pstatb->st_ino; 12187c478bd9Sstevel@tonic-gate myinfo->parent = myparent; 12197c478bd9Sstevel@tonic-gate rep->ancinfo = myinfo; 12207c478bd9Sstevel@tonic-gate 12217c478bd9Sstevel@tonic-gate /* 12227c478bd9Sstevel@tonic-gate * If this node has the same device id and 12237c478bd9Sstevel@tonic-gate * inode number of one of its ancestors, 12247c478bd9Sstevel@tonic-gate * then we've detected a cycle. 12257c478bd9Sstevel@tonic-gate */ 12267c478bd9Sstevel@tonic-gate if (myparent != NULL) { 12277c478bd9Sstevel@tonic-gate for (tptr = myparent; tptr->parent != NULL; 12287c478bd9Sstevel@tonic-gate tptr = tptr->parent) { 12297c478bd9Sstevel@tonic-gate if ((tptr->dev == pstatb->st_dev) && 12307c478bd9Sstevel@tonic-gate (tptr->ino == pstatb->st_ino)) { 12317c478bd9Sstevel@tonic-gate /* 12327c478bd9Sstevel@tonic-gate * Cycle detected for this 12337c478bd9Sstevel@tonic-gate * directory. Record the fact 12347c478bd9Sstevel@tonic-gate * it is a cycle so we don't 12357c478bd9Sstevel@tonic-gate * try to process this 12367c478bd9Sstevel@tonic-gate * directory as we are 12377c478bd9Sstevel@tonic-gate * walking through the 12387c478bd9Sstevel@tonic-gate * list of directories. 12397c478bd9Sstevel@tonic-gate */ 12407c478bd9Sstevel@tonic-gate rep->cycle = 1; 12417c478bd9Sstevel@tonic-gate err = 2; 12427c478bd9Sstevel@tonic-gate break; 12437c478bd9Sstevel@tonic-gate } 12447c478bd9Sstevel@tonic-gate } 12457c478bd9Sstevel@tonic-gate } 12467c478bd9Sstevel@tonic-gate } 12477c478bd9Sstevel@tonic-gate } 12487c478bd9Sstevel@tonic-gate 12497c478bd9Sstevel@tonic-gate /* 125064d425a7Sny155746 * Do re-calculate the mode for group for ACE_T type of acls. 125164d425a7Sny155746 * This is because, if the server's FS happens to be UFS, supporting 125264d425a7Sny155746 * POSIX ACL's, then it does a special calculation of group mode 125364d425a7Sny155746 * to be the bitwise OR of CLASS_OBJ and GROUP_OBJ (see PSARC/2001/717.) 125464d425a7Sny155746 * 125564d425a7Sny155746 * This algorithm is from the NFSv4 ACL Draft. Here a part of that 125664d425a7Sny155746 * algorithm is used for the group mode calculation only. 125764d425a7Sny155746 * What is modified here from the algorithm is that only the 125864d425a7Sny155746 * entries with flags ACE_GROUP are considered. For each entry 125964d425a7Sny155746 * with ACE_GROUP flag, the first occurance of a specific access 126064d425a7Sny155746 * is checked if it is allowed. 1261e2442894Sny155746 * We are not interested in perms for user and other, as they 126264d425a7Sny155746 * were taken from st_mode value. 126364d425a7Sny155746 * We are not interested in a_who field of ACE, as we need just 126464d425a7Sny155746 * unix mode bits for the group. 126564d425a7Sny155746 */ 1266e2442894Sny155746 1267e2442894Sny155746 #define OWNED_GROUP (ACE_GROUP | ACE_IDENTIFIER_GROUP) 1268e2442894Sny155746 #define IS_TYPE_ALLOWED(type) ((type) == ACE_ACCESS_ALLOWED_ACE_TYPE) 1269e2442894Sny155746 127064d425a7Sny155746 int 127164d425a7Sny155746 grp_mask_to_mode(acl_t *acep) 127264d425a7Sny155746 { 127364d425a7Sny155746 int mode = 0, seen = 0; 127464d425a7Sny155746 int acecnt; 1275e2442894Sny155746 int flags; 127664d425a7Sny155746 ace_t *ap; 127764d425a7Sny155746 127864d425a7Sny155746 acecnt = acl_cnt(acep); 127964d425a7Sny155746 for (ap = (ace_t *)acl_data(acep); acecnt--; ap++) { 1280e2442894Sny155746 1281e2442894Sny155746 if (ap->a_type != ACE_ACCESS_ALLOWED_ACE_TYPE && 1282e2442894Sny155746 ap->a_type != ACE_ACCESS_DENIED_ACE_TYPE) 1283e2442894Sny155746 continue; 1284e2442894Sny155746 1285e2442894Sny155746 if (ap->a_flags & ACE_INHERIT_ONLY_ACE) 1286e2442894Sny155746 continue; 1287e2442894Sny155746 1288e2442894Sny155746 /* 1289e2442894Sny155746 * if it is first group@ or first everyone@ 1290e2442894Sny155746 * for each of read, write and execute, then 1291e2442894Sny155746 * that will be the group mode bit. 1292e2442894Sny155746 */ 1293e2442894Sny155746 flags = ap->a_flags & ACE_TYPE_FLAGS; 1294e2442894Sny155746 if (flags == OWNED_GROUP || flags == ACE_EVERYONE) { 129564d425a7Sny155746 if (ap->a_access_mask & ACE_READ_DATA) { 129664d425a7Sny155746 if (!(seen & S_IRGRP)) { 129764d425a7Sny155746 seen |= S_IRGRP; 1298e2442894Sny155746 if (IS_TYPE_ALLOWED(ap->a_type)) 129964d425a7Sny155746 mode |= S_IRGRP; 130064d425a7Sny155746 } 130164d425a7Sny155746 } 130264d425a7Sny155746 if (ap->a_access_mask & ACE_WRITE_DATA) { 130364d425a7Sny155746 if (!(seen & S_IWGRP)) { 130464d425a7Sny155746 seen |= S_IWGRP; 1305e2442894Sny155746 if (IS_TYPE_ALLOWED(ap->a_type)) 130664d425a7Sny155746 mode |= S_IWGRP; 130764d425a7Sny155746 } 130864d425a7Sny155746 } 130964d425a7Sny155746 if (ap->a_access_mask & ACE_EXECUTE) { 131064d425a7Sny155746 if (!(seen & S_IXGRP)) { 131164d425a7Sny155746 seen |= S_IXGRP; 1312e2442894Sny155746 if (IS_TYPE_ALLOWED(ap->a_type)) 131364d425a7Sny155746 mode |= S_IXGRP; 131464d425a7Sny155746 } 131564d425a7Sny155746 } 131664d425a7Sny155746 } 131764d425a7Sny155746 } 131864d425a7Sny155746 return (mode); 131964d425a7Sny155746 } 132064d425a7Sny155746 132164d425a7Sny155746 /* 13227c478bd9Sstevel@tonic-gate * get status of file and recomputes tblocks; 13237c478bd9Sstevel@tonic-gate * argfl = 1 if file is a name in ls-command and = 0 13247c478bd9Sstevel@tonic-gate * for filename in a directory whose name is an 13257c478bd9Sstevel@tonic-gate * argument in the command; 13267c478bd9Sstevel@tonic-gate * stores a pointer in flist[nfiles] and 13277c478bd9Sstevel@tonic-gate * returns that pointer; 13287c478bd9Sstevel@tonic-gate * returns NULL if failed; 13297c478bd9Sstevel@tonic-gate */ 13307c478bd9Sstevel@tonic-gate static struct lbuf * 13317c478bd9Sstevel@tonic-gate gstat(char *file, int argfl, struct ditem *myparent) 13327c478bd9Sstevel@tonic-gate { 13337c478bd9Sstevel@tonic-gate struct stat statb, statb1; 13347c478bd9Sstevel@tonic-gate struct lbuf *rep; 13357c478bd9Sstevel@tonic-gate char buf[BUFSIZ]; 13367c478bd9Sstevel@tonic-gate ssize_t cc; 13377c478bd9Sstevel@tonic-gate int (*statf)() = ((Lflg) || (Hflg && argfl)) ? stat : lstat; 13387c478bd9Sstevel@tonic-gate int aclcnt; 1339fa9e4066Sahrens int error; 13407c478bd9Sstevel@tonic-gate aclent_t *tp; 13417c478bd9Sstevel@tonic-gate o_mode_t groupperm, mask; 13427c478bd9Sstevel@tonic-gate int grouppermfound, maskfound; 13437c478bd9Sstevel@tonic-gate 13447c478bd9Sstevel@tonic-gate if (nomocore) 13457c478bd9Sstevel@tonic-gate return (NULL); 13467c478bd9Sstevel@tonic-gate 13477c478bd9Sstevel@tonic-gate if (nfiles >= maxfils) { 13487c478bd9Sstevel@tonic-gate /* 13497c478bd9Sstevel@tonic-gate * all flist/lbuf pair assigned files, time to get some 13507c478bd9Sstevel@tonic-gate * more space 13517c478bd9Sstevel@tonic-gate */ 13527c478bd9Sstevel@tonic-gate maxfils += quantn; 13537c478bd9Sstevel@tonic-gate if (((flist = realloc(flist, 13547c478bd9Sstevel@tonic-gate maxfils * sizeof (struct lbuf *))) == NULL) || 13557c478bd9Sstevel@tonic-gate ((nxtlbf = malloc(quantn * 13567c478bd9Sstevel@tonic-gate sizeof (struct lbuf))) == NULL)) { 13577c478bd9Sstevel@tonic-gate perror("ls"); 13587c478bd9Sstevel@tonic-gate nomocore = 1; 13597c478bd9Sstevel@tonic-gate return (NULL); 13607c478bd9Sstevel@tonic-gate } 13617c478bd9Sstevel@tonic-gate } 13627c478bd9Sstevel@tonic-gate 13637c478bd9Sstevel@tonic-gate /* 13647c478bd9Sstevel@tonic-gate * nfiles is reset to nargs for each directory 13657c478bd9Sstevel@tonic-gate * that is given as an argument maxn is checked 13667c478bd9Sstevel@tonic-gate * to prevent the assignment of an lbuf to a flist entry 13677c478bd9Sstevel@tonic-gate * that already has one assigned. 13687c478bd9Sstevel@tonic-gate */ 13697c478bd9Sstevel@tonic-gate if (nfiles >= maxn) { 13707c478bd9Sstevel@tonic-gate rep = nxtlbf++; 13717c478bd9Sstevel@tonic-gate flist[nfiles++] = rep; 13727c478bd9Sstevel@tonic-gate maxn = nfiles; 13737c478bd9Sstevel@tonic-gate } else { 13747c478bd9Sstevel@tonic-gate rep = flist[nfiles++]; 13757c478bd9Sstevel@tonic-gate } 137644f31f13Sbasabi 137744f31f13Sbasabi /* Initialize */ 137844f31f13Sbasabi 13797c478bd9Sstevel@tonic-gate rep->lflags = (mode_t)0; 13807c478bd9Sstevel@tonic-gate rep->flinkto = NULL; 13817c478bd9Sstevel@tonic-gate rep->cycle = 0; 138244f31f13Sbasabi rep->lat.tv_sec = time(NULL); 138344f31f13Sbasabi rep->lat.tv_nsec = 0; 138444f31f13Sbasabi rep->lct.tv_sec = time(NULL); 138544f31f13Sbasabi rep->lct.tv_nsec = 0; 138644f31f13Sbasabi rep->lmt.tv_sec = time(NULL); 138744f31f13Sbasabi rep->lmt.tv_nsec = 0; 138844f31f13Sbasabi rep->exttr = NULL; 138944f31f13Sbasabi rep->extm = NULL; 139044f31f13Sbasabi 13917c478bd9Sstevel@tonic-gate if (argfl || statreq) { 13927c478bd9Sstevel@tonic-gate int doacl; 13937c478bd9Sstevel@tonic-gate 13947c478bd9Sstevel@tonic-gate if (lflg) 13957c478bd9Sstevel@tonic-gate doacl = 1; 13967c478bd9Sstevel@tonic-gate else 13977c478bd9Sstevel@tonic-gate doacl = 0; 139844f31f13Sbasabi 13997c478bd9Sstevel@tonic-gate if ((*statf)(file, &statb) < 0) { 14007c478bd9Sstevel@tonic-gate if (argfl || errno != ENOENT || 14017c478bd9Sstevel@tonic-gate (Lflg && lstat(file, &statb) == 0)) { 14027c478bd9Sstevel@tonic-gate /* 14037c478bd9Sstevel@tonic-gate * Avoid race between readdir and lstat. 14047c478bd9Sstevel@tonic-gate * Print error message in case of dangling link. 14057c478bd9Sstevel@tonic-gate */ 14067c478bd9Sstevel@tonic-gate perror(file); 14077c478bd9Sstevel@tonic-gate } 14087c478bd9Sstevel@tonic-gate nfiles--; 14097c478bd9Sstevel@tonic-gate return (NULL); 14107c478bd9Sstevel@tonic-gate } 14117c478bd9Sstevel@tonic-gate 14127c478bd9Sstevel@tonic-gate /* 14137c478bd9Sstevel@tonic-gate * If -H was specified, and the file linked to was 14147c478bd9Sstevel@tonic-gate * not a directory, then we need to get the info 14157c478bd9Sstevel@tonic-gate * for the symlink itself. 14167c478bd9Sstevel@tonic-gate */ 14177c478bd9Sstevel@tonic-gate if ((Hflg) && (argfl) && 14187c478bd9Sstevel@tonic-gate ((statb.st_mode & S_IFMT) != S_IFDIR)) { 14197c478bd9Sstevel@tonic-gate if (lstat(file, &statb) < 0) { 14207c478bd9Sstevel@tonic-gate perror(file); 14217c478bd9Sstevel@tonic-gate } 14227c478bd9Sstevel@tonic-gate } 14237c478bd9Sstevel@tonic-gate 14247c478bd9Sstevel@tonic-gate rep->lnum = statb.st_ino; 14257c478bd9Sstevel@tonic-gate rep->lsize = statb.st_size; 14267c478bd9Sstevel@tonic-gate rep->lblocks = statb.st_blocks; 14277c478bd9Sstevel@tonic-gate switch (statb.st_mode & S_IFMT) { 14287c478bd9Sstevel@tonic-gate case S_IFDIR: 14297c478bd9Sstevel@tonic-gate rep->ltype = 'd'; 14307c478bd9Sstevel@tonic-gate if (Rflg) { 14317c478bd9Sstevel@tonic-gate record_ancestry(file, &statb, rep, 14327c478bd9Sstevel@tonic-gate argfl, myparent); 14337c478bd9Sstevel@tonic-gate } 14347c478bd9Sstevel@tonic-gate break; 14357c478bd9Sstevel@tonic-gate case S_IFBLK: 14367c478bd9Sstevel@tonic-gate rep->ltype = 'b'; 14377c478bd9Sstevel@tonic-gate rep->lsize = (off_t)statb.st_rdev; 14387c478bd9Sstevel@tonic-gate break; 14397c478bd9Sstevel@tonic-gate case S_IFCHR: 14407c478bd9Sstevel@tonic-gate rep->ltype = 'c'; 14417c478bd9Sstevel@tonic-gate rep->lsize = (off_t)statb.st_rdev; 14427c478bd9Sstevel@tonic-gate break; 14437c478bd9Sstevel@tonic-gate case S_IFIFO: 14447c478bd9Sstevel@tonic-gate rep->ltype = 'p'; 14457c478bd9Sstevel@tonic-gate break; 14467c478bd9Sstevel@tonic-gate case S_IFSOCK: 14477c478bd9Sstevel@tonic-gate rep->ltype = 's'; 14487c478bd9Sstevel@tonic-gate rep->lsize = 0; 14497c478bd9Sstevel@tonic-gate break; 14507c478bd9Sstevel@tonic-gate case S_IFLNK: 14517c478bd9Sstevel@tonic-gate /* symbolic links may not have ACLs, so elide acl() */ 14527c478bd9Sstevel@tonic-gate if ((Lflg == 0) || (Hflg == 0) || 14537c478bd9Sstevel@tonic-gate ((Hflg) && (!argfl))) { 14547c478bd9Sstevel@tonic-gate doacl = 0; 14557c478bd9Sstevel@tonic-gate } 14567c478bd9Sstevel@tonic-gate rep->ltype = 'l'; 14577c478bd9Sstevel@tonic-gate if (lflg) { 14587c478bd9Sstevel@tonic-gate cc = readlink(file, buf, BUFSIZ); 14597c478bd9Sstevel@tonic-gate if (cc >= 0) { 14607c478bd9Sstevel@tonic-gate 14617c478bd9Sstevel@tonic-gate /* 14627c478bd9Sstevel@tonic-gate * follow the symbolic link 14637c478bd9Sstevel@tonic-gate * to generate the appropriate 14647c478bd9Sstevel@tonic-gate * Fflg marker for the object 14657c478bd9Sstevel@tonic-gate * eg, /bin -> /sym/bin/ 14667c478bd9Sstevel@tonic-gate */ 14677c478bd9Sstevel@tonic-gate if ((Fflg || pflg) && 14687c478bd9Sstevel@tonic-gate (stat(file, &statb1) >= 0)) { 14697c478bd9Sstevel@tonic-gate switch (statb1.st_mode & 14707c478bd9Sstevel@tonic-gate S_IFMT) { 14717c478bd9Sstevel@tonic-gate case S_IFDIR: 14727c478bd9Sstevel@tonic-gate buf[cc++] = '/'; 14737c478bd9Sstevel@tonic-gate break; 14747c478bd9Sstevel@tonic-gate case S_IFSOCK: 14757c478bd9Sstevel@tonic-gate buf[cc++] = '='; 14767c478bd9Sstevel@tonic-gate break; 14772236845bSakaplan case S_IFDOOR: 14782236845bSakaplan buf[cc++] = '>'; 14792236845bSakaplan break; 14802236845bSakaplan case S_IFIFO: 14812236845bSakaplan buf[cc++] = '|'; 14822236845bSakaplan break; 14837c478bd9Sstevel@tonic-gate default: 14847c478bd9Sstevel@tonic-gate if ((statb1.st_mode & 14857c478bd9Sstevel@tonic-gate ~S_IFMT) & 14867c478bd9Sstevel@tonic-gate (S_IXUSR|S_IXGRP| 14877c478bd9Sstevel@tonic-gate S_IXOTH)) 14887c478bd9Sstevel@tonic-gate buf[cc++] = '*'; 14897c478bd9Sstevel@tonic-gate break; 14907c478bd9Sstevel@tonic-gate } 14917c478bd9Sstevel@tonic-gate } 14927c478bd9Sstevel@tonic-gate buf[cc] = '\0'; 14937c478bd9Sstevel@tonic-gate rep->flinkto = strdup(buf); 14947c478bd9Sstevel@tonic-gate } 14957c478bd9Sstevel@tonic-gate break; 14967c478bd9Sstevel@tonic-gate } 14977c478bd9Sstevel@tonic-gate 14987c478bd9Sstevel@tonic-gate /* 14997c478bd9Sstevel@tonic-gate * ls /sym behaves differently from ls /sym/ 15007c478bd9Sstevel@tonic-gate * when /sym is a symbolic link. This is fixed 15017c478bd9Sstevel@tonic-gate * when explicit arguments are specified. 15027c478bd9Sstevel@tonic-gate */ 15037c478bd9Sstevel@tonic-gate 15047c478bd9Sstevel@tonic-gate #ifdef XPG6 15057c478bd9Sstevel@tonic-gate /* Do not follow a symlink when -F is specified */ 15067c478bd9Sstevel@tonic-gate if ((!argfl) || (argfl && Fflg) || 15077c478bd9Sstevel@tonic-gate (stat(file, &statb1) < 0)) 15087c478bd9Sstevel@tonic-gate #else 15097c478bd9Sstevel@tonic-gate /* Follow a symlink when -F is specified */ 15107c478bd9Sstevel@tonic-gate if (!argfl || stat(file, &statb1) < 0) 15117c478bd9Sstevel@tonic-gate #endif /* XPG6 */ 15127c478bd9Sstevel@tonic-gate break; 15137c478bd9Sstevel@tonic-gate if ((statb1.st_mode & S_IFMT) == S_IFDIR) { 15147c478bd9Sstevel@tonic-gate statb = statb1; 15157c478bd9Sstevel@tonic-gate rep->ltype = 'd'; 15167c478bd9Sstevel@tonic-gate rep->lsize = statb1.st_size; 15177c478bd9Sstevel@tonic-gate if (Rflg) { 15187c478bd9Sstevel@tonic-gate record_ancestry(file, &statb, rep, 15197c478bd9Sstevel@tonic-gate argfl, myparent); 15207c478bd9Sstevel@tonic-gate } 15217c478bd9Sstevel@tonic-gate } 15227c478bd9Sstevel@tonic-gate break; 15237c478bd9Sstevel@tonic-gate case S_IFDOOR: 15247c478bd9Sstevel@tonic-gate rep->ltype = 'D'; 15257c478bd9Sstevel@tonic-gate break; 15267c478bd9Sstevel@tonic-gate case S_IFREG: 15277c478bd9Sstevel@tonic-gate rep->ltype = '-'; 15287c478bd9Sstevel@tonic-gate break; 15297c478bd9Sstevel@tonic-gate case S_IFPORT: 15307c478bd9Sstevel@tonic-gate rep->ltype = 'P'; 15317c478bd9Sstevel@tonic-gate break; 15327c478bd9Sstevel@tonic-gate default: 15337c478bd9Sstevel@tonic-gate rep->ltype = '?'; 15347c478bd9Sstevel@tonic-gate break; 15357c478bd9Sstevel@tonic-gate } 15367c478bd9Sstevel@tonic-gate rep->lflags = statb.st_mode & ~S_IFMT; 15377c478bd9Sstevel@tonic-gate 15387c478bd9Sstevel@tonic-gate if (!S_ISREG(statb.st_mode)) 15397c478bd9Sstevel@tonic-gate rep->lflags |= LS_NOTREG; 15407c478bd9Sstevel@tonic-gate 154144f31f13Sbasabi rep->luid = statb.st_uid; 154244f31f13Sbasabi rep->lgid = statb.st_gid; 154344f31f13Sbasabi rep->lnl = statb.st_nlink; 154444f31f13Sbasabi if (uflg || (tmflg && atm)) 154544f31f13Sbasabi rep->lmtime = statb.st_atim; 154644f31f13Sbasabi else if (cflg || (tmflg && ctm)) 154744f31f13Sbasabi rep->lmtime = statb.st_ctim; 154844f31f13Sbasabi else 154944f31f13Sbasabi rep->lmtime = statb.st_mtim; 155044f31f13Sbasabi rep->lat = statb.st_atim; 155144f31f13Sbasabi rep->lct = statb.st_ctim; 155244f31f13Sbasabi rep->lmt = statb.st_mtim; 155344f31f13Sbasabi 15547c478bd9Sstevel@tonic-gate /* ACL: check acl entries count */ 15557c478bd9Sstevel@tonic-gate if (doacl) { 15567c478bd9Sstevel@tonic-gate 1557fa9e4066Sahrens error = acl_get(file, 0, &rep->aclp); 1558fa9e4066Sahrens if (error) { 1559fa9e4066Sahrens (void) fprintf(stderr, 1560fa9e4066Sahrens gettext("ls: can't read ACL on %s: %s\n"), 1561fa9e4066Sahrens file, acl_strerror(error)); 156244f31f13Sbasabi rep->acl = ' '; 1563*56798e90Sbasabi acl_err++; 156444f31f13Sbasabi return (rep); 15657c478bd9Sstevel@tonic-gate } 15667c478bd9Sstevel@tonic-gate 1567fa9e4066Sahrens rep->acl = ' '; 1568fa9e4066Sahrens 1569fa9e4066Sahrens if (rep->aclp && 1570fa9e4066Sahrens ((acl_flags(rep->aclp) & ACL_IS_TRIVIAL) == 0)) { 1571fa9e4066Sahrens rep->acl = '+'; 15727c478bd9Sstevel@tonic-gate /* 1573fa9e4066Sahrens * Special handling for ufs aka aclent_t ACL's 1574fa9e4066Sahrens */ 157564d425a7Sny155746 if (acl_type(rep->aclp) == ACLENT_T) { 1576fa9e4066Sahrens /* 1577fa9e4066Sahrens * For files with non-trivial acls, the 1578fa9e4066Sahrens * effective group permissions are the 1579fa9e4066Sahrens * intersection of the GROUP_OBJ value 1580fa9e4066Sahrens * and the CLASS_OBJ (acl mask) value. 1581fa9e4066Sahrens * Determine both the GROUP_OBJ and 1582fa9e4066Sahrens * CLASS_OBJ for this file and insert 1583fa9e4066Sahrens * the logical AND of those two values 1584fa9e4066Sahrens * in the group permissions field 1585fa9e4066Sahrens * of the lflags value for this file. 1586fa9e4066Sahrens */ 1587fa9e4066Sahrens 1588fa9e4066Sahrens /* 1589fa9e4066Sahrens * Until found in acl list, assume 1590fa9e4066Sahrens * maximum permissions for both group 1591fa9e4066Sahrens * a nd mask. (Just in case the acl 1592fa9e4066Sahrens * lacks either value for some reason.) 15937c478bd9Sstevel@tonic-gate */ 15947c478bd9Sstevel@tonic-gate groupperm = 07; 15957c478bd9Sstevel@tonic-gate mask = 07; 15967c478bd9Sstevel@tonic-gate grouppermfound = 0; 15977c478bd9Sstevel@tonic-gate maskfound = 0; 1598fa9e4066Sahrens aclcnt = acl_cnt(rep->aclp); 1599fa9e4066Sahrens for (tp = 1600fa9e4066Sahrens (aclent_t *)acl_data(rep->aclp); 1601fa9e4066Sahrens aclcnt--; tp++) { 16027c478bd9Sstevel@tonic-gate if (tp->a_type == GROUP_OBJ) { 16037c478bd9Sstevel@tonic-gate groupperm = tp->a_perm; 16047c478bd9Sstevel@tonic-gate grouppermfound = 1; 16057c478bd9Sstevel@tonic-gate continue; 16067c478bd9Sstevel@tonic-gate } 16077c478bd9Sstevel@tonic-gate if (tp->a_type == CLASS_OBJ) { 16087c478bd9Sstevel@tonic-gate mask = tp->a_perm; 16097c478bd9Sstevel@tonic-gate maskfound = 1; 16107c478bd9Sstevel@tonic-gate } 16117c478bd9Sstevel@tonic-gate if (grouppermfound && maskfound) 16127c478bd9Sstevel@tonic-gate break; 16137c478bd9Sstevel@tonic-gate } 16147c478bd9Sstevel@tonic-gate 16157c478bd9Sstevel@tonic-gate 16167c478bd9Sstevel@tonic-gate /* reset all the group bits */ 16177c478bd9Sstevel@tonic-gate rep->lflags &= ~S_IRWXG; 16187c478bd9Sstevel@tonic-gate 16197c478bd9Sstevel@tonic-gate /* 1620fa9e4066Sahrens * Now set them to the logical AND of 1621fa9e4066Sahrens * the GROUP_OBJ permissions and the 1622fa9e4066Sahrens * acl mask. 16237c478bd9Sstevel@tonic-gate */ 16247c478bd9Sstevel@tonic-gate 16257c478bd9Sstevel@tonic-gate rep->lflags |= (groupperm & mask) << 3; 1626fa9e4066Sahrens 162764d425a7Sny155746 } else if (acl_type(rep->aclp) == ACE_T) { 162864d425a7Sny155746 int mode; 162964d425a7Sny155746 mode = grp_mask_to_mode(rep->aclp); 163064d425a7Sny155746 rep->lflags &= ~S_IRWXG; 163164d425a7Sny155746 rep->lflags |= mode; 1632fa9e4066Sahrens } 16337c478bd9Sstevel@tonic-gate } 16347c478bd9Sstevel@tonic-gate 16355a5eeccaSmarks if (!vflg && !Vflg && rep->aclp) { 16365a5eeccaSmarks acl_free(rep->aclp); 16375a5eeccaSmarks rep->aclp = NULL; 16385a5eeccaSmarks } 16395a5eeccaSmarks 16407c478bd9Sstevel@tonic-gate if (atflg && pathconf(file, _PC_XATTR_EXISTS) == 1) 16417c478bd9Sstevel@tonic-gate rep->acl = '@'; 1642da6c28aaSamw 16437c478bd9Sstevel@tonic-gate } else 16447c478bd9Sstevel@tonic-gate rep->acl = ' '; 16457c478bd9Sstevel@tonic-gate 16467c478bd9Sstevel@tonic-gate /* mask ISARG and other file-type bits */ 16477c478bd9Sstevel@tonic-gate 16487c478bd9Sstevel@tonic-gate if (rep->ltype != 'b' && rep->ltype != 'c') 16497c478bd9Sstevel@tonic-gate tblocks += rep->lblocks; 1650da6c28aaSamw 1651da6c28aaSamw /* Get extended system attributes */ 1652da6c28aaSamw 1653da6c28aaSamw if ((saflg || (tmflg && crtm) || (tmflg && alltm)) && 1654da6c28aaSamw (sysattr_support(file, _PC_SATTR_EXISTS) == 1)) { 1655da6c28aaSamw int i; 1656da6c28aaSamw 1657da6c28aaSamw sacnt = attr_count(); 1658da6c28aaSamw /* 1659da6c28aaSamw * Allocate 'sacnt' size array to hold extended 1660da6c28aaSamw * system attribute name (verbose) or respective 1661da6c28aaSamw * symbol represenation (compact). 1662da6c28aaSamw */ 1663da6c28aaSamw rep->exttr = xmalloc(sacnt * sizeof (struct attrb), 1664da6c28aaSamw rep); 1665da6c28aaSamw 1666da6c28aaSamw /* initialize boolean attribute list */ 1667da6c28aaSamw for (i = 0; i < sacnt; i++) 1668da6c28aaSamw rep->exttr[i].name = NULL; 1669da6c28aaSamw if (get_sysxattr(file, rep) != 0) { 1670da6c28aaSamw (void) fprintf(stderr, 1671da6c28aaSamw gettext("ls:Failed to retrieve " 1672da6c28aaSamw "extended system attribute from " 1673da6c28aaSamw "%s\n"), file); 1674da6c28aaSamw rep->exttr[0].name = xmalloc(2, rep); 1675da6c28aaSamw (void) strlcpy(rep->exttr[0].name, "?", 2); 1676da6c28aaSamw } 1677da6c28aaSamw } 16787c478bd9Sstevel@tonic-gate } 16797c478bd9Sstevel@tonic-gate return (rep); 16807c478bd9Sstevel@tonic-gate } 16817c478bd9Sstevel@tonic-gate 16827c478bd9Sstevel@tonic-gate /* 16837c478bd9Sstevel@tonic-gate * returns pathname of the form dir/file; 16847c478bd9Sstevel@tonic-gate * dir and file are null-terminated strings. 16857c478bd9Sstevel@tonic-gate */ 16867c478bd9Sstevel@tonic-gate static char * 16877c478bd9Sstevel@tonic-gate makename(char *dir, char *file) 16887c478bd9Sstevel@tonic-gate { 16897c478bd9Sstevel@tonic-gate /* 16907c478bd9Sstevel@tonic-gate * PATH_MAX is the maximum length of a path name. 16917c478bd9Sstevel@tonic-gate * MAXNAMLEN is the maximum length of any path name component. 16927c478bd9Sstevel@tonic-gate * Allocate space for both, plus the '/' in the middle 16937c478bd9Sstevel@tonic-gate * and the null character at the end. 16947c478bd9Sstevel@tonic-gate * dfile is static as this is returned by makename(). 16957c478bd9Sstevel@tonic-gate */ 16967c478bd9Sstevel@tonic-gate static char dfile[PATH_MAX + 1 + MAXNAMLEN + 1]; 16977c478bd9Sstevel@tonic-gate char *dp, *fp; 16987c478bd9Sstevel@tonic-gate 16997c478bd9Sstevel@tonic-gate dp = dfile; 17007c478bd9Sstevel@tonic-gate fp = dir; 17017c478bd9Sstevel@tonic-gate while (*fp) 17027c478bd9Sstevel@tonic-gate *dp++ = *fp++; 17037c478bd9Sstevel@tonic-gate if (dp > dfile && *(dp - 1) != '/') 17047c478bd9Sstevel@tonic-gate *dp++ = '/'; 17057c478bd9Sstevel@tonic-gate fp = file; 17067c478bd9Sstevel@tonic-gate while (*fp) 17077c478bd9Sstevel@tonic-gate *dp++ = *fp++; 17087c478bd9Sstevel@tonic-gate *dp = '\0'; 17097c478bd9Sstevel@tonic-gate return (dfile); 17107c478bd9Sstevel@tonic-gate } 17117c478bd9Sstevel@tonic-gate 17127c478bd9Sstevel@tonic-gate 17137c478bd9Sstevel@tonic-gate #include <pwd.h> 17147c478bd9Sstevel@tonic-gate #include <grp.h> 17157c478bd9Sstevel@tonic-gate #include <utmpx.h> 17167c478bd9Sstevel@tonic-gate 17177c478bd9Sstevel@tonic-gate struct utmpx utmp; 17187c478bd9Sstevel@tonic-gate 17197c478bd9Sstevel@tonic-gate #define NMAX (sizeof (utmp.ut_name)) 17207c478bd9Sstevel@tonic-gate #define SCPYN(a, b) (void) strncpy(a, b, NMAX) 17217c478bd9Sstevel@tonic-gate 17227c478bd9Sstevel@tonic-gate 17237c478bd9Sstevel@tonic-gate struct cachenode { /* this struct must be zeroed before using */ 17247c478bd9Sstevel@tonic-gate struct cachenode *lesschild; /* subtree whose entries < val */ 17257c478bd9Sstevel@tonic-gate struct cachenode *grtrchild; /* subtree whose entries > val */ 17267c478bd9Sstevel@tonic-gate long val; /* the uid or gid of this entry */ 17277c478bd9Sstevel@tonic-gate int initted; /* name has been filled in */ 17287c478bd9Sstevel@tonic-gate char name[NMAX+1]; /* the string that val maps to */ 17297c478bd9Sstevel@tonic-gate }; 17307c478bd9Sstevel@tonic-gate static struct cachenode *names, *groups; 17317c478bd9Sstevel@tonic-gate 17327c478bd9Sstevel@tonic-gate static struct cachenode * 17337c478bd9Sstevel@tonic-gate findincache(struct cachenode **head, long val) 17347c478bd9Sstevel@tonic-gate { 17357c478bd9Sstevel@tonic-gate struct cachenode **parent = head; 17367c478bd9Sstevel@tonic-gate struct cachenode *c = *parent; 17377c478bd9Sstevel@tonic-gate 17387c478bd9Sstevel@tonic-gate while (c != NULL) { 17397c478bd9Sstevel@tonic-gate if (val == c->val) { 17407c478bd9Sstevel@tonic-gate /* found it */ 17417c478bd9Sstevel@tonic-gate return (c); 17427c478bd9Sstevel@tonic-gate } else if (val < c->val) { 17437c478bd9Sstevel@tonic-gate parent = &c->lesschild; 17447c478bd9Sstevel@tonic-gate c = c->lesschild; 17457c478bd9Sstevel@tonic-gate } else { 17467c478bd9Sstevel@tonic-gate parent = &c->grtrchild; 17477c478bd9Sstevel@tonic-gate c = c->grtrchild; 17487c478bd9Sstevel@tonic-gate } 17497c478bd9Sstevel@tonic-gate } 17507c478bd9Sstevel@tonic-gate 17517c478bd9Sstevel@tonic-gate /* not in the cache, make a new entry for it */ 17527c478bd9Sstevel@tonic-gate c = calloc(1, sizeof (struct cachenode)); 17537c478bd9Sstevel@tonic-gate if (c == NULL) { 17547c478bd9Sstevel@tonic-gate perror("ls"); 17557c478bd9Sstevel@tonic-gate exit(2); 17567c478bd9Sstevel@tonic-gate } 17577c478bd9Sstevel@tonic-gate *parent = c; 17587c478bd9Sstevel@tonic-gate c->val = val; 17597c478bd9Sstevel@tonic-gate return (c); 17607c478bd9Sstevel@tonic-gate } 17617c478bd9Sstevel@tonic-gate 17627c478bd9Sstevel@tonic-gate /* 17637c478bd9Sstevel@tonic-gate * get name from cache, or passwd file for a given uid; 17647c478bd9Sstevel@tonic-gate * lastuid is set to uid. 17657c478bd9Sstevel@tonic-gate */ 17667c478bd9Sstevel@tonic-gate static char * 17677c478bd9Sstevel@tonic-gate getname(uid_t uid) 17687c478bd9Sstevel@tonic-gate { 17697c478bd9Sstevel@tonic-gate struct passwd *pwent; 17707c478bd9Sstevel@tonic-gate struct cachenode *c; 17717c478bd9Sstevel@tonic-gate 17727c478bd9Sstevel@tonic-gate if ((uid == lastuid) && lastuname) 17737c478bd9Sstevel@tonic-gate return (lastuname); 17747c478bd9Sstevel@tonic-gate 17757c478bd9Sstevel@tonic-gate c = findincache(&names, uid); 17767c478bd9Sstevel@tonic-gate if (c->initted == 0) { 17777c478bd9Sstevel@tonic-gate if ((pwent = getpwuid(uid)) != NULL) { 17787c478bd9Sstevel@tonic-gate SCPYN(&c->name[0], pwent->pw_name); 17797c478bd9Sstevel@tonic-gate } else { 17807c478bd9Sstevel@tonic-gate (void) sprintf(&c->name[0], "%-8u", (int)uid); 17817c478bd9Sstevel@tonic-gate } 17827c478bd9Sstevel@tonic-gate c->initted = 1; 17837c478bd9Sstevel@tonic-gate } 17847c478bd9Sstevel@tonic-gate lastuid = uid; 17857c478bd9Sstevel@tonic-gate lastuname = &c->name[0]; 17867c478bd9Sstevel@tonic-gate return (lastuname); 17877c478bd9Sstevel@tonic-gate } 17887c478bd9Sstevel@tonic-gate 17897c478bd9Sstevel@tonic-gate /* 17907c478bd9Sstevel@tonic-gate * get name from cache, or group file for a given gid; 17917c478bd9Sstevel@tonic-gate * lastgid is set to gid. 17927c478bd9Sstevel@tonic-gate */ 17937c478bd9Sstevel@tonic-gate static char * 17947c478bd9Sstevel@tonic-gate getgroup(gid_t gid) 17957c478bd9Sstevel@tonic-gate { 17967c478bd9Sstevel@tonic-gate struct group *grent; 17977c478bd9Sstevel@tonic-gate struct cachenode *c; 17987c478bd9Sstevel@tonic-gate 17997c478bd9Sstevel@tonic-gate if ((gid == lastgid) && lastgname) 18007c478bd9Sstevel@tonic-gate return (lastgname); 18017c478bd9Sstevel@tonic-gate 18027c478bd9Sstevel@tonic-gate c = findincache(&groups, gid); 18037c478bd9Sstevel@tonic-gate if (c->initted == 0) { 18047c478bd9Sstevel@tonic-gate if ((grent = getgrgid(gid)) != NULL) { 18057c478bd9Sstevel@tonic-gate SCPYN(&c->name[0], grent->gr_name); 18067c478bd9Sstevel@tonic-gate } else { 18077c478bd9Sstevel@tonic-gate (void) sprintf(&c->name[0], "%-8u", (int)gid); 18087c478bd9Sstevel@tonic-gate } 18097c478bd9Sstevel@tonic-gate c->initted = 1; 18107c478bd9Sstevel@tonic-gate } 18117c478bd9Sstevel@tonic-gate lastgid = gid; 18127c478bd9Sstevel@tonic-gate lastgname = &c->name[0]; 18137c478bd9Sstevel@tonic-gate return (lastgname); 18147c478bd9Sstevel@tonic-gate } 18157c478bd9Sstevel@tonic-gate 18167c478bd9Sstevel@tonic-gate /* return >0 if item pointed by pp2 should appear first */ 18177c478bd9Sstevel@tonic-gate static int 18187c478bd9Sstevel@tonic-gate compar(struct lbuf **pp1, struct lbuf **pp2) 18197c478bd9Sstevel@tonic-gate { 18207c478bd9Sstevel@tonic-gate struct lbuf *p1, *p2; 18217c478bd9Sstevel@tonic-gate 18227c478bd9Sstevel@tonic-gate p1 = *pp1; 18237c478bd9Sstevel@tonic-gate p2 = *pp2; 18247c478bd9Sstevel@tonic-gate if (dflg == 0) { 18257c478bd9Sstevel@tonic-gate /* 18267c478bd9Sstevel@tonic-gate * compare two names in ls-command one of which is file 18277c478bd9Sstevel@tonic-gate * and the other is a directory; 18287c478bd9Sstevel@tonic-gate * this portion is not used for comparing files within 18297c478bd9Sstevel@tonic-gate * a directory name of ls-command; 18307c478bd9Sstevel@tonic-gate */ 18317c478bd9Sstevel@tonic-gate if (p1->lflags&ISARG && p1->ltype == 'd') { 18327c478bd9Sstevel@tonic-gate if (!(p2->lflags&ISARG && p2->ltype == 'd')) 18337c478bd9Sstevel@tonic-gate return (1); 18347c478bd9Sstevel@tonic-gate } else { 18357c478bd9Sstevel@tonic-gate if (p2->lflags&ISARG && p2->ltype == 'd') 18367c478bd9Sstevel@tonic-gate return (-1); 18377c478bd9Sstevel@tonic-gate } 18387c478bd9Sstevel@tonic-gate } 18397c478bd9Sstevel@tonic-gate if (tflg) { 18407c478bd9Sstevel@tonic-gate if (p2->lmtime.tv_sec > p1->lmtime.tv_sec) 18417c478bd9Sstevel@tonic-gate return (rflg); 18427c478bd9Sstevel@tonic-gate else if (p2->lmtime.tv_sec < p1->lmtime.tv_sec) 18437c478bd9Sstevel@tonic-gate return (-rflg); 18447c478bd9Sstevel@tonic-gate /* times are equal to the sec, check nsec */ 18457c478bd9Sstevel@tonic-gate if (p2->lmtime.tv_nsec > p1->lmtime.tv_nsec) 18467c478bd9Sstevel@tonic-gate return (rflg); 18477c478bd9Sstevel@tonic-gate else if (p2->lmtime.tv_nsec < p1->lmtime.tv_nsec) 18487c478bd9Sstevel@tonic-gate return (-rflg); 18497c478bd9Sstevel@tonic-gate /* if times are equal, fall through and sort by name */ 18507c478bd9Sstevel@tonic-gate } else if (Sflg) { 18517c478bd9Sstevel@tonic-gate /* 18527c478bd9Sstevel@tonic-gate * The size stored in lsize can be either the 18537c478bd9Sstevel@tonic-gate * size or the major minor number (in the case of 18547c478bd9Sstevel@tonic-gate * block and character special devices). If it's 18557c478bd9Sstevel@tonic-gate * a major minor number, then the size is considered 18567c478bd9Sstevel@tonic-gate * to be zero and we want to fall through and sort 18577c478bd9Sstevel@tonic-gate * by name. In addition, if the size of p2 is equal 18587c478bd9Sstevel@tonic-gate * to the size of p1 we want to fall through and 18597c478bd9Sstevel@tonic-gate * sort by name. 18607c478bd9Sstevel@tonic-gate */ 18617c478bd9Sstevel@tonic-gate off_t p1size = (p1->ltype == 'b') || 18627c478bd9Sstevel@tonic-gate (p1->ltype == 'c') ? 0 : p1->lsize; 18637c478bd9Sstevel@tonic-gate off_t p2size = (p2->ltype == 'b') || 18647c478bd9Sstevel@tonic-gate (p2->ltype == 'c') ? 0 : p2->lsize; 18657c478bd9Sstevel@tonic-gate if (p2size > p1size) { 18667c478bd9Sstevel@tonic-gate return (rflg); 18677c478bd9Sstevel@tonic-gate } else if (p2size < p1size) { 18687c478bd9Sstevel@tonic-gate return (-rflg); 18697c478bd9Sstevel@tonic-gate } 18707c478bd9Sstevel@tonic-gate /* Sizes are equal, fall through and sort by name. */ 18717c478bd9Sstevel@tonic-gate } 18727c478bd9Sstevel@tonic-gate return (rflg * strcoll( 18737c478bd9Sstevel@tonic-gate p1->lflags & ISARG ? p1->ln.namep : p1->ln.lname, 18747c478bd9Sstevel@tonic-gate p2->lflags&ISARG ? p2->ln.namep : p2->ln.lname)); 18757c478bd9Sstevel@tonic-gate } 18767c478bd9Sstevel@tonic-gate 18777c478bd9Sstevel@tonic-gate static void 18787c478bd9Sstevel@tonic-gate pprintf(char *s1, char *s2) 18797c478bd9Sstevel@tonic-gate { 18807c478bd9Sstevel@tonic-gate csi_pprintf((unsigned char *)s1); 18817c478bd9Sstevel@tonic-gate csi_pprintf((unsigned char *)s2); 18827c478bd9Sstevel@tonic-gate } 18837c478bd9Sstevel@tonic-gate 18847c478bd9Sstevel@tonic-gate static void 18857c478bd9Sstevel@tonic-gate csi_pprintf(unsigned char *s) 18867c478bd9Sstevel@tonic-gate { 18877c478bd9Sstevel@tonic-gate unsigned char *cp; 18887c478bd9Sstevel@tonic-gate char c; 18897c478bd9Sstevel@tonic-gate int i; 18907c478bd9Sstevel@tonic-gate int c_len; 18917c478bd9Sstevel@tonic-gate int p_col; 18927c478bd9Sstevel@tonic-gate wchar_t pcode; 18937c478bd9Sstevel@tonic-gate 18947c478bd9Sstevel@tonic-gate if (!qflg && !bflg) { 18957c478bd9Sstevel@tonic-gate for (cp = s; *cp != '\0'; cp++) { 18967c478bd9Sstevel@tonic-gate (void) putchar(*cp); 18977c478bd9Sstevel@tonic-gate curcol++; 18987c478bd9Sstevel@tonic-gate } 18997c478bd9Sstevel@tonic-gate return; 19007c478bd9Sstevel@tonic-gate } 19017c478bd9Sstevel@tonic-gate 19027c478bd9Sstevel@tonic-gate for (cp = s; *cp; ) { 19037c478bd9Sstevel@tonic-gate if (isascii(c = *cp)) { 19047c478bd9Sstevel@tonic-gate if (!isprint(c)) { 19057c478bd9Sstevel@tonic-gate if (qflg) { 19067c478bd9Sstevel@tonic-gate c = '?'; 19077c478bd9Sstevel@tonic-gate } else { 19087c478bd9Sstevel@tonic-gate curcol += 3; 19097c478bd9Sstevel@tonic-gate (void) putc('\\', stdout); 19107c478bd9Sstevel@tonic-gate c = '0' + ((*cp >> 6) & 07); 19117c478bd9Sstevel@tonic-gate (void) putc(c, stdout); 19127c478bd9Sstevel@tonic-gate c = '0' + ((*cp >> 3) & 07); 19137c478bd9Sstevel@tonic-gate (void) putc(c, stdout); 19147c478bd9Sstevel@tonic-gate c = '0' + (*cp & 07); 19157c478bd9Sstevel@tonic-gate } 19167c478bd9Sstevel@tonic-gate } 19177c478bd9Sstevel@tonic-gate curcol++; 19187c478bd9Sstevel@tonic-gate cp++; 19197c478bd9Sstevel@tonic-gate (void) putc(c, stdout); 19207c478bd9Sstevel@tonic-gate continue; 19217c478bd9Sstevel@tonic-gate } 19227c478bd9Sstevel@tonic-gate 19237c478bd9Sstevel@tonic-gate if ((c_len = mbtowc(&pcode, (char *)cp, MB_LEN_MAX)) <= 0) { 19247c478bd9Sstevel@tonic-gate c_len = 1; 19257c478bd9Sstevel@tonic-gate goto not_print; 19267c478bd9Sstevel@tonic-gate } 19277c478bd9Sstevel@tonic-gate 19287c478bd9Sstevel@tonic-gate if ((p_col = wcwidth(pcode)) > 0) { 19297c478bd9Sstevel@tonic-gate (void) putwchar(pcode); 19307c478bd9Sstevel@tonic-gate cp += c_len; 19317c478bd9Sstevel@tonic-gate curcol += p_col; 19327c478bd9Sstevel@tonic-gate continue; 19337c478bd9Sstevel@tonic-gate } 19347c478bd9Sstevel@tonic-gate 19357c478bd9Sstevel@tonic-gate not_print: 19367c478bd9Sstevel@tonic-gate for (i = 0; i < c_len; i++) { 19377c478bd9Sstevel@tonic-gate if (qflg) { 19387c478bd9Sstevel@tonic-gate c = '?'; 19397c478bd9Sstevel@tonic-gate } else { 19407c478bd9Sstevel@tonic-gate curcol += 3; 19417c478bd9Sstevel@tonic-gate (void) putc('\\', stdout); 19427c478bd9Sstevel@tonic-gate c = '0' + ((*cp >> 6) & 07); 19437c478bd9Sstevel@tonic-gate (void) putc(c, stdout); 19447c478bd9Sstevel@tonic-gate c = '0' + ((*cp >> 3) & 07); 19457c478bd9Sstevel@tonic-gate (void) putc(c, stdout); 19467c478bd9Sstevel@tonic-gate c = '0' + (*cp & 07); 19477c478bd9Sstevel@tonic-gate } 19487c478bd9Sstevel@tonic-gate curcol++; 19497c478bd9Sstevel@tonic-gate (void) putc(c, stdout); 19507c478bd9Sstevel@tonic-gate cp++; 19517c478bd9Sstevel@tonic-gate } 19527c478bd9Sstevel@tonic-gate } 19537c478bd9Sstevel@tonic-gate } 19547c478bd9Sstevel@tonic-gate 19557c478bd9Sstevel@tonic-gate static int 19567c478bd9Sstevel@tonic-gate strcol(unsigned char *s1) 19577c478bd9Sstevel@tonic-gate { 19587c478bd9Sstevel@tonic-gate int w; 19597c478bd9Sstevel@tonic-gate int w_col; 19607c478bd9Sstevel@tonic-gate int len; 19617c478bd9Sstevel@tonic-gate wchar_t wc; 19627c478bd9Sstevel@tonic-gate 19637c478bd9Sstevel@tonic-gate w = 0; 19647c478bd9Sstevel@tonic-gate while (*s1) { 19657c478bd9Sstevel@tonic-gate if (isascii(*s1)) { 19667c478bd9Sstevel@tonic-gate w++; 19677c478bd9Sstevel@tonic-gate s1++; 19687c478bd9Sstevel@tonic-gate continue; 19697c478bd9Sstevel@tonic-gate } 19707c478bd9Sstevel@tonic-gate 19717c478bd9Sstevel@tonic-gate if ((len = mbtowc(&wc, (char *)s1, MB_LEN_MAX)) <= 0) { 19727c478bd9Sstevel@tonic-gate w++; 19737c478bd9Sstevel@tonic-gate s1++; 19747c478bd9Sstevel@tonic-gate continue; 19757c478bd9Sstevel@tonic-gate } 19767c478bd9Sstevel@tonic-gate 19777c478bd9Sstevel@tonic-gate if ((w_col = wcwidth(wc)) < 0) 19787c478bd9Sstevel@tonic-gate w_col = len; 19797c478bd9Sstevel@tonic-gate s1 += len; 19807c478bd9Sstevel@tonic-gate w += w_col; 19817c478bd9Sstevel@tonic-gate } 19827c478bd9Sstevel@tonic-gate return (w); 19837c478bd9Sstevel@tonic-gate } 19847c478bd9Sstevel@tonic-gate 19857c478bd9Sstevel@tonic-gate /* 19867c478bd9Sstevel@tonic-gate * Convert an unsigned long long to a string representation and place the 19877c478bd9Sstevel@tonic-gate * result in the caller-supplied buffer. 19887c478bd9Sstevel@tonic-gate * 19897c478bd9Sstevel@tonic-gate * The number provided is a size in bytes. The number is first 19907c478bd9Sstevel@tonic-gate * converted to an integral multiple of 'scale' bytes. This new 19917c478bd9Sstevel@tonic-gate * number is then scaled down until it is small enough to be in a good 19927c478bd9Sstevel@tonic-gate * human readable format, i.e. in the range 0 thru scale-1. If the 19937c478bd9Sstevel@tonic-gate * number used to derive the final number is not a multiple of scale, and 19947c478bd9Sstevel@tonic-gate * the final number has only a single significant digit, we compute 19957c478bd9Sstevel@tonic-gate * tenths of units to provide a second significant digit. 19967c478bd9Sstevel@tonic-gate * 19977c478bd9Sstevel@tonic-gate * The value "(unsigned long long)-1" is a special case and is always 19987c478bd9Sstevel@tonic-gate * converted to "-1". 19997c478bd9Sstevel@tonic-gate * 20007c478bd9Sstevel@tonic-gate * A pointer to the caller-supplied buffer is returned. 20017c478bd9Sstevel@tonic-gate */ 20027c478bd9Sstevel@tonic-gate static char * 20037c478bd9Sstevel@tonic-gate number_to_scaled_string( 20047c478bd9Sstevel@tonic-gate numbuf_t buf, /* put the result here */ 20057c478bd9Sstevel@tonic-gate unsigned long long number, /* convert this number */ 20067c478bd9Sstevel@tonic-gate long scale) 20077c478bd9Sstevel@tonic-gate { 20087c478bd9Sstevel@tonic-gate unsigned long long save; 20097c478bd9Sstevel@tonic-gate /* Measurement: kilo, mega, giga, tera, peta, exa */ 20107c478bd9Sstevel@tonic-gate char *uom = "KMGTPE"; 20117c478bd9Sstevel@tonic-gate 20127c478bd9Sstevel@tonic-gate if ((long long)number == (long long)-1) { 20137c478bd9Sstevel@tonic-gate (void) strlcpy(buf, "-1", sizeof (numbuf_t)); 20147c478bd9Sstevel@tonic-gate return (buf); 20157c478bd9Sstevel@tonic-gate } 20167c478bd9Sstevel@tonic-gate 20177c478bd9Sstevel@tonic-gate save = number; 20187c478bd9Sstevel@tonic-gate number = number / scale; 20197c478bd9Sstevel@tonic-gate 20207c478bd9Sstevel@tonic-gate /* 20217c478bd9Sstevel@tonic-gate * Now we have number as a count of scale units. 20227c478bd9Sstevel@tonic-gate * If no further scaling is necessary, we round up as appropriate. 20237c478bd9Sstevel@tonic-gate * 20247c478bd9Sstevel@tonic-gate * The largest value number could have had entering the routine is 20257c478bd9Sstevel@tonic-gate * 16 Exabytes, so running off the end of the uom array should 20267c478bd9Sstevel@tonic-gate * never happen. We check for that, though, as a guard against 20277c478bd9Sstevel@tonic-gate * a breakdown elsewhere in the algorithm. 20287c478bd9Sstevel@tonic-gate */ 20297c478bd9Sstevel@tonic-gate if (number < (unsigned long long)scale) { 20307c478bd9Sstevel@tonic-gate if ((save % scale) >= (unsigned long long)(scale / 2)) { 20317c478bd9Sstevel@tonic-gate if (++number == (unsigned long long)scale) { 20327c478bd9Sstevel@tonic-gate uom++; 20337c478bd9Sstevel@tonic-gate number = 1; 20347c478bd9Sstevel@tonic-gate } 20357c478bd9Sstevel@tonic-gate } 20367c478bd9Sstevel@tonic-gate } else { 20377c478bd9Sstevel@tonic-gate while ((number >= (unsigned long long)scale) && (*uom != 'E')) { 20387c478bd9Sstevel@tonic-gate uom++; /* next unit of measurement */ 20397c478bd9Sstevel@tonic-gate save = number; 20407c478bd9Sstevel@tonic-gate /* 20417c478bd9Sstevel@tonic-gate * If we're over half way to the next unit of 20427c478bd9Sstevel@tonic-gate * 'scale' bytes (which means we should round 20437c478bd9Sstevel@tonic-gate * up), then adding half of 'scale' prior to 20447c478bd9Sstevel@tonic-gate * the division will push us into that next 20457c478bd9Sstevel@tonic-gate * unit of scale when we perform the division 20467c478bd9Sstevel@tonic-gate */ 20477c478bd9Sstevel@tonic-gate number = (number + (scale / 2)) / scale; 20487c478bd9Sstevel@tonic-gate } 20497c478bd9Sstevel@tonic-gate } 20507c478bd9Sstevel@tonic-gate 20517c478bd9Sstevel@tonic-gate /* check if we should output a decimal place after the point */ 20527c478bd9Sstevel@tonic-gate if ((save / scale) < 10) { 20537c478bd9Sstevel@tonic-gate /* snprintf() will round for us */ 20547c478bd9Sstevel@tonic-gate float fnum = (float)save / scale; 20557c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (numbuf_t), "%2.1f%c", 20567c478bd9Sstevel@tonic-gate fnum, *uom); 20577c478bd9Sstevel@tonic-gate } else { 20587c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (numbuf_t), "%4llu%c", 20597c478bd9Sstevel@tonic-gate number, *uom); 20607c478bd9Sstevel@tonic-gate } 20617c478bd9Sstevel@tonic-gate return (buf); 20627c478bd9Sstevel@tonic-gate } 2063da6c28aaSamw 2064da6c28aaSamw /* Get extended system attributes and set the display */ 2065da6c28aaSamw 2066da6c28aaSamw int 2067da6c28aaSamw get_sysxattr(char *fname, struct lbuf *rep) 2068da6c28aaSamw { 2069da6c28aaSamw boolean_t value; 2070da6c28aaSamw data_type_t type; 2071da6c28aaSamw int error; 2072da6c28aaSamw char *name; 2073da6c28aaSamw int i; 2074da6c28aaSamw 2075da6c28aaSamw if ((error = getattrat(AT_FDCWD, XATTR_VIEW_READWRITE, fname, 2076da6c28aaSamw &response)) != 0) { 2077da6c28aaSamw perror("ls:getattrat"); 2078da6c28aaSamw return (error); 2079da6c28aaSamw } 2080da6c28aaSamw 2081da6c28aaSamw /* 2082da6c28aaSamw * Allocate 'sacnt' size array to hold extended timestamp 2083da6c28aaSamw * system attributes and initialize the array. 2084da6c28aaSamw */ 2085da6c28aaSamw rep->extm = xmalloc(sacnt * sizeof (struct attrtm), rep); 2086da6c28aaSamw for (i = 0; i < sacnt; i++) { 2087da6c28aaSamw rep->extm[i].stm = 0; 2088da6c28aaSamw rep->extm[i].nstm = 0; 2089da6c28aaSamw rep->extm[i].name = NULL; 2090da6c28aaSamw } 2091da6c28aaSamw while ((pair = nvlist_next_nvpair(response, pair)) != NULL) { 2092da6c28aaSamw name = nvpair_name(pair); 2093da6c28aaSamw type = nvpair_type(pair); 2094da6c28aaSamw if (type == DATA_TYPE_BOOLEAN_VALUE) { 2095da6c28aaSamw error = nvpair_value_boolean_value(pair, &value); 2096da6c28aaSamw if (error) { 2097da6c28aaSamw (void) fprintf(stderr, 2098da6c28aaSamw gettext("nvpair_value_boolean_value " 2099da6c28aaSamw "failed: error = %d\n"), error); 2100da6c28aaSamw continue; 2101da6c28aaSamw } 2102da6c28aaSamw if (name != NULL) 2103da6c28aaSamw set_sysattrb_display(name, value, rep); 2104da6c28aaSamw continue; 2105da6c28aaSamw } else if (type == DATA_TYPE_UINT64_ARRAY) { 2106da6c28aaSamw if (name != NULL) 2107da6c28aaSamw set_sysattrtm_display(name, rep); 2108da6c28aaSamw continue; 2109da6c28aaSamw } 2110da6c28aaSamw } 2111da6c28aaSamw nvlist_free(response); 2112da6c28aaSamw return (0); 2113da6c28aaSamw } 2114da6c28aaSamw 2115da6c28aaSamw /* Set extended system attribute boolean display */ 2116da6c28aaSamw 2117da6c28aaSamw void 2118da6c28aaSamw set_sysattrb_display(char *name, boolean_t val, struct lbuf *rep) 2119da6c28aaSamw { 2120da6c28aaSamw f_attr_t fattr; 2121da6c28aaSamw const char *opt; 2122da6c28aaSamw size_t len; 2123da6c28aaSamw 2124da6c28aaSamw fattr = name_to_attr(name); 2125da6c28aaSamw if (fattr != F_ATTR_INVAL && fattr < sacnt) { 2126da6c28aaSamw if (vopt) { 2127da6c28aaSamw len = strlen(name); 2128da6c28aaSamw if (val) { 2129da6c28aaSamw rep->exttr[fattr].name = xmalloc(len + 1, rep); 2130da6c28aaSamw (void) strlcpy(rep->exttr[fattr].name, name, 2131da6c28aaSamw len + 1); 2132da6c28aaSamw } else { 2133da6c28aaSamw rep->exttr[fattr].name = xmalloc(len + 3, rep); 2134da6c28aaSamw (void) snprintf(rep->exttr[fattr].name, len + 3, 2135da6c28aaSamw "no%s", name); 2136da6c28aaSamw } 2137da6c28aaSamw } else { 2138da6c28aaSamw opt = attr_to_option(fattr); 2139da6c28aaSamw if (opt != NULL) { 2140da6c28aaSamw len = strlen(opt); 2141da6c28aaSamw rep->exttr[fattr].name = xmalloc(len + 1, rep); 2142da6c28aaSamw if (val) 2143da6c28aaSamw (void) strlcpy(rep->exttr[fattr].name, 2144da6c28aaSamw opt, len + 1); 2145da6c28aaSamw else 2146da6c28aaSamw (void) strlcpy(rep->exttr[fattr].name, 2147da6c28aaSamw "-", len + 1); 2148da6c28aaSamw } 2149da6c28aaSamw } 2150da6c28aaSamw } 2151da6c28aaSamw } 2152da6c28aaSamw 2153da6c28aaSamw /* Set extended system attribute timestamp display */ 2154da6c28aaSamw 2155da6c28aaSamw void 2156da6c28aaSamw set_sysattrtm_display(char *name, struct lbuf *rep) 2157da6c28aaSamw { 2158da6c28aaSamw uint_t nelem; 2159da6c28aaSamw uint64_t *value; 2160da6c28aaSamw int i; 2161da6c28aaSamw size_t len; 2162da6c28aaSamw 2163da6c28aaSamw if (nvpair_value_uint64_array(pair, &value, &nelem) == 0) { 2164da6c28aaSamw if (*value != NULL) { 2165da6c28aaSamw len = strlen(name); 2166da6c28aaSamw i = 0; 2167da6c28aaSamw while (rep->extm[i].stm != 0 && i < sacnt) 2168da6c28aaSamw i++; 2169da6c28aaSamw rep->extm[i].stm = value[0]; 2170da6c28aaSamw rep->extm[i].nstm = value[1]; 2171da6c28aaSamw rep->extm[i].name = xmalloc(len + 1, rep); 2172da6c28aaSamw (void) strlcpy(rep->extm[i].name, name, len + 1); 2173da6c28aaSamw } 2174da6c28aaSamw } 2175da6c28aaSamw } 2176da6c28aaSamw 2177da6c28aaSamw void 2178da6c28aaSamw format_time(const char *format, time_t sec) 2179da6c28aaSamw { 2180da6c28aaSamw 2181da6c28aaSamw (void) strftime(time_buf, sizeof (time_buf), 2182da6c28aaSamw dcgettext(NULL, format, LC_TIME), 2183da6c28aaSamw localtime(&sec)); 2184da6c28aaSamw } 2185da6c28aaSamw 2186da6c28aaSamw void 2187da6c28aaSamw format_etime(const char *format, time_t sec, time_t nsec) 2188da6c28aaSamw { 2189da6c28aaSamw char fmt_buf[FMTSIZE]; 2190da6c28aaSamw 2191da6c28aaSamw (void) snprintf(fmt_buf, FMTSIZE, 2192da6c28aaSamw format, nsec); 2193da6c28aaSamw (void) strftime(time_buf, sizeof (time_buf), 2194da6c28aaSamw fmt_buf, localtime(&sec)); 2195da6c28aaSamw } 2196da6c28aaSamw 2197da6c28aaSamw /* Format timestamp extended system attributes */ 2198da6c28aaSamw 2199da6c28aaSamw void 2200da6c28aaSamw format_attrtime(struct lbuf *p) 2201da6c28aaSamw { 2202da6c28aaSamw int tmattr = 0; 2203da6c28aaSamw int i; 2204da6c28aaSamw 2205da6c28aaSamw if (p->extm != NULL) { 2206da6c28aaSamw for (i = 0; i < sacnt; i++) { 2207da6c28aaSamw if (p->extm[i].name != NULL) { 2208da6c28aaSamw tmattr = 1; 2209da6c28aaSamw break; 2210da6c28aaSamw } 2211da6c28aaSamw } 2212da6c28aaSamw } 2213da6c28aaSamw if (tmattr) { 2214da6c28aaSamw if (Eflg) 2215da6c28aaSamw format_etime(FORMAT4, (time_t)p->extm[i].stm, 2216da6c28aaSamw (time_t)p->extm[i].nstm); 2217da6c28aaSamw else { 2218da6c28aaSamw if ((p->lmtime.tv_sec < year) || 2219da6c28aaSamw (p->lmtime.tv_sec > now)) 2220da6c28aaSamw format_time(FORMAT1, 2221da6c28aaSamw (time_t)p->extm[i].stm); 2222da6c28aaSamw else 2223da6c28aaSamw format_time(FORMAT2, 2224da6c28aaSamw (time_t)p->extm[i].stm); 2225da6c28aaSamw } 2226da6c28aaSamw } 2227da6c28aaSamw } 2228da6c28aaSamw 2229da6c28aaSamw void 2230da6c28aaSamw print_time(struct lbuf *p) 2231da6c28aaSamw { 2232da6c28aaSamw int i = 0; 2233da6c28aaSamw 2234da6c28aaSamw new_line(); 2235da6c28aaSamw if (Eflg) { 2236da6c28aaSamw format_etime(FORMAT4, p->lat.tv_sec, p->lat.tv_nsec); 2237da6c28aaSamw (void) printf(" timestamp: atime %s\n", 2238da6c28aaSamw time_buf); 2239da6c28aaSamw format_etime(FORMAT4, p->lct.tv_sec, p->lct.tv_nsec); 2240da6c28aaSamw (void) printf(" timestamp: ctime %s\n", 2241da6c28aaSamw time_buf); 2242da6c28aaSamw format_etime(FORMAT4, p->lmt.tv_sec, p->lmt.tv_nsec); 2243da6c28aaSamw (void) printf(" timestamp: mtime %s\n", 2244da6c28aaSamw time_buf); 2245da6c28aaSamw if (p->extm != NULL) { 2246da6c28aaSamw while (p->extm[i].nstm != 0 && i < sacnt) { 2247da6c28aaSamw format_etime(FORMAT4, p->extm[i].stm, 2248da6c28aaSamw p->extm[i].nstm); 2249da6c28aaSamw if (p->extm[i].name != NULL) { 2250da6c28aaSamw (void) printf(" timestamp:" 2251da6c28aaSamw " %s %s\n", 2252da6c28aaSamw p->extm[i].name, time_buf); 2253da6c28aaSamw } 2254da6c28aaSamw i++; 2255da6c28aaSamw } 2256da6c28aaSamw } 2257da6c28aaSamw } else { 2258da6c28aaSamw format_time(FORMAT3, p->lat.tv_sec); 2259da6c28aaSamw (void) printf(" timestamp: atime %s\n", 2260da6c28aaSamw time_buf); 2261da6c28aaSamw format_time(FORMAT3, p->lct.tv_sec); 2262da6c28aaSamw (void) printf(" timestamp: ctime %s\n", 2263da6c28aaSamw time_buf); 2264da6c28aaSamw format_time(FORMAT3, p->lmt.tv_sec); 2265da6c28aaSamw (void) printf(" timestamp: mtime %s\n", 2266da6c28aaSamw time_buf); 2267da6c28aaSamw if (p->extm != NULL) { 2268da6c28aaSamw while (p->extm[i].stm != 0 && i < sacnt) { 2269da6c28aaSamw format_time(FORMAT3, p->extm[i].stm); 2270da6c28aaSamw if (p->extm[i].name != NULL) { 2271da6c28aaSamw (void) printf(" timestamp:" 2272da6c28aaSamw " %s %s\n", 2273da6c28aaSamw p->extm[i].name, time_buf); 2274da6c28aaSamw } 2275da6c28aaSamw i++; 2276da6c28aaSamw } 2277da6c28aaSamw } 2278da6c28aaSamw } 2279da6c28aaSamw } 2280da6c28aaSamw 2281da6c28aaSamw /* Free extended system attribute lists */ 2282da6c28aaSamw 2283da6c28aaSamw void 2284da6c28aaSamw free_sysattr(struct lbuf *p) 2285da6c28aaSamw { 2286da6c28aaSamw int i; 2287da6c28aaSamw 2288da6c28aaSamw if (p->exttr != NULL) { 2289da6c28aaSamw for (i = 0; i < sacnt; i++) { 2290da6c28aaSamw if (p->exttr[i].name != NULL) 2291da6c28aaSamw free(p->exttr[i].name); 2292da6c28aaSamw } 2293da6c28aaSamw free(p->exttr); 2294da6c28aaSamw } 2295da6c28aaSamw if (p->extm != NULL) { 2296da6c28aaSamw for (i = 0; i < sacnt; i++) { 2297da6c28aaSamw if (p->extm[i].name != NULL) 2298da6c28aaSamw free(p->extm[i].name); 2299da6c28aaSamw } 2300da6c28aaSamw free(p->extm); 2301da6c28aaSamw } 2302da6c28aaSamw } 2303da6c28aaSamw 2304da6c28aaSamw /* Allocate extended system attribute list */ 2305da6c28aaSamw 2306da6c28aaSamw void * 2307da6c28aaSamw xmalloc(size_t size, struct lbuf *p) 2308da6c28aaSamw { 2309da6c28aaSamw if ((p = malloc(size)) == NULL) { 2310da6c28aaSamw perror("ls"); 2311da6c28aaSamw free_sysattr(p); 2312da6c28aaSamw nvlist_free(response); 2313da6c28aaSamw exit(2); 2314da6c28aaSamw } 2315da6c28aaSamw return (p); 2316da6c28aaSamw } 2317