14 #include "ruby/internal/config.h"
29 #if defined(HAVE_POLL)
30 # if defined(__linux__)
33 # if defined(__FreeBSD_version) && __FreeBSD_version >= 1100000
43 #define free(x) xfree(x)
45 #if defined(DOSISH) || defined(__CYGWIN__)
49 #include <sys/types.h>
50 #if defined HAVE_NET_SOCKET_H
51 # include <net/socket.h>
52 #elif defined HAVE_SYS_SOCKET_H
53 # include <sys/socket.h>
56 #if defined(__BOW__) || defined(__CYGWIN__) || defined(_WIN32)
57 # define NO_SAFE_RENAME
60 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__sun) || defined(_nec_ews)
68 #include <sys/types.h>
69 #if defined(HAVE_SYS_IOCTL_H) && !defined(_WIN32)
70 #include <sys/ioctl.h>
72 #if defined(HAVE_FCNTL_H) || defined(_WIN32)
74 #elif defined(HAVE_SYS_FCNTL_H)
75 #include <sys/fcntl.h>
78 #if !HAVE_OFF_T && !defined(off_t)
82 #ifdef HAVE_SYS_TIME_H
83 # include <sys/time.h>
88 #if defined(HAVE_SYS_PARAM_H) || defined(__HIUX_MPP__)
89 # include <sys/param.h>
100 #ifdef HAVE_SYSCALL_H
102 #elif defined HAVE_SYS_SYSCALL_H
103 #include <sys/syscall.h>
106 #ifdef HAVE_SYS_UIO_H
110 #ifdef HAVE_SYS_WAIT_H
111 # include <sys/wait.h>
114 #ifdef HAVE_COPYFILE_H
115 # include <copyfile.h>
119 #include "ccan/list/list.h"
121 #include "encindex.h"
123 #include "internal.h"
124 #include "internal/encoding.h"
125 #include "internal/error.h"
126 #include "internal/inits.h"
127 #include "internal/io.h"
128 #include "internal/numeric.h"
129 #include "internal/object.h"
130 #include "internal/process.h"
131 #include "internal/thread.h"
132 #include "internal/transcode.h"
133 #include "internal/variable.h"
138 #include "ruby_atomic.h"
142 # include "vm_core.h"
148 #define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR)
151 #if SIZEOF_OFF_T > SIZEOF_LONG && !defined(HAVE_LONG_LONG)
152 # error off_t is bigger than long, but you have no long long...
156 # ifdef _POSIX_PIPE_BUF
157 # define PIPE_BUF _POSIX_PIPE_BUF
159 # define PIPE_BUF 512
164 # define EWOULDBLOCK EAGAIN
167 #if defined(HAVE___SYSCALL) && (defined(__APPLE__) || defined(__OpenBSD__))
169 off_t __syscall(quad_t number, ...);
172 #define IO_RBUF_CAPA_MIN 8192
173 #define IO_CBUF_CAPA_MIN (128*1024)
174 #define IO_RBUF_CAPA_FOR(fptr) (NEED_READCONV(fptr) ? IO_CBUF_CAPA_MIN : IO_RBUF_CAPA_MIN)
175 #define IO_WBUF_CAPA_MIN 8192
180 #define open rb_w32_uopen
182 #define rename(f, t) rb_w32_urename((f), (t))
191 static VALUE rb_eEAGAINWaitReadable;
192 static VALUE rb_eEAGAINWaitWritable;
193 static VALUE rb_eEWOULDBLOCKWaitReadable;
194 static VALUE rb_eEWOULDBLOCKWaitWritable;
195 static VALUE rb_eEINPROGRESSWaitWritable;
196 static VALUE rb_eEINPROGRESSWaitReadable;
199 static VALUE orig_stdout, orig_stderr;
208 static ID id_write, id_read, id_getc, id_flush, id_readpartial, id_set_encoding, id_fileno;
209 static VALUE sym_mode, sym_perm, sym_flags, sym_extenc, sym_intenc, sym_encoding, sym_open_args;
210 static VALUE sym_textmode, sym_binmode, sym_autoclose;
211 static VALUE sym_SET, sym_CUR, sym_END;
212 static VALUE sym_wait_readable, sym_wait_writable;
214 static VALUE sym_DATA;
217 static VALUE sym_HOLE;
220 static VALUE prep_io(
int fd,
int fmode,
VALUE klass,
const char *path);
223 VALUE filename, current_file;
229 int8_t init_p, next_p, binmode;
240 if (fd < 0 || afd <= max_fd)
243 #if defined(HAVE_FCNTL) && defined(F_GETFL)
244 err = fcntl(fd, F_GETFL) == -1;
248 err = fstat(fd, &buf) != 0;
251 if (err && errno == EBADF) {
252 rb_bug(
"rb_update_max_fd: invalid fd (%d) given.", fd);
255 while (max_fd < afd) {
256 max_fd = ATOMIC_CAS(max_file_descriptor, max_fd, afd);
261 rb_maygvl_fd_fix_cloexec(
int fd)
264 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
265 int flags, flags2, ret;
266 flags = fcntl(fd, F_GETFD);
268 rb_bug(
"rb_maygvl_fd_fix_cloexec: fcntl(%d, F_GETFD) failed: %s", fd, strerror(errno));
271 flags2 = flags & ~FD_CLOEXEC;
273 flags2 = flags | FD_CLOEXEC;
274 if (flags != flags2) {
275 ret = fcntl(fd, F_SETFD, flags2);
277 rb_bug(
"rb_maygvl_fd_fix_cloexec: fcntl(%d, F_SETFD, %d) failed: %s", fd, flags2, strerror(errno));
286 rb_maygvl_fd_fix_cloexec(fd);
292 rb_fix_detect_o_cloexec(
int fd)
294 #if defined(O_CLOEXEC) && defined(F_GETFD)
295 int flags = fcntl(fd, F_GETFD);
298 rb_bug(
"rb_fix_detect_o_cloexec: fcntl(%d, F_GETFD) failed: %s", fd, strerror(errno));
300 if (flags & FD_CLOEXEC)
303 rb_maygvl_fd_fix_cloexec(fd);
310 return (e == EWOULDBLOCK) || (e == EAGAIN);
317 static int o_cloexec_state = -1;
319 static const int retry_interval = 0;
320 static const int retry_max_count = 10000;
327 #elif defined O_NOINHERIT
328 flags |= O_NOINHERIT;
331 while ((ret = open(pathname, flags, mode)) == -1) {
333 if (!io_again_p(e))
break;
334 if (retry_count++ >= retry_max_count)
break;
336 sleep(retry_interval);
339 if (ret < 0)
return ret;
340 if (ret <= 2 || o_cloexec_state == 0) {
341 rb_maygvl_fd_fix_cloexec(ret);
343 else if (o_cloexec_state > 0) {
347 o_cloexec_state = rb_fix_detect_o_cloexec(ret);
366 if (oldfd == newfd) {
370 #if defined(HAVE_DUP3) && defined(O_CLOEXEC)
371 static int try_dup3 = 1;
372 if (2 < newfd && try_dup3) {
373 ret = dup3(oldfd, newfd, O_CLOEXEC);
377 if (errno == ENOSYS) {
379 ret = dup2(oldfd, newfd);
383 ret = dup2(oldfd, newfd);
386 ret = dup2(oldfd, newfd);
388 if (ret < 0)
return ret;
390 rb_maygvl_fd_fix_cloexec(ret);
395 rb_fd_set_nonblock(
int fd)
398 return rb_w32_set_nonblock(fd);
399 #elif defined(F_GETFL)
400 int oflags = fcntl(fd, F_GETFL);
404 if (oflags & O_NONBLOCK)
406 oflags |= O_NONBLOCK;
407 return fcntl(fd, F_SETFL, oflags);
416 int result = pipe2(descriptors, O_CLOEXEC | O_NONBLOCK);
418 int result = pipe(descriptors);
425 if (result == 0 && descriptors[1] == -1) {
426 close(descriptors[0]);
434 rb_maygvl_fd_fix_cloexec(descriptors[0]);
435 rb_maygvl_fd_fix_cloexec(descriptors[1]);
438 rb_fd_set_nonblock(descriptors[0]);
439 rb_fd_set_nonblock(descriptors[1]);
451 #if defined(HAVE_FCNTL) && defined(F_DUPFD_CLOEXEC) && defined(F_DUPFD)
452 static int try_dupfd_cloexec = 1;
453 if (try_dupfd_cloexec) {
454 ret = fcntl(fd, F_DUPFD_CLOEXEC, minfd);
457 rb_maygvl_fd_fix_cloexec(ret);
461 if (errno == EINVAL) {
462 ret = fcntl(fd, F_DUPFD, minfd);
464 try_dupfd_cloexec = 0;
469 ret = fcntl(fd, F_DUPFD, minfd);
471 #elif defined(HAVE_FCNTL) && defined(F_DUPFD)
472 ret = fcntl(fd, F_DUPFD, minfd);
475 if (ret >= 0 && ret < minfd) {
476 const int prev_fd = ret;
482 if (ret < 0)
return ret;
483 rb_maygvl_fd_fix_cloexec(ret);
487 #define argf_of(obj) (*(struct argf *)DATA_PTR(obj))
488 #define ARGF argf_of(argf)
490 #define GetWriteIO(io) rb_io_get_write_io(io)
492 #define READ_DATA_PENDING(fptr) ((fptr)->rbuf.len)
493 #define READ_DATA_PENDING_COUNT(fptr) ((fptr)->rbuf.len)
494 #define READ_DATA_PENDING_PTR(fptr) ((fptr)->rbuf.ptr+(fptr)->rbuf.off)
495 #define READ_DATA_BUFFERED(fptr) READ_DATA_PENDING(fptr)
497 #define READ_CHAR_PENDING(fptr) ((fptr)->cbuf.len)
498 #define READ_CHAR_PENDING_COUNT(fptr) ((fptr)->cbuf.len)
499 #define READ_CHAR_PENDING_PTR(fptr) ((fptr)->cbuf.ptr+(fptr)->cbuf.off)
502 #define WAIT_FD_IN_WIN32(fptr) \
503 (rb_w32_io_cancelable_p((fptr)->fd) ? Qnil : rb_io_wait(fptr->self, RB_INT2NUM(RUBY_IO_READABLE), Qnil))
505 #define WAIT_FD_IN_WIN32(fptr)
508 #define READ_CHECK(fptr) do {\
509 if (!READ_DATA_PENDING(fptr)) {\
510 WAIT_FD_IN_WIN32(fptr);\
511 rb_io_check_closed(fptr);\
517 # define S_ISSOCK(m) _S_ISSOCK(m)
520 # define S_ISSOCK(m) (((m) & S_IFMT) == _S_IFSOCK)
523 # define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
529 static int io_fflush(
rb_io_t *);
532 #define FMODE_PREP (1<<16)
533 #define FMODE_SIGNAL_ON_EPIPE (1<<17)
535 #define fptr_signal_on_epipe(fptr) \
536 (((fptr)->mode & FMODE_SIGNAL_ON_EPIPE) != 0)
538 #define fptr_set_signal_on_epipe(fptr, flag) \
540 (fptr)->mode |= FMODE_SIGNAL_ON_EPIPE : \
541 (fptr)->mode &= ~FMODE_SIGNAL_ON_EPIPE)
543 extern ID ruby_static_id_signo;
545 NORETURN(
static void raise_on_write(
rb_io_t *fptr,
int e,
VALUE errinfo));
550 if (fptr_signal_on_epipe(fptr) && (e == EPIPE)) {
562 #define rb_sys_fail_on_write(fptr) \
565 raise_on_write(fptr, e, rb_syserr_new_path(e, (fptr)->pathv)); \
568 #define NEED_NEWLINE_DECORATOR_ON_READ(fptr) ((fptr)->mode & FMODE_TEXTMODE)
569 #define NEED_NEWLINE_DECORATOR_ON_WRITE(fptr) ((fptr)->mode & FMODE_TEXTMODE)
570 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
571 # define RUBY_CRLF_ENVIRONMENT 1
573 # define RUBY_CRLF_ENVIRONMENT 0
576 #if RUBY_CRLF_ENVIRONMENT
578 # define DEFAULT_TEXTMODE FMODE_TEXTMODE
579 # define TEXTMODE_NEWLINE_DECORATOR_ON_WRITE ECONV_CRLF_NEWLINE_DECORATOR
587 #define NEED_READCONV(fptr) ((fptr)->encs.enc2 != NULL || (fptr)->encs.ecflags & ~ECONV_CRLF_NEWLINE_DECORATOR)
588 #define WRITECONV_MASK ( \
589 (ECONV_DECORATOR_MASK & ~ECONV_CRLF_NEWLINE_DECORATOR)|\
590 ECONV_STATEFUL_DECORATOR_MASK|\
592 #define NEED_WRITECONV(fptr) ( \
593 ((fptr)->encs.enc != NULL && (fptr)->encs.enc != rb_ascii8bit_encoding()) || \
594 ((fptr)->encs.ecflags & WRITECONV_MASK) || \
596 #define SET_BINARY_MODE(fptr) setmode((fptr)->fd, O_BINARY)
598 #define NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr) do {\
599 if (NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {\
600 if (((fptr)->mode & FMODE_READABLE) &&\
601 !((fptr)->encs.ecflags & ECONV_NEWLINE_DECORATOR_MASK)) {\
602 setmode((fptr)->fd, O_BINARY);\
605 setmode((fptr)->fd, O_TEXT);\
610 #define SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags) do {\
611 if ((enc2) && ((ecflags) & ECONV_DEFAULT_NEWLINE_DECORATOR)) {\
612 (ecflags) |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;\
636 if (!rb_w32_fd_is_text(fptr->
fd)) {
637 r = lseek(fptr->
fd, -fptr->
rbuf.
len, SEEK_CUR);
638 if (r < 0 && errno) {
649 pos = lseek(fptr->
fd, 0, SEEK_CUR);
650 if (pos < 0 && errno) {
657 extra_max = (long)(pos - fptr->
rbuf.
len);
665 for (i = 0; i < fptr->
rbuf.
len; i++) {
666 if (*p ==
'\n') newlines++;
667 if (extra_max == newlines)
break;
672 while (newlines >= 0) {
673 r = lseek(fptr->
fd, pos - fptr->
rbuf.
len - newlines, SEEK_SET);
674 if (newlines == 0)
break;
679 read_size = _read(fptr->
fd, buf, fptr->
rbuf.
len + newlines);
683 rb_syserr_fail_path(e, fptr->
pathv);
685 if (read_size == fptr->
rbuf.
len) {
686 lseek(fptr->
fd, r, SEEK_SET);
707 set_binary_mode_with_seek_cur(
rb_io_t *fptr)
709 if (!rb_w32_fd_is_text(fptr->
fd))
return O_BINARY;
712 return setmode(fptr->
fd, O_BINARY);
714 flush_before_seek(fptr);
715 return setmode(fptr->
fd, O_BINARY);
717 #define SET_BINARY_MODE_WITH_SEEK_CUR(fptr) set_binary_mode_with_seek_cur(fptr)
721 # define DEFAULT_TEXTMODE 0
722 #define NEED_READCONV(fptr) ((fptr)->encs.enc2 != NULL || NEED_NEWLINE_DECORATOR_ON_READ(fptr))
723 #define NEED_WRITECONV(fptr) ( \
724 ((fptr)->encs.enc != NULL && (fptr)->encs.enc != rb_ascii8bit_encoding()) || \
725 NEED_NEWLINE_DECORATOR_ON_WRITE(fptr) || \
726 ((fptr)->encs.ecflags & (ECONV_DECORATOR_MASK|ECONV_STATEFUL_DECORATOR_MASK)) || \
728 #define SET_BINARY_MODE(fptr) (void)(fptr)
729 #define NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr) (void)(fptr)
730 #define SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags) ((void)(enc2), (void)(ecflags))
731 #define SET_BINARY_MODE_WITH_SEEK_CUR(fptr) (void)(fptr)
734 #if !defined HAVE_SHUTDOWN && !defined shutdown
735 #define shutdown(a,b) 0
739 #define is_socket(fd, path) rb_w32_is_socket(fd)
740 #elif !defined(S_ISSOCK)
741 #define is_socket(fd, path) 0
744 is_socket(
int fd,
VALUE path)
747 if (fstat(fd, &sbuf) < 0)
748 rb_sys_fail_path(path);
749 return S_ISSOCK(sbuf.st_mode);
753 static const char closed_stream[] =
"closed stream";
756 io_fd_check_closed(
int fd)
789 io_fd_check_closed(fptr->
fd);
793 rb_io_get_fptr(
VALUE io)
803 return rb_convert_type_with_id(io,
T_FILE,
"IO", idTo_io);
809 return rb_check_convert_type_with_id(io,
T_FILE,
"IO", idTo_io);
827 rb_io_t *fptr = rb_io_get_fptr(io);
836 return write_io ? write_io :
Qnil;
857 #if !RUBY_CRLF_ENVIRONMENT
867 r = lseek(fptr->
fd, -fptr->
rbuf.
len, SEEK_CUR);
868 if (r < 0 && errno) {
887 const int min_capa = IO_RBUF_CAPA_FOR(fptr);
890 #if SIZEOF_LONG > SIZEOF_INT
915 flush_before_seek(
rb_io_t *fptr)
917 if (io_fflush(fptr) < 0)
918 rb_sys_fail_on_write(fptr);
924 #define io_seek(fptr, ofs, whence) (errno = 0, lseek(flush_before_seek(fptr)->fd, (ofs), (whence)))
925 #define io_tell(fptr) lseek(flush_before_seek(fptr)->fd, 0, SEEK_CUR)
941 if (io_fflush(fptr) < 0)
942 rb_sys_fail_on_write(fptr);
947 if (io_fflush(wfptr) < 0)
948 rb_sys_fail_on_write(wfptr);
956 if (READ_CHAR_PENDING(fptr)) {
968 io_read_encoding(
rb_io_t *fptr)
977 io_input_encoding(
rb_io_t *fptr)
982 return io_read_encoding(fptr);
998 rb_io_read_pending(
rb_io_t *fptr)
1001 if (READ_CHAR_PENDING(fptr))
1003 return READ_DATA_PENDING(fptr);
1009 if (!READ_DATA_PENDING(fptr)) {
1016 rb_gc_for_fd(
int err)
1018 if (err == EMFILE || err == ENFILE || err == ENOMEM) {
1033 if (rb_gc_for_fd(e)) {
1045 io_alloc(
VALUE klass)
1055 # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
1073 struct io_internal_writev_struct {
1076 const struct iovec *iov;
1080 static int nogvl_wait_for(
VALUE th,
rb_io_t *fptr,
short events);
1082 internal_read_func(
void *ptr)
1087 r = read(iis->fptr->
fd, iis->buf, iis->capa);
1088 if (r < 0 && !iis->nonblock) {
1090 if (io_again_p(e)) {
1091 if (nogvl_wait_for(iis->th, iis->fptr, RB_WAITFD_IN) != -1) {
1100 #if defined __APPLE__
1101 # define do_write_retry(code) do {ret = code;} while (ret == -1 && errno == EPROTOTYPE)
1103 # define do_write_retry(code) ret = code
1106 internal_write_func(
void *ptr)
1110 do_write_retry(write(iis->fd, iis->buf, iis->capa));
1115 internal_write_func2(
void *ptr)
1117 return (
void*)internal_write_func(ptr);
1122 internal_writev_func(
void *ptr)
1124 struct io_internal_writev_struct *iis = ptr;
1126 do_write_retry(writev(iis->fd, iis->iov, iis->iovcnt));
1132 rb_read_internal(
rb_io_t *fptr,
void *buf,
size_t count)
1135 if (scheduler !=
Qnil) {
1151 return (ssize_t)rb_thread_io_blocking_region(internal_read_func, &iis, fptr->
fd);
1155 rb_write_internal(
rb_io_t *fptr,
const void *buf,
size_t count)
1158 if (scheduler !=
Qnil) {
1175 return (ssize_t)rb_thread_io_blocking_region(internal_write_func, &iis, fptr->
fd);
1180 rb_writev_internal(
rb_io_t *fptr,
const struct iovec *iov,
int iovcnt)
1183 if (scheduler !=
Qnil) {
1184 for (
int i = 0; i < iovcnt; i += 1) {
1193 struct io_internal_writev_struct iis = {
1199 return (ssize_t)rb_thread_io_blocking_region(internal_writev_func, &iis, fptr->
fd);
1204 io_flush_buffer_sync(
void *arg)
1224 io_flush_buffer_sync2(
void *arg)
1226 VALUE result = io_flush_buffer_sync(arg);
1232 return !result ? (
void*)1 : (
void*)result;
1236 io_flush_buffer_async(
VALUE arg)
1239 return rb_thread_io_blocking_region(io_flush_buffer_sync, fptr, fptr->
fd);
1243 io_flush_buffer_async2(
VALUE arg)
1255 else if (ret == 1) {
1262 io_flush_buffer(
rb_io_t *fptr)
1266 return (
int)io_flush_buffer_async2((
VALUE)fptr);
1271 return (
int)io_flush_buffer_async((
VALUE)fptr);
1283 while (fptr->
wbuf.
len > 0 && io_flush_buffer(fptr) != 0) {
1298 if (scheduler !=
Qnil) {
1308 if (timeout !=
Qnil) {
1313 int ready = rb_thread_wait_for_single_fd(fptr->
fd,
RB_NUM2INT(events), tv);
1333 return prep_io(fd, FMODE_PREP,
rb_cIO, NULL);
1337 io_wait_for_single_fd(
int fd,
int events,
struct timeval *timeout)
1341 if (scheduler !=
Qnil) {
1347 return rb_thread_wait_for_single_fd(fd, events, timeout);
1353 io_fd_check_closed(f);
1359 #if defined(ERESTART)
1366 #if EWOULDBLOCK != EAGAIN
1369 if (scheduler !=
Qnil) {
1387 io_fd_check_closed(f);
1393 #if defined(ERESTART)
1409 #if EWOULDBLOCK != EAGAIN
1412 if (scheduler !=
Qnil) {
1430 return io_wait_for_single_fd(fd, events, timeout);
1464 #if defined(ERESTART)
1474 #if EWOULDBLOCK != EAGAIN
1491 if (
RTEST(result)) {
1504 if (
RTEST(result)) {
1516 const char *senc, *denc;
1583 io_binwrite_string(
VALUE arg)
1590 struct iovec iov[2];
1593 iov[0].iov_len = fptr->
wbuf.
len;
1594 iov[1].iov_base = (
char *)p->ptr;
1595 iov[1].iov_len = p->length;
1597 r = rb_writev_internal(fptr, iov, 2);
1614 r = rb_write_internal(fptr, p->ptr, p->length);
1621 io_binwrite_string(
VALUE arg)
1627 l = len = p->length;
1630 if (fptr->
wbuf.
len+len <= fptr->wbuf.capa) {
1639 if (io_fflush(fptr) < 0)
1645 return rb_write_internal(p->fptr, p->ptr, p->length);
1650 io_binwrite(
VALUE str,
const char *ptr,
long len,
rb_io_t *fptr,
int nosync)
1652 long n, r, offset = 0;
1657 if ((n = len) <= 0)
return n;
1662 fptr->
wbuf.
capa = IO_WBUF_CAPA_MIN;
1675 arg.ptr = ptr + offset;
1682 r = io_binwrite_string((
VALUE)&arg);
1686 if (r == n)
return len;
1717 # define MODE_BTMODE(a,b,c) ((fmode & FMODE_BINMODE) ? (b) : \
1718 (fmode & FMODE_TEXTMODE) ? (c) : (a))
1720 #define MODE_BTXMODE(a, b, c, d, e, f) ((fmode & FMODE_EXCL) ? \
1721 MODE_BTMODE(d, e, f) : \
1722 MODE_BTMODE(a, b, c))
1727 if (NEED_WRITECONV(fptr)) {
1729 SET_BINARY_MODE(fptr);
1731 make_writeconv(fptr);
1734 #define fmode (fptr->mode)
1738 rb_raise(
rb_eArgError,
"ASCII incompatible string written for text mode IO without encoding conversion: %s",
1750 if (!
NIL_P(common_encoding)) {
1761 #if RUBY_CRLF_ENVIRONMENT
1762 #define fmode (fptr->mode)
1763 else if (MODE_BTMODE(DEFAULT_TEXTMODE,0,1)) {
1766 setmode(fptr->
fd, O_BINARY);
1769 setmode(fptr->
fd, O_TEXT);
1772 rb_raise(
rb_eArgError,
"ASCII incompatible string written for text mode IO without encoding conversion: %s",
1790 long len = rb_w32_write_console(str, fptr->
fd);
1791 if (len > 0)
return len;
1794 str = do_writeconv(str, fptr, &converted);
1798 tmp = rb_str_tmp_frozen_acquire(str);
1800 n = io_binwrite(tmp, ptr, len, fptr, nosync);
1801 rb_str_tmp_frozen_release(str, tmp);
1813 return (ssize_t)io_binwrite(0, buf, (
long)size, fptr, 0);
1823 io = GetWriteIO(io);
1836 n = io_fwrite(str, fptr, nosync);
1837 if (n < 0L) rb_sys_fail_on_write(fptr);
1843 struct binwritev_arg {
1845 const struct iovec *iov;
1850 call_writev_internal(
VALUE arg)
1852 struct binwritev_arg *p = (
struct binwritev_arg *)arg;
1853 return rb_writev_internal(p->fptr, p->iov, p->iovcnt);
1857 io_binwritev(
struct iovec *iov,
int iovcnt,
rb_io_t *fptr)
1860 long r, total = 0, written_len = 0;
1865 if (iovcnt == 0)
return 0;
1866 for (i = 1; i < iovcnt; i++) total += iov[i].iov_len;
1871 fptr->
wbuf.
capa = IO_WBUF_CAPA_MIN;
1879 if (offset + total <= fptr->wbuf.capa) {
1880 for (i = 1; i < iovcnt; i++) {
1881 memcpy(fptr->
wbuf.
ptr+offset, iov[i].iov_base, iov[i].iov_len);
1882 offset += iov[i].iov_len;
1889 iov[0].iov_len = fptr->
wbuf.
len;
1894 if (!--iovcnt)
return 0;
1899 struct binwritev_arg arg;
1902 arg.iovcnt = iovcnt;
1906 r = rb_writev_internal(fptr, iov, iovcnt);
1912 if (written_len < fptr->wbuf.len) {
1917 written_len -= fptr->
wbuf.
len;
1922 if (written_len == total)
return total;
1924 while (r >= (ssize_t)iov->iov_len) {
1929 if (!--iovcnt)
return total;
1932 iov->iov_base = (
char *)iov->iov_base + r;
1948 int i, converted, iovcnt = argc + 1;
1950 VALUE v1, v2, str, tmp, *tmp_array;
1956 for (i = 0; i < argc; i++) {
1959 str = do_writeconv(str, fptr, &converted);
1963 tmp = rb_str_tmp_frozen_acquire(str);
1970 n = io_binwritev(iov, iovcnt, fptr);
1973 for (i = 0; i < argc; i++) {
1974 rb_str_tmp_frozen_release(argv[i], tmp_array[i]);
1983 iovcnt_ok(
int iovcnt)
1986 return iovcnt < IOV_MAX;
1994 io_writev(
int argc,
const VALUE *argv,
VALUE io)
2001 io = GetWriteIO(io);
2012 for (i = 0; i < argc; i += cnt) {
2015 n = io_fwritev(cnt, &argv[i], fptr);
2024 if (n < 0L) rb_sys_fail_on_write(fptr);
2025 total = rb_fix_plus(
LONG2FIX(n), total);
2054 return io_writev(argc, argv, io);
2057 VALUE str = argv[0];
2058 return io_write(io, str, 0);
2069 rb_io_writev(
VALUE io,
int argc,
const VALUE *argv)
2076 " which accepts just one argument",
2114 nogvl_fsync(
void *ptr)
2119 if (GetFileType((HANDLE)rb_w32_get_osfhandle(fptr->
fd)) != FILE_TYPE_DISK)
2122 return (
VALUE)fsync(fptr->
fd);
2127 rb_io_flush_raw(
VALUE io,
int sync)
2135 io = GetWriteIO(io);
2139 if (io_fflush(fptr) < 0)
2140 rb_sys_fail_on_write(fptr);
2164 return rb_io_flush_raw(io, 1);
2186 rb_io_tell(
VALUE io)
2192 pos = io_tell(fptr);
2193 if (pos < 0 && errno) rb_sys_fail_path(fptr->
pathv);
2199 rb_io_seek(
VALUE io,
VALUE offset,
int whence)
2206 pos = io_seek(fptr, pos, whence);
2207 if (pos < 0 && errno) rb_sys_fail_path(fptr->
pathv);
2213 interpret_seek_whence(
VALUE vwhence)
2215 if (vwhence == sym_SET)
2217 if (vwhence == sym_CUR)
2219 if (vwhence == sym_END)
2222 if (vwhence == sym_DATA)
2226 if (vwhence == sym_HOLE)
2277 rb_io_seek_m(
int argc,
VALUE *argv,
VALUE io)
2279 VALUE offset, ptrname;
2280 int whence = SEEK_SET;
2282 if (
rb_scan_args(argc, argv,
"11", &offset, &ptrname) == 2) {
2283 whence = interpret_seek_whence(ptrname);
2286 return rb_io_seek(io, offset, whence);
2313 pos = io_seek(fptr, pos, SEEK_SET);
2314 if (pos < 0 && errno) rb_sys_fail_path(fptr->
pathv);
2319 static void clear_readconv(
rb_io_t *fptr);
2345 rb_io_rewind(
VALUE io)
2350 if (io_seek(fptr, 0L, 0) < 0 && errno) rb_sys_fail_path(fptr->
pathv);
2351 if (io == ARGF.current_file) {
2352 ARGF.lineno -= fptr->
lineno;
2356 clear_readconv(fptr);
2363 fptr_wait_readable(
rb_io_t *fptr)
2381 fptr->
rbuf.
capa = IO_RBUF_CAPA_FOR(fptr);
2392 if (fptr_wait_readable(fptr))
2401 rb_syserr_fail_path(e, path);
2457 if (READ_CHAR_PENDING(fptr))
return Qfalse;
2458 if (READ_DATA_PENDING(fptr))
return Qfalse;
2460 #if RUBY_CRLF_ENVIRONMENT
2461 if (!NEED_READCONV(fptr) && NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {
2462 return RBOOL(eof(fptr->
fd));;
2465 return RBOOL(io_fillbuf(fptr) < 0);
2484 rb_io_sync(
VALUE io)
2488 io = GetWriteIO(io);
2524 io = GetWriteIO(io);
2554 rb_io_fsync(
VALUE io)
2558 io = GetWriteIO(io);
2561 if (io_fflush(fptr) < 0)
2562 rb_sys_fail_on_write(fptr);
2563 if ((
int)rb_thread_io_blocking_region(nogvl_fsync, fptr, fptr->
fd) < 0)
2564 rb_sys_fail_path(fptr->
pathv);
2568 # define rb_io_fsync rb_f_notimplement
2569 # define rb_io_sync rb_f_notimplement
2578 #ifdef HAVE_FDATASYNC
2580 nogvl_fdatasync(
void *ptr)
2585 if (GetFileType((HANDLE)rb_w32_get_osfhandle(fptr->
fd)) != FILE_TYPE_DISK)
2588 return (
VALUE)fdatasync(fptr->
fd);
2603 rb_io_fdatasync(
VALUE io)
2607 io = GetWriteIO(io);
2610 if (io_fflush(fptr) < 0)
2611 rb_sys_fail_on_write(fptr);
2613 if ((
int)rb_thread_io_blocking_region(nogvl_fdatasync, fptr, fptr->
fd) == 0)
2617 return rb_io_fsync(io);
2620 #define rb_io_fdatasync rb_io_fsync
2639 rb_io_fileno(
VALUE io)
2708 rb_io_inspect(
VALUE obj)
2712 static const char closed[] =
" (closed)";
2714 fptr =
RFILE(obj)->fptr;
2721 rb_str_cat(result, closed+1, strlen(closed)-1);
2745 rb_io_to_io(
VALUE io)
2752 read_buffered_data(
char *ptr,
long len,
rb_io_t *fptr)
2756 n = READ_DATA_PENDING_COUNT(fptr);
2757 if (n <= 0)
return 0;
2758 if (n > len) n = (int)len;
2766 io_bufread(
char *ptr,
long len,
rb_io_t *fptr)
2772 if (READ_DATA_PENDING(fptr) == 0) {
2776 c = rb_read_internal(fptr, ptr+offset, n);
2779 if (fptr_wait_readable(fptr))
2784 if ((n -= c) <= 0)
break;
2790 c = read_buffered_data(ptr+offset, n, fptr);
2793 if ((n -= c) <= 0)
break;
2796 if (io_fillbuf(fptr) < 0) {
2803 static int io_setstrbuf(
VALUE *str,
long len);
2812 bufread_call(
VALUE arg)
2815 p->len = io_bufread(p->str_ptr, p->len, p->fptr);
2820 io_fread(
VALUE str,
long offset,
long size,
rb_io_t *fptr)
2825 io_setstrbuf(&str, offset + size);
2829 rb_str_locktmp_ensure(str, bufread_call, (
VALUE)&arg);
2831 if (len < 0) rb_sys_fail_path(fptr->
pathv);
2839 off_t siz = READ_DATA_PENDING_COUNT(fptr);
2842 if (fstat(fptr->
fd, &st) == 0 && S_ISREG(st.st_mode)
2843 #
if defined(__HAIKU__)
2848 if (io_fflush(fptr) < 0)
2849 rb_sys_fail_on_write(fptr);
2850 pos = lseek(fptr->
fd, 0, SEEK_CUR);
2851 if (st.st_size >= pos && pos >= 0) {
2852 siz += st.st_size - pos;
2853 if (siz > LONG_MAX) {
2872 make_readconv(
rb_io_t *fptr,
int size)
2877 const char *sname, *dname;
2892 if (size < IO_CBUF_CAPA_MIN) size = IO_CBUF_CAPA_MIN;
2898 #define MORE_CHAR_SUSPENDED Qtrue
2899 #define MORE_CHAR_FINISHED Qnil
2901 fill_cbuf(
rb_io_t *fptr,
int ec_flags)
2903 const unsigned char *ss, *sp, *se;
2904 unsigned char *ds, *dp, *de;
2913 return MORE_CHAR_SUSPENDED;
2924 ss = sp = (
const unsigned char *)fptr->
rbuf.
ptr + fptr->
rbuf.
off;
2929 fptr->
rbuf.
off += (int)(sp - ss);
2930 fptr->
rbuf.
len -= (int)(sp - ss);
2931 fptr->
cbuf.
len += (int)(dp - ds);
2936 fptr->
rbuf.
off -= putbackable;
2937 fptr->
rbuf.
len += putbackable;
2944 if (cbuf_len0 != fptr->
cbuf.
len)
2945 return MORE_CHAR_SUSPENDED;
2948 return MORE_CHAR_FINISHED;
2954 if (io_fillbuf(fptr) < 0) {
2956 return MORE_CHAR_FINISHED;
2961 fptr->
cbuf.
len += (int)(dp - ds);
2968 if (cbuf_len0 != fptr->
cbuf.
len)
2969 return MORE_CHAR_SUSPENDED;
2971 return MORE_CHAR_FINISHED;
2979 if (v != MORE_CHAR_SUSPENDED && v != MORE_CHAR_FINISHED)
3011 io_setstrbuf(
VALUE *str,
long len)
3014 len = (len + 1) & ~1L;
3033 #define MAX_REALLOC_GAP 4096
3035 io_shrink_read_string(
VALUE str,
long n)
3043 io_set_read_length(
VALUE str,
long n,
int shrinkable)
3048 if (shrinkable) io_shrink_read_string(str, n);
3062 if (NEED_READCONV(fptr)) {
3063 int first = !
NIL_P(str);
3064 SET_BINARY_MODE(fptr);
3065 shrinkable = io_setstrbuf(&str,0);
3066 make_readconv(fptr, 0);
3071 io_shift_cbuf(fptr, fptr->
cbuf.
len, &str);
3073 v = fill_cbuf(fptr, 0);
3074 if (v != MORE_CHAR_SUSPENDED && v != MORE_CHAR_FINISHED) {
3077 io_shift_cbuf(fptr, fptr->
cbuf.
len, &str);
3081 if (v == MORE_CHAR_FINISHED) {
3082 clear_readconv(fptr);
3084 if (shrinkable) io_shrink_read_string(str,
RSTRING_LEN(str));
3085 return io_enc_str(str, fptr);
3090 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
3094 enc = io_read_encoding(fptr);
3097 if (siz == 0) siz = BUFSIZ;
3098 shrinkable = io_setstrbuf(&str, siz);
3101 n = io_fread(str, bytes, siz - bytes, fptr);
3102 if (n == 0 && bytes == 0) {
3110 if (bytes < siz)
break;
3114 if (shrinkable) io_shrink_read_string(str,
RSTRING_LEN(str));
3115 str = io_enc_str(str, fptr);
3123 if (rb_fd_set_nonblock(fptr->
fd) != 0) {
3124 rb_sys_fail_path(fptr->
pathv);
3129 read_internal_call(
VALUE arg)
3134 if (scheduler !=
Qnil) {
3143 return rb_thread_io_blocking_region(internal_read_func, iis, iis->fptr->
fd);
3149 return (
long)rb_str_locktmp_ensure(str, read_internal_call, (
VALUE)iis);
3152 #define no_exception_p(opts) !rb_opts_exception_p((opts), TRUE)
3155 io_getpartial(
int argc,
VALUE *argv,
VALUE io,
int no_exception,
int nonblock)
3165 if ((len =
NUM2LONG(length)) < 0) {
3169 shrinkable = io_setstrbuf(&str, len);
3175 io_set_read_length(str, 0, shrinkable);
3181 n = read_buffered_data(
RSTRING_PTR(str), len, fptr);
3187 io_setstrbuf(&str, len);
3190 iis.nonblock = nonblock;
3193 n = read_internal_locktmp(str, &iis);
3196 if (!nonblock && fptr_wait_readable(fptr))
3198 if (nonblock && (io_again_p(e))) {
3200 return sym_wait_readable;
3203 e,
"read would block");
3205 rb_syserr_fail_path(e, fptr->
pathv);
3208 io_set_read_length(str, n, shrinkable);
3308 io_readpartial(
int argc,
VALUE *argv,
VALUE io)
3312 ret = io_getpartial(argc, argv, io,
Qnil, 0);
3319 io_nonblock_eof(
int no_exception)
3321 if (!no_exception) {
3336 if ((len =
NUM2LONG(length)) < 0) {
3340 shrinkable = io_setstrbuf(&str, len);
3341 rb_bool_expected(ex,
"exception");
3347 io_set_read_length(str, 0, shrinkable);
3351 n = read_buffered_data(
RSTRING_PTR(str), len, fptr);
3354 shrinkable |= io_setstrbuf(&str, len);
3359 n = read_internal_locktmp(str, &iis);
3362 if (io_again_p(e)) {
3363 if (!ex)
return sym_wait_readable;
3365 e,
"read would block");
3367 rb_syserr_fail_path(e, fptr->
pathv);
3370 io_set_read_length(str, n, shrinkable);
3373 if (!ex)
return Qnil;
3389 rb_bool_expected(ex,
"exception");
3391 io = GetWriteIO(io);
3395 if (io_fflush(fptr) < 0)
3396 rb_sys_fail_on_write(fptr);
3404 if (io_again_p(e)) {
3406 return sym_wait_writable;
3412 rb_syserr_fail_path(e, fptr->
pathv);
3494 #if RUBY_CRLF_ENVIRONMENT
3500 if (
NIL_P(length)) {
3503 return read_all(fptr, remain_size(fptr), str);
3510 shrinkable = io_setstrbuf(&str,len);
3515 io_set_read_length(str, 0, shrinkable);
3520 #if RUBY_CRLF_ENVIRONMENT
3521 previous_mode = set_binary_mode_with_seek_cur(fptr);
3523 n = io_fread(str, 0, len, fptr);
3524 io_set_read_length(str, n, shrinkable);
3525 #if RUBY_CRLF_ENVIRONMENT
3526 if (previous_mode == O_TEXT) {
3527 setmode(fptr->
fd, O_TEXT);
3530 if (n == 0)
return Qnil;
3536 rscheck(
const char *rsptr,
long rslen,
VALUE rs)
3544 appendline(
rb_io_t *fptr,
int delim,
VALUE *strp,
long *lp)
3549 if (NEED_READCONV(fptr)) {
3550 SET_BINARY_MODE(fptr);
3551 make_readconv(fptr, 0);
3554 int searchlen = READ_CHAR_PENDING_COUNT(fptr);
3556 p = READ_CHAR_PENDING_PTR(fptr);
3557 if (0 < limit && limit < searchlen)
3558 searchlen = (int)limit;
3559 e = memchr(p, delim, searchlen);
3561 int len = (int)(e-p+1);
3586 }
while (more_char(fptr) != MORE_CHAR_FINISHED);
3587 clear_readconv(fptr);
3592 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
3594 long pending = READ_DATA_PENDING_COUNT(fptr);
3596 const char *p = READ_DATA_PENDING_PTR(fptr);
3600 if (limit > 0 && pending > limit) pending = limit;
3601 e = memchr(p, delim, pending);
3602 if (e) pending = e - p + 1;
3612 read_buffered_data(
RSTRING_PTR(str) + last, pending, fptr);
3615 if (e)
return delim;
3620 }
while (io_fillbuf(fptr) >= 0);
3626 swallow(
rb_io_t *fptr,
int term)
3628 if (NEED_READCONV(fptr)) {
3631 SET_BINARY_MODE(fptr);
3632 make_readconv(fptr, 0);
3635 while ((cnt = READ_CHAR_PENDING_COUNT(fptr)) > 0) {
3636 const char *p = READ_CHAR_PENDING_PTR(fptr);
3639 if (*p != term)
return TRUE;
3641 while (--i && *++p == term);
3644 const char *e = p + cnt;
3646 while ((p += i) < e &&
rb_enc_ascget(p, e, &i, enc) == term);
3649 io_shift_cbuf(fptr, (
int)cnt - i, NULL);
3651 }
while (more_char(fptr) != MORE_CHAR_FINISHED);
3655 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
3658 while ((cnt = READ_DATA_PENDING_COUNT(fptr)) > 0) {
3660 const char *p = READ_DATA_PENDING_PTR(fptr);
3662 if (cnt >
sizeof buf) cnt =
sizeof buf;
3663 if (*p != term)
return TRUE;
3665 while (--i && *++p == term);
3666 if (!read_buffered_data(buf, cnt - i, fptr))
3667 rb_sys_fail_path(fptr->
pathv);
3670 }
while (io_fillbuf(fptr) == 0);
3683 int pending = READ_DATA_PENDING_COUNT(fptr);
3686 const char *p = READ_DATA_PENDING_PTR(fptr);
3690 e = memchr(p,
'\n', pending);
3692 pending = (int)(e - p + 1);
3694 chomplen = (pending > 1 && *(e-1) ==
'\r') + 1;
3704 read_buffered_data(
RSTRING_PTR(str)+len, pending - chomplen, fptr);
3707 if (pending == 1 && chomplen == 1 && len > 0) {
3714 len += pending - chomplen;
3720 }
while (io_fillbuf(fptr) >= 0);
3723 str = io_enc_str(str, fptr);
3734 unsigned int chomp: 1;
3750 args->chomp = chomp;
3768 else if (2 <= argc) {
3769 rs = argv[0], lim = argv[1];
3778 check_getline_args(
VALUE *rsp,
long *limit,
VALUE io)
3788 enc_io = io_read_encoding(fptr);
3789 if (enc_io != enc_rs &&
3810 argc =
rb_scan_args(argc, argv,
"02:", NULL, NULL, &opts);
3811 extract_getline_args(argc, argv, args);
3812 extract_getline_opts(opts, args);
3813 check_getline_args(&args->rs, &args->limit, io);
3817 rb_io_getline_0(
VALUE rs,
long limit,
int chomp,
rb_io_t *fptr)
3824 if (
NIL_P(rs) && limit < 0) {
3825 str = read_all(fptr, 0,
Qnil);
3829 else if (limit == 0) {
3832 else if (rs ==
rb_default_rs && limit < 0 && !NEED_READCONV(fptr) &&
3834 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
3835 return rb_io_getline_fast(fptr, enc, chomp);
3838 int c, newline = -1;
3839 const char *rsptr = 0;
3842 int extra_limit = 16;
3843 int chomp_cr = chomp;
3845 SET_BINARY_MODE(fptr);
3846 enc = io_read_encoding(fptr);
3854 swallow(fptr,
'\n');
3867 newline = (
unsigned char)rsptr[rslen - 1];
3868 chomp_cr = chomp && rslen == 1 && newline ==
'\n';
3872 while ((c = appendline(fptr, newline, &str, &limit)) != EOF) {
3873 const char *s, *p, *pp, *e;
3881 if (pp != p)
continue;
3882 if (!rspara) rscheck(rsptr, rslen, rs);
3883 if (memcmp(p, rsptr, rslen) == 0) {
3885 if (chomp_cr && p > s && *(p-1) ==
'\r') --p;
3909 if (rspara && c != EOF)
3910 swallow(fptr,
'\n');
3912 str = io_enc_str(str, fptr);
3915 if (!
NIL_P(str) && !nolimit) {
3923 rb_io_getline_1(
VALUE rs,
long limit,
int chomp,
VALUE io)
3926 int old_lineno, new_lineno;
3930 old_lineno = fptr->
lineno;
3931 str = rb_io_getline_0(rs, limit, chomp, fptr);
3932 if (!
NIL_P(str) && (new_lineno = fptr->
lineno) != old_lineno) {
3933 if (io == ARGF.current_file) {
3934 ARGF.lineno += new_lineno - old_lineno;
3935 ARGF.last_lineno = ARGF.lineno;
3938 ARGF.last_lineno = new_lineno;
3946 rb_io_getline(
int argc,
VALUE *argv,
VALUE io)
3950 prepare_getline_args(argc, argv, &args, io);
3951 return rb_io_getline_1(args.rs, args.limit, args.chomp, io);
3961 rb_io_gets_internal(
VALUE io)
4043 rb_io_gets_m(
int argc,
VALUE *argv,
VALUE io)
4047 str = rb_io_getline(argc, argv, io);
4076 rb_io_lineno(
VALUE io)
4123 rb_io_readline(
int argc,
VALUE *argv,
VALUE io)
4125 VALUE line = rb_io_gets_m(argc, argv, io);
4160 rb_io_readlines(
int argc,
VALUE *argv,
VALUE io)
4164 prepare_getline_args(argc, argv, &args, io);
4165 return io_readlines(&args, io);
4173 if (arg->limit == 0)
4176 while (!
NIL_P(line = rb_io_getline_1(arg->rs, arg->limit, arg->chomp, io))) {
4214 rb_io_each_line(
int argc,
VALUE *argv,
VALUE io)
4220 prepare_getline_args(argc, argv, &args, io);
4221 if (args.limit == 0)
4223 while (!
NIL_P(str = rb_io_getline_1(args.rs, args.limit, args.chomp, io))) {
4247 rb_io_each_byte(
VALUE io)
4263 }
while (io_fillbuf(fptr) >= 0);
4273 if (NEED_READCONV(fptr)) {
4277 SET_BINARY_MODE(fptr);
4278 make_readconv(fptr, 0);
4292 if (more_char(fptr) == MORE_CHAR_FINISHED) {
4294 clear_readconv(fptr);
4301 if (fptr->
cbuf.
len == 0) clear_readconv(fptr);
4310 io_shift_cbuf(fptr, r, &str);
4321 str = io_enc_str(str, fptr);
4326 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
4327 if (io_fillbuf(fptr) < 0) {
4349 if (io_fillbuf(fptr) != -1) {
4369 str = io_enc_str(str, fptr);
4390 rb_io_each_char(
VALUE io)
4400 enc = io_input_encoding(fptr);
4402 while (!
NIL_P(c = io_getc(fptr, enc))) {
4422 rb_io_each_codepoint(
VALUE io)
4434 if (NEED_READCONV(fptr)) {
4435 SET_BINARY_MODE(fptr);
4438 make_readconv(fptr, 0);
4446 r = ONIGENC_CONSTRUCT_MBCLEN_CHARFOUND(1);
4453 if (more_char(fptr) == MORE_CHAR_FINISHED) {
4454 clear_readconv(fptr);
4481 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
4482 enc = io_input_encoding(fptr);
4483 while (io_fillbuf(fptr) >= 0) {
4498 char cbuf[8], *p = cbuf;
4500 if (more > numberof(cbuf))
goto invalid;
4502 if (more > numberof(cbuf))
goto invalid;
4503 while ((n = (
int)read_buffered_data(p, more, fptr)) > 0 &&
4504 (p += n, (more -= n) > 0)) {
4505 if (io_fillbuf(fptr) < 0)
goto invalid;
4506 if ((n = fptr->
rbuf.
len) > more) n = more;
4538 rb_io_getc(
VALUE io)
4546 enc = io_input_encoding(fptr);
4548 return io_getc(fptr, enc);
4564 rb_io_readchar(
VALUE io)
4566 VALUE c = rb_io_getc(io);
4603 if (io_fillbuf(fptr) < 0) {
4621 rb_io_readbyte(
VALUE io)
4680 unsigned char c =
NUM2INT(v) & 0xFF;
4686 io_ungetbyte(b, fptr);
4733 else if (RB_BIGNUM_TYPE_P(c)) {
4739 if (NEED_READCONV(fptr)) {
4740 SET_BINARY_MODE(fptr);
4742 #if SIZEOF_LONG > SIZEOF_INT
4746 make_readconv(fptr, (
int)len);
4760 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
4761 io_ungetbyte(c, fptr);
4779 rb_io_isatty(
VALUE io)
4784 return RBOOL(isatty(fptr->
fd) != 0);
4787 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
4803 rb_io_close_on_exec_p(
VALUE io)
4809 write_io = GetWriteIO(io);
4810 if (io != write_io) {
4812 if (fptr && 0 <= (fd = fptr->
fd)) {
4813 if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->
pathv);
4814 if (!(ret & FD_CLOEXEC))
return Qfalse;
4819 if (fptr && 0 <= (fd = fptr->
fd)) {
4820 if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->
pathv);
4821 if (!(ret & FD_CLOEXEC))
return Qfalse;
4826 #define rb_io_close_on_exec_p rb_f_notimplement
4829 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
4853 int flag =
RTEST(arg) ? FD_CLOEXEC : 0;
4858 write_io = GetWriteIO(io);
4859 if (io != write_io) {
4861 if (fptr && 0 <= (fd = fptr->
fd)) {
4862 if ((ret = fcntl(fptr->
fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->
pathv);
4863 if ((ret & FD_CLOEXEC) != flag) {
4864 ret = (ret & ~FD_CLOEXEC) | flag;
4865 ret = fcntl(fd, F_SETFD, ret);
4866 if (ret != 0) rb_sys_fail_path(fptr->
pathv);
4873 if (fptr && 0 <= (fd = fptr->
fd)) {
4874 if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->
pathv);
4875 if ((ret & FD_CLOEXEC) != flag) {
4876 ret = (ret & ~FD_CLOEXEC) | flag;
4877 ret = fcntl(fd, F_SETFD, ret);
4878 if (ret != 0) rb_sys_fail_path(fptr->
pathv);
4884 #define rb_io_set_close_on_exec rb_f_notimplement
4887 #define IS_PREP_STDIO(f) ((f)->mode & FMODE_PREP)
4888 #define PREP_STDIO_NAME(f) (RSTRING_PTR((f)->pathv))
4891 finish_writeconv(
rb_io_t *fptr,
int noalloc)
4893 unsigned char *ds, *dp, *de;
4897 unsigned char buf[1024];
4903 de = buf +
sizeof(buf);
4907 r = rb_write_internal(fptr, ds, dp-ds);
4933 if (io_fflush(fptr) < 0)
4940 fptr->
wbuf.
len += (int)(dp - ds);
4956 finish_writeconv_sync(
VALUE arg)
4959 return finish_writeconv(p->fptr, p->noalloc);
4963 nogvl_close(
void *ptr)
4967 return (
void*)(intptr_t)close(*fd);
4971 maygvl_close(
int fd,
int keepgvl)
4984 nogvl_fclose(
void *ptr)
4988 return (
void*)(intptr_t)fclose(file);
4992 maygvl_fclose(
FILE *file,
int keepgvl)
4995 return fclose(file);
5001 static void clear_codeconv(
rb_io_t *fptr);
5004 fptr_finalize_flush(
rb_io_t *fptr,
int noraise,
int keepgvl,
5005 struct list_head *busy)
5010 int mode = fptr->
mode;
5016 arg.noalloc = noraise;
5020 err = finish_writeconv(fptr, noraise);
5025 io_flush_buffer_sync(fptr);
5028 if (io_fflush(fptr) < 0 &&
NIL_P(err))
5035 if (IS_PREP_STDIO(fptr) || fd <= 2) {
5059 if (!done && stdio_file) {
5061 if ((maygvl_fclose(stdio_file, noraise) < 0) &&
NIL_P(err))
5062 if (!noraise) err =
INT2NUM(errno);
5067 if (!done && fd >= 0) {
5073 if ((maygvl_close(fd, keepgvl) < 0) &&
NIL_P(err))
5074 if (!noraise) err =
INT2NUM(errno);
5079 if (!
NIL_P(err) && !noraise) {
5088 fptr_finalize(
rb_io_t *fptr,
int noraise)
5090 fptr_finalize_flush(fptr, noraise, FALSE, 0);
5091 free_io_buffer(&fptr->
rbuf);
5092 free_io_buffer(&fptr->
wbuf);
5093 clear_codeconv(fptr);
5097 rb_io_fptr_cleanup(
rb_io_t *fptr,
int noraise)
5103 fptr_finalize(fptr, noraise);
5111 ruby_sized_xfree(buf->
ptr, (
size_t)buf->
capa);
5123 free_io_buffer(&fptr->
cbuf);
5127 clear_writeconv(
rb_io_t *fptr)
5139 clear_readconv(fptr);
5140 clear_writeconv(fptr);
5144 rb_io_fptr_finalize_internal(
void *ptr)
5151 rb_io_fptr_cleanup(fptr, TRUE);
5153 free_io_buffer(&fptr->
rbuf);
5154 free_io_buffer(&fptr->
wbuf);
5155 clear_codeconv(fptr);
5159 #undef rb_io_fptr_finalize
5167 rb_io_fptr_finalize_internal(fptr);
5171 #define rb_io_fptr_finalize(fptr) rb_io_fptr_finalize_internal(fptr)
5173 RUBY_FUNC_EXPORTED
size_t
5174 rb_io_memsize(
const rb_io_t *fptr)
5176 size_t size =
sizeof(
rb_io_t);
5187 # define KEEPGVL TRUE
5189 # define KEEPGVL FALSE
5192 int rb_notify_fd_close(
int fd,
struct list_head *);
5194 io_close_fptr(
VALUE io)
5199 struct list_head busy;
5201 list_head_init(&busy);
5202 write_io = GetWriteIO(io);
5203 if (io != write_io) {
5204 write_fptr =
RFILE(write_io)->fptr;
5205 if (write_fptr && 0 <= write_fptr->
fd) {
5206 rb_io_fptr_cleanup(write_fptr, TRUE);
5210 fptr =
RFILE(io)->fptr;
5211 if (!fptr)
return 0;
5212 if (fptr->
fd < 0)
return 0;
5214 if (rb_notify_fd_close(fptr->
fd, &busy)) {
5216 fptr_finalize_flush(fptr, FALSE, KEEPGVL, &busy);
5218 rb_io_fptr_cleanup(fptr, FALSE);
5223 fptr_waitpid(
rb_io_t *fptr,
int nohang)
5227 rb_last_status_clear();
5236 rb_io_t *fptr = io_close_fptr(io);
5237 if (fptr) fptr_waitpid(fptr, 0);
5257 rb_io_close_m(
VALUE io)
5259 rb_io_t *fptr = rb_io_get_fptr(io);
5268 io_call_close(
VALUE io)
5277 enum {mesg_len =
sizeof(closed_stream)-1};
5281 memcmp(
RSTRING_PTR(mesg), closed_stream, mesg_len)) {
5292 rb_rescue2(io_call_close, io, ignore_closed_stream, io,
5317 rb_io_closed(
VALUE io)
5323 write_io = GetWriteIO(io);
5324 if (io != write_io) {
5325 write_fptr =
RFILE(write_io)->fptr;
5326 if (write_fptr && 0 <= write_fptr->
fd) {
5331 fptr = rb_io_get_fptr(io);
5332 return RBOOL(0 > fptr->
fd);
5356 rb_io_close_read(
VALUE io)
5362 if (fptr->
fd < 0)
return Qnil;
5363 if (is_socket(fptr->
fd, fptr->
pathv)) {
5367 if (shutdown(fptr->
fd, SHUT_RD) < 0)
5368 rb_sys_fail_path(fptr->
pathv);
5375 write_io = GetWriteIO(io);
5376 if (io != write_io) {
5381 RFILE(io)->fptr = wfptr;
5384 RFILE(write_io)->fptr = fptr;
5385 rb_io_fptr_cleanup(fptr, FALSE);
5418 rb_io_close_write(
VALUE io)
5423 write_io = GetWriteIO(io);
5425 if (fptr->
fd < 0)
return Qnil;
5426 if (is_socket(fptr->
fd, fptr->
pathv)) {
5430 if (shutdown(fptr->
fd, SHUT_WR) < 0)
5431 rb_sys_fail_path(fptr->
pathv);
5442 if (io != write_io) {
5464 rb_io_sysseek(
int argc,
VALUE *argv,
VALUE io)
5466 VALUE offset, ptrname;
5467 int whence = SEEK_SET;
5471 if (
rb_scan_args(argc, argv,
"11", &offset, &ptrname) == 2) {
5472 whence = interpret_seek_whence(ptrname);
5477 (READ_DATA_BUFFERED(fptr) || READ_CHAR_PENDING(fptr))) {
5481 rb_warn(
"sysseek for buffered IO");
5484 pos = lseek(fptr->
fd, pos, whence);
5485 if (pos < 0 && errno) rb_sys_fail_path(fptr->
pathv);
5514 io = GetWriteIO(io);
5519 rb_warn(
"syswrite for buffered IO");
5522 tmp = rb_str_tmp_frozen_acquire(str);
5524 n = rb_write_internal(fptr, ptr, len);
5525 if (n < 0) rb_sys_fail_path(fptr->
pathv);
5526 rb_str_tmp_frozen_release(str, tmp);
5551 rb_io_sysread(
int argc,
VALUE *argv,
VALUE io)
5562 shrinkable = io_setstrbuf(&str, ilen);
5563 if (ilen == 0)
return str;
5568 if (READ_DATA_BUFFERED(fptr)) {
5574 io_setstrbuf(&str, ilen);
5580 n = read_internal_locktmp(str, &iis);
5583 rb_sys_fail_path(fptr->
pathv);
5586 io_set_read_length(str, n, shrinkable);
5588 if (n == 0 && ilen > 0) {
5595 #if defined(HAVE_PREAD) || defined(HAVE_PWRITE)
5596 struct prdwr_internal_arg {
5604 #if defined(HAVE_PREAD)
5606 internal_pread_func(
void *arg)
5608 struct prdwr_internal_arg *p = arg;
5609 return (
VALUE)pread(p->fd, p->buf, p->count, p->offset);
5613 pread_internal_call(
VALUE arg)
5615 struct prdwr_internal_arg *p = (
struct prdwr_internal_arg *)arg;
5616 return rb_thread_io_blocking_region(internal_pread_func, p, p->fd);
5644 VALUE len, offset, str;
5647 struct prdwr_internal_arg arg;
5654 shrinkable = io_setstrbuf(&str, (
long)arg.count);
5655 if (arg.count == 0)
return str;
5668 rb_sys_fail_path(fptr->
pathv);
5670 io_set_read_length(str, n, shrinkable);
5671 if (n == 0 && arg.count > 0) {
5678 # define rb_io_pread rb_f_notimplement
5681 #if defined(HAVE_PWRITE)
5683 internal_pwrite_func(
void *ptr)
5685 struct prdwr_internal_arg *arg = ptr;
5687 return (
VALUE)pwrite(arg->fd, arg->buf, arg->count, arg->offset);
5714 struct prdwr_internal_arg arg;
5722 io = GetWriteIO(io);
5727 tmp = rb_str_tmp_frozen_acquire(str);
5731 n = (ssize_t)rb_thread_io_blocking_region(internal_pwrite_func, &arg, fptr->
fd);
5732 if (n < 0) rb_sys_fail_path(fptr->
pathv);
5733 rb_str_tmp_frozen_release(str, tmp);
5738 # define rb_io_pwrite rb_f_notimplement
5756 SET_BINARY_MODE_WITH_SEEK_CUR(fptr);
5759 setmode(fptr->
fd, O_BINARY);
5766 io_ascii8bit_binmode(
rb_io_t *fptr)
5778 SET_BINARY_MODE_WITH_SEEK_CUR(fptr);
5784 clear_codeconv(fptr);
5793 io_ascii8bit_binmode(fptr);
5811 rb_io_binmode_m(
VALUE io)
5817 write_io = GetWriteIO(io);
5830 rb_io_binmode_p(
VALUE io)
5838 rb_io_fmode_modestr(
int fmode)
5842 return MODE_BTMODE(
"a+",
"ab+",
"at+");
5844 return MODE_BTMODE(
"a",
"ab",
"at");
5850 return MODE_BTMODE(
"r",
"rb",
"rt");
5852 return MODE_BTXMODE(
"w",
"wb",
"wt",
"wx",
"wbx",
"wtx");
5855 return MODE_BTXMODE(
"w+",
"wb+",
"wt+",
"w+x",
"wb+x",
"wt+x");
5857 return MODE_BTMODE(
"r+",
"rb+",
"rt+");
5861 static const char bom_prefix[] =
"bom|";
5862 static const char utf_prefix[] =
"utf-";
5863 enum {bom_prefix_len = (int)
sizeof(bom_prefix) - 1};
5864 enum {utf_prefix_len = (int)
sizeof(utf_prefix) - 1};
5867 io_encname_bom_p(
const char *name,
long len)
5869 return len > bom_prefix_len &&
STRNCASECMP(name, bom_prefix, bom_prefix_len) == 0;
5876 const char *m = modestr, *p = NULL;
5904 if (modestr[0] !=
'w')
5912 if (io_encname_bom_p(m, p ? (
long)(p - m) : (
long)strlen(m)))
5930 rb_io_oflags_fmode(
int oflags)
5934 switch (oflags & O_ACCMODE) {
5946 if (oflags & O_APPEND) {
5949 if (oflags & O_TRUNC) {
5952 if (oflags & O_CREAT) {
5955 if (oflags & O_EXCL) {
5959 if (oflags & O_BINARY) {
5968 rb_io_fmode_oflags(
int fmode)
6012 rb_io_oflags_modestr(
int oflags)
6015 # define MODE_BINARY(a,b) ((oflags & O_BINARY) ? (b) : (a))
6017 # define MODE_BINARY(a,b) (a)
6020 if (oflags & O_EXCL) {
6023 accmode = oflags & (O_RDONLY|O_WRONLY|O_RDWR);
6024 if (oflags & O_APPEND) {
6025 if (accmode == O_WRONLY) {
6026 return MODE_BINARY(
"a",
"ab");
6028 if (accmode == O_RDWR) {
6029 return MODE_BINARY(
"a+",
"ab+");
6036 return MODE_BINARY(
"r",
"rb");
6038 return MODE_BINARY(
"w",
"wb");
6040 if (oflags & O_TRUNC) {
6041 return MODE_BINARY(
"w+",
"wb+");
6043 return MODE_BINARY(
"r+",
"rb+");
6055 int default_ext = 0;
6065 else if (intern == NULL) {
6071 *enc = (default_ext && intern != ext) ? NULL : ext;
6081 unsupported_encoding(
const char *name,
rb_encoding *enc)
6083 rb_enc_warn(enc,
"Unsupported encoding %s ignored", name);
6087 parse_mode_enc(
const char *estr,
rb_encoding *estr_enc,
6093 int fmode = fmode_p ? *fmode_p : 0;
6099 p = strrchr(estr,
':');
6100 len = p ? (p++ - estr) : (
long)strlen(estr);
6102 estr += bom_prefix_len;
6103 len -= bom_prefix_len;
6104 if (!
STRNCASECMP(estr, utf_prefix, utf_prefix_len)) {
6108 rb_enc_warn(estr_enc,
"BOM with non-UTF encoding %s is nonsense", estr);
6117 memcpy(encname, estr, len);
6118 encname[len] =
'\0';
6123 if (fmode_p) *fmode_p = fmode;
6129 unsupported_encoding(estr, estr_enc);
6135 if (*p ==
'-' && *(p+1) ==
'\0') {
6142 unsupported_encoding(p, estr_enc);
6151 rb_io_ext_int_to_encs(ext_enc, int_enc, enc_p, enc2_p, fmode);
6165 if (v !=
Qnil) encoding = v;
6167 if (v !=
Qnil) extenc = v;
6169 if (v !=
Qundef) intenc = v;
6175 rb_warn(
"Ignoring encoding parameter '%"PRIsVALUE
"': %s_encoding is used",
6176 encoding, extenc ==
Qundef ?
"internal" :
"external");
6184 if (
NIL_P(intenc)) {
6191 if (*p ==
'-' && *(p+1) ==
'\0') {
6202 if (extencoding == intencoding) {
6206 if (!
NIL_P(encoding)) {
6210 enc_p, enc2_p, fmode_p);
6213 rb_io_ext_int_to_encs(
rb_to_encoding(encoding), NULL, enc_p, enc2_p, 0);
6218 rb_io_ext_int_to_encs(extencoding, intencoding, enc_p, enc2_p, 0);
6228 int fmode = *fmode_p;
6244 #if !DEFAULT_TEXTMODE
6253 extract_binmode(
VALUE opthash,
int *fmode)
6255 if (!
NIL_P(opthash)) {
6283 int *oflags_p,
int *fmode_p, convconfig_t *convconfig_p)
6290 int has_enc = 0, has_vmode = 0;
6296 rb_io_ext_int_to_encs(NULL, NULL, &enc, &enc2, 0);
6306 fmode = rb_io_oflags_fmode(oflags);
6314 oflags = rb_io_fmode_oflags(fmode);
6318 parse_mode_enc(p+1,
rb_enc_get(vmode), &enc, &enc2, &fmode);
6324 rb_io_ext_int_to_encs(e, NULL, &enc, &enc2, fmode);
6328 if (
NIL_P(opthash)) {
6332 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
6334 MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE,
6335 0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE) : 0;
6337 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
6346 #if DEFAULT_TEXTMODE
6347 else if (
NIL_P(vmode)) {
6348 fmode |= DEFAULT_TEXTMODE;
6357 if (!
NIL_P(vmode)) {
6370 fmode = rb_io_oflags_fmode(oflags);
6372 extract_binmode(opthash, &fmode);
6380 #if DEFAULT_TEXTMODE
6381 else if (
NIL_P(vmode)) {
6382 fmode |= DEFAULT_TEXTMODE;
6388 if (!
NIL_P(*vperm_p)) {
6400 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
6402 MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE,
6403 0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE) : 0;
6411 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
6415 validate_enc_binmode(&fmode, ecflags, enc, enc2);
6421 convconfig_p->enc = enc;
6422 convconfig_p->enc2 = enc2;
6423 convconfig_p->ecflags = ecflags;
6424 convconfig_p->ecopts = ecopts;
6434 sysopen_func(
void *ptr)
6452 rb_sysopen(
VALUE fname,
int oflags, mode_t perm)
6459 data.oflags = oflags;
6462 fd = rb_sysopen_internal(&data);
6465 if (rb_gc_for_fd(e)) {
6466 fd = rb_sysopen_internal(&data);
6469 rb_syserr_fail_path(e, fname);
6483 file = fdopen(fd, modestr);
6490 file = fdopen(fd, modestr);
6494 if (rb_gc_for_fd(e)) {
6495 file = fdopen(fd, modestr);
6499 if (e == 0) e = EINVAL;
6500 #elif defined(__sun)
6501 if (e == 0) e = EMFILE;
6509 if (setvbuf(file, NULL, _IOFBF, 0) != 0)
6510 rb_warn(
"setvbuf() can't be honoured (fd=%d)", fd);
6518 int t = isatty(fptr->
fd);
6528 io_strip_bom(
VALUE io)
6530 VALUE b1, b2, b3, b4;
6551 return ENCINDEX_UTF_16BE;
6562 return ENCINDEX_UTF_32LE;
6567 return ENCINDEX_UTF_16LE;
6577 return ENCINDEX_UTF_32BE;
6591 io_set_encoding_by_bom(
VALUE io)
6593 int idx = io_strip_bom(io);
6601 rb_io_internal_encoding(io),
Qnil);
6610 rb_file_open_generic(
VALUE io,
VALUE filename,
int oflags,
int fmode,
6611 const convconfig_t *convconfig, mode_t perm)
6618 rb_io_ext_int_to_encs(NULL, NULL, &cc.enc, &cc.enc2, fmode);
6623 validate_enc_binmode(&fmode, convconfig->ecflags,
6624 convconfig->enc, convconfig->enc2);
6628 fptr->
encs = *convconfig;
6631 if (!(oflags & O_TMPFILE)) {
6632 fptr->
pathv = pathv;
6635 fptr->
pathv = pathv;
6637 fptr->
fd = rb_sysopen(pathv, oflags, perm);
6645 rb_file_open_internal(
VALUE io,
VALUE filename,
const char *modestr)
6648 const char *p = strchr(modestr,
':');
6649 convconfig_t convconfig;
6653 &convconfig.enc, &convconfig.enc2, &fmode);
6654 convconfig.ecflags = 0;
6655 convconfig.ecopts =
Qnil;
6662 rb_io_ext_int_to_encs(e, NULL, &convconfig.enc, &convconfig.enc2, fmode);
6663 convconfig.ecflags = 0;
6664 convconfig.ecopts =
Qnil;
6667 return rb_file_open_generic(io, filename,
6668 rb_io_fmode_oflags(fmode),
6678 return rb_file_open_internal(io_alloc(
rb_cFile), fname, modestr);
6687 #if defined(__CYGWIN__) || !defined(HAVE_WORKING_FORK)
6710 while ((tmp = *prev) != 0) {
6711 if (tmp->fptr == fptr) {
6720 #if defined (_WIN32) || defined(__CYGWIN__)
6736 pipe_finalize(
rb_io_t *fptr,
int noraise)
6738 #if !defined(HAVE_WORKING_FORK) && !defined(_WIN32)
6747 fptr_finalize(fptr, noraise);
6749 pipe_del_fptr(fptr);
6756 #if defined(__CYGWIN__) || !defined(HAVE_WORKING_FORK)
6759 if (old_finalize == orig->
finalize)
return;
6764 #if defined(__CYGWIN__) || !defined(HAVE_WORKING_FORK)
6765 if (old_finalize != pipe_finalize) {
6767 for (list =
pipe_list; list; list = list->next) {
6768 if (list->fptr == fptr)
break;
6770 if (!list) pipe_add_fptr(fptr);
6773 pipe_del_fptr(fptr);
6786 rb_io_unbuffered(
rb_io_t *fptr)
6797 if (rb_gc_for_fd(errno)) {
6809 #define HAVE_SPAWNV 1
6810 #define spawnv(mode, cmd, args) rb_w32_uaspawn((mode), (cmd), (args))
6811 #define spawn(mode, cmd) rb_w32_uspawn((mode), (cmd), 0)
6814 #if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
6824 #ifdef HAVE_WORKING_FORK
6825 # ifndef __EMSCRIPTEN__
6827 popen_redirect(
struct popen_arg *p)
6830 close(p->write_pair[1]);
6831 if (p->write_pair[0] != 0) {
6832 dup2(p->write_pair[0], 0);
6833 close(p->write_pair[0]);
6836 if (p->pair[1] != 1) {
6837 dup2(p->pair[1], 1);
6843 if (p->pair[1] != 1) {
6844 dup2(p->pair[1], 1);
6850 if (p->pair[0] != 0) {
6851 dup2(p->pair[0], 0);
6858 #if defined(__linux__)
6869 linux_get_maxfd(
void)
6872 char buf[4096], *p, *np, *e;
6875 if (fd < 0)
return fd;
6876 ss = read(fd, buf,
sizeof(buf));
6877 if (ss < 0)
goto err;
6880 while ((
int)
sizeof(
"FDSize:\t0\n")-1 <= e-p &&
6881 (np = memchr(p,
'\n', e-p)) != NULL) {
6882 if (memcmp(p,
"FDSize:",
sizeof(
"FDSize:")-1) == 0) {
6884 p +=
sizeof(
"FDSize:")-1;
6904 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
6906 int max = (int)max_file_descriptor;
6909 ret = fcntl(0, F_MAXFD);
6911 maxhint = max = ret;
6912 # elif defined(__linux__)
6913 ret = linux_get_maxfd();
6920 for (fd = lowfd; fd <= max; fd++) {
6921 if (!
NIL_P(noclose_fds) &&
6924 ret = fcntl(fd, F_GETFD);
6925 if (ret != -1 && !(ret & FD_CLOEXEC)) {
6926 fcntl(fd, F_SETFD, ret|FD_CLOEXEC);
6928 # define CONTIGUOUS_CLOSED_FDS 20
6930 if (max < fd + CONTIGUOUS_CLOSED_FDS)
6931 max = fd + CONTIGUOUS_CLOSED_FDS;
6937 # ifndef __EMSCRIPTEN__
6939 popen_exec(
void *pp,
char *errmsg,
size_t errmsg_len)
6941 struct popen_arg *p = (
struct popen_arg*)pp;
6943 return rb_exec_async_signal_safe(p->eargp, errmsg, errmsg_len);
6948 #if (defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)) && !defined __EMSCRIPTEN__
6950 rb_execarg_fixup_v(
VALUE execarg_obj)
6952 rb_execarg_parent_start(execarg_obj);
6956 char *rb_execarg_commandline(
const struct rb_execarg *eargp,
VALUE *prog);
6959 #ifndef __EMSCRIPTEN__
6961 pipe_open(
VALUE execarg_obj,
const char *modestr,
int fmode,
6962 const convconfig_t *convconfig)
6964 struct rb_execarg *eargp =
NIL_P(execarg_obj) ? NULL : rb_execarg_get(execarg_obj);
6965 VALUE prog = eargp ? (eargp->use_shell ? eargp->invoke.sh.shell_script : eargp->invoke.cmd.command_name) :
Qfalse ;
6971 #if defined(HAVE_WORKING_FORK)
6973 char errmsg[80] = {
'\0' };
6975 #if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
6977 struct popen_arg arg;
6980 #if defined(HAVE_SPAWNV)
6981 # if defined(HAVE_SPAWNVE)
6982 # define DO_SPAWN(cmd, args, envp) ((args) ? \
6983 spawnve(P_NOWAIT, (cmd), (args), (envp)) : \
6984 spawne(P_NOWAIT, (cmd), (envp)))
6986 # define DO_SPAWN(cmd, args, envp) ((args) ? \
6987 spawnv(P_NOWAIT, (cmd), (args)) : \
6988 spawn(P_NOWAIT, (cmd)))
6990 # if !defined(HAVE_WORKING_FORK)
6992 # if defined(HAVE_SPAWNVE)
6997 #if !defined(HAVE_WORKING_FORK)
7003 #if !defined(HAVE_WORKING_FORK)
7004 const char *cmd = 0;
7010 #if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
7011 arg.execarg_obj = execarg_obj;
7014 arg.pair[0] = arg.pair[1] = -1;
7015 arg.write_pair[0] = arg.write_pair[1] = -1;
7016 # if !defined(HAVE_WORKING_FORK)
7017 if (eargp && !eargp->use_shell) {
7018 args = ARGVSTR2ARGV(eargp->invoke.cmd.argv_str);
7023 if (
rb_pipe(arg.write_pair) < 0)
7027 close(arg.write_pair[0]);
7028 close(arg.write_pair[1]);
7032 rb_execarg_addopt(execarg_obj,
INT2FIX(0),
INT2FIX(arg.write_pair[0]));
7033 rb_execarg_addopt(execarg_obj,
INT2FIX(1),
INT2FIX(arg.pair[1]));
7040 rb_execarg_addopt(execarg_obj,
INT2FIX(1),
INT2FIX(arg.pair[1]));
7046 rb_execarg_addopt(execarg_obj,
INT2FIX(0),
INT2FIX(arg.pair[0]));
7051 if (!
NIL_P(execarg_obj)) {
7052 rb_protect(rb_execarg_fixup_v, execarg_obj, &state);
7054 if (0 <= arg.write_pair[0]) close(arg.write_pair[0]);
7055 if (0 <= arg.write_pair[1]) close(arg.write_pair[1]);
7056 if (0 <= arg.pair[0]) close(arg.pair[0]);
7057 if (0 <= arg.pair[1]) close(arg.pair[1]);
7058 rb_execarg_parent_end(execarg_obj);
7062 # if defined(HAVE_WORKING_FORK)
7063 pid = rb_fork_async_signal_safe(&status, popen_exec, &arg, arg.eargp->redirect_fds, errmsg,
sizeof(errmsg));
7065 rb_execarg_run_options(eargp, sargp, NULL, 0);
7066 # if defined(HAVE_SPAWNVE)
7067 if (eargp->envp_str) envp = (
char **)
RSTRING_PTR(eargp->envp_str);
7069 while ((pid = DO_SPAWN(cmd, args, envp)) < 0) {
7071 switch (e = errno) {
7073 # if EWOULDBLOCK != EAGAIN
7082 rb_execarg_run_options(sargp, NULL, NULL, 0);
7084 rb_execarg_parent_end(execarg_obj);
7087 # if defined(HAVE_WORKING_FORK)
7088 pid = rb_call_proc__fork();
7090 popen_redirect(&arg);
7102 # if defined(HAVE_WORKING_FORK)
7108 close(arg.write_pair[0]);
7109 close(arg.write_pair[1]);
7111 # if defined(HAVE_WORKING_FORK)
7120 close(arg.write_pair[0]);
7121 write_fd = arg.write_pair[1];
7132 cmd = rb_execarg_commandline(eargp, &prog);
7133 if (!
NIL_P(execarg_obj)) {
7134 rb_execarg_parent_start(execarg_obj);
7135 rb_execarg_run_options(eargp, sargp, NULL, 0);
7137 fp = popen(cmd, modestr);
7140 rb_execarg_parent_end(execarg_obj);
7141 rb_execarg_run_options(sargp, NULL, NULL, 0);
7143 if (!fp) rb_syserr_fail_path(e, prog);
7153 fptr->
encs = *convconfig;
7154 #if RUBY_CRLF_ENVIRONMENT
7161 if (NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {
7164 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
7165 if (NEED_NEWLINE_DECORATOR_ON_WRITE(fptr)) {
7166 fptr->
encs.
ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
7172 if (0 <= write_fd) {
7173 write_port = io_alloc(
rb_cIO);
7175 write_fptr->
fd = write_fd;
7182 #if defined (__CYGWIN__) || !defined(HAVE_WORKING_FORK)
7184 pipe_add_fptr(fptr);
7190 pipe_open(
VALUE execarg_obj,
const char *modestr,
int fmode,
7191 const convconfig_t *convconfig)
7198 is_popen_fork(
VALUE prog)
7201 #if !defined(HAVE_WORKING_FORK)
7203 "fork() function is unimplemented on this machine");
7212 pipe_open_s(
VALUE prog,
const char *modestr,
int fmode,
7213 const convconfig_t *convconfig)
7216 VALUE *argv = &prog;
7219 if (!is_popen_fork(prog))
7220 execarg_obj = rb_execarg_new(argc, argv, TRUE, FALSE);
7221 return pipe_open(execarg_obj, modestr, fmode, convconfig);
7225 pipe_close(
VALUE io)
7227 rb_io_t *fptr = io_close_fptr(io);
7323 rb_io_s_popen(
int argc,
VALUE *argv,
VALUE klass)
7337 int ex = !
NIL_P(opt);
7338 rb_error_arity(argc + ex, 1 + ex, 2 + ex);
7341 return popen_finish(rb_io_popen(pname, pmode, env, opt), klass);
7347 const char *modestr;
7350 convconfig_t convconfig;
7355 #if SIZEOF_LONG > SIZEOF_INT
7356 if (len > INT_MAX) {
7360 execarg_obj = rb_execarg_new((
int)len,
RARRAY_CONST_PTR(tmp), FALSE, FALSE);
7366 if (!is_popen_fork(pname))
7367 execarg_obj = rb_execarg_new(1, &pname, TRUE, FALSE);
7369 if (!
NIL_P(execarg_obj)) {
7371 opt = rb_execarg_extract_options(execarg_obj, opt);
7373 rb_execarg_setenv(execarg_obj, env);
7376 modestr = rb_io_oflags_modestr(oflags);
7378 return pipe_open(execarg_obj, modestr, fmode, &convconfig);
7394 RBASIC_SET_CLASS(port, klass);
7402 rb_scan_open_args(
int argc,
const VALUE *argv,
7403 VALUE *fname_p,
int *oflags_p,
int *fmode_p,
7404 convconfig_t *convconfig_p, mode_t *perm_p)
7406 VALUE opt, fname, vmode, vperm;
7410 argc =
rb_scan_args(argc, argv,
"12:", &fname, &vmode, &vperm, &opt);
7424 rb_open_file(
int argc,
const VALUE *argv,
VALUE io)
7428 convconfig_t convconfig;
7431 rb_scan_open_args(argc, argv, &fname, &oflags, &fmode, &convconfig, &perm);
7432 rb_file_open_generic(io, fname, oflags, fmode, &convconfig, perm);
7475 rb_io_s_open(
int argc,
VALUE *argv,
VALUE klass)
7499 VALUE fname, vmode, vperm;
7504 rb_scan_args(argc, argv,
"12", &fname, &vmode, &vperm);
7515 if (
NIL_P(vperm)) perm = 0666;
7519 fd = rb_sysopen(fname, oflags, perm);
7524 check_pipe_command(
VALUE filename_or_command)
7641 int redirect = FALSE;
7649 VALUE tmp = argv[0];
7655 VALUE cmd = check_pipe_command(tmp);
7658 return rb_io_s_popen(argc, argv,
rb_cIO);
7671 return rb_io_s_open(argc, argv,
rb_cFile);
7674 static VALUE rb_io_open_generic(
VALUE,
VALUE,
int,
int,
const convconfig_t *, mode_t);
7680 convconfig_t convconfig;
7685 return rb_io_open_generic(io, filename, oflags, fmode, &convconfig, perm);
7689 rb_io_open_generic(
VALUE klass,
VALUE filename,
int oflags,
int fmode,
7690 const convconfig_t *convconfig, mode_t perm)
7693 if (klass ==
rb_cIO && !
NIL_P(cmd = check_pipe_command(filename))) {
7694 return pipe_open_s(cmd, rb_io_oflags_modestr(oflags), fmode, convconfig);
7697 return rb_file_open_generic(io_alloc(klass), filename,
7698 oflags, fmode, convconfig, perm);
7713 if (fptr == orig)
return io;
7714 if (IS_PREP_STDIO(fptr)) {
7719 "%s can't change access mode from \"%s\" to \"%s\"",
7720 PREP_STDIO_NAME(fptr), rb_io_fmode_modestr(fptr->
mode),
7721 rb_io_fmode_modestr(orig->
mode));
7725 if (io_fflush(fptr) < 0)
7726 rb_sys_fail_on_write(fptr);
7729 flush_before_seek(fptr);
7732 pos = io_tell(orig);
7735 if (io_fflush(orig) < 0)
7736 rb_sys_fail_on_write(fptr);
7744 else if (!IS_PREP_STDIO(fptr)) fptr->
pathv =
Qnil;
7745 fptr_copy_finalizer(fptr, orig);
7750 if (IS_PREP_STDIO(fptr) || fd <= 2 || !fptr->
stdio_file) {
7753 rb_sys_fail_path(orig->
pathv);
7761 rb_sys_fail_path(orig->
pathv);
7767 if (io_seek(fptr, pos, SEEK_SET) < 0 && errno) {
7768 rb_sys_fail_path(fptr->
pathv);
7770 if (io_seek(orig, pos, SEEK_SET) < 0 && errno) {
7771 rb_sys_fail_path(orig->
pathv);
7785 int rb_freopen(
VALUE fname,
const char *mode,
FILE *fp);
7788 rb_freopen(
VALUE fname,
const char *mode,
FILE *fp)
7816 rb_io_reopen(
int argc,
VALUE *argv,
VALUE file)
7818 VALUE fname, nmode, opt;
7822 if (
rb_scan_args(argc, argv,
"11:", &fname, &nmode, &opt) == 1) {
7825 return io_reopen(file, tmp);
7831 fptr =
RFILE(file)->fptr;
7838 convconfig_t convconfig;
7841 if (IS_PREP_STDIO(fptr) &&
7845 "%s can't change access mode from \"%s\" to \"%s\"",
7846 PREP_STDIO_NAME(fptr), rb_io_fmode_modestr(fptr->
mode),
7847 rb_io_fmode_modestr(fmode));
7850 fptr->
encs = convconfig;
7853 oflags = rb_io_fmode_oflags(fptr->
mode);
7856 fptr->
pathv = fname;
7858 fptr->
fd = rb_sysopen(fptr->
pathv, oflags, 0666);
7864 if (io_fflush(fptr) < 0)
7865 rb_sys_fail_on_write(fptr);
7871 rb_io_oflags_modestr(oflags),
7873 if (e) rb_syserr_fail_path(e, fptr->
pathv);
7877 if (setvbuf(fptr->
stdio_file, NULL, _IOFBF, 0) != 0)
7878 rb_warn(
"setvbuf() can't be honoured for %"PRIsVALUE, fptr->
pathv);
7881 if (setvbuf(fptr->
stdio_file, NULL, _IONBF, BUFSIZ) != 0)
7882 rb_warn(
"setvbuf() can't be honoured for %"PRIsVALUE, fptr->
pathv);
7884 else if (fptr->
stdio_file == stdout && isatty(fptr->
fd)) {
7885 if (setvbuf(fptr->
stdio_file, NULL, _IOLBF, BUFSIZ) != 0)
7886 rb_warn(
"setvbuf() can't be honoured for %"PRIsVALUE, fptr->
pathv);
7890 int tmpfd = rb_sysopen(fptr->
pathv, oflags, 0666);
7896 rb_syserr_fail_path(err, fptr->
pathv);
7920 fptr->
mode = orig->
mode & ~FMODE_PREP;
7925 fptr_copy_finalizer(fptr, orig);
7927 fd = ruby_dup(orig->
fd);
7929 pos = io_tell(orig);
7931 io_seek(fptr, pos, SEEK_SET);
7936 write_io = GetWriteIO(io);
7937 if (io != write_io) {
7977 if (argc == 0)
return Qnil;
7996 rb_warn_deprecated(
"`%s'", NULL,
rb_id2name(
id));
8040 for (i=0; i<argc; i++) {
8115 #define forward(obj, id, argc, argv) \
8116 rb_funcallv_kw(obj, id, argc, argv, RB_PASS_CALLED_KEYWORDS)
8117 #define forward_public(obj, id, argc, argv) \
8118 rb_funcallv_public_kw(obj, id, argc, argv, RB_PASS_CALLED_KEYWORDS)
8119 #define forward_current(id, argc, argv) \
8120 forward_public(ARGF.current_file, id, argc, argv)
8138 if (recv == r_stdout) {
8139 return rb_io_putc(recv, ch);
8141 return forward(r_stdout,
rb_intern(
"putc"), 1, &ch);
8146 rb_str_end_with_asciichar(
VALUE str,
int c)
8153 if (len == 0)
return 0;
8155 return ptr[len - 1] == c;
8157 return rb_enc_ascget(ptr + ((len - 1) / n) * n, ptr + len, &n, enc) == c;
8211 VALUE line, args[2];
8218 for (i=0; i<argc; i++) {
8231 !rb_str_end_with_asciichar(line,
'\n')) {
8234 rb_io_writev(out, n, args);
8253 if (recv == r_stdout) {
8256 return forward(r_stdout,
rb_intern(
"puts"), argc, argv);
8260 rb_p_write(
VALUE str)
8268 io_writev(2, args, r_stdout);
8271 rb_io_writev(r_stdout, 2, args);
8283 rb_p_result(
int argc,
const VALUE *argv)
8290 else if (argc > 1) {
8322 for (i=0; i<argc; i++) {
8324 rb_uninterruptible(rb_p_write, inspected);
8326 return rb_p_result(argc, argv);
8354 rb_obj_display(
int argc,
VALUE *argv,
VALUE self)
8365 rb_stderr_to_original_p(
VALUE err)
8367 return (err == orig_stderr ||
RFILE(orig_stderr)->fptr->
fd < 0);
8374 if (rb_stderr_to_original_p(out)) {
8376 if (isatty(fileno(stderr))) {
8377 if (rb_w32_write_console(
rb_str_new(mesg, len), fileno(stderr)) > 0)
return;
8380 if (fwrite(mesg,
sizeof(
char), (
size_t)len, stderr) < (
size_t)len) {
8397 rb_write_error_str(
VALUE mesg)
8401 if (rb_stderr_to_original_p(out)) {
8404 if (isatty(fileno(stderr))) {
8405 if (rb_w32_write_console(mesg, fileno(stderr)) > 0)
return;
8408 if (fwrite(
RSTRING_PTR(mesg),
sizeof(
char), len, stderr) < len) {
8420 rb_stderr_tty_p(
void)
8423 return isatty(fileno(stderr));
8428 must_respond_to(
ID mid,
VALUE val,
ID id)
8444 stdin_getter(
ID id,
VALUE *ptr)
8452 must_respond_to(id_write, val,
id);
8457 stdout_getter(
ID id,
VALUE *ptr)
8465 must_respond_to(id_write, val,
id);
8470 stderr_getter(
ID id,
VALUE *ptr)
8476 prep_io(
int fd,
int fmode,
VALUE klass,
const char *path)
8479 VALUE io = io_alloc(klass);
8485 if (!io_check_tty(fp)) {
8488 setmode(fd, O_BINARY);
8502 if (path && strcmp(path,
"-")) klass =
rb_cFile;
8503 return prep_io(fd, rb_io_oflags_fmode(oflags), klass, path);
8507 prep_stdio(
FILE *f,
int fmode,
VALUE klass,
const char *path)
8510 VALUE io = prep_io(fileno(f), fmode|FMODE_PREP|DEFAULT_TEXTMODE, klass, path);
8514 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
8515 fptr->
encs.
ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
8526 rb_io_prep_stdin(
void)
8532 rb_io_prep_stdout(
void)
8538 rb_io_prep_stderr(
void)
8547 int oflags = rb_io_fmode_oflags(fptr->
mode) & ~O_EXCL;
8563 rb_io_fptr_new(
void)
8574 rb_io_buffer_init(&fp->
wbuf);
8575 rb_io_buffer_init(&fp->
rbuf);
8576 rb_io_buffer_init(&fp->
cbuf);
8593 rb_io_make_open_file(
VALUE obj)
8598 if (
RFILE(obj)->fptr) {
8601 RFILE(obj)->fptr = 0;
8603 fp = rb_io_fptr_new();
8605 RFILE(obj)->fptr = fp;
8763 rb_io_initialize(
int argc,
VALUE *argv,
VALUE io)
8767 int fd, fmode, oflags = O_RDONLY;
8768 convconfig_t convconfig;
8770 #if defined(HAVE_FCNTL) && defined(F_GETFL)
8777 argc =
rb_scan_args(argc, argv,
"11:", &fnum, &vmode, &opt);
8784 #if defined(HAVE_FCNTL) && defined(F_GETFL)
8785 oflags = fcntl(fd, F_GETFL);
8791 #if defined(HAVE_FCNTL) && defined(F_GETFL)
8792 ofmode = rb_io_oflags_fmode(oflags);
8802 fmode |= FMODE_PREP;
8808 fp->
encs = convconfig;
8811 if (fileno(stdin) == fd)
8813 else if (fileno(stdout) == fd)
8815 else if (fileno(stderr) == fd)
8841 rb_io_set_encoding_by_bom(
VALUE io)
8856 if (!io_set_encoding_by_bom(io))
return Qnil;
8886 rb_file_initialize(
int argc,
VALUE *argv,
VALUE io)
8888 if (
RFILE(io)->fptr) {
8891 if (0 < argc && argc < 3) {
8896 return rb_io_initialize(argc, argv, io);
8899 rb_open_file(argc, argv, io);
8906 rb_io_s_new(
int argc,
VALUE *argv,
VALUE klass)
8911 rb_warn(
"%"PRIsVALUE
"::new() does not take block; use %"PRIsVALUE
"::open() instead",
8927 rb_io_s_for_fd(
int argc,
VALUE *argv,
VALUE klass)
8930 rb_io_initialize(argc, argv, io);
8943 rb_io_autoclose_p(
VALUE io)
8968 rb_io_set_autoclose(
VALUE io,
VALUE autoclose)
8972 if (!
RTEST(autoclose))
8973 fptr->
mode |= FMODE_PREP;
8975 fptr->
mode &= ~FMODE_PREP;
8980 argf_mark(
void *ptr)
8982 struct argf *p = ptr;
8991 argf_memsize(
const void *ptr)
8993 const struct argf *p = ptr;
8994 size_t size =
sizeof(*p);
9001 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
9008 p->current_file =
Qnil;
9014 argf_alloc(
VALUE klass)
9029 memset(&ARGF, 0,
sizeof(ARGF));
9030 argf_init(&ARGF, argv);
9040 ARGF = argf_of(orig);
9067 ARGF.last_lineno = ARGF.lineno;
9096 #define next_argv() argf_next_argv(argf)
9097 #define ARGF_GENERIC_INPUT_P() \
9098 (ARGF.current_file == rb_stdin && !RB_TYPE_P(ARGF.current_file, T_FILE))
9099 #define ARGF_FORWARD(argc, argv) do {\
9100 if (ARGF_GENERIC_INPUT_P())\
9101 return argf_forward((argc), (argv), argf);\
9103 #define NEXT_ARGF_FORWARD(argc, argv) do {\
9104 if (!next_argv()) return Qnil;\
9105 ARGF_FORWARD((argc), (argv));\
9111 VALUE file = ARGF.current_file;
9125 int stdout_binmode = 0;
9136 if (ARGF.init_p == 0) {
9146 if (
NIL_P(ARGF.argv)) {
9149 else if (ARGF.next_p == -1 &&
RARRAY_LEN(ARGF.argv) > 0) {
9154 if (ARGF.next_p == 1) {
9155 if (ARGF.init_p == 1) argf_close(
argf);
9160 ARGF.filename = filename;
9166 rb_warn(
"Can't do inplace edit for stdio; skipping");
9172 int fr = rb_sysopen(filename, O_RDONLY, 0);
9176 #ifndef NO_SAFE_RENAME
9187 if (!
NIL_P(ARGF.inplace)) {
9188 VALUE suffix = ARGF.inplace;
9195 #ifdef NO_SAFE_RENAME
9199 rb_warn(
"Can't rename %"PRIsVALUE
" to %"PRIsVALUE
": %s, skipping file",
9200 filename, str, strerror(errno));
9203 fr = rb_sysopen(str, O_RDONLY, 0);
9206 rb_warn(
"Can't rename %"PRIsVALUE
" to %"PRIsVALUE
": %s, skipping file",
9207 filename, str, strerror(errno));
9214 #ifdef NO_SAFE_RENAME
9215 rb_fatal(
"Can't do inplace edit without backup");
9217 if (unlink(fn) < 0) {
9218 rb_warn(
"Can't remove %"PRIsVALUE
": %s, skipping file",
9219 filename, strerror(errno));
9225 fw = rb_sysopen(filename, O_WRONLY|O_CREAT|O_TRUNC, 0666);
9226 #ifndef NO_SAFE_RENAME
9229 fchmod(fw, st.st_mode);
9231 chmod(fn, st.st_mode);
9233 if (st.st_uid!=st2.st_uid || st.st_gid!=st2.st_gid) {
9236 err = fchown(fw, st.st_uid, st.st_gid);
9238 err = chown(fn, st.st_uid, st.st_gid);
9240 if (err && getuid() == 0 && st2.st_uid == 0) {
9242 rb_warn(
"Can't set owner/group of %"PRIsVALUE
" to same as %"PRIsVALUE
": %s, skipping file",
9243 filename, str, strerror(errno));
9256 if (!ARGF.binmode) {
9257 fmode |= DEFAULT_TEXTMODE;
9259 ARGF.current_file = prep_io(fr, fmode,
rb_cFile, fn);
9260 if (!
NIL_P(write_io)) {
9267 if (ARGF.encs.enc) {
9268 fptr->
encs = ARGF.encs;
9269 clear_codeconv(fptr);
9273 if (!ARGF.binmode) {
9275 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
9276 fptr->
encs.
ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
9287 else if (ARGF.next_p == -1) {
9291 rb_warn(
"Can't do inplace edit for stdio");
9295 if (ARGF.init_p == -1) ARGF.init_p = 1;
9303 long lineno = ARGF.lineno;
9306 if (!next_argv())
return Qnil;
9307 if (ARGF_GENERIC_INPUT_P()) {
9308 line = forward_current(idGets, argc, argv);
9315 line = rb_io_getline(argc, argv, ARGF.current_file);
9317 if (
NIL_P(line) && ARGF.next_p != -1) {
9324 ARGF.lineno = ++lineno;
9325 ARGF.last_lineno = ARGF.lineno;
9331 argf_lineno_getter(
ID id,
VALUE *var)
9334 return INT2FIX(ARGF.last_lineno);
9342 ARGF.last_lineno = ARGF.lineno = n;
9384 return argf_gets(argc, argv,
argf);
9386 return forward(
argf, idGets, argc, argv);
9412 line = argf_getline(argc, argv,
argf);
9424 return rb_f_gets(0, 0,
argf);
9428 if (!next_argv())
return Qnil;
9430 if (
NIL_P(line) && ARGF.next_p != -1) {
9438 ARGF.last_lineno = ARGF.lineno;
9457 rb_f_readline(
int argc,
VALUE *argv,
VALUE recv)
9460 return argf_readline(argc, argv,
argf);
9488 if (!next_argv()) rb_eof_error();
9489 ARGF_FORWARD(argc, argv);
9490 line = argf_gets(argc, argv,
argf);
9511 rb_f_readlines(
int argc,
VALUE *argv,
VALUE recv)
9514 return argf_readlines(argc, argv,
argf);
9538 long lineno = ARGF.lineno;
9542 while (next_argv()) {
9543 if (ARGF_GENERIC_INPUT_P()) {
9544 lines = forward_current(
rb_intern(
"readlines"), argc, argv);
9547 lines = rb_io_readlines(argc, argv, ARGF.current_file);
9553 ARGF.last_lineno = ARGF.lineno;
9581 rb_last_status_clear();
9582 port = pipe_open_s(str,
"r",
FMODE_READABLE|DEFAULT_TEXTMODE, NULL);
9586 result = read_all(fptr, remain_size(fptr),
Qnil);
9588 RFILE(port)->fptr = NULL;
9595 #ifdef HAVE_SYS_SELECT_H
9596 #include <sys/select.h>
9615 if (READ_DATA_PENDING(fptr) || READ_CHAR_PENDING(fptr)) {
9619 if (max < fptr->fd) max = fptr->
fd;
9622 timerec.tv_sec = timerec.tv_usec = 0;
9630 if (!
NIL_P(write)) {
9636 if (max < fptr->fd) max = fptr->
fd;
9643 if (!
NIL_P(except)) {
9647 VALUE write_io = GetWriteIO(io);
9650 if (max < fptr->fd) max = fptr->
fd;
9651 if (io != write_io) {
9654 if (max < fptr->fd) max = fptr->
fd;
9669 if (!pending && n == 0)
return Qnil;
9694 VALUE write_io = GetWriteIO(io);
9707 VALUE write_io = GetWriteIO(io);
9712 else if (io != write_io) {
9725 VALUE read, write, except;
9731 select_call(
VALUE arg)
9735 return select_internal(p->read, p->write, p->except, p->timeout, p->fdsets);
9739 select_end(
VALUE arg)
9744 for (i = 0; i < numberof(p->fdsets); ++i)
9749 static VALUE sym_normal, sym_sequential, sym_random,
9750 sym_willneed, sym_dontneed, sym_noreuse;
9752 #ifdef HAVE_POSIX_FADVISE
9753 struct io_advise_struct {
9761 io_advise_internal(
void *arg)
9763 struct io_advise_struct *ptr = arg;
9764 return posix_fadvise(ptr->fd, ptr->offset, ptr->len, ptr->advice);
9768 io_advise_sym_to_const(
VALUE sym)
9770 #ifdef POSIX_FADV_NORMAL
9771 if (sym == sym_normal)
9772 return INT2NUM(POSIX_FADV_NORMAL);
9775 #ifdef POSIX_FADV_RANDOM
9776 if (sym == sym_random)
9777 return INT2NUM(POSIX_FADV_RANDOM);
9780 #ifdef POSIX_FADV_SEQUENTIAL
9781 if (sym == sym_sequential)
9782 return INT2NUM(POSIX_FADV_SEQUENTIAL);
9785 #ifdef POSIX_FADV_WILLNEED
9786 if (sym == sym_willneed)
9787 return INT2NUM(POSIX_FADV_WILLNEED);
9790 #ifdef POSIX_FADV_DONTNEED
9791 if (sym == sym_dontneed)
9792 return INT2NUM(POSIX_FADV_DONTNEED);
9795 #ifdef POSIX_FADV_NOREUSE
9796 if (sym == sym_noreuse)
9797 return INT2NUM(POSIX_FADV_NOREUSE);
9804 do_io_advise(
rb_io_t *fptr,
VALUE advice, off_t offset, off_t len)
9807 struct io_advise_struct ias;
9810 num_adv = io_advise_sym_to_const(advice);
9820 ias.advice =
NUM2INT(num_adv);
9821 ias.offset = offset;
9824 rv = (int)rb_thread_io_blocking_region(io_advise_internal, &ias, fptr->
fd);
9825 if (rv && rv != ENOSYS) {
9832 fptr->
pathv, offset, len, advice);
9842 advice_arg_check(
VALUE advice)
9847 if (advice != sym_normal &&
9848 advice != sym_sequential &&
9849 advice != sym_random &&
9850 advice != sym_willneed &&
9851 advice != sym_dontneed &&
9852 advice != sym_noreuse) {
9900 rb_io_advise(
int argc,
VALUE *argv,
VALUE io)
9902 VALUE advice, offset, len;
9906 rb_scan_args(argc, argv,
"12", &advice, &offset, &len);
9907 advice_arg_check(advice);
9909 io = GetWriteIO(io);
9915 #ifdef HAVE_POSIX_FADVISE
9916 return do_io_advise(fptr, advice, off, l);
9918 ((void)off, (
void)l);
10064 rb_f_select(
int argc,
VALUE *argv,
VALUE obj)
10071 rb_scan_args(argc, argv,
"13", &args.read, &args.write, &args.except, &timeout);
10072 if (
NIL_P(timeout)) {
10077 args.timeout = &timerec;
10080 for (i = 0; i < numberof(args.fdsets); ++i)
10086 #ifdef IOCTL_REQ_TYPE
10087 typedef IOCTL_REQ_TYPE ioctl_req_t;
10089 typedef int ioctl_req_t;
10090 # define NUM2IOCTLREQ(num) ((int)NUM2LONG(num))
10101 nogvl_ioctl(
void *ptr)
10103 struct ioctl_arg *arg = ptr;
10105 return (
VALUE)ioctl(arg->fd, arg->cmd, arg->narg);
10109 do_ioctl(
int fd, ioctl_req_t cmd,
long narg)
10112 struct ioctl_arg arg;
10118 retval = (int)rb_thread_io_blocking_region(nogvl_ioctl, &arg, fd);
10124 #define DEFAULT_IOCTL_NARG_LEN (256)
10126 #if defined(__linux__) && defined(_IOC_SIZE)
10128 linux_iocparm_len(ioctl_req_t cmd)
10132 if ((cmd & 0xFFFF0000) == 0) {
10134 return DEFAULT_IOCTL_NARG_LEN;
10137 len = _IOC_SIZE(cmd);
10140 if (len < DEFAULT_IOCTL_NARG_LEN)
10141 len = DEFAULT_IOCTL_NARG_LEN;
10148 ioctl_narg_len(ioctl_req_t cmd)
10152 #ifdef IOCPARM_MASK
10153 #ifndef IOCPARM_LEN
10154 #define IOCPARM_LEN(x) (((x) >> 16) & IOCPARM_MASK)
10158 len = IOCPARM_LEN(cmd);
10159 #elif defined(__linux__) && defined(_IOC_SIZE)
10160 len = linux_iocparm_len(cmd);
10163 len = DEFAULT_IOCTL_NARG_LEN;
10171 typedef long fcntl_arg_t;
10174 typedef int fcntl_arg_t;
10178 fcntl_narg_len(ioctl_req_t cmd)
10185 len =
sizeof(fcntl_arg_t);
10193 #ifdef F_DUPFD_CLOEXEC
10194 case F_DUPFD_CLOEXEC:
10195 len =
sizeof(fcntl_arg_t);
10205 len =
sizeof(fcntl_arg_t);
10215 len =
sizeof(fcntl_arg_t);
10225 len =
sizeof(fcntl_arg_t);
10230 len =
sizeof(
struct f_owner_ex);
10235 len =
sizeof(
struct f_owner_ex);
10240 len =
sizeof(
struct flock);
10245 len =
sizeof(
struct flock);
10250 len =
sizeof(
struct flock);
10270 len =
sizeof(fcntl_arg_t);
10280 len =
sizeof(fcntl_arg_t);
10285 len =
sizeof(fcntl_arg_t);
10298 fcntl_narg_len(ioctl_req_t cmd)
10304 #define NARG_SENTINEL 17
10307 setup_narg(ioctl_req_t cmd,
VALUE *argp,
long (*narg_len)(ioctl_req_t))
10318 else if (arg ==
Qtrue) {
10332 len = narg_len(cmd);
10337 if (slen < len+1) {
10344 ptr[slen - 1] = NARG_SENTINEL;
10353 finish_narg(
int retval,
VALUE arg,
const rb_io_t *fptr)
10355 if (retval < 0) rb_sys_fail_path(fptr->
pathv);
10360 if (ptr[slen-1] != NARG_SENTINEL)
10362 ptr[slen-1] =
'\0';
10372 ioctl_req_t cmd = NUM2IOCTLREQ(req);
10377 narg = setup_narg(cmd, &arg, ioctl_narg_len);
10379 retval = do_ioctl(fptr->
fd, cmd, narg);
10380 return finish_narg(retval, arg, fptr);
10396 rb_io_ioctl(
int argc,
VALUE *argv,
VALUE io)
10401 return rb_ioctl(io, req, arg);
10404 #define rb_io_ioctl rb_f_notimplement
10415 nogvl_fcntl(
void *ptr)
10417 struct fcntl_arg *arg = ptr;
10419 #if defined(F_DUPFD)
10420 if (arg->cmd == F_DUPFD)
10423 return (
VALUE)fcntl(arg->fd, arg->cmd, arg->narg);
10427 do_fcntl(
int fd,
int cmd,
long narg)
10430 struct fcntl_arg arg;
10436 retval = (int)rb_thread_io_blocking_region(nogvl_fcntl, &arg, fd);
10437 if (retval != -1) {
10439 #if defined(F_DUPFD)
10442 #if defined(F_DUPFD_CLOEXEC)
10443 case F_DUPFD_CLOEXEC:
10460 narg = setup_narg(cmd, &arg, fcntl_narg_len);
10462 retval = do_fcntl(fptr->
fd, cmd, narg);
10463 return finish_narg(retval, arg, fptr);
10480 rb_io_fcntl(
int argc,
VALUE *argv,
VALUE io)
10485 return rb_fcntl(io, req, arg);
10488 #define rb_io_fcntl rb_f_notimplement
10491 #if defined(HAVE_SYSCALL) || defined(HAVE___SYSCALL)
10530 #if SIZEOF_VOIDP == 8 && defined(HAVE___SYSCALL) && SIZEOF_INT != 8
10531 # define SYSCALL __syscall
10532 # define NUM2SYSCALLID(x) NUM2LONG(x)
10533 # define RETVAL2NUM(x) LONG2NUM(x)
10534 # if SIZEOF_LONG == 8
10535 long num, retval = -1;
10536 # elif SIZEOF_LONG_LONG == 8
10537 long long num, retval = -1;
10539 # error ---->> it is asserted that __syscall takes the first argument and returns retval in 64bit signed integer. <<----
10541 #elif defined(__linux__)
10542 # define SYSCALL syscall
10543 # define NUM2SYSCALLID(x) NUM2LONG(x)
10544 # define RETVAL2NUM(x) LONG2NUM(x)
10552 long num, retval = -1;
10554 # define SYSCALL syscall
10555 # define NUM2SYSCALLID(x) NUM2INT(x)
10556 # define RETVAL2NUM(x) INT2NUM(x)
10557 int num, retval = -1;
10563 "We plan to remove a syscall function at future release. DL(Fiddle) provides safer alternative.");
10568 if (argc > numberof(arg))
10570 num = NUM2SYSCALLID(argv[0]); ++argv;
10571 for (i = argc - 1; i--; ) {
10586 retval = SYSCALL(num);
10589 retval = SYSCALL(num, arg[0]);
10592 retval = SYSCALL(num, arg[0],arg[1]);
10595 retval = SYSCALL(num, arg[0],arg[1],arg[2]);
10598 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3]);
10601 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4]);
10604 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5]);
10607 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6]);
10613 return RETVAL2NUM(retval);
10615 #undef NUM2SYSCALLID
10619 #define rb_f_syscall rb_f_notimplement
10623 io_new_instance(
VALUE args)
10629 find_encoding(
VALUE v)
10632 if (!enc)
rb_warn(
"Unsupported encoding %"PRIsVALUE
" ignored", v);
10644 enc2 = find_encoding(v1);
10653 enc = find_encoding(v2);
10660 enc = find_encoding(v2);
10666 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
10672 rb_io_ext_int_to_encs(NULL, NULL, &enc, &enc2, 0);
10673 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
10679 parse_mode_enc(
RSTRING_PTR(tmp), enc, &enc, &enc2, NULL);
10680 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
10684 rb_io_ext_int_to_encs(find_encoding(v1), NULL, &enc, &enc2, 0);
10685 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
10690 validate_enc_binmode(&fptr->
mode, ecflags, enc, enc2);
10695 clear_codeconv(fptr);
10707 io_encoding_set_v(
VALUE v)
10710 io_encoding_set(arg->fptr, arg->v1, arg->v2, arg->opt);
10715 pipe_pair_close(
VALUE rw)
10718 return rb_ensure(io_close, rwp[0], io_close, rwp[1]);
10782 rb_io_s_pipe(
int argc,
VALUE *argv,
VALUE klass)
10784 int pipes[2], state;
10785 VALUE r, w, args[3], v1, v2;
10792 argc =
rb_scan_args(argc, argv,
"02:", &v1, &v2, &opt);
10807 ies_args.fptr = fptr;
10810 ies_args.opt = opt;
10829 extract_binmode(opt, &fmode);
10836 #if DEFAULT_TEXTMODE
10839 setmode(fptr->
fd, O_BINARY);
10841 #if RUBY_CRLF_ENVIRONMENT
10847 fptr->
mode |= fmode;
10848 #if DEFAULT_TEXTMODE
10851 setmode(fptr2->
fd, O_BINARY);
10854 fptr2->
mode |= fmode;
10891 v = rb_to_array_type(v);
10896 arg->io = rb_io_open(klass, path, vmode, vperm, opt);
10900 io_s_foreach(
VALUE v)
10905 while (!
NIL_P(str = rb_io_getline_1(arg->rs, arg->limit, arg->chomp, arg->io))) {
10951 rb_io_s_foreach(
int argc,
VALUE *argv,
VALUE self)
10954 int orig_argc = argc;
10958 argc =
rb_scan_args(argc, argv,
"13:", NULL, NULL, NULL, NULL, &opt);
10960 extract_getline_args(argc-1, argv+1, &garg);
10961 open_key_args(
self, argc, argv, opt, &arg);
10963 extract_getline_opts(opt, &garg);
10964 check_getline_args(&garg.rs, &garg.limit, garg.io = arg.io);
10969 io_s_readlines(
VALUE v)
10972 return io_readlines(arg, arg->io);
11016 rb_io_s_readlines(
int argc,
VALUE *argv,
VALUE io)
11022 argc =
rb_scan_args(argc, argv,
"13:", NULL, NULL, NULL, NULL, &opt);
11023 extract_getline_args(argc-1, argv+1, &garg);
11024 open_key_args(io, argc, argv, opt, &arg);
11026 extract_getline_opts(opt, &garg);
11027 check_getline_args(&garg.rs, &garg.limit, garg.io = arg.io);
11035 return io_read(arg->argc, arg->argv, arg->io);
11045 seek_before_access(
VALUE argp)
11049 return rb_io_seek(arg->io, arg->offset, arg->mode);
11099 rb_io_s_read(
int argc,
VALUE *argv,
VALUE io)
11104 argc =
rb_scan_args(argc, argv,
"13:", NULL, NULL, &offset, NULL, &opt);
11105 open_key_args(io, argc, argv, opt, &arg);
11107 if (!
NIL_P(offset)) {
11111 sarg.offset = offset;
11112 sarg.mode = SEEK_SET;
11118 if (arg.argc == 2) arg.argc = 1;
11147 rb_io_s_binread(
int argc,
VALUE *argv,
VALUE io)
11158 convconfig_t convconfig = {NULL, NULL, 0,
Qnil};
11163 arg.io = rb_io_open_generic(io, argv[0], oflags, fmode, &convconfig, 0);
11166 arg.argc = (argc > 1) ? 1 : 0;
11167 if (!
NIL_P(offset)) {
11171 sarg.offset = offset;
11172 sarg.mode = SEEK_SET;
11183 io_s_write0(
VALUE v)
11186 return io_write(arg->io,arg->str,arg->nosync);
11190 io_s_write(
int argc,
VALUE *argv,
VALUE klass,
int binary)
11192 VALUE string, offset, opt;
11196 rb_scan_args(argc, argv,
"21:", NULL, &
string, &offset, &opt);
11203 int mode = O_WRONLY|O_CREAT;
11205 if (binary) mode |= O_BINARY;
11207 if (
NIL_P(offset)) mode |= O_TRUNC;
11210 open_key_args(klass, argc, argv, opt, &arg);
11213 if (binary) rb_io_binmode_m(arg.io);
11217 if (!
NIL_P(offset)) {
11221 sarg.offset = offset;
11222 sarg.mode = SEEK_SET;
11292 rb_io_s_write(
int argc,
VALUE *argv,
VALUE io)
11294 return io_s_write(argc, argv, io, 0);
11316 rb_io_s_binwrite(
int argc,
VALUE *argv,
VALUE io)
11318 return io_s_write(argc, argv, io, 1);
11329 unsigned close_src : 1;
11330 unsigned close_dst : 1;
11333 const char *syserr;
11334 const char *notimp;
11336 struct stat src_stat;
11337 struct stat dst_stat;
11338 #ifdef HAVE_FCOPYFILE
11339 copyfile_state_t copyfile_state;
11344 exec_interrupts(
void *arg)
11347 rb_thread_execute_interrupts(th);
11361 #if defined(ERESTART)
11366 rb_thread_execute_interrupts(stp->th);
11385 rb_thread_fiber_scheduler_wait_for(
void * _args)
11395 # define IOWAIT_SYSCALL "poll"
11396 STATIC_ASSERT(pollin_expected, POLLIN == RB_WAITFD_IN);
11397 STATIC_ASSERT(pollout_expected, POLLOUT == RB_WAITFD_OUT);
11402 if (scheduler !=
Qnil) {
11403 struct wait_for_single_fd args = {.scheduler = scheduler, .fptr = fptr, .events = events};
11405 return RTEST(args.result);
11409 if (fd == -1)
return 0;
11414 fds.events = events;
11416 return poll(&fds, 1, -1);
11419 # define IOWAIT_SYSCALL "select"
11424 if (scheduler !=
Qnil) {
11425 struct wait_for_single_fd args = {.scheduler = scheduler, .fptr = fptr, .events = events};
11427 return RTEST(args.result);
11431 if (fd == -1)
return 0;
11443 case RB_WAITFD_OUT:
11447 VM_UNREACHABLE(nogvl_wait_for);
11465 ret = nogvl_wait_for(stp->th, stp->src_fptr, RB_WAITFD_IN);
11467 }
while (ret < 0 && maygvl_copy_stream_continue_p(has_gvl, stp));
11470 stp->syserr = IOWAIT_SYSCALL;
11471 stp->error_no = errno;
11483 ret = nogvl_wait_for(stp->th, stp->dst_fptr, RB_WAITFD_OUT);
11484 }
while (ret < 0 && maygvl_copy_stream_continue_p(0, stp));
11487 stp->syserr = IOWAIT_SYSCALL;
11488 stp->error_no = errno;
11494 #ifdef USE_COPY_FILE_RANGE
11497 simple_copy_file_range(
int in_fd, off_t *in_offset,
int out_fd, off_t *out_offset,
size_t count,
unsigned int flags)
11499 #ifdef HAVE_COPY_FILE_RANGE
11500 return copy_file_range(in_fd, in_offset, out_fd, out_offset, count, flags);
11502 return syscall(__NR_copy_file_range, in_fd, in_offset, out_fd, out_offset, count, flags);
11511 off_t copy_length, src_offset, *src_offset_ptr;
11513 if (!S_ISREG(stp->src_stat.st_mode))
11516 src_size = stp->src_stat.st_size;
11517 src_offset = stp->src_offset;
11518 if (src_offset >= (off_t)0) {
11519 src_offset_ptr = &src_offset;
11522 src_offset_ptr = NULL;
11525 copy_length = stp->copy_length;
11526 if (copy_length < (off_t)0) {
11527 if (src_offset < (off_t)0) {
11528 off_t current_offset;
11530 current_offset = lseek(stp->src_fptr->
fd, 0, SEEK_CUR);
11531 if (current_offset < (off_t)0 && errno) {
11532 stp->syserr =
"lseek";
11533 stp->error_no = errno;
11534 return (
int)current_offset;
11536 copy_length = src_size - current_offset;
11539 copy_length = src_size - src_offset;
11543 retry_copy_file_range:
11544 # if SIZEOF_OFF_T > SIZEOF_SIZE_T
11546 ss = (copy_length > (off_t)SSIZE_MAX) ? SSIZE_MAX : (ssize_t)copy_length;
11548 ss = (ssize_t)copy_length;
11550 ss = simple_copy_file_range(stp->src_fptr->
fd, src_offset_ptr, stp->dst_fptr->
fd, NULL, ss, 0);
11554 if (0 < copy_length) {
11555 goto retry_copy_file_range;
11559 if (maygvl_copy_stream_continue_p(0, stp)) {
11560 goto retry_copy_file_range;
11574 #if EWOULDBLOCK != EAGAIN
11578 int ret = nogvl_copy_stream_wait_write(stp);
11579 if (ret < 0)
return ret;
11581 goto retry_copy_file_range;
11585 int flags = fcntl(stp->dst_fptr->
fd, F_GETFL);
11587 if (flags != -1 && flags & O_APPEND) {
11593 stp->syserr =
"copy_file_range";
11594 stp->error_no = errno;
11601 #ifdef HAVE_FCOPYFILE
11606 const off_t src_offset = stp->src_offset;
11609 if (stp->copy_length >= (off_t)0) {
11614 if (!S_ISREG(stp->src_stat.st_mode))
11617 if (!S_ISREG(stp->dst_stat.st_mode))
11619 if (lseek(stp->dst_fptr->
fd, 0, SEEK_CUR) > (off_t)0)
11621 if (fcntl(stp->dst_fptr->
fd, F_GETFL) & O_APPEND) {
11624 off_t end = lseek(stp->dst_fptr->
fd, 0, SEEK_END);
11625 lseek(stp->dst_fptr->
fd, 0, SEEK_SET);
11626 if (end > (off_t)0)
return 0;
11629 if (src_offset > (off_t)0) {
11634 cur = lseek(stp->src_fptr->
fd, 0, SEEK_CUR);
11635 if (cur < (off_t)0 && errno) {
11636 stp->error_no = errno;
11641 r = lseek(stp->src_fptr->
fd, src_offset, SEEK_SET);
11642 if (r < (off_t)0 && errno) {
11643 stp->error_no = errno;
11648 stp->copyfile_state = copyfile_state_alloc();
11649 ret = fcopyfile(stp->src_fptr->
fd, stp->dst_fptr->
fd, stp->copyfile_state, COPYFILE_DATA);
11650 copyfile_state_get(stp->copyfile_state, COPYFILE_STATE_COPIED, &ss);
11654 if (src_offset > (off_t)0) {
11658 r = lseek(stp->src_fptr->
fd, cur, SEEK_SET);
11659 if (r < (off_t)0 && errno) {
11660 stp->error_no = errno;
11672 stp->syserr =
"fcopyfile";
11673 stp->error_no = errno;
11680 #ifdef HAVE_SENDFILE
11683 # define USE_SENDFILE
11685 # ifdef HAVE_SYS_SENDFILE_H
11686 # include <sys/sendfile.h>
11690 simple_sendfile(
int out_fd,
int in_fd, off_t *offset, off_t count)
11692 return sendfile(out_fd, in_fd, offset, (
size_t)count);
11695 # elif 0 || defined(__APPLE__)
11699 # define USE_SENDFILE
11702 simple_sendfile(
int out_fd,
int in_fd, off_t *offset, off_t count)
11705 off_t pos = offset ? *offset : lseek(in_fd, 0, SEEK_CUR);
11708 r = sendfile(in_fd, out_fd, pos, &count, NULL, 0);
11711 r = sendfile(in_fd, out_fd, pos, (
size_t)count, NULL, &sbytes, 0);
11713 if (r != 0 && sbytes == 0)
return r;
11718 lseek(in_fd, sbytes, SEEK_CUR);
11720 return (ssize_t)sbytes;
11727 #ifdef USE_SENDFILE
11737 if (!S_ISREG(stp->src_stat.st_mode))
11740 src_size = stp->src_stat.st_size;
11742 if ((stp->dst_stat.st_mode & S_IFMT) != S_IFSOCK)
11746 src_offset = stp->src_offset;
11747 use_pread = src_offset >= (off_t)0;
11749 copy_length = stp->copy_length;
11750 if (copy_length < (off_t)0) {
11752 copy_length = src_size - src_offset;
11756 cur = lseek(stp->src_fptr->
fd, 0, SEEK_CUR);
11757 if (cur < (off_t)0 && errno) {
11758 stp->syserr =
"lseek";
11759 stp->error_no = errno;
11762 copy_length = src_size - cur;
11767 # if SIZEOF_OFF_T > SIZEOF_SIZE_T
11769 ss = (copy_length > (off_t)SSIZE_MAX) ? SSIZE_MAX : (ssize_t)copy_length;
11771 ss = (ssize_t)copy_length;
11774 ss = simple_sendfile(stp->dst_fptr->
fd, stp->src_fptr->
fd, &src_offset, ss);
11777 ss = simple_sendfile(stp->dst_fptr->
fd, stp->src_fptr->
fd, NULL, ss);
11782 if (0 < copy_length) {
11783 goto retry_sendfile;
11787 if (maygvl_copy_stream_continue_p(0, stp))
11788 goto retry_sendfile;
11801 #if EWOULDBLOCK != EAGAIN
11814 ret = maygvl_copy_stream_wait_read(0, stp);
11815 if (ret < 0)
return ret;
11817 ret = nogvl_copy_stream_wait_write(stp);
11818 if (ret < 0)
return ret;
11820 goto retry_sendfile;
11822 stp->syserr =
"sendfile";
11823 stp->error_no = errno;
11831 maygvl_read(
int has_gvl,
rb_io_t *fptr,
void *buf,
size_t count)
11834 return rb_read_internal(fptr, buf, count);
11836 return read(fptr->
fd, buf, count);
11840 maygvl_copy_stream_read(
int has_gvl,
struct copy_stream_struct *stp,
char *buf,
size_t len, off_t offset)
11844 if (offset < (off_t)0) {
11845 ss = maygvl_read(has_gvl, stp->src_fptr, buf, len);
11849 ss = pread(stp->src_fptr->
fd, buf, len, offset);
11851 stp->notimp =
"pread";
11859 if (maygvl_copy_stream_continue_p(has_gvl, stp))
11863 #if EWOULDBLOCK != EAGAIN
11867 int ret = maygvl_copy_stream_wait_read(has_gvl, stp);
11868 if (ret < 0)
return ret;
11873 stp->notimp =
"pread";
11877 stp->syserr = offset < (off_t)0 ?
"read" :
"pread";
11878 stp->error_no = errno;
11889 ss = write(stp->dst_fptr->
fd, buf+off, len);
11891 if (maygvl_copy_stream_continue_p(0, stp))
11893 if (io_again_p(errno)) {
11894 int ret = nogvl_copy_stream_wait_write(stp);
11895 if (ret < 0)
return ret;
11898 stp->syserr =
"write";
11899 stp->error_no = errno;
11921 copy_length = stp->copy_length;
11922 use_eof = copy_length < (off_t)0;
11923 src_offset = stp->src_offset;
11924 use_pread = src_offset >= (off_t)0;
11926 if (use_pread && stp->close_src) {
11929 r = lseek(stp->src_fptr->
fd, src_offset, SEEK_SET);
11930 if (r < (off_t)0 && errno) {
11931 stp->syserr =
"lseek";
11932 stp->error_no = errno;
11935 src_offset = (off_t)-1;
11939 while (use_eof || 0 < copy_length) {
11940 if (!use_eof && copy_length < (off_t)
sizeof(buf)) {
11941 len = (size_t)copy_length;
11947 ss = maygvl_copy_stream_read(0, stp, buf, len, src_offset);
11952 ss = maygvl_copy_stream_read(0, stp, buf, len, (off_t)-1);
11957 ret = nogvl_copy_stream_write(stp, buf, ss);
11967 nogvl_copy_stream_func(
void *arg)
11970 #if defined(USE_SENDFILE) || defined(USE_COPY_FILE_RANGE) || defined(HAVE_FCOPYFILE)
11974 #ifdef USE_COPY_FILE_RANGE
11975 ret = nogvl_copy_file_range(stp);
11980 #ifdef HAVE_FCOPYFILE
11981 ret = nogvl_fcopyfile(stp);
11986 #ifdef USE_SENDFILE
11987 ret = nogvl_copy_stream_sendfile(stp);
11992 nogvl_copy_stream_read_write(stp);
11994 #if defined(USE_SENDFILE) || defined(USE_COPY_FILE_RANGE) || defined(HAVE_FCOPYFILE)
12001 copy_stream_fallback_body(
VALUE arg)
12004 const int buflen = 16*1024;
12007 off_t rest = stp->copy_length;
12008 off_t off = stp->src_offset;
12009 ID read_method = id_readpartial;
12011 if (!stp->src_fptr) {
12013 read_method = id_read;
12020 if (stp->copy_length < (off_t)0) {
12028 l = buflen < rest ? buflen : (long)rest;
12030 if (!stp->src_fptr) {
12033 if (read_method == id_read &&
NIL_P(rc))
12039 ss = maygvl_copy_stream_read(1, stp,
RSTRING_PTR(buf), l, off);
12045 if (off >= (off_t)0)
12050 stp->total += numwrote;
12052 if (read_method == id_read &&
RSTRING_LEN(buf) == 0) {
12063 if (!stp->src_fptr && stp->src_offset >= (off_t)0) {
12073 copy_stream_body(
VALUE arg)
12076 VALUE src_io = stp->src, dst_io = stp->dst;
12077 const int common_oflags = 0
12087 if (src_io ==
argf ||
12091 stp->src_fptr = NULL;
12096 if (!
NIL_P(tmp_io)) {
12103 args[1] =
INT2NUM(O_RDONLY|common_oflags);
12106 stp->close_src = 1;
12111 stat_ret = fstat(stp->src_fptr->
fd, &stp->src_stat);
12112 if (stat_ret < 0) {
12113 stp->syserr =
"fstat";
12114 stp->error_no = errno;
12119 if (dst_io ==
argf ||
12123 stp->dst_fptr = NULL;
12128 if (!
NIL_P(tmp_io)) {
12129 dst_io = GetWriteIO(tmp_io);
12135 args[1] =
INT2NUM(O_WRONLY|O_CREAT|O_TRUNC|common_oflags);
12139 stp->close_dst = 1;
12142 dst_io = GetWriteIO(dst_io);
12148 stat_ret = fstat(stp->dst_fptr->
fd, &stp->dst_stat);
12149 if (stat_ret < 0) {
12150 stp->syserr =
"fstat";
12151 stp->error_no = errno;
12158 SET_BINARY_MODE_WITH_SEEK_CUR(stp->src_fptr);
12161 io_ascii8bit_binmode(stp->dst_fptr);
12163 if (stp->src_offset < (off_t)0 && stp->src_fptr && stp->src_fptr->
rbuf.
len) {
12164 size_t len = stp->src_fptr->
rbuf.
len;
12166 if (stp->copy_length >= (off_t)0 && stp->copy_length < (off_t)len) {
12167 len = (size_t)stp->copy_length;
12171 read_buffered_data(
RSTRING_PTR(str), len, stp->src_fptr);
12172 if (stp->dst_fptr) {
12174 rb_sys_fail_on_write(stp->dst_fptr);
12180 if (stp->copy_length >= (off_t)0)
12181 stp->copy_length -= len;
12184 if (stp->dst_fptr && io_fflush(stp->dst_fptr) < 0) {
12188 if (stp->copy_length == 0)
12191 if (stp->src_fptr == NULL || stp->dst_fptr == NULL) {
12192 return copy_stream_fallback(stp);
12200 copy_stream_finalize(
VALUE arg)
12204 #ifdef HAVE_FCOPYFILE
12205 if (stp->copyfile_state) {
12206 copyfile_state_free(stp->copyfile_state);
12210 if (stp->close_src) {
12211 rb_io_close_m(stp->src);
12213 if (stp->close_dst) {
12214 rb_io_close_m(stp->dst);
12258 rb_io_s_copy_stream(
int argc,
VALUE *argv,
VALUE io)
12260 VALUE src, dst, length, src_offset;
12265 rb_scan_args(argc, argv,
"22", &src, &dst, &length, &src_offset);
12270 st.src_fptr = NULL;
12271 st.dst_fptr = NULL;
12274 st.copy_length = (off_t)-1;
12276 st.copy_length =
NUM2OFFT(length);
12278 if (
NIL_P(src_offset))
12279 st.src_offset = (off_t)-1;
12281 st.src_offset =
NUM2OFFT(src_offset);
12297 rb_io_external_encoding(
VALUE io)
12321 rb_io_internal_encoding(
VALUE io)
12349 rb_io_set_encoding(
int argc,
VALUE *argv,
VALUE io)
12355 return forward(io, id_set_encoding, argc, argv);
12358 argc =
rb_scan_args(argc, argv,
"11:", &v1, &v2, &opt);
12360 io_encoding_set(fptr, v1, v2, opt);
12365 rb_stdio_set_default_encoding(
void)
12370 if (isatty(fileno(stdin))) {
12381 rb_io_set_encoding(1, &val,
rb_stdin);
12382 rb_io_set_encoding(1, &val,
rb_stdout);
12383 rb_io_set_encoding(1, &val,
rb_stderr);
12387 global_argf_p(
VALUE arg)
12389 return arg ==
argf;
12411 if (!
RTEST(ARGF.current_file)) {
12414 return rb_io_external_encoding(
rb_io_check_io(ARGF.current_file));
12433 if (!
RTEST(ARGF.current_file)) {
12436 return rb_io_internal_encoding(
rb_io_check_io(ARGF.current_file));
12475 if (!next_argv()) {
12478 rb_io_set_encoding(argc, argv, ARGF.current_file);
12480 ARGF.encs = fptr->
encs;
12499 if (!next_argv()) {
12502 ARGF_FORWARD(0, 0);
12503 return rb_io_tell(ARGF.current_file);
12516 if (!next_argv()) {
12519 ARGF_FORWARD(argc, argv);
12520 return rb_io_seek_m(argc, argv, ARGF.current_file);
12537 if (!next_argv()) {
12540 ARGF_FORWARD(1, &offset);
12541 return rb_io_set_pos(ARGF.current_file, offset);
12562 if (!next_argv()) {
12565 ARGF_FORWARD(0, 0);
12566 old_lineno =
RFILE(ARGF.current_file)->fptr->lineno;
12567 ret = rb_io_rewind(ARGF.current_file);
12568 if (!global_argf_p(
argf)) {
12569 ARGF.last_lineno = ARGF.lineno -= old_lineno;
12587 if (!next_argv()) {
12590 ARGF_FORWARD(0, 0);
12591 return rb_io_fileno(ARGF.current_file);
12610 ARGF_FORWARD(0, 0);
12611 return ARGF.current_file;
12636 if (
RTEST(ARGF.current_file)) {
12637 if (ARGF.init_p == 0)
return Qtrue;
12639 ARGF_FORWARD(0, 0);
12698 VALUE tmp, str, length;
12702 if (!
NIL_P(length)) {
12712 if (!next_argv()) {
12715 if (ARGF_GENERIC_INPUT_P()) {
12716 tmp = argf_forward(argc, argv,
argf);
12719 tmp = io_read(argc, argv, ARGF.current_file);
12721 if (
NIL_P(str)) str = tmp;
12724 if (ARGF.next_p != -1) {
12730 else if (argc >= 1) {
12747 argf_forward_call(
VALUE arg)
12750 argf_forward(p->argc, p->argv, p->argf);
12780 return argf_getpartial(argc, argv,
argf,
Qnil, 0);
12801 return argf_getpartial(argc, argv,
argf, opts, 1);
12807 VALUE tmp, str, length;
12815 no_exception = no_exception_p(opts);
12817 if (!next_argv()) {
12823 if (ARGF_GENERIC_INPUT_P()) {
12833 tmp = io_getpartial(argc, argv, ARGF.current_file, no_exception, nonblock);
12836 if (ARGF.next_p == -1) {
12837 return io_nonblock_eof(no_exception);
12842 return io_nonblock_eof(no_exception);
12880 if (!next_argv())
return Qnil;
12881 if (ARGF_GENERIC_INPUT_P()) {
12882 ch = forward_current(
rb_intern(
"getc"), 0, 0);
12885 ch = rb_io_getc(ARGF.current_file);
12887 if (
NIL_P(ch) && ARGF.next_p != -1) {
12920 if (!next_argv())
return Qnil;
12922 ch = forward_current(
rb_intern(
"getbyte"), 0, 0);
12927 if (
NIL_P(ch) && ARGF.next_p != -1) {
12960 if (!next_argv()) rb_eof_error();
12962 ch = forward_current(
rb_intern(
"getc"), 0, 0);
12965 ch = rb_io_getc(ARGF.current_file);
12967 if (
NIL_P(ch) && ARGF.next_p != -1) {
12999 NEXT_ARGF_FORWARD(0, 0);
13000 c = argf_getbyte(
argf);
13007 #define FOREACH_ARGF() while (next_argv())
13012 const VALUE current = ARGF.current_file;
13014 if (ARGF.init_p == -1 || current != ARGF.current_file) {
13020 #define ARGF_block_call(mid, argc, argv, func, argf) \
13021 rb_block_call_kw(ARGF.current_file, mid, argc, argv, \
13022 func, argf, rb_keyword_given_p())
13027 VALUE ret = ARGF_block_call(mid, argc, argv, argf_block_call_i,
argf);
13028 if (ret !=
Qundef) ARGF.next_p = 1;
13034 if (!global_argf_p(
argf)) {
13035 ARGF.last_lineno = ++ARGF.lineno;
13037 return argf_block_call_i(i,
argf, argc, argv, blockarg);
13043 VALUE ret = ARGF_block_call(mid, argc, argv, argf_block_call_line_i,
argf);
13044 if (ret !=
Qundef) ARGF.next_p = 1;
13092 argf_block_call_line(
rb_intern(
"each_line"), argc, argv,
argf);
13206 return ARGF.filename;
13210 argf_filename_getter(
ID id,
VALUE *var)
13212 return argf_filename(*var);
13237 return ARGF.current_file;
13256 ARGF_FORWARD(0, 0);
13277 return RBOOL(ARGF.binmode);
13297 if (ARGF.init_p && ARGF.next_p == 0) {
13326 if (ARGF.next_p != -1) {
13344 ARGF_FORWARD(0, 0);
13345 return rb_io_closed(ARGF.current_file);
13371 if (!ARGF.inplace)
return Qnil;
13379 return argf_inplace_mode_get(*var);
13409 ARGF.inplace =
Qnil;
13420 argf_inplace_mode_set(*var, val);
13424 ruby_set_inplace_mode(
const char *suffix)
13450 argf_argv_getter(
ID id,
VALUE *var)
13452 return argf_argv(*var);
13471 if (!
RTEST(ARGF.current_file)) {
13474 return GetWriteIO(ARGF.current_file);
13501 case RB_IO_WAIT_WRITABLE:
13504 c = rb_eEAGAINWaitWritable;
13506 #if EAGAIN != EWOULDBLOCK
13508 c = rb_eEWOULDBLOCKWaitWritable;
13512 c = rb_eEINPROGRESSWaitWritable;
13518 case RB_IO_WAIT_READABLE:
13521 c = rb_eEAGAINWaitReadable;
13523 #if EAGAIN != EWOULDBLOCK
13525 c = rb_eEWOULDBLOCKWaitReadable;
13529 c = rb_eEINPROGRESSWaitReadable;
13536 rb_bug(
"invalid read/write type passed to rb_readwrite_sys_fail: %d", waiting);
13542 get_LAST_READ_LINE(
ID _x,
VALUE *_y)
14133 #include <sys/cygwin.h>
14134 static struct __cygwin_perfile pf[] =
14136 {
"", O_RDONLY | O_BINARY},
14137 {
"", O_WRONLY | O_BINARY},
14138 {
"", O_RDWR | O_BINARY},
14139 {
"", O_APPEND | O_BINARY},
14142 cygwin_internal(CW_PERFILE, pf);
14191 #if EAGAIN == EWOULDBLOCK
14192 rb_eEWOULDBLOCKWaitReadable = rb_eEAGAINWaitReadable;
14195 rb_eEWOULDBLOCKWaitWritable = rb_eEAGAINWaitWritable;
14249 rb_gvar_ractor_local(
"$_");
14353 rb_gvar_ractor_local(
"$stdin");
14354 rb_gvar_ractor_local(
"$stdout");
14355 rb_gvar_ractor_local(
"$>");
14356 rb_gvar_ractor_local(
"$stderr");
14443 rb_define_method(rb_cARGF,
"external_encoding", argf_external_encoding, 0);
14444 rb_define_method(rb_cARGF,
"internal_encoding", argf_internal_encoding, 0);
14463 rb_gvar_ractor_local(
"$-i");
14467 #if defined (_WIN32) || defined(__CYGWIN__)
14468 atexit(pipe_atexit);
14480 sym_encoding =
ID2SYM(rb_id_encoding());
14504 #include "io.rbinc"
std::atomic< unsigned > rb_atomic_t
Type that is eligible for atomic operations.
unsigned long ruby_strtoul(const char *str, char **endptr, int base)
Our own locale-insensitive version of strtoul(3).
#define rb_define_singleton_method(klass, mid, func, arity)
Defines klass.mid.
void rb_include_module(VALUE klass, VALUE module)
Includes a module to a class.
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
VALUE rb_class_new(VALUE super)
Creates a new, anonymous class.
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
VALUE rb_define_module_under(VALUE outer, const char *name)
Defines a module under the namespace of outer.
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
int rb_scan_args_kw(int kw_flag, int argc, const VALUE *argv, const char *fmt,...)
Identical to rb_scan_args(), except it also accepts kw_splat.
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Retrieves argument from argc and argv to given VALUE references according to the format string.
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a method.
int rb_block_given_p(void)
Determines if the current method is given a block.
int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *values)
Keyword argument deconstructor.
void rb_define_global_function(const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a global function.
#define ECONV_AFTER_OUTPUT
Old name of RUBY_ECONV_AFTER_OUTPUT.
#define rb_str_new2
Old name of rb_str_new_cstr.
#define TYPE(_)
Old name of rb_type.
#define NEWOBJ_OF
Old name of RB_NEWOBJ_OF.
#define FL_SINGLETON
Old name of RUBY_FL_SINGLETON.
#define RB_INTEGER_TYPE_P
Old name of rb_integer_type_p.
#define ENC_CODERANGE_7BIT
Old name of RUBY_ENC_CODERANGE_7BIT.
#define T_FILE
Old name of RUBY_T_FILE.
#define ENC_CODERANGE_VALID
Old name of RUBY_ENC_CODERANGE_VALID.
#define ECONV_UNIVERSAL_NEWLINE_DECORATOR
Old name of RUBY_ECONV_UNIVERSAL_NEWLINE_DECORATOR.
#define OBJ_INIT_COPY(obj, orig)
Old name of RB_OBJ_INIT_COPY.
#define ALLOC
Old name of RB_ALLOC.
#define T_STRING
Old name of RUBY_T_STRING.
#define Qundef
Old name of RUBY_Qundef.
#define INT2FIX
Old name of RB_INT2FIX.
#define T_NIL
Old name of RUBY_T_NIL.
#define UNREACHABLE
Old name of RBIMPL_UNREACHABLE.
#define ID2SYM
Old name of RB_ID2SYM.
#define T_BIGNUM
Old name of RUBY_T_BIGNUM.
#define OBJ_FREEZE
Old name of RB_OBJ_FREEZE.
#define T_FIXNUM
Old name of RUBY_T_FIXNUM.
#define UNREACHABLE_RETURN
Old name of RBIMPL_UNREACHABLE_RETURN.
#define FIX2UINT
Old name of RB_FIX2UINT.
#define SSIZET2NUM
Old name of RB_SSIZE2NUM.
#define ZALLOC
Old name of RB_ZALLOC.
#define CLASS_OF
Old name of rb_class_of.
#define rb_ary_new4
Old name of rb_ary_new_from_values.
#define ECONV_NEWLINE_DECORATOR_WRITE_MASK
Old name of RUBY_ECONV_NEWLINE_DECORATOR_WRITE_MASK.
#define ENCODING_MAXNAMELEN
Old name of RUBY_ENCODING_MAXNAMELEN.
#define MBCLEN_NEEDMORE_LEN(ret)
Old name of ONIGENC_MBCLEN_NEEDMORE_LEN.
#define ENCODING_GET(obj)
Old name of RB_ENCODING_GET.
#define LONG2FIX
Old name of RB_INT2FIX.
#define NUM2UINT
Old name of RB_NUM2UINT.
#define ALLOC_N
Old name of RB_ALLOC_N.
#define MBCLEN_CHARFOUND_LEN(ret)
Old name of ONIGENC_MBCLEN_CHARFOUND_LEN.
#define LONG2NUM
Old name of RB_LONG2NUM.
#define rb_exc_new3
Old name of rb_exc_new_str.
#define STRNCASECMP
Old name of st_locale_insensitive_strncasecmp.
#define MBCLEN_INVALID_P(ret)
Old name of ONIGENC_MBCLEN_INVALID_P.
#define ISASCII
Old name of rb_isascii.
#define ECONV_STATEFUL_DECORATOR_MASK
Old name of RUBY_ECONV_STATEFUL_DECORATOR_MASK.
#define Qtrue
Old name of RUBY_Qtrue.
#define MBCLEN_NEEDMORE_P(ret)
Old name of ONIGENC_MBCLEN_NEEDMORE_P.
#define ECONV_PARTIAL_INPUT
Old name of RUBY_ECONV_PARTIAL_INPUT.
#define NUM2INT
Old name of RB_NUM2INT.
#define ECONV_ERROR_HANDLER_MASK
Old name of RUBY_ECONV_ERROR_HANDLER_MASK.
#define INT2NUM
Old name of RB_INT2NUM.
#define Qnil
Old name of RUBY_Qnil.
#define Qfalse
Old name of RUBY_Qfalse.
#define FIX2LONG
Old name of RB_FIX2LONG.
#define ENC_CODERANGE_BROKEN
Old name of RUBY_ENC_CODERANGE_BROKEN.
#define T_ARRAY
Old name of RUBY_T_ARRAY.
#define NIL_P
Old name of RB_NIL_P.
#define ALLOCV_N
Old name of RB_ALLOCV_N.
#define MBCLEN_CHARFOUND_P(ret)
Old name of ONIGENC_MBCLEN_CHARFOUND_P.
#define ECONV_NEWLINE_DECORATOR_READ_MASK
Old name of RUBY_ECONV_NEWLINE_DECORATOR_READ_MASK.
#define NUM2CHR
Old name of RB_NUM2CHR.
#define FL_TEST
Old name of RB_FL_TEST.
#define NUM2LONG
Old name of RB_NUM2LONG.
#define UINT2NUM
Old name of RB_UINT2NUM.
#define FIXNUM_P
Old name of RB_FIXNUM_P.
#define ECONV_NEWLINE_DECORATOR_MASK
Old name of RUBY_ECONV_NEWLINE_DECORATOR_MASK.
#define CONST_ID
Old name of RUBY_CONST_ID.
#define rb_ary_new2
Old name of rb_ary_new_capa.
#define NUM2SIZET
Old name of RB_NUM2SIZE.
#define ENC_CODERANGE_SET(obj, cr)
Old name of RB_ENC_CODERANGE_SET.
#define rb_str_new4
Old name of rb_str_new_frozen.
#define ALLOCV_END
Old name of RB_ALLOCV_END.
#define SYMBOL_P
Old name of RB_SYMBOL_P.
#define ECONV_DEFAULT_NEWLINE_DECORATOR
Old name of RUBY_ECONV_DEFAULT_NEWLINE_DECORATOR.
void rb_notimplement(void)
void rb_category_warn(rb_warning_category_t category, const char *fmt,...)
Identical to rb_category_warning(), except it reports always regardless of runtime -W flag.
void rb_raise(VALUE exc, const char *fmt,...)
Exception entry point.
void rb_category_warning(rb_warning_category_t category, const char *fmt,...)
Identical to rb_warning(), except it takes additional "category" parameter.
VALUE rb_rescue2(VALUE(*b_proc)(VALUE), VALUE data1, VALUE(*r_proc)(VALUE, VALUE), VALUE data2,...)
An equivalent of rescue clause.
VALUE rb_eNotImpError
NotImplementedError exception.
void rb_exc_raise(VALUE mesg)
Raises an exception in the current thread.
void rb_syserr_fail(int e, const char *mesg)
Raises appropriate exception that represents a C errno.
void rb_bug(const char *fmt,...)
Interpreter panic switch.
void rb_sys_fail(const char *mesg)
Converts a C errno into a Ruby exception, then raises it.
void rb_readwrite_syserr_fail(enum rb_io_wait_readwrite waiting, int n, const char *mesg)
Identical to rb_readwrite_sys_fail(), except it does not depend on C global variable errno.
VALUE rb_eIOError
IOError exception.
VALUE rb_eStandardError
StandardError exception.
void rb_mod_syserr_fail_str(VALUE mod, int e, VALUE mesg)
Identical to rb_mod_syserr_fail(), except it takes the message in Ruby's String instead of C's.
void rb_syserr_fail_str(int e, VALUE mesg)
Identical to rb_syserr_fail(), except it takes the message in Ruby's String instead of C's.
#define ruby_verbose
This variable controls whether the interpreter is in debug mode.
VALUE rb_eTypeError
TypeError exception.
VALUE rb_eEOFError
EOFError exception.
void rb_fatal(const char *fmt,...)
Raises the unsung "fatal" exception.
void rb_readwrite_sys_fail(enum rb_io_wait_readwrite waiting, const char *mesg)
Raises appropriate exception using the parameters.
void rb_iter_break_value(VALUE val)
Identical to rb_iter_break(), except it additionally takes the "value" of this breakage.
rb_io_wait_readwrite
for rb_readwrite_sys_fail first argument
VALUE rb_eRuntimeError
RuntimeError exception.
void rb_warn(const char *fmt,...)
Identical to rb_warning(), except it reports always regardless of runtime -W flag.
VALUE rb_eArgError
ArgumentError exception.
VALUE rb_ensure(VALUE(*b_proc)(VALUE), VALUE data1, VALUE(*e_proc)(VALUE), VALUE data2)
An equivalent to ensure clause.
void rb_sys_fail_str(VALUE mesg)
Identical to rb_sys_fail(), except it takes the message in Ruby's String instead of C's.
VALUE rb_eSystemCallError
SystemCallError exception.
@ RB_WARN_CATEGORY_DEPRECATED
Warning is for deprecated features.
VALUE rb_mKernel
Kernel module.
VALUE rb_check_to_int(VALUE val)
Identical to rb_check_to_integer(), except it uses #to_int for conversion.
VALUE rb_any_to_s(VALUE obj)
Generates a textual representation of the given object.
VALUE rb_obj_alloc(VALUE klass)
Allocates an instance of the given class.
VALUE rb_class_new_instance(int argc, const VALUE *argv, VALUE klass)
Allocates, then initialises an instance of the given class.
VALUE rb_class_new_instance_kw(int argc, const VALUE *argv, VALUE klass, int kw_splat)
Identical to rb_class_new_instance(), except you can specify how to handle the last element of the gi...
VALUE rb_mEnumerable
Enumerable module.
VALUE rb_stdin
STDIN constant.
VALUE rb_stderr
STDERR constant.
VALUE rb_obj_class(VALUE obj)
Queries the class of an object.
VALUE rb_obj_dup(VALUE obj)
Duplicates the given object.
VALUE rb_inspect(VALUE obj)
Generates a human-readable textual representation of the given object.
VALUE rb_mWaitReadable
IO::WaitReadable module.
VALUE rb_mWaitWritable
IO::WaitReadable module.
VALUE rb_obj_freeze(VALUE obj)
Just calls rb_obj_freeze_inline() inside.
VALUE rb_check_to_integer(VALUE val, const char *mid)
Identical to rb_check_convert_type(), except the return value type is fixed to rb_cInteger.
VALUE rb_cFile
File class.
VALUE rb_stdout
STDOUT constant.
VALUE rb_to_int(VALUE val)
Identical to rb_check_to_int(), except it raises in case of conversion mismatch.
rb_encoding * rb_locale_encoding(void)
Queries the encoding that represents the current locale.
rb_encoding * rb_default_external_encoding(void)
Queries the "default external" encoding.
int rb_enc_precise_mbclen(const char *p, const char *e, rb_encoding *enc)
Queries the number of bytes of the character at the passed pointer.
int rb_to_encoding_index(VALUE obj)
Obtains a encoding index from a wider range of objects (than rb_enc_find_index()).
VALUE rb_enc_associate(VALUE obj, rb_encoding *enc)
Identical to rb_enc_associate(), except it takes an encoding itself instead of its index.
rb_encoding * rb_usascii_encoding(void)
Queries the encoding that represents US-ASCII.
static char * rb_enc_left_char_head(const char *s, const char *p, const char *e, rb_encoding *enc)
Queries the left boundary of a character.
int rb_utf8_encindex(void)
Identical to rb_utf8_encoding(), except it returns the encoding's index instead of the encoding itsel...
rb_encoding * rb_default_internal_encoding(void)
Queries the "default internal" encoding.
rb_encoding * rb_find_encoding(VALUE obj)
Identical to rb_to_encoding_index(), except the return type.
rb_encoding * rb_to_encoding(VALUE obj)
Identical to rb_find_encoding(), except it raises an exception instead of returning NULL.
rb_encoding * rb_ascii8bit_encoding(void)
Queries the encoding that represents ASCII-8BIT a.k.a.
VALUE rb_enc_from_encoding(rb_encoding *enc)
Queries the Ruby-level counterpart instance of rb_cEncoding that corresponds to the passed encoding.
static bool rb_enc_asciicompat(rb_encoding *enc)
Queries if the passed encoding is in some sense compatible with ASCII.
static unsigned int rb_enc_codepoint(const char *p, const char *e, rb_encoding *enc)
Queries the code point of character pointed by the passed pointer.
rb_encoding * rb_enc_from_index(int idx)
Identical to rb_find_encoding(), except it takes an encoding index instead of a Ruby object.
int rb_enc_mbclen(const char *p, const char *e, rb_encoding *enc)
Queries the number of bytes of the character at the passed pointer.
rb_encoding * rb_enc_get(VALUE obj)
Identical to rb_enc_get_index(), except the return type.
static const char * rb_enc_name(rb_encoding *enc)
Queries the (canonical) name of the passed encoding.
int rb_enc_find_index(const char *name)
Queries the index of the encoding.
static int rb_enc_mbminlen(rb_encoding *enc)
Queries the minimum number of bytes that the passed encoding needs to represent a character.
int rb_enc_ascget(const char *p, const char *e, int *len, rb_encoding *enc)
Queries the code point of character pointed by the passed pointer.
int rb_enc_str_coderange(VALUE str)
Scans the passed string to collect its code range.
VALUE rb_enc_uint_chr(unsigned int code, rb_encoding *enc)
Encodes the passed code point into a series of bytes.
VALUE rb_enc_str_new(const char *ptr, long len, rb_encoding *enc)
Identical to rb_enc_str_new(), except it additionally takes an encoding.
long rb_str_coderange_scan_restartable(const char *str, const char *end, rb_encoding *enc, int *cr)
Scans the passed string until it finds something odd.
int rb_econv_prepare_options(VALUE opthash, VALUE *ecopts, int ecflags)
Identical to rb_econv_prepare_opts(), except it additionally takes the initial value of flags.
VALUE rb_econv_open_exc(const char *senc, const char *denc, int ecflags)
Creates a rb_eConverterNotFoundError exception object (but does not raise).
rb_econv_result_t rb_econv_convert(rb_econv_t *ec, const unsigned char **source_buffer_ptr, const unsigned char *source_buffer_end, unsigned char **destination_buffer_ptr, unsigned char *destination_buffer_end, int flags)
Converts a string from an encoding to another.
rb_econv_result_t
return value of rb_econv_convert()
@ econv_incomplete_input
The conversion stopped in middle of reading a character, possibly due to a partial read of a socket e...
@ econv_finished
The conversion stopped after converting everything.
@ econv_undefined_conversion
The conversion stopped when it found a character in the input which cannot be representable in the ou...
@ econv_source_buffer_empty
The conversion stopped because there is no input.
@ econv_destination_buffer_full
The conversion stopped because there is no destination.
@ econv_invalid_byte_sequence
The conversion stopped when it found an invalid sequence.
int rb_econv_putbackable(rb_econv_t *ec)
Queries if rb_econv_putback() makes sense, i.e.
VALUE rb_econv_str_convert(rb_econv_t *ec, VALUE src, int flags)
Identical to rb_econv_convert(), except it takes Ruby's string instead of C's pointer.
void rb_econv_binmode(rb_econv_t *ec)
This badly named function does not set the destination encoding to binary, but instead just nullifies...
VALUE rb_str_encode(VALUE str, VALUE to, int ecflags, VALUE ecopts)
Converts the contents of the passed string from its encoding to the passed one.
VALUE rb_econv_make_exception(rb_econv_t *ec)
This function makes sense right after rb_econv_convert() returns.
void rb_econv_check_error(rb_econv_t *ec)
This is a rb_econv_make_exception() + rb_exc_raise() combo.
const char * rb_econv_asciicompat_encoding(const char *encname)
Queries the passed encoding's corresponding ASCII compatible encoding.
rb_econv_t * rb_econv_open_opts(const char *source_encoding, const char *destination_encoding, int ecflags, VALUE ecopts)
Identical to rb_econv_open(), except it additionally takes a hash of optional strings.
void rb_econv_close(rb_econv_t *ec)
Destructs a converter.
void rb_econv_putback(rb_econv_t *ec, unsigned char *p, int n)
Puts back the bytes.
VALUE rb_funcall(VALUE recv, ID mid, int n,...)
Calls a method.
VALUE rb_funcallv_kw(VALUE recv, ID mid, int argc, const VALUE *argv, int kw_splat)
Identical to rb_funcallv(), except you can specify how to handle the last element of the given array.
VALUE rb_funcallv(VALUE recv, ID mid, int argc, const VALUE *argv)
Identical to rb_funcall(), except it takes the method arguments as a C array.
void rb_global_variable(VALUE *)
An alias for rb_gc_register_address().
void rb_gc_register_mark_object(VALUE object)
Inform the garbage collector that object is a live Ruby object that should not be moved.
Defines RBIMPL_HAS_BUILTIN.
VALUE rb_ary_concat(VALUE lhs, VALUE rhs)
Destructively appends the contents of latter into the end of former.
VALUE rb_ary_shift(VALUE ary)
Destructively deletes an element from the beginning of the passed array and returns what was deleted.
VALUE rb_check_array_type(VALUE obj)
Try converting an object to its array representation using its to_ary method, if any.
VALUE rb_ary_new(void)
Allocates a new, empty array.
VALUE rb_ary_push(VALUE ary, VALUE elem)
Special case of rb_ary_cat() that it adds only one element.
VALUE rb_ary_entry(VALUE ary, long off)
Queries an element of an array.
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Identical to rb_ary_new_from_values(), except it expects exactly two parameters.
#define RETURN_ENUMERATOR(obj, argc, argv)
Identical to RETURN_SIZED_ENUMERATOR(), except its size is unknown.
#define rb_check_frozen
Just another name of rb_check_frozen.
static int rb_check_arity(int argc, int min, int max)
Ensures that the passed integer is in the passed range.
ID rb_frame_this_func(void)
Queries the name of the Ruby level method that is calling this function.
void rb_jump_tag(int state)
This function is to re-throw global escapes.
VALUE rb_str_encode_ospath(VALUE path)
Converts a string into an "OS Path" encoding, if any.
void rb_gc_mark(VALUE obj)
Marks an object.
void rb_gc(void)
Triggers a GC process.
VALUE rb_check_hash_type(VALUE obj)
Try converting an object to its hash representation using its to_hash method, if any.
VALUE rb_hash_lookup2(VALUE hash, VALUE key, VALUE def)
Identical to rb_hash_lookup(), except you can specify what to return on misshits.
VALUE rb_hash_aref(VALUE hash, VALUE key)
Queries the given key in the given hash table.
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
Inserts or replaces ("upsert"s) the objects into the given hash table.
VALUE rb_hash_lookup(VALUE hash, VALUE key)
Identical to rb_hash_aref(), except it always returns RUBY_Qnil for misshits.
VALUE rb_hash_dup(VALUE hash)
Duplicates a hash.
VALUE rb_hash_new(void)
Creates a new, empty hash object.
VALUE rb_io_printf(int argc, const VALUE *argv, VALUE io)
This is a rb_f_sprintf() + rb_io_write() combo.
VALUE rb_io_gets(VALUE io)
Reads a "line" from the given IO.
int rb_cloexec_pipe(int fildes[2])
Opens a pipe with closing on exec.
VALUE rb_rs
The record separator character for inputs, or the $/.
VALUE rb_io_print(int argc, const VALUE *argv, VALUE io)
Iterates over the passed array to apply rb_io_write() individually.
VALUE rb_io_addstr(VALUE io, VALUE str)
Identical to rb_io_write(), except it always returns the passed IO.
void rb_write_error(const char *str)
Writes the given error message to somewhere applicable.
VALUE rb_io_ungetbyte(VALUE io, VALUE b)
Identical to rb_io_ungetc(), except it doesn't take the encoding of the passed IO into account.
VALUE rb_io_getbyte(VALUE io)
Reads a byte from the given IO.
VALUE rb_io_puts(int argc, const VALUE *argv, VALUE io)
Iterates over the passed array to apply rb_io_write() individually.
int rb_cloexec_dup2(int oldfd, int newfd)
Identical to rb_cloexec_dup(), except you can specify the destination file descriptor.
VALUE rb_io_fdopen(int fd, int flags, const char *path)
Creates an IO instance whose backend is the given file descriptor.
void rb_update_max_fd(int fd)
Informs the interpreter that the passed fd can be the max.
VALUE rb_io_write(VALUE io, VALUE str)
Writes the given string to the given IO.
int rb_cloexec_open(const char *pathname, int flags, mode_t mode)
Opens a file that closes on exec.
VALUE rb_output_rs
The record separator character for outputs, or the $\.
VALUE rb_io_eof(VALUE io)
Queries if the passed IO is at the end of file.
void rb_write_error2(const char *str, long len)
Identical to rb_write_error(), except it additionally takes the message's length.
void rb_close_before_exec(int lowfd, int maxhint, VALUE noclose_fds)
Closes everything.
int rb_reserved_fd_p(int fd)
Queries if the given FD is reserved or not.
void rb_fd_fix_cloexec(int fd)
Sets or clears the close-on-exec flag of the passed file descriptor to the desired state.
VALUE rb_io_flush(VALUE io)
Flushes any buffered data within the passed IO to the underlying operating system.
VALUE rb_io_ascii8bit_binmode(VALUE io)
Forces no conversions be applied to the passed IO.
VALUE rb_io_binmode(VALUE io)
Sets the binmode.
VALUE rb_io_ungetc(VALUE io, VALUE c)
"Unget"s a string.
int rb_pipe(int *pipes)
This is an rb_cloexec_pipe() + rb_update_max_fd() combo.
VALUE rb_gets(void)
Much like rb_io_gets(), but it reads from the mysterious ARGF object.
int rb_cloexec_fcntl_dupfd(int fd, int minfd)
Duplicates a file descriptor with closing on exec.
VALUE rb_output_fs
The field separator character for outputs, or the $,.
VALUE rb_file_open_str(VALUE fname, const char *fmode)
Identical to rb_file_open(), except it takes the pathname as a Ruby's string instead of C's.
int rb_cloexec_dup(int oldfd)
Identical to rb_cloexec_fcntl_dupfd(), except it implies minfd is 3.
VALUE rb_file_open(const char *fname, const char *fmode)
Opens a file located at the given path.
VALUE rb_io_close(VALUE io)
Closes the IO.
VALUE rb_default_rs
This is the default value of rb_rs, i.e.
void rb_lastline_set(VALUE str)
Updates $_.
VALUE rb_lastline_get(void)
Queries the last line, or the $_.
int rb_obj_method_arity(VALUE obj, ID mid)
Identical to rb_mod_method_arity(), except it searches for singleton methods rather than instance met...
VALUE rb_protect(VALUE(*func)(VALUE args), VALUE args, int *state)
Protects a function call from potential global escapes from the function.
rb_pid_t rb_waitpid(rb_pid_t pid, int *status, int flags)
Waits for a process, with releasing GVL.
void rb_last_status_set(int status, rb_pid_t pid)
Sets the "last status", or the $?.
VALUE rb_str_append(VALUE dst, VALUE src)
Identical to rb_str_buf_append(), except it converts the right hand side before concatenating.
VALUE rb_str_buf_cat(VALUE, const char *, long)
Just another name of rb_str_cat.
size_t rb_str_capacity(VALUE str)
Queries the capacity of the given string.
VALUE rb_str_new_frozen(VALUE str)
Creates a frozen copy of the string, if necessary.
VALUE rb_str_cat2(VALUE, const char *)
Just another name of rb_str_cat_cstr.
VALUE rb_str_dup(VALUE str)
Duplicates a string.
void rb_str_modify(VALUE str)
Declares that the string is about to be modified.
VALUE rb_str_cat(VALUE dst, const char *src, long srclen)
Destructively appends the passed contents to the string.
VALUE rb_str_locktmp(VALUE str)
Obtains a "temporary lock" of the string.
VALUE rb_usascii_str_new(const char *ptr, long len)
Identical to rb_str_new(), except it generates a string of "US ASCII" encoding.
rb_gvar_setter_t rb_str_setter
This is a rb_gvar_setter_t that refutes non-string assignments.
void rb_str_set_len(VALUE str, long len)
Overwrites the length of the string.
VALUE rb_str_buf_cat_ascii(VALUE dst, const char *src)
Identical to rb_str_cat_cstr(), except it additionally assumes the source string be a NUL terminated ...
VALUE rb_str_new(const char *ptr, long len)
Allocates an instance of rb_cString.
VALUE rb_check_string_type(VALUE obj)
Try converting an object to its stringised representation using its to_str method,...
VALUE rb_str_substr(VALUE str, long beg, long len)
This is the implementation of two-argumented String#slice.
VALUE rb_str_unlocktmp(VALUE str)
Releases a lock formerly obtained by rb_str_locktmp().
VALUE rb_str_new_cstr(const char *ptr)
Identical to rb_str_new(), except it assumes the passed pointer is a pointer to a C string.
VALUE rb_str_resize(VALUE str, long len)
Overwrites the length of the string.
void rb_str_modify_expand(VALUE str, long capa)
Identical to rb_str_modify(), except it additionally expands the capacity of the receiver.
VALUE rb_str_buf_new(long capa)
Allocates a "string buffer".
VALUE rb_obj_as_string(VALUE obj)
Try converting an object to its stringised representation using its to_s method, if any.
int rb_thread_interrupted(VALUE thval)
Checks if the thread's execution was recently interrupted.
VALUE rb_mutex_new(void)
Creates a mutex.
int rb_thread_fd_writable(int fd)
Identical to rb_thread_wait_fd(), except it blocks the current thread until the given file descriptor...
#define RUBY_UBF_IO
A special UBF for blocking IO operations.
VALUE rb_exec_recursive(VALUE(*f)(VALUE g, VALUE h, int r), VALUE g, VALUE h)
"Recursion" API entry point.
void rb_thread_fd_close(int fd)
Notifies a closing of a file descriptor to other threads.
VALUE rb_mutex_synchronize(VALUE mutex, VALUE(*func)(VALUE arg), VALUE arg)
Obtains the lock, runs the passed function, and releases the lock when it completes.
void rb_thread_check_ints(void)
Checks for interrupts.
VALUE rb_thread_current(void)
Obtains the "current" thread.
int rb_thread_wait_fd(int fd)
Blocks the current thread until the given file descriptor is ready to be read.
void rb_thread_schedule(void)
Tries to switch to another thread.
void rb_thread_sleep(int sec)
Blocks for the given period of time.
struct timeval rb_time_interval(VALUE num)
Creates a "time interval".
VALUE rb_attr_get(VALUE obj, ID name)
Identical to rb_ivar_get()
void rb_set_class_path(VALUE klass, VALUE space, const char *name)
Names a class.
VALUE rb_ivar_set(VALUE obj, ID name, VALUE val)
Identical to rb_iv_set(), except it accepts the name as an ID instead of a C string.
VALUE rb_class_name(VALUE obj)
Queries the name of the given object's class.
int rb_respond_to(VALUE obj, ID mid)
Queries if the object responds to the method.
int rb_method_basic_definition_p(VALUE klass, ID mid)
Well...
VALUE rb_check_funcall(VALUE recv, ID mid, int argc, const VALUE *argv)
Identical to rb_funcallv(), except it returns RUBY_Qundef instead of raising rb_eNoMethodError.
void rb_define_alloc_func(VALUE klass, rb_alloc_func_t func)
Sets the allocator function of a class.
static ID rb_intern_const(const char *str)
This is a "tiny optimisation" over rb_intern().
const char * rb_id2name(ID id)
Retrieves the name mapped to the given id.
ID rb_intern(const char *name)
Finds or creates a symbol of the given name.
VALUE rb_id2str(ID id)
Identical to rb_id2name(), except it returns a Ruby's String instead of C's.
void rb_define_global_const(const char *name, VALUE val)
Identical to rb_define_const(), except it defines that of "global", i.e.
void rb_define_readonly_variable(const char *name, const VALUE *var)
Identical to rb_define_variable(), except it does not allow Ruby programs to assign values to such gl...
rb_gvar_setter_t rb_gvar_readonly_setter
This function just raises rb_eNameError.
void rb_define_virtual_variable(const char *name, rb_gvar_getter_t *getter, rb_gvar_setter_t *setter)
Defines a global variable that is purely function-backended.
void rb_define_const(VALUE klass, const char *name, VALUE val)
Defines a Ruby level constant under a namespace.
void rb_define_hooked_variable(const char *name, VALUE *var, rb_gvar_getter_t *getter, rb_gvar_setter_t *setter)
Identical to rb_define_virtual_variable(), but can also specify a storage.
#define FMODE_READABLE
The IO is opened for reading.
int rb_io_modestr_fmode(const char *modestr)
Maps a file mode string (that rb_file_open() takes) into a mixture of FMODE_ flags.
VALUE rb_io_get_io(VALUE io)
Identical to rb_io_check_io(), except it raises exceptions on conversion failures.
VALUE rb_io_taint_check(VALUE obj)
void rb_io_read_check(rb_io_t *fptr)
Blocks until there is a pending read in the passed IO.
int rb_io_modestr_oflags(const char *modestr)
Identical to rb_io_modestr_fmode(), except it returns a mixture of O_ flags.
#define FMODE_SETENC_BY_BOM
This flag amends the encoding of the IO so that the BOM of the contents of the IO takes effect.
#define FMODE_READWRITE
The IO is opened for both read/write.
#define GetOpenFile
This is an old name of RB_IO_POINTER.
void rb_io_check_byte_readable(rb_io_t *fptr)
Asserts that an IO is opened for byte-based reading.
#define FMODE_TTY
The IO is a TTY.
#define FMODE_CREATE
The IO is opened for creating.
void rb_io_check_readable(rb_io_t *fptr)
Just another name of rb_io_check_byte_readable.
int rb_io_extract_encoding_option(VALUE opt, rb_encoding **enc_p, rb_encoding **enc2_p, int *fmode_p)
This function breaks down the option hash that IO#initialize takes into components.
struct rb_io_t rb_io_t
Ruby's IO, metadata and buffers.
FILE * rb_io_stdio_file(rb_io_t *fptr)
Finds or creates a stdio's file structure from a Ruby's one.
int rb_wait_for_single_fd(int fd, int events, struct timeval *tv)
Blocks until the passed file descriptor is ready for the passed events.
struct rb_io_enc_t rb_io_enc_t
Just another name of rb_io_enc_t.
int rb_io_descriptor(VALUE io)
Returns an integer representing the numeric file descriptor for io.
#define FMODE_WRITABLE
The IO is opened for writing.
#define FMODE_APPEND
The IO is opened for appending.
#define MakeOpenFile
This is an old name of RB_IO_OPEN.
#define FMODE_DUPLEX
Ruby eventually detects that the IO is bidirectional.
#define FMODE_BINMODE
The IO is in "binary mode".
int rb_io_maybe_wait_readable(int error, VALUE io, VALUE timeout)
Blocks until the passed IO is ready for reading, if that makes sense for the passed errno.
#define RB_IO_POINTER(obj, fp)
Queries the underlying IO pointer.
VALUE rb_io_maybe_wait(int error, VALUE io, VALUE events, VALUE timeout)
Identical to rb_io_wait() except it additionally takes previous errno.
#define FMODE_SYNC
The IO is in "sync mode".
void rb_io_check_initialized(rb_io_t *fptr)
Asserts that the passed IO is initialised.
#define FMODE_EXCL
This flag amends the effect of FMODE_CREATE, so that if there already is a file at the given path the...
#define FMODE_TEXTMODE
The IO is in "text mode".
int rb_io_fptr_finalize(rb_io_t *fptr)
Destroys the given IO.
VALUE rb_io_check_io(VALUE io)
Try converting an object to its IO representation using its to_io method, if any.
FILE * rb_fdopen(int fd, const char *modestr)
Identical to rb_io_stdio_file(), except it takes file descriptors instead of Ruby's IO.
ssize_t rb_io_bufwrite(VALUE io, const void *buf, size_t size)
Buffered write to the passed IO.
void rb_io_check_char_readable(rb_io_t *fptr)
Asserts that an IO is opened for character-based reading.
#define FMODE_TRUNC
This flag amends the effect of FMODE_CREATE, so that if there already is a file at the given path it ...
VALUE rb_io_get_write_io(VALUE io)
Queries the tied IO for writing.
void rb_io_set_nonblock(rb_io_t *fptr)
Sets an IO to a "nonblock mode".
void rb_io_extract_modeenc(VALUE *vmode_p, VALUE *vperm_p, VALUE opthash, int *oflags_p, int *fmode_p, rb_io_enc_t *convconfig_p)
This function can be seen as an extended version of rb_io_extract_encoding_option() that not only con...
int rb_io_wait_writable(int fd)
Blocks until the passed file descriptor gets writable.
VALUE rb_io_set_write_io(VALUE io, VALUE w)
Assigns the tied IO for writing.
void rb_io_check_writable(rb_io_t *fptr)
Asserts that an IO is opened for writing.
int rb_io_maybe_wait_writable(int error, VALUE io, VALUE timeout)
Blocks until the passed IO is ready for writing, if that makes sense for the passed errno.
void rb_io_check_closed(rb_io_t *fptr)
This badly named function asserts that the passed IO is open.
@ RUBY_IO_READABLE
IO::READABLE
@ RUBY_IO_PRIORITY
IO::PRIORITY
@ RUBY_IO_WRITABLE
IO::WRITABLE
int rb_io_wait_readable(int fd)
Blocks until the passed file descriptor gets readable.
void rb_io_synchronized(rb_io_t *fptr)
Sets FMODE_SYNC.
VALUE rb_io_wait(VALUE io, VALUE events, VALUE timeout)
Blocks until the passed IO is ready for the passed events.
void * rb_thread_call_without_gvl2(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2)
Identical to rb_thread_call_without_gvl(), except it does not interface with signals etc.
void * rb_thread_call_with_gvl(void *(*func)(void *), void *data1)
(Re-)acquires the GVL.
void * rb_thread_call_without_gvl(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2)
Allows the passed function to run in parallel with other Ruby threads.
#define RB_NUM2INT
Just another name of rb_num2int_inline.
#define RB_INT2NUM
Just another name of rb_int2num_inline.
VALUE rb_f_sprintf(int argc, const VALUE *argv)
Identical to rb_str_format(), except how the arguments are arranged.
VALUE rb_sprintf(const char *fmt,...)
Ruby's extended sprintf(3).
VALUE rb_str_catf(VALUE dst, const char *fmt,...)
Identical to rb_sprintf(), except it renders the output to the specified object rather than creating ...
#define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)
Shim for block function parameters.
VALUE rb_yield_values2(int n, const VALUE *argv)
Identical to rb_yield_values(), except it takes the parameters as a C array instead of variadic argum...
VALUE rb_yield(VALUE val)
Yields the block.
int rb_fd_select(int nfds, rb_fdset_t *rfds, rb_fdset_t *wfds, rb_fdset_t *efds, struct timeval *timeout)
Waits for multiple file descriptors at once.
int rb_fd_isset(int fd, const rb_fdset_t *f)
Queries if the given FD is in the given set.
void rb_fd_term(rb_fdset_t *f)
Destroys the rb_fdset_t, releasing any memory and resources it used.
#define MEMZERO(p, type, n)
Handy macro to erase a region of memory.
#define RB_GC_GUARD(v)
Prevents premature destruction of local objects.
#define MEMMOVE(p1, p2, type, n)
Handy macro to call memmove.
#define NUM2MODET
Converts a C's mode_t into an instance of rb_cInteger.
#define PRI_OFFT_PREFIX
A rb_sprintf() format prefix to be used for an off_t parameter.
#define OFFT2NUM
Converts a C's off_t into an instance of rb_cInteger.
#define NUM2OFFT
Converts an instance of rb_cNumeric into C's off_t.
#define PIDT2NUM
Converts a C's pid_t into an instance of rb_cInteger.
#define rb_fd_init
Initialises the :given :rb_fdset_t.
#define rb_fd_set
Sets the given fd to the rb_fdset_t.
VALUE rb_ractor_stderr(void)
Queries the standard error of the current Ractor that is calling this function.
VALUE rb_ractor_stdin(void)
Queries the standard input of the current Ractor that is calling this function.
void rb_ractor_stderr_set(VALUE io)
Assigns an IO to the standard error of the Ractor that is calling this function.
VALUE rb_ractor_stdout(void)
Queries the standard output of the current Ractor that is calling this function.
void rb_ractor_stdout_set(VALUE io)
Assigns an IO to the standard output of the Ractor that is calling this function.
void rb_ractor_stdin_set(VALUE io)
Assigns an IO to the standard input of the Ractor that is calling this function.
#define RARRAY_LEN
Just another name of rb_array_len.
static int RARRAY_LENINT(VALUE ary)
Identical to rb_array_len(), except it differs for the return type.
#define RARRAY_AREF(a, i)
#define RARRAY_CONST_PTR
Just another name of rb_array_const_ptr.
#define RFILE(obj)
Convenient casting macro.
#define SafeStringValue(v)
#define StringValue(v)
Ensures that the parameter object is a String.
static char * RSTRING_END(VALUE str)
Queries the end of the contents pointer of the string.
static char * RSTRING_PTR(VALUE str)
Queries the contents pointer of the string.
#define RSTRING_GETMEM(str, ptrvar, lenvar)
Convenient macro to obtain the contents and length at once.
static long RSTRING_LEN(VALUE str)
Queries the length of the string.
#define StringValueCStr(v)
Identical to StringValuePtr, except it additionally checks for the contents for viability as a C stri...
#define RUBY_TYPED_DEFAULT_FREE
This is a value you can set to rb_data_type_struct::dfree.
#define TypedData_Make_Struct(klass, type, data_type, sval)
Identical to TypedData_Wrap_Struct, except it allocates a new data region internally instead of takin...
VALUE rb_get_argv(void)
Queries the arguments passed to the current process that you can access from Ruby as ARGV.
void rb_p(VALUE obj)
Inspects an object.
#define FilePathValue(v)
Ensures that the parameter object is a path.
#define RB_SCAN_ARGS_LAST_HASH_KEYWORDS
Treat a final argument as keywords if it is a hash, and not as keywords otherwise.
#define RB_PASS_CALLED_KEYWORDS
Pass keywords if current method is called with keywords, useful for argument delegation.
VALUE rb_fiber_scheduler_current(void)
Identical to rb_fiber_scheduler_get(), except it also returns RUBY_Qnil in case of a blocking fiber.
VALUE rb_fiber_scheduler_make_timeout(struct timeval *timeout)
Converts the passed timeout to an expression that rb_fiber_scheduler_block() etc.
VALUE rb_fiber_scheduler_io_wait_readable(VALUE scheduler, VALUE io)
Nonblocking wait until the passed IO is ready for reading.
VALUE rb_fiber_scheduler_io_wait(VALUE scheduler, VALUE io, VALUE events, VALUE timeout)
Nonblocking version of rb_io_wait().
static ssize_t rb_fiber_scheduler_io_result_apply(VALUE result)
Apply an io result to the local thread, returning the value of the original system call that created ...
VALUE rb_fiber_scheduler_current_for_thread(VALUE thread)
Identical to rb_fiber_scheduler_current(), except it queries for that of the passed thread instead of...
VALUE rb_fiber_scheduler_io_wait_writable(VALUE scheduler, VALUE io)
Nonblocking wait until the passed IO is ready for writing.
VALUE rb_fiber_scheduler_io_write_memory(VALUE scheduler, VALUE io, const void *buffer, size_t size, size_t length)
Nonblocking write to the passed IO using a native buffer.
VALUE rb_fiber_scheduler_io_read_memory(VALUE scheduler, VALUE io, void *buffer, size_t size, size_t length)
Nonblocking read from the passed IO using a native buffer.
int rb_thread_fd_select(int nfds, rb_fdset_t *rfds, rb_fdset_t *wfds, rb_fdset_t *efds, struct timeval *timeout)
Waits for multiple file descriptors at once.
#define RTEST
This is an old name of RB_TEST.
#define _(args)
This was a transition path from K&R to ANSI.
This is the struct that holds necessary info for a struct.
The data structure which wraps the fd_set bitmap used by select(2).
int len
Length of the buffer.
char * ptr
Pointer to the underlying memory region, of at least capa bytes.
int off
Offset inside of ptr.
int capa
Designed capacity of the buffer.
rb_encoding * enc
Internal encoding.
rb_encoding * enc2
External encoding.
VALUE ecopts
Flags as Ruby hash.
Ruby's IO, metadata and buffers.
struct rb_io_t::rb_io_enc_t encs
Decomposed encoding flags.
int lineno
number of lines read
rb_econv_t * writeconv
Encoding converter used when writing to this IO.
rb_pid_t pid
child's pid (for pipes)
rb_io_buffer_t wbuf
Write buffer.
rb_econv_t * readconv
Encoding converter used when reading from this IO.
VALUE writeconv_asciicompat
This is, when set, an instance of rb_cString which holds the "common" encoding.
FILE * stdio_file
stdio ptr for read/write, if available.
int writeconv_initialized
Whether rb_io_t::writeconv is already set up.
VALUE pathv
pathname for file
int mode
mode flags: FMODE_XXXs
int writeconv_pre_ecflags
Value of rb_io_t::rb_io_enc_t::ecflags stored right before initialising rb_io_t::writeconv.
VALUE write_lock
This is a Ruby level mutex.
rb_io_buffer_t cbuf
rb_io_ungetc() destination.
VALUE self
The IO's Ruby level counterpart.
VALUE writeconv_pre_ecopts
Value of rb_io_t::rb_io_enc_t::ecopts stored right before initialising rb_io_t::writeconv.
VALUE tied_io_for_writing
Duplex IO object, if set.
void(* finalize)(struct rb_io_t *, int)
finalize proc
rb_io_buffer_t rbuf
(Byte) read buffer.
intptr_t SIGNED_VALUE
A signed integer type that has the same width with VALUE.
uintptr_t ID
Type that represents a Ruby identifier such as a variable name.
uintptr_t VALUE
Type that represents a Ruby object.
static void Check_Type(VALUE v, enum ruby_value_type t)
Identical to RB_TYPE_P(), except it raises exceptions on predication failure.
static bool RB_TYPE_P(VALUE obj, enum ruby_value_type t)
Queries if the given object is of given type.