vfs_syscalls.c
来自「基于组件方式开发操作系统的OSKIT源代码」· C语言 代码 · 共 2,115 行 · 第 1/4 页
C
2,115 行
sys_unlink(p, v, retval) struct proc *p; void *v; register_t *retval;{ struct sys_unlink_args /* { syscallarg(char *) path; } */ *uap = v; register struct vnode *vp; int error; struct nameidata nd; NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE, SCARG(uap, path), p); if ((error = namei(&nd)) != 0) return (error); vp = nd.ni_vp; /* * The root of a mounted filesystem cannot be deleted. */ if (vp->v_flag & VROOT) { VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); if (nd.ni_dvp == vp) vrele(nd.ni_dvp); else vput(nd.ni_dvp); vput(vp); error = EBUSY; goto out; } (void)vnode_pager_uncache(vp); VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);out: return (error);}/* * Reposition read/write file offset. */intsys_lseek(p, v, retval) struct proc *p; void *v; register_t *retval;{ register struct sys_lseek_args /* { syscallarg(int) fd; syscallarg(int) pad; syscallarg(off_t) offset; syscallarg(int) whence; } */ *uap = v; struct ucred *cred = p->p_ucred; register struct filedesc *fdp = p->p_fd; register struct file *fp; struct vattr vattr; int error; if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL) return (EBADF); if (fp->f_type != DTYPE_VNODE) return (ESPIPE); switch (SCARG(uap, whence)) { case L_INCR: fp->f_offset += SCARG(uap, offset); break; case L_XTND: error = VOP_GETATTR((struct vnode *)fp->f_data, &vattr, cred, p); if (error) return (error); fp->f_offset = SCARG(uap, offset) + vattr.va_size; break; case L_SET: fp->f_offset = SCARG(uap, offset); break; default: return (EINVAL); } *(off_t *)retval = fp->f_offset; return (0);}/* * Check access permissions. */intsys_access(p, v, retval) struct proc *p; void *v; register_t *retval;{ register struct sys_access_args /* { syscallarg(char *) path; syscallarg(int) flags; } */ *uap = v; register struct ucred *cred = p->p_ucred; register struct vnode *vp; int error, flags, t_gid, t_uid; struct nameidata nd; t_uid = cred->cr_uid; t_gid = cred->cr_gid; cred->cr_uid = p->p_cred->p_ruid; cred->cr_gid = p->p_cred->p_rgid; NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, SCARG(uap, path), p); if ((error = namei(&nd)) != 0) goto out1; vp = nd.ni_vp; /* Flags == 0 means only check for existence. */ if (SCARG(uap, flags)) { flags = 0; if (SCARG(uap, flags) & R_OK) flags |= VREAD; if (SCARG(uap, flags) & W_OK) flags |= VWRITE; if (SCARG(uap, flags) & X_OK) flags |= VEXEC; if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0) error = VOP_ACCESS(vp, flags, cred, p); } vput(vp);out1: cred->cr_uid = t_uid; cred->cr_gid = t_gid; return (error);}/* * Get file status; this version follows links. *//* ARGSUSED */intsys_stat(p, v, retval) struct proc *p; void *v; register_t *retval;{ register struct sys_stat_args /* { syscallarg(char *) path; syscallarg(struct stat *) ub; } */ *uap = v; struct stat sb; int error; struct nameidata nd; NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, SCARG(uap, path), p); if ((error = namei(&nd)) != 0) return (error); error = vn_stat(nd.ni_vp, &sb, p); vput(nd.ni_vp); if (error) return (error); error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb)); return (error);}/* * Get file status; this version does not follow links. *//* ARGSUSED */intsys_lstat(p, v, retval) struct proc *p; void *v; register_t *retval;{ register struct sys_lstat_args /* { syscallarg(char *) path; syscallarg(struct stat *) ub; } */ *uap = v; struct stat sb; int error; struct nameidata nd; NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, SCARG(uap, path), p); if ((error = namei(&nd)) != 0) return (error); error = vn_stat(nd.ni_vp, &sb, p); vput(nd.ni_vp); if (error) return (error); error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb)); return (error);}/* * Get configurable pathname variables. *//* ARGSUSED */intsys_pathconf(p, v, retval) struct proc *p; void *v; register_t *retval;{ register struct sys_pathconf_args /* { syscallarg(char *) path; syscallarg(int) name; } */ *uap = v; int error; struct nameidata nd; NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, SCARG(uap, path), p); if ((error = namei(&nd)) != 0) return (error); error = VOP_PATHCONF(nd.ni_vp, SCARG(uap, name), retval); vput(nd.ni_vp); return (error);}/* * Return target name of a symbolic link. *//* ARGSUSED */intsys_readlink(p, v, retval) struct proc *p; void *v; register_t *retval;{ register struct sys_readlink_args /* { syscallarg(char *) path; syscallarg(char *) buf; syscallarg(int) count; } */ *uap = v; register struct vnode *vp; struct iovec aiov; struct uio auio; int error; struct nameidata nd; NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, SCARG(uap, path), p); if ((error = namei(&nd)) != 0) return (error); vp = nd.ni_vp; if (vp->v_type != VLNK) error = EINVAL; else { aiov.iov_base = SCARG(uap, buf); aiov.iov_len = SCARG(uap, count); auio.uio_iov = &aiov; auio.uio_iovcnt = 1; auio.uio_offset = 0; auio.uio_rw = UIO_READ; auio.uio_segflg = UIO_USERSPACE; auio.uio_procp = p; auio.uio_resid = SCARG(uap, count); error = VOP_READLINK(vp, &auio, p->p_ucred); } vput(vp); *retval = SCARG(uap, count) - auio.uio_resid; return (error);}/* * Change flags of a file given a path name. *//* ARGSUSED */intsys_chflags(p, v, retval) struct proc *p; void *v; register_t *retval;{ register struct sys_chflags_args /* { syscallarg(char *) path; syscallarg(int) flags; } */ *uap = v; register struct vnode *vp; struct vattr vattr; int error; struct nameidata nd; NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); if ((error = namei(&nd)) != 0) return (error); vp = nd.ni_vp; VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); VOP_LOCK(vp); if (vp->v_mount->mnt_flag & MNT_RDONLY) error = EROFS; else { VATTR_NULL(&vattr); vattr.va_flags = SCARG(uap, flags); error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); } vput(vp); return (error);}/* * Change flags of a file given a file descriptor. *//* ARGSUSED */intsys_fchflags(p, v, retval) struct proc *p; void *v; register_t *retval;{ register struct sys_fchflags_args /* { syscallarg(int) fd; syscallarg(int) flags; } */ *uap = v; struct vattr vattr; struct vnode *vp; struct file *fp; int error; if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) return (error); vp = (struct vnode *)fp->f_data; VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); VOP_LOCK(vp); if (vp->v_mount->mnt_flag & MNT_RDONLY) error = EROFS; else { VATTR_NULL(&vattr); vattr.va_flags = SCARG(uap, flags); error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); } VOP_UNLOCK(vp); return (error);}/* * Change mode of a file given path name. *//* ARGSUSED */intsys_chmod(p, v, retval) struct proc *p; void *v; register_t *retval;{ register struct sys_chmod_args /* { syscallarg(char *) path; syscallarg(int) mode; } */ *uap = v; register struct vnode *vp; struct vattr vattr; int error; struct nameidata nd; NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); if ((error = namei(&nd)) != 0) return (error); vp = nd.ni_vp; VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); VOP_LOCK(vp); if (vp->v_mount->mnt_flag & MNT_RDONLY) error = EROFS; else { VATTR_NULL(&vattr); vattr.va_mode = SCARG(uap, mode) & ALLPERMS; error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); } vput(vp); return (error);}/* * Change mode of a file given a file descriptor. *//* ARGSUSED */intsys_fchmod(p, v, retval) struct proc *p; void *v; register_t *retval;{ register struct sys_fchmod_args /* { syscallarg(int) fd; syscallarg(int) mode; } */ *uap = v; struct vattr vattr; struct vnode *vp; struct file *fp; int error; if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) return (error); vp = (struct vnode *)fp->f_data; VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); VOP_LOCK(vp); if (vp->v_mount->mnt_flag & MNT_RDONLY) error = EROFS; else { VATTR_NULL(&vattr); vattr.va_mode = SCARG(uap, mode) & ALLPERMS; error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); } VOP_UNLOCK(vp); return (error);}/* * Set ownership given a path name. *//* ARGSUSED */intsys_chown(p, v, retval) struct proc *p; void *v; register_t *retval;{ register struct sys_chown_args /* { syscallarg(char *) path; syscallarg(int) uid; syscallarg(int) gid; } */ *uap = v; register struct vnode *vp; struct vattr vattr; int error; struct nameidata nd; NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); if ((error = namei(&nd)) != 0) return (error); vp = nd.ni_vp; VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); VOP_LOCK(vp); if (vp->v_mount->mnt_flag & MNT_RDONLY) error = EROFS; else { VATTR_NULL(&vattr); vattr.va_uid = SCARG(uap, uid); vattr.va_gid = SCARG(uap, gid); error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); } vput(vp); return (error);}/* * Set ownership given a file descriptor. *//* ARGSUSED */intsys_fchown(p, v, retval) struct proc *p; void *v; register_t *retval;{ register struct sys_fchown_args /* { syscallarg(int) fd; syscallarg(int) uid; syscallarg(int) gid; } */ *uap = v; register struct vnode *vp; struct vattr vattr; int error; struct file *fp; if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) return (error); vp = (struct vnode *)fp->f_data; VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); VOP_LOCK(vp); if (vp->v_mount->mnt_flag & MNT_RDONLY) error = EROFS; else { VATTR_NULL(&vattr); vattr.va_uid = SCARG(uap, uid); vattr.va_gid = SCARG(uap, gid); error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); } VOP_UNLOCK(vp); return (error);}/* * Set the access and modification times given a path name. *//* ARGSUSED */intsys_utimes(p, v, retval) struct proc *p; void *v; register_t *retval;{ register struct sys_utimes_args /* { syscallarg(char *) path; syscallarg(struct timeval *) tptr; } */ *uap = v; register struct vnode *vp; struct timeval tv[2]; struct vattr vattr; int error; struct nameidata nd; VATTR_NULL(&vattr); if (SCARG(uap, tptr) == NULL) { microtime(&tv[0]); tv[1] = tv[0]; vattr.va_vaflags |= VA_UTIMES_NULL; } else { error = copyin((caddr_t)SCARG(uap, tptr), (caddr_t)tv, sizeof (tv)); if (error) return (error); } NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); if ((error = namei(&nd)) != 0) return (error); vp = nd.ni_vp; VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); VOP_LOCK(vp); if (vp->v_mount->mnt_flag & MNT_RDONLY) error = EROFS; else { vattr.va_atime.tv_sec = tv[0].tv_sec; vattr.va_atime.tv_nsec = tv[0].tv_usec * 1000; vattr.va_mtime.tv_sec = tv[1].tv_sec; vattr.va_mtime.tv_nsec = tv[1].tv_usec * 1000; error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?