1 /* 2 * Copyright (c) 1982, 1986 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 * 6 * sys.c 1.2 86/12/18 7 * 8 * from @(#)sys.c 7.1 (Berkeley) 6/5/86 9 */ 10 11 #include "../machine/mtpr.h" 12 13 #include "param.h" 14 #include "inode.h" 15 #include "fs.h" 16 #include "dir.h" 17 #include "saio.h" 18 19 ino_t dlook(); 20 21 struct dirstuff { 22 int loc; 23 struct iob *io; 24 }; 25 26 static 27 openi(n, io) 28 register struct iob *io; 29 { 30 register struct dinode *dp; 31 int cc; 32 33 io->i_offset = 0; 34 io->i_bn = fsbtodb(&io->i_fs, itod(&io->i_fs, n)) + io->i_boff; 35 io->i_cc = io->i_fs.fs_bsize; 36 io->i_ma = io->i_buf; 37 cc = devread(io); 38 dp = (struct dinode *)io->i_buf; 39 io->i_ino.i_ic = dp[itoo(&io->i_fs, n)].di_ic; 40 return (cc); 41 } 42 43 static 44 find(path, file) 45 register char *path; 46 struct iob *file; 47 { 48 register char *q; 49 char c; 50 int n; 51 52 if (path==NULL || *path=='\0') { 53 printf("null path\n"); 54 return (0); 55 } 56 57 if (openi((ino_t) ROOTINO, file) < 0) { 58 printf("can't read root inode\n"); 59 return (0); 60 } 61 while (*path) { 62 while (*path == '/') 63 path++; 64 q = path; 65 while(*q != '/' && *q != '\0') 66 q++; 67 c = *q; 68 *q = '\0'; 69 if (q == path) path = "." ; /* "/" means "/." */ 70 71 if ((n = dlook(path, file)) != 0) { 72 if (c == '\0') 73 break; 74 if (openi(n, file) < 0) 75 return (0); 76 *q = c; 77 path = q; 78 continue; 79 } else { 80 printf("%s: not found\n", path); 81 return (0); 82 } 83 } 84 return (n); 85 } 86 87 static daddr_t 88 sbmap(io, bn) 89 register struct iob *io; 90 daddr_t bn; 91 { 92 register struct inode *ip; 93 int i, j, sh; 94 daddr_t nb, *bap; 95 96 ip = &io->i_ino; 97 if (bn < 0) { 98 printf("bn negative\n"); 99 return ((daddr_t)0); 100 } 101 102 /* 103 * blocks 0..NDADDR are direct blocks 104 */ 105 if(bn < NDADDR) { 106 nb = ip->i_db[bn]; 107 return (nb); 108 } 109 110 /* 111 * addresses NIADDR have single and double indirect blocks. 112 * the first step is to determine how many levels of indirection. 113 */ 114 sh = 1; 115 bn -= NDADDR; 116 for (j = NIADDR; j > 0; j--) { 117 sh *= NINDIR(&io->i_fs); 118 if (bn < sh) 119 break; 120 bn -= sh; 121 } 122 if (j == 0) { 123 printf("bn ovf %D\n", bn); 124 return ((daddr_t)0); 125 } 126 127 /* 128 * fetch the first indirect block address from the inode 129 */ 130 nb = ip->i_ib[NIADDR - j]; 131 if (nb == 0) { 132 printf("bn void %D\n",bn); 133 return ((daddr_t)0); 134 } 135 136 /* 137 * fetch through the indirect blocks 138 */ 139 for (; j <= NIADDR; j++) { 140 if (blknos[j] != nb) { 141 io->i_bn = fsbtodb(&io->i_fs, nb) + io->i_boff; 142 io->i_ma = b[j]; 143 io->i_cc = io->i_fs.fs_bsize; 144 if (devread(io) != io->i_fs.fs_bsize) { 145 if (io->i_error) 146 errno = io->i_error; 147 printf("bn %D: read error\n", io->i_bn); 148 return ((daddr_t)0); 149 } 150 blknos[j] = nb; 151 } 152 bap = (daddr_t *)b[j]; 153 sh /= NINDIR(&io->i_fs); 154 i = (bn / sh) % NINDIR(&io->i_fs); 155 nb = bap[i]; 156 if(nb == 0) { 157 printf("bn void %D\n",bn); 158 return ((daddr_t)0); 159 } 160 } 161 return (nb); 162 } 163 164 static ino_t 165 dlook(s, io) 166 char *s; 167 register struct iob *io; 168 { 169 register struct direct *dp; 170 register struct inode *ip; 171 struct dirstuff dirp; 172 int len; 173 174 if (s == NULL || *s == '\0') 175 return (0); 176 ip = &io->i_ino; 177 if ((ip->i_mode&IFMT) != IFDIR) { 178 printf("not a directory\n"); 179 printf("%s: not a directory\n", s); 180 return (0); 181 } 182 if (ip->i_size == 0) { 183 printf("%s: zero length directory\n", s); 184 return (0); 185 } 186 len = strlen(s); 187 dirp.loc = 0; 188 dirp.io = io; 189 for (dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) { 190 if(dp->d_ino == 0) 191 continue; 192 if (dp->d_namlen == len && !strcmp(s, dp->d_name)) 193 return (dp->d_ino); 194 } 195 return (0); 196 } 197 198 /* 199 * get next entry in a directory. 200 */ 201 struct direct * 202 readdir(dirp) 203 register struct dirstuff *dirp; 204 { 205 register struct direct *dp; 206 register struct iob *io; 207 daddr_t lbn, d; 208 int off; 209 210 io = dirp->io; 211 for(;;) { 212 if (dirp->loc >= io->i_ino.i_size) 213 return (NULL); 214 off = blkoff(&io->i_fs, dirp->loc); 215 if (off == 0) { 216 lbn = lblkno(&io->i_fs, dirp->loc); 217 d = sbmap(io, lbn); 218 if(d == 0) 219 return NULL; 220 io->i_bn = fsbtodb(&io->i_fs, d) + io->i_boff; 221 io->i_ma = io->i_buf; 222 io->i_cc = blksize(&io->i_fs, &io->i_ino, lbn); 223 if (devread(io) < 0) { 224 errno = io->i_error; 225 printf("bn %D: directory read error\n", 226 io->i_bn); 227 return (NULL); 228 } 229 } 230 dp = (struct direct *)(io->i_buf + off); 231 dirp->loc += dp->d_reclen; 232 if (dp->d_ino == 0) 233 continue; 234 return (dp); 235 } 236 } 237 238 lseek(fdesc, addr, ptr) 239 int fdesc, ptr; 240 off_t addr; 241 { 242 register struct iob *io; 243 244 #ifndef SMALL 245 if (ptr != 0) { 246 printf("Seek not from beginning of file\n"); 247 errno = EOFFSET; 248 return (-1); 249 } 250 #endif SMALL 251 fdesc -= 3; 252 if (fdesc < 0 || fdesc >= NFILES || 253 ((io = &iob[fdesc])->i_flgs & F_ALLOC) == 0) { 254 errno = EBADF; 255 return (-1); 256 } 257 io->i_offset = addr; 258 io->i_bn = addr / DEV_BSIZE; 259 io->i_cc = 0; 260 return (0); 261 } 262 263 getc(fdesc) 264 int fdesc; 265 { 266 register struct iob *io; 267 register struct fs *fs; 268 register char *p; 269 int c, lbn, off, size, diff; 270 271 272 if (fdesc >= 0 && fdesc <= 2) 273 return (getchar()); 274 fdesc -= 3; 275 if (fdesc < 0 || fdesc >= NFILES || 276 ((io = &iob[fdesc])->i_flgs&F_ALLOC) == 0) { 277 errno = EBADF; 278 return (-1); 279 } 280 p = io->i_ma; 281 if (io->i_cc <= 0) { 282 if ((io->i_flgs & F_FILE) != 0) { 283 diff = io->i_ino.i_size - io->i_offset; 284 if (diff <= 0) 285 return (-1); 286 fs = &io->i_fs; 287 lbn = lblkno(fs, io->i_offset); 288 io->i_bn = fsbtodb(fs, sbmap(io, lbn)) + io->i_boff; 289 off = blkoff(fs, io->i_offset); 290 size = blksize(fs, &io->i_ino, lbn); 291 } else { 292 io->i_bn = io->i_offset / DEV_BSIZE; 293 off = 0; 294 size = DEV_BSIZE; 295 } 296 io->i_ma = io->i_buf; 297 io->i_cc = size; 298 if (devread(io) < 0) { 299 errno = io->i_error; 300 return (-1); 301 } 302 if ((io->i_flgs & F_FILE) != 0) { 303 if (io->i_offset - off + size >= io->i_ino.i_size) 304 io->i_cc = diff + off; 305 io->i_cc -= off; 306 } 307 p = &io->i_buf[off]; 308 } 309 io->i_cc--; 310 io->i_offset++; 311 c = (unsigned)*p++; 312 io->i_ma = p; 313 return (c); 314 } 315 316 int errno; 317 318 read(fdesc, buf, count) 319 int fdesc, count; 320 char *buf; 321 { 322 register i, size; 323 register struct iob *file; 324 register struct fs *fs; 325 int lbn, off; 326 327 errno = 0; 328 if (fdesc >= 0 & fdesc <= 2) { 329 i = count; 330 do { 331 *buf = getchar(); 332 } while (--i && *buf++ != '\n'); 333 return (count - i); 334 } 335 fdesc -= 3; 336 if (fdesc < 0 || fdesc >= NFILES || 337 ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) { 338 errno = EBADF; 339 return (-1); 340 } 341 if ((file->i_flgs&F_READ) == 0) { 342 errno = EBADF; 343 return (-1); 344 } 345 #ifndef SMALL 346 if ((file->i_flgs & F_FILE) == 0) { 347 file->i_cc = count; 348 file->i_ma = buf; 349 file->i_bn = file->i_boff + (file->i_offset / DEV_BSIZE); 350 i = devread(file); 351 if (i < 0) 352 errno = file->i_error; 353 else 354 file->i_offset += i; 355 return (i); 356 } 357 #endif SMALL 358 if (file->i_offset+count > file->i_ino.i_size) 359 count = file->i_ino.i_size - file->i_offset; 360 if ((i = count) <= 0) 361 return (0); 362 /* 363 * While reading full blocks, do I/O into user buffer. 364 * Anything else uses getc(). 365 */ 366 fs = &file->i_fs; 367 while (i) { 368 off = blkoff(fs, file->i_offset); 369 lbn = lblkno(fs, file->i_offset); 370 size = blksize(fs, &file->i_ino, lbn); 371 if (off == 0 && size <= i) { 372 file->i_bn = fsbtodb(fs, sbmap(file, lbn)) + 373 file->i_boff; 374 file->i_cc = size; 375 file->i_ma = buf; 376 if (devread(file) < 0) { 377 errno = file->i_error; 378 return (-1); 379 } 380 file->i_offset += size; 381 file->i_cc = 0; 382 buf += size; 383 i -= size; 384 } else { 385 size -= off; 386 if (size > i) 387 size = i; 388 i -= size; 389 do { 390 *buf++ = getc(fdesc+3); 391 } while (--size); 392 } 393 } 394 return (count); 395 } 396 397 #ifndef SMALL 398 write(fdesc, buf, count) 399 int fdesc, count; 400 char *buf; 401 { 402 register i; 403 register struct iob *file; 404 405 errno = 0; 406 if (fdesc >= 0 && fdesc <= 2) { 407 i = count; 408 while (i--) 409 putchar(*buf++); 410 return (count); 411 } 412 fdesc -= 3; 413 if (fdesc < 0 || fdesc >= NFILES || 414 ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) { 415 errno = EBADF; 416 return (-1); 417 } 418 if ((file->i_flgs&F_WRITE) == 0) { 419 errno = EBADF; 420 return (-1); 421 } 422 file->i_cc = count; 423 file->i_ma = buf; 424 file->i_bn = file->i_boff + (file->i_offset / DEV_BSIZE); 425 i = devwrite(file); 426 file->i_offset += count; 427 if (i < 0) 428 errno = file->i_error; 429 return (i); 430 } 431 #endif SMALL 432 433 int openfirst = 1; 434 #ifdef notyet 435 int opendev; /* last device opened; for boot to set bootdev */ 436 extern int bootdev; 437 #endif notyet 438 439 open(str, how) 440 char *str; 441 int how; 442 { 443 register char *cp; 444 int i; 445 register struct iob *file; 446 register struct devsw *dp; 447 int fdesc; 448 long atol(); 449 450 if (openfirst) { 451 for (i = 0; i < NFILES; i++) 452 iob[i].i_flgs = 0; 453 openfirst = 0; 454 } 455 456 for (fdesc = 0; fdesc < NFILES; fdesc++) 457 if (iob[fdesc].i_flgs == 0) 458 goto gotfile; 459 _stop("No more file slots"); 460 gotfile: 461 (file = &iob[fdesc])->i_flgs |= F_ALLOC; 462 463 #ifdef notyet 464 for (cp = str; *cp && *cp != '/' && *cp != ':'; cp++) 465 ; 466 if (*cp != ':') { 467 /* default bootstrap unit and device */ 468 file->i_ino.i_dev = bootdev; 469 cp = str; 470 } else { 471 # define isdigit(n) ((n>='0') && (n<='9')) 472 /* 473 * syntax for possible device name: 474 * <alpha-string><digit-string><letter>: 475 */ 476 for (cp = str; *cp != ':' && !isdigit(*cp); cp++) 477 ; 478 for (dp = devsw; dp->dv_name; dp++) { 479 if (!strncmp(str, dp->dv_name,cp-str)) 480 goto gotdev; 481 } 482 printf("unknown device\n"); 483 file->i_flgs = 0; 484 errno = EDEV; 485 return (-1); 486 gotdev: 487 i = 0; 488 while (*cp >= '0' && *cp <= '9') 489 i = i * 10 + *cp++ - '0'; 490 if (i < 0 || i > 255) { 491 printf("minor device number out of range (0-255)\n"); 492 file->i_flgs = 0; 493 errno = EUNIT; 494 return (-1); 495 } 496 if (*cp >= 'a' && *cp <= 'h') { 497 if (i > 31) { 498 printf("unit number out of range (0-31)\n"); 499 file->i_flgs = 0; 500 errno = EUNIT; 501 return (-1); 502 } 503 i = make_minor(i, *cp++ - 'a'); 504 } 505 506 if (*cp++ != ':') { 507 printf("incorrect device specification\n"); 508 file->i_flgs = 0; 509 errno = EOFFSET; 510 return (-1); 511 } 512 opendev = file->i_ino.i_dev = makedev(dp-devsw, i); 513 } 514 file->i_boff = 0; 515 devopen(file); 516 if (cp != str && *cp == '\0') { 517 file->i_flgs |= how+1; 518 file->i_cc = 0; 519 file->i_offset = 0; 520 return (fdesc+3); 521 } 522 #else notyet 523 for (cp = str; *cp && *cp != '('; cp++) 524 ; 525 if (*cp != '(') { 526 printf("Bad device\n"); 527 file->i_flgs = 0; 528 errno = EDEV; 529 return (-1); 530 } 531 *cp++ = '\0'; 532 for (dp = devsw; dp->dv_name; dp++) { 533 if (!strcmp(str, dp->dv_name)) 534 goto gotdev; 535 } 536 printf("Unknown device\n"); 537 file->i_flgs = 0; 538 errno = ENXIO; 539 return (-1); 540 gotdev: 541 *(cp-1) = '('; 542 file->i_ino.i_dev = dp-devsw; 543 file->i_unit = *cp++ - '0'; 544 if (*cp >= '0' && *cp <= '9') 545 file->i_unit = file->i_unit * 10 + *cp++ - '0'; 546 if (file->i_unit < 0 || file->i_unit > 63) { 547 printf("Bad unit specifier\n"); 548 file->i_flgs = 0; 549 errno = EUNIT; 550 return (-1); 551 } 552 if (*cp++ != ',') { 553 badoff: 554 printf("Missing offset specification\n"); 555 file->i_flgs = 0; 556 errno = EOFFSET; 557 return (-1); 558 } 559 file->i_boff = atol(cp); 560 for (;;) { 561 if (*cp == ')') 562 break; 563 if (*cp++) 564 continue; 565 goto badoff; 566 } 567 file->i_flgs |= how+1; 568 devopen(file); 569 if (*++cp == '\0') { 570 file->i_cc = 0; 571 file->i_offset = 0; 572 return (fdesc+3); 573 } 574 #endif notyet 575 file->i_ma = (char *)(&file->i_fs); 576 file->i_cc = SBSIZE; 577 file->i_bn = SBLOCK + file->i_boff; 578 file->i_offset = 0; 579 if (devread(file) < 0) { 580 errno = file->i_error; 581 printf("super block read error\n"); 582 return (-1); 583 } 584 if ((i = find(cp, file)) == 0) { 585 file->i_flgs = 0; 586 errno = ESRCH; 587 return (-1); 588 } 589 #ifndef SMALL 590 if (how != 0) { 591 printf("Can't write files yet.. Sorry\n"); 592 file->i_flgs = 0; 593 errno = EIO; 594 return (-1); 595 } 596 #endif SMALL 597 if (openi(i, file) < 0) { 598 errno = file->i_error; 599 return (-1); 600 } 601 file->i_offset = 0; 602 file->i_cc = 0; 603 file->i_flgs |= F_FILE; 604 return (fdesc+3); 605 } 606 607 close(fdesc) 608 int fdesc; 609 { 610 struct iob *file; 611 612 fdesc -= 3; 613 if (fdesc < 0 || fdesc >= NFILES || 614 ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) { 615 errno = EBADF; 616 return (-1); 617 } 618 if ((file->i_flgs&F_FILE) == 0) 619 devclose(file); 620 file->i_flgs = 0; 621 return (0); 622 } 623 624 #ifndef SMALL 625 ioctl(fdesc, cmd, arg) 626 int fdesc, cmd; 627 char *arg; 628 { 629 register struct iob *file; 630 int error = 0; 631 632 fdesc -= 3; 633 if (fdesc < 0 || fdesc >= NFILES || 634 ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) { 635 errno = EBADF; 636 return (-1); 637 } 638 switch (cmd) { 639 640 case SAIOHDR: 641 file->i_flgs |= F_HDR; 642 break; 643 644 case SAIOCHECK: 645 file->i_flgs |= F_CHECK; 646 break; 647 648 case SAIOHCHECK: 649 file->i_flgs |= F_HCHECK; 650 break; 651 652 case SAIONOBAD: 653 file->i_flgs |= F_NBSF; 654 break; 655 656 case SAIODOBAD: 657 file->i_flgs &= ~F_NBSF; 658 break; 659 660 default: 661 error = devioctl(file, cmd, arg); 662 break; 663 } 664 if (error < 0) 665 errno = file->i_error; 666 return (error); 667 } 668 #endif SMALL 669 670 exit() 671 { 672 _stop("Exit called"); 673 } 674 675 _stop(s) 676 char *s; 677 { 678 int i; 679 680 for (i = 0; i < NFILES; i++) 681 if (iob[i].i_flgs != 0) 682 close(i); 683 printf("%s\n", s); 684 _rtt(); 685 } 686 687 #ifdef tahoe 688 trap(ps) 689 int ps; 690 { 691 printf("Trap %o\n", ps); 692 for (;;) 693 ; 694 } 695 696 uncache (addr) 697 char *addr; 698 { 699 /* Return *(addr-0x4000); DIRTY assumes this address is valid */ 700 mtpr(PDCS, addr); 701 } 702 #endif 703