diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2017-03-12 17:15:03 +0100 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2017-03-12 17:15:03 +0100 |
commit | 963cfc9a6f6e721f52aa949e6d1af0c3e8dc2ecc (patch) | |
tree | 749b74875dbc49bcf6ed0776648b8f0ef9417407 /sys/src/cmd/upas/fs/remove.c | |
parent | 8177d20fb2709ba9290dfd41308b8e5bee4e00f8 (diff) | |
download | plan9front-963cfc9a6f6e721f52aa949e6d1af0c3e8dc2ecc.tar.xz |
merging erik quanstros nupas
Diffstat (limited to 'sys/src/cmd/upas/fs/remove.c')
-rw-r--r-- | sys/src/cmd/upas/fs/remove.c | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/sys/src/cmd/upas/fs/remove.c b/sys/src/cmd/upas/fs/remove.c new file mode 100644 index 000000000..5bafe8a70 --- /dev/null +++ b/sys/src/cmd/upas/fs/remove.c @@ -0,0 +1,141 @@ +#include "common.h" +#include "dat.h" + +#define deprint(...) /* eprint(__VA_ARGS__) */ + +extern int dirskip(Dir*, uvlong*); + +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; +} + +static 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; +} + +static int +idiotcheck(char *path, Dir *d, int getindex) +{ + uvlong v; + + if(d->mode & DMDIR) + return 0; + if(strncmp(d->name, "L.", 2) == 0) + return 0; + if(getindex && isindex(d)) + return 0; + if(!dirskip(d, &v) || ismbox(path)) + return 0; + return -1; +} + +int +vremove(char *buf) +{ + deprint("rm %s\n", buf); + return remove(buf); +} + +static int +rm(char *dir, int flags, int level) +{ + char buf[Pathlen]; + int i, n, r, fd, isdir, rflag; + 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; + rflag = flags & Rrecur; + for(i = 0; i < n; i++){ + snprint(buf, sizeof buf, "%s/%s", dir, d[i].name); + if(rflag) + r |= rm(buf, flags, level + 1); + if(idiotcheck(buf, d + i, level + rflag) == -1) + continue; + if(vremove(buf) != 0) + r = -1; + } + free(d); + return r; +} + +void +rmidx(char *buf, int flags) +{ + char buf2[Pathlen]; + + snprint(buf2, sizeof buf2, "%s.idx", buf); + vremove(buf2); + if((flags & Rtrunc) == 0){ + snprint(buf2, sizeof buf2, "%s.imp", buf); + vremove(buf2); + } +} + +char* +localremove(Mailbox *mb, int flags) +{ + char *msg, *path; + int r, isdir; + Dir *d; + static char err[2*Pathlen]; + + path = mb->path; + if((d = dirstat(path)) == 0){ + snprint(err, sizeof err, "%s: doesn't exist\n", path); + return 0; + } + isdir = d->mode & DMDIR; + free(d); + msg = "deleting"; + if(flags & Rtrunc) + msg = "truncating"; + deprint("%s: %s\n", msg, path); + + /* must match folder.c:/^openfolder */ + r = rm(path, flags, 0); + if((flags & Rtrunc) == 0) + r = vremove(path); + else if(!isdir) + close(r = open(path, OWRITE|OTRUNC)); + + rmidx(path, flags); + + if(r == -1){ + snprint(err, sizeof err, "%s: can't %s\n", path, msg); + return err; + } + return 0; +} |