inetd: fix order of array index check and array access
[oweals/busybox.git] / coreutils / ls.c
index e7b2e39e1f9cf10af71a5784b8aa9943d6f06456..14c8beaffa6f043069170006b431e42c7d1c8d27 100644 (file)
@@ -42,7 +42,6 @@
 //usage:       IF_FEATURE_AUTOWIDTH(" [-w WIDTH]") " [FILE]..."
 //usage:#define ls_full_usage "\n\n"
 //usage:       "List directory contents\n"
-//usage:     "\nOptions:"
 //usage:     "\n       -1      One column output"
 //usage:     "\n       -a      Include entries which start with ."
 //usage:     "\n       -A      Like -a, but exclude . and .."
@@ -183,11 +182,10 @@ LIST_LONG       = LIST_MODEBITS | LIST_NLINKS | LIST_ID_NAME | LIST_SIZE | \
 /* -Q       GNU option, busybox always supports */
 /* -k       SELinux option, busybox always supports (ignores if !SELinux) */
 /*          Std has -k which means "show sizes in kbytes" */
-/* -FLHRctur Std options, busybox optionally supports */
-/* -p       Std option, busybox optionally supports */
-/*          Not fully compatible - we show not only '/' but other chars too */
+/* -LHRctur Std options, busybox optionally supports */
+/* -Fp      Std options, busybox optionally supports */
 /* -SXvhTw  GNU options, busybox optionally supports */
-/*          -T TABWIDTH is ignored (we don't use tabs on output) */
+/* -T WIDTH Ignored (we don't use tabs on output) */
 /* -KZ      SELinux mandated options, busybox optionally supports */
 /*          (coreutils 8.4 has no -K, remove it?) */
 /* -e       I think we made this one up (looks similar to GNU --full-time) */
