]> git.ipfire.org Git - thirdparty/man-pages.git/blob - man2/open_by_handle_at.2
man*/: srcfix (Use .P instead of .PP or .LP)
[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 (date) "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 .P
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 .P
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 .P
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 .P
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 .P
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 can be used in a subsequent call to
113 .BR open_by_handle_at ().
114 The caller can also use the opaque
115 .I file_handle
116 to compare the identity of filesystem objects
117 that were queried at different times and possibly
118 at different paths.
119 The
120 .BR fanotify (7)
121 subsystem can report events
122 with an information record containing a
123 .I file_handle
124 to identify the filesystem object.
125 .P
126 The
127 .I flags
128 argument is a bit mask constructed by ORing together zero or more of
129 .BR AT_HANDLE_FID ,
130 .BR AT_EMPTY_PATH ,
131 and
132 .BR AT_SYMLINK_FOLLOW ,
133 described below.
134 .P
135 When
136 .I flags
137 contain the
138 .BR AT_HANDLE_FID " (since Linux 6.5)"
139 .\" commit 96b2b072ee62be8ae68c8ecf14854c4d0505a8f8
140 flag, the caller indicates that the returned
141 .I file_handle
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 ()
146 with the returned
147 .I file_handle
148 may fail.
149 .P
150 Together, the
151 .I pathname
152 and
153 .I dirfd
154 arguments identify the file for which a handle is to be obtained.
155 There are four distinct cases:
156 .IP \[bu] 3
157 If
158 .I pathname
159 is a nonempty string containing an absolute pathname,
160 then a handle is returned for the file referred to by that pathname.
161 In this case,
162 .I dirfd
163 is ignored.
164 .IP \[bu]
165 If
166 .I pathname
167 is a nonempty string containing a relative pathname and
168 .I dirfd
169 has the special value
170 .BR AT_FDCWD ,
171 then
172 .I pathname
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.
175 .IP \[bu]
176 If
177 .I pathname
178 is a nonempty string containing a relative pathname and
179 .I dirfd
180 is a file descriptor referring to a directory, then
181 .I pathname
182 is interpreted relative to the directory referred to by
183 .IR dirfd ,
184 and a handle is returned for the file to which it refers.
185 (See
186 .BR openat (2)
187 for an explanation of why "directory file descriptors" are useful.)
188 .IP \[bu]
189 If
190 .I pathname
191 is an empty string and
192 .I flags
193 specifies the value
194 .BR AT_EMPTY_PATH ,
195 then
196 .I dirfd
197 can be an open file descriptor referring to any type of file,
198 or
199 .BR AT_FDCWD ,
200 meaning the current working directory,
201 and a handle is returned for the file to which it refers.
202 .P
203 The
204 .I mount_id
205 argument returns an identifier for the filesystem
206 mount that corresponds to
207 .IR pathname .
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 ().
214 .I mount_id
215 is returned both for a successful call and for a call that results
216 in the error
217 .BR EOVERFLOW .
218 .P
219 By default,
220 .BR name_to_handle_at ()
221 does not dereference
222 .I pathname
223 if it is a symbolic link, and thus returns a handle for the link itself.
224 If
225 .B AT_SYMLINK_FOLLOW
226 is specified in
227 .IR flags ,
228 .I pathname
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).
231 .P
232 .BR name_to_handle_at ()
233 does not trigger a mount when the final component of the pathname is an
234 automount point.
235 When a filesystem supports both file handles and
236 automount points, a
237 .BR name_to_handle_at ()
238 call on an automount point will return with error
239 .B EOVERFLOW
240 without having increased
241 .IR handle_bytes .
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
247 of the pathname.
248 .SS open_by_handle_at()
249 The
250 .BR open_by_handle_at ()
251 system call opens the file referred to by
252 .IR handle ,
253 a file handle returned by a previous call to
254 .BR name_to_handle_at ().
255 .P
256 The
257 .I mount_fd
258 argument is a file descriptor for any object (file, directory, etc.)
259 in the mounted filesystem with respect to which
260 .I handle
261 should be interpreted.
262 The special value
263 .B AT_FDCWD
264 can be specified, meaning the current working directory of the caller.
265 .P
266 The
267 .I flags
268 argument
269 is as for
270 .BR open (2).
271 If
272 .I handle
273 refers to a symbolic link, the caller must specify the
274 .B O_PATH
275 flag, and the symbolic link is not dereferenced; the
276 .B O_NOFOLLOW
277 flag, if specified, is ignored.
278 .P
279 The caller must have the
280 .B CAP_DAC_READ_SEARCH
281 capability to invoke
282 .BR open_by_handle_at ().
283 .SH RETURN VALUE
284 On success,
285 .BR name_to_handle_at ()
286 returns 0,
287 and
288 .BR open_by_handle_at ()
289 returns a file descriptor (a nonnegative integer).
290 .P
291 In the event of an error, both system calls return \-1 and set
292 .I errno
293 to indicate the error.
294 .SH ERRORS
295 .BR name_to_handle_at ()
296 and
297 .BR open_by_handle_at ()
298 can fail for the same errors as
299 .BR openat (2).
300 In addition, they can fail with the errors noted below.
301 .P
302 .BR name_to_handle_at ()
303 can fail with the following errors:
304 .TP
305 .B EFAULT
306 .IR pathname ,
307 .IR mount_id ,
308 or
309 .I handle
310 points outside your accessible address space.
311 .TP
312 .B EINVAL
313 .I flags
314 includes an invalid bit value.
315 .TP
316 .B EINVAL
317 .I handle\->handle_bytes
318 is greater than
319 .BR MAX_HANDLE_SZ .
320 .TP
321 .B ENOENT
322 .I pathname
323 is an empty string, but
324 .B AT_EMPTY_PATH
325 was not specified in
326 .IR flags .
327 .TP
328 .B ENOTDIR
329 The file descriptor supplied in
330 .I dirfd
331 does not refer to a directory,
332 and it is not the case that both
333 .I flags
334 includes
335 .B AT_EMPTY_PATH
336 and
337 .I pathname
338 is an empty string.
339 .TP
340 .B EOPNOTSUPP
341 The filesystem does not support decoding of a pathname to a file handle.
342 .TP
343 .B EOVERFLOW
344 The
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.
350 .\"
351 .\"
352 .P
353 .BR open_by_handle_at ()
354 can fail with the following errors:
355 .TP
356 .B EBADF
357 .I mount_fd
358 is not an open file descriptor.
359 .TP
360 .B EBADF
361 .I pathname
362 is relative but
363 .I dirfd
364 is neither
365 .B AT_FDCWD
366 nor a valid file descriptor.
367 .TP
368 .B EFAULT
369 .I handle
370 points outside your accessible address space.
371 .TP
372 .B EINVAL
373 .I handle\->handle_bytes
374 is greater than
375 .B MAX_HANDLE_SZ
376 or is equal to zero.
377 .TP
378 .B ELOOP
379 .I handle
380 refers to a symbolic link, but
381 .B O_PATH
382 was not specified in
383 .IR flags .
384 .TP
385 .B EPERM
386 The caller does not have the
387 .B CAP_DAC_READ_SEARCH
388 capability.
389 .TP
390 .B ESTALE
391 The specified
392 .I handle
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
396 .I handle
397 was acquired using the
398 .B AT_HANDLE_FID
399 flag and the filesystem does not support
400 .BR open_by_handle_at ().
401 .SH VERSIONS
402 FreeBSD has a broadly similar pair of system calls in the form of
403 .BR getfh ()
404 and
405 .BR openfh ().
406 .SH STANDARDS
407 Linux.
408 .SH HISTORY
409 Linux 2.6.39,
410 glibc 2.14.
411 .SH NOTES
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 ().
416 .P
417 Some filesystem don't support the translation of pathnames to
418 file handles, for example,
419 .IR /proc ,
420 .IR /sys ,
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 ().
425 .P
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
429 .B ESTALE
430 error from
431 .BR open_by_handle_at ().
432 .P
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.
442 .P
443 If
444 .I pathname
445 refers to a symbolic link and
446 .I flags
447 does not specify
448 .BR AT_SYMLINK_FOLLOW ,
449 then
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 ()
456 with the
457 .B O_PATH
458 flag, and then passing the file descriptor as the
459 .I dirfd
460 argument in system calls such as
461 .BR readlinkat (2)
462 and
463 .BR fchownat (2).
464 .SS Obtaining a persistent filesystem ID
465 The mount IDs in
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 ()
470 (in
471 .IR *mount_id )
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
475 .I mountinfo
476 record that corresponds to the mount ID
477 to derive a persistent identifier.
478 .P
479 For example, one can use the device name in the fifth field of the
480 .I mountinfo
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
485 .BR libblkid (3)
486 library.)
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
491 .I mount_fd
492 argument used by
493 .BR open_by_handle_at ().
494 .SH EXAMPLES
495 The two programs below demonstrate the use of
496 .BR name_to_handle_at ()
497 and
498 .BR open_by_handle_at ().
499 The first program
500 .RI ( t_name_to_handle_at.c )
501 uses
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.
506 .P
507 The second program
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
514 .I mount_fd
515 argument for
516 .BR open_by_handle_at ()
517 is obtained by opening the directory named in that argument.
518 Otherwise,
519 .I mount_fd
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.)
526 .P
527 The following shell session demonstrates the use of these two programs:
528 .P
529 .in +4n
530 .EX
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
536 Read 31 bytes
537 $ \fBrm cecilia.txt\fP
538 .EE
539 .in
540 .P
541 Now we delete and (quickly) re-create the file so that
542 it has the same content and (by chance) the same inode.
543 Nevertheless,
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
548 no longer exists.
549 .P
550 .in +4n
551 .EX
552 $ \fBstat \-\-printf="%i\en" cecilia.txt\fP # Display inode number
553 4072121
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
557 4072121
558 $ \fBsudo ./t_open_by_handle_at < fh\fP
559 open_by_handle_at: Stale NFS file handle
560 .EE
561 .in
562 .SS Program source: t_name_to_handle_at.c
563 \&
564 .\" SRC BEGIN (t_name_to_handle_at.c)
565 .EX
566 #define _GNU_SOURCE
567 #include <err.h>
568 #include <errno.h>
569 #include <fcntl.h>
570 #include <stdio.h>
571 #include <stdlib.h>
572 \&
573 int
574 main(int argc, char *argv[])
575 {
576 int mount_id, fhsize, flags, dirfd;
577 char *pathname;
578 struct file_handle *fhp;
579 \&
580 if (argc != 2) {
581 fprintf(stderr, "Usage: %s pathname\en", argv[0]);
582 exit(EXIT_FAILURE);
583 }
584 \&
585 pathname = argv[1];
586 \&
587 /* Allocate file_handle structure. */
588 \&
589 fhsize = sizeof(*fhp);
590 fhp = malloc(fhsize);
591 if (fhp == NULL)
592 err(EXIT_FAILURE, "malloc");
593 \&
594 /* Make an initial call to name_to_handle_at() to discover
595 the size required for file handle. */
596 \&
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)
603 {
604 fprintf(stderr, "Unexpected result from name_to_handle_at()\en");
605 exit(EXIT_FAILURE);
606 }
607 \&
608 /* Reallocate file_handle structure with correct size. */
609 \&
610 fhsize = sizeof(*fhp) + fhp\->handle_bytes;
611 fhp = realloc(fhp, fhsize); /* Copies fhp\->handle_bytes */
612 if (fhp == NULL)
613 err(EXIT_FAILURE, "realloc");
614 \&
615 /* Get file handle from pathname supplied on command line. */
616 \&
617 if (name_to_handle_at(dirfd, pathname, fhp, &mount_id, flags) == \-1)
618 err(EXIT_FAILURE, "name_to_handle_at");
619 \&
620 /* Write mount ID, file handle size, and file handle to stdout,
621 for later reuse by t_open_by_handle_at.c. */
622 \&
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]);
627 printf("\en");
628 \&
629 exit(EXIT_SUCCESS);
630 }
631 .EE
632 .\" SRC END
633 .SS Program source: t_open_by_handle_at.c
634 \&
635 .\" SRC BEGIN (t_open_by_handle_at.c)
636 .EX
637 #define _GNU_SOURCE
638 #include <err.h>
639 #include <fcntl.h>
640 #include <limits.h>
641 #include <stdio.h>
642 #include <stdlib.h>
643 #include <string.h>
644 #include <unistd.h>
645 \&
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
650 descriptor. */
651 \&
652 static int
653 open_mount_path_by_id(int mount_id)
654 {
655 int mi_mount_id, found;
656 char mount_path[PATH_MAX];
657 char *linep;
658 FILE *fp;
659 size_t lsize;
660 ssize_t nread;
661 \&
662 fp = fopen("/proc/self/mountinfo", "r");
663 if (fp == NULL)
664 err(EXIT_FAILURE, "fopen");
665 \&
666 found = 0;
667 linep = NULL;
668 while (!found) {
669 nread = getline(&linep, &lsize, fp);
670 if (nread == \-1)
671 break;
672 \&
673 nread = sscanf(linep, "%d %*d %*s %*s %s",
674 &mi_mount_id, mount_path);
675 if (nread != 2) {
676 fprintf(stderr, "Bad sscanf()\en");
677 exit(EXIT_FAILURE);
678 }
679 \&
680 if (mi_mount_id == mount_id)
681 found = 1;
682 }
683 free(linep);
684 \&
685 fclose(fp);
686 \&
687 if (!found) {
688 fprintf(stderr, "Could not find mount point\en");
689 exit(EXIT_FAILURE);
690 }
691 \&
692 return open(mount_path, O_RDONLY);
693 }
694 \&
695 int
696 main(int argc, char *argv[])
697 {
698 int mount_id, fd, mount_fd, handle_bytes;
699 char buf[1000];
700 #define LINE_SIZE 100
701 char line1[LINE_SIZE], line2[LINE_SIZE];
702 char *nextp;
703 ssize_t nread;
704 struct file_handle *fhp;
705 \&
706 if ((argc > 1 && strcmp(argv[1], "\-\-help") == 0) || argc > 2) {
707 fprintf(stderr, "Usage: %s [mount\-path]\en", argv[0]);
708 exit(EXIT_FAILURE);
709 }
710 \&
711 /* Standard input contains mount ID and file handle information:
712 \&
713 Line 1: <mount_id>
714 Line 2: <handle_bytes> <handle_type> <bytes of handle in hex>
715 */
716 \&
717 if (fgets(line1, sizeof(line1), stdin) == NULL ||
718 fgets(line2, sizeof(line2), stdin) == NULL)
719 {
720 fprintf(stderr, "Missing mount_id / file handle\en");
721 exit(EXIT_FAILURE);
722 }
723 \&
724 mount_id = atoi(line1);
725 \&
726 handle_bytes = strtoul(line2, &nextp, 0);
727 \&
728 /* Given handle_bytes, we can now allocate file_handle structure. */
729 \&
730 fhp = malloc(sizeof(*fhp) + handle_bytes);
731 if (fhp == NULL)
732 err(EXIT_FAILURE, "malloc");
733 \&
734 fhp\->handle_bytes = handle_bytes;
735 \&
736 fhp\->handle_type = strtoul(nextp, &nextp, 0);
737 \&
738 for (size_t j = 0; j < fhp\->handle_bytes; j++)
739 fhp\->f_handle[j] = strtoul(nextp, &nextp, 16);
740 \&
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. */
745 \&
746 if (argc > 1)
747 mount_fd = open(argv[1], O_RDONLY);
748 else
749 mount_fd = open_mount_path_by_id(mount_id);
750 \&
751 if (mount_fd == \-1)
752 err(EXIT_FAILURE, "opening mount fd");
753 \&
754 /* Open file using handle and mount point. */
755 \&
756 fd = open_by_handle_at(mount_fd, fhp, O_RDONLY);
757 if (fd == \-1)
758 err(EXIT_FAILURE, "open_by_handle_at");
759 \&
760 /* Try reading a few bytes from the file. */
761 \&
762 nread = read(fd, buf, sizeof(buf));
763 if (nread == \-1)
764 err(EXIT_FAILURE, "read");
765 \&
766 printf("Read %zd bytes\en", nread);
767 \&
768 exit(EXIT_SUCCESS);
769 }
770 .EE
771 .\" SRC END
772 .SH SEE ALSO
773 .BR open (2),
774 .BR libblkid (3),
775 .BR blkid (8),
776 .BR findfs (8),
777 .BR mount (8)
778 .P
779 The
780 .I libblkid
781 and
782 .I libmount
783 documentation in the latest
784 .I util\-linux
785 release at
786 .UR https://www.kernel.org/pub/linux/utils/util\-linux/
787 .UE