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