1 #include <u.h> 2 #include <libc.h> 3 #include <bio.h> 4 #include <auth.h> 5 #include <fcall.h> 6 #include "iotrack.h" 7 #include "dat.h" 8 #include "fns.h" 9 10 int 11 dosfs(Xfs *xf) 12 { 13 Iosect *p = 0; 14 Dosboot *b = 0; 15 Dosbpb *bp; 16 Dospart *dp; 17 int i, j; long offset; 18 19 for(i=2; i>0; i--){ 20 p = getsect(xf, 0); 21 if(p == 0) 22 return -1; 23 b = (Dosboot *)p->iobuf; 24 if(b->magic[0] == 0xe9) 25 break; 26 if(b->magic[0] == 0xeb && b->magic[2] == 0x90) 27 break; 28 if(i < 2 || p->iobuf[0x1fe] != 0x55 || p->iobuf[0x1ff] != 0xaa){ 29 i = 0; 30 break; 31 } 32 dp = (Dospart *)&p->iobuf[0x1be]; 33 for(j=4; j>0; j--,dp++){ 34 chat("0x%2.2ux (%d,%d) 0x%2.2ux (%d,%d) %d %d...", 35 dp->active, dp->hstart, GSHORT(dp->cylstart), 36 dp->type, dp->hend, GSHORT(dp->cylend), 37 GLONG(dp->start), GLONG(dp->length)); 38 if(dp->type) 39 break; 40 } 41 if(j <= 0){ 42 chat("no active partition..."); 43 putsect(p); 44 return -1; 45 } 46 offset = GLONG(dp->start)*Sectorsize; 47 putsect(p); 48 purgebuf(xf); 49 xf->offset = offset; 50 } 51 if(i <= 0){ 52 chat("bad magic..."); 53 putsect(p); 54 return -1; 55 } 56 if(chatty) 57 bootdump(2, b); 58 59 bp = malloc(sizeof(Dosbpb)); 60 xf->ptr = bp; 61 xf->fmt = 1; 62 63 bp->sectsize = GSHORT(b->sectsize); 64 bp->clustsize = b->clustsize; 65 bp->nresrv = GSHORT(b->nresrv); 66 bp->nfats = b->nfats; 67 bp->rootsize = GSHORT(b->rootsize); 68 bp->volsize = GSHORT(b->volsize); 69 if(bp->volsize == 0) 70 bp->volsize = GLONG(b->bigvolsize); 71 bp->mediadesc = b->mediadesc; 72 bp->fatsize = GSHORT(b->fatsize); 73 74 bp->fataddr = bp->nresrv; 75 bp->rootaddr = bp->fataddr + bp->nfats*bp->fatsize; 76 i = bp->rootsize*sizeof(Dosdir) + bp->sectsize-1; 77 i /= bp->sectsize; 78 bp->dataaddr = bp->rootaddr + i; 79 bp->fatclusters = 2+(bp->volsize - bp->dataaddr)/bp->clustsize; 80 if(bp->fatclusters < 4087) 81 bp->fatbits = 12; 82 else 83 bp->fatbits = 16; 84 bp->freeptr = 2; 85 chat("fatbits=%d (%d clusters)...", bp->fatbits, bp->fatclusters); 86 for(i=0; i<b->nfats; i++) 87 chat("fat %d: %d...", i, bp->fataddr+i*bp->fatsize); 88 chat("root: %d...", bp->rootaddr); 89 chat("data: %d...", bp->dataaddr); 90 putsect(p); 91 return 0; 92 } 93 94 int 95 getfile(Xfile *f) 96 { 97 Dosptr *dp = f->ptr; 98 Iosect *p; 99 Dosdir *d; 100 101 if(dp->p) 102 panic("getfile"); 103 p = getsect(f->xf, dp->addr); 104 if(p == 0) 105 return -1; 106 if(dp->addr != 0){ 107 d = (Dosdir *)&p->iobuf[dp->offset]; 108 if((f->qid.path & ~CHDIR) != GSHORT(d->start)){ 109 chat("qid mismatch f=0x%x d=0x%x...", 110 f->qid.path, GSHORT(d->start)); 111 putsect(p); 112 errno = Enonexist; 113 return -1; 114 } 115 dp->d = d; 116 } 117 dp->p = p; 118 return 0; 119 } 120 121 void 122 putfile(Xfile *f) 123 { 124 Dosptr *dp = f->ptr; 125 126 if(!dp->p) 127 panic("putfile"); 128 putsect(dp->p); 129 dp->p = 0; 130 dp->d = 0; 131 } 132 133 int 134 fileaddr(Xfile *f, int isect, int cflag) 135 { 136 Dosbpb *bp = f->xf->ptr; 137 Dosptr *dp = f->ptr; 138 Dosdir *d = dp->d; 139 int clust, iclust, nskip, next = 0; 140 141 if(dp->addr == 0){ 142 if(isect*bp->sectsize >= bp->rootsize*sizeof(Dosdir)) 143 return -1; 144 return bp->rootaddr + isect; 145 } 146 iclust = isect/bp->clustsize; 147 if(dp->clust == 0 || iclust < dp->iclust){ 148 clust = GSHORT(d->start); 149 nskip = iclust; 150 }else{ 151 clust = dp->clust; 152 nskip = iclust - dp->iclust; 153 } 154 if(chatty > 1 && nskip > 0) 155 chat("clust 0x%x, skip %d...", clust, nskip); 156 if(clust <= 0) 157 return -1; 158 if(nskip > 0){ 159 lock(bp); 160 while(--nskip >= 0){ 161 next = getfat(f->xf, clust); 162 if(chatty > 1) 163 chat("->0x%x", next); 164 if(next > 0){ 165 clust = next; 166 continue; 167 }else if(!cflag) 168 break; 169 next = falloc(f->xf); 170 if(next < 0) 171 break; 172 putfat(f->xf, clust, next); 173 clust = next; 174 } 175 unlock(bp); 176 if(next <= 0) 177 return -1; 178 dp->clust = clust; 179 dp->iclust = iclust; 180 } 181 if(chatty > 1) 182 chat(" clust(0x%x)=0x%x...", iclust, clust); 183 return bp->dataaddr + (clust-2)*bp->clustsize + isect%bp->clustsize; 184 } 185 186 int 187 searchdir(Xfile *f, char *name, Dosptr *dp, int cflag) 188 { 189 Xfs *xf = f->xf; 190 Dosbpb *bp = xf->ptr; 191 char uname[16], buf[16]; 192 int isect, addr, o; 193 int addr1 = 0, o1 = 0; 194 Iosect *p; 195 Dosdir *d, tmpdir; 196 197 putname(name, &tmpdir); 198 getname(uname, &tmpdir); 199 memset(dp, 0, sizeof(Dosptr)); 200 dp->paddr = ((Dosptr *)f->ptr)->addr; 201 dp->poffset = ((Dosptr *)f->ptr)->offset; 202 203 for(isect=0;; isect++){ 204 addr = fileaddr(f, isect, cflag); 205 if(addr < 0) 206 break; 207 p = getsect(xf, addr); 208 if(p == 0) 209 break; 210 for(o=0; o<bp->sectsize; o+=sizeof(Dosdir)){ 211 d = (Dosdir *)&p->iobuf[o]; 212 if(d->name[0] == 0x00){ 213 chat("end dir(0)..."); 214 putsect(p); 215 if(!cflag) 216 return -1; 217 if(addr1 == 0){ 218 addr1 = addr; 219 o1 = o; 220 } 221 dp->addr = addr1; 222 dp->offset = o1; 223 return 0; 224 } 225 if(d->name[0] == 0xe5){ 226 if(addr1 == 0){ 227 addr1 = addr; 228 o1 = o; 229 } 230 continue; 231 } 232 /*dirdump(d);*/ 233 if(d->attr&DVLABEL) 234 continue; 235 getname(buf, d); 236 if(strcmp(buf, uname) != 0) 237 continue; 238 dirdump(d); 239 if(cflag){ 240 putsect(p); 241 return -1; 242 } 243 dp->addr = addr; 244 dp->offset = o; 245 dp->p = p; 246 dp->d = d; 247 return 0; 248 } 249 putsect(p); 250 } 251 chat("end dir(1)..."); 252 return -1; 253 } 254 255 int 256 emptydir(Xfile *f) 257 { 258 Xfs *xf = f->xf; 259 Dosbpb *bp = xf->ptr; 260 int isect, addr, o; 261 Iosect *p; 262 Dosdir *d; 263 264 for(isect=0;; isect++){ 265 addr = fileaddr(f, isect, 0); 266 if(addr < 0) 267 break; 268 p = getsect(xf, addr); 269 if(p == 0) 270 return -1; 271 for(o=0; o<bp->sectsize; o+=sizeof(Dosdir)){ 272 d = (Dosdir *)&p->iobuf[o]; 273 if(d->name[0] == 0x00){ 274 putsect(p); 275 return 0; 276 } 277 if(d->name[0] == 0xe5) 278 continue; 279 if(d->name[0] == '.') 280 continue; 281 if(d->attr&DVLABEL) 282 continue; 283 putsect(p); 284 return -1; 285 } 286 putsect(p); 287 } 288 return 0; 289 } 290 291 long 292 readdir(Xfile *f, char *buf, long offset, long count) 293 { 294 Xfs *xf = f->xf; 295 Dosbpb *bp = xf->ptr; 296 Dir dir; 297 int isect, addr, o; 298 Iosect *p; 299 Dosdir *d; 300 long rcnt = 0; 301 302 if(count <= 0) 303 return 0; 304 for(isect=0;; isect++){ 305 addr = fileaddr(f, isect, 0); 306 if(addr < 0) 307 break; 308 p = getsect(xf, addr); 309 if(p == 0) 310 return -1; 311 for(o=0; o<bp->sectsize; o+=sizeof(Dosdir)){ 312 d = (Dosdir *)&p->iobuf[o]; 313 if(d->name[0] == 0x00){ 314 putsect(p); 315 return rcnt; 316 } 317 if(d->name[0] == 0xe5) 318 continue; 319 /*dirdump(d);*/ 320 if(d->name[0] == '.'){ 321 if(d->name[1] == ' ' || d->name[1] == 0) 322 continue; 323 if(d->name[1] == '.' && 324 (d->name[2] == ' ' || d->name[2] == 0)) 325 continue; 326 } 327 if(d->attr&DVLABEL) 328 continue; 329 if(offset > 0){ 330 offset -= DIRLEN; 331 continue; 332 } 333 getdir(&dir, d); 334 rcnt += convD2M(&dir, &buf[rcnt]); 335 if(rcnt >= count){ 336 putsect(p); 337 return rcnt; 338 } 339 } 340 putsect(p); 341 } 342 return rcnt; 343 } 344 345 int 346 walkup(Xfile *f, Dosptr *ndp) 347 { 348 Dosbpb *bp = f->xf->ptr; 349 Dosptr *dp = f->ptr; 350 Dosdir *xd; 351 Iosect *p; 352 int k, o, so, start, pstart, ppstart; 353 354 memset(ndp, 0, sizeof(Dosptr)); 355 ndp->addr = dp->paddr; 356 ndp->offset = dp->poffset; 357 chat("walkup: paddr=0x%x...", dp->paddr); 358 if(dp->paddr == 0) 359 return 0; 360 p = getsect(f->xf, dp->paddr); 361 if(p == 0) 362 goto error; 363 xd = (Dosdir *)&p->iobuf[dp->poffset]; 364 dirdump(xd); 365 start = GSHORT(xd->start); 366 chat("start=0x%x...", start); 367 if(start == 0) 368 goto error; 369 putsect(p); 370 p = getsect(f->xf, bp->dataaddr + (start-2)*bp->clustsize); 371 if(p == 0) 372 goto error; 373 xd = (Dosdir *)p->iobuf; 374 dirdump(xd); 375 if(xd->name[0]!='.' || xd->name[1]!=' ' || start!=GSHORT(xd->start)) 376 goto error; 377 xd++; 378 dirdump(xd); 379 if(xd->name[0] != '.' || xd->name[1] != '.') 380 goto error; 381 pstart = GSHORT(xd->start); 382 putsect(p); 383 if(pstart == 0) 384 return 0; 385 p = getsect(f->xf, bp->dataaddr + (pstart-2)*bp->clustsize); 386 if(p == 0){ 387 chat("getsect %d failed\n", pstart); 388 goto error; 389 } 390 xd = (Dosdir *)p->iobuf; 391 dirdump(xd); 392 if(xd->name[0]!='.' || xd->name[1]!=' ' || pstart!=GSHORT(xd->start)) 393 goto error; 394 xd++; 395 dirdump(xd); 396 if(xd->name[0] != '.' || xd->name[1] != '.') 397 goto error; 398 ppstart = GSHORT(xd->start); 399 putsect(p); 400 k = ppstart ? (bp->dataaddr + (ppstart-2)*bp->clustsize) : bp->rootaddr; 401 p = getsect(f->xf, k); 402 if(p == 0){ 403 chat("getsect %d failed\n", k); 404 goto error; 405 } 406 xd = (Dosdir *)p->iobuf; 407 dirdump(xd); 408 if(ppstart) 409 if(xd->name[0]!='.' || xd->name[1]!=' ' || ppstart!=GSHORT(xd->start)) 410 goto error; 411 for(so=1;; so++){ 412 for(o=0; o<bp->sectsize; o+=sizeof(Dosdir)){ 413 xd = (Dosdir *)&p->iobuf[o]; 414 if(xd->name[0] == 0x00){ 415 chat("end dir\n"); 416 goto error; 417 } 418 if(xd->name[0] == 0xe5) 419 continue; 420 if(GSHORT(xd->start) == pstart) 421 goto out; 422 } 423 if(ppstart){ 424 if(so%bp->clustsize == 0){ 425 lock(bp); 426 ppstart = getfat(f->xf, ppstart); 427 unlock(bp); 428 if(ppstart < 0){ 429 chat("getfat %d failed\n", ppstart); 430 goto error; 431 } 432 } 433 k = bp->dataaddr + (ppstart-2)*bp->clustsize + 434 so%bp->clustsize; 435 }else{ 436 if(so*bp->sectsize >= bp->rootsize*sizeof(Dosdir)) 437 goto error; 438 k = bp->rootaddr + so; 439 } 440 putsect(p); 441 p = getsect(f->xf, k); 442 if(p == 0){ 443 chat("getsect %d failed\n", k); 444 goto error; 445 } 446 } 447 out: 448 putsect(p); 449 ndp->paddr = k; 450 ndp->poffset = o; 451 return 0; 452 453 error: 454 if(p) 455 putsect(p); 456 return -1; 457 } 458 459 long 460 readfile(Xfile *f, uchar *buf, long offset, long count) 461 { 462 Xfs *xf = f->xf; 463 Dosbpb *bp = xf->ptr; 464 Dosptr *dp = f->ptr; 465 Dosdir *d = dp->d; 466 int isect, addr, o, c; 467 Iosect *p; 468 long length = GLONG(d->length), rcnt = 0; 469 470 if(offset >= length) 471 return 0; 472 if(offset+count >= length) 473 count = length - offset; 474 isect = offset/bp->sectsize; 475 o = offset%bp->sectsize; 476 while(count > 0){ 477 addr = fileaddr(f, isect++, 0); 478 if(addr < 0) 479 break; 480 c = bp->sectsize - o; 481 if(c > count) 482 c = count; 483 p = getsect(xf, addr); 484 if(p == 0) 485 return -1; 486 memmove(&buf[rcnt], &p->iobuf[o], c); 487 putsect(p); 488 count -= c; 489 rcnt += c; 490 o = 0; 491 } 492 return rcnt; 493 } 494 495 long 496 writefile(Xfile *f, uchar *buf, long offset, long count) 497 { 498 Xfs *xf = f->xf; 499 Dosbpb *bp = xf->ptr; 500 Dosptr *dp = f->ptr; 501 Dosdir *d = dp->d; 502 int isect, addr = 0, o, c; 503 Iosect *p; 504 long length, rcnt = 0, dlen; 505 506 isect = offset/bp->sectsize; 507 o = offset%bp->sectsize; 508 while(count > 0){ 509 addr = fileaddr(f, isect++, 1); 510 if(addr < 0) 511 break; 512 c = bp->sectsize - o; 513 if(c > count) 514 c = count; 515 if(c == bp->sectsize){ 516 p = getosect(xf, addr); 517 if(p == 0) 518 return -1; 519 p->flags = 0; 520 }else{ 521 p = getsect(xf, addr); 522 if(p == 0) 523 return -1; 524 } 525 memmove(&p->iobuf[o], &buf[rcnt], c); 526 p->flags |= BMOD; 527 putsect(p); 528 count -= c; 529 rcnt += c; 530 o = 0; 531 } 532 if(rcnt <= 0 && addr < 0) 533 return -1; 534 length = 0; 535 dlen = GLONG(d->length); 536 if(rcnt > 0) 537 length = offset+rcnt; 538 else if(dp->addr && dp->clust){ 539 c = bp->clustsize*bp->sectsize; 540 if(dp->iclust > (dlen+c-1)/c) 541 length = c*dp->iclust; 542 } 543 if(length > dlen){ 544 d->length[0] = length; 545 d->length[1] = length>>8; 546 d->length[2] = length>>16; 547 d->length[3] = length>>24; 548 } 549 puttime(d, 0); 550 dp->p->flags |= BMOD; 551 return rcnt; 552 } 553 554 int 555 truncfile(Xfile *f, int totally) 556 { 557 Xfs *xf = f->xf; 558 Dosbpb *bp = xf->ptr; 559 Dosptr *dp = f->ptr; 560 Dosdir *d = dp->d; 561 int clust, next; 562 563 lock(bp); 564 clust = GSHORT(d->start); 565 if(totally){ 566 d->start[0] = 0; 567 d->start[1] = 0; 568 }else{ 569 next = getfat(xf, clust); 570 putfat(xf, clust, 0xffff); 571 clust = next; 572 } 573 while(clust >= 0){ 574 next = getfat(xf, clust); 575 putfat(xf, clust, 0); 576 clust = next; 577 } 578 unlock(bp); 579 d->length[0] = 0; 580 d->length[1] = 0; 581 d->length[2] = 0; 582 d->length[3] = 0; 583 dp->iclust = 0; 584 dp->clust = 0; 585 dp->p->flags |= BMOD; 586 return 0; 587 } 588 589 void 590 getdir(Dir *dp, Dosdir *d) 591 { 592 char *p; 593 594 memset(dp, 0, sizeof(Dir)); 595 if(d == 0){ 596 dp->name[0] = '/'; 597 dp->qid.path = CHDIR; 598 dp->mode = CHDIR|0777; 599 }else{ 600 getname(dp->name, d); 601 for(p=dp->name; *p; p++) 602 *p = tolower(*p); 603 dp->qid.path = GSHORT(d->start); 604 if(d->attr & DRONLY) 605 dp->mode = 0444; 606 else 607 dp->mode = 0666; 608 dp->atime = gtime(d); 609 dp->mtime = dp->atime; 610 if(d->attr & DDIR){ 611 dp->qid.path |= CHDIR; 612 dp->mode |= CHDIR|0111; 613 }else 614 dp->length = GLONG(d->length); 615 if(d->attr & DSYSTEM) 616 dp->mode |= CHEXCL; 617 } 618 strcpy(dp->uid, "bill"); 619 strcpy(dp->gid, "trog"); 620 } 621 622 void 623 getname(char *p, Dosdir *d) 624 { 625 int c, i; 626 627 for(i=0; i<8; i++){ 628 c = d->name[i]; 629 if(c == 0 || c == ' ') 630 break; 631 if(i == 0 && c == 0x05) 632 c = 0xe5; 633 *p++ = c; 634 } 635 for(i=0; i<3; i++){ 636 c = d->ext[i]; 637 if(c == 0 || c == ' ') 638 break; 639 if(i == 0) 640 *p++ = '.'; 641 *p++ = c; 642 } 643 *p = 0; 644 } 645 646 void 647 putname(char *p, Dosdir *d) 648 { 649 int i; 650 651 memset(d->name, ' ', sizeof d->name+sizeof d->ext); 652 for(i=0; i<sizeof d->name; i++){ 653 if(*p == 0 || *p == '.') 654 break; 655 d->name[i] = toupper(*p++); 656 } 657 p = strrchr(p, '.'); 658 if(p){ 659 for(i=0; i<sizeof d->ext; i++){ 660 if(*++p == 0) 661 break; 662 d->ext[i] = toupper(*p); 663 } 664 } 665 } 666 667 int 668 getfat(Xfs *xf, int n) 669 { 670 Dosbpb *bp = xf->ptr; 671 ulong k = 0, sect; Iosect *p; 672 int o; 673 674 if(n < 2 || n >= bp->fatclusters) 675 return -1; 676 switch(bp->fatbits){ 677 case 12: 678 k = (3*n)/2; break; 679 case 16: 680 k = 2*n; break; 681 } 682 if(k >= bp->fatsize*bp->sectsize) 683 panic("getfat"); 684 sect = k/bp->sectsize + bp->fataddr; 685 o = k%bp->sectsize; 686 p = getsect(xf, sect); 687 if(p == 0) 688 return -1; 689 k = p->iobuf[o++]; 690 if(o >= bp->sectsize){ 691 putsect(p); 692 p = getsect(xf, sect+1); 693 if(p == 0) 694 return -1; 695 o = 0; 696 } 697 k |= p->iobuf[o]<<8; 698 putsect(p); 699 if(bp->fatbits == 12){ 700 if(n&1) 701 k >>= 4; 702 else 703 k &= 0xfff; 704 if(k >= 0xff8) 705 k |= 0xf000; 706 } 707 if(chatty > 1) 708 chat("fat(0x%x)=0x%x...", n, k); 709 return k < 0xfff8 ? k : -1; 710 } 711 712 void 713 putfat(Xfs *xf, int n, int val) 714 { 715 Dosbpb *bp = xf->ptr; 716 ulong k = 0, sect; Iosect *p; 717 int o; 718 719 switch(bp->fatbits){ 720 case 12: 721 k = (3*n)/2; break; 722 case 16: 723 k = 2*n; break; 724 } 725 if(k >= bp->fatsize*bp->sectsize) 726 panic("putfat"); 727 sect = k/bp->sectsize + bp->fataddr; 728 for(; sect<bp->rootaddr; sect+=bp->fatsize){ 729 o = k%bp->sectsize; 730 p = getsect(xf, sect); 731 if(p == 0) 732 continue; 733 switch(bp->fatbits){ 734 case 12: 735 if(n&1){ 736 p->iobuf[o] &= 0x0f; 737 p->iobuf[o++] |= val<<4; 738 if(o >= bp->sectsize){ 739 p->flags |= BMOD; 740 putsect(p); 741 p = getsect(xf, sect+1); 742 if(p == 0) 743 continue; 744 o = 0; 745 } 746 p->iobuf[o] = val>>4; 747 }else{ 748 p->iobuf[o++] = val; 749 if(o >= bp->sectsize){ 750 p->flags |= BMOD; 751 putsect(p); 752 p = getsect(xf, sect+1); 753 if(p == 0) 754 continue; 755 o = 0; 756 } 757 p->iobuf[o] &= 0xf0; 758 p->iobuf[o] |= (val>>8)&0x0f; 759 } 760 break; 761 case 16: 762 p->iobuf[o++] = val; 763 p->iobuf[o] = val>>8; 764 break; 765 } 766 p->flags |= BMOD; 767 putsect(p); 768 } 769 } 770 771 int 772 falloc(Xfs *xf) 773 { 774 Dosbpb *bp = xf->ptr; 775 int n, i, k; 776 Iosect *p; 777 778 n = bp->freeptr; 779 for(;;){ 780 if(getfat(xf, n) == 0) 781 break; 782 if(++n >= bp->fatclusters) 783 n = 2; 784 if(n == bp->freeptr) 785 return -1; 786 } 787 bp->freeptr = n+1; 788 if(bp->freeptr >= bp->fatclusters) 789 bp->freeptr = 2; 790 putfat(xf, n, 0xffff); 791 k = bp->dataaddr + (n-2)*bp->clustsize; 792 for(i=0; i<bp->clustsize; i++){ 793 p = getosect(xf, k+i); 794 if(p == 0) 795 break; 796 memset(p->iobuf, 0, bp->sectsize); 797 p->flags = BMOD; 798 putsect(p); 799 } 800 return n; 801 } 802 803 void 804 bootdump(int fd, Dosboot *b) 805 { 806 Biobuf *bp; 807 808 bp = malloc(sizeof(Biobuf)); 809 if(bp == 0) 810 panic("malloc"); 811 Binit(bp, fd, OWRITE); 812 Bprint(bp, "magic: 0x%2.2x 0x%2.2x 0x%2.2x\n", 813 b->magic[0], b->magic[1], b->magic[2]); 814 Bprint(bp, "version: \"%8.8s\"\n", b->version); 815 Bprint(bp, "sectsize: %d\n", GSHORT(b->sectsize)); 816 Bprint(bp, "allocsize: %d\n", b->clustsize); 817 Bprint(bp, "nresrv: %d\n", GSHORT(b->nresrv)); 818 Bprint(bp, "nfats: %d\n", b->nfats); 819 Bprint(bp, "rootsize: %d\n", GSHORT(b->rootsize)); 820 Bprint(bp, "volsize: %d\n", GSHORT(b->volsize)); 821 Bprint(bp, "mediadesc: 0x%2.2x\n", b->mediadesc); 822 Bprint(bp, "fatsize: %d\n", GSHORT(b->fatsize)); 823 Bprint(bp, "trksize: %d\n", GSHORT(b->trksize)); 824 Bprint(bp, "nheads: %d\n", GSHORT(b->nheads)); 825 Bprint(bp, "nhidden: %d\n", GLONG(b->nhidden)); 826 Bprint(bp, "bigvolsize: %d\n", GLONG(b->bigvolsize)); 827 Bprint(bp, "driveno: %d\n", b->driveno); 828 Bprint(bp, "reserved0: 0x%2.2x\n", b->reserved0); 829 Bprint(bp, "bootsig: 0x%2.2x\n", b->bootsig); 830 Bprint(bp, "volid: 0x%8.8x\n", GLONG(b->volid)); 831 Bprint(bp, "label: \"%11.11s\"\n", b->label); 832 Bterm(bp); 833 free(bp); 834 } 835 836 void 837 puttime(Dosdir *d, long s) 838 { 839 Tm *t; 840 ushort x; 841 842 if(s == 0) 843 s = time(0); 844 t = localtime(s); 845 846 x = (t->hour<<11) | (t->min<<5) | (t->sec>>1); 847 d->time[0] = x; 848 d->time[1] = x>>8; 849 x = ((t->year-80)<<9) | ((t->mon+1)<<5) | t->mday; 850 d->date[0] = x; 851 d->date[1] = x>>8; 852 } 853 854 static char dmsize[12] = { 855 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 856 }; 857 static int 858 dysize(int y) 859 { 860 861 if((y%4) == 0) 862 return 366; 863 return 365; 864 } 865 long 866 gtime(Dosdir *dp) 867 { 868 long t, noonGMT = 12*60*60; 869 int i, y, M, d, h, m, s; 870 871 i = GSHORT(dp->time); 872 h = i>>11; m = (i>>5)&63; s = (i&31)<<1; 873 i = GSHORT(dp->date); 874 y = 80+(i>>9); M = (i>>5)&15; d = i&31; 875 876 if (M < 1 || M > 12) 877 return 0; 878 if (d < 1 || d > dmsize[M-1]) 879 return 0; 880 if (h > 23) 881 return 0; 882 if (m > 59) 883 return 0; 884 if (s > 59) 885 return 0; 886 y += 1900; 887 t = 0; 888 for(i=1970; i<y; i++) 889 t += dysize(i); 890 if (dysize(y)==366 && M >= 3) 891 t++; 892 while(--M) 893 t += dmsize[M-1]; 894 t += d-1; 895 noonGMT += 24*60*60*t; 896 t = 24*t + h; 897 t = 60*t + m; 898 t = 60*t + s; 899 t += (12-localtime(noonGMT)->hour)*60*60; 900 return t; 901 } 902 903 void 904 dirdump(void *dbuf) 905 { 906 static char attrchar[] = "rhsvda67"; 907 char buf[72]; 908 Dosdir *d = dbuf; 909 int i, n = 0; 910 char *p; 911 912 if(!chatty) 913 return; 914 n += sprint(buf+n, "\"%.8s.%.3s\" ", d->name, d->ext); 915 p = attrchar+7; 916 for(i=0x80; i; i>>=1,p--) 917 n += sprint(buf+n, "%c", d->attr&i ? *p : '-'); 918 i = GSHORT(d->time); 919 n += sprint(buf+n, " %2.2d:%2.2d:%2.2d", i>>11, (i>>5)&63, (i&31)<<1); 920 i = GSHORT(d->date); 921 n += sprint(buf+n, " %2.2d.%2.2d.%2.2d", 80+(i>>9), (i>>5)&15, i&31); 922 sprint(buf+n, " %d %d", GSHORT(d->start), GSHORT(d->length)); 923 chat("%s\n", buf); 924 } 925