[git commit] ls: more correct handling of -c, -u

Denys Vlasenko vda.linux at googlemail.com
Sun Jan 22 18:02:57 UTC 2017


commit: https://git.busybox.net/busybox/commit/?id=f580baf94a5ad9cdfed919c17a1a1cdf26089f15
branch: https://git.busybox.net/busybox/commit/?id=refs/heads/master

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 at googlemail.com>
---
 coreutils/ls.c | 109 ++++++++++++++++++++++++++-------------------------------
 1 file changed, 50 insertions(+), 59 deletions(-)

diff --git a/coreutils/ls.c b/coreutils/ls.c
index 0774a9a..b9d74a2 100644
--- a/coreutils/ls.c
+++ b/coreutils/ls.c
@@ -101,11 +101,10 @@
 //usage:	IF_FEATURE_LS_FOLLOWLINKS("LH")
 //usage:	IF_FEATURE_LS_RECURSIVE("R")
 //usage:	IF_FEATURE_LS_FILETYPES("Fp") "lins"
-//usage:	IF_FEATURE_LS_TIMESTAMPS("e")
 //usage:	IF_FEATURE_HUMAN_READABLE("h")
 //usage:	IF_FEATURE_LS_SORTFILES("rSXv")
 //usage:	IF_FEATURE_LS_TIMESTAMPS("ctu")
-//usage:	IF_SELINUX("kKZ") "]"
+//usage:	IF_SELINUX("kZ") "]"
 //usage:	IF_FEATURE_LS_WIDTH(" [-w WIDTH]") " [FILE]..."
 //usage:#define ls_full_usage "\n\n"
 //usage:       "List directory contents\n"
@@ -130,6 +129,10 @@
 //usage:     "\n	-i	List inode numbers"
 //usage:     "\n	-n	List numeric UIDs and GIDs instead of names"
 //usage:     "\n	-s	List allocated blocks"
+//usage:	IF_FEATURE_LS_TIMESTAMPS(
+//usage:     "\n	-c	List ctime"
+//usage:     "\n	-u	List atime"
+//usage:	)
 //usage:	IF_FEATURE_LS_TIMESTAMPS(IF_LONG_OPTS(
 //usage:     "\n	--full-time	List full date and time"
 //usage:	))
@@ -143,13 +146,13 @@
 //usage:     "\n	-S	Sort by size"
 //usage:     "\n	-X	Sort by extension"
 //usage:     "\n	-v	Sort by version"
-//usage:     "\n	-r	Reverse sort order"
 //usage:	)
 //usage:	IF_FEATURE_LS_TIMESTAMPS(
-//usage:     "\n	-c	With -l: sort by ctime"
-//usage:     "\n	-t	With -l: sort by mtime"
-//usage:     "\n	-u	With -l: sort by atime"
+//usage:     "\n	-t	Sort by mtime"
+//usage:     "\n	-tc	Sort by ctime"
+//usage:     "\n	-tu	Sort by atime"
 //usage:	)
+//usage:     "\n	-r	Reverse sort order"
 //usage:	IF_SELINUX(
 //usage:     "\n	-k	List security context"
 //usage:     "\n	-Z	List security context and permission"
@@ -225,22 +228,15 @@ STYLE_LONG      = 2 << 19,      /* one record per line, extended info */
 STYLE_SINGLE    = 3 << 19,      /* one record per line */
 STYLE_MASK      = STYLE_SINGLE,
 
-/* which of the three times will be used */
-TIME_CHANGE     = (1 << 21) * ENABLE_FEATURE_LS_TIMESTAMPS,
-TIME_ACCESS     = (2 << 21) * ENABLE_FEATURE_LS_TIMESTAMPS,
-TIME_MASK       = (3 << 21) * ENABLE_FEATURE_LS_TIMESTAMPS,
-
 /* how will the files be sorted (CONFIG_FEATURE_LS_SORTFILES) */
 SORT_REVERSE    = 1 << 23,
 SORT_DIRS_FIRST = 1 << 24,
 
 SORT_NAME       = 0,            /* sort by file name */
 SORT_SIZE       = 1 << 25,      /* sort by file size */
