カレントディレクトリを消す実験でシェルから実行するとシェルが何をしているかわからないのでopenしているかもしれない。なのでテストプログラムを組んで実験してみた。

koie@guriandgura% df .
Filesystem  1024-blocks   Used  Avail Capacity  Mounted on
/dev/ad4s2a      507630 352518 114502    75%    /
koie@guriandgura% uname -sr
FreeBSD 9.0-CURRENT
koie@guriandgura% cat -n foo.c
     1  #include <stdio.h>
     2  #include <sys/types.h>
     3  #include <dirent.h>
     4  #include <sys/stat.h>
     5
     6  static void
     7  ls_file(const char* path)
     8  {
     9      struct stat st;
    10      lstat(path, &st);
    11      printf("%-10s ino=%ld nlink=%ld\n", path, st.st_ino, st.st_nlink);
    12  }
    13
    14  static void
    15  ls_dir(const char* path)
    16  {
    17      DIR* dp = opendir(path);
    18      if (dp == NULL) {
    19          perror("opendir");
    20          return;
    21      }
    22      printf("ls %s {\n", path);
    23      struct dirent *dep;
    24      while ((dep = readdir(dp)) != NULL) {
    25          char fn[100];
    26          snprintf(fn, sizeof fn, "%s/%s", path, dep->d_name);
    27          ls_file(fn);
    28      }
    29      closedir(dp);
    30      printf("}\n");
    31  }
    32
    33  int
    34  main()
    35  {
    36      int rc;
    37      if (mkdir("d", 0777) < 0) {
    38          perror("mkdir");
    39          return 1;
    40      }
    41      if (chdir("d") < 0) {
    42          perror("chdir");
    43          return 1;
    44      }
    45      ls_dir(".");
    46      if (rmdir(".", 0777) < 0) {
    47          perror("rmdir");
    48          printf("keep going.\n");
    49      }
    50      if (rmdir("../d", 0777) < 0) {
    51          perror("rmdir");
    52          return 1;
    53      }
    54      ls_dir(".");
    55      ls_file(".");
    56      return 0;
    57  }
koie@guriandgura% cc foo.c
koie@guriandgura% ./a.out
ls . {
./.        ino=33552 nlink=2
./..       ino=33544 nlink=3
}
rmdir: Invalid argument
keep going.
ls . {
}
.          ino=33552 nlink=0
koie@guriandgura%
$ uname -sr
Linux 2.6.18-194.32.1.el5
$ cc foo.c
$ uname -sr
Linux 2.6.18-194.32.1.el5
$ ./a.out
ls . {
./..       ino=64225281 nlink=4
./.        ino=64225284 nlink=2
}
rmdir: Invalid argument
keep going.
ls . {
}
.          ino=64225284 nlink=0
$

この結果からすると、ディレクトリのデータ部分(つまりディレクトリエントリ)は消えているが、ディレクトリ自身(=ディレクトリのメタデータ=inode)は消えてなくて、おそらくlookupで"."が特別扱いされいるためにディレクトリエントリを参照することなくカレントディレクトリを返しているのではないだろうか。

#正直なところおっさんにはカーネルソースを読む気力はすでにない。