V10/cmd/backup.old/wormy.c
#include <fio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
#include "sym.h"
#include "worm.h"
#include "fail.h"
#include "backup.h"
#include <ipc.h>
#include <sys/filio.h>
/*
we are started by wormserver. we talk by a pipe and our end
is fd 0. we look for fd's on 0 and whenever we are done,
we write on our pipe. then the other end will know it is safe to pass on
a new fd.
wormy protocol:
inputfd, outputfd
input:
uname gname\n
filename\n *
bye\n
output:
message\n | F.*\nfile
*/
Superblock s;
char *todir = 0;
int verbose = 0;
int worm = 0;
int dflag = 0;
int Fflag = 0;
char *inp, *outp;
char map[FNAMELEN];
char olddev[FNAMELEN] = "";
char me[FNAMELEN];
char usname[16], gpname[16];
main(argc, argv)
char **argv;
{
register ifd, ofd, n, ok;
char buf[256];
char *dev = argv[1];
char ret[256], goo[256];
struct passfd pfd;
for(n = 1; n < 128; n++)
close(n);
signal(SIGPIPE, SIG_IGN);
chdir("/tmp");
backupdir(map);
failinit(map);
strcpy(me, argv[2]);
s.fd = -1;
for(;;){
if(ioctl(0, FIORCVFD, &pfd) < 0){
/* assume eof */
exit(0);
}
ifd = pfd.fd;
if(ioctl(0, FIORCVFD, &pfd) < 0){
logprint("%s: error in rcvfd, errno=%d\n", me, errno);
exit(0);
}
ofd = pfd.fd;
if(s.fd < 0){
fprint(ofd, "reading worm%s directory (a couple of minutes)\n", dev);
ok = dodev(ofd, dev);
} else{
ok = 1;
}
if(ok)
session(ifd, ofd);
close(ifd);
close(ofd);
write(0, "X", 1);
}
}
dodev(fd, dev)
char *dev;
{
char buf[256];
char *err;
sprint(buf, "/dev/worm%s", dev);
if((s.fd = open(buf, 0)) < 0){
fprint(fd, "couldn't open worm device %s, errno=%d\n", buf, errno);
return(0);
}
if(err = openinode(&s, DO_INODE|SPIN_DOWN)){
fprint(fd, "%s: %s\n", buf, err);
close(s.fd);
s.fd = -1;
return(0);
}
return(1);
}
void
purge(name)
char *name;
{
symdel(name, S_TOGO);
}
long nf, nb;
int ofd;
session(in, out)
{
char buf[256];
long t1, t2;
char *ss, *b;
void do1();
time(&t1);
nb = nf = 0;
ofd = out;
Finit(in, (char *)0);
if((b = Frdline(in)) == 0){
logprint("%s: bad read errno=%d\n", me, errno);
fprint(out, "bad read!\n");
return;
}
if(*b != 'U'){
logprint("bad user line '%s'\n", b);
fprint(out, "bad user line '%s'\n", b);
return;
}
for(ss = ++b; *ss++ != ' ';)
;
ss[-1] = 0;
strcpy(usname, b);
strcpy(gpname, ss);
for(;;){
if((b = Frdline(in)) == 0){
logprint("%s: bad read errno=%d\n", me, errno);
fprint(out, "bad read!\n");
return;
}
if(strcmp(b, "bye") == 0)
break;
ss = strdup(b);
symlook(ss, S_TOGO, (void *)ss);
}
Finit(out, (char *)0);
symtraverse(S_TOGO, do1);
announce((char *)0);
fdump();
Fflush(out);
symtraverse(S_TOGO, purge);
time(&t2);
logprint("%s: %ld files, %ld bytes, %ds\n", me, nf, nb, t2-t1);
}
void
do1(iname)
char *iname;
{
long n;
char buf[1024]; /* must be a multiple of 1024 */
long size;
Inode *i;
struct backfile h;
if((i = inodeof(iname)) == 0){
fail(iname);
return;
}
Seek(&s, i->block);
if(Read(&s, &h, 1)){
Fprint(ofd, "%s: %s read error=%d\n", me, iname, errno);
return;
}
if(!permok(&h)){
Fprint(ofd, "%s: permission denied\n", iname);
return;
}
Fprint(ofd, "FILE\n"); /* nothing wrong */
if(Fwrite(ofd, (char *)&h, (long)sizeof h) != sizeof h){
logprint("%s: hdr write error during %s; bye!\n", me, iname);
return;
}
size = h.sbuf.st_size;
for(n = sizeof buf; size > 0; size -= n){
if(n > size)
n = size;
if(Read(&s, buf, (n+s.blocksize-1)/s.blocksize))
logprint("%s: %s read error=%d\n", me, iname, errno);
if(Fwrite(ofd, buf, n) != n)
return;
}
nf++;
nb += h.sbuf.st_size;
announce(iname);
}
permok(h)
register struct backfile *h;
{
/*logprint("permok(%s:%s, %s:%s, 0%o\n", h->uname, usname, h->gname, gpname, h->sbuf.st_mode&0777);/**/
if(strcmp(h->uname, usname) == 0)
return(h->sbuf.st_mode&0400);
if(strcmp(h->gname, gpname) == 0)
return(h->sbuf.st_mode&0040);
return(h->sbuf.st_mode&0004);
}
fail(s)
char *s;
{
char *os = s;
int n, i;
/* get second last path element */
if(s = strrchr(s, '/')){
while(s > os)
if(*--s == '/'){
s++;
break;
}
} else
s = os;
while(*s){
if((s[0] == 'v') && (s[1] >= '0') && (s[1] <= '9'))
break;
s++;
}
n = atoi(s+1);
for(i = 0; i < nvol; i++)
if(n < vol[i].vol) break;
vol[--i].fail++;
}
fdump()
{
register i;
for(i = 0; i < nvol; i++)
if(vol[i].fail){
Fprint(ofd, "%d file%s need%s disk %s\n", vol[i].fail,
(vol[i].fail==1)?"":"s", (vol[i].fail==1)?"s":"",
vol[i].name);
vol[i].fail = 0;
}
}
char abuf[4096];
int nsofar;
char *np = abuf;
#define NPERLINE 5
announce(s)
char *s;
{
if(s == 0){
if(nsofar){
logprint("%s: retrieved%s\n", me, abuf);
np = abuf;
nsofar = 0;
}
return;
}
*np++ = ' ';
while(*np++ = *s++)
;
np--;
if(++nsofar == NPERLINE)
announce((char *)0);
}