-SORT_ATIME      = 2 << 25,      /* sort by last access time */
-SORT_CTIME      = 3 << 25,      /* sort by last change time */
-SORT_MTIME      = 4 << 25,      /* sort by last modification time */
-SORT_VERSION    = 5 << 25,      /* sort by version */
-SORT_EXT        = 6 << 25,      /* sort by file name extension */
+SORT_TIME       = 2 << 25,      /* sort by {a,m,c}time */
+SORT_VERSION    = 3 << 25,      /* sort by version */
+SORT_EXT        = 4 << 25,      /* sort by file name extension */
 SORT_MASK       = (7 << 25) * ENABLE_FEATURE_LS_SORTFILES,
 
 LIST_LONG       = LIST_MODEBITS | LIST_NLINKS | LIST_ID_NAME | LIST_SIZE | \
@@ -268,14 +264,14 @@ static const char ls_options[] ALIGN1 =
 	IF_SELINUX("Z")                  /* 1, 24 */
 	IF_FEATURE_LS_FOLLOWLINKS("LH")  /* 2, 26 */
 	IF_FEATURE_HUMAN_READABLE("h")   /* 1, 27 */
-	IF_FEATURE_LS_WIDTH("T:w:")     /* 2, 29 */
-	/* with --color, we use all 32 bits */;
+	IF_FEATURE_LS_WIDTH("T:w:")      /* 2, 29 */
+;
 enum {
 	//OPT_C = (1 << 0),
 	//OPT_a = (1 << 1),
 	//OPT_d = (1 << 2),
 	//OPT_i = (1 << 3),
-	//OPT_l = (1 << 4),
+	OPT_l = (1 << 4),
 	//OPT_1 = (1 << 5),
 	OPT_g = (1 << 6),
 	//OPT_n = (1 << 7),
@@ -301,9 +297,10 @@ enum {
 	OPTBIT_h = OPTBIT_L + 2 * ENABLE_FEATURE_LS_FOLLOWLINKS,
 	OPTBIT_T = OPTBIT_h + 1 * ENABLE_FEATURE_HUMAN_READABLE,
 	OPTBIT_w, /* 28 */
-	OPTBIT_color      = OPTBIT_T + 2 * ENABLE_FEATURE_LS_WIDTH,
-	OPTBIT_dirs_first = OPTBIT_color + 1 * ENABLE_FEATURE_LS_COLOR,
-	OPTBIT_full_time,
+	OPTBIT_full_time = OPTBIT_T + 2 * ENABLE_FEATURE_LS_WIDTH,
+	OPTBIT_dirs_first,
+	OPTBIT_color, /* 31 */
+	/* with long opts, we use all 32 bits */
 
 	OPT_c = (1 << OPTBIT_c) * ENABLE_FEATURE_LS_TIMESTAMPS,
 	OPT_t = (1 << OPTBIT_t) * ENABLE_FEATURE_LS_TIMESTAMPS,
@@ -321,9 +318,9 @@ enum {
 	OPT_h = (1 << OPTBIT_h) * ENABLE_FEATURE_HUMAN_READABLE,
 	OPT_T = (1 << OPTBIT_T) * ENABLE_FEATURE_LS_WIDTH,
 	OPT_w = (1 << OPTBIT_w) * ENABLE_FEATURE_LS_WIDTH,
-	OPT_color      = (1 << OPTBIT_color     ) * ENABLE_FEATURE_LS_COLOR,
-	OPT_dirs_first = (1 << OPTBIT_dirs_first) * ENABLE_LONG_OPTS,
 	OPT_full_time  = (1 << OPTBIT_full_time ) * ENABLE_LONG_OPTS,
+	OPT_dirs_first = (1 << OPTBIT_dirs_first) * ENABLE_LONG_OPTS,
+	OPT_color      = (1 << OPTBIT_color     ) * ENABLE_FEATURE_LS_COLOR,
 };
 
 /* TODO: simple toggles may be stored as OPT_xxx bits instead */
@@ -342,9 +339,9 @@ static const uint32_t opt_flags[] = {
 	DISP_HIDDEN,                 /* A */
 	ENABLE_SELINUX * (LIST_CONTEXT|STYLE_SINGLE), /* k (ignored if !SELINUX) */
 #if ENABLE_FEATURE_LS_TIMESTAMPS
-	TIME_CHANGE | (ENABLE_FEATURE_LS_SORTFILES * SORT_CTIME), /* c */
-	ENABLE_FEATURE_LS_SORTFILES * SORT_MTIME, /* t */
-	TIME_ACCESS | (ENABLE_FEATURE_LS_SORTFILES * SORT_ATIME), /* u */
+	0,                           /* c - handled via OPT_c */
+	(ENABLE_FEATURE_LS_SORTFILES * SORT_TIME), /* t */
+	0,                           /* u - handled via OPT_u */
 #endif
 #if ENABLE_FEATURE_LS_SORTFILES
 	SORT_SIZE,                   /* S */
@@ -396,9 +393,7 @@ struct dnode {
 	mode_t    dn_mode; /* obtained with lstat OR stat, depending on -L etc */
 	off_t     dn_size;
 #if ENABLE_FEATURE_LS_TIMESTAMPS || ENABLE_FEATURE_LS_SORTFILES
-	time_t    dn_atime;
-	time_t    dn_mtime;
-	time_t    dn_ctime;
+	time_t    dn_time;
 #endif
 	ino_t     dn_ino;
 	blkcnt_t  dn_blocks;
@@ -632,14 +627,11 @@ static NOINLINE unsigned display_single(const struct dnode *dn)
 	}
 #if ENABLE_FEATURE_LS_TIMESTAMPS
 	if (G.all_fmt & (LIST_FULLTIME|LIST_DATE_TIME)) {
-		const time_t *ttime = &dn->dn_mtime;
-		if (G.all_fmt & TIME_ACCESS)
-			ttime = &dn->dn_atime;
-		if (G.all_fmt & TIME_CHANGE)
-			ttime = &dn->dn_ctime;
+		const time_t *ttime = &dn->dn_time;
 		if (G.all_fmt & LIST_FULLTIME) { /* --full-time */
 			/* coreutils 8.4 ls --full-time prints:
 			 * 2009-07-13 17:49:27.000000000 +0200
+			 * we don't show fractional seconds.
 			 */
 			char buf[sizeof("YYYY-mm-dd HH:MM:SS TIMEZONE")];
 			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
 	cur->dn_mode   = statbuf.st_mode  ;
 	cur->dn_size   = statbuf.st_size  ;
 #if ENABLE_FEATURE_LS_TIMESTAMPS || ENABLE_FEATURE_LS_SORTFILES
-	cur->dn_atime  = statbuf.st_atime ;
-	cur->dn_mtime  = statbuf.st_mtime ;
-	cur->dn_ctime  = statbuf.st_ctime ;
+	cur->dn_time   = statbuf.st_mtime ;
+	if (option_mask32 & OPT_u)
+		cur->dn_time = statbuf.st_atime;
+	if (option_mask32 & OPT_c)
+		cur->dn_time = statbuf.st_ctime;
 #endif
 	cur->dn_ino    = statbuf.st_ino   ;
 	cur->dn_blocks = statbuf.st_blocks;
@@ -951,14 +945,8 @@ static int sortcmp(const void *a, const void *b)
 	if (sort_opts == SORT_SIZE) {
 		dif = (d2->dn_size - d1->dn_size);
 	} else
-	if (sort_opts == SORT_ATIME) {
-		dif = (d2->dn_atime - d1->dn_atime);
-	} else
-	if (sort_opts == SORT_CTIME) {
-		dif = (d2->dn_ctime - d1->dn_ctime);
-	} else
-	if (sort_opts == SORT_MTIME) {
-		dif = (d2->dn_mtime - d1->dn_mtime);
+	if (sort_opts == SORT_TIME) {
+		dif = (d2->dn_time - d1->dn_time);
 	} else
 #if defined(HAVE_STRVERSCMP) && HAVE_STRVERSCMP == 1
 	if (sort_opts == SORT_VERSION) {
@@ -1159,9 +1147,9 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
 	 * (and substrings: "--color=alwa" work too)
 	 */
 	static const char ls_longopts[] ALIGN1 =
-		"color\0" Optional_argument "\xff" /* no short equivalent */
+		"full-time\0" No_argument "\xff"
 		"group-directories-first\0" No_argument "\xfe"
-		"full-time\0" No_argument "\xfd"
+		"color\0" Optional_argument "\xfd"
 	;
 	static const char color_str[] ALIGN1 =
 		"always\0""yes\0""force\0"
@@ -1188,7 +1176,7 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
 	IF_FEATURE_LS_COLOR(applet_long_options = ls_longopts;)
 	opt_complementary =
 		/* --full-time implies -l */
-		IF_FEATURE_LS_TIMESTAMPS(IF_LONG_OPTS("\xfd""l"))
+		IF_FEATURE_LS_TIMESTAMPS(IF_LONG_OPTS("\xff""l"))
 		/* http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ls.html:
 		 * in some pairs of opts, only last one takes effect:
 		 */
@@ -1206,8 +1194,9 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
 		IF_FEATURE_LS_COLOR(, &color_opt)
 	);
 #if 0 /* option bits debug */
-	bb_error_msg("opt:0x%08x H:%x color:%x dirs:%x", opt, OPT_H, OPT_color, OPT_dirs_first);
+	bb_error_msg("opt:0x%08x l:%x H:%x color:%x dirs:%x", opt, OPT_l, OPT_H, OPT_color, OPT_dirs_first);
 	if (opt & OPT_c         ) bb_error_msg("-c");
+	if (opt & OPT_l         ) bb_error_msg("-l");
 	if (opt & OPT_H         ) bb_error_msg("-H");
 	if (opt & OPT_color     ) bb_error_msg("--color");
 	if (opt & OPT_dirs_first) bb_error_msg("--group-directories-first");
@@ -1222,8 +1211,6 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
 				G.all_fmt &= ~STYLE_MASK;
 			if (flags & SORT_MASK)
 				G.all_fmt &= ~SORT_MASK;
-			if (flags & TIME_MASK)
-				G.all_fmt &= ~TIME_MASK;
 
 			G.all_fmt |= flags;
 		}
@@ -1261,14 +1248,18 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
 	/* sort out which command line options take precedence */
 	if (ENABLE_FEATURE_LS_RECURSIVE && (G.all_fmt & DISP_NOLIST))
 		G.all_fmt &= ~DISP_RECURSIVE;	/* no recurse if listing only dir */
-	if (ENABLE_FEATURE_LS_TIMESTAMPS && ENABLE_FEATURE_LS_SORTFILES) {
-		if (G.all_fmt & TIME_CHANGE)
-			G.all_fmt = (G.all_fmt & ~SORT_MASK) | SORT_CTIME;
-		if (G.all_fmt & TIME_ACCESS)
-			G.all_fmt = (G.all_fmt & ~SORT_MASK) | SORT_ATIME;
-	}
-	if ((G.all_fmt & STYLE_MASK) != STYLE_LONG) /* not -l? */
+	if ((G.all_fmt & STYLE_MASK) != STYLE_LONG) { /* not -l? */
 		G.all_fmt &= ~(LIST_ID_NUMERIC|LIST_ID_NAME|LIST_FULLTIME);
+		if (ENABLE_FEATURE_LS_TIMESTAMPS && ENABLE_FEATURE_LS_SORTFILES) {
+			/* when to sort by time? -t[cu] sorts by time even with -l */
+			/* (this is achieved by opt_flags[] element for -t) */
+			/* without -l, bare -c or -u enable sort too */
+			/* (with -l, bare -c or -u just select which time to show) */
+			if (opt & (OPT_c|OPT_u)) {
+				G.all_fmt = (G.all_fmt & ~SORT_MASK) | SORT_TIME;
+			}
+		}
+	}
 
 	/* choose a display format if one was not already specified by an option */
 	if (!(G.all_fmt & STYLE_MASK))


More information about the busybox-cvs mailing list