FTS(3)

名称
fts - ファイルの階層を横断する

書式
#include <sys/types.h> #include <sys/stat.h> #include <fts.h> FTS * fts_open(char * const *path_argv, int options, int (*compar)(const FTSENT **, const FTSENT **)) FTSENT * fts_read(FTS *ftsp) FTSENT * fts_children(FTS *ftsp, int options) int fts_set(FTS *ftsp, FTSENT *f, int options) int fts_close(FTS *ftsp)

解説
fts は、 UNIX ファイル階層を横断するための関数です。簡単に説明すると、 fts_open() 関数はファイル階層の「ハンドル」を戻します。このハンドルは、その他の fts 関数に指定できます。 fts_read() 関数は、ファイル階層の 1 つのファイルを表す構造体のポインタを戻します。 fts_children() 関数は、構造体のリンクリストへのポインタを戻します。各構造体は、 その階層のあるディレクトリに含まれるファイル 1 つを表します。 一般に、ディレクトリは、正順 (いずれの子にアクセスする前) と 逆順 (すべての子にアクセスした後) の 2 回アクセスされます。 ファイルは 1 回アクセスされます。 シンボリックリンクを無視した、階層への「論理的な」アクセス、 シンボリックリンクをたどる、階層への物理的なアクセス、 階層へのアクセス命令、階層の一部の切り離しや再アクセスが可能です。

インクルードファイル <fts.h> には、2 つの構造体が定義されて (かつ、typedef 型定義もされて) います。 1 つは、ファイル階層そのものを表す構造体 FTS です。もう 1 つは、ファイル階層のファイル一つを表す構造体 FTSENT です。通常は、ファイル階層のファイルすべてについて、構造体 FTSENT が一つ戻されます。このマニュアルページでは、 “ファイル” と “FTSENT 構造体” は、ほぼ同じ意味を持ちます。 FTSENT 構造体には、少なくとも以下に示すフィールドを含みます。それぞれの フィールドについては、後で詳しく説明します。

    typedef struct _ftsent {
    	u_short fts_info;		/* flags for FTSENT structure */
    	char *fts_accpath;		/* access path */
    	char *fts_path;			/* root path */
    	short fts_pathlen;		/* strlen(fts_path) */
    	char *fts_name;			/* file name */
    	short fts_namelen;		/* strlen(fts_name) */
    	short fts_level;		/* depth (-1 to N) */
    	int fts_errno;			/* file errno */
    	long fts_number;		/* local numeric value */
    	void *fts_pointer;		/* local address value */
    	struct ftsent *fts_parent;	/* parent directory */
    	struct ftsent *fts_link;	/* next file structure */
    	struct ftsent *fts_cycle;	/* cycle structure */
    	struct stat *fts_statp;		/* stat(2) information */
    } FTSENT;

これらのフィールドは、以下のように定義されています。

fts_info
    戻された FTSENT 構造体とそれが表すファイルを記述します。以下のうち 1 つの値を取ります。 エラーのないディレクトリ (FTS_D) を除けば、すべてのエントリは終端です。つまり、再アクセスされることは なく、子がアクセスされることもありません。

    FTS_D
        正順でアクセスされるディレクトリです。

    FTS_DC
        ツリーでの循環の原因となるディレクトリです。 ( FTSENT 構造体の fts_cycle フィールドにも同様にこの情報が入ります。)

    FTS_DEFAULT
        他のどの fts_info の値でも明確に表さないファイルタイプを表す FTSENT 構造体です。

    FTS_DNR
        読み込めないディレクトリです。これはエラーリターンで、 fts_errno フィールドにエラーの原因を表す値が設定されます。

    FTS_DOT
        fts_open() にファイル名として指定されていない、 ‘’. や、 ‘..’ という名前を持つファイルです ( FTS_SEEDOT を参照)。

    FTS_DP
        逆順でアクセスされるディレクトリです。 正順 (つまり、 fts_info フィールドに FTS_D が設定された場合) で戻ってきた時は、 FTSENT 構造体の内容は変更されていません。

    FTS_ERR
        これはエラーリターンであり、 fts_errno フィールドにエラーの原因が設定されます。

    FTS_F
        通常ファイルです。

    FTS_NS
        stat(2) で情報が取得できないファイルです。 fts_statp フィールドの内容は未定義になります。これはエラーリターンであり、 fts_errno フィールドにエラーの原因を表す値が設定されます。

    FTS_NSOK
        stat(2) での情報取得を要求しないファイルです。 fts_statp フィールドの内容は不定になります。

    FTS_SL
        シンボリックリンクです。

    FTS_SLNONE
        ターゲットが存在しないシンボリックリンクです。 fts_statp フィールドの内容は、そのシンボリックリンク自体の ファイル特性情報を参照します。

