---
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.1
Received 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