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