aboutsummaryrefslogtreecommitdiff
path: root/coreutils/ls.c
diff options
context:
space:
mode:
Diffstat (limited to 'coreutils/ls.c')
-rw-r--r--coreutils/ls.c73
1 files changed, 38 insertions, 35 deletions
diff --git a/coreutils/ls.c b/coreutils/ls.c
index 1afe28c8d..4a41db76a 100644
--- a/coreutils/ls.c
+++ b/coreutils/ls.c
@@ -1,6 +1,5 @@
1/* vi: set sw=4 ts=4: */ 1/* vi: set sw=4 ts=4: */
2/* 2/*
3 * tiny-ls.c version 0.1.0: A minimalist 'ls'
4 * Copyright (C) 1996 Brian Candler <B.Candler@pobox.com> 3 * Copyright (C) 1996 Brian Candler <B.Candler@pobox.com>
5 * 4 *
6 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 5 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
@@ -159,7 +158,7 @@ STYLE_MASK = STYLE_SINGLE,
159 158
160/* which of the three times will be used */ 159/* which of the three times will be used */
161TIME_CHANGE = (1 << 21) * ENABLE_FEATURE_LS_TIMESTAMPS, 160TIME_CHANGE = (1 << 21) * ENABLE_FEATURE_LS_TIMESTAMPS,
162TIME_ACCESS = (1 << 22) * ENABLE_FEATURE_LS_TIMESTAMPS, 161TIME_ACCESS = (2 << 21) * ENABLE_FEATURE_LS_TIMESTAMPS,
163TIME_MASK = (3 << 21) * ENABLE_FEATURE_LS_TIMESTAMPS, 162TIME_MASK = (3 << 21) * ENABLE_FEATURE_LS_TIMESTAMPS,
164 163
165/* how will the files be sorted (CONFIG_FEATURE_LS_SORTFILES) */ 164/* how will the files be sorted (CONFIG_FEATURE_LS_SORTFILES) */
@@ -189,10 +188,11 @@ LIST_LONG = LIST_MODEBITS | LIST_NLINKS | LIST_ID_NAME | LIST_SIZE | \
189/* Not fully compatible - we show not only '/' but other chars too */ 188/* Not fully compatible - we show not only '/' but other chars too */
190/* -SXvhTw GNU options, busybox optionally supports */ 189/* -SXvhTw GNU options, busybox optionally supports */
191/* -T TABWIDTH is ignored (we don't use tabs on output) */ 190/* -T TABWIDTH is ignored (we don't use tabs on output) */
192/* -K SELinux mandated options, busybox optionally supports */ 191/* -KZ SELinux mandated options, busybox optionally supports */
192/* (coreutils 8.4 has no -K, remove it?) */
193/* -e I think we made this one up (looks similar to GNU --full-time) */ 193/* -e I think we made this one up (looks similar to GNU --full-time) */
194/* Std opts we do not support: */ 194/* We already used up all 32 bits, if we need to add more, candidates for removal: */
195/* -H Follow the links on command line only */ 195/* -K, -T, -e (add --full-time instead) */
196static const char ls_options[] ALIGN1 = 196static const char ls_options[] ALIGN1 =
197 "Cadil1gnsxQAk" /* 13 opts, total 13 */ 197 "Cadil1gnsxQAk" /* 13 opts, total 13 */
198 IF_FEATURE_LS_TIMESTAMPS("cetu") /* 4, 17 */ 198 IF_FEATURE_LS_TIMESTAMPS("cetu") /* 4, 17 */
@@ -203,7 +203,7 @@ static const char ls_options[] ALIGN1 =
203 IF_FEATURE_LS_FOLLOWLINKS("LH") /* 2, 28 */ 203 IF_FEATURE_LS_FOLLOWLINKS("LH") /* 2, 28 */
204 IF_FEATURE_HUMAN_READABLE("h") /* 1, 29 */ 204 IF_FEATURE_HUMAN_READABLE("h") /* 1, 29 */
205 IF_FEATURE_AUTOWIDTH("T:w:") /* 2, 31 */ 205 IF_FEATURE_AUTOWIDTH("T:w:") /* 2, 31 */
206 ; 206 /* with --color, we use all 32 bits */;
207enum { 207enum {
208 //OPT_C = (1 << 0), 208 //OPT_C = (1 << 0),
209 //OPT_a = (1 << 1), 209 //OPT_a = (1 << 1),
@@ -234,8 +234,8 @@ enum {
234 OPTBIT_Z, /* 25 */ 234 OPTBIT_Z, /* 25 */
235 OPTBIT_L = OPTBIT_K + 2 * ENABLE_SELINUX, 235 OPTBIT_L = OPTBIT_K + 2 * ENABLE_SELINUX,
236 OPTBIT_H, /* 27 */ 236 OPTBIT_H, /* 27 */
237 OPTBIT_h = OPTBIT_L + 1 * ENABLE_FEATURE_LS_FOLLOWLINKS, 237 OPTBIT_h = OPTBIT_L + 2 * ENABLE_FEATURE_LS_FOLLOWLINKS,
238 OPTBIT_T = OPTBIT_h + 2 * ENABLE_FEATURE_HUMAN_READABLE, 238 OPTBIT_T = OPTBIT_h + 1 * ENABLE_FEATURE_HUMAN_READABLE,
239 OPTBIT_w, /* 30 */ 239 OPTBIT_w, /* 30 */
240 OPTBIT_color = OPTBIT_T + 2 * ENABLE_FEATURE_AUTOWIDTH, 240 OPTBIT_color = OPTBIT_T + 2 * ENABLE_FEATURE_AUTOWIDTH,
241 241
@@ -268,13 +268,13 @@ static const uint32_t opt_flags[] = {
268 LIST_INO, /* i */ 268 LIST_INO, /* i */
269 LIST_LONG | STYLE_LONG, /* l */ 269 LIST_LONG | STYLE_LONG, /* l */
270 STYLE_SINGLE, /* 1 */ 270 STYLE_SINGLE, /* 1 */
271 0, /* g (don't show owner) - handled via OPT_g */ 271 LIST_LONG | STYLE_LONG, /* g (don't show owner) - handled via OPT_g. assumes l */
272 LIST_ID_NUMERIC, /* n */ 272 LIST_ID_NUMERIC | LIST_LONG | STYLE_LONG, /* n (assumes l) */
273 LIST_BLOCKS, /* s */ 273 LIST_BLOCKS, /* s */
274 DISP_ROWS | STYLE_COLUMNAR, /* x */ 274 DISP_ROWS | STYLE_COLUMNAR, /* x */
275 0, /* Q (quote filename) - handled via OPT_Q */ 275 0, /* Q (quote filename) - handled via OPT_Q */
276 DISP_HIDDEN, /* A */ 276 DISP_HIDDEN, /* A */
277 ENABLE_SELINUX * LIST_CONTEXT, /* k (ignored if !SELINUX) */ 277 ENABLE_SELINUX * (LIST_CONTEXT|STYLE_SINGLE), /* k (ignored if !SELINUX) */
278#if ENABLE_FEATURE_LS_TIMESTAMPS 278#if ENABLE_FEATURE_LS_TIMESTAMPS
279 TIME_CHANGE | (ENABLE_FEATURE_LS_SORTFILES * SORT_CTIME), /* c */ 279 TIME_CHANGE | (ENABLE_FEATURE_LS_SORTFILES * SORT_CTIME), /* c */
280 LIST_FULLTIME, /* e */ 280 LIST_FULLTIME, /* e */
@@ -295,8 +295,8 @@ static const uint32_t opt_flags[] = {
295 DISP_RECURSIVE, /* R */ 295 DISP_RECURSIVE, /* R */
296#endif 296#endif
297#if ENABLE_SELINUX 297#if ENABLE_SELINUX
298 LIST_MODEBITS|LIST_NLINKS|LIST_CONTEXT|LIST_SIZE|LIST_DATE_TIME, /* K */ 298 LIST_MODEBITS|LIST_NLINKS|LIST_CONTEXT|LIST_SIZE|LIST_DATE_TIME|STYLE_SINGLE, /* K */
299 LIST_MODEBITS|LIST_ID_NAME|LIST_CONTEXT, /* Z */ 299 LIST_MODEBITS|LIST_ID_NAME|LIST_CONTEXT|STYLE_SINGLE, /* Z */
300#endif 300#endif
301 (1U << 31) 301 (1U << 31)
302 /* options after Z are not processed through opt_flags */ 302 /* options after Z are not processed through opt_flags */
@@ -682,19 +682,28 @@ static NOINLINE unsigned list_single(const struct dnode *dn)
682 682
683 if (all_fmt & LIST_INO) 683 if (all_fmt & LIST_INO)
684 column += printf("%7llu ", (long long) dn->dstat.st_ino); 684 column += printf("%7llu ", (long long) dn->dstat.st_ino);
685//TODO: -h should affect -s too:
685 if (all_fmt & LIST_BLOCKS) 686 if (all_fmt & LIST_BLOCKS)
686#if ENABLE_PLATFORM_MINGW32 687#if ENABLE_PLATFORM_MINGW32
687 /* MinGW does not have st_blocks */ 688 /* MinGW does not have st_blocks */
688 column += printf("%4"OFF_FMT"u ", (off_t)0); 689 column += printf("%6"OFF_FMT"u ", (off_t)0);
689#else 690#else
690 column += printf("%4"OFF_FMT"u ", (off_t) (dn->dstat.st_blocks >> 1)); 691 column += printf("%6"OFF_FMT"u ", (off_t) (dn->dstat.st_blocks >> 1));
691#endif 692#endif
692 if (all_fmt & LIST_MODEBITS) 693 if (all_fmt & LIST_MODEBITS)
693 column += printf("%-10s ", (char *) bb_mode_string(dn->dstat.st_mode)); 694 column += printf("%-10s ", (char *) bb_mode_string(dn->dstat.st_mode));
694 if (all_fmt & LIST_NLINKS) 695 if (all_fmt & LIST_NLINKS)
695 column += printf("%4lu ", (long) dn->dstat.st_nlink); 696 column += printf("%4lu ", (long) dn->dstat.st_nlink);
697 if (all_fmt & LIST_ID_NUMERIC) {
698 if (option_mask32 & OPT_g)
699 column += printf("%-8u ", (int) dn->dstat.st_gid);
700 else
701 column += printf("%-8u %-8u ",
702 (int) dn->dstat.st_uid,
703 (int) dn->dstat.st_gid);
704 }
696#if ENABLE_FEATURE_LS_USERNAME 705#if ENABLE_FEATURE_LS_USERNAME
697 if (all_fmt & LIST_ID_NAME) { 706 else if (all_fmt & LIST_ID_NAME) {
698 if (option_mask32 & OPT_g) { 707 if (option_mask32 & OPT_g) {
699 column += printf("%-8.8s ", 708 column += printf("%-8.8s ",
700 get_cached_groupname(dn->dstat.st_gid)); 709 get_cached_groupname(dn->dstat.st_gid));
@@ -705,14 +714,6 @@ static NOINLINE unsigned list_single(const struct dnode *dn)
705 } 714 }
706 } 715 }
707#endif 716#endif
708 if (all_fmt & LIST_ID_NUMERIC) {
709 if (option_mask32 & OPT_g)
710 column += printf("%-8u ", (int) dn->dstat.st_gid);
711 else
712 column += printf("%-8u %-8u ",
713 (int) dn->dstat.st_uid,
714 (int) dn->dstat.st_gid);
715 }
716 if (all_fmt & LIST_SIZE) { 717 if (all_fmt & LIST_SIZE) {
717 if (S_ISBLK(dn->dstat.st_mode) || S_ISCHR(dn->dstat.st_mode)) { 718 if (S_ISBLK(dn->dstat.st_mode) || S_ISCHR(dn->dstat.st_mode)) {
718 column += printf("%4u, %3u ", 719 column += printf("%4u, %3u ",
@@ -739,9 +740,12 @@ static NOINLINE unsigned list_single(const struct dnode *dn)
739 ttime = dn->dstat.st_ctime; 740 ttime = dn->dstat.st_ctime;
740 filetime = ctime(&ttime); 741 filetime = ctime(&ttime);
741 /* filetime's format: "Wed Jun 30 21:49:08 1993\n" */ 742 /* filetime's format: "Wed Jun 30 21:49:08 1993\n" */
742 if (all_fmt & LIST_FULLTIME) 743 if (all_fmt & LIST_FULLTIME) { /* -e */
744 /* Note: coreutils 8.4 ls --full-time prints:
745 * 2009-07-13 17:49:27.000000000 +0200
746 */
743 column += printf("%.24s ", filetime); 747 column += printf("%.24s ", filetime);
744 else { /* LIST_DATE_TIME */ 748 } else { /* LIST_DATE_TIME */
745 /* current_time_t ~== time(NULL) */ 749 /* current_time_t ~== time(NULL) */
746 time_t age = current_time_t - ttime; 750 time_t age = current_time_t - ttime;
747 printf("%.6s ", filetime + 4); /* "Jun 30" */ 751 printf("%.6s ", filetime + 4); /* "Jun 30" */
@@ -1049,7 +1053,8 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
1049 1053
1050 init_unicode(); 1054 init_unicode();
1051 1055
1052 all_fmt = ENABLE_FEATURE_LS_SORTFILES * SORT_NAME; 1056 if (ENABLE_FEATURE_LS_SORTFILES)
1057 all_fmt = SORT_NAME;
1053 1058
1054#if ENABLE_FEATURE_AUTOWIDTH 1059#if ENABLE_FEATURE_AUTOWIDTH
1055 /* obtain the terminal width */ 1060 /* obtain the terminal width */
@@ -1090,14 +1095,12 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
1090 if (flags & TIME_MASK) 1095 if (flags & TIME_MASK)
1091 all_fmt &= ~TIME_MASK; 1096 all_fmt &= ~TIME_MASK;
1092 1097
1093 if (flags & LIST_CONTEXT)
1094 all_fmt |= STYLE_SINGLE;
1095 all_fmt |= flags; 1098 all_fmt |= flags;
1096 } 1099 }
1097 } 1100 }
1098 1101
1099#if ENABLE_FEATURE_LS_COLOR 1102#if ENABLE_FEATURE_LS_COLOR
1100 /* find color bit value - last position for short getopt */ 1103 /* set show_color = 1/0 */
1101 if (ENABLE_FEATURE_LS_COLOR_IS_DEFAULT && isatty(STDOUT_FILENO)) { 1104 if (ENABLE_FEATURE_LS_COLOR_IS_DEFAULT && isatty(STDOUT_FILENO)) {
1102 char *p = getenv("LS_COLORS"); 1105 char *p = getenv("LS_COLORS");
1103 /* LS_COLORS is unset, or (not empty && not "none") ? */ 1106 /* LS_COLORS is unset, or (not empty && not "none") ? */
@@ -1130,11 +1133,8 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
1130 if (all_fmt & TIME_ACCESS) 1133 if (all_fmt & TIME_ACCESS)
1131 all_fmt = (all_fmt & ~SORT_MASK) | SORT_ATIME; 1134 all_fmt = (all_fmt & ~SORT_MASK) | SORT_ATIME;
1132 } 1135 }
1133 if ((all_fmt & STYLE_MASK) != STYLE_LONG) /* only for long list */ 1136 if ((all_fmt & STYLE_MASK) != STYLE_LONG) /* not -l? */
1134 all_fmt &= ~(LIST_ID_NUMERIC|LIST_ID_NAME|LIST_FULLTIME); 1137 all_fmt &= ~(LIST_ID_NUMERIC|LIST_ID_NAME|LIST_FULLTIME);
1135 if (ENABLE_FEATURE_LS_USERNAME)
1136 if ((all_fmt & STYLE_MASK) == STYLE_LONG && (all_fmt & LIST_ID_NUMERIC))
1137 all_fmt &= ~LIST_ID_NAME; /* don't list names if numeric uid */
1138 1138
1139 /* choose a display format if one was not already specified by an option */ 1139 /* choose a display format if one was not already specified by an option */
1140 if (!(all_fmt & STYLE_MASK)) 1140 if (!(all_fmt & STYLE_MASK))
@@ -1153,7 +1153,10 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
1153 do { 1153 do {
1154 cur = my_stat(*argv, *argv, 1154 cur = my_stat(*argv, *argv,
1155 /* follow links on command line unless -l, -s or -F: */ 1155 /* follow links on command line unless -l, -s or -F: */
1156 !((all_fmt & (STYLE_LONG|LIST_BLOCKS)) || (option_mask32 & OPT_F)) 1156 !((all_fmt & STYLE_MASK) == STYLE_LONG
1157 || (all_fmt & LIST_BLOCKS)
1158 || (option_mask32 & OPT_F)
1159 )
1157 /* ... or if -H: */ 1160 /* ... or if -H: */
1158 || (option_mask32 & OPT_H) 1161 || (option_mask32 & OPT_H)
1159 ); 1162 );