]> git.ipfire.org Git - thirdparty/man-pages.git/blob - man2/open_by_handle_at.2
open_by_handle_at.2: New page describing name_to_handle_at(2) and open_by_handle_at(2)
[thirdparty/man-pages.git] / man2 / open_by_handle_at.2
1 '\" t -*- coding: UTF-8 -*-
2 .\" Copyright (c) 2014 by Michael Kerrisk <mtk.manpages@gmail.com>
3 .\"
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.
8 .\"
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.
13 .\"
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
20 .\" professionally.
21 .\"
22 .\" Formatted or processed versions of this manual, if unaccompanied by
23 .\" the source, must acknowledge the copyright and authors of this work.
24 .\" %%%LICENSE_END
25 .\"
26 .TH OPEN_BY_HANDLE_AT 2 2014-03-24 "Linux" "Linux Programmer's Manual"
27 .SH NAME
28 name_to_handle_at, open_by_handle_at \- obtain handle
29 for a pathname and open file via a handle
30 .SH SYNOPSIS
31 .nf
32 .B #define _GNU_SOURCE
33 .B #include <sys/types.h>
34 .B #include <sys/stat.h>
35 .B #include <fcntl.h>
36
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 );
40
41 .BI "int open_by_handle_at(int " mountdirfd ", struct file_handle *" handle ,
42 .BI " int " flags );
43 .fi
44 .SH DESCRIPTION
45 The
46 .BR name_to_handle_at ()
47 and
48 .BR open_by_handle_at ()
49 system calls split the functionality of
50 .BR openat (2)
51 into two parts:
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()
59 The
60 .BR name_to_handle_at ()
61 system call returns a file handle and a mount ID corresponding to
62 the file specified by
63 .IR pathname ,
64 which specifies the pathname of an existing file.
65 The file handle is returned via the argument
66 .IR handle ,
67 which is a pointer to a structure of the following form:
68
69 .in +4n
70 .nf
71 struct file_handle {
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
75 caller) [out] */
76 };
77 .fi
78 .in
79 .PP
80 It is the caller's responsibility to allocate the structure
81 with a size large enough to hold the handle returned in
82 .IR f_handle .
83 Before the call, the
84 .IR handle_bytes
85 field should be initialized to contain the allocated size for
86 .IR f_handle .
87 (The constant
88 .BR MAX_HANDLE_SZ ,
89 defined in
90 .IR <fcntl.h> ,
91 specifies the maximum possible size for a file handle.)
92 Upon successful return, the
93 .IR handle_bytes
94 field is updated to contain the number of bytes actually written to
95 .IR f_handle .
96
97 The caller can discover the required size for the
98 .I file_handle
99 structure by making a call in which
100 .IR handle->handle_bytes
101 is zero;
102 in this case, the call fails with the error
103 .BR EOVERFLOW
104 and
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).
109
110 Other than the use of the
111 .IR handle_bytes
112 field, the caller should treat the
113 .IR file_handle
114 structure as an opaque data type: the
115 .IR handle_type
116 and
117 .IR f_handle
118 fields are needed only by a subsequent call to
119 .BR open_by_handle_at ().
120
121 The treatment of a relative pathname in
122 .I pathname
123 depends on the value of
124 .IR dirfd .
125 If
126 .I dirfd
127 has the special value
128 .BR AT_FDCWD ,
129 then
130 .I pathname
131 is interpreted relative to the current working
132 directory of the calling process.
133 (See
134 .BR openat (3)
135 for an explanation of why this is useful.)
136 Otherwise,
137 .IR dirfd
138 must be a file descriptor that refers to a directory, and
139 .I pathname
140 is interpreted relative to that directory.
141 If
142 .I pathname
143 is an absolute pathname, then
144 .I dirfd
145 is ignored.
146
147 The
148 .I mnt_id
149 argument returns an identifier for the filesystem
150 mount that corresponds to
151 .IR pathname .
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 ().
158
159 The
160 .I flags
161 argument is a bit mask constructed by ORing together
162 zero or more of the following value:
163 .TP
164 .B AT_EMPTY_PATH
165 If
166 .I pathname
167 is an empty string,
168 then obtain a handle for the file referred to by
169 .IR dirfd
170 (which may have been obtained using the
171 .BR open (2)
172 .B O_PATH
173 flag).
174 In this case,
175 .I dirfd
176 can refer to any type of file, not just a directory.
177 .TP
178 .B AT_SYMLINK_FOLLOW
179 By default,
180 .BR name_to_handle_at ()
181 does not dereference
182 .I pathname
183 if it is a symbolic link.
184 The flag
185 .B AT_SYMLINK_FOLLOW
186 can be specified in
187 .I flags
188 to cause
189 .I pathname
190 to be dereferenced if it is a symbolic link.
191 .SS open_by_handle_at()
192 The
193 .BR open_by_handle_at ()
194 system call opens the file referred to by
195 .IR handle ,
196 a file handle returned by a previous call to
197 .BR name_to_handle_at ().
198
199 The
200 .IR mountdirfd
201 argument is a file descriptor for a directory under
202 the mount point with respect to which
203 .IR handle
204 should be interpreted.
205 The special value
206 .B AT_FDCWD
207 can be specified, meaning the current working directory of the caller.
208
209 The
210 .I flags
211 argument
212 is as for
213 .BR open (2).
214
215 The caller must have the
216 .B CAP_DAC_READ_SEARCH
217 capability to invoke
218 .BR open_by_handle_at ().
219 .SH RETURN VALUE
220 On success,
221 .BR name_to_handle_at ()
222 returns 0,
223 and
224 .BR open_by_handle_at ()
225 returns a nonnegative file descriptor.
226
227 In the event of an error, both system calls return \-1 and set
228 .I errno
229 to indicate the cause of the error.
230 .SH ERRORS
231 .BR name_to_handle_at ()
232 and
233 .BR open_by_handle_at ()
234 can fail for the same errors as
235 .BR open (2).
236 In addition, they can fail with the errors noted below.
237
238 .BR name_to_handle_at ()
239 can fail with the following errors:
240 .TP
241 .B EBADF
242 .IR dirfd
243 is not an open file descriptor.
244 .TP
245 .B EINVAL
246 .I flags
247 includes an invalid bit value.
248 .TP
249 .B EINVAL
250 .IR handle_bytes\->handle_bytes
251 is greater than
252 .BR MAX_HANDLE_SZ .
253 .TP
254 .B ENOTDIR
255 The file descriptor supplied in
256 .I dirfd
257 does not refer to a directory,
258 and it it is not the case that both
259 .I flags
260 includes
261 .BR AT_EMPTY_PATH
262 and
263 .I pathname
264 is an empty string.
265 .TP
266 .B EOPNOTSUPP
267 The filesystem does not support decoding of a pathname to a file handle.
268 .TP
269 .B EOVERFLOW
270 The
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.
276 .\"
277 .\"
278 .PP
279 .BR open_by_handle_at ()
280 can fail with the following errors:
281 .TP
282 .B EBADF
283 .IR mountdirfd
284 is not an open file descriptor.
285 .TP
286 .B EINVAL
287 .I handle->handle_bytes
288 is greater than
289 .BR MAX_HANDLE_SZ
290 or is equal to zero.
291 .TP
292 .B ENOMEM
293 Insufficient memory.
294 .TP
295 .B ENOTDIR
296 .IR mountdirfd
297 is not
298 .B AT_FDCWD
299 and does not refer to a directory.
300 .TP
301 .B EPERM
302 The caller does not have the
303 .BR CAP_DAC_READ_SEARCH
304 capability.
305 .TP
306 .B ESTALE
307 The specified
308 .I handle
309 is no longer valid.
310 .SH VERSIONS
311 These system calls first appeared in Linux 2.6.39.
312 .SH CONFORMING TO
313 These system calls are nonstandard Linux extensions.
314 .SH NOTES
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 ().
319
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.
329
330 Specifying both
331 .BR O_PATH
332 and
333 .BR O_NOFOLLOW
334 in a call to
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
342 .IR dirfd
343 argument in system calls such as
344 .BR readlinkat (2)
345 and
346 .BR fchownat (2).
347 .SS Obtaining a persistent filesystem ID
348 The mount IDs in
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)
353 (in
354 .IR *mnt_id )
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
358 .I mountinfo
359 record that corresponds to the mount ID
360 to derive a persistent identifier.
361
362 For example, one can use the device name in the fifth field of the
363 .I mountinfo
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
368 .BR libblkid (3)
369 library, which uses the
370 .I /sys
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
376 .IR mountdirfd
377 argument used by
378 .BR open_by_name_at ().
379 .SH EXAMPLE
380 The two programs below demonstrate the use of
381 .BR name_to_handle_at ()
382 and
383 .BR open_by_handle_at ().
384 The first program
385 .RI ( t_name_to_handle_at.c )
386 uses
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.
391
392 The second program
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
399 .IR mountdirfd
400 argument for
401 .BR open_by_handle_at ()
402 is obtained by opening the directory named in that argument.
403 Otherwise,
404 .IR mountdirfd
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.)
411
412 The following shell session demonstrates the use of these two programs:
413
414 .in +4n
415 .nf
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
421 Read 28 bytes
422 $ \fBrm cecilia.txt\fP
423 .fi
424 .in
425
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.
429
430 .in +4n
431 .nf
432 $ \fBstat \-\-printf="%i\\n" cecilia.txt\fP # Display inode number
433 4072121
434 $ \fBecho 'Warum?' > cecilia.txt\fP
435 $ \fBstat \-\-printf="%i\\n" cecilia.txt\fP # Check inode number
436 4072121
437 $ \fBsudo ./t_open_by_handle_at < fh\fP
438 open_by_handle_at: Stale NFS file handle
439 .fi
440 .in
441 .SS Program source: t_name_to_handle_at.c
442 \&
443 .nf
444 #define _GNU_SOURCE
445 #include <sys/types.h>
446 #include <sys/stat.h>
447 #include <fcntl.h>
448 #include <stdio.h>
449 #include <stdlib.h>
450 #include <unistd.h>
451 #include <errno.h>
452 #include <string.h>
453
454 #define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \\
455 } while (0)
456
457 int
458 main(int argc, char *argv[])
459 {
460 struct file_handle *fhp;
461 int mount_id, fhsize, s;
462
463 if (argc < 2 || strcmp(argv[1], "\-\-help") == 0) {
464 fprintf(stderr, "Usage: %s pathname\\n", argv[0]);
465 exit(EXIT_FAILURE);
466 }
467
468 /* Allocate file_handle structure */
469
470 fhsize = sizeof(struct file_handle *);
471 fhp = malloc(fhsize);
472 if (fhp == NULL)
473 errExit("malloc");
474
475 /* Make an initial call to name_to_handle_at() to discover
476 the size required for file handle */
477
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");
482 exit(EXIT_FAILURE);
483 }
484
485 /* Reallocate file_handle structure with correct size */
486
487 fhsize = sizeof(struct file_handle) + fhp\->handle_bytes;
488 fhp = realloc(fhp, fhsize); /* Copies fhp\->handle_bytes */
489 if (fhp == NULL)
490 errExit("realloc");
491
492 /* Get file handle from pathname supplied on command line */
493
494 if (name_to_handle_at(AT_FDCWD, argv[1], fhp, &mount_id, 0) == \-1)
495 errExit("name_to_handle_at");
496
497 /* Write mount ID, file handle size, and file handle to stdout,
498 for later reuse by t_open_by_handle_at.c */
499
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");
504 exit(EXIT_FAILURE);
505 }
506
507 exit(EXIT_SUCCESS);
508 }
509 .fi
510 .SS Program source: t_open_by_handle_at.c
511 \&
512 .nf
513 #define _GNU_SOURCE
514 #include <sys/types.h>
515 #include <sys/stat.h>
516 #include <fcntl.h>
517 #include <limits.h>
518 #include <stdio.h>
519 #include <stdlib.h>
520 #include <unistd.h>
521 #include <string.h>
522
523 #define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \\
524 } while (0)
525
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
530 descriptor. */
531
532 static int
533 open_mount_path_by_id(int mount_id)
534 {
535 char *linep;
536 size_t lsize;
537 char mount_path[PATH_MAX];
538 int fmnt_id, fnd, nread;
539 FILE *fp;
540
541 fp = fopen("/proc/self/mountinfo", "r");
542 if (fp == NULL)
543 errExit("fopen");
544
545 for (fnd = 0; !fnd ; ) {
546 linep = NULL;
547 nread = getline(&linep, &lsize, fp);
548 if (nread == \-1)
549 break;
550
551 nread = sscanf(linep, "%d %*d %*s %*s %s", &fmnt_id, mount_path);
552 if (nread != 2) {
553 fprintf(stderr, "Bad sscanf()\\n");
554 exit(EXIT_FAILURE);
555 }
556
557 free(linep);
558
559 if (fmnt_id == mount_id)
560 fnd = 1;
561 }
562
563 fclose(fp);
564
565 if (!fnd) {
566 fprintf(stderr, "Could not find mount point\\n");
567 exit(EXIT_FAILURE);
568 }
569
570 return open(mount_path, O_RDONLY | O_DIRECTORY);
571 }
572
573 int
574 main(int argc, char *argv[])
575 {
576 struct file_handle *fhp;
577 int mount_id, fd, mount_fd, fhsize;
578 ssize_t nread;
579 #define BSIZE 1000
580 char buf[BSIZE];
581
582 if (argc > 1 && strcmp(argv[1], "\-\-help") == 0) {
583 fprintf(stderr, "Usage: %s [mount\-dir]]\\n",
584 argv[0]);
585 exit(EXIT_FAILURE);
586 }
587
588 /* Read data produced by t_name_to_handle_at.c */
589
590 if (read(STDIN_FILENO, &mount_id, sizeof(int)) != sizeof(int))
591 errExit("read");
592
593 if (read(STDIN_FILENO, &fhsize, sizeof(int)) != sizeof(int))
594 errExit("read");
595
596 fhp = malloc(fhsize);
597 if (fhp == NULL)
598 errExit("malloc");
599
600 if (read(STDIN_FILENO, fhp, fhsize) != fhsize)
601 errExit("read");
602
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) */
607
608 if (argc > 1)
609 mount_fd = open(argv[1], O_RDONLY | O_DIRECTORY);
610 else
611 mount_fd = open_mount_path_by_id(mount_id);
612
613 if (mount_fd == \-1)
614 errExit("opening mount fd");
615
616 /* Open name using handle and mount point */
617
618 fd = open_by_handle_at(mount_fd, fhp, O_RDONLY);
619 if (fd == \-1)
620 errExit("open_by_handle_at");
621
622 /* Try reading a few bytes from the file */
623
624 nread = read(fd, buf, BSIZE);
625 if (nread == \-1)
626 errExit("read");
627 printf("Read %ld bytes\\n", (long) nread);
628
629 exit(EXIT_SUCCESS);
630 }
631 .fi
632 .SH SEE ALSO
633 .BR blkid (1),
634 .BR findfs (1),
635 .BR open (2),
636 .BR libblkid (3),
637 .BR mount (8)
638
639 The
640 .I libblkid
641 and
642 .I libmount
643 documentation under the latest
644 .I util-linux
645 release at
646 .UR https://www.kernel.org/pub/linux/utils/util-linux/
647 .UE