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]; 109*97c31821SCameron Katri bool bold; 110*97c31821SCameron 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 435be90c1c6SBaptiste Daroussin static size_t 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 size_t ret; 441be90c1c6SBaptiste Daroussin 442be90c1c6SBaptiste Daroussin if ((posb = strstr(fmt, "%b")) != NULL) { 443be90c1c6SBaptiste Daroussin if (month_max_size == 0) { 444be90c1c6SBaptiste Daroussin compute_abbreviated_month_size(); 445be90c1c6SBaptiste Daroussin } 446be90c1c6SBaptiste Daroussin if (month_max_size > 0) { 447be90c1c6SBaptiste Daroussin snprintf(nfmt, sizeof(nfmt), "%.*s%s%*s%s", 448be90c1c6SBaptiste Daroussin (int)(posb - fmt), fmt, 449be90c1c6SBaptiste Daroussin get_abmon(tm->tm_mon), 450be90c1c6SBaptiste Daroussin (int)padding_for_month[tm->tm_mon], 451be90c1c6SBaptiste Daroussin "", 452be90c1c6SBaptiste Daroussin posb + 2); 453be90c1c6SBaptiste Daroussin format = nfmt; 454be90c1c6SBaptiste Daroussin } 455be90c1c6SBaptiste Daroussin } 456be90c1c6SBaptiste Daroussin ret = strftime(str, len, format, tm); 457be90c1c6SBaptiste Daroussin return (ret); 458be90c1c6SBaptiste Daroussin } 459be90c1c6SBaptiste Daroussin 4604b88c807SRodney W. Grimes static void 4610fdf7fa8SConrad Meyer printtime(time_t ftime) 4624b88c807SRodney W. Grimes { 463fc4a9bafSAndrey A. Chernov char longstring[80]; 46440feca3aSMark Murray static time_t now = 0; 46597e4e97bSJosef Karthauser const char *format; 4668234eb25SAndrey A. Chernov static int d_first = -1; 467f173abd0SMike Pritchard 46828fd017aSAndrey A. Chernov if (d_first < 0) 46928fd017aSAndrey A. Chernov d_first = (*nl_langinfo(D_MD_ORDER) == 'd'); 470f173abd0SMike Pritchard if (now == 0) 471f173abd0SMike Pritchard now = time(NULL); 4724b88c807SRodney W. Grimes 473656dcd43SGarrett Wollman #define SIXMONTHS ((365 / 2) * 86400) 4742269fa57SGreg Lehey if (f_timeformat) /* user specified format */ 4752269fa57SGreg Lehey format = f_timeformat; 4762269fa57SGreg Lehey else if (f_sectime) 4771e715e34SJosef Karthauser /* mmm dd hh:mm:ss yyyy || dd mmm hh:mm:ss yyyy */ 47828fd017aSAndrey A. Chernov format = d_first ? "%e %b %T %Y" : "%b %e %T %Y"; 479f173abd0SMike Pritchard else if (ftime + SIXMONTHS > now && ftime < now + SIXMONTHS) 4801e715e34SJosef Karthauser /* mmm dd hh:mm || dd mmm hh:mm */ 48128fd017aSAndrey A. Chernov format = d_first ? "%e %b %R" : "%b %e %R"; 48297e4e97bSJosef Karthauser else 4831e715e34SJosef Karthauser /* mmm dd yyyy || dd mmm yyyy */ 48428fd017aSAndrey A. Chernov format = d_first ? "%e %b %Y" : "%b %e %Y"; 485be90c1c6SBaptiste Daroussin ls_strftime(longstring, sizeof(longstring), format, localtime(&ftime)); 4860fdf7fa8SConrad Meyer fputs(longstring, stdout); 4870fdf7fa8SConrad Meyer fputc(' ', stdout); 4884b88c807SRodney W. Grimes } 4894b88c807SRodney W. Grimes 4904b88c807SRodney W. Grimes static int 49146251ddeSWarner Losh printtype(u_int mode) 4924b88c807SRodney W. Grimes { 49394274c73STim J. Robbins 49494274c73STim J. Robbins if (f_slash) { 49594274c73STim J. Robbins if ((mode & S_IFMT) == S_IFDIR) { 4960fdf7fa8SConrad Meyer (void)putchar('/'); 49794274c73STim J. Robbins return (1); 49894274c73STim J. Robbins } 49994274c73STim J. Robbins return (0); 50094274c73STim J. Robbins } 50194274c73STim J. Robbins 5024b88c807SRodney W. Grimes switch (mode & S_IFMT) { 5034b88c807SRodney W. Grimes case S_IFDIR: 5040fdf7fa8SConrad Meyer (void)putchar('/'); 5054b88c807SRodney W. Grimes return (1); 5064b88c807SRodney W. Grimes case S_IFIFO: 5070fdf7fa8SConrad Meyer (void)putchar('|'); 5084b88c807SRodney W. Grimes return (1); 5094b88c807SRodney W. Grimes case S_IFLNK: 5100fdf7fa8SConrad Meyer (void)putchar('@'); 5114b88c807SRodney W. Grimes return (1); 5124b88c807SRodney W. Grimes case S_IFSOCK: 5130fdf7fa8SConrad Meyer (void)putchar('='); 5144b88c807SRodney W. Grimes return (1); 515fb5cb208SSteve Price case S_IFWHT: 5160fdf7fa8SConrad Meyer (void)putchar('%'); 517fb5cb208SSteve Price return (1); 5189052855aSMark Murray default: 519568dcd5fSBill Fumerola break; 5204b88c807SRodney W. Grimes } 5214b88c807SRodney W. Grimes if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) { 5220fdf7fa8SConrad Meyer (void)putchar('*'); 5234b88c807SRodney W. Grimes return (1); 5244b88c807SRodney W. Grimes } 5254b88c807SRodney W. Grimes return (0); 5264b88c807SRodney W. Grimes } 5274b88c807SRodney W. Grimes 52874985094SJosef Karthauser #ifdef COLORLS 5291bf1478aSAndrey A. Chernov static int 53046251ddeSWarner Losh putch(int c) 531cf0feaeeSAndrey A. Chernov { 5320fdf7fa8SConrad Meyer (void)putchar(c); 53338782c25SAndrey A. Chernov return 0; 534cf0feaeeSAndrey A. Chernov } 535cf0feaeeSAndrey A. Chernov 5361bf1478aSAndrey A. Chernov static int 53746251ddeSWarner Losh writech(int c) 53838782c25SAndrey A. Chernov { 53940feca3aSMark Murray char tmp = (char)c; 54038782c25SAndrey A. Chernov 54138782c25SAndrey A. Chernov (void)write(STDOUT_FILENO, &tmp, 1); 54238782c25SAndrey A. Chernov return 0; 54338782c25SAndrey A. Chernov } 544cf0feaeeSAndrey A. Chernov 5451bf1478aSAndrey A. Chernov static void 546e10ba800SKyle Evans printcolor_termcap(Colors c) 5473885812cSJosef Karthauser { 54874985094SJosef Karthauser char *ansiseq; 54974985094SJosef Karthauser 550c1499cf6SJosef Karthauser if (colors[c].bold) 551c1499cf6SJosef Karthauser tputs(enter_bold, 1, putch); 552*97c31821SCameron Katri if (colors[c].underline) 553*97c31821SCameron Katri tputs(enter_underline, 1, putch); 554c1499cf6SJosef Karthauser 555c1499cf6SJosef Karthauser if (colors[c].num[0] != -1) { 556c1499cf6SJosef Karthauser ansiseq = tgoto(ansi_fgcol, 0, colors[c].num[0]); 55738782c25SAndrey A. Chernov if (ansiseq) 558cf0feaeeSAndrey A. Chernov tputs(ansiseq, 1, putch); 5593885812cSJosef Karthauser } 560c1499cf6SJosef Karthauser if (colors[c].num[1] != -1) { 561c1499cf6SJosef Karthauser ansiseq = tgoto(ansi_bgcol, 0, colors[c].num[1]); 56238782c25SAndrey A. Chernov if (ansiseq) 563cf0feaeeSAndrey A. Chernov tputs(ansiseq, 1, putch); 56474985094SJosef Karthauser } 56574985094SJosef Karthauser } 56674985094SJosef Karthauser 56738782c25SAndrey A. Chernov static void 568e10ba800SKyle Evans printcolor_ansi(Colors c) 56974985094SJosef Karthauser { 570e10ba800SKyle Evans 571e10ba800SKyle Evans printf("\033["); 572e10ba800SKyle Evans 573e10ba800SKyle Evans if (colors[c].bold) 574e10ba800SKyle Evans printf("1"); 575*97c31821SCameron Katri if (colors[c].underline) 576*97c31821SCameron Katri printf(";4"); 577e10ba800SKyle Evans if (colors[c].num[0] != -1) 578e10ba800SKyle Evans printf(";3%d", colors[c].num[0]); 579e10ba800SKyle Evans if (colors[c].num[1] != -1) 580e10ba800SKyle Evans printf(";4%d", colors[c].num[1]); 581e10ba800SKyle Evans printf("m"); 582e10ba800SKyle Evans } 583e10ba800SKyle Evans 584e10ba800SKyle Evans static void 585e10ba800SKyle Evans printcolor(Colors c) 586e10ba800SKyle Evans { 587e10ba800SKyle Evans 588e10ba800SKyle Evans if (explicitansi) 589e10ba800SKyle Evans printcolor_ansi(c); 590e10ba800SKyle Evans else 591e10ba800SKyle Evans printcolor_termcap(c); 592e10ba800SKyle Evans } 593e10ba800SKyle Evans 594e10ba800SKyle Evans static void 595e10ba800SKyle Evans endcolor_termcap(int sig) 596e10ba800SKyle Evans { 597e10ba800SKyle Evans 59838782c25SAndrey A. Chernov tputs(ansi_coloff, 1, sig ? writech : putch); 599c1499cf6SJosef Karthauser tputs(attrs_off, 1, sig ? writech : putch); 6003885812cSJosef Karthauser } 6013885812cSJosef Karthauser 602e10ba800SKyle Evans static void 603e10ba800SKyle Evans endcolor_ansi(void) 604e10ba800SKyle Evans { 605e10ba800SKyle Evans 606e10ba800SKyle Evans printf("\33[m"); 607e10ba800SKyle Evans } 608e10ba800SKyle Evans 609e10ba800SKyle Evans static void 610e10ba800SKyle Evans endcolor(int sig) 611e10ba800SKyle Evans { 612e10ba800SKyle Evans 613e10ba800SKyle Evans if (explicitansi) 614e10ba800SKyle Evans endcolor_ansi(); 615e10ba800SKyle Evans else 616e10ba800SKyle Evans endcolor_termcap(sig); 617e10ba800SKyle Evans } 618e10ba800SKyle Evans 61938782c25SAndrey A. Chernov static int 62046251ddeSWarner Losh colortype(mode_t mode) 6213885812cSJosef Karthauser { 6223885812cSJosef Karthauser switch (mode & S_IFMT) { 6233885812cSJosef Karthauser case S_IFDIR: 6243885812cSJosef Karthauser if (mode & S_IWOTH) 6253885812cSJosef Karthauser if (mode & S_ISTXT) 6263885812cSJosef Karthauser printcolor(C_WSDIR); 6273885812cSJosef Karthauser else 6283885812cSJosef Karthauser printcolor(C_WDIR); 6293885812cSJosef Karthauser else 6303885812cSJosef Karthauser printcolor(C_DIR); 6313885812cSJosef Karthauser return (1); 6323885812cSJosef Karthauser case S_IFLNK: 6333885812cSJosef Karthauser printcolor(C_LNK); 6343885812cSJosef Karthauser return (1); 6353885812cSJosef Karthauser case S_IFSOCK: 6363885812cSJosef Karthauser printcolor(C_SOCK); 6373885812cSJosef Karthauser return (1); 6383885812cSJosef Karthauser case S_IFIFO: 6393885812cSJosef Karthauser printcolor(C_FIFO); 6403885812cSJosef Karthauser return (1); 6413885812cSJosef Karthauser case S_IFBLK: 6423885812cSJosef Karthauser printcolor(C_BLK); 6433885812cSJosef Karthauser return (1); 6443885812cSJosef Karthauser case S_IFCHR: 6453885812cSJosef Karthauser printcolor(C_CHR); 6463885812cSJosef Karthauser return (1); 64740feca3aSMark Murray default:; 6483885812cSJosef Karthauser } 6493885812cSJosef Karthauser if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) { 6503885812cSJosef Karthauser if (mode & S_ISUID) 6513885812cSJosef Karthauser printcolor(C_SUID); 6523885812cSJosef Karthauser else if (mode & S_ISGID) 6533885812cSJosef Karthauser printcolor(C_SGID); 6543885812cSJosef Karthauser else 6553885812cSJosef Karthauser printcolor(C_EXEC); 6563885812cSJosef Karthauser return (1); 6573885812cSJosef Karthauser } 6583885812cSJosef Karthauser return (0); 6593885812cSJosef Karthauser } 6603885812cSJosef Karthauser 6613885812cSJosef Karthauser void 66246251ddeSWarner Losh parsecolors(const char *cs) 6633885812cSJosef Karthauser { 664b0bc91e9SJosef Karthauser int i; 665b0bc91e9SJosef Karthauser int j; 666ca2993fbSMark Murray size_t len; 6673885812cSJosef Karthauser char c[2]; 668c1499cf6SJosef Karthauser short legacy_warn = 0; 66938782c25SAndrey A. Chernov 670b0bc91e9SJosef Karthauser if (cs == NULL) 671b0bc91e9SJosef Karthauser cs = ""; /* LSCOLORS not set */ 6723885812cSJosef Karthauser len = strlen(cs); 67340feca3aSMark Murray for (i = 0; i < (int)C_NUMCOLORS; i++) { 674*97c31821SCameron Katri colors[i].bold = false; 675*97c31821SCameron Katri colors[i].underline = false; 676c1499cf6SJosef Karthauser 67740feca3aSMark Murray if (len <= 2 * (size_t)i) { 6783885812cSJosef Karthauser c[0] = defcolors[2 * i]; 6793885812cSJosef Karthauser c[1] = defcolors[2 * i + 1]; 6805dda5d0dSJosef Karthauser } else { 6813885812cSJosef Karthauser c[0] = cs[2 * i]; 6823885812cSJosef Karthauser c[1] = cs[2 * i + 1]; 6833885812cSJosef Karthauser } 6843885812cSJosef Karthauser for (j = 0; j < 2; j++) { 685c1499cf6SJosef Karthauser /* Legacy colours used 0-7 */ 686c1499cf6SJosef Karthauser if (c[j] >= '0' && c[j] <= '7') { 687c1499cf6SJosef Karthauser colors[i].num[j] = c[j] - '0'; 688c1499cf6SJosef Karthauser if (!legacy_warn) { 6890fdf7fa8SConrad Meyer warnx("LSCOLORS should use " 690130d15dcSJosef Karthauser "characters a-h instead of 0-9 (" 691e09fdabdSTim J. Robbins "see the manual page)"); 6923885812cSJosef Karthauser } 693c1499cf6SJosef Karthauser legacy_warn = 1; 694c1499cf6SJosef Karthauser } else if (c[j] >= 'a' && c[j] <= 'h') 695c1499cf6SJosef Karthauser colors[i].num[j] = c[j] - 'a'; 696c1499cf6SJosef Karthauser else if (c[j] >= 'A' && c[j] <= 'H') { 697c1499cf6SJosef Karthauser colors[i].num[j] = c[j] - 'A'; 698*97c31821SCameron Katri if (j == 1) 699*97c31821SCameron Katri colors[i].underline = true; 700*97c31821SCameron Katri else 701*97c31821SCameron Katri colors[i].bold = true; 702*97c31821SCameron Katri } else if (tolower((unsigned char)c[j]) == 'x') { 703*97c31821SCameron Katri if (j == 1 && c[j] == 'X') 704*97c31821SCameron Katri colors[i].underline = true; 705c1499cf6SJosef Karthauser colors[i].num[j] = -1; 706*97c31821SCameron Katri } else { 7070fdf7fa8SConrad Meyer warnx("invalid character '%c' in LSCOLORS" 708e09fdabdSTim J. Robbins " env var", c[j]); 7090d72516eSJosef Karthauser colors[i].num[j] = -1; 710c1499cf6SJosef Karthauser } 7113885812cSJosef Karthauser } 7123885812cSJosef Karthauser } 7133885812cSJosef Karthauser } 714cf0feaeeSAndrey A. Chernov 7151bf1478aSAndrey A. Chernov void 71646251ddeSWarner Losh colorquit(int sig) 717cf0feaeeSAndrey A. Chernov { 71838782c25SAndrey A. Chernov endcolor(sig); 719faebfe2eSAndrey A. Chernov 720faebfe2eSAndrey A. Chernov (void)signal(sig, SIG_DFL); 721faebfe2eSAndrey A. Chernov (void)kill(getpid(), sig); 722cf0feaeeSAndrey A. Chernov } 7235dda5d0dSJosef Karthauser 72474985094SJosef Karthauser #endif /* COLORLS */ 7253885812cSJosef Karthauser 7264b88c807SRodney W. Grimes static void 727ca2993fbSMark Murray printlink(const FTSENT *p) 7284b88c807SRodney W. Grimes { 7294b88c807SRodney W. Grimes int lnklen; 730b0bc91e9SJosef Karthauser char name[MAXPATHLEN + 1]; 731b0bc91e9SJosef Karthauser char path[MAXPATHLEN + 1]; 7324b88c807SRodney W. Grimes 7334b88c807SRodney W. Grimes if (p->fts_level == FTS_ROOTLEVEL) 7344b88c807SRodney W. Grimes (void)snprintf(name, sizeof(name), "%s", p->fts_name); 7354b88c807SRodney W. Grimes else 7364b88c807SRodney W. Grimes (void)snprintf(name, sizeof(name), 7374b88c807SRodney W. Grimes "%s/%s", p->fts_parent->fts_accpath, p->fts_name); 7384b88c807SRodney W. Grimes if ((lnklen = readlink(name, path, sizeof(path) - 1)) == -1) { 7390fdf7fa8SConrad Meyer (void)fprintf(stderr, "\nls: %s: %s\n", name, strerror(errno)); 7404b88c807SRodney W. Grimes return; 7414b88c807SRodney W. Grimes } 7424b88c807SRodney W. Grimes path[lnklen] = '\0'; 7430fdf7fa8SConrad Meyer (void)printf(" -> "); 7440fdf7fa8SConrad Meyer (void)printname(path); 7454b88c807SRodney W. Grimes } 7460e8d1551SJosef Karthauser 7470e8d1551SJosef Karthauser static void 7480fdf7fa8SConrad Meyer printsize(size_t width, off_t bytes) 7490e8d1551SJosef Karthauser { 7500e8d1551SJosef Karthauser 7510e8d1551SJosef Karthauser if (f_humanval) { 75255926a66SJaakko Heinonen /* 75355926a66SJaakko Heinonen * Reserve one space before the size and allocate room for 75455926a66SJaakko Heinonen * the trailing '\0'. 75555926a66SJaakko Heinonen */ 75655926a66SJaakko Heinonen char buf[HUMANVALSTR_LEN - 1 + 1]; 7570e8d1551SJosef Karthauser 758478aa805SPawel Jakub Dawidek humanize_number(buf, sizeof(buf), (int64_t)bytes, "", 759478aa805SPawel Jakub Dawidek HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL); 7600fdf7fa8SConrad Meyer (void)printf("%*s ", (u_int)width, buf); 7610fdf7fa8SConrad Meyer } else if (f_thousands) { /* with commas */ 7629aa68a3fSGreg Lehey /* This format assignment needed to work round gcc bug. */ 7630fdf7fa8SConrad Meyer const char *format = "%*j'd "; 7640fdf7fa8SConrad Meyer (void)printf(format, (u_int)width, bytes); 7650fdf7fa8SConrad Meyer } else 7660fdf7fa8SConrad Meyer (void)printf("%*jd ", (u_int)width, bytes); 7670e8d1551SJosef Karthauser } 7680e8d1551SJosef Karthauser 769dd9aaeb0STim J. Robbins /* 770dd9aaeb0STim J. Robbins * Add a + after the standard rwxrwxrwx mode if the file has an 771f7b8687aSEdward Tomasz Napierala * ACL. strmode() reserves space at the end of the string. 772dd9aaeb0STim J. Robbins */ 773f7b8687aSEdward Tomasz Napierala static void 774f7b8687aSEdward Tomasz Napierala aclmode(char *buf, const FTSENT *p) 775f7b8687aSEdward Tomasz Napierala { 776f7b8687aSEdward Tomasz Napierala char name[MAXPATHLEN + 1]; 777f7b8687aSEdward Tomasz Napierala int ret, trivial; 778f7b8687aSEdward Tomasz Napierala static dev_t previous_dev = NODEV; 779f7b8687aSEdward Tomasz Napierala static int supports_acls = -1; 780f7b8687aSEdward Tomasz Napierala static int type = ACL_TYPE_ACCESS; 781f7b8687aSEdward Tomasz Napierala acl_t facl; 782f7b8687aSEdward Tomasz Napierala 783f7b8687aSEdward Tomasz Napierala /* 784f7b8687aSEdward Tomasz Napierala * XXX: ACLs are not supported on whiteouts and device files 785f7b8687aSEdward Tomasz Napierala * residing on UFS. 786f7b8687aSEdward Tomasz Napierala */ 787f7b8687aSEdward Tomasz Napierala if (S_ISCHR(p->fts_statp->st_mode) || S_ISBLK(p->fts_statp->st_mode) || 788f7b8687aSEdward Tomasz Napierala S_ISWHT(p->fts_statp->st_mode)) 789f7b8687aSEdward Tomasz Napierala return; 790f7b8687aSEdward Tomasz Napierala 791a3429262SEdward Tomasz Napierala if (previous_dev == p->fts_statp->st_dev && supports_acls == 0) 792a3429262SEdward Tomasz Napierala return; 793f7b8687aSEdward Tomasz Napierala 794dd9aaeb0STim J. Robbins if (p->fts_level == FTS_ROOTLEVEL) 795dd9aaeb0STim J. Robbins snprintf(name, sizeof(name), "%s", p->fts_name); 796dd9aaeb0STim J. Robbins else 797dd9aaeb0STim J. Robbins snprintf(name, sizeof(name), "%s/%s", 798dd9aaeb0STim J. Robbins p->fts_parent->fts_accpath, p->fts_name); 799a3429262SEdward Tomasz Napierala 800a3429262SEdward Tomasz Napierala if (previous_dev != p->fts_statp->st_dev) { 801a3429262SEdward Tomasz Napierala previous_dev = p->fts_statp->st_dev; 802a3429262SEdward Tomasz Napierala supports_acls = 0; 803a3429262SEdward Tomasz Napierala 804f7b8687aSEdward Tomasz Napierala ret = lpathconf(name, _PC_ACL_NFS4); 805f7b8687aSEdward Tomasz Napierala if (ret > 0) { 806f7b8687aSEdward Tomasz Napierala type = ACL_TYPE_NFS4; 807f7b8687aSEdward Tomasz Napierala supports_acls = 1; 808f7b8687aSEdward Tomasz Napierala } else if (ret < 0 && errno != EINVAL) { 8090fdf7fa8SConrad Meyer warn("%s", name); 810dd9aaeb0STim J. Robbins return; 811dd9aaeb0STim J. Robbins } 812f7b8687aSEdward Tomasz Napierala if (supports_acls == 0) { 813f7b8687aSEdward Tomasz Napierala ret = lpathconf(name, _PC_ACL_EXTENDED); 814f7b8687aSEdward Tomasz Napierala if (ret > 0) { 815f7b8687aSEdward Tomasz Napierala type = ACL_TYPE_ACCESS; 816f7b8687aSEdward Tomasz Napierala supports_acls = 1; 817f7b8687aSEdward Tomasz Napierala } else if (ret < 0 && errno != EINVAL) { 8180fdf7fa8SConrad Meyer warn("%s", name); 819f7b8687aSEdward Tomasz Napierala return; 820dd9aaeb0STim J. Robbins } 821f7b8687aSEdward Tomasz Napierala } 822f7b8687aSEdward Tomasz Napierala } 823f7b8687aSEdward Tomasz Napierala if (supports_acls == 0) 824f7b8687aSEdward Tomasz Napierala return; 825f7b8687aSEdward Tomasz Napierala facl = acl_get_link_np(name, type); 826f7b8687aSEdward Tomasz Napierala if (facl == NULL) { 8270fdf7fa8SConrad Meyer warn("%s", name); 828f7b8687aSEdward Tomasz Napierala return; 829f7b8687aSEdward Tomasz Napierala } 830f7b8687aSEdward Tomasz Napierala if (acl_is_trivial_np(facl, &trivial)) { 831dd9aaeb0STim J. Robbins acl_free(facl); 8320fdf7fa8SConrad Meyer warn("%s", name); 833f7b8687aSEdward Tomasz Napierala return; 834f7b8687aSEdward Tomasz Napierala } 835f7b8687aSEdward Tomasz Napierala if (!trivial) 836f7b8687aSEdward Tomasz Napierala buf[10] = '+'; 837f7b8687aSEdward Tomasz Napierala acl_free(facl); 838dd9aaeb0STim J. Robbins } 839