fts_accpath
    カレントディレクトリからファイルにアクセスするためのパスです。

fts_path
    横断のルートからの、ファイルの相対パスです。このパスには、 fts_open() に指定したパスが接頭語として含まれます。

fts_pathlen
    fts_path が参照する文字列の長さです。

fts_name
    ファイルの名前です。

fts_namelen
    fts_name が参照する文字列の長さです。

fts_level
    このファイルが見つかった場所の、この横断における深さです。この深さは -1 から N までの番号が付けられます。横断の開始点の親 (またはルート) を表す FTSENT 構造体には、番号 -1 が付されます。 ルートの FTSENT 構造体には、番号 0 が付されます。

fts_errno
    関数 fts_children() もしくは fts_read() が構造体 FTSENT を戻すに際し、 fts_info フィールドに FTS_DNR, FTS_ERR, FTS_NS のいずれかが設定された状態の場合は、 fts_errno フィールドは、エラーの原因を示す外部変数 errno の値を含みます。その他の場合、 fts_errno フィールドの内容は未定義です。

fts_number
    このフィールドは、アプリケーションプログラムで 使用するためのもので、 fts 関数群はこのフィールドを変更しません。このフィールドは 0 で初期化されています。

fts_pointer
    このフィールドは、アプリケーションプログラムで使用するためのもので、 fts 関数群はこのフィールドを修正しません。このフィールドは NULL で初期化されています。

fts_parent
    このファイルがメンバとなっているディレクトリのように、現在着目している ファイルのすぐ上の階層にあるファイルを参照する FTSENT 構造体のポインタです。初期エントリポイントの親構造体も提供されますが、 fts_level フィールド、 fts_number フィールド、 fts_pointer フィールドの初期化しか保証されません。

fts_link
    fts_children() 関数から戻ると、 fts_link フィールドは、ディレクトリのメンバを表す、ナル終端されたリンクリスト の中の次の構造体を指します。その他の場合、 fts_link フィールドの内容は未定義です。

fts_cycle
    ディレクトリ 2 つの間のハードリンクや、ディレクトリを指す シンボリックリンクにより、あるディレクトリが階層構造の中で循環の 原因となっている場合 ( FTS_DC 参照)、この構造体の fts_cycle フィールドは、この階層構造の中で、 現在の FTSENT 構造体と同じファイルを参照する FTSENT 構造体を指します。その他の場合、 fts_cycle フィールドの内容は未定義です。

fts_statp
    ファイルの stat(2) の情報を指すポインタです。

ファイル階層にある全ファイルのすべてのパスに対し、1 つのバッファを 使用します。このため、 fts_path フィールドと fts_accpath フィールドは、 NUL終端されている ことが保証されるのは、 fts_read() が最後に戻したファイル のみ です。他の FTSENT 構造体が表すファイルを参照するために、この フィールドを使用するためには、その FTSENT 構造体の fts_pathlen フィールドに含まれる情報でパスバッファを 修正する必要があります。 fts_read() をさらに呼び出す前に、 このような修正を元に戻しておく必要があります。 fts_name フィールドは、常に NUL終端されています。

FTS_OPEN
関数 fts_open() は、横断対象の論理ファイル階層を構成する 1 つ以上のパスを 指定する文字型ポインタの配列を指すポインタを取ります。配列は、 NULL ポインタで終わっている必要があります。

数多くのオプションがありますが、最低でも次のうち 1 つ ( FTS_LOGICAL か FTS_PHYSICAL) を指定する必要があります。オプションは、以下の値の論理和を 取ることで選択されます。

FTS_COMFOLLOW
    このオプションを指定すると、 FTS_LOGICAL が指定されているかどうかに関わらず、ルートパスとして指定された シンボリックリンクがすぐにたどられます。

FTS_LOGICAL
    このオプションを指定すると、 fts ルーチンは、シンボリックリンクそのものではなく、 シンボリックリンクのターゲットの FTSENT 構造体を戻すようになります。このオプションを設定すると、 アプリケーションに戻される FTSENT 構造体が指すシンボリックリンクは、存在しないファイルを 参照するものだけになります。 fts_open() 関数には、 FTS_LOGICAL か FTS_PHYSICAL を指定する必要があります。

