ls: correctly handle recursivity

the path is now carried through ls() and lsdir(), directory entries are
listed before recursing.
This commit is contained in:
Quentin Rameau 2015-06-12 19:38:07 +02:00 committed by sin
parent 1905b83cc9
commit 74b5aa151c
1 changed files with 65 additions and 41 deletions

106
ls.c
View File

@ -45,9 +45,8 @@ static int tflag = 0;
static int Uflag = 0; static int Uflag = 0;
static int uflag = 0; static int uflag = 0;
static int first = 1; static int first = 1;
static int many;
static void ls(const struct entry *ent, int recurse); static void ls(const char *, const struct entry *, int);
static void static void
mkent(struct entry *ent, char *path, int dostat, int follow) mkent(struct entry *ent, char *path, int dostat, int follow)
@ -213,64 +212,87 @@ entcmp(const void *va, const void *vb)
} }
static void static void
lsdir(const char *path) lsdir(const char *path, const struct entry *dir)
{ {
DIR *dp; DIR *dp;
struct entry ent, *ents = NULL; struct entry *ent, *ents = NULL;
struct dirent *d; struct dirent *d;
size_t i, n = 0; size_t i, n = 0;
char cwd[PATH_MAX], *name; char prefix[PATH_MAX];
if (!getcwd(cwd, sizeof(cwd))) if (!(dp = opendir(dir->name)))
eprintf("getcwd:"); eprintf("opendir %s:", dir->name);
if (!(dp = opendir(path))) if (chdir(dir->name) < 0)
eprintf("opendir %s:", path); eprintf("chdir %s:", dir->name);
if (chdir(path) < 0)
eprintf("chdir %s:", path);
if (many || Rflag) {
if (!first)
putchar('\n');
printf("%s:\n", path);
}
first = 0;
while ((d = readdir(dp))) { while ((d = readdir(dp))) {
if (d->d_name[0] == '.' && !aflag && !Aflag) if (d->d_name[0] == '.' && !aflag && !Aflag)
continue; continue;
else if (Aflag) else if (Aflag)
if (strcmp(d->d_name, ".") == 0 || strcmp(d->d_name, "..") == 0) if (strcmp(d->d_name, ".") == 0 ||
strcmp(d->d_name, "..") == 0)
continue; continue;
if (Uflag){
mkent(&ent, d->d_name, Fflag || lflag || pflag || iflag || Rflag, Lflag); ents = ereallocarray(ents, ++n, sizeof(*ents));
ls(&ent, Rflag); mkent(&ents[n - 1], estrdup(d->d_name), Fflag || iflag ||
} else { lflag || pflag || Rflag || Sflag, Lflag);
ents = ereallocarray(ents, ++n, sizeof(*ents));
name = estrdup(d->d_name);
mkent(&ents[n - 1], name, tflag || Sflag || Fflag || iflag || lflag || pflag || Rflag, Lflag);
}
} }
closedir(dp); closedir(dp);
if (!Uflag){
if (!Uflag)
qsort(ents, n, sizeof(*ents), entcmp); qsort(ents, n, sizeof(*ents), entcmp);
if (path[0] || dir->name[0] != '.')
printf("%s:\n", dir->name);
for (i = 0; i < n; i++)
output(&ents[rflag ? (n - 1 - i) : i]);
if (Rflag) {
if (snprintf(prefix, PATH_MAX, "%s%s/", path, dir->name) >=
PATH_MAX)
eprintf("path too long: %s%s\n", path, dir->name);
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
ls(&ents[rflag ? (n - i - 1) : i], Rflag); ent = &ents[rflag ? (n - 1 - i) : i];
free(ents[rflag ? (n - i - 1) : i].name); if (strcmp(ent->name, ".") == 0 ||
strcmp(ent->name, "..") == 0)
continue;
if (S_ISLNK(ent->mode) && S_ISDIR(ent->tmode) && !Lflag)
continue;
ls(prefix, ent, Rflag);
} }
} }
if (chdir(cwd) < 0)
eprintf("chdir %s:", cwd); for (i = 0; i < n; ++i)
free(ents[i].name);
free(ents); free(ents);
} }
static void static void
ls(const struct entry *ent, int recurse) ls(const char *path, const struct entry *ent, int listdir)
{ {
if (recurse && (S_ISDIR(ent->mode) || (S_ISLNK(ent->mode) && char cwd[PATH_MAX];
S_ISDIR(ent->tmode) && !Fflag && !lflag)) && !dflag)
lsdir(ent->name); if (!listdir) {
else
output(ent); output(ent);
} else if (S_ISDIR(ent->mode) ||
(S_ISLNK(ent->mode) && S_ISDIR(ent->tmode))) {
if (!getcwd(cwd, PATH_MAX))
eprintf("getcwd:");
if (first)
first = !first;
else
putchar('\n');
printf("%s", path);
lsdir(path, ent);
if (chdir(cwd) < 0)
eprintf("chdir %s:", cwd);
}
} }
static void static void
@ -367,10 +389,12 @@ main(int argc, char *argv[])
case 1: case 1:
ent = emalloc(sizeof(*ent)); ent = emalloc(sizeof(*ent));
mkent(ent, argv[0], 1, Hflag || Lflag); mkent(ent, argv[0], 1, Hflag || Lflag);
ls(ent, 1); ls("", ent, (!dflag && S_ISDIR(ent->mode)) ||
((S_ISLNK(ent->mode) && S_ISDIR(ent->tmode)) &&
((Hflag || Lflag) || !(dflag || Fflag || lflag))));
break; break;
default: default:
many = 1;
for (i = ds = fs = 0, fents = dents = NULL; i < argc; ++i) { for (i = ds = fs = 0, fents = dents = NULL; i < argc; ++i) {
ent = emalloc(sizeof(*ent)); ent = emalloc(sizeof(*ent));
mkent(ent, argv[i], 1, Hflag || Lflag); mkent(ent, argv[i], 1, Hflag || Lflag);
@ -390,11 +414,11 @@ main(int argc, char *argv[])
qsort(dents, ds, sizeof(ent), entcmp); qsort(dents, ds, sizeof(ent), entcmp);
for (i = 0; i < fs; ++i) for (i = 0; i < fs; ++i)
ls(fents[rflag ? (fs - i - 1) : i], 0); ls("", fents[rflag ? (fs - i - 1) : i], 0);
if (fs && ds) if (fs && ds)
putchar('\n'); putchar('\n');
for (i = 0; i < ds; ++i) for (i = 0; i < ds; ++i)
ls(dents[rflag ? (ds - i - 1) : i], 1); ls("", dents[rflag ? (ds - i - 1) : i], 1);
} }
return fshut(stdout, "<stdout>"); return fshut(stdout, "<stdout>");