changeset 476:d10b58563cff

More ls updates from Andre Renaud: Add -R and initial support for listing files on the command line.
author Rob Landley <rob@landley.net>
date Sat, 18 Feb 2012 15:19:00 -0600
parents 1fb149e75ebf
children f0b07ce5f125
files toys/ls.c
diffstat 1 files changed, 40 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/toys/ls.c	Sat Feb 18 15:12:41 2012 -0600
+++ b/toys/ls.c	Sat Feb 18 15:19:00 2012 -0600
@@ -6,7 +6,7 @@
  *
  * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ls.html
 
-USE_LS(NEWTOY(ls, "lF1a", TOYFLAG_BIN))
+USE_LS(NEWTOY(ls, "RlF1a", TOYFLAG_BIN))
 
 config LS
 	bool "ls"
@@ -27,6 +27,7 @@
 #define FLAG_1 2
 #define FLAG_F 4
 #define FLAG_l 8
+#define FLAG_R 16
 
 static int dir_filter(const struct dirent *d)
 {
@@ -44,14 +45,30 @@
     int i;
     int maxwidth = -1;
     int ncolumns = 1;
+    struct dirent file_dirent;
+    struct dirent *file_direntp;
 
     if (!name || strcmp(name, "-") == 0)
         name = ".";
 
+    if (toys.optflags & FLAG_R)
+        xprintf("\n%s:\n", name);
+
     /* Get all the files in this directory */
     nentries = scandir(name, &entries, dir_filter, alphasort);
-    if (nentries < 0)
-        perror_exit("ls: cannot access %s'", name);
+    if (nentries < 0) {
+        /* We've just selected a single file, so create a single-length list */
+        /* FIXME: This means that ls *.x results in a whole bunch of single
+         * listings, not one combined listing.
+         */
+        if (errno == ENOTDIR) {
+            nentries = 1;
+            strcpy(file_dirent.d_name, name);
+            file_direntp = &file_dirent;
+            entries = &file_direntp;
+        } else 
+            perror_exit("ls: cannot access %s'", name);
+    }
 
 
     /* Determine the widest entry so we can flow them properly */
@@ -83,14 +100,16 @@
         struct stat st;
         int stat_valid = 0;
 
+        sprintf(toybuf, "%s/%s", name, ent->d_name);
+
         /* Provide the ls -l long output */
         if (toys.optflags & FLAG_l) {
             char type;
             char timestamp[64];
             struct tm mtime;
 
-            if (lstat(ent->d_name, &st))
-                perror_exit("Can't stat %s", ent->d_name);
+            if (lstat(toybuf, &st))
+                perror_exit("Can't stat %s", toybuf);
             stat_valid = 1;
             if (S_ISDIR(st.st_mode))
                 type = 'd';
@@ -134,8 +153,8 @@
         /* Append the file-type indicator character */
         if (toys.optflags & FLAG_F) {
             if (!stat_valid) {
-                if (lstat(ent->d_name, &st))
-                    perror_exit("Can't stat %s", ent->d_name);
+                if (lstat(toybuf, &st))
+                    perror_exit("Can't stat %s", toybuf);
                 stat_valid = 1;
             }
             if (S_ISDIR(st.st_mode)) {
@@ -162,6 +181,20 @@
     /* Make sure we put at a trailing new line in */
     if (!(toys.optflags & FLAG_1) && (i % ncolumns))
         xprintf("\n");
+
+    if (toys.optflags & FLAG_R) {
+        for (i = 0; i < nentries; i++) {
+            struct dirent *ent = entries[i];
+            struct stat st;
+            char dirname[PATH_MAX];
+
+            sprintf(dirname, "%s/%s", name, ent->d_name);
+            if (lstat(dirname, &st))
+                perror_exit("Can't stat %s", dirname);
+            if (S_ISDIR(st.st_mode))
+                do_ls(0, dirname);
+        }
+    }
 }
 
 void ls_main(void)