24#include "ccan/list/list.h"
28# if defined(__linux__)
31# if defined(__FreeBSD_version) && __FreeBSD_version >= 1100000
47#define free(x) xfree(x)
49#if defined(DOSISH) || defined(__CYGWIN__)
54#if defined HAVE_NET_SOCKET_H
55# include <net/socket.h>
56#elif defined HAVE_SYS_SOCKET_H
57# include <sys/socket.h>
60#if defined(__BOW__) || defined(__CYGWIN__) || defined(_WIN32)
61# define NO_SAFE_RENAME
64#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__sun) || defined(_nec_ews)
73#if defined(HAVE_SYS_IOCTL_H) && !defined(_WIN32)
76#if defined(HAVE_FCNTL_H) || defined(_WIN32)
78#elif defined(HAVE_SYS_FCNTL_H)
82#if !HAVE_OFF_T && !defined(off_t)
92#if defined(HAVE_SYS_PARAM_H) || defined(__HIUX_MPP__)
93# include <sys/param.h>
106#elif defined HAVE_SYS_SYSCALL_H
107#include <sys/syscall.h>
114#ifdef HAVE_SYS_WAIT_H
115# include <sys/wait.h>
118#ifdef HAVE_COPYFILE_H
119# include <copyfile.h>
125#define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR)
128#if SIZEOF_OFF_T > SIZEOF_LONG && !defined(HAVE_LONG_LONG)
129# error off_t is bigger than long, but you have no long long...
133# ifdef _POSIX_PIPE_BUF
134# define PIPE_BUF _POSIX_PIPE_BUF
141# define EWOULDBLOCK EAGAIN
144#if defined(HAVE___SYSCALL) && (defined(__APPLE__) || defined(__OpenBSD__))
146off_t __syscall(quad_t number, ...);
149#define IO_RBUF_CAPA_MIN 8192
150#define IO_CBUF_CAPA_MIN (128*1024)
151#define IO_RBUF_CAPA_FOR(fptr) (NEED_READCONV(fptr) ? IO_CBUF_CAPA_MIN : IO_RBUF_CAPA_MIN)
152#define IO_WBUF_CAPA_MIN 8192
157#define open rb_w32_uopen
159#define rename(f, t) rb_w32_urename((f), (t))
163# define RUBY_PIPE_NONBLOCK_DEFAULT (0)
164#elif defined(O_NONBLOCK)
166# define RUBY_PIPE_NONBLOCK_DEFAULT (0)
168# define RUBY_PIPE_NONBLOCK_DEFAULT (0)
177static VALUE rb_eEAGAINWaitReadable;
178static VALUE rb_eEAGAINWaitWritable;
179static VALUE rb_eEWOULDBLOCKWaitReadable;
180static VALUE rb_eEWOULDBLOCKWaitWritable;
181static VALUE rb_eEINPROGRESSWaitWritable;
182static VALUE rb_eEINPROGRESSWaitReadable;
185static VALUE orig_stdout, orig_stderr;
194static ID id_write, id_read, id_getc, id_flush, id_readpartial, id_set_encoding;
195static VALUE sym_mode, sym_perm, sym_flags, sym_extenc, sym_intenc, sym_encoding, sym_open_args;
196static VALUE sym_textmode, sym_binmode, sym_autoclose;
197static VALUE sym_SET, sym_CUR, sym_END;
198static VALUE sym_wait_readable, sym_wait_writable;
200static VALUE sym_DATA;
203static VALUE sym_HOLE;
224 if (fd < 0 || afd <= max_fd)
227#if defined(HAVE_FCNTL) && defined(F_GETFL)
236 rb_bug(
"rb_update_max_fd: invalid fd (%d) given.", fd);
239 while (max_fd < afd) {
240 max_fd =
ATOMIC_CAS(max_file_descriptor, max_fd, afd);
248#if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
249 int flags, flags2, ret;
255 flags2 = flags & ~FD_CLOEXEC;
258 if (flags != flags2) {
261 rb_bug(
"rb_maygvl_fd_fix_cloexec: fcntl(%d, F_SETFD, %d) failed: %s", fd, flags2,
strerror(
errno));
276rb_fix_detect_o_cloexec(
int fd)
278#if defined(O_CLOEXEC) && defined(F_GETFD)
295 static int o_cloexec_state = -1;
300#elif defined O_NOINHERIT
301 flags |= O_NOINHERIT;
303 ret = open(pathname, flags, mode);
304 if (ret < 0)
return ret;
305 if (ret <= 2 || o_cloexec_state == 0) {
308 else if (o_cloexec_state > 0) {
312 o_cloexec_state = rb_fix_detect_o_cloexec(ret);
331 if (oldfd == newfd) {
335#if defined(HAVE_DUP3) && defined(O_CLOEXEC)
336 static int try_dup3 = 1;
337 if (2 < newfd && try_dup3) {
344 ret =
dup2(oldfd, newfd);
348 ret =
dup2(oldfd, newfd);
351 ret =
dup2(oldfd, newfd);
353 if (ret < 0)
return ret;
360rb_fd_set_nonblock(
int fd)
364#elif defined(F_GETFL)
365 int oflags =
fcntl(fd, F_GETFL);
382#if defined(HAVE_PIPE2)
383 static int try_pipe2 = 1;
400 if (ret < 0)
return ret;
402 if (ret == 0 && fildes[1] == -1) {
412 rb_fd_set_nonblock(fildes[0]);
413 rb_fd_set_nonblock(fildes[1]);
423#if defined(HAVE_FCNTL) && defined(F_DUPFD_CLOEXEC) && defined(F_DUPFD)
424 static int try_dupfd_cloexec = 1;
425 if (try_dupfd_cloexec) {
436 try_dupfd_cloexec = 0;
443#elif defined(HAVE_FCNTL) && defined(F_DUPFD)
445#elif defined(HAVE_DUP)
447 if (ret >= 0 && ret < minfd) {
448 const int prev_fd = ret;
454# error "dup() or fcntl(F_DUPFD) must be supported."
456 if (ret < 0)
return ret;
461#define argf_of(obj) (*(struct argf *)DATA_PTR(obj))
462#define ARGF argf_of(argf)
464#define GetWriteIO(io) rb_io_get_write_io(io)
466#define READ_DATA_PENDING(fptr) ((fptr)->rbuf.len)
467#define READ_DATA_PENDING_COUNT(fptr) ((fptr)->rbuf.len)
468#define READ_DATA_PENDING_PTR(fptr) ((fptr)->rbuf.ptr+(fptr)->rbuf.off)
469#define READ_DATA_BUFFERED(fptr) READ_DATA_PENDING(fptr)
471#define READ_CHAR_PENDING(fptr) ((fptr)->cbuf.len)
472#define READ_CHAR_PENDING_COUNT(fptr) ((fptr)->cbuf.len)
473#define READ_CHAR_PENDING_PTR(fptr) ((fptr)->cbuf.ptr+(fptr)->cbuf.off)
476#define WAIT_FD_IN_WIN32(fptr) \
477 (rb_w32_io_cancelable_p((fptr)->fd) ? 0 : rb_thread_wait_fd((fptr)->fd))
479#define WAIT_FD_IN_WIN32(fptr)
482#define READ_CHECK(fptr) do {\
483 if (!READ_DATA_PENDING(fptr)) {\
484 WAIT_FD_IN_WIN32(fptr);\
485 rb_io_check_closed(fptr);\
491# define S_ISSOCK(m) _S_ISSOCK(m)
494# define S_ISSOCK(m) (((m) & S_IFMT) == _S_IFSOCK)
497# define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
503static int io_fflush(
rb_io_t *);
506#define NEED_NEWLINE_DECORATOR_ON_READ(fptr) ((fptr)->mode & FMODE_TEXTMODE)
507#define NEED_NEWLINE_DECORATOR_ON_WRITE(fptr) ((fptr)->mode & FMODE_TEXTMODE)
508#if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
510# define DEFAULT_TEXTMODE FMODE_TEXTMODE
511# define TEXTMODE_NEWLINE_DECORATOR_ON_WRITE ECONV_CRLF_NEWLINE_DECORATOR
519#define NEED_READCONV(fptr) ((fptr)->encs.enc2 != NULL || (fptr)->encs.ecflags & ~ECONV_CRLF_NEWLINE_DECORATOR)
520#define WRITECONV_MASK ( \
521 (ECONV_DECORATOR_MASK & ~ECONV_CRLF_NEWLINE_DECORATOR)|\
522 ECONV_STATEFUL_DECORATOR_MASK|\
524#define NEED_WRITECONV(fptr) ( \
525 ((fptr)->encs.enc != NULL && (fptr)->encs.enc != rb_ascii8bit_encoding()) || \
526 ((fptr)->encs.ecflags & WRITECONV_MASK) || \
528#define SET_BINARY_MODE(fptr) setmode((fptr)->fd, O_BINARY)
530#define NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr) do {\
531 if (NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {\
532 if (((fptr)->mode & FMODE_READABLE) &&\
533 !((fptr)->encs.ecflags & ECONV_NEWLINE_DECORATOR_MASK)) {\
534 setmode((fptr)->fd, O_BINARY);\
537 setmode((fptr)->fd, O_TEXT);\
542#define SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags) do {\
543 if ((enc2) && ((ecflags) & ECONV_DEFAULT_NEWLINE_DECORATOR)) {\
544 (ecflags) |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;\
570 if (r < 0 &&
errno) {
582 if (pos < 0 &&
errno) {
589 extra_max = (
long)(pos - fptr->
rbuf.len);
590 p = fptr->
rbuf.ptr + fptr->
rbuf.off;
593 if (*(fptr->
rbuf.ptr + fptr->
rbuf.capa - 1) ==
'\r') {
597 for (
i = 0;
i < fptr->
rbuf.len;
i++) {
598 if (*p ==
'\n') newlines++;
599 if (extra_max == newlines)
break;
604 while (newlines >= 0) {
606 if (newlines == 0)
break;
611 read_size = _read(fptr->
fd,
buf, fptr->
rbuf.len + newlines);
617 if (read_size == fptr->
rbuf.len) {
639set_binary_mode_with_seek_cur(
rb_io_t *fptr)
646 flush_before_seek(fptr);
649#define SET_BINARY_MODE_WITH_SEEK_CUR(fptr) set_binary_mode_with_seek_cur(fptr)
653# define DEFAULT_TEXTMODE 0
654#define NEED_READCONV(fptr) ((fptr)->encs.enc2 != NULL || NEED_NEWLINE_DECORATOR_ON_READ(fptr))
655#define NEED_WRITECONV(fptr) ( \
656 ((fptr)->encs.enc != NULL && (fptr)->encs.enc != rb_ascii8bit_encoding()) || \
657 NEED_NEWLINE_DECORATOR_ON_WRITE(fptr) || \
658 ((fptr)->encs.ecflags & (ECONV_DECORATOR_MASK|ECONV_STATEFUL_DECORATOR_MASK)) || \
660#define SET_BINARY_MODE(fptr) (void)(fptr)
661#define NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr) (void)(fptr)
662#define SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags) ((void)(enc2), (void)(ecflags))
663#define SET_BINARY_MODE_WITH_SEEK_CUR(fptr) (void)(fptr)
666#if !defined HAVE_SHUTDOWN && !defined shutdown
667#define shutdown(a,b) 0
671#define is_socket(fd, path) rb_w32_is_socket(fd)
672#elif !defined(S_ISSOCK)
673#define is_socket(fd, path) 0
679 if (
fstat(fd, &sbuf) < 0)
685static const char closed_stream[] =
"closed stream";
688io_fd_check_closed(
int fd)
721 io_fd_check_closed(fptr->
fd);
725rb_io_get_fptr(
VALUE io)
759 rb_io_t *fptr = rb_io_get_fptr(io);
768 return write_io ? write_io :
Qnil;
794#if !(defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32))
805 if (r < 0 &&
errno) {
827#if SIZEOF_LONG > SIZEOF_INT
834 fptr->
rbuf.capa = min_capa;
843 char, fptr->
rbuf.len);
852flush_before_seek(
rb_io_t *fptr)
854 if (io_fflush(fptr) < 0)
861#define io_seek(fptr, ofs, whence) (errno = 0, lseek(flush_before_seek(fptr)->fd, (ofs), (whence)))
862#define io_tell(fptr) lseek(flush_before_seek(fptr)->fd, 0, SEEK_CUR)
877 if (fptr->
wbuf.len) {
878 if (io_fflush(fptr) < 0)
884 if (io_fflush(wfptr) < 0)
914io_input_encoding(
rb_io_t *fptr)
919 return io_read_encoding(fptr);
929 if (fptr->
rbuf.len) {
992# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
1009struct io_internal_writev_struct {
1012 const struct iovec *iov;
1016static int nogvl_wait_for_single_fd(
int fd,
short events);
1018internal_read_func(
void *
ptr)
1036#if defined __APPLE__
1037# define do_write_retry(code) do {ret = code;} while (ret == -1 && errno == EPROTOTYPE)
1039# define do_write_retry(code) ret = code
1042internal_write_func(
void *
ptr)
1051internal_write_func2(
void *
ptr)
1053 return (
void*)internal_write_func(
ptr);
1058internal_writev_func(
void *
ptr)
1060 struct io_internal_writev_struct *iis =
ptr;
1068rb_read_internal(
int fd,
void *
buf,
size_t count)
1081rb_write_internal(
int fd,
const void *
buf,
size_t count)
1092rb_write_internal2(
int fd,
const void *
buf,
size_t count)
1105rb_writev_internal(
int fd,
const struct iovec *iov,
int iovcnt)
1107 struct io_internal_writev_struct iis;
1110 iis.iovcnt = iovcnt;
1117io_flush_buffer_sync(
void *
arg)
1120 long l = fptr->
wbuf.len;
1123 if (fptr->
wbuf.len <= r) {
1137io_flush_buffer_sync2(
void *
arg)
1139 VALUE result = io_flush_buffer_sync(
arg);
1145 return !result ? (
void*)1 : (
void*)result;
1169 else if (ret == 1) {
1180 return (
int)io_flush_buffer_async2((
VALUE)fptr);
1185 return (
int)io_flush_buffer_async((
VALUE)fptr);
1193 if (fptr->
wbuf.len == 0)
1195 while (fptr->
wbuf.len > 0 && io_flush_buffer(fptr) != 0) {
1206 io_fd_check_closed(
f);
1209#if defined(ERESTART)
1216#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
1230 io_fd_check_closed(
f);
1233#if defined(ERESTART)
1249#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
1264 const char *senc, *denc;
1271 ecflags = fptr->
encs.
ecflags & ~ECONV_NEWLINE_DECORATOR_READ_MASK;
1338 struct iovec iov[2];
1345 r = rb_writev_internal(fptr->
fd, iov, 2);
1350 if (fptr->
wbuf.len <= r) {
1351 r -= fptr->
wbuf.len;
1362 r = rb_write_internal(fptr->
fd, p->
ptr, p->
length);
1378 if (
fptr->
wbuf.len+len <= fptr->wbuf.capa) {
1387 if (io_fflush(
fptr) < 0)
1403 long n, r, offset = 0;
1408 if ((
n =
len) <= 0)
return n;
1430 r = io_binwrite_string((
VALUE)&
arg);
1433 if (r ==
n)
return len;
1459# define MODE_BTMODE(a,b,c) ((fmode & FMODE_BINMODE) ? (b) : \
1460 (fmode & FMODE_TEXTMODE) ? (c) : (a))
1462#define MODE_BTXMODE(a, b, c, d, e, f) ((fmode & FMODE_EXCL) ? \
1463 MODE_BTMODE(d, e, f) : \
1464 MODE_BTMODE(a, b, c))
1473 make_writeconv(
fptr);
1476#define fmode (fptr->mode)
1480 rb_raise(
rb_eArgError,
"ASCII incompatible string written for text mode IO without encoding conversion: %s",
1492 if (!
NIL_P(common_encoding)) {
1503#if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
1504#define fmode (fptr->mode)
1511 setmode(
fptr->
fd, O_TEXT);
1514 rb_raise(
rb_eArgError,
"ASCII incompatible string written for text mode IO without encoding conversion: %s",
1585struct binwritev_arg {
1587 const struct iovec *iov;
1594 struct binwritev_arg *p = (
struct binwritev_arg *)
arg;
1595 return rb_writev_internal(p->fptr->fd, p->iov, p->iovcnt);
1599io_binwritev(
struct iovec *iov,
int iovcnt,
rb_io_t *fptr)
1602 long r, total = 0, written_len = 0;
1607 if (iovcnt == 0)
return 0;
1608 for (
i = 1;
i < iovcnt;
i++) total += iov[
i].iov_len;
1619 if (fptr->
wbuf.ptr && fptr->
wbuf.len) {
1620 long offset = fptr->
wbuf.off + fptr->
wbuf.len;
1621 if (offset + total <= fptr->wbuf.capa) {
1622 for (
i = 1;
i < iovcnt;
i++) {
1623 memcpy(fptr->
wbuf.ptr+offset, iov[
i].iov_base, iov[
i].iov_len);
1626 fptr->
wbuf.len += total;
1636 if (!--iovcnt)
return 0;
1641 struct binwritev_arg
arg;
1644 arg.iovcnt = iovcnt;
1648 r = rb_writev_internal(fptr->
fd, iov, iovcnt);
1653 if (fptr->
wbuf.ptr && fptr->
wbuf.len) {
1654 if (written_len < fptr->wbuf.len) {
1655 fptr->
wbuf.off += r;
1656 fptr->
wbuf.len -= r;
1659 written_len -= fptr->
wbuf.len;
1664 if (written_len == total)
return total;
1671 if (!--iovcnt)
return total;
1690 int i, converted, iovcnt =
argc + 1;
1692 VALUE v1, v2,
str, tmp, *tmp_array;
1701 str = do_writeconv(
str, fptr, &converted);
1712 n = io_binwritev(iov, iovcnt, fptr);
1725iovcnt_ok(
int iovcnt)
1799 return io_write(io,
str, 0);
1817 " which accepts just one argument",
1851nogvl_fsync(
void *
ptr)
1876 if (io_fflush(fptr) < 0)
1930 pos -= fptr->
rbuf.len;
1935rb_io_seek(
VALUE io,
VALUE offset,
int whence)
1942 pos =
io_seek(fptr, pos, whence);
1949interpret_seek_whence(
VALUE vwhence)
1951 if (vwhence == sym_SET)
1953 if (vwhence == sym_CUR)
1955 if (vwhence == sym_END)
1958 if (vwhence == sym_DATA)
1962 if (vwhence == sym_HOLE)
1992 VALUE offset, ptrname;
1996 whence = interpret_seek_whence(ptrname);
1999 return rb_io_seek(io, offset, whence);
2029static void clear_readconv(
rb_io_t *fptr);
2048rb_io_rewind(
VALUE io)
2054 if (io ==
ARGF.current_file) {
2059 clear_readconv(fptr);
2066fptr_wait_readable(
rb_io_t *fptr)
2089 if (fptr->
rbuf.len == 0) {
2092 r = rb_read_internal(fptr->
fd, fptr->
rbuf.ptr, fptr->
rbuf.capa);
2095 if (fptr_wait_readable(fptr))
2159#if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
2164 if (io_fillbuf(fptr) < 0) {
2219 fptr->
mode &= ~FMODE_SYNC;
2245 if (io_fflush(fptr) < 0)
2252# define rb_io_fsync rb_f_notimplement
2253# define rb_io_sync rb_f_notimplement
2262#ifdef HAVE_FDATASYNC
2264nogvl_fdatasync(
void *
ptr)
2294 if (io_fflush(fptr) < 0)
2304#define rb_io_fdatasync rb_io_fsync
2320rb_io_fileno(
VALUE io)
2375 static const char closed[] =
" (closed)";
2407rb_io_to_io(
VALUE io)
2419 if (
n <= 0)
return 0;
2422 fptr->
rbuf.off +=
n;
2423 fptr->
rbuf.len -=
n;
2437 c = rb_read_internal(fptr->
fd,
ptr+offset,
n);
2440 if (fptr_wait_readable(fptr))
2445 if ((
n -= c) <= 0)
break;
2451 c = read_buffered_data(
ptr+offset,
n, fptr);
2454 if ((
n -= c) <= 0)
break;
2457 if (io_fillbuf(fptr) < 0) {
2486 io_setstrbuf(&
str, offset +
size);
2504#
if defined(__HAIKU__)
2509 if (io_fflush(fptr) < 0)
2512 if (
st.st_size >= pos && pos >= 0) {
2513 siz +=
st.st_size - pos;
2538 const char *sname, *dname;
2539 ecflags = fptr->
encs.
ecflags & ~ECONV_NEWLINE_DECORATOR_WRITE_MASK;
2559#define MORE_CHAR_SUSPENDED Qtrue
2560#define MORE_CHAR_FINISHED Qnil
2562fill_cbuf(
rb_io_t *fptr,
int ec_flags)
2564 const unsigned char *ss, *sp, *se;
2565 unsigned char *ds, *
dp, *de;
2573 if (fptr->
cbuf.len == fptr->
cbuf.capa)
2575 if (fptr->
cbuf.len == 0)
2577 else if (fptr->
cbuf.off + fptr->
cbuf.len == fptr->
cbuf.capa) {
2582 cbuf_len0 = fptr->
cbuf.len;
2585 ss = sp = (
const unsigned char *)fptr->
rbuf.ptr + fptr->
rbuf.off;
2586 se = sp + fptr->
rbuf.len;
2587 ds =
dp = (
unsigned char *)fptr->
cbuf.ptr + fptr->
cbuf.off + fptr->
cbuf.len;
2588 de = (
unsigned char *)fptr->
cbuf.ptr + fptr->
cbuf.capa;
2590 fptr->
rbuf.off += (
int)(sp - ss);
2591 fptr->
rbuf.len -= (
int)(sp - ss);
2597 fptr->
rbuf.off -= putbackable;
2598 fptr->
rbuf.len += putbackable;
2605 if (cbuf_len0 != fptr->
cbuf.len)
2613 if (fptr->
rbuf.len == 0) {
2615 if (io_fillbuf(fptr) < 0) {
2619 ds =
dp = (
unsigned char *)fptr->
cbuf.ptr + fptr->
cbuf.off + fptr->
cbuf.len;
2620 de = (
unsigned char *)fptr->
cbuf.ptr + fptr->
cbuf.capa;
2629 if (cbuf_len0 != fptr->
cbuf.len)
2662 if (fptr->
cbuf.len == 0)
2664 else if (fptr->
cbuf.capa/2 < fptr->
cbuf.off) {
2694#define MAX_REALLOC_GAP 4096
2704io_set_read_length(
VALUE str,
long n,
int shrinkable)
2709 if (shrinkable) io_shrink_read_string(
str,
n);
2726 shrinkable = io_setstrbuf(&
str,0);
2727 make_readconv(fptr, 0);
2730 if (fptr->
cbuf.len) {
2732 io_shift_cbuf(fptr, fptr->
cbuf.len, &
str);
2734 v = fill_cbuf(fptr, 0);
2736 if (fptr->
cbuf.len) {
2738 io_shift_cbuf(fptr, fptr->
cbuf.len, &
str);
2743 clear_readconv(fptr);
2746 return io_enc_str(
str, fptr);
2755 enc = io_read_encoding(fptr);
2758 if (siz == 0) siz =
BUFSIZ;
2759 shrinkable = io_setstrbuf(&
str, siz);
2762 n = io_fread(
str, bytes, siz - bytes, fptr);
2763 if (
n == 0 && bytes == 0) {
2771 if (bytes < siz)
break;
2776 str = io_enc_str(
str, fptr);
2784 if (rb_fd_set_nonblock(fptr->
fd) != 0) {
2803#define no_exception_p(opts) !rb_opts_exception_p((opts), TRUE)
2820 shrinkable = io_setstrbuf(&
str,
len);
2826 io_set_read_length(
str, 0, shrinkable);
2843 n = read_internal_locktmp(
str, &iis);
2846 if (!
nonblock && fptr_wait_readable(fptr))
2850 return sym_wait_readable;
2853 e,
"read would block");
2858 io_set_read_length(
str,
n, shrinkable);
2943io_nonblock_eof(
int no_exception)
2945 if (!no_exception) {
2964 shrinkable = io_setstrbuf(&
str,
len);
2971 io_set_read_length(
str, 0, shrinkable);
2978 shrinkable |= io_setstrbuf(&
str,
len);
2983 n = read_internal_locktmp(
str, &iis);
2987 if (!ex)
return sym_wait_readable;
2989 e,
"read would block");
2994 io_set_read_length(
str,
n, shrinkable);
2997 if (!ex)
return Qnil;
3019 if (io_fflush(fptr) < 0)
3030 return sym_wait_writable;
3116#if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
3122 if (
NIL_P(length)) {
3125 return read_all(fptr, remain_size(fptr),
str);
3132 shrinkable = io_setstrbuf(&
str,
len);
3137 io_set_read_length(
str, 0, shrinkable);
3142#if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
3143 previous_mode = set_binary_mode_with_seek_cur(fptr);
3145 n = io_fread(
str, 0,
len, fptr);
3146 io_set_read_length(
str,
n, shrinkable);
3147#if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
3148 if (previous_mode == O_TEXT) {
3149 setmode(fptr->
fd, O_TEXT);
3152 if (
n == 0)
return Qnil;
3158rscheck(
const char *rsptr,
long rslen,
VALUE rs)
3166appendline(
rb_io_t *fptr,
int delim,
VALUE *strp,
long *lp)
3173 make_readconv(fptr, 0);
3179 if (0 < limit && limit < searchlen)
3180 searchlen = (
int)limit;
3181 e =
memchr(p, delim, searchlen);
3199 fptr->
cbuf.off += searchlen;
3200 fptr->
cbuf.len -= searchlen;
3209 clear_readconv(fptr);
3222 if (limit > 0 && pending > limit) pending = limit;
3223 e =
memchr(p, delim, pending);
3224 if (e) pending = e - p + 1;
3237 if (e)
return delim;
3242 }
while (io_fillbuf(fptr) >= 0);
3254 make_readconv(fptr, 0);
3263 while (--
i && *++p ==
term);
3266 const char *e = p +
cnt;
3271 io_shift_cbuf(fptr, (
int)
cnt -
i,
NULL);
3287 while (--
i && *++p ==
term);
3288 if (!read_buffered_data(
buf,
cnt -
i, fptr))
3292 }
while (io_fillbuf(fptr) == 0);
3312 e =
memchr(p,
'\n', pending);
3314 pending = (
int)(e - p + 1);
3316 chomplen = (pending > 1 && *(e-1) ==
'\r') + 1;
3321 fptr->
rbuf.off += pending;
3322 fptr->
rbuf.len -= pending;
3327 fptr->
rbuf.off += chomplen;
3328 fptr->
rbuf.len -= chomplen;
3329 if (pending == 1 && chomplen == 1 &&
len > 0) {
3336 len += pending - chomplen;
3342 }
while (io_fillbuf(fptr) >= 0);
3345 str = io_enc_str(
str, fptr);
3356 unsigned int chomp: 1;
3372 args->
chomp = chomp;
3390 else if (2 <=
argc) {
3400check_getline_args(
VALUE *rsp,
long *limit,
VALUE io)
3410 enc_io = io_read_encoding(fptr);
3411 if (enc_io != enc_rs &&
3433 extract_getline_args(
argc,
argv, args);
3434 extract_getline_opts(opts, args);
3435 check_getline_args(&args->
rs, &args->
limit, io);
3439rb_io_getline_0(
VALUE rs,
long limit,
int chomp,
rb_io_t *fptr)
3446 if (
NIL_P(rs) && limit < 0) {
3447 str = read_all(fptr, 0,
Qnil);
3451 else if (limit == 0) {
3457 return rb_io_getline_fast(fptr, enc, chomp);
3460 int c, newline = -1;
3461 const char *rsptr = 0;
3464 int extra_limit = 16;
3465 int chomp_cr = chomp;
3468 enc = io_read_encoding(fptr);
3476 swallow(fptr,
'\n');
3489 newline = (
unsigned char)rsptr[rslen - 1];
3490 chomp_cr = chomp && rslen == 1 && newline ==
'\n';
3494 while ((c = appendline(fptr, newline, &
str, &limit)) !=
EOF) {
3495 const char *s, *p, *pp, *e;
3503 if (pp != p)
continue;
3504 if (!rspara) rscheck(rsptr, rslen, rs);
3505 if (
memcmp(p, rsptr, rslen) == 0) {
3507 if (chomp_cr && p > s && *(p-1) ==
'\r') --p;
3531 if (rspara && c !=
EOF)
3532 swallow(fptr,
'\n');
3534 str = io_enc_str(
str, fptr);
3545rb_io_getline_1(
VALUE rs,
long limit,
int chomp,
VALUE io)
3548 int old_lineno, new_lineno;
3552 old_lineno = fptr->
lineno;
3553 str = rb_io_getline_0(rs, limit, chomp, fptr);
3555 if (io ==
ARGF.current_file) {
3556 ARGF.lineno += new_lineno - old_lineno;
3560 ARGF.last_lineno = new_lineno;
3746 return io_readlines(&args,
io);
3754 if (
arg->limit == 0)
3757 while (!
NIL_P(line = rb_io_getline_1(
arg->rs,
arg->limit,
arg->chomp,
io))) {
3802 if (args.
limit == 0)
3849 while (fptr->
rbuf.len > 0) {
3850 char *p = fptr->
rbuf.ptr + fptr->
rbuf.off++;
3857 }
while (io_fillbuf(fptr) >= 0);
3871 return rb_io_each_byte(
io);
3885 make_readconv(fptr, 0);
3888 if (fptr->
cbuf.len) {
3894 if (fptr->
cbuf.len == fptr->
cbuf.capa) {
3900 if (fptr->
cbuf.len == 0) {
3901 clear_readconv(fptr);
3906 fptr->
cbuf.off += 1;
3907 fptr->
cbuf.len -= 1;
3908 if (fptr->
cbuf.len == 0) clear_readconv(fptr);
3917 io_shift_cbuf(fptr, r, &
str);
3928 str = io_enc_str(
str, fptr);
3934 if (io_fillbuf(fptr) < 0) {
3939 fptr->
rbuf.off += 1;
3940 fptr->
rbuf.len -= 1;
3948 fptr->
rbuf.off +=
n;
3949 fptr->
rbuf.len -=
n;
3956 if (io_fillbuf(fptr) != -1) {
3976 str = io_enc_str(
str, fptr);
4007 enc = io_input_encoding(fptr);
4009 while (!
NIL_P(c = io_getc(fptr, enc))) {
4025 return rb_io_each_char(
io);
4061 make_readconv(fptr, 0);
4063 if (fptr->
cbuf.len) {
4072 if (fptr->
cbuf.len == fptr->
cbuf.capa) {
4077 clear_readconv(fptr);
4098 fptr->
cbuf.off +=
n;
4099 fptr->
cbuf.len -=
n;
4104 enc = io_input_encoding(fptr);
4105 while (io_fillbuf(fptr) >= 0) {
4112 fptr->
rbuf.off +=
n;
4113 fptr->
rbuf.len -=
n;
4121 char cbuf[8], *p = cbuf;
4123 if (more >
numberof(cbuf))
goto invalid;
4124 more +=
n = fptr->
rbuf.len;
4125 if (more >
numberof(cbuf))
goto invalid;
4126 while ((
n = (
int)read_buffered_data(p, more, fptr)) > 0 &&
4127 (p +=
n, (more -=
n) > 0)) {
4128 if (io_fillbuf(fptr) < 0)
goto invalid;
4129 if ((
n = fptr->
rbuf.len) > more)
n = more;
4153 return rb_io_each_codepoint(
io);
4178 enc = io_input_encoding(fptr);
4180 return io_getc(fptr, enc);
4234 if (io_fillbuf(fptr) < 0) {
4292 unsigned char c =
NUM2INT(
v) & 0xFF;
4298 io_ungetbyte(b, fptr);
4339#if SIZEOF_LONG > SIZEOF_INT
4343 make_readconv(fptr, (
int)
len);
4349 char, fptr->
cbuf.len);
4358 io_ungetbyte(c, fptr);
4386#if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
4409 if (
io != write_io) {
4411 if (fptr && 0 <= (fd = fptr->
fd)) {
4418 if (fptr && 0 <= (fd = fptr->
fd)) {
4425#define rb_io_close_on_exec_p rb_f_notimplement
4428#if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
4458 if (
io != write_io) {
4460 if (fptr && 0 <= (fd = fptr->
fd)) {
4463 ret = (ret & ~FD_CLOEXEC) | flag;
4472 if (fptr && 0 <= (fd = fptr->
fd)) {
4475 ret = (ret & ~FD_CLOEXEC) | flag;
4483#define rb_io_set_close_on_exec rb_f_notimplement
4486#define FMODE_PREP (1<<16)
4487#define IS_PREP_STDIO(f) ((f)->mode & FMODE_PREP)
4488#define PREP_STDIO_NAME(f) (RSTRING_PTR((f)->pathv))
4491finish_writeconv(
rb_io_t *fptr,
int noalloc)
4493 unsigned char *ds, *
dp, *de;
4496 if (!fptr->
wbuf.ptr) {
4497 unsigned char buf[1024];
4508 r = rb_write_internal2(fptr->
fd, ds,
dp-ds);
4510 r = rb_write_internal(fptr->
fd, ds,
dp-ds);
4535 if (fptr->
wbuf.len == fptr->
wbuf.capa) {
4536 if (io_fflush(fptr) < 0)
4540 ds =
dp = (
unsigned char *)fptr->
wbuf.ptr + fptr->
wbuf.off + fptr->
wbuf.len;
4541 de = (
unsigned char *)fptr->
wbuf.ptr + fptr->
wbuf.capa;
4566nogvl_close(
void *
ptr)
4574maygvl_close(
int fd,
int keepgvl)
4587nogvl_fclose(
void *
ptr)
4595maygvl_fclose(
FILE *file,
int keepgvl)
4607fptr_finalize_flush(
rb_io_t *
fptr,
int noraise,
int keepgvl,
4619 arg.noalloc = noraise;
4623 err = finish_writeconv(
fptr, noraise);
4628 io_flush_buffer_sync(
fptr);
4651 else if (stdio_file) {
4654 if ((maygvl_fclose(stdio_file, noraise) < 0) &&
NIL_P(
err))
4665 if ((maygvl_close(fd, keepgvl) < 0) &&
NIL_P(
err))
4680 fptr_finalize_flush(
fptr, noraise,
FALSE, 0);
4683 clear_codeconv(
fptr);
4693 fptr_finalize(
fptr, noraise);
4729 clear_readconv(
fptr);
4730 clear_writeconv(
fptr);
4745 clear_codeconv(
fptr);
4749#undef rb_io_fptr_finalize
4761#define rb_io_fptr_finalize(fptr) rb_io_fptr_finalize_internal(fptr)
4777# define KEEPGVL TRUE
4779# define KEEPGVL FALSE
4784io_close_fptr(
VALUE io)
4791 list_head_init(&busy);
4793 if (io != write_io) {
4794 write_fptr =
RFILE(write_io)->fptr;
4795 if (write_fptr && 0 <= write_fptr->
fd) {
4796 rb_io_fptr_cleanup(write_fptr,
TRUE);
4800 fptr =
RFILE(io)->fptr;
4801 if (!fptr)
return 0;
4802 if (fptr->
fd < 0)
return 0;
4808 rb_io_fptr_cleanup(fptr,
FALSE);
4813fptr_waitpid(
rb_io_t *fptr,
int nohang)
4826 rb_io_t *fptr = io_close_fptr(io);
4827 if (fptr) fptr_waitpid(fptr, 0);
4847rb_io_close_m(
VALUE io)
4849 rb_io_t *fptr = rb_io_get_fptr(io);
4858io_call_close(
VALUE io)
4867 enum {mesg_len =
sizeof(closed_stream)-1};
4882 rb_rescue2(io_call_close, io, ignore_closed_stream, io,
4907rb_io_closed(
VALUE io)
4914 if (io != write_io) {
4915 write_fptr =
RFILE(write_io)->fptr;
4916 if (write_fptr && 0 <= write_fptr->
fd) {
4921 fptr = rb_io_get_fptr(io);
4946rb_io_close_read(
VALUE io)
4952 if (fptr->
fd < 0)
return Qnil;
4959 fptr->
mode &= ~FMODE_READABLE;
4966 if (io != write_io) {
4971 RFILE(io)->fptr = wfptr;
4974 RFILE(write_io)->fptr = fptr;
4975 rb_io_fptr_cleanup(fptr,
FALSE);
5008rb_io_close_write(
VALUE io)
5015 if (fptr->
fd < 0)
return Qnil;
5022 fptr->
mode &= ~FMODE_WRITABLE;
5032 if (io != write_io) {
5056 VALUE offset, ptrname;
5062 whence = interpret_seek_whence(ptrname);
5071 rb_warn(
"sysseek for buffered IO");
5074 pos =
lseek(fptr->
fd, pos, whence);
5108 if (fptr->
wbuf.len) {
5109 rb_warn(
"syswrite for buffered IO");
5114 n = rb_write_internal(fptr->
fd,
ptr,
len);
5152 shrinkable = io_setstrbuf(&
str, ilen);
5153 if (ilen == 0)
return str;
5173 io_setstrbuf(&
str, ilen);
5178 n = read_internal_locktmp(
str, &iis);
5183 io_set_read_length(
str,
n, shrinkable);
5184 if (
n == 0 && ilen > 0) {
5191#if defined(HAVE_PREAD) || defined(HAVE_PWRITE)
5192struct prdwr_internal_arg {
5200#if defined(HAVE_PREAD)
5202internal_pread_func(
void *
arg)
5204 struct prdwr_internal_arg *p =
arg;
5205 return (
VALUE)
pread(p->fd, p->buf, p->count, p->offset);
5211 struct prdwr_internal_arg *p = (
struct prdwr_internal_arg *)
arg;
5243 struct prdwr_internal_arg
arg;
5250 shrinkable = io_setstrbuf(&
str, (
long)
arg.count);
5251 if (
arg.count == 0)
return str;
5266 io_set_read_length(
str,
n, shrinkable);
5267 if (
n == 0 &&
arg.count > 0) {
5274# define rb_io_pread rb_f_notimplement
5277#if defined(HAVE_PWRITE)
5279internal_pwrite_func(
void *
ptr)
5281 struct prdwr_internal_arg *
arg =
ptr;
5310 struct prdwr_internal_arg
arg;
5334# define rb_io_pwrite rb_f_notimplement
5348 fptr->
mode &= ~FMODE_TEXTMODE;
5362io_ascii8bit_binmode(
rb_io_t *fptr)
5373 fptr->
mode &= ~FMODE_TEXTMODE;
5380 clear_codeconv(fptr);
5389 io_ascii8bit_binmode(fptr);
5407rb_io_binmode_m(
VALUE io)
5426rb_io_binmode_p(
VALUE io)
5434rb_io_fmode_modestr(
int fmode)
5448 return MODE_BTXMODE(
"w",
"wb",
"wt",
"wx",
"wbx",
"wtx");
5451 return MODE_BTXMODE(
"w+",
"wb+",
"wt+",
"w+x",
"wb+x",
"wt+x");
5457static const char bom_prefix[] =
"bom|";
5458static const char utf_prefix[] =
"utf-";
5463io_encname_bom_p(
const char *
name,
long len)
5472 const char *m = modestr, *p =
NULL;
5501 if (modestr[0] !=
'w')
5509 if (io_encname_bom_p(m, p ? (
long)(p - m) : (
long)
strlen(m)))
5539 if (oflags & O_APPEND) {
5542 if (oflags & O_TRUNC) {
5545 if (oflags & O_CREAT) {
5548 if (oflags & O_EXCL) {
5561rb_io_fmode_oflags(
int fmode)
5605rb_io_oflags_modestr(
int oflags)
5608# define MODE_BINARY(a,b) ((oflags & O_BINARY) ? (b) : (a))
5610# define MODE_BINARY(a,b) (a)
5613 if (oflags & O_EXCL) {
5616 accmode = oflags & (O_RDONLY|O_WRONLY|O_RDWR);
5617 if (oflags & O_APPEND) {
5618 if (accmode == O_WRONLY) {
5621 if (accmode == O_RDWR) {
5633 if (oflags & O_TRUNC) {
5648 int default_ext = 0;
5658 else if (intern ==
NULL) {
5664 *enc = (default_ext && intern != ext) ?
NULL : ext;
5680parse_mode_enc(
const char *estr,
rb_encoding *estr_enc,
5686 int fmode = fmode_p ? *fmode_p : 0;
5693 len = p ? (p++ - estr) : (
long)
strlen(estr);
5701 rb_enc_warn(estr_enc,
"BOM with non-UTF encoding %s is nonsense", estr);
5702 fmode &= ~FMODE_SETENC_BY_BOM;
5711 encname[
len] =
'\0';
5716 if (fmode_p) *fmode_p =
fmode;
5722 unsupported_encoding(estr, estr_enc);
5728 if (*p ==
'-' && *(p+1) ==
'\0') {
5735 unsupported_encoding(p, estr_enc);
5744 rb_io_ext_int_to_encs(ext_enc, int_enc, enc_p, enc2_p,
fmode);
5758 if (
v !=
Qnil) encoding =
v;
5760 if (
v !=
Qnil) extenc =
v;
5769 encoding, extenc ==
Qundef ?
"internal" :
"external");
5777 if (
NIL_P(intenc)) {
5784 if (*p ==
'-' && *(p+1) ==
'\0') {
5795 if (extencoding == intencoding) {
5799 if (!
NIL_P(encoding)) {
5803 enc_p, enc2_p, fmode_p);
5811 rb_io_ext_int_to_encs(extencoding, intencoding, enc_p, enc2_p, 0);
5821 int fmode = *fmode_p;
5837#if !DEFAULT_TEXTMODE
5839 fmode &= ~FMODE_TEXTMODE;
5848 if (!
NIL_P(opthash)) {
5876 int *oflags_p,
int *fmode_p,
convconfig_t *convconfig_p)
5883 int has_enc = 0, has_vmode = 0;
5889 rb_io_ext_int_to_encs(
NULL,
NULL, &enc, &enc2, 0);
5907 oflags = rb_io_fmode_oflags(
fmode);
5917 rb_io_ext_int_to_encs(e,
NULL, &enc, &enc2,
fmode);
5921 if (
NIL_P(opthash)) {
5925#ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
5928 0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE) : 0;
5938 if (!
NIL_P(vmode)) {
5953 extract_binmode(opthash, &
fmode);
5962 else if (
NIL_P(vmode)) {
5969 if (!
NIL_P(*vperm_p)) {
5981#ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
5984 0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE) : 0;
5996 validate_enc_binmode(&
fmode, ecflags, enc, enc2);
6002 convconfig_p->enc = enc;
6003 convconfig_p->enc2 = enc2;
6004 convconfig_p->ecflags = ecflags;
6005 convconfig_p->ecopts = ecopts;
6015sysopen_func(
void *
ptr)
6043 fd = rb_sysopen_internal(&data);
6047 fd = rb_sysopen_internal(&data);
6064 file =
fdopen(fd, modestr);
6071 file =
fdopen(fd, modestr);
6076 file =
fdopen(fd, modestr);
6091 rb_warn(
"setvbuf() can't be honoured (fd=%d)", fd);
6109io_strip_bom(
VALUE io)
6111 VALUE b1, b2, b3, b4;
6172io_set_encoding_by_bom(
VALUE io)
6174 int idx = io_strip_bom(io);
6182 rb_io_internal_encoding(io),
Qnil);
6204 validate_enc_binmode(&
fmode, convconfig->ecflags,
6205 convconfig->enc, convconfig->enc2);
6209 fptr->
encs = *convconfig;
6212 if (!(
oflags & O_TMPFILE)) {
6213 fptr->
pathv = pathv;
6216 fptr->
pathv = pathv;
6226rb_file_open_internal(
VALUE io,
VALUE filename,
const char *modestr)
6229 const char *p =
strchr(modestr,
':');
6234 &convconfig.enc, &convconfig.enc2, &
fmode);
6235 convconfig.ecflags = 0;
6236 convconfig.ecopts =
Qnil;
6243 rb_io_ext_int_to_encs(e,
NULL, &convconfig.enc, &convconfig.enc2,
fmode);
6244 convconfig.ecflags = 0;
6245 convconfig.ecopts =
Qnil;
6248 return rb_file_open_generic(io, filename,
6249 rb_io_fmode_oflags(
fmode),
6259 return rb_file_open_internal(io_alloc(
rb_cFile),
fname, modestr);
6268#if defined(__CYGWIN__) || !defined(HAVE_WORKING_FORK)
6269static struct pipe_list {
6271 struct pipe_list *next;
6277 struct pipe_list *
list;
6281 list->next = pipe_list;
6288 struct pipe_list **prev = &pipe_list;
6289 struct pipe_list *tmp;
6291 while ((tmp = *prev) != 0) {
6292 if (tmp->fptr == fptr) {
6301#if defined (_WIN32) || defined(__CYGWIN__)
6305 struct pipe_list *
list = pipe_list;
6306 struct pipe_list *tmp;
6317pipe_finalize(
rb_io_t *fptr,
int noraise)
6319#if !defined(HAVE_WORKING_FORK) && !defined(_WIN32)
6328 fptr_finalize(fptr, noraise);
6330 pipe_del_fptr(fptr);
6337#if defined(__CYGWIN__) || !defined(HAVE_WORKING_FORK)
6345#if defined(__CYGWIN__) || !defined(HAVE_WORKING_FORK)
6346 if (old_finalize != pipe_finalize) {
6347 struct pipe_list *
list;
6349 if (
list->fptr == fptr)
break;
6351 if (!
list) pipe_add_fptr(fptr);
6354 pipe_del_fptr(fptr);
6390#define HAVE_SPAWNV 1
6391#define spawnv(mode, cmd, args) rb_w32_uaspawn((mode), (cmd), (args))
6392#define spawn(mode, cmd) rb_w32_uspawn((mode), (cmd), 0)
6395#if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
6405#ifdef HAVE_WORKING_FORK
6407popen_redirect(
struct popen_arg *p)
6410 close(p->write_pair[1]);
6411 if (p->write_pair[0] != 0) {
6412 dup2(p->write_pair[0], 0);
6413 close(p->write_pair[0]);
6416 if (p->pair[1] != 1) {
6417 dup2(p->pair[1], 1);
6423 if (p->pair[1] != 1) {
6424 dup2(p->pair[1], 1);
6430 if (p->pair[0] != 0) {
6431 dup2(p->pair[0], 0);
6437#if defined(__linux__)
6448linux_get_maxfd(
void)
6451 char buf[4096], *p, *np, *e;
6454 if (fd < 0)
return fd;
6456 if (ss < 0)
goto err;
6459 while ((
int)
sizeof(
"FDSize:\t0\n")-1 <= e-p &&
6461 if (
memcmp(p,
"FDSize:",
sizeof(
"FDSize:")-1) == 0) {
6463 p +=
sizeof(
"FDSize:")-1;
6483#if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
6485 int max = (
int)max_file_descriptor;
6488 ret =
fcntl(0, F_MAXFD);
6490 maxhint = max = ret;
6491# elif defined(__linux__)
6492 ret = linux_get_maxfd();
6499 for (fd = lowfd; fd <= max; fd++) {
6500 if (!
NIL_P(noclose_fds) &&
6507# define CONTIGUOUS_CLOSED_FDS 20
6509 if (max < fd + CONTIGUOUS_CLOSED_FDS)
6510 max = fd + CONTIGUOUS_CLOSED_FDS;
6517popen_exec(
void *pp,
char *errmsg,
size_t errmsg_len)
6519 struct popen_arg *p = (
struct popen_arg*)pp;
6525#if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
6527rb_execarg_fixup_v(
VALUE execarg_obj)
6537pipe_open(
VALUE execarg_obj,
const char *modestr,
int fmode,
6547#if defined(HAVE_WORKING_FORK)
6549 char errmsg[80] = {
'\0' };
6551#if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
6553 struct popen_arg
arg;
6556#if defined(HAVE_SPAWNV)
6557# if defined(HAVE_SPAWNVE)
6558# define DO_SPAWN(cmd, args, envp) ((args) ? \
6559 spawnve(P_NOWAIT, (cmd), (args), (envp)) : \
6560 spawne(P_NOWAIT, (cmd), (envp)))
6562# define DO_SPAWN(cmd, args, envp) ((args) ? \
6563 spawnv(P_NOWAIT, (cmd), (args)) : \
6564 spawn(P_NOWAIT, (cmd)))
6566# if !defined(HAVE_WORKING_FORK)
6568# if defined(HAVE_SPAWNVE)
6573#if !defined(HAVE_WORKING_FORK)
6579#if !defined(HAVE_WORKING_FORK)
6580 const char *
cmd = 0;
6586#if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
6587 arg.execarg_obj = execarg_obj;
6590 arg.pair[0] =
arg.pair[1] = -1;
6591 arg.write_pair[0] =
arg.write_pair[1] = -1;
6592# if !defined(HAVE_WORKING_FORK)
6627 if (!
NIL_P(execarg_obj)) {
6628 rb_protect(rb_execarg_fixup_v, execarg_obj, &state);
6630 if (0 <=
arg.write_pair[0])
close(
arg.write_pair[0]);
6631 if (0 <=
arg.write_pair[1])
close(
arg.write_pair[1]);
6638# if defined(HAVE_WORKING_FORK)
6642# if defined(HAVE_SPAWNVE)
6645 while ((pid = DO_SPAWN(
cmd, args, envp)) < 0) {
6647 switch (e =
errno) {
6649# if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
6663# if defined(HAVE_WORKING_FORK)
6667 popen_redirect(&
arg);
6679# if defined(HAVE_WORKING_FORK)
6688# if defined(HAVE_WORKING_FORK)
6698 write_fd =
arg.write_pair[1];
6710 if (!
NIL_P(execarg_obj)) {
6730 fptr->
encs = *convconfig;
6731#if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
6741#ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
6743 fptr->
encs.
ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
6749 if (0 <= write_fd) {
6750 write_port = io_alloc(
rb_cIO);
6752 write_fptr->
fd = write_fd;
6754 fptr->
mode &= ~FMODE_WRITABLE;
6759#if defined (__CYGWIN__) || !defined(HAVE_WORKING_FORK)
6761 pipe_add_fptr(fptr);
6767is_popen_fork(
VALUE prog)
6770#if !defined(HAVE_WORKING_FORK)
6772 "fork() function is unimplemented on this machine");
6781pipe_open_s(
VALUE prog,
const char *modestr,
int fmode,
6788 if (!is_popen_fork(prog))
6790 return pipe_open(execarg_obj, modestr,
fmode, convconfig);
6796 rb_io_t *fptr = io_close_fptr(io);
6892 const char *modestr;
6907 int ex = !
NIL_P(opt);
6915#if SIZEOF_LONG > SIZEOF_INT
6926 if (!is_popen_fork(pname))
6929 if (!
NIL_P(execarg_obj)) {
6936 modestr = rb_io_oflags_modestr(oflags);
6938 port = pipe_open(execarg_obj, modestr,
fmode, &convconfig);
6958 VALUE *fname_p,
int *oflags_p,
int *fmode_p,
6961 VALUE opt, fname, vmode, vperm;
6986 rb_scan_open_args(
argc,
argv, &fname, &oflags, &
fmode, &convconfig, &perm);
6987 rb_file_open_generic(io, fname, oflags,
fmode, &convconfig, perm);
7054 VALUE fname, vmode, vperm;
7070 if (
NIL_P(vperm)) perm = 0666;
7074 fd = rb_sysopen(fname, oflags, perm);
7079check_pipe_command(
VALUE filename_or_command)
7195 int redirect =
FALSE;
7209 VALUE cmd = check_pipe_command(tmp);
7239 return rb_io_open_generic(io, filename, oflags,
fmode, &convconfig, perm);
7248 return pipe_open_s(
cmd, rb_io_oflags_modestr(oflags),
fmode, convconfig);
7251 return rb_file_open_generic(io_alloc(
klass), filename,
7252 oflags,
fmode, convconfig, perm);
7267 if (fptr == orig)
return io;
7273 "%s can't change access mode from \"%s\" to \"%s\"",
7275 rb_io_fmode_modestr(orig->
mode));
7279 if (io_fflush(fptr) < 0)
7283 flush_before_seek(fptr);
7289 if (io_fflush(orig) < 0)
7299 fptr_copy_finalizer(fptr, orig);
7372 VALUE fname, nmode, opt;
7379 return io_reopen(file, tmp);
7385 fptr =
RFILE(file)->fptr;
7399 "%s can't change access mode from \"%s\" to \"%s\"",
7401 rb_io_fmode_modestr(
fmode));
7404 fptr->
encs = convconfig;
7407 oflags = rb_io_fmode_oflags(fptr->
mode);
7410 fptr->
pathv = fname;
7412 fptr->
fd = rb_sysopen(fptr->
pathv, oflags, 0666);
7418 if (io_fflush(fptr) < 0)
7421 fptr->
rbuf.off = fptr->
rbuf.len = 0;
7425 rb_io_oflags_modestr(oflags),
7444 int tmpfd = rb_sysopen(fptr->
pathv, oflags, 0666);
7474 fptr->
mode = orig->
mode & ~FMODE_PREP;
7479 fptr_copy_finalizer(fptr, orig);
7481 fd = ruby_dup(orig->
fd);
7491 if (io != write_io) {
7682 return rb_io_putc(recv, ch);
7696 if (
len == 0)
return 0;
7698 return ptr[
len - 1] == c;
7754 VALUE line, args[2];
7777 rb_io_writev(out,
n, args);
7836 else if (
argc > 1) {
7909rb_stderr_to_original_p(
void)
7917 if (rb_stderr_to_original_p()) {
7943 if (rb_stderr_to_original_p()) {
7964 if (rb_stderr_to_original_p())
7970must_respond_to(
ID mid,
VALUE val,
ID id)
7982 must_respond_to(id_write, val,
id);
7995 if (!io_check_tty(fp)) {
8024#ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
8025 fptr->
encs.
ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
8039 int oflags = rb_io_fmode_oflags(fptr->
mode) & ~O_EXCL;
8065 rb_io_buffer_init(&fp->
wbuf);
8066 rb_io_buffer_init(&fp->
rbuf);
8067 rb_io_buffer_init(&fp->
cbuf);
8094 fp = rb_io_fptr_new();
8257 int fd,
fmode, oflags = O_RDONLY;
8260#if defined(HAVE_FCNTL) && defined(F_GETFL)
8274#if defined(HAVE_FCNTL) && defined(F_GETFL)
8275 oflags =
fcntl(fd, F_GETFL);
8281#if defined(HAVE_FCNTL) && defined(F_GETFL)
8297 fp->
encs = convconfig;
8330rb_io_set_encoding_by_bom(
VALUE io)
8345 if (!io_set_encoding_by_bom(io))
return Qnil;
8377 if (
RFILE(io)->fptr) {
8385 return rb_io_initialize(
argc,
argv, io);
8432rb_io_autoclose_p(
VALUE io)
8457rb_io_set_autoclose(
VALUE io,
VALUE autoclose)
8461 if (!
RTEST(autoclose))
8464 fptr->
mode &= ~FMODE_PREP;
8480argf_memsize(
const void *
ptr)
8483 size_t size =
sizeof(*p);
8585#define next_argv() argf_next_argv(argf)
8586#define ARGF_GENERIC_INPUT_P() \
8587 (ARGF.current_file == rb_stdin && !RB_TYPE_P(ARGF.current_file, T_FILE))
8588#define ARGF_FORWARD(argc, argv) do {\
8589 if (ARGF_GENERIC_INPUT_P())\
8590 return argf_forward((argc), (argv), argf);\
8592#define NEXT_ARGF_FORWARD(argc, argv) do {\
8593 if (!next_argv()) return Qnil;\
8594 ARGF_FORWARD((argc), (argv));\
8614 int stdout_binmode = 0;
8623 if (
ARGF.init_p == 0) {
8641 if (
ARGF.next_p == 1) {
8642 if (
ARGF.init_p == 1) argf_close(
argf);
8653 rb_warn(
"Can't do inplace edit for stdio; skipping");
8659 int fr = rb_sysopen(
filename, O_RDONLY, 0);
8663#ifndef NO_SAFE_RENAME
8682#ifdef NO_SAFE_RENAME
8690 fr = rb_sysopen(
str, O_RDONLY, 0);
8701#ifdef NO_SAFE_RENAME
8702 rb_fatal(
"Can't do inplace edit without backup");
8712 fw = rb_sysopen(filename, O_WRONLY|O_CREAT|O_TRUNC, 0666);
8713#ifndef NO_SAFE_RENAME
8720 if (
st.st_uid!=st2.st_uid ||
st.st_gid!=st2.st_gid) {
8727 if (
err &&
getuid() == 0 && st2.st_uid == 0) {
8743 if (!
ARGF.binmode) {
8747 if (!
NIL_P(write_io)) {
8754 if (
ARGF.encs.enc) {
8756 clear_codeconv(fptr);
8759 fptr->
encs.
ecflags &= ~ECONV_NEWLINE_DECORATOR_MASK;
8760 if (!
ARGF.binmode) {
8762#ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
8763 fptr->
encs.
ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
8774 else if (
ARGF.next_p == -1) {
8778 rb_warn(
"Can't do inplace edit for stdio");
8782 if (
ARGF.init_p == -1)
ARGF.init_p = 1;
8790 long lineno =
ARGF.lineno;
8811 ARGF.lineno = ++lineno;
8818argf_lineno_getter(
ID id,
VALUE *var)
8911 return rb_f_gets(0, 0,
argf);
9025 long lineno =
ARGF.lineno;
9034 lines = rb_io_readlines(
argc,
argv,
ARGF.current_file);
9073 result = read_all(fptr, remain_size(fptr),
Qnil);
9082#ifdef HAVE_SYS_SELECT_H
9083#include <sys/select.h>
9106 if (max < fptr->fd) max = fptr->
fd;
9109 timerec.tv_sec = timerec.tv_usec = 0;
9123 if (max < fptr->fd) max = fptr->
fd;
9130 if (!
NIL_P(except)) {
9137 if (max < fptr->fd) max = fptr->
fd;
9138 if (io != write_io) {
9141 if (max < fptr->fd) max = fptr->
fd;
9156 if (!pending &&
n == 0)
return Qnil;
9199 else if (io != write_io) {
9236static VALUE sym_normal, sym_sequential, sym_random,
9237 sym_willneed, sym_dontneed, sym_noreuse;
9239#ifdef HAVE_POSIX_FADVISE
9240struct io_advise_struct {
9248io_advise_internal(
void *
arg)
9250 struct io_advise_struct *
ptr =
arg;
9251 return posix_fadvise(
ptr->fd,
ptr->offset,
ptr->len,
ptr->advice);
9257#ifdef POSIX_FADV_NORMAL
9258 if (
sym == sym_normal)
9259 return INT2NUM(POSIX_FADV_NORMAL);
9262#ifdef POSIX_FADV_RANDOM
9263 if (
sym == sym_random)
9264 return INT2NUM(POSIX_FADV_RANDOM);
9267#ifdef POSIX_FADV_SEQUENTIAL
9268 if (
sym == sym_sequential)
9269 return INT2NUM(POSIX_FADV_SEQUENTIAL);
9272#ifdef POSIX_FADV_WILLNEED
9273 if (
sym == sym_willneed)
9274 return INT2NUM(POSIX_FADV_WILLNEED);
9277#ifdef POSIX_FADV_DONTNEED
9278 if (
sym == sym_dontneed)
9279 return INT2NUM(POSIX_FADV_DONTNEED);
9282#ifdef POSIX_FADV_NOREUSE
9283 if (
sym == sym_noreuse)
9284 return INT2NUM(POSIX_FADV_NOREUSE);
9294 struct io_advise_struct ias;
9297 num_adv = io_advise_sym_to_const(advice);
9307 ias.advice =
NUM2INT(num_adv);
9308 ias.offset = offset;
9312 if (rv && rv !=
ENOSYS) {
9329advice_arg_check(
VALUE advice)
9334 if (advice != sym_normal &&
9335 advice != sym_sequential &&
9336 advice != sym_random &&
9337 advice != sym_willneed &&
9338 advice != sym_dontneed &&
9339 advice != sym_noreuse) {
9394 advice_arg_check(advice);
9402#ifdef HAVE_POSIX_FADVISE
9403 return do_io_advise(fptr, advice, off, l);
9405 ((
void)off, (
void)l);
9559 if (
NIL_P(timeout)) {
9564 args.timeout = &timerec;
9573#if (defined(__linux__) && !defined(__ANDROID__)) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
9575# define NUM2IOCTLREQ(num) NUM2ULONG(num)
9578# define NUM2IOCTLREQ(num) ((int)NUM2LONG(num))
9589nogvl_ioctl(
void *
ptr)
9612#define DEFULT_IOCTL_NARG_LEN (256)
9614#if defined(__linux__) && defined(_IOC_SIZE)
9620 if ((cmd & 0xFFFF0000) == 0) {
9625 len = _IOC_SIZE(cmd);
9642#define IOCPARM_LEN(x) (((x) >> 16) & IOCPARM_MASK)
9646 len = IOCPARM_LEN(cmd);
9647#elif defined(__linux__) && defined(_IOC_SIZE)
9648 len = linux_iocparm_len(cmd);
9659typedef long fcntl_arg_t;
9662typedef int fcntl_arg_t;
9666fcntl_narg_len(
int cmd)
9673 len =
sizeof(fcntl_arg_t);
9681#ifdef F_DUPFD_CLOEXEC
9683 len =
sizeof(fcntl_arg_t);
9693 len =
sizeof(fcntl_arg_t);
9703 len =
sizeof(fcntl_arg_t);
9713 len =
sizeof(fcntl_arg_t);
9718 len =
sizeof(
struct f_owner_ex);
9723 len =
sizeof(
struct f_owner_ex);
9758 len =
sizeof(fcntl_arg_t);
9768 len =
sizeof(fcntl_arg_t);
9773 len =
sizeof(fcntl_arg_t);
9786fcntl_narg_len(
int cmd)
9819 len = ioctl_narg_len(cmd);
9821 len = fcntl_narg_len((
int)cmd);
9850 narg = setup_narg(cmd, &
arg, 1);
9852 retval = do_ioctl(fptr->
fd, cmd, narg);
9858 if (
ptr[slen-1] != 17)
9884 return rb_ioctl(io, req,
arg);
9887#define rb_io_ioctl rb_f_notimplement
9898nogvl_fcntl(
void *
ptr)
9900 struct fcntl_arg *
arg =
ptr;
9910do_fcntl(
int fd,
int cmd,
long narg)
9913 struct fcntl_arg
arg;
9925#if defined(F_DUPFD_CLOEXEC)
9943 narg = setup_narg(cmd, &
arg, 0);
9945 retval = do_fcntl(fptr->
fd, cmd, narg);
9951 if (
ptr[slen-1] != 17)
9978 return rb_fcntl(io, req,
arg);
9981#define rb_io_fcntl rb_f_notimplement
9984#if defined(HAVE_SYSCALL) || defined(HAVE___SYSCALL)
10023#if SIZEOF_VOIDP == 8 && defined(HAVE___SYSCALL) && SIZEOF_INT != 8
10024# define SYSCALL __syscall
10025# define NUM2SYSCALLID(x) NUM2LONG(x)
10026# define RETVAL2NUM(x) LONG2NUM(x)
10027# if SIZEOF_LONG == 8
10028 long num, retval = -1;
10029# elif SIZEOF_LONG_LONG == 8
10030 long long num, retval = -1;
10032# error ---->> it is asserted that __syscall takes the first argument and returns retval in 64bit signed integer. <<----
10034#elif defined(__linux__)
10035# define SYSCALL syscall
10036# define NUM2SYSCALLID(x) NUM2LONG(x)
10037# define RETVAL2NUM(x) LONG2NUM(x)
10045 long num, retval = -1;
10047# define SYSCALL syscall
10048# define NUM2SYSCALLID(x) NUM2INT(x)
10049# define RETVAL2NUM(x) INT2NUM(x)
10050 int num, retval = -1;
10055 rb_warning(
"We plan to remove a syscall function at future release. DL(Fiddle) provides safer alternative.");
10062 num = NUM2SYSCALLID(
argv[0]); ++
argv;
10063 for (
i =
argc - 1;
i--; ) {
10078 retval = SYSCALL(num);
10081 retval = SYSCALL(num,
arg[0]);
10084 retval = SYSCALL(num,
arg[0],
arg[1]);
10087 retval = SYSCALL(num,
arg[0],
arg[1],
arg[2]);
10105 return RETVAL2NUM(retval);
10107#undef NUM2SYSCALLID
10111#define rb_f_syscall rb_f_notimplement
10115io_new_instance(
VALUE args)
10136 enc2 = find_encoding(v1);
10145 enc = find_encoding(v2);
10152 enc = find_encoding(v2);
10164 rb_io_ext_int_to_encs(
NULL,
NULL, &enc, &enc2, 0);
10176 rb_io_ext_int_to_encs(find_encoding(v1),
NULL, &enc, &enc2, 0);
10182 validate_enc_binmode(&fptr->
mode, ecflags, enc, enc2);
10187 clear_codeconv(fptr);
10199io_encoding_set_v(
VALUE v)
10202 io_encoding_set(
arg->fptr,
arg->v1,
arg->v2,
arg->opt);
10207pipe_pair_close(
VALUE rw)
10210 return rb_ensure(io_close, rwp[0], io_close, rwp[1]);
10276 int pipes[2], state;
10299 ies_args.fptr =
fptr;
10302 ies_args.opt =
opt;
10328#if DEFAULT_TEXTMODE
10333#if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
10340#if DEFAULT_TEXTMODE
10342 fptr2->
mode &= ~FMODE_TEXTMODE;
10436 int orig_argc =
argc;
10442 extract_getline_args(
argc-1,
argv+1, &garg);
10445 extract_getline_opts(opt, &garg);
10446 check_getline_args(&garg.rs, &garg.limit, garg.io =
arg.io);
10454 return io_readlines(
arg,
arg->io);
10495 extract_getline_args(
argc-1,
argv+1, &garg);
10498 extract_getline_opts(opt, &garg);
10499 check_getline_args(&garg.rs, &garg.limit, garg.io =
arg.io);
10507 return io_read(
arg->argc,
arg->argv,
arg->io);
10517seek_before_access(
VALUE argp)
10521 return rb_io_seek(
arg->io,
arg->offset,
arg->mode);
10575 if (!
NIL_P(offset)) {
10586 if (
arg.argc == 2)
arg.argc = 1;
10622 arg.io = rb_io_open_generic(
io,
argv[0], oflags,
fmode, &convconfig, 0);
10625 arg.argc = (
argc > 1) ? 1 : 0;
10626 if (!
NIL_P(offset)) {
10645 return io_write(
arg->io,
arg->str,
arg->nosync);
10651 VALUE string, offset, opt;
10662 int mode = O_WRONLY|O_CREAT;
10666 if (
NIL_P(offset)) mode |= O_TRUNC;
10672 if (binary) rb_io_binmode_m(
arg.io);
10676 if (!
NIL_P(offset)) {
10777#ifdef HAVE_FCOPYFILE
10778 copyfile_state_t copyfile_state;
10783exec_interrupts(
void *
arg)
10800#if defined(ERESTART)
10815# define IOWAIT_SYSCALL "poll"
10819nogvl_wait_for_single_fd(
int fd,
short events)
10824 fds.events = events;
10826 return poll(&fds, 1, -1);
10829# define IOWAIT_SYSCALL "select"
10831nogvl_wait_for_single_fd(
int fd,
short events)
10867 }
while (ret < 0 && maygvl_copy_stream_continue_p(has_gvl, stp));
10884 }
while (ret < 0 && maygvl_copy_stream_continue_p(0, stp));
10894#if defined HAVE_COPY_FILE_RANGE || (defined __linux__ && defined __NR_copy_file_range)
10895# define USE_COPY_FILE_RANGE
10898#ifdef USE_COPY_FILE_RANGE
10901simple_copy_file_range(
int in_fd,
off_t *in_offset,
int out_fd,
off_t *out_offset,
size_t count,
unsigned int flags)
10903#ifdef HAVE_COPY_FILE_RANGE
10904 return copy_file_range(in_fd, in_offset, out_fd, out_offset,
count, flags);
10906 return syscall(__NR_copy_file_range, in_fd, in_offset, out_fd, out_offset,
count, flags);
10915 off_t copy_length, src_offset, *src_offset_ptr;
10922 if (src_offset >= (
off_t)0) {
10923 src_offset_ptr = &src_offset;
10926 src_offset_ptr =
NULL;
10930 if (copy_length < (
off_t)0) {
10931 if (src_offset < (
off_t)0) {
10932 off_t current_offset;
10938 return (
int)current_offset;
10940 copy_length = src_size - current_offset;
10943 copy_length = src_size - src_offset;
10947 retry_copy_file_range:
10948# if SIZEOF_OFF_T > SIZEOF_SIZE_T
10954 ss = simple_copy_file_range(stp->
src_fd, src_offset_ptr, stp->
dst_fd,
NULL, ss, 0);
10958 if (0 < copy_length) {
10959 goto retry_copy_file_range;
10963 if (maygvl_copy_stream_continue_p(0, stp)) {
10964 goto retry_copy_file_range;
10978#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
10982 int ret = nogvl_copy_stream_wait_write(stp);
10983 if (ret < 0)
return ret;
10985 goto retry_copy_file_range;
10991 if (flags != -1 && flags & O_APPEND) {
10997 stp->
syserr =
"copy_file_range";
11005#ifdef HAVE_FCOPYFILE
11030 if (end > (
off_t)0)
return 0;
11033 if (src_offset > (
off_t)0) {
11052 stp->copyfile_state = copyfile_state_alloc();
11053 ret = fcopyfile(stp->
src_fd, stp->
dst_fd, stp->copyfile_state, COPYFILE_DATA);
11054 copyfile_state_get(stp->copyfile_state, COPYFILE_STATE_COPIED, &ss);
11058 if (src_offset > (
off_t)0) {
11076 stp->
syserr =
"fcopyfile";
11084#ifdef HAVE_SENDFILE
11087# define USE_SENDFILE
11089# ifdef HAVE_SYS_SENDFILE_H
11090# include <sys/sendfile.h>
11096 return sendfile(out_fd, in_fd, offset, (
size_t)
count);
11099# elif 0 || defined(__APPLE__)
11103# define USE_SENDFILE
11112 r = sendfile(in_fd, out_fd, pos, &
count,
NULL, 0);
11115 r = sendfile(in_fd, out_fd, pos, (
size_t)
count,
NULL, &sbytes, 0);
11117 if (r != 0 && sbytes == 0)
return r;
11151 use_pread = src_offset >= (
off_t)0;
11154 if (copy_length < (
off_t)0) {
11156 copy_length = src_size - src_offset;
11166 copy_length = src_size - cur;
11171# if SIZEOF_OFF_T > SIZEOF_SIZE_T
11178 ss = simple_sendfile(stp->
dst_fd, stp->
src_fd, &src_offset, ss);
11186 if (0 < copy_length) {
11187 goto retry_sendfile;
11191 if (maygvl_copy_stream_continue_p(0, stp))
11192 goto retry_sendfile;
11200#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
11213 ret = maygvl_copy_stream_wait_read(0, stp);
11214 if (ret < 0)
return ret;
11216 ret = nogvl_copy_stream_wait_write(stp);
11217 if (ret < 0)
return ret;
11219 goto retry_sendfile;
11221 stp->
syserr =
"sendfile";
11230maygvl_read(
int has_gvl,
int fd,
void *
buf,
size_t count)
11233 return rb_read_internal(fd,
buf,
count);
11243 if (offset < (
off_t)0) {
11258 if (maygvl_copy_stream_continue_p(has_gvl, stp))
11262#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
11266 int ret = maygvl_copy_stream_wait_read(has_gvl, stp);
11267 if (ret < 0)
return ret;
11276 stp->
syserr = offset < (
off_t)0 ?
"read" :
"pread";
11290 if (maygvl_copy_stream_continue_p(0, stp))
11293 int ret = nogvl_copy_stream_wait_write(stp);
11294 if (ret < 0)
return ret;
11321 use_eof = copy_length < (
off_t)0;
11323 use_pread = src_offset >= (
off_t)0;
11334 src_offset = (
off_t)-1;
11338 while (use_eof || 0 < copy_length) {
11339 if (!use_eof && copy_length < (
off_t)
sizeof(
buf)) {
11346 ss = maygvl_copy_stream_read(0, stp,
buf,
len, src_offset);
11351 ss = maygvl_copy_stream_read(0, stp,
buf,
len, (
off_t)-1);
11356 ret = nogvl_copy_stream_write(stp,
buf, ss);
11366nogvl_copy_stream_func(
void *
arg)
11369#if defined(USE_SENDFILE) || defined(USE_COPY_FILE_RANGE) || defined(HAVE_FCOPYFILE)
11373#ifdef USE_COPY_FILE_RANGE
11374 ret = nogvl_copy_file_range(stp);
11379#ifdef HAVE_FCOPYFILE
11380 ret = nogvl_fcopyfile(stp);
11386 ret = nogvl_copy_stream_sendfile(stp);
11391 nogvl_copy_stream_read_write(stp);
11393#if defined(USE_SENDFILE) || defined(USE_COPY_FILE_RANGE) || defined(HAVE_FCOPYFILE)
11400copy_stream_fallback_body(
VALUE arg)
11403 const int buflen = 16*1024;
11408 ID read_method = id_readpartial;
11412 read_method = id_read;
11427 l = buflen < rest ? buflen : (
long)rest;
11432 if (read_method == id_read &&
NIL_P(rc))
11444 if (off >= (
off_t)0)
11449 stp->
total += numwrote;
11476 rb_io_t *src_fptr = 0, *dst_fptr = 0;
11478 const int common_oflags = 0
11488 if (src_io ==
argf ||
11497 if (!
NIL_P(tmp_io)) {
11504 args[1] =
INT2NUM(O_RDONLY|common_oflags);
11514 if (stat_ret < 0) {
11522 if (dst_io ==
argf ||
11531 if (!
NIL_P(tmp_io)) {
11538 args[1] =
INT2NUM(O_WRONLY|O_CREAT|O_TRUNC|common_oflags);
11553 if (stat_ret < 0) {
11566 io_ascii8bit_binmode(dst_fptr);
11569 size_t len = src_fptr->
rbuf.len;
11589 if (dst_fptr && io_fflush(dst_fptr) < 0) {
11597 return copy_stream_fallback(stp);
11609#ifdef HAVE_FCOPYFILE
11610 if (stp->copyfile_state) {
11611 copyfile_state_free(stp->copyfile_state);
11616 rb_io_close_m(stp->
src);
11619 rb_io_close_m(stp->
dst);
11699rb_io_external_encoding(
VALUE io)
11724rb_io_internal_encoding(
VALUE io)
11764 io_encoding_set(fptr, v1, v2, opt);
11773 rb_io_set_encoding(1, &val,
rb_stdin);
11774 rb_io_set_encoding(1, &val,
rb_stdout);
11775 rb_io_set_encoding(1, &val,
rb_stderr);
11895 return rb_io_tell(
ARGF.current_file);
11933 return rb_io_set_pos(
ARGF.current_file, offset);
11958 old_lineno =
RFILE(
ARGF.current_file)->fptr->lineno;
11959 ret = rb_io_rewind(
ARGF.current_file);
11960 if (!global_argf_p(
argf)) {
11961 ARGF.last_lineno =
ARGF.lineno -= old_lineno;
11983 return rb_io_fileno(
ARGF.current_file);
12003 return ARGF.current_file;
12094 if (!
NIL_P(length)) {
12116 if (
ARGF.next_p != -1) {
12122 else if (
argc >= 1) {
12226 tmp = io_getpartial(
argc,
argv,
ARGF.current_file, no_exception, nonblock);
12229 if (
ARGF.next_p == -1) {
12230 return io_nonblock_eof(no_exception);
12235 return io_nonblock_eof(no_exception);
12278 ch = rb_io_getc(
ARGF.current_file);
12358 ch = rb_io_getc(
ARGF.current_file);
12393 c = argf_getbyte(
argf);
12400#define FOREACH_ARGF() while (next_argv())
12405 const VALUE current =
ARGF.current_file;
12407 if (
ARGF.init_p == -1 || current !=
ARGF.current_file) {
12413#define ARGF_block_call(mid, argc, argv, func, argf) \
12414 rb_block_call_kw(ARGF.current_file, mid, argc, argv, \
12415 func, argf, rb_keyword_given_p())
12427 if (!global_argf_p(
argf)) {
12547 return argf_each_byte(
argf);
12586 return argf_each_char(
argf);
12625 return argf_each_codepoint(
argf);
12654 return ARGF.filename;
12658argf_filename_getter(
ID id,
VALUE *var)
12660 return argf_filename(*var);
12685 return ARGF.current_file;
12745 if (
ARGF.init_p &&
ARGF.next_p == 0) {
12774 if (
ARGF.next_p != -1) {
12793 return rb_io_closed(
ARGF.current_file);
12827 return argf_inplace_mode_get(*var);
12868 argf_inplace_mode_set(*var, val);
12898argf_argv_getter(
ID id,
VALUE *var)
12900 return argf_argv(*var);
12953#if EAGAIN != EWOULDBLOCK
12970#if EAGAIN != EWOULDBLOCK
12983 rb_bug(
"invalid read/write type passed to rb_readwrite_sys_fail: %d", writable);
12988get_LAST_READ_LINE(
ID _x,
VALUE *_y)
13158#define rb_intern(str) rb_intern_const(str)
13162#include <sys/cygwin.h>
13163 static struct __cygwin_perfile pf[] =
13171 cygwin_internal(CW_PERFILE, pf);
13181 id_readpartial =
rb_intern(
"readpartial");
13182 id_set_encoding =
rb_intern(
"set_encoding");
13215#if EAGAIN == EWOULDBLOCK
13216 rb_eEWOULDBLOCKWaitReadable = rb_eEAGAINWaitReadable;
13219 rb_eEWOULDBLOCKWaitWritable = rb_eEAGAINWaitWritable;
13463 rb_define_method(rb_cARGF,
"external_encoding", argf_external_encoding, 0);
13464 rb_define_method(rb_cARGF,
"internal_encoding", argf_internal_encoding, 0);
13485#if defined (_WIN32) || defined(__CYGWIN__)
#define ENCINDEX_UTF_32BE
#define ENCINDEX_UTF_32LE
#define ENCINDEX_UTF_16BE
#define ENCINDEX_UTF_16LE
struct rb_encoding_entry * list
rb_encoding * rb_find_encoding(VALUE enc)
int rb_enc_precise_mbclen(const char *p, const char *e, rb_encoding *enc)
int rb_to_encoding_index(VALUE enc)
VALUE rb_enc_associate(VALUE obj, rb_encoding *enc)
rb_encoding * rb_ascii8bit_encoding(void)
rb_encoding * rb_enc_from_index(int index)
rb_encoding * rb_default_internal_encoding(void)
int rb_utf8_encindex(void)
rb_encoding * rb_enc_get(VALUE obj)
rb_encoding * rb_default_external_encoding(void)
int rb_enc_mbclen(const char *p, const char *e, rb_encoding *enc)
rb_encoding * rb_to_encoding(VALUE enc)
rb_encoding * rb_usascii_encoding(void)
VALUE rb_enc_from_encoding(rb_encoding *encoding)
int rb_enc_find_index(const char *name)
int rb_enc_ascget(const char *p, const char *e, int *len, rb_encoding *enc)
#define ECONV_AFTER_OUTPUT
int rb_econv_prepare_options(VALUE opthash, VALUE *ecopts, int ecflags)
#define ENC_CODERANGE_7BIT
#define ENC_CODERANGE_VALID
VALUE rb_econv_open_exc(const char *senc, const char *denc, int ecflags)
#define ECONV_UNIVERSAL_NEWLINE_DECORATOR
#define rb_enc_left_char_head(s, p, e, enc)
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)
@ econv_undefined_conversion
@ econv_source_buffer_empty
@ econv_destination_buffer_full
@ econv_invalid_byte_sequence
int rb_econv_putbackable(rb_econv_t *ec)
int rb_enc_str_coderange(VALUE)
VALUE rb_enc_uint_chr(unsigned int code, rb_encoding *enc)
VALUE rb_enc_str_new(const char *, long, rb_encoding *)
#define ENCODING_MAXNAMELEN
#define MBCLEN_NEEDMORE_LEN(ret)
#define ENCODING_GET(obj)
const char * rb_econv_asciicompat_encoding(const char *encname)
VALUE rb_econv_str_convert(rb_econv_t *ec, VALUE src, int flags)
rb_econv_t * rb_econv_open_opts(const char *source_encoding, const char *destination_encoding, int ecflags, VALUE ecopts)
#define MBCLEN_CHARFOUND_LEN(ret)
#define rb_enc_asciicompat(enc)
void rb_econv_binmode(rb_econv_t *ec)
#define rb_enc_codepoint(p, e, enc)
VALUE rb_str_encode(VALUE str, VALUE to, int ecflags, VALUE ecopts)
VALUE rb_econv_make_exception(rb_econv_t *ec)
#define MBCLEN_INVALID_P(ret)
void rb_econv_check_error(rb_econv_t *ec)
#define ECONV_STATEFUL_DECORATOR_MASK
#define MBCLEN_NEEDMORE_P(ret)
#define rb_enc_mbminlen(enc)
#define ECONV_PARTIAL_INPUT
#define ECONV_ERROR_HANDLER_MASK
#define ENC_CODERANGE_BROKEN
long rb_str_coderange_scan_restartable(const char *, const char *, rb_encoding *, int *)
#define MBCLEN_CHARFOUND_P(ret)
void rb_econv_close(rb_econv_t *ec)
#define ECONV_NEWLINE_DECORATOR_MASK
#define ENC_CODERANGE_SET(obj, cr)
void rb_econv_putback(rb_econv_t *ec, unsigned char *p, int n)
#define ECONV_DEFAULT_NEWLINE_DECORATOR
char str[HTML_ESCAPE_MAX_LEN+1]
void rb_include_module(VALUE, VALUE)
VALUE rb_define_class(const char *, VALUE)
Defines a top-level class.
VALUE rb_class_new(VALUE)
Creates a new class.
VALUE rb_define_class_under(VALUE, const char *, VALUE)
Defines a class under the namespace of outer.
VALUE rb_define_module_under(VALUE, const char *)
ID rb_frame_this_func(void)
The original name of the current method.
int rb_scan_args_kw(int, int, const VALUE *, const char *,...)
void rb_define_alias(VALUE, const char *, const char *)
Defines an alias of a method.
int rb_block_given_p(void)
Determines if the current method is given a block.
int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *)
VALUE rb_mKernel
Kernel module.
VALUE rb_cObject
Object class.
void rb_notimplement(void)
void rb_syserr_fail(int e, const char *mesg)
void rb_raise(VALUE exc, const char *fmt,...)
void rb_mod_sys_fail_str(VALUE mod, VALUE mesg)
void rb_enc_warn(rb_encoding *enc, const char *fmt,...)
VALUE rb_rescue2(VALUE(*)(VALUE), VALUE, VALUE(*)(VALUE, VALUE), VALUE,...)
An equivalent of rescue clause.
void rb_exc_raise(VALUE mesg)
Raises an exception in the current thread.
void rb_bug(const char *fmt,...)
void rb_syserr_fail_str(int e, VALUE mesg)
void rb_sys_fail_str(VALUE mesg)
void rb_fatal(const char *fmt,...)
VALUE rb_protect(VALUE(*)(VALUE), VALUE, int *)
Protects a function call from potential global escapes from the function.
void rb_warn(const char *fmt,...)
VALUE rb_ensure(VALUE(*)(VALUE), VALUE, VALUE(*)(VALUE), VALUE)
An equivalent to ensure clause.
void rb_jump_tag(int tag)
Continues the exception caught by rb_protect() and rb_eval_string_protect().
int rb_str_end_with_asciichar(VALUE str, int c)
void rb_sys_fail(const char *mesg)
VALUE rb_eSystemCallError
VALUE rb_check_to_int(VALUE)
Tries to convert val into Integer.
VALUE rb_any_to_s(VALUE)
Default implementation of #to_s.
VALUE rb_obj_alloc(VALUE)
Allocates an instance of klass.
VALUE rb_class_new_instance(int, const VALUE *, VALUE)
Allocates and initializes an instance of klass.
VALUE rb_class_new_instance_kw(int, const VALUE *, VALUE, int)
int rb_bool_expected(VALUE, const char *)
VALUE rb_obj_class(VALUE)
Equivalent to Object#class in Ruby.
VALUE rb_obj_dup(VALUE)
Equivalent to Object#dup in Ruby.
VALUE rb_inspect(VALUE)
Convenient wrapper of Object::inspect.
VALUE rb_convert_type_with_id(VALUE, int, const char *, ID)
VALUE rb_obj_freeze(VALUE)
Make the object unmodifiable.
VALUE rb_check_to_integer(VALUE, const char *)
Tries to convert val into Integer.
VALUE rb_check_convert_type_with_id(VALUE, int, const char *, ID)
VALUE rb_to_int(VALUE)
Converts val into Integer.
#define rb_io_fptr_finalize(fptr)
VALUE rb_io_gets(VALUE io)
int rb_io_wait_writable(int f)
#define io_seek(fptr, ofs, whence)
int rb_io_modestr_fmode(const char *modestr)
VALUE rb_io_taint_check(VALUE io)
#define do_write_retry(code)
int rb_cloexec_pipe(int fildes[2])
VALUE rb_io_get_io(VALUE io)
VALUE rb_io_addstr(VALUE io, VALUE str)
void rb_io_fptr_finalize_internal(void *ptr)
void rb_io_read_check(rb_io_t *fptr)
int rb_io_modestr_oflags(const char *modestr)
VALUE rb_io_fdopen(int fd, int oflags, const char *path)
#define NEXT_ARGF_FORWARD(argc, argv)
VALUE rb_io_ungetbyte(VALUE io, VALUE b)
VALUE rb_io_gets_internal(VALUE io)
int rb_io_wait_readable(int f)
VALUE rb_io_getbyte(VALUE io)
#define SET_BINARY_MODE_WITH_SEEK_CUR(fptr)
void ruby_set_inplace_mode(const char *suffix)
#define NUM2IOCTLREQ(num)
int rb_cloexec_dup2(int oldfd, int newfd)
void rb_readwrite_syserr_fail(enum rb_io_wait_readwrite writable, int n, const char *mesg)
void rb_write_error_str(VALUE mesg)
#define READ_DATA_PENDING(fptr)
void rb_io_check_byte_readable(rb_io_t *fptr)
rb_io_t * rb_io_make_open_file(VALUE obj)
#define READ_DATA_PENDING_COUNT(fptr)
void rb_io_check_readable(rb_io_t *fptr)
#define rb_io_close_on_exec_p
#define ARGF_GENERIC_INPUT_P()
int rb_io_extract_encoding_option(VALUE opt, rb_encoding **enc_p, rb_encoding **enc2_p, int *fmode_p)
void rb_maygvl_fd_fix_cloexec(int fd)
#define READ_CHAR_PENDING_PTR(fptr)
#define NEED_WRITECONV(fptr)
int rb_io_oflags_fmode(int oflags)
#define MODE_BTMODE(a, b, c)
void Init_IO_nonblock(void)
#define no_exception_p(opts)
#define RUBY_PIPE_NONBLOCK_DEFAULT
void rb_update_max_fd(int fd)
FILE * rb_fdopen(int fd, const char *modestr)
int rb_gc_for_fd(int err)
VALUE rb_io_write(VALUE io, VALUE str)
#define NEED_NEWLINE_DECORATOR_ON_WRITE(fptr)
VALUE rb_io_puts(int argc, const VALUE *argv, VALUE out)
int rb_cloexec_open(const char *pathname, int flags, mode_t mode)
FILE * rb_io_stdio_file(rb_io_t *fptr)
void rb_readwrite_sys_fail(enum rb_io_wait_readwrite writable, const char *mesg)
#define PREP_STDIO_NAME(f)
#define DEFULT_IOCTL_NARG_LEN
VALUE rb_io_eof(VALUE io)
void rb_stdio_set_default_encoding(void)
#define NEED_NEWLINE_DECORATOR_ON_READ(fptr)
struct rb_io_enc_t convconfig_t
#define ARGF_FORWARD(argc, argv)
#define READ_DATA_PENDING_PTR(fptr)
#define NEED_READCONV(fptr)
#define is_socket(fd, path)
void rb_io_extract_modeenc(VALUE *vmode_p, VALUE *vperm_p, VALUE opthash, int *oflags_p, int *fmode_p, convconfig_t *convconfig_p)
#define READ_CHAR_PENDING(fptr)
void rb_fd_fix_cloexec(int fd)
VALUE rb_io_flush(VALUE io)
#define READ_CHAR_PENDING_COUNT(fptr)
void rb_io_check_initialized(rb_io_t *fptr)
VALUE rb_io_ascii8bit_binmode(VALUE io)
VALUE rb_io_binmode(VALUE io)
VALUE rb_io_check_io(VALUE io)
VALUE rb_io_printf(int argc, const VALUE *argv, VALUE out)
VALUE rb_io_ungetc(VALUE io, VALUE c)
#define IO_RBUF_CAPA_FOR(fptr)
#define MORE_CHAR_SUSPENDED
#define NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr)
void rb_io_unbuffered(rb_io_t *fptr)
int rb_notify_fd_close(int fd, struct list_head *)
int rb_stderr_tty_p(void)
ssize_t rb_io_bufwrite(VALUE io, const void *buf, size_t size)
VALUE rb_io_flush_raw(VALUE io, int sync)
int rb_cloexec_fcntl_dupfd(int fd, int minfd)
#define MODE_BINARY(a, b)
#define MODE_BTXMODE(a, b, c, d, e, f)
void rb_io_check_char_readable(rb_io_t *fptr)
#define READ_DATA_BUFFERED(fptr)
#define SET_BINARY_MODE(fptr)
#define ARGF_block_call(mid, argc, argv, func, argf)
int rb_io_read_pending(rb_io_t *fptr)
VALUE rb_io_get_write_io(VALUE io)
void rb_io_set_nonblock(rb_io_t *fptr)
RUBY_FUNC_EXPORTED size_t rb_io_memsize(const rb_io_t *fptr)
#define MORE_CHAR_FINISHED
#define rb_io_set_close_on_exec
VALUE rb_file_open(const char *fname, const char *modestr)
int rb_cloexec_dup(int oldfd)
VALUE rb_io_set_write_io(VALUE io, VALUE w)
VALUE rb_file_open_str(VALUE fname, const char *modestr)
void rb_write_error(const char *mesg)
void rb_io_check_writable(rb_io_t *fptr)
#define SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags)
char * rb_execarg_commandline(const struct rb_execarg *eargp, VALUE *prog)
VALUE rb_io_print(int argc, const VALUE *argv, VALUE out)
void rb_io_check_closed(rb_io_t *fptr)
void rb_write_error2(const char *mesg, long len)
void rb_io_synchronized(rb_io_t *fptr)
VALUE rb_io_close(VALUE io)
#define FMODE_SETENC_BY_BOM
int rb_wait_for_single_fd(int fd, int events, struct timeval *tv)
struct rb_io_enc_t rb_io_enc_t
#define MakeOpenFile(obj, fp)
#define GetOpenFile(obj, fp)
struct rb_io_buffer_t rb_io_buffer_t
unsigned char buf[MIME_BUF_SIZE]
#define ONIGENC_CONSTRUCT_MBCLEN_CHARFOUND(n)
rb_atomic_t cnt[RUBY_NSIG]
size_t rb_str_capacity(VALUE str)
VALUE rb_str_cat_conv_enc_opts(VALUE newstr, long ofs, const char *ptr, long len, rb_encoding *from, int ecflags, VALUE ecopts)
struct rb_execarg::@34::@36 cmd
union rb_execarg::@34 invoke
struct rb_execarg::@34::@35 sh
struct rb_io_t::rb_io_enc_t encs
VALUE writeconv_asciicompat
int writeconv_initialized
int writeconv_pre_ecflags
VALUE writeconv_pre_ecopts
VALUE tied_io_for_writing
void(* finalize)(struct rb_io_t *, int)
RUBY_SYMBOL_EXPORT_BEGIN void * rb_thread_call_with_gvl(void *(*func)(void *), void *data1)
void * rb_thread_call_without_gvl2(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2)
void * rb_thread_call_without_gvl(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2)
size_t rb_econv_memsize(rb_econv_t *ec)
void rb_iter_break_value(VALUE val)
MJIT_STATIC void rb_error_arity(int argc, int min, int max)
int rb_freopen(VALUE fname, const char *mode, FILE *file)
long rb_w32_write_console(uintptr_t, int)
SOCKET rb_w32_get_osfhandle(int)
char rb_w32_fd_is_text(int)
int rb_w32_set_nonblock(int)