【コードリーディング】cdコマンドって一体何なのさ?
みなさん、「cd」コマンドって具体的になにやってるか分かりますか?
ぼくはわかりません!!!
……というわけでソースを読んでみます。
※FreeBSDのshの中の"cd.c"を読みます。
bin/sh/cd.c
ざっくりと読む
エントリポイントは「cdcmd」関数と思われるので、そこから徐々に下っていきます。
- cdcmd ※エントリポイント、引数のパース
どうやら「cdlogical」と「cdphysical」がキモのようです。
辿ってみると、変数「pflag」の値によってどちらを呼び出すのか変わるみたいですが、中身はだいたい似ている感じなので一旦この違いは無視します。
続いて、
- chdir(2)
- updatepwd
の中身を見ていきます。
chdir(2)
とりあえず man 2 chdir します。
CHDIR(2) FreeBSD System Calls Manual CHDIR(2) NAME chdir, fchdir -- change current working directory LIBRARY Standard C Library (libc, -lc) SYNOPSIS #include <unistd.h> int chdir(const char *path); int fchdir(int fd);
chdir(2) の定義は unistd.h にあるようです。
で、実装箇所をgrepで探してみたのですが、どうやら実体は sys/kern/vfs_syscalls.c の kern_chdir にあるような感じでした。
読んでみましたが具体的に何をやっているのかは正直良くわかりませんorz
/* * Change current working directory (``.''). */ #ifndef _SYS_SYSPROTO_H_ struct chdir_args { char *path; }; #endif int sys_chdir(td, uap) struct thread *td; struct chdir_args /* { char *path; } */ *uap; { return (kern_chdir(td, uap->path, UIO_USERSPACE)); } int kern_chdir(struct thread *td, char *path, enum uio_seg pathseg) { struct nameidata nd; int error; NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF | AUDITVNODE1, pathseg, path, td); if ((error = namei(&nd)) != 0) return (error); if ((error = change_dir(nd.ni_vp, td)) != 0) { vput(nd.ni_vp); NDFREE(&nd, NDF_ONLY_PNBUF); return (error); } VOP_UNLOCK(nd.ni_vp, 0); NDFREE(&nd, NDF_ONLY_PNBUF); pwd_chdir(td, nd.ni_vp); return (0); } /* * Change notion of root (``/'') directory. */ #ifndef _SYS_SYSPROTO_H_ struct chroot_args { char *path; }; #endif
updatepwd
※該当箇所抜き出し
/* * Update curdir (the name of the current directory) in response to a * cd command. We also call hashcd to let the routines in exec.c know * that the current directory has changed. */ static void updatepwd(char *dir) { char *prevdir; hashcd(); /* update command hash table */ setvar("PWD", dir, VEXPORT); setvar("OLDPWD", curdir, VEXPORT); prevdir = curdir; curdir = dir ? savestr(dir) : NULL; ckfree(prevdir); }
やっていることは