トップ «前の日記(2014-05-19) 最新 次の日記(2014-05-21)» 編集

ヨタの日々

2001|08|09|10|11|12|
2002|01|02|03|04|05|06|07|08|09|10|11|12|
2003|01|02|03|04|05|06|07|08|09|10|11|12|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|08|09|10|11|12|
2020|01|02|03|04|05|06|07|08|09|10|11|12|
2021|01|02|03|04|05|06|07|08|09|10|11|12|
2022|01|02|03|04|05|06|07|08|09|10|11|12|
2023|01|02|03|04|05|06|07|08|12|
2024|01|02|03|04|05|06|07|08|09|10|11|

2014-05-20 :-(

_ 午前

0530 起床

0700 食堂

0830 出勤 && デバッグしTARI

_ 午後

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)