/* * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ #include "all.h"#include "io.h" 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; static Device* confdev;static int copyworm = 0, copydev = 0;static char *src, *dest; static int resetparams; Fspar fspar[] = { { "blocksize", RBUFSIZE, }, { "daddrbits", sizeof(Off)*8, }, { "indirblks", NIBLOCK, }, { "dirblks", NDBLOCK, }, { "namelen", NAMELEN, }, { nil, 0, },}; intdevcmpr(Device *d1, Device *d2){ while (d1 != d2) { if(d1 == nil || d2 == nil || d1->type != d2->type) return 1; switch(d1->type) { default: print("can't compare dev: %Z\n", d1); panic("devcmp"); return 1; case Devmcat: case Devmlev: case Devmirr: d1 = d1->cat.first; d2 = d2->cat.first; while(d1 && d2) { if(devcmpr(d1, d2)) return 1; d1 = d1->link; d2 = d2->link; } break; case Devnone: return 0; case Devro: d1 = d1->ro.parent; d2 = d2->ro.parent; break; case Devjuke: case Devcw: if(devcmpr(d1->cw.c, d2->cw.c)) return 1; d1 = d1->cw.w; d2 = d2->cw.w; break; case Devfworm: d1 = d1->fw.fw; d2 = d2->fw.fw; break; case Devwren: case Devworm: case Devlworm: if(d1->wren.ctrl == d2->wren.ctrl) if(d1->wren.targ == d2->wren.targ) if(d1->wren.lun == d2->wren.lun) return 0; return 1; case Devpart: if(d1->part.base == d2->part.base) if(d1->part.size == d2->part.size) { d1 = d1->part.d; d2 = d2->part.d; break; } return 1; } } return 0;} voidcdiag(char *s, int c1){ f.charp--; if(f.error == 0) { print("config diag: %s -- <%c>\n", s, c1); f.error = 1; }} intcnumb(void){ int c, n; c = *f.charp++; if(c == '<') { n = f.nextiter; if(n >= 0) { f.nextiter = n+f.diriter; if(n == f.lastiter) { f.nextiter = -1; f.lastiter = -1; } do { c = *f.charp++; } while (c != '>'); return n; } n = cnumb(); if(*f.charp++ != '-') { cdiag("- expected", f.charp[-1]); return 0; } c = cnumb(); if(*f.charp++ != '>') { cdiag("> expected", f.charp[-1]); return 0; } f.lastiter = c; f.diriter = 1; if(n > c) f.diriter = -1; f.nextiter = n+f.diriter; return n; } if(!isascii(c) || !isdigit(c)) { cdiag("number expected", c); return 0; } n = 0; while(isascii(c) && isdigit(c)) { n = n*10 + (c-'0'); c = *f.charp++; } f.charp--; return n;} Device*config1(int c){ Device *d, *t; int m; d = malloc(sizeof(Device)); 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 voidmap(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){ print("map: mapped wren %Z to existing file %s\n", d, map->to); // DEBUG d->wren.file = map->to; /* wren -> file mapping */} else if (map->tdev != nil){ print("map: mapped wren %Z to dev %Z\n", d, map->tdev); // DEBUG *d = *map->tdev; /* wren -> wren mapping */} else print("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; if(f.error) return devnone; d = malloc(sizeof(Device)); 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); case 'f': /* fd fake worm */ d->type = Devfworm; d->fw.fw = config(); break; case 'n': d->type = Devnone; break; case 'w': /* w[#.]#[.#] wren [ctrl] unit [lun] */ case 'r': /* r# worm side */ case 'l': /* l# labelled-worm side */ icp = f.charp; d->type = Devwren; d->wren.ctrl = 0; d->wren.targ = cnumb(); d->wren.lun = 0; m = *f.charp; if(m == '.') { f.charp++; d->wren.lun = cnumb(); m = *f.charp; if(m == '.') { f.charp++; d->wren.ctrl = d->wren.targ; d->wren.targ = d->wren.lun; d->wren.lun = cnumb(); } } if(f.nextiter >= 0) f.charp = icp-1; if(c == 'r') /* worms are virtual and not uniqued */ d->type = Devworm; else if(c == 'l') d->type = Devlworm; else map(d); /* subject wrens to optional mapping */ break; case 'o': /* o ro part of last cw */ if(f.lastcw == 0) { cdiag("no cw to match", c); return devnone; } return f.lastcw->cw.ro; case 'j': /* DD jukebox */ d->type = Devjuke; d->j.j = config(); d->j.m = config(); break; case 'c': /* cache/worm */ d->type = Devcw; d->cw.c = config(); d->cw.w = config(); d->cw.ro = malloc(sizeof(Device)); d->cw.ro->type = Devro; d->cw.ro->ro.parent = d; f.lastcw = d; break; case 'p': /* pd#.# partition base% size% */ d->type = Devpart; d->part.d = config(); d->part.base = cnumb(); c = *f.charp++; if(c != '.') cdiag("dot expected", c); d->part.size = cnumb(); break; case 'x': /* xD swab a device's metadata */ d->type = Devswab; d->swab.d = config(); break; } d->dlink = f.devlist; f.devlist = d; return d;} Device*iconfig(char *s){ Device *d; f.nextiter = -1; f.lastiter = -1; f.error = 0; f.icharp = s; f.charp = f.icharp; d = config(); if(*f.charp) { cdiag("junk on end", *f.charp); f.error = 1; } return d;} inttestconfig(char *s){ iconfig(s); return f.error;} /* * if b is a prefix of a, return 0. */intastrcmp(char *a, char *b){ int n, c; n = strlen(b); if(memcmp(a, b, n) != 0) return 1; c = a[n]; if(c == '\0') return 0; if(a[n+1]) return 1; if(isascii(c) && isdigit(c)) return 0; return 1;} static Fspar *getpar(char *name){ Fspar *fsp; 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. */voidmergeconf(Iobuf *p){ char word[Maxword+1]; char *cp; Filsys *fs; Fspar *fsp; for (cp = p->iobuf; *cp != '\0'; cp++) { cp = getwrd(word, cp); if(word[0] == '\0') break; else if (word[0] == '#') while (*cp != '\n' && *cp != '\0') cp++; else if(strcmp(word, "service") == 0) { cp = getwrd(word, cp); if(service[0] == 0) strncpy(service, word, sizeof service); } else if(strcmp(word, "ipauth") == 0) /* obsolete */ cp = getwrd(word, cp); else if(astrcmp(word, "ip") == 0) /* obsolete */ cp = getwrd(word, cp); else if(astrcmp(word, "ipgw") == 0) /* obsolete */ cp = getwrd(word, cp); else if(astrcmp(word, "ipsntp") == 0) /* obsolete */ cp = getwrd(word, cp); else if(astrcmp(word, "ipmask") == 0) /* obsolete */ cp = getwrd(word, cp); else if(strcmp(word, "filsys") == 0) { cp = getwrd(word, cp); for(fs = filsys; fs < filsys + nelem(filsys) - 1 && fs->name; fs++) if(strcmp(fs->name, word) == 0) break; if (fs >= filsys + nelem(filsys) - 1) panic("out of filsys structures"); if (fs->name && strcmp(fs->name, word) == 0 && fs->flags & FEDIT) cp = getwrd(word, cp); /* swallow conf */ else { fs->name = strdup(word); cp = getwrd(word, cp); if (word[0] == '\0') fs->conf = nil; else fs->conf = strdup(word); } } else if ((fsp = getpar(word)) != nil) { cp = getwrd(word, cp); if (!isascii(word[0]) || !isdigit(word[0])) print("bad %s value: %s", fsp->name, word); else fsp->declared = atol(word); } else { putbuf(p); panic("unknown keyword in config block: %s", word); } if(*cp != '\n') { putbuf(p); panic("syntax error in config block at `%s'", word); } }} voidcmd_printconf(int, char *[]){ char *p, *s; Iobuf *iob; iob = getbuf(confdev, 0, Brd); if(iob == nil) return; if(checktag(iob, Tconfig, 0)){ putbuf(iob); return; } print("config %s\n", nvrgetconfig()); for(s = p = iob->iobuf; *p != 0 && p < iob->iobuf+BUFSIZE; ){ if(*p++ != '\n') continue; if (strncmp(s, "ip", 2) != 0) /* don't print obsolete cmds */ print("%.*s", (int)(p-s), s); s = p; } if(p != s) print("%.*s", (int)(p-s), s); print("end\n"); putbuf(iob);} voidsysinit(void){ int error; char *cp, *ep; Device *d; Filsys *fs; Fspar *fsp; Iobuf *p; cons.chan = fs_chaninit(Devcon, 1, 0); Lines 1–500 of 1046. Load more
/* * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ #include "all.h" #include "io.h" 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; static Device* confdev; static int copyworm = 0, copydev = 0; static char *src, *dest; static int resetparams; Fspar fspar[] = { { "blocksize", RBUFSIZE, }, { "daddrbits", sizeof(Off)*8, }, { "indirblks", NIBLOCK, }, { "dirblks", NDBLOCK, }, { "namelen", NAMELEN, }, { nil, 0, }, }; int devcmpr(Device *d1, Device *d2) { while (d1 != d2) { if(d1 == nil || d2 == nil || d1->type != d2->type) return 1; switch(d1->type) { default: print("can't compare dev: %Z\n", d1); panic("devcmp"); return 1; case Devmcat: case Devmlev: case Devmirr: d1 = d1->cat.first; d2 = d2->cat.first; while(d1 && d2) { if(devcmpr(d1, d2)) return 1; d1 = d1->link; d2 = d2->link; } break; case Devnone: return 0; case Devro: d1 = d1->ro.parent; d2 = d2->ro.parent; break; case Devjuke: case Devcw: if(devcmpr(d1->cw.c, d2->cw.c)) return 1; d1 = d1->cw.w; d2 = d2->cw.w; break; case Devfworm: d1 = d1->fw.fw; d2 = d2->fw.fw; break; case Devwren: case Devworm: case Devlworm: if(d1->wren.ctrl == d2->wren.ctrl) if(d1->wren.targ == d2->wren.targ) if(d1->wren.lun == d2->wren.lun) return 0; return 1; case Devpart: if(d1->part.base == d2->part.base) if(d1->part.size == d2->part.size) { d1 = d1->part.d; d2 = d2->part.d; break; } return 1; } } return 0; } void cdiag(char *s, int c1) { f.charp--; if(f.error == 0) { print("config diag: %s -- <%c>\n", s, c1); f.error = 1; } } int cnumb(void) { int c, n; c = *f.charp++; if(c == '<') { n = f.nextiter; if(n >= 0) { f.nextiter = n+f.diriter; if(n == f.lastiter) { f.nextiter = -1; f.lastiter = -1; } do { c = *f.charp++; } while (c != '>'); return n; } n = cnumb(); if(*f.charp++ != '-') { cdiag("- expected", f.charp[-1]); return 0; } c = cnumb(); if(*f.charp++ != '>') { cdiag("> expected", f.charp[-1]); return 0; } f.lastiter = c; f.diriter = 1; if(n > c) f.diriter = -1; f.nextiter = n+f.diriter; return n; } if(!isascii(c) || !isdigit(c)) { cdiag("number expected", c); return 0; } n = 0; while(isascii(c) && isdigit(c)) { n = n*10 + (c-'0'); c = *f.charp++; } f.charp--; return n; } Device* config1(int c) { Device *d, *t; int m; d = malloc(sizeof(Device)); 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) { print("map: mapped wren %Z to existing file %s\n", d, map->to); // DEBUG d->wren.file = map->to; /* wren -> file mapping */ } else if (map->tdev != nil) { print("map: mapped wren %Z to dev %Z\n", d, map->tdev); // DEBUG *d = *map->tdev; /* wren -> wren mapping */ } else print("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; if(f.error) return devnone; d = malloc(sizeof(Device)); 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); case 'f': /* fd fake worm */ d->type = Devfworm; d->fw.fw = config(); break; case 'n': d->type = Devnone; break; case 'w': /* w[#.]#[.#] wren [ctrl] unit [lun] */ case 'r': /* r# worm side */ case 'l': /* l# labelled-worm side */ icp = f.charp; d->type = Devwren; d->wren.ctrl = 0; d->wren.targ = cnumb(); d->wren.lun = 0; m = *f.charp; if(m == '.') { f.charp++; d->wren.lun = cnumb(); m = *f.charp; if(m == '.') { f.charp++; d->wren.ctrl = d->wren.targ; d->wren.targ = d->wren.lun; d->wren.lun = cnumb(); } } if(f.nextiter >= 0) f.charp = icp-1; if(c == 'r') /* worms are virtual and not uniqued */ d->type = Devworm; else if(c == 'l') d->type = Devlworm; else map(d); /* subject wrens to optional mapping */ break; case 'o': /* o ro part of last cw */ if(f.lastcw == 0) { cdiag("no cw to match", c); return devnone; } return f.lastcw->cw.ro; case 'j': /* DD jukebox */ d->type = Devjuke; d->j.j = config(); d->j.m = config(); break; case 'c': /* cache/worm */ d->type = Devcw; d->cw.c = config(); d->cw.w = config(); d->cw.ro = malloc(sizeof(Device)); d->cw.ro->type = Devro; d->cw.ro->ro.parent = d; f.lastcw = d; break; case 'p': /* pd#.# partition base% size% */ d->type = Devpart; d->part.d = config(); d->part.base = cnumb(); c = *f.charp++; if(c != '.') cdiag("dot expected", c); d->part.size = cnumb(); break; case 'x': /* xD swab a device's metadata */ d->type = Devswab; d->swab.d = config(); break; } d->dlink = f.devlist; f.devlist = d; return d; } Device* iconfig(char *s) { Device *d; f.nextiter = -1; f.lastiter = -1; f.error = 0; f.icharp = s; f.charp = f.icharp; d = config(); if(*f.charp) { cdiag("junk on end", *f.charp); f.error = 1; } return d; } int testconfig(char *s) { iconfig(s); return f.error; } /* * if b is a prefix of a, return 0. */ int astrcmp(char *a, char *b) { int n, c; n = strlen(b); if(memcmp(a, b, n) != 0) return 1; c = a[n]; if(c == '\0') return 0; if(a[n+1]) return 1; if(isascii(c) && isdigit(c)) return 0; return 1; } static Fspar * getpar(char *name) { Fspar *fsp; 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; for (cp = p->iobuf; *cp != '\0'; cp++) { cp = getwrd(word, cp); if(word[0] == '\0') break; else if (word[0] == '#') while (*cp != '\n' && *cp != '\0') cp++; else if(strcmp(word, "service") == 0) { cp = getwrd(word, cp); if(service[0] == 0) strncpy(service, word, sizeof service); } else if(strcmp(word, "ipauth") == 0) /* obsolete */ cp = getwrd(word, cp); else if(astrcmp(word, "ip") == 0) /* obsolete */ cp = getwrd(word, cp); else if(astrcmp(word, "ipgw") == 0) /* obsolete */ cp = getwrd(word, cp); else if(astrcmp(word, "ipsntp") == 0) /* obsolete */ cp = getwrd(word, cp); else if(astrcmp(word, "ipmask") == 0) /* obsolete */ cp = getwrd(word, cp); else if(strcmp(word, "filsys") == 0) { cp = getwrd(word, cp); for(fs = filsys; fs < filsys + nelem(filsys) - 1 && fs->name; fs++) if(strcmp(fs->name, word) == 0) break; if (fs >= filsys + nelem(filsys) - 1) panic("out of filsys structures"); if (fs->name && strcmp(fs->name, word) == 0 && fs->flags & FEDIT) cp = getwrd(word, cp); /* swallow conf */ else { fs->name = strdup(word); cp = getwrd(word, cp); if (word[0] == '\0') fs->conf = nil; else fs->conf = strdup(word); } } else if ((fsp = getpar(word)) != nil) { cp = getwrd(word, cp); if (!isascii(word[0]) || !isdigit(word[0])) print("bad %s value: %s", fsp->name, word); else fsp->declared = atol(word); } else { putbuf(p); panic("unknown keyword in config block: %s", word); } if(*cp != '\n') { putbuf(p); panic("syntax error in config block at `%s'", word); } } } void cmd_printconf(int, char *[]) { char *p, *s; Iobuf *iob; iob = getbuf(confdev, 0, Brd); if(iob == nil) return; if(checktag(iob, Tconfig, 0)){ putbuf(iob); return; } print("config %s\n", nvrgetconfig()); for(s = p = iob->iobuf; *p != 0 && p < iob->iobuf+BUFSIZE; ){ if(*p++ != '\n') continue; if (strncmp(s, "ip", 2) != 0) /* don't print obsolete cmds */ print("%.*s", (int)(p-s), s); s = p; } if(p != s) print("%.*s", (int)(p-s), s); print("end\n"); putbuf(iob); } void sysinit(void) { int error; char *cp, *ep; Device *d; Filsys *fs; Fspar *fsp; Iobuf *p; cons.chan = fs_chaninit(Devcon, 1, 0);