Path: ccsf.homeunix.org!ccsf.homeunix.org!news1.wakwak.com!nf1.xephion.ne.jp!onion.ish.org!honnetnews!navi.honnet.co.jp!news.mcu.or.jp!cyber-magic.org!uinet.or.jp!Q.T.Honey!newsfeed.rim.or.jp!news2.rim.or.jp!dohzono From: dohzono@hf.rim.or.jp (Kazuo Fox DOHZONO) Newsgroups: fj.comp.lang.c Subject: Re: errno and library functions Date: 20 Aug 2004 05:28:32 GMT Organization: RIMNET (Fukuoka Domain) Lines: 81 Message-ID: References: NNTP-Posting-Host: 208.120.113.221.ap.yournet.ne.jp Mime-Version: 1.0 Content-Type: text/plain; charset=iso-2022-jp X-Trace: news2.rim.or.jp 1093118677 50549 221.113.120.208 (21 Aug 2004 20:04:37 GMT) X-Complaints-To: root@rim.or.jp NNTP-Posting-Date: Sat, 21 Aug 2004 20:04:37 +0000 (UTC) In-reply-to: yas@is.tsukuba.ac.jp's message of 28 Jul 2004 12:37:43 GMT Xref: ccsf.homeunix.org fj.comp.lang.c:347 # なんか書くのに体力使う…. In article yas@is.tsukuba.ac.jp (Yasushi Shinjo) writes: > rename() は、BSD 系では、システムコールかなあ。 そうだと思います. > f系のファイルにけっこうあますね。これはだいたいシステムコー > ルと関係していそう 私の感覚では (建前上は) 関係していないことになって います (fopen に owner とかの概念はありませんし). ANSI Rationale にも「どんな C 言語環境でも動作する ことを保証するため UNIX に依存するもの (open など のシステムコール) は省かれた」とありました. > remove() は、本当はライブラリではダメな気がします。unlink() > して失敗したら rmdir() という方法だと、unlink() に失敗した後、 > rmdir() の前に、隙をついて何かやられるとうまくありません。 # 少なくとも FreeBSD は lstat → unlink or rmdir[*]. ## 証明っぽいのも書いたけどとりあえず削除. その「うまく」ない状況というのは, 実は atomic でも 「うまく」ない場合が多いので, 「何かやられる」こと の方を問題とする (攻撃者がファイルを置き換えられる ような構成にしない) のが普通でしょう. # [*]: ネット上で「lstat → unlink の間にファイル # を入れ替えられると任意のファイルを削除してしまう」 # という文章を見ましたが, これは remove のことを言っ # ているのではなくて, 「確かに自分が作成したファイ # ルかどうか」を i-node で見ても駄目だよね, という # 話だと思いました (remove だと仮に atomic な操作 # にしても消えてしまうことは防げないので). > ライブラリ関数(システムコールを伴わないはず)なのに失敗して > errno に値を返すものがありますね。 関数の戻値がその型の範囲をカヴァーしてしまっている ものなど, でしょう. > strtol() とか。これも何か困る気がしたんだけど、 > 忘れました。 滞り無く処理が終了した場合でも errno が 0 になるこ とはない (errno を上書きしてくれない) ということを 知らないと strtol のエラーは拾えません. $ cat strtol_test.c #include #include #include int main (int ac, char **av) { unsigned i; for (i = 1; i < ac; i++) { char *endpos; long l; /* errno = 0; */ l = strtol (av[i], &endpos, 0); if (errno) perror (av[i]); else printf ("%ld %u\n", l, endpos - av[i]); } return 0; } $ cc -o strtol_test strtol_test.c $ ./strtol_test 0xa a 0xa 10 3 a: Invalid argument 0xa: Invalid argument $