'simple' error message functions by Loic Grenie <loic.grenie@gmail.com>.
[oweals/busybox.git] / coreutils / ls.c
index 34fae502691359d9772812e37bd8cfe8c2ba07a2..92a9a289dc9dbae829b121e0143349938b1ed99e 100644 (file)
  * 1. requires lstat (BSD) - how do you do it without?
  */
 
-#include "busybox.h"
 #include <getopt.h>
+#include "libbb.h"
+
+/* This is a NOEXEC applet. Be very careful! */
+
 
 enum {
 
@@ -114,13 +117,12 @@ SPLIT_SUBDIR    = 2,
 
 /* colored LS support by JaWi, janwillem.janssen@lxtreme.nl */
 #if ENABLE_FEATURE_LS_COLOR
-static int show_color;
+static smallint show_color;
 /* long option entry used only for --color, which has no short option
  * equivalent */
-static const struct option ls_color_opt[] = {
-       { "color", optional_argument, NULL, 1 },
-       { NULL, 0, NULL, 0 }
-};
+static const char ls_color_opt[] ALIGN1 =
+       "color\0" Optional_argument "\xff" /* no short equivalent */
+       ;
 #else
 enum { show_color = 0 };
 #endif
@@ -129,8 +131,8 @@ enum { show_color = 0 };
  * a directory entry and its stat info are stored here
  */
 struct dnode {                  /* the basic node */
-       char *name;             /* the dir entry name */
-       char *fullname;         /* the dir entry name */
+       const char *name;             /* the dir entry name */
+       const char *fullname;         /* the dir entry name */
        int   allocated;
        struct stat dstat;      /* the file stat info */
        USE_SELINUX(security_context_t sid;)
@@ -156,31 +158,31 @@ enum {
 
 static int status = EXIT_SUCCESS;
 
-static struct dnode *my_stat(char *fullname, char *name)
+static struct dnode *my_stat(const char *fullname, const char *name, int force_follow)
 {
        struct stat dstat;
        struct dnode *cur;
        USE_SELINUX(security_context_t sid = NULL;)
 
-       if (all_fmt & FOLLOW_LINKS) {
+       if ((all_fmt & FOLLOW_LINKS) || force_follow) {
 #if ENABLE_SELINUX
                if (is_selinux_enabled())  {
                         getfilecon(fullname, &sid);
                }
 #endif
                if (stat(fullname, &dstat)) {
-                       bb_perror_msg("%s", fullname);
+                       bb_simple_perror_msg(fullname);
                        status = EXIT_FAILURE;
                        return 0;
                }
        } else {
 #if ENABLE_SELINUX
                if (is_selinux_enabled()) {
-                       lgetfilecon(fullname,&sid);
+                       lgetfilecon(fullname, &sid);
                }
 #endif
                if (lstat(fullname, &dstat)) {
-                       bb_perror_msg("%s", fullname);
+                       bb_simple_perror_msg(fullname);
                        status = EXIT_FAILURE;
                        return 0;
                }
@@ -238,7 +240,7 @@ static int count_dirs(struct dnode **dn, int nfiles, int notsubdirs)
                return 0;
        dirs = 0;
        for (i = 0; i < nfiles; i++) {
-               char *name;
+               const char *name;
                if (!S_ISDIR(dn[i]->dstat.st_mode))
                        continue;
                name = dn[i]->name;
@@ -285,7 +287,7 @@ static void dfree(struct dnode **dnp, int nfiles)
        for (i = 0; i < nfiles; i++) {
                struct dnode *cur = dnp[i];
                if (cur->allocated)
-                       free(cur->fullname);    /* free the filename */
+                       free((char*)cur->fullname);     /* free the filename */
                free(cur);              /* free the dnode */
        }
        free(dnp);                      /* free the array holding the dnode pointers */
@@ -317,7 +319,7 @@ static struct dnode **splitdnarray(struct dnode **dn, int nfiles, int which)
        /* copy the entrys into the file or dir array */
        for (d = i = 0; i < nfiles; i++) {
                if (S_ISDIR(dn[i]->dstat.st_mode)) {
-                       char *name;
+                       const char *name;
                        if (!(which & (SPLIT_DIR|SPLIT_SUBDIR)))
                                continue;
                        name = dn[i]->name;
@@ -449,7 +451,7 @@ static void showdirs(struct dnode **dn, int ndirs, int first)
        for (i = 0; i < ndirs; i++) {
                if (all_fmt & (DISP_DIRNAME | DISP_RECURSIVE)) {
                        if (!first)
-                               puts("");
+                               bb_putchar('\n');
                        first = 0;
                        printf("%s:\n", dn[i]->fullname);
                }
@@ -501,16 +503,16 @@ static struct dnode **list_dir(const char *path)
 
                /* are we going to list the file- it may be . or .. or a hidden file */
                if (entry->d_name[0] == '.') {
-                       if ((entry->d_name[1] == 0 || (
-                               entry->d_name[1] == '.'
-                               && entry->d_name[2] == 0))
-                                       && !(all_fmt & DISP_DOT))
+                       if ((!entry->d_name[1] || (entry->d_name[1] == '.' && !entry->d_name[2]))
+                        && !(all_fmt & DISP_DOT)
+                       ) {
                                continue;
+                       }
                        if (!(all_fmt & DISP_HIDDEN))
                                continue;
                }
                fullname = concat_path_file(path, entry->d_name);
-               cur = my_stat(fullname, strrchr(fullname, '/') + 1);
+               cur = my_stat(fullname, bb_basename(fullname), 0);
                if (!cur) {
                        free(fullname);
                        continue;
@@ -708,7 +710,8 @@ static int list_single(struct dnode *dn)
 /* "[-]SXvThw", GNU options, busybox optionally supports */
 /* "[-]K", SELinux mandated options, busybox optionally supports */
 /* "[-]e", I think we made this one up */
-static const char ls_options[] = "Cadil1gnsxAk"
+static const char ls_options[] ALIGN1 =
+       "Cadil1gnsxAk"
        USE_FEATURE_LS_TIMESTAMPS("cetu")
        USE_FEATURE_LS_SORTFILES("SXrv")
        USE_FEATURE_LS_FILETYPES("Fp")
@@ -716,7 +719,8 @@ static const char ls_options[] = "Cadil1gnsxAk"
        USE_FEATURE_LS_RECURSIVE("R")
        USE_FEATURE_HUMAN_READABLE("h")
        USE_SELINUX("K")
-       USE_FEATURE_AUTOWIDTH("T:w:");
+       USE_FEATURE_AUTOWIDTH("T:w:")
+       USE_SELINUX("Z");
 
 enum {
        LIST_MASK_TRIGGER       = 0,
@@ -768,11 +772,17 @@ static const unsigned opt_flags[] = {
 #endif
 #if ENABLE_FEATURE_AUTOWIDTH
        0, 0,                       /* T, w - ignored */
+#endif
+#if ENABLE_SELINUX
+       LIST_MODEBITS|LIST_ID_NAME|LIST_CONTEXT, /* Z */
 #endif
        (1U<<31)
 };
 
 
+/* THIS IS A "SAFE" APPLET, main() MAY BE CALLED INTERNALLY FROM SHELL */
+/* BE CAREFUL! */
+
 int ls_main(int argc, char **argv);
 int ls_main(int argc, char **argv)
 {
@@ -793,8 +803,6 @@ int ls_main(int argc, char **argv)
        USE_FEATURE_AUTOWIDTH(char *terminal_width_str = NULL;)
        USE_FEATURE_LS_COLOR(char *color_opt;)
 
-       setvbuf(stdout, bb_common_bufsiz1, _IOFBF, BUFSIZ);
-
 #if ENABLE_FEATURE_LS_TIMESTAMPS
        time(&current_time_t);
 #endif
@@ -804,7 +812,7 @@ int ls_main(int argc, char **argv)
 
 #if ENABLE_FEATURE_AUTOWIDTH
        /* Obtain the terminal width */
-       get_terminal_width_height(STDOUT_FILENO, &terminal_width, NULL);
+       get_terminal_width_height(STDIN_FILENO, &terminal_width, NULL);
        /* Go one less... */
        terminal_width--;
 #endif
@@ -812,14 +820,14 @@ int ls_main(int argc, char **argv)
        /* process options */
        USE_FEATURE_LS_COLOR(applet_long_options = ls_color_opt;)
 #if ENABLE_FEATURE_AUTOWIDTH
-       opt = getopt32(argc, argv, ls_options, &tabstops_str, &terminal_width_str
+       opt = getopt32(argv, ls_options, &tabstops_str, &terminal_width_str
                                USE_FEATURE_LS_COLOR(, &color_opt));
        if (tabstops_str)
                tabstops = xatou(tabstops_str);
        if (terminal_width_str)
                terminal_width = xatou(terminal_width_str);
 #else
-       opt = getopt32(argc, argv, ls_options  USE_FEATURE_LS_COLOR(, &color_opt));
+       opt = getopt32(argv, ls_options USE_FEATURE_LS_COLOR(, &color_opt));
 #endif
        for (i = 0; opt_flags[i] != (1U<<31); i++) {
                if (opt & (1 << i)) {
@@ -837,8 +845,9 @@ int ls_main(int argc, char **argv)
                                all_fmt &= ~TIME_MASK;
                        if (flags & LIST_CONTEXT)
                                all_fmt |= STYLE_SINGLE;
-                       if (LS_DISP_HR && opt == 'l')
-                               all_fmt &= ~LS_DISP_HR;
+                       /* huh?? opt cannot be 'l' */
+                       //if (LS_DISP_HR && opt == 'l')
+                       //      all_fmt &= ~LS_DISP_HR;
                        all_fmt |= flags;
                }
        }
@@ -904,7 +913,8 @@ int ls_main(int argc, char **argv)
        /* stuff the command line file names into a dnode array */
        dn = NULL;
        for (oi = 0; oi < ac; oi++) {
-               cur = my_stat(av[oi], av[oi]);
+               /* ls w/o -l follows links on command line */
+               cur = my_stat(av[oi], av[oi], !(all_fmt & STYLE_LONG));
                if (!cur)
                        continue;
                cur->allocated = 0;