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.2 (Berkeley) 07/01/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 = 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 dinode *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->di_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->di_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 struct direct *readdir(); 168 register struct dinode *ip; 169 struct dirstuff dirp; 170 int len; 171 172 if (s == NULL || *s == '\0') 173 return (0); 174 ip = &io->i_ino; 175 if ((ip->di_mode&IFMT) != IFDIR) { 176 printf("not a directory\n"); 177 printf("%s: not a directory\n", s); 178 return (0); 179 } 180 if (ip->di_size == 0) { 181 printf("%s: zero length directory\n", s); 182 return (0); 183 } 184 len = strlen(s); 185 dirp.loc = 0; 186 dirp.io = io; 187 for (dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) { 188 if(dp->d_ino == 0) 189 continue; 190 if (dp->d_namlen == len && !strcmp(s, dp->d_name)) 191 return (dp->d_ino); 192 } 193 return (0); 194 } 195 196 /* 197 * get next entry in a directory. 198 */ 199 struct direct * 200 readdir(dirp) 201 register struct dirstuff *dirp; 202 { 203 register struct direct *dp; 204 register struct iob *io; 205 daddr_t lbn, d; 206 int off; 207 208 io = dirp->io; 209 for(;;) { 210 if (dirp->loc >= io->i_ino.di_size) 211 return (NULL); 212 off = blkoff(&io->i_fs, dirp->loc); 213 if (off == 0) { 214 lbn = lblkno(&io->i_fs, dirp->loc); 215 d = sbmap(io, lbn); 216 if(d == 0) 217 return NULL; 218 io->i_bn = fsbtodb(&io->i_fs, d) + io->i_boff; 219 io->i_ma = io->i_buf; 220 io->i_cc = dblksize(&io->i_fs, &io->i_ino, lbn); 221 if (devread(io) < 0) { 222 errno = io->i_error; 223 printf("bn %D: directory read error\n", 224 io->i_bn); 225 return (NULL); 226 } 227 } 228 dp = (struct direct *)(io->i_buf + off); 229 dirp->loc += dp->d_reclen; 230 if (dp->d_ino == 0) 231 continue; 232 return (dp); 233 } 234 } 235 236 lseek(fdesc, addr, ptr) 237 int fdesc, ptr; 238 off_t addr; 239 { 240 register struct iob *io; 241 242 #ifndef SMALL 243 if (ptr != 0) { 244 printf("Seek not from beginning of file\n"); 245 errno = EOFFSET; 246 return (-1); 247 } 248 #endif SMALL 249 fdesc -= 3; 250 if (fdesc < 0 || fdesc >= NFILES || 251 ((io = &iob[fdesc])->i_flgs & F_ALLOC) == 0) { 252 errno = EBADF; 253 return (-1); 254 } 255 io->i_offset = addr; 256 io->i_bn = addr / DEV_BSIZE; 257 io->i_cc = 0; 258 return (0); 259 } 260 261 getc(fdesc) 262 int fdesc; 263 { 264 register struct iob *io; 265 register struct fs *fs; 266 register char *p; 267 int c, lbn, off, size, diff; 268 269 270 if (fdesc >= 0 && fdesc <= 2) 271 return (getchar()); 272 fdesc -= 3; 273 if (fdesc < 0 || fdesc >= NFILES || 274 ((io = &iob[fdesc])->i_flgs&F_ALLOC) == 0) { 275 errno = EBADF; 276 return (-1); 277 } 278 p = io->i_ma; 279 if (io->i_cc <= 0) { 280 if ((io->i_flgs & F_FILE) != 0) { 281 diff = io->i_ino.di_size - io->i_offset; 282 if (diff <= 0) 283 return (-1); 284 fs = &io->i_fs; 285 lbn = lblkno(fs, io->i_offset); 286 io->i_bn = fsbtodb(fs, sbmap(io, lbn)) + io->i_boff; 287 off = blkoff(fs, io->i_offset); 288 size = dblksize(fs, &io->i_ino, lbn); 289 } else { 290 io->i_bn = io->i_offset / DEV_BSIZE; 291 off = 0; 292 size = DEV_BSIZE; 293 } 294 io->i_ma = io->i_buf; 295 io->i_cc = size; 296 if (devread(io) < 0) { 297 errno = io->i_error; 298 return (-1); 299 } 300 if ((io->i_flgs & F_FILE) != 0) { 301 if (io->i_offset - off + size >= io->i_ino.di_size) 302 io->i_cc = diff + off; 303 io->i_cc -= off; 304 } 305 p = &io->i_buf[off]; 306 } 307 io->i_cc--; 308 io->i_offset++; 309 c = (unsigned)*p++; 310 io->i_ma = p; 311 return (c); 312 } 313 314 int errno; 315 316 read(fdesc, buf, count) 317 int fdesc, count; 318 char *buf; 319 { 320 register i, size; 321 register struct iob *file; 322 register struct fs *fs; 323 int lbn, off; 324 325 errno = 0; 326 if (fdesc >= 0 & fdesc <= 2) { 327 i = count; 328 do { 329 *buf = getchar(); 330 } while (--i && *buf++ != '\n'); 331 return (count - i); 332 } 333 fdesc -= 3; 334 if (fdesc < 0 || fdesc >= NFILES || 335 ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) { 336 errno = EBADF; 337 return (-1); 338 } 339 if ((file->i_flgs&F_READ) == 0) { 340 errno = EBADF; 341 return (-1); 342 } 343 #ifndef SMALL 344 if ((file->i_flgs & F_FILE) == 0) { 345 file->i_cc = count; 346 file->i_ma = buf; 347 file->i_bn = file->i_boff + (file->i_offset / DEV_BSIZE); 348 i = devread(file); 349 file->i_offset += count; 350 if (i < 0) 351 errno = file->i_error; 352 return (i); 353 } 354 #endif SMALL 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 if (off == 0 && size <= i) { 369 file->i_bn = fsbtodb(fs, sbmap(file, lbn)) + 370 file->i_boff; 371 file->i_cc = size; 372 file->i_ma = buf; 373 if (devread(file) < 0) { 374 errno = file->i_error; 375 return (-1); 376 } 377 file->i_offset += size; 378 file->i_cc = 0; 379 buf += size; 380 i -= size; 381 } else { 382 size -= off; 383 if (size > i) 384 size = i; 385 i -= size; 386 do { 387 *buf++ = getc(fdesc+3); 388 } while (--size); 389 } 390 } 391 return (count); 392 } 393 394 #ifndef SMALL 395 write(fdesc, buf, count) 396 int fdesc, count; 397 char *buf; 398 { 399 register i; 400 register struct iob *file; 401 402 errno = 0; 403 if (fdesc >= 0 && fdesc <= 2) { 404 i = count; 405 while (i--) 406 putchar(0, *buf++); 407 return (count); 408 } 409 fdesc -= 3; 410 if (fdesc < 0 || fdesc >= NFILES || 411 ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) { 412 errno = EBADF; 413 return (-1); 414 } 415 if ((file->i_flgs&F_WRITE) == 0) { 416 errno = EBADF; 417 return (-1); 418 } 419 file->i_cc = count; 420 file->i_ma = buf; 421 file->i_bn = file->i_boff + (file->i_offset / DEV_BSIZE); 422 i = devwrite(file); 423 file->i_offset += count; 424 if (i < 0) 425 errno = file->i_error; 426 return (i); 427 } 428 #endif SMALL 429 430 int openfirst = 1; 431 #ifdef notyet 432 int opendev; /* last device opened; for boot to set bootdev */ 433 extern int bootdev; 434 #endif notyet 435 436 open(str, how) 437 char *str; 438 int how; 439 { 440 register char *cp; 441 int i; 442 register struct iob *file; 443 register struct devsw *dp; 444 int fdesc; 445 long atol(); 446 447 if (openfirst) { 448 for (i = 0; i < NFILES; i++) 449 iob[i].i_flgs = 0; 450 openfirst = 0; 451 } 452 453 for (fdesc = 0; fdesc < NFILES; fdesc++) 454 if (iob[fdesc].i_flgs == 0) 455 goto gotfile; 456 _stop("No more file slots"); 457 gotfile: 458 (file = &iob[fdesc])->i_flgs |= F_ALLOC; 459 460 #ifdef notyet 461 for (cp = str; *cp && *cp != '/' && *cp != ':'; cp++) 462 ; 463 if (*cp != ':') { 464 /* default bootstrap unit and device */ 465 file->i_dev = bootdev; 466 cp = str; 467 } else { 468 # define isdigit(n) ((n>='0') && (n<='9')) 469 /* 470 * syntax for possible device name: 471 * <alpha-string><digit-string><letter>: 472 */ 473 for (cp = str; *cp != ':' && !isdigit(*cp); cp++) 474 ; 475 for (dp = devsw; dp->dv_name; dp++) { 476 if (!strncmp(str, dp->dv_name,cp-str)) 477 goto gotdev; 478 } 479 printf("unknown device\n"); 480 file->i_flgs = 0; 481 errno = EDEV; 482 return (-1); 483 gotdev: 484 i = 0; 485 while (*cp >= '0' && *cp <= '9') 486 i = i * 10 + *cp++ - '0'; 487 if (i < 0 || i > 255) { 488 printf("minor device number out of range (0-255)\n"); 489 file->i_flgs = 0; 490 errno = EUNIT; 491 return (-1); 492 } 493 if (*cp >= 'a' && *cp <= 'h') { 494 if (i > 31) { 495 printf("unit number out of range (0-31)\n"); 496 file->i_flgs = 0; 497 errno = EUNIT; 498 return (-1); 499 } 500 i = make_minor(i, *cp++ - 'a'); 501 } 502 503 if (*cp++ != ':') { 504 printf("incorrect device specification\n"); 505 file->i_flgs = 0; 506 errno = EOFFSET; 507 return (-1); 508 } 509 opendev = file->i_dev = makedev(dp-devsw, i); 510 } 511 file->i_boff = 0; 512 devopen(file); 513 if (cp != str && *cp == '\0') { 514 file->i_flgs |= how+1; 515 file->i_cc = 0; 516 file->i_offset = 0; 517 return (fdesc+3); 518 } 519 #else notyet 520 for (cp = str; *cp && *cp != '('; cp++) 521 ; 522 if (*cp != '(') { 523 printf("Bad device\n"); 524 file->i_flgs = 0; 525 errno = EDEV; 526 return (-1); 527 } 528 *cp = '\0'; 529 for (dp = devsw; dp->dv_name; dp++) 530 if (!strcmp(str, dp->dv_name)) 531 break; 532 *cp++ = '('; 533 if (dp->dv_name == NULL) { 534 printf("Unknown device\n"); 535 file->i_flgs = 0; 536 errno = ENXIO; 537 return (-1); 538 } 539 file->i_dev = dp-devsw; 540 file->i_unit = *cp++ - '0'; 541 if (*cp >= '0' && *cp <= '9') 542 file->i_unit = file->i_unit * 10 + *cp++ - '0'; 543 if (file->i_unit < 0 || file->i_unit > 63) { 544 printf("Bad unit specifier\n"); 545 file->i_flgs = 0; 546 errno = EUNIT; 547 return (-1); 548 } 549 if (*cp++ != ',') { 550 badoff: 551 printf("Missing offset specification\n"); 552 file->i_flgs = 0; 553 errno = EOFFSET; 554 return (-1); 555 } 556 file->i_boff = atol(cp); 557 for (;;) { 558 if (*cp == ')') 559 break; 560 if (*cp++) 561 continue; 562 goto badoff; 563 } 564 devopen(file); 565 if (*++cp == '\0') { 566 file->i_flgs |= how+1; 567 file->i_cc = 0; 568 file->i_offset = 0; 569 return (fdesc+3); 570 } 571 #endif notyet 572 file->i_ma = (char *)(&file->i_fs); 573 file->i_cc = SBSIZE; 574 file->i_bn = SBLOCK + file->i_boff; 575 file->i_offset = 0; 576 if (devread(file) < 0) { 577 errno = file->i_error; 578 printf("super block read error\n"); 579 return (-1); 580 } 581 if ((i = find(cp, file)) == 0) { 582 file->i_flgs = 0; 583 errno = ESRCH; 584 return (-1); 585 } 586 #ifndef SMALL 587 if (how != 0) { 588 printf("Can't write files yet.. Sorry\n"); 589 file->i_flgs = 0; 590 errno = EIO; 591 return (-1); 592 } 593 #endif SMALL 594 if (openi(i, file) < 0) { 595 errno = file->i_error; 596 return (-1); 597 } 598 file->i_offset = 0; 599 file->i_cc = 0; 600 file->i_flgs |= F_FILE | (how+1); 601 return (fdesc+3); 602 } 603 604 close(fdesc) 605 int fdesc; 606 { 607 struct iob *file; 608 609 fdesc -= 3; 610 if (fdesc < 0 || fdesc >= NFILES || 611 ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) { 612 errno = EBADF; 613 return (-1); 614 } 615 if ((file->i_flgs&F_FILE) == 0) 616 devclose(file); 617 file->i_flgs = 0; 618 return (0); 619 } 620 621 exit() 622 { 623 _stop("Exit called"); 624 } 625 626 _stop(s) 627 char *s; 628 { 629 static int stopped = 0; 630 int i; 631 632 if (!stopped) { 633 stopped++; 634 for (i = 0; i < NFILES; i++) 635 if (iob[i].i_flgs != 0) 636 close(i); 637 } 638 printf("%s\n", s); 639 _rtt(); 640 } 641 642 #ifndef SMALL 643 ioctl(fdesc, cmd, arg) 644 int fdesc, cmd; 645 char *arg; 646 { 647 register struct iob *file; 648 int error = 0; 649 650 fdesc -= 3; 651 if (fdesc < 0 || fdesc >= NFILES || 652 ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) { 653 errno = EBADF; 654 return (-1); 655 } 656 switch (cmd) { 657 658 case SAIOHDR: 659 file->i_flgs |= F_HDR; 660 break; 661 662 case SAIOCHECK: 663 file->i_flgs |= F_CHECK; 664 break; 665 666 case SAIOHCHECK: 667 file->i_flgs |= F_HCHECK; 668 break; 669 670 case SAIONOBAD: 671 file->i_flgs |= F_NBSF; 672 break; 673 674 case SAIODOBAD: 675 file->i_flgs &= ~F_NBSF; 676 break; 677 678 default: 679 error = devioctl(file, cmd, arg); 680 break; 681 } 682 if (error < 0) 683 errno = file->i_error; 684 return (error); 685 } 686 687 extern char end; 688 static caddr_t theend = 0; 689 690 caddr_t 691 brk(addr) 692 char *addr; 693 { 694 char stkloc; 695 696 if (theend == (caddr_t)0) 697 theend = &end; 698 if (addr > &stkloc || addr < &end) 699 return((caddr_t)-1); 700 if (addr > theend) 701 bzero(theend, addr-theend); 702 theend = addr; 703 return(0); 704 } 705 706 caddr_t 707 sbrk(incr) 708 int incr; 709 { 710 caddr_t obrk, brk(); 711 712 if (theend == (caddr_t)0) 713 theend = &end; 714 obrk = theend; 715 if (brk(theend+incr) == (caddr_t)-1) 716 return((caddr_t)-1); 717 return(obrk); 718 } 719 720 getpagesize() 721 { 722 return(NBPG); 723 } 724 725 getdtablesize() 726 { 727 return(NFILES); 728 } 729 730 fstat(fdesc, sb) 731 struct stat *sb; 732 { 733 register struct iob *io; 734 735 fdesc -= 3; 736 if (fdesc < 0 || fdesc >= NFILES || 737 ((io = &iob[fdesc])->i_flgs & F_ALLOC) == 0) { 738 errno = EBADF; 739 return (-1); 740 } 741 /* only important stuff */ 742 sb->st_mode = io->i_ino.di_mode; 743 sb->st_uid = io->i_ino.di_uid; 744 sb->st_gid = io->i_ino.di_gid; 745 sb->st_size = io->i_ino.di_size; 746 return (0); 747 } 748 749 stat(str, sb) 750 { 751 /* the easy way */ 752 int f, rv = 0; 753 754 f = open(str, 0); 755 if (f < 0 || fstat(f, sb) < 0) 756 rv = -1; 757 (void) close(f); 758 return(rv); 759 } 760 761 #endif SMALL 762