FTS_NOCHDIR
    パフォーマンスを最適化するため、 fts 関数は、ファイル階層のアクセス中に カレントディレクトリを変更します。これには、横断中にどのディレクトリ にいるかがアプリケーションで特定できないという副作用があります。 FTS_NOCHDIR オプションはこの最適化を無効にするので、 fts 関数はカレントディレクトリを変更しなくなります。 FTS_NOCHDIR を指定していない、もしくは、 fts_open() に絶対パス名を引数として指定していない場合は、アプリケーションで カレントディレクトリを変更したり、ファイルにアクセスしたり しないでください。

FTS_NOSTAT
    デフォルトでは、戻される FTSENT 構造体は、アクセスしたファイルそれぞれについて ファイル特性情報 ( statp フィールド) を参照しています。このオプションは、パフォーマンスを 最適化するためにこの要件を緩和し、 fts 関数が fts_info フィールドに FTS_NSOK を設定して、 statp フィールドの内容を未定義のままにすることを許可します。

FTS_PHYSICAL
    このオプションを指定すると、 fts ルーチンは、シンボリックリンクが指すターゲットファイルではなく、 シンボリックリンク自体の FTSENT 構造体を戻すようになります。このオプションを設定すると、 階層に存在するすべてのシンボリックリンクの FTSENT 構造体がアプリケーションに戻されます。 fts_open() 関数には、 FTS_LOGICAL か FTS_PHYSICAL を指定する必要があります。

FTS_SEEDOT
    デフォルトでは、 fts_open() のパス引数として指定しない限り、ファイル階層に存在する、 ‘’. もしくは、 ‘..’ という名前のファイルは無視されます。このオプションを指定することにより、 fts ルーチンは、このような ファイルの FTSENT 構造体を戻すようになります。

FTS_XDEV
    このオプションを指定すると、 fts は、下降を始めたファイルと 異なるデバイス番号を持つディレクトリに下降しません。

引数 compar() は、階層横断の順序決めに使用されるユーザ定義関数を 指定します。この関数は、 FTSENT 構造体のポインタを指す 2 つのポインタを 引数として取り、最初の引数が参照するファイルが、2 番目の引数が 参照するファイルより前に来るか、前でも後ろでもどちらでも構わないか、 後ろに来るかによって、それぞれ負の値、ゼロ、正の値を戻さねばなりません。 この比較では、 FTSENT 構造体の fts_accpath, fts_path, fts_pathlen フィールドを 絶対に 使用してはいけません。 fts_info フィールドに FTS_NS か FTS_NSOK が設定されている場合、 fts_statp フィールドも使用してはなりません。 引数 compar() が NULL である場合、ディレクトリ横断順序は、ルートパスでは path_argv でリストされる順序に、その 他すべての場所では、ディレクトリでリストされている順序になります。

FTS_READ
fts_read() 関数は、階層のファイルを表す FTSENT 構造体のポインタを戻します。ディレクトリ (読込み可能で循環の原因とならないもの) は、正順探索時に 1 回と 逆順探索時に 1 回、少なくとも 2 回アクセスされます。 その他すべてのファイルは、最低 1 回アクセスされます。 (ディレクトリ間のハードリンクで循環の原因とならないもの、 またはシンボリックリンクに対するシンボリックリンクは、ファイルの場合、 1 回以上アクセスされる原因となり、ディレクトリの場合、 2 回以上アクセスされたりする原因となることがあります。)

階層のすべてのメンバが戻されると、 fts_read() は NULL を戻し、外部変数 errno に 0 を設定します。階層中のファイルと無関係なエラーが発生すると、 fts_read() は NULL を戻し、 errno に適切な値を設定します。戻されるファイルに 関係するエラーが発生すると、 FTSENT 構造体のポインタが戻され、 errno は設定されたり設定されなかったりします ( fts_info 参照)。

fts_read() が戻す FTSENT 構造体は、同じファイル階層ストリームに対して fts_close() を呼び出した後、もしくは、 その構造体がディレクトリ型ファイルを表していない場合に 同じファイル階層ストリームに対して fts_read() を呼び出した後、上書きされることがあります。 どちらの場合でも、逆順探索の際に fts_read() が FTSENT を返した後に fts_read() を呼び出すまでは、 FTSENT 構造体は上書きされません。

