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