From 9981ae56ec0889df52f6891cd8227ede937dd178 Mon Sep 17 00:00:00 2001 From: Christian Neukirchen Date: Wed, 20 Jul 2016 13:53:17 +0200 Subject: mlist: rename from list --- mlist.c | 247 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 247 insertions(+) create mode 100644 mlist.c (limited to 'mlist.c') diff --git a/mlist.c b/mlist.c new file mode 100644 index 0000000..689743b --- /dev/null +++ b/mlist.c @@ -0,0 +1,247 @@ +#define _GNU_SOURCE + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#define lc(c) ((c) | 0x20) +#define uc(c) ((c) & 0xdf) + +/* + +PRSTDF +prstdf + +-N new +-n not new + +-C cur +-c not cur + +-m age + +-r recursive? + +*/ + +static int8_t flags[255]; +static int flagsum; +static int flagset; +static int Nflag; +static int Cflag; +static int iflag; + +static long icount; +static long iunseen; +static long iflagged; +static long imatched; + +void +list(char *prefix, char *file) +{ + if (flagset) { + int sum = 0; + char *f = strstr(file, ":2,"); + if (!f) + return; + icount++; + f += 3; + while (*f) { + if (flags[(unsigned int)*f] == -1) + return; + if (flags[(unsigned int)*f] == 1) + sum++; + f++; + } + if (sum != flagsum) + return; + } + + if (iflag) { + char *f = strstr(file, ":2,"); + if (!f) + return; + imatched++; + if (!flagset) + icount++; + if (!strchr(f, 'S')) + iunseen++; + if (strchr(f, 'F')) + iflagged++; + return; + } + + if (prefix) { + fputs(prefix, stdout); + putc('/', stdout); + } + puts(file); +} + +#ifdef __linux__ +// faster implementation of readdir using a bigger getdents buffer + +struct linux_dirent64 { + ino64_t d_ino; /* 64-bit inode number */ + off64_t d_off; /* 64-bit offset to next structure */ + unsigned short d_reclen; /* Size of this dirent */ + unsigned char d_type; /* File type */ + char d_name[]; /* Filename (null-terminated) */ +}; +#define BUF_SIZE 1024000 + +void +listdir(char *dir) +{ + int fd, nread; + char buf[BUF_SIZE]; + struct linux_dirent64 *d; + int bpos; + + fd = open(dir, O_RDONLY | O_DIRECTORY); + if (fd == -1) { + perror("open"); + return; + } + + while (1) { + nread = syscall(SYS_getdents64, fd, buf, BUF_SIZE); + if (nread == -1) { + perror("getdents64"); + break; + } + + if (nread == 0) + break; + + for (bpos = 0; bpos < nread;) { + d = (struct linux_dirent64 *) (buf + bpos); + if (d->d_type != DT_REG && d->d_type != DT_UNKNOWN) + goto next; + if (d->d_name[0] == '.') + goto next; + list(dir, d->d_name); +next: + bpos += d->d_reclen; + } + } + + close(fd); +} +#else +void +listdir(char *dir) +{ + DIR *fd; + struct dirent *d; + + fd = opendir(dir); + if (!fd) + return; + while ((d = readdir(fd))) { + if (d->d_type != DT_REG && d->d_type != DT_UNKNOWN) + continue; + if (d->d_name[0] == '.') + continue; + list(dir, d->d_name); + } + closedir(fd); +} +#endif + +int +main(int argc, char *argv[]) +{ + int c; + while ((c = getopt(argc, argv, "PRSTDFprstdfNnCcim:")) != -1) + switch(c) { + case 'P': case 'R': case 'S': case 'T': case 'D': case 'F': + flags[(unsigned int)c] = 1; + break; + case 'p': case 'r': case 's': case 't': case 'd': case 'f': + flags[(unsigned int)uc(c)] = -1; + break; + case 'N': Nflag = 1; break; + case 'n': Nflag = -1; break; + case 'C': Cflag = 1; break; + case 'c': Cflag = -1; break; + case 'i': iflag = 1; break; + case 'm': // XXX todo + default: + // XXX usage + exit(1); + } + + int i; + + for (i = 0, flagsum = 0, flagset = 0; (size_t)i < sizeof flags; i++) { + if (flags[i] != 0) + flagset++; + if (flags[i] == 1) + flagsum++; + } + + for (i = optind; i < argc; i++) { + struct stat st; + if (stat(argv[i], &st) < 0) + continue; + if (S_ISDIR(st.st_mode)) { + char subdir[PATH_MAX]; + struct stat st2; + int maildir = 0; + + long gcount = icount; + long gunseen = iunseen; + long gflagged = iflagged; + long gmatched = imatched; + + icount = 0; + iunseen = 0; + iflagged = 0; + + snprintf(subdir, sizeof subdir, "%s/cur", argv[i]); + if (stat(subdir, &st2) == 0) { + maildir = 1; + if (Cflag >= 0 && Nflag <= 0) + listdir(subdir); + } + + snprintf(subdir, sizeof subdir, "%s/new", argv[i]); + if (stat(subdir, &st2) == 0) { + maildir = 1; + if (Nflag >= 0 && Cflag <= 0) + listdir(subdir); + } + + if (!maildir) + listdir(argv[i]); + + if (iflag && imatched) + printf("%6ld unseen %3ld flagged %6ld msg %s\n", + iunseen, iflagged, icount, argv[i]); + + icount = gcount; + iunseen = gunseen; + iflagged = gflagged; + imatched = gmatched; + } else if (S_ISREG(st.st_mode)) { + list(0, argv[i]); + } + } + + if (iflag && imatched) + printf("%6ld unseen %3ld flagged %6ld msg\n", + iunseen, iflagged, icount); + +exit(0); + + exit(EXIT_SUCCESS); +} -- cgit 1.4.1