14b88c807SRodney W. Grimes /* 24b88c807SRodney W. Grimes * Copyright (c) 1989, 1993, 1994 34b88c807SRodney W. Grimes * The Regents of the University of California. All rights reserved. 44b88c807SRodney W. Grimes * 54b88c807SRodney W. Grimes * This code is derived from software contributed to Berkeley by 64b88c807SRodney W. Grimes * Michael Fischbein. 74b88c807SRodney W. Grimes * 84b88c807SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 94b88c807SRodney W. Grimes * modification, are permitted provided that the following conditions 104b88c807SRodney W. Grimes * are met: 114b88c807SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 124b88c807SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 134b88c807SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 144b88c807SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 154b88c807SRodney W. Grimes * documentation and/or other materials provided with the distribution. 164b88c807SRodney W. Grimes * 3. All advertising materials mentioning features or use of this software 174b88c807SRodney W. Grimes * must display the following acknowledgement: 184b88c807SRodney W. Grimes * This product includes software developed by the University of 194b88c807SRodney W. Grimes * California, Berkeley and its contributors. 204b88c807SRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 214b88c807SRodney W. Grimes * may be used to endorse or promote products derived from this software 224b88c807SRodney W. Grimes * without specific prior written permission. 234b88c807SRodney W. Grimes * 244b88c807SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 254b88c807SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 264b88c807SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 274b88c807SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 284b88c807SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 294b88c807SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 304b88c807SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 314b88c807SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 324b88c807SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 334b88c807SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 344b88c807SRodney W. Grimes * SUCH DAMAGE. 354b88c807SRodney W. Grimes */ 364b88c807SRodney W. Grimes 37febad2fcSSteve Price #if 0 38c73d77ceSMark Murray #ifndef lint 39febad2fcSSteve Price static char sccsid[] = "@(#)print.c 8.4 (Berkeley) 4/17/94"; 404b88c807SRodney W. Grimes #endif /* not lint */ 41c73d77ceSMark Murray #endif 425eb43ac2SDavid E. O'Brien #include <sys/cdefs.h> 435eb43ac2SDavid E. O'Brien __FBSDID("$FreeBSD$"); 444b88c807SRodney W. Grimes 454b88c807SRodney W. Grimes #include <sys/param.h> 464b88c807SRodney W. Grimes #include <sys/stat.h> 47dd9aaeb0STim J. Robbins #include <sys/acl.h> 484b88c807SRodney W. Grimes 494b88c807SRodney W. Grimes #include <err.h> 504b88c807SRodney W. Grimes #include <errno.h> 514b88c807SRodney W. Grimes #include <fts.h> 520e8d1551SJosef Karthauser #include <math.h> 5328fd017aSAndrey A. Chernov #include <langinfo.h> 544b88c807SRodney W. Grimes #include <stdio.h> 554b88c807SRodney W. Grimes #include <stdlib.h> 564b88c807SRodney W. Grimes #include <string.h> 57434b6ea4SBruce Evans #include <time.h> 584b88c807SRodney W. Grimes #include <unistd.h> 59faebfe2eSAndrey A. Chernov #ifdef COLORLS 60faebfe2eSAndrey A. Chernov #include <ctype.h> 61faebfe2eSAndrey A. Chernov #include <termcap.h> 62faebfe2eSAndrey A. Chernov #include <signal.h> 63faebfe2eSAndrey A. Chernov #endif 644b88c807SRodney W. Grimes 654b88c807SRodney W. Grimes #include "ls.h" 664b88c807SRodney W. Grimes #include "extern.h" 674b88c807SRodney W. Grimes 6840feca3aSMark Murray static int printaname(const FTSENT *, u_long, u_long); 69ca2993fbSMark Murray static void printlink(const FTSENT *); 7046251ddeSWarner Losh static void printtime(time_t); 7146251ddeSWarner Losh static int printtype(u_int); 7246251ddeSWarner Losh static void printsize(size_t, off_t); 7338782c25SAndrey A. Chernov #ifdef COLORLS 7446251ddeSWarner Losh static void endcolor(int); 7546251ddeSWarner Losh static int colortype(mode_t); 7638782c25SAndrey A. Chernov #endif 7740feca3aSMark Murray static void aclmode(char *, const FTSENT *, int *); 784b88c807SRodney W. Grimes 794b88c807SRodney W. Grimes #define IS_NOPRINT(p) ((p)->fts_number == NO_PRINT) 800e8d1551SJosef Karthauser 810e8d1551SJosef Karthauser #define KILO_SZ(n) (n) 820e8d1551SJosef Karthauser #define MEGA_SZ(n) ((n) * (n)) 830e8d1551SJosef Karthauser #define GIGA_SZ(n) ((n) * (n) * (n)) 840e8d1551SJosef Karthauser #define TERA_SZ(n) ((n) * (n) * (n) * (n)) 850e8d1551SJosef Karthauser #define PETA_SZ(n) ((n) * (n) * (n) * (n) * (n)) 860e8d1551SJosef Karthauser 870e8d1551SJosef Karthauser #define KILO_2_SZ (KILO_SZ(1024ULL)) 880e8d1551SJosef Karthauser #define MEGA_2_SZ (MEGA_SZ(1024ULL)) 890e8d1551SJosef Karthauser #define GIGA_2_SZ (GIGA_SZ(1024ULL)) 900e8d1551SJosef Karthauser #define TERA_2_SZ (TERA_SZ(1024ULL)) 910e8d1551SJosef Karthauser #define PETA_2_SZ (PETA_SZ(1024ULL)) 920e8d1551SJosef Karthauser 939052855aSMark Murray static unsigned long long vals_base2[] = {1, KILO_2_SZ, MEGA_2_SZ, GIGA_2_SZ, TERA_2_SZ, PETA_2_SZ}; 940e8d1551SJosef Karthauser 955dda5d0dSJosef Karthauser typedef enum { 965dda5d0dSJosef Karthauser NONE, KILO, MEGA, GIGA, TERA, PETA, UNIT_MAX 975dda5d0dSJosef Karthauser } unit_t; 98598420eeSDima Dorfman static unit_t unit_adjust(double *); 990e8d1551SJosef Karthauser 100ca2993fbSMark Murray static unit_t unitp[] = {NONE, KILO, MEGA, GIGA, TERA, PETA}; 1014b88c807SRodney W. Grimes 10274985094SJosef Karthauser #ifdef COLORLS 1033885812cSJosef Karthauser /* Most of these are taken from <sys/stat.h> */ 1043885812cSJosef Karthauser typedef enum Colors { 1053885812cSJosef Karthauser C_DIR, /* directory */ 1063885812cSJosef Karthauser C_LNK, /* symbolic link */ 1073885812cSJosef Karthauser C_SOCK, /* socket */ 1083885812cSJosef Karthauser C_FIFO, /* pipe */ 1093885812cSJosef Karthauser C_EXEC, /* executable */ 1103885812cSJosef Karthauser C_BLK, /* block special */ 1113885812cSJosef Karthauser C_CHR, /* character special */ 1123885812cSJosef Karthauser C_SUID, /* setuid executable */ 1133885812cSJosef Karthauser C_SGID, /* setgid executable */ 1145dda5d0dSJosef Karthauser C_WSDIR, /* directory writeble to others, with sticky 1155dda5d0dSJosef Karthauser * bit */ 1165dda5d0dSJosef Karthauser C_WDIR, /* directory writeble to others, without 1175dda5d0dSJosef Karthauser * sticky bit */ 1183885812cSJosef Karthauser C_NUMCOLORS /* just a place-holder */ 1193885812cSJosef Karthauser } Colors; 1203885812cSJosef Karthauser 1219052855aSMark Murray static const char *defcolors = "exfxcxdxbxegedabagacad"; 1223885812cSJosef Karthauser 123c1499cf6SJosef Karthauser /* colors for file types */ 124c1499cf6SJosef Karthauser static struct { 125c1499cf6SJosef Karthauser int num[2]; 126c1499cf6SJosef Karthauser int bold; 127c1499cf6SJosef Karthauser } colors[C_NUMCOLORS]; 12874985094SJosef Karthauser #endif 1293885812cSJosef Karthauser 1304b88c807SRodney W. Grimes void 13140feca3aSMark Murray printscol(const DISPLAY *dp) 1324b88c807SRodney W. Grimes { 1334b88c807SRodney W. Grimes FTSENT *p; 1344b88c807SRodney W. Grimes 1354b88c807SRodney W. Grimes for (p = dp->list; p; p = p->fts_link) { 1364b88c807SRodney W. Grimes if (IS_NOPRINT(p)) 1374b88c807SRodney W. Grimes continue; 1384b88c807SRodney W. Grimes (void)printaname(p, dp->s_inode, dp->s_block); 1394b88c807SRodney W. Grimes (void)putchar('\n'); 1404b88c807SRodney W. Grimes } 1414b88c807SRodney W. Grimes } 1424b88c807SRodney W. Grimes 143ee579ffbSAssar Westerlund /* 144ee579ffbSAssar Westerlund * print name in current style 145ee579ffbSAssar Westerlund */ 1461656f850STim J. Robbins int 14746251ddeSWarner Losh printname(const char *name) 148ee579ffbSAssar Westerlund { 149ee579ffbSAssar Westerlund if (f_octal || f_octal_escape) 150ee579ffbSAssar Westerlund return prn_octal(name); 151ee579ffbSAssar Westerlund else if (f_nonprint) 152ee579ffbSAssar Westerlund return prn_printable(name); 153ee579ffbSAssar Westerlund else 154ee579ffbSAssar Westerlund return printf("%s", name); 155ee579ffbSAssar Westerlund } 156ee579ffbSAssar Westerlund 1574b88c807SRodney W. Grimes void 15840feca3aSMark Murray printlong(const DISPLAY *dp) 1594b88c807SRodney W. Grimes { 1604b88c807SRodney W. Grimes struct stat *sp; 1614b88c807SRodney W. Grimes FTSENT *p; 1624b88c807SRodney W. Grimes NAMES *np; 1634b88c807SRodney W. Grimes char buf[20]; 16447bb6b11SAndrey A. Chernov #ifdef COLORLS 16547bb6b11SAndrey A. Chernov int color_printed = 0; 16647bb6b11SAndrey A. Chernov #endif 167dd9aaeb0STim J. Robbins int haveacls; 168dd9aaeb0STim J. Robbins dev_t prevdev; 1694b88c807SRodney W. Grimes 1704b88c807SRodney W. Grimes if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size)) 1714b88c807SRodney W. Grimes (void)printf("total %lu\n", howmany(dp->btotal, blocksize)); 1724b88c807SRodney W. Grimes 173dd9aaeb0STim J. Robbins haveacls = 1; 174dd9aaeb0STim J. Robbins prevdev = (dev_t)-1; 1754b88c807SRodney W. Grimes for (p = dp->list; p; p = p->fts_link) { 1764b88c807SRodney W. Grimes if (IS_NOPRINT(p)) 1774b88c807SRodney W. Grimes continue; 1784b88c807SRodney W. Grimes sp = p->fts_statp; 1794b88c807SRodney W. Grimes if (f_inode) 180fb5cb208SSteve Price (void)printf("%*lu ", dp->s_inode, (u_long)sp->st_ino); 1814b88c807SRodney W. Grimes if (f_size) 18240feca3aSMark Murray (void)printf("%*jd ", 1834b88c807SRodney W. Grimes dp->s_block, howmany(sp->st_blocks, blocksize)); 1849052855aSMark Murray strmode(sp->st_mode, buf); 185dd9aaeb0STim J. Robbins /* 186dd9aaeb0STim J. Robbins * Cache whether or not the filesystem supports ACL's to 187dd9aaeb0STim J. Robbins * avoid expensive syscalls. Try again when we change devices. 188dd9aaeb0STim J. Robbins */ 189dd9aaeb0STim J. Robbins if (haveacls || sp->st_dev != prevdev) { 190dd9aaeb0STim J. Robbins aclmode(buf, p, &haveacls); 191dd9aaeb0STim J. Robbins prevdev = sp->st_dev; 192dd9aaeb0STim J. Robbins } 1934b88c807SRodney W. Grimes np = p->fts_pointer; 1944b88c807SRodney W. Grimes (void)printf("%s %*u %-*s %-*s ", buf, dp->s_nlink, 1954b88c807SRodney W. Grimes sp->st_nlink, dp->s_user, np->user, dp->s_group, 1964b88c807SRodney W. Grimes np->group); 1974b88c807SRodney W. Grimes if (f_flags) 1984b88c807SRodney W. Grimes (void)printf("%-*s ", dp->s_flags, np->flags); 1994d33b62eSRobert Watson if (f_label) 2004d33b62eSRobert Watson (void)printf("%-*s ", dp->s_label, np->label); 2014b88c807SRodney W. Grimes if (S_ISCHR(sp->st_mode) || S_ISBLK(sp->st_mode)) 202029b2bd0SBruce Evans if (minor(sp->st_rdev) > 255 || minor(sp->st_rdev) < 0) 203df2fbf15SJoerg Wunsch (void)printf("%3d, 0x%08x ", 204029b2bd0SBruce Evans major(sp->st_rdev), 205029b2bd0SBruce Evans (u_int)minor(sp->st_rdev)); 206df2fbf15SJoerg Wunsch else 2074b88c807SRodney W. Grimes (void)printf("%3d, %3d ", 2084b88c807SRodney W. Grimes major(sp->st_rdev), minor(sp->st_rdev)); 2094b88c807SRodney W. Grimes else if (dp->bcfile) 21040feca3aSMark Murray (void)printf("%*s%*jd ", 2114b88c807SRodney W. Grimes 8 - dp->s_size, "", dp->s_size, sp->st_size); 2124b88c807SRodney W. Grimes else 2130e8d1551SJosef Karthauser printsize(dp->s_size, sp->st_size); 2144b88c807SRodney W. Grimes if (f_accesstime) 2154b88c807SRodney W. Grimes printtime(sp->st_atime); 2164b88c807SRodney W. Grimes else if (f_statustime) 2174b88c807SRodney W. Grimes printtime(sp->st_ctime); 2184b88c807SRodney W. Grimes else 2194b88c807SRodney W. Grimes printtime(sp->st_mtime); 22074985094SJosef Karthauser #ifdef COLORLS 2213885812cSJosef Karthauser if (f_color) 222cf0feaeeSAndrey A. Chernov color_printed = colortype(sp->st_mode); 22374985094SJosef Karthauser #endif 224ee579ffbSAssar Westerlund (void)printname(p->fts_name); 22574985094SJosef Karthauser #ifdef COLORLS 226cf0feaeeSAndrey A. Chernov if (f_color && color_printed) 22738782c25SAndrey A. Chernov endcolor(0); 22874985094SJosef Karthauser #endif 2294b88c807SRodney W. Grimes if (f_type) 2304b88c807SRodney W. Grimes (void)printtype(sp->st_mode); 2314b88c807SRodney W. Grimes if (S_ISLNK(sp->st_mode)) 2324b88c807SRodney W. Grimes printlink(p); 2334b88c807SRodney W. Grimes (void)putchar('\n'); 2344b88c807SRodney W. Grimes } 2354b88c807SRodney W. Grimes } 2364b88c807SRodney W. Grimes 2374b88c807SRodney W. Grimes void 23840feca3aSMark Murray printstream(const DISPLAY *dp) 23994274c73STim J. Robbins { 24094274c73STim J. Robbins FTSENT *p; 24194274c73STim J. Robbins int chcnt; 24294274c73STim J. Robbins 24394274c73STim J. Robbins for (p = dp->list, chcnt = 0; p; p = p->fts_link) { 24494274c73STim J. Robbins if (p->fts_number == NO_PRINT) 24594274c73STim J. Robbins continue; 24694274c73STim J. Robbins if (strlen(p->fts_name) + chcnt + 24794274c73STim J. Robbins (p->fts_link ? 2 : 0) >= (unsigned)termwidth) { 24894274c73STim J. Robbins putchar('\n'); 24994274c73STim J. Robbins chcnt = 0; 25094274c73STim J. Robbins } 25194274c73STim J. Robbins chcnt += printaname(p, dp->s_inode, dp->s_block); 25294274c73STim J. Robbins if (p->fts_link) { 25394274c73STim J. Robbins printf(", "); 25494274c73STim J. Robbins chcnt += 2; 25594274c73STim J. Robbins } 25694274c73STim J. Robbins } 25794274c73STim J. Robbins if (chcnt) 25894274c73STim J. Robbins putchar('\n'); 25994274c73STim J. Robbins } 26094274c73STim J. Robbins 26194274c73STim J. Robbins void 26240feca3aSMark Murray printcol(const DISPLAY *dp) 2634b88c807SRodney W. Grimes { 2644b88c807SRodney W. Grimes static FTSENT **array; 2654b88c807SRodney W. Grimes static int lastentries = -1; 2664b88c807SRodney W. Grimes FTSENT *p; 267c5bc8709STim J. Robbins FTSENT **narray; 268b0bc91e9SJosef Karthauser int base; 269b0bc91e9SJosef Karthauser int chcnt; 270b0bc91e9SJosef Karthauser int cnt; 271b0bc91e9SJosef Karthauser int col; 272b0bc91e9SJosef Karthauser int colwidth; 273b0bc91e9SJosef Karthauser int endcol; 274b0bc91e9SJosef Karthauser int num; 275b0bc91e9SJosef Karthauser int numcols; 276b0bc91e9SJosef Karthauser int numrows; 277b0bc91e9SJosef Karthauser int row; 278545f583cSTim Vanderhoek int tabwidth; 279545f583cSTim Vanderhoek 280545f583cSTim Vanderhoek if (f_notabs) 281545f583cSTim Vanderhoek tabwidth = 1; 282545f583cSTim Vanderhoek else 283545f583cSTim Vanderhoek tabwidth = 8; 2844b88c807SRodney W. Grimes 2854b88c807SRodney W. Grimes /* 2864b88c807SRodney W. Grimes * Have to do random access in the linked list -- build a table 2874b88c807SRodney W. Grimes * of pointers. 2884b88c807SRodney W. Grimes */ 2894b88c807SRodney W. Grimes if (dp->entries > lastentries) { 290c5bc8709STim J. Robbins if ((narray = 2914b88c807SRodney W. Grimes realloc(array, dp->entries * sizeof(FTSENT *))) == NULL) { 2924b88c807SRodney W. Grimes warn(NULL); 2934b88c807SRodney W. Grimes printscol(dp); 294c5bc8709STim J. Robbins return; 2954b88c807SRodney W. Grimes } 296c5bc8709STim J. Robbins lastentries = dp->entries; 297c5bc8709STim J. Robbins array = narray; 2984b88c807SRodney W. Grimes } 2994b88c807SRodney W. Grimes for (p = dp->list, num = 0; p; p = p->fts_link) 3004b88c807SRodney W. Grimes if (p->fts_number != NO_PRINT) 3014b88c807SRodney W. Grimes array[num++] = p; 3024b88c807SRodney W. Grimes 3034b88c807SRodney W. Grimes colwidth = dp->maxlen; 3044b88c807SRodney W. Grimes if (f_inode) 3054b88c807SRodney W. Grimes colwidth += dp->s_inode + 1; 3064b88c807SRodney W. Grimes if (f_size) 3074b88c807SRodney W. Grimes colwidth += dp->s_block + 1; 3084b88c807SRodney W. Grimes if (f_type) 3094b88c807SRodney W. Grimes colwidth += 1; 3104b88c807SRodney W. Grimes 311545f583cSTim Vanderhoek colwidth = (colwidth + tabwidth) & ~(tabwidth - 1); 3124b88c807SRodney W. Grimes if (termwidth < 2 * colwidth) { 3134b88c807SRodney W. Grimes printscol(dp); 3144b88c807SRodney W. Grimes return; 3154b88c807SRodney W. Grimes } 3164b88c807SRodney W. Grimes numcols = termwidth / colwidth; 3174b88c807SRodney W. Grimes numrows = num / numcols; 3184b88c807SRodney W. Grimes if (num % numcols) 3194b88c807SRodney W. Grimes ++numrows; 3204b88c807SRodney W. Grimes 3214b88c807SRodney W. Grimes if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size)) 3224b88c807SRodney W. Grimes (void)printf("total %lu\n", howmany(dp->btotal, blocksize)); 32394274c73STim J. Robbins 32494274c73STim J. Robbins base = 0; 3254b88c807SRodney W. Grimes for (row = 0; row < numrows; ++row) { 3264b88c807SRodney W. Grimes endcol = colwidth; 32794274c73STim J. Robbins if (!f_sortacross) 32894274c73STim J. Robbins base = row; 32994274c73STim J. Robbins for (col = 0, chcnt = 0; col < numcols; ++col) { 3304b88c807SRodney W. Grimes chcnt += printaname(array[base], dp->s_inode, 3314b88c807SRodney W. Grimes dp->s_block); 33294274c73STim J. Robbins if (f_sortacross) 33394274c73STim J. Robbins base++; 33494274c73STim J. Robbins else 33594274c73STim J. Robbins base += numrows; 33694274c73STim J. Robbins if (base >= num) 3374b88c807SRodney W. Grimes break; 338545f583cSTim Vanderhoek while ((cnt = ((chcnt + tabwidth) & ~(tabwidth - 1))) 339545f583cSTim Vanderhoek <= endcol) { 34094274c73STim J. Robbins if (f_sortacross && col + 1 >= numcols) 34194274c73STim J. Robbins break; 342545f583cSTim Vanderhoek (void)putchar(f_notabs ? ' ' : '\t'); 3434b88c807SRodney W. Grimes chcnt = cnt; 3444b88c807SRodney W. Grimes } 3454b88c807SRodney W. Grimes endcol += colwidth; 3464b88c807SRodney W. Grimes } 3474b88c807SRodney W. Grimes (void)putchar('\n'); 3484b88c807SRodney W. Grimes } 3494b88c807SRodney W. Grimes } 3504b88c807SRodney W. Grimes 3514b88c807SRodney W. Grimes /* 3524b88c807SRodney W. Grimes * print [inode] [size] name 3534b88c807SRodney W. Grimes * return # of characters printed, no trailing characters. 3544b88c807SRodney W. Grimes */ 3554b88c807SRodney W. Grimes static int 35640feca3aSMark Murray printaname(const FTSENT *p, u_long inodefield, u_long sizefield) 3574b88c807SRodney W. Grimes { 3584b88c807SRodney W. Grimes struct stat *sp; 3594b88c807SRodney W. Grimes int chcnt; 36047bb6b11SAndrey A. Chernov #ifdef COLORLS 36147bb6b11SAndrey A. Chernov int color_printed = 0; 36247bb6b11SAndrey A. Chernov #endif 3634b88c807SRodney W. Grimes 3644b88c807SRodney W. Grimes sp = p->fts_statp; 3654b88c807SRodney W. Grimes chcnt = 0; 3664b88c807SRodney W. Grimes if (f_inode) 367fb5cb208SSteve Price chcnt += printf("%*lu ", (int)inodefield, (u_long)sp->st_ino); 3684b88c807SRodney W. Grimes if (f_size) 36940feca3aSMark Murray chcnt += printf("%*jd ", 3704b88c807SRodney W. Grimes (int)sizefield, howmany(sp->st_blocks, blocksize)); 37174985094SJosef Karthauser #ifdef COLORLS 3723885812cSJosef Karthauser if (f_color) 373cf0feaeeSAndrey A. Chernov color_printed = colortype(sp->st_mode); 37474985094SJosef Karthauser #endif 375ee579ffbSAssar Westerlund chcnt += printname(p->fts_name); 37674985094SJosef Karthauser #ifdef COLORLS 377cf0feaeeSAndrey A. Chernov if (f_color && color_printed) 37838782c25SAndrey A. Chernov endcolor(0); 37974985094SJosef Karthauser #endif 3804b88c807SRodney W. Grimes if (f_type) 3814b88c807SRodney W. Grimes chcnt += printtype(sp->st_mode); 3824b88c807SRodney W. Grimes return (chcnt); 3834b88c807SRodney W. Grimes } 3844b88c807SRodney W. Grimes 3854b88c807SRodney W. Grimes static void 38646251ddeSWarner Losh printtime(time_t ftime) 3874b88c807SRodney W. Grimes { 388fc4a9bafSAndrey A. Chernov char longstring[80]; 38940feca3aSMark Murray static time_t now = 0; 39097e4e97bSJosef Karthauser const char *format; 3918234eb25SAndrey A. Chernov static int d_first = -1; 392f173abd0SMike Pritchard 39328fd017aSAndrey A. Chernov if (d_first < 0) 39428fd017aSAndrey A. Chernov d_first = (*nl_langinfo(D_MD_ORDER) == 'd'); 395f173abd0SMike Pritchard if (now == 0) 396f173abd0SMike Pritchard now = time(NULL); 3974b88c807SRodney W. Grimes 398656dcd43SGarrett Wollman #define SIXMONTHS ((365 / 2) * 86400) 3994b88c807SRodney W. Grimes if (f_sectime) 4001e715e34SJosef Karthauser /* mmm dd hh:mm:ss yyyy || dd mmm hh:mm:ss yyyy */ 40128fd017aSAndrey A. Chernov format = d_first ? "%e %b %T %Y " : "%b %e %T %Y "; 402f173abd0SMike Pritchard else if (ftime + SIXMONTHS > now && ftime < now + SIXMONTHS) 4031e715e34SJosef Karthauser /* mmm dd hh:mm || dd mmm hh:mm */ 40428fd017aSAndrey A. Chernov format = d_first ? "%e %b %R " : "%b %e %R "; 40597e4e97bSJosef Karthauser else 4061e715e34SJosef Karthauser /* mmm dd yyyy || dd mmm yyyy */ 40728fd017aSAndrey A. Chernov format = d_first ? "%e %b %Y " : "%b %e %Y "; 40897e4e97bSJosef Karthauser strftime(longstring, sizeof(longstring), format, localtime(&ftime)); 40997e4e97bSJosef Karthauser fputs(longstring, stdout); 4104b88c807SRodney W. Grimes } 4114b88c807SRodney W. Grimes 4124b88c807SRodney W. Grimes static int 41346251ddeSWarner Losh printtype(u_int mode) 4144b88c807SRodney W. Grimes { 41594274c73STim J. Robbins 41694274c73STim J. Robbins if (f_slash) { 41794274c73STim J. Robbins if ((mode & S_IFMT) == S_IFDIR) { 41894274c73STim J. Robbins (void)putchar('/'); 41994274c73STim J. Robbins return (1); 42094274c73STim J. Robbins } 42194274c73STim J. Robbins return (0); 42294274c73STim J. Robbins } 42394274c73STim J. Robbins 4244b88c807SRodney W. Grimes switch (mode & S_IFMT) { 4254b88c807SRodney W. Grimes case S_IFDIR: 4264b88c807SRodney W. Grimes (void)putchar('/'); 4274b88c807SRodney W. Grimes return (1); 4284b88c807SRodney W. Grimes case S_IFIFO: 4294b88c807SRodney W. Grimes (void)putchar('|'); 4304b88c807SRodney W. Grimes return (1); 4314b88c807SRodney W. Grimes case S_IFLNK: 4324b88c807SRodney W. Grimes (void)putchar('@'); 4334b88c807SRodney W. Grimes return (1); 4344b88c807SRodney W. Grimes case S_IFSOCK: 4354b88c807SRodney W. Grimes (void)putchar('='); 4364b88c807SRodney W. Grimes return (1); 437fb5cb208SSteve Price case S_IFWHT: 438fb5cb208SSteve Price (void)putchar('%'); 439fb5cb208SSteve Price return (1); 4409052855aSMark Murray default: 441568dcd5fSBill Fumerola break; 4424b88c807SRodney W. Grimes } 4434b88c807SRodney W. Grimes if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) { 4444b88c807SRodney W. Grimes (void)putchar('*'); 4454b88c807SRodney W. Grimes return (1); 4464b88c807SRodney W. Grimes } 4474b88c807SRodney W. Grimes return (0); 4484b88c807SRodney W. Grimes } 4494b88c807SRodney W. Grimes 45074985094SJosef Karthauser #ifdef COLORLS 4511bf1478aSAndrey A. Chernov static int 45246251ddeSWarner Losh putch(int c) 453cf0feaeeSAndrey A. Chernov { 45438782c25SAndrey A. Chernov (void)putchar(c); 45538782c25SAndrey A. Chernov return 0; 456cf0feaeeSAndrey A. Chernov } 457cf0feaeeSAndrey A. Chernov 4581bf1478aSAndrey A. Chernov static int 45946251ddeSWarner Losh writech(int c) 46038782c25SAndrey A. Chernov { 46140feca3aSMark Murray char tmp = (char)c; 46238782c25SAndrey A. Chernov 46338782c25SAndrey A. Chernov (void)write(STDOUT_FILENO, &tmp, 1); 46438782c25SAndrey A. Chernov return 0; 46538782c25SAndrey A. Chernov } 466cf0feaeeSAndrey A. Chernov 4671bf1478aSAndrey A. Chernov static void 46846251ddeSWarner Losh printcolor(Colors c) 4693885812cSJosef Karthauser { 47074985094SJosef Karthauser char *ansiseq; 47174985094SJosef Karthauser 472c1499cf6SJosef Karthauser if (colors[c].bold) 473c1499cf6SJosef Karthauser tputs(enter_bold, 1, putch); 474c1499cf6SJosef Karthauser 475c1499cf6SJosef Karthauser if (colors[c].num[0] != -1) { 476c1499cf6SJosef Karthauser ansiseq = tgoto(ansi_fgcol, 0, colors[c].num[0]); 47738782c25SAndrey A. Chernov if (ansiseq) 478cf0feaeeSAndrey A. Chernov tputs(ansiseq, 1, putch); 4793885812cSJosef Karthauser } 480c1499cf6SJosef Karthauser if (colors[c].num[1] != -1) { 481c1499cf6SJosef Karthauser ansiseq = tgoto(ansi_bgcol, 0, colors[c].num[1]); 48238782c25SAndrey A. Chernov if (ansiseq) 483cf0feaeeSAndrey A. Chernov tputs(ansiseq, 1, putch); 48474985094SJosef Karthauser } 48574985094SJosef Karthauser } 48674985094SJosef Karthauser 48738782c25SAndrey A. Chernov static void 48846251ddeSWarner Losh endcolor(int sig) 48974985094SJosef Karthauser { 49038782c25SAndrey A. Chernov tputs(ansi_coloff, 1, sig ? writech : putch); 491c1499cf6SJosef Karthauser tputs(attrs_off, 1, sig ? writech : putch); 4923885812cSJosef Karthauser } 4933885812cSJosef Karthauser 49438782c25SAndrey A. Chernov static int 49546251ddeSWarner Losh colortype(mode_t mode) 4963885812cSJosef Karthauser { 4973885812cSJosef Karthauser switch (mode & S_IFMT) { 4983885812cSJosef Karthauser case S_IFDIR: 4993885812cSJosef Karthauser if (mode & S_IWOTH) 5003885812cSJosef Karthauser if (mode & S_ISTXT) 5013885812cSJosef Karthauser printcolor(C_WSDIR); 5023885812cSJosef Karthauser else 5033885812cSJosef Karthauser printcolor(C_WDIR); 5043885812cSJosef Karthauser else 5053885812cSJosef Karthauser printcolor(C_DIR); 5063885812cSJosef Karthauser return (1); 5073885812cSJosef Karthauser case S_IFLNK: 5083885812cSJosef Karthauser printcolor(C_LNK); 5093885812cSJosef Karthauser return (1); 5103885812cSJosef Karthauser case S_IFSOCK: 5113885812cSJosef Karthauser printcolor(C_SOCK); 5123885812cSJosef Karthauser return (1); 5133885812cSJosef Karthauser case S_IFIFO: 5143885812cSJosef Karthauser printcolor(C_FIFO); 5153885812cSJosef Karthauser return (1); 5163885812cSJosef Karthauser case S_IFBLK: 5173885812cSJosef Karthauser printcolor(C_BLK); 5183885812cSJosef Karthauser return (1); 5193885812cSJosef Karthauser case S_IFCHR: 5203885812cSJosef Karthauser printcolor(C_CHR); 5213885812cSJosef Karthauser return (1); 52240feca3aSMark Murray default:; 5233885812cSJosef Karthauser } 5243885812cSJosef Karthauser if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) { 5253885812cSJosef Karthauser if (mode & S_ISUID) 5263885812cSJosef Karthauser printcolor(C_SUID); 5273885812cSJosef Karthauser else if (mode & S_ISGID) 5283885812cSJosef Karthauser printcolor(C_SGID); 5293885812cSJosef Karthauser else 5303885812cSJosef Karthauser printcolor(C_EXEC); 5313885812cSJosef Karthauser return (1); 5323885812cSJosef Karthauser } 5333885812cSJosef Karthauser return (0); 5343885812cSJosef Karthauser } 5353885812cSJosef Karthauser 5363885812cSJosef Karthauser void 53746251ddeSWarner Losh parsecolors(const char *cs) 5383885812cSJosef Karthauser { 539b0bc91e9SJosef Karthauser int i; 540b0bc91e9SJosef Karthauser int j; 541ca2993fbSMark Murray size_t len; 5423885812cSJosef Karthauser char c[2]; 543c1499cf6SJosef Karthauser short legacy_warn = 0; 54438782c25SAndrey A. Chernov 545b0bc91e9SJosef Karthauser if (cs == NULL) 546b0bc91e9SJosef Karthauser cs = ""; /* LSCOLORS not set */ 5473885812cSJosef Karthauser len = strlen(cs); 54840feca3aSMark Murray for (i = 0; i < (int)C_NUMCOLORS; i++) { 549c1499cf6SJosef Karthauser colors[i].bold = 0; 550c1499cf6SJosef Karthauser 55140feca3aSMark Murray if (len <= 2 * (size_t)i) { 5523885812cSJosef Karthauser c[0] = defcolors[2 * i]; 5533885812cSJosef Karthauser c[1] = defcolors[2 * i + 1]; 5545dda5d0dSJosef Karthauser } else { 5553885812cSJosef Karthauser c[0] = cs[2 * i]; 5563885812cSJosef Karthauser c[1] = cs[2 * i + 1]; 5573885812cSJosef Karthauser } 5583885812cSJosef Karthauser for (j = 0; j < 2; j++) { 559c1499cf6SJosef Karthauser /* Legacy colours used 0-7 */ 560c1499cf6SJosef Karthauser if (c[j] >= '0' && c[j] <= '7') { 561c1499cf6SJosef Karthauser colors[i].num[j] = c[j] - '0'; 562c1499cf6SJosef Karthauser if (!legacy_warn) { 563e09fdabdSTim J. Robbins warnx("LSCOLORS should use " 564130d15dcSJosef Karthauser "characters a-h instead of 0-9 (" 565e09fdabdSTim J. Robbins "see the manual page)"); 5663885812cSJosef Karthauser } 567c1499cf6SJosef Karthauser legacy_warn = 1; 568c1499cf6SJosef Karthauser } else if (c[j] >= 'a' && c[j] <= 'h') 569c1499cf6SJosef Karthauser colors[i].num[j] = c[j] - 'a'; 570c1499cf6SJosef Karthauser else if (c[j] >= 'A' && c[j] <= 'H') { 571c1499cf6SJosef Karthauser colors[i].num[j] = c[j] - 'A'; 572c1499cf6SJosef Karthauser colors[i].bold = 1; 57340feca3aSMark Murray } else if (tolower((unsigned char)c[j]) == 'x') 574c1499cf6SJosef Karthauser colors[i].num[j] = -1; 575c1499cf6SJosef Karthauser else { 576e09fdabdSTim J. Robbins warnx("invalid character '%c' in LSCOLORS" 577e09fdabdSTim J. Robbins " env var", c[j]); 5780d72516eSJosef Karthauser colors[i].num[j] = -1; 579c1499cf6SJosef Karthauser } 5803885812cSJosef Karthauser } 5813885812cSJosef Karthauser } 5823885812cSJosef Karthauser } 583cf0feaeeSAndrey A. Chernov 5841bf1478aSAndrey A. Chernov void 58546251ddeSWarner Losh colorquit(int sig) 586cf0feaeeSAndrey A. Chernov { 58738782c25SAndrey A. Chernov endcolor(sig); 588faebfe2eSAndrey A. Chernov 589faebfe2eSAndrey A. Chernov (void)signal(sig, SIG_DFL); 590faebfe2eSAndrey A. Chernov (void)kill(getpid(), sig); 591cf0feaeeSAndrey A. Chernov } 5925dda5d0dSJosef Karthauser 59374985094SJosef Karthauser #endif /* COLORLS */ 5943885812cSJosef Karthauser 5954b88c807SRodney W. Grimes static void 596ca2993fbSMark Murray printlink(const FTSENT *p) 5974b88c807SRodney W. Grimes { 5984b88c807SRodney W. Grimes int lnklen; 599b0bc91e9SJosef Karthauser char name[MAXPATHLEN + 1]; 600b0bc91e9SJosef Karthauser char path[MAXPATHLEN + 1]; 6014b88c807SRodney W. Grimes 6024b88c807SRodney W. Grimes if (p->fts_level == FTS_ROOTLEVEL) 6034b88c807SRodney W. Grimes (void)snprintf(name, sizeof(name), "%s", p->fts_name); 6044b88c807SRodney W. Grimes else 6054b88c807SRodney W. Grimes (void)snprintf(name, sizeof(name), 6064b88c807SRodney W. Grimes "%s/%s", p->fts_parent->fts_accpath, p->fts_name); 6074b88c807SRodney W. Grimes if ((lnklen = readlink(name, path, sizeof(path) - 1)) == -1) { 6084b88c807SRodney W. Grimes (void)fprintf(stderr, "\nls: %s: %s\n", name, strerror(errno)); 6094b88c807SRodney W. Grimes return; 6104b88c807SRodney W. Grimes } 6114b88c807SRodney W. Grimes path[lnklen] = '\0'; 6127ea30648SDag-Erling Smørgrav (void)printf(" -> "); 6139052855aSMark Murray (void)printname(path); 6144b88c807SRodney W. Grimes } 6150e8d1551SJosef Karthauser 6160e8d1551SJosef Karthauser static void 61746251ddeSWarner Losh printsize(size_t width, off_t bytes) 6180e8d1551SJosef Karthauser { 619598420eeSDima Dorfman double dbytes; 6200e8d1551SJosef Karthauser unit_t unit; 6210e8d1551SJosef Karthauser 6220e8d1551SJosef Karthauser if (f_humanval) { 623598420eeSDima Dorfman dbytes = bytes; 624598420eeSDima Dorfman unit = unit_adjust(&dbytes); 6250e8d1551SJosef Karthauser 626598420eeSDima Dorfman if (dbytes == 0) 62740feca3aSMark Murray (void)printf("%*s ", (u_int)width, "0B"); 6280e8d1551SJosef Karthauser else 62940feca3aSMark Murray (void)printf("%*.*f%c ", (u_int)width - 1, 63040feca3aSMark Murray dbytes > 10 ? 0 : 1, dbytes, "BKMGTPE"[unit]); 6315dda5d0dSJosef Karthauser } else 63240feca3aSMark Murray (void)printf("%*jd ", (u_int)width, bytes); 6330e8d1551SJosef Karthauser } 6340e8d1551SJosef Karthauser 6350e8d1551SJosef Karthauser /* 6360e8d1551SJosef Karthauser * Output in "human-readable" format. Uses 3 digits max and puts 6370e8d1551SJosef Karthauser * unit suffixes at the end. Makes output compact and easy to read, 6380e8d1551SJosef Karthauser * especially on huge disks. 6390e8d1551SJosef Karthauser * 6400e8d1551SJosef Karthauser */ 641ca2993fbSMark Murray static unit_t 642598420eeSDima Dorfman unit_adjust(double *val) 6430e8d1551SJosef Karthauser { 6440e8d1551SJosef Karthauser double abval; 6450e8d1551SJosef Karthauser unit_t unit; 646ca2993fbSMark Murray u_int unit_sz; 6470e8d1551SJosef Karthauser 648598420eeSDima Dorfman abval = fabs(*val); 6490e8d1551SJosef Karthauser 650ca2993fbSMark Murray unit_sz = abval ? (u_int)ilogb(abval) / 10 : 0; 6510e8d1551SJosef Karthauser 652ca2993fbSMark Murray if (unit_sz >= (u_int)UNIT_MAX) { 6530e8d1551SJosef Karthauser unit = NONE; 6540e8d1551SJosef Karthauser } else { 6550e8d1551SJosef Karthauser unit = unitp[unit_sz]; 6560e8d1551SJosef Karthauser *val /= (double)vals_base2[unit_sz]; 6570e8d1551SJosef Karthauser } 6580e8d1551SJosef Karthauser 6590e8d1551SJosef Karthauser return (unit); 6600e8d1551SJosef Karthauser } 661dd9aaeb0STim J. Robbins 662dd9aaeb0STim J. Robbins static void 66340feca3aSMark Murray aclmode(char *buf, const FTSENT *p, int *haveacls) 664dd9aaeb0STim J. Robbins { 665dd9aaeb0STim J. Robbins char name[MAXPATHLEN + 1]; 666dd9aaeb0STim J. Robbins int entries, ret; 667dd9aaeb0STim J. Robbins acl_t facl; 668dd9aaeb0STim J. Robbins acl_entry_t ae; 669dd9aaeb0STim J. Robbins 670dd9aaeb0STim J. Robbins /* 671dd9aaeb0STim J. Robbins * Add a + after the standard rwxrwxrwx mode if the file has an 672dd9aaeb0STim J. Robbins * extended ACL. strmode() reserves space at the end of the string. 673dd9aaeb0STim J. Robbins */ 674dd9aaeb0STim J. Robbins if (p->fts_level == FTS_ROOTLEVEL) 675dd9aaeb0STim J. Robbins snprintf(name, sizeof(name), "%s", p->fts_name); 676dd9aaeb0STim J. Robbins else 677dd9aaeb0STim J. Robbins snprintf(name, sizeof(name), "%s/%s", 678dd9aaeb0STim J. Robbins p->fts_parent->fts_accpath, p->fts_name); 6793fceb9fdSTim J. Robbins /* 6803fceb9fdSTim J. Robbins * We have no way to tell whether a symbolic link has an ACL since 6813fceb9fdSTim J. Robbins * pathconf() and acl_get_file() both follow them. 6823fceb9fdSTim J. Robbins */ 6833fceb9fdSTim J. Robbins if (S_ISLNK(p->fts_statp->st_mode)) { 6843fceb9fdSTim J. Robbins *haveacls = 1; 6853fceb9fdSTim J. Robbins return; 6863fceb9fdSTim J. Robbins } 687dd9aaeb0STim J. Robbins if ((ret = pathconf(name, _PC_ACL_EXTENDED)) <= 0) { 688dd9aaeb0STim J. Robbins if (ret < 0 && errno != EINVAL) 689dd9aaeb0STim J. Robbins warn("%s", name); 690dd9aaeb0STim J. Robbins else 691dd9aaeb0STim J. Robbins *haveacls = 0; 692dd9aaeb0STim J. Robbins return; 693dd9aaeb0STim J. Robbins } 694dd9aaeb0STim J. Robbins *haveacls = 1; 695dd9aaeb0STim J. Robbins if ((facl = acl_get_file(name, ACL_TYPE_ACCESS)) != NULL) { 696dd9aaeb0STim J. Robbins if (acl_get_entry(facl, ACL_FIRST_ENTRY, &ae) == 1) { 697dd9aaeb0STim J. Robbins entries = 0; 698dd9aaeb0STim J. Robbins do 699dd9aaeb0STim J. Robbins entries++; 700dd9aaeb0STim J. Robbins while (acl_get_entry(facl, ACL_NEXT_ENTRY, &ae) == 1); 701dd9aaeb0STim J. Robbins if (entries != 3) 702dd9aaeb0STim J. Robbins buf[10] = '+'; 703dd9aaeb0STim J. Robbins } 704dd9aaeb0STim J. Robbins acl_free(facl); 705dd9aaeb0STim J. Robbins } else 706dd9aaeb0STim J. Robbins warn("%s", name); 707dd9aaeb0STim J. Robbins } 708