|
Packit |
7cfc04 |
.\" Copyright (c) 2014 by Michael Kerrisk <mtk.manpages@gmail.com>
|
|
Packit |
7cfc04 |
.\"
|
|
Packit |
7cfc04 |
.\" %%%LICENSE_START(VERBATIM)
|
|
Packit |
7cfc04 |
.\" Permission is granted to make and distribute verbatim copies of this
|
|
Packit |
7cfc04 |
.\" manual provided the copyright notice and this permission notice are
|
|
Packit |
7cfc04 |
.\" preserved on all copies.
|
|
Packit |
7cfc04 |
.\"
|
|
Packit |
7cfc04 |
.\" Permission is granted to copy and distribute modified versions of this
|
|
Packit |
7cfc04 |
.\" manual under the conditions for verbatim copying, provided that the
|
|
Packit |
7cfc04 |
.\" entire resulting derived work is distributed under the terms of a
|
|
Packit |
7cfc04 |
.\" permission notice identical to this one.
|
|
Packit |
7cfc04 |
.\"
|
|
Packit |
7cfc04 |
.\" Since the Linux kernel and libraries are constantly changing, this
|
|
Packit |
7cfc04 |
.\" manual page may be incorrect or out-of-date. The author(s) assume no
|
|
Packit |
7cfc04 |
.\" responsibility for errors or omissions, or for damages resulting from
|
|
Packit |
7cfc04 |
.\" the use of the information contained herein. The author(s) may not
|
|
Packit |
7cfc04 |
.\" have taken the same level of care in the production of this manual,
|
|
Packit |
7cfc04 |
.\" which is licensed free of charge, as they might when working
|
|
Packit |
7cfc04 |
.\" professionally.
|
|
Packit |
7cfc04 |
.\"
|
|
Packit |
7cfc04 |
.\" Formatted or processed versions of this manual, if unaccompanied by
|
|
Packit |
7cfc04 |
.\" the source, must acknowledge the copyright and authors of this work.
|
|
Packit |
7cfc04 |
.\" %%%LICENSE_END
|
|
Packit |
7cfc04 |
.\"
|
|
Packit |
7cfc04 |
.TH OPEN_BY_HANDLE_AT 2 2017-09-15 "Linux" "Linux Programmer's Manual"
|
|
Packit |
7cfc04 |
.SH NAME
|
|
Packit |
7cfc04 |
name_to_handle_at, open_by_handle_at \- obtain handle
|
|
Packit |
7cfc04 |
for a pathname and open file via a handle
|
|
Packit |
7cfc04 |
.SH SYNOPSIS
|
|
Packit |
7cfc04 |
.nf
|
|
Packit |
7cfc04 |
.BR "#define _GNU_SOURCE" " /* See feature_test_macros(7) */"
|
|
Packit |
7cfc04 |
.B #include <sys/types.h>
|
|
Packit |
7cfc04 |
.B #include <sys/stat.h>
|
|
Packit |
7cfc04 |
.B #include <fcntl.h>
|
|
Packit |
7cfc04 |
.PP
|
|
Packit |
7cfc04 |
.BI "int name_to_handle_at(int " dirfd ", const char *" pathname ,
|
|
Packit |
7cfc04 |
.BI " struct file_handle *" handle ,
|
|
Packit |
7cfc04 |
.BI " int *" mount_id ", int " flags );
|
|
Packit |
7cfc04 |
.PP
|
|
Packit |
7cfc04 |
.BI "int open_by_handle_at(int " mount_fd ", struct file_handle *" handle ,
|
|
Packit |
7cfc04 |
.BI " int " flags );
|
|
Packit |
7cfc04 |
.fi
|
|
Packit |
7cfc04 |
.SH DESCRIPTION
|
|
Packit |
7cfc04 |
The
|
|
Packit |
7cfc04 |
.BR name_to_handle_at ()
|
|
Packit |
7cfc04 |
and
|
|
Packit |
7cfc04 |
.BR open_by_handle_at ()
|
|
Packit |
7cfc04 |
system calls split the functionality of
|
|
Packit |
7cfc04 |
.BR openat (2)
|
|
Packit |
7cfc04 |
into two parts:
|
|
Packit |
7cfc04 |
.BR name_to_handle_at ()
|
|
Packit |
7cfc04 |
returns an opaque handle that corresponds to a specified file;
|
|
Packit |
7cfc04 |
.BR open_by_handle_at ()
|
|
Packit |
7cfc04 |
opens the file corresponding to a handle returned by a previous call to
|
|
Packit |
7cfc04 |
.BR name_to_handle_at ()
|
|
Packit |
7cfc04 |
and returns an open file descriptor.
|
|
Packit |
7cfc04 |
.\"
|
|
Packit |
7cfc04 |
.\"
|
|
Packit |
7cfc04 |
.SS name_to_handle_at()
|
|
Packit |
7cfc04 |
The
|
|
Packit |
7cfc04 |
.BR name_to_handle_at ()
|
|
Packit |
7cfc04 |
system call returns a file handle and a mount ID corresponding to
|
|
Packit |
7cfc04 |
the file specified by the
|
|
Packit |
7cfc04 |
.IR dirfd
|
|
Packit |
7cfc04 |
and
|
|
Packit |
7cfc04 |
.IR pathname
|
|
Packit |
7cfc04 |
arguments.
|
|
Packit |
7cfc04 |
The file handle is returned via the argument
|
|
Packit |
7cfc04 |
.IR handle ,
|
|
Packit |
7cfc04 |
which is a pointer to a structure of the following form:
|
|
Packit |
7cfc04 |
.PP
|
|
Packit |
7cfc04 |
.in +4n
|
|
Packit |
7cfc04 |
.EX
|
|
Packit |
7cfc04 |
struct file_handle {
|
|
Packit |
7cfc04 |
unsigned int handle_bytes; /* Size of f_handle [in, out] */
|
|
Packit |
7cfc04 |
int handle_type; /* Handle type [out] */
|
|
Packit |
7cfc04 |
unsigned char f_handle[0]; /* File identifier (sized by
|
|
Packit |
7cfc04 |
caller) [out] */
|
|
Packit |
7cfc04 |
};
|
|
Packit |
7cfc04 |
.EE
|
|
Packit |
7cfc04 |
.in
|
|
Packit |
7cfc04 |
.PP
|
|
Packit |
7cfc04 |
It is the caller's responsibility to allocate the structure
|
|
Packit |
7cfc04 |
with a size large enough to hold the handle returned in
|
|
Packit |
7cfc04 |
.IR f_handle .
|
|
Packit |
7cfc04 |
Before the call, the
|
|
Packit |
7cfc04 |
.IR handle_bytes
|
|
Packit |
7cfc04 |
field should be initialized to contain the allocated size for
|
|
Packit |
7cfc04 |
.IR f_handle .
|
|
Packit |
7cfc04 |
(The constant
|
|
Packit |
7cfc04 |
.BR MAX_HANDLE_SZ ,
|
|
Packit |
7cfc04 |
defined in
|
|
Packit |
7cfc04 |
.IR <fcntl.h> ,
|
|
Packit |
7cfc04 |
specifies the maximum expected size for a file handle.
|
|
Packit |
7cfc04 |
It is not a
|
|
Packit |
7cfc04 |
guaranteed upper limit as future filesystems may require more space.)
|
|
Packit |
7cfc04 |
Upon successful return, the
|
|
Packit |
7cfc04 |
.IR handle_bytes
|
|
Packit |
7cfc04 |
field is updated to contain the number of bytes actually written to
|
|
Packit |
7cfc04 |
.IR f_handle .
|
|
Packit |
7cfc04 |
.PP
|
|
Packit |
7cfc04 |
The caller can discover the required size for the
|
|
Packit |
7cfc04 |
.I file_handle
|
|
Packit |
7cfc04 |
structure by making a call in which
|
|
Packit |
7cfc04 |
.IR handle->handle_bytes
|
|
Packit |
7cfc04 |
is zero;
|
|
Packit |
7cfc04 |
in this case, the call fails with the error
|
|
Packit |
7cfc04 |
.BR EOVERFLOW
|
|
Packit |
7cfc04 |
and
|
|
Packit |
7cfc04 |
.IR handle->handle_bytes
|
|
Packit |
7cfc04 |
is set to indicate the required size;
|
|
Packit |
7cfc04 |
the caller can then use this information to allocate a structure
|
|
Packit |
7cfc04 |
of the correct size (see EXAMPLE below).
|
|
Packit |
7cfc04 |
Some care is needed here as
|
|
Packit |
7cfc04 |
.BR EOVERFLOW
|
|
Packit |
7cfc04 |
can also indicate that no file handle is available for this particular
|
|
Packit |
7cfc04 |
name in a filesystem which does normally support file-handle lookup.
|
|
Packit |
7cfc04 |
This case can be detected when the
|
|
Packit |
7cfc04 |
.B EOVERFLOW
|
|
Packit |
7cfc04 |
error is returned without
|
|
Packit |
7cfc04 |
.I handle_bytes
|
|
Packit |
7cfc04 |
being increased.
|
|
Packit |
7cfc04 |
.PP
|
|
Packit |
7cfc04 |
Other than the use of the
|
|
Packit |
7cfc04 |
.IR handle_bytes
|
|
Packit |
7cfc04 |
field, the caller should treat the
|
|
Packit |
7cfc04 |
.IR file_handle
|
|
Packit |
7cfc04 |
structure as an opaque data type: the
|
|
Packit |
7cfc04 |
.IR handle_type
|
|
Packit |
7cfc04 |
and
|
|
Packit |
7cfc04 |
.IR f_handle
|
|
Packit |
7cfc04 |
fields are needed only by a subsequent call to
|
|
Packit |
7cfc04 |
.BR open_by_handle_at ().
|
|
Packit |
7cfc04 |
.PP
|
|
Packit |
7cfc04 |
The
|
|
Packit |
7cfc04 |
.I flags
|
|
Packit |
7cfc04 |
argument is a bit mask constructed by ORing together zero or more of
|
|
Packit |
7cfc04 |
.BR AT_EMPTY_PATH
|
|
Packit |
7cfc04 |
and
|
|
Packit |
7cfc04 |
.BR AT_SYMLINK_FOLLOW ,
|
|
Packit |
7cfc04 |
described below.
|
|
Packit |
7cfc04 |
.PP
|
|
Packit |
7cfc04 |
Together, the
|
|
Packit |
7cfc04 |
.I pathname
|
|
Packit |
7cfc04 |
and
|
|
Packit |
7cfc04 |
.I dirfd
|
|
Packit |
7cfc04 |
arguments identify the file for which a handle is to be obtained.
|
|
Packit |
7cfc04 |
There are four distinct cases:
|
|
Packit |
7cfc04 |
.IP * 3
|
|
Packit |
7cfc04 |
If
|
|
Packit |
7cfc04 |
.I pathname
|
|
Packit |
7cfc04 |
is a nonempty string containing an absolute pathname,
|
|
Packit |
7cfc04 |
then a handle is returned for the file referred to by that pathname.
|
|
Packit |
7cfc04 |
In this case,
|
|
Packit |
7cfc04 |
.IR dirfd
|
|
Packit |
7cfc04 |
is ignored.
|
|
Packit |
7cfc04 |
.IP *
|
|
Packit |
7cfc04 |
If
|
|
Packit |
7cfc04 |
.I pathname
|
|
Packit |
7cfc04 |
is a nonempty string containing a relative pathname and
|
|
Packit |
7cfc04 |
.IR dirfd
|
|
Packit |
7cfc04 |
has the special value
|
|
Packit |
7cfc04 |
.BR AT_FDCWD ,
|
|
Packit |
7cfc04 |
then
|
|
Packit |
7cfc04 |
.I pathname
|
|
Packit |
7cfc04 |
is interpreted relative to the current working directory of the caller,
|
|
Packit |
7cfc04 |
and a handle is returned for the file to which it refers.
|
|
Packit |
7cfc04 |
.IP *
|
|
Packit |
7cfc04 |
If
|
|
Packit |
7cfc04 |
.I pathname
|
|
Packit |
7cfc04 |
is a nonempty string containing a relative pathname and
|
|
Packit |
7cfc04 |
.IR dirfd
|
|
Packit |
7cfc04 |
is a file descriptor referring to a directory, then
|
|
Packit |
7cfc04 |
.I pathname
|
|
Packit |
7cfc04 |
is interpreted relative to the directory referred to by
|
|
Packit |
7cfc04 |
.IR dirfd ,
|
|
Packit |
7cfc04 |
and a handle is returned for the file to which it refers.
|
|
Packit |
7cfc04 |
(See
|
|
Packit |
7cfc04 |
.BR openat (2)
|
|
Packit |
7cfc04 |
for an explanation of why "directory file descriptors" are useful.)
|
|
Packit |
7cfc04 |
.IP *
|
|
Packit |
7cfc04 |
If
|
|
Packit |
7cfc04 |
.I pathname
|
|
Packit |
7cfc04 |
is an empty string and
|
|
Packit |
7cfc04 |
.I flags
|
|
Packit |
7cfc04 |
specifies the value
|
|
Packit |
7cfc04 |
.BR AT_EMPTY_PATH ,
|
|
Packit |
7cfc04 |
then
|
|
Packit |
7cfc04 |
.IR dirfd
|
|
Packit |
7cfc04 |
can be an open file descriptor referring to any type of file,
|
|
Packit |
7cfc04 |
or
|
|
Packit |
7cfc04 |
.BR AT_FDCWD ,
|
|
Packit |
7cfc04 |
meaning the current working directory,
|
|
Packit |
7cfc04 |
and a handle is returned for the file to which it refers.
|
|
Packit |
7cfc04 |
.PP
|
|
Packit |
7cfc04 |
The
|
|
Packit |
7cfc04 |
.I mount_id
|
|
Packit |
7cfc04 |
argument returns an identifier for the filesystem
|
|
Packit |
7cfc04 |
mount that corresponds to
|
|
Packit |
7cfc04 |
.IR pathname .
|
|
Packit |
7cfc04 |
This corresponds to the first field in one of the records in
|
|
Packit |
7cfc04 |
.IR /proc/self/mountinfo .
|
|
Packit |
7cfc04 |
Opening the pathname in the fifth field of that record yields a file
|
|
Packit |
7cfc04 |
descriptor for the mount point;
|
|
Packit |
7cfc04 |
that file descriptor can be used in a subsequent call to
|
|
Packit |
7cfc04 |
.BR open_by_handle_at ().
|
|
Packit |
7cfc04 |
.I mount_id
|
|
Packit |
7cfc04 |
is returned both for a successful call and for a call that results
|
|
Packit |
7cfc04 |
in the error
|
|
Packit |
7cfc04 |
.BR EOVERFLOW .
|
|
Packit |
7cfc04 |
.PP
|
|
Packit |
7cfc04 |
By default,
|
|
Packit |
7cfc04 |
.BR name_to_handle_at ()
|
|
Packit |
7cfc04 |
does not dereference
|
|
Packit |
7cfc04 |
.I pathname
|
|
Packit |
7cfc04 |
if it is a symbolic link, and thus returns a handle for the link itself.
|
|
Packit |
7cfc04 |
If
|
|
Packit |
7cfc04 |
.B AT_SYMLINK_FOLLOW
|
|
Packit |
7cfc04 |
is specified in
|
|
Packit |
7cfc04 |
.IR flags ,
|
|
Packit |
7cfc04 |
.I pathname
|
|
Packit |
7cfc04 |
is dereferenced if it is a symbolic link
|
|
Packit |
7cfc04 |
(so that the call returns a handle for the file referred to by the link).
|
|
Packit |
7cfc04 |
.PP
|
|
Packit |
7cfc04 |
.BR name_to_handle_at ()
|
|
Packit |
7cfc04 |
does not trigger a mount when the final component of the path is an
|
|
Packit |
7cfc04 |
automount point.
|
|
Packit |
7cfc04 |
When a filesystem supports both file handles and
|
|
Packit |
7cfc04 |
automount points, a
|
|
Packit |
7cfc04 |
.BR name_to_handle_at ()
|
|
Packit |
7cfc04 |
call on an automount point will return with error
|
|
Packit |
7cfc04 |
.BR EOVERFLOW
|
|
Packit |
7cfc04 |
without having increased
|
|
Packit |
7cfc04 |
.IR handle_bytes .
|
|
Packit |
7cfc04 |
This can happen since Linux 4.13
|
|
Packit |
7cfc04 |
.\" commit 20fa19027286983ab2734b5910c4a687436e0c31
|
|
Packit |
7cfc04 |
with NFS when accessing a directory
|
|
Packit |
7cfc04 |
which is on a separate filesystem on the server.
|
|
Packit |
7cfc04 |
In this case, the automount can be triggered by adding a "/" to the end
|
|
Packit |
7cfc04 |
of the path.
|
|
Packit |
7cfc04 |
.SS open_by_handle_at()
|
|
Packit |
7cfc04 |
The
|
|
Packit |
7cfc04 |
.BR open_by_handle_at ()
|
|
Packit |
7cfc04 |
system call opens the file referred to by
|
|
Packit |
7cfc04 |
.IR handle ,
|
|
Packit |
7cfc04 |
a file handle returned by a previous call to
|
|
Packit |
7cfc04 |
.BR name_to_handle_at ().
|
|
Packit |
7cfc04 |
.PP
|
|
Packit |
7cfc04 |
The
|
|
Packit |
7cfc04 |
.IR mount_fd
|
|
Packit |
7cfc04 |
argument is a file descriptor for any object (file, directory, etc.)
|
|
Packit |
7cfc04 |
in the mounted filesystem with respect to which
|
|
Packit |
7cfc04 |
.IR handle
|
|
Packit |
7cfc04 |
should be interpreted.
|
|
Packit |
7cfc04 |
The special value
|
|
Packit |
7cfc04 |
.B AT_FDCWD
|
|
Packit |
7cfc04 |
can be specified, meaning the current working directory of the caller.
|
|
Packit |
7cfc04 |
.PP
|
|
Packit |
7cfc04 |
The
|
|
Packit |
7cfc04 |
.I flags
|
|
Packit |
7cfc04 |
argument
|
|
Packit |
7cfc04 |
is as for
|
|
Packit |
7cfc04 |
.BR open (2).
|
|
Packit |
7cfc04 |
If
|
|
Packit |
7cfc04 |
.I handle
|
|
Packit |
7cfc04 |
refers to a symbolic link, the caller must specify the
|
|
Packit |
7cfc04 |
.B O_PATH
|
|
Packit |
7cfc04 |
flag, and the symbolic link is not dereferenced; the
|
|
Packit |
7cfc04 |
.B O_NOFOLLOW
|
|
Packit |
7cfc04 |
flag, if specified, is ignored.
|
|
Packit |
7cfc04 |
.PP
|
|
Packit |
7cfc04 |
The caller must have the
|
|
Packit |
7cfc04 |
.B CAP_DAC_READ_SEARCH
|
|
Packit |
7cfc04 |
capability to invoke
|
|
Packit |
7cfc04 |
.BR open_by_handle_at ().
|
|
Packit |
7cfc04 |
.SH RETURN VALUE
|
|
Packit |
7cfc04 |
On success,
|
|
Packit |
7cfc04 |
.BR name_to_handle_at ()
|
|
Packit |
7cfc04 |
returns 0,
|
|
Packit |
7cfc04 |
and
|
|
Packit |
7cfc04 |
.BR open_by_handle_at ()
|
|
Packit |
7cfc04 |
returns a nonnegative file descriptor.
|
|
Packit |
7cfc04 |
.PP
|
|
Packit |
7cfc04 |
In the event of an error, both system calls return \-1 and set
|
|
Packit |
7cfc04 |
.I errno
|
|
Packit |
7cfc04 |
to indicate the cause of the error.
|
|
Packit |
7cfc04 |
.SH ERRORS
|
|
Packit |
7cfc04 |
.BR name_to_handle_at ()
|
|
Packit |
7cfc04 |
and
|
|
Packit |
7cfc04 |
.BR open_by_handle_at ()
|
|
Packit |
7cfc04 |
can fail for the same errors as
|
|
Packit |
7cfc04 |
.BR openat (2).
|
|
Packit |
7cfc04 |
In addition, they can fail with the errors noted below.
|
|
Packit |
7cfc04 |
.PP
|
|
Packit |
7cfc04 |
.BR name_to_handle_at ()
|
|
Packit |
7cfc04 |
can fail with the following errors:
|
|
Packit |
7cfc04 |
.TP
|
|
Packit |
7cfc04 |
.B EFAULT
|
|
Packit |
7cfc04 |
.IR pathname ,
|
|
Packit |
7cfc04 |
.IR mount_id ,
|
|
Packit |
7cfc04 |
or
|
|
Packit |
7cfc04 |
.IR handle
|
|
Packit |
7cfc04 |
points outside your accessible address space.
|
|
Packit |
7cfc04 |
.TP
|
|
Packit |
7cfc04 |
.B EINVAL
|
|
Packit |
7cfc04 |
.I flags
|
|
Packit |
7cfc04 |
includes an invalid bit value.
|
|
Packit |
7cfc04 |
.TP
|
|
Packit |
7cfc04 |
.B EINVAL
|
|
Packit |
7cfc04 |
.IR handle\->handle_bytes
|
|
Packit |
7cfc04 |
is greater than
|
|
Packit |
7cfc04 |
.BR MAX_HANDLE_SZ .
|
|
Packit |
7cfc04 |
.TP
|
|
Packit |
7cfc04 |
.B ENOENT
|
|
Packit |
7cfc04 |
.I pathname
|
|
Packit |
7cfc04 |
is an empty string, but
|
|
Packit |
7cfc04 |
.BR AT_EMPTY_PATH
|
|
Packit |
7cfc04 |
was not specified in
|
|
Packit |
7cfc04 |
.IR flags .
|
|
Packit |
7cfc04 |
.TP
|
|
Packit |
7cfc04 |
.B ENOTDIR
|
|
Packit |
7cfc04 |
The file descriptor supplied in
|
|
Packit |
7cfc04 |
.I dirfd
|
|
Packit |
7cfc04 |
does not refer to a directory,
|
|
Packit |
7cfc04 |
and it is not the case that both
|
|
Packit |
7cfc04 |
.I flags
|
|
Packit |
7cfc04 |
includes
|
|
Packit |
7cfc04 |
.BR AT_EMPTY_PATH
|
|
Packit |
7cfc04 |
and
|
|
Packit |
7cfc04 |
.I pathname
|
|
Packit |
7cfc04 |
is an empty string.
|
|
Packit |
7cfc04 |
.TP
|
|
Packit |
7cfc04 |
.B EOPNOTSUPP
|
|
Packit |
7cfc04 |
The filesystem does not support decoding of a pathname to a file handle.
|
|
Packit |
7cfc04 |
.TP
|
|
Packit |
7cfc04 |
.B EOVERFLOW
|
|
Packit |
7cfc04 |
The
|
|
Packit |
7cfc04 |
.I handle->handle_bytes
|
|
Packit |
7cfc04 |
value passed into the call was too small.
|
|
Packit |
7cfc04 |
When this error occurs,
|
|
Packit |
7cfc04 |
.I handle->handle_bytes
|
|
Packit |
7cfc04 |
is updated to indicate the required size for the handle.
|
|
Packit |
7cfc04 |
.\"
|
|
Packit |
7cfc04 |
.\"
|
|
Packit |
7cfc04 |
.PP
|
|
Packit |
7cfc04 |
.BR open_by_handle_at ()
|
|
Packit |
7cfc04 |
can fail with the following errors:
|
|
Packit |
7cfc04 |
.TP
|
|
Packit |
7cfc04 |
.B EBADF
|
|
Packit |
7cfc04 |
.IR mount_fd
|
|
Packit |
7cfc04 |
is not an open file descriptor.
|
|
Packit |
7cfc04 |
.TP
|
|
Packit |
7cfc04 |
.B EFAULT
|
|
Packit |
7cfc04 |
.IR handle
|
|
Packit |
7cfc04 |
points outside your accessible address space.
|
|
Packit |
7cfc04 |
.TP
|
|
Packit |
7cfc04 |
.B EINVAL
|
|
Packit |
7cfc04 |
.I handle->handle_bytes
|
|
Packit |
7cfc04 |
is greater than
|
|
Packit |
7cfc04 |
.BR MAX_HANDLE_SZ
|
|
Packit |
7cfc04 |
or is equal to zero.
|
|
Packit |
7cfc04 |
.TP
|
|
Packit |
7cfc04 |
.B ELOOP
|
|
Packit |
7cfc04 |
.I handle
|
|
Packit |
7cfc04 |
refers to a symbolic link, but
|
|
Packit |
7cfc04 |
.B O_PATH
|
|
Packit |
7cfc04 |
was not specified in
|
|
Packit |
7cfc04 |
.IR flags .
|
|
Packit |
7cfc04 |
.TP
|
|
Packit |
7cfc04 |
.B EPERM
|
|
Packit |
7cfc04 |
The caller does not have the
|
|
Packit |
7cfc04 |
.BR CAP_DAC_READ_SEARCH
|
|
Packit |
7cfc04 |
capability.
|
|
Packit |
7cfc04 |
.TP
|
|
Packit |
7cfc04 |
.B ESTALE
|
|
Packit |
7cfc04 |
The specified
|
|
Packit |
7cfc04 |
.I handle
|
|
Packit |
7cfc04 |
is not valid.
|
|
Packit |
7cfc04 |
This error will occur if, for example, the file has been deleted.
|
|
Packit |
7cfc04 |
.SH VERSIONS
|
|
Packit |
7cfc04 |
These system calls first appeared in Linux 2.6.39.
|
|
Packit |
7cfc04 |
Library support is provided in glibc since version 2.14.
|
|
Packit |
7cfc04 |
.SH CONFORMING TO
|
|
Packit |
7cfc04 |
These system calls are nonstandard Linux extensions.
|
|
Packit |
7cfc04 |
.PP
|
|
Packit |
7cfc04 |
FreeBSD has a broadly similar pair of system calls in the form of
|
|
Packit |
7cfc04 |
.BR getfh ()
|
|
Packit |
7cfc04 |
and
|
|
Packit |
7cfc04 |
.BR openfh ().
|
|
Packit |
7cfc04 |
.SH NOTES
|
|
Packit |
7cfc04 |
A file handle can be generated in one process using
|
|
Packit |
7cfc04 |
.BR name_to_handle_at ()
|
|
Packit |
7cfc04 |
and later used in a different process that calls
|
|
Packit |
7cfc04 |
.BR open_by_handle_at ().
|
|
Packit |
7cfc04 |
.PP
|
|
Packit |
7cfc04 |
Some filesystem don't support the translation of pathnames to
|
|
Packit |
7cfc04 |
file handles, for example,
|
|
Packit |
7cfc04 |
.IR /proc ,
|
|
Packit |
7cfc04 |
.IR /sys ,
|
|
Packit |
7cfc04 |
and various network filesystems.
|
|
Packit |
7cfc04 |
.PP
|
|
Packit |
7cfc04 |
A file handle may become invalid ("stale") if a file is deleted,
|
|
Packit |
7cfc04 |
or for other filesystem-specific reasons.
|
|
Packit |
7cfc04 |
Invalid handles are notified by an
|
|
Packit |
7cfc04 |
.B ESTALE
|
|
Packit |
7cfc04 |
error from
|
|
Packit |
7cfc04 |
.BR open_by_handle_at ().
|
|
Packit |
7cfc04 |
.PP
|
|
Packit |
7cfc04 |
These system calls are designed for use by user-space file servers.
|
|
Packit |
7cfc04 |
For example, a user-space NFS server might generate a file handle
|
|
Packit |
7cfc04 |
and pass it to an NFS client.
|
|
Packit |
7cfc04 |
Later, when the client wants to open the file,
|
|
Packit |
7cfc04 |
it could pass the handle back to the server.
|
|
Packit |
7cfc04 |
.\" https://lwn.net/Articles/375888/
|
|
Packit |
7cfc04 |
.\" "Open by handle" - Jonathan Corbet, 2010-02-23
|
|
Packit |
7cfc04 |
This sort of functionality allows a user-space file server to operate in
|
|
Packit |
7cfc04 |
a stateless fashion with respect to the files it serves.
|
|
Packit |
7cfc04 |
.PP
|
|
Packit |
7cfc04 |
If
|
|
Packit |
7cfc04 |
.I pathname
|
|
Packit |
7cfc04 |
refers to a symbolic link and
|
|
Packit |
7cfc04 |
.IR flags
|
|
Packit |
7cfc04 |
does not specify
|
|
Packit |
7cfc04 |
.BR AT_SYMLINK_FOLLOW ,
|
|
Packit |
7cfc04 |
then
|
|
Packit |
7cfc04 |
.BR name_to_handle_at ()
|
|
Packit |
7cfc04 |
returns a handle for the link (rather than the file to which it refers).
|
|
Packit |
7cfc04 |
.\" commit bcda76524cd1fa32af748536f27f674a13e56700
|
|
Packit |
7cfc04 |
The process receiving the handle can later perform operations
|
|
Packit |
7cfc04 |
on the symbolic link by converting the handle to a file descriptor using
|
|
Packit |
7cfc04 |
.BR open_by_handle_at ()
|
|
Packit |
7cfc04 |
with the
|
|
Packit |
7cfc04 |
.BR O_PATH
|
|
Packit |
7cfc04 |
flag, and then passing the file descriptor as the
|
|
Packit |
7cfc04 |
.IR dirfd
|
|
Packit |
7cfc04 |
argument in system calls such as
|
|
Packit |
7cfc04 |
.BR readlinkat (2)
|
|
Packit |
7cfc04 |
and
|
|
Packit |
7cfc04 |
.BR fchownat (2).
|
|
Packit |
7cfc04 |
.SS Obtaining a persistent filesystem ID
|
|
Packit |
7cfc04 |
The mount IDs in
|
|
Packit |
7cfc04 |
.IR /proc/self/mountinfo
|
|
Packit |
7cfc04 |
can be reused as filesystems are unmounted and mounted.
|
|
Packit |
7cfc04 |
Therefore, the mount ID returned by
|
|
Packit |
7cfc04 |
.BR name_to_handle_at ()
|
|
Packit |
7cfc04 |
(in
|
|
Packit |
7cfc04 |
.IR *mount_id )
|
|
Packit |
7cfc04 |
should not be treated as a persistent identifier
|
|
Packit |
7cfc04 |
for the corresponding mounted filesystem.
|
|
Packit |
7cfc04 |
However, an application can use the information in the
|
|
Packit |
7cfc04 |
.I mountinfo
|
|
Packit |
7cfc04 |
record that corresponds to the mount ID
|
|
Packit |
7cfc04 |
to derive a persistent identifier.
|
|
Packit |
7cfc04 |
.PP
|
|
Packit |
7cfc04 |
For example, one can use the device name in the fifth field of the
|
|
Packit |
7cfc04 |
.I mountinfo
|
|
Packit |
7cfc04 |
record to search for the corresponding device UUID via the symbolic links in
|
|
Packit |
7cfc04 |
.IR /dev/disks/by-uuid .
|
|
Packit |
7cfc04 |
(A more comfortable way of obtaining the UUID is to use the
|
|
Packit |
7cfc04 |
.\" e.g., http://stackoverflow.com/questions/6748429/using-libblkid-to-find-uuid-of-a-partition
|
|
Packit |
7cfc04 |
.BR libblkid (3)
|
|
Packit |
7cfc04 |
library.)
|
|
Packit |
7cfc04 |
That process can then be reversed,
|
|
Packit |
7cfc04 |
using the UUID to look up the device name,
|
|
Packit |
7cfc04 |
and then obtaining the corresponding mount point,
|
|
Packit |
7cfc04 |
in order to produce the
|
|
Packit |
7cfc04 |
.IR mount_fd
|
|
Packit |
7cfc04 |
argument used by
|
|
Packit |
7cfc04 |
.BR open_by_handle_at ().
|
|
Packit |
7cfc04 |
.SH EXAMPLE
|
|
Packit |
7cfc04 |
The two programs below demonstrate the use of
|
|
Packit |
7cfc04 |
.BR name_to_handle_at ()
|
|
Packit |
7cfc04 |
and
|
|
Packit |
7cfc04 |
.BR open_by_handle_at ().
|
|
Packit |
7cfc04 |
The first program
|
|
Packit |
7cfc04 |
.RI ( t_name_to_handle_at.c )
|
|
Packit |
7cfc04 |
uses
|
|
Packit |
7cfc04 |
.BR name_to_handle_at ()
|
|
Packit |
7cfc04 |
to obtain the file handle and mount ID
|
|
Packit |
7cfc04 |
for the file specified in its command-line argument;
|
|
Packit |
7cfc04 |
the handle and mount ID are written to standard output.
|
|
Packit |
7cfc04 |
.PP
|
|
Packit |
7cfc04 |
The second program
|
|
Packit |
7cfc04 |
.RI ( t_open_by_handle_at.c )
|
|
Packit |
7cfc04 |
reads a mount ID and file handle from standard input.
|
|
Packit |
7cfc04 |
The program then employs
|
|
Packit |
7cfc04 |
.BR open_by_handle_at ()
|
|
Packit |
7cfc04 |
to open the file using that handle.
|
|
Packit |
7cfc04 |
If an optional command-line argument is supplied, then the
|
|
Packit |
7cfc04 |
.IR mount_fd
|
|
Packit |
7cfc04 |
argument for
|
|
Packit |
7cfc04 |
.BR open_by_handle_at ()
|
|
Packit |
7cfc04 |
is obtained by opening the directory named in that argument.
|
|
Packit |
7cfc04 |
Otherwise,
|
|
Packit |
7cfc04 |
.IR mount_fd
|
|
Packit |
7cfc04 |
is obtained by scanning
|
|
Packit |
7cfc04 |
.IR /proc/self/mountinfo
|
|
Packit |
7cfc04 |
to find a record whose mount ID matches the mount ID
|
|
Packit |
7cfc04 |
read from standard input,
|
|
Packit |
7cfc04 |
and the mount directory specified in that record is opened.
|
|
Packit |
7cfc04 |
(These programs do not deal with the fact that mount IDs are not persistent.)
|
|
Packit |
7cfc04 |
.PP
|
|
Packit |
7cfc04 |
The following shell session demonstrates the use of these two programs:
|
|
Packit |
7cfc04 |
.PP
|
|
Packit |
7cfc04 |
.in +4n
|
|
Packit |
7cfc04 |
.EX
|
|
Packit |
7cfc04 |
$ \fBecho 'Can you please think about it?' > cecilia.txt\fP
|
|
Packit |
7cfc04 |
$ \fB./t_name_to_handle_at cecilia.txt > fh\fP
|
|
Packit |
7cfc04 |
$ \fB./t_open_by_handle_at < fh\fP
|
|
Packit |
7cfc04 |
open_by_handle_at: Operation not permitted
|
|
Packit |
7cfc04 |
$ \fBsudo ./t_open_by_handle_at < fh\fP # Need CAP_SYS_ADMIN
|
|
Packit |
7cfc04 |
Read 31 bytes
|
|
Packit |
7cfc04 |
$ \fBrm cecilia.txt\fP
|
|
Packit |
7cfc04 |
.EE
|
|
Packit |
7cfc04 |
.in
|
|
Packit |
7cfc04 |
.PP
|
|
Packit |
7cfc04 |
Now we delete and (quickly) re-create the file so that
|
|
Packit |
7cfc04 |
it has the same content and (by chance) the same inode.
|
|
Packit |
7cfc04 |
Nevertheless,
|
|
Packit |
7cfc04 |
.BR open_by_handle_at ()
|
|
Packit |
7cfc04 |
.\" Christoph Hellwig: That's why the file handles contain a generation
|
|
Packit |
7cfc04 |
.\" counter that gets incremented in this case.
|
|
Packit |
7cfc04 |
recognizes that the original file referred to by the file handle
|
|
Packit |
7cfc04 |
no longer exists.
|
|
Packit |
7cfc04 |
.PP
|
|
Packit |
7cfc04 |
.in +4n
|
|
Packit |
7cfc04 |
.EX
|
|
Packit |
7cfc04 |
$ \fBstat \-\-printf="%i\\n" cecilia.txt\fP # Display inode number
|
|
Packit |
7cfc04 |
4072121
|
|
Packit |
7cfc04 |
$ \fBrm cecilia.txt\fP
|
|
Packit |
7cfc04 |
$ \fBecho 'Can you please think about it?' > cecilia.txt\fP
|
|
Packit |
7cfc04 |
$ \fBstat \-\-printf="%i\\n" cecilia.txt\fP # Check inode number
|
|
Packit |
7cfc04 |
4072121
|
|
Packit |
7cfc04 |
$ \fBsudo ./t_open_by_handle_at < fh\fP
|
|
Packit |
7cfc04 |
open_by_handle_at: Stale NFS file handle
|
|
Packit |
7cfc04 |
.EE
|
|
Packit |
7cfc04 |
.in
|
|
Packit |
7cfc04 |
.SS Program source: t_name_to_handle_at.c
|
|
Packit |
7cfc04 |
\&
|
|
Packit |
7cfc04 |
.EX
|
|
Packit |
7cfc04 |
#define _GNU_SOURCE
|
|
Packit |
7cfc04 |
#include <sys/types.h>
|
|
Packit |
7cfc04 |
#include <sys/stat.h>
|
|
Packit |
7cfc04 |
#include <fcntl.h>
|
|
Packit |
7cfc04 |
#include <stdio.h>
|
|
Packit |
7cfc04 |
#include <stdlib.h>
|
|
Packit |
7cfc04 |
#include <unistd.h>
|
|
Packit |
7cfc04 |
#include <errno.h>
|
|
Packit |
7cfc04 |
#include <string.h>
|
|
Packit |
7cfc04 |
|
|
Packit |
7cfc04 |
#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \\
|
|
Packit |
7cfc04 |
} while (0)
|
|
Packit |
7cfc04 |
|
|
Packit |
7cfc04 |
int
|
|
Packit |
7cfc04 |
main(int argc, char *argv[])
|
|
Packit |
7cfc04 |
{
|
|
Packit |
7cfc04 |
struct file_handle *fhp;
|
|
Packit |
7cfc04 |
int mount_id, fhsize, flags, dirfd, j;
|
|
Packit |
7cfc04 |
char *pathname;
|
|
Packit |
7cfc04 |
|
|
Packit |
7cfc04 |
if (argc != 2) {
|
|
Packit |
7cfc04 |
fprintf(stderr, "Usage: %s pathname\\n", argv[0]);
|
|
Packit |
7cfc04 |
exit(EXIT_FAILURE);
|
|
Packit |
7cfc04 |
}
|
|
Packit |
7cfc04 |
|
|
Packit |
7cfc04 |
pathname = argv[1];
|
|
Packit |
7cfc04 |
|
|
Packit |
7cfc04 |
/* Allocate file_handle structure */
|
|
Packit |
7cfc04 |
|
|
Packit |
7cfc04 |
fhsize = sizeof(*fhp);
|
|
Packit |
7cfc04 |
fhp = malloc(fhsize);
|
|
Packit |
7cfc04 |
if (fhp == NULL)
|
|
Packit |
7cfc04 |
errExit("malloc");
|
|
Packit |
7cfc04 |
|
|
Packit |
7cfc04 |
/* Make an initial call to name_to_handle_at() to discover
|
|
Packit |
7cfc04 |
the size required for file handle */
|
|
Packit |
7cfc04 |
|
|
Packit |
7cfc04 |
dirfd = AT_FDCWD; /* For name_to_handle_at() calls */
|
|
Packit |
7cfc04 |
flags = 0; /* For name_to_handle_at() calls */
|
|
Packit |
7cfc04 |
fhp\->handle_bytes = 0;
|
|
Packit |
7cfc04 |
if (name_to_handle_at(dirfd, pathname, fhp,
|
|
Packit |
7cfc04 |
&mount_id, flags) != \-1 || errno != EOVERFLOW) {
|
|
Packit |
7cfc04 |
fprintf(stderr, "Unexpected result from name_to_handle_at()\\n");
|
|
Packit |
7cfc04 |
exit(EXIT_FAILURE);
|
|
Packit |
7cfc04 |
}
|
|
Packit |
7cfc04 |
|
|
Packit |
7cfc04 |
/* Reallocate file_handle structure with correct size */
|
|
Packit |
7cfc04 |
|
|
Packit |
7cfc04 |
fhsize = sizeof(struct file_handle) + fhp\->handle_bytes;
|
|
Packit |
7cfc04 |
fhp = realloc(fhp, fhsize); /* Copies fhp\->handle_bytes */
|
|
Packit |
7cfc04 |
if (fhp == NULL)
|
|
Packit |
7cfc04 |
errExit("realloc");
|
|
Packit |
7cfc04 |
|
|
Packit |
7cfc04 |
/* Get file handle from pathname supplied on command line */
|
|
Packit |
7cfc04 |
|
|
Packit |
7cfc04 |
if (name_to_handle_at(dirfd, pathname, fhp, &mount_id, flags) == \-1)
|
|
Packit |
7cfc04 |
errExit("name_to_handle_at");
|
|
Packit |
7cfc04 |
|
|
Packit |
7cfc04 |
/* Write mount ID, file handle size, and file handle to stdout,
|
|
Packit |
7cfc04 |
for later reuse by t_open_by_handle_at.c */
|
|
Packit |
7cfc04 |
|
|
Packit |
7cfc04 |
printf("%d\\n", mount_id);
|
|
Packit |
7cfc04 |
printf("%d %d ", fhp\->handle_bytes, fhp\->handle_type);
|
|
Packit |
7cfc04 |
for (j = 0; j < fhp\->handle_bytes; j++)
|
|
Packit |
7cfc04 |
printf(" %02x", fhp\->f_handle[j]);
|
|
Packit |
7cfc04 |
printf("\\n");
|
|
Packit |
7cfc04 |
|
|
Packit |
7cfc04 |
exit(EXIT_SUCCESS);
|
|
Packit |
7cfc04 |
}
|
|
Packit |
7cfc04 |
.EE
|
|
Packit |
7cfc04 |
.SS Program source: t_open_by_handle_at.c
|
|
Packit |
7cfc04 |
\&
|
|
Packit |
7cfc04 |
.EX
|
|
Packit |
7cfc04 |
#define _GNU_SOURCE
|
|
Packit |
7cfc04 |
#include <sys/types.h>
|
|
Packit |
7cfc04 |
#include <sys/stat.h>
|
|
Packit |
7cfc04 |
#include <fcntl.h>
|
|
Packit |
7cfc04 |
#include <limits.h>
|
|
Packit |
7cfc04 |
#include <stdio.h>
|
|
Packit |
7cfc04 |
#include <stdlib.h>
|
|
Packit |
7cfc04 |
#include <unistd.h>
|
|
Packit |
7cfc04 |
#include <string.h>
|
|
Packit |
7cfc04 |
|
|
Packit |
7cfc04 |
#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \\
|
|
Packit |
7cfc04 |
} while (0)
|
|
Packit |
7cfc04 |
|
|
Packit |
7cfc04 |
/* Scan /proc/self/mountinfo to find the line whose mount ID matches
|
|
Packit |
7cfc04 |
\(aqmount_id\(aq. (An easier way to do this is to install and use the
|
|
Packit |
7cfc04 |
\(aqlibmount\(aq library provided by the \(aqutil\-linux\(aq project.)
|
|
Packit |
7cfc04 |
Open the corresponding mount path and return the resulting file
|
|
Packit |
7cfc04 |
descriptor. */
|
|
Packit |
7cfc04 |
|
|
Packit |
7cfc04 |
static int
|
|
Packit |
7cfc04 |
open_mount_path_by_id(int mount_id)
|
|
Packit |
7cfc04 |
{
|
|
Packit |
7cfc04 |
char *linep;
|
|
Packit |
7cfc04 |
size_t lsize;
|
|
Packit |
7cfc04 |
char mount_path[PATH_MAX];
|
|
Packit |
7cfc04 |
int mi_mount_id, found;
|
|
Packit |
7cfc04 |
ssize_t nread;
|
|
Packit |
7cfc04 |
FILE *fp;
|
|
Packit |
7cfc04 |
|
|
Packit |
7cfc04 |
fp = fopen("/proc/self/mountinfo", "r");
|
|
Packit |
7cfc04 |
if (fp == NULL)
|
|
Packit |
7cfc04 |
errExit("fopen");
|
|
Packit |
7cfc04 |
|
|
Packit |
7cfc04 |
found = 0;
|
|
Packit |
7cfc04 |
linep = NULL;
|
|
Packit |
7cfc04 |
while (!found) {
|
|
Packit |
7cfc04 |
nread = getline(&linep, &lsize, fp);
|
|
Packit |
7cfc04 |
if (nread == \-1)
|
|
Packit |
7cfc04 |
break;
|
|
Packit |
7cfc04 |
|
|
Packit |
7cfc04 |
nread = sscanf(linep, "%d %*d %*s %*s %s",
|
|
Packit |
7cfc04 |
&mi_mount_id, mount_path);
|
|
Packit |
7cfc04 |
if (nread != 2) {
|
|
Packit |
7cfc04 |
fprintf(stderr, "Bad sscanf()\\n");
|
|
Packit |
7cfc04 |
exit(EXIT_FAILURE);
|
|
Packit |
7cfc04 |
}
|
|
Packit |
7cfc04 |
|
|
Packit |
7cfc04 |
if (mi_mount_id == mount_id)
|
|
Packit |
7cfc04 |
found = 1;
|
|
Packit |
7cfc04 |
}
|
|
Packit |
7cfc04 |
free(linep);
|
|
Packit |
7cfc04 |
|
|
Packit |
7cfc04 |
fclose(fp);
|
|
Packit |
7cfc04 |
|
|
Packit |
7cfc04 |
if (!found) {
|
|
Packit |
7cfc04 |
fprintf(stderr, "Could not find mount point\\n");
|
|
Packit |
7cfc04 |
exit(EXIT_FAILURE);
|
|
Packit |
7cfc04 |
}
|
|
Packit |
7cfc04 |
|
|
Packit |
7cfc04 |
return open(mount_path, O_RDONLY);
|
|
Packit |
7cfc04 |
}
|
|
Packit |
7cfc04 |
|
|
Packit |
7cfc04 |
int
|
|
Packit |
7cfc04 |
main(int argc, char *argv[])
|
|
Packit |
7cfc04 |
{
|
|
Packit |
7cfc04 |
struct file_handle *fhp;
|
|
Packit |
7cfc04 |
int mount_id, fd, mount_fd, handle_bytes, j;
|
|
Packit |
7cfc04 |
ssize_t nread;
|
|
Packit |
7cfc04 |
char buf[1000];
|
|
Packit |
7cfc04 |
#define LINE_SIZE 100
|
|
Packit |
7cfc04 |
char line1[LINE_SIZE], line2[LINE_SIZE];
|
|
Packit |
7cfc04 |
char *nextp;
|
|
Packit |
7cfc04 |
|
|
Packit |
7cfc04 |
if ((argc > 1 && strcmp(argv[1], "\-\-help") == 0) || argc > 2) {
|
|
Packit |
7cfc04 |
fprintf(stderr, "Usage: %s [mount\-path]\\n", argv[0]);
|
|
Packit |
7cfc04 |
exit(EXIT_FAILURE);
|
|
Packit |
7cfc04 |
}
|
|
Packit |
7cfc04 |
|
|
Packit |
7cfc04 |
/* Standard input contains mount ID and file handle information:
|
|
Packit |
7cfc04 |
|
|
Packit |
7cfc04 |
Line 1: <mount_id>
|
|
Packit |
7cfc04 |
Line 2: <handle_bytes> <handle_type> <bytes of handle in hex>
|
|
Packit |
7cfc04 |
*/
|
|
Packit |
7cfc04 |
|
|
Packit |
7cfc04 |
if ((fgets(line1, sizeof(line1), stdin) == NULL) ||
|
|
Packit |
7cfc04 |
(fgets(line2, sizeof(line2), stdin) == NULL)) {
|
|
Packit |
7cfc04 |
fprintf(stderr, "Missing mount_id / file handle\\n");
|
|
Packit |
7cfc04 |
exit(EXIT_FAILURE);
|
|
Packit |
7cfc04 |
}
|
|
Packit |
7cfc04 |
|
|
Packit |
7cfc04 |
mount_id = atoi(line1);
|
|
Packit |
7cfc04 |
|
|
Packit |
7cfc04 |
handle_bytes = strtoul(line2, &nextp, 0);
|
|
Packit |
7cfc04 |
|
|
Packit |
7cfc04 |
/* Given handle_bytes, we can now allocate file_handle structure */
|
|
Packit |
7cfc04 |
|
|
Packit |
7cfc04 |
fhp = malloc(sizeof(struct file_handle) + handle_bytes);
|
|
Packit |
7cfc04 |
if (fhp == NULL)
|
|
Packit |
7cfc04 |
errExit("malloc");
|
|
Packit |
7cfc04 |
|
|
Packit |
7cfc04 |
fhp\->handle_bytes = handle_bytes;
|
|
Packit |
7cfc04 |
|
|
Packit |
7cfc04 |
fhp\->handle_type = strtoul(nextp, &nextp, 0);
|
|
Packit |
7cfc04 |
|
|
Packit |
7cfc04 |
for (j = 0; j < fhp\->handle_bytes; j++)
|
|
Packit |
7cfc04 |
fhp\->f_handle[j] = strtoul(nextp, &nextp, 16);
|
|
Packit |
7cfc04 |
|
|
Packit |
7cfc04 |
/* Obtain file descriptor for mount point, either by opening
|
|
Packit |
7cfc04 |
the pathname specified on the command line, or by scanning
|
|
Packit |
7cfc04 |
/proc/self/mounts to find a mount that matches the \(aqmount_id\(aq
|
|
Packit |
7cfc04 |
that we received from stdin. */
|
|
Packit |
7cfc04 |
|
|
Packit |
7cfc04 |
if (argc > 1)
|
|
Packit |
7cfc04 |
mount_fd = open(argv[1], O_RDONLY);
|
|
Packit |
7cfc04 |
else
|
|
Packit |
7cfc04 |
mount_fd = open_mount_path_by_id(mount_id);
|
|
Packit |
7cfc04 |
|
|
Packit |
7cfc04 |
if (mount_fd == \-1)
|
|
Packit |
7cfc04 |
errExit("opening mount fd");
|
|
Packit |
7cfc04 |
|
|
Packit |
7cfc04 |
/* Open file using handle and mount point */
|
|
Packit |
7cfc04 |
|
|
Packit |
7cfc04 |
fd = open_by_handle_at(mount_fd, fhp, O_RDONLY);
|
|
Packit |
7cfc04 |
if (fd == \-1)
|
|
Packit |
7cfc04 |
errExit("open_by_handle_at");
|
|
Packit |
7cfc04 |
|
|
Packit |
7cfc04 |
/* Try reading a few bytes from the file */
|
|
Packit |
7cfc04 |
|
|
Packit |
7cfc04 |
nread = read(fd, buf, sizeof(buf));
|
|
Packit |
7cfc04 |
if (nread == \-1)
|
|
Packit |
7cfc04 |
errExit("read");
|
|
Packit |
7cfc04 |
|
|
Packit |
7cfc04 |
printf("Read %zd bytes\\n", nread);
|
|
Packit |
7cfc04 |
|
|
Packit |
7cfc04 |
exit(EXIT_SUCCESS);
|
|
Packit |
7cfc04 |
}
|
|
Packit |
7cfc04 |
.EE
|
|
Packit |
7cfc04 |
.SH SEE ALSO
|
|
Packit |
7cfc04 |
.BR open (2),
|
|
Packit |
7cfc04 |
.BR libblkid (3),
|
|
Packit |
7cfc04 |
.BR blkid (8),
|
|
Packit |
7cfc04 |
.BR findfs (8),
|
|
Packit |
7cfc04 |
.BR mount (8)
|
|
Packit |
7cfc04 |
.PP
|
|
Packit |
7cfc04 |
The
|
|
Packit |
7cfc04 |
.I libblkid
|
|
Packit |
7cfc04 |
and
|
|
Packit |
7cfc04 |
.I libmount
|
|
Packit |
7cfc04 |
documentation in the latest
|
|
Packit |
7cfc04 |
.I util-linux
|
|
Packit |
7cfc04 |
release at
|
|
Packit |
7cfc04 |
.UR https://www.kernel.org/pub/linux/utils/util\-linux/
|
|
Packit |
7cfc04 |
.UE
|
|
Packit |
7cfc04 |
.SH COLOPHON
|
|
Packit |
7cfc04 |
This page is part of release 4.15 of the Linux
|
|
Packit |
7cfc04 |
.I man-pages
|
|
Packit |
7cfc04 |
project.
|
|
Packit |
7cfc04 |
A description of the project,
|
|
Packit |
7cfc04 |
information about reporting bugs,
|
|
Packit |
7cfc04 |
and the latest version of this page,
|
|
Packit |
7cfc04 |
can be found at
|
|
Packit |
7cfc04 |
\%https://www.kernel.org/doc/man\-pages/.
|