AIX 上での readdir_r は戻り値が若干違う2012年02月10日 20時41分28秒

他のシステムでは問題なく動いているのだが、AIX でのみ問題が起きる現象があったので調べた。AIX では全てのディレクトリを読み終わった時に、readdir_r が 9 を返すのが原因だった。

以下の様に、戻り値が 0 でない時に、処理を中断するようにしてあった。目的のファイルが存在するかを調べるため、ディレクトリを調べているコードだった。


    struct dirent* ent;
    ret = readdir_r(path, (struct dirent*)buf, &ent);

    if (ret != 0)
        return false;

そこで、愚直に直せば以下の形になる。

    struct dirent* ent;
    ret = readdir_r(path, (struct dirent*)buf, &ent);

#ifdef _AIX
    if (ret != 0 || ret != 9)
#else
    if (ret != 0)
#endif
        return false;

readdir_ も他のシステムコールや多々の標準関数の様に errno を設定する。各種システムの man readdir_r を読み比べると、どのシステムでも、正しく読めた場合は第三引数にポインタを設定するらしい。そして、ファイルの終端に付いたときは、AIX を含めてエラーではないため、errno を変更せず、そして、第三引数に NULL を設定するらしい。そこで、errno を調べれば、AIX の 9 の点検が必要なくなる。


    struct dirent* ent;
    errno = 0;
    ret = readdir_r(path, (struct dirent*)buf, &ent);

    if(errno != 0 && env == NULL)
        return false;

上記の例では、一応 env も調べるようにしている。

以下、 AIX の man readdir_r より抜粋。

Return Values
0 Indicates that the subroutine was successful.
9 Indicates that the subroutine was not successful or that the end of the directory was reached. If the user has set the environment variable XPG_SUS_ENV=ON prior to execution of the process, then the SIGXFSZ signal is posted to the process when exceeding the process' file size limit, and the subroutine will always be successful.

Error Codes
If the readdir_r subroutine is unsuccessful, the errno global variable is set to one of the following values: