From: WATANABE Tetsuya Date: 2002-09-30T11:51:49+09:00 Subject: [ruby-dev:18419] Re: rubicon on EWS4800 渡辺哲也です。 完全に出遅れていますが... HP-UX 関係で STDIO の挙動から添付しているパッチを常用 しています(テストを含めて)。 一連の流れを読めていないのですが、とりあえずおしらせ しておきます。 # もっとちゃんとまとめてからと思ったのですが... ruby-dev に流れていたテストのためのスクリプトなどは、 このパッチで問題がでないことを確認しました(抜けがある かも...)。 In message "[ruby-dev:18322] Re: rubicon on EWS4800" on 02/09/21, Koji Arai さん writes: |新井です。 |これは、EWS4800 でのstdioの挙動がそうなるようです。C で書い |ても同様になりました。man には、 | | ファイルが更新モードでオープンされると、その stream 上では入 | 力 も 出 力 も 両 方 行 うことができます。ただし、入力の後に | fflush(3S) や fseek(3S) あるいは fsetpos(3S) や rewind(3S) | を 介 在 さ せ ず に 直接出力を続けたり、出力の後に fseek や | fsetpos あるいは rewind を介在させずに直接入力を続けたり、あ | るいはエンド・オブ・ファイルを検出する入力操作なしに出力の後 | に直接入力を続けたりすることはできません。 | |っとあるので、このせいかも。仕方ないですね。 このパッチのよろしくないところは、fseek のエラー処理 (エラーになるか確認したかったため)と「struct OpenFile の mode」の bit を増やしているところです。 ------------------------------ --- io.c.org Wed Sep 25 18:40:20 2002 +++ io.c Mon Sep 30 11:09:18 2002 @@ -294,6 +294,20 @@ rb_io_check_writable(fptr); f = GetWriteFile(fptr); +#ifdef OLD_STDIO_RW + if (fptr->mode & FMODE_READABLE && + fptr->mode & FMODE_WRITABLE && + fptr->f2 == NULL) { + if (fptr->mode & FMODE_RW_STATE_R) { + if (fseeko(fptr->f, 0, 1) == -1) { + rb_sys_fail(fptr->path); + } + fptr->mode ^= FMODE_RW_STATE_R; + } + fptr->mode |= FMODE_RW_STATE_W; + } +#endif + ptr = RSTRING(str)->ptr; n = RSTRING(str)->len; do { @@ -377,6 +391,14 @@ off_t pos; GetOpenFile(io, fptr); +#ifdef OLD_STDIO_RW + if (fptr->mode & FMODE_READABLE && + fptr->mode & FMODE_WRITABLE && + fptr->f2 == NULL) { + fptr->mode &= ~FMODE_RW_STATE_R; + fptr->mode &= ~FMODE_RW_STATE_W; + } +#endif pos = ftello(fptr->f); if (ferror(fptr->f)) rb_sys_fail(fptr->path); return OFFT2NUM(pos); @@ -397,6 +419,14 @@ off_t pos; GetOpenFile(io, fptr); +#ifdef OLD_STDIO_RW + if (fptr->mode & FMODE_READABLE && + fptr->mode & FMODE_WRITABLE && + fptr->f2 == NULL) { + fptr->mode &= ~FMODE_RW_STATE_R; + fptr->mode &= ~FMODE_RW_STATE_W; + } +#endif pos = fseeko(fptr->f, NUM2OFFT(offset), whence); if (pos != 0) rb_sys_fail(fptr->path); clearerr(fptr->f); @@ -428,6 +458,14 @@ off_t pos; GetOpenFile(io, fptr); +#ifdef OLD_STDIO_RW + if (fptr->mode & FMODE_READABLE && + fptr->mode & FMODE_WRITABLE && + fptr->f2 == NULL) { + fptr->mode &= ~FMODE_RW_STATE_R; + fptr->mode &= ~FMODE_RW_STATE_W; + } +#endif pos = fseeko(fptr->f, NUM2OFFT(offset), SEEK_SET); if (pos != 0) rb_sys_fail(fptr->path); clearerr(fptr->f); @@ -442,6 +480,14 @@ OpenFile *fptr; GetOpenFile(io, fptr); +#ifdef OLD_STDIO_RW + if (fptr->mode & FMODE_READABLE && + fptr->mode & FMODE_WRITABLE && + fptr->f2 == NULL) { + fptr->mode &= ~FMODE_RW_STATE_R; + fptr->mode &= ~FMODE_RW_STATE_W; + } +#endif if (fseeko(fptr->f, 0L, 0) != 0) rb_sys_fail(fptr->path); clearerr(fptr->f); if (io == current_file) { @@ -702,6 +748,19 @@ READ_CHECK(fptr->f); if (!siz) siz = BUFSIZ; str = rb_tainted_str_new(0, siz); +#ifdef OLD_STDIO_RW + if (fptr->mode & FMODE_READABLE && + fptr->mode & FMODE_WRITABLE && + fptr->f2 == NULL) { + if (fptr->mode & FMODE_RW_STATE_W) { + if (fseeko(fptr->f, 0, 1) == -1) { + rb_sys_fail(fptr->path); + } + fptr->mode ^= FMODE_RW_STATE_W; + } + fptr->mode |= FMODE_RW_STATE_R; + } +#endif pos = ftello(fptr->f); for (;;) { n = rb_io_fread(RSTRING(str)->ptr+bytes, siz-bytes, fptr->f); @@ -735,6 +794,19 @@ GetOpenFile(io, fptr); rb_io_check_readable(fptr); +#ifdef OLD_STDIO_RW + if (fptr->mode & FMODE_READABLE && + fptr->mode & FMODE_WRITABLE && + fptr->f2 == NULL) { + if (fptr->mode & FMODE_RW_STATE_W) { + if (fseeko(fptr->f, 0, 1) == -1) { + rb_sys_fail(fptr->path); + } + fptr->mode ^= FMODE_RW_STATE_W; + } + fptr->mode |= FMODE_RW_STATE_R; + } +#endif if (NIL_P(length)) { return read_all(fptr, remain_size(fptr)); } @@ -776,6 +848,20 @@ int cnt; #endif +#ifdef OLD_STDIO_RW + if (fptr->mode & FMODE_READABLE && + fptr->mode & FMODE_WRITABLE && + fptr->f2 == NULL) { + if (fptr->mode & FMODE_RW_STATE_W) { + if (fseeko(fptr->f, 0, 1) == -1) { + rb_sys_fail(fptr->path); + } + fptr->mode ^= FMODE_RW_STATE_W; + } + fptr->mode |= FMODE_RW_STATE_R; + } +#endif + do { #ifdef READ_DATA_PENDING_PTR long pending = READ_DATA_PENDING_COUNT(f); @@ -863,6 +949,20 @@ FILE *f = fptr->f; int c; +#ifdef OLD_STDIO_RW + if (fptr->mode & FMODE_READABLE && + fptr->mode & FMODE_WRITABLE && + fptr->f2 == NULL) { + if (fptr->mode & FMODE_RW_STATE_W) { + if (fseeko(fptr->f, 0, 1) == -1) { + rb_sys_fail(fptr->path); + } + fptr->mode ^= FMODE_RW_STATE_W; + } + fptr->mode |= FMODE_RW_STATE_R; + } +#endif + do { #ifdef READ_DATA_PENDING_PTR long cnt; @@ -1124,6 +1224,19 @@ GetOpenFile(io, fptr); rb_io_check_readable(fptr); +#ifdef OLD_STDIO_RW + if (fptr->mode & FMODE_READABLE && + fptr->mode & FMODE_WRITABLE && + fptr->f2 == NULL) { + if (fptr->mode & FMODE_RW_STATE_W) { + if (fseeko(fptr->f, 0, 1) == -1) { + rb_sys_fail(fptr->path); + } + fptr->mode ^= FMODE_RW_STATE_W; + } + fptr->mode |= FMODE_RW_STATE_R; + } +#endif f = fptr->f; for (;;) { @@ -1154,6 +1267,19 @@ GetOpenFile(io, fptr); rb_io_check_readable(fptr); +#ifdef OLD_STDIO_RW + if (fptr->mode & FMODE_READABLE && + fptr->mode & FMODE_WRITABLE && + fptr->f2 == NULL) { + if (fptr->mode & FMODE_RW_STATE_W) { + if (fseeko(fptr->f, 0, 1) == -1) { + rb_sys_fail(fptr->path); + } + fptr->mode ^= FMODE_RW_STATE_W; + } + fptr->mode |= FMODE_RW_STATE_R; + } +#endif f = fptr->f; retry: --- rubyio.h.org Fri Aug 16 14:43:14 2002 +++ rubyio.h Mon Sep 30 11:09:18 2002 @@ -32,6 +32,10 @@ #define FMODE_BINMODE 4 #define FMODE_SYNC 8 #define FMODE_WBUF 16 +#ifdef OLD_STDIO_RW +#define FMODE_RW_STATE_R 32 +#define FMODE_RW_STATE_W 64 +#endif #define GetOpenFile(obj,fp) rb_io_check_closed((fp) = RFILE(rb_io_taint_check(obj))->fptr) ------------------------------