2014-05-20 :-(
_ 午後
1300 デバッグしTARI
_ 夜
1700 残業アワー
2100 退勤 || ここんとこ無駄な時間が多いような || 以前は 17 時に退勤しないといけなかったから、どうすれば 17 時までに仕事を完了できるか、如何にして無駄をなくすか、ということに腐心していたんだが、最近の仕事場は【禁則事項です】なのでつい無制限に
2200 飯
_ [NetBSD][cat][コードリーディング]NetBSD /bin/cat を読む
src/bin/cat/cat.c
オプションなしで呼び出した場合を読む。
% cat file1 file2 file3
関数はこう呼ばれる
main raw_args raw_cat
main を読む。
(void)setlocale(LC_ALL, "");
マニュアルによると、"" を指定しているので環境変数 LC_ALL が使われる。
setlocale - NetBSD Manual Pages
Only three locales are defined by default, the empty string "" which
denotes the native environment, and the "C" and "POSIX" locales, which
denote the C language environment.
オプションを与えてないのでここは raw_args へ行く。
if (bflag || eflag || nflag || sflag || tflag || vflag)
cook_args(argv);
else
raw_args(argv);
raw_args を読む。
全体が do while で囲まれている。
do {
:
} while (*argv);
argv には /bin/cat に渡された引数が入る。つまりファイル 1 つ以上である。ファイル 1 つ以上をすべて do while で処理する。
ファイルディスクリプタ fd に初期値設定。デフォルトでは標準入力。stdin はたぶん unistd.h で定義されてる。マニュアル stdin - NetBSD Manual Pages によると定数 STDIN_FILENO などらしいんだが。
fd = fileno(stdin); filename = "stdin";
条件分岐はここを通る。ようはファイルを open している。
else if ((fd = open(*argv, O_RDONLY, 0)) < 0) {
skip:
warn("%s", *argv);
skipnomsg:
rval = EXIT_FAILURE;
++argv;
continue;
}
open が返したファイルディスクリプタを raw_cat へ渡す。
raw_cat(fd);
raw_cat を読む。短いので関数を全部。ファイルから読んで標準出力 stdout へ書き出す。
void
raw_cat(int rfd)
{
static char *buf;
static char fb_buf[BUFSIZ];
static size_t bsize;
ssize_t nr, nw, off;
int wfd;
wfd = fileno(stdout);
// /bin/cat に渡されたファイル 1 つ以上を処理するので、buf は static であり最初だけ NULL チェックする
if (buf == NULL) {
struct stat sbuf;
// ファイルサイズを取得する
if (fstat(wfd, &sbuf) == 0 &&
sbuf.st_blksize > sizeof(fb_buf)) {
bsize = sbuf.st_blksize;
buf = malloc(bsize);
}
if (buf == NULL) {
bsize = sizeof(fb_buf);
buf = fb_buf;
}
}
// 1 回の read で読みこみ完了するとは限らないのでループを回す
while ((nr = read(rfd, buf, bsize)) > 0)
// さらに write も 1 回で完了するとは限らないのでループする
for (off = 0; nr; nr -= nw, off += nw)
if ((nw = write(wfd, buf + off, (size_t)nr)) < 0)
err(EXIT_FAILURE, "stdout");
if (nr < 0) {
warn("%s", filename);
rval = EXIT_FAILURE;
}
}
read はマニュアルにベストプラクティスが書いてある read - NetBSD Manual Pages 面倒くさい。
Error checks should explicitly test for -1. Code such as
while ((nr = read(fd, buf, sizeof(buf))) > 0)
is not maximally portable, as some platforms allow for nbytes to range
between SSIZE_MAX and SIZE_MAX - 2, in which case the return value of an
error-free read() may appear as a negative number distinct from -1.
Proper loops should use
while ((nr = read(fd, buf, sizeof(buf))) != -1 && nr != 0)
write(2) も当然ある write(2) - NetBSD Manual Pages
Error checks should explicitly test for -1. Code such as
while ((nr = write(fd, buf, sizeof(buf))) > 0)
is not maximally portable, as some platforms allow for nbytes to range
between SSIZE_MAX and SIZE_MAX - 2, in which case the return value of an
error-free write() may appear as a negative number distinct from -1.
Proper loops should use
while ((nr = write(fd, buf, sizeof(buf))) != -1 && nr != 0)



