14#include "ruby/internal/config.h"
30# if defined(__linux__)
33# if defined(__FreeBSD_version) && __FreeBSD_version >= 1100000
43#define free(x) xfree(x)
45#if defined(DOSISH) || defined(__CYGWIN__)
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)
69#if defined(HAVE_SYS_IOCTL_H) && !defined(_WIN32)
72#if defined(HAVE_FCNTL_H) || defined(_WIN32)
74#elif defined(HAVE_SYS_FCNTL_H)
84#if defined(HAVE_SYS_PARAM_H) || defined(__HIUX_MPP__)
85# include <sys/param.h>
98#elif defined HAVE_SYS_SYSCALL_H
99#include <sys/syscall.h>
106#ifdef HAVE_SYS_WAIT_H
107# include <sys/wait.h>
110#ifdef HAVE_COPYFILE_H
111# include <copyfile.h>
115#include "ccan/list/list.h"
120#include "internal/encoding.h"
121#include "internal/error.h"
122#include "internal/inits.h"
123#include "internal/io.h"
124#include "internal/numeric.h"
125#include "internal/object.h"
126#include "internal/process.h"
127#include "internal/thread.h"
128#include "internal/transcode.h"
129#include "internal/variable.h"
132#include "ruby/missing.h"
135#include "ruby_atomic.h"
145#define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR)
149# ifdef _POSIX_PIPE_BUF
150# define PIPE_BUF _POSIX_PIPE_BUF
157# define EWOULDBLOCK EAGAIN
160#if defined(HAVE___SYSCALL) && (defined(__APPLE__) || defined(__OpenBSD__))
162off_t __syscall(quad_t number, ...);
165#define IO_RBUF_CAPA_MIN 8192
166#define IO_CBUF_CAPA_MIN (128*1024)
167#define IO_RBUF_CAPA_FOR(fptr) (NEED_READCONV(fptr) ? IO_CBUF_CAPA_MIN : IO_RBUF_CAPA_MIN)
168#define IO_WBUF_CAPA_MIN 8192
170#define IO_MAX_BUFFER_GROWTH 8 * 1024 * 1024
175#define open rb_w32_uopen
177#define rename(f, t) rb_w32_urename((f), (t))
187static VALUE rb_eEAGAINWaitReadable;
188static VALUE rb_eEAGAINWaitWritable;
189static VALUE rb_eEWOULDBLOCKWaitReadable;
190static VALUE rb_eEWOULDBLOCKWaitWritable;
191static VALUE rb_eEINPROGRESSWaitWritable;
192static VALUE rb_eEINPROGRESSWaitReadable;
195static VALUE orig_stdout, orig_stderr;
204static ID id_write, id_read, id_getc, id_flush, id_readpartial, id_set_encoding, id_fileno;
205static VALUE sym_mode, sym_perm, sym_flags, sym_extenc, sym_intenc, sym_encoding, sym_open_args;
206static VALUE sym_textmode, sym_binmode, sym_autoclose;
207static VALUE sym_SET, sym_CUR, sym_END;
208static VALUE sym_wait_readable, sym_wait_writable;
210static VALUE sym_DATA;
213static VALUE sym_HOLE;
216static VALUE prep_io(
int fd,
int fmode,
VALUE klass,
const char *path);
219 VALUE filename, current_file;
225 int8_t init_p, next_p, binmode;
236 if (fd < 0 || afd <= max_fd)
239#if defined(HAVE_FCNTL) && defined(F_GETFL)
240 err = fcntl(fd, F_GETFL) == -1;
244 err = fstat(fd, &buf) != 0;
247 if (err && errno == EBADF) {
248 rb_bug(
"rb_update_max_fd: invalid fd (%d) given.", fd);
251 while (max_fd < afd) {
252 max_fd = ATOMIC_CAS(max_file_descriptor, max_fd, afd);
257rb_maygvl_fd_fix_cloexec(
int fd)
260#if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
261 int flags, flags2, ret;
262 flags = fcntl(fd, F_GETFD);
264 rb_bug(
"rb_maygvl_fd_fix_cloexec: fcntl(%d, F_GETFD) failed: %s", fd, strerror(errno));
267 flags2 = flags & ~FD_CLOEXEC;
269 flags2 = flags | FD_CLOEXEC;
270 if (flags != flags2) {
271 ret = fcntl(fd, F_SETFD, flags2);
273 rb_bug(
"rb_maygvl_fd_fix_cloexec: fcntl(%d, F_SETFD, %d) failed: %s", fd, flags2, strerror(errno));
282 rb_maygvl_fd_fix_cloexec(fd);
288rb_fix_detect_o_cloexec(
int fd)
290#if defined(O_CLOEXEC) && defined(F_GETFD)
291 int flags = fcntl(fd, F_GETFD);
294 rb_bug(
"rb_fix_detect_o_cloexec: fcntl(%d, F_GETFD) failed: %s", fd, strerror(errno));
296 if (flags & FD_CLOEXEC)
299 rb_maygvl_fd_fix_cloexec(fd);
306 return (e == EWOULDBLOCK) || (e == EAGAIN);
313 static int o_cloexec_state = -1;
315 static const int retry_interval = 0;
316 static const int retry_max_count = 10000;
323#elif defined O_NOINHERIT
324 flags |= O_NOINHERIT;
327 while ((ret = open(pathname, flags, mode)) == -1) {
329 if (!io_again_p(e))
break;
330 if (retry_count++ >= retry_max_count)
break;
332 sleep(retry_interval);
335 if (ret < 0)
return ret;
336 if (ret <= 2 || o_cloexec_state == 0) {
337 rb_maygvl_fd_fix_cloexec(ret);
339 else if (o_cloexec_state > 0) {
343 o_cloexec_state = rb_fix_detect_o_cloexec(ret);
362 if (oldfd == newfd) {
366#if defined(HAVE_DUP3) && defined(O_CLOEXEC)
367 static int try_dup3 = 1;
368 if (2 < newfd && try_dup3) {
369 ret = dup3(oldfd, newfd, O_CLOEXEC);
373 if (errno == ENOSYS) {
375 ret = dup2(oldfd, newfd);
379 ret = dup2(oldfd, newfd);
382 ret = dup2(oldfd, newfd);
384 if (ret < 0)
return ret;
386 rb_maygvl_fd_fix_cloexec(ret);
391rb_fd_set_nonblock(
int fd)
394 return rb_w32_set_nonblock(fd);
395#elif defined(F_GETFL)
396 int oflags = fcntl(fd, F_GETFL);
400 if (oflags & O_NONBLOCK)
402 oflags |= O_NONBLOCK;
403 return fcntl(fd, F_SETFL, oflags);
412 int result = pipe2(descriptors, O_CLOEXEC | O_NONBLOCK);
414 int result = pipe(descriptors);
421 if (result == 0 && descriptors[1] == -1) {
422 close(descriptors[0]);
430 rb_maygvl_fd_fix_cloexec(descriptors[0]);
431 rb_maygvl_fd_fix_cloexec(descriptors[1]);
434 rb_fd_set_nonblock(descriptors[0]);
435 rb_fd_set_nonblock(descriptors[1]);
447#if defined(HAVE_FCNTL) && defined(F_DUPFD_CLOEXEC) && defined(F_DUPFD)
448 static int try_dupfd_cloexec = 1;
449 if (try_dupfd_cloexec) {
450 ret = fcntl(fd, F_DUPFD_CLOEXEC, minfd);
453 rb_maygvl_fd_fix_cloexec(ret);
457 if (errno == EINVAL) {
458 ret = fcntl(fd, F_DUPFD, minfd);
460 try_dupfd_cloexec = 0;
465 ret = fcntl(fd, F_DUPFD, minfd);
467#elif defined(HAVE_FCNTL) && defined(F_DUPFD)
468 ret = fcntl(fd, F_DUPFD, minfd);
471 if (ret >= 0 && ret < minfd) {
472 const int prev_fd = ret;
478 if (ret < 0)
return ret;
479 rb_maygvl_fd_fix_cloexec(ret);
483#define argf_of(obj) (*(struct argf *)DATA_PTR(obj))
484#define ARGF argf_of(argf)
486#define GetWriteIO(io) rb_io_get_write_io(io)
488#define READ_DATA_PENDING(fptr) ((fptr)->rbuf.len)
489#define READ_DATA_PENDING_COUNT(fptr) ((fptr)->rbuf.len)
490#define READ_DATA_PENDING_PTR(fptr) ((fptr)->rbuf.ptr+(fptr)->rbuf.off)
491#define READ_DATA_BUFFERED(fptr) READ_DATA_PENDING(fptr)
493#define READ_CHAR_PENDING(fptr) ((fptr)->cbuf.len)
494#define READ_CHAR_PENDING_COUNT(fptr) ((fptr)->cbuf.len)
495#define READ_CHAR_PENDING_PTR(fptr) ((fptr)->cbuf.ptr+(fptr)->cbuf.off)
498#define WAIT_FD_IN_WIN32(fptr) \
499 (rb_w32_io_cancelable_p((fptr)->fd) ? Qnil : rb_io_wait(fptr->self, RB_INT2NUM(RUBY_IO_READABLE), RUBY_IO_TIMEOUT_DEFAULT))
501#define WAIT_FD_IN_WIN32(fptr)
504#define READ_CHECK(fptr) do {\
505 if (!READ_DATA_PENDING(fptr)) {\
506 WAIT_FD_IN_WIN32(fptr);\
507 rb_io_check_closed(fptr);\
513# define S_ISSOCK(m) _S_ISSOCK(m)
516# define S_ISSOCK(m) (((m) & S_IFMT) == _S_IFSOCK)
519# define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
525static int io_fflush(
rb_io_t *);
528#define FMODE_PREP (1<<16)
529#define FMODE_SIGNAL_ON_EPIPE (1<<17)
531#define fptr_signal_on_epipe(fptr) \
532 (((fptr)->mode & FMODE_SIGNAL_ON_EPIPE) != 0)
534#define fptr_set_signal_on_epipe(fptr, flag) \
536 (fptr)->mode |= FMODE_SIGNAL_ON_EPIPE : \
537 (fptr)->mode &= ~FMODE_SIGNAL_ON_EPIPE)
539extern ID ruby_static_id_signo;
541NORETURN(
static void raise_on_write(
rb_io_t *fptr,
int e,
VALUE errinfo));
546 if (fptr_signal_on_epipe(fptr) && (e == EPIPE)) {
558#define rb_sys_fail_on_write(fptr) \
561 raise_on_write(fptr, e, rb_syserr_new_path(e, (fptr)->pathv)); \
564#define NEED_NEWLINE_DECORATOR_ON_READ(fptr) ((fptr)->mode & FMODE_TEXTMODE)
565#define NEED_NEWLINE_DECORATOR_ON_WRITE(fptr) ((fptr)->mode & FMODE_TEXTMODE)
566#if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
567# define RUBY_CRLF_ENVIRONMENT 1
569# define RUBY_CRLF_ENVIRONMENT 0
572#if RUBY_CRLF_ENVIRONMENT
574# define DEFAULT_TEXTMODE FMODE_TEXTMODE
575# define TEXTMODE_NEWLINE_DECORATOR_ON_WRITE ECONV_CRLF_NEWLINE_DECORATOR
583#define NEED_READCONV(fptr) ((fptr)->encs.enc2 != NULL || (fptr)->encs.ecflags & ~ECONV_CRLF_NEWLINE_DECORATOR)
584#define WRITECONV_MASK ( \
585 (ECONV_DECORATOR_MASK & ~ECONV_CRLF_NEWLINE_DECORATOR)|\
586 ECONV_STATEFUL_DECORATOR_MASK|\
588#define NEED_WRITECONV(fptr) ( \
589 ((fptr)->encs.enc != NULL && (fptr)->encs.enc != rb_ascii8bit_encoding()) || \
590 ((fptr)->encs.ecflags & WRITECONV_MASK) || \
592#define SET_BINARY_MODE(fptr) setmode((fptr)->fd, O_BINARY)
594#define NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr) do {\
595 if (NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {\
596 if (((fptr)->mode & FMODE_READABLE) &&\
597 !((fptr)->encs.ecflags & ECONV_NEWLINE_DECORATOR_MASK)) {\
598 setmode((fptr)->fd, O_BINARY);\
601 setmode((fptr)->fd, O_TEXT);\
606#define SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags) do {\
607 if ((enc2) && ((ecflags) & ECONV_DEFAULT_NEWLINE_DECORATOR)) {\
608 (ecflags) |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;\
632 if (!rb_w32_fd_is_text(fptr->
fd)) {
633 r = lseek(fptr->
fd, -fptr->
rbuf.
len, SEEK_CUR);
634 if (r < 0 && errno) {
645 pos = lseek(fptr->
fd, 0, SEEK_CUR);
646 if (pos < 0 && errno) {
653 extra_max = (long)(pos - fptr->
rbuf.
len);
661 for (i = 0; i < fptr->
rbuf.
len; i++) {
662 if (*p ==
'\n') newlines++;
663 if (extra_max == newlines)
break;
668 while (newlines >= 0) {
669 r = lseek(fptr->
fd, pos - fptr->
rbuf.
len - newlines, SEEK_SET);
670 if (newlines == 0)
break;
675 read_size = _read(fptr->
fd, buf, fptr->
rbuf.
len + newlines);
679 rb_syserr_fail_path(e, fptr->
pathv);
681 if (read_size == fptr->
rbuf.
len) {
682 lseek(fptr->
fd, r, SEEK_SET);
703set_binary_mode_with_seek_cur(
rb_io_t *fptr)
705 if (!rb_w32_fd_is_text(fptr->
fd))
return O_BINARY;
708 return setmode(fptr->
fd, O_BINARY);
710 flush_before_seek(fptr);
711 return setmode(fptr->
fd, O_BINARY);
713#define SET_BINARY_MODE_WITH_SEEK_CUR(fptr) set_binary_mode_with_seek_cur(fptr)
717# define DEFAULT_TEXTMODE 0
718#define NEED_READCONV(fptr) ((fptr)->encs.enc2 != NULL || NEED_NEWLINE_DECORATOR_ON_READ(fptr))
719#define NEED_WRITECONV(fptr) ( \
720 ((fptr)->encs.enc != NULL && (fptr)->encs.enc != rb_ascii8bit_encoding()) || \
721 NEED_NEWLINE_DECORATOR_ON_WRITE(fptr) || \
722 ((fptr)->encs.ecflags & (ECONV_DECORATOR_MASK|ECONV_STATEFUL_DECORATOR_MASK)) || \
724#define SET_BINARY_MODE(fptr) (void)(fptr)
725#define NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr) (void)(fptr)
726#define SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags) ((void)(enc2), (void)(ecflags))
727#define SET_BINARY_MODE_WITH_SEEK_CUR(fptr) (void)(fptr)
730#if !defined HAVE_SHUTDOWN && !defined shutdown
731#define shutdown(a,b) 0
735#define is_socket(fd, path) rb_w32_is_socket(fd)
736#elif !defined(S_ISSOCK)
737#define is_socket(fd, path) 0
740is_socket(
int fd,
VALUE path)
743 if (fstat(fd, &sbuf) < 0)
744 rb_sys_fail_path(path);
745 return S_ISSOCK(sbuf.st_mode);
749static const char closed_stream[] =
"closed stream";
752io_fd_check_closed(
int fd)
785 io_fd_check_closed(fptr->
fd);
789rb_io_get_fptr(
VALUE io)
799 return rb_convert_type_with_id(io,
T_FILE,
"IO", idTo_io);
805 return rb_check_convert_type_with_id(io,
T_FILE,
"IO", idTo_io);
823 rb_io_t *fptr = rb_io_get_fptr(io);
832 return write_io ? write_io :
Qnil;
845 rb_io_t *fptr = rb_io_get_fptr(self);
872 if (
RTEST(timeout)) {
876 rb_io_t *fptr = rb_io_get_fptr(self);
901#if !RUBY_CRLF_ENVIRONMENT
911 r = lseek(fptr->
fd, -fptr->
rbuf.
len, SEEK_CUR);
912 if (r < 0 && errno) {
931 const int min_capa = IO_RBUF_CAPA_FOR(fptr);
934#if SIZEOF_LONG > SIZEOF_INT
959flush_before_seek(
rb_io_t *fptr)
961 if (io_fflush(fptr) < 0)
962 rb_sys_fail_on_write(fptr);
968#define io_seek(fptr, ofs, whence) (errno = 0, lseek(flush_before_seek(fptr)->fd, (ofs), (whence)))
969#define io_tell(fptr) lseek(flush_before_seek(fptr)->fd, 0, SEEK_CUR)
985 if (io_fflush(fptr) < 0)
986 rb_sys_fail_on_write(fptr);
991 if (io_fflush(wfptr) < 0)
992 rb_sys_fail_on_write(wfptr);
1000 if (READ_CHAR_PENDING(fptr)) {
1012io_read_encoding(
rb_io_t *fptr)
1017 return rb_default_external_encoding();
1021io_input_encoding(
rb_io_t *fptr)
1026 return io_read_encoding(fptr);
1042rb_io_read_pending(
rb_io_t *fptr)
1045 if (READ_CHAR_PENDING(fptr))
1047 return READ_DATA_PENDING(fptr);
1053 if (!READ_DATA_PENDING(fptr)) {
1060rb_gc_for_fd(
int err)
1062 if (err == EMFILE || err == ENFILE || err == ENOMEM) {
1077 if (rb_gc_for_fd(e)) {
1089io_alloc(
VALUE klass)
1099# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
1125struct io_internal_writev_struct {
1132 const struct iovec *iov;
1145io_internal_wait(
VALUE thread,
rb_io_t *fptr,
int error,
int events,
struct timeval *timeout)
1147 int ready = nogvl_wait_for(thread, fptr, events, timeout);
1151 }
else if (ready == 0) {
1161internal_read_func(
void *ptr)
1166 if (iis->timeout && !iis->nonblock) {
1167 if (io_internal_wait(iis->th, iis->fptr, 0, RB_WAITFD_IN, iis->timeout) == -1) {
1173 result = read(iis->fd, iis->buf, iis->capa);
1175 if (result < 0 && !iis->nonblock) {
1176 if (io_again_p(errno)) {
1177 if (io_internal_wait(iis->th, iis->fptr, errno, RB_WAITFD_IN, iis->timeout) == -1) {
1188#if defined __APPLE__
1189# define do_write_retry(code) do {result = code;} while (result == -1 && errno == EPROTOTYPE)
1191# define do_write_retry(code) result = code
1195internal_write_func(
void *ptr)
1200 if (iis->timeout && !iis->nonblock) {
1201 if (io_internal_wait(iis->th, iis->fptr, 0, RB_WAITFD_OUT, iis->timeout) == -1) {
1207 do_write_retry(write(iis->fd, iis->buf, iis->capa));
1209 if (result < 0 && !iis->nonblock) {
1211 if (io_again_p(e)) {
1212 if (io_internal_wait(iis->th, iis->fptr, errno, RB_WAITFD_OUT, iis->timeout) == -1) {
1225internal_writev_func(
void *ptr)
1227 struct io_internal_writev_struct *iis = ptr;
1230 if (iis->timeout && !iis->nonblock) {
1231 if (io_internal_wait(iis->th, iis->fptr, 0, RB_WAITFD_OUT, iis->timeout) == -1) {
1237 do_write_retry(writev(iis->fd, iis->iov, iis->iovcnt));
1239 if (result < 0 && !iis->nonblock) {
1240 if (io_again_p(errno)) {
1241 if (io_internal_wait(iis->th, iis->fptr, errno, RB_WAITFD_OUT, iis->timeout) == -1) {
1254rb_io_read_memory(
rb_io_t *fptr,
void *buf,
size_t count)
1257 if (scheduler !=
Qnil) {
1260 if (!UNDEF_P(result)) {
1276 struct timeval timeout_storage;
1280 iis.timeout = &timeout_storage;
1283 return (ssize_t)rb_thread_io_blocking_region(internal_read_func, &iis, fptr->
fd);
1287rb_io_write_memory(
rb_io_t *fptr,
const void *buf,
size_t count)
1290 if (scheduler !=
Qnil) {
1293 if (!UNDEF_P(result)) {
1309 struct timeval timeout_storage;
1313 iis.timeout = &timeout_storage;
1316 return (ssize_t)rb_thread_io_blocking_region(internal_write_func, &iis, fptr->
fd);
1321rb_writev_internal(
rb_io_t *fptr,
const struct iovec *iov,
int iovcnt)
1323 if (!iovcnt)
return 0;
1326 if (scheduler !=
Qnil) {
1330 if (!UNDEF_P(result)) {
1335 struct io_internal_writev_struct iis = {
1346 struct timeval timeout_storage;
1350 iis.timeout = &timeout_storage;
1353 return (ssize_t)rb_thread_io_blocking_region(internal_writev_func, &iis, fptr->
fd);
1358io_flush_buffer_sync(
void *arg)
1380io_flush_buffer_async(
VALUE arg)
1383 return rb_thread_io_blocking_region(io_flush_buffer_sync, fptr, fptr->
fd);
1390 return (
int)io_flush_buffer_async((
VALUE)fptr);
1405 while (fptr->
wbuf.
len > 0 && io_flush_buffer(fptr) != 0) {
1420 if (scheduler !=
Qnil) {
1430 if (NIL_OR_UNDEF_P(timeout)) {
1434 if (timeout !=
Qnil) {
1439 int ready = rb_thread_wait_for_single_fd(fptr->
fd,
RB_NUM2INT(events), tv);
1459 return prep_io(fd, FMODE_PREP,
rb_cIO, NULL);
1463io_wait_for_single_fd(
int fd,
int events,
struct timeval *timeout)
1467 if (scheduler !=
Qnil) {
1473 return rb_thread_wait_for_single_fd(fd, events, timeout);
1479 io_fd_check_closed(f);
1485#if defined(ERESTART)
1492#if EWOULDBLOCK != EAGAIN
1495 if (scheduler !=
Qnil) {
1513 io_fd_check_closed(f);
1519#if defined(ERESTART)
1535#if EWOULDBLOCK != EAGAIN
1538 if (scheduler !=
Qnil) {
1556 return io_wait_for_single_fd(fd, events, timeout);
1590#if defined(ERESTART)
1600#if EWOULDBLOCK != EAGAIN
1617 if (
RTEST(result)) {
1630 if (
RTEST(result)) {
1642 const char *senc, *denc;
1649 ecflags = fptr->
encs.
ecflags & ~ECONV_NEWLINE_DECORATOR_READ_MASK;
1709io_binwrite_string_internal(
rb_io_t *fptr,
const char *ptr,
long length)
1712 struct iovec iov[2];
1715 iov[0].iov_len = fptr->
wbuf.
len;
1716 iov[1].iov_base = (
void*)ptr;
1717 iov[1].iov_len = length;
1719 ssize_t result = rb_writev_internal(fptr, iov, 2);
1724 if (result >= fptr->
wbuf.
len) {
1732 fptr->
wbuf.
off += (int)result;
1733 fptr->
wbuf.
len -= (int)result;
1741 return rb_io_write_memory(fptr, ptr, length);
1746io_binwrite_string_internal(
rb_io_t *fptr,
const char *ptr,
long length)
1748 long remaining = length;
1751 if (fptr->
wbuf.
len+length <= fptr->wbuf.capa) {
1758 fptr->
wbuf.
len += (int)length;
1765 if (io_fflush(fptr) < 0) {
1770 if (remaining == 0) {
1776 return rb_io_write_memory(fptr, ptr, length);
1781io_binwrite_string(
VALUE arg)
1785 const char *ptr = p->ptr;
1786 size_t remaining = p->length;
1790 ssize_t result = io_binwrite_string_internal(p->fptr, ptr, remaining);
1796 else if (result > 0) {
1797 if ((
size_t)result == remaining)
break;
1799 remaining -= result;
1815io_allocate_write_buffer(
rb_io_t *fptr,
int sync)
1820 fptr->
wbuf.
capa = IO_WBUF_CAPA_MIN;
1831io_binwrite_requires_flush_write(
rb_io_t *fptr,
long len,
int nosync)
1846io_binwrite(
VALUE str,
const char *ptr,
long len,
rb_io_t *fptr,
int nosync)
1848 if (len <= 0)
return len;
1853 io_allocate_write_buffer(fptr, !nosync);
1855 if (io_binwrite_requires_flush_write(fptr, len, nosync)) {
1867 return io_binwrite_string((
VALUE)&arg);
1884# define MODE_BTMODE(a,b,c) ((fmode & FMODE_BINMODE) ? (b) : \
1885 (fmode & FMODE_TEXTMODE) ? (c) : (a))
1887#define MODE_BTXMODE(a, b, c, d, e, f) ((fmode & FMODE_EXCL) ? \
1888 MODE_BTMODE(d, e, f) : \
1889 MODE_BTMODE(a, b, c))
1894 if (NEED_WRITECONV(fptr)) {
1896 SET_BINARY_MODE(fptr);
1898 make_writeconv(fptr);
1901#define fmode (fptr->mode)
1904 else if (MODE_BTMODE(DEFAULT_TEXTMODE,0,1) && !
rb_enc_asciicompat(rb_enc_get(str))) {
1905 rb_raise(
rb_eArgError,
"ASCII incompatible string written for text mode IO without encoding conversion: %s",
1912 common_encoding = rb_enc_from_encoding(fptr->
encs.
enc2);
1913 else if (fptr->
encs.
enc != rb_ascii8bit_encoding())
1914 common_encoding = rb_enc_from_encoding(fptr->
encs.
enc);
1917 if (!
NIL_P(common_encoding)) {
1928#if RUBY_CRLF_ENVIRONMENT
1929#define fmode (fptr->mode)
1930 else if (MODE_BTMODE(DEFAULT_TEXTMODE,0,1)) {
1933 setmode(fptr->
fd, O_BINARY);
1936 setmode(fptr->
fd, O_TEXT);
1939 rb_raise(
rb_eArgError,
"ASCII incompatible string written for text mode IO without encoding conversion: %s",
1958 long len = rb_w32_write_console(str, fptr->
fd);
1959 if (len > 0)
return len;
1963 str = do_writeconv(str, fptr, &converted);
1967 tmp = rb_str_tmp_frozen_acquire(str);
1969 n = io_binwrite(tmp, ptr, len, fptr, nosync);
1970 rb_str_tmp_frozen_release(str, tmp);
1982 return (ssize_t)io_binwrite(0, buf, (
long)size, fptr, 0);
1992 io = GetWriteIO(io);
2007 n = io_fwrite(str, fptr, nosync);
2008 if (n < 0L) rb_sys_fail_on_write(fptr);
2014struct binwritev_arg {
2022io_binwritev_internal(
VALUE arg)
2024 struct binwritev_arg *p = (
struct binwritev_arg *)arg;
2026 size_t remaining = p->total;
2030 struct iovec *iov = p->iov;
2031 int iovcnt = p->iovcnt;
2034 long result = rb_writev_internal(fptr, iov, iovcnt);
2039 if (offset < (
size_t)fptr->
wbuf.
len) {
2044 offset -= (size_t)fptr->
wbuf.
len;
2050 if (offset == p->total) {
2054 while (result >= (ssize_t)iov->iov_len) {
2056 result -= iov->iov_len;
2066 iov->iov_base = (
char *)iov->iov_base + result;
2067 iov->iov_len -= result;
2081io_binwritev(
struct iovec *iov,
int iovcnt,
rb_io_t *fptr)
2086 if (iovcnt == 0)
return 0;
2089 for (
int i = 1; i < iovcnt; i++) total += iov[i].iov_len;
2091 io_allocate_write_buffer(fptr, 1);
2097 if (offset + total <= (
size_t)fptr->
wbuf.
capa) {
2098 for (
int i = 1; i < iovcnt; i++) {
2099 memcpy(fptr->
wbuf.
ptr+offset, iov[i].iov_base, iov[i].iov_len);
2100 offset += iov[i].iov_len;
2109 iov[0].iov_len = fptr->
wbuf.
len;
2122 struct binwritev_arg arg;
2125 arg.iovcnt = iovcnt;
2132 return io_binwritev_internal((
VALUE)&arg);
2139 int i, converted, iovcnt = argc + 1;
2141 VALUE v1, v2, str, tmp, *tmp_array;
2147 for (i = 0; i < argc; i++) {
2150 str = do_writeconv(str, fptr, &converted);
2155 tmp = rb_str_tmp_frozen_acquire(str);
2163 n = io_binwritev(iov, iovcnt, fptr);
2166 for (i = 0; i < argc; i++) {
2167 rb_str_tmp_frozen_release(argv[i], tmp_array[i]);
2176iovcnt_ok(
int iovcnt)
2179 return iovcnt < IOV_MAX;
2187io_writev(
int argc,
const VALUE *argv,
VALUE io)
2194 io = GetWriteIO(io);
2199 return rb_funcallv(io, id_write, argc, argv);
2207 for (i = 0; i < argc; i += cnt) {
2210 n = io_fwritev(cnt, &argv[i], fptr);
2221 rb_sys_fail_on_write(fptr);
2223 total = rb_fix_plus(
LONG2FIX(n), total);
2254 return io_writev(argc, argv, io);
2257 VALUE str = argv[0];
2258 return io_write(io, str, 0);
2265 return rb_funcallv(io, id_write, 1, &str);
2269rb_io_writev(
VALUE io,
int argc,
const VALUE *argv)
2277 " which accepts just one argument",
2287 return rb_funcallv(io, id_write, argc, argv);
2319nogvl_fsync(
void *ptr)
2324 if (GetFileType((HANDLE)rb_w32_get_osfhandle(fptr->
fd)) != FILE_TYPE_DISK)
2327 return (
VALUE)fsync(fptr->
fd);
2332rb_io_flush_raw(
VALUE io,
int sync)
2340 io = GetWriteIO(io);
2344 if (io_fflush(fptr) < 0)
2345 rb_sys_fail_on_write(fptr);
2369 return rb_io_flush_raw(io, 1);
2398 pos = io_tell(fptr);
2399 if (pos < 0 && errno) rb_sys_fail_path(fptr->
pathv);
2405rb_io_seek(
VALUE io,
VALUE offset,
int whence)
2412 pos = io_seek(fptr, pos, whence);
2413 if (pos < 0 && errno) rb_sys_fail_path(fptr->
pathv);
2419interpret_seek_whence(
VALUE vwhence)
2421 if (vwhence == sym_SET)
2423 if (vwhence == sym_CUR)
2425 if (vwhence == sym_END)
2428 if (vwhence == sym_DATA)
2432 if (vwhence == sym_HOLE)
2488 VALUE offset, ptrname;
2489 int whence = SEEK_SET;
2491 if (
rb_scan_args(argc, argv,
"11", &offset, &ptrname) == 2) {
2492 whence = interpret_seek_whence(ptrname);
2495 return rb_io_seek(io, offset, whence);
2523 pos = io_seek(fptr, pos, SEEK_SET);
2524 if (pos < 0 && errno) rb_sys_fail_path(fptr->
pathv);
2529static void clear_readconv(
rb_io_t *fptr);
2556rb_io_rewind(
VALUE io)
2561 if (io_seek(fptr, 0L, 0) < 0 && errno) rb_sys_fail_path(fptr->
pathv);
2562 if (io == ARGF.current_file) {
2563 ARGF.lineno -= fptr->
lineno;
2567 clear_readconv(fptr);
2574fptr_wait_readable(
rb_io_t *fptr)
2592 fptr->
rbuf.
capa = IO_RBUF_CAPA_FOR(fptr);
2603 if (fptr_wait_readable(fptr))
2612 rb_syserr_fail_path(e, path);
2669 if (READ_CHAR_PENDING(fptr))
return Qfalse;
2670 if (READ_DATA_PENDING(fptr))
return Qfalse;
2672#if RUBY_CRLF_ENVIRONMENT
2673 if (!NEED_READCONV(fptr) && NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {
2674 return RBOOL(eof(fptr->
fd));;
2677 return RBOOL(io_fillbuf(fptr) < 0);
2701 io = GetWriteIO(io);
2738 io = GetWriteIO(io);
2744 fptr->
mode &= ~FMODE_SYNC;
2768rb_io_fsync(
VALUE io)
2772 io = GetWriteIO(io);
2775 if (io_fflush(fptr) < 0)
2776 rb_sys_fail_on_write(fptr);
2777 if ((
int)rb_thread_io_blocking_region(nogvl_fsync, fptr, fptr->
fd) < 0)
2778 rb_sys_fail_path(fptr->
pathv);
2782# define rb_io_fsync rb_f_notimplement
2783# define rb_io_sync rb_f_notimplement
2792#ifdef HAVE_FDATASYNC
2794nogvl_fdatasync(
void *ptr)
2799 if (GetFileType((HANDLE)rb_w32_get_osfhandle(fptr->
fd)) != FILE_TYPE_DISK)
2802 return (
VALUE)fdatasync(fptr->
fd);
2817rb_io_fdatasync(
VALUE io)
2821 io = GetWriteIO(io);
2824 if (io_fflush(fptr) < 0)
2825 rb_sys_fail_on_write(fptr);
2827 if ((
int)rb_thread_io_blocking_region(nogvl_fdatasync, fptr, fptr->
fd) == 0)
2831 return rb_io_fsync(io);
2834#define rb_io_fdatasync rb_io_fsync
2854rb_io_fileno(
VALUE io)
2947rb_io_inspect(
VALUE obj)
2951 static const char closed[] =
" (closed)";
2953 fptr =
RFILE(obj)->fptr;
2960 rb_str_cat(result, closed+1, strlen(closed)-1);
2984rb_io_to_io(
VALUE io)
2991read_buffered_data(
char *ptr,
long len,
rb_io_t *fptr)
2995 n = READ_DATA_PENDING_COUNT(fptr);
2996 if (n <= 0)
return 0;
2997 if (n > len) n = (int)len;
3005io_bufread(
char *ptr,
long len,
rb_io_t *fptr)
3011 if (READ_DATA_PENDING(fptr) == 0) {
3015 c = rb_io_read_memory(fptr, ptr+offset, n);
3018 if (fptr_wait_readable(fptr))
3023 if ((n -= c) <= 0)
break;
3029 c = read_buffered_data(ptr+offset, n, fptr);
3032 if ((n -= c) <= 0)
break;
3035 if (io_fillbuf(fptr) < 0) {
3042static int io_setstrbuf(
VALUE *str,
long len);
3051bufread_call(
VALUE arg)
3054 p->len = io_bufread(p->str_ptr, p->len, p->fptr);
3059io_fread(
VALUE str,
long offset,
long size,
rb_io_t *fptr)
3064 io_setstrbuf(&str, offset + size);
3068 rb_str_locktmp_ensure(str, bufread_call, (
VALUE)&arg);
3070 if (len < 0) rb_sys_fail_path(fptr->
pathv);
3078 rb_off_t siz = READ_DATA_PENDING_COUNT(fptr);
3081 if (fstat(fptr->
fd, &st) == 0 && S_ISREG(st.st_mode)
3082#
if defined(__HAIKU__)
3087 if (io_fflush(fptr) < 0)
3088 rb_sys_fail_on_write(fptr);
3089 pos = lseek(fptr->
fd, 0, SEEK_CUR);
3090 if (st.st_size >= pos && pos >= 0) {
3091 siz += st.st_size - pos;
3092 if (siz > LONG_MAX) {
3106 rb_enc_associate(str, io_read_encoding(fptr));
3113make_readconv(
rb_io_t *fptr,
int size)
3118 const char *sname, *dname;
3119 ecflags = fptr->
encs.
ecflags & ~ECONV_NEWLINE_DECORATOR_WRITE_MASK;
3133 if (size < IO_CBUF_CAPA_MIN) size = IO_CBUF_CAPA_MIN;
3139#define MORE_CHAR_SUSPENDED Qtrue
3140#define MORE_CHAR_FINISHED Qnil
3142fill_cbuf(
rb_io_t *fptr,
int ec_flags)
3144 const unsigned char *ss, *sp, *se;
3145 unsigned char *ds, *dp, *de;
3154 return MORE_CHAR_SUSPENDED;
3165 ss = sp = (
const unsigned char *)fptr->
rbuf.
ptr + fptr->
rbuf.
off;
3170 fptr->
rbuf.
off += (int)(sp - ss);
3171 fptr->
rbuf.
len -= (int)(sp - ss);
3172 fptr->
cbuf.
len += (int)(dp - ds);
3177 fptr->
rbuf.
off -= putbackable;
3178 fptr->
rbuf.
len += putbackable;
3185 if (cbuf_len0 != fptr->
cbuf.
len)
3186 return MORE_CHAR_SUSPENDED;
3189 return MORE_CHAR_FINISHED;
3195 if (io_fillbuf(fptr) < 0) {
3197 return MORE_CHAR_FINISHED;
3202 fptr->
cbuf.
len += (int)(dp - ds);
3209 if (cbuf_len0 != fptr->
cbuf.
len)
3210 return MORE_CHAR_SUSPENDED;
3212 return MORE_CHAR_FINISHED;
3220 if (v != MORE_CHAR_SUSPENDED && v != MORE_CHAR_FINISHED)
3237 rb_enc_associate(str, fptr->
encs.
enc);
3252io_setstrbuf(
VALUE *str,
long len)
3256 len = (len + 1) & ~1L;
3277#define MAX_REALLOC_GAP 4096
3279io_shrink_read_string(
VALUE str,
long n)
3287io_set_read_length(
VALUE str,
long n,
int shrinkable)
3292 if (shrinkable) io_shrink_read_string(str, n);
3306 if (NEED_READCONV(fptr)) {
3307 int first = !
NIL_P(str);
3308 SET_BINARY_MODE(fptr);
3309 shrinkable = io_setstrbuf(&str,0);
3310 make_readconv(fptr, 0);
3315 io_shift_cbuf(fptr, fptr->
cbuf.
len, &str);
3317 v = fill_cbuf(fptr, 0);
3318 if (v != MORE_CHAR_SUSPENDED && v != MORE_CHAR_FINISHED) {
3321 io_shift_cbuf(fptr, fptr->
cbuf.
len, &str);
3325 if (v == MORE_CHAR_FINISHED) {
3326 clear_readconv(fptr);
3328 if (shrinkable) io_shrink_read_string(str,
RSTRING_LEN(str));
3329 return io_enc_str(str, fptr);
3334 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
3338 enc = io_read_encoding(fptr);
3341 if (siz == 0) siz = BUFSIZ;
3342 shrinkable = io_setstrbuf(&str, siz);
3345 n = io_fread(str, bytes, siz - bytes, fptr);
3346 if (n == 0 && bytes == 0) {
3354 if (bytes < siz)
break;
3359 if (capa < BUFSIZ) {
3362 else if (capa > IO_MAX_BUFFER_GROWTH) {
3363 capa = IO_MAX_BUFFER_GROWTH;
3368 if (shrinkable) io_shrink_read_string(str,
RSTRING_LEN(str));
3369 str = io_enc_str(str, fptr);
3377 if (rb_fd_set_nonblock(fptr->
fd) != 0) {
3378 rb_sys_fail_path(fptr->
pathv);
3383io_read_memory_call(
VALUE arg)
3388 if (scheduler !=
Qnil) {
3391 if (!UNDEF_P(result)) {
3397 return rb_thread_io_blocking_region(internal_read_func, iis, iis->fptr->
fd);
3403 return (
long)rb_str_locktmp_ensure(str, io_read_memory_call, (
VALUE)iis);
3406#define no_exception_p(opts) !rb_opts_exception_p((opts), TRUE)
3409io_getpartial(
int argc,
VALUE *argv,
VALUE io,
int no_exception,
int nonblock)
3419 if ((len =
NUM2LONG(length)) < 0) {
3423 shrinkable = io_setstrbuf(&str, len);
3429 io_set_read_length(str, 0, shrinkable);
3435 n = read_buffered_data(
RSTRING_PTR(str), len, fptr);
3441 io_setstrbuf(&str, len);
3444 iis.nonblock = nonblock;
3449 n = io_read_memory_locktmp(str, &iis);
3452 if (!nonblock && fptr_wait_readable(fptr))
3454 if (nonblock && (io_again_p(e))) {
3456 return sym_wait_readable;
3459 e,
"read would block");
3461 rb_syserr_fail_path(e, fptr->
pathv);
3464 io_set_read_length(str, n, shrinkable);
3565io_readpartial(
int argc,
VALUE *argv,
VALUE io)
3569 ret = io_getpartial(argc, argv, io,
Qnil, 0);
3576io_nonblock_eof(
int no_exception)
3578 if (!no_exception) {
3593 if ((len =
NUM2LONG(length)) < 0) {
3597 shrinkable = io_setstrbuf(&str, len);
3598 rb_bool_expected(ex,
"exception", TRUE);
3604 io_set_read_length(str, 0, shrinkable);
3608 n = read_buffered_data(
RSTRING_PTR(str), len, fptr);
3610 rb_fd_set_nonblock(fptr->
fd);
3611 shrinkable |= io_setstrbuf(&str, len);
3618 n = io_read_memory_locktmp(str, &iis);
3621 if (io_again_p(e)) {
3622 if (!ex)
return sym_wait_readable;
3624 e,
"read would block");
3626 rb_syserr_fail_path(e, fptr->
pathv);
3629 io_set_read_length(str, n, shrinkable);
3632 if (!ex)
return Qnil;
3648 rb_bool_expected(ex,
"exception", TRUE);
3650 io = GetWriteIO(io);
3654 if (io_fflush(fptr) < 0)
3655 rb_sys_fail_on_write(fptr);
3657 rb_fd_set_nonblock(fptr->
fd);
3663 if (io_again_p(e)) {
3665 return sym_wait_writable;
3671 rb_syserr_fail_path(e, fptr->
pathv);
3755#if RUBY_CRLF_ENVIRONMENT
3761 if (
NIL_P(length)) {
3764 return read_all(fptr, remain_size(fptr), str);
3771 shrinkable = io_setstrbuf(&str,len);
3776 io_set_read_length(str, 0, shrinkable);
3781#if RUBY_CRLF_ENVIRONMENT
3782 previous_mode = set_binary_mode_with_seek_cur(fptr);
3784 n = io_fread(str, 0, len, fptr);
3785 io_set_read_length(str, n, shrinkable);
3786#if RUBY_CRLF_ENVIRONMENT
3787 if (previous_mode == O_TEXT) {
3788 setmode(fptr->
fd, O_TEXT);
3791 if (n == 0)
return Qnil;
3797rscheck(
const char *rsptr,
long rslen,
VALUE rs)
3805appendline(
rb_io_t *fptr,
int delim,
VALUE *strp,
long *lp)
3810 if (NEED_READCONV(fptr)) {
3811 SET_BINARY_MODE(fptr);
3812 make_readconv(fptr, 0);
3815 int searchlen = READ_CHAR_PENDING_COUNT(fptr);
3817 p = READ_CHAR_PENDING_PTR(fptr);
3818 if (0 < limit && limit < searchlen)
3819 searchlen = (int)limit;
3820 e = memchr(p, delim, searchlen);
3822 int len = (int)(e-p+1);
3847 }
while (more_char(fptr) != MORE_CHAR_FINISHED);
3848 clear_readconv(fptr);
3853 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
3855 long pending = READ_DATA_PENDING_COUNT(fptr);
3857 const char *p = READ_DATA_PENDING_PTR(fptr);
3861 if (limit > 0 && pending > limit) pending = limit;
3862 e = memchr(p, delim, pending);
3863 if (e) pending = e - p + 1;
3873 read_buffered_data(
RSTRING_PTR(str) + last, pending, fptr);
3876 if (e)
return delim;
3881 }
while (io_fillbuf(fptr) >= 0);
3887swallow(
rb_io_t *fptr,
int term)
3889 if (NEED_READCONV(fptr)) {
3892 SET_BINARY_MODE(fptr);
3893 make_readconv(fptr, 0);
3896 while ((cnt = READ_CHAR_PENDING_COUNT(fptr)) > 0) {
3897 const char *p = READ_CHAR_PENDING_PTR(fptr);
3900 if (*p != term)
return TRUE;
3902 while (--i && *++p == term);
3905 const char *e = p + cnt;
3906 if (rb_enc_ascget(p, e, &i, enc) != term)
return TRUE;
3907 while ((p += i) < e && rb_enc_ascget(p, e, &i, enc) == term);
3910 io_shift_cbuf(fptr, (
int)cnt - i, NULL);
3912 }
while (more_char(fptr) != MORE_CHAR_FINISHED);
3916 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
3919 while ((cnt = READ_DATA_PENDING_COUNT(fptr)) > 0) {
3921 const char *p = READ_DATA_PENDING_PTR(fptr);
3923 if (cnt >
sizeof buf) cnt =
sizeof buf;
3924 if (*p != term)
return TRUE;
3926 while (--i && *++p == term);
3927 if (!read_buffered_data(buf, cnt - i, fptr))
3928 rb_sys_fail_path(fptr->
pathv);
3931 }
while (io_fillbuf(fptr) == 0);
3944 int pending = READ_DATA_PENDING_COUNT(fptr);
3947 const char *p = READ_DATA_PENDING_PTR(fptr);
3951 e = memchr(p,
'\n', pending);
3953 pending = (int)(e - p + 1);
3955 chomplen = (pending > 1 && *(e-1) ==
'\r') + 1;
3965 read_buffered_data(
RSTRING_PTR(str)+len, pending - chomplen, fptr);
3968 if (pending == 1 && chomplen == 1 && len > 0) {
3975 len += pending - chomplen;
3981 }
while (io_fillbuf(fptr) >= 0);
3984 str = io_enc_str(str, fptr);
3995 unsigned int chomp: 1;
4009 chomp = (!UNDEF_P(vchomp)) &&
RTEST(vchomp);
4011 args->chomp = chomp;
4029 else if (2 <= argc) {
4030 rs = argv[0], lim = argv[1];
4039check_getline_args(
VALUE *rsp,
long *limit,
VALUE io)
4048 enc_rs = rb_enc_get(rs);
4049 enc_io = io_read_encoding(fptr);
4050 if (enc_io != enc_rs &&
4051 (!is_ascii_string(rs) ||
4053 if (rs == rb_default_rs) {
4071 argc =
rb_scan_args(argc, argv,
"02:", NULL, NULL, &opts);
4072 extract_getline_args(argc, argv, args);
4073 extract_getline_opts(opts, args);
4074 check_getline_args(&args->rs, &args->limit, io);
4078rb_io_getline_0(
VALUE rs,
long limit,
int chomp,
rb_io_t *fptr)
4085 if (
NIL_P(rs) && limit < 0) {
4086 str = read_all(fptr, 0,
Qnil);
4089 else if (limit == 0) {
4092 else if (rs == rb_default_rs && limit < 0 && !NEED_READCONV(fptr) &&
4094 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
4095 return rb_io_getline_fast(fptr, enc, chomp);
4098 int c, newline = -1;
4099 const char *rsptr = 0;
4102 int extra_limit = 16;
4103 int chomp_cr = chomp;
4105 SET_BINARY_MODE(fptr);
4106 enc = io_read_encoding(fptr);
4114 swallow(fptr,
'\n');
4127 newline = (
unsigned char)rsptr[rslen - 1];
4128 chomp_cr = chomp && rslen == 1 && newline ==
'\n';
4132 while ((c = appendline(fptr, newline, &str, &limit)) != EOF) {
4133 const char *s, *p, *pp, *e;
4141 if (pp != p)
continue;
4142 if (!rspara) rscheck(rsptr, rslen, rs);
4143 if (memcmp(p, rsptr, rslen) == 0) {
4145 if (chomp_cr && p > s && *(p-1) ==
'\r') --p;
4169 if (rspara && c != EOF)
4170 swallow(fptr,
'\n');
4172 str = io_enc_str(str, fptr);
4175 if (!
NIL_P(str) && !nolimit) {
4183rb_io_getline_1(
VALUE rs,
long limit,
int chomp,
VALUE io)
4186 int old_lineno, new_lineno;
4190 old_lineno = fptr->
lineno;
4191 str = rb_io_getline_0(rs, limit, chomp, fptr);
4192 if (!
NIL_P(str) && (new_lineno = fptr->
lineno) != old_lineno) {
4193 if (io == ARGF.current_file) {
4194 ARGF.lineno += new_lineno - old_lineno;
4195 ARGF.last_lineno = ARGF.lineno;
4198 ARGF.last_lineno = new_lineno;
4206rb_io_getline(
int argc,
VALUE *argv,
VALUE io)
4210 prepare_getline_args(argc, argv, &args, io);
4211 return rb_io_getline_1(args.rs, args.limit, args.chomp, io);
4221rb_io_gets_internal(
VALUE io)
4225 return rb_io_getline_0(rb_default_rs, -1, FALSE, fptr);
4308 str = rb_io_getline(argc, argv, io);
4324rb_io_lineno(
VALUE io)
4366rb_io_readline(
int argc,
VALUE *argv,
VALUE io)
4368 VALUE line = rb_io_gets_m(argc, argv, io);
4445rb_io_readlines(
int argc,
VALUE *argv,
VALUE io)
4449 prepare_getline_args(argc, argv, &args, io);
4450 return io_readlines(&args, io);
4458 if (arg->limit == 0)
4461 while (!
NIL_P(line = rb_io_getline_1(arg->rs, arg->limit, arg->chomp, io))) {
4462 rb_ary_push(ary, line);
4579rb_io_each_line(
int argc,
VALUE *argv,
VALUE io)
4585 prepare_getline_args(argc, argv, &args, io);
4586 if (args.limit == 0)
4588 while (!
NIL_P(str = rb_io_getline_1(args.rs, args.limit, args.chomp, io))) {
4615rb_io_each_byte(
VALUE io)
4631 }
while (io_fillbuf(fptr) >= 0);
4641 if (NEED_READCONV(fptr)) {
4645 SET_BINARY_MODE(fptr);
4646 make_readconv(fptr, 0);
4660 if (more_char(fptr) == MORE_CHAR_FINISHED) {
4662 clear_readconv(fptr);
4669 if (fptr->
cbuf.
len == 0) clear_readconv(fptr);
4678 io_shift_cbuf(fptr, r, &str);
4689 str = io_enc_str(str, fptr);
4694 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
4695 if (io_fillbuf(fptr) < 0) {
4717 if (io_fillbuf(fptr) != -1) {
4737 str = io_enc_str(str, fptr);
4763rb_io_each_char(
VALUE io)
4773 enc = io_input_encoding(fptr);
4775 while (!
NIL_P(c = io_getc(fptr, enc))) {
4801rb_io_each_codepoint(
VALUE io)
4813 if (NEED_READCONV(fptr)) {
4814 SET_BINARY_MODE(fptr);
4817 make_readconv(fptr, 0);
4825 r = ONIGENC_CONSTRUCT_MBCLEN_CHARFOUND(1);
4832 if (more_char(fptr) == MORE_CHAR_FINISHED) {
4833 clear_readconv(fptr);
4860 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
4861 enc = io_input_encoding(fptr);
4862 while (io_fillbuf(fptr) >= 0) {
4877 char cbuf[8], *p = cbuf;
4879 if (more > numberof(cbuf))
goto invalid;
4881 if (more > numberof(cbuf))
goto invalid;
4882 while ((n = (
int)read_buffered_data(p, more, fptr)) > 0 &&
4883 (p += n, (more -= n) > 0)) {
4884 if (io_fillbuf(fptr) < 0)
goto invalid;
4885 if ((n = fptr->
rbuf.
len) > more) n = more;
4887 r = rb_enc_precise_mbclen(cbuf, p, enc);
4932 enc = io_input_encoding(fptr);
4934 return io_getc(fptr, enc);
4957rb_io_readchar(
VALUE io)
4959 VALUE c = rb_io_getc(io);
5002 if (io_fillbuf(fptr) < 0) {
5031rb_io_readbyte(
VALUE io)
5092 unsigned char c =
NUM2INT(v) & 0xFF;
5098 io_ungetbyte(b, fptr);
5154 else if (RB_BIGNUM_TYPE_P(c)) {
5160 if (NEED_READCONV(fptr)) {
5161 SET_BINARY_MODE(fptr);
5163#if SIZEOF_LONG > SIZEOF_INT
5167 make_readconv(fptr, (
int)len);
5181 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
5182 io_ungetbyte(c, fptr);
5204rb_io_isatty(
VALUE io)
5209 return RBOOL(isatty(fptr->
fd) != 0);
5212#if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
5228rb_io_close_on_exec_p(
VALUE io)
5234 write_io = GetWriteIO(io);
5235 if (io != write_io) {
5237 if (fptr && 0 <= (fd = fptr->
fd)) {
5238 if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->
pathv);
5239 if (!(ret & FD_CLOEXEC))
return Qfalse;
5244 if (fptr && 0 <= (fd = fptr->
fd)) {
5245 if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->
pathv);
5246 if (!(ret & FD_CLOEXEC))
return Qfalse;
5251#define rb_io_close_on_exec_p rb_f_notimplement
5254#if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
5278 int flag =
RTEST(arg) ? FD_CLOEXEC : 0;
5283 write_io = GetWriteIO(io);
5284 if (io != write_io) {
5286 if (fptr && 0 <= (fd = fptr->
fd)) {
5287 if ((ret = fcntl(fptr->
fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->
pathv);
5288 if ((ret & FD_CLOEXEC) != flag) {
5289 ret = (ret & ~FD_CLOEXEC) | flag;
5290 ret = fcntl(fd, F_SETFD, ret);
5291 if (ret != 0) rb_sys_fail_path(fptr->
pathv);
5298 if (fptr && 0 <= (fd = fptr->
fd)) {
5299 if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->
pathv);
5300 if ((ret & FD_CLOEXEC) != flag) {
5301 ret = (ret & ~FD_CLOEXEC) | flag;
5302 ret = fcntl(fd, F_SETFD, ret);
5303 if (ret != 0) rb_sys_fail_path(fptr->
pathv);
5309#define rb_io_set_close_on_exec rb_f_notimplement
5312#define IS_PREP_STDIO(f) ((f)->mode & FMODE_PREP)
5313#define PREP_STDIO_NAME(f) (RSTRING_PTR((f)->pathv))
5316finish_writeconv(
rb_io_t *fptr,
int noalloc)
5318 unsigned char *ds, *dp, *de;
5322 unsigned char buf[1024];
5327 de = buf +
sizeof(buf);
5330 size_t remaining = dp-ds;
5331 long result = rb_io_write_memory(fptr, ds, remaining);
5335 if ((
size_t)result == remaining)
break;
5358 if (io_fflush(fptr) < 0) {
5366 fptr->
wbuf.
len += (int)(dp - ds);
5382finish_writeconv_sync(
VALUE arg)
5385 return finish_writeconv(p->fptr, p->noalloc);
5389nogvl_close(
void *ptr)
5393 return (
void*)(intptr_t)close(*fd);
5397maygvl_close(
int fd,
int keepgvl)
5410nogvl_fclose(
void *ptr)
5414 return (
void*)(intptr_t)fclose(file);
5418maygvl_fclose(
FILE *file,
int keepgvl)
5421 return fclose(file);
5427static void clear_codeconv(
rb_io_t *fptr);
5430fptr_finalize_flush(
rb_io_t *fptr,
int noraise,
int keepgvl,
5431 struct ccan_list_head *busy)
5436 int mode = fptr->
mode;
5442 arg.noalloc = noraise;
5446 error = finish_writeconv(fptr, noraise);
5451 io_flush_buffer_sync(fptr);
5454 if (io_fflush(fptr) < 0 &&
NIL_P(error)) {
5462 if (IS_PREP_STDIO(fptr) || fd <= 2) {
5486 if (!done && stdio_file) {
5488 if ((maygvl_fclose(stdio_file, noraise) < 0) &&
NIL_P(error)) {
5497 if (!done && fd >= 0) {
5503 if ((maygvl_close(fd, keepgvl) < 0) &&
NIL_P(error)) {
5512 if (!
NIL_P(error) && !noraise) {
5521fptr_finalize(
rb_io_t *fptr,
int noraise)
5523 fptr_finalize_flush(fptr, noraise, FALSE, 0);
5524 free_io_buffer(&fptr->
rbuf);
5525 free_io_buffer(&fptr->
wbuf);
5526 clear_codeconv(fptr);
5530rb_io_fptr_cleanup(
rb_io_t *fptr,
int noraise)
5536 fptr_finalize(fptr, noraise);
5544 ruby_sized_xfree(buf->
ptr, (
size_t)buf->
capa);
5556 free_io_buffer(&fptr->
cbuf);
5572 clear_readconv(fptr);
5573 clear_writeconv(fptr);
5577rb_io_fptr_finalize_internal(
void *ptr)
5584 rb_io_fptr_cleanup(fptr, TRUE);
5586 free_io_buffer(&fptr->
rbuf);
5587 free_io_buffer(&fptr->
wbuf);
5588 clear_codeconv(fptr);
5592#undef rb_io_fptr_finalize
5600 rb_io_fptr_finalize_internal(fptr);
5604#define rb_io_fptr_finalize(fptr) rb_io_fptr_finalize_internal(fptr)
5606RUBY_FUNC_EXPORTED
size_t
5607rb_io_memsize(
const rb_io_t *fptr)
5609 size_t size =
sizeof(
rb_io_t);
5620# define KEEPGVL TRUE
5622# define KEEPGVL FALSE
5625int rb_notify_fd_close(
int fd,
struct ccan_list_head *);
5627io_close_fptr(
VALUE io)
5632 struct ccan_list_head busy;
5634 ccan_list_head_init(&busy);
5635 write_io = GetWriteIO(io);
5636 if (io != write_io) {
5637 write_fptr =
RFILE(write_io)->fptr;
5638 if (write_fptr && 0 <= write_fptr->
fd) {
5639 rb_io_fptr_cleanup(write_fptr, TRUE);
5643 fptr =
RFILE(io)->fptr;
5644 if (!fptr)
return 0;
5645 if (fptr->
fd < 0)
return 0;
5647 if (rb_notify_fd_close(fptr->
fd, &busy)) {
5649 fptr_finalize_flush(fptr, FALSE, KEEPGVL, &busy);
5651 rb_io_fptr_cleanup(fptr, FALSE);
5656fptr_waitpid(
rb_io_t *fptr,
int nohang)
5660 rb_last_status_clear();
5669 rb_io_t *fptr = io_close_fptr(io);
5670 if (fptr) fptr_waitpid(fptr, 0);
5707rb_io_close_m(
VALUE io)
5709 rb_io_t *fptr = rb_io_get_fptr(io);
5718io_call_close(
VALUE io)
5727 enum {mesg_len =
sizeof(closed_stream)-1};
5731 memcmp(
RSTRING_PTR(mesg), closed_stream, mesg_len)) {
5741 if (!UNDEF_P(closed) &&
RTEST(closed))
return io;
5742 rb_rescue2(io_call_close, io, ignore_closed_stream, io,
5774rb_io_closed(
VALUE io)
5780 write_io = GetWriteIO(io);
5781 if (io != write_io) {
5782 write_fptr =
RFILE(write_io)->fptr;
5783 if (write_fptr && 0 <= write_fptr->
fd) {
5788 fptr = rb_io_get_fptr(io);
5789 return RBOOL(0 > fptr->
fd);
5825rb_io_close_read(
VALUE io)
5831 if (fptr->
fd < 0)
return Qnil;
5832 if (is_socket(fptr->
fd, fptr->
pathv)) {
5836 if (shutdown(fptr->
fd, SHUT_RD) < 0)
5837 rb_sys_fail_path(fptr->
pathv);
5838 fptr->
mode &= ~FMODE_READABLE;
5844 write_io = GetWriteIO(io);
5845 if (io != write_io) {
5850 RFILE(io)->fptr = wfptr;
5853 RFILE(write_io)->fptr = fptr;
5854 rb_io_fptr_cleanup(fptr, FALSE);
5898rb_io_close_write(
VALUE io)
5903 write_io = GetWriteIO(io);
5905 if (fptr->
fd < 0)
return Qnil;
5906 if (is_socket(fptr->
fd, fptr->
pathv)) {
5910 if (shutdown(fptr->
fd, SHUT_WR) < 0)
5911 rb_sys_fail_path(fptr->
pathv);
5912 fptr->
mode &= ~FMODE_WRITABLE;
5922 if (io != write_io) {
5942rb_io_sysseek(
int argc,
VALUE *argv,
VALUE io)
5944 VALUE offset, ptrname;
5945 int whence = SEEK_SET;
5949 if (
rb_scan_args(argc, argv,
"11", &offset, &ptrname) == 2) {
5950 whence = interpret_seek_whence(ptrname);
5955 (READ_DATA_BUFFERED(fptr) || READ_CHAR_PENDING(fptr))) {
5959 rb_warn(
"sysseek for buffered IO");
5962 pos = lseek(fptr->
fd, pos, whence);
5963 if (pos < 0 && errno) rb_sys_fail_path(fptr->
pathv);
5997 io = GetWriteIO(io);
6002 rb_warn(
"syswrite for buffered IO");
6005 tmp = rb_str_tmp_frozen_acquire(str);
6007 n = rb_io_write_memory(fptr, ptr, len);
6008 if (n < 0) rb_sys_fail_path(fptr->
pathv);
6009 rb_str_tmp_frozen_release(str, tmp);
6026rb_io_sysread(
int argc,
VALUE *argv,
VALUE io)
6037 shrinkable = io_setstrbuf(&str, ilen);
6038 if (ilen == 0)
return str;
6043 if (READ_DATA_BUFFERED(fptr)) {
6049 io_setstrbuf(&str, ilen);
6057 n = io_read_memory_locktmp(str, &iis);
6060 rb_sys_fail_path(fptr->
pathv);
6063 io_set_read_length(str, n, shrinkable);
6065 if (n == 0 && ilen > 0) {
6072#if defined(HAVE_PREAD) || defined(HAVE_PWRITE)
6073struct prdwr_internal_arg {
6081#if defined(HAVE_PREAD)
6083internal_pread_func(
void *arg)
6085 struct prdwr_internal_arg *p = arg;
6086 return (
VALUE)pread(p->fd, p->buf, p->count, p->offset);
6090pread_internal_call(
VALUE arg)
6092 struct prdwr_internal_arg *p = (
struct prdwr_internal_arg *)arg;
6093 return rb_thread_io_blocking_region(internal_pread_func, p, p->fd);
6127 VALUE len, offset, str;
6130 struct prdwr_internal_arg arg;
6137 shrinkable = io_setstrbuf(&str, (
long)arg.count);
6138 if (arg.count == 0)
return str;
6151 rb_sys_fail_path(fptr->
pathv);
6153 io_set_read_length(str, n, shrinkable);
6154 if (n == 0 && arg.count > 0) {
6161# define rb_io_pread rb_f_notimplement
6164#if defined(HAVE_PWRITE)
6166internal_pwrite_func(
void *ptr)
6168 struct prdwr_internal_arg *arg = ptr;
6170 return (
VALUE)pwrite(arg->fd, arg->buf, arg->count, arg->offset);
6203 struct prdwr_internal_arg arg;
6211 io = GetWriteIO(io);
6216 tmp = rb_str_tmp_frozen_acquire(str);
6220 n = (ssize_t)rb_thread_io_blocking_region(internal_pwrite_func, &arg, fptr->
fd);
6221 if (n < 0) rb_sys_fail_path(fptr->
pathv);
6222 rb_str_tmp_frozen_release(str, tmp);
6227# define rb_io_pwrite rb_f_notimplement
6241 fptr->
mode &= ~FMODE_TEXTMODE;
6245 SET_BINARY_MODE_WITH_SEEK_CUR(fptr);
6248 setmode(fptr->
fd, O_BINARY);
6255io_ascii8bit_binmode(
rb_io_t *fptr)
6266 fptr->
mode &= ~FMODE_TEXTMODE;
6267 SET_BINARY_MODE_WITH_SEEK_CUR(fptr);
6269 fptr->
encs.
enc = rb_ascii8bit_encoding();
6273 clear_codeconv(fptr);
6282 io_ascii8bit_binmode(fptr);
6299rb_io_binmode_m(
VALUE io)
6305 write_io = GetWriteIO(io);
6320rb_io_binmode_p(
VALUE io)
6328rb_io_fmode_modestr(
int fmode)
6332 return MODE_BTMODE(
"a+",
"ab+",
"at+");
6334 return MODE_BTMODE(
"a",
"ab",
"at");
6340 return MODE_BTMODE(
"r",
"rb",
"rt");
6342 return MODE_BTXMODE(
"w",
"wb",
"wt",
"wx",
"wbx",
"wtx");
6345 return MODE_BTXMODE(
"w+",
"wb+",
"wt+",
"w+x",
"wb+x",
"wt+x");
6347 return MODE_BTMODE(
"r+",
"rb+",
"rt+");
6351static const char bom_prefix[] =
"bom|";
6352static const char utf_prefix[] =
"utf-";
6353enum {bom_prefix_len = (int)
sizeof(bom_prefix) - 1};
6354enum {utf_prefix_len = (int)
sizeof(utf_prefix) - 1};
6357io_encname_bom_p(
const char *name,
long len)
6359 return len > bom_prefix_len &&
STRNCASECMP(name, bom_prefix, bom_prefix_len) == 0;
6366 const char *m = modestr, *p = NULL;
6394 if (modestr[0] !=
'w')
6402 if (io_encname_bom_p(m, p ? (
long)(p - m) : (long)strlen(m)))
6420rb_io_oflags_fmode(
int oflags)
6424 switch (oflags & O_ACCMODE) {
6436 if (oflags & O_APPEND) {
6439 if (oflags & O_TRUNC) {
6442 if (oflags & O_CREAT) {
6445 if (oflags & O_EXCL) {
6449 if (oflags & O_BINARY) {
6458rb_io_fmode_oflags(
int fmode)
6502rb_io_oflags_modestr(
int oflags)
6505# define MODE_BINARY(a,b) ((oflags & O_BINARY) ? (b) : (a))
6507# define MODE_BINARY(a,b) (a)
6510 if (oflags & O_EXCL) {
6513 accmode = oflags & (O_RDONLY|O_WRONLY|O_RDWR);
6514 if (oflags & O_APPEND) {
6515 if (accmode == O_WRONLY) {
6516 return MODE_BINARY(
"a",
"ab");
6518 if (accmode == O_RDWR) {
6519 return MODE_BINARY(
"a+",
"ab+");
6526 return MODE_BINARY(
"r",
"rb");
6528 return MODE_BINARY(
"w",
"wb");
6530 if (oflags & O_TRUNC) {
6531 return MODE_BINARY(
"w+",
"wb+");
6533 return MODE_BINARY(
"r+",
"rb+");
6545 int default_ext = 0;
6548 ext = rb_default_external_encoding();
6551 if (rb_is_ascii8bit_enc(ext)) {
6555 else if (intern == NULL) {
6556 intern = rb_default_internal_encoding();
6561 *enc = (default_ext && intern != ext) ? NULL : ext;
6571unsupported_encoding(
const char *name,
rb_encoding *enc)
6573 rb_enc_warn(enc,
"Unsupported encoding %s ignored", name);
6577parse_mode_enc(
const char *estr,
rb_encoding *estr_enc,
6583 int fmode = fmode_p ? *fmode_p : 0;
6589 p = strrchr(estr,
':');
6590 len = p ? (p++ - estr) : (long)strlen(estr);
6592 estr += bom_prefix_len;
6593 len -= bom_prefix_len;
6594 if (!
STRNCASECMP(estr, utf_prefix, utf_prefix_len)) {
6598 rb_enc_warn(estr_enc,
"BOM with non-UTF encoding %s is nonsense", estr);
6599 fmode &= ~FMODE_SETENC_BY_BOM;
6607 memcpy(encname, estr, len);
6608 encname[len] =
'\0';
6611 idx = rb_enc_find_index(estr);
6613 if (fmode_p) *fmode_p = fmode;
6616 ext_enc = rb_enc_from_index(idx);
6619 unsupported_encoding(estr, estr_enc);
6625 if (*p ==
'-' && *(p+1) ==
'\0') {
6630 idx2 = rb_enc_find_index(p);
6632 unsupported_encoding(p, estr_enc);
6637 int_enc = rb_enc_from_index(idx2);
6641 rb_io_ext_int_to_encs(ext_enc, int_enc, enc_p, enc2_p, fmode);
6654 v = rb_hash_lookup2(opt, sym_encoding,
Qnil);
6655 if (v !=
Qnil) encoding = v;
6656 v = rb_hash_lookup2(opt, sym_extenc,
Qundef);
6657 if (v !=
Qnil) extenc = v;
6658 v = rb_hash_lookup2(opt, sym_intenc,
Qundef);
6659 if (!UNDEF_P(v)) intenc = v;
6661 if ((!UNDEF_P(extenc) || !UNDEF_P(intenc)) && !
NIL_P(encoding)) {
6663 int idx = rb_to_encoding_index(encoding);
6664 if (idx >= 0) encoding = rb_enc_from_encoding(rb_enc_from_index(idx));
6665 rb_warn(
"Ignoring encoding parameter '%"PRIsVALUE
"': %s_encoding is used",
6666 encoding, UNDEF_P(extenc) ?
"internal" :
"external");
6670 if (!UNDEF_P(extenc) && !
NIL_P(extenc)) {
6671 extencoding = rb_to_encoding(extenc);
6673 if (!UNDEF_P(intenc)) {
6674 if (
NIL_P(intenc)) {
6681 if (*p ==
'-' && *(p+1) ==
'\0') {
6686 intencoding = rb_to_encoding(intenc);
6690 intencoding = rb_to_encoding(intenc);
6692 if (extencoding == intencoding) {
6696 if (!
NIL_P(encoding)) {
6700 enc_p, enc2_p, fmode_p);
6703 rb_io_ext_int_to_encs(rb_to_encoding(encoding), NULL, enc_p, enc2_p, 0);
6706 else if (!UNDEF_P(extenc) || !UNDEF_P(intenc)) {
6708 rb_io_ext_int_to_encs(extencoding, intencoding, enc_p, enc2_p, 0);
6718 int fmode = *fmode_p;
6734#if !DEFAULT_TEXTMODE
6736 fmode &= ~FMODE_TEXTMODE;
6743extract_binmode(
VALUE opthash,
int *fmode)
6745 if (!
NIL_P(opthash)) {
6747 v = rb_hash_aref(opthash, sym_textmode);
6756 v = rb_hash_aref(opthash, sym_binmode);
6773 int *oflags_p,
int *fmode_p,
convconfig_t *convconfig_p)
6780 int has_enc = 0, has_vmode = 0;
6786 rb_io_ext_int_to_encs(NULL, NULL, &
enc, &
enc2, 0);
6796 fmode = rb_io_oflags_fmode(oflags);
6804 oflags = rb_io_fmode_oflags(fmode);
6808 parse_mode_enc(p+1, rb_enc_get(vmode), &
enc, &
enc2, &fmode);
6813 e = (fmode &
FMODE_BINMODE) ? rb_ascii8bit_encoding() : NULL;
6814 rb_io_ext_int_to_encs(e, NULL, &
enc, &
enc2, fmode);
6818 if (
NIL_P(opthash)) {
6822#ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
6824 MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE,
6825 0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE) : 0;
6827 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(
enc2,
ecflags);
6834 rb_io_ext_int_to_encs(rb_ascii8bit_encoding(), NULL, &
enc, &
enc2, fmode);
6837 else if (
NIL_P(vmode)) {
6838 fmode |= DEFAULT_TEXTMODE;
6845 v = rb_hash_aref(opthash, sym_mode);
6847 if (!
NIL_P(vmode)) {
6855 v = rb_hash_aref(opthash, sym_flags);
6860 fmode = rb_io_oflags_fmode(oflags);
6862 extract_binmode(opthash, &fmode);
6868 rb_io_ext_int_to_encs(rb_ascii8bit_encoding(), NULL, &
enc, &
enc2, fmode);
6871 else if (
NIL_P(vmode)) {
6872 fmode |= DEFAULT_TEXTMODE;
6875 v = rb_hash_aref(opthash, sym_perm);
6878 if (!
NIL_P(*vperm_p)) {
6890#ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
6892 MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE,
6893 0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE) : 0;
6901 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(
enc2,
ecflags);
6924sysopen_func(
void *ptr)
6942rb_sysopen(
VALUE fname,
int oflags, mode_t perm)
6947 data.fname = rb_str_encode_ospath(fname);
6949 data.oflags = oflags;
6952 fd = rb_sysopen_internal(&data);
6955 if (rb_gc_for_fd(e)) {
6956 fd = rb_sysopen_internal(&data);
6959 rb_syserr_fail_path(e, fname);
6973 file = fdopen(fd, modestr);
6980 file = fdopen(fd, modestr);
6984 if (rb_gc_for_fd(e)) {
6985 file = fdopen(fd, modestr);
6989 if (e == 0) e = EINVAL;
6991 if (e == 0) e = EMFILE;
6999 if (setvbuf(file, NULL, _IOFBF, 0) != 0)
7000 rb_warn(
"setvbuf() can't be honoured (fd=%d)", fd);
7008 int t = isatty(fptr->
fd);
7018io_strip_bom(
VALUE io)
7020 VALUE b1, b2, b3, b4;
7031 return rb_utf8_encindex();
7041 return ENCINDEX_UTF_16BE;
7052 return ENCINDEX_UTF_32LE;
7057 return ENCINDEX_UTF_16LE;
7067 return ENCINDEX_UTF_32BE;
7081io_set_encoding_by_bom(
VALUE io)
7083 int idx = io_strip_bom(io);
7089 extenc = rb_enc_from_index(idx);
7090 io_encoding_set(fptr, rb_enc_from_encoding(extenc),
7091 rb_io_internal_encoding(io),
Qnil);
7100rb_file_open_generic(
VALUE io,
VALUE filename,
int oflags,
int fmode,
7108 rb_io_ext_int_to_encs(NULL, NULL, &cc.
enc, &cc.
enc2, fmode);
7113 validate_enc_binmode(&fmode, convconfig->
ecflags,
7114 convconfig->
enc, convconfig->
enc2);
7118 fptr->
encs = *convconfig;
7121 if (!(oflags & O_TMPFILE)) {
7122 fptr->
pathv = pathv;
7125 fptr->
pathv = pathv;
7127 fptr->
fd = rb_sysopen(pathv, oflags, perm);
7135rb_file_open_internal(
VALUE io,
VALUE filename,
const char *modestr)
7138 const char *p = strchr(modestr,
':');
7142 parse_mode_enc(p+1, rb_usascii_encoding(),
7143 &convconfig.
enc, &convconfig.
enc2, &fmode);
7151 e = (fmode &
FMODE_BINMODE) ? rb_ascii8bit_encoding() : NULL;
7152 rb_io_ext_int_to_encs(e, NULL, &convconfig.
enc, &convconfig.
enc2, fmode);
7157 return rb_file_open_generic(io, filename,
7158 rb_io_fmode_oflags(fmode),
7168 return rb_file_open_internal(io_alloc(
rb_cFile), fname, modestr);
7177#if defined(__CYGWIN__) || !defined(HAVE_WORKING_FORK)
7200 while ((tmp = *prev) != 0) {
7201 if (tmp->fptr == fptr) {
7210#if defined (_WIN32) || defined(__CYGWIN__)
7219 rb_io_fptr_finalize(list->fptr);
7226pipe_finalize(
rb_io_t *fptr,
int noraise)
7228#if !defined(HAVE_WORKING_FORK) && !defined(_WIN32)
7237 fptr_finalize(fptr, noraise);
7239 pipe_del_fptr(fptr);
7246#if defined(__CYGWIN__) || !defined(HAVE_WORKING_FORK)
7249 if (old_finalize == orig->finalize)
return;
7254#if defined(__CYGWIN__) || !defined(HAVE_WORKING_FORK)
7255 if (old_finalize != pipe_finalize) {
7257 for (list =
pipe_list; list; list = list->next) {
7258 if (list->fptr == fptr)
break;
7260 if (!list) pipe_add_fptr(fptr);
7263 pipe_del_fptr(fptr);
7276rb_io_unbuffered(
rb_io_t *fptr)
7287 if (rb_gc_for_fd(errno)) {
7299#define HAVE_SPAWNV 1
7300#define spawnv(mode, cmd, args) rb_w32_uaspawn((mode), (cmd), (args))
7301#define spawn(mode, cmd) rb_w32_uspawn((mode), (cmd), 0)
7304#if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
7314#ifdef HAVE_WORKING_FORK
7315# ifndef __EMSCRIPTEN__
7317popen_redirect(
struct popen_arg *p)
7320 close(p->write_pair[1]);
7321 if (p->write_pair[0] != 0) {
7322 dup2(p->write_pair[0], 0);
7323 close(p->write_pair[0]);
7326 if (p->pair[1] != 1) {
7327 dup2(p->pair[1], 1);
7333 if (p->pair[1] != 1) {
7334 dup2(p->pair[1], 1);
7340 if (p->pair[0] != 0) {
7341 dup2(p->pair[0], 0);
7348#if defined(__linux__)
7359linux_get_maxfd(
void)
7362 char buf[4096], *p, *np, *e;
7365 if (fd < 0)
return fd;
7366 ss = read(fd, buf,
sizeof(buf));
7367 if (ss < 0)
goto err;
7370 while ((
int)
sizeof(
"FDSize:\t0\n")-1 <= e-p &&
7371 (np = memchr(p,
'\n', e-p)) != NULL) {
7372 if (memcmp(p,
"FDSize:",
sizeof(
"FDSize:")-1) == 0) {
7374 p +=
sizeof(
"FDSize:")-1;
7394#if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
7396 int max = (int)max_file_descriptor;
7399 ret = fcntl(0, F_MAXFD);
7401 maxhint = max = ret;
7402# elif defined(__linux__)
7403 ret = linux_get_maxfd();
7410 for (fd = lowfd; fd <= max; fd++) {
7411 if (!
NIL_P(noclose_fds) &&
7414 ret = fcntl(fd, F_GETFD);
7415 if (ret != -1 && !(ret & FD_CLOEXEC)) {
7416 fcntl(fd, F_SETFD, ret|FD_CLOEXEC);
7418# define CONTIGUOUS_CLOSED_FDS 20
7420 if (max < fd + CONTIGUOUS_CLOSED_FDS)
7421 max = fd + CONTIGUOUS_CLOSED_FDS;
7427# ifndef __EMSCRIPTEN__
7429popen_exec(
void *pp,
char *errmsg,
size_t errmsg_len)
7431 struct popen_arg *p = (
struct popen_arg*)pp;
7433 return rb_exec_async_signal_safe(p->eargp, errmsg, errmsg_len);
7438#if (defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)) && !defined __EMSCRIPTEN__
7440rb_execarg_fixup_v(
VALUE execarg_obj)
7442 rb_execarg_parent_start(execarg_obj);
7446char *rb_execarg_commandline(
const struct rb_execarg *eargp,
VALUE *prog);
7449#ifndef __EMSCRIPTEN__
7451pipe_open(
VALUE execarg_obj,
const char *modestr,
int fmode,
7454 struct rb_execarg *eargp =
NIL_P(execarg_obj) ? NULL : rb_execarg_get(execarg_obj);
7455 VALUE prog = eargp ? (eargp->use_shell ? eargp->invoke.sh.shell_script : eargp->invoke.cmd.command_name) :
Qfalse ;
7461#if defined(HAVE_WORKING_FORK)
7463 char errmsg[80] = {
'\0' };
7465#if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
7467 struct popen_arg arg;
7470#if defined(HAVE_SPAWNV)
7471# if defined(HAVE_SPAWNVE)
7472# define DO_SPAWN(cmd, args, envp) ((args) ? \
7473 spawnve(P_NOWAIT, (cmd), (args), (envp)) : \
7474 spawne(P_NOWAIT, (cmd), (envp)))
7476# define DO_SPAWN(cmd, args, envp) ((args) ? \
7477 spawnv(P_NOWAIT, (cmd), (args)) : \
7478 spawn(P_NOWAIT, (cmd)))
7480# if !defined(HAVE_WORKING_FORK)
7482# if defined(HAVE_SPAWNVE)
7487#if !defined(HAVE_WORKING_FORK)
7493#if !defined(HAVE_WORKING_FORK)
7494 const char *cmd = 0;
7500#if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
7501 arg.execarg_obj = execarg_obj;
7504 arg.pair[0] = arg.pair[1] = -1;
7505 arg.write_pair[0] = arg.write_pair[1] = -1;
7506# if !defined(HAVE_WORKING_FORK)
7507 if (eargp && !eargp->use_shell) {
7508 args = ARGVSTR2ARGV(eargp->invoke.cmd.argv_str);
7513 if (
rb_pipe(arg.write_pair) < 0)
7517 close(arg.write_pair[0]);
7518 close(arg.write_pair[1]);
7522 rb_execarg_addopt(execarg_obj,
INT2FIX(0),
INT2FIX(arg.write_pair[0]));
7523 rb_execarg_addopt(execarg_obj,
INT2FIX(1),
INT2FIX(arg.pair[1]));
7530 rb_execarg_addopt(execarg_obj,
INT2FIX(1),
INT2FIX(arg.pair[1]));
7536 rb_execarg_addopt(execarg_obj,
INT2FIX(0),
INT2FIX(arg.pair[0]));
7541 if (!
NIL_P(execarg_obj)) {
7542 rb_protect(rb_execarg_fixup_v, execarg_obj, &state);
7544 if (0 <= arg.write_pair[0]) close(arg.write_pair[0]);
7545 if (0 <= arg.write_pair[1]) close(arg.write_pair[1]);
7546 if (0 <= arg.pair[0]) close(arg.pair[0]);
7547 if (0 <= arg.pair[1]) close(arg.pair[1]);
7548 rb_execarg_parent_end(execarg_obj);
7552# if defined(HAVE_WORKING_FORK)
7553 pid = rb_fork_async_signal_safe(&status, popen_exec, &arg, arg.eargp->redirect_fds, errmsg,
sizeof(errmsg));
7555 rb_execarg_run_options(eargp, sargp, NULL, 0);
7556# if defined(HAVE_SPAWNVE)
7557 if (eargp->envp_str) envp = (
char **)
RSTRING_PTR(eargp->envp_str);
7559 while ((pid = DO_SPAWN(cmd, args, envp)) < 0) {
7561 switch (e = errno) {
7563# if EWOULDBLOCK != EAGAIN
7572 rb_execarg_run_options(sargp, NULL, NULL, 0);
7574 rb_execarg_parent_end(execarg_obj);
7577# if defined(HAVE_WORKING_FORK)
7578 pid = rb_call_proc__fork();
7580 popen_redirect(&arg);
7592# if defined(HAVE_WORKING_FORK)
7598 close(arg.write_pair[0]);
7599 close(arg.write_pair[1]);
7601# if defined(HAVE_WORKING_FORK)
7610 close(arg.write_pair[0]);
7611 write_fd = arg.write_pair[1];
7622 cmd = rb_execarg_commandline(eargp, &prog);
7623 if (!
NIL_P(execarg_obj)) {
7624 rb_execarg_parent_start(execarg_obj);
7625 rb_execarg_run_options(eargp, sargp, NULL, 0);
7627 fp = popen(cmd, modestr);
7630 rb_execarg_parent_end(execarg_obj);
7631 rb_execarg_run_options(sargp, NULL, NULL, 0);
7633 if (!fp) rb_syserr_fail_path(e, prog);
7643 fptr->
encs = *convconfig;
7644#if RUBY_CRLF_ENVIRONMENT
7651 if (NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {
7654#ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
7655 if (NEED_NEWLINE_DECORATOR_ON_WRITE(fptr)) {
7656 fptr->
encs.
ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
7662 if (0 <= write_fd) {
7663 write_port = io_alloc(
rb_cIO);
7665 write_fptr->
fd = write_fd;
7667 fptr->
mode &= ~FMODE_WRITABLE;
7672#if defined (__CYGWIN__) || !defined(HAVE_WORKING_FORK)
7674 pipe_add_fptr(fptr);
7680pipe_open(
VALUE execarg_obj,
const char *modestr,
int fmode,
7688is_popen_fork(
VALUE prog)
7691#if !defined(HAVE_WORKING_FORK)
7693 "fork() function is unimplemented on this machine");
7702pipe_open_s(
VALUE prog,
const char *modestr,
int fmode,
7706 VALUE *argv = &prog;
7709 if (!is_popen_fork(prog))
7710 execarg_obj = rb_execarg_new(argc, argv, TRUE, FALSE);
7711 return pipe_open(execarg_obj, modestr, fmode, convconfig);
7717 rb_io_t *fptr = io_close_fptr(io);
7885rb_io_s_popen(
int argc,
VALUE *argv,
VALUE klass)
7889 if (argc > 1 && !
NIL_P(opt = rb_check_hash_type(argv[argc-1]))) --argc;
7890 if (argc > 1 && !
NIL_P(env = rb_check_hash_type(argv[0]))) --argc, ++argv;
7899 int ex = !
NIL_P(opt);
7900 rb_error_arity(argc + ex, 1 + ex, 2 + ex);
7903 return popen_finish(rb_io_popen(pname, pmode, env, opt), klass);
7909 const char *modestr;
7914 tmp = rb_check_array_type(pname);
7917#if SIZEOF_LONG > SIZEOF_INT
7918 if (len > INT_MAX) {
7922 execarg_obj = rb_execarg_new((
int)len,
RARRAY_CONST_PTR(tmp), FALSE, FALSE);
7928 if (!is_popen_fork(pname))
7929 execarg_obj = rb_execarg_new(1, &pname, TRUE, FALSE);
7931 if (!
NIL_P(execarg_obj)) {
7933 opt = rb_execarg_extract_options(execarg_obj, opt);
7935 rb_execarg_setenv(execarg_obj, env);
7938 modestr = rb_io_oflags_modestr(oflags);
7940 return pipe_open(execarg_obj, modestr, fmode, &convconfig);
7956 RBASIC_SET_CLASS(port, klass);
7964rb_scan_open_args(
int argc,
const VALUE *argv,
7965 VALUE *fname_p,
int *oflags_p,
int *fmode_p,
7968 VALUE opt, fname, vmode, vperm;
7972 argc =
rb_scan_args(argc, argv,
"12:", &fname, &vmode, &vperm, &opt);
7986rb_open_file(
int argc,
const VALUE *argv,
VALUE io)
7993 rb_scan_open_args(argc, argv, &fname, &oflags, &fmode, &convconfig, &perm);
7994 rb_file_open_generic(io, fname, oflags, fmode, &convconfig, perm);
8032rb_io_s_open(
int argc,
VALUE *argv,
VALUE klass)
8064 VALUE fname, vmode, vperm;
8069 rb_scan_args(argc, argv,
"12", &fname, &vmode, &vperm);
8080 if (
NIL_P(vperm)) perm = 0666;
8084 fd = rb_sysopen(fname, oflags, perm);
8089check_pipe_command(
VALUE filename_or_command)
8096 if (rb_enc_ascget(s, e, &chlen, rb_enc_get(filename_or_command)) ==
'|') {
8205 int redirect = FALSE;
8213 VALUE tmp = argv[0];
8219 VALUE cmd = check_pipe_command(tmp);
8222 return rb_io_s_popen(argc, argv,
rb_cIO);
8235 return rb_io_s_open(argc, argv,
rb_cFile);
8249 return rb_io_open_generic(io, filename, oflags, fmode, &convconfig, perm);
8253rb_io_open_generic(
VALUE klass,
VALUE filename,
int oflags,
int fmode,
8257 if (klass ==
rb_cIO && !
NIL_P(cmd = check_pipe_command(filename))) {
8258 return pipe_open_s(cmd, rb_io_oflags_modestr(oflags), fmode, convconfig);
8261 return rb_file_open_generic(io_alloc(klass), filename,
8262 oflags, fmode, convconfig, perm);
8277 if (fptr == orig)
return io;
8278 if (IS_PREP_STDIO(fptr)) {
8283 "%s can't change access mode from \"%s\" to \"%s\"",
8284 PREP_STDIO_NAME(fptr), rb_io_fmode_modestr(fptr->
mode),
8285 rb_io_fmode_modestr(orig->
mode));
8289 if (io_fflush(fptr) < 0)
8290 rb_sys_fail_on_write(fptr);
8293 flush_before_seek(fptr);
8296 pos = io_tell(orig);
8299 if (io_fflush(orig) < 0)
8300 rb_sys_fail_on_write(fptr);
8308 else if (!IS_PREP_STDIO(fptr)) fptr->
pathv =
Qnil;
8309 fptr_copy_finalizer(fptr, orig);
8314 if (IS_PREP_STDIO(fptr) || fd <= 2 || !fptr->stdio_file) {
8317 rb_sys_fail_path(orig->
pathv);
8325 rb_sys_fail_path(orig->
pathv);
8331 if (io_seek(fptr, pos, SEEK_SET) < 0 && errno) {
8332 rb_sys_fail_path(fptr->
pathv);
8334 if (io_seek(orig, pos, SEEK_SET) < 0 && errno) {
8335 rb_sys_fail_path(orig->
pathv);
8349int rb_freopen(
VALUE fname,
const char *mode,
FILE *fp);
8352rb_freopen(
VALUE fname,
const char *mode,
FILE *fp)
8397rb_io_reopen(
int argc,
VALUE *argv,
VALUE file)
8399 VALUE fname, nmode, opt;
8403 if (
rb_scan_args(argc, argv,
"11:", &fname, &nmode, &opt) == 1) {
8406 return io_reopen(file, tmp);
8412 fptr =
RFILE(file)->fptr;
8422 if (IS_PREP_STDIO(fptr) &&
8426 "%s can't change access mode from \"%s\" to \"%s\"",
8427 PREP_STDIO_NAME(fptr), rb_io_fmode_modestr(fptr->
mode),
8428 rb_io_fmode_modestr(fmode));
8431 fptr->
encs = convconfig;
8434 oflags = rb_io_fmode_oflags(fptr->
mode);
8437 fptr->
pathv = fname;
8439 fptr->
fd = rb_sysopen(fptr->
pathv, oflags, 0666);
8445 if (io_fflush(fptr) < 0)
8446 rb_sys_fail_on_write(fptr);
8451 int e = rb_freopen(rb_str_encode_ospath(fptr->
pathv),
8452 rb_io_oflags_modestr(oflags),
8454 if (e) rb_syserr_fail_path(e, fptr->
pathv);
8458 if (setvbuf(fptr->
stdio_file, NULL, _IOFBF, 0) != 0)
8459 rb_warn(
"setvbuf() can't be honoured for %"PRIsVALUE, fptr->
pathv);
8462 if (setvbuf(fptr->
stdio_file, NULL, _IONBF, BUFSIZ) != 0)
8463 rb_warn(
"setvbuf() can't be honoured for %"PRIsVALUE, fptr->
pathv);
8465 else if (fptr->
stdio_file == stdout && isatty(fptr->
fd)) {
8466 if (setvbuf(fptr->
stdio_file, NULL, _IOLBF, BUFSIZ) != 0)
8467 rb_warn(
"setvbuf() can't be honoured for %"PRIsVALUE, fptr->
pathv);
8471 int tmpfd = rb_sysopen(fptr->
pathv, oflags, 0666);
8477 rb_syserr_fail_path(err, fptr->
pathv);
8501 fptr->
mode = orig->
mode & ~FMODE_PREP;
8507 fptr_copy_finalizer(fptr, orig);
8509 fd = ruby_dup(orig->
fd);
8511 pos = io_tell(orig);
8513 io_seek(fptr, pos, SEEK_SET);
8518 write_io = GetWriteIO(io);
8519 if (io != write_io) {
8585 if (argc == 0)
return Qnil;
8604 rb_warn_deprecated(
"`%s'", NULL,
rb_id2name(
id));
8677 if (argc > 1 && !
NIL_P(rb_output_fs)) {
8680 for (i=0; i<argc; i++) {
8681 if (!
NIL_P(rb_output_fs) && i>0) {
8785#define forward(obj, id, argc, argv) \
8786 rb_funcallv_kw(obj, id, argc, argv, RB_PASS_CALLED_KEYWORDS)
8787#define forward_public(obj, id, argc, argv) \
8788 rb_funcallv_public_kw(obj, id, argc, argv, RB_PASS_CALLED_KEYWORDS)
8789#define forward_current(id, argc, argv) \
8790 forward_public(ARGF.current_file, id, argc, argv)
8808 if (recv == r_stdout) {
8809 return rb_io_putc(recv, ch);
8811 return forward(r_stdout,
rb_intern(
"putc"), 1, &ch);
8816rb_str_end_with_asciichar(
VALUE str,
int c)
8823 if (len == 0)
return 0;
8825 return ptr[len - 1] == c;
8827 return rb_enc_ascget(ptr + ((len - 1) / n) * n, ptr + len, &n, enc) == c;
8841 ary = rb_check_array_type(ary);
8900 VALUE line, args[2];
8907 for (
int i = 0; i < argc; i++) {
8926 if (!rb_str_end_with_asciichar(line,
'\n')) {
8931 rb_io_writev(out, n, args);
8950 if (recv == r_stdout) {
8953 return forward(r_stdout,
rb_intern(
"puts"), argc, argv);
8957rb_p_write(
VALUE str)
8964 rb_method_basic_definition_p(
CLASS_OF(r_stdout), id_write)) {
8965 io_writev(2, args, r_stdout);
8968 rb_io_writev(r_stdout, 2, args);
8980rb_p_result(
int argc,
const VALUE *argv)
8987 else if (argc > 1) {
9029 for (i=0; i<argc; i++) {
9031 rb_uninterruptible(rb_p_write, inspected);
9033 return rb_p_result(argc, argv);
9054rb_obj_display(
int argc,
VALUE *argv,
VALUE self)
9065rb_stderr_to_original_p(
VALUE err)
9067 return (err == orig_stderr ||
RFILE(orig_stderr)->fptr->
fd < 0);
9074 if (rb_stderr_to_original_p(out)) {
9076 if (isatty(fileno(stderr))) {
9077 if (rb_w32_write_console(
rb_str_new(mesg, len), fileno(stderr)) > 0)
return;
9080 if (fwrite(mesg,
sizeof(
char), (
size_t)len, stderr) < (
size_t)len) {
9097rb_write_error_str(
VALUE mesg)
9101 if (rb_stderr_to_original_p(out)) {
9104 if (isatty(fileno(stderr))) {
9105 if (rb_w32_write_console(mesg, fileno(stderr)) > 0)
return;
9108 if (fwrite(
RSTRING_PTR(mesg),
sizeof(
char), len, stderr) < len) {
9120rb_stderr_tty_p(
void)
9123 return isatty(fileno(stderr));
9128must_respond_to(
ID mid,
VALUE val,
ID id)
9132 rb_id2str(
id), rb_id2str(mid),
9144stdin_getter(
ID id,
VALUE *ptr)
9152 must_respond_to(id_write, val,
id);
9157stdout_getter(
ID id,
VALUE *ptr)
9165 must_respond_to(id_write, val,
id);
9170stderr_getter(
ID id,
VALUE *ptr)
9176prep_io(
int fd,
int fmode,
VALUE klass,
const char *path)
9179 VALUE io = io_alloc(klass);
9186 if (!io_check_tty(fp)) {
9189 setmode(fd, O_BINARY);
9203 if (path && strcmp(path,
"-")) klass =
rb_cFile;
9204 return prep_io(fd, rb_io_oflags_fmode(oflags), klass, path);
9208prep_stdio(
FILE *f,
int fmode,
VALUE klass,
const char *path)
9211 VALUE io = prep_io(fileno(f), fmode|FMODE_PREP|DEFAULT_TEXTMODE, klass, path);
9215#ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
9216 fptr->
encs.
ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
9227rb_io_prep_stdin(
void)
9233rb_io_prep_stdout(
void)
9239rb_io_prep_stderr(
void)
9248 int oflags = rb_io_fmode_oflags(fptr->
mode) & ~O_EXCL;
9275 rb_io_buffer_init(&fp->
wbuf);
9276 rb_io_buffer_init(&fp->
rbuf);
9277 rb_io_buffer_init(&fp->
cbuf);
9295rb_io_make_open_file(
VALUE obj)
9300 if (
RFILE(obj)->fptr) {
9302 rb_io_fptr_finalize(
RFILE(obj)->fptr);
9303 RFILE(obj)->fptr = 0;
9305 fp = rb_io_fptr_new();
9307 RFILE(obj)->fptr = fp;
9353rb_io_initialize(
int argc,
VALUE *argv,
VALUE io)
9357 int fd, fmode, oflags = O_RDONLY;
9360#if defined(HAVE_FCNTL) && defined(F_GETFL)
9367 argc =
rb_scan_args(argc, argv,
"11:", &fnum, &vmode, &opt);
9374#if defined(HAVE_FCNTL) && defined(F_GETFL)
9375 oflags = fcntl(fd, F_GETFL);
9381#if defined(HAVE_FCNTL) && defined(F_GETFL)
9382 ofmode = rb_io_oflags_fmode(oflags);
9394 if (rb_hash_aref(opt, sym_autoclose) ==
Qfalse) {
9395 fmode |= FMODE_PREP;
9398 path = rb_hash_aref(opt,
RB_ID2SYM(idPath));
9409 fp->
encs = convconfig;
9414 if (fileno(stdin) == fd)
9416 else if (fileno(stdout) == fd)
9418 else if (fileno(stderr) == fd)
9450rb_io_set_encoding_by_bom(
VALUE io)
9461 else if (fptr->
encs.
enc && fptr->
encs.
enc != rb_ascii8bit_encoding()) {
9465 if (!io_set_encoding_by_bom(io))
return Qnil;
9466 return rb_enc_from_encoding(fptr->
encs.
enc);
9511rb_file_initialize(
int argc,
VALUE *argv,
VALUE io)
9513 if (
RFILE(io)->fptr) {
9516 if (0 < argc && argc < 3) {
9521 return rb_io_initialize(argc, argv, io);
9524 rb_open_file(argc, argv, io);
9531rb_io_s_new(
int argc,
VALUE *argv,
VALUE klass)
9536 rb_warn(
"%"PRIsVALUE
"::new() does not take block; use %"PRIsVALUE
"::open() instead",
9552rb_io_s_for_fd(
int argc,
VALUE *argv,
VALUE klass)
9555 rb_io_initialize(argc, argv, io);
9568rb_io_autoclose_p(
VALUE io)
9572 return RBOOL(!(fptr->
mode & FMODE_PREP));
9593rb_io_set_autoclose(
VALUE io,
VALUE autoclose)
9597 if (!
RTEST(autoclose))
9598 fptr->
mode |= FMODE_PREP;
9600 fptr->
mode &= ~FMODE_PREP;
9605io_wait_event(
VALUE io,
int event,
VALUE timeout,
int return_io)
9637io_wait_readable(
int argc,
VALUE *argv,
VALUE io)
9644 if (rb_io_read_pending(fptr))
return Qtrue;
9647 VALUE timeout = (argc == 1 ? argv[0] :
Qnil);
9661io_wait_writable(
int argc,
VALUE *argv,
VALUE io)
9669 VALUE timeout = (argc == 1 ? argv[0] :
Qnil);
9684io_wait_priority(
int argc,
VALUE *argv,
VALUE io)
9691 if (rb_io_read_pending(fptr))
return Qtrue;
9694 VALUE timeout = argc == 1 ? argv[0] :
Qnil;
9700wait_mode_sym(
VALUE mode)
9703 return RB_WAITFD_IN;
9706 return RB_WAITFD_IN;
9709 return RB_WAITFD_IN;
9712 return RB_WAITFD_OUT;
9715 return RB_WAITFD_OUT;
9718 return RB_WAITFD_OUT;
9721 return RB_WAITFD_IN|RB_WAITFD_OUT;
9724 return RB_WAITFD_IN|RB_WAITFD_OUT;
9727 return RB_WAITFD_IN|RB_WAITFD_OUT;
9734io_event_from_value(
VALUE value)
9776 for (
int i = 0; i < argc; i += 1) {
9778 events |= wait_mode_sym(argv[i]);
9780 else if (UNDEF_P(timeout)) {
9788 if (UNDEF_P(timeout)) timeout =
Qnil;
9796 events = io_event_from_value(argv[0]);
9804 if (rb_io_read_pending(fptr)) {
9806 if (return_io)
return Qtrue;
9812 return io_wait_event(io, events, timeout, return_io);
9818 struct argf *p = ptr;
9819 rb_gc_mark(p->filename);
9820 rb_gc_mark(p->current_file);
9821 rb_gc_mark(p->argv);
9822 rb_gc_mark(p->inplace);
9823 rb_gc_mark(p->encs.
ecopts);
9827argf_memsize(
const void *ptr)
9829 const struct argf *p = ptr;
9830 size_t size =
sizeof(*p);
9837 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
9844 p->current_file =
Qnil;
9850argf_alloc(
VALUE klass)
9865 memset(&ARGF, 0,
sizeof(ARGF));
9866 argf_init(&ARGF, argv);
9876 ARGF = argf_of(orig);
9903 ARGF.last_lineno = ARGF.lineno;
9929 return forward_current(rb_frame_this_func(), argc, argv);
9932#define next_argv() argf_next_argv(argf)
9933#define ARGF_GENERIC_INPUT_P() \
9934 (ARGF.current_file == rb_stdin && !RB_TYPE_P(ARGF.current_file, T_FILE))
9935#define ARGF_FORWARD(argc, argv) do {\
9936 if (ARGF_GENERIC_INPUT_P())\
9937 return argf_forward((argc), (argv), argf);\
9939#define NEXT_ARGF_FORWARD(argc, argv) do {\
9940 if (!next_argv()) return Qnil;\
9941 ARGF_FORWARD((argc), (argv));\
9947 VALUE file = ARGF.current_file;
9961 int stdout_binmode = 0;
9972 if (ARGF.init_p == 0) {
9982 if (
NIL_P(ARGF.argv)) {
9985 else if (ARGF.next_p == -1 &&
RARRAY_LEN(ARGF.argv) > 0) {
9990 if (ARGF.next_p == 1) {
9991 if (ARGF.init_p == 1) argf_close(
argf);
9994 VALUE filename = rb_ary_shift(ARGF.argv);
9996 ARGF.filename = filename;
9997 filename = rb_str_encode_ospath(filename);
10001 if (ARGF.inplace) {
10002 rb_warn(
"Can't do inplace edit for stdio; skipping");
10008 int fr = rb_sysopen(filename, O_RDONLY, 0);
10010 if (ARGF.inplace) {
10012#ifndef NO_SAFE_RENAME
10023 if (!
NIL_P(ARGF.inplace)) {
10024 VALUE suffix = ARGF.inplace;
10028 rb_enc_get(suffix), 0,
Qnil))) {
10031#ifdef NO_SAFE_RENAME
10035 rb_warn(
"Can't rename %"PRIsVALUE
" to %"PRIsVALUE
": %s, skipping file",
10036 filename, str, strerror(errno));
10039 fr = rb_sysopen(str, O_RDONLY, 0);
10042 rb_warn(
"Can't rename %"PRIsVALUE
" to %"PRIsVALUE
": %s, skipping file",
10043 filename, str, strerror(errno));
10050#ifdef NO_SAFE_RENAME
10051 rb_fatal(
"Can't do inplace edit without backup");
10053 if (unlink(fn) < 0) {
10054 rb_warn(
"Can't remove %"PRIsVALUE
": %s, skipping file",
10055 filename, strerror(errno));
10061 fw = rb_sysopen(filename, O_WRONLY|O_CREAT|O_TRUNC, 0666);
10062#ifndef NO_SAFE_RENAME
10065 fchmod(fw, st.st_mode);
10067 chmod(fn, st.st_mode);
10069 if (st.st_uid!=st2.st_uid || st.st_gid!=st2.st_gid) {
10072 err = fchown(fw, st.st_uid, st.st_gid);
10074 err = chown(fn, st.st_uid, st.st_gid);
10076 if (err && getuid() == 0 && st2.st_uid == 0) {
10078 rb_warn(
"Can't set owner/group of %"PRIsVALUE
" to same as %"PRIsVALUE
": %s, skipping file",
10079 filename, str, strerror(errno));
10082 (void)unlink(wkfn);
10092 if (!ARGF.binmode) {
10093 fmode |= DEFAULT_TEXTMODE;
10095 ARGF.current_file = prep_io(fr, fmode,
rb_cFile, fn);
10096 if (!
NIL_P(write_io)) {
10103 if (ARGF.encs.enc) {
10104 fptr->
encs = ARGF.encs;
10105 clear_codeconv(fptr);
10108 fptr->
encs.
ecflags &= ~ECONV_NEWLINE_DECORATOR_MASK;
10109 if (!ARGF.binmode) {
10111#ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
10112 fptr->
encs.
ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
10123 else if (ARGF.next_p == -1) {
10126 if (ARGF.inplace) {
10127 rb_warn(
"Can't do inplace edit for stdio");
10131 if (ARGF.init_p == -1) ARGF.init_p = 1;
10139 long lineno = ARGF.lineno;
10142 if (!next_argv())
return Qnil;
10143 if (ARGF_GENERIC_INPUT_P()) {
10144 line = forward_current(idGets, argc, argv);
10151 line = rb_io_getline(argc, argv, ARGF.current_file);
10153 if (
NIL_P(line) && ARGF.next_p != -1) {
10159 if (!
NIL_P(line)) {
10160 ARGF.lineno = ++lineno;
10161 ARGF.last_lineno = ARGF.lineno;
10167argf_lineno_getter(
ID id,
VALUE *var)
10170 return INT2FIX(ARGF.last_lineno);
10178 ARGF.last_lineno = ARGF.lineno = n;
10182rb_reset_argf_lineno(
long n)
10184 ARGF.last_lineno = ARGF.lineno = n;
10225 if (recv ==
argf) {
10226 return argf_gets(argc, argv,
argf);
10228 return forward(
argf, idGets, argc, argv);
10254 line = argf_getline(argc, argv,
argf);
10266 return rb_f_gets(0, 0,
argf);
10270 if (!next_argv())
return Qnil;
10272 if (
NIL_P(line) && ARGF.next_p != -1) {
10278 if (!
NIL_P(line)) {
10280 ARGF.last_lineno = ARGF.lineno;
10306rb_f_readline(
int argc,
VALUE *argv,
VALUE recv)
10308 if (recv ==
argf) {
10309 return argf_readline(argc, argv,
argf);
10337 if (!next_argv()) rb_eof_error();
10338 ARGF_FORWARD(argc, argv);
10339 line = argf_gets(argc, argv,
argf);
10408rb_f_readlines(
int argc,
VALUE *argv,
VALUE recv)
10410 if (recv ==
argf) {
10411 return argf_readlines(argc, argv,
argf);
10435 long lineno = ARGF.lineno;
10438 ary = rb_ary_new();
10439 while (next_argv()) {
10440 if (ARGF_GENERIC_INPUT_P()) {
10441 lines = forward_current(
rb_intern(
"readlines"), argc, argv);
10444 lines = rb_io_readlines(argc, argv, ARGF.current_file);
10448 rb_ary_concat(ary, lines);
10450 ARGF.last_lineno = ARGF.lineno;
10485 rb_last_status_clear();
10486 port = pipe_open_s(str,
"r",
FMODE_READABLE|DEFAULT_TEXTMODE, NULL);
10490 result = read_all(fptr, remain_size(fptr),
Qnil);
10492 RFILE(port)->fptr = NULL;
10493 rb_io_fptr_finalize(fptr);
10499#ifdef HAVE_SYS_SELECT_H
10500#include <sys/select.h>
10514 if (!
NIL_P(read)) {
10519 if (READ_DATA_PENDING(fptr) || READ_CHAR_PENDING(fptr)) {
10523 if (max < fptr->fd) max = fptr->
fd;
10526 timerec.tv_sec = timerec.tv_usec = 0;
10534 if (!
NIL_P(write)) {
10540 if (max < fptr->fd) max = fptr->
fd;
10547 if (!
NIL_P(except)) {
10551 VALUE write_io = GetWriteIO(io);
10554 if (max < fptr->fd) max = fptr->
fd;
10555 if (io != write_io) {
10558 if (max < fptr->fd) max = fptr->
fd;
10573 if (!pending && n == 0)
return Qnil;
10576 rb_ary_push(res, rp?rb_ary_new():
rb_ary_new2(0));
10577 rb_ary_push(res, wp?rb_ary_new():
rb_ary_new2(0));
10578 rb_ary_push(res, ep?rb_ary_new():
rb_ary_new2(0));
10583 VALUE obj = rb_ary_entry(read, i);
10588 rb_ary_push(list, obj);
10596 VALUE obj = rb_ary_entry(write, i);
10598 VALUE write_io = GetWriteIO(io);
10601 rb_ary_push(list, obj);
10609 VALUE obj = rb_ary_entry(except, i);
10611 VALUE write_io = GetWriteIO(io);
10614 rb_ary_push(list, obj);
10616 else if (io != write_io) {
10619 rb_ary_push(list, obj);
10629 VALUE read, write, except;
10635select_call(
VALUE arg)
10639 return select_internal(p->read, p->write, p->except, p->timeout, p->fdsets);
10643select_end(
VALUE arg)
10648 for (i = 0; i < numberof(p->fdsets); ++i)
10653static VALUE sym_normal, sym_sequential, sym_random,
10654 sym_willneed, sym_dontneed, sym_noreuse;
10656#ifdef HAVE_POSIX_FADVISE
10657struct io_advise_struct {
10665io_advise_internal(
void *arg)
10667 struct io_advise_struct *ptr = arg;
10668 return posix_fadvise(ptr->fd, ptr->offset, ptr->len, ptr->advice);
10672io_advise_sym_to_const(
VALUE sym)
10674#ifdef POSIX_FADV_NORMAL
10675 if (sym == sym_normal)
10676 return INT2NUM(POSIX_FADV_NORMAL);
10679#ifdef POSIX_FADV_RANDOM
10680 if (sym == sym_random)
10681 return INT2NUM(POSIX_FADV_RANDOM);
10684#ifdef POSIX_FADV_SEQUENTIAL
10685 if (sym == sym_sequential)
10686 return INT2NUM(POSIX_FADV_SEQUENTIAL);
10689#ifdef POSIX_FADV_WILLNEED
10690 if (sym == sym_willneed)
10691 return INT2NUM(POSIX_FADV_WILLNEED);
10694#ifdef POSIX_FADV_DONTNEED
10695 if (sym == sym_dontneed)
10696 return INT2NUM(POSIX_FADV_DONTNEED);
10699#ifdef POSIX_FADV_NOREUSE
10700 if (sym == sym_noreuse)
10701 return INT2NUM(POSIX_FADV_NOREUSE);
10708do_io_advise(
rb_io_t *fptr,
VALUE advice, rb_off_t offset, rb_off_t len)
10711 struct io_advise_struct ias;
10714 num_adv = io_advise_sym_to_const(advice);
10720 if (
NIL_P(num_adv))
10724 ias.advice =
NUM2INT(num_adv);
10725 ias.offset = offset;
10728 rv = (int)rb_thread_io_blocking_region(io_advise_internal, &ias, fptr->
fd);
10729 if (rv && rv != ENOSYS) {
10736 fptr->
pathv, offset, len, advice);
10746advice_arg_check(
VALUE advice)
10751 if (advice != sym_normal &&
10752 advice != sym_sequential &&
10753 advice != sym_random &&
10754 advice != sym_willneed &&
10755 advice != sym_dontneed &&
10756 advice != sym_noreuse) {
10795rb_io_advise(
int argc,
VALUE *argv,
VALUE io)
10797 VALUE advice, offset, len;
10801 rb_scan_args(argc, argv,
"12", &advice, &offset, &len);
10802 advice_arg_check(advice);
10804 io = GetWriteIO(io);
10810#ifdef HAVE_POSIX_FADVISE
10811 return do_io_advise(fptr, advice, off, l);
10813 ((void)off, (
void)l);
10968rb_f_select(
int argc,
VALUE *argv,
VALUE obj)
10971 if (scheduler !=
Qnil) {
10974 if (!UNDEF_P(result))
return result;
10982 rb_scan_args(argc, argv,
"13", &args.read, &args.write, &args.except, &timeout);
10983 if (
NIL_P(timeout)) {
10988 args.timeout = &timerec;
10991 for (i = 0; i < numberof(args.fdsets); ++i)
10997#ifdef IOCTL_REQ_TYPE
10998 typedef IOCTL_REQ_TYPE ioctl_req_t;
11000 typedef int ioctl_req_t;
11001# define NUM2IOCTLREQ(num) ((int)NUM2LONG(num))
11012nogvl_ioctl(
void *ptr)
11014 struct ioctl_arg *arg = ptr;
11016 return (
VALUE)ioctl(arg->fd, arg->cmd, arg->narg);
11020do_ioctl(
int fd, ioctl_req_t cmd,
long narg)
11023 struct ioctl_arg arg;
11029 retval = (int)rb_thread_io_blocking_region(nogvl_ioctl, &arg, fd);
11035#define DEFAULT_IOCTL_NARG_LEN (256)
11037#if defined(__linux__) && defined(_IOC_SIZE)
11039linux_iocparm_len(ioctl_req_t cmd)
11043 if ((cmd & 0xFFFF0000) == 0) {
11045 return DEFAULT_IOCTL_NARG_LEN;
11048 len = _IOC_SIZE(cmd);
11051 if (len < DEFAULT_IOCTL_NARG_LEN)
11052 len = DEFAULT_IOCTL_NARG_LEN;
11060ioctl_narg_len(ioctl_req_t cmd)
11066#define IOCPARM_LEN(x) (((x) >> 16) & IOCPARM_MASK)
11070 len = IOCPARM_LEN(cmd);
11071#elif defined(__linux__) && defined(_IOC_SIZE)
11072 len = linux_iocparm_len(cmd);
11075 len = DEFAULT_IOCTL_NARG_LEN;
11084typedef long fcntl_arg_t;
11087typedef int fcntl_arg_t;
11091fcntl_narg_len(ioctl_req_t cmd)
11098 len =
sizeof(fcntl_arg_t);
11106#ifdef F_DUPFD_CLOEXEC
11107 case F_DUPFD_CLOEXEC:
11108 len =
sizeof(fcntl_arg_t);
11118 len =
sizeof(fcntl_arg_t);
11128 len =
sizeof(fcntl_arg_t);
11138 len =
sizeof(fcntl_arg_t);
11143 len =
sizeof(
struct f_owner_ex);
11148 len =
sizeof(
struct f_owner_ex);
11153 len =
sizeof(
struct flock);
11158 len =
sizeof(
struct flock);
11163 len =
sizeof(
struct flock);
11183 len =
sizeof(fcntl_arg_t);
11193 len =
sizeof(fcntl_arg_t);
11198 len =
sizeof(fcntl_arg_t);
11211fcntl_narg_len(ioctl_req_t cmd)
11217#define NARG_SENTINEL 17
11220setup_narg(ioctl_req_t cmd,
VALUE *argp,
long (*narg_len)(ioctl_req_t))
11231 else if (arg ==
Qtrue) {
11245 len = narg_len(cmd);
11250 if (slen < len+1) {
11257 ptr[slen - 1] = NARG_SENTINEL;
11266finish_narg(
int retval,
VALUE arg,
const rb_io_t *fptr)
11268 if (retval < 0) rb_sys_fail_path(fptr->
pathv);
11273 if (ptr[slen-1] != NARG_SENTINEL)
11275 ptr[slen-1] =
'\0';
11285 ioctl_req_t cmd = NUM2IOCTLREQ(req);
11290 narg = setup_narg(cmd, &arg, ioctl_narg_len);
11292 retval = do_ioctl(fptr->
fd, cmd, narg);
11293 return finish_narg(retval, arg, fptr);
11320 return rb_ioctl(io, req, arg);
11323#define rb_io_ioctl rb_f_notimplement
11334nogvl_fcntl(
void *ptr)
11336 struct fcntl_arg *arg = ptr;
11338#if defined(F_DUPFD)
11339 if (arg->cmd == F_DUPFD)
11342 return (
VALUE)fcntl(arg->fd, arg->cmd, arg->narg);
11346do_fcntl(
int fd,
int cmd,
long narg)
11349 struct fcntl_arg arg;
11355 retval = (int)rb_thread_io_blocking_region(nogvl_fcntl, &arg, fd);
11356 if (retval != -1) {
11358#if defined(F_DUPFD)
11361#if defined(F_DUPFD_CLOEXEC)
11362 case F_DUPFD_CLOEXEC:
11379 narg = setup_narg(cmd, &arg, fcntl_narg_len);
11381 retval = do_fcntl(fptr->
fd, cmd, narg);
11382 return finish_narg(retval, arg, fptr);
11408 return rb_fcntl(io, req, arg);
11411#define rb_io_fcntl rb_f_notimplement
11414#if defined(HAVE_SYSCALL) || defined(HAVE___SYSCALL)
11446#if SIZEOF_VOIDP == 8 && defined(HAVE___SYSCALL) && SIZEOF_INT != 8
11447# define SYSCALL __syscall
11448# define NUM2SYSCALLID(x) NUM2LONG(x)
11449# define RETVAL2NUM(x) LONG2NUM(x)
11450# if SIZEOF_LONG == 8
11451 long num, retval = -1;
11452# elif SIZEOF_LONG_LONG == 8
11453 long long num, retval = -1;
11455# error ---->> it is asserted that __syscall takes the first argument and returns retval in 64bit signed integer. <<----
11457#elif defined(__linux__)
11458# define SYSCALL syscall
11459# define NUM2SYSCALLID(x) NUM2LONG(x)
11460# define RETVAL2NUM(x) LONG2NUM(x)
11468 long num, retval = -1;
11470# define SYSCALL syscall
11471# define NUM2SYSCALLID(x) NUM2INT(x)
11472# define RETVAL2NUM(x) INT2NUM(x)
11473 int num, retval = -1;
11479 "We plan to remove a syscall function at future release. DL(Fiddle) provides safer alternative.");
11484 if (argc > numberof(arg))
11486 num = NUM2SYSCALLID(argv[0]); ++argv;
11487 for (i = argc - 1; i--; ) {
11502 retval = SYSCALL(num);
11505 retval = SYSCALL(num, arg[0]);
11508 retval = SYSCALL(num, arg[0],arg[1]);
11511 retval = SYSCALL(num, arg[0],arg[1],arg[2]);
11514 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3]);
11517 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4]);
11520 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5]);
11523 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6]);
11529 return RETVAL2NUM(retval);
11531#undef NUM2SYSCALLID
11535#define rb_f_syscall rb_f_notimplement
11539io_new_instance(
VALUE args)
11545find_encoding(
VALUE v)
11548 if (!enc)
rb_warn(
"Unsupported encoding %"PRIsVALUE
" ignored", v);
11560 enc2 = find_encoding(v1);
11569 enc = find_encoding(v2);
11576 enc = find_encoding(v2);
11582 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
11588 rb_io_ext_int_to_encs(NULL, NULL, &enc, &enc2, 0);
11589 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
11595 parse_mode_enc(
RSTRING_PTR(tmp), enc, &enc, &enc2, NULL);
11596 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
11600 rb_io_ext_int_to_encs(find_encoding(v1), NULL, &enc, &enc2, 0);
11601 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
11606 validate_enc_binmode(&fptr->
mode, ecflags, enc, enc2);
11611 clear_codeconv(fptr);
11623io_encoding_set_v(
VALUE v)
11626 io_encoding_set(arg->fptr, arg->v1, arg->v2, arg->opt);
11631pipe_pair_close(
VALUE rw)
11634 return rb_ensure(io_close, rwp[0], io_close, rwp[1]);
11717rb_io_s_pipe(
int argc,
VALUE *argv,
VALUE klass)
11719 int pipes[2], state;
11720 VALUE r, w, args[3], v1, v2;
11727 argc =
rb_scan_args(argc, argv,
"02:", &v1, &v2, &opt);
11734 r = rb_protect(io_new_instance, (
VALUE)args, &state);
11738 rb_jump_tag(state);
11742 ies_args.fptr = fptr;
11745 ies_args.opt = opt;
11746 rb_protect(io_encoding_set_v, (
VALUE)&ies_args, &state);
11750 rb_jump_tag(state);
11755 w = rb_protect(io_new_instance, (
VALUE)args, &state);
11759 rb_jump_tag(state);
11764 extract_binmode(opt, &fmode);
11771#if DEFAULT_TEXTMODE
11773 fptr->
mode &= ~FMODE_TEXTMODE;
11774 setmode(fptr->
fd, O_BINARY);
11776#if RUBY_CRLF_ENVIRONMENT
11782 fptr->
mode |= fmode;
11783#if DEFAULT_TEXTMODE
11785 fptr2->
mode &= ~FMODE_TEXTMODE;
11786 setmode(fptr2->
fd, O_BINARY);
11789 fptr2->
mode |= fmode;
11791 ret = rb_assoc_new(r, w);
11823 else if (!
NIL_P(v = rb_hash_aref(opt, sym_open_args))) {
11826 v = rb_to_array_type(v);
11831 arg->io = rb_io_open(klass, path, vmode, vperm, opt);
11835io_s_foreach(
VALUE v)
11840 if (arg->limit == 0)
11842 while (!
NIL_P(str = rb_io_getline_1(arg->rs, arg->limit, arg->chomp, arg->io))) {
11943rb_io_s_foreach(
int argc,
VALUE *argv,
VALUE self)
11946 int orig_argc = argc;
11950 argc =
rb_scan_args(argc, argv,
"12:", NULL, NULL, NULL, &opt);
11952 extract_getline_args(argc-1, argv+1, &garg);
11953 open_key_args(self, argc, argv, opt, &arg);
11955 extract_getline_opts(opt, &garg);
11956 check_getline_args(&garg.rs, &garg.limit, garg.io = arg.io);
11957 return rb_ensure(io_s_foreach, (
VALUE)&garg, rb_io_close, arg.io);
11961io_s_readlines(
VALUE v)
11964 return io_readlines(arg, arg->io);
12039rb_io_s_readlines(
int argc,
VALUE *argv,
VALUE io)
12045 argc =
rb_scan_args(argc, argv,
"12:", NULL, NULL, NULL, &opt);
12046 extract_getline_args(argc-1, argv+1, &garg);
12047 open_key_args(io, argc, argv, opt, &arg);
12049 extract_getline_opts(opt, &garg);
12050 check_getline_args(&garg.rs, &garg.limit, garg.io = arg.io);
12051 return rb_ensure(io_s_readlines, (
VALUE)&garg, rb_io_close, arg.io);
12058 return io_read(arg->argc, arg->argv, arg->io);
12068seek_before_access(
VALUE argp)
12072 return rb_io_seek(arg->io, arg->offset, arg->mode);
12132rb_io_s_read(
int argc,
VALUE *argv,
VALUE io)
12137 argc =
rb_scan_args(argc, argv,
"13:", NULL, NULL, &offset, NULL, &opt);
12138 open_key_args(io, argc, argv, opt, &arg);
12140 if (!
NIL_P(offset)) {
12144 sarg.offset = offset;
12145 sarg.mode = SEEK_SET;
12146 rb_protect(seek_before_access, (
VALUE)&sarg, &state);
12149 rb_jump_tag(state);
12151 if (arg.argc == 2) arg.argc = 1;
12171rb_io_s_binread(
int argc,
VALUE *argv,
VALUE io)
12186 convconfig.
enc = rb_ascii8bit_encoding();
12187 arg.io = rb_io_open_generic(io, argv[0], oflags, fmode, &convconfig, 0);
12190 arg.argc = (argc > 1) ? 1 : 0;
12191 if (!
NIL_P(offset)) {
12195 sarg.offset = offset;
12196 sarg.mode = SEEK_SET;
12197 rb_protect(seek_before_access, (
VALUE)&sarg, &state);
12200 rb_jump_tag(state);
12207io_s_write0(
VALUE v)
12210 return io_write(arg->io,arg->str,arg->nosync);
12214io_s_write(
int argc,
VALUE *argv,
VALUE klass,
int binary)
12216 VALUE string, offset, opt;
12220 rb_scan_args(argc, argv,
"21:", NULL, &
string, &offset, &opt);
12222 if (
NIL_P(opt)) opt = rb_hash_new();
12223 else opt = rb_hash_dup(opt);
12226 if (
NIL_P(rb_hash_aref(opt,sym_mode))) {
12227 int mode = O_WRONLY|O_CREAT;
12229 if (binary) mode |= O_BINARY;
12231 if (
NIL_P(offset)) mode |= O_TRUNC;
12232 rb_hash_aset(opt,sym_mode,
INT2NUM(mode));
12234 open_key_args(klass, argc, argv, opt, &arg);
12237 if (binary) rb_io_binmode_m(arg.io);
12241 if (!
NIL_P(offset)) {
12245 sarg.offset = offset;
12246 sarg.mode = SEEK_SET;
12247 rb_protect(seek_before_access, (
VALUE)&sarg, &state);
12250 rb_jump_tag(state);
12258 return rb_ensure(io_s_write0, (
VALUE)&warg, rb_io_close, arg.io);
12323rb_io_s_write(
int argc,
VALUE *argv,
VALUE io)
12325 return io_s_write(argc, argv, io, 0);
12343rb_io_s_binwrite(
int argc,
VALUE *argv,
VALUE io)
12345 return io_s_write(argc, argv, io, 1);
12351 rb_off_t copy_length;
12352 rb_off_t src_offset;
12356 unsigned close_src : 1;
12357 unsigned close_dst : 1;
12360 const char *syserr;
12361 const char *notimp;
12363 struct stat src_stat;
12364 struct stat dst_stat;
12365#ifdef HAVE_FCOPYFILE
12366 copyfile_state_t copyfile_state;
12371exec_interrupts(
void *arg)
12374 rb_thread_execute_interrupts(th);
12388#if defined(ERESTART)
12393 rb_thread_execute_interrupts(stp->th);
12412fiber_scheduler_wait_for(
void * _arguments)
12422# define IOWAIT_SYSCALL "poll"
12423STATIC_ASSERT(pollin_expected, POLLIN == RB_WAITFD_IN);
12424STATIC_ASSERT(pollout_expected, POLLOUT == RB_WAITFD_OUT);
12429 if (scheduler !=
Qnil) {
12432 return RTEST(args.result);
12436 if (fd == -1)
return 0;
12441 fds.events = events;
12443 int timeout_milliseconds = -1;
12446 timeout_milliseconds = (int)(timeout->tv_sec * 1000) + (int)(timeout->tv_usec / 1000);
12449 return poll(&fds, 1, timeout_milliseconds);
12452# define IOWAIT_SYSCALL "select"
12457 if (scheduler !=
Qnil) {
12460 return RTEST(args.result);
12480 case RB_WAITFD_OUT:
12484 VM_UNREACHABLE(nogvl_wait_for);
12504 ret = nogvl_wait_for(stp->th, stp->src_fptr, RB_WAITFD_IN, NULL);
12506 }
while (ret < 0 && maygvl_copy_stream_continue_p(has_gvl, stp));
12509 stp->syserr = IOWAIT_SYSCALL;
12510 stp->error_no = errno;
12522 ret = nogvl_wait_for(stp->th, stp->dst_fptr, RB_WAITFD_OUT, NULL);
12523 }
while (ret < 0 && maygvl_copy_stream_continue_p(0, stp));
12526 stp->syserr = IOWAIT_SYSCALL;
12527 stp->error_no = errno;
12533#ifdef USE_COPY_FILE_RANGE
12536simple_copy_file_range(
int in_fd, rb_off_t *in_offset,
int out_fd, rb_off_t *out_offset,
size_t count,
unsigned int flags)
12538#ifdef HAVE_COPY_FILE_RANGE
12539 return copy_file_range(in_fd, in_offset, out_fd, out_offset, count, flags);
12541 return syscall(__NR_copy_file_range, in_fd, in_offset, out_fd, out_offset, count, flags);
12550 rb_off_t copy_length, src_offset, *src_offset_ptr;
12552 if (!S_ISREG(stp->src_stat.st_mode))
12555 src_size = stp->src_stat.st_size;
12556 src_offset = stp->src_offset;
12557 if (src_offset >= (rb_off_t)0) {
12558 src_offset_ptr = &src_offset;
12561 src_offset_ptr = NULL;
12564 copy_length = stp->copy_length;
12565 if (copy_length < (rb_off_t)0) {
12566 if (src_offset < (rb_off_t)0) {
12567 rb_off_t current_offset;
12569 current_offset = lseek(stp->src_fptr->
fd, 0, SEEK_CUR);
12570 if (current_offset < (rb_off_t)0 && errno) {
12571 stp->syserr =
"lseek";
12572 stp->error_no = errno;
12573 return (
int)current_offset;
12575 copy_length = src_size - current_offset;
12578 copy_length = src_size - src_offset;
12582 retry_copy_file_range:
12583# if SIZEOF_OFF_T > SIZEOF_SIZE_T
12585 ss = (copy_length > (rb_off_t)SSIZE_MAX) ? SSIZE_MAX : (ssize_t)copy_length;
12587 ss = (ssize_t)copy_length;
12589 ss = simple_copy_file_range(stp->src_fptr->
fd, src_offset_ptr, stp->dst_fptr->
fd, NULL, ss, 0);
12593 if (0 < copy_length) {
12594 goto retry_copy_file_range;
12598 if (maygvl_copy_stream_continue_p(0, stp)) {
12599 goto retry_copy_file_range;
12613#if EWOULDBLOCK != EAGAIN
12617 int ret = nogvl_copy_stream_wait_write(stp);
12618 if (ret < 0)
return ret;
12620 goto retry_copy_file_range;
12624 int flags = fcntl(stp->dst_fptr->
fd, F_GETFL);
12626 if (flags != -1 && flags & O_APPEND) {
12632 stp->syserr =
"copy_file_range";
12633 stp->error_no = errno;
12640#ifdef HAVE_FCOPYFILE
12644 rb_off_t cur, ss = 0;
12645 const rb_off_t src_offset = stp->src_offset;
12648 if (stp->copy_length >= (rb_off_t)0) {
12653 if (!S_ISREG(stp->src_stat.st_mode))
12656 if (!S_ISREG(stp->dst_stat.st_mode))
12658 if (lseek(stp->dst_fptr->
fd, 0, SEEK_CUR) > (rb_off_t)0)
12660 if (fcntl(stp->dst_fptr->
fd, F_GETFL) & O_APPEND) {
12663 rb_off_t end = lseek(stp->dst_fptr->
fd, 0, SEEK_END);
12664 lseek(stp->dst_fptr->
fd, 0, SEEK_SET);
12665 if (end > (rb_off_t)0)
return 0;
12668 if (src_offset > (rb_off_t)0) {
12673 cur = lseek(stp->src_fptr->
fd, 0, SEEK_CUR);
12674 if (cur < (rb_off_t)0 && errno) {
12675 stp->error_no = errno;
12680 r = lseek(stp->src_fptr->
fd, src_offset, SEEK_SET);
12681 if (r < (rb_off_t)0 && errno) {
12682 stp->error_no = errno;
12687 stp->copyfile_state = copyfile_state_alloc();
12688 ret = fcopyfile(stp->src_fptr->
fd, stp->dst_fptr->
fd, stp->copyfile_state, COPYFILE_DATA);
12689 copyfile_state_get(stp->copyfile_state, COPYFILE_STATE_COPIED, &ss);
12693 if (src_offset > (rb_off_t)0) {
12697 r = lseek(stp->src_fptr->
fd, cur, SEEK_SET);
12698 if (r < (rb_off_t)0 && errno) {
12699 stp->error_no = errno;
12711 stp->syserr =
"fcopyfile";
12712 stp->error_no = errno;
12719#ifdef HAVE_SENDFILE
12722# define USE_SENDFILE
12724# ifdef HAVE_SYS_SENDFILE_H
12725# include <sys/sendfile.h>
12729simple_sendfile(
int out_fd,
int in_fd, rb_off_t *offset, rb_off_t count)
12731 return sendfile(out_fd, in_fd, offset, (
size_t)count);
12734# elif 0 || defined(__APPLE__)
12738# define USE_SENDFILE
12741simple_sendfile(
int out_fd,
int in_fd, rb_off_t *offset, rb_off_t count)
12744 rb_off_t pos = offset ? *offset : lseek(in_fd, 0, SEEK_CUR);
12747 r = sendfile(in_fd, out_fd, pos, &count, NULL, 0);
12750 r = sendfile(in_fd, out_fd, pos, (
size_t)count, NULL, &sbytes, 0);
12752 if (r != 0 && sbytes == 0)
return r;
12757 lseek(in_fd, sbytes, SEEK_CUR);
12759 return (ssize_t)sbytes;
12772 rb_off_t copy_length;
12773 rb_off_t src_offset;
12776 if (!S_ISREG(stp->src_stat.st_mode))
12779 src_size = stp->src_stat.st_size;
12781 if ((stp->dst_stat.st_mode & S_IFMT) != S_IFSOCK)
12785 src_offset = stp->src_offset;
12786 use_pread = src_offset >= (rb_off_t)0;
12788 copy_length = stp->copy_length;
12789 if (copy_length < (rb_off_t)0) {
12791 copy_length = src_size - src_offset;
12795 cur = lseek(stp->src_fptr->
fd, 0, SEEK_CUR);
12796 if (cur < (rb_off_t)0 && errno) {
12797 stp->syserr =
"lseek";
12798 stp->error_no = errno;
12801 copy_length = src_size - cur;
12806# if SIZEOF_OFF_T > SIZEOF_SIZE_T
12808 ss = (copy_length > (rb_off_t)SSIZE_MAX) ? SSIZE_MAX : (ssize_t)copy_length;
12810 ss = (ssize_t)copy_length;
12813 ss = simple_sendfile(stp->dst_fptr->
fd, stp->src_fptr->
fd, &src_offset, ss);
12816 ss = simple_sendfile(stp->dst_fptr->
fd, stp->src_fptr->
fd, NULL, ss);
12821 if (0 < copy_length) {
12822 goto retry_sendfile;
12826 if (maygvl_copy_stream_continue_p(0, stp))
12827 goto retry_sendfile;
12840#if EWOULDBLOCK != EAGAIN
12853 ret = maygvl_copy_stream_wait_read(0, stp);
12854 if (ret < 0)
return ret;
12856 ret = nogvl_copy_stream_wait_write(stp);
12857 if (ret < 0)
return ret;
12859 goto retry_sendfile;
12861 stp->syserr =
"sendfile";
12862 stp->error_no = errno;
12870maygvl_read(
int has_gvl,
rb_io_t *fptr,
void *buf,
size_t count)
12873 return rb_io_read_memory(fptr, buf, count);
12875 return read(fptr->
fd, buf, count);
12879maygvl_copy_stream_read(
int has_gvl,
struct copy_stream_struct *stp,
char *buf,
size_t len, rb_off_t offset)
12883 if (offset < (rb_off_t)0) {
12884 ss = maygvl_read(has_gvl, stp->src_fptr, buf, len);
12888 ss = pread(stp->src_fptr->
fd, buf, len, offset);
12890 stp->notimp =
"pread";
12898 if (maygvl_copy_stream_continue_p(has_gvl, stp))
12902#if EWOULDBLOCK != EAGAIN
12906 int ret = maygvl_copy_stream_wait_read(has_gvl, stp);
12907 if (ret < 0)
return ret;
12912 stp->notimp =
"pread";
12916 stp->syserr = offset < (rb_off_t)0 ?
"read" :
"pread";
12917 stp->error_no = errno;
12928 ss = write(stp->dst_fptr->
fd, buf+off, len);
12930 if (maygvl_copy_stream_continue_p(0, stp))
12932 if (io_again_p(errno)) {
12933 int ret = nogvl_copy_stream_wait_write(stp);
12934 if (ret < 0)
return ret;
12937 stp->syserr =
"write";
12938 stp->error_no = errno;
12955 rb_off_t copy_length;
12956 rb_off_t src_offset;
12960 copy_length = stp->copy_length;
12961 use_eof = copy_length < (rb_off_t)0;
12962 src_offset = stp->src_offset;
12963 use_pread = src_offset >= (rb_off_t)0;
12965 if (use_pread && stp->close_src) {
12968 r = lseek(stp->src_fptr->
fd, src_offset, SEEK_SET);
12969 if (r < (rb_off_t)0 && errno) {
12970 stp->syserr =
"lseek";
12971 stp->error_no = errno;
12974 src_offset = (rb_off_t)-1;
12978 while (use_eof || 0 < copy_length) {
12979 if (!use_eof && copy_length < (rb_off_t)
sizeof(buf)) {
12980 len = (size_t)copy_length;
12986 ss = maygvl_copy_stream_read(0, stp, buf, len, src_offset);
12991 ss = maygvl_copy_stream_read(0, stp, buf, len, (rb_off_t)-1);
12996 ret = nogvl_copy_stream_write(stp, buf, ss);
13006nogvl_copy_stream_func(
void *arg)
13009#if defined(USE_SENDFILE) || defined(USE_COPY_FILE_RANGE) || defined(HAVE_FCOPYFILE)
13013#ifdef USE_COPY_FILE_RANGE
13014 ret = nogvl_copy_file_range(stp);
13019#ifdef HAVE_FCOPYFILE
13020 ret = nogvl_fcopyfile(stp);
13026 ret = nogvl_copy_stream_sendfile(stp);
13031 nogvl_copy_stream_read_write(stp);
13033#if defined(USE_SENDFILE) || defined(USE_COPY_FILE_RANGE) || defined(HAVE_FCOPYFILE)
13040copy_stream_fallback_body(
VALUE arg)
13043 const int buflen = 16*1024;
13046 rb_off_t rest = stp->copy_length;
13047 rb_off_t off = stp->src_offset;
13048 ID read_method = id_readpartial;
13050 if (!stp->src_fptr) {
13052 read_method = id_read;
13059 if (stp->copy_length < (rb_off_t)0) {
13067 l = buflen < rest ? buflen : (long)rest;
13069 if (!stp->src_fptr) {
13072 if (read_method == id_read &&
NIL_P(rc))
13078 ss = maygvl_copy_stream_read(1, stp,
RSTRING_PTR(buf), l, off);
13084 if (off >= (rb_off_t)0)
13089 stp->total += numwrote;
13091 if (read_method == id_read &&
RSTRING_LEN(buf) == 0) {
13102 if (!stp->src_fptr && stp->src_offset >= (rb_off_t)0) {
13112copy_stream_body(
VALUE arg)
13115 VALUE src_io = stp->src, dst_io = stp->dst;
13116 const int common_oflags = 0
13126 if (src_io ==
argf ||
13130 stp->src_fptr = NULL;
13135 if (!
NIL_P(tmp_io)) {
13142 args[1] =
INT2NUM(O_RDONLY|common_oflags);
13145 stp->close_src = 1;
13150 stat_ret = fstat(stp->src_fptr->
fd, &stp->src_stat);
13151 if (stat_ret < 0) {
13152 stp->syserr =
"fstat";
13153 stp->error_no = errno;
13158 if (dst_io ==
argf ||
13162 stp->dst_fptr = NULL;
13167 if (!
NIL_P(tmp_io)) {
13168 dst_io = GetWriteIO(tmp_io);
13174 args[1] =
INT2NUM(O_WRONLY|O_CREAT|O_TRUNC|common_oflags);
13178 stp->close_dst = 1;
13181 dst_io = GetWriteIO(dst_io);
13187 stat_ret = fstat(stp->dst_fptr->
fd, &stp->dst_stat);
13188 if (stat_ret < 0) {
13189 stp->syserr =
"fstat";
13190 stp->error_no = errno;
13197 SET_BINARY_MODE_WITH_SEEK_CUR(stp->src_fptr);
13200 io_ascii8bit_binmode(stp->dst_fptr);
13202 if (stp->src_offset < (rb_off_t)0 && stp->src_fptr && stp->src_fptr->
rbuf.
len) {
13203 size_t len = stp->src_fptr->
rbuf.
len;
13205 if (stp->copy_length >= (rb_off_t)0 && stp->copy_length < (rb_off_t)len) {
13206 len = (size_t)stp->copy_length;
13210 read_buffered_data(
RSTRING_PTR(str), len, stp->src_fptr);
13211 if (stp->dst_fptr) {
13213 rb_sys_fail_on_write(stp->dst_fptr);
13219 if (stp->copy_length >= (rb_off_t)0)
13220 stp->copy_length -= len;
13223 if (stp->dst_fptr && io_fflush(stp->dst_fptr) < 0) {
13227 if (stp->copy_length == 0)
13230 if (stp->src_fptr == NULL || stp->dst_fptr == NULL) {
13231 return copy_stream_fallback(stp);
13239copy_stream_finalize(
VALUE arg)
13243#ifdef HAVE_FCOPYFILE
13244 if (stp->copyfile_state) {
13245 copyfile_state_free(stp->copyfile_state);
13249 if (stp->close_src) {
13250 rb_io_close_m(stp->src);
13252 if (stp->close_dst) {
13253 rb_io_close_m(stp->dst);
13316rb_io_s_copy_stream(
int argc,
VALUE *argv,
VALUE io)
13318 VALUE src, dst, length, src_offset;
13323 rb_scan_args(argc, argv,
"22", &src, &dst, &length, &src_offset);
13328 st.src_fptr = NULL;
13329 st.dst_fptr = NULL;
13332 st.copy_length = (rb_off_t)-1;
13334 st.copy_length =
NUM2OFFT(length);
13336 if (
NIL_P(src_offset))
13337 st.src_offset = (rb_off_t)-1;
13339 st.src_offset =
NUM2OFFT(src_offset);
13358rb_io_external_encoding(
VALUE io)
13363 return rb_enc_from_encoding(fptr->
encs.
enc2);
13367 return rb_enc_from_encoding(fptr->
encs.
enc);
13370 return rb_enc_from_encoding(io_read_encoding(fptr));
13386rb_io_internal_encoding(
VALUE io)
13391 return rb_enc_from_encoding(io_read_encoding(fptr));
13419rb_io_set_encoding(
int argc,
VALUE *argv,
VALUE io)
13425 return forward(io, id_set_encoding, argc, argv);
13428 argc =
rb_scan_args(argc, argv,
"11:", &v1, &v2, &opt);
13430 io_encoding_set(fptr, v1, v2, opt);
13435rb_stdio_set_default_encoding(
void)
13440 if (isatty(fileno(stdin))) {
13442 rb_encoding *internal = rb_default_internal_encoding();
13443 if (!internal) internal = rb_default_external_encoding();
13445 rb_enc_from_encoding(external),
13446 rb_enc_from_encoding(internal),
13451 rb_io_set_encoding(1, &val,
rb_stdin);
13452 rb_io_set_encoding(1, &val,
rb_stdout);
13453 rb_io_set_encoding(1, &val,
rb_stderr);
13457global_argf_p(
VALUE arg)
13459 return arg ==
argf;
13462typedef VALUE (*argf_encoding_func)(
VALUE io);
13465argf_encoding(
VALUE argf, argf_encoding_func func)
13467 if (!
RTEST(ARGF.current_file)) {
13468 return rb_enc_default_external();
13492 return argf_encoding(
argf, rb_io_external_encoding);
13511 return argf_encoding(
argf, rb_io_internal_encoding);
13550 if (!next_argv()) {
13553 rb_io_set_encoding(argc, argv, ARGF.current_file);
13555 ARGF.encs = fptr->
encs;
13574 if (!next_argv()) {
13577 ARGF_FORWARD(0, 0);
13578 return rb_io_tell(ARGF.current_file);
13591 if (!next_argv()) {
13594 ARGF_FORWARD(argc, argv);
13595 return rb_io_seek_m(argc, argv, ARGF.current_file);
13612 if (!next_argv()) {
13615 ARGF_FORWARD(1, &offset);
13616 return rb_io_set_pos(ARGF.current_file, offset);
13637 if (!next_argv()) {
13640 ARGF_FORWARD(0, 0);
13641 old_lineno =
RFILE(ARGF.current_file)->fptr->lineno;
13642 ret = rb_io_rewind(ARGF.current_file);
13643 if (!global_argf_p(
argf)) {
13644 ARGF.last_lineno = ARGF.lineno -= old_lineno;
13662 if (!next_argv()) {
13665 ARGF_FORWARD(0, 0);
13666 return rb_io_fileno(ARGF.current_file);
13685 ARGF_FORWARD(0, 0);
13686 return ARGF.current_file;
13711 if (
RTEST(ARGF.current_file)) {
13712 if (ARGF.init_p == 0)
return Qtrue;
13714 ARGF_FORWARD(0, 0);
13773 VALUE tmp, str, length;
13777 if (!
NIL_P(length)) {
13787 if (!next_argv()) {
13790 if (ARGF_GENERIC_INPUT_P()) {
13791 tmp = argf_forward(argc, argv,
argf);
13794 tmp = io_read(argc, argv, ARGF.current_file);
13796 if (
NIL_P(str)) str = tmp;
13799 if (ARGF.next_p != -1) {
13805 else if (argc >= 1) {
13822argf_forward_call(
VALUE arg)
13825 argf_forward(p->argc, p->argv, p->argf);
13855 return argf_getpartial(argc, argv,
argf,
Qnil, 0);
13876 return argf_getpartial(argc, argv,
argf, opts, 1);
13882 VALUE tmp, str, length;
13890 no_exception = no_exception_p(opts);
13892 if (!next_argv()) {
13898 if (ARGF_GENERIC_INPUT_P()) {
13908 tmp = io_getpartial(argc, argv, ARGF.current_file, no_exception, nonblock);
13911 if (ARGF.next_p == -1) {
13912 return io_nonblock_eof(no_exception);
13917 return io_nonblock_eof(no_exception);
13955 if (!next_argv())
return Qnil;
13956 if (ARGF_GENERIC_INPUT_P()) {
13957 ch = forward_current(
rb_intern(
"getc"), 0, 0);
13960 ch = rb_io_getc(ARGF.current_file);
13962 if (
NIL_P(ch) && ARGF.next_p != -1) {
13995 if (!next_argv())
return Qnil;
13997 ch = forward_current(
rb_intern(
"getbyte"), 0, 0);
14002 if (
NIL_P(ch) && ARGF.next_p != -1) {
14035 if (!next_argv()) rb_eof_error();
14037 ch = forward_current(
rb_intern(
"getc"), 0, 0);
14040 ch = rb_io_getc(ARGF.current_file);
14042 if (
NIL_P(ch) && ARGF.next_p != -1) {
14074 NEXT_ARGF_FORWARD(0, 0);
14075 c = argf_getbyte(
argf);
14082#define FOREACH_ARGF() while (next_argv())
14087 const VALUE current = ARGF.current_file;
14089 if (ARGF.init_p == -1 || current != ARGF.current_file) {
14095#define ARGF_block_call(mid, argc, argv, func, argf) \
14096 rb_block_call_kw(ARGF.current_file, mid, argc, argv, \
14097 func, argf, rb_keyword_given_p())
14102 VALUE ret = ARGF_block_call(mid, argc, argv, argf_block_call_i,
argf);
14103 if (!UNDEF_P(ret)) ARGF.next_p = 1;
14109 if (!global_argf_p(
argf)) {
14110 ARGF.last_lineno = ++ARGF.lineno;
14112 return argf_block_call_i(i,
argf, argc, argv, blockarg);
14118 VALUE ret = ARGF_block_call(mid, argc, argv, argf_block_call_line_i,
argf);
14119 if (!UNDEF_P(ret)) ARGF.next_p = 1;
14167 argf_block_call_line(
rb_intern(
"each_line"), argc, argv,
argf);
14281 return ARGF.filename;
14285argf_filename_getter(
ID id,
VALUE *var)
14287 return argf_filename(*var);
14312 return ARGF.current_file;
14331 ARGF_FORWARD(0, 0);
14352 return RBOOL(ARGF.binmode);
14372 if (ARGF.init_p && ARGF.next_p == 0) {
14401 if (ARGF.next_p != -1) {
14419 ARGF_FORWARD(0, 0);
14420 return rb_io_closed(ARGF.current_file);
14446 if (!ARGF.inplace)
return Qnil;
14454 return argf_inplace_mode_get(*var);
14485 ARGF.inplace =
Qnil;
14496 argf_inplace_mode_set(*var, val);
14500ruby_set_inplace_mode(
const char *suffix)
14526argf_argv_getter(
ID id,
VALUE *var)
14528 return argf_argv(*var);
14547 if (!
RTEST(ARGF.current_file)) {
14550 return GetWriteIO(ARGF.current_file);
14577 case RB_IO_WAIT_WRITABLE:
14580 c = rb_eEAGAINWaitWritable;
14582#if EAGAIN != EWOULDBLOCK
14584 c = rb_eEWOULDBLOCKWaitWritable;
14588 c = rb_eEINPROGRESSWaitWritable;
14594 case RB_IO_WAIT_READABLE:
14597 c = rb_eEAGAINWaitReadable;
14599#if EAGAIN != EWOULDBLOCK
14601 c = rb_eEWOULDBLOCKWaitReadable;
14605 c = rb_eEINPROGRESSWaitReadable;
14612 rb_bug(
"invalid read/write type passed to rb_readwrite_sys_fail: %d", waiting);
14618get_LAST_READ_LINE(
ID _x,
VALUE *_y)
15270#include <sys/cygwin.h>
15271 static struct __cygwin_perfile pf[] =
15273 {
"", O_RDONLY | O_BINARY},
15274 {
"", O_WRONLY | O_BINARY},
15275 {
"", O_RDWR | O_BINARY},
15276 {
"", O_APPEND | O_BINARY},
15279 cygwin_internal(CW_PERFILE, pf);
15330#if EAGAIN == EWOULDBLOCK
15331 rb_eEWOULDBLOCKWaitReadable = rb_eEAGAINWaitReadable;
15334 rb_eEWOULDBLOCKWaitWritable = rb_eEAGAINWaitWritable;
15376 rb_output_fs =
Qnil;
15388 rb_gvar_ractor_local(
"$_");
15505 rb_gvar_ractor_local(
"$stdin");
15506 rb_gvar_ractor_local(
"$stdout");
15507 rb_gvar_ractor_local(
"$>");
15508 rb_gvar_ractor_local(
"$stderr");
15595 rb_define_method(rb_cARGF,
"external_encoding", argf_external_encoding, 0);
15596 rb_define_method(rb_cARGF,
"internal_encoding", argf_internal_encoding, 0);
15615 rb_gvar_ractor_local(
"$-i");
15619#if defined (_WIN32) || defined(__CYGWIN__)
15620 atexit(pipe_atexit);
15632 sym_encoding =
ID2SYM(rb_id_encoding());
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_method(klass, mid, func, arity)
Defines klass#mid.
#define rb_define_singleton_method(klass, mid, func, arity)
Defines klass.mid.
#define rb_define_global_function(mid, func, arity)
Defines rb_mKernel #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.
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.
#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 rb_str_cat2
Old name of rb_str_cat_cstr.
#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 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 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_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.
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.
static const char * rb_enc_name(rb_encoding *enc)
Queries the (canonical) name of the passed encoding.
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.
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.
static int rb_enc_mbminlen(rb_encoding *enc)
Queries the minimum number of bytes that the passed encoding needs to represent a character.
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.
const char * rb_econv_asciicompat_encoding(const char *encname)
Queries the passed encoding's corresponding ASCII compatible encoding.
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.
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_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.
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.
#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.
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_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_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...
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.
#define rb_str_new(str, len)
Allocates an instance of rb_cString.
#define rb_str_buf_cat
Just another name of rb_str_cat.
#define rb_usascii_str_new(str, len)
Identical to rb_str_new, except it generates a string of "US ASCII" encoding.
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_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.
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_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_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".
#define rb_str_new_cstr(str)
Identical to rb_str_new, except it assumes the passed pointer is a pointer to a C string.
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.
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().
ID rb_intern(const char *name)
Finds or creates a symbol of the given name.
#define RB_ID2SYM
Just another name of rb_id2sym.
const char * rb_id2name(ID id)
Retrieves the name mapped to the given id.
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_const(VALUE klass, const char *name, VALUE val)
Defines a Ruby level constant under a namespace.
#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_timeout(VALUE io)
Get the timeout associated with the specified io object.
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.
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.
FILE * rb_fdopen(int fd, const char *modestr)
Identical to rb_io_stdio_file(), except it takes file descriptors instead of Ruby's IO.
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.
FILE * rb_io_stdio_file(rb_io_t *fptr)
Finds or creates a stdio's file structure from a Ruby's one.
#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.
VALUE rb_eIOTimeoutError
Indicates that a timeout has occurred while performing an IO operation.
#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".
VALUE rb_io_check_io(VALUE io)
Try converting an object to its IO representation using its to_io method, if any.
VALUE rb_io_set_timeout(VALUE io, VALUE timeout)
Set the timeout associated with the specified io object.
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)
Instructs the OS to put its internal file structure into "nonblocking 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.
rb_io_event_t
Type of events that an IO can wait.
@ 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.
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.
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.
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.
void rb_define_hooked_variable(const char *q, VALUE *w, type *e, void_type *r)
Define a function-backended global variable.
void rb_define_virtual_variable(const char *q, type *w, void_type *e)
Define a function-backended global variable.
VALUE rb_rescue2(type *q, VALUE w, type *e, VALUE r,...)
An equivalent of rescue clause.
VALUE rb_ensure(type *q, VALUE w, type *e, VALUE r)
An equivalent of ensure clause.
#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_isset
Queries if the given fd is in the rb_fdset_t.
#define rb_fd_select
Waits for multiple file descriptors at once.
#define rb_fd_init
Initialises the :given :rb_fdset_t.
#define rb_fd_set
Sets the given fd to the rb_fdset_t.
#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.
#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.
static char * RSTRING_PTR(VALUE str)
Queries the contents pointer 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)
Non-blocking wait until the passed IO is ready for reading.
VALUE rb_fiber_scheduler_io_wait(VALUE scheduler, VALUE io, VALUE events, VALUE timeout)
Non-blocking 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_io_selectv(VALUE scheduler, int argc, VALUE *argv)
Non-blocking version of IO.select, argv variant.
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)
Non-blocking 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)
Non-blocking 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)
Non-blocking 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.
static bool RB_TEST(VALUE obj)
Emulates Ruby's "if" statement.
#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.
Decomposed encoding flags (e.g.
rb_encoding * enc2
External encoding.
VALUE ecopts
Flags as Ruby hash.
rb_encoding * enc
Internal encoding.
Ruby's IO, metadata and buffers.
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.
struct rb_io_enc_t encs
Decomposed encoding flags.
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
VALUE timeout
The timeout associated with this IO when performing blocking operations.
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 bool RB_SYMBOL_P(VALUE obj)
Queries if the object is an instance of rb_cSymbol.
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.