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);
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);
1152 else if (ready == 0) {
1162internal_read_func(
void *ptr)
1167 if (iis->timeout && !iis->nonblock) {
1168 if (io_internal_wait(iis->th, iis->fptr, 0, RB_WAITFD_IN, iis->timeout) == -1) {
1174 result = read(iis->fd, iis->buf, iis->capa);
1176 if (result < 0 && !iis->nonblock) {
1177 if (io_again_p(errno)) {
1178 if (io_internal_wait(iis->th, iis->fptr, errno, RB_WAITFD_IN, iis->timeout) == -1) {
1190#if defined __APPLE__
1191# define do_write_retry(code) do {result = code;} while (result == -1 && errno == EPROTOTYPE)
1193# define do_write_retry(code) result = code
1197internal_write_func(
void *ptr)
1202 if (iis->timeout && !iis->nonblock) {
1203 if (io_internal_wait(iis->th, iis->fptr, 0, RB_WAITFD_OUT, iis->timeout) == -1) {
1209 do_write_retry(write(iis->fd, iis->buf, iis->capa));
1211 if (result < 0 && !iis->nonblock) {
1213 if (io_again_p(e)) {
1214 if (io_internal_wait(iis->th, iis->fptr, errno, RB_WAITFD_OUT, iis->timeout) == -1) {
1228internal_writev_func(
void *ptr)
1230 struct io_internal_writev_struct *iis = ptr;
1233 if (iis->timeout && !iis->nonblock) {
1234 if (io_internal_wait(iis->th, iis->fptr, 0, RB_WAITFD_OUT, iis->timeout) == -1) {
1240 do_write_retry(writev(iis->fd, iis->iov, iis->iovcnt));
1242 if (result < 0 && !iis->nonblock) {
1243 if (io_again_p(errno)) {
1244 if (io_internal_wait(iis->th, iis->fptr, errno, RB_WAITFD_OUT, iis->timeout) == -1) {
1258rb_io_read_memory(
rb_io_t *fptr,
void *buf,
size_t count)
1261 if (scheduler !=
Qnil) {
1264 if (!UNDEF_P(result)) {
1280 struct timeval timeout_storage;
1284 iis.timeout = &timeout_storage;
1287 return (ssize_t)rb_thread_io_blocking_region(internal_read_func, &iis, fptr->
fd);
1291rb_io_write_memory(
rb_io_t *fptr,
const void *buf,
size_t count)
1294 if (scheduler !=
Qnil) {
1297 if (!UNDEF_P(result)) {
1313 struct timeval timeout_storage;
1317 iis.timeout = &timeout_storage;
1320 return (ssize_t)rb_thread_io_blocking_region(internal_write_func, &iis, fptr->
fd);
1325rb_writev_internal(
rb_io_t *fptr,
const struct iovec *iov,
int iovcnt)
1327 if (!iovcnt)
return 0;
1330 if (scheduler !=
Qnil) {
1334 if (!UNDEF_P(result)) {
1339 struct io_internal_writev_struct iis = {
1350 struct timeval timeout_storage;
1354 iis.timeout = &timeout_storage;
1357 return (ssize_t)rb_thread_io_blocking_region(internal_writev_func, &iis, fptr->
fd);
1362io_flush_buffer_sync(
void *arg)
1384io_flush_buffer_async(
VALUE arg)
1387 return rb_thread_io_blocking_region(io_flush_buffer_sync, fptr, fptr->
fd);
1394 return (
int)io_flush_buffer_async((
VALUE)fptr);
1409 while (fptr->
wbuf.
len > 0 && io_flush_buffer(fptr) != 0) {
1424 if (scheduler !=
Qnil) {
1434 if (NIL_OR_UNDEF_P(timeout)) {
1438 if (timeout !=
Qnil) {
1443 int ready = rb_thread_wait_for_single_fd(fptr->
fd,
RB_NUM2INT(events), tv);
1463 return prep_io(fd, FMODE_PREP,
rb_cIO, NULL);
1467io_wait_for_single_fd(
int fd,
int events,
struct timeval *timeout)
1471 if (scheduler !=
Qnil) {
1477 return rb_thread_wait_for_single_fd(fd, events, timeout);
1483 io_fd_check_closed(f);
1489#if defined(ERESTART)
1496#if EWOULDBLOCK != EAGAIN
1499 if (scheduler !=
Qnil) {
1517 io_fd_check_closed(f);
1523#if defined(ERESTART)
1539#if EWOULDBLOCK != EAGAIN
1542 if (scheduler !=
Qnil) {
1560 return io_wait_for_single_fd(fd, events, timeout);
1594#if defined(ERESTART)
1604#if EWOULDBLOCK != EAGAIN
1621 if (
RTEST(result)) {
1634 if (
RTEST(result)) {
1646 const char *senc, *denc;
1653 ecflags = fptr->
encs.
ecflags & ~ECONV_NEWLINE_DECORATOR_READ_MASK;
1713io_binwrite_string_internal(
rb_io_t *fptr,
const char *ptr,
long length)
1716 struct iovec iov[2];
1719 iov[0].iov_len = fptr->
wbuf.
len;
1720 iov[1].iov_base = (
void*)ptr;
1721 iov[1].iov_len = length;
1723 ssize_t result = rb_writev_internal(fptr, iov, 2);
1728 if (result >= fptr->
wbuf.
len) {
1736 fptr->
wbuf.
off += (int)result;
1737 fptr->
wbuf.
len -= (int)result;
1745 return rb_io_write_memory(fptr, ptr, length);
1750io_binwrite_string_internal(
rb_io_t *fptr,
const char *ptr,
long length)
1752 long remaining = length;
1755 if (fptr->
wbuf.
len+length <= fptr->wbuf.capa) {
1762 fptr->
wbuf.
len += (int)length;
1769 if (io_fflush(fptr) < 0) {
1774 if (remaining == 0) {
1780 return rb_io_write_memory(fptr, ptr, length);
1785io_binwrite_string(
VALUE arg)
1789 const char *ptr = p->ptr;
1790 size_t remaining = p->length;
1794 ssize_t result = io_binwrite_string_internal(p->fptr, ptr, remaining);
1800 else if (result > 0) {
1801 if ((
size_t)result == remaining)
break;
1803 remaining -= result;
1819io_allocate_write_buffer(
rb_io_t *fptr,
int sync)
1824 fptr->
wbuf.
capa = IO_WBUF_CAPA_MIN;
1835io_binwrite_requires_flush_write(
rb_io_t *fptr,
long len,
int nosync)
1850io_binwrite(
VALUE str,
const char *ptr,
long len,
rb_io_t *fptr,
int nosync)
1852 if (len <= 0)
return len;
1857 io_allocate_write_buffer(fptr, !nosync);
1859 if (io_binwrite_requires_flush_write(fptr, len, nosync)) {
1871 return io_binwrite_string((
VALUE)&arg);
1888# define MODE_BTMODE(a,b,c) ((fmode & FMODE_BINMODE) ? (b) : \
1889 (fmode & FMODE_TEXTMODE) ? (c) : (a))
1891#define MODE_BTXMODE(a, b, c, d, e, f) ((fmode & FMODE_EXCL) ? \
1892 MODE_BTMODE(d, e, f) : \
1893 MODE_BTMODE(a, b, c))
1898 if (NEED_WRITECONV(fptr)) {
1900 SET_BINARY_MODE(fptr);
1902 make_writeconv(fptr);
1905#define fmode (fptr->mode)
1908 else if (MODE_BTMODE(DEFAULT_TEXTMODE,0,1) && !
rb_enc_asciicompat(rb_enc_get(str))) {
1909 rb_raise(
rb_eArgError,
"ASCII incompatible string written for text mode IO without encoding conversion: %s",
1916 common_encoding = rb_enc_from_encoding(fptr->
encs.
enc2);
1917 else if (fptr->
encs.
enc != rb_ascii8bit_encoding())
1918 common_encoding = rb_enc_from_encoding(fptr->
encs.
enc);
1921 if (!
NIL_P(common_encoding)) {
1932#if RUBY_CRLF_ENVIRONMENT
1933#define fmode (fptr->mode)
1934 else if (MODE_BTMODE(DEFAULT_TEXTMODE,0,1)) {
1937 setmode(fptr->
fd, O_BINARY);
1940 setmode(fptr->
fd, O_TEXT);
1943 rb_raise(
rb_eArgError,
"ASCII incompatible string written for text mode IO without encoding conversion: %s",
1962 long len = rb_w32_write_console(str, fptr->
fd);
1963 if (len > 0)
return len;
1967 str = do_writeconv(str, fptr, &converted);
1971 tmp = rb_str_tmp_frozen_acquire(str);
1973 n = io_binwrite(tmp, ptr, len, fptr, nosync);
1974 rb_str_tmp_frozen_release(str, tmp);
1986 return (ssize_t)io_binwrite(0, buf, (
long)size, fptr, 0);
1996 io = GetWriteIO(io);
2011 n = io_fwrite(str, fptr, nosync);
2012 if (n < 0L) rb_sys_fail_on_write(fptr);
2018struct binwritev_arg {
2026io_binwritev_internal(
VALUE arg)
2028 struct binwritev_arg *p = (
struct binwritev_arg *)arg;
2030 size_t remaining = p->total;
2034 struct iovec *iov = p->iov;
2035 int iovcnt = p->iovcnt;
2038 long result = rb_writev_internal(fptr, iov, iovcnt);
2043 if (offset < (
size_t)fptr->
wbuf.
len) {
2048 offset -= (size_t)fptr->
wbuf.
len;
2054 if (offset == p->total) {
2058 while (result >= (ssize_t)iov->iov_len) {
2060 result -= iov->iov_len;
2070 iov->iov_base = (
char *)iov->iov_base + result;
2071 iov->iov_len -= result;
2085io_binwritev(
struct iovec *iov,
int iovcnt,
rb_io_t *fptr)
2090 if (iovcnt == 0)
return 0;
2093 for (
int i = 1; i < iovcnt; i++) total += iov[i].iov_len;
2095 io_allocate_write_buffer(fptr, 1);
2101 if (offset + total <= (
size_t)fptr->
wbuf.
capa) {
2102 for (
int i = 1; i < iovcnt; i++) {
2103 memcpy(fptr->
wbuf.
ptr+offset, iov[i].iov_base, iov[i].iov_len);
2104 offset += iov[i].iov_len;
2113 iov[0].iov_len = fptr->
wbuf.
len;
2126 struct binwritev_arg arg;
2129 arg.iovcnt = iovcnt;
2136 return io_binwritev_internal((
VALUE)&arg);
2143 int i, converted, iovcnt = argc + 1;
2145 VALUE v1, v2, str, tmp, *tmp_array;
2151 for (i = 0; i < argc; i++) {
2154 str = do_writeconv(str, fptr, &converted);
2159 tmp = rb_str_tmp_frozen_acquire(str);
2167 n = io_binwritev(iov, iovcnt, fptr);
2170 for (i = 0; i < argc; i++) {
2171 rb_str_tmp_frozen_release(argv[i], tmp_array[i]);
2180iovcnt_ok(
int iovcnt)
2183 return iovcnt < IOV_MAX;
2191io_writev(
int argc,
const VALUE *argv,
VALUE io)
2198 io = GetWriteIO(io);
2203 return rb_funcallv(io, id_write, argc, argv);
2211 for (i = 0; i < argc; i += cnt) {
2214 n = io_fwritev(cnt, &argv[i], fptr);
2225 rb_sys_fail_on_write(fptr);
2227 total = rb_fix_plus(
LONG2FIX(n), total);
2258 return io_writev(argc, argv, io);
2261 VALUE str = argv[0];
2262 return io_write(io, str, 0);
2269 return rb_funcallv(io, id_write, 1, &str);
2273rb_io_writev(
VALUE io,
int argc,
const VALUE *argv)
2281 " which accepts just one argument",
2291 return rb_funcallv(io, id_write, argc, argv);
2323nogvl_fsync(
void *ptr)
2328 if (GetFileType((HANDLE)rb_w32_get_osfhandle(fptr->
fd)) != FILE_TYPE_DISK)
2331 return (
VALUE)fsync(fptr->
fd);
2336rb_io_flush_raw(
VALUE io,
int sync)
2344 io = GetWriteIO(io);
2348 if (io_fflush(fptr) < 0)
2349 rb_sys_fail_on_write(fptr);
2373 return rb_io_flush_raw(io, 1);
2402 pos = io_tell(fptr);
2403 if (pos < 0 && errno) rb_sys_fail_path(fptr->
pathv);
2409rb_io_seek(
VALUE io,
VALUE offset,
int whence)
2416 pos = io_seek(fptr, pos, whence);
2417 if (pos < 0 && errno) rb_sys_fail_path(fptr->
pathv);
2423interpret_seek_whence(
VALUE vwhence)
2425 if (vwhence == sym_SET)
2427 if (vwhence == sym_CUR)
2429 if (vwhence == sym_END)
2432 if (vwhence == sym_DATA)
2436 if (vwhence == sym_HOLE)
2492 VALUE offset, ptrname;
2493 int whence = SEEK_SET;
2495 if (
rb_scan_args(argc, argv,
"11", &offset, &ptrname) == 2) {
2496 whence = interpret_seek_whence(ptrname);
2499 return rb_io_seek(io, offset, whence);
2527 pos = io_seek(fptr, pos, SEEK_SET);
2528 if (pos < 0 && errno) rb_sys_fail_path(fptr->
pathv);
2533static void clear_readconv(
rb_io_t *fptr);
2560rb_io_rewind(
VALUE io)
2565 if (io_seek(fptr, 0L, 0) < 0 && errno) rb_sys_fail_path(fptr->
pathv);
2566 if (io == ARGF.current_file) {
2567 ARGF.lineno -= fptr->
lineno;
2571 clear_readconv(fptr);
2578fptr_wait_readable(
rb_io_t *fptr)
2596 fptr->
rbuf.
capa = IO_RBUF_CAPA_FOR(fptr);
2607 if (fptr_wait_readable(fptr))
2616 rb_syserr_fail_path(e, path);
2673 if (READ_CHAR_PENDING(fptr))
return Qfalse;
2674 if (READ_DATA_PENDING(fptr))
return Qfalse;
2676#if RUBY_CRLF_ENVIRONMENT
2677 if (!NEED_READCONV(fptr) && NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {
2678 return RBOOL(eof(fptr->
fd));;
2681 return RBOOL(io_fillbuf(fptr) < 0);
2705 io = GetWriteIO(io);
2742 io = GetWriteIO(io);
2748 fptr->
mode &= ~FMODE_SYNC;
2772rb_io_fsync(
VALUE io)
2776 io = GetWriteIO(io);
2779 if (io_fflush(fptr) < 0)
2780 rb_sys_fail_on_write(fptr);
2781 if ((
int)rb_thread_io_blocking_region(nogvl_fsync, fptr, fptr->
fd) < 0)
2782 rb_sys_fail_path(fptr->
pathv);
2786# define rb_io_fsync rb_f_notimplement
2787# define rb_io_sync rb_f_notimplement
2796#ifdef HAVE_FDATASYNC
2798nogvl_fdatasync(
void *ptr)
2803 if (GetFileType((HANDLE)rb_w32_get_osfhandle(fptr->
fd)) != FILE_TYPE_DISK)
2806 return (
VALUE)fdatasync(fptr->
fd);
2821rb_io_fdatasync(
VALUE io)
2825 io = GetWriteIO(io);
2828 if (io_fflush(fptr) < 0)
2829 rb_sys_fail_on_write(fptr);
2831 if ((
int)rb_thread_io_blocking_region(nogvl_fdatasync, fptr, fptr->
fd) == 0)
2835 return rb_io_fsync(io);
2838#define rb_io_fdatasync rb_io_fsync
2858rb_io_fileno(
VALUE io)
2951rb_io_inspect(
VALUE obj)
2955 static const char closed[] =
" (closed)";
2957 fptr =
RFILE(obj)->fptr;
2964 rb_str_cat(result, closed+1, strlen(closed)-1);
2988rb_io_to_io(
VALUE io)
2995read_buffered_data(
char *ptr,
long len,
rb_io_t *fptr)
2999 n = READ_DATA_PENDING_COUNT(fptr);
3000 if (n <= 0)
return 0;
3001 if (n > len) n = (int)len;
3009io_bufread(
char *ptr,
long len,
rb_io_t *fptr)
3015 if (READ_DATA_PENDING(fptr) == 0) {
3019 c = rb_io_read_memory(fptr, ptr+offset, n);
3022 if (fptr_wait_readable(fptr))
3027 if ((n -= c) <= 0)
break;
3033 c = read_buffered_data(ptr+offset, n, fptr);
3036 if ((n -= c) <= 0)
break;
3039 if (io_fillbuf(fptr) < 0) {
3046static int io_setstrbuf(
VALUE *str,
long len);
3055bufread_call(
VALUE arg)
3058 p->len = io_bufread(p->str_ptr, p->len, p->fptr);
3063io_fread(
VALUE str,
long offset,
long size,
rb_io_t *fptr)
3068 io_setstrbuf(&str, offset + size);
3072 rb_str_locktmp_ensure(str, bufread_call, (
VALUE)&arg);
3074 if (len < 0) rb_sys_fail_path(fptr->
pathv);
3082 rb_off_t siz = READ_DATA_PENDING_COUNT(fptr);
3085 if (fstat(fptr->
fd, &st) == 0 && S_ISREG(st.st_mode)
3086#
if defined(__HAIKU__)
3091 if (io_fflush(fptr) < 0)
3092 rb_sys_fail_on_write(fptr);
3093 pos = lseek(fptr->
fd, 0, SEEK_CUR);
3094 if (st.st_size >= pos && pos >= 0) {
3095 siz += st.st_size - pos;
3096 if (siz > LONG_MAX) {
3110 rb_enc_associate(str, io_read_encoding(fptr));
3117make_readconv(
rb_io_t *fptr,
int size)
3122 const char *sname, *dname;
3123 ecflags = fptr->
encs.
ecflags & ~ECONV_NEWLINE_DECORATOR_WRITE_MASK;
3137 if (size < IO_CBUF_CAPA_MIN) size = IO_CBUF_CAPA_MIN;
3143#define MORE_CHAR_SUSPENDED Qtrue
3144#define MORE_CHAR_FINISHED Qnil
3146fill_cbuf(
rb_io_t *fptr,
int ec_flags)
3148 const unsigned char *ss, *sp, *se;
3149 unsigned char *ds, *dp, *de;
3158 return MORE_CHAR_SUSPENDED;
3169 ss = sp = (
const unsigned char *)fptr->
rbuf.
ptr + fptr->
rbuf.
off;
3174 fptr->
rbuf.
off += (int)(sp - ss);
3175 fptr->
rbuf.
len -= (int)(sp - ss);
3176 fptr->
cbuf.
len += (int)(dp - ds);
3181 fptr->
rbuf.
off -= putbackable;
3182 fptr->
rbuf.
len += putbackable;
3189 if (cbuf_len0 != fptr->
cbuf.
len)
3190 return MORE_CHAR_SUSPENDED;
3193 return MORE_CHAR_FINISHED;
3199 if (io_fillbuf(fptr) < 0) {
3201 return MORE_CHAR_FINISHED;
3206 fptr->
cbuf.
len += (int)(dp - ds);
3213 if (cbuf_len0 != fptr->
cbuf.
len)
3214 return MORE_CHAR_SUSPENDED;
3216 return MORE_CHAR_FINISHED;
3224 if (v != MORE_CHAR_SUSPENDED && v != MORE_CHAR_FINISHED)
3241 rb_enc_associate(str, fptr->
encs.
enc);
3256io_setstrbuf(
VALUE *str,
long len)
3260 len = (len + 1) & ~1L;
3281#define MAX_REALLOC_GAP 4096
3283io_shrink_read_string(
VALUE str,
long n)
3291io_set_read_length(
VALUE str,
long n,
int shrinkable)
3296 if (shrinkable) io_shrink_read_string(str, n);
3310 if (NEED_READCONV(fptr)) {
3311 int first = !
NIL_P(str);
3312 SET_BINARY_MODE(fptr);
3313 shrinkable = io_setstrbuf(&str,0);
3314 make_readconv(fptr, 0);
3319 io_shift_cbuf(fptr, fptr->
cbuf.
len, &str);
3321 v = fill_cbuf(fptr, 0);
3322 if (v != MORE_CHAR_SUSPENDED && v != MORE_CHAR_FINISHED) {
3325 io_shift_cbuf(fptr, fptr->
cbuf.
len, &str);
3329 if (v == MORE_CHAR_FINISHED) {
3330 clear_readconv(fptr);
3332 if (shrinkable) io_shrink_read_string(str,
RSTRING_LEN(str));
3333 return io_enc_str(str, fptr);
3338 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
3342 enc = io_read_encoding(fptr);
3345 if (siz == 0) siz = BUFSIZ;
3346 shrinkable = io_setstrbuf(&str, siz);
3349 n = io_fread(str, bytes, siz - bytes, fptr);
3350 if (n == 0 && bytes == 0) {
3358 if (bytes < siz)
break;
3363 if (capa < BUFSIZ) {
3366 else if (capa > IO_MAX_BUFFER_GROWTH) {
3367 capa = IO_MAX_BUFFER_GROWTH;
3372 if (shrinkable) io_shrink_read_string(str,
RSTRING_LEN(str));
3373 str = io_enc_str(str, fptr);
3381 if (rb_fd_set_nonblock(fptr->
fd) != 0) {
3382 rb_sys_fail_path(fptr->
pathv);
3387io_read_memory_call(
VALUE arg)
3392 if (scheduler !=
Qnil) {
3395 if (!UNDEF_P(result)) {
3401 return rb_thread_io_blocking_region(internal_read_func, iis, iis->fptr->
fd);
3407 return (
long)rb_str_locktmp_ensure(str, io_read_memory_call, (
VALUE)iis);
3410#define no_exception_p(opts) !rb_opts_exception_p((opts), TRUE)
3413io_getpartial(
int argc,
VALUE *argv,
VALUE io,
int no_exception,
int nonblock)
3423 if ((len =
NUM2LONG(length)) < 0) {
3427 shrinkable = io_setstrbuf(&str, len);
3433 io_set_read_length(str, 0, shrinkable);
3439 n = read_buffered_data(
RSTRING_PTR(str), len, fptr);
3445 io_setstrbuf(&str, len);
3448 iis.nonblock = nonblock;
3453 n = io_read_memory_locktmp(str, &iis);
3456 if (!nonblock && fptr_wait_readable(fptr))
3458 if (nonblock && (io_again_p(e))) {
3460 return sym_wait_readable;
3463 e,
"read would block");
3465 rb_syserr_fail_path(e, fptr->
pathv);
3468 io_set_read_length(str, n, shrinkable);
3569io_readpartial(
int argc,
VALUE *argv,
VALUE io)
3573 ret = io_getpartial(argc, argv, io,
Qnil, 0);
3580io_nonblock_eof(
int no_exception)
3582 if (!no_exception) {
3597 if ((len =
NUM2LONG(length)) < 0) {
3601 shrinkable = io_setstrbuf(&str, len);
3602 rb_bool_expected(ex,
"exception", TRUE);
3608 io_set_read_length(str, 0, shrinkable);
3612 n = read_buffered_data(
RSTRING_PTR(str), len, fptr);
3614 rb_fd_set_nonblock(fptr->
fd);
3615 shrinkable |= io_setstrbuf(&str, len);
3622 n = io_read_memory_locktmp(str, &iis);
3625 if (io_again_p(e)) {
3626 if (!ex)
return sym_wait_readable;
3628 e,
"read would block");
3630 rb_syserr_fail_path(e, fptr->
pathv);
3633 io_set_read_length(str, n, shrinkable);
3636 if (!ex)
return Qnil;
3652 rb_bool_expected(ex,
"exception", TRUE);
3654 io = GetWriteIO(io);
3658 if (io_fflush(fptr) < 0)
3659 rb_sys_fail_on_write(fptr);
3661 rb_fd_set_nonblock(fptr->
fd);
3667 if (io_again_p(e)) {
3669 return sym_wait_writable;
3675 rb_syserr_fail_path(e, fptr->
pathv);
3759#if RUBY_CRLF_ENVIRONMENT
3765 if (
NIL_P(length)) {
3768 return read_all(fptr, remain_size(fptr), str);
3775 shrinkable = io_setstrbuf(&str,len);
3780 io_set_read_length(str, 0, shrinkable);
3785#if RUBY_CRLF_ENVIRONMENT
3786 previous_mode = set_binary_mode_with_seek_cur(fptr);
3788 n = io_fread(str, 0, len, fptr);
3789 io_set_read_length(str, n, shrinkable);
3790#if RUBY_CRLF_ENVIRONMENT
3791 if (previous_mode == O_TEXT) {
3792 setmode(fptr->
fd, O_TEXT);
3795 if (n == 0)
return Qnil;
3801rscheck(
const char *rsptr,
long rslen,
VALUE rs)
3809appendline(
rb_io_t *fptr,
int delim,
VALUE *strp,
long *lp)
3814 if (NEED_READCONV(fptr)) {
3815 SET_BINARY_MODE(fptr);
3816 make_readconv(fptr, 0);
3819 int searchlen = READ_CHAR_PENDING_COUNT(fptr);
3821 p = READ_CHAR_PENDING_PTR(fptr);
3822 if (0 < limit && limit < searchlen)
3823 searchlen = (int)limit;
3824 e = memchr(p, delim, searchlen);
3826 int len = (int)(e-p+1);
3851 }
while (more_char(fptr) != MORE_CHAR_FINISHED);
3852 clear_readconv(fptr);
3857 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
3859 long pending = READ_DATA_PENDING_COUNT(fptr);
3861 const char *p = READ_DATA_PENDING_PTR(fptr);
3865 if (limit > 0 && pending > limit) pending = limit;
3866 e = memchr(p, delim, pending);
3867 if (e) pending = e - p + 1;
3877 read_buffered_data(
RSTRING_PTR(str) + last, pending, fptr);
3880 if (e)
return delim;
3885 }
while (io_fillbuf(fptr) >= 0);
3891swallow(
rb_io_t *fptr,
int term)
3893 if (NEED_READCONV(fptr)) {
3896 SET_BINARY_MODE(fptr);
3897 make_readconv(fptr, 0);
3900 while ((cnt = READ_CHAR_PENDING_COUNT(fptr)) > 0) {
3901 const char *p = READ_CHAR_PENDING_PTR(fptr);
3904 if (*p != term)
return TRUE;
3906 while (--i && *++p == term);
3909 const char *e = p + cnt;
3910 if (rb_enc_ascget(p, e, &i, enc) != term)
return TRUE;
3911 while ((p += i) < e && rb_enc_ascget(p, e, &i, enc) == term);
3914 io_shift_cbuf(fptr, (
int)cnt - i, NULL);
3916 }
while (more_char(fptr) != MORE_CHAR_FINISHED);
3920 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
3923 while ((cnt = READ_DATA_PENDING_COUNT(fptr)) > 0) {
3925 const char *p = READ_DATA_PENDING_PTR(fptr);
3927 if (cnt >
sizeof buf) cnt =
sizeof buf;
3928 if (*p != term)
return TRUE;
3930 while (--i && *++p == term);
3931 if (!read_buffered_data(buf, cnt - i, fptr))
3932 rb_sys_fail_path(fptr->
pathv);
3935 }
while (io_fillbuf(fptr) == 0);
3948 int pending = READ_DATA_PENDING_COUNT(fptr);
3951 const char *p = READ_DATA_PENDING_PTR(fptr);
3955 e = memchr(p,
'\n', pending);
3957 pending = (int)(e - p + 1);
3959 chomplen = (pending > 1 && *(e-1) ==
'\r') + 1;
3969 read_buffered_data(
RSTRING_PTR(str)+len, pending - chomplen, fptr);
3972 if (pending == 1 && chomplen == 1 && len > 0) {
3979 len += pending - chomplen;
3985 }
while (io_fillbuf(fptr) >= 0);
3988 str = io_enc_str(str, fptr);
3999 unsigned int chomp: 1;
4013 chomp = (!UNDEF_P(vchomp)) &&
RTEST(vchomp);
4015 args->chomp = chomp;
4033 else if (2 <= argc) {
4034 rs = argv[0], lim = argv[1];
4043check_getline_args(
VALUE *rsp,
long *limit,
VALUE io)
4052 enc_rs = rb_enc_get(rs);
4053 enc_io = io_read_encoding(fptr);
4054 if (enc_io != enc_rs &&
4055 (!is_ascii_string(rs) ||
4057 if (rs == rb_default_rs) {
4075 argc =
rb_scan_args(argc, argv,
"02:", NULL, NULL, &opts);
4076 extract_getline_args(argc, argv, args);
4077 extract_getline_opts(opts, args);
4078 check_getline_args(&args->rs, &args->limit, io);
4082rb_io_getline_0(
VALUE rs,
long limit,
int chomp,
rb_io_t *fptr)
4089 if (
NIL_P(rs) && limit < 0) {
4090 str = read_all(fptr, 0,
Qnil);
4093 else if (limit == 0) {
4096 else if (rs == rb_default_rs && limit < 0 && !NEED_READCONV(fptr) &&
4098 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
4099 return rb_io_getline_fast(fptr, enc, chomp);
4102 int c, newline = -1;
4103 const char *rsptr = 0;
4106 int extra_limit = 16;
4107 int chomp_cr = chomp;
4109 SET_BINARY_MODE(fptr);
4110 enc = io_read_encoding(fptr);
4118 swallow(fptr,
'\n');
4131 newline = (
unsigned char)rsptr[rslen - 1];
4132 chomp_cr = chomp && rslen == 1 && newline ==
'\n';
4136 while ((c = appendline(fptr, newline, &str, &limit)) != EOF) {
4137 const char *s, *p, *pp, *e;
4145 if (pp != p)
continue;
4146 if (!rspara) rscheck(rsptr, rslen, rs);
4147 if (memcmp(p, rsptr, rslen) == 0) {
4149 if (chomp_cr && p > s && *(p-1) ==
'\r') --p;
4173 if (rspara && c != EOF)
4174 swallow(fptr,
'\n');
4176 str = io_enc_str(str, fptr);
4179 if (!
NIL_P(str) && !nolimit) {
4187rb_io_getline_1(
VALUE rs,
long limit,
int chomp,
VALUE io)
4190 int old_lineno, new_lineno;
4194 old_lineno = fptr->
lineno;
4195 str = rb_io_getline_0(rs, limit, chomp, fptr);
4196 if (!
NIL_P(str) && (new_lineno = fptr->
lineno) != old_lineno) {
4197 if (io == ARGF.current_file) {
4198 ARGF.lineno += new_lineno - old_lineno;
4199 ARGF.last_lineno = ARGF.lineno;
4202 ARGF.last_lineno = new_lineno;
4210rb_io_getline(
int argc,
VALUE *argv,
VALUE io)
4214 prepare_getline_args(argc, argv, &args, io);
4215 return rb_io_getline_1(args.rs, args.limit, args.chomp, io);
4225rb_io_gets_internal(
VALUE io)
4229 return rb_io_getline_0(rb_default_rs, -1, FALSE, fptr);
4312 str = rb_io_getline(argc, argv, io);
4328rb_io_lineno(
VALUE io)
4370rb_io_readline(
int argc,
VALUE *argv,
VALUE io)
4372 VALUE line = rb_io_gets_m(argc, argv, io);
4449rb_io_readlines(
int argc,
VALUE *argv,
VALUE io)
4453 prepare_getline_args(argc, argv, &args, io);
4454 return io_readlines(&args, io);
4462 if (arg->limit == 0)
4465 while (!
NIL_P(line = rb_io_getline_1(arg->rs, arg->limit, arg->chomp, io))) {
4466 rb_ary_push(ary, line);
4583rb_io_each_line(
int argc,
VALUE *argv,
VALUE io)
4589 prepare_getline_args(argc, argv, &args, io);
4590 if (args.limit == 0)
4592 while (!
NIL_P(str = rb_io_getline_1(args.rs, args.limit, args.chomp, io))) {
4619rb_io_each_byte(
VALUE io)
4635 }
while (io_fillbuf(fptr) >= 0);
4645 if (NEED_READCONV(fptr)) {
4649 SET_BINARY_MODE(fptr);
4650 make_readconv(fptr, 0);
4664 if (more_char(fptr) == MORE_CHAR_FINISHED) {
4666 clear_readconv(fptr);
4673 if (fptr->
cbuf.
len == 0) clear_readconv(fptr);
4682 io_shift_cbuf(fptr, r, &str);
4693 str = io_enc_str(str, fptr);
4698 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
4699 if (io_fillbuf(fptr) < 0) {
4721 if (io_fillbuf(fptr) != -1) {
4741 str = io_enc_str(str, fptr);
4767rb_io_each_char(
VALUE io)
4777 enc = io_input_encoding(fptr);
4779 while (!
NIL_P(c = io_getc(fptr, enc))) {
4805rb_io_each_codepoint(
VALUE io)
4817 if (NEED_READCONV(fptr)) {
4818 SET_BINARY_MODE(fptr);
4821 make_readconv(fptr, 0);
4829 r = ONIGENC_CONSTRUCT_MBCLEN_CHARFOUND(1);
4836 if (more_char(fptr) == MORE_CHAR_FINISHED) {
4837 clear_readconv(fptr);
4864 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
4865 enc = io_input_encoding(fptr);
4866 while (io_fillbuf(fptr) >= 0) {
4881 char cbuf[8], *p = cbuf;
4883 if (more > numberof(cbuf))
goto invalid;
4885 if (more > numberof(cbuf))
goto invalid;
4886 while ((n = (
int)read_buffered_data(p, more, fptr)) > 0 &&
4887 (p += n, (more -= n) > 0)) {
4888 if (io_fillbuf(fptr) < 0)
goto invalid;
4889 if ((n = fptr->
rbuf.
len) > more) n = more;
4891 r = rb_enc_precise_mbclen(cbuf, p, enc);
4936 enc = io_input_encoding(fptr);
4938 return io_getc(fptr, enc);
4961rb_io_readchar(
VALUE io)
4963 VALUE c = rb_io_getc(io);
5006 if (io_fillbuf(fptr) < 0) {
5035rb_io_readbyte(
VALUE io)
5096 unsigned char c =
NUM2INT(v) & 0xFF;
5102 io_ungetbyte(b, fptr);
5158 else if (RB_BIGNUM_TYPE_P(c)) {
5164 if (NEED_READCONV(fptr)) {
5165 SET_BINARY_MODE(fptr);
5167#if SIZEOF_LONG > SIZEOF_INT
5171 make_readconv(fptr, (
int)len);
5185 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
5186 io_ungetbyte(c, fptr);
5208rb_io_isatty(
VALUE io)
5213 return RBOOL(isatty(fptr->
fd) != 0);
5216#if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
5232rb_io_close_on_exec_p(
VALUE io)
5238 write_io = GetWriteIO(io);
5239 if (io != write_io) {
5241 if (fptr && 0 <= (fd = fptr->
fd)) {
5242 if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->
pathv);
5243 if (!(ret & FD_CLOEXEC))
return Qfalse;
5248 if (fptr && 0 <= (fd = fptr->
fd)) {
5249 if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->
pathv);
5250 if (!(ret & FD_CLOEXEC))
return Qfalse;
5255#define rb_io_close_on_exec_p rb_f_notimplement
5258#if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
5282 int flag =
RTEST(arg) ? FD_CLOEXEC : 0;
5287 write_io = GetWriteIO(io);
5288 if (io != write_io) {
5290 if (fptr && 0 <= (fd = fptr->
fd)) {
5291 if ((ret = fcntl(fptr->
fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->
pathv);
5292 if ((ret & FD_CLOEXEC) != flag) {
5293 ret = (ret & ~FD_CLOEXEC) | flag;
5294 ret = fcntl(fd, F_SETFD, ret);
5295 if (ret != 0) rb_sys_fail_path(fptr->
pathv);
5302 if (fptr && 0 <= (fd = fptr->
fd)) {
5303 if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->
pathv);
5304 if ((ret & FD_CLOEXEC) != flag) {
5305 ret = (ret & ~FD_CLOEXEC) | flag;
5306 ret = fcntl(fd, F_SETFD, ret);
5307 if (ret != 0) rb_sys_fail_path(fptr->
pathv);
5313#define rb_io_set_close_on_exec rb_f_notimplement
5316#define IS_PREP_STDIO(f) ((f)->mode & FMODE_PREP)
5317#define PREP_STDIO_NAME(f) (RSTRING_PTR((f)->pathv))
5320finish_writeconv(
rb_io_t *fptr,
int noalloc)
5322 unsigned char *ds, *dp, *de;
5326 unsigned char buf[1024];
5331 de = buf +
sizeof(buf);
5334 size_t remaining = dp-ds;
5335 long result = rb_io_write_memory(fptr, ds, remaining);
5339 if ((
size_t)result == remaining)
break;
5362 if (io_fflush(fptr) < 0) {
5370 fptr->
wbuf.
len += (int)(dp - ds);
5386finish_writeconv_sync(
VALUE arg)
5389 return finish_writeconv(p->fptr, p->noalloc);
5393nogvl_close(
void *ptr)
5397 return (
void*)(intptr_t)close(*fd);
5401maygvl_close(
int fd,
int keepgvl)
5414nogvl_fclose(
void *ptr)
5418 return (
void*)(intptr_t)fclose(file);
5422maygvl_fclose(
FILE *file,
int keepgvl)
5425 return fclose(file);
5431static void clear_codeconv(
rb_io_t *fptr);
5434fptr_finalize_flush(
rb_io_t *fptr,
int noraise,
int keepgvl,
5435 struct ccan_list_head *busy)
5440 int mode = fptr->
mode;
5446 arg.noalloc = noraise;
5450 error = finish_writeconv(fptr, noraise);
5455 io_flush_buffer_sync(fptr);
5458 if (io_fflush(fptr) < 0 &&
NIL_P(error)) {
5466 if (IS_PREP_STDIO(fptr) || fd <= 2) {
5490 if (!done && stdio_file) {
5492 if ((maygvl_fclose(stdio_file, noraise) < 0) &&
NIL_P(error)) {
5501 if (!done && fd >= 0) {
5507 if ((maygvl_close(fd, keepgvl) < 0) &&
NIL_P(error)) {
5516 if (!
NIL_P(error) && !noraise) {
5525fptr_finalize(
rb_io_t *fptr,
int noraise)
5527 fptr_finalize_flush(fptr, noraise, FALSE, 0);
5528 free_io_buffer(&fptr->
rbuf);
5529 free_io_buffer(&fptr->
wbuf);
5530 clear_codeconv(fptr);
5534rb_io_fptr_cleanup(
rb_io_t *fptr,
int noraise)
5540 fptr_finalize(fptr, noraise);
5548 ruby_sized_xfree(buf->
ptr, (
size_t)buf->
capa);
5560 free_io_buffer(&fptr->
cbuf);
5576 clear_readconv(fptr);
5577 clear_writeconv(fptr);
5581rb_io_fptr_finalize_internal(
void *ptr)
5588 rb_io_fptr_cleanup(fptr, TRUE);
5590 free_io_buffer(&fptr->
rbuf);
5591 free_io_buffer(&fptr->
wbuf);
5592 clear_codeconv(fptr);
5596#undef rb_io_fptr_finalize
5604 rb_io_fptr_finalize_internal(fptr);
5608#define rb_io_fptr_finalize(fptr) rb_io_fptr_finalize_internal(fptr)
5610RUBY_FUNC_EXPORTED
size_t
5611rb_io_memsize(
const rb_io_t *fptr)
5613 size_t size =
sizeof(
rb_io_t);
5624# define KEEPGVL TRUE
5626# define KEEPGVL FALSE
5629int rb_notify_fd_close(
int fd,
struct ccan_list_head *);
5631io_close_fptr(
VALUE io)
5636 struct ccan_list_head busy;
5638 ccan_list_head_init(&busy);
5639 write_io = GetWriteIO(io);
5640 if (io != write_io) {
5641 write_fptr =
RFILE(write_io)->fptr;
5642 if (write_fptr && 0 <= write_fptr->
fd) {
5643 rb_io_fptr_cleanup(write_fptr, TRUE);
5647 fptr =
RFILE(io)->fptr;
5648 if (!fptr)
return 0;
5649 if (fptr->
fd < 0)
return 0;
5651 if (rb_notify_fd_close(fptr->
fd, &busy)) {
5653 fptr_finalize_flush(fptr, FALSE, KEEPGVL, &busy);
5655 rb_io_fptr_cleanup(fptr, FALSE);
5660fptr_waitpid(
rb_io_t *fptr,
int nohang)
5664 rb_last_status_clear();
5673 rb_io_t *fptr = io_close_fptr(io);
5674 if (fptr) fptr_waitpid(fptr, 0);
5711rb_io_close_m(
VALUE io)
5713 rb_io_t *fptr = rb_io_get_fptr(io);
5722io_call_close(
VALUE io)
5731 enum {mesg_len =
sizeof(closed_stream)-1};
5735 memcmp(
RSTRING_PTR(mesg), closed_stream, mesg_len)) {
5745 if (!UNDEF_P(closed) &&
RTEST(closed))
return io;
5746 rb_rescue2(io_call_close, io, ignore_closed_stream, io,
5778rb_io_closed(
VALUE io)
5784 write_io = GetWriteIO(io);
5785 if (io != write_io) {
5786 write_fptr =
RFILE(write_io)->fptr;
5787 if (write_fptr && 0 <= write_fptr->
fd) {
5792 fptr = rb_io_get_fptr(io);
5793 return RBOOL(0 > fptr->
fd);
5829rb_io_close_read(
VALUE io)
5835 if (fptr->
fd < 0)
return Qnil;
5836 if (is_socket(fptr->
fd, fptr->
pathv)) {
5840 if (shutdown(fptr->
fd, SHUT_RD) < 0)
5841 rb_sys_fail_path(fptr->
pathv);
5842 fptr->
mode &= ~FMODE_READABLE;
5848 write_io = GetWriteIO(io);
5849 if (io != write_io) {
5854 RFILE(io)->fptr = wfptr;
5857 RFILE(write_io)->fptr = fptr;
5858 rb_io_fptr_cleanup(fptr, FALSE);
5902rb_io_close_write(
VALUE io)
5907 write_io = GetWriteIO(io);
5909 if (fptr->
fd < 0)
return Qnil;
5910 if (is_socket(fptr->
fd, fptr->
pathv)) {
5914 if (shutdown(fptr->
fd, SHUT_WR) < 0)
5915 rb_sys_fail_path(fptr->
pathv);
5916 fptr->
mode &= ~FMODE_WRITABLE;
5926 if (io != write_io) {
5946rb_io_sysseek(
int argc,
VALUE *argv,
VALUE io)
5948 VALUE offset, ptrname;
5949 int whence = SEEK_SET;
5953 if (
rb_scan_args(argc, argv,
"11", &offset, &ptrname) == 2) {
5954 whence = interpret_seek_whence(ptrname);
5959 (READ_DATA_BUFFERED(fptr) || READ_CHAR_PENDING(fptr))) {
5963 rb_warn(
"sysseek for buffered IO");
5966 pos = lseek(fptr->
fd, pos, whence);
5967 if (pos < 0 && errno) rb_sys_fail_path(fptr->
pathv);
6001 io = GetWriteIO(io);
6006 rb_warn(
"syswrite for buffered IO");
6009 tmp = rb_str_tmp_frozen_acquire(str);
6011 n = rb_io_write_memory(fptr, ptr, len);
6012 if (n < 0) rb_sys_fail_path(fptr->
pathv);
6013 rb_str_tmp_frozen_release(str, tmp);
6030rb_io_sysread(
int argc,
VALUE *argv,
VALUE io)
6041 shrinkable = io_setstrbuf(&str, ilen);
6042 if (ilen == 0)
return str;
6047 if (READ_DATA_BUFFERED(fptr)) {
6053 io_setstrbuf(&str, ilen);
6061 n = io_read_memory_locktmp(str, &iis);
6064 rb_sys_fail_path(fptr->
pathv);
6067 io_set_read_length(str, n, shrinkable);
6069 if (n == 0 && ilen > 0) {
6076#if defined(HAVE_PREAD) || defined(HAVE_PWRITE)
6077struct prdwr_internal_arg {
6085#if defined(HAVE_PREAD)
6087internal_pread_func(
void *arg)
6089 struct prdwr_internal_arg *p = arg;
6090 return (
VALUE)pread(p->fd, p->buf, p->count, p->offset);
6094pread_internal_call(
VALUE arg)
6096 struct prdwr_internal_arg *p = (
struct prdwr_internal_arg *)arg;
6097 return rb_thread_io_blocking_region(internal_pread_func, p, p->fd);
6131 VALUE len, offset, str;
6134 struct prdwr_internal_arg arg;
6141 shrinkable = io_setstrbuf(&str, (
long)arg.count);
6142 if (arg.count == 0)
return str;
6155 rb_sys_fail_path(fptr->
pathv);
6157 io_set_read_length(str, n, shrinkable);
6158 if (n == 0 && arg.count > 0) {
6165# define rb_io_pread rb_f_notimplement
6168#if defined(HAVE_PWRITE)
6170internal_pwrite_func(
void *ptr)
6172 struct prdwr_internal_arg *arg = ptr;
6174 return (
VALUE)pwrite(arg->fd, arg->buf, arg->count, arg->offset);
6207 struct prdwr_internal_arg arg;
6215 io = GetWriteIO(io);
6220 tmp = rb_str_tmp_frozen_acquire(str);
6224 n = (ssize_t)rb_thread_io_blocking_region(internal_pwrite_func, &arg, fptr->
fd);
6225 if (n < 0) rb_sys_fail_path(fptr->
pathv);
6226 rb_str_tmp_frozen_release(str, tmp);
6231# define rb_io_pwrite rb_f_notimplement
6245 fptr->
mode &= ~FMODE_TEXTMODE;
6249 SET_BINARY_MODE_WITH_SEEK_CUR(fptr);
6252 setmode(fptr->
fd, O_BINARY);
6259io_ascii8bit_binmode(
rb_io_t *fptr)
6270 fptr->
mode &= ~FMODE_TEXTMODE;
6271 SET_BINARY_MODE_WITH_SEEK_CUR(fptr);
6273 fptr->
encs.
enc = rb_ascii8bit_encoding();
6277 clear_codeconv(fptr);
6286 io_ascii8bit_binmode(fptr);
6303rb_io_binmode_m(
VALUE io)
6309 write_io = GetWriteIO(io);
6324rb_io_binmode_p(
VALUE io)
6332rb_io_fmode_modestr(
int fmode)
6336 return MODE_BTMODE(
"a+",
"ab+",
"at+");
6338 return MODE_BTMODE(
"a",
"ab",
"at");
6344 return MODE_BTMODE(
"r",
"rb",
"rt");
6346 return MODE_BTXMODE(
"w",
"wb",
"wt",
"wx",
"wbx",
"wtx");
6349 return MODE_BTXMODE(
"w+",
"wb+",
"wt+",
"w+x",
"wb+x",
"wt+x");
6351 return MODE_BTMODE(
"r+",
"rb+",
"rt+");
6355static const char bom_prefix[] =
"bom|";
6356static const char utf_prefix[] =
"utf-";
6357enum {bom_prefix_len = (int)
sizeof(bom_prefix) - 1};
6358enum {utf_prefix_len = (int)
sizeof(utf_prefix) - 1};
6361io_encname_bom_p(
const char *name,
long len)
6363 return len > bom_prefix_len &&
STRNCASECMP(name, bom_prefix, bom_prefix_len) == 0;
6370 const char *m = modestr, *p = NULL;
6398 if (modestr[0] !=
'w')
6406 if (io_encname_bom_p(m, p ? (
long)(p - m) : (
long)strlen(m)))
6428 switch (oflags & O_ACCMODE) {
6440 if (oflags & O_APPEND) {
6443 if (oflags & O_TRUNC) {
6446 if (oflags & O_CREAT) {
6449 if (oflags & O_EXCL) {
6453 if (oflags & O_BINARY) {
6462rb_io_fmode_oflags(
int fmode)
6506rb_io_oflags_modestr(
int oflags)
6509# define MODE_BINARY(a,b) ((oflags & O_BINARY) ? (b) : (a))
6511# define MODE_BINARY(a,b) (a)
6514 if (oflags & O_EXCL) {
6517 accmode = oflags & (O_RDONLY|O_WRONLY|O_RDWR);
6518 if (oflags & O_APPEND) {
6519 if (accmode == O_WRONLY) {
6520 return MODE_BINARY(
"a",
"ab");
6522 if (accmode == O_RDWR) {
6523 return MODE_BINARY(
"a+",
"ab+");
6530 return MODE_BINARY(
"r",
"rb");
6532 return MODE_BINARY(
"w",
"wb");
6534 if (oflags & O_TRUNC) {
6535 return MODE_BINARY(
"w+",
"wb+");
6537 return MODE_BINARY(
"r+",
"rb+");
6549 int default_ext = 0;
6552 ext = rb_default_external_encoding();
6555 if (rb_is_ascii8bit_enc(ext)) {
6559 else if (intern == NULL) {
6560 intern = rb_default_internal_encoding();
6565 *enc = (default_ext && intern != ext) ? NULL : ext;
6575unsupported_encoding(
const char *name,
rb_encoding *enc)
6577 rb_enc_warn(enc,
"Unsupported encoding %s ignored", name);
6581parse_mode_enc(
const char *estr,
rb_encoding *estr_enc,
6587 int fmode = fmode_p ? *fmode_p : 0;
6593 p = strrchr(estr,
':');
6594 len = p ? (p++ - estr) : (long)strlen(estr);
6596 estr += bom_prefix_len;
6597 len -= bom_prefix_len;
6598 if (!
STRNCASECMP(estr, utf_prefix, utf_prefix_len)) {
6602 rb_enc_warn(estr_enc,
"BOM with non-UTF encoding %s is nonsense", estr);
6603 fmode &= ~FMODE_SETENC_BY_BOM;
6611 memcpy(encname, estr, len);
6612 encname[len] =
'\0';
6615 idx = rb_enc_find_index(estr);
6617 if (fmode_p) *fmode_p = fmode;
6620 ext_enc = rb_enc_from_index(idx);
6623 unsupported_encoding(estr, estr_enc);
6629 if (*p ==
'-' && *(p+1) ==
'\0') {
6634 idx2 = rb_enc_find_index(p);
6636 unsupported_encoding(p, estr_enc);
6641 int_enc = rb_enc_from_index(idx2);
6645 rb_io_ext_int_to_encs(ext_enc, int_enc, enc_p, enc2_p, fmode);
6658 v = rb_hash_lookup2(opt, sym_encoding,
Qnil);
6659 if (v !=
Qnil) encoding = v;
6660 v = rb_hash_lookup2(opt, sym_extenc,
Qundef);
6661 if (v !=
Qnil) extenc = v;
6662 v = rb_hash_lookup2(opt, sym_intenc,
Qundef);
6663 if (!UNDEF_P(v)) intenc = v;
6665 if ((!UNDEF_P(extenc) || !UNDEF_P(intenc)) && !
NIL_P(encoding)) {
6667 int idx = rb_to_encoding_index(encoding);
6668 if (idx >= 0) encoding = rb_enc_from_encoding(rb_enc_from_index(idx));
6669 rb_warn(
"Ignoring encoding parameter '%"PRIsVALUE
"': %s_encoding is used",
6670 encoding, UNDEF_P(extenc) ?
"internal" :
"external");
6674 if (!UNDEF_P(extenc) && !
NIL_P(extenc)) {
6675 extencoding = rb_to_encoding(extenc);
6677 if (!UNDEF_P(intenc)) {
6678 if (
NIL_P(intenc)) {
6685 if (*p ==
'-' && *(p+1) ==
'\0') {
6690 intencoding = rb_to_encoding(intenc);
6694 intencoding = rb_to_encoding(intenc);
6696 if (extencoding == intencoding) {
6700 if (!
NIL_P(encoding)) {
6704 enc_p, enc2_p, fmode_p);
6707 rb_io_ext_int_to_encs(rb_to_encoding(encoding), NULL, enc_p, enc2_p, 0);
6710 else if (!UNDEF_P(extenc) || !UNDEF_P(intenc)) {
6712 rb_io_ext_int_to_encs(extencoding, intencoding, enc_p, enc2_p, 0);
6722 int fmode = *fmode_p;
6738#if !DEFAULT_TEXTMODE
6740 fmode &= ~FMODE_TEXTMODE;
6747extract_binmode(
VALUE opthash,
int *fmode)
6749 if (!
NIL_P(opthash)) {
6751 v = rb_hash_aref(opthash, sym_textmode);
6760 v = rb_hash_aref(opthash, sym_binmode);
6777 int *oflags_p,
int *fmode_p,
convconfig_t *convconfig_p)
6784 int has_enc = 0, has_vmode = 0;
6790 rb_io_ext_int_to_encs(NULL, NULL, &
enc, &
enc2, 0);
6808 oflags = rb_io_fmode_oflags(fmode);
6812 parse_mode_enc(p+1, rb_enc_get(vmode), &
enc, &
enc2, &fmode);
6817 e = (fmode &
FMODE_BINMODE) ? rb_ascii8bit_encoding() : NULL;
6818 rb_io_ext_int_to_encs(e, NULL, &
enc, &
enc2, fmode);
6822 if (
NIL_P(opthash)) {
6826#ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
6828 MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE,
6829 0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE) : 0;
6831 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(
enc2,
ecflags);
6838 rb_io_ext_int_to_encs(rb_ascii8bit_encoding(), NULL, &
enc, &
enc2, fmode);
6841 else if (
NIL_P(vmode)) {
6842 fmode |= DEFAULT_TEXTMODE;
6849 v = rb_hash_aref(opthash, sym_mode);
6851 if (!
NIL_P(vmode)) {
6859 v = rb_hash_aref(opthash, sym_flags);
6866 extract_binmode(opthash, &fmode);
6872 rb_io_ext_int_to_encs(rb_ascii8bit_encoding(), NULL, &
enc, &
enc2, fmode);
6875 else if (
NIL_P(vmode)) {
6876 fmode |= DEFAULT_TEXTMODE;
6879 v = rb_hash_aref(opthash, sym_perm);
6882 if (!
NIL_P(*vperm_p)) {
6894#ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
6896 MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE,
6897 0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE) : 0;
6905 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(
enc2,
ecflags);
6928sysopen_func(
void *ptr)
6946rb_sysopen(
VALUE fname,
int oflags, mode_t perm)
6951 data.fname = rb_str_encode_ospath(fname);
6953 data.oflags = oflags;
6956 fd = rb_sysopen_internal(&data);
6959 if (rb_gc_for_fd(e)) {
6960 fd = rb_sysopen_internal(&data);
6963 rb_syserr_fail_path(e, fname);
6977 file = fdopen(fd, modestr);
6984 file = fdopen(fd, modestr);
6988 if (rb_gc_for_fd(e)) {
6989 file = fdopen(fd, modestr);
6993 if (e == 0) e = EINVAL;
6995 if (e == 0) e = EMFILE;
7003 if (setvbuf(file, NULL, _IOFBF, 0) != 0)
7004 rb_warn(
"setvbuf() can't be honoured (fd=%d)", fd);
7012 int t = isatty(fptr->
fd);
7022io_strip_bom(
VALUE io)
7024 VALUE b1, b2, b3, b4;
7035 return rb_utf8_encindex();
7045 return ENCINDEX_UTF_16BE;
7056 return ENCINDEX_UTF_32LE;
7061 return ENCINDEX_UTF_16LE;
7071 return ENCINDEX_UTF_32BE;
7085io_set_encoding_by_bom(
VALUE io)
7087 int idx = io_strip_bom(io);
7093 extenc = rb_enc_from_index(idx);
7094 io_encoding_set(fptr, rb_enc_from_encoding(extenc),
7095 rb_io_internal_encoding(io),
Qnil);
7104rb_file_open_generic(
VALUE io,
VALUE filename,
int oflags,
int fmode,
7112 rb_io_ext_int_to_encs(NULL, NULL, &cc.
enc, &cc.
enc2, fmode);
7117 validate_enc_binmode(&fmode, convconfig->
ecflags,
7118 convconfig->
enc, convconfig->
enc2);
7122 fptr->
encs = *convconfig;
7125 if (!(oflags & O_TMPFILE)) {
7126 fptr->
pathv = pathv;
7129 fptr->
pathv = pathv;
7131 fptr->
fd = rb_sysopen(pathv, oflags, perm);
7139rb_file_open_internal(
VALUE io,
VALUE filename,
const char *modestr)
7142 const char *p = strchr(modestr,
':');
7146 parse_mode_enc(p+1, rb_usascii_encoding(),
7147 &convconfig.
enc, &convconfig.
enc2, &fmode);
7155 e = (fmode &
FMODE_BINMODE) ? rb_ascii8bit_encoding() : NULL;
7156 rb_io_ext_int_to_encs(e, NULL, &convconfig.
enc, &convconfig.
enc2, fmode);
7161 return rb_file_open_generic(io, filename,
7162 rb_io_fmode_oflags(fmode),
7172 return rb_file_open_internal(io_alloc(
rb_cFile), fname, modestr);
7181#if defined(__CYGWIN__) || !defined(HAVE_WORKING_FORK)
7204 while ((tmp = *prev) != 0) {
7205 if (tmp->fptr == fptr) {
7214#if defined (_WIN32) || defined(__CYGWIN__)
7223 rb_io_fptr_finalize(list->fptr);
7230pipe_finalize(
rb_io_t *fptr,
int noraise)
7232#if !defined(HAVE_WORKING_FORK) && !defined(_WIN32)
7241 fptr_finalize(fptr, noraise);
7243 pipe_del_fptr(fptr);
7250#if defined(__CYGWIN__) || !defined(HAVE_WORKING_FORK)
7253 if (old_finalize == orig->finalize)
return;
7258#if defined(__CYGWIN__) || !defined(HAVE_WORKING_FORK)
7259 if (old_finalize != pipe_finalize) {
7261 for (list =
pipe_list; list; list = list->next) {
7262 if (list->fptr == fptr)
break;
7264 if (!list) pipe_add_fptr(fptr);
7267 pipe_del_fptr(fptr);
7280rb_io_unbuffered(
rb_io_t *fptr)
7291 if (rb_gc_for_fd(errno)) {
7303#define HAVE_SPAWNV 1
7304#define spawnv(mode, cmd, args) rb_w32_uaspawn((mode), (cmd), (args))
7305#define spawn(mode, cmd) rb_w32_uspawn((mode), (cmd), 0)
7308#if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
7318#ifdef HAVE_WORKING_FORK
7319# ifndef __EMSCRIPTEN__
7321popen_redirect(
struct popen_arg *p)
7324 close(p->write_pair[1]);
7325 if (p->write_pair[0] != 0) {
7326 dup2(p->write_pair[0], 0);
7327 close(p->write_pair[0]);
7330 if (p->pair[1] != 1) {
7331 dup2(p->pair[1], 1);
7337 if (p->pair[1] != 1) {
7338 dup2(p->pair[1], 1);
7344 if (p->pair[0] != 0) {
7345 dup2(p->pair[0], 0);
7352#if defined(__linux__)
7363linux_get_maxfd(
void)
7366 char buf[4096], *p, *np, *e;
7369 if (fd < 0)
return fd;
7370 ss = read(fd, buf,
sizeof(buf));
7371 if (ss < 0)
goto err;
7374 while ((
int)
sizeof(
"FDSize:\t0\n")-1 <= e-p &&
7375 (np = memchr(p,
'\n', e-p)) != NULL) {
7376 if (memcmp(p,
"FDSize:",
sizeof(
"FDSize:")-1) == 0) {
7378 p +=
sizeof(
"FDSize:")-1;
7398#if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
7400 int max = (int)max_file_descriptor;
7403 ret = fcntl(0, F_MAXFD);
7405 maxhint = max = ret;
7406# elif defined(__linux__)
7407 ret = linux_get_maxfd();
7414 for (fd = lowfd; fd <= max; fd++) {
7415 if (!
NIL_P(noclose_fds) &&
7418 ret = fcntl(fd, F_GETFD);
7419 if (ret != -1 && !(ret & FD_CLOEXEC)) {
7420 fcntl(fd, F_SETFD, ret|FD_CLOEXEC);
7422# define CONTIGUOUS_CLOSED_FDS 20
7424 if (max < fd + CONTIGUOUS_CLOSED_FDS)
7425 max = fd + CONTIGUOUS_CLOSED_FDS;
7431# ifndef __EMSCRIPTEN__
7433popen_exec(
void *pp,
char *errmsg,
size_t errmsg_len)
7435 struct popen_arg *p = (
struct popen_arg*)pp;
7437 return rb_exec_async_signal_safe(p->eargp, errmsg, errmsg_len);
7442#if (defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)) && !defined __EMSCRIPTEN__
7444rb_execarg_fixup_v(
VALUE execarg_obj)
7446 rb_execarg_parent_start(execarg_obj);
7450char *rb_execarg_commandline(
const struct rb_execarg *eargp,
VALUE *prog);
7453#ifndef __EMSCRIPTEN__
7455pipe_open(
VALUE execarg_obj,
const char *modestr,
int fmode,
7458 struct rb_execarg *eargp =
NIL_P(execarg_obj) ? NULL : rb_execarg_get(execarg_obj);
7459 VALUE prog = eargp ? (eargp->use_shell ? eargp->invoke.sh.shell_script : eargp->invoke.cmd.command_name) :
Qfalse ;
7465#if defined(HAVE_WORKING_FORK)
7467 char errmsg[80] = {
'\0' };
7469#if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
7471 struct popen_arg arg;
7474#if defined(HAVE_SPAWNV)
7475# if defined(HAVE_SPAWNVE)
7476# define DO_SPAWN(cmd, args, envp) ((args) ? \
7477 spawnve(P_NOWAIT, (cmd), (args), (envp)) : \
7478 spawne(P_NOWAIT, (cmd), (envp)))
7480# define DO_SPAWN(cmd, args, envp) ((args) ? \
7481 spawnv(P_NOWAIT, (cmd), (args)) : \
7482 spawn(P_NOWAIT, (cmd)))
7484# if !defined(HAVE_WORKING_FORK)
7486# if defined(HAVE_SPAWNVE)
7491#if !defined(HAVE_WORKING_FORK)
7497#if !defined(HAVE_WORKING_FORK)
7498 const char *cmd = 0;
7504#if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
7505 arg.execarg_obj = execarg_obj;
7508 arg.pair[0] = arg.pair[1] = -1;
7509 arg.write_pair[0] = arg.write_pair[1] = -1;
7510# if !defined(HAVE_WORKING_FORK)
7511 if (eargp && !eargp->use_shell) {
7512 args = ARGVSTR2ARGV(eargp->invoke.cmd.argv_str);
7517 if (
rb_pipe(arg.write_pair) < 0)
7521 close(arg.write_pair[0]);
7522 close(arg.write_pair[1]);
7526 rb_execarg_addopt(execarg_obj,
INT2FIX(0),
INT2FIX(arg.write_pair[0]));
7527 rb_execarg_addopt(execarg_obj,
INT2FIX(1),
INT2FIX(arg.pair[1]));
7534 rb_execarg_addopt(execarg_obj,
INT2FIX(1),
INT2FIX(arg.pair[1]));
7540 rb_execarg_addopt(execarg_obj,
INT2FIX(0),
INT2FIX(arg.pair[0]));
7545 if (!
NIL_P(execarg_obj)) {
7546 rb_protect(rb_execarg_fixup_v, execarg_obj, &state);
7548 if (0 <= arg.write_pair[0]) close(arg.write_pair[0]);
7549 if (0 <= arg.write_pair[1]) close(arg.write_pair[1]);
7550 if (0 <= arg.pair[0]) close(arg.pair[0]);
7551 if (0 <= arg.pair[1]) close(arg.pair[1]);
7552 rb_execarg_parent_end(execarg_obj);
7556# if defined(HAVE_WORKING_FORK)
7557 pid = rb_fork_async_signal_safe(&status, popen_exec, &arg, arg.eargp->redirect_fds, errmsg,
sizeof(errmsg));
7559 rb_execarg_run_options(eargp, sargp, NULL, 0);
7560# if defined(HAVE_SPAWNVE)
7561 if (eargp->envp_str) envp = (
char **)
RSTRING_PTR(eargp->envp_str);
7563 while ((pid = DO_SPAWN(cmd, args, envp)) < 0) {
7565 switch (e = errno) {
7567# if EWOULDBLOCK != EAGAIN
7576 rb_execarg_run_options(sargp, NULL, NULL, 0);
7578 rb_execarg_parent_end(execarg_obj);
7581# if defined(HAVE_WORKING_FORK)
7582 pid = rb_call_proc__fork();
7584 popen_redirect(&arg);
7596# if defined(HAVE_WORKING_FORK)
7602 close(arg.write_pair[0]);
7603 close(arg.write_pair[1]);
7605# if defined(HAVE_WORKING_FORK)
7614 close(arg.write_pair[0]);
7615 write_fd = arg.write_pair[1];
7626 cmd = rb_execarg_commandline(eargp, &prog);
7627 if (!
NIL_P(execarg_obj)) {
7628 rb_execarg_parent_start(execarg_obj);
7629 rb_execarg_run_options(eargp, sargp, NULL, 0);
7631 fp = popen(cmd, modestr);
7634 rb_execarg_parent_end(execarg_obj);
7635 rb_execarg_run_options(sargp, NULL, NULL, 0);
7637 if (!fp) rb_syserr_fail_path(e, prog);
7647 fptr->
encs = *convconfig;
7648#if RUBY_CRLF_ENVIRONMENT
7655 if (NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {
7658#ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
7659 if (NEED_NEWLINE_DECORATOR_ON_WRITE(fptr)) {
7660 fptr->
encs.
ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
7666 if (0 <= write_fd) {
7667 write_port = io_alloc(
rb_cIO);
7669 write_fptr->
fd = write_fd;
7671 fptr->
mode &= ~FMODE_WRITABLE;
7676#if defined (__CYGWIN__) || !defined(HAVE_WORKING_FORK)
7678 pipe_add_fptr(fptr);
7684pipe_open(
VALUE execarg_obj,
const char *modestr,
int fmode,
7692is_popen_fork(
VALUE prog)
7695#if !defined(HAVE_WORKING_FORK)
7697 "fork() function is unimplemented on this machine");
7706pipe_open_s(
VALUE prog,
const char *modestr,
int fmode,
7710 VALUE *argv = &prog;
7713 if (!is_popen_fork(prog))
7714 execarg_obj = rb_execarg_new(argc, argv, TRUE, FALSE);
7715 return pipe_open(execarg_obj, modestr, fmode, convconfig);
7721 rb_io_t *fptr = io_close_fptr(io);
7889rb_io_s_popen(
int argc,
VALUE *argv,
VALUE klass)
7893 if (argc > 1 && !
NIL_P(opt = rb_check_hash_type(argv[argc-1]))) --argc;
7894 if (argc > 1 && !
NIL_P(env = rb_check_hash_type(argv[0]))) --argc, ++argv;
7903 int ex = !
NIL_P(opt);
7904 rb_error_arity(argc + ex, 1 + ex, 2 + ex);
7907 return popen_finish(rb_io_popen(pname, pmode, env, opt), klass);
7913 const char *modestr;
7918 tmp = rb_check_array_type(pname);
7921#if SIZEOF_LONG > SIZEOF_INT
7922 if (len > INT_MAX) {
7926 execarg_obj = rb_execarg_new((
int)len,
RARRAY_CONST_PTR(tmp), FALSE, FALSE);
7932 if (!is_popen_fork(pname))
7933 execarg_obj = rb_execarg_new(1, &pname, TRUE, FALSE);
7935 if (!
NIL_P(execarg_obj)) {
7937 opt = rb_execarg_extract_options(execarg_obj, opt);
7939 rb_execarg_setenv(execarg_obj, env);
7942 modestr = rb_io_oflags_modestr(oflags);
7944 return pipe_open(execarg_obj, modestr, fmode, &convconfig);
7960 RBASIC_SET_CLASS(port, klass);
7968rb_scan_open_args(
int argc,
const VALUE *argv,
7969 VALUE *fname_p,
int *oflags_p,
int *fmode_p,
7972 VALUE opt, fname, vmode, vperm;
7976 argc =
rb_scan_args(argc, argv,
"12:", &fname, &vmode, &vperm, &opt);
7990rb_open_file(
int argc,
const VALUE *argv,
VALUE io)
7997 rb_scan_open_args(argc, argv, &fname, &oflags, &fmode, &convconfig, &perm);
7998 rb_file_open_generic(io, fname, oflags, fmode, &convconfig, perm);
8036rb_io_s_open(
int argc,
VALUE *argv,
VALUE klass)
8068 VALUE fname, vmode, vperm;
8073 rb_scan_args(argc, argv,
"12", &fname, &vmode, &vperm);
8084 if (
NIL_P(vperm)) perm = 0666;
8088 fd = rb_sysopen(fname, oflags, perm);
8093check_pipe_command(
VALUE filename_or_command)
8100 if (rb_enc_ascget(s, e, &chlen, rb_enc_get(filename_or_command)) ==
'|') {
8209 int redirect = FALSE;
8217 VALUE tmp = argv[0];
8223 VALUE cmd = check_pipe_command(tmp);
8226 return rb_io_s_popen(argc, argv,
rb_cIO);
8239 return rb_io_s_open(argc, argv,
rb_cFile);
8253 return rb_io_open_generic(io, filename, oflags, fmode, &convconfig, perm);
8257rb_io_open_generic(
VALUE klass,
VALUE filename,
int oflags,
int fmode,
8261 if (klass ==
rb_cIO && !
NIL_P(cmd = check_pipe_command(filename))) {
8262 return pipe_open_s(cmd, rb_io_oflags_modestr(oflags), fmode, convconfig);
8265 return rb_file_open_generic(io_alloc(klass), filename,
8266 oflags, fmode, convconfig, perm);
8281 if (fptr == orig)
return io;
8282 if (IS_PREP_STDIO(fptr)) {
8287 "%s can't change access mode from \"%s\" to \"%s\"",
8288 PREP_STDIO_NAME(fptr), rb_io_fmode_modestr(fptr->
mode),
8289 rb_io_fmode_modestr(orig->
mode));
8293 if (io_fflush(fptr) < 0)
8294 rb_sys_fail_on_write(fptr);
8297 flush_before_seek(fptr);
8300 pos = io_tell(orig);
8303 if (io_fflush(orig) < 0)
8304 rb_sys_fail_on_write(fptr);
8312 else if (!IS_PREP_STDIO(fptr)) fptr->
pathv =
Qnil;
8313 fptr_copy_finalizer(fptr, orig);
8318 if (IS_PREP_STDIO(fptr) || fd <= 2 || !fptr->stdio_file) {
8321 rb_sys_fail_path(orig->
pathv);
8329 rb_sys_fail_path(orig->
pathv);
8335 if (io_seek(fptr, pos, SEEK_SET) < 0 && errno) {
8336 rb_sys_fail_path(fptr->
pathv);
8338 if (io_seek(orig, pos, SEEK_SET) < 0 && errno) {
8339 rb_sys_fail_path(orig->
pathv);
8353int rb_freopen(
VALUE fname,
const char *mode,
FILE *fp);
8356rb_freopen(
VALUE fname,
const char *mode,
FILE *fp)
8401rb_io_reopen(
int argc,
VALUE *argv,
VALUE file)
8403 VALUE fname, nmode, opt;
8407 if (
rb_scan_args(argc, argv,
"11:", &fname, &nmode, &opt) == 1) {
8410 return io_reopen(file, tmp);
8416 fptr =
RFILE(file)->fptr;
8426 if (IS_PREP_STDIO(fptr) &&
8430 "%s can't change access mode from \"%s\" to \"%s\"",
8431 PREP_STDIO_NAME(fptr), rb_io_fmode_modestr(fptr->
mode),
8432 rb_io_fmode_modestr(fmode));
8435 fptr->
encs = convconfig;
8438 oflags = rb_io_fmode_oflags(fptr->
mode);
8441 fptr->
pathv = fname;
8443 fptr->
fd = rb_sysopen(fptr->
pathv, oflags, 0666);
8449 if (io_fflush(fptr) < 0)
8450 rb_sys_fail_on_write(fptr);
8455 int e = rb_freopen(rb_str_encode_ospath(fptr->
pathv),
8456 rb_io_oflags_modestr(oflags),
8458 if (e) rb_syserr_fail_path(e, fptr->
pathv);
8462 if (setvbuf(fptr->
stdio_file, NULL, _IOFBF, 0) != 0)
8463 rb_warn(
"setvbuf() can't be honoured for %"PRIsVALUE, fptr->
pathv);
8466 if (setvbuf(fptr->
stdio_file, NULL, _IONBF, BUFSIZ) != 0)
8467 rb_warn(
"setvbuf() can't be honoured for %"PRIsVALUE, fptr->
pathv);
8469 else if (fptr->
stdio_file == stdout && isatty(fptr->
fd)) {
8470 if (setvbuf(fptr->
stdio_file, NULL, _IOLBF, BUFSIZ) != 0)
8471 rb_warn(
"setvbuf() can't be honoured for %"PRIsVALUE, fptr->
pathv);
8475 int tmpfd = rb_sysopen(fptr->
pathv, oflags, 0666);
8481 rb_syserr_fail_path(err, fptr->
pathv);
8505 fptr->
mode = orig->
mode & ~FMODE_PREP;
8511 fptr_copy_finalizer(fptr, orig);
8513 fd = ruby_dup(orig->
fd);
8515 pos = io_tell(orig);
8517 io_seek(fptr, pos, SEEK_SET);
8522 write_io = GetWriteIO(io);
8523 if (io != write_io) {
8589 if (argc == 0)
return Qnil;
8608 rb_warn_deprecated(
"`%s'", NULL,
rb_id2name(
id));
8681 if (argc > 1 && !
NIL_P(rb_output_fs)) {
8684 for (i=0; i<argc; i++) {
8685 if (!
NIL_P(rb_output_fs) && i>0) {
8789#define forward(obj, id, argc, argv) \
8790 rb_funcallv_kw(obj, id, argc, argv, RB_PASS_CALLED_KEYWORDS)
8791#define forward_public(obj, id, argc, argv) \
8792 rb_funcallv_public_kw(obj, id, argc, argv, RB_PASS_CALLED_KEYWORDS)
8793#define forward_current(id, argc, argv) \
8794 forward_public(ARGF.current_file, id, argc, argv)
8812 if (recv == r_stdout) {
8813 return rb_io_putc(recv, ch);
8815 return forward(r_stdout,
rb_intern(
"putc"), 1, &ch);
8820rb_str_end_with_asciichar(
VALUE str,
int c)
8827 if (len == 0)
return 0;
8829 return ptr[len - 1] == c;
8831 return rb_enc_ascget(ptr + ((len - 1) / n) * n, ptr + len, &n, enc) == c;
8845 ary = rb_check_array_type(ary);
8904 VALUE line, args[2];
8911 for (
int i = 0; i < argc; i++) {
8930 if (!rb_str_end_with_asciichar(line,
'\n')) {
8935 rb_io_writev(out, n, args);
8954 if (recv == r_stdout) {
8957 return forward(r_stdout,
rb_intern(
"puts"), argc, argv);
8961rb_p_write(
VALUE str)
8968 rb_method_basic_definition_p(
CLASS_OF(r_stdout), id_write)) {
8969 io_writev(2, args, r_stdout);
8972 rb_io_writev(r_stdout, 2, args);
8984rb_p_result(
int argc,
const VALUE *argv)
8991 else if (argc > 1) {
9033 for (i=0; i<argc; i++) {
9035 rb_uninterruptible(rb_p_write, inspected);
9037 return rb_p_result(argc, argv);
9058rb_obj_display(
int argc,
VALUE *argv,
VALUE self)
9069rb_stderr_to_original_p(
VALUE err)
9071 return (err == orig_stderr ||
RFILE(orig_stderr)->fptr->
fd < 0);
9078 if (rb_stderr_to_original_p(out)) {
9080 if (isatty(fileno(stderr))) {
9081 if (rb_w32_write_console(
rb_str_new(mesg, len), fileno(stderr)) > 0)
return;
9084 if (fwrite(mesg,
sizeof(
char), (
size_t)len, stderr) < (
size_t)len) {
9101rb_write_error_str(
VALUE mesg)
9105 if (rb_stderr_to_original_p(out)) {
9108 if (isatty(fileno(stderr))) {
9109 if (rb_w32_write_console(mesg, fileno(stderr)) > 0)
return;
9112 if (fwrite(
RSTRING_PTR(mesg),
sizeof(
char), len, stderr) < len) {
9124rb_stderr_tty_p(
void)
9127 return isatty(fileno(stderr));
9132must_respond_to(
ID mid,
VALUE val,
ID id)
9136 rb_id2str(
id), rb_id2str(mid),
9148stdin_getter(
ID id,
VALUE *ptr)
9156 must_respond_to(id_write, val,
id);
9161stdout_getter(
ID id,
VALUE *ptr)
9169 must_respond_to(id_write, val,
id);
9174stderr_getter(
ID id,
VALUE *ptr)
9180prep_io(
int fd,
int fmode,
VALUE klass,
const char *path)
9183 VALUE io = io_alloc(klass);
9190 if (!io_check_tty(fp)) {
9193 setmode(fd, O_BINARY);
9207 if (path && strcmp(path,
"-")) klass =
rb_cFile;
9212prep_stdio(
FILE *f,
int fmode,
VALUE klass,
const char *path)
9215 VALUE io = prep_io(fileno(f), fmode|FMODE_PREP|DEFAULT_TEXTMODE, klass, path);
9219#ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
9220 fptr->
encs.
ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
9231rb_io_prep_stdin(
void)
9237rb_io_prep_stdout(
void)
9243rb_io_prep_stderr(
void)
9252 int oflags = rb_io_fmode_oflags(fptr->
mode) & ~O_EXCL;
9279 rb_io_buffer_init(&fp->
wbuf);
9280 rb_io_buffer_init(&fp->
rbuf);
9281 rb_io_buffer_init(&fp->
cbuf);
9299rb_io_make_open_file(
VALUE obj)
9304 if (
RFILE(obj)->fptr) {
9306 rb_io_fptr_finalize(
RFILE(obj)->fptr);
9307 RFILE(obj)->fptr = 0;
9309 fp = rb_io_fptr_new();
9311 RFILE(obj)->fptr = fp;
9357rb_io_initialize(
int argc,
VALUE *argv,
VALUE io)
9361 int fd, fmode, oflags = O_RDONLY;
9364#if defined(HAVE_FCNTL) && defined(F_GETFL)
9371 argc =
rb_scan_args(argc, argv,
"11:", &fnum, &vmode, &opt);
9378#if defined(HAVE_FCNTL) && defined(F_GETFL)
9379 oflags = fcntl(fd, F_GETFL);
9385#if defined(HAVE_FCNTL) && defined(F_GETFL)
9398 if (rb_hash_aref(opt, sym_autoclose) ==
Qfalse) {
9399 fmode |= FMODE_PREP;
9402 path = rb_hash_aref(opt,
RB_ID2SYM(idPath));
9413 fp->
encs = convconfig;
9418 if (fileno(stdin) == fd)
9420 else if (fileno(stdout) == fd)
9422 else if (fileno(stderr) == fd)
9454rb_io_set_encoding_by_bom(
VALUE io)
9465 else if (fptr->
encs.
enc && fptr->
encs.
enc != rb_ascii8bit_encoding()) {
9469 if (!io_set_encoding_by_bom(io))
return Qnil;
9470 return rb_enc_from_encoding(fptr->
encs.
enc);
9515rb_file_initialize(
int argc,
VALUE *argv,
VALUE io)
9517 if (
RFILE(io)->fptr) {
9520 if (0 < argc && argc < 3) {
9525 return rb_io_initialize(argc, argv, io);
9528 rb_open_file(argc, argv, io);
9535rb_io_s_new(
int argc,
VALUE *argv,
VALUE klass)
9540 rb_warn(
"%"PRIsVALUE
"::new() does not take block; use %"PRIsVALUE
"::open() instead",
9556rb_io_s_for_fd(
int argc,
VALUE *argv,
VALUE klass)
9559 rb_io_initialize(argc, argv, io);
9572rb_io_autoclose_p(
VALUE io)
9576 return RBOOL(!(fptr->
mode & FMODE_PREP));
9597rb_io_set_autoclose(
VALUE io,
VALUE autoclose)
9601 if (!
RTEST(autoclose))
9602 fptr->
mode |= FMODE_PREP;
9604 fptr->
mode &= ~FMODE_PREP;
9609io_wait_event(
VALUE io,
int event,
VALUE timeout,
int return_io)
9641io_wait_readable(
int argc,
VALUE *argv,
VALUE io)
9651 VALUE timeout = (argc == 1 ? argv[0] :
Qnil);
9665io_wait_writable(
int argc,
VALUE *argv,
VALUE io)
9673 VALUE timeout = (argc == 1 ? argv[0] :
Qnil);
9688io_wait_priority(
int argc,
VALUE *argv,
VALUE io)
9698 VALUE timeout = argc == 1 ? argv[0] :
Qnil;
9704wait_mode_sym(
VALUE mode)
9707 return RB_WAITFD_IN;
9710 return RB_WAITFD_IN;
9713 return RB_WAITFD_IN;
9716 return RB_WAITFD_OUT;
9719 return RB_WAITFD_OUT;
9722 return RB_WAITFD_OUT;
9725 return RB_WAITFD_IN|RB_WAITFD_OUT;
9728 return RB_WAITFD_IN|RB_WAITFD_OUT;
9731 return RB_WAITFD_IN|RB_WAITFD_OUT;
9738io_event_from_value(
VALUE value)
9780 for (
int i = 0; i < argc; i += 1) {
9782 events |= wait_mode_sym(argv[i]);
9784 else if (UNDEF_P(timeout)) {
9792 if (UNDEF_P(timeout)) timeout =
Qnil;
9800 events = io_event_from_value(argv[0]);
9810 if (return_io)
return Qtrue;
9816 return io_wait_event(io, events, timeout, return_io);
9822 struct argf *p = ptr;
9823 rb_gc_mark(p->filename);
9824 rb_gc_mark(p->current_file);
9825 rb_gc_mark(p->argv);
9826 rb_gc_mark(p->inplace);
9827 rb_gc_mark(p->encs.
ecopts);
9831argf_memsize(
const void *ptr)
9833 const struct argf *p = ptr;
9834 size_t size =
sizeof(*p);
9841 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
9848 p->current_file =
Qnil;
9854argf_alloc(
VALUE klass)
9869 memset(&ARGF, 0,
sizeof(ARGF));
9870 argf_init(&ARGF, argv);
9880 ARGF = argf_of(orig);
9907 ARGF.last_lineno = ARGF.lineno;
9933 return forward_current(rb_frame_this_func(), argc, argv);
9936#define next_argv() argf_next_argv(argf)
9937#define ARGF_GENERIC_INPUT_P() \
9938 (ARGF.current_file == rb_stdin && !RB_TYPE_P(ARGF.current_file, T_FILE))
9939#define ARGF_FORWARD(argc, argv) do {\
9940 if (ARGF_GENERIC_INPUT_P())\
9941 return argf_forward((argc), (argv), argf);\
9943#define NEXT_ARGF_FORWARD(argc, argv) do {\
9944 if (!next_argv()) return Qnil;\
9945 ARGF_FORWARD((argc), (argv));\
9951 VALUE file = ARGF.current_file;
9965 int stdout_binmode = 0;
9976 if (ARGF.init_p == 0) {
9986 if (
NIL_P(ARGF.argv)) {
9989 else if (ARGF.next_p == -1 &&
RARRAY_LEN(ARGF.argv) > 0) {
9994 if (ARGF.next_p == 1) {
9995 if (ARGF.init_p == 1) argf_close(
argf);
9998 VALUE filename = rb_ary_shift(ARGF.argv);
10000 ARGF.filename = filename;
10001 filename = rb_str_encode_ospath(filename);
10003 if (
RSTRING_LEN(filename) == 1 && fn[0] ==
'-') {
10005 if (ARGF.inplace) {
10006 rb_warn(
"Can't do inplace edit for stdio; skipping");
10012 int fr = rb_sysopen(filename, O_RDONLY, 0);
10014 if (ARGF.inplace) {
10016#ifndef NO_SAFE_RENAME
10027 if (!
NIL_P(ARGF.inplace)) {
10028 VALUE suffix = ARGF.inplace;
10032 rb_enc_get(suffix), 0,
Qnil))) {
10035#ifdef NO_SAFE_RENAME
10039 rb_warn(
"Can't rename %"PRIsVALUE
" to %"PRIsVALUE
": %s, skipping file",
10040 filename, str, strerror(errno));
10043 fr = rb_sysopen(str, O_RDONLY, 0);
10046 rb_warn(
"Can't rename %"PRIsVALUE
" to %"PRIsVALUE
": %s, skipping file",
10047 filename, str, strerror(errno));
10054#ifdef NO_SAFE_RENAME
10055 rb_fatal(
"Can't do inplace edit without backup");
10057 if (unlink(fn) < 0) {
10058 rb_warn(
"Can't remove %"PRIsVALUE
": %s, skipping file",
10059 filename, strerror(errno));
10065 fw = rb_sysopen(filename, O_WRONLY|O_CREAT|O_TRUNC, 0666);
10066#ifndef NO_SAFE_RENAME
10069 fchmod(fw, st.st_mode);
10071 chmod(fn, st.st_mode);
10073 if (st.st_uid!=st2.st_uid || st.st_gid!=st2.st_gid) {
10076 err = fchown(fw, st.st_uid, st.st_gid);
10078 err = chown(fn, st.st_uid, st.st_gid);
10080 if (err && getuid() == 0 && st2.st_uid == 0) {
10082 rb_warn(
"Can't set owner/group of %"PRIsVALUE
" to same as %"PRIsVALUE
": %s, skipping file",
10083 filename, str, strerror(errno));
10086 (void)unlink(wkfn);
10096 if (!ARGF.binmode) {
10097 fmode |= DEFAULT_TEXTMODE;
10099 ARGF.current_file = prep_io(fr, fmode,
rb_cFile, fn);
10100 if (!
NIL_P(write_io)) {
10107 if (ARGF.encs.enc) {
10108 fptr->
encs = ARGF.encs;
10109 clear_codeconv(fptr);
10112 fptr->
encs.
ecflags &= ~ECONV_NEWLINE_DECORATOR_MASK;
10113 if (!ARGF.binmode) {
10115#ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
10116 fptr->
encs.
ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
10127 else if (ARGF.next_p == -1) {
10130 if (ARGF.inplace) {
10131 rb_warn(
"Can't do inplace edit for stdio");
10135 if (ARGF.init_p == -1) ARGF.init_p = 1;
10143 long lineno = ARGF.lineno;
10146 if (!next_argv())
return Qnil;
10147 if (ARGF_GENERIC_INPUT_P()) {
10148 line = forward_current(idGets, argc, argv);
10155 line = rb_io_getline(argc, argv, ARGF.current_file);
10157 if (
NIL_P(line) && ARGF.next_p != -1) {
10163 if (!
NIL_P(line)) {
10164 ARGF.lineno = ++lineno;
10165 ARGF.last_lineno = ARGF.lineno;
10171argf_lineno_getter(
ID id,
VALUE *var)
10174 return INT2FIX(ARGF.last_lineno);
10182 ARGF.last_lineno = ARGF.lineno = n;
10186rb_reset_argf_lineno(
long n)
10188 ARGF.last_lineno = ARGF.lineno = n;
10229 if (recv ==
argf) {
10230 return argf_gets(argc, argv,
argf);
10232 return forward(
argf, idGets, argc, argv);
10258 line = argf_getline(argc, argv,
argf);
10270 return rb_f_gets(0, 0,
argf);
10274 if (!next_argv())
return Qnil;
10276 if (
NIL_P(line) && ARGF.next_p != -1) {
10282 if (!
NIL_P(line)) {
10284 ARGF.last_lineno = ARGF.lineno;
10310rb_f_readline(
int argc,
VALUE *argv,
VALUE recv)
10312 if (recv ==
argf) {
10313 return argf_readline(argc, argv,
argf);
10342 ARGF_FORWARD(argc, argv);
10343 line = argf_gets(argc, argv,
argf);
10412rb_f_readlines(
int argc,
VALUE *argv,
VALUE recv)
10414 if (recv ==
argf) {
10415 return argf_readlines(argc, argv,
argf);
10439 long lineno = ARGF.lineno;
10442 ary = rb_ary_new();
10443 while (next_argv()) {
10444 if (ARGF_GENERIC_INPUT_P()) {
10445 lines = forward_current(
rb_intern(
"readlines"), argc, argv);
10448 lines = rb_io_readlines(argc, argv, ARGF.current_file);
10452 rb_ary_concat(ary, lines);
10454 ARGF.last_lineno = ARGF.lineno;
10489 rb_last_status_clear();
10490 port = pipe_open_s(str,
"r",
FMODE_READABLE|DEFAULT_TEXTMODE, NULL);
10494 result = read_all(fptr, remain_size(fptr),
Qnil);
10496 RFILE(port)->fptr = NULL;
10497 rb_io_fptr_finalize(fptr);
10503#ifdef HAVE_SYS_SELECT_H
10504#include <sys/select.h>
10518 if (!
NIL_P(read)) {
10523 if (READ_DATA_PENDING(fptr) || READ_CHAR_PENDING(fptr)) {
10527 if (max < fptr->fd) max = fptr->
fd;
10530 timerec.tv_sec = timerec.tv_usec = 0;
10538 if (!
NIL_P(write)) {
10544 if (max < fptr->fd) max = fptr->
fd;
10551 if (!
NIL_P(except)) {
10555 VALUE write_io = GetWriteIO(io);
10558 if (max < fptr->fd) max = fptr->
fd;
10559 if (io != write_io) {
10562 if (max < fptr->fd) max = fptr->
fd;
10577 if (!pending && n == 0)
return Qnil;
10580 rb_ary_push(res, rp?rb_ary_new():
rb_ary_new2(0));
10581 rb_ary_push(res, wp?rb_ary_new():
rb_ary_new2(0));
10582 rb_ary_push(res, ep?rb_ary_new():
rb_ary_new2(0));
10587 VALUE obj = rb_ary_entry(read, i);
10592 rb_ary_push(list, obj);
10600 VALUE obj = rb_ary_entry(write, i);
10602 VALUE write_io = GetWriteIO(io);
10605 rb_ary_push(list, obj);
10613 VALUE obj = rb_ary_entry(except, i);
10615 VALUE write_io = GetWriteIO(io);
10618 rb_ary_push(list, obj);
10620 else if (io != write_io) {
10623 rb_ary_push(list, obj);
10633 VALUE read, write, except;
10639select_call(
VALUE arg)
10643 return select_internal(p->read, p->write, p->except, p->timeout, p->fdsets);
10647select_end(
VALUE arg)
10652 for (i = 0; i < numberof(p->fdsets); ++i)
10657static VALUE sym_normal, sym_sequential, sym_random,
10658 sym_willneed, sym_dontneed, sym_noreuse;
10660#ifdef HAVE_POSIX_FADVISE
10661struct io_advise_struct {
10669io_advise_internal(
void *arg)
10671 struct io_advise_struct *ptr = arg;
10672 return posix_fadvise(ptr->fd, ptr->offset, ptr->len, ptr->advice);
10676io_advise_sym_to_const(
VALUE sym)
10678#ifdef POSIX_FADV_NORMAL
10679 if (sym == sym_normal)
10680 return INT2NUM(POSIX_FADV_NORMAL);
10683#ifdef POSIX_FADV_RANDOM
10684 if (sym == sym_random)
10685 return INT2NUM(POSIX_FADV_RANDOM);
10688#ifdef POSIX_FADV_SEQUENTIAL
10689 if (sym == sym_sequential)
10690 return INT2NUM(POSIX_FADV_SEQUENTIAL);
10693#ifdef POSIX_FADV_WILLNEED
10694 if (sym == sym_willneed)
10695 return INT2NUM(POSIX_FADV_WILLNEED);
10698#ifdef POSIX_FADV_DONTNEED
10699 if (sym == sym_dontneed)
10700 return INT2NUM(POSIX_FADV_DONTNEED);
10703#ifdef POSIX_FADV_NOREUSE
10704 if (sym == sym_noreuse)
10705 return INT2NUM(POSIX_FADV_NOREUSE);
10712do_io_advise(
rb_io_t *fptr,
VALUE advice, rb_off_t offset, rb_off_t len)
10715 struct io_advise_struct ias;
10718 num_adv = io_advise_sym_to_const(advice);
10724 if (
NIL_P(num_adv))
10728 ias.advice =
NUM2INT(num_adv);
10729 ias.offset = offset;
10732 rv = (int)rb_thread_io_blocking_region(io_advise_internal, &ias, fptr->
fd);
10733 if (rv && rv != ENOSYS) {
10740 fptr->
pathv, offset, len, advice);
10750advice_arg_check(
VALUE advice)
10755 if (advice != sym_normal &&
10756 advice != sym_sequential &&
10757 advice != sym_random &&
10758 advice != sym_willneed &&
10759 advice != sym_dontneed &&
10760 advice != sym_noreuse) {
10799rb_io_advise(
int argc,
VALUE *argv,
VALUE io)
10801 VALUE advice, offset, len;
10805 rb_scan_args(argc, argv,
"12", &advice, &offset, &len);
10806 advice_arg_check(advice);
10808 io = GetWriteIO(io);
10814#ifdef HAVE_POSIX_FADVISE
10815 return do_io_advise(fptr, advice, off, l);
10817 ((void)off, (void)l);
10972rb_f_select(
int argc,
VALUE *argv,
VALUE obj)
10975 if (scheduler !=
Qnil) {
10978 if (!UNDEF_P(result))
return result;
10986 rb_scan_args(argc, argv,
"13", &args.read, &args.write, &args.except, &timeout);
10987 if (
NIL_P(timeout)) {
10992 args.timeout = &timerec;
10995 for (i = 0; i < numberof(args.fdsets); ++i)
11001#ifdef IOCTL_REQ_TYPE
11002 typedef IOCTL_REQ_TYPE ioctl_req_t;
11004 typedef int ioctl_req_t;
11005# define NUM2IOCTLREQ(num) ((int)NUM2LONG(num))
11016nogvl_ioctl(
void *ptr)
11018 struct ioctl_arg *arg = ptr;
11020 return (
VALUE)ioctl(arg->fd, arg->cmd, arg->narg);
11024do_ioctl(
int fd, ioctl_req_t cmd,
long narg)
11027 struct ioctl_arg arg;
11033 retval = (int)rb_thread_io_blocking_region(nogvl_ioctl, &arg, fd);
11039#define DEFAULT_IOCTL_NARG_LEN (256)
11041#if defined(__linux__) && defined(_IOC_SIZE)
11043linux_iocparm_len(ioctl_req_t cmd)
11047 if ((cmd & 0xFFFF0000) == 0) {
11049 return DEFAULT_IOCTL_NARG_LEN;
11052 len = _IOC_SIZE(cmd);
11055 if (len < DEFAULT_IOCTL_NARG_LEN)
11056 len = DEFAULT_IOCTL_NARG_LEN;
11064ioctl_narg_len(ioctl_req_t cmd)
11070#define IOCPARM_LEN(x) (((x) >> 16) & IOCPARM_MASK)
11074 len = IOCPARM_LEN(cmd);
11075#elif defined(__linux__) && defined(_IOC_SIZE)
11076 len = linux_iocparm_len(cmd);
11079 len = DEFAULT_IOCTL_NARG_LEN;
11088typedef long fcntl_arg_t;
11091typedef int fcntl_arg_t;
11095fcntl_narg_len(ioctl_req_t cmd)
11102 len =
sizeof(fcntl_arg_t);
11110#ifdef F_DUPFD_CLOEXEC
11111 case F_DUPFD_CLOEXEC:
11112 len =
sizeof(fcntl_arg_t);
11122 len =
sizeof(fcntl_arg_t);
11132 len =
sizeof(fcntl_arg_t);
11142 len =
sizeof(fcntl_arg_t);
11147 len =
sizeof(
struct f_owner_ex);
11152 len =
sizeof(
struct f_owner_ex);
11157 len =
sizeof(
struct flock);
11162 len =
sizeof(
struct flock);
11167 len =
sizeof(
struct flock);
11187 len =
sizeof(fcntl_arg_t);
11197 len =
sizeof(fcntl_arg_t);
11202 len =
sizeof(fcntl_arg_t);
11215fcntl_narg_len(ioctl_req_t cmd)
11221#define NARG_SENTINEL 17
11224setup_narg(ioctl_req_t cmd,
VALUE *argp,
long (*narg_len)(ioctl_req_t))
11235 else if (arg ==
Qtrue) {
11249 len = narg_len(cmd);
11254 if (slen < len+1) {
11261 ptr[slen - 1] = NARG_SENTINEL;
11270finish_narg(
int retval,
VALUE arg,
const rb_io_t *fptr)
11272 if (retval < 0) rb_sys_fail_path(fptr->
pathv);
11277 if (ptr[slen-1] != NARG_SENTINEL)
11279 ptr[slen-1] =
'\0';
11289 ioctl_req_t cmd = NUM2IOCTLREQ(req);
11294 narg = setup_narg(cmd, &arg, ioctl_narg_len);
11296 retval = do_ioctl(fptr->
fd, cmd, narg);
11297 return finish_narg(retval, arg, fptr);
11324 return rb_ioctl(io, req, arg);
11327#define rb_io_ioctl rb_f_notimplement
11338nogvl_fcntl(
void *ptr)
11340 struct fcntl_arg *arg = ptr;
11342#if defined(F_DUPFD)
11343 if (arg->cmd == F_DUPFD)
11346 return (
VALUE)fcntl(arg->fd, arg->cmd, arg->narg);
11350do_fcntl(
int fd,
int cmd,
long narg)
11353 struct fcntl_arg arg;
11359 retval = (int)rb_thread_io_blocking_region(nogvl_fcntl, &arg, fd);
11360 if (retval != -1) {
11362#if defined(F_DUPFD)
11365#if defined(F_DUPFD_CLOEXEC)
11366 case F_DUPFD_CLOEXEC:
11383 narg = setup_narg(cmd, &arg, fcntl_narg_len);
11385 retval = do_fcntl(fptr->
fd, cmd, narg);
11386 return finish_narg(retval, arg, fptr);
11412 return rb_fcntl(io, req, arg);
11415#define rb_io_fcntl rb_f_notimplement
11418#if defined(HAVE_SYSCALL) || defined(HAVE___SYSCALL)
11450#if SIZEOF_VOIDP == 8 && defined(HAVE___SYSCALL) && SIZEOF_INT != 8
11451# define SYSCALL __syscall
11452# define NUM2SYSCALLID(x) NUM2LONG(x)
11453# define RETVAL2NUM(x) LONG2NUM(x)
11454# if SIZEOF_LONG == 8
11455 long num, retval = -1;
11456# elif SIZEOF_LONG_LONG == 8
11457 long long num, retval = -1;
11459# error ---->> it is asserted that __syscall takes the first argument and returns retval in 64bit signed integer. <<----
11461#elif defined(__linux__)
11462# define SYSCALL syscall
11463# define NUM2SYSCALLID(x) NUM2LONG(x)
11464# define RETVAL2NUM(x) LONG2NUM(x)
11472 long num, retval = -1;
11474# define SYSCALL syscall
11475# define NUM2SYSCALLID(x) NUM2INT(x)
11476# define RETVAL2NUM(x) INT2NUM(x)
11477 int num, retval = -1;
11483 "We plan to remove a syscall function at future release. DL(Fiddle) provides safer alternative.");
11488 if (argc > numberof(arg))
11490 num = NUM2SYSCALLID(argv[0]); ++argv;
11491 for (i = argc - 1; i--; ) {
11506 retval = SYSCALL(num);
11509 retval = SYSCALL(num, arg[0]);
11512 retval = SYSCALL(num, arg[0],arg[1]);
11515 retval = SYSCALL(num, arg[0],arg[1],arg[2]);
11518 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3]);
11521 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4]);
11524 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5]);
11527 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6]);
11533 return RETVAL2NUM(retval);
11535#undef NUM2SYSCALLID
11539#define rb_f_syscall rb_f_notimplement
11543io_new_instance(
VALUE args)
11549find_encoding(
VALUE v)
11552 if (!enc)
rb_warn(
"Unsupported encoding %"PRIsVALUE
" ignored", v);
11564 enc2 = find_encoding(v1);
11573 enc = find_encoding(v2);
11580 enc = find_encoding(v2);
11586 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
11592 rb_io_ext_int_to_encs(NULL, NULL, &enc, &enc2, 0);
11593 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
11599 parse_mode_enc(
RSTRING_PTR(tmp), enc, &enc, &enc2, NULL);
11600 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
11604 rb_io_ext_int_to_encs(find_encoding(v1), NULL, &enc, &enc2, 0);
11605 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
11610 validate_enc_binmode(&fptr->
mode, ecflags, enc, enc2);
11615 clear_codeconv(fptr);
11627io_encoding_set_v(
VALUE v)
11630 io_encoding_set(arg->fptr, arg->v1, arg->v2, arg->opt);
11635pipe_pair_close(
VALUE rw)
11638 return rb_ensure(io_close, rwp[0], io_close, rwp[1]);
11721rb_io_s_pipe(
int argc,
VALUE *argv,
VALUE klass)
11723 int pipes[2], state;
11724 VALUE r, w, args[3], v1, v2;
11731 argc =
rb_scan_args(argc, argv,
"02:", &v1, &v2, &opt);
11738 r = rb_protect(io_new_instance, (
VALUE)args, &state);
11742 rb_jump_tag(state);
11746 ies_args.fptr = fptr;
11749 ies_args.opt = opt;
11750 rb_protect(io_encoding_set_v, (
VALUE)&ies_args, &state);
11754 rb_jump_tag(state);
11759 w = rb_protect(io_new_instance, (
VALUE)args, &state);
11763 rb_jump_tag(state);
11768 extract_binmode(opt, &fmode);
11775#if DEFAULT_TEXTMODE
11777 fptr->
mode &= ~FMODE_TEXTMODE;
11778 setmode(fptr->
fd, O_BINARY);
11780#if RUBY_CRLF_ENVIRONMENT
11786 fptr->
mode |= fmode;
11787#if DEFAULT_TEXTMODE
11789 fptr2->
mode &= ~FMODE_TEXTMODE;
11790 setmode(fptr2->
fd, O_BINARY);
11793 fptr2->
mode |= fmode;
11795 ret = rb_assoc_new(r, w);
11827 else if (!
NIL_P(v = rb_hash_aref(opt, sym_open_args))) {
11830 v = rb_to_array_type(v);
11835 arg->io = rb_io_open(klass, path, vmode, vperm, opt);
11839io_s_foreach(
VALUE v)
11844 if (arg->limit == 0)
11846 while (!
NIL_P(str = rb_io_getline_1(arg->rs, arg->limit, arg->chomp, arg->io))) {
11947rb_io_s_foreach(
int argc,
VALUE *argv,
VALUE self)
11950 int orig_argc = argc;
11954 argc =
rb_scan_args(argc, argv,
"12:", NULL, NULL, NULL, &opt);
11956 extract_getline_args(argc-1, argv+1, &garg);
11957 open_key_args(self, argc, argv, opt, &arg);
11959 extract_getline_opts(opt, &garg);
11960 check_getline_args(&garg.rs, &garg.limit, garg.io = arg.io);
11961 return rb_ensure(io_s_foreach, (
VALUE)&garg, rb_io_close, arg.io);
11965io_s_readlines(
VALUE v)
11968 return io_readlines(arg, arg->io);
12043rb_io_s_readlines(
int argc,
VALUE *argv,
VALUE io)
12049 argc =
rb_scan_args(argc, argv,
"12:", NULL, NULL, NULL, &opt);
12050 extract_getline_args(argc-1, argv+1, &garg);
12051 open_key_args(io, argc, argv, opt, &arg);
12053 extract_getline_opts(opt, &garg);
12054 check_getline_args(&garg.rs, &garg.limit, garg.io = arg.io);
12055 return rb_ensure(io_s_readlines, (
VALUE)&garg, rb_io_close, arg.io);
12062 return io_read(arg->argc, arg->argv, arg->io);
12072seek_before_access(
VALUE argp)
12076 return rb_io_seek(arg->io, arg->offset, arg->mode);
12136rb_io_s_read(
int argc,
VALUE *argv,
VALUE io)
12141 argc =
rb_scan_args(argc, argv,
"13:", NULL, NULL, &offset, NULL, &opt);
12142 open_key_args(io, argc, argv, opt, &arg);
12144 if (!
NIL_P(offset)) {
12148 sarg.offset = offset;
12149 sarg.mode = SEEK_SET;
12150 rb_protect(seek_before_access, (
VALUE)&sarg, &state);
12153 rb_jump_tag(state);
12155 if (arg.argc == 2) arg.argc = 1;
12175rb_io_s_binread(
int argc,
VALUE *argv,
VALUE io)
12190 convconfig.
enc = rb_ascii8bit_encoding();
12191 arg.io = rb_io_open_generic(io, argv[0], oflags, fmode, &convconfig, 0);
12194 arg.argc = (argc > 1) ? 1 : 0;
12195 if (!
NIL_P(offset)) {
12199 sarg.offset = offset;
12200 sarg.mode = SEEK_SET;
12201 rb_protect(seek_before_access, (
VALUE)&sarg, &state);
12204 rb_jump_tag(state);
12211io_s_write0(
VALUE v)
12214 return io_write(arg->io,arg->str,arg->nosync);
12218io_s_write(
int argc,
VALUE *argv,
VALUE klass,
int binary)
12220 VALUE string, offset, opt;
12224 rb_scan_args(argc, argv,
"21:", NULL, &
string, &offset, &opt);
12226 if (
NIL_P(opt)) opt = rb_hash_new();
12227 else opt = rb_hash_dup(opt);
12230 if (
NIL_P(rb_hash_aref(opt,sym_mode))) {
12231 int mode = O_WRONLY|O_CREAT;
12233 if (binary) mode |= O_BINARY;
12235 if (
NIL_P(offset)) mode |= O_TRUNC;
12236 rb_hash_aset(opt,sym_mode,
INT2NUM(mode));
12238 open_key_args(klass, argc, argv, opt, &arg);
12241 if (binary) rb_io_binmode_m(arg.io);
12245 if (!
NIL_P(offset)) {
12249 sarg.offset = offset;
12250 sarg.mode = SEEK_SET;
12251 rb_protect(seek_before_access, (
VALUE)&sarg, &state);
12254 rb_jump_tag(state);
12262 return rb_ensure(io_s_write0, (
VALUE)&warg, rb_io_close, arg.io);
12327rb_io_s_write(
int argc,
VALUE *argv,
VALUE io)
12329 return io_s_write(argc, argv, io, 0);
12347rb_io_s_binwrite(
int argc,
VALUE *argv,
VALUE io)
12349 return io_s_write(argc, argv, io, 1);
12355 rb_off_t copy_length;
12356 rb_off_t src_offset;
12360 unsigned close_src : 1;
12361 unsigned close_dst : 1;
12364 const char *syserr;
12365 const char *notimp;
12367 struct stat src_stat;
12368 struct stat dst_stat;
12369#ifdef HAVE_FCOPYFILE
12370 copyfile_state_t copyfile_state;
12375exec_interrupts(
void *arg)
12378 rb_thread_execute_interrupts(th);
12392#if defined(ERESTART)
12397 rb_thread_execute_interrupts(stp->th);
12416fiber_scheduler_wait_for(
void * _arguments)
12426# define IOWAIT_SYSCALL "poll"
12427STATIC_ASSERT(pollin_expected, POLLIN == RB_WAITFD_IN);
12428STATIC_ASSERT(pollout_expected, POLLOUT == RB_WAITFD_OUT);
12433 if (scheduler !=
Qnil) {
12436 return RTEST(args.result);
12440 if (fd == -1)
return 0;
12445 fds.events = events;
12447 int timeout_milliseconds = -1;
12450 timeout_milliseconds = (int)(timeout->tv_sec * 1000) + (int)(timeout->tv_usec / 1000);
12453 return poll(&fds, 1, timeout_milliseconds);
12456# define IOWAIT_SYSCALL "select"
12461 if (scheduler !=
Qnil) {
12464 return RTEST(args.result);
12484 case RB_WAITFD_OUT:
12488 VM_UNREACHABLE(nogvl_wait_for);
12508 ret = nogvl_wait_for(stp->th, stp->src_fptr, RB_WAITFD_IN, NULL);
12510 }
while (ret < 0 && maygvl_copy_stream_continue_p(has_gvl, stp));
12513 stp->syserr = IOWAIT_SYSCALL;
12514 stp->error_no = errno;
12526 ret = nogvl_wait_for(stp->th, stp->dst_fptr, RB_WAITFD_OUT, NULL);
12527 }
while (ret < 0 && maygvl_copy_stream_continue_p(0, stp));
12530 stp->syserr = IOWAIT_SYSCALL;
12531 stp->error_no = errno;
12537#ifdef USE_COPY_FILE_RANGE
12540simple_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)
12542#ifdef HAVE_COPY_FILE_RANGE
12543 return copy_file_range(in_fd, in_offset, out_fd, out_offset, count, flags);
12545 return syscall(__NR_copy_file_range, in_fd, in_offset, out_fd, out_offset, count, flags);
12554 rb_off_t copy_length, src_offset, *src_offset_ptr;
12556 if (!S_ISREG(stp->src_stat.st_mode))
12559 src_size = stp->src_stat.st_size;
12560 src_offset = stp->src_offset;
12561 if (src_offset >= (rb_off_t)0) {
12562 src_offset_ptr = &src_offset;
12565 src_offset_ptr = NULL;
12568 copy_length = stp->copy_length;
12569 if (copy_length < (rb_off_t)0) {
12570 if (src_offset < (rb_off_t)0) {
12571 rb_off_t current_offset;
12573 current_offset = lseek(stp->src_fptr->
fd, 0, SEEK_CUR);
12574 if (current_offset < (rb_off_t)0 && errno) {
12575 stp->syserr =
"lseek";
12576 stp->error_no = errno;
12577 return (
int)current_offset;
12579 copy_length = src_size - current_offset;
12582 copy_length = src_size - src_offset;
12586 retry_copy_file_range:
12587# if SIZEOF_OFF_T > SIZEOF_SIZE_T
12589 ss = (copy_length > (rb_off_t)SSIZE_MAX) ? SSIZE_MAX : (ssize_t)copy_length;
12591 ss = (ssize_t)copy_length;
12593 ss = simple_copy_file_range(stp->src_fptr->
fd, src_offset_ptr, stp->dst_fptr->
fd, NULL, ss, 0);
12597 if (0 < copy_length) {
12598 goto retry_copy_file_range;
12602 if (maygvl_copy_stream_continue_p(0, stp)) {
12603 goto retry_copy_file_range;
12617#if EWOULDBLOCK != EAGAIN
12621 int ret = nogvl_copy_stream_wait_write(stp);
12622 if (ret < 0)
return ret;
12624 goto retry_copy_file_range;
12628 int flags = fcntl(stp->dst_fptr->
fd, F_GETFL);
12630 if (flags != -1 && flags & O_APPEND) {
12636 stp->syserr =
"copy_file_range";
12637 stp->error_no = errno;
12644#ifdef HAVE_FCOPYFILE
12648 rb_off_t cur, ss = 0;
12649 const rb_off_t src_offset = stp->src_offset;
12652 if (stp->copy_length >= (rb_off_t)0) {
12657 if (!S_ISREG(stp->src_stat.st_mode))
12660 if (!S_ISREG(stp->dst_stat.st_mode))
12662 if (lseek(stp->dst_fptr->
fd, 0, SEEK_CUR) > (rb_off_t)0)
12664 if (fcntl(stp->dst_fptr->
fd, F_GETFL) & O_APPEND) {
12667 rb_off_t end = lseek(stp->dst_fptr->
fd, 0, SEEK_END);
12668 lseek(stp->dst_fptr->
fd, 0, SEEK_SET);
12669 if (end > (rb_off_t)0)
return 0;
12672 if (src_offset > (rb_off_t)0) {
12677 cur = lseek(stp->src_fptr->
fd, 0, SEEK_CUR);
12678 if (cur < (rb_off_t)0 && errno) {
12679 stp->error_no = errno;
12684 r = lseek(stp->src_fptr->
fd, src_offset, SEEK_SET);
12685 if (r < (rb_off_t)0 && errno) {
12686 stp->error_no = errno;
12691 stp->copyfile_state = copyfile_state_alloc();
12692 ret = fcopyfile(stp->src_fptr->
fd, stp->dst_fptr->
fd, stp->copyfile_state, COPYFILE_DATA);
12693 copyfile_state_get(stp->copyfile_state, COPYFILE_STATE_COPIED, &ss);
12697 if (src_offset > (rb_off_t)0) {
12701 r = lseek(stp->src_fptr->
fd, cur, SEEK_SET);
12702 if (r < (rb_off_t)0 && errno) {
12703 stp->error_no = errno;
12715 stp->syserr =
"fcopyfile";
12716 stp->error_no = errno;
12723#ifdef HAVE_SENDFILE
12726# define USE_SENDFILE
12728# ifdef HAVE_SYS_SENDFILE_H
12729# include <sys/sendfile.h>
12733simple_sendfile(
int out_fd,
int in_fd, rb_off_t *offset, rb_off_t count)
12735 return sendfile(out_fd, in_fd, offset, (
size_t)count);
12738# elif 0 || defined(__APPLE__)
12742# define USE_SENDFILE
12745simple_sendfile(
int out_fd,
int in_fd, rb_off_t *offset, rb_off_t count)
12748 rb_off_t pos = offset ? *offset : lseek(in_fd, 0, SEEK_CUR);
12751 r = sendfile(in_fd, out_fd, pos, &count, NULL, 0);
12754 r = sendfile(in_fd, out_fd, pos, (
size_t)count, NULL, &sbytes, 0);
12756 if (r != 0 && sbytes == 0)
return r;
12761 lseek(in_fd, sbytes, SEEK_CUR);
12763 return (ssize_t)sbytes;
12776 rb_off_t copy_length;
12777 rb_off_t src_offset;
12780 if (!S_ISREG(stp->src_stat.st_mode))
12783 src_size = stp->src_stat.st_size;
12785 if ((stp->dst_stat.st_mode & S_IFMT) != S_IFSOCK)
12789 src_offset = stp->src_offset;
12790 use_pread = src_offset >= (rb_off_t)0;
12792 copy_length = stp->copy_length;
12793 if (copy_length < (rb_off_t)0) {
12795 copy_length = src_size - src_offset;
12799 cur = lseek(stp->src_fptr->
fd, 0, SEEK_CUR);
12800 if (cur < (rb_off_t)0 && errno) {
12801 stp->syserr =
"lseek";
12802 stp->error_no = errno;
12805 copy_length = src_size - cur;
12810# if SIZEOF_OFF_T > SIZEOF_SIZE_T
12812 ss = (copy_length > (rb_off_t)SSIZE_MAX) ? SSIZE_MAX : (ssize_t)copy_length;
12814 ss = (ssize_t)copy_length;
12817 ss = simple_sendfile(stp->dst_fptr->
fd, stp->src_fptr->
fd, &src_offset, ss);
12820 ss = simple_sendfile(stp->dst_fptr->
fd, stp->src_fptr->
fd, NULL, ss);
12825 if (0 < copy_length) {
12826 goto retry_sendfile;
12830 if (maygvl_copy_stream_continue_p(0, stp))
12831 goto retry_sendfile;
12844#if EWOULDBLOCK != EAGAIN
12857 ret = maygvl_copy_stream_wait_read(0, stp);
12858 if (ret < 0)
return ret;
12860 ret = nogvl_copy_stream_wait_write(stp);
12861 if (ret < 0)
return ret;
12863 goto retry_sendfile;
12865 stp->syserr =
"sendfile";
12866 stp->error_no = errno;
12874maygvl_read(
int has_gvl,
rb_io_t *fptr,
void *buf,
size_t count)
12877 return rb_io_read_memory(fptr, buf, count);
12879 return read(fptr->
fd, buf, count);
12883maygvl_copy_stream_read(
int has_gvl,
struct copy_stream_struct *stp,
char *buf,
size_t len, rb_off_t offset)
12887 if (offset < (rb_off_t)0) {
12888 ss = maygvl_read(has_gvl, stp->src_fptr, buf, len);
12892 ss = pread(stp->src_fptr->
fd, buf, len, offset);
12894 stp->notimp =
"pread";
12902 if (maygvl_copy_stream_continue_p(has_gvl, stp))
12906#if EWOULDBLOCK != EAGAIN
12910 int ret = maygvl_copy_stream_wait_read(has_gvl, stp);
12911 if (ret < 0)
return ret;
12916 stp->notimp =
"pread";
12920 stp->syserr = offset < (rb_off_t)0 ?
"read" :
"pread";
12921 stp->error_no = errno;
12932 ss = write(stp->dst_fptr->
fd, buf+off, len);
12934 if (maygvl_copy_stream_continue_p(0, stp))
12936 if (io_again_p(errno)) {
12937 int ret = nogvl_copy_stream_wait_write(stp);
12938 if (ret < 0)
return ret;
12941 stp->syserr =
"write";
12942 stp->error_no = errno;
12959 rb_off_t copy_length;
12960 rb_off_t src_offset;
12964 copy_length = stp->copy_length;
12965 use_eof = copy_length < (rb_off_t)0;
12966 src_offset = stp->src_offset;
12967 use_pread = src_offset >= (rb_off_t)0;
12969 if (use_pread && stp->close_src) {
12972 r = lseek(stp->src_fptr->
fd, src_offset, SEEK_SET);
12973 if (r < (rb_off_t)0 && errno) {
12974 stp->syserr =
"lseek";
12975 stp->error_no = errno;
12978 src_offset = (rb_off_t)-1;
12982 while (use_eof || 0 < copy_length) {
12983 if (!use_eof && copy_length < (rb_off_t)
sizeof(buf)) {
12984 len = (size_t)copy_length;
12990 ss = maygvl_copy_stream_read(0, stp, buf, len, src_offset);
12995 ss = maygvl_copy_stream_read(0, stp, buf, len, (rb_off_t)-1);
13000 ret = nogvl_copy_stream_write(stp, buf, ss);
13010nogvl_copy_stream_func(
void *arg)
13013#if defined(USE_SENDFILE) || defined(USE_COPY_FILE_RANGE) || defined(HAVE_FCOPYFILE)
13017#ifdef USE_COPY_FILE_RANGE
13018 ret = nogvl_copy_file_range(stp);
13023#ifdef HAVE_FCOPYFILE
13024 ret = nogvl_fcopyfile(stp);
13030 ret = nogvl_copy_stream_sendfile(stp);
13035 nogvl_copy_stream_read_write(stp);
13037#if defined(USE_SENDFILE) || defined(USE_COPY_FILE_RANGE) || defined(HAVE_FCOPYFILE)
13044copy_stream_fallback_body(
VALUE arg)
13047 const int buflen = 16*1024;
13050 rb_off_t rest = stp->copy_length;
13051 rb_off_t off = stp->src_offset;
13052 ID read_method = id_readpartial;
13054 if (!stp->src_fptr) {
13056 read_method = id_read;
13063 if (stp->copy_length < (rb_off_t)0) {
13071 l = buflen < rest ? buflen : (long)rest;
13073 if (!stp->src_fptr) {
13076 if (read_method == id_read &&
NIL_P(rc))
13082 ss = maygvl_copy_stream_read(1, stp,
RSTRING_PTR(buf), l, off);
13088 if (off >= (rb_off_t)0)
13093 stp->total += numwrote;
13095 if (read_method == id_read &&
RSTRING_LEN(buf) == 0) {
13106 if (!stp->src_fptr && stp->src_offset >= (rb_off_t)0) {
13116copy_stream_body(
VALUE arg)
13119 VALUE src_io = stp->src, dst_io = stp->dst;
13120 const int common_oflags = 0
13130 if (src_io ==
argf ||
13134 stp->src_fptr = NULL;
13139 if (!
NIL_P(tmp_io)) {
13146 args[1] =
INT2NUM(O_RDONLY|common_oflags);
13149 stp->close_src = 1;
13154 stat_ret = fstat(stp->src_fptr->
fd, &stp->src_stat);
13155 if (stat_ret < 0) {
13156 stp->syserr =
"fstat";
13157 stp->error_no = errno;
13162 if (dst_io ==
argf ||
13166 stp->dst_fptr = NULL;
13171 if (!
NIL_P(tmp_io)) {
13172 dst_io = GetWriteIO(tmp_io);
13178 args[1] =
INT2NUM(O_WRONLY|O_CREAT|O_TRUNC|common_oflags);
13182 stp->close_dst = 1;
13185 dst_io = GetWriteIO(dst_io);
13191 stat_ret = fstat(stp->dst_fptr->
fd, &stp->dst_stat);
13192 if (stat_ret < 0) {
13193 stp->syserr =
"fstat";
13194 stp->error_no = errno;
13201 SET_BINARY_MODE_WITH_SEEK_CUR(stp->src_fptr);
13204 io_ascii8bit_binmode(stp->dst_fptr);
13206 if (stp->src_offset < (rb_off_t)0 && stp->src_fptr && stp->src_fptr->
rbuf.
len) {
13207 size_t len = stp->src_fptr->
rbuf.
len;
13209 if (stp->copy_length >= (rb_off_t)0 && stp->copy_length < (rb_off_t)len) {
13210 len = (size_t)stp->copy_length;
13214 read_buffered_data(
RSTRING_PTR(str), len, stp->src_fptr);
13215 if (stp->dst_fptr) {
13217 rb_sys_fail_on_write(stp->dst_fptr);
13223 if (stp->copy_length >= (rb_off_t)0)
13224 stp->copy_length -= len;
13227 if (stp->dst_fptr && io_fflush(stp->dst_fptr) < 0) {
13231 if (stp->copy_length == 0)
13234 if (stp->src_fptr == NULL || stp->dst_fptr == NULL) {
13235 return copy_stream_fallback(stp);
13243copy_stream_finalize(
VALUE arg)
13247#ifdef HAVE_FCOPYFILE
13248 if (stp->copyfile_state) {
13249 copyfile_state_free(stp->copyfile_state);
13253 if (stp->close_src) {
13254 rb_io_close_m(stp->src);
13256 if (stp->close_dst) {
13257 rb_io_close_m(stp->dst);
13320rb_io_s_copy_stream(
int argc,
VALUE *argv,
VALUE io)
13322 VALUE src, dst, length, src_offset;
13327 rb_scan_args(argc, argv,
"22", &src, &dst, &length, &src_offset);
13332 st.src_fptr = NULL;
13333 st.dst_fptr = NULL;
13336 st.copy_length = (rb_off_t)-1;
13338 st.copy_length =
NUM2OFFT(length);
13340 if (
NIL_P(src_offset))
13341 st.src_offset = (rb_off_t)-1;
13343 st.src_offset =
NUM2OFFT(src_offset);
13362rb_io_external_encoding(
VALUE io)
13367 return rb_enc_from_encoding(fptr->
encs.
enc2);
13371 return rb_enc_from_encoding(fptr->
encs.
enc);
13374 return rb_enc_from_encoding(io_read_encoding(fptr));
13390rb_io_internal_encoding(
VALUE io)
13395 return rb_enc_from_encoding(io_read_encoding(fptr));
13423rb_io_set_encoding(
int argc,
VALUE *argv,
VALUE io)
13429 return forward(io, id_set_encoding, argc, argv);
13432 argc =
rb_scan_args(argc, argv,
"11:", &v1, &v2, &opt);
13434 io_encoding_set(fptr, v1, v2, opt);
13439rb_stdio_set_default_encoding(
void)
13444 if (isatty(fileno(stdin))) {
13446 rb_encoding *internal = rb_default_internal_encoding();
13447 if (!internal) internal = rb_default_external_encoding();
13449 rb_enc_from_encoding(external),
13450 rb_enc_from_encoding(internal),
13455 rb_io_set_encoding(1, &val,
rb_stdin);
13456 rb_io_set_encoding(1, &val,
rb_stdout);
13457 rb_io_set_encoding(1, &val,
rb_stderr);
13461global_argf_p(
VALUE arg)
13463 return arg ==
argf;
13466typedef VALUE (*argf_encoding_func)(
VALUE io);
13469argf_encoding(
VALUE argf, argf_encoding_func func)
13471 if (!
RTEST(ARGF.current_file)) {
13472 return rb_enc_default_external();
13496 return argf_encoding(
argf, rb_io_external_encoding);
13515 return argf_encoding(
argf, rb_io_internal_encoding);
13554 if (!next_argv()) {
13557 rb_io_set_encoding(argc, argv, ARGF.current_file);
13559 ARGF.encs = fptr->
encs;
13578 if (!next_argv()) {
13581 ARGF_FORWARD(0, 0);
13582 return rb_io_tell(ARGF.current_file);
13595 if (!next_argv()) {
13598 ARGF_FORWARD(argc, argv);
13599 return rb_io_seek_m(argc, argv, ARGF.current_file);
13616 if (!next_argv()) {
13619 ARGF_FORWARD(1, &offset);
13620 return rb_io_set_pos(ARGF.current_file, offset);
13641 if (!next_argv()) {
13644 ARGF_FORWARD(0, 0);
13645 old_lineno =
RFILE(ARGF.current_file)->fptr->lineno;
13646 ret = rb_io_rewind(ARGF.current_file);
13647 if (!global_argf_p(
argf)) {
13648 ARGF.last_lineno = ARGF.lineno -= old_lineno;
13666 if (!next_argv()) {
13669 ARGF_FORWARD(0, 0);
13670 return rb_io_fileno(ARGF.current_file);
13689 ARGF_FORWARD(0, 0);
13690 return ARGF.current_file;
13715 if (
RTEST(ARGF.current_file)) {
13716 if (ARGF.init_p == 0)
return Qtrue;
13718 ARGF_FORWARD(0, 0);
13777 VALUE tmp, str, length;
13781 if (!
NIL_P(length)) {
13791 if (!next_argv()) {
13794 if (ARGF_GENERIC_INPUT_P()) {
13795 tmp = argf_forward(argc, argv,
argf);
13798 tmp = io_read(argc, argv, ARGF.current_file);
13800 if (
NIL_P(str)) str = tmp;
13803 if (ARGF.next_p != -1) {
13809 else if (argc >= 1) {
13826argf_forward_call(
VALUE arg)
13829 argf_forward(p->argc, p->argv, p->argf);
13859 return argf_getpartial(argc, argv,
argf,
Qnil, 0);
13880 return argf_getpartial(argc, argv,
argf, opts, 1);
13886 VALUE tmp, str, length;
13894 no_exception = no_exception_p(opts);
13896 if (!next_argv()) {
13902 if (ARGF_GENERIC_INPUT_P()) {
13912 tmp = io_getpartial(argc, argv, ARGF.current_file, no_exception, nonblock);
13915 if (ARGF.next_p == -1) {
13916 return io_nonblock_eof(no_exception);
13921 return io_nonblock_eof(no_exception);
13959 if (!next_argv())
return Qnil;
13960 if (ARGF_GENERIC_INPUT_P()) {
13961 ch = forward_current(
rb_intern(
"getc"), 0, 0);
13964 ch = rb_io_getc(ARGF.current_file);
13966 if (
NIL_P(ch) && ARGF.next_p != -1) {
13999 if (!next_argv())
return Qnil;
14001 ch = forward_current(
rb_intern(
"getbyte"), 0, 0);
14006 if (
NIL_P(ch) && ARGF.next_p != -1) {
14041 ch = forward_current(
rb_intern(
"getc"), 0, 0);
14044 ch = rb_io_getc(ARGF.current_file);
14046 if (
NIL_P(ch) && ARGF.next_p != -1) {
14078 NEXT_ARGF_FORWARD(0, 0);
14079 c = argf_getbyte(
argf);
14086#define FOREACH_ARGF() while (next_argv())
14091 const VALUE current = ARGF.current_file;
14093 if (ARGF.init_p == -1 || current != ARGF.current_file) {
14099#define ARGF_block_call(mid, argc, argv, func, argf) \
14100 rb_block_call_kw(ARGF.current_file, mid, argc, argv, \
14101 func, argf, rb_keyword_given_p())
14106 VALUE ret = ARGF_block_call(mid, argc, argv, argf_block_call_i,
argf);
14107 if (!UNDEF_P(ret)) ARGF.next_p = 1;
14113 if (!global_argf_p(
argf)) {
14114 ARGF.last_lineno = ++ARGF.lineno;
14116 return argf_block_call_i(i,
argf, argc, argv, blockarg);
14122 VALUE ret = ARGF_block_call(mid, argc, argv, argf_block_call_line_i,
argf);
14123 if (!UNDEF_P(ret)) ARGF.next_p = 1;
14171 argf_block_call_line(
rb_intern(
"each_line"), argc, argv,
argf);
14285 return ARGF.filename;
14289argf_filename_getter(
ID id,
VALUE *var)
14291 return argf_filename(*var);
14316 return ARGF.current_file;
14335 ARGF_FORWARD(0, 0);
14356 return RBOOL(ARGF.binmode);
14376 if (ARGF.init_p && ARGF.next_p == 0) {
14405 if (ARGF.next_p != -1) {
14423 ARGF_FORWARD(0, 0);
14424 return rb_io_closed(ARGF.current_file);
14450 if (!ARGF.inplace)
return Qnil;
14458 return argf_inplace_mode_get(*var);
14489 ARGF.inplace =
Qnil;
14500 argf_inplace_mode_set(*var, val);
14504ruby_set_inplace_mode(
const char *suffix)
14530argf_argv_getter(
ID id,
VALUE *var)
14532 return argf_argv(*var);
14551 if (!
RTEST(ARGF.current_file)) {
14554 return GetWriteIO(ARGF.current_file);
14581 case RB_IO_WAIT_WRITABLE:
14584 c = rb_eEAGAINWaitWritable;
14586#if EAGAIN != EWOULDBLOCK
14588 c = rb_eEWOULDBLOCKWaitWritable;
14592 c = rb_eEINPROGRESSWaitWritable;
14598 case RB_IO_WAIT_READABLE:
14601 c = rb_eEAGAINWaitReadable;
14603#if EAGAIN != EWOULDBLOCK
14605 c = rb_eEWOULDBLOCKWaitReadable;
14609 c = rb_eEINPROGRESSWaitReadable;
14616 rb_bug(
"invalid read/write type passed to rb_readwrite_sys_fail: %d", waiting);
14622get_LAST_READ_LINE(
ID _x,
VALUE *_y)
15274#include <sys/cygwin.h>
15275 static struct __cygwin_perfile pf[] =
15277 {
"", O_RDONLY | O_BINARY},
15278 {
"", O_WRONLY | O_BINARY},
15279 {
"", O_RDWR | O_BINARY},
15280 {
"", O_APPEND | O_BINARY},
15283 cygwin_internal(CW_PERFILE, pf);
15334#if EAGAIN == EWOULDBLOCK
15335 rb_eEWOULDBLOCKWaitReadable = rb_eEAGAINWaitReadable;
15338 rb_eEWOULDBLOCKWaitWritable = rb_eEAGAINWaitWritable;
15380 rb_output_fs =
Qnil;
15392 rb_gvar_ractor_local(
"$_");
15509 rb_gvar_ractor_local(
"$stdin");
15510 rb_gvar_ractor_local(
"$stdout");
15511 rb_gvar_ractor_local(
"$>");
15512 rb_gvar_ractor_local(
"$stderr");
15599 rb_define_method(rb_cARGF,
"external_encoding", argf_external_encoding, 0);
15600 rb_define_method(rb_cARGF,
"internal_encoding", argf_internal_encoding, 0);
15619 rb_gvar_ractor_local(
"$-i");
15623#if defined (_WIN32) || defined(__CYGWIN__)
15624 atexit(pipe_atexit);
15636 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_io_oflags_fmode(int oflags)
Converts an oflags (that rb_io_modestr_oflags() returns) to a fmode (that rb_io_mode_flags() returns)...
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 ...
int rb_io_read_pending(rb_io_t *fptr)
Queries if the passed IO has any pending reads.
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.
void rb_eof_error(void)
Utility function to raise rb_eEOFError.
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.