aboutsummaryrefslogtreecommitdiff
path: root/coreutils/ls.c
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2010-12-19 21:54:39 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2010-12-19 21:54:39 +0100
commit982aa263a0cef10ee4f4c06084a87af736c449ac (patch)
treefd75841a9ce0efe915f59eb495c5f4b48e779216 /coreutils/ls.c
parent86ffe5c15a14dc7f8483faf42ef907c5f861137d (diff)
downloadbusybox-w32-982aa263a0cef10ee4f4c06084a87af736c449ac.tar.gz
busybox-w32-982aa263a0cef10ee4f4c06084a87af736c449ac.tar.bz2
busybox-w32-982aa263a0cef10ee4f4c06084a87af736c449ac.zip
ls: add support for -H
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'coreutils/ls.c')
-rw-r--r--coreutils/ls.c159
1 files changed, 86 insertions, 73 deletions
diff --git a/coreutils/ls.c b/coreutils/ls.c
index eadd6cee7..d27c36ddc 100644
--- a/coreutils/ls.c
+++ b/coreutils/ls.c
@@ -32,7 +32,7 @@
32 32
33//usage:#define ls_trivial_usage 33//usage:#define ls_trivial_usage
34//usage: "[-1AaCxd" 34//usage: "[-1AaCxd"
35//usage: IF_FEATURE_LS_FOLLOWLINKS("L") 35//usage: IF_FEATURE_LS_FOLLOWLINKS("LH")
36//usage: IF_FEATURE_LS_RECURSIVE("R") 36//usage: IF_FEATURE_LS_RECURSIVE("R")
37//usage: IF_FEATURE_LS_FILETYPES("Fp") "lins" 37//usage: IF_FEATURE_LS_FILETYPES("Fp") "lins"
38//usage: IF_FEATURE_LS_TIMESTAMPS("e") 38//usage: IF_FEATURE_LS_TIMESTAMPS("e")
@@ -51,7 +51,8 @@
51//usage: "\n -x List by lines" 51//usage: "\n -x List by lines"
52//usage: "\n -d List directory entries instead of contents" 52//usage: "\n -d List directory entries instead of contents"
53//usage: IF_FEATURE_LS_FOLLOWLINKS( 53//usage: IF_FEATURE_LS_FOLLOWLINKS(
54//usage: "\n -L List entries pointed to by symlinks" 54//usage: "\n -L Follow symlinks"
55//usage: "\n -H Follow symlinks on command line only"
55//usage: ) 56//usage: )
56//usage: IF_FEATURE_LS_RECURSIVE( 57//usage: IF_FEATURE_LS_RECURSIVE(
57//usage: "\n -R Recurse" 58//usage: "\n -R Recurse"
@@ -118,11 +119,11 @@
118enum { 119enum {
119TERMINAL_WIDTH = 80, /* use 79 if terminal has linefold bug */ 120TERMINAL_WIDTH = 80, /* use 79 if terminal has linefold bug */
120 121
121/* what is the overall style of the listing */ 122SPLIT_DIR = 1,
122STYLE_COLUMNAR = 1 << 21, /* many records per line */ 123SPLIT_FILE = 0,
123STYLE_LONG = 2 << 21, /* one record per line, extended info */ 124SPLIT_SUBDIR = 2,
124STYLE_SINGLE = 3 << 21, /* one record per line */ 125
125STYLE_MASK = STYLE_SINGLE, 126/* Bits in all_fmt: */
126 127
127/* 51306 lrwxrwxrwx 1 root root 2 May 11 01:43 /bin/view -> vi* */ 128/* 51306 lrwxrwxrwx 1 root root 2 May 11 01:43 /bin/view -> vi* */
128/* what file information will be listed */ 129/* what file information will be listed */
@@ -152,44 +153,41 @@ DISP_RECURSIVE = 1 << 19, /* show directory and everything below it */
152DISP_ROWS = 1 << 20, /* print across rows */ 153DISP_ROWS = 1 << 20, /* print across rows */
153DISP_MASK = ((DISP_ROWS << 1) - 1) & ~(DISP_DIRNAME - 1), 154DISP_MASK = ((DISP_ROWS << 1) - 1) & ~(DISP_DIRNAME - 1),
154 155
155/* how will the files be sorted (CONFIG_FEATURE_LS_SORTFILES) */ 156/* what is the overall style of the listing */
156SORT_FORWARD = 0, /* sort in reverse order */ 157STYLE_COLUMNAR = 1 << 21, /* many records per line */
157SORT_REVERSE = 1 << 27, /* sort in reverse order */ 158STYLE_LONG = 2 << 21, /* one record per line, extended info */
158 159STYLE_SINGLE = 3 << 21, /* one record per line */
159SORT_NAME = 0, /* sort by file name */ 160STYLE_MASK = STYLE_SINGLE,
160SORT_SIZE = 1 << 28, /* sort by file size */
161SORT_ATIME = 2 << 28, /* sort by last access time */
162SORT_CTIME = 3 << 28, /* sort by last change time */
163SORT_MTIME = 4 << 28, /* sort by last modification time */
164SORT_VERSION = 5 << 28, /* sort by version */
165SORT_EXT = 6 << 28, /* sort by file name extension */
166SORT_DIR = 7 << 28, /* sort by file or directory */
167SORT_MASK = (7 << 28) * ENABLE_FEATURE_LS_SORTFILES,
168 161
169/* which of the three times will be used */ 162/* which of the three times will be used */
170TIME_CHANGE = (1 << 23) * ENABLE_FEATURE_LS_TIMESTAMPS, 163TIME_CHANGE = (1 << 23) * ENABLE_FEATURE_LS_TIMESTAMPS,
171TIME_ACCESS = (1 << 24) * ENABLE_FEATURE_LS_TIMESTAMPS, 164TIME_ACCESS = (1 << 24) * ENABLE_FEATURE_LS_TIMESTAMPS,
172TIME_MASK = (3 << 23) * ENABLE_FEATURE_LS_TIMESTAMPS, 165TIME_MASK = (3 << 23) * ENABLE_FEATURE_LS_TIMESTAMPS,
173 166
174FOLLOW_LINKS = (1 << 25) * ENABLE_FEATURE_LS_FOLLOWLINKS, 167/* how will the files be sorted (CONFIG_FEATURE_LS_SORTFILES) */
168SORT_REVERSE = 1 << 25,
175 169
176LS_DISP_HR = (1 << 26) * ENABLE_FEATURE_HUMAN_READABLE, 170SORT_NAME = 0, /* sort by file name */
171SORT_SIZE = 1 << 26, /* sort by file size */
172SORT_ATIME = 2 << 26, /* sort by last access time */
173SORT_CTIME = 3 << 26, /* sort by last change time */
174SORT_MTIME = 4 << 26, /* sort by last modification time */
175SORT_VERSION = 5 << 26, /* sort by version */
176SORT_EXT = 6 << 26, /* sort by file name extension */
177SORT_DIR = 7 << 26, /* sort by file or directory */
178SORT_MASK = (7 << 26) * ENABLE_FEATURE_LS_SORTFILES,
177 179
178LIST_SHORT = LIST_FILENAME, 180LIST_SHORT = LIST_FILENAME,
179LIST_LONG = LIST_MODEBITS | LIST_NLINKS | LIST_ID_NAME | LIST_SIZE | \ 181LIST_LONG = LIST_MODEBITS | LIST_NLINKS | LIST_ID_NAME | LIST_SIZE | \
180 LIST_DATE_TIME | LIST_FILENAME | LIST_SYMLINK, 182 LIST_DATE_TIME | LIST_FILENAME | LIST_SYMLINK,
181
182SPLIT_DIR = 1,
183SPLIT_FILE = 0,
184SPLIT_SUBDIR = 2,
185}; 183};
186 184
187/* -Cadil1 Std options, busybox always supports */ 185/* -Cadil1 Std options, busybox always supports */
188/* -gnsxA Std options, busybox always supports */ 186/* -gnsxA Std options, busybox always supports */
189/* -Q GNU option? busybox always supports */ 187/* -Q GNU option, busybox always supports */
190/* -k SELinux option, busybox always supports (ignores if !SELinux) */ 188/* -k SELinux option, busybox always supports (ignores if !SELinux) */
191/* Std has -k which means "show sizes in kbytes" */ 189/* Std has -k which means "show sizes in kbytes" */
192/* -FLRctur Std options, busybox optionally supports */ 190/* -FLHRctur Std options, busybox optionally supports */
193/* -p Std option, busybox optionally supports */ 191/* -p Std option, busybox optionally supports */
194/* Not fully compatible - we show not only '/' but other chars too */ 192/* Not fully compatible - we show not only '/' but other chars too */
195/* -SXvhTw GNU options, busybox optionally supports */ 193/* -SXvhTw GNU options, busybox optionally supports */
@@ -199,15 +197,15 @@ SPLIT_SUBDIR = 2,
199/* Std opts we do not support: */ 197/* Std opts we do not support: */
200/* -H Follow the links on command line only */ 198/* -H Follow the links on command line only */
201static const char ls_options[] ALIGN1 = 199static const char ls_options[] ALIGN1 =
202 "Cadil1gnsxQAk" /* 13 opts, total 13 */ 200 "Cadil1gnsxQAk" /* 13 opts, total 13 */
203 IF_FEATURE_LS_TIMESTAMPS("cetu") /* 4, 17 */ 201 IF_FEATURE_LS_TIMESTAMPS("cetu") /* 4, 17 */
204 IF_FEATURE_LS_SORTFILES("SXrv") /* 4, 21 */ 202 IF_FEATURE_LS_SORTFILES("SXrv") /* 4, 21 */
205 IF_FEATURE_LS_FILETYPES("Fp") /* 2, 23 */ 203 IF_FEATURE_LS_FILETYPES("Fp") /* 2, 23 */
206 IF_FEATURE_LS_FOLLOWLINKS("L") /* 1, 24 */ 204 IF_FEATURE_LS_RECURSIVE("R") /* 1, 24 */
207 IF_FEATURE_LS_RECURSIVE("R") /* 1, 25 */ 205 IF_SELINUX("KZ") /* 2, 26 */
208 IF_FEATURE_HUMAN_READABLE("h") /* 1, 26 */ 206 IF_FEATURE_LS_FOLLOWLINKS("LH") /* 2, 28 */
209 IF_SELINUX("KZ") /* 2, 28 */ 207 IF_FEATURE_HUMAN_READABLE("h") /* 1, 29 */
210 IF_FEATURE_AUTOWIDTH("T:w:") /* 2, 30 */ 208 IF_FEATURE_AUTOWIDTH("T:w:") /* 2, 31 */
211 ; 209 ;
212enum { 210enum {
213 //OPT_C = (1 << 0), 211 //OPT_C = (1 << 0),
@@ -223,27 +221,55 @@ enum {
223 OPT_Q = (1 << 10), 221 OPT_Q = (1 << 10),
224 //OPT_A = (1 << 11), 222 //OPT_A = (1 << 11),
225 //OPT_k = (1 << 12), 223 //OPT_k = (1 << 12),
226 OPTBIT_F = 13 224
227 + 4 * ENABLE_FEATURE_LS_TIMESTAMPS 225 OPTBIT_c = 13,
228 + 4 * ENABLE_FEATURE_LS_SORTFILES, 226 OPTBIT_e,
229 OPTBIT_color = OPTBIT_F 227 OPTBIT_t,
230 + 2 * ENABLE_FEATURE_LS_FILETYPES 228 OPTBIT_u,
231 + 1 * ENABLE_FEATURE_LS_FOLLOWLINKS 229 OPTBIT_S = OPTBIT_c + 4 * ENABLE_FEATURE_LS_TIMESTAMPS,
232 + 1 * ENABLE_FEATURE_LS_RECURSIVE 230 OPTBIT_X, /* 18 */
233 + 1 * ENABLE_FEATURE_HUMAN_READABLE 231 OPTBIT_r,
234 + 2 * ENABLE_SELINUX 232 OPTBIT_v,
235 + 2 * ENABLE_FEATURE_AUTOWIDTH, 233 OPTBIT_F = OPTBIT_S + 4 * ENABLE_FEATURE_LS_SORTFILES,
236 OPT_F = (1 << OPTBIT_F) * ENABLE_FEATURE_LS_FILETYPES, 234 OPTBIT_p, /* 22 */
237 OPT_color = (1 << OPTBIT_color), 235 OPTBIT_R = OPTBIT_F + 2 * ENABLE_FEATURE_LS_FILETYPES,
236 OPTBIT_K = OPTBIT_R + 1 * ENABLE_FEATURE_LS_RECURSIVE,
237 OPTBIT_Z, /* 25 */
238 OPTBIT_L = OPTBIT_K + 2 * ENABLE_SELINUX,
239 OPTBIT_H, /* 27 */
240 OPTBIT_h = OPTBIT_L + 1 * ENABLE_FEATURE_LS_FOLLOWLINKS,
241 OPTBIT_T = OPTBIT_h + 2 * ENABLE_FEATURE_HUMAN_READABLE,
242 OPTBIT_w, /* 30 */
243 OPTBIT_color = OPTBIT_T + 2 * ENABLE_FEATURE_AUTOWIDTH,
244
245 OPT_c = (1 << OPTBIT_c) * ENABLE_FEATURE_LS_TIMESTAMPS,
246 OPT_e = (1 << OPTBIT_e) * ENABLE_FEATURE_LS_TIMESTAMPS,
247 OPT_t = (1 << OPTBIT_t) * ENABLE_FEATURE_LS_TIMESTAMPS,
248 OPT_u = (1 << OPTBIT_u) * ENABLE_FEATURE_LS_TIMESTAMPS,
249 OPT_S = (1 << OPTBIT_S) * ENABLE_FEATURE_LS_SORTFILES,
250 OPT_X = (1 << OPTBIT_X) * ENABLE_FEATURE_LS_SORTFILES,
251 OPT_r = (1 << OPTBIT_r) * ENABLE_FEATURE_LS_SORTFILES,
252 OPT_v = (1 << OPTBIT_v) * ENABLE_FEATURE_LS_SORTFILES,
253 OPT_F = (1 << OPTBIT_F) * ENABLE_FEATURE_LS_FILETYPES,
254 OPT_p = (1 << OPTBIT_p) * ENABLE_FEATURE_LS_FILETYPES,
255 OPT_R = (1 << OPTBIT_R) * ENABLE_FEATURE_LS_RECURSIVE,
256 OPT_K = (1 << OPTBIT_K) * ENABLE_SELINUX,
257 OPT_Z = (1 << OPTBIT_Z) * ENABLE_SELINUX,
258 OPT_L = (1 << OPTBIT_L) * ENABLE_FEATURE_LS_FOLLOWLINKS,
259 OPT_H = (1 << OPTBIT_H) * ENABLE_FEATURE_LS_FOLLOWLINKS,
260 OPT_h = (1 << OPTBIT_h) * ENABLE_FEATURE_HUMAN_READABLE,
261 OPT_T = (1 << OPTBIT_T) * ENABLE_FEATURE_AUTOWIDTH,
262 OPT_w = (1 << OPTBIT_w) * ENABLE_FEATURE_AUTOWIDTH,
263 OPT_color = (1 << OPTBIT_color) * ENABLE_FEATURE_LS_COLOR,
238}; 264};
239 265
240/* TODO: simple toggles may be stored as OPT_xxx bits instead */ 266/* TODO: simple toggles may be stored as OPT_xxx bits instead */
241static const unsigned opt_flags[] = { 267static const uint32_t opt_flags[] = {
242 LIST_SHORT | STYLE_COLUMNAR, /* C */ 268 LIST_SHORT | STYLE_COLUMNAR, /* C */
243 DISP_HIDDEN | DISP_DOT, /* a */ 269 DISP_HIDDEN | DISP_DOT, /* a */
244 DISP_NOLIST, /* d */ 270 DISP_NOLIST, /* d */
245 LIST_INO, /* i */ 271 LIST_INO, /* i */
246 LIST_LONG | STYLE_LONG, /* l - remember LS_DISP_HR in mask! */ 272 LIST_LONG | STYLE_LONG, /* l */
247 LIST_SHORT | STYLE_SINGLE, /* 1 */ 273 LIST_SHORT | STYLE_SINGLE, /* 1 */
248 0, /* g (don't show owner) - handled via OPT_g */ 274 0, /* g (don't show owner) - handled via OPT_g */
249 LIST_ID_NUMERIC, /* n */ 275 LIST_ID_NUMERIC, /* n */
@@ -268,23 +294,15 @@ static const unsigned opt_flags[] = {
268 LIST_FILETYPE | LIST_EXEC, /* F */ 294 LIST_FILETYPE | LIST_EXEC, /* F */
269 LIST_FILETYPE, /* p */ 295 LIST_FILETYPE, /* p */
270#endif 296#endif
271#if ENABLE_FEATURE_LS_FOLLOWLINKS
272 FOLLOW_LINKS, /* L */
273#endif
274#if ENABLE_FEATURE_LS_RECURSIVE 297#if ENABLE_FEATURE_LS_RECURSIVE
275 DISP_RECURSIVE, /* R */ 298 DISP_RECURSIVE, /* R */
276#endif 299#endif
277#if ENABLE_FEATURE_HUMAN_READABLE
278 LS_DISP_HR, /* h */
279#endif
280#if ENABLE_SELINUX 300#if ENABLE_SELINUX
281 LIST_MODEBITS|LIST_NLINKS|LIST_CONTEXT|LIST_SIZE|LIST_DATE_TIME, /* K */ 301 LIST_MODEBITS|LIST_NLINKS|LIST_CONTEXT|LIST_SIZE|LIST_DATE_TIME, /* K */
282 LIST_MODEBITS|LIST_ID_NAME|LIST_CONTEXT, /* Z */ 302 LIST_MODEBITS|LIST_ID_NAME|LIST_CONTEXT, /* Z */
283#endif 303#endif
284 (1U<<31) 304 (1U << 31)
285 /* options after Z are not processed through opt_flags: 305 /* options after Z are not processed through opt_flags */
286 * T, w - ignored
287 */
288}; 306};
289 307
290 308
@@ -344,7 +362,7 @@ static struct dnode *my_stat(const char *fullname, const char *name, int force_f
344 struct dnode *cur; 362 struct dnode *cur;
345 IF_SELINUX(security_context_t sid = NULL;) 363 IF_SELINUX(security_context_t sid = NULL;)
346 364
347 if ((all_fmt & FOLLOW_LINKS) || force_follow) { 365 if ((option_mask32 & OPT_L) || force_follow) {
348#if ENABLE_SELINUX 366#if ENABLE_SELINUX
349 if (is_selinux_enabled()) { 367 if (is_selinux_enabled()) {
350 getfilecon(fullname, &sid); 368 getfilecon(fullname, &sid);
@@ -699,7 +717,7 @@ static NOINLINE unsigned list_single(const struct dnode *dn)
699 (int) major(dn->dstat.st_rdev), 717 (int) major(dn->dstat.st_rdev),
700 (int) minor(dn->dstat.st_rdev)); 718 (int) minor(dn->dstat.st_rdev));
701 } else { 719 } else {
702 if (all_fmt & LS_DISP_HR) { 720 if (option_mask32 & OPT_h) {
703 column += printf("%"HUMAN_READABLE_MAX_WIDTH_STR"s ", 721 column += printf("%"HUMAN_READABLE_MAX_WIDTH_STR"s ",
704 /* print st_size, show one fractional, use suffixes */ 722 /* print st_size, show one fractional, use suffixes */
705 make_human_readable_str(dn->dstat.st_size, 1, 0) 723 make_human_readable_str(dn->dstat.st_size, 1, 0)
@@ -887,12 +905,6 @@ static void showdirs(struct dnode **dn, int first)
887 struct dnode **subdnp; 905 struct dnode **subdnp;
888 struct dnode **dnd; 906 struct dnode **dnd;
889 907
890 /* Never happens:
891 if (dn == NULL || ndirs < 1) {
892 return;
893 }
894 */
895
896 for (; *dn; dn++) { 908 for (; *dn; dn++) {
897 if (all_fmt & (DISP_DIRNAME | DISP_RECURSIVE)) { 909 if (all_fmt & (DISP_DIRNAME | DISP_RECURSIVE)) {
898 if (!first) 910 if (!first)
@@ -1031,8 +1043,7 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
1031 1043
1032 init_unicode(); 1044 init_unicode();
1033 1045
1034 all_fmt = LIST_SHORT | 1046 all_fmt = LIST_SHORT | (ENABLE_FEATURE_LS_SORTFILES * SORT_NAME);
1035 (ENABLE_FEATURE_LS_SORTFILES * (SORT_NAME | SORT_FORWARD));
1036 1047
1037#if ENABLE_FEATURE_AUTOWIDTH 1048#if ENABLE_FEATURE_AUTOWIDTH
1038 /* obtain the terminal width */ 1049 /* obtain the terminal width */
@@ -1050,8 +1061,8 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
1050 * in some pairs of opts, only last one takes effect: 1061 * in some pairs of opts, only last one takes effect:
1051 */ 1062 */
1052 IF_FEATURE_LS_TIMESTAMPS(IF_FEATURE_LS_SORTFILES(":t-S:S-t")) /* time/size */ 1063 IF_FEATURE_LS_TIMESTAMPS(IF_FEATURE_LS_SORTFILES(":t-S:S-t")) /* time/size */
1053 // ":H-L:L-H:" - we don't have -H 1064 // ":m-l:l-m" - we don't have -m
1054 // ":m-l:l-m:" - we don't have -m 1065 IF_FEATURE_LS_FOLLOWLINKS(":H-L:L-H")
1055 ":C-xl:x-Cl:l-xC" /* bycols/bylines/long */ 1066 ":C-xl:x-Cl:l-xC" /* bycols/bylines/long */
1056 ":C-1:1-C" /* bycols/oneline */ 1067 ":C-1:1-C" /* bycols/oneline */
1057 ":x-1:1-x" /* bylines/oneline (not in SuS, but in GNU coreutils 8.4) */ 1068 ":x-1:1-x" /* bylines/oneline (not in SuS, but in GNU coreutils 8.4) */
@@ -1062,9 +1073,9 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
1062 IF_FEATURE_AUTOWIDTH(, NULL, &terminal_width) 1073 IF_FEATURE_AUTOWIDTH(, NULL, &terminal_width)
1063 IF_FEATURE_LS_COLOR(, &color_opt) 1074 IF_FEATURE_LS_COLOR(, &color_opt)
1064 ); 1075 );
1065 for (i = 0; opt_flags[i] != (1U<<31); i++) { 1076 for (i = 0; opt_flags[i] != (1U << 31); i++) {
1066 if (opt & (1 << i)) { 1077 if (opt & (1 << i)) {
1067 unsigned flags = opt_flags[i]; 1078 uint32_t flags = opt_flags[i];
1068 1079
1069 if (flags & STYLE_MASK) 1080 if (flags & STYLE_MASK)
1070 all_fmt &= ~STYLE_MASK; 1081 all_fmt &= ~STYLE_MASK;
@@ -1134,9 +1145,11 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
1134 dn = NULL; 1145 dn = NULL;
1135 nfiles = 0; 1146 nfiles = 0;
1136 do { 1147 do {
1137 /* NB: follow links on command line unless -l, -s or -F */
1138 cur = my_stat(*argv, *argv, 1148 cur = my_stat(*argv, *argv,
1149 /* follow links on command line unless -l, -s or -F: */
1139 !((all_fmt & (STYLE_LONG|LIST_BLOCKS)) || (option_mask32 & OPT_F)) 1150 !((all_fmt & (STYLE_LONG|LIST_BLOCKS)) || (option_mask32 & OPT_F))
1151 /* ... or if -H: */
1152 || (option_mask32 & OPT_H)
1140 ); 1153 );
1141 argv++; 1154 argv++;
1142 if (!cur) 1155 if (!cur)