C言語入門(28) 実際にプログラムを読んで理解を深めよう ls編(2)

Posted: 2013年02月21日

前回は、main関数を解説してきました。
main関数では、コマンドの引数解析を主に行って来ましたが
今回はmain関数が最後に処理を行うtraverseを解説していきます。

ls.c traverse関数です。

プログラムプログラム:

    /* Terminal defaults to -Cq, non-terminal defaults to -1. */
    FTS *ftsp;
    FTSENT *p, *chp;
    int ch_options;

    if ((ftsp =
        fts_open(argv, options, f_nosort ? NULL : mastercmp)) == NULL)
        err(1, "fts_open");

    /*
     * We ignore errors from fts_children here since they will be
     * replicated and signalled on the next call to fts_read() below.
     */
    chp = fts_children(ftsp, 0);
    if (chp != NULL)
        display(NULL, chp, options);
    if (f_listdir)
        return;

解説解説:

fts_openでディレクトリの改装を取得するハンドルを取得します。
argvの先頭に設定されているかれんドディレクトリのパスを設定
ほかは、main関数で解釈した引数のフラグを設定しています。

fts_childrenでopenしたディレクトリのファイルリストを取得しています。

プログラムプログラム:

    while ((p = fts_read(ftsp)) != NULL)
        switch (p->fts_info) {
        case FTS_DC:
            warnx("%s: directory causes a cycle", p->fts_name);
            break;
        case FTS_DNR:
        case FTS_ERR:
            warnx("%s: %s", p->fts_path, strerror(p->fts_errno));
            rval = 1;
            break;
        case FTS_D:
            if (p->fts_level != FTS_ROOTLEVEL &&
                p->fts_name[0] == '.' && !f_listdot)
                break;

            /*
             * If already output something, put out a newline as
             * a separator.  If multiple arguments, precede each
             * directory with its name.
             */
            if (output) {
                putchar('n');
                (void)printname(p->fts_path);
                puts(":");
            } else if (argc > 1) {
                (void)printname(p->fts_path);
                puts(":");
                output = 1;
            }
            chp = fts_children(ftsp, ch_options);
            display(p, chp, options);

            if (!f_recursive && chp != NULL)
                (void)fts_set(ftsp, p, FTS_SKIP);
            break;
        default:
            break;
        }

解説解説:

fts_readでディレクトリを一つづつ処理します。
取得したディレクトリ情報を用いて処理を分けます。

FTS_DC,DNR,ERRは対象外
FTS_Dは正常な処理を表します。
printnameでパスを表示します。
fts_childrenを呼び出し次のディレクトリへ移動します。
f_recursiveがサブディレクトリのチェック処理フラグであり
 チェックされている且つディレクトリの場合は、そのディレクトリ内に移動し処理を続けます。
つまりftp_setでfts_childrenで移動したディレクトリを元に戻します。

display関数で対象ディレクトリ内のファイルなどの情報を表示しています。
この関数については次回書いていきます。

カテゴリー: プログラム, 入門 | タグ: , , | コメント無し »

コメント