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