* Copyright (c) 1989 The Regents of the University of California.
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by the University of California, Berkeley. The name of the
* University may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
* @(#)vfs_syscalls.c 7.44 (Berkeley) %G%
#define RETURN(val) { scp->u_error = (val); if (scp->u_spare[0] != 0) panic("lock count"); return; }
* Virtual File System System Calls
register struct syscontext
*scp
;
} *uap
= (struct a
*)scp
->sc_ap
;
register struct nameidata
*ndp
= &scp
->sc_nd
;
register struct vnode
*vp
;
register struct mount
*mp
;
if (error
= suser(scp
->sc_cred
, &scp
->sc_acflag
))
* Get vnode to be covered
ndp
->ni_nameiop
= LOOKUP
| FOLLOW
| LOCKLEAF
;
ndp
->ni_segflg
= UIO_USERSPACE
;
if (uap
->flags
& M_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
->m_flag
& M_RDONLY
) == 0 &&
(uap
->flags
& M_RDONLY
) != 0) {
RETURN (EOPNOTSUPP
); /* Needs translation */
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
->m_op
= vfssw
[uap
->type
];
mp
->m_mounth
= (struct vnode
*)0;
if (error
= vfs_lock(mp
)) {
free((caddr_t
)mp
, M_MOUNT
);
if (vp
->v_mountedhere
!= (struct mount
*)0) {
free((caddr_t
)mp
, M_MOUNT
);
* Set the mount level flags.
if (uap
->flags
& M_RDONLY
)
if (uap
->flags
& M_NOSUID
)
if (uap
->flags
& M_NOEXEC
)
if (uap
->flags
& M_NODEV
)
if (uap
->flags
& M_SYNCHRONOUS
)
mp
->m_flag
|= M_SYNCHRONOUS
;
mp
->m_flag
&= ~M_SYNCHRONOUS
;
error
= VFS_MOUNT(mp
, uap
->dir
, uap
->data
, ndp
);
if (mp
->m_flag
& M_UPDATE
) {
* Put the new filesystem on the mount list after root.
mp
->m_next
= rootfs
->m_next
;
error
= VFS_START(mp
, 0);
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 syscontext
*scp
;
} *uap
= (struct a
*)scp
->sc_ap
;
register struct vnode
*vp
;
register struct nameidata
*ndp
= &scp
->sc_nd
;
if (error
= suser(scp
->sc_cred
, &scp
->sc_acflag
))
ndp
->ni_nameiop
= LOOKUP
| LOCKLEAF
| FOLLOW
;
ndp
->ni_segflg
= UIO_USERSPACE
;
ndp
->ni_dirp
= uap
->pathp
;
* Must be the root of the filesystem
if ((vp
->v_flag
& VROOT
) == 0) {
RETURN (dounmount(mp
, uap
->flags
));
register struct mount
*mp
;
coveredvp
= mp
->m_vnodecovered
;
if (error
= vfs_lock(mp
))
xumount(mp
); /* remove unused sticky files from text table */
cache_purgevfs(mp
); /* remove cache entries for this file sys */
error
= VFS_UNMOUNT(mp
, flags
);
mp
->m_flag
&= ~M_UNMOUNT
;
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
->m_flag
& (M_MLOCK
|M_RDONLY
|M_MPBUSY
)) == 0 &&
VFS_SYNC(mp
, MNT_NOWAIT
);
* operate on filesystem quotas
register struct syscontext
*scp
;
} *uap
= (struct a
*)scp
->sc_ap
;
register struct mount
*mp
;
register struct nameidata
*ndp
= &scp
->sc_nd
;
ndp
->ni_nameiop
= LOOKUP
| FOLLOW
;
ndp
->ni_segflg
= UIO_USERSPACE
;
ndp
->ni_dirp
= uap
->path
;
mp
= ndp
->ni_vp
->v_mount
;
RETURN (VFS_QUOTACTL(mp
, uap
->cmd
, uap
->uid
, uap
->arg
));
* get filesystem statistics
register struct syscontext
*scp
;
} *uap
= (struct a
*)scp
->sc_ap
;
register struct mount
*mp
;
register struct nameidata
*ndp
= &scp
->sc_nd
;
register struct statfs
*sp
;
ndp
->ni_nameiop
= LOOKUP
| FOLLOW
;
ndp
->ni_segflg
= UIO_USERSPACE
;
ndp
->ni_dirp
= uap
->path
;
mp
= ndp
->ni_vp
->v_mount
;
if (error
= VFS_STATFS(mp
, sp
))
sp
->f_flags
= mp
->m_flag
& M_VISFLAGMASK
;
RETURN (copyout((caddr_t
)sp
, (caddr_t
)uap
->buf
, sizeof(*sp
)));
register struct syscontext
*scp
;
} *uap
= (struct a
*)scp
->sc_ap
;
register struct statfs
*sp
;
if (error
= getvnode(scp
->sc_ofile
, uap
->fd
, &fp
))
mp
= ((struct vnode
*)fp
->f_data
)->v_mount
;
if (error
= VFS_STATFS(mp
, sp
))
sp
->f_flags
= mp
->m_flag
& M_VISFLAGMASK
;
RETURN (copyout((caddr_t
)sp
, (caddr_t
)uap
->buf
, sizeof(*sp
)));
* get statistics on all filesystems
register struct syscontext
*scp
;
} *uap
= (struct a
*)scp
->sc_ap
;
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
->m_flag
& M_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
))) {
sp
->f_flags
= mp
->m_flag
& M_VISFLAGMASK
;
if (error
= copyout((caddr_t
)sp
, sfsp
, sizeof(*sp
)))
if (sfsp
&& count
> maxcount
)
scp
->sc_retval1
= maxcount
;
* Change current working directory to a given file descriptor.
register struct syscontext
*scp
;
} *uap
= (struct a
*)scp
->sc_ap
;
register struct vnode
*vp
;
if (error
= getvnode(scp
->sc_ofile
, uap
->fd
, &fp
))
vp
= (struct vnode
*)fp
->f_data
;
error
= VOP_ACCESS(vp
, VEXEC
, scp
->sc_cred
);
* Change current working directory (``.'').
register struct syscontext
*scp
;
} *uap
= (struct a
*)scp
->sc_ap
;
register struct nameidata
*ndp
= &scp
->sc_nd
;
ndp
->ni_nameiop
= LOOKUP
| FOLLOW
| LOCKLEAF
;
ndp
->ni_segflg
= UIO_USERSPACE
;
ndp
->ni_dirp
= uap
->fname
;
if (error
= chdirec(ndp
))
scp
->sc_cdir
= ndp
->ni_vp
;
* Change notion of root (``/'') directory.
register struct syscontext
*scp
;
} *uap
= (struct a
*)scp
->sc_ap
;
register struct nameidata
*ndp
= &scp
->sc_nd
;
if (error
= suser(scp
->sc_cred
, &scp
->sc_acflag
))
ndp
->ni_nameiop
= LOOKUP
| FOLLOW
| LOCKLEAF
;
ndp
->ni_segflg
= UIO_USERSPACE
;
ndp
->ni_dirp
= uap
->fname
;
if (error
= chdirec(ndp
))
if (scp
->sc_rdir
!= NULL
)
scp
->sc_rdir
= ndp
->ni_vp
;
* Common routine for chroot and chdir.
register struct nameidata
*ndp
;
error
= VOP_ACCESS(vp
, VEXEC
, ndp
->ni_cred
);
register struct syscontext
*scp
;
} *uap
= (struct a
*) scp
->sc_ap
;
struct nameidata
*ndp
= &scp
->sc_nd
;
ndp
->ni_segflg
= UIO_USERSPACE
;
ndp
->ni_dirp
= uap
->fname
;
RETURN (copen(scp
, uap
->mode
-FOPEN
, uap
->crtmode
&~ scp
->sc_cmask
, ndp
,
register struct syscontext
*scp
;
} *uap
= (struct a
*)scp
->sc_ap
;
struct nameidata
*ndp
= &scp
->sc_nd
;
ndp
->ni_segflg
= UIO_USERSPACE
;
ndp
->ni_dirp
= uap
->fname
;
RETURN (copen(scp
, FWRITE
|FCREAT
|FTRUNC
, uap
->fmode
&~ scp
->sc_cmask
,
* Common code for open and creat.
* Check permissions, allocate an open file structure,
* and call the device open routine if any.
copen(scp
, fmode
, cmode
, ndp
, resultfd
)
register struct syscontext
*scp
;
register struct file
*fp
;
extern struct fileops vnops
;
if (error
= falloc(&nfp
, &indx
))
scp
->sc_retval1
= indx
; /* XXX for fdopen() */
if (error
= vn_open(ndp
, fmode
, (cmode
& 07777) &~ S_ISVTX
)) {
if (error
== EJUSTRETURN
) /* XXX from fdopen */
return (0); /* XXX from fdopen */
scp
->sc_ofile
[indx
] = NULL
;
fp
->f_flag
= fmode
& FMASK
;
fp
->f_type
= DTYPE_VNODE
;
fp
->f_data
= (caddr_t
)ndp
->ni_vp
;
register struct syscontext
*scp
;
} *uap
= (struct a
*)scp
->sc_ap
;
register struct nameidata
*ndp
= &scp
->sc_nd
;
register struct vnode
*vp
;
if (error
= suser(scp
->sc_cred
, &scp
->sc_acflag
))
ndp
->ni_nameiop
= CREATE
| LOCKPARENT
;
ndp
->ni_segflg
= UIO_USERSPACE
;
ndp
->ni_dirp
= uap
->fname
;
switch (uap
->fmode
& S_IFMT
) {
case S_IFMT
: /* used by badsect to flag bad sectors */
vattr
.va_mode
= (uap
->fmode
& 07777) &~ scp
->sc_cmask
;
vattr
.va_rdev
= uap
->dev
;
error
= VOP_MKNOD(ndp
, &vattr
, ndp
->ni_cred
);
register struct syscontext
*scp
;
} *uap
= (struct a
*)scp
->sc_ap
;
register struct nameidata
*ndp
= &scp
->sc_nd
;
ndp
->ni_nameiop
= CREATE
| LOCKPARENT
;
ndp
->ni_segflg
= UIO_USERSPACE
;
ndp
->ni_dirp
= uap
->fname
;
if (ndp
->ni_vp
!= NULL
) {
vattr
.va_mode
= (uap
->fmode
& 07777) &~ scp
->sc_cmask
;
RETURN (VOP_MKNOD(ndp
, &vattr
, ndp
->ni_cred
));
register struct syscontext
*scp
;
} *uap
= (struct a
*)scp
->sc_ap
;
register struct nameidata
*ndp
= &scp
->sc_nd
;
register struct vnode
*vp
, *xp
;
ndp
->ni_nameiop
= LOOKUP
| FOLLOW
;
ndp
->ni_segflg
= UIO_USERSPACE
;
ndp
->ni_dirp
= uap
->target
;
if (vp
->v_type
== VDIR
&&
(error
= suser(scp
->sc_cred
, &scp
->sc_acflag
)))
ndp
->ni_nameiop
= CREATE
| LOCKPARENT
;
ndp
->ni_dirp
= (caddr_t
)uap
->linkname
;
if (vp
->v_mount
!= xp
->v_mount
)
error
= VOP_LINK(vp
, ndp
);
* symlink -- make a symbolic link
register struct syscontext
*scp
;
} *uap
= (struct a
*)scp
->sc_ap
;
register struct nameidata
*ndp
= &scp
->sc_nd
;
register struct vnode
*vp
;
ndp
->ni_segflg
= UIO_USERSPACE
;
ndp
->ni_dirp
= uap
->linkname
;
MALLOC(target
, char *, MAXPATHLEN
, M_NAMEI
, M_WAITOK
);
if (error
= copyinstr(uap
->target
, target
, MAXPATHLEN
, (u_int
*)0))
ndp
->ni_nameiop
= CREATE
| LOCKPARENT
;
vattr
.va_mode
= 0777 &~ scp
->sc_cmask
;
error
= VOP_SYMLINK(ndp
, &vattr
, target
);
* Hard to avoid races here, especially
* in unlinking directories.
register struct syscontext
*scp
;
} *uap
= (struct a
*)scp
->sc_ap
;
register struct nameidata
*ndp
= &scp
->sc_nd
;
register struct vnode
*vp
;
ndp
->ni_nameiop
= DELETE
| LOCKPARENT
| LOCKLEAF
;
ndp
->ni_segflg
= UIO_USERSPACE
;
ndp
->ni_dirp
= uap
->fname
;
if (vp
->v_type
== VDIR
&&
(error
= suser(scp
->sc_cred
, &scp
->sc_acflag
)))
* Don't unlink a mounted file.
if (vp
->v_flag
& VROOT
) {
xrele(vp
); /* try once to free text */
register struct syscontext
*scp
;
register struct file
*fp
;
} *uap
= (struct a
*)scp
->sc_ap
;
if ((unsigned)uap
->fdes
>= NOFILE
||
(fp
= scp
->sc_ofile
[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
;
scp
->sc_offset
= fp
->f_offset
;
register struct syscontext
*scp
;
} *uap
= (struct a
*)scp
->sc_ap
;
register struct nameidata
*ndp
= &scp
->sc_nd
;
register struct vnode
*vp
;
int error
, mode
, svuid
, svgid
;
scp
->sc_uid
= scp
->sc_ruid
;
scp
->sc_gid
= scp
->sc_rgid
;
ndp
->ni_nameiop
= LOOKUP
| FOLLOW
| LOCKLEAF
;
ndp
->ni_segflg
= UIO_USERSPACE
;
ndp
->ni_dirp
= uap
->fname
;
* fmode == 0 means only check for exist
if ((mode
& VWRITE
) == 0 || (error
= vn_writechk(vp
)) == 0)
error
= VOP_ACCESS(vp
, mode
, ndp
->ni_cred
);
* Stat system call. This version follows links.
* Lstat system call. This version does not follow links.
register struct syscontext
*scp
;
} *uap
= (struct a
*)scp
->sc_ap
;
register struct nameidata
*ndp
= &scp
->sc_nd
;
ndp
->ni_nameiop
= LOOKUP
| LOCKLEAF
| follow
;
ndp
->ni_segflg
= UIO_USERSPACE
;
ndp
->ni_dirp
= uap
->fname
;
error
= vn_stat(ndp
->ni_vp
, &sb
);
error
= copyout((caddr_t
)&sb
, (caddr_t
)uap
->ub
, sizeof (sb
));
* Return target name of a symbolic link
register struct syscontext
*scp
;
} *uap
= (struct a
*)scp
->sc_ap
;
register struct nameidata
*ndp
= &scp
->sc_nd
;
register struct vnode
*vp
;
ndp
->ni_nameiop
= LOOKUP
| LOCKLEAF
;
ndp
->ni_segflg
= UIO_USERSPACE
;
ndp
->ni_dirp
= uap
->name
;
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
, ndp
->ni_cred
);
scp
->sc_retval1
= uap
->count
- auio
.uio_resid
;
* Change flags of a file given path name.
register struct syscontext
*scp
;
} *uap
= (struct a
*)scp
->sc_ap
;
register struct nameidata
*ndp
= &scp
->sc_nd
;
register struct vnode
*vp
;
ndp
->ni_nameiop
= LOOKUP
| FOLLOW
| LOCKLEAF
;
ndp
->ni_segflg
= UIO_USERSPACE
;
ndp
->ni_dirp
= uap
->fname
;
vattr
.va_flags
= uap
->flags
;
if (vp
->v_mount
->m_flag
& M_RDONLY
) {
error
= VOP_SETATTR(vp
, &vattr
, ndp
->ni_cred
);
* Change flags of a file given a file descriptor.
register struct syscontext
*scp
;
} *uap
= (struct a
*)scp
->sc_ap
;
if (error
= getvnode(scp
->sc_ofile
, uap
->fd
, &fp
))
vattr
.va_flags
= uap
->flags
;
vp
= (struct vnode
*)fp
->f_data
;
if (vp
->v_mount
->m_flag
& M_RDONLY
) {
error
= VOP_SETATTR(vp
, &vattr
, fp
->f_cred
);
* Change mode of a file given path name.
register struct syscontext
*scp
;
} *uap
= (struct a
*)scp
->sc_ap
;
register struct nameidata
*ndp
= &scp
->sc_nd
;
register struct vnode
*vp
;
ndp
->ni_nameiop
= LOOKUP
| FOLLOW
| LOCKLEAF
;
ndp
->ni_segflg
= UIO_USERSPACE
;
ndp
->ni_dirp
= uap
->fname
;
vattr
.va_mode
= uap
->fmode
& 07777;
if (vp
->v_mount
->m_flag
& M_RDONLY
) {
error
= VOP_SETATTR(vp
, &vattr
, ndp
->ni_cred
);
* Change mode of a file given a file descriptor.
register struct syscontext
*scp
;
} *uap
= (struct a
*)scp
->sc_ap
;
if (error
= getvnode(scp
->sc_ofile
, uap
->fd
, &fp
))
vattr
.va_mode
= uap
->fmode
& 07777;
vp
= (struct vnode
*)fp
->f_data
;
if (vp
->v_mount
->m_flag
& M_RDONLY
) {
error
= VOP_SETATTR(vp
, &vattr
, fp
->f_cred
);
* Set ownership given a path name.
register struct syscontext
*scp
;
} *uap
= (struct a
*)scp
->sc_ap
;
register struct nameidata
*ndp
= &scp
->sc_nd
;
register struct vnode
*vp
;
ndp
->ni_nameiop
= LOOKUP
| NOFOLLOW
| LOCKLEAF
;
ndp
->ni_segflg
= UIO_USERSPACE
;
ndp
->ni_dirp
= uap
->fname
;
if (vp
->v_mount
->m_flag
& M_RDONLY
) {
error
= VOP_SETATTR(vp
, &vattr
, ndp
->ni_cred
);
* Set ownership given a file descriptor.
register struct syscontext
*scp
;
} *uap
= (struct a
*)scp
->sc_ap
;
if (error
= getvnode(scp
->sc_ofile
, uap
->fd
, &fp
))
vp
= (struct vnode
*)fp
->f_data
;
if (vp
->v_mount
->m_flag
& M_RDONLY
) {
error
= VOP_SETATTR(vp
, &vattr
, fp
->f_cred
);
register struct syscontext
*scp
;
} *uap
= (struct a
*)scp
->sc_ap
;
register struct nameidata
*ndp
= &scp
->sc_nd
;
register struct vnode
*vp
;
if (error
= copyin((caddr_t
)uap
->tptr
, (caddr_t
)tv
, sizeof (tv
)))
ndp
->ni_nameiop
= LOOKUP
| FOLLOW
| LOCKLEAF
;
ndp
->ni_segflg
= UIO_USERSPACE
;
ndp
->ni_dirp
= uap
->fname
;
if (vp
->v_mount
->m_flag
& M_RDONLY
) {
error
= VOP_SETATTR(vp
, &vattr
, ndp
->ni_cred
);
* Truncate a file given its path name.
register struct syscontext
*scp
;
} *uap
= (struct a
*)scp
->sc_ap
;
register struct nameidata
*ndp
= &scp
->sc_nd
;
register struct vnode
*vp
;
ndp
->ni_nameiop
= LOOKUP
| FOLLOW
| LOCKLEAF
;
ndp
->ni_segflg
= UIO_USERSPACE
;
ndp
->ni_dirp
= uap
->fname
;
vattr
.va_size
= uap
->length
;
if (vp
->v_type
== VDIR
) {
if ((error
= vn_writechk(vp
)) ||
(error
= VOP_ACCESS(vp
, VWRITE
, ndp
->ni_cred
)))
error
= VOP_SETATTR(vp
, &vattr
, ndp
->ni_cred
);
* Truncate a file given a file descriptor.
register struct syscontext
*scp
;
} *uap
= (struct a
*)scp
->sc_ap
;
if (error
= getvnode(scp
->sc_ofile
, uap
->fd
, &fp
))
if ((fp
->f_flag
& FWRITE
) == 0)
vattr
.va_size
= uap
->length
;
vp
= (struct vnode
*)fp
->f_data
;
if (vp
->v_type
== VDIR
) {
if (error
= vn_writechk(vp
))
error
= VOP_SETATTR(vp
, &vattr
, fp
->f_cred
);
register struct syscontext
*scp
;
} *uap
= (struct a
*)scp
->sc_ap
;
register struct vnode
*vp
;
if (error
= getvnode(scp
->sc_ofile
, uap
->fd
, &fp
))
vp
= (struct vnode
*)fp
->f_data
;
error
= VOP_FSYNC(vp
, fp
->f_flag
, fp
->f_cred
, MNT_WAIT
);
* Source and destination must either both be directories, or both
* not be directories. If target is a directory, it must be empty.
register struct syscontext
*scp
;
} *uap
= (struct a
*)scp
->sc_ap
;
register struct vnode
*tvp
, *fvp
, *tdvp
;
register struct nameidata
*ndp
= &scp
->sc_nd
;
ndp
->ni_nameiop
= DELETE
| WANTPARENT
;
ndp
->ni_segflg
= UIO_USERSPACE
;
ndp
->ni_dirp
= uap
->from
;
tond
.ni_nameiop
= RENAME
| LOCKPARENT
| LOCKLEAF
| NOCACHE
;
tond
.ni_segflg
= UIO_USERSPACE
;
if (fvp
->v_type
== VDIR
&& tvp
->v_type
!= VDIR
) {
} else if (fvp
->v_type
!= VDIR
&& tvp
->v_type
== VDIR
) {
if (fvp
->v_mount
!= tdvp
->v_mount
) {
* If source is the same as the destination,
* then there is nothing to do.
error
= VOP_RENAME(ndp
, &tond
);
register struct syscontext
*scp
;
} *uap
= (struct a
*)scp
->sc_ap
;
register struct nameidata
*ndp
= &scp
->sc_nd
;
register struct vnode
*vp
;
ndp
->ni_nameiop
= CREATE
| LOCKPARENT
;
ndp
->ni_segflg
= UIO_USERSPACE
;
ndp
->ni_dirp
= uap
->name
;
vattr
.va_mode
= (uap
->dmode
& 0777) &~ scp
->sc_cmask
;
error
= VOP_MKDIR(ndp
, &vattr
);
register struct syscontext
*scp
;
} *uap
= (struct a
*)scp
->sc_ap
;
register struct nameidata
*ndp
= &scp
->sc_nd
;
register struct vnode
*vp
;
ndp
->ni_nameiop
= DELETE
| LOCKPARENT
| LOCKLEAF
;
ndp
->ni_segflg
= UIO_USERSPACE
;
ndp
->ni_dirp
= uap
->name
;
if (vp
->v_type
!= VDIR
) {
* Don't unlink a mounted file.
* Read a block of directory entries in a file system independent format
register struct syscontext
*scp
;
} *uap
= (struct a
*)scp
->sc_ap
;
register struct vnode
*vp
;
if (error
= getvnode(scp
->sc_ofile
, 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));
scp
->sc_retval1
= uap
->count
- auio
.uio_resid
;
* mode mask for creation of files
register struct syscontext
*scp
;
} *uap
= (struct a
*)scp
->sc_ap
;
scp
->sc_retval1
= scp
->sc_cmask
;
scp
->sc_cmask
= uap
->mask
& 07777;
* Void all references to file by ripping underlying filesystem
register struct syscontext
*scp
;
} *uap
= (struct a
*)scp
->sc_ap
;
register struct nameidata
*ndp
= &scp
->sc_nd
;
register struct vnode
*vp
;
ndp
->ni_nameiop
= LOOKUP
| FOLLOW
;
ndp
->ni_segflg
= UIO_USERSPACE
;
ndp
->ni_dirp
= uap
->fname
;
if (vp
->v_type
!= VCHR
&& vp
->v_type
!= VBLK
) {
if (error
= VOP_GETATTR(vp
, &vattr
, scp
->sc_cred
))
if (scp
->sc_uid
!= vattr
.va_uid
||
(error
= suser(scp
->sc_cred
, &scp
->sc_acflag
)))
if (vp
->v_usecount
> 1 || (vp
->v_flag
& VALIASED
))
getvnode(ofile
, fdes
, fpp
)
if ((unsigned)fdes
>= NOFILE
|| (fp
= ofile
[fdes
]) == NULL
)
if (fp
->f_type
!= DTYPE_VNODE
)