[ruby-dev:19308] Re: [BUG] errno == 0
From:
nobu.nakada@...
Date:
2003-01-05 16:48:32 UTC
List:
ruby-dev #19308
なかだです。
At Sun, 5 Jan 2003 19:01:51 +0900,
U.Nakamura <usa@osb.att.ne.jp> wrote:
> > > bccwin32はfflush()では救えなかったので対処してません。
> > > fseek(fp, SEEK_CUR, 0)はOKっぽいので、下記のパッチのような方
> > > 法でこの問題自体は潰せますが、なんか他にもいろいろありそうな
> > > 感じだったので深く踏み込んではいません。
> >
> > そもそもR/Wの切り替えのときには、fflushではなくてfseekしたほう
> > がいいような気がして来ました。
>
> Cの規格によると、WからRはfflushでもいいけどRからWはfseek(か
> その類)じゃないといけないとなってるので、fseekの方が無難だろ
> うと思います。bccのような例もあるし。
元々fseekを使えばいいはずというのが頭にあったんですが、なぜか途
中でfflushに化けてしまったようです。
> ところで、1.6はどうしましょう?
> [ruby-dev:18439]にパッチはあるのですが、commitされてないのは
> なんででしたっけ?
忘れてました。パッチは作り直しました。
Index: configure.in
===================================================================
RCS file: /cvs/ruby/src/ruby/configure.in,v
retrieving revision 1.68.2.41
diff -u -2 -p -r1.68.2.41 configure.in
--- configure.in 31 Dec 2002 11:24:47 -0000 1.68.2.41
+++ configure.in 5 Jan 2003 16:07:24 -0000
@@ -243,8 +243,12 @@ human*) ac_cv_func_getpgrp_void=yes;;
beos*) ;;
cygwin*) rb_cv_have_daylight=no
+ rb_cv_need_io_seek_between_rw=no
+ rb_cv_need_io_flush_before_seek=no
ac_cv_var_tzname=no
ac_cv_func_setitimer=no
;;
mingw*) LIBS="-lwsock32 -lmsvcrt $LIBS"
+ rb_cv_need_io_seek_between_rw=yes
+ rb_cv_need_io_flush_before_seek=no
ac_cv_header_a_out_h=no
ac_cv_header_pwd_h=no
@@ -457,4 +461,62 @@ else
fi
+AC_DEFUN(RUBY_CHECK_IO_NEED,
+[AC_CACHE_CHECK(whether need to [$1], [$2],
+ [AC_TRY_RUN([
+#include <stdio.h>
+#ifndef SEEK_SET
+#define SEEK_SET 0
+#endif
+#ifndef SEEK_CUR
+#define SEEK_CUR 1
+#endif
+#define before_seek(f) ]ifelse(index($2,flush_before_seek),-1,[fflush(f)],[(f,0)])[
+#define reset_rw(f) ]ifelse(index($2,seek_between_rw),-1,[do_seek(f,SEEK_CUR)],[(f,0)])[
+#define do_seek(f, w) (before_seek(f), fseek(f,0,w))
+
+char *fn = "conftest.dat";
+char *wombat = "wombat\n";
+char *koara = "koara\n";
+
+int main()
+{
+ char buf[BUFSIZ];
+ FILE *f;
+ int r = 1;
+
+ if (!(f = fopen(fn, "w+"))) return 1;
+ fputs(wombat, f);
+ do_seek(f, SEEK_SET);
+ if (!fgets(buf, BUFSIZ, f) || strcmp(buf, wombat)) goto fail;
+ reset_rw(f);
+ fputs(koara, f);
+ do_seek(f, SEEK_SET);
+ if (!fgets(buf, BUFSIZ, f) || strcmp(buf, wombat)) goto fail;
+ if (!fgets(buf, BUFSIZ, f) || strcmp(buf, koara)) goto fail;
+ r = 0;
+ fail:
+ fclose(f);
+ unlink(fn);
+ return r;
+}
+], [$2]=no, [$2]=yes, [$2]=yes)])])
+RUBY_CHECK_IO_NEED(seek between R/W, rb_cv_need_io_seek_between_rw)
+RUBY_CHECK_IO_NEED(flush before seek, rb_cv_need_io_flush_before_seek)
+check_do_something_else=no
+if test "$rb_cv_need_io_seek_between_rw" = yes; then
+ AC_DEFINE(NEED_IO_SEEK_BETWEEN_RW, 1)
+ check_do_something_else=yes
+fi
+if test "$rb_cv_need_io_flush_before_seek" = yes; then
+ AC_DEFINE(NEED_IO_FLUSH_BEFORE_SEEK, 1)
+ check_do_something_else=yes
+fi
+if test "$cross_compiling" = no -a "$check_do_something_else" = yes; then
+ RUBY_CHECK_IO_NEED(do something else, unexpected_stdio_behavior)
+ if test "$unexpected_stdio_behavior" = yes; then
+ AC_MSG_FAILURE([unexpected stdio behavior])
+ fi
+fi
+
dnl default value for $KANJI
DEFAULT_KCODE="KCODE_NONE"
Index: io.c
===================================================================
RCS file: /cvs/ruby/src/ruby/io.c,v
retrieving revision 1.69.2.29
diff -u -2 -p -r1.69.2.29 io.c
--- io.c 31 Dec 2002 17:23:29 -0000 1.69.2.29
+++ io.c 5 Jan 2003 15:25:36 -0000
@@ -152,4 +152,29 @@ rb_io_check_closed(fptr)
}
+static void io_fflush _((FILE *, const char *));
+
+#if NEED_IO_FLUSH_BEFORE_SEEK
+static OpenFile *
+flush_before_seek(fptr)
+ OpenFile *fptr;
+{
+ if (fptr->mode & FMODE_WBUF) {
+ io_fflush(GetWriteFile(fptr), fptr);
+ }
+ return fptr;
+}
+#else
+#define flush_before_seek(fptr) fptr
+#endif
+
+#define io_seek(fptr, ofs, whence) fseek(flush_before_seek(fptr)->f, ofs, whence)
+#define io_tell(fptr) ftell(flush_before_seek(fptr)->f)
+
+#ifndef SEEK_CUR
+# define SEEK_SET 0
+# define SEEK_CUR 1
+# define SEEK_END 2
+#endif
+
void
rb_io_check_readable(fptr)
@@ -159,4 +184,11 @@ rb_io_check_readable(fptr)
rb_raise(rb_eIOError, "not opened for reading");
}
+#if NEED_IO_SEEK_BETWEEN_RW
+ if ((fptr->mode & FMODE_WBUF) && !fptr->f2) {
+ io_seek(fptr, 0, SEEK_CUR);
+ fptr->mode &= ~FMODE_WBUF;
+ }
+ fptr->mode |= FMODE_RBUF;
+#endif
}
@@ -168,4 +200,10 @@ rb_io_check_writable(fptr)
rb_raise(rb_eIOError, "not opened for writing");
}
+#if NEED_IO_SEEK_BETWEEN_RW
+ if ((fptr->mode & FMODE_RBUF) && !fptr->f2) {
+ io_seek(fptr, 0, SEEK_CUR);
+ fptr->mode &= ~FMODE_RBUF;
+ }
+#endif
}
@@ -305,5 +343,5 @@ rb_io_tell(io)
GetOpenFile(io, fptr);
- pos = ftell(fptr->f);
+ pos = io_tell(fptr);
if (ferror(fptr->f)) rb_sys_fail(fptr->path);
@@ -311,10 +349,4 @@ rb_io_tell(io)
}
-#ifndef SEEK_CUR
-# define SEEK_SET 0
-# define SEEK_CUR 1
-# define SEEK_END 2
-#endif
-
static VALUE
rb_io_seek(argc, argv, io)
@@ -333,5 +365,5 @@ rb_io_seek(argc, argv, io)
GetOpenFile(io, fptr);
- pos = fseek(fptr->f, NUM2INT(offset), whence);
+ pos = io_seek(fptr, NUM2INT(offset), whence);
if (pos != 0) rb_sys_fail(fptr->path);
clearerr(fptr->f);
@@ -348,5 +380,5 @@ rb_io_set_pos(io, offset)
GetOpenFile(io, fptr);
- pos = fseek(fptr->f, NUM2INT(offset), SEEK_SET);
+ pos = io_seek(fptr, NUM2INT(offset), SEEK_SET);
if (pos != 0) rb_sys_fail(fptr->path);
clearerr(fptr->f);
@@ -362,5 +394,5 @@ rb_io_rewind(io)
GetOpenFile(io, fptr);
- if (fseek(fptr->f, 0L, 0) != 0) rb_sys_fail(fptr->path);
+ if (io_seek(fptr, 0L, 0) != 0) rb_sys_fail(fptr->path);
clearerr(fptr->f);
if (io == current_file) {
@@ -518,5 +550,5 @@ read_all(port)
)
{
- pos = ftell(fptr->f);
+ pos = io_tell(fptr);
if (st.st_size > pos && pos >= 0) {
siz = st.st_size - pos + 1;
@@ -1853,6 +1885,6 @@ io_reopen(io, nfile)
}
if ((orig->mode & FMODE_READABLE) && pos >= 0) {
- fseek(fptr->f, pos, SEEK_SET);
- fseek(orig->f, pos, SEEK_SET);
+ io_seek(fptr, pos, SEEK_SET);
+ io_seek(orig, pos, SEEK_SET);
}
Index: rubyio.h
===================================================================
RCS file: /cvs/ruby/src/ruby/rubyio.h,v
retrieving revision 1.9.2.1
diff -u -2 -p -r1.9.2.1 rubyio.h
--- rubyio.h 17 Dec 2001 08:13:17 -0000 1.9.2.1
+++ rubyio.h 2 Oct 2002 10:32:33 -0000
@@ -32,4 +32,6 @@ typedef struct OpenFile {
#define FMODE_BINMODE 4
#define FMODE_SYNC 8
+#define FMODE_WBUF 16
+#define FMODE_RBUF 32
#define GetOpenFile(obj,fp) rb_io_check_closed((fp) = RFILE(rb_io_taint_check(obj))->fptr)
--
--- 僕の前にBugはない。
--- 僕の後ろにBugはできる。
中田 伸悦