vfs_sys.c
来自「操作系统SunOS 4.1.3版本的源码」· C语言 代码 · 共 716 行
C
716 行
#ifndef lintstatic char sccsid[] = "@(#)vfs_sys.c 1.1 92/07/30 Copyr 1986 Sun Micro";#endif/* * Copyright (c) 1986 by Sun Microsystems, Inc. *//* * 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 "boot/param.h"#include <sys/param.h>#include <stand/saio.h>#include "boot/systm.h"#include <sys/dir.h>#include <sys/time.h>#include "boot/vnode.h"#include <ufs/fs.h>#include "boot/inode.h"#include <sys/uio.h>#include <sys/fcntl.h>#include <sys/file.h>#include <sys/user.h>#include "boot/iob.h"#ifdef OPENPROMS#include "boot/conf.h"#endif#undef uextern struct user u;/* These are the pools of buffers, iob's, etc. */char b[NBUFS][MAXBSIZE];daddr_t blknos[NBUFS];struct iob iob[NFILES];static int dump_debug = 20;extern char *gethex();char *string();char *dev_unit_file();char *pathname();char *server_path();/* * */intxopen(str, how) char *str; int how;{ register char *p; char dev[DEV_NAME_LEN+1]; char filename[FILE_NAME_LEN+1]; char server[SERVER_NAME_LEN+1]; char pathname[PATHNAME_LEN+1]; int ctlr, unit, part; if ((p = dev_unit_file(str, dev, &ctlr, &unit, &part, filename)) != (char *)-1) { if (*p != '\0') { printf ("garbage after filename '%s'\n", filename); return (-1); } return (open_dev_file(dev, ctlr, unit, part, filename)); } else if ((p = server_path(str, server, pathname)) != (char *)-1) { if (*p != '\0') { printf ("garbage after pathname '%s'\n", pathname); return (-1); } return (open_server_path(server, pathname)); } else { printf ("syntax error: try again\n"); return (-1); }}/* * Parse the construct: * * <dev_unit_file> -> <dev>(<ctlr>, <unit>, <part>) <filename> */char *dev_unit_file(str, dev, ctlr, unit, part, filename) char *str; char *dev; int *ctlr; int *unit; int *part; char *filename;{ char *p; if ((p = string(str, dev)) == (char *)-1) { printf ("%s: bad device\n", str); return ((char *)-1); } if (*p++ != '(') { return ((char *)-1); } p = gethex(p, ctlr); if (*p++ != ',') { return ((char *)-1); } p = gethex(p, unit); if (*p++ != ',') { return ((char *)-1); } p = gethex(p, part); if (*p++ != ')') { return ((char *)-1); } if ((p = string(p, filename)) == (char *)-1) { return ((char *)-1); } return (p);}/* * Parses: * * <server_path> -> <server> : <pathname> */char *server_path(str, server, path) char *str; char *server; char *path;{ char *p; if ((p = string(str, server)) == (char *)-1) { printf("%s: bad server name\n", str); return ((char *)-1); } if (*p++ != ':') { printf("%s: no ':' following server name\n", str); return ((char *)-1); } if ((p = pathname(p, path)) == (char *)-1) { printf("%s: bad pathname\n", str); return ((char *)-1); } return (0);}/* * Parses: * <path> = / <string> */char *pathname(str, path) char *str; char *path;{ char *p, *p1; for (p = str, p1 = path; *p; p++, p1++) *p1 = *p; *p1 = '\0'; return (p);}/* * Parses: * * <string> -> {[a-z][A-Z][0-9][._-,:+%]}* * * Terminates the output string with a zero byte. * Returns: pointer to the next character after the end of * the string, or -1 if there is no valid character in the * string. */char *string(str, dest) char *str; char *dest;{ char *p, *p1; for (p = str; *p == ' '; p++); for (p1 = dest; *p; p++, p1++) { if ((*p >= 'a') && (*p <= 'z')) *p1 = *p; else if ((*p >= 'A') && (*p <= 'Z')) *p1 = *p; else if ((*p >= '0') && (*p <= '9')) *p1 = *p; else if ((*p == '.') || (*p == '_') || (*p == '-') || (*p == ',') || (*p == ':') || (*p == '+') || (*p == '%') || (*p == '*') || (*p == '/')) *p1 = *p; else break; } if (p1 == dest) { /* No valid characters. */ dprint(dump_debug, 6, "string: no valid characters p 0x%x p1 0x%x\n", p, p1); *p1 = '\0'; return ((char *)-1); } *p1 = '\0'; return (p); /* Next character after string */}open_server_path(server, path) char *server; char *path;{ return (-1);}intopen_dev_file(dev, ctlr, unit, part, file) char *dev; int ctlr; int unit; int part; char *file;{ return (-1);}fopen(fnamep, fmode, cmode) char *fnamep; int fmode; int cmode;{}boot_lseek(fd, off, sbase) int fd; register off_t off; int sbase;{ struct iob *fp; u.u_error = getvnodefp(fd, &fp); if (u.u_error) {#ifdef DUMP_DEBUG dprint(dump_debug, 6, "lseek: bad fd 0x%x\n", fd);#endif DUMP_DEBUG return (-1); } if (((struct vnode *)fp->i_ino.i_devvp)->v_type == VFIFO) { u.u_error = ESPIPE; return (-1); } switch (sbase) { case L_INCR: fp->i_offset += off; break; case L_XTND: { struct vattr vattr; u.u_error = VOP_GETATTR((struct vnode *)fp->i_ino.i_devvp, &vattr, u.u_cred); if (u.u_error) return (-1); fp->i_offset = off + vattr.va_size; break; } case L_SET: fp->i_offset = off; break; default: u.u_error = EINVAL; } u.u_r.r_off = fp->i_offset;#ifdef DUMP_DEBUG1 dprint(dump_debug, 6, "lseek: new offset 0x%x\n", fp->i_offset);#endif DUMP_DEBUG1 return (0);}/*ARGSUSED*/boot_read(fdesc, buf, count) int fdesc; register char *buf; int count;{ int this_count = 0x2000; int total_read = 0; int this_read = 0; int cc;#ifdef DUMP_DEBUG1 dprint(dump_debug, 6, "read(fdesc %x, buf %x, count %x)\n", fdesc, buf, count);#endif DUMP_DEBUG1 while (count > 0) { cc = (count > this_count) ? this_count : count; this_read = xread(fdesc, buf, cc); if (u.u_error != 0) {#ifdef DEBUG printf("boot_read: u.u_error = %d!\n", u.u_error);#endif DEBUG return (-1); } if (this_read == 0) { /* EOF */#ifdef DEBUG printf("boot_read: this_read = 0, total_read = %d\n", total_read);#endif DEBUG break; } count -= this_read; buf += this_read; total_read += this_read; feedback(); /* Show activity */ }#ifdef DEBUG printf("boot_read: returning total_read = %d\n", total_read);#endif DEBUG return (total_read);}xread(fdesc, buf, count) int fdesc; register char *buf; int count;{ struct uio auio; struct iovec aiov;#ifdef DUMP_DEBUG1 dprint(dump_debug, 6, "xread(fdesc %x, buf %x, count %x)\n", fdesc, buf, count);#endif DUMP_DEBUG1 aiov.iov_base = buf; aiov.iov_len = count; auio.uio_iov = &aiov; auio.uio_iovcnt = 1; /* * It's all dark, really. */ auio.uio_seg = UIOSEG_KERNEL; rwuio(fdesc, &auio, UIO_READ); return (count-auio.uio_resid);}xclose(fdesc) int fdesc;{#ifdef lint fdesc = fdesc;#endif lint}exit(){ _stop((char *)0);}_stop(s) char *s;{ if (s) printf("%s\n", s); _exit();}panic(s) char *s;{ _stop(s);}/* * Open a device. No files involved at this point. */opendev(fdesc, file, how) int fdesc; struct iob *file; int how;{#ifdef OPENPROMS if (prom_getversion() > 0) return (obp_opendev(fdesc, file, how));#endif#ifndef sun4m /* * Only set ctlr field if device is an IPI ctlr. This allows * UNIX to be booted from multiple IPI ctlrs. Can't set * ctlr number in this fashion if sd device (such as CD-ROM) * since the bits are used for unit info (see below) */ if (major(file->i_ino.i_dev) == 1) file->i_si.si_ctlr = minor(file->i_ino.i_dev) >> 6; /* XXX * Purposely don't "AND" unit with 0x7, might break * other drivers. Driver must get rid of the ctlr * explicitly. */ file->i_si.si_unit = minor(file->i_ino.i_dev) >> 3; file->i_si.si_boff = minor(file->i_ino.i_dev) & 0x7;#ifndef OPENPROMS /* * XXX HACK HACK HACK - the non-OPENPROM "sd" driver (among others) * assumes that it will be given "unit" as a PROM style * (target * 8) + lun number. But getblockdev() needs to give * a real UNIX minor number (or loose some bits), thus it does * if ("sd") unit = (((unit & 0xF8) >> 2) | (unit & 0x01)); * Now we convert the si_unit for the "sd" driver back into * (target * 8) + lun. * This HACK is here instead of fixing "sd" driver so we * don't have to fix tpboot and standalone copy (may they die soon!) * as this work is being done betwee 4.1 preFCS and FCS!!! */ /* HARDCODE "sd" major number */ if (major(file->i_ino.i_dev) == 7) file->i_si.si_unit = ((minor(file->i_ino.i_dev) & 0xF0) >> 1) | ((minor(file->i_ino.i_dev) & 0x08) >> 3);#endif OPENPROMS if (devopen(&file->i_si)) { file->i_flgs = 0;#ifdef DUMP_DEBUG1 dprint(dump_debug, 6, "opendev: bad open\n");#endif DUMP_DEBUG1 return (-1); /* if devopen fails, open fails */ } file->i_flgs |= how+1; file->i_cc = 0; file->i_offset = 0; return (fdesc+3);#endif !sun4m}#ifdef OPENPROMS/* * Open a device. No files involved at this point. */obp_opendev(fdesc, file, how) int fdesc; struct iob *file; int how;{ register struct boottab *dp; register struct binfo *bd; register int phandle; char devtype[32]; dp = file->i_boottab; bd = (struct binfo *)kmem_alloc(sizeof (struct binfo)); bzero((caddr_t)bd, sizeof (struct binfo)); (struct binfo *)file->i_si.si_devdata = bd; bd->name = dp->b_desc; bd->ihandle = 0; if (devopen(&file->i_si)) { file->i_flgs = 0;#ifdef DUMP_DEBUG1 dprint(dump_debug, 6, "opendev: bad open\n");#endif DUMP_DEBUG1 return (-1); /* if devopen fails, open fails */ } /* * find out if the open device is a block device */ phandle = prom_getphandle(bd->ihandle); devtype[0] = '\0'; (void)prom_getprop(phandle, "device_type", devtype); switch (dp->b_dev[0]) { case 'b': if ((strcmp (devtype, "block") != 0) && (strcmp (devtype, "byte") != 0)) { devclose(&file->i_si); file->i_flgs = 0;#ifdef DUMP_DEBUG dprint(dump_debug, 6, "opendev: open device is not a block or byte device\n");#endif DUMP_DEBUG return (-2); /* if devopen fails, open fails */ } break; case 'n': if (strcmp (devtype, "network") != 0) { devclose(&file->i_si); file->i_flgs = 0;#ifdef DUMP_DEBUG dprint(dump_debug, 6, "opendev: open device is not a network device\n");#endif DUMP_DEBUG return (-2); /* if devopen fails, open fails */ } break; default: devclose(&file->i_si); file->i_flgs = 0;#ifdef DUMP_DEBUG dprint(dump_debug, 6, "opendev: open device is not a block, byte or net device\n");#endif DUMP_DEBUG return (-2); /* if devopen fails, open fails */ } file->i_flgs |= how+1; file->i_cc = 0; file->i_offset = 0; return (fdesc+3);}#endifrwuio(fdesc, uio, rw) int fdesc; register struct uio *uio; enum uio_rw rw;{ register struct iob *file; register struct iovec *iov; int i;#ifdef DUMP_DEBUG1 dprint(dump_debug, 6, "rwuio(fdesc 0x%x uio 0x%x rw 0x%x)\n", fdesc, uio, rw);#endif DUMP_DEBUG1 file = &iob[fdesc]; uio->uio_resid = 0; /* * It's all dark, really. */ uio->uio_seg = UIOSEG_KERNEL; iov = uio->uio_iov; for (i = 0; i < uio->uio_iovcnt; i++) { if (iov->iov_len < 0) { u.u_error = EINVAL;#ifdef DEBUG printf("rwuio: EINVAL: iov_len = %d\n", iov->iov_len);#endif DEBUG return; } uio->uio_resid += iov->iov_len; if (uio->uio_resid < 0) { u.u_error = EINVAL;#ifdef DEBUG printf("rwuio: EINVAL: iov_len %d, uio_resid %d\n", iov->iov_len, uio->uio_resid);#endif DEBUG return; } iov++; } /* * file->i_offset should be set correctly by lseek. */ uio->uio_offset = file->i_offset; uio->uio_fmode = 0 /* fp->f_flag */; if ((i = vno_rw(file, rw, uio)) != 0) {#ifdef DEBUG printf("rwuio: EIO: error %d from vno_rw!\n", i);#endif DEBUG u.u_error = EIO; return; } file->i_offset = uio->uio_offset;#ifdef DUMP_DEBUG1 dprint(dump_debug, 6, "rwuio: new offset 0x%x\n", file->i_offset);#endif DUMP_DEBUG1}vno_rw(fp, rw, uiop) struct iob *fp; enum uio_rw rw; struct uio *uiop;{ struct vnode *vp; register int error; /* * We store a pointer to the vnode in i_devvp. */ vp = fp->i_ino.i_devvp;#ifdef DUMP_DEBUG1 dprint(dump_debug, 6, "vno_rw: fp 0x%x vp 0x%x\n", fp, vp);#endif DUMP_DEBUG1 if (vp->v_type == VREG) { error = VOP_RDWR(vp, uiop, rw, IO_UNIT, u.u_cred); } else if (vp->v_type == VFIFO) { /* * NOTE: Kludge to ensure that FAPPEND stays set. * This ensures that fp->f_offset is always accurate. * * fp->f_flag |= FAPPEND; */ /* * NOTE: Kludge to ensure 'no delay' bit passes thru */ error = VOP_RDWR(vp, uiop, rw, IO_APPEND, u.u_cred); } else { error = VOP_RDWR(vp, uiop, rw, 0, u.u_cred); } if (error) {#ifdef DEBUG printf("vno_rw: returning error %d from VOP_RDWR, v_type ", error); switch (vp->v_type) { case VREG: printf("VREG\n"); break; case VFIFO: printf("VFIFO\n"); break; default: printf("default (%d)\n", vp->v_type); break; }#endif DEBUG return (error); } return (0);}/* * Get the file structure entry for the file descrpitor, but make sure * its a vnode. */intgetvnodefp(fd, fpp) int fd; struct iob **fpp;{ register struct iob *fp;#ifdef NEVER fp = getf(fd); if (fp == (struct file *)0) return (EBADF); if (fp->f_type != DTYPE_VNODE) return (EINVAL);#endif NEVER fp = &iob[fd]; *fpp = fp; return (0);}#define DIR_BUFF_LEN 512list_directory(dir) char *dir;{ char buffer[DIR_BUFF_LEN]; long basep; int directory; struct direct *dp;#ifdef DUMP_DEBUG dprint(dump_debug, 6, "list_directory('%s')\n", dir);#endif DUMP_DEBUG if ((directory = open (dir, O_RDONLY)) == -1) { dprint(dump_debug, 10, "list_directory: bad directory %s\n", dir); return (-1); }#ifdef DUMP_DEBUG dprint(dump_debug, 6, "list_directory: directory '%s' fd 0x%x\n", dir, directory);#endif DUMP_DEBUG while (1) { if (getdirents(directory, buffer, DIR_BUFF_LEN, &basep) == -1) {#ifdef DUMP_DEBUG dprint(dump_debug, 10, "list_directory: bad getdirents\n");#endif DUMP_DEBUG return (-1); } if (u.u_r.r_val1 == 0) {#ifdef DUMP_DEBUG dprint(dump_debug, 6, "list_directory: end of directory\n");#endif DUMP_DEBUG return (0); } for (dp = (struct direct *)buffer; dp < (struct direct *) ((char *)buffer + u.u_r.r_val1); /* enpty */) { printf("ino 0x%x: name '%s'\n", dp->d_fileno, &(dp->d_name[0])); dp = (struct direct *)((char *)dp + dp->d_reclen); } }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?