]> git.ipfire.org Git - thirdparty/man-pages.git/blob - man2/open_by_handle_at.2
Many pages: Fix style issues reported by `make lint-groff`
[thirdparty/man-pages.git] / man2 / open_by_handle_at.2
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 2021-08-27 "Linux" "Linux Programmer's Manual"
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] */
59 };
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.
103 .PP
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
110 and
111 .I f_handle
112 fields are needed only by a subsequent call to
113 .BR open_by_handle_at ().
114 .PP
115 The
116 .I flags
117 argument is a bit mask constructed by ORing together zero or more of
118 .B AT_EMPTY_PATH
119 and
120 .BR AT_SYMLINK_FOLLOW ,
121 described below.
122 .PP
123 Together, the
124 .I pathname
125 and
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
130 If
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 *
138 If
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 *
149 If
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 *
162 If
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,
171 or
172 .BR AT_FDCWD ,
173 meaning the current working directory,
174 and a handle is returned for the file to which it refers.
175 .PP
176 The
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 .
191 .PP
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.
197 If
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).
204 .PP
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()
222 The
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 ().
228 .PP
229 The
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.
238 .PP
239 The
240 .I flags
241 argument
242 is as for
243 .BR open (2).
244 If
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.
251 .PP
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,
260 and
261 .BR open_by_handle_at ()
262 returns a file descriptor (a nonnegative integer).
263 .PP
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 ()
269 and
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.
274 .PP
275 .BR name_to_handle_at ()
276 can fail with the following errors:
277 .TP
278 .B EFAULT
279 .IR pathname ,
280 .IR mount_id ,
281 or
282 .I handle
283 points outside your accessible address space.
284 .TP
285 .B EINVAL
286 .I flags
287 includes an invalid bit value.
288 .TP
289 .B EINVAL
290 .I handle\->handle_bytes
291 is greater than
292 .BR MAX_HANDLE_SZ .
293 .TP
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 .
300 .TP
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
309 and
310 .I pathname
311 is an empty string.
312 .TP
313 .B EOPNOTSUPP
314 The filesystem does not support decoding of a pathname to a file handle.
315 .TP
316 .B EOVERFLOW
317 The
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.
323 .\"
324 .\"
325 .PP
326 .BR open_by_handle_at ()
327 can fail with the following errors:
328 .TP
329 .B EBADF
330 .I mount_fd
331 is not an open file descriptor.
332 .TP
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.
340 .TP
341 .B EFAULT
342 .I handle
343 points outside your accessible address space.
344 .TP
345 .B EINVAL
346 .I handle\->handle_bytes
347 is greater than
348 .B MAX_HANDLE_SZ
349 or is equal to zero.
350 .TP
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 .
357 .TP
358 .B EPERM
359 The caller does not have the
360 .B CAP_DAC_READ_SEARCH
361 capability.
362 .TP
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 CONFORMING TO
372 These system calls are nonstandard Linux extensions.
373 .PP
374 FreeBSD has a broadly similar pair of system calls in the form of
375 .BR getfh ()
376 and
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 ().
383 .PP
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.
389 .PP
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 ().
396 .PP
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.
406 .PP
407 If
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)
426 and
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 ()
434 (in
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.
442 .PP
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 ()
461 and
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.
470 .PP
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.)
490 .PP
491 The following shell session demonstrates the use of these two programs:
492 .PP
493 .in +4n
494 .EX
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
502 .EE
503 .in
504 .PP
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.
513 .PP
514 .in +4n
515 .EX
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
524 .EE
525 .in
526 .SS Program source: t_name_to_handle_at.c
527 \&
528 .EX
529 #define _GNU_SOURCE
530 #include <sys/types.h>
531 #include <sys/stat.h>
532 #include <fcntl.h>
533 #include <stdio.h>
534 #include <stdlib.h>
535 #include <unistd.h>
536 #include <errno.h>
537 #include <string.h>
538
539 #define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \e
540 } while (0)
541
542 int
543 main(int argc, char *argv[])
544 {
545 struct file_handle *fhp;
546 int mount_id, fhsize, flags, dirfd;
547 char *pathname;
548
549 if (argc != 2) {
550 fprintf(stderr, "Usage: %s pathname\en", argv[0]);
551 exit(EXIT_FAILURE);
552 }
553
554 pathname = argv[1];
555
556 /* Allocate file_handle structure. */
557
558 fhsize = sizeof(*fhp);
559 fhp = malloc(fhsize);
560 if (fhp == NULL)
561 errExit("malloc");
562
563 /* Make an initial call to name_to_handle_at() to discover
564 the size required for file handle. */
565
566 dirfd = AT_FDCWD; /* For name_to_handle_at() calls */
567 flags = 0; /* For name_to_handle_at() calls */
568 fhp\->handle_bytes = 0;
569 if (name_to_handle_at(dirfd, pathname, fhp,
570 &mount_id, flags) != \-1 || errno != EOVERFLOW) {
571 fprintf(stderr, "Unexpected result from name_to_handle_at()\en");
572 exit(EXIT_FAILURE);
573 }
574
575 /* Reallocate file_handle structure with correct size. */
576
577 fhsize = sizeof(*fhp) + fhp\->handle_bytes;
578 fhp = realloc(fhp, fhsize); /* Copies fhp\->handle_bytes */
579 if (fhp == NULL)
580 errExit("realloc");
581
582 /* Get file handle from pathname supplied on command line. */
583
584 if (name_to_handle_at(dirfd, pathname, fhp, &mount_id, flags) == \-1)
585 errExit("name_to_handle_at");
586
587 /* Write mount ID, file handle size, and file handle to stdout,
588 for later reuse by t_open_by_handle_at.c. */
589
590 printf("%d\en", mount_id);
591 printf("%u %d ", fhp\->handle_bytes, fhp\->handle_type);
592 for (int j = 0; j < fhp\->handle_bytes; j++)
593 printf(" %02x", fhp\->f_handle[j]);
594 printf("\en");
595
596 exit(EXIT_SUCCESS);
597 }
598 .EE
599 .SS Program source: t_open_by_handle_at.c
600 \&
601 .EX
602 #define _GNU_SOURCE
603 #include <sys/types.h>
604 #include <sys/stat.h>
605 #include <fcntl.h>
606 #include <limits.h>
607 #include <stdio.h>
608 #include <stdlib.h>
609 #include <unistd.h>
610 #include <string.h>
611
612 #define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \e
613 } while (0)
614
615 /* Scan /proc/self/mountinfo to find the line whose mount ID matches
616 \(aqmount_id\(aq. (An easier way to do this is to install and use the
617 \(aqlibmount\(aq library provided by the \(aqutil\-linux\(aq project.)
618 Open the corresponding mount path and return the resulting file
619 descriptor. */
620
621 static int
622 open_mount_path_by_id(int mount_id)
623 {
624 char *linep;
625 size_t lsize;
626 char mount_path[PATH_MAX];
627 int mi_mount_id, found;
628 ssize_t nread;
629 FILE *fp;
630
631 fp = fopen("/proc/self/mountinfo", "r");
632 if (fp == NULL)
633 errExit("fopen");
634
635 found = 0;
636 linep = NULL;
637 while (!found) {
638 nread = getline(&linep, &lsize, fp);
639 if (nread == \-1)
640 break;
641
642 nread = sscanf(linep, "%d %*d %*s %*s %s",
643 &mi_mount_id, mount_path);
644 if (nread != 2) {
645 fprintf(stderr, "Bad sscanf()\en");
646 exit(EXIT_FAILURE);
647 }
648
649 if (mi_mount_id == mount_id)
650 found = 1;
651 }
652 free(linep);
653
654 fclose(fp);
655
656 if (!found) {
657 fprintf(stderr, "Could not find mount point\en");
658 exit(EXIT_FAILURE);
659 }
660
661 return open(mount_path, O_RDONLY);
662 }
663
664 int
665 main(int argc, char *argv[])
666 {
667 struct file_handle *fhp;
668 int mount_id, fd, mount_fd, handle_bytes;
669 ssize_t nread;
670 char buf[1000];
671 #define LINE_SIZE 100
672 char line1[LINE_SIZE], line2[LINE_SIZE];
673 char *nextp;
674
675 if ((argc > 1 && strcmp(argv[1], "\-\-help") == 0) || argc > 2) {
676 fprintf(stderr, "Usage: %s [mount\-path]\en", argv[0]);
677 exit(EXIT_FAILURE);
678 }
679
680 /* Standard input contains mount ID and file handle information:
681
682 Line 1: <mount_id>
683 Line 2: <handle_bytes> <handle_type> <bytes of handle in hex>
684 */
685
686 if ((fgets(line1, sizeof(line1), stdin) == NULL) ||
687 (fgets(line2, sizeof(line2), stdin) == NULL)) {
688 fprintf(stderr, "Missing mount_id / file handle\en");
689 exit(EXIT_FAILURE);
690 }
691
692 mount_id = atoi(line1);
693
694 handle_bytes = strtoul(line2, &nextp, 0);
695
696 /* Given handle_bytes, we can now allocate file_handle structure. */
697
698 fhp = malloc(sizeof(*fhp) + handle_bytes);
699 if (fhp == NULL)
700 errExit("malloc");
701
702 fhp\->handle_bytes = handle_bytes;
703
704 fhp\->handle_type = strtoul(nextp, &nextp, 0);
705
706 for (int j = 0; j < fhp\->handle_bytes; j++)
707 fhp\->f_handle[j] = strtoul(nextp, &nextp, 16);
708
709 /* Obtain file descriptor for mount point, either by opening
710 the pathname specified on the command line, or by scanning
711 /proc/self/mounts to find a mount that matches the \(aqmount_id\(aq
712 that we received from stdin. */
713
714 if (argc > 1)
715 mount_fd = open(argv[1], O_RDONLY);
716 else
717 mount_fd = open_mount_path_by_id(mount_id);
718
719 if (mount_fd == \-1)
720 errExit("opening mount fd");
721
722 /* Open file using handle and mount point. */
723
724 fd = open_by_handle_at(mount_fd, fhp, O_RDONLY);
725 if (fd == \-1)
726 errExit("open_by_handle_at");
727
728 /* Try reading a few bytes from the file. */
729
730 nread = read(fd, buf, sizeof(buf));
731 if (nread == \-1)
732 errExit("read");
733
734 printf("Read %zd bytes\en", nread);
735
736 exit(EXIT_SUCCESS);
737 }
738 .EE
739 .SH SEE ALSO
740 .BR open (2),
741 .BR libblkid (3),
742 .BR blkid (8),
743 .BR findfs (8),
744 .BR mount (8)
745 .PP
746 The
747 .I libblkid
748 and
749 .I libmount
750 documentation in the latest
751 .I util\-linux
752 release at
753 .UR https://www.kernel.org/pub/linux/utils/util\-linux/
754 .UE