pwdってなんですか?

この記事を書いた背景

他人「pwdってなんですか?」

自分「pwdはカレントディレクトリを調べるコマンドです。」

他人「どうやってそれを調べてるんですか?」

自分「あう…」

あれから数年を経て、その質問に少しだけ答える事ができるようになったという話です。

対象読者

とりあえず、次の事を知ってる人は、もうこれを「読まなくて良い」です。

調べてみよう

しらべてみた結果、こうやればpwdっぽい事ができるようだ

書いてみよう

ディレクトリ一覧が欲しい

うーんPerlのopendirはiノードの番号が取得できないみたいなので(覚えたての)C言語で書いてみよう

% vi test_opendir.c
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>

int main ()
{
    DIR *dir_ptr;
    struct dirent *direntp;

    dir_ptr = opendir(".");
    if( dir_ptr == NULL ) {
        perror( "." );
        exit(1);
    }

    while( ( direntp = readdir( dir_ptr ) ) != NULL ) {
        printf("%d %s\n", direntp->d_ino, direntp->d_name);
    }

    closedir( dir_ptr );
    exit(0);
}
% gcc -Wall -o test_opendir test_opendir.c
% ./test_opendir

カレントディレクトリのiノードと親ディレクトリのiノードを調べる

% vi test_stat.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>

ino_t get_inode( char *fname );

int main ()
{
    ino_t   my_inode;
    ino_t   p_inode;

    my_inode = get_inode( "." );
    p_inode  = get_inode( ".." );

    printf( "%d\n", my_inode);
    printf( "%d\n", p_inode);

    exit(0);
}

ino_t get_inode( char *fname )
{
    struct stat info;

    if ( stat(fname, &info ) == -1 ) {
        fprintf( stderr, "Cannot stat ");
        perror(fname);
        exit(1);
    }
    return info.st_ino;
}
% gcc -Wall -o test_stat test_stat.c
% ./test_stat
ディレクトリ移動

chdirつかえばいけるんじゃないかな*1

結論

上記の方法を組み合わせれば、なんとなくpwdっぽいことができると思います。ひまがあれば実装してみようと思います。

そういうわけで、こんどから「pwdって何ですか?」と聞かれた時には

「カレントディレクトリのiノードと親ディレクトリのiノードを調べ、一致するまで親ディレクトリをさかのぼります。またiノードからディレクトリへをオープンし、ディレクトリの構造体一覧を取得できるので、ひとつ下のディレクトリの名前をiノードから調べる事ができるので、親ディレクトリまで遡る過程でこれらを記憶しておき、親ディレクトリまで走査した後に、それまでに発見したディレクトリ名をつなげてに標準出力に書き込みます。」

と答える事ができます。あってるかな?*2

*1:コード書くの飽きてしまったという

*2:まだマウントの概念を考慮してないので実際のpwdとは違ってますがご容赦下さい