diff options
Diffstat (limited to 'coreutils/ls.c')
| -rw-r--r-- | coreutils/ls.c | 90 |
1 files changed, 88 insertions, 2 deletions
diff --git a/coreutils/ls.c b/coreutils/ls.c index 40017efc6..b8d276e53 100644 --- a/coreutils/ls.c +++ b/coreutils/ls.c | |||
| @@ -98,6 +98,7 @@ | |||
| 98 | 98 | ||
| 99 | //usage:#define ls_trivial_usage | 99 | //usage:#define ls_trivial_usage |
| 100 | //usage: "[-1AaCxd" | 100 | //usage: "[-1AaCxd" |
| 101 | //usage: IF_PLATFORM_MINGW32("g") | ||
| 101 | //usage: IF_FEATURE_LS_FOLLOWLINKS("LH") | 102 | //usage: IF_FEATURE_LS_FOLLOWLINKS("LH") |
| 102 | //usage: IF_FEATURE_LS_RECURSIVE("R") | 103 | //usage: IF_FEATURE_LS_RECURSIVE("R") |
| 103 | //usage: IF_FEATURE_LS_FILETYPES("Fp") "lins" | 104 | //usage: IF_FEATURE_LS_FILETYPES("Fp") "lins" |
| @@ -109,8 +110,12 @@ | |||
| 109 | //usage:#define ls_full_usage "\n\n" | 110 | //usage:#define ls_full_usage "\n\n" |
| 110 | //usage: "List directory contents\n" | 111 | //usage: "List directory contents\n" |
| 111 | //usage: "\n -1 One column output" | 112 | //usage: "\n -1 One column output" |
| 112 | //usage: "\n -a Include names starting with ." | 113 | //usage: "\n -a Include names starting with ." IF_PLATFORM_MINGW32(" and hidden files") |
| 113 | //usage: "\n -A Like -a, but exclude . and .." | 114 | //usage: "\n -A Like -a, but exclude . and .." |
| 115 | //usage: IF_PLATFORM_MINGW32( | ||
| 116 | //usage: "\n -aa,-AA Like -a,-A but omit hidden system files" | ||
| 117 | //usage: "\n -C List by columns" | ||
| 118 | //usage: ) | ||
| 114 | ////usage: "\n -C List by columns" - don't show, this is a default anyway | 119 | ////usage: "\n -C List by columns" - don't show, this is a default anyway |
| 115 | //usage: "\n -x List by lines" | 120 | //usage: "\n -x List by lines" |
| 116 | //usage: "\n -d List directory names, not contents" | 121 | //usage: "\n -d List directory names, not contents" |
| @@ -126,6 +131,9 @@ | |||
| 126 | //usage: "\n -F Append indicator (one of */=@|) to names" | 131 | //usage: "\n -F Append indicator (one of */=@|) to names" |
| 127 | //usage: ) | 132 | //usage: ) |
| 128 | //usage: "\n -l Long format" | 133 | //usage: "\n -l Long format" |
| 134 | //usage: IF_PLATFORM_MINGW32( | ||
| 135 | //usage: "\n -g Long format without group column" | ||
| 136 | //usage: ) | ||
| 129 | ////usage: "\n -g Long format without group column" | 137 | ////usage: "\n -g Long format without group column" |
| 130 | ////TODO: support -G too ("suppress owner column", GNUism) | 138 | ////TODO: support -G too ("suppress owner column", GNUism) |
| 131 | //usage: "\n -i List inode numbers" | 139 | //usage: "\n -i List inode numbers" |
| @@ -344,6 +352,9 @@ struct dnode { | |||
| 344 | int dn_rdev_min; | 352 | int dn_rdev_min; |
| 345 | // dev_t dn_dev; | 353 | // dev_t dn_dev; |
| 346 | // blksize_t dn_blksize; | 354 | // blksize_t dn_blksize; |
| 355 | #if ENABLE_PLATFORM_MINGW32 | ||
| 356 | DWORD dn_attr; | ||
| 357 | #endif | ||
| 347 | }; | 358 | }; |
| 348 | 359 | ||
| 349 | struct globals { | 360 | struct globals { |
| @@ -366,6 +377,10 @@ struct globals { | |||
| 366 | /* Do time() just once. Saves one syscall per file for "ls -l" */ | 377 | /* Do time() just once. Saves one syscall per file for "ls -l" */ |
| 367 | time_t current_time_t; | 378 | time_t current_time_t; |
| 368 | #endif | 379 | #endif |
| 380 | #if ENABLE_PLATFORM_MINGW32 | ||
| 381 | int a_count, A_count; | ||
| 382 | # define HIDSYS (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM) | ||
| 383 | #endif | ||
| 369 | } FIX_ALIASING; | 384 | } FIX_ALIASING; |
| 370 | #define G (*(struct globals*)bb_common_bufsiz1) | 385 | #define G (*(struct globals*)bb_common_bufsiz1) |
| 371 | #define INIT_G() do { \ | 386 | #define INIT_G() do { \ |
| @@ -568,7 +583,11 @@ static NOINLINE unsigned display_single(const struct dnode *dn) | |||
| 568 | lpath = xmalloc_readlink_or_warn(dn->fullname); | 583 | lpath = xmalloc_readlink_or_warn(dn->fullname); |
| 569 | 584 | ||
| 570 | if (opt & OPT_i) /* show inode# */ | 585 | if (opt & OPT_i) /* show inode# */ |
| 571 | column += printf("%7llu ", (long long) dn->dn_ino); | 586 | #if !ENABLE_FEATURE_EXTRA_FILE_DATA |
| 587 | column += printf("%7"LL_FMT"u ", (long long) dn->dn_ino); | ||
| 588 | #else | ||
| 589 | column += printf("%19"LL_FMT"u ", (long long) dn->dn_ino); | ||
| 590 | #endif | ||
| 572 | if (opt & OPT_s) { /* show allocated blocks */ | 591 | if (opt & OPT_s) { /* show allocated blocks */ |
| 573 | if (opt & OPT_h) { | 592 | if (opt & OPT_h) { |
| 574 | column += printf("%"HUMAN_READABLE_MAX_WIDTH_STR"s ", | 593 | column += printf("%"HUMAN_READABLE_MAX_WIDTH_STR"s ", |
| @@ -730,7 +749,11 @@ static void display_files(struct dnode **dn, unsigned nfiles) | |||
| 730 | } | 749 | } |
| 731 | column_width += 2 | 750 | column_width += 2 |
| 732 | + ((option_mask32 & OPT_Z) ? 33 : 0) /* context width */ | 751 | + ((option_mask32 & OPT_Z) ? 33 : 0) /* context width */ |
| 752 | #if !ENABLE_FEATURE_EXTRA_FILE_DATA | ||
| 733 | + ((option_mask32 & OPT_i) ? 8 : 0) /* inode# width */ | 753 | + ((option_mask32 & OPT_i) ? 8 : 0) /* inode# width */ |
| 754 | #else | ||
| 755 | + ((option_mask32 & OPT_i) ? 20 : 0) /* inode# width */ | ||
| 756 | #endif | ||
| 734 | + ((option_mask32 & OPT_s) ? 5 : 0) /* "alloc block" width */ | 757 | + ((option_mask32 & OPT_s) ? 5 : 0) /* "alloc block" width */ |
| 735 | ; | 758 | ; |
| 736 | ncols = (unsigned)G_terminal_width / column_width; | 759 | ncols = (unsigned)G_terminal_width / column_width; |
| @@ -816,6 +839,9 @@ static struct dnode *my_stat(const char *fullname, const char *name, int force_f | |||
| 816 | 839 | ||
| 817 | /* cur->dstat = statbuf: */ | 840 | /* cur->dstat = statbuf: */ |
| 818 | cur->dn_mode = statbuf.st_mode ; | 841 | cur->dn_mode = statbuf.st_mode ; |
| 842 | #if ENABLE_PLATFORM_MINGW32 | ||
| 843 | cur->dn_attr = statbuf.st_attr ; | ||
| 844 | #endif | ||
| 819 | cur->dn_size = statbuf.st_size ; | 845 | cur->dn_size = statbuf.st_size ; |
| 820 | #if ENABLE_FEATURE_LS_TIMESTAMPS || ENABLE_FEATURE_LS_SORTFILES | 846 | #if ENABLE_FEATURE_LS_TIMESTAMPS || ENABLE_FEATURE_LS_SORTFILES |
| 821 | cur->dn_time = statbuf.st_mtime ; | 847 | cur->dn_time = statbuf.st_mtime ; |
| @@ -996,6 +1022,15 @@ static void sort_and_display_files(struct dnode **dn, unsigned nfiles) | |||
| 996 | # define sort_and_display_files(dn, nfiles) display_files(dn, nfiles) | 1022 | # define sort_and_display_files(dn, nfiles) display_files(dn, nfiles) |
| 997 | #endif | 1023 | #endif |
| 998 | 1024 | ||
| 1025 | #if ENABLE_PLATFORM_MINGW32 | ||
| 1026 | static int hide_file(DWORD attr) | ||
| 1027 | { | ||
| 1028 | return | ||
| 1029 | ((attr & FILE_ATTRIBUTE_HIDDEN) && !(option_mask32 & (OPT_a|OPT_A))) || | ||
| 1030 | (((attr & HIDSYS) == HIDSYS) && MAX(G.a_count, G.A_count) > 1); | ||
| 1031 | } | ||
| 1032 | #endif | ||
| 1033 | |||
| 999 | /* Returns NULL-terminated malloced vector of pointers (or NULL) */ | 1034 | /* Returns NULL-terminated malloced vector of pointers (or NULL) */ |
| 1000 | static struct dnode **scan_one_dir(const char *path, unsigned *nfiles_p) | 1035 | static struct dnode **scan_one_dir(const char *path, unsigned *nfiles_p) |
| 1001 | { | 1036 | { |
| @@ -1003,6 +1038,9 @@ static struct dnode **scan_one_dir(const char *path, unsigned *nfiles_p) | |||
| 1003 | struct dirent *entry; | 1038 | struct dirent *entry; |
| 1004 | DIR *dir; | 1039 | DIR *dir; |
| 1005 | unsigned i, nfiles; | 1040 | unsigned i, nfiles; |
| 1041 | #if ENABLE_PLATFORM_MINGW32 | ||
| 1042 | struct stat statbuf; | ||
| 1043 | #endif | ||
| 1006 | 1044 | ||
| 1007 | *nfiles_p = 0; | 1045 | *nfiles_p = 0; |
| 1008 | dir = warn_opendir(path); | 1046 | dir = warn_opendir(path); |
| @@ -1025,9 +1063,29 @@ static struct dnode **scan_one_dir(const char *path, unsigned *nfiles_p) | |||
| 1025 | continue; /* if only -A, skip . and .. but show other dotfiles */ | 1063 | continue; /* if only -A, skip . and .. but show other dotfiles */ |
| 1026 | } | 1064 | } |
| 1027 | } | 1065 | } |
| 1066 | #if ENABLE_PLATFORM_MINGW32 | ||
| 1067 | if (has_dos_drive_prefix(path) && path[2] == '\0') | ||
| 1068 | fullname = xasprintf("%s%s", path, entry->d_name); | ||
| 1069 | else | ||
| 1070 | #endif | ||
| 1028 | fullname = concat_path_file(path, entry->d_name); | 1071 | fullname = concat_path_file(path, entry->d_name); |
| 1072 | #if ENABLE_PLATFORM_MINGW32 | ||
| 1073 | /* When showing link targets we must first check the | ||
| 1074 | * attributes of the link itself to see if it's hidden. */ | ||
| 1075 | if ((option_mask32 & OPT_L) && !lstat(fullname, &statbuf)) { | ||
| 1076 | if (hide_file(statbuf.st_attr)) { | ||
| 1077 | free(fullname); | ||
| 1078 | continue; | ||
| 1079 | } | ||
| 1080 | } | ||
| 1081 | #endif | ||
| 1029 | cur = my_stat(fullname, bb_basename(fullname), 0); | 1082 | cur = my_stat(fullname, bb_basename(fullname), 0); |
| 1083 | #if !ENABLE_PLATFORM_MINGW32 | ||
| 1030 | if (!cur) { | 1084 | if (!cur) { |
| 1085 | #else | ||
| 1086 | if (!cur || hide_file(cur->dn_attr)) { | ||
| 1087 | /* skip invalid or hidden files */ | ||
| 1088 | #endif | ||
| 1031 | free(fullname); | 1089 | free(fullname); |
| 1032 | continue; | 1090 | continue; |
| 1033 | } | 1091 | } |
| @@ -1136,6 +1194,18 @@ static void scan_and_display_dirs_recur(struct dnode **dn, int first) | |||
| 1136 | } | 1194 | } |
| 1137 | } | 1195 | } |
| 1138 | 1196 | ||
| 1197 | #if ENABLE_PLATFORM_MINGW32 | ||
| 1198 | static char *fix_backslash(char *p) | ||
| 1199 | { | ||
| 1200 | const char *flag = getenv("BB_FIX_BACKSLASH"); | ||
| 1201 | int value = flag ? atoi(flag) : 0; | ||
| 1202 | |||
| 1203 | if (value == 1) | ||
| 1204 | bs_to_slash(p); | ||
| 1205 | return p; | ||
| 1206 | } | ||
| 1207 | #endif | ||
| 1208 | |||
| 1139 | 1209 | ||
| 1140 | int ls_main(int argc UNUSED_PARAM, char **argv) | 1210 | int ls_main(int argc UNUSED_PARAM, char **argv) |
| 1141 | { /* ^^^^^^^^^^^^^^^^^ note: if FTPD, argc can be wrong, see ftpd.c */ | 1211 | { /* ^^^^^^^^^^^^^^^^^ note: if FTPD, argc can be wrong, see ftpd.c */ |
| @@ -1191,9 +1261,11 @@ int ls_main(int argc UNUSED_PARAM, char **argv) | |||
| 1191 | IF_FEATURE_LS_TIMESTAMPS(":c-u:u-c") /* mtime/atime */ | 1261 | IF_FEATURE_LS_TIMESTAMPS(":c-u:u-c") /* mtime/atime */ |
| 1192 | /* -w NUM: */ | 1262 | /* -w NUM: */ |
| 1193 | IF_FEATURE_LS_WIDTH(":w+") | 1263 | IF_FEATURE_LS_WIDTH(":w+") |
| 1264 | IF_PLATFORM_MINGW32(":aa:AA") | ||
| 1194 | , ls_longopts | 1265 | , ls_longopts |
| 1195 | IF_FEATURE_LS_WIDTH(, /*-T*/ NULL, /*-w*/ &G_terminal_width) | 1266 | IF_FEATURE_LS_WIDTH(, /*-T*/ NULL, /*-w*/ &G_terminal_width) |
| 1196 | IF_FEATURE_LS_COLOR(, &color_opt) | 1267 | IF_FEATURE_LS_COLOR(, &color_opt) |
| 1268 | IF_PLATFORM_MINGW32(, &G.a_count, &G.A_count) | ||
| 1197 | ); | 1269 | ); |
| 1198 | #if 0 /* option bits debug */ | 1270 | #if 0 /* option bits debug */ |
| 1199 | bb_error_msg("opt:0x%08x l:%x H:%x color:%x dirs:%x", opt, OPT_l, OPT_H, OPT_color, OPT_dirs_first); | 1271 | bb_error_msg("opt:0x%08x l:%x H:%x color:%x dirs:%x", opt, OPT_l, OPT_H, OPT_color, OPT_dirs_first); |
| @@ -1240,6 +1312,11 @@ int ls_main(int argc UNUSED_PARAM, char **argv) | |||
| 1240 | /* set G_show_color = 1/0 */ | 1312 | /* set G_show_color = 1/0 */ |
| 1241 | if (ENABLE_FEATURE_LS_COLOR_IS_DEFAULT && !is_TERM_dumb()) { | 1313 | if (ENABLE_FEATURE_LS_COLOR_IS_DEFAULT && !is_TERM_dumb()) { |
| 1242 | char *p = getenv("LS_COLORS"); | 1314 | char *p = getenv("LS_COLORS"); |
| 1315 | # if ENABLE_PLATFORM_MINGW32 | ||
| 1316 | /* No colour if unset or empty: https://no-color.org */ | ||
| 1317 | char *no_c = getenv("NO_COLOR"); | ||
| 1318 | if (!no_c || no_c[0] == '\0') | ||
| 1319 | # endif | ||
| 1243 | /* LS_COLORS is unset, or (not empty && not "none") ? */ | 1320 | /* LS_COLORS is unset, or (not empty && not "none") ? */ |
| 1244 | if (!p || (p[0] && strcmp(p, "none") != 0)) { | 1321 | if (!p || (p[0] && strcmp(p, "none") != 0)) { |
| 1245 | if (G_isatty()) { | 1322 | if (G_isatty()) { |
| @@ -1292,6 +1369,12 @@ int ls_main(int argc UNUSED_PARAM, char **argv) | |||
| 1292 | if (!(opt & OPT_q) && G_isatty()) | 1369 | if (!(opt & OPT_q) && G_isatty()) |
| 1293 | opt = option_mask32 |= OPT_q; | 1370 | opt = option_mask32 |= OPT_q; |
| 1294 | 1371 | ||
| 1372 | #if ENABLE_FEATURE_EXTRA_FILE_DATA | ||
| 1373 | /* Enable accurate link counts for directories */ | ||
| 1374 | if (opt & OPT_l) | ||
| 1375 | count_subdirs(NULL); | ||
| 1376 | #endif | ||
| 1377 | |||
| 1295 | argv += optind; | 1378 | argv += optind; |
| 1296 | if (!argv[0]) | 1379 | if (!argv[0]) |
| 1297 | *--argv = (char*)"."; | 1380 | *--argv = (char*)"."; |
| @@ -1303,6 +1386,9 @@ int ls_main(int argc UNUSED_PARAM, char **argv) | |||
| 1303 | dn = NULL; | 1386 | dn = NULL; |
| 1304 | nfiles = 0; | 1387 | nfiles = 0; |
| 1305 | do { | 1388 | do { |
| 1389 | #if ENABLE_PLATFORM_MINGW32 | ||
| 1390 | *argv = fix_backslash(*argv); | ||
| 1391 | #endif | ||
| 1306 | cur = my_stat(*argv, *argv, | 1392 | cur = my_stat(*argv, *argv, |
| 1307 | /* follow links on command line unless -l, -i, -s or -F: */ | 1393 | /* follow links on command line unless -l, -i, -s or -F: */ |
| 1308 | !(option_mask32 & (OPT_l|OPT_i|OPT_s|OPT_F)) | 1394 | !(option_mask32 & (OPT_l|OPT_i|OPT_s|OPT_F)) |
