19ddb49cbSWarner Losh /*- 28a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 38a16b7a1SPedro F. Giffuni * 44b88c807SRodney W. Grimes * Copyright (c) 1989, 1993, 1994 54b88c807SRodney W. Grimes * The Regents of the University of California. All rights reserved. 64b88c807SRodney W. Grimes * 74b88c807SRodney W. Grimes * This code is derived from software contributed to Berkeley by 84b88c807SRodney W. Grimes * Michael Fischbein. 94b88c807SRodney W. Grimes * 104b88c807SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 114b88c807SRodney W. Grimes * modification, are permitted provided that the following conditions 124b88c807SRodney W. Grimes * are met: 134b88c807SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 144b88c807SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 154b88c807SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 164b88c807SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 174b88c807SRodney W. Grimes * documentation and/or other materials provided with the distribution. 18fbbd9655SWarner Losh * 3. Neither the name of the University nor the names of its contributors 194b88c807SRodney W. Grimes * may be used to endorse or promote products derived from this software 204b88c807SRodney W. Grimes * without specific prior written permission. 214b88c807SRodney W. Grimes * 224b88c807SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 234b88c807SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 244b88c807SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 254b88c807SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 264b88c807SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 274b88c807SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 284b88c807SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 294b88c807SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 304b88c807SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 314b88c807SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 324b88c807SRodney W. Grimes * SUCH DAMAGE. 334b88c807SRodney W. Grimes */ 344b88c807SRodney W. Grimes 35febad2fcSSteve Price #if 0 36c73d77ceSMark Murray #ifndef lint 37febad2fcSSteve Price static char sccsid[] = "@(#)print.c 8.4 (Berkeley) 4/17/94"; 384b88c807SRodney W. Grimes #endif /* not lint */ 39c73d77ceSMark Murray #endif 405eb43ac2SDavid E. O'Brien #include <sys/cdefs.h> 415eb43ac2SDavid E. O'Brien __FBSDID("$FreeBSD$"); 424b88c807SRodney W. Grimes 434b88c807SRodney W. Grimes #include <sys/param.h> 444b88c807SRodney W. Grimes #include <sys/stat.h> 45dd9aaeb0STim J. Robbins #include <sys/acl.h> 464b88c807SRodney W. Grimes 474b88c807SRodney W. Grimes #include <err.h> 484b88c807SRodney W. Grimes #include <errno.h> 494b88c807SRodney W. Grimes #include <fts.h> 5028fd017aSAndrey A. Chernov #include <langinfo.h> 51478aa805SPawel Jakub Dawidek #include <libutil.h> 52be90c1c6SBaptiste Daroussin #include <limits.h> 534b88c807SRodney W. Grimes #include <stdio.h> 549f365aa1SEd Schouten #include <stdint.h> 554b88c807SRodney W. Grimes #include <stdlib.h> 564b88c807SRodney W. Grimes #include <string.h> 57434b6ea4SBruce Evans #include <time.h> 584b88c807SRodney W. Grimes #include <unistd.h> 59be90c1c6SBaptiste Daroussin #include <wchar.h> 60faebfe2eSAndrey A. Chernov #ifdef COLORLS 61faebfe2eSAndrey A. Chernov #include <ctype.h> 62faebfe2eSAndrey A. Chernov #include <termcap.h> 63faebfe2eSAndrey A. Chernov #include <signal.h> 64faebfe2eSAndrey A. Chernov #endif 654b88c807SRodney W. Grimes 664b88c807SRodney W. Grimes #include "ls.h" 674b88c807SRodney W. Grimes #include "extern.h" 684b88c807SRodney W. Grimes 6940feca3aSMark Murray static int printaname(const FTSENT *, u_long, u_long); 7055926a66SJaakko Heinonen static void printdev(size_t, dev_t); 71ca2993fbSMark Murray static void printlink(const FTSENT *); 720fdf7fa8SConrad Meyer static void printtime(time_t); 7346251ddeSWarner Losh static int printtype(u_int); 740fdf7fa8SConrad Meyer static void printsize(size_t, off_t); 7538782c25SAndrey A. Chernov #ifdef COLORLS 76e10ba800SKyle Evans static void endcolor_termcap(int); 77e10ba800SKyle Evans static void endcolor_ansi(void); 7846251ddeSWarner Losh static void endcolor(int); 7946251ddeSWarner Losh static int colortype(mode_t); 8038782c25SAndrey A. Chernov #endif 81f7b8687aSEdward Tomasz Napierala static void aclmode(char *, const FTSENT *); 824b88c807SRodney W. Grimes 834b88c807SRodney W. Grimes #define IS_NOPRINT(p) ((p)->fts_number == NO_PRINT) 840e8d1551SJosef Karthauser 8574985094SJosef Karthauser #ifdef COLORLS 863885812cSJosef Karthauser /* Most of these are taken from <sys/stat.h> */ 873885812cSJosef Karthauser typedef enum Colors { 883885812cSJosef Karthauser C_DIR, /* directory */ 893885812cSJosef Karthauser C_LNK, /* symbolic link */ 903885812cSJosef Karthauser C_SOCK, /* socket */ 913885812cSJosef Karthauser C_FIFO, /* pipe */ 923885812cSJosef Karthauser C_EXEC, /* executable */ 933885812cSJosef Karthauser C_BLK, /* block special */ 943885812cSJosef Karthauser C_CHR, /* character special */ 953885812cSJosef Karthauser C_SUID, /* setuid executable */ 963885812cSJosef Karthauser C_SGID, /* setgid executable */ 975dda5d0dSJosef Karthauser C_WSDIR, /* directory writeble to others, with sticky 985dda5d0dSJosef Karthauser * bit */ 995dda5d0dSJosef Karthauser C_WDIR, /* directory writeble to others, without 1005dda5d0dSJosef Karthauser * sticky bit */ 1013885812cSJosef Karthauser C_NUMCOLORS /* just a place-holder */ 1023885812cSJosef Karthauser } Colors; 1033885812cSJosef Karthauser 1049052855aSMark Murray static const char *defcolors = "exfxcxdxbxegedabagacad"; 1053885812cSJosef Karthauser 106c1499cf6SJosef Karthauser /* colors for file types */ 107c1499cf6SJosef Karthauser static struct { 108c1499cf6SJosef Karthauser int num[2]; 10997c31821SCameron Katri bool bold; 11097c31821SCameron Katri bool underline; 111c1499cf6SJosef Karthauser } colors[C_NUMCOLORS]; 11274985094SJosef Karthauser #endif 1133885812cSJosef Karthauser 114be90c1c6SBaptiste Daroussin static size_t padding_for_month[12]; 115be90c1c6SBaptiste Daroussin static size_t month_max_size = 0; 116be90c1c6SBaptiste Daroussin 1174b88c807SRodney W. Grimes void 11840feca3aSMark Murray printscol(const DISPLAY *dp) 1194b88c807SRodney W. Grimes { 1204b88c807SRodney W. Grimes FTSENT *p; 1214b88c807SRodney W. Grimes 1224b88c807SRodney W. Grimes for (p = dp->list; p; p = p->fts_link) { 1234b88c807SRodney W. Grimes if (IS_NOPRINT(p)) 1244b88c807SRodney W. Grimes continue; 1254b88c807SRodney W. Grimes (void)printaname(p, dp->s_inode, dp->s_block); 1260fdf7fa8SConrad Meyer (void)putchar('\n'); 1274b88c807SRodney W. Grimes } 1284b88c807SRodney W. Grimes } 1294b88c807SRodney W. Grimes 130ee579ffbSAssar Westerlund /* 131ee579ffbSAssar Westerlund * print name in current style 132ee579ffbSAssar Westerlund */ 1331656f850STim J. Robbins int 1340fdf7fa8SConrad Meyer printname(const char *name) 13552e4a08cSMarcel Moolenaar { 1360fdf7fa8SConrad Meyer if (f_octal || f_octal_escape) 1370fdf7fa8SConrad Meyer return prn_octal(name); 1380fdf7fa8SConrad Meyer else if (f_nonprint) 1390fdf7fa8SConrad Meyer return prn_printable(name); 1400fdf7fa8SConrad Meyer else 1410fdf7fa8SConrad Meyer return prn_normal(name); 14252e4a08cSMarcel Moolenaar } 14352e4a08cSMarcel Moolenaar 144be90c1c6SBaptiste Daroussin static const char * 145be90c1c6SBaptiste Daroussin get_abmon(int mon) 146be90c1c6SBaptiste Daroussin { 147be90c1c6SBaptiste Daroussin 148be90c1c6SBaptiste Daroussin switch (mon) { 149be90c1c6SBaptiste Daroussin case 0: return (nl_langinfo(ABMON_1)); 150be90c1c6SBaptiste Daroussin case 1: return (nl_langinfo(ABMON_2)); 151be90c1c6SBaptiste Daroussin case 2: return (nl_langinfo(ABMON_3)); 152be90c1c6SBaptiste Daroussin case 3: return (nl_langinfo(ABMON_4)); 153be90c1c6SBaptiste Daroussin case 4: return (nl_langinfo(ABMON_5)); 154be90c1c6SBaptiste Daroussin case 5: return (nl_langinfo(ABMON_6)); 155be90c1c6SBaptiste Daroussin case 6: return (nl_langinfo(ABMON_7)); 156be90c1c6SBaptiste Daroussin case 7: return (nl_langinfo(ABMON_8)); 157be90c1c6SBaptiste Daroussin case 8: return (nl_langinfo(ABMON_9)); 158be90c1c6SBaptiste Daroussin case 9: return (nl_langinfo(ABMON_10)); 159be90c1c6SBaptiste Daroussin case 10: return (nl_langinfo(ABMON_11)); 160be90c1c6SBaptiste Daroussin case 11: return (nl_langinfo(ABMON_12)); 161be90c1c6SBaptiste Daroussin } 162be90c1c6SBaptiste Daroussin 163be90c1c6SBaptiste Daroussin /* should never happen */ 164be90c1c6SBaptiste Daroussin abort(); 165be90c1c6SBaptiste Daroussin } 166be90c1c6SBaptiste Daroussin 167be90c1c6SBaptiste Daroussin static size_t 168be90c1c6SBaptiste Daroussin mbswidth(const char *month) 169be90c1c6SBaptiste Daroussin { 170be90c1c6SBaptiste Daroussin wchar_t wc; 171be90c1c6SBaptiste Daroussin size_t width, donelen, clen, w; 172be90c1c6SBaptiste Daroussin 173be90c1c6SBaptiste Daroussin width = donelen = 0; 174be90c1c6SBaptiste Daroussin while ((clen = mbrtowc(&wc, month + donelen, MB_LEN_MAX, NULL)) != 0) { 175be90c1c6SBaptiste Daroussin if (clen == (size_t)-1 || clen == (size_t)-2) 176be90c1c6SBaptiste Daroussin return (-1); 177be90c1c6SBaptiste Daroussin donelen += clen; 178be90c1c6SBaptiste Daroussin if ((w = wcwidth(wc)) == (size_t)-1) 179be90c1c6SBaptiste Daroussin return (-1); 180be90c1c6SBaptiste Daroussin width += w; 181be90c1c6SBaptiste Daroussin } 182be90c1c6SBaptiste Daroussin 183be90c1c6SBaptiste Daroussin return (width); 184be90c1c6SBaptiste Daroussin } 185be90c1c6SBaptiste Daroussin 186be90c1c6SBaptiste Daroussin static void 187be90c1c6SBaptiste Daroussin compute_abbreviated_month_size(void) 188be90c1c6SBaptiste Daroussin { 189be90c1c6SBaptiste Daroussin int i; 190be90c1c6SBaptiste Daroussin size_t width; 191be90c1c6SBaptiste Daroussin size_t months_width[12]; 192be90c1c6SBaptiste Daroussin 193be90c1c6SBaptiste Daroussin for (i = 0; i < 12; i++) { 194be90c1c6SBaptiste Daroussin width = mbswidth(get_abmon(i)); 195be90c1c6SBaptiste Daroussin if (width == (size_t)-1) { 196be90c1c6SBaptiste Daroussin month_max_size = -1; 197be90c1c6SBaptiste Daroussin return; 198be90c1c6SBaptiste Daroussin } 199be90c1c6SBaptiste Daroussin months_width[i] = width; 200be90c1c6SBaptiste Daroussin if (width > month_max_size) 201be90c1c6SBaptiste Daroussin month_max_size = width; 202be90c1c6SBaptiste Daroussin } 203be90c1c6SBaptiste Daroussin 204be90c1c6SBaptiste Daroussin for (i = 0; i < 12; i++) 205be90c1c6SBaptiste Daroussin padding_for_month[i] = month_max_size - months_width[i]; 206be90c1c6SBaptiste Daroussin } 207be90c1c6SBaptiste Daroussin 2084b88c807SRodney W. Grimes void 20940feca3aSMark Murray printlong(const DISPLAY *dp) 2104b88c807SRodney W. Grimes { 2114b88c807SRodney W. Grimes struct stat *sp; 2124b88c807SRodney W. Grimes FTSENT *p; 2134b88c807SRodney W. Grimes NAMES *np; 2144b88c807SRodney W. Grimes char buf[20]; 21547bb6b11SAndrey A. Chernov #ifdef COLORLS 21647bb6b11SAndrey A. Chernov int color_printed = 0; 21747bb6b11SAndrey A. Chernov #endif 2184b88c807SRodney W. Grimes 21948a91b69SDavid Schultz if ((dp->list == NULL || dp->list->fts_level != FTS_ROOTLEVEL) && 22048a91b69SDavid Schultz (f_longform || f_size)) { 2210fdf7fa8SConrad Meyer (void)printf("total %lu\n", howmany(dp->btotal, blocksize)); 22248a91b69SDavid Schultz } 2234b88c807SRodney W. Grimes 2244b88c807SRodney W. Grimes for (p = dp->list; p; p = p->fts_link) { 2254b88c807SRodney W. Grimes if (IS_NOPRINT(p)) 2264b88c807SRodney W. Grimes continue; 2274b88c807SRodney W. Grimes sp = p->fts_statp; 2284b88c807SRodney W. Grimes if (f_inode) 2290fdf7fa8SConrad Meyer (void)printf("%*ju ", 2306db1a7f1SMatthew D Fleming dp->s_inode, (uintmax_t)sp->st_ino); 2314b88c807SRodney W. Grimes if (f_size) 2320fdf7fa8SConrad Meyer (void)printf("%*jd ", 2334b88c807SRodney W. Grimes dp->s_block, howmany(sp->st_blocks, blocksize)); 2349052855aSMark Murray strmode(sp->st_mode, buf); 235f7b8687aSEdward Tomasz Napierala aclmode(buf, p); 2364b88c807SRodney W. Grimes np = p->fts_pointer; 2370fdf7fa8SConrad Meyer (void)printf("%s %*ju %-*s %-*s ", buf, dp->s_nlink, 2380fdf7fa8SConrad Meyer (uintmax_t)sp->st_nlink, dp->s_user, np->user, dp->s_group, 2390fdf7fa8SConrad Meyer np->group); 2404b88c807SRodney W. Grimes if (f_flags) 2410fdf7fa8SConrad Meyer (void)printf("%-*s ", dp->s_flags, np->flags); 2424d33b62eSRobert Watson if (f_label) 2430fdf7fa8SConrad Meyer (void)printf("%-*s ", dp->s_label, np->label); 2444b88c807SRodney W. Grimes if (S_ISCHR(sp->st_mode) || S_ISBLK(sp->st_mode)) 24555926a66SJaakko Heinonen printdev(dp->s_size, sp->st_rdev); 2464b88c807SRodney W. Grimes else 2470fdf7fa8SConrad Meyer printsize(dp->s_size, sp->st_size); 2484b88c807SRodney W. Grimes if (f_accesstime) 2490fdf7fa8SConrad Meyer printtime(sp->st_atime); 250fe79420eSJohn Baldwin else if (f_birthtime) 2510fdf7fa8SConrad Meyer printtime(sp->st_birthtime); 2524b88c807SRodney W. Grimes else if (f_statustime) 2530fdf7fa8SConrad Meyer printtime(sp->st_ctime); 2544b88c807SRodney W. Grimes else 2550fdf7fa8SConrad Meyer printtime(sp->st_mtime); 25674985094SJosef Karthauser #ifdef COLORLS 2573885812cSJosef Karthauser if (f_color) 258cf0feaeeSAndrey A. Chernov color_printed = colortype(sp->st_mode); 25974985094SJosef Karthauser #endif 2600fdf7fa8SConrad Meyer (void)printname(p->fts_name); 26174985094SJosef Karthauser #ifdef COLORLS 262cf0feaeeSAndrey A. Chernov if (f_color && color_printed) 26338782c25SAndrey A. Chernov endcolor(0); 26474985094SJosef Karthauser #endif 2654b88c807SRodney W. Grimes if (f_type) 2664b88c807SRodney W. Grimes (void)printtype(sp->st_mode); 2674b88c807SRodney W. Grimes if (S_ISLNK(sp->st_mode)) 2684b88c807SRodney W. Grimes printlink(p); 2690fdf7fa8SConrad Meyer (void)putchar('\n'); 2704b88c807SRodney W. Grimes } 2714b88c807SRodney W. Grimes } 2724b88c807SRodney W. Grimes 2734b88c807SRodney W. Grimes void 27440feca3aSMark Murray printstream(const DISPLAY *dp) 27594274c73STim J. Robbins { 27694274c73STim J. Robbins FTSENT *p; 27794274c73STim J. Robbins int chcnt; 27894274c73STim J. Robbins 27994274c73STim J. Robbins for (p = dp->list, chcnt = 0; p; p = p->fts_link) { 28094274c73STim J. Robbins if (p->fts_number == NO_PRINT) 28194274c73STim J. Robbins continue; 282107409f4STim J. Robbins /* XXX strlen does not take octal escapes into account. */ 28394274c73STim J. Robbins if (strlen(p->fts_name) + chcnt + 28494274c73STim J. Robbins (p->fts_link ? 2 : 0) >= (unsigned)termwidth) { 2850fdf7fa8SConrad Meyer putchar('\n'); 28694274c73STim J. Robbins chcnt = 0; 28794274c73STim J. Robbins } 28894274c73STim J. Robbins chcnt += printaname(p, dp->s_inode, dp->s_block); 28994274c73STim J. Robbins if (p->fts_link) { 2900fdf7fa8SConrad Meyer printf(", "); 29194274c73STim J. Robbins chcnt += 2; 29294274c73STim J. Robbins } 29394274c73STim J. Robbins } 29494274c73STim J. Robbins if (chcnt) 2950fdf7fa8SConrad Meyer putchar('\n'); 29694274c73STim J. Robbins } 29794274c73STim J. Robbins 29894274c73STim J. Robbins void 29940feca3aSMark Murray printcol(const DISPLAY *dp) 3004b88c807SRodney W. Grimes { 3014b88c807SRodney W. Grimes static FTSENT **array; 3024b88c807SRodney W. Grimes static int lastentries = -1; 3034b88c807SRodney W. Grimes FTSENT *p; 304c5bc8709STim J. Robbins FTSENT **narray; 305b0bc91e9SJosef Karthauser int base; 306b0bc91e9SJosef Karthauser int chcnt; 307b0bc91e9SJosef Karthauser int cnt; 308b0bc91e9SJosef Karthauser int col; 309b0bc91e9SJosef Karthauser int colwidth; 310b0bc91e9SJosef Karthauser int endcol; 311b0bc91e9SJosef Karthauser int num; 312b0bc91e9SJosef Karthauser int numcols; 313b0bc91e9SJosef Karthauser int numrows; 314b0bc91e9SJosef Karthauser int row; 315545f583cSTim Vanderhoek int tabwidth; 316545f583cSTim Vanderhoek 317545f583cSTim Vanderhoek if (f_notabs) 318545f583cSTim Vanderhoek tabwidth = 1; 319545f583cSTim Vanderhoek else 320545f583cSTim Vanderhoek tabwidth = 8; 3214b88c807SRodney W. Grimes 3224b88c807SRodney W. Grimes /* 3234b88c807SRodney W. Grimes * Have to do random access in the linked list -- build a table 3244b88c807SRodney W. Grimes * of pointers. 3254b88c807SRodney W. Grimes */ 3264b88c807SRodney W. Grimes if (dp->entries > lastentries) { 327c5bc8709STim J. Robbins if ((narray = 3284b88c807SRodney W. Grimes realloc(array, dp->entries * sizeof(FTSENT *))) == NULL) { 3290fdf7fa8SConrad Meyer warn(NULL); 3304b88c807SRodney W. Grimes printscol(dp); 331c5bc8709STim J. Robbins return; 3324b88c807SRodney W. Grimes } 333c5bc8709STim J. Robbins lastentries = dp->entries; 334c5bc8709STim J. Robbins array = narray; 3354b88c807SRodney W. Grimes } 3364b88c807SRodney W. Grimes for (p = dp->list, num = 0; p; p = p->fts_link) 3374b88c807SRodney W. Grimes if (p->fts_number != NO_PRINT) 3384b88c807SRodney W. Grimes array[num++] = p; 3394b88c807SRodney W. Grimes 3404b88c807SRodney W. Grimes colwidth = dp->maxlen; 3414b88c807SRodney W. Grimes if (f_inode) 3424b88c807SRodney W. Grimes colwidth += dp->s_inode + 1; 3434b88c807SRodney W. Grimes if (f_size) 3444b88c807SRodney W. Grimes colwidth += dp->s_block + 1; 3454b88c807SRodney W. Grimes if (f_type) 3464b88c807SRodney W. Grimes colwidth += 1; 3474b88c807SRodney W. Grimes 348545f583cSTim Vanderhoek colwidth = (colwidth + tabwidth) & ~(tabwidth - 1); 3494b88c807SRodney W. Grimes if (termwidth < 2 * colwidth) { 3504b88c807SRodney W. Grimes printscol(dp); 3514b88c807SRodney W. Grimes return; 3524b88c807SRodney W. Grimes } 3534b88c807SRodney W. Grimes numcols = termwidth / colwidth; 3544b88c807SRodney W. Grimes numrows = num / numcols; 3554b88c807SRodney W. Grimes if (num % numcols) 3564b88c807SRodney W. Grimes ++numrows; 3574b88c807SRodney W. Grimes 35848a91b69SDavid Schultz if ((dp->list == NULL || dp->list->fts_level != FTS_ROOTLEVEL) && 35948a91b69SDavid Schultz (f_longform || f_size)) { 3600fdf7fa8SConrad Meyer (void)printf("total %lu\n", howmany(dp->btotal, blocksize)); 36148a91b69SDavid Schultz } 36294274c73STim J. Robbins 36394274c73STim J. Robbins base = 0; 3644b88c807SRodney W. Grimes for (row = 0; row < numrows; ++row) { 3654b88c807SRodney W. Grimes endcol = colwidth; 36694274c73STim J. Robbins if (!f_sortacross) 36794274c73STim J. Robbins base = row; 36894274c73STim J. Robbins for (col = 0, chcnt = 0; col < numcols; ++col) { 3694b88c807SRodney W. Grimes chcnt += printaname(array[base], dp->s_inode, 3704b88c807SRodney W. Grimes dp->s_block); 37194274c73STim J. Robbins if (f_sortacross) 37294274c73STim J. Robbins base++; 37394274c73STim J. Robbins else 37494274c73STim J. Robbins base += numrows; 37594274c73STim J. Robbins if (base >= num) 3764b88c807SRodney W. Grimes break; 377545f583cSTim Vanderhoek while ((cnt = ((chcnt + tabwidth) & ~(tabwidth - 1))) 378545f583cSTim Vanderhoek <= endcol) { 37994274c73STim J. Robbins if (f_sortacross && col + 1 >= numcols) 38094274c73STim J. Robbins break; 3810fdf7fa8SConrad Meyer (void)putchar(f_notabs ? ' ' : '\t'); 3824b88c807SRodney W. Grimes chcnt = cnt; 3834b88c807SRodney W. Grimes } 3844b88c807SRodney W. Grimes endcol += colwidth; 3854b88c807SRodney W. Grimes } 3860fdf7fa8SConrad Meyer (void)putchar('\n'); 3874b88c807SRodney W. Grimes } 3884b88c807SRodney W. Grimes } 3894b88c807SRodney W. Grimes 3904b88c807SRodney W. Grimes /* 3914b88c807SRodney W. Grimes * print [inode] [size] name 3924b88c807SRodney W. Grimes * return # of characters printed, no trailing characters. 3934b88c807SRodney W. Grimes */ 3944b88c807SRodney W. Grimes static int 39540feca3aSMark Murray printaname(const FTSENT *p, u_long inodefield, u_long sizefield) 3964b88c807SRodney W. Grimes { 3974b88c807SRodney W. Grimes struct stat *sp; 3984b88c807SRodney W. Grimes int chcnt; 39947bb6b11SAndrey A. Chernov #ifdef COLORLS 40047bb6b11SAndrey A. Chernov int color_printed = 0; 40147bb6b11SAndrey A. Chernov #endif 4024b88c807SRodney W. Grimes 4034b88c807SRodney W. Grimes sp = p->fts_statp; 4044b88c807SRodney W. Grimes chcnt = 0; 4054b88c807SRodney W. Grimes if (f_inode) 4060fdf7fa8SConrad Meyer chcnt += printf("%*ju ", 4076db1a7f1SMatthew D Fleming (int)inodefield, (uintmax_t)sp->st_ino); 4084b88c807SRodney W. Grimes if (f_size) 4090fdf7fa8SConrad Meyer chcnt += printf("%*jd ", 4104b88c807SRodney W. Grimes (int)sizefield, howmany(sp->st_blocks, blocksize)); 41174985094SJosef Karthauser #ifdef COLORLS 4123885812cSJosef Karthauser if (f_color) 413cf0feaeeSAndrey A. Chernov color_printed = colortype(sp->st_mode); 41474985094SJosef Karthauser #endif 4150fdf7fa8SConrad Meyer chcnt += printname(p->fts_name); 41674985094SJosef Karthauser #ifdef COLORLS 417cf0feaeeSAndrey A. Chernov if (f_color && color_printed) 41838782c25SAndrey A. Chernov endcolor(0); 41974985094SJosef Karthauser #endif 4204b88c807SRodney W. Grimes if (f_type) 4214b88c807SRodney W. Grimes chcnt += printtype(sp->st_mode); 4224b88c807SRodney W. Grimes return (chcnt); 4234b88c807SRodney W. Grimes } 4244b88c807SRodney W. Grimes 42555926a66SJaakko Heinonen /* 42655926a66SJaakko Heinonen * Print device special file major and minor numbers. 42755926a66SJaakko Heinonen */ 42855926a66SJaakko Heinonen static void 42955926a66SJaakko Heinonen printdev(size_t width, dev_t dev) 43055926a66SJaakko Heinonen { 4310fdf7fa8SConrad Meyer 4320fdf7fa8SConrad Meyer (void)printf("%#*jx ", (u_int)width, (uintmax_t)dev); 43355926a66SJaakko Heinonen } 43455926a66SJaakko Heinonen 435*927f8d8bSKirk McKusick static void 436be90c1c6SBaptiste Daroussin ls_strftime(char *str, size_t len, const char *fmt, const struct tm *tm) 437be90c1c6SBaptiste Daroussin { 438be90c1c6SBaptiste Daroussin char *posb, nfmt[BUFSIZ]; 439be90c1c6SBaptiste Daroussin const char *format = fmt; 440be90c1c6SBaptiste Daroussin 441be90c1c6SBaptiste Daroussin if ((posb = strstr(fmt, "%b")) != NULL) { 442be90c1c6SBaptiste Daroussin if (month_max_size == 0) { 443be90c1c6SBaptiste Daroussin compute_abbreviated_month_size(); 444be90c1c6SBaptiste Daroussin } 445*927f8d8bSKirk McKusick if (month_max_size > 0 && tm != NULL) { 446be90c1c6SBaptiste Daroussin snprintf(nfmt, sizeof(nfmt), "%.*s%s%*s%s", 447be90c1c6SBaptiste Daroussin (int)(posb - fmt), fmt, 448be90c1c6SBaptiste Daroussin get_abmon(tm->tm_mon), 449be90c1c6SBaptiste Daroussin (int)padding_for_month[tm->tm_mon], 450be90c1c6SBaptiste Daroussin "", 451be90c1c6SBaptiste Daroussin posb + 2); 452be90c1c6SBaptiste Daroussin format = nfmt; 453be90c1c6SBaptiste Daroussin } 454be90c1c6SBaptiste Daroussin } 455*927f8d8bSKirk McKusick if (tm != NULL) 456*927f8d8bSKirk McKusick strftime(str, len, format, tm); 457*927f8d8bSKirk McKusick else 458*927f8d8bSKirk McKusick strlcpy(str, "bad date val", len); 459be90c1c6SBaptiste Daroussin } 460be90c1c6SBaptiste Daroussin 4614b88c807SRodney W. Grimes static void 4620fdf7fa8SConrad Meyer printtime(time_t ftime) 4634b88c807SRodney W. Grimes { 464fc4a9bafSAndrey A. Chernov char longstring[80]; 46540feca3aSMark Murray static time_t now = 0; 46697e4e97bSJosef Karthauser const char *format; 4678234eb25SAndrey A. Chernov static int d_first = -1; 468f173abd0SMike Pritchard 46928fd017aSAndrey A. Chernov if (d_first < 0) 47028fd017aSAndrey A. Chernov d_first = (*nl_langinfo(D_MD_ORDER) == 'd'); 471f173abd0SMike Pritchard if (now == 0) 472f173abd0SMike Pritchard now = time(NULL); 4734b88c807SRodney W. Grimes 474656dcd43SGarrett Wollman #define SIXMONTHS ((365 / 2) * 86400) 4752269fa57SGreg Lehey if (f_timeformat) /* user specified format */ 4762269fa57SGreg Lehey format = f_timeformat; 4772269fa57SGreg Lehey else if (f_sectime) 4781e715e34SJosef Karthauser /* mmm dd hh:mm:ss yyyy || dd mmm hh:mm:ss yyyy */ 47928fd017aSAndrey A. Chernov format = d_first ? "%e %b %T %Y" : "%b %e %T %Y"; 480f173abd0SMike Pritchard else if (ftime + SIXMONTHS > now && ftime < now + SIXMONTHS) 4811e715e34SJosef Karthauser /* mmm dd hh:mm || dd mmm hh:mm */ 48228fd017aSAndrey A. Chernov format = d_first ? "%e %b %R" : "%b %e %R"; 48397e4e97bSJosef Karthauser else 4841e715e34SJosef Karthauser /* mmm dd yyyy || dd mmm yyyy */ 48528fd017aSAndrey A. Chernov format = d_first ? "%e %b %Y" : "%b %e %Y"; 486be90c1c6SBaptiste Daroussin ls_strftime(longstring, sizeof(longstring), format, localtime(&ftime)); 4870fdf7fa8SConrad Meyer fputs(longstring, stdout); 4880fdf7fa8SConrad Meyer fputc(' ', stdout); 4894b88c807SRodney W. Grimes } 4904b88c807SRodney W. Grimes 4914b88c807SRodney W. Grimes static int 49246251ddeSWarner Losh printtype(u_int mode) 4934b88c807SRodney W. Grimes { 49494274c73STim J. Robbins 49594274c73STim J. Robbins if (f_slash) { 49694274c73STim J. Robbins if ((mode & S_IFMT) == S_IFDIR) { 4970fdf7fa8SConrad Meyer (void)putchar('/'); 49894274c73STim J. Robbins return (1); 49994274c73STim J. Robbins } 50094274c73STim J. Robbins return (0); 50194274c73STim J. Robbins } 50294274c73STim J. Robbins 5034b88c807SRodney W. Grimes switch (mode & S_IFMT) { 5044b88c807SRodney W. Grimes case S_IFDIR: 5050fdf7fa8SConrad Meyer (void)putchar('/'); 5064b88c807SRodney W. Grimes return (1); 5074b88c807SRodney W. Grimes case S_IFIFO: 5080fdf7fa8SConrad Meyer (void)putchar('|'); 5094b88c807SRodney W. Grimes return (1); 5104b88c807SRodney W. Grimes case S_IFLNK: 5110fdf7fa8SConrad Meyer (void)putchar('@'); 5124b88c807SRodney W. Grimes return (1); 5134b88c807SRodney W. Grimes case S_IFSOCK: 5140fdf7fa8SConrad Meyer (void)putchar('='); 5154b88c807SRodney W. Grimes return (1); 516fb5cb208SSteve Price case S_IFWHT: 5170fdf7fa8SConrad Meyer (void)putchar('%'); 518fb5cb208SSteve Price return (1); 5199052855aSMark Murray default: 520568dcd5fSBill Fumerola break; 5214b88c807SRodney W. Grimes } 5224b88c807SRodney W. Grimes if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) { 5230fdf7fa8SConrad Meyer (void)putchar('*'); 5244b88c807SRodney W. Grimes return (1); 5254b88c807SRodney W. Grimes } 5264b88c807SRodney W. Grimes return (0); 5274b88c807SRodney W. Grimes } 5284b88c807SRodney W. Grimes 52974985094SJosef Karthauser #ifdef COLORLS 5301bf1478aSAndrey A. Chernov static int 53146251ddeSWarner Losh putch(int c) 532cf0feaeeSAndrey A. Chernov { 5330fdf7fa8SConrad Meyer (void)putchar(c); 53438782c25SAndrey A. Chernov return 0; 535cf0feaeeSAndrey A. Chernov } 536cf0feaeeSAndrey A. Chernov 5371bf1478aSAndrey A. Chernov static int 53846251ddeSWarner Losh writech(int c) 53938782c25SAndrey A. Chernov { 54040feca3aSMark Murray char tmp = (char)c; 54138782c25SAndrey A. Chernov 54238782c25SAndrey A. Chernov (void)write(STDOUT_FILENO, &tmp, 1); 54338782c25SAndrey A. Chernov return 0; 54438782c25SAndrey A. Chernov } 545cf0feaeeSAndrey A. Chernov 5461bf1478aSAndrey A. Chernov static void 547e10ba800SKyle Evans printcolor_termcap(Colors c) 5483885812cSJosef Karthauser { 54974985094SJosef Karthauser char *ansiseq; 55074985094SJosef Karthauser 551c1499cf6SJosef Karthauser if (colors[c].bold) 552c1499cf6SJosef Karthauser tputs(enter_bold, 1, putch); 55397c31821SCameron Katri if (colors[c].underline) 55497c31821SCameron Katri tputs(enter_underline, 1, putch); 555c1499cf6SJosef Karthauser 556c1499cf6SJosef Karthauser if (colors[c].num[0] != -1) { 557c1499cf6SJosef Karthauser ansiseq = tgoto(ansi_fgcol, 0, colors[c].num[0]); 55838782c25SAndrey A. Chernov if (ansiseq) 559cf0feaeeSAndrey A. Chernov tputs(ansiseq, 1, putch); 5603885812cSJosef Karthauser } 561c1499cf6SJosef Karthauser if (colors[c].num[1] != -1) { 562c1499cf6SJosef Karthauser ansiseq = tgoto(ansi_bgcol, 0, colors[c].num[1]); 56338782c25SAndrey A. Chernov if (ansiseq) 564cf0feaeeSAndrey A. Chernov tputs(ansiseq, 1, putch); 56574985094SJosef Karthauser } 56674985094SJosef Karthauser } 56774985094SJosef Karthauser 56838782c25SAndrey A. Chernov static void 569e10ba800SKyle Evans printcolor_ansi(Colors c) 57074985094SJosef Karthauser { 571e10ba800SKyle Evans 572e10ba800SKyle Evans printf("\033["); 573e10ba800SKyle Evans 574e10ba800SKyle Evans if (colors[c].bold) 575e10ba800SKyle Evans printf("1"); 57697c31821SCameron Katri if (colors[c].underline) 57797c31821SCameron Katri printf(";4"); 578e10ba800SKyle Evans if (colors[c].num[0] != -1) 579e10ba800SKyle Evans printf(";3%d", colors[c].num[0]); 580e10ba800SKyle Evans if (colors[c].num[1] != -1) 581e10ba800SKyle Evans printf(";4%d", colors[c].num[1]); 582e10ba800SKyle Evans printf("m"); 583e10ba800SKyle Evans } 584e10ba800SKyle Evans 585e10ba800SKyle Evans static void 586e10ba800SKyle Evans printcolor(Colors c) 587e10ba800SKyle Evans { 588e10ba800SKyle Evans 589e10ba800SKyle Evans if (explicitansi) 590e10ba800SKyle Evans printcolor_ansi(c); 591e10ba800SKyle Evans else 592e10ba800SKyle Evans printcolor_termcap(c); 593e10ba800SKyle Evans } 594e10ba800SKyle Evans 595e10ba800SKyle Evans static void 596e10ba800SKyle Evans endcolor_termcap(int sig) 597e10ba800SKyle Evans { 598e10ba800SKyle Evans 59938782c25SAndrey A. Chernov tputs(ansi_coloff, 1, sig ? writech : putch); 600c1499cf6SJosef Karthauser tputs(attrs_off, 1, sig ? writech : putch); 6013885812cSJosef Karthauser } 6023885812cSJosef Karthauser 603e10ba800SKyle Evans static void 604e10ba800SKyle Evans endcolor_ansi(void) 605e10ba800SKyle Evans { 606e10ba800SKyle Evans 607e10ba800SKyle Evans printf("\33[m"); 608e10ba800SKyle Evans } 609e10ba800SKyle Evans 610e10ba800SKyle Evans static void 611e10ba800SKyle Evans endcolor(int sig) 612e10ba800SKyle Evans { 613e10ba800SKyle Evans 614e10ba800SKyle Evans if (explicitansi) 615e10ba800SKyle Evans endcolor_ansi(); 616e10ba800SKyle Evans else 617e10ba800SKyle Evans endcolor_termcap(sig); 618e10ba800SKyle Evans } 619e10ba800SKyle Evans 62038782c25SAndrey A. Chernov static int 62146251ddeSWarner Losh colortype(mode_t mode) 6223885812cSJosef Karthauser { 6233885812cSJosef Karthauser switch (mode & S_IFMT) { 6243885812cSJosef Karthauser case S_IFDIR: 6253885812cSJosef Karthauser if (mode & S_IWOTH) 6263885812cSJosef Karthauser if (mode & S_ISTXT) 6273885812cSJosef Karthauser printcolor(C_WSDIR); 6283885812cSJosef Karthauser else 6293885812cSJosef Karthauser printcolor(C_WDIR); 6303885812cSJosef Karthauser else 6313885812cSJosef Karthauser printcolor(C_DIR); 6323885812cSJosef Karthauser return (1); 6333885812cSJosef Karthauser case S_IFLNK: 6343885812cSJosef Karthauser printcolor(C_LNK); 6353885812cSJosef Karthauser return (1); 6363885812cSJosef Karthauser case S_IFSOCK: 6373885812cSJosef Karthauser printcolor(C_SOCK); 6383885812cSJosef Karthauser return (1); 6393885812cSJosef Karthauser case S_IFIFO: 6403885812cSJosef Karthauser printcolor(C_FIFO); 6413885812cSJosef Karthauser return (1); 6423885812cSJosef Karthauser case S_IFBLK: 6433885812cSJosef Karthauser printcolor(C_BLK); 6443885812cSJosef Karthauser return (1); 6453885812cSJosef Karthauser case S_IFCHR: 6463885812cSJosef Karthauser printcolor(C_CHR); 6473885812cSJosef Karthauser return (1); 64840feca3aSMark Murray default:; 6493885812cSJosef Karthauser } 6503885812cSJosef Karthauser if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) { 6513885812cSJosef Karthauser if (mode & S_ISUID) 6523885812cSJosef Karthauser printcolor(C_SUID); 6533885812cSJosef Karthauser else if (mode & S_ISGID) 6543885812cSJosef Karthauser printcolor(C_SGID); 6553885812cSJosef Karthauser else 6563885812cSJosef Karthauser printcolor(C_EXEC); 6573885812cSJosef Karthauser return (1); 6583885812cSJosef Karthauser } 6593885812cSJosef Karthauser return (0); 6603885812cSJosef Karthauser } 6613885812cSJosef Karthauser 6623885812cSJosef Karthauser void 66346251ddeSWarner Losh parsecolors(const char *cs) 6643885812cSJosef Karthauser { 665b0bc91e9SJosef Karthauser int i; 666b0bc91e9SJosef Karthauser int j; 667ca2993fbSMark Murray size_t len; 6683885812cSJosef Karthauser char c[2]; 669c1499cf6SJosef Karthauser short legacy_warn = 0; 67038782c25SAndrey A. Chernov 671b0bc91e9SJosef Karthauser if (cs == NULL) 672b0bc91e9SJosef Karthauser cs = ""; /* LSCOLORS not set */ 6733885812cSJosef Karthauser len = strlen(cs); 67440feca3aSMark Murray for (i = 0; i < (int)C_NUMCOLORS; i++) { 67597c31821SCameron Katri colors[i].bold = false; 67697c31821SCameron Katri colors[i].underline = false; 677c1499cf6SJosef Karthauser 67840feca3aSMark Murray if (len <= 2 * (size_t)i) { 6793885812cSJosef Karthauser c[0] = defcolors[2 * i]; 6803885812cSJosef Karthauser c[1] = defcolors[2 * i + 1]; 6815dda5d0dSJosef Karthauser } else { 6823885812cSJosef Karthauser c[0] = cs[2 * i]; 6833885812cSJosef Karthauser c[1] = cs[2 * i + 1]; 6843885812cSJosef Karthauser } 6853885812cSJosef Karthauser for (j = 0; j < 2; j++) { 686c1499cf6SJosef Karthauser /* Legacy colours used 0-7 */ 687c1499cf6SJosef Karthauser if (c[j] >= '0' && c[j] <= '7') { 688c1499cf6SJosef Karthauser colors[i].num[j] = c[j] - '0'; 689c1499cf6SJosef Karthauser if (!legacy_warn) { 6900fdf7fa8SConrad Meyer warnx("LSCOLORS should use " 691130d15dcSJosef Karthauser "characters a-h instead of 0-9 (" 692e09fdabdSTim J. Robbins "see the manual page)"); 6933885812cSJosef Karthauser } 694c1499cf6SJosef Karthauser legacy_warn = 1; 695c1499cf6SJosef Karthauser } else if (c[j] >= 'a' && c[j] <= 'h') 696c1499cf6SJosef Karthauser colors[i].num[j] = c[j] - 'a'; 697c1499cf6SJosef Karthauser else if (c[j] >= 'A' && c[j] <= 'H') { 698c1499cf6SJosef Karthauser colors[i].num[j] = c[j] - 'A'; 69997c31821SCameron Katri if (j == 1) 70097c31821SCameron Katri colors[i].underline = true; 70197c31821SCameron Katri else 70297c31821SCameron Katri colors[i].bold = true; 70397c31821SCameron Katri } else if (tolower((unsigned char)c[j]) == 'x') { 70497c31821SCameron Katri if (j == 1 && c[j] == 'X') 70597c31821SCameron Katri colors[i].underline = true; 706c1499cf6SJosef Karthauser colors[i].num[j] = -1; 70797c31821SCameron Katri } else { 7080fdf7fa8SConrad Meyer warnx("invalid character '%c' in LSCOLORS" 709e09fdabdSTim J. Robbins " env var", c[j]); 7100d72516eSJosef Karthauser colors[i].num[j] = -1; 711c1499cf6SJosef Karthauser } 7123885812cSJosef Karthauser } 7133885812cSJosef Karthauser } 7143885812cSJosef Karthauser } 715cf0feaeeSAndrey A. Chernov 7161bf1478aSAndrey A. Chernov void 71746251ddeSWarner Losh colorquit(int sig) 718cf0feaeeSAndrey A. Chernov { 71938782c25SAndrey A. Chernov endcolor(sig); 720faebfe2eSAndrey A. Chernov 721faebfe2eSAndrey A. Chernov (void)signal(sig, SIG_DFL); 722faebfe2eSAndrey A. Chernov (void)kill(getpid(), sig); 723cf0feaeeSAndrey A. Chernov } 7245dda5d0dSJosef Karthauser 72574985094SJosef Karthauser #endif /* COLORLS */ 7263885812cSJosef Karthauser 7274b88c807SRodney W. Grimes static void 728ca2993fbSMark Murray printlink(const FTSENT *p) 7294b88c807SRodney W. Grimes { 7304b88c807SRodney W. Grimes int lnklen; 731b0bc91e9SJosef Karthauser char name[MAXPATHLEN + 1]; 732b0bc91e9SJosef Karthauser char path[MAXPATHLEN + 1]; 7334b88c807SRodney W. Grimes 7344b88c807SRodney W. Grimes if (p->fts_level == FTS_ROOTLEVEL) 7354b88c807SRodney W. Grimes (void)snprintf(name, sizeof(name), "%s", p->fts_name); 7364b88c807SRodney W. Grimes else 7374b88c807SRodney W. Grimes (void)snprintf(name, sizeof(name), 7384b88c807SRodney W. Grimes "%s/%s", p->fts_parent->fts_accpath, p->fts_name); 7394b88c807SRodney W. Grimes if ((lnklen = readlink(name, path, sizeof(path) - 1)) == -1) { 7400fdf7fa8SConrad Meyer (void)fprintf(stderr, "\nls: %s: %s\n", name, strerror(errno)); 7414b88c807SRodney W. Grimes return; 7424b88c807SRodney W. Grimes } 7434b88c807SRodney W. Grimes path[lnklen] = '\0'; 7440fdf7fa8SConrad Meyer (void)printf(" -> "); 7450fdf7fa8SConrad Meyer (void)printname(path); 7464b88c807SRodney W. Grimes } 7470e8d1551SJosef Karthauser 7480e8d1551SJosef Karthauser static void 7490fdf7fa8SConrad Meyer printsize(size_t width, off_t bytes) 7500e8d1551SJosef Karthauser { 7510e8d1551SJosef Karthauser 7520e8d1551SJosef Karthauser if (f_humanval) { 75355926a66SJaakko Heinonen /* 75455926a66SJaakko Heinonen * Reserve one space before the size and allocate room for 75555926a66SJaakko Heinonen * the trailing '\0'. 75655926a66SJaakko Heinonen */ 75755926a66SJaakko Heinonen char buf[HUMANVALSTR_LEN - 1 + 1]; 7580e8d1551SJosef Karthauser 759478aa805SPawel Jakub Dawidek humanize_number(buf, sizeof(buf), (int64_t)bytes, "", 760478aa805SPawel Jakub Dawidek HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL); 7610fdf7fa8SConrad Meyer (void)printf("%*s ", (u_int)width, buf); 7620fdf7fa8SConrad Meyer } else if (f_thousands) { /* with commas */ 7639aa68a3fSGreg Lehey /* This format assignment needed to work round gcc bug. */ 7640fdf7fa8SConrad Meyer const char *format = "%*j'd "; 7650fdf7fa8SConrad Meyer (void)printf(format, (u_int)width, bytes); 7660fdf7fa8SConrad Meyer } else 7670fdf7fa8SConrad Meyer (void)printf("%*jd ", (u_int)width, bytes); 7680e8d1551SJosef Karthauser } 7690e8d1551SJosef Karthauser 770dd9aaeb0STim J. Robbins /* 771dd9aaeb0STim J. Robbins * Add a + after the standard rwxrwxrwx mode if the file has an 772f7b8687aSEdward Tomasz Napierala * ACL. strmode() reserves space at the end of the string. 773dd9aaeb0STim J. Robbins */ 774f7b8687aSEdward Tomasz Napierala static void 775f7b8687aSEdward Tomasz Napierala aclmode(char *buf, const FTSENT *p) 776f7b8687aSEdward Tomasz Napierala { 777f7b8687aSEdward Tomasz Napierala char name[MAXPATHLEN + 1]; 778f7b8687aSEdward Tomasz Napierala int ret, trivial; 779f7b8687aSEdward Tomasz Napierala static dev_t previous_dev = NODEV; 780f7b8687aSEdward Tomasz Napierala static int supports_acls = -1; 781f7b8687aSEdward Tomasz Napierala static int type = ACL_TYPE_ACCESS; 782f7b8687aSEdward Tomasz Napierala acl_t facl; 783f7b8687aSEdward Tomasz Napierala 784f7b8687aSEdward Tomasz Napierala /* 785f7b8687aSEdward Tomasz Napierala * XXX: ACLs are not supported on whiteouts and device files 786f7b8687aSEdward Tomasz Napierala * residing on UFS. 787f7b8687aSEdward Tomasz Napierala */ 788f7b8687aSEdward Tomasz Napierala if (S_ISCHR(p->fts_statp->st_mode) || S_ISBLK(p->fts_statp->st_mode) || 789f7b8687aSEdward Tomasz Napierala S_ISWHT(p->fts_statp->st_mode)) 790f7b8687aSEdward Tomasz Napierala return; 791f7b8687aSEdward Tomasz Napierala 792a3429262SEdward Tomasz Napierala if (previous_dev == p->fts_statp->st_dev && supports_acls == 0) 793a3429262SEdward Tomasz Napierala return; 794f7b8687aSEdward Tomasz Napierala 795dd9aaeb0STim J. Robbins if (p->fts_level == FTS_ROOTLEVEL) 796dd9aaeb0STim J. Robbins snprintf(name, sizeof(name), "%s", p->fts_name); 797dd9aaeb0STim J. Robbins else 798dd9aaeb0STim J. Robbins snprintf(name, sizeof(name), "%s/%s", 799dd9aaeb0STim J. Robbins p->fts_parent->fts_accpath, p->fts_name); 800a3429262SEdward Tomasz Napierala 801a3429262SEdward Tomasz Napierala if (previous_dev != p->fts_statp->st_dev) { 802a3429262SEdward Tomasz Napierala previous_dev = p->fts_statp->st_dev; 803a3429262SEdward Tomasz Napierala supports_acls = 0; 804a3429262SEdward Tomasz Napierala 805f7b8687aSEdward Tomasz Napierala ret = lpathconf(name, _PC_ACL_NFS4); 806f7b8687aSEdward Tomasz Napierala if (ret > 0) { 807f7b8687aSEdward Tomasz Napierala type = ACL_TYPE_NFS4; 808f7b8687aSEdward Tomasz Napierala supports_acls = 1; 809f7b8687aSEdward Tomasz Napierala } else if (ret < 0 && errno != EINVAL) { 8100fdf7fa8SConrad Meyer warn("%s", name); 811dd9aaeb0STim J. Robbins return; 812dd9aaeb0STim J. Robbins } 813f7b8687aSEdward Tomasz Napierala if (supports_acls == 0) { 814f7b8687aSEdward Tomasz Napierala ret = lpathconf(name, _PC_ACL_EXTENDED); 815f7b8687aSEdward Tomasz Napierala if (ret > 0) { 816f7b8687aSEdward Tomasz Napierala type = ACL_TYPE_ACCESS; 817f7b8687aSEdward Tomasz Napierala supports_acls = 1; 818f7b8687aSEdward Tomasz Napierala } else if (ret < 0 && errno != EINVAL) { 8190fdf7fa8SConrad Meyer warn("%s", name); 820f7b8687aSEdward Tomasz Napierala return; 821dd9aaeb0STim J. Robbins } 822f7b8687aSEdward Tomasz Napierala } 823f7b8687aSEdward Tomasz Napierala } 824f7b8687aSEdward Tomasz Napierala if (supports_acls == 0) 825f7b8687aSEdward Tomasz Napierala return; 826f7b8687aSEdward Tomasz Napierala facl = acl_get_link_np(name, type); 827f7b8687aSEdward Tomasz Napierala if (facl == NULL) { 8280fdf7fa8SConrad Meyer warn("%s", name); 829f7b8687aSEdward Tomasz Napierala return; 830f7b8687aSEdward Tomasz Napierala } 831f7b8687aSEdward Tomasz Napierala if (acl_is_trivial_np(facl, &trivial)) { 832dd9aaeb0STim J. Robbins acl_free(facl); 8330fdf7fa8SConrad Meyer warn("%s", name); 834f7b8687aSEdward Tomasz Napierala return; 835f7b8687aSEdward Tomasz Napierala } 836f7b8687aSEdward Tomasz Napierala if (!trivial) 837f7b8687aSEdward Tomasz Napierala buf[10] = '+'; 838f7b8687aSEdward Tomasz Napierala acl_free(facl); 839dd9aaeb0STim J. Robbins } 840