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 *);
546 #define FMODE_SIGNAL_ON_EPIPE (1<<17)
548 #define fptr_signal_on_epipe(fptr) \
549 (((fptr)->mode & FMODE_SIGNAL_ON_EPIPE) != 0)
551 #define fptr_set_signal_on_epipe(fptr, flag) \
553 (fptr)->mode |= FMODE_SIGNAL_ON_EPIPE : \
554 (fptr)->mode &= ~FMODE_SIGNAL_ON_EPIPE)
556 extern ID ruby_static_id_signo;
558 NORETURN(
static void rb_sys_fail_on_write(
rb_io_t *fptr));
560 rb_sys_fail_on_write(
rb_io_t *fptr)
563 VALUE errinfo = rb_syserr_new_path(e, (fptr)->pathv);
565 if (fptr_signal_on_epipe(fptr) && (e == EPIPE)) {
577 #define NEED_NEWLINE_DECORATOR_ON_READ(fptr) ((fptr)->mode & FMODE_TEXTMODE)
578 #define NEED_NEWLINE_DECORATOR_ON_WRITE(fptr) ((fptr)->mode & FMODE_TEXTMODE)
579 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
580 # define RUBY_CRLF_ENVIRONMENT 1
582 # define RUBY_CRLF_ENVIRONMENT 0
585 #if RUBY_CRLF_ENVIRONMENT
587 # define DEFAULT_TEXTMODE FMODE_TEXTMODE
588 # define TEXTMODE_NEWLINE_DECORATOR_ON_WRITE ECONV_CRLF_NEWLINE_DECORATOR
596 #define NEED_READCONV(fptr) ((fptr)->encs.enc2 != NULL || (fptr)->encs.ecflags & ~ECONV_CRLF_NEWLINE_DECORATOR)
597 #define WRITECONV_MASK ( \
598 (ECONV_DECORATOR_MASK & ~ECONV_CRLF_NEWLINE_DECORATOR)|\
599 ECONV_STATEFUL_DECORATOR_MASK|\
601 #define NEED_WRITECONV(fptr) ( \
602 ((fptr)->encs.enc != NULL && (fptr)->encs.enc != rb_ascii8bit_encoding()) || \
603 ((fptr)->encs.ecflags & WRITECONV_MASK) || \
605 #define SET_BINARY_MODE(fptr) setmode((fptr)->fd, O_BINARY)
607 #define NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr) do {\
608 if (NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {\
609 if (((fptr)->mode & FMODE_READABLE) &&\
610 !((fptr)->encs.ecflags & ECONV_NEWLINE_DECORATOR_MASK)) {\
611 setmode((fptr)->fd, O_BINARY);\
614 setmode((fptr)->fd, O_TEXT);\
619 #define SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags) do {\
620 if ((enc2) && ((ecflags) & ECONV_DEFAULT_NEWLINE_DECORATOR)) {\
621 (ecflags) |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;\
645 if (!rb_w32_fd_is_text(fptr->
fd)) {
646 r = lseek(fptr->
fd, -fptr->
rbuf.
len, SEEK_CUR);
647 if (r < 0 &&
errno) {
658 pos = lseek(fptr->
fd, 0, SEEK_CUR);
659 if (pos < 0 &&
errno) {
666 extra_max = (long)(pos - fptr->
rbuf.
len);
674 for (i = 0; i < fptr->
rbuf.
len; i++) {
675 if (*p ==
'\n') newlines++;
676 if (extra_max == newlines)
break;
681 while (newlines >= 0) {
682 r = lseek(fptr->
fd, pos - fptr->
rbuf.
len - newlines, SEEK_SET);
683 if (newlines == 0)
break;
688 read_size = _read(fptr->
fd, buf, fptr->
rbuf.
len + newlines);
692 rb_syserr_fail_path(e, fptr->
pathv);
694 if (read_size == fptr->
rbuf.
len) {
695 lseek(fptr->
fd, r, SEEK_SET);
716 set_binary_mode_with_seek_cur(
rb_io_t *fptr)
718 if (!rb_w32_fd_is_text(fptr->
fd))
return O_BINARY;
721 return setmode(fptr->
fd, O_BINARY);
723 flush_before_seek(fptr);
724 return setmode(fptr->
fd, O_BINARY);
726 #define SET_BINARY_MODE_WITH_SEEK_CUR(fptr) set_binary_mode_with_seek_cur(fptr)
730 # define DEFAULT_TEXTMODE 0
731 #define NEED_READCONV(fptr) ((fptr)->encs.enc2 != NULL || NEED_NEWLINE_DECORATOR_ON_READ(fptr))
732 #define NEED_WRITECONV(fptr) ( \
733 ((fptr)->encs.enc != NULL && (fptr)->encs.enc != rb_ascii8bit_encoding()) || \
734 NEED_NEWLINE_DECORATOR_ON_WRITE(fptr) || \
735 ((fptr)->encs.ecflags & (ECONV_DECORATOR_MASK|ECONV_STATEFUL_DECORATOR_MASK)) || \
737 #define SET_BINARY_MODE(fptr) (void)(fptr)
738 #define NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr) (void)(fptr)
739 #define SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags) ((void)(enc2), (void)(ecflags))
740 #define SET_BINARY_MODE_WITH_SEEK_CUR(fptr) (void)(fptr)
743 #if !defined HAVE_SHUTDOWN && !defined shutdown
744 #define shutdown(a,b) 0
748 #define is_socket(fd, path) rb_w32_is_socket(fd)
749 #elif !defined(S_ISSOCK)
750 #define is_socket(fd, path) 0
753 is_socket(
int fd,
VALUE path)
756 if (fstat(fd, &sbuf) < 0)
757 rb_sys_fail_path(path);
758 return S_ISSOCK(sbuf.st_mode);
762 static const char closed_stream[] =
"closed stream";
765 io_fd_check_closed(
int fd)
798 io_fd_check_closed(fptr->
fd);
802 rb_io_get_fptr(
VALUE io)
812 return rb_convert_type_with_id(io,
T_FILE,
"IO", idTo_io);
818 return rb_check_convert_type_with_id(io,
T_FILE,
"IO", idTo_io);
836 rb_io_t *fptr = rb_io_get_fptr(io);
845 return write_io ? write_io :
Qnil;
858 rb_io_t *fptr = rb_io_get_fptr(
self);
888 if (
RTEST(timeout)) {
892 rb_io_t *fptr = rb_io_get_fptr(
self);
917 #if !RUBY_CRLF_ENVIRONMENT
927 r = lseek(fptr->
fd, -fptr->
rbuf.
len, SEEK_CUR);
928 if (r < 0 &&
errno) {
947 const int min_capa = IO_RBUF_CAPA_FOR(fptr);
950 #if SIZEOF_LONG > SIZEOF_INT
975 flush_before_seek(
rb_io_t *fptr)
977 if (io_fflush(fptr) < 0)
978 rb_sys_fail_on_write(fptr);
984 #define io_seek(fptr, ofs, whence) (errno = 0, lseek(flush_before_seek(fptr)->fd, (ofs), (whence)))
985 #define io_tell(fptr) lseek(flush_before_seek(fptr)->fd, 0, SEEK_CUR)
1001 if (io_fflush(fptr) < 0)
1002 rb_sys_fail_on_write(fptr);
1007 if (io_fflush(wfptr) < 0)
1008 rb_sys_fail_on_write(wfptr);
1016 if (READ_CHAR_PENDING(fptr)) {
1028 io_read_encoding(
rb_io_t *fptr)
1037 io_input_encoding(
rb_io_t *fptr)
1042 return io_read_encoding(fptr);
1058 rb_io_read_pending(
rb_io_t *fptr)
1061 if (READ_CHAR_PENDING(fptr))
1063 return READ_DATA_PENDING(fptr);
1069 if (!READ_DATA_PENDING(fptr)) {
1076 rb_gc_for_fd(
int err)
1078 if (err == EMFILE || err == ENFILE || err == ENOMEM) {
1088 #define TRY_WITH_GC(expr) \
1089 for (int first_errno, retried_errno = 0, retried = 0; \
1092 (!rb_gc_for_fd(first_errno = errno) || !(expr)) && \
1093 (retried_errno = errno, 1)); \
1094 (void)retried_errno, retried = 1)
1109 io_alloc(
VALUE klass)
1119 # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
1145 struct io_internal_writev_struct {
1152 const struct iovec *iov;
1157 static int nogvl_wait_for(
VALUE th,
rb_io_t *fptr,
short events,
struct timeval *timeout);
1165 io_internal_wait(
VALUE thread,
rb_io_t *fptr,
int error,
int events,
struct timeval *timeout)
1167 if (!timeout && rb_thread_mn_schedulable(thread)) {
1172 int ready = nogvl_wait_for(thread, fptr, events, timeout);
1177 else if (ready == 0) {
1187 internal_read_func(
void *
ptr)
1192 if (iis->timeout && !iis->nonblock) {
1193 if (io_internal_wait(iis->th, iis->fptr, 0, RB_WAITFD_IN, iis->timeout) == -1) {
1199 result = read(iis->fd, iis->buf, iis->capa);
1201 if (result < 0 && !iis->nonblock) {
1202 if (io_again_p(
errno)) {
1203 if (io_internal_wait(iis->th, iis->fptr,
errno, RB_WAITFD_IN, iis->timeout) == -1) {
1215 #if defined __APPLE__
1216 # define do_write_retry(code) do {result = code;} while (result == -1 && errno == EPROTOTYPE)
1218 # define do_write_retry(code) result = code
1222 internal_write_func(
void *
ptr)
1227 if (iis->timeout && !iis->nonblock) {
1228 if (io_internal_wait(iis->th, iis->fptr, 0, RB_WAITFD_OUT, iis->timeout) == -1) {
1234 do_write_retry(write(iis->fd, iis->buf, iis->capa));
1236 if (result < 0 && !iis->nonblock) {
1238 if (io_again_p(e)) {
1239 if (io_internal_wait(iis->th, iis->fptr,
errno, RB_WAITFD_OUT, iis->timeout) == -1) {
1253 internal_writev_func(
void *
ptr)
1255 struct io_internal_writev_struct *iis =
ptr;
1258 if (iis->timeout && !iis->nonblock) {
1259 if (io_internal_wait(iis->th, iis->fptr, 0, RB_WAITFD_OUT, iis->timeout) == -1) {
1265 do_write_retry(writev(iis->fd, iis->iov, iis->iovcnt));
1267 if (result < 0 && !iis->nonblock) {
1268 if (io_again_p(
errno)) {
1269 if (io_internal_wait(iis->th, iis->fptr,
errno, RB_WAITFD_OUT, iis->timeout) == -1) {
1283 rb_io_read_memory(
rb_io_t *fptr,
void *buf,
size_t count)
1286 if (scheduler !=
Qnil) {
1289 if (!UNDEF_P(result)) {
1305 struct timeval timeout_storage;
1309 iis.timeout = &timeout_storage;
1312 return (ssize_t)rb_io_blocking_region_wait(fptr, internal_read_func, &iis,
RUBY_IO_READABLE);
1316 rb_io_write_memory(
rb_io_t *fptr,
const void *buf,
size_t count)
1319 if (scheduler !=
Qnil) {
1322 if (!UNDEF_P(result)) {
1338 struct timeval timeout_storage;
1342 iis.timeout = &timeout_storage;
1345 return (ssize_t)rb_io_blocking_region_wait(fptr, internal_write_func, &iis,
RUBY_IO_WRITABLE);
1350 rb_writev_internal(
rb_io_t *fptr,
const struct iovec *iov,
int iovcnt)
1352 if (!iovcnt)
return 0;
1355 if (scheduler !=
Qnil) {
1359 if (!UNDEF_P(result)) {
1364 struct io_internal_writev_struct iis = {
1375 struct timeval timeout_storage;
1379 iis.timeout = &timeout_storage;
1382 return (ssize_t)rb_io_blocking_region_wait(fptr, internal_writev_func, &iis,
RUBY_IO_WRITABLE);
1387 io_flush_buffer_sync(
void *arg)
1409 io_flush_buffer_async(
VALUE arg)
1412 return rb_io_blocking_region_wait(fptr, io_flush_buffer_sync, fptr,
RUBY_IO_WRITABLE);
1416 io_flush_buffer(
rb_io_t *fptr)
1419 return (
int)io_flush_buffer_async((
VALUE)fptr);
1434 while (fptr->
wbuf.
len > 0 && io_flush_buffer(fptr) != 0) {
1449 if (scheduler !=
Qnil) {
1459 if (NIL_OR_UNDEF_P(timeout)) {
1463 if (timeout !=
Qnil) {
1468 int ready = rb_thread_wait_for_single_fd(fptr->
fd,
RB_NUM2INT(events), tv);
1492 io_wait_for_single_fd(
int fd,
int events,
struct timeval *timeout)
1496 if (scheduler !=
Qnil) {
1502 return rb_thread_wait_for_single_fd(fd, events, timeout);
1508 io_fd_check_closed(f);
1514 #if defined(ERESTART)
1521 #if EWOULDBLOCK != EAGAIN
1524 if (scheduler !=
Qnil) {
1542 io_fd_check_closed(f);
1548 #if defined(ERESTART)
1564 #if EWOULDBLOCK != EAGAIN
1567 if (scheduler !=
Qnil) {
1585 return io_wait_for_single_fd(fd, events, timeout);
1619 #if defined(ERESTART)
1629 #if EWOULDBLOCK != EAGAIN
1646 if (
RTEST(result)) {
1661 if (
RTEST(result)) {
1675 const char *senc, *denc;
1741 io_binwrite_string_internal(
rb_io_t *fptr,
const char *
ptr,
long length)
1744 struct iovec iov[2];
1747 iov[0].iov_len = fptr->
wbuf.
len;
1748 iov[1].iov_base = (
void*)
ptr;
1749 iov[1].iov_len = length;
1751 ssize_t result = rb_writev_internal(fptr, iov, 2);
1756 if (result >= fptr->
wbuf.
len) {
1764 fptr->
wbuf.
off += (int)result;
1765 fptr->
wbuf.
len -= (int)result;
1773 return rb_io_write_memory(fptr,
ptr, length);
1778 io_binwrite_string_internal(
rb_io_t *fptr,
const char *
ptr,
long length)
1780 long remaining = length;
1783 if (fptr->
wbuf.
len+length <= fptr->wbuf.capa) {
1790 fptr->
wbuf.
len += (int)length;
1797 if (io_fflush(fptr) < 0) {
1802 if (remaining == 0) {
1808 return rb_io_write_memory(fptr,
ptr, length);
1813 io_binwrite_string(
VALUE arg)
1817 const char *
ptr = p->ptr;
1818 size_t remaining = p->length;
1822 ssize_t result = io_binwrite_string_internal(p->fptr,
ptr, remaining);
1828 else if (result > 0) {
1829 if ((
size_t)result == remaining)
break;
1831 remaining -= result;
1847 io_allocate_write_buffer(
rb_io_t *fptr,
int sync)
1852 fptr->
wbuf.
capa = IO_WBUF_CAPA_MIN;
1863 io_binwrite_requires_flush_write(
rb_io_t *fptr,
long len,
int nosync)
1878 io_binwrite(
const char *
ptr,
long len,
rb_io_t *fptr,
int nosync)
1880 if (
len <= 0)
return len;
1885 io_allocate_write_buffer(fptr, !nosync);
1887 if (io_binwrite_requires_flush_write(fptr,
len, nosync)) {
1898 return io_binwrite_string((
VALUE)&arg);
1915 # define MODE_BTMODE(a,b,c) ((fmode & FMODE_BINMODE) ? (b) : \
1916 (fmode & FMODE_TEXTMODE) ? (c) : (a))
1918 #define MODE_BTXMODE(a, b, c, d, e, f) ((fmode & FMODE_EXCL) ? \
1919 MODE_BTMODE(d, e, f) : \
1920 MODE_BTMODE(a, b, c))
1925 if (NEED_WRITECONV(fptr)) {
1927 SET_BINARY_MODE(fptr);
1929 make_writeconv(fptr);
1932 #define fmode (fptr->mode)
1936 rb_raise(
rb_eArgError,
"ASCII incompatible string written for text mode IO without encoding conversion: %s",
1948 if (!
NIL_P(common_encoding)) {
1959 #if RUBY_CRLF_ENVIRONMENT
1960 #define fmode (fptr->mode)
1961 else if (MODE_BTMODE(DEFAULT_TEXTMODE,0,1)) {
1964 setmode(fptr->
fd, O_BINARY);
1967 setmode(fptr->
fd, O_TEXT);
1970 rb_raise(
rb_eArgError,
"ASCII incompatible string written for text mode IO without encoding conversion: %s",
1989 long len = rb_w32_write_console(str, fptr->
fd);
1994 str = do_writeconv(str, fptr, &converted);
1998 tmp = rb_str_tmp_frozen_no_embed_acquire(str);
2000 n = io_binwrite(
ptr,
len, fptr, nosync);
2001 rb_str_tmp_frozen_release(str, tmp);
2013 return (ssize_t)io_binwrite(buf, (
long)size, fptr, 0);
2023 io = GetWriteIO(io);
2038 n = io_fwrite(str, fptr, nosync);
2039 if (n < 0L) rb_sys_fail_on_write(fptr);
2045 struct binwritev_arg {
2053 io_binwritev_internal(
VALUE arg)
2055 struct binwritev_arg *p = (
struct binwritev_arg *)arg;
2057 size_t remaining = p->total;
2061 struct iovec *iov = p->iov;
2062 int iovcnt = p->iovcnt;
2065 long result = rb_writev_internal(fptr, iov, iovcnt);
2070 if (offset < (
size_t)fptr->
wbuf.
len) {
2075 offset -= (size_t)fptr->
wbuf.
len;
2081 if (offset == p->total) {
2085 while (result >= (ssize_t)iov->iov_len) {
2087 result -= iov->iov_len;
2097 iov->iov_base = (
char *)iov->iov_base + result;
2098 iov->iov_len -= result;
2112 io_binwritev(
struct iovec *iov,
int iovcnt,
rb_io_t *fptr)
2117 if (iovcnt == 0)
return 0;
2120 for (
int i = 1; i < iovcnt; i++) total += iov[i].iov_len;
2122 io_allocate_write_buffer(fptr, 1);
2128 if (offset + total <= (
size_t)fptr->
wbuf.
capa) {
2129 for (
int i = 1; i < iovcnt; i++) {
2130 memcpy(fptr->
wbuf.
ptr+offset, iov[i].iov_base, iov[i].iov_len);
2131 offset += iov[i].iov_len;
2140 iov[0].iov_len = fptr->
wbuf.
len;
2153 struct binwritev_arg arg;
2156 arg.iovcnt = iovcnt;
2163 return io_binwritev_internal((
VALUE)&arg);
2170 int i, converted, iovcnt = argc + 1;
2172 VALUE v1, v2, str, tmp, *tmp_array;
2178 for (i = 0; i < argc; i++) {
2181 str = do_writeconv(str, fptr, &converted);
2186 tmp = rb_str_tmp_frozen_acquire(str);
2194 n = io_binwritev(iov, iovcnt, fptr);
2197 for (i = 0; i < argc; i++) {
2198 rb_str_tmp_frozen_release(argv[i], tmp_array[i]);
2207 iovcnt_ok(
int iovcnt)
2210 return iovcnt < IOV_MAX;
2218 io_writev(
int argc,
const VALUE *argv,
VALUE io)
2225 io = GetWriteIO(io);
2238 for (i = 0; i < argc; i += cnt) {
2241 n = io_fwritev(cnt, &argv[i], fptr);
2252 rb_sys_fail_on_write(fptr);
2254 total = rb_fix_plus(
LONG2FIX(n), total);
2285 return io_writev(argc, argv, io);
2288 VALUE str = argv[0];
2289 return io_write(io, str, 0);
2300 rb_io_writev(
VALUE io,
int argc,
const VALUE *argv)
2305 char sep = RCLASS_SINGLETON_P(klass) ? (klass = io,
'.') :
'#';
2308 " which accepts just one argument",
2350 nogvl_fsync(
void *
ptr)
2355 if (GetFileType((HANDLE)rb_w32_get_osfhandle(fptr->
fd)) != FILE_TYPE_DISK)
2358 return (
VALUE)fsync(fptr->
fd);
2363 rb_io_flush_raw(
VALUE io,
int sync)
2371 io = GetWriteIO(io);
2375 if (io_fflush(fptr) < 0)
2376 rb_sys_fail_on_write(fptr);
2400 return rb_io_flush_raw(io, 1);
2420 rb_io_tell(
VALUE io)
2426 pos = io_tell(fptr);
2427 if (pos < 0 &&
errno) rb_sys_fail_path(fptr->
pathv);
2433 rb_io_seek(
VALUE io,
VALUE offset,
int whence)
2440 pos = io_seek(fptr, pos, whence);
2441 if (pos < 0 &&
errno) rb_sys_fail_path(fptr->
pathv);
2447 interpret_seek_whence(
VALUE vwhence)
2449 if (vwhence == sym_SET)
2451 if (vwhence == sym_CUR)
2453 if (vwhence == sym_END)
2456 if (vwhence == sym_DATA)
2460 if (vwhence == sym_HOLE)
2514 rb_io_seek_m(
int argc,
VALUE *argv,
VALUE io)
2516 VALUE offset, ptrname;
2517 int whence = SEEK_SET;
2519 if (
rb_scan_args(argc, argv,
"11", &offset, &ptrname) == 2) {
2520 whence = interpret_seek_whence(ptrname);
2523 return rb_io_seek(io, offset, whence);
2551 pos = io_seek(fptr, pos, SEEK_SET);
2552 if (pos < 0 &&
errno) rb_sys_fail_path(fptr->
pathv);
2557 static void clear_readconv(
rb_io_t *fptr);
2584 rb_io_rewind(
VALUE io)
2589 if (io_seek(fptr, 0L, 0) < 0 &&
errno) rb_sys_fail_path(fptr->
pathv);
2590 if (io == ARGF.current_file) {
2591 ARGF.lineno -= fptr->
lineno;
2595 clear_readconv(fptr);
2602 fptr_wait_readable(
rb_io_t *fptr)
2620 fptr->
rbuf.
capa = IO_RBUF_CAPA_FOR(fptr);
2631 if (fptr_wait_readable(fptr))
2640 rb_syserr_fail_path(e, path);
2694 if (READ_CHAR_PENDING(fptr))
return Qfalse;
2695 if (READ_DATA_PENDING(fptr))
return Qfalse;
2697 #if RUBY_CRLF_ENVIRONMENT
2698 if (!NEED_READCONV(fptr) && NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {
2699 return RBOOL(eof(fptr->
fd));
2702 return RBOOL(io_fillbuf(fptr) < 0);
2722 rb_io_sync(
VALUE io)
2726 io = GetWriteIO(io);
2763 io = GetWriteIO(io);
2793 rb_io_fsync(
VALUE io)
2797 io = GetWriteIO(io);
2800 if (io_fflush(fptr) < 0)
2801 rb_sys_fail_on_write(fptr);
2803 if ((
int)rb_io_blocking_region(fptr, nogvl_fsync, fptr))
2804 rb_sys_fail_path(fptr->
pathv);
2809 # define rb_io_fsync rb_f_notimplement
2810 # define rb_io_sync rb_f_notimplement
2819 #ifdef HAVE_FDATASYNC
2821 nogvl_fdatasync(
void *
ptr)
2826 if (GetFileType((HANDLE)rb_w32_get_osfhandle(fptr->
fd)) != FILE_TYPE_DISK)
2829 return (
VALUE)fdatasync(fptr->
fd);
2844 rb_io_fdatasync(
VALUE io)
2848 io = GetWriteIO(io);
2851 if (io_fflush(fptr) < 0)
2852 rb_sys_fail_on_write(fptr);
2854 if ((
int)rb_io_blocking_region(fptr, nogvl_fdatasync, fptr) == 0)
2858 return rb_io_fsync(io);
2861 #define rb_io_fdatasync rb_io_fsync
2879 rb_io_fileno(
VALUE io)
2899 if (!UNDEF_P(fileno)) {
2987 rb_io_inspect(
VALUE obj)
2991 static const char closed[] =
" (closed)";
2993 fptr =
RFILE(obj)->fptr;
3000 rb_str_cat(result, closed+1, strlen(closed)-1);
3024 rb_io_to_io(
VALUE io)
3035 n = READ_DATA_PENDING_COUNT(fptr);
3036 if (n <= 0)
return 0;
3037 if (n >
len) n = (int)
len;
3051 if (READ_DATA_PENDING(fptr) == 0) {
3055 c = rb_io_read_memory(fptr,
ptr+offset, n);
3058 if (fptr_wait_readable(fptr))
3063 if ((n -= c) <= 0)
break;
3069 c = read_buffered_data(
ptr+offset, n, fptr);
3072 if ((n -= c) <= 0)
break;
3075 if (io_fillbuf(fptr) < 0) {
3082 static int io_setstrbuf(
VALUE *str,
long len);
3091 bufread_call(
VALUE arg)
3094 p->len = io_bufread(p->str_ptr, p->len, p->fptr);
3099 io_fread(
VALUE str,
long offset,
long size,
rb_io_t *fptr)
3104 io_setstrbuf(&str, offset + size);
3108 rb_str_locktmp_ensure(str, bufread_call, (
VALUE)&arg);
3110 if (
len < 0) rb_sys_fail_path(fptr->
pathv);
3118 rb_off_t siz = READ_DATA_PENDING_COUNT(fptr);
3121 if (fstat(fptr->
fd, &st) == 0 && S_ISREG(st.st_mode)
3122 #
if defined(__HAIKU__)
3127 if (io_fflush(fptr) < 0)
3128 rb_sys_fail_on_write(fptr);
3129 pos = lseek(fptr->
fd, 0, SEEK_CUR);
3130 if (st.st_size >= pos && pos >= 0) {
3131 siz += st.st_size - pos;
3132 if (siz > LONG_MAX) {
3153 make_readconv(
rb_io_t *fptr,
int size)
3158 const char *sname, *dname;
3173 if (size < IO_CBUF_CAPA_MIN) size = IO_CBUF_CAPA_MIN;
3179 #define MORE_CHAR_SUSPENDED Qtrue
3180 #define MORE_CHAR_FINISHED Qnil
3182 fill_cbuf(
rb_io_t *fptr,
int ec_flags)
3184 const unsigned char *ss, *sp, *se;
3185 unsigned char *ds, *dp, *de;
3194 return MORE_CHAR_SUSPENDED;
3205 ss = sp = (
const unsigned char *)fptr->
rbuf.
ptr + fptr->
rbuf.
off;
3210 fptr->
rbuf.
off += (int)(sp - ss);
3211 fptr->
rbuf.
len -= (int)(sp - ss);
3212 fptr->
cbuf.
len += (int)(dp - ds);
3217 fptr->
rbuf.
off -= putbackable;
3218 fptr->
rbuf.
len += putbackable;
3225 if (cbuf_len0 != fptr->
cbuf.
len)
3226 return MORE_CHAR_SUSPENDED;
3229 return MORE_CHAR_FINISHED;
3235 if (io_fillbuf(fptr) < 0) {
3237 return MORE_CHAR_FINISHED;
3242 fptr->
cbuf.
len += (int)(dp - ds);
3249 if (cbuf_len0 != fptr->
cbuf.
len)
3250 return MORE_CHAR_SUSPENDED;
3252 return MORE_CHAR_FINISHED;
3260 if (v != MORE_CHAR_SUSPENDED && v != MORE_CHAR_FINISHED)
3318 #define MAX_REALLOC_GAP 4096
3320 io_shrink_read_string(
VALUE str,
long n)
3328 io_set_read_length(
VALUE str,
long n,
int shrinkable)
3333 if (shrinkable) io_shrink_read_string(str, n);
3347 if (NEED_READCONV(fptr)) {
3348 int first = !
NIL_P(str);
3349 SET_BINARY_MODE(fptr);
3350 shrinkable = io_setstrbuf(&str,0);
3351 make_readconv(fptr, 0);
3356 io_shift_cbuf(fptr, fptr->
cbuf.
len, &str);
3358 v = fill_cbuf(fptr, 0);
3359 if (v != MORE_CHAR_SUSPENDED && v != MORE_CHAR_FINISHED) {
3362 io_shift_cbuf(fptr, fptr->
cbuf.
len, &str);
3366 if (v == MORE_CHAR_FINISHED) {
3367 clear_readconv(fptr);
3369 if (shrinkable) io_shrink_read_string(str,
RSTRING_LEN(str));
3370 return io_enc_str(str, fptr);
3375 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
3379 enc = io_read_encoding(fptr);
3382 if (siz == 0) siz = BUFSIZ;
3383 shrinkable = io_setstrbuf(&str, siz);
3386 n = io_fread(str, bytes, siz - bytes, fptr);
3387 if (n == 0 && bytes == 0) {
3395 if (bytes < siz)
break;
3400 if (
capa < BUFSIZ) {
3403 else if (
capa > IO_MAX_BUFFER_GROWTH) {
3404 capa = IO_MAX_BUFFER_GROWTH;
3409 if (shrinkable) io_shrink_read_string(str,
RSTRING_LEN(str));
3410 str = io_enc_str(str, fptr);
3418 if (rb_fd_set_nonblock(fptr->
fd) != 0) {
3419 rb_sys_fail_path(fptr->
pathv);
3424 io_read_memory_call(
VALUE arg)
3429 if (scheduler !=
Qnil) {
3432 if (!UNDEF_P(result)) {
3438 if (iis->nonblock) {
3439 return rb_io_blocking_region(iis->fptr, internal_read_func, iis);
3442 return rb_io_blocking_region_wait(iis->fptr, internal_read_func, iis,
RUBY_IO_READABLE);
3449 return (
long)rb_str_locktmp_ensure(str, io_read_memory_call, (
VALUE)iis);
3452 #define no_exception_p(opts) !rb_opts_exception_p((opts), TRUE)
3455 io_getpartial(
int argc,
VALUE *argv,
VALUE io,
int no_exception,
int nonblock)
3469 shrinkable = io_setstrbuf(&str,
len);
3475 io_set_read_length(str, 0, shrinkable);
3487 io_setstrbuf(&str,
len);
3490 iis.nonblock = nonblock;
3495 n = io_read_memory_locktmp(str, &iis);
3498 if (!nonblock && fptr_wait_readable(fptr))
3500 if (nonblock && (io_again_p(e))) {
3502 return sym_wait_readable;
3505 e,
"read would block");
3507 rb_syserr_fail_path(e, fptr->
pathv);
3510 io_set_read_length(str, n, shrinkable);
3611 io_readpartial(
int argc,
VALUE *argv,
VALUE io)
3615 ret = io_getpartial(argc, argv, io,
Qnil, 0);
3622 io_nonblock_eof(
int no_exception)
3624 if (!no_exception) {
3643 shrinkable = io_setstrbuf(&str,
len);
3644 rb_bool_expected(ex,
"exception", TRUE);
3650 io_set_read_length(str, 0, shrinkable);
3656 rb_fd_set_nonblock(fptr->
fd);
3657 shrinkable |= io_setstrbuf(&str,
len);
3664 n = io_read_memory_locktmp(str, &iis);
3667 if (io_again_p(e)) {
3668 if (!ex)
return sym_wait_readable;
3670 e,
"read would block");
3672 rb_syserr_fail_path(e, fptr->
pathv);
3675 io_set_read_length(str, n, shrinkable);
3678 if (!ex)
return Qnil;
3694 rb_bool_expected(ex,
"exception", TRUE);
3696 io = GetWriteIO(io);
3700 if (io_fflush(fptr) < 0)
3701 rb_sys_fail_on_write(fptr);
3703 rb_fd_set_nonblock(fptr->
fd);
3709 if (io_again_p(e)) {
3711 return sym_wait_writable;
3717 rb_syserr_fail_path(e, fptr->
pathv);
3801 #if RUBY_CRLF_ENVIRONMENT
3807 if (
NIL_P(length)) {
3810 return read_all(fptr, remain_size(fptr), str);
3817 shrinkable = io_setstrbuf(&str,
len);
3822 io_set_read_length(str, 0, shrinkable);
3827 #if RUBY_CRLF_ENVIRONMENT
3828 previous_mode = set_binary_mode_with_seek_cur(fptr);
3830 n = io_fread(str, 0,
len, fptr);
3831 io_set_read_length(str, n, shrinkable);
3832 #if RUBY_CRLF_ENVIRONMENT
3833 if (previous_mode == O_TEXT) {
3834 setmode(fptr->
fd, O_TEXT);
3837 if (n == 0)
return Qnil;
3843 rscheck(
const char *rsptr,
long rslen,
VALUE rs)
3851 appendline(
rb_io_t *fptr,
int delim,
VALUE *strp,
long *lp)
3856 if (NEED_READCONV(fptr)) {
3857 SET_BINARY_MODE(fptr);
3858 make_readconv(fptr, 0);
3861 int searchlen = READ_CHAR_PENDING_COUNT(fptr);
3863 p = READ_CHAR_PENDING_PTR(fptr);
3864 if (0 < limit && limit < searchlen)
3865 searchlen = (int)limit;
3866 e = memchr(p, delim, searchlen);
3868 int len = (int)(e-p+1);
3893 }
while (more_char(fptr) != MORE_CHAR_FINISHED);
3894 clear_readconv(fptr);
3899 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
3901 long pending = READ_DATA_PENDING_COUNT(fptr);
3903 const char *p = READ_DATA_PENDING_PTR(fptr);
3907 if (limit > 0 && pending > limit) pending = limit;
3908 e = memchr(p, delim, pending);
3909 if (e) pending = e - p + 1;
3919 read_buffered_data(
RSTRING_PTR(str) + last, pending, fptr);
3922 if (e)
return delim;
3927 }
while (io_fillbuf(fptr) >= 0);
3933 swallow(
rb_io_t *fptr,
int term)
3935 if (NEED_READCONV(fptr)) {
3938 SET_BINARY_MODE(fptr);
3939 make_readconv(fptr, 0);
3942 while ((cnt = READ_CHAR_PENDING_COUNT(fptr)) > 0) {
3943 const char *p = READ_CHAR_PENDING_PTR(fptr);
3946 if (*p != term)
return TRUE;
3948 while (--i && *++p == term);
3951 const char *e = p + cnt;
3953 while ((p += i) < e &&
rb_enc_ascget(p, e, &i, enc) == term);
3956 io_shift_cbuf(fptr, (
int)cnt - i, NULL);
3958 }
while (more_char(fptr) != MORE_CHAR_FINISHED);
3962 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
3965 while ((cnt = READ_DATA_PENDING_COUNT(fptr)) > 0) {
3967 const char *p = READ_DATA_PENDING_PTR(fptr);
3969 if (cnt >
sizeof buf) cnt =
sizeof buf;
3970 if (*p != term)
return TRUE;
3972 while (--i && *++p == term);
3973 if (!read_buffered_data(buf, cnt - i, fptr))
3974 rb_sys_fail_path(fptr->
pathv);
3977 }
while (io_fillbuf(fptr) == 0);
3990 int pending = READ_DATA_PENDING_COUNT(fptr);
3993 const char *p = READ_DATA_PENDING_PTR(fptr);
3997 e = memchr(p,
'\n', pending);
3999 pending = (int)(e - p + 1);
4001 chomplen = (pending > 1 && *(e-1) ==
'\r') + 1;
4011 read_buffered_data(
RSTRING_PTR(str)+
len, pending - chomplen, fptr);
4014 if (pending == 1 && chomplen == 1 &&
len > 0) {
4021 len += pending - chomplen;
4027 }
while (io_fillbuf(fptr) >= 0);
4030 str = io_enc_str(str, fptr);
4041 unsigned int chomp: 1;
4055 chomp = (!UNDEF_P(vchomp)) &&
RTEST(vchomp);
4057 args->chomp = chomp;
4075 else if (2 <= argc) {
4076 rs = argv[0], lim = argv[1];
4085 check_getline_args(
VALUE *rsp,
long *limit,
VALUE io)
4095 enc_io = io_read_encoding(fptr);
4096 if (enc_io != enc_rs &&
4097 (!is_ascii_string(rs) ||
4117 argc =
rb_scan_args(argc, argv,
"02:", NULL, NULL, &opts);
4118 extract_getline_args(argc, argv, args);
4119 extract_getline_opts(opts, args);
4120 check_getline_args(&args->rs, &args->limit, io);
4124 rb_io_getline_0(
VALUE rs,
long limit,
int chomp,
rb_io_t *fptr)
4131 if (
NIL_P(rs) && limit < 0) {
4132 str = read_all(fptr, 0,
Qnil);
4135 else if (limit == 0) {
4138 else if (rs ==
rb_default_rs && limit < 0 && !NEED_READCONV(fptr) &&
4140 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
4141 return rb_io_getline_fast(fptr, enc, chomp);
4144 int c, newline = -1;
4145 const char *rsptr = 0;
4148 int extra_limit = 16;
4149 int chomp_cr = chomp;
4151 SET_BINARY_MODE(fptr);
4152 enc = io_read_encoding(fptr);
4160 swallow(fptr,
'\n');
4173 newline = (
unsigned char)rsptr[rslen - 1];
4174 chomp_cr = chomp && rslen == 1 && newline ==
'\n';
4178 while ((c = appendline(fptr, newline, &str, &limit)) != EOF) {
4179 const char *s, *p, *pp, *e;
4186 if (!at_char_boundary(s, p, e, enc))
continue;
4187 if (!rspara) rscheck(rsptr, rslen, rs);
4188 if (memcmp(p, rsptr, rslen) == 0) {
4190 if (chomp_cr && p > s && *(p-1) ==
'\r') --p;
4214 if (rspara && c != EOF)
4215 swallow(fptr,
'\n');
4217 str = io_enc_str(str, fptr);
4220 if (!
NIL_P(str) && !nolimit) {
4228 rb_io_getline_1(
VALUE rs,
long limit,
int chomp,
VALUE io)
4231 int old_lineno, new_lineno;
4235 old_lineno = fptr->
lineno;
4236 str = rb_io_getline_0(rs, limit, chomp, fptr);
4237 if (!
NIL_P(str) && (new_lineno = fptr->
lineno) != old_lineno) {
4238 if (io == ARGF.current_file) {
4239 ARGF.lineno += new_lineno - old_lineno;
4240 ARGF.last_lineno = ARGF.lineno;
4243 ARGF.last_lineno = new_lineno;
4251 rb_io_getline(
int argc,
VALUE *argv,
VALUE io)
4255 prepare_getline_args(argc, argv, &args, io);
4256 return rb_io_getline_1(args.rs, args.limit, args.chomp, io);
4266 rb_io_gets_internal(
VALUE io)
4346 rb_io_gets_m(
int argc,
VALUE *argv,
VALUE io)
4350 str = rb_io_getline(argc, argv, io);
4366 rb_io_lineno(
VALUE io)
4421 check_getline_args(&sep, &limit, io);
4423 VALUE line = rb_io_getline_1(sep, limit,
RTEST(chomp), io);
4424 rb_lastline_set_up(line, 1);
4499 rb_io_readlines(
int argc,
VALUE *argv,
VALUE io)
4503 prepare_getline_args(argc, argv, &args, io);
4504 return io_readlines(&args, io);
4512 if (arg->limit == 0)
4515 while (!
NIL_P(line = rb_io_getline_1(arg->rs, arg->limit, arg->chomp, io))) {
4628 rb_io_each_line(
int argc,
VALUE *argv,
VALUE io)
4634 prepare_getline_args(argc, argv, &args, io);
4635 if (args.limit == 0)
4637 while (!
NIL_P(str = rb_io_getline_1(args.rs, args.limit, args.chomp, io))) {
4664 rb_io_each_byte(
VALUE io)
4680 }
while (io_fillbuf(fptr) >= 0);
4690 if (NEED_READCONV(fptr)) {
4694 SET_BINARY_MODE(fptr);
4695 make_readconv(fptr, 0);
4709 if (more_char(fptr) == MORE_CHAR_FINISHED) {
4711 clear_readconv(fptr);
4718 if (fptr->
cbuf.
len == 0) clear_readconv(fptr);
4727 io_shift_cbuf(fptr, r, &str);
4738 str = io_enc_str(str, fptr);
4743 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
4744 if (io_fillbuf(fptr) < 0) {
4766 if (io_fillbuf(fptr) != -1) {
4786 str = io_enc_str(str, fptr);
4812 rb_io_each_char(
VALUE io)
4822 enc = io_input_encoding(fptr);
4824 while (!
NIL_P(c = io_getc(fptr, enc))) {
4850 rb_io_each_codepoint(
VALUE io)
4862 if (NEED_READCONV(fptr)) {
4863 SET_BINARY_MODE(fptr);
4866 make_readconv(fptr, 0);
4874 r = ONIGENC_CONSTRUCT_MBCLEN_CHARFOUND(1);
4881 if (more_char(fptr) == MORE_CHAR_FINISHED) {
4882 clear_readconv(fptr);
4909 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
4910 enc = io_input_encoding(fptr);
4911 while (io_fillbuf(fptr) >= 0) {
4926 char cbuf[8], *p = cbuf;
4928 if (more > numberof(cbuf))
goto invalid;
4930 if (more > numberof(cbuf))
goto invalid;
4931 while ((n = (
int)read_buffered_data(p, more, fptr)) > 0 &&
4932 (p += n, (more -= n) > 0)) {
4933 if (io_fillbuf(fptr) < 0)
goto invalid;
4934 if ((n = fptr->
rbuf.
len) > more) n = more;
4973 rb_io_getc(
VALUE io)
4981 enc = io_input_encoding(fptr);
4983 return io_getc(fptr, enc);
5006 rb_io_readchar(
VALUE io)
5008 VALUE c = rb_io_getc(io);
5051 if (io_fillbuf(fptr) < 0) {
5080 rb_io_readbyte(
VALUE io)
5141 unsigned char c =
NUM2INT(v) & 0xFF;
5147 io_ungetbyte(b, fptr);
5203 else if (RB_BIGNUM_TYPE_P(c)) {
5209 if (NEED_READCONV(fptr)) {
5210 SET_BINARY_MODE(fptr);
5212 #if SIZEOF_LONG > SIZEOF_INT
5216 make_readconv(fptr, (
int)
len);
5230 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
5231 io_ungetbyte(c, fptr);
5251 rb_io_isatty(
VALUE io)
5256 return RBOOL(isatty(fptr->
fd) != 0);
5259 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
5275 rb_io_close_on_exec_p(
VALUE io)
5281 write_io = GetWriteIO(io);
5282 if (io != write_io) {
5284 if (fptr && 0 <= (fd = fptr->
fd)) {
5285 if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->
pathv);
5286 if (!(ret & FD_CLOEXEC))
return Qfalse;
5291 if (fptr && 0 <= (fd = fptr->
fd)) {
5292 if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->
pathv);
5293 if (!(ret & FD_CLOEXEC))
return Qfalse;
5298 #define rb_io_close_on_exec_p rb_f_notimplement
5301 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
5325 int flag =
RTEST(arg) ? FD_CLOEXEC : 0;
5330 write_io = GetWriteIO(io);
5331 if (io != write_io) {
5333 if (fptr && 0 <= (fd = fptr->
fd)) {
5334 if ((ret = fcntl(fptr->
fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->
pathv);
5335 if ((ret & FD_CLOEXEC) != flag) {
5336 ret = (ret & ~FD_CLOEXEC) | flag;
5337 ret = fcntl(fd, F_SETFD, ret);
5338 if (ret != 0) rb_sys_fail_path(fptr->
pathv);
5345 if (fptr && 0 <= (fd = fptr->
fd)) {
5346 if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->
pathv);
5347 if ((ret & FD_CLOEXEC) != flag) {
5348 ret = (ret & ~FD_CLOEXEC) | flag;
5349 ret = fcntl(fd, F_SETFD, ret);
5350 if (ret != 0) rb_sys_fail_path(fptr->
pathv);
5356 #define rb_io_set_close_on_exec rb_f_notimplement
5359 #define RUBY_IO_EXTERNAL_P(f) ((f)->mode & FMODE_EXTERNAL)
5360 #define PREP_STDIO_NAME(f) (RSTRING_PTR((f)->pathv))
5363 finish_writeconv(
rb_io_t *fptr,
int noalloc)
5365 unsigned char *ds, *dp, *de;
5369 unsigned char buf[1024];
5374 de = buf +
sizeof(buf);
5377 size_t remaining = dp-ds;
5378 long result = rb_io_write_memory(fptr, ds, remaining);
5382 if ((
size_t)result == remaining)
break;
5405 if (io_fflush(fptr) < 0) {
5413 fptr->
wbuf.
len += (int)(dp - ds);
5429 finish_writeconv_sync(
VALUE arg)
5432 return finish_writeconv(p->fptr, p->noalloc);
5436 nogvl_close(
void *
ptr)
5440 return (
void*)(intptr_t)close(*fd);
5444 maygvl_close(
int fd,
int keepgvl)
5453 return IO_WITHOUT_GVL_INT(nogvl_close, &fd);
5457 nogvl_fclose(
void *
ptr)
5461 return (
void*)(intptr_t)fclose(file);
5465 maygvl_fclose(
FILE *file,
int keepgvl)
5468 return fclose(file);
5470 return IO_WITHOUT_GVL_INT(nogvl_fclose, file);
5474 static void clear_codeconv(
rb_io_t *fptr);
5477 fptr_finalize_flush(
rb_io_t *fptr,
int noraise,
int keepgvl,
5483 int mode = fptr->
mode;
5489 arg.noalloc = noraise;
5493 error = finish_writeconv(fptr, noraise);
5498 io_flush_buffer_sync(fptr);
5501 if (io_fflush(fptr) < 0 &&
NIL_P(error)) {
5509 if (RUBY_IO_EXTERNAL_P(fptr) || fd <= 2) {
5521 rb_notify_fd_close_wait(busy);
5533 if (!done && stdio_file) {
5535 if ((maygvl_fclose(stdio_file, noraise) < 0) &&
NIL_P(error)) {
5544 if (!done && fd >= 0) {
5550 if ((maygvl_close(fd, keepgvl) < 0) &&
NIL_P(error)) {
5559 if (!
NIL_P(error) && !noraise) {
5568 fptr_finalize(
rb_io_t *fptr,
int noraise)
5570 fptr_finalize_flush(fptr, noraise, FALSE, 0);
5571 free_io_buffer(&fptr->
rbuf);
5572 free_io_buffer(&fptr->
wbuf);
5573 clear_codeconv(fptr);
5577 rb_io_fptr_cleanup(
rb_io_t *fptr,
int noraise)
5583 fptr_finalize(fptr, noraise);
5591 ruby_sized_xfree(buf->
ptr, (
size_t)buf->
capa);
5603 free_io_buffer(&fptr->
cbuf);
5607 clear_writeconv(
rb_io_t *fptr)
5619 clear_readconv(fptr);
5620 clear_writeconv(fptr);
5624 rb_io_fptr_cleanup_all(
rb_io_t *fptr)
5628 rb_io_fptr_cleanup(fptr, TRUE);
5630 free_io_buffer(&fptr->
rbuf);
5631 free_io_buffer(&fptr->
wbuf);
5632 clear_codeconv(fptr);
5636 rb_io_fptr_finalize_internal(
void *
ptr)
5639 rb_io_fptr_cleanup_all(
ptr);
5643 #undef rb_io_fptr_finalize
5651 rb_io_fptr_finalize_internal(fptr);
5655 #define rb_io_fptr_finalize(fptr) rb_io_fptr_finalize_internal(fptr)
5658 rb_io_memsize(
const rb_io_t *fptr)
5660 size_t size =
sizeof(
rb_io_t);
5671 # define KEEPGVL TRUE
5673 # define KEEPGVL FALSE
5677 io_close_fptr(
VALUE io)
5684 write_io = GetWriteIO(io);
5685 if (io != write_io) {
5686 write_fptr =
RFILE(write_io)->fptr;
5687 if (write_fptr && 0 <= write_fptr->
fd) {
5688 rb_io_fptr_cleanup(write_fptr, TRUE);
5692 fptr =
RFILE(io)->fptr;
5693 if (!fptr)
return 0;
5694 if (fptr->
fd < 0)
return 0;
5696 if (rb_notify_fd_close(fptr->
fd, &busy)) {
5698 fptr_finalize_flush(fptr, FALSE, KEEPGVL, &busy);
5700 rb_io_fptr_cleanup(fptr, FALSE);
5705 fptr_waitpid(
rb_io_t *fptr,
int nohang)
5709 rb_last_status_clear();
5718 rb_io_t *fptr = io_close_fptr(io);
5719 if (fptr) fptr_waitpid(fptr, 0);
5759 rb_io_close_m(
VALUE io)
5761 rb_io_t *fptr = rb_io_get_fptr(io);
5770 io_call_close(
VALUE io)
5779 enum {mesg_len =
sizeof(closed_stream)-1};
5783 memcmp(
RSTRING_PTR(mesg), closed_stream, mesg_len)) {
5793 if (!UNDEF_P(closed) &&
RTEST(closed))
return io;
5794 rb_rescue2(io_call_close, io, ignore_closed_stream, io,
5830 write_io = GetWriteIO(io);
5831 if (io != write_io) {
5832 write_fptr =
RFILE(write_io)->fptr;
5833 if (write_fptr && 0 <= write_fptr->
fd) {
5838 fptr = rb_io_get_fptr(io);
5839 return RBOOL(0 > fptr->
fd);
5875 rb_io_close_read(
VALUE io)
5881 if (fptr->
fd < 0)
return Qnil;
5882 if (is_socket(fptr->
fd, fptr->
pathv)) {
5886 if (shutdown(fptr->
fd, SHUT_RD) < 0)
5887 rb_sys_fail_path(fptr->
pathv);
5894 write_io = GetWriteIO(io);
5895 if (io != write_io) {
5900 RFILE(io)->fptr = wfptr;
5903 RFILE(write_io)->fptr = fptr;
5904 rb_io_fptr_cleanup(fptr, FALSE);
5948 rb_io_close_write(
VALUE io)
5953 write_io = GetWriteIO(io);
5955 if (fptr->
fd < 0)
return Qnil;
5956 if (is_socket(fptr->
fd, fptr->
pathv)) {
5960 if (shutdown(fptr->
fd, SHUT_WR) < 0)
5961 rb_sys_fail_path(fptr->
pathv);
5972 if (io != write_io) {
5992 rb_io_sysseek(
int argc,
VALUE *argv,
VALUE io)
5994 VALUE offset, ptrname;
5995 int whence = SEEK_SET;
5999 if (
rb_scan_args(argc, argv,
"11", &offset, &ptrname) == 2) {
6000 whence = interpret_seek_whence(ptrname);
6005 (READ_DATA_BUFFERED(fptr) || READ_CHAR_PENDING(fptr))) {
6009 rb_warn(
"sysseek for buffered IO");
6012 pos = lseek(fptr->
fd, pos, whence);
6013 if (pos < 0 &&
errno) rb_sys_fail_path(fptr->
pathv);
6047 io = GetWriteIO(io);
6052 rb_warn(
"syswrite for buffered IO");
6055 tmp = rb_str_tmp_frozen_acquire(str);
6057 n = rb_io_write_memory(fptr,
ptr,
len);
6058 if (n < 0) rb_sys_fail_path(fptr->
pathv);
6059 rb_str_tmp_frozen_release(str, tmp);
6076 rb_io_sysread(
int argc,
VALUE *argv,
VALUE io)
6087 shrinkable = io_setstrbuf(&str, ilen);
6088 if (ilen == 0)
return str;
6093 if (READ_DATA_BUFFERED(fptr)) {
6099 io_setstrbuf(&str, ilen);
6107 n = io_read_memory_locktmp(str, &iis);
6110 rb_sys_fail_path(fptr->
pathv);
6113 io_set_read_length(str, n, shrinkable);
6115 if (n == 0 && ilen > 0) {
6131 internal_pread_func(
void *_arg)
6135 return (
VALUE)pread(arg->fd, arg->buf, arg->count, arg->offset);
6139 pread_internal_call(
VALUE _arg)
6144 if (scheduler !=
Qnil) {
6147 if (!UNDEF_P(result)) {
6152 return rb_io_blocking_region_wait(arg->io, internal_pread_func, arg,
RUBY_IO_READABLE);
6196 shrinkable = io_setstrbuf(&str, (
long)arg.count);
6197 if (arg.count == 0)
return str;
6211 rb_sys_fail_path(fptr->
pathv);
6213 io_set_read_length(str, n, shrinkable);
6214 if (n == 0 && arg.count > 0) {
6222 internal_pwrite_func(
void *_arg)
6227 if (scheduler !=
Qnil) {
6230 if (!UNDEF_P(result)) {
6236 return (
VALUE)pwrite(arg->fd, arg->buf, arg->count, arg->offset);
6277 io = GetWriteIO(io);
6284 tmp = rb_str_tmp_frozen_acquire(str);
6288 n = (ssize_t)rb_io_blocking_region_wait(fptr, internal_pwrite_func, &arg,
RUBY_IO_WRITABLE);
6289 if (n < 0) rb_sys_fail_path(fptr->
pathv);
6290 rb_str_tmp_frozen_release(str, tmp);
6310 SET_BINARY_MODE_WITH_SEEK_CUR(fptr);
6313 setmode(fptr->
fd, O_BINARY);
6320 io_ascii8bit_binmode(
rb_io_t *fptr)
6332 SET_BINARY_MODE_WITH_SEEK_CUR(fptr);
6338 clear_codeconv(fptr);
6347 io_ascii8bit_binmode(fptr);
6364 rb_io_binmode_m(
VALUE io)
6370 write_io = GetWriteIO(io);
6385 rb_io_binmode_p(
VALUE io)
6393 rb_io_fmode_modestr(
int fmode)
6397 return MODE_BTMODE(
"a+",
"ab+",
"at+");
6399 return MODE_BTMODE(
"a",
"ab",
"at");
6405 return MODE_BTMODE(
"r",
"rb",
"rt");
6407 return MODE_BTXMODE(
"w",
"wb",
"wt",
"wx",
"wbx",
"wtx");
6410 return MODE_BTXMODE(
"w+",
"wb+",
"wt+",
"w+x",
"wb+x",
"wt+x");
6412 return MODE_BTMODE(
"r+",
"rb+",
"rt+");
6416 static const char bom_prefix[] =
"bom|";
6417 static const char utf_prefix[] =
"utf-";
6418 enum {bom_prefix_len = (int)
sizeof(bom_prefix) - 1};
6419 enum {utf_prefix_len = (int)
sizeof(utf_prefix) - 1};
6422 io_encname_bom_p(
const char *name,
long len)
6424 return len > bom_prefix_len &&
STRNCASECMP(name, bom_prefix, bom_prefix_len) == 0;
6431 const char *m = modestr, *p = NULL;
6459 if (modestr[0] !=
'w')
6467 if (io_encname_bom_p(m, p ? (
long)(p - m) : (
long)strlen(m)))
6485 rb_io_oflags_fmode(
int oflags)
6489 switch (oflags & O_ACCMODE) {
6501 if (oflags & O_APPEND) {
6504 if (oflags & O_TRUNC) {
6507 if (oflags & O_CREAT) {
6510 if (oflags & O_EXCL) {
6514 if (oflags & O_BINARY) {
6523 rb_io_fmode_oflags(
int fmode)
6567 rb_io_oflags_modestr(
int oflags)
6570 # define MODE_BINARY(a,b) ((oflags & O_BINARY) ? (b) : (a))
6572 # define MODE_BINARY(a,b) (a)
6575 if (oflags & O_EXCL) {
6578 accmode = oflags & (O_RDONLY|O_WRONLY|O_RDWR);
6579 if (oflags & O_APPEND) {
6580 if (accmode == O_WRONLY) {
6581 return MODE_BINARY(
"a",
"ab");
6583 if (accmode == O_RDWR) {
6584 return MODE_BINARY(
"a+",
"ab+");
6591 return MODE_BINARY(
"r",
"rb");
6593 return MODE_BINARY(
"w",
"wb");
6595 if (oflags & O_TRUNC) {
6596 return MODE_BINARY(
"w+",
"wb+");
6598 return MODE_BINARY(
"r+",
"rb+");
6610 int default_ext = 0;
6616 if (rb_is_ascii8bit_enc(ext)) {
6620 else if (intern == NULL) {
6626 *enc = (default_ext && intern != ext) ? NULL : ext;
6636 unsupported_encoding(
const char *name,
rb_encoding *enc)
6638 rb_enc_warn(enc,
"Unsupported encoding %s ignored", name);
6642 parse_mode_enc(
const char *estr,
rb_encoding *estr_enc,
6648 int fmode = fmode_p ? *fmode_p : 0;
6654 p = strrchr(estr,
':');
6655 len = p ? (p++ - estr) : (
long)strlen(estr);
6657 estr += bom_prefix_len;
6658 len -= bom_prefix_len;
6659 if (!
STRNCASECMP(estr, utf_prefix, utf_prefix_len)) {
6663 rb_enc_warn(estr_enc,
"BOM with non-UTF encoding %s is nonsense", estr);
6672 memcpy(encname, estr,
len);
6673 encname[
len] =
'\0';
6678 if (fmode_p) *fmode_p = fmode;
6684 unsupported_encoding(estr, estr_enc);
6690 if (*p ==
'-' && *(p+1) ==
'\0') {
6697 unsupported_encoding(p, estr_enc);
6706 rb_io_ext_int_to_encs(ext_enc, int_enc, enc_p, enc2_p, fmode);
6720 if (v !=
Qnil) encoding = v;
6722 if (v !=
Qnil) extenc = v;
6724 if (!UNDEF_P(v)) intenc = v;
6726 if ((!UNDEF_P(extenc) || !UNDEF_P(intenc)) && !
NIL_P(encoding)) {
6730 rb_warn(
"Ignoring encoding parameter '%"PRIsVALUE
"': %s_encoding is used",
6731 encoding, UNDEF_P(extenc) ?
"internal" :
"external");
6735 if (!UNDEF_P(extenc) && !
NIL_P(extenc)) {
6738 if (!UNDEF_P(intenc)) {
6739 if (
NIL_P(intenc)) {
6746 if (*p ==
'-' && *(p+1) ==
'\0') {
6757 if (extencoding == intencoding) {
6761 if (!
NIL_P(encoding)) {
6765 enc_p, enc2_p, fmode_p);
6768 rb_io_ext_int_to_encs(
rb_to_encoding(encoding), NULL, enc_p, enc2_p, 0);
6771 else if (!UNDEF_P(extenc) || !UNDEF_P(intenc)) {
6773 rb_io_ext_int_to_encs(extencoding, intencoding, enc_p, enc2_p, 0);
6781 int fmode = *fmode_p;
6797 #if !DEFAULT_TEXTMODE
6806 extract_binmode(
VALUE opthash,
int *fmode)
6808 if (!
NIL_P(opthash)) {
6836 int *oflags_p,
int *fmode_p,
struct rb_io_encoding *convconfig_p)
6843 int has_enc = 0, has_vmode = 0;
6849 rb_io_ext_int_to_encs(NULL, NULL, &enc, &enc2, 0);
6859 fmode = rb_io_oflags_fmode(oflags);
6867 oflags = rb_io_fmode_oflags(fmode);
6871 parse_mode_enc(p+1,
rb_enc_get(vmode), &enc, &enc2, &fmode);
6877 rb_io_ext_int_to_encs(e, NULL, &enc, &enc2, fmode);
6881 if (
NIL_P(opthash)) {
6885 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
6887 MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE,
6888 0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE) : 0;
6890 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
6899 #if DEFAULT_TEXTMODE
6900 else if (
NIL_P(vmode)) {
6901 fmode |= DEFAULT_TEXTMODE;
6910 if (!
NIL_P(vmode)) {
6923 fmode = rb_io_oflags_fmode(oflags);
6925 extract_binmode(opthash, &fmode);
6933 #if DEFAULT_TEXTMODE
6934 else if (
NIL_P(vmode)) {
6935 fmode |= DEFAULT_TEXTMODE;
6941 if (!
NIL_P(*vperm_p)) {
6953 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
6955 MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE,
6956 0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE) : 0;
6964 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
6968 validate_enc_binmode(&fmode, ecflags, enc, enc2);
6974 convconfig_p->
enc = enc;
6975 convconfig_p->
enc2 = enc2;
6976 convconfig_p->
ecflags = ecflags;
6977 convconfig_p->
ecopts = ecopts;
6987 sysopen_func(
void *
ptr)
6999 fd = IO_WITHOUT_GVL_INT(sysopen_func, data);
7000 }
while (fd < 0 &&
errno == EINTR);
7007 rb_sysopen(
VALUE fname,
int oflags, mode_t perm)
7014 data.oflags = oflags;
7017 TRY_WITH_GC((fd = rb_sysopen_internal(&data)) >= 0) {
7018 rb_syserr_fail_path(first_errno, fname);
7023 static inline FILE *
7024 fdopen_internal(
int fd,
const char *modestr)
7031 file = fdopen(fd, modestr);
7035 #elif defined(__sun)
7047 TRY_WITH_GC((file = fdopen_internal(fd, modestr)) != 0) {
7053 if (setvbuf(file, NULL, _IOFBF, 0) != 0)
7054 rb_warn(
"setvbuf() can't be honoured (fd=%d)", fd);
7062 int t = isatty(fptr->
fd);
7072 io_strip_bom(
VALUE io)
7074 VALUE b1, b2, b3, b4;
7095 return ENCINDEX_UTF_16BE;
7106 return ENCINDEX_UTF_32LE;
7111 return ENCINDEX_UTF_16LE;
7121 return ENCINDEX_UTF_32BE;
7135 io_set_encoding_by_bom(
VALUE io)
7137 int idx = io_strip_bom(io);
7145 rb_io_internal_encoding(io),
Qnil);
7154 rb_file_open_generic(
VALUE io,
VALUE filename,
int oflags,
int fmode,
7162 rb_io_ext_int_to_encs(NULL, NULL, &cc.enc, &cc.enc2, fmode);
7167 validate_enc_binmode(&fmode, convconfig->
ecflags,
7168 convconfig->
enc, convconfig->
enc2);
7172 fptr->
encs = *convconfig;
7175 if (!(oflags & O_TMPFILE)) {
7176 fptr->
pathv = pathv;
7179 fptr->
pathv = pathv;
7181 fptr->
fd = rb_sysopen(pathv, oflags, perm);
7189 rb_file_open_internal(
VALUE io,
VALUE filename,
const char *modestr)
7192 const char *p = strchr(modestr,
':');
7197 &convconfig.
enc, &convconfig.
enc2, &fmode);
7204 rb_io_ext_int_to_encs(e, NULL, &convconfig.
enc, &convconfig.
enc2, fmode);
7210 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
7212 MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE,
7213 0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE) : 0;
7215 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(convconfig.
enc2, convconfig.
ecflags);
7218 return rb_file_open_generic(io, filename,
7219 rb_io_fmode_oflags(fmode),
7229 return rb_file_open_internal(io_alloc(
rb_cFile), fname, modestr);
7238 #if defined(__CYGWIN__) || !defined(HAVE_WORKING_FORK)
7261 while ((tmp = *prev) != 0) {
7262 if (tmp->fptr == fptr) {
7271 #if defined (_WIN32) || defined(__CYGWIN__)
7287 pipe_finalize(
rb_io_t *fptr,
int noraise)
7289 #if !defined(HAVE_WORKING_FORK) && !defined(_WIN32)
7298 fptr_finalize(fptr, noraise);
7300 pipe_del_fptr(fptr);
7307 #if defined(__CYGWIN__) || !defined(HAVE_WORKING_FORK)
7308 void (*
const old_finalize)(
struct rb_io*,int) = fptr->
finalize;
7310 if (old_finalize == orig->
finalize)
return;
7315 #if defined(__CYGWIN__) || !defined(HAVE_WORKING_FORK)
7316 if (old_finalize != pipe_finalize) {
7318 for (list =
pipe_list; list; list = list->next) {
7319 if (list->fptr == fptr)
break;
7321 if (!list) pipe_add_fptr(fptr);
7324 pipe_del_fptr(fptr);
7337 rb_io_unbuffered(
rb_io_t *fptr)
7355 #define HAVE_SPAWNV 1
7356 #define spawnv(mode, cmd, args) rb_w32_uaspawn((mode), (cmd), (args))
7357 #define spawn(mode, cmd) rb_w32_uspawn((mode), (cmd), 0)
7360 #if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
7370 #ifdef HAVE_WORKING_FORK
7371 # ifndef __EMSCRIPTEN__
7373 popen_redirect(
struct popen_arg *p)
7376 close(p->write_pair[1]);
7377 if (p->write_pair[0] != 0) {
7378 dup2(p->write_pair[0], 0);
7379 close(p->write_pair[0]);
7382 if (p->pair[1] != 1) {
7383 dup2(p->pair[1], 1);
7389 if (p->pair[1] != 1) {
7390 dup2(p->pair[1], 1);
7396 if (p->pair[0] != 0) {
7397 dup2(p->pair[0], 0);
7404 #if defined(__linux__)
7415 linux_get_maxfd(
void)
7418 char buf[4096], *p, *np, *e;
7421 if (fd < 0)
return fd;
7422 ss = read(fd, buf,
sizeof(buf));
7423 if (ss < 0)
goto err;
7426 while ((
int)
sizeof(
"FDSize:\t0\n")-1 <= e-p &&
7427 (np = memchr(p,
'\n', e-p)) != NULL) {
7428 if (memcmp(p,
"FDSize:",
sizeof(
"FDSize:")-1) == 0) {
7430 p +=
sizeof(
"FDSize:")-1;
7450 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
7452 int max = (int)max_file_descriptor;
7455 ret = fcntl(0, F_MAXFD);
7457 maxhint = max = ret;
7458 # elif defined(__linux__)
7459 ret = linux_get_maxfd();
7466 for (fd = lowfd; fd <= max; fd++) {
7467 if (!
NIL_P(noclose_fds) &&
7470 ret = fcntl(fd, F_GETFD);
7471 if (ret != -1 && !(ret & FD_CLOEXEC)) {
7472 fcntl(fd, F_SETFD, ret|FD_CLOEXEC);
7474 # define CONTIGUOUS_CLOSED_FDS 20
7476 if (max < fd + CONTIGUOUS_CLOSED_FDS)
7477 max = fd + CONTIGUOUS_CLOSED_FDS;
7483 # ifndef __EMSCRIPTEN__
7485 popen_exec(
void *pp,
char *errmsg,
size_t errmsg_len)
7487 struct popen_arg *p = (
struct popen_arg*)pp;
7489 return rb_exec_async_signal_safe(p->eargp, errmsg, errmsg_len);
7494 #if (defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)) && !defined __EMSCRIPTEN__
7496 rb_execarg_fixup_v(
VALUE execarg_obj)
7498 rb_execarg_parent_start(execarg_obj);
7502 char *rb_execarg_commandline(
const struct rb_execarg *eargp,
VALUE *prog);
7505 #ifndef __EMSCRIPTEN__
7507 pipe_open(
VALUE execarg_obj,
const char *modestr,
int fmode,
7510 struct rb_execarg *eargp =
NIL_P(execarg_obj) ? NULL : rb_execarg_get(execarg_obj);
7511 VALUE prog = eargp ? (eargp->use_shell ? eargp->invoke.sh.shell_script : eargp->invoke.cmd.command_name) :
Qfalse ;
7517 #if defined(HAVE_WORKING_FORK)
7519 char errmsg[80] = {
'\0' };
7521 #if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
7523 struct popen_arg arg;
7526 #if defined(HAVE_SPAWNV)
7527 # if defined(HAVE_SPAWNVE)
7528 # define DO_SPAWN(cmd, args, envp) ((args) ? \
7529 spawnve(P_NOWAIT, (cmd), (args), (envp)) : \
7530 spawne(P_NOWAIT, (cmd), (envp)))
7532 # define DO_SPAWN(cmd, args, envp) ((args) ? \
7533 spawnv(P_NOWAIT, (cmd), (args)) : \
7534 spawn(P_NOWAIT, (cmd)))
7536 # if !defined(HAVE_WORKING_FORK)
7538 # if defined(HAVE_SPAWNVE)
7543 #if !defined(HAVE_WORKING_FORK)
7549 #if !defined(HAVE_WORKING_FORK)
7550 const char *cmd = 0;
7556 #if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
7557 arg.execarg_obj = execarg_obj;
7560 arg.pair[0] = arg.pair[1] = -1;
7561 arg.write_pair[0] = arg.write_pair[1] = -1;
7562 # if !defined(HAVE_WORKING_FORK)
7563 if (eargp && !eargp->use_shell) {
7564 args = ARGVSTR2ARGV(eargp->invoke.cmd.argv_str);
7569 if (
rb_pipe(arg.write_pair) < 0)
7573 close(arg.write_pair[0]);
7574 close(arg.write_pair[1]);
7578 rb_execarg_addopt(execarg_obj,
INT2FIX(0),
INT2FIX(arg.write_pair[0]));
7579 rb_execarg_addopt(execarg_obj,
INT2FIX(1),
INT2FIX(arg.pair[1]));
7586 rb_execarg_addopt(execarg_obj,
INT2FIX(1),
INT2FIX(arg.pair[1]));
7592 rb_execarg_addopt(execarg_obj,
INT2FIX(0),
INT2FIX(arg.pair[0]));
7597 if (!
NIL_P(execarg_obj)) {
7598 rb_protect(rb_execarg_fixup_v, execarg_obj, &state);
7600 if (0 <= arg.write_pair[0]) close(arg.write_pair[0]);
7601 if (0 <= arg.write_pair[1]) close(arg.write_pair[1]);
7602 if (0 <= arg.pair[0]) close(arg.pair[0]);
7603 if (0 <= arg.pair[1]) close(arg.pair[1]);
7604 rb_execarg_parent_end(execarg_obj);
7608 # if defined(HAVE_WORKING_FORK)
7609 pid = rb_fork_async_signal_safe(&status, popen_exec, &arg, arg.eargp->redirect_fds, errmsg,
sizeof(errmsg));
7611 rb_execarg_run_options(eargp, sargp, NULL, 0);
7612 # if defined(HAVE_SPAWNVE)
7613 if (eargp->envp_str) envp = (
char **)
RSTRING_PTR(eargp->envp_str);
7615 while ((pid = DO_SPAWN(cmd, args, envp)) < 0) {
7617 switch (e =
errno) {
7619 # if EWOULDBLOCK != EAGAIN
7628 rb_execarg_run_options(sargp, NULL, NULL, 0);
7630 rb_execarg_parent_end(execarg_obj);
7633 # if defined(HAVE_WORKING_FORK)
7634 pid = rb_call_proc__fork();
7636 popen_redirect(&arg);
7648 # if defined(HAVE_WORKING_FORK)
7654 close(arg.write_pair[0]);
7655 close(arg.write_pair[1]);
7657 # if defined(HAVE_WORKING_FORK)
7666 close(arg.write_pair[0]);
7667 write_fd = arg.write_pair[1];
7678 cmd = rb_execarg_commandline(eargp, &prog);
7679 if (!
NIL_P(execarg_obj)) {
7680 rb_execarg_parent_start(execarg_obj);
7681 rb_execarg_run_options(eargp, sargp, NULL, 0);
7683 fp = popen(cmd, modestr);
7686 rb_execarg_parent_end(execarg_obj);
7687 rb_execarg_run_options(sargp, NULL, NULL, 0);
7689 if (!fp) rb_syserr_fail_path(e, prog);
7699 fptr->
encs = *convconfig;
7700 #if RUBY_CRLF_ENVIRONMENT
7707 if (NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {
7710 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
7711 if (NEED_NEWLINE_DECORATOR_ON_WRITE(fptr)) {
7712 fptr->
encs.
ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
7718 if (0 <= write_fd) {
7719 write_port = io_alloc(
rb_cIO);
7721 write_fptr->
fd = write_fd;
7728 #if defined (__CYGWIN__) || !defined(HAVE_WORKING_FORK)
7730 pipe_add_fptr(fptr);
7736 pipe_open(
VALUE execarg_obj,
const char *modestr,
int fmode,
7744 is_popen_fork(
VALUE prog)
7747 #if !defined(HAVE_WORKING_FORK)
7749 "fork() function is unimplemented on this machine");
7758 pipe_open_s(
VALUE prog,
const char *modestr,
int fmode,
7762 VALUE *argv = &prog;
7765 if (!is_popen_fork(prog))
7766 execarg_obj = rb_execarg_new(argc, argv, TRUE, FALSE);
7767 return pipe_open(execarg_obj, modestr, fmode, convconfig);
7771 pipe_close(
VALUE io)
7773 rb_io_t *fptr = io_close_fptr(io);
7941 rb_io_s_popen(
int argc,
VALUE *argv,
VALUE klass)
7955 int ex = !
NIL_P(opt);
7956 rb_error_arity(argc + ex, 1 + ex, 2 + ex);
7959 return popen_finish(rb_io_popen(pname, pmode, env, opt), klass);
7965 const char *modestr;
7973 #if SIZEOF_LONG > SIZEOF_INT
7974 if (
len > INT_MAX) {
7984 if (!is_popen_fork(pname))
7985 execarg_obj = rb_execarg_new(1, &pname, TRUE, FALSE);
7987 if (!
NIL_P(execarg_obj)) {
7989 opt = rb_execarg_extract_options(execarg_obj, opt);
7991 rb_execarg_setenv(execarg_obj, env);
7994 modestr = rb_io_oflags_modestr(oflags);
7996 return pipe_open(execarg_obj, modestr, fmode, &convconfig);
8012 RBASIC_SET_CLASS(port, klass);
8019 #if defined(HAVE_WORKING_FORK) && !defined(__EMSCRIPTEN__)
8020 struct popen_writer_arg {
8022 struct popen_arg popen;
8026 exec_popen_writer(
void *arg,
char *errmsg,
size_t buflen)
8028 struct popen_writer_arg *pw = arg;
8030 popen_redirect(&pw->popen);
8031 execv(pw->argv[0], pw->argv);
8032 strlcpy(errmsg, strerror(
errno), buflen);
8038 ruby_popen_writer(
char *
const *argv, rb_pid_t *pid)
8040 #if (defined(HAVE_WORKING_FORK) && !defined(__EMSCRIPTEN__)) || defined(_WIN32)
8041 # ifdef HAVE_WORKING_FORK
8042 struct popen_writer_arg pw;
8043 int *
const write_pair = pw.popen.pair;
8051 # ifdef HAVE_WORKING_FORK
8054 char errmsg[80] = {
'\0'};
8055 *pid = rb_fork_async_signal_safe(&status, exec_popen_writer, &pw,
Qnil, errmsg,
sizeof(errmsg));
8057 *pid = rb_w32_uspawn_process(P_NOWAIT, argv[0], argv, write_pair[0], -1, -1, 0);
8058 const char *errmsg = (*pid < 0) ? strerror(
errno) : NULL;
8060 close(write_pair[0]);
8062 close(write_pair[1]);
8063 fprintf(stderr,
"ruby_popen_writer(%s): %s\n", argv[0], errmsg);
8066 return fdopen(write_pair[1],
"w");
8085 rb_file_open_generic(io, fname, oflags, fmode, &convconfig, perm);
8123 rb_io_s_open(
int argc,
VALUE *argv,
VALUE klass)
8155 VALUE fname, vmode, vperm;
8160 rb_scan_args(argc, argv,
"12", &fname, &vmode, &vperm);
8171 if (
NIL_P(vperm)) perm = 0666;
8175 fd = rb_sysopen(fname, oflags, perm);
8180 check_pipe_command(
VALUE filename_or_command)
8225 int redirect = FALSE;
8233 VALUE tmp = argv[0];
8239 VALUE cmd = check_pipe_command(tmp);
8242 rb_warn_deprecated_to_remove_at(4.0,
"Calling Kernel#open with a leading '|'",
"IO.popen");
8244 return rb_io_s_popen(argc, argv,
rb_cIO);
8257 return rb_io_s_open(argc, argv,
rb_cFile);
8271 return rb_io_open_generic(io, filename, oflags, fmode, &convconfig, perm);
8275 rb_io_open_generic(
VALUE klass,
VALUE filename,
int oflags,
int fmode,
8279 if (klass ==
rb_cIO && !
NIL_P(cmd = check_pipe_command(filename))) {
8281 rb_warn_deprecated_to_remove_at(4.0,
"IO process creation with a leading '|'",
"IO.popen");
8282 return pipe_open_s(cmd, rb_io_oflags_modestr(oflags), fmode, convconfig);
8285 return rb_file_open_generic(io_alloc(klass), filename,
8286 oflags, fmode, convconfig, perm);
8301 if (fptr == orig)
return io;
8302 if (RUBY_IO_EXTERNAL_P(fptr)) {
8307 "%s can't change access mode from \"%s\" to \"%s\"",
8308 PREP_STDIO_NAME(fptr), rb_io_fmode_modestr(fptr->
mode),
8309 rb_io_fmode_modestr(orig->
mode));
8313 if (io_fflush(fptr) < 0)
8314 rb_sys_fail_on_write(fptr);
8317 flush_before_seek(fptr);
8320 pos = io_tell(orig);
8323 if (io_fflush(orig) < 0)
8324 rb_sys_fail_on_write(fptr);
8332 else if (!RUBY_IO_EXTERNAL_P(fptr)) fptr->
pathv =
Qnil;
8333 fptr_copy_finalizer(fptr, orig);
8338 if (RUBY_IO_EXTERNAL_P(fptr) || fd <= 2 || !fptr->
stdio_file) {
8341 rb_sys_fail_path(orig->
pathv);
8349 rb_sys_fail_path(orig->
pathv);
8355 if (io_seek(fptr, pos, SEEK_SET) < 0 &&
errno) {
8356 rb_sys_fail_path(fptr->
pathv);
8358 if (io_seek(orig, pos, SEEK_SET) < 0 &&
errno) {
8359 rb_sys_fail_path(orig->
pathv);
8373 int rb_freopen(
VALUE fname,
const char *mode,
FILE *fp);
8376 rb_freopen(
VALUE fname,
const char *mode,
FILE *fp)
8421 rb_io_reopen(
int argc,
VALUE *argv,
VALUE file)
8423 VALUE fname, nmode, opt;
8427 if (
rb_scan_args(argc, argv,
"11:", &fname, &nmode, &opt) == 1) {
8430 return io_reopen(file, tmp);
8436 fptr =
RFILE(file)->fptr;
8446 if (RUBY_IO_EXTERNAL_P(fptr) &&
8450 "%s can't change access mode from \"%s\" to \"%s\"",
8451 PREP_STDIO_NAME(fptr), rb_io_fmode_modestr(fptr->
mode),
8452 rb_io_fmode_modestr(fmode));
8455 fptr->
encs = convconfig;
8458 oflags = rb_io_fmode_oflags(fptr->
mode);
8461 fptr->
pathv = fname;
8463 fptr->
fd = rb_sysopen(fptr->
pathv, oflags, 0666);
8469 if (io_fflush(fptr) < 0)
8470 rb_sys_fail_on_write(fptr);
8476 rb_io_oflags_modestr(oflags),
8478 if (e) rb_syserr_fail_path(e, fptr->
pathv);
8482 if (setvbuf(fptr->
stdio_file, NULL, _IOFBF, 0) != 0)
8483 rb_warn(
"setvbuf() can't be honoured for %"PRIsVALUE, fptr->
pathv);
8486 if (setvbuf(fptr->
stdio_file, NULL, _IONBF, BUFSIZ) != 0)
8487 rb_warn(
"setvbuf() can't be honoured for %"PRIsVALUE, fptr->
pathv);
8489 else if (fptr->
stdio_file == stdout && isatty(fptr->
fd)) {
8490 if (setvbuf(fptr->
stdio_file, NULL, _IOLBF, BUFSIZ) != 0)
8491 rb_warn(
"setvbuf() can't be honoured for %"PRIsVALUE, fptr->
pathv);
8495 int tmpfd = rb_sysopen(fptr->
pathv, oflags, 0666);
8501 rb_syserr_fail_path(err, fptr->
pathv);
8531 fptr_copy_finalizer(fptr, orig);
8533 fd = ruby_dup(orig->
fd);
8535 pos = io_tell(orig);
8537 io_seek(fptr, pos, SEEK_SET);
8542 write_io = GetWriteIO(io);
8543 if (io != write_io) {
8609 if (argc == 0)
return Qnil;
8628 rb_warn_deprecated(
"'%s'", NULL,
rb_id2name(
id));
8704 for (i=0; i<argc; i++) {
8809 #define forward(obj, id, argc, argv) \
8810 rb_funcallv_kw(obj, id, argc, argv, RB_PASS_CALLED_KEYWORDS)
8811 #define forward_public(obj, id, argc, argv) \
8812 rb_funcallv_public_kw(obj, id, argc, argv, RB_PASS_CALLED_KEYWORDS)
8813 #define forward_current(id, argc, argv) \
8814 forward_public(ARGF.current_file, id, argc, argv)
8832 if (recv == r_stdout) {
8833 return rb_io_putc(recv, ch);
8835 return forward(r_stdout,
rb_intern(
"putc"), 1, &ch);
8840 rb_str_end_with_asciichar(
VALUE str,
int c)
8847 if (
len == 0)
return 0;
8849 return ptr[
len - 1] == c;
8924 VALUE line, args[2];
8931 for (
int i = 0; i < argc; i++) {
8950 if (!rb_str_end_with_asciichar(line,
'\n')) {
8955 rb_io_writev(out, n, args);
8974 if (recv == r_stdout) {
8977 return forward(r_stdout,
rb_intern(
"puts"), argc, argv);
8981 rb_p_write(
VALUE str)
8989 io_writev(2, args, r_stdout);
8992 rb_io_writev(r_stdout, 2, args);
9004 rb_p_result(
int argc,
const VALUE *argv)
9011 else if (argc > 1) {
9057 for (i=0; i<argc; i++) {
9059 rb_uninterruptible(rb_p_write, inspected);
9061 return rb_p_result(argc, argv);
9082 rb_obj_display(
int argc,
VALUE *argv,
VALUE self)
9093 rb_stderr_to_original_p(
VALUE err)
9095 return (err == orig_stderr ||
RFILE(orig_stderr)->fptr->
fd < 0);
9102 if (rb_stderr_to_original_p(out)) {
9104 if (isatty(fileno(stderr))) {
9105 if (rb_w32_write_console(
rb_str_new(mesg,
len), fileno(stderr)) > 0)
return;
9108 if (fwrite(mesg,
sizeof(
char), (
size_t)
len, stderr) < (
size_t)
len) {
9125 rb_write_error_str(
VALUE mesg)
9129 if (rb_stderr_to_original_p(out)) {
9132 if (isatty(fileno(stderr))) {
9133 if (rb_w32_write_console(mesg, fileno(stderr)) > 0)
return;
9148 rb_stderr_tty_p(
void)
9151 return isatty(fileno(stderr));
9156 must_respond_to(
ID mid,
VALUE val,
ID id)
9180 must_respond_to(id_write, val,
id);
9193 must_respond_to(id_write, val,
id);
9204 allocate_and_open_new_file(
VALUE klass)
9206 VALUE self = io_alloc(klass);
9207 rb_io_make_open_file(
self);
9223 maygvl_close(descriptor, 0);
9231 io->
fd = descriptor;
9249 io->
encs = *encoding;
9258 prep_io(
int fd,
int fmode,
VALUE klass,
const char *path)
9269 rb_io_ext_int_to_encs(e, NULL, &convconfig.
enc, &convconfig.
enc2, fmode);
9273 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
9275 MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE,
9276 0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE) : 0;
9278 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(convconfig.
enc2, convconfig.
ecflags);
9284 if (!io_check_tty(io)) {
9287 setmode(fd, O_BINARY);
9299 if (path && strcmp(path,
"-")) klass =
rb_cFile;
9300 return prep_io(fd, rb_io_oflags_fmode(oflags), klass, path);
9304 prep_stdio(
FILE *f,
int fmode,
VALUE klass,
const char *path)
9311 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
9312 fptr->
encs.
ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
9323 rb_io_prep_stdin(
void)
9329 rb_io_prep_stdout(
void)
9335 rb_io_prep_stderr(
void)
9344 int oflags = rb_io_fmode_oflags(fptr->
mode) & ~O_EXCL;
9360 rb_io_fptr_new(
void)
9371 rb_io_buffer_init(&fp->
wbuf);
9372 rb_io_buffer_init(&fp->
rbuf);
9373 rb_io_buffer_init(&fp->
cbuf);
9391 rb_io_make_open_file(
VALUE obj)
9396 if (
RFILE(obj)->fptr) {
9399 RFILE(obj)->fptr = 0;
9401 fp = rb_io_fptr_new();
9403 RFILE(obj)->fptr = fp;
9451 rb_io_initialize(
int argc,
VALUE *argv,
VALUE io)
9457 return io_initialize(io, fnum, vmode, opt);
9464 int fd, fmode, oflags = O_RDONLY;
9466 #if defined(HAVE_FCNTL) && defined(F_GETFL)
9478 #if defined(HAVE_FCNTL) && defined(F_GETFL)
9479 oflags = fcntl(fd, F_GETFL);
9485 #if defined(HAVE_FCNTL) && defined(F_GETFL)
9486 ofmode = rb_io_oflags_fmode(oflags);
9513 fp->
encs = convconfig;
9518 if (fileno(stdin) == fd)
9520 else if (fileno(stdout) == fd)
9522 else if (fileno(stderr) == fd)
9554 rb_io_set_encoding_by_bom(
VALUE io)
9569 if (!io_set_encoding_by_bom(io))
return Qnil;
9615 rb_file_initialize(
int argc,
VALUE *argv,
VALUE io)
9617 if (
RFILE(io)->fptr) {
9620 VALUE fname, vmode, vperm, opt;
9621 int posargc =
rb_scan_args(argc, argv,
"12:", &fname, &vmode, &vperm, &opt);
9626 return io_initialize(io, fd, vmode, opt);
9629 return rb_open_file(io, fname, vmode, vperm, opt);
9634 rb_io_s_new(
int argc,
VALUE *argv,
VALUE klass)
9639 rb_warn(
"%"PRIsVALUE
"::new() does not take block; use %"PRIsVALUE
"::open() instead",
9655 rb_io_s_for_fd(
int argc,
VALUE *argv,
VALUE klass)
9658 rb_io_initialize(argc, argv, io);
9671 rb_io_autoclose_p(
VALUE io)
9696 rb_io_set_autoclose(
VALUE io,
VALUE autoclose)
9700 if (!
RTEST(autoclose))
9708 io_wait_event(
VALUE io,
int event,
VALUE timeout,
int return_io)
9740 io_wait_readable(
int argc,
VALUE *argv,
VALUE io)
9747 if (rb_io_read_pending(fptr))
return Qtrue;
9750 VALUE timeout = (argc == 1 ? argv[0] :
Qnil);
9764 io_wait_writable(
int argc,
VALUE *argv,
VALUE io)
9772 VALUE timeout = (argc == 1 ? argv[0] :
Qnil);
9787 io_wait_priority(
int argc,
VALUE *argv,
VALUE io)
9794 if (rb_io_read_pending(fptr))
return Qtrue;
9797 VALUE timeout = argc == 1 ? argv[0] :
Qnil;
9803 wait_mode_sym(
VALUE mode)
9806 return RB_WAITFD_IN;
9809 return RB_WAITFD_IN;
9812 return RB_WAITFD_IN;
9815 return RB_WAITFD_OUT;
9818 return RB_WAITFD_OUT;
9821 return RB_WAITFD_OUT;
9824 return RB_WAITFD_IN|RB_WAITFD_OUT;
9827 return RB_WAITFD_IN|RB_WAITFD_OUT;
9830 return RB_WAITFD_IN|RB_WAITFD_OUT;
9837 io_event_from_value(
VALUE value)
9879 for (
int i = 0; i < argc; i += 1) {
9881 events |= wait_mode_sym(argv[i]);
9883 else if (UNDEF_P(timeout)) {
9891 if (UNDEF_P(timeout)) timeout =
Qnil;
9899 events = io_event_from_value(argv[0]);
9907 if (rb_io_read_pending(fptr)) {
9909 if (return_io)
return Qtrue;
9915 return io_wait_event(io, events, timeout, return_io);
9919 argf_mark(
void *
ptr)
9930 argf_memsize(
const void *
ptr)
9933 size_t size =
sizeof(*p);
9940 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
9947 p->current_file =
Qnil;
9953 argf_alloc(
VALUE klass)
9968 memset(&ARGF, 0,
sizeof(ARGF));
9969 argf_init(&ARGF, argv);
9979 ARGF = argf_of(orig);
10006 ARGF.last_lineno = ARGF.lineno;
10035 #define next_argv() argf_next_argv(argf)
10036 #define ARGF_GENERIC_INPUT_P() \
10037 (ARGF.current_file == rb_stdin && !RB_TYPE_P(ARGF.current_file, T_FILE))
10038 #define ARGF_FORWARD(argc, argv) do {\
10039 if (ARGF_GENERIC_INPUT_P())\
10040 return argf_forward((argc), (argv), argf);\
10042 #define NEXT_ARGF_FORWARD(argc, argv) do {\
10043 if (!next_argv()) return Qnil;\
10044 ARGF_FORWARD((argc), (argv));\
10050 VALUE file = ARGF.current_file;
10064 int stdout_binmode = 0;
10072 stdout_binmode = 1;
10075 if (ARGF.init_p == 0) {
10085 if (
NIL_P(ARGF.argv)) {
10088 else if (ARGF.next_p == -1 &&
RARRAY_LEN(ARGF.argv) > 0) {
10093 if (ARGF.next_p == 1) {
10094 if (ARGF.init_p == 1) argf_close(
argf);
10099 ARGF.filename = filename;
10102 if (
RSTRING_LEN(filename) == 1 && fn[0] ==
'-') {
10104 if (ARGF.inplace) {
10105 rb_warn(
"Can't do inplace edit for stdio; skipping");
10111 int fr = rb_sysopen(filename, O_RDONLY, 0);
10113 if (ARGF.inplace) {
10115 #ifndef NO_SAFE_RENAME
10126 if (!
NIL_P(ARGF.inplace)) {
10127 VALUE suffix = ARGF.inplace;
10134 #ifdef NO_SAFE_RENAME
10138 rb_warn(
"Can't rename %"PRIsVALUE
" to %"PRIsVALUE
": %s, skipping file",
10139 filename, str, strerror(
errno));
10142 fr = rb_sysopen(str, O_RDONLY, 0);
10145 rb_warn(
"Can't rename %"PRIsVALUE
" to %"PRIsVALUE
": %s, skipping file",
10146 filename, str, strerror(
errno));
10153 #ifdef NO_SAFE_RENAME
10154 rb_fatal(
"Can't do inplace edit without backup");
10156 if (unlink(fn) < 0) {
10157 rb_warn(
"Can't remove %"PRIsVALUE
": %s, skipping file",
10158 filename, strerror(
errno));
10164 fw = rb_sysopen(filename, O_WRONLY|O_CREAT|O_TRUNC, 0666);
10165 #ifndef NO_SAFE_RENAME
10168 fchmod(fw, st.st_mode);
10170 chmod(fn, st.st_mode);
10172 if (st.st_uid!=st2.st_uid || st.st_gid!=st2.st_gid) {
10175 err = fchown(fw, st.st_uid, st.st_gid);
10177 err = chown(fn, st.st_uid, st.st_gid);
10179 if (err && getuid() == 0 && st2.st_uid == 0) {
10181 rb_warn(
"Can't set owner/group of %"PRIsVALUE
" to same as %"PRIsVALUE
": %s, skipping file",
10182 filename, str, strerror(
errno));
10185 (void)unlink(wkfn);
10195 if (!ARGF.binmode) {
10196 fmode |= DEFAULT_TEXTMODE;
10198 ARGF.current_file = prep_io(fr, fmode,
rb_cFile, fn);
10199 if (!
NIL_P(write_io)) {
10206 if (ARGF.encs.enc) {
10207 fptr->
encs = ARGF.encs;
10208 clear_codeconv(fptr);
10212 if (!ARGF.binmode) {
10214 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
10215 fptr->
encs.
ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
10226 else if (ARGF.next_p == -1) {
10229 if (ARGF.inplace) {
10230 rb_warn(
"Can't do inplace edit for stdio");
10234 if (ARGF.init_p == -1) ARGF.init_p = 1;
10242 long lineno = ARGF.lineno;
10245 if (!next_argv())
return Qnil;
10246 if (ARGF_GENERIC_INPUT_P()) {
10247 line = forward_current(idGets, argc, argv);
10254 line = rb_io_getline(argc, argv, ARGF.current_file);
10256 if (
NIL_P(line) && ARGF.next_p != -1) {
10262 if (!
NIL_P(line)) {
10263 ARGF.lineno = ++lineno;
10264 ARGF.last_lineno = ARGF.lineno;
10270 argf_lineno_getter(
ID id,
VALUE *var)
10273 return INT2FIX(ARGF.last_lineno);
10281 ARGF.last_lineno = ARGF.lineno = n;
10285 rb_reset_argf_lineno(
long n)
10287 ARGF.last_lineno = ARGF.lineno = n;
10326 rb_f_gets(
int argc,
VALUE *argv,
VALUE recv)
10328 if (recv ==
argf) {
10329 return argf_gets(argc, argv,
argf);
10331 return forward(
argf, idGets, argc, argv);
10357 line = argf_getline(argc, argv,
argf);
10369 return rb_f_gets(0, 0,
argf);
10373 if (!next_argv())
return Qnil;
10375 if (
NIL_P(line) && ARGF.next_p != -1) {
10381 if (!
NIL_P(line)) {
10383 ARGF.last_lineno = ARGF.lineno;
10409 rb_f_readline(
int argc,
VALUE *argv,
VALUE recv)
10411 if (recv ==
argf) {
10412 return argf_readline(argc, argv,
argf);
10440 if (!next_argv()) rb_eof_error();
10441 ARGF_FORWARD(argc, argv);
10442 line = argf_gets(argc, argv,
argf);
10512 rb_f_readlines(
int argc,
VALUE *argv,
VALUE recv)
10514 if (recv ==
argf) {
10515 return argf_readlines(argc, argv,
argf);
10541 long lineno = ARGF.lineno;
10545 while (next_argv()) {
10546 if (ARGF_GENERIC_INPUT_P()) {
10547 lines = forward_current(
rb_intern(
"readlines"), argc, argv);
10550 lines = rb_io_readlines(argc, argv, ARGF.current_file);
10556 ARGF.last_lineno = ARGF.lineno;
10591 rb_last_status_clear();
10592 port = pipe_open_s(str,
"r",
FMODE_READABLE|DEFAULT_TEXTMODE, NULL);
10596 result = read_all(fptr, remain_size(fptr),
Qnil);
10598 rb_io_fptr_cleanup_all(fptr);
10604 #ifdef HAVE_SYS_SELECT_H
10605 #include <sys/select.h>
10619 if (!
NIL_P(read)) {
10624 if (READ_DATA_PENDING(fptr) || READ_CHAR_PENDING(fptr)) {
10628 if (max < fptr->fd) max = fptr->
fd;
10631 timerec.tv_sec = timerec.tv_usec = 0;
10639 if (!
NIL_P(write)) {
10645 if (max < fptr->fd) max = fptr->
fd;
10652 if (!
NIL_P(except)) {
10656 VALUE write_io = GetWriteIO(io);
10659 if (max < fptr->fd) max = fptr->
fd;
10660 if (io != write_io) {
10663 if (max < fptr->fd) max = fptr->
fd;
10678 if (!pending && n == 0)
return Qnil;
10703 VALUE write_io = GetWriteIO(io);
10716 VALUE write_io = GetWriteIO(io);
10721 else if (io != write_io) {
10734 VALUE read, write, except;
10740 select_call(
VALUE arg)
10744 return select_internal(p->read, p->write, p->except, p->timeout, p->fdsets);
10748 select_end(
VALUE arg)
10753 for (i = 0; i < numberof(p->fdsets); ++i)
10758 static VALUE sym_normal, sym_sequential, sym_random,
10759 sym_willneed, sym_dontneed, sym_noreuse;
10761 #ifdef HAVE_POSIX_FADVISE
10762 struct io_advise_struct {
10770 io_advise_internal(
void *arg)
10772 struct io_advise_struct *
ptr = arg;
10773 return posix_fadvise(
ptr->fd,
ptr->offset,
ptr->len,
ptr->advice);
10777 io_advise_sym_to_const(
VALUE sym)
10779 #ifdef POSIX_FADV_NORMAL
10780 if (sym == sym_normal)
10781 return INT2NUM(POSIX_FADV_NORMAL);
10784 #ifdef POSIX_FADV_RANDOM
10785 if (sym == sym_random)
10786 return INT2NUM(POSIX_FADV_RANDOM);
10789 #ifdef POSIX_FADV_SEQUENTIAL
10790 if (sym == sym_sequential)
10791 return INT2NUM(POSIX_FADV_SEQUENTIAL);
10794 #ifdef POSIX_FADV_WILLNEED
10795 if (sym == sym_willneed)
10796 return INT2NUM(POSIX_FADV_WILLNEED);
10799 #ifdef POSIX_FADV_DONTNEED
10800 if (sym == sym_dontneed)
10801 return INT2NUM(POSIX_FADV_DONTNEED);
10804 #ifdef POSIX_FADV_NOREUSE
10805 if (sym == sym_noreuse)
10806 return INT2NUM(POSIX_FADV_NOREUSE);
10813 do_io_advise(
rb_io_t *fptr,
VALUE advice, rb_off_t offset, rb_off_t
len)
10816 struct io_advise_struct ias;
10819 num_adv = io_advise_sym_to_const(advice);
10825 if (
NIL_P(num_adv))
10829 ias.advice =
NUM2INT(num_adv);
10830 ias.offset = offset;
10833 rv = (int)rb_io_blocking_region(fptr, io_advise_internal, &ias);
10834 if (rv && rv != ENOSYS) {
10841 fptr->
pathv, offset,
len, advice);
10851 advice_arg_check(
VALUE advice)
10856 if (advice != sym_normal &&
10857 advice != sym_sequential &&
10858 advice != sym_random &&
10859 advice != sym_willneed &&
10860 advice != sym_dontneed &&
10861 advice != sym_noreuse) {
10900 rb_io_advise(
int argc,
VALUE *argv,
VALUE io)
10907 advice_arg_check(advice);
10909 io = GetWriteIO(io);
10915 #ifdef HAVE_POSIX_FADVISE
10916 return do_io_advise(fptr, advice,
off, l);
10918 ((void)
off, (
void)l);
11074 rb_f_select(
int argc,
VALUE *argv,
VALUE obj)
11077 if (scheduler !=
Qnil) {
11080 if (!UNDEF_P(result))
return result;
11088 rb_scan_args(argc, argv,
"13", &args.read, &args.write, &args.except, &timeout);
11089 if (
NIL_P(timeout)) {
11094 args.timeout = &timerec;
11097 for (i = 0; i < numberof(args.fdsets); ++i)
11103 #ifdef IOCTL_REQ_TYPE
11104 typedef IOCTL_REQ_TYPE ioctl_req_t;
11106 typedef int ioctl_req_t;
11107 # define NUM2IOCTLREQ(num) ((int)NUM2LONG(num))
11118 nogvl_ioctl(
void *
ptr)
11120 struct ioctl_arg *arg =
ptr;
11122 return (
VALUE)ioctl(arg->fd, arg->cmd, arg->narg);
11126 do_ioctl(
struct rb_io *io, ioctl_req_t cmd,
long narg)
11129 struct ioctl_arg arg;
11135 retval = (int)rb_io_blocking_region(io, nogvl_ioctl, &arg);
11141 #define DEFAULT_IOCTL_NARG_LEN (256)
11143 #if defined(__linux__) && defined(_IOC_SIZE)
11145 linux_iocparm_len(ioctl_req_t cmd)
11149 if ((cmd & 0xFFFF0000) == 0) {
11151 return DEFAULT_IOCTL_NARG_LEN;
11154 len = _IOC_SIZE(cmd);
11157 if (
len < DEFAULT_IOCTL_NARG_LEN)
11158 len = DEFAULT_IOCTL_NARG_LEN;
11166 ioctl_narg_len(ioctl_req_t cmd)
11170 #ifdef IOCPARM_MASK
11171 #ifndef IOCPARM_LEN
11172 #define IOCPARM_LEN(x) (((x) >> 16) & IOCPARM_MASK)
11176 len = IOCPARM_LEN(cmd);
11177 #elif defined(__linux__) && defined(_IOC_SIZE)
11178 len = linux_iocparm_len(cmd);
11181 len = DEFAULT_IOCTL_NARG_LEN;
11190 typedef long fcntl_arg_t;
11193 typedef int fcntl_arg_t;
11197 fcntl_narg_len(ioctl_req_t cmd)
11204 len =
sizeof(fcntl_arg_t);
11212 #ifdef F_DUPFD_CLOEXEC
11213 case F_DUPFD_CLOEXEC:
11214 len =
sizeof(fcntl_arg_t);
11224 len =
sizeof(fcntl_arg_t);
11234 len =
sizeof(fcntl_arg_t);
11244 len =
sizeof(fcntl_arg_t);
11249 len =
sizeof(
struct f_owner_ex);
11254 len =
sizeof(
struct f_owner_ex);
11259 len =
sizeof(
struct flock);
11264 len =
sizeof(
struct flock);
11269 len =
sizeof(
struct flock);
11289 len =
sizeof(fcntl_arg_t);
11299 len =
sizeof(fcntl_arg_t);
11304 len =
sizeof(fcntl_arg_t);
11317 fcntl_narg_len(ioctl_req_t cmd)
11323 #define NARG_SENTINEL 17
11326 setup_narg(ioctl_req_t cmd,
VALUE *argp,
long (*narg_len)(ioctl_req_t))
11337 else if (arg ==
Qtrue) {
11351 len = narg_len(cmd);
11356 if (slen <
len+1) {
11363 ptr[slen - 1] = NARG_SENTINEL;
11372 finish_narg(
int retval,
VALUE arg,
const rb_io_t *fptr)
11374 if (retval < 0) rb_sys_fail_path(fptr->
pathv);
11379 if (
ptr[slen-1] != NARG_SENTINEL)
11381 ptr[slen-1] =
'\0';
11391 ioctl_req_t cmd = NUM2IOCTLREQ(req);
11396 narg = setup_narg(cmd, &arg, ioctl_narg_len);
11398 retval = do_ioctl(fptr, cmd, narg);
11399 return finish_narg(retval, arg, fptr);
11421 rb_io_ioctl(
int argc,
VALUE *argv,
VALUE io)
11426 return rb_ioctl(io, req, arg);
11429 #define rb_io_ioctl rb_f_notimplement
11440 nogvl_fcntl(
void *
ptr)
11442 struct fcntl_arg *arg =
ptr;
11444 #if defined(F_DUPFD)
11445 if (arg->cmd == F_DUPFD)
11448 return (
VALUE)fcntl(arg->fd, arg->cmd, arg->narg);
11452 do_fcntl(
struct rb_io *io,
int cmd,
long narg)
11455 struct fcntl_arg arg;
11461 retval = (int)rb_io_blocking_region(io, nogvl_fcntl, &arg);
11462 if (retval != -1) {
11464 #if defined(F_DUPFD)
11467 #if defined(F_DUPFD_CLOEXEC)
11468 case F_DUPFD_CLOEXEC:
11485 narg = setup_narg(cmd, &arg, fcntl_narg_len);
11487 retval = do_fcntl(fptr, cmd, narg);
11488 return finish_narg(retval, arg, fptr);
11509 rb_io_fcntl(
int argc,
VALUE *argv,
VALUE io)
11514 return rb_fcntl(io, req, arg);
11517 #define rb_io_fcntl rb_f_notimplement
11520 #if defined(HAVE_SYSCALL) || defined(HAVE___SYSCALL)
11552 #if SIZEOF_VOIDP == 8 && defined(HAVE___SYSCALL) && SIZEOF_INT != 8
11553 # define SYSCALL __syscall
11554 # define NUM2SYSCALLID(x) NUM2LONG(x)
11555 # define RETVAL2NUM(x) LONG2NUM(x)
11556 # if SIZEOF_LONG == 8
11557 long num, retval = -1;
11558 # elif SIZEOF_LONG_LONG == 8
11559 long long num, retval = -1;
11561 # error ---->> it is asserted that __syscall takes the first argument and returns retval in 64bit signed integer. <<----
11563 #elif defined(__linux__)
11564 # define SYSCALL syscall
11565 # define NUM2SYSCALLID(x) NUM2LONG(x)
11566 # define RETVAL2NUM(x) LONG2NUM(x)
11574 long num, retval = -1;
11576 # define SYSCALL syscall
11577 # define NUM2SYSCALLID(x) NUM2INT(x)
11578 # define RETVAL2NUM(x) INT2NUM(x)
11579 int num, retval = -1;
11585 "We plan to remove a syscall function at future release. DL(Fiddle) provides safer alternative.");
11590 if (argc > numberof(arg))
11592 num = NUM2SYSCALLID(argv[0]); ++argv;
11593 for (i = argc - 1; i--; ) {
11608 retval = SYSCALL(num);
11611 retval = SYSCALL(num, arg[0]);
11614 retval = SYSCALL(num, arg[0],arg[1]);
11617 retval = SYSCALL(num, arg[0],arg[1],arg[2]);
11620 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3]);
11623 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4]);
11626 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5]);
11629 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6]);
11635 return RETVAL2NUM(retval);
11637 #undef NUM2SYSCALLID
11641 #define rb_f_syscall rb_f_notimplement
11645 io_new_instance(
VALUE args)
11651 find_encoding(
VALUE v)
11654 if (!enc)
rb_warn(
"Unsupported encoding %"PRIsVALUE
" ignored", v);
11666 enc2 = find_encoding(v1);
11675 enc = find_encoding(v2);
11682 enc = find_encoding(v2);
11693 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
11699 rb_io_ext_int_to_encs(NULL, NULL, &enc, &enc2, 0);
11700 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
11706 parse_mode_enc(
RSTRING_PTR(tmp), enc, &enc, &enc2, NULL);
11707 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
11711 rb_io_ext_int_to_encs(find_encoding(v1), NULL, &enc, &enc2, 0);
11712 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
11717 validate_enc_binmode(&fptr->
mode, ecflags, enc, enc2);
11722 clear_codeconv(fptr);
11734 io_encoding_set_v(
VALUE v)
11737 io_encoding_set(arg->fptr, arg->v1, arg->v2, arg->opt);
11742 pipe_pair_close(
VALUE rw)
11745 return rb_ensure(io_close, rwp[0], io_close, rwp[1]);
11828 rb_io_s_pipe(
int argc,
VALUE *argv,
VALUE klass)
11830 int pipes[2], state;
11831 VALUE r, w, args[3], v1, v2;
11838 argc =
rb_scan_args(argc, argv,
"02:", &v1, &v2, &opt);
11853 ies_args.fptr = fptr;
11856 ies_args.opt = opt;
11875 extract_binmode(opt, &fmode);
11882 #if DEFAULT_TEXTMODE
11885 setmode(fptr->
fd, O_BINARY);
11887 #if RUBY_CRLF_ENVIRONMENT
11893 fptr->
mode |= fmode;
11894 #if DEFAULT_TEXTMODE
11897 setmode(fptr2->
fd, O_BINARY);
11900 fptr2->
mode |= fmode;
11937 v = rb_to_array_type(v);
11942 arg->io = rb_io_open(klass, path, vmode, vperm, opt);
11946 io_s_foreach(
VALUE v)
11951 if (arg->limit == 0)
11953 while (!
NIL_P(str = rb_io_getline_1(arg->rs, arg->limit, arg->chomp, arg->io))) {
12041 rb_io_s_foreach(
int argc,
VALUE *argv,
VALUE self)
12044 int orig_argc = argc;
12048 argc =
rb_scan_args(argc, argv,
"12:", NULL, NULL, NULL, &opt);
12050 extract_getline_args(argc-1, argv+1, &garg);
12051 open_key_args(
self, argc, argv, opt, &arg);
12053 extract_getline_opts(opt, &garg);
12054 check_getline_args(&garg.rs, &garg.limit, garg.io = arg.io);
12059 io_s_readlines(
VALUE v)
12062 return io_readlines(arg, arg->io);
12119 rb_io_s_readlines(
int argc,
VALUE *argv,
VALUE io)
12125 argc =
rb_scan_args(argc, argv,
"12:", NULL, NULL, NULL, &opt);
12126 extract_getline_args(argc-1, argv+1, &garg);
12127 open_key_args(io, argc, argv, opt, &arg);
12129 extract_getline_opts(opt, &garg);
12130 check_getline_args(&garg.rs, &garg.limit, garg.io = arg.io);
12138 return io_read(arg->argc, arg->argv, arg->io);
12148 seek_before_access(
VALUE argp)
12152 return rb_io_seek(arg->io, arg->offset, arg->mode);
12198 rb_io_s_read(
int argc,
VALUE *argv,
VALUE io)
12204 argc =
rb_scan_args(argc, argv,
"13:", NULL, NULL, &offset, NULL, &opt);
12208 open_key_args(io, argc, argv, opt, &arg);
12210 if (!
NIL_P(offset)) {
12214 sarg.offset = offset;
12215 sarg.mode = SEEK_SET;
12221 if (arg.argc == 2) arg.argc = 1;
12240 rb_io_s_binread(
int argc,
VALUE *argv,
VALUE io)
12256 arg.io = rb_io_open_generic(io, argv[0], oflags, fmode, &convconfig, 0);
12259 arg.argc = (argc > 1) ? 1 : 0;
12260 if (!
NIL_P(offset)) {
12264 sarg.offset = offset;
12265 sarg.mode = SEEK_SET;
12276 io_s_write0(
VALUE v)
12279 return io_write(arg->io,arg->str,arg->nosync);
12283 io_s_write(
int argc,
VALUE *argv,
VALUE klass,
int binary)
12285 VALUE string, offset, opt;
12289 rb_scan_args(argc, argv,
"21:", NULL, &
string, &offset, &opt);
12296 int mode = O_WRONLY|O_CREAT;
12298 if (binary) mode |= O_BINARY;
12300 if (
NIL_P(offset)) mode |= O_TRUNC;
12303 open_key_args(klass, argc, argv, opt, &arg);
12306 if (binary) rb_io_binmode_m(arg.io);
12310 if (!
NIL_P(offset)) {
12314 sarg.offset = offset;
12315 sarg.mode = SEEK_SET;
12375 rb_io_s_write(
int argc,
VALUE *argv,
VALUE io)
12377 return io_s_write(argc, argv, io, 0);
12394 rb_io_s_binwrite(
int argc,
VALUE *argv,
VALUE io)
12396 return io_s_write(argc, argv, io, 1);
12402 rb_off_t copy_length;
12403 rb_off_t src_offset;
12407 unsigned close_src : 1;
12408 unsigned close_dst : 1;
12411 const char *syserr;
12412 const char *notimp;
12414 struct stat src_stat;
12415 struct stat dst_stat;
12416 #ifdef HAVE_FCOPYFILE
12417 copyfile_state_t copyfile_state;
12422 exec_interrupts(
void *arg)
12425 rb_thread_execute_interrupts(th);
12439 #if defined(ERESTART)
12444 rb_thread_execute_interrupts(stp->th);
12463 fiber_scheduler_wait_for(
void * _arguments)
12473 # define IOWAIT_SYSCALL "poll"
12474 STATIC_ASSERT(pollin_expected, POLLIN == RB_WAITFD_IN);
12475 STATIC_ASSERT(pollout_expected, POLLOUT == RB_WAITFD_OUT);
12480 if (scheduler !=
Qnil) {
12483 return RTEST(args.result);
12487 if (fd == -1)
return 0;
12492 fds.events = events;
12494 int timeout_milliseconds = -1;
12497 timeout_milliseconds = (int)(timeout->tv_sec * 1000) + (int)(timeout->tv_usec / 1000);
12500 return poll(&fds, 1, timeout_milliseconds);
12503 # define IOWAIT_SYSCALL "select"
12508 if (scheduler !=
Qnil) {
12511 return RTEST(args.result);
12531 case RB_WAITFD_OUT:
12535 VM_UNREACHABLE(nogvl_wait_for);
12555 ret = nogvl_wait_for(stp->th, stp->src_fptr, RB_WAITFD_IN, NULL);
12557 }
while (ret < 0 && maygvl_copy_stream_continue_p(has_gvl, stp));
12560 stp->syserr = IOWAIT_SYSCALL;
12561 stp->error_no =
errno;
12573 ret = nogvl_wait_for(stp->th, stp->dst_fptr, RB_WAITFD_OUT, NULL);
12574 }
while (ret < 0 && maygvl_copy_stream_continue_p(0, stp));
12577 stp->syserr = IOWAIT_SYSCALL;
12578 stp->error_no =
errno;
12584 #ifdef USE_COPY_FILE_RANGE
12587 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)
12589 #ifdef HAVE_COPY_FILE_RANGE
12590 return copy_file_range(in_fd, in_offset, out_fd, out_offset, count, flags);
12592 return syscall(__NR_copy_file_range, in_fd, in_offset, out_fd, out_offset, count, flags);
12601 rb_off_t copy_length, src_offset, *src_offset_ptr;
12603 if (!S_ISREG(stp->src_stat.st_mode))
12606 src_size = stp->src_stat.st_size;
12607 src_offset = stp->src_offset;
12608 if (src_offset >= (rb_off_t)0) {
12609 src_offset_ptr = &src_offset;
12612 src_offset_ptr = NULL;
12615 copy_length = stp->copy_length;
12616 if (copy_length < (rb_off_t)0) {
12617 if (src_offset < (rb_off_t)0) {
12618 rb_off_t current_offset;
12620 current_offset = lseek(stp->src_fptr->
fd, 0, SEEK_CUR);
12621 if (current_offset < (rb_off_t)0 &&
errno) {
12622 stp->syserr =
"lseek";
12623 stp->error_no =
errno;
12624 return (
int)current_offset;
12626 copy_length = src_size - current_offset;
12629 copy_length = src_size - src_offset;
12633 retry_copy_file_range:
12634 # if SIZEOF_OFF_T > SIZEOF_SIZE_T
12636 ss = (copy_length > (rb_off_t)SSIZE_MAX) ? SSIZE_MAX : (ssize_t)copy_length;
12638 ss = (ssize_t)copy_length;
12640 ss = simple_copy_file_range(stp->src_fptr->
fd, src_offset_ptr, stp->dst_fptr->
fd, NULL, ss, 0);
12644 if (0 < copy_length) {
12645 goto retry_copy_file_range;
12649 if (maygvl_copy_stream_continue_p(0, stp)) {
12650 goto retry_copy_file_range;
12664 #if EWOULDBLOCK != EAGAIN
12668 int ret = nogvl_copy_stream_wait_write(stp);
12669 if (ret < 0)
return ret;
12671 goto retry_copy_file_range;
12675 int flags = fcntl(stp->dst_fptr->
fd, F_GETFL);
12677 if (flags != -1 && flags & O_APPEND) {
12683 stp->syserr =
"copy_file_range";
12684 stp->error_no =
errno;
12691 #ifdef HAVE_FCOPYFILE
12695 rb_off_t cur, ss = 0;
12696 const rb_off_t src_offset = stp->src_offset;
12699 if (stp->copy_length >= (rb_off_t)0) {
12704 if (!S_ISREG(stp->src_stat.st_mode))
12707 if (!S_ISREG(stp->dst_stat.st_mode))
12709 if (lseek(stp->dst_fptr->
fd, 0, SEEK_CUR) > (rb_off_t)0)
12711 if (fcntl(stp->dst_fptr->
fd, F_GETFL) & O_APPEND) {
12714 rb_off_t end = lseek(stp->dst_fptr->
fd, 0, SEEK_END);
12715 lseek(stp->dst_fptr->
fd, 0, SEEK_SET);
12716 if (end > (rb_off_t)0)
return 0;
12719 if (src_offset > (rb_off_t)0) {
12724 cur = lseek(stp->src_fptr->
fd, 0, SEEK_CUR);
12725 if (cur < (rb_off_t)0 &&
errno) {
12726 stp->error_no =
errno;
12731 r = lseek(stp->src_fptr->
fd, src_offset, SEEK_SET);
12732 if (r < (rb_off_t)0 &&
errno) {
12733 stp->error_no =
errno;
12738 stp->copyfile_state = copyfile_state_alloc();
12739 ret = fcopyfile(stp->src_fptr->
fd, stp->dst_fptr->
fd, stp->copyfile_state, COPYFILE_DATA);
12740 copyfile_state_get(stp->copyfile_state, COPYFILE_STATE_COPIED, &ss);
12744 if (src_offset > (rb_off_t)0) {
12748 r = lseek(stp->src_fptr->
fd, cur, SEEK_SET);
12749 if (r < (rb_off_t)0 &&
errno) {
12750 stp->error_no =
errno;
12762 stp->syserr =
"fcopyfile";
12763 stp->error_no =
errno;
12770 #ifdef HAVE_SENDFILE
12773 # define USE_SENDFILE
12775 # ifdef HAVE_SYS_SENDFILE_H
12776 # include <sys/sendfile.h>
12780 simple_sendfile(
int out_fd,
int in_fd, rb_off_t *offset, rb_off_t count)
12782 return sendfile(out_fd, in_fd, offset, (
size_t)count);
12785 # elif 0 || defined(__APPLE__)
12789 # define USE_SENDFILE
12792 simple_sendfile(
int out_fd,
int in_fd, rb_off_t *offset, rb_off_t count)
12795 rb_off_t pos = offset ? *offset : lseek(in_fd, 0, SEEK_CUR);
12798 r = sendfile(in_fd, out_fd, pos, &count, NULL, 0);
12801 r = sendfile(in_fd, out_fd, pos, (
size_t)count, NULL, &sbytes, 0);
12803 if (r != 0 && sbytes == 0)
return r;
12808 lseek(in_fd, sbytes, SEEK_CUR);
12810 return (ssize_t)sbytes;
12817 #ifdef USE_SENDFILE
12823 rb_off_t copy_length;
12824 rb_off_t src_offset;
12827 if (!S_ISREG(stp->src_stat.st_mode))
12830 src_size = stp->src_stat.st_size;
12832 if ((stp->dst_stat.st_mode & S_IFMT) != S_IFSOCK)
12836 src_offset = stp->src_offset;
12837 use_pread = src_offset >= (rb_off_t)0;
12839 copy_length = stp->copy_length;
12840 if (copy_length < (rb_off_t)0) {
12842 copy_length = src_size - src_offset;
12846 cur = lseek(stp->src_fptr->
fd, 0, SEEK_CUR);
12847 if (cur < (rb_off_t)0 &&
errno) {
12848 stp->syserr =
"lseek";
12849 stp->error_no =
errno;
12852 copy_length = src_size - cur;
12857 # if SIZEOF_OFF_T > SIZEOF_SIZE_T
12859 ss = (copy_length > (rb_off_t)SSIZE_MAX) ? SSIZE_MAX : (ssize_t)copy_length;
12861 ss = (ssize_t)copy_length;
12864 ss = simple_sendfile(stp->dst_fptr->
fd, stp->src_fptr->
fd, &src_offset, ss);
12867 ss = simple_sendfile(stp->dst_fptr->
fd, stp->src_fptr->
fd, NULL, ss);
12872 if (0 < copy_length) {
12873 goto retry_sendfile;
12877 if (maygvl_copy_stream_continue_p(0, stp))
12878 goto retry_sendfile;
12891 #if EWOULDBLOCK != EAGAIN
12904 ret = maygvl_copy_stream_wait_read(0, stp);
12905 if (ret < 0)
return ret;
12907 ret = nogvl_copy_stream_wait_write(stp);
12908 if (ret < 0)
return ret;
12910 goto retry_sendfile;
12912 stp->syserr =
"sendfile";
12913 stp->error_no =
errno;
12921 maygvl_read(
int has_gvl,
rb_io_t *fptr,
void *buf,
size_t count)
12924 return rb_io_read_memory(fptr, buf, count);
12926 return read(fptr->
fd, buf, count);
12930 maygvl_copy_stream_read(
int has_gvl,
struct copy_stream_struct *stp,
char *buf,
size_t len, rb_off_t offset)
12934 if (offset < (rb_off_t)0) {
12935 ss = maygvl_read(has_gvl, stp->src_fptr, buf,
len);
12938 ss = pread(stp->src_fptr->
fd, buf,
len, offset);
12944 if (maygvl_copy_stream_continue_p(has_gvl, stp))
12948 #if EWOULDBLOCK != EAGAIN
12952 int ret = maygvl_copy_stream_wait_read(has_gvl, stp);
12953 if (ret < 0)
return ret;
12958 stp->notimp =
"pread";
12962 stp->syserr = offset < (rb_off_t)0 ?
"read" :
"pread";
12963 stp->error_no =
errno;
12974 ss = write(stp->dst_fptr->
fd, buf+
off,
len);
12976 if (maygvl_copy_stream_continue_p(0, stp))
12978 if (io_again_p(
errno)) {
12979 int ret = nogvl_copy_stream_wait_write(stp);
12980 if (ret < 0)
return ret;
12983 stp->syserr =
"write";
12984 stp->error_no =
errno;
13001 rb_off_t copy_length;
13002 rb_off_t src_offset;
13006 copy_length = stp->copy_length;
13007 use_eof = copy_length < (rb_off_t)0;
13008 src_offset = stp->src_offset;
13009 use_pread = src_offset >= (rb_off_t)0;
13011 if (use_pread && stp->close_src) {
13014 r = lseek(stp->src_fptr->
fd, src_offset, SEEK_SET);
13015 if (r < (rb_off_t)0 &&
errno) {
13016 stp->syserr =
"lseek";
13017 stp->error_no =
errno;
13020 src_offset = (rb_off_t)-1;
13024 while (use_eof || 0 < copy_length) {
13025 if (!use_eof && copy_length < (rb_off_t)
sizeof(buf)) {
13026 len = (size_t)copy_length;
13032 ss = maygvl_copy_stream_read(0, stp, buf,
len, src_offset);
13037 ss = maygvl_copy_stream_read(0, stp, buf,
len, (rb_off_t)-1);
13042 ret = nogvl_copy_stream_write(stp, buf, ss);
13052 nogvl_copy_stream_func(
void *arg)
13055 #if defined(USE_SENDFILE) || defined(USE_COPY_FILE_RANGE) || defined(HAVE_FCOPYFILE)
13059 #ifdef USE_COPY_FILE_RANGE
13060 ret = nogvl_copy_file_range(stp);
13065 #ifdef HAVE_FCOPYFILE
13066 ret = nogvl_fcopyfile(stp);
13071 #ifdef USE_SENDFILE
13072 ret = nogvl_copy_stream_sendfile(stp);
13077 nogvl_copy_stream_read_write(stp);
13079 #if defined(USE_SENDFILE) || defined(USE_COPY_FILE_RANGE) || defined(HAVE_FCOPYFILE)
13086 copy_stream_fallback_body(
VALUE arg)
13089 const int buflen = 16*1024;
13092 rb_off_t rest = stp->copy_length;
13093 rb_off_t
off = stp->src_offset;
13094 ID read_method = id_readpartial;
13096 if (!stp->src_fptr) {
13098 read_method = id_read;
13105 if (stp->copy_length < (rb_off_t)0) {
13113 l = buflen < rest ? buflen : (long)rest;
13115 if (!stp->src_fptr) {
13118 if (read_method == id_read &&
NIL_P(rc))
13130 if (
off >= (rb_off_t)0)
13135 stp->total += numwrote;
13137 if (read_method == id_read &&
RSTRING_LEN(buf) == 0) {
13148 if (!stp->src_fptr && stp->src_offset >= (rb_off_t)0) {
13158 copy_stream_body(
VALUE arg)
13161 VALUE src_io = stp->src, dst_io = stp->dst;
13162 const int common_oflags = 0
13172 if (src_io ==
argf ||
13176 stp->src_fptr = NULL;
13181 if (!
NIL_P(tmp_io)) {
13188 args[1] =
INT2NUM(O_RDONLY|common_oflags);
13191 stp->close_src = 1;
13196 stat_ret = fstat(stp->src_fptr->
fd, &stp->src_stat);
13197 if (stat_ret < 0) {
13198 stp->syserr =
"fstat";
13199 stp->error_no =
errno;
13204 if (dst_io ==
argf ||
13208 stp->dst_fptr = NULL;
13213 if (!
NIL_P(tmp_io)) {
13214 dst_io = GetWriteIO(tmp_io);
13220 args[1] =
INT2NUM(O_WRONLY|O_CREAT|O_TRUNC|common_oflags);
13224 stp->close_dst = 1;
13227 dst_io = GetWriteIO(dst_io);
13233 stat_ret = fstat(stp->dst_fptr->
fd, &stp->dst_stat);
13234 if (stat_ret < 0) {
13235 stp->syserr =
"fstat";
13236 stp->error_no =
errno;
13243 SET_BINARY_MODE_WITH_SEEK_CUR(stp->src_fptr);
13246 io_ascii8bit_binmode(stp->dst_fptr);
13248 if (stp->src_offset < (rb_off_t)0 && stp->src_fptr && stp->src_fptr->
rbuf.
len) {
13251 if (stp->copy_length >= (rb_off_t)0 && stp->copy_length < (rb_off_t)
len) {
13252 len = (size_t)stp->copy_length;
13257 if (stp->dst_fptr) {
13259 rb_sys_fail_on_write(stp->dst_fptr);
13265 if (stp->copy_length >= (rb_off_t)0)
13266 stp->copy_length -=
len;
13269 if (stp->dst_fptr && io_fflush(stp->dst_fptr) < 0) {
13273 if (stp->copy_length == 0)
13276 if (stp->src_fptr == NULL || stp->dst_fptr == NULL) {
13277 return copy_stream_fallback(stp);
13280 IO_WITHOUT_GVL(nogvl_copy_stream_func, stp);
13285 copy_stream_finalize(
VALUE arg)
13289 #ifdef HAVE_FCOPYFILE
13290 if (stp->copyfile_state) {
13291 copyfile_state_free(stp->copyfile_state);
13295 if (stp->close_src) {
13296 rb_io_close_m(stp->src);
13298 if (stp->close_dst) {
13299 rb_io_close_m(stp->dst);
13362 rb_io_s_copy_stream(
int argc,
VALUE *argv,
VALUE io)
13364 VALUE src, dst, length, src_offset;
13369 rb_scan_args(argc, argv,
"22", &src, &dst, &length, &src_offset);
13374 st.src_fptr = NULL;
13375 st.dst_fptr = NULL;
13378 st.copy_length = (rb_off_t)-1;
13380 st.copy_length =
NUM2OFFT(length);
13382 if (
NIL_P(src_offset))
13383 st.src_offset = (rb_off_t)-1;
13385 st.src_offset =
NUM2OFFT(src_offset);
13404 rb_io_external_encoding(
VALUE io)
13432 rb_io_internal_encoding(
VALUE io)
13471 rb_io_set_encoding(
int argc,
VALUE *argv,
VALUE io)
13477 return forward(io, id_set_encoding, argc, argv);
13480 argc =
rb_scan_args(argc, argv,
"11:", &v1, &v2, &opt);
13482 io_encoding_set(fptr, v1, v2, opt);
13487 rb_stdio_set_default_encoding(
void)
13492 if (isatty(fileno(stdin))) {
13503 rb_io_set_encoding(1, &val,
rb_stdin);
13504 rb_io_set_encoding(1, &val,
rb_stdout);
13505 rb_io_set_encoding(1, &val,
rb_stderr);
13509 global_argf_p(
VALUE arg)
13511 return arg ==
argf;
13514 typedef VALUE (*argf_encoding_func)(
VALUE io);
13517 argf_encoding(
VALUE argf, argf_encoding_func func)
13519 if (!
RTEST(ARGF.current_file)) {
13544 return argf_encoding(
argf, rb_io_external_encoding);
13563 return argf_encoding(
argf, rb_io_internal_encoding);
13602 if (!next_argv()) {
13605 rb_io_set_encoding(argc, argv, ARGF.current_file);
13607 ARGF.encs = fptr->
encs;
13626 if (!next_argv()) {
13629 ARGF_FORWARD(0, 0);
13630 return rb_io_tell(ARGF.current_file);
13643 if (!next_argv()) {
13646 ARGF_FORWARD(argc, argv);
13647 return rb_io_seek_m(argc, argv, ARGF.current_file);
13664 if (!next_argv()) {
13667 ARGF_FORWARD(1, &offset);
13668 return rb_io_set_pos(ARGF.current_file, offset);
13689 if (!next_argv()) {
13692 ARGF_FORWARD(0, 0);
13693 old_lineno =
RFILE(ARGF.current_file)->fptr->lineno;
13694 ret = rb_io_rewind(ARGF.current_file);
13695 if (!global_argf_p(
argf)) {
13696 ARGF.last_lineno = ARGF.lineno -= old_lineno;
13714 if (!next_argv()) {
13717 ARGF_FORWARD(0, 0);
13718 return rb_io_fileno(ARGF.current_file);
13737 ARGF_FORWARD(0, 0);
13738 return ARGF.current_file;
13763 if (
RTEST(ARGF.current_file)) {
13764 if (ARGF.init_p == 0)
return Qtrue;
13766 ARGF_FORWARD(0, 0);
13825 VALUE tmp, str, length;
13829 if (!
NIL_P(length)) {
13839 if (!next_argv()) {
13842 if (ARGF_GENERIC_INPUT_P()) {
13843 tmp = argf_forward(argc, argv,
argf);
13846 tmp = io_read(argc, argv, ARGF.current_file);
13848 if (
NIL_P(str)) str = tmp;
13851 if (ARGF.next_p != -1) {
13857 else if (argc >= 1) {
13874 argf_forward_call(
VALUE arg)
13877 argf_forward(p->argc, p->argv, p->argf);
13907 return argf_getpartial(argc, argv,
argf,
Qnil, 0);
13928 return argf_getpartial(argc, argv,
argf, opts, 1);
13934 VALUE tmp, str, length;
13942 no_exception = no_exception_p(opts);
13944 if (!next_argv()) {
13950 if (ARGF_GENERIC_INPUT_P()) {
13960 tmp = io_getpartial(argc, argv, ARGF.current_file, no_exception, nonblock);
13963 if (ARGF.next_p == -1) {
13964 return io_nonblock_eof(no_exception);
13969 return io_nonblock_eof(no_exception);
14007 if (!next_argv())
return Qnil;
14008 if (ARGF_GENERIC_INPUT_P()) {
14009 ch = forward_current(
rb_intern(
"getc"), 0, 0);
14012 ch = rb_io_getc(ARGF.current_file);
14014 if (
NIL_P(ch) && ARGF.next_p != -1) {
14047 if (!next_argv())
return Qnil;
14049 ch = forward_current(
rb_intern(
"getbyte"), 0, 0);
14054 if (
NIL_P(ch) && ARGF.next_p != -1) {
14087 if (!next_argv()) rb_eof_error();
14089 ch = forward_current(
rb_intern(
"getc"), 0, 0);
14092 ch = rb_io_getc(ARGF.current_file);
14094 if (
NIL_P(ch) && ARGF.next_p != -1) {
14126 NEXT_ARGF_FORWARD(0, 0);
14127 c = argf_getbyte(
argf);
14134 #define FOREACH_ARGF() while (next_argv())
14139 const VALUE current = ARGF.current_file;
14141 if (ARGF.init_p == -1 || current != ARGF.current_file) {
14147 #define ARGF_block_call(mid, argc, argv, func, argf) \
14148 rb_block_call_kw(ARGF.current_file, mid, argc, argv, \
14149 func, argf, rb_keyword_given_p())
14154 VALUE ret = ARGF_block_call(mid, argc, argv, argf_block_call_i,
argf);
14155 if (!UNDEF_P(ret)) ARGF.next_p = 1;
14161 if (!global_argf_p(
argf)) {
14162 ARGF.last_lineno = ++ARGF.lineno;
14164 return argf_block_call_i(i,
argf, argc, argv, blockarg);
14170 VALUE ret = ARGF_block_call(mid, argc, argv, argf_block_call_line_i,
argf);
14171 if (!UNDEF_P(ret)) ARGF.next_p = 1;
14219 argf_block_call_line(
rb_intern(
"each_line"), argc, argv,
argf);
14333 return ARGF.filename;
14337 argf_filename_getter(
ID id,
VALUE *var)
14339 return argf_filename(*var);
14364 return ARGF.current_file;
14383 ARGF_FORWARD(0, 0);
14404 return RBOOL(ARGF.binmode);
14424 if (ARGF.init_p && ARGF.next_p == 0) {
14453 if (ARGF.next_p != -1) {
14471 ARGF_FORWARD(0, 0);
14498 if (!ARGF.inplace)
return Qnil;
14506 return argf_inplace_mode_get(*var);
14537 ARGF.inplace =
Qnil;
14548 argf_inplace_mode_set(*var, val);
14552 ruby_set_inplace_mode(
const char *suffix)
14578 argf_argv_getter(
ID id,
VALUE *var)
14580 return argf_argv(*var);
14599 if (!
RTEST(ARGF.current_file)) {
14602 return GetWriteIO(ARGF.current_file);
14614 return rb_io_writev(argf_write_io(
argf), argc, argv);
14629 case RB_IO_WAIT_WRITABLE:
14632 c = rb_eEAGAINWaitWritable;
14634 #if EAGAIN != EWOULDBLOCK
14636 c = rb_eEWOULDBLOCKWaitWritable;
14640 c = rb_eEINPROGRESSWaitWritable;
14646 case RB_IO_WAIT_READABLE:
14649 c = rb_eEAGAINWaitReadable;
14651 #if EAGAIN != EWOULDBLOCK
14653 c = rb_eEWOULDBLOCKWaitReadable;
14657 c = rb_eEINPROGRESSWaitReadable;
14664 rb_bug(
"invalid read/write type passed to rb_readwrite_sys_fail: %d", waiting);
14670 get_LAST_READ_LINE(
ID _x,
VALUE *_y)
15551 #include <sys/cygwin.h>
15552 static struct __cygwin_perfile pf[] =
15554 {
"", O_RDONLY | O_BINARY},
15555 {
"", O_WRONLY | O_BINARY},
15556 {
"", O_RDWR | O_BINARY},
15557 {
"", O_APPEND | O_BINARY},
15560 cygwin_internal(CW_PERFILE, pf);
15615 #if EAGAIN == EWOULDBLOCK
15616 rb_eEWOULDBLOCKWaitReadable = rb_eEAGAINWaitReadable;
15619 rb_eEWOULDBLOCKWaitWritable = rb_eEAGAINWaitWritable;
15673 rb_gvar_ractor_local(
"$_");
15789 rb_gvar_ractor_local(
"$stdin");
15790 rb_gvar_ractor_local(
"$stdout");
15791 rb_gvar_ractor_local(
"$>");
15792 rb_gvar_ractor_local(
"$stderr");
15878 rb_define_method(rb_cARGF,
"external_encoding", argf_external_encoding, 0);
15879 rb_define_method(rb_cARGF,
"internal_encoding", argf_internal_encoding, 0);
15898 rb_gvar_ractor_local(
"$-i");
15902 #if defined (_WIN32) || defined(__CYGWIN__)
15903 atexit(pipe_atexit);
15915 sym_encoding =
ID2SYM(rb_id_encoding());
15939 #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.