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 334b88c807SRodney W. Grimes #ifndef lint 34d46c1a60SSteve Price static const char copyright[] = 354b88c807SRodney W. Grimes "@(#) Copyright (c) 1989, 1993, 1994\n\ 364b88c807SRodney W. Grimes The Regents of the University of California. All rights reserved.\n"; 37febad2fcSSteve Price #endif /* not lint */ 38febad2fcSSteve Price 39febad2fcSSteve Price #if 0 40c73d77ceSMark Murray #ifndef lint 41febad2fcSSteve Price static char sccsid[] = "@(#)ls.c 8.5 (Berkeley) 4/2/94"; 424b88c807SRodney W. Grimes #endif /* not lint */ 43c73d77ceSMark Murray #endif 445eb43ac2SDavid E. O'Brien #include <sys/cdefs.h> 455eb43ac2SDavid E. O'Brien __FBSDID("$FreeBSD$"); 464b88c807SRodney W. Grimes 474b88c807SRodney W. Grimes #include <sys/types.h> 484b88c807SRodney W. Grimes #include <sys/stat.h> 494b88c807SRodney W. Grimes #include <sys/ioctl.h> 504d33b62eSRobert Watson #include <sys/mac.h> 514b88c807SRodney W. Grimes 524b88c807SRodney W. Grimes #include <dirent.h> 534b88c807SRodney W. Grimes #include <err.h> 544b88c807SRodney W. Grimes #include <errno.h> 554b88c807SRodney W. Grimes #include <fts.h> 56576541a9SWarner Losh #include <grp.h> 5740feca3aSMark Murray #include <inttypes.h> 58008a4910SSheldon Hearn #include <limits.h> 59008a4910SSheldon Hearn #include <locale.h> 60576541a9SWarner Losh #include <pwd.h> 614b88c807SRodney W. Grimes #include <stdio.h> 624b88c807SRodney W. Grimes #include <stdlib.h> 634b88c807SRodney W. Grimes #include <string.h> 644b88c807SRodney W. Grimes #include <unistd.h> 65bd82d8abSAndrey A. Chernov #ifdef COLORLS 66bd82d8abSAndrey A. Chernov #include <termcap.h> 67bd82d8abSAndrey A. Chernov #include <signal.h> 68bd82d8abSAndrey A. Chernov #endif 694b88c807SRodney W. Grimes 704b88c807SRodney W. Grimes #include "ls.h" 714b88c807SRodney W. Grimes #include "extern.h" 724b88c807SRodney W. Grimes 73008a4910SSheldon Hearn /* 74008a4910SSheldon Hearn * Upward approximation of the maximum number of characters needed to 75008a4910SSheldon Hearn * represent a value of integral type t as a string, excluding the 76008a4910SSheldon Hearn * NUL terminator, with provision for a sign. 77008a4910SSheldon Hearn */ 781f94b779SSheldon Hearn #define STRBUF_SIZEOF(t) (1 + CHAR_BIT * sizeof(t) / 3 + 1) 79008a4910SSheldon Hearn 8040feca3aSMark Murray /* 8140feca3aSMark Murray * MAKENINES(n) turns n into (10**n)-1. This is useful for converting a width 8240feca3aSMark Murray * into a number that wide in decimal. 8340feca3aSMark Murray * XXX: Overflows are not considered. 8440feca3aSMark Murray */ 8540feca3aSMark Murray #define MAKENINES(n) \ 8640feca3aSMark Murray do { \ 8740feca3aSMark Murray intmax_t i; \ 8840feca3aSMark Murray \ 8940feca3aSMark Murray /* Use a loop as all values of n are small. */ \ 9040feca3aSMark Murray for (i = 1; n > 0; i *= 10) \ 9140feca3aSMark Murray n--; \ 9240feca3aSMark Murray n = i - 1; \ 9340feca3aSMark Murray } while(0) 9440feca3aSMark Murray 9540feca3aSMark Murray static void display(const FTSENT *, FTSENT *, int); 960d3bcc2eSGarrett Wollman static int mastercmp(const FTSENT * const *, const FTSENT * const *); 9746251ddeSWarner Losh static void traverse(int, char **, int); 984b88c807SRodney W. Grimes 9940feca3aSMark Murray static void (*printfcn)(const DISPLAY *); 10046251ddeSWarner Losh static int (*sortfcn)(const FTSENT *, const FTSENT *); 1014b88c807SRodney W. Grimes 1024b88c807SRodney W. Grimes long blocksize; /* block size units */ 1034b88c807SRodney W. Grimes int termwidth = 80; /* default terminal width */ 1044b88c807SRodney W. Grimes 1054b88c807SRodney W. Grimes /* flags */ 1064b88c807SRodney W. Grimes int f_accesstime; /* use time of last access */ 1074b88c807SRodney W. Grimes int f_flags; /* show flags associated with a file */ 1080e8d1551SJosef Karthauser int f_humanval; /* show human-readable file sizes */ 1094b88c807SRodney W. Grimes int f_inode; /* print inode */ 1109052855aSMark Murray static int f_kblocks; /* print size in kilobytes */ 1119052855aSMark Murray static int f_listdir; /* list actual directory, not contents */ 1129052855aSMark Murray static int f_listdot; /* list files beginning with . */ 1134b88c807SRodney W. Grimes int f_longform; /* long listing format */ 1144b88c807SRodney W. Grimes int f_nonprint; /* show unprintables as ? */ 1159052855aSMark Murray static int f_nosort; /* don't sort output */ 116008a4910SSheldon Hearn int f_notabs; /* don't use tab-separated multi-col output */ 1179052855aSMark Murray static int f_numericonly; /* don't convert uid/gid to name */ 1187ea30648SDag-Erling Smørgrav int f_octal; /* show unprintables as \xxx */ 1190d86878cSDag-Erling Smørgrav int f_octal_escape; /* like f_octal but use C escapes if possible */ 1209052855aSMark Murray static int f_recursive; /* ls subdirectories also */ 1219052855aSMark Murray static int f_reversesort; /* reverse whatever sort is used */ 1224b88c807SRodney W. Grimes int f_sectime; /* print the real time for all files */ 1239052855aSMark Murray static int f_singlecol; /* use single column output */ 1244b88c807SRodney W. Grimes int f_size; /* list size in short listing */ 12594274c73STim J. Robbins int f_slash; /* similar to f_type, but only for dirs */ 12694274c73STim J. Robbins int f_sortacross; /* sort across rows, not down columns */ 1274b88c807SRodney W. Grimes int f_statustime; /* use time of last mode change */ 12840feca3aSMark Murray static int f_stream; /* stream the output, separate with commas */ 1299052855aSMark Murray static int f_timesort; /* sort by time vice name */ 13071b8b748SDima Dorfman static int f_sizesort; 1314b88c807SRodney W. Grimes int f_type; /* add type character for non-regular files */ 1329052855aSMark Murray static int f_whiteout; /* show whiteout entries */ 1334d33b62eSRobert Watson int f_label; /* show MAC label */ 13474985094SJosef Karthauser #ifdef COLORLS 1353885812cSJosef Karthauser int f_color; /* add type in color for non-regular files */ 1365a890e22SJosef Karthauser 1375a890e22SJosef Karthauser char *ansi_bgcol; /* ANSI sequence to set background colour */ 1385a890e22SJosef Karthauser char *ansi_fgcol; /* ANSI sequence to set foreground colour */ 1395a890e22SJosef Karthauser char *ansi_coloff; /* ANSI sequence to reset colours */ 140c1499cf6SJosef Karthauser char *attrs_off; /* ANSI sequence to turn off attributes */ 141c1499cf6SJosef Karthauser char *enter_bold; /* ANSI sequence to set color to bold mode */ 14274985094SJosef Karthauser #endif 1434b88c807SRodney W. Grimes 1449052855aSMark Murray static int rval; 145fb1000d6SAdam David 1464b88c807SRodney W. Grimes int 14746251ddeSWarner Losh main(int argc, char *argv[]) 1484b88c807SRodney W. Grimes { 1494b88c807SRodney W. Grimes static char dot[] = ".", *dotav[] = {dot, NULL}; 1504b88c807SRodney W. Grimes struct winsize win; 1514b88c807SRodney W. Grimes int ch, fts_options, notused; 1524b88c807SRodney W. Grimes char *p; 1535a890e22SJosef Karthauser #ifdef COLORLS 1545a890e22SJosef Karthauser char termcapbuf[1024]; /* termcap definition buffer */ 1555a890e22SJosef Karthauser char tcapbuf[512]; /* capability buffer */ 1565a890e22SJosef Karthauser char *bp = tcapbuf; 1575a890e22SJosef Karthauser #endif 1585a890e22SJosef Karthauser 159f5bd01c6SAndrey A. Chernov (void)setlocale(LC_ALL, ""); 160f5bd01c6SAndrey A. Chernov 1614b88c807SRodney W. Grimes /* Terminal defaults to -Cq, non-terminal defaults to -1. */ 1624b88c807SRodney W. Grimes if (isatty(STDOUT_FILENO)) { 163a28edf9aSTim J. Robbins termwidth = 80; 164a28edf9aSTim J. Robbins if ((p = getenv("COLUMNS")) != NULL && *p != '\0') 1654b88c807SRodney W. Grimes termwidth = atoi(p); 166a28edf9aSTim J. Robbins else if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &win) != -1 && 167a28edf9aSTim J. Robbins win.ws_col > 0) 1684b88c807SRodney W. Grimes termwidth = win.ws_col; 1699052855aSMark Murray f_nonprint = 1; 17034994fcdSJoerg Wunsch } else { 1714b88c807SRodney W. Grimes f_singlecol = 1; 17234994fcdSJoerg Wunsch /* retrieve environment variable, in case of explicit -C */ 1739052855aSMark Murray p = getenv("COLUMNS"); 1749052855aSMark Murray if (p) 17534994fcdSJoerg Wunsch termwidth = atoi(p); 17634994fcdSJoerg Wunsch } 1774b88c807SRodney W. Grimes 1784b88c807SRodney W. Grimes /* Root is -A automatically. */ 1794b88c807SRodney W. Grimes if (!getuid()) 1804b88c807SRodney W. Grimes f_listdot = 1; 1814b88c807SRodney W. Grimes 1824b88c807SRodney W. Grimes fts_options = FTS_PHYSICAL; 18371b8b748SDima Dorfman while ((ch = getopt(argc, argv, 18471b8b748SDima Dorfman "1ABCFGHLPRSTWZabcdfghiklmnopqrstuwx")) != -1) { 1854b88c807SRodney W. Grimes switch (ch) { 1864b88c807SRodney W. Grimes /* 18794274c73STim J. Robbins * The -1, -C, -x and -l options all override each other so 18894274c73STim J. Robbins * shell aliasing works right. 1894b88c807SRodney W. Grimes */ 1904b88c807SRodney W. Grimes case '1': 1914b88c807SRodney W. Grimes f_singlecol = 1; 1929052855aSMark Murray f_longform = 0; 19394274c73STim J. Robbins f_stream = 0; 1944b88c807SRodney W. Grimes break; 1950d86878cSDag-Erling Smørgrav case 'B': 1960d86878cSDag-Erling Smørgrav f_nonprint = 0; 1970d86878cSDag-Erling Smørgrav f_octal = 1; 1980d86878cSDag-Erling Smørgrav f_octal_escape = 0; 1990d86878cSDag-Erling Smørgrav break; 2004b88c807SRodney W. Grimes case 'C': 20194274c73STim J. Robbins f_sortacross = f_longform = f_singlecol = 0; 2024b88c807SRodney W. Grimes break; 2034b88c807SRodney W. Grimes case 'l': 2044b88c807SRodney W. Grimes f_longform = 1; 2059052855aSMark Murray f_singlecol = 0; 20694274c73STim J. Robbins f_stream = 0; 20794274c73STim J. Robbins break; 20894274c73STim J. Robbins case 'x': 20994274c73STim J. Robbins f_sortacross = 1; 21094274c73STim J. Robbins f_longform = 0; 21194274c73STim J. Robbins f_singlecol = 0; 2124b88c807SRodney W. Grimes break; 2134b88c807SRodney W. Grimes /* The -c and -u options override each other. */ 2144b88c807SRodney W. Grimes case 'c': 2154b88c807SRodney W. Grimes f_statustime = 1; 2164b88c807SRodney W. Grimes f_accesstime = 0; 2174b88c807SRodney W. Grimes break; 2184b88c807SRodney W. Grimes case 'u': 2194b88c807SRodney W. Grimes f_accesstime = 1; 2204b88c807SRodney W. Grimes f_statustime = 0; 2214b88c807SRodney W. Grimes break; 2224b88c807SRodney W. Grimes case 'F': 2234b88c807SRodney W. Grimes f_type = 1; 22494274c73STim J. Robbins f_slash = 0; 2254b88c807SRodney W. Grimes break; 2263a34dbf7SDag-Erling Smørgrav case 'H': 2273a34dbf7SDag-Erling Smørgrav fts_options |= FTS_COMFOLLOW; 2283a34dbf7SDag-Erling Smørgrav break; 2293885812cSJosef Karthauser case 'G': 2303d2ddc9eSJosef Karthauser setenv("CLICOLOR", "", 1); 2313885812cSJosef Karthauser break; 2324b88c807SRodney W. Grimes case 'L': 2334b88c807SRodney W. Grimes fts_options &= ~FTS_PHYSICAL; 2344b88c807SRodney W. Grimes fts_options |= FTS_LOGICAL; 2354b88c807SRodney W. Grimes break; 2363a34dbf7SDag-Erling Smørgrav case 'P': 2373a34dbf7SDag-Erling Smørgrav fts_options &= ~FTS_COMFOLLOW; 2383a34dbf7SDag-Erling Smørgrav fts_options &= ~FTS_LOGICAL; 2393a34dbf7SDag-Erling Smørgrav fts_options |= FTS_PHYSICAL; 2403a34dbf7SDag-Erling Smørgrav break; 2414b88c807SRodney W. Grimes case 'R': 2424b88c807SRodney W. Grimes f_recursive = 1; 2434b88c807SRodney W. Grimes break; 2444b88c807SRodney W. Grimes case 'a': 2454b88c807SRodney W. Grimes fts_options |= FTS_SEEDOT; 2464b88c807SRodney W. Grimes /* FALLTHROUGH */ 2474b88c807SRodney W. Grimes case 'A': 2484b88c807SRodney W. Grimes f_listdot = 1; 2494b88c807SRodney W. Grimes break; 2504b88c807SRodney W. Grimes /* The -d option turns off the -R option. */ 2514b88c807SRodney W. Grimes case 'd': 2524b88c807SRodney W. Grimes f_listdir = 1; 2534b88c807SRodney W. Grimes f_recursive = 0; 2544b88c807SRodney W. Grimes break; 2554b88c807SRodney W. Grimes case 'f': 2564b88c807SRodney W. Grimes f_nosort = 1; 2574b88c807SRodney W. Grimes break; 2584b88c807SRodney W. Grimes case 'g': /* Compatibility with 4.3BSD. */ 2594b88c807SRodney W. Grimes break; 2600e8d1551SJosef Karthauser case 'h': 2610e8d1551SJosef Karthauser f_humanval = 1; 2620e8d1551SJosef Karthauser break; 2634b88c807SRodney W. Grimes case 'i': 2644b88c807SRodney W. Grimes f_inode = 1; 2654b88c807SRodney W. Grimes break; 266475727a0SPaul Traina case 'k': 267d5f9f41cSDavid E. O'Brien f_humanval = 0; 268475727a0SPaul Traina f_kblocks = 1; 269475727a0SPaul Traina break; 27094274c73STim J. Robbins case 'm': 27194274c73STim J. Robbins f_stream = 1; 27294274c73STim J. Robbins f_singlecol = 0; 27394274c73STim J. Robbins f_longform = 0; 27494274c73STim J. Robbins break; 275f3a6a64eSSheldon Hearn case 'n': 276f3a6a64eSSheldon Hearn f_numericonly = 1; 277f3a6a64eSSheldon Hearn break; 2784b88c807SRodney W. Grimes case 'o': 2794b88c807SRodney W. Grimes f_flags = 1; 2804b88c807SRodney W. Grimes break; 28194274c73STim J. Robbins case 'p': 28294274c73STim J. Robbins f_slash = 1; 28394274c73STim J. Robbins f_type = 1; 28494274c73STim J. Robbins break; 2854b88c807SRodney W. Grimes case 'q': 2864b88c807SRodney W. Grimes f_nonprint = 1; 2877ea30648SDag-Erling Smørgrav f_octal = 0; 2880d86878cSDag-Erling Smørgrav f_octal_escape = 0; 2894b88c807SRodney W. Grimes break; 2904b88c807SRodney W. Grimes case 'r': 2914b88c807SRodney W. Grimes f_reversesort = 1; 2924b88c807SRodney W. Grimes break; 2934b88c807SRodney W. Grimes case 's': 2944b88c807SRodney W. Grimes f_size = 1; 2954b88c807SRodney W. Grimes break; 2964b88c807SRodney W. Grimes case 'T': 2974b88c807SRodney W. Grimes f_sectime = 1; 2984b88c807SRodney W. Grimes break; 2994b88c807SRodney W. Grimes case 't': 3004b88c807SRodney W. Grimes f_timesort = 1; 3014b88c807SRodney W. Grimes break; 30271b8b748SDima Dorfman case 'S': 30371b8b748SDima Dorfman f_sizesort = 1; 30471b8b748SDima Dorfman break; 305fb5cb208SSteve Price case 'W': 306fb5cb208SSteve Price f_whiteout = 1; 307fb5cb208SSteve Price break; 3087ea30648SDag-Erling Smørgrav case 'b': 3097ea30648SDag-Erling Smørgrav f_nonprint = 0; 3100d86878cSDag-Erling Smørgrav f_octal = 0; 3110d86878cSDag-Erling Smørgrav f_octal_escape = 1; 3127ea30648SDag-Erling Smørgrav break; 31347f884f0SJosef Karthauser case 'w': 31447f884f0SJosef Karthauser f_nonprint = 0; 31547f884f0SJosef Karthauser f_octal = 0; 31647f884f0SJosef Karthauser f_octal_escape = 0; 31747f884f0SJosef Karthauser break; 3187304f61fSBrian Feldman case 'Z': 3194d33b62eSRobert Watson f_label = 1; 3207304f61fSBrian Feldman break; 3214b88c807SRodney W. Grimes default: 3224b88c807SRodney W. Grimes case '?': 3234b88c807SRodney W. Grimes usage(); 3244b88c807SRodney W. Grimes } 3254b88c807SRodney W. Grimes } 3264b88c807SRodney W. Grimes argc -= optind; 3274b88c807SRodney W. Grimes argv += optind; 3284b88c807SRodney W. Grimes 3293d2ddc9eSJosef Karthauser /* Enabling of colours is conditional on the environment. */ 3303d2ddc9eSJosef Karthauser if (getenv("CLICOLOR") && 3313d2ddc9eSJosef Karthauser (isatty(STDOUT_FILENO) || getenv("CLICOLOR_FORCE"))) 332d4413063SJosef Karthauser #ifdef COLORLS 3333d2ddc9eSJosef Karthauser if (tgetent(termcapbuf, getenv("TERM")) == 1) { 3343d2ddc9eSJosef Karthauser ansi_fgcol = tgetstr("AF", &bp); 3353d2ddc9eSJosef Karthauser ansi_bgcol = tgetstr("AB", &bp); 336c1499cf6SJosef Karthauser attrs_off = tgetstr("me", &bp); 337c1499cf6SJosef Karthauser enter_bold = tgetstr("md", &bp); 3383d2ddc9eSJosef Karthauser 3393d2ddc9eSJosef Karthauser /* To switch colours off use 'op' if 3403d2ddc9eSJosef Karthauser * available, otherwise use 'oc', or 3413d2ddc9eSJosef Karthauser * don't do colours at all. */ 3423d2ddc9eSJosef Karthauser ansi_coloff = tgetstr("op", &bp); 3433d2ddc9eSJosef Karthauser if (!ansi_coloff) 3443d2ddc9eSJosef Karthauser ansi_coloff = tgetstr("oc", &bp); 3453d2ddc9eSJosef Karthauser if (ansi_fgcol && ansi_bgcol && ansi_coloff) 3463d2ddc9eSJosef Karthauser f_color = 1; 3473d2ddc9eSJosef Karthauser } 348d4413063SJosef Karthauser #else 349e09fdabdSTim J. Robbins warnx("color support not compiled in"); 350d4413063SJosef Karthauser #endif /*COLORLS*/ 3513d2ddc9eSJosef Karthauser 352d4413063SJosef Karthauser #ifdef COLORLS 353bd82d8abSAndrey A. Chernov if (f_color) { 35422ff3e9eSAndrey A. Chernov /* 35522ff3e9eSAndrey A. Chernov * We can't put tabs and color sequences together: 35622ff3e9eSAndrey A. Chernov * column number will be incremented incorrectly 35722ff3e9eSAndrey A. Chernov * for "stty oxtabs" mode. 35822ff3e9eSAndrey A. Chernov */ 35922ff3e9eSAndrey A. Chernov f_notabs = 1; 360bd82d8abSAndrey A. Chernov (void)signal(SIGINT, colorquit); 361ab08444fSMartin Cracauer (void)signal(SIGQUIT, colorquit); 3623885812cSJosef Karthauser parsecolors(getenv("LSCOLORS")); 363bd82d8abSAndrey A. Chernov } 36474985094SJosef Karthauser #endif 3653885812cSJosef Karthauser 3664b88c807SRodney W. Grimes /* 36771b8b748SDima Dorfman * If not -F, -i, -l, -s, -S or -t options, don't require stat 3683885812cSJosef Karthauser * information, unless in color mode in which case we do 3693885812cSJosef Karthauser * need this to determine which colors to display. 3704b88c807SRodney W. Grimes */ 37171b8b748SDima Dorfman if (!f_inode && !f_longform && !f_size && !f_timesort && 37271b8b748SDima Dorfman !f_sizesort && !f_type 37374985094SJosef Karthauser #ifdef COLORLS 37474985094SJosef Karthauser && !f_color 37574985094SJosef Karthauser #endif 37674985094SJosef Karthauser ) 3774b88c807SRodney W. Grimes fts_options |= FTS_NOSTAT; 3784b88c807SRodney W. Grimes 3794b88c807SRodney W. Grimes /* 3804b88c807SRodney W. Grimes * If not -F, -d or -l options, follow any symbolic links listed on 3814b88c807SRodney W. Grimes * the command line. 3824b88c807SRodney W. Grimes */ 3834b88c807SRodney W. Grimes if (!f_longform && !f_listdir && !f_type) 3844b88c807SRodney W. Grimes fts_options |= FTS_COMFOLLOW; 3854b88c807SRodney W. Grimes 386fb5cb208SSteve Price /* 387fb5cb208SSteve Price * If -W, show whiteout entries 388fb5cb208SSteve Price */ 389fb5cb208SSteve Price #ifdef FTS_WHITEOUT 390fb5cb208SSteve Price if (f_whiteout) 391fb5cb208SSteve Price fts_options |= FTS_WHITEOUT; 392fb5cb208SSteve Price #endif 393fb5cb208SSteve Price 3944b88c807SRodney W. Grimes /* If -l or -s, figure out block size. */ 3954b88c807SRodney W. Grimes if (f_longform || f_size) { 39690b0ec31SPoul-Henning Kamp if (f_kblocks) 39790b0ec31SPoul-Henning Kamp blocksize = 2; 39890b0ec31SPoul-Henning Kamp else { 3994b88c807SRodney W. Grimes (void)getbsize(¬used, &blocksize); 4004b88c807SRodney W. Grimes blocksize /= 512; 40190b0ec31SPoul-Henning Kamp } 4024b88c807SRodney W. Grimes } 4034b88c807SRodney W. Grimes /* Select a sort function. */ 4044b88c807SRodney W. Grimes if (f_reversesort) { 40571b8b748SDima Dorfman if (!f_timesort && !f_sizesort) 4064b88c807SRodney W. Grimes sortfcn = revnamecmp; 4074b88c807SRodney W. Grimes else if (f_accesstime) 4084b88c807SRodney W. Grimes sortfcn = revacccmp; 4094b88c807SRodney W. Grimes else if (f_statustime) 4104b88c807SRodney W. Grimes sortfcn = revstatcmp; 41171b8b748SDima Dorfman else if (f_sizesort) 41271b8b748SDima Dorfman sortfcn = revsizecmp; 4134b88c807SRodney W. Grimes else /* Use modification time. */ 4144b88c807SRodney W. Grimes sortfcn = revmodcmp; 4154b88c807SRodney W. Grimes } else { 41671b8b748SDima Dorfman if (!f_timesort && !f_sizesort) 4174b88c807SRodney W. Grimes sortfcn = namecmp; 4184b88c807SRodney W. Grimes else if (f_accesstime) 4194b88c807SRodney W. Grimes sortfcn = acccmp; 4204b88c807SRodney W. Grimes else if (f_statustime) 4214b88c807SRodney W. Grimes sortfcn = statcmp; 42271b8b748SDima Dorfman else if (f_sizesort) 42371b8b748SDima Dorfman sortfcn = sizecmp; 4244b88c807SRodney W. Grimes else /* Use modification time. */ 4254b88c807SRodney W. Grimes sortfcn = modcmp; 4264b88c807SRodney W. Grimes } 4274b88c807SRodney W. Grimes 4284b88c807SRodney W. Grimes /* Select a print function. */ 4294b88c807SRodney W. Grimes if (f_singlecol) 4304b88c807SRodney W. Grimes printfcn = printscol; 4314b88c807SRodney W. Grimes else if (f_longform) 4324b88c807SRodney W. Grimes printfcn = printlong; 43394274c73STim J. Robbins else if (f_stream) 43494274c73STim J. Robbins printfcn = printstream; 4354b88c807SRodney W. Grimes else 4364b88c807SRodney W. Grimes printfcn = printcol; 4374b88c807SRodney W. Grimes 4384b88c807SRodney W. Grimes if (argc) 4394b88c807SRodney W. Grimes traverse(argc, argv, fts_options); 4404b88c807SRodney W. Grimes else 4414b88c807SRodney W. Grimes traverse(1, dotav, fts_options); 442fb1000d6SAdam David exit(rval); 4434b88c807SRodney W. Grimes } 4444b88c807SRodney W. Grimes 4454b88c807SRodney W. Grimes static int output; /* If anything output. */ 4464b88c807SRodney W. Grimes 4474b88c807SRodney W. Grimes /* 4484b88c807SRodney W. Grimes * Traverse() walks the logical directory structure specified by the argv list 4494b88c807SRodney W. Grimes * in the order specified by the mastercmp() comparison function. During the 4504b88c807SRodney W. Grimes * traversal it passes linked lists of structures to display() which represent 4514b88c807SRodney W. Grimes * a superset (may be exact set) of the files to be displayed. 4524b88c807SRodney W. Grimes */ 4534b88c807SRodney W. Grimes static void 45446251ddeSWarner Losh traverse(int argc, char *argv[], int options) 4554b88c807SRodney W. Grimes { 4564b88c807SRodney W. Grimes FTS *ftsp; 4574b88c807SRodney W. Grimes FTSENT *p, *chp; 4584b88c807SRodney W. Grimes int ch_options; 4594b88c807SRodney W. Grimes 4604b88c807SRodney W. Grimes if ((ftsp = 4614b88c807SRodney W. Grimes fts_open(argv, options, f_nosort ? NULL : mastercmp)) == NULL) 4625ad9e45fSMatthew Dillon err(1, "fts_open"); 4634b88c807SRodney W. Grimes 46470bad4f7SDavid Schultz /* 46570bad4f7SDavid Schultz * We ignore errors from fts_children here since they will be 46670bad4f7SDavid Schultz * replicated and signalled on the next call to fts_read() below. 46770bad4f7SDavid Schultz */ 46870bad4f7SDavid Schultz chp = fts_children(ftsp, 0); 46970bad4f7SDavid Schultz if (chp != NULL) 47070bad4f7SDavid Schultz display(NULL, chp, options); 4714b88c807SRodney W. Grimes if (f_listdir) 4724b88c807SRodney W. Grimes return; 4734b88c807SRodney W. Grimes 4744b88c807SRodney W. Grimes /* 4754b88c807SRodney W. Grimes * If not recursing down this tree and don't need stat info, just get 4764b88c807SRodney W. Grimes * the names. 4774b88c807SRodney W. Grimes */ 4783c3f5f9cSRobert Watson ch_options = !f_recursive && !f_label && 4793c3f5f9cSRobert Watson options & FTS_NOSTAT ? FTS_NAMEONLY : 0; 4804b88c807SRodney W. Grimes 4814b88c807SRodney W. Grimes while ((p = fts_read(ftsp)) != NULL) 4824b88c807SRodney W. Grimes switch (p->fts_info) { 4834b88c807SRodney W. Grimes case FTS_DC: 4844b88c807SRodney W. Grimes warnx("%s: directory causes a cycle", p->fts_name); 4854b88c807SRodney W. Grimes break; 4864b88c807SRodney W. Grimes case FTS_DNR: 4874b88c807SRodney W. Grimes case FTS_ERR: 4884b88c807SRodney W. Grimes warnx("%s: %s", p->fts_name, strerror(p->fts_errno)); 489fb1000d6SAdam David rval = 1; 4904b88c807SRodney W. Grimes break; 4914b88c807SRodney W. Grimes case FTS_D: 4924b88c807SRodney W. Grimes if (p->fts_level != FTS_ROOTLEVEL && 4934b88c807SRodney W. Grimes p->fts_name[0] == '.' && !f_listdot) 4944b88c807SRodney W. Grimes break; 4954b88c807SRodney W. Grimes 4964b88c807SRodney W. Grimes /* 4974b88c807SRodney W. Grimes * If already output something, put out a newline as 4984b88c807SRodney W. Grimes * a separator. If multiple arguments, precede each 4994b88c807SRodney W. Grimes * directory with its name. 5004b88c807SRodney W. Grimes */ 5011656f850STim J. Robbins if (output) { 5021656f850STim J. Robbins putchar('\n'); 50340feca3aSMark Murray (void)printname(p->fts_path); 5041656f850STim J. Robbins puts(":"); 5051656f850STim J. Robbins } else if (argc > 1) { 50640feca3aSMark Murray (void)printname(p->fts_path); 5071656f850STim J. Robbins puts(":"); 5084b88c807SRodney W. Grimes output = 1; 5094b88c807SRodney W. Grimes } 5104b88c807SRodney W. Grimes chp = fts_children(ftsp, ch_options); 5114d33b62eSRobert Watson display(p, chp, options); 5124b88c807SRodney W. Grimes 5134b88c807SRodney W. Grimes if (!f_recursive && chp != NULL) 5144b88c807SRodney W. Grimes (void)fts_set(ftsp, p, FTS_SKIP); 5154b88c807SRodney W. Grimes break; 516568dcd5fSBill Fumerola default: 517568dcd5fSBill Fumerola break; 5184b88c807SRodney W. Grimes } 5194b88c807SRodney W. Grimes if (errno) 5204b88c807SRodney W. Grimes err(1, "fts_read"); 5214b88c807SRodney W. Grimes } 5224b88c807SRodney W. Grimes 5234b88c807SRodney W. Grimes /* 5244b88c807SRodney W. Grimes * Display() takes a linked list of FTSENT structures and passes the list 5254b88c807SRodney W. Grimes * along with any other necessary information to the print function. P 5264b88c807SRodney W. Grimes * points to the parent directory of the display list. 5274b88c807SRodney W. Grimes */ 5284b88c807SRodney W. Grimes static void 52940feca3aSMark Murray display(const FTSENT *p, FTSENT *list, int options) 5304b88c807SRodney W. Grimes { 5314b88c807SRodney W. Grimes struct stat *sp; 5324b88c807SRodney W. Grimes DISPLAY d; 5334b88c807SRodney W. Grimes FTSENT *cur; 5344b88c807SRodney W. Grimes NAMES *np; 5359052855aSMark Murray off_t maxsize; 53640feca3aSMark Murray long maxblock; 53740feca3aSMark Murray u_long btotal, labelstrlen, maxinode, maxlen, maxnlink; 5384d33b62eSRobert Watson u_long maxlabelstr; 5399052855aSMark Murray int bcfile, maxflags; 5409052855aSMark Murray gid_t maxgroup; 5419052855aSMark Murray uid_t maxuser; 5429052855aSMark Murray size_t flen, ulen, glen; 543545f583cSTim Vanderhoek char *initmax; 5444b88c807SRodney W. Grimes int entries, needstats; 5450928a7f1SJuli Mallett const char *user, *group; 5464d33b62eSRobert Watson char *flags, *labelstr = NULL; 547008a4910SSheldon Hearn char buf[STRBUF_SIZEOF(u_quad_t) + 1]; 548008a4910SSheldon Hearn char ngroup[STRBUF_SIZEOF(uid_t) + 1]; 549008a4910SSheldon Hearn char nuser[STRBUF_SIZEOF(gid_t) + 1]; 5504b88c807SRodney W. Grimes 5514b88c807SRodney W. Grimes needstats = f_inode || f_longform || f_size; 5524b88c807SRodney W. Grimes flen = 0; 553545f583cSTim Vanderhoek btotal = 0; 554545f583cSTim Vanderhoek initmax = getenv("LS_COLWIDTHS"); 555545f583cSTim Vanderhoek /* Fields match -lios order. New ones should be added at the end. */ 5564d33b62eSRobert Watson maxlabelstr = maxblock = maxinode = maxlen = maxnlink = 5579052855aSMark Murray maxuser = maxgroup = maxflags = maxsize = 0; 558545f583cSTim Vanderhoek if (initmax != NULL && *initmax != '\0') { 559545f583cSTim Vanderhoek char *initmax2, *jinitmax; 560545f583cSTim Vanderhoek int ninitmax; 561545f583cSTim Vanderhoek 562545f583cSTim Vanderhoek /* Fill-in "::" as "0:0:0" for the sake of scanf. */ 56340feca3aSMark Murray jinitmax = malloc(strlen(initmax) * 2 + 2); 564545f583cSTim Vanderhoek if (jinitmax == NULL) 5655ad9e45fSMatthew Dillon err(1, "malloc"); 56640feca3aSMark Murray initmax2 = jinitmax; 567545f583cSTim Vanderhoek if (*initmax == ':') 568545f583cSTim Vanderhoek strcpy(initmax2, "0:"), initmax2 += 2; 569545f583cSTim Vanderhoek else 570545f583cSTim Vanderhoek *initmax2++ = *initmax, *initmax2 = '\0'; 571545f583cSTim Vanderhoek for (initmax++; *initmax != '\0'; initmax++) { 572545f583cSTim Vanderhoek if (initmax[-1] == ':' && initmax[0] == ':') { 573545f583cSTim Vanderhoek *initmax2++ = '0'; 574545f583cSTim Vanderhoek *initmax2++ = initmax[0]; 575545f583cSTim Vanderhoek initmax2[1] = '\0'; 576545f583cSTim Vanderhoek } else { 577545f583cSTim Vanderhoek *initmax2++ = initmax[0]; 578545f583cSTim Vanderhoek initmax2[1] = '\0'; 579545f583cSTim Vanderhoek } 580545f583cSTim Vanderhoek } 5815dda5d0dSJosef Karthauser if (initmax2[-1] == ':') 5825dda5d0dSJosef Karthauser strcpy(initmax2, "0"); 583545f583cSTim Vanderhoek 584545f583cSTim Vanderhoek ninitmax = sscanf(jinitmax, 58540feca3aSMark Murray " %lu : %ld : %lu : %u : %u : %i : %jd : %lu : %lu ", 586545f583cSTim Vanderhoek &maxinode, &maxblock, &maxnlink, &maxuser, 5874d33b62eSRobert Watson &maxgroup, &maxflags, &maxsize, &maxlen, &maxlabelstr); 588545f583cSTim Vanderhoek f_notabs = 1; 589545f583cSTim Vanderhoek switch (ninitmax) { 5905dda5d0dSJosef Karthauser case 0: 5915dda5d0dSJosef Karthauser maxinode = 0; 5920d9f1a69SPhilippe Charnier /* FALLTHROUGH */ 5935dda5d0dSJosef Karthauser case 1: 5945dda5d0dSJosef Karthauser maxblock = 0; 5950d9f1a69SPhilippe Charnier /* FALLTHROUGH */ 5965dda5d0dSJosef Karthauser case 2: 5975dda5d0dSJosef Karthauser maxnlink = 0; 5980d9f1a69SPhilippe Charnier /* FALLTHROUGH */ 5995dda5d0dSJosef Karthauser case 3: 6005dda5d0dSJosef Karthauser maxuser = 0; 6010d9f1a69SPhilippe Charnier /* FALLTHROUGH */ 6025dda5d0dSJosef Karthauser case 4: 6035dda5d0dSJosef Karthauser maxgroup = 0; 6040d9f1a69SPhilippe Charnier /* FALLTHROUGH */ 6055dda5d0dSJosef Karthauser case 5: 6065dda5d0dSJosef Karthauser maxflags = 0; 6070d9f1a69SPhilippe Charnier /* FALLTHROUGH */ 6085dda5d0dSJosef Karthauser case 6: 6095dda5d0dSJosef Karthauser maxsize = 0; 6100d9f1a69SPhilippe Charnier /* FALLTHROUGH */ 6115dda5d0dSJosef Karthauser case 7: 6125dda5d0dSJosef Karthauser maxlen = 0; 6130d9f1a69SPhilippe Charnier /* FALLTHROUGH */ 6145dda5d0dSJosef Karthauser case 8: 6154d33b62eSRobert Watson maxlabelstr = 0; 6160d9f1a69SPhilippe Charnier /* FALLTHROUGH */ 61718d8a22bSAndrey A. Chernov #ifdef COLORLS 61818d8a22bSAndrey A. Chernov if (!f_color) 61922ff3e9eSAndrey A. Chernov #endif 62018d8a22bSAndrey A. Chernov f_notabs = 0; 6210d9f1a69SPhilippe Charnier /* FALLTHROUGH */ 6229052855aSMark Murray default: 623568dcd5fSBill Fumerola break; 624545f583cSTim Vanderhoek } 62540feca3aSMark Murray MAKENINES(maxinode); 62640feca3aSMark Murray MAKENINES(maxblock); 62740feca3aSMark Murray MAKENINES(maxnlink); 62840feca3aSMark Murray MAKENINES(maxsize); 6297fcc4669SLukas Ertl free(jinitmax); 6309052855aSMark Murray } 6314b88c807SRodney W. Grimes bcfile = 0; 6320fd510b7SJoerg Wunsch flags = NULL; 6334b88c807SRodney W. Grimes for (cur = list, entries = 0; cur; cur = cur->fts_link) { 6344b88c807SRodney W. Grimes if (cur->fts_info == FTS_ERR || cur->fts_info == FTS_NS) { 6354b88c807SRodney W. Grimes warnx("%s: %s", 6364b88c807SRodney W. Grimes cur->fts_name, strerror(cur->fts_errno)); 6374b88c807SRodney W. Grimes cur->fts_number = NO_PRINT; 638fb1000d6SAdam David rval = 1; 6394b88c807SRodney W. Grimes continue; 6404b88c807SRodney W. Grimes } 6414b88c807SRodney W. Grimes /* 6424b88c807SRodney W. Grimes * P is NULL if list is the argv list, to which different rules 6434b88c807SRodney W. Grimes * apply. 6444b88c807SRodney W. Grimes */ 6454b88c807SRodney W. Grimes if (p == NULL) { 6464b88c807SRodney W. Grimes /* Directories will be displayed later. */ 6474b88c807SRodney W. Grimes if (cur->fts_info == FTS_D && !f_listdir) { 6484b88c807SRodney W. Grimes cur->fts_number = NO_PRINT; 6494b88c807SRodney W. Grimes continue; 6504b88c807SRodney W. Grimes } 6514b88c807SRodney W. Grimes } else { 6524b88c807SRodney W. Grimes /* Only display dot file if -a/-A set. */ 6534b88c807SRodney W. Grimes if (cur->fts_name[0] == '.' && !f_listdot) { 6544b88c807SRodney W. Grimes cur->fts_number = NO_PRINT; 6554b88c807SRodney W. Grimes continue; 6564b88c807SRodney W. Grimes } 6574b88c807SRodney W. Grimes } 6584b88c807SRodney W. Grimes if (cur->fts_namelen > maxlen) 6594b88c807SRodney W. Grimes maxlen = cur->fts_namelen; 6600d86878cSDag-Erling Smørgrav if (f_octal || f_octal_escape) { 6616bd042dfSJosef Karthauser u_long t = len_octal(cur->fts_name, cur->fts_namelen); 6625dda5d0dSJosef Karthauser 6635dda5d0dSJosef Karthauser if (t > maxlen) 6645dda5d0dSJosef Karthauser maxlen = t; 6657ea30648SDag-Erling Smørgrav } 6664b88c807SRodney W. Grimes if (needstats) { 6674b88c807SRodney W. Grimes sp = cur->fts_statp; 6684b88c807SRodney W. Grimes if (sp->st_blocks > maxblock) 6694b88c807SRodney W. Grimes maxblock = sp->st_blocks; 6704b88c807SRodney W. Grimes if (sp->st_ino > maxinode) 6714b88c807SRodney W. Grimes maxinode = sp->st_ino; 6724b88c807SRodney W. Grimes if (sp->st_nlink > maxnlink) 6734b88c807SRodney W. Grimes maxnlink = sp->st_nlink; 6744b88c807SRodney W. Grimes if (sp->st_size > maxsize) 6754b88c807SRodney W. Grimes maxsize = sp->st_size; 6764b88c807SRodney W. Grimes 6774b88c807SRodney W. Grimes btotal += sp->st_blocks; 6784b88c807SRodney W. Grimes if (f_longform) { 679f3a6a64eSSheldon Hearn if (f_numericonly) { 680f3a6a64eSSheldon Hearn (void)snprintf(nuser, sizeof(nuser), 681f3a6a64eSSheldon Hearn "%u", sp->st_uid); 682f3a6a64eSSheldon Hearn (void)snprintf(ngroup, sizeof(ngroup), 683f3a6a64eSSheldon Hearn "%u", sp->st_gid); 684f3a6a64eSSheldon Hearn user = nuser; 685f3a6a64eSSheldon Hearn group = ngroup; 686f3a6a64eSSheldon Hearn } else { 6874b88c807SRodney W. Grimes user = user_from_uid(sp->st_uid, 0); 688f3a6a64eSSheldon Hearn group = group_from_gid(sp->st_gid, 0); 689f3a6a64eSSheldon Hearn } 6904b88c807SRodney W. Grimes if ((ulen = strlen(user)) > maxuser) 6914b88c807SRodney W. Grimes maxuser = ulen; 6924b88c807SRodney W. Grimes if ((glen = strlen(group)) > maxgroup) 6934b88c807SRodney W. Grimes maxgroup = glen; 6944b88c807SRodney W. Grimes if (f_flags) { 695141d77b8SJosef Karthauser flags = fflagstostr(sp->st_flags); 696141d77b8SJosef Karthauser if (flags != NULL && *flags == '\0') { 697141d77b8SJosef Karthauser free(flags); 698141d77b8SJosef Karthauser flags = strdup("-"); 699141d77b8SJosef Karthauser } 700141d77b8SJosef Karthauser if (flags == NULL) 7015ad9e45fSMatthew Dillon err(1, "fflagstostr"); 7029052855aSMark Murray flen = strlen(flags); 7039052855aSMark Murray if (flen > (size_t)maxflags) 7044b88c807SRodney W. Grimes maxflags = flen; 7054b88c807SRodney W. Grimes } else 7064b88c807SRodney W. Grimes flen = 0; 7074d33b62eSRobert Watson labelstr = NULL; 7084d33b62eSRobert Watson if (f_label) { 7094df6dabaSRobert Watson char name[PATH_MAX + 1]; 7104d33b62eSRobert Watson mac_t label; 7114d33b62eSRobert Watson int error; 7124b88c807SRodney W. Grimes 7134d33b62eSRobert Watson error = mac_prepare_file_label(&label); 7144d33b62eSRobert Watson if (error == -1) { 7153c3f5f9cSRobert Watson warn("MAC label for %s/%s", 7163c3f5f9cSRobert Watson cur->fts_parent->fts_path, 7173c3f5f9cSRobert Watson cur->fts_name); 7184d33b62eSRobert Watson goto label_out; 7194d33b62eSRobert Watson } 7204d33b62eSRobert Watson 7214df6dabaSRobert Watson if (cur->fts_level == FTS_ROOTLEVEL) 7224df6dabaSRobert Watson snprintf(name, sizeof(name), 7234df6dabaSRobert Watson "%s", cur->fts_name); 7244d33b62eSRobert Watson else 7254df6dabaSRobert Watson snprintf(name, sizeof(name), 7263c3f5f9cSRobert Watson "%s/%s", cur->fts_parent-> 7273c3f5f9cSRobert Watson fts_accpath, cur->fts_name); 7284df6dabaSRobert Watson 7294df6dabaSRobert Watson if (options & FTS_LOGICAL) 7304df6dabaSRobert Watson error = mac_get_file(name, 7314df6dabaSRobert Watson label); 7324df6dabaSRobert Watson else 7334df6dabaSRobert Watson error = mac_get_link(name, 7344df6dabaSRobert Watson label); 7354d33b62eSRobert Watson if (error == -1) { 7363c3f5f9cSRobert Watson warn("MAC label for %s/%s", 7373c3f5f9cSRobert Watson cur->fts_parent->fts_path, 7383c3f5f9cSRobert Watson cur->fts_name); 7394d33b62eSRobert Watson mac_free(label); 7404d33b62eSRobert Watson goto label_out; 7414d33b62eSRobert Watson } 7424d33b62eSRobert Watson 7434d33b62eSRobert Watson error = mac_to_text(label, 7444d33b62eSRobert Watson &labelstr); 7454d33b62eSRobert Watson if (error == -1) { 7463c3f5f9cSRobert Watson warn("MAC label for %s/%s", 7473c3f5f9cSRobert Watson cur->fts_parent->fts_path, 7483c3f5f9cSRobert Watson cur->fts_name); 7494d33b62eSRobert Watson mac_free(label); 7504d33b62eSRobert Watson goto label_out; 7514d33b62eSRobert Watson } 7524d33b62eSRobert Watson mac_free(label); 7534d33b62eSRobert Watson label_out: 7544d33b62eSRobert Watson if (labelstr == NULL) 755317f1d53SRobert Watson labelstr = strdup("-"); 7564d33b62eSRobert Watson labelstrlen = strlen(labelstr); 7574d33b62eSRobert Watson if (labelstrlen > maxlabelstr) 7584d33b62eSRobert Watson maxlabelstr = labelstrlen; 7594d33b62eSRobert Watson } else 7604d33b62eSRobert Watson labelstrlen = 0; 7614d33b62eSRobert Watson 7624d33b62eSRobert Watson if ((np = malloc(sizeof(NAMES) + labelstrlen + 7637304f61fSBrian Feldman ulen + glen + flen + 4)) == NULL) 7645ad9e45fSMatthew Dillon err(1, "malloc"); 7654b88c807SRodney W. Grimes 7664b88c807SRodney W. Grimes np->user = &np->data[0]; 7674b88c807SRodney W. Grimes (void)strcpy(np->user, user); 7684b88c807SRodney W. Grimes np->group = &np->data[ulen + 1]; 7694b88c807SRodney W. Grimes (void)strcpy(np->group, group); 7704b88c807SRodney W. Grimes 7714b88c807SRodney W. Grimes if (S_ISCHR(sp->st_mode) || 7724b88c807SRodney W. Grimes S_ISBLK(sp->st_mode)) 7734b88c807SRodney W. Grimes bcfile = 1; 7744b88c807SRodney W. Grimes 7754b88c807SRodney W. Grimes if (f_flags) { 7764b88c807SRodney W. Grimes np->flags = &np->data[ulen + glen + 2]; 7774b88c807SRodney W. Grimes (void)strcpy(np->flags, flags); 778141d77b8SJosef Karthauser free(flags); 7794b88c807SRodney W. Grimes } 7804d33b62eSRobert Watson if (f_label) { 7814d33b62eSRobert Watson np->label = &np->data[ulen + glen + 2 7827304f61fSBrian Feldman + (f_flags ? flen + 1 : 0)]; 7834d33b62eSRobert Watson (void)strcpy(np->label, labelstr); 7844d33b62eSRobert Watson free(labelstr); 7857304f61fSBrian Feldman } 7864b88c807SRodney W. Grimes cur->fts_pointer = np; 7874b88c807SRodney W. Grimes } 7884b88c807SRodney W. Grimes } 7894b88c807SRodney W. Grimes ++entries; 7904b88c807SRodney W. Grimes } 7914b88c807SRodney W. Grimes 79270bad4f7SDavid Schultz /* 79370bad4f7SDavid Schultz * If there are no entries to display, we normally stop right 79470bad4f7SDavid Schultz * here. However, we must continue if we have to display the 79570bad4f7SDavid Schultz * total block count. In this case, we display the total only 79670bad4f7SDavid Schultz * on the second (p != NULL) pass. 79770bad4f7SDavid Schultz */ 79870bad4f7SDavid Schultz if (!entries && (!(f_longform || f_size) || p == NULL)) 7994b88c807SRodney W. Grimes return; 8004b88c807SRodney W. Grimes 8014b88c807SRodney W. Grimes d.list = list; 8024b88c807SRodney W. Grimes d.entries = entries; 8034b88c807SRodney W. Grimes d.maxlen = maxlen; 8044b88c807SRodney W. Grimes if (needstats) { 8054b88c807SRodney W. Grimes d.bcfile = bcfile; 8064b88c807SRodney W. Grimes d.btotal = btotal; 8074b88c807SRodney W. Grimes (void)snprintf(buf, sizeof(buf), "%lu", maxblock); 8084b88c807SRodney W. Grimes d.s_block = strlen(buf); 8094b88c807SRodney W. Grimes d.s_flags = maxflags; 8104d33b62eSRobert Watson d.s_label = maxlabelstr; 8114b88c807SRodney W. Grimes d.s_group = maxgroup; 8124b88c807SRodney W. Grimes (void)snprintf(buf, sizeof(buf), "%lu", maxinode); 8134b88c807SRodney W. Grimes d.s_inode = strlen(buf); 8144b88c807SRodney W. Grimes (void)snprintf(buf, sizeof(buf), "%lu", maxnlink); 8154b88c807SRodney W. Grimes d.s_nlink = strlen(buf); 81640feca3aSMark Murray (void)snprintf(buf, sizeof(buf), "%ju", maxsize); 8174b88c807SRodney W. Grimes d.s_size = strlen(buf); 8184b88c807SRodney W. Grimes d.s_user = maxuser; 8194b88c807SRodney W. Grimes } 8204b88c807SRodney W. Grimes printfcn(&d); 8214b88c807SRodney W. Grimes output = 1; 8224b88c807SRodney W. Grimes 8234b88c807SRodney W. Grimes if (f_longform) 8244b88c807SRodney W. Grimes for (cur = list; cur; cur = cur->fts_link) 8254b88c807SRodney W. Grimes free(cur->fts_pointer); 8264b88c807SRodney W. Grimes } 8274b88c807SRodney W. Grimes 8284b88c807SRodney W. Grimes /* 8294b88c807SRodney W. Grimes * Ordering for mastercmp: 8304b88c807SRodney W. Grimes * If ordering the argv (fts_level = FTS_ROOTLEVEL) return non-directories 8314b88c807SRodney W. Grimes * as larger than directories. Within either group, use the sort function. 8324b88c807SRodney W. Grimes * All other levels use the sort function. Error entries remain unsorted. 8334b88c807SRodney W. Grimes */ 8344b88c807SRodney W. Grimes static int 8350d3bcc2eSGarrett Wollman mastercmp(const FTSENT * const *a, const FTSENT * const *b) 8364b88c807SRodney W. Grimes { 8374b88c807SRodney W. Grimes int a_info, b_info; 8384b88c807SRodney W. Grimes 8394b88c807SRodney W. Grimes a_info = (*a)->fts_info; 8404b88c807SRodney W. Grimes if (a_info == FTS_ERR) 8414b88c807SRodney W. Grimes return (0); 8424b88c807SRodney W. Grimes b_info = (*b)->fts_info; 8434b88c807SRodney W. Grimes if (b_info == FTS_ERR) 8444b88c807SRodney W. Grimes return (0); 8454b88c807SRodney W. Grimes 8464b88c807SRodney W. Grimes if (a_info == FTS_NS || b_info == FTS_NS) 8474b88c807SRodney W. Grimes return (namecmp(*a, *b)); 8484b88c807SRodney W. Grimes 84951f26ac5SSean Eric Fagan if (a_info != b_info && 85051f26ac5SSean Eric Fagan (*a)->fts_level == FTS_ROOTLEVEL && !f_listdir) { 8514b88c807SRodney W. Grimes if (a_info == FTS_D) 8524b88c807SRodney W. Grimes return (1); 85351f26ac5SSean Eric Fagan if (b_info == FTS_D) 8544b88c807SRodney W. Grimes return (-1); 85551f26ac5SSean Eric Fagan } 8564b88c807SRodney W. Grimes return (sortfcn(*a, *b)); 8574b88c807SRodney W. Grimes } 858