V10/cmd/oworm/btree.c
#include <libc.h>
#include <cbt.h>
#undef nfree
#include "worm.h"
#include "sym.h"
#include <sys/types.h>
#include <sys/stat.h>
static char *inonames;
static bfile *bf;
static dirlk(), wormdir();
char *
cbtinit(s, blk, doinodes)
register Superblock *s;
long blk;
{
static char buf[64];
char name[256], buf1[256];
if(s->magic != SMAGIC){
fprint(2, "bad Superblock at %ld\n", blk);
exit(1);
}
numinodes = s->ninodes;
if(doinodes){
inonames = malloc(s->blocksize*(int)NBLKS(s, s->ninochars));
if(inonames == 0){
sprint(buf, "cbtinit: can't malloc %d\n", s->blocksize*(int)NBLKS(s, s->ninochars));
return(buf);
}
if(dirlk(s) == 0)
wormdir(s);
} else
inonames = 0;
return((char *)0);
}
static
dirlk(s)
register Superblock *s;
{
char name[256], buf1[256];
struct stat sbuf;
int fd;
sprint(name, "/usr/worm/dirs/%s", s->vol_id);
sprint(buf1, "%s.I", name);
if(stat(buf1, &sbuf) < 0)
return(0);
if(sbuf.st_mtime < s->ctime)
return(0); /* worm is more recent than disk */
if((bf = bopen(name, 0)) == 0)
return(0);
sprint(buf1, "%s.I", name);
if((fd = open(buf1, 0)) < 0){
fprint(2, "%s: btree but no inodes\n", name);
return(0);
}
if(read(fd, inonames, (int)s->ninochars) != s->ninochars){
fprint(2, "%s: expected %d chars\n", buf1, s->ninochars);
close(fd);
return(0);
}
close(fd);
return(1);
}
static
wormdir(s)
register Superblock *s;
{
char name[256], buf1[256];
sprint(name, "/tmp/worm%d", getpid());
Seek(s, s->binodes);
sprint(buf1, "%s.F", name);
copyout(s, buf1, s->nF, 0, 1);
sprint(buf1, "%s.T", name);
copyout(s, buf1, s->nT, 0, 1);
if(Read(s, inonames, NBLKS(s, s->ninochars)))
return(0);
if((bf = bopen(name, 0)) == 0){
fprint(2, "can't bopen %s", name);
return(0);
}
sprint(buf1, "%s.F", name); unlink(buf1);
sprint(buf1, "%s.T", name); unlink(buf1);
return(1);
}
copyout(s, name, len, overwrite, verbose)
register Superblock *s;
char *name;
long len;
{
int fd, l;
char *buf;
if(access(name, 0) == 0){
if(!overwrite){
fprint(2, "%s already exists!\n", name);
exit(1);
}
if(verbose)
fprint(2, "overwriting %s\n", name);
}
if((fd = creat(name, 0666)) < 0){
perror(name);
exit(1);
}
if((buf = malloc(l = (BIGBLOCK/1024)*s->blocksize)) == 0){
fprint(2, "can't malloc %d\n", l);
exit(1);
}
if(verbose)
print("%s: %d bytes\n", name, len);
while(len >= l){
if(Read(s, buf, NBLKS(s, l)))
exit(1);
if(write(fd, buf, l) != l){
perror(name);
exit(2);
}
len -= l;
}
if(Read(s, buf, NBLKS(s, len)))
exit(2);
if(write(fd, buf, (int)len) != len){
perror(name);
exit(2);
}
free(buf);
}
Inode *
binodefn(s)
char *s;
{
static Inode i;
mbuf key;
if(inonames == 0)
return((Inode *)0);
key.mdata = s;
key.mlen = strlen(s);
if(bseek(bf, key) != 1)
return((Inode *)0);
key.mdata = (char *)&i;
if(bread(bf, (mbuf *)0, &key)){
perror("inode read");
return((Inode *)0);
}
i.name.n = i.name.o+inonames;
return(&i);
}
void
btraverse(fn)
void (*fn)();
{
static Inode i;
mbuf key;
if(inonames == 0)
return;
bfirst(bf);
key.mdata = (char *)&i;
while(bread(bf, (mbuf *)0, &key) == 0){
i.name.n = i.name.o+inonames;
(*fn)(&i);
}
}