OSDN Git Service

Release pages for LDP v3.77
[linuxjm/LDP_man-pages.git] / release / man7 / fanotify.7
1 .\" Copyright (C) 2013, Heinrich Schuchardt <xypron.glpk@gmx.de>
2 .\" and Copyright (C) 2014, Michael Kerrisk <mtk.manpages@gmail.com>
3 .\"
4 .\" %%%LICENSE_START(VERBATIM)
5 .\" Permission is granted to make and distribute verbatim copies of this
6 .\" manual provided the copyright notice and this permission notice are
7 .\" preserved on all copies.
8 .\"
9 .\" Permission is granted to copy and distribute modified versions of
10 .\" this manual under the conditions for verbatim copying, provided that
11 .\" the entire resulting derived work is distributed under the terms of
12 .\" a permission notice identical to this one.
13 .\"
14 .\" Since the Linux kernel and libraries are constantly changing, this
15 .\" manual page may be incorrect or out-of-date.  The author(s) assume.
16 .\" no responsibility for errors or omissions, or for damages resulting.
17 .\" from the use of the information contained herein.  The author(s) may.
18 .\" not have taken the same level of care in the production of this.
19 .\" manual, which is licensed free of charge, as they might when working.
20 .\" professionally.
21 .\"
22 .\" Formatted or processed versions of this manual, if unaccompanied by
23 .\" the source, must acknowledge the copyright and authors of this work.
24 .\" %%%LICENSE_END
25 .\"*******************************************************************
26 .\"
27 .\" This file was generated with po4a. Translate the source file.
28 .\"
29 .\"*******************************************************************
30 .TH FANOTIFY 7 2014\-12\-31 Linux "Linux Programmer's Manual"
31 .SH 名前
32 fanotify \- ファイルシステムイベントを監視する
33 .SH 説明
34 fanotify API はファイルシステムイベントの通知と横取り機能 (interception) を提供する。
35 ユースケースとしては、ウイルススキャンや階層型ストレージの管理などがある。 現在のところ、限定的なイベントのみがサポートされている。 特に、作成
36 (create)、削除 (delete)、移動 (move) イベントがサポートされていない (これらのイベントを通知する API の詳細については
37 \fBinotify\fP(7) を参照)。
38
39 \fBinotify\fP(7) API と比較して追加されている機能としては、 マウントされたファイルシステムの全オブジェクトを監視する機能、
40 アクセス許可の判定を行う機能、 他のアプリケーションによるアクセスの前にファイルを読み出したり変更したりする機能がある。
41
42 この API では以下のシステムコールを使用する: \fBfanotify_init\fP(2), \fBfanotify_mark\fP(2),
43 \fBread\fP(2), \fBwrite\fP(2), \fBclose\fP(2)。
44 .SS "fanotify_init(), fanotify_mark() と通知グループ"
45 \fBfanotify_init\fP(2) システムコールは fanotify 通知グループを作成、初期化し、
46 この通知グループを参照するファイルディスクリプターを返す。
47 .PP
48 fanotify 通知グループはカーネル内部のオブジェクトで、 イベントが作成されるファイル、 ディレクトリ、 マウントポイントのリストを保持する。
49 .PP
50 fanotify 通知グループの各エントリーには 2 つのビットマスクがある。 \fImark\fP マスクと \fIignore\fP マスクである。 mark
51 マスクはどのファイル操作についてイベントを作成するかを定義する。 ignore マスクはどの操作についてイベントを作成しないかを定義する。 これらの 2
52 種類のマスクがあることで、 マウントポイントやディレクトリに対してイベントの受信を mark しておきつつ、
53 同時にそのマウントポイントやディレクトリ配下の特定のオブジェクトに対するイベントを無視する、 といったことができる。
54 .PP
55 \fBfanotify_mark\fP(2) システムコールは、ファイル、ディレクトリ、マウントを通知グループに追加し、 どのイベントを報告 (もしくは無視)
56 するかを指定する。 また、このようなエントリーの削除、変更も行う。
57 .PP
58 ignore マスクの考えられる使用方法はファイルキャッシュに対してである。
59 ファイルキャッシュに関して興味のあるイベントは、ファイルの変更とファイルのクローズである。 それゆえ、
60 キャッシュされたディレクトリやマウントポイントは、 これらのイベントを受信するようにマークされる。
61 ファイルが変更されたという最初のイベントを受信した後は、 対応するキャッシュエントリーは無効化される。 そのファイルがクローズされるまでは、
62 このファイルに対する変更イベントは興味のない情報となる。 したがって、 変更イベントを ignore マスクに追加することができる。
63 クローズイベントを受信すると、 変更イベントを ignore イベントから削除し、 ファイルキャッシュエントリーを更新することができる。
64 .PP
65 fanotify 通知グループのエントリーは、 ファイルやディレクトリでは inode 番号経由で参照され、 マウントではマウント ID
66 経由で参照される。 ファイルやディレクトリの名前が変更されたり、移動されたりした場合も、 関連するエントリーはそのまま残る。
67 ファイルやディレクトリが削除されたり、マウントがアンマウントされたりした場合には、 対応するエントリーは削除される。
68 .SS イベントキュー
69 通知グループにより監視されているファイルシステムオブジェクトでイベントが発生すると、 fanotify システムはイベントを生成し、
70 そのイベントはキューにまとめられる。 これらのイベントは、 \fBfanotify_init\fP(2) が返した fanotify
71 ファイルディスクリプターから (\fBread\fP(2) などを使って) 読み出すことができる。
72
73 2 種類のイベントが生成される。 \fInotification\fP (通知) イベントと \fIpermission\fP (アクセス許可) イベントである。
74 通知イベントは単なる情報通知であり、 イベントで渡されたファイルディスクリプターをクローズする場合 (下記参照) を除き、
75 受信したアプリケーションでアクションを取る必要はない。 アクセス許可イベントは、
76 受信したアプリケーションがファイルアクセスの許可を承認するかを判定する必要がある。 この場合、
77 受信者はアクセスが許可されたか否かを決定する応答を書き込まなければならない。
78
79 イベントは、 読み出されると、 fanotify グループのイベントキューから削除される。 読み出されたアクセス許可イベントは、 fanotify
80 ファイルディスクリプターにアクセス許可の判定が書き込まれるか、 fanotify ファイルディスクリプターがクローズされるまで、 fanotify
81 グループの内部のリストに保持される。
82 .SS "fanotify イベントの読み出し"
83 \fBfanotify_init\fP(2) が返したファイルディスクリプターに対する \fBread\fP(2) を呼び出しは、
84 (\fBfanotify_init\fP(2) の呼び出しでフラグ \fBFAN_NONBLOCK\fP を指定しなかった場合)
85 ファイルイベントが起こるか、呼び出しがシグナルによって割り込まれる (\fBsignal\fP(7) 参照) まで停止する。
86
87 \fBread\fP(2) が成功すると、読み出しバッファーには以下の構造体が 1 つ以上格納される。
88
89 .in +4n
90 .nf
91 struct fanotify_event_metadata {
92     __u32 event_len;
93     __u8 vers;
94     __u8 reserved;
95     __u16 metadata_len;
96     __aligned_u64 mask;
97     __s32 fd;
98     __s32 pid;
99 };
100 .fi
101 .in
102 .PP
103 性能上の理由から、複数のイベントを一度の \fBread\fP(2) で取得できるように大きめのバッファーサイズ (例えば 4096 バイト)
104 を使用することを推奨する。
105
106 \fBread\fP(2) の返り値はバッファーに格納されたバイト数である。 エラーの場合は \-1 が返される (ただし、バグも参照)。
107
108 \fIfanotify_event_metadata\fP 構造体のフィールドは以下のとおりである。
109 .TP 
110 \fIevent_len\fP
111 これは、 このイベントのデータ長であり、バッファー内の次のイベントへのオフセットである。 現在の実装では、 \fIevent_len\fP の値は常に
112 \fBFAN_EVENT_METADATA_LEN\fP である。 しかしながら、 API は将来可変長の構造体を返すことができるように設計されている。
113 .TP 
114 \fIvers\fP
115 このフィールドには構造体のバージョン番号が入る。 実行時に返された構造体がコンパイル時の構造体と一致しているかを検査するには、 この値を
116 \fBFANOTIFY_METADATA_VERSION\fP を比較すること。 一致しない場合、 アプリケーションはその fanotify
117 ファイルディスクリプターを使用するのを諦めるべきである。
118 .TP 
119 \fIreserved\fP
120 このフィールドは使用されない。
121 .TP 
122 \fImetadata_len\fP
123 この構造体の長さである。 このフィールドは、 イベント種別単位のオプションヘッダーの実装を扱うために導入された。
124 現在の実装ではこのようなオプションヘッダーは存在しない。
125 .TP 
126 \fImask\fP
127 イベントを示すビットマスクである (下記参照)
128 .TP 
129 \fIfd\fP
130 これはアクセスされたオブジェクトに対するオープンされたファイルディスクリプターである。 または、キューのオーバーフローが発生した場合には
131 \fBFAN_NOFD\fP が入る。 ファイルディスクリプターは監視対象のファイルやディレクトリの内容にアクセスするのに使用できる。
132 読み出したアプリケーションは責任を持ってこのファイルディスクリプターをクローズしなければならない。
133 .IP
134 \fBfanotify_init\fP(2) を呼び出す際、
135 呼び出し元はこのファイルディスクリプターに対応するオープンファイル記述にセットされた様々なファイル状態フラグを (\fIevent_f_flags\fP
136 引き数を使って) 指定することができる。 さらに、 (カーネル内部の) \fBFMODE_NONOTIFY\fP
137 ファイル状態フラグがオープンファイル記述にセットされる。 このフラグは fanotify イベントの生成を抑制する。 したがって、 fanotify
138 イベントの受信者がこのファイルディスクリプターを使って通知されたファイルやディレクトリにアクセスした際に、 これ以上イベントが作成されなくなる。
139 .TP 
140 \fIpid\fP
141 これはイベントが発生する原因となったプロセス ID である。 fanotify イベントを監視しているプログラムは、 この PID を
142 \fBgetpid\fP(2) が返す PID と比較することで、 イベントが監視しているプログラム自身から発生したかどうか、
143 別のプロセスによるファイルアクセスにより発生したか、を判定できる。
144 .PP
145 \fImask\fP のビットマスクは、1 つのファイルシステムオブジェクトに対してどのイベントが発生したかを示す。
146 監視対象のファイルシステムオブジェクトに複数のイベントが発生した場合は、 このマスクに複数のビットがセットされることがある。 特に、
147 同じファイルシステムオブジェクトに対する連続するイベントが同じプロセスから生成された場合には、 一つのイベントにまとめられることがある。 例外として、
148 2 つのアクセス許可イベントが一つのキューエントリーにまとめられることは決してない。
149 .PP
150 \fImask\fP でセットされている可能性のあるビットは以下のとおりである。
151 .TP 
152 \fBFAN_ACCESS\fP
153 ファイルやディレクトリがアクセスされた (読み出しが行われた) (ただし、「バグ」の節も参照)。
154 .TP 
155 \fBFAN_OPEN\fP
156 ファイルやディレクトリがオープンされた。
157 .TP 
158 \fBFAN_MODIFY\fP
159 ファイルやディレクトリが変更された。
160 .TP 
161 \fBFAN_CLOSE_WRITE\fP
162 書き込み用 (\fBO_WRONLY\fP か \fBO_RDWR\fP) にオープンされたファイルがクローズされた。
163 .TP 
164 \fBFAN_CLOSE_NOWRITE\fP
165 読み出し用 (\fBO_RDONLY\fP) にオープンされたファイルがクローズされた。
166 .TP 
167 \fBFAN_Q_OVERFLOW\fP
168 イベントキューが 16384 エントリーの上限を超過した。 この上限は \fBfanotify_init\fP(2) 呼び出し時に
169 \fBFAN_UNLIMITED_QUEUE\fP フラグを指定することで上書きできる。
170 .TP 
171 \fBFAN_ACCESS_PERM\fP
172 アプリケーションが例えば \fBread\fP(2) や \fBreaddir\fP(2) などを使ってファイルやディレクトリを読み出そうとした。
173 このイベントを読み出したプログラムは、 そのファイルシステムオブジェクトへのアクセス許可を承認するかを判定し (下記で説明するとおり)
174 応答を書き込まなければならない。
175 .TP 
176 \fBFAN_OPEN_PERM\fP
177 アプリケーションがファイルやディレクトリをオープンしようとした。 このイベントを読み出したプログラムは、
178 そのファイルシステムオブジェクトのオープンを承認するかを判定し (下記で説明するとおり) 応答を書き込まなければならない。
179 .PP
180 クローズイベントを確認するために以下のビットマスクを使うことができる。
181 .TP 
182 \fBFAN_CLOSE\fP
183 ファイルがクローズされた。 以下の同義語である。
184
185     FAN_CLOSE_WRITE | FAN_CLOSE_NOWRITE
186 .PP
187 fanotify ファイルディスクリプターからの \fBread\fP(2) が返した fanotify
188 イベントメタデータを含むバッファーに対して繰り返しを行うため、 以下のマクロが提供されている。
189 .TP 
190 \fBFAN_EVENT_OK(meta, len)\fP
191 このマクロは、 バッファー \fImeta\fP の残りの長さ \fIlen\fP を、 メタデータ構造体の長さとバッファーの最初のメタデータ構造体の
192 \fIevent_len\fP フィールドと比較して検査する。
193 .TP 
194 \fBFAN_EVENT_NEXT(meta, len)\fP
195 このマクロは、 \fImeta\fP が指すメタデータ構造体の \fIevent_len\fP フィールドで示された長さを使って、 \fImeta\fP
196 の次のメタデータ構造体のアドレスを計算する。 \fIlen\fP はバッファーに現在残っているメタデータのバイト数である。 このマクロは \fImeta\fP
197 の次のメタデータ構造体へのポインターを返し、 スキップされたメタデータ構造体のバイト数だけ \fIlen\fP を減算する (つまり、 \fIlen\fP から
198 \fImeta\->event_len\fP を引き算する)。
199 .PP
200 また、 以下のマクロも用意されている。
201 .TP 
202 \fBFAN_EVENT_METADATA_LEN\fP
203 .\"
204 このマクロは \fIfanotify_event_metadata\fP 構造体の (バイト単位の) サイズを返す。
205 返される値はイベントメタデータの最小値である (現在のところ、これが唯一のサイズである)。
206 .SS "fanotify ファイルディスクリプターのイベントを監視する"
207 fanotify イベントが発生すると、 \fBepoll\fP(7), \fBpoll\fP(2), \fBselect\fP(2) に fanotify
208 ファイルディスクリプターが渡された場合には、そのファイルディスクリプターが読み出し可能であると通知される。
209 .SS アクセス許可イベントの取り扱い
210 アクセス許可イベントでは、 アプリケーションは以下の形式の構造体を fanotify ファイルディスクリプターに \fBwrite\fP(2)
211 しなければならない。
212
213 .in +4n
214 .nf
215 struct fanotify_response {
216     __s32 fd;
217     __u32 response;
218 };
219 .fi
220 .in
221 .PP
222 この構造体のフィールドは以下のとおりである。
223 .TP 
224 \fIfd\fP
225 このフィールドは \fIfanotify_event_metadata\fP 構造体で返されたファイルディスクリプターである。
226 .TP 
227 \fIresponse\fP
228 このフィールドはアクセス許可を承認するかどうかを示す。 値は、このファイル操作を許可する \fBFAN_ALLOW\fP か、 このファイル操作を拒否する
229 \fBFAN_DENY\fP のいずれかでなければならない。
230 .PP
231 アクセスを拒否した場合、 アクセスを要求したアプリケーションは \fBEPERM\fP エラーを受け取ることになる。
232 .SS "fanotify ファイルディスクリプターのクローズ"
233 .PP
234 fanotify 通知グループを参照するすべてのファイルディスクリプターがクローズされると、 fanotify グループは解放され、
235 カーネルが再利用できるようにそのリソースは解放される。 \fBclose\fP(2) の際に、 処理中であったアクセス許可イベントには許可が設定される。
236 .SS /proc/[pid]/fdinfo
237 ファイル \fI/proc/[pid]/fdinfo/[fd]\fP には、 プロセス \fIpid\fP のファイルディスクリプター \fIfd\fP の
238 fanotify マークに関する情報が格納される。 詳細はカーネルのソースファイル
239 \fIDocumentation/filesystems/proc.txt\fP を参照。
240 .SH エラー
241 通常の \fBread\fP(2) のエラーに加え、 fanotify ファイルディスクリプターから読み出しを行った際に以下のエラーが発生することがある。
242 .TP 
243 \fBEINVAL\fP
244 バッファーがイベントを保持するには小さすぎる。
245 .TP 
246 \fBEMFILE\fP
247 オープンしたファイル数のプロセス毎の上限に達した。 \fBgetrlimit\fP(2) の \fBRLIMIT_NOFILE\fP の説明を参照。
248 .TP 
249 \fBENFILE\fP
250 オープンされたファイル数のシステム全体の上限に達した。 \fBproc\fP(5) の \fI/proc/sys/fs/file\-max\fP を参照。
251 .TP 
252 \fBETXTBSY\fP
253 \fBfanotify_init\fP(2) の呼び出し時に \fBO_RDWR\fP か \fBO_WRONLY\fP が \fIevent_f_flags\fP
254 引き数に指定されており、 現在実行中の監視対象のファイルに対してイベントが発生した際に、 このエラーが \fBread\fP(2) から返される。
255 .PP
256 通常の \fBwrite\fP(2) のエラーに加え、 fanotify ファイルディスクリプターに書き込みを行った際に以下のエラーが発生することがある。
257 .TP 
258 \fBEINVAL\fP
259 fanotify アクセス許可がカーネルの設定で有効になっていない。 応答構造体の \fIresponse\fP 値が無効である。
260 .TP 
261 \fBENOENT\fP
262 応答構造体のファイルディスクリプター \fIfd\fP が無効である。 このエラーはアクセス許可イベントに対する応答がすでに書き込まれている際に発生する。
263 .SH バージョン
264 fanotify API は Linux カーネルのバージョン 2.6.36 で導入され、 バージョン 2.6.37 で有効にされた。 fdinfo
265 のサポートはバージョン 3.8 で追加された。
266 .SH 準拠
267 fanotify API は Linux 独自のものである。
268 .SH 注意
269 fanotify API が利用できるのは、 カーネルが \fBCONFIG_FANOTIFY\fP 設定オプションを有効にして作成されている場合だけである。
270 また、 fanotify アクセス許可の処理が利用できるのは \fBCONFIG_FANOTIFY_ACCESS_PERMISSIONS\fP
271 設定オプションが有効になっている場合だけである。
272 .SS 制限と警告
273 fanotify が報告するのはユーザー空間プログラムがファイルシステム API 経由で行ったイベントだけである。 その結果、 fanotify
274 ではネットワークファイルシステム上で発生したリモートイベントは捕捉できない。
275 .PP
276 inotify API は \fBmmap\fP(2), \fBmsync\fP(2), \fBmunmap\fP(2)
277 により起こったファイルのアクセスと変更を報告しない。
278 .PP
279 ディレクトリのイベントは、ディレクトリ自身がオープン、読み出し、クローズされた場合にしか作成されない。
280 マークされたディレクトリでの子要素の追加、削除、変更では、監視対象のディレクトリ自身へのイベントは作成されない。
281 .PP
282 fanotify のディレクトリの監視は再帰的ではない。 ディレクトリ内のサブディレクトリを監視するには、
283 追加で監視用のマークを作成しなければならない。 (ただし、 fanotify API
284 では、サブディレクトリが監視対象としてマークされているディレクトリに作成された際に検出する手段は提供されていない点に注意すること。)
285 マウントの監視を使うことで、 ディレクトリツリー全体を監視することができる。
286 .PP
287 ベントキューはオーバーフローすることがある。 この場合、 イベントは失われる。
288 .SH バグ
289 Linux 3.17 時点では、 以下のバグが存在する。
290 .IP * 3
291 Linux では、ファイルシステムオブジェクトは複数のパスでアクセス可能である。 例えば、 ファイルシステムの一部は \fBmount\fP(8) の
292 \fI\-\-bind\fP オプションを使って再マウントされることがある。 マークされたマウントの監視者は、
293 同じマウントを使ったファイルオブジェクトについてのみイベント通知を受ける。 それ以外のイベントは通知されない。
294 .IP *
295 \fBfallocate\fP(2) の呼び出しでは fanotify イベントが作成されない。
296 .IP *
297 .\" FIXME . A patch was proposed.
298 イベントが生成された際に、 そのファイルのファイルディスクリプターを渡す前に、 イベントを受信するプロセスのユーザー ID
299 がそのファイルに対する読み出し/書き込み許可があるかの確認は行われない。 非特権ユーザーによって実行されたプログラムに \fBCAP_SYS_ADMIN\fP
300 ケーパビリティーがセットされている場合には、 このことはセキュリティーリスクとなる。
301 .IP *
302 \fBread\fP(2) の呼び出しが fanotify キューから複数のイベントを処理している際に、 エラーが発生した場合、
303 返り値はエラーが発生する前までにユーザー空間バッファーに正常にコピーされたイベントの合計長となる。 返り値は \-1 にならず、 \fIerrno\fP
304 もセットされない。 したがって、 読み出しを行うアプリケーションではエラーを検出する方法はない。
305 .SH 例
306 以下のプログラムは fanotify API の使用法を示すものである。 コマンドライン引き数で渡されたマウントポイントを監視し、 種別が
307 \fBFAN_PERM_OPEN\fP と \fBFAN_CLOSE_WRITE\fP のイベントを待つ。 アクセス許可イベントが発生には、
308 \fBFAN_ALLOW\fP 応答を返す。
309 .PP
310 以下の出力例はファイル \fI/home/user/temp/notes\fP を編集した際に記録されたものである。 ファイルをオープンする前に
311 \fBFAN_OPEN_PERM\fP イベントが発生している。 ファイルをクローズした後に \fBFAN_CLOSE_WRITE\fP イベントが発生している。
312 エンターキーをユーザーが押すと、 このプログラムの実行は終了する。
313 .SS 出力例
314 .in +4n
315 .nf
316 # ./fanotify_example /home
317 Press enter key to terminate.
318 Listening for events.
319 FAN_OPEN_PERM: File /home/user/temp/notes
320 FAN_CLOSE_WRITE: File /home/user/temp/notes
321
322 Listening for events stopped.
323 .fi
324 .in
325 .SS プログラムソース
326 .nf
327 #define _GNU_SOURCE     /* O_LARGEFILE の定義を得るために必要 */
328 #include <errno.h>
329 #include <fcntl.h>
330 #include <limits.h>
331 #include <poll.h>
332 #include <stdio.h>
333 #include <stdlib.h>
334 #include <sys/fanotify.h>
335 #include <unistd.h>
336
337 /* ファイルディスクリプター 'fd' から読み出しできる全 fanotify イベントを読み出す */
338
339 static void
340 handle_events(int fd)
341 {
342     const struct fanotify_event_metadata *metadata;
343     struct fanotify_event_metadata buf[200];
344     ssize_t len;
345     char path[PATH_MAX];
346     ssize_t path_len;
347     char procfd_path[PATH_MAX];
348     struct fanotify_response response;
349
350     /* fanotify ファイルディスクリプターからイベントが読み出せる間はループする */
351
352     for(;;) {
353
354         /* イベントを読み出す */
355
356         len = read(fd, (void *) &buf, sizeof(buf));
357         if (len == \-1 && errno != EAGAIN) {
358             perror("read");
359             exit(EXIT_FAILURE);
360         }
361
362         /* 読み出せるデータの最後に達しているかチェックする */
363
364         if (len <= 0)
365             break;
366
367         /* バッファーの最初のイベントを参照する */
368
369         metadata = buf;
370
371         /* バッファー内の全イベントを処理する */
372
373         while (FAN_EVENT_OK(metadata, len)) {
374
375             /* 実行時とコンパイル時の構造体が一致するか確認する */
376
377             if (metadata\->vers != FANOTIFY_METADATA_VERSION) {
378                 fprintf(stderr,
379                         "Mismatch of fanotify metadata version.\en");
380                 exit(EXIT_FAILURE);
381             }
382
383             /* metadata\->fd には、キューのオーバーフローを示す FAN_NOFD か、
384                ファイルディスクリプター (負でない整数) のいずれかが入っている。
385                ここではキューのオーバーフローは無視している。 */
386
387             if (metadata\->fd >= 0) {
388
389                 /* オープン許可イベントを処理する */
390
391                 if (metadata\->mask & FAN_OPEN_PERM) {
392                     printf("FAN_OPEN_PERM: ");
393
394                     /* ファイルのオープンを許可する */
395
396                     response.fd = metadata\->fd;
397                     response.response = FAN_ALLOW;
398                     write(fd, &response,
399                           sizeof(struct fanotify_response));
400                 }
401
402                 /* 書き込み可能ファイルのクローズイベントを処理する */
403
404                 if (metadata\->mask & FAN_CLOSE_WRITE)
405                     printf("FAN_CLOSE_WRITE: ");
406
407                 /* アクセスされたファイルのパス名を取得し表示する */
408
409                 snprintf(procfd_path, sizeof(procfd_path),
410                          "/proc/self/fd/%d", metadata\->fd);
411                 path_len = readlink(procfd_path, path,
412                                     sizeof(path) \- 1);
413                 if (path_len == \-1) {
414                     perror("readlink");
415                     exit(EXIT_FAILURE);
416                 }
417
418                 path[path_len] = '\e0';
419                 printf("File %s\en", path);
420
421                 /* イベントのファイルディスクリプターをクローズする */
422
423                 close(metadata\->fd);
424             }
425
426             /* 次のイベントに進む */
427
428             metadata = FAN_EVENT_NEXT(metadata, len);
429         }
430     }
431 }
432
433 int
434 main(int argc, char *argv[])
435 {
436     char buf;
437     int fd, poll_num;
438     nfds_t nfds;
439     struct pollfd fds[2];
440
441     /* マウントポイントが指定されたか確認する */
442
443     if (argc != 2) {
444         fprintf(stderr, "Usage: %s MOUNT\en", argv[0]);
445         exit(EXIT_FAILURE);
446     }
447
448     printf("Press enter key to terminate.\en");
449
450     /* fanotify API にアクセスするためのファイルディスクリプターを作成する */
451
452     fd = fanotify_init(FAN_CLOEXEC | FAN_CLASS_CONTENT | FAN_NONBLOCK,
453                        O_RDONLY | O_LARGEFILE);
454     if (fd == \-1) {
455         perror("fanotify_init");
456         exit(EXIT_FAILURE);
457     }
458
459     /* 指定されたマウントに対して以下を監視するようにマークを付ける:
460        \- ファイルのオープン前のアクセス許可イベント
461        \- 書き込み可能なファイルディスクリプターのクローズ後の
462          通知イベント */
463
464     if (fanotify_mark(fd, FAN_MARK_ADD | FAN_MARK_MOUNT,
465                       FAN_OPEN_PERM | FAN_CLOSE_WRITE, AT_FDCWD,
466                       argv[1]) == \-1) {
467         perror("fanotify_mark");
468         exit(EXIT_FAILURE);
469     }
470
471     /* ポーリングの準備 */
472
473     nfds = 2;
474
475     /* コンソールの入力 */
476
477     fds[0].fd = STDIN_FILENO;
478     fds[0].events = POLLIN;
479
480     /* fanotify の入力 */
481
482     fds[1].fd = fd;
483     fds[1].events = POLLIN;
484
485     /* イベントの発生を待つループ */
486
487     printf("Listening for events.\en");
488
489     while (1) {
490         poll_num = poll(fds, nfds, \-1);
491         if (poll_num == \-1) {
492             if (errno == EINTR)     /* シグナルに割り込まれた場合 */
493                 continue;           /* poll() を再開する */
494
495             perror("poll");         /* 予期しないエラー */
496             exit(EXIT_FAILURE);
497         }
498
499         if (poll_num > 0) {
500             if (fds[0].revents & POLLIN) {
501
502                 /* コンソールからの入力がある場合: 空の標準入力であれば終了 */
503
504                 while (read(STDIN_FILENO, &buf, 1) > 0 && buf != '\en')
505                     continue;
506                 break;
507             }
508
509             if (fds[1].revents & POLLIN) {
510
511                 /* fanotify イベントがある場合 */
512
513                 handle_events(fd);
514             }
515         }
516     }
517
518     printf("Listening for events stopped.\en");
519     exit(EXIT_SUCCESS);
520 }
521 .fi
522 .SH 関連項目
523 .ad l
524 \fBfanotify_init\fP(2), \fBfanotify_mark\fP(2), \fBinotify\fP(7)
525 .SH この文書について
526 この man ページは Linux \fIman\-pages\fP プロジェクトのリリース 3.77 の一部
527 である。プロジェクトの説明とバグ報告に関する情報は
528 http://www.kernel.org/doc/man\-pages/ に書かれている。