- Tweak kern_msgctl() to return a copy of the requested message queue id

structure in the struct pointed to by the 3rd argument for IPC_STAT and
  get rid of the 4th argument.  The old way returned a pointer into the
  kernel array that the calling function would then access afterwards
  without holding the appropriate locks and doing non-lock-safe things like
  copyout() with the data anyways.  This change removes that unsafeness and
  resulting race conditions as well as simplifying the interface.
- Implement kern_foo wrappers for stat(), lstat(), fstat(), statfs(),
  fstatfs(), and fhstatfs().  Use these wrappers to cut out a lot of
  code duplication for freebsd4 and netbsd compatability system calls.
- Add a new lookup function kern_alternate_path() that looks up a filename
  under an alternate prefix and determines which filename should be used.
  This is basically a more general version of linux_emul_convpath() that
  can be shared by all the ABIs thus allowing for further reduction of
  code duplication.
This commit is contained in:
John Baldwin 2005-02-07 18:44:55 +00:00
parent c90110d639
commit 76951d21d1
7 changed files with 346 additions and 278 deletions

View File

@ -637,7 +637,6 @@ linux_msgctl(struct thread *td, struct linux_msgctl_args *args)
int error, bsd_cmd;
struct l_msqid_ds linux_msqid;
struct msqid_ds bsd_msqid;
struct msqid_ds *bsd_msqptr;
error = linux_msqid_pullup(args->cmd & LINUX_IPC_64,
&linux_msqid, (caddr_t)PTRIN(args->buf));
@ -647,13 +646,13 @@ linux_msgctl(struct thread *td, struct linux_msgctl_args *args)
if (bsd_cmd == LINUX_IPC_SET)
linux_to_bsd_msqid_ds(&linux_msqid, &bsd_msqid);
error = kern_msgctl(td, args->msqid, bsd_cmd, &bsd_msqid, &bsd_msqptr);
error = kern_msgctl(td, args->msqid, bsd_cmd, &bsd_msqid);
if (error != 0)
if (bsd_cmd != LINUX_IPC_RMID || error != EINVAL)
return (error);
if (bsd_cmd == LINUX_IPC_STAT) {
bsd_to_linux_msqid_ds(bsd_msqptr, &linux_msqid);
bsd_to_linux_msqid_ds(&bsd_msqid, &linux_msqid);
return (linux_msqid_pushdown(args->cmd & LINUX_IPC_64,
&linux_msqid, (caddr_t)PTRIN(args->buf)));
}

View File

