FTW(3) | Linux Programmer's Manual | FTW(3) |
名前
ftw, nftw -ファイルツリーを歩きまわる書式
#include <ftw.h>
int ftw(const char * dirpath ,
int (* fn ) (const char * fpath , const struct stat * sb ,
int typeflag ),
int nopenfd );
#define _XOPEN_SOURCE 500 /* feature_test_macros(7) 参照 */
#define _XOPEN_SOURCE 500
#include <ftw.h>
int nftw(const char * dirpath ,
int (* fn ) (const char * fpath , const struct stat * sb ,
int typeflag , struct FTW * ftwbuf ),
int nopenfd , int flags );
説明
ftw() は、 dirpath で指定されたディレクトリ以下のディレクトリツリー全体を歩きまわり、ツリー中でエントリが見付かるごとに、 fn() を呼び出す。デフォルトでは、ディレクトリそのものが、そのディレクトリにあるファイルやサブディレクトリよりも先に処理される (行きがけ順探索; preorder traversal)。- FTW_F
- fpath が通常のファイルである
- FTW_D
- fpath がディレクトリである
- FTW_DNR
- fpath が読み込みできないディレクトリである
- FTW_NS
-
シンボリックリンクではない
fpath に対する
stat(2) 呼び出しが失敗した。
ツリーの探索を止めたい場合は、 fn() が 0 以外の値を返せば良い (この値は ftw() 自身の戻り値となる)。それ以外の場合は ftw() はツリー全体の探索を続け、すべてのツリーを探索し終えたところで 0 を返す。探索中に ( malloc(3) の失敗などの) エラーが起こると-1 を返す。
ftw() は動的なデータ構造を用いるので、ツリー探索を安全に中断する唯一の方法は 0 以外の値を fn() の返り値とすることである。割り込みを扱うには、例えば発生した割り込みをマークしておいて、 0 以外の値を返すようにするシグナルによりメモリリークを起こさずに探索を終了できるようにするには、シグナルハンドラで fn() がチェックするグローバルなフラグをセットするようにすればよい。プログラムを終了させる場合以外は、 longjmp(3) を使用しないこと。
nftw()
関数 nftw() は ftw() と同じだが、引き数 flags が追加される点と、 fn() の引き数に ftwbuf が追加される点が異なる。- FTW_ACTIONRETVAL (glibc 2.3.3 以降)
- このフラグは glibc 固有である。このフラグをセットすると、 nftw() の fn() の返り値の扱いが変わる。 fn() は以下の値のいずれか一つを返す必要がある。
- FTW_CONTINUE
- nftw() は通常通り処理を続ける。
- FTW_SKIP_SIBLINGS
- fn() がこの値を返した場合、処理中のエントリの兄弟 (同じ階層のエントリ) の処理はスキップされ、親ディレクトリで続きの処理が行われる。
- FTW_SKIP_SUBTREE
- fn() が呼び出されたエントリがディレクトリ ( typeflag が FTW_D) の場合に、この値を返すと fn() の引き数として渡されたディレクトリ内のエントリの処理が行われなくなる。 nftw() は処理中のディレクトリの兄弟 (同じ階層のエントリ) から処理を続ける。
- FTW_STOP
- nftw () は、返り値 FTW_STOP ですぐに復帰する。
他の返り値は将来新しい動作に対応付けられる可能性がある。 fn() は上記のリストにある値以外を返さないようにすべきである。
<ftw.h> で FTW_ACTIONRETVAL の定義が有効にするためには、 (「どの」ヘッダファイルをインクルードするよりも前に) 機能検査マクロ _GNU_SOURCE を定義しなければならない。
- FTW_CHDIR
- セットされると、ディレクトリの内容を処理する前にそのディレクトリに chdir(2) する。このフラグは、 fpath が属すディレクトリで何らかの動作を実行する必要がある場合に便利である。
- FTW_DEPTH
- セットされると、帰りがけ順探索 (post-order traversal) を行う。つまり、ディレクトリそのものを引き数とした fn() 呼出しは、そのディレクトリに含まれるファイルとサブディレクトリに対する処理の「後で」行われる (デフォルトでは、ディレクトリ自身の処理はディレクトリ内のエントリより「前に」行なわれる)。
- FTW_MOUNT
- セットされると、同じファイルシステムの中だけを探索対象とする (つまり、マウントポイントをまたぐことはない)。
- FTW_PHYS
-
セットされると、シンボリックリンクを辿らない (おそらくこちらが通常望ましい動作だろう)。セットされていないとシンボリックリンクを辿るが、同じファイルが二回報告されることはない。
ディレクトリツリーのエントリ毎に、 nftw() は 4つの引き数で fn() を呼び出す。 fpath と sb は ftw() と同じである。 typeflag には、 ftw() で取り得る値のいずれか、または以下の値のいずれかが渡される:
- FTW_DP
- fpath がディレクトリで、かつ flags で FTW_DEPTH が指定されていた。 fpath 配下のファイルとサブディレクトリは全て処理が終わっている。
- FTW_SL
- fpath がシンボリックリンクで、かつ FTW_PHYS が flags にセットされていた。
- FTW_SLN
- fpath がシンボリックリンクで、存在しないファイルを指している (これがセットされるのは FTW_PHYS がセットされていない場合だけである)。
nftw() が fn() を呼び出す際に渡す 4つめの引き数は FTW 型の構造体である。
struct FTW {
int base;
int level;
};
base は、ファイル名 (basename 要素) の、 fpath で渡されるパス名の中でのオフセットである。 level はディレクトリツリーでの fpath の深さを示す。深さはディレクトリツリーのトップ (root) からの相対値である ( dirpath は深さ 0 である)。
返り値
これらの関数は、成功すると 0 を、エラーが発生すると-1 を返す。準拠
POSIX.1-2001, SVr4, SUSv1. POSIX.1-2008 は ftw() を廃止予定としている。注意
POSIX.1-2001 の注記によると、 fn がカレントワーキングディレクトリを保持しなかった場合の結果は規定されていないとされている。nftw() 関数と、 ftw() における FTW_SL は、SUSv1 で導入された。
ftw() で FTW_SL を一切使わないシステムや、存在しないファイルを指しているシンボリックリンクの場合にのみ FTW_SL を使うシステム、また ftw() が全てのシンボリックリンクに対して FTW_SL を使うシステムもある。予測可能な動作をさせるためには、 nftw() を使うこと。
Linux では、 libc4, libc5, glibc 2.0.6 は「stat できるがディレクトリではないオブジェクト」 (ファイル, シンボリックリンク, fifo 等) に対してはすべて FTW_F を使う。
nftw() 関数は glibc 2.1 以降で利用できる。
FTW_ACTIONRETVAL は glibc 固有である。
例
以下のプログラムは、一つ目のコマンドライン引き数を名前に持つパス以下のディレクトリツリーを探索する。引き数が指定されなかった場合は、カレントディレクトリ以下を探索する。各々のファイルについて様々の情報が表示される。二番目のコマンドライン引き数に文字を指定することで、 nftw() を呼び出す際に flags 引き数に渡す値を制御することができる。
#define _XOPEN_SOURCE 500
#include <ftw.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
static int
display_info(const char *fpath, const struct stat *sb,
int tflag, struct FTW *ftwbuf)
{
printf("%-3s %2d %7jd %-40s %d %s\n",
(tflag == FTW_D) ? "d" : (tflag == FTW_DNR) ? "dnr" :
(tflag == FTW_DP) ? "dp" : (tflag == FTW_F) ? "f" :
(tflag == FTW_NS) ? "ns" : (tflag == FTW_SL) ? "sl" :
(tflag == FTW_SLN) ? "sln" : "???",
ftwbuf->level, (intmax_t) sb->st_size,
fpath, ftwbuf->base, fpath + ftwbuf->base);
return 0; /* To tell nftw() to continue */
}
int
main(int argc, char *argv[])
{
int flags = 0;
if (argc > 2 && strchr(argv[2], 'd') != NULL)
flags |= FTW_DEPTH;
if (argc > 2 && strchr(argv[2], 'p') != NULL)
flags |= FTW_PHYS;
if (nftw((argc < 2) ? "." : argv[1], display_info, 20, flags)
== -1) {
perror("nftw");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
関連項目
stat(2), fts(3), readdir(3)この文書について
この man ページは Linux man-pages プロジェクトのリリース 3.51 の一部である。プロジェクトの説明とバグ報告に関する情報は http://www.kernel.org/doc/man-pages/ に書かれている。2010-09-20 | Linux |