diff options
author | NARUSE, Yui <naruse@airemix.jp> | 2023-06-01 08:43:22 +0900 |
---|---|---|
committer | NARUSE, Yui <naruse@airemix.jp> | 2023-06-01 08:43:22 +0900 |
commit | 85dcc4866d9ff29834596e9186cc97d622ee06f8 (patch) | |
tree | d5daa60146c5c8c2de9a9459a05e6e771d934362 | |
parent | e4163112f6b99d9c205f6bc260878dcb00954a13 (diff) | |
download | ruby-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.mk | 1 | ||||
-rw-r--r-- | debug.c | 2 | ||||
-rw-r--r-- | ext/objspace/depend | 1 | ||||
-rw-r--r-- | ext/objspace/objspace_dump.c | 1 | ||||
-rw-r--r-- | ext/pty/pty.c | 54 | ||||
-rw-r--r-- | ext/stringio/stringio.c | 4 | ||||
-rw-r--r-- | file.c | 1 | ||||
-rw-r--r-- | include/ruby/internal/core/rfile.h | 9 | ||||
-rw-r--r-- | include/ruby/io.h | 159 | ||||
-rw-r--r-- | internal/io.h | 119 | ||||
-rw-r--r-- | io.c | 142 | ||||
-rw-r--r-- | process.c | 1 | ||||
-rw-r--r-- | spec/ruby/optional/capi/ext/io_spec.c | 10 | ||||
-rw-r--r-- | win32/win32.c | 5 |
14 files changed, 211 insertions, 298 deletions
@@ -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 @@ -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); @@ -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 *); @@ -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); @@ -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 { |