static void dowormcopy(void);
static int dodevcopy(void);
struct {
char* icharp;
char* charp;
int error;
int newconf; /* clear before start */
int modconf; /* write back when done */
int nextiter;
int lastiter;
int diriter;
Device* lastcw;
Device* devlist;
} f;
d = ialloc(sizeof(Device), 0);
do {
t = config();
if(d->cat.first == 0)
d->cat.first = t;
else
d->cat.last->link = t;
d->cat.last = t;
if(f.error)
return devnone;
m = *f.charp;
if(c == '(' && m == ')')
d->type = Devmcat;
else if(c == '[' && m == ']')
d->type = Devmlev;
else if(c == '{' && m == '}')
d->type = Devmirr;
} while (d->type == 0);
f.charp++;
if(d->cat.first == d->cat.last)
d = d->cat.first;
return d;
}
static void
map(Device *d)
{
Map *map;
if (d->type != Devwren || d->wren.mapped)
return;
for (map = devmap; map != nil; map = map->next)
if (devcmpr(d, map->fdev) == 0)
break;
if (map == nil)
return;
if (access(map->to, AEXIST) >= 0){
if(chatty)
print("map: mapped wren %Z to existing file %s\n", d, map->to);
d->wren.file = map->to; /* wren -> file mapping */
} else if (map->tdev != nil){
if(chatty)
print("map: mapped wren %Z to dev %Z\n", d, map->tdev);
*d = *map->tdev; /* wren -> wren mapping */
} else
fprint(2, "bad mapping %Z to %s; no such file or device", d, map->to);
d->wren.mapped = 1;
}
Device*
config(void)
{
int c, m;
Device *d;
char *icp, *s, *e;
if(f.error)
return devnone;
d = ialloc(sizeof(Device), 0);
c = *f.charp++;
switch(c) {
default:
cdiag("unknown type", c);
return devnone;
case '(': /* (d+) one or multiple cat */
case '[': /* [d+] one or multiple interleave */
case '{': /* {d+} a mirrored device and optional mirrors */
return config1(c);
for (fsp = fspar; fsp->name != nil; fsp++)
if (strcmp(name, fsp->name) == 0)
return fsp;
return nil;
}
/*
* continue to parse obsolete keywords so that old configurations can
* still work.
*/
void
mergeconf(Iobuf *p)
{
char word[Maxword+1];
char *cp;
Filsys *fs;
Fspar *fsp;
/*
* part 5 -- optionally copy devices or worms
*/
if (copyworm) {
dowormcopy(); /* can return if user quits early */
panic("copyworm bailed out!");
}
if (copydev)
if (dodevcopy() < 0)
panic("copydev failed!");
else
panic("copydev done.");
}
/* an unfinished idea. a non-blocking rawchar() would help. */
static int
userabort(char *msg)
{
USED(msg);
return 0;
}
static int
blockok(Device *d, Off a)
{
Iobuf *p = getbuf(d, a, Brd);
/*
* special case for fake worms only:
* we need to size the inner cw's worm device.
* in particular, we want to avoid copying the fake-worm bitmap
* at the end of the device.
*
* N.B.: for real worms (e.g. cw jukes), we need to compute devsize(cw(juke)),
* *NOT* devsize(juke).
*/
static Device *
wormof(Device *dev)
{
Device *worm = dev, *cw;
/*
* return the number of the highest-numbered block actually written, plus 1.
* 0 indicates an error.
*/
static Devsize
writtensize(Device *worm)
{
Devsize lim = devsize(worm);
Iobuf *p;
/* find worm's last valid block in case "worm" is an (f)worm */
while (lim > 0) {
if (userabort("sizing")) {
lim = 0; /* you lose */
break;
}
--lim;
p = getbuf(worm, lim, Brd);
if (p != 0) { /* actually read one okay? */
putbuf(p);
break;
}
}
if(chatty)
print("limit(%Z) = %lld\n", worm, (Wideoff)lim);
if (lim <= 0)
return 0;
return lim + 1;
}
/* copy worm fs from "main"'s inner worm to "output" */
static void
dowormcopy(void)
{
Filsys *f1, *f2;
Device *fdev, *from, *to = nil;
Iobuf *p;
Off a;
Devsize lim;
/*
* convert file system names into Filsyss and Devices.
*/
f1 = fsstr("main");
if(f1 == nil)
panic("main file system missing");
fdev = f1->dev;
from = wormof(fdev); /* fake worm special */
if (from->type != Devfworm && from->type != Devcw) {
print("main file system is not a worm; copyworm may not do what you want!\n");
print("waiting for 20 seconds...\n");
delay(20000);
}
f2 = fsstr("output");
if(f2 == nil) {
print("no output file system - check only\n\n");
print("reading worm from %Z (worm %Z)\n", fdev, from);
} else {
to = f2->dev;
print("\ncopying worm from %Z (worm %Z) to %Z, starting in 8 seconds\n",
fdev, from, to);
delay(8000);
}
if (userabort("preparing to copy"))
return;
/*
* initialise devices, size them, more sanity checking.
*/
devinit(from);
if (0 && fdev != from) {
devinit(fdev);
print("debugging, sizing %Z first\n", fdev);
writtensize(fdev);
}
lim = writtensize(from);
if(lim == 0)
panic("no blocks to copy on %Z", from);
if (to) {
print("reaming %Z in 8 seconds\n", to);
delay(8000);
if (userabort("preparing to ream & copy"))
return;
devream(to, 0);
devinit(to);
print("copying worm: %lld blocks from %Z to %Z\n",
(Wideoff)lim, from, to);
}
/* can't read to's blocks in case to is a real WORM device */
/*
* Copy written fs blocks, a block at a time (or just read
* if no "output" fs).
*/
for (a = 0; a < lim; a++) {
if (userabort("copy"))
break;
p = getbuf(from, a, Brd);
/*
* if from is a real WORM device, we'll get errors trying to
* read unwritten blocks, but the unwritten blocks need not
* be contiguous.
*/
if (p == 0) {
print("%lld not written yet; can't read\n", (Wideoff)a);
continue;
}
if (to != 0 && devwrite(to, p->addr, p->iobuf) != 0) {
print("out block %lld: write error; bailing",
(Wideoff)a);
break;
}
putbuf(p);
if(a % 20000 == 0)
print("block %lld %T\n", (Wideoff)a, time(nil));
}
/*
* wrap up: sync target, loop
*/
print("copied %lld blocks from %Z to %Z\n", (Wideoff)a, from, to);
sync("wormcopy");
print("looping; reset the machine at any time.\n");
for(;;)
delay(10000); /* await reset */
}
/* copy device from src to dest */
static int
dodevcopy(void)
{
Device *from, *to;
Iobuf *p;
Off a;
Devsize lim, tosize;
/*
* convert config strings into Devices.
*/
from = iconfig(src);
if(f.error || from == nil) {
print("bad src device %s\n", src);
return -1;
}
to = iconfig(dest);
if(f.error || to == nil) {
print("bad dest device %s\n", dest);
return -1;
}
/*
* initialise devices, size them, more sanity checking.
*/
devinit(from);
lim = devsize(from);
if(lim == 0)
panic("no blocks to copy on %Z", from);
devinit(to);
tosize = devsize(to);
if(tosize == 0)
panic("no blocks to copy on %Z", to);
/* use smaller of the device sizes */
if (tosize < lim)
lim = tosize;
print("copy %Z to %Z in 8 seconds\n", from, to);
delay(8000);
if (userabort("preparing to copy"))
return -1;
print("copying dev: %lld blocks from %Z to %Z\n", (Wideoff)lim,
from, to);
/*
* Copy all blocks, a block at a time.
*/
for (a = 0; a < lim; a++) {
if (userabort("copy"))
break;
p = getbuf(from, a, Brd);
/*
* if from is a real WORM device, we'll get errors trying to
* read unwritten blocks, but the unwritten blocks need not
* be contiguous.
*/
if (p == 0) {
fprint(2, "%lld not written yet; can't read\n", (Wideoff)a);
continue;
}
if (to != 0 && devwrite(to, p->addr, p->iobuf) != 0) {
print("out block %lld: write error; bailing",
(Wideoff)a);
break;
}
putbuf(p);
if(a % 20000 == 0)
print("block %lld %T\n", (Wideoff)a, time(nil));
}