OSDN Git Service

LDP: Address fuzzy changes (stdio)
[linuxjm/jm.git] / manual / LDP_man-pages / draft / man2 / open_by_handle_at.2
1 .\" Copyright (c) 2014 by Michael Kerrisk <mtk.manpages@gmail.com>
2 .\"
3 .\" %%%LICENSE_START(VERBATIM)
4 .\" Permission is granted to make and distribute verbatim copies of this
5 .\" manual provided the copyright notice and this permission notice are
6 .\" preserved on all copies.
7 .\"
8 .\" Permission is granted to copy and distribute modified versions of this
9 .\" manual under the conditions for verbatim copying, provided that the
10 .\" entire resulting derived work is distributed under the terms of a
11 .\" permission notice identical to this one.
12 .\"
13 .\" Since the Linux kernel and libraries are constantly changing, this
14 .\" manual page may be incorrect or out-of-date.  The author(s) assume no
15 .\" responsibility for errors or omissions, or for damages resulting from
16 .\" the use of the information contained herein.  The author(s) may not
17 .\" have taken the same level of care in the production of this manual,
18 .\" which is licensed free of charge, as they might when working
19 .\" professionally.
20 .\"
21 .\" Formatted or processed versions of this manual, if unaccompanied by
22 .\" the source, must acknowledge the copyright and authors of this work.
23 .\" %%%LICENSE_END
24 .\"
25 .\"*******************************************************************
26 .\"
27 .\" This file was generated with po4a. Translate the source file.
28 .\"
29 .\"*******************************************************************
30 .TH OPEN_BY_HANDLE_AT 2 2020\-11\-01 Linux "Linux Programmer's Manual"
31 .SH 名前
32 name_to_handle_at, open_by_handle_at \- パス名に対するハンドルの取得とハンドルによるファイルのオープン
33 .SH 書式
34 .nf
35 \fB#define _GNU_SOURCE\fP         /* feature_test_macros(7) 参照 */
36 \fB#include <sys/types.h>\fP
37 \fB#include <sys/stat.h>\fP
38 \fB#include <fcntl.h>\fP
39 .PP
40 \fBint name_to_handle_at(int \fP\fIdirfd\fP\fB, const char *\fP\fIpathname\fP\fB,\fP
41 \fB                      struct file_handle *\fP\fIhandle\fP\fB,\fP
42 \fB                      int *\fP\fImount_id\fP\fB, int \fP\fIflags\fP\fB);\fP
43 .PP
44 \fBint open_by_handle_at(int \fP\fImount_fd\fP\fB, struct file_handle *\fP\fIhandle\fP\fB,\fP
45 \fB                      int \fP\fIflags\fP\fB);\fP
46 .fi
47 .SH 説明
48 .\"
49 .\"
50 システムコール \fBname_to_handle_at\fP() と \fBopen_by_handle_at\fP() は \fBopenat\fP(2) の機能を
51 2 つに分割したものである。 \fBname_to_handle_at\fP() は指定されたファイルに対応するハンドルを返す。
52 \fBopen_by_handle_at\fP() は \fBname_to_handle_at\fP() が返したハンドルに対応するファイルをオープンし、
53 オープンされたファイルディスクリプターを返す。
54 .SS name_to_handle_at()
55 \fBname_to_handle_at\fP() システムコールは、 引き数 \fIdirfd\fP と \fIpathname\fP
56 で指定されるファイルに対応するファイルハンドルとマウント ID を返す。 ファイルハンドルは引き数 \fIhandle\fP で返される。 \fIhandle\fP
57 は以下の形式の構造体へのポインターである。
58 .PP
59 .in +4n
60 .EX
61 struct file_handle {
62     unsigned int  handle_bytes;   /* Size of f_handle [in, out] */
63     int           handle_type;    /* Handle type [out] */
64     unsigned char f_handle[0];    /* File identifier (sized by
65                                      caller) [out] */
66 };
67 .EE
68 .in
69 .PP
70 It is the caller's responsibility to allocate the structure with a size
71 large enough to hold the handle returned in \fIf_handle\fP.  Before the call,
72 the \fIhandle_bytes\fP field should be initialized to contain the allocated
73 size for \fIf_handle\fP.  (The constant \fBMAX_HANDLE_SZ\fP, defined in
74 \fI<fcntl.h>\fP, specifies the maximum expected size for a file
75 handle.  It is not a guaranteed upper limit as future filesystems may
76 require more space.)  Upon successful return, the \fIhandle_bytes\fP field is
77 updated to contain the number of bytes actually written to \fIf_handle\fP.
78 .PP
79 The caller can discover the required size for the \fIfile_handle\fP structure
80 by making a call in which \fIhandle\->handle_bytes\fP is zero; in this case,
81 the call fails with the error \fBEOVERFLOW\fP and \fIhandle\->handle_bytes\fP
82 is set to indicate the required size; the caller can then use this
83 information to allocate a structure of the correct size (see EXAMPLES
84 below).  Some care is needed here as \fBEOVERFLOW\fP can also indicate that no
85 file handle is available for this particular name in a filesystem which does
86 normally support file\-handle lookup.  This case can be detected when the
87 \fBEOVERFLOW\fP error is returned without \fIhandle_bytes\fP being increased.
88 .PP
89 \fIhandle_bytes\fP フィールドを使用する以外は、 呼び出し元は \fIfile_handle\fP 構造体の内容を意識せずに扱うべきである。
90 フィールド \fIhandle_type\fP と \fIf_handle\fP は後で \fBopen_by_handle_at\fP()
91 を呼び出す場合にだけ必要である。
92 .PP
93 \fIflags\fP 引き数は、 下記の \fBAT_EMPTY_PATH\fP と \fBAT_SYMLINK_FOLLOW\fP のうち 0
94 個以上の論理和を取って構成されるビットマスクである。
95 .PP
96 引き数 \fIpathname\fP と \fIdirfd\fP はその組み合わせでハンドルを取得するファイルを指定する。 以下の 4 つのパターンがある。
97 .IP * 3
98 \fIpathname\fP が空でない文字列で絶対パス名を含む場合、 このパス名が参照するファイルに対するハンドルが返される。
99 .IP *
100 \fIpathname\fP が相対パスが入った空でない文字列で、 \fIdirfd\fP が特別な値 \fBAT_FDCWD\fP の場合、 \fIpathname\fP
101 は呼び出し元のカレントワーキングディレクトリに対する相対パスと解釈され、 そのファイルに対するハンドルが返される。
102 .IP *
103 \fIpathname\fP が相対パスが入った空でない文字列で、 \fIdirfd\fP がディレクトリを参照するファイルディスクリプターの場合、
104 \fIpathname\fP は \fIdirfd\fP が参照するディレクトリに対する相対パスと解釈され、
105 そのファイルを参照するハンドルが返される。(なぜ「ディレクトリファイルディスクリプター」が役に立つのかについては \fBopenat\fP(2) を参照。)
106 .IP *
107 \fIpathname\fP が空の文字列で \fIflags\fP に \fBAT_EMPTY_PATH\fP が指定されている場合、 \fIdirfd\fP
108 には任意の種別のファイルを参照するオープンされたファイルディスクリプターか \fBAT_FDCWD\fP (カレントワーキングディレクトリを意味する)
109 を指定でき、 \fIdirfd\fP が参照するファイルに対するハンドルが返される。
110 .PP
111 The \fImount_id\fP argument returns an identifier for the filesystem mount that
112 corresponds to \fIpathname\fP.  This corresponds to the first field in one of
113 the records in \fI/proc/self/mountinfo\fP.  Opening the pathname in the fifth
114 field of that record yields a file descriptor for the mount point; that file
115 descriptor can be used in a subsequent call to \fBopen_by_handle_at\fP().
116 \fImount_id\fP is returned both for a successful call and for a call that
117 results in the error \fBEOVERFLOW\fP.
118 .PP
119 デフォルトでは、 \fBname_to_handle_at\fP() は \fIpathname\fP がシンボリックリンクの場合にその展開
120 (dereference) を行わず、 リンク自身に対するハンドルを返す。 \fBAT_SYMLINK_FOLLOW\fP が \fIflags\fP
121 に指定されると、 \fIpathname\fP がシンボリックリンクの場合にリンクの展開が行われる (リンクが参照するファイルに対するハンドルが返される)。
122 .PP
123 .\" commit 20fa19027286983ab2734b5910c4a687436e0c31
124 \fBname_to_handle_at\fP()  does not trigger a mount when the final component of
125 the pathname is an automount point.  When a filesystem supports both file
126 handles and automount points, a \fBname_to_handle_at\fP()  call on an automount
127 point will return with error \fBEOVERFLOW\fP without having increased
128 \fIhandle_bytes\fP.  This can happen since Linux 4.13 with NFS when accessing a
129 directory which is on a separate filesystem on the server.  In this case,
130 the automount can be triggered by adding a "/" to the end of the pathname.
131 .SS open_by_handle_at()
132 \fBopen_by_handle_at\fP() システムコールは \fIhandle\fP が参照するファイルをオープンする。 \fIhandle\fP は
133 前に呼び出した \fBname_to_handle_at\fP() が返したファイルハンドルである。
134 .PP
135 \fImount_fd\fP 引き数は、 \fIhandle\fP がそのファイルシステムに関連すると解釈されるマウントされたファイルシステム内の任意のオブジェクト
136 (ファイル、 ディレクトリなど) のファイルディスクリプターである。 特別な値 \fBAT_FDCWD\fP も指定できる。
137 この値は呼び出し元のカレントワーキングディレクトリを意味する。
138 .PP
139 引き数 \fIflags\fP は \fBopen\fP(2) と同じである。 \fIhandle\fP がシンボリックリンクを参照している場合、 呼び出し元は
140 \fBO_PATH\fP フラグを指定しなければならず、 そのシンボリックリンクは展開されない。 \fBO_NOFOLLOW\fP が指定された場合は、
141 \fBO_NOFOLLOW\fP は無視される。
142 .PP
143 \fBopen_by_handle_at\fP() を呼び出すには、 呼び出し元が \fBCAP_DAC_READ_SEARCH\fP
144 ケーパビリティーを持っていなければならない。
145 .SH 返り値
146 成功すると、 \fBname_to_handle_at\fP() は 0 を返し、 \fBopen_by_handle_at\fP() はファイルディスクリプター
147 (非負の整数) を返す。
148 .PP
149 エラーの場合、 どちらのシステムコールも \-1 を返し、 \fIerrno\fP にエラーの原因を示す値を設定する。
150 .SH エラー
151 \fBname_to_handle_at\fP() と \fBopen_by_handle_at\fP() は \fBopenat\fP(2) と同じエラーで失敗する。
152 また、 これらのシステムコールは以下のエラーで失敗することもある。
153 .PP
154 \fBname_to_handle_at\fP() は以下のエラーで失敗することがある。
155 .TP 
156 \fBEFAULT\fP
157 \fIpathname\fP, \fImount_id\fP, \fIhandle\fP のどれかがアクセス可能なアドレス空間の外を指している。
158 .TP 
159 \fBEINVAL\fP
160 \fIflags\fP に無効なビット値が含まれている。
161 .TP 
162 \fBEINVAL\fP
163 \fIhandle\->handle_bytes\fP が \fBMAX_HANDLE_SZ\fP よりも大きい。
164 .TP 
165 \fBENOENT\fP
166 \fIpathname\fP が空文字列だが、 \fIflags\fP に \fBAT_EMPTY_PATH\fP がされていなかった。
167 .TP 
168 \fBENOTDIR\fP
169 \fIdirfd\fP で指定されたファイルディスクリプターがディレクトリを参照しておらず、 両方の \fIflags\fP に \fBAT_EMPTY_PATH\fP
170 が指定され、 かつ \fIpathname\fP が空文字列である場合でもない。
171 .TP 
172 \fBEOPNOTSUPP\fP
173 ファイルシステムがパス名をファイルハンドルへの変換をサポートしていない。
174 .TP 
175 \fBEOVERFLOW\fP
176 .\"
177 .\"
178 呼び出しに渡された \fIhandle\->handle_bytes\fP の値が小さすぎた。 このエラーが発生した際、
179 \fIhandle\->handle_bytes\fP はハンドルに必要なサイズに更新される。
180 .PP
181 \fBopen_by_handle_at\fP() は以下のエラーで失敗することがある。
182 .TP 
183 \fBEBADF\fP
184 \fImount_fd\fP がオープンされたファイルディスクリプターでない。
185 .TP 
186 \fBEFAULT\fP
187 \fIhandle\fP がアクセス可能なアドレス空間の外を指している。
188 .TP 
189 \fBEINVAL\fP
190 \fIhandle\->handle_bytes\fP が \fBMAX_HANDLE_SZ\fP より大きいか 0 に等しい。
191 .TP 
192 \fBELOOP\fP
193 \fIhandle\fP がシンボリックリンクを参照しているが、 \fIflags\fP に \fBO_PATH\fP がされていなかった。
194 .TP 
195 \fBEPERM\fP
196 呼び出し元が \fBCAP_DAC_READ_SEARCH\fP ケーパビリティを持っていない。
197 .TP 
198 \fBESTALE\fP
199 指定された \fIhandle\fP が有効ではない。 このエラーは、 例えばファイルが削除された場合などに発生する。
200 .SH バージョン
201 これらのシステムコールは Linux 2.6.39 で初めて登場した。ライブラリによるサポートはバージョン 2.14 以降の glibc
202 で提供されている。
203 .SH 準拠
204 これらのシステムコールは非標準の Linux の拡張である。
205 .PP
206 FreeBSD には \fBgetfh\fP() と \fBopenfh\fP() というほとんど同じ機能のシステムコールのペアが存在する。
207 .SH 注意
208 あるプロセスで \fBname_to_handle_at\fP() を使ってファイルハンドルを生成して、 そのハンドルを別のプロセスの
209 \fBopen_by_handle_at\fP() で使用することができる。
210 .PP
211 いくつかのファイルシステムでは、 パス名からファイルハンドルへの変換がサポートされていない。 例えば、 \fI/proc\fP, \fI/sys\fP
212 や種々のネットワークファイルシステムなどである。
213 .PP
214 ファイルハンドルは、 ファイルが削除されたり、 その他のファイルシステム固有の理由で、 無効 ("stale") になる場合がある。
215 無効なハンドルであることは、 \fBopen_by_handle_at\fP() からエラー \fBESTALE\fP が返ることで通知される。
216 .PP
217 .\" https://lwn.net/Articles/375888/
218 .\"     "Open by handle" - Jonathan Corbet, 2010-02-23
219 これらのシステムコールは、 ユーザー空間のファイルサーバーでの使用を意図して設計されている。 例えば、 ユーザー空間 NFS
220 サーバーがファイルハンドルを生成して、 そのハンドルを NFS クライアントに渡すことができる。 その後、
221 クライアントがファイルをオープンしようとした際に、 このハンドルをサーバーに送り返すことができる。 このような機能により、
222 ユーザー空間ファイルサーバーは、 そのサーバーが提供するファイルに関してステートレスで (状態を保持せずに) 動作することができる。
223 .PP
224 .\" commit bcda76524cd1fa32af748536f27f674a13e56700
225 \fIpathname\fP がシンボリックリンクを参照していて、 \fIflags\fP に \fBAT_SYMLINK_FOLLOW\fP が指定されていない場合、
226 \fBname_to_handle_at\fP() は (シンボリックが参照するファイルではなく) リンクに対するハンドルを返す。
227 ハンドルを受け取ったプロセスは、 \fBopen_by_handle_at\fP() の \fBO_PATH\fP
228 フラグを使ってハンドルをファイルディスクリプターに変換し、 そのファイルディスクリプターを \fBreadlinkat\fP(2) や
229 \fBfchownat\fP(2) などのシステムコールの \fIdirfd\fP 引き数として渡すことで、 そのシンボリックリンクに対して操作を行うことができる。
230 .SS "永続的なファイルシステム ID の取得"
231 \fI/proc/self/mountinfo\fP のマウント ID は、
232 ファイルシステムのアンマウント、マウントが行われるに連れて再利用されることがある。 したがって、 \fBname_to_handle_at\fP() (の
233 \fI*mount_id\fP) で返されたマウント ID は対応するマウントされたファイルシステムを表す永続的な ID と考えるべきではない。 ただし、
234 アプリケーションは、 マウント ID に対応する  \fImountinfo\fP レコードの情報を使うことで、 永続的な ID を得ることができる。
235 .PP
236 .\" e.g., http://stackoverflow.com/questions/6748429/using-libblkid-to-find-uuid-of-a-partition
237 例えば、 \fImountinfo\fP レコードの 5 番目のフィールドのデバイス名を使って、 \fI/dev/disks/by\-uuid\fP
238 のシンボリックリンク経由で対応するデバイス UUID を検索できる。 (UUID を取得するもっと便利な方法は \fBlibblkid\fP(3)
239 ライブラリを使用することである。) そのプロセスは、逆に、 この UUID を使ってデバイス名を検索し、 対応するマウントポイントを取得することで、
240 \fBopen_by_handle_at\fP() で使用する \fImount_fd\fP 引き数を生成することができる。
241 .SH 例
242 以下の 2 つのプログラムは \fBname_to_handle_at\fP() と \fBopen_by_handle_at\fP()
243 の使用例を示したものである。 最初のプログラム (\fIt_name_to_handle_at.c\fP) は \fBname_to_handle_at\fP()
244 を使用して、 コマンドライン引き数で指定されたファイルに対応するファイルハンドルとマウント ID を取得する。 ハンドルとマウント ID
245 は標準出力に出力される。
246 .PP
247 2 つ目のプログラム (\fIt_open_by_handle_at.c\fP) は、 標準入力からマウント ID とファイルハンドルを読み込む。 それから、
248 \fBopen_by_handle_at\fP() を利用して、 そのハンドルを使ってファイルをオープンする。 追加のコマンドライン引き数が指定された場合は、
249 \fBopen_by_handle_at\fP() の \fImount_fd\fP 引き数は、 この引き数で渡された名前のディレクトリをオープンして取得する。
250 それ以外の場合、 \fI/proc/self/mountinfo\fP からスキャンして標準入力から読み込んだマウント ID に一致するマウント ID
251 を検索し、 そのレコードで指定されているマウントディレクトリをオープンして、 \fImount_fd\fP を入手する。 (これらのプログラムではマウント
252 ID が永続的ではない点についての対処は行わない。)
253 .PP
254 以下のシェルセッションは、これら 2 つのプログラムの使用例である。
255 .PP
256 .in +4n
257 .EX
258 $ \fBecho \(aqCan you please think about it?\(aq > cecilia.txt\fP
259 $ \fB./t_name_to_handle_at cecilia.txt > fh\fP
260 $ \fB./t_open_by_handle_at < fh\fP
261 open_by_handle_at: Operation not permitted
262 $ \fBsudo ./t_open_by_handle_at < fh\fP      # Need CAP_SYS_ADMIN
263 Read 31 bytes
264 $ \fBrm cecilia.txt\fP
265 .EE
266 .in
267 .PP
268 .\" Christoph Hellwig: That's why the file handles contain a generation
269 .\" counter that gets incremented in this case.
270 ここで、 ファイルを削除し (すぐに) 再作成する。 同じ内容で (運がよければ) 同じ inode になる。 この場合でも、
271 \fBopen_by_handle_at\fP() はこのファイルハンドルが参照する元のファイルがすでに存在しないことを認識する。
272 .PP
273 .in +4n
274 .EX
275 $ \fBstat \-\-printf="%i\en" cecilia.txt\fP     # Display inode number
276 4072121
277 $ \fBrm cecilia.txt\fP
278 $ \fBecho \(aqCan you please think about it?\(aq > cecilia.txt\fP
279 $ \fBstat \-\-printf="%i\en" cecilia.txt\fP     # Check inode number
280 4072121
281 $ \fBsudo ./t_open_by_handle_at < fh\fP
282 open_by_handle_at: Stale NFS file handle
283 .EE
284 .in
285 .SS "プログラムのソース: t_name_to_handle_at.c"
286 \&
287 .EX
288 #define _GNU_SOURCE
289 #include <sys/types.h>
290 #include <sys/stat.h>
291 #include <fcntl.h>
292 #include <stdio.h>
293 #include <stdlib.h>
294 #include <unistd.h>
295 #include <errno.h>
296 #include <string.h>
297
298 #define errExit(msg)    do { perror(msg); exit(EXIT_FAILURE); \e
299                         } while (0)
300
301 int
302 main(int argc, char *argv[])
303 {
304     struct file_handle *fhp;
305     int mount_id, fhsize, flags, dirfd;
306     char *pathname;
307
308     if (argc != 2) {
309         fprintf(stderr, "Usage: %s pathname\en", argv[0]);
310         exit(EXIT_FAILURE);
311     }
312
313     pathname = argv[1];
314
315     /* file_handle 構造体を確保する */
316
317     fhsize = sizeof(*fhp);
318     fhp = malloc(fhsize);
319     if (fhp == NULL)
320         errExit("malloc");
321
322     /* name_to_handle_at() を最初に呼び出して
323        ファイルハンドルに必要なサイズを入手する */
324
325     dirfd = AT_FDCWD;           /* For name_to_handle_at() calls */
326     flags = 0;                  /* For name_to_handle_at() calls */
327     fhp\->handle_bytes = 0;
328     if (name_to_handle_at(dirfd, pathname, fhp,
329                 &mount_id, flags) != \-1 || errno != EOVERFLOW) {
330         fprintf(stderr, "Unexpected result from name_to_handle_at()\en");
331         exit(EXIT_FAILURE);
332     }
333
334     /* file_handle 構造体を正しいサイズに確保し直す */
335
336     fhsize = sizeof(*fhp) + fhp\->handle_bytes;
337     fhp = realloc(fhp, fhsize);         /* Copies fhp\->handle_bytes */
338     if (fhp == NULL)
339         errExit("realloc");
340
341     /* コマンドラインで指定されたパス名からファイルハンドルを取得 */
342
343     if (name_to_handle_at(dirfd, pathname, fhp, &mount_id, flags) == \-1)
344         errExit("name_to_handle_at");
345
346     /* t_open_by_handle_at.c で後で再利用できるように、マウント ID、
347        ファイルハンドルのサイズ、ファイルハンドルを標準出力に書き出す */
348
349     printf("%d\en", mount_id);
350     printf("%u %d   ", fhp\->handle_bytes, fhp\->handle_type);
351     for (int j = 0; j < fhp\->handle_bytes; j++)
352         printf(" %02x", fhp\->f_handle[j]);
353     printf("\en");
354
355     exit(EXIT_SUCCESS);
356 }
357 .EE
358 .SS "プログラムのソース: t_open_by_handle_at.c"
359 \&
360 .EX
361 #define _GNU_SOURCE
362 #include <sys/types.h>
363 #include <sys/stat.h>
364 #include <fcntl.h>
365 #include <limits.h>
366 #include <stdio.h>
367 #include <stdlib.h>
368 #include <unistd.h>
369 #include <string.h>
370
371 #define errExit(msg)    do { perror(msg); exit(EXIT_FAILURE); \e
372                         } while (0)
373
374 /* /proc/self/mountinfo をスキャンして、マウント ID が \(aqmount_id\(aq に
375    一致する行を探す。 (もっと簡単な方法は \(aqutil\-linux\(aq プロジェクト
376    が提供する \(aqlibmount\(aq ライブラリをインストールして使うことである)
377    対応するマウントパスをオープンし、得られたファイルディスクリプターを返す。 */
378
379 static int
380 open_mount_path_by_id(int mount_id)
381 {
382     char *linep;
383     size_t lsize;
384     char mount_path[PATH_MAX];
385     int mi_mount_id, found;
386     ssize_t nread;
387     FILE *fp;
388
389     fp = fopen("/proc/self/mountinfo", "r");
390     if (fp == NULL)
391         errExit("fopen");
392
393     found = 0;
394     linep = NULL;
395     while (!found) {
396         nread = getline(&linep, &lsize, fp);
397         if (nread == \-1)
398             break;
399
400         nread = sscanf(linep, "%d %*d %*s %*s %s",
401                        &mi_mount_id, mount_path);
402         if (nread != 2) {
403             fprintf(stderr, "Bad sscanf()\en");
404             exit(EXIT_FAILURE);
405         }
406
407         if (mi_mount_id == mount_id)
408             found = 1;
409     }
410     free(linep);
411
412     fclose(fp);
413
414     if (!found) {
415         fprintf(stderr, "Could not find mount point\en");
416         exit(EXIT_FAILURE);
417     }
418
419     return open(mount_path, O_RDONLY);
420 }
421
422 int
423 main(int argc, char *argv[])
424 {
425     struct file_handle *fhp;
426     int mount_id, fd, mount_fd, handle_bytes;
427     ssize_t nread;
428     char buf[1000];
429 #define LINE_SIZE 100
430     char line1[LINE_SIZE], line2[LINE_SIZE];
431     char *nextp;
432
433     if ((argc > 1 && strcmp(argv[1], "\-\-help") == 0) || argc > 2) {
434         fprintf(stderr, "Usage: %s [mount\-path]\en", argv[0]);
435         exit(EXIT_FAILURE);
436     }
437
438     /* マウント ID とファイルハンドル情報が入った標準入力:
439
440          Line 1: <mount_id>
441          Line 2: <handle_bytes> <handle_type>   <bytes of handle in hex>
442     */
443
444     if ((fgets(line1, sizeof(line1), stdin) == NULL) ||
445            (fgets(line2, sizeof(line2), stdin) == NULL)) {
446         fprintf(stderr, "Missing mount_id / file handle\en");
447         exit(EXIT_FAILURE);
448     }
449
450     mount_id = atoi(line1);
451
452     handle_bytes = strtoul(line2, &nextp, 0);
453
454     /* handle_bytes があれば、
455        file_handle 構造体をここで割り当てできる */
456
457     fhp = malloc(sizeof(*fhp) + handle_bytes);
458     if (fhp == NULL)
459         errExit("malloc");
460
461     fhp\->handle_bytes = handle_bytes;
462
463     fhp\->handle_type = strtoul(nextp, &nextp, 0);
464
465     for (int j = 0; j < fhp\->handle_bytes; j++)
466         fhp\->f_handle[j] = strtoul(nextp, &nextp, 16);
467
468     /* マウントポイントのファイルディスクリプターを取得する。
469        取得は、コマンドラインで指定されたパス名をオープンするか、
470        /proc/self/mounts をスキャンして標準入力から受け取った
471        \(aqmount_id\(aq に一致するマウントを探すことで行う。 */
472
473     if (argc > 1)
474         mount_fd = open(argv[1], O_RDONLY);
475     else
476         mount_fd = open_mount_path_by_id(mount_id);
477
478     if (mount_fd == \-1)
479         errExit("opening mount fd");
480
481     /* ハンドルとマウントポイントを使ってファイルをオープンする */
482
483     fd = open_by_handle_at(mount_fd, fhp, O_RDONLY);
484     if (fd == \-1)
485         errExit("open_by_handle_at");
486
487     /* そのファイルからバイトを読み出す */
488
489     nread = read(fd, buf, sizeof(buf));
490     if (nread == \-1)
491         errExit("read");
492
493     printf("Read %zd bytes\en", nread);
494
495     exit(EXIT_SUCCESS);
496 }
497 .EE
498 .SH 関連項目
499 \fBopen\fP(2), \fBlibblkid\fP(3), \fBblkid\fP(8), \fBfindfs\fP(8), \fBmount\fP(8)
500 .PP
501 .UR https://www.kernel.org/pub/linux/utils/util\-linux/
502 .UE
503 で入手できる最新の
504 \fIutil\-linux\fP リリースの \fIlibblkid\fP と \fIlibmount\fP のドキュメント。
505 .SH この文書について
506 この man ページは Linux \fIman\-pages\fP プロジェクトのリリース 5.10 の一部である。プロジェクトの説明とバグ報告に関する情報は
507 \%https://www.kernel.org/doc/man\-pages/ に書かれている。