X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=coreutils%2Fls.c;h=4e21454cef9af6d5e4dd91b38b2843c85d20a968;hb=5cfa5ef6f358bb979b76f8927899b920074f698d;hp=4a4956611d2d03e969e11f8affa74350aa0abbb5;hpb=cad5364599eb5062d59e0c397ed638ddd61a8d5d;p=oweals%2Fbusybox.git diff --git a/coreutils/ls.c b/coreutils/ls.c index 4a4956611..4e21454ce 100644 --- a/coreutils/ls.c +++ b/coreutils/ls.c @@ -61,17 +61,18 @@ enum { #include #include #include +#include /* major() and minor() */ #include "busybox.h" +#ifdef CONFIG_SELINUX +#include +#include +#include +#endif #ifdef CONFIG_FEATURE_LS_TIMESTAMPS #include #endif -#ifndef MAJOR -#define MAJOR(dev) (((dev)>>8)&0xff) -#define MINOR(dev) ((dev)&0xff) -#endif - /* what is the overall style of the listing */ #define STYLE_AUTO (0) #define STYLE_COLUMNS (1U<<21) /* fill columns */ @@ -89,14 +90,15 @@ enum { #define LIST_NLINKS (1U<<3) #define LIST_ID_NAME (1U<<4) #define LIST_ID_NUMERIC (1U<<5) -#define LIST_SIZE (1U<<6) -#define LIST_DEV (1U<<7) -#define LIST_DATE_TIME (1U<<8) -#define LIST_FULLTIME (1U<<9) -#define LIST_FILENAME (1U<<10) -#define LIST_SYMLINK (1U<<11) -#define LIST_FILETYPE (1U<<12) -#define LIST_EXEC (1U<<13) +#define LIST_CONTEXT (1U<<6) +#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) +#define LIST_SYMLINK (1U<<12) +#define LIST_FILETYPE (1U<<13) +#define LIST_EXEC (1U<<14) #define LIST_MASK ((LIST_EXEC << 1) - 1) @@ -179,6 +181,9 @@ struct dnode { /* the basic node */ char *name; /* the dir entry name */ char *fullname; /* the dir entry name */ struct stat dstat; /* the file stat info */ +#ifdef CONFIG_SELINUX + security_id_t sid; +#endif struct dnode *next; /* point at the next node */ }; typedef struct dnode dnode_t; @@ -189,8 +194,12 @@ static int list_single(struct dnode *); static unsigned int all_fmt; +#ifdef CONFIG_SELINUX +static int is_flask_enabled_flag; +#endif + #ifdef CONFIG_FEATURE_AUTOWIDTH -static unsigned short terminal_width = TERMINAL_WIDTH; +static int terminal_width = TERMINAL_WIDTH; static unsigned short tabstops = COLUMN_GAP; #else #define tabstops COLUMN_GAP @@ -203,26 +212,49 @@ static struct dnode *my_stat(char *fullname, char *name) { struct stat dstat; struct dnode *cur; +#ifdef CONFIG_SELINUX + security_id_t sid; +#endif + int rc; #ifdef CONFIG_FEATURE_LS_FOLLOWLINKS if (all_fmt & FOLLOW_LINKS) { - if (stat(fullname, &dstat)) { +#ifdef CONFIG_SELINUX + if(is_flask_enabled_flag) + rc = stat_secure(fullname, &dstat, &sid); + else +#endif + rc = stat(fullname, &dstat); + if(rc) + { bb_perror_msg("%s", fullname); status = EXIT_FAILURE; return 0; } } else #endif - if (lstat(fullname, &dstat)) { - bb_perror_msg("%s", fullname); - status = EXIT_FAILURE; - return 0; + { +#ifdef CONFIG_SELINUX + if(is_flask_enabled_flag) + rc = lstat_secure(fullname, &dstat, &sid); + else +#endif + rc = lstat(fullname, &dstat); + if(rc) + { + bb_perror_msg("%s", fullname); + status = EXIT_FAILURE; + return 0; + } } cur = (struct dnode *) xmalloc(sizeof(struct dnode)); cur->fullname = fullname; cur->name = name; cur->dstat = dstat; +#ifdef CONFIG_SELINUX + cur->sid = sid; +#endif return cur; } @@ -279,7 +311,7 @@ static int count_dirs(struct dnode **dn, int nfiles, int notsubdirs) if (S_ISDIR(dn[i]->dstat.st_mode) && (notsubdirs || ((dn[i]->name[0] != '.') - || (dn[i]->name[1] + || (dn[i]->name[1] && ((dn[i]->name[1] != '.') || dn[i]->name[2]))))) dirs++; @@ -451,6 +483,9 @@ static void showfiles(struct dnode **dn, int nfiles) /* find the longest file name- use that as the column width */ for (i = 0; i < nfiles; i++) { int len = strlen(dn[i]->name) + +#ifdef CONFIG_SELINUX + ((all_fmt & LIST_CONTEXT) ? 33 : 0) + +#endif ((all_fmt & LIST_INO) ? 8 : 0) + ((all_fmt & LIST_BLOCKS) ? 5 : 0); if (column_width < len) @@ -493,7 +528,7 @@ static void showfiles(struct dnode **dn, int nfiles) } /*----------------------------------------------------------------------*/ -static void showdirs(struct dnode **dn, int ndirs) +static void showdirs(struct dnode **dn, int ndirs, int first) { int i, nfiles; struct dnode **subdnp; @@ -508,7 +543,10 @@ static void showdirs(struct dnode **dn, int ndirs) for (i = 0; i < ndirs; i++) { if (all_fmt & (DISP_DIRNAME | DISP_RECURSIVE)) { - printf("\n%s:\n", dn[i]->fullname); + if (!first) + printf("\n"); + first = 0; + printf("%s:\n", dn[i]->fullname); } subdnp = list_dir(dn[i]->fullname); nfiles = countfiles(subdnp); @@ -527,7 +565,7 @@ static void showdirs(struct dnode **dn, int ndirs) #ifdef CONFIG_FEATURE_LS_SORTFILES shellsort(dnd, dndirs); #endif - showdirs(dnd, dndirs); + showdirs(dnd, dndirs, 0); free(dnd); /* free the array of dnode pointers to the dirs */ } } @@ -645,9 +683,9 @@ static int list_single(struct dnode *dn) break; case LIST_ID_NAME: #ifdef CONFIG_FEATURE_LS_USERNAME - my_getpwuid(scratch, dn->dstat.st_uid); + my_getpwuid(scratch, dn->dstat.st_uid, sizeof(scratch)); printf("%-8.8s ", scratch); - my_getgrgid(scratch, dn->dstat.st_gid); + my_getgrgid(scratch, dn->dstat.st_gid, sizeof(scratch)); printf("%-8.8s", scratch); column += 17; break; @@ -658,8 +696,8 @@ static int list_single(struct dnode *dn) case LIST_SIZE: case LIST_DEV: if (S_ISBLK(dn->dstat.st_mode) || S_ISCHR(dn->dstat.st_mode)) { - column += printf("%4d, %3d ", (int) MAJOR(dn->dstat.st_rdev), - (int) MINOR(dn->dstat.st_rdev)); + column += printf("%4d, %3d ", (int) major(dn->dstat.st_rdev), + (int) minor(dn->dstat.st_rdev)); } else { #ifdef CONFIG_FEATURE_HUMAN_READABLE if (all_fmt & LS_DISP_HR) { @@ -678,21 +716,36 @@ static int list_single(struct dnode *dn) break; #ifdef CONFIG_FEATURE_LS_TIMESTAMPS case LIST_FULLTIME: + printf("%24.24s ", filetime); + column += 25; + break; case LIST_DATE_TIME: - if (all_fmt & LIST_FULLTIME) { - printf("%24.24s ", filetime); - column += 25; - break; + if ((all_fmt & LIST_FULLTIME) == 0) { + age = time(NULL) - ttime; + printf("%6.6s ", filetime + 4); + if (age < 3600L * 24 * 365 / 2 && age > -15 * 60) { + /* hh:mm if less than 6 months old */ + printf("%5.5s ", filetime + 11); + } else { + printf(" %4.4s ", filetime + 20); + } + column += 13; } - age = time(NULL) - ttime; - printf("%6.6s ", filetime + 4); - if (age < 3600L * 24 * 365 / 2 && age > -15 * 60) { - /* hh:mm if less than 6 months old */ - printf("%5.5s ", filetime + 11); - } else { - printf(" %4.4s ", filetime + 20); + break; +#endif +#ifdef CONFIG_SELINUX + case LIST_CONTEXT: + { + char context[64]; + int len = sizeof(context); + if(security_sid_to_context(dn->sid, context, &len)) + { + strcpy(context, "unknown"); + len = 7; + } + printf("%-32s ", context); + column += MAX(33, len); } - column += 13; break; #endif case LIST_FILENAME: @@ -754,87 +807,137 @@ static int list_single(struct dnode *dn) /*----------------------------------------------------------------------*/ -static const char ls_opts[] = "1AaCdgilnsx" -#ifdef CONFIG_FEATURE_LS_FILETYPES - "Fp" -#endif -#ifdef CONFIG_FEATURE_LS_RECURSIVE - "R" +/* "[-]Cadil1", POSIX mandated options, busybox always supports */ +/* "[-]gnsx", POSIX non-mandated options, busybox always supports */ +/* "[-]Ak" GNU options, busybox always supports */ +/* "[-]FLRctur", POSIX mandated options, busybox optionally supports */ +/* "[-]p", POSIX non-mandated options, busybox optionally supports */ +/* "[-]SXvThw", GNU options, busybox optionally supports */ +/* "[-]K", SELinux mandated options, busybox optionally supports */ +/* "[-]e", I think we made this one up */ + +#ifdef CONFIG_FEATURE_LS_TIMESTAMPS +# define LS_STR_TIMESTAMPS "cetu" +#else +# define LS_STR_TIMESTAMPS "" #endif + #ifdef CONFIG_FEATURE_LS_SORTFILES - "rSvX" +# define LS_STR_SORTFILES "SXrv" +#else +# define LS_STR_SORTFILES "" #endif -#ifdef CONFIG_FEATURE_LS_TIMESTAMPS - "ecut" + +#ifdef CONFIG_FEATURE_LS_FILETYPES +# define LS_STR_FILETYPES "Fp" +#else +# define LS_STR_FILETYPES "" #endif + #ifdef CONFIG_FEATURE_LS_FOLLOWLINKS - "L" +# define LS_STR_FOLLOW_LINKS "L" +#else +# define LS_STR_FOLLOW_LINKS "" +#endif + +#ifdef CONFIG_FEATURE_LS_RECURSIVE +# define LS_STR_RECURSIVE "R" +#else +# define LS_STR_RECURSIVE "" #endif + #ifdef CONFIG_FEATURE_HUMAN_READABLE - "h" +# define LS_STR_HUMAN_READABLE "h" +#else +# define LS_STR_HUMAN_READABLE "" +#endif + +#ifdef CONFIG_SELINUX +# define LS_STR_SELINUX "K" +#else +# define LS_STR_SELINUX "" #endif - "k" + #ifdef CONFIG_FEATURE_AUTOWIDTH - "T:w:" +# define LS_STR_AUTOWIDTH "T:w:" +#else +# define LS_STR_AUTOWIDTH "" #endif - ; -#define LIST_MASK_TRIGGER LIST_SHORT -#define STYLE_MASK_TRIGGER STYLE_MASK -#define SORT_MASK_TRIGGER SORT_MASK -#define DISP_MASK_TRIGGER DISP_ROWS -#define TIME_MASK_TRIGGER TIME_MASK +static const char ls_options[]="Cadil1gnsxAk" \ + LS_STR_TIMESTAMPS \ + LS_STR_SORTFILES \ + LS_STR_FILETYPES \ + LS_STR_FOLLOW_LINKS \ + LS_STR_RECURSIVE \ + LS_STR_HUMAN_READABLE \ + LS_STR_SELINUX \ + LS_STR_AUTOWIDTH; + +#define LIST_MASK_TRIGGER 0 +#define STYLE_MASK_TRIGGER STYLE_MASK +#define SORT_MASK_TRIGGER SORT_MASK +#define DISP_MASK_TRIGGER DISP_ROWS +#define TIME_MASK_TRIGGER TIME_MASK static const unsigned opt_flags[] = { - LIST_SHORT | STYLE_SINGLE, /* 1 */ - DISP_HIDDEN, /* A */ - DISP_HIDDEN | DISP_DOT, /* a */ LIST_SHORT | STYLE_COLUMNS, /* C */ - DISP_NOLIST, /* d */ - 0, /* g - ingored */ - LIST_INO, /* i */ - LIST_LONG | STYLE_LONG, /* l - remember LS_DISP_HR in mask! */ - LIST_ID_NUMERIC, /* n */ - LIST_BLOCKS, /* s */ - DISP_ROWS, /* x */ -#ifdef CONFIG_FEATURE_LS_FILETYPES - LIST_FILETYPE | LIST_EXEC, /* F */ - LIST_FILETYPE, /* p */ -#endif -#ifdef CONFIG_FEATURE_LS_RECURSIVE - DISP_RECURSIVE, /* R */ -#endif -#ifdef CONFIG_FEATURE_LS_SORTFILES - SORT_ORDER_REVERSE, /* r */ - SORT_SIZE, /* S */ - SORT_VERSION, /* v */ - SORT_EXT, /* v */ + DISP_HIDDEN | DISP_DOT, /* a */ + DISP_NOLIST, /* d */ + LIST_INO, /* i */ + LIST_LONG | STYLE_LONG, /* l - remember LS_DISP_HR in mask! */ + LIST_SHORT | STYLE_SINGLE, /* 1 */ + 0, /* g - ingored */ + LIST_ID_NUMERIC, /* n */ + LIST_BLOCKS, /* s */ + DISP_ROWS, /* x */ + DISP_HIDDEN, /* A */ +#ifdef CONFIG_SELINUX + LIST_CONTEXT, /* k */ +#else + 0, /* k - ingored */ #endif #ifdef CONFIG_FEATURE_LS_TIMESTAMPS - LIST_FULLTIME, /* e */ -#ifdef CONFIG_FEATURE_LS_SORTFILES +# ifdef CONFIG_FEATURE_LS_SORTFILES TIME_CHANGE | SORT_CTIME, /* c */ -#else - TIME_CHANGE, /* c */ -#endif -#ifdef CONFIG_FEATURE_LS_SORTFILES +# else + TIME_CHANGE, /* c */ +# endif + LIST_FULLTIME, /* e */ +# ifdef CONFIG_FEATURE_LS_SORTFILES + SORT_MTIME, /* t */ +# else + 0, /* t - ignored -- is this correct? */ +# endif +# ifdef CONFIG_FEATURE_LS_SORTFILES TIME_ACCESS | SORT_ATIME, /* u */ -#else - TIME_ACCESS, /* u */ +# else + TIME_ACCESS, /* u */ +# endif #endif #ifdef CONFIG_FEATURE_LS_SORTFILES - SORT_MTIME, /* t */ -#else - 0, /* t - ignored -- is this correct? */ + SORT_SIZE, /* S */ + SORT_EXT, /* X */ + SORT_ORDER_REVERSE, /* r */ + SORT_VERSION, /* v */ #endif +#ifdef CONFIG_FEATURE_LS_FILETYPES + LIST_FILETYPE | LIST_EXEC, /* F */ + LIST_FILETYPE, /* p */ #endif #ifdef CONFIG_FEATURE_LS_FOLLOWLINKS - FOLLOW_LINKS, /* L */ + FOLLOW_LINKS, /* L */ +#endif +#ifdef CONFIG_FEATURE_LS_RECURSIVE + DISP_RECURSIVE, /* R */ #endif #ifdef CONFIG_FEATURE_HUMAN_READABLE -LS_DISP_HR, /* h */ + LS_DISP_HR, /* h */ +#endif +#ifdef CONFIG_SELINUX + LIST_MODEBITS|LIST_NLINKS|LIST_CONTEXT|LIST_SIZE|LIST_DATE_TIME, /* K */ #endif - 0, /* k - ingored */ + (1U<<31) }; @@ -842,16 +945,26 @@ LS_DISP_HR, /* h */ extern int ls_main(int argc, char **argv) { - struct dnode **dnf, **dnd; - int dnfiles, dndirs; - struct dnode *dn, *cur, **dnp; - int i, nfiles; - int opt; - int oi, ac; + struct dnode **dnd; + struct dnode **dnf; + struct dnode **dnp; + struct dnode *dn; + struct dnode *cur; + long opt; + int nfiles = 0; + int dnfiles; + int dndirs; + int oi; + int ac; + int i; char **av; - #ifdef CONFIG_FEATURE_AUTOWIDTH - struct winsize win = { 0, 0, 0, 0 }; + char *tabstops_str = NULL; + char *terminal_width_str = NULL; +#endif + +#ifdef CONFIG_SELINUX + is_flask_enabled_flag = is_flask_enabled(); #endif all_fmt = LIST_SHORT | DISP_NORMAL | STYLE_AUTO @@ -862,55 +975,56 @@ extern int ls_main(int argc, char **argv) | SORT_NAME | SORT_ORDER_FORWARD #endif ; + #ifdef CONFIG_FEATURE_AUTOWIDTH - ioctl(fileno(stdout), TIOCGWINSZ, &win); - if (win.ws_col > 0) - terminal_width = win.ws_col - 1; + /* Obtain the terminal width. */ + get_terminal_width_height(STDOUT_FILENO, &terminal_width, NULL); + /* Go one less... */ + terminal_width--; #endif - nfiles = 0; #ifdef CONFIG_FEATURE_LS_COLOR - if (isatty(fileno(stdout))) + if (isatty(STDOUT_FILENO)) show_color = 1; #endif /* process options */ - while ((opt = getopt(argc, argv, ls_opts)) > 0) { #ifdef CONFIG_FEATURE_AUTOWIDTH - if (opt == 'T') { - tabstops = atoi(optarg); - continue; - } - if (opt == 'w') { - terminal_width = atoi(optarg); - continue; - } - if (opt == ':') { - goto print_usage_message; - } + opt = bb_getopt_ulflags(argc, argv, ls_options, &tabstops_str, &terminal_width_str); + if (tabstops_str) { + tabstops = atoi(tabstops_str); + } + if (terminal_width_str) { + terminal_width = atoi(terminal_width_str); + } +#else + opt = bb_getopt_ulflags(argc, argv, ls_options); #endif - { - unsigned int flags; - const char *p = strchr(ls_opts, opt); - if (!p) { /* shouldn't be necessary */ - goto print_usage_message; - } - flags = opt_flags[(int)(p - ls_opts)]; + 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; } if (flags & STYLE_MASK_TRIGGER) { all_fmt &= ~STYLE_MASK; } +#ifdef CONFIG_FEATURE_LS_SORTFILES if (flags & SORT_MASK_TRIGGER) { all_fmt &= ~SORT_MASK; } +#endif if (flags & DISP_MASK_TRIGGER) { all_fmt &= ~DISP_MASK; } +#ifdef CONFIG_FEATURE_LS_TIMESTAMPS if (flags & TIME_MASK_TRIGGER) { all_fmt &= ~TIME_MASK; } +#endif + if (flags & LIST_CONTEXT) { + all_fmt |= STYLE_SINGLE; + } #ifdef CONFIG_FEATURE_HUMAN_READABLE if (opt == 'l') { all_fmt &= ~LS_DISP_HR; @@ -920,7 +1034,6 @@ extern int ls_main(int argc, char **argv) } } - /* sort out which command line options take precedence */ #ifdef CONFIG_FEATURE_LS_RECURSIVE if (all_fmt & DISP_NOLIST) @@ -938,14 +1051,14 @@ extern int ls_main(int argc, char **argv) if ((all_fmt & STYLE_MASK) == STYLE_LONG && (all_fmt & LIST_ID_NUMERIC)) all_fmt &= ~LIST_ID_NAME; /* don't list names if numeric uid */ #endif - + /* choose a display format */ if ((all_fmt & STYLE_MASK) == STYLE_AUTO) #if STYLE_AUTO != 0 all_fmt = (all_fmt & ~STYLE_MASK) - | (isatty(fileno(stdout)) ? STYLE_COLUMNS : STYLE_SINGLE); + | (isatty(STDOUT_FILENO) ? STYLE_COLUMNS : STYLE_SINGLE); #else - all_fmt |= (isatty(fileno(stdout)) ? STYLE_COLUMNS : STYLE_SINGLE); + all_fmt |= (isatty(STDOUT_FILENO) ? STYLE_COLUMNS : STYLE_SINGLE); #endif /* @@ -993,7 +1106,6 @@ extern int ls_main(int argc, char **argv) cur = cur->next; } - if (all_fmt & DISP_NOLIST) { #ifdef CONFIG_FEATURE_LS_SORTFILES shellsort(dnp, nfiles); @@ -1015,11 +1127,8 @@ extern int ls_main(int argc, char **argv) #ifdef CONFIG_FEATURE_LS_SORTFILES shellsort(dnd, dndirs); #endif - showdirs(dnd, dndirs); + showdirs(dnd, dndirs, dnfiles == 0); } } return (status); - - print_usage_message: - bb_show_usage(); }