ls: detect infinite loop with recursivity

populate an history of visited directories inodes and search it before
recursing
This commit is contained in:
Quentin Rameau 2015-06-12 20:03:04 +02:00 committed by sin
parent 74b5aa151c
commit f1bbe6529a
1 changed files with 45 additions and 3 deletions

48
ls.c
View File

@ -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);