diff options
-rw-r--r-- | coreutils/ls.c | 141 |
1 files changed, 64 insertions, 77 deletions
diff --git a/coreutils/ls.c b/coreutils/ls.c index 75d7b1f..ac2557a 100644 --- a/coreutils/ls.c +++ b/coreutils/ls.c @@ -83,15 +83,15 @@ enum { /* 51306 lrwxrwxrwx 1 root root 2 May 11 01:43 /bin/view -> vi* */ /* what file information will be listed */ -#define LIST_INO (1U<<0) -#define LIST_BLOCKS (1U<<1) +#define LIST_INO (1U<<0) +#define LIST_BLOCKS (1U<<1) #define LIST_MODEBITS (1U<<2) -#define LIST_NLINKS (1U<<3) +#define LIST_NLINKS (1U<<3) #define LIST_ID_NAME (1U<<4) #define LIST_ID_NUMERIC (1U<<5) #define LIST_CONTEXT (1U<<6) -#define LIST_SIZE (1U<<7) -#define LIST_DEV (1U<<8) +#define LIST_SIZE (1U<<7) +#define LIST_DEV (1U<<8) #define LIST_DATE_TIME (1U<<9) #define LIST_FULLTIME (1U<<10) #define LIST_FILENAME (1U<<11) @@ -103,22 +103,22 @@ enum { /* what files will be displayed */ /* TODO -- We may be able to make DISP_NORMAL 0 to save a bit slot. */ -#define DISP_NORMAL (1U<<14) /* show normal filenames */ +#define DISP_NORMAL (1U<<14) /* show normal filenames */ #define DISP_DIRNAME (1U<<15) /* 2 or more items? label directories */ -#define DISP_HIDDEN (1U<<16) /* show filenames starting with . */ -#define DISP_DOT (1U<<17) /* show . and .. */ -#define DISP_NOLIST (1U<<18) /* show directory as itself, not contents */ +#define DISP_HIDDEN (1U<<16) /* show filenames starting with . */ +#define DISP_DOT (1U<<17) /* show . and .. */ +#define DISP_NOLIST (1U<<18) /* show directory as itself, not contents */ #define DISP_RECURSIVE (1U<<19) /* show directory and everything below it */ -#define DISP_ROWS (1U<<20) /* print across rows */ +#define DISP_ROWS (1U<<20) /* print across rows */ #define DISP_MASK (((DISP_ROWS << 1) - 1) & ~(DISP_NORMAL - 1)) #ifdef CONFIG_FEATURE_LS_SORTFILES /* how will the files be sorted */ -#define SORT_ORDER_FORWARD 0 /* sort in reverse order */ +#define SORT_ORDER_FORWARD 0 /* sort in reverse order */ #define SORT_ORDER_REVERSE (1U<<27) /* sort in reverse order */ -#define SORT_NAME 0 /* sort by file name */ +#define SORT_NAME 0 /* sort by file name */ #define SORT_SIZE (1U<<28) /* sort by file size */ #define SORT_ATIME (2U<<28) /* sort by last access time */ #define SORT_CTIME (3U<<28) /* sort by last change time */ @@ -170,25 +170,25 @@ static int show_color = 0; /* long option entry used only for --color, which has no short option * equivalent. */ -static int got_color_opt; static struct option ls_color_opt[] = { - {"color", optional_argument, &got_color_opt, 1}, + {"color", optional_argument, NULL, 1}, {NULL, 0, NULL, 0} }; #define COLOR(mode) ("\000\043\043\043\042\000\043\043"\ - "\000\000\044\000\043\000\000\040" [TYPEINDEX(mode)]) + "\000\000\044\000\043\000\000\040" [TYPEINDEX(mode)]) #define ATTR(mode) ("\00\00\01\00\01\00\01\00"\ - "\00\00\01\00\01\00\00\01" [TYPEINDEX(mode)]) + "\00\00\01\00\01\00\00\01" [TYPEINDEX(mode)]) #endif /* * a directory entry and its stat info are stored here */ struct dnode { /* the basic node */ - char *name; /* the dir entry name */ + char *name; /* the dir entry name */ char *fullname; /* the dir entry name */ + int allocated; struct stat dstat; /* the file stat info */ #ifdef CONFIG_SELINUX security_context_t sid; @@ -235,8 +235,7 @@ static struct dnode *my_stat(char *fullname, char *name) } #endif rc = stat(fullname, &dstat); - if(rc) - { + if(rc) { bb_perror_msg("%s", fullname); status = EXIT_FAILURE; return 0; @@ -251,8 +250,7 @@ static struct dnode *my_stat(char *fullname, char *name) } #endif rc = lstat(fullname, &dstat); - if(rc) - { + if(rc) { bb_perror_msg("%s", fullname); status = EXIT_FAILURE; return 0; @@ -320,11 +318,10 @@ static int count_dirs(struct dnode **dn, int nfiles, int notsubdirs) dirs = 0; for (i = 0; i < nfiles; i++) { if (S_ISDIR(dn[i]->dstat.st_mode) - && (notsubdirs - || ((dn[i]->name[0] != '.') - || (dn[i]->name[1] + && (notsubdirs || + ((dn[i]->name[0] != '.') || (dn[i]->name[1] && ((dn[i]->name[1] != '.') - || dn[i]->name[2]))))) + || dn[i]->name[2]))))) dirs++; } return (dirs); @@ -352,8 +349,7 @@ static struct dnode **dnalloc(int num) if (num < 1) return (NULL); - p = (struct dnode **) xcalloc((size_t) num, - (size_t) (sizeof(struct dnode *))); + p = (struct dnode **) xcalloc((size_t) num, (size_t) (sizeof(struct dnode *))); return (p); } @@ -367,7 +363,8 @@ static void dfree(struct dnode **dnp) cur = dnp[0]; while (cur != NULL) { - free(cur->fullname); /* free the filename */ + if(cur->allocated) + free(cur->fullname); /* free the filename */ next = cur->next; free(cur); /* free the dnode */ cur = next; @@ -622,6 +619,7 @@ static struct dnode **list_dir(const char *path) cur = my_stat(fullname, strrchr(fullname, '/') + 1); if (!cur) continue; + cur->allocated = 1; cur->next = dn; dn = cur; nfiles++; @@ -756,7 +754,7 @@ static int list_single(struct dnode *dn) safe_strncpy(context, dn->sid, len); freecon(dn->sid); }else { - safe_strncpy(context, "unknown",8); + safe_strncpy(context, "unknown", 8); } printf("%-32s ", context); column += MAX(33, len); @@ -952,6 +950,9 @@ static const unsigned opt_flags[] = { #ifdef CONFIG_SELINUX LIST_MODEBITS|LIST_NLINKS|LIST_CONTEXT|LIST_SIZE|LIST_DATE_TIME, /* K */ #endif +#ifdef CONFIG_FEATURE_AUTOWIDTH + 0, 0, /* T, w - ignored */ +#endif (1U<<31) }; @@ -977,6 +978,9 @@ extern int ls_main(int argc, char **argv) char *tabstops_str = NULL; char *terminal_width_str = NULL; #endif +#ifdef CONFIG_FEATURE_LS_COLOR + char *color_opt; +#endif all_fmt = LIST_SHORT | DISP_NORMAL | STYLE_AUTO #ifdef CONFIG_FEATURE_LS_TIMESTAMPS @@ -1000,7 +1004,11 @@ extern int ls_main(int argc, char **argv) /* process options */ #ifdef CONFIG_FEATURE_AUTOWIDTH - opt = bb_getopt_ulflags(argc, argv, ls_options, &tabstops_str, &terminal_width_str); + opt = bb_getopt_ulflags(argc, argv, ls_options, &tabstops_str, &terminal_width_str +#ifdef CONFIG_FEATURE_LS_COLOR + , &color_opt +#endif + ); if (tabstops_str) { tabstops = atoi(tabstops_str); } @@ -1008,11 +1016,16 @@ extern int ls_main(int argc, char **argv) terminal_width = atoi(terminal_width_str); } #else - opt = bb_getopt_ulflags(argc, argv, ls_options); + opt = bb_getopt_ulflags(argc, argv, ls_options +#ifdef CONFIG_FEATURE_LS_COLOR + , &color_opt +#endif + ); #endif for (i = 0; opt_flags[i] != (1U<<31); i++) { if (opt & (1 << i)) { unsigned int flags = opt_flags[i]; + if (flags & LIST_MASK_TRIGGER) { all_fmt &= ~LIST_MASK; } @@ -1045,51 +1058,28 @@ extern int ls_main(int argc, char **argv) } #ifdef CONFIG_FEATURE_LS_COLOR - if (got_color_opt) { - /* there is no way for bb_getopt_ulflags() to - * return us the argument string for long options - * which don't have a short option equivalent. - * all we can find out is that the option was - * present, and we have to rescan to find the - * argument string. - */ - got_color_opt=0; - optind = 1; - while ((i = getopt_long (argc, argv, ls_options, - ls_color_opt, NULL)) >= 0) { - if (i != 0) continue; - if (got_color_opt) { - if (!optarg || strcmp("always", optarg) == 0) - show_color = 1; - else if (strcmp("never", optarg) == 0) - show_color = 0; - else if (strcmp("auto", optarg) == 0 && - isatty(STDOUT_FILENO)) - show_color = 1; - - /* don't break; want to a) pick up repeated - * --color options, and b) leave optind - * set correctly when we're done. - */ - got_color_opt = 0; - } - } + { + /* find color bit value - last position for short getopt */ + #if CONFIG_FEATURE_LS_COLOR_IS_DEFAULT - } else { - /* if no option set by user, then this config option - * forces "auto", which is what busybox 1.00 and previous - * did. however, provide one more "out" for users that - * don't want color: if LS_COLOR is set, and is null or - * "none" -- then default coloring to "off". - */ char *p; + if ((p = getenv ("LS_COLORS")) != NULL && (*p == '\0' || (strcmp(p, "none") == 0))) { - show_color = 0; + ; } else if (isatty(STDOUT_FILENO)) { show_color = 1; } #endif + + if((opt & (1 << i))) { /* next flag after short options */ + if (color_opt == NULL || strcmp("always", color_opt) == 0) + show_color = 1; + else if (color_opt != NULL && strcmp("never", color_opt) == 0) + show_color = 0; + else if (color_opt != NULL && strcmp("auto", color_opt) == 0 && isatty(STDOUT_FILENO)) + show_color = 1; + } } #endif @@ -1129,14 +1119,12 @@ extern int ls_main(int argc, char **argv) */ ac = argc - optind; /* how many cmd line args are left */ if (ac < 1) { - av = (char **) xcalloc((size_t) 1, (size_t) (sizeof(char *))); - av[0] = bb_xstrdup("."); + static const char * const dotdir[] = { "." }; + + av = (char **) dotdir; ac = 1; } else { - av = (char **) xcalloc((size_t) ac, (size_t) (sizeof(char *))); - for (oi = 0; oi < ac; oi++) { - av[oi] = argv[optind++]; /* copy pointer to real cmd line arg */ - } + av = argv + optind; } /* now, everything is in the av array */ @@ -1146,11 +1134,10 @@ extern int ls_main(int argc, char **argv) /* stuff the command line file names into an dnode array */ dn = NULL; for (oi = 0; oi < ac; oi++) { - char *fullname = bb_xstrdup(av[oi]); - - cur = my_stat(fullname, fullname); + cur = my_stat(av[oi], av[oi]); if (!cur) continue; + cur->allocated = 0; cur->next = dn; dn = cur; nfiles++; |