1*11083Ssam /* sys.c 4.10 83/02/16 */ 2327Sbill 36068Smckusic #include "../h/param.h" 46068Smckusic #include "../h/inode.h" 56068Smckusic #include "../h/fs.h" 67446Sroot #include "../h/dir.h" 7327Sbill #include "saio.h" 8327Sbill 9327Sbill ino_t dlook(); 10327Sbill 116068Smckusic struct dirstuff { 126068Smckusic int loc; 136068Smckusic struct iob *io; 146068Smckusic }; 156068Smckusic 16327Sbill static 1710022Ssam openi(n, io) 186068Smckusic register struct iob *io; 19327Sbill { 20327Sbill register struct dinode *dp; 21*11083Ssam int cc; 22327Sbill 23327Sbill io->i_offset = 0; 246068Smckusic io->i_bn = fsbtodb(&io->i_fs, itod(&io->i_fs, n)) + io->i_boff; 256068Smckusic io->i_cc = io->i_fs.fs_bsize; 26327Sbill io->i_ma = io->i_buf; 27*11083Ssam cc = devread(io); 28327Sbill dp = (struct dinode *)io->i_buf; 296068Smckusic io->i_ino.i_ic = dp[itoo(&io->i_fs, n)].di_ic; 30*11083Ssam return (cc); 31327Sbill } 32327Sbill 33327Sbill static 34327Sbill find(path, file) 356068Smckusic register char *path; 366068Smckusic struct iob *file; 37327Sbill { 38327Sbill register char *q; 39327Sbill char c; 40327Sbill int n; 41327Sbill 42327Sbill if (path==NULL || *path=='\0') { 43327Sbill printf("null path\n"); 4410022Ssam return (0); 45327Sbill } 46327Sbill 47*11083Ssam if (openi((ino_t) ROOTINO, file) < 0) { 48*11083Ssam printf("can't read root inode\n"); 49*11083Ssam return (0); 50*11083Ssam } 51327Sbill while (*path) { 52327Sbill while (*path == '/') 53327Sbill path++; 54327Sbill q = path; 55327Sbill while(*q != '/' && *q != '\0') 56327Sbill q++; 57327Sbill c = *q; 58327Sbill *q = '\0'; 59327Sbill 60*11083Ssam if ((n = dlook(path, file)) != 0) { 61*11083Ssam if (c == '\0') 62327Sbill break; 63*11083Ssam if (openi(n, file) < 0) 64*11083Ssam return (0); 65327Sbill *q = c; 66327Sbill path = q; 67327Sbill continue; 68327Sbill } else { 69*11083Ssam printf("%s not found\n", path); 7010022Ssam return (0); 71327Sbill } 72327Sbill } 7310022Ssam return (n); 74327Sbill } 75327Sbill 76327Sbill static daddr_t 77327Sbill sbmap(io, bn) 786068Smckusic register struct iob *io; 796068Smckusic daddr_t bn; 80327Sbill { 81327Sbill register struct inode *ip; 826068Smckusic int i, j, sh; 83327Sbill daddr_t nb, *bap; 84327Sbill 85327Sbill ip = &io->i_ino; 866068Smckusic if (bn < 0) { 87327Sbill printf("bn negative\n"); 8810022Ssam return ((daddr_t)0); 89327Sbill } 90327Sbill 91327Sbill /* 926068Smckusic * blocks 0..NDADDR are direct blocks 93327Sbill */ 946068Smckusic if(bn < NDADDR) { 956068Smckusic nb = ip->i_db[bn]; 9610022Ssam return (nb); 97327Sbill } 98327Sbill 99327Sbill /* 1006068Smckusic * addresses NIADDR have single and double indirect blocks. 1016068Smckusic * the first step is to determine how many levels of indirection. 102327Sbill */ 1036068Smckusic sh = 1; 1046068Smckusic bn -= NDADDR; 1056068Smckusic for (j = NIADDR; j > 0; j--) { 1066068Smckusic sh *= NINDIR(&io->i_fs); 1076068Smckusic if (bn < sh) 108327Sbill break; 1096068Smckusic bn -= sh; 110327Sbill } 1116068Smckusic if (j == 0) { 1126068Smckusic printf("bn ovf %D\n", bn); 1136068Smckusic return ((daddr_t)0); 114327Sbill } 115327Sbill 116327Sbill /* 1176068Smckusic * fetch the first indirect block address from the inode 118327Sbill */ 1196068Smckusic nb = ip->i_ib[NIADDR - j]; 1206068Smckusic if (nb == 0) { 121327Sbill printf("bn void %D\n",bn); 12210022Ssam return ((daddr_t)0); 123327Sbill } 124327Sbill 125327Sbill /* 126327Sbill * fetch through the indirect blocks 127327Sbill */ 1286068Smckusic for (; j <= NIADDR; j++) { 129327Sbill if (blknos[j] != nb) { 1306068Smckusic io->i_bn = fsbtodb(&io->i_fs, nb) + io->i_boff; 131327Sbill io->i_ma = b[j]; 1326068Smckusic io->i_cc = io->i_fs.fs_bsize; 133*11083Ssam if (devread(io) != io->i_fs.fs_bsize) { 134*11083Ssam if (io->i_error) 135*11083Ssam errno = io->i_error; 136*11083Ssam printf("bn %D: read error\n", io->i_bn); 137*11083Ssam return ((daddr_t)0); 138*11083Ssam } 139327Sbill blknos[j] = nb; 140327Sbill } 141327Sbill bap = (daddr_t *)b[j]; 1426068Smckusic sh /= NINDIR(&io->i_fs); 1436068Smckusic i = (bn / sh) % NINDIR(&io->i_fs); 144327Sbill nb = bap[i]; 145327Sbill if(nb == 0) { 146327Sbill printf("bn void %D\n",bn); 14710022Ssam return ((daddr_t)0); 148327Sbill } 149327Sbill } 15010022Ssam return (nb); 151327Sbill } 152327Sbill 153327Sbill static ino_t 154327Sbill dlook(s, io) 1556068Smckusic char *s; 1566068Smckusic register struct iob *io; 157327Sbill { 158327Sbill register struct direct *dp; 159327Sbill register struct inode *ip; 1606068Smckusic struct dirstuff dirp; 1616068Smckusic int len; 162327Sbill 1636068Smckusic if (s == NULL || *s == '\0') 16410022Ssam return (0); 165327Sbill ip = &io->i_ino; 1666068Smckusic if ((ip->i_mode&IFMT) != IFDIR) { 167327Sbill printf("not a directory\n"); 16810022Ssam return (0); 169327Sbill } 1706068Smckusic if (ip->i_size == 0) { 171327Sbill printf("zero length directory\n"); 17210022Ssam return (0); 173327Sbill } 1746068Smckusic len = strlen(s); 1756068Smckusic dirp.loc = 0; 1766068Smckusic dirp.io = io; 1776068Smckusic for (dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) { 1786068Smckusic if(dp->d_ino == 0) 1796068Smckusic continue; 1806068Smckusic if (dp->d_namlen == len && !strcmp(s, dp->d_name)) 18110022Ssam return (dp->d_ino); 182327Sbill } 18310022Ssam return (0); 184327Sbill } 185327Sbill 1866068Smckusic /* 1876068Smckusic * get next entry in a directory. 1886068Smckusic */ 1896068Smckusic struct direct * 1906068Smckusic readdir(dirp) 1916068Smckusic register struct dirstuff *dirp; 192327Sbill { 1936068Smckusic register struct direct *dp; 1946068Smckusic register struct iob *io; 1956068Smckusic daddr_t lbn, d; 1966068Smckusic int off; 197327Sbill 1986068Smckusic io = dirp->io; 1996068Smckusic for(;;) { 2006068Smckusic if (dirp->loc >= io->i_ino.i_size) 201*11083Ssam return (NULL); 2026068Smckusic off = blkoff(&io->i_fs, dirp->loc); 2036068Smckusic if (off == 0) { 2046068Smckusic lbn = lblkno(&io->i_fs, dirp->loc); 2056068Smckusic d = sbmap(io, lbn); 2066068Smckusic if(d == 0) 2076068Smckusic return NULL; 2086068Smckusic io->i_bn = fsbtodb(&io->i_fs, d) + io->i_boff; 2096068Smckusic io->i_ma = io->i_buf; 2106068Smckusic io->i_cc = blksize(&io->i_fs, &io->i_ino, lbn); 211*11083Ssam if (devread(io) < 0) { 212*11083Ssam errno = io->i_error; 213*11083Ssam printf("bn %D: read error\n", io->i_bn); 214*11083Ssam return (NULL); 215*11083Ssam } 2166068Smckusic } 2176068Smckusic dp = (struct direct *)(io->i_buf + off); 2186068Smckusic dirp->loc += dp->d_reclen; 2196068Smckusic if (dp->d_ino == 0) 2206068Smckusic continue; 2216068Smckusic return (dp); 222327Sbill } 223327Sbill } 224327Sbill 225327Sbill lseek(fdesc, addr, ptr) 22610022Ssam int fdesc, ptr; 22710022Ssam off_t addr; 228327Sbill { 229327Sbill register struct iob *io; 230327Sbill 231327Sbill if (ptr != 0) { 232327Sbill printf("Seek not from beginning of file\n"); 23310022Ssam errno = EOFFSET; 23410022Ssam return (-1); 235327Sbill } 236327Sbill fdesc -= 3; 2376068Smckusic if (fdesc < 0 || fdesc >= NFILES || 23810022Ssam ((io = &iob[fdesc])->i_flgs & F_ALLOC) == 0) { 23910022Ssam errno = EBADF; 24010022Ssam return (-1); 24110022Ssam } 242327Sbill io->i_offset = addr; 2436068Smckusic io->i_bn = addr / DEV_BSIZE; 244327Sbill io->i_cc = 0; 24510022Ssam return (0); 246327Sbill } 247327Sbill 248327Sbill getc(fdesc) 24910022Ssam int fdesc; 250327Sbill { 251327Sbill register struct iob *io; 2526068Smckusic register struct fs *fs; 253327Sbill register char *p; 2546068Smckusic int c, lbn, off, size, diff; 255327Sbill 256327Sbill 257327Sbill if (fdesc >= 0 && fdesc <= 2) 25810022Ssam return (getchar()); 259327Sbill fdesc -= 3; 2606068Smckusic if (fdesc < 0 || fdesc >= NFILES || 26110022Ssam ((io = &iob[fdesc])->i_flgs&F_ALLOC) == 0) { 26210022Ssam errno = EBADF; 26310022Ssam return (-1); 26410022Ssam } 265327Sbill p = io->i_ma; 266327Sbill if (io->i_cc <= 0) { 2676068Smckusic if ((io->i_flgs & F_FILE) != 0) { 2686068Smckusic diff = io->i_ino.i_size - io->i_offset; 2696068Smckusic if (diff <= 0) 2706068Smckusic return (-1); 2716068Smckusic fs = &io->i_fs; 2726068Smckusic lbn = lblkno(fs, io->i_offset); 2736068Smckusic io->i_bn = fsbtodb(fs, sbmap(io, lbn)) + io->i_boff; 2746068Smckusic off = blkoff(fs, io->i_offset); 2756068Smckusic size = blksize(fs, &io->i_ino, lbn); 2766068Smckusic } else { 2776068Smckusic io->i_bn = io->i_offset / DEV_BSIZE; 2786068Smckusic off = 0; 2796068Smckusic size = DEV_BSIZE; 2806068Smckusic } 281327Sbill io->i_ma = io->i_buf; 2826068Smckusic io->i_cc = size; 283*11083Ssam if (devread(io) < 0) { 284*11083Ssam errno = io->i_error; 285*11083Ssam return (-1); 286*11083Ssam } 2876068Smckusic if ((io->i_flgs & F_FILE) != 0) { 2886068Smckusic if (io->i_offset - off + size >= io->i_ino.i_size) 2896068Smckusic io->i_cc = diff + off; 290327Sbill io->i_cc -= off; 2916068Smckusic } 292327Sbill p = &io->i_buf[off]; 293327Sbill } 294327Sbill io->i_cc--; 295327Sbill io->i_offset++; 296327Sbill c = (unsigned)*p++; 297327Sbill io->i_ma = p; 29810022Ssam return (c); 299327Sbill } 3006068Smckusic 301327Sbill /* does this port? 302327Sbill getw(fdesc) 30310022Ssam int fdesc; 304327Sbill { 305327Sbill register w,i; 306327Sbill register char *cp; 307327Sbill int val; 308327Sbill 309327Sbill for (i = 0, val = 0, cp = &val; i < sizeof(val); i++) { 310327Sbill w = getc(fdesc); 311327Sbill if (w < 0) { 312327Sbill if (i == 0) 31310022Ssam return (-1); 314327Sbill else 31510022Ssam return (val); 316327Sbill } 317327Sbill *cp++ = w; 318327Sbill } 31910022Ssam return (val); 320327Sbill } 321327Sbill */ 32210022Ssam int errno; 323327Sbill 324327Sbill read(fdesc, buf, count) 32510022Ssam int fdesc, count; 32610022Ssam char *buf; 327327Sbill { 328327Sbill register i; 329327Sbill register struct iob *file; 330327Sbill 33110022Ssam errno = 0; 332327Sbill if (fdesc >= 0 & fdesc <= 2) { 333327Sbill i = count; 334327Sbill do { 335327Sbill *buf = getchar(); 336327Sbill } while (--i && *buf++ != '\n'); 33710022Ssam return (count - i); 338327Sbill } 339327Sbill fdesc -= 3; 3406068Smckusic if (fdesc < 0 || fdesc >= NFILES || 34110022Ssam ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) { 34210022Ssam errno = EBADF; 34310022Ssam return (-1); 34410022Ssam } 34510022Ssam if ((file->i_flgs&F_READ) == 0) { 34610022Ssam errno = EBADF; 34710022Ssam return (-1); 34810022Ssam } 3496068Smckusic if ((file->i_flgs & F_FILE) == 0) { 350327Sbill file->i_cc = count; 351327Sbill file->i_ma = buf; 3527446Sroot file->i_bn = file->i_boff + (file->i_offset / DEV_BSIZE); 353327Sbill i = devread(file); 3547446Sroot file->i_offset += count; 35510022Ssam if (i < 0) 35610022Ssam errno = file->i_error; 35710022Ssam return (i); 3586068Smckusic } else { 359327Sbill if (file->i_offset+count > file->i_ino.i_size) 360327Sbill count = file->i_ino.i_size - file->i_offset; 361327Sbill if ((i = count) <= 0) 36210022Ssam return (0); 363327Sbill do { 364327Sbill *buf++ = getc(fdesc+3); 365327Sbill } while (--i); 36610022Ssam return (count); 367327Sbill } 368327Sbill } 369327Sbill 370327Sbill write(fdesc, buf, count) 37110022Ssam int fdesc, count; 37210022Ssam char *buf; 373327Sbill { 374327Sbill register i; 375327Sbill register struct iob *file; 376327Sbill 37710022Ssam errno = 0; 378327Sbill if (fdesc >= 0 && fdesc <= 2) { 379327Sbill i = count; 380327Sbill while (i--) 381327Sbill putchar(*buf++); 38210022Ssam return (count); 383327Sbill } 384327Sbill fdesc -= 3; 3856068Smckusic if (fdesc < 0 || fdesc >= NFILES || 38610022Ssam ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) { 38710022Ssam errno = EBADF; 38810022Ssam return (-1); 38910022Ssam } 39010022Ssam if ((file->i_flgs&F_WRITE) == 0) { 39110022Ssam errno = EBADF; 39210022Ssam return (-1); 39310022Ssam } 394327Sbill file->i_cc = count; 395327Sbill file->i_ma = buf; 3967446Sroot file->i_bn = file->i_boff + (file->i_offset / DEV_BSIZE); 397327Sbill i = devwrite(file); 3987446Sroot file->i_offset += count; 39910022Ssam if (i < 0) 40010022Ssam errno = file->i_error; 40110022Ssam return (i); 402327Sbill } 403327Sbill 4043349Swnj int openfirst = 1; 4053349Swnj 406327Sbill open(str, how) 4076068Smckusic char *str; 40810022Ssam int how; 409327Sbill { 410327Sbill register char *cp; 411327Sbill int i; 412327Sbill register struct iob *file; 413327Sbill register struct devsw *dp; 41410022Ssam int fdesc; 41510022Ssam long atol(); 416327Sbill 4173349Swnj if (openfirst) { 418327Sbill for (i = 0; i < NFILES; i++) 419327Sbill iob[i].i_flgs = 0; 4203349Swnj openfirst = 0; 421327Sbill } 422327Sbill 423327Sbill for (fdesc = 0; fdesc < NFILES; fdesc++) 424327Sbill if (iob[fdesc].i_flgs == 0) 425327Sbill goto gotfile; 426327Sbill _stop("No more file slots"); 427327Sbill gotfile: 428327Sbill (file = &iob[fdesc])->i_flgs |= F_ALLOC; 429327Sbill 430327Sbill for (cp = str; *cp && *cp != '('; cp++) 431327Sbill ; 432327Sbill if (*cp != '(') { 433327Sbill printf("Bad device\n"); 434327Sbill file->i_flgs = 0; 43510022Ssam errno = EDEV; 43610022Ssam return (-1); 437327Sbill } 438327Sbill *cp++ = '\0'; 439327Sbill for (dp = devsw; dp->dv_name; dp++) { 4406068Smckusic if (!strcmp(str, dp->dv_name)) 441327Sbill goto gotdev; 442327Sbill } 443327Sbill printf("Unknown device\n"); 444327Sbill file->i_flgs = 0; 44510022Ssam errno = ENXIO; 44610022Ssam return (-1); 447327Sbill gotdev: 448327Sbill *(cp-1) = '('; 449327Sbill file->i_ino.i_dev = dp-devsw; 450327Sbill file->i_unit = *cp++ - '0'; 4513274Swnj if (*cp >= '0' && *cp <= '9') 4523274Swnj file->i_unit = file->i_unit * 10 + *cp++ - '0'; 4533274Swnj if (file->i_unit < 0 || file->i_unit > 31) { 454327Sbill printf("Bad unit specifier\n"); 455327Sbill file->i_flgs = 0; 45610022Ssam errno = EUNIT; 45710022Ssam return (-1); 458327Sbill } 459327Sbill if (*cp++ != ',') { 460327Sbill badoff: 461327Sbill printf("Missing offset specification\n"); 462327Sbill file->i_flgs = 0; 46310022Ssam errno = EOFFSET; 46410022Ssam return (-1); 465327Sbill } 466327Sbill file->i_boff = atol(cp); 467327Sbill for (;;) { 468327Sbill if (*cp == ')') 469327Sbill break; 470327Sbill if (*cp++) 471327Sbill continue; 472327Sbill goto badoff; 473327Sbill } 474327Sbill devopen(file); 475327Sbill if (*++cp == '\0') { 476327Sbill file->i_flgs |= how+1; 477327Sbill file->i_cc = 0; 478327Sbill file->i_offset = 0; 47910022Ssam return (fdesc+3); 480327Sbill } 4816068Smckusic file->i_ma = (char *)(&file->i_fs); 4826068Smckusic file->i_cc = SBSIZE; 4837446Sroot file->i_bn = SBLOCK + file->i_boff; 4846068Smckusic file->i_offset = 0; 485*11083Ssam if (devread(file) < 0) { 486*11083Ssam errno = file->i_error; 487*11083Ssam printf("super block read error\n"); 488*11083Ssam return (-1); 489*11083Ssam } 490327Sbill if ((i = find(cp, file)) == 0) { 491327Sbill file->i_flgs = 0; 49210022Ssam errno = ESRCH; 49310022Ssam return (-1); 494327Sbill } 495327Sbill if (how != 0) { 496327Sbill printf("Can't write files yet.. Sorry\n"); 497327Sbill file->i_flgs = 0; 49810022Ssam errno = EIO; 49910022Ssam return (-1); 500327Sbill } 501*11083Ssam if (openi(i, file) < 0) { 502*11083Ssam errno = file->i_error; 503*11083Ssam return (-1); 504*11083Ssam } 505327Sbill file->i_offset = 0; 506327Sbill file->i_cc = 0; 507327Sbill file->i_flgs |= F_FILE | (how+1); 50810022Ssam return (fdesc+3); 509327Sbill } 510327Sbill 511327Sbill close(fdesc) 51210022Ssam int fdesc; 513327Sbill { 514327Sbill struct iob *file; 515327Sbill 516327Sbill fdesc -= 3; 5176068Smckusic if (fdesc < 0 || fdesc >= NFILES || 51810022Ssam ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) { 51910022Ssam errno = EBADF; 52010022Ssam return (-1); 52110022Ssam } 522327Sbill if ((file->i_flgs&F_FILE) == 0) 523327Sbill devclose(file); 524327Sbill file->i_flgs = 0; 52510022Ssam return (0); 526327Sbill } 527327Sbill 52810022Ssam ioctl(fdesc, cmd, arg) 52910022Ssam int fdesc, cmd; 53010022Ssam char *arg; 53110022Ssam { 53210022Ssam register struct iob *file; 53310022Ssam int error = 0; 53410022Ssam 53510331Shelge fdesc -= 3; 53610022Ssam if (fdesc < 0 || fdesc >= NFILES || 53710022Ssam ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) { 53810022Ssam errno = EBADF; 53910022Ssam return (-1); 54010022Ssam } 54110022Ssam switch (cmd) { 54210022Ssam 54310022Ssam case SAIOHDR: 54410022Ssam file->i_flgs |= F_HDR; 54510022Ssam break; 54610022Ssam 54710022Ssam case SAIOCHECK: 54810022Ssam file->i_flgs |= F_CHECK; 54910022Ssam break; 55010022Ssam 55110022Ssam case SAIOHCHECK: 55210022Ssam file->i_flgs |= F_HCHECK; 55310022Ssam break; 55410022Ssam 55510331Shelge case SAIONOBAD: 55610331Shelge file->i_flgs |= F_NBSF; 55710331Shelge break; 55810331Shelge 55910331Shelge case SAIODOBAD: 56010331Shelge file->i_flgs &= ~F_NBSF; 56110331Shelge break; 56210331Shelge 56310331Shelge case SAIOECCLIM: 56410331Shelge file->i_flgs |= F_ECCLM; 56510331Shelge break; 56610331Shelge 56710331Shelge case SAIOECCUNL: 56810331Shelge file->i_flgs &= ~F_ECCLM; 56910331Shelge break; 57010331Shelge 57110022Ssam default: 57210022Ssam error = devioctl(file, cmd, arg); 57310022Ssam break; 57410022Ssam } 57510022Ssam if (error < 0) 57610022Ssam errno = file->i_error; 57710022Ssam return (error); 57810022Ssam } 57910022Ssam 580327Sbill exit() 581327Sbill { 582327Sbill _stop("Exit called"); 583327Sbill } 584327Sbill 585327Sbill _stop(s) 58610022Ssam char *s; 587327Sbill { 5882391Stoy int i; 5892391Stoy 5902391Stoy for (i = 0; i < NFILES; i++) 5912391Stoy if (iob[i].i_flgs != 0) 5922391Stoy close(i); 593327Sbill printf("%s\n", s); 594327Sbill _rtt(); 595327Sbill } 596327Sbill 597327Sbill trap(ps) 5986068Smckusic int ps; 599327Sbill { 600327Sbill printf("Trap %o\n", ps); 601327Sbill for (;;) 602327Sbill ; 603327Sbill } 604