mblaze/mlist.c

262 lines
4.6 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 <sys/syscall.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>
#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;
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
void
list(char *prefix, char *file)
{
if (flagset) {
int sum = 0;
char *f = strstr(file, ":2,");
if (!f)
return;
icount++;
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) {
char *f = strstr(file, ":2,");
if (!f)
return;
imatched++;
if (!flagset)
icount++;
if (!strchr(f, 'S'))
iunseen++;
if (strchr(f, 'F'))
iflagged++;
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
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);
2016-07-18 15:06:41 +00:00
if (nread == -1) {
perror("getdents64");
break;
}
2016-07-12 15:51:34 +00:00
if (nread == 0)
break;
for (bpos = 0; bpos < nread;) {
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)
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;
2016-07-26 19:57:54 +00:00
while ((c = getopt(argc, argv, "PRSTDFprstdfX:x:NnCci")) != -1)
2016-07-12 15:51:34 +00:00
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;
2016-07-22 16:11:38 +00:00
case 'X':
while (*optarg)
flags[(unsigned int)*optarg++] = 1;
break;
case 'x':
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:
2016-07-26 19:57:54 +00:00
usage:
fprintf(stderr,
"Usage: mlist [-DFPRST] [-X str]\n"
" [-dfprst] [-x str]\n"
" [-N | -n | -C | -c]\n"
" [-i] dirs...\n"
);
2016-07-12 15:51:34 +00:00
exit(1);
}
2016-07-26 19:57:54 +00:00
if (optind == argc)
goto usage;
2016-07-12 15:51:34 +00:00
int i;
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++;
}
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;
2016-07-12 17:20:26 +00:00
long gcount = icount;
long gunseen = iunseen;
2016-07-12 17:20:26 +00:00
long gflagged = iflagged;
long gmatched = imatched;
2016-07-12 17:20:26 +00:00
icount = 0;
iunseen = 0;
2016-07-12 17:20:26 +00:00
iflagged = 0;
2016-07-12 15:51:34 +00:00
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]);
2016-07-12 17:20:26 +00:00
if (iflag && imatched)
2016-07-12 17:20:26 +00:00
printf("%6ld unseen %3ld flagged %6ld msg %s\n",
iunseen, iflagged, icount, argv[i]);
2016-07-12 17:20:26 +00:00
icount = gcount;
iunseen = gunseen;
2016-07-12 17:20:26 +00:00
iflagged = gflagged;
imatched = gmatched;
2016-07-12 15:51:34 +00:00
} else if (S_ISREG(st.st_mode)) {
list(0, argv[i]);
}
}
if (iflag && imatched)
2016-07-12 17:20:26 +00:00
printf("%6ld unseen %3ld flagged %6ld msg\n",
iunseen, iflagged, icount);
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
}