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