FTS_CHILDREN
関数 fts_children() は、 fts_read() が最近戻した FTSENT 構造体が表す ディレクトリのファイルの NULL で終わるリンクリストの最初のエントリである FTSENT 構造体のポインタを戻します。リストは、 FTSENT 構造体の fts_link フィールドでリンクされ、ユーザ定義比較関数がある場合は、それで 順序付けられます。 fts_children() を繰り返し呼び出すと、このリンクリストは そのたびに再作成されます。

特別な場合として、その階層で fts_read() がまだ呼び出されていない場合、 fts_children() は、 fts_open() に指定された 論理ディレクトリにあるファイル (すなわち、 ftp_open() に指定された引数) を指すポインタを戻します。 fts_read() がすでに呼び出されているときに、 fts_read() が最近戻した FTSENT 構造体が、正順探索でアクセスされたディレクトリでないか、 ディレクトリにファイルが含まれていない場合、 fts_children() は NULL を戻し、 errno にゼロを設定します。エラーが発生すると、 fts_children() は NULL を戻し、 errno に適切な値を設定します。

fts_children() が戻す FTSENT 構造体は、同じファイル階層ストリームを 使用した fts_children(), fts_close(), fts_read() の呼び出しの後、 上書きされることがあります。

option には、以下の値を設定できます。

FTS_NAMEONLY
    ファイルの名前だけが必要であることを示します。戻された構造体の リンクリストに存在するすべてのフィールドの内容は、 fts_name フィールドと fts_namelen フィールドを除いて未定義になります。

FTS_SET
関数 fts_set() により、ストリーム ftsp のファイル f に対して、さらに行なう処理を ユーザアプリケーションが決めることができます。 fts_set() 関数は、問題がなければ 0 を戻し、エラーが発生した場合は -1 を戻します。 option として、以下のうちの 1 つの値を 設定する必要があります。

FTS_AGAIN
    ファイルを再アクセスします。どのようなファイルタイプのファイルも 再アクセスされる可能性があります。その次に fts_read() を呼び出すことで、参照されたファイルが戻されます。そのとき、構造体の fts_stat フィールドと fts_info フィールドが再び初期化されますが、その他のフィールドは変更されません。 このオプションは、 fts_read() が最近戻したファイルに対してのみ意味を持ちます。通常の場合は逆順 ディレクトリアクセスに使用します。この場合はディレクトリが正順と逆順の 両方で再アクセスされ、その子すべても再アクセスされます。

FTS_FOLLOW
    参照するファイルは、シンボリックリンクである必要があります。 参照するファイルが、 fts_read() で最近戻されたものである場合、次に fts_read() を呼び出すと、 fts_info フィールドと fts_statp フィールドが 初期化され、シンボリックリンク自体ではなくシンボリックリンクのターゲットを 指した状態でファイルが戻されます。ファイルが fts_children() で最近戻されたものである場合、構造体の fts_info フィールドと fts_statp フィールドは、 fts_read() で戻されると、シンボリックリンク自体ではなく シンボリックリンクのターゲットを反映します。どちらの場合でも、 シンボリックリンクのターゲットが存在しなければ、戻される構造体のフィールド は変更されず、 fts_info フィールドは FTS_SLNONE に設定されます。

    リンクのターゲットがディレクトリである場合は、正順探索でのリターン、 すべての子孫のリターン、逆順探索のリターンがこの順序で実行されます。

FTS_SKIP
    このファイルの子はアクセスされません。ここで指定するファイルとして、 fts_children() か fts_read() が最近戻したものどちらかが可能です。

FTS_CLOSE
関数 fts_close() は、ファイル階層ストリーム ftsp を閉じ、カレントディレクトリを、 fts_open() を呼び出した時のディレクトリに戻します。 fts_close() 関数は、エラーがなければ 0 を戻し、エラーが発生した場合は -1 を戻します。

エラー
fts_open() 関数の実行が失敗しエラーになると、ライブラリ関数 open(2) と malloc(3) で指定されたエラーが errno に設定されることがあります。

fts_close() 関数がエラーになると、ライブラリ関数 chdir(2) と close(2) が指定したエラーが errno 設定されることがあります。

fts_read() 関数と fts_children() 関数がエラーになると、ライブラリ関数 chdir(2), malloc(3), opendir(3), readdir(3), stat(2) で指定されたエラーが errno に設定されることがあります。

fts_children(), fts_open(), fts_set() がエラーになると、以下のように errno を設定します。

[EINVAL]
    オプションが正しくありません。

関連項目
find(1), chdir(2), stat(2), qsort(3)

規格
fts ユーティリティは、将来、 p1003.1-88 リビジョンに組み込まれると思われます。