1 .\" Copyright (c) 2014 by Michael Kerrisk <mtk.manpages@gmail.com>
3 .\" %%%LICENSE_START(VERBATIM)
4 .\" Permission is granted to make and distribute verbatim copies of this
5 .\" manual provided the copyright notice and this permission notice are
6 .\" preserved on all copies.
8 .\" Permission is granted to copy and distribute modified versions of this
9 .\" manual under the conditions for verbatim copying, provided that the
10 .\" entire resulting derived work is distributed under the terms of a
11 .\" permission notice identical to this one.
13 .\" Since the Linux kernel and libraries are constantly changing, this
14 .\" manual page may be incorrect or out-of-date. The author(s) assume no
15 .\" responsibility for errors or omissions, or for damages resulting from
16 .\" the use of the information contained herein. The author(s) may not
17 .\" have taken the same level of care in the production of this manual,
18 .\" which is licensed free of charge, as they might when working
21 .\" Formatted or processed versions of this manual, if unaccompanied by
22 .\" the source, must acknowledge the copyright and authors of this work.
25 .TH OPEN_BY_HANDLE_AT 2 2019-03-06 "Linux" "Linux Programmer's Manual"
27 name_to_handle_at, open_by_handle_at \- obtain handle
28 for a pathname and open file via a handle
31 .BR "#define _GNU_SOURCE" " /* See feature_test_macros(7) */"
32 .B #include <sys/types.h>
33 .B #include <sys/stat.h>
36 .BI "int name_to_handle_at(int " dirfd ", const char *" pathname ,
37 .BI " struct file_handle *" handle ,
38 .BI " int *" mount_id ", int " flags );
40 .BI "int open_by_handle_at(int " mount_fd ", struct file_handle *" handle ,
45 .BR name_to_handle_at ()
47 .BR open_by_handle_at ()
48 system calls split the functionality of
51 .BR name_to_handle_at ()
52 returns an opaque handle that corresponds to a specified file;
53 .BR open_by_handle_at ()
54 opens the file corresponding to a handle returned by a previous call to
55 .BR name_to_handle_at ()
56 and returns an open file descriptor.
59 .SS name_to_handle_at()
61 .BR name_to_handle_at ()
62 system call returns a file handle and a mount ID corresponding to
63 the file specified by the
68 The file handle is returned via the argument
70 which is a pointer to a structure of the following form:
75 unsigned int handle_bytes; /* Size of f_handle [in, out] */
76 int handle_type; /* Handle type [out] */
77 unsigned char f_handle[0]; /* File identifier (sized by
83 It is the caller's responsibility to allocate the structure
84 with a size large enough to hold the handle returned in
88 field should be initialized to contain the allocated size for
94 specifies the maximum expected size for a file handle.
96 guaranteed upper limit as future filesystems may require more space.)
97 Upon successful return, the
99 field is updated to contain the number of bytes actually written to
102 The caller can discover the required size for the
104 structure by making a call in which
105 .IR handle->handle_bytes
107 in this case, the call fails with the error
110 .IR handle->handle_bytes
111 is set to indicate the required size;
112 the caller can then use this information to allocate a structure
113 of the correct size (see EXAMPLE below).
114 Some care is needed here as
116 can also indicate that no file handle is available for this particular
117 name in a filesystem which does normally support file-handle lookup.
118 This case can be detected when the
120 error is returned without
124 Other than the use of the
126 field, the caller should treat the
128 structure as an opaque data type: the
132 fields are needed only by a subsequent call to
133 .BR open_by_handle_at ().
137 argument is a bit mask constructed by ORing together zero or more of
140 .BR AT_SYMLINK_FOLLOW ,
147 arguments identify the file for which a handle is to be obtained.
148 There are four distinct cases:
152 is a nonempty string containing an absolute pathname,
153 then a handle is returned for the file referred to by that pathname.
160 is a nonempty string containing a relative pathname and
162 has the special value
166 is interpreted relative to the current working directory of the caller,
167 and a handle is returned for the file to which it refers.
171 is a nonempty string containing a relative pathname and
173 is a file descriptor referring to a directory, then
175 is interpreted relative to the directory referred to by
177 and a handle is returned for the file to which it refers.
180 for an explanation of why "directory file descriptors" are useful.)
184 is an empty string and
190 can be an open file descriptor referring to any type of file,
193 meaning the current working directory,
194 and a handle is returned for the file to which it refers.
198 argument returns an identifier for the filesystem
199 mount that corresponds to
201 This corresponds to the first field in one of the records in
202 .IR /proc/self/mountinfo .
203 Opening the pathname in the fifth field of that record yields a file
204 descriptor for the mount point;
205 that file descriptor can be used in a subsequent call to
206 .BR open_by_handle_at ().
208 is returned both for a successful call and for a call that results
213 .BR name_to_handle_at ()
216 if it is a symbolic link, and thus returns a handle for the link itself.
222 is dereferenced if it is a symbolic link
223 (so that the call returns a handle for the file referred to by the link).
225 .BR name_to_handle_at ()
226 does not trigger a mount when the final component of the pathname is an
228 When a filesystem supports both file handles and
230 .BR name_to_handle_at ()
231 call on an automount point will return with error
233 without having increased
235 This can happen since Linux 4.13
236 .\" commit 20fa19027286983ab2734b5910c4a687436e0c31
237 with NFS when accessing a directory
238 which is on a separate filesystem on the server.
239 In this case, the automount can be triggered by adding a "/" to the end
241 .SS open_by_handle_at()
243 .BR open_by_handle_at ()
244 system call opens the file referred to by
246 a file handle returned by a previous call to
247 .BR name_to_handle_at ().
251 argument is a file descriptor for any object (file, directory, etc.)
252 in the mounted filesystem with respect to which
254 should be interpreted.
257 can be specified, meaning the current working directory of the caller.
266 refers to a symbolic link, the caller must specify the
268 flag, and the symbolic link is not dereferenced; the
270 flag, if specified, is ignored.
272 The caller must have the
273 .B CAP_DAC_READ_SEARCH
275 .BR open_by_handle_at ().
278 .BR name_to_handle_at ()
281 .BR open_by_handle_at ()
282 returns a nonnegative file descriptor.
284 In the event of an error, both system calls return \-1 and set
286 to indicate the cause of the error.
288 .BR name_to_handle_at ()
290 .BR open_by_handle_at ()
291 can fail for the same errors as
293 In addition, they can fail with the errors noted below.
295 .BR name_to_handle_at ()
296 can fail with the following errors:
303 points outside your accessible address space.
307 includes an invalid bit value.
310 .IR handle\->handle_bytes
316 is an empty string, but
322 The file descriptor supplied in
324 does not refer to a directory,
325 and it is not the case that both
334 The filesystem does not support decoding of a pathname to a file handle.
338 .I handle->handle_bytes
339 value passed into the call was too small.
340 When this error occurs,
341 .I handle->handle_bytes
342 is updated to indicate the required size for the handle.
346 .BR open_by_handle_at ()
347 can fail with the following errors:
351 is not an open file descriptor.
355 points outside your accessible address space.
358 .I handle->handle_bytes
365 refers to a symbolic link, but
371 The caller does not have the
372 .BR CAP_DAC_READ_SEARCH
379 This error will occur if, for example, the file has been deleted.
381 These system calls first appeared in Linux 2.6.39.
382 Library support is provided in glibc since version 2.14.
384 These system calls are nonstandard Linux extensions.
386 FreeBSD has a broadly similar pair of system calls in the form of
391 A file handle can be generated in one process using
392 .BR name_to_handle_at ()
393 and later used in a different process that calls
394 .BR open_by_handle_at ().
396 Some filesystem don't support the translation of pathnames to
397 file handles, for example,
400 and various network filesystems.
402 A file handle may become invalid ("stale") if a file is deleted,
403 or for other filesystem-specific reasons.
404 Invalid handles are notified by an
407 .BR open_by_handle_at ().
409 These system calls are designed for use by user-space file servers.
410 For example, a user-space NFS server might generate a file handle
411 and pass it to an NFS client.
412 Later, when the client wants to open the file,
413 it could pass the handle back to the server.
414 .\" https://lwn.net/Articles/375888/
415 .\" "Open by handle" - Jonathan Corbet, 2010-02-23
416 This sort of functionality allows a user-space file server to operate in
417 a stateless fashion with respect to the files it serves.
421 refers to a symbolic link and
424 .BR AT_SYMLINK_FOLLOW ,
426 .BR name_to_handle_at ()
427 returns a handle for the link (rather than the file to which it refers).
428 .\" commit bcda76524cd1fa32af748536f27f674a13e56700
429 The process receiving the handle can later perform operations
430 on the symbolic link by converting the handle to a file descriptor using
431 .BR open_by_handle_at ()
434 flag, and then passing the file descriptor as the
436 argument in system calls such as
440 .SS Obtaining a persistent filesystem ID
442 .IR /proc/self/mountinfo
443 can be reused as filesystems are unmounted and mounted.
444 Therefore, the mount ID returned by
445 .BR name_to_handle_at ()
448 should not be treated as a persistent identifier
449 for the corresponding mounted filesystem.
450 However, an application can use the information in the
452 record that corresponds to the mount ID
453 to derive a persistent identifier.
455 For example, one can use the device name in the fifth field of the
457 record to search for the corresponding device UUID via the symbolic links in
458 .IR /dev/disks/by-uuid .
459 (A more comfortable way of obtaining the UUID is to use the
460 .\" e.g., http://stackoverflow.com/questions/6748429/using-libblkid-to-find-uuid-of-a-partition
463 That process can then be reversed,
464 using the UUID to look up the device name,
465 and then obtaining the corresponding mount point,
466 in order to produce the
469 .BR open_by_handle_at ().
471 The two programs below demonstrate the use of
472 .BR name_to_handle_at ()
474 .BR open_by_handle_at ().
476 .RI ( t_name_to_handle_at.c )
478 .BR name_to_handle_at ()
479 to obtain the file handle and mount ID
480 for the file specified in its command-line argument;
481 the handle and mount ID are written to standard output.
484 .RI ( t_open_by_handle_at.c )
485 reads a mount ID and file handle from standard input.
486 The program then employs
487 .BR open_by_handle_at ()
488 to open the file using that handle.
489 If an optional command-line argument is supplied, then the
492 .BR open_by_handle_at ()
493 is obtained by opening the directory named in that argument.
496 is obtained by scanning
497 .IR /proc/self/mountinfo
498 to find a record whose mount ID matches the mount ID
499 read from standard input,
500 and the mount directory specified in that record is opened.
501 (These programs do not deal with the fact that mount IDs are not persistent.)
503 The following shell session demonstrates the use of these two programs:
507 $ \fBecho 'Can you please think about it?' > cecilia.txt\fP
508 $ \fB./t_name_to_handle_at cecilia.txt > fh\fP
509 $ \fB./t_open_by_handle_at < fh\fP
510 open_by_handle_at: Operation not permitted
511 $ \fBsudo ./t_open_by_handle_at < fh\fP # Need CAP_SYS_ADMIN
513 $ \fBrm cecilia.txt\fP
517 Now we delete and (quickly) re-create the file so that
518 it has the same content and (by chance) the same inode.
520 .BR open_by_handle_at ()
521 .\" Christoph Hellwig: That's why the file handles contain a generation
522 .\" counter that gets incremented in this case.
523 recognizes that the original file referred to by the file handle
528 $ \fBstat \-\-printf="%i\en" cecilia.txt\fP # Display inode number
530 $ \fBrm cecilia.txt\fP
531 $ \fBecho 'Can you please think about it?' > cecilia.txt\fP
532 $ \fBstat \-\-printf="%i\en" cecilia.txt\fP # Check inode number
534 $ \fBsudo ./t_open_by_handle_at < fh\fP
535 open_by_handle_at: Stale NFS file handle
538 .SS Program source: t_name_to_handle_at.c
542 #include <sys/types.h>
543 #include <sys/stat.h>
551 #define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \e
555 main(int argc, char *argv[])
557 struct file_handle *fhp;
558 int mount_id, fhsize, flags, dirfd, j;
562 fprintf(stderr, "Usage: %s pathname\en", argv[0]);
568 /* Allocate file_handle structure */
570 fhsize = sizeof(*fhp);
571 fhp = malloc(fhsize);
575 /* Make an initial call to name_to_handle_at() to discover
576 the size required for file handle */
578 dirfd = AT_FDCWD; /* For name_to_handle_at() calls */
579 flags = 0; /* For name_to_handle_at() calls */
580 fhp\->handle_bytes = 0;
581 if (name_to_handle_at(dirfd, pathname, fhp,
582 &mount_id, flags) != \-1 || errno != EOVERFLOW) {
583 fprintf(stderr, "Unexpected result from name_to_handle_at()\en");
587 /* Reallocate file_handle structure with correct size */
589 fhsize = sizeof(struct file_handle) + fhp\->handle_bytes;
590 fhp = realloc(fhp, fhsize); /* Copies fhp\->handle_bytes */
594 /* Get file handle from pathname supplied on command line */
596 if (name_to_handle_at(dirfd, pathname, fhp, &mount_id, flags) == \-1)
597 errExit("name_to_handle_at");
599 /* Write mount ID, file handle size, and file handle to stdout,
600 for later reuse by t_open_by_handle_at.c */
602 printf("%d\en", mount_id);
603 printf("%d %d ", fhp\->handle_bytes, fhp\->handle_type);
604 for (j = 0; j < fhp\->handle_bytes; j++)
605 printf(" %02x", fhp\->f_handle[j]);
611 .SS Program source: t_open_by_handle_at.c
615 #include <sys/types.h>
616 #include <sys/stat.h>
624 #define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \e
627 /* Scan /proc/self/mountinfo to find the line whose mount ID matches
628 \(aqmount_id\(aq. (An easier way to do this is to install and use the
629 \(aqlibmount\(aq library provided by the \(aqutil\-linux\(aq project.)
630 Open the corresponding mount path and return the resulting file
634 open_mount_path_by_id(int mount_id)
638 char mount_path[PATH_MAX];
639 int mi_mount_id, found;
643 fp = fopen("/proc/self/mountinfo", "r");
650 nread = getline(&linep, &lsize, fp);
654 nread = sscanf(linep, "%d %*d %*s %*s %s",
655 &mi_mount_id, mount_path);
657 fprintf(stderr, "Bad sscanf()\en");
661 if (mi_mount_id == mount_id)
669 fprintf(stderr, "Could not find mount point\en");
673 return open(mount_path, O_RDONLY);
677 main(int argc, char *argv[])
679 struct file_handle *fhp;
680 int mount_id, fd, mount_fd, handle_bytes, j;
683 #define LINE_SIZE 100
684 char line1[LINE_SIZE], line2[LINE_SIZE];
687 if ((argc > 1 && strcmp(argv[1], "\-\-help") == 0) || argc > 2) {
688 fprintf(stderr, "Usage: %s [mount\-path]\en", argv[0]);
692 /* Standard input contains mount ID and file handle information:
695 Line 2: <handle_bytes> <handle_type> <bytes of handle in hex>
698 if ((fgets(line1, sizeof(line1), stdin) == NULL) ||
699 (fgets(line2, sizeof(line2), stdin) == NULL)) {
700 fprintf(stderr, "Missing mount_id / file handle\en");
704 mount_id = atoi(line1);
706 handle_bytes = strtoul(line2, &nextp, 0);
708 /* Given handle_bytes, we can now allocate file_handle structure */
710 fhp = malloc(sizeof(struct file_handle) + handle_bytes);
714 fhp\->handle_bytes = handle_bytes;
716 fhp\->handle_type = strtoul(nextp, &nextp, 0);
718 for (j = 0; j < fhp\->handle_bytes; j++)
719 fhp\->f_handle[j] = strtoul(nextp, &nextp, 16);
721 /* Obtain file descriptor for mount point, either by opening
722 the pathname specified on the command line, or by scanning
723 /proc/self/mounts to find a mount that matches the \(aqmount_id\(aq
724 that we received from stdin. */
727 mount_fd = open(argv[1], O_RDONLY);
729 mount_fd = open_mount_path_by_id(mount_id);
732 errExit("opening mount fd");
734 /* Open file using handle and mount point */
736 fd = open_by_handle_at(mount_fd, fhp, O_RDONLY);
738 errExit("open_by_handle_at");
740 /* Try reading a few bytes from the file */
742 nread = read(fd, buf, sizeof(buf));
746 printf("Read %zd bytes\en", nread);
762 documentation in the latest
765 .UR https://www.kernel.org/pub/linux/utils/util\-linux/