aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2017-01-23 18:01:48 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2017-01-23 18:01:48 +0100
commit11540a8da47318e34267f6ff033825ebabbd9181 (patch)
tree345dda466fdd11ddbaeb5afed24c660b44b252d6
parent7a18b9502aedbd6a9201c7c7603ded997a401f53 (diff)
downloadbusybox-w32-11540a8da47318e34267f6ff033825ebabbd9181.tar.gz
busybox-w32-11540a8da47318e34267f6ff033825ebabbd9181.tar.bz2
busybox-w32-11540a8da47318e34267f6ff033825ebabbd9181.zip
ls: handle all sort options through option_mask32
function old new delta packed_usage 31007 31024 +17 my_stat 318 324 +6 sort_and_display_files 419 420 +1 print_name 216 217 +1 sortcmp 228 216 -12 opt_flags 96 64 -32 ls_main 732 685 -47 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 4/3 up/down: 25/-91) Total: -66 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--coreutils/ls.c113
1 files changed, 42 insertions, 71 deletions
diff --git a/coreutils/ls.c b/coreutils/ls.c
index b48df8bf5..eb14a34e4 100644
--- a/coreutils/ls.c
+++ b/coreutils/ls.c
@@ -137,7 +137,7 @@
137//usage: "\n --full-time List full date and time" 137//usage: "\n --full-time List full date and time"
138//usage: )) 138//usage: ))
139//usage: IF_FEATURE_HUMAN_READABLE( 139//usage: IF_FEATURE_HUMAN_READABLE(
140//usage: "\n -h List sizes in human readable format (1K 243M 2G)" 140//usage: "\n -h Human readable sizes (1K 243M 2G)"
141//usage: ) 141//usage: )
142//usage: IF_FEATURE_LS_SORTFILES( 142//usage: IF_FEATURE_LS_SORTFILES(
143//usage: IF_LONG_OPTS( 143//usage: IF_LONG_OPTS(
@@ -158,7 +158,7 @@
158//usage: "\n -Z List security context and permission" 158//usage: "\n -Z List security context and permission"
159//usage: ) 159//usage: )
160//usage: IF_FEATURE_LS_WIDTH( 160//usage: IF_FEATURE_LS_WIDTH(
161//usage: "\n -w N Assume the terminal is N columns wide" 161//usage: "\n -w N Format N columns wide"
162//usage: ) 162//usage: )
163//usage: IF_FEATURE_LS_COLOR( 163//usage: IF_FEATURE_LS_COLOR(
164//usage: "\n --color[={always,never,auto}] Control coloring" 164//usage: "\n --color[={always,never,auto}] Control coloring"
@@ -228,17 +228,6 @@ STYLE_LONG = 2 << 19, /* one record per line, extended info */
228STYLE_SINGLE = 3 << 19, /* one record per line */ 228STYLE_SINGLE = 3 << 19, /* one record per line */
229STYLE_MASK = STYLE_SINGLE, 229STYLE_MASK = STYLE_SINGLE,
230 230
231/* how will the files be sorted (CONFIG_FEATURE_LS_SORTFILES) */
232SORT_REVERSE = 1 << 23,
233SORT_DIRS_FIRST = 1 << 24,
234
235SORT_NAME = 0, /* sort by file name */
236SORT_SIZE = 1 << 25, /* sort by file size */
237SORT_TIME = 2 << 25, /* sort by {a,m,c}time */
238SORT_VERSION = 3 << 25, /* sort by version */
239SORT_EXT = 4 << 25, /* sort by file name extension */
240SORT_MASK = (7 << 25) * ENABLE_FEATURE_LS_SORTFILES,
241
242LIST_LONG = LIST_MODEBITS | LIST_NLINKS | LIST_ID_NAME | LIST_SIZE | \ 231LIST_LONG = LIST_MODEBITS | LIST_NLINKS | LIST_ID_NAME | LIST_SIZE | \
243 LIST_DATE_TIME | LIST_SYMLINK, 232 LIST_DATE_TIME | LIST_SYMLINK,
244}; 233};
@@ -256,12 +245,13 @@ LIST_LONG = LIST_MODEBITS | LIST_NLINKS | LIST_ID_NAME | LIST_SIZE | \
256/* -T WIDTH Ignored (we don't use tabs on output) */ 245/* -T WIDTH Ignored (we don't use tabs on output) */
257/* -Z SELinux mandated option, busybox optionally supports */ 246/* -Z SELinux mandated option, busybox optionally supports */
258static const char ls_options[] ALIGN1 = 247static const char ls_options[] ALIGN1 =
259 "Cadi1lgnsxQAk" /* 13 opts, total 13 */ 248 "Cadi1lgnsxAk" /* 12 opts, total 12 */
260 IF_FEATURE_LS_TIMESTAMPS("ctu") /* 3, 16 */ 249 IF_FEATURE_LS_FILETYPES("Fp") /* 2, 14 */
261 IF_FEATURE_LS_SORTFILES("SXrv") /* 4, 20 */ 250 IF_FEATURE_LS_RECURSIVE("R") /* 1, 15 */
262 IF_FEATURE_LS_FILETYPES("Fp") /* 2, 22 */ 251 IF_SELINUX("Z") /* 1, 16 */
263 IF_FEATURE_LS_RECURSIVE("R") /* 1, 23 */ 252 "Q" /* 1, 17 */
264 IF_SELINUX("Z") /* 1, 24 */ 253 IF_FEATURE_LS_TIMESTAMPS("ctu") /* 3, 20 */
254 IF_FEATURE_LS_SORTFILES("SXrv") /* 4, 24 */
265 IF_FEATURE_LS_FOLLOWLINKS("LH") /* 2, 26 */ 255 IF_FEATURE_LS_FOLLOWLINKS("LH") /* 2, 26 */
266 IF_FEATURE_HUMAN_READABLE("h") /* 1, 27 */ 256 IF_FEATURE_HUMAN_READABLE("h") /* 1, 27 */
267 IF_FEATURE_LS_WIDTH("T:w:") /* 2, 29 */ 257 IF_FEATURE_LS_WIDTH("T:w:") /* 2, 29 */
@@ -277,22 +267,22 @@ enum {
277 //OPT_n = (1 << 7), 267 //OPT_n = (1 << 7),
278 //OPT_s = (1 << 8), 268 //OPT_s = (1 << 8),
279 //OPT_x = (1 << 9), 269 //OPT_x = (1 << 9),
280 OPT_Q = (1 << 10), 270 //OPT_A = (1 << 10),
281 //OPT_A = (1 << 11), 271 //OPT_k = (1 << 11),
282 //OPT_k = (1 << 12),
283 272
284 OPTBIT_c = 13, 273 OPTBIT_F = 12,
285 OPTBIT_t, 274 OPTBIT_p, /* 13 */
286 OPTBIT_u,
287 OPTBIT_S = OPTBIT_c + 3 * ENABLE_FEATURE_LS_TIMESTAMPS,
288 OPTBIT_X, /* 17 */
289 OPTBIT_r,
290 OPTBIT_v,
291 OPTBIT_F = OPTBIT_S + 4 * ENABLE_FEATURE_LS_SORTFILES,
292 OPTBIT_p, /* 21 */
293 OPTBIT_R = OPTBIT_F + 2 * ENABLE_FEATURE_LS_FILETYPES, 275 OPTBIT_R = OPTBIT_F + 2 * ENABLE_FEATURE_LS_FILETYPES,
294 OPTBIT_Z = OPTBIT_R + 1 * ENABLE_FEATURE_LS_RECURSIVE, 276 OPTBIT_Z = OPTBIT_R + 1 * ENABLE_FEATURE_LS_RECURSIVE,
295 OPTBIT_L = OPTBIT_Z + 2 * ENABLE_SELINUX, 277 OPTBIT_Q = OPTBIT_Z + 1 * ENABLE_SELINUX,
278 OPTBIT_c, /* 17 */
279 OPTBIT_t, /* 18 */
280 OPTBIT_u, /* 19 */
281 OPTBIT_S = OPTBIT_c + 3 * ENABLE_FEATURE_LS_TIMESTAMPS,
282 OPTBIT_X, /* 21 */
283 OPTBIT_r, /* 22 */
284 OPTBIT_v, /* 23 */
285 OPTBIT_L = OPTBIT_S + 4 * ENABLE_FEATURE_LS_SORTFILES,
296 OPTBIT_H, /* 25 */ 286 OPTBIT_H, /* 25 */
297 OPTBIT_h = OPTBIT_L + 2 * ENABLE_FEATURE_LS_FOLLOWLINKS, 287 OPTBIT_h = OPTBIT_L + 2 * ENABLE_FEATURE_LS_FOLLOWLINKS,
298 OPTBIT_T = OPTBIT_h + 1 * ENABLE_FEATURE_HUMAN_READABLE, 288 OPTBIT_T = OPTBIT_h + 1 * ENABLE_FEATURE_HUMAN_READABLE,
@@ -302,6 +292,11 @@ enum {
302 OPTBIT_color, /* 31 */ 292 OPTBIT_color, /* 31 */
303 /* with long opts, we use all 32 bits */ 293 /* with long opts, we use all 32 bits */
304 294
295 OPT_F = (1 << OPTBIT_F) * ENABLE_FEATURE_LS_FILETYPES,
296 OPT_p = (1 << OPTBIT_p) * ENABLE_FEATURE_LS_FILETYPES,
297 OPT_R = (1 << OPTBIT_R) * ENABLE_FEATURE_LS_RECURSIVE,
298 OPT_Z = (1 << OPTBIT_Z) * ENABLE_SELINUX,
299 OPT_Q = (1 << OPTBIT_Q),
305 OPT_c = (1 << OPTBIT_c) * ENABLE_FEATURE_LS_TIMESTAMPS, 300 OPT_c = (1 << OPTBIT_c) * ENABLE_FEATURE_LS_TIMESTAMPS,
306 OPT_t = (1 << OPTBIT_t) * ENABLE_FEATURE_LS_TIMESTAMPS, 301 OPT_t = (1 << OPTBIT_t) * ENABLE_FEATURE_LS_TIMESTAMPS,
307 OPT_u = (1 << OPTBIT_u) * ENABLE_FEATURE_LS_TIMESTAMPS, 302 OPT_u = (1 << OPTBIT_u) * ENABLE_FEATURE_LS_TIMESTAMPS,
@@ -309,10 +304,6 @@ enum {
309 OPT_X = (1 << OPTBIT_X) * ENABLE_FEATURE_LS_SORTFILES, 304 OPT_X = (1 << OPTBIT_X) * ENABLE_FEATURE_LS_SORTFILES,
310 OPT_r = (1 << OPTBIT_r) * ENABLE_FEATURE_LS_SORTFILES, 305 OPT_r = (1 << OPTBIT_r) * ENABLE_FEATURE_LS_SORTFILES,
311 OPT_v = (1 << OPTBIT_v) * ENABLE_FEATURE_LS_SORTFILES, 306 OPT_v = (1 << OPTBIT_v) * ENABLE_FEATURE_LS_SORTFILES,
312 OPT_F = (1 << OPTBIT_F) * ENABLE_FEATURE_LS_FILETYPES,
313 OPT_p = (1 << OPTBIT_p) * ENABLE_FEATURE_LS_FILETYPES,
314 OPT_R = (1 << OPTBIT_R) * ENABLE_FEATURE_LS_RECURSIVE,
315 OPT_Z = (1 << OPTBIT_Z) * ENABLE_SELINUX,
316 OPT_L = (1 << OPTBIT_L) * ENABLE_FEATURE_LS_FOLLOWLINKS, 307 OPT_L = (1 << OPTBIT_L) * ENABLE_FEATURE_LS_FOLLOWLINKS,
317 OPT_H = (1 << OPTBIT_H) * ENABLE_FEATURE_LS_FOLLOWLINKS, 308 OPT_H = (1 << OPTBIT_H) * ENABLE_FEATURE_LS_FOLLOWLINKS,
318 OPT_h = (1 << OPTBIT_h) * ENABLE_FEATURE_HUMAN_READABLE, 309 OPT_h = (1 << OPTBIT_h) * ENABLE_FEATURE_HUMAN_READABLE,
@@ -335,20 +326,8 @@ static const uint32_t opt_flags[] = {
335 LIST_LONG | STYLE_LONG | LIST_ID_NUMERIC, /* n (assumes l) */ 326 LIST_LONG | STYLE_LONG | LIST_ID_NUMERIC, /* n (assumes l) */
336 LIST_BLOCKS, /* s */ 327 LIST_BLOCKS, /* s */
337 DISP_ROWS | STYLE_COLUMNAR, /* x */ 328 DISP_ROWS | STYLE_COLUMNAR, /* x */
338 0, /* Q (quote filename) - handled via OPT_Q */
339 DISP_HIDDEN, /* A */ 329 DISP_HIDDEN, /* A */
340 ENABLE_SELINUX * (LIST_CONTEXT|STYLE_SINGLE), /* k (ignored if !SELINUX) */ 330 ENABLE_SELINUX * (LIST_CONTEXT|STYLE_SINGLE), /* k (ignored if !SELINUX) */
341#if ENABLE_FEATURE_LS_TIMESTAMPS
342 0, /* c - handled via OPT_c */
343 (ENABLE_FEATURE_LS_SORTFILES * SORT_TIME), /* t */
344 0, /* u - handled via OPT_u */
345#endif
346#if ENABLE_FEATURE_LS_SORTFILES
347 SORT_SIZE, /* S */
348 SORT_EXT, /* X */
349 SORT_REVERSE, /* r */
350 SORT_VERSION, /* v */
351#endif
352#if ENABLE_FEATURE_LS_FILETYPES 331#if ENABLE_FEATURE_LS_FILETYPES
353 LIST_FILETYPE | LIST_CLASSIFY, /* F */ 332 LIST_FILETYPE | LIST_CLASSIFY, /* F */
354 LIST_FILETYPE, /* p */ 333 LIST_FILETYPE, /* p */
@@ -930,30 +909,30 @@ static int sortcmp(const void *a, const void *b)
930{ 909{
931 struct dnode *d1 = *(struct dnode **)a; 910 struct dnode *d1 = *(struct dnode **)a;
932 struct dnode *d2 = *(struct dnode **)b; 911 struct dnode *d2 = *(struct dnode **)b;
933 unsigned sort_opts = G.all_fmt & SORT_MASK; 912 unsigned opt = option_mask32;
934 off_t dif; 913 off_t dif;
935 914
936 dif = 0; /* assume SORT_NAME */ 915 dif = 0; /* assume sort by name */
937 // TODO: use pre-initialized function pointer 916 // TODO: use pre-initialized function pointer
938 // instead of branch forest 917 // instead of branch forest
939 if (G.all_fmt & SORT_DIRS_FIRST) { 918 if (opt & OPT_dirs_first) {
940 dif = S_ISDIR(d2->dn_mode) - S_ISDIR(d1->dn_mode); 919 dif = S_ISDIR(d2->dn_mode) - S_ISDIR(d1->dn_mode);
941 if (dif != 0) 920 if (dif != 0)
942 goto maybe_invert_and_ret; 921 goto maybe_invert_and_ret;
943 } 922 }
944 923
945 if (sort_opts == SORT_SIZE) { 924 if (opt & OPT_S) { /* sort by size */
946 dif = (d2->dn_size - d1->dn_size); 925 dif = (d2->dn_size - d1->dn_size);
947 } else 926 } else
948 if (sort_opts == SORT_TIME) { 927 if (opt & OPT_t) { /* sort by time */
949 dif = (d2->dn_time - d1->dn_time); 928 dif = (d2->dn_time - d1->dn_time);
950 } else 929 } else
951#if defined(HAVE_STRVERSCMP) && HAVE_STRVERSCMP == 1 930#if defined(HAVE_STRVERSCMP) && HAVE_STRVERSCMP == 1
952 if (sort_opts == SORT_VERSION) { 931 if (opt & OPT_v) { /* sort by version */
953 dif = strverscmp(d1->name, d2->name); 932 dif = strverscmp(d1->name, d2->name);
954 } else 933 } else
955#endif 934#endif
956 if (sort_opts == SORT_EXT) { 935 if (opt & OPT_X) { /* sort by extension */
957 dif = strcmp(strchrnul(d1->name, '.'), strchrnul(d2->name, '.')); 936 dif = strcmp(strchrnul(d1->name, '.'), strchrnul(d2->name, '.'));
958 } 937 }
959 if (dif == 0) { 938 if (dif == 0) {
@@ -962,18 +941,17 @@ static int sortcmp(const void *a, const void *b)
962 dif = strcoll(d1->name, d2->name); 941 dif = strcoll(d1->name, d2->name);
963 else 942 else
964 dif = strcmp(d1->name, d2->name); 943 dif = strcmp(d1->name, d2->name);
965 } 944 } else {
966 945 /* Make dif fit into an int */
967 /* Make dif fit into an int */ 946 if (sizeof(dif) > sizeof(int)) {
968 if (sizeof(dif) > sizeof(int)) { 947 enum { BITS_TO_SHIFT = 8 * (sizeof(dif) - sizeof(int)) };
969 enum { BITS_TO_SHIFT = 8 * (sizeof(dif) - sizeof(int)) }; 948 /* shift leaving only "int" worth of bits */
970 /* shift leaving only "int" worth of bits */ 949 /* (this requires dif != 0, and here it is nonzero) */
971 if (dif != 0) {
972 dif = 1 | (int)((uoff_t)dif >> BITS_TO_SHIFT); 950 dif = 1 | (int)((uoff_t)dif >> BITS_TO_SHIFT);
973 } 951 }
974 } 952 }
975 maybe_invert_and_ret: 953 maybe_invert_and_ret:
976 return (G.all_fmt & SORT_REVERSE) ? -(int)dif : (int)dif; 954 return (opt & OPT_r) ? -(int)dif : (int)dif;
977} 955}
978 956
979static void dnsort(struct dnode **dn, int size) 957static void dnsort(struct dnode **dn, int size)
@@ -1162,9 +1140,6 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
1162 1140
1163 init_unicode(); 1141 init_unicode();
1164 1142
1165 if (ENABLE_FEATURE_LS_SORTFILES)
1166 G.all_fmt = SORT_NAME;
1167
1168#if ENABLE_FEATURE_LS_WIDTH 1143#if ENABLE_FEATURE_LS_WIDTH
1169 /* obtain the terminal width */ 1144 /* obtain the terminal width */
1170 G_terminal_width = get_terminal_width(STDIN_FILENO); 1145 G_terminal_width = get_terminal_width(STDIN_FILENO);
@@ -1209,14 +1184,10 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
1209 1184
1210 if (flags & STYLE_MASK) 1185 if (flags & STYLE_MASK)
1211 G.all_fmt &= ~STYLE_MASK; 1186 G.all_fmt &= ~STYLE_MASK;
1212 if (flags & SORT_MASK)
1213 G.all_fmt &= ~SORT_MASK;
1214 1187
1215 G.all_fmt |= flags; 1188 G.all_fmt |= flags;
1216 } 1189 }
1217 } 1190 }
1218 if (opt & OPT_dirs_first)
1219 G.all_fmt |= SORT_DIRS_FIRST;
1220 if (opt & OPT_full_time) 1191 if (opt & OPT_full_time)
1221 G.all_fmt |= LIST_FULLTIME; 1192 G.all_fmt |= LIST_FULLTIME;
1222 1193
@@ -1256,7 +1227,7 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
1256 /* without -l, bare -c or -u enable sort too */ 1227 /* without -l, bare -c or -u enable sort too */
1257 /* (with -l, bare -c or -u just select which time to show) */ 1228 /* (with -l, bare -c or -u just select which time to show) */
1258 if (opt & (OPT_c|OPT_u)) { 1229 if (opt & (OPT_c|OPT_u)) {
1259 G.all_fmt = (G.all_fmt & ~SORT_MASK) | SORT_TIME; 1230 option_mask32 |= OPT_t;
1260 } 1231 }
1261 } 1232 }
1262 } 1233 }