MacOS Xのtelldir/seekdir

MacOS Xのtelldir(3), seekdir(3)の挙動がちょっと面白かった。

今、ls -lするとこうなるディレクトリにいるとしよう。

total 40
drwxr-xr-x   2 yugui  yugui     68  9  7 22:16 1.d/
drwxr-xr-x   2 yugui  yugui     68  9  7 22:16 2.d/
drwxr-xr-x   2 yugui  yugui     68  9  7 22:16 3.d/
drwxr-xr-x   2 yugui  yugui     68  9  7 22:16 4.d/
-rwxr-xr-x   1 yugui  yugui  13484  9 10 21:51 test*
-rw-r--r--   1 yugui  yugui    537  9 10 21:51 test.c

ここで、こんなプログラムを動かしてみる。

#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>

int main(void)
{
    DIR *dp;
    struct dirent *pent;

    dp = opendir(".");
    printf("%ld\n", telldir(dp));
    printf("%ld\n", telldir(dp));
    printf("%ld\n", telldir(dp));
    printf("%ld\n", telldir(dp));
    seekdir(dp, telldir(dp));
    puts("---");
    while ( (pent = readdir(dp)) != NULL )
      {
        printf("%ld: %s\n", telldir(dp), pent->d_name);
        telldir(dp);
        telldir(dp);
        telldir(dp);
        telldir(dp);
        seekdir(dp, telldir(dp)-5);
      }
    return 0;
}

要は無用にtelldirしてるだけ。結果はこうなる。

1
2
3
4
---
6: .
12: ..
18: 1.d
24: 2.d
30: 3.d
36: 4.d
42: test
48: test.c
  • telldirすると毎度ディレクトリストリームのカウンタが進む。
  • 別に最後に呼んだときのカウンタ値以外をseekdirに渡してもOKみたい。

WindowsでMSVCRTとか、Linuxとかだとtelldirは何度呼んでも次にreaddirするまで同じ値を返し続けるんだけど。その感覚からするとtelldirでカウンタが進むのはちょっと驚き。BSD系ってこういうもの? それとも、HFS+の仕様?

manに書いてある通りに使えば問題はない。けれども、manを無視して「どうせオフセット値」とか思って悪いことをすると嵌りそうだ。大昔の、struct direntが実際には配列の要素だったころとは随分違うんだね。