@ -1030,20 +1030,15 @@ struct ofstat_args {
int
ofstat(struct thread *td, struct ofstat_args *uap)
{
struct file *fp;
struct stat ub;
struct ostat oub;
struct stat ub;
int error;
if ((error = fget(td, uap->fd, &fp)) != 0)
goto done2;
error = fo_stat(fp, &ub, td->td_ucred, td);
error = kern_fstat(td, uap->fd, &ub);
if (error == 0) {
cvtstat(&ub, &oub);
error = copyout(&oub, uap->sb, sizeof(oub));
}
fdrop(fp, td);
done2:
return (error);
}
#endif /* COMPAT_43 */
@ -1064,17 +1059,25 @@ struct fstat_args {
int
fstat(struct thread *td, struct fstat_args *uap)
{
struct file *fp;
struct stat ub;
int error;
if ((error = fget(td, uap->fd, &fp)) != 0)
goto done2;
error = fo_stat(fp, &ub, td->td_ucred, td);
error = kern_fstat(td, uap->fd, &ub);
if (error == 0)
error = copyout(&ub, uap->sb, sizeof(ub));
return (error);
}
int
kern_fstat(struct thread *td, int fd, struct stat *sbp)
{
struct file *fp;
int error;
if ((error = fget(td, fd, &fp)) != 0)
return (error);
error = fo_stat(fp, sbp, td->td_ucred, td);
fdrop(fp, td);
done2:
return (error);
}
@ -1094,20 +1097,15 @@ struct nfstat_args {
int
nfstat(struct thread *td, struct nfstat_args *uap)
{
struct file *fp;
struct stat ub;
struct nstat nub;
struct stat ub;
int error;
if ((error = fget(td, uap->fd, &fp)) != 0)
goto done2;
error = fo_stat(fp, &ub, td->td_ucred, td);
error = kern_fstat(td, uap->fd, &ub);
if (error == 0) {
cvtnstat(&ub, &nub);
error = copyout(&nub, uap->sb, sizeof(nub));
}
fdrop(fp, td);
done2:
return (error);
}

View File

@ -397,26 +397,24 @@ msgctl(td, uap)
int msqid = uap->msqid;
int cmd = uap->cmd;
struct msqid_ds msqbuf;
struct msqid_ds *msqptr;
int error;
DPRINTF(("call to msgctl(%d, %d, 0x%x)\n", msqid, cmd, uap->buf));
if (cmd == IPC_SET &&
(error = copyin(uap->buf, &msqbuf, sizeof(msqbuf))) != 0)
return (error);
error = kern_msgctl(td, msqid, cmd, &msqbuf, &msqptr);
error = kern_msgctl(td, msqid, cmd, &msqbuf);
if (cmd == IPC_STAT && error == 0)
error = copyout(msqptr, uap->buf, sizeof(struct msqid_ds));
error = copyout(&msqbuf, uap->buf, sizeof(struct msqid_ds));
return (error);
}
int
kern_msgctl(td, msqid, cmd, msqbuf, msqptr)
kern_msgctl(td, msqid, cmd, msqbuf)
struct thread *td;
int msqid;
int cmd;
struct msqid_ds *msqbuf;
struct msqid_ds **msqptr;
{
int rval, error, msqix;
register struct msqid_kernel *msqkptr;
@ -545,7 +543,7 @@ kern_msgctl(td, msqid, cmd, msqbuf, msqptr)
DPRINTF(("requester doesn't have read access\n"));
goto done2;
}
*msqptr = &(msqkptr->u);
*msqbuf = msqkptr->u;
break;
default:
@ -558,7 +556,7 @@ kern_msgctl(td, msqid, cmd, msqbuf, msqptr)
td->td_retval[0] = rval;
done2:
mtx_unlock(&msq_mtx);
return(error);
return (error);
}
#ifndef _SYS_SYSPROTO_H_

View File

@ -220,6 +220,19 @@ statfs(td, uap)
char *path;
struct statfs *buf;
} */ *uap;
{
struct statfs sf;
int error;
error = kern_statfs(td, uap->path, UIO_USERSPACE, &sf);
if (error == 0)
error = copyout(&sf, uap->buf, sizeof(sf));
return (error);
}
int
kern_statfs(struct thread *td, char *path, enum uio_seg pathseg,
struct statfs *buf)
{
struct mount *mp;
struct statfs *sp, sb;
@ -227,7 +240,7 @@ statfs(td, uap)
struct nameidata nd;
mtx_lock(&Giant);
NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td);
NDINIT(&nd, LOOKUP, FOLLOW, pathseg, path, td);
if ((error = namei(&nd)) != 0) {
mtx_unlock(&Giant);
return (error);
@ -258,7 +271,8 @@ statfs(td, uap)
sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
sp = &sb;
}
return (copyout(sp, uap->buf, sizeof(*sp)));
*buf = *sp;
return (0);
}
/*
@ -277,13 +291,25 @@ fstatfs(td, uap)
int fd;
struct statfs *buf;
} */ *uap;
{
struct statfs sf;
int error;
error = kern_fstatfs(td, uap->fd, &sf);
if (error == 0)
error = copyout(&sf, uap->buf, sizeof(sf));
return (error);
}
int
kern_fstatfs(struct thread *td, int fd, struct statfs *buf)
{
struct file *fp;
struct mount *mp;
struct statfs *sp, sb;
int error;
if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
if ((error = getvnode(td->td_proc->p_fd, fd, &fp)) != 0)
return (error);
mtx_lock(&Giant);
mp = fp->f_vnode->v_mount;
@ -315,7 +341,8 @@ fstatfs(td, uap)
sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
sp = &sb;
}
return (copyout(sp, uap->buf, sizeof(*sp)));
*buf = *sp;
return (0);
}
/*
@ -431,29 +458,14 @@ freebsd4_statfs(td, uap)
struct ostatfs *buf;
} */ *uap;
{
struct mount *mp;
struct statfs *sp;
struct ostatfs osb;
struct statfs sf;
int error;
struct nameidata nd;
NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td);
if ((error = namei(&nd)) != 0)
return (error);
mp = nd.ni_vp->v_mount;
sp = &mp->mnt_stat;
NDFREE(&nd, NDF_ONLY_PNBUF);
vrele(nd.ni_vp);
#ifdef MAC
error = mac_check_mount_stat(td->td_ucred, mp);
error = kern_statfs(td, uap->path, UIO_USERSPACE, &sf);
if (error)
return (error);
#endif
error = VFS_STATFS(mp, sp, td);
if (error)
return (error);
sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
cvtstatfs(td, sp, &osb);
cvtstatfs(td, &sf, &osb);
return (copyout(&osb, uap->buf, sizeof(osb)));
}
@ -474,29 +486,14 @@ freebsd4_fstatfs(td, uap)
struct ostatfs *buf;
} */ *uap;
{
struct file *fp;
struct mount *mp;
struct statfs *sp;
struct ostatfs osb;
struct statfs sf;
int error;
if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
return (error);
mp = fp->f_vnode->v_mount;
fdrop(fp, td);
if (mp == NULL)
return (EBADF);
#ifdef MAC
error = mac_check_mount_stat(td->td_ucred, mp);
error = kern_fstatfs(td, uap->fd, &sf);
if (error)
return (error);
#endif
sp = &mp->mnt_stat;
error = VFS_STATFS(mp, sp, td);
if (error)
return (error);
sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
cvtstatfs(td, sp, &osb);
cvtstatfs(td, &sf, &osb);
return (copyout(&osb, uap->buf, sizeof(osb)));
}
@ -598,34 +595,17 @@ freebsd4_fhstatfs(td, uap)
struct ostatfs *buf;
} */ *uap;
{
struct statfs *sp;
struct mount *mp;
struct vnode *vp;
struct ostatfs osb;
struct statfs sf;
fhandle_t fh;
int error;
error = suser(td);
if (error)
return (error);
if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0)
return (error);
if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
return (ESTALE);
if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)))
return (error);
mp = vp->v_mount;
sp = &mp->mnt_stat;
vput(vp);
#ifdef MAC
error = mac_check_mount_stat(td->td_ucred, mp);
error = kern_fhstatfs(td, fh, &sf);
if (error)
return (error);
#endif
if ((error = VFS_STATFS(mp, sp, td)) != 0)
return (error);
sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
cvtstatfs(td, sp, &osb);
cvtstatfs(td, &sf, &osb);
return (copyout(&osb, uap->buf, sizeof(osb)));
}
@ -1972,15 +1952,8 @@ ostat(td, uap)
struct stat sb;
struct ostat osb;
int error;
struct nameidata nd;
NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
uap->path, td);
if ((error = namei(&nd)) != 0)
return (error);
NDFREE(&nd, NDF_ONLY_PNBUF);
error = vn_stat(nd.ni_vp, &sb, td->td_ucred, NOCRED, td);
vput(nd.ni_vp);
error = kern_stat(td, uap->path, UIO_USERSPACE, &sb);
if (error)
return (error);
cvtstat(&sb, &osb);
@ -2005,20 +1978,11 @@ olstat(td, uap)
struct ostat *ub;
} */ *uap;
{
struct vnode *vp;
struct stat sb;
struct ostat osb;
int error;
struct nameidata nd;
NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
uap->path, td);
if ((error = namei(&nd)) != 0)
return (error);
vp = nd.ni_vp;
error = vn_stat(vp, &sb, td->td_ucred, NOCRED, td);
NDFREE(&nd, NDF_ONLY_PNBUF);
vput(vp);
error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb);
if (error)
return (error);
cvtstat(&sb, &osb);
@ -2075,15 +2039,26 @@ stat(td, uap)
{
struct stat sb;
int error;
error = kern_stat(td, uap->path, UIO_USERSPACE, &sb);
if (error == 0)
error = copyout(&sb, uap->ub, sizeof (sb));
return (error);
}
int
kern_stat(struct thread *td, char *path, enum uio_seg pathseg, struct stat *sbp)
{
struct nameidata nd;
int vfslocked;
struct stat sb;
int error, vfslocked;
#ifdef LOOKUP_SHARED
NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF | NOOBJ | MPSAFE,
UIO_USERSPACE, uap->path, td);
pathseg, path, td);
#else
NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ | MPSAFE, UIO_USERSPACE,
uap->path, td);
NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ | MPSAFE, pathseg, path,
td);
#endif
if ((error = namei(&nd)) != 0)
return (error);
@ -2094,8 +2069,8 @@ stat(td, uap)
VFS_UNLOCK_GIANT(vfslocked);
if (error)
return (error);
error = copyout(&sb, uap->ub, sizeof (sb));
return (error);
*sbp = sb;
return (0);
}
/*
@ -2115,14 +2090,26 @@ lstat(td, uap)
struct stat *ub;
} */ *uap;
{
struct stat sb;
int error;
error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb);
if (error == 0)
error = copyout(&sb, uap->ub, sizeof (sb));
return (error);
}
int
kern_lstat(struct thread *td, char *path, enum uio_seg pathseg, struct stat *sbp)
{
struct vnode *vp;
struct stat sb;
struct nameidata nd;
int vfslocked;
int error, vfslocked;
/* XXX LOOKUP_SHARED? */
NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ | MPSAFE,
UIO_USERSPACE, uap->path, td);
pathseg, path, td);
if ((error = namei(&nd)) != 0)
return (error);
vfslocked = NDHASGIANT(&nd);
@ -2133,16 +2120,12 @@ lstat(td, uap)
VFS_UNLOCK_GIANT(vfslocked);
if (error)
return (error);
error = copyout(&sb, uap->ub, sizeof (sb));
return (error);
*sbp = sb;
return (0);
}
/*
* Implementation of the NetBSD stat() function.
* XXX This should probably be collapsed with the FreeBSD version,
* as the differences are only due to vn_stat() clearing spares at
* the end of the structures. vn_stat could be split to avoid this,
* and thus collapse the following to close to zero code.
* Implementation of the NetBSD [l]stat() functions.
*/
void
cvtnstat(sb, nsb)
@ -2185,18 +2168,8 @@ nstat(td, uap)
struct stat sb;
struct nstat nsb;
int error;
struct nameidata nd;
int vfslocked;
NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ | MPSAFE, UIO_USERSPACE,
uap->path, td);
if ((error = namei(&nd)) != 0)
return (error);
vfslocked = NDHASGIANT(&nd);
NDFREE(&nd, NDF_ONLY_PNBUF);
error = vn_stat(nd.ni_vp, &sb, td->td_ucred, NOCRED, td);
vput(nd.ni_vp);
VFS_UNLOCK_GIANT(vfslocked);
error = kern_stat(td, uap->path, UIO_USERSPACE, &sb);
if (error)
return (error);
cvtnstat(&sb, &nsb);
@ -2221,23 +2194,11 @@ nlstat(td, uap)
struct nstat *ub;
} */ *uap;
{
int error;
struct vnode *vp;
struct stat sb;
struct nstat nsb;
struct nameidata nd;
int vfslocked;
int error;
NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ | MPSAFE,
UIO_USERSPACE, uap->path, td);
if ((error = namei(&nd)) != 0)
return (error);
vfslocked = NDHASGIANT(&nd);
vp = nd.ni_vp;
NDFREE(&nd, NDF_ONLY_PNBUF);
error = vn_stat(vp, &sb, td->td_ucred, NOCRED, td);
vput(vp);
VFS_UNLOCK_GIANT(vfslocked);
error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb);
if (error)
return (error);
cvtnstat(&sb, &nsb);
@ -4233,18 +4194,30 @@ fhstatfs(td, uap)
struct fhandle *u_fhp;
struct statfs *buf;
} */ *uap;
{
struct statfs sf;
fhandle_t fh;
int error;
if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0)
return (error);
error = kern_fhstatfs(td, fh, &sf);
if (error == 0)
error = copyout(&sf, uap->buf, sizeof(sf));
return (error);
}
int
kern_fhstatfs(struct thread *td, fhandle_t fh, struct statfs *buf)
{
struct statfs *sp;
struct mount *mp;
struct vnode *vp;
fhandle_t fh;
int error;
error = suser(td);
if (error)
return (error);
if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0)
return (error);
if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
return (ESTALE);
if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)))
@ -4265,7 +4238,8 @@ fhstatfs(td, uap)
sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
if ((error = VFS_STATFS(mp, sp, td)) != 0)
return (error);
return (copyout(sp, uap->buf, sizeof(*sp)));
*buf = *sp;
return (0);
}
/*

View File

@ -51,6 +51,7 @@ __FBSDID("$FreeBSD$");
#include <sys/mount.h>
#include <sys/filedesc.h>
#include <sys/proc.h>
#include <sys/syscallsubr.h>
#ifdef KTRACE
#include <sys/ktrace.h>
#endif
@ -807,3 +808,115 @@ relookup(dvp, vpp, cnp)
*vpp = NULL;
return (error);
}
/*
* Determine if there is a suitable alternate filename under the specified
* prefix for the specified path. If the create flag is set, then the
* alternate prefix will be used so long as the parent directory exists.
* This is used by the various compatiblity ABIs so that Linux binaries prefer
* files under /compat/linux for example. The chosen path (whether under
* the prefix or under /) is returned in a kernel malloc'd buffer pointed
* to by pathbuf. The caller is responsible for free'ing the buffer from
* the M_TEMP bucket if one is returned.
*/
int
kern_alternate_path(struct thread *td, const char *prefix, char *path,
enum uio_seg pathseg, char **pathbuf, int create)
{
struct nameidata nd, ndroot;
char *ptr, *buf, *cp;
size_t len, sz;
int error;
buf = (char *) malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
*pathbuf = buf;
/* Copy the prefix into the new pathname as a starting point. */
len = strlcpy(buf, prefix, MAXPATHLEN);
if (len >= MAXPATHLEN) {
*pathbuf = NULL;
free(buf, M_TEMP);
return (EINVAL);
}
sz = MAXPATHLEN - len;
ptr = buf + len;
/* Append the filename to the prefix. */
if (pathseg == UIO_SYSSPACE)
error = copystr(path, ptr, sz, &len);
else
error = copyinstr(path, ptr, sz, &len);
if (error) {
*pathbuf = NULL;
free(buf, M_TEMP);
return (error);
}
/* Only use a prefix with absolute pathnames. */
if (*ptr != '/') {
error = EINVAL;
goto keeporig;
}
/* XXX: VFS_LOCK_GIANT? */
mtx_lock(&Giant);
/*
* We know that there is a / somewhere in this pathname.
* Search backwards for it, to find the file's parent dir
* to see if it exists in the alternate tree. If it does,
* and we want to create a file (cflag is set). We don't
* need to worry about the root comparison in this case.
*/
if (create) {
for (cp = &ptr[len] - 1; *cp != '/'; cp--);
*cp = '\0';
NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td);
error = namei(&nd);
*cp = '/';
if (error != 0)
goto nd_failed;
} else {
NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, td);
error = namei(&nd);
if (error != 0)
goto nd_failed;
/*
* We now compare the vnode of the prefix to the one
* vnode asked. If they resolve to be the same, then we
* ignore the match so that the real root gets used.
* This avoids the problem of traversing "../.." to find the
* root directory and never finding it, because "/" resolves
* to the emulation root directory. This is expensive :-(
*/
NDINIT(&ndroot, LOOKUP, FOLLOW, UIO_SYSSPACE, prefix, td);
/* We shouldn't ever get an error from this namei(). */
error = namei(&ndroot);
if (error == 0) {
if (nd.ni_vp == ndroot.ni_vp)
error = ENOENT;
NDFREE(&ndroot, NDF_ONLY_PNBUF);
vrele(ndroot.ni_vp);
}
}
NDFREE(&nd, NDF_ONLY_PNBUF);
vrele(nd.ni_vp);
nd_failed:
/* XXX: VFS_UNLOCK_GIANT? */
mtx_unlock(&Giant);
keeporig:
/* If there was an error, use the original path name. */
if (error)
bcopy(ptr, buf, len);
return (error);
}

