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