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