Start of man-pages-NEXT: Move Changes to Changes.old
[man-pages.git] / man2 / open_by_handle_at.2
blob76239e74597e98af73f0d783249b284d6f40da1f
1 .\" Copyright (c) 2014 by Michael Kerrisk <mtk.manpages@gmail.com>
2 .\"
3 .\" SPDX-License-Identifier: Linux-man-pages-copyleft
4 .\"
5 .TH OPEN_BY_HANDLE_AT 2 2022-09-17 "Linux man-pages (unreleased)"
6 .SH NAME
7 name_to_handle_at, open_by_handle_at \- obtain handle
8 for a pathname and open file via a handle
9 .SH LIBRARY
10 Standard C library
11 .RI ( libc ", " \-lc )
12 .SH SYNOPSIS
13 .nf
14 .BR "#define _GNU_SOURCE" "         /* See feature_test_macros(7) */"
15 .B #include <fcntl.h>
16 .PP
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 ,
21 .BI "                      int " flags );
22 .fi
23 .SH DESCRIPTION
24 The
25 .BR name_to_handle_at ()
26 and
27 .BR open_by_handle_at ()
28 system calls split the functionality of
29 .BR openat (2)
30 into two parts:
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.
37 .\"
38 .\"
39 .SS name_to_handle_at()
40 The
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
44 .I dirfd
45 and
46 .I pathname
47 arguments.
48 The file handle is returned via the argument
49 .IR handle ,
50 which is a pointer to a structure of the following form:
51 .PP
52 .in +4n
53 .EX
54 struct file_handle {
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
58                                      caller) [out] */
60 .EE
61 .in
62 .PP
63 It is the caller's responsibility to allocate the structure
64 with a size large enough to hold the handle returned in
65 .IR f_handle .
66 Before the call, the
67 .I handle_bytes
68 field should be initialized to contain the allocated size for
69 .IR f_handle .
70 (The constant
71 .BR MAX_HANDLE_SZ ,
72 defined in
73 .IR <fcntl.h> ,
74 specifies the maximum expected size for a file handle.
75 It is not a
76 guaranteed upper limit as future filesystems may require more space.)
77 Upon successful return, the
78 .I handle_bytes
79 field is updated to contain the number of bytes actually written to
80 .IR f_handle .
81 .PP
82 The caller can discover the required size for the
83 .I file_handle
84 structure by making a call in which
85 .I handle\->handle_bytes
86 is zero;
87 in this case, the call fails with the error
88 .B EOVERFLOW
89 and
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
95 .B EOVERFLOW
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
99 .B EOVERFLOW
100 error is returned without
101 .I handle_bytes
102 being increased.
104 Other than the use of the
105 .I handle_bytes
106 field, the caller should treat the
107 .I file_handle
108 structure as an opaque data type: the
109 .I handle_type
111 .I f_handle
112 fields are needed only by a subsequent call to
113 .BR open_by_handle_at ().
116 .I flags
117 argument is a bit mask constructed by ORing together zero or more of
118 .B AT_EMPTY_PATH
120 .BR AT_SYMLINK_FOLLOW ,
121 described below.
123 Together, the
124 .I pathname
126 .I dirfd
127 arguments identify the file for which a handle is to be obtained.
128 There are four distinct cases:
129 .IP * 3
131 .I pathname
132 is a nonempty string containing an absolute pathname,
133 then a handle is returned for the file referred to by that pathname.
134 In this case,
135 .I dirfd
136 is ignored.
137 .IP *
139 .I pathname
140 is a nonempty string containing a relative pathname and
141 .I dirfd
142 has the special value
143 .BR AT_FDCWD ,
144 then
145 .I pathname
146 is interpreted relative to the current working directory of the caller,
147 and a handle is returned for the file to which it refers.
148 .IP *
150 .I pathname
151 is a nonempty string containing a relative pathname and
152 .I dirfd
153 is a file descriptor referring to a directory, then
154 .I pathname
155 is interpreted relative to the directory referred to by
156 .IR dirfd ,
157 and a handle is returned for the file to which it refers.
158 (See
159 .BR openat (2)
160 for an explanation of why "directory file descriptors" are useful.)
161 .IP *
163 .I pathname
164 is an empty string and
165 .I flags
166 specifies the value
167 .BR AT_EMPTY_PATH ,
168 then
169 .I dirfd
170 can be an open file descriptor referring to any type of file,
172 .BR AT_FDCWD ,
173 meaning the current working directory,
174 and a handle is returned for the file to which it refers.
177 .I mount_id
178 argument returns an identifier for the filesystem
179 mount that corresponds to
180 .IR pathname .
181 This corresponds to the first field in one of the records in
182 .IR /proc/self/mountinfo .
183 Opening the pathname in the fifth field of that record yields a file
184 descriptor for the mount point;
185 that file descriptor can be used in a subsequent call to
186 .BR open_by_handle_at ().
187 .I mount_id
188 is returned both for a successful call and for a call that results
189 in the error
190 .BR EOVERFLOW .
192 By default,
193 .BR name_to_handle_at ()
194 does not dereference
195 .I pathname
196 if it is a symbolic link, and thus returns a handle for the link itself.
198 .B AT_SYMLINK_FOLLOW
199 is specified in
200 .IR flags ,
201 .I pathname
202 is dereferenced if it is a symbolic link
203 (so that the call returns a handle for the file referred to by the link).
205 .BR name_to_handle_at ()
206 does not trigger a mount when the final component of the pathname is an
207 automount point.
208 When a filesystem supports both file handles and
209 automount points, a
210 .BR name_to_handle_at ()
211 call on an automount point will return with error
212 .B EOVERFLOW
213 without having increased
214 .IR handle_bytes .
215 This can happen since Linux 4.13
216 .\" commit 20fa19027286983ab2734b5910c4a687436e0c31
217 with NFS when accessing a directory
218 which is on a separate filesystem on the server.
219 In this case, the automount can be triggered by adding a "/" to the end
220 of the pathname.
221 .SS open_by_handle_at()
223 .BR open_by_handle_at ()
224 system call opens the file referred to by
225 .IR handle ,
226 a file handle returned by a previous call to
227 .BR name_to_handle_at ().
230 .I mount_fd
231 argument is a file descriptor for any object (file, directory, etc.)
232 in the mounted filesystem with respect to which
233 .I handle
234 should be interpreted.
235 The special value
236 .B AT_FDCWD
237 can be specified, meaning the current working directory of the caller.
240 .I flags
241 argument
242 is as for
243 .BR open (2).
245 .I handle
246 refers to a symbolic link, the caller must specify the
247 .B O_PATH
248 flag, and the symbolic link is not dereferenced; the
249 .B O_NOFOLLOW
250 flag, if specified, is ignored.
252 The caller must have the
253 .B CAP_DAC_READ_SEARCH
254 capability to invoke
255 .BR open_by_handle_at ().
256 .SH RETURN VALUE
257 On success,
258 .BR name_to_handle_at ()
259 returns 0,
261 .BR open_by_handle_at ()
262 returns a file descriptor (a nonnegative integer).
264 In the event of an error, both system calls return \-1 and set
265 .I errno
266 to indicate the error.
267 .SH ERRORS
268 .BR name_to_handle_at ()
270 .BR open_by_handle_at ()
271 can fail for the same errors as
272 .BR openat (2).
273 In addition, they can fail with the errors noted below.
275 .BR name_to_handle_at ()
276 can fail with the following errors:
278 .B EFAULT
279 .IR pathname ,
280 .IR mount_id ,
282 .I handle
283 points outside your accessible address space.
285 .B EINVAL
286 .I flags
287 includes an invalid bit value.
289 .B EINVAL
290 .I handle\->handle_bytes
291 is greater than
292 .BR MAX_HANDLE_SZ .
294 .B ENOENT
295 .I pathname
296 is an empty string, but
297 .B AT_EMPTY_PATH
298 was not specified in
299 .IR flags .
301 .B ENOTDIR
302 The file descriptor supplied in
303 .I dirfd
304 does not refer to a directory,
305 and it is not the case that both
306 .I flags
307 includes
308 .B AT_EMPTY_PATH
310 .I pathname
311 is an empty string.
313 .B EOPNOTSUPP
314 The filesystem does not support decoding of a pathname to a file handle.
316 .B EOVERFLOW
318 .I handle\->handle_bytes
319 value passed into the call was too small.
320 When this error occurs,
321 .I handle\->handle_bytes
322 is updated to indicate the required size for the handle.
326 .BR open_by_handle_at ()
327 can fail with the following errors:
329 .B EBADF
330 .I mount_fd
331 is not an open file descriptor.
333 .B EBADF
334 .I pathname
335 is relative but
336 .I dirfd
337 is neither
338 .B AT_FDCWD
339 nor a valid file descriptor.
341 .B EFAULT
342 .I handle
343 points outside your accessible address space.
345 .B EINVAL
346 .I handle\->handle_bytes
347 is greater than
348 .B MAX_HANDLE_SZ
349 or is equal to zero.
351 .B ELOOP
352 .I handle
353 refers to a symbolic link, but
354 .B O_PATH
355 was not specified in
356 .IR flags .
358 .B EPERM
359 The caller does not have the
360 .B CAP_DAC_READ_SEARCH
361 capability.
363 .B ESTALE
364 The specified
365 .I handle
366 is not valid.
367 This error will occur if, for example, the file has been deleted.
368 .SH VERSIONS
369 These system calls first appeared in Linux 2.6.39.
370 Library support is provided in glibc since version 2.14.
371 .SH STANDARDS
372 These system calls are nonstandard Linux extensions.
374 FreeBSD has a broadly similar pair of system calls in the form of
375 .BR getfh ()
377 .BR openfh ().
378 .SH NOTES
379 A file handle can be generated in one process using
380 .BR name_to_handle_at ()
381 and later used in a different process that calls
382 .BR open_by_handle_at ().
384 Some filesystem don't support the translation of pathnames to
385 file handles, for example,
386 .IR /proc ,
387 .IR /sys ,
388 and various network filesystems.
390 A file handle may become invalid ("stale") if a file is deleted,
391 or for other filesystem-specific reasons.
392 Invalid handles are notified by an
393 .B ESTALE
394 error from
395 .BR open_by_handle_at ().
397 These system calls are designed for use by user-space file servers.
398 For example, a user-space NFS server might generate a file handle
399 and pass it to an NFS client.
400 Later, when the client wants to open the file,
401 it could pass the handle back to the server.
402 .\" https://lwn.net/Articles/375888/
403 .\"     "Open by handle" - Jonathan Corbet, 2010-02-23
404 This sort of functionality allows a user-space file server to operate in
405 a stateless fashion with respect to the files it serves.
408 .I pathname
409 refers to a symbolic link and
410 .I flags
411 does not specify
412 .BR AT_SYMLINK_FOLLOW ,
413 then
414 .BR name_to_handle_at ()
415 returns a handle for the link (rather than the file to which it refers).
416 .\" commit bcda76524cd1fa32af748536f27f674a13e56700
417 The process receiving the handle can later perform operations
418 on the symbolic link by converting the handle to a file descriptor using
419 .BR open_by_handle_at ()
420 with the
421 .B O_PATH
422 flag, and then passing the file descriptor as the
423 .I dirfd
424 argument in system calls such as
425 .BR readlinkat (2)
427 .BR fchownat (2).
428 .SS Obtaining a persistent filesystem ID
429 The mount IDs in
430 .I /proc/self/mountinfo
431 can be reused as filesystems are unmounted and mounted.
432 Therefore, the mount ID returned by
433 .BR name_to_handle_at ()
435 .IR *mount_id )
436 should not be treated as a persistent identifier
437 for the corresponding mounted filesystem.
438 However, an application can use the information in the
439 .I mountinfo
440 record that corresponds to the mount ID
441 to derive a persistent identifier.
443 For example, one can use the device name in the fifth field of the
444 .I mountinfo
445 record to search for the corresponding device UUID via the symbolic links in
446 .IR /dev/disks/by\-uuid .
447 (A more comfortable way of obtaining the UUID is to use the
448 .\" e.g., http://stackoverflow.com/questions/6748429/using-libblkid-to-find-uuid-of-a-partition
449 .BR libblkid (3)
450 library.)
451 That process can then be reversed,
452 using the UUID to look up the device name,
453 and then obtaining the corresponding mount point,
454 in order to produce the
455 .I mount_fd
456 argument used by
457 .BR open_by_handle_at ().
458 .SH EXAMPLES
459 The two programs below demonstrate the use of
460 .BR name_to_handle_at ()
462 .BR open_by_handle_at ().
463 The first program
464 .RI ( t_name_to_handle_at.c )
465 uses
466 .BR name_to_handle_at ()
467 to obtain the file handle and mount ID
468 for the file specified in its command-line argument;
469 the handle and mount ID are written to standard output.
471 The second program
472 .RI ( t_open_by_handle_at.c )
473 reads a mount ID and file handle from standard input.
474 The program then employs
475 .BR open_by_handle_at ()
476 to open the file using that handle.
477 If an optional command-line argument is supplied, then the
478 .I mount_fd
479 argument for
480 .BR open_by_handle_at ()
481 is obtained by opening the directory named in that argument.
482 Otherwise,
483 .I mount_fd
484 is obtained by scanning
485 .I /proc/self/mountinfo
486 to find a record whose mount ID matches the mount ID
487 read from standard input,
488 and the mount directory specified in that record is opened.
489 (These programs do not deal with the fact that mount IDs are not persistent.)
491 The following shell session demonstrates the use of these two programs:
493 .in +4n
495 $ \fBecho \(aqCan you please think about it?\(aq > cecilia.txt\fP
496 $ \fB./t_name_to_handle_at cecilia.txt > fh\fP
497 $ \fB./t_open_by_handle_at < fh\fP
498 open_by_handle_at: Operation not permitted
499 $ \fBsudo ./t_open_by_handle_at < fh\fP      # Need CAP_SYS_ADMIN
500 Read 31 bytes
501 $ \fBrm cecilia.txt\fP
505 Now we delete and (quickly) re-create the file so that
506 it has the same content and (by chance) the same inode.
507 Nevertheless,
508 .BR open_by_handle_at ()
509 .\" Christoph Hellwig: That's why the file handles contain a generation
510 .\" counter that gets incremented in this case.
511 recognizes that the original file referred to by the file handle
512 no longer exists.
514 .in +4n
516 $ \fBstat \-\-printf="%i\en" cecilia.txt\fP     # Display inode number
517 4072121
518 $ \fBrm cecilia.txt\fP
519 $ \fBecho \(aqCan you please think about it?\(aq > cecilia.txt\fP
520 $ \fBstat \-\-printf="%i\en" cecilia.txt\fP     # Check inode number
521 4072121
522 $ \fBsudo ./t_open_by_handle_at < fh\fP
523 open_by_handle_at: Stale NFS file handle
526 .SS Program source: t_name_to_handle_at.c
528 .\" SRC BEGIN (t_name_to_handle_at.c)
530 #define _GNU_SOURCE
531 #include <err.h>
532 #include <errno.h>
533 #include <fcntl.h>
534 #include <stdio.h>
535 #include <stdlib.h>
538 main(int argc, char *argv[])
540     int                 mount_id, fhsize, flags, dirfd;
541     char                *pathname;
542     struct file_handle  *fhp;
544     if (argc != 2) {
545         fprintf(stderr, "Usage: %s pathname\en", argv[0]);
546         exit(EXIT_FAILURE);
547     }
549     pathname = argv[1];
551     /* Allocate file_handle structure. */
553     fhsize = sizeof(*fhp);
554     fhp = malloc(fhsize);
555     if (fhp == NULL)
556         err(EXIT_FAILURE, "malloc");
558     /* Make an initial call to name_to_handle_at() to discover
559        the size required for file handle. */
561     dirfd = AT_FDCWD;           /* For name_to_handle_at() calls */
562     flags = 0;                  /* For name_to_handle_at() calls */
563     fhp\->handle_bytes = 0;
564     if (name_to_handle_at(dirfd, pathname, fhp,
565                           &mount_id, flags) != \-1
566         || errno != EOVERFLOW)
567     {
568         fprintf(stderr, "Unexpected result from name_to_handle_at()\en");
569         exit(EXIT_FAILURE);
570     }
572     /* Reallocate file_handle structure with correct size. */
574     fhsize = sizeof(*fhp) + fhp\->handle_bytes;
575     fhp = realloc(fhp, fhsize);         /* Copies fhp\->handle_bytes */
576     if (fhp == NULL)
577         err(EXIT_FAILURE, "realloc");
579     /* Get file handle from pathname supplied on command line. */
581     if (name_to_handle_at(dirfd, pathname, fhp, &mount_id, flags) == \-1)
582         err(EXIT_FAILURE, "name_to_handle_at");
584     /* Write mount ID, file handle size, and file handle to stdout,
585        for later reuse by t_open_by_handle_at.c. */
587     printf("%d\en", mount_id);
588     printf("%u %d   ", fhp\->handle_bytes, fhp\->handle_type);
589     for (size_t j = 0; j < fhp\->handle_bytes; j++)
590         printf(" %02x", fhp\->f_handle[j]);
591     printf("\en");
593     exit(EXIT_SUCCESS);
596 .\" SRC END
597 .SS Program source: t_open_by_handle_at.c
599 .\" SRC BEGIN (t_open_by_handle_at.c)
601 #define _GNU_SOURCE
602 #include <err.h>
603 #include <fcntl.h>
604 #include <limits.h>
605 #include <stdio.h>
606 #include <stdlib.h>
607 #include <string.h>
608 #include <unistd.h>
610 /* Scan /proc/self/mountinfo to find the line whose mount ID matches
611    \(aqmount_id\(aq. (An easier way to do this is to install and use the
612    \(aqlibmount\(aq library provided by the \(aqutil\-linux\(aq project.)
613    Open the corresponding mount path and return the resulting file
614    descriptor. */
616 static int
617 open_mount_path_by_id(int mount_id)
619     int      mi_mount_id, found;
620     char     mount_path[PATH_MAX];
621     char     *linep;
622     FILE     *fp;
623     size_t   lsize;
624     ssize_t  nread;
626     fp = fopen("/proc/self/mountinfo", "r");
627     if (fp == NULL)
628         err(EXIT_FAILURE, "fopen");
630     found = 0;
631     linep = NULL;
632     while (!found) {
633         nread = getline(&linep, &lsize, fp);
634         if (nread == \-1)
635             break;
637         nread = sscanf(linep, "%d %*d %*s %*s %s",
638                        &mi_mount_id, mount_path);
639         if (nread != 2) {
640             fprintf(stderr, "Bad sscanf()\en");
641             exit(EXIT_FAILURE);
642         }
644         if (mi_mount_id == mount_id)
645             found = 1;
646     }
647     free(linep);
649     fclose(fp);
651     if (!found) {
652         fprintf(stderr, "Could not find mount point\en");
653         exit(EXIT_FAILURE);
654     }
656     return open(mount_path, O_RDONLY);
660 main(int argc, char *argv[])
662     int                 mount_id, fd, mount_fd, handle_bytes;
663     char                buf[1000];
664 #define LINE_SIZE 100
665     char                line1[LINE_SIZE], line2[LINE_SIZE];
666     char                *nextp;
667     ssize_t             nread;
668     struct file_handle  *fhp;
670     if ((argc > 1 && strcmp(argv[1], "\-\-help") == 0) || argc > 2) {
671         fprintf(stderr, "Usage: %s [mount\-path]\en", argv[0]);
672         exit(EXIT_FAILURE);
673     }
675     /* Standard input contains mount ID and file handle information:
677          Line 1: <mount_id>
678          Line 2: <handle_bytes> <handle_type>   <bytes of handle in hex>
679     */
681     if (fgets(line1, sizeof(line1), stdin) == NULL ||
682         fgets(line2, sizeof(line2), stdin) == NULL)
683     {
684         fprintf(stderr, "Missing mount_id / file handle\en");
685         exit(EXIT_FAILURE);
686     }
688     mount_id = atoi(line1);
690     handle_bytes = strtoul(line2, &nextp, 0);
692     /* Given handle_bytes, we can now allocate file_handle structure. */
694     fhp = malloc(sizeof(*fhp) + handle_bytes);
695     if (fhp == NULL)
696         err(EXIT_FAILURE, "malloc");
698     fhp\->handle_bytes = handle_bytes;
700     fhp\->handle_type = strtoul(nextp, &nextp, 0);
702     for (size_t j = 0; j < fhp\->handle_bytes; j++)
703         fhp\->f_handle[j] = strtoul(nextp, &nextp, 16);
705     /* Obtain file descriptor for mount point, either by opening
706        the pathname specified on the command line, or by scanning
707        /proc/self/mounts to find a mount that matches the \(aqmount_id\(aq
708        that we received from stdin. */
710     if (argc > 1)
711         mount_fd = open(argv[1], O_RDONLY);
712     else
713         mount_fd = open_mount_path_by_id(mount_id);
715     if (mount_fd == \-1)
716         err(EXIT_FAILURE, "opening mount fd");
718     /* Open file using handle and mount point. */
720     fd = open_by_handle_at(mount_fd, fhp, O_RDONLY);
721     if (fd == \-1)
722         err(EXIT_FAILURE, "open_by_handle_at");
724     /* Try reading a few bytes from the file. */
726     nread = read(fd, buf, sizeof(buf));
727     if (nread == \-1)
728         err(EXIT_FAILURE, "read");
730     printf("Read %zd bytes\en", nread);
732     exit(EXIT_SUCCESS);
735 .\" SRC END
736 .SH SEE ALSO
737 .BR open (2),
738 .BR libblkid (3),
739 .BR blkid (8),
740 .BR findfs (8),
741 .BR mount (8)
744 .I libblkid
746 .I libmount
747 documentation in the latest
748 .I util\-linux
749 release at
750 .UR https://www.kernel.org/pub/linux/utils/util\-linux/