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); }