@@ -262,7 +260,7 @@ enum {
 
 /* TODO: simple toggles may be stored as OPT_xxx bits instead */
 static const uint32_t opt_flags[] = {
-       STYLE_COLUMNAR,              /* C */
+       STYLE_COLUMNAR,              /* C */
        DISP_HIDDEN | DISP_DOT,      /* a */
        DISP_NOLIST,                 /* d */
        LIST_INO,                    /* i */
@@ -568,12 +566,12 @@ static NOINLINE unsigned display_single(const struct dnode *dn)
 #if ENABLE_FEATURE_LS_TIMESTAMPS
        if (G.all_fmt & (LIST_FULLTIME|LIST_DATE_TIME)) {
                char *filetime;
-               time_t ttime = dn->dn_mtime;
+               const time_t *ttime = &dn->dn_mtime;
                if (G.all_fmt & TIME_ACCESS)
-                       ttime = dn->dn_atime;
+                       ttime = &dn->dn_atime;
                if (G.all_fmt & TIME_CHANGE)
-                       ttime = dn->dn_ctime;
-               filetime = ctime(&ttime);
+                       ttime = &dn->dn_ctime;
+               filetime = ctime(ttime);
                /* filetime's format: "Wed Jun 30 21:49:08 1993\n" */
                if (G.all_fmt & LIST_FULLTIME) { /* -e */
                        /* Note: coreutils 8.4 ls --full-time prints:
@@ -582,13 +580,16 @@ static NOINLINE unsigned display_single(const struct dnode *dn)
                        column += printf("%.24s ", filetime);
                } else { /* LIST_DATE_TIME */
                        /* G.current_time_t ~== time(NULL) */
-                       time_t age = G.current_time_t - ttime;
-                       printf("%.6s ", filetime + 4); /* "Jun 30" */
+                       time_t age = G.current_time_t - *ttime;
                        if (age < 3600L * 24 * 365 / 2 && age > -15 * 60) {
-                               /* hh:mm if less than 6 months old */
-                               printf("%.5s ", filetime + 11);
-                       } else { /* year. buggy if year > 9999 ;) */
-                               printf(" %.4s ", filetime + 20);
+                               /* less than 6 months old */
+                               /* "mmm dd hh:mm " */
+                               printf("%.12s ", filetime + 4);
+                       } else {
+                               /* "mmm dd  yyyy " */
+                               /* "mmm dd yyyyy " after year 9999 :) */
+                               strchr(filetime + 20, '\n')[0] = ' ';
+                               printf("%.7s%6s", filetime + 4, filetime + 20);
                        }
                        column += 13;
                }
@@ -722,7 +723,7 @@ static struct dnode *my_stat(const char *fullname, const char *name, int force_f
        if ((option_mask32 & OPT_L) || force_follow) {
 #if ENABLE_SELINUX
                if (is_selinux_enabled())  {
-                        getfilecon(fullname, &cur->sid);
+                       getfilecon(fullname, &cur->sid);
                }
 #endif
                if (stat(fullname, &statbuf)) {
@@ -875,19 +876,29 @@ static int sortcmp(const void *a, const void *b)
        // instead of branch forest
        if (sort_opts == SORT_SIZE) {
                dif = (d2->dn_size - d1->dn_size);
-       } else if (sort_opts == SORT_ATIME) {
+       } else
+       if (sort_opts == SORT_ATIME) {
                dif = (d2->dn_atime - d1->dn_atime);
-       } else if (sort_opts == SORT_CTIME) {
+       } else
+       if (sort_opts == SORT_CTIME) {
                dif = (d2->dn_ctime - d1->dn_ctime);
-       } else if (sort_opts == SORT_MTIME) {
+       } else
+       if (sort_opts == SORT_MTIME) {
                dif = (d2->dn_mtime - d1->dn_mtime);
-       } else if (sort_opts == SORT_DIR) {
+       } else
+       if (sort_opts == SORT_DIR) {
                dif = S_ISDIR(d2->dn_mode) - S_ISDIR(d1->dn_mode);
-               /* } else if (sort_opts == SORT_VERSION) { */
-               /* } else if (sort_opts == SORT_EXT) { */
+       } else
+#if defined(HAVE_STRVERSCMP) && HAVE_STRVERSCMP == 1
+       if (sort_opts == SORT_VERSION) {
+               dif = strverscmp(d1->name, d2->name);
+       } else
+#endif
+       if (sort_opts == SORT_EXT) {
+               dif = strcmp(strchrnul(d1->name, '.'), strchrnul(d2->name, '.'));
        }
        if (dif == 0) {
-               /* sort by name, or tie_breaker for other sorts */
+               /* sort by name, use as tie breaker for other sorts */
                if (ENABLE_LOCALE_SUPPORT)
                        dif = strcoll(d1->name, d2->name);
                else
@@ -1024,7 +1035,7 @@ static void scan_and_display_dirs_recur(struct dnode **dn, int first)
                }
                subdnp = scan_one_dir((*dn)->fullname, &nfiles);
 #if ENABLE_DESKTOP
-               if ((G.all_fmt & STYLE_MASK) == STYLE_LONG)
+               if ((G.all_fmt & STYLE_MASK) == STYLE_LONG || (G.all_fmt & LIST_BLOCKS))
                        printf("total %"OFF_FMT"u\n", calculate_blocks(subdnp));
 #endif
                if (nfiles > 0) {
@@ -1103,7 +1114,7 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
        IF_FEATURE_LS_COLOR(applet_long_options = ls_longopts;)
        opt_complementary =
                /* -e implies -l */
-               "el"
+               IF_FEATURE_LS_TIMESTAMPS("el")
                /* http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ls.html:
                 * in some pairs of opts, only last one takes effect:
                 */
@@ -1113,7 +1124,7 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
                ":C-xl:x-Cl:l-xC" /* bycols/bylines/long */
                ":C-1:1-C" /* bycols/oneline */
                ":x-1:1-x" /* bylines/oneline (not in SuS, but in GNU coreutils 8.4) */
-               ":c-u:u-c" /* mtime/atime */
+               IF_FEATURE_LS_TIMESTAMPS(":c-u:u-c") /* mtime/atime */
                /* -w NUM: */
                IF_FEATURE_AUTOWIDTH(":w+");
        opt = getopt32(argv, ls_options