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