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