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 354b88c807SRodney W. Grimes #include <sys/param.h> 364b88c807SRodney W. Grimes #include <sys/stat.h> 37dd9aaeb0STim J. Robbins #include <sys/acl.h> 384b88c807SRodney W. Grimes 394b88c807SRodney W. Grimes #include <err.h> 404b88c807SRodney W. Grimes #include <errno.h> 414b88c807SRodney W. Grimes #include <fts.h> 4228fd017aSAndrey A. Chernov #include <langinfo.h> 43478aa805SPawel Jakub Dawidek #include <libutil.h> 44be90c1c6SBaptiste Daroussin #include <limits.h> 454b88c807SRodney W. Grimes #include <stdio.h> 469f365aa1SEd Schouten #include <stdint.h> 474b88c807SRodney W. Grimes #include <stdlib.h> 484b88c807SRodney W. Grimes #include <string.h> 49434b6ea4SBruce Evans #include <time.h> 504b88c807SRodney W. Grimes #include <unistd.h> 51be90c1c6SBaptiste Daroussin #include <wchar.h> 52faebfe2eSAndrey A. Chernov #ifdef COLORLS 53faebfe2eSAndrey A. Chernov #include <ctype.h> 54faebfe2eSAndrey A. Chernov #include <termcap.h> 55faebfe2eSAndrey A. Chernov #include <signal.h> 56faebfe2eSAndrey A. Chernov #endif 574b88c807SRodney W. Grimes 584b88c807SRodney W. Grimes #include "ls.h" 594b88c807SRodney W. Grimes #include "extern.h" 604b88c807SRodney W. Grimes 6140feca3aSMark Murray static int printaname(const FTSENT *, u_long, u_long); 6255926a66SJaakko Heinonen static void printdev(size_t, dev_t); 63ca2993fbSMark Murray static void printlink(const FTSENT *); 640fdf7fa8SConrad Meyer static void printtime(time_t); 6546251ddeSWarner Losh static int printtype(u_int); 660fdf7fa8SConrad Meyer static void printsize(size_t, off_t); 6738782c25SAndrey A. Chernov #ifdef COLORLS 68e10ba800SKyle Evans static void endcolor_termcap(int); 69e10ba800SKyle Evans static void endcolor_ansi(void); 7046251ddeSWarner Losh static void endcolor(int); 7146251ddeSWarner Losh static int colortype(mode_t); 7238782c25SAndrey A. Chernov #endif 73f7b8687aSEdward Tomasz Napierala static void aclmode(char *, const FTSENT *); 744b88c807SRodney W. Grimes 754b88c807SRodney W. Grimes #define IS_NOPRINT(p) ((p)->fts_number == NO_PRINT) 760e8d1551SJosef Karthauser 7774985094SJosef Karthauser #ifdef COLORLS 783885812cSJosef Karthauser /* Most of these are taken from <sys/stat.h> */ 793885812cSJosef Karthauser typedef enum Colors { 803885812cSJosef Karthauser C_DIR, /* directory */ 813885812cSJosef Karthauser C_LNK, /* symbolic link */ 823885812cSJosef Karthauser C_SOCK, /* socket */ 833885812cSJosef Karthauser C_FIFO, /* pipe */ 843885812cSJosef Karthauser C_EXEC, /* executable */ 853885812cSJosef Karthauser C_BLK, /* block special */ 863885812cSJosef Karthauser C_CHR, /* character special */ 873885812cSJosef Karthauser C_SUID, /* setuid executable */ 883885812cSJosef Karthauser C_SGID, /* setgid executable */ 895dda5d0dSJosef Karthauser C_WSDIR, /* directory writeble to others, with sticky 905dda5d0dSJosef Karthauser * bit */ 915dda5d0dSJosef Karthauser C_WDIR, /* directory writeble to others, without 925dda5d0dSJosef Karthauser * sticky bit */ 933885812cSJosef Karthauser C_NUMCOLORS /* just a place-holder */ 943885812cSJosef Karthauser } Colors; 953885812cSJosef Karthauser 969052855aSMark Murray static const char *defcolors = "exfxcxdxbxegedabagacad"; 973885812cSJosef Karthauser 98c1499cf6SJosef Karthauser /* colors for file types */ 99c1499cf6SJosef Karthauser static struct { 100c1499cf6SJosef Karthauser int num[2]; 10197c31821SCameron Katri bool bold; 10297c31821SCameron Katri bool underline; 103c1499cf6SJosef Karthauser } colors[C_NUMCOLORS]; 10474985094SJosef Karthauser #endif 1053885812cSJosef Karthauser 106be90c1c6SBaptiste Daroussin static size_t padding_for_month[12]; 107be90c1c6SBaptiste Daroussin static size_t month_max_size = 0; 108be90c1c6SBaptiste Daroussin 1094b88c807SRodney W. Grimes void 11040feca3aSMark Murray printscol(const DISPLAY *dp) 1114b88c807SRodney W. Grimes { 1124b88c807SRodney W. Grimes FTSENT *p; 1134b88c807SRodney W. Grimes 1144b88c807SRodney W. Grimes for (p = dp->list; p; p = p->fts_link) { 1154b88c807SRodney W. Grimes if (IS_NOPRINT(p)) 1164b88c807SRodney W. Grimes continue; 1174b88c807SRodney W. Grimes (void)printaname(p, dp->s_inode, dp->s_block); 1180fdf7fa8SConrad Meyer (void)putchar('\n'); 1194b88c807SRodney W. Grimes } 1204b88c807SRodney W. Grimes } 1214b88c807SRodney W. Grimes 122ee579ffbSAssar Westerlund /* 123ee579ffbSAssar Westerlund * print name in current style 124ee579ffbSAssar Westerlund */ 1251656f850STim J. Robbins int 1260fdf7fa8SConrad Meyer printname(const char *name) 12752e4a08cSMarcel Moolenaar { 1280fdf7fa8SConrad Meyer if (f_octal || f_octal_escape) 1290fdf7fa8SConrad Meyer return prn_octal(name); 1300fdf7fa8SConrad Meyer else if (f_nonprint) 1310fdf7fa8SConrad Meyer return prn_printable(name); 1320fdf7fa8SConrad Meyer else 1330fdf7fa8SConrad Meyer return prn_normal(name); 13452e4a08cSMarcel Moolenaar } 13552e4a08cSMarcel Moolenaar 136be90c1c6SBaptiste Daroussin static const char * 137be90c1c6SBaptiste Daroussin get_abmon(int mon) 138be90c1c6SBaptiste Daroussin { 139be90c1c6SBaptiste Daroussin 140be90c1c6SBaptiste Daroussin switch (mon) { 141be90c1c6SBaptiste Daroussin case 0: return (nl_langinfo(ABMON_1)); 142be90c1c6SBaptiste Daroussin case 1: return (nl_langinfo(ABMON_2)); 143be90c1c6SBaptiste Daroussin case 2: return (nl_langinfo(ABMON_3)); 144be90c1c6SBaptiste Daroussin case 3: return (nl_langinfo(ABMON_4)); 145be90c1c6SBaptiste Daroussin case 4: return (nl_langinfo(ABMON_5)); 146be90c1c6SBaptiste Daroussin case 5: return (nl_langinfo(ABMON_6)); 147be90c1c6SBaptiste Daroussin case 6: return (nl_langinfo(ABMON_7)); 148be90c1c6SBaptiste Daroussin case 7: return (nl_langinfo(ABMON_8)); 149be90c1c6SBaptiste Daroussin case 8: return (nl_langinfo(ABMON_9)); 150be90c1c6SBaptiste Daroussin case 9: return (nl_langinfo(ABMON_10)); 151be90c1c6SBaptiste Daroussin case 10: return (nl_langinfo(ABMON_11)); 152be90c1c6SBaptiste Daroussin case 11: return (nl_langinfo(ABMON_12)); 153be90c1c6SBaptiste Daroussin } 154be90c1c6SBaptiste Daroussin 155be90c1c6SBaptiste Daroussin /* should never happen */ 156be90c1c6SBaptiste Daroussin abort(); 157be90c1c6SBaptiste Daroussin } 158be90c1c6SBaptiste Daroussin 159be90c1c6SBaptiste Daroussin static size_t 160be90c1c6SBaptiste Daroussin mbswidth(const char *month) 161be90c1c6SBaptiste Daroussin { 162be90c1c6SBaptiste Daroussin wchar_t wc; 163be90c1c6SBaptiste Daroussin size_t width, donelen, clen, w; 164be90c1c6SBaptiste Daroussin 165be90c1c6SBaptiste Daroussin width = donelen = 0; 166be90c1c6SBaptiste Daroussin while ((clen = mbrtowc(&wc, month + donelen, MB_LEN_MAX, NULL)) != 0) { 167be90c1c6SBaptiste Daroussin if (clen == (size_t)-1 || clen == (size_t)-2) 168be90c1c6SBaptiste Daroussin return (-1); 169be90c1c6SBaptiste Daroussin donelen += clen; 170be90c1c6SBaptiste Daroussin if ((w = wcwidth(wc)) == (size_t)-1) 171be90c1c6SBaptiste Daroussin return (-1); 172be90c1c6SBaptiste Daroussin width += w; 173be90c1c6SBaptiste Daroussin } 174be90c1c6SBaptiste Daroussin 175be90c1c6SBaptiste Daroussin return (width); 176be90c1c6SBaptiste Daroussin } 177be90c1c6SBaptiste Daroussin 178be90c1c6SBaptiste Daroussin static void 179be90c1c6SBaptiste Daroussin compute_abbreviated_month_size(void) 180be90c1c6SBaptiste Daroussin { 181be90c1c6SBaptiste Daroussin int i; 182be90c1c6SBaptiste Daroussin size_t width; 183be90c1c6SBaptiste Daroussin size_t months_width[12]; 184be90c1c6SBaptiste Daroussin 185be90c1c6SBaptiste Daroussin for (i = 0; i < 12; i++) { 186be90c1c6SBaptiste Daroussin width = mbswidth(get_abmon(i)); 187be90c1c6SBaptiste Daroussin if (width == (size_t)-1) { 188be90c1c6SBaptiste Daroussin month_max_size = -1; 189be90c1c6SBaptiste Daroussin return; 190be90c1c6SBaptiste Daroussin } 191be90c1c6SBaptiste Daroussin months_width[i] = width; 192be90c1c6SBaptiste Daroussin if (width > month_max_size) 193be90c1c6SBaptiste Daroussin month_max_size = width; 194be90c1c6SBaptiste Daroussin } 195be90c1c6SBaptiste Daroussin 196be90c1c6SBaptiste Daroussin for (i = 0; i < 12; i++) 197be90c1c6SBaptiste Daroussin padding_for_month[i] = month_max_size - months_width[i]; 198be90c1c6SBaptiste Daroussin } 199be90c1c6SBaptiste Daroussin 2004b88c807SRodney W. Grimes void 20140feca3aSMark Murray printlong(const DISPLAY *dp) 2024b88c807SRodney W. Grimes { 2034b88c807SRodney W. Grimes struct stat *sp; 2044b88c807SRodney W. Grimes FTSENT *p; 2054b88c807SRodney W. Grimes NAMES *np; 2064b88c807SRodney W. Grimes char buf[20]; 20747bb6b11SAndrey A. Chernov #ifdef COLORLS 20847bb6b11SAndrey A. Chernov int color_printed = 0; 20947bb6b11SAndrey A. Chernov #endif 2104b88c807SRodney W. Grimes 21148a91b69SDavid Schultz if ((dp->list == NULL || dp->list->fts_level != FTS_ROOTLEVEL) && 21248a91b69SDavid Schultz (f_longform || f_size)) { 213*82fa7f83SPiotr Pawel Stefaniak if (!f_humanval) 2140fdf7fa8SConrad Meyer (void)printf("total %lu\n", howmany(dp->btotal, blocksize)); 215*82fa7f83SPiotr Pawel Stefaniak else { 216*82fa7f83SPiotr Pawel Stefaniak (void)humanize_number(buf, 7 /* "1024 KB" */, 217*82fa7f83SPiotr Pawel Stefaniak dp->btotal * 512, "B", HN_AUTOSCALE, HN_DECIMAL); 218*82fa7f83SPiotr Pawel Stefaniak 219*82fa7f83SPiotr Pawel Stefaniak (void)printf("total %s\n", buf); 220*82fa7f83SPiotr Pawel Stefaniak } 22148a91b69SDavid Schultz } 2224b88c807SRodney W. Grimes 2234b88c807SRodney W. Grimes for (p = dp->list; p; p = p->fts_link) { 2244b88c807SRodney W. Grimes if (IS_NOPRINT(p)) 2254b88c807SRodney W. Grimes continue; 2264b88c807SRodney W. Grimes sp = p->fts_statp; 2274b88c807SRodney W. Grimes if (f_inode) 2280fdf7fa8SConrad Meyer (void)printf("%*ju ", 2296db1a7f1SMatthew D Fleming dp->s_inode, (uintmax_t)sp->st_ino); 2304b88c807SRodney W. Grimes if (f_size) 231647d4a8cSDag-Erling Smørgrav (void)printf(f_thousands ? "%'*jd " : "%*jd ", 2324b88c807SRodney W. Grimes dp->s_block, howmany(sp->st_blocks, blocksize)); 2339052855aSMark Murray strmode(sp->st_mode, buf); 234f7b8687aSEdward Tomasz Napierala aclmode(buf, p); 2354b88c807SRodney W. Grimes np = p->fts_pointer; 2363bfbb521SMinsoo Choo (void)printf("%s %*ju ", buf, dp->s_nlink, 2373bfbb521SMinsoo Choo (uintmax_t)sp->st_nlink); 2383bfbb521SMinsoo Choo if (!f_sowner) 2393bfbb521SMinsoo Choo (void)printf("%-*s ", dp->s_user, np->user); 2403bfbb521SMinsoo Choo (void)printf("%-*s ", dp->s_group, np->group); 2414b88c807SRodney W. Grimes if (f_flags) 2420fdf7fa8SConrad Meyer (void)printf("%-*s ", dp->s_flags, np->flags); 2434d33b62eSRobert Watson if (f_label) 2440fdf7fa8SConrad Meyer (void)printf("%-*s ", dp->s_label, np->label); 2454b88c807SRodney W. Grimes if (S_ISCHR(sp->st_mode) || S_ISBLK(sp->st_mode)) 24655926a66SJaakko Heinonen printdev(dp->s_size, sp->st_rdev); 2474b88c807SRodney W. Grimes else 2480fdf7fa8SConrad Meyer printsize(dp->s_size, sp->st_size); 2494b88c807SRodney W. Grimes if (f_accesstime) 2500fdf7fa8SConrad Meyer printtime(sp->st_atime); 251fe79420eSJohn Baldwin else if (f_birthtime) 2520fdf7fa8SConrad Meyer printtime(sp->st_birthtime); 2534b88c807SRodney W. Grimes else if (f_statustime) 2540fdf7fa8SConrad Meyer printtime(sp->st_ctime); 2554b88c807SRodney W. Grimes else 2560fdf7fa8SConrad Meyer printtime(sp->st_mtime); 25774985094SJosef Karthauser #ifdef COLORLS 2583885812cSJosef Karthauser if (f_color) 259cf0feaeeSAndrey A. Chernov color_printed = colortype(sp->st_mode); 26074985094SJosef Karthauser #endif 2610fdf7fa8SConrad Meyer (void)printname(p->fts_name); 26274985094SJosef Karthauser #ifdef COLORLS 263cf0feaeeSAndrey A. Chernov if (f_color && color_printed) 26438782c25SAndrey A. Chernov endcolor(0); 26574985094SJosef Karthauser #endif 2664b88c807SRodney W. Grimes if (f_type) 2674b88c807SRodney W. Grimes (void)printtype(sp->st_mode); 2684b88c807SRodney W. Grimes if (S_ISLNK(sp->st_mode)) 2694b88c807SRodney W. Grimes printlink(p); 2700fdf7fa8SConrad Meyer (void)putchar('\n'); 2714b88c807SRodney W. Grimes } 2724b88c807SRodney W. Grimes } 2734b88c807SRodney W. Grimes 2744b88c807SRodney W. Grimes void 27540feca3aSMark Murray printstream(const DISPLAY *dp) 27694274c73STim J. Robbins { 27794274c73STim J. Robbins FTSENT *p; 27894274c73STim J. Robbins int chcnt; 27994274c73STim J. Robbins 28094274c73STim J. Robbins for (p = dp->list, chcnt = 0; p; p = p->fts_link) { 28194274c73STim J. Robbins if (p->fts_number == NO_PRINT) 28294274c73STim J. Robbins continue; 283107409f4STim J. Robbins /* XXX strlen does not take octal escapes into account. */ 28494274c73STim J. Robbins if (strlen(p->fts_name) + chcnt + 28594274c73STim J. Robbins (p->fts_link ? 2 : 0) >= (unsigned)termwidth) { 2860fdf7fa8SConrad Meyer putchar('\n'); 28794274c73STim J. Robbins chcnt = 0; 28894274c73STim J. Robbins } 28994274c73STim J. Robbins chcnt += printaname(p, dp->s_inode, dp->s_block); 29094274c73STim J. Robbins if (p->fts_link) { 2910fdf7fa8SConrad Meyer printf(", "); 29294274c73STim J. Robbins chcnt += 2; 29394274c73STim J. Robbins } 29494274c73STim J. Robbins } 29594274c73STim J. Robbins if (chcnt) 2960fdf7fa8SConrad Meyer putchar('\n'); 29794274c73STim J. Robbins } 29894274c73STim J. Robbins 29994274c73STim J. Robbins void 30040feca3aSMark Murray printcol(const DISPLAY *dp) 3014b88c807SRodney W. Grimes { 3024b88c807SRodney W. Grimes static FTSENT **array; 3034b88c807SRodney W. Grimes static int lastentries = -1; 3044b88c807SRodney W. Grimes FTSENT *p; 305c5bc8709STim J. Robbins FTSENT **narray; 306b0bc91e9SJosef Karthauser int base; 307b0bc91e9SJosef Karthauser int chcnt; 308b0bc91e9SJosef Karthauser int cnt; 309b0bc91e9SJosef Karthauser int col; 310b0bc91e9SJosef Karthauser int colwidth; 311b0bc91e9SJosef Karthauser int endcol; 312b0bc91e9SJosef Karthauser int num; 313b0bc91e9SJosef Karthauser int numcols; 314b0bc91e9SJosef Karthauser int numrows; 315b0bc91e9SJosef Karthauser int row; 316545f583cSTim Vanderhoek int tabwidth; 317545f583cSTim Vanderhoek 318545f583cSTim Vanderhoek if (f_notabs) 319545f583cSTim Vanderhoek tabwidth = 1; 320545f583cSTim Vanderhoek else 321545f583cSTim Vanderhoek tabwidth = 8; 3224b88c807SRodney W. Grimes 3234b88c807SRodney W. Grimes /* 3244b88c807SRodney W. Grimes * Have to do random access in the linked list -- build a table 3254b88c807SRodney W. Grimes * of pointers. 3264b88c807SRodney W. Grimes */ 3274b88c807SRodney W. Grimes if (dp->entries > lastentries) { 328c5bc8709STim J. Robbins if ((narray = 3294b88c807SRodney W. Grimes realloc(array, dp->entries * sizeof(FTSENT *))) == NULL) { 3300fdf7fa8SConrad Meyer warn(NULL); 3314b88c807SRodney W. Grimes printscol(dp); 332c5bc8709STim J. Robbins return; 3334b88c807SRodney W. Grimes } 334c5bc8709STim J. Robbins lastentries = dp->entries; 335c5bc8709STim J. Robbins array = narray; 3364b88c807SRodney W. Grimes } 3374b88c807SRodney W. Grimes for (p = dp->list, num = 0; p; p = p->fts_link) 3384b88c807SRodney W. Grimes if (p->fts_number != NO_PRINT) 3394b88c807SRodney W. Grimes array[num++] = p; 3404b88c807SRodney W. Grimes 3414b88c807SRodney W. Grimes colwidth = dp->maxlen; 3424b88c807SRodney W. Grimes if (f_inode) 3434b88c807SRodney W. Grimes colwidth += dp->s_inode + 1; 3444b88c807SRodney W. Grimes if (f_size) 3454b88c807SRodney W. Grimes colwidth += dp->s_block + 1; 3464b88c807SRodney W. Grimes if (f_type) 3474b88c807SRodney W. Grimes colwidth += 1; 3484b88c807SRodney W. Grimes 349545f583cSTim Vanderhoek colwidth = (colwidth + tabwidth) & ~(tabwidth - 1); 3504b88c807SRodney W. Grimes if (termwidth < 2 * colwidth) { 3514b88c807SRodney W. Grimes printscol(dp); 3524b88c807SRodney W. Grimes return; 3534b88c807SRodney W. Grimes } 3544b88c807SRodney W. Grimes numcols = termwidth / colwidth; 3554b88c807SRodney W. Grimes numrows = num / numcols; 3564b88c807SRodney W. Grimes if (num % numcols) 3574b88c807SRodney W. Grimes ++numrows; 3584b88c807SRodney W. Grimes 35948a91b69SDavid Schultz if ((dp->list == NULL || dp->list->fts_level != FTS_ROOTLEVEL) && 36048a91b69SDavid Schultz (f_longform || f_size)) { 3610fdf7fa8SConrad Meyer (void)printf("total %lu\n", howmany(dp->btotal, blocksize)); 36248a91b69SDavid Schultz } 36394274c73STim J. Robbins 36494274c73STim J. Robbins base = 0; 3654b88c807SRodney W. Grimes for (row = 0; row < numrows; ++row) { 3664b88c807SRodney W. Grimes endcol = colwidth; 36794274c73STim J. Robbins if (!f_sortacross) 36894274c73STim J. Robbins base = row; 36994274c73STim J. Robbins for (col = 0, chcnt = 0; col < numcols; ++col) { 3704b88c807SRodney W. Grimes chcnt += printaname(array[base], dp->s_inode, 3714b88c807SRodney W. Grimes dp->s_block); 37294274c73STim J. Robbins if (f_sortacross) 37394274c73STim J. Robbins base++; 37494274c73STim J. Robbins else 37594274c73STim J. Robbins base += numrows; 37694274c73STim J. Robbins if (base >= num) 3774b88c807SRodney W. Grimes break; 378545f583cSTim Vanderhoek while ((cnt = ((chcnt + tabwidth) & ~(tabwidth - 1))) 379545f583cSTim Vanderhoek <= endcol) { 38094274c73STim J. Robbins if (f_sortacross && col + 1 >= numcols) 38194274c73STim J. Robbins break; 3820fdf7fa8SConrad Meyer (void)putchar(f_notabs ? ' ' : '\t'); 3834b88c807SRodney W. Grimes chcnt = cnt; 3844b88c807SRodney W. Grimes } 3854b88c807SRodney W. Grimes endcol += colwidth; 3864b88c807SRodney W. Grimes } 3870fdf7fa8SConrad Meyer (void)putchar('\n'); 3884b88c807SRodney W. Grimes } 3894b88c807SRodney W. Grimes } 3904b88c807SRodney W. Grimes 3914b88c807SRodney W. Grimes /* 3924b88c807SRodney W. Grimes * print [inode] [size] name 3934b88c807SRodney W. Grimes * return # of characters printed, no trailing characters. 3944b88c807SRodney W. Grimes */ 3954b88c807SRodney W. Grimes static int 39640feca3aSMark Murray printaname(const FTSENT *p, u_long inodefield, u_long sizefield) 3974b88c807SRodney W. Grimes { 3984b88c807SRodney W. Grimes struct stat *sp; 3994b88c807SRodney W. Grimes int chcnt; 40047bb6b11SAndrey A. Chernov #ifdef COLORLS 40147bb6b11SAndrey A. Chernov int color_printed = 0; 40247bb6b11SAndrey A. Chernov #endif 4034b88c807SRodney W. Grimes 4044b88c807SRodney W. Grimes sp = p->fts_statp; 4054b88c807SRodney W. Grimes chcnt = 0; 4064b88c807SRodney W. Grimes if (f_inode) 4070fdf7fa8SConrad Meyer chcnt += printf("%*ju ", 4086db1a7f1SMatthew D Fleming (int)inodefield, (uintmax_t)sp->st_ino); 4094b88c807SRodney W. Grimes if (f_size) 410647d4a8cSDag-Erling Smørgrav chcnt += printf(f_thousands ? "%'*jd " : "%*jd ", 4114b88c807SRodney W. Grimes (int)sizefield, howmany(sp->st_blocks, blocksize)); 41274985094SJosef Karthauser #ifdef COLORLS 4133885812cSJosef Karthauser if (f_color) 414cf0feaeeSAndrey A. Chernov color_printed = colortype(sp->st_mode); 41574985094SJosef Karthauser #endif 4160fdf7fa8SConrad Meyer chcnt += printname(p->fts_name); 41774985094SJosef Karthauser #ifdef COLORLS 418cf0feaeeSAndrey A. Chernov if (f_color && color_printed) 41938782c25SAndrey A. Chernov endcolor(0); 42074985094SJosef Karthauser #endif 4214b88c807SRodney W. Grimes if (f_type) 4224b88c807SRodney W. Grimes chcnt += printtype(sp->st_mode); 4234b88c807SRodney W. Grimes return (chcnt); 4244b88c807SRodney W. Grimes } 4254b88c807SRodney W. Grimes 42655926a66SJaakko Heinonen /* 42755926a66SJaakko Heinonen * Print device special file major and minor numbers. 42855926a66SJaakko Heinonen */ 42955926a66SJaakko Heinonen static void 43055926a66SJaakko Heinonen printdev(size_t width, dev_t dev) 43155926a66SJaakko Heinonen { 4320fdf7fa8SConrad Meyer 4330fdf7fa8SConrad Meyer (void)printf("%#*jx ", (u_int)width, (uintmax_t)dev); 43455926a66SJaakko Heinonen } 43555926a66SJaakko Heinonen 436927f8d8bSKirk McKusick static void 437be90c1c6SBaptiste Daroussin ls_strftime(char *str, size_t len, const char *fmt, const struct tm *tm) 438be90c1c6SBaptiste Daroussin { 439be90c1c6SBaptiste Daroussin char *posb, nfmt[BUFSIZ]; 440be90c1c6SBaptiste Daroussin const char *format = fmt; 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 } 446927f8d8bSKirk McKusick if (month_max_size > 0 && tm != NULL) { 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 } 456927f8d8bSKirk McKusick if (tm != NULL) 457927f8d8bSKirk McKusick strftime(str, len, format, tm); 458927f8d8bSKirk McKusick else 459927f8d8bSKirk McKusick strlcpy(str, "bad date val", len); 460be90c1c6SBaptiste Daroussin } 461be90c1c6SBaptiste Daroussin 4624b88c807SRodney W. Grimes static void 4630fdf7fa8SConrad Meyer printtime(time_t ftime) 4644b88c807SRodney W. Grimes { 465fc4a9bafSAndrey A. Chernov char longstring[80]; 46640feca3aSMark Murray static time_t now = 0; 46797e4e97bSJosef Karthauser const char *format; 4688234eb25SAndrey A. Chernov static int d_first = -1; 469f173abd0SMike Pritchard 47028fd017aSAndrey A. Chernov if (d_first < 0) 47128fd017aSAndrey A. Chernov d_first = (*nl_langinfo(D_MD_ORDER) == 'd'); 472f173abd0SMike Pritchard if (now == 0) 473f173abd0SMike Pritchard now = time(NULL); 4744b88c807SRodney W. Grimes 475656dcd43SGarrett Wollman #define SIXMONTHS ((365 / 2) * 86400) 4762269fa57SGreg Lehey if (f_timeformat) /* user specified format */ 4772269fa57SGreg Lehey format = f_timeformat; 4782269fa57SGreg Lehey else if (f_sectime) 4791e715e34SJosef Karthauser /* mmm dd hh:mm:ss yyyy || dd mmm hh:mm:ss yyyy */ 48028fd017aSAndrey A. Chernov format = d_first ? "%e %b %T %Y" : "%b %e %T %Y"; 481f173abd0SMike Pritchard else if (ftime + SIXMONTHS > now && ftime < now + SIXMONTHS) 4821e715e34SJosef Karthauser /* mmm dd hh:mm || dd mmm hh:mm */ 48328fd017aSAndrey A. Chernov format = d_first ? "%e %b %R" : "%b %e %R"; 48497e4e97bSJosef Karthauser else 4851e715e34SJosef Karthauser /* mmm dd yyyy || dd mmm yyyy */ 48628fd017aSAndrey A. Chernov format = d_first ? "%e %b %Y" : "%b %e %Y"; 487be90c1c6SBaptiste Daroussin ls_strftime(longstring, sizeof(longstring), format, localtime(&ftime)); 4880fdf7fa8SConrad Meyer fputs(longstring, stdout); 4890fdf7fa8SConrad Meyer fputc(' ', stdout); 4904b88c807SRodney W. Grimes } 4914b88c807SRodney W. Grimes 4924b88c807SRodney W. Grimes static int 49346251ddeSWarner Losh printtype(u_int mode) 4944b88c807SRodney W. Grimes { 49594274c73STim J. Robbins 49694274c73STim J. Robbins if (f_slash) { 49794274c73STim J. Robbins if ((mode & S_IFMT) == S_IFDIR) { 4980fdf7fa8SConrad Meyer (void)putchar('/'); 49994274c73STim J. Robbins return (1); 50094274c73STim J. Robbins } 50194274c73STim J. Robbins return (0); 50294274c73STim J. Robbins } 50394274c73STim J. Robbins 5044b88c807SRodney W. Grimes switch (mode & S_IFMT) { 5054b88c807SRodney W. Grimes case S_IFDIR: 5060fdf7fa8SConrad Meyer (void)putchar('/'); 5074b88c807SRodney W. Grimes return (1); 5084b88c807SRodney W. Grimes case S_IFIFO: 5090fdf7fa8SConrad Meyer (void)putchar('|'); 5104b88c807SRodney W. Grimes return (1); 5114b88c807SRodney W. Grimes case S_IFLNK: 5120fdf7fa8SConrad Meyer (void)putchar('@'); 5134b88c807SRodney W. Grimes return (1); 5144b88c807SRodney W. Grimes case S_IFSOCK: 5150fdf7fa8SConrad Meyer (void)putchar('='); 5164b88c807SRodney W. Grimes return (1); 517fb5cb208SSteve Price case S_IFWHT: 5180fdf7fa8SConrad Meyer (void)putchar('%'); 519fb5cb208SSteve Price return (1); 5209052855aSMark Murray default: 521568dcd5fSBill Fumerola break; 5224b88c807SRodney W. Grimes } 5234b88c807SRodney W. Grimes if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) { 5240fdf7fa8SConrad Meyer (void)putchar('*'); 5254b88c807SRodney W. Grimes return (1); 5264b88c807SRodney W. Grimes } 5274b88c807SRodney W. Grimes return (0); 5284b88c807SRodney W. Grimes } 5294b88c807SRodney W. Grimes 53074985094SJosef Karthauser #ifdef COLORLS 5311bf1478aSAndrey A. Chernov static int 53246251ddeSWarner Losh putch(int c) 533cf0feaeeSAndrey A. Chernov { 5340fdf7fa8SConrad Meyer (void)putchar(c); 53538782c25SAndrey A. Chernov return 0; 536cf0feaeeSAndrey A. Chernov } 537cf0feaeeSAndrey A. Chernov 5381bf1478aSAndrey A. Chernov static int 53946251ddeSWarner Losh writech(int c) 54038782c25SAndrey A. Chernov { 54140feca3aSMark Murray char tmp = (char)c; 54238782c25SAndrey A. Chernov 54338782c25SAndrey A. Chernov (void)write(STDOUT_FILENO, &tmp, 1); 54438782c25SAndrey A. Chernov return 0; 54538782c25SAndrey A. Chernov } 546cf0feaeeSAndrey A. Chernov 5471bf1478aSAndrey A. Chernov static void 548e10ba800SKyle Evans printcolor_termcap(Colors c) 5493885812cSJosef Karthauser { 55074985094SJosef Karthauser char *ansiseq; 55174985094SJosef Karthauser 552c1499cf6SJosef Karthauser if (colors[c].bold) 553c1499cf6SJosef Karthauser tputs(enter_bold, 1, putch); 55497c31821SCameron Katri if (colors[c].underline) 55597c31821SCameron Katri tputs(enter_underline, 1, putch); 556c1499cf6SJosef Karthauser 557c1499cf6SJosef Karthauser if (colors[c].num[0] != -1) { 558c1499cf6SJosef Karthauser ansiseq = tgoto(ansi_fgcol, 0, colors[c].num[0]); 55938782c25SAndrey A. Chernov if (ansiseq) 560cf0feaeeSAndrey A. Chernov tputs(ansiseq, 1, putch); 5613885812cSJosef Karthauser } 562c1499cf6SJosef Karthauser if (colors[c].num[1] != -1) { 563c1499cf6SJosef Karthauser ansiseq = tgoto(ansi_bgcol, 0, colors[c].num[1]); 56438782c25SAndrey A. Chernov if (ansiseq) 565cf0feaeeSAndrey A. Chernov tputs(ansiseq, 1, putch); 56674985094SJosef Karthauser } 56774985094SJosef Karthauser } 56874985094SJosef Karthauser 56938782c25SAndrey A. Chernov static void 570e10ba800SKyle Evans printcolor_ansi(Colors c) 57174985094SJosef Karthauser { 572e10ba800SKyle Evans 573e10ba800SKyle Evans printf("\033["); 574e10ba800SKyle Evans 575e10ba800SKyle Evans if (colors[c].bold) 576e10ba800SKyle Evans printf("1"); 57797c31821SCameron Katri if (colors[c].underline) 57897c31821SCameron Katri printf(";4"); 579e10ba800SKyle Evans if (colors[c].num[0] != -1) 580e10ba800SKyle Evans printf(";3%d", colors[c].num[0]); 581e10ba800SKyle Evans if (colors[c].num[1] != -1) 582e10ba800SKyle Evans printf(";4%d", colors[c].num[1]); 583e10ba800SKyle Evans printf("m"); 584e10ba800SKyle Evans } 585e10ba800SKyle Evans 586e10ba800SKyle Evans static void 587e10ba800SKyle Evans printcolor(Colors c) 588e10ba800SKyle Evans { 589e10ba800SKyle Evans 590e10ba800SKyle Evans if (explicitansi) 591e10ba800SKyle Evans printcolor_ansi(c); 592e10ba800SKyle Evans else 593e10ba800SKyle Evans printcolor_termcap(c); 594e10ba800SKyle Evans } 595e10ba800SKyle Evans 596e10ba800SKyle Evans static void 597e10ba800SKyle Evans endcolor_termcap(int sig) 598e10ba800SKyle Evans { 599e10ba800SKyle Evans 60038782c25SAndrey A. Chernov tputs(ansi_coloff, 1, sig ? writech : putch); 601c1499cf6SJosef Karthauser tputs(attrs_off, 1, sig ? writech : putch); 6023885812cSJosef Karthauser } 6033885812cSJosef Karthauser 604e10ba800SKyle Evans static void 605e10ba800SKyle Evans endcolor_ansi(void) 606e10ba800SKyle Evans { 607e10ba800SKyle Evans 608e10ba800SKyle Evans printf("\33[m"); 609e10ba800SKyle Evans } 610e10ba800SKyle Evans 611e10ba800SKyle Evans static void 612e10ba800SKyle Evans endcolor(int sig) 613e10ba800SKyle Evans { 614e10ba800SKyle Evans 615e10ba800SKyle Evans if (explicitansi) 616e10ba800SKyle Evans endcolor_ansi(); 617e10ba800SKyle Evans else 618e10ba800SKyle Evans endcolor_termcap(sig); 619e10ba800SKyle Evans } 620e10ba800SKyle Evans 62138782c25SAndrey A. Chernov static int 62246251ddeSWarner Losh colortype(mode_t mode) 6233885812cSJosef Karthauser { 6243885812cSJosef Karthauser switch (mode & S_IFMT) { 6253885812cSJosef Karthauser case S_IFDIR: 6263885812cSJosef Karthauser if (mode & S_IWOTH) 6273885812cSJosef Karthauser if (mode & S_ISTXT) 6283885812cSJosef Karthauser printcolor(C_WSDIR); 6293885812cSJosef Karthauser else 6303885812cSJosef Karthauser printcolor(C_WDIR); 6313885812cSJosef Karthauser else 6323885812cSJosef Karthauser printcolor(C_DIR); 6333885812cSJosef Karthauser return (1); 6343885812cSJosef Karthauser case S_IFLNK: 6353885812cSJosef Karthauser printcolor(C_LNK); 6363885812cSJosef Karthauser return (1); 6373885812cSJosef Karthauser case S_IFSOCK: 6383885812cSJosef Karthauser printcolor(C_SOCK); 6393885812cSJosef Karthauser return (1); 6403885812cSJosef Karthauser case S_IFIFO: 6413885812cSJosef Karthauser printcolor(C_FIFO); 6423885812cSJosef Karthauser return (1); 6433885812cSJosef Karthauser case S_IFBLK: 6443885812cSJosef Karthauser printcolor(C_BLK); 6453885812cSJosef Karthauser return (1); 6463885812cSJosef Karthauser case S_IFCHR: 6473885812cSJosef Karthauser printcolor(C_CHR); 6483885812cSJosef Karthauser return (1); 64940feca3aSMark Murray default:; 6503885812cSJosef Karthauser } 6513885812cSJosef Karthauser if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) { 6523885812cSJosef Karthauser if (mode & S_ISUID) 6533885812cSJosef Karthauser printcolor(C_SUID); 6543885812cSJosef Karthauser else if (mode & S_ISGID) 6553885812cSJosef Karthauser printcolor(C_SGID); 6563885812cSJosef Karthauser else 6573885812cSJosef Karthauser printcolor(C_EXEC); 6583885812cSJosef Karthauser return (1); 6593885812cSJosef Karthauser } 6603885812cSJosef Karthauser return (0); 6613885812cSJosef Karthauser } 6623885812cSJosef Karthauser 6633885812cSJosef Karthauser void 66446251ddeSWarner Losh parsecolors(const char *cs) 6653885812cSJosef Karthauser { 666b0bc91e9SJosef Karthauser int i; 667b0bc91e9SJosef Karthauser int j; 668ca2993fbSMark Murray size_t len; 6693885812cSJosef Karthauser char c[2]; 670c1499cf6SJosef Karthauser short legacy_warn = 0; 67138782c25SAndrey A. Chernov 672b0bc91e9SJosef Karthauser if (cs == NULL) 673b0bc91e9SJosef Karthauser cs = ""; /* LSCOLORS not set */ 6743885812cSJosef Karthauser len = strlen(cs); 67540feca3aSMark Murray for (i = 0; i < (int)C_NUMCOLORS; i++) { 67697c31821SCameron Katri colors[i].bold = false; 67797c31821SCameron Katri colors[i].underline = false; 678c1499cf6SJosef Karthauser 67940feca3aSMark Murray if (len <= 2 * (size_t)i) { 6803885812cSJosef Karthauser c[0] = defcolors[2 * i]; 6813885812cSJosef Karthauser c[1] = defcolors[2 * i + 1]; 6825dda5d0dSJosef Karthauser } else { 6833885812cSJosef Karthauser c[0] = cs[2 * i]; 6843885812cSJosef Karthauser c[1] = cs[2 * i + 1]; 6853885812cSJosef Karthauser } 6863885812cSJosef Karthauser for (j = 0; j < 2; j++) { 687c1499cf6SJosef Karthauser /* Legacy colours used 0-7 */ 688c1499cf6SJosef Karthauser if (c[j] >= '0' && c[j] <= '7') { 689c1499cf6SJosef Karthauser colors[i].num[j] = c[j] - '0'; 690c1499cf6SJosef Karthauser if (!legacy_warn) { 6910fdf7fa8SConrad Meyer warnx("LSCOLORS should use " 692130d15dcSJosef Karthauser "characters a-h instead of 0-9 (" 693e09fdabdSTim J. Robbins "see the manual page)"); 6943885812cSJosef Karthauser } 695c1499cf6SJosef Karthauser legacy_warn = 1; 696c1499cf6SJosef Karthauser } else if (c[j] >= 'a' && c[j] <= 'h') 697c1499cf6SJosef Karthauser colors[i].num[j] = c[j] - 'a'; 698c1499cf6SJosef Karthauser else if (c[j] >= 'A' && c[j] <= 'H') { 699c1499cf6SJosef Karthauser colors[i].num[j] = c[j] - 'A'; 70097c31821SCameron Katri if (j == 1) 70197c31821SCameron Katri colors[i].underline = true; 70297c31821SCameron Katri else 70397c31821SCameron Katri colors[i].bold = true; 70497c31821SCameron Katri } else if (tolower((unsigned char)c[j]) == 'x') { 70597c31821SCameron Katri if (j == 1 && c[j] == 'X') 70697c31821SCameron Katri colors[i].underline = true; 707c1499cf6SJosef Karthauser colors[i].num[j] = -1; 70897c31821SCameron Katri } else { 7090fdf7fa8SConrad Meyer warnx("invalid character '%c' in LSCOLORS" 710e09fdabdSTim J. Robbins " env var", c[j]); 7110d72516eSJosef Karthauser colors[i].num[j] = -1; 712c1499cf6SJosef Karthauser } 7133885812cSJosef Karthauser } 7143885812cSJosef Karthauser } 7153885812cSJosef Karthauser } 716cf0feaeeSAndrey A. Chernov 7171bf1478aSAndrey A. Chernov void 71846251ddeSWarner Losh colorquit(int sig) 719cf0feaeeSAndrey A. Chernov { 72038782c25SAndrey A. Chernov endcolor(sig); 721faebfe2eSAndrey A. Chernov 722faebfe2eSAndrey A. Chernov (void)signal(sig, SIG_DFL); 723faebfe2eSAndrey A. Chernov (void)kill(getpid(), sig); 724cf0feaeeSAndrey A. Chernov } 7255dda5d0dSJosef Karthauser 72674985094SJosef Karthauser #endif /* COLORLS */ 7273885812cSJosef Karthauser 7284b88c807SRodney W. Grimes static void 729ca2993fbSMark Murray printlink(const FTSENT *p) 7304b88c807SRodney W. Grimes { 7314b88c807SRodney W. Grimes int lnklen; 732b0bc91e9SJosef Karthauser char name[MAXPATHLEN + 1]; 733b0bc91e9SJosef Karthauser char path[MAXPATHLEN + 1]; 7344b88c807SRodney W. Grimes 7354b88c807SRodney W. Grimes if (p->fts_level == FTS_ROOTLEVEL) 7364b88c807SRodney W. Grimes (void)snprintf(name, sizeof(name), "%s", p->fts_name); 7374b88c807SRodney W. Grimes else 7384b88c807SRodney W. Grimes (void)snprintf(name, sizeof(name), 7394b88c807SRodney W. Grimes "%s/%s", p->fts_parent->fts_accpath, p->fts_name); 7404b88c807SRodney W. Grimes if ((lnklen = readlink(name, path, sizeof(path) - 1)) == -1) { 7410fdf7fa8SConrad Meyer (void)fprintf(stderr, "\nls: %s: %s\n", name, strerror(errno)); 7424b88c807SRodney W. Grimes return; 7434b88c807SRodney W. Grimes } 7444b88c807SRodney W. Grimes path[lnklen] = '\0'; 7450fdf7fa8SConrad Meyer (void)printf(" -> "); 7460fdf7fa8SConrad Meyer (void)printname(path); 7474b88c807SRodney W. Grimes } 7480e8d1551SJosef Karthauser 7490e8d1551SJosef Karthauser static void 7500fdf7fa8SConrad Meyer printsize(size_t width, off_t bytes) 7510e8d1551SJosef Karthauser { 7520e8d1551SJosef Karthauser 7530e8d1551SJosef Karthauser if (f_humanval) { 75455926a66SJaakko Heinonen /* 75555926a66SJaakko Heinonen * Reserve one space before the size and allocate room for 75655926a66SJaakko Heinonen * the trailing '\0'. 75755926a66SJaakko Heinonen */ 75855926a66SJaakko Heinonen char buf[HUMANVALSTR_LEN - 1 + 1]; 7590e8d1551SJosef Karthauser 760478aa805SPawel Jakub Dawidek humanize_number(buf, sizeof(buf), (int64_t)bytes, "", 761478aa805SPawel Jakub Dawidek HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL); 7620fdf7fa8SConrad Meyer (void)printf("%*s ", (u_int)width, buf); 763647d4a8cSDag-Erling Smørgrav } else { 764647d4a8cSDag-Erling Smørgrav (void)printf(f_thousands ? "%'*jd " : "%*jd ", 765647d4a8cSDag-Erling Smørgrav (u_int)width, bytes); 766647d4a8cSDag-Erling Smørgrav } 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