vfs_syscalls.c
来自「基于组件方式开发操作系统的OSKIT源代码」· C语言 代码 · 共 2,115 行 · 第 1/4 页
C
2,115 行
void *v; register_t *retval;{ register struct sys_fstatfs_args /* { syscallarg(int) fd; syscallarg(struct statfs *) buf; } */ *uap = v; struct file *fp; struct mount *mp; register struct statfs *sp; int error; if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) return (error); mp = ((struct vnode *)fp->f_data)->v_mount; sp = &mp->mnt_stat; if ((error = VFS_STATFS(mp, sp, p)) != 0) return (error); sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp)));}/* * Get statistics on all filesystems. */intsys_getfsstat(p, v, retval) struct proc *p; void *v; register_t *retval;{ register struct sys_getfsstat_args /* { syscallarg(struct statfs *) buf; syscallarg(long) bufsize; syscallarg(int) flags; } */ *uap = v; register struct mount *mp, *nmp; register struct statfs *sp; caddr_t sfsp; long count, maxcount, error; maxcount = SCARG(uap, bufsize) / sizeof(struct statfs); sfsp = (caddr_t)SCARG(uap, buf); for (count = 0, mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = nmp) { nmp = mp->mnt_list.cqe_next; if (sfsp && count < maxcount && ((mp->mnt_flag & MNT_MLOCK) == 0)) { sp = &mp->mnt_stat; /* * If MNT_NOWAIT is specified, do not refresh the * fsstat cache. MNT_WAIT overrides MNT_NOWAIT. */ if (((SCARG(uap, flags) & MNT_NOWAIT) == 0 || (SCARG(uap, flags) & MNT_WAIT)) && (error = VFS_STATFS(mp, sp, p))) continue; sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; error = copyout((caddr_t)sp, sfsp, sizeof(*sp)); if (error) return (error); sfsp += sizeof(*sp); } count++; } if (sfsp && count > maxcount) *retval = maxcount; else *retval = count; return (0);}/* * Change current working directory to a given file descriptor. *//* ARGSUSED */intsys_fchdir(p, v, retval) struct proc *p; void *v; register_t *retval;{ struct sys_fchdir_args /* { syscallarg(int) fd; } */ *uap = v; register struct filedesc *fdp = p->p_fd; struct vnode *vp, *tdp; struct mount *mp; struct file *fp; int error; if ((error = getvnode(fdp, SCARG(uap, fd), &fp)) != 0) return (error); vp = (struct vnode *)fp->f_data; VREF(vp); VOP_LOCK(vp); if (vp->v_type != VDIR) error = ENOTDIR; else error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p); while (!error && (mp = vp->v_mountedhere) != NULL) { if (mp->mnt_flag & MNT_MLOCK) { mp->mnt_flag |= MNT_MWAIT; sleep((caddr_t)mp, PVFS); continue; } if ((error = VFS_ROOT(mp, &tdp)) != 0) break; vput(vp); vp = tdp; } VOP_UNLOCK(vp); if (error) { vrele(vp); return (error); } vrele(fdp->fd_cdir); fdp->fd_cdir = vp; return (0);}/* * Change current working directory (``.''). *//* ARGSUSED */intsys_chdir(p, v, retval) struct proc *p; void *v; register_t *retval;{ struct sys_chdir_args /* { syscallarg(char *) path; } */ *uap = v; register struct filedesc *fdp = p->p_fd; int error; struct nameidata nd; NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, SCARG(uap, path), p); if ((error = change_dir(&nd, p)) != 0) return (error); vrele(fdp->fd_cdir); fdp->fd_cdir = nd.ni_vp; return (0);}/* * Change notion of root (``/'') directory. *//* ARGSUSED */intsys_chroot(p, v, retval) struct proc *p; void *v; register_t *retval;{ struct sys_chroot_args /* { syscallarg(char *) path; } */ *uap = v; register struct filedesc *fdp = p->p_fd; int error; struct nameidata nd; if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) return (error); NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, SCARG(uap, path), p); if ((error = change_dir(&nd, p)) != 0) return (error); if (fdp->fd_rdir != NULL) vrele(fdp->fd_rdir); fdp->fd_rdir = nd.ni_vp; return (0);}/* * Common routine for chroot and chdir. */static intchange_dir(ndp, p) register struct nameidata *ndp; struct proc *p;{ struct vnode *vp; int error; if ((error = namei(ndp)) != 0) return (error); vp = ndp->ni_vp; if (vp->v_type != VDIR) error = ENOTDIR; else error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p); VOP_UNLOCK(vp); if (error) vrele(vp); return (error);}/* * Check permissions, allocate an open file structure, * and call the device open routine if any. */intsys_open(p, v, retval) struct proc *p; void *v; register_t *retval;{ register struct sys_open_args /* { syscallarg(char *) path; syscallarg(int) flags; syscallarg(int) mode; } */ *uap = v; register struct filedesc *fdp = p->p_fd; register struct file *fp; register struct vnode *vp; int flags, cmode; struct file *nfp; int type, indx, error; struct flock lf; struct nameidata nd; extern struct fileops vnops; if ((error = falloc(p, &nfp, &indx)) != 0) return (error); fp = nfp; flags = FFLAGS(SCARG(uap, flags)); cmode = ((SCARG(uap, mode) &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT; NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); p->p_dupfd = -indx - 1; /* XXX check for fdopen */ if ((error = vn_open(&nd, flags, cmode)) != 0) { ffree(fp); if ((error == ENODEV || error == ENXIO) && p->p_dupfd >= 0 && /* XXX from fdopen */ (error = dupfdopen(fdp, indx, p->p_dupfd, flags, error)) == 0) { *retval = indx; return (0); } if (error == ERESTART) error = EINTR; fdp->fd_ofiles[indx] = NULL; return (error); } p->p_dupfd = 0; vp = nd.ni_vp; fp->f_flag = flags & FMASK; fp->f_type = DTYPE_VNODE; fp->f_ops = &vnops; fp->f_data = (caddr_t)vp; if (flags & (O_EXLOCK | O_SHLOCK)) { lf.l_whence = SEEK_SET; lf.l_start = 0; lf.l_len = 0; if (flags & O_EXLOCK) lf.l_type = F_WRLCK; else lf.l_type = F_RDLCK; type = F_FLOCK; if ((flags & FNONBLOCK) == 0) type |= F_WAIT; VOP_UNLOCK(vp); error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type); if (error) { (void) vn_close(vp, fp->f_flag, fp->f_cred, p); ffree(fp); fdp->fd_ofiles[indx] = NULL; return (error); } VOP_LOCK(vp); fp->f_flag |= FHASLOCK; } VOP_UNLOCK(vp); *retval = indx; return (0);}/* * Create a special file. *//* ARGSUSED */intsys_mknod(p, v, retval) struct proc *p; void *v; register_t *retval;{ register struct sys_mknod_args /* { syscallarg(char *) path; syscallarg(int) mode; syscallarg(int) dev; } */ *uap = v; register struct vnode *vp; struct vattr vattr; int error; int whiteout = 0; struct nameidata nd; if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) return (error); NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p); if ((error = namei(&nd)) != 0) return (error); vp = nd.ni_vp; if (vp != NULL) error = EEXIST; else { VATTR_NULL(&vattr); vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask; vattr.va_rdev = SCARG(uap, dev); whiteout = 0; switch (SCARG(uap, mode) & S_IFMT) { case S_IFMT: /* used by badsect to flag bad sectors */ vattr.va_type = VBAD; break; case S_IFCHR: vattr.va_type = VCHR; break; case S_IFBLK: vattr.va_type = VBLK; break; case S_IFWHT: whiteout = 1; break; default: error = EINVAL; break; } } if (!error) { VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); if (whiteout) { error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, CREATE); if (error) VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); vput(nd.ni_dvp); } else { error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); } } else { VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); if (nd.ni_dvp == vp) vrele(nd.ni_dvp); else vput(nd.ni_dvp); if (vp) vrele(vp); } return (error);}/* * Create a named pipe. *//* ARGSUSED */intsys_mkfifo(p, v, retval) struct proc *p; void *v; register_t *retval;{#ifndef FIFO return (EOPNOTSUPP);#else register struct sys_mkfifo_args /* { syscallarg(char *) path; syscallarg(int) mode; } */ *uap = v; struct vattr vattr; int error; struct nameidata nd; NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p); if ((error = namei(&nd)) != 0) return (error); if (nd.ni_vp != NULL) { VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); if (nd.ni_dvp == nd.ni_vp) vrele(nd.ni_dvp); else vput(nd.ni_dvp); vrele(nd.ni_vp); return (EEXIST); } VATTR_NULL(&vattr); vattr.va_type = VFIFO; vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask; VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); return (VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr));#endif /* FIFO */}/* * Make a hard file link. *//* ARGSUSED */intsys_link(p, v, retval) struct proc *p; void *v; register_t *retval;{ register struct sys_link_args /* { syscallarg(char *) path; syscallarg(char *) link; } */ *uap = v; register struct vnode *vp; struct nameidata nd; int error; NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); if ((error = namei(&nd)) != 0) return (error); vp = nd.ni_vp; NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, link), p); if ((error = namei(&nd)) != 0) goto out; if (nd.ni_vp) { VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); if (nd.ni_dvp == nd.ni_vp) vrele(nd.ni_dvp); else vput(nd.ni_dvp); vrele(nd.ni_vp); error = EEXIST; goto out; } VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);out: vrele(vp); return (error);}/* * Make a symbolic link. *//* ARGSUSED */intsys_symlink(p, v, retval) struct proc *p; void *v; register_t *retval;{ register struct sys_symlink_args /* { syscallarg(char *) path; syscallarg(char *) link; } */ *uap = v; struct vattr vattr; char *path; int error; struct nameidata nd; MALLOC(path, char *, MAXPATHLEN, M_NAMEI, M_WAITOK); error = copyinstr(SCARG(uap, path), path, MAXPATHLEN, NULL); if (error) goto out; NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, link), p); if ((error = namei(&nd)) != 0) goto out; if (nd.ni_vp) { VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); if (nd.ni_dvp == nd.ni_vp) vrele(nd.ni_dvp); else vput(nd.ni_dvp); vrele(nd.ni_vp); error = EEXIST; goto out; } VATTR_NULL(&vattr); vattr.va_mode = ACCESSPERMS &~ p->p_fd->fd_cmask; VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path);out: FREE(path, M_NAMEI); return (error);}/* * Delete a whiteout from the filesystem. *//* ARGSUSED */intsys_undelete(p, v, retval) struct proc *p; void *v; register_t *retval;{ register struct sys_undelete_args /* { syscallarg(char *) path; } */ *uap = v; int error; struct nameidata nd; NDINIT(&nd, DELETE, LOCKPARENT|DOWHITEOUT, UIO_USERSPACE, SCARG(uap, path), p); error = namei(&nd); if (error) return (error); if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) { VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); if (nd.ni_dvp == nd.ni_vp) vrele(nd.ni_dvp); else vput(nd.ni_dvp); if (nd.ni_vp) vrele(nd.ni_vp); return (EEXIST); } VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); if ((error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE)) != 0) VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); vput(nd.ni_dvp); return (error);}/* * Delete a name from the filesystem. *//* ARGSUSED */int
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?