coreutils 패키지는 linux의 core utility (대부분 /bin 디렉토리에 위치한 명령들) 들을 담고 있다. 여기에는 cat, chmod, chown, 등등 기본적인 명령어들이 거의 다 포함되어 있다. 그 중 df에 관한 내용을 살펴보자.
이하 디렉토리 경로는 coreutils 소스의 root 경로까지는 생략한다.
coreutils는 자신의 시스템 바이너리들을 위해 libfetish 라는 라이브러리를 생성한다. (해당 소스는 coreutils 디렉토리의 lib/ 폴더에 위치한다.) 실제로 src/df.c 안의 내용에는 참고할만한 사항이 그리 많지가 않다. 핵심적인 부분은 거의 모두 libfetish 에서 해결되기 때문이다.
이 라이브러리 구조는 어떻게 보면 간편한 것이, 음, 생각할 것이 적어진다고 할까. (사실 라이브러리를 사용하지 않는 것이 취향이긴 하나 기본적인 커맨드들이 쓰는 라이브러리고, 사실상 소스코드가 해당 라이브러리에 너무 종속적이라 걷어내기 힘든 감이 있었다.)
df.c의 중심 동작은 show_dev() 함수에서부터 시작한다. get_fs_usage() 함수를 부르는 것 부터 disk 정보를 얻어오는 동작이 시작되고, 해당 함수는 libfetish (lib/fsusage.c) 라이브러리에 포함되어 있다. 그리고, 결국 statfs라는 시스템 콜을 호출한다.
statfs라는 시스템 콜은 statfs라는 mount 된 file system에 대한 정보를 담은 구조체를 되돌리는데, 해당 구조체에 관한 정보는 다음과 같다. (아래 정보는 i386계열의 statfs 정보인것 같고, man페이지를 참고했다. 실제로 get_fs_usage() 함수는 statfs, 혹은 다른 시스템에서의 stat, dustat 등의 시스템 콜에 대한 wrapper 함수로써의 동작을 하고 있다.)
struct statfs {
long f_type; /* type of filesystem (see below) */
long f_bsize; /* optimal transfer block size */
long f_blocks; /* total data blocks in file system */
long f_bfree; /* free blocks in fs */
long f_bavail; /* free blocks avail to non-superuser */
long f_files; /* total file nodes in file system */
long f_ffree; /* free file nodes in fs */
fsid_t f_fsid; /* file system id */
long f_namelen; /* maximum length of filenames */
};
get_fs_usage 함수에서는 이 구조체를 약간 편집하여 리턴하는데, i386에서 처리되는 상황을 보면,