Page MenuHomeFreeBSD

D18359.id51358.diff
No OneTemporary

D18359.id51358.diff

Index: lib/libc/sys/Makefile.inc
===================================================================
--- lib/libc/sys/Makefile.inc
+++ lib/libc/sys/Makefile.inc
@@ -184,7 +184,9 @@
extattr_get_file.2 \
fcntl.2 \
ffclock.2 \
+ fhlink.2 \
fhopen.2 \
+ fhreadlink.2 \
flock.2 \
fork.2 \
fsync.2 \
@@ -395,7 +397,8 @@
MLINKS+=fhopen.2 fhstat.2 fhopen.2 fhstatfs.2
MLINKS+=fsync.2 fdatasync.2
MLINKS+=getdirentries.2 getdents.2
-MLINKS+=getfh.2 lgetfh.2
+MLINKS+=getfh.2 lgetfh.2 \
+ getfh.2 getfhat.2
MLINKS+=getgid.2 getegid.2
MLINKS+=getitimer.2 setitimer.2
MLINKS+=getlogin.2 getlogin_r.3
Index: lib/libc/sys/Symbol.map
===================================================================
--- lib/libc/sys/Symbol.map
+++ lib/libc/sys/Symbol.map
@@ -401,6 +401,13 @@
cpuset_setdomain;
};
+FBSD_1.6 {
+ fhlink;
+ fhlinkat;
+ fhreadlink;
+ getfhat;
+};
+
FBSDprivate_1.0 {
___acl_aclcheck_fd;
__sys___acl_aclcheck_fd;
Index: lib/libc/sys/fhlink.2
===================================================================
--- /dev/null
+++ lib/libc/sys/fhlink.2
@@ -0,0 +1,270 @@
+.\" Copyright (c) 1980, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd November 29, 2018
+.Dt FHLINK 2
+.Os
+.Sh NAME
+.Nm fhlink ,
+.Nm fhlinkat
+.Nd make a hard file link
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In unistd.h
+.Ft int
+.Fn link "fhandle_t *fhp" "const char *to"
+.Ft int
+.Fn link "fhandle_t *fhp" "int tofd" "const char *to"
+.Fc
+.Sh DESCRIPTION
+The
+.Fn fhlink
+system call
+atomically creates the specified directory entry (hard link)
+.Fa to
+with the attributes of the underlying object pointed at by
+.Fa fhp .
+If the link is successful: the link count of the underlying object
+is incremented;
+.Fa fhp
+and
+.Fa to
+share equal access and rights
+to the
+underlying object.
+.Pp
+If
+.Fa fhp
+is removed, the file
+.Fa to
+is not deleted and the link count of the
+underlying object is
+decremented.
+.Pp
+The object pointed at by the
+.Fa fhp
+argument
+must exist for the hard link to
+succeed and
+both
+.Fa fhp
+and
+.Fa to
+must be in the same file system.
+The
+.Fa fhp
+argument
+may not be a directory.
+.Pp
+The
+.Fn linkat
+system call is equivalent to
+.Fa link
+except in the case where
+.Fa to
+is a relative paths.
+In this case a relative path
+.Fa to
+is interpreted relative to
+the directory associated with the file descriptor
+.Fa tofd
+instead of the current working directory.
+.Pp
+Values for
+.Fa flag
+are constructed by a bitwise-inclusive OR of flags from the following
+list, defined in
+.In fcntl.h :
+.Bl -tag -width indent
+.It Dv AT_SYMLINK_FOLLOW
+If
+.Fa fhp
+names a symbolic link, a new link for the target of the symbolic link is
+created.
+.It Dv AT_BENEATH
+Only allow to link to a file which is beneath of the topping directory.
+See the description of the
+.Dv O_BENEATH
+flag in the
+.Xr open 2
+manual page.
+.El
+.Pp
+If
+.Fn linkat
+is passed the special value
+.Dv AT_FDCWD
+in the
+.Fa tofd
+parameter, the current working directory is used for the
+.Fa to
+argument.
+If
+.Fa tofd
+has value
+.Dv AT_FDCWD ,
+the behavior is identical to a call to
+.Fn link .
+Unless
+.Fa flag
+contains the
+.Dv AT_SYMLINK_FOLLOW
+flag, if
+.Fa fhp
+names a symbolic link, a new link is created for the symbolic link
+.Fa fhp
+and not its target.
+.Sh RETURN VALUES
+.Rv -std link
+.Sh ERRORS
+The
+.Fn link
+system call
+will fail and no link will be created if:
+.Bl -tag -width Er
+.It Bq Er ENOTDIR
+A component of
+.Fa to
+prefix is not a directory.
+.It Bq Er ENAMETOOLONG
+A component of
+.Fa to
+exceeded 255 characters,
+or entire length of
+.Fa to
+name exceeded 1023 characters.
+.It Bq Er ENOENT
+A component of
+.Fa to
+prefix does not exist.
+.It Bq Er EOPNOTSUPP
+The file system containing the file pointed at by
+.Fa fhp
+does not support links.
+.It Bq Er EMLINK
+The link count of the file pointed at by
+.Fa fhp
+would exceed 32767.
+.It Bq Er EACCES
+A component of
+.Fa to
+prefix denies search permission.
+.It Bq Er EACCES
+The requested link requires writing in a directory with a mode
+that denies write permission.
+.It Bq Er ELOOP
+Too many symbolic links were encountered in translating one of the pathnames.
+.It Bq Er ENOENT
+The file pointed at by
+.Fa fhp
+does not exist.
+.It Bq Er EEXIST
+The link named by
+.Fa to
+does exist.
+.It Bq Er EPERM
+The file pointed at by
+.Fa fhp
+is a directory.
+.It Bq Er EPERM
+The file pointed at by
+.Fa fhp
+has its immutable or append-only flag set, see the
+.Xr chflags 2
+manual page for more information.
+.It Bq Er EPERM
+The parent directory of the file named by
+.Fa to
+has its immutable flag set.
+.It Bq Er EXDEV
+The link named by
+.Fa to
+and the file pointed at by
+.Fa fhp
+are on different file systems.
+.It Bq Er ENOSPC
+The directory in which the entry for the new link is being placed
+cannot be extended because there is no space left on the file
+system containing the directory.
+.It Bq Er EDQUOT
+The directory in which the entry for the new link
+is being placed cannot be extended because the
+user's quota of disk blocks on the file system
+containing the directory has been exhausted.
+.It Bq Er EIO
+An I/O error occurred while reading from or writing to
+the file system to make the directory entry.
+.It Bq Er EROFS
+The requested link requires writing in a directory on a read-only file
+system.
+.It Bq Er EFAULT
+One of the pathnames specified
+is outside the process's allocated address space.
+.It Bq Er ESTALE
+The file handle
+.Fa fhp
+is no longer valid
+.El
+.Pp
+In addition to the errors returned by the
+.Fn link ,
+the
+.Fn linkat
+system call may fail if:
+.Bl -tag -width Er
+.It Bq Er EBADF
+The
+.Fa fhp
+or
+.Fa to
+argument does not specify an absolute path and the
+.Fa tofd
+argument, is not
+.Dv AT_FDCWD
+nor a valid file descriptor open for searching.
+.It Bq Er EINVAL
+The value of the
+.Fa flag
+argument is not valid.
+.It Bq Er ENOTDIR
+The
+.Fa fhp
+or
+.Fa to
+argument is not an absolute path and
+.Fa tofd
+is not
+.Dv AT_FDCWD
+nor a file descriptor associated with a directory.
+.El
+.Sh SEE ALSO
+.Xr fhstat 2 ,
+.Xr fhreadlink 2 ,
+.Xr fhlink 2 ,
Index: lib/libc/sys/fhreadlink.2
===================================================================
--- /dev/null
+++ lib/libc/sys/fhreadlink.2
@@ -0,0 +1,94 @@
+.\" Copyright (c) 1983, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd November 29, 2018
+.Dt FHREADLINK 2
+.Os
+.Sh NAME
+.Nm fhreadlink
+.Nd read value of a symbolic link
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/param.h
+.In sys/mount.h
+.Ft int
+.Fn fhreadlink "fhandle_t *fhp" "char *buf" "size_t bufsize"
+.Fc
+.Sh DESCRIPTION
+The
+.Fn fhreadlink
+system call
+places the contents of the symbolic link
+.Fa fhp
+in the buffer
+.Fa buf ,
+which has size
+.Fa bufsiz .
+The
+.Fn fhreadlink
+system call does not append a
+.Dv NUL
+character to
+.Fa buf .
+.Pp
+.Sh RETURN VALUES
+The call returns the count of characters placed in the buffer
+if it succeeds, or a \-1 if an error occurs, placing the error
+code in the global variable
+.Va errno .
+.Sh ERRORS
+The
+.Fn readlink
+system call
+will fail if:
+.Bl -tag -width Er
+.It Bq Er ENOENT
+The named file does not exist.
+.It Bq Er ELOOP
+Too many symbolic links were encountered in translating the file handle
+.Fa fhp .
+.It Bq Er EINVAL
+The named file is not a symbolic link.
+.It Bq Er EIO
+An I/O error occurred while reading from the file system.
+.It Bq Er EFAULT
+The
+.Fa buf
+argument
+extends outside the process's allocated address space.
+.It Bq Er ESTALE
+The file handle
+.Fa fhp
+is no longer valid
+.El
+.El
+.Sh SEE ALSO
+.Xr fhstat 2 ,
+.Xr fhlink 2 ,
Index: lib/libc/sys/getfh.2
===================================================================
--- lib/libc/sys/getfh.2
+++ lib/libc/sys/getfh.2
@@ -28,12 +28,13 @@
.\" @(#)getfh.2 8.1 (Berkeley) 6/9/93
.\" $FreeBSD$
.\"
-.Dd April 14, 2011
+.Dd November 26, 2018
.Dt GETFH 2
.Os
.Sh NAME
.Nm getfh ,
-.Nm lgetfh
+.Nm lgetfh ,
+.Nm getfhat
.Nd get file handle
.Sh LIBRARY
.Lb libc
@@ -44,6 +45,8 @@
.Fn getfh "const char *path" "fhandle_t *fhp"
.Ft int
.Fn lgetfh "const char *path" "fhandle_t *fhp"
+.Ft int
+.Fn getfhat "int fd" "const char *path" "fhandle_t *fhp" "int flag"
.Sh DESCRIPTION
The
.Fn getfh
@@ -51,6 +54,7 @@
returns a file handle for the specified file or directory
in the file handle pointed to by
.Fa fhp .
+.Pp
The
.Fn lgetfh
system call is like
@@ -62,7 +66,87 @@
while
.Fn getfh
returns information about the file the link references.
+.Pp
+The
+.Fn getfhat
+system call is equivalent to
+.Fn getfh
+and
+.Fn lgetfh
+except when the
+.Fa path
+specifies a relative or NULL path, or the
+.Dv AT_BENEATH
+flag is provided.
+For
+.Fn getfhat
+and relative or NULL
+.Fa path ,
+the status is retrieved from a file relative to
+the directory associated with the file descriptor
+.Fa fd
+instead of the current working directory.
+For
+.Dv AT_BENEATH
+and absolute
+.Fa path ,
+the status is retrieved from a file specified by the
+.Fa path ,
+but additional permission checks are performed, see below.
+.Pp
+The values for the
+.Fa flag
+are constructed by a bitwise-inclusive OR of flags from this list,
+defined in
+.In fcntl.h :
+.Bl -tag -width indent
+.It Dv AT_SYMLINK_NOFOLLOW
+If
+.Fa path
+names a symbolic link, the status of the symbolic link is returned.
+.It Dv AT_BENEATH
+Only stat files and directories below the topping directory.
+See the description of the
+.Dv O_BENEATH
+flag in the
+.Xr open 2
+manual page.
+.El
+.Pp
+If
+.Fn getfhat
+is passed the special value
+.Dv AT_FDCWD
+in the
+.Fa fd
+parameter, the current working directory is used and the behavior is
+identical to a call to
+.Fn getfth
+or
+.Fn lgetfh
+respectively, depending on whether or not the
+.Dv AT_SYMLINK_NOFOLLOW
+bit is set in
+.Fa flag .
+.Pp
+When
+.Fn getfhat
+is called with an absolute
+.Fa path
+without the
+.Dv AT_BENEATH
+flag, it ignores the
+.Fa fd
+argument.
+When
+.Dv AT_BENEATH
+is specified with an absolute
+.Fa path ,
+a directory passed by the
+.Fa fd
+argument is used as the topping point for the resolution.
These system calls are restricted to the superuser.
+When
.Sh RETURN VALUES
.Rv -std
.Sh ERRORS
@@ -99,11 +183,49 @@
.Fa fhp
argument
points to an invalid address.
+.It Bq Er EFAULT
+The
+.Fa path
+argument
+points outside the processe's allocated address space.
.It Bq Er EIO
An
.Tn I/O
error occurred while reading from or writing to the file system.
+.It Bq Er ESTALE
+The file handle
+.Fa fhp
+is no longer valid
.El
+.Pp
+In addition to the errors returned by
+.Fn getfh ,
+and
+.Fn lgetfh ,
+the
+.Fn getfhat
+system call may fail if:
+.Bl -tag -width Er
+.It Bq Er EBADF
+The
+.Fa path
+argument does not specify an absolute path and the
+.Fa fd
+argument, is neither
+.Dv AT_FDCWD
+nor a valid file descriptor open for searching.
+.It Bq Er EINVAL
+The value of the
+.Fa flag
+argument is not valid.
+.It Bq Er ENOTDIR
+The
+.Fa path
+argument is not an absolute path and
+.Fa fd
+is neither
+.Dv AT_FDCWD
+nor a file descriptor associated with a directory.
.Sh SEE ALSO
.Xr fhopen 2 ,
.Xr open 2 ,
Index: sys/compat/freebsd32/syscalls.master
===================================================================
--- sys/compat/freebsd32/syscalls.master
+++ sys/compat/freebsd32/syscalls.master
@@ -1138,5 +1138,12 @@
int policy); }
563 AUE_NULL NOPROTO { int getrandom(void *buf, size_t buflen, \
unsigned int flags); }
+564 AUE_NULL NOPROTO { int getfhat( int fd, char *path, \
+ struct fhandle *fhp, int flags); }
+565 AUE_NULL NOPROTO { int fhlink( struct fhandle *fhp, const char *to ); }
+566 AUE_NULL NOPROTO { int fhlinkat( struct fhandle *fhp, int tofd, \
+ const char *to); }
+567 AUE_NULL NOPROTO { int fhreadlink( struct fhandle *fhp, char *buf, \
+ size_t bufsize); }
; vim: syntax=off
Index: sys/kern/capabilities.conf
===================================================================
--- sys/kern/capabilities.conf
+++ sys/kern/capabilities.conf
@@ -469,6 +469,7 @@
symlinkat
unlinkat
utimensat
+getfhat
##
## Process descriptor-related system calls are allowed.
Index: sys/kern/syscalls.master
===================================================================
--- sys/kern/syscalls.master
+++ sys/kern/syscalls.master
@@ -3139,6 +3139,34 @@
unsigned int flags
);
}
+564 AUE_NULL STD {
+ int getfhat(
+ int fd,
+ _In_z_ char *path,
+ _Out_ struct fhandle *fhp,
+ int flags
+ );
+ }
+565 AUE_NULL STD {
+ int fhlink(
+ _In_ struct fhandle *fhp,
+ _In_z_ const char *to
+ );
+ }
+566 AUE_NULL STD {
+ int fhlinkat(
+ _In_ struct fhandle *fhp,
+ int tofd,
+ _In_z_ const char *to,
+ );
+ }
+567 AUE_NULL STD {
+ int fhreadlink(
+ _In_ struct fhandle *fhp,
+ _Out_writes_(bufsize) char *buf,
+ size_t bufsize
+ );
+ }
; Please copy any additions and changes to the following compatability tables:
; sys/compat/freebsd32/syscalls.master
Index: sys/kern/vfs_syscalls.c
===================================================================
--- sys/kern/vfs_syscalls.c
+++ sys/kern/vfs_syscalls.c
@@ -105,6 +105,14 @@
const struct timespec *, int, int);
static int vn_access(struct vnode *vp, int user_flags, struct ucred *cred,
struct thread *td);
+static int kern_fhlinkat(struct thread *td, int fd, const char *path,
+ enum uio_seg pathseg, fhandle_t *fhp);
+static int kern_getfhat(struct thread *td, int flags, int fd,
+ const char *path, enum uio_seg pathseg, fhandle_t *fhp);
+static int vn_readlink(struct vnode *vp, char *buf, enum uio_seg bufseg, size_t count,
+ struct thread *td);
+static int vn_linkat(struct thread *td, struct vnode *vp, int fd, const char *path,
+ enum uio_seg segflag, bool locked);
/*
* Sync each mounted filesystem.
@@ -1492,28 +1500,40 @@
int
kern_linkat(struct thread *td, int fd1, int fd2, const char *path1,
- const char *path2, enum uio_seg segflg, int follow)
+ const char *path2, enum uio_seg segflag, int follow)
{
struct vnode *vp;
- struct mount *mp;
struct nameidata nd;
int error;
-again:
- bwillwrite();
- NDINIT_ATRIGHTS(&nd, LOOKUP, follow | AUDITVNODE1, segflg, path1, fd1,
- &cap_linkat_source_rights, td);
+ do {
+ bwillwrite();
+ NDINIT_ATRIGHTS(&nd, LOOKUP, follow | AUDITVNODE1, segflag, path1, fd1,
+ &cap_linkat_source_rights, td);
+
+ if ((error = namei(&nd)) != 0)
+ return (error);
+ NDFREE(&nd, NDF_ONLY_PNBUF);
+ vp = nd.ni_vp;
+
+ } while ((error = vn_linkat(td, vp, fd2, path2, segflag, false) == EAGAIN));
+ return (error);
+}
+
+static int
+vn_linkat(struct thread *td, struct vnode *vp, int fd, const char *path,
+ enum uio_seg segflag, bool locked)
+{
+ struct nameidata nd;
+ struct mount *mp;
+ int error;
- if ((error = namei(&nd)) != 0)
- return (error);
- NDFREE(&nd, NDF_ONLY_PNBUF);
- vp = nd.ni_vp;
if (vp->v_type == VDIR) {
- vrele(vp);
+ locked ? vput(vp) : vrele(vp);
return (EPERM); /* POSIX */
}
NDINIT_ATRIGHTS(&nd, CREATE,
- LOCKPARENT | SAVENAME | AUDITVNODE2 | NOCACHE, segflg, path2, fd2,
+ LOCKPARENT | SAVENAME | AUDITVNODE2 | NOCACHE, segflag, path, fd,
&cap_linkat_target_rights, td);
if ((error = namei(&nd)) == 0) {
if (nd.ni_vp != NULL) {
@@ -1523,7 +1543,7 @@
else
vput(nd.ni_dvp);
vrele(nd.ni_vp);
- vrele(vp);
+ locked ? vput(vp) : vrele(vp);
return (EEXIST);
} else if (nd.ni_dvp->v_mount != vp->v_mount) {
/*
@@ -1533,9 +1553,9 @@
*/
NDFREE(&nd, NDF_ONLY_PNBUF);
vput(nd.ni_dvp);
- vrele(vp);
+ locked ? vput(vp) : vrele(vp);
return (EXDEV);
- } else if ((error = vn_lock(vp, LK_EXCLUSIVE)) == 0) {
+ } else if (locked || (error = vn_lock(vp, LK_EXCLUSIVE)) == 0) {
error = can_hardlink(vp, td->td_ucred);
#ifdef MAC
if (error == 0)
@@ -1557,7 +1577,7 @@
V_XSLEEP | PCATCH);
if (error != 0)
return (error);
- goto again;
+ return (EAGAIN);
}
error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
VOP_UNLOCK(vp, 0);
@@ -1568,10 +1588,10 @@
vput(nd.ni_dvp);
NDFREE(&nd, NDF_ONLY_PNBUF);
vrele(vp);
- goto again;
+ return (EAGAIN);
}
}
- vrele(vp);
+ locked ? vput(vp) : vrele(vp);
return (error);
}
@@ -2486,8 +2506,6 @@
enum uio_seg pathseg, char *buf, enum uio_seg bufseg, size_t count)
{
struct vnode *vp;
- struct iovec aiov;
- struct uio auio;
struct nameidata nd;
int error;
@@ -2501,10 +2519,27 @@
return (error);
NDFREE(&nd, NDF_ONLY_PNBUF);
vp = nd.ni_vp;
+
+ error = vn_readlink(vp, buf, bufseg, count, td);
+ vput(vp);
+
+ return (error);
+}
+
+/*
+ * Helper function to readlink from a vnode
+ */
+static int
+vn_readlink(struct vnode *vp, char *buf, enum uio_seg bufseg, size_t count,
+ struct thread *td)
+{
+ struct iovec aiov;
+ struct uio auio;
+ int error;
+
#ifdef MAC
error = mac_vnode_check_readlink(td->td_ucred, vp);
if (error != 0) {
- vput(vp);
return (error);
}
#endif
@@ -2523,7 +2558,6 @@
error = VOP_READLINK(vp, &auio, td->td_ucred);
td->td_retval[0] = count - auio.uio_resid;
}
- vput(vp);
return (error);
}
@@ -4121,12 +4155,60 @@
*/
#ifndef _SYS_SYSPROTO_H_
struct lgetfh_args {
- char *fname;
+ char *fname;
fhandle_t *fhp;
};
#endif
int
sys_lgetfh(struct thread *td, struct lgetfh_args *uap)
+{
+
+ return (kern_getfhat(td, AT_SYMLINK_NOFOLLOW, AT_FDCWD, uap->fname,
+ UIO_USERSPACE, uap->fhp));
+}
+
+#ifndef _SYS_SYSPROTO_H_
+struct getfh_args {
+ char *fname;
+ fhandle_t *fhp;
+};
+#endif
+int
+sys_getfh(struct thread *td, struct getfh_args *uap)
+{
+
+ return (kern_getfhat(td, 0, AT_FDCWD, uap->fname, UIO_USERSPACE,
+ uap->fhp));
+}
+
+/*
+ * syscall for the rpc.lockd to use to translate an open descriptor into
+ * a NFS file handle.
+ *
+ * warning: do not remove the priv_check() call or this becomes one giant
+ * security hole.
+ */
+#ifndef _SYS_SYSPROTO_H_
+struct getfhat_args {
+ int fd;
+ char *path;
+ fhandle_t *fhp;
+ int flags;
+};
+#endif
+int
+sys_getfhat(struct thread *td, struct getfhat_args *uap)
+{
+
+ if ((uap->flags & ~(AT_SYMLINK_NOFOLLOW | AT_BENEATH)) != 0)
+ return (EINVAL);
+ return (kern_getfhat(td, uap->flags, uap->fd, uap->path ? uap->path : ".",
+ UIO_USERSPACE, uap->fhp));
+}
+
+static int
+kern_getfhat(struct thread *td, int flags, int fd, const char *path,
+ enum uio_seg pathseg, fhandle_t *fhp)
{
struct nameidata nd;
fhandle_t fh;
@@ -4136,52 +4218,120 @@
error = priv_check(td, PRIV_VFS_GETFH);
if (error != 0)
return (error);
- NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | AUDITVNODE1, UIO_USERSPACE,
- uap->fname, td);
+
+ NDINIT_AT(&nd, LOOKUP, ((flags & AT_SYMLINK_NOFOLLOW) != 0 ? NOFOLLOW :
+ FOLLOW) | ((flags & AT_BENEATH) != 0 ? BENEATH : 0) | LOCKLEAF |
+ AUDITVNODE1, pathseg, path, fd, td);
error = namei(&nd);
if (error != 0)
return (error);
NDFREE(&nd, NDF_ONLY_PNBUF);
vp = nd.ni_vp;
+
bzero(&fh, sizeof(fh));
fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid;
error = VOP_VPTOFH(vp, &fh.fh_fid);
vput(vp);
if (error == 0)
- error = copyout(&fh, uap->fhp, sizeof (fh));
+ error = copyout(&fh, fhp, sizeof (fh));
return (error);
}
#ifndef _SYS_SYSPROTO_H_
-struct getfh_args {
- char *fname;
+struct fhlink_args {
fhandle_t *fhp;
+ const char *to;
};
#endif
int
-sys_getfh(struct thread *td, struct getfh_args *uap)
+sys_fhlink(struct thread *td, struct fhlink_args *uap)
+{
+
+ return (kern_fhlinkat(td, AT_FDCWD, uap->to, UIO_USERSPACE, uap->fhp));
+}
+
+#ifndef _SYS_SYSPROTO_H_
+struct fhlinkat_args {
+ fhandle_t *fhp;
+ int tofd;
+ const char *to;
+};
+#endif
+int
+sys_fhlinkat(struct thread *td, struct fhlinkat_args *uap)
+{
+
+ return (kern_fhlinkat(td, uap->tofd, uap->to, UIO_USERSPACE, uap->fhp));
+}
+
+static int
+kern_fhlinkat(struct thread *td, int fd, const char *path,
+ enum uio_seg pathseg, fhandle_t *fhp)
{
- struct nameidata nd;
fhandle_t fh;
+ struct mount *mp;
struct vnode *vp;
int error;
error = priv_check(td, PRIV_VFS_GETFH);
if (error != 0)
return (error);
- NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | AUDITVNODE1, UIO_USERSPACE,
- uap->fname, td);
- error = namei(&nd);
+
+ error = copyin(fhp, &fh, sizeof(fh));
if (error != 0)
return (error);
- NDFREE(&nd, NDF_ONLY_PNBUF);
- vp = nd.ni_vp;
- bzero(&fh, sizeof(fh));
- fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid;
- error = VOP_VPTOFH(vp, &fh.fh_fid);
+
+ do {
+ bwillwrite();
+ if ((mp = vfs_busyfs(&fh.fh_fsid)) == NULL)
+ return (ESTALE);
+
+ error = VFS_FHTOVP(mp, &fh.fh_fid, LK_EXCLUSIVE, &vp);
+ vfs_unbusy(mp);
+ if (error != 0)
+ return (error);
+ } while ((error = vn_linkat(td, vp, fd, path, pathseg, true)) == EAGAIN);
+
+ return (error);
+}
+
+#ifndef _SYS_SYSPROTO_H_
+struct fhreadlink_args {
+ fhandle_t *fhp;
+ char *buf;
+ size_t bufsize;
+};
+#endif
+int
+sys_fhreadlink(struct thread *td, struct fhreadlink_args *uap)
+{
+ fhandle_t fh;
+ struct mount *mp;
+ struct vnode *vp;
+ int error;
+
+ error = priv_check(td, PRIV_VFS_GETFH);
+ if (error != 0)
+ return (error);
+
+ if (uap->bufsize > IOSIZE_MAX)
+ return (EINVAL);
+
+ error = copyin(uap->fhp, &fh, sizeof(fh));
+ if (error != 0)
+ return (error);
+
+ if ((mp = vfs_busyfs(&fh.fh_fsid)) == NULL)
+ return (ESTALE);
+
+ error = VFS_FHTOVP(mp, &fh.fh_fid, LK_EXCLUSIVE, &vp);
+ vfs_unbusy(mp);
+ if (error != 0)
+ return (error);
+
+ error = vn_readlink(vp, uap->buf, UIO_USERSPACE, uap->bufsize, td);
vput(vp);
- if (error == 0)
- error = copyout(&fh, uap->fhp, sizeof (fh));
+
return (error);
}
Index: sys/sys/mount.h
===================================================================
--- sys/sys/mount.h
+++ sys/sys/mount.h
@@ -932,11 +932,15 @@
struct stat;
__BEGIN_DECLS
+int fhlink(struct fhandle *, const char *);
+int fhlinkat(struct fhandle *, int, const char *, int);
int fhopen(const struct fhandle *, int);
+int fhreadlink(struct fhandle *, char *, size_t);
int fhstat(const struct fhandle *, struct stat *);
int fhstatfs(const struct fhandle *, struct statfs *);
int fstatfs(int, struct statfs *);
int getfh(const char *, fhandle_t *);
+int getfhat(int, char *, struct fhandle *, int);
int getfsstat(struct statfs *, long, int);
int getmntinfo(struct statfs **, int);
int lgetfh(const char *, fhandle_t *);

File Metadata

Mime Type
text/plain
Expires
Tue, Jan 14, 4:29 PM (1 h, 41 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15796628
Default Alt Text
D18359.id51358.diff (24 KB)

Event Timeline