aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNARUSE, Yui <naruse@airemix.jp>2023-06-01 08:43:22 +0900
committerNARUSE, Yui <naruse@airemix.jp>2023-06-01 08:43:22 +0900
commit85dcc4866d9ff29834596e9186cc97d622ee06f8 (patch)
treed5daa60146c5c8c2de9a9459a05e6e771d934362
parente4163112f6b99d9c205f6bc260878dcb00954a13 (diff)
downloadruby-85dcc4866d9ff29834596e9186cc97d622ee06f8.tar.gz
Revert "Hide most of the implementation of `struct rb_io`. (#6511)"
This reverts commit 18e55fc1e1ec20e8f3166e3059e76c885fc9f8f2. fix [Bug #19704] https://bugs.ruby-lang.org/issues/19704 This breaks compatibility for extension libraries. Such changes need a discussion.
-rw-r--r--common.mk1
-rw-r--r--debug.c2
-rw-r--r--ext/objspace/depend1
-rw-r--r--ext/objspace/objspace_dump.c1
-rw-r--r--ext/pty/pty.c54
-rw-r--r--ext/stringio/stringio.c4
-rw-r--r--file.c1
-rw-r--r--include/ruby/internal/core/rfile.h9
-rw-r--r--include/ruby/io.h159
-rw-r--r--internal/io.h119
-rw-r--r--io.c142
-rw-r--r--process.c1
-rw-r--r--spec/ruby/optional/capi/ext/io_spec.c10
-rw-r--r--win32/win32.c5
14 files changed, 211 insertions, 298 deletions
diff --git a/common.mk b/common.mk
index 71ae5eb6e6..ec13d25ca2 100644
--- a/common.mk
+++ b/common.mk
@@ -10997,7 +10997,6 @@ process.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
process.$(OBJEXT): $(top_srcdir)/internal/gc.h
process.$(OBJEXT): $(top_srcdir)/internal/hash.h
process.$(OBJEXT): $(top_srcdir)/internal/imemo.h
-process.$(OBJEXT): $(top_srcdir)/internal/io.h
process.$(OBJEXT): $(top_srcdir)/internal/numeric.h
process.$(OBJEXT): $(top_srcdir)/internal/object.h
process.$(OBJEXT): $(top_srcdir)/internal/process.h
diff --git a/debug.c b/debug.c
index b5cba590ba..d3f41f1a3a 100644
--- a/debug.c
+++ b/debug.c
@@ -70,7 +70,7 @@ const union {
RUBY_FMODE_NOREVLOOKUP = 0x00000100,
RUBY_FMODE_TRUNC = FMODE_TRUNC,
RUBY_FMODE_TEXTMODE = FMODE_TEXTMODE,
- RUBY_FMODE_EXTERNAL = 0x00010000,
+ RUBY_FMODE_PREP = 0x00010000,
RUBY_FMODE_SETENC_BY_BOM = FMODE_SETENC_BY_BOM,
RUBY_FMODE_UNIX = 0x00200000,
RUBY_FMODE_INET = 0x00400000,
diff --git a/ext/objspace/depend b/ext/objspace/depend
index 3cdfaffa66..91ae569d67 100644
--- a/ext/objspace/depend
+++ b/ext/objspace/depend
@@ -580,7 +580,6 @@ objspace_dump.o: $(top_srcdir)/internal/compilers.h
objspace_dump.o: $(top_srcdir)/internal/gc.h
objspace_dump.o: $(top_srcdir)/internal/hash.h
objspace_dump.o: $(top_srcdir)/internal/imemo.h
-objspace_dump.o: $(top_srcdir)/internal/io.h
objspace_dump.o: $(top_srcdir)/internal/sanitizers.h
objspace_dump.o: $(top_srcdir)/internal/serial.h
objspace_dump.o: $(top_srcdir)/internal/static_assert.h
diff --git a/ext/objspace/objspace_dump.c b/ext/objspace/objspace_dump.c
index 39584e03b8..d8a11083d6 100644
--- a/ext/objspace/objspace_dump.c
+++ b/ext/objspace/objspace_dump.c
@@ -18,7 +18,6 @@
#include "internal/class.h"
#include "internal/gc.h"
#include "internal/hash.h"
-#include "internal/io.h"
#include "internal/string.h"
#include "internal/sanitizers.h"
#include "symbol.h"
diff --git a/ext/pty/pty.c b/ext/pty/pty.c
index 0aca10bfa0..acec33f9bf 100644
--- a/ext/pty/pty.c
+++ b/ext/pty/pty.c
@@ -448,10 +448,8 @@ pty_close_pty(VALUE assoc)
for (i = 0; i < 2; i++) {
io = rb_ary_entry(assoc, i);
- if (RB_TYPE_P(io, T_FILE)) {
- /* it's OK to call rb_io_close again even if it's already closed */
+ if (RB_TYPE_P(io, T_FILE) && 0 <= RFILE(io)->fptr->fd)
rb_io_close(io);
- }
}
return Qnil;
}
@@ -501,21 +499,28 @@ pty_open(VALUE klass)
{
int master_fd, slave_fd;
char slavename[DEVICELEN];
+ VALUE master_io, slave_file;
+ rb_io_t *master_fptr, *slave_fptr;
+ VALUE assoc;
getDevice(&master_fd, &slave_fd, slavename, 1);
- VALUE master_path = rb_obj_freeze(rb_sprintf("masterpty:%s", slavename));
- VALUE master_io = rb_io_open_descriptor(rb_cIO, master_fd, FMODE_READWRITE | FMODE_SYNC | FMODE_DUPLEX, master_path, RUBY_IO_TIMEOUT_DEFAULT, NULL);
-
- VALUE slave_path = rb_obj_freeze(rb_str_new_cstr(slavename));
- VALUE slave_file = rb_io_open_descriptor(rb_cFile, slave_fd, FMODE_READWRITE | FMODE_SYNC | FMODE_DUPLEX | FMODE_TTY, slave_path, RUBY_IO_TIMEOUT_DEFAULT, NULL);
+ master_io = rb_obj_alloc(rb_cIO);
+ MakeOpenFile(master_io, master_fptr);
+ master_fptr->mode = FMODE_READWRITE | FMODE_SYNC | FMODE_DUPLEX;
+ master_fptr->fd = master_fd;
+ master_fptr->pathv = rb_obj_freeze(rb_sprintf("masterpty:%s", slavename));
- VALUE assoc = rb_assoc_new(master_io, slave_file);
+ slave_file = rb_obj_alloc(rb_cFile);
+ MakeOpenFile(slave_file, slave_fptr);
+ slave_fptr->mode = FMODE_READWRITE | FMODE_SYNC | FMODE_DUPLEX | FMODE_TTY;
+ slave_fptr->fd = slave_fd;
+ slave_fptr->pathv = rb_obj_freeze(rb_str_new_cstr(slavename));
+ assoc = rb_assoc_new(master_io, slave_file);
if (rb_block_given_p()) {
return rb_ensure(rb_yield, assoc, pty_close_pty, assoc);
}
-
return assoc;
}
@@ -572,27 +577,30 @@ pty_getpty(int argc, VALUE *argv, VALUE self)
{
VALUE res;
struct pty_info info;
+ rb_io_t *wfptr,*rfptr;
+ VALUE rport = rb_obj_alloc(rb_cFile);
+ VALUE wport = rb_obj_alloc(rb_cFile);
char SlaveName[DEVICELEN];
+ MakeOpenFile(rport, rfptr);
+ MakeOpenFile(wport, wfptr);
+
establishShell(argc, argv, &info, SlaveName);
- VALUE pty_path = rb_obj_freeze(rb_str_new_cstr(SlaveName));
- VALUE rport = rb_io_open_descriptor(
- rb_cFile, info.fd, FMODE_READABLE, pty_path, RUBY_IO_TIMEOUT_DEFAULT, NULL
- );
+ rfptr->mode = rb_io_modestr_fmode("r");
+ rfptr->fd = info.fd;
+ rfptr->pathv = rb_obj_freeze(rb_str_new_cstr(SlaveName));
- int wpty_fd = rb_cloexec_dup(info.fd);
- if (wpty_fd == -1) {
+ wfptr->mode = rb_io_modestr_fmode("w") | FMODE_SYNC;
+ wfptr->fd = rb_cloexec_dup(info.fd);
+ if (wfptr->fd == -1)
rb_sys_fail("dup()");
- }
- VALUE wport = rb_io_open_descriptor(
- rb_cFile, wpty_fd, FMODE_WRITABLE | FMODE_TRUNC | FMODE_CREATE | FMODE_SYNC,
- pty_path, RUBY_IO_TIMEOUT_DEFAULT, NULL
- );
+ rb_update_max_fd(wfptr->fd);
+ wfptr->pathv = rfptr->pathv;
res = rb_ary_new2(3);
- rb_ary_store(res, 0, rport);
- rb_ary_store(res, 1, wport);
+ rb_ary_store(res,0,(VALUE)rport);
+ rb_ary_store(res,1,(VALUE)wport);
rb_ary_store(res,2,PIDT2NUM(info.child_pid));
if (rb_block_given_p()) {
diff --git a/ext/stringio/stringio.c b/ext/stringio/stringio.c
index cb9dbece1c..e69afc31f1 100644
--- a/ext/stringio/stringio.c
+++ b/ext/stringio/stringio.c
@@ -276,7 +276,7 @@ strio_init(int argc, VALUE *argv, struct StringIO *ptr, VALUE self)
{
VALUE string, vmode, opt;
int oflags;
- struct rb_io_encoding convconfig;
+ struct rb_io_enc_t convconfig;
argc = rb_scan_args(argc, argv, "02:", &string, &vmode, &opt);
rb_io_extract_modeenc(&vmode, 0, opt, &oflags, &ptr->flags, &convconfig);
@@ -1743,7 +1743,7 @@ strio_set_encoding(int argc, VALUE *argv, VALUE self)
else {
enc = rb_find_encoding(ext_enc);
if (!enc) {
- struct rb_io_encoding convconfig;
+ struct rb_io_enc_t convconfig;
int oflags, fmode;
VALUE vmode = rb_str_append(rb_str_new_cstr("r:"), ext_enc);
rb_io_extract_modeenc(&vmode, 0, Qnil, &oflags, &fmode, &convconfig);
diff --git a/file.c b/file.c
index 5f59373a45..2c74f3eff5 100644
--- a/file.c
+++ b/file.c
@@ -169,6 +169,7 @@ int flock(int, int);
#include "internal/thread.h"
#include "internal/vm.h"
#include "ruby/encoding.h"
+#include "ruby/io.h"
#include "ruby/thread.h"
#include "ruby/util.h"
diff --git a/include/ruby/internal/core/rfile.h b/include/ruby/internal/core/rfile.h
index 8cf2c4db5b..f8dddde9e5 100644
--- a/include/ruby/internal/core/rfile.h
+++ b/include/ruby/internal/core/rfile.h
@@ -23,10 +23,9 @@
#include "ruby/internal/core/rbasic.h"
#include "ruby/internal/cast.h"
-/* rb_io is in ruby/io.h and internal/io.h. The header file has historically
- * not been included into ruby/ruby.h. We follow that tradition.
- */
-struct rb_io;
+/* rb_io_t is in ruby/io.h. The header file has historically not been included
+ * into ruby/ruby.h. We follow that tradition. */
+struct rb_io_t;
/**
* Ruby's File and IO. Ruby's IO are not just file descriptors. They have
@@ -39,7 +38,7 @@ struct RFile {
struct RBasic basic;
/** IO's specific fields. */
- struct rb_io *fptr;
+ struct rb_io_t *fptr;
};
/**
diff --git a/include/ruby/io.h b/include/ruby/io.h
index 881bac03a7..8be83a215c 100644
--- a/include/ruby/io.h
+++ b/include/ruby/io.h
@@ -84,6 +84,29 @@ typedef enum {
RUBY_IO_PRIORITY = RB_WAITFD_PRI, /**< `IO::PRIORITY` */
} rb_io_event_t;
+/**
+ * IO buffers. This is an implementation detail of ::rb_io_t::wbuf and
+ * ::rb_io_t::rbuf. People don't manipulate it directly.
+ */
+RBIMPL_ATTR_PACKED_STRUCT_UNALIGNED_BEGIN()
+struct rb_io_buffer_t {
+
+ /** Pointer to the underlying memory region, of at least `capa` bytes. */
+ char *ptr; /* off + len <= capa */
+
+ /** Offset inside of `ptr`. */
+ int off;
+
+ /** Length of the buffer. */
+ int len;
+
+ /** Designed capacity of the buffer. */
+ int capa;
+} RBIMPL_ATTR_PACKED_STRUCT_UNALIGNED_END();
+
+/** @alias{rb_io_buffer_t} */
+typedef struct rb_io_buffer_t rb_io_buffer_t;
+
/** Decomposed encoding flags (e.g. `"enc:enc2""`). */
/*
* enc enc2 read action write action
@@ -91,7 +114,7 @@ typedef enum {
* e1 NULL force_encoding(e1) convert str.encoding to e1
* e1 e2 convert from e2 to e1 convert str.encoding to e2
*/
-struct rb_io_encoding {
+struct rb_io_enc_t {
/** Internal encoding. */
rb_encoding *enc;
/** External encoding. */
@@ -112,10 +135,103 @@ struct rb_io_encoding {
VALUE ecopts;
};
-struct rb_io;
-typedef struct rb_io rb_io_t;
+/** Ruby's IO, metadata and buffers. */
+typedef struct rb_io_t {
+
+ /** The IO's Ruby level counterpart. */
+ VALUE self;
+
+ /** stdio ptr for read/write, if available. */
+ FILE *stdio_file;
+
+ /** file descriptor. */
+ int fd;
+
+ /** mode flags: FMODE_XXXs */
+ int mode;
+
+ /** child's pid (for pipes) */
+ rb_pid_t pid;
+
+ /** number of lines read */
+ int lineno;
+
+ /** pathname for file */
+ VALUE pathv;
+
+ /** finalize proc */
+ void (*finalize)(struct rb_io_t*,int);
+
+ /** Write buffer. */
+ rb_io_buffer_t wbuf;
+
+ /**
+ * (Byte) read buffer. Note also that there is a field called
+ * ::rb_io_t::cbuf, which also concerns read IO.
+ */
+ rb_io_buffer_t rbuf;
+
+ /**
+ * Duplex IO object, if set.
+ *
+ * @see rb_io_set_write_io()
+ */
+ VALUE tied_io_for_writing;
+
+ struct rb_io_enc_t encs; /**< Decomposed encoding flags. */
+
+ /** Encoding converter used when reading from this IO. */
+ rb_econv_t *readconv;
+
+ /**
+ * rb_io_ungetc() destination. This buffer is read before checking
+ * ::rb_io_t::rbuf
+ */
+ rb_io_buffer_t cbuf;
+
+ /** Encoding converter used when writing to this IO. */
+ rb_econv_t *writeconv;
+
+ /**
+ * This is, when set, an instance of ::rb_cString which holds the "common"
+ * encoding. Write conversion can convert strings twice... In case
+ * conversion from encoding X to encoding Y does not exist, Ruby finds an
+ * encoding Z that bridges the two, so that X to Z to Y conversion happens.
+ */
+ VALUE writeconv_asciicompat;
+
+ /** Whether ::rb_io_t::writeconv is already set up. */
+ int writeconv_initialized;
-typedef struct rb_io_encoding rb_io_enc_t;
+ /**
+ * Value of ::rb_io_t::rb_io_enc_t::ecflags stored right before
+ * initialising ::rb_io_t::writeconv.
+ */
+ int writeconv_pre_ecflags;
+
+ /**
+ * Value of ::rb_io_t::rb_io_enc_t::ecopts stored right before initialising
+ * ::rb_io_t::writeconv.
+ */
+ VALUE writeconv_pre_ecopts;
+
+ /**
+ * This is a Ruby level mutex. It avoids multiple threads to write to an
+ * IO at once; helps for instance rb_io_puts() to ensure newlines right
+ * next to its arguments.
+ *
+ * This of course doesn't help inter-process IO interleaves, though.
+ */
+ VALUE write_lock;
+
+ /**
+ * The timeout associated with this IO when performing blocking operations.
+ */
+ VALUE timeout;
+} rb_io_t;
+
+/** @alias{rb_io_enc_t} */
+typedef struct rb_io_enc_t rb_io_enc_t;
/**
* @private
@@ -215,16 +331,7 @@ typedef struct rb_io_encoding rb_io_enc_t;
* Setting this one and #FMODE_BINMODE at the same time is a contradiction.
*/
#define FMODE_TEXTMODE 0x00001000
-/**
- * This flag means that an IO object is wrapping an "external" file descriptor,
- * which is owned by something outside the Ruby interpreter (usually a C extension).
- * Ruby will not close this file when the IO object is garbage collected.
- * If this flag is set, then IO#autoclose? is false, and vice-versa.
- *
- * This flag was previously called FMODE_PREP internally.
- */
-#define FMODE_EXTERNAL 0x00010000
-
+/* #define FMODE_PREP 0x00010000 */
/* #define FMODE_SIGNAL_ON_EPIPE 0x00020000 */
/**
@@ -239,18 +346,6 @@ typedef struct rb_io_encoding rb_io_enc_t;
/** @} */
/**
- * Allocate a new IO object, with the given file descriptor.
- */
-VALUE rb_io_open_descriptor(VALUE klass, int descriptor, int mode, VALUE path, VALUE timeout, struct rb_io_encoding *encoding);
-
-/**
- * Returns whether or not the underlying IO is closed.
- *
- * @return Whether the underlying IO is closed.
- */
-VALUE rb_io_closed_p(VALUE io);
-
-/**
* Queries the underlying IO pointer.
*
* @param[in] obj An IO object.
@@ -609,12 +704,6 @@ VALUE rb_io_set_write_io(VALUE io, VALUE w);
void rb_io_set_nonblock(rb_io_t *fptr);
/**
- * Returns the path for the given IO.
- *
- */
-VALUE rb_io_path(VALUE io);
-
-/**
* Returns an integer representing the numeric file descriptor for
* <em>io</em>.
*
@@ -624,12 +713,6 @@ VALUE rb_io_path(VALUE io);
int rb_io_descriptor(VALUE io);
/**
- * Get the mode of the IO.
- *
- */
-int rb_io_mode(VALUE io);
-
-/**
* This function breaks down the option hash that `IO#initialize` takes into
* components. This is an implementation detail of rb_io_extract_modeenc()
* today. People prefer that API instead.
diff --git a/internal/io.h b/internal/io.h
index c97fd1e616..b5f15499d7 100644
--- a/internal/io.h
+++ b/internal/io.h
@@ -8,125 +8,8 @@
* file COPYING are met. Consult the file for details.
* @brief Internal header for IO.
*/
-
-#define RB_IO_T
-
#include "ruby/ruby.h" /* for VALUE */
-#include "ruby/io.h"
-
-/**
- * IO buffers. This is an implementation detail of ::rb_io_t::wbuf and
- * ::rb_io_t::rbuf. People don't manipulate it directly.
- */
-RBIMPL_ATTR_PACKED_STRUCT_UNALIGNED_BEGIN()
-struct rb_io_internal_buffer {
-
- /** Pointer to the underlying memory region, of at least `capa` bytes. */
- char *ptr; /* off + len <= capa */
-
- /** Offset inside of `ptr`. */
- int off;
-
- /** Length of the buffer. */
- int len;
-
- /** Designed capacity of the buffer. */
- int capa;
-} RBIMPL_ATTR_PACKED_STRUCT_UNALIGNED_END();
-
-/** Ruby's IO, metadata and buffers. */
-struct rb_io {
- /** The IO's Ruby level counterpart. */
- VALUE self;
-
- /** stdio ptr for read/write, if available. */
- FILE *stdio_file;
-
- /** file descriptor. */
- int fd;
-
- /** mode flags: FMODE_XXXs */
- int mode;
-
- /** child's pid (for pipes) */
- rb_pid_t pid;
-
- /** number of lines read */
- int lineno;
-
- /** pathname for file */
- VALUE pathv;
-
- /**
- * Duplex IO object, if set.
- *
- * @see rb_io_set_write_io()
- */
- VALUE tied_io_for_writing;
-
- /** finalize proc */
- void (*finalize)(struct rb_io*,int);
-
- /** Write buffer. */
- struct rb_io_internal_buffer wbuf;
-
- /**
- * (Byte) read buffer. Note also that there is a field called
- * ::rb_io_t::cbuf, which also concerns read IO.
- */
- struct rb_io_internal_buffer rbuf;
-
- struct rb_io_encoding encs; /**< Decomposed encoding flags. */
-
- /** Encoding converter used when reading from this IO. */
- rb_econv_t *readconv;
-
- /**
- * rb_io_ungetc() destination. This buffer is read before checking
- * ::rb_io_t::rbuf
- */
- struct rb_io_internal_buffer cbuf;
-
- /** Encoding converter used when writing to this IO. */
- rb_econv_t *writeconv;
-
- /**
- * This is, when set, an instance of ::rb_cString which holds the "common"
- * encoding. Write conversion can convert strings twice... In case
- * conversion from encoding X to encoding Y does not exist, Ruby finds an
- * encoding Z that bridges the two, so that X to Z to Y conversion happens.
- */
- VALUE writeconv_asciicompat;
-
- /** Whether ::rb_io_t::writeconv is already set up. */
- int writeconv_initialized;
-
- /**
- * Value of ::rb_io_t::rb_io_enc_t::ecflags stored right before
- * initialising ::rb_io_t::writeconv.
- */
- int writeconv_pre_ecflags;
-
- /**
- * Value of ::rb_io_t::rb_io_enc_t::ecopts stored right before initialising
- * ::rb_io_t::writeconv.
- */
- VALUE writeconv_pre_ecopts;
-
- /**
- * This is a Ruby level mutex. It avoids multiple threads to write to an
- * IO at once; helps for instance rb_io_puts() to ensure newlines right
- * next to its arguments.
- *
- * This of course doesn't help inter-process IO interleaves, though.
- */
- VALUE write_lock;
-
- /**
- * The timeout associated with this IO when performing blocking operations.
- */
- VALUE timeout;
-};
+#include "ruby/io.h" /* for rb_io_t */
/* io.c */
void ruby_set_inplace_mode(const char *);
diff --git a/io.c b/io.c
index 26c95d2d86..88cb2667f5 100644
--- a/io.c
+++ b/io.c
@@ -16,6 +16,11 @@
#include "ruby/fiber/scheduler.h"
#include "ruby/io/buffer.h"
+#ifdef _WIN32
+# include "ruby/ruby.h"
+# include "ruby/io.h"
+#endif
+
#include <ctype.h>
#include <errno.h>
#include <stddef.h>
@@ -216,7 +221,7 @@ struct argf {
long lineno;
VALUE argv;
VALUE inplace;
- struct rb_io_encoding encs;
+ struct rb_io_enc_t encs;
int8_t init_p, next_p, binmode;
};
@@ -520,6 +525,7 @@ rb_cloexec_fcntl_dupfd(int fd, int minfd)
static int io_fflush(rb_io_t *);
static rb_io_t *flush_before_seek(rb_io_t *fptr);
+#define FMODE_PREP (1<<16)
#define FMODE_SIGNAL_ON_EPIPE (1<<17)
#define fptr_signal_on_epipe(fptr) \
@@ -1457,7 +1463,7 @@ rb_io_wait(VALUE io, VALUE events, VALUE timeout)
static VALUE
io_from_fd(int fd)
{
- return prep_io(fd, FMODE_EXTERNAL, rb_cIO, NULL);
+ return prep_io(fd, FMODE_PREP, rb_cIO, NULL);
}
static int
@@ -2869,13 +2875,6 @@ rb_io_descriptor(VALUE io)
}
}
-int rb_io_mode(VALUE io)
-{
- rb_io_t *fptr;
- GetOpenFile(io, fptr);
- return fptr->mode;
-}
-
/*
* call-seq:
* pid -> integer or nil
@@ -2922,7 +2921,7 @@ rb_io_pid(VALUE io)
* File.open("testfile") {|f| f.path} # => "testfile"
*/
-VALUE
+static VALUE
rb_io_path(VALUE io)
{
rb_io_t *fptr = RFILE(io)->fptr;
@@ -5306,7 +5305,7 @@ rb_io_set_close_on_exec(VALUE io, VALUE arg)
#define rb_io_set_close_on_exec rb_f_notimplement
#endif
-#define RUBY_IO_EXTERNAL_P(f) ((f)->mode & FMODE_EXTERNAL)
+#define IS_PREP_STDIO(f) ((f)->mode & FMODE_PREP)
#define PREP_STDIO_NAME(f) (RSTRING_PTR((f)->pathv))
static VALUE
@@ -5420,7 +5419,7 @@ maygvl_fclose(FILE *file, int keepgvl)
return (int)(intptr_t)rb_thread_call_without_gvl(nogvl_fclose, file, RUBY_UBF_IO, 0);
}
-static void free_io_buffer(struct rb_io_internal_buffer *buf);
+static void free_io_buffer(rb_io_buffer_t *buf);
static void clear_codeconv(rb_io_t *fptr);
static void*
@@ -5464,7 +5463,7 @@ fptr_finalize_flush(rb_io_t *fptr, int noraise, int keepgvl,
int done = 0;
- if (RUBY_IO_EXTERNAL_P(fptr) || fd <= 2) {
+ if (IS_PREP_STDIO(fptr) || fd <= 2) {
// Need to keep FILE objects of stdin, stdout and stderr, so we are done:
done = 1;
}
@@ -5543,7 +5542,7 @@ rb_io_fptr_cleanup(rb_io_t *fptr, int noraise)
}
static void
-free_io_buffer(struct rb_io_internal_buffer *buf)
+free_io_buffer(rb_io_buffer_t *buf)
{
if (buf->ptr) {
ruby_sized_xfree(buf->ptr, (size_t)buf->capa);
@@ -5771,8 +5770,10 @@ io_close(VALUE io)
*
* Related: IO#close_read, IO#close_write, IO#close.
*/
-VALUE
-rb_io_closed_p(VALUE io)
+
+
+static VALUE
+rb_io_closed(VALUE io)
{
rb_io_t *fptr;
VALUE write_io;
@@ -6723,7 +6724,7 @@ rb_io_extract_encoding_option(VALUE opt, rb_encoding **enc_p, rb_encoding **enc2
return extracted;
}
-typedef struct rb_io_encoding convconfig_t;
+typedef struct rb_io_enc_t convconfig_t;
static void
validate_enc_binmode(int *fmode_p, int ecflags, rb_encoding *enc, rb_encoding *enc2)
@@ -7257,7 +7258,7 @@ static void
fptr_copy_finalizer(rb_io_t *fptr, const rb_io_t *orig)
{
#if defined(__CYGWIN__) || !defined(HAVE_WORKING_FORK)
- void (*const old_finalize)(rb_io_t*,int) = fptr->finalize;
+ void (*const old_finalize)(struct rb_io_t*,int) = fptr->finalize;
if (old_finalize == orig->finalize) return;
#endif
@@ -8288,7 +8289,7 @@ io_reopen(VALUE io, VALUE nfile)
GetOpenFile(nfile, orig);
if (fptr == orig) return io;
- if (RUBY_IO_EXTERNAL_P(fptr)) {
+ if (IS_PREP_STDIO(fptr)) {
if ((fptr->stdio_file == stdin && !(orig->mode & FMODE_READABLE)) ||
(fptr->stdio_file == stdout && !(orig->mode & FMODE_WRITABLE)) ||
(fptr->stdio_file == stderr && !(orig->mode & FMODE_WRITABLE))) {
@@ -8314,17 +8315,17 @@ io_reopen(VALUE io, VALUE nfile)
}
/* copy rb_io_t structure */
- fptr->mode = orig->mode | (fptr->mode & FMODE_EXTERNAL);
+ fptr->mode = orig->mode | (fptr->mode & FMODE_PREP);
fptr->pid = orig->pid;
fptr->lineno = orig->lineno;
if (RTEST(orig->pathv)) fptr->pathv = orig->pathv;
- else if (!RUBY_IO_EXTERNAL_P(fptr)) fptr->pathv = Qnil;
+ else if (!IS_PREP_STDIO(fptr)) fptr->pathv = Qnil;
fptr_copy_finalizer(fptr, orig);
fd = fptr->fd;
fd2 = orig->fd;
if (fd != fd2) {
- if (RUBY_IO_EXTERNAL_P(fptr) || fd <= 2 || !fptr->stdio_file) {
+ if (IS_PREP_STDIO(fptr) || fd <= 2 || !fptr->stdio_file) {
/* need to keep FILE objects of stdin, stdout and stderr */
if (rb_cloexec_dup2(fd2, fd) < 0)
rb_sys_fail_path(orig->pathv);
@@ -8432,7 +8433,7 @@ rb_io_reopen(int argc, VALUE *argv, VALUE file)
convconfig_t convconfig;
rb_io_extract_modeenc(&nmode, 0, opt, &oflags, &fmode, &convconfig);
- if (RUBY_IO_EXTERNAL_P(fptr) &&
+ if (IS_PREP_STDIO(fptr) &&
((fptr->mode & FMODE_READWRITE) & (fmode & FMODE_READWRITE)) !=
(fptr->mode & FMODE_READWRITE)) {
rb_raise(rb_eArgError,
@@ -8511,7 +8512,7 @@ rb_io_init_copy(VALUE dest, VALUE io)
rb_io_flush(io);
/* copy rb_io_t structure */
- fptr->mode = orig->mode & ~FMODE_EXTERNAL;
+ fptr->mode = orig->mode & ~FMODE_PREP;
fptr->encs = orig->encs;
fptr->pid = orig->pid;
fptr->lineno = orig->lineno;
@@ -9186,79 +9187,26 @@ stderr_getter(ID id, VALUE *ptr)
}
static VALUE
-allocate_and_open_new_file(VALUE klass)
-{
- VALUE self = io_alloc(klass);
- rb_io_make_open_file(self);
- return self;
-}
-
-VALUE
-rb_io_open_descriptor(VALUE klass, int descriptor, int mode, VALUE path, VALUE timeout, struct rb_io_encoding *encoding)
-{
-
- int state;
- VALUE self = rb_protect(allocate_and_open_new_file, klass, &state);
- if (state) {
- /* if we raised an exception allocating an IO object, but the caller
- intended to transfer ownership of this FD to us, close the fd before
- raising the exception. Otherwise, we would leak a FD - the caller
- expects GC to close the file, but we never got around to assigning
- it to a rb_io. */
- if (!(mode & FMODE_EXTERNAL)) {
- maygvl_close(descriptor, 0);
- }
- rb_jump_tag(state);
- }
-
-
- struct rb_io *io = RFILE(self)->fptr;
- io->self = self;
- io->fd = descriptor;
- io->mode = mode;
-
- /* At this point, Ruby fully owns the descriptor, and will close it when
- the IO gets GC'd (unless FMODE_EXTERNAL was set), no matter what happens
- in the rest of this method. */
-
- if (NIL_P(path)) {
- io->pathv = Qnil;
- }
- else {
- StringValue(path);
- io->pathv = rb_str_new_frozen(path);
- }
-
- io->timeout = timeout;
-
- if (encoding) {
- io->encs = *encoding;
- }
-
- rb_update_max_fd(descriptor);
-
- return self;
-}
-
-static VALUE
prep_io(int fd, int fmode, VALUE klass, const char *path)
{
- VALUE path_value = Qnil;
- if (path) {
- path_value = rb_obj_freeze(rb_str_new_cstr(path));
- }
-
- VALUE self = rb_io_open_descriptor(klass, fd, fmode, path_value, Qnil, NULL);
- struct rb_io *io = RFILE(self)->fptr;
+ rb_io_t *fp;
+ VALUE io = io_alloc(klass);
- if (!io_check_tty(io)) {
+ MakeOpenFile(io, fp);
+ fp->self = io;
+ fp->fd = fd;
+ fp->mode = fmode;
+ fp->timeout = Qnil;
+ if (!io_check_tty(fp)) {
#ifdef __CYGWIN__
- io->mode |= FMODE_BINMODE;
+ fp->mode |= FMODE_BINMODE;
setmode(fd, O_BINARY);
#endif
}
+ if (path) fp->pathv = rb_obj_freeze(rb_str_new_cstr(path));
+ rb_update_max_fd(fd);
- return self;
+ return io;
}
VALUE
@@ -9274,7 +9222,7 @@ static VALUE
prep_stdio(FILE *f, int fmode, VALUE klass, const char *path)
{
rb_io_t *fptr;
- VALUE io = prep_io(fileno(f), fmode|FMODE_EXTERNAL|DEFAULT_TEXTMODE, klass, path);
+ VALUE io = prep_io(fileno(f), fmode|FMODE_PREP|DEFAULT_TEXTMODE, klass, path);
GetOpenFile(io, fptr);
fptr->encs.ecflags |= ECONV_DEFAULT_NEWLINE_DECORATOR;
@@ -9318,7 +9266,7 @@ rb_io_stdio_file(rb_io_t *fptr)
}
static inline void
-rb_io_buffer_init(struct rb_io_internal_buffer *buf)
+rb_io_buffer_init(rb_io_buffer_t *buf)
{
buf->ptr = NULL;
buf->off = 0;
@@ -9458,7 +9406,7 @@ rb_io_initialize(int argc, VALUE *argv, VALUE io)
if (!NIL_P(opt)) {
if (rb_hash_aref(opt, sym_autoclose) == Qfalse) {
- fmode |= FMODE_EXTERNAL;
+ fmode |= FMODE_PREP;
}
path = rb_hash_aref(opt, RB_ID2SYM(idPath));
@@ -9635,7 +9583,7 @@ rb_io_autoclose_p(VALUE io)
{
rb_io_t *fptr = RFILE(io)->fptr;
rb_io_check_closed(fptr);
- return RBOOL(!(fptr->mode & FMODE_EXTERNAL));
+ return RBOOL(!(fptr->mode & FMODE_PREP));
}
/*
@@ -9661,9 +9609,9 @@ rb_io_set_autoclose(VALUE io, VALUE autoclose)
rb_io_t *fptr;
GetOpenFile(io, fptr);
if (!RTEST(autoclose))
- fptr->mode |= FMODE_EXTERNAL;
+ fptr->mode |= FMODE_PREP;
else
- fptr->mode &= ~FMODE_EXTERNAL;
+ fptr->mode &= ~FMODE_PREP;
return autoclose;
}
@@ -14494,7 +14442,7 @@ argf_closed(VALUE argf)
{
next_argv();
ARGF_FORWARD(0, 0);
- return rb_io_closed_p(ARGF.current_file);
+ return rb_io_closed(ARGF.current_file);
}
/*
@@ -15541,7 +15489,7 @@ Init_IO(void)
rb_define_method(rb_cIO, "close_on_exec=", rb_io_set_close_on_exec, 1);
rb_define_method(rb_cIO, "close", rb_io_close_m, 0);
- rb_define_method(rb_cIO, "closed?", rb_io_closed_p, 0);
+ rb_define_method(rb_cIO, "closed?", rb_io_closed, 0);
rb_define_method(rb_cIO, "close_read", rb_io_close_read, 0);
rb_define_method(rb_cIO, "close_write", rb_io_close_write, 0);
diff --git a/process.c b/process.c
index b4435446f0..c54e11860e 100644
--- a/process.c
+++ b/process.c
@@ -103,7 +103,6 @@ int initgroups(const char *, rb_gid_t);
#include "internal/error.h"
#include "internal/eval.h"
#include "internal/hash.h"
-#include "internal/io.h"
#include "internal/numeric.h"
#include "internal/object.h"
#include "internal/process.h"
diff --git a/spec/ruby/optional/capi/ext/io_spec.c b/spec/ruby/optional/capi/ext/io_spec.c
index 1c554a1a31..cd4bc80229 100644
--- a/spec/ruby/optional/capi/ext/io_spec.c
+++ b/spec/ruby/optional/capi/ext/io_spec.c
@@ -28,13 +28,9 @@ static int set_non_blocking(int fd) {
}
static int io_spec_get_fd(VALUE io) {
-#ifdef RUBY_VERSION_IS_3_1
- return rb_io_descriptor(io);
-#else
rb_io_t* fp;
GetOpenFile(io, fp);
return fp->fd;
-#endif
}
VALUE io_spec_GetOpenFile_fd(VALUE self, VALUE io) {
@@ -307,7 +303,7 @@ VALUE io_spec_rb_io_set_nonblock(VALUE self, VALUE io) {
GetOpenFile(io, fp);
rb_io_set_nonblock(fp);
#ifdef F_GETFL
- flags = fcntl(io_spec_get_fd(io), F_GETFL, 0);
+ flags = fcntl(fp->fd, F_GETFL, 0);
return flags & O_NONBLOCK ? Qtrue : Qfalse;
#else
return Qfalse;
@@ -326,13 +322,9 @@ static VALUE io_spec_errno_set(VALUE self, VALUE val) {
}
VALUE io_spec_mode_sync_flag(VALUE self, VALUE io) {
-#ifdef RUBY_VERSION_IS_3_3
- if (rb_io_mode(io) & FMODE_SYNC) {
-#else
rb_io_t *fp;
GetOpenFile(io, fp);
if (fp->mode & FMODE_SYNC) {
-#endif
return Qtrue;
} else {
return Qfalse;
diff --git a/win32/win32.c b/win32/win32.c
index c2d12a79f4..ec65f5383b 100644
--- a/win32/win32.c
+++ b/win32/win32.c
@@ -8269,7 +8269,10 @@ w32_io_info(VALUE *file, w32_io_info_t *st)
tmp = rb_check_convert_type_with_id(*file, T_FILE, "IO", idTo_io);
if (!NIL_P(tmp)) {
- f = (HANDLE)rb_w32_get_osfhandle(rb_io_descriptor(tmp));
+ rb_io_t *fptr;
+
+ GetOpenFile(tmp, fptr);
+ f = (HANDLE)rb_w32_get_osfhandle(fptr->fd);
if (f == (HANDLE)-1) return INVALID_HANDLE_VALUE;
}
else {