aboutsummaryrefslogtreecommitdiff
path: root/bin/ls/ls.c
diff options
context:
space:
mode:
Diffstat (limited to 'bin/ls/ls.c')
-rw-r--r--bin/ls/ls.c104
1 files changed, 71 insertions, 33 deletions
diff --git a/bin/ls/ls.c b/bin/ls/ls.c
index 8a30dd326b4e..b3d0a508d714 100644
--- a/bin/ls/ls.c
+++ b/bin/ls/ls.c
@@ -32,20 +32,6 @@
* SUCH DAMAGE.
*/
-#ifndef lint
-static const char copyright[] =
-"@(#) Copyright (c) 1989, 1993, 1994\n\
- The Regents of the University of California. All rights reserved.\n";
-#endif /* not lint */
-
-#if 0
-#ifndef lint
-static char sccsid[] = "@(#)ls.c 8.5 (Berkeley) 4/2/94";
-#endif /* not lint */
-#endif
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
@@ -101,12 +87,24 @@ static void display(const FTSENT *, FTSENT *, int);
static int mastercmp(const FTSENT * const *, const FTSENT * const *);
static void traverse(int, char **, int);
-#define COLOR_OPT (CHAR_MAX + 1)
+enum {
+ GRP_NONE = 0,
+ GRP_DIR_FIRST = -1,
+ GRP_DIR_LAST = 1
+};
+
+enum {
+ BIN_OPT = CHAR_MAX,
+ COLOR_OPT,
+ GROUP_OPT
+};
static const struct option long_opts[] =
{
- {"color", optional_argument, NULL, COLOR_OPT},
- {NULL, no_argument, NULL, 0}
+ {"color", optional_argument, NULL, COLOR_OPT},
+ {"group-directories", optional_argument, NULL, GROUP_OPT},
+ {"group-directories-first", no_argument, NULL, GROUP_OPT},
+ {NULL, no_argument, NULL, 0}
};
static void (*printfcn)(const DISPLAY *);
@@ -119,6 +117,7 @@ int termwidth = 80; /* default terminal width */
int f_accesstime; /* use time of last access */
int f_birthtime; /* use time of birth */
int f_flags; /* show flags associated with a file */
+static int f_groupdir = GRP_NONE;/* group directories first/last */
int f_humanval; /* show human-readable file sizes */
int f_inode; /* print inode */
static int f_kblocks; /* print size in kilobytes */
@@ -136,6 +135,7 @@ static int f_numericonly; /* don't convert uid/gid to name */
int f_octal_escape; /* like f_octal but use C escapes if possible */
static int f_recursive; /* ls subdirectories also */
static int f_reversesort; /* reverse whatever sort is used */
+static int f_verssort; /* sort names using strverscmp(3) rather than strcoll(3) */
int f_samesort; /* sort time and name in same direction */
int f_sectime; /* print full time information */
static int f_singlecol; /* use single column output */
@@ -143,6 +143,7 @@ static int f_singlecol; /* use single column output */
static int f_sizesort;
int f_slash; /* similar to f_type, but only for dirs */
int f_sortacross; /* sort across rows, not down columns */
+ int f_sowner; /* disable showing owner's name */
int f_statustime; /* use time of last mode change */
static int f_stream; /* stream the output, separate with commas */
int f_thousands; /* show file sizes with thousands separators */
@@ -275,7 +276,7 @@ main(int argc, char *argv[])
colorflag = COLORFLAG_AUTO;
#endif
while ((ch = getopt_long(argc, argv,
- "+1ABCD:FGHILPRSTUWXZabcdfghiklmnopqrstuwxy,", long_opts,
+ "+1ABCD:FGHILPRSTUWXZabcdfghiklmnopqrstuvwxy,", long_opts,
NULL)) != -1) {
switch (ch) {
/*
@@ -325,14 +326,21 @@ main(int argc, char *argv[])
case 'A':
f_listdot = 1;
break;
- /* The -t and -S options override each other. */
+ /* The -S, -t and -v options override each other. */
case 'S':
f_sizesort = 1;
f_timesort = 0;
+ f_verssort = 0;
break;
case 't':
f_timesort = 1;
f_sizesort = 0;
+ f_verssort = 0;
+ break;
+ case 'v':
+ f_verssort = 1;
+ f_sizesort = 0;
+ f_timesort = 0;
break;
/* Other flags. Please keep alphabetic. */
case ',':
@@ -401,7 +409,11 @@ main(int argc, char *argv[])
f_listdir = 1;
f_recursive = 0;
break;
- case 'g': /* Compatibility with 4.3BSD. */
+ case 'g':
+ f_longform = 1;
+ f_singlecol = 0;
+ f_stream = 0;
+ f_sowner = 1;
break;
case 'h':
f_humanval = 1;
@@ -420,6 +432,9 @@ main(int argc, char *argv[])
break;
case 'n':
f_numericonly = 1;
+ f_longform = 1;
+ f_singlecol = 0;
+ f_stream = 0;
break;
case 'o':
f_flags = 1;
@@ -447,6 +462,15 @@ main(int argc, char *argv[])
case 'y':
f_samesort = 1;
break;
+ case GROUP_OPT:
+ if (optarg == NULL || strcmp(optarg, "first") == 0)
+ f_groupdir = GRP_DIR_FIRST;
+ else if (strcmp(optarg, "last") == 0)
+ f_groupdir = GRP_DIR_LAST;
+ else
+ errx(2, "unsupported --group-directories value '%s' (must be first or last)",
+ optarg);
+ break;
case COLOR_OPT:
#ifdef COLORLS
if (optarg == NULL || do_color_always(optarg))
@@ -523,12 +547,12 @@ main(int argc, char *argv[])
#endif
/*
- * If not -F, -i, -l, -s, -S or -t options, don't require stat
- * information, unless in color mode in which case we do
- * need this to determine which colors to display.
+ * If not -F, -i, -l, -s, -S, -t or --group-directories options,
+ * don't require stat information, unless in color mode in which case
+ * we do need this to determine which colors to display.
*/
if (!f_inode && !f_longform && !f_size && !f_timesort &&
- !f_sizesort && !f_type
+ !f_sizesort && !f_type && f_groupdir == GRP_NONE
#ifdef COLORLS
&& !f_color
#endif
@@ -564,12 +588,15 @@ main(int argc, char *argv[])
blocksize /= 512;
}
}
+
/* Select a sort function. */
if (f_reversesort) {
- if (!f_timesort && !f_sizesort)
- sortfcn = revnamecmp;
- else if (f_sizesort)
+ if (f_sizesort)
sortfcn = revsizecmp;
+ else if (f_verssort)
+ sortfcn = revverscmp;
+ else if (!f_timesort)
+ sortfcn = revnamecmp;
else if (f_accesstime)
sortfcn = revacccmp;
else if (f_birthtime)
@@ -579,10 +606,12 @@ main(int argc, char *argv[])
else /* Use modification time. */
sortfcn = revmodcmp;
} else {
- if (!f_timesort && !f_sizesort)
- sortfcn = namecmp;
- else if (f_sizesort)
+ if (f_sizesort)
sortfcn = sizecmp;
+ else if (f_verssort)
+ sortfcn = verscmp;
+ else if (!f_timesort)
+ sortfcn = namecmp;
else if (f_accesstime)
sortfcn = acccmp;
else if (f_birthtime)
@@ -636,8 +665,10 @@ traverse(int argc, char *argv[], int options)
chp = fts_children(ftsp, 0);
if (chp != NULL)
display(NULL, chp, options);
- if (f_listdir)
+ if (f_listdir) {
+ fts_close(ftsp);
return;
+ }
/*
* If not recursing down this tree and don't need stat info, just get
@@ -686,6 +717,7 @@ traverse(int argc, char *argv[], int options)
}
if (errno)
err(1, "fts_read");
+ fts_close(ftsp);
}
/*
@@ -962,7 +994,8 @@ label_out:
d.maxlen = maxlen;
if (needstats) {
d.btotal = btotal;
- d.s_block = snprintf(NULL, 0, "%lu", howmany(maxblock, blocksize));
+ d.s_block = snprintf(NULL, 0, f_thousands ? "%'ld" : "%ld",
+ howmany(maxblock, blocksize));
d.s_flags = maxflags;
d.s_label = maxlabelstr;
d.s_group = maxgroup;
@@ -993,7 +1026,7 @@ label_out:
static int
mastercmp(const FTSENT * const *a, const FTSENT * const *b)
{
- int a_info, b_info;
+ int a_info, b_info, dir;
a_info = (*a)->fts_info;
if (a_info == FTS_ERR)
@@ -1012,5 +1045,10 @@ mastercmp(const FTSENT * const *a, const FTSENT * const *b)
if (b_info == FTS_D)
return (-1);
}
+
+ if (f_groupdir != GRP_NONE)
+ if ((dir = (a_info == FTS_D) - (b_info == FTS_D)) != 0)
+ return (f_groupdir * dir);
+
return (sortfcn(*a, *b));
}