14 #include "ruby/internal/config.h"
24 #if defined(HAVE_POLL)
25 # if defined(__linux__)
28 # if defined(__FreeBSD_version) && __FreeBSD_version >= 1100000
38 #define free(x) xfree(x)
40 #if defined(DOSISH) || defined(__CYGWIN__)
44 #include <sys/types.h>
45 #if defined HAVE_NET_SOCKET_H
46 # include <net/socket.h>
47 #elif defined HAVE_SYS_SOCKET_H
48 # include <sys/socket.h>
51 #if defined(__BOW__) || defined(__CYGWIN__) || defined(_WIN32)
52 # define NO_SAFE_RENAME
55 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__sun) || defined(_nec_ews)
63 #include <sys/types.h>
64 #if defined(HAVE_SYS_IOCTL_H) && !defined(_WIN32)
65 #include <sys/ioctl.h>
67 #if defined(HAVE_FCNTL_H) || defined(_WIN32)
69 #elif defined(HAVE_SYS_FCNTL_H)
70 #include <sys/fcntl.h>
73 #ifdef HAVE_SYS_TIME_H
74 # include <sys/time.h>
79 #if defined(HAVE_SYS_PARAM_H) || defined(__HIUX_MPP__)
80 # include <sys/param.h>
93 #elif defined HAVE_SYS_SYSCALL_H
94 #include <sys/syscall.h>
101 #ifdef HAVE_SYS_WAIT_H
102 # include <sys/wait.h>
105 #ifdef HAVE_COPYFILE_H
106 # include <copyfile.h>
108 # ifndef COPYFILE_STATE_COPIED
114 # undef HAVE_FCOPYFILE
120 #include "ccan/list/list.h"
122 #include "encindex.h"
124 #include "internal.h"
125 #include "internal/class.h"
126 #include "internal/encoding.h"
127 #include "internal/error.h"
128 #include "internal/inits.h"
129 #include "internal/io.h"
130 #include "internal/numeric.h"
131 #include "internal/object.h"
132 #include "internal/process.h"
133 #include "internal/thread.h"
134 #include "internal/transcode.h"
135 #include "internal/variable.h"
138 #include "ruby/missing.h"
141 #include "ruby_atomic.h"
145 # include "vm_core.h"
151 #define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR)
155 # ifdef _POSIX_PIPE_BUF
156 # define PIPE_BUF _POSIX_PIPE_BUF
158 # define PIPE_BUF 512
163 # define EWOULDBLOCK EAGAIN
166 #if defined(HAVE___SYSCALL) && (defined(__APPLE__) || defined(__OpenBSD__))
168 off_t __syscall(quad_t number, ...);
171 #define IO_RBUF_CAPA_MIN 8192
172 #define IO_CBUF_CAPA_MIN (128*1024)
173 #define IO_RBUF_CAPA_FOR(fptr) (NEED_READCONV(fptr) ? IO_CBUF_CAPA_MIN : IO_RBUF_CAPA_MIN)
174 #define IO_WBUF_CAPA_MIN 8192
176 #define IO_MAX_BUFFER_GROWTH 8 * 1024 * 1024
181 #define open rb_w32_uopen
183 #define rename(f, t) rb_w32_urename((f), (t))
184 #include "win32/file.h"
194 static VALUE rb_eEAGAINWaitReadable;
195 static VALUE rb_eEAGAINWaitWritable;
196 static VALUE rb_eEWOULDBLOCKWaitReadable;
197 static VALUE rb_eEWOULDBLOCKWaitWritable;
198 static VALUE rb_eEINPROGRESSWaitWritable;
199 static VALUE rb_eEINPROGRESSWaitReadable;
202 static VALUE orig_stdout, orig_stderr;
211 static ID id_write, id_read, id_getc, id_flush, id_readpartial, id_set_encoding, id_fileno;
212 static VALUE sym_mode, sym_perm, sym_flags, sym_extenc, sym_intenc, sym_encoding, sym_open_args;
213 static VALUE sym_textmode, sym_binmode, sym_autoclose;
214 static VALUE sym_SET, sym_CUR, sym_END;
215 static VALUE sym_wait_readable, sym_wait_writable;
217 static VALUE sym_DATA;
220 static VALUE sym_HOLE;
223 static VALUE prep_io(
int fd,
int fmode,
VALUE klass,
const char *path);
226 rb_io_blocking_region_wait(
struct rb_io *io, rb_blocking_function_t *
function,
void *argument,
enum rb_io_event events)
228 return rb_thread_io_blocking_call(
function, argument, io->
fd, events);
231 VALUE rb_io_blocking_region(
struct rb_io *io, rb_blocking_function_t *
function,
void *argument)
233 return rb_io_blocking_region_wait(io,
function, argument, 0);
237 VALUE filename, current_file;
243 int8_t init_p, next_p, binmode;
254 if (fd < 0 || afd <= max_fd)
257 #if defined(HAVE_FCNTL) && defined(F_GETFL)
258 err = fcntl(fd, F_GETFL) == -1;
262 err = fstat(fd, &buf) != 0;
265 if (err &&
errno == EBADF) {
266 rb_bug(
"rb_update_max_fd: invalid fd (%d) given.", fd);
269 while (max_fd < afd) {
270 max_fd = ATOMIC_CAS(max_file_descriptor, max_fd, afd);
275 rb_maygvl_fd_fix_cloexec(
int fd)
278 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
279 int flags, flags2, ret;
280 flags = fcntl(fd, F_GETFD);
282 rb_bug(
"rb_maygvl_fd_fix_cloexec: fcntl(%d, F_GETFD) failed: %s", fd, strerror(
errno));
285 flags2 = flags & ~FD_CLOEXEC;
287 flags2 = flags | FD_CLOEXEC;
288 if (flags != flags2) {
289 ret = fcntl(fd, F_SETFD, flags2);
291 rb_bug(
"rb_maygvl_fd_fix_cloexec: fcntl(%d, F_SETFD, %d) failed: %s", fd, flags2, strerror(
errno));
300 rb_maygvl_fd_fix_cloexec(fd);
306 rb_fix_detect_o_cloexec(
int fd)
308 #if defined(O_CLOEXEC) && defined(F_GETFD)
309 int flags = fcntl(fd, F_GETFD);
312 rb_bug(
"rb_fix_detect_o_cloexec: fcntl(%d, F_GETFD) failed: %s", fd, strerror(
errno));
314 if (flags & FD_CLOEXEC)
317 rb_maygvl_fd_fix_cloexec(fd);
324 return (e == EWOULDBLOCK) || (e == EAGAIN);
331 static int o_cloexec_state = -1;
333 static const int retry_interval = 0;
334 static const int retry_max_count = 10000;
341 #elif defined O_NOINHERIT
342 flags |= O_NOINHERIT;
345 while ((ret = open(pathname, flags, mode)) == -1) {
347 if (!io_again_p(e))
break;
348 if (retry_count++ >= retry_max_count)
break;
350 sleep(retry_interval);
353 if (ret < 0)
return ret;
354 if (ret <= 2 || o_cloexec_state == 0) {
355 rb_maygvl_fd_fix_cloexec(ret);
357 else if (o_cloexec_state > 0) {
361 o_cloexec_state = rb_fix_detect_o_cloexec(ret);
380 if (oldfd == newfd) {
384 #if defined(HAVE_DUP3) && defined(O_CLOEXEC)
385 static int try_dup3 = 1;
386 if (2 < newfd && try_dup3) {
387 ret = dup3(oldfd, newfd, O_CLOEXEC);
391 if (
errno == ENOSYS) {
393 ret = dup2(oldfd, newfd);
397 ret = dup2(oldfd, newfd);
400 ret = dup2(oldfd, newfd);
402 if (ret < 0)
return ret;
404 rb_maygvl_fd_fix_cloexec(ret);
409 rb_fd_set_nonblock(
int fd)
412 return rb_w32_set_nonblock(fd);
413 #elif defined(F_GETFL)
414 int oflags = fcntl(fd, F_GETFL);
418 if (oflags & O_NONBLOCK)
420 oflags |= O_NONBLOCK;
421 return fcntl(fd, F_SETFL, oflags);
430 int result = pipe2(descriptors, O_CLOEXEC | O_NONBLOCK);
432 int result = pipe(descriptors);
439 if (result == 0 && descriptors[1] == -1) {
440 close(descriptors[0]);
448 rb_maygvl_fd_fix_cloexec(descriptors[0]);
449 rb_maygvl_fd_fix_cloexec(descriptors[1]);
452 rb_fd_set_nonblock(descriptors[0]);
453 rb_fd_set_nonblock(descriptors[1]);
465 #if defined(HAVE_FCNTL) && defined(F_DUPFD_CLOEXEC) && defined(F_DUPFD)
466 static int try_dupfd_cloexec = 1;
467 if (try_dupfd_cloexec) {
468 ret = fcntl(fd, F_DUPFD_CLOEXEC, minfd);
471 rb_maygvl_fd_fix_cloexec(ret);
475 if (
errno == EINVAL) {
476 ret = fcntl(fd, F_DUPFD, minfd);
478 try_dupfd_cloexec = 0;
483 ret = fcntl(fd, F_DUPFD, minfd);
485 #elif defined(HAVE_FCNTL) && defined(F_DUPFD)
486 ret = fcntl(fd, F_DUPFD, minfd);
489 if (ret >= 0 && ret < minfd) {
490 const int prev_fd = ret;
496 if (ret < 0)
return ret;
497 rb_maygvl_fd_fix_cloexec(ret);
501 #define argf_of(obj) (*(struct argf *)DATA_PTR(obj))
502 #define ARGF argf_of(argf)
504 #define GetWriteIO(io) rb_io_get_write_io(io)
506 #define READ_DATA_PENDING(fptr) ((fptr)->rbuf.len)
507 #define READ_DATA_PENDING_COUNT(fptr) ((fptr)->rbuf.len)
508 #define READ_DATA_PENDING_PTR(fptr) ((fptr)->rbuf.ptr+(fptr)->rbuf.off)
509 #define READ_DATA_BUFFERED(fptr) READ_DATA_PENDING(fptr)
511 #define READ_CHAR_PENDING(fptr) ((fptr)->cbuf.len)
512 #define READ_CHAR_PENDING_COUNT(fptr) ((fptr)->cbuf.len)
513 #define READ_CHAR_PENDING_PTR(fptr) ((fptr)->cbuf.ptr+(fptr)->cbuf.off)
516 #define WAIT_FD_IN_WIN32(fptr) \
517 (rb_w32_io_cancelable_p((fptr)->fd) ? Qnil : rb_io_wait(fptr->self, RB_INT2NUM(RUBY_IO_READABLE), RUBY_IO_TIMEOUT_DEFAULT))
519 #define WAIT_FD_IN_WIN32(fptr)
522 #define READ_CHECK(fptr) do {\
523 if (!READ_DATA_PENDING(fptr)) {\
524 WAIT_FD_IN_WIN32(fptr);\
525 rb_io_check_closed(fptr);\
531 # define S_ISSOCK(m) _S_ISSOCK(m)
534 # define S_ISSOCK(m) (((m) & S_IFMT) == _S_IFSOCK)
537 # define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
543 static int io_fflush(
rb_io_t *);
544 static rb_io_t *flush_before_seek(
rb_io_t *fptr,
bool discard_rbuf);
545 static void clear_codeconv(
rb_io_t *fptr);
547 #define FMODE_SIGNAL_ON_EPIPE (1<<17)
549 #define fptr_signal_on_epipe(fptr) \
550 (((fptr)->mode & FMODE_SIGNAL_ON_EPIPE) != 0)
552 #define fptr_set_signal_on_epipe(fptr, flag) \
554 (fptr)->mode |= FMODE_SIGNAL_ON_EPIPE : \
555 (fptr)->mode &= ~FMODE_SIGNAL_ON_EPIPE)
557 extern ID ruby_static_id_signo;
559 NORETURN(
static void rb_sys_fail_on_write(
rb_io_t *fptr));
561 rb_sys_fail_on_write(
rb_io_t *fptr)
564 VALUE errinfo = rb_syserr_new_path(e, (fptr)->pathv);
566 if (fptr_signal_on_epipe(fptr) && (e == EPIPE)) {
578 #define NEED_NEWLINE_DECORATOR_ON_READ(fptr) ((fptr)->mode & FMODE_TEXTMODE)
579 #define NEED_NEWLINE_DECORATOR_ON_WRITE(fptr) ((fptr)->mode & FMODE_TEXTMODE)
580 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
581 # define RUBY_CRLF_ENVIRONMENT 1
583 # define RUBY_CRLF_ENVIRONMENT 0
586 #if RUBY_CRLF_ENVIRONMENT
588 # define DEFAULT_TEXTMODE FMODE_TEXTMODE
589 # define TEXTMODE_NEWLINE_DECORATOR_ON_WRITE ECONV_CRLF_NEWLINE_DECORATOR
597 #define NEED_READCONV(fptr) ((fptr)->encs.enc2 != NULL || (fptr)->encs.ecflags & ~ECONV_CRLF_NEWLINE_DECORATOR)
598 #define WRITECONV_MASK ( \
599 (ECONV_DECORATOR_MASK & ~ECONV_CRLF_NEWLINE_DECORATOR)|\
600 ECONV_STATEFUL_DECORATOR_MASK|\
602 #define NEED_WRITECONV(fptr) ( \
603 ((fptr)->encs.enc != NULL && (fptr)->encs.enc != rb_ascii8bit_encoding()) || \
604 ((fptr)->encs.ecflags & WRITECONV_MASK) || \
606 #define SET_BINARY_MODE(fptr) setmode((fptr)->fd, O_BINARY)
608 #define NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr) do {\
609 if (NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {\
610 if (((fptr)->mode & FMODE_READABLE) &&\
611 !((fptr)->encs.ecflags & ECONV_NEWLINE_DECORATOR_MASK)) {\
612 setmode((fptr)->fd, O_BINARY);\
615 setmode((fptr)->fd, O_TEXT);\
620 #define SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags) do {\
621 if ((enc2) && ((ecflags) & ECONV_DEFAULT_NEWLINE_DECORATOR)) {\
622 (ecflags) |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;\
630 io_unread(
rb_io_t *fptr,
bool discard_rbuf)
646 if (!rb_w32_fd_is_text(fptr->
fd)) {
647 r = lseek(fptr->
fd, -fptr->
rbuf.
len, SEEK_CUR);
648 if (r < 0 &&
errno) {
651 if (!discard_rbuf)
return;
657 pos = lseek(fptr->
fd, 0, SEEK_CUR);
658 if (pos < 0 &&
errno) {
661 if (!discard_rbuf)
goto end;
665 extra_max = (long)(pos - fptr->
rbuf.
len);
673 for (i = 0; i < fptr->
rbuf.
len; i++) {
674 if (*p ==
'\n') newlines++;
675 if (extra_max == newlines)
break;
680 while (newlines >= 0) {
681 r = lseek(fptr->
fd, pos - fptr->
rbuf.
len - newlines, SEEK_SET);
682 if (newlines == 0)
break;
687 read_size = _read(fptr->
fd, buf, fptr->
rbuf.
len + newlines);
691 rb_syserr_fail_path(e, fptr->
pathv);
693 if (read_size == fptr->
rbuf.
len) {
694 lseek(fptr->
fd, r, SEEK_SET);
705 clear_codeconv(fptr);
717 set_binary_mode_with_seek_cur(
rb_io_t *fptr)
719 if (!rb_w32_fd_is_text(fptr->
fd))
return O_BINARY;
722 return setmode(fptr->
fd, O_BINARY);
724 flush_before_seek(fptr,
false);
725 return setmode(fptr->
fd, O_BINARY);
727 #define SET_BINARY_MODE_WITH_SEEK_CUR(fptr) set_binary_mode_with_seek_cur(fptr)
731 # define DEFAULT_TEXTMODE 0
732 #define NEED_READCONV(fptr) ((fptr)->encs.enc2 != NULL || NEED_NEWLINE_DECORATOR_ON_READ(fptr))
733 #define NEED_WRITECONV(fptr) ( \
734 ((fptr)->encs.enc != NULL && (fptr)->encs.enc != rb_ascii8bit_encoding()) || \
735 NEED_NEWLINE_DECORATOR_ON_WRITE(fptr) || \
736 ((fptr)->encs.ecflags & (ECONV_DECORATOR_MASK|ECONV_STATEFUL_DECORATOR_MASK)) || \
738 #define SET_BINARY_MODE(fptr) (void)(fptr)
739 #define NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr) (void)(fptr)
740 #define SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags) ((void)(enc2), (void)(ecflags))
741 #define SET_BINARY_MODE_WITH_SEEK_CUR(fptr) (void)(fptr)
744 #if !defined HAVE_SHUTDOWN && !defined shutdown
745 #define shutdown(a,b) 0
749 #define is_socket(fd, path) rb_w32_is_socket(fd)
750 #elif !defined(S_ISSOCK)
751 #define is_socket(fd, path) 0
754 is_socket(
int fd,
VALUE path)
757 if (fstat(fd, &sbuf) < 0)
758 rb_sys_fail_path(path);
759 return S_ISSOCK(sbuf.st_mode);
763 static const char closed_stream[] =
"closed stream";
766 io_fd_check_closed(
int fd)
799 io_fd_check_closed(fptr->
fd);
803 rb_io_get_fptr(
VALUE io)
813 return rb_convert_type_with_id(io,
T_FILE,
"IO", idTo_io);
819 return rb_check_convert_type_with_id(io,
T_FILE,
"IO", idTo_io);
837 rb_io_t *fptr = rb_io_get_fptr(io);
846 return write_io ? write_io :
Qnil;
859 rb_io_t *fptr = rb_io_get_fptr(
self);
889 if (
RTEST(timeout)) {
893 rb_io_t *fptr = rb_io_get_fptr(
self);
918 #if !RUBY_CRLF_ENVIRONMENT
920 io_unread(
rb_io_t *fptr,
bool discard_rbuf)
928 r = lseek(fptr->
fd, -fptr->
rbuf.
len, SEEK_CUR);
929 if (r < 0 &&
errno) {
932 if (!discard_rbuf)
return;
936 clear_codeconv(fptr);
949 const int min_capa = IO_RBUF_CAPA_FOR(fptr);
952 #if SIZEOF_LONG > SIZEOF_INT
977 flush_before_seek(
rb_io_t *fptr,
bool discard_rbuf)
979 if (io_fflush(fptr) < 0)
980 rb_sys_fail_on_write(fptr);
981 io_unread(fptr, discard_rbuf);
986 #define io_seek(fptr, ofs, whence) (errno = 0, lseek(flush_before_seek(fptr, true)->fd, (ofs), (whence)))
987 #define io_tell(fptr) lseek(flush_before_seek(fptr, false)->fd, 0, SEEK_CUR)
1003 if (io_fflush(fptr) < 0)
1004 rb_sys_fail_on_write(fptr);
1009 if (io_fflush(wfptr) < 0)
1010 rb_sys_fail_on_write(wfptr);
1018 if (READ_CHAR_PENDING(fptr)) {
1030 io_read_encoding(
rb_io_t *fptr)
1039 io_input_encoding(
rb_io_t *fptr)
1044 return io_read_encoding(fptr);
1055 io_unread(fptr,
true);
1060 rb_io_read_pending(
rb_io_t *fptr)
1063 if (READ_CHAR_PENDING(fptr))
1065 return READ_DATA_PENDING(fptr);
1071 if (!READ_DATA_PENDING(fptr)) {
1078 rb_gc_for_fd(
int err)
1080 if (err == EMFILE || err == ENFILE || err == ENOMEM) {
1090 #define TRY_WITH_GC(expr) \
1091 for (int first_errno, retried_errno = 0, retried = 0; \
1094 (!rb_gc_for_fd(first_errno = errno) || !(expr)) && \
1095 (retried_errno = errno, 1)); \
1096 (void)retried_errno, retried = 1)
1111 io_alloc(
VALUE klass)
1121 # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
1147 struct io_internal_writev_struct {
1154 const struct iovec *iov;
1159 static int nogvl_wait_for(
VALUE th,
rb_io_t *fptr,
short events,
struct timeval *timeout);
1167 io_internal_wait(
VALUE thread,
rb_io_t *fptr,
int error,
int events,
struct timeval *timeout)
1169 if (!timeout && rb_thread_mn_schedulable(thread)) {
1174 int ready = nogvl_wait_for(thread, fptr, events, timeout);
1179 else if (ready == 0) {
1189 internal_read_func(
void *
ptr)
1194 if (iis->timeout && !iis->nonblock) {
1195 if (io_internal_wait(iis->th, iis->fptr, 0, RB_WAITFD_IN, iis->timeout) == -1) {
1201 result = read(iis->fd, iis->buf, iis->capa);
1203 if (result < 0 && !iis->nonblock) {
1204 if (io_again_p(
errno)) {
1205 if (io_internal_wait(iis->th, iis->fptr,
errno, RB_WAITFD_IN, iis->timeout) == -1) {
1217 #if defined __APPLE__
1218 # define do_write_retry(code) do {result = code;} while (result == -1 && errno == EPROTOTYPE)
1220 # define do_write_retry(code) result = code
1224 internal_write_func(
void *
ptr)
1229 if (iis->timeout && !iis->nonblock) {
1230 if (io_internal_wait(iis->th, iis->fptr, 0, RB_WAITFD_OUT, iis->timeout) == -1) {
1236 do_write_retry(write(iis->fd, iis->buf, iis->capa));
1238 if (result < 0 && !iis->nonblock) {
1240 if (io_again_p(e)) {
1241 if (io_internal_wait(iis->th, iis->fptr,
errno, RB_WAITFD_OUT, iis->timeout) == -1) {
1255 internal_writev_func(
void *
ptr)
1257 struct io_internal_writev_struct *iis =
ptr;
1260 if (iis->timeout && !iis->nonblock) {
1261 if (io_internal_wait(iis->th, iis->fptr, 0, RB_WAITFD_OUT, iis->timeout) == -1) {
1267 do_write_retry(writev(iis->fd, iis->iov, iis->iovcnt));
1269 if (result < 0 && !iis->nonblock) {
1270 if (io_again_p(
errno)) {
1271 if (io_internal_wait(iis->th, iis->fptr,
errno, RB_WAITFD_OUT, iis->timeout) == -1) {
1285 rb_io_read_memory(
rb_io_t *fptr,
void *buf,
size_t count)
1288 if (scheduler !=
Qnil) {
1291 if (!UNDEF_P(result)) {
1307 struct timeval timeout_storage;
1311 iis.timeout = &timeout_storage;
1314 return (ssize_t)rb_io_blocking_region_wait(fptr, internal_read_func, &iis,
RUBY_IO_READABLE);
1318 rb_io_write_memory(
rb_io_t *fptr,
const void *buf,
size_t count)
1321 if (scheduler !=
Qnil) {
1324 if (!UNDEF_P(result)) {
1340 struct timeval timeout_storage;
1344 iis.timeout = &timeout_storage;
1347 return (ssize_t)rb_io_blocking_region_wait(fptr, internal_write_func, &iis,
RUBY_IO_WRITABLE);
1352 rb_writev_internal(
rb_io_t *fptr,
const struct iovec *iov,
int iovcnt)
1354 if (!iovcnt)
return 0;
1357 if (scheduler !=
Qnil) {
1361 if (!UNDEF_P(result)) {
1366 struct io_internal_writev_struct iis = {
1377 struct timeval timeout_storage;
1381 iis.timeout = &timeout_storage;
1384 return (ssize_t)rb_io_blocking_region_wait(fptr, internal_writev_func, &iis,
RUBY_IO_WRITABLE);
1389 io_flush_buffer_sync(
void *arg)
1411 io_flush_buffer_async(
VALUE arg)
1414 return rb_io_blocking_region_wait(fptr, io_flush_buffer_sync, fptr,
RUBY_IO_WRITABLE);
1418 io_flush_buffer(
rb_io_t *fptr)
1421 return (
int)io_flush_buffer_async((
VALUE)fptr);
1436 while (fptr->
wbuf.
len > 0 && io_flush_buffer(fptr) != 0) {
1451 if (scheduler !=
Qnil) {
1461 if (NIL_OR_UNDEF_P(timeout)) {
1465 if (timeout !=
Qnil) {
1470 int ready = rb_thread_wait_for_single_fd(fptr->
fd,
RB_NUM2INT(events), tv);
1494 io_wait_for_single_fd(
int fd,
int events,
struct timeval *timeout)
1498 if (scheduler !=
Qnil) {
1504 return rb_thread_wait_for_single_fd(fd, events, timeout);
1510 io_fd_check_closed(f);
1516 #if defined(ERESTART)
1523 #if EWOULDBLOCK != EAGAIN
1526 if (scheduler !=
Qnil) {
1544 io_fd_check_closed(f);
1550 #if defined(ERESTART)
1566 #if EWOULDBLOCK != EAGAIN
1569 if (scheduler !=
Qnil) {
1587 return io_wait_for_single_fd(fd, events, timeout);
1621 #if defined(ERESTART)
1631 #if EWOULDBLOCK != EAGAIN
1648 if (
RTEST(result)) {
1663 if (
RTEST(result)) {
1677 const char *senc, *denc;
1743 io_binwrite_string_internal(
rb_io_t *fptr,
const char *
ptr,
long length)
1746 struct iovec iov[2];
1749 iov[0].iov_len = fptr->
wbuf.
len;
1750 iov[1].iov_base = (
void*)
ptr;
1751 iov[1].iov_len = length;
1753 ssize_t result = rb_writev_internal(fptr, iov, 2);
1758 if (result >= fptr->
wbuf.
len) {
1766 fptr->
wbuf.
off += (int)result;
1767 fptr->
wbuf.
len -= (int)result;
1775 return rb_io_write_memory(fptr,
ptr, length);
1780 io_binwrite_string_internal(
rb_io_t *fptr,
const char *
ptr,
long length)
1782 long remaining = length;
1785 if (fptr->
wbuf.
len+length <= fptr->wbuf.capa) {
1792 fptr->
wbuf.
len += (int)length;
1799 if (io_fflush(fptr) < 0) {
1804 if (remaining == 0) {
1810 return rb_io_write_memory(fptr,
ptr, length);
1815 io_binwrite_string(
VALUE arg)
1819 const char *
ptr = p->ptr;
1820 size_t remaining = p->length;
1824 ssize_t result = io_binwrite_string_internal(p->fptr,
ptr, remaining);
1830 else if (result > 0) {
1831 if ((
size_t)result == remaining)
break;
1833 remaining -= result;
1849 io_allocate_write_buffer(
rb_io_t *fptr,
int sync)
1854 fptr->
wbuf.
capa = IO_WBUF_CAPA_MIN;
1865 io_binwrite_requires_flush_write(
rb_io_t *fptr,
long len,
int nosync)
1880 io_binwrite(
const char *
ptr,
long len,
rb_io_t *fptr,
int nosync)
1882 if (
len <= 0)
return len;
1887 io_allocate_write_buffer(fptr, !nosync);
1889 if (io_binwrite_requires_flush_write(fptr,
len, nosync)) {
1900 return io_binwrite_string((
VALUE)&arg);
1917 # define MODE_BTMODE(a,b,c) ((fmode & FMODE_BINMODE) ? (b) : \
1918 (fmode & FMODE_TEXTMODE) ? (c) : (a))
1920 #define MODE_BTXMODE(a, b, c, d, e, f) ((fmode & FMODE_EXCL) ? \
1921 MODE_BTMODE(d, e, f) : \
1922 MODE_BTMODE(a, b, c))
1927 if (NEED_WRITECONV(fptr)) {
1929 SET_BINARY_MODE(fptr);
1931 make_writeconv(fptr);
1934 #define fmode (fptr->mode)
1938 rb_raise(
rb_eArgError,
"ASCII incompatible string written for text mode IO without encoding conversion: %s",
1950 if (!
NIL_P(common_encoding)) {
1961 #if RUBY_CRLF_ENVIRONMENT
1962 #define fmode (fptr->mode)
1963 else if (MODE_BTMODE(DEFAULT_TEXTMODE,0,1)) {
1966 setmode(fptr->
fd, O_BINARY);
1969 setmode(fptr->
fd, O_TEXT);
1972 rb_raise(
rb_eArgError,
"ASCII incompatible string written for text mode IO without encoding conversion: %s",
1991 long len = rb_w32_write_console(str, fptr->
fd);
1996 str = do_writeconv(str, fptr, &converted);
2000 tmp = rb_str_tmp_frozen_no_embed_acquire(str);
2002 n = io_binwrite(
ptr,
len, fptr, nosync);
2003 rb_str_tmp_frozen_release(str, tmp);
2015 return (ssize_t)io_binwrite(buf, (
long)size, fptr, 0);
2025 io = GetWriteIO(io);
2040 n = io_fwrite(str, fptr, nosync);
2041 if (n < 0L) rb_sys_fail_on_write(fptr);
2047 struct binwritev_arg {
2055 io_binwritev_internal(
VALUE arg)
2057 struct binwritev_arg *p = (
struct binwritev_arg *)arg;
2059 size_t remaining = p->total;
2063 struct iovec *iov = p->iov;
2064 int iovcnt = p->iovcnt;
2067 long result = rb_writev_internal(fptr, iov, iovcnt);
2072 if (offset < (
size_t)fptr->
wbuf.
len) {
2077 offset -= (size_t)fptr->
wbuf.
len;
2083 if (offset == p->total) {
2087 while (result >= (ssize_t)iov->iov_len) {
2089 result -= iov->iov_len;
2099 iov->iov_base = (
char *)iov->iov_base + result;
2100 iov->iov_len -= result;
2114 io_binwritev(
struct iovec *iov,
int iovcnt,
rb_io_t *fptr)
2119 if (iovcnt == 0)
return 0;
2122 for (
int i = 1; i < iovcnt; i++) total += iov[i].iov_len;
2124 io_allocate_write_buffer(fptr, 1);
2130 if (offset + total <= (
size_t)fptr->
wbuf.
capa) {
2131 for (
int i = 1; i < iovcnt; i++) {
2132 memcpy(fptr->
wbuf.
ptr+offset, iov[i].iov_base, iov[i].iov_len);
2133 offset += iov[i].iov_len;
2142 iov[0].iov_len = fptr->
wbuf.
len;
2155 struct binwritev_arg arg;
2158 arg.iovcnt = iovcnt;
2165 return io_binwritev_internal((
VALUE)&arg);
2172 int i, converted, iovcnt = argc + 1;
2174 VALUE v1, v2, str, tmp, *tmp_array;
2180 for (i = 0; i < argc; i++) {
2183 str = do_writeconv(str, fptr, &converted);
2188 tmp = rb_str_tmp_frozen_acquire(str);
2196 n = io_binwritev(iov, iovcnt, fptr);
2199 for (i = 0; i < argc; i++) {
2200 rb_str_tmp_frozen_release(argv[i], tmp_array[i]);
2209 iovcnt_ok(
int iovcnt)
2212 return iovcnt < IOV_MAX;
2220 io_writev(
int argc,
const VALUE *argv,
VALUE io)
2227 io = GetWriteIO(io);
2240 for (i = 0; i < argc; i += cnt) {
2243 n = io_fwritev(cnt, &argv[i], fptr);
2254 rb_sys_fail_on_write(fptr);
2256 total = rb_fix_plus(
LONG2FIX(n), total);
2287 return io_writev(argc, argv, io);
2290 VALUE str = argv[0];
2291 return io_write(io, str, 0);
2302 rb_io_writev(
VALUE io,
int argc,
const VALUE *argv)
2307 char sep = RCLASS_SINGLETON_P(klass) ? (klass = io,
'.') :
'#';
2310 " which accepts just one argument",
2352 nogvl_fsync(
void *
ptr)
2357 if (GetFileType((HANDLE)rb_w32_get_osfhandle(fptr->
fd)) != FILE_TYPE_DISK)
2360 return (
VALUE)fsync(fptr->
fd);
2365 rb_io_flush_raw(
VALUE io,
int sync)
2373 io = GetWriteIO(io);
2377 if (io_fflush(fptr) < 0)
2378 rb_sys_fail_on_write(fptr);
2381 io_unread(fptr,
true);
2402 return rb_io_flush_raw(io, 1);
2422 rb_io_tell(
VALUE io)
2428 pos = io_tell(fptr);
2429 if (pos < 0 &&
errno) rb_sys_fail_path(fptr->
pathv);
2435 rb_io_seek(
VALUE io,
VALUE offset,
int whence)
2442 pos = io_seek(fptr, pos, whence);
2443 if (pos < 0 &&
errno) rb_sys_fail_path(fptr->
pathv);
2449 interpret_seek_whence(
VALUE vwhence)
2451 if (vwhence == sym_SET)
2453 if (vwhence == sym_CUR)
2455 if (vwhence == sym_END)
2458 if (vwhence == sym_DATA)
2462 if (vwhence == sym_HOLE)
2516 rb_io_seek_m(
int argc,
VALUE *argv,
VALUE io)
2518 VALUE offset, ptrname;
2519 int whence = SEEK_SET;
2521 if (
rb_scan_args(argc, argv,
"11", &offset, &ptrname) == 2) {
2522 whence = interpret_seek_whence(ptrname);
2525 return rb_io_seek(io, offset, whence);
2553 pos = io_seek(fptr, pos, SEEK_SET);
2554 if (pos < 0 &&
errno) rb_sys_fail_path(fptr->
pathv);
2559 static void clear_readconv(
rb_io_t *fptr);
2586 rb_io_rewind(
VALUE io)
2591 if (io_seek(fptr, 0L, 0) < 0 &&
errno) rb_sys_fail_path(fptr->
pathv);
2592 if (io == ARGF.current_file) {
2593 ARGF.lineno -= fptr->
lineno;
2597 clear_readconv(fptr);
2604 fptr_wait_readable(
rb_io_t *fptr)
2622 fptr->
rbuf.
capa = IO_RBUF_CAPA_FOR(fptr);
2633 if (fptr_wait_readable(fptr))
2642 rb_syserr_fail_path(e, path);
2696 if (READ_CHAR_PENDING(fptr))
return Qfalse;
2697 if (READ_DATA_PENDING(fptr))
return Qfalse;
2699 #if RUBY_CRLF_ENVIRONMENT
2700 if (!NEED_READCONV(fptr) && NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {
2701 return RBOOL(eof(fptr->
fd));
2704 return RBOOL(io_fillbuf(fptr) < 0);
2724 rb_io_sync(
VALUE io)
2728 io = GetWriteIO(io);
2765 io = GetWriteIO(io);
2795 rb_io_fsync(
VALUE io)
2799 io = GetWriteIO(io);
2802 if (io_fflush(fptr) < 0)
2803 rb_sys_fail_on_write(fptr);
2805 if ((
int)rb_io_blocking_region(fptr, nogvl_fsync, fptr))
2806 rb_sys_fail_path(fptr->
pathv);
2811 # define rb_io_fsync rb_f_notimplement
2812 # define rb_io_sync rb_f_notimplement
2821 #ifdef HAVE_FDATASYNC
2823 nogvl_fdatasync(
void *
ptr)
2828 if (GetFileType((HANDLE)rb_w32_get_osfhandle(fptr->
fd)) != FILE_TYPE_DISK)
2831 return (
VALUE)fdatasync(fptr->
fd);
2846 rb_io_fdatasync(
VALUE io)
2850 io = GetWriteIO(io);
2853 if (io_fflush(fptr) < 0)
2854 rb_sys_fail_on_write(fptr);
2856 if ((
int)rb_io_blocking_region(fptr, nogvl_fdatasync, fptr) == 0)
2860 return rb_io_fsync(io);
2863 #define rb_io_fdatasync rb_io_fsync
2881 rb_io_fileno(
VALUE io)
2901 if (!UNDEF_P(fileno)) {
2989 rb_io_inspect(
VALUE obj)
2993 static const char closed[] =
" (closed)";
2995 fptr =
RFILE(obj)->fptr;
3002 rb_str_cat(result, closed+1, strlen(closed)-1);
3026 rb_io_to_io(
VALUE io)
3037 n = READ_DATA_PENDING_COUNT(fptr);
3038 if (n <= 0)
return 0;
3039 if (n >
len) n = (int)
len;
3053 if (READ_DATA_PENDING(fptr) == 0) {
3057 c = rb_io_read_memory(fptr,
ptr+offset, n);
3060 if (fptr_wait_readable(fptr))
3065 if ((n -= c) <= 0)
break;
3071 c = read_buffered_data(
ptr+offset, n, fptr);
3074 if ((n -= c) <= 0)
break;
3077 if (io_fillbuf(fptr) < 0) {
3084 static int io_setstrbuf(
VALUE *str,
long len);
3093 bufread_call(
VALUE arg)
3096 p->len = io_bufread(p->str_ptr, p->len, p->fptr);
3101 io_fread(
VALUE str,
long offset,
long size,
rb_io_t *fptr)
3106 io_setstrbuf(&str, offset + size);
3110 rb_str_locktmp_ensure(str, bufread_call, (
VALUE)&arg);
3112 if (
len < 0) rb_sys_fail_path(fptr->
pathv);
3120 rb_off_t siz = READ_DATA_PENDING_COUNT(fptr);
3123 if (fstat(fptr->
fd, &st) == 0 && S_ISREG(st.st_mode)
3124 #
if defined(__HAIKU__)
3129 if (io_fflush(fptr) < 0)
3130 rb_sys_fail_on_write(fptr);
3131 pos = lseek(fptr->
fd, 0, SEEK_CUR);
3132 if (st.st_size >= pos && pos >= 0) {
3133 siz += st.st_size - pos;
3134 if (siz > LONG_MAX) {
3155 make_readconv(
rb_io_t *fptr,
int size)
3160 const char *sname, *dname;
3175 if (size < IO_CBUF_CAPA_MIN) size = IO_CBUF_CAPA_MIN;
3181 #define MORE_CHAR_SUSPENDED Qtrue
3182 #define MORE_CHAR_FINISHED Qnil
3184 fill_cbuf(
rb_io_t *fptr,
int ec_flags)
3186 const unsigned char *ss, *sp, *se;
3187 unsigned char *ds, *dp, *de;
3196 return MORE_CHAR_SUSPENDED;
3207 ss = sp = (
const unsigned char *)fptr->
rbuf.
ptr + fptr->
rbuf.
off;
3212 fptr->
rbuf.
off += (int)(sp - ss);
3213 fptr->
rbuf.
len -= (int)(sp - ss);
3214 fptr->
cbuf.
len += (int)(dp - ds);
3219 fptr->
rbuf.
off -= putbackable;
3220 fptr->
rbuf.
len += putbackable;
3227 if (cbuf_len0 != fptr->
cbuf.
len)
3228 return MORE_CHAR_SUSPENDED;
3231 return MORE_CHAR_FINISHED;
3237 if (io_fillbuf(fptr) < 0) {
3239 return MORE_CHAR_FINISHED;
3244 fptr->
cbuf.
len += (int)(dp - ds);
3251 if (cbuf_len0 != fptr->
cbuf.
len)
3252 return MORE_CHAR_SUSPENDED;
3254 return MORE_CHAR_FINISHED;
3262 if (v != MORE_CHAR_SUSPENDED && v != MORE_CHAR_FINISHED)
3320 #define MAX_REALLOC_GAP 4096
3322 io_shrink_read_string(
VALUE str,
long n)
3330 io_set_read_length(
VALUE str,
long n,
int shrinkable)
3335 if (shrinkable) io_shrink_read_string(str, n);
3349 if (NEED_READCONV(fptr)) {
3350 int first = !
NIL_P(str);
3351 SET_BINARY_MODE(fptr);
3352 shrinkable = io_setstrbuf(&str,0);
3353 make_readconv(fptr, 0);
3358 io_shift_cbuf(fptr, fptr->
cbuf.
len, &str);
3360 v = fill_cbuf(fptr, 0);
3361 if (v != MORE_CHAR_SUSPENDED && v != MORE_CHAR_FINISHED) {
3364 io_shift_cbuf(fptr, fptr->
cbuf.
len, &str);
3368 if (v == MORE_CHAR_FINISHED) {
3369 clear_readconv(fptr);
3371 if (shrinkable) io_shrink_read_string(str,
RSTRING_LEN(str));
3372 return io_enc_str(str, fptr);
3377 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
3381 enc = io_read_encoding(fptr);
3384 if (siz == 0) siz = BUFSIZ;
3385 shrinkable = io_setstrbuf(&str, siz);
3388 n = io_fread(str, bytes, siz - bytes, fptr);
3389 if (n == 0 && bytes == 0) {
3397 if (bytes < siz)
break;
3402 if (
capa < BUFSIZ) {
3405 else if (
capa > IO_MAX_BUFFER_GROWTH) {
3406 capa = IO_MAX_BUFFER_GROWTH;
3411 if (shrinkable) io_shrink_read_string(str,
RSTRING_LEN(str));
3412 str = io_enc_str(str, fptr);
3420 if (rb_fd_set_nonblock(fptr->
fd) != 0) {
3421 rb_sys_fail_path(fptr->
pathv);
3426 io_read_memory_call(
VALUE arg)
3431 if (scheduler !=
Qnil) {
3434 if (!UNDEF_P(result)) {
3440 if (iis->nonblock) {
3441 return rb_io_blocking_region(iis->fptr, internal_read_func, iis);
3444 return rb_io_blocking_region_wait(iis->fptr, internal_read_func, iis,
RUBY_IO_READABLE);
3451 return (
long)rb_str_locktmp_ensure(str, io_read_memory_call, (
VALUE)iis);
3454 #define no_exception_p(opts) !rb_opts_exception_p((opts), TRUE)
3457 io_getpartial(
int argc,
VALUE *argv,
VALUE io,
int no_exception,
int nonblock)
3471 shrinkable = io_setstrbuf(&str,
len);
3477 io_set_read_length(str, 0, shrinkable);
3489 io_setstrbuf(&str,
len);
3492 iis.nonblock = nonblock;
3497 n = io_read_memory_locktmp(str, &iis);
3500 if (!nonblock && fptr_wait_readable(fptr))
3502 if (nonblock && (io_again_p(e))) {
3504 return sym_wait_readable;
3507 e,
"read would block");
3509 rb_syserr_fail_path(e, fptr->
pathv);
3512 io_set_read_length(str, n, shrinkable);
3613 io_readpartial(
int argc,
VALUE *argv,
VALUE io)
3617 ret = io_getpartial(argc, argv, io,
Qnil, 0);
3624 io_nonblock_eof(
int no_exception)
3626 if (!no_exception) {
3645 shrinkable = io_setstrbuf(&str,
len);
3646 rb_bool_expected(ex,
"exception", TRUE);
3652 io_set_read_length(str, 0, shrinkable);
3658 rb_fd_set_nonblock(fptr->
fd);
3659 shrinkable |= io_setstrbuf(&str,
len);
3666 n = io_read_memory_locktmp(str, &iis);
3669 if (io_again_p(e)) {
3670 if (!ex)
return sym_wait_readable;
3672 e,
"read would block");
3674 rb_syserr_fail_path(e, fptr->
pathv);
3677 io_set_read_length(str, n, shrinkable);
3680 if (!ex)
return Qnil;
3696 rb_bool_expected(ex,
"exception", TRUE);
3698 io = GetWriteIO(io);
3702 if (io_fflush(fptr) < 0)
3703 rb_sys_fail_on_write(fptr);
3705 rb_fd_set_nonblock(fptr->
fd);
3711 if (io_again_p(e)) {
3713 return sym_wait_writable;
3719 rb_syserr_fail_path(e, fptr->
pathv);
3803 #if RUBY_CRLF_ENVIRONMENT
3809 if (
NIL_P(length)) {
3812 return read_all(fptr, remain_size(fptr), str);
3819 shrinkable = io_setstrbuf(&str,
len);
3824 io_set_read_length(str, 0, shrinkable);
3829 #if RUBY_CRLF_ENVIRONMENT
3830 previous_mode = set_binary_mode_with_seek_cur(fptr);
3832 n = io_fread(str, 0,
len, fptr);
3833 io_set_read_length(str, n, shrinkable);
3834 #if RUBY_CRLF_ENVIRONMENT
3835 if (previous_mode == O_TEXT) {
3836 setmode(fptr->
fd, O_TEXT);
3839 if (n == 0)
return Qnil;
3845 rscheck(
const char *rsptr,
long rslen,
VALUE rs)
3853 appendline(
rb_io_t *fptr,
int delim,
VALUE *strp,
long *lp)
3858 if (NEED_READCONV(fptr)) {
3859 SET_BINARY_MODE(fptr);
3860 make_readconv(fptr, 0);
3863 int searchlen = READ_CHAR_PENDING_COUNT(fptr);
3865 p = READ_CHAR_PENDING_PTR(fptr);
3866 if (0 < limit && limit < searchlen)
3867 searchlen = (int)limit;
3868 e = memchr(p, delim, searchlen);
3870 int len = (int)(e-p+1);
3895 }
while (more_char(fptr) != MORE_CHAR_FINISHED);
3896 clear_readconv(fptr);
3901 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
3903 long pending = READ_DATA_PENDING_COUNT(fptr);
3905 const char *p = READ_DATA_PENDING_PTR(fptr);
3909 if (limit > 0 && pending > limit) pending = limit;
3910 e = memchr(p, delim, pending);
3911 if (e) pending = e - p + 1;
3921 read_buffered_data(
RSTRING_PTR(str) + last, pending, fptr);
3924 if (e)
return delim;
3929 }
while (io_fillbuf(fptr) >= 0);
3935 swallow(
rb_io_t *fptr,
int term)
3937 if (NEED_READCONV(fptr)) {
3940 SET_BINARY_MODE(fptr);
3941 make_readconv(fptr, 0);
3944 while ((cnt = READ_CHAR_PENDING_COUNT(fptr)) > 0) {
3945 const char *p = READ_CHAR_PENDING_PTR(fptr);
3948 if (*p != term)
return TRUE;
3950 while (--i && *++p == term);
3953 const char *e = p + cnt;
3955 while ((p += i) < e &&
rb_enc_ascget(p, e, &i, enc) == term);
3958 io_shift_cbuf(fptr, (
int)cnt - i, NULL);
3960 }
while (more_char(fptr) != MORE_CHAR_FINISHED);
3964 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
3967 while ((cnt = READ_DATA_PENDING_COUNT(fptr)) > 0) {
3969 const char *p = READ_DATA_PENDING_PTR(fptr);
3971 if (cnt >
sizeof buf) cnt =
sizeof buf;
3972 if (*p != term)
return TRUE;
3974 while (--i && *++p == term);
3975 if (!read_buffered_data(buf, cnt - i, fptr))
3976 rb_sys_fail_path(fptr->
pathv);
3979 }
while (io_fillbuf(fptr) == 0);
3992 int pending = READ_DATA_PENDING_COUNT(fptr);
3995 const char *p = READ_DATA_PENDING_PTR(fptr);
3999 e = memchr(p,
'\n', pending);
4001 pending = (int)(e - p + 1);
4003 chomplen = (pending > 1 && *(e-1) ==
'\r') + 1;
4013 read_buffered_data(
RSTRING_PTR(str)+
len, pending - chomplen, fptr);
4016 if (pending == 1 && chomplen == 1 &&
len > 0) {
4023 len += pending - chomplen;
4029 }
while (io_fillbuf(fptr) >= 0);
4032 str = io_enc_str(str, fptr);
4043 unsigned int chomp: 1;
4057 chomp = (!UNDEF_P(vchomp)) &&
RTEST(vchomp);
4059 args->chomp = chomp;
4077 else if (2 <= argc) {
4078 rs = argv[0], lim = argv[1];
4087 check_getline_args(
VALUE *rsp,
long *limit,
VALUE io)
4097 enc_io = io_read_encoding(fptr);
4098 if (enc_io != enc_rs &&
4099 (!is_ascii_string(rs) ||
4119 argc =
rb_scan_args(argc, argv,
"02:", NULL, NULL, &opts);
4120 extract_getline_args(argc, argv, args);
4121 extract_getline_opts(opts, args);
4122 check_getline_args(&args->rs, &args->limit, io);
4126 rb_io_getline_0(
VALUE rs,
long limit,
int chomp,
rb_io_t *fptr)
4133 if (
NIL_P(rs) && limit < 0) {
4134 str = read_all(fptr, 0,
Qnil);
4137 else if (limit == 0) {
4140 else if (rs ==
rb_default_rs && limit < 0 && !NEED_READCONV(fptr) &&
4142 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
4143 return rb_io_getline_fast(fptr, enc, chomp);
4146 int c, newline = -1;
4147 const char *rsptr = 0;
4150 int extra_limit = 16;
4151 int chomp_cr = chomp;
4153 SET_BINARY_MODE(fptr);
4154 enc = io_read_encoding(fptr);
4162 swallow(fptr,
'\n');
4175 newline = (
unsigned char)rsptr[rslen - 1];
4176 chomp_cr = chomp && rslen == 1 && newline ==
'\n';
4180 while ((c = appendline(fptr, newline, &str, &limit)) != EOF) {
4181 const char *s, *p, *pp, *e;
4188 if (!at_char_boundary(s, p, e, enc))
continue;
4189 if (!rspara) rscheck(rsptr, rslen, rs);
4190 if (memcmp(p, rsptr, rslen) == 0) {
4192 if (chomp_cr && p > s && *(p-1) ==
'\r') --p;
4216 if (rspara && c != EOF)
4217 swallow(fptr,
'\n');
4219 str = io_enc_str(str, fptr);
4222 if (!
NIL_P(str) && !nolimit) {
4230 rb_io_getline_1(
VALUE rs,
long limit,
int chomp,
VALUE io)
4233 int old_lineno, new_lineno;
4237 old_lineno = fptr->
lineno;
4238 str = rb_io_getline_0(rs, limit, chomp, fptr);
4239 if (!
NIL_P(str) && (new_lineno = fptr->
lineno) != old_lineno) {
4240 if (io == ARGF.current_file) {
4241 ARGF.lineno += new_lineno - old_lineno;
4242 ARGF.last_lineno = ARGF.lineno;
4245 ARGF.last_lineno = new_lineno;
4253 rb_io_getline(
int argc,
VALUE *argv,
VALUE io)
4257 prepare_getline_args(argc, argv, &args, io);
4258 return rb_io_getline_1(args.rs, args.limit, args.chomp, io);
4268 rb_io_gets_internal(
VALUE io)
4348 rb_io_gets_m(
int argc,
VALUE *argv,
VALUE io)
4352 str = rb_io_getline(argc, argv, io);
4368 rb_io_lineno(
VALUE io)
4423 check_getline_args(&sep, &limit, io);
4425 VALUE line = rb_io_getline_1(sep, limit,
RTEST(chomp), io);
4426 rb_lastline_set_up(line, 1);
4501 rb_io_readlines(
int argc,
VALUE *argv,
VALUE io)
4505 prepare_getline_args(argc, argv, &args, io);
4506 return io_readlines(&args, io);
4514 if (arg->limit == 0)
4517 while (!
NIL_P(line = rb_io_getline_1(arg->rs, arg->limit, arg->chomp, io))) {
4630 rb_io_each_line(
int argc,
VALUE *argv,
VALUE io)
4636 prepare_getline_args(argc, argv, &args, io);
4637 if (args.limit == 0)
4639 while (!
NIL_P(str = rb_io_getline_1(args.rs, args.limit, args.chomp, io))) {
4666 rb_io_each_byte(
VALUE io)
4682 }
while (io_fillbuf(fptr) >= 0);
4692 if (NEED_READCONV(fptr)) {
4696 SET_BINARY_MODE(fptr);
4697 make_readconv(fptr, 0);
4711 if (more_char(fptr) == MORE_CHAR_FINISHED) {
4713 clear_readconv(fptr);
4720 if (fptr->
cbuf.
len == 0) clear_readconv(fptr);
4729 io_shift_cbuf(fptr, r, &str);
4740 str = io_enc_str(str, fptr);
4745 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
4746 if (io_fillbuf(fptr) < 0) {
4768 if (io_fillbuf(fptr) != -1) {
4788 str = io_enc_str(str, fptr);
4814 rb_io_each_char(
VALUE io)
4824 enc = io_input_encoding(fptr);
4826 while (!
NIL_P(c = io_getc(fptr, enc))) {
4852 rb_io_each_codepoint(
VALUE io)
4864 if (NEED_READCONV(fptr)) {
4865 SET_BINARY_MODE(fptr);
4868 make_readconv(fptr, 0);
4876 r = ONIGENC_CONSTRUCT_MBCLEN_CHARFOUND(1);
4883 if (more_char(fptr) == MORE_CHAR_FINISHED) {
4884 clear_readconv(fptr);
4911 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
4912 enc = io_input_encoding(fptr);
4913 while (io_fillbuf(fptr) >= 0) {
4928 char cbuf[8], *p = cbuf;
4930 if (more > numberof(cbuf))
goto invalid;
4932 if (more > numberof(cbuf))
goto invalid;
4933 while ((n = (
int)read_buffered_data(p, more, fptr)) > 0 &&
4934 (p += n, (more -= n) > 0)) {
4935 if (io_fillbuf(fptr) < 0)
goto invalid;
4936 if ((n = fptr->
rbuf.
len) > more) n = more;
4975 rb_io_getc(
VALUE io)
4983 enc = io_input_encoding(fptr);
4985 return io_getc(fptr, enc);
5008 rb_io_readchar(
VALUE io)
5010 VALUE c = rb_io_getc(io);
5053 if (io_fillbuf(fptr) < 0) {
5082 rb_io_readbyte(
VALUE io)
5143 unsigned char c =
NUM2INT(v) & 0xFF;
5149 io_ungetbyte(b, fptr);
5205 else if (RB_BIGNUM_TYPE_P(c)) {
5211 if (NEED_READCONV(fptr)) {
5212 SET_BINARY_MODE(fptr);
5214 #if SIZEOF_LONG > SIZEOF_INT
5218 make_readconv(fptr, (
int)
len);
5232 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
5233 io_ungetbyte(c, fptr);
5253 rb_io_isatty(
VALUE io)
5258 return RBOOL(isatty(fptr->
fd) != 0);
5261 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
5277 rb_io_close_on_exec_p(
VALUE io)
5283 write_io = GetWriteIO(io);
5284 if (io != write_io) {
5286 if (fptr && 0 <= (fd = fptr->
fd)) {
5287 if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->
pathv);
5288 if (!(ret & FD_CLOEXEC))
return Qfalse;
5293 if (fptr && 0 <= (fd = fptr->
fd)) {
5294 if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->
pathv);
5295 if (!(ret & FD_CLOEXEC))
return Qfalse;
5300 #define rb_io_close_on_exec_p rb_f_notimplement
5303 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
5327 int flag =
RTEST(arg) ? FD_CLOEXEC : 0;
5332 write_io = GetWriteIO(io);
5333 if (io != write_io) {
5335 if (fptr && 0 <= (fd = fptr->
fd)) {
5336 if ((ret = fcntl(fptr->
fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->
pathv);
5337 if ((ret & FD_CLOEXEC) != flag) {
5338 ret = (ret & ~FD_CLOEXEC) | flag;
5339 ret = fcntl(fd, F_SETFD, ret);
5340 if (ret != 0) rb_sys_fail_path(fptr->
pathv);
5347 if (fptr && 0 <= (fd = fptr->
fd)) {
5348 if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->
pathv);
5349 if ((ret & FD_CLOEXEC) != flag) {
5350 ret = (ret & ~FD_CLOEXEC) | flag;
5351 ret = fcntl(fd, F_SETFD, ret);
5352 if (ret != 0) rb_sys_fail_path(fptr->
pathv);
5358 #define rb_io_set_close_on_exec rb_f_notimplement
5361 #define RUBY_IO_EXTERNAL_P(f) ((f)->mode & FMODE_EXTERNAL)
5362 #define PREP_STDIO_NAME(f) (RSTRING_PTR((f)->pathv))
5365 finish_writeconv(
rb_io_t *fptr,
int noalloc)
5367 unsigned char *ds, *dp, *de;
5371 unsigned char buf[1024];
5376 de = buf +
sizeof(buf);
5379 size_t remaining = dp-ds;
5380 long result = rb_io_write_memory(fptr, ds, remaining);
5384 if ((
size_t)result == remaining)
break;
5407 if (io_fflush(fptr) < 0) {
5415 fptr->
wbuf.
len += (int)(dp - ds);
5431 finish_writeconv_sync(
VALUE arg)
5434 return finish_writeconv(p->fptr, p->noalloc);
5438 nogvl_close(
void *
ptr)
5442 return (
void*)(intptr_t)close(*fd);
5446 maygvl_close(
int fd,
int keepgvl)
5455 return IO_WITHOUT_GVL_INT(nogvl_close, &fd);
5459 nogvl_fclose(
void *
ptr)
5463 return (
void*)(intptr_t)fclose(file);
5467 maygvl_fclose(
FILE *file,
int keepgvl)
5470 return fclose(file);
5472 return IO_WITHOUT_GVL_INT(nogvl_fclose, file);
5478 fptr_finalize_flush(
rb_io_t *fptr,
int noraise,
int keepgvl,
5484 int mode = fptr->
mode;
5490 arg.noalloc = noraise;
5494 error = finish_writeconv(fptr, noraise);
5499 io_flush_buffer_sync(fptr);
5502 if (io_fflush(fptr) < 0 &&
NIL_P(error)) {
5510 if (RUBY_IO_EXTERNAL_P(fptr) || fd <= 2) {
5522 rb_notify_fd_close_wait(busy);
5534 if (!done && stdio_file) {
5536 if ((maygvl_fclose(stdio_file, noraise) < 0) &&
NIL_P(error)) {
5545 if (!done && fd >= 0) {
5551 if ((maygvl_close(fd, keepgvl) < 0) &&
NIL_P(error)) {
5560 if (!
NIL_P(error) && !noraise) {
5569 fptr_finalize(
rb_io_t *fptr,
int noraise)
5571 fptr_finalize_flush(fptr, noraise, FALSE, 0);
5572 free_io_buffer(&fptr->
rbuf);
5573 free_io_buffer(&fptr->
wbuf);
5574 clear_codeconv(fptr);
5578 rb_io_fptr_cleanup(
rb_io_t *fptr,
int noraise)
5584 fptr_finalize(fptr, noraise);
5592 ruby_sized_xfree(buf->
ptr, (
size_t)buf->
capa);
5604 free_io_buffer(&fptr->
cbuf);
5608 clear_writeconv(
rb_io_t *fptr)
5620 clear_readconv(fptr);
5621 clear_writeconv(fptr);
5625 rb_io_fptr_cleanup_all(
rb_io_t *fptr)
5629 rb_io_fptr_cleanup(fptr, TRUE);
5631 free_io_buffer(&fptr->
rbuf);
5632 free_io_buffer(&fptr->
wbuf);
5633 clear_codeconv(fptr);
5637 rb_io_fptr_finalize_internal(
void *
ptr)
5640 rb_io_fptr_cleanup_all(
ptr);
5644 #undef rb_io_fptr_finalize
5652 rb_io_fptr_finalize_internal(fptr);
5656 #define rb_io_fptr_finalize(fptr) rb_io_fptr_finalize_internal(fptr)
5659 rb_io_memsize(
const rb_io_t *fptr)
5661 size_t size =
sizeof(
rb_io_t);
5672 # define KEEPGVL TRUE
5674 # define KEEPGVL FALSE
5678 io_close_fptr(
VALUE io)
5685 write_io = GetWriteIO(io);
5686 if (io != write_io) {
5687 write_fptr =
RFILE(write_io)->fptr;
5688 if (write_fptr && 0 <= write_fptr->
fd) {
5689 rb_io_fptr_cleanup(write_fptr, TRUE);
5693 fptr =
RFILE(io)->fptr;
5694 if (!fptr)
return 0;
5695 if (fptr->
fd < 0)
return 0;
5697 if (rb_notify_fd_close(fptr->
fd, &busy)) {
5699 fptr_finalize_flush(fptr, FALSE, KEEPGVL, &busy);
5701 rb_io_fptr_cleanup(fptr, FALSE);
5706 fptr_waitpid(
rb_io_t *fptr,
int nohang)
5710 rb_last_status_clear();
5719 rb_io_t *fptr = io_close_fptr(io);
5720 if (fptr) fptr_waitpid(fptr, 0);
5760 rb_io_close_m(
VALUE io)
5762 rb_io_t *fptr = rb_io_get_fptr(io);
5771 io_call_close(
VALUE io)
5780 enum {mesg_len =
sizeof(closed_stream)-1};
5784 memcmp(
RSTRING_PTR(mesg), closed_stream, mesg_len)) {
5794 if (!UNDEF_P(closed) &&
RTEST(closed))
return io;
5795 rb_rescue2(io_call_close, io, ignore_closed_stream, io,
5831 write_io = GetWriteIO(io);
5832 if (io != write_io) {
5833 write_fptr =
RFILE(write_io)->fptr;
5834 if (write_fptr && 0 <= write_fptr->
fd) {
5839 fptr = rb_io_get_fptr(io);
5840 return RBOOL(0 > fptr->
fd);
5876 rb_io_close_read(
VALUE io)
5882 if (fptr->
fd < 0)
return Qnil;
5883 if (is_socket(fptr->
fd, fptr->
pathv)) {
5887 if (shutdown(fptr->
fd, SHUT_RD) < 0)
5888 rb_sys_fail_path(fptr->
pathv);
5895 write_io = GetWriteIO(io);
5896 if (io != write_io) {
5901 RFILE(io)->fptr = wfptr;
5904 RFILE(write_io)->fptr = fptr;
5905 rb_io_fptr_cleanup(fptr, FALSE);
5949 rb_io_close_write(
VALUE io)
5954 write_io = GetWriteIO(io);
5956 if (fptr->
fd < 0)
return Qnil;
5957 if (is_socket(fptr->
fd, fptr->
pathv)) {
5961 if (shutdown(fptr->
fd, SHUT_WR) < 0)
5962 rb_sys_fail_path(fptr->
pathv);
5973 if (io != write_io) {
5993 rb_io_sysseek(
int argc,
VALUE *argv,
VALUE io)
5995 VALUE offset, ptrname;
5996 int whence = SEEK_SET;
6000 if (
rb_scan_args(argc, argv,
"11", &offset, &ptrname) == 2) {
6001 whence = interpret_seek_whence(ptrname);
6006 (READ_DATA_BUFFERED(fptr) || READ_CHAR_PENDING(fptr))) {
6010 rb_warn(
"sysseek for buffered IO");
6013 pos = lseek(fptr->
fd, pos, whence);
6014 if (pos < 0 &&
errno) rb_sys_fail_path(fptr->
pathv);
6048 io = GetWriteIO(io);
6053 rb_warn(
"syswrite for buffered IO");
6056 tmp = rb_str_tmp_frozen_acquire(str);
6058 n = rb_io_write_memory(fptr,
ptr,
len);
6059 if (n < 0) rb_sys_fail_path(fptr->
pathv);
6060 rb_str_tmp_frozen_release(str, tmp);
6077 rb_io_sysread(
int argc,
VALUE *argv,
VALUE io)
6088 shrinkable = io_setstrbuf(&str, ilen);
6089 if (ilen == 0)
return str;
6094 if (READ_DATA_BUFFERED(fptr)) {
6100 io_setstrbuf(&str, ilen);
6108 n = io_read_memory_locktmp(str, &iis);
6111 rb_sys_fail_path(fptr->
pathv);
6114 io_set_read_length(str, n, shrinkable);
6116 if (n == 0 && ilen > 0) {
6132 internal_pread_func(
void *_arg)
6136 return (
VALUE)pread(arg->fd, arg->buf, arg->count, arg->offset);
6140 pread_internal_call(
VALUE _arg)
6145 if (scheduler !=
Qnil) {
6148 if (!UNDEF_P(result)) {
6153 return rb_io_blocking_region_wait(arg->io, internal_pread_func, arg,
RUBY_IO_READABLE);
6197 shrinkable = io_setstrbuf(&str, (
long)arg.count);
6198 if (arg.count == 0)
return str;
6212 rb_sys_fail_path(fptr->
pathv);
6214 io_set_read_length(str, n, shrinkable);
6215 if (n == 0 && arg.count > 0) {
6223 internal_pwrite_func(
void *_arg)
6228 if (scheduler !=
Qnil) {
6231 if (!UNDEF_P(result)) {
6237 return (
VALUE)pwrite(arg->fd, arg->buf, arg->count, arg->offset);
6278 io = GetWriteIO(io);
6285 tmp = rb_str_tmp_frozen_acquire(str);
6289 n = (ssize_t)rb_io_blocking_region_wait(fptr, internal_pwrite_func, &arg,
RUBY_IO_WRITABLE);
6290 if (n < 0) rb_sys_fail_path(fptr->
pathv);
6291 rb_str_tmp_frozen_release(str, tmp);
6311 SET_BINARY_MODE_WITH_SEEK_CUR(fptr);
6314 setmode(fptr->
fd, O_BINARY);
6321 io_ascii8bit_binmode(
rb_io_t *fptr)
6333 SET_BINARY_MODE_WITH_SEEK_CUR(fptr);
6339 clear_codeconv(fptr);
6348 io_ascii8bit_binmode(fptr);
6365 rb_io_binmode_m(
VALUE io)
6371 write_io = GetWriteIO(io);
6386 rb_io_binmode_p(
VALUE io)
6394 rb_io_fmode_modestr(
int fmode)
6398 return MODE_BTMODE(
"a+",
"ab+",
"at+");
6400 return MODE_BTMODE(
"a",
"ab",
"at");
6406 return MODE_BTMODE(
"r",
"rb",
"rt");
6408 return MODE_BTXMODE(
"w",
"wb",
"wt",
"wx",
"wbx",
"wtx");
6411 return MODE_BTXMODE(
"w+",
"wb+",
"wt+",
"w+x",
"wb+x",
"wt+x");
6413 return MODE_BTMODE(
"r+",
"rb+",
"rt+");
6417 static const char bom_prefix[] =
"bom|";
6418 static const char utf_prefix[] =
"utf-";
6419 enum {bom_prefix_len = (int)
sizeof(bom_prefix) - 1};
6420 enum {utf_prefix_len = (int)
sizeof(utf_prefix) - 1};
6423 io_encname_bom_p(
const char *name,
long len)
6425 return len > bom_prefix_len &&
STRNCASECMP(name, bom_prefix, bom_prefix_len) == 0;
6432 const char *m = modestr, *p = NULL;
6460 if (modestr[0] !=
'w')
6468 if (io_encname_bom_p(m, p ? (
long)(p - m) : (
long)strlen(m)))
6486 rb_io_oflags_fmode(
int oflags)
6490 switch (oflags & O_ACCMODE) {
6502 if (oflags & O_APPEND) {
6505 if (oflags & O_TRUNC) {
6508 if (oflags & O_CREAT) {
6511 if (oflags & O_EXCL) {
6515 if (oflags & O_BINARY) {
6524 rb_io_fmode_oflags(
int fmode)
6568 rb_io_oflags_modestr(
int oflags)
6571 # define MODE_BINARY(a,b) ((oflags & O_BINARY) ? (b) : (a))
6573 # define MODE_BINARY(a,b) (a)
6576 if (oflags & O_EXCL) {
6579 accmode = oflags & (O_RDONLY|O_WRONLY|O_RDWR);
6580 if (oflags & O_APPEND) {
6581 if (accmode == O_WRONLY) {
6582 return MODE_BINARY(
"a",
"ab");
6584 if (accmode == O_RDWR) {
6585 return MODE_BINARY(
"a+",
"ab+");
6592 return MODE_BINARY(
"r",
"rb");
6594 return MODE_BINARY(
"w",
"wb");
6596 if (oflags & O_TRUNC) {
6597 return MODE_BINARY(
"w+",
"wb+");
6599 return MODE_BINARY(
"r+",
"rb+");
6611 int default_ext = 0;
6617 if (rb_is_ascii8bit_enc(ext)) {
6621 else if (intern == NULL) {
6627 *enc = (default_ext && intern != ext) ? NULL : ext;
6637 unsupported_encoding(
const char *name,
rb_encoding *enc)
6639 rb_enc_warn(enc,
"Unsupported encoding %s ignored", name);
6643 parse_mode_enc(
const char *estr,
rb_encoding *estr_enc,
6649 int fmode = fmode_p ? *fmode_p : 0;
6655 p = strrchr(estr,
':');
6656 len = p ? (p++ - estr) : (
long)strlen(estr);
6658 estr += bom_prefix_len;
6659 len -= bom_prefix_len;
6660 if (!
STRNCASECMP(estr, utf_prefix, utf_prefix_len)) {
6664 rb_enc_warn(estr_enc,
"BOM with non-UTF encoding %s is nonsense", estr);
6673 memcpy(encname, estr,
len);
6674 encname[
len] =
'\0';
6679 if (fmode_p) *fmode_p = fmode;
6685 unsupported_encoding(estr, estr_enc);
6691 if (*p ==
'-' && *(p+1) ==
'\0') {
6698 unsupported_encoding(p, estr_enc);
6707 rb_io_ext_int_to_encs(ext_enc, int_enc, enc_p, enc2_p, fmode);
6721 if (v !=
Qnil) encoding = v;
6723 if (v !=
Qnil) extenc = v;
6725 if (!UNDEF_P(v)) intenc = v;
6727 if ((!UNDEF_P(extenc) || !UNDEF_P(intenc)) && !
NIL_P(encoding)) {
6731 rb_warn(
"Ignoring encoding parameter '%"PRIsVALUE
"': %s_encoding is used",
6732 encoding, UNDEF_P(extenc) ?
"internal" :
"external");
6736 if (!UNDEF_P(extenc) && !
NIL_P(extenc)) {
6739 if (!UNDEF_P(intenc)) {
6740 if (
NIL_P(intenc)) {
6747 if (*p ==
'-' && *(p+1) ==
'\0') {
6758 if (extencoding == intencoding) {
6762 if (!
NIL_P(encoding)) {
6766 enc_p, enc2_p, fmode_p);
6769 rb_io_ext_int_to_encs(
rb_to_encoding(encoding), NULL, enc_p, enc2_p, 0);
6772 else if (!UNDEF_P(extenc) || !UNDEF_P(intenc)) {
6774 rb_io_ext_int_to_encs(extencoding, intencoding, enc_p, enc2_p, 0);
6782 int fmode = *fmode_p;
6798 #if !DEFAULT_TEXTMODE
6807 extract_binmode(
VALUE opthash,
int *fmode)
6809 if (!
NIL_P(opthash)) {
6837 int *oflags_p,
int *fmode_p,
struct rb_io_encoding *convconfig_p)
6844 int has_enc = 0, has_vmode = 0;
6850 rb_io_ext_int_to_encs(NULL, NULL, &enc, &enc2, 0);
6860 fmode = rb_io_oflags_fmode(oflags);
6868 oflags = rb_io_fmode_oflags(fmode);
6872 parse_mode_enc(p+1,
rb_enc_get(vmode), &enc, &enc2, &fmode);
6878 rb_io_ext_int_to_encs(e, NULL, &enc, &enc2, fmode);
6882 if (
NIL_P(opthash)) {
6886 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
6888 MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE,
6889 0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE) : 0;
6891 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
6900 #if DEFAULT_TEXTMODE
6901 else if (
NIL_P(vmode)) {
6902 fmode |= DEFAULT_TEXTMODE;
6911 if (!
NIL_P(vmode)) {
6924 fmode = rb_io_oflags_fmode(oflags);
6926 extract_binmode(opthash, &fmode);
6934 #if DEFAULT_TEXTMODE
6935 else if (
NIL_P(vmode)) {
6936 fmode |= DEFAULT_TEXTMODE;
6942 if (!
NIL_P(*vperm_p)) {
6954 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
6956 MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE,
6957 0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE) : 0;
6965 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
6969 validate_enc_binmode(&fmode, ecflags, enc, enc2);
6975 convconfig_p->
enc = enc;
6976 convconfig_p->
enc2 = enc2;
6977 convconfig_p->
ecflags = ecflags;
6978 convconfig_p->
ecopts = ecopts;
6988 sysopen_func(
void *
ptr)
7000 fd = IO_WITHOUT_GVL_INT(sysopen_func, data);
7001 }
while (fd < 0 &&
errno == EINTR);
7008 rb_sysopen(
VALUE fname,
int oflags, mode_t perm)
7015 data.oflags = oflags;
7018 TRY_WITH_GC((fd = rb_sysopen_internal(&data)) >= 0) {
7019 rb_syserr_fail_path(first_errno, fname);
7024 static inline FILE *
7025 fdopen_internal(
int fd,
const char *modestr)
7032 file = fdopen(fd, modestr);
7036 #elif defined(__sun)
7048 TRY_WITH_GC((file = fdopen_internal(fd, modestr)) != 0) {
7054 if (setvbuf(file, NULL, _IOFBF, 0) != 0)
7055 rb_warn(
"setvbuf() can't be honoured (fd=%d)", fd);
7063 int t = isatty(fptr->
fd);
7073 io_strip_bom(
VALUE io)
7075 VALUE b1, b2, b3, b4;
7096 return ENCINDEX_UTF_16BE;
7107 return ENCINDEX_UTF_32LE;
7112 return ENCINDEX_UTF_16LE;
7122 return ENCINDEX_UTF_32BE;
7136 io_set_encoding_by_bom(
VALUE io)
7138 int idx = io_strip_bom(io);
7146 rb_io_internal_encoding(io),
Qnil);
7155 rb_file_open_generic(
VALUE io,
VALUE filename,
int oflags,
int fmode,
7163 rb_io_ext_int_to_encs(NULL, NULL, &cc.enc, &cc.enc2, fmode);
7168 validate_enc_binmode(&fmode, convconfig->
ecflags,
7169 convconfig->
enc, convconfig->
enc2);
7173 fptr->
encs = *convconfig;
7176 if (!(oflags & O_TMPFILE)) {
7177 fptr->
pathv = pathv;
7180 fptr->
pathv = pathv;
7182 fptr->
fd = rb_sysopen(pathv, oflags, perm);
7190 rb_file_open_internal(
VALUE io,
VALUE filename,
const char *modestr)
7193 const char *p = strchr(modestr,
':');
7198 &convconfig.
enc, &convconfig.
enc2, &fmode);
7205 rb_io_ext_int_to_encs(e, NULL, &convconfig.
enc, &convconfig.
enc2, fmode);
7211 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
7213 MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE,
7214 0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE) : 0;
7216 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(convconfig.
enc2, convconfig.
ecflags);
7219 return rb_file_open_generic(io, filename,
7220 rb_io_fmode_oflags(fmode),
7230 return rb_file_open_internal(io_alloc(
rb_cFile), fname, modestr);
7239 #if defined(__CYGWIN__) || !defined(HAVE_WORKING_FORK)
7262 while ((tmp = *prev) != 0) {
7263 if (tmp->fptr == fptr) {
7272 #if defined (_WIN32) || defined(__CYGWIN__)
7288 pipe_finalize(
rb_io_t *fptr,
int noraise)
7290 #if !defined(HAVE_WORKING_FORK) && !defined(_WIN32)
7299 fptr_finalize(fptr, noraise);
7301 pipe_del_fptr(fptr);
7308 #if defined(__CYGWIN__) || !defined(HAVE_WORKING_FORK)
7309 void (*
const old_finalize)(
struct rb_io*,int) = fptr->
finalize;
7311 if (old_finalize == orig->
finalize)
return;
7316 #if defined(__CYGWIN__) || !defined(HAVE_WORKING_FORK)
7317 if (old_finalize != pipe_finalize) {
7319 for (list =
pipe_list; list; list = list->next) {
7320 if (list->fptr == fptr)
break;
7322 if (!list) pipe_add_fptr(fptr);
7325 pipe_del_fptr(fptr);
7338 rb_io_unbuffered(
rb_io_t *fptr)
7356 #define HAVE_SPAWNV 1
7357 #define spawnv(mode, cmd, args) rb_w32_uaspawn((mode), (cmd), (args))
7358 #define spawn(mode, cmd) rb_w32_uspawn((mode), (cmd), 0)
7361 #if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
7371 #ifdef HAVE_WORKING_FORK
7372 # ifndef __EMSCRIPTEN__
7374 popen_redirect(
struct popen_arg *p)
7377 close(p->write_pair[1]);
7378 if (p->write_pair[0] != 0) {
7379 dup2(p->write_pair[0], 0);
7380 close(p->write_pair[0]);
7383 if (p->pair[1] != 1) {
7384 dup2(p->pair[1], 1);
7390 if (p->pair[1] != 1) {
7391 dup2(p->pair[1], 1);
7397 if (p->pair[0] != 0) {
7398 dup2(p->pair[0], 0);
7405 #if defined(__linux__)
7416 linux_get_maxfd(
void)
7419 char buf[4096], *p, *np, *e;
7422 if (fd < 0)
return fd;
7423 ss = read(fd, buf,
sizeof(buf));
7424 if (ss < 0)
goto err;
7427 while ((
int)
sizeof(
"FDSize:\t0\n")-1 <= e-p &&
7428 (np = memchr(p,
'\n', e-p)) != NULL) {
7429 if (memcmp(p,
"FDSize:",
sizeof(
"FDSize:")-1) == 0) {
7431 p +=
sizeof(
"FDSize:")-1;
7451 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
7453 int max = (int)max_file_descriptor;
7456 ret = fcntl(0, F_MAXFD);
7458 maxhint = max = ret;
7459 # elif defined(__linux__)
7460 ret = linux_get_maxfd();
7467 for (fd = lowfd; fd <= max; fd++) {
7468 if (!
NIL_P(noclose_fds) &&
7471 ret = fcntl(fd, F_GETFD);
7472 if (ret != -1 && !(ret & FD_CLOEXEC)) {
7473 fcntl(fd, F_SETFD, ret|FD_CLOEXEC);
7475 # define CONTIGUOUS_CLOSED_FDS 20
7477 if (max < fd + CONTIGUOUS_CLOSED_FDS)
7478 max = fd + CONTIGUOUS_CLOSED_FDS;
7484 # ifndef __EMSCRIPTEN__
7486 popen_exec(
void *pp,
char *errmsg,
size_t errmsg_len)
7488 struct popen_arg *p = (
struct popen_arg*)pp;
7490 return rb_exec_async_signal_safe(p->eargp, errmsg, errmsg_len);
7495 #if (defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)) && !defined __EMSCRIPTEN__
7497 rb_execarg_fixup_v(
VALUE execarg_obj)
7499 rb_execarg_parent_start(execarg_obj);
7503 char *rb_execarg_commandline(
const struct rb_execarg *eargp,
VALUE *prog);
7506 #ifndef __EMSCRIPTEN__
7508 pipe_open(
VALUE execarg_obj,
const char *modestr,
int fmode,
7511 struct rb_execarg *eargp =
NIL_P(execarg_obj) ? NULL : rb_execarg_get(execarg_obj);
7512 VALUE prog = eargp ? (eargp->use_shell ? eargp->invoke.sh.shell_script : eargp->invoke.cmd.command_name) :
Qfalse ;
7518 #if defined(HAVE_WORKING_FORK)
7520 char errmsg[80] = {
'\0' };
7522 #if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
7524 struct popen_arg arg;
7527 #if defined(HAVE_SPAWNV)
7528 # if defined(HAVE_SPAWNVE)
7529 # define DO_SPAWN(cmd, args, envp) ((args) ? \
7530 spawnve(P_NOWAIT, (cmd), (args), (envp)) : \
7531 spawne(P_NOWAIT, (cmd), (envp)))
7533 # define DO_SPAWN(cmd, args, envp) ((args) ? \
7534 spawnv(P_NOWAIT, (cmd), (args)) : \
7535 spawn(P_NOWAIT, (cmd)))
7537 # if !defined(HAVE_WORKING_FORK)
7539 # if defined(HAVE_SPAWNVE)
7544 #if !defined(HAVE_WORKING_FORK)
7550 #if !defined(HAVE_WORKING_FORK)
7551 const char *cmd = 0;
7557 #if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
7558 arg.execarg_obj = execarg_obj;
7561 arg.pair[0] = arg.pair[1] = -1;
7562 arg.write_pair[0] = arg.write_pair[1] = -1;
7563 # if !defined(HAVE_WORKING_FORK)
7564 if (eargp && !eargp->use_shell) {
7565 args = ARGVSTR2ARGV(eargp->invoke.cmd.argv_str);
7570 if (
rb_pipe(arg.write_pair) < 0)
7574 close(arg.write_pair[0]);
7575 close(arg.write_pair[1]);
7579 rb_execarg_addopt(execarg_obj,
INT2FIX(0),
INT2FIX(arg.write_pair[0]));
7580 rb_execarg_addopt(execarg_obj,
INT2FIX(1),
INT2FIX(arg.pair[1]));
7587 rb_execarg_addopt(execarg_obj,
INT2FIX(1),
INT2FIX(arg.pair[1]));
7593 rb_execarg_addopt(execarg_obj,
INT2FIX(0),
INT2FIX(arg.pair[0]));
7598 if (!
NIL_P(execarg_obj)) {
7599 rb_protect(rb_execarg_fixup_v, execarg_obj, &state);
7601 if (0 <= arg.write_pair[0]) close(arg.write_pair[0]);
7602 if (0 <= arg.write_pair[1]) close(arg.write_pair[1]);
7603 if (0 <= arg.pair[0]) close(arg.pair[0]);
7604 if (0 <= arg.pair[1]) close(arg.pair[1]);
7605 rb_execarg_parent_end(execarg_obj);
7609 # if defined(HAVE_WORKING_FORK)
7610 pid = rb_fork_async_signal_safe(&status, popen_exec, &arg, arg.eargp->redirect_fds, errmsg,
sizeof(errmsg));
7612 rb_execarg_run_options(eargp, sargp, NULL, 0);
7613 # if defined(HAVE_SPAWNVE)
7614 if (eargp->envp_str) envp = (
char **)
RSTRING_PTR(eargp->envp_str);
7616 while ((pid = DO_SPAWN(cmd, args, envp)) < 0) {
7618 switch (e =
errno) {
7620 # if EWOULDBLOCK != EAGAIN
7629 rb_execarg_run_options(sargp, NULL, NULL, 0);
7631 rb_execarg_parent_end(execarg_obj);
7634 # if defined(HAVE_WORKING_FORK)
7635 pid = rb_call_proc__fork();
7637 popen_redirect(&arg);
7649 # if defined(HAVE_WORKING_FORK)
7655 close(arg.write_pair[0]);
7656 close(arg.write_pair[1]);
7658 # if defined(HAVE_WORKING_FORK)
7667 close(arg.write_pair[0]);
7668 write_fd = arg.write_pair[1];
7679 cmd = rb_execarg_commandline(eargp, &prog);
7680 if (!
NIL_P(execarg_obj)) {
7681 rb_execarg_parent_start(execarg_obj);
7682 rb_execarg_run_options(eargp, sargp, NULL, 0);
7684 fp = popen(cmd, modestr);
7687 rb_execarg_parent_end(execarg_obj);
7688 rb_execarg_run_options(sargp, NULL, NULL, 0);
7690 if (!fp) rb_syserr_fail_path(e, prog);
7700 fptr->
encs = *convconfig;
7701 #if RUBY_CRLF_ENVIRONMENT
7708 if (NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {
7711 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
7712 if (NEED_NEWLINE_DECORATOR_ON_WRITE(fptr)) {
7713 fptr->
encs.
ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
7719 if (0 <= write_fd) {
7720 write_port = io_alloc(
rb_cIO);
7722 write_fptr->
fd = write_fd;
7729 #if defined (__CYGWIN__) || !defined(HAVE_WORKING_FORK)
7731 pipe_add_fptr(fptr);
7737 pipe_open(
VALUE execarg_obj,
const char *modestr,
int fmode,
7745 is_popen_fork(
VALUE prog)
7748 #if !defined(HAVE_WORKING_FORK)
7750 "fork() function is unimplemented on this machine");
7759 pipe_open_s(
VALUE prog,
const char *modestr,
int fmode,
7763 VALUE *argv = &prog;
7766 if (!is_popen_fork(prog))
7767 execarg_obj = rb_execarg_new(argc, argv, TRUE, FALSE);
7768 return pipe_open(execarg_obj, modestr, fmode, convconfig);
7772 pipe_close(
VALUE io)
7774 rb_io_t *fptr = io_close_fptr(io);
7942 rb_io_s_popen(
int argc,
VALUE *argv,
VALUE klass)
7956 int ex = !
NIL_P(opt);
7957 rb_error_arity(argc + ex, 1 + ex, 2 + ex);
7960 return popen_finish(rb_io_popen(pname, pmode, env, opt), klass);
7966 const char *modestr;
7974 #if SIZEOF_LONG > SIZEOF_INT
7975 if (
len > INT_MAX) {
7985 if (!is_popen_fork(pname))
7986 execarg_obj = rb_execarg_new(1, &pname, TRUE, FALSE);
7988 if (!
NIL_P(execarg_obj)) {
7990 opt = rb_execarg_extract_options(execarg_obj, opt);
7992 rb_execarg_setenv(execarg_obj, env);
7995 modestr = rb_io_oflags_modestr(oflags);
7997 return pipe_open(execarg_obj, modestr, fmode, &convconfig);
8013 RBASIC_SET_CLASS(port, klass);
8020 #if defined(HAVE_WORKING_FORK) && !defined(__EMSCRIPTEN__)
8021 struct popen_writer_arg {
8023 struct popen_arg popen;
8027 exec_popen_writer(
void *arg,
char *errmsg,
size_t buflen)
8029 struct popen_writer_arg *pw = arg;
8031 popen_redirect(&pw->popen);
8032 execv(pw->argv[0], pw->argv);
8033 strlcpy(errmsg, strerror(
errno), buflen);
8039 ruby_popen_writer(
char *
const *argv, rb_pid_t *pid)
8041 #if (defined(HAVE_WORKING_FORK) && !defined(__EMSCRIPTEN__)) || defined(_WIN32)
8042 # ifdef HAVE_WORKING_FORK
8043 struct popen_writer_arg pw;
8044 int *
const write_pair = pw.popen.pair;
8052 # ifdef HAVE_WORKING_FORK
8055 char errmsg[80] = {
'\0'};
8056 *pid = rb_fork_async_signal_safe(&status, exec_popen_writer, &pw,
Qnil, errmsg,
sizeof(errmsg));
8058 *pid = rb_w32_uspawn_process(P_NOWAIT, argv[0], argv, write_pair[0], -1, -1, 0);
8059 const char *errmsg = (*pid < 0) ? strerror(
errno) : NULL;
8061 close(write_pair[0]);
8063 close(write_pair[1]);
8064 fprintf(stderr,
"ruby_popen_writer(%s): %s\n", argv[0], errmsg);
8067 return fdopen(write_pair[1],
"w");
8086 rb_file_open_generic(io, fname, oflags, fmode, &convconfig, perm);
8124 rb_io_s_open(
int argc,
VALUE *argv,
VALUE klass)
8156 VALUE fname, vmode, vperm;
8161 rb_scan_args(argc, argv,
"12", &fname, &vmode, &vperm);
8172 if (
NIL_P(vperm)) perm = 0666;
8176 fd = rb_sysopen(fname, oflags, perm);
8181 check_pipe_command(
VALUE filename_or_command)
8226 int redirect = FALSE;
8234 VALUE tmp = argv[0];
8240 VALUE cmd = check_pipe_command(tmp);
8243 rb_warn_deprecated_to_remove_at(4.0,
"Calling Kernel#open with a leading '|'",
"IO.popen");
8245 return rb_io_s_popen(argc, argv,
rb_cIO);
8258 return rb_io_s_open(argc, argv,
rb_cFile);
8272 return rb_io_open_generic(io, filename, oflags, fmode, &convconfig, perm);
8276 rb_io_open_generic(
VALUE klass,
VALUE filename,
int oflags,
int fmode,
8280 if (klass ==
rb_cIO && !
NIL_P(cmd = check_pipe_command(filename))) {
8282 rb_warn_deprecated_to_remove_at(4.0,
"IO process creation with a leading '|'",
"IO.popen");
8283 return pipe_open_s(cmd, rb_io_oflags_modestr(oflags), fmode, convconfig);
8286 return rb_file_open_generic(io_alloc(klass), filename,
8287 oflags, fmode, convconfig, perm);
8302 if (fptr == orig)
return io;
8303 if (RUBY_IO_EXTERNAL_P(fptr)) {
8308 "%s can't change access mode from \"%s\" to \"%s\"",
8309 PREP_STDIO_NAME(fptr), rb_io_fmode_modestr(fptr->
mode),
8310 rb_io_fmode_modestr(orig->
mode));
8314 if (io_fflush(fptr) < 0)
8315 rb_sys_fail_on_write(fptr);
8318 flush_before_seek(fptr,
true);
8321 pos = io_tell(orig);
8324 if (io_fflush(orig) < 0)
8325 rb_sys_fail_on_write(fptr);
8334 else if (!RUBY_IO_EXTERNAL_P(fptr)) fptr->
pathv =
Qnil;
8335 fptr_copy_finalizer(fptr, orig);
8340 if (RUBY_IO_EXTERNAL_P(fptr) || fd <= 2 || !fptr->
stdio_file) {
8343 rb_sys_fail_path(orig->
pathv);
8351 rb_sys_fail_path(orig->
pathv);
8357 if (io_seek(fptr, pos, SEEK_SET) < 0 &&
errno) {
8358 rb_sys_fail_path(fptr->
pathv);
8360 if (io_seek(orig, pos, SEEK_SET) < 0 &&
errno) {
8361 rb_sys_fail_path(orig->
pathv);
8375 int rb_freopen(
VALUE fname,
const char *mode,
FILE *fp);
8378 rb_freopen(
VALUE fname,
const char *mode,
FILE *fp)
8423 rb_io_reopen(
int argc,
VALUE *argv,
VALUE file)
8425 VALUE fname, nmode, opt;
8429 if (
rb_scan_args(argc, argv,
"11:", &fname, &nmode, &opt) == 1) {
8432 return io_reopen(file, tmp);
8438 fptr =
RFILE(file)->fptr;
8448 if (RUBY_IO_EXTERNAL_P(fptr) &&
8452 "%s can't change access mode from \"%s\" to \"%s\"",
8453 PREP_STDIO_NAME(fptr), rb_io_fmode_modestr(fptr->
mode),
8454 rb_io_fmode_modestr(fmode));
8457 fptr->
encs = convconfig;
8460 oflags = rb_io_fmode_oflags(fptr->
mode);
8463 fptr->
pathv = fname;
8465 fptr->
fd = rb_sysopen(fptr->
pathv, oflags, 0666);
8471 if (io_fflush(fptr) < 0)
8472 rb_sys_fail_on_write(fptr);
8478 rb_io_oflags_modestr(oflags),
8480 if (e) rb_syserr_fail_path(e, fptr->
pathv);
8484 if (setvbuf(fptr->
stdio_file, NULL, _IOFBF, 0) != 0)
8485 rb_warn(
"setvbuf() can't be honoured for %"PRIsVALUE, fptr->
pathv);
8488 if (setvbuf(fptr->
stdio_file, NULL, _IONBF, BUFSIZ) != 0)
8489 rb_warn(
"setvbuf() can't be honoured for %"PRIsVALUE, fptr->
pathv);
8491 else if (fptr->
stdio_file == stdout && isatty(fptr->
fd)) {
8492 if (setvbuf(fptr->
stdio_file, NULL, _IOLBF, BUFSIZ) != 0)
8493 rb_warn(
"setvbuf() can't be honoured for %"PRIsVALUE, fptr->
pathv);
8497 int tmpfd = rb_sysopen(fptr->
pathv, oflags, 0666);
8503 rb_syserr_fail_path(err, fptr->
pathv);
8533 fptr_copy_finalizer(fptr, orig);
8535 fd = ruby_dup(orig->
fd);
8537 pos = io_tell(orig);
8539 io_seek(fptr, pos, SEEK_SET);
8544 write_io = GetWriteIO(io);
8545 if (io != write_io) {
8611 if (argc == 0)
return Qnil;
8630 rb_warn_deprecated(
"'%s'", NULL,
rb_id2name(
id));
8706 for (i=0; i<argc; i++) {
8811 #define forward(obj, id, argc, argv) \
8812 rb_funcallv_kw(obj, id, argc, argv, RB_PASS_CALLED_KEYWORDS)
8813 #define forward_public(obj, id, argc, argv) \
8814 rb_funcallv_public_kw(obj, id, argc, argv, RB_PASS_CALLED_KEYWORDS)
8815 #define forward_current(id, argc, argv) \
8816 forward_public(ARGF.current_file, id, argc, argv)
8834 if (recv == r_stdout) {
8835 return rb_io_putc(recv, ch);
8837 return forward(r_stdout,
rb_intern(
"putc"), 1, &ch);
8842 rb_str_end_with_asciichar(
VALUE str,
int c)
8849 if (
len == 0)
return 0;
8851 return ptr[
len - 1] == c;
8926 VALUE line, args[2];
8933 for (
int i = 0; i < argc; i++) {
8952 if (!rb_str_end_with_asciichar(line,
'\n')) {
8957 rb_io_writev(out, n, args);
8976 if (recv == r_stdout) {
8979 return forward(r_stdout,
rb_intern(
"puts"), argc, argv);
8983 rb_p_write(
VALUE str)
8991 io_writev(2, args, r_stdout);
8994 rb_io_writev(r_stdout, 2, args);
9006 rb_p_result(
int argc,
const VALUE *argv)
9013 else if (argc > 1) {
9059 for (i=0; i<argc; i++) {
9061 rb_uninterruptible(rb_p_write, inspected);
9063 return rb_p_result(argc, argv);
9084 rb_obj_display(
int argc,
VALUE *argv,
VALUE self)
9095 rb_stderr_to_original_p(
VALUE err)
9097 return (err == orig_stderr ||
RFILE(orig_stderr)->fptr->
fd < 0);
9104 if (rb_stderr_to_original_p(out)) {
9106 if (isatty(fileno(stderr))) {
9107 if (rb_w32_write_console(
rb_str_new(mesg,
len), fileno(stderr)) > 0)
return;
9110 if (fwrite(mesg,
sizeof(
char), (
size_t)
len, stderr) < (
size_t)
len) {
9127 rb_write_error_str(
VALUE mesg)
9131 if (rb_stderr_to_original_p(out)) {
9134 if (isatty(fileno(stderr))) {
9135 if (rb_w32_write_console(mesg, fileno(stderr)) > 0)
return;
9150 rb_stderr_tty_p(
void)
9153 return isatty(fileno(stderr));
9158 must_respond_to(
ID mid,
VALUE val,
ID id)
9182 must_respond_to(id_write, val,
id);
9195 must_respond_to(id_write, val,
id);
9206 allocate_and_open_new_file(
VALUE klass)
9208 VALUE self = io_alloc(klass);
9209 rb_io_make_open_file(
self);
9225 maygvl_close(descriptor, 0);
9233 io->
fd = descriptor;
9251 io->
encs = *encoding;
9260 prep_io(
int fd,
int fmode,
VALUE klass,
const char *path)
9271 rb_io_ext_int_to_encs(e, NULL, &convconfig.
enc, &convconfig.
enc2, fmode);
9275 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
9277 MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE,
9278 0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE) : 0;
9280 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(convconfig.
enc2, convconfig.
ecflags);
9286 if (!io_check_tty(io)) {
9289 setmode(fd, O_BINARY);
9301 if (path && strcmp(path,
"-")) klass =
rb_cFile;
9302 return prep_io(fd, rb_io_oflags_fmode(oflags), klass, path);
9306 prep_stdio(
FILE *f,
int fmode,
VALUE klass,
const char *path)
9313 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
9314 fptr->
encs.
ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
9325 rb_io_prep_stdin(
void)
9331 rb_io_prep_stdout(
void)
9337 rb_io_prep_stderr(
void)
9346 int oflags = rb_io_fmode_oflags(fptr->
mode) & ~O_EXCL;
9362 rb_io_fptr_new(
void)
9373 rb_io_buffer_init(&fp->
wbuf);
9374 rb_io_buffer_init(&fp->
rbuf);
9375 rb_io_buffer_init(&fp->
cbuf);
9393 rb_io_make_open_file(
VALUE obj)
9398 if (
RFILE(obj)->fptr) {
9401 RFILE(obj)->fptr = 0;
9403 fp = rb_io_fptr_new();
9405 RFILE(obj)->fptr = fp;
9453 rb_io_initialize(
int argc,
VALUE *argv,
VALUE io)
9459 return io_initialize(io, fnum, vmode, opt);
9466 int fd, fmode, oflags = O_RDONLY;
9468 #if defined(HAVE_FCNTL) && defined(F_GETFL)
9480 #if defined(HAVE_FCNTL) && defined(F_GETFL)
9481 oflags = fcntl(fd, F_GETFL);
9487 #if defined(HAVE_FCNTL) && defined(F_GETFL)
9488 ofmode = rb_io_oflags_fmode(oflags);
9515 fp->
encs = convconfig;
9520 if (fileno(stdin) == fd)
9522 else if (fileno(stdout) == fd)
9524 else if (fileno(stderr) == fd)
9556 rb_io_set_encoding_by_bom(
VALUE io)
9571 if (!io_set_encoding_by_bom(io))
return Qnil;
9617 rb_file_initialize(
int argc,
VALUE *argv,
VALUE io)
9619 if (
RFILE(io)->fptr) {
9622 VALUE fname, vmode, vperm, opt;
9623 int posargc =
rb_scan_args(argc, argv,
"12:", &fname, &vmode, &vperm, &opt);
9628 return io_initialize(io, fd, vmode, opt);
9631 return rb_open_file(io, fname, vmode, vperm, opt);
9636 rb_io_s_new(
int argc,
VALUE *argv,
VALUE klass)
9641 rb_warn(
"%"PRIsVALUE
"::new() does not take block; use %"PRIsVALUE
"::open() instead",
9657 rb_io_s_for_fd(
int argc,
VALUE *argv,
VALUE klass)
9660 rb_io_initialize(argc, argv, io);
9673 rb_io_autoclose_p(
VALUE io)
9698 rb_io_set_autoclose(
VALUE io,
VALUE autoclose)
9702 if (!
RTEST(autoclose))
9710 io_wait_event(
VALUE io,
int event,
VALUE timeout,
int return_io)
9742 io_wait_readable(
int argc,
VALUE *argv,
VALUE io)
9749 if (rb_io_read_pending(fptr))
return Qtrue;
9752 VALUE timeout = (argc == 1 ? argv[0] :
Qnil);
9766 io_wait_writable(
int argc,
VALUE *argv,
VALUE io)
9774 VALUE timeout = (argc == 1 ? argv[0] :
Qnil);
9789 io_wait_priority(
int argc,
VALUE *argv,
VALUE io)
9796 if (rb_io_read_pending(fptr))
return Qtrue;
9799 VALUE timeout = argc == 1 ? argv[0] :
Qnil;
9805 wait_mode_sym(
VALUE mode)
9808 return RB_WAITFD_IN;
9811 return RB_WAITFD_IN;
9814 return RB_WAITFD_IN;
9817 return RB_WAITFD_OUT;
9820 return RB_WAITFD_OUT;
9823 return RB_WAITFD_OUT;
9826 return RB_WAITFD_IN|RB_WAITFD_OUT;
9829 return RB_WAITFD_IN|RB_WAITFD_OUT;
9832 return RB_WAITFD_IN|RB_WAITFD_OUT;
9839 io_event_from_value(
VALUE value)
9881 for (
int i = 0; i < argc; i += 1) {
9883 events |= wait_mode_sym(argv[i]);
9885 else if (UNDEF_P(timeout)) {
9893 if (UNDEF_P(timeout)) timeout =
Qnil;
9901 events = io_event_from_value(argv[0]);
9909 if (rb_io_read_pending(fptr)) {
9911 if (return_io)
return Qtrue;
9917 return io_wait_event(io, events, timeout, return_io);
9921 argf_mark(
void *
ptr)
9932 argf_memsize(
const void *
ptr)
9935 size_t size =
sizeof(*p);
9942 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
9949 p->current_file =
Qnil;
9955 argf_alloc(
VALUE klass)
9970 memset(&ARGF, 0,
sizeof(ARGF));
9971 argf_init(&ARGF, argv);
9981 ARGF = argf_of(orig);
10008 ARGF.last_lineno = ARGF.lineno;
10037 #define next_argv() argf_next_argv(argf)
10038 #define ARGF_GENERIC_INPUT_P() \
10039 (ARGF.current_file == rb_stdin && !RB_TYPE_P(ARGF.current_file, T_FILE))
10040 #define ARGF_FORWARD(argc, argv) do {\
10041 if (ARGF_GENERIC_INPUT_P())\
10042 return argf_forward((argc), (argv), argf);\
10044 #define NEXT_ARGF_FORWARD(argc, argv) do {\
10045 if (!next_argv()) return Qnil;\
10046 ARGF_FORWARD((argc), (argv));\
10052 VALUE file = ARGF.current_file;
10066 int stdout_binmode = 0;
10074 stdout_binmode = 1;
10077 if (ARGF.init_p == 0) {
10087 if (
NIL_P(ARGF.argv)) {
10090 else if (ARGF.next_p == -1 &&
RARRAY_LEN(ARGF.argv) > 0) {
10095 if (ARGF.next_p == 1) {
10096 if (ARGF.init_p == 1) argf_close(
argf);
10101 ARGF.filename = filename;
10104 if (
RSTRING_LEN(filename) == 1 && fn[0] ==
'-') {
10106 if (ARGF.inplace) {
10107 rb_warn(
"Can't do inplace edit for stdio; skipping");
10113 int fr = rb_sysopen(filename, O_RDONLY, 0);
10115 if (ARGF.inplace) {
10117 #ifndef NO_SAFE_RENAME
10128 if (!
NIL_P(ARGF.inplace)) {
10129 VALUE suffix = ARGF.inplace;
10136 #ifdef NO_SAFE_RENAME
10140 rb_warn(
"Can't rename %"PRIsVALUE
" to %"PRIsVALUE
": %s, skipping file",
10141 filename, str, strerror(
errno));
10144 fr = rb_sysopen(str, O_RDONLY, 0);
10147 rb_warn(
"Can't rename %"PRIsVALUE
" to %"PRIsVALUE
": %s, skipping file",
10148 filename, str, strerror(
errno));
10155 #ifdef NO_SAFE_RENAME
10156 rb_fatal(
"Can't do inplace edit without backup");
10158 if (unlink(fn) < 0) {
10159 rb_warn(
"Can't remove %"PRIsVALUE
": %s, skipping file",
10160 filename, strerror(
errno));
10166 fw = rb_sysopen(filename, O_WRONLY|O_CREAT|O_TRUNC, 0666);
10167 #ifndef NO_SAFE_RENAME
10170 fchmod(fw, st.st_mode);
10172 chmod(fn, st.st_mode);
10174 if (st.st_uid!=st2.st_uid || st.st_gid!=st2.st_gid) {
10177 err = fchown(fw, st.st_uid, st.st_gid);
10179 err = chown(fn, st.st_uid, st.st_gid);
10181 if (err && getuid() == 0 && st2.st_uid == 0) {
10183 rb_warn(
"Can't set owner/group of %"PRIsVALUE
" to same as %"PRIsVALUE
": %s, skipping file",
10184 filename, str, strerror(
errno));
10187 (void)unlink(wkfn);
10197 if (!ARGF.binmode) {
10198 fmode |= DEFAULT_TEXTMODE;
10200 ARGF.current_file = prep_io(fr, fmode,
rb_cFile, fn);
10201 if (!
NIL_P(write_io)) {
10208 if (ARGF.encs.enc) {
10209 fptr->
encs = ARGF.encs;
10210 clear_codeconv(fptr);
10214 if (!ARGF.binmode) {
10216 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
10217 fptr->
encs.
ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
10228 else if (ARGF.next_p == -1) {
10231 if (ARGF.inplace) {
10232 rb_warn(
"Can't do inplace edit for stdio");
10236 if (ARGF.init_p == -1) ARGF.init_p = 1;
10244 long lineno = ARGF.lineno;
10247 if (!next_argv())
return Qnil;
10248 if (ARGF_GENERIC_INPUT_P()) {
10249 line = forward_current(idGets, argc, argv);
10256 line = rb_io_getline(argc, argv, ARGF.current_file);
10258 if (
NIL_P(line) && ARGF.next_p != -1) {
10264 if (!
NIL_P(line)) {
10265 ARGF.lineno = ++lineno;
10266 ARGF.last_lineno = ARGF.lineno;
10272 argf_lineno_getter(
ID id,
VALUE *var)
10275 return INT2FIX(ARGF.last_lineno);
10283 ARGF.last_lineno = ARGF.lineno = n;
10287 rb_reset_argf_lineno(
long n)
10289 ARGF.last_lineno = ARGF.lineno = n;
10328 rb_f_gets(
int argc,
VALUE *argv,
VALUE recv)
10330 if (recv ==
argf) {
10331 return argf_gets(argc, argv,
argf);
10333 return forward(
argf, idGets, argc, argv);
10359 line = argf_getline(argc, argv,
argf);
10371 return rb_f_gets(0, 0,
argf);
10375 if (!next_argv())
return Qnil;
10377 if (
NIL_P(line) && ARGF.next_p != -1) {
10383 if (!
NIL_P(line)) {
10385 ARGF.last_lineno = ARGF.lineno;
10411 rb_f_readline(
int argc,
VALUE *argv,
VALUE recv)
10413 if (recv ==
argf) {
10414 return argf_readline(argc, argv,
argf);
10442 if (!next_argv()) rb_eof_error();
10443 ARGF_FORWARD(argc, argv);
10444 line = argf_gets(argc, argv,
argf);
10514 rb_f_readlines(
int argc,
VALUE *argv,
VALUE recv)
10516 if (recv ==
argf) {
10517 return argf_readlines(argc, argv,
argf);
10543 long lineno = ARGF.lineno;
10547 while (next_argv()) {
10548 if (ARGF_GENERIC_INPUT_P()) {
10549 lines = forward_current(
rb_intern(
"readlines"), argc, argv);
10552 lines = rb_io_readlines(argc, argv, ARGF.current_file);
10558 ARGF.last_lineno = ARGF.lineno;
10593 rb_last_status_clear();
10594 port = pipe_open_s(str,
"r",
FMODE_READABLE|DEFAULT_TEXTMODE, NULL);
10598 result = read_all(fptr, remain_size(fptr),
Qnil);
10600 rb_io_fptr_cleanup_all(fptr);
10606 #ifdef HAVE_SYS_SELECT_H
10607 #include <sys/select.h>
10621 if (!
NIL_P(read)) {
10626 if (READ_DATA_PENDING(fptr) || READ_CHAR_PENDING(fptr)) {
10630 if (max < fptr->fd) max = fptr->
fd;
10633 timerec.tv_sec = timerec.tv_usec = 0;
10641 if (!
NIL_P(write)) {
10647 if (max < fptr->fd) max = fptr->
fd;
10654 if (!
NIL_P(except)) {
10658 VALUE write_io = GetWriteIO(io);
10661 if (max < fptr->fd) max = fptr->
fd;
10662 if (io != write_io) {
10665 if (max < fptr->fd) max = fptr->
fd;
10680 if (!pending && n == 0)
return Qnil;
10705 VALUE write_io = GetWriteIO(io);
10718 VALUE write_io = GetWriteIO(io);
10723 else if (io != write_io) {
10736 VALUE read, write, except;
10742 select_call(
VALUE arg)
10746 return select_internal(p->read, p->write, p->except, p->timeout, p->fdsets);
10750 select_end(
VALUE arg)
10755 for (i = 0; i < numberof(p->fdsets); ++i)
10760 static VALUE sym_normal, sym_sequential, sym_random,
10761 sym_willneed, sym_dontneed, sym_noreuse;
10763 #ifdef HAVE_POSIX_FADVISE
10764 struct io_advise_struct {
10772 io_advise_internal(
void *arg)
10774 struct io_advise_struct *
ptr = arg;
10775 return posix_fadvise(
ptr->fd,
ptr->offset,
ptr->len,
ptr->advice);
10779 io_advise_sym_to_const(
VALUE sym)
10781 #ifdef POSIX_FADV_NORMAL
10782 if (sym == sym_normal)
10783 return INT2NUM(POSIX_FADV_NORMAL);
10786 #ifdef POSIX_FADV_RANDOM
10787 if (sym == sym_random)
10788 return INT2NUM(POSIX_FADV_RANDOM);
10791 #ifdef POSIX_FADV_SEQUENTIAL
10792 if (sym == sym_sequential)
10793 return INT2NUM(POSIX_FADV_SEQUENTIAL);
10796 #ifdef POSIX_FADV_WILLNEED
10797 if (sym == sym_willneed)
10798 return INT2NUM(POSIX_FADV_WILLNEED);
10801 #ifdef POSIX_FADV_DONTNEED
10802 if (sym == sym_dontneed)
10803 return INT2NUM(POSIX_FADV_DONTNEED);
10806 #ifdef POSIX_FADV_NOREUSE
10807 if (sym == sym_noreuse)
10808 return INT2NUM(POSIX_FADV_NOREUSE);
10815 do_io_advise(
rb_io_t *fptr,
VALUE advice, rb_off_t offset, rb_off_t
len)
10818 struct io_advise_struct ias;
10821 num_adv = io_advise_sym_to_const(advice);
10827 if (
NIL_P(num_adv))
10831 ias.advice =
NUM2INT(num_adv);
10832 ias.offset = offset;
10835 rv = (int)rb_io_blocking_region(fptr, io_advise_internal, &ias);
10836 if (rv && rv != ENOSYS) {
10843 fptr->
pathv, offset,
len, advice);
10853 advice_arg_check(
VALUE advice)
10858 if (advice != sym_normal &&
10859 advice != sym_sequential &&
10860 advice != sym_random &&
10861 advice != sym_willneed &&
10862 advice != sym_dontneed &&
10863 advice != sym_noreuse) {
10902 rb_io_advise(
int argc,
VALUE *argv,
VALUE io)
10909 advice_arg_check(advice);
10911 io = GetWriteIO(io);
10917 #ifdef HAVE_POSIX_FADVISE
10918 return do_io_advise(fptr, advice,
off, l);
10920 ((void)
off, (
void)l);
11076 rb_f_select(
int argc,
VALUE *argv,
VALUE obj)
11079 if (scheduler !=
Qnil) {
11082 if (!UNDEF_P(result))
return result;
11090 rb_scan_args(argc, argv,
"13", &args.read, &args.write, &args.except, &timeout);
11091 if (
NIL_P(timeout)) {
11096 args.timeout = &timerec;
11099 for (i = 0; i < numberof(args.fdsets); ++i)
11105 #ifdef IOCTL_REQ_TYPE
11106 typedef IOCTL_REQ_TYPE ioctl_req_t;
11108 typedef int ioctl_req_t;
11109 # define NUM2IOCTLREQ(num) ((int)NUM2LONG(num))
11120 nogvl_ioctl(
void *
ptr)
11122 struct ioctl_arg *arg =
ptr;
11124 return (
VALUE)ioctl(arg->fd, arg->cmd, arg->narg);
11128 do_ioctl(
struct rb_io *io, ioctl_req_t cmd,
long narg)
11131 struct ioctl_arg arg;
11137 retval = (int)rb_io_blocking_region(io, nogvl_ioctl, &arg);
11143 #define DEFAULT_IOCTL_NARG_LEN (256)
11145 #if defined(__linux__) && defined(_IOC_SIZE)
11147 linux_iocparm_len(ioctl_req_t cmd)
11151 if ((cmd & 0xFFFF0000) == 0) {
11153 return DEFAULT_IOCTL_NARG_LEN;
11156 len = _IOC_SIZE(cmd);
11159 if (
len < DEFAULT_IOCTL_NARG_LEN)
11160 len = DEFAULT_IOCTL_NARG_LEN;
11168 ioctl_narg_len(ioctl_req_t cmd)
11172 #ifdef IOCPARM_MASK
11173 #ifndef IOCPARM_LEN
11174 #define IOCPARM_LEN(x) (((x) >> 16) & IOCPARM_MASK)
11178 len = IOCPARM_LEN(cmd);
11179 #elif defined(__linux__) && defined(_IOC_SIZE)
11180 len = linux_iocparm_len(cmd);
11183 len = DEFAULT_IOCTL_NARG_LEN;
11192 typedef long fcntl_arg_t;
11195 typedef int fcntl_arg_t;
11199 fcntl_narg_len(ioctl_req_t cmd)
11206 len =
sizeof(fcntl_arg_t);
11214 #ifdef F_DUPFD_CLOEXEC
11215 case F_DUPFD_CLOEXEC:
11216 len =
sizeof(fcntl_arg_t);
11226 len =
sizeof(fcntl_arg_t);
11236 len =
sizeof(fcntl_arg_t);
11246 len =
sizeof(fcntl_arg_t);
11251 len =
sizeof(
struct f_owner_ex);
11256 len =
sizeof(
struct f_owner_ex);
11261 len =
sizeof(
struct flock);
11266 len =
sizeof(
struct flock);
11271 len =
sizeof(
struct flock);
11291 len =
sizeof(fcntl_arg_t);
11301 len =
sizeof(fcntl_arg_t);
11306 len =
sizeof(fcntl_arg_t);
11319 fcntl_narg_len(ioctl_req_t cmd)
11325 #define NARG_SENTINEL 17
11328 setup_narg(ioctl_req_t cmd,
VALUE *argp,
long (*narg_len)(ioctl_req_t))
11339 else if (arg ==
Qtrue) {
11353 len = narg_len(cmd);
11358 if (slen <
len+1) {
11365 ptr[slen - 1] = NARG_SENTINEL;
11374 finish_narg(
int retval,
VALUE arg,
const rb_io_t *fptr)
11376 if (retval < 0) rb_sys_fail_path(fptr->
pathv);
11381 if (
ptr[slen-1] != NARG_SENTINEL)
11383 ptr[slen-1] =
'\0';
11393 ioctl_req_t cmd = NUM2IOCTLREQ(req);
11398 narg = setup_narg(cmd, &arg, ioctl_narg_len);
11400 retval = do_ioctl(fptr, cmd, narg);
11401 return finish_narg(retval, arg, fptr);
11423 rb_io_ioctl(
int argc,
VALUE *argv,
VALUE io)
11428 return rb_ioctl(io, req, arg);
11431 #define rb_io_ioctl rb_f_notimplement
11442 nogvl_fcntl(
void *
ptr)
11444 struct fcntl_arg *arg =
ptr;
11446 #if defined(F_DUPFD)
11447 if (arg->cmd == F_DUPFD)
11450 return (
VALUE)fcntl(arg->fd, arg->cmd, arg->narg);
11454 do_fcntl(
struct rb_io *io,
int cmd,
long narg)
11457 struct fcntl_arg arg;
11463 retval = (int)rb_io_blocking_region(io, nogvl_fcntl, &arg);
11464 if (retval != -1) {
11466 #if defined(F_DUPFD)
11469 #if defined(F_DUPFD_CLOEXEC)
11470 case F_DUPFD_CLOEXEC:
11487 narg = setup_narg(cmd, &arg, fcntl_narg_len);
11489 retval = do_fcntl(fptr, cmd, narg);
11490 return finish_narg(retval, arg, fptr);
11511 rb_io_fcntl(
int argc,
VALUE *argv,
VALUE io)
11516 return rb_fcntl(io, req, arg);
11519 #define rb_io_fcntl rb_f_notimplement
11522 #if defined(HAVE_SYSCALL) || defined(HAVE___SYSCALL)
11554 #if SIZEOF_VOIDP == 8 && defined(HAVE___SYSCALL) && SIZEOF_INT != 8
11555 # define SYSCALL __syscall
11556 # define NUM2SYSCALLID(x) NUM2LONG(x)
11557 # define RETVAL2NUM(x) LONG2NUM(x)
11558 # if SIZEOF_LONG == 8
11559 long num, retval = -1;
11560 # elif SIZEOF_LONG_LONG == 8
11561 long long num, retval = -1;
11563 # error ---->> it is asserted that __syscall takes the first argument and returns retval in 64bit signed integer. <<----
11565 #elif defined(__linux__)
11566 # define SYSCALL syscall
11567 # define NUM2SYSCALLID(x) NUM2LONG(x)
11568 # define RETVAL2NUM(x) LONG2NUM(x)
11576 long num, retval = -1;
11578 # define SYSCALL syscall
11579 # define NUM2SYSCALLID(x) NUM2INT(x)
11580 # define RETVAL2NUM(x) INT2NUM(x)
11581 int num, retval = -1;
11587 "We plan to remove a syscall function at future release. DL(Fiddle) provides safer alternative.");
11592 if (argc > numberof(arg))
11594 num = NUM2SYSCALLID(argv[0]); ++argv;
11595 for (i = argc - 1; i--; ) {
11610 retval = SYSCALL(num);
11613 retval = SYSCALL(num, arg[0]);
11616 retval = SYSCALL(num, arg[0],arg[1]);
11619 retval = SYSCALL(num, arg[0],arg[1],arg[2]);
11622 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3]);
11625 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4]);
11628 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5]);
11631 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6]);
11637 return RETVAL2NUM(retval);
11639 #undef NUM2SYSCALLID
11643 #define rb_f_syscall rb_f_notimplement
11647 io_new_instance(
VALUE args)
11653 find_encoding(
VALUE v)
11656 if (!enc)
rb_warn(
"Unsupported encoding %"PRIsVALUE
" ignored", v);
11668 enc2 = find_encoding(v1);
11677 enc = find_encoding(v2);
11684 enc = find_encoding(v2);
11695 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
11701 rb_io_ext_int_to_encs(NULL, NULL, &enc, &enc2, 0);
11702 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
11708 parse_mode_enc(
RSTRING_PTR(tmp), enc, &enc, &enc2, NULL);
11709 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
11713 rb_io_ext_int_to_encs(find_encoding(v1), NULL, &enc, &enc2, 0);
11714 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
11719 validate_enc_binmode(&fptr->
mode, ecflags, enc, enc2);
11724 clear_codeconv(fptr);
11736 io_encoding_set_v(
VALUE v)
11739 io_encoding_set(arg->fptr, arg->v1, arg->v2, arg->opt);
11744 pipe_pair_close(
VALUE rw)
11747 return rb_ensure(io_close, rwp[0], io_close, rwp[1]);
11830 rb_io_s_pipe(
int argc,
VALUE *argv,
VALUE klass)
11832 int pipes[2], state;
11833 VALUE r, w, args[3], v1, v2;
11840 argc =
rb_scan_args(argc, argv,
"02:", &v1, &v2, &opt);
11855 ies_args.fptr = fptr;
11858 ies_args.opt = opt;
11877 extract_binmode(opt, &fmode);
11884 #if DEFAULT_TEXTMODE
11887 setmode(fptr->
fd, O_BINARY);
11889 #if RUBY_CRLF_ENVIRONMENT
11895 fptr->
mode |= fmode;
11896 #if DEFAULT_TEXTMODE
11899 setmode(fptr2->
fd, O_BINARY);
11902 fptr2->
mode |= fmode;
11939 v = rb_to_array_type(v);
11944 arg->io = rb_io_open(klass, path, vmode, vperm, opt);
11948 io_s_foreach(
VALUE v)
11953 if (arg->limit == 0)
11955 while (!
NIL_P(str = rb_io_getline_1(arg->rs, arg->limit, arg->chomp, arg->io))) {
12043 rb_io_s_foreach(
int argc,
VALUE *argv,
VALUE self)
12046 int orig_argc = argc;
12050 argc =
rb_scan_args(argc, argv,
"12:", NULL, NULL, NULL, &opt);
12052 extract_getline_args(argc-1, argv+1, &garg);
12053 open_key_args(
self, argc, argv, opt, &arg);
12055 extract_getline_opts(opt, &garg);
12056 check_getline_args(&garg.rs, &garg.limit, garg.io = arg.io);
12061 io_s_readlines(
VALUE v)
12064 return io_readlines(arg, arg->io);
12121 rb_io_s_readlines(
int argc,
VALUE *argv,
VALUE io)
12127 argc =
rb_scan_args(argc, argv,
"12:", NULL, NULL, NULL, &opt);
12128 extract_getline_args(argc-1, argv+1, &garg);
12129 open_key_args(io, argc, argv, opt, &arg);
12131 extract_getline_opts(opt, &garg);
12132 check_getline_args(&garg.rs, &garg.limit, garg.io = arg.io);
12140 return io_read(arg->argc, arg->argv, arg->io);
12150 seek_before_access(
VALUE argp)
12154 return rb_io_seek(arg->io, arg->offset, arg->mode);
12200 rb_io_s_read(
int argc,
VALUE *argv,
VALUE io)
12206 argc =
rb_scan_args(argc, argv,
"13:", NULL, NULL, &offset, NULL, &opt);
12210 open_key_args(io, argc, argv, opt, &arg);
12212 if (!
NIL_P(offset)) {
12216 sarg.offset = offset;
12217 sarg.mode = SEEK_SET;
12223 if (arg.argc == 2) arg.argc = 1;
12242 rb_io_s_binread(
int argc,
VALUE *argv,
VALUE io)
12258 arg.io = rb_io_open_generic(io, argv[0], oflags, fmode, &convconfig, 0);
12261 arg.argc = (argc > 1) ? 1 : 0;
12262 if (!
NIL_P(offset)) {
12266 sarg.offset = offset;
12267 sarg.mode = SEEK_SET;
12278 io_s_write0(
VALUE v)
12281 return io_write(arg->io,arg->str,arg->nosync);
12285 io_s_write(
int argc,
VALUE *argv,
VALUE klass,
int binary)
12287 VALUE string, offset, opt;
12291 rb_scan_args(argc, argv,
"21:", NULL, &
string, &offset, &opt);
12298 int mode = O_WRONLY|O_CREAT;
12300 if (binary) mode |= O_BINARY;
12302 if (
NIL_P(offset)) mode |= O_TRUNC;
12305 open_key_args(klass, argc, argv, opt, &arg);
12308 if (binary) rb_io_binmode_m(arg.io);
12312 if (!
NIL_P(offset)) {
12316 sarg.offset = offset;
12317 sarg.mode = SEEK_SET;
12377 rb_io_s_write(
int argc,
VALUE *argv,
VALUE io)
12379 return io_s_write(argc, argv, io, 0);
12396 rb_io_s_binwrite(
int argc,
VALUE *argv,
VALUE io)
12398 return io_s_write(argc, argv, io, 1);
12404 rb_off_t copy_length;
12405 rb_off_t src_offset;
12409 unsigned close_src : 1;
12410 unsigned close_dst : 1;
12413 const char *syserr;
12414 const char *notimp;
12416 struct stat src_stat;
12417 struct stat dst_stat;
12418 #ifdef HAVE_FCOPYFILE
12419 copyfile_state_t copyfile_state;
12424 exec_interrupts(
void *arg)
12427 rb_thread_execute_interrupts(th);
12441 #if defined(ERESTART)
12446 rb_thread_execute_interrupts(stp->th);
12465 fiber_scheduler_wait_for(
void * _arguments)
12475 # define IOWAIT_SYSCALL "poll"
12476 STATIC_ASSERT(pollin_expected, POLLIN == RB_WAITFD_IN);
12477 STATIC_ASSERT(pollout_expected, POLLOUT == RB_WAITFD_OUT);
12482 if (scheduler !=
Qnil) {
12485 return RTEST(args.result);
12489 if (fd == -1)
return 0;
12494 fds.events = events;
12496 int timeout_milliseconds = -1;
12499 timeout_milliseconds = (int)(timeout->tv_sec * 1000) + (int)(timeout->tv_usec / 1000);
12502 return poll(&fds, 1, timeout_milliseconds);
12505 # define IOWAIT_SYSCALL "select"
12510 if (scheduler !=
Qnil) {
12513 return RTEST(args.result);
12533 case RB_WAITFD_OUT:
12537 VM_UNREACHABLE(nogvl_wait_for);
12557 ret = nogvl_wait_for(stp->th, stp->src_fptr, RB_WAITFD_IN, NULL);
12559 }
while (ret < 0 && maygvl_copy_stream_continue_p(has_gvl, stp));
12562 stp->syserr = IOWAIT_SYSCALL;
12563 stp->error_no =
errno;
12575 ret = nogvl_wait_for(stp->th, stp->dst_fptr, RB_WAITFD_OUT, NULL);
12576 }
while (ret < 0 && maygvl_copy_stream_continue_p(0, stp));
12579 stp->syserr = IOWAIT_SYSCALL;
12580 stp->error_no =
errno;
12586 #ifdef USE_COPY_FILE_RANGE
12589 simple_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)
12591 #ifdef HAVE_COPY_FILE_RANGE
12592 return copy_file_range(in_fd, in_offset, out_fd, out_offset, count, flags);
12594 return syscall(__NR_copy_file_range, in_fd, in_offset, out_fd, out_offset, count, flags);
12603 rb_off_t copy_length, src_offset, *src_offset_ptr;
12605 if (!S_ISREG(stp->src_stat.st_mode))
12608 src_size = stp->src_stat.st_size;
12609 src_offset = stp->src_offset;
12610 if (src_offset >= (rb_off_t)0) {
12611 src_offset_ptr = &src_offset;
12614 src_offset_ptr = NULL;
12617 copy_length = stp->copy_length;
12618 if (copy_length < (rb_off_t)0) {
12619 if (src_offset < (rb_off_t)0) {
12620 rb_off_t current_offset;
12622 current_offset = lseek(stp->src_fptr->
fd, 0, SEEK_CUR);
12623 if (current_offset < (rb_off_t)0 &&
errno) {
12624 stp->syserr =
"lseek";
12625 stp->error_no =
errno;
12626 return (
int)current_offset;
12628 copy_length = src_size - current_offset;
12631 copy_length = src_size - src_offset;
12635 retry_copy_file_range:
12636 # if SIZEOF_OFF_T > SIZEOF_SIZE_T
12638 ss = (copy_length > (rb_off_t)SSIZE_MAX) ? SSIZE_MAX : (ssize_t)copy_length;
12640 ss = (ssize_t)copy_length;
12642 ss = simple_copy_file_range(stp->src_fptr->
fd, src_offset_ptr, stp->dst_fptr->
fd, NULL, ss, 0);
12646 if (0 < copy_length) {
12647 goto retry_copy_file_range;
12651 if (maygvl_copy_stream_continue_p(0, stp)) {
12652 goto retry_copy_file_range;
12666 #if EWOULDBLOCK != EAGAIN
12670 int ret = nogvl_copy_stream_wait_write(stp);
12671 if (ret < 0)
return ret;
12673 goto retry_copy_file_range;
12677 int flags = fcntl(stp->dst_fptr->
fd, F_GETFL);
12679 if (flags != -1 && flags & O_APPEND) {
12685 stp->syserr =
"copy_file_range";
12686 stp->error_no =
errno;
12693 #ifdef HAVE_FCOPYFILE
12697 rb_off_t cur, ss = 0;
12698 const rb_off_t src_offset = stp->src_offset;
12701 if (stp->copy_length >= (rb_off_t)0) {
12706 if (!S_ISREG(stp->src_stat.st_mode))
12709 if (!S_ISREG(stp->dst_stat.st_mode))
12711 if (lseek(stp->dst_fptr->
fd, 0, SEEK_CUR) > (rb_off_t)0)
12713 if (fcntl(stp->dst_fptr->
fd, F_GETFL) & O_APPEND) {
12716 rb_off_t end = lseek(stp->dst_fptr->
fd, 0, SEEK_END);
12717 lseek(stp->dst_fptr->
fd, 0, SEEK_SET);
12718 if (end > (rb_off_t)0)
return 0;
12721 if (src_offset > (rb_off_t)0) {
12726 cur = lseek(stp->src_fptr->
fd, 0, SEEK_CUR);
12727 if (cur < (rb_off_t)0 &&
errno) {
12728 stp->error_no =
errno;
12733 r = lseek(stp->src_fptr->
fd, src_offset, SEEK_SET);
12734 if (r < (rb_off_t)0 &&
errno) {
12735 stp->error_no =
errno;
12740 stp->copyfile_state = copyfile_state_alloc();
12741 ret = fcopyfile(stp->src_fptr->
fd, stp->dst_fptr->
fd, stp->copyfile_state, COPYFILE_DATA);
12742 copyfile_state_get(stp->copyfile_state, COPYFILE_STATE_COPIED, &ss);
12746 if (src_offset > (rb_off_t)0) {
12750 r = lseek(stp->src_fptr->
fd, cur, SEEK_SET);
12751 if (r < (rb_off_t)0 &&
errno) {
12752 stp->error_no =
errno;
12764 stp->syserr =
"fcopyfile";
12765 stp->error_no =
errno;
12772 #ifdef HAVE_SENDFILE
12775 # define USE_SENDFILE
12777 # ifdef HAVE_SYS_SENDFILE_H
12778 # include <sys/sendfile.h>
12782 simple_sendfile(
int out_fd,
int in_fd, rb_off_t *offset, rb_off_t count)
12784 return sendfile(out_fd, in_fd, offset, (
size_t)count);
12787 # elif 0 || defined(__APPLE__)
12791 # define USE_SENDFILE
12794 simple_sendfile(
int out_fd,
int in_fd, rb_off_t *offset, rb_off_t count)
12797 rb_off_t pos = offset ? *offset : lseek(in_fd, 0, SEEK_CUR);
12800 r = sendfile(in_fd, out_fd, pos, &count, NULL, 0);
12803 r = sendfile(in_fd, out_fd, pos, (
size_t)count, NULL, &sbytes, 0);
12805 if (r != 0 && sbytes == 0)
return r;
12810 lseek(in_fd, sbytes, SEEK_CUR);
12812 return (ssize_t)sbytes;
12819 #ifdef USE_SENDFILE
12825 rb_off_t copy_length;
12826 rb_off_t src_offset;
12829 if (!S_ISREG(stp->src_stat.st_mode))
12832 src_size = stp->src_stat.st_size;
12834 if ((stp->dst_stat.st_mode & S_IFMT) != S_IFSOCK)
12838 src_offset = stp->src_offset;
12839 use_pread = src_offset >= (rb_off_t)0;
12841 copy_length = stp->copy_length;
12842 if (copy_length < (rb_off_t)0) {
12844 copy_length = src_size - src_offset;
12848 cur = lseek(stp->src_fptr->
fd, 0, SEEK_CUR);
12849 if (cur < (rb_off_t)0 &&
errno) {
12850 stp->syserr =
"lseek";
12851 stp->error_no =
errno;
12854 copy_length = src_size - cur;
12859 # if SIZEOF_OFF_T > SIZEOF_SIZE_T
12861 ss = (copy_length > (rb_off_t)SSIZE_MAX) ? SSIZE_MAX : (ssize_t)copy_length;
12863 ss = (ssize_t)copy_length;
12866 ss = simple_sendfile(stp->dst_fptr->
fd, stp->src_fptr->
fd, &src_offset, ss);
12869 ss = simple_sendfile(stp->dst_fptr->
fd, stp->src_fptr->
fd, NULL, ss);
12874 if (0 < copy_length) {
12875 goto retry_sendfile;
12879 if (maygvl_copy_stream_continue_p(0, stp))
12880 goto retry_sendfile;
12893 #if EWOULDBLOCK != EAGAIN
12906 ret = maygvl_copy_stream_wait_read(0, stp);
12907 if (ret < 0)
return ret;
12909 ret = nogvl_copy_stream_wait_write(stp);
12910 if (ret < 0)
return ret;
12912 goto retry_sendfile;
12914 stp->syserr =
"sendfile";
12915 stp->error_no =
errno;
12923 maygvl_read(
int has_gvl,
rb_io_t *fptr,
void *buf,
size_t count)
12926 return rb_io_read_memory(fptr, buf, count);
12928 return read(fptr->
fd, buf, count);
12932 maygvl_copy_stream_read(
int has_gvl,
struct copy_stream_struct *stp,
char *buf,
size_t len, rb_off_t offset)
12936 if (offset < (rb_off_t)0) {
12937 ss = maygvl_read(has_gvl, stp->src_fptr, buf,
len);
12940 ss = pread(stp->src_fptr->
fd, buf,
len, offset);
12946 if (maygvl_copy_stream_continue_p(has_gvl, stp))
12950 #if EWOULDBLOCK != EAGAIN
12954 int ret = maygvl_copy_stream_wait_read(has_gvl, stp);
12955 if (ret < 0)
return ret;
12960 stp->notimp =
"pread";
12964 stp->syserr = offset < (rb_off_t)0 ?
"read" :
"pread";
12965 stp->error_no =
errno;
12976 ss = write(stp->dst_fptr->
fd, buf+
off,
len);
12978 if (maygvl_copy_stream_continue_p(0, stp))
12980 if (io_again_p(
errno)) {
12981 int ret = nogvl_copy_stream_wait_write(stp);
12982 if (ret < 0)
return ret;
12985 stp->syserr =
"write";
12986 stp->error_no =
errno;
13003 rb_off_t copy_length;
13004 rb_off_t src_offset;
13008 copy_length = stp->copy_length;
13009 use_eof = copy_length < (rb_off_t)0;
13010 src_offset = stp->src_offset;
13011 use_pread = src_offset >= (rb_off_t)0;
13013 if (use_pread && stp->close_src) {
13016 r = lseek(stp->src_fptr->
fd, src_offset, SEEK_SET);
13017 if (r < (rb_off_t)0 &&
errno) {
13018 stp->syserr =
"lseek";
13019 stp->error_no =
errno;
13022 src_offset = (rb_off_t)-1;
13026 while (use_eof || 0 < copy_length) {
13027 if (!use_eof && copy_length < (rb_off_t)
sizeof(buf)) {
13028 len = (size_t)copy_length;
13034 ss = maygvl_copy_stream_read(0, stp, buf,
len, src_offset);
13039 ss = maygvl_copy_stream_read(0, stp, buf,
len, (rb_off_t)-1);
13044 ret = nogvl_copy_stream_write(stp, buf, ss);
13054 nogvl_copy_stream_func(
void *arg)
13057 #if defined(USE_SENDFILE) || defined(USE_COPY_FILE_RANGE) || defined(HAVE_FCOPYFILE)
13061 #ifdef USE_COPY_FILE_RANGE
13062 ret = nogvl_copy_file_range(stp);
13067 #ifdef HAVE_FCOPYFILE
13068 ret = nogvl_fcopyfile(stp);
13073 #ifdef USE_SENDFILE
13074 ret = nogvl_copy_stream_sendfile(stp);
13079 nogvl_copy_stream_read_write(stp);
13081 #if defined(USE_SENDFILE) || defined(USE_COPY_FILE_RANGE) || defined(HAVE_FCOPYFILE)
13088 copy_stream_fallback_body(
VALUE arg)
13091 const int buflen = 16*1024;
13094 rb_off_t rest = stp->copy_length;
13095 rb_off_t
off = stp->src_offset;
13096 ID read_method = id_readpartial;
13098 if (!stp->src_fptr) {
13100 read_method = id_read;
13107 if (stp->copy_length < (rb_off_t)0) {
13115 l = buflen < rest ? buflen : (long)rest;
13117 if (!stp->src_fptr) {
13120 if (read_method == id_read &&
NIL_P(rc))
13132 if (
off >= (rb_off_t)0)
13137 stp->total += numwrote;
13139 if (read_method == id_read &&
RSTRING_LEN(buf) == 0) {
13150 if (!stp->src_fptr && stp->src_offset >= (rb_off_t)0) {
13160 copy_stream_body(
VALUE arg)
13163 VALUE src_io = stp->src, dst_io = stp->dst;
13164 const int common_oflags = 0
13174 if (src_io ==
argf ||
13178 stp->src_fptr = NULL;
13183 if (!
NIL_P(tmp_io)) {
13190 args[1] =
INT2NUM(O_RDONLY|common_oflags);
13193 stp->close_src = 1;
13198 stat_ret = fstat(stp->src_fptr->
fd, &stp->src_stat);
13199 if (stat_ret < 0) {
13200 stp->syserr =
"fstat";
13201 stp->error_no =
errno;
13206 if (dst_io ==
argf ||
13210 stp->dst_fptr = NULL;
13215 if (!
NIL_P(tmp_io)) {
13216 dst_io = GetWriteIO(tmp_io);
13222 args[1] =
INT2NUM(O_WRONLY|O_CREAT|O_TRUNC|common_oflags);
13226 stp->close_dst = 1;
13229 dst_io = GetWriteIO(dst_io);
13235 stat_ret = fstat(stp->dst_fptr->
fd, &stp->dst_stat);
13236 if (stat_ret < 0) {
13237 stp->syserr =
"fstat";
13238 stp->error_no =
errno;
13245 SET_BINARY_MODE_WITH_SEEK_CUR(stp->src_fptr);
13248 io_ascii8bit_binmode(stp->dst_fptr);
13250 if (stp->src_offset < (rb_off_t)0 && stp->src_fptr && stp->src_fptr->
rbuf.
len) {
13253 if (stp->copy_length >= (rb_off_t)0 && stp->copy_length < (rb_off_t)
len) {
13254 len = (size_t)stp->copy_length;
13259 if (stp->dst_fptr) {
13261 rb_sys_fail_on_write(stp->dst_fptr);
13267 if (stp->copy_length >= (rb_off_t)0)
13268 stp->copy_length -=
len;
13271 if (stp->dst_fptr && io_fflush(stp->dst_fptr) < 0) {
13275 if (stp->copy_length == 0)
13278 if (stp->src_fptr == NULL || stp->dst_fptr == NULL) {
13279 return copy_stream_fallback(stp);
13282 IO_WITHOUT_GVL(nogvl_copy_stream_func, stp);
13287 copy_stream_finalize(
VALUE arg)
13291 #ifdef HAVE_FCOPYFILE
13292 if (stp->copyfile_state) {
13293 copyfile_state_free(stp->copyfile_state);
13297 if (stp->close_src) {
13298 rb_io_close_m(stp->src);
13300 if (stp->close_dst) {
13301 rb_io_close_m(stp->dst);
13364 rb_io_s_copy_stream(
int argc,
VALUE *argv,
VALUE io)
13366 VALUE src, dst, length, src_offset;
13371 rb_scan_args(argc, argv,
"22", &src, &dst, &length, &src_offset);
13376 st.src_fptr = NULL;
13377 st.dst_fptr = NULL;
13380 st.copy_length = (rb_off_t)-1;
13382 st.copy_length =
NUM2OFFT(length);
13384 if (
NIL_P(src_offset))
13385 st.src_offset = (rb_off_t)-1;
13387 st.src_offset =
NUM2OFFT(src_offset);
13406 rb_io_external_encoding(
VALUE io)
13434 rb_io_internal_encoding(
VALUE io)
13473 rb_io_set_encoding(
int argc,
VALUE *argv,
VALUE io)
13479 return forward(io, id_set_encoding, argc, argv);
13482 argc =
rb_scan_args(argc, argv,
"11:", &v1, &v2, &opt);
13484 io_encoding_set(fptr, v1, v2, opt);
13489 rb_stdio_set_default_encoding(
void)
13494 if (isatty(fileno(stdin))) {
13505 rb_io_set_encoding(1, &val,
rb_stdin);
13506 rb_io_set_encoding(1, &val,
rb_stdout);
13507 rb_io_set_encoding(1, &val,
rb_stderr);
13511 global_argf_p(
VALUE arg)
13513 return arg ==
argf;
13516 typedef VALUE (*argf_encoding_func)(
VALUE io);
13519 argf_encoding(
VALUE argf, argf_encoding_func func)
13521 if (!
RTEST(ARGF.current_file)) {
13546 return argf_encoding(
argf, rb_io_external_encoding);
13565 return argf_encoding(
argf, rb_io_internal_encoding);
13604 if (!next_argv()) {
13607 rb_io_set_encoding(argc, argv, ARGF.current_file);
13609 ARGF.encs = fptr->
encs;
13628 if (!next_argv()) {
13631 ARGF_FORWARD(0, 0);
13632 return rb_io_tell(ARGF.current_file);
13645 if (!next_argv()) {
13648 ARGF_FORWARD(argc, argv);
13649 return rb_io_seek_m(argc, argv, ARGF.current_file);
13666 if (!next_argv()) {
13669 ARGF_FORWARD(1, &offset);
13670 return rb_io_set_pos(ARGF.current_file, offset);
13691 if (!next_argv()) {
13694 ARGF_FORWARD(0, 0);
13695 old_lineno =
RFILE(ARGF.current_file)->fptr->lineno;
13696 ret = rb_io_rewind(ARGF.current_file);
13697 if (!global_argf_p(
argf)) {
13698 ARGF.last_lineno = ARGF.lineno -= old_lineno;
13716 if (!next_argv()) {
13719 ARGF_FORWARD(0, 0);
13720 return rb_io_fileno(ARGF.current_file);
13739 ARGF_FORWARD(0, 0);
13740 return ARGF.current_file;
13765 if (
RTEST(ARGF.current_file)) {
13766 if (ARGF.init_p == 0)
return Qtrue;
13768 ARGF_FORWARD(0, 0);
13827 VALUE tmp, str, length;
13831 if (!
NIL_P(length)) {
13841 if (!next_argv()) {
13844 if (ARGF_GENERIC_INPUT_P()) {
13845 tmp = argf_forward(argc, argv,
argf);
13848 tmp = io_read(argc, argv, ARGF.current_file);
13850 if (
NIL_P(str)) str = tmp;
13853 if (ARGF.next_p != -1) {
13859 else if (argc >= 1) {
13876 argf_forward_call(
VALUE arg)
13879 argf_forward(p->argc, p->argv, p->argf);
13909 return argf_getpartial(argc, argv,
argf,
Qnil, 0);
13930 return argf_getpartial(argc, argv,
argf, opts, 1);
13936 VALUE tmp, str, length;
13944 no_exception = no_exception_p(opts);
13946 if (!next_argv()) {
13952 if (ARGF_GENERIC_INPUT_P()) {
13962 tmp = io_getpartial(argc, argv, ARGF.current_file, no_exception, nonblock);
13965 if (ARGF.next_p == -1) {
13966 return io_nonblock_eof(no_exception);
13971 return io_nonblock_eof(no_exception);
14009 if (!next_argv())
return Qnil;
14010 if (ARGF_GENERIC_INPUT_P()) {
14011 ch = forward_current(
rb_intern(
"getc"), 0, 0);
14014 ch = rb_io_getc(ARGF.current_file);
14016 if (
NIL_P(ch) && ARGF.next_p != -1) {
14049 if (!next_argv())
return Qnil;
14051 ch = forward_current(
rb_intern(
"getbyte"), 0, 0);
14056 if (
NIL_P(ch) && ARGF.next_p != -1) {
14089 if (!next_argv()) rb_eof_error();
14091 ch = forward_current(
rb_intern(
"getc"), 0, 0);
14094 ch = rb_io_getc(ARGF.current_file);
14096 if (
NIL_P(ch) && ARGF.next_p != -1) {
14128 NEXT_ARGF_FORWARD(0, 0);
14129 c = argf_getbyte(
argf);
14136 #define FOREACH_ARGF() while (next_argv())
14141 const VALUE current = ARGF.current_file;
14143 if (ARGF.init_p == -1 || current != ARGF.current_file) {
14149 #define ARGF_block_call(mid, argc, argv, func, argf) \
14150 rb_block_call_kw(ARGF.current_file, mid, argc, argv, \
14151 func, argf, rb_keyword_given_p())
14156 VALUE ret = ARGF_block_call(mid, argc, argv, argf_block_call_i,
argf);
14157 if (!UNDEF_P(ret)) ARGF.next_p = 1;
14163 if (!global_argf_p(
argf)) {
14164 ARGF.last_lineno = ++ARGF.lineno;
14166 return argf_block_call_i(i,
argf, argc, argv, blockarg);
14172 VALUE ret = ARGF_block_call(mid, argc, argv, argf_block_call_line_i,
argf);
14173 if (!UNDEF_P(ret)) ARGF.next_p = 1;
14221 argf_block_call_line(
rb_intern(
"each_line"), argc, argv,
argf);
14335 return ARGF.filename;
14339 argf_filename_getter(
ID id,
VALUE *var)
14341 return argf_filename(*var);
14366 return ARGF.current_file;
14385 ARGF_FORWARD(0, 0);
14406 return RBOOL(ARGF.binmode);
14426 if (ARGF.init_p && ARGF.next_p == 0) {
14455 if (ARGF.next_p != -1) {
14473 ARGF_FORWARD(0, 0);
14500 if (!ARGF.inplace)
return Qnil;
14508 return argf_inplace_mode_get(*var);
14539 ARGF.inplace =
Qnil;
14550 argf_inplace_mode_set(*var, val);
14554 ruby_set_inplace_mode(
const char *suffix)
14580 argf_argv_getter(
ID id,
VALUE *var)
14582 return argf_argv(*var);
14601 if (!
RTEST(ARGF.current_file)) {
14604 return GetWriteIO(ARGF.current_file);
14616 return rb_io_writev(argf_write_io(
argf), argc, argv);
14631 case RB_IO_WAIT_WRITABLE:
14634 c = rb_eEAGAINWaitWritable;
14636 #if EAGAIN != EWOULDBLOCK
14638 c = rb_eEWOULDBLOCKWaitWritable;
14642 c = rb_eEINPROGRESSWaitWritable;
14648 case RB_IO_WAIT_READABLE:
14651 c = rb_eEAGAINWaitReadable;
14653 #if EAGAIN != EWOULDBLOCK
14655 c = rb_eEWOULDBLOCKWaitReadable;
14659 c = rb_eEINPROGRESSWaitReadable;
14666 rb_bug(
"invalid read/write type passed to rb_readwrite_sys_fail: %d", waiting);
14672 get_LAST_READ_LINE(
ID _x,
VALUE *_y)
15557 #include <sys/cygwin.h>
15558 static struct __cygwin_perfile pf[] =
15560 {
"", O_RDONLY | O_BINARY},
15561 {
"", O_WRONLY | O_BINARY},
15562 {
"", O_RDWR | O_BINARY},
15563 {
"", O_APPEND | O_BINARY},
15566 cygwin_internal(CW_PERFILE, pf);
15621 #if EAGAIN == EWOULDBLOCK
15622 rb_eEWOULDBLOCKWaitReadable = rb_eEAGAINWaitReadable;
15625 rb_eEWOULDBLOCKWaitWritable = rb_eEAGAINWaitWritable;
15679 rb_gvar_ractor_local(
"$_");
15795 rb_gvar_ractor_local(
"$stdin");
15796 rb_gvar_ractor_local(
"$stdout");
15797 rb_gvar_ractor_local(
"$>");
15798 rb_gvar_ractor_local(
"$stderr");
15884 rb_define_method(rb_cARGF,
"external_encoding", argf_external_encoding, 0);
15885 rb_define_method(rb_cARGF,
"internal_encoding", argf_internal_encoding, 0);
15904 rb_gvar_ractor_local(
"$-i");
15908 #if defined (_WIN32) || defined(__CYGWIN__)
15909 atexit(pipe_atexit);
15921 sym_encoding =
ID2SYM(rb_id_encoding());
15945 #include "io.rbinc"
#define RUBY_ASSERT(...)
Asserts that the given expression is truthy if and only if RUBY_DEBUG is truthy.
std::atomic< unsigned > rb_atomic_t
Type that is eligible for atomic operations.
unsigned long ruby_strtoul(const char *str, char **endptr, int base)
Our own locale-insensitive version of strtoul(3).
#define rb_define_singleton_method(klass, mid, func, arity)
Defines klass.mid.
void rb_include_module(VALUE klass, VALUE module)
Includes a module to a class.
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
VALUE rb_class_new(VALUE super)
Creates a new, anonymous class.
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
VALUE rb_define_module_under(VALUE outer, const char *name)
Defines a module under the namespace of outer.
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
int rb_scan_args_kw(int kw_flag, int argc, const VALUE *argv, const char *fmt,...)
Identical to rb_scan_args(), except it also accepts kw_splat.
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Retrieves argument from argc and argv to given VALUE references according to the format string.
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a method.
int rb_block_given_p(void)
Determines if the current method is given a block.
int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *values)
Keyword argument deconstructor.
void rb_define_global_function(const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a global function.
#define ECONV_AFTER_OUTPUT
Old name of RUBY_ECONV_AFTER_OUTPUT.
#define rb_str_new2
Old name of rb_str_new_cstr.
#define TYPE(_)
Old name of rb_type.
#define RB_INTEGER_TYPE_P
Old name of rb_integer_type_p.
#define ENC_CODERANGE_7BIT
Old name of RUBY_ENC_CODERANGE_7BIT.
#define T_FILE
Old name of RUBY_T_FILE.
#define ENC_CODERANGE_VALID
Old name of RUBY_ENC_CODERANGE_VALID.
#define ECONV_UNIVERSAL_NEWLINE_DECORATOR
Old name of RUBY_ECONV_UNIVERSAL_NEWLINE_DECORATOR.
#define OBJ_INIT_COPY(obj, orig)
Old name of RB_OBJ_INIT_COPY.
#define ALLOC
Old name of RB_ALLOC.
#define T_STRING
Old name of RUBY_T_STRING.
#define Qundef
Old name of RUBY_Qundef.
#define INT2FIX
Old name of RB_INT2FIX.
#define T_NIL
Old name of RUBY_T_NIL.
#define UNREACHABLE
Old name of RBIMPL_UNREACHABLE.
#define ID2SYM
Old name of RB_ID2SYM.
#define T_BIGNUM
Old name of RUBY_T_BIGNUM.
#define OBJ_FREEZE
Old name of RB_OBJ_FREEZE.
#define T_FIXNUM
Old name of RUBY_T_FIXNUM.
#define UNREACHABLE_RETURN
Old name of RBIMPL_UNREACHABLE_RETURN.
#define FIX2UINT
Old name of RB_FIX2UINT.
#define SSIZET2NUM
Old name of RB_SSIZE2NUM.
#define ZALLOC
Old name of RB_ZALLOC.
#define CLASS_OF
Old name of rb_class_of.
#define rb_ary_new4
Old name of rb_ary_new_from_values.
#define ECONV_NEWLINE_DECORATOR_WRITE_MASK
Old name of RUBY_ECONV_NEWLINE_DECORATOR_WRITE_MASK.
#define ENCODING_MAXNAMELEN
Old name of RUBY_ENCODING_MAXNAMELEN.
#define MBCLEN_NEEDMORE_LEN(ret)
Old name of ONIGENC_MBCLEN_NEEDMORE_LEN.
#define ENCODING_GET(obj)
Old name of RB_ENCODING_GET.
#define LONG2FIX
Old name of RB_INT2FIX.
#define NUM2UINT
Old name of RB_NUM2UINT.
#define ALLOC_N
Old name of RB_ALLOC_N.
#define MBCLEN_CHARFOUND_LEN(ret)
Old name of ONIGENC_MBCLEN_CHARFOUND_LEN.
#define LONG2NUM
Old name of RB_LONG2NUM.
#define rb_exc_new3
Old name of rb_exc_new_str.
#define STRNCASECMP
Old name of st_locale_insensitive_strncasecmp.
#define MBCLEN_INVALID_P(ret)
Old name of ONIGENC_MBCLEN_INVALID_P.
#define ISASCII
Old name of rb_isascii.
#define ECONV_STATEFUL_DECORATOR_MASK
Old name of RUBY_ECONV_STATEFUL_DECORATOR_MASK.
#define Qtrue
Old name of RUBY_Qtrue.
#define MBCLEN_NEEDMORE_P(ret)
Old name of ONIGENC_MBCLEN_NEEDMORE_P.
#define ECONV_PARTIAL_INPUT
Old name of RUBY_ECONV_PARTIAL_INPUT.
#define NUM2INT
Old name of RB_NUM2INT.
#define ECONV_ERROR_HANDLER_MASK
Old name of RUBY_ECONV_ERROR_HANDLER_MASK.
#define INT2NUM
Old name of RB_INT2NUM.
#define Qnil
Old name of RUBY_Qnil.
#define Qfalse
Old name of RUBY_Qfalse.
#define FIX2LONG
Old name of RB_FIX2LONG.
#define ENC_CODERANGE_BROKEN
Old name of RUBY_ENC_CODERANGE_BROKEN.
#define T_ARRAY
Old name of RUBY_T_ARRAY.
#define NIL_P
Old name of RB_NIL_P.
#define ALLOCV_N
Old name of RB_ALLOCV_N.
#define MBCLEN_CHARFOUND_P(ret)
Old name of ONIGENC_MBCLEN_CHARFOUND_P.
#define ECONV_NEWLINE_DECORATOR_READ_MASK
Old name of RUBY_ECONV_NEWLINE_DECORATOR_READ_MASK.
#define NUM2CHR
Old name of RB_NUM2CHR.
#define 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 unless $VERBOSE is nil.
void rb_raise(VALUE exc, const char *fmt,...)
Exception entry point.
void rb_category_warning(rb_warning_category_t category, const char *fmt,...)
Identical to rb_warning(), except it takes additional "category" parameter.
VALUE rb_rescue2(VALUE(*b_proc)(VALUE), VALUE data1, VALUE(*r_proc)(VALUE, VALUE), VALUE data2,...)
An equivalent of rescue clause.
VALUE rb_eNotImpError
NotImplementedError exception.
void rb_exc_raise(VALUE mesg)
Raises an exception in the current thread.
void rb_syserr_fail(int e, const char *mesg)
Raises appropriate exception that represents a C errno.
void rb_bug(const char *fmt,...)
Interpreter panic switch.
void rb_sys_fail(const char *mesg)
Converts a C errno into a Ruby exception, then raises it.
void rb_readwrite_syserr_fail(enum rb_io_wait_readwrite waiting, int n, const char *mesg)
Identical to rb_readwrite_sys_fail(), except it does not depend on C global variable errno.
VALUE rb_eIOError
IOError exception.
VALUE rb_eStandardError
StandardError exception.
void rb_mod_syserr_fail_str(VALUE mod, int e, VALUE mesg)
Identical to rb_mod_syserr_fail(), except it takes the message in Ruby's String instead of C's.
void rb_syserr_fail_str(int e, VALUE mesg)
Identical to rb_syserr_fail(), except it takes the message in Ruby's String instead of C's.
#define ruby_verbose
This variable controls whether the interpreter is in debug mode.
VALUE rb_eTypeError
TypeError exception.
VALUE rb_eEOFError
EOFError exception.
void rb_fatal(const char *fmt,...)
Raises the unsung "fatal" exception.
void rb_readwrite_sys_fail(enum rb_io_wait_readwrite waiting, const char *mesg)
Raises appropriate exception using the parameters.
void rb_iter_break_value(VALUE val)
Identical to rb_iter_break(), except it additionally takes the "value" of this breakage.
rb_io_wait_readwrite
for rb_readwrite_sys_fail first argument
VALUE rb_eRuntimeError
RuntimeError exception.
void rb_warn(const char *fmt,...)
Identical to rb_warning(), except it reports unless $VERBOSE is nil.
VALUE rb_eArgError
ArgumentError exception.
VALUE rb_ensure(VALUE(*b_proc)(VALUE), VALUE data1, VALUE(*e_proc)(VALUE), VALUE data2)
An equivalent to ensure clause.
void rb_sys_fail_str(VALUE mesg)
Identical to rb_sys_fail(), except it takes the message in Ruby's String instead of C's.
VALUE rb_eSystemCallError
SystemCallError exception.
@ RB_WARN_CATEGORY_DEPRECATED
Warning is for deprecated features.
VALUE rb_mKernel
Kernel module.
VALUE rb_check_to_int(VALUE val)
Identical to rb_check_to_integer(), except it uses #to_int for conversion.
VALUE rb_any_to_s(VALUE obj)
Generates a textual representation of the given object.
VALUE rb_obj_alloc(VALUE klass)
Allocates an instance of the given class.
VALUE rb_class_new_instance(int argc, const VALUE *argv, VALUE klass)
Allocates, then initialises an instance of the given class.
VALUE rb_class_new_instance_kw(int argc, const VALUE *argv, VALUE klass, int kw_splat)
Identical to rb_class_new_instance(), except you can specify how to handle the last element of the gi...
VALUE rb_mEnumerable
Enumerable module.
VALUE rb_stdin
STDIN constant.
VALUE rb_stderr
STDERR constant.
VALUE rb_obj_class(VALUE obj)
Queries the class of an object.
VALUE rb_obj_dup(VALUE obj)
Duplicates the given object.
VALUE rb_inspect(VALUE obj)
Generates a human-readable textual representation of the given object.
VALUE rb_mWaitReadable
IO::WaitReadable module.
VALUE rb_mWaitWritable
IO::WaitReadable module.
VALUE rb_obj_freeze(VALUE obj)
Just calls rb_obj_freeze_inline() inside.
VALUE rb_check_to_integer(VALUE val, const char *mid)
Identical to rb_check_convert_type(), except the return value type is fixed to rb_cInteger.
VALUE rb_cFile
File class.
VALUE rb_stdout
STDOUT constant.
VALUE rb_to_int(VALUE val)
Identical to rb_check_to_int(), except it raises in case of conversion mismatch.
rb_encoding * rb_locale_encoding(void)
Queries the encoding that represents the current locale.
rb_encoding * rb_default_external_encoding(void)
Queries the "default external" encoding.
int rb_enc_precise_mbclen(const char *p, const char *e, rb_encoding *enc)
Queries the number of bytes of the character at the passed pointer.
int rb_to_encoding_index(VALUE obj)
Obtains a encoding index from a wider range of objects (than rb_enc_find_index()).
VALUE rb_enc_associate(VALUE obj, rb_encoding *enc)
Identical to rb_enc_associate_index(), except it takes an encoding itself instead of its index.
rb_encoding * rb_usascii_encoding(void)
Queries the encoding that represents US-ASCII.
static char * rb_enc_left_char_head(const char *s, const char *p, const char *e, rb_encoding *enc)
Queries the left boundary of a character.
int rb_utf8_encindex(void)
Identical to rb_utf8_encoding(), except it returns the encoding's index instead of the encoding itsel...
rb_encoding * rb_default_internal_encoding(void)
Queries the "default internal" encoding.
rb_encoding * rb_find_encoding(VALUE obj)
Identical to rb_to_encoding_index(), except the return type.
rb_encoding * rb_to_encoding(VALUE obj)
Identical to rb_find_encoding(), except it raises an exception instead of returning NULL.
rb_encoding * rb_ascii8bit_encoding(void)
Queries the encoding that represents ASCII-8BIT a.k.a.
VALUE rb_enc_default_external(void)
Identical to rb_default_external_encoding(), except it returns the Ruby-level counterpart instance of...
VALUE rb_enc_from_encoding(rb_encoding *enc)
Queries the Ruby-level counterpart instance of rb_cEncoding that corresponds to the passed encoding.
static bool rb_enc_asciicompat(rb_encoding *enc)
Queries if the passed encoding is in some sense compatible with ASCII.
static unsigned int rb_enc_codepoint(const char *p, const char *e, rb_encoding *enc)
Queries the code point of character pointed by the passed pointer.
rb_encoding * rb_enc_from_index(int idx)
Identical to rb_find_encoding(), except it takes an encoding index instead of a Ruby object.
int rb_enc_mbclen(const char *p, const char *e, rb_encoding *enc)
Queries the number of bytes of the character at the passed pointer.
rb_encoding * rb_enc_get(VALUE obj)
Identical to rb_enc_get_index(), except the return type.
static const char * rb_enc_name(rb_encoding *enc)
Queries the (canonical) name of the passed encoding.
int rb_enc_find_index(const char *name)
Queries the index of the encoding.
static int rb_enc_mbminlen(rb_encoding *enc)
Queries the minimum number of bytes that the passed encoding needs to represent a character.
int rb_enc_ascget(const char *p, const char *e, int *len, rb_encoding *enc)
Queries the code point of character pointed by the passed pointer.
VALUE rb_enc_uint_chr(unsigned int code, rb_encoding *enc)
Encodes the passed code point into a series of bytes.
VALUE rb_enc_str_new(const char *ptr, long len, rb_encoding *enc)
Identical to rb_str_new(), except it additionally takes an encoding.
long rb_str_coderange_scan_restartable(const char *str, const char *end, rb_encoding *enc, int *cr)
Scans the passed string until it finds something odd.
int rb_econv_prepare_options(VALUE opthash, VALUE *ecopts, int ecflags)
Identical to rb_econv_prepare_opts(), except it additionally takes the initial value of flags.
VALUE rb_econv_open_exc(const char *senc, const char *denc, int ecflags)
Creates a rb_eConverterNotFoundError exception object (but does not raise).
rb_econv_result_t rb_econv_convert(rb_econv_t *ec, const unsigned char **source_buffer_ptr, const unsigned char *source_buffer_end, unsigned char **destination_buffer_ptr, unsigned char *destination_buffer_end, int flags)
Converts a string from an encoding to another.
rb_econv_result_t
return value of rb_econv_convert()
@ econv_incomplete_input
The conversion stopped in middle of reading a character, possibly due to a partial read of a socket e...
@ econv_finished
The conversion stopped after converting everything.
@ econv_undefined_conversion
The conversion stopped when it found a character in the input which cannot be representable in the ou...
@ econv_source_buffer_empty
The conversion stopped because there is no input.
@ econv_destination_buffer_full
The conversion stopped because there is no destination.
@ econv_invalid_byte_sequence
The conversion stopped when it found an invalid sequence.
int rb_econv_putbackable(rb_econv_t *ec)
Queries if rb_econv_putback() makes sense, i.e.
VALUE rb_econv_str_convert(rb_econv_t *ec, VALUE src, int flags)
Identical to rb_econv_convert(), except it takes Ruby's string instead of C's pointer.
void rb_econv_binmode(rb_econv_t *ec)
This badly named function does not set the destination encoding to binary, but instead just nullifies...
VALUE rb_str_encode(VALUE str, VALUE to, int ecflags, VALUE ecopts)
Converts the contents of the passed string from its encoding to the passed one.
VALUE rb_econv_make_exception(rb_econv_t *ec)
This function makes sense right after rb_econv_convert() returns.
void rb_econv_check_error(rb_econv_t *ec)
This is a rb_econv_make_exception() + rb_exc_raise() combo.
const char * rb_econv_asciicompat_encoding(const char *encname)
Queries the passed encoding's corresponding ASCII compatible encoding.
rb_econv_t * rb_econv_open_opts(const char *source_encoding, const char *destination_encoding, int ecflags, VALUE ecopts)
Identical to rb_econv_open(), except it additionally takes a hash of optional strings.
void rb_econv_close(rb_econv_t *ec)
Destructs a converter.
void rb_econv_putback(rb_econv_t *ec, unsigned char *p, int n)
Puts back the bytes.
VALUE rb_funcall(VALUE recv, ID mid, int n,...)
Calls a method.
VALUE rb_funcallv_kw(VALUE recv, ID mid, int argc, const VALUE *argv, int kw_splat)
Identical to rb_funcallv(), except you can specify how to handle the last element of the given array.
VALUE rb_funcallv(VALUE recv, ID mid, int argc, const VALUE *argv)
Identical to rb_funcall(), except it takes the method arguments as a C array.
void rb_gc_mark(VALUE obj)
Marks an object.
void rb_gc(void)
Triggers a GC process.
void rb_global_variable(VALUE *)
An alias for rb_gc_register_address().
Defines RBIMPL_HAS_BUILTIN.
VALUE rb_ary_concat(VALUE lhs, VALUE rhs)
Destructively appends the contents of latter into the end of former.
VALUE rb_ary_shift(VALUE ary)
Destructively deletes an element from the beginning of the passed array and returns what was deleted.
VALUE rb_check_array_type(VALUE obj)
Try converting an object to its array representation using its to_ary method, if any.
VALUE rb_ary_new(void)
Allocates a new, empty array.
VALUE rb_ary_push(VALUE ary, VALUE elem)
Special case of rb_ary_cat() that it adds only one element.
VALUE rb_ary_entry(VALUE ary, long off)
Queries an element of an array.
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Identical to rb_ary_new_from_values(), except it expects exactly two parameters.
#define RETURN_ENUMERATOR(obj, argc, argv)
Identical to RETURN_SIZED_ENUMERATOR(), except its size is unknown.
static int rb_check_arity(int argc, int min, int max)
Ensures that the passed integer is in the passed range.
ID rb_frame_this_func(void)
Queries the name of the Ruby level method that is calling this function.
void rb_jump_tag(int state)
This function is to re-throw global escapes.
VALUE rb_str_encode_ospath(VALUE path)
Converts a string into an "OS Path" encoding, if any.
VALUE rb_check_hash_type(VALUE obj)
Try converting an object to its hash representation using its to_hash method, if any.
VALUE rb_hash_lookup2(VALUE hash, VALUE key, VALUE def)
Identical to rb_hash_lookup(), except you can specify what to return on misshits.
VALUE rb_hash_aref(VALUE hash, VALUE key)
Queries the given key in the given hash table.
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
Inserts or replaces ("upsert"s) the objects into the given hash table.
VALUE rb_hash_lookup(VALUE hash, VALUE key)
Identical to rb_hash_aref(), except it always returns RUBY_Qnil for misshits.
VALUE rb_hash_dup(VALUE hash)
Duplicates a hash.
VALUE rb_hash_new(void)
Creates a new, empty hash object.
VALUE rb_io_printf(int argc, const VALUE *argv, VALUE io)
This is a rb_f_sprintf() + rb_io_write() combo.
VALUE rb_io_gets(VALUE io)
Reads a "line" from the given IO.
int rb_cloexec_pipe(int fildes[2])
Opens a pipe with closing on exec.
VALUE rb_rs
The record separator character for inputs, or the $/.
VALUE rb_io_print(int argc, const VALUE *argv, VALUE io)
Iterates over the passed array to apply rb_io_write() individually.
VALUE rb_io_addstr(VALUE io, VALUE str)
Identical to rb_io_write(), except it always returns the passed IO.
void rb_write_error(const char *str)
Writes the given error message to somewhere applicable.
VALUE rb_io_ungetbyte(VALUE io, VALUE b)
Identical to rb_io_ungetc(), except it doesn't take the encoding of the passed IO into account.
VALUE rb_io_getbyte(VALUE io)
Reads a byte from the given IO.
VALUE rb_io_puts(int argc, const VALUE *argv, VALUE io)
Iterates over the passed array to apply rb_io_write() individually.
int rb_cloexec_dup2(int oldfd, int newfd)
Identical to rb_cloexec_dup(), except you can specify the destination file descriptor.
VALUE rb_io_fdopen(int fd, int flags, const char *path)
Creates an IO instance whose backend is the given file descriptor.
void rb_update_max_fd(int fd)
Informs the interpreter that the passed fd can be the max.
VALUE rb_io_write(VALUE io, VALUE str)
Writes the given string to the given IO.
int rb_cloexec_open(const char *pathname, int flags, mode_t mode)
Opens a file that closes on exec.
VALUE rb_output_rs
The record separator character for outputs, or the $\.
VALUE rb_io_eof(VALUE io)
Queries if the passed IO is at the end of file.
void rb_write_error2(const char *str, long len)
Identical to rb_write_error(), except it additionally takes the message's length.
void rb_close_before_exec(int lowfd, int maxhint, VALUE noclose_fds)
Closes everything.
int rb_reserved_fd_p(int fd)
Queries if the given FD is reserved or not.
void rb_fd_fix_cloexec(int fd)
Sets or clears the close-on-exec flag of the passed file descriptor to the desired state.
VALUE rb_io_flush(VALUE io)
Flushes any buffered data within the passed IO to the underlying operating system.
VALUE rb_io_ascii8bit_binmode(VALUE io)
Forces no conversions be applied to the passed IO.
VALUE rb_io_binmode(VALUE io)
Sets the binmode.
VALUE rb_io_ungetc(VALUE io, VALUE c)
"Unget"s a string.
int rb_pipe(int *pipes)
This is an rb_cloexec_pipe() + rb_update_max_fd() combo.
VALUE rb_gets(void)
Much like rb_io_gets(), but it reads from the mysterious ARGF object.
int rb_cloexec_fcntl_dupfd(int fd, int minfd)
Duplicates a file descriptor with closing on exec.
VALUE rb_output_fs
The field separator character for outputs, or the $,.
VALUE rb_file_open_str(VALUE fname, const char *fmode)
Identical to rb_file_open(), except it takes the pathname as a Ruby's string instead of C's.
int rb_cloexec_dup(int oldfd)
Identical to rb_cloexec_fcntl_dupfd(), except it implies minfd is 3.
VALUE rb_file_open(const char *fname, const char *fmode)
Opens a file located at the given path.
VALUE rb_io_close(VALUE io)
Closes the IO.
VALUE rb_default_rs
This is the default value of rb_rs, i.e.
void rb_lastline_set(VALUE str)
Updates $_.
VALUE rb_lastline_get(void)
Queries the last line, or the $_.
int rb_obj_method_arity(VALUE obj, ID mid)
Identical to rb_mod_method_arity(), except it searches for singleton methods rather than instance met...
VALUE rb_protect(VALUE(*func)(VALUE args), VALUE args, int *state)
Protects a function call from potential global escapes from the function.
rb_pid_t rb_waitpid(rb_pid_t pid, int *status, int flags)
Waits for a process, with releasing GVL.
void rb_last_status_set(int status, rb_pid_t pid)
Sets the "last status", or the $?.
VALUE rb_str_append(VALUE dst, VALUE src)
Identical to rb_str_buf_append(), except it converts the right hand side before concatenating.
VALUE rb_str_buf_cat(VALUE, const char *, long)
Just another name of rb_str_cat.
size_t rb_str_capacity(VALUE str)
Queries the capacity of the given string.
VALUE rb_str_new_frozen(VALUE str)
Creates a frozen copy of the string, if necessary.
VALUE rb_str_cat2(VALUE, const char *)
Just another name of rb_str_cat_cstr.
VALUE rb_str_dup(VALUE str)
Duplicates a string.
void rb_str_modify(VALUE str)
Declares that the string is about to be modified.
VALUE rb_str_cat(VALUE dst, const char *src, long srclen)
Destructively appends the passed contents to the string.
VALUE rb_str_locktmp(VALUE str)
Obtains a "temporary lock" of the string.
VALUE rb_usascii_str_new(const char *ptr, long len)
Identical to rb_str_new(), except it generates a string of "US ASCII" encoding.
rb_gvar_setter_t rb_str_setter
This is a rb_gvar_setter_t that refutes non-string assignments.
void rb_str_set_len(VALUE str, long len)
Overwrites the length of the string.
VALUE rb_str_buf_cat_ascii(VALUE dst, const char *src)
Identical to rb_str_cat_cstr(), except it additionally assumes the source string be a NUL terminated ...
VALUE rb_str_new(const char *ptr, long len)
Allocates an instance of rb_cString.
VALUE rb_check_string_type(VALUE obj)
Try converting an object to its stringised representation using its to_str method,...
VALUE rb_str_substr(VALUE str, long beg, long len)
This is the implementation of two-argumented String#slice.
VALUE rb_str_unlocktmp(VALUE str)
Releases a lock formerly obtained by rb_str_locktmp().
VALUE rb_str_new_cstr(const char *ptr)
Identical to rb_str_new(), except it assumes the passed pointer is a pointer to a C string.
VALUE rb_str_resize(VALUE str, long len)
Overwrites the length of the string.
void rb_str_modify_expand(VALUE str, long capa)
Identical to rb_str_modify(), except it additionally expands the capacity of the receiver.
VALUE rb_str_buf_new(long capa)
Allocates a "string buffer".
VALUE rb_obj_as_string(VALUE obj)
Try converting an object to its stringised representation using its to_s method, if any.
int rb_thread_interrupted(VALUE thval)
Checks if the thread's execution was recently interrupted.
VALUE rb_mutex_new(void)
Creates a mutex.
int rb_thread_fd_writable(int fd)
Identical to rb_thread_wait_fd(), except it blocks the current thread until the given file descriptor...
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_sleep(int sec)
Blocks for the given period of time.
struct timeval rb_time_interval(VALUE num)
Creates a "time interval".
VALUE rb_attr_get(VALUE obj, ID name)
Identical to rb_ivar_get()
void rb_set_class_path(VALUE klass, VALUE space, const char *name)
Names a class.
VALUE rb_ivar_set(VALUE obj, ID name, VALUE val)
Identical to rb_iv_set(), except it accepts the name as an ID instead of a C string.
VALUE rb_class_name(VALUE obj)
Queries the name of the given object's class.
int rb_respond_to(VALUE obj, ID mid)
Queries if the object responds to the method.
int rb_method_basic_definition_p(VALUE klass, ID mid)
Well...
VALUE rb_check_funcall(VALUE recv, ID mid, int argc, const VALUE *argv)
Identical to rb_funcallv(), except it returns RUBY_Qundef instead of raising rb_eNoMethodError.
void rb_define_alloc_func(VALUE klass, rb_alloc_func_t func)
Sets the allocator function of a class.
static ID rb_intern_const(const char *str)
This is a "tiny optimisation" over rb_intern().
const char * rb_id2name(ID id)
Retrieves the name mapped to the given id.
ID rb_intern(const char *name)
Finds or creates a symbol of the given name.
#define RB_ID2SYM
Just another name of rb_id2sym.
VALUE rb_id2str(ID id)
Identical to rb_id2name(), except it returns a Ruby's String instead of C's.
void rb_define_global_const(const char *name, VALUE val)
Identical to rb_define_const(), except it defines that of "global", i.e.
void rb_define_readonly_variable(const char *name, const VALUE *var)
Identical to rb_define_variable(), except it does not allow Ruby programs to assign values to such gl...
rb_gvar_setter_t rb_gvar_readonly_setter
This function just raises rb_eNameError.
void rb_define_virtual_variable(const char *name, rb_gvar_getter_t *getter, rb_gvar_setter_t *setter)
Defines a global variable that is purely function-backended.
void rb_define_const(VALUE klass, const char *name, VALUE val)
Defines a Ruby level constant under a namespace.
void rb_define_hooked_variable(const char *name, VALUE *var, rb_gvar_getter_t *getter, rb_gvar_setter_t *setter)
Identical to rb_define_virtual_variable(), but can also specify a storage.
#define FMODE_READABLE
The IO is opened for reading.
int rb_io_modestr_fmode(const char *modestr)
Maps a file mode string (that rb_file_open() takes) into a mixture of FMODE_ flags.
VALUE rb_io_get_io(VALUE io)
Identical to rb_io_check_io(), except it raises exceptions on conversion failures.
VALUE rb_io_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.
int rb_io_mode(VALUE io)
Get the mode of the IO.
rb_io_event
Type of events that an IO can wait.
@ RUBY_IO_READABLE
IO::READABLE
@ RUBY_IO_PRIORITY
IO::PRIORITY
@ RUBY_IO_WRITABLE
IO::WRITABLE
#define FMODE_READWRITE
The IO is opened for both read/write.
#define FMODE_EXTERNAL
This flag means that an IO object is wrapping an "external" file descriptor, which is owned by someth...
#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.
FILE * rb_io_stdio_file(rb_io_t *fptr)
Finds or creates a stdio's file structure from a Ruby's one.
int rb_wait_for_single_fd(int fd, int events, struct timeval *tv)
Blocks until the passed file descriptor is ready for the passed events.
int rb_io_descriptor(VALUE io)
Returns an integer representing the numeric file descriptor for io.
#define FMODE_WRITABLE
The IO is opened for writing.
#define FMODE_APPEND
The IO is opened for appending.
#define MakeOpenFile
This is an old name of RB_IO_OPEN.
#define FMODE_DUPLEX
Ruby eventually detects that the IO is bidirectional.
#define FMODE_BINMODE
The IO is in "binary mode".
int rb_io_maybe_wait_readable(int error, VALUE io, VALUE timeout)
Blocks until the passed IO is ready for reading, if that makes sense for the passed errno.
int capa
Designed capacity of the buffer.
#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.
char * ptr
Pointer to the underlying memory region, of at least capa bytes.
#define FMODE_SYNC
The IO is in "sync mode".
int off
Offset inside of ptr.
VALUE rb_io_path(VALUE io)
Returns the path for the given IO.
void rb_io_check_initialized(rb_io_t *fptr)
Asserts that the passed IO is initialised.
#define FMODE_EXCL
This flag amends the effect of FMODE_CREATE, so that if there already is a file at the given path the...
#define FMODE_TEXTMODE
The IO is in "text mode".
int rb_io_fptr_finalize(rb_io_t *fptr)
Destroys the given IO.
VALUE rb_io_check_io(VALUE io)
Try converting an object to its IO representation using its to_io method, if any.
VALUE rb_io_closed_p(VALUE io)
Returns whether or not the underlying IO is closed.
FILE * rb_fdopen(int fd, const char *modestr)
Identical to rb_io_stdio_file(), except it takes file descriptors instead of Ruby's IO.
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_open_descriptor(VALUE klass, int descriptor, int mode, VALUE path, VALUE timeout, struct rb_io_encoding *encoding)
Allocate a new IO object, with the given file descriptor.
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.
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.
int len
Length of the buffer.
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.
#define RB_NUM2INT
Just another name of rb_num2int_inline.
#define RB_INT2NUM
Just another name of rb_int2num_inline.
VALUE rb_f_sprintf(int argc, const VALUE *argv)
Identical to rb_str_format(), except how the arguments are arranged.
VALUE rb_sprintf(const char *fmt,...)
Ruby's extended sprintf(3).
VALUE rb_str_catf(VALUE dst, const char *fmt,...)
Identical to rb_sprintf(), except it renders the output to the specified object rather than creating ...
#define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)
Shim for block function parameters.
VALUE rb_yield_values2(int n, const VALUE *argv)
Identical to rb_yield_values(), except it takes the parameters as a C array instead of variadic argum...
VALUE rb_yield(VALUE val)
Yields the block.
int rb_fd_select(int nfds, rb_fdset_t *rfds, rb_fdset_t *wfds, rb_fdset_t *efds, struct timeval *timeout)
Waits for multiple file descriptors at once.
int rb_fd_isset(int fd, const rb_fdset_t *f)
Queries if the given FD is in the given set.
void rb_fd_term(rb_fdset_t *f)
Destroys the rb_fdset_t, releasing any memory and resources it used.
#define MEMZERO(p, type, n)
Handy macro to erase a region of memory.
#define RB_GC_GUARD(v)
Prevents premature destruction of local objects.
#define MEMMOVE(p1, p2, type, n)
Handy macro to call memmove.
#define NUM2MODET
Converts a C's mode_t into an instance of rb_cInteger.
#define PRI_OFFT_PREFIX
A rb_sprintf() format prefix to be used for an off_t parameter.
#define OFFT2NUM
Converts a C's off_t into an instance of rb_cInteger.
#define NUM2OFFT
Converts an instance of rb_cNumeric into C's off_t.
#define PIDT2NUM
Converts a C's pid_t into an instance of rb_cInteger.
#define rb_fd_init
Initialises the :given :rb_fdset_t.
#define rb_fd_set
Sets the given fd to the rb_fdset_t.
#define RARRAY_LEN
Just another name of rb_array_len.
static int RARRAY_LENINT(VALUE ary)
Identical to rb_array_len(), except it differs for the return type.
#define RARRAY_AREF(a, i)
#define RARRAY_CONST_PTR
Just another name of rb_array_const_ptr.
#define RFILE(obj)
Convenient casting macro.
#define StringValue(v)
Ensures that the parameter object is a String.
static char * RSTRING_END(VALUE str)
Queries the end of the contents pointer of the string.
static char * RSTRING_PTR(VALUE str)
Queries the contents pointer of the string.
#define RSTRING_GETMEM(str, ptrvar, lenvar)
Convenient macro to obtain the contents and length at once.
static long RSTRING_LEN(VALUE str)
Queries the length of the string.
#define StringValueCStr(v)
Identical to StringValuePtr, except it additionally checks for the contents for viability as a C stri...
#define RUBY_TYPED_DEFAULT_FREE
This is a value you can set to rb_data_type_struct::dfree.
#define TypedData_Make_Struct(klass, type, data_type, sval)
Identical to TypedData_Wrap_Struct, except it allocates a new data region internally instead of takin...
VALUE rb_get_argv(void)
Queries the arguments passed to the current process that you can access from Ruby as ARGV.
void rb_p(VALUE obj)
Inspects an object.
#define FilePathValue(v)
Ensures that the parameter object is a path.
#define errno
Ractor-aware version of errno.
#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_io_pread_memory(VALUE scheduler, VALUE io, rb_off_t from, void *base, size_t size, size_t length)
Non-blocking pread from the passed IO using a native buffer.
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_read_memory(VALUE scheduler, VALUE io, void *base, size_t size, size_t length)
Non-blocking read from the passed IO using a native buffer.
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_io_pwrite_memory(VALUE scheduler, VALUE io, rb_off_t from, const void *base, size_t size, size_t length)
Non-blocking pwrite to the passed IO using a native buffer.
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_write_memory(VALUE scheduler, VALUE io, const void *base, size_t size, size_t length)
Non-blocking write to the passed IO using a native buffer.
VALUE rb_fiber_scheduler_io_wait_writable(VALUE scheduler, VALUE io)
Non-blocking wait until the passed IO is ready for writing.
int rb_thread_fd_select(int nfds, rb_fdset_t *rfds, rb_fdset_t *wfds, rb_fdset_t *efds, struct timeval *timeout)
Waits for multiple file descriptors at once.
static bool RB_TEST(VALUE obj)
Emulates Ruby's "if" statement.
#define RTEST
This is an old name of RB_TEST.
#define _(args)
This was a transition path from K&R to ANSI.
This is the struct that holds necessary info for a struct.
The data structure which wraps the fd_set bitmap used by select(2).
Decomposed encoding flags (e.g.
VALUE ecopts
Flags as Ruby hash.
rb_encoding * enc2
External encoding.
rb_encoding * enc
Internal encoding.
char * ptr
Pointer to the underlying memory region, of at least capa bytes.
int off
Offset inside of ptr.
int len
Length of the buffer.
int capa
Designed capacity of the buffer.
Ruby's IO, metadata and buffers.
int mode
mode flags: FMODE_XXXs
rb_io_buffer_t wbuf
Write buffer.
void(* finalize)(struct rb_io *, int)
finalize proc
rb_econv_t * readconv
Encoding converter used when reading from this IO.
rb_econv_t * writeconv
Encoding converter used when writing to this IO.
struct rb_io_encoding encs
Decomposed encoding flags.
VALUE self
The IO's Ruby level counterpart.
VALUE write_lock
This is a Ruby level mutex.
VALUE timeout
The timeout associated with this IO when performing blocking operations.
FILE * stdio_file
stdio ptr for read/write, if available.
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.
int writeconv_initialized
Whether rb_io_t::writeconv is already set up.
rb_io_buffer_t rbuf
(Byte) read buffer.
int lineno
number of lines read
VALUE writeconv_asciicompat
This is, when set, an instance of rb_cString which holds the "common" encoding.
rb_io_buffer_t cbuf
rb_io_ungetc() destination.
rb_pid_t pid
child's pid (for pipes)
int writeconv_pre_ecflags
Value of ::rb_io_t::rb_io_enc_t::ecflags stored right before initialising rb_io_t::writeconv.
VALUE pathv
pathname for file
intptr_t SIGNED_VALUE
A signed integer type that has the same width with VALUE.
uintptr_t ID
Type that represents a Ruby identifier such as a variable name.
uintptr_t VALUE
Type that represents a Ruby object.
static bool RB_SYMBOL_P(VALUE obj)
Queries if the object is an instance of rb_cSymbol.
static void Check_Type(VALUE v, enum ruby_value_type t)
Identical to RB_TYPE_P(), except it raises exceptions on predication failure.
static bool RB_TYPE_P(VALUE obj, enum ruby_value_type t)
Queries if the given object is of given type.