123243Smckusick /* 229310Smckusick * Copyright (c) 1982, 1986 Regents of the University of California. 323243Smckusick * All rights reserved. The Berkeley software License Agreement 423243Smckusick * specifies the terms and conditions for redistribution. 523243Smckusick * 6*33408Skarels * @(#)sys.c 7.5 (Berkeley) 01/28/88 723243Smckusick */ 8327Sbill 930768Skarels #include "param.h" 1030768Skarels #include "inode.h" 1130768Skarels #include "fs.h" 1230768Skarels #include "dir.h" 1330768Skarels #include "reboot.h" 14327Sbill #include "saio.h" 15327Sbill 16327Sbill ino_t dlook(); 17327Sbill 186068Smckusic struct dirstuff { 196068Smckusic int loc; 206068Smckusic struct iob *io; 216068Smckusic }; 226068Smckusic 23327Sbill static 2410022Ssam openi(n, io) 256068Smckusic register struct iob *io; 26327Sbill { 27327Sbill register struct dinode *dp; 2811083Ssam int cc; 29327Sbill 30327Sbill io->i_offset = 0; 316068Smckusic io->i_bn = fsbtodb(&io->i_fs, itod(&io->i_fs, n)) + io->i_boff; 326068Smckusic io->i_cc = io->i_fs.fs_bsize; 33327Sbill io->i_ma = io->i_buf; 3411083Ssam cc = devread(io); 35327Sbill dp = (struct dinode *)io->i_buf; 366068Smckusic io->i_ino.i_ic = dp[itoo(&io->i_fs, n)].di_ic; 3711083Ssam return (cc); 38327Sbill } 39327Sbill 40327Sbill static 41327Sbill find(path, file) 426068Smckusic register char *path; 436068Smckusic struct iob *file; 44327Sbill { 45327Sbill register char *q; 4630768Skarels char *dir; 47327Sbill char c; 48327Sbill int n; 49327Sbill 50327Sbill if (path==NULL || *path=='\0') { 51327Sbill printf("null path\n"); 5210022Ssam return (0); 53327Sbill } 54327Sbill 5511083Ssam if (openi((ino_t) ROOTINO, file) < 0) { 5611083Ssam printf("can't read root inode\n"); 5711083Ssam return (0); 5811083Ssam } 5930768Skarels dir = path; 60327Sbill while (*path) { 61327Sbill while (*path == '/') 62327Sbill path++; 63327Sbill q = path; 64327Sbill while(*q != '/' && *q != '\0') 65327Sbill q++; 66327Sbill c = *q; 67327Sbill *q = '\0'; 6825166Skarels if (q == path) path = "." ; /* "/" means "/." */ 69327Sbill 7030768Skarels if ((n = dlook(path, file, dir)) != 0) { 7111083Ssam if (c == '\0') 72327Sbill break; 7311083Ssam if (openi(n, file) < 0) 7411083Ssam return (0); 75327Sbill *q = c; 76327Sbill path = q; 77327Sbill continue; 78327Sbill } else { 7925166Skarels printf("%s: not found\n", path); 8010022Ssam return (0); 81327Sbill } 82327Sbill } 8310022Ssam return (n); 84327Sbill } 85327Sbill 86327Sbill static daddr_t 87327Sbill sbmap(io, bn) 886068Smckusic register struct iob *io; 896068Smckusic daddr_t bn; 90327Sbill { 91327Sbill register struct inode *ip; 926068Smckusic int i, j, sh; 93327Sbill daddr_t nb, *bap; 94327Sbill 95327Sbill ip = &io->i_ino; 966068Smckusic if (bn < 0) { 97327Sbill printf("bn negative\n"); 9810022Ssam return ((daddr_t)0); 99327Sbill } 100327Sbill 101327Sbill /* 1026068Smckusic * blocks 0..NDADDR are direct blocks 103327Sbill */ 1046068Smckusic if(bn < NDADDR) { 1056068Smckusic nb = ip->i_db[bn]; 10610022Ssam return (nb); 107327Sbill } 108327Sbill 109327Sbill /* 1106068Smckusic * addresses NIADDR have single and double indirect blocks. 1116068Smckusic * the first step is to determine how many levels of indirection. 112327Sbill */ 1136068Smckusic sh = 1; 1146068Smckusic bn -= NDADDR; 1156068Smckusic for (j = NIADDR; j > 0; j--) { 1166068Smckusic sh *= NINDIR(&io->i_fs); 1176068Smckusic if (bn < sh) 118327Sbill break; 1196068Smckusic bn -= sh; 120327Sbill } 1216068Smckusic if (j == 0) { 1226068Smckusic printf("bn ovf %D\n", bn); 1236068Smckusic return ((daddr_t)0); 124327Sbill } 125327Sbill 126327Sbill /* 1276068Smckusic * fetch the first indirect block address from the inode 128327Sbill */ 1296068Smckusic nb = ip->i_ib[NIADDR - j]; 1306068Smckusic if (nb == 0) { 131327Sbill printf("bn void %D\n",bn); 13210022Ssam return ((daddr_t)0); 133327Sbill } 134327Sbill 135327Sbill /* 136327Sbill * fetch through the indirect blocks 137327Sbill */ 1386068Smckusic for (; j <= NIADDR; j++) { 139327Sbill if (blknos[j] != nb) { 1406068Smckusic io->i_bn = fsbtodb(&io->i_fs, nb) + io->i_boff; 141327Sbill io->i_ma = b[j]; 1426068Smckusic io->i_cc = io->i_fs.fs_bsize; 14311083Ssam if (devread(io) != io->i_fs.fs_bsize) { 14411083Ssam if (io->i_error) 14511083Ssam errno = io->i_error; 14611083Ssam printf("bn %D: read error\n", io->i_bn); 14711083Ssam return ((daddr_t)0); 14811083Ssam } 149327Sbill blknos[j] = nb; 150327Sbill } 151327Sbill bap = (daddr_t *)b[j]; 1526068Smckusic sh /= NINDIR(&io->i_fs); 1536068Smckusic i = (bn / sh) % NINDIR(&io->i_fs); 154327Sbill nb = bap[i]; 155327Sbill if(nb == 0) { 156327Sbill printf("bn void %D\n",bn); 15710022Ssam return ((daddr_t)0); 158327Sbill } 159327Sbill } 16010022Ssam return (nb); 161327Sbill } 162327Sbill 163327Sbill static ino_t 16430768Skarels dlook(s, io, dir) 1656068Smckusic char *s; 1666068Smckusic register struct iob *io; 16730768Skarels char *dir; 168327Sbill { 169327Sbill register struct direct *dp; 170327Sbill register struct inode *ip; 1716068Smckusic struct dirstuff dirp; 1726068Smckusic int len; 173327Sbill 1746068Smckusic if (s == NULL || *s == '\0') 17510022Ssam return (0); 176327Sbill ip = &io->i_ino; 1776068Smckusic if ((ip->i_mode&IFMT) != IFDIR) { 17830768Skarels printf("%s: not a directory\n", dir); 17910022Ssam return (0); 180327Sbill } 1816068Smckusic if (ip->i_size == 0) { 18230768Skarels printf("%s: zero length directory\n", dir); 18310022Ssam return (0); 184327Sbill } 1856068Smckusic len = strlen(s); 1866068Smckusic dirp.loc = 0; 1876068Smckusic dirp.io = io; 1886068Smckusic for (dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) { 1896068Smckusic if(dp->d_ino == 0) 1906068Smckusic continue; 1916068Smckusic if (dp->d_namlen == len && !strcmp(s, dp->d_name)) 19210022Ssam return (dp->d_ino); 193327Sbill } 19410022Ssam return (0); 195327Sbill } 196327Sbill 1976068Smckusic /* 1986068Smckusic * get next entry in a directory. 1996068Smckusic */ 2006068Smckusic struct direct * 2016068Smckusic readdir(dirp) 2026068Smckusic register struct dirstuff *dirp; 203327Sbill { 2046068Smckusic register struct direct *dp; 2056068Smckusic register struct iob *io; 2066068Smckusic daddr_t lbn, d; 2076068Smckusic int off; 208327Sbill 2096068Smckusic io = dirp->io; 2106068Smckusic for(;;) { 2116068Smckusic if (dirp->loc >= io->i_ino.i_size) 21211083Ssam return (NULL); 2136068Smckusic off = blkoff(&io->i_fs, dirp->loc); 2146068Smckusic if (off == 0) { 2156068Smckusic lbn = lblkno(&io->i_fs, dirp->loc); 2166068Smckusic d = sbmap(io, lbn); 2176068Smckusic if(d == 0) 2186068Smckusic return NULL; 2196068Smckusic io->i_bn = fsbtodb(&io->i_fs, d) + io->i_boff; 2206068Smckusic io->i_ma = io->i_buf; 2216068Smckusic io->i_cc = blksize(&io->i_fs, &io->i_ino, lbn); 22211083Ssam if (devread(io) < 0) { 22311083Ssam errno = io->i_error; 22425166Skarels printf("bn %D: directory read error\n", 22525166Skarels io->i_bn); 22611083Ssam return (NULL); 22711083Ssam } 2286068Smckusic } 2296068Smckusic dp = (struct direct *)(io->i_buf + off); 2306068Smckusic dirp->loc += dp->d_reclen; 2316068Smckusic if (dp->d_ino == 0) 2326068Smckusic continue; 2336068Smckusic return (dp); 234327Sbill } 235327Sbill } 236327Sbill 237327Sbill lseek(fdesc, addr, ptr) 23810022Ssam int fdesc, ptr; 23910022Ssam off_t addr; 240327Sbill { 241327Sbill register struct iob *io; 242327Sbill 24325442Skarels #ifndef SMALL 244327Sbill if (ptr != 0) { 245327Sbill printf("Seek not from beginning of file\n"); 24610022Ssam errno = EOFFSET; 24710022Ssam return (-1); 248327Sbill } 24925442Skarels #endif SMALL 250327Sbill fdesc -= 3; 2516068Smckusic if (fdesc < 0 || fdesc >= NFILES || 25210022Ssam ((io = &iob[fdesc])->i_flgs & F_ALLOC) == 0) { 25310022Ssam errno = EBADF; 25410022Ssam return (-1); 25510022Ssam } 256327Sbill io->i_offset = addr; 2576068Smckusic io->i_bn = addr / DEV_BSIZE; 258327Sbill io->i_cc = 0; 25910022Ssam return (0); 260327Sbill } 261327Sbill 262327Sbill getc(fdesc) 26310022Ssam int fdesc; 264327Sbill { 265327Sbill register struct iob *io; 2666068Smckusic register struct fs *fs; 267327Sbill register char *p; 2686068Smckusic int c, lbn, off, size, diff; 269327Sbill 270327Sbill 271327Sbill if (fdesc >= 0 && fdesc <= 2) 27210022Ssam return (getchar()); 273327Sbill fdesc -= 3; 2746068Smckusic if (fdesc < 0 || fdesc >= NFILES || 27510022Ssam ((io = &iob[fdesc])->i_flgs&F_ALLOC) == 0) { 27610022Ssam errno = EBADF; 27710022Ssam return (-1); 27810022Ssam } 279327Sbill p = io->i_ma; 280327Sbill if (io->i_cc <= 0) { 2816068Smckusic if ((io->i_flgs & F_FILE) != 0) { 2826068Smckusic diff = io->i_ino.i_size - io->i_offset; 2836068Smckusic if (diff <= 0) 2846068Smckusic return (-1); 2856068Smckusic fs = &io->i_fs; 2866068Smckusic lbn = lblkno(fs, io->i_offset); 2876068Smckusic io->i_bn = fsbtodb(fs, sbmap(io, lbn)) + io->i_boff; 2886068Smckusic off = blkoff(fs, io->i_offset); 2896068Smckusic size = blksize(fs, &io->i_ino, lbn); 2906068Smckusic } else { 2916068Smckusic io->i_bn = io->i_offset / DEV_BSIZE; 2926068Smckusic off = 0; 2936068Smckusic size = DEV_BSIZE; 2946068Smckusic } 295327Sbill io->i_ma = io->i_buf; 2966068Smckusic io->i_cc = size; 29711083Ssam if (devread(io) < 0) { 29811083Ssam errno = io->i_error; 29911083Ssam return (-1); 30011083Ssam } 3016068Smckusic if ((io->i_flgs & F_FILE) != 0) { 3026068Smckusic if (io->i_offset - off + size >= io->i_ino.i_size) 3036068Smckusic io->i_cc = diff + off; 304327Sbill io->i_cc -= off; 3056068Smckusic } 306327Sbill p = &io->i_buf[off]; 307327Sbill } 308327Sbill io->i_cc--; 309327Sbill io->i_offset++; 310327Sbill c = (unsigned)*p++; 311327Sbill io->i_ma = p; 31210022Ssam return (c); 313327Sbill } 3146068Smckusic 31510022Ssam int errno; 316327Sbill 317327Sbill read(fdesc, buf, count) 31810022Ssam int fdesc, count; 31910022Ssam char *buf; 320327Sbill { 32125166Skarels register i, size; 322327Sbill register struct iob *file; 32325166Skarels register struct fs *fs; 32425166Skarels int lbn, off; 325327Sbill 32610022Ssam errno = 0; 327327Sbill if (fdesc >= 0 & fdesc <= 2) { 328327Sbill i = count; 329327Sbill do { 330327Sbill *buf = getchar(); 331327Sbill } while (--i && *buf++ != '\n'); 33210022Ssam return (count - i); 333327Sbill } 334327Sbill fdesc -= 3; 3356068Smckusic if (fdesc < 0 || fdesc >= NFILES || 33610022Ssam ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) { 33710022Ssam errno = EBADF; 33810022Ssam return (-1); 33910022Ssam } 34010022Ssam if ((file->i_flgs&F_READ) == 0) { 34110022Ssam errno = EBADF; 34210022Ssam return (-1); 34310022Ssam } 34425442Skarels #ifndef SMALL 3456068Smckusic if ((file->i_flgs & F_FILE) == 0) { 346327Sbill file->i_cc = count; 347327Sbill file->i_ma = buf; 3487446Sroot file->i_bn = file->i_boff + (file->i_offset / DEV_BSIZE); 349327Sbill i = devread(file); 35010022Ssam if (i < 0) 35110022Ssam errno = file->i_error; 35230547Skarels else 35330547Skarels file->i_offset += i; 35410022Ssam return (i); 355327Sbill } 35625442Skarels #endif SMALL 35725166Skarels if (file->i_offset+count > file->i_ino.i_size) 35825166Skarels count = file->i_ino.i_size - file->i_offset; 35925166Skarels if ((i = count) <= 0) 36025166Skarels return (0); 36125166Skarels /* 36225166Skarels * While reading full blocks, do I/O into user buffer. 36325166Skarels * Anything else uses getc(). 36425166Skarels */ 36525166Skarels fs = &file->i_fs; 36625166Skarels while (i) { 36725166Skarels off = blkoff(fs, file->i_offset); 36825166Skarels lbn = lblkno(fs, file->i_offset); 36925166Skarels size = blksize(fs, &file->i_ino, lbn); 37025166Skarels if (off == 0 && size <= i) { 37125166Skarels file->i_bn = fsbtodb(fs, sbmap(file, lbn)) + 37225166Skarels file->i_boff; 37325166Skarels file->i_cc = size; 37425166Skarels file->i_ma = buf; 37525166Skarels if (devread(file) < 0) { 37625166Skarels errno = file->i_error; 37725166Skarels return (-1); 37825166Skarels } 37925166Skarels file->i_offset += size; 38025166Skarels file->i_cc = 0; 38125166Skarels buf += size; 38225166Skarels i -= size; 38325166Skarels } else { 38425166Skarels size -= off; 38525166Skarels if (size > i) 38625166Skarels size = i; 38725166Skarels i -= size; 38825166Skarels do { 38925166Skarels *buf++ = getc(fdesc+3); 39025166Skarels } while (--size); 39125166Skarels } 39225166Skarels } 39325166Skarels return (count); 394327Sbill } 395327Sbill 39625442Skarels #ifndef SMALL 397327Sbill write(fdesc, buf, count) 39810022Ssam int fdesc, count; 39910022Ssam char *buf; 400327Sbill { 401327Sbill register i; 402327Sbill register struct iob *file; 403327Sbill 40410022Ssam errno = 0; 405327Sbill if (fdesc >= 0 && fdesc <= 2) { 406327Sbill i = count; 407327Sbill while (i--) 408327Sbill putchar(*buf++); 40910022Ssam return (count); 410327Sbill } 411327Sbill fdesc -= 3; 4126068Smckusic if (fdesc < 0 || fdesc >= NFILES || 41310022Ssam ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) { 41410022Ssam errno = EBADF; 41510022Ssam return (-1); 41610022Ssam } 41710022Ssam if ((file->i_flgs&F_WRITE) == 0) { 41810022Ssam errno = EBADF; 41910022Ssam return (-1); 42010022Ssam } 421327Sbill file->i_cc = count; 422327Sbill file->i_ma = buf; 4237446Sroot file->i_bn = file->i_boff + (file->i_offset / DEV_BSIZE); 424327Sbill i = devwrite(file); 4257446Sroot file->i_offset += count; 42610022Ssam if (i < 0) 42710022Ssam errno = file->i_error; 42810022Ssam return (i); 429327Sbill } 43025442Skarels #endif SMALL 431327Sbill 4323349Swnj int openfirst = 1; 43330547Skarels unsigned opendev; /* last device opened */ 43430547Skarels extern unsigned bootdev; 4353349Swnj 436327Sbill open(str, how) 4376068Smckusic char *str; 43810022Ssam int how; 439327Sbill { 440327Sbill register char *cp; 44130547Skarels register int i; 442327Sbill register struct iob *file; 44310022Ssam int fdesc; 44410022Ssam long atol(); 445327Sbill 4463349Swnj if (openfirst) { 447327Sbill for (i = 0; i < NFILES; i++) 448327Sbill iob[i].i_flgs = 0; 4493349Swnj openfirst = 0; 450327Sbill } 451327Sbill 452327Sbill for (fdesc = 0; fdesc < NFILES; fdesc++) 453327Sbill if (iob[fdesc].i_flgs == 0) 454327Sbill goto gotfile; 455327Sbill _stop("No more file slots"); 456327Sbill gotfile: 457327Sbill (file = &iob[fdesc])->i_flgs |= F_ALLOC; 458327Sbill 45930924Skarels #ifndef SMALL 46030547Skarels for (cp = str; *cp && *cp != '/' && *cp != ':' && *cp != '('; cp++) 46130547Skarels ; 46230547Skarels if (*cp == '(') { 46330547Skarels if ((file->i_ino.i_dev = getdev(str, cp - str)) == -1) 46430547Skarels goto bad; 46530547Skarels cp++; 46630547Skarels if ((file->i_unit = getunit(cp)) == -1) 46730547Skarels goto bad; 46830547Skarels for (; *cp != ','; cp++) 469*33408Skarels if (*cp == 0) { 47030547Skarels errno = EOFFSET; 47130547Skarels goto badspec; 47230547Skarels } 47330768Skarels file->i_boff = atol(++cp); 47430547Skarels for (;;) { 47530547Skarels if (*cp == ')') 47630547Skarels break; 47730547Skarels if (*cp++) 47830547Skarels continue; 47930547Skarels goto badspec; 48030547Skarels } 48130768Skarels cp++; 48230547Skarels } else if (*cp != ':') { 48330924Skarels #endif 48425166Skarels /* default bootstrap unit and device */ 48530547Skarels file->i_ino.i_dev = (bootdev >> B_TYPESHIFT) & B_TYPEMASK; 48630547Skarels file->i_unit = ((bootdev >> B_UNITSHIFT) & B_UNITMASK) + 48730547Skarels (8 * ((bootdev >> B_ADAPTORSHIFT) & B_ADAPTORMASK)); 48830547Skarels file->i_boff = (bootdev >> B_PARTITIONSHIFT) & B_PARTITIONMASK; 48925166Skarels cp = str; 49030924Skarels #ifndef SMALL 49125166Skarels } else { 49225166Skarels # define isdigit(n) ((n>='0') && (n<='9')) 49330547Skarels if (cp == str) 49430547Skarels goto badspec; 49525166Skarels /* 49625166Skarels * syntax for possible device name: 49725166Skarels * <alpha-string><digit-string><letter>: 49825166Skarels */ 49925166Skarels for (cp = str; *cp != ':' && !isdigit(*cp); cp++) 50025166Skarels ; 50130547Skarels if ((file->i_ino.i_dev = getdev(str, cp - str)) == -1) 50230547Skarels goto bad; 50330547Skarels if ((file->i_unit = getunit(cp)) == -1) 50430547Skarels goto bad; 50530547Skarels while (isdigit(*cp)) 50630547Skarels cp++; 50730547Skarels file->i_boff = 0; 50830547Skarels if (*cp >= 'a' && *cp <= 'h') 50930547Skarels file->i_boff = *cp++ - 'a'; 51025166Skarels if (*cp++ != ':') { 51125166Skarels errno = EOFFSET; 51230547Skarels goto badspec; 51325166Skarels } 51425166Skarels } 51530924Skarels #endif 51630547Skarels opendev = file->i_ino.i_dev << B_TYPESHIFT; 517*33408Skarels opendev |= (file->i_unit % 8) << B_UNITSHIFT; 518*33408Skarels opendev |= (file->i_unit / 8) << B_ADAPTORSHIFT; 51930547Skarels opendev |= file->i_boff << B_PARTITIONSHIFT; 52030768Skarels opendev |= B_DEVMAGIC; 52130547Skarels if (errno = devopen(file)) 52230547Skarels goto bad; 523*33408Skarels #ifndef SMALL 52425166Skarels if (cp != str && *cp == '\0') { 52525166Skarels file->i_flgs |= how+1; 52625166Skarels file->i_cc = 0; 52725166Skarels file->i_offset = 0; 52825166Skarels return (fdesc+3); 52925166Skarels } 530*33408Skarels #endif 5316068Smckusic file->i_ma = (char *)(&file->i_fs); 5326068Smckusic file->i_cc = SBSIZE; 53330768Skarels file->i_bn = SBOFF / DEV_BSIZE + file->i_boff; 5346068Smckusic file->i_offset = 0; 53511083Ssam if (devread(file) < 0) { 53611083Ssam errno = file->i_error; 53711083Ssam printf("super block read error\n"); 53830547Skarels goto bad; 53911083Ssam } 540327Sbill if ((i = find(cp, file)) == 0) { 54110022Ssam errno = ESRCH; 54230547Skarels goto bad; 543327Sbill } 54425442Skarels #ifndef SMALL 545327Sbill if (how != 0) { 546327Sbill printf("Can't write files yet.. Sorry\n"); 54710022Ssam errno = EIO; 54830547Skarels goto bad; 549327Sbill } 55025442Skarels #endif SMALL 55111083Ssam if (openi(i, file) < 0) { 55211083Ssam errno = file->i_error; 55330547Skarels goto bad; 55411083Ssam } 555327Sbill file->i_offset = 0; 556327Sbill file->i_cc = 0; 557327Sbill file->i_flgs |= F_FILE | (how+1); 55810022Ssam return (fdesc+3); 55930547Skarels 560*33408Skarels #ifndef SMALL 56130547Skarels badspec: 56230547Skarels printf("malformed device specification\n"); 563*33408Skarels #endif 56430547Skarels bad: 56530547Skarels file->i_flgs = 0; 56630547Skarels return (-1); 567327Sbill } 568327Sbill 56930924Skarels #ifndef SMALL 57030547Skarels static 57130547Skarels getdev(str, len) 572*33408Skarels register char *str; 57330547Skarels int len; 57430547Skarels { 57530547Skarels register struct devsw *dp; 576*33408Skarels register int i; 577*33408Skarels char c = str[len]; 57830547Skarels 579*33408Skarels str[len] = 0; 580*33408Skarels for (dp = devsw, i = 0; i < ndevs; dp++, i++) 581*33408Skarels if (dp->dv_name && strcmp(str, dp->dv_name) == 0) { 582*33408Skarels str[len] = c; 583*33408Skarels return (i); 584*33408Skarels } 585*33408Skarels printf("Unknown device\nKnown devices are:\n"); 586*33408Skarels for (dp = devsw, i = 0; i < ndevs; dp++, i++) 587*33408Skarels if (dp->dv_name) 588*33408Skarels printf(" %s", dp->dv_name); 58930547Skarels errno = ENXIO; 59030547Skarels return (-1); 59130547Skarels } 59230547Skarels 59330547Skarels static 59430547Skarels getunit(cp) 59530547Skarels register char *cp; 59630547Skarels { 59730547Skarels register int i = 0; 59830547Skarels 59930547Skarels while (*cp >= '0' && *cp <= '9') 60030547Skarels i = i * 10 + *cp++ - '0'; 60130547Skarels if ((unsigned) i > 255) { 60230547Skarels printf("minor device number out of range (0-255)\n"); 60330547Skarels errno = EUNIT; 60430547Skarels i = -1; 60530547Skarels } 60630547Skarels return (i); 60730547Skarels } 60830924Skarels #endif 60930547Skarels 610327Sbill close(fdesc) 61110022Ssam int fdesc; 612327Sbill { 613327Sbill struct iob *file; 614327Sbill 615327Sbill fdesc -= 3; 6166068Smckusic if (fdesc < 0 || fdesc >= NFILES || 61710022Ssam ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) { 61810022Ssam errno = EBADF; 61910022Ssam return (-1); 62010022Ssam } 621327Sbill if ((file->i_flgs&F_FILE) == 0) 622327Sbill devclose(file); 623327Sbill file->i_flgs = 0; 62410022Ssam return (0); 625327Sbill } 626327Sbill 62725442Skarels #ifndef SMALL 62810022Ssam ioctl(fdesc, cmd, arg) 62910022Ssam int fdesc, cmd; 63010022Ssam char *arg; 63110022Ssam { 63210022Ssam register struct iob *file; 63310022Ssam int error = 0; 63410022Ssam 63510331Shelge fdesc -= 3; 63610022Ssam if (fdesc < 0 || fdesc >= NFILES || 63710022Ssam ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) { 63810022Ssam errno = EBADF; 63910022Ssam return (-1); 64010022Ssam } 64110022Ssam switch (cmd) { 64210022Ssam 64310022Ssam case SAIOHDR: 64410022Ssam file->i_flgs |= F_HDR; 64510022Ssam break; 64610022Ssam 64710022Ssam case SAIOCHECK: 64810022Ssam file->i_flgs |= F_CHECK; 64910022Ssam break; 65010022Ssam 65110022Ssam case SAIOHCHECK: 65210022Ssam file->i_flgs |= F_HCHECK; 65310022Ssam break; 65410022Ssam 65510331Shelge case SAIONOBAD: 65610331Shelge file->i_flgs |= F_NBSF; 65710331Shelge break; 65810331Shelge 65910331Shelge case SAIODOBAD: 66010331Shelge file->i_flgs &= ~F_NBSF; 66110331Shelge break; 66210331Shelge 66310022Ssam default: 66410022Ssam error = devioctl(file, cmd, arg); 66510022Ssam break; 66610022Ssam } 66710022Ssam if (error < 0) 66810022Ssam errno = file->i_error; 66910022Ssam return (error); 67010022Ssam } 67125442Skarels #endif SMALL 67210022Ssam 673327Sbill exit() 674327Sbill { 675327Sbill _stop("Exit called"); 676327Sbill } 677327Sbill 678327Sbill _stop(s) 67910022Ssam char *s; 680327Sbill { 6812391Stoy int i; 6822391Stoy 6832391Stoy for (i = 0; i < NFILES; i++) 6842391Stoy if (iob[i].i_flgs != 0) 6852391Stoy close(i); 686327Sbill printf("%s\n", s); 687327Sbill _rtt(); 688327Sbill } 689