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