aboutsummaryrefslogtreecommitdiff
path: root/coreutils/ls.c
diff options
context:
space:
mode:
Diffstat (limited to 'coreutils/ls.c')
-rw-r--r--coreutils/ls.c80
1 files changed, 78 insertions, 2 deletions
diff --git a/coreutils/ls.c b/coreutils/ls.c
index b69b80460..df4277fbd 100644
--- a/coreutils/ls.c
+++ b/coreutils/ls.c
@@ -109,8 +109,11 @@
109//usage:#define ls_full_usage "\n\n" 109//usage:#define ls_full_usage "\n\n"
110//usage: "List directory contents\n" 110//usage: "List directory contents\n"
111//usage: "\n -1 One column output" 111//usage: "\n -1 One column output"
112//usage: "\n -a Include names starting with ." 112//usage: "\n -a Include names starting with ." IF_PLATFORM_MINGW32(" and hidden files")
113//usage: "\n -A Like -a, but exclude . and .." 113//usage: "\n -A Like -a, but exclude . and .."
114//usage: IF_PLATFORM_MINGW32(
115//usage: "\n -aa,-AA Like -a,-A but omit hidden system files"
116//usage: )
114////usage: "\n -C List by columns" - don't show, this is a default anyway 117////usage: "\n -C List by columns" - don't show, this is a default anyway
115//usage: "\n -x List by lines" 118//usage: "\n -x List by lines"
116//usage: "\n -d List directory names, not contents" 119//usage: "\n -d List directory names, not contents"
@@ -316,6 +319,9 @@ struct dnode {
316 int dn_rdev_min; 319 int dn_rdev_min;
317// dev_t dn_dev; 320// dev_t dn_dev;
318// blksize_t dn_blksize; 321// blksize_t dn_blksize;
322#if ENABLE_PLATFORM_MINGW32
323 DWORD dn_attr;
324#endif
319}; 325};
320 326
321struct globals { 327struct globals {
@@ -337,6 +343,10 @@ struct globals {
337 /* Do time() just once. Saves one syscall per file for "ls -l" */ 343 /* Do time() just once. Saves one syscall per file for "ls -l" */
338 time_t current_time_t; 344 time_t current_time_t;
339#endif 345#endif
346#if ENABLE_PLATFORM_MINGW32
347 int a_count, A_count;
348# define HIDSYS (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)
349#endif
340} FIX_ALIASING; 350} FIX_ALIASING;
341#define G (*(struct globals*)bb_common_bufsiz1) 351#define G (*(struct globals*)bb_common_bufsiz1)
342#define INIT_G() do { \ 352#define INIT_G() do { \
@@ -497,7 +507,11 @@ static NOINLINE unsigned display_single(const struct dnode *dn)
497 lpath = xmalloc_readlink_or_warn(dn->fullname); 507 lpath = xmalloc_readlink_or_warn(dn->fullname);
498 508
499 if (opt & OPT_i) /* show inode# */ 509 if (opt & OPT_i) /* show inode# */
500 column += printf("%7llu ", (long long) dn->dn_ino); 510#if !ENABLE_FEATURE_EXTRA_FILE_DATA
511 column += printf("%7"LL_FMT"u ", (long long) dn->dn_ino);
512#else
513 column += printf("%19"LL_FMT"u ", (long long) dn->dn_ino);
514#endif
501 if (opt & OPT_s) { /* show allocated blocks */ 515 if (opt & OPT_s) { /* show allocated blocks */
502 if (opt & OPT_h) { 516 if (opt & OPT_h) {
503 column += printf("%"HUMAN_READABLE_MAX_WIDTH_STR"s ", 517 column += printf("%"HUMAN_READABLE_MAX_WIDTH_STR"s ",
@@ -659,7 +673,11 @@ static void display_files(struct dnode **dn, unsigned nfiles)
659 } 673 }
660 column_width += 2 674 column_width += 2
661 + ((option_mask32 & OPT_Z) ? 33 : 0) /* context width */ 675 + ((option_mask32 & OPT_Z) ? 33 : 0) /* context width */
676#if !ENABLE_FEATURE_EXTRA_FILE_DATA
662 + ((option_mask32 & OPT_i) ? 8 : 0) /* inode# width */ 677 + ((option_mask32 & OPT_i) ? 8 : 0) /* inode# width */
678#else
679 + ((option_mask32 & OPT_i) ? 20 : 0) /* inode# width */
680#endif
663 + ((option_mask32 & OPT_s) ? 5 : 0) /* "alloc block" width */ 681 + ((option_mask32 & OPT_s) ? 5 : 0) /* "alloc block" width */
664 ; 682 ;
665 ncols = (unsigned)G_terminal_width / column_width; 683 ncols = (unsigned)G_terminal_width / column_width;
@@ -740,6 +758,9 @@ static struct dnode *my_stat(const char *fullname, const char *name, int force_f
740 758
741 /* cur->dstat = statbuf: */ 759 /* cur->dstat = statbuf: */
742 cur->dn_mode = statbuf.st_mode ; 760 cur->dn_mode = statbuf.st_mode ;
761#if ENABLE_PLATFORM_MINGW32
762 cur->dn_attr = statbuf.st_attr ;
763#endif
743 cur->dn_size = statbuf.st_size ; 764 cur->dn_size = statbuf.st_size ;
744#if ENABLE_FEATURE_LS_TIMESTAMPS || ENABLE_FEATURE_LS_SORTFILES 765#if ENABLE_FEATURE_LS_TIMESTAMPS || ENABLE_FEATURE_LS_SORTFILES
745 cur->dn_time = statbuf.st_mtime ; 766 cur->dn_time = statbuf.st_mtime ;
@@ -920,6 +941,15 @@ static void sort_and_display_files(struct dnode **dn, unsigned nfiles)
920# define sort_and_display_files(dn, nfiles) display_files(dn, nfiles) 941# define sort_and_display_files(dn, nfiles) display_files(dn, nfiles)
921#endif 942#endif
922 943
944#if ENABLE_PLATFORM_MINGW32
945static int hide_file(DWORD attr)
946{
947 return
948 ((attr & FILE_ATTRIBUTE_HIDDEN) && !(option_mask32 & (OPT_a|OPT_A))) ||
949 (((attr & HIDSYS) == HIDSYS) && MAX(G.a_count, G.A_count) > 1);
950}
951#endif
952
923/* Returns NULL-terminated malloced vector of pointers (or NULL) */ 953/* Returns NULL-terminated malloced vector of pointers (or NULL) */
924static struct dnode **scan_one_dir(const char *path, unsigned *nfiles_p) 954static struct dnode **scan_one_dir(const char *path, unsigned *nfiles_p)
925{ 955{
@@ -927,6 +957,9 @@ static struct dnode **scan_one_dir(const char *path, unsigned *nfiles_p)
927 struct dirent *entry; 957 struct dirent *entry;
928 DIR *dir; 958 DIR *dir;
929 unsigned i, nfiles; 959 unsigned i, nfiles;
960#if ENABLE_PLATFORM_MINGW32
961 struct stat statbuf;
962#endif
930 963
931 *nfiles_p = 0; 964 *nfiles_p = 0;
932 dir = warn_opendir(path); 965 dir = warn_opendir(path);
@@ -949,9 +982,29 @@ static struct dnode **scan_one_dir(const char *path, unsigned *nfiles_p)
949 continue; /* if only -A, skip . and .. but show other dotfiles */ 982 continue; /* if only -A, skip . and .. but show other dotfiles */
950 } 983 }
951 } 984 }
985#if ENABLE_PLATFORM_MINGW32
986 if (has_dos_drive_prefix(path) && path[2] == '\0')
987 fullname = xasprintf("%s%s", path, entry->d_name);
988 else
989#endif
952 fullname = concat_path_file(path, entry->d_name); 990 fullname = concat_path_file(path, entry->d_name);
991#if ENABLE_PLATFORM_MINGW32
992 /* When showing link targets we must first check the
993 * attributes of the link itself to see if it's hidden. */
994 if ((option_mask32 & OPT_L) && !lstat(fullname, &statbuf)) {
995 if (hide_file(statbuf.st_attr)) {
996 free(fullname);
997 continue;
998 }
999 }
1000#endif
953 cur = my_stat(fullname, bb_basename(fullname), 0); 1001 cur = my_stat(fullname, bb_basename(fullname), 0);
1002#if !ENABLE_PLATFORM_MINGW32
954 if (!cur) { 1003 if (!cur) {
1004#else
1005 if (!cur || hide_file(cur->dn_attr)) {
1006 /* skip invalid or hidden files */
1007#endif
955 free(fullname); 1008 free(fullname);
956 continue; 1009 continue;
957 } 1010 }
@@ -1060,6 +1113,18 @@ static void scan_and_display_dirs_recur(struct dnode **dn, int first)
1060 } 1113 }
1061} 1114}
1062 1115
1116#if ENABLE_PLATFORM_MINGW32
1117static char *fix_backslash(char *p)
1118{
1119 const char *flag = getenv("BB_FIX_BACKSLASH");
1120 int value = flag ? atoi(flag) : 0;
1121
1122 if (value == 1)
1123 bs_to_slash(p);
1124 return p;
1125}
1126#endif
1127
1063 1128
1064int ls_main(int argc UNUSED_PARAM, char **argv) 1129int ls_main(int argc UNUSED_PARAM, char **argv)
1065{ /* ^^^^^^^^^^^^^^^^^ note: if FTPD, argc can be wrong, see ftpd.c */ 1130{ /* ^^^^^^^^^^^^^^^^^ note: if FTPD, argc can be wrong, see ftpd.c */
@@ -1129,9 +1194,11 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
1129 IF_FEATURE_LS_TIMESTAMPS(":c-u:u-c") /* mtime/atime */ 1194 IF_FEATURE_LS_TIMESTAMPS(":c-u:u-c") /* mtime/atime */
1130 /* -w NUM: */ 1195 /* -w NUM: */
1131 IF_FEATURE_LS_WIDTH(":w+") 1196 IF_FEATURE_LS_WIDTH(":w+")
1197 IF_PLATFORM_MINGW32(":aa:AA")
1132 , ls_longopts 1198 , ls_longopts
1133 IF_FEATURE_LS_WIDTH(, /*-T*/ NULL, /*-w*/ &G_terminal_width) 1199 IF_FEATURE_LS_WIDTH(, /*-T*/ NULL, /*-w*/ &G_terminal_width)
1134 IF_FEATURE_LS_COLOR(, &color_opt) 1200 IF_FEATURE_LS_COLOR(, &color_opt)
1201 IF_PLATFORM_MINGW32(, &G.a_count, &G.A_count)
1135 ); 1202 );
1136#if 0 /* option bits debug */ 1203#if 0 /* option bits debug */
1137 bb_error_msg("opt:0x%08x l:%x H:%x color:%x dirs:%x", opt, OPT_l, OPT_H, OPT_color, OPT_dirs_first); 1204 bb_error_msg("opt:0x%08x l:%x H:%x color:%x dirs:%x", opt, OPT_l, OPT_H, OPT_color, OPT_dirs_first);
@@ -1204,6 +1271,12 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
1204 option_mask32 |= OPT_dirs_first; 1271 option_mask32 |= OPT_dirs_first;
1205 } 1272 }
1206 1273
1274#if ENABLE_FEATURE_EXTRA_FILE_DATA
1275 /* Enable accurate link counts for directories */
1276 if (opt & OPT_l)
1277 count_subdirs(NULL);
1278#endif
1279
1207 argv += optind; 1280 argv += optind;
1208 if (!argv[0]) 1281 if (!argv[0])
1209 *--argv = (char*)"."; 1282 *--argv = (char*)".";
@@ -1215,6 +1288,9 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
1215 dn = NULL; 1288 dn = NULL;
1216 nfiles = 0; 1289 nfiles = 0;
1217 do { 1290 do {
1291#if ENABLE_PLATFORM_MINGW32
1292 *argv = fix_backslash(*argv);
1293#endif
1218 cur = my_stat(*argv, *argv, 1294 cur = my_stat(*argv, *argv,
1219 /* follow links on command line unless -l, -i, -s or -F: */ 1295 /* follow links on command line unless -l, -i, -s or -F: */
1220 !(option_mask32 & (OPT_l|OPT_i|OPT_s|OPT_F)) 1296 !(option_mask32 & (OPT_l|OPT_i|OPT_s|OPT_F))