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