1*01a344a2SDavid du Colombier #include "all.h"
2*01a344a2SDavid du Colombier #include "io.h"
3*01a344a2SDavid du Colombier
4*01a344a2SDavid du Colombier static void dowormcopy(void);
5*01a344a2SDavid du Colombier static int dodevcopy(void);
6*01a344a2SDavid du Colombier
7*01a344a2SDavid du Colombier struct {
8*01a344a2SDavid du Colombier char* icharp;
9*01a344a2SDavid du Colombier char* charp;
10*01a344a2SDavid du Colombier int error;
11*01a344a2SDavid du Colombier int newconf; /* clear before start */
12*01a344a2SDavid du Colombier int modconf; /* write back when done */
13*01a344a2SDavid du Colombier int nextiter;
14*01a344a2SDavid du Colombier int lastiter;
15*01a344a2SDavid du Colombier int diriter;
16*01a344a2SDavid du Colombier Device* lastcw;
17*01a344a2SDavid du Colombier Device* devlist;
18*01a344a2SDavid du Colombier } f;
19*01a344a2SDavid du Colombier
20*01a344a2SDavid du Colombier static Device* confdev;
21*01a344a2SDavid du Colombier static int copyworm = 0, copydev = 0;
22*01a344a2SDavid du Colombier static char *src, *dest;
23*01a344a2SDavid du Colombier
24*01a344a2SDavid du Colombier static int resetparams;
25*01a344a2SDavid du Colombier
26*01a344a2SDavid du Colombier Fspar fspar[] = {
27*01a344a2SDavid du Colombier { "blocksize", RBUFSIZE, },
28*01a344a2SDavid du Colombier { "daddrbits", sizeof(Off)*8, },
29*01a344a2SDavid du Colombier { "indirblks", NIBLOCK, },
30*01a344a2SDavid du Colombier { "dirblks", NDBLOCK, },
31*01a344a2SDavid du Colombier { "namelen", NAMELEN, },
32*01a344a2SDavid du Colombier { nil, 0, },
33*01a344a2SDavid du Colombier };
34*01a344a2SDavid du Colombier
35*01a344a2SDavid du Colombier int
devcmpr(Device * d1,Device * d2)36*01a344a2SDavid du Colombier devcmpr(Device *d1, Device *d2)
37*01a344a2SDavid du Colombier {
38*01a344a2SDavid du Colombier while (d1 != d2) {
39*01a344a2SDavid du Colombier if(d1 == nil || d2 == nil || d1->type != d2->type)
40*01a344a2SDavid du Colombier return 1;
41*01a344a2SDavid du Colombier
42*01a344a2SDavid du Colombier switch(d1->type) {
43*01a344a2SDavid du Colombier default:
44*01a344a2SDavid du Colombier print("can't compare dev: %Z\n", d1);
45*01a344a2SDavid du Colombier panic("devcmp");
46*01a344a2SDavid du Colombier return 1;
47*01a344a2SDavid du Colombier
48*01a344a2SDavid du Colombier case Devmcat:
49*01a344a2SDavid du Colombier case Devmlev:
50*01a344a2SDavid du Colombier case Devmirr:
51*01a344a2SDavid du Colombier d1 = d1->cat.first;
52*01a344a2SDavid du Colombier d2 = d2->cat.first;
53*01a344a2SDavid du Colombier while(d1 && d2) {
54*01a344a2SDavid du Colombier if(devcmpr(d1, d2))
55*01a344a2SDavid du Colombier return 1;
56*01a344a2SDavid du Colombier d1 = d1->link;
57*01a344a2SDavid du Colombier d2 = d2->link;
58*01a344a2SDavid du Colombier }
59*01a344a2SDavid du Colombier break;
60*01a344a2SDavid du Colombier
61*01a344a2SDavid du Colombier case Devnone:
62*01a344a2SDavid du Colombier return 0;
63*01a344a2SDavid du Colombier
64*01a344a2SDavid du Colombier case Devro:
65*01a344a2SDavid du Colombier d1 = d1->ro.parent;
66*01a344a2SDavid du Colombier d2 = d2->ro.parent;
67*01a344a2SDavid du Colombier break;
68*01a344a2SDavid du Colombier
69*01a344a2SDavid du Colombier case Devjuke:
70*01a344a2SDavid du Colombier case Devcw:
71*01a344a2SDavid du Colombier if(devcmpr(d1->cw.c, d2->cw.c))
72*01a344a2SDavid du Colombier return 1;
73*01a344a2SDavid du Colombier d1 = d1->cw.w;
74*01a344a2SDavid du Colombier d2 = d2->cw.w;
75*01a344a2SDavid du Colombier break;
76*01a344a2SDavid du Colombier
77*01a344a2SDavid du Colombier case Devfworm:
78*01a344a2SDavid du Colombier d1 = d1->fw.fw;
79*01a344a2SDavid du Colombier d2 = d2->fw.fw;
80*01a344a2SDavid du Colombier break;
81*01a344a2SDavid du Colombier
82*01a344a2SDavid du Colombier case Devwren:
83*01a344a2SDavid du Colombier case Devworm:
84*01a344a2SDavid du Colombier case Devlworm:
85*01a344a2SDavid du Colombier if(d1->wren.ctrl == d2->wren.ctrl)
86*01a344a2SDavid du Colombier if(d1->wren.targ == d2->wren.targ)
87*01a344a2SDavid du Colombier if(d1->wren.lun == d2->wren.lun)
88*01a344a2SDavid du Colombier return 0;
89*01a344a2SDavid du Colombier return 1;
90*01a344a2SDavid du Colombier
91*01a344a2SDavid du Colombier case Devpart:
92*01a344a2SDavid du Colombier if(d1->part.base == d2->part.base)
93*01a344a2SDavid du Colombier if(d1->part.size == d2->part.size) {
94*01a344a2SDavid du Colombier d1 = d1->part.d;
95*01a344a2SDavid du Colombier d2 = d2->part.d;
96*01a344a2SDavid du Colombier break;
97*01a344a2SDavid du Colombier }
98*01a344a2SDavid du Colombier return 1;
99*01a344a2SDavid du Colombier }
100*01a344a2SDavid du Colombier }
101*01a344a2SDavid du Colombier return 0;
102*01a344a2SDavid du Colombier }
103*01a344a2SDavid du Colombier
104*01a344a2SDavid du Colombier void
cdiag(char * s,int c1)105*01a344a2SDavid du Colombier cdiag(char *s, int c1)
106*01a344a2SDavid du Colombier {
107*01a344a2SDavid du Colombier
108*01a344a2SDavid du Colombier f.charp--;
109*01a344a2SDavid du Colombier if(f.error == 0) {
110*01a344a2SDavid du Colombier print("config diag: %s -- <%c>\n", s, c1);
111*01a344a2SDavid du Colombier f.error = 1;
112*01a344a2SDavid du Colombier }
113*01a344a2SDavid du Colombier }
114*01a344a2SDavid du Colombier
115*01a344a2SDavid du Colombier int
cnumb(void)116*01a344a2SDavid du Colombier cnumb(void)
117*01a344a2SDavid du Colombier {
118*01a344a2SDavid du Colombier int c, n;
119*01a344a2SDavid du Colombier
120*01a344a2SDavid du Colombier c = *f.charp++;
121*01a344a2SDavid du Colombier if(c == '<') {
122*01a344a2SDavid du Colombier n = f.nextiter;
123*01a344a2SDavid du Colombier if(n >= 0) {
124*01a344a2SDavid du Colombier f.nextiter = n+f.diriter;
125*01a344a2SDavid du Colombier if(n == f.lastiter) {
126*01a344a2SDavid du Colombier f.nextiter = -1;
127*01a344a2SDavid du Colombier f.lastiter = -1;
128*01a344a2SDavid du Colombier }
129*01a344a2SDavid du Colombier do {
130*01a344a2SDavid du Colombier c = *f.charp++;
131*01a344a2SDavid du Colombier } while (c != '>');
132*01a344a2SDavid du Colombier return n;
133*01a344a2SDavid du Colombier }
134*01a344a2SDavid du Colombier n = cnumb();
135*01a344a2SDavid du Colombier if(*f.charp++ != '-') {
136*01a344a2SDavid du Colombier cdiag("- expected", f.charp[-1]);
137*01a344a2SDavid du Colombier return 0;
138*01a344a2SDavid du Colombier }
139*01a344a2SDavid du Colombier c = cnumb();
140*01a344a2SDavid du Colombier if(*f.charp++ != '>') {
141*01a344a2SDavid du Colombier cdiag("> expected", f.charp[-1]);
142*01a344a2SDavid du Colombier return 0;
143*01a344a2SDavid du Colombier }
144*01a344a2SDavid du Colombier f.lastiter = c;
145*01a344a2SDavid du Colombier f.diriter = 1;
146*01a344a2SDavid du Colombier if(n > c)
147*01a344a2SDavid du Colombier f.diriter = -1;
148*01a344a2SDavid du Colombier f.nextiter = n+f.diriter;
149*01a344a2SDavid du Colombier return n;
150*01a344a2SDavid du Colombier }
151*01a344a2SDavid du Colombier if(!isascii(c) || !isdigit(c)) {
152*01a344a2SDavid du Colombier cdiag("number expected", c);
153*01a344a2SDavid du Colombier return 0;
154*01a344a2SDavid du Colombier }
155*01a344a2SDavid du Colombier n = 0;
156*01a344a2SDavid du Colombier while(isascii(c) && isdigit(c)) {
157*01a344a2SDavid du Colombier n = n*10 + (c-'0');
158*01a344a2SDavid du Colombier c = *f.charp++;
159*01a344a2SDavid du Colombier }
160*01a344a2SDavid du Colombier f.charp--;
161*01a344a2SDavid du Colombier return n;
162*01a344a2SDavid du Colombier }
163*01a344a2SDavid du Colombier
164*01a344a2SDavid du Colombier Device*
config1(int c)165*01a344a2SDavid du Colombier config1(int c)
166*01a344a2SDavid du Colombier {
167*01a344a2SDavid du Colombier Device *d, *t;
168*01a344a2SDavid du Colombier int m;
169*01a344a2SDavid du Colombier
170*01a344a2SDavid du Colombier d = malloc(sizeof(Device));
171*01a344a2SDavid du Colombier do {
172*01a344a2SDavid du Colombier t = config();
173*01a344a2SDavid du Colombier if(d->cat.first == 0)
174*01a344a2SDavid du Colombier d->cat.first = t;
175*01a344a2SDavid du Colombier else
176*01a344a2SDavid du Colombier d->cat.last->link = t;
177*01a344a2SDavid du Colombier d->cat.last = t;
178*01a344a2SDavid du Colombier if(f.error)
179*01a344a2SDavid du Colombier return devnone;
180*01a344a2SDavid du Colombier m = *f.charp;
181*01a344a2SDavid du Colombier if(c == '(' && m == ')')
182*01a344a2SDavid du Colombier d->type = Devmcat;
183*01a344a2SDavid du Colombier else if(c == '[' && m == ']')
184*01a344a2SDavid du Colombier d->type = Devmlev;
185*01a344a2SDavid du Colombier else if(c == '{' && m == '}')
186*01a344a2SDavid du Colombier d->type = Devmirr;
187*01a344a2SDavid du Colombier } while (d->type == 0);
188*01a344a2SDavid du Colombier f.charp++;
189*01a344a2SDavid du Colombier if(d->cat.first == d->cat.last)
190*01a344a2SDavid du Colombier d = d->cat.first;
191*01a344a2SDavid du Colombier return d;
192*01a344a2SDavid du Colombier }
193*01a344a2SDavid du Colombier
194*01a344a2SDavid du Colombier static void
map(Device * d)195*01a344a2SDavid du Colombier map(Device *d)
196*01a344a2SDavid du Colombier {
197*01a344a2SDavid du Colombier Map *map;
198*01a344a2SDavid du Colombier
199*01a344a2SDavid du Colombier if (d->type != Devwren || d->wren.mapped)
200*01a344a2SDavid du Colombier return;
201*01a344a2SDavid du Colombier for (map = devmap; map != nil; map = map->next)
202*01a344a2SDavid du Colombier if (devcmpr(d, map->fdev) == 0)
203*01a344a2SDavid du Colombier break;
204*01a344a2SDavid du Colombier if (map == nil)
205*01a344a2SDavid du Colombier return;
206*01a344a2SDavid du Colombier if (access(map->to, AEXIST) >= 0)
207*01a344a2SDavid du Colombier { print("map: mapped wren %Z to existing file %s\n", d, map->to); // DEBUG
208*01a344a2SDavid du Colombier d->wren.file = map->to; /* wren -> file mapping */
209*01a344a2SDavid du Colombier }
210*01a344a2SDavid du Colombier else if (map->tdev != nil)
211*01a344a2SDavid du Colombier { print("map: mapped wren %Z to dev %Z\n", d, map->tdev); // DEBUG
212*01a344a2SDavid du Colombier *d = *map->tdev; /* wren -> wren mapping */
213*01a344a2SDavid du Colombier }
214*01a344a2SDavid du Colombier else
215*01a344a2SDavid du Colombier print("bad mapping %Z to %s; no such file or device",
216*01a344a2SDavid du Colombier d, map->to);
217*01a344a2SDavid du Colombier d->wren.mapped = 1;
218*01a344a2SDavid du Colombier }
219*01a344a2SDavid du Colombier
220*01a344a2SDavid du Colombier Device*
config(void)221*01a344a2SDavid du Colombier config(void)
222*01a344a2SDavid du Colombier {
223*01a344a2SDavid du Colombier int c, m;
224*01a344a2SDavid du Colombier Device *d;
225*01a344a2SDavid du Colombier char *icp;
226*01a344a2SDavid du Colombier
227*01a344a2SDavid du Colombier if(f.error)
228*01a344a2SDavid du Colombier return devnone;
229*01a344a2SDavid du Colombier d = malloc(sizeof(Device));
230*01a344a2SDavid du Colombier
231*01a344a2SDavid du Colombier c = *f.charp++;
232*01a344a2SDavid du Colombier switch(c) {
233*01a344a2SDavid du Colombier default:
234*01a344a2SDavid du Colombier cdiag("unknown type", c);
235*01a344a2SDavid du Colombier return devnone;
236*01a344a2SDavid du Colombier
237*01a344a2SDavid du Colombier case '(': /* (d+) one or multiple cat */
238*01a344a2SDavid du Colombier case '[': /* [d+] one or multiple interleave */
239*01a344a2SDavid du Colombier case '{': /* {d+} a mirrored device and optional mirrors */
240*01a344a2SDavid du Colombier return config1(c);
241*01a344a2SDavid du Colombier
242*01a344a2SDavid du Colombier case 'f': /* fd fake worm */
243*01a344a2SDavid du Colombier d->type = Devfworm;
244*01a344a2SDavid du Colombier d->fw.fw = config();
245*01a344a2SDavid du Colombier break;
246*01a344a2SDavid du Colombier
247*01a344a2SDavid du Colombier case 'n':
248*01a344a2SDavid du Colombier d->type = Devnone;
249*01a344a2SDavid du Colombier break;
250*01a344a2SDavid du Colombier
251*01a344a2SDavid du Colombier case 'w': /* w[#.]#[.#] wren [ctrl] unit [lun] */
252*01a344a2SDavid du Colombier case 'r': /* r# worm side */
253*01a344a2SDavid du Colombier case 'l': /* l# labelled-worm side */
254*01a344a2SDavid du Colombier icp = f.charp;
255*01a344a2SDavid du Colombier d->type = Devwren;
256*01a344a2SDavid du Colombier d->wren.ctrl = 0;
257*01a344a2SDavid du Colombier d->wren.targ = cnumb();
258*01a344a2SDavid du Colombier d->wren.lun = 0;
259*01a344a2SDavid du Colombier m = *f.charp;
260*01a344a2SDavid du Colombier if(m == '.') {
261*01a344a2SDavid du Colombier f.charp++;
262*01a344a2SDavid du Colombier d->wren.lun = cnumb();
263*01a344a2SDavid du Colombier m = *f.charp;
264*01a344a2SDavid du Colombier if(m == '.') {
265*01a344a2SDavid du Colombier f.charp++;
266*01a344a2SDavid du Colombier d->wren.ctrl = d->wren.targ;
267*01a344a2SDavid du Colombier d->wren.targ = d->wren.lun;
268*01a344a2SDavid du Colombier d->wren.lun = cnumb();
269*01a344a2SDavid du Colombier }
270*01a344a2SDavid du Colombier }
271*01a344a2SDavid du Colombier if(f.nextiter >= 0)
272*01a344a2SDavid du Colombier f.charp = icp-1;
273*01a344a2SDavid du Colombier if(c == 'r') /* worms are virtual and not uniqued */
274*01a344a2SDavid du Colombier d->type = Devworm;
275*01a344a2SDavid du Colombier else if(c == 'l')
276*01a344a2SDavid du Colombier d->type = Devlworm;
277*01a344a2SDavid du Colombier else
278*01a344a2SDavid du Colombier map(d); /* subject wrens to optional mapping */
279*01a344a2SDavid du Colombier break;
280*01a344a2SDavid du Colombier
281*01a344a2SDavid du Colombier case 'o': /* o ro part of last cw */
282*01a344a2SDavid du Colombier if(f.lastcw == 0) {
283*01a344a2SDavid du Colombier cdiag("no cw to match", c);
284*01a344a2SDavid du Colombier return devnone;
285*01a344a2SDavid du Colombier }
286*01a344a2SDavid du Colombier return f.lastcw->cw.ro;
287*01a344a2SDavid du Colombier
288*01a344a2SDavid du Colombier case 'j': /* DD jukebox */
289*01a344a2SDavid du Colombier d->type = Devjuke;
290*01a344a2SDavid du Colombier d->j.j = config();
291*01a344a2SDavid du Colombier d->j.m = config();
292*01a344a2SDavid du Colombier break;
293*01a344a2SDavid du Colombier
294*01a344a2SDavid du Colombier case 'c': /* cache/worm */
295*01a344a2SDavid du Colombier d->type = Devcw;
296*01a344a2SDavid du Colombier d->cw.c = config();
297*01a344a2SDavid du Colombier d->cw.w = config();
298*01a344a2SDavid du Colombier d->cw.ro = malloc(sizeof(Device));
299*01a344a2SDavid du Colombier d->cw.ro->type = Devro;
300*01a344a2SDavid du Colombier d->cw.ro->ro.parent = d;
301*01a344a2SDavid du Colombier f.lastcw = d;
302*01a344a2SDavid du Colombier break;
303*01a344a2SDavid du Colombier
304*01a344a2SDavid du Colombier case 'p': /* pd#.# partition base% size% */
305*01a344a2SDavid du Colombier d->type = Devpart;
306*01a344a2SDavid du Colombier d->part.d = config();
307*01a344a2SDavid du Colombier d->part.base = cnumb();
308*01a344a2SDavid du Colombier c = *f.charp++;
309*01a344a2SDavid du Colombier if(c != '.')
310*01a344a2SDavid du Colombier cdiag("dot expected", c);
311*01a344a2SDavid du Colombier d->part.size = cnumb();
312*01a344a2SDavid du Colombier break;
313*01a344a2SDavid du Colombier
314*01a344a2SDavid du Colombier case 'x': /* xD swab a device's metadata */
315*01a344a2SDavid du Colombier d->type = Devswab;
316*01a344a2SDavid du Colombier d->swab.d = config();
317*01a344a2SDavid du Colombier break;
318*01a344a2SDavid du Colombier }
319*01a344a2SDavid du Colombier d->dlink = f.devlist;
320*01a344a2SDavid du Colombier f.devlist = d;
321*01a344a2SDavid du Colombier return d;
322*01a344a2SDavid du Colombier }
323*01a344a2SDavid du Colombier
324*01a344a2SDavid du Colombier Device*
iconfig(char * s)325*01a344a2SDavid du Colombier iconfig(char *s)
326*01a344a2SDavid du Colombier {
327*01a344a2SDavid du Colombier Device *d;
328*01a344a2SDavid du Colombier
329*01a344a2SDavid du Colombier f.nextiter = -1;
330*01a344a2SDavid du Colombier f.lastiter = -1;
331*01a344a2SDavid du Colombier f.error = 0;
332*01a344a2SDavid du Colombier f.icharp = s;
333*01a344a2SDavid du Colombier f.charp = f.icharp;
334*01a344a2SDavid du Colombier d = config();
335*01a344a2SDavid du Colombier if(*f.charp) {
336*01a344a2SDavid du Colombier cdiag("junk on end", *f.charp);
337*01a344a2SDavid du Colombier f.error = 1;
338*01a344a2SDavid du Colombier }
339*01a344a2SDavid du Colombier return d;
340*01a344a2SDavid du Colombier }
341*01a344a2SDavid du Colombier
342*01a344a2SDavid du Colombier int
testconfig(char * s)343*01a344a2SDavid du Colombier testconfig(char *s)
344*01a344a2SDavid du Colombier {
345*01a344a2SDavid du Colombier iconfig(s);
346*01a344a2SDavid du Colombier return f.error;
347*01a344a2SDavid du Colombier }
348*01a344a2SDavid du Colombier
349*01a344a2SDavid du Colombier /*
350*01a344a2SDavid du Colombier * if b is a prefix of a, return 0.
351*01a344a2SDavid du Colombier */
352*01a344a2SDavid du Colombier int
astrcmp(char * a,char * b)353*01a344a2SDavid du Colombier astrcmp(char *a, char *b)
354*01a344a2SDavid du Colombier {
355*01a344a2SDavid du Colombier int n, c;
356*01a344a2SDavid du Colombier
357*01a344a2SDavid du Colombier n = strlen(b);
358*01a344a2SDavid du Colombier if(memcmp(a, b, n) != 0)
359*01a344a2SDavid du Colombier return 1;
360*01a344a2SDavid du Colombier c = a[n];
361*01a344a2SDavid du Colombier if(c == '\0')
362*01a344a2SDavid du Colombier return 0;
363*01a344a2SDavid du Colombier if(a[n+1])
364*01a344a2SDavid du Colombier return 1;
365*01a344a2SDavid du Colombier if(isascii(c) && isdigit(c))
366*01a344a2SDavid du Colombier return 0;
367*01a344a2SDavid du Colombier return 1;
368*01a344a2SDavid du Colombier }
369*01a344a2SDavid du Colombier
370*01a344a2SDavid du Colombier static Fspar *
getpar(char * name)371*01a344a2SDavid du Colombier getpar(char *name)
372*01a344a2SDavid du Colombier {
373*01a344a2SDavid du Colombier Fspar *fsp;
374*01a344a2SDavid du Colombier
375*01a344a2SDavid du Colombier for (fsp = fspar; fsp->name != nil; fsp++)
376*01a344a2SDavid du Colombier if (strcmp(name, fsp->name) == 0)
377*01a344a2SDavid du Colombier return fsp;
378*01a344a2SDavid du Colombier return nil;
379*01a344a2SDavid du Colombier }
380*01a344a2SDavid du Colombier
381*01a344a2SDavid du Colombier /*
382*01a344a2SDavid du Colombier * continue to parse obsolete keywords so that old configurations can
383*01a344a2SDavid du Colombier * still work.
384*01a344a2SDavid du Colombier */
385*01a344a2SDavid du Colombier void
mergeconf(Iobuf * p)386*01a344a2SDavid du Colombier mergeconf(Iobuf *p)
387*01a344a2SDavid du Colombier {
388*01a344a2SDavid du Colombier char word[Maxword+1];
389*01a344a2SDavid du Colombier char *cp;
390*01a344a2SDavid du Colombier Filsys *fs;
391*01a344a2SDavid du Colombier Fspar *fsp;
392*01a344a2SDavid du Colombier
393*01a344a2SDavid du Colombier for (cp = p->iobuf; *cp != '\0'; cp++) {
394*01a344a2SDavid du Colombier cp = getwrd(word, cp);
395*01a344a2SDavid du Colombier if(word[0] == '\0')
396*01a344a2SDavid du Colombier break;
397*01a344a2SDavid du Colombier else if (word[0] == '#')
398*01a344a2SDavid du Colombier while (*cp != '\n' && *cp != '\0')
399*01a344a2SDavid du Colombier cp++;
400*01a344a2SDavid du Colombier else if(strcmp(word, "service") == 0) {
401*01a344a2SDavid du Colombier cp = getwrd(word, cp);
402*01a344a2SDavid du Colombier if(service[0] == 0)
403*01a344a2SDavid du Colombier strncpy(service, word, sizeof service);
404*01a344a2SDavid du Colombier } else if(strcmp(word, "ipauth") == 0) /* obsolete */
405*01a344a2SDavid du Colombier cp = getwrd(word, cp);
406*01a344a2SDavid du Colombier else if(astrcmp(word, "ip") == 0) /* obsolete */
407*01a344a2SDavid du Colombier cp = getwrd(word, cp);
408*01a344a2SDavid du Colombier else if(astrcmp(word, "ipgw") == 0) /* obsolete */
409*01a344a2SDavid du Colombier cp = getwrd(word, cp);
410*01a344a2SDavid du Colombier else if(astrcmp(word, "ipsntp") == 0) /* obsolete */
411*01a344a2SDavid du Colombier cp = getwrd(word, cp);
412*01a344a2SDavid du Colombier else if(astrcmp(word, "ipmask") == 0) /* obsolete */
413*01a344a2SDavid du Colombier cp = getwrd(word, cp);
414*01a344a2SDavid du Colombier else if(strcmp(word, "filsys") == 0) {
415*01a344a2SDavid du Colombier cp = getwrd(word, cp);
416*01a344a2SDavid du Colombier for(fs = filsys; fs < filsys + nelem(filsys) - 1 &&
417*01a344a2SDavid du Colombier fs->name; fs++)
418*01a344a2SDavid du Colombier if(strcmp(fs->name, word) == 0)
419*01a344a2SDavid du Colombier break;
420*01a344a2SDavid du Colombier if (fs >= filsys + nelem(filsys) - 1)
421*01a344a2SDavid du Colombier panic("out of filsys structures");
422*01a344a2SDavid du Colombier if (fs->name && strcmp(fs->name, word) == 0 &&
423*01a344a2SDavid du Colombier fs->flags & FEDIT)
424*01a344a2SDavid du Colombier cp = getwrd(word, cp); /* swallow conf */
425*01a344a2SDavid du Colombier else {
426*01a344a2SDavid du Colombier fs->name = strdup(word);
427*01a344a2SDavid du Colombier cp = getwrd(word, cp);
428*01a344a2SDavid du Colombier if (word[0] == '\0')
429*01a344a2SDavid du Colombier fs->conf = nil;
430*01a344a2SDavid du Colombier else
431*01a344a2SDavid du Colombier fs->conf = strdup(word);
432*01a344a2SDavid du Colombier }
433*01a344a2SDavid du Colombier } else if ((fsp = getpar(word)) != nil) {
434*01a344a2SDavid du Colombier cp = getwrd(word, cp);
435*01a344a2SDavid du Colombier if (!isascii(word[0]) || !isdigit(word[0]))
436*01a344a2SDavid du Colombier print("bad %s value: %s", fsp->name, word);
437*01a344a2SDavid du Colombier else
438*01a344a2SDavid du Colombier fsp->declared = atol(word);
439*01a344a2SDavid du Colombier } else {
440*01a344a2SDavid du Colombier putbuf(p);
441*01a344a2SDavid du Colombier panic("unknown keyword in config block: %s", word);
442*01a344a2SDavid du Colombier }
443*01a344a2SDavid du Colombier
444*01a344a2SDavid du Colombier if(*cp != '\n') {
445*01a344a2SDavid du Colombier putbuf(p);
446*01a344a2SDavid du Colombier panic("syntax error in config block at `%s'", word);
447*01a344a2SDavid du Colombier }
448*01a344a2SDavid du Colombier }
449*01a344a2SDavid du Colombier }
450*01a344a2SDavid du Colombier
451*01a344a2SDavid du Colombier void
cmd_printconf(int,char * [])452*01a344a2SDavid du Colombier cmd_printconf(int, char *[])
453*01a344a2SDavid du Colombier {
454*01a344a2SDavid du Colombier char *p, *s;
455*01a344a2SDavid du Colombier Iobuf *iob;
456*01a344a2SDavid du Colombier
457*01a344a2SDavid du Colombier iob = getbuf(confdev, 0, Brd);
458*01a344a2SDavid du Colombier if(iob == nil)
459*01a344a2SDavid du Colombier return;
460*01a344a2SDavid du Colombier if(checktag(iob, Tconfig, 0)){
461*01a344a2SDavid du Colombier putbuf(iob);
462*01a344a2SDavid du Colombier return;
463*01a344a2SDavid du Colombier }
464*01a344a2SDavid du Colombier
465*01a344a2SDavid du Colombier print("config %s\n", nvrgetconfig());
466*01a344a2SDavid du Colombier for(s = p = iob->iobuf; *p != 0 && p < iob->iobuf+BUFSIZE; ){
467*01a344a2SDavid du Colombier if(*p++ != '\n')
468*01a344a2SDavid du Colombier continue;
469*01a344a2SDavid du Colombier if (strncmp(s, "ip", 2) != 0) /* don't print obsolete cmds */
470*01a344a2SDavid du Colombier print("%.*s", (int)(p-s), s);
471*01a344a2SDavid du Colombier s = p;
472*01a344a2SDavid du Colombier }
473*01a344a2SDavid du Colombier if(p != s)
474*01a344a2SDavid du Colombier print("%.*s", (int)(p-s), s);
475*01a344a2SDavid du Colombier print("end\n");
476*01a344a2SDavid du Colombier
477*01a344a2SDavid du Colombier putbuf(iob);
478*01a344a2SDavid du Colombier }
479*01a344a2SDavid du Colombier
480*01a344a2SDavid du Colombier void
sysinit(void)481*01a344a2SDavid du Colombier sysinit(void)
482*01a344a2SDavid du Colombier {
483*01a344a2SDavid du Colombier int error;
484*01a344a2SDavid du Colombier char *cp, *ep;
485*01a344a2SDavid du Colombier Device *d;
486*01a344a2SDavid du Colombier Filsys *fs;
487*01a344a2SDavid du Colombier Fspar *fsp;
488*01a344a2SDavid du Colombier Iobuf *p;
489*01a344a2SDavid du Colombier
490*01a344a2SDavid du Colombier cons.chan = fs_chaninit(Devcon, 1, 0);
491*01a344a2SDavid du Colombier
492*01a344a2SDavid du Colombier start:
493*01a344a2SDavid du Colombier /*
494*01a344a2SDavid du Colombier * part 1 -- read the config file
495*01a344a2SDavid du Colombier */
496*01a344a2SDavid du Colombier devnone = iconfig("n");
497*01a344a2SDavid du Colombier
498*01a344a2SDavid du Colombier cp = nvrgetconfig();
499*01a344a2SDavid du Colombier print("config %s\n", cp);
500*01a344a2SDavid du Colombier
501*01a344a2SDavid du Colombier confdev = d = iconfig(cp);
502*01a344a2SDavid du Colombier devinit(d);
503*01a344a2SDavid du Colombier if(f.newconf) {
504*01a344a2SDavid du Colombier p = getbuf(d, 0, Bmod);
505*01a344a2SDavid du Colombier memset(p->iobuf, 0, RBUFSIZE);
506*01a344a2SDavid du Colombier settag(p, Tconfig, 0);
507*01a344a2SDavid du Colombier } else
508*01a344a2SDavid du Colombier p = getbuf(d, 0, Brd|Bmod);
509*01a344a2SDavid du Colombier if(!p || checktag(p, Tconfig, 0))
510*01a344a2SDavid du Colombier panic("config io");
511*01a344a2SDavid du Colombier
512*01a344a2SDavid du Colombier mergeconf(p);
513*01a344a2SDavid du Colombier
514*01a344a2SDavid du Colombier if (resetparams) {
515*01a344a2SDavid du Colombier for (fsp = fspar; fsp->name != nil; fsp++)
516*01a344a2SDavid du Colombier fsp->declared = 0;
517*01a344a2SDavid du Colombier resetparams = 0;
518*01a344a2SDavid du Colombier }
519*01a344a2SDavid du Colombier
520*01a344a2SDavid du Colombier for (fsp = fspar; fsp->name != nil; fsp++) {
521*01a344a2SDavid du Colombier /* supply defaults from this cwfs instance */
522*01a344a2SDavid du Colombier if (fsp->declared == 0) {
523*01a344a2SDavid du Colombier fsp->declared = fsp->actual;
524*01a344a2SDavid du Colombier f.modconf = 1;
525*01a344a2SDavid du Colombier }
526*01a344a2SDavid du Colombier /* warn if declared value is not our compiled-in value */
527*01a344a2SDavid du Colombier if (fsp->declared != fsp->actual)
528*01a344a2SDavid du Colombier print("warning: config %s %ld != compiled-in %ld\n",
529*01a344a2SDavid du Colombier fsp->name, fsp->declared, fsp->actual);
530*01a344a2SDavid du Colombier }
531*01a344a2SDavid du Colombier
532*01a344a2SDavid du Colombier if(f.modconf) {
533*01a344a2SDavid du Colombier memset(p->iobuf, 0, BUFSIZE);
534*01a344a2SDavid du Colombier p->flags |= Bmod|Bimm;
535*01a344a2SDavid du Colombier cp = p->iobuf;
536*01a344a2SDavid du Colombier ep = p->iobuf + RBUFSIZE - 1;
537*01a344a2SDavid du Colombier if(service[0])
538*01a344a2SDavid du Colombier cp = seprint(cp, ep, "service %s\n", service);
539*01a344a2SDavid du Colombier for(fs=filsys; fs->name; fs++)
540*01a344a2SDavid du Colombier if(fs->conf && fs->conf[0] != '\0')
541*01a344a2SDavid du Colombier cp = seprint(cp, ep, "filsys %s %s\n", fs->name,
542*01a344a2SDavid du Colombier fs->conf);
543*01a344a2SDavid du Colombier
544*01a344a2SDavid du Colombier for (fsp = fspar; fsp->name != nil; fsp++)
545*01a344a2SDavid du Colombier cp = seprint(cp, ep, "%s %ld\n",
546*01a344a2SDavid du Colombier fsp->name, fsp->declared);
547*01a344a2SDavid du Colombier
548*01a344a2SDavid du Colombier putbuf(p);
549*01a344a2SDavid du Colombier f.modconf = f.newconf = 0;
550*01a344a2SDavid du Colombier print("config block written\n");
551*01a344a2SDavid du Colombier goto start;
552*01a344a2SDavid du Colombier }
553*01a344a2SDavid du Colombier putbuf(p);
554*01a344a2SDavid du Colombier
555*01a344a2SDavid du Colombier print("service %s\n", service);
556*01a344a2SDavid du Colombier
557*01a344a2SDavid du Colombier loop:
558*01a344a2SDavid du Colombier /*
559*01a344a2SDavid du Colombier * part 2 -- squeeze out the deleted filesystems
560*01a344a2SDavid du Colombier */
561*01a344a2SDavid du Colombier for(fs=filsys; fs->name; fs++)
562*01a344a2SDavid du Colombier if(fs->conf == nil || fs->conf[0] == '\0') {
563*01a344a2SDavid du Colombier for(; fs->name; fs++)
564*01a344a2SDavid du Colombier *fs = *(fs+1);
565*01a344a2SDavid du Colombier goto loop;
566*01a344a2SDavid du Colombier }
567*01a344a2SDavid du Colombier if(filsys[0].name == nil)
568*01a344a2SDavid du Colombier panic("no filsys");
569*01a344a2SDavid du Colombier
570*01a344a2SDavid du Colombier /*
571*01a344a2SDavid du Colombier * part 3 -- compile the device expression
572*01a344a2SDavid du Colombier */
573*01a344a2SDavid du Colombier error = 0;
574*01a344a2SDavid du Colombier for(fs=filsys; fs->name; fs++) {
575*01a344a2SDavid du Colombier print("filsys %s %s\n", fs->name, fs->conf);
576*01a344a2SDavid du Colombier fs->dev = iconfig(fs->conf);
577*01a344a2SDavid du Colombier if(f.error) {
578*01a344a2SDavid du Colombier error = 1;
579*01a344a2SDavid du Colombier continue;
580*01a344a2SDavid du Colombier }
581*01a344a2SDavid du Colombier }
582*01a344a2SDavid du Colombier if(error)
583*01a344a2SDavid du Colombier panic("fs config");
584*01a344a2SDavid du Colombier
585*01a344a2SDavid du Colombier /*
586*01a344a2SDavid du Colombier * part 4 -- initialize the devices
587*01a344a2SDavid du Colombier */
588*01a344a2SDavid du Colombier for(fs=filsys; fs->name; fs++) {
589*01a344a2SDavid du Colombier delay(3000);
590*01a344a2SDavid du Colombier print("sysinit: %s\n", fs->name);
591*01a344a2SDavid du Colombier if(fs->flags & FREAM)
592*01a344a2SDavid du Colombier devream(fs->dev, 1);
593*01a344a2SDavid du Colombier if(fs->flags & FRECOVER)
594*01a344a2SDavid du Colombier devrecover(fs->dev);
595*01a344a2SDavid du Colombier devinit(fs->dev);
596*01a344a2SDavid du Colombier }
597*01a344a2SDavid du Colombier
598*01a344a2SDavid du Colombier /*
599*01a344a2SDavid du Colombier * part 5 -- optionally copy devices or worms
600*01a344a2SDavid du Colombier */
601*01a344a2SDavid du Colombier if (copyworm) {
602*01a344a2SDavid du Colombier dowormcopy(); /* can return if user quits early */
603*01a344a2SDavid du Colombier panic("copyworm bailed out!");
604*01a344a2SDavid du Colombier }
605*01a344a2SDavid du Colombier if (copydev)
606*01a344a2SDavid du Colombier if (dodevcopy() < 0)
607*01a344a2SDavid du Colombier panic("copydev failed!");
608*01a344a2SDavid du Colombier else
609*01a344a2SDavid du Colombier panic("copydev done.");
610*01a344a2SDavid du Colombier }
611*01a344a2SDavid du Colombier
612*01a344a2SDavid du Colombier /* an unfinished idea. a non-blocking rawchar() would help. */
613*01a344a2SDavid du Colombier static int
userabort(char * msg)614*01a344a2SDavid du Colombier userabort(char *msg)
615*01a344a2SDavid du Colombier {
616*01a344a2SDavid du Colombier USED(msg);
617*01a344a2SDavid du Colombier return 0;
618*01a344a2SDavid du Colombier }
619*01a344a2SDavid du Colombier
620*01a344a2SDavid du Colombier static int
blockok(Device * d,Off a)621*01a344a2SDavid du Colombier blockok(Device *d, Off a)
622*01a344a2SDavid du Colombier {
623*01a344a2SDavid du Colombier Iobuf *p = getbuf(d, a, Brd);
624*01a344a2SDavid du Colombier
625*01a344a2SDavid du Colombier if (p == 0) {
626*01a344a2SDavid du Colombier print("i/o error reading %Z block %lld\n", d, (Wideoff)a);
627*01a344a2SDavid du Colombier return 0;
628*01a344a2SDavid du Colombier }
629*01a344a2SDavid du Colombier putbuf(p);
630*01a344a2SDavid du Colombier return 1;
631*01a344a2SDavid du Colombier }
632*01a344a2SDavid du Colombier
633*01a344a2SDavid du Colombier /*
634*01a344a2SDavid du Colombier * special case for fake worms only:
635*01a344a2SDavid du Colombier * we need to size the inner cw's worm device.
636*01a344a2SDavid du Colombier * in particular, we want to avoid copying the fake-worm bitmap
637*01a344a2SDavid du Colombier * at the end of the device.
638*01a344a2SDavid du Colombier *
639*01a344a2SDavid du Colombier * N.B.: for real worms (e.g. cw jukes), we need to compute devsize(cw(juke)),
640*01a344a2SDavid du Colombier * *NOT* devsize(juke).
641*01a344a2SDavid du Colombier */
642*01a344a2SDavid du Colombier static Device *
wormof(Device * dev)643*01a344a2SDavid du Colombier wormof(Device *dev)
644*01a344a2SDavid du Colombier {
645*01a344a2SDavid du Colombier Device *worm = dev, *cw;
646*01a344a2SDavid du Colombier
647*01a344a2SDavid du Colombier if (dev->type == Devfworm) {
648*01a344a2SDavid du Colombier cw = dev->fw.fw;
649*01a344a2SDavid du Colombier if (cw != nil && cw->type == Devcw)
650*01a344a2SDavid du Colombier worm = cw->cw.w;
651*01a344a2SDavid du Colombier }
652*01a344a2SDavid du Colombier // print("wormof(%Z)=%Z\n", dev, worm);
653*01a344a2SDavid du Colombier return worm;
654*01a344a2SDavid du Colombier }
655*01a344a2SDavid du Colombier
656*01a344a2SDavid du Colombier /*
657*01a344a2SDavid du Colombier * return the number of the highest-numbered block actually written, plus 1.
658*01a344a2SDavid du Colombier * 0 indicates an error.
659*01a344a2SDavid du Colombier */
660*01a344a2SDavid du Colombier static Devsize
writtensize(Device * worm)661*01a344a2SDavid du Colombier writtensize(Device *worm)
662*01a344a2SDavid du Colombier {
663*01a344a2SDavid du Colombier Devsize lim = devsize(worm);
664*01a344a2SDavid du Colombier Iobuf *p;
665*01a344a2SDavid du Colombier
666*01a344a2SDavid du Colombier print("devsize(%Z) = %lld\n", worm, (Wideoff)lim);
667*01a344a2SDavid du Colombier if (!blockok(worm, 0) || !blockok(worm, lim-1))
668*01a344a2SDavid du Colombier return 0;
669*01a344a2SDavid du Colombier delay(5*1000);
670*01a344a2SDavid du Colombier if (userabort("sanity checks"))
671*01a344a2SDavid du Colombier return 0;
672*01a344a2SDavid du Colombier
673*01a344a2SDavid du Colombier /* find worm's last valid block in case "worm" is an (f)worm */
674*01a344a2SDavid du Colombier while (lim > 0) {
675*01a344a2SDavid du Colombier if (userabort("sizing")) {
676*01a344a2SDavid du Colombier lim = 0; /* you lose */
677*01a344a2SDavid du Colombier break;
678*01a344a2SDavid du Colombier }
679*01a344a2SDavid du Colombier --lim;
680*01a344a2SDavid du Colombier p = getbuf(worm, lim, Brd);
681*01a344a2SDavid du Colombier if (p != 0) { /* actually read one okay? */
682*01a344a2SDavid du Colombier putbuf(p);
683*01a344a2SDavid du Colombier break;
684*01a344a2SDavid du Colombier }
685*01a344a2SDavid du Colombier }
686*01a344a2SDavid du Colombier print("limit(%Z) = %lld\n", worm, (Wideoff)lim);
687*01a344a2SDavid du Colombier if (lim <= 0)
688*01a344a2SDavid du Colombier return 0;
689*01a344a2SDavid du Colombier return lim + 1;
690*01a344a2SDavid du Colombier }
691*01a344a2SDavid du Colombier
692*01a344a2SDavid du Colombier /* copy worm fs from "main"'s inner worm to "output" */
693*01a344a2SDavid du Colombier static void
dowormcopy(void)694*01a344a2SDavid du Colombier dowormcopy(void)
695*01a344a2SDavid du Colombier {
696*01a344a2SDavid du Colombier Filsys *f1, *f2;
697*01a344a2SDavid du Colombier Device *fdev, *from, *to = nil;
698*01a344a2SDavid du Colombier Iobuf *p;
699*01a344a2SDavid du Colombier Off a;
700*01a344a2SDavid du Colombier Devsize lim;
701*01a344a2SDavid du Colombier
702*01a344a2SDavid du Colombier /*
703*01a344a2SDavid du Colombier * convert file system names into Filsyss and Devices.
704*01a344a2SDavid du Colombier */
705*01a344a2SDavid du Colombier
706*01a344a2SDavid du Colombier f1 = fsstr("main");
707*01a344a2SDavid du Colombier if(f1 == nil)
708*01a344a2SDavid du Colombier panic("main file system missing");
709*01a344a2SDavid du Colombier fdev = f1->dev;
710*01a344a2SDavid du Colombier from = wormof(fdev); /* fake worm special */
711*01a344a2SDavid du Colombier if (from->type != Devfworm && from->type != Devcw) {
712*01a344a2SDavid du Colombier print("main file system is not a worm; copyworm may not do what you want!\n");
713*01a344a2SDavid du Colombier print("waiting for 20 seconds...\n");
714*01a344a2SDavid du Colombier delay(20000);
715*01a344a2SDavid du Colombier }
716*01a344a2SDavid du Colombier
717*01a344a2SDavid du Colombier f2 = fsstr("output");
718*01a344a2SDavid du Colombier if(f2 == nil) {
719*01a344a2SDavid du Colombier print("no output file system - check only\n\n");
720*01a344a2SDavid du Colombier print("reading worm from %Z (worm %Z)\n", fdev, from);
721*01a344a2SDavid du Colombier } else {
722*01a344a2SDavid du Colombier to = f2->dev;
723*01a344a2SDavid du Colombier print("\ncopying worm from %Z (worm %Z) to %Z, starting in 8 seconds\n",
724*01a344a2SDavid du Colombier fdev, from, to);
725*01a344a2SDavid du Colombier delay(8000);
726*01a344a2SDavid du Colombier }
727*01a344a2SDavid du Colombier if (userabort("preparing to copy"))
728*01a344a2SDavid du Colombier return;
729*01a344a2SDavid du Colombier
730*01a344a2SDavid du Colombier /*
731*01a344a2SDavid du Colombier * initialise devices, size them, more sanity checking.
732*01a344a2SDavid du Colombier */
733*01a344a2SDavid du Colombier
734*01a344a2SDavid du Colombier devinit(from);
735*01a344a2SDavid du Colombier if (0 && fdev != from) {
736*01a344a2SDavid du Colombier devinit(fdev);
737*01a344a2SDavid du Colombier print("debugging, sizing %Z first\n", fdev);
738*01a344a2SDavid du Colombier writtensize(fdev);
739*01a344a2SDavid du Colombier }
740*01a344a2SDavid du Colombier lim = writtensize(from);
741*01a344a2SDavid du Colombier if(lim == 0)
742*01a344a2SDavid du Colombier panic("no blocks to copy on %Z", from);
743*01a344a2SDavid du Colombier if (to) {
744*01a344a2SDavid du Colombier print("reaming %Z in 8 seconds\n", to);
745*01a344a2SDavid du Colombier delay(8000);
746*01a344a2SDavid du Colombier if (userabort("preparing to ream & copy"))
747*01a344a2SDavid du Colombier return;
748*01a344a2SDavid du Colombier devream(to, 0);
749*01a344a2SDavid du Colombier devinit(to);
750*01a344a2SDavid du Colombier print("copying worm: %lld blocks from %Z to %Z\n",
751*01a344a2SDavid du Colombier (Wideoff)lim, from, to);
752*01a344a2SDavid du Colombier }
753*01a344a2SDavid du Colombier /* can't read to's blocks in case to is a real WORM device */
754*01a344a2SDavid du Colombier
755*01a344a2SDavid du Colombier /*
756*01a344a2SDavid du Colombier * Copy written fs blocks, a block at a time (or just read
757*01a344a2SDavid du Colombier * if no "output" fs).
758*01a344a2SDavid du Colombier */
759*01a344a2SDavid du Colombier
760*01a344a2SDavid du Colombier for (a = 0; a < lim; a++) {
761*01a344a2SDavid du Colombier if (userabort("copy"))
762*01a344a2SDavid du Colombier break;
763*01a344a2SDavid du Colombier p = getbuf(from, a, Brd);
764*01a344a2SDavid du Colombier /*
765*01a344a2SDavid du Colombier * if from is a real WORM device, we'll get errors trying to
766*01a344a2SDavid du Colombier * read unwritten blocks, but the unwritten blocks need not
767*01a344a2SDavid du Colombier * be contiguous.
768*01a344a2SDavid du Colombier */
769*01a344a2SDavid du Colombier if (p == 0) {
770*01a344a2SDavid du Colombier print("%lld not written yet; can't read\n", (Wideoff)a);
771*01a344a2SDavid du Colombier continue;
772*01a344a2SDavid du Colombier }
773*01a344a2SDavid du Colombier if (to != 0 && devwrite(to, p->addr, p->iobuf) != 0) {
774*01a344a2SDavid du Colombier print("out block %lld: write error; bailing",
775*01a344a2SDavid du Colombier (Wideoff)a);
776*01a344a2SDavid du Colombier break;
777*01a344a2SDavid du Colombier }
778*01a344a2SDavid du Colombier putbuf(p);
779*01a344a2SDavid du Colombier if(a % 20000 == 0)
780*01a344a2SDavid du Colombier print("block %lld %T\n", (Wideoff)a, time(nil));
781*01a344a2SDavid du Colombier }
782*01a344a2SDavid du Colombier
783*01a344a2SDavid du Colombier /*
784*01a344a2SDavid du Colombier * wrap up: sync target, loop
785*01a344a2SDavid du Colombier */
786*01a344a2SDavid du Colombier print("copied %lld blocks from %Z to %Z\n", (Wideoff)a, from, to);
787*01a344a2SDavid du Colombier sync("wormcopy");
788*01a344a2SDavid du Colombier delay(2000);
789*01a344a2SDavid du Colombier print("looping; reset the machine at any time.\n");
790*01a344a2SDavid du Colombier for (; ; )
791*01a344a2SDavid du Colombier continue; /* await reset */
792*01a344a2SDavid du Colombier }
793*01a344a2SDavid du Colombier
794*01a344a2SDavid du Colombier /* copy device from src to dest */
795*01a344a2SDavid du Colombier static int
dodevcopy(void)796*01a344a2SDavid du Colombier dodevcopy(void)
797*01a344a2SDavid du Colombier {
798*01a344a2SDavid du Colombier Device *from, *to;
799*01a344a2SDavid du Colombier Iobuf *p;
800*01a344a2SDavid du Colombier Off a;
801*01a344a2SDavid du Colombier Devsize lim, tosize;
802*01a344a2SDavid du Colombier
803*01a344a2SDavid du Colombier /*
804*01a344a2SDavid du Colombier * convert config strings into Devices.
805*01a344a2SDavid du Colombier */
806*01a344a2SDavid du Colombier from = iconfig(src);
807*01a344a2SDavid du Colombier if(f.error || from == nil) {
808*01a344a2SDavid du Colombier print("bad src device %s\n", src);
809*01a344a2SDavid du Colombier return -1;
810*01a344a2SDavid du Colombier }
811*01a344a2SDavid du Colombier to = iconfig(dest);
812*01a344a2SDavid du Colombier if(f.error || to == nil) {
813*01a344a2SDavid du Colombier print("bad dest device %s\n", dest);
814*01a344a2SDavid du Colombier return -1;
815*01a344a2SDavid du Colombier }
816*01a344a2SDavid du Colombier
817*01a344a2SDavid du Colombier /*
818*01a344a2SDavid du Colombier * initialise devices, size them, more sanity checking.
819*01a344a2SDavid du Colombier */
820*01a344a2SDavid du Colombier
821*01a344a2SDavid du Colombier devinit(from);
822*01a344a2SDavid du Colombier lim = devsize(from);
823*01a344a2SDavid du Colombier if(lim == 0)
824*01a344a2SDavid du Colombier panic("no blocks to copy on %Z", from);
825*01a344a2SDavid du Colombier devinit(to);
826*01a344a2SDavid du Colombier tosize = devsize(to);
827*01a344a2SDavid du Colombier if(tosize == 0)
828*01a344a2SDavid du Colombier panic("no blocks to copy on %Z", to);
829*01a344a2SDavid du Colombier
830*01a344a2SDavid du Colombier /* use smaller of the device sizes */
831*01a344a2SDavid du Colombier if (tosize < lim)
832*01a344a2SDavid du Colombier lim = tosize;
833*01a344a2SDavid du Colombier
834*01a344a2SDavid du Colombier print("copy %Z to %Z in 8 seconds\n", from, to);
835*01a344a2SDavid du Colombier delay(8000);
836*01a344a2SDavid du Colombier if (userabort("preparing to copy"))
837*01a344a2SDavid du Colombier return -1;
838*01a344a2SDavid du Colombier print("copying dev: %lld blocks from %Z to %Z\n", (Wideoff)lim,
839*01a344a2SDavid du Colombier from, to);
840*01a344a2SDavid du Colombier
841*01a344a2SDavid du Colombier /*
842*01a344a2SDavid du Colombier * Copy all blocks, a block at a time.
843*01a344a2SDavid du Colombier */
844*01a344a2SDavid du Colombier
845*01a344a2SDavid du Colombier for (a = 0; a < lim; a++) {
846*01a344a2SDavid du Colombier if (userabort("copy"))
847*01a344a2SDavid du Colombier break;
848*01a344a2SDavid du Colombier p = getbuf(from, a, Brd);
849*01a344a2SDavid du Colombier /*
850*01a344a2SDavid du Colombier * if from is a real WORM device, we'll get errors trying to
851*01a344a2SDavid du Colombier * read unwritten blocks, but the unwritten blocks need not
852*01a344a2SDavid du Colombier * be contiguous.
853*01a344a2SDavid du Colombier */
854*01a344a2SDavid du Colombier if (p == 0) {
855*01a344a2SDavid du Colombier print("%lld not written yet; can't read\n", (Wideoff)a);
856*01a344a2SDavid du Colombier continue;
857*01a344a2SDavid du Colombier }
858*01a344a2SDavid du Colombier if (to != 0 && devwrite(to, p->addr, p->iobuf) != 0) {
859*01a344a2SDavid du Colombier print("out block %lld: write error; bailing",
860*01a344a2SDavid du Colombier (Wideoff)a);
861*01a344a2SDavid du Colombier break;
862*01a344a2SDavid du Colombier }
863*01a344a2SDavid du Colombier putbuf(p);
864*01a344a2SDavid du Colombier if(a % 20000 == 0)
865*01a344a2SDavid du Colombier print("block %lld %T\n", (Wideoff)a, time(nil));
866*01a344a2SDavid du Colombier }
867*01a344a2SDavid du Colombier
868*01a344a2SDavid du Colombier /*
869*01a344a2SDavid du Colombier * wrap up: sync target
870*01a344a2SDavid du Colombier */
871*01a344a2SDavid du Colombier print("copied %lld blocks from %Z to %Z\n", (Wideoff)a, from, to);
872*01a344a2SDavid du Colombier sync("devcopy");
873*01a344a2SDavid du Colombier return 0;
874*01a344a2SDavid du Colombier }
875*01a344a2SDavid du Colombier
876*01a344a2SDavid du Colombier static void
setconfig(char * dev)877*01a344a2SDavid du Colombier setconfig(char *dev)
878*01a344a2SDavid du Colombier {
879*01a344a2SDavid du Colombier if (dev != nil && !testconfig(dev))
880*01a344a2SDavid du Colombier nvrsetconfig(dev); /* if it fails, it will complain */
881*01a344a2SDavid du Colombier }
882*01a344a2SDavid du Colombier
883*01a344a2SDavid du Colombier void
arginit(void)884*01a344a2SDavid du Colombier arginit(void)
885*01a344a2SDavid du Colombier {
886*01a344a2SDavid du Colombier int verb;
887*01a344a2SDavid du Colombier char *line;
888*01a344a2SDavid du Colombier char word[Maxword+1], *cp;
889*01a344a2SDavid du Colombier Filsys *fs;
890*01a344a2SDavid du Colombier
891*01a344a2SDavid du Colombier if(nvrcheck() == 0) {
892*01a344a2SDavid du Colombier setconfig(conf.confdev);
893*01a344a2SDavid du Colombier if (!conf.configfirst)
894*01a344a2SDavid du Colombier return;
895*01a344a2SDavid du Colombier }
896*01a344a2SDavid du Colombier
897*01a344a2SDavid du Colombier /* nvr was bad or invoker requested configuration step */
898*01a344a2SDavid du Colombier setconfig(conf.confdev);
899*01a344a2SDavid du Colombier for (;;) {
900*01a344a2SDavid du Colombier print("config: ");
901*01a344a2SDavid du Colombier if ((line = Brdline(&bin, '\n')) == nil)
902*01a344a2SDavid du Colombier return;
903*01a344a2SDavid du Colombier line[Blinelen(&bin)-1] = '\0';
904*01a344a2SDavid du Colombier
905*01a344a2SDavid du Colombier cp = getwrd(word, line);
906*01a344a2SDavid du Colombier if (word[0] == '\0' || word[0] == '#')
907*01a344a2SDavid du Colombier continue;
908*01a344a2SDavid du Colombier if(strcmp(word, "end") == 0)
909*01a344a2SDavid du Colombier return;
910*01a344a2SDavid du Colombier if(strcmp(word, "halt") == 0)
911*01a344a2SDavid du Colombier exit();
912*01a344a2SDavid du Colombier if(strcmp(word, "queryjuke") == 0) {
913*01a344a2SDavid du Colombier getwrd(word, cp);
914*01a344a2SDavid du Colombier if(testconfig(word) == 0)
915*01a344a2SDavid du Colombier querychanger(iconfig(word));
916*01a344a2SDavid du Colombier continue;
917*01a344a2SDavid du Colombier }
918*01a344a2SDavid du Colombier
919*01a344a2SDavid du Colombier if(strcmp(word, "allow") == 0) {
920*01a344a2SDavid du Colombier wstatallow = 1;
921*01a344a2SDavid du Colombier writeallow = 1;
922*01a344a2SDavid du Colombier continue;
923*01a344a2SDavid du Colombier }
924*01a344a2SDavid du Colombier if(strcmp(word, "copyworm") == 0) {
925*01a344a2SDavid du Colombier copyworm = 1;
926*01a344a2SDavid du Colombier continue;
927*01a344a2SDavid du Colombier }
928*01a344a2SDavid du Colombier if(strcmp(word, "copydev") == 0) {
929*01a344a2SDavid du Colombier cp = getwrd(word, cp);
930*01a344a2SDavid du Colombier if(testconfig(word))
931*01a344a2SDavid du Colombier continue;
932*01a344a2SDavid du Colombier src = strdup(word);
933*01a344a2SDavid du Colombier getwrd(word, cp);
934*01a344a2SDavid du Colombier if(testconfig(word))
935*01a344a2SDavid du Colombier continue;
936*01a344a2SDavid du Colombier dest = strdup(word);
937*01a344a2SDavid du Colombier copydev = 1;
938*01a344a2SDavid du Colombier continue;
939*01a344a2SDavid du Colombier }
940*01a344a2SDavid du Colombier if(strcmp(word, "noauth") == 0) {
941*01a344a2SDavid du Colombier noauth = !noauth;
942*01a344a2SDavid du Colombier continue;
943*01a344a2SDavid du Colombier }
944*01a344a2SDavid du Colombier if(strcmp(word, "noattach") == 0) {
945*01a344a2SDavid du Colombier noattach = !noattach;
946*01a344a2SDavid du Colombier continue;
947*01a344a2SDavid du Colombier }
948*01a344a2SDavid du Colombier if(strcmp(word, "readonly") == 0) {
949*01a344a2SDavid du Colombier readonly = 1;
950*01a344a2SDavid du Colombier continue;
951*01a344a2SDavid du Colombier }
952*01a344a2SDavid du Colombier
953*01a344a2SDavid du Colombier if(strcmp(word, "ream") == 0) {
954*01a344a2SDavid du Colombier verb = FREAM;
955*01a344a2SDavid du Colombier goto gfsname;
956*01a344a2SDavid du Colombier }
957*01a344a2SDavid du Colombier if(strcmp(word, "recover") == 0) {
958*01a344a2SDavid du Colombier verb = FRECOVER;
959*01a344a2SDavid du Colombier goto gfsname;
960*01a344a2SDavid du Colombier }
961*01a344a2SDavid du Colombier if(strcmp(word, "filsys") == 0) {
962*01a344a2SDavid du Colombier verb = FEDIT;
963*01a344a2SDavid du Colombier goto gfsname;
964*01a344a2SDavid du Colombier }
965*01a344a2SDavid du Colombier
966*01a344a2SDavid du Colombier if(strcmp(word, "nvram") == 0) {
967*01a344a2SDavid du Colombier getwrd(word, cp);
968*01a344a2SDavid du Colombier if(testconfig(word))
969*01a344a2SDavid du Colombier continue;
970*01a344a2SDavid du Colombier /* if it fails, it will complain */
971*01a344a2SDavid du Colombier nvrsetconfig(word);
972*01a344a2SDavid du Colombier continue;
973*01a344a2SDavid du Colombier }
974*01a344a2SDavid du Colombier if(strcmp(word, "config") == 0) {
975*01a344a2SDavid du Colombier getwrd(word, cp);
976*01a344a2SDavid du Colombier if(!testconfig(word) && nvrsetconfig(word) == 0)
977*01a344a2SDavid du Colombier f.newconf = 1;
978*01a344a2SDavid du Colombier continue;
979*01a344a2SDavid du Colombier }
980*01a344a2SDavid du Colombier if(strcmp(word, "service") == 0) {
981*01a344a2SDavid du Colombier getwrd(word, cp);
982*01a344a2SDavid du Colombier strncpy(service, word, sizeof service);
983*01a344a2SDavid du Colombier f.modconf = 1;
984*01a344a2SDavid du Colombier continue;
985*01a344a2SDavid du Colombier }
986*01a344a2SDavid du Colombier if (strcmp(word, "resetparams") == 0) {
987*01a344a2SDavid du Colombier resetparams++;
988*01a344a2SDavid du Colombier continue;
989*01a344a2SDavid du Colombier }
990*01a344a2SDavid du Colombier
991*01a344a2SDavid du Colombier /*
992*01a344a2SDavid du Colombier * continue to parse obsolete keywords so that old
993*01a344a2SDavid du Colombier * configurations can still work.
994*01a344a2SDavid du Colombier */
995*01a344a2SDavid du Colombier if (strcmp(word, "ipauth") != 0 &&
996*01a344a2SDavid du Colombier astrcmp(word, "ip") != 0 &&
997*01a344a2SDavid du Colombier astrcmp(word, "ipgw") != 0 &&
998*01a344a2SDavid du Colombier astrcmp(word, "ipmask") != 0 &&
999*01a344a2SDavid du Colombier astrcmp(word, "ipsntp") != 0) {
1000*01a344a2SDavid du Colombier print("unknown config command\n");
1001*01a344a2SDavid du Colombier print("\ttype end to get out\n");
1002*01a344a2SDavid du Colombier continue;
1003*01a344a2SDavid du Colombier }
1004*01a344a2SDavid du Colombier
1005*01a344a2SDavid du Colombier getwrd(word, cp);
1006*01a344a2SDavid du Colombier f.modconf = 1;
1007*01a344a2SDavid du Colombier continue;
1008*01a344a2SDavid du Colombier
1009*01a344a2SDavid du Colombier gfsname:
1010*01a344a2SDavid du Colombier cp = getwrd(word, cp);
1011*01a344a2SDavid du Colombier for(fs=filsys; fs->name; fs++)
1012*01a344a2SDavid du Colombier if(strcmp(word, fs->name) == 0)
1013*01a344a2SDavid du Colombier break;
1014*01a344a2SDavid du Colombier if (fs->name == nil) {
1015*01a344a2SDavid du Colombier memset(fs, 0, sizeof *fs);
1016*01a344a2SDavid du Colombier fs->name = strdup(word);
1017*01a344a2SDavid du Colombier }
1018*01a344a2SDavid du Colombier switch(verb) {
1019*01a344a2SDavid du Colombier case FREAM:
1020*01a344a2SDavid du Colombier if(strcmp(fs->name, "main") == 0)
1021*01a344a2SDavid du Colombier wstatallow = 1; /* only set, never reset */
1022*01a344a2SDavid du Colombier /* fallthrough */
1023*01a344a2SDavid du Colombier case FRECOVER:
1024*01a344a2SDavid du Colombier fs->flags |= verb;
1025*01a344a2SDavid du Colombier break;
1026*01a344a2SDavid du Colombier case FEDIT:
1027*01a344a2SDavid du Colombier f.modconf = 1;
1028*01a344a2SDavid du Colombier getwrd(word, cp);
1029*01a344a2SDavid du Colombier fs->flags |= verb;
1030*01a344a2SDavid du Colombier if(word[0] == 0)
1031*01a344a2SDavid du Colombier fs->conf = nil;
1032*01a344a2SDavid du Colombier else if(!testconfig(word))
1033*01a344a2SDavid du Colombier fs->conf = strdup(word);
1034*01a344a2SDavid du Colombier break;
1035*01a344a2SDavid du Colombier }
1036*01a344a2SDavid du Colombier }
1037*01a344a2SDavid du Colombier }
1038