aboutsummaryrefslogtreecommitdiff
path: root/toys/ls.c
diff options
context:
space:
mode:
authorRob Landley <rob@landley.net>2012-04-26 19:59:38 -0500
committerRob Landley <rob@landley.net>2012-04-26 19:59:38 -0500
commitf3b4a916525c6658e71def23ee37532b0313b663 (patch)
treef4ca897509e8389610023eef732b4b41c8828bc4 /toys/ls.c
parent0b11a16626867a362ed9aff3950650af94d1cfa7 (diff)
downloadtoybox-f3b4a916525c6658e71def23ee37532b0313b663.tar.gz
Simplify/unify listfiles recursion: populate directory node (and detect top of tree) at start of function rather than end (and redundantly in main). Move title printing down next to total printing.
Diffstat (limited to 'toys/ls.c')
-rw-r--r--toys/ls.c79
1 files changed, 32 insertions, 47 deletions
diff --git a/toys/ls.c b/toys/ls.c
index b21f7b38..87a39978 100644
--- a/toys/ls.c
+++ b/toys/ls.c
@@ -58,7 +58,7 @@ DEFINE_GLOBALS(
struct dirtree *files;
unsigned width;
- int again;
+ int nl_title;
)
#define TT this.ls
@@ -149,30 +149,26 @@ static int filter(struct dirtree *new)
// Display a list of dirtree entries, according to current format
// Output types -1, -l, -C, or stream
-static void listfiles(struct dirtree *indir)
+static void listfiles(int dirfd, struct dirtree *indir)
{
struct dirtree *dt, **sort = 0;
unsigned long dtlen = 0, ul = 0;
unsigned width, flags = toys.optflags, totals[6], len[6];
- // There are two "top of tree" variants:
- // ls arg1 arg2 arg3
- // detect: !indir->parent
- // behavior: don't display dirs, never show dirname/total, option -H
- // ls onedir (or just "ls" which implies "." as first arg).
- // detect: indir == TT.files
- // behavior: only show dirname/total with -R
-
- // Show current directory name if showing one directory with -d or
- // not top of tree and -R
- if (!(indir == TT.files || (flags & FLAG_d))
- || (indir->parent && (flags & FLAG_R)))
- {
- char *path = dirtree_path(indir, 0);
-
- if (TT.again++) xputc('\n');
- xprintf("%s:\n", path);
- free(path);
+
+ // Silently descend into single directory listed by itself on command line.
+ // In this case only show dirname/total header when given -R.
+ if (!indir->parent) {
+ if (!(dt = indir->child)) return;
+ if (S_ISDIR(dt->st.st_mode) && !dt->next && !(toys.optflags&FLAG_d)) {
+ dt->extra = 1;
+ listfiles(open(dt->name, 0), dt);
+ return;
+ }
+ } else {
+ // Read directory contents. We dup() the fd because this will close it.
+ indir->data = dup(dirfd);
+ dirtree_recurse(indir, filter);
}
// Copy linked list to array and sort it. Directories go in array because
@@ -203,6 +199,16 @@ static void listfiles(struct dirtree *indir)
} else if (*len > *totals) *totals = *len;
}
+ // Label directory if not top of tree, or if -R
+ if (indir->parent && (!indir->extra || (flags&FLAG_R)))
+ {
+ char *path = dirtree_path(indir, 0);
+
+ if (TT.nl_title++) xputc('\n');
+ xprintf("%s:\n", path);
+ free(path);
+ }
+
// This is wrong, should be blocks used not file count.
if (indir->parent && (flags & FLAG_l)) xprintf("total %lu\n", dtlen);
@@ -216,6 +222,7 @@ static void listfiles(struct dirtree *indir)
// Skip directories at the top of the tree when -d isn't set
if (S_ISDIR(mode) && !indir->parent && !(flags & FLAG_d)) continue;
+ TT.nl_title=1;
// Do we need to wrap at right edge of screen?
entrylen(sort[ul], len);
@@ -285,17 +292,11 @@ static void listfiles(struct dirtree *indir)
|| dirtree_isdotdot(sort[ul])) continue;
// Recurse into dirs if at top of the tree or given -R
- if (!indir->parent || (flags & FLAG_R)) {
- int fd = openat(indir->data, sort[ul]->name, 0);
-
- sort[ul]->data = dup(fd);
- dirtree_recurse(sort[ul], filter);
- sort[ul]->data = fd;
- listfiles(sort[ul]);
- }
+ if (!indir->parent || (flags & FLAG_R))
+ listfiles(openat(dirfd, sort[ul]->name, 0), sort[ul]);
}
free(sort);
- if (indir->data != AT_FDCWD) close(indir->data);
+ if (dirfd != AT_FDCWD) close(indir->data);
}
void ls_main(void)
@@ -330,27 +331,11 @@ void ls_main(void)
(struct double_list *)dt);
}
- if (!TT.files->child) return;
-
// Turn double_list into dirtree
dlist_to_dirtree(TT.files);
- // Special case a single directory argument: silently descend into it.
- dt = TT.files->child;
-
- if (S_ISDIR(dt->st.st_mode) && !dt->next && !(toys.optflags&FLAG_d)) {
- int fd = open(dt->name, 0);
- TT.files = dt;
- dt->data = dup(fd);
- dirtree_recurse(dt, filter);
- dt->data = fd;
- } else TT.files->data = AT_FDCWD;
-
// Display the files we collected
- listfiles(TT.files);
+ listfiles(AT_FDCWD, TT.files);
- if (CFG_TOYBOX_FREE) {
- free(TT.files->parent);
- free(TT.files);
- }
+ if (CFG_TOYBOX_FREE) free(TT.files);
}