📄 sys.c
字号:
#ifndef lintstatic char sccsid[] = "@(#)sys.c 1.1 92/07/30 SMI";#endif/* * Copyright (c) 1985-1989 Sun Microsystems, Inc. */#ifndef KADB/* * Basic file system reading code for standalone I/O system. * Simulates a primitive UNIX I/O system (read(), write(), open(), etc). * Does not attempt writes to file systems, tho writing to whole devices * is supported, when the driver supports it. */#include <stand/param.h>#include <stand/saio.h>#include <sys/time.h>#include <sys/vnode.h>#include <ufs/fsdir.h>#include <ufs/fs.h>#include <ufs/inode.h>#define NULL 0#define skipblank(p) { while (*(p) == ' ') (p)++; }struct direct *readdir();/* * This struct keeps track of an open file in the standalone I/O system. * * It includes an IOB for device addess, an inode, a buffer for reading * indirect blocks and inodes, and a buffer for the superblock of the * file system (if any). */struct iob { struct saioreq i_si; /* I/O request block for this file */ struct inode i_ino; /* Inode for this file */ char i_buf[MAXBSIZE];/* Buffer for reading inodes & dirs */ union { struct fs ui_fs; /* Superblock for file system */ char dummy[SBSIZE]; } i_un;};#define i_flgs i_si.si_flgs#define i_boottab i_si.si_boottab#define i_devdata i_si.si_devdata#define i_ctlr i_si.si_ctlr#define i_unit i_si.si_unit#define i_boff i_si.si_boff#define i_cyloff i_si.si_cyloff#define i_offset i_si.si_offset#define i_bn i_si.si_bn#define i_ma i_si.si_ma#define i_cc i_si.si_cc#define i_fs i_un.ui_fs/* These are the pools of buffers, iob's, etc. */#define NBUFS (NIADDR+1) /* NOT! a variable */char b[NBUFS][MAXBSIZE];daddr_t blknos[NBUFS];struct saioreq *open_sip;struct iob iob[NFILES];ino_t dlook();struct dirstuff { int loc; struct iob *io;};staticopeni(n,io) ino_t n; register struct iob *io;{ register struct dinode *dp; io->i_offset = 0; io->i_bn = fsbtodb(&io->i_fs, itod(&io->i_fs, n)); io->i_cc = io->i_fs.fs_bsize; io->i_ma = io->i_buf; /* FIXME: this call to devread() does not check for errors! */ devread(&io->i_si); dp = (struct dinode *)io->i_buf; io->i_ino.i_ic = dp[itoo(&io->i_fs, n)].di_ic;}static ino_tfind(path, file) register char *path; struct iob *file;{ register char *q; char c; ino_t n; if (path==NULL || *path=='\0') { printf("null path\n"); return(0); } openi((ino_t) ROOTINO, file); while (*path) { while (*path == '/') path++; q = path; while(*q != '/' && *q != '\0') q++; c = *q; *q = '\0'; if ((n=dlook(path, file))!=0) { if (c=='\0') break; openi(n, file); *q = c; path = q; continue; } else { printf("%s not found\n",path); return(0); } } return(n);}static daddr_tsbmap(io, bn) register struct iob *io; daddr_t bn;{ register struct inode *ip; register int i, j, sh; register daddr_t nb, *bap; register daddr_t *db; ip = &io->i_ino; db = ip->i_db; /* * blocks 0..NDADDR are direct blocks */ if(bn < NDADDR) { nb = db[bn]; return(nb); }#ifndef BOOTBLOCK /* * addresses NIADDR have single and double indirect blocks. * the first step is to determine how many levels of indirection. */ sh = 1; bn -= NDADDR; for (j = NIADDR; j > 0; j--) { sh *= NINDIR(&io->i_fs); if (bn < sh) break; bn -= sh; } if (j == 0) { printf("bn ovf %D\n", bn); return ((daddr_t)0); } /* * fetch the first indirect block address from the inode */ nb = ip->i_ib[NIADDR - j]; if (nb == 0) { printf("bn void %D\n",bn); return((daddr_t)0); } /* * fetch through the indirect blocks */ for (; j <= NIADDR; j++) { if (blknos[j] != nb) { io->i_bn = fsbtodb(&io->i_fs, nb); io->i_ma = b[j]; io->i_cc = io->i_fs.fs_bsize; if (devread(&io->i_si) != io->i_cc) return((daddr_t)0); blknos[j] = nb; } bap = (daddr_t *)b[j]; sh /= NINDIR(&io->i_fs); i = (bn / sh) % NINDIR(&io->i_fs); nb = bap[i]; if(nb == 0) { printf("bn void %D\n",bn); return((daddr_t)0); } } return(nb);#else BOOTBLOCK return((daddr_t)0);#endif BOOTBLOCK}static ino_tdlook(s, io) char *s; register struct iob *io;{ register struct direct *dp; register struct inode *ip; struct dirstuff dirp; register int len; ip = &io->i_ino;#ifndef BOOTBLOCK if (s == NULL || *s == '\0') return(0); if ((ip->i_mode&IFMT) != IFDIR) { printf("not a directory\n"); return(0); } if (ip->i_size == 0) { printf("zero length directory\n"); return(0); }#endif BOOTBLOCK len = strlen(s); dirp.loc = 0; dirp.io = io; for (dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) { if(dp->d_ino == 0) continue; if (dp->d_namlen == len && !strcmp(s, dp->d_name)) return(dp->d_ino);#ifndef BOOTBLOCK /* Allow "*" to print all names at that level, w/out match */ if (!strcmp(s, "*")) printf("%s\n", dp->d_name);#endif BOOTBLOCK } return(0);}/* * get next entry in a directory. */struct direct *readdir(dirp) register struct dirstuff *dirp;{ register struct direct *dp; register struct iob *io; register daddr_t lbn, d; register int off; io = dirp->io; for(;;) { if (dirp->loc >= io->i_ino.i_size) return NULL; off = blkoff(&io->i_fs, dirp->loc); if (off == 0) { lbn = lblkno(&io->i_fs, dirp->loc); d = sbmap(io, lbn); if(d == 0) return NULL; io->i_bn = fsbtodb(&io->i_fs, d); io->i_ma = io->i_buf; io->i_cc = blksize(&io->i_fs, &io->i_ino, lbn); if (devread(&io->i_si) != io->i_cc) return NULL; } dp = (struct direct *)(io->i_buf + off); dirp->loc += dp->d_reclen; if (dp->d_ino == 0) continue; return (dp); }}/*ARGSUSED*/lseek(fdesc, addr, ptr) int fdesc; register off_t addr; int ptr;{ register struct iob *io;#ifndef BOOTBLOCK fdesc -= 3; if (fdesc < 0 || fdesc >= NFILES || ((io = &iob[fdesc])->i_flgs & F_ALLOC) == 0) return(-1);#else BOOTBLOCK io = &iob[fdesc - 3];#endif BOOTBLOCK io->i_si.si_flgs &= ~F_EOF; io->i_offset = addr; io->i_bn = addr / DEV_BSIZE; io->i_cc = 0; return(0);}/* FIXME: possibly make this static and pass iob, eliminating assorted tests? */getc(fdesc) int fdesc;{ register struct iob *io; register struct fs *fs; register char *p; register int c, off, size, diff; register daddr_t lbn;#ifndef BOOTBLOCK if (fdesc >= 0 && fdesc <= 2) return(getchar()); fdesc -= 3; if (fdesc < 0 || fdesc >= NFILES || ((io = &iob[fdesc])->i_flgs&F_ALLOC) == 0) return(-1);#else BOOTBLOCK io = &iob[fdesc -= 3];#endif BOOTBLOCK p = io->i_ma; if (io->i_cc <= 0) { if ((io->i_flgs & F_FILE) != 0) { diff = io->i_ino.i_size - io->i_offset; if (diff <= 0) return (-1); fs = &io->i_fs; lbn = lblkno(fs, io->i_offset); io->i_bn = fsbtodb(fs, sbmap(io, lbn)); off = blkoff(fs, io->i_offset); size = blksize(fs, &io->i_ino, lbn); } else { io->i_bn = io->i_offset / DEV_BSIZE; off = 0; size = DEV_BSIZE; } io->i_ma = io->i_buf; io->i_cc = size; if (devread(&io->i_si) != io->i_cc) /* Trap errors */ return(-1); if ((io->i_flgs & F_FILE) != 0) { if (io->i_offset - off + size >= io->i_ino.i_size) io->i_cc = diff + off; io->i_cc -= off; } p = &io->i_buf[off]; } io->i_cc--; io->i_offset++; c = (unsigned)*p++; io->i_ma = p; return(c);}read(fdesc, buf, count) int fdesc; register char *buf; int count;{ register i,j; register struct iob *file;#ifndef BOOTBLOCK if (fdesc >= 0 && fdesc <= 2) { i = count; do { *buf = getchar(); } while (--i && *buf++ != '\n'); return(count - i); } fdesc -= 3; if (fdesc < 0 || fdesc >= NFILES || ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) return(-1); if ((file->i_flgs&F_READ) == 0) return(-1); fdesc += 3;#else BOOTBLOCK file = &iob[fdesc - 3];#endif BOOTBLOCK if ((file->i_flgs & F_FILE) == 0) { file->i_cc = count; file->i_ma = buf; file->i_bn = (file->i_offset / DEV_BSIZE); i = devread(&file->i_si); file->i_offset += count; return(i); } else { if (file->i_offset+count > file->i_ino.i_size) count = file->i_ino.i_size - file->i_offset; if ((i = count) <= 0) return(0);#ifdef BOOTBLOCK do { *buf++ = getc(fdesc); } while (--i);#else BOOTBLOCK while (i > 0) { if ((j = file->i_cc) <= 0) { *buf++ = getc(fdesc); i--; } else { if (i < j) j = i; bcopy(file->i_ma, buf, (unsigned)j); buf += j; file->i_ma += j; file->i_offset += j; file->i_cc -= j; i -= j; } }#endif BOOTBLOCK return(count); }}#ifndef BOOTBLOCKwrite(fdesc, buf, count) int fdesc; char *buf; int count;{ register i; register struct iob *file; if (fdesc >= 0 && fdesc <= 2) { i = count; while (i--) putchar(*buf++); return(count); } fdesc -= 3; if (fdesc < 0 || fdesc >= NFILES || ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) return(-1); if ((file->i_flgs&F_WRITE) == 0) return(-1); if (count % DEV_BSIZE) printf("count=%d?\n", count); file->i_cc = count; file->i_ma = buf; file->i_bn = (file->i_offset / DEV_BSIZE); i = devwrite(&file->i_si); file->i_offset += count; return(i);}#endif BOOTBLOCK/* * Open a file on a physical device, or open the device itself. * * The device is identified by a struct bootparam which gives pointers * to the struct boottab, containing the device open, strategy and close * routines; and the device parameters such as controller #, unit #, etc. * * If *str == 0, the device is opened, else the named file in the file * system on the device is opened. */intphysopen(bp, str, how) register struct bootparam *bp; char *str; int how;{ int fdesc; register struct iob *file;#ifdef BOOTBLOCK fdesc = 0; file = &iob[0]; file->i_flgs |= F_ALLOC;#else BOOTBLOCK fdesc = getiob(); /* Allocate an IOB */ file = &iob[fdesc];#endif BOOTBLOCK file->i_boottab = bp->bp_boottab; /* Record pointer to boot table */ file->i_ctlr = bp->bp_ctlr; file->i_unit = bp->bp_unit; file->i_boff = bp->bp_part; file->i_ino.i_dev = 0; /* Call it device 0 for chuckles */ return(openfile(fdesc, file, str, how));}#ifndef BOOTBLOCKint openfirst = 1;/* * Allocate an IOB for a newly opened file. */intgetiob(){ register int fdesc; if (openfirst) { openfirst = 0; for (fdesc = 0; fdesc < NFILES; fdesc++) iob[fdesc].i_flgs = 0; } for (fdesc = 0; fdesc < NFILES; fdesc++) if (iob[fdesc].i_flgs == 0) goto gotfile; _stop("No more file slots");gotfile: (&iob[fdesc])->i_flgs |= F_ALLOC; return fdesc;}/* * Description: Reads string for hex variable. * Also ignores blanks. Returns a pointer pointing at the next * non-blank character, skipping over one ','. * * Synopsis: status = gethex(p, ip) * status :(char *) pointer to next non-blank character * p :(char *) pointer to location of start of hex number * ip :(int) hex variable read */char *gethex(p, ip) register char *p; int *ip;{ register int ac = 0; skipblank(p); while (*p) { if (*p >= '0' && *p <= '9') ac = (ac<<4) + (*p - '0'); else if (*p >= 'a' && *p <= 'f') ac = (ac<<4) + (*p - 'a' + 10); else if (*p >= 'A' && *p <= 'F') ac = (ac<<4) + (*p - 'A' + 10); else break; p++; } skipblank(p); if (*p == ',') p++; skipblank(p); *ip = ac; return (p);}/* * Open a device or file-in-file-system-on-device. */intopen(str, how) char *str; int how;{ register char *cp; register struct iob *file; register struct boottab *dp; register struct boottab **tablep; int fdesc; long atol(); extern struct boottab *(devsw[]); fdesc = getiob(); /* Allocate an IOB */ file = &iob[fdesc]; open_sip = &file->i_si; for (cp = str; *cp && *cp != '('; cp++) ; if (*cp++ != '(') { file->i_flgs = 0; goto badsyntax; } for (tablep = devsw; 0 != (dp = *tablep); tablep++) { if (str[0] == dp->b_dev[0] && str[1] == dp->b_dev[1]) goto gotdev; } printf("Unknown device: %c%c; known devices:\n", str[0], str[1]); for (tablep = devsw; 0 != (dp = *tablep); tablep++) printf(" %s\n", dp->b_desc); file->i_flgs = 0; return(-1);gotdev: file->i_boottab = dp; /* Record pointer to boot table */ file->i_ino.i_dev = tablep-devsw; cp = gethex(cp, &file->i_ctlr); cp = gethex(cp, &file->i_unit); cp = gethex(cp, (int *)&file->i_boff); if (*cp == '\0') goto doit; if (*cp++ != ')') {badsyntax: printf("%s: bad syntax, try dev(ctlr,unit,part)name\n", str); return -1; } skipblank(cp);doit: return(openfile(fdesc, file, cp, how));}#endif NOOPEN/* * File processing for open call */openfile(fdesc, file, cp, how) int fdesc; struct iob *file; char *cp; int how;{ ino_t ino; if (devopen(&file->i_si)) { file->i_flgs = 0; return(-1); /* if devopen fails, open fails */ } if (*cp == '\0') { /* Opening a device */ file->i_flgs |= how+1; file->i_cc = 0; file->i_offset = 0; return(fdesc+3); } /* Opening a file system; read the superblock. */ file->i_ma = (char *)(&file->i_fs); file->i_cc = SBSIZE; file->i_bn = SBLOCK; file->i_offset = 0; if (devread(&file->i_si) != SBSIZE) { file->i_flgs = 0; return(-1); }#ifndef BOOTBLOCK if (file->i_fs.fs_magic != FS_MAGIC) { printf("Not a file system\n"); return(-1); }#endif BOOTBLOCK if ((ino = find(cp, file)) == 0) { file->i_flgs = 0; return(-1); }#ifndef BOOTBLOCK if (how != 0) { printf("Can't write files yet.. Sorry\n"); file->i_flgs = 0; return(-1); }#endif BOOTBLOCK openi(ino, file); file->i_offset = 0; file->i_cc = 0; file->i_flgs |= F_FILE | (how+1); return(fdesc+3);}close(fdesc) int fdesc;{ register struct iob *file; fdesc -= 3; if (fdesc < 0 || fdesc >= NFILES || ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0) return(-1); devclose(&file->i_si); /* For a file-in-filesys or for raw dev */ file->i_flgs = 0; return(0);}exit(){ _stop((char *)0);}_stop(s) char *s;{ register int i; for (i = 0; i < NFILES; i++) if (iob[i].i_flgs != 0) close(i); if (s) printf("%s\n", s); _exit();}panic(s) char *s;{ _stop(s);}#endif KADB
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -