1 .\" Copyright (c) 2014 by Michael Kerrisk <mtk.manpages@gmail.com>
3 .\" SPDX-License-Identifier: Linux-man-pages-copyleft
5 .TH open_by_handle_at 2 (date) "Linux man-pages (unreleased)"
7 name_to_handle_at, open_by_handle_at \- obtain handle
8 for a pathname and open file via a handle
11 .RI ( libc ", " \-lc )
14 .BR "#define _GNU_SOURCE" " /* See feature_test_macros(7) */"
17 .BI "int name_to_handle_at(int " dirfd ", const char *" pathname ,
18 .BI " struct file_handle *" handle ,
19 .BI " int *" mount_id ", int " flags );
20 .BI "int open_by_handle_at(int " mount_fd ", struct file_handle *" handle ,
25 .BR name_to_handle_at ()
27 .BR open_by_handle_at ()
28 system calls split the functionality of
31 .BR name_to_handle_at ()
32 returns an opaque handle that corresponds to a specified file;
33 .BR open_by_handle_at ()
34 opens the file corresponding to a handle returned by a previous call to
35 .BR name_to_handle_at ()
36 and returns an open file descriptor.
39 .SS name_to_handle_at()
41 .BR name_to_handle_at ()
42 system call returns a file handle and a mount ID corresponding to
43 the file specified by the
48 The file handle is returned via the argument
50 which is a pointer to a structure of the following form:
55 unsigned int handle_bytes; /* Size of f_handle [in, out] */
56 int handle_type; /* Handle type [out] */
57 unsigned char f_handle[0]; /* File identifier (sized by
63 It is the caller's responsibility to allocate the structure
64 with a size large enough to hold the handle returned in
68 field should be initialized to contain the allocated size for
74 specifies the maximum expected size for a file handle.
76 guaranteed upper limit as future filesystems may require more space.)
77 Upon successful return, the
79 field is updated to contain the number of bytes actually written to
82 The caller can discover the required size for the
84 structure by making a call in which
85 .I handle\->handle_bytes
87 in this case, the call fails with the error
90 .I handle\->handle_bytes
91 is set to indicate the required size;
92 the caller can then use this information to allocate a structure
93 of the correct size (see EXAMPLES below).
94 Some care is needed here as
96 can also indicate that no file handle is available for this particular
97 name in a filesystem which does normally support file-handle lookup.
98 This case can be detected when the
100 error is returned without
104 Other than the use of the
106 field, the caller should treat the
108 structure as an opaque data type: the
112 fields can be used in a subsequent call to
113 .BR open_by_handle_at ().
114 The caller can also use the opaque
116 to compare the identity of filesystem objects
117 that were queried at different times and possibly
121 subsystem can report events
122 with an information record containing a
124 to identify the filesystem object.
128 argument is a bit mask constructed by ORing together zero or more of
132 .BR AT_SYMLINK_FOLLOW ,
138 .BR AT_HANDLE_FID " (since Linux 6.5)"
139 .\" commit 96b2b072ee62be8ae68c8ecf14854c4d0505a8f8
140 flag, the caller indicates that the returned
142 is needed to identify the filesystem object,
143 and not for opening the file later,
144 so it should be expected that a subsequent call to
145 .BR open_by_handle_at ()
154 arguments identify the file for which a handle is to be obtained.
155 There are four distinct cases:
159 is a nonempty string containing an absolute pathname,
160 then a handle is returned for the file referred to by that pathname.
167 is a nonempty string containing a relative pathname and
169 has the special value
173 is interpreted relative to the current working directory of the caller,
174 and a handle is returned for the file to which it refers.
178 is a nonempty string containing a relative pathname and
180 is a file descriptor referring to a directory, then
182 is interpreted relative to the directory referred to by
184 and a handle is returned for the file to which it refers.
187 for an explanation of why "directory file descriptors" are useful.)
191 is an empty string and
197 can be an open file descriptor referring to any type of file,
200 meaning the current working directory,
201 and a handle is returned for the file to which it refers.
205 argument returns an identifier for the filesystem
206 mount that corresponds to
208 This corresponds to the first field in one of the records in
209 .IR /proc/self/mountinfo .
210 Opening the pathname in the fifth field of that record yields a file
211 descriptor for the mount point;
212 that file descriptor can be used in a subsequent call to
213 .BR open_by_handle_at ().
215 is returned both for a successful call and for a call that results
220 .BR name_to_handle_at ()
223 if it is a symbolic link, and thus returns a handle for the link itself.
229 is dereferenced if it is a symbolic link
230 (so that the call returns a handle for the file referred to by the link).
232 .BR name_to_handle_at ()
233 does not trigger a mount when the final component of the pathname is an
235 When a filesystem supports both file handles and
237 .BR name_to_handle_at ()
238 call on an automount point will return with error
240 without having increased
242 This can happen since Linux 4.13
243 .\" commit 20fa19027286983ab2734b5910c4a687436e0c31
244 with NFS when accessing a directory
245 which is on a separate filesystem on the server.
246 In this case, the automount can be triggered by adding a "/" to the end
248 .SS open_by_handle_at()
250 .BR open_by_handle_at ()
251 system call opens the file referred to by
253 a file handle returned by a previous call to
254 .BR name_to_handle_at ().
258 argument is a file descriptor for any object (file, directory, etc.)
259 in the mounted filesystem with respect to which
261 should be interpreted.
264 can be specified, meaning the current working directory of the caller.
273 refers to a symbolic link, the caller must specify the
275 flag, and the symbolic link is not dereferenced; the
277 flag, if specified, is ignored.
279 The caller must have the
280 .B CAP_DAC_READ_SEARCH
282 .BR open_by_handle_at ().
285 .BR name_to_handle_at ()
288 .BR open_by_handle_at ()
289 returns a file descriptor (a nonnegative integer).
291 In the event of an error, both system calls return \-1 and set
293 to indicate the error.
295 .BR name_to_handle_at ()
297 .BR open_by_handle_at ()
298 can fail for the same errors as
300 In addition, they can fail with the errors noted below.
302 .BR name_to_handle_at ()
303 can fail with the following errors:
310 points outside your accessible address space.
314 includes an invalid bit value.
317 .I handle\->handle_bytes
323 is an empty string, but
329 The file descriptor supplied in
331 does not refer to a directory,
332 and it is not the case that both
341 The filesystem does not support decoding of a pathname to a file handle.
345 .I handle\->handle_bytes
346 value passed into the call was too small.
347 When this error occurs,
348 .I handle\->handle_bytes
349 is updated to indicate the required size for the handle.
353 .BR open_by_handle_at ()
354 can fail with the following errors:
358 is not an open file descriptor.
366 nor a valid file descriptor.
370 points outside your accessible address space.
373 .I handle\->handle_bytes
380 refers to a symbolic link, but
386 The caller does not have the
387 .B CAP_DAC_READ_SEARCH
393 is not valid for opening a file.
394 This error will occur if, for example, the file has been deleted.
395 This error can also occur if the
397 was acquired using the
399 flag and the filesystem does not support
400 .BR open_by_handle_at ().
402 FreeBSD has a broadly similar pair of system calls in the form of
412 A file handle can be generated in one process using
413 .BR name_to_handle_at ()
414 and later used in a different process that calls
415 .BR open_by_handle_at ().
417 Some filesystem don't support the translation of pathnames to
418 file handles, for example,
421 and various network filesystems.
422 Some filesystems support the translation of pathnames to
423 file handles, but do not support using those file handles in
424 .BR open_by_handle_at ().
426 A file handle may become invalid ("stale") if a file is deleted,
427 or for other filesystem-specific reasons.
428 Invalid handles are notified by an
431 .BR open_by_handle_at ().
433 These system calls are designed for use by user-space file servers.
434 For example, a user-space NFS server might generate a file handle
435 and pass it to an NFS client.
436 Later, when the client wants to open the file,
437 it could pass the handle back to the server.
438 .\" https://lwn.net/Articles/375888/
439 .\" "Open by handle" - Jonathan Corbet, 2010-02-23
440 This sort of functionality allows a user-space file server to operate in
441 a stateless fashion with respect to the files it serves.
445 refers to a symbolic link and
448 .BR AT_SYMLINK_FOLLOW ,
450 .BR name_to_handle_at ()
451 returns a handle for the link (rather than the file to which it refers).
452 .\" commit bcda76524cd1fa32af748536f27f674a13e56700
453 The process receiving the handle can later perform operations
454 on the symbolic link by converting the handle to a file descriptor using
455 .BR open_by_handle_at ()
458 flag, and then passing the file descriptor as the
460 argument in system calls such as
464 .SS Obtaining a persistent filesystem ID
466 .I /proc/self/mountinfo
467 can be reused as filesystems are unmounted and mounted.
468 Therefore, the mount ID returned by
469 .BR name_to_handle_at ()
472 should not be treated as a persistent identifier
473 for the corresponding mounted filesystem.
474 However, an application can use the information in the
476 record that corresponds to the mount ID
477 to derive a persistent identifier.
479 For example, one can use the device name in the fifth field of the
481 record to search for the corresponding device UUID via the symbolic links in
482 .IR /dev/disks/by\-uuid .
483 (A more comfortable way of obtaining the UUID is to use the
484 .\" e.g., http://stackoverflow.com/questions/6748429/using-libblkid-to-find-uuid-of-a-partition
487 That process can then be reversed,
488 using the UUID to look up the device name,
489 and then obtaining the corresponding mount point,
490 in order to produce the
493 .BR open_by_handle_at ().
495 The two programs below demonstrate the use of
496 .BR name_to_handle_at ()
498 .BR open_by_handle_at ().
500 .RI ( t_name_to_handle_at.c )
502 .BR name_to_handle_at ()
503 to obtain the file handle and mount ID
504 for the file specified in its command-line argument;
505 the handle and mount ID are written to standard output.
508 .RI ( t_open_by_handle_at.c )
509 reads a mount ID and file handle from standard input.
510 The program then employs
511 .BR open_by_handle_at ()
512 to open the file using that handle.
513 If an optional command-line argument is supplied, then the
516 .BR open_by_handle_at ()
517 is obtained by opening the directory named in that argument.
520 is obtained by scanning
521 .I /proc/self/mountinfo
522 to find a record whose mount ID matches the mount ID
523 read from standard input,
524 and the mount directory specified in that record is opened.
525 (These programs do not deal with the fact that mount IDs are not persistent.)
527 The following shell session demonstrates the use of these two programs:
531 $ \fBecho \[aq]Can you please think about it?\[aq] > cecilia.txt\fP
532 $ \fB./t_name_to_handle_at cecilia.txt > fh\fP
533 $ \fB./t_open_by_handle_at < fh\fP
534 open_by_handle_at: Operation not permitted
535 $ \fBsudo ./t_open_by_handle_at < fh\fP # Need CAP_SYS_ADMIN
537 $ \fBrm cecilia.txt\fP
541 Now we delete and (quickly) re-create the file so that
542 it has the same content and (by chance) the same inode.
544 .BR open_by_handle_at ()
545 .\" Christoph Hellwig: That's why the file handles contain a generation
546 .\" counter that gets incremented in this case.
547 recognizes that the original file referred to by the file handle
552 $ \fBstat \-\-printf="%i\en" cecilia.txt\fP # Display inode number
554 $ \fBrm cecilia.txt\fP
555 $ \fBecho \[aq]Can you please think about it?\[aq] > cecilia.txt\fP
556 $ \fBstat \-\-printf="%i\en" cecilia.txt\fP # Check inode number
558 $ \fBsudo ./t_open_by_handle_at < fh\fP
559 open_by_handle_at: Stale NFS file handle
562 .SS Program source: t_name_to_handle_at.c
564 .\" SRC BEGIN (t_name_to_handle_at.c)
574 main(int argc, char *argv[])
576 int mount_id, fhsize, flags, dirfd;
578 struct file_handle *fhp;
581 fprintf(stderr, "Usage: %s pathname\en", argv[0]);
587 /* Allocate file_handle structure. */
589 fhsize = sizeof(*fhp);
590 fhp = malloc(fhsize);
592 err(EXIT_FAILURE, "malloc");
594 /* Make an initial call to name_to_handle_at() to discover
595 the size required for file handle. */
597 dirfd = AT_FDCWD; /* For name_to_handle_at() calls */
598 flags = 0; /* For name_to_handle_at() calls */
599 fhp\->handle_bytes = 0;
600 if (name_to_handle_at(dirfd, pathname, fhp,
601 &mount_id, flags) != \-1
602 || errno != EOVERFLOW)
604 fprintf(stderr, "Unexpected result from name_to_handle_at()\en");
608 /* Reallocate file_handle structure with correct size. */
610 fhsize = sizeof(*fhp) + fhp\->handle_bytes;
611 fhp = realloc(fhp, fhsize); /* Copies fhp\->handle_bytes */
613 err(EXIT_FAILURE, "realloc");
615 /* Get file handle from pathname supplied on command line. */
617 if (name_to_handle_at(dirfd, pathname, fhp, &mount_id, flags) == \-1)
618 err(EXIT_FAILURE, "name_to_handle_at");
620 /* Write mount ID, file handle size, and file handle to stdout,
621 for later reuse by t_open_by_handle_at.c. */
623 printf("%d\en", mount_id);
624 printf("%u %d ", fhp\->handle_bytes, fhp\->handle_type);
625 for (size_t j = 0; j < fhp\->handle_bytes; j++)
626 printf(" %02x", fhp\->f_handle[j]);
633 .SS Program source: t_open_by_handle_at.c
635 .\" SRC BEGIN (t_open_by_handle_at.c)
646 /* Scan /proc/self/mountinfo to find the line whose mount ID matches
647 \[aq]mount_id\[aq]. (An easier way to do this is to install and use the
648 \[aq]libmount\[aq] library provided by the \[aq]util\-linux\[aq] project.)
649 Open the corresponding mount path and return the resulting file
653 open_mount_path_by_id(int mount_id)
655 int mi_mount_id, found;
656 char mount_path[PATH_MAX];
662 fp = fopen("/proc/self/mountinfo", "r");
664 err(EXIT_FAILURE, "fopen");
669 nread = getline(&linep, &lsize, fp);
673 nread = sscanf(linep, "%d %*d %*s %*s %s",
674 &mi_mount_id, mount_path);
676 fprintf(stderr, "Bad sscanf()\en");
680 if (mi_mount_id == mount_id)
688 fprintf(stderr, "Could not find mount point\en");
692 return open(mount_path, O_RDONLY);
696 main(int argc, char *argv[])
698 int mount_id, fd, mount_fd, handle_bytes;
700 #define LINE_SIZE 100
701 char line1[LINE_SIZE], line2[LINE_SIZE];
704 struct file_handle *fhp;
706 if ((argc > 1 && strcmp(argv[1], "\-\-help") == 0) || argc > 2) {
707 fprintf(stderr, "Usage: %s [mount\-path]\en", argv[0]);
711 /* Standard input contains mount ID and file handle information:
714 Line 2: <handle_bytes> <handle_type> <bytes of handle in hex>
717 if (fgets(line1, sizeof(line1), stdin) == NULL ||
718 fgets(line2, sizeof(line2), stdin) == NULL)
720 fprintf(stderr, "Missing mount_id / file handle\en");
724 mount_id = atoi(line1);
726 handle_bytes = strtoul(line2, &nextp, 0);
728 /* Given handle_bytes, we can now allocate file_handle structure. */
730 fhp = malloc(sizeof(*fhp) + handle_bytes);
732 err(EXIT_FAILURE, "malloc");
734 fhp\->handle_bytes = handle_bytes;
736 fhp\->handle_type = strtoul(nextp, &nextp, 0);
738 for (size_t j = 0; j < fhp\->handle_bytes; j++)
739 fhp\->f_handle[j] = strtoul(nextp, &nextp, 16);
741 /* Obtain file descriptor for mount point, either by opening
742 the pathname specified on the command line, or by scanning
743 /proc/self/mounts to find a mount that matches the \[aq]mount_id\[aq]
744 that we received from stdin. */
747 mount_fd = open(argv[1], O_RDONLY);
749 mount_fd = open_mount_path_by_id(mount_id);
752 err(EXIT_FAILURE, "opening mount fd");
754 /* Open file using handle and mount point. */
756 fd = open_by_handle_at(mount_fd, fhp, O_RDONLY);
758 err(EXIT_FAILURE, "open_by_handle_at");
760 /* Try reading a few bytes from the file. */
762 nread = read(fd, buf, sizeof(buf));
764 err(EXIT_FAILURE, "read");
766 printf("Read %zd bytes\en", nread);
783 documentation in the latest
786 .UR https://www.kernel.org/pub/linux/utils/util\-linux/