* Copyright (c) 1989 The Regents of the University of California.
* %sccs.include.redist.c%
* @(#)vfs_syscalls.c 7.80 (Berkeley) %G%
#define CURCOUNT (curproc ? curproc->p_spare[0] : 0)
#define CHECKPOINTREF int oldrefcount = CURCOUNT;
#define CHECKREFS(F) if (oldrefcount != CURCOUNT) \
printf("REFCOUNT: %s, old=%d, new=%d\n", (F), oldrefcount, CURCOUNT);
* Virtual File System System Calls
register struct vnode
*vp
;
register struct mount
*mp
;
if (error
= suser(p
->p_ucred
, &p
->p_acflag
))
* Get vnode to be covered
NDINIT(&nd
, LOOKUP
, FOLLOW
| LOCKLEAF
, UIO_USERSPACE
, uap
->dir
, p
);
if (uap
->flags
& MNT_UPDATE
) {
if ((vp
->v_flag
& VROOT
) == 0) {
* We allow going from read-only to read-write,
* but not from read-write to read-only.
if ((mp
->mnt_flag
& MNT_RDONLY
) == 0 &&
(uap
->flags
& MNT_RDONLY
) != 0) {
return (EOPNOTSUPP
); /* Needs translation */
mp
->mnt_flag
|= MNT_UPDATE
;
if (vp
->v_usecount
!= 1) {
if (vp
->v_type
!= VDIR
) {
if ((unsigned long)uap
->type
> MOUNT_MAXTYPE
||
vfssw
[uap
->type
] == (struct vfsops
*)0) {
* Allocate and initialize the file system.
mp
= (struct mount
*)malloc((u_long
)sizeof(struct mount
),
mp
->mnt_op
= vfssw
[uap
->type
];
if (error
= vfs_lock(mp
)) {
free((caddr_t
)mp
, M_MOUNT
);
if (vp
->v_mountedhere
!= (struct mount
*)0) {
free((caddr_t
)mp
, M_MOUNT
);
mp
->mnt_vnodecovered
= vp
;
* Set the mount level flags.
if (uap
->flags
& MNT_RDONLY
)
mp
->mnt_flag
|= MNT_RDONLY
;
mp
->mnt_flag
&= ~MNT_RDONLY
;
if (uap
->flags
& MNT_NOSUID
)
mp
->mnt_flag
|= MNT_NOSUID
;
mp
->mnt_flag
&= ~MNT_NOSUID
;
if (uap
->flags
& MNT_NOEXEC
)
mp
->mnt_flag
|= MNT_NOEXEC
;
mp
->mnt_flag
&= ~MNT_NOEXEC
;
if (uap
->flags
& MNT_NODEV
)
mp
->mnt_flag
|= MNT_NODEV
;
mp
->mnt_flag
&= ~MNT_NODEV
;
if (uap
->flags
& MNT_SYNCHRONOUS
)
mp
->mnt_flag
|= MNT_SYNCHRONOUS
;
mp
->mnt_flag
&= ~MNT_SYNCHRONOUS
;
error
= VFS_MOUNT(mp
, uap
->dir
, uap
->data
, &nd
, p
);
if (mp
->mnt_flag
& MNT_UPDATE
) {
mp
->mnt_flag
&= ~MNT_UPDATE
;
* Put the new filesystem on the mount list after root.
mp
->mnt_next
= rootfs
->mnt_next
;
mp
->mnt_next
->mnt_prev
= mp
;
error
= VFS_START(mp
, 0, p
);
free((caddr_t
)mp
, M_MOUNT
);
* Note: unmount takes a path to the vnode mounted on as argument,
* not special file (as before).
register struct vnode
*vp
;
if (error
= suser(p
->p_ucred
, &p
->p_acflag
))
NDINIT(&nd
, LOOKUP
, FOLLOW
| LOCKLEAF
, UIO_USERSPACE
, uap
->pathp
, p
);
* Must be the root of the filesystem
if ((vp
->v_flag
& VROOT
) == 0) {
return (dounmount(mp
, uap
->flags
, p
));
register struct mount
*mp
;
coveredvp
= mp
->mnt_vnodecovered
;
mp
->mnt_flag
|= MNT_UNMOUNT
;
if (error
= vfs_lock(mp
))
vnode_pager_umount(mp
); /* release cached vnodes */
cache_purgevfs(mp
); /* remove cache entries for this file sys */
if ((error
= VFS_SYNC(mp
, MNT_WAIT
)) == 0 || (flags
& MNT_FORCE
))
error
= VFS_UNMOUNT(mp
, flags
, p
);
mp
->mnt_flag
&= ~MNT_UNMOUNT
;
if (mp
->mnt_mounth
!= NULL
)
panic("unmount: dangling vnode");
free((caddr_t
)mp
, M_MOUNT
);
* Sync each mounted filesystem.
register struct mount
*mp
;
* The lock check below is to avoid races with mount
if ((mp
->mnt_flag
& (MNT_MLOCK
|MNT_RDONLY
|MNT_MPBUSY
)) == 0 &&
VFS_SYNC(mp
, MNT_NOWAIT
);
* Operate on filesystem quotas.
register struct mount
*mp
;
NDINIT(&nd
, LOOKUP
, FOLLOW
, UIO_USERSPACE
, uap
->path
, p
);
return (VFS_QUOTACTL(mp
, uap
->cmd
, uap
->uid
, uap
->arg
, p
));
* Get filesystem statistics.
register struct mount
*mp
;
register struct statfs
*sp
;
NDINIT(&nd
, LOOKUP
, FOLLOW
, UIO_USERSPACE
, uap
->path
, p
);
if (error
= VFS_STATFS(mp
, sp
, p
))
sp
->f_flags
= mp
->mnt_flag
& MNT_VISFLAGMASK
;
return (copyout((caddr_t
)sp
, (caddr_t
)uap
->buf
, sizeof(*sp
)));
* Get filesystem statistics.
register struct statfs
*sp
;
if (error
= getvnode(p
->p_fd
, uap
->fd
, &fp
))
mp
= ((struct vnode
*)fp
->f_data
)->v_mount
;
if (error
= VFS_STATFS(mp
, sp
, p
))
sp
->f_flags
= mp
->mnt_flag
& MNT_VISFLAGMASK
;
return (copyout((caddr_t
)sp
, (caddr_t
)uap
->buf
, sizeof(*sp
)));
* Get statistics on all filesystems.
getfsstat(p
, uap
, retval
)
register struct mount
*mp
;
register struct statfs
*sp
;
long count
, maxcount
, error
;
maxcount
= uap
->bufsize
/ sizeof(struct statfs
);
sfsp
= (caddr_t
)uap
->buf
;
if (sfsp
&& count
< maxcount
&&
((mp
->mnt_flag
& MNT_MLOCK
) == 0)) {
* If MNT_NOWAIT is specified, do not refresh the
* fsstat cache. MNT_WAIT overrides MNT_NOWAIT.
if (((uap
->flags
& MNT_NOWAIT
) == 0 ||
(uap
->flags
& MNT_WAIT
)) &&
(error
= VFS_STATFS(mp
, sp
, p
))) {
sp
->f_flags
= mp
->mnt_flag
& MNT_VISFLAGMASK
;
if (error
= copyout((caddr_t
)sp
, sfsp
, sizeof(*sp
)))
if (sfsp
&& count
> maxcount
)
* Change current working directory to a given file descriptor.
register struct filedesc
*fdp
= p
->p_fd
;
register struct vnode
*vp
;
if (error
= getvnode(fdp
, uap
->fd
, &fp
))
vp
= (struct vnode
*)fp
->f_data
;
error
= VOP_ACCESS(vp
, VEXEC
, p
->p_ucred
, p
);
* Change current working directory (``.'').
register struct filedesc
*fdp
= p
->p_fd
;
NDINIT(&nd
, LOOKUP
, FOLLOW
| LOCKLEAF
, UIO_USERSPACE
, uap
->fname
, p
);
if (error
= chdirec(&nd
, p
))
* Change notion of root (``/'') directory.
register struct filedesc
*fdp
= p
->p_fd
;
if (error
= suser(p
->p_ucred
, &p
->p_acflag
))
NDINIT(&nd
, LOOKUP
, FOLLOW
| LOCKLEAF
, UIO_USERSPACE
, uap
->fname
, p
);
if (error
= chdirec(&nd
, p
))
if (fdp
->fd_rdir
!= NULL
)
* Common routine for chroot and chdir.
register struct nameidata
*ndp
;
error
= VOP_ACCESS(vp
, VEXEC
, p
->p_ucred
, p
);
* Check permissions, allocate an open file structure,
* and call the device open routine if any.
register struct filedesc
*fdp
= p
->p_fd
;
register struct file
*fp
;
register struct vnode
*vp
;
extern struct fileops vnops
;
if (error
= falloc(p
, &nfp
, &indx
))
fmode
= FFLAGS(uap
->mode
);
cmode
= ((uap
->crtmode
&~ fdp
->fd_cmask
) & 07777) &~ S_ISVTX
;
NDINIT(&nd
, LOOKUP
, FOLLOW
, UIO_USERSPACE
, uap
->fname
, p
);
p
->p_dupfd
= -indx
- 1; /* XXX check for fdopen */
if (error
= vn_open(&nd
, fmode
, cmode
)) {
if (error
== ENODEV
&& /* XXX from fdopen */
(error
= dupfdopen(fdp
, indx
, p
->p_dupfd
, fmode
)) == 0) {
fdp
->fd_ofiles
[indx
] = NULL
;
fp
->f_flag
= fmode
& FMASK
;
if (fmode
& (O_EXLOCK
| O_SHLOCK
)) {
if ((fmode
& FNONBLOCK
) == 0)
if (error
= VOP_ADVLOCK(vp
, (caddr_t
)fp
, F_SETLK
, &lf
, type
)) {
(void) vn_close(vp
, fp
->f_flag
, fp
->f_cred
, p
);
fdp
->fd_ofiles
[indx
] = NULL
;
fp
->f_type
= DTYPE_VNODE
;
fp
->f_data
= (caddr_t
)vp
;
openuap
.fname
= uap
->fname
;
openuap
.crtmode
= uap
->fmode
;
openuap
.mode
= O_WRONLY
| O_CREAT
| O_TRUNC
;
return (open(p
, &openuap
, retval
));
register struct vnode
*vp
;
if (error
= suser(p
->p_ucred
, &p
->p_acflag
))
NDINIT(&nd
, CREATE
, LOCKPARENT
, UIO_USERSPACE
, uap
->fname
, p
);
switch (uap
->fmode
& S_IFMT
) {
case S_IFMT
: /* used by badsect to flag bad sectors */
vattr
.va_mode
= (uap
->fmode
& 07777) &~ p
->p_fd
->fd_cmask
;
vattr
.va_rdev
= uap
->dev
;
LEASE_CHECK(nd
.ni_dvp
, p
, p
->p_ucred
, LEASE_WRITE
);
error
= VOP_MKNOD(nd
.ni_dvp
, &nd
.ni_vp
, &nd
.ni_cnd
, &vattr
);
VOP_ABORTOP(nd
.ni_dvp
, &nd
.ni_cnd
);
NDINIT(&nd
, CREATE
, LOCKPARENT
, UIO_USERSPACE
, uap
->fname
, p
);
VOP_ABORTOP(nd
.ni_dvp
, &nd
.ni_cnd
);
if (nd
.ni_dvp
== nd
.ni_vp
)
vattr
.va_mode
= (uap
->fmode
& 07777) &~ p
->p_fd
->fd_cmask
;
LEASE_CHECK(nd
.ni_dvp
, p
, p
->p_ucred
, LEASE_WRITE
);
return (VOP_MKNOD(nd
.ni_dvp
, &nd
.ni_vp
, &nd
.ni_cnd
, &vattr
));
register struct vnode
*vp
, *xp
;
NDINIT(&nd
, LOOKUP
, FOLLOW
, UIO_USERSPACE
, uap
->target
, p
);
if (vp
->v_type
== VDIR
&&
(error
= suser(p
->p_ucred
, &p
->p_acflag
)))
nd
.ni_cnd
.cn_nameiop
= CREATE
;
nd
.ni_cnd
.cn_flags
= LOCKPARENT
;
nd
.ni_dirp
= (caddr_t
)uap
->linkname
;
if (vp
->v_mount
!= xp
->v_mount
)
LEASE_CHECK(xp
, p
, p
->p_ucred
, LEASE_WRITE
);
LEASE_CHECK(vp
, p
, p
->p_ucred
, LEASE_WRITE
);
error
= VOP_LINK(nd
.ni_dvp
, vp
, &nd
.ni_cnd
);
VOP_ABORTOP(nd
.ni_dvp
, &nd
.ni_cnd
);
if (nd
.ni_dvp
== nd
.ni_vp
)
MALLOC(target
, char *, MAXPATHLEN
, M_NAMEI
, M_WAITOK
);
if (error
= copyinstr(uap
->target
, target
, MAXPATHLEN
, (u_int
*)0))
NDINIT(&nd
, CREATE
, LOCKPARENT
, UIO_USERSPACE
, uap
->linkname
, p
);
VOP_ABORTOP(nd
.ni_dvp
, &nd
.ni_cnd
);
if (nd
.ni_dvp
== nd
.ni_vp
)
vattr
.va_mode
= 0777 &~ p
->p_fd
->fd_cmask
;
LEASE_CHECK(nd
.ni_dvp
, p
, p
->p_ucred
, LEASE_WRITE
);
error
= VOP_SYMLINK(nd
.ni_dvp
, &nd
.ni_vp
, &nd
.ni_cnd
, &vattr
, target
);
* Delete a name from the filesystem.
register struct vnode
*vp
;
NDINIT(&nd
, DELETE
, LOCKPARENT
| LOCKLEAF
, UIO_USERSPACE
, uap
->name
, p
);
if (vp
->v_type
== VDIR
&&
(error
= suser(p
->p_ucred
, &p
->p_acflag
)))
* The root of a mounted filesystem cannot be deleted.
if (vp
->v_flag
& VROOT
) {
(void) vnode_pager_uncache(vp
);
LEASE_CHECK(nd
.ni_dvp
, p
, p
->p_ucred
, LEASE_WRITE
);
LEASE_CHECK(vp
, p
, p
->p_ucred
, LEASE_WRITE
);
error
= VOP_REMOVE(nd
.ni_dvp
, nd
.ni_vp
, &nd
.ni_cnd
);
VOP_ABORTOP(nd
.ni_dvp
, &nd
.ni_cnd
);
struct ucred
*cred
= p
->p_ucred
;
register struct filedesc
*fdp
= p
->p_fd
;
register struct file
*fp
;
if ((unsigned)uap
->fdes
>= fdp
->fd_nfiles
||
(fp
= fdp
->fd_ofiles
[uap
->fdes
]) == NULL
)
if (fp
->f_type
!= DTYPE_VNODE
)
fp
->f_offset
+= uap
->off
;
if (error
= VOP_GETATTR((struct vnode
*)fp
->f_data
,
fp
->f_offset
= uap
->off
+ vattr
.va_size
;
* Check access permissions.
register struct ucred
*cred
= p
->p_ucred
;
register struct vnode
*vp
;
int error
, mode
, svuid
, svgid
;
svgid
= cred
->cr_groups
[0];
cred
->cr_uid
= p
->p_cred
->p_ruid
;
cred
->cr_groups
[0] = p
->p_cred
->p_rgid
;
NDINIT(&nd
, LOOKUP
, FOLLOW
| LOCKLEAF
, UIO_USERSPACE
, uap
->fname
, p
);
* fmode == 0 means only check for exist
if ((mode
& VWRITE
) == 0 || (error
= vn_writechk(vp
)) == 0)
error
= VOP_ACCESS(vp
, mode
, cred
, p
);
cred
->cr_groups
[0] = svgid
;
* This version follows links.
NDINIT(&nd
, LOOKUP
, FOLLOW
| LOCKLEAF
, UIO_USERSPACE
, uap
->fname
, p
);
error
= vn_stat(nd
.ni_vp
, &sb
, p
);
error
= copyout((caddr_t
)&sb
, (caddr_t
)uap
->ub
, sizeof (sb
));
* This version does not follow links.
NDINIT(&nd
, LOOKUP
, NOFOLLOW
| LOCKLEAF
, UIO_USERSPACE
, uap
->fname
, p
);
error
= vn_stat(nd
.ni_vp
, &sb
, p
);
error
= copyout((caddr_t
)&sb
, (caddr_t
)uap
->ub
, sizeof (sb
));
* Return target name of a symbolic link.
register struct vnode
*vp
;
NDINIT(&nd
, LOOKUP
, NOFOLLOW
| LOCKLEAF
, UIO_USERSPACE
, uap
->name
, p
);
if (vp
->v_type
!= VLNK
) {
aiov
.iov_base
= uap
->buf
;
aiov
.iov_len
= uap
->count
;
auio
.uio_segflg
= UIO_USERSPACE
;
auio
.uio_resid
= uap
->count
;
error
= VOP_READLINK(vp
, &auio
, p
->p_ucred
);
*retval
= uap
->count
- auio
.uio_resid
;
* Change flags of a file given path name.
register struct vnode
*vp
;
NDINIT(&nd
, LOOKUP
, FOLLOW
| LOCKLEAF
, UIO_USERSPACE
, uap
->fname
, p
);
if (vp
->v_mount
->mnt_flag
& MNT_RDONLY
) {
vattr
.va_flags
= uap
->flags
;
LEASE_CHECK(vp
, p
, p
->p_ucred
, LEASE_WRITE
);
error
= VOP_SETATTR(vp
, &vattr
, p
->p_ucred
, p
);
* Change flags of a file given a file descriptor.
if (error
= getvnode(p
->p_fd
, uap
->fd
, &fp
))
vp
= (struct vnode
*)fp
->f_data
;
if (vp
->v_mount
->mnt_flag
& MNT_RDONLY
) {
vattr
.va_flags
= uap
->flags
;
LEASE_CHECK(vp
, p
, p
->p_ucred
, LEASE_WRITE
);
error
= VOP_SETATTR(vp
, &vattr
, p
->p_ucred
, p
);
* Change mode of a file given path name.
register struct vnode
*vp
;
NDINIT(&nd
, LOOKUP
, FOLLOW
| LOCKLEAF
, UIO_USERSPACE
, uap
->fname
, p
);
if (vp
->v_mount
->mnt_flag
& MNT_RDONLY
) {
vattr
.va_mode
= uap
->fmode
& 07777;
LEASE_CHECK(vp
, p
, p
->p_ucred
, LEASE_WRITE
);
error
= VOP_SETATTR(vp
, &vattr
, p
->p_ucred
, p
);
* Change mode of a file given a file descriptor.
if (error
= getvnode(p
->p_fd
, uap
->fd
, &fp
))
vp
= (struct vnode
*)fp
->f_data
;
if (vp
->v_mount
->mnt_flag
& MNT_RDONLY
) {
vattr
.va_mode
= uap
->fmode
& 07777;
LEASE_CHECK(vp
, p
, p
->p_ucred
, LEASE_WRITE
);
error
= VOP_SETATTR(vp
, &vattr
, p
->p_ucred
, p
);
* Set ownership given a path name.
register struct vnode
*vp
;
NDINIT(&nd
, LOOKUP
, NOFOLLOW
| LOCKLEAF
, UIO_USERSPACE
, uap
->fname
, p
);
if (vp
->v_mount
->mnt_flag
& MNT_RDONLY
) {
LEASE_CHECK(vp
, p
, p
->p_ucred
, LEASE_WRITE
);
error
= VOP_SETATTR(vp
, &vattr
, p
->p_ucred
, p
);
* Set ownership given a file descriptor.
if (error
= getvnode(p
->p_fd
, uap
->fd
, &fp
))
vp
= (struct vnode
*)fp
->f_data
;
if (vp
->v_mount
->mnt_flag
& MNT_RDONLY
) {
LEASE_CHECK(vp
, p
, p
->p_ucred
, LEASE_WRITE
);
error
= VOP_SETATTR(vp
, &vattr
, p
->p_ucred
, p
);
* Set the access and modification times of a file.
register struct vnode
*vp
;
if (error
= copyin((caddr_t
)uap
->tptr
, (caddr_t
)tv
, sizeof (tv
)))
NDINIT(&nd
, LOOKUP
, FOLLOW
| LOCKLEAF
, UIO_USERSPACE
, uap
->fname
, p
);
if (vp
->v_mount
->mnt_flag
& MNT_RDONLY
) {
LEASE_CHECK(vp
, p
, p
->p_ucred
, LEASE_WRITE
);
error
= VOP_SETATTR(vp
, &vattr
, p
->p_ucred
, p
);
* Truncate a file given its path name.
register struct vnode
*vp
;
NDINIT(&nd
, LOOKUP
, FOLLOW
| LOCKLEAF
, UIO_USERSPACE
, uap
->fname
, p
);
if (vp
->v_type
== VDIR
) {
if ((error
= vn_writechk(vp
)) ||
(error
= VOP_ACCESS(vp
, VWRITE
, p
->p_ucred
, p
)))
vattr
.va_size
= uap
->length
;
LEASE_CHECK(vp
, p
, p
->p_ucred
, LEASE_WRITE
);
error
= VOP_SETATTR(vp
, &vattr
, p
->p_ucred
, p
);
* Truncate a file given a file descriptor.
ftruncate(p
, uap
, retval
)
if (error
= getvnode(p
->p_fd
, uap
->fd
, &fp
))
if ((fp
->f_flag
& FWRITE
) == 0)
vp
= (struct vnode
*)fp
->f_data
;
if (vp
->v_type
== VDIR
) {
if (error
= vn_writechk(vp
))
vattr
.va_size
= uap
->length
;
LEASE_CHECK(vp
, p
, p
->p_ucred
, LEASE_WRITE
);
error
= VOP_SETATTR(vp
, &vattr
, fp
->f_cred
, p
);
register struct vnode
*vp
;
if (error
= getvnode(p
->p_fd
, uap
->fd
, &fp
))
vp
= (struct vnode
*)fp
->f_data
;
error
= VOP_FSYNC(vp
, fp
->f_flag
, fp
->f_cred
, MNT_WAIT
, p
);
* Source and destination must either both be directories, or both
* not be directories. If target is a directory, it must be empty.
register struct vnode
*tvp
, *fvp
, *tdvp
;
struct nameidata fromnd
, tond
;
NDINIT(&fromnd
, DELETE
, WANTPARENT
| SAVESTART
, UIO_USERSPACE
,
if (error
= namei(&fromnd
))
NDINIT(&tond
, RENAME
, LOCKPARENT
| LOCKLEAF
| NOCACHE
| SAVESTART
,
UIO_USERSPACE
, uap
->to
, p
);
if (error
= namei(&tond
)) {
VOP_ABORTOP(fromnd
.ni_dvp
, &fromnd
.ni_cnd
);
if (fvp
->v_type
== VDIR
&& tvp
->v_type
!= VDIR
) {
} else if (fvp
->v_type
!= VDIR
&& tvp
->v_type
== VDIR
) {
if (fvp
->v_mount
!= tvp
->v_mount
) {
if (fvp
->v_mount
!= tdvp
->v_mount
) {
* If source is the same as the destination (that is the
* same inode number with the same name in the same directory),
* then there is nothing to do.
if (fvp
== tvp
&& fromnd
.ni_dvp
== tdvp
&&
fromnd
.ni_cnd
.cn_namelen
== tond
.ni_cnd
.cn_namelen
&&
!bcmp(fromnd
.ni_cnd
.cn_nameptr
, tond
.ni_cnd
.cn_nameptr
,
fromnd
.ni_cnd
.cn_namelen
))
LEASE_CHECK(tdvp
, p
, p
->p_ucred
, LEASE_WRITE
);
if (fromnd
.ni_dvp
!= tdvp
)
LEASE_CHECK(fromnd
.ni_dvp
, p
, p
->p_ucred
, LEASE_WRITE
);
LEASE_CHECK(tvp
, p
, p
->p_ucred
, LEASE_WRITE
);
error
= VOP_RENAME(fromnd
.ni_dvp
, fromnd
.ni_vp
, &fromnd
.ni_cnd
,
tond
.ni_dvp
, tond
.ni_vp
, &tond
.ni_cnd
);
VOP_ABORTOP(tond
.ni_dvp
, &tond
.ni_cnd
);
VOP_ABORTOP(fromnd
.ni_dvp
, &fromnd
.ni_cnd
);
FREE(tond
.ni_cnd
.cn_pnbuf
, M_NAMEI
);
vrele(fromnd
.ni_startdir
);
FREE(fromnd
.ni_cnd
.cn_pnbuf
, M_NAMEI
);
register struct vnode
*vp
;
NDINIT(&nd
, CREATE
, LOCKPARENT
, UIO_USERSPACE
, uap
->name
, p
);
VOP_ABORTOP(nd
.ni_dvp
, &nd
.ni_cnd
);
vattr
.va_mode
= (uap
->dmode
& 0777) &~ p
->p_fd
->fd_cmask
;
LEASE_CHECK(nd
.ni_dvp
, p
, p
->p_ucred
, LEASE_WRITE
);
error
= VOP_MKDIR(nd
.ni_dvp
, &nd
.ni_vp
, &nd
.ni_cnd
, &vattr
);
register struct vnode
*vp
;
NDINIT(&nd
, DELETE
, LOCKPARENT
| LOCKLEAF
, UIO_USERSPACE
, uap
->name
, p
);
if (vp
->v_type
!= VDIR
) {
* The root of a mounted filesystem cannot be deleted.
LEASE_CHECK(nd
.ni_dvp
, p
, p
->p_ucred
, LEASE_WRITE
);
LEASE_CHECK(vp
, p
, p
->p_ucred
, LEASE_WRITE
);
error
= VOP_RMDIR(nd
.ni_dvp
, nd
.ni_vp
, &nd
.ni_cnd
);
VOP_ABORTOP(nd
.ni_dvp
, &nd
.ni_cnd
);
* Read a block of directory entries in a file system independent format.
getdirentries(p
, uap
, retval
)
register struct vnode
*vp
;
if (error
= getvnode(p
->p_fd
, uap
->fd
, &fp
))
if ((fp
->f_flag
& FREAD
) == 0)
vp
= (struct vnode
*)fp
->f_data
;
aiov
.iov_base
= uap
->buf
;
aiov
.iov_len
= uap
->count
;
auio
.uio_segflg
= UIO_USERSPACE
;
auio
.uio_resid
= uap
->count
;
auio
.uio_offset
= off
= fp
->f_offset
;
error
= VOP_READDIR(vp
, &auio
, fp
->f_cred
, &eofflag
);
fp
->f_offset
= auio
.uio_offset
;
error
= copyout((caddr_t
)&off
, (caddr_t
)uap
->basep
, sizeof(long));
*retval
= uap
->count
- auio
.uio_resid
;
* Set the mode mask for creation of filesystem nodes.
register struct filedesc
*fdp
= p
->p_fd
;
fdp
->fd_cmask
= uap
->mask
& 07777;
* Void all references to file by ripping underlying filesystem
register struct vnode
*vp
;
NDINIT(&nd
, LOOKUP
, FOLLOW
, UIO_USERSPACE
, uap
->fname
, p
);
if (vp
->v_type
!= VCHR
&& vp
->v_type
!= VBLK
) {
if (error
= VOP_GETATTR(vp
, &vattr
, p
->p_ucred
, p
))
if (p
->p_ucred
->cr_uid
!= vattr
.va_uid
&&
(error
= suser(p
->p_ucred
, &p
->p_acflag
)))
if (vp
->v_usecount
> 1 || (vp
->v_flag
& VALIASED
))
* Convert a user file descriptor to a kernel file entry.
if ((unsigned)fdes
>= fdp
->fd_nfiles
||
(fp
= fdp
->fd_ofiles
[fdes
]) == NULL
)
if (fp
->f_type
!= DTYPE_VNODE
)