|
|
researchv10 Norman
#include <libc.h>
#include "worm.h"
#include "sym.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fio.h>
Inode **inos;
long nino;
int fdT, fdF;
char *inonames;
char *timenow();
char *tmp = "/tmp";
cmp(a, b)
Inode **a, **b;
{
return(strcmp((*a)->name.n, (*b)->name.n));
}
main(argc, argv)
char **argv;
{
Superblock s, news;
char *e;
char *dev = "/dev/worm0";
int c, fd;
char dbname[256];
extern char *optarg;
extern int optind;
void blkfn();
while((c = getopt(argc, argv, "t:f:")) != -1)
switch(c)
{
case 'f': dev = optarg; break;
case 't': tmp = optarg; break;
case '?': usage();
}
dev = mapdev(dev);
if(optind != argc-1)
usage();
sprint(dbname, "%s/cbt%d", tmp, getpid());
fd = dbinit(dbname);
if((s.fd = open(dev, 2)) < 0){
perror(dev);
exit(1);
}
if(e = openinode(&s, DO_INODE|SPIN_DOWN)){
fprint(2, "%s: %s\n", dev, e);
exit(1);
}
if(strcmp(argv[optind], s.vol_id)){
fprint(2, "wanted volid '%s'; got '%s'\n", argv[optind], s.vol_id);
exit(1);
}
if((inos = (Inode **)malloc(sizeof(inos[0])*(int)numinodes)) == 0){
fprint(2, "out of memory (%d inodes, %d bytes)\n", numinodes, sizeof(inos[0])*(int)numinodes);
exit(1);
}
nino = 0;
inodetraverse(blkfn);
fprint(2, "%s: sorting inodes\n", timenow());
qsort((char *)inos, (int)nino, sizeof(inos[0]), cmp);
news = s;
news.ninodes = nino;
creatdb(fd, dbname, &news); /* fills in nF, nT, inochars */
c = NBLKS(&news, news.nF)+NBLKS(&news, news.nT)+NBLKS(&news, news.ninochars);
if(c > news.nfree){
fprint(2, "%s: sorry, not enough blocks; %d+%d+%d>%d\n", news.vol_id,
NBLKS(&news, news.nF), NBLKS(&news, news.nT),
NBLKS(&news, news.ninochars), news.nfree);
exit(1);
}
Seek(&s, news.binodes = s.nextffree);
fdwrite(&s, fdF, (int)news.nF);
fdwrite(&s, fdT, (int)news.nT);
memwrite(&s, inonames, (int)news.ninochars);
/* set up link ptrs so that zeroing block zero undoes btreeing */
s.nfree -= c;
s.nextffree += c;
s.ninodes = 0;
if(e = lkwsb(&s))
fprint(2, "%s\n", e);
news.nextffree = s.nextffree;
news.nfree = s.nfree;
news.myblock = 0;
news.version = VBTREE;
news.nextsb = s.myblock;
time(&news.ctime);
Seek(&s, news.myblock);
free((char *)inos);
e = malloc(news.blocksize);
if(e == 0){
fprint(2, "wbtree: unbelievable malloc fail of %d\n", news.blocksize);
exit(1);
}
memset(e, 0, news.blocksize);
*((Superblock *)e) = news;
Write(&s, e, 1L);
exit(0);
}
usage()
{
fprint(2, "Usage: worm btree [-fdevice] [-ttmpdir] vol_id\n");
exit(2);
}
dbinit(name)
char *name;
{
char buf[256];
struct stat sbuf;
int pid, pip[2];
fprint(2, "%s: init db '%s'\n", timenow(), name);
sprint(buf, "cbt creat %s", name);
if(system(buf))
exit(1);
pipe(pip);
pid = fork();
if(pid < 0){
perror("fork");
exit(1);
}
if(pid){
close(pip[0]);
return(pip[1]);
} else {
close(pip[1]);
dup2(pip[0], 0);
close(pip[0]);
execl("/usr/lib/btree/btbuild", "btbuild", name, 0);
perror("execl");
exit(1);
return(0);
}
}
creatdb(fd, name, s)
char *name;
Superblock *s; /* fills in nF, nT, inochars */
{
char buf[256];
struct stat sbuf;
int status, i;
short n;
char *np;
fprint(2, "%s: creating db '%s'\n", timenow(), name);
inonames = malloc((int)numnamechars+1024);
if(inonames == 0){
sprint(buf, "malloc(%d) namechars failed", numnamechars+1024);
perror(buf);
exit(1);
}
Finit(fd, (char *)0);
np = inonames;
for(i = 0; i < nino; i++){
n = strlen(inos[i]->name.n);
Fwrite(fd, (char *)&n, 2L);
Fwrite(fd, inos[i]->name.n, (long)n);
memcpy(np, inos[i]->name.n, n+1);
inos[i]->name.o = np - inonames;
np += n+1;
n = sizeof(Inode);
Fwrite(fd, (char *)&n, 2L);
Fwrite(fd, (char *)inos[i], (long)n);
}
s->ninochars = np-inonames;
Fflush(fd);
close(fd);
if(wait(&status) < 0){
perror("wbtree: wait");
exit(1);
}
if(status){
fprint(2, "wbtree: bad status %d from btbuild\n", status);
exit(1);
}
sprint(buf, "%s.F", name);
if(((fdF = open(buf, 0)) < 0) || (fstat(fdF, &sbuf) < 0)){
perror(buf);
exit(1);
}
unlink(buf);
s->nF = sbuf.st_size;
sprint(buf, "%s.T", name);
if(((fdT = open(buf, 0)) < 0) || (fstat(fdT, &sbuf) < 0)){
perror(buf);
exit(1);
}
unlink(buf);
s->nT = sbuf.st_size;
fprint(2, "%s: db done\n", timenow());
}
void
blkfn(i)
Inode *i;
{
inos[nino++] = i;
}
fdwrite(s, fd, cnt)
Superblock *s;
{
char b[BIGBLOCK];
int n;
lseek(fd, 0L, 0);
while(cnt >= sizeof b){
n = read(fd, b, sizeof b);
if(n != sizeof b){
perror("short read");
exit(3);
}
Write(s, b, NBLKS(s, sizeof b));
cnt -= sizeof b;
}
if(cnt){
if(read(fd, b, cnt) != cnt){
perror("short read");
exit(4);
}
memset(b+cnt, 0, sizeof b - cnt);
Write(s, b, NBLKS(s, cnt));
}
}
memwrite(s, base, cnt)
Superblock *s;
char *base;
{
int chunk = (BIGBLOCK/1024)*s->blocksize;
while(cnt >= chunk){
Write(s, base, NBLKS(s, chunk));
cnt -= chunk;
base += chunk;
}
if(cnt)
Write(s, base, NBLKS(s, cnt));
}
char *
timenow()
{
long tim;
char *tims;
time(&tim);
tims = ctime(&tim);
tims[19] = 0;
return(tims);
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.