df と ls
以下、昨日のメモです。
coreutils パケジのソースを解凍して色々確認。
df.c
まず df.c から。いっちゃん最後にある main() 関数のさらに最後らへん。
if (optind < argc) { int i; /* Display explicitly requested empty file systems. */ show_listed_fs = true; if (n_valid_args > 0) print_header (); for (i = optind; i < argc; ++i) if (argv[i]) show_entry (argv[i], &stats[i - optind]); } else { print_header (); show_all_entries (); }
通常 df には引数は渡さない、という事で対象は show_all_entries() な関数と見て掘削開始。show_all_entries() 関数の定義が以下。
/* Show all mounted file systems, except perhaps those that are of an unselected type or are empty. */ static void show_all_entries (void) { struct mount_entry *me; for (me = mount_list; me; me = me->me_next) show_dev (me->me_devname, me->me_mountdir, NULL, me->me_type, me->me_dummy, me->me_remote); }
コメント的にもビンゴな模様。がしかし、mount_list って何でしょ、と言いつつ M-t しても知らぬ、と言われます。ちなみに mount_list は df.c にて定義されてます。
/* Linked list of mounted file systems. */ static struct mount_entry *mount_list;
mount_entry 構造体はどこで定義されとるのかいな。include されてるヘッダの名前で適当なのに当たりを付けて find してみたら lib 配下にファイルを発見。lib/mountlist.h にて定義されている mount_entry 構造体の定義は以下。
/* A mount table entry. */ struct mount_entry { char *me_devname; /* Device node name, including "/dev/". */ char *me_mountdir; /* Mount point directory name. */ char *me_type; /* "nfs", "4.2", etc. */ dev_t me_dev; /* Device number of me_mountdir. */ unsigned int me_dummy : 1; /* Nonzero for dummy file systems. */ unsigned int me_remote : 1; /* Nonzero for remote fileystems. */ unsigned int me_type_malloced : 1; /* Nonzero if me_type was malloced. */ struct mount_entry *me_next; };
確かにリストになっとりますな。で、df.c にて mount_entry なリストのどこかのポインタを取得しているのが以下。
mount_list = read_file_system_list ((fs_select_list != NULL || fs_exclude_list != NULL || print_type || show_local_fs));
read_file_system_list() 関数の定義は lib/mountlist.c な模様。以下なコメントが関数定義の直上に記述。
/* Return a list of the currently mounted file systems, or NULL on error. Add each entry to the tail of the list so that they stay in order. If NEED_FS_TYPE is true, ensure that the file system type fields in the returned list are valid. Otherwise, they might not be. */
おそらく mount されたナニを順に列挙するんだろうと踏んで show_all_entries() に戻ってループの中で呼ばれている show_dev() 関数を確認。
この中で fs_usage 構造体なローカル領域に get_fs_usage() という関数を使って情報を取得している模様。
if (get_fs_usage (stat_file, disk, &fsu)) { error (0, errno, "%s", quote (stat_file)); exit_status = EXIT_FAILURE; return; }
この fs_usage な構造体は lib/fsusage.h にて定義。
struct fs_usage { uintmax_t fsu_blocksize; /* Size of a block. */ uintmax_t fsu_blocks; /* Total blocks. */ uintmax_t fsu_bfree; /* Free blocks available to superuser. */ uintmax_t fsu_bavail; /* Free blocks available to non-superuser. */ bool fsu_bavail_top_bit_set; /* 1 if fsu_bavail represents a value < 0. */ uintmax_t fsu_files; /* Total file nodes. */ uintmax_t fsu_ffree; /* Free file nodes. */ };
ブロックサイズとかがあるな。で、get_fs_usage() 関数は fsusage.c にて定義。
int get_fs_usage (char const *file, char const *disk, struct fs_usage *fsp) { #ifdef STAT_STATFS3_OSF1 struct statfs fsd; if (statfs (file, &fsd, sizeof (struct statfs)) != 0) return -1;
statfs() はシステムコールです。df は statfs() を使って情報取得しているという事にします。
ls.c
読みづらい。stat() 読んでるとみて、とりあえず報告。カーネル側を読む方向。