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; 237*3bfbb521SMinsoo Choo (void)printf("%s %*ju ", buf, dp->s_nlink, 238*3bfbb521SMinsoo Choo (uintmax_t)sp->st_nlink); 239*3bfbb521SMinsoo Choo if (!f_sowner) 240*3bfbb521SMinsoo Choo (void)printf("%-*s ", dp->s_user, np->user); 241*3bfbb521SMinsoo Choo (void)printf("%-*s ", dp->s_group, np->group); 2424b88c807SRodney W. Grimes if (f_flags) 2430fdf7fa8SConrad Meyer (void)printf("%-*s ", dp->s_flags, np->flags); 2444d33b62eSRobert Watson if (f_label) 2450fdf7fa8SConrad Meyer (void)printf("%-*s ", dp->s_label, np->label); 2464b88c807SRodney W. Grimes if (S_ISCHR(sp->st_mode) || S_ISBLK(sp->st_mode)) 24755926a66SJaakko Heinonen printdev(dp->s_size, sp->st_rdev); 2484b88c807SRodney W. Grimes else 2490fdf7fa8SConrad Meyer printsize(dp->s_size, sp->st_size); 2504b88c807SRodney W. Grimes if (f_accesstime) 2510fdf7fa8SConrad Meyer printtime(sp->st_atime); 252fe79420eSJohn Baldwin else if (f_birthtime) 2530fdf7fa8SConrad Meyer printtime(sp->st_birthtime); 2544b88c807SRodney W. Grimes else if (f_statustime) 2550fdf7fa8SConrad Meyer printtime(sp->st_ctime); 2564b88c807SRodney W. Grimes else 2570fdf7fa8SConrad Meyer printtime(sp->st_mtime); 25874985094SJosef Karthauser #ifdef COLORLS 2593885812cSJosef Karthauser if (f_color) 260cf0feaeeSAndrey A. Chernov color_printed = colortype(sp->st_mode); 26174985094SJosef Karthauser #endif 2620fdf7fa8SConrad Meyer (void)printname(p->fts_name); 26374985094SJosef Karthauser #ifdef COLORLS 264cf0feaeeSAndrey A. Chernov if (f_color && color_printed) 26538782c25SAndrey A. Chernov endcolor(0); 26674985094SJosef Karthauser #endif 2674b88c807SRodney W. Grimes if (f_type) 2684b88c807SRodney W. Grimes (void)printtype(sp->st_mode); 2694b88c807SRodney W. Grimes if (S_ISLNK(sp->st_mode)) 2704b88c807SRodney W. Grimes printlink(p); 2710fdf7fa8SConrad Meyer (void)putchar('\n'); 2724b88c807SRodney W. Grimes } 2734b88c807SRodney W. Grimes } 2744b88c807SRodney W. Grimes 2754b88c807SRodney W. Grimes void 27640feca3aSMark Murray printstream(const DISPLAY *dp) 27794274c73STim J. Robbins { 27894274c73STim J. Robbins FTSENT *p; 27994274c73STim J. Robbins int chcnt; 28094274c73STim J. Robbins 28194274c73STim J. Robbins for (p = dp->list, chcnt = 0; p; p = p->fts_link) { 28294274c73STim J. Robbins if (p->fts_number == NO_PRINT) 28394274c73STim J. Robbins continue; 284107409f4STim J. Robbins /* XXX strlen does not take octal escapes into account. */ 28594274c73STim J. Robbins if (strlen(p->fts_name) + chcnt + 28694274c73STim J. Robbins (p->fts_link ? 2 : 0) >= (unsigned)termwidth) { 2870fdf7fa8SConrad Meyer putchar('\n'); 28894274c73STim J. Robbins chcnt = 0; 28994274c73STim J. Robbins } 29094274c73STim J. Robbins chcnt += printaname(p, dp->s_inode, dp->s_block); 29194274c73STim J. Robbins if (p->fts_link) { 2920fdf7fa8SConrad Meyer printf(", "); 29394274c73STim J. Robbins chcnt += 2; 29494274c73STim J. Robbins } 29594274c73STim J. Robbins } 29694274c73STim J. Robbins if (chcnt) 2970fdf7fa8SConrad Meyer putchar('\n'); 29894274c73STim J. Robbins } 29994274c73STim J. Robbins 30094274c73STim J. Robbins void 30140feca3aSMark Murray printcol(const DISPLAY *dp) 3024b88c807SRodney W. Grimes { 3034b88c807SRodney W. Grimes static FTSENT **array; 3044b88c807SRodney W. Grimes static int lastentries = -1; 3054b88c807SRodney W. Grimes FTSENT *p; 306c5bc8709STim J. Robbins FTSENT **narray; 307b0bc91e9SJosef Karthauser int base; 308b0bc91e9SJosef Karthauser int chcnt; 309b0bc91e9SJosef Karthauser int cnt; 310b0bc91e9SJosef Karthauser int col; 311b0bc91e9SJosef Karthauser int colwidth; 312b0bc91e9SJosef Karthauser int endcol; 313b0bc91e9SJosef Karthauser int num; 314b0bc91e9SJosef Karthauser int numcols; 315b0bc91e9SJosef Karthauser int numrows; 316b0bc91e9SJosef Karthauser int row; 317545f583cSTim Vanderhoek int tabwidth; 318545f583cSTim Vanderhoek 319545f583cSTim Vanderhoek if (f_notabs) 320545f583cSTim Vanderhoek tabwidth = 1; 321545f583cSTim Vanderhoek else 322545f583cSTim Vanderhoek tabwidth = 8; 3234b88c807SRodney W. Grimes 3244b88c807SRodney W. Grimes /* 3254b88c807SRodney W. Grimes * Have to do random access in the linked list -- build a table 3264b88c807SRodney W. Grimes * of pointers. 3274b88c807SRodney W. Grimes */ 3284b88c807SRodney W. Grimes if (dp->entries > lastentries) { 329c5bc8709STim J. Robbins if ((narray = 3304b88c807SRodney W. Grimes realloc(array, dp->entries * sizeof(FTSENT *))) == NULL) { 3310fdf7fa8SConrad Meyer warn(NULL); 3324b88c807SRodney W. Grimes printscol(dp); 333c5bc8709STim J. Robbins return; 3344b88c807SRodney W. Grimes } 335c5bc8709STim J. Robbins lastentries = dp->entries; 336c5bc8709STim J. Robbins array = narray; 3374b88c807SRodney W. Grimes } 3384b88c807SRodney W. Grimes for (p = dp->list, num = 0; p; p = p->fts_link) 3394b88c807SRodney W. Grimes if (p->fts_number != NO_PRINT) 3404b88c807SRodney W. Grimes array[num++] = p; 3414b88c807SRodney W. Grimes 3424b88c807SRodney W. Grimes colwidth = dp->maxlen; 3434b88c807SRodney W. Grimes if (f_inode) 3444b88c807SRodney W. Grimes colwidth += dp->s_inode + 1; 3454b88c807SRodney W. Grimes if (f_size) 3464b88c807SRodney W. Grimes colwidth += dp->s_block + 1; 3474b88c807SRodney W. Grimes if (f_type) 3484b88c807SRodney W. Grimes colwidth += 1; 3494b88c807SRodney W. Grimes 350545f583cSTim Vanderhoek colwidth = (colwidth + tabwidth) & ~(tabwidth - 1); 3514b88c807SRodney W. Grimes if (termwidth < 2 * colwidth) { 3524b88c807SRodney W. Grimes printscol(dp); 3534b88c807SRodney W. Grimes return; 3544b88c807SRodney W. Grimes } 3554b88c807SRodney W. Grimes numcols = termwidth / colwidth; 3564b88c807SRodney W. Grimes numrows = num / numcols; 3574b88c807SRodney W. Grimes if (num % numcols) 3584b88c807SRodney W. Grimes ++numrows; 3594b88c807SRodney W. Grimes 36048a91b69SDavid Schultz if ((dp->list == NULL || dp->list->fts_level != FTS_ROOTLEVEL) && 36148a91b69SDavid Schultz (f_longform || f_size)) { 3620fdf7fa8SConrad Meyer (void)printf("total %lu\n", howmany(dp->btotal, blocksize)); 36348a91b69SDavid Schultz } 36494274c73STim J. Robbins 36594274c73STim J. Robbins base = 0; 3664b88c807SRodney W. Grimes for (row = 0; row < numrows; ++row) { 3674b88c807SRodney W. Grimes endcol = colwidth; 36894274c73STim J. Robbins if (!f_sortacross) 36994274c73STim J. Robbins base = row; 37094274c73STim J. Robbins for (col = 0, chcnt = 0; col < numcols; ++col) { 3714b88c807SRodney W. Grimes chcnt += printaname(array[base], dp->s_inode, 3724b88c807SRodney W. Grimes dp->s_block); 37394274c73STim J. Robbins if (f_sortacross) 37494274c73STim J. Robbins base++; 37594274c73STim J. Robbins else 37694274c73STim J. Robbins base += numrows; 37794274c73STim J. Robbins if (base >= num) 3784b88c807SRodney W. Grimes break; 379545f583cSTim Vanderhoek while ((cnt = ((chcnt + tabwidth) & ~(tabwidth - 1))) 380545f583cSTim Vanderhoek <= endcol) { 38194274c73STim J. Robbins if (f_sortacross && col + 1 >= numcols) 38294274c73STim J. Robbins break; 3830fdf7fa8SConrad Meyer (void)putchar(f_notabs ? ' ' : '\t'); 3844b88c807SRodney W. Grimes chcnt = cnt; 3854b88c807SRodney W. Grimes } 3864b88c807SRodney W. Grimes endcol += colwidth; 3874b88c807SRodney W. Grimes } 3880fdf7fa8SConrad Meyer (void)putchar('\n'); 3894b88c807SRodney W. Grimes } 3904b88c807SRodney W. Grimes } 3914b88c807SRodney W. Grimes 3924b88c807SRodney W. Grimes /* 3934b88c807SRodney W. Grimes * print [inode] [size] name 3944b88c807SRodney W. Grimes * return # of characters printed, no trailing characters. 3954b88c807SRodney W. Grimes */ 3964b88c807SRodney W. Grimes static int 39740feca3aSMark Murray printaname(const FTSENT *p, u_long inodefield, u_long sizefield) 3984b88c807SRodney W. Grimes { 3994b88c807SRodney W. Grimes struct stat *sp; 4004b88c807SRodney W. Grimes int chcnt; 40147bb6b11SAndrey A. Chernov #ifdef COLORLS 40247bb6b11SAndrey A. Chernov int color_printed = 0; 40347bb6b11SAndrey A. Chernov #endif 4044b88c807SRodney W. Grimes 4054b88c807SRodney W. Grimes sp = p->fts_statp; 4064b88c807SRodney W. Grimes chcnt = 0; 4074b88c807SRodney W. Grimes if (f_inode) 4080fdf7fa8SConrad Meyer chcnt += printf("%*ju ", 4096db1a7f1SMatthew D Fleming (int)inodefield, (uintmax_t)sp->st_ino); 4104b88c807SRodney W. Grimes if (f_size) 4110fdf7fa8SConrad Meyer chcnt += printf("%*jd ", 4124b88c807SRodney W. Grimes (int)sizefield, howmany(sp->st_blocks, blocksize)); 41374985094SJosef Karthauser #ifdef COLORLS 4143885812cSJosef Karthauser if (f_color) 415cf0feaeeSAndrey A. Chernov color_printed = colortype(sp->st_mode); 41674985094SJosef Karthauser #endif 4170fdf7fa8SConrad Meyer chcnt += printname(p->fts_name); 41874985094SJosef Karthauser #ifdef COLORLS 419cf0feaeeSAndrey A. Chernov if (f_color && color_printed) 42038782c25SAndrey A. Chernov endcolor(0); 42174985094SJosef Karthauser #endif 4224b88c807SRodney W. Grimes if (f_type) 4234b88c807SRodney W. Grimes chcnt += printtype(sp->st_mode); 4244b88c807SRodney W. Grimes return (chcnt); 4254b88c807SRodney W. Grimes } 4264b88c807SRodney W. Grimes 42755926a66SJaakko Heinonen /* 42855926a66SJaakko Heinonen * Print device special file major and minor numbers. 42955926a66SJaakko Heinonen */ 43055926a66SJaakko Heinonen static void 43155926a66SJaakko Heinonen printdev(size_t width, dev_t dev) 43255926a66SJaakko Heinonen { 4330fdf7fa8SConrad Meyer 4340fdf7fa8SConrad Meyer (void)printf("%#*jx ", (u_int)width, (uintmax_t)dev); 43555926a66SJaakko Heinonen } 43655926a66SJaakko Heinonen 437927f8d8bSKirk McKusick static void 438be90c1c6SBaptiste Daroussin ls_strftime(char *str, size_t len, const char *fmt, const struct tm *tm) 439be90c1c6SBaptiste Daroussin { 440be90c1c6SBaptiste Daroussin char *posb, nfmt[BUFSIZ]; 441be90c1c6SBaptiste Daroussin const char *format = fmt; 442be90c1c6SBaptiste Daroussin 443be90c1c6SBaptiste Daroussin if ((posb = strstr(fmt, "%b")) != NULL) { 444be90c1c6SBaptiste Daroussin if (month_max_size == 0) { 445be90c1c6SBaptiste Daroussin compute_abbreviated_month_size(); 446be90c1c6SBaptiste Daroussin } 447927f8d8bSKirk McKusick if (month_max_size > 0 && tm != NULL) { 448be90c1c6SBaptiste Daroussin snprintf(nfmt, sizeof(nfmt), "%.*s%s%*s%s", 449be90c1c6SBaptiste Daroussin (int)(posb - fmt), fmt, 450be90c1c6SBaptiste Daroussin get_abmon(tm->tm_mon), 451be90c1c6SBaptiste Daroussin (int)padding_for_month[tm->tm_mon], 452be90c1c6SBaptiste Daroussin "", 453be90c1c6SBaptiste Daroussin posb + 2); 454be90c1c6SBaptiste Daroussin format = nfmt; 455be90c1c6SBaptiste Daroussin } 456be90c1c6SBaptiste Daroussin } 457927f8d8bSKirk McKusick if (tm != NULL) 458927f8d8bSKirk McKusick strftime(str, len, format, tm); 459927f8d8bSKirk McKusick else 460927f8d8bSKirk McKusick strlcpy(str, "bad date val", len); 461be90c1c6SBaptiste Daroussin } 462be90c1c6SBaptiste Daroussin 4634b88c807SRodney W. Grimes static void 4640fdf7fa8SConrad Meyer printtime(time_t ftime) 4654b88c807SRodney W. Grimes { 466fc4a9bafSAndrey A. Chernov char longstring[80]; 46740feca3aSMark Murray static time_t now = 0; 46897e4e97bSJosef Karthauser const char *format; 4698234eb25SAndrey A. Chernov static int d_first = -1; 470f173abd0SMike Pritchard 47128fd017aSAndrey A. Chernov if (d_first < 0) 47228fd017aSAndrey A. Chernov d_first = (*nl_langinfo(D_MD_ORDER) == 'd'); 473f173abd0SMike Pritchard if (now == 0) 474f173abd0SMike Pritchard now = time(NULL); 4754b88c807SRodney W. Grimes 476656dcd43SGarrett Wollman #define SIXMONTHS ((365 / 2) * 86400) 4772269fa57SGreg Lehey if (f_timeformat) /* user specified format */ 4782269fa57SGreg Lehey format = f_timeformat; 4792269fa57SGreg Lehey else if (f_sectime) 4801e715e34SJosef Karthauser /* mmm dd hh:mm:ss yyyy || dd mmm hh:mm:ss yyyy */ 48128fd017aSAndrey A. Chernov format = d_first ? "%e %b %T %Y" : "%b %e %T %Y"; 482f173abd0SMike Pritchard else if (ftime + SIXMONTHS > now && ftime < now + SIXMONTHS) 4831e715e34SJosef Karthauser /* mmm dd hh:mm || dd mmm hh:mm */ 48428fd017aSAndrey A. Chernov format = d_first ? "%e %b %R" : "%b %e %R"; 48597e4e97bSJosef Karthauser else 4861e715e34SJosef Karthauser /* mmm dd yyyy || dd mmm yyyy */ 48728fd017aSAndrey A. Chernov format = d_first ? "%e %b %Y" : "%b %e %Y"; 488be90c1c6SBaptiste Daroussin ls_strftime(longstring, sizeof(longstring), format, localtime(&ftime)); 4890fdf7fa8SConrad Meyer fputs(longstring, stdout); 4900fdf7fa8SConrad Meyer fputc(' ', stdout); 4914b88c807SRodney W. Grimes } 4924b88c807SRodney W. Grimes 4934b88c807SRodney W. Grimes static int 49446251ddeSWarner Losh printtype(u_int mode) 4954b88c807SRodney W. Grimes { 49694274c73STim J. Robbins 49794274c73STim J. Robbins if (f_slash) { 49894274c73STim J. Robbins if ((mode & S_IFMT) == S_IFDIR) { 4990fdf7fa8SConrad Meyer (void)putchar('/'); 50094274c73STim J. Robbins return (1); 50194274c73STim J. Robbins } 50294274c73STim J. Robbins return (0); 50394274c73STim J. Robbins } 50494274c73STim J. Robbins 5054b88c807SRodney W. Grimes switch (mode & S_IFMT) { 5064b88c807SRodney W. Grimes case S_IFDIR: 5070fdf7fa8SConrad Meyer (void)putchar('/'); 5084b88c807SRodney W. Grimes return (1); 5094b88c807SRodney W. Grimes case S_IFIFO: 5100fdf7fa8SConrad Meyer (void)putchar('|'); 5114b88c807SRodney W. Grimes return (1); 5124b88c807SRodney W. Grimes case S_IFLNK: 5130fdf7fa8SConrad Meyer (void)putchar('@'); 5144b88c807SRodney W. Grimes return (1); 5154b88c807SRodney W. Grimes case S_IFSOCK: 5160fdf7fa8SConrad Meyer (void)putchar('='); 5174b88c807SRodney W. Grimes return (1); 518fb5cb208SSteve Price case S_IFWHT: 5190fdf7fa8SConrad Meyer (void)putchar('%'); 520fb5cb208SSteve Price return (1); 5219052855aSMark Murray default: 522568dcd5fSBill Fumerola break; 5234b88c807SRodney W. Grimes } 5244b88c807SRodney W. Grimes if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) { 5250fdf7fa8SConrad Meyer (void)putchar('*'); 5264b88c807SRodney W. Grimes return (1); 5274b88c807SRodney W. Grimes } 5284b88c807SRodney W. Grimes return (0); 5294b88c807SRodney W. Grimes } 5304b88c807SRodney W. Grimes 53174985094SJosef Karthauser #ifdef COLORLS 5321bf1478aSAndrey A. Chernov static int 53346251ddeSWarner Losh putch(int c) 534cf0feaeeSAndrey A. Chernov { 5350fdf7fa8SConrad Meyer (void)putchar(c); 53638782c25SAndrey A. Chernov return 0; 537cf0feaeeSAndrey A. Chernov } 538cf0feaeeSAndrey A. Chernov 5391bf1478aSAndrey A. Chernov static int 54046251ddeSWarner Losh writech(int c) 54138782c25SAndrey A. Chernov { 54240feca3aSMark Murray char tmp = (char)c; 54338782c25SAndrey A. Chernov 54438782c25SAndrey A. Chernov (void)write(STDOUT_FILENO, &tmp, 1); 54538782c25SAndrey A. Chernov return 0; 54638782c25SAndrey A. Chernov } 547cf0feaeeSAndrey A. Chernov 5481bf1478aSAndrey A. Chernov static void 549e10ba800SKyle Evans printcolor_termcap(Colors c) 5503885812cSJosef Karthauser { 55174985094SJosef Karthauser char *ansiseq; 55274985094SJosef Karthauser 553c1499cf6SJosef Karthauser if (colors[c].bold) 554c1499cf6SJosef Karthauser tputs(enter_bold, 1, putch); 55597c31821SCameron Katri if (colors[c].underline) 55697c31821SCameron Katri tputs(enter_underline, 1, putch); 557c1499cf6SJosef Karthauser 558c1499cf6SJosef Karthauser if (colors[c].num[0] != -1) { 559c1499cf6SJosef Karthauser ansiseq = tgoto(ansi_fgcol, 0, colors[c].num[0]); 56038782c25SAndrey A. Chernov if (ansiseq) 561cf0feaeeSAndrey A. Chernov tputs(ansiseq, 1, putch); 5623885812cSJosef Karthauser } 563c1499cf6SJosef Karthauser if (colors[c].num[1] != -1) { 564c1499cf6SJosef Karthauser ansiseq = tgoto(ansi_bgcol, 0, colors[c].num[1]); 56538782c25SAndrey A. Chernov if (ansiseq) 566cf0feaeeSAndrey A. Chernov tputs(ansiseq, 1, putch); 56774985094SJosef Karthauser } 56874985094SJosef Karthauser } 56974985094SJosef Karthauser 57038782c25SAndrey A. Chernov static void 571e10ba800SKyle Evans printcolor_ansi(Colors c) 57274985094SJosef Karthauser { 573e10ba800SKyle Evans 574e10ba800SKyle Evans printf("\033["); 575e10ba800SKyle Evans 576e10ba800SKyle Evans if (colors[c].bold) 577e10ba800SKyle Evans printf("1"); 57897c31821SCameron Katri if (colors[c].underline) 57997c31821SCameron Katri printf(";4"); 580e10ba800SKyle Evans if (colors[c].num[0] != -1) 581e10ba800SKyle Evans printf(";3%d", colors[c].num[0]); 582e10ba800SKyle Evans if (colors[c].num[1] != -1) 583e10ba800SKyle Evans printf(";4%d", colors[c].num[1]); 584e10ba800SKyle Evans printf("m"); 585e10ba800SKyle Evans } 586e10ba800SKyle Evans 587e10ba800SKyle Evans static void 588e10ba800SKyle Evans printcolor(Colors c) 589e10ba800SKyle Evans { 590e10ba800SKyle Evans 591e10ba800SKyle Evans if (explicitansi) 592e10ba800SKyle Evans printcolor_ansi(c); 593e10ba800SKyle Evans else 594e10ba800SKyle Evans printcolor_termcap(c); 595e10ba800SKyle Evans } 596e10ba800SKyle Evans 597e10ba800SKyle Evans static void 598e10ba800SKyle Evans endcolor_termcap(int sig) 599e10ba800SKyle Evans { 600e10ba800SKyle Evans 60138782c25SAndrey A. Chernov tputs(ansi_coloff, 1, sig ? writech : putch); 602c1499cf6SJosef Karthauser tputs(attrs_off, 1, sig ? writech : putch); 6033885812cSJosef Karthauser } 6043885812cSJosef Karthauser 605e10ba800SKyle Evans static void 606e10ba800SKyle Evans endcolor_ansi(void) 607e10ba800SKyle Evans { 608e10ba800SKyle Evans 609e10ba800SKyle Evans printf("\33[m"); 610e10ba800SKyle Evans } 611e10ba800SKyle Evans 612e10ba800SKyle Evans static void 613e10ba800SKyle Evans endcolor(int sig) 614e10ba800SKyle Evans { 615e10ba800SKyle Evans 616e10ba800SKyle Evans if (explicitansi) 617e10ba800SKyle Evans endcolor_ansi(); 618e10ba800SKyle Evans else 619e10ba800SKyle Evans endcolor_termcap(sig); 620e10ba800SKyle Evans } 621e10ba800SKyle Evans 62238782c25SAndrey A. Chernov static int 62346251ddeSWarner Losh colortype(mode_t mode) 6243885812cSJosef Karthauser { 6253885812cSJosef Karthauser switch (mode & S_IFMT) { 6263885812cSJosef Karthauser case S_IFDIR: 6273885812cSJosef Karthauser if (mode & S_IWOTH) 6283885812cSJosef Karthauser if (mode & S_ISTXT) 6293885812cSJosef Karthauser printcolor(C_WSDIR); 6303885812cSJosef Karthauser else 6313885812cSJosef Karthauser printcolor(C_WDIR); 6323885812cSJosef Karthauser else 6333885812cSJosef Karthauser printcolor(C_DIR); 6343885812cSJosef Karthauser return (1); 6353885812cSJosef Karthauser case S_IFLNK: 6363885812cSJosef Karthauser printcolor(C_LNK); 6373885812cSJosef Karthauser return (1); 6383885812cSJosef Karthauser case S_IFSOCK: 6393885812cSJosef Karthauser printcolor(C_SOCK); 6403885812cSJosef Karthauser return (1); 6413885812cSJosef Karthauser case S_IFIFO: 6423885812cSJosef Karthauser printcolor(C_FIFO); 6433885812cSJosef Karthauser return (1); 6443885812cSJosef Karthauser case S_IFBLK: 6453885812cSJosef Karthauser printcolor(C_BLK); 6463885812cSJosef Karthauser return (1); 6473885812cSJosef Karthauser case S_IFCHR: 6483885812cSJosef Karthauser printcolor(C_CHR); 6493885812cSJosef Karthauser return (1); 65040feca3aSMark Murray default:; 6513885812cSJosef Karthauser } 6523885812cSJosef Karthauser if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) { 6533885812cSJosef Karthauser if (mode & S_ISUID) 6543885812cSJosef Karthauser printcolor(C_SUID); 6553885812cSJosef Karthauser else if (mode & S_ISGID) 6563885812cSJosef Karthauser printcolor(C_SGID); 6573885812cSJosef Karthauser else 6583885812cSJosef Karthauser printcolor(C_EXEC); 6593885812cSJosef Karthauser return (1); 6603885812cSJosef Karthauser } 6613885812cSJosef Karthauser return (0); 6623885812cSJosef Karthauser } 6633885812cSJosef Karthauser 6643885812cSJosef Karthauser void 66546251ddeSWarner Losh parsecolors(const char *cs) 6663885812cSJosef Karthauser { 667b0bc91e9SJosef Karthauser int i; 668b0bc91e9SJosef Karthauser int j; 669ca2993fbSMark Murray size_t len; 6703885812cSJosef Karthauser char c[2]; 671c1499cf6SJosef Karthauser short legacy_warn = 0; 67238782c25SAndrey A. Chernov 673b0bc91e9SJosef Karthauser if (cs == NULL) 674b0bc91e9SJosef Karthauser cs = ""; /* LSCOLORS not set */ 6753885812cSJosef Karthauser len = strlen(cs); 67640feca3aSMark Murray for (i = 0; i < (int)C_NUMCOLORS; i++) { 67797c31821SCameron Katri colors[i].bold = false; 67897c31821SCameron Katri colors[i].underline = false; 679c1499cf6SJosef Karthauser 68040feca3aSMark Murray if (len <= 2 * (size_t)i) { 6813885812cSJosef Karthauser c[0] = defcolors[2 * i]; 6823885812cSJosef Karthauser c[1] = defcolors[2 * i + 1]; 6835dda5d0dSJosef Karthauser } else { 6843885812cSJosef Karthauser c[0] = cs[2 * i]; 6853885812cSJosef Karthauser c[1] = cs[2 * i + 1]; 6863885812cSJosef Karthauser } 6873885812cSJosef Karthauser for (j = 0; j < 2; j++) { 688c1499cf6SJosef Karthauser /* Legacy colours used 0-7 */ 689c1499cf6SJosef Karthauser if (c[j] >= '0' && c[j] <= '7') { 690c1499cf6SJosef Karthauser colors[i].num[j] = c[j] - '0'; 691c1499cf6SJosef Karthauser if (!legacy_warn) { 6920fdf7fa8SConrad Meyer warnx("LSCOLORS should use " 693130d15dcSJosef Karthauser "characters a-h instead of 0-9 (" 694e09fdabdSTim J. Robbins "see the manual page)"); 6953885812cSJosef Karthauser } 696c1499cf6SJosef Karthauser legacy_warn = 1; 697c1499cf6SJosef Karthauser } else if (c[j] >= 'a' && c[j] <= 'h') 698c1499cf6SJosef Karthauser colors[i].num[j] = c[j] - 'a'; 699c1499cf6SJosef Karthauser else if (c[j] >= 'A' && c[j] <= 'H') { 700c1499cf6SJosef Karthauser colors[i].num[j] = c[j] - 'A'; 70197c31821SCameron Katri if (j == 1) 70297c31821SCameron Katri colors[i].underline = true; 70397c31821SCameron Katri else 70497c31821SCameron Katri colors[i].bold = true; 70597c31821SCameron Katri } else if (tolower((unsigned char)c[j]) == 'x') { 70697c31821SCameron Katri if (j == 1 && c[j] == 'X') 70797c31821SCameron Katri colors[i].underline = true; 708c1499cf6SJosef Karthauser colors[i].num[j] = -1; 70997c31821SCameron Katri } else { 7100fdf7fa8SConrad Meyer warnx("invalid character '%c' in LSCOLORS" 711e09fdabdSTim J. Robbins " env var", c[j]); 7120d72516eSJosef Karthauser colors[i].num[j] = -1; 713c1499cf6SJosef Karthauser } 7143885812cSJosef Karthauser } 7153885812cSJosef Karthauser } 7163885812cSJosef Karthauser } 717cf0feaeeSAndrey A. Chernov 7181bf1478aSAndrey A. Chernov void 71946251ddeSWarner Losh colorquit(int sig) 720cf0feaeeSAndrey A. Chernov { 72138782c25SAndrey A. Chernov endcolor(sig); 722faebfe2eSAndrey A. Chernov 723faebfe2eSAndrey A. Chernov (void)signal(sig, SIG_DFL); 724faebfe2eSAndrey A. Chernov (void)kill(getpid(), sig); 725cf0feaeeSAndrey A. Chernov } 7265dda5d0dSJosef Karthauser 72774985094SJosef Karthauser #endif /* COLORLS */ 7283885812cSJosef Karthauser 7294b88c807SRodney W. Grimes static void 730ca2993fbSMark Murray printlink(const FTSENT *p) 7314b88c807SRodney W. Grimes { 7324b88c807SRodney W. Grimes int lnklen; 733b0bc91e9SJosef Karthauser char name[MAXPATHLEN + 1]; 734b0bc91e9SJosef Karthauser char path[MAXPATHLEN + 1]; 7354b88c807SRodney W. Grimes 7364b88c807SRodney W. Grimes if (p->fts_level == FTS_ROOTLEVEL) 7374b88c807SRodney W. Grimes (void)snprintf(name, sizeof(name), "%s", p->fts_name); 7384b88c807SRodney W. Grimes else 7394b88c807SRodney W. Grimes (void)snprintf(name, sizeof(name), 7404b88c807SRodney W. Grimes "%s/%s", p->fts_parent->fts_accpath, p->fts_name); 7414b88c807SRodney W. Grimes if ((lnklen = readlink(name, path, sizeof(path) - 1)) == -1) { 7420fdf7fa8SConrad Meyer (void)fprintf(stderr, "\nls: %s: %s\n", name, strerror(errno)); 7434b88c807SRodney W. Grimes return; 7444b88c807SRodney W. Grimes } 7454b88c807SRodney W. Grimes path[lnklen] = '\0'; 7460fdf7fa8SConrad Meyer (void)printf(" -> "); 7470fdf7fa8SConrad Meyer (void)printname(path); 7484b88c807SRodney W. Grimes } 7490e8d1551SJosef Karthauser 7500e8d1551SJosef Karthauser static void 7510fdf7fa8SConrad Meyer printsize(size_t width, off_t bytes) 7520e8d1551SJosef Karthauser { 7530e8d1551SJosef Karthauser 7540e8d1551SJosef Karthauser if (f_humanval) { 75555926a66SJaakko Heinonen /* 75655926a66SJaakko Heinonen * Reserve one space before the size and allocate room for 75755926a66SJaakko Heinonen * the trailing '\0'. 75855926a66SJaakko Heinonen */ 75955926a66SJaakko Heinonen char buf[HUMANVALSTR_LEN - 1 + 1]; 7600e8d1551SJosef Karthauser 761478aa805SPawel Jakub Dawidek humanize_number(buf, sizeof(buf), (int64_t)bytes, "", 762478aa805SPawel Jakub Dawidek HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL); 7630fdf7fa8SConrad Meyer (void)printf("%*s ", (u_int)width, buf); 7640fdf7fa8SConrad Meyer } else if (f_thousands) { /* with commas */ 7659aa68a3fSGreg Lehey /* This format assignment needed to work round gcc bug. */ 7660fdf7fa8SConrad Meyer const char *format = "%*j'd "; 7670fdf7fa8SConrad Meyer (void)printf(format, (u_int)width, bytes); 7680fdf7fa8SConrad Meyer } else 7690fdf7fa8SConrad Meyer (void)printf("%*jd ", (u_int)width, bytes); 7700e8d1551SJosef Karthauser } 7710e8d1551SJosef Karthauser 772dd9aaeb0STim J. Robbins /* 773dd9aaeb0STim J. Robbins * Add a + after the standard rwxrwxrwx mode if the file has an 774f7b8687aSEdward Tomasz Napierala * ACL. strmode() reserves space at the end of the string. 775dd9aaeb0STim J. Robbins */ 776f7b8687aSEdward Tomasz Napierala static void 777f7b8687aSEdward Tomasz Napierala aclmode(char *buf, const FTSENT *p) 778f7b8687aSEdward Tomasz Napierala { 779f7b8687aSEdward Tomasz Napierala char name[MAXPATHLEN + 1]; 780f7b8687aSEdward Tomasz Napierala int ret, trivial; 781f7b8687aSEdward Tomasz Napierala static dev_t previous_dev = NODEV; 782f7b8687aSEdward Tomasz Napierala static int supports_acls = -1; 783f7b8687aSEdward Tomasz Napierala static int type = ACL_TYPE_ACCESS; 784f7b8687aSEdward Tomasz Napierala acl_t facl; 785f7b8687aSEdward Tomasz Napierala 786f7b8687aSEdward Tomasz Napierala /* 787f7b8687aSEdward Tomasz Napierala * XXX: ACLs are not supported on whiteouts and device files 788f7b8687aSEdward Tomasz Napierala * residing on UFS. 789f7b8687aSEdward Tomasz Napierala */ 790f7b8687aSEdward Tomasz Napierala if (S_ISCHR(p->fts_statp->st_mode) || S_ISBLK(p->fts_statp->st_mode) || 791f7b8687aSEdward Tomasz Napierala S_ISWHT(p->fts_statp->st_mode)) 792f7b8687aSEdward Tomasz Napierala return; 793f7b8687aSEdward Tomasz Napierala 794a3429262SEdward Tomasz Napierala if (previous_dev == p->fts_statp->st_dev && supports_acls == 0) 795a3429262SEdward Tomasz Napierala return; 796f7b8687aSEdward Tomasz Napierala 797dd9aaeb0STim J. Robbins if (p->fts_level == FTS_ROOTLEVEL) 798dd9aaeb0STim J. Robbins snprintf(name, sizeof(name), "%s", p->fts_name); 799dd9aaeb0STim J. Robbins else 800dd9aaeb0STim J. Robbins snprintf(name, sizeof(name), "%s/%s", 801dd9aaeb0STim J. Robbins p->fts_parent->fts_accpath, p->fts_name); 802a3429262SEdward Tomasz Napierala 803a3429262SEdward Tomasz Napierala if (previous_dev != p->fts_statp->st_dev) { 804a3429262SEdward Tomasz Napierala previous_dev = p->fts_statp->st_dev; 805a3429262SEdward Tomasz Napierala supports_acls = 0; 806a3429262SEdward Tomasz Napierala 807f7b8687aSEdward Tomasz Napierala ret = lpathconf(name, _PC_ACL_NFS4); 808f7b8687aSEdward Tomasz Napierala if (ret > 0) { 809f7b8687aSEdward Tomasz Napierala type = ACL_TYPE_NFS4; 810f7b8687aSEdward Tomasz Napierala supports_acls = 1; 811f7b8687aSEdward Tomasz Napierala } else if (ret < 0 && errno != EINVAL) { 8120fdf7fa8SConrad Meyer warn("%s", name); 813dd9aaeb0STim J. Robbins return; 814dd9aaeb0STim J. Robbins } 815f7b8687aSEdward Tomasz Napierala if (supports_acls == 0) { 816f7b8687aSEdward Tomasz Napierala ret = lpathconf(name, _PC_ACL_EXTENDED); 817f7b8687aSEdward Tomasz Napierala if (ret > 0) { 818f7b8687aSEdward Tomasz Napierala type = ACL_TYPE_ACCESS; 819f7b8687aSEdward Tomasz Napierala supports_acls = 1; 820f7b8687aSEdward Tomasz Napierala } else if (ret < 0 && errno != EINVAL) { 8210fdf7fa8SConrad Meyer warn("%s", name); 822f7b8687aSEdward Tomasz Napierala return; 823dd9aaeb0STim J. Robbins } 824f7b8687aSEdward Tomasz Napierala } 825f7b8687aSEdward Tomasz Napierala } 826f7b8687aSEdward Tomasz Napierala if (supports_acls == 0) 827f7b8687aSEdward Tomasz Napierala return; 828f7b8687aSEdward Tomasz Napierala facl = acl_get_link_np(name, type); 829f7b8687aSEdward Tomasz Napierala if (facl == NULL) { 8300fdf7fa8SConrad Meyer warn("%s", name); 831f7b8687aSEdward Tomasz Napierala return; 832f7b8687aSEdward Tomasz Napierala } 833f7b8687aSEdward Tomasz Napierala if (acl_is_trivial_np(facl, &trivial)) { 834dd9aaeb0STim J. Robbins acl_free(facl); 8350fdf7fa8SConrad Meyer warn("%s", name); 836f7b8687aSEdward Tomasz Napierala return; 837f7b8687aSEdward Tomasz Napierala } 838f7b8687aSEdward Tomasz Napierala if (!trivial) 839f7b8687aSEdward Tomasz Napierala buf[10] = '+'; 840f7b8687aSEdward Tomasz Napierala acl_free(facl); 841dd9aaeb0STim J. Robbins } 842