1 '\" t -*- coding: UTF-8 -*-
2 .\" Copyright (c) 2014 by Michael Kerrisk <mtk.manpages@gmail.com>
4 .\" %%%LICENSE_START(VERBATIM)
5 .\" Permission is granted to make and distribute verbatim copies of this
6 .\" manual provided the copyright notice and this permission notice are
7 .\" preserved on all copies.
9 .\" Permission is granted to copy and distribute modified versions of this
10 .\" manual under the conditions for verbatim copying, provided that the
11 .\" entire resulting derived work is distributed under the terms of a
12 .\" permission notice identical to this one.
14 .\" Since the Linux kernel and libraries are constantly changing, this
15 .\" manual page may be incorrect or out-of-date. The author(s) assume no
16 .\" responsibility for errors or omissions, or for damages resulting from
17 .\" the use of the information contained herein. The author(s) may not
18 .\" have taken the same level of care in the production of this manual,
19 .\" which is licensed free of charge, as they might when working
22 .\" Formatted or processed versions of this manual, if unaccompanied by
23 .\" the source, must acknowledge the copyright and authors of this work.
26 .TH OPEN_BY_HANDLE_AT 2 2014-03-24 "Linux" "Linux Programmer's Manual"
28 name_to_handle_at, open_by_handle_at \- obtain handle
29 for a pathname and open file via a handle
32 .B #define _GNU_SOURCE
33 .B #include <sys/types.h>
34 .B #include <sys/stat.h>
37 .BI "int name_to_handle_at(int " dirfd ", const char *" pathname ,
38 .BI " struct file_handle *" handle ,
39 .BI " int *" mnt_id ", int " flags );
41 .BI "int open_by_handle_at(int " mountdirfd ", struct file_handle *" handle ,
46 .BR name_to_handle_at ()
48 .BR open_by_handle_at ()
49 system calls split the functionality of
52 .BR name_to_handle_at ()
53 returns an opaque handle that corresponds to a specified file;
54 .BR open_by_handle_at ()
55 opens the file corresponding to a handle returned by a previous call to
56 .BR name_to_handle_at ()
57 and returns an open file descriptor.
58 .SS name_to_handle_at()
60 .BR name_to_handle_at ()
61 system call returns a file handle and a mount ID corresponding to
64 which specifies the pathname of an existing file.
65 The file handle is returned via the argument
67 which is a pointer to a structure of the following form:
72 unsigned int handle_bytes; /* Size of f_handle [in, out] */
73 int handle_type; /* Handle type [out] */
74 unsigned char f_handle[0]; /* File identifier (sized by
80 It is the caller's responsibility to allocate the structure
81 with a size large enough to hold the handle returned in
85 field should be initialized to contain the allocated size for
91 specifies the maximum possible size for a file handle.)
92 Upon successful return, the
94 field is updated to contain the number of bytes actually written to
97 The caller can discover the required size for the
99 structure by making a call in which
100 .IR handle->handle_bytes
102 in this case, the call fails with the error
105 .IR handle->handle_bytes
106 is set to indicate the required size;
107 the caller can then use this information to allocate a structure
108 of the correct size (see EXAMPLE below).
110 Other than the use of the
112 field, the caller should treat the
114 structure as an opaque data type: the
118 fields are needed only by a subsequent call to
119 .BR open_by_handle_at ().
121 The treatment of a relative pathname in
123 depends on the value of
127 has the special value
131 is interpreted relative to the current working
132 directory of the calling process.
135 for an explanation of why this is useful.)
138 must be a file descriptor that refers to a directory, and
140 is interpreted relative to that directory.
143 is an absolute pathname, then
149 argument returns an identifier for the filesystem
150 mount that corresponds to
152 This corresponds to the first field in one of the records in
153 .IR /proc/self/mountinfo .
154 Opening the pathname in the fifth field of that record yields a file
155 descriptor for the mount point;
156 that file descriptor can be used in a subsequent call to
157 .BR open_by_handle_at ().
161 argument is a bit mask constructed by ORing together
162 zero or more of the following value:
168 then obtain a handle for the file referred to by
170 (which may have been obtained using the
176 can refer to any type of file, not just a directory.
180 .BR name_to_handle_at ()
183 if it is a symbolic link.
190 to be dereferenced if it is a symbolic link.
191 .SS open_by_handle_at()
193 .BR open_by_handle_at ()
194 system call opens the file referred to by
196 a file handle returned by a previous call to
197 .BR name_to_handle_at ().
201 argument is a file descriptor for a directory under
202 the mount point with respect to which
204 should be interpreted.
207 can be specified, meaning the current working directory of the caller.
215 The caller must have the
216 .B CAP_DAC_READ_SEARCH
218 .BR open_by_handle_at ().
221 .BR name_to_handle_at ()
224 .BR open_by_handle_at ()
225 returns a nonnegative file descriptor.
227 In the event of an error, both system calls return \-1 and set
229 to indicate the cause of the error.
231 .BR name_to_handle_at ()
233 .BR open_by_handle_at ()
234 can fail for the same errors as
236 In addition, they can fail with the errors noted below.
238 .BR name_to_handle_at ()
239 can fail with the following errors:
243 is not an open file descriptor.
247 includes an invalid bit value.
250 .IR handle_bytes\->handle_bytes
255 The file descriptor supplied in
257 does not refer to a directory,
258 and it it is not the case that both
267 The filesystem does not support decoding of a pathname to a file handle.
271 .I handle->handle_bytes
272 value passed into the call was too small.
273 When this error occurs,
274 .I handle->handle_bytes
275 is updated to indicate the required size for the handle.
279 .BR open_by_handle_at ()
280 can fail with the following errors:
284 is not an open file descriptor.
287 .I handle->handle_bytes
299 and does not refer to a directory.
302 The caller does not have the
303 .BR CAP_DAC_READ_SEARCH
311 These system calls first appeared in Linux 2.6.39.
313 These system calls are nonstandard Linux extensions.
315 A file handle can be generated in one process using
316 .BR name_to_handle_at ()
317 and later used in a different process that calls
318 .BR open_by_handle_at ().
320 These system calls are designed for use by user-space file servers.
321 For example, a user-space NFS server might generate a file handle
322 and pass it to an NFS client.
323 Later, when the client wants to open the file,
324 it could pass the handle back to the server.
325 .\" https://lwn.net/Articles/375888/
326 .\" "Open by handle" - Jonathan Corbet, 2010-02-23
327 This sort of functionality allows a user-space file server to operate in
328 a stateless fashion with respect to the files it serves.
335 .BR name_to_handle_at ()
336 that operates on a symbolic link can be used to obtain a handle for the link.
337 .\" commit bcda76524cd1fa32af748536f27f674a13e56700
338 The process receiving the handle can later perform operations
339 on the symbolic link by converting the handle to a file descriptor using
340 .BR open_by_handle_at ()
341 and then passing the file descriptor as the
343 argument in system calls such as
347 .SS Obtaining a persistent filesystem ID
349 .IR /proc/self/mountinfo
350 can be reused as filesystems are unmounted and mounted.
351 Therefore, the mount ID returned by
352 .BR name_to_handle_at (3)
355 should not be treated as a persistent identifier
356 for the corresponding mounted filesystem.
357 However, an application can use the information in the
359 record that corresponds to the mount ID
360 to derive a persistent identifier.
362 For example, one can use the device name in the fifth field of the
364 record to search for the corresponding device UUID via the symbolic links in
365 .IR /dev/disks/by-uuid .
366 (A more comfortable way of obtaining the UUID is to use the
367 .\" e.g., http://stackoverflow.com/questions/6748429/using-libblkid-to-find-uuid-of-a-partition
369 library, which uses the
371 filesystem to obtain the same information.)
372 That process can then be reversed,
373 using the UUID to look up the device name,
374 and then obtaining the corresponding mount point,
375 in order to produce the
378 .BR open_by_name_at ().
380 The two programs below demonstrate the use of
381 .BR name_to_handle_at ()
383 .BR open_by_handle_at ().
385 .RI ( t_name_to_handle_at.c )
387 .BR name_to_handle_at ()
388 to obtain the file handle and mount ID
389 for the file specified in its command-line argument;
390 the handle and ID are written to standard output.
393 .RI ( t_open_by_handle_at.c )
394 reads a mount ID and file handle from standard input.
395 The program then employs
396 .BR open_by_handle_at ()
397 to open the file using that handle.
398 If an optional command-line argument is supplied, then the
401 .BR open_by_handle_at ()
402 is obtained by opening the directory named in that argument.
405 is obtained by scanning
406 .IR /proc/self/mountinfo
407 to find a record whose mount ID matches the mount ID
408 read from standard input,
409 and the mount directory specified in that record is opened.
410 (These programs do not deal with the fact that mount IDs are not persistent.)
412 The following shell session demonstrates the use of these two programs:
416 $ \fBecho 'Kannst du bitte überlegen?' > cecilia.txt\fP
417 $ \fB./t_name_to_handle_at cecilia.txt > fh\fP
418 $ \fB./t_open_by_handle_at < fh\fP
419 open_by_handle_at: Operation not permitted
420 $ \fBsudo ./t_open_by_handle_at < fh\fP # Need CAP_SYS_ADMIN
422 $ \fBrm cecilia.txt\fP
426 Now delete and re-create the file with the same inode number;
427 .BR open_by_handle_at ()
428 recognizes that the file referred to by the file handle no longer exists.
432 $ \fBstat \-\-printf="%i\\n" cecilia.txt\fP # Display inode number
434 $ \fBecho 'Warum?' > cecilia.txt\fP
435 $ \fBstat \-\-printf="%i\\n" cecilia.txt\fP # Check inode number
437 $ \fBsudo ./t_open_by_handle_at < fh\fP
438 open_by_handle_at: Stale NFS file handle
441 .SS Program source: t_name_to_handle_at.c
445 #include <sys/types.h>
446 #include <sys/stat.h>
454 #define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \\
458 main(int argc, char *argv[])
460 struct file_handle *fhp;
461 int mount_id, fhsize, s;
463 if (argc < 2 || strcmp(argv[1], "\-\-help") == 0) {
464 fprintf(stderr, "Usage: %s pathname\\n", argv[0]);
468 /* Allocate file_handle structure */
470 fhsize = sizeof(struct file_handle *);
471 fhp = malloc(fhsize);
475 /* Make an initial call to name_to_handle_at() to discover
476 the size required for file handle */
478 fhp\->handle_bytes = 0;
479 s = name_to_handle_at(AT_FDCWD, argv[1], fhp, &mount_id, 0);
480 if (s != \-1 || errno != EOVERFLOW) {
481 fprintf(stderr, "Unexpected result from name_to_handle_at()\\n");
485 /* Reallocate file_handle structure with correct size */
487 fhsize = sizeof(struct file_handle) + fhp\->handle_bytes;
488 fhp = realloc(fhp, fhsize); /* Copies fhp\->handle_bytes */
492 /* Get file handle from pathname supplied on command line */
494 if (name_to_handle_at(AT_FDCWD, argv[1], fhp, &mount_id, 0) == \-1)
495 errExit("name_to_handle_at");
497 /* Write mount ID, file handle size, and file handle to stdout,
498 for later reuse by t_open_by_handle_at.c */
500 if (write(STDOUT_FILENO, &mount_id, sizeof(int)) != sizeof(int) ||
501 write(STDOUT_FILENO, &fhsize, sizeof(int)) != sizeof(int) ||
502 write(STDOUT_FILENO, fhp, fhsize) != fhsize) {
503 fprintf(stderr, "Write failure\\n");
510 .SS Program source: t_open_by_handle_at.c
514 #include <sys/types.h>
515 #include <sys/stat.h>
523 #define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \\
526 /* Scan /proc/self/mountinfo to find the line whose mount ID matches
527 \(aqmount_id\(aq. (An easier way to do this is to install and use the
528 \(aqlibmount\(aq library provided by the \(aqutil\-linux\(aq project.)
529 Open the corresponding mount path and return the resulting file
533 open_mount_path_by_id(int mount_id)
537 char mount_path[PATH_MAX];
538 int fmnt_id, fnd, nread;
541 fp = fopen("/proc/self/mountinfo", "r");
545 for (fnd = 0; !fnd ; ) {
547 nread = getline(&linep, &lsize, fp);
551 nread = sscanf(linep, "%d %*d %*s %*s %s", &fmnt_id, mount_path);
553 fprintf(stderr, "Bad sscanf()\\n");
559 if (fmnt_id == mount_id)
566 fprintf(stderr, "Could not find mount point\\n");
570 return open(mount_path, O_RDONLY | O_DIRECTORY);
574 main(int argc, char *argv[])
576 struct file_handle *fhp;
577 int mount_id, fd, mount_fd, fhsize;
582 if (argc > 1 && strcmp(argv[1], "\-\-help") == 0) {
583 fprintf(stderr, "Usage: %s [mount\-dir]]\\n",
588 /* Read data produced by t_name_to_handle_at.c */
590 if (read(STDIN_FILENO, &mount_id, sizeof(int)) != sizeof(int))
593 if (read(STDIN_FILENO, &fhsize, sizeof(int)) != sizeof(int))
596 fhp = malloc(fhsize);
600 if (read(STDIN_FILENO, fhp, fhsize) != fhsize)
603 /* Obtain file descriptor for mount point, either by opening
604 the pathname specified on the command line, or by scanning
605 /proc/self/mounts to find a mount that matches the \(aqmount_id\(aq
606 obtained by name_to_handle_at() (in t_name_to_handle_at.c) */
609 mount_fd = open(argv[1], O_RDONLY | O_DIRECTORY);
611 mount_fd = open_mount_path_by_id(mount_id);
614 errExit("opening mount fd");
616 /* Open name using handle and mount point */
618 fd = open_by_handle_at(mount_fd, fhp, O_RDONLY);
620 errExit("open_by_handle_at");
622 /* Try reading a few bytes from the file */
624 nread = read(fd, buf, BSIZE);
627 printf("Read %ld bytes\\n", (long) nread);
643 documentation under the latest
646 .UR https://www.kernel.org/pub/linux/utils/util-linux/