19ddb49cbSWarner Losh /*- 24b88c807SRodney W. Grimes * Copyright (c) 1989, 1993, 1994 34b88c807SRodney W. Grimes * The Regents of the University of California. All rights reserved. 44b88c807SRodney W. Grimes * 54b88c807SRodney W. Grimes * This code is derived from software contributed to Berkeley by 64b88c807SRodney W. Grimes * Michael Fischbein. 74b88c807SRodney W. Grimes * 84b88c807SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 94b88c807SRodney W. Grimes * modification, are permitted provided that the following conditions 104b88c807SRodney W. Grimes * are met: 114b88c807SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 124b88c807SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 134b88c807SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 144b88c807SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 154b88c807SRodney W. Grimes * documentation and/or other materials provided with the distribution. 164b88c807SRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 174b88c807SRodney W. Grimes * may be used to endorse or promote products derived from this software 184b88c807SRodney W. Grimes * without specific prior written permission. 194b88c807SRodney W. Grimes * 204b88c807SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 214b88c807SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 224b88c807SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 234b88c807SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 244b88c807SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 254b88c807SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 264b88c807SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 274b88c807SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 284b88c807SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 294b88c807SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 304b88c807SRodney W. Grimes * SUCH DAMAGE. 314b88c807SRodney W. Grimes */ 324b88c807SRodney W. Grimes 33febad2fcSSteve Price #if 0 34c73d77ceSMark Murray #ifndef lint 35febad2fcSSteve Price static char sccsid[] = "@(#)print.c 8.4 (Berkeley) 4/17/94"; 364b88c807SRodney W. Grimes #endif /* not lint */ 37c73d77ceSMark Murray #endif 385eb43ac2SDavid E. O'Brien #include <sys/cdefs.h> 395eb43ac2SDavid E. O'Brien __FBSDID("$FreeBSD$"); 404b88c807SRodney W. Grimes 414b88c807SRodney W. Grimes #include <sys/param.h> 424b88c807SRodney W. Grimes #include <sys/stat.h> 43dd9aaeb0STim J. Robbins #include <sys/acl.h> 444b88c807SRodney W. Grimes 454b88c807SRodney W. Grimes #include <err.h> 464b88c807SRodney W. Grimes #include <errno.h> 474b88c807SRodney W. Grimes #include <fts.h> 4828fd017aSAndrey A. Chernov #include <langinfo.h> 49478aa805SPawel Jakub Dawidek #include <libutil.h> 50*be90c1c6SBaptiste Daroussin #include <limits.h> 514b88c807SRodney W. Grimes #include <stdio.h> 529f365aa1SEd Schouten #include <stdint.h> 534b88c807SRodney W. Grimes #include <stdlib.h> 544b88c807SRodney W. Grimes #include <string.h> 55434b6ea4SBruce Evans #include <time.h> 564b88c807SRodney W. Grimes #include <unistd.h> 57*be90c1c6SBaptiste Daroussin #include <wchar.h> 58faebfe2eSAndrey A. Chernov #ifdef COLORLS 59faebfe2eSAndrey A. Chernov #include <ctype.h> 60faebfe2eSAndrey A. Chernov #include <termcap.h> 61faebfe2eSAndrey A. Chernov #include <signal.h> 62faebfe2eSAndrey A. Chernov #endif 6352e4a08cSMarcel Moolenaar #include <libxo/xo.h> 644b88c807SRodney W. Grimes 654b88c807SRodney W. Grimes #include "ls.h" 664b88c807SRodney W. Grimes #include "extern.h" 674b88c807SRodney W. Grimes 6840feca3aSMark Murray static int printaname(const FTSENT *, u_long, u_long); 6955926a66SJaakko Heinonen static void printdev(size_t, dev_t); 70ca2993fbSMark Murray static void printlink(const FTSENT *); 7152e4a08cSMarcel Moolenaar static void printtime(const char *, time_t); 7246251ddeSWarner Losh static int printtype(u_int); 7352e4a08cSMarcel Moolenaar static void printsize(const char *, size_t, off_t); 7438782c25SAndrey A. Chernov #ifdef COLORLS 7546251ddeSWarner Losh static void endcolor(int); 7646251ddeSWarner Losh static int colortype(mode_t); 7738782c25SAndrey A. Chernov #endif 78f7b8687aSEdward Tomasz Napierala static void aclmode(char *, const FTSENT *); 794b88c807SRodney W. Grimes 804b88c807SRodney W. Grimes #define IS_NOPRINT(p) ((p)->fts_number == NO_PRINT) 810e8d1551SJosef Karthauser 8274985094SJosef Karthauser #ifdef COLORLS 833885812cSJosef Karthauser /* Most of these are taken from <sys/stat.h> */ 843885812cSJosef Karthauser typedef enum Colors { 853885812cSJosef Karthauser C_DIR, /* directory */ 863885812cSJosef Karthauser C_LNK, /* symbolic link */ 873885812cSJosef Karthauser C_SOCK, /* socket */ 883885812cSJosef Karthauser C_FIFO, /* pipe */ 893885812cSJosef Karthauser C_EXEC, /* executable */ 903885812cSJosef Karthauser C_BLK, /* block special */ 913885812cSJosef Karthauser C_CHR, /* character special */ 923885812cSJosef Karthauser C_SUID, /* setuid executable */ 933885812cSJosef Karthauser C_SGID, /* setgid executable */ 945dda5d0dSJosef Karthauser C_WSDIR, /* directory writeble to others, with sticky 955dda5d0dSJosef Karthauser * bit */ 965dda5d0dSJosef Karthauser C_WDIR, /* directory writeble to others, without 975dda5d0dSJosef Karthauser * sticky bit */ 983885812cSJosef Karthauser C_NUMCOLORS /* just a place-holder */ 993885812cSJosef Karthauser } Colors; 1003885812cSJosef Karthauser 1019052855aSMark Murray static const char *defcolors = "exfxcxdxbxegedabagacad"; 1023885812cSJosef Karthauser 103c1499cf6SJosef Karthauser /* colors for file types */ 104c1499cf6SJosef Karthauser static struct { 105c1499cf6SJosef Karthauser int num[2]; 106c1499cf6SJosef Karthauser int bold; 107c1499cf6SJosef Karthauser } colors[C_NUMCOLORS]; 10874985094SJosef Karthauser #endif 1093885812cSJosef Karthauser 110*be90c1c6SBaptiste Daroussin static size_t padding_for_month[12]; 111*be90c1c6SBaptiste Daroussin static size_t month_max_size = 0; 112*be90c1c6SBaptiste Daroussin 1134b88c807SRodney W. Grimes void 11440feca3aSMark Murray printscol(const DISPLAY *dp) 1154b88c807SRodney W. Grimes { 1164b88c807SRodney W. Grimes FTSENT *p; 1174b88c807SRodney W. Grimes 11852e4a08cSMarcel Moolenaar xo_open_list("entry"); 1194b88c807SRodney W. Grimes for (p = dp->list; p; p = p->fts_link) { 1204b88c807SRodney W. Grimes if (IS_NOPRINT(p)) 1214b88c807SRodney W. Grimes continue; 12252e4a08cSMarcel Moolenaar xo_open_instance("entry"); 1234b88c807SRodney W. Grimes (void)printaname(p, dp->s_inode, dp->s_block); 12452e4a08cSMarcel Moolenaar xo_close_instance("entry"); 12552e4a08cSMarcel Moolenaar xo_emit("\n"); 1264b88c807SRodney W. Grimes } 12752e4a08cSMarcel Moolenaar xo_close_list("entry"); 1284b88c807SRodney W. Grimes } 1294b88c807SRodney W. Grimes 130ee579ffbSAssar Westerlund /* 131ee579ffbSAssar Westerlund * print name in current style 132ee579ffbSAssar Westerlund */ 1331656f850STim J. Robbins int 13452e4a08cSMarcel Moolenaar printname(const char *field, const char *name) 13552e4a08cSMarcel Moolenaar { 13652e4a08cSMarcel Moolenaar char fmt[BUFSIZ]; 13752e4a08cSMarcel Moolenaar char *s = getname(name); 13852e4a08cSMarcel Moolenaar int rc; 13952e4a08cSMarcel Moolenaar 14052e4a08cSMarcel Moolenaar snprintf(fmt, sizeof(fmt), "{:%s/%%hs}", field); 14152e4a08cSMarcel Moolenaar rc = xo_emit(fmt, s); 14252e4a08cSMarcel Moolenaar free(s); 14352e4a08cSMarcel Moolenaar return rc; 14452e4a08cSMarcel Moolenaar } 14552e4a08cSMarcel Moolenaar 146*be90c1c6SBaptiste Daroussin static const char * 147*be90c1c6SBaptiste Daroussin get_abmon(int mon) 148*be90c1c6SBaptiste Daroussin { 149*be90c1c6SBaptiste Daroussin 150*be90c1c6SBaptiste Daroussin switch (mon) { 151*be90c1c6SBaptiste Daroussin case 0: return (nl_langinfo(ABMON_1)); 152*be90c1c6SBaptiste Daroussin case 1: return (nl_langinfo(ABMON_2)); 153*be90c1c6SBaptiste Daroussin case 2: return (nl_langinfo(ABMON_3)); 154*be90c1c6SBaptiste Daroussin case 3: return (nl_langinfo(ABMON_4)); 155*be90c1c6SBaptiste Daroussin case 4: return (nl_langinfo(ABMON_5)); 156*be90c1c6SBaptiste Daroussin case 5: return (nl_langinfo(ABMON_6)); 157*be90c1c6SBaptiste Daroussin case 6: return (nl_langinfo(ABMON_7)); 158*be90c1c6SBaptiste Daroussin case 7: return (nl_langinfo(ABMON_8)); 159*be90c1c6SBaptiste Daroussin case 8: return (nl_langinfo(ABMON_9)); 160*be90c1c6SBaptiste Daroussin case 9: return (nl_langinfo(ABMON_10)); 161*be90c1c6SBaptiste Daroussin case 10: return (nl_langinfo(ABMON_11)); 162*be90c1c6SBaptiste Daroussin case 11: return (nl_langinfo(ABMON_12)); 163*be90c1c6SBaptiste Daroussin } 164*be90c1c6SBaptiste Daroussin 165*be90c1c6SBaptiste Daroussin /* should never happen */ 166*be90c1c6SBaptiste Daroussin abort(); 167*be90c1c6SBaptiste Daroussin } 168*be90c1c6SBaptiste Daroussin 169*be90c1c6SBaptiste Daroussin static size_t 170*be90c1c6SBaptiste Daroussin mbswidth(const char *month) 171*be90c1c6SBaptiste Daroussin { 172*be90c1c6SBaptiste Daroussin wchar_t wc; 173*be90c1c6SBaptiste Daroussin size_t width, donelen, clen, w; 174*be90c1c6SBaptiste Daroussin 175*be90c1c6SBaptiste Daroussin width = donelen = 0; 176*be90c1c6SBaptiste Daroussin while ((clen = mbrtowc(&wc, month + donelen, MB_LEN_MAX, NULL)) != 0) { 177*be90c1c6SBaptiste Daroussin if (clen == (size_t)-1 || clen == (size_t)-2) 178*be90c1c6SBaptiste Daroussin return (-1); 179*be90c1c6SBaptiste Daroussin donelen += clen; 180*be90c1c6SBaptiste Daroussin if ((w = wcwidth(wc)) == (size_t)-1) 181*be90c1c6SBaptiste Daroussin return (-1); 182*be90c1c6SBaptiste Daroussin width += w; 183*be90c1c6SBaptiste Daroussin } 184*be90c1c6SBaptiste Daroussin 185*be90c1c6SBaptiste Daroussin return (width); 186*be90c1c6SBaptiste Daroussin } 187*be90c1c6SBaptiste Daroussin 188*be90c1c6SBaptiste Daroussin static void 189*be90c1c6SBaptiste Daroussin compute_abbreviated_month_size(void) 190*be90c1c6SBaptiste Daroussin { 191*be90c1c6SBaptiste Daroussin int i; 192*be90c1c6SBaptiste Daroussin size_t width; 193*be90c1c6SBaptiste Daroussin size_t months_width[12]; 194*be90c1c6SBaptiste Daroussin 195*be90c1c6SBaptiste Daroussin for (i = 0; i < 12; i++) { 196*be90c1c6SBaptiste Daroussin width = mbswidth(get_abmon(i)); 197*be90c1c6SBaptiste Daroussin if (width == (size_t)-1) { 198*be90c1c6SBaptiste Daroussin month_max_size = -1; 199*be90c1c6SBaptiste Daroussin return; 200*be90c1c6SBaptiste Daroussin } 201*be90c1c6SBaptiste Daroussin months_width[i] = width; 202*be90c1c6SBaptiste Daroussin if (width > month_max_size) 203*be90c1c6SBaptiste Daroussin month_max_size = width; 204*be90c1c6SBaptiste Daroussin } 205*be90c1c6SBaptiste Daroussin 206*be90c1c6SBaptiste Daroussin for (i = 0; i < 12; i++) 207*be90c1c6SBaptiste Daroussin padding_for_month[i] = month_max_size - months_width[i]; 208*be90c1c6SBaptiste Daroussin } 209*be90c1c6SBaptiste Daroussin 21052e4a08cSMarcel Moolenaar /* 21152e4a08cSMarcel Moolenaar * print name in current style 21252e4a08cSMarcel Moolenaar */ 21352e4a08cSMarcel Moolenaar char * 21452e4a08cSMarcel Moolenaar getname(const char *name) 215ee579ffbSAssar Westerlund { 216ee579ffbSAssar Westerlund if (f_octal || f_octal_escape) 21752e4a08cSMarcel Moolenaar return get_octal(name); 218ee579ffbSAssar Westerlund else if (f_nonprint) 21952e4a08cSMarcel Moolenaar return get_printable(name); 220ee579ffbSAssar Westerlund else 22152e4a08cSMarcel Moolenaar return strdup(name); 222ee579ffbSAssar Westerlund } 223ee579ffbSAssar Westerlund 2244b88c807SRodney W. Grimes void 22540feca3aSMark Murray printlong(const DISPLAY *dp) 2264b88c807SRodney W. Grimes { 2274b88c807SRodney W. Grimes struct stat *sp; 2284b88c807SRodney W. Grimes FTSENT *p; 2294b88c807SRodney W. Grimes NAMES *np; 2304b88c807SRodney W. Grimes char buf[20]; 23147bb6b11SAndrey A. Chernov #ifdef COLORLS 23247bb6b11SAndrey A. Chernov int color_printed = 0; 23347bb6b11SAndrey A. Chernov #endif 2344b88c807SRodney W. Grimes 23548a91b69SDavid Schultz if ((dp->list == NULL || dp->list->fts_level != FTS_ROOTLEVEL) && 23648a91b69SDavid Schultz (f_longform || f_size)) { 23752e4a08cSMarcel Moolenaar xo_emit("{L:total} {:total-blocks/%lu}\n", 23852e4a08cSMarcel Moolenaar howmany(dp->btotal, blocksize)); 23948a91b69SDavid Schultz } 2404b88c807SRodney W. Grimes 24152e4a08cSMarcel Moolenaar xo_open_list("entry"); 2424b88c807SRodney W. Grimes for (p = dp->list; p; p = p->fts_link) { 243e5542be4SAllan Jude char *name, *type; 2444b88c807SRodney W. Grimes if (IS_NOPRINT(p)) 2454b88c807SRodney W. Grimes continue; 24652e4a08cSMarcel Moolenaar xo_open_instance("entry"); 2474b88c807SRodney W. Grimes sp = p->fts_statp; 24852e4a08cSMarcel Moolenaar name = getname(p->fts_name); 24952e4a08cSMarcel Moolenaar if (name) 2500d5beab5SAlexander Kabaev xo_emit("{ke:name/%hs}", name); 2514b88c807SRodney W. Grimes if (f_inode) 252e5542be4SAllan Jude xo_emit("{t:inode/%*ju} ", 2536db1a7f1SMatthew D Fleming dp->s_inode, (uintmax_t)sp->st_ino); 2544b88c807SRodney W. Grimes if (f_size) 255e5542be4SAllan Jude xo_emit("{t:blocks/%*jd} ", 2564b88c807SRodney W. Grimes dp->s_block, howmany(sp->st_blocks, blocksize)); 2579052855aSMark Murray strmode(sp->st_mode, buf); 258f7b8687aSEdward Tomasz Napierala aclmode(buf, p); 2594b88c807SRodney W. Grimes np = p->fts_pointer; 26052e4a08cSMarcel Moolenaar xo_attr("value", "%03o", (int) sp->st_mode & ALLPERMS); 261e5542be4SAllan Jude if (f_numericonly) { 262e5542be4SAllan Jude xo_emit("{t:mode/%s}{e:mode_octal/%03o} {t:links/%*u} {td:user/%-*s}{e:user/%ju} {td:group/%-*s}{e:group/%ju} ", 263e5542be4SAllan Jude buf, (int) sp->st_mode & ALLPERMS, dp->s_nlink, sp->st_nlink, 264e9eed90cSAllan Jude dp->s_user, np->user, (uintmax_t)sp->st_uid, dp->s_group, np->group, (uintmax_t)sp->st_gid); 265e5542be4SAllan Jude } else { 266e5542be4SAllan Jude xo_emit("{t:mode/%s}{e:mode_octal/%03o} {t:links/%*u} {t:user/%-*s} {t:group/%-*s} ", 267e5542be4SAllan Jude buf, (int) sp->st_mode & ALLPERMS, dp->s_nlink, sp->st_nlink, 26852e4a08cSMarcel Moolenaar dp->s_user, np->user, dp->s_group, np->group); 269e5542be4SAllan Jude } 270e5542be4SAllan Jude if (S_ISBLK(sp->st_mode)) 271e5542be4SAllan Jude asprintf(&type, "block"); 272e5542be4SAllan Jude if (S_ISCHR(sp->st_mode)) 273e5542be4SAllan Jude asprintf(&type, "character"); 274e5542be4SAllan Jude if (S_ISDIR(sp->st_mode)) 275e5542be4SAllan Jude asprintf(&type, "directory"); 276e5542be4SAllan Jude if (S_ISFIFO(sp->st_mode)) 277e5542be4SAllan Jude asprintf(&type, "fifo"); 278e5542be4SAllan Jude if (S_ISLNK(sp->st_mode)) 279e5542be4SAllan Jude asprintf(&type, "symlink"); 280e5542be4SAllan Jude if (S_ISREG(sp->st_mode)) 281e5542be4SAllan Jude asprintf(&type, "regular"); 282e5542be4SAllan Jude if (S_ISSOCK(sp->st_mode)) 283e5542be4SAllan Jude asprintf(&type, "socket"); 284e5542be4SAllan Jude if (S_ISWHT(sp->st_mode)) 285e5542be4SAllan Jude asprintf(&type, "whiteout"); 286e5542be4SAllan Jude xo_emit("{e:type/%s}", type); 287e5542be4SAllan Jude free(type); 2884b88c807SRodney W. Grimes if (f_flags) 28952e4a08cSMarcel Moolenaar xo_emit("{:flags/%-*s} ", dp->s_flags, np->flags); 2904d33b62eSRobert Watson if (f_label) 291e5542be4SAllan Jude xo_emit("{t:label/%-*s} ", dp->s_label, np->label); 2924b88c807SRodney W. Grimes if (S_ISCHR(sp->st_mode) || S_ISBLK(sp->st_mode)) 29355926a66SJaakko Heinonen printdev(dp->s_size, sp->st_rdev); 2944b88c807SRodney W. Grimes else 29552e4a08cSMarcel Moolenaar printsize("size", dp->s_size, sp->st_size); 2964b88c807SRodney W. Grimes if (f_accesstime) 29752e4a08cSMarcel Moolenaar printtime("access-time", sp->st_atime); 298fe79420eSJohn Baldwin else if (f_birthtime) 29952e4a08cSMarcel Moolenaar printtime("birth-time", sp->st_birthtime); 3004b88c807SRodney W. Grimes else if (f_statustime) 30152e4a08cSMarcel Moolenaar printtime("change-time", sp->st_ctime); 3024b88c807SRodney W. Grimes else 30352e4a08cSMarcel Moolenaar printtime("modify-time", sp->st_mtime); 30474985094SJosef Karthauser #ifdef COLORLS 3053885812cSJosef Karthauser if (f_color) 306cf0feaeeSAndrey A. Chernov color_printed = colortype(sp->st_mode); 30774985094SJosef Karthauser #endif 30852e4a08cSMarcel Moolenaar 30952e4a08cSMarcel Moolenaar if (name) { 3100d5beab5SAlexander Kabaev xo_emit("{dk:name/%hs}", name); 31152e4a08cSMarcel Moolenaar free(name); 31252e4a08cSMarcel Moolenaar } 31352e4a08cSMarcel Moolenaar 31474985094SJosef Karthauser #ifdef COLORLS 315cf0feaeeSAndrey A. Chernov if (f_color && color_printed) 31638782c25SAndrey A. Chernov endcolor(0); 31774985094SJosef Karthauser #endif 3184b88c807SRodney W. Grimes if (f_type) 3194b88c807SRodney W. Grimes (void)printtype(sp->st_mode); 3204b88c807SRodney W. Grimes if (S_ISLNK(sp->st_mode)) 3214b88c807SRodney W. Grimes printlink(p); 32252e4a08cSMarcel Moolenaar xo_close_instance("entry"); 32352e4a08cSMarcel Moolenaar xo_emit("\n"); 3244b88c807SRodney W. Grimes } 32552e4a08cSMarcel Moolenaar xo_close_list("entry"); 3264b88c807SRodney W. Grimes } 3274b88c807SRodney W. Grimes 3284b88c807SRodney W. Grimes void 32940feca3aSMark Murray printstream(const DISPLAY *dp) 33094274c73STim J. Robbins { 33194274c73STim J. Robbins FTSENT *p; 33294274c73STim J. Robbins int chcnt; 33394274c73STim J. Robbins 334e5542be4SAllan Jude xo_open_list("entry"); 33594274c73STim J. Robbins for (p = dp->list, chcnt = 0; p; p = p->fts_link) { 33694274c73STim J. Robbins if (p->fts_number == NO_PRINT) 33794274c73STim J. Robbins continue; 338107409f4STim J. Robbins /* XXX strlen does not take octal escapes into account. */ 33994274c73STim J. Robbins if (strlen(p->fts_name) + chcnt + 34094274c73STim J. Robbins (p->fts_link ? 2 : 0) >= (unsigned)termwidth) { 34152e4a08cSMarcel Moolenaar xo_emit("\n"); 34294274c73STim J. Robbins chcnt = 0; 34394274c73STim J. Robbins } 344e5542be4SAllan Jude xo_open_instance("file"); 34594274c73STim J. Robbins chcnt += printaname(p, dp->s_inode, dp->s_block); 346e5542be4SAllan Jude xo_close_instance("file"); 34794274c73STim J. Robbins if (p->fts_link) { 34852e4a08cSMarcel Moolenaar xo_emit(", "); 34994274c73STim J. Robbins chcnt += 2; 35094274c73STim J. Robbins } 35194274c73STim J. Robbins } 352e5542be4SAllan Jude xo_close_list("entry"); 35394274c73STim J. Robbins if (chcnt) 35452e4a08cSMarcel Moolenaar xo_emit("\n"); 35594274c73STim J. Robbins } 35694274c73STim J. Robbins 35794274c73STim J. Robbins void 35840feca3aSMark Murray printcol(const DISPLAY *dp) 3594b88c807SRodney W. Grimes { 3604b88c807SRodney W. Grimes static FTSENT **array; 3614b88c807SRodney W. Grimes static int lastentries = -1; 3624b88c807SRodney W. Grimes FTSENT *p; 363c5bc8709STim J. Robbins FTSENT **narray; 364b0bc91e9SJosef Karthauser int base; 365b0bc91e9SJosef Karthauser int chcnt; 366b0bc91e9SJosef Karthauser int cnt; 367b0bc91e9SJosef Karthauser int col; 368b0bc91e9SJosef Karthauser int colwidth; 369b0bc91e9SJosef Karthauser int endcol; 370b0bc91e9SJosef Karthauser int num; 371b0bc91e9SJosef Karthauser int numcols; 372b0bc91e9SJosef Karthauser int numrows; 373b0bc91e9SJosef Karthauser int row; 374545f583cSTim Vanderhoek int tabwidth; 375545f583cSTim Vanderhoek 376545f583cSTim Vanderhoek if (f_notabs) 377545f583cSTim Vanderhoek tabwidth = 1; 378545f583cSTim Vanderhoek else 379545f583cSTim Vanderhoek tabwidth = 8; 3804b88c807SRodney W. Grimes 3814b88c807SRodney W. Grimes /* 3824b88c807SRodney W. Grimes * Have to do random access in the linked list -- build a table 3834b88c807SRodney W. Grimes * of pointers. 3844b88c807SRodney W. Grimes */ 3854b88c807SRodney W. Grimes if (dp->entries > lastentries) { 386c5bc8709STim J. Robbins if ((narray = 3874b88c807SRodney W. Grimes realloc(array, dp->entries * sizeof(FTSENT *))) == NULL) { 3884b88c807SRodney W. Grimes printscol(dp); 389c5bc8709STim J. Robbins return; 3904b88c807SRodney W. Grimes } 391c5bc8709STim J. Robbins lastentries = dp->entries; 392c5bc8709STim J. Robbins array = narray; 3934b88c807SRodney W. Grimes } 3944b88c807SRodney W. Grimes for (p = dp->list, num = 0; p; p = p->fts_link) 3954b88c807SRodney W. Grimes if (p->fts_number != NO_PRINT) 3964b88c807SRodney W. Grimes array[num++] = p; 3974b88c807SRodney W. Grimes 3984b88c807SRodney W. Grimes colwidth = dp->maxlen; 3994b88c807SRodney W. Grimes if (f_inode) 4004b88c807SRodney W. Grimes colwidth += dp->s_inode + 1; 4014b88c807SRodney W. Grimes if (f_size) 4024b88c807SRodney W. Grimes colwidth += dp->s_block + 1; 4034b88c807SRodney W. Grimes if (f_type) 4044b88c807SRodney W. Grimes colwidth += 1; 4054b88c807SRodney W. Grimes 406545f583cSTim Vanderhoek colwidth = (colwidth + tabwidth) & ~(tabwidth - 1); 4074b88c807SRodney W. Grimes if (termwidth < 2 * colwidth) { 4084b88c807SRodney W. Grimes printscol(dp); 4094b88c807SRodney W. Grimes return; 4104b88c807SRodney W. Grimes } 4114b88c807SRodney W. Grimes numcols = termwidth / colwidth; 4124b88c807SRodney W. Grimes numrows = num / numcols; 4134b88c807SRodney W. Grimes if (num % numcols) 4144b88c807SRodney W. Grimes ++numrows; 4154b88c807SRodney W. Grimes 41648a91b69SDavid Schultz if ((dp->list == NULL || dp->list->fts_level != FTS_ROOTLEVEL) && 41748a91b69SDavid Schultz (f_longform || f_size)) { 41852e4a08cSMarcel Moolenaar xo_emit("{L:total} {:total-blocks/%lu}\n", 41952e4a08cSMarcel Moolenaar howmany(dp->btotal, blocksize)); 42048a91b69SDavid Schultz } 42194274c73STim J. Robbins 42252e4a08cSMarcel Moolenaar xo_open_list("entry"); 42394274c73STim J. Robbins base = 0; 4244b88c807SRodney W. Grimes for (row = 0; row < numrows; ++row) { 4254b88c807SRodney W. Grimes endcol = colwidth; 42694274c73STim J. Robbins if (!f_sortacross) 42794274c73STim J. Robbins base = row; 42894274c73STim J. Robbins for (col = 0, chcnt = 0; col < numcols; ++col) { 42952e4a08cSMarcel Moolenaar xo_open_instance("entry"); 4304b88c807SRodney W. Grimes chcnt += printaname(array[base], dp->s_inode, 4314b88c807SRodney W. Grimes dp->s_block); 43252e4a08cSMarcel Moolenaar xo_close_instance("entry"); 43394274c73STim J. Robbins if (f_sortacross) 43494274c73STim J. Robbins base++; 43594274c73STim J. Robbins else 43694274c73STim J. Robbins base += numrows; 43794274c73STim J. Robbins if (base >= num) 4384b88c807SRodney W. Grimes break; 439545f583cSTim Vanderhoek while ((cnt = ((chcnt + tabwidth) & ~(tabwidth - 1))) 440545f583cSTim Vanderhoek <= endcol) { 44194274c73STim J. Robbins if (f_sortacross && col + 1 >= numcols) 44294274c73STim J. Robbins break; 44352e4a08cSMarcel Moolenaar xo_emit(f_notabs ? " " : "\t"); 4444b88c807SRodney W. Grimes chcnt = cnt; 4454b88c807SRodney W. Grimes } 4464b88c807SRodney W. Grimes endcol += colwidth; 4474b88c807SRodney W. Grimes } 44852e4a08cSMarcel Moolenaar xo_emit("\n"); 4494b88c807SRodney W. Grimes } 45052e4a08cSMarcel Moolenaar xo_close_list("entry"); 4514b88c807SRodney W. Grimes } 4524b88c807SRodney W. Grimes 4534b88c807SRodney W. Grimes /* 4544b88c807SRodney W. Grimes * print [inode] [size] name 4554b88c807SRodney W. Grimes * return # of characters printed, no trailing characters. 4564b88c807SRodney W. Grimes */ 4574b88c807SRodney W. Grimes static int 45840feca3aSMark Murray printaname(const FTSENT *p, u_long inodefield, u_long sizefield) 4594b88c807SRodney W. Grimes { 4604b88c807SRodney W. Grimes struct stat *sp; 4614b88c807SRodney W. Grimes int chcnt; 46247bb6b11SAndrey A. Chernov #ifdef COLORLS 46347bb6b11SAndrey A. Chernov int color_printed = 0; 46447bb6b11SAndrey A. Chernov #endif 4654b88c807SRodney W. Grimes 4664b88c807SRodney W. Grimes sp = p->fts_statp; 4674b88c807SRodney W. Grimes chcnt = 0; 4684b88c807SRodney W. Grimes if (f_inode) 469e5542be4SAllan Jude chcnt += xo_emit("{t:inode/%*ju} ", 4706db1a7f1SMatthew D Fleming (int)inodefield, (uintmax_t)sp->st_ino); 4714b88c807SRodney W. Grimes if (f_size) 472e5542be4SAllan Jude chcnt += xo_emit("{t:size/%*jd} ", 4734b88c807SRodney W. Grimes (int)sizefield, howmany(sp->st_blocks, blocksize)); 47474985094SJosef Karthauser #ifdef COLORLS 4753885812cSJosef Karthauser if (f_color) 476cf0feaeeSAndrey A. Chernov color_printed = colortype(sp->st_mode); 47774985094SJosef Karthauser #endif 47852e4a08cSMarcel Moolenaar chcnt += printname("name", p->fts_name); 47974985094SJosef Karthauser #ifdef COLORLS 480cf0feaeeSAndrey A. Chernov if (f_color && color_printed) 48138782c25SAndrey A. Chernov endcolor(0); 48274985094SJosef Karthauser #endif 4834b88c807SRodney W. Grimes if (f_type) 4844b88c807SRodney W. Grimes chcnt += printtype(sp->st_mode); 4854b88c807SRodney W. Grimes return (chcnt); 4864b88c807SRodney W. Grimes } 4874b88c807SRodney W. Grimes 48855926a66SJaakko Heinonen /* 48955926a66SJaakko Heinonen * Print device special file major and minor numbers. 49055926a66SJaakko Heinonen */ 49155926a66SJaakko Heinonen static void 49255926a66SJaakko Heinonen printdev(size_t width, dev_t dev) 49355926a66SJaakko Heinonen { 49452e4a08cSMarcel Moolenaar xo_emit("{:device/%#*jx} ", (u_int)width, (uintmax_t)dev); 49555926a66SJaakko Heinonen } 49655926a66SJaakko Heinonen 497*be90c1c6SBaptiste Daroussin static size_t 498*be90c1c6SBaptiste Daroussin ls_strftime(char *str, size_t len, const char *fmt, const struct tm *tm) 499*be90c1c6SBaptiste Daroussin { 500*be90c1c6SBaptiste Daroussin char *posb, nfmt[BUFSIZ]; 501*be90c1c6SBaptiste Daroussin const char *format = fmt; 502*be90c1c6SBaptiste Daroussin size_t ret; 503*be90c1c6SBaptiste Daroussin 504*be90c1c6SBaptiste Daroussin if ((posb = strstr(fmt, "%b")) != NULL) { 505*be90c1c6SBaptiste Daroussin if (month_max_size == 0) { 506*be90c1c6SBaptiste Daroussin compute_abbreviated_month_size(); 507*be90c1c6SBaptiste Daroussin } 508*be90c1c6SBaptiste Daroussin if (month_max_size > 0) { 509*be90c1c6SBaptiste Daroussin snprintf(nfmt, sizeof(nfmt), "%.*s%s%*s%s", 510*be90c1c6SBaptiste Daroussin (int)(posb - fmt), fmt, 511*be90c1c6SBaptiste Daroussin get_abmon(tm->tm_mon), 512*be90c1c6SBaptiste Daroussin (int)padding_for_month[tm->tm_mon], 513*be90c1c6SBaptiste Daroussin "", 514*be90c1c6SBaptiste Daroussin posb + 2); 515*be90c1c6SBaptiste Daroussin format = nfmt; 516*be90c1c6SBaptiste Daroussin } 517*be90c1c6SBaptiste Daroussin } 518*be90c1c6SBaptiste Daroussin ret = strftime(str, len, format, tm); 519*be90c1c6SBaptiste Daroussin return (ret); 520*be90c1c6SBaptiste Daroussin } 521*be90c1c6SBaptiste Daroussin 5224b88c807SRodney W. Grimes static void 52352e4a08cSMarcel Moolenaar printtime(const char *field, time_t ftime) 5244b88c807SRodney W. Grimes { 525fc4a9bafSAndrey A. Chernov char longstring[80]; 52652e4a08cSMarcel Moolenaar char fmt[BUFSIZ]; 52740feca3aSMark Murray static time_t now = 0; 52897e4e97bSJosef Karthauser const char *format; 5298234eb25SAndrey A. Chernov static int d_first = -1; 530f173abd0SMike Pritchard 53128fd017aSAndrey A. Chernov if (d_first < 0) 53228fd017aSAndrey A. Chernov d_first = (*nl_langinfo(D_MD_ORDER) == 'd'); 533f173abd0SMike Pritchard if (now == 0) 534f173abd0SMike Pritchard now = time(NULL); 5354b88c807SRodney W. Grimes 536656dcd43SGarrett Wollman #define SIXMONTHS ((365 / 2) * 86400) 5372269fa57SGreg Lehey if (f_timeformat) /* user specified format */ 5382269fa57SGreg Lehey format = f_timeformat; 5392269fa57SGreg Lehey else if (f_sectime) 5401e715e34SJosef Karthauser /* mmm dd hh:mm:ss yyyy || dd mmm hh:mm:ss yyyy */ 54128fd017aSAndrey A. Chernov format = d_first ? "%e %b %T %Y" : "%b %e %T %Y"; 542f173abd0SMike Pritchard else if (ftime + SIXMONTHS > now && ftime < now + SIXMONTHS) 5431e715e34SJosef Karthauser /* mmm dd hh:mm || dd mmm hh:mm */ 54428fd017aSAndrey A. Chernov format = d_first ? "%e %b %R" : "%b %e %R"; 54597e4e97bSJosef Karthauser else 5461e715e34SJosef Karthauser /* mmm dd yyyy || dd mmm yyyy */ 54728fd017aSAndrey A. Chernov format = d_first ? "%e %b %Y" : "%b %e %Y"; 548*be90c1c6SBaptiste Daroussin ls_strftime(longstring, sizeof(longstring), format, localtime(&ftime)); 54952e4a08cSMarcel Moolenaar 550e5542be4SAllan Jude snprintf(fmt, sizeof(fmt), "{d:%s/%%hs} ", field); 55152e4a08cSMarcel Moolenaar xo_attr("value", "%ld", (long) ftime); 55252e4a08cSMarcel Moolenaar xo_emit(fmt, longstring); 553e5542be4SAllan Jude snprintf(fmt, sizeof(fmt), "{en:%s/%%ld}", field); 554e5542be4SAllan Jude xo_emit(fmt, (long) ftime); 5554b88c807SRodney W. Grimes } 5564b88c807SRodney W. Grimes 5574b88c807SRodney W. Grimes static int 55846251ddeSWarner Losh printtype(u_int mode) 5594b88c807SRodney W. Grimes { 56094274c73STim J. Robbins 56194274c73STim J. Robbins if (f_slash) { 56294274c73STim J. Robbins if ((mode & S_IFMT) == S_IFDIR) { 56352e4a08cSMarcel Moolenaar xo_emit("{D:\\/}{e:type/directory}"); 56494274c73STim J. Robbins return (1); 56594274c73STim J. Robbins } 56694274c73STim J. Robbins return (0); 56794274c73STim J. Robbins } 56894274c73STim J. Robbins 5694b88c807SRodney W. Grimes switch (mode & S_IFMT) { 5704b88c807SRodney W. Grimes case S_IFDIR: 57152e4a08cSMarcel Moolenaar xo_emit("{D:/\\/}{e:type/directory}"); 5724b88c807SRodney W. Grimes return (1); 5734b88c807SRodney W. Grimes case S_IFIFO: 57452e4a08cSMarcel Moolenaar xo_emit("{D:|}{e:type/fifo}"); 5754b88c807SRodney W. Grimes return (1); 5764b88c807SRodney W. Grimes case S_IFLNK: 57752e4a08cSMarcel Moolenaar xo_emit("{D:@}{e:type/link}"); 5784b88c807SRodney W. Grimes return (1); 5794b88c807SRodney W. Grimes case S_IFSOCK: 58052e4a08cSMarcel Moolenaar xo_emit("{D:=}{e:type/socket}"); 5814b88c807SRodney W. Grimes return (1); 582fb5cb208SSteve Price case S_IFWHT: 583e9eed90cSAllan Jude xo_emit("{D:%%}{e:type/whiteout}"); 584fb5cb208SSteve Price return (1); 5859052855aSMark Murray default: 586568dcd5fSBill Fumerola break; 5874b88c807SRodney W. Grimes } 5884b88c807SRodney W. Grimes if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) { 58952e4a08cSMarcel Moolenaar xo_emit("{D:*}{e:executable/}"); 5904b88c807SRodney W. Grimes return (1); 5914b88c807SRodney W. Grimes } 5924b88c807SRodney W. Grimes return (0); 5934b88c807SRodney W. Grimes } 5944b88c807SRodney W. Grimes 59574985094SJosef Karthauser #ifdef COLORLS 5961bf1478aSAndrey A. Chernov static int 59746251ddeSWarner Losh putch(int c) 598cf0feaeeSAndrey A. Chernov { 59952e4a08cSMarcel Moolenaar xo_emit("{D:/%c}", c); 60038782c25SAndrey A. Chernov return 0; 601cf0feaeeSAndrey A. Chernov } 602cf0feaeeSAndrey A. Chernov 6031bf1478aSAndrey A. Chernov static int 60446251ddeSWarner Losh writech(int c) 60538782c25SAndrey A. Chernov { 60640feca3aSMark Murray char tmp = (char)c; 60738782c25SAndrey A. Chernov 60838782c25SAndrey A. Chernov (void)write(STDOUT_FILENO, &tmp, 1); 60938782c25SAndrey A. Chernov return 0; 61038782c25SAndrey A. Chernov } 611cf0feaeeSAndrey A. Chernov 6121bf1478aSAndrey A. Chernov static void 61346251ddeSWarner Losh printcolor(Colors c) 6143885812cSJosef Karthauser { 61574985094SJosef Karthauser char *ansiseq; 61674985094SJosef Karthauser 617c1499cf6SJosef Karthauser if (colors[c].bold) 618c1499cf6SJosef Karthauser tputs(enter_bold, 1, putch); 619c1499cf6SJosef Karthauser 620c1499cf6SJosef Karthauser if (colors[c].num[0] != -1) { 621c1499cf6SJosef Karthauser ansiseq = tgoto(ansi_fgcol, 0, colors[c].num[0]); 62238782c25SAndrey A. Chernov if (ansiseq) 623cf0feaeeSAndrey A. Chernov tputs(ansiseq, 1, putch); 6243885812cSJosef Karthauser } 625c1499cf6SJosef Karthauser if (colors[c].num[1] != -1) { 626c1499cf6SJosef Karthauser ansiseq = tgoto(ansi_bgcol, 0, colors[c].num[1]); 62738782c25SAndrey A. Chernov if (ansiseq) 628cf0feaeeSAndrey A. Chernov tputs(ansiseq, 1, putch); 62974985094SJosef Karthauser } 63074985094SJosef Karthauser } 63174985094SJosef Karthauser 63238782c25SAndrey A. Chernov static void 63346251ddeSWarner Losh endcolor(int sig) 63474985094SJosef Karthauser { 63538782c25SAndrey A. Chernov tputs(ansi_coloff, 1, sig ? writech : putch); 636c1499cf6SJosef Karthauser tputs(attrs_off, 1, sig ? writech : putch); 6373885812cSJosef Karthauser } 6383885812cSJosef Karthauser 63938782c25SAndrey A. Chernov static int 64046251ddeSWarner Losh colortype(mode_t mode) 6413885812cSJosef Karthauser { 6423885812cSJosef Karthauser switch (mode & S_IFMT) { 6433885812cSJosef Karthauser case S_IFDIR: 6443885812cSJosef Karthauser if (mode & S_IWOTH) 6453885812cSJosef Karthauser if (mode & S_ISTXT) 6463885812cSJosef Karthauser printcolor(C_WSDIR); 6473885812cSJosef Karthauser else 6483885812cSJosef Karthauser printcolor(C_WDIR); 6493885812cSJosef Karthauser else 6503885812cSJosef Karthauser printcolor(C_DIR); 6513885812cSJosef Karthauser return (1); 6523885812cSJosef Karthauser case S_IFLNK: 6533885812cSJosef Karthauser printcolor(C_LNK); 6543885812cSJosef Karthauser return (1); 6553885812cSJosef Karthauser case S_IFSOCK: 6563885812cSJosef Karthauser printcolor(C_SOCK); 6573885812cSJosef Karthauser return (1); 6583885812cSJosef Karthauser case S_IFIFO: 6593885812cSJosef Karthauser printcolor(C_FIFO); 6603885812cSJosef Karthauser return (1); 6613885812cSJosef Karthauser case S_IFBLK: 6623885812cSJosef Karthauser printcolor(C_BLK); 6633885812cSJosef Karthauser return (1); 6643885812cSJosef Karthauser case S_IFCHR: 6653885812cSJosef Karthauser printcolor(C_CHR); 6663885812cSJosef Karthauser return (1); 66740feca3aSMark Murray default:; 6683885812cSJosef Karthauser } 6693885812cSJosef Karthauser if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) { 6703885812cSJosef Karthauser if (mode & S_ISUID) 6713885812cSJosef Karthauser printcolor(C_SUID); 6723885812cSJosef Karthauser else if (mode & S_ISGID) 6733885812cSJosef Karthauser printcolor(C_SGID); 6743885812cSJosef Karthauser else 6753885812cSJosef Karthauser printcolor(C_EXEC); 6763885812cSJosef Karthauser return (1); 6773885812cSJosef Karthauser } 6783885812cSJosef Karthauser return (0); 6793885812cSJosef Karthauser } 6803885812cSJosef Karthauser 6813885812cSJosef Karthauser void 68246251ddeSWarner Losh parsecolors(const char *cs) 6833885812cSJosef Karthauser { 684b0bc91e9SJosef Karthauser int i; 685b0bc91e9SJosef Karthauser int j; 686ca2993fbSMark Murray size_t len; 6873885812cSJosef Karthauser char c[2]; 688c1499cf6SJosef Karthauser short legacy_warn = 0; 68938782c25SAndrey A. Chernov 690b0bc91e9SJosef Karthauser if (cs == NULL) 691b0bc91e9SJosef Karthauser cs = ""; /* LSCOLORS not set */ 6923885812cSJosef Karthauser len = strlen(cs); 69340feca3aSMark Murray for (i = 0; i < (int)C_NUMCOLORS; i++) { 694c1499cf6SJosef Karthauser colors[i].bold = 0; 695c1499cf6SJosef Karthauser 69640feca3aSMark Murray if (len <= 2 * (size_t)i) { 6973885812cSJosef Karthauser c[0] = defcolors[2 * i]; 6983885812cSJosef Karthauser c[1] = defcolors[2 * i + 1]; 6995dda5d0dSJosef Karthauser } else { 7003885812cSJosef Karthauser c[0] = cs[2 * i]; 7013885812cSJosef Karthauser c[1] = cs[2 * i + 1]; 7023885812cSJosef Karthauser } 7033885812cSJosef Karthauser for (j = 0; j < 2; j++) { 704c1499cf6SJosef Karthauser /* Legacy colours used 0-7 */ 705c1499cf6SJosef Karthauser if (c[j] >= '0' && c[j] <= '7') { 706c1499cf6SJosef Karthauser colors[i].num[j] = c[j] - '0'; 707c1499cf6SJosef Karthauser if (!legacy_warn) { 70852e4a08cSMarcel Moolenaar xo_warnx("LSCOLORS should use " 709130d15dcSJosef Karthauser "characters a-h instead of 0-9 (" 710e09fdabdSTim J. Robbins "see the manual page)"); 7113885812cSJosef Karthauser } 712c1499cf6SJosef Karthauser legacy_warn = 1; 713c1499cf6SJosef Karthauser } else if (c[j] >= 'a' && c[j] <= 'h') 714c1499cf6SJosef Karthauser colors[i].num[j] = c[j] - 'a'; 715c1499cf6SJosef Karthauser else if (c[j] >= 'A' && c[j] <= 'H') { 716c1499cf6SJosef Karthauser colors[i].num[j] = c[j] - 'A'; 717c1499cf6SJosef Karthauser colors[i].bold = 1; 71840feca3aSMark Murray } else if (tolower((unsigned char)c[j]) == 'x') 719c1499cf6SJosef Karthauser colors[i].num[j] = -1; 720c1499cf6SJosef Karthauser else { 72152e4a08cSMarcel Moolenaar xo_warnx("invalid character '%c' in LSCOLORS" 722e09fdabdSTim J. Robbins " env var", c[j]); 7230d72516eSJosef Karthauser colors[i].num[j] = -1; 724c1499cf6SJosef Karthauser } 7253885812cSJosef Karthauser } 7263885812cSJosef Karthauser } 7273885812cSJosef Karthauser } 728cf0feaeeSAndrey A. Chernov 7291bf1478aSAndrey A. Chernov void 73046251ddeSWarner Losh colorquit(int sig) 731cf0feaeeSAndrey A. Chernov { 73238782c25SAndrey A. Chernov endcolor(sig); 733faebfe2eSAndrey A. Chernov 734faebfe2eSAndrey A. Chernov (void)signal(sig, SIG_DFL); 735faebfe2eSAndrey A. Chernov (void)kill(getpid(), sig); 736cf0feaeeSAndrey A. Chernov } 7375dda5d0dSJosef Karthauser 73874985094SJosef Karthauser #endif /* COLORLS */ 7393885812cSJosef Karthauser 7404b88c807SRodney W. Grimes static void 741ca2993fbSMark Murray printlink(const FTSENT *p) 7424b88c807SRodney W. Grimes { 7434b88c807SRodney W. Grimes int lnklen; 744b0bc91e9SJosef Karthauser char name[MAXPATHLEN + 1]; 745b0bc91e9SJosef Karthauser char path[MAXPATHLEN + 1]; 7464b88c807SRodney W. Grimes 7474b88c807SRodney W. Grimes if (p->fts_level == FTS_ROOTLEVEL) 7484b88c807SRodney W. Grimes (void)snprintf(name, sizeof(name), "%s", p->fts_name); 7494b88c807SRodney W. Grimes else 7504b88c807SRodney W. Grimes (void)snprintf(name, sizeof(name), 7514b88c807SRodney W. Grimes "%s/%s", p->fts_parent->fts_accpath, p->fts_name); 7524b88c807SRodney W. Grimes if ((lnklen = readlink(name, path, sizeof(path) - 1)) == -1) { 75352e4a08cSMarcel Moolenaar xo_error("\nls: %s: %s\n", name, strerror(errno)); 7544b88c807SRodney W. Grimes return; 7554b88c807SRodney W. Grimes } 7564b88c807SRodney W. Grimes path[lnklen] = '\0'; 75752e4a08cSMarcel Moolenaar xo_emit(" -> "); 75852e4a08cSMarcel Moolenaar (void)printname("target", path); 7594b88c807SRodney W. Grimes } 7600e8d1551SJosef Karthauser 7610e8d1551SJosef Karthauser static void 76252e4a08cSMarcel Moolenaar printsize(const char *field, size_t width, off_t bytes) 7630e8d1551SJosef Karthauser { 76452e4a08cSMarcel Moolenaar char fmt[BUFSIZ]; 7650e8d1551SJosef Karthauser 7660e8d1551SJosef Karthauser if (f_humanval) { 76755926a66SJaakko Heinonen /* 76855926a66SJaakko Heinonen * Reserve one space before the size and allocate room for 76955926a66SJaakko Heinonen * the trailing '\0'. 77055926a66SJaakko Heinonen */ 77155926a66SJaakko Heinonen char buf[HUMANVALSTR_LEN - 1 + 1]; 7720e8d1551SJosef Karthauser 773478aa805SPawel Jakub Dawidek humanize_number(buf, sizeof(buf), (int64_t)bytes, "", 774478aa805SPawel Jakub Dawidek HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL); 77552e4a08cSMarcel Moolenaar snprintf(fmt, sizeof(fmt), "{:%s/%%%ds} ", field, (int) width); 77652e4a08cSMarcel Moolenaar xo_attr("value", "%jd", (intmax_t) bytes); 77752e4a08cSMarcel Moolenaar xo_emit(fmt, buf); 77852e4a08cSMarcel Moolenaar } else { /* with commas */ 7799aa68a3fSGreg Lehey /* This format assignment needed to work round gcc bug. */ 78052e4a08cSMarcel Moolenaar snprintf(fmt, sizeof(fmt), "{:%s/%%%dj%sd} ", 78152e4a08cSMarcel Moolenaar field, (int) width, f_thousands ? "'" : ""); 78252e4a08cSMarcel Moolenaar xo_emit(fmt, (intmax_t) bytes); 78352e4a08cSMarcel Moolenaar } 7840e8d1551SJosef Karthauser } 7850e8d1551SJosef Karthauser 786dd9aaeb0STim J. Robbins /* 787dd9aaeb0STim J. Robbins * Add a + after the standard rwxrwxrwx mode if the file has an 788f7b8687aSEdward Tomasz Napierala * ACL. strmode() reserves space at the end of the string. 789dd9aaeb0STim J. Robbins */ 790f7b8687aSEdward Tomasz Napierala static void 791f7b8687aSEdward Tomasz Napierala aclmode(char *buf, const FTSENT *p) 792f7b8687aSEdward Tomasz Napierala { 793f7b8687aSEdward Tomasz Napierala char name[MAXPATHLEN + 1]; 794f7b8687aSEdward Tomasz Napierala int ret, trivial; 795f7b8687aSEdward Tomasz Napierala static dev_t previous_dev = NODEV; 796f7b8687aSEdward Tomasz Napierala static int supports_acls = -1; 797f7b8687aSEdward Tomasz Napierala static int type = ACL_TYPE_ACCESS; 798f7b8687aSEdward Tomasz Napierala acl_t facl; 799f7b8687aSEdward Tomasz Napierala 800f7b8687aSEdward Tomasz Napierala /* 801f7b8687aSEdward Tomasz Napierala * XXX: ACLs are not supported on whiteouts and device files 802f7b8687aSEdward Tomasz Napierala * residing on UFS. 803f7b8687aSEdward Tomasz Napierala */ 804f7b8687aSEdward Tomasz Napierala if (S_ISCHR(p->fts_statp->st_mode) || S_ISBLK(p->fts_statp->st_mode) || 805f7b8687aSEdward Tomasz Napierala S_ISWHT(p->fts_statp->st_mode)) 806f7b8687aSEdward Tomasz Napierala return; 807f7b8687aSEdward Tomasz Napierala 808a3429262SEdward Tomasz Napierala if (previous_dev == p->fts_statp->st_dev && supports_acls == 0) 809a3429262SEdward Tomasz Napierala return; 810f7b8687aSEdward Tomasz Napierala 811dd9aaeb0STim J. Robbins if (p->fts_level == FTS_ROOTLEVEL) 812dd9aaeb0STim J. Robbins snprintf(name, sizeof(name), "%s", p->fts_name); 813dd9aaeb0STim J. Robbins else 814dd9aaeb0STim J. Robbins snprintf(name, sizeof(name), "%s/%s", 815dd9aaeb0STim J. Robbins p->fts_parent->fts_accpath, p->fts_name); 816a3429262SEdward Tomasz Napierala 817a3429262SEdward Tomasz Napierala if (previous_dev != p->fts_statp->st_dev) { 818a3429262SEdward Tomasz Napierala previous_dev = p->fts_statp->st_dev; 819a3429262SEdward Tomasz Napierala supports_acls = 0; 820a3429262SEdward Tomasz Napierala 821f7b8687aSEdward Tomasz Napierala ret = lpathconf(name, _PC_ACL_NFS4); 822f7b8687aSEdward Tomasz Napierala if (ret > 0) { 823f7b8687aSEdward Tomasz Napierala type = ACL_TYPE_NFS4; 824f7b8687aSEdward Tomasz Napierala supports_acls = 1; 825f7b8687aSEdward Tomasz Napierala } else if (ret < 0 && errno != EINVAL) { 82652e4a08cSMarcel Moolenaar xo_warn("%s", name); 827dd9aaeb0STim J. Robbins return; 828dd9aaeb0STim J. Robbins } 829f7b8687aSEdward Tomasz Napierala if (supports_acls == 0) { 830f7b8687aSEdward Tomasz Napierala ret = lpathconf(name, _PC_ACL_EXTENDED); 831f7b8687aSEdward Tomasz Napierala if (ret > 0) { 832f7b8687aSEdward Tomasz Napierala type = ACL_TYPE_ACCESS; 833f7b8687aSEdward Tomasz Napierala supports_acls = 1; 834f7b8687aSEdward Tomasz Napierala } else if (ret < 0 && errno != EINVAL) { 83552e4a08cSMarcel Moolenaar xo_warn("%s", name); 836f7b8687aSEdward Tomasz Napierala return; 837dd9aaeb0STim J. Robbins } 838f7b8687aSEdward Tomasz Napierala } 839f7b8687aSEdward Tomasz Napierala } 840f7b8687aSEdward Tomasz Napierala if (supports_acls == 0) 841f7b8687aSEdward Tomasz Napierala return; 842f7b8687aSEdward Tomasz Napierala facl = acl_get_link_np(name, type); 843f7b8687aSEdward Tomasz Napierala if (facl == NULL) { 84452e4a08cSMarcel Moolenaar xo_warn("%s", name); 845f7b8687aSEdward Tomasz Napierala return; 846f7b8687aSEdward Tomasz Napierala } 847f7b8687aSEdward Tomasz Napierala if (acl_is_trivial_np(facl, &trivial)) { 848dd9aaeb0STim J. Robbins acl_free(facl); 84952e4a08cSMarcel Moolenaar xo_warn("%s", name); 850f7b8687aSEdward Tomasz Napierala return; 851f7b8687aSEdward Tomasz Napierala } 852f7b8687aSEdward Tomasz Napierala if (!trivial) 853f7b8687aSEdward Tomasz Napierala buf[10] = '+'; 854f7b8687aSEdward Tomasz Napierala acl_free(facl); 855dd9aaeb0STim J. Robbins } 856