--- ls.c | 89 +++++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 61 insertions(+), 28 deletions(-) diff --git a/ls.c b/ls.c index b716aba..076f6b7 100644 --- a/ls.c +++ b/ls.c _AT_@ -10,11 +10,13 @@ #include <string.h> #include <time.h> #include <unistd.h> +#include <errno.h> #include "utf.h" #include "util.h" struct entry { + char valid; char *name; mode_t mode, tmode; nlink_t nlink; _AT_@ -58,15 +60,33 @@ static int showdirs; static void ls(const char *, const struct entry *, int); static void -mkent(struct entry *ent, char *path, int dostat, int follow) +mkent(struct entry *ent, char *prefix, char *name, int dostat, int follow, + int fatal) { struct stat st; + char path[PATH_MAX]; - ent->name = path; + ent->valid = 0; + ent->name = name; if (!dostat) return; - if ((follow ? stat : lstat)(path, &st) < 0) - eprintf("%s %s:", follow ? "stat" : "lstat", path); + + if (prefix != NULL) + snprintf(path, PATH_MAX, "%s/%s", prefix, name); + else + strncpy(path, name, PATH_MAX); + + if ((follow ? stat : lstat)(path, &st) < 0) { + if (errno == EACCES && !fatal) { + weprintf("%s %s:", follow ? "stat" : "lstat", path); + return; + } else { + eprintf("%s %s:", follow ? "stat" : "lstat", path); + } + } else { + ent->valid = 1; + } + ent->mode = st.st_mode; ent->nlink = st.st_nlink; ent->uid = st.st_uid; _AT_@ -130,12 +150,13 @@ printname(const char *name) } static void -output(const struct entry *ent) +output(const char *prefix, const struct entry *ent) { struct group *gr; struct passwd *pw; struct tm *tm; ssize_t len; + char path[PATH_MAX]; char *fmt, buf[BUFSIZ], pwname[_SC_LOGIN_NAME_MAX], grname[_SC_LOGIN_NAME_MAX], mode[] = "----------"; _AT_@ -163,6 +184,14 @@ output(const struct entry *ent) else mode[0] = '?'; + if (!ent->valid) { + printf("%c????????? ? ? ? ? ? ", mode[0]); + printname(ent->name); + fputs(indicator(ent->mode), stdout); + putchar('\n'); + return; + } + if (ent->mode & S_IRUSR) mode[1] = 'r'; if (ent->mode & S_IWUSR) mode[2] = 'w'; if (ent->mode & S_IXUSR) mode[3] = 'x'; _AT_@ -208,7 +237,8 @@ output(const struct entry *ent) printname(ent->name); fputs(indicator(ent->mode), stdout); if (S_ISLNK(ent->mode)) { - if ((len = readlink(ent->name, buf, sizeof(buf) - 1)) < 0) + snprintf(path, PATH_MAX, "%s/%s", prefix, ent->name); + if ((len = readlink(path, buf, sizeof(buf) - 1)) < 0) eprintf("readlink %s:", ent->name); buf[len] = '\0'; printf(" -> %s%s", buf, indicator(ent->tmode)); _AT_@ -247,13 +277,15 @@ lsdir(const char *path, const struct entry *dir) size_t i, n = 0; char prefix[PATH_MAX]; - if (!(dp = opendir(dir->name))) { + if (snprintf(prefix, PATH_MAX, "%s%s", path, dir->name) >= + PATH_MAX) + eprintf("path too long: %s%s\n", path, dir->name); + + if (!(dp = opendir(prefix))) { ret = 1; - weprintf("opendir %s%s:", path, dir->name); + weprintf("opendir %s:", prefix); return; } - if (chdir(dir->name) < 0) - eprintf("chdir %s:", dir->name); while ((d = readdir(dp))) { if (d->d_name[0] == '.' && !aflag && !Aflag) _AT_@ -264,8 +296,12 @@ lsdir(const char *path, const struct entry *dir) continue; ents = ereallocarray(ents, ++n, sizeof(*ents)); - mkent(&ents[n - 1], estrdup(d->d_name), Fflag || iflag || - lflag || pflag || Rflag || sort, Lflag); + ent = &ents[n - 1]; + mkent(ent, prefix, estrdup(d->d_name), Fflag || iflag || + lflag || pflag || Rflag || sort, Lflag, 0); + if (!ent->valid) { + ent->mode = DTTOIF(d->d_type); + } } closedir(dp); _AT_@ -279,13 +315,9 @@ lsdir(const char *path, const struct entry *dir) puts(":"); } for (i = 0; i < n; i++) - output(&ents[i]); + output(dir->name, &ents[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++) { ent = &ents[i]; if (strcmp(ent->name, ".") == 0 || _AT_@ -328,10 +360,10 @@ static void ls(const char *path, const struct entry *ent, int listdir) { int treeind; - char cwd[PATH_MAX]; + char correct_path[PATH_MAX]; if (!listdir) { - output(ent); + output(path, ent); } else if (S_ISDIR(ent->mode) || (S_ISLNK(ent->mode) && S_ISDIR(ent->tmode))) { if ((treeind = visit(ent)) < 0) { _AT_@ -340,19 +372,20 @@ ls(const char *path, const struct entry *ent, int listdir) return; } - if (!getcwd(cwd, PATH_MAX)) - eprintf("getcwd:"); - if (first) first = 0; else putchar('\n'); - lsdir(path, ent); - tree[treeind].ino = 0; - if (chdir(cwd) < 0) - eprintf("chdir %s:", cwd); + if (strlen(path) == 0 || path[strlen(path) - 1] == '/') { + lsdir(path, ent); + } else { + snprintf(correct_path, sizeof(correct_path), "%s/", path); + lsdir(correct_path, ent); + } + + tree[treeind].ino = 0; } } _AT_@ -446,7 +479,7 @@ main(int argc, char *argv[]) case 0: /* fallthrough */ *--argv = ".", ++argc; case 1: - mkent(&ent, argv[0], 1, Hflag || Lflag); + mkent(&ent, NULL, argv[0], 1, Hflag || Lflag, 1); ls("", &ent, (!dflag && S_ISDIR(ent.mode)) || (S_ISLNK(ent.mode) && S_ISDIR(ent.tmode) && !(dflag || Fflag || lflag))); _AT_@ -454,7 +487,7 @@ main(int argc, char *argv[]) break; default: for (i = ds = fs = 0, fents = dents = NULL; i < argc; ++i) { - mkent(&ent, argv[i], 1, Hflag || Lflag); + mkent(&ent, NULL, argv[i], 1, Hflag || Lflag, 1); if ((!dflag && S_ISDIR(ent.mode)) || (S_ISLNK(ent.mode) && S_ISDIR(ent.tmode) && -- 2.17.1Received on Sun Jul 08 2018 - 12:43:04 CEST
This archive was generated by hypermail 2.3.0 : Sun Jul 08 2018 - 12:48:25 CEST