aboutsummaryrefslogtreecommitdiff
path: root/coreutils
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2017-02-08 20:09:29 +0000
committerRon Yorston <rmy@pobox.com>2017-02-08 20:09:29 +0000
commit373275a708bafb88fa4f0519de2166154f44fed9 (patch)
tree4587b4fd3f695e0f3705b2a217e199f3144df931 /coreutils
parentb74b2619779b1deb903b7766261807df1e9b1f7f (diff)
parentc2b18583a3df06aeecf535c3cea6856aa1f2e205 (diff)
downloadbusybox-w32-373275a708bafb88fa4f0519de2166154f44fed9.tar.gz
busybox-w32-373275a708bafb88fa4f0519de2166154f44fed9.tar.bz2
busybox-w32-373275a708bafb88fa4f0519de2166154f44fed9.zip
Merge branch 'busybox' into merge
Diffstat (limited to 'coreutils')
-rw-r--r--coreutils/Config.src16
-rw-r--r--coreutils/Kbuild.src9
-rw-r--r--coreutils/chown.c2
-rw-r--r--coreutils/cp.c4
-rw-r--r--coreutils/dd.c4
-rw-r--r--coreutils/df.c8
-rw-r--r--coreutils/echo.c9
-rw-r--r--coreutils/env.c2
-rw-r--r--coreutils/expand.c13
-rw-r--r--coreutils/head.c4
-rw-r--r--coreutils/install.c2
-rw-r--r--coreutils/link.c41
-rw-r--r--coreutils/ls.c556
-rw-r--r--coreutils/md5_sha1_sum.c3
-rw-r--r--coreutils/mkdir.c2
-rw-r--r--coreutils/mv.c2
-rw-r--r--coreutils/printf.c5
-rw-r--r--coreutils/split.c2
-rw-r--r--coreutils/tail.c7
-rw-r--r--coreutils/test.c17
-rw-r--r--coreutils/wc.c4
-rw-r--r--coreutils/who.c1
22 files changed, 319 insertions, 394 deletions
diff --git a/coreutils/Config.src b/coreutils/Config.src
index c056320f8..1d2fea1fb 100644
--- a/coreutils/Config.src
+++ b/coreutils/Config.src
@@ -27,25 +27,11 @@ config FEATURE_PRESERVE_HARDLINKS
27 help 27 help
28 Allow cp and mv to preserve hard links. 28 Allow cp and mv to preserve hard links.
29 29
30comment "Common options for ls, more and telnet"
31 depends on LS || MORE || TELNET
32
33config FEATURE_AUTOWIDTH
34 bool "Calculate terminal & column widths"
35 default y
36 depends on LS || MORE || TELNET
37 help
38 This option allows utilities such as 'ls', 'more' and 'telnet'
39 to determine the width of the screen, which can allow them to
40 display additional text or avoid wrapping text onto the next line.
41 If you leave this disabled, your utilities will be especially
42 primitive and will be unable to determine the current screen width.
43
44comment "Common options for df, du, ls" 30comment "Common options for df, du, ls"
45 depends on DF || DU || LS 31 depends on DF || DU || LS
46 32
47config FEATURE_HUMAN_READABLE 33config FEATURE_HUMAN_READABLE
48 bool "Support for human readable output (example 13k, 23M, 235G)" 34 bool "Support human readable output (example 13k, 23M, 235G)"
49 default y 35 default y
50 depends on DF || DU || LS 36 depends on DF || DU || LS
51 help 37 help
diff --git a/coreutils/Kbuild.src b/coreutils/Kbuild.src
index d9a448781..a805b64fe 100644
--- a/coreutils/Kbuild.src
+++ b/coreutils/Kbuild.src
@@ -14,12 +14,5 @@ lib-$(CONFIG_MORE) += cat.o # more uses it if stdout isn't a tty
14lib-$(CONFIG_LESS) += cat.o # less too 14lib-$(CONFIG_LESS) += cat.o # less too
15lib-$(CONFIG_CRONTAB) += cat.o # crontab -l 15lib-$(CONFIG_CRONTAB) += cat.o # crontab -l
16lib-$(CONFIG_ADDUSER) += chown.o # used by adduser 16lib-$(CONFIG_ADDUSER) += chown.o # used by adduser
17lib-$(CONFIG_ADDGROUP) += chown.o # used by adduser 17lib-$(CONFIG_ADDGROUP) += chown.o # used by addgroup
18lib-$(CONFIG_ASH) += echo.o # used by ash
19lib-$(CONFIG_SH_IS_ASH) += echo.o # used by ash
20lib-$(CONFIG_BASH_IS_ASH) += echo.o # used by ash
21lib-$(CONFIG_HUSH) += echo.o # used by hush
22lib-$(CONFIG_SH_IS_HUSH) += echo.o # used by hush
23lib-$(CONFIG_BASH_IS_HUSH) += echo.o # used by hush
24lib-$(CONFIG_FTPD) += ls.o # used by ftpd 18lib-$(CONFIG_FTPD) += ls.o # used by ftpd
25lib-$(CONFIG_ASH_BUILTIN_PRINTF) += printf.o
diff --git a/coreutils/chown.c b/coreutils/chown.c
index 50b06d73a..12cd0eacc 100644
--- a/coreutils/chown.c
+++ b/coreutils/chown.c
@@ -17,8 +17,6 @@
17//config: bool "Enable long options" 17//config: bool "Enable long options"
18//config: default y 18//config: default y
19//config: depends on CHOWN && LONG_OPTS 19//config: depends on CHOWN && LONG_OPTS
20//config: help
21//config: Enable use of long options
22 20
23//applet:IF_CHOWN(APPLET_NOEXEC(chown, chown, BB_DIR_BIN, BB_SUID_DROP, chown)) 21//applet:IF_CHOWN(APPLET_NOEXEC(chown, chown, BB_DIR_BIN, BB_SUID_DROP, chown))
24 22
diff --git a/coreutils/cp.c b/coreutils/cp.c
index 4ecdaafda..1e5f36d10 100644
--- a/coreutils/cp.c
+++ b/coreutils/cp.c
@@ -18,11 +18,11 @@
18//config: cp is used to copy files and directories. 18//config: cp is used to copy files and directories.
19//config: 19//config:
20//config:config FEATURE_CP_LONG_OPTIONS 20//config:config FEATURE_CP_LONG_OPTIONS
21//config: bool "Enable long options for cp" 21//config: bool "Enable long options"
22//config: default y 22//config: default y
23//config: depends on CP && LONG_OPTS 23//config: depends on CP && LONG_OPTS
24//config: help 24//config: help
25//config: Enable long options for cp. 25//config: Enable long options.
26//config: Also add support for --parents option. 26//config: Also add support for --parents option.
27 27
28//applet:IF_CP(APPLET_NOEXEC(cp, cp, BB_DIR_BIN, BB_SUID_DROP, cp)) 28//applet:IF_CP(APPLET_NOEXEC(cp, cp, BB_DIR_BIN, BB_SUID_DROP, cp))
diff --git a/coreutils/dd.c b/coreutils/dd.c
index 8c144cfd2..85152d8ce 100644
--- a/coreutils/dd.c
+++ b/coreutils/dd.c
@@ -41,7 +41,7 @@
41//config: default y 41//config: default y
42//config: depends on DD 42//config: depends on DD
43//config: help 43//config: help
44//config: Enables support for writing a certain number of bytes in and out, 44//config: Enable support for writing a certain number of bytes in and out,
45//config: at a time, and performing conversions on the data stream. 45//config: at a time, and performing conversions on the data stream.
46//config: 46//config:
47//config:config FEATURE_DD_STATUS 47//config:config FEATURE_DD_STATUS
@@ -49,7 +49,7 @@
49//config: default y 49//config: default y
50//config: depends on DD 50//config: depends on DD
51//config: help 51//config: help
52//config: Enables support for status=noxfer/none option. 52//config: Enable support for status=noxfer/none option.
53 53
54//applet:IF_DD(APPLET_NOEXEC(dd, dd, BB_DIR_BIN, BB_SUID_DROP, dd)) 54//applet:IF_DD(APPLET_NOEXEC(dd, dd, BB_DIR_BIN, BB_SUID_DROP, dd))
55 55
diff --git a/coreutils/df.c b/coreutils/df.c
index 79e4c4670..cf367161a 100644
--- a/coreutils/df.c
+++ b/coreutils/df.c
@@ -29,11 +29,9 @@
29//config: default y 29//config: default y
30//config: depends on DF 30//config: depends on DF
31//config: help 31//config: help
32//config: This option enables -a, -i and -B. 32//config: -a Show all filesystems
33//config: 33//config: -i Inodes
34//config: -a Show all filesystems 34//config: -B <SIZE> Blocksize
35//config: -i Inodes
36//config: -B <SIZE> Blocksize
37 35
38//applet:IF_DF(APPLET(df, BB_DIR_BIN, BB_SUID_DROP)) 36//applet:IF_DF(APPLET(df, BB_DIR_BIN, BB_SUID_DROP))
39 37
diff --git a/coreutils/echo.c b/coreutils/echo.c
index fd0d9b780..a7e4ca9ac 100644
--- a/coreutils/echo.c
+++ b/coreutils/echo.c
@@ -26,16 +26,17 @@
26//config: 26//config:
27//config:# this entry also appears in shell/Config.in, next to the echo builtin 27//config:# this entry also appears in shell/Config.in, next to the echo builtin
28//config:config FEATURE_FANCY_ECHO 28//config:config FEATURE_FANCY_ECHO
29//config: bool "Enable echo options (-n and -e)" 29//config: bool "Enable -n and -e options"
30//config: default y 30//config: default y
31//config: depends on ECHO || ASH_BUILTIN_ECHO || HUSH 31//config: depends on ECHO || ASH_ECHO || HUSH_ECHO
32//config: help
33//config: This adds options (-n and -e) to echo.
34 32
35//applet:IF_ECHO(APPLET_NOFORK(echo, echo, BB_DIR_BIN, BB_SUID_DROP, echo)) 33//applet:IF_ECHO(APPLET_NOFORK(echo, echo, BB_DIR_BIN, BB_SUID_DROP, echo))
36 34
37//kbuild:lib-$(CONFIG_ECHO) += echo.o 35//kbuild:lib-$(CONFIG_ECHO) += echo.o
38 36
37//kbuild:lib-$(CONFIG_ASH_ECHO) += echo.o
38//kbuild:lib-$(CONFIG_HUSH_ECHO) += echo.o
39
39/* BB_AUDIT SUSv3 compliant -- unless configured as fancy echo. */ 40/* BB_AUDIT SUSv3 compliant -- unless configured as fancy echo. */
40/* http://www.opengroup.org/onlinepubs/007904975/utilities/echo.html */ 41/* http://www.opengroup.org/onlinepubs/007904975/utilities/echo.html */
41 42
diff --git a/coreutils/env.c b/coreutils/env.c
index e91eddb5c..2bd5f41d0 100644
--- a/coreutils/env.c
+++ b/coreutils/env.c
@@ -35,8 +35,6 @@
35//config: bool "Enable long options" 35//config: bool "Enable long options"
36//config: default y 36//config: default y
37//config: depends on ENV && LONG_OPTS 37//config: depends on ENV && LONG_OPTS
38//config: help
39//config: Support long options for the env applet.
40 38
41//applet:IF_ENV(APPLET_NOEXEC(env, env, BB_DIR_USR_BIN, BB_SUID_DROP, env)) 39//applet:IF_ENV(APPLET_NOEXEC(env, env, BB_DIR_USR_BIN, BB_SUID_DROP, env))
42 40
diff --git a/coreutils/expand.c b/coreutils/expand.c
index bb59af46d..9ce86ebff 100644
--- a/coreutils/expand.c
+++ b/coreutils/expand.c
@@ -8,13 +8,13 @@
8 * David MacKenzie <djm@gnu.ai.mit.edu> 8 * David MacKenzie <djm@gnu.ai.mit.edu>
9 * 9 *
10 * Options for expand: 10 * Options for expand:
11 * -t num --tabs=NUM Convert tabs to num spaces (default 8 spaces). 11 * -t num --tabs NUM Convert tabs to num spaces (default 8 spaces).
12 * -i --initial Only convert initial tabs on each line to spaces. 12 * -i --initial Only convert initial tabs on each line to spaces.
13 * 13 *
14 * Options for unexpand: 14 * Options for unexpand:
15 * -a --all Convert all blanks, instead of just initial blanks. 15 * -a --all Convert all blanks, instead of just initial blanks.
16 * -f --first-only Convert only leading sequences of blanks (default). 16 * -f --first-only Convert only leading sequences of blanks (default).
17 * -t num --tabs=NUM Have tabs num characters apart instead of 8. 17 * -t num --tabs NUM Have tabs num characters apart instead of 8.
18 * 18 *
19 * Busybox version (C) 2007 by Tito Ragusa <farmatito@tiscali.it> 19 * Busybox version (C) 2007 by Tito Ragusa <farmatito@tiscali.it>
20 * 20 *
@@ -30,8 +30,6 @@
30//config: bool "Enable long options" 30//config: bool "Enable long options"
31//config: default y 31//config: default y
32//config: depends on EXPAND && LONG_OPTS 32//config: depends on EXPAND && LONG_OPTS
33//config: help
34//config: Support long options for the expand applet.
35//config: 33//config:
36//config:config UNEXPAND 34//config:config UNEXPAND
37//config: bool "unexpand" 35//config: bool "unexpand"
@@ -43,10 +41,9 @@
43//config: bool "Enable long options" 41//config: bool "Enable long options"
44//config: default y 42//config: default y
45//config: depends on UNEXPAND && LONG_OPTS 43//config: depends on UNEXPAND && LONG_OPTS
46//config: help
47//config: Support long options for the unexpand applet.
48 44
49//applet:IF_EXPAND(APPLET(expand, BB_DIR_USR_BIN, BB_SUID_DROP)) 45//applet:IF_EXPAND(APPLET(expand, BB_DIR_USR_BIN, BB_SUID_DROP))
46// APPLET_ODDNAME:name main location suid_type help
50//applet:IF_UNEXPAND(APPLET_ODDNAME(unexpand, expand, BB_DIR_USR_BIN, BB_SUID_DROP, unexpand)) 47//applet:IF_UNEXPAND(APPLET_ODDNAME(unexpand, expand, BB_DIR_USR_BIN, BB_SUID_DROP, unexpand))
51 48
52//kbuild:lib-$(CONFIG_EXPAND) += expand.o 49//kbuild:lib-$(CONFIG_EXPAND) += expand.o
@@ -58,7 +55,7 @@
58//usage: "Convert tabs to spaces, writing to stdout\n" 55//usage: "Convert tabs to spaces, writing to stdout\n"
59//usage: IF_FEATURE_EXPAND_LONG_OPTIONS( 56//usage: IF_FEATURE_EXPAND_LONG_OPTIONS(
60//usage: "\n -i,--initial Don't convert tabs after non blanks" 57//usage: "\n -i,--initial Don't convert tabs after non blanks"
61//usage: "\n -t,--tabs=N Tabstops every N chars" 58//usage: "\n -t,--tabs N Tabstops every N chars"
62//usage: ) 59//usage: )
63//usage: IF_NOT_FEATURE_EXPAND_LONG_OPTIONS( 60//usage: IF_NOT_FEATURE_EXPAND_LONG_OPTIONS(
64//usage: "\n -i Don't convert tabs after non blanks" 61//usage: "\n -i Don't convert tabs after non blanks"
@@ -72,7 +69,7 @@
72//usage: IF_FEATURE_UNEXPAND_LONG_OPTIONS( 69//usage: IF_FEATURE_UNEXPAND_LONG_OPTIONS(
73//usage: "\n -a,--all Convert all blanks" 70//usage: "\n -a,--all Convert all blanks"
74//usage: "\n -f,--first-only Convert only leading blanks" 71//usage: "\n -f,--first-only Convert only leading blanks"
75//usage: "\n -t,--tabs=N Tabstops every N chars" 72//usage: "\n -t,--tabs N Tabstops every N chars"
76//usage: ) 73//usage: )
77//usage: IF_NOT_FEATURE_UNEXPAND_LONG_OPTIONS( 74//usage: IF_NOT_FEATURE_UNEXPAND_LONG_OPTIONS(
78//usage: "\n -a Convert all blanks" 75//usage: "\n -a Convert all blanks"
diff --git a/coreutils/head.c b/coreutils/head.c
index 176e91e3a..d49113e7f 100644
--- a/coreutils/head.c
+++ b/coreutils/head.c
@@ -14,11 +14,9 @@
14//config: from files. 14//config: from files.
15//config: 15//config:
16//config:config FEATURE_FANCY_HEAD 16//config:config FEATURE_FANCY_HEAD
17//config: bool "Enable head options (-c, -q, and -v)" 17//config: bool "Enable -c, -q, and -v"
18//config: default y 18//config: default y
19//config: depends on HEAD 19//config: depends on HEAD
20//config: help
21//config: This enables the head options (-c, -q, and -v).
22 20
23//applet:IF_HEAD(APPLET_NOEXEC(head, head, BB_DIR_USR_BIN, BB_SUID_DROP, head)) 21//applet:IF_HEAD(APPLET_NOEXEC(head, head, BB_DIR_USR_BIN, BB_SUID_DROP, head))
24 22
diff --git a/coreutils/install.c b/coreutils/install.c
index 831f9b802..2a642bdb6 100644
--- a/coreutils/install.c
+++ b/coreutils/install.c
@@ -15,8 +15,6 @@
15//config: bool "Enable long options" 15//config: bool "Enable long options"
16//config: default y 16//config: default y
17//config: depends on INSTALL && LONG_OPTS 17//config: depends on INSTALL && LONG_OPTS
18//config: help
19//config: Support long options for the install applet.
20 18
21//applet:IF_INSTALL(APPLET(install, BB_DIR_USR_BIN, BB_SUID_DROP)) 19//applet:IF_INSTALL(APPLET(install, BB_DIR_USR_BIN, BB_SUID_DROP))
22 20
diff --git a/coreutils/link.c b/coreutils/link.c
new file mode 100644
index 000000000..ac3ef85d9
--- /dev/null
+++ b/coreutils/link.c
@@ -0,0 +1,41 @@
1/*
2 * link implementation for busybox
3 *
4 * Copyright (C) 2017 Denys Vlasenko <vda.linux@googlemail.com>
5 *
6 * Licensed under GPLv2, see file LICENSE in this source tree.
7 */
8//config:config LINK
9//config: bool "link"
10//config: default y
11//config: help
12//config: link creates hard links between files.
13
14//applet:IF_LINK(APPLET_NOFORK(link, link, BB_DIR_BIN, BB_SUID_DROP, link))
15
16//kbuild:lib-$(CONFIG_LINK) += link.o
17
18//usage:#define link_trivial_usage
19//usage: "FILE LINK"
20//usage:#define link_full_usage "\n\n"
21//usage: "Create hard LINK to FILE"
22
23#include "libbb.h"
24
25/* This is a NOFORK applet. Be very careful! */
26
27int link_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
28int link_main(int argc UNUSED_PARAM, char **argv)
29{
30 opt_complementary = "=2"; /* exactly 2 params */
31 getopt32(argv, "");
32 argv += optind;
33 if (link(argv[0], argv[1]) != 0) {
34 /* shared message */
35 bb_perror_msg_and_die("can't create %slink "
36 "%s to %s", "hard",
37 argv[1], argv[0]
38 );
39 }
40 return EXIT_SUCCESS;
41}
diff --git a/coreutils/ls.c b/coreutils/ls.c
index 0f35c70d5..6e0a52d75 100644
--- a/coreutils/ls.c
+++ b/coreutils/ls.c
@@ -37,22 +37,21 @@
37//config: bool "Enable filetyping options (-p and -F)" 37//config: bool "Enable filetyping options (-p and -F)"
38//config: default y 38//config: default y
39//config: depends on LS 39//config: depends on LS
40//config: help
41//config: Enable the ls options (-p and -F).
42//config: 40//config:
43//config:config FEATURE_LS_FOLLOWLINKS 41//config:config FEATURE_LS_FOLLOWLINKS
44//config: bool "Enable symlinks dereferencing (-L)" 42//config: bool "Enable symlinks dereferencing (-L)"
45//config: default y 43//config: default y
46//config: depends on LS 44//config: depends on LS
47//config: help
48//config: Enable the ls option (-L).
49//config: 45//config:
50//config:config FEATURE_LS_RECURSIVE 46//config:config FEATURE_LS_RECURSIVE
51//config: bool "Enable recursion (-R)" 47//config: bool "Enable recursion (-R)"
52//config: default y 48//config: default y
53//config: depends on LS 49//config: depends on LS
54//config: help 50//config:
55//config: Enable the ls option (-R). 51//config:config FEATURE_LS_WIDTH
52//config: bool "Enable -w WIDTH and window size autodetection"
53//config: default y
54//config: depends on LS
56//config: 55//config:
57//config:config FEATURE_LS_SORTFILES 56//config:config FEATURE_LS_SORTFILES
58//config: bool "Sort the file names" 57//config: bool "Sort the file names"
@@ -102,18 +101,17 @@
102//usage: IF_FEATURE_LS_FOLLOWLINKS("LH") 101//usage: IF_FEATURE_LS_FOLLOWLINKS("LH")
103//usage: IF_FEATURE_LS_RECURSIVE("R") 102//usage: IF_FEATURE_LS_RECURSIVE("R")
104//usage: IF_FEATURE_LS_FILETYPES("Fp") "lins" 103//usage: IF_FEATURE_LS_FILETYPES("Fp") "lins"
105//usage: IF_FEATURE_LS_TIMESTAMPS("e")
106//usage: IF_FEATURE_HUMAN_READABLE("h") 104//usage: IF_FEATURE_HUMAN_READABLE("h")
107//usage: IF_FEATURE_LS_SORTFILES("rSXv") 105//usage: IF_FEATURE_LS_SORTFILES("rSXv")
108//usage: IF_FEATURE_LS_TIMESTAMPS("ctu") 106//usage: IF_FEATURE_LS_TIMESTAMPS("ctu")
109//usage: IF_SELINUX("kKZ") "]" 107//usage: IF_SELINUX("kZ") "]"
110//usage: IF_FEATURE_AUTOWIDTH(" [-w WIDTH]") " [FILE]..." 108//usage: IF_FEATURE_LS_WIDTH(" [-w WIDTH]") " [FILE]..."
111//usage:#define ls_full_usage "\n\n" 109//usage:#define ls_full_usage "\n\n"
112//usage: "List directory contents\n" 110//usage: "List directory contents\n"
113//usage: "\n -1 One column output" 111//usage: "\n -1 One column output"
114//usage: "\n -a Include entries which start with ." 112//usage: "\n -a Include entries which start with ."
115//usage: "\n -A Like -a, but exclude . and .." 113//usage: "\n -A Like -a, but exclude . and .."
116//usage: "\n -C List by columns" 114////usage: "\n -C List by columns" - don't show, this is a default anyway
117//usage: "\n -x List by lines" 115//usage: "\n -x List by lines"
118//usage: "\n -d List directory entries instead of contents" 116//usage: "\n -d List directory entries instead of contents"
119//usage: IF_FEATURE_LS_FOLLOWLINKS( 117//usage: IF_FEATURE_LS_FOLLOWLINKS(
@@ -132,29 +130,34 @@
132//usage: "\n -n List numeric UIDs and GIDs instead of names" 130//usage: "\n -n List numeric UIDs and GIDs instead of names"
133//usage: "\n -s List allocated blocks" 131//usage: "\n -s List allocated blocks"
134//usage: IF_FEATURE_LS_TIMESTAMPS( 132//usage: IF_FEATURE_LS_TIMESTAMPS(
135//usage: "\n -e List full date and time" 133//usage: "\n -lc List ctime"
134//usage: "\n -lu List atime"
136//usage: ) 135//usage: )
136//usage: IF_FEATURE_LS_TIMESTAMPS(IF_LONG_OPTS(
137//usage: "\n --full-time List full date and time"
138//usage: ))
137//usage: IF_FEATURE_HUMAN_READABLE( 139//usage: IF_FEATURE_HUMAN_READABLE(
138//usage: "\n -h List sizes in human readable format (1K 243M 2G)" 140//usage: "\n -h Human readable sizes (1K 243M 2G)"
139//usage: ) 141//usage: )
140//usage: IF_FEATURE_LS_SORTFILES( 142//usage: IF_FEATURE_LS_SORTFILES(
141//usage: "\n -r Sort in reverse order" 143//usage: IF_LONG_OPTS(
144//usage: "\n --group-directories-first"
145//usage: )
142//usage: "\n -S Sort by size" 146//usage: "\n -S Sort by size"
143//usage: "\n -X Sort by extension" 147//usage: "\n -X Sort by extension"
144//usage: "\n -v Sort by version" 148//usage: "\n -v Sort by version"
145//usage: ) 149//usage: )
146//usage: IF_FEATURE_LS_TIMESTAMPS( 150//usage: IF_FEATURE_LS_TIMESTAMPS(
147//usage: "\n -c With -l: sort by ctime" 151//usage: "\n -t Sort by mtime"
148//usage: "\n -t With -l: sort by mtime" 152//usage: "\n -tc Sort by ctime"
149//usage: "\n -u With -l: sort by atime" 153//usage: "\n -tu Sort by atime"
150//usage: ) 154//usage: )
155//usage: "\n -r Reverse sort order"
151//usage: IF_SELINUX( 156//usage: IF_SELINUX(
152//usage: "\n -k List security context"
153//usage: "\n -K List security context in long format"
154//usage: "\n -Z List security context and permission" 157//usage: "\n -Z List security context and permission"
155//usage: ) 158//usage: )
156//usage: IF_FEATURE_AUTOWIDTH( 159//usage: IF_FEATURE_LS_WIDTH(
157//usage: "\n -w N Assume the terminal is N columns wide" 160//usage: "\n -w N Format N columns wide"
158//usage: ) 161//usage: )
159//usage: IF_FEATURE_LS_COLOR( 162//usage: IF_FEATURE_LS_COLOR(
160//usage: "\n --color[={always,never,auto}] Control coloring" 163//usage: "\n --color[={always,never,auto}] Control coloring"
@@ -189,187 +192,90 @@ TERMINAL_WIDTH = 80, /* use 79 if terminal has linefold bug */
189SPLIT_FILE = 0, 192SPLIT_FILE = 0,
190SPLIT_DIR = 1, 193SPLIT_DIR = 1,
191SPLIT_SUBDIR = 2, 194SPLIT_SUBDIR = 2,
192
193/* Bits in G.all_fmt: */
194
195/* 51306 lrwxrwxrwx 1 root root 2 May 11 01:43 /bin/view -> vi* */
196/* what file information will be listed */
197LIST_INO = 1 << 0,
198LIST_BLOCKS = 1 << 1,
199LIST_MODEBITS = 1 << 2,
200LIST_NLINKS = 1 << 3,
201LIST_ID_NAME = 1 << 4,
202LIST_ID_NUMERIC = 1 << 5,
203LIST_CONTEXT = 1 << 6,
204LIST_SIZE = 1 << 7,
205LIST_DATE_TIME = 1 << 8,
206LIST_FULLTIME = 1 << 9,
207LIST_SYMLINK = 1 << 10,
208LIST_FILETYPE = 1 << 11, /* show / suffix for dirs */
209LIST_CLASSIFY = 1 << 12, /* requires LIST_FILETYPE, also show *,|,@,= suffixes */
210LIST_MASK = (LIST_CLASSIFY << 1) - 1,
211
212/* what files will be displayed */
213DISP_DIRNAME = 1 << 13, /* 2 or more items? label directories */
214DISP_HIDDEN = 1 << 14, /* show filenames starting with . */
215DISP_DOT = 1 << 15, /* show . and .. */
216DISP_NOLIST = 1 << 16, /* show directory as itself, not contents */
217DISP_RECURSIVE = 1 << 17, /* show directory and everything below it */
218DISP_ROWS = 1 << 18, /* print across rows */
219DISP_MASK = ((DISP_ROWS << 1) - 1) & ~(DISP_DIRNAME - 1),
220
221/* what is the overall style of the listing */
222STYLE_COLUMNAR = 1 << 19, /* many records per line */
223STYLE_LONG = 2 << 19, /* one record per line, extended info */
224STYLE_SINGLE = 3 << 19, /* one record per line */
225STYLE_MASK = STYLE_SINGLE,
226
227/* which of the three times will be used */
228TIME_CHANGE = (1 << 21) * ENABLE_FEATURE_LS_TIMESTAMPS,
229TIME_ACCESS = (2 << 21) * ENABLE_FEATURE_LS_TIMESTAMPS,
230TIME_MASK = (3 << 21) * ENABLE_FEATURE_LS_TIMESTAMPS,
231
232/* how will the files be sorted (CONFIG_FEATURE_LS_SORTFILES) */
233SORT_REVERSE = 1 << 23,
234
235SORT_NAME = 0, /* sort by file name */
236SORT_SIZE = 1 << 24, /* sort by file size */
237SORT_ATIME = 2 << 24, /* sort by last access time */
238SORT_CTIME = 3 << 24, /* sort by last change time */
239SORT_MTIME = 4 << 24, /* sort by last modification time */
240SORT_VERSION = 5 << 24, /* sort by version */
241SORT_EXT = 6 << 24, /* sort by file name extension */
242SORT_DIR = 7 << 24, /* sort by file or directory */
243SORT_MASK = (7 << 24) * ENABLE_FEATURE_LS_SORTFILES,
244
245LIST_LONG = LIST_MODEBITS | LIST_NLINKS | LIST_ID_NAME | LIST_SIZE | \
246 LIST_DATE_TIME | LIST_SYMLINK,
247}; 195};
248 196
249/* -Cadil1 Std options, busybox always supports */ 197/* -Cadi1l Std options, busybox always supports */
250/* -gnsxA Std options, busybox always supports */ 198/* -gnsxA Std options, busybox always supports */
251/* -Q GNU option, busybox always supports */ 199/* -Q GNU option, busybox always supports */
252/* -k SELinux option, busybox always supports (ignores if !SELinux) */ 200/* -k Std option, busybox always supports (by ignoring) */
253/* Std has -k which means "show sizes in kbytes" */ 201/* It means "for -s, show sizes in kbytes" */
202/* Seems to only affect "POSIXLY_CORRECT=1 ls -sk" */
203/* since otherwise -s shows kbytes anyway */
254/* -LHRctur Std options, busybox optionally supports */ 204/* -LHRctur Std options, busybox optionally supports */
255/* -Fp Std options, busybox optionally supports */ 205/* -Fp Std options, busybox optionally supports */
256/* -SXvhTw GNU options, busybox optionally supports */ 206/* -SXvhTw GNU options, busybox optionally supports */
257/* -T WIDTH Ignored (we don't use tabs on output) */ 207/* -T WIDTH Ignored (we don't use tabs on output) */
258/* -KZ SELinux mandated options, busybox optionally supports */ 208/* -Z SELinux mandated option, busybox optionally supports */
259/* (coreutils 8.4 has no -K, remove it?) */
260/* -e I think we made this one up (looks similar to GNU --full-time) */
261/* We already used up all 32 bits, if we need to add more, candidates for removal: */
262/* -K, -T, -e (add --full-time instead) */
263static const char ls_options[] ALIGN1 = 209static const char ls_options[] ALIGN1 =
264 "Cadil1gnsxQAk" /* 13 opts, total 13 */ 210 "Cadi1lgnsxAk" /* 12 opts, total 12 */
265 IF_FEATURE_LS_TIMESTAMPS("cetu") /* 4, 17 */ 211 IF_FEATURE_LS_FILETYPES("Fp") /* 2, 14 */
266 IF_FEATURE_LS_SORTFILES("SXrv") /* 4, 21 */ 212 IF_FEATURE_LS_RECURSIVE("R") /* 1, 15 */
267 IF_FEATURE_LS_FILETYPES("Fp") /* 2, 23 */ 213 IF_SELINUX("Z") /* 1, 16 */
268 IF_FEATURE_LS_RECURSIVE("R") /* 1, 24 */ 214 "Q" /* 1, 17 */
269 IF_SELINUX("KZ") /* 2, 26 */ 215 IF_FEATURE_LS_TIMESTAMPS("ctu") /* 3, 20 */
270 IF_FEATURE_LS_FOLLOWLINKS("LH") /* 2, 28 */ 216 IF_FEATURE_LS_SORTFILES("SXrv") /* 4, 24 */
271 IF_FEATURE_HUMAN_READABLE("h") /* 1, 29 */ 217 IF_FEATURE_LS_FOLLOWLINKS("LH") /* 2, 26 */
272 IF_FEATURE_AUTOWIDTH("T:w:") /* 2, 31 */ 218 IF_FEATURE_HUMAN_READABLE("h") /* 1, 27 */
273 /* with --color, we use all 32 bits */; 219 IF_FEATURE_LS_WIDTH("T:w:") /* 2, 29 */
220;
274enum { 221enum {
275 //OPT_C = (1 << 0), 222 OPT_C = (1 << 0),
276 //OPT_a = (1 << 1), 223 OPT_a = (1 << 1),
277 //OPT_d = (1 << 2), 224 OPT_d = (1 << 2),
278 //OPT_i = (1 << 3), 225 OPT_i = (1 << 3),
279 //OPT_l = (1 << 4), 226 OPT_1 = (1 << 4),
280 //OPT_1 = (1 << 5), 227 OPT_l = (1 << 5),
281 OPT_g = (1 << 6), 228 OPT_g = (1 << 6),
282 //OPT_n = (1 << 7), 229 OPT_n = (1 << 7),
283 //OPT_s = (1 << 8), 230 OPT_s = (1 << 8),
284 //OPT_x = (1 << 9), 231 OPT_x = (1 << 9),
285 OPT_Q = (1 << 10), 232 OPT_A = (1 << 10),
286 //OPT_A = (1 << 11), 233 //OPT_k = (1 << 11),
287 //OPT_k = (1 << 12), 234
288 235 OPTBIT_F = 12,
289 OPTBIT_c = 13, 236 OPTBIT_p, /* 13 */
290 OPTBIT_e,
291 OPTBIT_t,
292 OPTBIT_u,
293 OPTBIT_S = OPTBIT_c + 4 * ENABLE_FEATURE_LS_TIMESTAMPS,
294 OPTBIT_X, /* 18 */
295 OPTBIT_r,
296 OPTBIT_v,
297 OPTBIT_F = OPTBIT_S + 4 * ENABLE_FEATURE_LS_SORTFILES,
298 OPTBIT_p, /* 22 */
299 OPTBIT_R = OPTBIT_F + 2 * ENABLE_FEATURE_LS_FILETYPES, 237 OPTBIT_R = OPTBIT_F + 2 * ENABLE_FEATURE_LS_FILETYPES,
300 OPTBIT_K = OPTBIT_R + 1 * ENABLE_FEATURE_LS_RECURSIVE, 238 OPTBIT_Z = OPTBIT_R + 1 * ENABLE_FEATURE_LS_RECURSIVE,
301 OPTBIT_Z, /* 25 */ 239 OPTBIT_Q = OPTBIT_Z + 1 * ENABLE_SELINUX,
302 OPTBIT_L = OPTBIT_K + 2 * ENABLE_SELINUX, 240 OPTBIT_c, /* 17 */
303 OPTBIT_H, /* 27 */ 241 OPTBIT_t, /* 18 */
242 OPTBIT_u, /* 19 */
243 OPTBIT_S = OPTBIT_c + 3 * ENABLE_FEATURE_LS_TIMESTAMPS,
244 OPTBIT_X, /* 21 */
245 OPTBIT_r, /* 22 */
246 OPTBIT_v, /* 23 */
247 OPTBIT_L = OPTBIT_S + 4 * ENABLE_FEATURE_LS_SORTFILES,
248 OPTBIT_H, /* 25 */
304 OPTBIT_h = OPTBIT_L + 2 * ENABLE_FEATURE_LS_FOLLOWLINKS, 249 OPTBIT_h = OPTBIT_L + 2 * ENABLE_FEATURE_LS_FOLLOWLINKS,
305 OPTBIT_T = OPTBIT_h + 1 * ENABLE_FEATURE_HUMAN_READABLE, 250 OPTBIT_T = OPTBIT_h + 1 * ENABLE_FEATURE_HUMAN_READABLE,
306 OPTBIT_w, /* 30 */ 251 OPTBIT_w, /* 28 */
307 OPTBIT_color = OPTBIT_T + 2 * ENABLE_FEATURE_AUTOWIDTH, 252 OPTBIT_full_time = OPTBIT_T + 2 * ENABLE_FEATURE_LS_WIDTH,
253 OPTBIT_dirs_first,
254 OPTBIT_color, /* 31 */
255 /* with long opts, we use all 32 bits */
308 256
257 OPT_F = (1 << OPTBIT_F) * ENABLE_FEATURE_LS_FILETYPES,
258 OPT_p = (1 << OPTBIT_p) * ENABLE_FEATURE_LS_FILETYPES,
259 OPT_R = (1 << OPTBIT_R) * ENABLE_FEATURE_LS_RECURSIVE,
260 OPT_Z = (1 << OPTBIT_Z) * ENABLE_SELINUX,
261 OPT_Q = (1 << OPTBIT_Q),
309 OPT_c = (1 << OPTBIT_c) * ENABLE_FEATURE_LS_TIMESTAMPS, 262 OPT_c = (1 << OPTBIT_c) * ENABLE_FEATURE_LS_TIMESTAMPS,
310 OPT_e = (1 << OPTBIT_e) * ENABLE_FEATURE_LS_TIMESTAMPS,
311 OPT_t = (1 << OPTBIT_t) * ENABLE_FEATURE_LS_TIMESTAMPS, 263 OPT_t = (1 << OPTBIT_t) * ENABLE_FEATURE_LS_TIMESTAMPS,
312 OPT_u = (1 << OPTBIT_u) * ENABLE_FEATURE_LS_TIMESTAMPS, 264 OPT_u = (1 << OPTBIT_u) * ENABLE_FEATURE_LS_TIMESTAMPS,
313 OPT_S = (1 << OPTBIT_S) * ENABLE_FEATURE_LS_SORTFILES, 265 OPT_S = (1 << OPTBIT_S) * ENABLE_FEATURE_LS_SORTFILES,
314 OPT_X = (1 << OPTBIT_X) * ENABLE_FEATURE_LS_SORTFILES, 266 OPT_X = (1 << OPTBIT_X) * ENABLE_FEATURE_LS_SORTFILES,
315 OPT_r = (1 << OPTBIT_r) * ENABLE_FEATURE_LS_SORTFILES, 267 OPT_r = (1 << OPTBIT_r) * ENABLE_FEATURE_LS_SORTFILES,
316 OPT_v = (1 << OPTBIT_v) * ENABLE_FEATURE_LS_SORTFILES, 268 OPT_v = (1 << OPTBIT_v) * ENABLE_FEATURE_LS_SORTFILES,
317 OPT_F = (1 << OPTBIT_F) * ENABLE_FEATURE_LS_FILETYPES,
318 OPT_p = (1 << OPTBIT_p) * ENABLE_FEATURE_LS_FILETYPES,
319 OPT_R = (1 << OPTBIT_R) * ENABLE_FEATURE_LS_RECURSIVE,
320 OPT_K = (1 << OPTBIT_K) * ENABLE_SELINUX,
321 OPT_Z = (1 << OPTBIT_Z) * ENABLE_SELINUX,
322 OPT_L = (1 << OPTBIT_L) * ENABLE_FEATURE_LS_FOLLOWLINKS, 269 OPT_L = (1 << OPTBIT_L) * ENABLE_FEATURE_LS_FOLLOWLINKS,
323 OPT_H = (1 << OPTBIT_H) * ENABLE_FEATURE_LS_FOLLOWLINKS, 270 OPT_H = (1 << OPTBIT_H) * ENABLE_FEATURE_LS_FOLLOWLINKS,
324 OPT_h = (1 << OPTBIT_h) * ENABLE_FEATURE_HUMAN_READABLE, 271 OPT_h = (1 << OPTBIT_h) * ENABLE_FEATURE_HUMAN_READABLE,
325 OPT_T = (1 << OPTBIT_T) * ENABLE_FEATURE_AUTOWIDTH, 272 OPT_T = (1 << OPTBIT_T) * ENABLE_FEATURE_LS_WIDTH,
326 OPT_w = (1 << OPTBIT_w) * ENABLE_FEATURE_AUTOWIDTH, 273 OPT_w = (1 << OPTBIT_w) * ENABLE_FEATURE_LS_WIDTH,
327 OPT_color = (1 << OPTBIT_color) * ENABLE_FEATURE_LS_COLOR, 274 OPT_full_time = (1 << OPTBIT_full_time ) * ENABLE_LONG_OPTS,
328}; 275 OPT_dirs_first = (1 << OPTBIT_dirs_first) * ENABLE_LONG_OPTS,
329 276 OPT_color = (1 << OPTBIT_color ) * ENABLE_FEATURE_LS_COLOR,
330/* TODO: simple toggles may be stored as OPT_xxx bits instead */
331static const uint32_t opt_flags[] = {
332 STYLE_COLUMNAR, /* C */
333 DISP_HIDDEN | DISP_DOT, /* a */
334 DISP_NOLIST, /* d */
335 LIST_INO, /* i */
336 LIST_LONG | STYLE_LONG, /* l */
337 STYLE_SINGLE, /* 1 */
338 LIST_LONG | STYLE_LONG, /* g (don't show owner) - handled via OPT_g. assumes l */
339 LIST_ID_NUMERIC | LIST_LONG | STYLE_LONG, /* n (assumes l) */
340 LIST_BLOCKS, /* s */
341 DISP_ROWS | STYLE_COLUMNAR, /* x */
342 0, /* Q (quote filename) - handled via OPT_Q */
343 DISP_HIDDEN, /* A */
344 ENABLE_SELINUX * (LIST_CONTEXT|STYLE_SINGLE), /* k (ignored if !SELINUX) */
345#if ENABLE_FEATURE_LS_TIMESTAMPS
346 TIME_CHANGE | (ENABLE_FEATURE_LS_SORTFILES * SORT_CTIME), /* c */
347 LIST_FULLTIME, /* e */
348 ENABLE_FEATURE_LS_SORTFILES * SORT_MTIME, /* t */
349 TIME_ACCESS | (ENABLE_FEATURE_LS_SORTFILES * SORT_ATIME), /* u */
350#endif
351#if ENABLE_FEATURE_LS_SORTFILES
352 SORT_SIZE, /* S */
353 SORT_EXT, /* X */
354 SORT_REVERSE, /* r */
355 SORT_VERSION, /* v */
356#endif
357#if ENABLE_FEATURE_LS_FILETYPES
358 LIST_FILETYPE | LIST_CLASSIFY, /* F */
359 LIST_FILETYPE, /* p */
360#endif
361#if ENABLE_FEATURE_LS_RECURSIVE
362 DISP_RECURSIVE, /* R */
363#endif
364#if ENABLE_SELINUX
365 LIST_MODEBITS|LIST_NLINKS|LIST_CONTEXT|LIST_SIZE|LIST_DATE_TIME|STYLE_SINGLE, /* K */
366 LIST_MODEBITS|LIST_ID_NAME|LIST_CONTEXT|STYLE_SINGLE, /* Z */
367#endif
368 (1U << 31)
369 /* options after Z are not processed through opt_flags */
370}; 277};
371 278
372
373/* 279/*
374 * a directory entry and its stat info 280 * a directory entry and its stat info
375 */ 281 */
@@ -399,9 +305,7 @@ struct dnode {
399 mode_t dn_mode; /* obtained with lstat OR stat, depending on -L etc */ 305 mode_t dn_mode; /* obtained with lstat OR stat, depending on -L etc */
400 off_t dn_size; 306 off_t dn_size;
401#if ENABLE_FEATURE_LS_TIMESTAMPS || ENABLE_FEATURE_LS_SORTFILES 307#if ENABLE_FEATURE_LS_TIMESTAMPS || ENABLE_FEATURE_LS_SORTFILES
402 time_t dn_atime; 308 time_t dn_time;
403 time_t dn_mtime;
404 time_t dn_ctime;
405#endif 309#endif
406 ino_t dn_ino; 310 ino_t dn_ino;
407 blkcnt_t dn_blocks; 311 blkcnt_t dn_blocks;
@@ -422,8 +326,8 @@ struct globals {
422# define G_show_color 0 326# define G_show_color 0
423#endif 327#endif
424 smallint exit_code; 328 smallint exit_code;
425 unsigned all_fmt; 329 smallint show_dirname;
426#if ENABLE_FEATURE_AUTOWIDTH 330#if ENABLE_FEATURE_LS_WIDTH
427 unsigned terminal_width; 331 unsigned terminal_width;
428# define G_terminal_width (G.terminal_width) 332# define G_terminal_width (G.terminal_width)
429#else 333#else
@@ -439,7 +343,7 @@ struct globals {
439 setup_common_bufsiz(); \ 343 setup_common_bufsiz(); \
440 /* we have to zero it out because of NOEXEC */ \ 344 /* we have to zero it out because of NOEXEC */ \
441 memset(&G, 0, sizeof(G)); \ 345 memset(&G, 0, sizeof(G)); \
442 IF_FEATURE_AUTOWIDTH(G_terminal_width = TERMINAL_WIDTH;) \ 346 IF_FEATURE_LS_WIDTH(G_terminal_width = TERMINAL_WIDTH;) \
443 IF_FEATURE_LS_TIMESTAMPS(time(&G.current_time_t);) \ 347 IF_FEATURE_LS_TIMESTAMPS(time(&G.current_time_t);) \
444} while (0) 348} while (0)
445 349
@@ -496,11 +400,12 @@ static char bold(mode_t mode)
496#if ENABLE_FEATURE_LS_FILETYPES 400#if ENABLE_FEATURE_LS_FILETYPES
497static char append_char(mode_t mode) 401static char append_char(mode_t mode)
498{ 402{
499 if (!(G.all_fmt & LIST_FILETYPE)) 403 if (!(option_mask32 & (OPT_F|OPT_p)))
500 return '\0'; 404 return '\0';
405
501 if (S_ISDIR(mode)) 406 if (S_ISDIR(mode))
502 return '/'; 407 return '/';
503 if (!(G.all_fmt & LIST_CLASSIFY)) 408 if (!(option_mask32 & OPT_F))
504 return '\0'; 409 return '\0';
505 if (S_ISREG(mode) && (mode & (S_IXUSR | S_IXGRP | S_IXOTH))) 410 if (S_ISREG(mode) && (mode & (S_IXUSR | S_IXGRP | S_IXOTH)))
506 return '*'; 411 return '*';
@@ -531,8 +436,8 @@ static unsigned calc_name_len(const char *name)
531} 436}
532 437
533/* Return the number of used columns. 438/* Return the number of used columns.
534 * Note that only STYLE_COLUMNAR uses return value. 439 * Note that only columnar output uses return value.
535 * STYLE_SINGLE and STYLE_LONG don't care. 440 * -l and -1 modes don't care.
536 * coreutils 7.2 also supports: 441 * coreutils 7.2 also supports:
537 * ls -b (--escape) = octal escapes (although it doesn't look like working) 442 * ls -b (--escape) = octal escapes (although it doesn't look like working)
538 * ls -N (--literal) = not escape at all 443 * ls -N (--literal) = not escape at all
@@ -565,13 +470,14 @@ static unsigned print_name(const char *name)
565} 470}
566 471
567/* Return the number of used columns. 472/* Return the number of used columns.
568 * Note that only STYLE_COLUMNAR uses return value, 473 * Note that only columnar output uses return value,
569 * STYLE_SINGLE and STYLE_LONG don't care. 474 * -l and -1 modes don't care.
570 */ 475 */
571static NOINLINE unsigned display_single(const struct dnode *dn) 476static NOINLINE unsigned display_single(const struct dnode *dn)
572{ 477{
573 unsigned column = 0; 478 unsigned column = 0;
574 char *lpath; 479 char *lpath;
480 int opt;
575#if ENABLE_FEATURE_LS_FILETYPES || ENABLE_FEATURE_LS_COLOR 481#if ENABLE_FEATURE_LS_FILETYPES || ENABLE_FEATURE_LS_COLOR
576 struct stat statbuf; 482 struct stat statbuf;
577 char append; 483 char append;
@@ -580,50 +486,61 @@ static NOINLINE unsigned display_single(const struct dnode *dn)
580#if ENABLE_FEATURE_LS_FILETYPES 486#if ENABLE_FEATURE_LS_FILETYPES
581 append = append_char(dn->dn_mode); 487 append = append_char(dn->dn_mode);
582#endif 488#endif
489 opt = option_mask32;
583 490
584 /* Do readlink early, so that if it fails, error message 491 /* Do readlink early, so that if it fails, error message
585 * does not appear *inside* the "ls -l" line */ 492 * does not appear *inside* the "ls -l" line */
586 lpath = NULL; 493 lpath = NULL;
587 if (G.all_fmt & LIST_SYMLINK) 494 if (opt & OPT_l)
588 if (S_ISLNK(dn->dn_mode)) 495 if (S_ISLNK(dn->dn_mode))
589 lpath = xmalloc_readlink_or_warn(dn->fullname); 496 lpath = xmalloc_readlink_or_warn(dn->fullname);
590 497
591 if (G.all_fmt & LIST_INO) 498 if (opt & OPT_i) /* show inode# */
592 column += printf("%7llu ", (long long) dn->dn_ino); 499 column += printf("%7llu ", (long long) dn->dn_ino);
593//TODO: -h should affect -s too: 500//TODO: -h should affect -s too:
594 if (G.all_fmt & LIST_BLOCKS) 501 if (opt & OPT_s) /* show allocated blocks */
595 column += printf("%6"OFF_FMT"u ", (off_t) (dn->dn_blocks >> 1)); 502 column += printf("%6"OFF_FMT"u ", (off_t) (dn->dn_blocks >> 1));
596 if (G.all_fmt & LIST_MODEBITS) 503 if (opt & OPT_l) {
504 /* long listing: show mode */
597 column += printf("%-10s ", (char *) bb_mode_string(dn->dn_mode)); 505 column += printf("%-10s ", (char *) bb_mode_string(dn->dn_mode));
598 if (G.all_fmt & LIST_NLINKS) 506 /* long listing: show number of links */
599 column += printf("%4lu ", (long) dn->dn_nlink); 507 column += printf("%4lu ", (long) dn->dn_nlink);
600 if (G.all_fmt & LIST_ID_NUMERIC) { 508 /* long listing: show user/group */
601 if (option_mask32 & OPT_g) 509 if (opt & OPT_n) {
602 column += printf("%-8u ", (int) dn->dn_gid); 510 if (opt & OPT_g)
603 else 511 column += printf("%-8u ", (int) dn->dn_gid);
604 column += printf("%-8u %-8u ", 512 else
605 (int) dn->dn_uid, 513 column += printf("%-8u %-8u ",
606 (int) dn->dn_gid); 514 (int) dn->dn_uid,
607 } 515 (int) dn->dn_gid);
516 }
608#if ENABLE_FEATURE_LS_USERNAME 517#if ENABLE_FEATURE_LS_USERNAME
609 else if (G.all_fmt & LIST_ID_NAME) { 518 else {
610 if (option_mask32 & OPT_g) { 519 if (opt & OPT_g) {
611 column += printf("%-8.8s ", 520 column += printf("%-8.8s ",
612 get_cached_groupname(dn->dn_gid)); 521 get_cached_groupname(dn->dn_gid));
613 } else { 522 } else {
614 column += printf("%-8.8s %-8.8s ", 523 column += printf("%-8.8s %-8.8s ",
615 get_cached_username(dn->dn_uid), 524 get_cached_username(dn->dn_uid),
616 get_cached_groupname(dn->dn_gid)); 525 get_cached_groupname(dn->dn_gid));
526 }
617 } 527 }
528#endif
529#if ENABLE_SELINUX
530 }
531 if (opt & OPT_Z) {
532 column += printf("%-32s ", dn->sid ? dn->sid : "?");
533 freecon(dn->sid);
618 } 534 }
535 if (opt & OPT_l) {
619#endif 536#endif
620 if (G.all_fmt & LIST_SIZE) { 537 /* long listing: show size */
621 if (S_ISBLK(dn->dn_mode) || S_ISCHR(dn->dn_mode)) { 538 if (S_ISBLK(dn->dn_mode) || S_ISCHR(dn->dn_mode)) {
622 column += printf("%4u, %3u ", 539 column += printf("%4u, %3u ",
623 dn->dn_rdev_maj, 540 dn->dn_rdev_maj,
624 dn->dn_rdev_min); 541 dn->dn_rdev_min);
625 } else { 542 } else {
626 if (option_mask32 & OPT_h) { 543 if (opt & OPT_h) {
627 column += printf("%"HUMAN_READABLE_MAX_WIDTH_STR"s ", 544 column += printf("%"HUMAN_READABLE_MAX_WIDTH_STR"s ",
628 /* print size, show one fractional, use suffixes */ 545 /* print size, show one fractional, use suffixes */
629 make_human_readable_str(dn->dn_size, 1, 0) 546 make_human_readable_str(dn->dn_size, 1, 0)
@@ -632,25 +549,22 @@ static NOINLINE unsigned display_single(const struct dnode *dn)
632 column += printf("%9"OFF_FMT"u ", dn->dn_size); 549 column += printf("%9"OFF_FMT"u ", dn->dn_size);
633 } 550 }
634 } 551 }
635 }
636#if ENABLE_FEATURE_LS_TIMESTAMPS 552#if ENABLE_FEATURE_LS_TIMESTAMPS
637 if (G.all_fmt & (LIST_FULLTIME|LIST_DATE_TIME)) { 553 /* long listing: show {m,c,a}time */
638 char *filetime; 554 if (opt & OPT_full_time) { /* --full-time */
639 const time_t *ttime = &dn->dn_mtime; 555 /* coreutils 8.4 ls --full-time prints:
640 if (G.all_fmt & TIME_ACCESS)
641 ttime = &dn->dn_atime;
642 if (G.all_fmt & TIME_CHANGE)
643 ttime = &dn->dn_ctime;
644 filetime = ctime(ttime);
645 /* filetime's format: "Wed Jun 30 21:49:08 1993\n" */
646 if (G.all_fmt & LIST_FULLTIME) { /* -e */
647 /* Note: coreutils 8.4 ls --full-time prints:
648 * 2009-07-13 17:49:27.000000000 +0200 556 * 2009-07-13 17:49:27.000000000 +0200
557 * we don't show fractional seconds.
649 */ 558 */
650 column += printf("%.24s ", filetime); 559 char buf[sizeof("YYYY-mm-dd HH:MM:SS TIMEZONE")];
651 } else { /* LIST_DATE_TIME */ 560 strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S %z",
652 /* G.current_time_t ~== time(NULL) */ 561 localtime(&dn->dn_time));
653 time_t age = G.current_time_t - *ttime; 562 column += printf("%s ", buf);
563 } else { /* ordinary time format */
564 /* G.current_time_t is ~== time(NULL) */
565 char *filetime = ctime(&dn->dn_time);
566 /* filetime's format: "Wed Jun 30 21:49:08 1993\n" */
567 time_t age = G.current_time_t - dn->dn_time;
654 if (age < 3600L * 24 * 365 / 2 && age > -15 * 60) { 568 if (age < 3600L * 24 * 365 / 2 && age > -15 * 60) {
655 /* less than 6 months old */ 569 /* less than 6 months old */
656 /* "mmm dd hh:mm " */ 570 /* "mmm dd hh:mm " */
@@ -663,14 +577,8 @@ static NOINLINE unsigned display_single(const struct dnode *dn)
663 } 577 }
664 column += 13; 578 column += 13;
665 } 579 }
666 }
667#endif 580#endif
668#if ENABLE_SELINUX
669 if (G.all_fmt & LIST_CONTEXT) {
670 column += printf("%-32s ", dn->sid ? dn->sid : "unknown");
671 freecon(dn->sid);
672 } 581 }
673#endif
674 582
675#if ENABLE_FEATURE_LS_COLOR 583#if ENABLE_FEATURE_LS_COLOR
676 if (G_show_color) { 584 if (G_show_color) {
@@ -689,7 +597,9 @@ static NOINLINE unsigned display_single(const struct dnode *dn)
689 if (lpath) { 597 if (lpath) {
690 printf(" -> "); 598 printf(" -> ");
691#if ENABLE_FEATURE_LS_FILETYPES || ENABLE_FEATURE_LS_COLOR 599#if ENABLE_FEATURE_LS_FILETYPES || ENABLE_FEATURE_LS_COLOR
692 if ((G.all_fmt & LIST_FILETYPE) || G_show_color) { 600 if ((opt & (OPT_F|OPT_p))
601 || G_show_color
602 ) {
693 mode_t mode = dn->dn_mode_stat; 603 mode_t mode = dn->dn_mode_stat;
694 if (!mode) 604 if (!mode)
695 if (stat(dn->fullname, &statbuf) == 0) 605 if (stat(dn->fullname, &statbuf) == 0)
@@ -711,7 +621,7 @@ static NOINLINE unsigned display_single(const struct dnode *dn)
711 } 621 }
712 } 622 }
713#if ENABLE_FEATURE_LS_FILETYPES 623#if ENABLE_FEATURE_LS_FILETYPES
714 if (G.all_fmt & LIST_FILETYPE) { 624 if (opt & (OPT_F|OPT_p)) {
715 if (append) { 625 if (append) {
716 putchar(append); 626 putchar(append);
717 column++; 627 column++;
@@ -727,9 +637,9 @@ static void display_files(struct dnode **dn, unsigned nfiles)
727 unsigned i, ncols, nrows, row, nc; 637 unsigned i, ncols, nrows, row, nc;
728 unsigned column; 638 unsigned column;
729 unsigned nexttab; 639 unsigned nexttab;
730 unsigned column_width = 0; /* used only by STYLE_COLUMNAR */ 640 unsigned column_width = 0; /* used only by coulmnal output */
731 641
732 if (G.all_fmt & STYLE_LONG) { /* STYLE_LONG or STYLE_SINGLE */ 642 if (option_mask32 & (OPT_l|OPT_1)) {
733 ncols = 1; 643 ncols = 1;
734 } else { 644 } else {
735 /* find the longest file name, use that as the column width */ 645 /* find the longest file name, use that as the column width */
@@ -738,10 +648,11 @@ static void display_files(struct dnode **dn, unsigned nfiles)
738 if (column_width < len) 648 if (column_width < len)
739 column_width = len; 649 column_width = len;
740 } 650 }
741 column_width += 2 + 651 column_width += 2
742 IF_SELINUX( ((G.all_fmt & LIST_CONTEXT) ? 33 : 0) + ) 652 + ((option_mask32 & OPT_Z) ? 33 : 0) /* context width */
743 ((G.all_fmt & LIST_INO) ? 8 : 0) + 653 + ((option_mask32 & OPT_i) ? 8 : 0) /* inode# width */
744 ((G.all_fmt & LIST_BLOCKS) ? 5 : 0); 654 + ((option_mask32 & OPT_s) ? 5 : 0) /* "alloc block" width */
655 ;
745 ncols = (unsigned)G_terminal_width / column_width; 656 ncols = (unsigned)G_terminal_width / column_width;
746 } 657 }
747 658
@@ -759,7 +670,7 @@ static void display_files(struct dnode **dn, unsigned nfiles)
759 for (row = 0; row < nrows; row++) { 670 for (row = 0; row < nrows; row++) {
760 for (nc = 0; nc < ncols; nc++) { 671 for (nc = 0; nc < ncols; nc++) {
761 /* reach into the array based on the column and row */ 672 /* reach into the array based on the column and row */
762 if (G.all_fmt & DISP_ROWS) 673 if (option_mask32 & OPT_x)
763 i = (row * ncols) + nc; /* display across row */ 674 i = (row * ncols) + nc; /* display across row */
764 else 675 else
765 i = (nc * nrows) + row; /* display by column */ 676 i = (nc * nrows) + row; /* display by column */
@@ -792,7 +703,7 @@ static struct dnode *my_stat(const char *fullname, const char *name, int force_f
792 703
793 if ((option_mask32 & OPT_L) || force_follow) { 704 if ((option_mask32 & OPT_L) || force_follow) {
794#if ENABLE_SELINUX 705#if ENABLE_SELINUX
795 if (is_selinux_enabled()) { 706 if (option_mask32 & OPT_Z) {
796 getfilecon(fullname, &cur->sid); 707 getfilecon(fullname, &cur->sid);
797 } 708 }
798#endif 709#endif
@@ -805,7 +716,7 @@ static struct dnode *my_stat(const char *fullname, const char *name, int force_f
805 cur->dn_mode_stat = statbuf.st_mode; 716 cur->dn_mode_stat = statbuf.st_mode;
806 } else { 717 } else {
807#if ENABLE_SELINUX 718#if ENABLE_SELINUX
808 if (is_selinux_enabled()) { 719 if (option_mask32 & OPT_Z) {
809 lgetfilecon(fullname, &cur->sid); 720 lgetfilecon(fullname, &cur->sid);
810 } 721 }
811#endif 722#endif
@@ -822,9 +733,11 @@ static struct dnode *my_stat(const char *fullname, const char *name, int force_f
822 cur->dn_mode = statbuf.st_mode ; 733 cur->dn_mode = statbuf.st_mode ;
823 cur->dn_size = statbuf.st_size ; 734 cur->dn_size = statbuf.st_size ;
824#if ENABLE_FEATURE_LS_TIMESTAMPS || ENABLE_FEATURE_LS_SORTFILES 735#if ENABLE_FEATURE_LS_TIMESTAMPS || ENABLE_FEATURE_LS_SORTFILES
825 cur->dn_atime = statbuf.st_atime ; 736 cur->dn_time = statbuf.st_mtime ;
826 cur->dn_mtime = statbuf.st_mtime ; 737 if (option_mask32 & OPT_u)
827 cur->dn_ctime = statbuf.st_ctime ; 738 cur->dn_time = statbuf.st_atime;
739 if (option_mask32 & OPT_c)
740 cur->dn_time = statbuf.st_ctime;
828#endif 741#endif
829 cur->dn_ino = statbuf.st_ino ; 742 cur->dn_ino = statbuf.st_ino ;
830 cur->dn_blocks = statbuf.st_blocks; 743 cur->dn_blocks = statbuf.st_blocks;
@@ -938,33 +851,30 @@ static int sortcmp(const void *a, const void *b)
938{ 851{
939 struct dnode *d1 = *(struct dnode **)a; 852 struct dnode *d1 = *(struct dnode **)a;
940 struct dnode *d2 = *(struct dnode **)b; 853 struct dnode *d2 = *(struct dnode **)b;
941 unsigned sort_opts = G.all_fmt & SORT_MASK; 854 unsigned opt = option_mask32;
942 off_t dif; 855 off_t dif;
943 856
944 dif = 0; /* assume SORT_NAME */ 857 dif = 0; /* assume sort by name */
945 // TODO: use pre-initialized function pointer 858 // TODO: use pre-initialized function pointer
946 // instead of branch forest 859 // instead of branch forest
947 if (sort_opts == SORT_SIZE) { 860 if (opt & OPT_dirs_first) {
861 dif = S_ISDIR(d2->dn_mode) - S_ISDIR(d1->dn_mode);
862 if (dif != 0)
863 goto maybe_invert_and_ret;
864 }
865
866 if (opt & OPT_S) { /* sort by size */
948 dif = (d2->dn_size - d1->dn_size); 867 dif = (d2->dn_size - d1->dn_size);
949 } else 868 } else
950 if (sort_opts == SORT_ATIME) { 869 if (opt & OPT_t) { /* sort by time */
951 dif = (d2->dn_atime - d1->dn_atime); 870 dif = (d2->dn_time - d1->dn_time);
952 } else
953 if (sort_opts == SORT_CTIME) {
954 dif = (d2->dn_ctime - d1->dn_ctime);
955 } else
956 if (sort_opts == SORT_MTIME) {
957 dif = (d2->dn_mtime - d1->dn_mtime);
958 } else
959 if (sort_opts == SORT_DIR) {
960 dif = S_ISDIR(d2->dn_mode) - S_ISDIR(d1->dn_mode);
961 } else 871 } else
962#if defined(HAVE_STRVERSCMP) && HAVE_STRVERSCMP == 1 872#if defined(HAVE_STRVERSCMP) && HAVE_STRVERSCMP == 1
963 if (sort_opts == SORT_VERSION) { 873 if (opt & OPT_v) { /* sort by version */
964 dif = strverscmp(d1->name, d2->name); 874 dif = strverscmp(d1->name, d2->name);
965 } else 875 } else
966#endif 876#endif
967 if (sort_opts == SORT_EXT) { 877 if (opt & OPT_X) { /* sort by extension */
968 dif = strcmp(strchrnul(d1->name, '.'), strchrnul(d2->name, '.')); 878 dif = strcmp(strchrnul(d1->name, '.'), strchrnul(d2->name, '.'));
969 } 879 }
970 if (dif == 0) { 880 if (dif == 0) {
@@ -973,18 +883,17 @@ static int sortcmp(const void *a, const void *b)
973 dif = strcoll(d1->name, d2->name); 883 dif = strcoll(d1->name, d2->name);
974 else 884 else
975 dif = strcmp(d1->name, d2->name); 885 dif = strcmp(d1->name, d2->name);
976 } 886 } else {
977 887 /* Make dif fit into an int */
978 /* Make dif fit into an int */ 888 if (sizeof(dif) > sizeof(int)) {
979 if (sizeof(dif) > sizeof(int)) { 889 enum { BITS_TO_SHIFT = 8 * (sizeof(dif) - sizeof(int)) };
980 enum { BITS_TO_SHIFT = 8 * (sizeof(dif) - sizeof(int)) }; 890 /* shift leaving only "int" worth of bits */
981 /* shift leaving only "int" worth of bits */ 891 /* (this requires dif != 0, and here it is nonzero) */
982 if (dif != 0) {
983 dif = 1 | (int)((uoff_t)dif >> BITS_TO_SHIFT); 892 dif = 1 | (int)((uoff_t)dif >> BITS_TO_SHIFT);
984 } 893 }
985 } 894 }
986 895 maybe_invert_and_ret:
987 return (G.all_fmt & SORT_REVERSE) ? -(int)dif : (int)dif; 896 return (opt & OPT_r) ? -(int)dif : (int)dif;
988} 897}
989 898
990static void dnsort(struct dnode **dn, int size) 899static void dnsort(struct dnode **dn, int size)
@@ -1023,13 +932,13 @@ static struct dnode **scan_one_dir(const char *path, unsigned *nfiles_p)
1023 932
1024 /* are we going to list the file- it may be . or .. or a hidden file */ 933 /* are we going to list the file- it may be . or .. or a hidden file */
1025 if (entry->d_name[0] == '.') { 934 if (entry->d_name[0] == '.') {
1026 if ((!entry->d_name[1] || (entry->d_name[1] == '.' && !entry->d_name[2])) 935 if (!(option_mask32 & (OPT_a|OPT_A)))
1027 && !(G.all_fmt & DISP_DOT) 936 continue; /* skip all dotfiles if no -a/-A */
937 if (!(option_mask32 & OPT_a)
938 && (!entry->d_name[1] || (entry->d_name[1] == '.' && !entry->d_name[2]))
1028 ) { 939 ) {
1029 continue; 940 continue; /* if only -A, skip . and .. but show other dotfiles */
1030 } 941 }
1031 if (!(G.all_fmt & DISP_HIDDEN))
1032 continue;
1033 } 942 }
1034 fullname = concat_path_file(path, entry->d_name); 943 fullname = concat_path_file(path, entry->d_name);
1035 cur = my_stat(fullname, bb_basename(fullname), 0); 944 cur = my_stat(fullname, bb_basename(fullname), 0);
@@ -1097,7 +1006,7 @@ static void scan_and_display_dirs_recur(struct dnode **dn, int first)
1097 struct dnode **subdnp; 1006 struct dnode **subdnp;
1098 1007
1099 for (; *dn; dn++) { 1008 for (; *dn; dn++) {
1100 if (G.all_fmt & (DISP_DIRNAME | DISP_RECURSIVE)) { 1009 if (G.show_dirname || (option_mask32 & OPT_R)) {
1101 if (!first) 1010 if (!first)
1102 bb_putchar('\n'); 1011 bb_putchar('\n');
1103 first = 0; 1012 first = 0;
@@ -1105,15 +1014,16 @@ static void scan_and_display_dirs_recur(struct dnode **dn, int first)
1105 } 1014 }
1106 subdnp = scan_one_dir((*dn)->fullname, &nfiles); 1015 subdnp = scan_one_dir((*dn)->fullname, &nfiles);
1107#if ENABLE_DESKTOP 1016#if ENABLE_DESKTOP
1108 if ((G.all_fmt & STYLE_MASK) == STYLE_LONG || (G.all_fmt & LIST_BLOCKS)) 1017 if (option_mask32 & (OPT_s|OPT_l)) {
1109 printf("total %"OFF_FMT"u\n", calculate_blocks(subdnp)); 1018 printf("total %"OFF_FMT"u\n", calculate_blocks(subdnp));
1019 }
1110#endif 1020#endif
1111 if (nfiles > 0) { 1021 if (nfiles > 0) {
1112 /* list all files at this level */ 1022 /* list all files at this level */
1113 sort_and_display_files(subdnp, nfiles); 1023 sort_and_display_files(subdnp, nfiles);
1114 1024
1115 if (ENABLE_FEATURE_LS_RECURSIVE 1025 if (ENABLE_FEATURE_LS_RECURSIVE
1116 && (G.all_fmt & DISP_RECURSIVE) 1026 && (option_mask32 & OPT_R)
1117 ) { 1027 ) {
1118 struct dnode **dnd; 1028 struct dnode **dnd;
1119 unsigned dndirs; 1029 unsigned dndirs;
@@ -1135,7 +1045,7 @@ static void scan_and_display_dirs_recur(struct dnode **dn, int first)
1135 1045
1136 1046
1137int ls_main(int argc UNUSED_PARAM, char **argv) 1047int ls_main(int argc UNUSED_PARAM, char **argv)
1138{ 1048{ /* ^^^^^^^^^^^^^^^^^ note: if FTPD, argc can be wrong, see ftpd.c */
1139 struct dnode **dnd; 1049 struct dnode **dnd;
1140 struct dnode **dnf; 1050 struct dnode **dnf;
1141 struct dnode **dnp; 1051 struct dnode **dnp;
@@ -1158,7 +1068,10 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
1158 * (and substrings: "--color=alwa" work too) 1068 * (and substrings: "--color=alwa" work too)
1159 */ 1069 */
1160 static const char ls_longopts[] ALIGN1 = 1070 static const char ls_longopts[] ALIGN1 =
1161 "color\0" Optional_argument "\xff"; /* no short equivalent */ 1071 "full-time\0" No_argument "\xff"
1072 "group-directories-first\0" No_argument "\xfe"
1073 "color\0" Optional_argument "\xfd"
1074 ;
1162 static const char color_str[] ALIGN1 = 1075 static const char color_str[] ALIGN1 =
1163 "always\0""yes\0""force\0" 1076 "always\0""yes\0""force\0"
1164 "auto\0""tty\0""if-tty\0"; 1077 "auto\0""tty\0""if-tty\0";
@@ -1170,10 +1083,7 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
1170 1083
1171 init_unicode(); 1084 init_unicode();
1172 1085
1173 if (ENABLE_FEATURE_LS_SORTFILES) 1086#if ENABLE_FEATURE_LS_WIDTH
1174 G.all_fmt = SORT_NAME;
1175
1176#if ENABLE_FEATURE_AUTOWIDTH
1177 /* obtain the terminal width */ 1087 /* obtain the terminal width */
1178 G_terminal_width = get_terminal_width(STDIN_FILENO); 1088 G_terminal_width = get_terminal_width(STDIN_FILENO);
1179 /* go one less... */ 1089 /* go one less... */
@@ -1183,8 +1093,10 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
1183 /* process options */ 1093 /* process options */
1184 IF_FEATURE_LS_COLOR(applet_long_options = ls_longopts;) 1094 IF_FEATURE_LS_COLOR(applet_long_options = ls_longopts;)
1185 opt_complementary = 1095 opt_complementary =
1186 /* -e implies -l */ 1096 /* -n and -g imply -l */
1187 IF_FEATURE_LS_TIMESTAMPS("el") 1097 "nl:gl"
1098 /* --full-time implies -l */
1099 IF_FEATURE_LS_TIMESTAMPS(IF_LONG_OPTS(":\xff""l"))
1188 /* http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ls.html: 1100 /* http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ls.html:
1189 * in some pairs of opts, only last one takes effect: 1101 * in some pairs of opts, only last one takes effect:
1190 */ 1102 */
@@ -1196,25 +1108,28 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
1196 ":x-1:1-x" /* bylines/oneline (not in SuS, but in GNU coreutils 8.4) */ 1108 ":x-1:1-x" /* bylines/oneline (not in SuS, but in GNU coreutils 8.4) */
1197 IF_FEATURE_LS_TIMESTAMPS(":c-u:u-c") /* mtime/atime */ 1109 IF_FEATURE_LS_TIMESTAMPS(":c-u:u-c") /* mtime/atime */
1198 /* -w NUM: */ 1110 /* -w NUM: */
1199 IF_FEATURE_AUTOWIDTH(":w+"); 1111 IF_FEATURE_LS_WIDTH(":w+");
1200 opt = getopt32(argv, ls_options 1112 opt = getopt32(argv, ls_options
1201 IF_FEATURE_AUTOWIDTH(, NULL, &G_terminal_width) 1113 IF_FEATURE_LS_WIDTH(, /*-T*/ NULL, /*-w*/ &G_terminal_width)
1202 IF_FEATURE_LS_COLOR(, &color_opt) 1114 IF_FEATURE_LS_COLOR(, &color_opt)
1203 ); 1115 );
1204 for (i = 0; opt_flags[i] != (1U << 31); i++) { 1116#if 0 /* option bits debug */
1205 if (opt & (1 << i)) { 1117 bb_error_msg("opt:0x%08x l:%x H:%x color:%x dirs:%x", opt, OPT_l, OPT_H, OPT_color, OPT_dirs_first);
1206 uint32_t flags = opt_flags[i]; 1118 if (opt & OPT_c ) bb_error_msg("-c");
1207 1119 if (opt & OPT_l ) bb_error_msg("-l");
1208 if (flags & STYLE_MASK) 1120 if (opt & OPT_H ) bb_error_msg("-H");
1209 G.all_fmt &= ~STYLE_MASK; 1121 if (opt & OPT_color ) bb_error_msg("--color");
1210 if (flags & SORT_MASK) 1122 if (opt & OPT_dirs_first) bb_error_msg("--group-directories-first");
1211 G.all_fmt &= ~SORT_MASK; 1123 if (opt & OPT_full_time ) bb_error_msg("--full-time");
1212 if (flags & TIME_MASK) 1124 exit(0);
1213 G.all_fmt &= ~TIME_MASK; 1125#endif
1214 1126
1215 G.all_fmt |= flags; 1127#if ENABLE_SELINUX
1216 } 1128 if (opt & OPT_Z) {
1129 if (!is_selinux_enabled())
1130 option_mask32 &= ~OPT_Z;
1217 } 1131 }
1132#endif
1218 1133
1219#if ENABLE_FEATURE_LS_COLOR 1134#if ENABLE_FEATURE_LS_COLOR
1220 /* set G_show_color = 1/0 */ 1135 /* set G_show_color = 1/0 */
@@ -1242,27 +1157,35 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
1242#endif 1157#endif
1243 1158
1244 /* sort out which command line options take precedence */ 1159 /* sort out which command line options take precedence */
1245 if (ENABLE_FEATURE_LS_RECURSIVE && (G.all_fmt & DISP_NOLIST)) 1160 if (ENABLE_FEATURE_LS_RECURSIVE && (opt & OPT_d))
1246 G.all_fmt &= ~DISP_RECURSIVE; /* no recurse if listing only dir */ 1161 option_mask32 &= ~OPT_R; /* no recurse if listing only dir */
1247 if (ENABLE_FEATURE_LS_TIMESTAMPS && ENABLE_FEATURE_LS_SORTFILES) { 1162 if (!(opt & OPT_l)) { /* not -l? */
1248 if (G.all_fmt & TIME_CHANGE) 1163 if (ENABLE_FEATURE_LS_TIMESTAMPS && ENABLE_FEATURE_LS_SORTFILES) {
1249 G.all_fmt = (G.all_fmt & ~SORT_MASK) | SORT_CTIME; 1164 /* when to sort by time? -t[cu] sorts by time even with -l */
1250 if (G.all_fmt & TIME_ACCESS) 1165 /* (this is achieved by opt_flags[] element for -t) */
1251 G.all_fmt = (G.all_fmt & ~SORT_MASK) | SORT_ATIME; 1166 /* without -l, bare -c or -u enable sort too */
1167 /* (with -l, bare -c or -u just select which time to show) */
1168 if (opt & (OPT_c|OPT_u)) {
1169 option_mask32 |= OPT_t;
1170 }
1171 }
1252 } 1172 }
1253 if ((G.all_fmt & STYLE_MASK) != STYLE_LONG) /* not -l? */
1254 G.all_fmt &= ~(LIST_ID_NUMERIC|LIST_ID_NAME|LIST_FULLTIME);
1255 1173
1256 /* choose a display format if one was not already specified by an option */ 1174 /* choose a display format if one was not already specified by an option */
1257 if (!(G.all_fmt & STYLE_MASK)) 1175 if (!(option_mask32 & (OPT_l|OPT_1|OPT_x|OPT_C)))
1258 G.all_fmt |= (isatty(STDOUT_FILENO) ? STYLE_COLUMNAR : STYLE_SINGLE); 1176 option_mask32 |= (isatty(STDOUT_FILENO) ? OPT_C : OPT_1);
1177
1178 if (ENABLE_FTPD && applet_name[0] == 'f') {
1179 /* ftpd secret backdoor. dirs first are much nicer */
1180 option_mask32 |= OPT_dirs_first;
1181 }
1259 1182
1260 argv += optind; 1183 argv += optind;
1261 if (!argv[0]) 1184 if (!argv[0])
1262 *--argv = (char*)"."; 1185 *--argv = (char*)".";
1263 1186
1264 if (argv[1]) 1187 if (argv[1])
1265 G.all_fmt |= DISP_DIRNAME; /* 2 or more items? label directories */ 1188 G.show_dirname = 1; /* 2 or more items? label directories */
1266 1189
1267 /* stuff the command line file names into a dnode array */ 1190 /* stuff the command line file names into a dnode array */
1268 dn = NULL; 1191 dn = NULL;
@@ -1270,10 +1193,7 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
1270 do { 1193 do {
1271 cur = my_stat(*argv, *argv, 1194 cur = my_stat(*argv, *argv,
1272 /* follow links on command line unless -l, -s or -F: */ 1195 /* follow links on command line unless -l, -s or -F: */
1273 !((G.all_fmt & STYLE_MASK) == STYLE_LONG 1196 !(option_mask32 & (OPT_l|OPT_s|OPT_F))
1274 || (G.all_fmt & LIST_BLOCKS)
1275 || (option_mask32 & OPT_F)
1276 )
1277 /* ... or if -H: */ 1197 /* ... or if -H: */
1278 || (option_mask32 & OPT_H) 1198 || (option_mask32 & OPT_H)
1279 /* ... or if -L, but my_stat always follows links if -L */ 1199 /* ... or if -L, but my_stat always follows links if -L */
@@ -1302,7 +1222,7 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
1302 break; 1222 break;
1303 } 1223 }
1304 1224
1305 if (G.all_fmt & DISP_NOLIST) { 1225 if (option_mask32 & OPT_d) {
1306 sort_and_display_files(dnp, nfiles); 1226 sort_and_display_files(dnp, nfiles);
1307 } else { 1227 } else {
1308 dnd = splitdnarray(dnp, SPLIT_DIR); 1228 dnd = splitdnarray(dnp, SPLIT_DIR);
diff --git a/coreutils/md5_sha1_sum.c b/coreutils/md5_sha1_sum.c
index 783f44027..50111bd26 100644
--- a/coreutils/md5_sha1_sum.c
+++ b/coreutils/md5_sha1_sum.c
@@ -45,7 +45,6 @@
45//config: help 45//config: help
46//config: Enabling the -c options allows files to be checked 46//config: Enabling the -c options allows files to be checked
47//config: against pre-calculated hash values. 47//config: against pre-calculated hash values.
48//config:
49//config: -s and -w are useful options when verifying checksums. 48//config: -s and -w are useful options when verifying checksums.
50 49
51//applet:IF_MD5SUM(APPLET_NOEXEC(md5sum, md5_sha1_sum, BB_DIR_USR_BIN, BB_SUID_DROP, md5sum)) 50//applet:IF_MD5SUM(APPLET_NOEXEC(md5sum, md5_sha1_sum, BB_DIR_USR_BIN, BB_SUID_DROP, md5sum))
@@ -167,7 +166,7 @@ static uint8_t *hash_file(const char *filename, unsigned sha3_width)
167 } context; 166 } context;
168 uint8_t *hash_value; 167 uint8_t *hash_value;
169 void FAST_FUNC (*update)(void*, const void*, size_t); 168 void FAST_FUNC (*update)(void*, const void*, size_t);
170 void FAST_FUNC (*final)(void*, void*); 169 unsigned FAST_FUNC (*final)(void*, void*);
171 char hash_algo; 170 char hash_algo;
172 171
173 src_fd = open_or_warn_stdin(filename); 172 src_fd = open_or_warn_stdin(filename);
diff --git a/coreutils/mkdir.c b/coreutils/mkdir.c
index 3afe76c28..fcc34f1ad 100644
--- a/coreutils/mkdir.c
+++ b/coreutils/mkdir.c
@@ -23,8 +23,6 @@
23//config: bool "Enable long options" 23//config: bool "Enable long options"
24//config: default y 24//config: default y
25//config: depends on MKDIR && LONG_OPTS 25//config: depends on MKDIR && LONG_OPTS
26//config: help
27//config: Support long options for the mkdir applet.
28 26
29//applet:IF_MKDIR(APPLET_NOFORK(mkdir, mkdir, BB_DIR_BIN, BB_SUID_DROP, mkdir)) 27//applet:IF_MKDIR(APPLET_NOFORK(mkdir, mkdir, BB_DIR_BIN, BB_SUID_DROP, mkdir))
30 28
diff --git a/coreutils/mv.c b/coreutils/mv.c
index 1cc318fd1..df2ef0a52 100644
--- a/coreutils/mv.c
+++ b/coreutils/mv.c
@@ -21,8 +21,6 @@
21//config: bool "Enable long options" 21//config: bool "Enable long options"
22//config: default y 22//config: default y
23//config: depends on MV && LONG_OPTS 23//config: depends on MV && LONG_OPTS
24//config: help
25//config: Support long options for the mv applet.
26 24
27//applet:IF_MV(APPLET(mv, BB_DIR_BIN, BB_SUID_DROP)) 25//applet:IF_MV(APPLET(mv, BB_DIR_BIN, BB_SUID_DROP))
28 26
diff --git a/coreutils/printf.c b/coreutils/printf.c
index 6c8e115d8..bc22e0ee7 100644
--- a/coreutils/printf.c
+++ b/coreutils/printf.c
@@ -49,6 +49,9 @@
49 49
50//kbuild:lib-$(CONFIG_PRINTF) += printf.o 50//kbuild:lib-$(CONFIG_PRINTF) += printf.o
51 51
52//kbuild:lib-$(CONFIG_ASH_PRINTF) += printf.o
53//kbuild:lib-$(CONFIG_HUSH_PRINTF) += printf.o
54
52//usage:#define printf_trivial_usage 55//usage:#define printf_trivial_usage
53//usage: "FORMAT [ARG]..." 56//usage: "FORMAT [ARG]..."
54//usage:#define printf_full_usage "\n\n" 57//usage:#define printf_full_usage "\n\n"
@@ -417,7 +420,7 @@ int printf_main(int argc UNUSED_PARAM, char **argv)
417 if (argv[1] && argv[1][0] == '-' && argv[1][1] == '-' && !argv[1][2]) 420 if (argv[1] && argv[1][0] == '-' && argv[1][1] == '-' && !argv[1][2])
418 argv++; 421 argv++;
419 if (!argv[1]) { 422 if (!argv[1]) {
420 if (ENABLE_ASH_BUILTIN_PRINTF 423 if (ENABLE_ASH_PRINTF
421 && applet_name[0] != 'p' 424 && applet_name[0] != 'p'
422 ) { 425 ) {
423 bb_error_msg("usage: printf FORMAT [ARGUMENT...]"); 426 bb_error_msg("usage: printf FORMAT [ARGUMENT...]");
diff --git a/coreutils/split.c b/coreutils/split.c
index 50918a1ce..7af359d0e 100644
--- a/coreutils/split.c
+++ b/coreutils/split.c
@@ -9,7 +9,7 @@
9//config: bool "split" 9//config: bool "split"
10//config: default y 10//config: default y
11//config: help 11//config: help
12//config: split a file into pieces. 12//config: Split a file into pieces.
13//config: 13//config:
14//config:config FEATURE_SPLIT_FANCY 14//config:config FEATURE_SPLIT_FANCY
15//config: bool "Fancy extensions" 15//config: bool "Fancy extensions"
diff --git a/coreutils/tail.c b/coreutils/tail.c
index 99f58ddd8..e7a24a7a8 100644
--- a/coreutils/tail.c
+++ b/coreutils/tail.c
@@ -26,13 +26,12 @@
26//config: from files. 26//config: from files.
27//config: 27//config:
28//config:config FEATURE_FANCY_TAIL 28//config:config FEATURE_FANCY_TAIL
29//config: bool "Enable extra tail options (-q, -s, -v, and -F)" 29//config: bool "Enable -q, -s, -v, and -F options"
30//config: default y 30//config: default y
31//config: depends on TAIL 31//config: depends on TAIL
32//config: help 32//config: help
33//config: The options (-q, -s, -v and -F) are provided by GNU tail, but 33//config: These options are provided by GNU tail, but
34//config: are not specific in the SUSv3 standard. 34//config: are not specific in the SUSv3 standard:
35//config:
36//config: -q Never output headers giving file names 35//config: -q Never output headers giving file names
37//config: -s SEC Wait SEC seconds between reads with -f 36//config: -s SEC Wait SEC seconds between reads with -f
38//config: -v Always output headers giving file names 37//config: -v Always output headers giving file names
diff --git a/coreutils/test.c b/coreutils/test.c
index 67fdfde4f..c949a3cc9 100644
--- a/coreutils/test.c
+++ b/coreutils/test.c
@@ -42,21 +42,20 @@
42//config:config FEATURE_TEST_64 42//config:config FEATURE_TEST_64
43//config: bool "Extend test to 64 bit" 43//config: bool "Extend test to 64 bit"
44//config: default y 44//config: default y
45//config: depends on TEST || TEST1 || TEST2 || ASH_BUILTIN_TEST || HUSH 45//config: depends on TEST || TEST1 || TEST2 || ASH_TEST || HUSH_TEST
46//config: help 46//config: help
47//config: Enable 64-bit support in test. 47//config: Enable 64-bit support in test.
48 48
49//applet:IF_TEST(APPLET_NOFORK(test, test, BB_DIR_USR_BIN, BB_SUID_DROP, test)) 49//applet:IF_TEST(APPLET_NOFORK(test, test, BB_DIR_USR_BIN, BB_SUID_DROP, test))
50//applet:IF_TEST1(APPLET_NOFORK([, test, BB_DIR_USR_BIN, BB_SUID_DROP, test)) 50//applet:IF_TEST1(APPLET_NOFORK([, test, BB_DIR_USR_BIN, BB_SUID_DROP, test))
51//applet:IF_TEST2(APPLET_NOFORK([[, test, BB_DIR_USR_BIN, BB_SUID_DROP, test)) 51//applet:IF_TEST2(APPLET_NOFORK([[, test, BB_DIR_USR_BIN, BB_SUID_DROP, test))
52 52
53//kbuild:lib-$(CONFIG_TEST) += test.o test_ptr_hack.o 53//kbuild:lib-$(CONFIG_TEST) += test.o test_ptr_hack.o
54//kbuild:lib-$(CONFIG_TEST1) += test.o test_ptr_hack.o 54//kbuild:lib-$(CONFIG_TEST1) += test.o test_ptr_hack.o
55//kbuild:lib-$(CONFIG_TEST2) += test.o test_ptr_hack.o 55//kbuild:lib-$(CONFIG_TEST2) += test.o test_ptr_hack.o
56//kbuild:lib-$(CONFIG_ASH_BUILTIN_TEST) += test.o test_ptr_hack.o 56
57//kbuild:lib-$(CONFIG_HUSH) += test.o test_ptr_hack.o 57//kbuild:lib-$(CONFIG_ASH_TEST) += test.o test_ptr_hack.o
58//kbuild:lib-$(CONFIG_SH_IS_HUSH) += test.o test_ptr_hack.o 58//kbuild:lib-$(CONFIG_HUSH_TEST) += test.o test_ptr_hack.o
59//kbuild:lib-$(CONFIG_BASH_IS_HUSH) += test.o test_ptr_hack.o
60 59
61/* "test --help" is special-cased to ignore --help */ 60/* "test --help" is special-cased to ignore --help */
62//usage:#define test_trivial_usage NOUSAGE_STR 61//usage:#define test_trivial_usage NOUSAGE_STR
@@ -858,7 +857,7 @@ int test_main(int argc, char **argv)
858 const char *arg0; 857 const char *arg0;
859 858
860 arg0 = bb_basename(argv[0]); 859 arg0 = bb_basename(argv[0]);
861 if ((ENABLE_TEST1 || ENABLE_TEST2 || ENABLE_ASH_BUILTIN_TEST || ENABLE_HUSH) 860 if ((ENABLE_TEST1 || ENABLE_TEST2 || ENABLE_ASH_TEST || ENABLE_HUSH_TEST)
862 && (arg0[0] == '[') 861 && (arg0[0] == '[')
863 ) { 862 ) {
864 --argc; 863 --argc;
diff --git a/coreutils/wc.c b/coreutils/wc.c
index 73837141e..4c53049b0 100644
--- a/coreutils/wc.c
+++ b/coreutils/wc.c
@@ -40,11 +40,11 @@
40//config: in specified files. 40//config: in specified files.
41//config: 41//config:
42//config:config FEATURE_WC_LARGE 42//config:config FEATURE_WC_LARGE
43//config: bool "Support very large files in wc" 43//config: bool "Support very large counts"
44//config: default y 44//config: default y
45//config: depends on WC 45//config: depends on WC
46//config: help 46//config: help
47//config: Use "unsigned long long" in wc for counter variables. 47//config: Use "unsigned long long" for counter variables.
48 48
49//applet:IF_WC(APPLET(wc, BB_DIR_USR_BIN, BB_SUID_DROP)) 49//applet:IF_WC(APPLET(wc, BB_DIR_USR_BIN, BB_SUID_DROP))
50 50
diff --git a/coreutils/who.c b/coreutils/who.c
index ac19dc720..e6179bb00 100644
--- a/coreutils/who.c
+++ b/coreutils/who.c
@@ -30,6 +30,7 @@
30//config: help 30//config: help
31//config: Print users currently logged on. 31//config: Print users currently logged on.
32 32
33// APPLET_ODDNAME:name main location suid_type help
33//applet:IF_USERS(APPLET_ODDNAME(users, who, BB_DIR_USR_BIN, BB_SUID_DROP, users)) 34//applet:IF_USERS(APPLET_ODDNAME(users, who, BB_DIR_USR_BIN, BB_SUID_DROP, users))
34//applet:IF_WHO(APPLET(who, BB_DIR_USR_BIN, BB_SUID_DROP)) 35//applet:IF_WHO(APPLET(who, BB_DIR_USR_BIN, BB_SUID_DROP))
35 36