diff --git a/ChangeLog b/ChangeLog index efceb883e4..f79099a86b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +Mon Dec 6 17:32:38 2004 Tanaka Akira + + * rubyio.h, intern.h, io.c, file.c, process.c, ext/socket/socket.c, + ext/pty/pty.c, ext/io/wait/wait.c, ext/openssl/ossl_ssl.c: + Use own buffering mechanism instead of stdio. + + * io.c, ext/stringio/stringio.c, test/ruby/ut_eof.rb: + EOF flag removed. + Mon Dec 6 17:15:17 2004 Nobuyoshi Nakada * test/socket/test_socket.rb (TestBasicSocket#test_setsockopt): diff --git a/ext/io/wait/wait.c b/ext/io/wait/wait.c index 53d5bd7d18..df8d24c29b 100644 --- a/ext/io/wait/wait.c +++ b/ext/io/wait/wait.c @@ -40,15 +40,12 @@ io_ready_p(io) VALUE io; { OpenFile *fptr; - FILE *fp; int n; GetOpenFile(io, fptr); rb_io_check_readable(fptr); - fp = fptr->f; - if (feof(fp)) return Qfalse; - if (rb_read_pending(fp)) return Qtrue; - if (ioctl(fileno(fp), FIONREAD, &n)) rb_sys_fail(0); + if (rb_io_read_pending(fptr)) return Qtrue; + if (ioctl(fptr->fd, FIONREAD, &n)) rb_sys_fail(0); if (n > 0) return INT2NUM(n); return Qnil; } @@ -68,7 +65,6 @@ io_wait(argc, argv, io) { OpenFile *fptr; fd_set rd; - FILE *fp; int fd, n; VALUE timeout; struct timeval *tp, timerec; @@ -84,16 +80,14 @@ io_wait(argc, argv, io) tp = &timerec; } - fp = fptr->f; - if (feof(fp)) return Qfalse; - if (rb_read_pending(fp)) return Qtrue; - fd = fileno(fp); + if (rb_io_read_pending(fptr)) return Qtrue; + fd = fptr->fd; FD_ZERO(&rd); FD_SET(fd, &rd); if (rb_thread_select(fd + 1, &rd, NULL, NULL, tp) < 0) rb_sys_fail(0); rb_io_check_closed(fptr); - if (ioctl(fileno(fp), FIONREAD, &n)) rb_sys_fail(0); + if (ioctl(fptr->fd, FIONREAD, &n)) rb_sys_fail(0); if (n > 0) return io; return Qnil; } diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c index 24bca62084..7ab21678c5 100644 --- a/ext/openssl/ossl_ssl.c +++ b/ext/openssl/ossl_ssl.c @@ -429,7 +429,7 @@ ossl_ssl_setup(VALUE self) GetOpenFile(io, fptr); rb_io_check_readable(fptr); rb_io_check_writable(fptr); - SSL_set_fd(ssl, TO_SOCKET(fileno(fptr->f))); + SSL_set_fd(ssl, TO_SOCKET(fptr->fd)); } return Qtrue; @@ -505,7 +505,7 @@ ossl_ssl_read(int argc, VALUE *argv, VALUE self) if (ssl) { if(SSL_pending(ssl) <= 0) - rb_thread_wait_fd(fileno(fptr->f)); + rb_thread_wait_fd(fptr->fd); for (;;){ nread = SSL_read(ssl, RSTRING(str)->ptr, RSTRING(str)->len); switch(SSL_get_error(ssl, nread)){ diff --git a/ext/pty/pty.c b/ext/pty/pty.c index cfd7e4854e..d47acbe5b5 100644 --- a/ext/pty/pty.c +++ b/ext/pty/pty.c @@ -427,11 +427,13 @@ pty_getpty(argc, argv, self) establishShell(argc, argv, &info); rfptr->mode = rb_io_mode_flags("r"); - rfptr->f = fdopen(info.fd, "r"); + rfptr->fd = info.fd; + rfptr->f = rb_fdopen(info.fd, "r"); rfptr->path = strdup(SlaveName); wfptr->mode = rb_io_mode_flags("w") | FMODE_SYNC; - wfptr->f = fdopen(dup(info.fd), "w"); + wfptr->fd = dup(info.fd); + wfptr->f = rb_fdopen(wfptr->fd, "w"); wfptr->path = strdup(SlaveName); res = rb_ary_new2(3); diff --git a/ext/socket/socket.c b/ext/socket/socket.c index 0e44cdc94c..de49c7398c 100644 --- a/ext/socket/socket.c +++ b/ext/socket/socket.c @@ -182,8 +182,8 @@ init_sock(sock, fd) OpenFile *fp; MakeOpenFile(sock, fp); - fp->f = rb_fdopen(fd, "r"); - fp->f2 = rb_fdopen(fd, "w"); + fp->fd = fd; + fp->f = rb_fdopen(fd, "r+"); fp->mode = FMODE_READWRITE; if (do_not_reverse_lookup) { fp->mode |= FMODE_NOREVLOOKUP; @@ -228,7 +228,7 @@ bsock_shutdown(argc, argv, sock) } } GetOpenFile(sock, fptr); - if (shutdown(fileno(fptr->f), how) == -1) + if (shutdown(fptr->fd, how) == -1) rb_sys_fail(0); return INT2FIX(0); @@ -244,7 +244,7 @@ bsock_close_read(sock) rb_raise(rb_eSecurityError, "Insecure: can't close socket"); } GetOpenFile(sock, fptr); - shutdown(fileno(fptr->f), 0); + shutdown(fptr->fd, 0); if (!(fptr->mode & FMODE_WRITABLE)) { return rb_io_close(sock); } @@ -266,7 +266,7 @@ bsock_close_write(sock) if (!(fptr->mode & FMODE_READABLE)) { return rb_io_close(sock); } - shutdown(fileno(fptr->f2), 1); + shutdown(fptr->fd, 1); fptr->mode &= ~FMODE_WRITABLE; return Qnil; @@ -306,7 +306,7 @@ bsock_setsockopt(sock, lev, optname, val) break; } - if (setsockopt(fileno(fptr->f), level, option, v, vlen) < 0) + if (setsockopt(fptr->fd, level, option, v, vlen) < 0) rb_sys_fail(fptr->path); return INT2FIX(0); @@ -328,7 +328,7 @@ bsock_getsockopt(sock, lev, optname) buf = ALLOCA_N(char,len); GetOpenFile(sock, fptr); - if (getsockopt(fileno(fptr->f), level, option, buf, &len) < 0) + if (getsockopt(fptr->fd, level, option, buf, &len) < 0) rb_sys_fail(fptr->path); return rb_str_new(buf, len); @@ -346,7 +346,7 @@ bsock_getsockname(sock) OpenFile *fptr; GetOpenFile(sock, fptr); - if (getsockname(fileno(fptr->f), (struct sockaddr*)buf, &len) < 0) + if (getsockname(fptr->fd, (struct sockaddr*)buf, &len) < 0) rb_sys_fail("getsockname(2)"); return rb_str_new(buf, len); } @@ -360,7 +360,7 @@ bsock_getpeername(sock) OpenFile *fptr; GetOpenFile(sock, fptr); - if (getpeername(fileno(fptr->f), (struct sockaddr*)buf, &len) < 0) + if (getpeername(fptr->fd, (struct sockaddr*)buf, &len) < 0) rb_sys_fail("getpeername(2)"); return rb_str_new(buf, len); } @@ -374,15 +374,13 @@ bsock_send(argc, argv, sock) VALUE mesg, to; VALUE flags; OpenFile *fptr; - FILE *f; int fd, n; rb_secure(4); rb_scan_args(argc, argv, "21", &mesg, &flags, &to); GetOpenFile(sock, fptr); - f = GetWriteFile(fptr); - fd = fileno(f); + fd = fptr->fd; rb_thread_fd_writable(fd); StringValue(mesg); retry: @@ -465,10 +463,10 @@ s_recvfrom(sock, argc, argv, from) else flags = NUM2INT(flg); GetOpenFile(sock, fptr); - if (rb_read_pending(fptr->f)) { + if (rb_io_read_pending(fptr)) { rb_raise(rb_eIOError, "recv for buffered IO"); } - fd = fileno(fptr->f); + fd = fptr->fd; buflen = NUM2INT(len); str = rb_tainted_str_new(0, buflen); @@ -1123,8 +1121,7 @@ socks_s_close(sock) rb_raise(rb_eSecurityError, "Insecure: can't close socket"); } GetOpenFile(sock, fptr); - shutdown(fileno(fptr->f), 2); - shutdown(fileno(fptr->f2), 2); + shutdown(fptr->fd, 2); return rb_io_close(sock); } #endif @@ -1276,7 +1273,7 @@ tcp_accept(sock) GetOpenFile(sock, fptr); fromlen = sizeof(from); - return s_accept(rb_cTCPSocket, fileno(fptr->f), + return s_accept(rb_cTCPSocket, fptr->fd, (struct sockaddr*)&from, &fromlen); } @@ -1290,7 +1287,7 @@ tcp_sysaccept(sock) GetOpenFile(sock, fptr); fromlen = sizeof(from); - return s_accept(0, fileno(fptr->f), (struct sockaddr*)&from, &fromlen); + return s_accept(0, fptr->fd, (struct sockaddr*)&from, &fromlen); } #ifdef HAVE_SYS_UN_H @@ -1367,7 +1364,7 @@ ip_addr(sock) GetOpenFile(sock, fptr); - if (getsockname(fileno(fptr->f), (struct sockaddr*)&addr, &len) < 0) + if (getsockname(fptr->fd, (struct sockaddr*)&addr, &len) < 0) rb_sys_fail("getsockname(2)"); return ipaddr((struct sockaddr*)&addr, fptr->mode & FMODE_NOREVLOOKUP); } @@ -1382,7 +1379,7 @@ ip_peeraddr(sock) GetOpenFile(sock, fptr); - if (getpeername(fileno(fptr->f), (struct sockaddr*)&addr, &len) < 0) + if (getpeername(fptr->fd, (struct sockaddr*)&addr, &len) < 0) rb_sys_fail("getpeername(2)"); return ipaddr((struct sockaddr*)&addr, fptr->mode & FMODE_NOREVLOOKUP); } @@ -1464,7 +1461,7 @@ udp_connect(sock, host, port) rb_secure(3); GetOpenFile(sock, fptr); arg.res = sock_addrinfo(host, port, SOCK_DGRAM, 0); - arg.fd = fileno(fptr->f); + arg.fd = fptr->fd; ret = rb_ensure(udp_connect_internal, (VALUE)&arg, RUBY_METHOD_FUNC(freeaddrinfo), (VALUE)arg.res); if (!ret) rb_sys_fail("connect(2)"); @@ -1482,7 +1479,7 @@ udp_bind(sock, host, port) GetOpenFile(sock, fptr); res0 = sock_addrinfo(host, port, SOCK_DGRAM, 0); for (res = res0; res; res = res->ai_next) { - if (bind(fileno(fptr->f), res->ai_addr, res->ai_addrlen) < 0) { + if (bind(fptr->fd, res->ai_addr, res->ai_addrlen) < 0) { continue; } freeaddrinfo(res0); @@ -1501,7 +1498,6 @@ udp_send(argc, argv, sock) { VALUE mesg, flags, host, port; OpenFile *fptr; - FILE *f; int n; struct addrinfo *res0, *res; @@ -1513,17 +1509,16 @@ udp_send(argc, argv, sock) GetOpenFile(sock, fptr); res0 = sock_addrinfo(host, port, SOCK_DGRAM, 0); - f = GetWriteFile(fptr); StringValue(mesg); for (res = res0; res; res = res->ai_next) { retry: - n = sendto(fileno(f), RSTRING(mesg)->ptr, RSTRING(mesg)->len, NUM2INT(flags), + n = sendto(fptr->fd, RSTRING(mesg)->ptr, RSTRING(mesg)->len, NUM2INT(flags), res->ai_addr, res->ai_addrlen); if (n >= 0) { freeaddrinfo(res0); return INT2FIX(n); } - if (rb_io_wait_writable(fileno(f))) { + if (rb_io_wait_writable(fptr->fd)) { goto retry; } } @@ -1550,7 +1545,7 @@ unix_path(sock) if (fptr->path == 0) { struct sockaddr_un addr; socklen_t len = sizeof(addr); - if (getsockname(fileno(fptr->f), (struct sockaddr*)&addr, &len) < 0) + if (getsockname(fptr->fd, (struct sockaddr*)&addr, &len) < 0) rb_sys_fail(0); fptr->path = strdup(addr.sun_path); } @@ -1606,7 +1601,7 @@ unix_send_io(sock, val) if (rb_obj_is_kind_of(val, rb_cIO)) { OpenFile *valfptr; GetOpenFile(val, valfptr); - fd = fileno(valfptr->f); + fd = valfptr->fd; } else if (FIXNUM_P(val)) { fd = FIX2INT(val); @@ -1640,7 +1635,7 @@ unix_send_io(sock, val) msg.msg_accrightslen = sizeof(fd); #endif - if (sendmsg(fileno(fptr->f), &msg, 0) == -1) + if (sendmsg(fptr->fd, &msg, 0) == -1) rb_sys_fail("sendmsg(2)"); return Qnil; @@ -1692,7 +1687,7 @@ unix_recv_io(argc, argv, sock) GetOpenFile(sock, fptr); - thread_read_select(fileno(fptr->f)); + thread_read_select(fptr->fd); msg.msg_name = NULL; msg.msg_namelen = 0; @@ -1716,7 +1711,7 @@ unix_recv_io(argc, argv, sock) fd = -1; #endif - if (recvmsg(fileno(fptr->f), &msg, 0) == -1) + if (recvmsg(fptr->fd, &msg, 0) == -1) rb_sys_fail("recvmsg(2)"); if ( @@ -1765,7 +1760,7 @@ unix_accept(sock) GetOpenFile(sock, fptr); fromlen = sizeof(struct sockaddr_un); - return s_accept(rb_cUNIXSocket, fileno(fptr->f), + return s_accept(rb_cUNIXSocket, fptr->fd, (struct sockaddr*)&from, &fromlen); } @@ -1779,7 +1774,7 @@ unix_sysaccept(sock) GetOpenFile(sock, fptr); fromlen = sizeof(struct sockaddr_un); - return s_accept(0, fileno(fptr->f), (struct sockaddr*)&from, &fromlen); + return s_accept(0, fptr->fd, (struct sockaddr*)&from, &fromlen); } #ifdef HAVE_SYS_UN_H @@ -1802,7 +1797,7 @@ unix_addr(sock) GetOpenFile(sock, fptr); - if (getsockname(fileno(fptr->f), (struct sockaddr*)&addr, &len) < 0) + if (getsockname(fptr->fd, (struct sockaddr*)&addr, &len) < 0) rb_sys_fail("getsockname(2)"); if (len == 0) addr.sun_path[0] = '\0'; @@ -1819,7 +1814,7 @@ unix_peeraddr(sock) GetOpenFile(sock, fptr); - if (getpeername(fileno(fptr->f), (struct sockaddr*)&addr, &len) < 0) + if (getpeername(fptr->fd, (struct sockaddr*)&addr, &len) < 0) rb_sys_fail("getsockname(2)"); if (len == 0) addr.sun_path[0] = '\0'; @@ -1987,7 +1982,7 @@ sock_connect(sock, addr) StringValue(addr); GetOpenFile(sock, fptr); - fd = fileno(fptr->f); + fd = fptr->fd; rb_str_locktmp(addr); n = ruby_connect(fd, (struct sockaddr*)RSTRING(addr)->ptr, RSTRING(addr)->len, 0); rb_str_unlocktmp(addr); @@ -2006,7 +2001,7 @@ sock_bind(sock, addr) StringValue(addr); GetOpenFile(sock, fptr); - if (bind(fileno(fptr->f), (struct sockaddr*)RSTRING(addr)->ptr, RSTRING(addr)->len) < 0) + if (bind(fptr->fd, (struct sockaddr*)RSTRING(addr)->ptr, RSTRING(addr)->len) < 0) rb_sys_fail("bind(2)"); return INT2FIX(0); @@ -2020,7 +2015,7 @@ sock_listen(sock, log) rb_secure(4); GetOpenFile(sock, fptr); - if (listen(fileno(fptr->f), NUM2INT(log)) < 0) + if (listen(fptr->fd, NUM2INT(log)) < 0) rb_sys_fail("listen(2)"); return INT2FIX(0); @@ -2045,7 +2040,7 @@ sock_accept(sock) socklen_t len = sizeof buf; GetOpenFile(sock, fptr); - sock2 = s_accept(rb_cSocket,fileno(fptr->f),(struct sockaddr*)buf,&len); + sock2 = s_accept(rb_cSocket,fptr->fd,(struct sockaddr*)buf,&len); return rb_assoc_new(sock2, rb_str_new(buf, len)); } @@ -2060,7 +2055,7 @@ sock_sysaccept(sock) socklen_t len = sizeof buf; GetOpenFile(sock, fptr); - sock2 = s_accept(0,fileno(fptr->f),(struct sockaddr*)buf,&len); + sock2 = s_accept(0,fptr->fd,(struct sockaddr*)buf,&len); return rb_assoc_new(sock2, rb_str_new(buf, len)); } diff --git a/ext/stringio/stringio.c b/ext/stringio/stringio.c index f46af0f0ad..b31f1818b2 100644 --- a/ext/stringio/stringio.c +++ b/ext/stringio/stringio.c @@ -20,8 +20,6 @@ #include #endif -#define STRIO_EOF FMODE_SYNC - struct StringIO { VALUE string; long pos; @@ -490,7 +488,6 @@ strio_rewind(self) struct StringIO *ptr = StringIO(self); ptr->pos = 0; ptr->lineno = 0; - ptr->flags &= ~STRIO_EOF; return INT2FIX(0); } @@ -522,7 +519,6 @@ strio_seek(argc, argv, self) error_inval(0); } ptr->pos = offset; - ptr->flags &= ~STRIO_EOF; return INT2FIX(0); } @@ -557,7 +553,6 @@ strio_getc(self) struct StringIO *ptr = readable(StringIO(self)); int c; if (ptr->pos >= RSTRING(ptr->string)->len) { - ptr->flags |= STRIO_EOF; return Qnil; } c = RSTRING(ptr->string)->ptr[ptr->pos++]; @@ -588,7 +583,6 @@ strio_ungetc(self, ch) OBJ_INFECT(ptr->string, self); } --ptr->pos; - ptr->flags &= ~STRIO_EOF; } return Qnil; } @@ -661,7 +655,6 @@ strio_getline(argc, argv, ptr) } if (ptr->pos >= (n = RSTRING(ptr->string)->len)) { - ptr->flags |= STRIO_EOF; return Qnil; } s = RSTRING(ptr->string)->ptr; @@ -674,7 +667,6 @@ strio_getline(argc, argv, ptr) p = s; while (*p == '\n') { if (++p == e) { - ptr->flags |= STRIO_EOF; return Qnil; } } @@ -858,11 +850,6 @@ strio_read(argc, argv, self) rb_raise(rb_eArgError, "negative length %ld given", len); } if (len > 0 && ptr->pos >= RSTRING(ptr->string)->len) { - ptr->flags |= STRIO_EOF; - if (!NIL_P(str)) rb_str_resize(str, 0); - return Qnil; - } - else if (ptr->flags & STRIO_EOF) { if (!NIL_P(str)) rb_str_resize(str, 0); return Qnil; } @@ -873,7 +860,6 @@ strio_read(argc, argv, self) olen = -1; len = RSTRING(ptr->string)->len; if (len <= ptr->pos) { - ptr->flags |= STRIO_EOF; if (NIL_P(str)) { str = rb_str_new(0, 0); } @@ -899,13 +885,12 @@ strio_read(argc, argv, self) MEMCPY(RSTRING(str)->ptr, RSTRING(ptr->string)->ptr + ptr->pos, char, len); } if (NIL_P(str)) { - if (!(ptr->flags & STRIO_EOF)) str = rb_str_new(0, 0); + str = rb_str_new(0, 0); len = 0; } else { ptr->pos += len = RSTRING(str)->len; } - if (olen < 0 || olen > len) ptr->flags |= STRIO_EOF; return str; } diff --git a/file.c b/file.c index b185d0cd59..2555e7032e 100644 --- a/file.c +++ b/file.c @@ -639,7 +639,7 @@ rb_stat(file, st) OpenFile *fptr; GetOpenFile(tmp, fptr); - return fstat(fileno(fptr->f), st); + return fstat(fptr->fd, st); } FilePathValue(file); return stat(StringValueCStr(file), st); @@ -693,7 +693,7 @@ rb_io_stat(obj) struct stat st; GetOpenFile(obj, fptr); - if (fstat(fileno(fptr->f), &st) == -1) { + if (fstat(fptr->fd, &st) == -1) { rb_sys_fail(fptr->path); } return stat_new(&st); @@ -1531,7 +1531,7 @@ rb_file_atime(obj) struct stat st; GetOpenFile(obj, fptr); - if (fstat(fileno(fptr->f), &st) == -1) { + if (fstat(fptr->fd, &st) == -1) { rb_sys_fail(fptr->path); } return rb_time_new(st.st_atime, 0); @@ -1576,7 +1576,7 @@ rb_file_mtime(obj) struct stat st; GetOpenFile(obj, fptr); - if (fstat(fileno(fptr->f), &st) == -1) { + if (fstat(fptr->fd, &st) == -1) { rb_sys_fail(fptr->path); } return rb_time_new(st.st_mtime, 0); @@ -1624,7 +1624,7 @@ rb_file_ctime(obj) struct stat st; GetOpenFile(obj, fptr); - if (fstat(fileno(fptr->f), &st) == -1) { + if (fstat(fptr->fd, &st) == -1) { rb_sys_fail(fptr->path); } return rb_time_new(st.st_ctime, 0); @@ -1695,7 +1695,7 @@ rb_file_chmod(obj, vmode) GetOpenFile(obj, fptr); #ifdef HAVE_FCHMOD - if (fchmod(fileno(fptr->f), mode) == -1) + if (fchmod(fptr->fd, mode) == -1) rb_sys_fail(fptr->path); #else if (!fptr->path) return Qnil; @@ -1840,7 +1840,7 @@ rb_file_chown(obj, owner, group) if (chown(fptr->path, o, g) == -1) rb_sys_fail(fptr->path); #else - if (fchown(fileno(fptr->f), o, g) == -1) + if (fchown(fptr->fd, o, g) == -1) rb_sys_fail(fptr->path); #endif @@ -2973,7 +2973,6 @@ rb_file_truncate(obj, len) VALUE obj, len; { OpenFile *fptr; - FILE *f; off_t pos; rb_secure(2); @@ -2982,15 +2981,13 @@ rb_file_truncate(obj, len) if (!(fptr->mode & FMODE_WRITABLE)) { rb_raise(rb_eIOError, "not opened for writing"); } - f = GetWriteFile(fptr); - fflush(f); - fseeko(f, (off_t)0, SEEK_CUR); + rb_io_flush(obj); #ifdef HAVE_TRUNCATE - if (ftruncate(fileno(f), pos) < 0) + if (ftruncate(fptr->fd, pos) < 0) rb_sys_fail(fptr->path); #else # ifdef HAVE_CHSIZE - if (chsize(fileno(f), pos) < 0) + if (chsize(fptr->fd, pos) < 0) rb_sys_fail(fptr->path); # else rb_notimplement(); @@ -3084,10 +3081,10 @@ rb_file_flock(obj, operation) GetOpenFile(obj, fptr); if (fptr->mode & FMODE_WRITABLE) { - fflush(GetWriteFile(fptr)); + rb_io_flush(obj); } retry: - if (flock(fileno(fptr->f), op) < 0) { + if (flock(fptr->fd, op) < 0) { switch (errno) { case EAGAIN: case EACCES: diff --git a/intern.h b/intern.h index ef2eaaecd5..8bc30db0e7 100644 --- a/intern.h +++ b/intern.h @@ -278,6 +278,7 @@ VALUE rb_io_gets _((VALUE)); VALUE rb_io_getc _((VALUE)); VALUE rb_io_ungetc _((VALUE, VALUE)); VALUE rb_io_close _((VALUE)); +VALUE rb_io_flush _((VALUE)); VALUE rb_io_eof _((VALUE)); VALUE rb_io_binmode _((VALUE)); VALUE rb_io_addstr _((VALUE, VALUE)); diff --git a/io.c b/io.c index 6a5af2576c..beaf102611 100644 --- a/io.c +++ b/io.c @@ -19,6 +19,8 @@ #include #include +#include +#include #if defined(MSDOS) || defined(__BOW__) || defined(__CYGWIN__) || defined(_WIN32) || defined(__human68k__) || defined(__EMX__) || defined(__BEOS__) # define NO_SAFE_RENAME @@ -101,7 +103,7 @@ VALUE rb_default_rs; static VALUE argf; -static ID id_write, id_read, id_getc; +static ID id_write, id_read, id_getc, id_flush; extern char *ruby_inplace_mode; @@ -117,50 +119,14 @@ static VALUE lineno = INT2FIX(0); #define open(file_spec, flags, mode) open(file_spec, flags, mode, "rfm=stmlf") #endif -#ifdef _STDIO_USES_IOSTREAM /* GNU libc */ -# ifdef _IO_fpos_t -# define READ_DATA_PENDING(fp) ((fp)->_IO_read_ptr != (fp)->_IO_read_end) -# define READ_DATA_PENDING_COUNT(fp) ((fp)->_IO_read_end - (fp)->_IO_read_ptr) -# define READ_DATA_PENDING_PTR(fp) ((fp)->_IO_read_ptr) -# else -# define READ_DATA_PENDING(fp) ((fp)->_gptr < (fp)->_egptr) -# define READ_DATA_PENDING_COUNT(fp) ((fp)->_egptr - (fp)->_gptr) -# define READ_DATA_PENDING_PTR(fp) ((fp)->_gptr) -# endif -#elif defined(FILE_COUNT) -# define READ_DATA_PENDING(fp) ((fp)->FILE_COUNT > 0) -# define READ_DATA_PENDING_COUNT(fp) ((fp)->FILE_COUNT) -#elif defined(FILE_READEND) -# define READ_DATA_PENDING(fp) ((fp)->FILE_READPTR < (fp)->FILE_READEND) -# define READ_DATA_PENDING_COUNT(fp) ((fp)->FILE_READEND - (fp)->FILE_READPTR) -#elif defined(__BEOS__) -# define READ_DATA_PENDING(fp) (fp->_state._eof == 0) -#elif defined(__VMS) -# define READ_DATA_PENDING(fp) (((unsigned int)((*(fp))->_flag) & _IOEOF) == 0) -#else -/* requires systems own version of the ReadDataPending() */ -extern int ReadDataPending(); -# define READ_DATA_PENDING(fp) (!feof(fp)) -# define READ_DATA_BUFFERED(fp) 0 -#endif -#ifndef READ_DATA_BUFFERED -# define READ_DATA_BUFFERED(fp) READ_DATA_PENDING(fp) -#endif +#define READ_DATA_PENDING(fptr) ((fptr)->rbuf_len) +#define READ_DATA_PENDING_COUNT(fptr) ((fptr)->rbuf_len) +#define READ_DATA_PENDING_PTR(fptr) ((fptr)->rbuf+(fptr)->rbuf_off) +#define READ_DATA_BUFFERED(fptr) READ_DATA_PENDING(fptr) -#ifndef READ_DATA_PENDING_PTR -# ifdef FILE_READPTR -# define READ_DATA_PENDING_PTR(fp) ((char *)(fp)->FILE_READPTR) -# endif -#endif - -#if defined __DJGPP__ -# undef READ_DATA_PENDING_COUNT -# undef READ_DATA_PENDING_PTR -#endif - -#define READ_CHECK(fp) do {\ - if (!READ_DATA_PENDING(fp)) {\ - rb_thread_wait_fd(fileno(fp));\ +#define READ_CHECK(fptr) do {\ + if (!READ_DATA_PENDING(fptr)) {\ + rb_thread_wait_fd((fptr)->fd);\ rb_io_check_closed(fptr);\ }\ } while(0) @@ -195,12 +161,12 @@ rb_io_check_closed(fptr) OpenFile *fptr; { rb_io_check_initialized(fptr); - if (!fptr->f && !fptr->f2) { + if (fptr->fd < 0 || !fptr->f) { rb_raise(rb_eIOError, "closed stream"); } } -static void io_fflush _((FILE *, OpenFile *)); +static int io_fflush _((OpenFile *)); static VALUE rb_io_get_io(io) @@ -216,18 +182,59 @@ rb_io_check_io(io) return rb_check_convert_type(io, T_FILE, "IO", "to_io"); } +static void +io_unread(OpenFile *fptr) +{ + off_t r; + rb_io_check_closed(fptr); + if (fptr->rbuf_len == 0 || fptr->mode & FMODE_UNSEEKABLE) + return; + /* xxx: target position may be negative if buffer is filled by ungetc */ + r = lseek(fptr->fd, -fptr->rbuf_len, SEEK_CUR); + if (r < 0) { + if (errno == ESPIPE) + fptr->mode |= FMODE_UNSEEKABLE; + return; + } + fptr->rbuf_off = 0; + fptr->rbuf_len = 0; + return; +} + +static int +io_ungetc(int c, OpenFile *fptr) +{ + if (fptr->rbuf == NULL) { + fptr->rbuf_off = 0; + fptr->rbuf_len = 0; + fptr->rbuf_capa = 8192; + fptr->rbuf = ALLOC_N(char, fptr->rbuf_capa); + } + if (c < 0 || fptr->rbuf_len == fptr->rbuf_capa) { + return -1; + } + if (fptr->rbuf_off == 0) { + if (fptr->rbuf_len) + MEMMOVE(fptr->rbuf+1, fptr->rbuf, char, fptr->rbuf_len); + fptr->rbuf_off = 1; + } + fptr->rbuf_off--; + fptr->rbuf_len++; + fptr->rbuf[fptr->rbuf_off] = c; + return c; +} + static OpenFile * flush_before_seek(fptr) OpenFile *fptr; { - if (fptr->mode & FMODE_WBUF) { - io_fflush(GetWriteFile(fptr), fptr); - } + io_fflush(fptr); + io_unread(fptr); return fptr; } -#define io_seek(fptr, ofs, whence) fseeko(flush_before_seek(fptr)->f, ofs, whence) -#define io_tell(fptr) ftello(flush_before_seek(fptr)->f) +#define io_seek(fptr, ofs, whence) lseek(flush_before_seek(fptr)->fd, ofs, whence) +#define io_tell(fptr) lseek(flush_before_seek(fptr)->fd, 0, SEEK_CUR) #ifndef SEEK_CUR # define SEEK_SET 0 @@ -242,15 +249,12 @@ rb_io_check_readable(fptr) OpenFile *fptr; { rb_io_check_closed(fptr); -#if NEED_IO_SEEK_BETWEEN_RW - if (((fptr->mode & FMODE_WBUF) || - (fptr->mode & (FMODE_SYNCWRITE|FMODE_RBUF)) == FMODE_SYNCWRITE) && - !feof(fptr->f) && - !fptr->f2) { - io_seek(fptr, 0, SEEK_CUR); + if (!(fptr->mode & FMODE_READABLE)) { + rb_raise(rb_eIOError, "not opened for reading"); + } + if (fptr->wbuf_len) { + io_fflush(fptr); } -#endif - fptr->mode |= FMODE_RBUF; } void @@ -261,11 +265,8 @@ rb_io_check_writable(fptr) if (!(fptr->mode & FMODE_WRITABLE)) { rb_raise(rb_eIOError, "not opened for writing"); } - if ((fptr->mode & FMODE_RBUF) && !feof(fptr->f) && !fptr->f2) { - io_seek(fptr, 0, SEEK_CUR); - } - if (!fptr->f2) { - fptr->mode &= ~FMODE_RBUF; + if (fptr->rbuf_len) { + io_unread(fptr); } } @@ -273,16 +274,35 @@ int rb_read_pending(fp) FILE *fp; { - return READ_DATA_PENDING(fp); + /* xxx: return READ_DATA_PENDING(fp); */ + return 1; +} + +int +rb_io_read_pending(OpenFile *fptr) +{ + return READ_DATA_PENDING(fptr); } void rb_read_check(fp) FILE *fp; { + /* xxx: if (!READ_DATA_PENDING(fp)) { rb_thread_wait_fd(fileno(fp)); } + */ + return; +} + +void +rb_io_read_check(OpenFile *fptr) +{ + if (!READ_DATA_PENDING(fptr)) { + rb_thread_wait_fd(fptr->fd); + } + return; } static int @@ -317,26 +337,42 @@ io_alloc(klass) return (VALUE)io; } -static void -io_fflush(f, fptr) - FILE *f; +static int +io_fflush(fptr) OpenFile *fptr; { - int n; + int r; + int wbuf_off, wbuf_len; - if (!rb_thread_fd_writable(fileno(f))) { + rb_io_check_closed(fptr); + if (fptr->wbuf_len == 0) + return 0; + if (!rb_thread_fd_writable(fptr->fd)) { rb_io_check_closed(fptr); } - for (;;) { - TRAP_BEG; - n = fflush(f); - TRAP_END; - if (n != EOF) break; - if (!rb_io_wait_writable(fileno(f))) - rb_sys_fail(fptr->path); - rb_io_check_closed(fptr); + retry: + if (fptr->wbuf_len == 0) + return 0; + wbuf_off = fptr->wbuf_off; + wbuf_len = fptr->wbuf_len; + TRAP_BEG; + r = write(fptr->fd, fptr->wbuf+fptr->wbuf_off, fptr->wbuf_len); + TRAP_END; /* xxx: signal handler may modify wbuf */ + if (r == fptr->wbuf_len) { + fptr->wbuf_off = 0; + fptr->wbuf_len = 0; + return 0; } - fptr->mode &= ~FMODE_WBUF; + if (0 <= r) { + fptr->wbuf_off = (wbuf_off += r); + fptr->wbuf_len = (wbuf_len -= r); + errno = EAGAIN; + } + if (rb_io_wait_writable(fptr->fd)) { + rb_io_check_closed(fptr); + goto retry; + } + return -1; } int @@ -403,55 +439,59 @@ io_fwrite(ptr, len, fptr) OpenFile *fptr; { long n, r; - FILE *f = GetWriteFile(fptr); if ((n = len) <= 0) return n; - if (fptr->mode & FMODE_SYNC) { - io_fflush(f, fptr); - if (!rb_thread_fd_writable(fileno(f))) { + if (fptr->wbuf == NULL && !(fptr->mode & FMODE_SYNC)) { + fptr->wbuf_off = 0; + fptr->wbuf_len = 0; + fptr->wbuf_capa = 8192; + fptr->wbuf = ALLOC_N(char, fptr->wbuf_capa); + } + if ((fptr->mode & FMODE_SYNC) || + (fptr->wbuf && fptr->wbuf_capa <= fptr->wbuf_len + len) || + ((fptr->mode & FMODE_LINEBUF) && memchr(ptr, '\n', len))) { + /* xxx: use writev to avoid double write if available */ + if (fptr->wbuf_len+len <= fptr->wbuf_capa) { + if (fptr->wbuf_capa < fptr->wbuf_off+fptr->wbuf_len+len) { + MEMMOVE(fptr->wbuf, fptr->wbuf+fptr->wbuf_off, char, fptr->wbuf_len); + fptr->wbuf_off = 0; + } + MEMMOVE(fptr->wbuf+fptr->wbuf_off+fptr->wbuf_len, ptr, char, len); + fptr->wbuf_len += len; + n = 0; + } + if (io_fflush(fptr) < 0) + return -1L; + if (n == 0) + return len; + if (!rb_thread_fd_writable(fptr->fd)) { rb_io_check_closed(fptr); } retry: - r = write(fileno(f), ptr, n); + TRAP_BEG; + r = write(fptr->fd, ptr, n); + TRAP_END; /* xxx: signal handler may modify given string. */ if (r == n) return len; if (0 <= r) { ptr += r; n -= r; errno = EAGAIN; } - if (rb_io_wait_writable(fileno(f))) { + if (rb_io_wait_writable(fptr->fd)) { rb_io_check_closed(fptr); goto retry; } return -1L; } -#if defined __human68k__ - do { - if (fputc(*ptr++, f) == EOF) { - if (ferror(f)) return -1L; - break; - } - } while (--n > 0); -#else - while (errno = 0, ptr += (r = fwrite(ptr, 1, n, f)), (n -= r) > 0) { - if (ferror(f) -#if defined __BORLANDC__ - || errno -#endif - ) { -#ifdef __hpux - if (!errno) errno = EAGAIN; -#endif - if (rb_io_wait_writable(fileno(f))) { - rb_io_check_closed(fptr); - clearerr(f); - continue; - } - return -1L; - } + + if (fptr->wbuf_off) { + if (fptr->wbuf_len) + MEMMOVE(fptr->wbuf, fptr->wbuf+fptr->wbuf_off, char, fptr->wbuf_len); + fptr->wbuf_off = 0; } -#endif - return len - n; + MEMMOVE(fptr->wbuf+fptr->wbuf_off+fptr->wbuf_len, ptr, char, len); + fptr->wbuf_len += len; + return len; } long @@ -462,8 +502,8 @@ rb_io_fwrite(ptr, len, f) { OpenFile of; + of.fd = fileno(f); of.f = f; - of.f2 = NULL; of.mode = FMODE_WRITABLE; of.path = NULL; return io_fwrite(ptr, len, &of); @@ -512,9 +552,6 @@ io_write(io, str) n = io_fwrite(RSTRING(str)->ptr, RSTRING(str)->len, fptr); rb_str_unlocktmp(str); if (n == -1L) rb_sys_fail(fptr->path); - if (!(fptr->mode & FMODE_SYNC)) { - fptr->mode |= FMODE_WBUF; - } return LONG2FIX(n); } @@ -566,23 +603,28 @@ rb_io_addstr(io, str) * no newline */ -static VALUE +VALUE rb_io_flush(io) VALUE io; { OpenFile *fptr; - FILE *f; + + if (TYPE(io) != T_FILE) { + return rb_funcall(io, id_flush, 0); + } GetOpenFile(io, fptr); - rb_io_check_writable(fptr); - f = GetWriteFile(fptr); - io_fflush(f, fptr); + if (fptr->mode & FMODE_WRITABLE) { + io_fflush(fptr); + } + if (fptr->mode & FMODE_READABLE) { + io_unread(fptr); + } return io; } - /* * call-seq: * ios.pos => integer @@ -621,7 +663,6 @@ rb_io_seek(io, offset, whence) GetOpenFile(io, fptr); pos = io_seek(fptr, pos, whence); if (pos < 0) rb_sys_fail(fptr->path); - clearerr(fptr->f); return INT2FIX(0); } @@ -685,7 +726,6 @@ rb_io_set_pos(io, offset) GetOpenFile(io, fptr); pos = io_seek(fptr, pos, SEEK_SET); if (pos < 0) rb_sys_fail(fptr->path); - clearerr(fptr->f); return OFFT2NUM(pos); } @@ -712,7 +752,6 @@ rb_io_rewind(io) GetOpenFile(io, fptr); if (io_seek(fptr, 0L, 0) < 0) rb_sys_fail(fptr->path); - clearerr(fptr->f); if (io == current_file) { gets_lineno -= fptr->lineno; } @@ -721,6 +760,36 @@ rb_io_rewind(io) return INT2FIX(0); } +static int +io_getc(OpenFile *fptr) +{ + int r; + if (fptr->rbuf == NULL) { + fptr->rbuf_off = 0; + fptr->rbuf_len = 0; + fptr->rbuf_capa = 8192; + fptr->rbuf = ALLOC_N(char, fptr->rbuf_capa); + } + if (fptr->rbuf_len == 0) { + retry: + TRAP_BEG; + r = read(fptr->fd, fptr->rbuf, fptr->rbuf_capa); + TRAP_END; /* xxx: signal handler may modify rbuf */ + if (r < 0) { + if (rb_io_wait_readable(fptr->fd)) + goto retry; + rb_sys_fail(fptr->path); + } + fptr->rbuf_off = 0; + fptr->rbuf_len = r; + if (r == 0) + return -1; /* EOF */ + } + fptr->rbuf_off++; + fptr->rbuf_len--; + return (unsigned char)fptr->rbuf[fptr->rbuf_off-1]; +} + /* * call-seq: * ios.eof => true or false @@ -744,18 +813,14 @@ rb_io_eof(io) GetOpenFile(io, fptr); rb_io_check_readable(fptr); - if (feof(fptr->f)) return Qtrue; - if (READ_DATA_PENDING(fptr->f)) return Qfalse; - READ_CHECK(fptr->f); - TRAP_BEG; - ch = getc(fptr->f); - TRAP_END; + if (READ_DATA_PENDING(fptr)) return Qfalse; + READ_CHECK(fptr); + ch = io_getc(fptr); if (ch != EOF) { - ungetc(ch, fptr->f); + io_ungetc(ch, fptr); return Qfalse; } - clearerr(fptr->f); return Qtrue; } @@ -831,13 +896,11 @@ rb_io_fsync(io) { #ifdef HAVE_FSYNC OpenFile *fptr; - FILE *f; GetOpenFile(io, fptr); - f = GetWriteFile(fptr); - io_fflush(f, fptr); - if (fsync(fileno(f)) < 0) + io_fflush(fptr); + if (fsync(fptr->fd) < 0) rb_sys_fail(fptr->path); return INT2FIX(0); #else @@ -866,7 +929,7 @@ rb_io_fileno(io) int fd; GetOpenFile(io, fptr); - fd = fileno(fptr->f); + fd = fptr->fd; return INT2FIX(fd); } @@ -923,7 +986,7 @@ rb_io_inspect(obj) if (!fptr || !fptr->path) return rb_any_to_s(obj); cname = rb_obj_classname(obj); len = strlen(cname) + strlen(fptr->path) + 5; - if (!(fptr->f || fptr->f2)) { + if (!fptr->f) { st = " (closed)"; len += 9; } @@ -948,24 +1011,17 @@ rb_io_to_io(io) /* reading functions */ static long -read_buffered_data(ptr, len, f) - char *ptr; - long len; - FILE *f; +read_buffered_data(char *ptr, long len, OpenFile *fptr) { long n; -#ifdef READ_DATA_PENDING_COUNT - n = READ_DATA_PENDING_COUNT(f); + n = READ_DATA_PENDING_COUNT(fptr); if (n <= 0) return 0; if (n > len) n = len; - return fread(ptr, 1, n, f); -#else - for (n = 0; n < len && READ_DATA_PENDING(f); ++n) { - *ptr++ = getc(f); - } + MEMMOVE(ptr, fptr->rbuf+fptr->rbuf_off, char, n); + fptr->rbuf_off += n; + fptr->rbuf_len -= n; return n; -#endif } long @@ -978,37 +1034,15 @@ io_fread(ptr, len, fptr) int c; while (n > 0) { - c = read_buffered_data(ptr, n, fptr->f); - if (c < 0) goto eof; + c = read_buffered_data(ptr, n, fptr); if (c > 0) { ptr += c; if ((n -= c) <= 0) break; } - rb_thread_wait_fd(fileno(fptr->f)); + rb_thread_wait_fd(fptr->fd); rb_io_check_closed(fptr); - TRAP_BEG; - c = getc(fptr->f); - TRAP_END; - if (c == EOF) { - eof: - if (ferror(fptr->f)) { - switch (errno) { - case EINTR: -#if defined(ERESTART) - case ERESTART: -#endif - clearerr(fptr->f); - continue; - case EAGAIN: -#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN - case EWOULDBLOCK: -#endif - if (len > n) { - clearerr(fptr->f); - } - } - if (len == n) return 0; - } + c = io_getc(fptr); + if (c < 0) { break; } *ptr++ = c; @@ -1025,8 +1059,8 @@ rb_io_fread(ptr, len, f) { OpenFile of; + of.fd = fileno(f); of.f = f; - of.f2 = NULL; of.mode = FMODE_READABLE; return io_fread(ptr, len, &of); } @@ -1045,8 +1079,7 @@ remain_size(fptr) off_t siz = BUFSIZ; off_t pos; - if (feof(fptr->f)) return 0; - if (fstat(fileno(fptr->f), &st) == 0 && S_ISREG(st.st_mode) + if (fstat(fptr->fd, &st) == 0 && S_ISREG(st.st_mode) #ifdef __BEOS__ && (st.st_dev > 3) #endif @@ -1081,14 +1114,11 @@ read_all(fptr, siz, str) } for (;;) { rb_str_locktmp(str); - READ_CHECK(fptr->f); + READ_CHECK(fptr); n = io_fread(RSTRING(str)->ptr+bytes, siz-bytes, fptr); rb_str_unlocktmp(str); if (n == 0 && bytes == 0) { - if (!fptr->f) break; - if (feof(fptr->f)) break; - if (!ferror(fptr->f)) break; - rb_sys_fail(fptr->path); + break; } bytes += n; if (bytes < siz) break; @@ -1186,20 +1216,20 @@ io_readpartial(argc, argv, io) if (len == 0) return str; - READ_CHECK(fptr->f); + READ_CHECK(fptr); if (RSTRING(str)->len != len) { modified: rb_raise(rb_eRuntimeError, "buffer string modified"); } - n = read_buffered_data(RSTRING(str)->ptr, len, fptr->f); + n = read_buffered_data(RSTRING(str)->ptr, len, fptr); if (n <= 0) { again: if (RSTRING(str)->len != len) goto modified; TRAP_BEG; - n = read(fileno(fptr->f), RSTRING(str)->ptr, len); + n = read(fptr->fd, RSTRING(str)->ptr, len); TRAP_END; if (n < 0) { - if (rb_io_wait_readable(fileno(fptr->f))) + if (rb_io_wait_readable(fptr->fd)) goto again; rb_sys_fail(fptr->path); } @@ -1260,11 +1290,10 @@ io_read(argc, argv, io) GetOpenFile(io, fptr); rb_io_check_readable(fptr); - if (feof(fptr->f)) return Qnil; if (len == 0) return str; rb_str_locktmp(str); - READ_CHECK(fptr->f); + READ_CHECK(fptr); if (RSTRING(str)->len != len) { rb_raise(rb_eRuntimeError, "buffer string modified"); } @@ -1272,11 +1301,8 @@ io_read(argc, argv, io) rb_str_unlocktmp(str); if (n == 0) { if (!fptr->f) return Qnil; - if (feof(fptr->f)) { - rb_str_resize(str, 0); - return Qnil; - } - if (len > 0) rb_sys_fail(fptr->path); + rb_str_resize(str, 0); + return Qnil; } rb_str_resize(str, n); RSTRING(str)->len = n; @@ -1292,20 +1318,13 @@ appendline(fptr, delim, strp) int delim; VALUE *strp; { - FILE *f = fptr->f; VALUE str = *strp; int c = EOF; -#ifndef READ_DATA_PENDING_PTR - char buf[8192]; - char *bp = buf, *bpe = buf + sizeof buf - 3; - int update = Qfalse; -#endif do { -#ifdef READ_DATA_PENDING_PTR - long pending = READ_DATA_PENDING_COUNT(f); + long pending = READ_DATA_PENDING_COUNT(fptr); if (pending > 0) { - const char *p = READ_DATA_PENDING_PTR(f); + const char *p = READ_DATA_PENDING_PTR(fptr); const char *e = memchr(p, delim, pending); long last = 0, len = (c != EOF); if (e) pending = e - p + 1; @@ -1322,7 +1341,7 @@ appendline(fptr, delim, strp) if (c != EOF) { RSTRING(str)->ptr[last++] = c; } - fread(RSTRING(str)->ptr + last, 1, pending, f); /* must not fail */ + read_buffered_data(RSTRING(str)->ptr + last, pending, fptr); /* must not fail */ if (e) return delim; } else if (c != EOF) { @@ -1335,47 +1354,14 @@ appendline(fptr, delim, strp) RSTRING(str)->ptr[RSTRING(str)->len++] = c; } } - rb_thread_wait_fd(fileno(f)); + rb_thread_wait_fd(fptr->fd); rb_io_check_closed(fptr); -#else - READ_CHECK(f); -#endif - TRAP_BEG; - c = getc(f); - TRAP_END; - if (c == EOF) { - if (ferror(f)) { - clearerr(f); - if (!rb_io_wait_readable(fileno(f))) - rb_sys_fail(fptr->path); - continue; - } -#ifdef READ_DATA_PENDING_PTR + c = io_getc(fptr); + if (c < 0) { return c; -#endif } -#ifndef READ_DATA_PENDING_PTR - if (c == EOF || (*bp++ = c) == delim || bp == bpe) { - int cnt = bp - buf; - - if (cnt > 0) { - if (!NIL_P(str)) - rb_str_cat(str, buf, cnt); - else - *strp = str = rb_str_new(buf, cnt); - } - if (c == EOF) { - if (update) - return (int)RSTRING(str)->ptr[RSTRING(str)->len-1]; - return c; - } - bp = buf; - } - update = Qtrue; -#endif } while (c != delim); -#ifdef READ_DATA_PENDING_PTR { char ch = c; if (!NIL_P(str)) { @@ -1385,7 +1371,6 @@ appendline(fptr, delim, strp) *strp = str = rb_str_new(&ch, 1); } } -#endif return c; } @@ -1395,33 +1380,26 @@ swallow(fptr, term) OpenFile *fptr; int term; { - FILE *f = fptr->f; int c; do { -#ifdef READ_DATA_PENDING_PTR long cnt; - while ((cnt = READ_DATA_PENDING_COUNT(f)) > 0) { + while ((cnt = READ_DATA_PENDING_COUNT(fptr)) > 0) { char buf[1024]; - const char *p = READ_DATA_PENDING_PTR(f); + const char *p = READ_DATA_PENDING_PTR(fptr); int i; if (cnt > sizeof buf) cnt = sizeof buf; if (*p != term) return Qtrue; i = cnt; while (--i && *++p == term); - if (!fread(buf, 1, cnt - i, f)) /* must not fail */ + if (!read_buffered_data(buf, cnt - i, fptr)) /* must not fail */ rb_sys_fail(fptr->path); } - rb_thread_wait_fd(fileno(f)); + rb_thread_wait_fd(fptr->fd); rb_io_check_closed(fptr); -#else - READ_CHECK(f); -#endif - TRAP_BEG; - c = getc(f); - TRAP_END; + c = io_getc(fptr); if (c != term) { - ungetc(c, f); + io_ungetc(c, fptr); return Qtrue; } } while (c != EOF); @@ -1782,22 +1760,13 @@ rb_io_each_byte(io) for (;;) { rb_io_check_readable(fptr); f = fptr->f; - READ_CHECK(f); - TRAP_BEG; - c = getc(f); - TRAP_END; - if (c == EOF) { - if (ferror(f)) { - clearerr(f); - if (!rb_io_wait_readable(fileno(f))) - rb_sys_fail(fptr->path); - continue; - } + READ_CHECK(fptr); + c = io_getc(fptr); + if (c < 0) { break; } rb_yield(INT2FIX(c & 0xff)); } - if (ferror(f)) rb_sys_fail(fptr->path); return io; } @@ -1825,19 +1794,10 @@ rb_io_getc(io) rb_io_check_readable(fptr); f = fptr->f; - retry: - READ_CHECK(f); - TRAP_BEG; - c = getc(f); - TRAP_END; + READ_CHECK(fptr); + c = io_getc(fptr); - if (c == EOF) { - if (ferror(f)) { - clearerr(f); - if (!rb_io_wait_readable(fileno(f))) - rb_sys_fail(fptr->path); - goto retry; - } + if (c < 0) { return Qnil; } return INT2FIX(c & 0xff); @@ -1847,6 +1807,7 @@ int rb_getc(f) FILE *f; { + /*xxx int c; if (!READ_DATA_PENDING(f)) { @@ -1857,6 +1818,8 @@ rb_getc(f) TRAP_END; return c; + */ + return -1; } /* @@ -1903,11 +1866,9 @@ rb_io_ungetc(io, c) int cc = NUM2INT(c); GetOpenFile(io, fptr); - if (!(fptr->mode & FMODE_RBUF)) - rb_raise(rb_eIOError, "unread stream"); rb_io_check_readable(fptr); - if (ungetc(cc, fptr->f) == EOF && cc != EOF) { + if (io_ungetc(cc, fptr) == EOF && cc != EOF) { rb_raise(rb_eIOError, "ungetc failed"); } return Qnil; @@ -1932,7 +1893,7 @@ rb_io_isatty(io) OpenFile *fptr; GetOpenFile(io, fptr); - if (isatty(fileno(fptr->f)) == 0) + if (isatty(fptr->fd) == 0) return Qfalse; return Qtrue; } @@ -1942,43 +1903,18 @@ fptr_finalize(fptr, noraise) OpenFile *fptr; int noraise; { - int n1 = 0, n2 = 0, f1, f2 = -1; - - if (fptr->f2) { - f2 = fileno(fptr->f2); - while (n2 = 0, fflush(fptr->f2) < 0) { - n2 = errno; - if (!rb_io_wait_writable(f2)) { - break; - } - if (!fptr->f2) break; - } - if (fclose(fptr->f2) < 0 && n2 == 0) { - n2 = errno; - } - fptr->f2 = 0; + if (fptr->wbuf_len) { + io_fflush(fptr); } - if (fptr->f) { - f1 = fileno(fptr->f); - if ((f2 == -1) && (fptr->mode & FMODE_WBUF)) { - while (n1 = 0, fflush(fptr->f) < 0) { - n1 = errno; - if (!rb_io_wait_writable(f1)) break; - if (!fptr->f) break; - } - } - if (fclose(fptr->f) < 0 && n1 == 0) { - n1 = errno; - } - fptr->f = 0; - if (n1 == EBADF && f1 == f2) { - n1 = 0; - } + if (fptr->f == stdin || fptr->f == stdout || fptr->f == stderr || fptr->fd <= 2) { + return; } - if (!noraise && (n1 || n2)) { - errno = (n1 ? n1 : n2); + if (fptr->f && fclose(fptr->f) < 0 && !noraise) { rb_sys_fail(fptr->path); } + fptr->fd = -1; + fptr->f = 0; + fptr->mode &= ~(FMODE_READABLE|FMODE_WRITABLE); } static void @@ -1999,16 +1935,19 @@ rb_io_fptr_finalize(fptr) OpenFile *fptr; { if (!fptr) return 0; - if (fptr->f == stdin || fptr->f == stdout || fptr->f == stderr) { - return 0; - } if (fptr->refcnt <= 0 || --fptr->refcnt) return 0; if (fptr->path) { free(fptr->path); fptr->path = 0; } - if ((fptr->f && fileno(fptr->f) > 2) || fptr->f2) { - rb_io_fptr_cleanup(fptr, Qtrue); + rb_io_fptr_cleanup(fptr, Qtrue); + if (fptr->rbuf) { + free(fptr->rbuf); + fptr->rbuf = 0; + } + if (fptr->wbuf) { + free(fptr->wbuf); + fptr->wbuf = 0; } free(fptr); return 1; @@ -2019,22 +1958,15 @@ rb_io_close(io) VALUE io; { OpenFile *fptr; - int fd, fd2; + int fd; fptr = RFILE(io)->fptr; if (!fptr) return Qnil; - if (fptr->f2) { - fd2 = fileno(fptr->f2); - } - else { - if (!fptr->f) return Qnil; - fd2 = -1; - } + if (!fptr->f) return Qnil; - fd = fileno(fptr->f); + fd = fptr->fd; rb_io_fptr_cleanup(fptr, Qfalse); rb_thread_fd_close(fd); - if (fd2 >= 0) rb_thread_fd_close(fd2); if (fptr->pid) { rb_syswait(fptr->pid); @@ -2101,7 +2033,7 @@ rb_io_closed(io) fptr = RFILE(io)->fptr; rb_io_check_initialized(fptr); - return (fptr->f || fptr->f2)?Qfalse:Qtrue; + return fptr->f ? Qfalse : Qtrue; } /* @@ -2127,25 +2059,26 @@ rb_io_close_read(io) VALUE io; { OpenFile *fptr; - int n; + struct stat sbuf; if (rb_safe_level() >= 4 && !OBJ_TAINTED(io)) { rb_raise(rb_eSecurityError, "Insecure: can't close"); } GetOpenFile(io, fptr); - if (fptr->f2 == 0 && (fptr->mode & FMODE_WRITABLE)) { + if (fstat(fptr->fd, &sbuf) < 0) + rb_sys_fail(fptr->path); + if (S_ISSOCK(sbuf.st_mode)) { + if (shutdown(fptr->fd, 0) < 0) + rb_sys_fail(fptr->path); + fptr->mode &= ~FMODE_READABLE; + if (!(fptr->mode & FMODE_WRITABLE)) + return rb_io_close(io); + return Qnil; + } + if (fptr->mode & FMODE_WRITABLE) { rb_raise(rb_eIOError, "closing non-duplex IO for reading"); } - if (fptr->f2 == 0) { - return rb_io_close(io); - } - n = fclose(fptr->f); - fptr->mode &= ~FMODE_READABLE; - fptr->f = fptr->f2; - fptr->f2 = 0; - if (n < 0) rb_sys_fail(fptr->path); - - return Qnil; + return rb_io_close(io); } /* @@ -2172,24 +2105,27 @@ rb_io_close_write(io) VALUE io; { OpenFile *fptr; - int n; + struct stat sbuf; if (rb_safe_level() >= 4 && !OBJ_TAINTED(io)) { rb_raise(rb_eSecurityError, "Insecure: can't close"); } GetOpenFile(io, fptr); - if (fptr->f2 == 0 && (fptr->mode & FMODE_READABLE)) { + if (fstat(fptr->fd, &sbuf) < 0) + rb_sys_fail(fptr->path); + if (S_ISSOCK(sbuf.st_mode)) { + if (shutdown(fptr->fd, 1) < 0) + rb_sys_fail(fptr->path); + fptr->mode &= ~FMODE_WRITABLE; + if (!(fptr->mode & FMODE_READABLE)) + return rb_io_close(io); + return Qnil; + } + + if (fptr->mode & FMODE_READABLE) { rb_raise(rb_eIOError, "closing non-duplex IO for writing"); } - if (fptr->f2 == 0) { - return rb_io_close(io); - } - n = fclose(fptr->f2); - fptr->f2 = 0; - fptr->mode &= ~FMODE_WRITABLE; - if (n < 0) rb_sys_fail(fptr->path); - - return Qnil; + return rb_io_close(io); } /* @@ -2221,15 +2157,14 @@ rb_io_sysseek(argc, argv, io) } pos = NUM2OFFT(offset); GetOpenFile(io, fptr); - if ((fptr->mode & FMODE_READABLE) && READ_DATA_BUFFERED(fptr->f)) { + if ((fptr->mode & FMODE_READABLE) && READ_DATA_BUFFERED(fptr)) { rb_raise(rb_eIOError, "sysseek for buffered IO"); } - if ((fptr->mode & FMODE_WRITABLE) && (fptr->mode & FMODE_WBUF)) { + if ((fptr->mode & FMODE_WRITABLE) && fptr->wbuf_len) { rb_warn("sysseek for buffered IO"); } - pos = lseek(fileno(fptr->f), pos, whence); + pos = lseek(fptr->fd, pos, whence); if (pos == -1) rb_sys_fail(fptr->path); - clearerr(fptr->f); return OFFT2NUM(pos); } @@ -2252,7 +2187,6 @@ rb_io_syswrite(io, str) VALUE io, str; { OpenFile *fptr; - FILE *f; long n; rb_secure(4); @@ -2261,15 +2195,14 @@ rb_io_syswrite(io, str) GetOpenFile(io, fptr); rb_io_check_writable(fptr); - f = GetWriteFile(fptr); - if (fptr->mode & FMODE_WBUF) { + if (fptr->wbuf_len) { rb_warn("syswrite for buffered IO"); } - if (!rb_thread_fd_writable(fileno(f))) { + if (!rb_thread_fd_writable(fptr->fd)) { rb_io_check_closed(fptr); } - n = write(fileno(f), RSTRING(str)->ptr, RSTRING(str)->len); + n = write(fptr->fd, RSTRING(str)->ptr, RSTRING(str)->len); if (n == -1) rb_sys_fail(fptr->path); @@ -2318,19 +2251,19 @@ rb_io_sysread(argc, argv, io) GetOpenFile(io, fptr); rb_io_check_readable(fptr); - if (READ_DATA_BUFFERED(fptr->f)) { + if (READ_DATA_BUFFERED(fptr)) { rb_raise(rb_eIOError, "sysread for buffered IO"); } rb_str_locktmp(str); - n = fileno(fptr->f); - rb_thread_wait_fd(fileno(fptr->f)); + n = fptr->fd; + rb_thread_wait_fd(fptr->fd); rb_io_check_closed(fptr); if (RSTRING(str)->len != ilen) { rb_raise(rb_eRuntimeError, "buffer string modified"); } TRAP_BEG; - n = read(fileno(fptr->f), RSTRING(str)->ptr, ilen); + n = read(fptr->fd, RSTRING(str)->ptr, ilen); TRAP_END; rb_str_unlocktmp(str); @@ -2365,18 +2298,14 @@ rb_io_binmode(io) OpenFile *fptr; GetOpenFile(io, fptr); - if (!(fptr->mode & FMODE_BINMODE) && READ_DATA_BUFFERED(fptr->f)) { + if (!(fptr->mode & FMODE_BINMODE) && READ_DATA_BUFFERED(fptr)) { rb_raise(rb_eIOError, "buffer already filled with text-mode content"); } #ifdef __human68k__ if (fptr->f) fmode(fptr->f, _IOBIN); - if (fptr->f2) - fmode(fptr->f2, _IOBIN); #else - if (fptr->f && setmode(fileno(fptr->f), O_BINARY) == -1) - rb_sys_fail(fptr->path); - if (fptr->f2 && setmode(fileno(fptr->f2), O_BINARY) == -1) + if (fptr->f && setmode(fptr->fd, O_BINARY) == -1) rb_sys_fail(fptr->path); #endif @@ -2636,6 +2565,7 @@ rb_fdopen(fd, mode) } } + /* xxx: should be _IONBF? A buffer in FILE may have trouble. */ #ifdef USE_SETVBUF if (setvbuf(file, NULL, _IOFBF, 0) != 0) rb_warn("setvbuf() can't be honoured (fd=%d)", fd); @@ -2653,7 +2583,10 @@ rb_file_open_internal(io, fname, mode) MakeOpenFile(io, fptr); fptr->mode = rb_io_mode_flags(mode); fptr->path = strdup(fname); - fptr->f = rb_fopen(fptr->path, rb_io_flags_mode(fptr->mode)); + fptr->fd = rb_sysopen(fptr->path, rb_io_mode_modenum(rb_io_flags_mode(fptr->mode)), 0666); + fptr->f = rb_fdopen(fptr->fd, rb_io_flags_mode(fptr->mode)); + if ((fptr->mode & FMODE_WRITABLE) && isatty(fptr->fd)) + fptr->mode |= FMODE_LINEBUF; return io; } @@ -2672,7 +2605,6 @@ rb_file_sysopen_internal(io, fname, flags, mode) int flags, mode; { OpenFile *fptr; - int fd; char *m; MakeOpenFile(io, fptr); @@ -2680,8 +2612,10 @@ rb_file_sysopen_internal(io, fname, flags, mode) fptr->path = strdup(fname); m = rb_io_modenum_mode(flags); fptr->mode = rb_io_modenum_flags(flags); - fd = rb_sysopen(fptr->path, flags, mode); - fptr->f = rb_fdopen(fd, m); + fptr->fd = rb_sysopen(fptr->path, flags, mode); + fptr->f = rb_fdopen(fptr->fd, m); + if ((fptr->mode & FMODE_WRITABLE) && isatty(fptr->fd)) + fptr->mode |= FMODE_LINEBUF; return io; } @@ -2762,10 +2696,8 @@ pipe_finalize(fptr, noraise) if (fptr->f) { status = pclose(fptr->f); } - if (fptr->f2) { - status = pclose(fptr->f2); - } - fptr->f = fptr->f2 = 0; + fptr->fd = -1; + fptr->f = 0; #if defined DJGPP status <<= 8; #endif @@ -2793,26 +2725,34 @@ rb_io_unbuffered(fptr) struct popen_arg { struct rb_exec_arg exec; - int pr[2], pw[2]; + int modef; + int pair[2]; }; static void popen_redirect(p) struct popen_arg *p; { - if (p->pr[1] != -1) { - close(p->pr[0]); - if (p->pr[1] != 1) { - dup2(p->pr[1], 1); - close(p->pr[1]); - } + if ((p->modef & FMODE_READABLE) && (p->modef & FMODE_WRITABLE)) { + close(p->pair[0]); + dup2(p->pair[1], 0); + dup2(p->pair[1], 1); + if (2 <= p->pair[1]) + close(p->pair[1]); } - if (p->pw[0] != -1) { - close(p->pw[1]); - if (p->pw[0] != 0) { - dup2(p->pw[0], 0); - close(p->pw[0]); - } + else if (p->modef & FMODE_READABLE) { + close(p->pair[0]); + if (p->pair[1] != 1) { + dup2(p->pair[1], 1); + close(p->pair[1]); + } + } + else { + close(p->pair[1]); + if (p->pair[0] != 0) { + dup2(p->pair[0], 0); + close(p->pair[0]); + } } } @@ -2855,6 +2795,7 @@ pipe_open(argc, argv, mode) char *exename = NULL; #endif char *cmd; + FILE *fp; prog = rb_check_argv(argc, argv); if (!prog) { @@ -2867,22 +2808,26 @@ pipe_open(argc, argv, mode) doexec = (strcmp("-", cmd) != 0); if (!doexec) { fflush(stdin); /* is it really needed? */ - fflush(stdout); - fflush(stderr); + rb_io_flush(rb_stdout); + rb_io_flush(rb_stderr); } - arg.pr[0] = arg.pr[1] = arg.pw[0] = arg.pw[1] = -1; - if ((modef & FMODE_READABLE) && pipe(arg.pr) == -1) { - rb_sys_fail(cmd); + arg.modef = modef; + arg.pair[0] = arg.pair[1] = -1; + if ((modef & FMODE_READABLE) && (modef & FMODE_WRITABLE)) { + if (socketpair(AF_UNIX, SOCK_STREAM, 0, arg.pair) < 0) + rb_sys_fail(cmd); } - if ((modef & FMODE_WRITABLE) && pipe(arg.pw) == -1) { - if (modef & FMODE_READABLE) { - int e = errno; - close(arg.pr[0]); close(arg.pr[1]); - errno = e; - } - rb_sys_fail(cmd); + else if (modef & FMODE_READABLE) { + if (pipe(arg.pair) < 0) + rb_sys_fail(cmd); + } + else if (modef & FMODE_WRITABLE) { + if (pipe(arg.pair) < 0) + rb_sys_fail(cmd); + } + else { + rb_sys_fail(cmd); } - if (doexec) { arg.exec.argc = argc; arg.exec.argv = argv; @@ -2900,16 +2845,25 @@ pipe_open(argc, argv, mode) } /* parent */ - if (modef & FMODE_READABLE) close(arg.pr[1]); - if (modef & FMODE_WRITABLE) close(arg.pw[0]); if (pid == -1) { int e = errno; - if (modef & FMODE_READABLE) close(arg.pr[0]); - if (modef & FMODE_WRITABLE) close(arg.pw[1]); + close(arg.pair[0]); + close(arg.pair[1]); errno = e; rb_sys_fail(cmd); } -#define PIPE_FDOPEN(i) (rb_fdopen((i?arg.pw:arg.pr)[i], i?"w":"r")) + if ((modef & FMODE_READABLE) && (modef & FMODE_WRITABLE)) { + close(arg.pair[1]); + fp = rb_fdopen(arg.pair[0], "r+"); + } + else if (modef & FMODE_READABLE) { + close(arg.pair[1]); + fp = rb_fdopen(arg.pair[0], "r"); + } + else { + close(arg.pair[0]); + fp = rb_fdopen(arg.pair[1], "w"); + } #elif defined(_WIN32) if (argc) { char **args = ALLOCA_N(char *, argc+1); @@ -2943,25 +2897,18 @@ pipe_open(argc, argv, mode) #define PIPE_FDOPEN(i) (i?fpw:fpr) #else prog = rb_ary_join(rb_ary_new4(argc, argv), rb_str_new2(" ")); - fpr = popen(StringValueCStr(prog), mode); + fp = popen(StringValueCStr(prog), mode); - if (!fpr) rb_sys_fail(RSTRING(prog)->ptr); -#define PIPE_FDOPEN(i) (fpr) + if (!fp) rb_sys_fail(RSTRING(prog)->ptr); #endif port = io_alloc(rb_cIO); MakeOpenFile(port, fptr); + fptr->f = fp; + fptr->fd = fileno(fp); fptr->mode = modef | FMODE_SYNC; fptr->pid = pid; - if (modef & FMODE_READABLE) { - fptr->f = PIPE_FDOPEN(0); - } - if (modef & FMODE_WRITABLE) { - FILE *fpwt = PIPE_FDOPEN(1); - if (fptr->f) fptr->f2 = fpwt; - else fptr->f = fpwt; - } #if defined (__CYGWIN__) || !defined(HAVE_FORK) fptr->finalize = pipe_finalize; pipe_add_fptr(fptr); @@ -3052,8 +2999,8 @@ rb_io_s_popen(argc, argv, klass) /* child */ if (rb_block_given_p()) { rb_yield(Qnil); - fflush(stdout); - fflush(stderr); + rb_io_flush(rb_stdout); + rb_io_flush(rb_stderr); _exit(0); } return Qnil; @@ -3323,14 +3270,11 @@ io_reopen(io, nfile) if (orig->mode & FMODE_READABLE) { pos = io_tell(orig); } - if (orig->f2) { - io_fflush(orig->f2, orig); - } - else if (orig->mode & FMODE_WRITABLE) { - io_fflush(orig->f, orig); + if (orig->mode & FMODE_WRITABLE) { + io_fflush(orig); } if (fptr->mode & FMODE_WRITABLE) { - io_fflush(GetWriteFile(fptr), fptr); + io_fflush(fptr); } /* copy OpenFile structure */ @@ -3343,12 +3287,11 @@ io_reopen(io, nfile) fptr->finalize = orig->finalize; mode = rb_io_mode_string(fptr); - fd = fileno(fptr->f); - fd2 = fileno(orig->f); + fd = fptr->fd; + fd2 = orig->fd; if (fd != fd2) { #if !defined __CYGWIN__ if (fptr->f == stdin || fptr->f == stdout || fptr->f == stderr) { - clearerr(fptr->f); /* need to keep stdio objects */ if (dup2(fd2, fd) < 0) rb_sys_fail(orig->path); @@ -3373,22 +3316,6 @@ io_reopen(io, nfile) } } - if (fptr->f2 && fd != fileno(fptr->f2)) { - fd = fileno(fptr->f2); - if (!orig->f2) { - fclose(fptr->f2); - rb_thread_fd_close(fd); - fptr->f2 = 0; - } - else if (fd != (fd2 = fileno(orig->f2))) { - fclose(fptr->f2); - rb_thread_fd_close(fd); - if (dup2(fd2, fd) < 0) - rb_sys_fail(orig->path); - fptr->f2 = rb_fdopen(fd, "w"); - } - } - if (fptr->mode & FMODE_BINMODE) { rb_io_binmode(io); } @@ -3451,11 +3378,8 @@ rb_io_reopen(argc, argv, file) fptr->path = strdup(RSTRING(fname)->ptr); mode = rb_io_flags_mode(fptr->mode); if (!fptr->f) { - fptr->f = rb_fopen(fptr->path, mode); - if (fptr->f2) { - fclose(fptr->f2); - fptr->f2 = 0; - } + fptr->fd = rb_sysopen(fptr->path, rb_io_mode_modenum(mode), 0666); + fptr->f = rb_fdopen(fptr->fd, mode); return file; } @@ -3467,12 +3391,6 @@ rb_io_reopen(argc, argv, file) rb_warn("setvbuf() can't be honoured for %s", RSTRING(fname)->ptr); #endif - if (fptr->f2) { - if (freopen(RSTRING(fname)->ptr, "w", fptr->f2) == 0) { - rb_sys_fail(fptr->path); - } - } - return file; } @@ -3490,16 +3408,7 @@ rb_io_init_copy(dest, io) GetOpenFile(io, orig); MakeOpenFile(dest, fptr); - if (orig->f2) { - io_fflush(orig->f2, orig); - fseeko(orig->f, 0L, SEEK_CUR); - } - else if (orig->mode & FMODE_WRITABLE) { - io_fflush(orig->f, orig); - } - else { - fseeko(orig->f, 0L, SEEK_CUR); - } + rb_io_flush(io); /* copy OpenFile structure */ fptr->mode = orig->mode; @@ -3515,20 +3424,12 @@ rb_io_init_copy(dest, io) case FMODE_WRITABLE: mode = "w"; break; case FMODE_READWRITE: - if (orig->f2) mode = "r"; - else mode = "r+"; - break; + mode = "r+"; break; } - fd = ruby_dup(fileno(orig->f)); + fd = ruby_dup(orig->fd); + fptr->fd = fd; fptr->f = rb_fdopen(fd, mode); - fseeko(fptr->f, ftello(orig->f), SEEK_SET); - if (orig->f2) { - if (fileno(orig->f) != fileno(orig->f2)) { - fd = ruby_dup(fileno(orig->f2)); - } - fptr->f2 = rb_fdopen(fd, "w"); - fseeko(fptr->f2, ftello(orig->f2), SEEK_SET); - } + io_seek(fptr, io_tell(orig), SEEK_SET); if (fptr->mode & FMODE_BINMODE) { rb_io_binmode(dest); } @@ -3957,14 +3858,23 @@ prep_stdio(f, mode, klass) VALUE io = io_alloc(klass); MakeOpenFile(io, fp); + fp->fd = fileno(f); #ifdef __CYGWIN__ - if (!isatty(fileno(f))) { + if (!isatty(fp->fd)) { mode |= O_BINARY; - setmode(fileno(f), O_BINARY); + setmode(fp->fd, O_BINARY); } #endif fp->f = f; fp->mode = mode; + if (fp->mode & FMODE_WRITABLE) { + if (fp->fd == 2) { /* stderr must be unbuffered */ + fp->mode |= FMODE_SYNC; + } + if (isatty(fp->fd)) { + fp->mode |= FMODE_LINEBUF; + } + } return io; } @@ -4035,8 +3945,11 @@ rb_io_initialize(argc, argv, io) #endif } MakeOpenFile(io, fp); + fp->fd = fd; fp->mode = rb_io_modenum_flags(flags); fp->f = rb_fdopen(fd, rb_io_modenum_mode(flags)); + if ((fp->mode & FMODE_WRITABLE) && isatty(fp->fd)) + fp->mode |= FMODE_LINEBUF; } else if (RFILE(io)->fptr) { rb_raise(rb_eRuntimeError, "reinitializing IO"); @@ -4559,12 +4472,12 @@ rb_f_select(argc, argv, obj) FD_ZERO(rp); for (i=0; ilen; i++) { GetOpenFile(rb_io_get_io(RARRAY(read)->ptr[i]), fptr); - FD_SET(fileno(fptr->f), rp); - if (READ_DATA_PENDING(fptr->f)) { /* check for buffered data */ + FD_SET(fptr->fd, rp); + if (READ_DATA_PENDING(fptr)) { /* check for buffered data */ pending++; - FD_SET(fileno(fptr->f), &pset); + FD_SET(fptr->fd, &pset); } - if (max < fileno(fptr->f)) max = fileno(fptr->f); + if (max < fptr->fd) max = fptr->fd; } if (pending) { /* no blocking if there's buffered data */ timerec.tv_sec = timerec.tv_usec = 0; @@ -4580,12 +4493,8 @@ rb_f_select(argc, argv, obj) FD_ZERO(wp); for (i=0; ilen; i++) { GetOpenFile(rb_io_get_io(RARRAY(write)->ptr[i]), fptr); - FD_SET(fileno(fptr->f), wp); - if (max < fileno(fptr->f)) max = fileno(fptr->f); - if (fptr->f2) { - FD_SET(fileno(fptr->f2), wp); - if (max < fileno(fptr->f2)) max = fileno(fptr->f2); - } + FD_SET(fptr->fd, wp); + if (max < fptr->fd) max = fptr->fd; } } else @@ -4597,12 +4506,8 @@ rb_f_select(argc, argv, obj) FD_ZERO(ep); for (i=0; ilen; i++) { GetOpenFile(rb_io_get_io(RARRAY(except)->ptr[i]), fptr); - FD_SET(fileno(fptr->f), ep); - if (max < fileno(fptr->f)) max = fileno(fptr->f); - if (fptr->f2) { - FD_SET(fileno(fptr->f2), ep); - if (max < fileno(fptr->f2)) max = fileno(fptr->f2); - } + FD_SET(fptr->fd, ep); + if (max < fptr->fd) max = fptr->fd; } } else { @@ -4627,8 +4532,8 @@ rb_f_select(argc, argv, obj) list = RARRAY(res)->ptr[0]; for (i=0; i< RARRAY(read)->len; i++) { GetOpenFile(rb_io_get_io(RARRAY(read)->ptr[i]), fptr); - if (FD_ISSET(fileno(fptr->f), rp) - || FD_ISSET(fileno(fptr->f), &pset)) { + if (FD_ISSET(fptr->fd, rp) + || FD_ISSET(fptr->fd, &pset)) { rb_ary_push(list, RARRAY(read)->ptr[i]); } } @@ -4638,10 +4543,7 @@ rb_f_select(argc, argv, obj) list = RARRAY(res)->ptr[1]; for (i=0; i< RARRAY(write)->len; i++) { GetOpenFile(rb_io_get_io(RARRAY(write)->ptr[i]), fptr); - if (FD_ISSET(fileno(fptr->f), wp)) { - rb_ary_push(list, RARRAY(write)->ptr[i]); - } - else if (fptr->f2 && FD_ISSET(fileno(fptr->f2), wp)) { + if (FD_ISSET(fptr->fd, wp)) { rb_ary_push(list, RARRAY(write)->ptr[i]); } } @@ -4651,10 +4553,7 @@ rb_f_select(argc, argv, obj) list = RARRAY(res)->ptr[2]; for (i=0; i< RARRAY(except)->len; i++) { GetOpenFile(rb_io_get_io(RARRAY(except)->ptr[i]), fptr); - if (FD_ISSET(fileno(fptr->f), ep)) { - rb_ary_push(list, RARRAY(except)->ptr[i]); - } - else if (fptr->f2 && FD_ISSET(fileno(fptr->f2), ep)) { + if (FD_ISSET(fptr->fd, ep)) { rb_ary_push(list, RARRAY(except)->ptr[i]); } } @@ -4746,17 +4645,12 @@ rb_io_ctl(io, req, arg, io_p) } } GetOpenFile(io, fptr); - retval = io_cntl(fileno(fptr->f), cmd, narg, io_p); + retval = io_cntl(fptr->fd, cmd, narg, io_p); if (retval < 0) rb_sys_fail(fptr->path); if (TYPE(arg) == T_STRING && RSTRING(arg)->ptr[len] != 17) { rb_raise(rb_eArgError, "return value overflowed string"); } - if (fptr->f2 && fileno(fptr->f) != fileno(fptr->f2)) { - /* call on f2 too; ignore result */ - io_cntl(fileno(fptr->f2), cmd, narg, io_p); - } - return INT2NUM(retval); #else rb_notimplement(); @@ -5527,6 +5421,7 @@ Init_IO() id_write = rb_intern("write"); id_read = rb_intern("read"); id_getc = rb_intern("getc"); + id_flush = rb_intern("flush"); rb_define_global_function("syscall", rb_f_syscall, -1); diff --git a/process.c b/process.c index 9970383748..ca37d87291 100644 --- a/process.c +++ b/process.c @@ -1349,8 +1349,8 @@ rb_fork(status, chfunc, charg) #endif #ifndef __VMS - fflush(stdout); - fflush(stderr); + rb_io_flush(rb_stdout); + rb_io_flush(rb_stderr); #endif #ifdef FD_CLOEXEC diff --git a/rubyio.h b/rubyio.h index 200232939f..52ce3790b6 100644 --- a/rubyio.h +++ b/rubyio.h @@ -21,14 +21,22 @@ #endif typedef struct OpenFile { + int fd; FILE *f; /* stdio ptr for read/write */ - FILE *f2; /* additional ptr for rw pipes */ int mode; /* mode flags */ int pid; /* child's pid (for pipes) */ int lineno; /* number of lines read */ char *path; /* pathname for file */ void (*finalize) _((struct OpenFile*,int)); /* finalize proc */ long refcnt; + char *wbuf; + int wbuf_off; + int wbuf_len; + int wbuf_capa; + char *rbuf; + int rbuf_off; + int rbuf_len; + int rbuf_capa; } OpenFile; #define FMODE_READABLE 1 @@ -38,8 +46,8 @@ typedef struct OpenFile { #define FMODE_CREATE 128 #define FMODE_BINMODE 4 #define FMODE_SYNC 8 -#define FMODE_WBUF 16 -#define FMODE_RBUF 32 +#define FMODE_LINEBUF 16 +#define FMODE_UNSEEKABLE 32 #define GetOpenFile(obj,fp) rb_io_check_closed((fp) = RFILE(rb_io_taint_check(obj))->fptr) @@ -51,23 +59,29 @@ typedef struct OpenFile { }\ fp = 0;\ fp = RFILE(obj)->fptr = ALLOC(OpenFile);\ - fp->f = fp->f2 = NULL;\ + fp->fd = -1;\ + fp->f = NULL;\ fp->mode = 0;\ fp->pid = 0;\ fp->lineno = 0;\ fp->path = NULL;\ fp->finalize = 0;\ fp->refcnt = 1;\ + fp->wbuf = NULL;\ + fp->wbuf_off = 0;\ + fp->wbuf_len = 0;\ + fp->wbuf_capa = 0;\ + fp->rbuf = NULL;\ + fp->rbuf_off = 0;\ + fp->rbuf_len = 0;\ + fp->rbuf_capa = 0;\ } while (0) #define GetReadFile(fptr) ((fptr)->f) -#define GetWriteFile(fptr) (((fptr)->f2) ? (fptr)->f2 : (fptr)->f) +#define GetWriteFile(fptr) ((fptr)->f) FILE *rb_fopen _((const char*, const char*)); FILE *rb_fdopen _((int, const char*)); -int rb_getc _((FILE*)); -long rb_io_fread _((char *, long, FILE *)); -long rb_io_fwrite _((const char *, long, FILE *)); int rb_io_mode_flags _((const char*)); int rb_io_modenum_flags _((int)); void rb_io_check_writable _((OpenFile*)); @@ -82,6 +96,32 @@ int rb_io_wait_writable _((int)); VALUE rb_io_taint_check _((VALUE)); NORETURN(void rb_eof_error _((void))); -void rb_read_check _((FILE*)); -int rb_read_pending _((FILE*)); +void rb_io_read_check _((OpenFile*)); +int rb_io_read_pending _((OpenFile*)); + +int rb_getc _((FILE*)) +#ifdef __GNUC__ + __attribute__ ((deprecated)) +#endif + ; +long rb_io_fread _((char *, long, FILE *)) +#ifdef __GNUC__ + __attribute__ ((deprecated)) +#endif + ; +long rb_io_fwrite _((const char *, long, FILE *)) +#ifdef __GNUC__ + __attribute__ ((deprecated)) +#endif + ; +void rb_read_check _((FILE*)) +#ifdef __GNUC__ + __attribute__ ((deprecated)) +#endif + ; +int rb_read_pending _((FILE*)) +#ifdef __GNUC__ + __attribute__ ((deprecated)) +#endif + ; #endif diff --git a/test/ruby/ut_eof.rb b/test/ruby/ut_eof.rb index eff0bddc0b..bf03771fc3 100644 --- a/test/ruby/ut_eof.rb +++ b/test/ruby/ut_eof.rb @@ -6,8 +6,8 @@ module TestEOF assert_equal("", f.read(0)) assert_equal("", f.read(0)) assert_equal("", f.read) - assert_nil(f.read(0)) - assert_nil(f.read(0)) + assert_equal("", f.read(0)) + assert_equal("", f.read(0)) } open_file("") {|f| assert_nil(f.read(1)) @@ -43,8 +43,8 @@ module TestEOF assert_equal("" , f.read(0)) assert_equal("" , f.read(0)) assert_equal("", f.read) - assert_nil(f.read(0)) - assert_nil(f.read(0)) + assert_equal("", f.read(0)) + assert_equal("", f.read(0)) } open_file("a") {|f| assert_equal("a", f.read(1)) @@ -69,7 +69,7 @@ module TestEOF } open_file("a") {|f| assert_equal("a", f.read) - assert_nil(f.read(0)) + assert_equal("", f.read(0)) } open_file("a") {|f| s = "x" @@ -96,7 +96,7 @@ module TestEOF assert_equal(10, f.pos) assert_equal("", f.read(0)) assert_equal("", f.read) - assert_nil(f.read(0)) + assert_equal("", f.read(0)) assert_equal("", f.read) } end