Add new file handle system calls.
Namely, getfhat(2), fhlink(2), fhlinkat(2), fhreadlink(2). The syscalls are provided for a NFS userspace server (nfs-ganesha). Submitted by: Jack Halford <jack@gandi.net> Sponsored by: Gandi.net Tested by: pho Feedback from: brooks, markj MFC after: 1 week Differential revision: https://reviews.freebsd.org/D18359
This commit is contained in:
parent
73f834bfbb
commit
48d91fd889
@ -184,7 +184,9 @@ MAN+= abort2.2 \
|
||||
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+=ffclock.2 ffclock_getcounter.2 \
|
||||
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
|
||||
|
@ -401,6 +401,13 @@ FBSD_1.5 {
|
||||
cpuset_setdomain;
|
||||
};
|
||||
|
||||
FBSD_1.6 {
|
||||
fhlink;
|
||||
fhlinkat;
|
||||
fhreadlink;
|
||||
getfhat;
|
||||
};
|
||||
|
||||
FBSDprivate_1.0 {
|
||||
___acl_aclcheck_fd;
|
||||
__sys___acl_aclcheck_fd;
|
||||
|
268
lib/libc/sys/fhlink.2
Normal file
268
lib/libc/sys/fhlink.2
Normal file
@ -0,0 +1,268 @@
|
||||
.\" SPDX-License-Identifier: BSD-2-Clause
|
||||
.\"
|
||||
.\" Copyright (c) 2018 Gandi
|
||||
.\"
|
||||
.\" 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.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 fhlink "fhandle_t *fhp" "const char *to"
|
||||
.Ft int
|
||||
.Fn fhlinkat "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 fhlinkat
|
||||
system call is equivalent to
|
||||
.Fa fhlink
|
||||
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 fhlinkat
|
||||
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 fhlink
|
||||
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 fhlink ,
|
||||
the
|
||||
.Fn fhlinkat
|
||||
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 fhopen 2 ,
|
92
lib/libc/sys/fhreadlink.2
Normal file
92
lib/libc/sys/fhreadlink.2
Normal file
@ -0,0 +1,92 @@
|
||||
.\" SPDX-License-Identifier: BSD-2-Clause
|
||||
.\"
|
||||
.\" Copyright (c) 2018 Gandi
|
||||
.\"
|
||||
.\" 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.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 ,
|
@ -1,5 +1,6 @@
|
||||
.\" Copyright (c) 1989, 1991, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\" Copyright (c) 2018 Gandi
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
@ -28,12 +29,13 @@
|
||||
.\" @(#)getfh.2 8.1 (Berkeley) 6/9/93
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd April 14, 2011
|
||||
.Dd December 7, 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 +46,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 +55,7 @@ system call
|
||||
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,6 +67,85 @@ returns information about the link,
|
||||
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.
|
||||
.Sh RETURN VALUES
|
||||
.Rv -std
|
||||
@ -99,11 +183,49 @@ The
|
||||
.Fa fhp
|
||||
argument
|
||||
points to an invalid address.
|
||||
.It Bq Er EFAULT
|
||||
The
|
||||
.Fa path
|
||||
argument
|
||||
points to an invalid address.
|
||||
.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 ,
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -105,6 +105,14 @@ static int setutimes(struct thread *td, struct vnode *,
|
||||
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 kern_readlink_vp(struct vnode *vp, char *buf, enum uio_seg bufseg,
|
||||
size_t count, struct thread *td);
|
||||
static int kern_linkat_vp(struct thread *td, struct vnode *vp, int fd,
|
||||
const char *path, enum uio_seg segflag);
|
||||
|
||||
/*
|
||||
* Sync each mounted filesystem.
|
||||
@ -1492,28 +1500,38 @@ can_hardlink(struct vnode *vp, struct ucred *cred)
|
||||
|
||||
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 = kern_linkat_vp(td, vp, fd2, path2, segflag) == EAGAIN));
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
kern_linkat_vp(struct thread *td, struct vnode *vp, int fd, const char *path,
|
||||
enum uio_seg segflag)
|
||||
{
|
||||
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);
|
||||
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) {
|
||||
@ -1557,7 +1575,7 @@ kern_linkat(struct thread *td, int fd1, int fd2, const char *path1,
|
||||
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,7 +1586,7 @@ kern_linkat(struct thread *td, int fd1, int fd2, const char *path1,
|
||||
vput(nd.ni_dvp);
|
||||
NDFREE(&nd, NDF_ONLY_PNBUF);
|
||||
vrele(vp);
|
||||
goto again;
|
||||
return (EAGAIN);
|
||||
}
|
||||
}
|
||||
vrele(vp);
|
||||
@ -2484,8 +2502,6 @@ kern_readlinkat(struct thread *td, int fd, const char *path,
|
||||
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;
|
||||
|
||||
@ -2499,12 +2515,29 @@ kern_readlinkat(struct thread *td, int fd, const char *path,
|
||||
return (error);
|
||||
NDFREE(&nd, NDF_ONLY_PNBUF);
|
||||
vp = nd.ni_vp;
|
||||
|
||||
error = kern_readlink_vp(vp, buf, bufseg, count, td);
|
||||
vput(vp);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper function to readlink from a vnode
|
||||
*/
|
||||
static int
|
||||
kern_readlink_vp(struct vnode *vp, char *buf, enum uio_seg bufseg, size_t count,
|
||||
struct thread *td)
|
||||
{
|
||||
struct iovec aiov;
|
||||
struct uio auio;
|
||||
int error;
|
||||
|
||||
ASSERT_VOP_LOCKED(vp, "kern_readlink_vp(): vp not locked");
|
||||
#ifdef MAC
|
||||
error = mac_vnode_check_readlink(td->td_ucred, vp);
|
||||
if (error != 0) {
|
||||
vput(vp);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
}
|
||||
#endif
|
||||
if (vp->v_type != VLNK && (vp->v_vflag & VV_READLINK) == 0)
|
||||
error = EINVAL;
|
||||
@ -2521,7 +2554,6 @@ kern_readlinkat(struct thread *td, int fd, const char *path,
|
||||
error = VOP_READLINK(vp, &auio, td->td_ucred);
|
||||
td->td_retval[0] = count - auio.uio_resid;
|
||||
}
|
||||
vput(vp);
|
||||
return (error);
|
||||
}
|
||||
|
||||
@ -4119,45 +4151,60 @@ getvnode(struct thread *td, int fd, cap_rights_t *rightsp, struct file **fpp)
|
||||
*/
|
||||
#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)
|
||||
{
|
||||
struct nameidata nd;
|
||||
fhandle_t fh;
|
||||
struct vnode *vp;
|
||||
int error;
|
||||
|
||||
error = priv_check(td, PRIV_VFS_GETFH);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | AUDITVNODE1, UIO_USERSPACE,
|
||||
uap->fname, 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));
|
||||
return (error);
|
||||
return (kern_getfhat(td, AT_SYMLINK_NOFOLLOW, AT_FDCWD, uap->fname,
|
||||
UIO_USERSPACE, uap->fhp));
|
||||
}
|
||||
|
||||
#ifndef _SYS_SYSPROTO_H_
|
||||
struct getfh_args {
|
||||
char *fname;
|
||||
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;
|
||||
@ -4167,8 +4214,9 @@ sys_getfh(struct thread *td, struct getfh_args *uap)
|
||||
error = priv_check(td, PRIV_VFS_GETFH);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
NDINIT(&nd, LOOKUP, FOLLOW | 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);
|
||||
@ -4179,7 +4227,96 @@ sys_getfh(struct thread *td, struct getfh_args *uap)
|
||||
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 fhlink_args {
|
||||
fhandle_t *fhp;
|
||||
const char *to;
|
||||
};
|
||||
#endif
|
||||
int
|
||||
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)
|
||||
{
|
||||
fhandle_t fh;
|
||||
struct mount *mp;
|
||||
struct vnode *vp;
|
||||
int error;
|
||||
|
||||
error = priv_check(td, PRIV_VFS_GETFH);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
error = copyin(fhp, &fh, sizeof(fh));
|
||||
if (error != 0)
|
||||
return (error);
|
||||
do {
|
||||
bwillwrite();
|
||||
if ((mp = vfs_busyfs(&fh.fh_fsid)) == NULL)
|
||||
return (ESTALE);
|
||||
error = VFS_FHTOVP(mp, &fh.fh_fid, LK_SHARED, &vp);
|
||||
vfs_unbusy(mp);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
VOP_UNLOCK(vp, 0);
|
||||
} while ((error = kern_linkat_vp(td, vp, fd, path, pathseg)) == 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_SHARED, &vp);
|
||||
vfs_unbusy(mp);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
error = kern_readlink_vp(vp, uap->buf, UIO_USERSPACE, uap->bufsize, td);
|
||||
vput(vp);
|
||||
return (error);
|
||||
}
|
||||
|
||||
|
@ -932,11 +932,15 @@ void syncer_resume(void);
|
||||
struct stat;
|
||||
|
||||
__BEGIN_DECLS
|
||||
int fhlink(struct fhandle *, const char *);
|
||||
int fhlinkat(struct fhandle *, int, const char *);
|
||||
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 *);
|
||||
|
Loading…
Reference in New Issue
Block a user