commit bec3c32dbdd6a0a67036d0545cf66f3d15a10e4c
parent 9da1deaab920e2b2635079729aa816822f324eab
Author: FRIGN <dev@frign.de>
Date: Mon, 16 Feb 2015 19:20:06 +0100
Refactor ls(1)
Diffstat:
M | ls.c | | | 353 | ++++++++++++++++++++++++++++++++++++++----------------------------------------- |
1 file changed, 171 insertions(+), 182 deletions(-)
diff --git a/ls.c b/ls.c
@@ -12,22 +12,16 @@
#include "util.h"
-typedef struct {
- char *name;
- mode_t mode, tmode;
+struct entry {
+ char *name;
+ mode_t mode, tmode;
nlink_t nlink;
- uid_t uid;
- gid_t gid;
- off_t size;
- time_t t;
- ino_t ino;
-} Entry;
-
-static int entcmp(const void *, const void *);
-static void ls(Entry *);
-static void lsdir(const char *);
-static void mkent(Entry *, char *, int, int);
-static void output(Entry *);
+ uid_t uid;
+ gid_t gid;
+ off_t size;
+ time_t t;
+ ino_t ino;
+};
static int aflag = 0;
static int cflag = 0;
@@ -45,164 +39,22 @@ static int first = 1;
static int many;
static void
-usage(void)
-{
- eprintf("usage: %s [-1acdFHhiLlrtU] [file ...]\n", argv0);
-}
-
-int
-main(int argc, char *argv[])
-{
- int i;
- Entry *ents;
-
- ARGBEGIN {
- case '1':
- /* ignore */
- break;
- case 'a':
- aflag = 1;
- break;
- case 'c':
- cflag = 1;
- break;
- case 'd':
- dflag = 1;
- break;
- case 'F':
- Fflag = 1;
- break;
- case 'H':
- Hflag = 1;
- break;
- case 'h':
- hflag = 1;
- break;
- case 'i':
- iflag = 1;
- break;
- case 'L':
- Lflag = 1;
- break;
- case 'l':
- lflag = 1;
- break;
- case 'r':
- rflag = 1;
- break;
- case 't':
- tflag = 1;
- break;
- case 'U':
- Uflag = 1;
- break;
- default:
- usage();
- } ARGEND;
-
- many = (argc > 1);
- if (argc == 0)
- *--argv = ".", argc++;
-
- ents = emalloc(argc * sizeof(*ents));
-
- for (i = 0; i < argc; i++)
- mkent(&ents[i], argv[i], 1, Hflag || Lflag);
- qsort(ents, argc, sizeof *ents, entcmp);
- for (i = 0; i < argc; i++)
- ls(&ents[rflag ? argc-i-1 : i]);
-
- return 0;
-}
-
-static int
-entcmp(const void *va, const void *vb)
-{
- const Entry *a = va, *b = vb;
-
- if (tflag)
- return b->t - a->t;
- else
- return strcmp(a->name, b->name);
-}
-
-static void
-ls(Entry *ent)
-{
- if ((S_ISDIR(ent->mode) || (S_ISLNK(ent->mode) && S_ISDIR(ent->tmode) && !Fflag && !lflag)) && !dflag) {
- lsdir(ent->name);
- } else {
- output(ent);
- }
-}
-
-static void
-lsdir(const char *path)
-{
- char *cwd, *p;
- long i, n = 0;
- struct dirent *d;
- DIR *dp;
- Entry ent, *ents = NULL;
- size_t sz;
-
- cwd = agetcwd();
- if (!(dp = opendir(path)))
- eprintf("opendir %s:", path);
- if (chdir(path) < 0)
- eprintf("chdir %s:", path);
-
- if (many) {
- if (!first)
- putchar('\n');
- printf("%s:\n", path);
- first = 0;
- }
-
- while ((d = readdir(dp))) {
- if (d->d_name[0] == '.' && !aflag)
- continue;
- if (Uflag){
- mkent(&ent, d->d_name, Fflag || lflag || iflag, Lflag);
- output(&ent);
- } else {
- ents = erealloc(ents, ++n * sizeof *ents);
- p = emalloc((sz = strlen(d->d_name)+1));
- memcpy(p, d->d_name, sz);
- mkent(&ents[n-1], p, tflag || Fflag || lflag || iflag, Lflag);
- }
- }
- closedir(dp);
- if (!Uflag){
- qsort(ents, n, sizeof *ents, entcmp);
- for (i = 0; i < n; i++) {
- output(&ents[rflag ? n-i-1 : i]);
- free(ents[rflag ? n-i-1 : i].name);
- }
- }
- if (chdir(cwd) < 0)
- eprintf("chdir %s:", cwd);
- free(ents);
- free(cwd);
-}
-
-static void
-mkent(Entry *ent, char *path, int dostat, int follow)
+mkent(struct entry *ent, char *path, int dostat, int follow)
{
struct stat st;
- ent->name = path;
+ ent->name = path;
if (!dostat)
return;
if ((follow ? stat : lstat)(path, &st) < 0)
eprintf("%s %s:", follow ? "stat" : "lstat", path);
- ent->mode = st.st_mode;
- ent->nlink = st.st_nlink;
- ent->uid = st.st_uid;
- ent->gid = st.st_gid;
- ent->size = st.st_size;
- ent->t = cflag ? st.st_ctime : st.st_mtime;
- ent->ino = st.st_ino;
+ ent->mode = st.st_mode;
+ ent->nlink = st.st_nlink;
+ ent->uid = st.st_uid;
+ ent->gid = st.st_gid;
+ ent->size = st.st_size;
+ ent->t = cflag ? st.st_ctime : st.st_mtime;
+ ent->ino = st.st_ino;
if (S_ISLNK(ent->mode))
ent->tmode = stat(path, &st) == 0 ? st.st_mode : 0;
}
@@ -221,24 +73,21 @@ indicator(mode_t mode)
return "|";
else if (S_ISSOCK(mode))
return "=";
- else if (mode & S_IXUSR ||
- mode & S_IXGRP ||
- mode & S_IXOTH)
+ else if (mode & S_IXUSR || mode & S_IXGRP || mode & S_IXOTH)
return "*";
else
return "";
}
static void
-output(Entry *ent)
+output(const struct entry *ent)
{
- char buf[BUFSIZ], *fmt;
- char mode[] = "----------";
- ssize_t len;
struct group *gr;
struct passwd *pw;
- char pwname[_SC_LOGIN_NAME_MAX];
- char grname[_SC_LOGIN_NAME_MAX];
+ ssize_t len;
+ char buf[BUFSIZ], *fmt,
+ pwname[_SC_LOGIN_NAME_MAX], grname[_SC_LOGIN_NAME_MAX],
+ mode[] = "----------";
if (iflag)
printf("%lu ", (unsigned long)ent->ino);
@@ -279,22 +128,22 @@ output(Entry *ent)
pw = getpwuid(ent->uid);
if (pw)
- snprintf(pwname, sizeof(pwname), "%s", pw->pw_name);
+ snprintf(pwname, LEN(pwname), "%s", pw->pw_name);
else
- snprintf(pwname, sizeof(pwname), "%d", ent->uid);
+ snprintf(pwname, LEN(pwname), "%d", ent->uid);
gr = getgrgid(ent->gid);
if (gr)
- snprintf(grname, sizeof(grname), "%s", gr->gr_name);
+ snprintf(grname, LEN(grname), "%s", gr->gr_name);
else
- snprintf(grname, sizeof(grname), "%d", ent->gid);
+ snprintf(grname, LEN(grname), "%d", ent->gid);
- if (time(NULL) > ent->t + (180*24*60*60)) /* 6 months ago? */
+ if (time(NULL) > ent->t + (180 * 24 * 60 * 60)) /* 6 months ago? */
fmt = "%b %d %Y";
else
fmt = "%b %d %H:%M";
- strftime(buf, sizeof buf, fmt, localtime(&ent->t));
+ strftime(buf, sizeof(buf), fmt, localtime(&ent->t));
printf("%s %4ld %-8.8s %-8.8s ", mode, (long)ent->nlink, pwname, grname);
if (hflag)
printf("%10s ", humansize((unsigned long)ent->size));
@@ -302,10 +151,150 @@ output(Entry *ent)
printf("%10lu ", (unsigned long)ent->size);
printf("%s %s%s", buf, ent->name, indicator(ent->mode));
if (S_ISLNK(ent->mode)) {
- if ((len = readlink(ent->name, buf, sizeof buf - 1)) < 0)
+ if ((len = readlink(ent->name, buf, sizeof(buf) - 1)) < 0)
eprintf("readlink %s:", ent->name);
buf[len] = '\0';
printf(" -> %s%s", buf, indicator(ent->tmode));
}
putchar('\n');
}
+
+static int
+entcmp(const void *va, const void *vb)
+{
+ const struct entry *a = va, *b = vb;
+
+ if (tflag)
+ return b->t - a->t;
+ else
+ return strcmp(a->name, b->name);
+}
+
+static void
+lsdir(const char *path)
+{
+ DIR *dp;
+ struct entry ent, *ents = NULL;
+ struct dirent *d;
+ size_t i, n = 0;
+ char *cwd, *p;
+
+ cwd = agetcwd();
+ if (!(dp = opendir(path)))
+ eprintf("opendir %s:", path);
+ if (chdir(path) < 0)
+ eprintf("chdir %s:", path);
+
+ if (many) {
+ if (!first)
+ putchar('\n');
+ printf("%s:\n", path);
+ first = 0;
+ }
+
+ while ((d = readdir(dp))) {
+ if (d->d_name[0] == '.' && !aflag)
+ continue;
+ if (Uflag){
+ mkent(&ent, d->d_name, Fflag || lflag || iflag, Lflag);
+ output(&ent);
+ } else {
+ ents = erealloc(ents, ++n * sizeof(*ents));
+ p = estrdup(d->d_name);
+ mkent(&ents[n - 1], p, tflag || Fflag || lflag || iflag, Lflag);
+ }
+ }
+ closedir(dp);
+ if (!Uflag){
+ qsort(ents, n, sizeof(*ents), entcmp);
+ for (i = 0; i < n; i++) {
+ output(&ents[rflag ? (n - i - 1) : i]);
+ free(ents[rflag ? (n - i - 1) : i].name);
+ }
+ }
+ if (chdir(cwd) < 0)
+ eprintf("chdir %s:", cwd);
+ free(ents);
+ free(cwd);
+}
+
+static void
+ls(const struct entry *ent)
+{
+ if ((S_ISDIR(ent->mode) || (S_ISLNK(ent->mode) &&
+ S_ISDIR(ent->tmode) && !Fflag && !lflag)) && !dflag)
+ lsdir(ent->name);
+ else
+ output(ent);
+}
+
+static void
+usage(void)
+{
+ eprintf("usage: %s [-1acdFHhiLlrtU] [file ...]\n", argv0);
+}
+
+int
+main(int argc, char *argv[])
+{
+ struct entry *ents;
+ size_t i;
+
+ ARGBEGIN {
+ case '1':
+ /* ignore */
+ break;
+ case 'a':
+ aflag = 1;
+ break;
+ case 'c':
+ cflag = 1;
+ break;
+ case 'd':
+ dflag = 1;
+ break;
+ case 'F':
+ Fflag = 1;
+ break;
+ case 'H':
+ Hflag = 1;
+ break;
+ case 'h':
+ hflag = 1;
+ break;
+ case 'i':
+ iflag = 1;
+ break;
+ case 'L':
+ Lflag = 1;
+ break;
+ case 'l':
+ lflag = 1;
+ break;
+ case 'r':
+ rflag = 1;
+ break;
+ case 't':
+ tflag = 1;
+ break;
+ case 'U':
+ Uflag = 1;
+ break;
+ default:
+ usage();
+ } ARGEND;
+
+ many = (argc > 1);
+ if (argc == 0)
+ *--argv = ".", argc++;
+
+ ents = emalloc(argc * sizeof(*ents));
+
+ for (i = 0; i < argc; i++)
+ mkent(&ents[i], argv[i], 1, Hflag || Lflag);
+ qsort(ents, argc, sizeof(*ents), entcmp);
+ for (i = 0; i < argc; i++)
+ ls(&ents[rflag ? argc-i-1 : i]);
+
+ return 0;
+}