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