2014-05-29 :-(
_ 午後
1300 lint祭り
_ [NetBSD][/bin/ln][ln][コードリーディング]NetBSD /bin/ln を読む
ソース src/bin/ln/ln.c
使用例
ln -s src dst
流れ
main linkit link または symlink
コード読む
main の外にグローバル変数が宣言されている。関数ポインタへの変数
static int (*linkf)(const char *, const char *);
main() はこう。
-s した場合は symlink を設定し、そうでなければ link を使う。
if (sflag) {
linkf = symlink;
linkch = '-';
} else {
linkf = link;
linkch = '=';
}
dst がディレクトリでなければここを通っておしまい。
switch(argc) {
case 0:
usage();
/* NOTREACHED */
case 1: /* ln target */
exit(linkit(argv[0], ".", 1));
/* NOTREACHED */
// ln -s src dst だとここを通る
case 2: /* ln target source */
exit(linkit(argv[0], argv[1], 0));
/* NOTREACHED */
}
linkit() を読む
lstat してファイル存在有無確認してるらしい lstat - NetBSD Manual Pages lstat の戻り値は以下のとおり。正常なら 0 、そうでないなら -1 が返る。
RETURN VALUES
The stat(), lstat(), fstat(), and fstatat() functions return the value 0
if successful; otherwise the value -1 is returned and the global variable
errno is set to indicate the error.
というわけで
// 正常ならば exists は 1 になる
exists = !lstat(source, &sb);
// ln -f src dst と呼ばれたら以下が通る
// 一度 unlink つまり削除しているらしい。えー
/*
* If the file exists, then unlink it forcibly if -f was specified
* and interactively if -i was specified.
*/
if (fflag && exists) {
if (unlink(source)) {
warn("%s", source);
return (1);
}
最後に linkf で link または symlink を呼び出す。
/* Attempt the link. */
if ((*linkf)(target, source)) {
warn("%s", source);
return (1);
}
[ツッコミを入れる]









