sbase

suckless unix tools
git clone git://git.2f30.org/sbase.git
Log | Files | Refs | README | LICENSE

commit f1bbe6529ab0a092731e5fa8ec9bf7d82a806f69
parent 74b5aa151cf1fbf439b1aec60c0da4e1904ad1ef
Author: Quentin Rameau <quinq@quinq.eu.org>
Date:   Fri Jun 12 20:03:04 +0200

ls: detect infinite loop with recursivity

populate an history of visited directories inodes and search it before
recursing

Diffstat:
ls.c | 48+++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 45 insertions(+), 3 deletions(-)
diff --git a/ls.c b/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);