Patch from Matt Kraai to enable proxy support.
[oweals/busybox.git] / ls.c
diff --git a/ls.c b/ls.c
index 28b2f954d9d0e685a176a91b9a15044dc7606710..94c73b377433ab8c1a8984069f7f75028f09b1dd 100644 (file)
--- a/ls.c
+++ b/ls.c
 
 #define SPLIT_DIR              0
 #define SPLIT_FILE             1
+#define SPLIT_SUBDIR   2
 
 #define TYPEINDEX(mode) (((mode) >> 12) & 0x0f)
 #define TYPECHAR(mode)  ("0pcCd?bB-?l?s???" [TYPEINDEX(mode)])
@@ -175,6 +176,29 @@ static unsigned short tabstops = 8;
 
 static int status = EXIT_SUCCESS;
 
+static int my_stat(struct dnode *cur)
+{
+#ifdef BB_FEATURE_LS_FOLLOWLINKS
+       if (follow_links == TRUE) {
+               if (stat(cur->fullname, &cur->dstat)) {
+                       error_msg("%s: %s\n", cur->fullname, strerror(errno));
+                       status = EXIT_FAILURE;
+                       free(cur->fullname);
+                       free(cur);
+                       return -1;
+               }
+       } else
+#endif
+       if (lstat(cur->fullname, &cur->dstat)) {
+               error_msg("%s: %s\n", cur->fullname, strerror(errno));
+               status = EXIT_FAILURE;
+               free(cur->fullname);
+               free(cur);
+               return -1;
+       }
+       return 0;
+}
+
 static void newline(void)
 {
     if (column > 0) {
@@ -213,11 +237,16 @@ static void nexttabstop( void )
 }
 
 /*----------------------------------------------------------------------*/
+static int is_subdir(struct dnode *dn)
+{
+       return (S_ISDIR(dn->dstat.st_mode) && strcmp(dn->name, ".") != 0 &&
+                       strcmp(dn->name, "..") != 0);
+}
+
 int countdirs(struct dnode **dn, int nfiles)
 {
        int i, dirs;
 
-       /* count how many dirs and regular files there are */
        if (dn==NULL || nfiles < 1) return(0);
        dirs= 0;
        for (i=0; i<nfiles; i++) {
@@ -226,6 +255,18 @@ int countdirs(struct dnode **dn, int nfiles)
        return(dirs);
 }
 
+int countsubdirs(struct dnode **dn, int nfiles)
+{
+       int i, subdirs;
+
+       if (dn == NULL || nfiles < 1) return 0;
+       subdirs = 0;
+       for (i = 0; i < nfiles; i++)
+               if (is_subdir(dn[i]))
+                       subdirs++;
+       return subdirs;
+}
+
 int countfiles(struct dnode **dnp)
 {
        int nfiles;
@@ -273,9 +314,13 @@ struct dnode **splitdnarray(struct dnode **dn, int nfiles, int which)
        if (dn==NULL || nfiles < 1) return(NULL);
 
        /* count how many dirs and regular files there are */
-       dncnt= countdirs(dn, nfiles); /* assume we are looking for dirs */
-       if (which != SPLIT_DIR)
-               dncnt= nfiles - dncnt;  /* looking for files */
+       if (which == SPLIT_SUBDIR)
+               dncnt = countsubdirs(dn, nfiles);
+       else {
+               dncnt= countdirs(dn, nfiles); /* assume we are looking for dirs */
+               if (which == SPLIT_FILE)
+                       dncnt= nfiles - dncnt;  /* looking for files */
+       }
 
        /* allocate a file array and a dir array */
        dnp= dnalloc(dncnt);
@@ -286,6 +331,10 @@ struct dnode **splitdnarray(struct dnode **dn, int nfiles, int which)
                        if (S_ISDIR(dn[i]->dstat.st_mode)) {
                                dnp[d++]= dn[i];
                        }  /* else skip the file */
+               } else if (which == SPLIT_SUBDIR) {
+                       if (is_subdir(dn[i])) {
+                               dnp[d++]= dn[i];
+                       }  /* else skip the file or dir */
                } else {
                        if (!(S_ISDIR(dn[i]->dstat.st_mode))) {
                                dnp[d++]= dn[i];
@@ -410,7 +459,7 @@ void showdirs(struct dnode **dn, int ndirs)
 {
        int i, nfiles;
        struct dnode **subdnp;
-#ifdef BB_FEATURE_LS_SORTFILES
+#ifdef BB_FEATURE_LS_RECURSIVE
        int dndirs;
        struct dnode **dnd;
 #endif
@@ -432,10 +481,12 @@ void showdirs(struct dnode **dn, int ndirs)
 #ifdef BB_FEATURE_LS_RECURSIVE
                        if (disp_opts & DISP_RECURSIVE) {
                                /* recursive- list the sub-dirs */
-                               dnd= splitdnarray(subdnp, nfiles, SPLIT_DIR);
-                               dndirs= countdirs(subdnp, nfiles);
+                               dnd= splitdnarray(subdnp, nfiles, SPLIT_SUBDIR);
+                               dndirs= countsubdirs(subdnp, nfiles);
                                if (dndirs > 0) {
+#ifdef BB_FEATURE_LS_SORTFILES
                                        shellsort(dnd, dndirs);
+#endif
                                        showdirs(dnd, dndirs);
                                        free(dnd);  /* free the array of dnode pointers to the dirs */
                                }
@@ -460,7 +511,7 @@ struct dnode **list_dir(char *path)
        nfiles= 0;
        dir = opendir(path);
        if (dir == NULL) {
-               errorMsg("%s: %s\n", path, strerror(errno));
+               error_msg("%s: %s\n", path, strerror(errno));
                status = EXIT_FAILURE;
                return(NULL);   /* could not open the dir */
        }
@@ -476,24 +527,8 @@ struct dnode **list_dir(char *path)
                        strcat(cur->fullname, "/");
                cur->name= cur->fullname + strlen(cur->fullname);
                strcat(cur->fullname, entry->d_name);
-#ifdef BB_FEATURE_LS_FOLLOWLINKS
-               if (follow_links == TRUE) {
-                       if (stat(cur->fullname, &cur->dstat)) {
-                               errorMsg("%s: %s\n", cur->fullname, strerror(errno));
-                               status = EXIT_FAILURE;
-                               free(cur->fullname);
-                               free(cur);
-                               continue;
-                       }
-               } else
-#endif
-               if (lstat(cur->fullname, &cur->dstat)) {   /* get file stat info into node */
-                       errorMsg("%s: %s\n", cur->fullname, strerror(errno));
-                       status = EXIT_FAILURE;
-                       free(cur->fullname);
-                       free(cur);
+               if (my_stat(cur))
                        continue;
-               }
                cur->next= dn;
                dn= cur;
                nfiles++;
@@ -522,8 +557,10 @@ int list_single(struct dnode *dn)
        char *filetime;
        time_t ttime, age;
 #endif
-#ifdef BB_FEATURE_LS_FILETYPES
+#if defined (BB_FEATURE_LS_FILETYPES)
        struct stat info;
+#endif
+#ifdef BB_FEATURE_LS_FILETYPES
        char append;
 #endif
 
@@ -554,7 +591,7 @@ int list_single(struct dnode *dn)
                                column += 5;
                                break;
                        case LIST_MODEBITS:
-                               fprintf(stdout, "%10s", (char *)modeString(dn->dstat.st_mode));
+                               fprintf(stdout, "%10s", (char *)mode_string(dn->dstat.st_mode));
                                column += 10;
                                break;
                        case LIST_NLINKS:
@@ -563,28 +600,19 @@ int list_single(struct dnode *dn)
                                break;
                        case LIST_ID_NAME:
 #ifdef BB_FEATURE_LS_USERNAME
-                               {
-                                       memset(&info, 0, sizeof(struct stat));
-                                       memset(scratch, 0, sizeof(scratch));
-                                       if (!stat(dn->fullname, &info)) {
-                                               my_getpwuid(scratch, info.st_uid);
-                                       }
-                                       if (*scratch) {
-                                               fprintf(stdout, "%-8.8s ", scratch);
-                                       } else {
-                                               fprintf(stdout, "%-8d ", dn->dstat.st_uid);
-                                       }
-                                       memset(scratch, 0, sizeof(scratch));
-                                       if (info.st_ctime != 0) {
-                                               my_getgrgid(scratch, info.st_gid);
-                                       }
-                                       if (*scratch) {
-                                               fprintf(stdout, "%-8.8s", scratch);
-                                       } else {
-                                               fprintf(stdout, "%-8d", dn->dstat.st_gid);
-                                       }
+                               memset(scratch, 0, sizeof(scratch));
+                               my_getpwuid(scratch, dn->dstat.st_uid);
+                               if (*scratch)
+                                       fprintf(stdout, "%-8.8s ", scratch);
+                               else
+                                       fprintf(stdout, "%-8d ", dn->dstat.st_uid);
+                               memset(scratch, 0, sizeof(scratch));
+                               my_getgrgid(scratch, dn->dstat.st_gid);
+                               if (*scratch)
+                                       fprintf(stdout, "%-8.8s", scratch);
+                               else
+                                       fprintf(stdout, "%-8d", dn->dstat.st_gid);
                                column += 17;
-                               }
                                break;
 #endif
                        case LIST_ID_NUMERIC:
@@ -678,7 +706,6 @@ extern int ls_main(int argc, char **argv)
 #endif
        nfiles=0;
 
-       applet_name= argv[0];
        /* process options */
        while ((opt = getopt(argc, argv, "1AaCdgilnsx"
 #ifdef BB_FEATURE_AUTOWIDTH
@@ -706,7 +733,6 @@ extern int ls_main(int argc, char **argv)
                        case 'a': disp_opts |= DISP_HIDDEN | DISP_DOT; break;
                        case 'C': style_fmt = STYLE_COLUMNS; break;
                        case 'd': disp_opts |= DISP_NOLIST; break;
-                       case 'e': list_fmt |= LIST_FULLTIME; break;
                        case 'g': /* ignore -- for ftp servers */ break;
                        case 'i': list_fmt |= LIST_INO; break;
                        case 'l': style_fmt = STYLE_LONG; list_fmt |= LIST_LONG; break;
@@ -727,9 +753,24 @@ extern int ls_main(int argc, char **argv)
                        case 'X': sort_opts= SORT_EXT; break;
 #endif
 #ifdef BB_FEATURE_LS_TIMESTAMPS
-                       case 'c': time_fmt = TIME_CHANGE; sort_opts= SORT_CTIME; break;
-                       case 't': sort_opts= SORT_MTIME; break;
-                       case 'u': time_fmt = TIME_ACCESS; sort_opts= SORT_ATIME; break;
+                       case 'e': list_fmt |= LIST_FULLTIME; break;
+                       case 'c':
+                               time_fmt = TIME_CHANGE;
+#ifdef BB_FEATURE_LS_SORTFILES
+                               sort_opts= SORT_CTIME;
+#endif
+                               break;
+                       case 'u':
+                               time_fmt = TIME_ACCESS;
+#ifdef BB_FEATURE_LS_SORTFILES
+                               sort_opts= SORT_ATIME;
+#endif
+                               break;
+                       case 't':
+#ifdef BB_FEATURE_LS_SORTFILES
+                               sort_opts= SORT_MTIME;
+#endif
+                               break;
 #endif
 #ifdef BB_FEATURE_LS_FOLLOWLINKS
                        case 'L': follow_links= TRUE; break;
@@ -748,7 +789,7 @@ extern int ls_main(int argc, char **argv)
        if (disp_opts & DISP_NOLIST)
                disp_opts &= ~DISP_RECURSIVE;   /* no recurse if listing only dir */
 #endif
-#ifdef BB_FEATURE_LS_TIMESTAMPS
+#if defined (BB_FEATURE_LS_TIMESTAMPS) && defined (BB_FEATURE_LS_SORTFILES)
        if (time_fmt & TIME_CHANGE) sort_opts= SORT_CTIME;
        if (time_fmt & TIME_ACCESS) sort_opts= SORT_ATIME;
 #endif
@@ -792,24 +833,8 @@ extern int ls_main(int argc, char **argv)
                cur= (struct dnode *)xmalloc(sizeof(struct dnode));
                cur->fullname= xstrdup(av[oi]);
                cur->name= cur->fullname;
-#ifdef BB_FEATURE_LS_FOLLOWLINKS
-               if (follow_links == TRUE) {
-                       if (stat(av[oi], &cur->dstat)) {
-                               errorMsg("%s: %s\n", av[oi], strerror(errno));
-                               status = EXIT_FAILURE;
-                               free(cur->fullname);
-                               free(cur);
-                               continue;
-                       }
-               } else
-#endif
-               if (lstat(av[oi], &cur->dstat)) {  /* get file info into node */
-                       errorMsg("%s: %s\n", av[oi], strerror(errno));
-                       status = EXIT_FAILURE;
-                       free(cur->fullname);
-                       free(cur);
+               if (my_stat(cur))
                        continue;
-               }
                cur->next= dn;
                dn= cur;
                nfiles++;
@@ -853,5 +878,4 @@ extern int ls_main(int argc, char **argv)
 
   print_usage_message:
        usage(ls_usage);
-       return(FALSE);
 }