ls.c revision 20417
11556Srgrimes/* 21556Srgrimes * Copyright (c) 1989, 1993, 1994 31556Srgrimes * The Regents of the University of California. All rights reserved. 41556Srgrimes * 51556Srgrimes * This code is derived from software contributed to Berkeley by 61556Srgrimes * Michael Fischbein. 71556Srgrimes * 81556Srgrimes * Redistribution and use in source and binary forms, with or without 91556Srgrimes * modification, are permitted provided that the following conditions 101556Srgrimes * are met: 111556Srgrimes * 1. Redistributions of source code must retain the above copyright 121556Srgrimes * notice, this list of conditions and the following disclaimer. 131556Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 141556Srgrimes * notice, this list of conditions and the following disclaimer in the 151556Srgrimes * documentation and/or other materials provided with the distribution. 161556Srgrimes * 3. All advertising materials mentioning features or use of this software 171556Srgrimes * must display the following acknowledgement: 181556Srgrimes * This product includes software developed by the University of 191556Srgrimes * California, Berkeley and its contributors. 201556Srgrimes * 4. Neither the name of the University nor the names of its contributors 211556Srgrimes * may be used to endorse or promote products derived from this software 221556Srgrimes * without specific prior written permission. 231556Srgrimes * 241556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 251556Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 261556Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 271556Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 281556Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 291556Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 301556Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 311556Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 321556Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 331556Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 341556Srgrimes * SUCH DAMAGE. 353044Sdg * 3620417Ssteve * $Id: ls.c,v 1.10 1996/08/27 21:51:48 adam Exp $ 371556Srgrimes */ 381556Srgrimes 391556Srgrimes#ifndef lint 4020417Sstevestatic char const copyright[] = 411556Srgrimes"@(#) Copyright (c) 1989, 1993, 1994\n\ 421556Srgrimes The Regents of the University of California. All rights reserved.\n"; 431556Srgrimes#endif /* not lint */ 441556Srgrimes 451556Srgrimes#ifndef lint 4620417Sstevestatic char const sccsid[] = "@(#)ls.c 8.5 (Berkeley) 4/2/94"; 471556Srgrimes#endif /* not lint */ 481556Srgrimes 491556Srgrimes#include <sys/types.h> 501556Srgrimes#include <sys/stat.h> 511556Srgrimes#include <sys/ioctl.h> 521556Srgrimes 531556Srgrimes#include <dirent.h> 541556Srgrimes#include <err.h> 551556Srgrimes#include <errno.h> 561556Srgrimes#include <fts.h> 571556Srgrimes#include <stdio.h> 581556Srgrimes#include <stdlib.h> 591556Srgrimes#include <string.h> 601556Srgrimes#include <unistd.h> 6111740Sache#include <locale.h> 621556Srgrimes 631556Srgrimes#include "ls.h" 641556Srgrimes#include "extern.h" 651556Srgrimes 661556Srgrimesstatic void display __P((FTSENT *, FTSENT *)); 671556Srgrimesstatic int mastercmp __P((const FTSENT **, const FTSENT **)); 681556Srgrimesstatic void traverse __P((int, char **, int)); 691556Srgrimes 701556Srgrimesstatic void (*printfcn) __P((DISPLAY *)); 711556Srgrimesstatic int (*sortfcn) __P((const FTSENT *, const FTSENT *)); 721556Srgrimes 731556Srgrimeslong blocksize; /* block size units */ 741556Srgrimesint termwidth = 80; /* default terminal width */ 751556Srgrimes 761556Srgrimes/* flags */ 771556Srgrimesint f_accesstime; /* use time of last access */ 781556Srgrimesint f_column; /* columnated format */ 791556Srgrimesint f_flags; /* show flags associated with a file */ 801556Srgrimesint f_inode; /* print inode */ 812889Spstint f_kblocks; /* print size in kilobytes */ 821556Srgrimesint f_listdir; /* list actual directory, not contents */ 831556Srgrimesint f_listdot; /* list files beginning with . */ 841556Srgrimesint f_longform; /* long listing format */ 851556Srgrimesint f_newline; /* if precede with newline */ 861556Srgrimesint f_nonprint; /* show unprintables as ? */ 871556Srgrimesint f_nosort; /* don't sort output */ 881556Srgrimesint f_recursive; /* ls subdirectories also */ 891556Srgrimesint f_reversesort; /* reverse whatever sort is used */ 901556Srgrimesint f_sectime; /* print the real time for all files */ 911556Srgrimesint f_singlecol; /* use single column output */ 921556Srgrimesint f_size; /* list size in short listing */ 931556Srgrimesint f_statustime; /* use time of last mode change */ 941556Srgrimesint f_dirname; /* if precede with directory name */ 951556Srgrimesint f_timesort; /* sort by time vice name */ 961556Srgrimesint f_type; /* add type character for non-regular files */ 9720417Ssteve#ifndef BSD4_4_LITE 9820417Ssteveint f_whiteout; /* show whiteout entries */ 9920417Ssteve#endif 1001556Srgrimes 10117852Sadamint rval; 10217852Sadam 1031556Srgrimesint 1041556Srgrimesmain(argc, argv) 1051556Srgrimes int argc; 1061556Srgrimes char *argv[]; 1071556Srgrimes{ 1081556Srgrimes static char dot[] = ".", *dotav[] = { dot, NULL }; 1091556Srgrimes struct winsize win; 1101556Srgrimes int ch, fts_options, notused; 1111556Srgrimes char *p; 1121556Srgrimes 11311808Sache (void) setlocale(LC_ALL, ""); 11411808Sache 1151556Srgrimes /* Terminal defaults to -Cq, non-terminal defaults to -1. */ 1161556Srgrimes if (isatty(STDOUT_FILENO)) { 1171556Srgrimes if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &win) == -1 || 1181556Srgrimes !win.ws_col) { 1191556Srgrimes if ((p = getenv("COLUMNS")) != NULL) 1201556Srgrimes termwidth = atoi(p); 1211556Srgrimes } 1221556Srgrimes else 1231556Srgrimes termwidth = win.ws_col; 1241556Srgrimes f_column = f_nonprint = 1; 1255158Sjoerg } else { 1261556Srgrimes f_singlecol = 1; 1275158Sjoerg /* retrieve environment variable, in case of explicit -C */ 1287165Sjoerg if ((p = getenv("COLUMNS"))) 1295158Sjoerg termwidth = atoi(p); 1305158Sjoerg } 1311556Srgrimes 1321556Srgrimes /* Root is -A automatically. */ 1331556Srgrimes if (!getuid()) 1341556Srgrimes f_listdot = 1; 1351556Srgrimes 1361556Srgrimes fts_options = FTS_PHYSICAL; 13720417Ssteve#ifdef BSD4_4_LITE 1382889Spst while ((ch = getopt(argc, argv, "1ACFLRTacdfgikloqrstu")) != EOF) { 13920417Ssteve#else 14020417Ssteve while ((ch = getopt(argc, argv, "1ACFLRTWacdfgikloqrstu")) != EOF) { 14120417Ssteve#endif 1421556Srgrimes switch (ch) { 1431556Srgrimes /* 1441556Srgrimes * The -1, -C and -l options all override each other so shell 1451556Srgrimes * aliasing works right. 1461556Srgrimes */ 1471556Srgrimes case '1': 1481556Srgrimes f_singlecol = 1; 1491556Srgrimes f_column = f_longform = 0; 1501556Srgrimes break; 1511556Srgrimes case 'C': 1521556Srgrimes f_column = 1; 1531556Srgrimes f_longform = f_singlecol = 0; 1541556Srgrimes break; 1551556Srgrimes case 'l': 1561556Srgrimes f_longform = 1; 1571556Srgrimes f_column = f_singlecol = 0; 1581556Srgrimes break; 1591556Srgrimes /* The -c and -u options override each other. */ 1601556Srgrimes case 'c': 1611556Srgrimes f_statustime = 1; 1621556Srgrimes f_accesstime = 0; 1631556Srgrimes break; 1641556Srgrimes case 'u': 1651556Srgrimes f_accesstime = 1; 1661556Srgrimes f_statustime = 0; 1671556Srgrimes break; 1681556Srgrimes case 'F': 1691556Srgrimes f_type = 1; 1701556Srgrimes break; 1711556Srgrimes case 'L': 1721556Srgrimes fts_options &= ~FTS_PHYSICAL; 1731556Srgrimes fts_options |= FTS_LOGICAL; 1741556Srgrimes break; 1751556Srgrimes case 'R': 1761556Srgrimes f_recursive = 1; 1771556Srgrimes break; 1781556Srgrimes case 'a': 1791556Srgrimes fts_options |= FTS_SEEDOT; 1801556Srgrimes /* FALLTHROUGH */ 1811556Srgrimes case 'A': 1821556Srgrimes f_listdot = 1; 1831556Srgrimes break; 1841556Srgrimes /* The -d option turns off the -R option. */ 1851556Srgrimes case 'd': 1861556Srgrimes f_listdir = 1; 1871556Srgrimes f_recursive = 0; 1881556Srgrimes break; 1891556Srgrimes case 'f': 1901556Srgrimes f_nosort = 1; 1911556Srgrimes break; 1921556Srgrimes case 'g': /* Compatibility with 4.3BSD. */ 1931556Srgrimes break; 1941556Srgrimes case 'i': 1951556Srgrimes f_inode = 1; 1961556Srgrimes break; 1972889Spst case 'k': 1982889Spst f_kblocks = 1; 1992889Spst break; 2001556Srgrimes case 'o': 2011556Srgrimes f_flags = 1; 2021556Srgrimes break; 2031556Srgrimes case 'q': 2041556Srgrimes f_nonprint = 1; 2051556Srgrimes break; 2061556Srgrimes case 'r': 2071556Srgrimes f_reversesort = 1; 2081556Srgrimes break; 2091556Srgrimes case 's': 2101556Srgrimes f_size = 1; 2111556Srgrimes break; 2121556Srgrimes case 'T': 2131556Srgrimes f_sectime = 1; 2141556Srgrimes break; 2151556Srgrimes case 't': 2161556Srgrimes f_timesort = 1; 2171556Srgrimes break; 21820417Ssteve#ifndef BSD4_4_LITE 21920417Ssteve case 'W': 22020417Ssteve f_whiteout = 1; 22120417Ssteve break; 22220417Ssteve#endif 2231556Srgrimes default: 2241556Srgrimes case '?': 2251556Srgrimes usage(); 2261556Srgrimes } 2271556Srgrimes } 2281556Srgrimes argc -= optind; 2291556Srgrimes argv += optind; 2301556Srgrimes 2311556Srgrimes /* 2321556Srgrimes * If not -F, -i, -l, -s or -t options, don't require stat 2331556Srgrimes * information. 2341556Srgrimes */ 2351556Srgrimes if (!f_inode && !f_longform && !f_size && !f_timesort && !f_type) 2361556Srgrimes fts_options |= FTS_NOSTAT; 2371556Srgrimes 2381556Srgrimes /* 2391556Srgrimes * If not -F, -d or -l options, follow any symbolic links listed on 2401556Srgrimes * the command line. 2411556Srgrimes */ 2421556Srgrimes if (!f_longform && !f_listdir && !f_type) 2431556Srgrimes fts_options |= FTS_COMFOLLOW; 2441556Srgrimes 24520417Ssteve#ifndef BSD4_4_LITE 24620417Ssteve /* 24720417Ssteve * If -W, show whiteout entries 24820417Ssteve */ 24920417Ssteve#ifdef FTS_WHITEOUT 25020417Ssteve if (f_whiteout) 25120417Ssteve fts_options |= FTS_WHITEOUT; 25220417Ssteve#endif 25320417Ssteve#endif 25420417Ssteve 2551556Srgrimes /* If -l or -s, figure out block size. */ 2561556Srgrimes if (f_longform || f_size) { 2572889Spst if (f_kblocks) 2587282Sphk blocksize = 2; 2597282Sphk else { 2607282Sphk (void)getbsize(¬used, &blocksize); 2617282Sphk blocksize /= 512; 2627282Sphk } 2631556Srgrimes } 2641556Srgrimes 2651556Srgrimes /* Select a sort function. */ 2661556Srgrimes if (f_reversesort) { 2671556Srgrimes if (!f_timesort) 2681556Srgrimes sortfcn = revnamecmp; 2691556Srgrimes else if (f_accesstime) 2701556Srgrimes sortfcn = revacccmp; 2711556Srgrimes else if (f_statustime) 2721556Srgrimes sortfcn = revstatcmp; 2731556Srgrimes else /* Use modification time. */ 2741556Srgrimes sortfcn = revmodcmp; 2751556Srgrimes } else { 2761556Srgrimes if (!f_timesort) 2771556Srgrimes sortfcn = namecmp; 2781556Srgrimes else if (f_accesstime) 2791556Srgrimes sortfcn = acccmp; 2801556Srgrimes else if (f_statustime) 2811556Srgrimes sortfcn = statcmp; 2821556Srgrimes else /* Use modification time. */ 2831556Srgrimes sortfcn = modcmp; 2841556Srgrimes } 2851556Srgrimes 2861556Srgrimes /* Select a print function. */ 2871556Srgrimes if (f_singlecol) 2881556Srgrimes printfcn = printscol; 2891556Srgrimes else if (f_longform) 2901556Srgrimes printfcn = printlong; 2911556Srgrimes else 2921556Srgrimes printfcn = printcol; 2931556Srgrimes 2941556Srgrimes if (argc) 2951556Srgrimes traverse(argc, argv, fts_options); 2961556Srgrimes else 2971556Srgrimes traverse(1, dotav, fts_options); 29817852Sadam exit(rval); 2991556Srgrimes} 3001556Srgrimes 3011556Srgrimesstatic int output; /* If anything output. */ 3021556Srgrimes 3031556Srgrimes/* 3041556Srgrimes * Traverse() walks the logical directory structure specified by the argv list 3051556Srgrimes * in the order specified by the mastercmp() comparison function. During the 3061556Srgrimes * traversal it passes linked lists of structures to display() which represent 3071556Srgrimes * a superset (may be exact set) of the files to be displayed. 3081556Srgrimes */ 3091556Srgrimesstatic void 3101556Srgrimestraverse(argc, argv, options) 3111556Srgrimes int argc, options; 3121556Srgrimes char *argv[]; 3131556Srgrimes{ 3141556Srgrimes FTS *ftsp; 3151556Srgrimes FTSENT *p, *chp; 3161556Srgrimes int ch_options; 3171556Srgrimes 3181556Srgrimes if ((ftsp = 3191556Srgrimes fts_open(argv, options, f_nosort ? NULL : mastercmp)) == NULL) 3201556Srgrimes err(1, NULL); 3211556Srgrimes 3221556Srgrimes display(NULL, fts_children(ftsp, 0)); 3231556Srgrimes if (f_listdir) 3241556Srgrimes return; 3251556Srgrimes 3261556Srgrimes /* 3271556Srgrimes * If not recursing down this tree and don't need stat info, just get 3281556Srgrimes * the names. 3291556Srgrimes */ 3301556Srgrimes ch_options = !f_recursive && options & FTS_NOSTAT ? FTS_NAMEONLY : 0; 3311556Srgrimes 3321556Srgrimes while ((p = fts_read(ftsp)) != NULL) 3331556Srgrimes switch (p->fts_info) { 3341556Srgrimes case FTS_DC: 3351556Srgrimes warnx("%s: directory causes a cycle", p->fts_name); 3361556Srgrimes break; 3371556Srgrimes case FTS_DNR: 3381556Srgrimes case FTS_ERR: 3391556Srgrimes warnx("%s: %s", p->fts_name, strerror(p->fts_errno)); 34017852Sadam rval = 1; 3411556Srgrimes break; 3421556Srgrimes case FTS_D: 3431556Srgrimes if (p->fts_level != FTS_ROOTLEVEL && 3441556Srgrimes p->fts_name[0] == '.' && !f_listdot) 3451556Srgrimes break; 3461556Srgrimes 3471556Srgrimes /* 3481556Srgrimes * If already output something, put out a newline as 3491556Srgrimes * a separator. If multiple arguments, precede each 3501556Srgrimes * directory with its name. 3511556Srgrimes */ 3521556Srgrimes if (output) 3531556Srgrimes (void)printf("\n%s:\n", p->fts_path); 3541556Srgrimes else if (argc > 1) { 3551556Srgrimes (void)printf("%s:\n", p->fts_path); 3561556Srgrimes output = 1; 3571556Srgrimes } 3581556Srgrimes 3591556Srgrimes chp = fts_children(ftsp, ch_options); 3601556Srgrimes display(p, chp); 3611556Srgrimes 3621556Srgrimes if (!f_recursive && chp != NULL) 3631556Srgrimes (void)fts_set(ftsp, p, FTS_SKIP); 3641556Srgrimes break; 3651556Srgrimes } 3661556Srgrimes if (errno) 3671556Srgrimes err(1, "fts_read"); 3681556Srgrimes} 3691556Srgrimes 3701556Srgrimes/* 3711556Srgrimes * Display() takes a linked list of FTSENT structures and passes the list 3721556Srgrimes * along with any other necessary information to the print function. P 3731556Srgrimes * points to the parent directory of the display list. 3741556Srgrimes */ 3751556Srgrimesstatic void 3761556Srgrimesdisplay(p, list) 3771556Srgrimes FTSENT *p, *list; 3781556Srgrimes{ 3791556Srgrimes struct stat *sp; 3801556Srgrimes DISPLAY d; 3811556Srgrimes FTSENT *cur; 3821556Srgrimes NAMES *np; 3831556Srgrimes u_quad_t maxsize; 3841556Srgrimes u_long btotal, maxblock, maxinode, maxlen, maxnlink; 3851556Srgrimes int bcfile, flen, glen, ulen, maxflags, maxgroup, maxuser; 3861556Srgrimes int entries, needstats; 3871556Srgrimes char *user, *group, *flags, buf[20]; /* 32 bits == 10 digits */ 3881556Srgrimes 3891556Srgrimes /* 3901556Srgrimes * If list is NULL there are two possibilities: that the parent 3911556Srgrimes * directory p has no children, or that fts_children() returned an 3921556Srgrimes * error. We ignore the error case since it will be replicated 3931556Srgrimes * on the next call to fts_read() on the post-order visit to the 3941556Srgrimes * directory p, and will be signalled in traverse(). 3951556Srgrimes */ 3961556Srgrimes if (list == NULL) 3971556Srgrimes return; 3981556Srgrimes 3991556Srgrimes needstats = f_inode || f_longform || f_size; 4001556Srgrimes flen = 0; 4011556Srgrimes btotal = maxblock = maxinode = maxlen = maxnlink = 0; 4021556Srgrimes bcfile = 0; 4031556Srgrimes maxuser = maxgroup = maxflags = 0; 4047165Sjoerg flags = NULL; 4051556Srgrimes maxsize = 0; 4061556Srgrimes for (cur = list, entries = 0; cur; cur = cur->fts_link) { 4071556Srgrimes if (cur->fts_info == FTS_ERR || cur->fts_info == FTS_NS) { 4081556Srgrimes warnx("%s: %s", 4091556Srgrimes cur->fts_name, strerror(cur->fts_errno)); 4101556Srgrimes cur->fts_number = NO_PRINT; 41117852Sadam rval = 1; 4121556Srgrimes continue; 4131556Srgrimes } 4141556Srgrimes 4151556Srgrimes /* 4161556Srgrimes * P is NULL if list is the argv list, to which different rules 4171556Srgrimes * apply. 4181556Srgrimes */ 4191556Srgrimes if (p == NULL) { 4201556Srgrimes /* Directories will be displayed later. */ 4211556Srgrimes if (cur->fts_info == FTS_D && !f_listdir) { 4221556Srgrimes cur->fts_number = NO_PRINT; 4231556Srgrimes continue; 4241556Srgrimes } 4251556Srgrimes } else { 4261556Srgrimes /* Only display dot file if -a/-A set. */ 4271556Srgrimes if (cur->fts_name[0] == '.' && !f_listdot) { 4281556Srgrimes cur->fts_number = NO_PRINT; 4291556Srgrimes continue; 4301556Srgrimes } 4311556Srgrimes } 4321556Srgrimes if (f_nonprint) 4331556Srgrimes prcopy(cur->fts_name, cur->fts_name, cur->fts_namelen); 4341556Srgrimes if (cur->fts_namelen > maxlen) 4351556Srgrimes maxlen = cur->fts_namelen; 4361556Srgrimes if (needstats) { 4371556Srgrimes sp = cur->fts_statp; 4381556Srgrimes if (sp->st_blocks > maxblock) 4391556Srgrimes maxblock = sp->st_blocks; 4401556Srgrimes if (sp->st_ino > maxinode) 4411556Srgrimes maxinode = sp->st_ino; 4421556Srgrimes if (sp->st_nlink > maxnlink) 4431556Srgrimes maxnlink = sp->st_nlink; 4441556Srgrimes if (sp->st_size > maxsize) 4451556Srgrimes maxsize = sp->st_size; 4461556Srgrimes 4471556Srgrimes btotal += sp->st_blocks; 4481556Srgrimes if (f_longform) { 4491556Srgrimes user = user_from_uid(sp->st_uid, 0); 4501556Srgrimes if ((ulen = strlen(user)) > maxuser) 4511556Srgrimes maxuser = ulen; 4521556Srgrimes group = group_from_gid(sp->st_gid, 0); 4531556Srgrimes if ((glen = strlen(group)) > maxgroup) 4541556Srgrimes maxgroup = glen; 4551556Srgrimes if (f_flags) { 4561556Srgrimes flags = 4571556Srgrimes flags_to_string(sp->st_flags, "-"); 4581556Srgrimes if ((flen = strlen(flags)) > maxflags) 4591556Srgrimes maxflags = flen; 4601556Srgrimes } else 4611556Srgrimes flen = 0; 4621556Srgrimes 4631556Srgrimes if ((np = malloc(sizeof(NAMES) + 4641556Srgrimes ulen + glen + flen + 3)) == NULL) 4651556Srgrimes err(1, NULL); 4661556Srgrimes 4671556Srgrimes np->user = &np->data[0]; 4681556Srgrimes (void)strcpy(np->user, user); 4691556Srgrimes np->group = &np->data[ulen + 1]; 4701556Srgrimes (void)strcpy(np->group, group); 4711556Srgrimes 4721556Srgrimes if (S_ISCHR(sp->st_mode) || 4731556Srgrimes S_ISBLK(sp->st_mode)) 4741556Srgrimes bcfile = 1; 4751556Srgrimes 4761556Srgrimes if (f_flags) { 4771556Srgrimes np->flags = &np->data[ulen + glen + 2]; 4781556Srgrimes (void)strcpy(np->flags, flags); 4791556Srgrimes } 4801556Srgrimes cur->fts_pointer = np; 4811556Srgrimes } 4821556Srgrimes } 4831556Srgrimes ++entries; 4841556Srgrimes } 4851556Srgrimes 4861556Srgrimes if (!entries) 4871556Srgrimes return; 4881556Srgrimes 4891556Srgrimes d.list = list; 4901556Srgrimes d.entries = entries; 4911556Srgrimes d.maxlen = maxlen; 4921556Srgrimes if (needstats) { 4931556Srgrimes d.bcfile = bcfile; 4941556Srgrimes d.btotal = btotal; 4951556Srgrimes (void)snprintf(buf, sizeof(buf), "%lu", maxblock); 4961556Srgrimes d.s_block = strlen(buf); 4971556Srgrimes d.s_flags = maxflags; 4981556Srgrimes d.s_group = maxgroup; 4991556Srgrimes (void)snprintf(buf, sizeof(buf), "%lu", maxinode); 5001556Srgrimes d.s_inode = strlen(buf); 5011556Srgrimes (void)snprintf(buf, sizeof(buf), "%lu", maxnlink); 5021556Srgrimes d.s_nlink = strlen(buf); 5031556Srgrimes (void)snprintf(buf, sizeof(buf), "%qu", maxsize); 5041556Srgrimes d.s_size = strlen(buf); 5051556Srgrimes d.s_user = maxuser; 5061556Srgrimes } 5071556Srgrimes 5081556Srgrimes printfcn(&d); 5091556Srgrimes output = 1; 5101556Srgrimes 5111556Srgrimes if (f_longform) 5121556Srgrimes for (cur = list; cur; cur = cur->fts_link) 5131556Srgrimes free(cur->fts_pointer); 5141556Srgrimes} 5151556Srgrimes 5161556Srgrimes/* 5171556Srgrimes * Ordering for mastercmp: 5181556Srgrimes * If ordering the argv (fts_level = FTS_ROOTLEVEL) return non-directories 5191556Srgrimes * as larger than directories. Within either group, use the sort function. 5201556Srgrimes * All other levels use the sort function. Error entries remain unsorted. 5211556Srgrimes */ 5221556Srgrimesstatic int 5231556Srgrimesmastercmp(a, b) 5241556Srgrimes const FTSENT **a, **b; 5251556Srgrimes{ 5261556Srgrimes int a_info, b_info; 5271556Srgrimes 5281556Srgrimes a_info = (*a)->fts_info; 5291556Srgrimes if (a_info == FTS_ERR) 5301556Srgrimes return (0); 5311556Srgrimes b_info = (*b)->fts_info; 5321556Srgrimes if (b_info == FTS_ERR) 5331556Srgrimes return (0); 5341556Srgrimes 5351556Srgrimes if (a_info == FTS_NS || b_info == FTS_NS) 5361556Srgrimes return (namecmp(*a, *b)); 5371556Srgrimes 5381556Srgrimes if (a_info == b_info) 5391556Srgrimes return (sortfcn(*a, *b)); 5401556Srgrimes 5411556Srgrimes if ((*a)->fts_level == FTS_ROOTLEVEL) 5421556Srgrimes if (a_info == FTS_D) 5431556Srgrimes return (1); 5441556Srgrimes else if (b_info == FTS_D) 5451556Srgrimes return (-1); 5461556Srgrimes else 5471556Srgrimes return (sortfcn(*a, *b)); 5481556Srgrimes else 5491556Srgrimes return (sortfcn(*a, *b)); 5501556Srgrimes} 551