1 .\" Copyright (c) 2014 by Michael Kerrisk <mtk.manpages@gmail.com>
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.
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.
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
21 .\" Formatted or processed versions of this manual, if unaccompanied by
22 .\" the source, must acknowledge the copyright and authors of this work.
25 .\"*******************************************************************
27 .\" This file was generated with po4a. Translate the source file.
29 .\"*******************************************************************
30 .TH OPEN_BY_HANDLE_AT 2 2020\-11\-01 Linux "Linux Programmer's Manual"
32 name_to_handle_at, open_by_handle_at \- パス名に対するハンドルの取得とハンドルによるファイルのオープン
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
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
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
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
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
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.
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.
89 \fIhandle_bytes\fP フィールドを使用する以外は、 呼び出し元は \fIfile_handle\fP 構造体の内容を意識せずに扱うべきである。
90 フィールド \fIhandle_type\fP と \fIf_handle\fP は後で \fBopen_by_handle_at\fP()
93 \fIflags\fP 引き数は、 下記の \fBAT_EMPTY_PATH\fP と \fBAT_SYMLINK_FOLLOW\fP のうち 0
94 個以上の論理和を取って構成されるビットマスクである。
96 引き数 \fIpathname\fP と \fIdirfd\fP はその組み合わせでハンドルを取得するファイルを指定する。 以下の 4 つのパターンがある。
98 \fIpathname\fP が空でない文字列で絶対パス名を含む場合、 このパス名が参照するファイルに対するハンドルが返される。
100 \fIpathname\fP が相対パスが入った空でない文字列で、 \fIdirfd\fP が特別な値 \fBAT_FDCWD\fP の場合、 \fIpathname\fP
101 は呼び出し元のカレントワーキングディレクトリに対する相対パスと解釈され、 そのファイルに対するハンドルが返される。
103 \fIpathname\fP が相対パスが入った空でない文字列で、 \fIdirfd\fP がディレクトリを参照するファイルディスクリプターの場合、
104 \fIpathname\fP は \fIdirfd\fP が参照するディレクトリに対する相対パスと解釈され、
105 そのファイルを参照するハンドルが返される。(なぜ「ディレクトリファイルディスクリプター」が役に立つのかについては \fBopenat\fP(2) を参照。)
107 \fIpathname\fP が空の文字列で \fIflags\fP に \fBAT_EMPTY_PATH\fP が指定されている場合、 \fIdirfd\fP
108 には任意の種別のファイルを参照するオープンされたファイルディスクリプターか \fBAT_FDCWD\fP (カレントワーキングディレクトリを意味する)
109 を指定でき、 \fIdirfd\fP が参照するファイルに対するハンドルが返される。
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.
119 デフォルトでは、 \fBname_to_handle_at\fP() は \fIpathname\fP がシンボリックリンクの場合にその展開
120 (dereference) を行わず、 リンク自身に対するハンドルを返す。 \fBAT_SYMLINK_FOLLOW\fP が \fIflags\fP
121 に指定されると、 \fIpathname\fP がシンボリックリンクの場合にリンクの展開が行われる (リンクが参照するファイルに対するハンドルが返される)。
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() が返したファイルハンドルである。
135 \fImount_fd\fP 引き数は、 \fIhandle\fP がそのファイルシステムに関連すると解釈されるマウントされたファイルシステム内の任意のオブジェクト
136 (ファイル、 ディレクトリなど) のファイルディスクリプターである。 特別な値 \fBAT_FDCWD\fP も指定できる。
137 この値は呼び出し元のカレントワーキングディレクトリを意味する。
139 引き数 \fIflags\fP は \fBopen\fP(2) と同じである。 \fIhandle\fP がシンボリックリンクを参照している場合、 呼び出し元は
140 \fBO_PATH\fP フラグを指定しなければならず、 そのシンボリックリンクは展開されない。 \fBO_NOFOLLOW\fP が指定された場合は、
141 \fBO_NOFOLLOW\fP は無視される。
143 \fBopen_by_handle_at\fP() を呼び出すには、 呼び出し元が \fBCAP_DAC_READ_SEARCH\fP
144 ケーパビリティーを持っていなければならない。
146 成功すると、 \fBname_to_handle_at\fP() は 0 を返し、 \fBopen_by_handle_at\fP() はファイルディスクリプター
149 エラーの場合、 どちらのシステムコールも \-1 を返し、 \fIerrno\fP にエラーの原因を示す値を設定する。
151 \fBname_to_handle_at\fP() と \fBopen_by_handle_at\fP() は \fBopenat\fP(2) と同じエラーで失敗する。
152 また、 これらのシステムコールは以下のエラーで失敗することもある。
154 \fBname_to_handle_at\fP() は以下のエラーで失敗することがある。
157 \fIpathname\fP, \fImount_id\fP, \fIhandle\fP のどれかがアクセス可能なアドレス空間の外を指している。
160 \fIflags\fP に無効なビット値が含まれている。
163 \fIhandle\->handle_bytes\fP が \fBMAX_HANDLE_SZ\fP よりも大きい。
166 \fIpathname\fP が空文字列だが、 \fIflags\fP に \fBAT_EMPTY_PATH\fP がされていなかった。
169 \fIdirfd\fP で指定されたファイルディスクリプターがディレクトリを参照しておらず、 両方の \fIflags\fP に \fBAT_EMPTY_PATH\fP
170 が指定され、 かつ \fIpathname\fP が空文字列である場合でもない。
173 ファイルシステムがパス名をファイルハンドルへの変換をサポートしていない。
178 呼び出しに渡された \fIhandle\->handle_bytes\fP の値が小さすぎた。 このエラーが発生した際、
179 \fIhandle\->handle_bytes\fP はハンドルに必要なサイズに更新される。
181 \fBopen_by_handle_at\fP() は以下のエラーで失敗することがある。
184 \fImount_fd\fP がオープンされたファイルディスクリプターでない。
187 \fIhandle\fP がアクセス可能なアドレス空間の外を指している。
190 \fIhandle\->handle_bytes\fP が \fBMAX_HANDLE_SZ\fP より大きいか 0 に等しい。
193 \fIhandle\fP がシンボリックリンクを参照しているが、 \fIflags\fP に \fBO_PATH\fP がされていなかった。
196 呼び出し元が \fBCAP_DAC_READ_SEARCH\fP ケーパビリティを持っていない。
199 指定された \fIhandle\fP が有効ではない。 このエラーは、 例えばファイルが削除された場合などに発生する。
201 これらのシステムコールは Linux 2.6.39 で初めて登場した。ライブラリによるサポートはバージョン 2.14 以降の glibc
204 これらのシステムコールは非標準の Linux の拡張である。
206 FreeBSD には \fBgetfh\fP() と \fBopenfh\fP() というほとんど同じ機能のシステムコールのペアが存在する。
208 あるプロセスで \fBname_to_handle_at\fP() を使ってファイルハンドルを生成して、 そのハンドルを別のプロセスの
209 \fBopen_by_handle_at\fP() で使用することができる。
211 いくつかのファイルシステムでは、 パス名からファイルハンドルへの変換がサポートされていない。 例えば、 \fI/proc\fP, \fI/sys\fP
212 や種々のネットワークファイルシステムなどである。
214 ファイルハンドルは、 ファイルが削除されたり、 その他のファイルシステム固有の理由で、 無効 ("stale") になる場合がある。
215 無効なハンドルであることは、 \fBopen_by_handle_at\fP() からエラー \fBESTALE\fP が返ることで通知される。
217 .\" https://lwn.net/Articles/375888/
218 .\" "Open by handle" - Jonathan Corbet, 2010-02-23
219 これらのシステムコールは、 ユーザー空間のファイルサーバーでの使用を意図して設計されている。 例えば、 ユーザー空間 NFS
220 サーバーがファイルハンドルを生成して、 そのハンドルを NFS クライアントに渡すことができる。 その後、
221 クライアントがファイルをオープンしようとした際に、 このハンドルをサーバーに送り返すことができる。 このような機能により、
222 ユーザー空間ファイルサーバーは、 そのサーバーが提供するファイルに関してステートレスで (状態を保持せずに) 動作することができる。
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 を得ることができる。
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 引き数を生成することができる。
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
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 が永続的ではない点についての対処は行わない。)
254 以下のシェルセッションは、これら 2 つのプログラムの使用例である。
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
264 $ \fBrm cecilia.txt\fP
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() はこのファイルハンドルが参照する元のファイルがすでに存在しないことを認識する。
275 $ \fBstat \-\-printf="%i\en" cecilia.txt\fP # Display inode number
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
281 $ \fBsudo ./t_open_by_handle_at < fh\fP
282 open_by_handle_at: Stale NFS file handle
285 .SS "プログラムのソース: t_name_to_handle_at.c"
289 #include <sys/types.h>
290 #include <sys/stat.h>
298 #define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \e
302 main(int argc, char *argv[])
304 struct file_handle *fhp;
305 int mount_id, fhsize, flags, dirfd;
309 fprintf(stderr, "Usage: %s pathname\en", argv[0]);
315 /* file_handle 構造体を確保する */
317 fhsize = sizeof(*fhp);
318 fhp = malloc(fhsize);
322 /* name_to_handle_at() を最初に呼び出して
323 ファイルハンドルに必要なサイズを入手する */
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");
334 /* file_handle 構造体を正しいサイズに確保し直す */
336 fhsize = sizeof(*fhp) + fhp\->handle_bytes;
337 fhp = realloc(fhp, fhsize); /* Copies fhp\->handle_bytes */
341 /* コマンドラインで指定されたパス名からファイルハンドルを取得 */
343 if (name_to_handle_at(dirfd, pathname, fhp, &mount_id, flags) == \-1)
344 errExit("name_to_handle_at");
346 /* t_open_by_handle_at.c で後で再利用できるように、マウント ID、
347 ファイルハンドルのサイズ、ファイルハンドルを標準出力に書き出す */
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]);
358 .SS "プログラムのソース: t_open_by_handle_at.c"
362 #include <sys/types.h>
363 #include <sys/stat.h>
371 #define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \e
374 /* /proc/self/mountinfo をスキャンして、マウント ID が \(aqmount_id\(aq に
375 一致する行を探す。 (もっと簡単な方法は \(aqutil\-linux\(aq プロジェクト
376 が提供する \(aqlibmount\(aq ライブラリをインストールして使うことである)
377 対応するマウントパスをオープンし、得られたファイルディスクリプターを返す。 */
380 open_mount_path_by_id(int mount_id)
384 char mount_path[PATH_MAX];
385 int mi_mount_id, found;
389 fp = fopen("/proc/self/mountinfo", "r");
396 nread = getline(&linep, &lsize, fp);
400 nread = sscanf(linep, "%d %*d %*s %*s %s",
401 &mi_mount_id, mount_path);
403 fprintf(stderr, "Bad sscanf()\en");
407 if (mi_mount_id == mount_id)
415 fprintf(stderr, "Could not find mount point\en");
419 return open(mount_path, O_RDONLY);
423 main(int argc, char *argv[])
425 struct file_handle *fhp;
426 int mount_id, fd, mount_fd, handle_bytes;
429 #define LINE_SIZE 100
430 char line1[LINE_SIZE], line2[LINE_SIZE];
433 if ((argc > 1 && strcmp(argv[1], "\-\-help") == 0) || argc > 2) {
434 fprintf(stderr, "Usage: %s [mount\-path]\en", argv[0]);
438 /* マウント ID とファイルハンドル情報が入った標準入力:
441 Line 2: <handle_bytes> <handle_type> <bytes of handle in hex>
444 if ((fgets(line1, sizeof(line1), stdin) == NULL) ||
445 (fgets(line2, sizeof(line2), stdin) == NULL)) {
446 fprintf(stderr, "Missing mount_id / file handle\en");
450 mount_id = atoi(line1);
452 handle_bytes = strtoul(line2, &nextp, 0);
454 /* handle_bytes があれば、
455 file_handle 構造体をここで割り当てできる */
457 fhp = malloc(sizeof(*fhp) + handle_bytes);
461 fhp\->handle_bytes = handle_bytes;
463 fhp\->handle_type = strtoul(nextp, &nextp, 0);
465 for (int j = 0; j < fhp\->handle_bytes; j++)
466 fhp\->f_handle[j] = strtoul(nextp, &nextp, 16);
468 /* マウントポイントのファイルディスクリプターを取得する。
469 取得は、コマンドラインで指定されたパス名をオープンするか、
470 /proc/self/mounts をスキャンして標準入力から受け取った
471 \(aqmount_id\(aq に一致するマウントを探すことで行う。 */
474 mount_fd = open(argv[1], O_RDONLY);
476 mount_fd = open_mount_path_by_id(mount_id);
479 errExit("opening mount fd");
481 /* ハンドルとマウントポイントを使ってファイルをオープンする */
483 fd = open_by_handle_at(mount_fd, fhp, O_RDONLY);
485 errExit("open_by_handle_at");
487 /* そのファイルからバイトを読み出す */
489 nread = read(fd, buf, sizeof(buf));
493 printf("Read %zd bytes\en", nread);
499 \fBopen\fP(2), \fBlibblkid\fP(3), \fBblkid\fP(8), \fBfindfs\fP(8), \fBmount\fP(8)
501 .UR https://www.kernel.org/pub/linux/utils/util\-linux/
504 \fIutil\-linux\fP リリースの \fIlibblkid\fP と \fIlibmount\fP のドキュメント。
506 この man ページは Linux \fIman\-pages\fP プロジェクトのリリース 5.10 の一部である。プロジェクトの説明とバグ報告に関する情報は
507 \%https://www.kernel.org/doc/man\-pages/ に書かれている。