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