1715d0f95SDavid du Colombier /* 2715d0f95SDavid du Colombier * partfs - serve an underlying file, with devsd-style partitions 3715d0f95SDavid du Colombier */ 4715d0f95SDavid du Colombier #include <u.h> 5715d0f95SDavid du Colombier #include <libc.h> 6715d0f95SDavid du Colombier #include <auth.h> 7715d0f95SDavid du Colombier #include <fcall.h> 8715d0f95SDavid du Colombier #include <thread.h> 9715d0f95SDavid du Colombier #include <9p.h> 10715d0f95SDavid du Colombier 11715d0f95SDavid du Colombier typedef struct Part Part; 12715d0f95SDavid du Colombier struct Part 13715d0f95SDavid du Colombier { 14715d0f95SDavid du Colombier int inuse; 15715d0f95SDavid du Colombier int vers; 16715d0f95SDavid du Colombier ulong mode; 17715d0f95SDavid du Colombier char *name; 18715d0f95SDavid du Colombier vlong offset; /* in sectors */ 19715d0f95SDavid du Colombier vlong length; /* in sectors */ 20715d0f95SDavid du Colombier }; 21715d0f95SDavid du Colombier 22715d0f95SDavid du Colombier enum 23715d0f95SDavid du Colombier { 24715d0f95SDavid du Colombier Qroot = 0, 25715d0f95SDavid du Colombier Qdir, 26715d0f95SDavid du Colombier Qctl, 27715d0f95SDavid du Colombier Qpart, 28715d0f95SDavid du Colombier }; 29715d0f95SDavid du Colombier 30715d0f95SDavid du Colombier int fd = -1, ctlfd = -1; 31715d0f95SDavid du Colombier int rdonly; 32715d0f95SDavid du Colombier ulong ctlmode = 0666; 33715d0f95SDavid du Colombier ulong time0; 34715d0f95SDavid du Colombier vlong nsect, sectsize; 35715d0f95SDavid du Colombier 36715d0f95SDavid du Colombier char *inquiry = "partfs hard drive"; 37715d0f95SDavid du Colombier char *sdname = "sdXX"; 38715d0f95SDavid du Colombier Part tab[64]; 39715d0f95SDavid du Colombier 40715d0f95SDavid du Colombier char* 41715d0f95SDavid du Colombier ctlstring(void) 42715d0f95SDavid du Colombier { 43715d0f95SDavid du Colombier Part *p; 44715d0f95SDavid du Colombier Fmt fmt; 45715d0f95SDavid du Colombier 46715d0f95SDavid du Colombier fmtstrinit(&fmt); 47715d0f95SDavid du Colombier fmtprint(&fmt, "inquiry %s\n", inquiry); 48715d0f95SDavid du Colombier fmtprint(&fmt, "geometry %lld %lld\n", nsect, sectsize); 49715d0f95SDavid du Colombier for (p = tab; p < tab + nelem(tab); p++) 50715d0f95SDavid du Colombier if (p->inuse) 51715d0f95SDavid du Colombier fmtprint(&fmt, "part %s %lld %lld\n", 52715d0f95SDavid du Colombier p->name, p->offset, p->length); 53715d0f95SDavid du Colombier return fmtstrflush(&fmt); 54715d0f95SDavid du Colombier } 55715d0f95SDavid du Colombier 56715d0f95SDavid du Colombier int 57715d0f95SDavid du Colombier addpart(char *name, vlong start, vlong end) 58715d0f95SDavid du Colombier { 59715d0f95SDavid du Colombier Part *p; 60715d0f95SDavid du Colombier 61715d0f95SDavid du Colombier if(start < 0 || start > end || end > nsect){ 62715d0f95SDavid du Colombier werrstr("bad partition boundaries"); 63715d0f95SDavid du Colombier return -1; 64715d0f95SDavid du Colombier } 65715d0f95SDavid du Colombier 66715d0f95SDavid du Colombier if (strcmp(name, "ctl") == 0 || strcmp(name, "data") == 0) { 67715d0f95SDavid du Colombier werrstr("partition name already in use"); 68715d0f95SDavid du Colombier return -1; 69715d0f95SDavid du Colombier } 70715d0f95SDavid du Colombier for (p = tab; p < tab + nelem(tab) && p->inuse; p++) 71715d0f95SDavid du Colombier if (strcmp(p->name, name) == 0) { 72715d0f95SDavid du Colombier werrstr("partition name already in use"); 73715d0f95SDavid du Colombier return -1; 74715d0f95SDavid du Colombier } 75715d0f95SDavid du Colombier if(p == tab + nelem(tab)){ 76715d0f95SDavid du Colombier werrstr("no free partition slots"); 77715d0f95SDavid du Colombier return -1; 78715d0f95SDavid du Colombier } 79715d0f95SDavid du Colombier 80715d0f95SDavid du Colombier p->inuse = 1; 81715d0f95SDavid du Colombier free(p->name); 82715d0f95SDavid du Colombier p->name = estrdup9p(name); 83715d0f95SDavid du Colombier p->offset = start; 84715d0f95SDavid du Colombier p->length = end - start; 85715d0f95SDavid du Colombier p->mode = ctlmode; 86715d0f95SDavid du Colombier p->vers++; 87715d0f95SDavid du Colombier return 0; 88715d0f95SDavid du Colombier } 89715d0f95SDavid du Colombier 90715d0f95SDavid du Colombier int 91715d0f95SDavid du Colombier delpart(char *s) 92715d0f95SDavid du Colombier { 93715d0f95SDavid du Colombier Part *p; 94715d0f95SDavid du Colombier 95715d0f95SDavid du Colombier for (p = tab; p < tab + nelem(tab); p++) 96715d0f95SDavid du Colombier if(p->inuse && strcmp(p->name, s) == 0) 97715d0f95SDavid du Colombier break; 98715d0f95SDavid du Colombier if(p == tab + nelem(tab)){ 99715d0f95SDavid du Colombier werrstr("partition not found"); 100715d0f95SDavid du Colombier return -1; 101715d0f95SDavid du Colombier } 102715d0f95SDavid du Colombier 103715d0f95SDavid du Colombier p->inuse = 0; 104715d0f95SDavid du Colombier free(p->name); 105715d0f95SDavid du Colombier p->name = nil; 106715d0f95SDavid du Colombier return 0; 107715d0f95SDavid du Colombier } 108715d0f95SDavid du Colombier 109715d0f95SDavid du Colombier static void 110*8c055935SDavid du Colombier addparts(char *buf) 111*8c055935SDavid du Colombier { 112*8c055935SDavid du Colombier char *f[4], *p, *q; 113*8c055935SDavid du Colombier 114*8c055935SDavid du Colombier /* 115*8c055935SDavid du Colombier * Use partitions passed from boot program, 116*8c055935SDavid du Colombier * e.g. 117*8c055935SDavid du Colombier * sdC0part=dos 63 123123/plan9 123123 456456 118*8c055935SDavid du Colombier * This happens before /boot sets hostname so the 119*8c055935SDavid du Colombier * partitions will have the null-string for user. 120*8c055935SDavid du Colombier */ 121*8c055935SDavid du Colombier for(p = buf; p != nil; p = q){ 122*8c055935SDavid du Colombier if(q = strchr(p, '/')) 123*8c055935SDavid du Colombier *q++ = '\0'; 124*8c055935SDavid du Colombier if(tokenize(p, f, nelem(f)) >= 3 && 125*8c055935SDavid du Colombier addpart(f[0], strtoull(f[1], 0, 0), strtoull(f[2], 0, 0)) < 0) 126*8c055935SDavid du Colombier fprint(2, "%s: addpart %s: %r\n", argv0, f[0]); 127*8c055935SDavid du Colombier } 128*8c055935SDavid du Colombier } 129*8c055935SDavid du Colombier 130*8c055935SDavid du Colombier static void 131715d0f95SDavid du Colombier ctlwrite0(Req *r, char *msg, Cmdbuf *cb) 132715d0f95SDavid du Colombier { 133715d0f95SDavid du Colombier vlong start, end; 134715d0f95SDavid du Colombier Part *p; 135715d0f95SDavid du Colombier 136715d0f95SDavid du Colombier r->ofcall.count = r->ifcall.count; 137715d0f95SDavid du Colombier 138715d0f95SDavid du Colombier if(cb->nf < 1){ 139715d0f95SDavid du Colombier respond(r, "empty control message"); 140715d0f95SDavid du Colombier return; 141715d0f95SDavid du Colombier } 142715d0f95SDavid du Colombier 143715d0f95SDavid du Colombier if(strcmp(cb->f[0], "part") == 0){ 144715d0f95SDavid du Colombier if(cb->nf != 4){ 145715d0f95SDavid du Colombier respondcmderror(r, cb, "part takes 3 args"); 146715d0f95SDavid du Colombier return; 147715d0f95SDavid du Colombier } 148715d0f95SDavid du Colombier start = strtoll(cb->f[2], 0, 0); 149715d0f95SDavid du Colombier end = strtoll(cb->f[3], 0, 0); 150715d0f95SDavid du Colombier if(addpart(cb->f[1], start, end) < 0){ 151715d0f95SDavid du Colombier respondcmderror(r, cb, "%r"); 152715d0f95SDavid du Colombier return; 153715d0f95SDavid du Colombier } 154715d0f95SDavid du Colombier } 155715d0f95SDavid du Colombier else if(strcmp(cb->f[0], "delpart") == 0){ 156715d0f95SDavid du Colombier if(cb->nf != 2){ 157715d0f95SDavid du Colombier respondcmderror(r, cb, "delpart takes 1 arg"); 158715d0f95SDavid du Colombier return; 159715d0f95SDavid du Colombier } 160715d0f95SDavid du Colombier if(delpart(cb->f[1]) < 0){ 161715d0f95SDavid du Colombier respondcmderror(r, cb, "%r"); 162715d0f95SDavid du Colombier return; 163715d0f95SDavid du Colombier } 164715d0f95SDavid du Colombier } 165715d0f95SDavid du Colombier else if(strcmp(cb->f[0], "inquiry") == 0){ 166715d0f95SDavid du Colombier if(cb->nf != 2){ 167715d0f95SDavid du Colombier respondcmderror(r, cb, "inquiry takes 1 arg"); 168715d0f95SDavid du Colombier return; 169715d0f95SDavid du Colombier } 170715d0f95SDavid du Colombier free(inquiry); 171715d0f95SDavid du Colombier inquiry = estrdup9p(cb->f[1]); 172715d0f95SDavid du Colombier } 173715d0f95SDavid du Colombier else if(strcmp(cb->f[0], "geometry") == 0){ 174715d0f95SDavid du Colombier if(cb->nf != 3){ 175715d0f95SDavid du Colombier respondcmderror(r, cb, "geometry takes 2 args"); 176715d0f95SDavid du Colombier return; 177715d0f95SDavid du Colombier } 178715d0f95SDavid du Colombier nsect = strtoll(cb->f[1], 0, 0); 179715d0f95SDavid du Colombier sectsize = strtoll(cb->f[2], 0, 0); 180715d0f95SDavid du Colombier if(tab[0].inuse && strcmp(tab[0].name, "data") == 0 && 181715d0f95SDavid du Colombier tab[0].vers == 0){ 182715d0f95SDavid du Colombier tab[0].offset = 0; 183715d0f95SDavid du Colombier tab[0].length = nsect; 184715d0f95SDavid du Colombier } 185715d0f95SDavid du Colombier for(p = tab; p < tab + nelem(tab); p++) 186715d0f95SDavid du Colombier if(p->inuse && p->offset + p->length > nsect){ 187715d0f95SDavid du Colombier p->inuse = 0; 188715d0f95SDavid du Colombier free(p->name); 189715d0f95SDavid du Colombier p->name = nil; 190715d0f95SDavid du Colombier } 191715d0f95SDavid du Colombier } else 192715d0f95SDavid du Colombier /* pass through to underlying ctl file, if any */ 193715d0f95SDavid du Colombier if (write(ctlfd, msg, r->ifcall.count) != r->ifcall.count) { 194715d0f95SDavid du Colombier respondcmderror(r, cb, "%r"); 195715d0f95SDavid du Colombier return; 196715d0f95SDavid du Colombier } 197715d0f95SDavid du Colombier respond(r, nil); 198715d0f95SDavid du Colombier } 199715d0f95SDavid du Colombier 200715d0f95SDavid du Colombier void 201715d0f95SDavid du Colombier ctlwrite(Req *r) 202715d0f95SDavid du Colombier { 203715d0f95SDavid du Colombier char *msg; 204715d0f95SDavid du Colombier Cmdbuf *cb; 205715d0f95SDavid du Colombier 206715d0f95SDavid du Colombier r->ofcall.count = r->ifcall.count; 207715d0f95SDavid du Colombier 208715d0f95SDavid du Colombier msg = emalloc9p(r->ifcall.count+1); 209715d0f95SDavid du Colombier memmove(msg, r->ifcall.data, r->ifcall.count); 210715d0f95SDavid du Colombier msg[r->ifcall.count] = '\0'; 211715d0f95SDavid du Colombier 212715d0f95SDavid du Colombier cb = parsecmd(r->ifcall.data, r->ifcall.count); 213715d0f95SDavid du Colombier ctlwrite0(r, msg, cb); 214715d0f95SDavid du Colombier 215715d0f95SDavid du Colombier free(cb); 216715d0f95SDavid du Colombier free(msg); 217715d0f95SDavid du Colombier } 218715d0f95SDavid du Colombier 219715d0f95SDavid du Colombier int 220715d0f95SDavid du Colombier rootgen(int off, Dir *d, void*) 221715d0f95SDavid du Colombier { 222715d0f95SDavid du Colombier memset(d, 0, sizeof *d); 223715d0f95SDavid du Colombier d->atime = time0; 224715d0f95SDavid du Colombier d->mtime = time0; 225715d0f95SDavid du Colombier if(off == 0){ 226715d0f95SDavid du Colombier d->name = estrdup9p(sdname); 227715d0f95SDavid du Colombier d->mode = DMDIR|0777; 228715d0f95SDavid du Colombier d->qid.path = Qdir; 229715d0f95SDavid du Colombier d->qid.type = QTDIR; 230715d0f95SDavid du Colombier d->uid = estrdup9p("partfs"); 231715d0f95SDavid du Colombier d->gid = estrdup9p("partfs"); 232715d0f95SDavid du Colombier d->muid = estrdup9p(""); 233715d0f95SDavid du Colombier return 0; 234715d0f95SDavid du Colombier } 235715d0f95SDavid du Colombier return -1; 236715d0f95SDavid du Colombier } 237715d0f95SDavid du Colombier 238715d0f95SDavid du Colombier int 239715d0f95SDavid du Colombier dirgen(int off, Dir *d, void*) 240715d0f95SDavid du Colombier { 241715d0f95SDavid du Colombier int n; 242715d0f95SDavid du Colombier Part *p; 243715d0f95SDavid du Colombier 244715d0f95SDavid du Colombier memset(d, 0, sizeof *d); 245715d0f95SDavid du Colombier d->atime = time0; 246715d0f95SDavid du Colombier d->mtime = time0; 247715d0f95SDavid du Colombier if(off == 0){ 248715d0f95SDavid du Colombier d->name = estrdup9p("ctl"); 249715d0f95SDavid du Colombier d->mode = ctlmode; 250715d0f95SDavid du Colombier d->qid.path = Qctl; 251715d0f95SDavid du Colombier goto Have; 252715d0f95SDavid du Colombier } 253715d0f95SDavid du Colombier 254715d0f95SDavid du Colombier off--; 255715d0f95SDavid du Colombier n = 0; 256715d0f95SDavid du Colombier for(p = tab; p < tab + nelem(tab); p++, n++){ 257715d0f95SDavid du Colombier if(!p->inuse) 258715d0f95SDavid du Colombier continue; 259715d0f95SDavid du Colombier if(n == off){ 260715d0f95SDavid du Colombier d->name = estrdup9p(p->name); 261715d0f95SDavid du Colombier d->length = p->length*sectsize; 262715d0f95SDavid du Colombier d->mode = p->mode; 263715d0f95SDavid du Colombier d->qid.path = Qpart + p - tab; 264715d0f95SDavid du Colombier d->qid.vers = p->vers; 265715d0f95SDavid du Colombier goto Have; 266715d0f95SDavid du Colombier } 267715d0f95SDavid du Colombier } 268715d0f95SDavid du Colombier return -1; 269715d0f95SDavid du Colombier 270715d0f95SDavid du Colombier Have: 271715d0f95SDavid du Colombier d->uid = estrdup9p("partfs"); 272715d0f95SDavid du Colombier d->gid = estrdup9p("partfs"); 273715d0f95SDavid du Colombier d->muid = estrdup9p(""); 274715d0f95SDavid du Colombier return 0; 275715d0f95SDavid du Colombier } 276715d0f95SDavid du Colombier 277715d0f95SDavid du Colombier void* 278715d0f95SDavid du Colombier evommem(void *a, void *b, ulong n) 279715d0f95SDavid du Colombier { 280715d0f95SDavid du Colombier return memmove(b, a, n); 281715d0f95SDavid du Colombier } 282715d0f95SDavid du Colombier 283715d0f95SDavid du Colombier int 284715d0f95SDavid du Colombier rdwrpart(Req *r) 285715d0f95SDavid du Colombier { 286715d0f95SDavid du Colombier int q; 287715d0f95SDavid du Colombier long count, tot; 288715d0f95SDavid du Colombier vlong offset; 289715d0f95SDavid du Colombier uchar *dat; 290715d0f95SDavid du Colombier Part *p; 291715d0f95SDavid du Colombier 292715d0f95SDavid du Colombier q = r->fid->qid.path - Qpart; 293715d0f95SDavid du Colombier if(q < 0 || q > nelem(tab) || !tab[q].inuse || 294715d0f95SDavid du Colombier tab[q].vers != r->fid->qid.vers){ 295715d0f95SDavid du Colombier respond(r, "unknown partition"); 296715d0f95SDavid du Colombier return -1; 297715d0f95SDavid du Colombier } 298715d0f95SDavid du Colombier p = &tab[q]; 299715d0f95SDavid du Colombier 300715d0f95SDavid du Colombier offset = r->ifcall.offset; 301715d0f95SDavid du Colombier count = r->ifcall.count; 302715d0f95SDavid du Colombier if(offset < 0){ 303715d0f95SDavid du Colombier respond(r, "negative offset"); 304715d0f95SDavid du Colombier return -1; 305715d0f95SDavid du Colombier } 306715d0f95SDavid du Colombier if(count < 0){ 307715d0f95SDavid du Colombier respond(r, "negative count"); 308715d0f95SDavid du Colombier return -1; 309715d0f95SDavid du Colombier } 310715d0f95SDavid du Colombier if(offset > p->length*sectsize){ 311715d0f95SDavid du Colombier respond(r, "offset past end of partition"); 312715d0f95SDavid du Colombier return -1; 313715d0f95SDavid du Colombier } 314715d0f95SDavid du Colombier if(offset+count > p->length*sectsize) 315715d0f95SDavid du Colombier count = p->length*sectsize - offset; 316715d0f95SDavid du Colombier offset += p->offset*sectsize; 317715d0f95SDavid du Colombier 318715d0f95SDavid du Colombier if(r->ifcall.type == Tread) 319715d0f95SDavid du Colombier dat = (uchar*)r->ofcall.data; 320715d0f95SDavid du Colombier else 321715d0f95SDavid du Colombier dat = (uchar*)r->ifcall.data; 322715d0f95SDavid du Colombier 323715d0f95SDavid du Colombier /* pass i/o through to underlying file */ 324715d0f95SDavid du Colombier seek(fd, offset, 0); 325715d0f95SDavid du Colombier if (r->ifcall.type == Twrite) { 326715d0f95SDavid du Colombier tot = write(fd, dat, count); 327715d0f95SDavid du Colombier if (tot != count) { 328715d0f95SDavid du Colombier respond(r, "%r"); 329715d0f95SDavid du Colombier return -1; 330715d0f95SDavid du Colombier } 331715d0f95SDavid du Colombier } else { 332715d0f95SDavid du Colombier tot = read(fd, dat, count); 333715d0f95SDavid du Colombier if (tot < 0) { 334715d0f95SDavid du Colombier respond(r, "%r"); 335715d0f95SDavid du Colombier return -1; 336715d0f95SDavid du Colombier } 337715d0f95SDavid du Colombier } 338715d0f95SDavid du Colombier r->ofcall.count = tot; 339715d0f95SDavid du Colombier respond(r, nil); 340715d0f95SDavid du Colombier return 0; 341715d0f95SDavid du Colombier } 342715d0f95SDavid du Colombier 343715d0f95SDavid du Colombier void 344715d0f95SDavid du Colombier fsread(Req *r) 345715d0f95SDavid du Colombier { 346715d0f95SDavid du Colombier char *s; 347715d0f95SDavid du Colombier 348715d0f95SDavid du Colombier switch((int)r->fid->qid.path){ 349715d0f95SDavid du Colombier case Qroot: 350715d0f95SDavid du Colombier dirread9p(r, rootgen, nil); 351715d0f95SDavid du Colombier break; 352715d0f95SDavid du Colombier case Qdir: 353715d0f95SDavid du Colombier dirread9p(r, dirgen, nil); 354715d0f95SDavid du Colombier break; 355715d0f95SDavid du Colombier case Qctl: 356715d0f95SDavid du Colombier s = ctlstring(); 357715d0f95SDavid du Colombier readstr(r, s); 358715d0f95SDavid du Colombier free(s); 359715d0f95SDavid du Colombier break; 360715d0f95SDavid du Colombier default: 361715d0f95SDavid du Colombier rdwrpart(r); 362715d0f95SDavid du Colombier return; 363715d0f95SDavid du Colombier } 364715d0f95SDavid du Colombier respond(r, nil); 365715d0f95SDavid du Colombier } 366715d0f95SDavid du Colombier 367715d0f95SDavid du Colombier void 368715d0f95SDavid du Colombier fswrite(Req *r) 369715d0f95SDavid du Colombier { 370715d0f95SDavid du Colombier switch((int)r->fid->qid.path){ 371715d0f95SDavid du Colombier case Qroot: 372715d0f95SDavid du Colombier case Qdir: 373715d0f95SDavid du Colombier respond(r, "write to a directory?"); 374715d0f95SDavid du Colombier break; 375715d0f95SDavid du Colombier case Qctl: 376715d0f95SDavid du Colombier ctlwrite(r); 377715d0f95SDavid du Colombier break; 378715d0f95SDavid du Colombier default: 379715d0f95SDavid du Colombier rdwrpart(r); 380715d0f95SDavid du Colombier break; 381715d0f95SDavid du Colombier } 382715d0f95SDavid du Colombier } 383715d0f95SDavid du Colombier 384715d0f95SDavid du Colombier void 385715d0f95SDavid du Colombier fsopen(Req *r) 386715d0f95SDavid du Colombier { 387715d0f95SDavid du Colombier if(r->ifcall.mode&ORCLOSE) 388715d0f95SDavid du Colombier respond(r, "cannot open ORCLOSE"); 389715d0f95SDavid du Colombier 390715d0f95SDavid du Colombier switch((int)r->fid->qid.path){ 391715d0f95SDavid du Colombier case Qroot: 392715d0f95SDavid du Colombier case Qdir: 393715d0f95SDavid du Colombier if(r->ifcall.mode != OREAD){ 394715d0f95SDavid du Colombier respond(r, "bad mode for directory open"); 395715d0f95SDavid du Colombier return; 396715d0f95SDavid du Colombier } 397715d0f95SDavid du Colombier } 398715d0f95SDavid du Colombier 399715d0f95SDavid du Colombier respond(r, nil); 400715d0f95SDavid du Colombier } 401715d0f95SDavid du Colombier 402715d0f95SDavid du Colombier void 403715d0f95SDavid du Colombier fsstat(Req *r) 404715d0f95SDavid du Colombier { 405715d0f95SDavid du Colombier int q; 406715d0f95SDavid du Colombier Dir *d; 407715d0f95SDavid du Colombier Part *p; 408715d0f95SDavid du Colombier 409715d0f95SDavid du Colombier d = &r->d; 410715d0f95SDavid du Colombier memset(d, 0, sizeof *d); 411715d0f95SDavid du Colombier d->qid = r->fid->qid; 412715d0f95SDavid du Colombier d->atime = d->mtime = time0; 413715d0f95SDavid du Colombier q = r->fid->qid.path; 414715d0f95SDavid du Colombier switch(q){ 415715d0f95SDavid du Colombier case Qroot: 416715d0f95SDavid du Colombier d->name = estrdup9p("/"); 417715d0f95SDavid du Colombier d->mode = DMDIR|0777; 418715d0f95SDavid du Colombier break; 419715d0f95SDavid du Colombier 420715d0f95SDavid du Colombier case Qdir: 421715d0f95SDavid du Colombier d->name = estrdup9p(sdname); 422715d0f95SDavid du Colombier d->mode = DMDIR|0777; 423715d0f95SDavid du Colombier break; 424715d0f95SDavid du Colombier 425715d0f95SDavid du Colombier case Qctl: 426715d0f95SDavid du Colombier d->name = estrdup9p("ctl"); 427715d0f95SDavid du Colombier d->mode = 0666; 428715d0f95SDavid du Colombier break; 429715d0f95SDavid du Colombier 430715d0f95SDavid du Colombier default: 431715d0f95SDavid du Colombier q -= Qpart; 432715d0f95SDavid du Colombier if(q < 0 || q > nelem(tab) || tab[q].inuse == 0 || 433715d0f95SDavid du Colombier r->fid->qid.vers != tab[q].vers){ 434715d0f95SDavid du Colombier respond(r, "partition no longer exists"); 435715d0f95SDavid du Colombier return; 436715d0f95SDavid du Colombier } 437715d0f95SDavid du Colombier p = &tab[q]; 438715d0f95SDavid du Colombier d->name = estrdup9p(p->name); 439715d0f95SDavid du Colombier d->length = p->length * sectsize; 440715d0f95SDavid du Colombier d->mode = p->mode; 441715d0f95SDavid du Colombier break; 442715d0f95SDavid du Colombier } 443715d0f95SDavid du Colombier 444715d0f95SDavid du Colombier d->uid = estrdup9p("partfs"); 445715d0f95SDavid du Colombier d->gid = estrdup9p("partfs"); 446715d0f95SDavid du Colombier d->muid = estrdup9p(""); 447715d0f95SDavid du Colombier respond(r, nil); 448715d0f95SDavid du Colombier } 449715d0f95SDavid du Colombier 450715d0f95SDavid du Colombier void 451715d0f95SDavid du Colombier fsattach(Req *r) 452715d0f95SDavid du Colombier { 453715d0f95SDavid du Colombier char *spec; 454715d0f95SDavid du Colombier 455715d0f95SDavid du Colombier spec = r->ifcall.aname; 456715d0f95SDavid du Colombier if(spec && spec[0]){ 457715d0f95SDavid du Colombier respond(r, "invalid attach specifier"); 458715d0f95SDavid du Colombier return; 459715d0f95SDavid du Colombier } 460715d0f95SDavid du Colombier r->ofcall.qid = (Qid){Qroot, 0, QTDIR}; 461715d0f95SDavid du Colombier r->fid->qid = r->ofcall.qid; 462715d0f95SDavid du Colombier respond(r, nil); 463715d0f95SDavid du Colombier } 464715d0f95SDavid du Colombier 465715d0f95SDavid du Colombier char* 466715d0f95SDavid du Colombier fswalk1(Fid *fid, char *name, Qid *qid) 467715d0f95SDavid du Colombier { 468715d0f95SDavid du Colombier Part *p; 469715d0f95SDavid du Colombier 470715d0f95SDavid du Colombier switch((int)fid->qid.path){ 471715d0f95SDavid du Colombier case Qroot: 472715d0f95SDavid du Colombier if(strcmp(name, sdname) == 0){ 473715d0f95SDavid du Colombier fid->qid.path = Qdir; 474715d0f95SDavid du Colombier fid->qid.type = QTDIR; 475715d0f95SDavid du Colombier *qid = fid->qid; 476715d0f95SDavid du Colombier return nil; 477715d0f95SDavid du Colombier } 478715d0f95SDavid du Colombier break; 479715d0f95SDavid du Colombier case Qdir: 480715d0f95SDavid du Colombier if(strcmp(name, "ctl") == 0){ 481715d0f95SDavid du Colombier fid->qid.path = Qctl; 482715d0f95SDavid du Colombier fid->qid.vers = 0; 483715d0f95SDavid du Colombier fid->qid.type = 0; 484715d0f95SDavid du Colombier *qid = fid->qid; 485715d0f95SDavid du Colombier return nil; 486715d0f95SDavid du Colombier } 487715d0f95SDavid du Colombier for(p = tab; p < tab + nelem(tab); p++) 488715d0f95SDavid du Colombier if(p->inuse && strcmp(p->name, name) == 0){ 489715d0f95SDavid du Colombier fid->qid.path = p - tab + Qpart; 490715d0f95SDavid du Colombier fid->qid.vers = p->vers; 491715d0f95SDavid du Colombier fid->qid.type = 0; 492715d0f95SDavid du Colombier *qid = fid->qid; 493715d0f95SDavid du Colombier return nil; 494715d0f95SDavid du Colombier } 495715d0f95SDavid du Colombier break; 496715d0f95SDavid du Colombier } 497715d0f95SDavid du Colombier return "file not found"; 498715d0f95SDavid du Colombier } 499715d0f95SDavid du Colombier 500715d0f95SDavid du Colombier Srv fs = { 501715d0f95SDavid du Colombier .attach=fsattach, 502715d0f95SDavid du Colombier .open= fsopen, 503715d0f95SDavid du Colombier .read= fsread, 504715d0f95SDavid du Colombier .write= fswrite, 505715d0f95SDavid du Colombier .stat= fsstat, 506715d0f95SDavid du Colombier .walk1= fswalk1, 507715d0f95SDavid du Colombier }; 508715d0f95SDavid du Colombier 509715d0f95SDavid du Colombier char *mtpt = "/dev"; 510715d0f95SDavid du Colombier char *srvname; 511715d0f95SDavid du Colombier 512715d0f95SDavid du Colombier void 513715d0f95SDavid du Colombier usage(void) 514715d0f95SDavid du Colombier { 515*8c055935SDavid du Colombier fprint(2, "usage: %s [-Dr] [-d sdname] [-m mtpt] [-p 9parts] " 516*8c055935SDavid du Colombier "[-s srvname] diskimage\n", argv0); 517715d0f95SDavid du Colombier fprint(2, "\tdefault mtpt is /dev\n"); 518715d0f95SDavid du Colombier exits("usage"); 519715d0f95SDavid du Colombier } 520715d0f95SDavid du Colombier 521715d0f95SDavid du Colombier void 522715d0f95SDavid du Colombier main(int argc, char **argv) 523715d0f95SDavid du Colombier { 524715d0f95SDavid du Colombier int isdir; 525*8c055935SDavid du Colombier char *file, *cname, *parts; 526715d0f95SDavid du Colombier Dir *dir; 527715d0f95SDavid du Colombier 528715d0f95SDavid du Colombier quotefmtinstall(); 529715d0f95SDavid du Colombier time0 = time(0); 530*8c055935SDavid du Colombier parts = nil; 531715d0f95SDavid du Colombier 532715d0f95SDavid du Colombier ARGBEGIN{ 533715d0f95SDavid du Colombier case 'D': 534715d0f95SDavid du Colombier chatty9p++; 535715d0f95SDavid du Colombier break; 536950da38cSDavid du Colombier case 'd': 537950da38cSDavid du Colombier sdname = EARGF(usage()); 538715d0f95SDavid du Colombier break; 539715d0f95SDavid du Colombier case 'm': 540715d0f95SDavid du Colombier mtpt = EARGF(usage()); 541715d0f95SDavid du Colombier break; 542*8c055935SDavid du Colombier case 'p': 543*8c055935SDavid du Colombier parts = EARGF(usage()); 544*8c055935SDavid du Colombier break; 545715d0f95SDavid du Colombier case 'r': 546715d0f95SDavid du Colombier rdonly = 1; 547715d0f95SDavid du Colombier break; 548715d0f95SDavid du Colombier case 's': 549715d0f95SDavid du Colombier srvname = EARGF(usage()); 550715d0f95SDavid du Colombier break; 551715d0f95SDavid du Colombier default: 552715d0f95SDavid du Colombier usage(); 553715d0f95SDavid du Colombier }ARGEND 554715d0f95SDavid du Colombier 555950da38cSDavid du Colombier if(argc != 1) 556715d0f95SDavid du Colombier usage(); 557950da38cSDavid du Colombier file = argv[0]; 558715d0f95SDavid du Colombier dir = dirstat(file); 559715d0f95SDavid du Colombier if(!dir) 560715d0f95SDavid du Colombier sysfatal("%s: %r", file); 561715d0f95SDavid du Colombier isdir = (dir->mode & DMDIR) != 0; 562715d0f95SDavid du Colombier free(dir); 563715d0f95SDavid du Colombier 564715d0f95SDavid du Colombier if (isdir) { 565715d0f95SDavid du Colombier cname = smprint("%s/ctl", file); 566715d0f95SDavid du Colombier if ((ctlfd = open(cname, ORDWR)) < 0) 567715d0f95SDavid du Colombier sysfatal("open %s: %r", cname); 568715d0f95SDavid du Colombier file = smprint("%s/data", file); 569715d0f95SDavid du Colombier } 570715d0f95SDavid du Colombier if((fd = open(file, rdonly? OREAD: ORDWR)) < 0) 571715d0f95SDavid du Colombier sysfatal("open %s: %r", file); 572715d0f95SDavid du Colombier 573715d0f95SDavid du Colombier sectsize = 512; /* conventional */ 574715d0f95SDavid du Colombier dir = dirfstat(fd); 575715d0f95SDavid du Colombier if (dir) 576715d0f95SDavid du Colombier nsect = dir->length / sectsize; 577715d0f95SDavid du Colombier free(dir); 578715d0f95SDavid du Colombier 579715d0f95SDavid du Colombier inquiry = estrdup9p(inquiry); 580715d0f95SDavid du Colombier tab[0].inuse = 1; 581715d0f95SDavid du Colombier tab[0].name = estrdup9p("data"); 582715d0f95SDavid du Colombier tab[0].mode = 0666; 583715d0f95SDavid du Colombier tab[0].length = nsect; 584715d0f95SDavid du Colombier 585*8c055935SDavid du Colombier /* 586*8c055935SDavid du Colombier * hack for booting from usb: add 9load partitions. 587*8c055935SDavid du Colombier */ 588*8c055935SDavid du Colombier if(parts != nil) 589*8c055935SDavid du Colombier addparts(parts); 590*8c055935SDavid du Colombier 591715d0f95SDavid du Colombier postmountsrv(&fs, srvname, mtpt, MBEFORE); 592715d0f95SDavid du Colombier exits(nil); 593715d0f95SDavid du Colombier } 594