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