1*23243Smckusick /* 2*23243Smckusick * Copyright (c) 1982 Regents of the University of California. 3*23243Smckusick * All rights reserved. The Berkeley software License Agreement 4*23243Smckusick * specifies the terms and conditions for redistribution. 5*23243Smckusick * 6*23243Smckusick * @(#)sys.c 6.3 (Berkeley) 06/08/85 7*23243Smckusick */ 8327Sbill 96068Smckusic #include "../h/param.h" 106068Smckusic #include "../h/inode.h" 116068Smckusic #include "../h/fs.h" 127446Sroot #include "../h/dir.h" 13327Sbill #include "saio.h" 14327Sbill 15327Sbill ino_t dlook(); 16327Sbill 176068Smckusic struct dirstuff { 186068Smckusic int loc; 196068Smckusic struct iob *io; 206068Smckusic }; 216068Smckusic 22327Sbill static 2310022Ssam openi(n, io) 246068Smckusic register struct iob *io; 25327Sbill { 26327Sbill register struct dinode *dp; 2711083Ssam int cc; 28327Sbill 29327Sbill io->i_offset = 0; 306068Smckusic io->i_bn = fsbtodb(&io->i_fs, itod(&io->i_fs, n)) + io->i_boff; 316068Smckusic io->i_cc = io->i_fs.fs_bsize; 32327Sbill io->i_ma = io->i_buf; 3311083Ssam cc = devread(io); 34327Sbill dp = (struct dinode *)io->i_buf; 356068Smckusic io->i_ino.i_ic = dp[itoo(&io->i_fs, n)].di_ic; 3611083Ssam return (cc); 37327Sbill } 38327Sbill 39327Sbill static 40327Sbill find(path, file) 416068Smckusic register char *path; 426068Smckusic struct iob *file; 43327Sbill { 44327Sbill register char *q; 45327Sbill char c; 46327Sbill int n; 47327Sbill 48327Sbill if (path==NULL || *path=='\0') { 49327Sbill printf("null path\n"); 5010022Ssam return (0); 51327Sbill } 52327Sbill 5311083Ssam if (openi((ino_t) ROOTINO, file) < 0) { 5411083Ssam printf("can't read root inode\n"); 5511083Ssam return (0); 5611083Ssam } 57327Sbill while (*path) { 58327Sbill while (*path == '/') 59327Sbill path++; 60327Sbill q = path; 61327Sbill while(*q != '/' && *q != '\0') 62327Sbill q++; 63327Sbill c = *q; 64327Sbill *q = '\0'; 65327Sbill 6611083Ssam if ((n = dlook(path, file)) != 0) { 6711083Ssam if (c == '\0') 68327Sbill break; 6911083Ssam if (openi(n, file) < 0) 7011083Ssam return (0); 71327Sbill *q = c; 72327Sbill path = q; 73327Sbill continue; 74327Sbill } else { 7511083Ssam printf("%s not found\n", path); 7610022Ssam return (0); 77327Sbill } 78327Sbill } 7910022Ssam return (n); 80327Sbill } 81327Sbill 82327Sbill static daddr_t 83327Sbill sbmap(io, bn) 846068Smckusic register struct iob *io; 856068Smckusic daddr_t bn; 86327Sbill { 87327Sbill register struct inode *ip; 886068Smckusic int i, j, sh; 89327Sbill daddr_t nb, *bap; 90327Sbill 91327Sbill ip = &io->i_ino; 926068Smckusic if (bn < 0) { 93327Sbill printf("bn negative\n"); 9410022Ssam return ((daddr_t)0); 95327Sbill } 96327Sbill 97327Sbill /* 986068Smckusic * blocks 0..NDADDR are direct blocks 99327Sbill */ 1006068Smckusic if(bn < NDADDR) { 1016068Smckusic nb = ip->i_db[bn]; 10210022Ssam return (nb); 103327Sbill } 104327Sbill 105327Sbill /* 1066068Smckusic * addresses NIADDR have single and double indirect blocks. 1076068Smckusic * the first step is to determine how many levels of indirection. 108327Sbill */ 1096068Smckusic sh = 1; 1106068Smckusic bn -= NDADDR; 1116068Smckusic for (j = NIADDR; j > 0; j--) { 1126068Smckusic sh *= NINDIR(&io->i_fs); 1136068Smckusic if (bn < sh) 114327Sbill break; 1156068Smckusic bn -= sh; 116327Sbill } 1176068Smckusic if (j == 0) { 1186068Smckusic printf("bn ovf %D\n", bn); 1196068Smckusic return ((daddr_t)0); 120327Sbill } 121327Sbill 122327Sbill /* 1236068Smckusic * fetch the first indirect block address from the inode 124327Sbill */ 1256068Smckusic nb = ip->i_ib[NIADDR - j]; 1266068Smckusic if (nb == 0) { 127327Sbill printf("bn void %D\n",bn); 12810022Ssam return ((daddr_t)0); 129327Sbill } 130327Sbill 131327Sbill /* 132327Sbill * fetch through the indirect blocks 133327Sbill */ 1346068Smckusic for (; j <= NIADDR; j++) { 135327Sbill if (blknos[j] != nb) { 1366068Smckusic io->i_bn = fsbtodb(&io->i_fs, nb) + io->i_boff; 137327Sbill io->i_ma = b[j]; 1386068Smckusic io->i_cc = io->i_fs.fs_bsize; 13911083Ssam if (devread(io) != io->i_fs.fs_bsize) { 14011083Ssam if (io->i_error) 14111083Ssam errno = io->i_error; 14211083Ssam printf("bn %D: read error\n", io->i_bn); 14311083Ssam return ((daddr_t)0); 14411083Ssam } 145327Sbill blknos[j] = nb; 146327Sbill } 147327Sbill bap = (daddr_t *)b[j]; 1486068Smckusic sh /= NINDIR(&io->i_fs); 1496068Smckusic i = (bn / sh) % NINDIR(&io->i_fs); 150327Sbill nb = bap[i]; 151327Sbill if(nb == 0) { 152327Sbill printf("bn void %D\n",bn); 15310022Ssam return ((daddr_t)0); 154327Sbill } 155327Sbill } 15610022Ssam return (nb); 157327Sbill } 158327Sbill 159327Sbill static ino_t 160327Sbill dlook(s, io) 1616068Smckusic char *s; 1626068Smckusic register struct iob *io; 163327Sbill { 164327Sbill register struct direct *dp; 165327Sbill register struct inode *ip; 1666068Smckusic struct dirstuff dirp; 1676068Smckusic int len; 168327Sbill 1696068Smckusic if (s == NULL || *s == '\0') 17010022Ssam return (0); 171327Sbill ip = &io->i_ino; 1726068Smckusic if ((ip->i_mode&IFMT) != IFDIR) { 173327Sbill printf("not a directory\n"); 17410022Ssam return (0); 175327Sbill } 1766068Smckusic if (ip->i_size == 0) { 177327Sbill printf("zero length directory\n"); 17810022Ssam return (0); 179327Sbill } 1806068Smckusic len = strlen(s); 1816068Smckusic dirp.loc = 0; 1826068Smckusic dirp.io = io; 1836068Smckusic for (dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) { 1846068Smckusic if(dp->d_ino == 0) 1856068Smckusic continue; 1866068Smckusic if (dp->d_namlen == len && !strcmp(s, dp->d_name)) 18710022Ssam return (dp->d_ino); 188327Sbill } 18910022Ssam return (0); 190327Sbill } 191327Sbill 1926068Smckusic /* 1936068Smckusic * get next entry in a directory. 1946068Smckusic */ 1956068Smckusic struct direct * 1966068Smckusic readdir(dirp) 1976068Smckusic register struct dirstuff *dirp; 198327Sbill { 1996068Smckusic register struct direct *dp; 2006068Smckusic register struct iob *io; 2016068Smckusic daddr_t lbn, d; 2026068Smckusic int off; 203327Sbill 2046068Smckusic io = dirp->io; 2056068Smckusic for(;;) { 2066068Smckusic if (dirp->loc >= io->i_ino.i_size) 20711083Ssam return (NULL); 2086068Smckusic off = blkoff(&io->i_fs, dirp->loc); 2096068Smckusic if (off == 0) { 2106068Smckusic lbn = lblkno(&io->i_fs, dirp->loc); 2116068Smckusic d = sbmap(io, lbn); 2126068Smckusic if(d == 0) 2136068Smckusic return NULL; 2146068Smckusic io->i_bn = fsbtodb(&io->i_fs, d) + io->i_boff; 2156068Smckusic io->i_ma = io->i_buf; 2166068Smckusic io->i_cc = blksize(&io->i_fs, &io->i_ino, lbn); 21711083Ssam if (devread(io) < 0) { 21811083Ssam errno = io->i_error; 21911083Ssam printf("bn %D: read error\n", io->i_bn); 22011083Ssam return (NULL); 22111083Ssam } 2226068Smckusic } 2236068Smckusic dp = (struct direct *)(io->i_buf + off); 2246068Smckusic dirp->loc += dp->d_reclen; 2256068Smckusic if (dp->d_ino == 0) 2266068Smckusic continue; 2276068Smckusic return (dp); 228327Sbill } 229327Sbill } 230327Sbill 231327Sbill lseek(fdesc, addr, ptr) 23210022Ssam int fdesc, ptr; 23310022Ssam off_t addr; 234327Sbill { 235327Sbill register struct iob *io; 236327Sbill 237327Sbill if (ptr != 0) { 238327Sbill printf("Seek not from beginning of file\n"); 23910022Ssam errno = EOFFSET; 24010022Ssam return (-1); 241327Sbill } 242327Sbill fdesc -= 3; 2436068Smckusic if (fdesc < 0 || fdesc >= NFILES || 24410022Ssam ((io = &iob[fdesc])->i_flgs & F_ALLOC) == 0) { 24510022Ssam errno = EBADF; 24610022Ssam return (-1); 24710022Ssam } 248327Sbill io->i_offset = addr; 2496068Smckusic io->i_bn = addr / DEV_BSIZE; 250327Sbill io->i_cc = 0; 25110022Ssam return (0); 252327Sbill } 253327Sbill 254327Sbill getc(fdesc) 25510022Ssam int fdesc; 256327Sbill { 257327Sbill register struct iob *io; 2586068Smckusic register struct fs *fs; 259327Sbill register char *p; 2606068Smckusic int c, lbn, off, size, diff; 261327Sbill 262327Sbill 263327Sbill if (fdesc >= 0 && fdesc <= 2) 26410022Ssam return (getchar()); 265327Sbill fdesc -= 3; 2666068Smckusic if (fdesc < 0 || fdesc >= NFILES || 26710022Ssam ((io = &iob[fdesc])->i_flgs&F_ALLOC) == 0) { 26810022Ssam errno = EBADF; 26910022Ssam return (-1); 27010022Ssam } 271327Sbill p = io->i_ma; 272327Sbill if (io->i_cc <= 0) { 2736068Smckusic if ((io->i_flgs & F_FILE) != 0) { 2746068Smckusic diff = io->i_ino.i_size - io->i_offset; 2756068Smckusic if (diff <= 0) 2766068Smckusic return (-1); 2776068Smckusic fs = &io->i_fs; 2786068Smckusic lbn = lblkno(fs, io->i_offset); 2796068Smckusic io->i_bn = fsbtodb(fs, sbmap(io, lbn)) + io->i_boff; 2806068Smckusic off = blkoff(fs, io->i_offset); 2816068Smckusic size = blksize(fs, &io->i_ino, lbn); 2826068Smckusic } else { 2836068Smckusic io->i_bn = io->i_offset / DEV_BSIZE; 2846068Smckusic off = 0; 2856068Smckusic size = DEV_BSIZE; 2866068Smckusic } 287327Sbill io->i_ma = io->i_buf; 2886068Smckusic io->i_cc = size; 28911083Ssam if (devread(io) < 0) { 29011083Ssam errno = io->i_error; 29111083Ssam return (-1); 29211083Ssam } 2936068Smckusic if ((io->i_flgs & F_FILE) != 0) { 2946068Smckusic if (io->i_offset - off + size >= io->i_ino.i_size) 2956068Smckusic io->i_cc = diff + off; 296327Sbill io->i_cc -= off; 2976068Smckusic } 298327Sbill p = &io->i_buf[off]; 299327Sbill } 300327Sbill io->i_cc--; 301327Sbill io->i_offset++; 302327Sbill c = (unsigned)*p++; 303327Sbill io->i_ma = p; 30410022Ssam return (c); 305327Sbill } 3066068Smckusic 307327Sbill /* does this port? 308327Sbill getw(fdesc) 30910022Ssam int fdesc; 310327Sbill { 311327Sbill register w,i; 312327Sbill register char *cp; 313327Sbill int val; 314327Sbill 315327Sbill for (i = 0, val = 0, cp = &val; i < sizeof(val); i++) { 316327Sbill w = getc(fdesc); 317327Sbill if (w < 0) { 318327Sbill if (i == 0) 31910022Ssam return (-1); 320327Sbill else 32110022Ssam return (val); 322327Sbill } 323327Sbill *cp++ = w; 324327Sbill } 32510022Ssam return (val); 326327Sbill } 327327Sbill */ 32810022Ssam int errno; 329327Sbill 330327Sbill read(fdesc, buf, count) 33110022Ssam int fdesc, count; 33210022Ssam char *buf; 333327Sbill { 334327Sbill register i; 335327Sbill register struct iob *file; 336327Sbill 33710022Ssam errno = 0; 338327Sbill if (fdesc >= 0 & fdesc <= 2) { 339327Sbill i = count; 340327Sbill do { 341327Sbill *buf = getchar(); 342327Sbill } while (--i && *buf++ != '\n'); 34310022Ssam return (count - i); 344327Sbill } 345327Sbill fdesc -= 3; 3466068Smckusic if (fdesc < 0 || fdesc >= NFILES || 34710022Ssam ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) { 34810022Ssam errno = EBADF; 34910022Ssam return (-1); 35010022Ssam } 35110022Ssam if ((file->i_flgs&F_READ) == 0) { 35210022Ssam errno = EBADF; 35310022Ssam return (-1); 35410022Ssam } 3556068Smckusic if ((file->i_flgs & F_FILE) == 0) { 356327Sbill file->i_cc = count; 357327Sbill file->i_ma = buf; 3587446Sroot file->i_bn = file->i_boff + (file->i_offset / DEV_BSIZE); 359327Sbill i = devread(file); 3607446Sroot file->i_offset += count; 36110022Ssam if (i < 0) 36210022Ssam errno = file->i_error; 36310022Ssam return (i); 3646068Smckusic } else { 365327Sbill if (file->i_offset+count > file->i_ino.i_size) 366327Sbill count = file->i_ino.i_size - file->i_offset; 367327Sbill if ((i = count) <= 0) 36810022Ssam return (0); 369327Sbill do { 370327Sbill *buf++ = getc(fdesc+3); 371327Sbill } while (--i); 37210022Ssam return (count); 373327Sbill } 374327Sbill } 375327Sbill 376327Sbill write(fdesc, buf, count) 37710022Ssam int fdesc, count; 37810022Ssam char *buf; 379327Sbill { 380327Sbill register i; 381327Sbill register struct iob *file; 382327Sbill 38310022Ssam errno = 0; 384327Sbill if (fdesc >= 0 && fdesc <= 2) { 385327Sbill i = count; 386327Sbill while (i--) 387327Sbill putchar(*buf++); 38810022Ssam return (count); 389327Sbill } 390327Sbill fdesc -= 3; 3916068Smckusic if (fdesc < 0 || fdesc >= NFILES || 39210022Ssam ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) { 39310022Ssam errno = EBADF; 39410022Ssam return (-1); 39510022Ssam } 39610022Ssam if ((file->i_flgs&F_WRITE) == 0) { 39710022Ssam errno = EBADF; 39810022Ssam return (-1); 39910022Ssam } 400327Sbill file->i_cc = count; 401327Sbill file->i_ma = buf; 4027446Sroot file->i_bn = file->i_boff + (file->i_offset / DEV_BSIZE); 403327Sbill i = devwrite(file); 4047446Sroot file->i_offset += count; 40510022Ssam if (i < 0) 40610022Ssam errno = file->i_error; 40710022Ssam return (i); 408327Sbill } 409327Sbill 4103349Swnj int openfirst = 1; 4113349Swnj 412327Sbill open(str, how) 4136068Smckusic char *str; 41410022Ssam int how; 415327Sbill { 416327Sbill register char *cp; 417327Sbill int i; 418327Sbill register struct iob *file; 419327Sbill register struct devsw *dp; 42010022Ssam int fdesc; 42110022Ssam long atol(); 422327Sbill 4233349Swnj if (openfirst) { 424327Sbill for (i = 0; i < NFILES; i++) 425327Sbill iob[i].i_flgs = 0; 4263349Swnj openfirst = 0; 427327Sbill } 428327Sbill 429327Sbill for (fdesc = 0; fdesc < NFILES; fdesc++) 430327Sbill if (iob[fdesc].i_flgs == 0) 431327Sbill goto gotfile; 432327Sbill _stop("No more file slots"); 433327Sbill gotfile: 434327Sbill (file = &iob[fdesc])->i_flgs |= F_ALLOC; 435327Sbill 436327Sbill for (cp = str; *cp && *cp != '('; cp++) 437327Sbill ; 438327Sbill if (*cp != '(') { 439327Sbill printf("Bad device\n"); 440327Sbill file->i_flgs = 0; 44110022Ssam errno = EDEV; 44210022Ssam return (-1); 443327Sbill } 444327Sbill *cp++ = '\0'; 445327Sbill for (dp = devsw; dp->dv_name; dp++) { 4466068Smckusic if (!strcmp(str, dp->dv_name)) 447327Sbill goto gotdev; 448327Sbill } 449327Sbill printf("Unknown device\n"); 450327Sbill file->i_flgs = 0; 45110022Ssam errno = ENXIO; 45210022Ssam return (-1); 453327Sbill gotdev: 454327Sbill *(cp-1) = '('; 455327Sbill file->i_ino.i_dev = dp-devsw; 456327Sbill file->i_unit = *cp++ - '0'; 4573274Swnj if (*cp >= '0' && *cp <= '9') 4583274Swnj file->i_unit = file->i_unit * 10 + *cp++ - '0'; 4593274Swnj if (file->i_unit < 0 || file->i_unit > 31) { 460327Sbill printf("Bad unit specifier\n"); 461327Sbill file->i_flgs = 0; 46210022Ssam errno = EUNIT; 46310022Ssam return (-1); 464327Sbill } 465327Sbill if (*cp++ != ',') { 466327Sbill badoff: 467327Sbill printf("Missing offset specification\n"); 468327Sbill file->i_flgs = 0; 46910022Ssam errno = EOFFSET; 47010022Ssam return (-1); 471327Sbill } 472327Sbill file->i_boff = atol(cp); 473327Sbill for (;;) { 474327Sbill if (*cp == ')') 475327Sbill break; 476327Sbill if (*cp++) 477327Sbill continue; 478327Sbill goto badoff; 479327Sbill } 480327Sbill devopen(file); 481327Sbill if (*++cp == '\0') { 482327Sbill file->i_flgs |= how+1; 483327Sbill file->i_cc = 0; 484327Sbill file->i_offset = 0; 48510022Ssam return (fdesc+3); 486327Sbill } 4876068Smckusic file->i_ma = (char *)(&file->i_fs); 4886068Smckusic file->i_cc = SBSIZE; 4897446Sroot file->i_bn = SBLOCK + file->i_boff; 4906068Smckusic file->i_offset = 0; 49111083Ssam if (devread(file) < 0) { 49211083Ssam errno = file->i_error; 49311083Ssam printf("super block read error\n"); 49411083Ssam return (-1); 49511083Ssam } 496327Sbill if ((i = find(cp, file)) == 0) { 497327Sbill file->i_flgs = 0; 49810022Ssam errno = ESRCH; 49910022Ssam return (-1); 500327Sbill } 501327Sbill if (how != 0) { 502327Sbill printf("Can't write files yet.. Sorry\n"); 503327Sbill file->i_flgs = 0; 50410022Ssam errno = EIO; 50510022Ssam return (-1); 506327Sbill } 50711083Ssam if (openi(i, file) < 0) { 50811083Ssam errno = file->i_error; 50911083Ssam return (-1); 51011083Ssam } 511327Sbill file->i_offset = 0; 512327Sbill file->i_cc = 0; 513327Sbill file->i_flgs |= F_FILE | (how+1); 51410022Ssam return (fdesc+3); 515327Sbill } 516327Sbill 517327Sbill close(fdesc) 51810022Ssam int fdesc; 519327Sbill { 520327Sbill struct iob *file; 521327Sbill 522327Sbill fdesc -= 3; 5236068Smckusic if (fdesc < 0 || fdesc >= NFILES || 52410022Ssam ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) { 52510022Ssam errno = EBADF; 52610022Ssam return (-1); 52710022Ssam } 528327Sbill if ((file->i_flgs&F_FILE) == 0) 529327Sbill devclose(file); 530327Sbill file->i_flgs = 0; 53110022Ssam return (0); 532327Sbill } 533327Sbill 53410022Ssam ioctl(fdesc, cmd, arg) 53510022Ssam int fdesc, cmd; 53610022Ssam char *arg; 53710022Ssam { 53810022Ssam register struct iob *file; 53910022Ssam int error = 0; 54010022Ssam 54110331Shelge fdesc -= 3; 54210022Ssam if (fdesc < 0 || fdesc >= NFILES || 54310022Ssam ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) { 54410022Ssam errno = EBADF; 54510022Ssam return (-1); 54610022Ssam } 54710022Ssam switch (cmd) { 54810022Ssam 54910022Ssam case SAIOHDR: 55010022Ssam file->i_flgs |= F_HDR; 55110022Ssam break; 55210022Ssam 55310022Ssam case SAIOCHECK: 55410022Ssam file->i_flgs |= F_CHECK; 55510022Ssam break; 55610022Ssam 55710022Ssam case SAIOHCHECK: 55810022Ssam file->i_flgs |= F_HCHECK; 55910022Ssam break; 56010022Ssam 56110331Shelge case SAIONOBAD: 56210331Shelge file->i_flgs |= F_NBSF; 56310331Shelge break; 56410331Shelge 56510331Shelge case SAIODOBAD: 56610331Shelge file->i_flgs &= ~F_NBSF; 56710331Shelge break; 56810331Shelge 56910331Shelge case SAIOECCLIM: 57010331Shelge file->i_flgs |= F_ECCLM; 57110331Shelge break; 57210331Shelge 57310331Shelge case SAIOECCUNL: 57410331Shelge file->i_flgs &= ~F_ECCLM; 57510331Shelge break; 57610331Shelge 57715053Skarels case SAIOSEVRE: 57815053Skarels file->i_flgs |= F_SEVRE; 57915053Skarels break; 58015053Skarels 58115053Skarels case SAIONSEVRE: 58215053Skarels file->i_flgs &= ~F_SEVRE; 58315053Skarels break; 58415053Skarels 58510022Ssam default: 58610022Ssam error = devioctl(file, cmd, arg); 58710022Ssam break; 58810022Ssam } 58910022Ssam if (error < 0) 59010022Ssam errno = file->i_error; 59110022Ssam return (error); 59210022Ssam } 59310022Ssam 594327Sbill exit() 595327Sbill { 596327Sbill _stop("Exit called"); 597327Sbill } 598327Sbill 599327Sbill _stop(s) 60010022Ssam char *s; 601327Sbill { 6022391Stoy int i; 6032391Stoy 6042391Stoy for (i = 0; i < NFILES; i++) 6052391Stoy if (iob[i].i_flgs != 0) 6062391Stoy close(i); 607327Sbill printf("%s\n", s); 608327Sbill _rtt(); 609327Sbill } 610327Sbill 611327Sbill trap(ps) 6126068Smckusic int ps; 613327Sbill { 614327Sbill printf("Trap %o\n", ps); 615327Sbill for (;;) 616327Sbill ; 617327Sbill } 618