aboutsummaryrefslogtreecommitdiff
path: root/coreutils/ls.c
diff options
context:
space:
mode:
Diffstat (limited to 'coreutils/ls.c')
-rw-r--r--coreutils/ls.c90
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
349struct globals { 360struct 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
1026static 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) */
1000static struct dnode **scan_one_dir(const char *path, unsigned *nfiles_p) 1035static 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
1198static 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
1140int ls_main(int argc UNUSED_PARAM, char **argv) 1210int 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))