config.c 20 KB

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