plan9fox/sys/src/cmd/upas/filterkit/mbremove.c
2017-03-12 17:15:03 +01:00

244 lines
3.5 KiB
C

/*
* why did i write this and not use upas/fs?
*/
#include "dat.h"
#include "common.h"
int qflag;
int pflag;
int rflag;
int tflag;
int vflag;
/* must be [0-9]+(\..*)? */
static int
dirskip(Dir *a, uvlong *uv)
{
char *p;
if(a->length == 0)
return 1;
*uv = strtoul(a->name, &p, 0);
if(*uv < 1000000 || *p != '.')
return 1;
*uv = *uv<<8 | strtoul(p+1, &p, 10);
if(*p)
return 1;
return 0;
}
static int
ismbox(char *path)
{
char buf[512];
int fd, r;
fd = open(path, OREAD);
if(fd == -1)
return 0;
r = 1;
if(read(fd, buf, sizeof buf) < 28+5)
r = 0;
else if(strncmp(buf, "From ", 5))
r = 0;
close(fd);
return r;
}
int
isindex(Dir *d)
{
char *p;
p = strrchr(d->name, '.');
if(!p)
return -1;
if(strcmp(p, ".idx") || strcmp(p, ".imp"))
return 1;
return 0;
}
int
idiotcheck(char *path, Dir *d, int getindex)
{
uvlong v;
if(d->mode & DMDIR)
return 0;
if(!strncmp(d->name, "L.", 2))
return 0;
if(getindex && isindex(d))
return 0;
if(!dirskip(d, &v) || ismbox(path))
return 0;
return -1;
}
int
vremove(char *buf)
{
if(vflag)
fprint(2, "rm %s\n", buf);
if(!pflag)
return remove(buf);
return 0;
}
int
rm(char *dir, int level)
{
char buf[Pathlen];
int i, n, r, fd, isdir;
Dir *d;
d = dirstat(dir);
isdir = d->mode & DMDIR;
free(d);
if(!isdir)
return 0;
fd = open(dir, OREAD);
if(fd == -1)
return -1;
n = dirreadall(fd, &d);
close(fd);
r = 0;
for(i = 0; i < n; i++){
snprint(buf, sizeof buf, "%s/%s", dir, d[i].name);
if(rflag)
r |= rm(buf, level+1);
if(idiotcheck(buf, d+i, level+rflag) == -1)
continue;
if(vremove(buf) != 0)
r = -1;
}
free(d);
return r;
}
void
nukeidx(char *buf)
{
char buf2[Pathlen];
snprint(buf2, sizeof buf2, "%s.idx", buf);
vremove(buf2);
snprint(buf2, sizeof buf2, "%s.imp", buf);
vremove(buf2);
}
void
truncidx(char *buf)
{
char buf2[Pathlen];
snprint(buf2, sizeof buf2, "%s.idx", buf);
vremove(buf2);
// snprint(buf2, sizeof buf2, "%s.imp", buf);
// vremove(buf2);
}
static int
removefolder0(char *user, char *folder, char *ftype)
{
char *msg, buf[Pathlen];
int r, isdir;
Dir *d;
assert(folder != 0);
mboxpathbuf(buf, sizeof buf, user, folder);
if((d = dirstat(buf)) == 0){
fprint(2, "%s: %s doesn't exist\n", buf, ftype);
return 0;
}
isdir = d->mode & DMDIR;
free(d);
msg = "deleting";
if(tflag)
msg = "truncating";
fprint(2, "%s %s: %s\n", msg, ftype, buf);
/* must match folder.c:/^openfolder */
r = rm(buf, 0);
if(!tflag)
r = vremove(buf);
else if(!isdir)
r = open(buf, OWRITE|OTRUNC);
if(tflag)
truncidx(buf);
else
nukeidx(buf);
if(r == -1){
fprint(2, "%s: can't %s %s\n", buf, msg, ftype);
return -1;
}
close(r);
return 0;
}
int
removefolder(char *user, char *folder)
{
return removefolder0(user, folder, "folder");
}
int
removembox(char *user, char *mbox)
{
char buf[Pathlen];
if(mbox == 0)
snprint(buf, sizeof buf, "mbox");
else
snprint(buf, sizeof buf, "%s/mbox", mbox);
return removefolder0(user, buf, "mbox");
}
void
usage(void)
{
fprint(2, "usage: mbremove [-fpqrtv] ...\n");
exits("usage");
}
void
main(int argc, char **argv)
{
int r;
int (*f)(char*, char*);
f = removembox;
ARGBEGIN{
case 'f':
f = removefolder;
break;
case 'p':
pflag++;
break;
case 'q':
qflag++;
close(2);
open("/dev/null", OWRITE);
break;
case 'r':
rflag++;
break;
case 't':
tflag++;
break;
case 'v':
vflag++;
break;
default:
usage();
}ARGEND
r = 0;
for(; *argv; argv++)
r |= f(getuser(), *argv);
if(r)
exits("errors");
exits("");
}