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 2014\-06\-13 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 \fIf_handle\fP で返されるハンドルを保持するのに十分な大きさの構造体を確保するのは、 呼び出し元が責任をもって行う必要がある。 呼び出し前に、
71 \fIhandle_bytes\fP フィールドは \fIf_handle\fP 用に格納されたサイズで初期化すべきである
72 (\fI<fcntl.h>\fP で定義されている定数 \fBMAX_HANDLE_SZ\fP でファイルハンドルの最大サイズが規定されている)。
73 呼び出しが成功でリターンする際、 \fIhandle_bytes\fP フィールドは \fIf_handle\fP に実際に書き込まれたバイト数に更新される。
75 呼び出し元では、 \fIhandle\->handle_bytes\fP を 0 に設定して呼び出しを行うことで、 \fIfile_handle\fP
76 構造体に必要なサイズを知ることができる。 この場合、 この呼び出しはエラー \fBEOVERFLOW\fP で失敗し、
77 \fIhandle\->handle_bytes\fP に必要なサイズが設定される。
78 呼び出し元はこの情報を使って、正しいサイズの構造体を割り当てることができる (下記の「例」を参照)。
80 \fIhandle_bytes\fP フィールドを使用する以外は、 呼び出し元は \fIfile_handle\fP 構造体の内容を意識せずに扱うべきである。
81 フィールド \fIhandle_type\fP と \fIf_handle\fP は後で \fBopen_by_handle_at\fP()
84 \fIflags\fP 引き数は、 下記の \fBAT_EMPTY_PATH\fP と \fBAT_SYMLINK_FOLLOW\fP のうち 0
85 個以上の論理和を取って構成されるビットマスクである。
87 引き数 \fIpathname\fP と \fIdirfd\fP はその組み合わせでハンドルを取得するファイルを指定する。 以下の 4 つのパターンがある。
89 \fIpathname\fP が空でない文字列で絶対パス名を含む場合、 このパス名が参照するファイルに対するハンドルが返される。
91 \fIpathname\fP が相対パスが入った空でない文字列で、 \fIdirfd\fP が特別な値 \fBAT_FDCWD\fP の場合、 \fIpathname\fP
92 は呼び出し元のカレントワーキングディレクトリに対する相対パスと解釈され、 そのファイルに対するハンドルが返される。
94 \fIpathname\fP が相対パスが入った空でない文字列で、 \fIdirfd\fP がディレクトリを参照するファイルディスクリプターの場合、
95 \fIpathname\fP は \fIdirfd\fP が参照するディレクトリに対する相対パスと解釈され、
96 そのファイルを参照するハンドルが返される。(なぜ「ディレクトリファイルディスクリプター」が役に立つのかについては \fBopenat\fP(2) を参照。)
98 \fIpathname\fP が空の文字列で \fIflags\fP に \fBAT_EMPTY_PATH\fP が指定されている場合、 \fIdirfd\fP
99 には任意の種別のファイルを参照するオープンされたファイルディスクリプターか \fBAT_FDCWD\fP (カレントワーキングディレクトリを意味する)
100 を指定でき、 \fIdirfd\fP が参照するファイルに対するハンドルが返される。
102 \fImount_id\fP 引き数は、 \fIpathname\fP に対応するファイルシステムのマウントの識別子を返す。 この識別子は
103 \fI/proc/self/mountinfo\fP のいずれかのレコードの最初のフィールドに対応する。 対応するレコードの 5
104 番目のフィールドのパス名をオープンすると、 このマウントポイントのファイルディスクリプターが得られる。 このファイルディスクリプターはこの後の
105 \fBopen_by_handle_at\fP() の呼び出しで使用できる。
107 デフォルトでは、 \fBname_to_handle_at\fP() は \fIpathname\fP がシンボリックリンクの場合にその展開
108 (dereference) を行わず、 リンク自身に対するハンドルを返す。 \fBAT_SYMLINK_FOLLOW\fP が \fIflags\fP
109 に指定されると、 \fIpathname\fP がシンボリックリンクの場合にリンクの展開が行われる (リンクが参照するファイルに対するハンドルが返される)。
110 .SS open_by_handle_at()
111 \fBopen_by_handle_at\fP() システムコールは \fIhandle\fP が参照するファイルをオープンする。 \fIhandle\fP は
112 前に呼び出した \fBname_to_handle_at\fP() が返したファイルハンドルである。
114 \fImount_fd\fP 引き数は、 \fIhandle\fP がそのファイルシステムに関連すると解釈されるマウントされたファイルシステム内の任意のオブジェクト
115 (ファイル、 ディレクトリなど) のファイルディスクリプターである。 特別な値 \fBAT_FDCWD\fP も指定できる。
116 この値は呼び出し元のカレントワーキングディレクトリを意味する。
118 引き数 \fIflags\fP は \fBopen\fP(2) と同じである。 \fIhandle\fP がシンボリックリンクを参照している場合、 呼び出し元は
119 \fBO_PATH\fP フラグを指定しなければならず、 そのシンボリックリンクは展開されない。 \fBO_NOFOLLOW\fP が指定された場合は、
120 \fBO_NOFOLLOW\fP は無視される。
123 \fBopen_by_handle_at\fP() を呼び出すには、 呼び出し元が \fBCAP_DAC_READ_SEARCH\fP
124 ケーパビリティーを持っていなければならない。
126 成功すると、 \fBname_to_handle_at\fP() は 0 を返し、 \fBopen_by_handle_at\fP()
127 は負でないファイルディスクリプターを返す。
129 エラーの場合、 どちらのシステムコールも \-1 を返し、 \fIerrno\fP にエラーの原因を示す値を設定する。
131 \fBname_to_handle_at\fP() と \fBopen_by_handle_at\fP() は \fBopenat\fP(2) と同じエラーで失敗する。
132 また、 これらのシステムコールは以下のエラーで失敗することもある。
134 \fBname_to_handle_at\fP() は以下のエラーで失敗することがある。
137 \fIpathname\fP, \fImount_id\fP, \fIhandle\fP のどれかがアクセス可能なアドレス空間の外を指している。
140 \fIflags\fP に無効なビット値が含まれている。
143 \fIhandle\->handle_bytes\fP が \fBMAX_HANDLE_SZ\fP よりも大きい。
146 \fIpathname\fP が空文字列だが、 \fIflags\fP に \fBAT_EMPTY_PATH\fP がされていなかった。
149 \fIdirfd\fP で指定されたファイルディスクリプターがディレクトリを参照しておらず、 両方の \fIflags\fP に \fBAT_EMPTY_PATH\fP
150 が指定され、 かつ \fIpathname\fP が空文字列である場合でもない。
153 ファイルシステムがパス名をファイルハンドルへの変換をサポートしていない。
158 呼び出しに渡された \fIhandle\->handle_bytes\fP の値が小さすぎた。 このエラーが発生した際、
159 \fIhandle\->handle_bytes\fP はハンドルに必要なサイズに更新される。
161 \fBopen_by_handle_at\fP() は以下のエラーで失敗することがある。
164 \fImount_fd\fP がオープンされたファイルディスクリプターでない。
167 \fIhandle\fP がアクセス可能なアドレス空間の外を指している。
170 \fIhandle\->handle_bytes\fP が \fBMAX_HANDLE_SZ\fP より大きいか 0 に等しい。
173 \fIhandle\fP がシンボリックリンクを参照しているが、 \fIflags\fP に \fBO_PATH\fP がされていなかった。
176 呼び出し元が \fBCAP_DAC_READ_SEARCH\fP ケーパビリティを持っていない。
179 指定された \fIhandle\fP が有効ではない。 このエラーは、 例えばファイルが削除された場合などに発生する。
181 これらのシステムコールは Linux 2.6.39 で初めて登場した。ライブラリによるサポートはバージョン 2.14 以降の glibc
184 これらのシステムコールは非標準の Linux の拡張である。
186 FreeBSD には \fBgetfh\fP() と \fBopenfh\fP() というほとんど同じ機能のシステムコールのペアが存在する。
188 あるプロセスで \fBname_to_handle_at\fP() を使ってファイルハンドルを生成して、 そのハンドルを別のプロセスの
189 \fBopen_by_handle_at\fP() で使用することができる。
191 いくつかのファイルシステムでは、 パス名からファイルハンドルへの変換がサポートされていない。 例えば、 \fI/proc\fP, \fI/sys\fP
192 や種々のネットワークファイルシステムなどである。
194 ファイルハンドルは、 ファイルが削除されたり、 その他のファイルシステム固有の理由で、 無効 ("stale") になる場合がある。
195 無効なハンドルであることは、 \fBopen_by_handle_at\fP() からエラー \fBESTALE\fP が返ることで通知される。
197 .\" https://lwn.net/Articles/375888/
198 .\" "Open by handle" - Jonathan Corbet, 2010-02-23
199 これらのシステムコールは、 ユーザー空間のファイルサーバーでの使用を意図して設計されている。 例えば、 ユーザー空間 NFS
200 サーバーがファイルハンドルを生成して、 そのハンドルを NFS クライアントに渡すことができる。 その後、
201 クライアントがファイルをオープンしようとした際に、 このハンドルをサーバーに送り返すことができる。 このような機能により、
202 ユーザー空間ファイルサーバーは、 そのサーバーが提供するファイルに関してステートレスで (状態を保持せずに) 動作することができる。
204 .\" commit bcda76524cd1fa32af748536f27f674a13e56700
205 \fIpathname\fP がシンボリックリンクを参照していて、 \fIflags\fP に \fBAT_SYMLINK_FOLLOW\fP が指定されていない場合、
206 \fBname_to_handle_at\fP() は (シンボリックが参照するファイルではなく) リンクに対するハンドルを返す。
207 ハンドルを受け取ったプロセスは、 \fBopen_by_handle_at\fP() の \fBO_PATH\fP
208 フラグを使ってハンドルをファイルディスクリプターに変換し、 そのファイルディスクリプターを \fBreadlinkat\fP(2) や
209 \fBfchownat\fP(2) などのシステムコールの \fIdirfd\fP 引き数として渡すことで、 そのシンボリックリンクに対して操作を行うことができる。
210 .SS "永続的なファイルシステム ID の取得"
211 \fI/proc/self/mountinfo\fP のマウント ID は、
212 ファイルシステムのアンマウント、マウントが行われるに連れて再利用されることがある。 したがって、 \fBname_to_handle_at\fP() (の
213 \fI*mount_id\fP) で返されたマウント ID は対応するマウントされたファイルシステムを表す永続的な ID と考えるべきではない。 ただし、
214 アプリケーションは、 マウント ID に対応する \fImountinfo\fP レコードの情報を使うことで、 永続的な ID を得ることができる。
216 .\" e.g., http://stackoverflow.com/questions/6748429/using-libblkid-to-find-uuid-of-a-partition
217 例えば、 \fImountinfo\fP レコードの 5 番目のフィールドのデバイス名を使って、 \fI/dev/disks/by\-uuid\fP
218 のシンボリックリンク経由で対応するデバイス UUID を検索できる。 (UUID を取得するもっと便利な方法は \fBlibblkid\fP(3)
219 ライブラリを使用することである。) そのプロセスは、逆に、 この UUID を使ってデバイス名を検索し、 対応するマウントポイントを取得することで、
220 \fBopen_by_handle_at\fP() で使用する \fImount_fd\fP 引き数を生成することができる。
222 以下の 2 つのプログラムは \fBname_to_handle_at\fP() と \fBopen_by_handle_at\fP()
223 の使用例を示したものである。 最初のプログラム (\fIt_name_to_handle_at.c\fP) は \fBname_to_handle_at\fP()
224 を使用して、 コマンドライン引き数で指定されたファイルに対応するファイルハンドルとマウント ID を取得する。 ハンドルとマウント ID
227 2 つ目のプログラム (\fIt_open_by_handle_at.c\fP) は、 標準入力からマウント ID とファイルハンドルを読み込む。 それから、
228 \fBopen_by_handle_at\fP() を利用して、 そのハンドルを使ってファイルをオープンする。 追加のコマンドライン引き数が指定された場合は、
229 \fBopen_by_handle_at\fP() の \fImount_fd\fP 引き数は、 この引き数で渡された名前のディレクトリをオープンして取得する。
230 それ以外の場合、 \fI/proc/self/mountinfo\fP からスキャンして標準入力から読み込んだマウント ID に一致するマウント ID
231 を検索し、 そのレコードで指定されているマウントディレクトリをオープンして、 \fImount_fd\fP を入手する。 (これらのプログラムではマウント
232 ID が永続的ではない点についての対処は行わない。)
234 以下のシェルセッションは、これら 2 つのプログラムの使用例である。
238 $ \fBecho 'Can you please think about it?' > cecilia.txt\fP
239 $ \fB./t_name_to_handle_at cecilia.txt > fh\fP
240 $ \fB./t_open_by_handle_at < fh\fP
241 open_by_handle_at: Operation not permitted
242 $ \fBsudo ./t_open_by_handle_at < fh\fP # Need CAP_SYS_ADMIN
244 $ \fBrm cecilia.txt\fP
248 .\" Christoph Hellwig: That's why the file handles contain a generation
249 .\" counter that gets incremented in this case.
250 ここで、 ファイルを削除し (すぐに) 再作成する。 同じ内容で (運がよければ) 同じ inode になる。 この場合でも、
251 \fBopen_by_handle_at\fP() はこのファイルハンドルが参照する元のファイルがすでに存在しないことを認識する。
255 $ \fBstat \-\-printf="%i\en" cecilia.txt\fP # Display inode number
257 $ \fBrm cecilia.txt\fP
258 $ \fBecho 'Can you please think about it?' > cecilia.txt\fP
259 $ \fBstat \-\-printf="%i\en" cecilia.txt\fP # Check inode number
261 $ \fBsudo ./t_open_by_handle_at < fh\fP
262 open_by_handle_at: Stale NFS file handle
265 .SS "プログラムのソース: t_name_to_handle_at.c"
269 #include <sys/types.h>
270 #include <sys/stat.h>
278 #define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \e
282 main(int argc, char *argv[])
284 struct file_handle *fhp;
285 int mount_id, fhsize, flags, dirfd, j;
289 fprintf(stderr, "Usage: %s pathname\en", argv[0]);
295 /* file_handle 構造体を確保する */
297 fhsize = sizeof(*fhp);
298 fhp = malloc(fhsize);
302 /* name_to_handle_at() を最初に呼び出して
303 ファイルハンドルに必要なサイズを入手する */
305 dirfd = AT_FDCWD; /* For name_to_handle_at() calls */
306 flags = 0; /* For name_to_handle_at() calls */
307 fhp\->handle_bytes = 0;
308 if (name_to_handle_at(dirfd, pathname, fhp,
309 &mount_id, flags) != \-1 || errno != EOVERFLOW) {
310 fprintf(stderr, "Unexpected result from name_to_handle_at()\en");
314 /* file_handle 構造体を正しいサイズに確保し直す */
316 fhsize = sizeof(struct file_handle) + fhp\->handle_bytes;
317 fhp = realloc(fhp, fhsize); /* Copies fhp\->handle_bytes */
321 /* コマンドラインで指定されたパス名からファイルハンドルを取得 */
323 if (name_to_handle_at(dirfd, pathname, fhp, &mount_id, flags) == \-1)
324 errExit("name_to_handle_at");
326 /* t_open_by_handle_at.c で後で再利用できるように、マウント ID、
327 ファイルハンドルのサイズ、ファイルハンドルを標準出力に書き出す */
329 printf("%d\en", mount_id);
330 printf("%d %d ", fhp\->handle_bytes, fhp\->handle_type);
331 for (j = 0; j < fhp\->handle_bytes; j++)
332 printf(" %02x", fhp\->f_handle[j]);
338 .SS "プログラムのソース: t_open_by_handle_at.c"
342 #include <sys/types.h>
343 #include <sys/stat.h>
351 #define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \e
354 /* /proc/self/mountinfo をスキャンして、マウント ID が \(aqmount_id\(aq に
355 一致する行を探す。 (もっと簡単な方法は \(aqutil\-linux\(aq プロジェクト
356 が提供する \(aqlibmount\(aq ライブラリをインストールして使うことである)
357 対応するマウントパスをオープンし、得られたファイルディスクリプターを返す。 */
360 open_mount_path_by_id(int mount_id)
364 char mount_path[PATH_MAX];
365 int mi_mount_id, found;
369 fp = fopen("/proc/self/mountinfo", "r");
376 nread = getline(&linep, &lsize, fp);
380 nread = sscanf(linep, "%d %*d %*s %*s %s",
381 &mi_mount_id, mount_path);
383 fprintf(stderr, "Bad sscanf()\en");
387 if (mi_mount_id == mount_id)
395 fprintf(stderr, "Could not find mount point\en");
399 return open(mount_path, O_RDONLY);
403 main(int argc, char *argv[])
405 struct file_handle *fhp;
406 int mount_id, fd, mount_fd, handle_bytes, j;
409 #define LINE_SIZE 100
410 char line1[LINE_SIZE], line2[LINE_SIZE];
413 if ((argc > 1 && strcmp(argv[1], "\-\-help") == 0) || argc > 2) {
414 fprintf(stderr, "Usage: %s [mount\-path]\en", argv[0]);
418 /* マウント ID とファイルハンドル情報が入った標準入力:
421 Line 2: <handle_bytes> <handle_type> <bytes of handle in hex>
424 if ((fgets(line1, sizeof(line1), stdin) == NULL) ||
425 (fgets(line2, sizeof(line2), stdin) == NULL)) {
426 fprintf(stderr, "Missing mount_id / file handle\en");
430 mount_id = atoi(line1);
432 handle_bytes = strtoul(line2, &nextp, 0);
434 /* handle_bytes があれば、
435 file_handle 構造体をここで割り当てできる */
437 fhp = malloc(sizeof(struct file_handle) + handle_bytes);
441 fhp\->handle_bytes = handle_bytes;
443 fhp\->handle_type = strtoul(nextp, &nextp, 0);
445 for (j = 0; j < fhp\->handle_bytes; j++)
446 fhp\->f_handle[j] = strtoul(nextp, &nextp, 16);
448 /* マウントポイントのファイルディスクリプターを取得する。
449 取得は、コマンドラインで指定されたパス名をオープンするか、
450 /proc/self/mounts をスキャンして標準入力から受け取った
451 \(aqmount_id\(aq に一致するマウントを探すことで行う。 */
454 mount_fd = open(argv[1], O_RDONLY);
456 mount_fd = open_mount_path_by_id(mount_id);
459 errExit("opening mount fd");
461 /* ハンドルとマウントポイントを使ってファイルをオープンする */
463 fd = open_by_handle_at(mount_fd, fhp, O_RDONLY);
465 errExit("open_by_handle_at");
467 /* そのファイルからバイトを読み出す */
469 nread = read(fd, buf, sizeof(buf));
473 printf("Read %zd bytes\en", nread);
479 \fBopen\fP(2), \fBlibblkid\fP(3), \fBblkid\fP(8), \fBfindfs\fP(8), \fBmount\fP(8)
481 .UR https://www.kernel.org/pub/linux/utils/util\-linux/
484 \fIutil\-linux\fP リリースの \fIlibblkid\fP と \fIlibmount\fP のドキュメント。
486 この man ページは Linux \fIman\-pages\fP プロジェクトのリリース 3.79 の一部
487 である。プロジェクトの説明とバグ報告に関する情報は
488 http://www.kernel.org/doc/man\-pages/ に書かれている。