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;
|
||||
off_t size;
|
||||
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 cflag = 0;
|
||||
|
@ -69,9 +75,17 @@ mkent(struct entry *ent, char *path, int dostat, int follow)
|
|||
ent->t = st.st_atime;
|
||||
else
|
||||
ent->t = st.st_mtime;
|
||||
ent->dev = st.st_dev;
|
||||
ent->ino = st.st_ino;
|
||||
if (S_ISLNK(ent->mode))
|
||||
ent->tmode = stat(path, &st) == 0 ? st.st_mode : 0;
|
||||
if (S_ISLNK(ent->mode)) {
|
||||
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 *
|
||||
|
@ -270,15 +284,42 @@ lsdir(const char *path, const struct entry *dir)
|
|||
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
|
||||
ls(const char *path, const struct entry *ent, int listdir)
|
||||
{
|
||||
int treeind;
|
||||
char cwd[PATH_MAX];
|
||||
|
||||
if (!listdir) {
|
||||
output(ent);
|
||||
} else if (S_ISDIR(ent->mode) ||
|
||||
(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))
|
||||
eprintf("getcwd:");
|
||||
|
||||
|
@ -289,6 +330,7 @@ ls(const char *path, const struct entry *ent, int listdir)
|
|||
|
||||
printf("%s", path);
|
||||
lsdir(path, ent);
|
||||
tree[treeind].ino = 0;
|
||||
|
||||
if (chdir(cwd) < 0)
|
||||
eprintf("chdir %s:", cwd);
|
||||
|
|
Loading…
Reference in New Issue
Block a user