ls: detect infinite loop with recursivity
populate an history of visited directories inodes and search it before recursing
This commit is contained in:
parent
74b5aa151c
commit
f1bbe6529a
48
ls.c
48
ls.c
@ -21,9 +21,15 @@ struct entry {
|
|||||||
gid_t gid;
|
gid_t gid;
|
||||||
off_t size;
|
off_t size;
|
||||||
time_t t;
|
time_t t;
|
||||||
ino_t ino;
|
dev_t dev;
|
||||||
|
ino_t ino, tino;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
dev_t dev;
|
||||||
|
ino_t ino;
|
||||||
|
} tree[PATH_MAX] = { { 0, 0 } };
|
||||||
|
|
||||||
static int Aflag = 0;
|
static int Aflag = 0;
|
||||||
static int aflag = 0;
|
static int aflag = 0;
|
||||||
static int cflag = 0;
|
static int cflag = 0;
|
||||||
@ -69,9 +75,17 @@ mkent(struct entry *ent, char *path, int dostat, int follow)
|
|||||||
ent->t = st.st_atime;
|
ent->t = st.st_atime;
|
||||||
else
|
else
|
||||||
ent->t = st.st_mtime;
|
ent->t = st.st_mtime;
|
||||||
|
ent->dev = st.st_dev;
|
||||||
ent->ino = st.st_ino;
|
ent->ino = st.st_ino;
|
||||||
if (S_ISLNK(ent->mode))
|
if (S_ISLNK(ent->mode)) {
|
||||||
ent->tmode = stat(path, &st) == 0 ? st.st_mode : 0;
|
if (stat(path, &st) == 0) {
|
||||||
|
ent->tmode = st.st_mode;
|
||||||
|
ent->dev = st.st_dev;
|
||||||
|
ent->tino = st.st_ino;
|
||||||
|
} else {
|
||||||
|
ent->tmode = ent->tino = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
@ -270,15 +284,42 @@ lsdir(const char *path, const struct entry *dir)
|
|||||||
free(ents);
|
free(ents);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
visit(const struct entry *ent)
|
||||||
|
{
|
||||||
|
dev_t dev;
|
||||||
|
ino_t ino;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
dev = ent->dev;
|
||||||
|
ino = S_ISLNK(ent->mode) ? ent->tino : ent->ino;
|
||||||
|
|
||||||
|
for (i = 0; tree[i].ino && i < PATH_MAX; ++i) {
|
||||||
|
if (ino == tree[i].ino && dev == tree[i].dev)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
tree[i].ino = ino;
|
||||||
|
tree[i].dev = dev;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ls(const char *path, const struct entry *ent, int listdir)
|
ls(const char *path, const struct entry *ent, int listdir)
|
||||||
{
|
{
|
||||||
|
int treeind;
|
||||||
char cwd[PATH_MAX];
|
char cwd[PATH_MAX];
|
||||||
|
|
||||||
if (!listdir) {
|
if (!listdir) {
|
||||||
output(ent);
|
output(ent);
|
||||||
} else if (S_ISDIR(ent->mode) ||
|
} else if (S_ISDIR(ent->mode) ||
|
||||||
(S_ISLNK(ent->mode) && S_ISDIR(ent->tmode))) {
|
(S_ISLNK(ent->mode) && S_ISDIR(ent->tmode))) {
|
||||||
|
if ((treeind = visit(ent)) < 0) {
|
||||||
|
fprintf(stderr, "%s%s: already visited\n",
|
||||||
|
path, ent->name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!getcwd(cwd, PATH_MAX))
|
if (!getcwd(cwd, PATH_MAX))
|
||||||
eprintf("getcwd:");
|
eprintf("getcwd:");
|
||||||
|
|
||||||
@ -289,6 +330,7 @@ ls(const char *path, const struct entry *ent, int listdir)
|
|||||||
|
|
||||||
printf("%s", path);
|
printf("%s", path);
|
||||||
lsdir(path, ent);
|
lsdir(path, ent);
|
||||||
|
tree[treeind].ino = 0;
|
||||||
|
|
||||||
if (chdir(cwd) < 0)
|
if (chdir(cwd) < 0)
|
||||||
eprintf("chdir %s:", cwd);
|
eprintf("chdir %s:", cwd);
|
||||||
|
Loading…
Reference in New Issue
Block a user