View File

@ -220,6 +220,19 @@ statfs(td, uap)
char *path;
struct statfs *buf;
} */ *uap;
{
struct statfs sf;
int error;
error = kern_statfs(td, uap->path, UIO_USERSPACE, &sf);
if (error == 0)
error = copyout(&sf, uap->buf, sizeof(sf));
return (error);
}
int
kern_statfs(struct thread *td, char *path, enum uio_seg pathseg,
struct statfs *buf)
{
struct mount *mp;
struct statfs *sp, sb;
@ -227,7 +240,7 @@ statfs(td, uap)
struct nameidata nd;
mtx_lock(&Giant);
NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td);
NDINIT(&nd, LOOKUP, FOLLOW, pathseg, path, td);
if ((error = namei(&nd)) != 0) {
mtx_unlock(&Giant);
return (error);
@ -258,7 +271,8 @@ statfs(td, uap)
sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
sp = &sb;
}
return (copyout(sp, uap->buf, sizeof(*sp)));
*buf = *sp;
return (0);
}
/*
@ -277,13 +291,25 @@ fstatfs(td, uap)
int fd;
struct statfs *buf;
} */ *uap;
{
struct statfs sf;
int error;
error = kern_fstatfs(td, uap->fd, &sf);
if (error == 0)
error = copyout(&sf, uap->buf, sizeof(sf));
return (error);
}
int
kern_fstatfs(struct thread *td, int fd, struct statfs *buf)
{
struct file *fp;
struct mount *mp;
struct statfs *sp, sb;
int error;
if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
if ((error = getvnode(td->td_proc->p_fd, fd, &fp)) != 0)
return (error);
mtx_lock(&Giant);
mp = fp->f_vnode->v_mount;
@ -315,7 +341,8 @@ fstatfs(td, uap)
sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
sp = &sb;
}
return (copyout(sp, uap->buf, sizeof(*sp)));
*buf = *sp;
return (0);
}
/*
@ -431,29 +458,14 @@ freebsd4_statfs(td, uap)
struct ostatfs *buf;
} */ *uap;
{
struct mount *mp;
struct statfs *sp;
struct ostatfs osb;
struct statfs sf;
int error;
struct nameidata nd;
NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td);
if ((error = namei(&nd)) != 0)
return (error);
mp = nd.ni_vp->v_mount;
sp = &mp->mnt_stat;
NDFREE(&nd, NDF_ONLY_PNBUF);
vrele(nd.ni_vp);
#ifdef MAC
error = mac_check_mount_stat(td->td_ucred, mp);
error = kern_statfs(td, uap->path, UIO_USERSPACE, &sf);
if (error)
return (error);
#endif
error = VFS_STATFS(mp, sp, td);
if (error)
return (error);
sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
cvtstatfs(td, sp, &osb);
cvtstatfs(td, &sf, &osb);
return (copyout(&osb, uap->buf, sizeof(osb)));
}
@ -474,29 +486,14 @@ freebsd4_fstatfs(td, uap)
struct ostatfs *buf;
} */ *uap;
{
struct file *fp;
struct mount *mp;
struct statfs *sp;
struct ostatfs osb;
struct statfs sf;
int error;
if ((error = getvnode(td->td_proc->p_fd, uap->fd, &fp)) != 0)
return (error);
mp = fp->f_vnode->v_mount;
fdrop(fp, td);
if (mp == NULL)
return (EBADF);
#ifdef MAC
error = mac_check_mount_stat(td->td_ucred, mp);
error = kern_fstatfs(td, uap->fd, &sf);
if (error)
return (error);
#endif
sp = &mp->mnt_stat;
error = VFS_STATFS(mp, sp, td);
if (error)
return (error);
sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
cvtstatfs(td, sp, &osb);
cvtstatfs(td, &sf, &osb);
return (copyout(&osb, uap->buf, sizeof(osb)));
}
@ -598,34 +595,17 @@ freebsd4_fhstatfs(td, uap)
struct ostatfs *buf;
} */ *uap;
{
struct statfs *sp;
struct mount *mp;
struct vnode *vp;
struct ostatfs osb;
struct statfs sf;
fhandle_t fh;
int error;
error = suser(td);
if (error)
return (error);
if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0)
return (error);
if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
return (ESTALE);
if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)))
return (error);
mp = vp->v_mount;
sp = &mp->mnt_stat;
vput(vp);
#ifdef MAC
error = mac_check_mount_stat(td->td_ucred, mp);
error = kern_fhstatfs(td, fh, &sf);
if (error)
return (error);
#endif
if ((error = VFS_STATFS(mp, sp, td)) != 0)
return (error);
sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
cvtstatfs(td, sp, &osb);
cvtstatfs(td, &sf, &osb);
return (copyout(&osb, uap->buf, sizeof(osb)));
}
@ -1972,15 +1952,8 @@ ostat(td, uap)
struct stat sb;
struct ostat osb;
int error;
struct nameidata nd;
NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
uap->path, td);
if ((error = namei(&nd)) != 0)
return (error);
NDFREE(&nd, NDF_ONLY_PNBUF);
error = vn_stat(nd.ni_vp, &sb, td->td_ucred, NOCRED, td);
vput(nd.ni_vp);
error = kern_stat(td, uap->path, UIO_USERSPACE, &sb);
if (error)
return (error);
cvtstat(&sb, &osb);
@ -2005,20 +1978,11 @@ olstat(td, uap)
struct ostat *ub;
} */ *uap;
{
struct vnode *vp;
struct stat sb;
struct ostat osb;
int error;
struct nameidata nd;
NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE,
uap->path, td);
if ((error = namei(&nd)) != 0)
return (error);
vp = nd.ni_vp;
error = vn_stat(vp, &sb, td->td_ucred, NOCRED, td);
NDFREE(&nd, NDF_ONLY_PNBUF);
vput(vp);
error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb);
if (error)
return (error);
cvtstat(&sb, &osb);
@ -2075,15 +2039,26 @@ stat(td, uap)
{
struct stat sb;
int error;
error = kern_stat(td, uap->path, UIO_USERSPACE, &sb);
if (error == 0)
error = copyout(&sb, uap->ub, sizeof (sb));
return (error);
}
int
kern_stat(struct thread *td, char *path, enum uio_seg pathseg, struct stat *sbp)
{
struct nameidata nd;
int vfslocked;
struct stat sb;
int error, vfslocked;
#ifdef LOOKUP_SHARED
NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF | NOOBJ | MPSAFE,
UIO_USERSPACE, uap->path, td);
pathseg, path, td);
#else
NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ | MPSAFE, UIO_USERSPACE,
uap->path, td);
NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ | MPSAFE, pathseg, path,
td);
#endif
if ((error = namei(&nd)) != 0)
return (error);
@ -2094,8 +2069,8 @@ stat(td, uap)
VFS_UNLOCK_GIANT(vfslocked);
if (error)
return (error);
error = copyout(&sb, uap->ub, sizeof (sb));
return (error);
*sbp = sb;
return (0);
}
/*
@ -2115,14 +2090,26 @@ lstat(td, uap)
struct stat *ub;
} */ *uap;
{
struct stat sb;
int error;
error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb);
if (error == 0)
error = copyout(&sb, uap->ub, sizeof (sb));
return (error);
}
int
kern_lstat(struct thread *td, char *path, enum uio_seg pathseg, struct stat *sbp)
{
struct vnode *vp;
struct stat sb;
struct nameidata nd;
int vfslocked;
int error, vfslocked;
/* XXX LOOKUP_SHARED? */
NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ | MPSAFE,
UIO_USERSPACE, uap->path, td);
pathseg, path, td);
if ((error = namei(&nd)) != 0)
return (error);
vfslocked = NDHASGIANT(&nd);
@ -2133,16 +2120,12 @@ lstat(td, uap)
VFS_UNLOCK_GIANT(vfslocked);
if (error)
return (error);
error = copyout(&sb, uap->ub, sizeof (sb));
return (error);
*sbp = sb;
return (0);
}
/*
* Implementation of the NetBSD stat() function.
* XXX This should probably be collapsed with the FreeBSD version,
* as the differences are only due to vn_stat() clearing spares at
* the end of the structures. vn_stat could be split to avoid this,
* and thus collapse the following to close to zero code.
* Implementation of the NetBSD [l]stat() functions.
*/
void
cvtnstat(sb, nsb)
@ -2185,18 +2168,8 @@ nstat(td, uap)
struct stat sb;
struct nstat nsb;
int error;
struct nameidata nd;
int vfslocked;
NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ | MPSAFE, UIO_USERSPACE,
uap->path, td);
if ((error = namei(&nd)) != 0)
return (error);
vfslocked = NDHASGIANT(&nd);
NDFREE(&nd, NDF_ONLY_PNBUF);
error = vn_stat(nd.ni_vp, &sb, td->td_ucred, NOCRED, td);
vput(nd.ni_vp);
VFS_UNLOCK_GIANT(vfslocked);
error = kern_stat(td, uap->path, UIO_USERSPACE, &sb);
if (error)
return (error);
cvtnstat(&sb, &nsb);
@ -2221,23 +2194,11 @@ nlstat(td, uap)
struct nstat *ub;
} */ *uap;
{
int error;
struct vnode *vp;
struct stat sb;
struct nstat nsb;
struct nameidata nd;
int vfslocked;
int error;
NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ | MPSAFE,
UIO_USERSPACE, uap->path, td);
if ((error = namei(&nd)) != 0)
return (error);
vfslocked = NDHASGIANT(&nd);
vp = nd.ni_vp;
NDFREE(&nd, NDF_ONLY_PNBUF);
error = vn_stat(vp, &sb, td->td_ucred, NOCRED, td);
vput(vp);
VFS_UNLOCK_GIANT(vfslocked);
error = kern_lstat(td, uap->path, UIO_USERSPACE, &sb);
if (error)
return (error);
cvtnstat(&sb, &nsb);
@ -4233,18 +4194,30 @@ fhstatfs(td, uap)
struct fhandle *u_fhp;
struct statfs *buf;
} */ *uap;
{
struct statfs sf;
fhandle_t fh;
int error;
if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0)
return (error);
error = kern_fhstatfs(td, fh, &sf);
if (error == 0)
error = copyout(&sf, uap->buf, sizeof(sf));
return (error);
}
int
kern_fhstatfs(struct thread *td, fhandle_t fh, struct statfs *buf)
{
struct statfs *sp;
struct mount *mp;
struct vnode *vp;
fhandle_t fh;
int error;
error = suser(td);
if (error)
return (error);
if ((error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t))) != 0)
return (error);
if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
return (ESTALE);
if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)))
@ -4265,7 +4238,8 @@ fhstatfs(td, uap)
sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
if ((error = VFS_STATFS(mp, sp, td)) != 0)
return (error);
return (copyout(sp, uap->buf, sizeof(*sp)));
*buf = *sp;
return (0);
}
/*

View File

@ -32,20 +32,24 @@
#include <sys/uio.h>
#include <sys/socket.h>
#include <sys/mac.h>
#include <sys/mount.h>
struct itimerval;
struct image_args;
struct mbuf;
struct msghdr;
struct msqid_ds;
struct rlimit;
struct rusage;
struct sockaddr;
struct itimerval;
struct msqid_ds;
struct image_args;
struct stat;
int kern___getcwd(struct thread *td, u_char *buf, enum uio_seg bufseg,
u_int buflen);
int kern_access(struct thread *td, char *path, enum uio_seg pathseg,
int flags);
int kern_alternate_path(struct thread *td, const char *prefix, char *path,
enum uio_seg pathseg, char **pathbuf, int create);
int kern_bind(struct thread *td, int fd, struct sockaddr *sa);
int kern_chdir(struct thread *td, char *path, enum uio_seg pathseg);
int kern_chmod(struct thread *td, char *path, enum uio_seg pathseg,
@ -56,6 +60,9 @@ int kern_connect(struct thread *td, int fd, struct sockaddr *sa);
int kern_execve(struct thread *td, struct image_args *args,
struct mac *mac_p);
int kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg);
int kern_fhstatfs(struct thread *td, fhandle_t fh, struct statfs *buf);
int kern_fstat(struct thread *td, int fd, struct stat *sbp);
int kern_fstatfs(struct thread *td, int fd, struct statfs *buf);
int kern_futimes(struct thread *td, int fd, struct timeval *tptr,
enum uio_seg tptrseg);
int kern_getitimer(struct thread *, u_int, struct itimerval *);
@ -66,6 +73,8 @@ int kern_lchown(struct thread *td, char *path, enum uio_seg pathseg,
int uid, int gid);
int kern_link(struct thread *td, char *path, char *link,
enum uio_seg segflg);
int kern_lstat(struct thread *td, char *path, enum uio_seg pathseg,
struct stat *sbp);
int kern_lutimes(struct thread *td, char *path, enum uio_seg pathseg,
struct timeval *tptr, enum uio_seg tptrseg);
int kern_mkdir(struct thread *td, char *path, enum uio_seg segflg,
@ -74,8 +83,7 @@ int kern_mkfifo(struct thread *td, char *path, enum uio_seg pathseg,
int mode);
int kern_mknod(struct thread *td, char *path, enum uio_seg pathseg,
int mode, int dev);
int kern_msgctl(struct thread *, int, int, struct msqid_ds *,
struct msqid_ds **);
int kern_msgctl(struct thread *, int, int, struct msqid_ds *);
int kern_nanosleep(struct thread *td, struct timespec *rqt,
struct timespec *rmt);
int kern_open(struct thread *td, char *path, enum uio_seg pathseg,
@ -106,6 +114,10 @@ int kern_sigaltstack(struct thread *td, stack_t *ss, stack_t *oss);
int kern_sigprocmask(struct thread *td, int how,
sigset_t *set, sigset_t *oset, int old);
int kern_sigsuspend(struct thread *td, sigset_t mask);
int kern_stat(struct thread *td, char *path, enum uio_seg pathseg,
struct stat *sbp);
int kern_statfs(struct thread *td, char *path, enum uio_seg pathseg,
struct statfs *buf);
int kern_symlink(struct thread *td, char *path, char *link,
enum uio_seg segflg);
int kern_truncate(struct thread *td, char *path, enum uio_seg pathseg,