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) {
928 long len = RSTRING_LEN(str);
931 const int min_capa = IO_RBUF_CAPA_FOR(fptr);
934#if SIZEOF_LONG > SIZEOF_INT
959flush_before_seek(
rb_io_t *fptr)
961 if (io_fflush(fptr) < 0)
962 rb_sys_fail_on_write(fptr);
968#define io_seek(fptr, ofs, whence) (errno = 0, lseek(flush_before_seek(fptr)->fd, (ofs), (whence)))
969#define io_tell(fptr) lseek(flush_before_seek(fptr)->fd, 0, SEEK_CUR)
985 if (io_fflush(fptr) < 0)
986 rb_sys_fail_on_write(fptr);
991 if (io_fflush(wfptr) < 0)
992 rb_sys_fail_on_write(wfptr);
1000 if (READ_CHAR_PENDING(fptr)) {
1012io_read_encoding(
rb_io_t *fptr)
1017 return rb_default_external_encoding();
1021io_input_encoding(
rb_io_t *fptr)
1026 return io_read_encoding(fptr);
1042rb_io_read_pending(
rb_io_t *fptr)
1045 if (READ_CHAR_PENDING(fptr))
1047 return READ_DATA_PENDING(fptr);
1053 if (!READ_DATA_PENDING(fptr)) {
1060rb_gc_for_fd(
int err)
1062 if (err == EMFILE || err == ENFILE || err == ENOMEM) {
1077 if (rb_gc_for_fd(e)) {
1089io_alloc(
VALUE klass)
1099# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
1125struct io_internal_writev_struct {
1132 const struct iovec *iov;
1145io_internal_wait(
VALUE thread,
rb_io_t *fptr,
int error,
int events,
struct timeval *timeout)
1147 int ready = nogvl_wait_for(thread, fptr, events, timeout);
1151 }
else if (ready == 0) {
1161internal_read_func(
void *ptr)
1166 if (iis->timeout && !iis->nonblock) {
1167 if (io_internal_wait(iis->th, iis->fptr, 0, RB_WAITFD_IN, iis->timeout) == -1) {
1173 result = read(iis->fd, iis->buf, iis->capa);
1175 if (result < 0 && !iis->nonblock) {
1176 if (io_again_p(errno)) {
1177 if (io_internal_wait(iis->th, iis->fptr, errno, RB_WAITFD_IN, iis->timeout) == -1) {
1188#if defined __APPLE__
1189# define do_write_retry(code) do {result = code;} while (result == -1 && errno == EPROTOTYPE)
1191# define do_write_retry(code) result = code
1195internal_write_func(
void *ptr)
1200 if (iis->timeout && !iis->nonblock) {
1201 if (io_internal_wait(iis->th, iis->fptr, 0, RB_WAITFD_OUT, iis->timeout) == -1) {
1207 do_write_retry(write(iis->fd, iis->buf, iis->capa));
1209 if (result < 0 && !iis->nonblock) {
1211 if (io_again_p(e)) {
1212 if (io_internal_wait(iis->th, iis->fptr, errno, RB_WAITFD_OUT, iis->timeout) == -1) {
1225internal_writev_func(
void *ptr)
1227 struct io_internal_writev_struct *iis = ptr;
1230 if (iis->timeout && !iis->nonblock) {
1231 if (io_internal_wait(iis->th, iis->fptr, 0, RB_WAITFD_OUT, iis->timeout) == -1) {
1237 do_write_retry(writev(iis->fd, iis->iov, iis->iovcnt));
1239 if (result < 0 && !iis->nonblock) {
1240 if (io_again_p(errno)) {
1241 if (io_internal_wait(iis->th, iis->fptr, errno, RB_WAITFD_OUT, iis->timeout) == -1) {
1254rb_io_read_memory(
rb_io_t *fptr,
void *buf,
size_t count)
1257 if (scheduler !=
Qnil) {
1260 if (!UNDEF_P(result)) {
1276 struct timeval timeout_storage;
1280 iis.timeout = &timeout_storage;
1283 return (ssize_t)rb_thread_io_blocking_region(internal_read_func, &iis, fptr->
fd);
1287rb_io_write_memory(
rb_io_t *fptr,
const void *buf,
size_t count)
1290 if (scheduler !=
Qnil) {
1293 if (!UNDEF_P(result)) {
1309 struct timeval timeout_storage;
1313 iis.timeout = &timeout_storage;
1316 return (ssize_t)rb_thread_io_blocking_region(internal_write_func, &iis, fptr->
fd);
1321rb_writev_internal(
rb_io_t *fptr,
const struct iovec *iov,
int iovcnt)
1324 if (scheduler !=
Qnil) {
1325 for (
int i = 0; i < iovcnt; i += 1) {
1328 if (!UNDEF_P(result)) {
1334 struct io_internal_writev_struct iis = {
1345 struct timeval timeout_storage;
1349 iis.timeout = &timeout_storage;
1352 return (ssize_t)rb_thread_io_blocking_region(internal_writev_func, &iis, fptr->
fd);
1357io_flush_buffer_sync(
void *arg)
1379io_flush_buffer_async(
VALUE arg)
1382 return rb_thread_io_blocking_region(io_flush_buffer_sync, fptr, fptr->
fd);
1389 return (
int)io_flush_buffer_async((
VALUE)fptr);
1404 while (fptr->
wbuf.
len > 0 && io_flush_buffer(fptr) != 0) {
1419 if (scheduler !=
Qnil) {
1429 if (NIL_OR_UNDEF_P(timeout)) {
1433 if (timeout !=
Qnil) {
1438 int ready = rb_thread_wait_for_single_fd(fptr->
fd,
RB_NUM2INT(events), tv);
1458 return prep_io(fd, FMODE_PREP,
rb_cIO, NULL);
1462io_wait_for_single_fd(
int fd,
int events,
struct timeval *timeout)
1466 if (scheduler !=
Qnil) {
1472 return rb_thread_wait_for_single_fd(fd, events, timeout);
1478 io_fd_check_closed(f);
1484#if defined(ERESTART)
1491#if EWOULDBLOCK != EAGAIN
1494 if (scheduler !=
Qnil) {
1512 io_fd_check_closed(f);
1518#if defined(ERESTART)
1534#if EWOULDBLOCK != EAGAIN
1537 if (scheduler !=
Qnil) {
1555 return io_wait_for_single_fd(fd, events, timeout);
1589#if defined(ERESTART)
1599#if EWOULDBLOCK != EAGAIN
1616 if (
RTEST(result)) {
1629 if (
RTEST(result)) {
1641 const char *senc, *denc;
1648 ecflags = fptr->
encs.
ecflags & ~ECONV_NEWLINE_DECORATOR_READ_MASK;
1675 denc = rb_enc_name(enc);
1708io_binwrite_string_internal(
rb_io_t *fptr,
const char *ptr,
long length)
1711 struct iovec iov[2];
1714 iov[0].iov_len = fptr->
wbuf.
len;
1715 iov[1].iov_base = (
void*)ptr;
1716 iov[1].iov_len = length;
1718 ssize_t result = rb_writev_internal(fptr, iov, 2);
1723 if (result >= fptr->
wbuf.
len) {
1731 fptr->
wbuf.
off += (int)result;
1732 fptr->
wbuf.
len -= (int)result;
1740 return rb_io_write_memory(fptr, ptr, length);
1745io_binwrite_string_internal(
rb_io_t *fptr,
const char *ptr,
long length)
1747 long remaining = length;
1750 if (fptr->
wbuf.
len+length <= fptr->wbuf.capa) {
1757 fptr->
wbuf.
len += (int)length;
1764 if (io_fflush(fptr) < 0) {
1769 if (remaining == 0) {
1775 return rb_io_write_memory(fptr, ptr, length);
1780io_binwrite_string(
VALUE arg)
1784 const char *ptr = p->ptr;
1785 size_t remaining = p->length;
1789 ssize_t result = io_binwrite_string_internal(p->fptr, ptr, remaining);
1794 errno = EWOULDBLOCK;
1798 if ((
size_t)result == remaining)
break;
1800 remaining -= result;
1816io_allocate_write_buffer(
rb_io_t *fptr,
int sync)
1821 fptr->
wbuf.
capa = IO_WBUF_CAPA_MIN;
1832io_binwrite_requires_flush_write(
rb_io_t *fptr,
long len,
int nosync)
1847io_binwrite(
VALUE str,
const char *ptr,
long len,
rb_io_t *fptr,
int nosync)
1849 if (len <= 0)
return len;
1854 io_allocate_write_buffer(fptr, !nosync);
1856 if (io_binwrite_requires_flush_write(fptr, len, nosync)) {
1868 return io_binwrite_string((
VALUE)&arg);
1885# define MODE_BTMODE(a,b,c) ((fmode & FMODE_BINMODE) ? (b) : \
1886 (fmode & FMODE_TEXTMODE) ? (c) : (a))
1888#define MODE_BTXMODE(a, b, c, d, e, f) ((fmode & FMODE_EXCL) ? \
1889 MODE_BTMODE(d, e, f) : \
1890 MODE_BTMODE(a, b, c))
1895 if (NEED_WRITECONV(fptr)) {
1897 SET_BINARY_MODE(fptr);
1899 make_writeconv(fptr);
1902#define fmode (fptr->mode)
1905 else if (MODE_BTMODE(DEFAULT_TEXTMODE,0,1) && !rb_enc_asciicompat(rb_enc_get(str))) {
1906 rb_raise(
rb_eArgError,
"ASCII incompatible string written for text mode IO without encoding conversion: %s",
1907 rb_enc_name(rb_enc_get(str)));
1913 common_encoding = rb_enc_from_encoding(fptr->
encs.
enc2);
1914 else if (fptr->
encs.
enc != rb_ascii8bit_encoding())
1915 common_encoding = rb_enc_from_encoding(fptr->
encs.
enc);
1918 if (!
NIL_P(common_encoding)) {
1929#if RUBY_CRLF_ENVIRONMENT
1930#define fmode (fptr->mode)
1931 else if (MODE_BTMODE(DEFAULT_TEXTMODE,0,1)) {
1934 setmode(fptr->
fd, O_BINARY);
1937 setmode(fptr->
fd, O_TEXT);
1939 if (!rb_enc_asciicompat(rb_enc_get(str))) {
1940 rb_raise(
rb_eArgError,
"ASCII incompatible string written for text mode IO without encoding conversion: %s",
1941 rb_enc_name(rb_enc_get(str)));
1959 long len = rb_w32_write_console(str, fptr->
fd);
1960 if (len > 0)
return len;
1964 str = do_writeconv(str, fptr, &converted);
1968 tmp = rb_str_tmp_frozen_acquire(str);
1970 n = io_binwrite(tmp, ptr, len, fptr, nosync);
1971 rb_str_tmp_frozen_release(str, tmp);
1983 return (ssize_t)io_binwrite(0, buf, (
long)size, fptr, 0);
1993 io = GetWriteIO(io);
1999 return rb_funcall(io, id_write, 1, str);
2003 if (RSTRING_LEN(str) == 0)
return INT2FIX(0);
2008 n = io_fwrite(str, fptr, nosync);
2009 if (n < 0L) rb_sys_fail_on_write(fptr);
2015struct binwritev_arg {
2023io_binwritev_internal(
VALUE arg)
2025 struct binwritev_arg *p = (
struct binwritev_arg *)arg;
2027 size_t remaining = p->total;
2031 struct iovec *iov = p->iov;
2032 int iovcnt = p->iovcnt;
2035 long result = rb_writev_internal(fptr, iov, iovcnt);
2040 if (offset < (
size_t)fptr->
wbuf.
len) {
2045 offset -= (size_t)fptr->
wbuf.
len;
2051 if (offset == p->total) {
2055 while (result >= (ssize_t)iov->iov_len) {
2057 result -= iov->iov_len;
2067 iov->iov_base = (
char *)iov->iov_base + result;
2068 iov->iov_len -= result;
2082io_binwritev(
struct iovec *iov,
int iovcnt,
rb_io_t *fptr)
2087 if (iovcnt == 0)
return 0;
2090 for (
int i = 1; i < iovcnt; i++) total += iov[i].iov_len;
2092 io_allocate_write_buffer(fptr, 1);
2098 if (offset + total <= (
size_t)fptr->
wbuf.
capa) {
2099 for (
int i = 1; i < iovcnt; i++) {
2100 memcpy(fptr->
wbuf.
ptr+offset, iov[i].iov_base, iov[i].iov_len);
2101 offset += iov[i].iov_len;
2110 iov[0].iov_len = fptr->
wbuf.
len;
2123 struct binwritev_arg arg;
2126 arg.iovcnt = iovcnt;
2133 return io_binwritev_internal((
VALUE)&arg);
2140 int i, converted, iovcnt = argc + 1;
2142 VALUE v1, v2, str, tmp, *tmp_array;
2148 for (i = 0; i < argc; i++) {
2151 str = do_writeconv(str, fptr, &converted);
2156 tmp = rb_str_tmp_frozen_acquire(str);
2160 iov[i+1].iov_base = RSTRING_PTR(tmp);
2161 iov[i+1].iov_len = RSTRING_LEN(tmp);
2164 n = io_binwritev(iov, iovcnt, fptr);
2167 for (i = 0; i < argc; i++) {
2168 rb_str_tmp_frozen_release(argv[i], tmp_array[i]);
2177iovcnt_ok(
int iovcnt)
2180 return iovcnt < IOV_MAX;
2188io_writev(
int argc,
const VALUE *argv,
VALUE io)
2195 io = GetWriteIO(io);
2200 return rb_funcallv(io, id_write, argc, argv);
2208 for (i = 0; i < argc; i += cnt) {
2211 n = io_fwritev(cnt, &argv[i], fptr);
2222 rb_sys_fail_on_write(fptr);
2224 total = rb_fix_plus(
LONG2FIX(n), total);
2255 return io_writev(argc, argv, io);
2258 VALUE str = argv[0];
2259 return io_write(io, str, 0);
2266 return rb_funcallv(io, id_write, 1, &str);
2270rb_io_writev(
VALUE io,
int argc,
const VALUE *argv)
2278 " which accepts just one argument",
2288 return rb_funcallv(io, id_write, argc, argv);
2320nogvl_fsync(
void *ptr)
2325 if (GetFileType((HANDLE)rb_w32_get_osfhandle(fptr->
fd)) != FILE_TYPE_DISK)
2328 return (
VALUE)fsync(fptr->
fd);
2333rb_io_flush_raw(
VALUE io,
int sync)
2337 if (!RB_TYPE_P(io,
T_FILE)) {
2338 return rb_funcall(io, id_flush, 0);
2341 io = GetWriteIO(io);
2345 if (io_fflush(fptr) < 0)
2346 rb_sys_fail_on_write(fptr);
2370 return rb_io_flush_raw(io, 1);
2399 pos = io_tell(fptr);
2400 if (pos < 0 && errno) rb_sys_fail_path(fptr->
pathv);
2406rb_io_seek(
VALUE io,
VALUE offset,
int whence)
2413 pos = io_seek(fptr, pos, whence);
2414 if (pos < 0 && errno) rb_sys_fail_path(fptr->
pathv);
2420interpret_seek_whence(
VALUE vwhence)
2422 if (vwhence == sym_SET)
2424 if (vwhence == sym_CUR)
2426 if (vwhence == sym_END)
2429 if (vwhence == sym_DATA)
2433 if (vwhence == sym_HOLE)
2489 VALUE offset, ptrname;
2490 int whence = SEEK_SET;
2492 if (rb_scan_args(argc, argv,
"11", &offset, &ptrname) == 2) {
2493 whence = interpret_seek_whence(ptrname);
2496 return rb_io_seek(io, offset, whence);
2524 pos = io_seek(fptr, pos, SEEK_SET);
2525 if (pos < 0 && errno) rb_sys_fail_path(fptr->
pathv);
2530static void clear_readconv(
rb_io_t *fptr);
2557rb_io_rewind(
VALUE io)
2562 if (io_seek(fptr, 0L, 0) < 0 && errno) rb_sys_fail_path(fptr->
pathv);
2563 if (io == ARGF.current_file) {
2564 ARGF.lineno -= fptr->
lineno;
2568 clear_readconv(fptr);
2575fptr_wait_readable(
rb_io_t *fptr)
2593 fptr->
rbuf.
capa = IO_RBUF_CAPA_FOR(fptr);
2604 if (fptr_wait_readable(fptr))
2613 rb_syserr_fail_path(e, path);
2670 if (READ_CHAR_PENDING(fptr))
return Qfalse;
2671 if (READ_DATA_PENDING(fptr))
return Qfalse;
2673#if RUBY_CRLF_ENVIRONMENT
2674 if (!NEED_READCONV(fptr) && NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {
2675 return RBOOL(eof(fptr->
fd));;
2678 return RBOOL(io_fillbuf(fptr) < 0);
2702 io = GetWriteIO(io);
2739 io = GetWriteIO(io);
2745 fptr->
mode &= ~FMODE_SYNC;
2769rb_io_fsync(
VALUE io)
2773 io = GetWriteIO(io);
2776 if (io_fflush(fptr) < 0)
2777 rb_sys_fail_on_write(fptr);
2778 if ((
int)rb_thread_io_blocking_region(nogvl_fsync, fptr, fptr->
fd) < 0)
2779 rb_sys_fail_path(fptr->
pathv);
2783# define rb_io_fsync rb_f_notimplement
2784# define rb_io_sync rb_f_notimplement
2793#ifdef HAVE_FDATASYNC
2795nogvl_fdatasync(
void *ptr)
2800 if (GetFileType((HANDLE)rb_w32_get_osfhandle(fptr->
fd)) != FILE_TYPE_DISK)
2803 return (
VALUE)fdatasync(fptr->
fd);
2818rb_io_fdatasync(
VALUE io)
2822 io = GetWriteIO(io);
2825 if (io_fflush(fptr) < 0)
2826 rb_sys_fail_on_write(fptr);
2828 if ((
int)rb_thread_io_blocking_region(nogvl_fdatasync, fptr, fptr->
fd) == 0)
2832 return rb_io_fsync(io);
2835#define rb_io_fdatasync rb_io_fsync
2855rb_io_fileno(
VALUE io)
2868 if (RB_TYPE_P(io,
T_FILE)) {
2874 return RB_NUM2INT(rb_funcall(io, id_fileno, 0));
2948rb_io_inspect(
VALUE obj)
2952 static const char closed[] =
" (closed)";
2954 fptr =
RFILE(obj)->fptr;
2961 rb_str_cat(result, closed+1, strlen(closed)-1);
2985rb_io_to_io(
VALUE io)
2992read_buffered_data(
char *ptr,
long len,
rb_io_t *fptr)
2996 n = READ_DATA_PENDING_COUNT(fptr);
2997 if (n <= 0)
return 0;
2998 if (n > len) n = (int)len;
3006io_bufread(
char *ptr,
long len,
rb_io_t *fptr)
3012 if (READ_DATA_PENDING(fptr) == 0) {
3016 c = rb_io_read_memory(fptr, ptr+offset, n);
3019 if (fptr_wait_readable(fptr))
3024 if ((n -= c) <= 0)
break;
3030 c = read_buffered_data(ptr+offset, n, fptr);
3033 if ((n -= c) <= 0)
break;
3036 if (io_fillbuf(fptr) < 0) {
3043static int io_setstrbuf(
VALUE *str,
long len);
3052bufread_call(
VALUE arg)
3055 p->len = io_bufread(p->str_ptr, p->len, p->fptr);
3060io_fread(
VALUE str,
long offset,
long size,
rb_io_t *fptr)
3065 io_setstrbuf(&str, offset + size);
3066 arg.str_ptr = RSTRING_PTR(str) + offset;
3069 rb_str_locktmp_ensure(str, bufread_call, (
VALUE)&arg);
3071 if (len < 0) rb_sys_fail_path(fptr->
pathv);
3079 rb_off_t siz = READ_DATA_PENDING_COUNT(fptr);
3082 if (fstat(fptr->
fd, &st) == 0 && S_ISREG(st.st_mode)
3083#
if defined(__HAIKU__)
3088 if (io_fflush(fptr) < 0)
3089 rb_sys_fail_on_write(fptr);
3090 pos = lseek(fptr->
fd, 0, SEEK_CUR);
3091 if (st.st_size >= pos && pos >= 0) {
3092 siz += st.st_size - pos;
3093 if (siz > LONG_MAX) {
3107 rb_enc_associate(str, io_read_encoding(fptr));
3114make_readconv(
rb_io_t *fptr,
int size)
3119 const char *sname, *dname;
3120 ecflags = fptr->
encs.
ecflags & ~ECONV_NEWLINE_DECORATOR_WRITE_MASK;
3123 sname = rb_enc_name(fptr->
encs.
enc2);
3124 dname = rb_enc_name(io_read_encoding(fptr));
3134 if (size < IO_CBUF_CAPA_MIN) size = IO_CBUF_CAPA_MIN;
3140#define MORE_CHAR_SUSPENDED Qtrue
3141#define MORE_CHAR_FINISHED Qnil
3143fill_cbuf(
rb_io_t *fptr,
int ec_flags)
3145 const unsigned char *ss, *sp, *se;
3146 unsigned char *ds, *dp, *de;
3155 return MORE_CHAR_SUSPENDED;
3166 ss = sp = (
const unsigned char *)fptr->
rbuf.
ptr + fptr->
rbuf.
off;
3171 fptr->
rbuf.
off += (int)(sp - ss);
3172 fptr->
rbuf.
len -= (int)(sp - ss);
3173 fptr->
cbuf.
len += (int)(dp - ds);
3178 fptr->
rbuf.
off -= putbackable;
3179 fptr->
rbuf.
len += putbackable;
3186 if (cbuf_len0 != fptr->
cbuf.
len)
3187 return MORE_CHAR_SUSPENDED;
3190 return MORE_CHAR_FINISHED;
3196 if (io_fillbuf(fptr) < 0) {
3198 return MORE_CHAR_FINISHED;
3203 fptr->
cbuf.
len += (int)(dp - ds);
3210 if (cbuf_len0 != fptr->
cbuf.
len)
3211 return MORE_CHAR_SUSPENDED;
3213 return MORE_CHAR_FINISHED;
3221 if (v != MORE_CHAR_SUSPENDED && v != MORE_CHAR_FINISHED)
3238 rb_enc_associate(str, fptr->
encs.
enc);
3253io_setstrbuf(
VALUE *str,
long len)
3257 len = (len + 1) & ~1L;
3265 long clen = RSTRING_LEN(s);
3272 if ((
rb_str_capacity(*str) - (
size_t)RSTRING_LEN(*str)) < (
size_t)len) {
3278#define MAX_REALLOC_GAP 4096
3280io_shrink_read_string(
VALUE str,
long n)
3288io_set_read_length(
VALUE str,
long n,
int shrinkable)
3290 if (RSTRING_LEN(str) != n) {
3293 if (shrinkable) io_shrink_read_string(str, n);
3307 if (NEED_READCONV(fptr)) {
3308 int first = !
NIL_P(str);
3309 SET_BINARY_MODE(fptr);
3310 shrinkable = io_setstrbuf(&str,0);
3311 make_readconv(fptr, 0);
3316 io_shift_cbuf(fptr, fptr->
cbuf.
len, &str);
3318 v = fill_cbuf(fptr, 0);
3319 if (v != MORE_CHAR_SUSPENDED && v != MORE_CHAR_FINISHED) {
3322 io_shift_cbuf(fptr, fptr->
cbuf.
len, &str);
3326 if (v == MORE_CHAR_FINISHED) {
3327 clear_readconv(fptr);
3329 if (shrinkable) io_shrink_read_string(str, RSTRING_LEN(str));
3330 return io_enc_str(str, fptr);
3335 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
3339 enc = io_read_encoding(fptr);
3342 if (siz == 0) siz = BUFSIZ;
3343 shrinkable = io_setstrbuf(&str, siz);
3346 n = io_fread(str, bytes, siz - bytes, fptr);
3347 if (n == 0 && bytes == 0) {
3355 if (bytes < siz)
break;
3359 if (capa < (
size_t)RSTRING_LEN(str) + BUFSIZ) {
3360 if (capa < BUFSIZ) {
3363 else if (capa > IO_MAX_BUFFER_GROWTH) {
3364 capa = IO_MAX_BUFFER_GROWTH;
3369 if (shrinkable) io_shrink_read_string(str, RSTRING_LEN(str));
3370 str = io_enc_str(str, fptr);
3378 if (rb_fd_set_nonblock(fptr->
fd) != 0) {
3379 rb_sys_fail_path(fptr->
pathv);
3384io_read_memory_call(
VALUE arg)
3389 if (scheduler !=
Qnil) {
3392 if (!UNDEF_P(result)) {
3398 return rb_thread_io_blocking_region(internal_read_func, iis, iis->fptr->
fd);
3404 return (
long)rb_str_locktmp_ensure(str, io_read_memory_call, (
VALUE)iis);
3407#define no_exception_p(opts) !rb_opts_exception_p((opts), TRUE)
3410io_getpartial(
int argc,
VALUE *argv,
VALUE io,
int no_exception,
int nonblock)
3418 rb_scan_args(argc, argv,
"11", &length, &str);
3420 if ((len =
NUM2LONG(length)) < 0) {
3424 shrinkable = io_setstrbuf(&str, len);
3430 io_set_read_length(str, 0, shrinkable);
3436 n = read_buffered_data(RSTRING_PTR(str), len, fptr);
3442 io_setstrbuf(&str, len);
3445 iis.nonblock = nonblock;
3447 iis.buf = RSTRING_PTR(str);
3450 n = io_read_memory_locktmp(str, &iis);
3453 if (!nonblock && fptr_wait_readable(fptr))
3455 if (nonblock && (io_again_p(e))) {
3457 return sym_wait_readable;
3460 e,
"read would block");
3462 rb_syserr_fail_path(e, fptr->
pathv);
3465 io_set_read_length(str, n, shrinkable);
3566io_readpartial(
int argc,
VALUE *argv,
VALUE io)
3570 ret = io_getpartial(argc, argv, io,
Qnil, 0);
3577io_nonblock_eof(
int no_exception)
3579 if (!no_exception) {
3594 if ((len =
NUM2LONG(length)) < 0) {
3598 shrinkable = io_setstrbuf(&str, len);
3599 rb_bool_expected(ex,
"exception", TRUE);
3605 io_set_read_length(str, 0, shrinkable);
3609 n = read_buffered_data(RSTRING_PTR(str), len, fptr);
3611 rb_fd_set_nonblock(fptr->
fd);
3612 shrinkable |= io_setstrbuf(&str, len);
3616 iis.buf = RSTRING_PTR(str);
3619 n = io_read_memory_locktmp(str, &iis);
3622 if (io_again_p(e)) {
3623 if (!ex)
return sym_wait_readable;
3625 e,
"read would block");
3627 rb_syserr_fail_path(e, fptr->
pathv);
3630 io_set_read_length(str, n, shrinkable);
3633 if (!ex)
return Qnil;
3649 rb_bool_expected(ex,
"exception", TRUE);
3651 io = GetWriteIO(io);
3655 if (io_fflush(fptr) < 0)
3656 rb_sys_fail_on_write(fptr);
3658 rb_fd_set_nonblock(fptr->
fd);
3659 n = write(fptr->
fd, RSTRING_PTR(str), RSTRING_LEN(str));
3664 if (io_again_p(e)) {
3666 return sym_wait_writable;
3672 rb_syserr_fail_path(e, fptr->
pathv);
3756#if RUBY_CRLF_ENVIRONMENT
3760 rb_scan_args(argc, argv,
"02", &length, &str);
3762 if (
NIL_P(length)) {
3765 return read_all(fptr, remain_size(fptr), str);
3772 shrinkable = io_setstrbuf(&str,len);
3777 io_set_read_length(str, 0, shrinkable);
3782#if RUBY_CRLF_ENVIRONMENT
3783 previous_mode = set_binary_mode_with_seek_cur(fptr);
3785 n = io_fread(str, 0, len, fptr);
3786 io_set_read_length(str, n, shrinkable);
3787#if RUBY_CRLF_ENVIRONMENT
3788 if (previous_mode == O_TEXT) {
3789 setmode(fptr->
fd, O_TEXT);
3792 if (n == 0)
return Qnil;
3798rscheck(
const char *rsptr,
long rslen,
VALUE rs)
3801 if (RSTRING_PTR(rs) != rsptr && RSTRING_LEN(rs) != rslen)
3806appendline(
rb_io_t *fptr,
int delim,
VALUE *strp,
long *lp)
3811 if (NEED_READCONV(fptr)) {
3812 SET_BINARY_MODE(fptr);
3813 make_readconv(fptr, 0);
3816 int searchlen = READ_CHAR_PENDING_COUNT(fptr);
3818 p = READ_CHAR_PENDING_PTR(fptr);
3819 if (0 < limit && limit < searchlen)
3820 searchlen = (int)limit;
3821 e = memchr(p, delim, searchlen);
3823 int len = (int)(e-p+1);
3845 return (
unsigned char)RSTRING_PTR(str)[RSTRING_LEN(str)-1];
3848 }
while (more_char(fptr) != MORE_CHAR_FINISHED);
3849 clear_readconv(fptr);
3854 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
3856 long pending = READ_DATA_PENDING_COUNT(fptr);
3858 const char *p = READ_DATA_PENDING_PTR(fptr);
3862 if (limit > 0 && pending > limit) pending = limit;
3863 e = memchr(p, delim, pending);
3864 if (e) pending = e - p + 1;
3866 last = RSTRING_LEN(str);
3874 read_buffered_data(RSTRING_PTR(str) + last, pending, fptr);
3877 if (e)
return delim;
3879 return (
unsigned char)RSTRING_PTR(str)[RSTRING_LEN(str)-1];
3882 }
while (io_fillbuf(fptr) >= 0);
3888swallow(
rb_io_t *fptr,
int term)
3890 if (NEED_READCONV(fptr)) {
3892 int needconv = rb_enc_mbminlen(enc) != 1;
3893 SET_BINARY_MODE(fptr);
3894 make_readconv(fptr, 0);
3897 while ((cnt = READ_CHAR_PENDING_COUNT(fptr)) > 0) {
3898 const char *p = READ_CHAR_PENDING_PTR(fptr);
3901 if (*p != term)
return TRUE;
3903 while (--i && *++p == term);
3906 const char *e = p + cnt;
3907 if (rb_enc_ascget(p, e, &i, enc) != term)
return TRUE;
3908 while ((p += i) < e && rb_enc_ascget(p, e, &i, enc) == term);
3911 io_shift_cbuf(fptr, (
int)cnt - i, NULL);
3913 }
while (more_char(fptr) != MORE_CHAR_FINISHED);
3917 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
3920 while ((cnt = READ_DATA_PENDING_COUNT(fptr)) > 0) {
3922 const char *p = READ_DATA_PENDING_PTR(fptr);
3924 if (cnt >
sizeof buf) cnt =
sizeof buf;
3925 if (*p != term)
return TRUE;
3927 while (--i && *++p == term);
3928 if (!read_buffered_data(buf, cnt - i, fptr))
3929 rb_sys_fail_path(fptr->
pathv);
3932 }
while (io_fillbuf(fptr) == 0);
3945 int pending = READ_DATA_PENDING_COUNT(fptr);
3948 const char *p = READ_DATA_PENDING_PTR(fptr);
3952 e = memchr(p,
'\n', pending);
3954 pending = (int)(e - p + 1);
3956 chomplen = (pending > 1 && *(e-1) ==
'\r') + 1;
3966 read_buffered_data(RSTRING_PTR(str)+len, pending - chomplen, fptr);
3969 if (pending == 1 && chomplen == 1 && len > 0) {
3970 if (RSTRING_PTR(str)[len-1] ==
'\r') {
3976 len += pending - chomplen;
3982 }
while (io_fillbuf(fptr) >= 0);
3985 str = io_enc_str(str, fptr);
3996 unsigned int chomp: 1;
4007 kwds[0] = rb_intern_const(
"chomp");
4010 chomp = (!UNDEF_P(vchomp)) &&
RTEST(vchomp);
4012 args->chomp = chomp;
4030 else if (2 <= argc) {
4031 rs = argv[0], lim = argv[1];
4040check_getline_args(
VALUE *rsp,
long *limit,
VALUE io)
4049 enc_rs = rb_enc_get(rs);
4050 enc_io = io_read_encoding(fptr);
4051 if (enc_io != enc_rs &&
4052 (!is_ascii_string(rs) ||
4053 (RSTRING_LEN(rs) > 0 && !rb_enc_asciicompat(enc_io)))) {
4054 if (rs == rb_default_rs) {
4055 rs = rb_enc_str_new(0, 0, enc_io);
4061 rb_enc_name(enc_io),
4062 rb_enc_name(enc_rs));
4072 argc = rb_scan_args(argc, argv,
"02:", NULL, NULL, &opts);
4073 extract_getline_args(argc, argv, args);
4074 extract_getline_opts(opts, args);
4075 check_getline_args(&args->rs, &args->limit, io);
4079rb_io_getline_0(
VALUE rs,
long limit,
int chomp,
rb_io_t *fptr)
4086 if (
NIL_P(rs) && limit < 0) {
4087 str = read_all(fptr, 0,
Qnil);
4088 if (RSTRING_LEN(str) == 0)
return Qnil;
4090 else if (limit == 0) {
4091 return rb_enc_str_new(0, 0, io_read_encoding(fptr));
4093 else if (rs == rb_default_rs && limit < 0 && !NEED_READCONV(fptr) &&
4094 rb_enc_asciicompat(enc = io_read_encoding(fptr))) {
4095 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
4096 return rb_io_getline_fast(fptr, enc, chomp);
4099 int c, newline = -1;
4100 const char *rsptr = 0;
4103 int extra_limit = 16;
4104 int chomp_cr = chomp;
4106 SET_BINARY_MODE(fptr);
4107 enc = io_read_encoding(fptr);
4110 rslen = RSTRING_LEN(rs);
4115 swallow(fptr,
'\n');
4117 if (!rb_enc_asciicompat(enc)) {
4121 rsptr = RSTRING_PTR(rs);
4122 rslen = RSTRING_LEN(rs);
4126 rsptr = RSTRING_PTR(rs);
4128 newline = (
unsigned char)rsptr[rslen - 1];
4129 chomp_cr = chomp && rslen == 1 && newline ==
'\n';
4133 while ((c = appendline(fptr, newline, &str, &limit)) != EOF) {
4134 const char *s, *p, *pp, *e;
4137 if (RSTRING_LEN(str) < rslen)
continue;
4138 s = RSTRING_PTR(str);
4139 e = RSTRING_END(str);
4141 pp = rb_enc_left_char_head(s, p, e, enc);
4142 if (pp != p)
continue;
4143 if (!rspara) rscheck(rsptr, rslen, rs);
4144 if (memcmp(p, rsptr, rslen) == 0) {
4146 if (chomp_cr && p > s && *(p-1) ==
'\r') --p;
4153 s = RSTRING_PTR(str);
4154 p = RSTRING_END(str);
4155 pp = rb_enc_left_char_head(s, p-1, p, enc);
4170 if (rspara && c != EOF)
4171 swallow(fptr,
'\n');
4173 str = io_enc_str(str, fptr);
4176 if (!
NIL_P(str) && !nolimit) {
4184rb_io_getline_1(
VALUE rs,
long limit,
int chomp,
VALUE io)
4187 int old_lineno, new_lineno;
4191 old_lineno = fptr->
lineno;
4192 str = rb_io_getline_0(rs, limit, chomp, fptr);
4193 if (!
NIL_P(str) && (new_lineno = fptr->
lineno) != old_lineno) {
4194 if (io == ARGF.current_file) {
4195 ARGF.lineno += new_lineno - old_lineno;
4196 ARGF.last_lineno = ARGF.lineno;
4199 ARGF.last_lineno = new_lineno;
4207rb_io_getline(
int argc,
VALUE *argv,
VALUE io)
4211 prepare_getline_args(argc, argv, &args, io);
4212 return rb_io_getline_1(args.rs, args.limit, args.chomp, io);
4222rb_io_gets_internal(
VALUE io)
4226 return rb_io_getline_0(rb_default_rs, -1, FALSE, fptr);
4309 str = rb_io_getline(argc, argv, io);
4325rb_io_lineno(
VALUE io)
4367rb_io_readline(
int argc,
VALUE *argv,
VALUE io)
4369 VALUE line = rb_io_gets_m(argc, argv, io);
4446rb_io_readlines(
int argc,
VALUE *argv,
VALUE io)
4450 prepare_getline_args(argc, argv, &args, io);
4451 return io_readlines(&args, io);
4459 if (arg->limit == 0)
4462 while (!
NIL_P(line = rb_io_getline_1(arg->rs, arg->limit, arg->chomp, io))) {
4463 rb_ary_push(ary, line);
4580rb_io_each_line(
int argc,
VALUE *argv,
VALUE io)
4586 prepare_getline_args(argc, argv, &args, io);
4587 if (args.limit == 0)
4589 while (!
NIL_P(str = rb_io_getline_1(args.rs, args.limit, args.chomp, io))) {
4616rb_io_each_byte(
VALUE io)
4632 }
while (io_fillbuf(fptr) >= 0);
4642 if (NEED_READCONV(fptr)) {
4646 SET_BINARY_MODE(fptr);
4647 make_readconv(fptr, 0);
4661 if (more_char(fptr) == MORE_CHAR_FINISHED) {
4663 clear_readconv(fptr);
4667 str = rb_enc_str_new(fptr->
cbuf.
ptr+fptr->
cbuf.
off, 1, read_enc);
4670 if (fptr->
cbuf.
len == 0) clear_readconv(fptr);
4679 io_shift_cbuf(fptr, r, &str);
4686 ISASCII(RSTRING_PTR(str)[0])) {
4690 str = io_enc_str(str, fptr);
4695 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
4696 if (io_fillbuf(fptr) < 0) {
4718 if (io_fillbuf(fptr) != -1) {
4722 r = rb_enc_precise_mbclen(RSTRING_PTR(str), RSTRING_PTR(str)+RSTRING_LEN(str), enc);
4738 str = io_enc_str(str, fptr);
4764rb_io_each_char(
VALUE io)
4774 enc = io_input_encoding(fptr);
4776 while (!
NIL_P(c = io_getc(fptr, enc))) {
4802rb_io_each_codepoint(
VALUE io)
4814 if (NEED_READCONV(fptr)) {
4815 SET_BINARY_MODE(fptr);
4818 make_readconv(fptr, 0);
4826 r = ONIGENC_CONSTRUCT_MBCLEN_CHARFOUND(1);
4833 if (more_char(fptr) == MORE_CHAR_FINISHED) {
4834 clear_readconv(fptr);
4861 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
4862 enc = io_input_encoding(fptr);
4863 while (io_fillbuf(fptr) >= 0) {
4878 char cbuf[8], *p = cbuf;
4880 if (more > numberof(cbuf))
goto invalid;
4882 if (more > numberof(cbuf))
goto invalid;
4883 while ((n = (
int)read_buffered_data(p, more, fptr)) > 0 &&
4884 (p += n, (more -= n) > 0)) {
4885 if (io_fillbuf(fptr) < 0)
goto invalid;
4886 if ((n = fptr->
rbuf.
len) > more) n = more;
4888 r = rb_enc_precise_mbclen(cbuf, p, enc);
4890 c = rb_enc_codepoint(cbuf, p, enc);
4933 enc = io_input_encoding(fptr);
4935 return io_getc(fptr, enc);
4958rb_io_readchar(
VALUE io)
4960 VALUE c = rb_io_getc(io);
5003 if (io_fillbuf(fptr) < 0) {
5032rb_io_readbyte(
VALUE io)
5093 unsigned char c =
NUM2INT(v) & 0xFF;
5099 io_ungetbyte(b, fptr);
5155 else if (RB_BIGNUM_TYPE_P(c)) {
5161 if (NEED_READCONV(fptr)) {
5162 SET_BINARY_MODE(fptr);
5163 len = RSTRING_LEN(c);
5164#if SIZEOF_LONG > SIZEOF_INT
5168 make_readconv(fptr, (
int)len);
5182 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
5183 io_ungetbyte(c, fptr);
5205rb_io_isatty(
VALUE io)
5210 return RBOOL(isatty(fptr->
fd) != 0);
5213#if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
5229rb_io_close_on_exec_p(
VALUE io)
5235 write_io = GetWriteIO(io);
5236 if (io != write_io) {
5238 if (fptr && 0 <= (fd = fptr->
fd)) {
5239 if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->
pathv);
5240 if (!(ret & FD_CLOEXEC))
return Qfalse;
5245 if (fptr && 0 <= (fd = fptr->
fd)) {
5246 if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->
pathv);
5247 if (!(ret & FD_CLOEXEC))
return Qfalse;
5252#define rb_io_close_on_exec_p rb_f_notimplement
5255#if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
5279 int flag =
RTEST(arg) ? FD_CLOEXEC : 0;
5284 write_io = GetWriteIO(io);
5285 if (io != write_io) {
5287 if (fptr && 0 <= (fd = fptr->
fd)) {
5288 if ((ret = fcntl(fptr->
fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->
pathv);
5289 if ((ret & FD_CLOEXEC) != flag) {
5290 ret = (ret & ~FD_CLOEXEC) | flag;
5291 ret = fcntl(fd, F_SETFD, ret);
5292 if (ret != 0) rb_sys_fail_path(fptr->
pathv);
5299 if (fptr && 0 <= (fd = fptr->
fd)) {
5300 if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->
pathv);
5301 if ((ret & FD_CLOEXEC) != flag) {
5302 ret = (ret & ~FD_CLOEXEC) | flag;
5303 ret = fcntl(fd, F_SETFD, ret);
5304 if (ret != 0) rb_sys_fail_path(fptr->
pathv);
5310#define rb_io_set_close_on_exec rb_f_notimplement
5313#define IS_PREP_STDIO(f) ((f)->mode & FMODE_PREP)
5314#define PREP_STDIO_NAME(f) (RSTRING_PTR((f)->pathv))
5317finish_writeconv(
rb_io_t *fptr,
int noalloc)
5319 unsigned char *ds, *dp, *de;
5323 unsigned char buf[1024];
5328 de = buf +
sizeof(buf);
5331 size_t remaining = dp-ds;
5332 long result = rb_io_write_memory(fptr, ds, remaining);
5336 if ((
size_t)result == remaining)
break;
5359 if (io_fflush(fptr) < 0) {
5367 fptr->
wbuf.
len += (int)(dp - ds);
5383finish_writeconv_sync(
VALUE arg)
5386 return finish_writeconv(p->fptr, p->noalloc);
5390nogvl_close(
void *ptr)
5394 return (
void*)(intptr_t)close(*fd);
5398maygvl_close(
int fd,
int keepgvl)
5411nogvl_fclose(
void *ptr)
5415 return (
void*)(intptr_t)fclose(file);
5419maygvl_fclose(
FILE *file,
int keepgvl)
5422 return fclose(file);
5428static void clear_codeconv(
rb_io_t *fptr);
5431fptr_finalize_flush(
rb_io_t *fptr,
int noraise,
int keepgvl,
5437 int mode = fptr->
mode;
5443 arg.noalloc = noraise;
5447 error = finish_writeconv(fptr, noraise);
5452 io_flush_buffer_sync(fptr);
5455 if (io_fflush(fptr) < 0 &&
NIL_P(error)) {
5463 if (IS_PREP_STDIO(fptr) || fd <= 2) {
5487 if (!done && stdio_file) {
5489 if ((maygvl_fclose(stdio_file, noraise) < 0) &&
NIL_P(error)) {
5498 if (!done && fd >= 0) {
5504 if ((maygvl_close(fd, keepgvl) < 0) &&
NIL_P(error)) {
5513 if (!
NIL_P(error) && !noraise) {
5522fptr_finalize(
rb_io_t *fptr,
int noraise)
5524 fptr_finalize_flush(fptr, noraise, FALSE, 0);
5525 free_io_buffer(&fptr->
rbuf);
5526 free_io_buffer(&fptr->
wbuf);
5527 clear_codeconv(fptr);
5531rb_io_fptr_cleanup(
rb_io_t *fptr,
int noraise)
5537 fptr_finalize(fptr, noraise);
5545 ruby_sized_xfree(buf->ptr, (
size_t)buf->capa);
5557 free_io_buffer(&fptr->
cbuf);
5573 clear_readconv(fptr);
5574 clear_writeconv(fptr);
5578rb_io_fptr_finalize_internal(
void *ptr)
5585 rb_io_fptr_cleanup(fptr, TRUE);
5587 free_io_buffer(&fptr->
rbuf);
5588 free_io_buffer(&fptr->
wbuf);
5589 clear_codeconv(fptr);
5593#undef rb_io_fptr_finalize
5601 rb_io_fptr_finalize_internal(fptr);
5605#define rb_io_fptr_finalize(fptr) rb_io_fptr_finalize_internal(fptr)
5607RUBY_FUNC_EXPORTED
size_t
5608rb_io_memsize(
const rb_io_t *fptr)
5610 size_t size =
sizeof(
rb_io_t);
5621# define KEEPGVL TRUE
5623# define KEEPGVL FALSE
5628io_close_fptr(
VALUE io)
5635 ccan_list_head_init(&busy);
5636 write_io = GetWriteIO(io);
5637 if (io != write_io) {
5638 write_fptr =
RFILE(write_io)->fptr;
5639 if (write_fptr && 0 <= write_fptr->
fd) {
5640 rb_io_fptr_cleanup(write_fptr, TRUE);
5644 fptr =
RFILE(io)->fptr;
5645 if (!fptr)
return 0;
5646 if (fptr->
fd < 0)
return 0;
5648 if (rb_notify_fd_close(fptr->
fd, &busy)) {
5650 fptr_finalize_flush(fptr, FALSE, KEEPGVL, &busy);
5652 rb_io_fptr_cleanup(fptr, FALSE);
5657fptr_waitpid(
rb_io_t *fptr,
int nohang)
5661 rb_last_status_clear();
5670 rb_io_t *fptr = io_close_fptr(io);
5671 if (fptr) fptr_waitpid(fptr, 0);
5708rb_io_close_m(
VALUE io)
5710 rb_io_t *fptr = rb_io_get_fptr(io);
5719io_call_close(
VALUE io)
5728 enum {mesg_len =
sizeof(closed_stream)-1};
5731 RSTRING_LEN(mesg) != mesg_len ||
5732 memcmp(RSTRING_PTR(mesg), closed_stream, mesg_len)) {
5742 if (!UNDEF_P(closed) &&
RTEST(closed))
return io;
5743 rb_rescue2(io_call_close, io, ignore_closed_stream, io,
5775rb_io_closed(
VALUE io)
5781 write_io = GetWriteIO(io);
5782 if (io != write_io) {
5783 write_fptr =
RFILE(write_io)->fptr;
5784 if (write_fptr && 0 <= write_fptr->
fd) {
5789 fptr = rb_io_get_fptr(io);
5790 return RBOOL(0 > fptr->
fd);
5826rb_io_close_read(
VALUE io)
5832 if (fptr->
fd < 0)
return Qnil;
5833 if (is_socket(fptr->
fd, fptr->
pathv)) {
5837 if (shutdown(fptr->
fd, SHUT_RD) < 0)
5838 rb_sys_fail_path(fptr->
pathv);
5839 fptr->
mode &= ~FMODE_READABLE;
5845 write_io = GetWriteIO(io);
5846 if (io != write_io) {
5851 RFILE(io)->fptr = wfptr;
5854 RFILE(write_io)->fptr = fptr;
5855 rb_io_fptr_cleanup(fptr, FALSE);
5899rb_io_close_write(
VALUE io)
5904 write_io = GetWriteIO(io);
5906 if (fptr->
fd < 0)
return Qnil;
5907 if (is_socket(fptr->
fd, fptr->
pathv)) {
5911 if (shutdown(fptr->
fd, SHUT_WR) < 0)
5912 rb_sys_fail_path(fptr->
pathv);
5913 fptr->
mode &= ~FMODE_WRITABLE;
5923 if (io != write_io) {
5943rb_io_sysseek(
int argc,
VALUE *argv,
VALUE io)
5945 VALUE offset, ptrname;
5946 int whence = SEEK_SET;
5950 if (rb_scan_args(argc, argv,
"11", &offset, &ptrname) == 2) {
5951 whence = interpret_seek_whence(ptrname);
5956 (READ_DATA_BUFFERED(fptr) || READ_CHAR_PENDING(fptr))) {
5960 rb_warn(
"sysseek for buffered IO");
5963 pos = lseek(fptr->
fd, pos, whence);
5964 if (pos < 0 && errno) rb_sys_fail_path(fptr->
pathv);
5998 io = GetWriteIO(io);
6003 rb_warn(
"syswrite for buffered IO");
6006 tmp = rb_str_tmp_frozen_acquire(str);
6008 n = rb_io_write_memory(fptr, ptr, len);
6009 if (n < 0) rb_sys_fail_path(fptr->
pathv);
6010 rb_str_tmp_frozen_release(str, tmp);
6027rb_io_sysread(
int argc,
VALUE *argv,
VALUE io)
6035 rb_scan_args(argc, argv,
"11", &len, &str);
6038 shrinkable = io_setstrbuf(&str, ilen);
6039 if (ilen == 0)
return str;
6044 if (READ_DATA_BUFFERED(fptr)) {
6050 io_setstrbuf(&str, ilen);
6055 iis.buf = RSTRING_PTR(str);
6058 n = io_read_memory_locktmp(str, &iis);
6061 rb_sys_fail_path(fptr->
pathv);
6064 io_set_read_length(str, n, shrinkable);
6066 if (n == 0 && ilen > 0) {
6073#if defined(HAVE_PREAD) || defined(HAVE_PWRITE)
6074struct prdwr_internal_arg {
6082#if defined(HAVE_PREAD)
6084internal_pread_func(
void *arg)
6086 struct prdwr_internal_arg *p = arg;
6087 return (
VALUE)pread(p->fd, p->buf, p->count, p->offset);
6091pread_internal_call(
VALUE arg)
6093 struct prdwr_internal_arg *p = (
struct prdwr_internal_arg *)arg;
6094 return rb_thread_io_blocking_region(internal_pread_func, p, p->fd);
6128 VALUE len, offset, str;
6131 struct prdwr_internal_arg arg;
6134 rb_scan_args(argc, argv,
"21", &len, &offset, &str);
6138 shrinkable = io_setstrbuf(&str, (
long)arg.count);
6139 if (arg.count == 0)
return str;
6140 arg.buf = RSTRING_PTR(str);
6152 rb_sys_fail_path(fptr->
pathv);
6154 io_set_read_length(str, n, shrinkable);
6155 if (n == 0 && arg.count > 0) {
6162# define rb_io_pread rb_f_notimplement
6165#if defined(HAVE_PWRITE)
6167internal_pwrite_func(
void *ptr)
6169 struct prdwr_internal_arg *arg = ptr;
6171 return (
VALUE)pwrite(arg->fd, arg->buf, arg->count, arg->offset);
6204 struct prdwr_internal_arg arg;
6212 io = GetWriteIO(io);
6217 tmp = rb_str_tmp_frozen_acquire(str);
6218 arg.buf = RSTRING_PTR(tmp);
6219 arg.count = (size_t)RSTRING_LEN(tmp);
6221 n = (ssize_t)rb_thread_io_blocking_region(internal_pwrite_func, &arg, fptr->
fd);
6222 if (n < 0) rb_sys_fail_path(fptr->
pathv);
6223 rb_str_tmp_frozen_release(str, tmp);
6228# define rb_io_pwrite rb_f_notimplement
6242 fptr->
mode &= ~FMODE_TEXTMODE;
6246 SET_BINARY_MODE_WITH_SEEK_CUR(fptr);
6249 setmode(fptr->
fd, O_BINARY);
6256io_ascii8bit_binmode(
rb_io_t *fptr)
6267 fptr->
mode &= ~FMODE_TEXTMODE;
6268 SET_BINARY_MODE_WITH_SEEK_CUR(fptr);
6270 fptr->
encs.
enc = rb_ascii8bit_encoding();
6274 clear_codeconv(fptr);
6283 io_ascii8bit_binmode(fptr);
6300rb_io_binmode_m(
VALUE io)
6306 write_io = GetWriteIO(io);
6321rb_io_binmode_p(
VALUE io)
6329rb_io_fmode_modestr(
int fmode)
6333 return MODE_BTMODE(
"a+",
"ab+",
"at+");
6335 return MODE_BTMODE(
"a",
"ab",
"at");
6341 return MODE_BTMODE(
"r",
"rb",
"rt");
6343 return MODE_BTXMODE(
"w",
"wb",
"wt",
"wx",
"wbx",
"wtx");
6346 return MODE_BTXMODE(
"w+",
"wb+",
"wt+",
"w+x",
"wb+x",
"wt+x");
6348 return MODE_BTMODE(
"r+",
"rb+",
"rt+");
6352static const char bom_prefix[] =
"bom|";
6353static const char utf_prefix[] =
"utf-";
6354enum {bom_prefix_len = (int)
sizeof(bom_prefix) - 1};
6355enum {utf_prefix_len = (int)
sizeof(utf_prefix) - 1};
6358io_encname_bom_p(
const char *name,
long len)
6360 return len > bom_prefix_len &&
STRNCASECMP(name, bom_prefix, bom_prefix_len) == 0;
6367 const char *m = modestr, *p = NULL;
6395 if (modestr[0] !=
'w')
6403 if (io_encname_bom_p(m, p ? (
long)(p - m) : (long)strlen(m)))
6421rb_io_oflags_fmode(
int oflags)
6425 switch (oflags & O_ACCMODE) {
6437 if (oflags & O_APPEND) {
6440 if (oflags & O_TRUNC) {
6443 if (oflags & O_CREAT) {
6446 if (oflags & O_EXCL) {
6450 if (oflags & O_BINARY) {
6459rb_io_fmode_oflags(
int fmode)
6503rb_io_oflags_modestr(
int oflags)
6506# define MODE_BINARY(a,b) ((oflags & O_BINARY) ? (b) : (a))
6508# define MODE_BINARY(a,b) (a)
6511 if (oflags & O_EXCL) {
6514 accmode = oflags & (O_RDONLY|O_WRONLY|O_RDWR);
6515 if (oflags & O_APPEND) {
6516 if (accmode == O_WRONLY) {
6517 return MODE_BINARY(
"a",
"ab");
6519 if (accmode == O_RDWR) {
6520 return MODE_BINARY(
"a+",
"ab+");
6527 return MODE_BINARY(
"r",
"rb");
6529 return MODE_BINARY(
"w",
"wb");
6531 if (oflags & O_TRUNC) {
6532 return MODE_BINARY(
"w+",
"wb+");
6534 return MODE_BINARY(
"r+",
"rb+");
6546 int default_ext = 0;
6549 ext = rb_default_external_encoding();
6552 if (rb_is_ascii8bit_enc(ext)) {
6556 else if (intern == NULL) {
6557 intern = rb_default_internal_encoding();
6562 *enc = (default_ext && intern != ext) ? NULL : ext;
6572unsupported_encoding(
const char *name,
rb_encoding *enc)
6574 rb_enc_warn(enc,
"Unsupported encoding %s ignored", name);
6578parse_mode_enc(
const char *estr,
rb_encoding *estr_enc,
6584 int fmode = fmode_p ? *fmode_p : 0;
6590 p = strrchr(estr,
':');
6591 len = p ? (p++ - estr) : (long)strlen(estr);
6593 estr += bom_prefix_len;
6594 len -= bom_prefix_len;
6595 if (!
STRNCASECMP(estr, utf_prefix, utf_prefix_len)) {
6599 rb_enc_warn(estr_enc,
"BOM with non-UTF encoding %s is nonsense", estr);
6600 fmode &= ~FMODE_SETENC_BY_BOM;
6608 memcpy(encname, estr, len);
6609 encname[len] =
'\0';
6612 idx = rb_enc_find_index(estr);
6614 if (fmode_p) *fmode_p = fmode;
6617 ext_enc = rb_enc_from_index(idx);
6620 unsupported_encoding(estr, estr_enc);
6626 if (*p ==
'-' && *(p+1) ==
'\0') {
6631 idx2 = rb_enc_find_index(p);
6633 unsupported_encoding(p, estr_enc);
6638 int_enc = rb_enc_from_index(idx2);
6642 rb_io_ext_int_to_encs(ext_enc, int_enc, enc_p, enc2_p, fmode);
6655 v = rb_hash_lookup2(opt, sym_encoding,
Qnil);
6656 if (v !=
Qnil) encoding = v;
6657 v = rb_hash_lookup2(opt, sym_extenc,
Qundef);
6658 if (v !=
Qnil) extenc = v;
6659 v = rb_hash_lookup2(opt, sym_intenc,
Qundef);
6660 if (!UNDEF_P(v)) intenc = v;
6662 if ((!UNDEF_P(extenc) || !UNDEF_P(intenc)) && !
NIL_P(encoding)) {
6664 int idx = rb_to_encoding_index(encoding);
6665 if (idx >= 0) encoding = rb_enc_from_encoding(rb_enc_from_index(idx));
6666 rb_warn(
"Ignoring encoding parameter '%"PRIsVALUE
"': %s_encoding is used",
6667 encoding, UNDEF_P(extenc) ?
"internal" :
"external");
6671 if (!UNDEF_P(extenc) && !
NIL_P(extenc)) {
6672 extencoding = rb_to_encoding(extenc);
6674 if (!UNDEF_P(intenc)) {
6675 if (
NIL_P(intenc)) {
6682 if (*p ==
'-' && *(p+1) ==
'\0') {
6687 intencoding = rb_to_encoding(intenc);
6691 intencoding = rb_to_encoding(intenc);
6693 if (extencoding == intencoding) {
6697 if (!
NIL_P(encoding)) {
6701 enc_p, enc2_p, fmode_p);
6704 rb_io_ext_int_to_encs(rb_to_encoding(encoding), NULL, enc_p, enc2_p, 0);
6707 else if (!UNDEF_P(extenc) || !UNDEF_P(intenc)) {
6709 rb_io_ext_int_to_encs(extencoding, intencoding, enc_p, enc2_p, 0);
6719 int fmode = *fmode_p;
6724 !rb_enc_asciicompat(
enc ?
enc : rb_default_external_encoding()))
6735#if !DEFAULT_TEXTMODE
6737 fmode &= ~FMODE_TEXTMODE;
6744extract_binmode(
VALUE opthash,
int *fmode)
6746 if (!
NIL_P(opthash)) {
6748 v = rb_hash_aref(opthash, sym_textmode);
6757 v = rb_hash_aref(opthash, sym_binmode);
6774 int *oflags_p,
int *fmode_p,
convconfig_t *convconfig_p)
6781 int has_enc = 0, has_vmode = 0;
6787 rb_io_ext_int_to_encs(NULL, NULL, &
enc, &
enc2, 0);
6797 fmode = rb_io_oflags_fmode(oflags);
6805 oflags = rb_io_fmode_oflags(fmode);
6809 parse_mode_enc(p+1, rb_enc_get(vmode), &
enc, &
enc2, &fmode);
6814 e = (fmode &
FMODE_BINMODE) ? rb_ascii8bit_encoding() : NULL;
6815 rb_io_ext_int_to_encs(e, NULL, &
enc, &
enc2, fmode);
6819 if (
NIL_P(opthash)) {
6823#ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
6825 MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE,
6826 0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE) : 0;
6828 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(
enc2,
ecflags);
6835 rb_io_ext_int_to_encs(rb_ascii8bit_encoding(), NULL, &
enc, &
enc2, fmode);
6838 else if (
NIL_P(vmode)) {
6839 fmode |= DEFAULT_TEXTMODE;
6846 v = rb_hash_aref(opthash, sym_mode);
6848 if (!
NIL_P(vmode)) {
6856 v = rb_hash_aref(opthash, sym_flags);
6861 fmode = rb_io_oflags_fmode(oflags);
6863 extract_binmode(opthash, &fmode);
6869 rb_io_ext_int_to_encs(rb_ascii8bit_encoding(), NULL, &
enc, &
enc2, fmode);
6872 else if (
NIL_P(vmode)) {
6873 fmode |= DEFAULT_TEXTMODE;
6876 v = rb_hash_aref(opthash, sym_perm);
6879 if (!
NIL_P(*vperm_p)) {
6891#ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
6893 MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE,
6894 0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE) : 0;
6902 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(
enc2,
ecflags);
6925sysopen_func(
void *ptr)
6928 const char *fname = RSTRING_PTR(data->fname);
6943rb_sysopen(
VALUE fname,
int oflags, mode_t perm)
6948 data.fname = rb_str_encode_ospath(fname);
6950 data.oflags = oflags;
6953 fd = rb_sysopen_internal(&data);
6956 if (rb_gc_for_fd(e)) {
6957 fd = rb_sysopen_internal(&data);
6960 rb_syserr_fail_path(e, fname);
6974 file = fdopen(fd, modestr);
6981 file = fdopen(fd, modestr);
6985 if (rb_gc_for_fd(e)) {
6986 file = fdopen(fd, modestr);
6990 if (e == 0) e = EINVAL;
6992 if (e == 0) e = EMFILE;
7000 if (setvbuf(file, NULL, _IOFBF, 0) != 0)
7001 rb_warn(
"setvbuf() can't be honoured (fd=%d)", fd);
7009 int t = isatty(fptr->
fd);
7019io_strip_bom(
VALUE io)
7021 VALUE b1, b2, b3, b4;
7032 return rb_utf8_encindex();
7042 return ENCINDEX_UTF_16BE;
7053 return ENCINDEX_UTF_32LE;
7058 return ENCINDEX_UTF_16LE;
7068 return ENCINDEX_UTF_32BE;
7082io_set_encoding_by_bom(
VALUE io)
7084 int idx = io_strip_bom(io);
7090 extenc = rb_enc_from_index(idx);
7091 io_encoding_set(fptr, rb_enc_from_encoding(extenc),
7092 rb_io_internal_encoding(io),
Qnil);
7101rb_file_open_generic(
VALUE io,
VALUE filename,
int oflags,
int fmode,
7109 rb_io_ext_int_to_encs(NULL, NULL, &cc.enc, &cc.enc2, fmode);
7114 validate_enc_binmode(&fmode, convconfig->
ecflags,
7115 convconfig->
enc, convconfig->
enc2);
7119 fptr->
encs = *convconfig;
7122 if (!(oflags & O_TMPFILE)) {
7123 fptr->
pathv = pathv;
7126 fptr->
pathv = pathv;
7128 fptr->
fd = rb_sysopen(pathv, oflags, perm);
7136rb_file_open_internal(
VALUE io,
VALUE filename,
const char *modestr)
7139 const char *p = strchr(modestr,
':');
7143 parse_mode_enc(p+1, rb_usascii_encoding(),
7144 &convconfig.
enc, &convconfig.
enc2, &fmode);
7152 e = (fmode &
FMODE_BINMODE) ? rb_ascii8bit_encoding() : NULL;
7153 rb_io_ext_int_to_encs(e, NULL, &convconfig.
enc, &convconfig.
enc2, fmode);
7158 return rb_file_open_generic(io, filename,
7159 rb_io_fmode_oflags(fmode),
7169 return rb_file_open_internal(io_alloc(
rb_cFile), fname, modestr);
7178#if defined(__CYGWIN__) || !defined(HAVE_WORKING_FORK)
7201 while ((tmp = *prev) != 0) {
7202 if (tmp->fptr == fptr) {
7211#if defined (_WIN32) || defined(__CYGWIN__)
7220 rb_io_fptr_finalize(list->fptr);
7227pipe_finalize(
rb_io_t *fptr,
int noraise)
7229#if !defined(HAVE_WORKING_FORK) && !defined(_WIN32)
7238 fptr_finalize(fptr, noraise);
7240 pipe_del_fptr(fptr);
7247#if defined(__CYGWIN__) || !defined(HAVE_WORKING_FORK)
7250 if (old_finalize == orig->finalize)
return;
7255#if defined(__CYGWIN__) || !defined(HAVE_WORKING_FORK)
7256 if (old_finalize != pipe_finalize) {
7258 for (list =
pipe_list; list; list = list->next) {
7259 if (list->fptr == fptr)
break;
7261 if (!list) pipe_add_fptr(fptr);
7264 pipe_del_fptr(fptr);
7277rb_io_unbuffered(
rb_io_t *fptr)
7288 if (rb_gc_for_fd(errno)) {
7300#define HAVE_SPAWNV 1
7301#define spawnv(mode, cmd, args) rb_w32_uaspawn((mode), (cmd), (args))
7302#define spawn(mode, cmd) rb_w32_uspawn((mode), (cmd), 0)
7305#if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
7315#ifdef HAVE_WORKING_FORK
7316# ifndef __EMSCRIPTEN__
7318popen_redirect(
struct popen_arg *p)
7321 close(p->write_pair[1]);
7322 if (p->write_pair[0] != 0) {
7323 dup2(p->write_pair[0], 0);
7324 close(p->write_pair[0]);
7327 if (p->pair[1] != 1) {
7328 dup2(p->pair[1], 1);
7334 if (p->pair[1] != 1) {
7335 dup2(p->pair[1], 1);
7341 if (p->pair[0] != 0) {
7342 dup2(p->pair[0], 0);
7349#if defined(__linux__)
7360linux_get_maxfd(
void)
7363 char buf[4096], *p, *np, *e;
7366 if (fd < 0)
return fd;
7367 ss = read(fd, buf,
sizeof(buf));
7368 if (ss < 0)
goto err;
7371 while ((
int)
sizeof(
"FDSize:\t0\n")-1 <= e-p &&
7372 (np = memchr(p,
'\n', e-p)) != NULL) {
7373 if (memcmp(p,
"FDSize:",
sizeof(
"FDSize:")-1) == 0) {
7375 p +=
sizeof(
"FDSize:")-1;
7395#if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
7397 int max = (int)max_file_descriptor;
7400 ret = fcntl(0, F_MAXFD);
7402 maxhint = max = ret;
7403# elif defined(__linux__)
7404 ret = linux_get_maxfd();
7411 for (fd = lowfd; fd <= max; fd++) {
7412 if (!
NIL_P(noclose_fds) &&
7415 ret = fcntl(fd, F_GETFD);
7416 if (ret != -1 && !(ret & FD_CLOEXEC)) {
7417 fcntl(fd, F_SETFD, ret|FD_CLOEXEC);
7419# define CONTIGUOUS_CLOSED_FDS 20
7421 if (max < fd + CONTIGUOUS_CLOSED_FDS)
7422 max = fd + CONTIGUOUS_CLOSED_FDS;
7428# ifndef __EMSCRIPTEN__
7430popen_exec(
void *pp,
char *errmsg,
size_t errmsg_len)
7432 struct popen_arg *p = (
struct popen_arg*)pp;
7434 return rb_exec_async_signal_safe(p->eargp, errmsg, errmsg_len);
7439#if (defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)) && !defined __EMSCRIPTEN__
7441rb_execarg_fixup_v(
VALUE execarg_obj)
7443 rb_execarg_parent_start(execarg_obj);
7447char *rb_execarg_commandline(
const struct rb_execarg *eargp,
VALUE *prog);
7450#ifndef __EMSCRIPTEN__
7452pipe_open(
VALUE execarg_obj,
const char *modestr,
int fmode,
7455 struct rb_execarg *eargp =
NIL_P(execarg_obj) ? NULL : rb_execarg_get(execarg_obj);
7456 VALUE prog = eargp ? (eargp->use_shell ? eargp->invoke.sh.shell_script : eargp->invoke.cmd.command_name) :
Qfalse ;
7462#if defined(HAVE_WORKING_FORK)
7464 char errmsg[80] = {
'\0' };
7466#if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
7468 struct popen_arg arg;
7471#if defined(HAVE_SPAWNV)
7472# if defined(HAVE_SPAWNVE)
7473# define DO_SPAWN(cmd, args, envp) ((args) ? \
7474 spawnve(P_NOWAIT, (cmd), (args), (envp)) : \
7475 spawne(P_NOWAIT, (cmd), (envp)))
7477# define DO_SPAWN(cmd, args, envp) ((args) ? \
7478 spawnv(P_NOWAIT, (cmd), (args)) : \
7479 spawn(P_NOWAIT, (cmd)))
7481# if !defined(HAVE_WORKING_FORK)
7483# if defined(HAVE_SPAWNVE)
7488#if !defined(HAVE_WORKING_FORK)
7494#if !defined(HAVE_WORKING_FORK)
7495 const char *cmd = 0;
7501#if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
7502 arg.execarg_obj = execarg_obj;
7505 arg.pair[0] = arg.pair[1] = -1;
7506 arg.write_pair[0] = arg.write_pair[1] = -1;
7507# if !defined(HAVE_WORKING_FORK)
7508 if (eargp && !eargp->use_shell) {
7509 args = ARGVSTR2ARGV(eargp->invoke.cmd.argv_str);
7514 if (
rb_pipe(arg.write_pair) < 0)
7518 close(arg.write_pair[0]);
7519 close(arg.write_pair[1]);
7523 rb_execarg_addopt(execarg_obj,
INT2FIX(0),
INT2FIX(arg.write_pair[0]));
7524 rb_execarg_addopt(execarg_obj,
INT2FIX(1),
INT2FIX(arg.pair[1]));
7531 rb_execarg_addopt(execarg_obj,
INT2FIX(1),
INT2FIX(arg.pair[1]));
7537 rb_execarg_addopt(execarg_obj,
INT2FIX(0),
INT2FIX(arg.pair[0]));
7542 if (!
NIL_P(execarg_obj)) {
7543 rb_protect(rb_execarg_fixup_v, execarg_obj, &state);
7545 if (0 <= arg.write_pair[0]) close(arg.write_pair[0]);
7546 if (0 <= arg.write_pair[1]) close(arg.write_pair[1]);
7547 if (0 <= arg.pair[0]) close(arg.pair[0]);
7548 if (0 <= arg.pair[1]) close(arg.pair[1]);
7549 rb_execarg_parent_end(execarg_obj);
7553# if defined(HAVE_WORKING_FORK)
7554 pid = rb_fork_async_signal_safe(&status, popen_exec, &arg, arg.eargp->redirect_fds, errmsg,
sizeof(errmsg));
7556 rb_execarg_run_options(eargp, sargp, NULL, 0);
7557# if defined(HAVE_SPAWNVE)
7558 if (eargp->envp_str) envp = (
char **)RSTRING_PTR(eargp->envp_str);
7560 while ((pid = DO_SPAWN(cmd, args, envp)) < 0) {
7562 switch (e = errno) {
7564# if EWOULDBLOCK != EAGAIN
7573 rb_execarg_run_options(sargp, NULL, NULL, 0);
7575 rb_execarg_parent_end(execarg_obj);
7578# if defined(HAVE_WORKING_FORK)
7579 pid = rb_call_proc__fork();
7581 popen_redirect(&arg);
7593# if defined(HAVE_WORKING_FORK)
7599 close(arg.write_pair[0]);
7600 close(arg.write_pair[1]);
7602# if defined(HAVE_WORKING_FORK)
7611 close(arg.write_pair[0]);
7612 write_fd = arg.write_pair[1];
7623 cmd = rb_execarg_commandline(eargp, &prog);
7624 if (!
NIL_P(execarg_obj)) {
7625 rb_execarg_parent_start(execarg_obj);
7626 rb_execarg_run_options(eargp, sargp, NULL, 0);
7628 fp = popen(cmd, modestr);
7631 rb_execarg_parent_end(execarg_obj);
7632 rb_execarg_run_options(sargp, NULL, NULL, 0);
7634 if (!fp) rb_syserr_fail_path(e, prog);
7644 fptr->
encs = *convconfig;
7645#if RUBY_CRLF_ENVIRONMENT
7652 if (NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {
7655#ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
7656 if (NEED_NEWLINE_DECORATOR_ON_WRITE(fptr)) {
7657 fptr->
encs.
ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
7663 if (0 <= write_fd) {
7664 write_port = io_alloc(
rb_cIO);
7666 write_fptr->
fd = write_fd;
7668 fptr->
mode &= ~FMODE_WRITABLE;
7670 rb_ivar_set(port, rb_intern(
"@tied_io_for_writing"), write_port);
7673#if defined (__CYGWIN__) || !defined(HAVE_WORKING_FORK)
7675 pipe_add_fptr(fptr);
7681pipe_open(
VALUE execarg_obj,
const char *modestr,
int fmode,
7689is_popen_fork(
VALUE prog)
7691 if (RSTRING_LEN(prog) == 1 && RSTRING_PTR(prog)[0] ==
'-') {
7692#if !defined(HAVE_WORKING_FORK)
7694 "fork() function is unimplemented on this machine");
7703pipe_open_s(
VALUE prog,
const char *modestr,
int fmode,
7707 VALUE *argv = &prog;
7710 if (!is_popen_fork(prog))
7711 execarg_obj = rb_execarg_new(argc, argv, TRUE, FALSE);
7712 return pipe_open(execarg_obj, modestr, fmode, convconfig);
7718 rb_io_t *fptr = io_close_fptr(io);
7886rb_io_s_popen(
int argc,
VALUE *argv,
VALUE klass)
7890 if (argc > 1 && !
NIL_P(opt = rb_check_hash_type(argv[argc-1]))) --argc;
7891 if (argc > 1 && !
NIL_P(env = rb_check_hash_type(argv[0]))) --argc, ++argv;
7900 int ex = !
NIL_P(opt);
7901 rb_error_arity(argc + ex, 1 + ex, 2 + ex);
7904 return popen_finish(rb_io_popen(pname, pmode, env, opt), klass);
7910 const char *modestr;
7915 tmp = rb_check_array_type(pname);
7918#if SIZEOF_LONG > SIZEOF_INT
7919 if (len > INT_MAX) {
7923 execarg_obj = rb_execarg_new((
int)len,
RARRAY_CONST_PTR(tmp), FALSE, FALSE);
7929 if (!is_popen_fork(pname))
7930 execarg_obj = rb_execarg_new(1, &pname, TRUE, FALSE);
7932 if (!
NIL_P(execarg_obj)) {
7934 opt = rb_execarg_extract_options(execarg_obj, opt);
7936 rb_execarg_setenv(execarg_obj, env);
7939 modestr = rb_io_oflags_modestr(oflags);
7941 return pipe_open(execarg_obj, modestr, fmode, &convconfig);
7957 RBASIC_SET_CLASS(port, klass);
7965rb_scan_open_args(
int argc,
const VALUE *argv,
7966 VALUE *fname_p,
int *oflags_p,
int *fmode_p,
7969 VALUE opt, fname, vmode, vperm;
7973 argc = rb_scan_args(argc, argv,
"12:", &fname, &vmode, &vperm, &opt);
7987rb_open_file(
int argc,
const VALUE *argv,
VALUE io)
7994 rb_scan_open_args(argc, argv, &fname, &oflags, &fmode, &convconfig, &perm);
7995 rb_file_open_generic(io, fname, oflags, fmode, &convconfig, perm);
8033rb_io_s_open(
int argc,
VALUE *argv,
VALUE klass)
8065 VALUE fname, vmode, vperm;
8070 rb_scan_args(argc, argv,
"12", &fname, &vmode, &vperm);
8081 if (
NIL_P(vperm)) perm = 0666;
8085 fd = rb_sysopen(fname, oflags, perm);
8090check_pipe_command(
VALUE filename_or_command)
8092 char *s = RSTRING_PTR(filename_or_command);
8093 long l = RSTRING_LEN(filename_or_command);
8097 if (rb_enc_ascget(s, e, &chlen, rb_enc_get(filename_or_command)) ==
'|') {
8206 int redirect = FALSE;
8214 VALUE tmp = argv[0];
8220 VALUE cmd = check_pipe_command(tmp);
8223 return rb_io_s_popen(argc, argv,
rb_cIO);
8236 return rb_io_s_open(argc, argv,
rb_cFile);
8250 return rb_io_open_generic(io, filename, oflags, fmode, &convconfig, perm);
8254rb_io_open_generic(
VALUE klass,
VALUE filename,
int oflags,
int fmode,
8258 if (klass ==
rb_cIO && !
NIL_P(cmd = check_pipe_command(filename))) {
8259 return pipe_open_s(cmd, rb_io_oflags_modestr(oflags), fmode, convconfig);
8262 return rb_file_open_generic(io_alloc(klass), filename,
8263 oflags, fmode, convconfig, perm);
8278 if (fptr == orig)
return io;
8279 if (IS_PREP_STDIO(fptr)) {
8284 "%s can't change access mode from \"%s\" to \"%s\"",
8285 PREP_STDIO_NAME(fptr), rb_io_fmode_modestr(fptr->
mode),
8286 rb_io_fmode_modestr(orig->
mode));
8290 if (io_fflush(fptr) < 0)
8291 rb_sys_fail_on_write(fptr);
8294 flush_before_seek(fptr);
8297 pos = io_tell(orig);
8300 if (io_fflush(orig) < 0)
8301 rb_sys_fail_on_write(fptr);
8309 else if (!IS_PREP_STDIO(fptr)) fptr->
pathv =
Qnil;
8310 fptr_copy_finalizer(fptr, orig);
8315 if (IS_PREP_STDIO(fptr) || fd <= 2 || !fptr->stdio_file) {
8318 rb_sys_fail_path(orig->
pathv);
8326 rb_sys_fail_path(orig->
pathv);
8332 if (io_seek(fptr, pos, SEEK_SET) < 0 && errno) {
8333 rb_sys_fail_path(fptr->
pathv);
8335 if (io_seek(orig, pos, SEEK_SET) < 0 && errno) {
8336 rb_sys_fail_path(orig->
pathv);
8350int rb_freopen(
VALUE fname,
const char *mode,
FILE *fp);
8353rb_freopen(
VALUE fname,
const char *mode,
FILE *fp)
8355 if (!freopen(RSTRING_PTR(fname), mode, fp)) {
8398rb_io_reopen(
int argc,
VALUE *argv,
VALUE file)
8400 VALUE fname, nmode, opt;
8404 if (rb_scan_args(argc, argv,
"11:", &fname, &nmode, &opt) == 1) {
8407 return io_reopen(file, tmp);
8413 fptr =
RFILE(file)->fptr;
8423 if (IS_PREP_STDIO(fptr) &&
8427 "%s can't change access mode from \"%s\" to \"%s\"",
8428 PREP_STDIO_NAME(fptr), rb_io_fmode_modestr(fptr->
mode),
8429 rb_io_fmode_modestr(fmode));
8432 fptr->
encs = convconfig;
8435 oflags = rb_io_fmode_oflags(fptr->
mode);
8438 fptr->
pathv = fname;
8440 fptr->
fd = rb_sysopen(fptr->
pathv, oflags, 0666);
8446 if (io_fflush(fptr) < 0)
8447 rb_sys_fail_on_write(fptr);
8452 int e = rb_freopen(rb_str_encode_ospath(fptr->
pathv),
8453 rb_io_oflags_modestr(oflags),
8455 if (e) rb_syserr_fail_path(e, fptr->
pathv);
8459 if (setvbuf(fptr->
stdio_file, NULL, _IOFBF, 0) != 0)
8460 rb_warn(
"setvbuf() can't be honoured for %"PRIsVALUE, fptr->
pathv);
8463 if (setvbuf(fptr->
stdio_file, NULL, _IONBF, BUFSIZ) != 0)
8464 rb_warn(
"setvbuf() can't be honoured for %"PRIsVALUE, fptr->
pathv);
8466 else if (fptr->
stdio_file == stdout && isatty(fptr->
fd)) {
8467 if (setvbuf(fptr->
stdio_file, NULL, _IOLBF, BUFSIZ) != 0)
8468 rb_warn(
"setvbuf() can't be honoured for %"PRIsVALUE, fptr->
pathv);
8472 int tmpfd = rb_sysopen(fptr->
pathv, oflags, 0666);
8478 rb_syserr_fail_path(err, fptr->
pathv);
8502 fptr->
mode = orig->
mode & ~FMODE_PREP;
8508 fptr_copy_finalizer(fptr, orig);
8510 fd = ruby_dup(orig->
fd);
8512 pos = io_tell(orig);
8514 io_seek(fptr, pos, SEEK_SET);
8519 write_io = GetWriteIO(io);
8520 if (io != write_io) {
8523 rb_ivar_set(dest, rb_intern(
"@tied_io_for_writing"), write_io);
8586 if (argc == 0)
return Qnil;
8587 if (RB_TYPE_P(argv[0],
T_STRING)) {
8605 rb_warn_deprecated(
"`%s'", NULL,
rb_id2name(
id));
8678 if (argc > 1 && !
NIL_P(rb_output_fs)) {
8681 for (i=0; i<argc; i++) {
8682 if (!
NIL_P(rb_output_fs) && i>0) {
8786#define forward(obj, id, argc, argv) \
8787 rb_funcallv_kw(obj, id, argc, argv, RB_PASS_CALLED_KEYWORDS)
8788#define forward_public(obj, id, argc, argv) \
8789 rb_funcallv_public_kw(obj, id, argc, argv, RB_PASS_CALLED_KEYWORDS)
8790#define forward_current(id, argc, argv) \
8791 forward_public(ARGF.current_file, id, argc, argv)
8809 if (recv == r_stdout) {
8810 return rb_io_putc(recv, ch);
8812 return forward(r_stdout, rb_intern(
"putc"), 1, &ch);
8817rb_str_end_with_asciichar(
VALUE str,
int c)
8819 long len = RSTRING_LEN(str);
8820 const char *ptr = RSTRING_PTR(str);
8824 if (len == 0)
return 0;
8825 if ((n = rb_enc_mbminlen(enc)) == 1) {
8826 return ptr[len - 1] == c;
8828 return rb_enc_ascget(ptr + ((len - 1) / n) * n, ptr + len, &n, enc) == c;
8842 ary = rb_check_array_type(ary);
8902 VALUE line, args[2];
8909 for (i=0; i<argc; i++) {
8910 if (RB_TYPE_P(argv[i],
T_STRING)) {
8921 if (RSTRING_LEN(line) == 0 ||
8922 !rb_str_end_with_asciichar(line,
'\n')) {
8925 rb_io_writev(out, n, args);
8944 if (recv == r_stdout) {
8947 return forward(r_stdout, rb_intern(
"puts"), argc, argv);
8951rb_p_write(
VALUE str)
8957 if (RB_TYPE_P(r_stdout,
T_FILE) &&
8958 rb_method_basic_definition_p(
CLASS_OF(r_stdout), id_write)) {
8959 io_writev(2, args, r_stdout);
8962 rb_io_writev(r_stdout, 2, args);
8974rb_p_result(
int argc,
const VALUE *argv)
8981 else if (argc > 1) {
8985 if (RB_TYPE_P(r_stdout,
T_FILE)) {
9023 for (i=0; i<argc; i++) {
9025 rb_uninterruptible(rb_p_write, inspected);
9027 return rb_p_result(argc, argv);
9048rb_obj_display(
int argc,
VALUE *argv,
VALUE self)
9059rb_stderr_to_original_p(
VALUE err)
9061 return (err == orig_stderr ||
RFILE(orig_stderr)->fptr->
fd < 0);
9068 if (rb_stderr_to_original_p(out)) {
9070 if (isatty(fileno(stderr))) {
9071 if (rb_w32_write_console(
rb_str_new(mesg, len), fileno(stderr)) > 0)
return;
9074 if (fwrite(mesg,
sizeof(
char), (
size_t)len, stderr) < (
size_t)len) {
9091rb_write_error_str(
VALUE mesg)
9095 if (rb_stderr_to_original_p(out)) {
9096 size_t len = (size_t)RSTRING_LEN(mesg);
9098 if (isatty(fileno(stderr))) {
9099 if (rb_w32_write_console(mesg, fileno(stderr)) > 0)
return;
9102 if (fwrite(RSTRING_PTR(mesg),
sizeof(
char), len, stderr) < len) {
9114rb_stderr_tty_p(
void)
9117 return isatty(fileno(stderr));
9122must_respond_to(
ID mid,
VALUE val,
ID id)
9126 rb_id2str(
id), rb_id2str(mid),
9138stdin_getter(
ID id,
VALUE *ptr)
9146 must_respond_to(id_write, val,
id);
9151stdout_getter(
ID id,
VALUE *ptr)
9159 must_respond_to(id_write, val,
id);
9164stderr_getter(
ID id,
VALUE *ptr)
9170prep_io(
int fd,
int fmode,
VALUE klass,
const char *path)
9173 VALUE io = io_alloc(klass);
9180 if (!io_check_tty(fp)) {
9183 setmode(fd, O_BINARY);
9197 if (path && strcmp(path,
"-")) klass =
rb_cFile;
9198 return prep_io(fd, rb_io_oflags_fmode(oflags), klass, path);
9202prep_stdio(
FILE *f,
int fmode,
VALUE klass,
const char *path)
9205 VALUE io = prep_io(fileno(f), fmode|FMODE_PREP|DEFAULT_TEXTMODE, klass, path);
9209#ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
9210 fptr->
encs.
ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
9221rb_io_prep_stdin(
void)
9227rb_io_prep_stdout(
void)
9233rb_io_prep_stderr(
void)
9242 int oflags = rb_io_fmode_oflags(fptr->
mode) & ~O_EXCL;
9269 rb_io_buffer_init(&fp->
wbuf);
9270 rb_io_buffer_init(&fp->
rbuf);
9271 rb_io_buffer_init(&fp->
cbuf);
9289rb_io_make_open_file(
VALUE obj)
9294 if (
RFILE(obj)->fptr) {
9296 rb_io_fptr_finalize(
RFILE(obj)->fptr);
9297 RFILE(obj)->fptr = 0;
9299 fp = rb_io_fptr_new();
9301 RFILE(obj)->fptr = fp;
9347rb_io_initialize(
int argc,
VALUE *argv,
VALUE io)
9351 int fd, fmode, oflags = O_RDONLY;
9354#if defined(HAVE_FCNTL) && defined(F_GETFL)
9361 argc = rb_scan_args(argc, argv,
"11:", &fnum, &vmode, &opt);
9368#if defined(HAVE_FCNTL) && defined(F_GETFL)
9369 oflags = fcntl(fd, F_GETFL);
9375#if defined(HAVE_FCNTL) && defined(F_GETFL)
9376 ofmode = rb_io_oflags_fmode(oflags);
9388 if (rb_hash_aref(opt, sym_autoclose) ==
Qfalse) {
9389 fmode |= FMODE_PREP;
9392 path = rb_hash_aref(opt,
RB_ID2SYM(idPath));
9403 fp->
encs = convconfig;
9408 if (fileno(stdin) == fd)
9410 else if (fileno(stdout) == fd)
9412 else if (fileno(stderr) == fd)
9444rb_io_set_encoding_by_bom(
VALUE io)
9455 else if (fptr->
encs.
enc && fptr->
encs.
enc != rb_ascii8bit_encoding()) {
9459 if (!io_set_encoding_by_bom(io))
return Qnil;
9460 return rb_enc_from_encoding(fptr->
encs.
enc);
9505rb_file_initialize(
int argc,
VALUE *argv,
VALUE io)
9507 if (
RFILE(io)->fptr) {
9510 if (0 < argc && argc < 3) {
9515 return rb_io_initialize(argc, argv, io);
9518 rb_open_file(argc, argv, io);
9525rb_io_s_new(
int argc,
VALUE *argv,
VALUE klass)
9530 rb_warn(
"%"PRIsVALUE
"::new() does not take block; use %"PRIsVALUE
"::open() instead",
9546rb_io_s_for_fd(
int argc,
VALUE *argv,
VALUE klass)
9549 rb_io_initialize(argc, argv, io);
9562rb_io_autoclose_p(
VALUE io)
9566 return RBOOL(!(fptr->
mode & FMODE_PREP));
9587rb_io_set_autoclose(
VALUE io,
VALUE autoclose)
9591 if (!
RTEST(autoclose))
9592 fptr->
mode |= FMODE_PREP;
9594 fptr->
mode &= ~FMODE_PREP;
9599io_wait_event(
VALUE io,
int event,
VALUE timeout,
int return_io)
9603 if (!RB_TEST(result)) {
9631io_wait_readable(
int argc,
VALUE *argv,
VALUE io)
9638 if (rb_io_read_pending(fptr))
return Qtrue;
9640 rb_check_arity(argc, 0, 1);
9641 VALUE timeout = (argc == 1 ? argv[0] :
Qnil);
9655io_wait_writable(
int argc,
VALUE *argv,
VALUE io)
9662 rb_check_arity(argc, 0, 1);
9663 VALUE timeout = (argc == 1 ? argv[0] :
Qnil);
9678io_wait_priority(
int argc,
VALUE *argv,
VALUE io)
9685 if (rb_io_read_pending(fptr))
return Qtrue;
9687 rb_check_arity(argc, 0, 1);
9688 VALUE timeout = argc == 1 ? argv[0] :
Qnil;
9694wait_mode_sym(
VALUE mode)
9696 if (mode ==
ID2SYM(rb_intern(
"r"))) {
9697 return RB_WAITFD_IN;
9699 if (mode ==
ID2SYM(rb_intern(
"read"))) {
9700 return RB_WAITFD_IN;
9702 if (mode ==
ID2SYM(rb_intern(
"readable"))) {
9703 return RB_WAITFD_IN;
9705 if (mode ==
ID2SYM(rb_intern(
"w"))) {
9706 return RB_WAITFD_OUT;
9708 if (mode ==
ID2SYM(rb_intern(
"write"))) {
9709 return RB_WAITFD_OUT;
9711 if (mode ==
ID2SYM(rb_intern(
"writable"))) {
9712 return RB_WAITFD_OUT;
9714 if (mode ==
ID2SYM(rb_intern(
"rw"))) {
9715 return RB_WAITFD_IN|RB_WAITFD_OUT;
9717 if (mode ==
ID2SYM(rb_intern(
"read_write"))) {
9718 return RB_WAITFD_IN|RB_WAITFD_OUT;
9720 if (mode ==
ID2SYM(rb_intern(
"readable_writable"))) {
9721 return RB_WAITFD_IN|RB_WAITFD_OUT;
9728io_event_from_value(
VALUE value)
9765 if (argc != 2 || (RB_SYMBOL_P(argv[0]) || RB_SYMBOL_P(argv[1]))) {
9770 for (
int i = 0; i < argc; i += 1) {
9771 if (RB_SYMBOL_P(argv[i])) {
9772 events |= wait_mode_sym(argv[i]);
9774 else if (UNDEF_P(timeout)) {
9782 if (UNDEF_P(timeout)) timeout =
Qnil;
9790 events = io_event_from_value(argv[0]);
9798 if (rb_io_read_pending(fptr)) {
9800 if (return_io)
return Qtrue;
9806 return io_wait_event(io, events, timeout, return_io);
9812 struct argf *p = ptr;
9813 rb_gc_mark(p->filename);
9814 rb_gc_mark(p->current_file);
9815 rb_gc_mark(p->argv);
9816 rb_gc_mark(p->inplace);
9817 rb_gc_mark(p->encs.
ecopts);
9821argf_memsize(
const void *ptr)
9823 const struct argf *p = ptr;
9824 size_t size =
sizeof(*p);
9831 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
9838 p->current_file =
Qnil;
9844argf_alloc(
VALUE klass)
9859 memset(&ARGF, 0,
sizeof(ARGF));
9860 argf_init(&ARGF, argv);
9870 ARGF = argf_of(orig);
9897 ARGF.last_lineno = ARGF.lineno;
9923 return forward_current(rb_frame_this_func(), argc, argv);
9926#define next_argv() argf_next_argv(argf)
9927#define ARGF_GENERIC_INPUT_P() \
9928 (ARGF.current_file == rb_stdin && !RB_TYPE_P(ARGF.current_file, T_FILE))
9929#define ARGF_FORWARD(argc, argv) do {\
9930 if (ARGF_GENERIC_INPUT_P())\
9931 return argf_forward((argc), (argv), argf);\
9933#define NEXT_ARGF_FORWARD(argc, argv) do {\
9934 if (!next_argv()) return Qnil;\
9935 ARGF_FORWARD((argc), (argv));\
9941 VALUE file = ARGF.current_file;
9943 if (RB_TYPE_P(file,
T_FILE)) {
9955 int stdout_binmode = 0;
9960 if (RB_TYPE_P(r_stdout,
T_FILE)) {
9966 if (ARGF.init_p == 0) {
9976 if (
NIL_P(ARGF.argv)) {
9979 else if (ARGF.next_p == -1 &&
RARRAY_LEN(ARGF.argv) > 0) {
9984 if (ARGF.next_p == 1) {
9985 if (ARGF.init_p == 1) argf_close(
argf);
9988 VALUE filename = rb_ary_shift(ARGF.argv);
9990 ARGF.filename = filename;
9991 filename = rb_str_encode_ospath(filename);
9993 if (RSTRING_LEN(filename) == 1 && fn[0] ==
'-') {
9996 rb_warn(
"Can't do inplace edit for stdio; skipping");
10002 int fr = rb_sysopen(filename, O_RDONLY, 0);
10004 if (ARGF.inplace) {
10006#ifndef NO_SAFE_RENAME
10012 if (RB_TYPE_P(r_stdout,
T_FILE) && r_stdout != orig_stdout) {
10017 if (!
NIL_P(ARGF.inplace)) {
10018 VALUE suffix = ARGF.inplace;
10020 if (
NIL_P(rb_str_cat_conv_enc_opts(str, RSTRING_LEN(str),
10021 RSTRING_PTR(suffix), RSTRING_LEN(suffix),
10022 rb_enc_get(suffix), 0,
Qnil))) {
10025#ifdef NO_SAFE_RENAME
10027 (void)unlink(RSTRING_PTR(str));
10028 if (rename(fn, RSTRING_PTR(str)) < 0) {
10029 rb_warn(
"Can't rename %"PRIsVALUE
" to %"PRIsVALUE
": %s, skipping file",
10030 filename, str, strerror(errno));
10033 fr = rb_sysopen(str, O_RDONLY, 0);
10035 if (rename(fn, RSTRING_PTR(str)) < 0) {
10036 rb_warn(
"Can't rename %"PRIsVALUE
" to %"PRIsVALUE
": %s, skipping file",
10037 filename, str, strerror(errno));
10044#ifdef NO_SAFE_RENAME
10045 rb_fatal(
"Can't do inplace edit without backup");
10047 if (unlink(fn) < 0) {
10048 rb_warn(
"Can't remove %"PRIsVALUE
": %s, skipping file",
10049 filename, strerror(errno));
10055 fw = rb_sysopen(filename, O_WRONLY|O_CREAT|O_TRUNC, 0666);
10056#ifndef NO_SAFE_RENAME
10059 fchmod(fw, st.st_mode);
10061 chmod(fn, st.st_mode);
10063 if (st.st_uid!=st2.st_uid || st.st_gid!=st2.st_gid) {
10066 err = fchown(fw, st.st_uid, st.st_gid);
10068 err = chown(fn, st.st_uid, st.st_gid);
10070 if (err && getuid() == 0 && st2.st_uid == 0) {
10071 const char *wkfn = RSTRING_PTR(filename);
10072 rb_warn(
"Can't set owner/group of %"PRIsVALUE
" to same as %"PRIsVALUE
": %s, skipping file",
10073 filename, str, strerror(errno));
10076 (void)unlink(wkfn);
10086 if (!ARGF.binmode) {
10087 fmode |= DEFAULT_TEXTMODE;
10089 ARGF.current_file = prep_io(fr, fmode,
rb_cFile, fn);
10090 if (!
NIL_P(write_io)) {
10097 if (ARGF.encs.enc) {
10098 fptr->
encs = ARGF.encs;
10099 clear_codeconv(fptr);
10102 fptr->
encs.
ecflags &= ~ECONV_NEWLINE_DECORATOR_MASK;
10103 if (!ARGF.binmode) {
10105#ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
10106 fptr->
encs.
ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
10117 else if (ARGF.next_p == -1) {
10120 if (ARGF.inplace) {
10121 rb_warn(
"Can't do inplace edit for stdio");
10125 if (ARGF.init_p == -1) ARGF.init_p = 1;
10133 long lineno = ARGF.lineno;
10136 if (!next_argv())
return Qnil;
10137 if (ARGF_GENERIC_INPUT_P()) {
10138 line = forward_current(idGets, argc, argv);
10145 line = rb_io_getline(argc, argv, ARGF.current_file);
10147 if (
NIL_P(line) && ARGF.next_p != -1) {
10153 if (!
NIL_P(line)) {
10154 ARGF.lineno = ++lineno;
10155 ARGF.last_lineno = ARGF.lineno;
10161argf_lineno_getter(
ID id,
VALUE *var)
10164 return INT2FIX(ARGF.last_lineno);
10172 ARGF.last_lineno = ARGF.lineno = n;
10176rb_reset_argf_lineno(
long n)
10178 ARGF.last_lineno = ARGF.lineno = n;
10219 if (recv ==
argf) {
10220 return argf_gets(argc, argv,
argf);
10222 return forward(
argf, idGets, argc, argv);
10248 line = argf_getline(argc, argv,
argf);
10260 return rb_f_gets(0, 0,
argf);
10264 if (!next_argv())
return Qnil;
10266 if (
NIL_P(line) && ARGF.next_p != -1) {
10272 if (!
NIL_P(line)) {
10274 ARGF.last_lineno = ARGF.lineno;
10300rb_f_readline(
int argc,
VALUE *argv,
VALUE recv)
10302 if (recv ==
argf) {
10303 return argf_readline(argc, argv,
argf);
10305 return forward(
argf, rb_intern(
"readline"), argc, argv);
10331 if (!next_argv()) rb_eof_error();
10332 ARGF_FORWARD(argc, argv);
10333 line = argf_gets(argc, argv,
argf);
10402rb_f_readlines(
int argc,
VALUE *argv,
VALUE recv)
10404 if (recv ==
argf) {
10405 return argf_readlines(argc, argv,
argf);
10407 return forward(
argf, rb_intern(
"readlines"), argc, argv);
10429 long lineno = ARGF.lineno;
10432 ary = rb_ary_new();
10433 while (next_argv()) {
10434 if (ARGF_GENERIC_INPUT_P()) {
10435 lines = forward_current(rb_intern(
"readlines"), argc, argv);
10438 lines = rb_io_readlines(argc, argv, ARGF.current_file);
10442 rb_ary_concat(ary, lines);
10444 ARGF.last_lineno = ARGF.lineno;
10479 rb_last_status_clear();
10480 port = pipe_open_s(str,
"r",
FMODE_READABLE|DEFAULT_TEXTMODE, NULL);
10484 result = read_all(fptr, remain_size(fptr),
Qnil);
10486 RFILE(port)->fptr = NULL;
10487 rb_io_fptr_finalize(fptr);
10493#ifdef HAVE_SYS_SELECT_H
10494#include <sys/select.h>
10508 if (!
NIL_P(read)) {
10513 if (READ_DATA_PENDING(fptr) || READ_CHAR_PENDING(fptr)) {
10517 if (max < fptr->fd) max = fptr->
fd;
10520 timerec.tv_sec = timerec.tv_usec = 0;
10528 if (!
NIL_P(write)) {
10534 if (max < fptr->fd) max = fptr->
fd;
10541 if (!
NIL_P(except)) {
10545 VALUE write_io = GetWriteIO(io);
10548 if (max < fptr->fd) max = fptr->
fd;
10549 if (io != write_io) {
10552 if (max < fptr->fd) max = fptr->
fd;
10567 if (!pending && n == 0)
return Qnil;
10570 rb_ary_push(res, rp?rb_ary_new():
rb_ary_new2(0));
10571 rb_ary_push(res, wp?rb_ary_new():
rb_ary_new2(0));
10572 rb_ary_push(res, ep?rb_ary_new():
rb_ary_new2(0));
10577 VALUE obj = rb_ary_entry(read, i);
10582 rb_ary_push(list, obj);
10590 VALUE obj = rb_ary_entry(write, i);
10592 VALUE write_io = GetWriteIO(io);
10595 rb_ary_push(list, obj);
10603 VALUE obj = rb_ary_entry(except, i);
10605 VALUE write_io = GetWriteIO(io);
10608 rb_ary_push(list, obj);
10610 else if (io != write_io) {
10613 rb_ary_push(list, obj);
10623 VALUE read, write, except;
10629select_call(
VALUE arg)
10633 return select_internal(p->read, p->write, p->except, p->timeout, p->fdsets);
10637select_end(
VALUE arg)
10642 for (i = 0; i < numberof(p->fdsets); ++i)
10647static VALUE sym_normal, sym_sequential, sym_random,
10648 sym_willneed, sym_dontneed, sym_noreuse;
10650#ifdef HAVE_POSIX_FADVISE
10651struct io_advise_struct {
10659io_advise_internal(
void *arg)
10661 struct io_advise_struct *ptr = arg;
10662 return posix_fadvise(ptr->fd, ptr->offset, ptr->len, ptr->advice);
10666io_advise_sym_to_const(
VALUE sym)
10668#ifdef POSIX_FADV_NORMAL
10669 if (sym == sym_normal)
10670 return INT2NUM(POSIX_FADV_NORMAL);
10673#ifdef POSIX_FADV_RANDOM
10674 if (sym == sym_random)
10675 return INT2NUM(POSIX_FADV_RANDOM);
10678#ifdef POSIX_FADV_SEQUENTIAL
10679 if (sym == sym_sequential)
10680 return INT2NUM(POSIX_FADV_SEQUENTIAL);
10683#ifdef POSIX_FADV_WILLNEED
10684 if (sym == sym_willneed)
10685 return INT2NUM(POSIX_FADV_WILLNEED);
10688#ifdef POSIX_FADV_DONTNEED
10689 if (sym == sym_dontneed)
10690 return INT2NUM(POSIX_FADV_DONTNEED);
10693#ifdef POSIX_FADV_NOREUSE
10694 if (sym == sym_noreuse)
10695 return INT2NUM(POSIX_FADV_NOREUSE);
10702do_io_advise(
rb_io_t *fptr,
VALUE advice, rb_off_t offset, rb_off_t len)
10705 struct io_advise_struct ias;
10708 num_adv = io_advise_sym_to_const(advice);
10714 if (
NIL_P(num_adv))
10718 ias.advice =
NUM2INT(num_adv);
10719 ias.offset = offset;
10722 rv = (int)rb_thread_io_blocking_region(io_advise_internal, &ias, fptr->
fd);
10723 if (rv && rv != ENOSYS) {
10730 fptr->
pathv, offset, len, advice);
10740advice_arg_check(
VALUE advice)
10745 if (advice != sym_normal &&
10746 advice != sym_sequential &&
10747 advice != sym_random &&
10748 advice != sym_willneed &&
10749 advice != sym_dontneed &&
10750 advice != sym_noreuse) {
10789rb_io_advise(
int argc,
VALUE *argv,
VALUE io)
10791 VALUE advice, offset, len;
10795 rb_scan_args(argc, argv,
"12", &advice, &offset, &len);
10796 advice_arg_check(advice);
10798 io = GetWriteIO(io);
10804#ifdef HAVE_POSIX_FADVISE
10805 return do_io_advise(fptr, advice, off, l);
10807 ((void)off, (
void)l);
10962rb_f_select(
int argc,
VALUE *argv,
VALUE obj)
10965 if (scheduler !=
Qnil) {
10968 if (!UNDEF_P(result))
return result;
10976 rb_scan_args(argc, argv,
"13", &args.read, &args.write, &args.except, &timeout);
10977 if (
NIL_P(timeout)) {
10982 args.timeout = &timerec;
10985 for (i = 0; i < numberof(args.fdsets); ++i)
10991#ifdef IOCTL_REQ_TYPE
10992 typedef IOCTL_REQ_TYPE ioctl_req_t;
10994 typedef int ioctl_req_t;
10995# define NUM2IOCTLREQ(num) ((int)NUM2LONG(num))
11006nogvl_ioctl(
void *ptr)
11008 struct ioctl_arg *arg = ptr;
11010 return (
VALUE)ioctl(arg->fd, arg->cmd, arg->narg);
11014do_ioctl(
int fd, ioctl_req_t cmd,
long narg)
11017 struct ioctl_arg arg;
11023 retval = (int)rb_thread_io_blocking_region(nogvl_ioctl, &arg, fd);
11029#define DEFAULT_IOCTL_NARG_LEN (256)
11031#if defined(__linux__) && defined(_IOC_SIZE)
11033linux_iocparm_len(ioctl_req_t cmd)
11037 if ((cmd & 0xFFFF0000) == 0) {
11039 return DEFAULT_IOCTL_NARG_LEN;
11042 len = _IOC_SIZE(cmd);
11045 if (len < DEFAULT_IOCTL_NARG_LEN)
11046 len = DEFAULT_IOCTL_NARG_LEN;
11054ioctl_narg_len(ioctl_req_t cmd)
11060#define IOCPARM_LEN(x) (((x) >> 16) & IOCPARM_MASK)
11064 len = IOCPARM_LEN(cmd);
11065#elif defined(__linux__) && defined(_IOC_SIZE)
11066 len = linux_iocparm_len(cmd);
11069 len = DEFAULT_IOCTL_NARG_LEN;
11078typedef long fcntl_arg_t;
11081typedef int fcntl_arg_t;
11085fcntl_narg_len(ioctl_req_t cmd)
11092 len =
sizeof(fcntl_arg_t);
11100#ifdef F_DUPFD_CLOEXEC
11101 case F_DUPFD_CLOEXEC:
11102 len =
sizeof(fcntl_arg_t);
11112 len =
sizeof(fcntl_arg_t);
11122 len =
sizeof(fcntl_arg_t);
11132 len =
sizeof(fcntl_arg_t);
11137 len =
sizeof(
struct f_owner_ex);
11142 len =
sizeof(
struct f_owner_ex);
11147 len =
sizeof(
struct flock);
11152 len =
sizeof(
struct flock);
11157 len =
sizeof(
struct flock);
11177 len =
sizeof(fcntl_arg_t);
11187 len =
sizeof(fcntl_arg_t);
11192 len =
sizeof(fcntl_arg_t);
11205fcntl_narg_len(ioctl_req_t cmd)
11211#define NARG_SENTINEL 17
11214setup_narg(ioctl_req_t cmd,
VALUE *argp,
long (*narg_len)(ioctl_req_t))
11225 else if (arg ==
Qtrue) {
11239 len = narg_len(cmd);
11242 slen = RSTRING_LEN(arg);
11244 if (slen < len+1) {
11246 MEMZERO(RSTRING_PTR(arg)+slen,
char, len-slen);
11250 ptr = RSTRING_PTR(arg);
11251 ptr[slen - 1] = NARG_SENTINEL;
11260finish_narg(
int retval,
VALUE arg,
const rb_io_t *fptr)
11262 if (retval < 0) rb_sys_fail_path(fptr->
pathv);
11267 if (ptr[slen-1] != NARG_SENTINEL)
11269 ptr[slen-1] =
'\0';
11279 ioctl_req_t cmd = NUM2IOCTLREQ(req);
11284 narg = setup_narg(cmd, &arg, ioctl_narg_len);
11286 retval = do_ioctl(fptr->
fd, cmd, narg);
11287 return finish_narg(retval, arg, fptr);
11313 rb_scan_args(argc, argv,
"11", &req, &arg);
11314 return rb_ioctl(io, req, arg);
11317#define rb_io_ioctl rb_f_notimplement
11328nogvl_fcntl(
void *ptr)
11330 struct fcntl_arg *arg = ptr;
11332#if defined(F_DUPFD)
11333 if (arg->cmd == F_DUPFD)
11336 return (
VALUE)fcntl(arg->fd, arg->cmd, arg->narg);
11340do_fcntl(
int fd,
int cmd,
long narg)
11343 struct fcntl_arg arg;
11349 retval = (int)rb_thread_io_blocking_region(nogvl_fcntl, &arg, fd);
11350 if (retval != -1) {
11352#if defined(F_DUPFD)
11355#if defined(F_DUPFD_CLOEXEC)
11356 case F_DUPFD_CLOEXEC:
11373 narg = setup_narg(cmd, &arg, fcntl_narg_len);
11375 retval = do_fcntl(fptr->
fd, cmd, narg);
11376 return finish_narg(retval, arg, fptr);
11401 rb_scan_args(argc, argv,
"11", &req, &arg);
11402 return rb_fcntl(io, req, arg);
11405#define rb_io_fcntl rb_f_notimplement
11408#if defined(HAVE_SYSCALL) || defined(HAVE___SYSCALL)
11440#if SIZEOF_VOIDP == 8 && defined(HAVE___SYSCALL) && SIZEOF_INT != 8
11441# define SYSCALL __syscall
11442# define NUM2SYSCALLID(x) NUM2LONG(x)
11443# define RETVAL2NUM(x) LONG2NUM(x)
11444# if SIZEOF_LONG == 8
11445 long num, retval = -1;
11446# elif SIZEOF_LONG_LONG == 8
11447 long long num, retval = -1;
11449# error ---->> it is asserted that __syscall takes the first argument and returns retval in 64bit signed integer. <<----
11451#elif defined(__linux__)
11452# define SYSCALL syscall
11453# define NUM2SYSCALLID(x) NUM2LONG(x)
11454# define RETVAL2NUM(x) LONG2NUM(x)
11462 long num, retval = -1;
11464# define SYSCALL syscall
11465# define NUM2SYSCALLID(x) NUM2INT(x)
11466# define RETVAL2NUM(x) INT2NUM(x)
11467 int num, retval = -1;
11473 "We plan to remove a syscall function at future release. DL(Fiddle) provides safer alternative.");
11478 if (argc > numberof(arg))
11480 num = NUM2SYSCALLID(argv[0]); ++argv;
11481 for (i = argc - 1; i--; ) {
11496 retval = SYSCALL(num);
11499 retval = SYSCALL(num, arg[0]);
11502 retval = SYSCALL(num, arg[0],arg[1]);
11505 retval = SYSCALL(num, arg[0],arg[1],arg[2]);
11508 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3]);
11511 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4]);
11514 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5]);
11517 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6]);
11523 return RETVAL2NUM(retval);
11525#undef NUM2SYSCALLID
11529#define rb_f_syscall rb_f_notimplement
11533io_new_instance(
VALUE args)
11539find_encoding(
VALUE v)
11542 if (!enc)
rb_warn(
"Unsupported encoding %"PRIsVALUE
" ignored", v);
11554 enc2 = find_encoding(v1);
11557 if (RSTRING_LEN(tmp) == 1 && RSTRING_PTR(tmp)[0] ==
'-') {
11563 enc = find_encoding(v2);
11570 enc = find_encoding(v2);
11576 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
11582 rb_io_ext_int_to_encs(NULL, NULL, &enc, &enc2, 0);
11583 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
11588 if (!
NIL_P(tmp) && rb_enc_asciicompat(enc = rb_enc_get(tmp))) {
11589 parse_mode_enc(RSTRING_PTR(tmp), enc, &enc, &enc2, NULL);
11590 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
11594 rb_io_ext_int_to_encs(find_encoding(v1), NULL, &enc, &enc2, 0);
11595 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
11600 validate_enc_binmode(&fptr->
mode, ecflags, enc, enc2);
11605 clear_codeconv(fptr);
11617io_encoding_set_v(
VALUE v)
11620 io_encoding_set(arg->fptr, arg->v1, arg->v2, arg->opt);
11625pipe_pair_close(
VALUE rw)
11628 return rb_ensure(io_close, rwp[0], io_close, rwp[1]);
11711rb_io_s_pipe(
int argc,
VALUE *argv,
VALUE klass)
11713 int pipes[2], state;
11714 VALUE r, w, args[3], v1, v2;
11721 argc = rb_scan_args(argc, argv,
"02:", &v1, &v2, &opt);
11728 r = rb_protect(io_new_instance, (
VALUE)args, &state);
11732 rb_jump_tag(state);
11736 ies_args.fptr = fptr;
11739 ies_args.opt = opt;
11740 rb_protect(io_encoding_set_v, (
VALUE)&ies_args, &state);
11744 rb_jump_tag(state);
11749 w = rb_protect(io_new_instance, (
VALUE)args, &state);
11753 rb_jump_tag(state);
11758 extract_binmode(opt, &fmode);
11765#if DEFAULT_TEXTMODE
11767 fptr->
mode &= ~FMODE_TEXTMODE;
11768 setmode(fptr->
fd, O_BINARY);
11770#if RUBY_CRLF_ENVIRONMENT
11776 fptr->
mode |= fmode;
11777#if DEFAULT_TEXTMODE
11779 fptr2->
mode &= ~FMODE_TEXTMODE;
11780 setmode(fptr2->
fd, O_BINARY);
11783 fptr2->
mode |= fmode;
11785 ret = rb_assoc_new(r, w);
11817 else if (!
NIL_P(v = rb_hash_aref(opt, sym_open_args))) {
11820 v = rb_to_array_type(v);
11821 n = RARRAY_LENINT(v);
11822 rb_check_arity(n, 0, 3);
11825 arg->io = rb_io_open(klass, path, vmode, vperm, opt);
11829io_s_foreach(
VALUE v)
11834 if (arg->limit == 0)
11836 while (!
NIL_P(str = rb_io_getline_1(arg->rs, arg->limit, arg->chomp, arg->io))) {
11937rb_io_s_foreach(
int argc,
VALUE *argv,
VALUE self)
11940 int orig_argc = argc;
11944 argc = rb_scan_args(argc, argv,
"12:", NULL, NULL, NULL, &opt);
11946 extract_getline_args(argc-1, argv+1, &garg);
11947 open_key_args(self, argc, argv, opt, &arg);
11949 extract_getline_opts(opt, &garg);
11950 check_getline_args(&garg.rs, &garg.limit, garg.io = arg.io);
11951 return rb_ensure(io_s_foreach, (
VALUE)&garg, rb_io_close, arg.io);
11955io_s_readlines(
VALUE v)
11958 return io_readlines(arg, arg->io);
12033rb_io_s_readlines(
int argc,
VALUE *argv,
VALUE io)
12039 argc = rb_scan_args(argc, argv,
"12:", NULL, NULL, NULL, &opt);
12040 extract_getline_args(argc-1, argv+1, &garg);
12041 open_key_args(io, argc, argv, opt, &arg);
12043 extract_getline_opts(opt, &garg);
12044 check_getline_args(&garg.rs, &garg.limit, garg.io = arg.io);
12045 return rb_ensure(io_s_readlines, (
VALUE)&garg, rb_io_close, arg.io);
12052 return io_read(arg->argc, arg->argv, arg->io);
12062seek_before_access(
VALUE argp)
12066 return rb_io_seek(arg->io, arg->offset, arg->mode);
12126rb_io_s_read(
int argc,
VALUE *argv,
VALUE io)
12131 argc = rb_scan_args(argc, argv,
"13:", NULL, NULL, &offset, NULL, &opt);
12132 open_key_args(io, argc, argv, opt, &arg);
12134 if (!
NIL_P(offset)) {
12138 sarg.offset = offset;
12139 sarg.mode = SEEK_SET;
12140 rb_protect(seek_before_access, (
VALUE)&sarg, &state);
12143 rb_jump_tag(state);
12145 if (arg.argc == 2) arg.argc = 1;
12165rb_io_s_binread(
int argc,
VALUE *argv,
VALUE io)
12178 rb_scan_args(argc, argv,
"12", NULL, NULL, &offset);
12180 convconfig.
enc = rb_ascii8bit_encoding();
12181 arg.io = rb_io_open_generic(io, argv[0], oflags, fmode, &convconfig, 0);
12184 arg.argc = (argc > 1) ? 1 : 0;
12185 if (!
NIL_P(offset)) {
12189 sarg.offset = offset;
12190 sarg.mode = SEEK_SET;
12191 rb_protect(seek_before_access, (
VALUE)&sarg, &state);
12194 rb_jump_tag(state);
12201io_s_write0(
VALUE v)
12204 return io_write(arg->io,arg->str,arg->nosync);
12208io_s_write(
int argc,
VALUE *argv,
VALUE klass,
int binary)
12210 VALUE string, offset, opt;
12214 rb_scan_args(argc, argv,
"21:", NULL, &
string, &offset, &opt);
12216 if (
NIL_P(opt)) opt = rb_hash_new();
12217 else opt = rb_hash_dup(opt);
12220 if (
NIL_P(rb_hash_aref(opt,sym_mode))) {
12221 int mode = O_WRONLY|O_CREAT;
12223 if (binary) mode |= O_BINARY;
12225 if (
NIL_P(offset)) mode |= O_TRUNC;
12226 rb_hash_aset(opt,sym_mode,
INT2NUM(mode));
12228 open_key_args(klass, argc, argv, opt, &arg);
12231 if (binary) rb_io_binmode_m(arg.io);
12235 if (!
NIL_P(offset)) {
12239 sarg.offset = offset;
12240 sarg.mode = SEEK_SET;
12241 rb_protect(seek_before_access, (
VALUE)&sarg, &state);
12244 rb_jump_tag(state);
12252 return rb_ensure(io_s_write0, (
VALUE)&warg, rb_io_close, arg.io);
12317rb_io_s_write(
int argc,
VALUE *argv,
VALUE io)
12319 return io_s_write(argc, argv, io, 0);
12337rb_io_s_binwrite(
int argc,
VALUE *argv,
VALUE io)
12339 return io_s_write(argc, argv, io, 1);
12345 rb_off_t copy_length;
12346 rb_off_t src_offset;
12350 unsigned close_src : 1;
12351 unsigned close_dst : 1;
12354 const char *syserr;
12355 const char *notimp;
12357 struct stat src_stat;
12358 struct stat dst_stat;
12359#ifdef HAVE_FCOPYFILE
12360 copyfile_state_t copyfile_state;
12365exec_interrupts(
void *arg)
12368 rb_thread_execute_interrupts(th);
12382#if defined(ERESTART)
12387 rb_thread_execute_interrupts(stp->th);
12406fiber_scheduler_wait_for(
void * _arguments)
12416# define IOWAIT_SYSCALL "poll"
12417STATIC_ASSERT(pollin_expected, POLLIN == RB_WAITFD_IN);
12418STATIC_ASSERT(pollout_expected, POLLOUT == RB_WAITFD_OUT);
12423 if (scheduler !=
Qnil) {
12426 return RTEST(args.result);
12430 if (fd == -1)
return 0;
12435 fds.events = events;
12437 int timeout_milliseconds = -1;
12440 timeout_milliseconds = (int)(timeout->tv_sec * 1000) + (int)(timeout->tv_usec / 1000);
12443 return poll(&fds, 1, timeout_milliseconds);
12446# define IOWAIT_SYSCALL "select"
12451 if (scheduler !=
Qnil) {
12454 return RTEST(args.result);
12474 case RB_WAITFD_OUT:
12478 VM_UNREACHABLE(nogvl_wait_for);
12498 ret = nogvl_wait_for(stp->th, stp->src_fptr, RB_WAITFD_IN, NULL);
12500 }
while (ret < 0 && maygvl_copy_stream_continue_p(has_gvl, stp));
12503 stp->syserr = IOWAIT_SYSCALL;
12504 stp->error_no = errno;
12516 ret = nogvl_wait_for(stp->th, stp->dst_fptr, RB_WAITFD_OUT, NULL);
12517 }
while (ret < 0 && maygvl_copy_stream_continue_p(0, stp));
12520 stp->syserr = IOWAIT_SYSCALL;
12521 stp->error_no = errno;
12527#ifdef USE_COPY_FILE_RANGE
12530simple_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)
12532#ifdef HAVE_COPY_FILE_RANGE
12533 return copy_file_range(in_fd, in_offset, out_fd, out_offset, count, flags);
12535 return syscall(__NR_copy_file_range, in_fd, in_offset, out_fd, out_offset, count, flags);
12544 rb_off_t copy_length, src_offset, *src_offset_ptr;
12546 if (!S_ISREG(stp->src_stat.st_mode))
12549 src_size = stp->src_stat.st_size;
12550 src_offset = stp->src_offset;
12551 if (src_offset >= (rb_off_t)0) {
12552 src_offset_ptr = &src_offset;
12555 src_offset_ptr = NULL;
12558 copy_length = stp->copy_length;
12559 if (copy_length < (rb_off_t)0) {
12560 if (src_offset < (rb_off_t)0) {
12561 rb_off_t current_offset;
12563 current_offset = lseek(stp->src_fptr->
fd, 0, SEEK_CUR);
12564 if (current_offset < (rb_off_t)0 && errno) {
12565 stp->syserr =
"lseek";
12566 stp->error_no = errno;
12567 return (
int)current_offset;
12569 copy_length = src_size - current_offset;
12572 copy_length = src_size - src_offset;
12576 retry_copy_file_range:
12577# if SIZEOF_OFF_T > SIZEOF_SIZE_T
12579 ss = (copy_length > (rb_off_t)SSIZE_MAX) ? SSIZE_MAX : (ssize_t)copy_length;
12581 ss = (ssize_t)copy_length;
12583 ss = simple_copy_file_range(stp->src_fptr->
fd, src_offset_ptr, stp->dst_fptr->
fd, NULL, ss, 0);
12587 if (0 < copy_length) {
12588 goto retry_copy_file_range;
12592 if (maygvl_copy_stream_continue_p(0, stp)) {
12593 goto retry_copy_file_range;
12607#if EWOULDBLOCK != EAGAIN
12611 int ret = nogvl_copy_stream_wait_write(stp);
12612 if (ret < 0)
return ret;
12614 goto retry_copy_file_range;
12618 int flags = fcntl(stp->dst_fptr->
fd, F_GETFL);
12620 if (flags != -1 && flags & O_APPEND) {
12626 stp->syserr =
"copy_file_range";
12627 stp->error_no = errno;
12634#ifdef HAVE_FCOPYFILE
12638 rb_off_t cur, ss = 0;
12639 const rb_off_t src_offset = stp->src_offset;
12642 if (stp->copy_length >= (rb_off_t)0) {
12647 if (!S_ISREG(stp->src_stat.st_mode))
12650 if (!S_ISREG(stp->dst_stat.st_mode))
12652 if (lseek(stp->dst_fptr->
fd, 0, SEEK_CUR) > (rb_off_t)0)
12654 if (fcntl(stp->dst_fptr->
fd, F_GETFL) & O_APPEND) {
12657 rb_off_t end = lseek(stp->dst_fptr->
fd, 0, SEEK_END);
12658 lseek(stp->dst_fptr->
fd, 0, SEEK_SET);
12659 if (end > (rb_off_t)0)
return 0;
12662 if (src_offset > (rb_off_t)0) {
12667 cur = lseek(stp->src_fptr->
fd, 0, SEEK_CUR);
12668 if (cur < (rb_off_t)0 && errno) {
12669 stp->error_no = errno;
12674 r = lseek(stp->src_fptr->
fd, src_offset, SEEK_SET);
12675 if (r < (rb_off_t)0 && errno) {
12676 stp->error_no = errno;
12681 stp->copyfile_state = copyfile_state_alloc();
12682 ret = fcopyfile(stp->src_fptr->
fd, stp->dst_fptr->
fd, stp->copyfile_state, COPYFILE_DATA);
12683 copyfile_state_get(stp->copyfile_state, COPYFILE_STATE_COPIED, &ss);
12687 if (src_offset > (rb_off_t)0) {
12691 r = lseek(stp->src_fptr->
fd, cur, SEEK_SET);
12692 if (r < (rb_off_t)0 && errno) {
12693 stp->error_no = errno;
12705 stp->syserr =
"fcopyfile";
12706 stp->error_no = errno;
12713#ifdef HAVE_SENDFILE
12716# define USE_SENDFILE
12718# ifdef HAVE_SYS_SENDFILE_H
12719# include <sys/sendfile.h>
12723simple_sendfile(
int out_fd,
int in_fd, rb_off_t *offset, rb_off_t count)
12725 return sendfile(out_fd, in_fd, offset, (
size_t)count);
12728# elif 0 || defined(__APPLE__)
12732# define USE_SENDFILE
12735simple_sendfile(
int out_fd,
int in_fd, rb_off_t *offset, rb_off_t count)
12738 rb_off_t pos = offset ? *offset : lseek(in_fd, 0, SEEK_CUR);
12741 r = sendfile(in_fd, out_fd, pos, &count, NULL, 0);
12744 r = sendfile(in_fd, out_fd, pos, (
size_t)count, NULL, &sbytes, 0);
12746 if (r != 0 && sbytes == 0)
return r;
12751 lseek(in_fd, sbytes, SEEK_CUR);
12753 return (ssize_t)sbytes;
12766 rb_off_t copy_length;
12767 rb_off_t src_offset;
12770 if (!S_ISREG(stp->src_stat.st_mode))
12773 src_size = stp->src_stat.st_size;
12775 if ((stp->dst_stat.st_mode & S_IFMT) != S_IFSOCK)
12779 src_offset = stp->src_offset;
12780 use_pread = src_offset >= (rb_off_t)0;
12782 copy_length = stp->copy_length;
12783 if (copy_length < (rb_off_t)0) {
12785 copy_length = src_size - src_offset;
12789 cur = lseek(stp->src_fptr->
fd, 0, SEEK_CUR);
12790 if (cur < (rb_off_t)0 && errno) {
12791 stp->syserr =
"lseek";
12792 stp->error_no = errno;
12795 copy_length = src_size - cur;
12800# if SIZEOF_OFF_T > SIZEOF_SIZE_T
12802 ss = (copy_length > (rb_off_t)SSIZE_MAX) ? SSIZE_MAX : (ssize_t)copy_length;
12804 ss = (ssize_t)copy_length;
12807 ss = simple_sendfile(stp->dst_fptr->
fd, stp->src_fptr->
fd, &src_offset, ss);
12810 ss = simple_sendfile(stp->dst_fptr->
fd, stp->src_fptr->
fd, NULL, ss);
12815 if (0 < copy_length) {
12816 goto retry_sendfile;
12820 if (maygvl_copy_stream_continue_p(0, stp))
12821 goto retry_sendfile;
12834#if EWOULDBLOCK != EAGAIN
12847 ret = maygvl_copy_stream_wait_read(0, stp);
12848 if (ret < 0)
return ret;
12850 ret = nogvl_copy_stream_wait_write(stp);
12851 if (ret < 0)
return ret;
12853 goto retry_sendfile;
12855 stp->syserr =
"sendfile";
12856 stp->error_no = errno;
12864maygvl_read(
int has_gvl,
rb_io_t *fptr,
void *buf,
size_t count)
12867 return rb_io_read_memory(fptr, buf, count);
12869 return read(fptr->
fd, buf, count);
12873maygvl_copy_stream_read(
int has_gvl,
struct copy_stream_struct *stp,
char *buf,
size_t len, rb_off_t offset)
12877 if (offset < (rb_off_t)0) {
12878 ss = maygvl_read(has_gvl, stp->src_fptr, buf, len);
12882 ss = pread(stp->src_fptr->
fd, buf, len, offset);
12884 stp->notimp =
"pread";
12892 if (maygvl_copy_stream_continue_p(has_gvl, stp))
12896#if EWOULDBLOCK != EAGAIN
12900 int ret = maygvl_copy_stream_wait_read(has_gvl, stp);
12901 if (ret < 0)
return ret;
12906 stp->notimp =
"pread";
12910 stp->syserr = offset < (rb_off_t)0 ?
"read" :
"pread";
12911 stp->error_no = errno;
12922 ss = write(stp->dst_fptr->
fd, buf+off, len);
12924 if (maygvl_copy_stream_continue_p(0, stp))
12926 if (io_again_p(errno)) {
12927 int ret = nogvl_copy_stream_wait_write(stp);
12928 if (ret < 0)
return ret;
12931 stp->syserr =
"write";
12932 stp->error_no = errno;
12949 rb_off_t copy_length;
12950 rb_off_t src_offset;
12954 copy_length = stp->copy_length;
12955 use_eof = copy_length < (rb_off_t)0;
12956 src_offset = stp->src_offset;
12957 use_pread = src_offset >= (rb_off_t)0;
12959 if (use_pread && stp->close_src) {
12962 r = lseek(stp->src_fptr->
fd, src_offset, SEEK_SET);
12963 if (r < (rb_off_t)0 && errno) {
12964 stp->syserr =
"lseek";
12965 stp->error_no = errno;
12968 src_offset = (rb_off_t)-1;
12972 while (use_eof || 0 < copy_length) {
12973 if (!use_eof && copy_length < (rb_off_t)
sizeof(buf)) {
12974 len = (size_t)copy_length;
12980 ss = maygvl_copy_stream_read(0, stp, buf, len, src_offset);
12985 ss = maygvl_copy_stream_read(0, stp, buf, len, (rb_off_t)-1);
12990 ret = nogvl_copy_stream_write(stp, buf, ss);
13000nogvl_copy_stream_func(
void *arg)
13003#if defined(USE_SENDFILE) || defined(USE_COPY_FILE_RANGE) || defined(HAVE_FCOPYFILE)
13007#ifdef USE_COPY_FILE_RANGE
13008 ret = nogvl_copy_file_range(stp);
13013#ifdef HAVE_FCOPYFILE
13014 ret = nogvl_fcopyfile(stp);
13020 ret = nogvl_copy_stream_sendfile(stp);
13025 nogvl_copy_stream_read_write(stp);
13027#if defined(USE_SENDFILE) || defined(USE_COPY_FILE_RANGE) || defined(HAVE_FCOPYFILE)
13034copy_stream_fallback_body(
VALUE arg)
13037 const int buflen = 16*1024;
13040 rb_off_t rest = stp->copy_length;
13041 rb_off_t off = stp->src_offset;
13042 ID read_method = id_readpartial;
13044 if (!stp->src_fptr) {
13046 read_method = id_read;
13053 if (stp->copy_length < (rb_off_t)0) {
13061 l = buflen < rest ? buflen : (long)rest;
13063 if (!stp->src_fptr) {
13064 VALUE rc = rb_funcall(stp->src, read_method, 2,
INT2FIX(l), buf);
13066 if (read_method == id_read &&
NIL_P(rc))
13072 ss = maygvl_copy_stream_read(1, stp, RSTRING_PTR(buf), l, off);
13078 if (off >= (rb_off_t)0)
13083 stp->total += numwrote;
13085 if (read_method == id_read && RSTRING_LEN(buf) == 0) {
13096 if (!stp->src_fptr && stp->src_offset >= (rb_off_t)0) {
13106copy_stream_body(
VALUE arg)
13109 VALUE src_io = stp->src, dst_io = stp->dst;
13110 const int common_oflags = 0
13120 if (src_io ==
argf ||
13121 !(RB_TYPE_P(src_io,
T_FILE) ||
13124 stp->src_fptr = NULL;
13129 if (!
NIL_P(tmp_io)) {
13132 else if (!RB_TYPE_P(src_io,
T_FILE)) {
13136 args[1] =
INT2NUM(O_RDONLY|common_oflags);
13139 stp->close_src = 1;
13144 stat_ret = fstat(stp->src_fptr->
fd, &stp->src_stat);
13145 if (stat_ret < 0) {
13146 stp->syserr =
"fstat";
13147 stp->error_no = errno;
13152 if (dst_io ==
argf ||
13153 !(RB_TYPE_P(dst_io,
T_FILE) ||
13156 stp->dst_fptr = NULL;
13161 if (!
NIL_P(tmp_io)) {
13162 dst_io = GetWriteIO(tmp_io);
13164 else if (!RB_TYPE_P(dst_io,
T_FILE)) {
13168 args[1] =
INT2NUM(O_WRONLY|O_CREAT|O_TRUNC|common_oflags);
13172 stp->close_dst = 1;
13175 dst_io = GetWriteIO(dst_io);
13181 stat_ret = fstat(stp->dst_fptr->
fd, &stp->dst_stat);
13182 if (stat_ret < 0) {
13183 stp->syserr =
"fstat";
13184 stp->error_no = errno;
13191 SET_BINARY_MODE_WITH_SEEK_CUR(stp->src_fptr);
13194 io_ascii8bit_binmode(stp->dst_fptr);
13196 if (stp->src_offset < (rb_off_t)0 && stp->src_fptr && stp->src_fptr->
rbuf.
len) {
13197 size_t len = stp->src_fptr->
rbuf.
len;
13199 if (stp->copy_length >= (rb_off_t)0 && stp->copy_length < (rb_off_t)len) {
13200 len = (size_t)stp->copy_length;
13204 read_buffered_data(RSTRING_PTR(str), len, stp->src_fptr);
13205 if (stp->dst_fptr) {
13206 if (io_binwrite(str, RSTRING_PTR(str), RSTRING_LEN(str), stp->dst_fptr, 0) < 0)
13207 rb_sys_fail_on_write(stp->dst_fptr);
13213 if (stp->copy_length >= (rb_off_t)0)
13214 stp->copy_length -= len;
13217 if (stp->dst_fptr && io_fflush(stp->dst_fptr) < 0) {
13221 if (stp->copy_length == 0)
13224 if (stp->src_fptr == NULL || stp->dst_fptr == NULL) {
13225 return copy_stream_fallback(stp);
13233copy_stream_finalize(
VALUE arg)
13237#ifdef HAVE_FCOPYFILE
13238 if (stp->copyfile_state) {
13239 copyfile_state_free(stp->copyfile_state);
13243 if (stp->close_src) {
13244 rb_io_close_m(stp->src);
13246 if (stp->close_dst) {
13247 rb_io_close_m(stp->dst);
13310rb_io_s_copy_stream(
int argc,
VALUE *argv,
VALUE io)
13312 VALUE src, dst, length, src_offset;
13317 rb_scan_args(argc, argv,
"22", &src, &dst, &length, &src_offset);
13322 st.src_fptr = NULL;
13323 st.dst_fptr = NULL;
13326 st.copy_length = (rb_off_t)-1;
13328 st.copy_length =
NUM2OFFT(length);
13330 if (
NIL_P(src_offset))
13331 st.src_offset = (rb_off_t)-1;
13333 st.src_offset =
NUM2OFFT(src_offset);
13352rb_io_external_encoding(
VALUE io)
13357 return rb_enc_from_encoding(fptr->
encs.
enc2);
13361 return rb_enc_from_encoding(fptr->
encs.
enc);
13364 return rb_enc_from_encoding(io_read_encoding(fptr));
13380rb_io_internal_encoding(
VALUE io)
13385 return rb_enc_from_encoding(io_read_encoding(fptr));
13413rb_io_set_encoding(
int argc,
VALUE *argv,
VALUE io)
13418 if (!RB_TYPE_P(io,
T_FILE)) {
13419 return forward(io, id_set_encoding, argc, argv);
13422 argc = rb_scan_args(argc, argv,
"11:", &v1, &v2, &opt);
13424 io_encoding_set(fptr, v1, v2, opt);
13429rb_stdio_set_default_encoding(
void)
13434 if (isatty(fileno(stdin))) {
13436 rb_encoding *internal = rb_default_internal_encoding();
13437 if (!internal) internal = rb_default_external_encoding();
13439 rb_enc_from_encoding(external),
13440 rb_enc_from_encoding(internal),
13445 rb_io_set_encoding(1, &val,
rb_stdin);
13446 rb_io_set_encoding(1, &val,
rb_stdout);
13447 rb_io_set_encoding(1, &val,
rb_stderr);
13451global_argf_p(
VALUE arg)
13453 return arg ==
argf;
13456typedef VALUE (*argf_encoding_func)(
VALUE io);
13459argf_encoding(
VALUE argf, argf_encoding_func func)
13461 if (!
RTEST(ARGF.current_file)) {
13462 return rb_enc_default_external();
13486 return argf_encoding(
argf, rb_io_external_encoding);
13505 return argf_encoding(
argf, rb_io_internal_encoding);
13544 if (!next_argv()) {
13547 rb_io_set_encoding(argc, argv, ARGF.current_file);
13549 ARGF.encs = fptr->
encs;
13568 if (!next_argv()) {
13571 ARGF_FORWARD(0, 0);
13572 return rb_io_tell(ARGF.current_file);
13585 if (!next_argv()) {
13588 ARGF_FORWARD(argc, argv);
13589 return rb_io_seek_m(argc, argv, ARGF.current_file);
13606 if (!next_argv()) {
13609 ARGF_FORWARD(1, &offset);
13610 return rb_io_set_pos(ARGF.current_file, offset);
13631 if (!next_argv()) {
13634 ARGF_FORWARD(0, 0);
13635 old_lineno =
RFILE(ARGF.current_file)->fptr->lineno;
13636 ret = rb_io_rewind(ARGF.current_file);
13637 if (!global_argf_p(
argf)) {
13638 ARGF.last_lineno = ARGF.lineno -= old_lineno;
13656 if (!next_argv()) {
13659 ARGF_FORWARD(0, 0);
13660 return rb_io_fileno(ARGF.current_file);
13679 ARGF_FORWARD(0, 0);
13680 return ARGF.current_file;
13705 if (
RTEST(ARGF.current_file)) {
13706 if (ARGF.init_p == 0)
return Qtrue;
13708 ARGF_FORWARD(0, 0);
13767 VALUE tmp, str, length;
13770 rb_scan_args(argc, argv,
"02", &length, &str);
13771 if (!
NIL_P(length)) {
13781 if (!next_argv()) {
13784 if (ARGF_GENERIC_INPUT_P()) {
13785 tmp = argf_forward(argc, argv,
argf);
13788 tmp = io_read(argc, argv, ARGF.current_file);
13790 if (
NIL_P(str)) str = tmp;
13793 if (ARGF.next_p != -1) {
13799 else if (argc >= 1) {
13800 long slen = RSTRING_LEN(str);
13816argf_forward_call(
VALUE arg)
13819 argf_forward(p->argc, p->argv, p->argf);
13849 return argf_getpartial(argc, argv,
argf,
Qnil, 0);
13865 rb_scan_args(argc, argv,
"11:", NULL, NULL, &opts);
13870 return argf_getpartial(argc, argv,
argf, opts, 1);
13876 VALUE tmp, str, length;
13879 rb_scan_args(argc, argv,
"11", &length, &str);
13884 no_exception = no_exception_p(opts);
13886 if (!next_argv()) {
13892 if (ARGF_GENERIC_INPUT_P()) {
13902 tmp = io_getpartial(argc, argv, ARGF.current_file, no_exception, nonblock);
13905 if (ARGF.next_p == -1) {
13906 return io_nonblock_eof(no_exception);
13911 return io_nonblock_eof(no_exception);
13949 if (!next_argv())
return Qnil;
13950 if (ARGF_GENERIC_INPUT_P()) {
13951 ch = forward_current(rb_intern(
"getc"), 0, 0);
13954 ch = rb_io_getc(ARGF.current_file);
13956 if (
NIL_P(ch) && ARGF.next_p != -1) {
13989 if (!next_argv())
return Qnil;
13990 if (!RB_TYPE_P(ARGF.current_file,
T_FILE)) {
13991 ch = forward_current(rb_intern(
"getbyte"), 0, 0);
13996 if (
NIL_P(ch) && ARGF.next_p != -1) {
14029 if (!next_argv()) rb_eof_error();
14030 if (!RB_TYPE_P(ARGF.current_file,
T_FILE)) {
14031 ch = forward_current(rb_intern(
"getc"), 0, 0);
14034 ch = rb_io_getc(ARGF.current_file);
14036 if (
NIL_P(ch) && ARGF.next_p != -1) {
14068 NEXT_ARGF_FORWARD(0, 0);
14069 c = argf_getbyte(
argf);
14076#define FOREACH_ARGF() while (next_argv())
14081 const VALUE current = ARGF.current_file;
14083 if (ARGF.init_p == -1 || current != ARGF.current_file) {
14089#define ARGF_block_call(mid, argc, argv, func, argf) \
14090 rb_block_call_kw(ARGF.current_file, mid, argc, argv, \
14091 func, argf, rb_keyword_given_p())
14096 VALUE ret = ARGF_block_call(mid, argc, argv, argf_block_call_i,
argf);
14097 if (!UNDEF_P(ret)) ARGF.next_p = 1;
14103 if (!global_argf_p(
argf)) {
14104 ARGF.last_lineno = ++ARGF.lineno;
14106 return argf_block_call_i(i,
argf, argc, argv, blockarg);
14112 VALUE ret = ARGF_block_call(mid, argc, argv, argf_block_call_line_i,
argf);
14113 if (!UNDEF_P(ret)) ARGF.next_p = 1;
14161 argf_block_call_line(rb_intern(
"each_line"), argc, argv,
argf);
14192 argf_block_call(rb_intern(
"each_byte"), 0, 0,
argf);
14218 argf_block_call(rb_intern(
"each_char"), 0, 0,
argf);
14244 argf_block_call(rb_intern(
"each_codepoint"), 0, 0,
argf);
14275 return ARGF.filename;
14279argf_filename_getter(
ID id,
VALUE *var)
14281 return argf_filename(*var);
14306 return ARGF.current_file;
14325 ARGF_FORWARD(0, 0);
14346 return RBOOL(ARGF.binmode);
14366 if (ARGF.init_p && ARGF.next_p == 0) {
14395 if (ARGF.next_p != -1) {
14413 ARGF_FORWARD(0, 0);
14414 return rb_io_closed(ARGF.current_file);
14440 if (!ARGF.inplace)
return Qnil;
14448 return argf_inplace_mode_get(*var);
14479 ARGF.inplace =
Qnil;
14490 argf_inplace_mode_set(*var, val);
14494ruby_set_inplace_mode(
const char *suffix)
14520argf_argv_getter(
ID id,
VALUE *var)
14522 return argf_argv(*var);
14541 if (!
RTEST(ARGF.current_file)) {
14544 return GetWriteIO(ARGF.current_file);
14571 case RB_IO_WAIT_WRITABLE:
14574 c = rb_eEAGAINWaitWritable;
14576#if EAGAIN != EWOULDBLOCK
14578 c = rb_eEWOULDBLOCKWaitWritable;
14582 c = rb_eEINPROGRESSWaitWritable;
14588 case RB_IO_WAIT_READABLE:
14591 c = rb_eEAGAINWaitReadable;
14593#if EAGAIN != EWOULDBLOCK
14595 c = rb_eEWOULDBLOCKWaitReadable;
14599 c = rb_eEINPROGRESSWaitReadable;
14606 rb_bug(
"invalid read/write type passed to rb_readwrite_sys_fail: %d", waiting);
14612get_LAST_READ_LINE(
ID _x,
VALUE *_y)
15264#include <sys/cygwin.h>
15265 static struct __cygwin_perfile pf[] =
15267 {
"", O_RDONLY | O_BINARY},
15268 {
"", O_WRONLY | O_BINARY},
15269 {
"", O_RDWR | O_BINARY},
15270 {
"", O_APPEND | O_BINARY},
15273 cygwin_internal(CW_PERFILE, pf);
15279 id_write = rb_intern_const(
"write");
15280 id_read = rb_intern_const(
"read");
15281 id_getc = rb_intern_const(
"getc");
15282 id_flush = rb_intern_const(
"flush");
15283 id_readpartial = rb_intern_const(
"readpartial");
15284 id_set_encoding = rb_intern_const(
"set_encoding");
15285 id_fileno = rb_intern_const(
"fileno");
15324#if EAGAIN == EWOULDBLOCK
15325 rb_eEWOULDBLOCKWaitReadable = rb_eEAGAINWaitReadable;
15328 rb_eEWOULDBLOCKWaitWritable = rb_eEAGAINWaitWritable;
15370 rb_output_fs =
Qnil;
15382 rb_gvar_ractor_local(
"$_");
15499 rb_gvar_ractor_local(
"$stdin");
15500 rb_gvar_ractor_local(
"$stdout");
15501 rb_gvar_ractor_local(
"$>");
15502 rb_gvar_ractor_local(
"$stderr");
15589 rb_define_method(rb_cARGF,
"external_encoding", argf_external_encoding, 0);
15590 rb_define_method(rb_cARGF,
"internal_encoding", argf_internal_encoding, 0);
15609 rb_gvar_ractor_local(
"$-i");
15613#if defined (_WIN32) || defined(__CYGWIN__)
15614 atexit(pipe_atexit);
15621 sym_mode =
ID2SYM(rb_intern_const(
"mode"));
15622 sym_perm =
ID2SYM(rb_intern_const(
"perm"));
15623 sym_flags =
ID2SYM(rb_intern_const(
"flags"));
15624 sym_extenc =
ID2SYM(rb_intern_const(
"external_encoding"));
15625 sym_intenc =
ID2SYM(rb_intern_const(
"internal_encoding"));
15626 sym_encoding =
ID2SYM(rb_id_encoding());
15627 sym_open_args =
ID2SYM(rb_intern_const(
"open_args"));
15628 sym_textmode =
ID2SYM(rb_intern_const(
"textmode"));
15629 sym_binmode =
ID2SYM(rb_intern_const(
"binmode"));
15630 sym_autoclose =
ID2SYM(rb_intern_const(
"autoclose"));
15631 sym_normal =
ID2SYM(rb_intern_const(
"normal"));
15632 sym_sequential =
ID2SYM(rb_intern_const(
"sequential"));
15633 sym_random =
ID2SYM(rb_intern_const(
"random"));
15634 sym_willneed =
ID2SYM(rb_intern_const(
"willneed"));
15635 sym_dontneed =
ID2SYM(rb_intern_const(
"dontneed"));
15636 sym_noreuse =
ID2SYM(rb_intern_const(
"noreuse"));
15637 sym_SET =
ID2SYM(rb_intern_const(
"SET"));
15638 sym_CUR =
ID2SYM(rb_intern_const(
"CUR"));
15639 sym_END =
ID2SYM(rb_intern_const(
"END"));
15641 sym_DATA =
ID2SYM(rb_intern_const(
"DATA"));
15644 sym_HOLE =
ID2SYM(rb_intern_const(
"HOLE"));
15646 sym_wait_readable =
ID2SYM(rb_intern_const(
"wait_readable"));
15647 sym_wait_writable =
ID2SYM(rb_intern_const(
"wait_writable"));
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_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.
VALUE rb_enc_uint_chr(unsigned int code, rb_encoding *enc)
Encodes the passed code point into a series of bytes.
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_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.
Defines RBIMPL_HAS_BUILTIN.
#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.
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.
#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.
int rb_wait_for_single_fd(int fd, int events, struct timeval *tv)
Blocks until the passed file descriptor is ready for the passed events.
FILE * rb_fdopen(int fd, const char *modestr)
Identical to rb_io_stdio_file(), except it takes file descriptors instead of Ruby's IO.
int rb_io_descriptor(VALUE io)
Returns an integer representing the numeric file descriptor for io.
#define FMODE_WRITABLE
The IO is opened for writing.
FILE * rb_io_stdio_file(rb_io_t *fptr)
Finds or creates a stdio's file structure from a Ruby's one.
#define FMODE_APPEND
The IO is opened for appending.
#define MakeOpenFile
This is an old name of RB_IO_OPEN.
#define FMODE_DUPLEX
Ruby eventually detects that the IO is bidirectional.
#define FMODE_BINMODE
The IO is in "binary mode".
int rb_io_maybe_wait_readable(int error, VALUE io, VALUE timeout)
Blocks until the passed IO is ready for reading, if that makes sense for the passed errno.
#define RB_IO_POINTER(obj, fp)
Queries the underlying IO pointer.
VALUE rb_io_maybe_wait(int error, VALUE io, VALUE events, VALUE timeout)
Identical to rb_io_wait() except it additionally takes previous errno.
VALUE rb_eIOTimeoutError
Indicates that a timeout has occurred while performing an IO operation.
#define FMODE_SYNC
The IO is in "sync mode".
void rb_io_check_initialized(rb_io_t *fptr)
Asserts that the passed IO is initialised.
#define FMODE_EXCL
This flag amends the effect of FMODE_CREATE, so that if there already is a file at the given path the...
#define FMODE_TEXTMODE
The IO is in "text mode".
VALUE rb_io_check_io(VALUE io)
Try converting an object to its IO representation using its to_io method, if any.
VALUE rb_io_set_timeout(VALUE io, VALUE timeout)
Set the timeout associated with the specified io object.
ssize_t rb_io_bufwrite(VALUE io, const void *buf, size_t size)
Buffered write to the passed IO.
void rb_io_check_char_readable(rb_io_t *fptr)
Asserts that an IO is opened for character-based reading.
#define FMODE_TRUNC
This flag amends the effect of FMODE_CREATE, so that if there already is a file at the given path it ...
VALUE rb_io_get_write_io(VALUE io)
Queries the tied IO for writing.
void rb_io_set_nonblock(rb_io_t *fptr)
Instructs the OS to put its internal file structure into "nonblocking mode".
void rb_io_extract_modeenc(VALUE *vmode_p, VALUE *vperm_p, VALUE opthash, int *oflags_p, int *fmode_p, rb_io_enc_t *convconfig_p)
This function can be seen as an extended version of rb_io_extract_encoding_option() that not only con...
int rb_io_wait_writable(int fd)
Blocks until the passed file descriptor gets writable.
VALUE rb_io_set_write_io(VALUE io, VALUE w)
Assigns the tied IO for writing.
void rb_io_check_writable(rb_io_t *fptr)
Asserts that an IO is opened for writing.
int rb_io_maybe_wait_writable(int error, VALUE io, VALUE timeout)
Blocks until the passed IO is ready for writing, if that makes sense for the passed errno.
void rb_io_check_closed(rb_io_t *fptr)
This badly named function asserts that the passed IO is open.
rb_io_event_t
Type of events that an IO can wait.
@ RUBY_IO_READABLE
IO::READABLE
@ RUBY_IO_PRIORITY
IO::PRIORITY
@ RUBY_IO_WRITABLE
IO::WRITABLE
int rb_io_wait_readable(int fd)
Blocks until the passed file descriptor gets readable.
void rb_io_synchronized(rb_io_t *fptr)
Sets FMODE_SYNC.
VALUE rb_io_wait(VALUE io, VALUE events, VALUE timeout)
Blocks until the passed IO is ready for the passed events.
VALUE rb_ractor_stderr(void)
Queries the standard error of the current Ractor that is calling this function.
VALUE rb_ractor_stdin(void)
Queries the standard input of the current Ractor that is calling this function.
void rb_ractor_stderr_set(VALUE io)
Assigns an IO to the standard error of the Ractor that is calling this function.
VALUE rb_ractor_stdout(void)
Queries the standard output of the current Ractor that is calling this function.
void rb_ractor_stdout_set(VALUE io)
Assigns an IO to the standard output of the Ractor that is calling this function.
void rb_ractor_stdin_set(VALUE io)
Assigns an IO to the standard input of the Ractor that is calling this function.
void * rb_thread_call_with_gvl(void *(*func)(void *), void *data1)
(Re-)acquires the GVL.
void * rb_thread_call_without_gvl(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2)
Allows the passed function to run in parallel with other Ruby threads.
#define RB_NUM2INT
Just another name of rb_num2int_inline.
#define RB_INT2NUM
Just another name of rb_int2num_inline.
VALUE rb_f_sprintf(int argc, const VALUE *argv)
Identical to rb_str_format(), except how the arguments are arranged.
VALUE rb_sprintf(const char *fmt,...)
Ruby's extended sprintf(3).
VALUE rb_str_catf(VALUE dst, const char *fmt,...)
Identical to rb_sprintf(), except it renders the output to the specified object rather than creating ...
#define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)
Shim for block function parameters.
VALUE rb_yield_values2(int n, const VALUE *argv)
Identical to rb_yield_values(), except it takes the parameters as a C array instead of variadic argum...
VALUE rb_yield(VALUE val)
Yields the block.
void rb_fd_term(rb_fdset_t *f)
Destroys the rb_fdset_t, releasing any memory and resources it used.
#define MEMZERO(p, type, n)
Handy macro to erase a region of memory.
#define RB_GC_GUARD(v)
Prevents premature destruction of local objects.
#define MEMMOVE(p1, p2, type, n)
Handy macro to call memmove.
#define NUM2MODET
Converts a C's mode_t into an instance of rb_cInteger.
void rb_define_hooked_variable(const char *q, VALUE *w, type *e, void_type *r)
Define a function-backended global variable.
void rb_define_virtual_variable(const char *q, type *w, void_type *e)
Define a function-backended global variable.
VALUE rb_rescue2(type *q, VALUE w, type *e, VALUE r,...)
An equivalent of rescue clause.
VALUE rb_ensure(type *q, VALUE w, type *e, VALUE r)
An equivalent of ensure clause.
#define PRI_OFFT_PREFIX
A rb_sprintf() format prefix to be used for an off_t parameter.
#define OFFT2NUM
Converts a C's off_t into an instance of rb_cInteger.
#define NUM2OFFT
Converts an instance of rb_cNumeric into C's off_t.
#define PIDT2NUM
Converts a C's pid_t into an instance of rb_cInteger.
#define rb_fd_isset
Queries if the given fd is in the rb_fdset_t.
#define rb_fd_select
Waits for multiple file descriptors at once.
#define rb_fd_init
Initialises the :given :rb_fdset_t.
#define rb_fd_set
Sets the given fd to the rb_fdset_t.
#define RARRAY_LEN
Just another name of rb_array_len.
#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.
#define RSTRING_GETMEM(str, ptrvar, lenvar)
Convenient macro to obtain the contents and length at once.
#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.
#define RTEST
This is an old name of RB_TEST.
#define _(args)
This was a transition path from K&R to ANSI.
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 VALUE
Type that represents a Ruby object.
uintptr_t ID
Type that represents a Ruby identifier such as a variable name.