aboutsummaryrefslogtreecommitdiff
path: root/coreutils
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2017-01-22 19:02:57 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2017-01-22 19:02:57 +0100
commitf580baf94a5ad9cdfed919c17a1a1cdf26089f15 (patch)
treeff5fc746a4a3f94ae6ddddaee314100542ab4bdd /coreutils
parent194b2ebd2a0cfc1d27744dea10ef706975c61317 (diff)
downloadbusybox-w32-f580baf94a5ad9cdfed919c17a1a1cdf26089f15.tar.gz
busybox-w32-f580baf94a5ad9cdfed919c17a1a1cdf26089f15.tar.bz2
busybox-w32-f580baf94a5ad9cdfed919c17a1a1cdf26089f15.zip
ls: more correct handling of -c, -u
function old new delta my_stat 302 318 +16 packed_usage 30977 30969 -8 display_single 928 910 -18 sortcmp 258 228 -30 ls_main 776 732 -44 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/4 up/down: 16/-100) Total: -84 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'coreutils')
-rw-r--r--coreutils/ls.c109
1 files changed, 50 insertions, 59 deletions
diff --git a/coreutils/ls.c b/coreutils/ls.c
index 0774a9a45..b9d74a2cb 100644
--- a/coreutils/ls.c
+++ b/coreutils/ls.c
@@ -101,11 +101,10 @@
101//usage: IF_FEATURE_LS_FOLLOWLINKS("LH") 101//usage: IF_FEATURE_LS_FOLLOWLINKS("LH")
102//usage: IF_FEATURE_LS_RECURSIVE("R") 102//usage: IF_FEATURE_LS_RECURSIVE("R")
103//usage: IF_FEATURE_LS_FILETYPES("Fp") "lins" 103//usage: IF_FEATURE_LS_FILETYPES("Fp") "lins"
104//usage: IF_FEATURE_LS_TIMESTAMPS("e")
105//usage: IF_FEATURE_HUMAN_READABLE("h") 104//usage: IF_FEATURE_HUMAN_READABLE("h")
106//usage: IF_FEATURE_LS_SORTFILES("rSXv") 105//usage: IF_FEATURE_LS_SORTFILES("rSXv")
107//usage: IF_FEATURE_LS_TIMESTAMPS("ctu") 106//usage: IF_FEATURE_LS_TIMESTAMPS("ctu")
108//usage: IF_SELINUX("kKZ") "]" 107//usage: IF_SELINUX("kZ") "]"
109//usage: IF_FEATURE_LS_WIDTH(" [-w WIDTH]") " [FILE]..." 108//usage: IF_FEATURE_LS_WIDTH(" [-w WIDTH]") " [FILE]..."
110//usage:#define ls_full_usage "\n\n" 109//usage:#define ls_full_usage "\n\n"
111//usage: "List directory contents\n" 110//usage: "List directory contents\n"
@@ -130,6 +129,10 @@
130//usage: "\n -i List inode numbers" 129//usage: "\n -i List inode numbers"
131//usage: "\n -n List numeric UIDs and GIDs instead of names" 130//usage: "\n -n List numeric UIDs and GIDs instead of names"
132//usage: "\n -s List allocated blocks" 131//usage: "\n -s List allocated blocks"
132//usage: IF_FEATURE_LS_TIMESTAMPS(
133//usage: "\n -c List ctime"
134//usage: "\n -u List atime"
135//usage: )
133//usage: IF_FEATURE_LS_TIMESTAMPS(IF_LONG_OPTS( 136//usage: IF_FEATURE_LS_TIMESTAMPS(IF_LONG_OPTS(
134//usage: "\n --full-time List full date and time" 137//usage: "\n --full-time List full date and time"
135//usage: )) 138//usage: ))
@@ -143,13 +146,13 @@
143//usage: "\n -S Sort by size" 146//usage: "\n -S Sort by size"
144//usage: "\n -X Sort by extension" 147//usage: "\n -X Sort by extension"
145//usage: "\n -v Sort by version" 148//usage: "\n -v Sort by version"
146//usage: "\n -r Reverse sort order"
147//usage: ) 149//usage: )
148//usage: IF_FEATURE_LS_TIMESTAMPS( 150//usage: IF_FEATURE_LS_TIMESTAMPS(
149//usage: "\n -c With -l: sort by ctime" 151//usage: "\n -t Sort by mtime"
150//usage: "\n -t With -l: sort by mtime" 152//usage: "\n -tc Sort by ctime"
151//usage: "\n -u With -l: sort by atime" 153//usage: "\n -tu Sort by atime"
152//usage: ) 154//usage: )
155//usage: "\n -r Reverse sort order"
153//usage: IF_SELINUX( 156//usage: IF_SELINUX(
154//usage: "\n -k List security context" 157//usage: "\n -k List security context"
155//usage: "\n -Z List security context and permission" 158//usage: "\n -Z List security context and permission"
@@ -225,22 +228,15 @@ STYLE_LONG = 2 << 19, /* one record per line, extended info */
225STYLE_SINGLE = 3 << 19, /* one record per line */ 228STYLE_SINGLE = 3 << 19, /* one record per line */
226STYLE_MASK = STYLE_SINGLE, 229STYLE_MASK = STYLE_SINGLE,
227 230
228/* which of the three times will be used */
229TIME_CHANGE = (1 << 21) * ENABLE_FEATURE_LS_TIMESTAMPS,
230TIME_ACCESS = (2 << 21) * ENABLE_FEATURE_LS_TIMESTAMPS,
231TIME_MASK = (3 << 21) * ENABLE_FEATURE_LS_TIMESTAMPS,
232
233/* how will the files be sorted (CONFIG_FEATURE_LS_SORTFILES) */ 231/* how will the files be sorted (CONFIG_FEATURE_LS_SORTFILES) */
234SORT_REVERSE = 1 << 23, 232SORT_REVERSE = 1 << 23,
235SORT_DIRS_FIRST = 1 << 24, 233SORT_DIRS_FIRST = 1 << 24,
236 234
237SORT_NAME = 0, /* sort by file name */ 235SORT_NAME = 0, /* sort by file name */
238SORT_SIZE = 1 << 25, /* sort by file size */ 236SORT_SIZE = 1 << 25, /* sort by file size */
239SORT_ATIME = 2 << 25, /* sort by last access time */ 237SORT_TIME = 2 << 25, /* sort by {a,m,c}time */
240SORT_CTIME = 3 << 25, /* sort by last change time */ 238SORT_VERSION = 3 << 25, /* sort by version */
241SORT_MTIME = 4 << 25, /* sort by last modification time */ 239SORT_EXT = 4 << 25, /* sort by file name extension */
242SORT_VERSION = 5 << 25, /* sort by version */
243SORT_EXT = 6 << 25, /* sort by file name extension */
244SORT_MASK = (7 << 25) * ENABLE_FEATURE_LS_SORTFILES, 240SORT_MASK = (7 << 25) * ENABLE_FEATURE_LS_SORTFILES,
245 241
246LIST_LONG = LIST_MODEBITS | LIST_NLINKS | LIST_ID_NAME | LIST_SIZE | \ 242LIST_LONG = LIST_MODEBITS | LIST_NLINKS | LIST_ID_NAME | LIST_SIZE | \
@@ -268,14 +264,14 @@ static const char ls_options[] ALIGN1 =
268 IF_SELINUX("Z") /* 1, 24 */ 264 IF_SELINUX("Z") /* 1, 24 */
269 IF_FEATURE_LS_FOLLOWLINKS("LH") /* 2, 26 */ 265 IF_FEATURE_LS_FOLLOWLINKS("LH") /* 2, 26 */
270 IF_FEATURE_HUMAN_READABLE("h") /* 1, 27 */ 266 IF_FEATURE_HUMAN_READABLE("h") /* 1, 27 */
271 IF_FEATURE_LS_WIDTH("T:w:") /* 2, 29 */ 267 IF_FEATURE_LS_WIDTH("T:w:") /* 2, 29 */
272 /* with --color, we use all 32 bits */; 268;
273enum { 269enum {
274 //OPT_C = (1 << 0), 270 //OPT_C = (1 << 0),
275 //OPT_a = (1 << 1), 271 //OPT_a = (1 << 1),
276 //OPT_d = (1 << 2), 272 //OPT_d = (1 << 2),
277 //OPT_i = (1 << 3), 273 //OPT_i = (1 << 3),
278 //OPT_l = (1 << 4), 274 OPT_l = (1 << 4),
279 //OPT_1 = (1 << 5), 275 //OPT_1 = (1 << 5),
280 OPT_g = (1 << 6), 276 OPT_g = (1 << 6),
281 //OPT_n = (1 << 7), 277 //OPT_n = (1 << 7),
@@ -301,9 +297,10 @@ enum {
301 OPTBIT_h = OPTBIT_L + 2 * ENABLE_FEATURE_LS_FOLLOWLINKS, 297 OPTBIT_h = OPTBIT_L + 2 * ENABLE_FEATURE_LS_FOLLOWLINKS,
302 OPTBIT_T = OPTBIT_h + 1 * ENABLE_FEATURE_HUMAN_READABLE, 298 OPTBIT_T = OPTBIT_h + 1 * ENABLE_FEATURE_HUMAN_READABLE,
303 OPTBIT_w, /* 28 */ 299 OPTBIT_w, /* 28 */
304 OPTBIT_color = OPTBIT_T + 2 * ENABLE_FEATURE_LS_WIDTH, 300 OPTBIT_full_time = OPTBIT_T + 2 * ENABLE_FEATURE_LS_WIDTH,
305 OPTBIT_dirs_first = OPTBIT_color + 1 * ENABLE_FEATURE_LS_COLOR, 301 OPTBIT_dirs_first,
306 OPTBIT_full_time, 302 OPTBIT_color, /* 31 */
303 /* with long opts, we use all 32 bits */
307 304
308 OPT_c = (1 << OPTBIT_c) * ENABLE_FEATURE_LS_TIMESTAMPS, 305 OPT_c = (1 << OPTBIT_c) * ENABLE_FEATURE_LS_TIMESTAMPS,
309 OPT_t = (1 << OPTBIT_t) * ENABLE_FEATURE_LS_TIMESTAMPS, 306 OPT_t = (1 << OPTBIT_t) * ENABLE_FEATURE_LS_TIMESTAMPS,
@@ -321,9 +318,9 @@ enum {
321 OPT_h = (1 << OPTBIT_h) * ENABLE_FEATURE_HUMAN_READABLE, 318 OPT_h = (1 << OPTBIT_h) * ENABLE_FEATURE_HUMAN_READABLE,
322 OPT_T = (1 << OPTBIT_T) * ENABLE_FEATURE_LS_WIDTH, 319 OPT_T = (1 << OPTBIT_T) * ENABLE_FEATURE_LS_WIDTH,
323 OPT_w = (1 << OPTBIT_w) * ENABLE_FEATURE_LS_WIDTH, 320 OPT_w = (1 << OPTBIT_w) * ENABLE_FEATURE_LS_WIDTH,
324 OPT_color = (1 << OPTBIT_color ) * ENABLE_FEATURE_LS_COLOR,
325 OPT_dirs_first = (1 << OPTBIT_dirs_first) * ENABLE_LONG_OPTS,
326 OPT_full_time = (1 << OPTBIT_full_time ) * ENABLE_LONG_OPTS, 321 OPT_full_time = (1 << OPTBIT_full_time ) * ENABLE_LONG_OPTS,
322 OPT_dirs_first = (1 << OPTBIT_dirs_first) * ENABLE_LONG_OPTS,
323 OPT_color = (1 << OPTBIT_color ) * ENABLE_FEATURE_LS_COLOR,
327}; 324};
328 325
329/* TODO: simple toggles may be stored as OPT_xxx bits instead */ 326/* TODO: simple toggles may be stored as OPT_xxx bits instead */
@@ -342,9 +339,9 @@ static const uint32_t opt_flags[] = {
342 DISP_HIDDEN, /* A */ 339 DISP_HIDDEN, /* A */
343 ENABLE_SELINUX * (LIST_CONTEXT|STYLE_SINGLE), /* k (ignored if !SELINUX) */ 340 ENABLE_SELINUX * (LIST_CONTEXT|STYLE_SINGLE), /* k (ignored if !SELINUX) */
344#if ENABLE_FEATURE_LS_TIMESTAMPS 341#if ENABLE_FEATURE_LS_TIMESTAMPS
345 TIME_CHANGE | (ENABLE_FEATURE_LS_SORTFILES * SORT_CTIME), /* c */ 342 0, /* c - handled via OPT_c */
346 ENABLE_FEATURE_LS_SORTFILES * SORT_MTIME, /* t */ 343 (ENABLE_FEATURE_LS_SORTFILES * SORT_TIME), /* t */
347 TIME_ACCESS | (ENABLE_FEATURE_LS_SORTFILES * SORT_ATIME), /* u */ 344 0, /* u - handled via OPT_u */
348#endif 345#endif
349#if ENABLE_FEATURE_LS_SORTFILES 346#if ENABLE_FEATURE_LS_SORTFILES
350 SORT_SIZE, /* S */ 347 SORT_SIZE, /* S */
@@ -396,9 +393,7 @@ struct dnode {
396 mode_t dn_mode; /* obtained with lstat OR stat, depending on -L etc */ 393 mode_t dn_mode; /* obtained with lstat OR stat, depending on -L etc */
397 off_t dn_size; 394 off_t dn_size;
398#if ENABLE_FEATURE_LS_TIMESTAMPS || ENABLE_FEATURE_LS_SORTFILES 395#if ENABLE_FEATURE_LS_TIMESTAMPS || ENABLE_FEATURE_LS_SORTFILES
399 time_t dn_atime; 396 time_t dn_time;
400 time_t dn_mtime;
401 time_t dn_ctime;
402#endif 397#endif
403 ino_t dn_ino; 398 ino_t dn_ino;
404 blkcnt_t dn_blocks; 399 blkcnt_t dn_blocks;
@@ -632,14 +627,11 @@ static NOINLINE unsigned display_single(const struct dnode *dn)
632 } 627 }
633#if ENABLE_FEATURE_LS_TIMESTAMPS 628#if ENABLE_FEATURE_LS_TIMESTAMPS
634 if (G.all_fmt & (LIST_FULLTIME|LIST_DATE_TIME)) { 629 if (G.all_fmt & (LIST_FULLTIME|LIST_DATE_TIME)) {
635 const time_t *ttime = &dn->dn_mtime; 630 const time_t *ttime = &dn->dn_time;
636 if (G.all_fmt & TIME_ACCESS)
637 ttime = &dn->dn_atime;
638 if (G.all_fmt & TIME_CHANGE)
639 ttime = &dn->dn_ctime;
640 if (G.all_fmt & LIST_FULLTIME) { /* --full-time */ 631 if (G.all_fmt & LIST_FULLTIME) { /* --full-time */
641 /* coreutils 8.4 ls --full-time prints: 632 /* coreutils 8.4 ls --full-time prints:
642 * 2009-07-13 17:49:27.000000000 +0200 633 * 2009-07-13 17:49:27.000000000 +0200
634 * we don't show fractional seconds.
643 */ 635 */
644 char buf[sizeof("YYYY-mm-dd HH:MM:SS TIMEZONE")]; 636 char buf[sizeof("YYYY-mm-dd HH:MM:SS TIMEZONE")];
645 strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S %z", localtime(ttime)); 637 strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S %z", localtime(ttime));
@@ -820,9 +812,11 @@ static struct dnode *my_stat(const char *fullname, const char *name, int force_f
820 cur->dn_mode = statbuf.st_mode ; 812 cur->dn_mode = statbuf.st_mode ;
821 cur->dn_size = statbuf.st_size ; 813 cur->dn_size = statbuf.st_size ;
822#if ENABLE_FEATURE_LS_TIMESTAMPS || ENABLE_FEATURE_LS_SORTFILES 814#if ENABLE_FEATURE_LS_TIMESTAMPS || ENABLE_FEATURE_LS_SORTFILES
823 cur->dn_atime = statbuf.st_atime ; 815 cur->dn_time = statbuf.st_mtime ;
824 cur->dn_mtime = statbuf.st_mtime ; 816 if (option_mask32 & OPT_u)
825 cur->dn_ctime = statbuf.st_ctime ; 817 cur->dn_time = statbuf.st_atime;
818 if (option_mask32 & OPT_c)
819 cur->dn_time = statbuf.st_ctime;
826#endif 820#endif
827 cur->dn_ino = statbuf.st_ino ; 821 cur->dn_ino = statbuf.st_ino ;
828 cur->dn_blocks = statbuf.st_blocks; 822 cur->dn_blocks = statbuf.st_blocks;
@@ -951,14 +945,8 @@ static int sortcmp(const void *a, const void *b)
951 if (sort_opts == SORT_SIZE) { 945 if (sort_opts == SORT_SIZE) {
952 dif = (d2->dn_size - d1->dn_size); 946 dif = (d2->dn_size - d1->dn_size);
953 } else 947 } else
954 if (sort_opts == SORT_ATIME) { 948 if (sort_opts == SORT_TIME) {
955 dif = (d2->dn_atime - d1->dn_atime); 949 dif = (d2->dn_time - d1->dn_time);
956 } else
957 if (sort_opts == SORT_CTIME) {
958 dif = (d2->dn_ctime - d1->dn_ctime);
959 } else
960 if (sort_opts == SORT_MTIME) {
961 dif = (d2->dn_mtime - d1->dn_mtime);
962 } else 950 } else
963#if defined(HAVE_STRVERSCMP) && HAVE_STRVERSCMP == 1 951#if defined(HAVE_STRVERSCMP) && HAVE_STRVERSCMP == 1
964 if (sort_opts == SORT_VERSION) { 952 if (sort_opts == SORT_VERSION) {
@@ -1159,9 +1147,9 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
1159 * (and substrings: "--color=alwa" work too) 1147 * (and substrings: "--color=alwa" work too)
1160 */ 1148 */
1161 static const char ls_longopts[] ALIGN1 = 1149 static const char ls_longopts[] ALIGN1 =
1162 "color\0" Optional_argument "\xff" /* no short equivalent */ 1150 "full-time\0" No_argument "\xff"
1163 "group-directories-first\0" No_argument "\xfe" 1151 "group-directories-first\0" No_argument "\xfe"
1164 "full-time\0" No_argument "\xfd" 1152 "color\0" Optional_argument "\xfd"
1165 ; 1153 ;
1166 static const char color_str[] ALIGN1 = 1154 static const char color_str[] ALIGN1 =
1167 "always\0""yes\0""force\0" 1155 "always\0""yes\0""force\0"
@@ -1188,7 +1176,7 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
1188 IF_FEATURE_LS_COLOR(applet_long_options = ls_longopts;) 1176 IF_FEATURE_LS_COLOR(applet_long_options = ls_longopts;)
1189 opt_complementary = 1177 opt_complementary =
1190 /* --full-time implies -l */ 1178 /* --full-time implies -l */
1191 IF_FEATURE_LS_TIMESTAMPS(IF_LONG_OPTS("\xfd""l")) 1179 IF_FEATURE_LS_TIMESTAMPS(IF_LONG_OPTS("\xff""l"))
1192 /* http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ls.html: 1180 /* http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ls.html:
1193 * in some pairs of opts, only last one takes effect: 1181 * in some pairs of opts, only last one takes effect:
1194 */ 1182 */
@@ -1206,8 +1194,9 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
1206 IF_FEATURE_LS_COLOR(, &color_opt) 1194 IF_FEATURE_LS_COLOR(, &color_opt)
1207 ); 1195 );
1208#if 0 /* option bits debug */ 1196#if 0 /* option bits debug */
1209 bb_error_msg("opt:0x%08x H:%x color:%x dirs:%x", opt, OPT_H, OPT_color, OPT_dirs_first); 1197 bb_error_msg("opt:0x%08x l:%x H:%x color:%x dirs:%x", opt, OPT_l, OPT_H, OPT_color, OPT_dirs_first);
1210 if (opt & OPT_c ) bb_error_msg("-c"); 1198 if (opt & OPT_c ) bb_error_msg("-c");
1199 if (opt & OPT_l ) bb_error_msg("-l");
1211 if (opt & OPT_H ) bb_error_msg("-H"); 1200 if (opt & OPT_H ) bb_error_msg("-H");
1212 if (opt & OPT_color ) bb_error_msg("--color"); 1201 if (opt & OPT_color ) bb_error_msg("--color");
1213 if (opt & OPT_dirs_first) bb_error_msg("--group-directories-first"); 1202 if (opt & OPT_dirs_first) bb_error_msg("--group-directories-first");
@@ -1222,8 +1211,6 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
1222 G.all_fmt &= ~STYLE_MASK; 1211 G.all_fmt &= ~STYLE_MASK;
1223 if (flags & SORT_MASK) 1212 if (flags & SORT_MASK)
1224 G.all_fmt &= ~SORT_MASK; 1213 G.all_fmt &= ~SORT_MASK;
1225 if (flags & TIME_MASK)
1226 G.all_fmt &= ~TIME_MASK;
1227 1214
1228 G.all_fmt |= flags; 1215 G.all_fmt |= flags;
1229 } 1216 }
@@ -1261,14 +1248,18 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
1261 /* sort out which command line options take precedence */ 1248 /* sort out which command line options take precedence */
1262 if (ENABLE_FEATURE_LS_RECURSIVE && (G.all_fmt & DISP_NOLIST)) 1249 if (ENABLE_FEATURE_LS_RECURSIVE && (G.all_fmt & DISP_NOLIST))
1263 G.all_fmt &= ~DISP_RECURSIVE; /* no recurse if listing only dir */ 1250 G.all_fmt &= ~DISP_RECURSIVE; /* no recurse if listing only dir */
1264 if (ENABLE_FEATURE_LS_TIMESTAMPS && ENABLE_FEATURE_LS_SORTFILES) { 1251 if ((G.all_fmt & STYLE_MASK) != STYLE_LONG) { /* not -l? */
1265 if (G.all_fmt & TIME_CHANGE)
1266 G.all_fmt = (G.all_fmt & ~SORT_MASK) | SORT_CTIME;
1267 if (G.all_fmt & TIME_ACCESS)
1268 G.all_fmt = (G.all_fmt & ~SORT_MASK) | SORT_ATIME;
1269 }
1270 if ((G.all_fmt & STYLE_MASK) != STYLE_LONG) /* not -l? */
1271 G.all_fmt &= ~(LIST_ID_NUMERIC|LIST_ID_NAME|LIST_FULLTIME); 1252 G.all_fmt &= ~(LIST_ID_NUMERIC|LIST_ID_NAME|LIST_FULLTIME);
1253 if (ENABLE_FEATURE_LS_TIMESTAMPS && ENABLE_FEATURE_LS_SORTFILES) {
1254 /* when to sort by time? -t[cu] sorts by time even with -l */
1255 /* (this is achieved by opt_flags[] element for -t) */
1256 /* without -l, bare -c or -u enable sort too */
1257 /* (with -l, bare -c or -u just select which time to show) */
1258 if (opt & (OPT_c|OPT_u)) {
1259 G.all_fmt = (G.all_fmt & ~SORT_MASK) | SORT_TIME;
1260 }
1261 }
1262 }
1272 1263
1273 /* choose a display format if one was not already specified by an option */ 1264 /* choose a display format if one was not already specified by an option */
1274 if (!(G.all_fmt & STYLE_MASK)) 1265 if (!(G.all_fmt & STYLE_MASK))