mblaze/mlist.c

293 lines
5.0 KiB
C
Raw Normal View History

2016-07-12 15:51:34 +00:00
#define _GNU_SOURCE
2016-07-18 15:06:41 +00:00
#include <sys/stat.h>
#include <dirent.h>
2016-07-12 15:51:34 +00:00
#include <fcntl.h>
2016-07-18 15:06:41 +00:00
#include <limits.h>
#include <stdint.h>
2016-07-12 15:51:34 +00:00
#include <stdio.h>
2016-07-18 15:06:41 +00:00
#include <stdlib.h>
2016-07-12 15:51:34 +00:00
#include <string.h>
#include <unistd.h>
#include "blaze822.h"
2020-03-08 16:11:36 +00:00
#include "blaze822_priv.h"
2016-07-12 15:51:34 +00:00
/*
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;
2016-07-12 17:20:26 +00:00
static int iflag;
static long icount;
static long iunseen;
2016-07-12 17:20:26 +00:00
static long iflagged;
static long imatched;
2016-07-12 15:51:34 +00:00
static long tdirs;
static long tunseen;
static long tflagged;
static long tcount;
2016-07-12 15:51:34 +00:00
void
list(char *prefix, char *file)
{
char *f = 0;
if (flagset || iflag) {
size_t prefixlen;
f = strstr(file, ":2,");
if (!f &&
prefix &&
(prefixlen = strlen(prefix)) &&
prefixlen >= 4 &&
strcmp(prefix + prefixlen - 4, "/new") == 0)
f = ":2,";
}
2016-07-12 15:51:34 +00:00
if (flagset) {
int sum = 0;
if (!f)
return;
icount++;
2018-01-01 17:44:36 +00:00
tcount++;
2016-07-12 15:51:34 +00:00
f += 3;
while (*f) {
if (flags[(unsigned int)*f] == -1)
return;
if (flags[(unsigned int)*f] == 1)
sum++;
f++;
}
if (sum != flagsum)
return;
}
2016-07-12 17:20:26 +00:00
if (iflag) {
if (!f)
return;
imatched++;
if (!flagset)
icount++, tcount++;
if (!strchr(f, 'S'))
iunseen++, tunseen++;
if (strchr(f, 'F'))
iflagged++, tflagged++;
2016-07-12 17:20:26 +00:00
return;
}
2016-07-12 15:51:34 +00:00
if (prefix) {
fputs(prefix, stdout);
putc('/', stdout);
}
puts(file);
}
#ifdef __linux__
// faster implementation of readdir using a bigger getdents buffer
#include <sys/syscall.h>
2016-07-12 15:51:34 +00:00
struct linux_dirent64 {
2017-08-31 15:30:17 +00:00
ino64_t d_ino; /* 64-bit inode number */
off64_t d_off; /* 64-bit offset to next structure */
2016-07-12 15:51:34 +00:00
unsigned short d_reclen; /* Size of this dirent */
2017-08-31 15:30:17 +00:00
unsigned char d_type; /* File type */
char d_name[]; /* Filename (null-terminated) */
2016-07-12 15:51:34 +00:00
};
#define BUF_SIZE 1024000
char buf[BUF_SIZE];
2016-07-12 15:51:34 +00:00
void
listdir(char *dir)
{
int fd;
ssize_t nread;
ssize_t bpos;
2016-07-12 15:51:34 +00:00
struct linux_dirent64 *d;
fd = open(dir, O_RDONLY | O_DIRECTORY);
if (fd == -1) {
perror("open");
return;
}
2017-08-31 15:30:17 +00:00
2016-07-12 15:51:34 +00:00
while (1) {
nread = syscall(SYS_getdents64, fd, buf, BUF_SIZE);
2016-07-18 15:06:41 +00:00
if (nread == -1) {
perror("getdents64");
break;
}
2017-08-31 15:30:17 +00:00
2016-07-12 15:51:34 +00:00
if (nread == 0)
break;
for (bpos = 0; bpos < nread; bpos += d->d_reclen) {
2016-07-25 19:00:41 +00:00
d = (struct linux_dirent64 *)(buf + bpos);
2016-07-12 15:51:34 +00:00
if (d->d_type != DT_REG && d->d_type != DT_UNKNOWN)
continue;
2016-07-12 15:51:34 +00:00
if (d->d_name[0] == '.')
continue;
2016-07-12 15:51:34 +00:00
list(dir, d->d_name);
}
}
close(fd);
}
#else
void
listdir(char *dir)
{
DIR *fd;
2017-01-26 19:27:26 +00:00
struct dirent *d;
2016-07-12 15:51:34 +00:00
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
void
listarg(char *arg)
{
2017-07-12 20:31:01 +00:00
squeeze_slash(arg);
struct stat st;
if (stat(arg, &st) < 0)
return;
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", arg);
if (stat(subdir, &st2) == 0) {
maildir = 1;
if (Cflag >= 0 && Nflag <= 0)
listdir(subdir);
}
snprintf(subdir, sizeof subdir, "%s/new", arg);
if (stat(subdir, &st2) == 0) {
maildir = 1;
if (Nflag >= 0 && Cflag <= 0)
listdir(subdir);
}
if (!maildir)
listdir(arg);
if (iflag && (imatched || (maildir && !flagset))) {
tdirs++;
printf("%6ld unseen %3ld flagged %6ld msg %s\n",
iunseen, iflagged, icount, arg);
}
icount = gcount;
iunseen = gunseen;
iflagged = gflagged;
imatched = gmatched;
} else if (S_ISREG(st.st_mode)) {
list(0, arg);
}
}
2016-07-12 15:51:34 +00:00
int
main(int argc, char *argv[])
{
int c;
2016-07-26 19:57:54 +00:00
while ((c = getopt(argc, argv, "PRSTDFprstdfX:x:NnCci")) != -1)
2017-08-31 15:30:17 +00:00
switch (c) {
2016-07-12 15:51:34 +00:00
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;
2017-01-26 19:27:26 +00:00
case 'X':
2016-07-22 16:11:38 +00:00
while (*optarg)
flags[(unsigned int)*optarg++] = 1;
break;
2017-01-26 19:27:26 +00:00
case 'x':
2016-07-22 16:11:38 +00:00
while (*optarg)
flags[(unsigned int)*optarg++] = -1;
break;
2016-07-12 15:51:34 +00:00
case 'N': Nflag = 1; break;
case 'n': Nflag = -1; break;
case 'C': Cflag = 1; break;
case 'c': Cflag = -1; break;
2016-07-12 17:20:26 +00:00
case 'i': iflag = 1; break;
2016-07-12 15:51:34 +00:00
default:
2017-08-31 15:30:17 +00:00
usage:
2016-07-26 19:57:54 +00:00
fprintf(stderr,
"Usage: mlist [-DFPRST] [-X str]\n"
2017-02-14 14:31:09 +00:00
" [-dfprst] [-x str]\n"
" [-N | -n | -C | -c]\n"
" [-i] [dirs...]\n"
2016-07-26 19:57:54 +00:00
);
2016-07-12 15:51:34 +00:00
exit(1);
}
2017-01-26 19:27:26 +00:00
int i;
2017-08-31 15:30:17 +00:00
2016-07-14 16:21:38 +00:00
for (i = 0, flagsum = 0, flagset = 0; (size_t)i < sizeof flags; i++) {
2016-07-12 15:51:34 +00:00
if (flags[i] != 0)
flagset++;
if (flags[i] == 1)
flagsum++;
}
if (optind == argc) {
if (isatty(0))
goto usage;
blaze822_loop(0, 0, listarg);
} else {
for (i = optind; i < argc; i++)
listarg(argv[i]);
}
2016-07-12 15:51:34 +00:00
if (iflag && tdirs > 1)
2016-07-12 17:20:26 +00:00
printf("%6ld unseen %3ld flagged %6ld msg\n",
tunseen, tflagged, tcount);
2016-07-12 17:20:26 +00:00
2016-07-22 16:12:56 +00:00
return 0;
2016-07-12 15:51:34 +00:00
}