19ddb49cbSWarner Losh /*- 2*8a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 3*8a16b7a1SPedro 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 6552e4a08cSMarcel Moolenaar #include <libxo/xo.h> 664b88c807SRodney W. Grimes 674b88c807SRodney W. Grimes #include "ls.h" 684b88c807SRodney W. Grimes #include "extern.h" 694b88c807SRodney W. Grimes 7040feca3aSMark Murray static int printaname(const FTSENT *, u_long, u_long); 7155926a66SJaakko Heinonen static void printdev(size_t, dev_t); 72ca2993fbSMark Murray static void printlink(const FTSENT *); 7352e4a08cSMarcel Moolenaar static void printtime(const char *, time_t); 7446251ddeSWarner Losh static int printtype(u_int); 7552e4a08cSMarcel Moolenaar static void printsize(const char *, size_t, off_t); 7638782c25SAndrey A. Chernov #ifdef COLORLS 7746251ddeSWarner Losh static void endcolor(int); 7846251ddeSWarner Losh static int colortype(mode_t); 7938782c25SAndrey A. Chernov #endif 80f7b8687aSEdward Tomasz Napierala static void aclmode(char *, const FTSENT *); 814b88c807SRodney W. Grimes 824b88c807SRodney W. Grimes #define IS_NOPRINT(p) ((p)->fts_number == NO_PRINT) 830e8d1551SJosef Karthauser 8474985094SJosef Karthauser #ifdef COLORLS 853885812cSJosef Karthauser /* Most of these are taken from <sys/stat.h> */ 863885812cSJosef Karthauser typedef enum Colors { 873885812cSJosef Karthauser C_DIR, /* directory */ 883885812cSJosef Karthauser C_LNK, /* symbolic link */ 893885812cSJosef Karthauser C_SOCK, /* socket */ 903885812cSJosef Karthauser C_FIFO, /* pipe */ 913885812cSJosef Karthauser C_EXEC, /* executable */ 923885812cSJosef Karthauser C_BLK, /* block special */ 933885812cSJosef Karthauser C_CHR, /* character special */ 943885812cSJosef Karthauser C_SUID, /* setuid executable */ 953885812cSJosef Karthauser C_SGID, /* setgid executable */ 965dda5d0dSJosef Karthauser C_WSDIR, /* directory writeble to others, with sticky 975dda5d0dSJosef Karthauser * bit */ 985dda5d0dSJosef Karthauser C_WDIR, /* directory writeble to others, without 995dda5d0dSJosef Karthauser * sticky bit */ 1003885812cSJosef Karthauser C_NUMCOLORS /* just a place-holder */ 1013885812cSJosef Karthauser } Colors; 1023885812cSJosef Karthauser 1039052855aSMark Murray static const char *defcolors = "exfxcxdxbxegedabagacad"; 1043885812cSJosef Karthauser 105c1499cf6SJosef Karthauser /* colors for file types */ 106c1499cf6SJosef Karthauser static struct { 107c1499cf6SJosef Karthauser int num[2]; 108c1499cf6SJosef Karthauser int bold; 109c1499cf6SJosef Karthauser } colors[C_NUMCOLORS]; 11074985094SJosef Karthauser #endif 1113885812cSJosef Karthauser 112be90c1c6SBaptiste Daroussin static size_t padding_for_month[12]; 113be90c1c6SBaptiste Daroussin static size_t month_max_size = 0; 114be90c1c6SBaptiste Daroussin 1154b88c807SRodney W. Grimes void 11640feca3aSMark Murray printscol(const DISPLAY *dp) 1174b88c807SRodney W. Grimes { 1184b88c807SRodney W. Grimes FTSENT *p; 1194b88c807SRodney W. Grimes 12052e4a08cSMarcel Moolenaar xo_open_list("entry"); 1214b88c807SRodney W. Grimes for (p = dp->list; p; p = p->fts_link) { 1224b88c807SRodney W. Grimes if (IS_NOPRINT(p)) 1234b88c807SRodney W. Grimes continue; 12452e4a08cSMarcel Moolenaar xo_open_instance("entry"); 1254b88c807SRodney W. Grimes (void)printaname(p, dp->s_inode, dp->s_block); 12652e4a08cSMarcel Moolenaar xo_close_instance("entry"); 12752e4a08cSMarcel Moolenaar xo_emit("\n"); 1284b88c807SRodney W. Grimes } 12952e4a08cSMarcel Moolenaar xo_close_list("entry"); 1304b88c807SRodney W. Grimes } 1314b88c807SRodney W. Grimes 132ee579ffbSAssar Westerlund /* 133ee579ffbSAssar Westerlund * print name in current style 134ee579ffbSAssar Westerlund */ 1351656f850STim J. Robbins int 13652e4a08cSMarcel Moolenaar printname(const char *field, const char *name) 13752e4a08cSMarcel Moolenaar { 13852e4a08cSMarcel Moolenaar char fmt[BUFSIZ]; 13952e4a08cSMarcel Moolenaar char *s = getname(name); 14052e4a08cSMarcel Moolenaar int rc; 14152e4a08cSMarcel Moolenaar 14252e4a08cSMarcel Moolenaar snprintf(fmt, sizeof(fmt), "{:%s/%%hs}", field); 14352e4a08cSMarcel Moolenaar rc = xo_emit(fmt, s); 14452e4a08cSMarcel Moolenaar free(s); 14552e4a08cSMarcel Moolenaar return rc; 14652e4a08cSMarcel Moolenaar } 14752e4a08cSMarcel Moolenaar 148be90c1c6SBaptiste Daroussin static const char * 149be90c1c6SBaptiste Daroussin get_abmon(int mon) 150be90c1c6SBaptiste Daroussin { 151be90c1c6SBaptiste Daroussin 152be90c1c6SBaptiste Daroussin switch (mon) { 153be90c1c6SBaptiste Daroussin case 0: return (nl_langinfo(ABMON_1)); 154be90c1c6SBaptiste Daroussin case 1: return (nl_langinfo(ABMON_2)); 155be90c1c6SBaptiste Daroussin case 2: return (nl_langinfo(ABMON_3)); 156be90c1c6SBaptiste Daroussin case 3: return (nl_langinfo(ABMON_4)); 157be90c1c6SBaptiste Daroussin case 4: return (nl_langinfo(ABMON_5)); 158be90c1c6SBaptiste Daroussin case 5: return (nl_langinfo(ABMON_6)); 159be90c1c6SBaptiste Daroussin case 6: return (nl_langinfo(ABMON_7)); 160be90c1c6SBaptiste Daroussin case 7: return (nl_langinfo(ABMON_8)); 161be90c1c6SBaptiste Daroussin case 8: return (nl_langinfo(ABMON_9)); 162be90c1c6SBaptiste Daroussin case 9: return (nl_langinfo(ABMON_10)); 163be90c1c6SBaptiste Daroussin case 10: return (nl_langinfo(ABMON_11)); 164be90c1c6SBaptiste Daroussin case 11: return (nl_langinfo(ABMON_12)); 165be90c1c6SBaptiste Daroussin } 166be90c1c6SBaptiste Daroussin 167be90c1c6SBaptiste Daroussin /* should never happen */ 168be90c1c6SBaptiste Daroussin abort(); 169be90c1c6SBaptiste Daroussin } 170be90c1c6SBaptiste Daroussin 171be90c1c6SBaptiste Daroussin static size_t 172be90c1c6SBaptiste Daroussin mbswidth(const char *month) 173be90c1c6SBaptiste Daroussin { 174be90c1c6SBaptiste Daroussin wchar_t wc; 175be90c1c6SBaptiste Daroussin size_t width, donelen, clen, w; 176be90c1c6SBaptiste Daroussin 177be90c1c6SBaptiste Daroussin width = donelen = 0; 178be90c1c6SBaptiste Daroussin while ((clen = mbrtowc(&wc, month + donelen, MB_LEN_MAX, NULL)) != 0) { 179be90c1c6SBaptiste Daroussin if (clen == (size_t)-1 || clen == (size_t)-2) 180be90c1c6SBaptiste Daroussin return (-1); 181be90c1c6SBaptiste Daroussin donelen += clen; 182be90c1c6SBaptiste Daroussin if ((w = wcwidth(wc)) == (size_t)-1) 183be90c1c6SBaptiste Daroussin return (-1); 184be90c1c6SBaptiste Daroussin width += w; 185be90c1c6SBaptiste Daroussin } 186be90c1c6SBaptiste Daroussin 187be90c1c6SBaptiste Daroussin return (width); 188be90c1c6SBaptiste Daroussin } 189be90c1c6SBaptiste Daroussin 190be90c1c6SBaptiste Daroussin static void 191be90c1c6SBaptiste Daroussin compute_abbreviated_month_size(void) 192be90c1c6SBaptiste Daroussin { 193be90c1c6SBaptiste Daroussin int i; 194be90c1c6SBaptiste Daroussin size_t width; 195be90c1c6SBaptiste Daroussin size_t months_width[12]; 196be90c1c6SBaptiste Daroussin 197be90c1c6SBaptiste Daroussin for (i = 0; i < 12; i++) { 198be90c1c6SBaptiste Daroussin width = mbswidth(get_abmon(i)); 199be90c1c6SBaptiste Daroussin if (width == (size_t)-1) { 200be90c1c6SBaptiste Daroussin month_max_size = -1; 201be90c1c6SBaptiste Daroussin return; 202be90c1c6SBaptiste Daroussin } 203be90c1c6SBaptiste Daroussin months_width[i] = width; 204be90c1c6SBaptiste Daroussin if (width > month_max_size) 205be90c1c6SBaptiste Daroussin month_max_size = width; 206be90c1c6SBaptiste Daroussin } 207be90c1c6SBaptiste Daroussin 208be90c1c6SBaptiste Daroussin for (i = 0; i < 12; i++) 209be90c1c6SBaptiste Daroussin padding_for_month[i] = month_max_size - months_width[i]; 210be90c1c6SBaptiste Daroussin } 211be90c1c6SBaptiste Daroussin 21252e4a08cSMarcel Moolenaar /* 21352e4a08cSMarcel Moolenaar * print name in current style 21452e4a08cSMarcel Moolenaar */ 21552e4a08cSMarcel Moolenaar char * 21652e4a08cSMarcel Moolenaar getname(const char *name) 217ee579ffbSAssar Westerlund { 218ee579ffbSAssar Westerlund if (f_octal || f_octal_escape) 21952e4a08cSMarcel Moolenaar return get_octal(name); 220ee579ffbSAssar Westerlund else if (f_nonprint) 22152e4a08cSMarcel Moolenaar return get_printable(name); 222ee579ffbSAssar Westerlund else 22352e4a08cSMarcel Moolenaar return strdup(name); 224ee579ffbSAssar Westerlund } 225ee579ffbSAssar Westerlund 2264b88c807SRodney W. Grimes void 22740feca3aSMark Murray printlong(const DISPLAY *dp) 2284b88c807SRodney W. Grimes { 2294b88c807SRodney W. Grimes struct stat *sp; 2304b88c807SRodney W. Grimes FTSENT *p; 2314b88c807SRodney W. Grimes NAMES *np; 2324b88c807SRodney W. Grimes char buf[20]; 23347bb6b11SAndrey A. Chernov #ifdef COLORLS 23447bb6b11SAndrey A. Chernov int color_printed = 0; 23547bb6b11SAndrey A. Chernov #endif 2364b88c807SRodney W. Grimes 23748a91b69SDavid Schultz if ((dp->list == NULL || dp->list->fts_level != FTS_ROOTLEVEL) && 23848a91b69SDavid Schultz (f_longform || f_size)) { 23952e4a08cSMarcel Moolenaar xo_emit("{L:total} {:total-blocks/%lu}\n", 24052e4a08cSMarcel Moolenaar howmany(dp->btotal, blocksize)); 24148a91b69SDavid Schultz } 2424b88c807SRodney W. Grimes 24352e4a08cSMarcel Moolenaar xo_open_list("entry"); 2444b88c807SRodney W. Grimes for (p = dp->list; p; p = p->fts_link) { 245e5542be4SAllan Jude char *name, *type; 2464b88c807SRodney W. Grimes if (IS_NOPRINT(p)) 2474b88c807SRodney W. Grimes continue; 24852e4a08cSMarcel Moolenaar xo_open_instance("entry"); 2494b88c807SRodney W. Grimes sp = p->fts_statp; 25052e4a08cSMarcel Moolenaar name = getname(p->fts_name); 25152e4a08cSMarcel Moolenaar if (name) 2520d5beab5SAlexander Kabaev xo_emit("{ke:name/%hs}", name); 2534b88c807SRodney W. Grimes if (f_inode) 254e5542be4SAllan Jude xo_emit("{t:inode/%*ju} ", 2556db1a7f1SMatthew D Fleming dp->s_inode, (uintmax_t)sp->st_ino); 2564b88c807SRodney W. Grimes if (f_size) 257e5542be4SAllan Jude xo_emit("{t:blocks/%*jd} ", 2584b88c807SRodney W. Grimes dp->s_block, howmany(sp->st_blocks, blocksize)); 2599052855aSMark Murray strmode(sp->st_mode, buf); 260f7b8687aSEdward Tomasz Napierala aclmode(buf, p); 2614b88c807SRodney W. Grimes np = p->fts_pointer; 26252e4a08cSMarcel Moolenaar xo_attr("value", "%03o", (int) sp->st_mode & ALLPERMS); 263e5542be4SAllan Jude if (f_numericonly) { 264cdf44896SKonstantin Belousov xo_emit("{t:mode/%s}{e:mode_octal/%03o} {t:links/%*ju} {td:user/%-*s}{e:user/%ju} {td:group/%-*s}{e:group/%ju} ", 265cdf44896SKonstantin Belousov buf, (int) sp->st_mode & ALLPERMS, dp->s_nlink, (uintmax_t)sp->st_nlink, 266e9eed90cSAllan Jude dp->s_user, np->user, (uintmax_t)sp->st_uid, dp->s_group, np->group, (uintmax_t)sp->st_gid); 267e5542be4SAllan Jude } else { 268cdf44896SKonstantin Belousov xo_emit("{t:mode/%s}{e:mode_octal/%03o} {t:links/%*ju} {t:user/%-*s} {t:group/%-*s} ", 269cdf44896SKonstantin Belousov buf, (int) sp->st_mode & ALLPERMS, dp->s_nlink, (uintmax_t)sp->st_nlink, 27052e4a08cSMarcel Moolenaar dp->s_user, np->user, dp->s_group, np->group); 271e5542be4SAllan Jude } 272e5542be4SAllan Jude if (S_ISBLK(sp->st_mode)) 273e5542be4SAllan Jude asprintf(&type, "block"); 274e5542be4SAllan Jude if (S_ISCHR(sp->st_mode)) 275e5542be4SAllan Jude asprintf(&type, "character"); 276e5542be4SAllan Jude if (S_ISDIR(sp->st_mode)) 277e5542be4SAllan Jude asprintf(&type, "directory"); 278e5542be4SAllan Jude if (S_ISFIFO(sp->st_mode)) 279e5542be4SAllan Jude asprintf(&type, "fifo"); 280e5542be4SAllan Jude if (S_ISLNK(sp->st_mode)) 281e5542be4SAllan Jude asprintf(&type, "symlink"); 282e5542be4SAllan Jude if (S_ISREG(sp->st_mode)) 283e5542be4SAllan Jude asprintf(&type, "regular"); 284e5542be4SAllan Jude if (S_ISSOCK(sp->st_mode)) 285e5542be4SAllan Jude asprintf(&type, "socket"); 286e5542be4SAllan Jude if (S_ISWHT(sp->st_mode)) 287e5542be4SAllan Jude asprintf(&type, "whiteout"); 288e5542be4SAllan Jude xo_emit("{e:type/%s}", type); 289e5542be4SAllan Jude free(type); 2904b88c807SRodney W. Grimes if (f_flags) 29152e4a08cSMarcel Moolenaar xo_emit("{:flags/%-*s} ", dp->s_flags, np->flags); 2924d33b62eSRobert Watson if (f_label) 293e5542be4SAllan Jude xo_emit("{t:label/%-*s} ", dp->s_label, np->label); 2944b88c807SRodney W. Grimes if (S_ISCHR(sp->st_mode) || S_ISBLK(sp->st_mode)) 29555926a66SJaakko Heinonen printdev(dp->s_size, sp->st_rdev); 2964b88c807SRodney W. Grimes else 29752e4a08cSMarcel Moolenaar printsize("size", dp->s_size, sp->st_size); 2984b88c807SRodney W. Grimes if (f_accesstime) 29952e4a08cSMarcel Moolenaar printtime("access-time", sp->st_atime); 300fe79420eSJohn Baldwin else if (f_birthtime) 30152e4a08cSMarcel Moolenaar printtime("birth-time", sp->st_birthtime); 3024b88c807SRodney W. Grimes else if (f_statustime) 30352e4a08cSMarcel Moolenaar printtime("change-time", sp->st_ctime); 3044b88c807SRodney W. Grimes else 30552e4a08cSMarcel Moolenaar printtime("modify-time", sp->st_mtime); 30674985094SJosef Karthauser #ifdef COLORLS 3073885812cSJosef Karthauser if (f_color) 308cf0feaeeSAndrey A. Chernov color_printed = colortype(sp->st_mode); 30974985094SJosef Karthauser #endif 31052e4a08cSMarcel Moolenaar 31152e4a08cSMarcel Moolenaar if (name) { 3120d5beab5SAlexander Kabaev xo_emit("{dk:name/%hs}", name); 31352e4a08cSMarcel Moolenaar free(name); 31452e4a08cSMarcel Moolenaar } 31552e4a08cSMarcel Moolenaar 31674985094SJosef Karthauser #ifdef COLORLS 317cf0feaeeSAndrey A. Chernov if (f_color && color_printed) 31838782c25SAndrey A. Chernov endcolor(0); 31974985094SJosef Karthauser #endif 3204b88c807SRodney W. Grimes if (f_type) 3214b88c807SRodney W. Grimes (void)printtype(sp->st_mode); 3224b88c807SRodney W. Grimes if (S_ISLNK(sp->st_mode)) 3234b88c807SRodney W. Grimes printlink(p); 32452e4a08cSMarcel Moolenaar xo_close_instance("entry"); 32552e4a08cSMarcel Moolenaar xo_emit("\n"); 3264b88c807SRodney W. Grimes } 32752e4a08cSMarcel Moolenaar xo_close_list("entry"); 3284b88c807SRodney W. Grimes } 3294b88c807SRodney W. Grimes 3304b88c807SRodney W. Grimes void 33140feca3aSMark Murray printstream(const DISPLAY *dp) 33294274c73STim J. Robbins { 33394274c73STim J. Robbins FTSENT *p; 33494274c73STim J. Robbins int chcnt; 33594274c73STim J. Robbins 336e5542be4SAllan Jude xo_open_list("entry"); 33794274c73STim J. Robbins for (p = dp->list, chcnt = 0; p; p = p->fts_link) { 33894274c73STim J. Robbins if (p->fts_number == NO_PRINT) 33994274c73STim J. Robbins continue; 340107409f4STim J. Robbins /* XXX strlen does not take octal escapes into account. */ 34194274c73STim J. Robbins if (strlen(p->fts_name) + chcnt + 34294274c73STim J. Robbins (p->fts_link ? 2 : 0) >= (unsigned)termwidth) { 34352e4a08cSMarcel Moolenaar xo_emit("\n"); 34494274c73STim J. Robbins chcnt = 0; 34594274c73STim J. Robbins } 346e5542be4SAllan Jude xo_open_instance("file"); 34794274c73STim J. Robbins chcnt += printaname(p, dp->s_inode, dp->s_block); 348e5542be4SAllan Jude xo_close_instance("file"); 34994274c73STim J. Robbins if (p->fts_link) { 35052e4a08cSMarcel Moolenaar xo_emit(", "); 35194274c73STim J. Robbins chcnt += 2; 35294274c73STim J. Robbins } 35394274c73STim J. Robbins } 354e5542be4SAllan Jude xo_close_list("entry"); 35594274c73STim J. Robbins if (chcnt) 35652e4a08cSMarcel Moolenaar xo_emit("\n"); 35794274c73STim J. Robbins } 35894274c73STim J. Robbins 35994274c73STim J. Robbins void 36040feca3aSMark Murray printcol(const DISPLAY *dp) 3614b88c807SRodney W. Grimes { 3624b88c807SRodney W. Grimes static FTSENT **array; 3634b88c807SRodney W. Grimes static int lastentries = -1; 3644b88c807SRodney W. Grimes FTSENT *p; 365c5bc8709STim J. Robbins FTSENT **narray; 366b0bc91e9SJosef Karthauser int base; 367b0bc91e9SJosef Karthauser int chcnt; 368b0bc91e9SJosef Karthauser int cnt; 369b0bc91e9SJosef Karthauser int col; 370b0bc91e9SJosef Karthauser int colwidth; 371b0bc91e9SJosef Karthauser int endcol; 372b0bc91e9SJosef Karthauser int num; 373b0bc91e9SJosef Karthauser int numcols; 374b0bc91e9SJosef Karthauser int numrows; 375b0bc91e9SJosef Karthauser int row; 376545f583cSTim Vanderhoek int tabwidth; 377545f583cSTim Vanderhoek 378545f583cSTim Vanderhoek if (f_notabs) 379545f583cSTim Vanderhoek tabwidth = 1; 380545f583cSTim Vanderhoek else 381545f583cSTim Vanderhoek tabwidth = 8; 3824b88c807SRodney W. Grimes 3834b88c807SRodney W. Grimes /* 3844b88c807SRodney W. Grimes * Have to do random access in the linked list -- build a table 3854b88c807SRodney W. Grimes * of pointers. 3864b88c807SRodney W. Grimes */ 3874b88c807SRodney W. Grimes if (dp->entries > lastentries) { 388c5bc8709STim J. Robbins if ((narray = 3894b88c807SRodney W. Grimes realloc(array, dp->entries * sizeof(FTSENT *))) == NULL) { 3904b88c807SRodney W. Grimes printscol(dp); 391c5bc8709STim J. Robbins return; 3924b88c807SRodney W. Grimes } 393c5bc8709STim J. Robbins lastentries = dp->entries; 394c5bc8709STim J. Robbins array = narray; 3954b88c807SRodney W. Grimes } 3964b88c807SRodney W. Grimes for (p = dp->list, num = 0; p; p = p->fts_link) 3974b88c807SRodney W. Grimes if (p->fts_number != NO_PRINT) 3984b88c807SRodney W. Grimes array[num++] = p; 3994b88c807SRodney W. Grimes 4004b88c807SRodney W. Grimes colwidth = dp->maxlen; 4014b88c807SRodney W. Grimes if (f_inode) 4024b88c807SRodney W. Grimes colwidth += dp->s_inode + 1; 4034b88c807SRodney W. Grimes if (f_size) 4044b88c807SRodney W. Grimes colwidth += dp->s_block + 1; 4054b88c807SRodney W. Grimes if (f_type) 4064b88c807SRodney W. Grimes colwidth += 1; 4074b88c807SRodney W. Grimes 408545f583cSTim Vanderhoek colwidth = (colwidth + tabwidth) & ~(tabwidth - 1); 4094b88c807SRodney W. Grimes if (termwidth < 2 * colwidth) { 4104b88c807SRodney W. Grimes printscol(dp); 4114b88c807SRodney W. Grimes return; 4124b88c807SRodney W. Grimes } 4134b88c807SRodney W. Grimes numcols = termwidth / colwidth; 4144b88c807SRodney W. Grimes numrows = num / numcols; 4154b88c807SRodney W. Grimes if (num % numcols) 4164b88c807SRodney W. Grimes ++numrows; 4174b88c807SRodney W. Grimes 41848a91b69SDavid Schultz if ((dp->list == NULL || dp->list->fts_level != FTS_ROOTLEVEL) && 41948a91b69SDavid Schultz (f_longform || f_size)) { 42052e4a08cSMarcel Moolenaar xo_emit("{L:total} {:total-blocks/%lu}\n", 42152e4a08cSMarcel Moolenaar howmany(dp->btotal, blocksize)); 42248a91b69SDavid Schultz } 42394274c73STim J. Robbins 42452e4a08cSMarcel Moolenaar xo_open_list("entry"); 42594274c73STim J. Robbins base = 0; 4264b88c807SRodney W. Grimes for (row = 0; row < numrows; ++row) { 4274b88c807SRodney W. Grimes endcol = colwidth; 42894274c73STim J. Robbins if (!f_sortacross) 42994274c73STim J. Robbins base = row; 43094274c73STim J. Robbins for (col = 0, chcnt = 0; col < numcols; ++col) { 43152e4a08cSMarcel Moolenaar xo_open_instance("entry"); 4324b88c807SRodney W. Grimes chcnt += printaname(array[base], dp->s_inode, 4334b88c807SRodney W. Grimes dp->s_block); 43452e4a08cSMarcel Moolenaar xo_close_instance("entry"); 43594274c73STim J. Robbins if (f_sortacross) 43694274c73STim J. Robbins base++; 43794274c73STim J. Robbins else 43894274c73STim J. Robbins base += numrows; 43994274c73STim J. Robbins if (base >= num) 4404b88c807SRodney W. Grimes break; 441545f583cSTim Vanderhoek while ((cnt = ((chcnt + tabwidth) & ~(tabwidth - 1))) 442545f583cSTim Vanderhoek <= endcol) { 44394274c73STim J. Robbins if (f_sortacross && col + 1 >= numcols) 44494274c73STim J. Robbins break; 44552e4a08cSMarcel Moolenaar xo_emit(f_notabs ? " " : "\t"); 4464b88c807SRodney W. Grimes chcnt = cnt; 4474b88c807SRodney W. Grimes } 4484b88c807SRodney W. Grimes endcol += colwidth; 4494b88c807SRodney W. Grimes } 45052e4a08cSMarcel Moolenaar xo_emit("\n"); 4514b88c807SRodney W. Grimes } 45252e4a08cSMarcel Moolenaar xo_close_list("entry"); 4534b88c807SRodney W. Grimes } 4544b88c807SRodney W. Grimes 4554b88c807SRodney W. Grimes /* 4564b88c807SRodney W. Grimes * print [inode] [size] name 4574b88c807SRodney W. Grimes * return # of characters printed, no trailing characters. 4584b88c807SRodney W. Grimes */ 4594b88c807SRodney W. Grimes static int 46040feca3aSMark Murray printaname(const FTSENT *p, u_long inodefield, u_long sizefield) 4614b88c807SRodney W. Grimes { 4624b88c807SRodney W. Grimes struct stat *sp; 4634b88c807SRodney W. Grimes int chcnt; 46447bb6b11SAndrey A. Chernov #ifdef COLORLS 46547bb6b11SAndrey A. Chernov int color_printed = 0; 46647bb6b11SAndrey A. Chernov #endif 4674b88c807SRodney W. Grimes 4684b88c807SRodney W. Grimes sp = p->fts_statp; 4694b88c807SRodney W. Grimes chcnt = 0; 4704b88c807SRodney W. Grimes if (f_inode) 471e5542be4SAllan Jude chcnt += xo_emit("{t:inode/%*ju} ", 4726db1a7f1SMatthew D Fleming (int)inodefield, (uintmax_t)sp->st_ino); 4734b88c807SRodney W. Grimes if (f_size) 474e5542be4SAllan Jude chcnt += xo_emit("{t:size/%*jd} ", 4754b88c807SRodney W. Grimes (int)sizefield, howmany(sp->st_blocks, blocksize)); 47674985094SJosef Karthauser #ifdef COLORLS 4773885812cSJosef Karthauser if (f_color) 478cf0feaeeSAndrey A. Chernov color_printed = colortype(sp->st_mode); 47974985094SJosef Karthauser #endif 48052e4a08cSMarcel Moolenaar chcnt += printname("name", p->fts_name); 48174985094SJosef Karthauser #ifdef COLORLS 482cf0feaeeSAndrey A. Chernov if (f_color && color_printed) 48338782c25SAndrey A. Chernov endcolor(0); 48474985094SJosef Karthauser #endif 4854b88c807SRodney W. Grimes if (f_type) 4864b88c807SRodney W. Grimes chcnt += printtype(sp->st_mode); 4874b88c807SRodney W. Grimes return (chcnt); 4884b88c807SRodney W. Grimes } 4894b88c807SRodney W. Grimes 49055926a66SJaakko Heinonen /* 49155926a66SJaakko Heinonen * Print device special file major and minor numbers. 49255926a66SJaakko Heinonen */ 49355926a66SJaakko Heinonen static void 49455926a66SJaakko Heinonen printdev(size_t width, dev_t dev) 49555926a66SJaakko Heinonen { 49652e4a08cSMarcel Moolenaar xo_emit("{:device/%#*jx} ", (u_int)width, (uintmax_t)dev); 49755926a66SJaakko Heinonen } 49855926a66SJaakko Heinonen 499be90c1c6SBaptiste Daroussin static size_t 500be90c1c6SBaptiste Daroussin ls_strftime(char *str, size_t len, const char *fmt, const struct tm *tm) 501be90c1c6SBaptiste Daroussin { 502be90c1c6SBaptiste Daroussin char *posb, nfmt[BUFSIZ]; 503be90c1c6SBaptiste Daroussin const char *format = fmt; 504be90c1c6SBaptiste Daroussin size_t ret; 505be90c1c6SBaptiste Daroussin 506be90c1c6SBaptiste Daroussin if ((posb = strstr(fmt, "%b")) != NULL) { 507be90c1c6SBaptiste Daroussin if (month_max_size == 0) { 508be90c1c6SBaptiste Daroussin compute_abbreviated_month_size(); 509be90c1c6SBaptiste Daroussin } 510be90c1c6SBaptiste Daroussin if (month_max_size > 0) { 511be90c1c6SBaptiste Daroussin snprintf(nfmt, sizeof(nfmt), "%.*s%s%*s%s", 512be90c1c6SBaptiste Daroussin (int)(posb - fmt), fmt, 513be90c1c6SBaptiste Daroussin get_abmon(tm->tm_mon), 514be90c1c6SBaptiste Daroussin (int)padding_for_month[tm->tm_mon], 515be90c1c6SBaptiste Daroussin "", 516be90c1c6SBaptiste Daroussin posb + 2); 517be90c1c6SBaptiste Daroussin format = nfmt; 518be90c1c6SBaptiste Daroussin } 519be90c1c6SBaptiste Daroussin } 520be90c1c6SBaptiste Daroussin ret = strftime(str, len, format, tm); 521be90c1c6SBaptiste Daroussin return (ret); 522be90c1c6SBaptiste Daroussin } 523be90c1c6SBaptiste Daroussin 5244b88c807SRodney W. Grimes static void 52552e4a08cSMarcel Moolenaar printtime(const char *field, time_t ftime) 5264b88c807SRodney W. Grimes { 527fc4a9bafSAndrey A. Chernov char longstring[80]; 52852e4a08cSMarcel Moolenaar char fmt[BUFSIZ]; 52940feca3aSMark Murray static time_t now = 0; 53097e4e97bSJosef Karthauser const char *format; 5318234eb25SAndrey A. Chernov static int d_first = -1; 532f173abd0SMike Pritchard 53328fd017aSAndrey A. Chernov if (d_first < 0) 53428fd017aSAndrey A. Chernov d_first = (*nl_langinfo(D_MD_ORDER) == 'd'); 535f173abd0SMike Pritchard if (now == 0) 536f173abd0SMike Pritchard now = time(NULL); 5374b88c807SRodney W. Grimes 538656dcd43SGarrett Wollman #define SIXMONTHS ((365 / 2) * 86400) 5392269fa57SGreg Lehey if (f_timeformat) /* user specified format */ 5402269fa57SGreg Lehey format = f_timeformat; 5412269fa57SGreg Lehey else if (f_sectime) 5421e715e34SJosef Karthauser /* mmm dd hh:mm:ss yyyy || dd mmm hh:mm:ss yyyy */ 54328fd017aSAndrey A. Chernov format = d_first ? "%e %b %T %Y" : "%b %e %T %Y"; 544f173abd0SMike Pritchard else if (ftime + SIXMONTHS > now && ftime < now + SIXMONTHS) 5451e715e34SJosef Karthauser /* mmm dd hh:mm || dd mmm hh:mm */ 54628fd017aSAndrey A. Chernov format = d_first ? "%e %b %R" : "%b %e %R"; 54797e4e97bSJosef Karthauser else 5481e715e34SJosef Karthauser /* mmm dd yyyy || dd mmm yyyy */ 54928fd017aSAndrey A. Chernov format = d_first ? "%e %b %Y" : "%b %e %Y"; 550be90c1c6SBaptiste Daroussin ls_strftime(longstring, sizeof(longstring), format, localtime(&ftime)); 55152e4a08cSMarcel Moolenaar 552e5542be4SAllan Jude snprintf(fmt, sizeof(fmt), "{d:%s/%%hs} ", field); 55352e4a08cSMarcel Moolenaar xo_attr("value", "%ld", (long) ftime); 55452e4a08cSMarcel Moolenaar xo_emit(fmt, longstring); 555e5542be4SAllan Jude snprintf(fmt, sizeof(fmt), "{en:%s/%%ld}", field); 556e5542be4SAllan Jude xo_emit(fmt, (long) ftime); 5574b88c807SRodney W. Grimes } 5584b88c807SRodney W. Grimes 5594b88c807SRodney W. Grimes static int 56046251ddeSWarner Losh printtype(u_int mode) 5614b88c807SRodney W. Grimes { 56294274c73STim J. Robbins 56394274c73STim J. Robbins if (f_slash) { 56494274c73STim J. Robbins if ((mode & S_IFMT) == S_IFDIR) { 56552e4a08cSMarcel Moolenaar xo_emit("{D:\\/}{e:type/directory}"); 56694274c73STim J. Robbins return (1); 56794274c73STim J. Robbins } 56894274c73STim J. Robbins return (0); 56994274c73STim J. Robbins } 57094274c73STim J. Robbins 5714b88c807SRodney W. Grimes switch (mode & S_IFMT) { 5724b88c807SRodney W. Grimes case S_IFDIR: 57352e4a08cSMarcel Moolenaar xo_emit("{D:/\\/}{e:type/directory}"); 5744b88c807SRodney W. Grimes return (1); 5754b88c807SRodney W. Grimes case S_IFIFO: 57652e4a08cSMarcel Moolenaar xo_emit("{D:|}{e:type/fifo}"); 5774b88c807SRodney W. Grimes return (1); 5784b88c807SRodney W. Grimes case S_IFLNK: 57952e4a08cSMarcel Moolenaar xo_emit("{D:@}{e:type/link}"); 5804b88c807SRodney W. Grimes return (1); 5814b88c807SRodney W. Grimes case S_IFSOCK: 58252e4a08cSMarcel Moolenaar xo_emit("{D:=}{e:type/socket}"); 5834b88c807SRodney W. Grimes return (1); 584fb5cb208SSteve Price case S_IFWHT: 585e9eed90cSAllan Jude xo_emit("{D:%%}{e:type/whiteout}"); 586fb5cb208SSteve Price return (1); 5879052855aSMark Murray default: 588568dcd5fSBill Fumerola break; 5894b88c807SRodney W. Grimes } 5904b88c807SRodney W. Grimes if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) { 59152e4a08cSMarcel Moolenaar xo_emit("{D:*}{e:executable/}"); 5924b88c807SRodney W. Grimes return (1); 5934b88c807SRodney W. Grimes } 5944b88c807SRodney W. Grimes return (0); 5954b88c807SRodney W. Grimes } 5964b88c807SRodney W. Grimes 59774985094SJosef Karthauser #ifdef COLORLS 5981bf1478aSAndrey A. Chernov static int 59946251ddeSWarner Losh putch(int c) 600cf0feaeeSAndrey A. Chernov { 60152e4a08cSMarcel Moolenaar xo_emit("{D:/%c}", c); 60238782c25SAndrey A. Chernov return 0; 603cf0feaeeSAndrey A. Chernov } 604cf0feaeeSAndrey A. Chernov 6051bf1478aSAndrey A. Chernov static int 60646251ddeSWarner Losh writech(int c) 60738782c25SAndrey A. Chernov { 60840feca3aSMark Murray char tmp = (char)c; 60938782c25SAndrey A. Chernov 61038782c25SAndrey A. Chernov (void)write(STDOUT_FILENO, &tmp, 1); 61138782c25SAndrey A. Chernov return 0; 61238782c25SAndrey A. Chernov } 613cf0feaeeSAndrey A. Chernov 6141bf1478aSAndrey A. Chernov static void 61546251ddeSWarner Losh printcolor(Colors c) 6163885812cSJosef Karthauser { 61774985094SJosef Karthauser char *ansiseq; 61874985094SJosef Karthauser 619c1499cf6SJosef Karthauser if (colors[c].bold) 620c1499cf6SJosef Karthauser tputs(enter_bold, 1, putch); 621c1499cf6SJosef Karthauser 622c1499cf6SJosef Karthauser if (colors[c].num[0] != -1) { 623c1499cf6SJosef Karthauser ansiseq = tgoto(ansi_fgcol, 0, colors[c].num[0]); 62438782c25SAndrey A. Chernov if (ansiseq) 625cf0feaeeSAndrey A. Chernov tputs(ansiseq, 1, putch); 6263885812cSJosef Karthauser } 627c1499cf6SJosef Karthauser if (colors[c].num[1] != -1) { 628c1499cf6SJosef Karthauser ansiseq = tgoto(ansi_bgcol, 0, colors[c].num[1]); 62938782c25SAndrey A. Chernov if (ansiseq) 630cf0feaeeSAndrey A. Chernov tputs(ansiseq, 1, putch); 63174985094SJosef Karthauser } 63274985094SJosef Karthauser } 63374985094SJosef Karthauser 63438782c25SAndrey A. Chernov static void 63546251ddeSWarner Losh endcolor(int sig) 63674985094SJosef Karthauser { 63738782c25SAndrey A. Chernov tputs(ansi_coloff, 1, sig ? writech : putch); 638c1499cf6SJosef Karthauser tputs(attrs_off, 1, sig ? writech : putch); 6393885812cSJosef Karthauser } 6403885812cSJosef Karthauser 64138782c25SAndrey A. Chernov static int 64246251ddeSWarner Losh colortype(mode_t mode) 6433885812cSJosef Karthauser { 6443885812cSJosef Karthauser switch (mode & S_IFMT) { 6453885812cSJosef Karthauser case S_IFDIR: 6463885812cSJosef Karthauser if (mode & S_IWOTH) 6473885812cSJosef Karthauser if (mode & S_ISTXT) 6483885812cSJosef Karthauser printcolor(C_WSDIR); 6493885812cSJosef Karthauser else 6503885812cSJosef Karthauser printcolor(C_WDIR); 6513885812cSJosef Karthauser else 6523885812cSJosef Karthauser printcolor(C_DIR); 6533885812cSJosef Karthauser return (1); 6543885812cSJosef Karthauser case S_IFLNK: 6553885812cSJosef Karthauser printcolor(C_LNK); 6563885812cSJosef Karthauser return (1); 6573885812cSJosef Karthauser case S_IFSOCK: 6583885812cSJosef Karthauser printcolor(C_SOCK); 6593885812cSJosef Karthauser return (1); 6603885812cSJosef Karthauser case S_IFIFO: 6613885812cSJosef Karthauser printcolor(C_FIFO); 6623885812cSJosef Karthauser return (1); 6633885812cSJosef Karthauser case S_IFBLK: 6643885812cSJosef Karthauser printcolor(C_BLK); 6653885812cSJosef Karthauser return (1); 6663885812cSJosef Karthauser case S_IFCHR: 6673885812cSJosef Karthauser printcolor(C_CHR); 6683885812cSJosef Karthauser return (1); 66940feca3aSMark Murray default:; 6703885812cSJosef Karthauser } 6713885812cSJosef Karthauser if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) { 6723885812cSJosef Karthauser if (mode & S_ISUID) 6733885812cSJosef Karthauser printcolor(C_SUID); 6743885812cSJosef Karthauser else if (mode & S_ISGID) 6753885812cSJosef Karthauser printcolor(C_SGID); 6763885812cSJosef Karthauser else 6773885812cSJosef Karthauser printcolor(C_EXEC); 6783885812cSJosef Karthauser return (1); 6793885812cSJosef Karthauser } 6803885812cSJosef Karthauser return (0); 6813885812cSJosef Karthauser } 6823885812cSJosef Karthauser 6833885812cSJosef Karthauser void 68446251ddeSWarner Losh parsecolors(const char *cs) 6853885812cSJosef Karthauser { 686b0bc91e9SJosef Karthauser int i; 687b0bc91e9SJosef Karthauser int j; 688ca2993fbSMark Murray size_t len; 6893885812cSJosef Karthauser char c[2]; 690c1499cf6SJosef Karthauser short legacy_warn = 0; 69138782c25SAndrey A. Chernov 692b0bc91e9SJosef Karthauser if (cs == NULL) 693b0bc91e9SJosef Karthauser cs = ""; /* LSCOLORS not set */ 6943885812cSJosef Karthauser len = strlen(cs); 69540feca3aSMark Murray for (i = 0; i < (int)C_NUMCOLORS; i++) { 696c1499cf6SJosef Karthauser colors[i].bold = 0; 697c1499cf6SJosef Karthauser 69840feca3aSMark Murray if (len <= 2 * (size_t)i) { 6993885812cSJosef Karthauser c[0] = defcolors[2 * i]; 7003885812cSJosef Karthauser c[1] = defcolors[2 * i + 1]; 7015dda5d0dSJosef Karthauser } else { 7023885812cSJosef Karthauser c[0] = cs[2 * i]; 7033885812cSJosef Karthauser c[1] = cs[2 * i + 1]; 7043885812cSJosef Karthauser } 7053885812cSJosef Karthauser for (j = 0; j < 2; j++) { 706c1499cf6SJosef Karthauser /* Legacy colours used 0-7 */ 707c1499cf6SJosef Karthauser if (c[j] >= '0' && c[j] <= '7') { 708c1499cf6SJosef Karthauser colors[i].num[j] = c[j] - '0'; 709c1499cf6SJosef Karthauser if (!legacy_warn) { 71052e4a08cSMarcel Moolenaar xo_warnx("LSCOLORS should use " 711130d15dcSJosef Karthauser "characters a-h instead of 0-9 (" 712e09fdabdSTim J. Robbins "see the manual page)"); 7133885812cSJosef Karthauser } 714c1499cf6SJosef Karthauser legacy_warn = 1; 715c1499cf6SJosef Karthauser } else if (c[j] >= 'a' && c[j] <= 'h') 716c1499cf6SJosef Karthauser colors[i].num[j] = c[j] - 'a'; 717c1499cf6SJosef Karthauser else if (c[j] >= 'A' && c[j] <= 'H') { 718c1499cf6SJosef Karthauser colors[i].num[j] = c[j] - 'A'; 719c1499cf6SJosef Karthauser colors[i].bold = 1; 72040feca3aSMark Murray } else if (tolower((unsigned char)c[j]) == 'x') 721c1499cf6SJosef Karthauser colors[i].num[j] = -1; 722c1499cf6SJosef Karthauser else { 72352e4a08cSMarcel Moolenaar xo_warnx("invalid character '%c' in LSCOLORS" 724e09fdabdSTim J. Robbins " env var", c[j]); 7250d72516eSJosef Karthauser colors[i].num[j] = -1; 726c1499cf6SJosef Karthauser } 7273885812cSJosef Karthauser } 7283885812cSJosef Karthauser } 7293885812cSJosef Karthauser } 730cf0feaeeSAndrey A. Chernov 7311bf1478aSAndrey A. Chernov void 73246251ddeSWarner Losh colorquit(int sig) 733cf0feaeeSAndrey A. Chernov { 73438782c25SAndrey A. Chernov endcolor(sig); 735faebfe2eSAndrey A. Chernov 736faebfe2eSAndrey A. Chernov (void)signal(sig, SIG_DFL); 737faebfe2eSAndrey A. Chernov (void)kill(getpid(), sig); 738cf0feaeeSAndrey A. Chernov } 7395dda5d0dSJosef Karthauser 74074985094SJosef Karthauser #endif /* COLORLS */ 7413885812cSJosef Karthauser 7424b88c807SRodney W. Grimes static void 743ca2993fbSMark Murray printlink(const FTSENT *p) 7444b88c807SRodney W. Grimes { 7454b88c807SRodney W. Grimes int lnklen; 746b0bc91e9SJosef Karthauser char name[MAXPATHLEN + 1]; 747b0bc91e9SJosef Karthauser char path[MAXPATHLEN + 1]; 7484b88c807SRodney W. Grimes 7494b88c807SRodney W. Grimes if (p->fts_level == FTS_ROOTLEVEL) 7504b88c807SRodney W. Grimes (void)snprintf(name, sizeof(name), "%s", p->fts_name); 7514b88c807SRodney W. Grimes else 7524b88c807SRodney W. Grimes (void)snprintf(name, sizeof(name), 7534b88c807SRodney W. Grimes "%s/%s", p->fts_parent->fts_accpath, p->fts_name); 7544b88c807SRodney W. Grimes if ((lnklen = readlink(name, path, sizeof(path) - 1)) == -1) { 75552e4a08cSMarcel Moolenaar xo_error("\nls: %s: %s\n", name, strerror(errno)); 7564b88c807SRodney W. Grimes return; 7574b88c807SRodney W. Grimes } 7584b88c807SRodney W. Grimes path[lnklen] = '\0'; 75952e4a08cSMarcel Moolenaar xo_emit(" -> "); 76052e4a08cSMarcel Moolenaar (void)printname("target", path); 7614b88c807SRodney W. Grimes } 7620e8d1551SJosef Karthauser 7630e8d1551SJosef Karthauser static void 76452e4a08cSMarcel Moolenaar printsize(const char *field, size_t width, off_t bytes) 7650e8d1551SJosef Karthauser { 76652e4a08cSMarcel Moolenaar char fmt[BUFSIZ]; 7670e8d1551SJosef Karthauser 7680e8d1551SJosef Karthauser if (f_humanval) { 76955926a66SJaakko Heinonen /* 77055926a66SJaakko Heinonen * Reserve one space before the size and allocate room for 77155926a66SJaakko Heinonen * the trailing '\0'. 77255926a66SJaakko Heinonen */ 77355926a66SJaakko Heinonen char buf[HUMANVALSTR_LEN - 1 + 1]; 7740e8d1551SJosef Karthauser 775478aa805SPawel Jakub Dawidek humanize_number(buf, sizeof(buf), (int64_t)bytes, "", 776478aa805SPawel Jakub Dawidek HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL); 77752e4a08cSMarcel Moolenaar snprintf(fmt, sizeof(fmt), "{:%s/%%%ds} ", field, (int) width); 77852e4a08cSMarcel Moolenaar xo_attr("value", "%jd", (intmax_t) bytes); 77952e4a08cSMarcel Moolenaar xo_emit(fmt, buf); 78052e4a08cSMarcel Moolenaar } else { /* with commas */ 7819aa68a3fSGreg Lehey /* This format assignment needed to work round gcc bug. */ 78252e4a08cSMarcel Moolenaar snprintf(fmt, sizeof(fmt), "{:%s/%%%dj%sd} ", 78352e4a08cSMarcel Moolenaar field, (int) width, f_thousands ? "'" : ""); 78452e4a08cSMarcel Moolenaar xo_emit(fmt, (intmax_t) bytes); 78552e4a08cSMarcel Moolenaar } 7860e8d1551SJosef Karthauser } 7870e8d1551SJosef Karthauser 788dd9aaeb0STim J. Robbins /* 789dd9aaeb0STim J. Robbins * Add a + after the standard rwxrwxrwx mode if the file has an 790f7b8687aSEdward Tomasz Napierala * ACL. strmode() reserves space at the end of the string. 791dd9aaeb0STim J. Robbins */ 792f7b8687aSEdward Tomasz Napierala static void 793f7b8687aSEdward Tomasz Napierala aclmode(char *buf, const FTSENT *p) 794f7b8687aSEdward Tomasz Napierala { 795f7b8687aSEdward Tomasz Napierala char name[MAXPATHLEN + 1]; 796f7b8687aSEdward Tomasz Napierala int ret, trivial; 797f7b8687aSEdward Tomasz Napierala static dev_t previous_dev = NODEV; 798f7b8687aSEdward Tomasz Napierala static int supports_acls = -1; 799f7b8687aSEdward Tomasz Napierala static int type = ACL_TYPE_ACCESS; 800f7b8687aSEdward Tomasz Napierala acl_t facl; 801f7b8687aSEdward Tomasz Napierala 802f7b8687aSEdward Tomasz Napierala /* 803f7b8687aSEdward Tomasz Napierala * XXX: ACLs are not supported on whiteouts and device files 804f7b8687aSEdward Tomasz Napierala * residing on UFS. 805f7b8687aSEdward Tomasz Napierala */ 806f7b8687aSEdward Tomasz Napierala if (S_ISCHR(p->fts_statp->st_mode) || S_ISBLK(p->fts_statp->st_mode) || 807f7b8687aSEdward Tomasz Napierala S_ISWHT(p->fts_statp->st_mode)) 808f7b8687aSEdward Tomasz Napierala return; 809f7b8687aSEdward Tomasz Napierala 810a3429262SEdward Tomasz Napierala if (previous_dev == p->fts_statp->st_dev && supports_acls == 0) 811a3429262SEdward Tomasz Napierala return; 812f7b8687aSEdward Tomasz Napierala 813dd9aaeb0STim J. Robbins if (p->fts_level == FTS_ROOTLEVEL) 814dd9aaeb0STim J. Robbins snprintf(name, sizeof(name), "%s", p->fts_name); 815dd9aaeb0STim J. Robbins else 816dd9aaeb0STim J. Robbins snprintf(name, sizeof(name), "%s/%s", 817dd9aaeb0STim J. Robbins p->fts_parent->fts_accpath, p->fts_name); 818a3429262SEdward Tomasz Napierala 819a3429262SEdward Tomasz Napierala if (previous_dev != p->fts_statp->st_dev) { 820a3429262SEdward Tomasz Napierala previous_dev = p->fts_statp->st_dev; 821a3429262SEdward Tomasz Napierala supports_acls = 0; 822a3429262SEdward Tomasz Napierala 823f7b8687aSEdward Tomasz Napierala ret = lpathconf(name, _PC_ACL_NFS4); 824f7b8687aSEdward Tomasz Napierala if (ret > 0) { 825f7b8687aSEdward Tomasz Napierala type = ACL_TYPE_NFS4; 826f7b8687aSEdward Tomasz Napierala supports_acls = 1; 827f7b8687aSEdward Tomasz Napierala } else if (ret < 0 && errno != EINVAL) { 82852e4a08cSMarcel Moolenaar xo_warn("%s", name); 829dd9aaeb0STim J. Robbins return; 830dd9aaeb0STim J. Robbins } 831f7b8687aSEdward Tomasz Napierala if (supports_acls == 0) { 832f7b8687aSEdward Tomasz Napierala ret = lpathconf(name, _PC_ACL_EXTENDED); 833f7b8687aSEdward Tomasz Napierala if (ret > 0) { 834f7b8687aSEdward Tomasz Napierala type = ACL_TYPE_ACCESS; 835f7b8687aSEdward Tomasz Napierala supports_acls = 1; 836f7b8687aSEdward Tomasz Napierala } else if (ret < 0 && errno != EINVAL) { 83752e4a08cSMarcel Moolenaar xo_warn("%s", name); 838f7b8687aSEdward Tomasz Napierala return; 839dd9aaeb0STim J. Robbins } 840f7b8687aSEdward Tomasz Napierala } 841f7b8687aSEdward Tomasz Napierala } 842f7b8687aSEdward Tomasz Napierala if (supports_acls == 0) 843f7b8687aSEdward Tomasz Napierala return; 844f7b8687aSEdward Tomasz Napierala facl = acl_get_link_np(name, type); 845f7b8687aSEdward Tomasz Napierala if (facl == NULL) { 84652e4a08cSMarcel Moolenaar xo_warn("%s", name); 847f7b8687aSEdward Tomasz Napierala return; 848f7b8687aSEdward Tomasz Napierala } 849f7b8687aSEdward Tomasz Napierala if (acl_is_trivial_np(facl, &trivial)) { 850dd9aaeb0STim J. Robbins acl_free(facl); 85152e4a08cSMarcel Moolenaar xo_warn("%s", name); 852f7b8687aSEdward Tomasz Napierala return; 853f7b8687aSEdward Tomasz Napierala } 854f7b8687aSEdward Tomasz Napierala if (!trivial) 855f7b8687aSEdward Tomasz Napierala buf[10] = '+'; 856f7b8687aSEdward Tomasz Napierala acl_free(facl); 857dd9aaeb0STim J. Robbins } 858