summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog9
-rw-r--r--ext/io/wait/wait.c16
-rw-r--r--ext/openssl/ossl_ssl.c4
-rw-r--r--ext/pty/pty.c6
-rw-r--r--ext/socket/socket.c75
-rw-r--r--ext/stringio/stringio.c17
-rw-r--r--file.c27
-rw-r--r--intern.h1
-rw-r--r--io.c929
-rw-r--r--process.c4
-rw-r--r--rubyio.h60
-rw-r--r--test/ruby/ut_eof.rb12
12 files changed, 539 insertions, 621 deletions
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 <akr@m17n.org>
+
+ * 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 <nobu@ruby-lang.org>
* 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 <sys/fcntl.h>
#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 <ctype.h>
#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
#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
-
-#ifndef READ_DATA_PENDING_PTR
-# ifdef FILE_READPTR
-# define READ_DATA_PENDING_PTR(fp) ((char *)(fp)->FILE_READPTR)
-# endif
-#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)
-#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);
+ 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;
+ }
+ 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;
}
- fptr->mode &= ~FMODE_WBUF;
+ 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)) {
- rb_raise(rb_eIOError, "closing non-duplex IO for reading");
+ 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->f2 == 0) {
- return rb_io_close(io);
+ if (fptr->mode & FMODE_WRITABLE) {
+ rb_raise(rb_eIOError, "closing non-duplex IO for reading");
}
- 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)) {
- rb_raise(rb_eIOError, "closing non-duplex IO for writing");
- }
- if (fptr->f2 == 0) {
- return rb_io_close(io);
+ 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;
}
- n = fclose(fptr->f2);
- fptr->f2 = 0;
- fptr->mode &= ~FMODE_WRITABLE;
- if (n < 0) rb_sys_fail(fptr->path);
- return Qnil;
+ if (fptr->mode & FMODE_READABLE) {
+ rb_raise(rb_eIOError, "closing non-duplex IO for writing");
+ }
+ 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]);
+ }
+ else if (p->modef & FMODE_READABLE) {
+ close(p->pair[0]);
+ if (p->pair[1] != 1) {
+ dup2(p->pair[1], 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 {
+ 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; i<RARRAY(read)->len; 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; i<RARRAY(write)->len; 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; i<RARRAY(except)->len; 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