カレントディレクトリを消す実験でシェルから実行するとシェルが何をしているかわからないので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で"."が特別扱いされいるためにディレクトリエントリを参照することなくカレントディレクトリを返しているのではないだろうか。
#正直なところおっさんにはカーネルソースを読む気力はすでにない。