19ddb49cbSWarner Losh /*- 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 * 4. Neither the name of the University nor the names of its contributors 174b88c807SRodney W. Grimes * may be used to endorse or promote products derived from this software 184b88c807SRodney W. Grimes * without specific prior written permission. 194b88c807SRodney W. Grimes * 204b88c807SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 214b88c807SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 224b88c807SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 234b88c807SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 244b88c807SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 254b88c807SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 264b88c807SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 274b88c807SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 284b88c807SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 294b88c807SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 304b88c807SRodney W. Grimes * SUCH DAMAGE. 314b88c807SRodney W. Grimes */ 324b88c807SRodney W. Grimes 33febad2fcSSteve Price #if 0 34c73d77ceSMark Murray #ifndef lint 35febad2fcSSteve Price static char sccsid[] = "@(#)print.c 8.4 (Berkeley) 4/17/94"; 364b88c807SRodney W. Grimes #endif /* not lint */ 37c73d77ceSMark Murray #endif 385eb43ac2SDavid E. O'Brien #include <sys/cdefs.h> 395eb43ac2SDavid E. O'Brien __FBSDID("$FreeBSD$"); 404b88c807SRodney W. Grimes 414b88c807SRodney W. Grimes #include <sys/param.h> 424b88c807SRodney W. Grimes #include <sys/stat.h> 43dd9aaeb0STim J. Robbins #include <sys/acl.h> 444b88c807SRodney W. Grimes 454b88c807SRodney W. Grimes #include <err.h> 464b88c807SRodney W. Grimes #include <errno.h> 474b88c807SRodney W. Grimes #include <fts.h> 4828fd017aSAndrey A. Chernov #include <langinfo.h> 49478aa805SPawel Jakub Dawidek #include <libutil.h> 504b88c807SRodney W. Grimes #include <stdio.h> 519f365aa1SEd Schouten #include <stdint.h> 524b88c807SRodney W. Grimes #include <stdlib.h> 534b88c807SRodney W. Grimes #include <string.h> 54434b6ea4SBruce Evans #include <time.h> 554b88c807SRodney W. Grimes #include <unistd.h> 56faebfe2eSAndrey A. Chernov #ifdef COLORLS 57faebfe2eSAndrey A. Chernov #include <ctype.h> 58faebfe2eSAndrey A. Chernov #include <termcap.h> 59faebfe2eSAndrey A. Chernov #include <signal.h> 60faebfe2eSAndrey A. Chernov #endif 614b88c807SRodney W. Grimes 624b88c807SRodney W. Grimes #include "ls.h" 634b88c807SRodney W. Grimes #include "extern.h" 644b88c807SRodney W. Grimes 6540feca3aSMark Murray static int printaname(const FTSENT *, u_long, u_long); 6655926a66SJaakko Heinonen static void printdev(size_t, dev_t); 67ca2993fbSMark Murray static void printlink(const FTSENT *); 6846251ddeSWarner Losh static void printtime(time_t); 6946251ddeSWarner Losh static int printtype(u_int); 7046251ddeSWarner Losh static void printsize(size_t, off_t); 7138782c25SAndrey A. Chernov #ifdef COLORLS 7246251ddeSWarner Losh static void endcolor(int); 7346251ddeSWarner Losh static int colortype(mode_t); 7438782c25SAndrey A. Chernov #endif 75f7b8687aSEdward Tomasz Napierala static void aclmode(char *, const FTSENT *); 764b88c807SRodney W. Grimes 774b88c807SRodney W. Grimes #define IS_NOPRINT(p) ((p)->fts_number == NO_PRINT) 780e8d1551SJosef Karthauser 7974985094SJosef Karthauser #ifdef COLORLS 803885812cSJosef Karthauser /* Most of these are taken from <sys/stat.h> */ 813885812cSJosef Karthauser typedef enum Colors { 823885812cSJosef Karthauser C_DIR, /* directory */ 833885812cSJosef Karthauser C_LNK, /* symbolic link */ 843885812cSJosef Karthauser C_SOCK, /* socket */ 853885812cSJosef Karthauser C_FIFO, /* pipe */ 863885812cSJosef Karthauser C_EXEC, /* executable */ 873885812cSJosef Karthauser C_BLK, /* block special */ 883885812cSJosef Karthauser C_CHR, /* character special */ 893885812cSJosef Karthauser C_SUID, /* setuid executable */ 903885812cSJosef Karthauser C_SGID, /* setgid executable */ 915dda5d0dSJosef Karthauser C_WSDIR, /* directory writeble to others, with sticky 925dda5d0dSJosef Karthauser * bit */ 935dda5d0dSJosef Karthauser C_WDIR, /* directory writeble to others, without 945dda5d0dSJosef Karthauser * sticky bit */ 953885812cSJosef Karthauser C_NUMCOLORS /* just a place-holder */ 963885812cSJosef Karthauser } Colors; 973885812cSJosef Karthauser 989052855aSMark Murray static const char *defcolors = "exfxcxdxbxegedabagacad"; 993885812cSJosef Karthauser 100c1499cf6SJosef Karthauser /* colors for file types */ 101c1499cf6SJosef Karthauser static struct { 102c1499cf6SJosef Karthauser int num[2]; 103c1499cf6SJosef Karthauser int bold; 104c1499cf6SJosef Karthauser } colors[C_NUMCOLORS]; 10574985094SJosef Karthauser #endif 1063885812cSJosef Karthauser 1074b88c807SRodney W. Grimes void 10840feca3aSMark Murray printscol(const DISPLAY *dp) 1094b88c807SRodney W. Grimes { 1104b88c807SRodney W. Grimes FTSENT *p; 1114b88c807SRodney W. Grimes 1124b88c807SRodney W. Grimes for (p = dp->list; p; p = p->fts_link) { 1134b88c807SRodney W. Grimes if (IS_NOPRINT(p)) 1144b88c807SRodney W. Grimes continue; 1154b88c807SRodney W. Grimes (void)printaname(p, dp->s_inode, dp->s_block); 1164b88c807SRodney W. Grimes (void)putchar('\n'); 1174b88c807SRodney W. Grimes } 1184b88c807SRodney W. Grimes } 1194b88c807SRodney W. Grimes 120ee579ffbSAssar Westerlund /* 121ee579ffbSAssar Westerlund * print name in current style 122ee579ffbSAssar Westerlund */ 1231656f850STim J. Robbins int 12446251ddeSWarner Losh printname(const char *name) 125ee579ffbSAssar Westerlund { 126ee579ffbSAssar Westerlund if (f_octal || f_octal_escape) 127ee579ffbSAssar Westerlund return prn_octal(name); 128ee579ffbSAssar Westerlund else if (f_nonprint) 129ee579ffbSAssar Westerlund return prn_printable(name); 130ee579ffbSAssar Westerlund else 131107409f4STim J. Robbins return prn_normal(name); 132ee579ffbSAssar Westerlund } 133ee579ffbSAssar Westerlund 1344b88c807SRodney W. Grimes void 13540feca3aSMark Murray printlong(const DISPLAY *dp) 1364b88c807SRodney W. Grimes { 1374b88c807SRodney W. Grimes struct stat *sp; 1384b88c807SRodney W. Grimes FTSENT *p; 1394b88c807SRodney W. Grimes NAMES *np; 1404b88c807SRodney W. Grimes char buf[20]; 14147bb6b11SAndrey A. Chernov #ifdef COLORLS 14247bb6b11SAndrey A. Chernov int color_printed = 0; 14347bb6b11SAndrey A. Chernov #endif 1444b88c807SRodney W. Grimes 14548a91b69SDavid Schultz if ((dp->list == NULL || dp->list->fts_level != FTS_ROOTLEVEL) && 14648a91b69SDavid Schultz (f_longform || f_size)) { 1474b88c807SRodney W. Grimes (void)printf("total %lu\n", howmany(dp->btotal, blocksize)); 14848a91b69SDavid Schultz } 1494b88c807SRodney W. Grimes 1504b88c807SRodney W. Grimes for (p = dp->list; p; p = p->fts_link) { 1514b88c807SRodney W. Grimes if (IS_NOPRINT(p)) 1524b88c807SRodney W. Grimes continue; 1534b88c807SRodney W. Grimes sp = p->fts_statp; 1544b88c807SRodney W. Grimes if (f_inode) 155*6db1a7f1SMatthew D Fleming (void)printf("%*ju ", 156*6db1a7f1SMatthew D Fleming dp->s_inode, (uintmax_t)sp->st_ino); 1574b88c807SRodney W. Grimes if (f_size) 15840feca3aSMark Murray (void)printf("%*jd ", 1594b88c807SRodney W. Grimes dp->s_block, howmany(sp->st_blocks, blocksize)); 1609052855aSMark Murray strmode(sp->st_mode, buf); 161f7b8687aSEdward Tomasz Napierala aclmode(buf, p); 1624b88c807SRodney W. Grimes np = p->fts_pointer; 1634b88c807SRodney W. Grimes (void)printf("%s %*u %-*s %-*s ", buf, dp->s_nlink, 1644b88c807SRodney W. Grimes sp->st_nlink, dp->s_user, np->user, dp->s_group, 1654b88c807SRodney W. Grimes np->group); 1664b88c807SRodney W. Grimes if (f_flags) 1674b88c807SRodney W. Grimes (void)printf("%-*s ", dp->s_flags, np->flags); 1684d33b62eSRobert Watson if (f_label) 1694d33b62eSRobert Watson (void)printf("%-*s ", dp->s_label, np->label); 1704b88c807SRodney W. Grimes if (S_ISCHR(sp->st_mode) || S_ISBLK(sp->st_mode)) 17155926a66SJaakko Heinonen printdev(dp->s_size, sp->st_rdev); 1724b88c807SRodney W. Grimes else 1730e8d1551SJosef Karthauser printsize(dp->s_size, sp->st_size); 1744b88c807SRodney W. Grimes if (f_accesstime) 1754b88c807SRodney W. Grimes printtime(sp->st_atime); 176fe79420eSJohn Baldwin else if (f_birthtime) 177fe79420eSJohn Baldwin printtime(sp->st_birthtime); 1784b88c807SRodney W. Grimes else if (f_statustime) 1794b88c807SRodney W. Grimes printtime(sp->st_ctime); 1804b88c807SRodney W. Grimes else 1814b88c807SRodney W. Grimes printtime(sp->st_mtime); 18274985094SJosef Karthauser #ifdef COLORLS 1833885812cSJosef Karthauser if (f_color) 184cf0feaeeSAndrey A. Chernov color_printed = colortype(sp->st_mode); 18574985094SJosef Karthauser #endif 186ee579ffbSAssar Westerlund (void)printname(p->fts_name); 18774985094SJosef Karthauser #ifdef COLORLS 188cf0feaeeSAndrey A. Chernov if (f_color && color_printed) 18938782c25SAndrey A. Chernov endcolor(0); 19074985094SJosef Karthauser #endif 1914b88c807SRodney W. Grimes if (f_type) 1924b88c807SRodney W. Grimes (void)printtype(sp->st_mode); 1934b88c807SRodney W. Grimes if (S_ISLNK(sp->st_mode)) 1944b88c807SRodney W. Grimes printlink(p); 1954b88c807SRodney W. Grimes (void)putchar('\n'); 1964b88c807SRodney W. Grimes } 1974b88c807SRodney W. Grimes } 1984b88c807SRodney W. Grimes 1994b88c807SRodney W. Grimes void 20040feca3aSMark Murray printstream(const DISPLAY *dp) 20194274c73STim J. Robbins { 20294274c73STim J. Robbins FTSENT *p; 20394274c73STim J. Robbins int chcnt; 20494274c73STim J. Robbins 20594274c73STim J. Robbins for (p = dp->list, chcnt = 0; p; p = p->fts_link) { 20694274c73STim J. Robbins if (p->fts_number == NO_PRINT) 20794274c73STim J. Robbins continue; 208107409f4STim J. Robbins /* XXX strlen does not take octal escapes into account. */ 20994274c73STim J. Robbins if (strlen(p->fts_name) + chcnt + 21094274c73STim J. Robbins (p->fts_link ? 2 : 0) >= (unsigned)termwidth) { 21194274c73STim J. Robbins putchar('\n'); 21294274c73STim J. Robbins chcnt = 0; 21394274c73STim J. Robbins } 21494274c73STim J. Robbins chcnt += printaname(p, dp->s_inode, dp->s_block); 21594274c73STim J. Robbins if (p->fts_link) { 21694274c73STim J. Robbins printf(", "); 21794274c73STim J. Robbins chcnt += 2; 21894274c73STim J. Robbins } 21994274c73STim J. Robbins } 22094274c73STim J. Robbins if (chcnt) 22194274c73STim J. Robbins putchar('\n'); 22294274c73STim J. Robbins } 22394274c73STim J. Robbins 22494274c73STim J. Robbins void 22540feca3aSMark Murray printcol(const DISPLAY *dp) 2264b88c807SRodney W. Grimes { 2274b88c807SRodney W. Grimes static FTSENT **array; 2284b88c807SRodney W. Grimes static int lastentries = -1; 2294b88c807SRodney W. Grimes FTSENT *p; 230c5bc8709STim J. Robbins FTSENT **narray; 231b0bc91e9SJosef Karthauser int base; 232b0bc91e9SJosef Karthauser int chcnt; 233b0bc91e9SJosef Karthauser int cnt; 234b0bc91e9SJosef Karthauser int col; 235b0bc91e9SJosef Karthauser int colwidth; 236b0bc91e9SJosef Karthauser int endcol; 237b0bc91e9SJosef Karthauser int num; 238b0bc91e9SJosef Karthauser int numcols; 239b0bc91e9SJosef Karthauser int numrows; 240b0bc91e9SJosef Karthauser int row; 241545f583cSTim Vanderhoek int tabwidth; 242545f583cSTim Vanderhoek 243545f583cSTim Vanderhoek if (f_notabs) 244545f583cSTim Vanderhoek tabwidth = 1; 245545f583cSTim Vanderhoek else 246545f583cSTim Vanderhoek tabwidth = 8; 2474b88c807SRodney W. Grimes 2484b88c807SRodney W. Grimes /* 2494b88c807SRodney W. Grimes * Have to do random access in the linked list -- build a table 2504b88c807SRodney W. Grimes * of pointers. 2514b88c807SRodney W. Grimes */ 2524b88c807SRodney W. Grimes if (dp->entries > lastentries) { 253c5bc8709STim J. Robbins if ((narray = 2544b88c807SRodney W. Grimes realloc(array, dp->entries * sizeof(FTSENT *))) == NULL) { 2554b88c807SRodney W. Grimes warn(NULL); 2564b88c807SRodney W. Grimes printscol(dp); 257c5bc8709STim J. Robbins return; 2584b88c807SRodney W. Grimes } 259c5bc8709STim J. Robbins lastentries = dp->entries; 260c5bc8709STim J. Robbins array = narray; 2614b88c807SRodney W. Grimes } 2624b88c807SRodney W. Grimes for (p = dp->list, num = 0; p; p = p->fts_link) 2634b88c807SRodney W. Grimes if (p->fts_number != NO_PRINT) 2644b88c807SRodney W. Grimes array[num++] = p; 2654b88c807SRodney W. Grimes 2664b88c807SRodney W. Grimes colwidth = dp->maxlen; 2674b88c807SRodney W. Grimes if (f_inode) 2684b88c807SRodney W. Grimes colwidth += dp->s_inode + 1; 2694b88c807SRodney W. Grimes if (f_size) 2704b88c807SRodney W. Grimes colwidth += dp->s_block + 1; 2714b88c807SRodney W. Grimes if (f_type) 2724b88c807SRodney W. Grimes colwidth += 1; 2734b88c807SRodney W. Grimes 274545f583cSTim Vanderhoek colwidth = (colwidth + tabwidth) & ~(tabwidth - 1); 2754b88c807SRodney W. Grimes if (termwidth < 2 * colwidth) { 2764b88c807SRodney W. Grimes printscol(dp); 2774b88c807SRodney W. Grimes return; 2784b88c807SRodney W. Grimes } 2794b88c807SRodney W. Grimes numcols = termwidth / colwidth; 2804b88c807SRodney W. Grimes numrows = num / numcols; 2814b88c807SRodney W. Grimes if (num % numcols) 2824b88c807SRodney W. Grimes ++numrows; 2834b88c807SRodney W. Grimes 28448a91b69SDavid Schultz if ((dp->list == NULL || dp->list->fts_level != FTS_ROOTLEVEL) && 28548a91b69SDavid Schultz (f_longform || f_size)) { 2864b88c807SRodney W. Grimes (void)printf("total %lu\n", howmany(dp->btotal, blocksize)); 28748a91b69SDavid Schultz } 28894274c73STim J. Robbins 28994274c73STim J. Robbins base = 0; 2904b88c807SRodney W. Grimes for (row = 0; row < numrows; ++row) { 2914b88c807SRodney W. Grimes endcol = colwidth; 29294274c73STim J. Robbins if (!f_sortacross) 29394274c73STim J. Robbins base = row; 29494274c73STim J. Robbins for (col = 0, chcnt = 0; col < numcols; ++col) { 2954b88c807SRodney W. Grimes chcnt += printaname(array[base], dp->s_inode, 2964b88c807SRodney W. Grimes dp->s_block); 29794274c73STim J. Robbins if (f_sortacross) 29894274c73STim J. Robbins base++; 29994274c73STim J. Robbins else 30094274c73STim J. Robbins base += numrows; 30194274c73STim J. Robbins if (base >= num) 3024b88c807SRodney W. Grimes break; 303545f583cSTim Vanderhoek while ((cnt = ((chcnt + tabwidth) & ~(tabwidth - 1))) 304545f583cSTim Vanderhoek <= endcol) { 30594274c73STim J. Robbins if (f_sortacross && col + 1 >= numcols) 30694274c73STim J. Robbins break; 307545f583cSTim Vanderhoek (void)putchar(f_notabs ? ' ' : '\t'); 3084b88c807SRodney W. Grimes chcnt = cnt; 3094b88c807SRodney W. Grimes } 3104b88c807SRodney W. Grimes endcol += colwidth; 3114b88c807SRodney W. Grimes } 3124b88c807SRodney W. Grimes (void)putchar('\n'); 3134b88c807SRodney W. Grimes } 3144b88c807SRodney W. Grimes } 3154b88c807SRodney W. Grimes 3164b88c807SRodney W. Grimes /* 3174b88c807SRodney W. Grimes * print [inode] [size] name 3184b88c807SRodney W. Grimes * return # of characters printed, no trailing characters. 3194b88c807SRodney W. Grimes */ 3204b88c807SRodney W. Grimes static int 32140feca3aSMark Murray printaname(const FTSENT *p, u_long inodefield, u_long sizefield) 3224b88c807SRodney W. Grimes { 3234b88c807SRodney W. Grimes struct stat *sp; 3244b88c807SRodney W. Grimes int chcnt; 32547bb6b11SAndrey A. Chernov #ifdef COLORLS 32647bb6b11SAndrey A. Chernov int color_printed = 0; 32747bb6b11SAndrey A. Chernov #endif 3284b88c807SRodney W. Grimes 3294b88c807SRodney W. Grimes sp = p->fts_statp; 3304b88c807SRodney W. Grimes chcnt = 0; 3314b88c807SRodney W. Grimes if (f_inode) 332*6db1a7f1SMatthew D Fleming chcnt += printf("%*ju ", 333*6db1a7f1SMatthew D Fleming (int)inodefield, (uintmax_t)sp->st_ino); 3344b88c807SRodney W. Grimes if (f_size) 33540feca3aSMark Murray chcnt += printf("%*jd ", 3364b88c807SRodney W. Grimes (int)sizefield, howmany(sp->st_blocks, blocksize)); 33774985094SJosef Karthauser #ifdef COLORLS 3383885812cSJosef Karthauser if (f_color) 339cf0feaeeSAndrey A. Chernov color_printed = colortype(sp->st_mode); 34074985094SJosef Karthauser #endif 341ee579ffbSAssar Westerlund chcnt += printname(p->fts_name); 34274985094SJosef Karthauser #ifdef COLORLS 343cf0feaeeSAndrey A. Chernov if (f_color && color_printed) 34438782c25SAndrey A. Chernov endcolor(0); 34574985094SJosef Karthauser #endif 3464b88c807SRodney W. Grimes if (f_type) 3474b88c807SRodney W. Grimes chcnt += printtype(sp->st_mode); 3484b88c807SRodney W. Grimes return (chcnt); 3494b88c807SRodney W. Grimes } 3504b88c807SRodney W. Grimes 35155926a66SJaakko Heinonen /* 35255926a66SJaakko Heinonen * Print device special file major and minor numbers. 35355926a66SJaakko Heinonen */ 35455926a66SJaakko Heinonen static void 35555926a66SJaakko Heinonen printdev(size_t width, dev_t dev) 35655926a66SJaakko Heinonen { 35755926a66SJaakko Heinonen 3589f365aa1SEd Schouten (void)printf("%#*jx ", (u_int)width, (uintmax_t)dev); 35955926a66SJaakko Heinonen } 36055926a66SJaakko Heinonen 3614b88c807SRodney W. Grimes static void 36246251ddeSWarner Losh printtime(time_t ftime) 3634b88c807SRodney W. Grimes { 364fc4a9bafSAndrey A. Chernov char longstring[80]; 36540feca3aSMark Murray static time_t now = 0; 36697e4e97bSJosef Karthauser const char *format; 3678234eb25SAndrey A. Chernov static int d_first = -1; 368f173abd0SMike Pritchard 36928fd017aSAndrey A. Chernov if (d_first < 0) 37028fd017aSAndrey A. Chernov d_first = (*nl_langinfo(D_MD_ORDER) == 'd'); 371f173abd0SMike Pritchard if (now == 0) 372f173abd0SMike Pritchard now = time(NULL); 3734b88c807SRodney W. Grimes 374656dcd43SGarrett Wollman #define SIXMONTHS ((365 / 2) * 86400) 3752269fa57SGreg Lehey if (f_timeformat) /* user specified format */ 3762269fa57SGreg Lehey format = f_timeformat; 3772269fa57SGreg Lehey else if (f_sectime) 3781e715e34SJosef Karthauser /* mmm dd hh:mm:ss yyyy || dd mmm hh:mm:ss yyyy */ 37928fd017aSAndrey A. Chernov format = d_first ? "%e %b %T %Y" : "%b %e %T %Y"; 380f173abd0SMike Pritchard else if (ftime + SIXMONTHS > now && ftime < now + SIXMONTHS) 3811e715e34SJosef Karthauser /* mmm dd hh:mm || dd mmm hh:mm */ 38228fd017aSAndrey A. Chernov format = d_first ? "%e %b %R" : "%b %e %R"; 38397e4e97bSJosef Karthauser else 3841e715e34SJosef Karthauser /* mmm dd yyyy || dd mmm yyyy */ 38528fd017aSAndrey A. Chernov format = d_first ? "%e %b %Y" : "%b %e %Y"; 38697e4e97bSJosef Karthauser strftime(longstring, sizeof(longstring), format, localtime(&ftime)); 38797e4e97bSJosef Karthauser fputs(longstring, stdout); 3882269fa57SGreg Lehey fputc(' ', stdout); 3894b88c807SRodney W. Grimes } 3904b88c807SRodney W. Grimes 3914b88c807SRodney W. Grimes static int 39246251ddeSWarner Losh printtype(u_int mode) 3934b88c807SRodney W. Grimes { 39494274c73STim J. Robbins 39594274c73STim J. Robbins if (f_slash) { 39694274c73STim J. Robbins if ((mode & S_IFMT) == S_IFDIR) { 39794274c73STim J. Robbins (void)putchar('/'); 39894274c73STim J. Robbins return (1); 39994274c73STim J. Robbins } 40094274c73STim J. Robbins return (0); 40194274c73STim J. Robbins } 40294274c73STim J. Robbins 4034b88c807SRodney W. Grimes switch (mode & S_IFMT) { 4044b88c807SRodney W. Grimes case S_IFDIR: 4054b88c807SRodney W. Grimes (void)putchar('/'); 4064b88c807SRodney W. Grimes return (1); 4074b88c807SRodney W. Grimes case S_IFIFO: 4084b88c807SRodney W. Grimes (void)putchar('|'); 4094b88c807SRodney W. Grimes return (1); 4104b88c807SRodney W. Grimes case S_IFLNK: 4114b88c807SRodney W. Grimes (void)putchar('@'); 4124b88c807SRodney W. Grimes return (1); 4134b88c807SRodney W. Grimes case S_IFSOCK: 4144b88c807SRodney W. Grimes (void)putchar('='); 4154b88c807SRodney W. Grimes return (1); 416fb5cb208SSteve Price case S_IFWHT: 417fb5cb208SSteve Price (void)putchar('%'); 418fb5cb208SSteve Price return (1); 4199052855aSMark Murray default: 420568dcd5fSBill Fumerola break; 4214b88c807SRodney W. Grimes } 4224b88c807SRodney W. Grimes if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) { 4234b88c807SRodney W. Grimes (void)putchar('*'); 4244b88c807SRodney W. Grimes return (1); 4254b88c807SRodney W. Grimes } 4264b88c807SRodney W. Grimes return (0); 4274b88c807SRodney W. Grimes } 4284b88c807SRodney W. Grimes 42974985094SJosef Karthauser #ifdef COLORLS 4301bf1478aSAndrey A. Chernov static int 43146251ddeSWarner Losh putch(int c) 432cf0feaeeSAndrey A. Chernov { 43338782c25SAndrey A. Chernov (void)putchar(c); 43438782c25SAndrey A. Chernov return 0; 435cf0feaeeSAndrey A. Chernov } 436cf0feaeeSAndrey A. Chernov 4371bf1478aSAndrey A. Chernov static int 43846251ddeSWarner Losh writech(int c) 43938782c25SAndrey A. Chernov { 44040feca3aSMark Murray char tmp = (char)c; 44138782c25SAndrey A. Chernov 44238782c25SAndrey A. Chernov (void)write(STDOUT_FILENO, &tmp, 1); 44338782c25SAndrey A. Chernov return 0; 44438782c25SAndrey A. Chernov } 445cf0feaeeSAndrey A. Chernov 4461bf1478aSAndrey A. Chernov static void 44746251ddeSWarner Losh printcolor(Colors c) 4483885812cSJosef Karthauser { 44974985094SJosef Karthauser char *ansiseq; 45074985094SJosef Karthauser 451c1499cf6SJosef Karthauser if (colors[c].bold) 452c1499cf6SJosef Karthauser tputs(enter_bold, 1, putch); 453c1499cf6SJosef Karthauser 454c1499cf6SJosef Karthauser if (colors[c].num[0] != -1) { 455c1499cf6SJosef Karthauser ansiseq = tgoto(ansi_fgcol, 0, colors[c].num[0]); 45638782c25SAndrey A. Chernov if (ansiseq) 457cf0feaeeSAndrey A. Chernov tputs(ansiseq, 1, putch); 4583885812cSJosef Karthauser } 459c1499cf6SJosef Karthauser if (colors[c].num[1] != -1) { 460c1499cf6SJosef Karthauser ansiseq = tgoto(ansi_bgcol, 0, colors[c].num[1]); 46138782c25SAndrey A. Chernov if (ansiseq) 462cf0feaeeSAndrey A. Chernov tputs(ansiseq, 1, putch); 46374985094SJosef Karthauser } 46474985094SJosef Karthauser } 46574985094SJosef Karthauser 46638782c25SAndrey A. Chernov static void 46746251ddeSWarner Losh endcolor(int sig) 46874985094SJosef Karthauser { 46938782c25SAndrey A. Chernov tputs(ansi_coloff, 1, sig ? writech : putch); 470c1499cf6SJosef Karthauser tputs(attrs_off, 1, sig ? writech : putch); 4713885812cSJosef Karthauser } 4723885812cSJosef Karthauser 47338782c25SAndrey A. Chernov static int 47446251ddeSWarner Losh colortype(mode_t mode) 4753885812cSJosef Karthauser { 4763885812cSJosef Karthauser switch (mode & S_IFMT) { 4773885812cSJosef Karthauser case S_IFDIR: 4783885812cSJosef Karthauser if (mode & S_IWOTH) 4793885812cSJosef Karthauser if (mode & S_ISTXT) 4803885812cSJosef Karthauser printcolor(C_WSDIR); 4813885812cSJosef Karthauser else 4823885812cSJosef Karthauser printcolor(C_WDIR); 4833885812cSJosef Karthauser else 4843885812cSJosef Karthauser printcolor(C_DIR); 4853885812cSJosef Karthauser return (1); 4863885812cSJosef Karthauser case S_IFLNK: 4873885812cSJosef Karthauser printcolor(C_LNK); 4883885812cSJosef Karthauser return (1); 4893885812cSJosef Karthauser case S_IFSOCK: 4903885812cSJosef Karthauser printcolor(C_SOCK); 4913885812cSJosef Karthauser return (1); 4923885812cSJosef Karthauser case S_IFIFO: 4933885812cSJosef Karthauser printcolor(C_FIFO); 4943885812cSJosef Karthauser return (1); 4953885812cSJosef Karthauser case S_IFBLK: 4963885812cSJosef Karthauser printcolor(C_BLK); 4973885812cSJosef Karthauser return (1); 4983885812cSJosef Karthauser case S_IFCHR: 4993885812cSJosef Karthauser printcolor(C_CHR); 5003885812cSJosef Karthauser return (1); 50140feca3aSMark Murray default:; 5023885812cSJosef Karthauser } 5033885812cSJosef Karthauser if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) { 5043885812cSJosef Karthauser if (mode & S_ISUID) 5053885812cSJosef Karthauser printcolor(C_SUID); 5063885812cSJosef Karthauser else if (mode & S_ISGID) 5073885812cSJosef Karthauser printcolor(C_SGID); 5083885812cSJosef Karthauser else 5093885812cSJosef Karthauser printcolor(C_EXEC); 5103885812cSJosef Karthauser return (1); 5113885812cSJosef Karthauser } 5123885812cSJosef Karthauser return (0); 5133885812cSJosef Karthauser } 5143885812cSJosef Karthauser 5153885812cSJosef Karthauser void 51646251ddeSWarner Losh parsecolors(const char *cs) 5173885812cSJosef Karthauser { 518b0bc91e9SJosef Karthauser int i; 519b0bc91e9SJosef Karthauser int j; 520ca2993fbSMark Murray size_t len; 5213885812cSJosef Karthauser char c[2]; 522c1499cf6SJosef Karthauser short legacy_warn = 0; 52338782c25SAndrey A. Chernov 524b0bc91e9SJosef Karthauser if (cs == NULL) 525b0bc91e9SJosef Karthauser cs = ""; /* LSCOLORS not set */ 5263885812cSJosef Karthauser len = strlen(cs); 52740feca3aSMark Murray for (i = 0; i < (int)C_NUMCOLORS; i++) { 528c1499cf6SJosef Karthauser colors[i].bold = 0; 529c1499cf6SJosef Karthauser 53040feca3aSMark Murray if (len <= 2 * (size_t)i) { 5313885812cSJosef Karthauser c[0] = defcolors[2 * i]; 5323885812cSJosef Karthauser c[1] = defcolors[2 * i + 1]; 5335dda5d0dSJosef Karthauser } else { 5343885812cSJosef Karthauser c[0] = cs[2 * i]; 5353885812cSJosef Karthauser c[1] = cs[2 * i + 1]; 5363885812cSJosef Karthauser } 5373885812cSJosef Karthauser for (j = 0; j < 2; j++) { 538c1499cf6SJosef Karthauser /* Legacy colours used 0-7 */ 539c1499cf6SJosef Karthauser if (c[j] >= '0' && c[j] <= '7') { 540c1499cf6SJosef Karthauser colors[i].num[j] = c[j] - '0'; 541c1499cf6SJosef Karthauser if (!legacy_warn) { 542e09fdabdSTim J. Robbins warnx("LSCOLORS should use " 543130d15dcSJosef Karthauser "characters a-h instead of 0-9 (" 544e09fdabdSTim J. Robbins "see the manual page)"); 5453885812cSJosef Karthauser } 546c1499cf6SJosef Karthauser legacy_warn = 1; 547c1499cf6SJosef Karthauser } else if (c[j] >= 'a' && c[j] <= 'h') 548c1499cf6SJosef Karthauser colors[i].num[j] = c[j] - 'a'; 549c1499cf6SJosef Karthauser else if (c[j] >= 'A' && c[j] <= 'H') { 550c1499cf6SJosef Karthauser colors[i].num[j] = c[j] - 'A'; 551c1499cf6SJosef Karthauser colors[i].bold = 1; 55240feca3aSMark Murray } else if (tolower((unsigned char)c[j]) == 'x') 553c1499cf6SJosef Karthauser colors[i].num[j] = -1; 554c1499cf6SJosef Karthauser else { 555e09fdabdSTim J. Robbins warnx("invalid character '%c' in LSCOLORS" 556e09fdabdSTim J. Robbins " env var", c[j]); 5570d72516eSJosef Karthauser colors[i].num[j] = -1; 558c1499cf6SJosef Karthauser } 5593885812cSJosef Karthauser } 5603885812cSJosef Karthauser } 5613885812cSJosef Karthauser } 562cf0feaeeSAndrey A. Chernov 5631bf1478aSAndrey A. Chernov void 56446251ddeSWarner Losh colorquit(int sig) 565cf0feaeeSAndrey A. Chernov { 56638782c25SAndrey A. Chernov endcolor(sig); 567faebfe2eSAndrey A. Chernov 568faebfe2eSAndrey A. Chernov (void)signal(sig, SIG_DFL); 569faebfe2eSAndrey A. Chernov (void)kill(getpid(), sig); 570cf0feaeeSAndrey A. Chernov } 5715dda5d0dSJosef Karthauser 57274985094SJosef Karthauser #endif /* COLORLS */ 5733885812cSJosef Karthauser 5744b88c807SRodney W. Grimes static void 575ca2993fbSMark Murray printlink(const FTSENT *p) 5764b88c807SRodney W. Grimes { 5774b88c807SRodney W. Grimes int lnklen; 578b0bc91e9SJosef Karthauser char name[MAXPATHLEN + 1]; 579b0bc91e9SJosef Karthauser char path[MAXPATHLEN + 1]; 5804b88c807SRodney W. Grimes 5814b88c807SRodney W. Grimes if (p->fts_level == FTS_ROOTLEVEL) 5824b88c807SRodney W. Grimes (void)snprintf(name, sizeof(name), "%s", p->fts_name); 5834b88c807SRodney W. Grimes else 5844b88c807SRodney W. Grimes (void)snprintf(name, sizeof(name), 5854b88c807SRodney W. Grimes "%s/%s", p->fts_parent->fts_accpath, p->fts_name); 5864b88c807SRodney W. Grimes if ((lnklen = readlink(name, path, sizeof(path) - 1)) == -1) { 5874b88c807SRodney W. Grimes (void)fprintf(stderr, "\nls: %s: %s\n", name, strerror(errno)); 5884b88c807SRodney W. Grimes return; 5894b88c807SRodney W. Grimes } 5904b88c807SRodney W. Grimes path[lnklen] = '\0'; 5917ea30648SDag-Erling Smørgrav (void)printf(" -> "); 5929052855aSMark Murray (void)printname(path); 5934b88c807SRodney W. Grimes } 5940e8d1551SJosef Karthauser 5950e8d1551SJosef Karthauser static void 59646251ddeSWarner Losh printsize(size_t width, off_t bytes) 5970e8d1551SJosef Karthauser { 5980e8d1551SJosef Karthauser 5990e8d1551SJosef Karthauser if (f_humanval) { 60055926a66SJaakko Heinonen /* 60155926a66SJaakko Heinonen * Reserve one space before the size and allocate room for 60255926a66SJaakko Heinonen * the trailing '\0'. 60355926a66SJaakko Heinonen */ 60455926a66SJaakko Heinonen char buf[HUMANVALSTR_LEN - 1 + 1]; 6050e8d1551SJosef Karthauser 606478aa805SPawel Jakub Dawidek humanize_number(buf, sizeof(buf), (int64_t)bytes, "", 607478aa805SPawel Jakub Dawidek HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL); 60855926a66SJaakko Heinonen (void)printf("%*s ", (u_int)width, buf); 6095dda5d0dSJosef Karthauser } else 61040feca3aSMark Murray (void)printf("%*jd ", (u_int)width, bytes); 6110e8d1551SJosef Karthauser } 6120e8d1551SJosef Karthauser 613dd9aaeb0STim J. Robbins /* 614dd9aaeb0STim J. Robbins * Add a + after the standard rwxrwxrwx mode if the file has an 615f7b8687aSEdward Tomasz Napierala * ACL. strmode() reserves space at the end of the string. 616dd9aaeb0STim J. Robbins */ 617f7b8687aSEdward Tomasz Napierala static void 618f7b8687aSEdward Tomasz Napierala aclmode(char *buf, const FTSENT *p) 619f7b8687aSEdward Tomasz Napierala { 620f7b8687aSEdward Tomasz Napierala char name[MAXPATHLEN + 1]; 621f7b8687aSEdward Tomasz Napierala int ret, trivial; 622f7b8687aSEdward Tomasz Napierala static dev_t previous_dev = NODEV; 623f7b8687aSEdward Tomasz Napierala static int supports_acls = -1; 624f7b8687aSEdward Tomasz Napierala static int type = ACL_TYPE_ACCESS; 625f7b8687aSEdward Tomasz Napierala acl_t facl; 626f7b8687aSEdward Tomasz Napierala 627f7b8687aSEdward Tomasz Napierala /* 628f7b8687aSEdward Tomasz Napierala * XXX: ACLs are not supported on whiteouts and device files 629f7b8687aSEdward Tomasz Napierala * residing on UFS. 630f7b8687aSEdward Tomasz Napierala */ 631f7b8687aSEdward Tomasz Napierala if (S_ISCHR(p->fts_statp->st_mode) || S_ISBLK(p->fts_statp->st_mode) || 632f7b8687aSEdward Tomasz Napierala S_ISWHT(p->fts_statp->st_mode)) 633f7b8687aSEdward Tomasz Napierala return; 634f7b8687aSEdward Tomasz Napierala 635a3429262SEdward Tomasz Napierala if (previous_dev == p->fts_statp->st_dev && supports_acls == 0) 636a3429262SEdward Tomasz Napierala return; 637f7b8687aSEdward Tomasz Napierala 638dd9aaeb0STim J. Robbins if (p->fts_level == FTS_ROOTLEVEL) 639dd9aaeb0STim J. Robbins snprintf(name, sizeof(name), "%s", p->fts_name); 640dd9aaeb0STim J. Robbins else 641dd9aaeb0STim J. Robbins snprintf(name, sizeof(name), "%s/%s", 642dd9aaeb0STim J. Robbins p->fts_parent->fts_accpath, p->fts_name); 643a3429262SEdward Tomasz Napierala 644a3429262SEdward Tomasz Napierala if (previous_dev != p->fts_statp->st_dev) { 645a3429262SEdward Tomasz Napierala previous_dev = p->fts_statp->st_dev; 646a3429262SEdward Tomasz Napierala supports_acls = 0; 647a3429262SEdward Tomasz Napierala 648f7b8687aSEdward Tomasz Napierala ret = lpathconf(name, _PC_ACL_NFS4); 649f7b8687aSEdward Tomasz Napierala if (ret > 0) { 650f7b8687aSEdward Tomasz Napierala type = ACL_TYPE_NFS4; 651f7b8687aSEdward Tomasz Napierala supports_acls = 1; 652f7b8687aSEdward Tomasz Napierala } else if (ret < 0 && errno != EINVAL) { 653dd9aaeb0STim J. Robbins warn("%s", name); 654dd9aaeb0STim J. Robbins return; 655dd9aaeb0STim J. Robbins } 656f7b8687aSEdward Tomasz Napierala if (supports_acls == 0) { 657f7b8687aSEdward Tomasz Napierala ret = lpathconf(name, _PC_ACL_EXTENDED); 658f7b8687aSEdward Tomasz Napierala if (ret > 0) { 659f7b8687aSEdward Tomasz Napierala type = ACL_TYPE_ACCESS; 660f7b8687aSEdward Tomasz Napierala supports_acls = 1; 661f7b8687aSEdward Tomasz Napierala } else if (ret < 0 && errno != EINVAL) { 662f7b8687aSEdward Tomasz Napierala warn("%s", name); 663f7b8687aSEdward Tomasz Napierala return; 664dd9aaeb0STim J. Robbins } 665f7b8687aSEdward Tomasz Napierala } 666f7b8687aSEdward Tomasz Napierala } 667f7b8687aSEdward Tomasz Napierala if (supports_acls == 0) 668f7b8687aSEdward Tomasz Napierala return; 669f7b8687aSEdward Tomasz Napierala facl = acl_get_link_np(name, type); 670f7b8687aSEdward Tomasz Napierala if (facl == NULL) { 671f7b8687aSEdward Tomasz Napierala warn("%s", name); 672f7b8687aSEdward Tomasz Napierala return; 673f7b8687aSEdward Tomasz Napierala } 674f7b8687aSEdward Tomasz Napierala if (acl_is_trivial_np(facl, &trivial)) { 675dd9aaeb0STim J. Robbins acl_free(facl); 676dd9aaeb0STim J. Robbins warn("%s", name); 677f7b8687aSEdward Tomasz Napierala return; 678f7b8687aSEdward Tomasz Napierala } 679f7b8687aSEdward Tomasz Napierala if (!trivial) 680f7b8687aSEdward Tomasz Napierala buf[10] = '+'; 681f7b8687aSEdward Tomasz Napierala acl_free(facl); 682dd9aaeb0STim J. Robbins } 683