sbase

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

commit bec3c32dbdd6a0a67036d0545cf66f3d15a10e4c
parent 9da1deaab920e2b2635079729aa816822f324eab
Author: FRIGN <dev@frign.de>
Date:   Mon Feb 16 19:20:06 +0100

Refactor ls(1)

Diffstat:
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; +}