24 #include "ccan/list/list.h"
27 #if defined(HAVE_POLL)
28 # if defined(__linux__)
31 # if defined(__FreeBSD_version) && __FreeBSD_version >= 1100000
47 #define free(x) xfree(x)
49 #if defined(DOSISH) || defined(__CYGWIN__)
53 #include <sys/types.h>
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)
72 #include <sys/types.h>
73 #if defined(HAVE_SYS_IOCTL_H) && !defined(_WIN32)
74 #include <sys/ioctl.h>
76 #if defined(HAVE_FCNTL_H) || defined(_WIN32)
78 #elif defined(HAVE_SYS_FCNTL_H)
79 #include <sys/fcntl.h>
82 #if !HAVE_OFF_T && !defined(off_t)
86 #ifdef HAVE_SYS_TIME_H
87 # include <sys/time.h>
92 #if defined(HAVE_SYS_PARAM_H) || defined(__HIUX_MPP__)
93 # include <sys/param.h>
104 #ifdef HAVE_SYSCALL_H
106 #elif defined HAVE_SYS_SYSCALL_H
107 #include <sys/syscall.h>
110 #ifdef HAVE_SYS_UIO_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
136 # define PIPE_BUF 512
141 # define EWOULDBLOCK EAGAIN
144 #if defined(HAVE___SYSCALL) && (defined(__APPLE__) || defined(__OpenBSD__))
146 off_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)
177 static VALUE rb_eEAGAINWaitReadable;
178 static VALUE rb_eEAGAINWaitWritable;
179 static VALUE rb_eEWOULDBLOCKWaitReadable;
180 static VALUE rb_eEWOULDBLOCKWaitWritable;
181 static VALUE rb_eEINPROGRESSWaitWritable;
182 static VALUE rb_eEINPROGRESSWaitReadable;
185 static VALUE orig_stdout, orig_stderr;
194 static ID id_write, id_read, id_getc, id_flush, id_readpartial, id_set_encoding;
195 static VALUE sym_mode, sym_perm, sym_flags, sym_extenc, sym_intenc, sym_encoding, sym_open_args;
196 static VALUE sym_textmode, sym_binmode, sym_autoclose;
197 static VALUE sym_SET, sym_CUR, sym_END;
198 static VALUE sym_wait_readable, sym_wait_writable;
200 static VALUE sym_DATA;
203 static 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;
258 if (flags != flags2) {
261 rb_bug(
"rb_maygvl_fd_fix_cloexec: fcntl(%d, F_SETFD, %d) failed: %s", fd, flags2,
strerror(
errno));
276 rb_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;
360 rb_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)
503 static 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) {
639 set_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)
685 static const char closed_stream[] =
"closed stream";
688 io_fd_check_closed(
int fd)
721 io_fd_check_closed(fptr->
fd);
725 rb_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);
852 flush_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)
905 io_read_encoding(
rb_io_t *fptr)
914 io_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)
1009 struct io_internal_writev_struct {
1012 const struct iovec *iov;
1016 static int nogvl_wait_for_single_fd(
int fd,
short events);
1018 internal_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
1042 internal_write_func(
void *
ptr)
1051 internal_write_func2(
void *
ptr)
1053 return (
void*)internal_write_func(
ptr);
1058 internal_writev_func(
void *
ptr)
1060 struct io_internal_writev_struct *iis =
ptr;
1068 rb_read_internal(
int fd,
void *
buf,
size_t count)
1081 rb_write_internal(
int fd,
const void *
buf,
size_t count)
1092 rb_write_internal2(
int fd,
const void *
buf,
size_t count)
1105 rb_writev_internal(
int fd,
const struct iovec *iov,
int iovcnt)
1107 struct io_internal_writev_struct iis;
1110 iis.iovcnt = iovcnt;
1117 io_flush_buffer_sync(
void *
arg)
1120 long l = fptr->
wbuf.len;
1123 if (fptr->
wbuf.len <= r) {
1137 io_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) {
1176 io_flush_buffer(
rb_io_t *fptr)
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;
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",
1585 struct 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);
1599 io_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);
1725 iovcnt_ok(
int iovcnt)
1799 return io_write(io,
str, 0);
1817 " which accepts just one argument",
1851 nogvl_fsync(
void *
ptr)
1876 if (io_fflush(fptr) < 0)
1922 rb_io_tell(
VALUE io)
1930 pos -= fptr->
rbuf.len;
1935 rb_io_seek(
VALUE io,
VALUE offset,
int whence)
1942 pos =
io_seek(fptr, pos, whence);
1949 interpret_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);
2029 static void clear_readconv(
rb_io_t *fptr);
2048 rb_io_rewind(
VALUE io)
2054 if (io ==
ARGF.current_file) {
2059 clear_readconv(fptr);
2066 fptr_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) {
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
2264 nogvl_fdatasync(
void *
ptr)
2294 if (io_fflush(fptr) < 0)
2304 #define rb_io_fdatasync rb_io_fsync
2320 rb_io_fileno(
VALUE io)
2375 static const char closed[] =
" (closed)";
2407 rb_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;
2559 #define MORE_CHAR_SUSPENDED Qtrue
2560 #define MORE_CHAR_FINISHED Qnil
2562 fill_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
2696 io_shrink_read_string(
VALUE str,
long n)
2704 io_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);
2841 n = read_internal_locktmp(
str, &iis);
2844 if (!
nonblock && fptr_wait_readable(fptr))
2848 return sym_wait_readable;
2851 e,
"read would block");
2856 io_set_read_length(
str,
n, shrinkable);
2941 io_nonblock_eof(
int no_exception)
2943 if (!no_exception) {
2962 shrinkable = io_setstrbuf(&
str,
len);
2974 shrinkable |= io_setstrbuf(&
str,
len);
2979 n = read_internal_locktmp(
str, &iis);
2983 if (!ex)
return sym_wait_readable;
2985 e,
"read would block");
2990 io_set_read_length(
str,
n, shrinkable);
2993 if (!ex)
return Qnil;
3015 if (io_fflush(fptr) < 0)
3026 return sym_wait_writable;
3112 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
3118 if (
NIL_P(length)) {
3121 return read_all(fptr, remain_size(fptr),
str);
3128 shrinkable = io_setstrbuf(&
str,
len);
3133 io_set_read_length(
str, 0, shrinkable);
3138 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
3139 previous_mode = set_binary_mode_with_seek_cur(fptr);
3141 n = io_fread(
str, 0,
len, fptr);
3142 io_set_read_length(
str,
n, shrinkable);
3143 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
3144 if (previous_mode == O_TEXT) {
3145 setmode(fptr->
fd, O_TEXT);
3148 if (
n == 0)
return Qnil;
3154 rscheck(
const char *rsptr,
long rslen,
VALUE rs)
3162 appendline(
rb_io_t *fptr,
int delim,
VALUE *strp,
long *lp)
3169 make_readconv(fptr, 0);
3175 if (0 < limit && limit < searchlen)
3176 searchlen = (
int)limit;
3177 e =
memchr(p, delim, searchlen);
3195 fptr->
cbuf.off += searchlen;
3196 fptr->
cbuf.len -= searchlen;
3205 clear_readconv(fptr);
3218 if (limit > 0 && pending > limit) pending = limit;
3219 e =
memchr(p, delim, pending);
3220 if (e) pending = e - p + 1;
3233 if (e)
return delim;
3238 }
while (io_fillbuf(fptr) >= 0);
3250 make_readconv(fptr, 0);
3259 while (--
i && *++p ==
term);
3262 const char *e = p +
cnt;
3267 io_shift_cbuf(fptr, (
int)
cnt -
i,
NULL);
3283 while (--
i && *++p ==
term);
3284 if (!read_buffered_data(
buf,
cnt -
i, fptr))
3288 }
while (io_fillbuf(fptr) == 0);
3308 e =
memchr(p,
'\n', pending);
3310 pending = (
int)(e - p + 1);
3312 chomplen = (pending > 1 && *(e-1) ==
'\r') + 1;
3317 fptr->
rbuf.off += pending;
3318 fptr->
rbuf.len -= pending;
3323 fptr->
rbuf.off += chomplen;
3324 fptr->
rbuf.len -= chomplen;
3325 if (pending == 1 && chomplen == 1 &&
len > 0) {
3332 len += pending - chomplen;
3338 }
while (io_fillbuf(fptr) >= 0);
3341 str = io_enc_str(
str, fptr);
3352 unsigned int chomp: 1;
3368 args->
chomp = chomp;
3386 else if (2 <=
argc) {
3396 check_getline_args(
VALUE *rsp,
long *limit,
VALUE io)
3406 enc_io = io_read_encoding(fptr);
3407 if (enc_io != enc_rs &&
3429 extract_getline_args(
argc,
argv, args);
3430 extract_getline_opts(opts, args);
3431 check_getline_args(&args->
rs, &args->
limit, io);
3435 rb_io_getline_0(
VALUE rs,
long limit,
int chomp,
rb_io_t *fptr)
3442 if (
NIL_P(rs) && limit < 0) {
3443 str = read_all(fptr, 0,
Qnil);
3447 else if (limit == 0) {
3453 return rb_io_getline_fast(fptr, enc, chomp);
3456 int c, newline = -1;
3457 const char *rsptr = 0;
3460 int extra_limit = 16;
3461 int chomp_cr = chomp;
3464 enc = io_read_encoding(fptr);
3472 swallow(fptr,
'\n');
3485 newline = (
unsigned char)rsptr[rslen - 1];
3486 chomp_cr = chomp && rslen == 1 && newline ==
'\n';
3490 while ((c = appendline(fptr, newline, &
str, &limit)) !=
EOF) {
3491 const char *s, *p, *pp, *e;
3499 if (pp != p)
continue;
3500 if (!rspara) rscheck(rsptr, rslen, rs);
3501 if (
memcmp(p, rsptr, rslen) == 0) {
3503 if (chomp_cr && p > s && *(p-1) ==
'\r') --p;
3527 if (rspara && c !=
EOF)
3528 swallow(fptr,
'\n');
3530 str = io_enc_str(
str, fptr);
3541 rb_io_getline_1(
VALUE rs,
long limit,
int chomp,
VALUE io)
3544 int old_lineno, new_lineno;
3548 old_lineno = fptr->
lineno;
3549 str = rb_io_getline_0(rs, limit, chomp, fptr);
3551 if (io ==
ARGF.current_file) {
3552 ARGF.lineno += new_lineno - old_lineno;
3556 ARGF.last_lineno = new_lineno;
3742 return io_readlines(&args,
io);
3750 if (
arg->limit == 0)
3753 while (!
NIL_P(line = rb_io_getline_1(
arg->rs,
arg->limit,
arg->chomp,
io))) {
3798 if (args.
limit == 0)
3845 while (fptr->
rbuf.len > 0) {
3846 char *p = fptr->
rbuf.ptr + fptr->
rbuf.off++;
3853 }
while (io_fillbuf(fptr) >= 0);
3867 return rb_io_each_byte(
io);
3881 make_readconv(fptr, 0);
3884 if (fptr->
cbuf.len) {
3890 if (fptr->
cbuf.len == fptr->
cbuf.capa) {
3896 if (fptr->
cbuf.len == 0) {
3897 clear_readconv(fptr);
3902 fptr->
cbuf.off += 1;
3903 fptr->
cbuf.len -= 1;
3904 if (fptr->
cbuf.len == 0) clear_readconv(fptr);
3913 io_shift_cbuf(fptr, r, &
str);
3924 str = io_enc_str(
str, fptr);
3930 if (io_fillbuf(fptr) < 0) {
3935 fptr->
rbuf.off += 1;
3936 fptr->
rbuf.len -= 1;
3944 fptr->
rbuf.off +=
n;
3945 fptr->
rbuf.len -=
n;
3952 if (io_fillbuf(fptr) != -1) {
3972 str = io_enc_str(
str, fptr);
4003 enc = io_input_encoding(fptr);
4005 while (!
NIL_P(c = io_getc(fptr, enc))) {
4021 return rb_io_each_char(
io);
4041 rb_io_each_codepoint(
VALUE io)
4057 make_readconv(fptr, 0);
4059 if (fptr->
cbuf.len) {
4068 if (fptr->
cbuf.len == fptr->
cbuf.capa) {
4073 clear_readconv(fptr);
4094 fptr->
cbuf.off +=
n;
4095 fptr->
cbuf.len -=
n;
4100 enc = io_input_encoding(fptr);
4101 while (io_fillbuf(fptr) >= 0) {
4108 fptr->
rbuf.off +=
n;
4109 fptr->
rbuf.len -=
n;
4117 char cbuf[8], *p = cbuf;
4119 if (more >
numberof(cbuf))
goto invalid;
4120 more +=
n = fptr->
rbuf.len;
4121 if (more >
numberof(cbuf))
goto invalid;
4122 while ((
n = (
int)read_buffered_data(p, more, fptr)) > 0 &&
4123 (p +=
n, (more -=
n) > 0)) {
4124 if (io_fillbuf(fptr) < 0)
goto invalid;
4125 if ((
n = fptr->
rbuf.len) > more)
n = more;
4149 return rb_io_each_codepoint(
io);
4174 enc = io_input_encoding(fptr);
4176 return io_getc(fptr, enc);
4230 if (io_fillbuf(fptr) < 0) {
4288 unsigned char c =
NUM2INT(
v) & 0xFF;
4294 io_ungetbyte(b, fptr);
4335 #if SIZEOF_LONG > SIZEOF_INT
4339 make_readconv(fptr, (
int)
len);
4345 char, fptr->
cbuf.len);
4354 io_ungetbyte(c, fptr);
4382 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
4405 if (
io != write_io) {
4407 if (fptr && 0 <= (fd = fptr->
fd)) {
4414 if (fptr && 0 <= (fd = fptr->
fd)) {
4421 #define rb_io_close_on_exec_p rb_f_notimplement
4424 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
4454 if (
io != write_io) {
4456 if (fptr && 0 <= (fd = fptr->
fd)) {
4468 if (fptr && 0 <= (fd = fptr->
fd)) {
4479 #define rb_io_set_close_on_exec rb_f_notimplement
4482 #define FMODE_PREP (1<<16)
4483 #define IS_PREP_STDIO(f) ((f)->mode & FMODE_PREP)
4484 #define PREP_STDIO_NAME(f) (RSTRING_PTR((f)->pathv))
4487 finish_writeconv(
rb_io_t *fptr,
int noalloc)
4489 unsigned char *ds, *
dp, *de;
4492 if (!fptr->
wbuf.ptr) {
4493 unsigned char buf[1024];
4504 r = rb_write_internal2(fptr->
fd, ds,
dp-ds);
4506 r = rb_write_internal(fptr->
fd, ds,
dp-ds);
4531 if (fptr->
wbuf.len == fptr->
wbuf.capa) {
4532 if (io_fflush(fptr) < 0)
4536 ds =
dp = (
unsigned char *)fptr->
wbuf.ptr + fptr->
wbuf.off + fptr->
wbuf.len;
4537 de = (
unsigned char *)fptr->
wbuf.ptr + fptr->
wbuf.capa;
4562 nogvl_close(
void *
ptr)
4570 maygvl_close(
int fd,
int keepgvl)
4583 nogvl_fclose(
void *
ptr)
4591 maygvl_fclose(
FILE *file,
int keepgvl)
4603 fptr_finalize_flush(
rb_io_t *
fptr,
int noraise,
int keepgvl,
4615 arg.noalloc = noraise;
4619 err = finish_writeconv(
fptr, noraise);
4624 io_flush_buffer_sync(
fptr);
4647 else if (stdio_file) {
4650 if ((maygvl_fclose(stdio_file, noraise) < 0) &&
NIL_P(
err))
4661 if ((maygvl_close(fd, keepgvl) < 0) &&
NIL_P(
err))
4676 fptr_finalize_flush(
fptr, noraise,
FALSE, 0);
4679 clear_codeconv(
fptr);
4689 fptr_finalize(
fptr, noraise);
4725 clear_readconv(
fptr);
4726 clear_writeconv(
fptr);
4741 clear_codeconv(
fptr);
4745 #undef rb_io_fptr_finalize
4757 #define rb_io_fptr_finalize(fptr) rb_io_fptr_finalize_internal(fptr)
4773 # define KEEPGVL TRUE
4775 # define KEEPGVL FALSE
4780 io_close_fptr(
VALUE io)
4787 list_head_init(&busy);
4789 if (io != write_io) {
4790 write_fptr =
RFILE(write_io)->fptr;
4791 if (write_fptr && 0 <= write_fptr->
fd) {
4792 rb_io_fptr_cleanup(write_fptr,
TRUE);
4796 fptr =
RFILE(io)->fptr;
4797 if (!fptr)
return 0;
4798 if (fptr->
fd < 0)
return 0;
4804 rb_io_fptr_cleanup(fptr,
FALSE);
4809 fptr_waitpid(
rb_io_t *fptr,
int nohang)
4822 rb_io_t *fptr = io_close_fptr(io);
4823 if (fptr) fptr_waitpid(fptr, 0);
4843 rb_io_close_m(
VALUE io)
4845 rb_io_t *fptr = rb_io_get_fptr(io);
4854 io_call_close(
VALUE io)
4863 enum {mesg_len =
sizeof(closed_stream)-1};
4878 rb_rescue2(io_call_close, io, ignore_closed_stream, io,
4903 rb_io_closed(
VALUE io)
4910 if (io != write_io) {
4911 write_fptr =
RFILE(write_io)->fptr;
4912 if (write_fptr && 0 <= write_fptr->
fd) {
4917 fptr = rb_io_get_fptr(io);
4942 rb_io_close_read(
VALUE io)
4948 if (fptr->
fd < 0)
return Qnil;
4962 if (io != write_io) {
4967 RFILE(io)->fptr = wfptr;
4970 RFILE(write_io)->fptr = fptr;
4971 rb_io_fptr_cleanup(fptr,
FALSE);
5004 rb_io_close_write(
VALUE io)
5011 if (fptr->
fd < 0)
return Qnil;
5028 if (io != write_io) {
5052 VALUE offset, ptrname;
5058 whence = interpret_seek_whence(ptrname);
5067 rb_warn(
"sysseek for buffered IO");
5070 pos =
lseek(fptr->
fd, pos, whence);
5104 if (fptr->
wbuf.len) {
5105 rb_warn(
"syswrite for buffered IO");
5110 n = rb_write_internal(fptr->
fd,
ptr,
len);
5148 shrinkable = io_setstrbuf(&
str, ilen);
5149 if (ilen == 0)
return str;
5169 io_setstrbuf(&
str, ilen);
5174 n = read_internal_locktmp(
str, &iis);
5179 io_set_read_length(
str,
n, shrinkable);
5180 if (
n == 0 && ilen > 0) {
5187 #if defined(HAVE_PREAD) || defined(HAVE_PWRITE)
5188 struct prdwr_internal_arg {
5196 #if defined(HAVE_PREAD)
5198 internal_pread_func(
void *
arg)
5200 struct prdwr_internal_arg *p =
arg;
5201 return (
VALUE)
pread(p->fd, p->buf, p->count, p->offset);
5207 struct prdwr_internal_arg *p = (
struct prdwr_internal_arg *)
arg;
5239 struct prdwr_internal_arg
arg;
5246 shrinkable = io_setstrbuf(&
str, (
long)
arg.count);
5247 if (
arg.count == 0)
return str;
5262 io_set_read_length(
str,
n, shrinkable);
5263 if (
n == 0 &&
arg.count > 0) {
5270 # define rb_io_pread rb_f_notimplement
5273 #if defined(HAVE_PWRITE)
5275 internal_pwrite_func(
void *
ptr)
5277 struct prdwr_internal_arg *
arg =
ptr;
5306 struct prdwr_internal_arg
arg;
5330 # define rb_io_pwrite rb_f_notimplement
5358 io_ascii8bit_binmode(
rb_io_t *fptr)
5376 clear_codeconv(fptr);
5385 io_ascii8bit_binmode(fptr);
5403 rb_io_binmode_m(
VALUE io)
5422 rb_io_binmode_p(
VALUE io)
5430 rb_io_fmode_modestr(
int fmode)
5444 return MODE_BTXMODE(
"w",
"wb",
"wt",
"wx",
"wbx",
"wtx");
5447 return MODE_BTXMODE(
"w+",
"wb+",
"wt+",
"w+x",
"wb+x",
"wt+x");
5453 static const char bom_prefix[] =
"bom|";
5454 static const char utf_prefix[] =
"utf-";
5459 io_encname_bom_p(
const char *
name,
long len)
5468 const char *m = modestr, *p =
NULL;
5497 if (modestr[0] !=
'w')
5505 if (io_encname_bom_p(m, p ? (
long)(p - m) : (
long)
strlen(m)))
5535 if (oflags & O_APPEND) {
5538 if (oflags & O_TRUNC) {
5541 if (oflags & O_CREAT) {
5544 if (oflags & O_EXCL) {
5557 rb_io_fmode_oflags(
int fmode)
5601 rb_io_oflags_modestr(
int oflags)
5604 # define MODE_BINARY(a,b) ((oflags & O_BINARY) ? (b) : (a))
5606 # define MODE_BINARY(a,b) (a)
5609 if (oflags & O_EXCL) {
5612 accmode = oflags & (O_RDONLY|O_WRONLY|O_RDWR);
5613 if (oflags & O_APPEND) {
5614 if (accmode == O_WRONLY) {
5617 if (accmode == O_RDWR) {
5629 if (oflags & O_TRUNC) {
5644 int default_ext = 0;
5654 else if (intern ==
NULL) {
5660 *enc = (default_ext && intern != ext) ?
NULL : ext;
5676 parse_mode_enc(
const char *estr,
rb_encoding *estr_enc,
5682 int fmode = fmode_p ? *fmode_p : 0;
5689 len = p ? (p++ - estr) : (
long)
strlen(estr);
5697 rb_enc_warn(estr_enc,
"BOM with non-UTF encoding %s is nonsense", estr);
5707 encname[
len] =
'\0';
5712 if (fmode_p) *fmode_p =
fmode;
5718 unsupported_encoding(estr, estr_enc);
5724 if (*p ==
'-' && *(p+1) ==
'\0') {
5731 unsupported_encoding(p, estr_enc);
5740 rb_io_ext_int_to_encs(ext_enc, int_enc, enc_p, enc2_p,
fmode);
5754 if (
v !=
Qnil) encoding =
v;
5756 if (
v !=
Qnil) extenc =
v;
5765 encoding, extenc ==
Qundef ?
"internal" :
"external");
5773 if (
NIL_P(intenc)) {
5780 if (*p ==
'-' && *(p+1) ==
'\0') {
5791 if (extencoding == intencoding) {
5795 if (!
NIL_P(encoding)) {
5799 enc_p, enc2_p, fmode_p);
5807 rb_io_ext_int_to_encs(extencoding, intencoding, enc_p, enc2_p, 0);
5817 int fmode = *fmode_p;
5833 #if !DEFAULT_TEXTMODE
5844 if (!
NIL_P(opthash)) {
5872 int *oflags_p,
int *fmode_p,
convconfig_t *convconfig_p)
5879 int has_enc = 0, has_vmode = 0;
5885 rb_io_ext_int_to_encs(
NULL,
NULL, &enc, &enc2, 0);
5903 oflags = rb_io_fmode_oflags(
fmode);
5913 rb_io_ext_int_to_encs(e,
NULL, &enc, &enc2,
fmode);
5917 if (
NIL_P(opthash)) {
5921 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
5924 0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE) : 0;
5934 if (!
NIL_P(vmode)) {
5949 extract_binmode(opthash, &
fmode);
5957 #if DEFAULT_TEXTMODE
5958 else if (
NIL_P(vmode)) {
5965 if (!
NIL_P(*vperm_p)) {
5977 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
5980 0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE) : 0;
5992 validate_enc_binmode(&
fmode, ecflags, enc, enc2);
5998 convconfig_p->enc = enc;
5999 convconfig_p->enc2 = enc2;
6000 convconfig_p->ecflags = ecflags;
6001 convconfig_p->ecopts = ecopts;
6011 sysopen_func(
void *
ptr)
6039 fd = rb_sysopen_internal(&data);
6043 fd = rb_sysopen_internal(&data);
6060 file =
fdopen(fd, modestr);
6067 file =
fdopen(fd, modestr);
6072 file =
fdopen(fd, modestr);
6077 #elif defined(__sun)
6087 rb_warn(
"setvbuf() can't be honoured (fd=%d)", fd);
6105 io_strip_bom(
VALUE io)
6107 VALUE b1, b2, b3, b4;
6168 io_set_encoding_by_bom(
VALUE io)
6170 int idx = io_strip_bom(io);
6178 rb_io_internal_encoding(io),
Qnil);
6200 validate_enc_binmode(&
fmode, convconfig->ecflags,
6201 convconfig->enc, convconfig->enc2);
6205 fptr->
encs = *convconfig;
6208 if (!(
oflags & O_TMPFILE)) {
6209 fptr->
pathv = pathv;
6212 fptr->
pathv = pathv;
6222 rb_file_open_internal(
VALUE io,
VALUE filename,
const char *modestr)
6225 const char *p =
strchr(modestr,
':');
6230 &convconfig.enc, &convconfig.enc2, &
fmode);
6231 convconfig.ecflags = 0;
6232 convconfig.ecopts =
Qnil;
6239 rb_io_ext_int_to_encs(e,
NULL, &convconfig.enc, &convconfig.enc2,
fmode);
6240 convconfig.ecflags = 0;
6241 convconfig.ecopts =
Qnil;
6244 return rb_file_open_generic(io, filename,
6245 rb_io_fmode_oflags(
fmode),
6255 return rb_file_open_internal(io_alloc(
rb_cFile),
fname, modestr);
6264 #if defined(__CYGWIN__) || !defined(HAVE_WORKING_FORK)
6265 static struct pipe_list {
6267 struct pipe_list *next;
6273 struct pipe_list *
list;
6277 list->next = pipe_list;
6284 struct pipe_list **prev = &pipe_list;
6285 struct pipe_list *tmp;
6287 while ((tmp = *prev) != 0) {
6288 if (tmp->fptr == fptr) {
6297 #if defined (_WIN32) || defined(__CYGWIN__)
6301 struct pipe_list *
list = pipe_list;
6302 struct pipe_list *tmp;
6313 pipe_finalize(
rb_io_t *fptr,
int noraise)
6315 #if !defined(HAVE_WORKING_FORK) && !defined(_WIN32)
6324 fptr_finalize(fptr, noraise);
6326 pipe_del_fptr(fptr);
6333 #if defined(__CYGWIN__) || !defined(HAVE_WORKING_FORK)
6341 #if defined(__CYGWIN__) || !defined(HAVE_WORKING_FORK)
6342 if (old_finalize != pipe_finalize) {
6343 struct pipe_list *
list;
6345 if (
list->fptr == fptr)
break;
6347 if (!
list) pipe_add_fptr(fptr);
6350 pipe_del_fptr(fptr);
6386 #define HAVE_SPAWNV 1
6387 #define spawnv(mode, cmd, args) rb_w32_uaspawn((mode), (cmd), (args))
6388 #define spawn(mode, cmd) rb_w32_uspawn((mode), (cmd), 0)
6391 #if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
6401 #ifdef HAVE_WORKING_FORK
6403 popen_redirect(
struct popen_arg *p)
6406 close(p->write_pair[1]);
6407 if (p->write_pair[0] != 0) {
6408 dup2(p->write_pair[0], 0);
6409 close(p->write_pair[0]);
6412 if (p->pair[1] != 1) {
6413 dup2(p->pair[1], 1);
6419 if (p->pair[1] != 1) {
6420 dup2(p->pair[1], 1);
6426 if (p->pair[0] != 0) {
6427 dup2(p->pair[0], 0);
6433 #if defined(__linux__)
6444 linux_get_maxfd(
void)
6447 char buf[4096], *p, *np, *e;
6450 if (fd < 0)
return fd;
6452 if (ss < 0)
goto err;
6455 while ((
int)
sizeof(
"FDSize:\t0\n")-1 <= e-p &&
6457 if (
memcmp(p,
"FDSize:",
sizeof(
"FDSize:")-1) == 0) {
6459 p +=
sizeof(
"FDSize:")-1;
6479 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
6481 int max = (
int)max_file_descriptor;
6484 ret =
fcntl(0, F_MAXFD);
6486 maxhint = max = ret;
6487 # elif defined(__linux__)
6488 ret = linux_get_maxfd();
6495 for (fd = lowfd; fd <= max; fd++) {
6496 if (!
NIL_P(noclose_fds) &&
6503 # define CONTIGUOUS_CLOSED_FDS 20
6505 if (max < fd + CONTIGUOUS_CLOSED_FDS)
6506 max = fd + CONTIGUOUS_CLOSED_FDS;
6513 popen_exec(
void *pp,
char *errmsg,
size_t errmsg_len)
6515 struct popen_arg *p = (
struct popen_arg*)pp;
6521 #if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
6523 rb_execarg_fixup_v(
VALUE execarg_obj)
6533 pipe_open(
VALUE execarg_obj,
const char *modestr,
int fmode,
6543 #if defined(HAVE_WORKING_FORK)
6545 char errmsg[80] = {
'\0' };
6547 #if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
6549 struct popen_arg
arg;
6552 #if defined(HAVE_SPAWNV)
6553 # if defined(HAVE_SPAWNVE)
6554 # define DO_SPAWN(cmd, args, envp) ((args) ? \
6555 spawnve(P_NOWAIT, (cmd), (args), (envp)) : \
6556 spawne(P_NOWAIT, (cmd), (envp)))
6558 # define DO_SPAWN(cmd, args, envp) ((args) ? \
6559 spawnv(P_NOWAIT, (cmd), (args)) : \
6560 spawn(P_NOWAIT, (cmd)))
6562 # if !defined(HAVE_WORKING_FORK)
6564 # if defined(HAVE_SPAWNVE)
6569 #if !defined(HAVE_WORKING_FORK)
6575 #if !defined(HAVE_WORKING_FORK)
6576 const char *
cmd = 0;
6582 #if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
6583 arg.execarg_obj = execarg_obj;
6586 arg.pair[0] =
arg.pair[1] = -1;
6587 arg.write_pair[0] =
arg.write_pair[1] = -1;
6588 # if !defined(HAVE_WORKING_FORK)
6623 if (!
NIL_P(execarg_obj)) {
6624 rb_protect(rb_execarg_fixup_v, execarg_obj, &state);
6626 if (0 <=
arg.write_pair[0])
close(
arg.write_pair[0]);
6627 if (0 <=
arg.write_pair[1])
close(
arg.write_pair[1]);
6634 # if defined(HAVE_WORKING_FORK)
6638 # if defined(HAVE_SPAWNVE)
6641 while ((pid = DO_SPAWN(
cmd, args, envp)) < 0) {
6643 switch (e =
errno) {
6645 # if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
6659 # if defined(HAVE_WORKING_FORK)
6663 popen_redirect(&
arg);
6675 # if defined(HAVE_WORKING_FORK)
6684 # if defined(HAVE_WORKING_FORK)
6694 write_fd =
arg.write_pair[1];
6706 if (!
NIL_P(execarg_obj)) {
6726 fptr->
encs = *convconfig;
6727 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
6737 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
6739 fptr->
encs.
ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
6745 if (0 <= write_fd) {
6746 write_port = io_alloc(
rb_cIO);
6748 write_fptr->
fd = write_fd;
6755 #if defined (__CYGWIN__) || !defined(HAVE_WORKING_FORK)
6757 pipe_add_fptr(fptr);
6763 is_popen_fork(
VALUE prog)
6766 #if !defined(HAVE_WORKING_FORK)
6768 "fork() function is unimplemented on this machine");
6777 pipe_open_s(
VALUE prog,
const char *modestr,
int fmode,
6784 if (!is_popen_fork(prog))
6786 return pipe_open(execarg_obj, modestr,
fmode, convconfig);
6790 pipe_close(
VALUE io)
6792 rb_io_t *fptr = io_close_fptr(io);
6888 const char *modestr;
6903 int ex = !
NIL_P(opt);
6911 #if SIZEOF_LONG > SIZEOF_INT
6922 if (!is_popen_fork(pname))
6925 if (!
NIL_P(execarg_obj)) {
6932 modestr = rb_io_oflags_modestr(oflags);
6934 port = pipe_open(execarg_obj, modestr,
fmode, &convconfig);
6954 VALUE *fname_p,
int *oflags_p,
int *fmode_p,
6957 VALUE opt, fname, vmode, vperm;
6982 rb_scan_open_args(
argc,
argv, &fname, &oflags, &
fmode, &convconfig, &perm);
6983 rb_file_open_generic(io, fname, oflags,
fmode, &convconfig, perm);
7050 VALUE fname, vmode, vperm;
7066 if (
NIL_P(vperm)) perm = 0666;
7070 fd = rb_sysopen(fname, oflags, perm);
7075 check_pipe_command(
VALUE filename_or_command)
7191 int redirect =
FALSE;
7205 VALUE cmd = check_pipe_command(tmp);
7235 return rb_io_open_generic(io, filename, oflags,
fmode, &convconfig, perm);
7244 return pipe_open_s(
cmd, rb_io_oflags_modestr(oflags),
fmode, convconfig);
7247 return rb_file_open_generic(io_alloc(
klass), filename,
7248 oflags,
fmode, convconfig, perm);
7263 if (fptr == orig)
return io;
7269 "%s can't change access mode from \"%s\" to \"%s\"",
7271 rb_io_fmode_modestr(orig->
mode));
7275 if (io_fflush(fptr) < 0)
7279 flush_before_seek(fptr);
7285 if (io_fflush(orig) < 0)
7295 fptr_copy_finalizer(fptr, orig);
7368 VALUE fname, nmode, opt;
7375 return io_reopen(file, tmp);
7381 fptr =
RFILE(file)->fptr;
7395 "%s can't change access mode from \"%s\" to \"%s\"",
7397 rb_io_fmode_modestr(
fmode));
7400 fptr->
encs = convconfig;
7403 oflags = rb_io_fmode_oflags(fptr->
mode);
7406 fptr->
pathv = fname;
7408 fptr->
fd = rb_sysopen(fptr->
pathv, oflags, 0666);
7414 if (io_fflush(fptr) < 0)
7417 fptr->
rbuf.off = fptr->
rbuf.len = 0;
7421 rb_io_oflags_modestr(oflags),
7440 int tmpfd = rb_sysopen(fptr->
pathv, oflags, 0666);
7475 fptr_copy_finalizer(fptr, orig);
7477 fd = ruby_dup(orig->
fd);
7487 if (io != write_io) {
7678 return rb_io_putc(recv, ch);
7692 if (
len == 0)
return 0;
7694 return ptr[
len - 1] == c;
7750 VALUE line, args[2];
7773 rb_io_writev(out,
n, args);
7832 else if (
argc > 1) {
7905 rb_stderr_to_original_p(
void)
7913 if (rb_stderr_to_original_p()) {
7939 if (rb_stderr_to_original_p()) {
7960 if (rb_stderr_to_original_p())
7966 must_respond_to(
ID mid,
VALUE val,
ID id)
7978 must_respond_to(id_write, val,
id);
7991 if (!io_check_tty(fp)) {
8020 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
8021 fptr->
encs.
ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
8035 int oflags = rb_io_fmode_oflags(fptr->
mode) & ~O_EXCL;
8051 rb_io_fptr_new(
void)
8061 rb_io_buffer_init(&fp->
wbuf);
8062 rb_io_buffer_init(&fp->
rbuf);
8063 rb_io_buffer_init(&fp->
cbuf);
8090 fp = rb_io_fptr_new();
8253 int fd,
fmode, oflags = O_RDONLY;
8256 #if defined(HAVE_FCNTL) && defined(F_GETFL)
8270 #if defined(HAVE_FCNTL) && defined(F_GETFL)
8271 oflags =
fcntl(fd, F_GETFL);
8277 #if defined(HAVE_FCNTL) && defined(F_GETFL)
8293 fp->
encs = convconfig;
8326 rb_io_set_encoding_by_bom(
VALUE io)
8341 if (!io_set_encoding_by_bom(io))
return Qnil;
8373 if (
RFILE(io)->fptr) {
8381 return rb_io_initialize(
argc,
argv, io);
8428 rb_io_autoclose_p(
VALUE io)
8453 rb_io_set_autoclose(
VALUE io,
VALUE autoclose)
8457 if (!
RTEST(autoclose))
8465 argf_mark(
void *
ptr)
8476 argf_memsize(
const void *
ptr)
8479 size_t size =
sizeof(*p);
8581 #define next_argv() argf_next_argv(argf)
8582 #define ARGF_GENERIC_INPUT_P() \
8583 (ARGF.current_file == rb_stdin && !RB_TYPE_P(ARGF.current_file, T_FILE))
8584 #define ARGF_FORWARD(argc, argv) do {\
8585 if (ARGF_GENERIC_INPUT_P())\
8586 return argf_forward((argc), (argv), argf);\
8588 #define NEXT_ARGF_FORWARD(argc, argv) do {\
8589 if (!next_argv()) return Qnil;\
8590 ARGF_FORWARD((argc), (argv));\
8610 int stdout_binmode = 0;
8619 if (
ARGF.init_p == 0) {
8637 if (
ARGF.next_p == 1) {
8638 if (
ARGF.init_p == 1) argf_close(
argf);
8649 rb_warn(
"Can't do inplace edit for stdio; skipping");
8655 int fr = rb_sysopen(
filename, O_RDONLY, 0);
8659 #ifndef NO_SAFE_RENAME
8678 #ifdef NO_SAFE_RENAME
8686 fr = rb_sysopen(
str, O_RDONLY, 0);
8697 #ifdef NO_SAFE_RENAME
8698 rb_fatal(
"Can't do inplace edit without backup");
8708 fw = rb_sysopen(filename, O_WRONLY|O_CREAT|O_TRUNC, 0666);
8709 #ifndef NO_SAFE_RENAME
8716 if (
st.st_uid!=st2.st_uid ||
st.st_gid!=st2.st_gid) {
8723 if (
err &&
getuid() == 0 && st2.st_uid == 0) {
8739 if (!
ARGF.binmode) {
8743 if (!
NIL_P(write_io)) {
8750 if (
ARGF.encs.enc) {
8752 clear_codeconv(fptr);
8756 if (!
ARGF.binmode) {
8758 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
8759 fptr->
encs.
ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
8770 else if (
ARGF.next_p == -1) {
8774 rb_warn(
"Can't do inplace edit for stdio");
8778 if (
ARGF.init_p == -1)
ARGF.init_p = 1;
8786 long lineno =
ARGF.lineno;
8807 ARGF.lineno = ++lineno;
8814 argf_lineno_getter(
ID id,
VALUE *var)
8907 return rb_f_gets(0, 0,
argf);
9021 long lineno =
ARGF.lineno;
9030 lines = rb_io_readlines(
argc,
argv,
ARGF.current_file);
9069 result = read_all(fptr, remain_size(fptr),
Qnil);
9078 #ifdef HAVE_SYS_SELECT_H
9079 #include <sys/select.h>
9102 if (max < fptr->fd) max = fptr->
fd;
9105 timerec.tv_sec = timerec.tv_usec = 0;
9119 if (max < fptr->fd) max = fptr->
fd;
9126 if (!
NIL_P(except)) {
9133 if (max < fptr->fd) max = fptr->
fd;
9134 if (io != write_io) {
9137 if (max < fptr->fd) max = fptr->
fd;
9152 if (!pending &&
n == 0)
return Qnil;
9195 else if (io != write_io) {
9232 static VALUE sym_normal, sym_sequential, sym_random,
9233 sym_willneed, sym_dontneed, sym_noreuse;
9235 #ifdef HAVE_POSIX_FADVISE
9236 struct io_advise_struct {
9244 io_advise_internal(
void *
arg)
9246 struct io_advise_struct *
ptr =
arg;
9247 return posix_fadvise(
ptr->fd,
ptr->offset,
ptr->len,
ptr->advice);
9253 #ifdef POSIX_FADV_NORMAL
9254 if (
sym == sym_normal)
9255 return INT2NUM(POSIX_FADV_NORMAL);
9258 #ifdef POSIX_FADV_RANDOM
9259 if (
sym == sym_random)
9260 return INT2NUM(POSIX_FADV_RANDOM);
9263 #ifdef POSIX_FADV_SEQUENTIAL
9264 if (
sym == sym_sequential)
9265 return INT2NUM(POSIX_FADV_SEQUENTIAL);
9268 #ifdef POSIX_FADV_WILLNEED
9269 if (
sym == sym_willneed)
9270 return INT2NUM(POSIX_FADV_WILLNEED);
9273 #ifdef POSIX_FADV_DONTNEED
9274 if (
sym == sym_dontneed)
9275 return INT2NUM(POSIX_FADV_DONTNEED);
9278 #ifdef POSIX_FADV_NOREUSE
9279 if (
sym == sym_noreuse)
9280 return INT2NUM(POSIX_FADV_NOREUSE);
9290 struct io_advise_struct ias;
9293 num_adv = io_advise_sym_to_const(advice);
9303 ias.advice =
NUM2INT(num_adv);
9304 ias.offset = offset;
9308 if (rv && rv !=
ENOSYS) {
9325 advice_arg_check(
VALUE advice)
9330 if (advice != sym_normal &&
9331 advice != sym_sequential &&
9332 advice != sym_random &&
9333 advice != sym_willneed &&
9334 advice != sym_dontneed &&
9335 advice != sym_noreuse) {
9390 advice_arg_check(advice);
9398 #ifdef HAVE_POSIX_FADVISE
9399 return do_io_advise(fptr, advice, off, l);
9401 ((
void)off, (
void)l);
9555 if (
NIL_P(timeout)) {
9560 args.timeout = &timerec;
9569 #if (defined(__linux__) && !defined(__ANDROID__)) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
9571 # define NUM2IOCTLREQ(num) NUM2ULONG(num)
9574 # define NUM2IOCTLREQ(num) ((int)NUM2LONG(num))
9585 nogvl_ioctl(
void *
ptr)
9608 #define DEFULT_IOCTL_NARG_LEN (256)
9610 #if defined(__linux__) && defined(_IOC_SIZE)
9616 if ((cmd & 0xFFFF0000) == 0) {
9621 len = _IOC_SIZE(cmd);
9638 #define IOCPARM_LEN(x) (((x) >> 16) & IOCPARM_MASK)
9642 len = IOCPARM_LEN(cmd);
9643 #elif defined(__linux__) && defined(_IOC_SIZE)
9644 len = linux_iocparm_len(cmd);
9655 typedef long fcntl_arg_t;
9658 typedef int fcntl_arg_t;
9662 fcntl_narg_len(
int cmd)
9669 len =
sizeof(fcntl_arg_t);
9677 #ifdef F_DUPFD_CLOEXEC
9679 len =
sizeof(fcntl_arg_t);
9689 len =
sizeof(fcntl_arg_t);
9699 len =
sizeof(fcntl_arg_t);
9709 len =
sizeof(fcntl_arg_t);
9714 len =
sizeof(
struct f_owner_ex);
9719 len =
sizeof(
struct f_owner_ex);
9754 len =
sizeof(fcntl_arg_t);
9764 len =
sizeof(fcntl_arg_t);
9769 len =
sizeof(fcntl_arg_t);
9782 fcntl_narg_len(
int cmd)
9815 len = ioctl_narg_len(cmd);
9817 len = fcntl_narg_len((
int)cmd);
9846 narg = setup_narg(cmd, &
arg, 1);
9848 retval = do_ioctl(fptr->
fd, cmd, narg);
9854 if (
ptr[slen-1] != 17)
9880 return rb_ioctl(io, req,
arg);
9883 #define rb_io_ioctl rb_f_notimplement
9894 nogvl_fcntl(
void *
ptr)
9896 struct fcntl_arg *
arg =
ptr;
9898 #if defined(F_DUPFD)
9906 do_fcntl(
int fd,
int cmd,
long narg)
9909 struct fcntl_arg
arg;
9918 #if defined(F_DUPFD)
9921 #if defined(F_DUPFD_CLOEXEC)
9939 narg = setup_narg(cmd, &
arg, 0);
9941 retval = do_fcntl(fptr->
fd, cmd, narg);
9947 if (
ptr[slen-1] != 17)
9974 return rb_fcntl(io, req,
arg);
9977 #define rb_io_fcntl rb_f_notimplement
9980 #if defined(HAVE_SYSCALL) || defined(HAVE___SYSCALL)
10019 #if SIZEOF_VOIDP == 8 && defined(HAVE___SYSCALL) && SIZEOF_INT != 8
10020 # define SYSCALL __syscall
10021 # define NUM2SYSCALLID(x) NUM2LONG(x)
10022 # define RETVAL2NUM(x) LONG2NUM(x)
10023 # if SIZEOF_LONG == 8
10024 long num, retval = -1;
10025 # elif SIZEOF_LONG_LONG == 8
10026 long long num, retval = -1;
10028 # error ---->> it is asserted that __syscall takes the first argument and returns retval in 64bit signed integer. <<----
10030 #elif defined(__linux__)
10031 # define SYSCALL syscall
10032 # define NUM2SYSCALLID(x) NUM2LONG(x)
10033 # define RETVAL2NUM(x) LONG2NUM(x)
10041 long num, retval = -1;
10043 # define SYSCALL syscall
10044 # define NUM2SYSCALLID(x) NUM2INT(x)
10045 # define RETVAL2NUM(x) INT2NUM(x)
10046 int num, retval = -1;
10051 rb_warning(
"We plan to remove a syscall function at future release. DL(Fiddle) provides safer alternative.");
10058 num = NUM2SYSCALLID(
argv[0]); ++
argv;
10059 for (
i =
argc - 1;
i--; ) {
10074 retval = SYSCALL(num);
10077 retval = SYSCALL(num,
arg[0]);
10080 retval = SYSCALL(num,
arg[0],
arg[1]);
10083 retval = SYSCALL(num,
arg[0],
arg[1],
arg[2]);
10101 return RETVAL2NUM(retval);
10103 #undef NUM2SYSCALLID
10107 #define rb_f_syscall rb_f_notimplement
10111 io_new_instance(
VALUE args)
10132 enc2 = find_encoding(v1);
10141 enc = find_encoding(v2);
10148 enc = find_encoding(v2);
10160 rb_io_ext_int_to_encs(
NULL,
NULL, &enc, &enc2, 0);
10172 rb_io_ext_int_to_encs(find_encoding(v1),
NULL, &enc, &enc2, 0);
10178 validate_enc_binmode(&fptr->
mode, ecflags, enc, enc2);
10183 clear_codeconv(fptr);
10195 io_encoding_set_v(
VALUE v)
10198 io_encoding_set(
arg->fptr,
arg->v1,
arg->v2,
arg->opt);
10203 pipe_pair_close(
VALUE rw)
10206 return rb_ensure(io_close, rwp[0], io_close, rwp[1]);
10272 int pipes[2], state;
10295 ies_args.fptr =
fptr;
10298 ies_args.opt =
opt;
10324 #if DEFAULT_TEXTMODE
10329 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
10336 #if DEFAULT_TEXTMODE
10432 int orig_argc =
argc;
10438 extract_getline_args(
argc-1,
argv+1, &garg);
10441 extract_getline_opts(opt, &garg);
10442 check_getline_args(&garg.rs, &garg.limit, garg.io =
arg.io);
10450 return io_readlines(
arg,
arg->io);
10491 extract_getline_args(
argc-1,
argv+1, &garg);
10494 extract_getline_opts(opt, &garg);
10495 check_getline_args(&garg.rs, &garg.limit, garg.io =
arg.io);
10503 return io_read(
arg->argc,
arg->argv,
arg->io);
10513 seek_before_access(
VALUE argp)
10517 return rb_io_seek(
arg->io,
arg->offset,
arg->mode);
10571 if (!
NIL_P(offset)) {
10582 if (
arg.argc == 2)
arg.argc = 1;
10618 arg.io = rb_io_open_generic(
io,
argv[0], oflags,
fmode, &convconfig, 0);
10621 arg.argc = (
argc > 1) ? 1 : 0;
10622 if (!
NIL_P(offset)) {
10641 return io_write(
arg->io,
arg->str,
arg->nosync);
10647 VALUE string, offset, opt;
10658 int mode = O_WRONLY|O_CREAT;
10662 if (
NIL_P(offset)) mode |= O_TRUNC;
10668 if (binary) rb_io_binmode_m(
arg.io);
10672 if (!
NIL_P(offset)) {
10773 #ifdef HAVE_FCOPYFILE
10774 copyfile_state_t copyfile_state;
10779 exec_interrupts(
void *
arg)
10796 #if defined(ERESTART)
10811 # define IOWAIT_SYSCALL "poll"
10815 nogvl_wait_for_single_fd(
int fd,
short events)
10820 fds.events = events;
10822 return poll(&fds, 1, -1);
10825 # define IOWAIT_SYSCALL "select"
10827 nogvl_wait_for_single_fd(
int fd,
short events)
10863 }
while (ret < 0 && maygvl_copy_stream_continue_p(has_gvl, stp));
10880 }
while (ret < 0 && maygvl_copy_stream_continue_p(0, stp));
10890 #if defined HAVE_COPY_FILE_RANGE || (defined __linux__ && defined __NR_copy_file_range)
10891 # define USE_COPY_FILE_RANGE
10894 #ifdef USE_COPY_FILE_RANGE
10897 simple_copy_file_range(
int in_fd,
off_t *in_offset,
int out_fd,
off_t *out_offset,
size_t count,
unsigned int flags)
10899 #ifdef HAVE_COPY_FILE_RANGE
10900 return copy_file_range(in_fd, in_offset, out_fd, out_offset,
count, flags);
10902 return syscall(__NR_copy_file_range, in_fd, in_offset, out_fd, out_offset,
count, flags);
10911 off_t copy_length, src_offset, *src_offset_ptr;
10918 if (src_offset >= (
off_t)0) {
10919 src_offset_ptr = &src_offset;
10922 src_offset_ptr =
NULL;
10926 if (copy_length < (
off_t)0) {
10927 if (src_offset < (
off_t)0) {
10928 off_t current_offset;
10934 return (
int)current_offset;
10936 copy_length = src_size - current_offset;
10939 copy_length = src_size - src_offset;
10943 retry_copy_file_range:
10944 # if SIZEOF_OFF_T > SIZEOF_SIZE_T
10950 ss = simple_copy_file_range(stp->
src_fd, src_offset_ptr, stp->
dst_fd,
NULL, ss, 0);
10954 if (0 < copy_length) {
10955 goto retry_copy_file_range;
10959 if (maygvl_copy_stream_continue_p(0, stp)) {
10960 goto retry_copy_file_range;
10974 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
10978 int ret = nogvl_copy_stream_wait_write(stp);
10979 if (ret < 0)
return ret;
10981 goto retry_copy_file_range;
10987 if (flags != -1 && flags & O_APPEND) {
10993 stp->
syserr =
"copy_file_range";
11001 #ifdef HAVE_FCOPYFILE
11022 if (src_offset > (
off_t)0) {
11041 stp->copyfile_state = copyfile_state_alloc();
11042 ret = fcopyfile(stp->
src_fd, stp->
dst_fd, stp->copyfile_state, COPYFILE_DATA);
11043 copyfile_state_get(stp->copyfile_state, COPYFILE_STATE_COPIED, &ss);
11047 if (src_offset > (
off_t)0) {
11065 stp->
syserr =
"fcopyfile";
11073 #ifdef HAVE_SENDFILE
11076 # define USE_SENDFILE
11078 # ifdef HAVE_SYS_SENDFILE_H
11079 # include <sys/sendfile.h>
11085 return sendfile(out_fd, in_fd, offset, (
size_t)
count);
11088 # elif 0 || defined(__APPLE__)
11092 # define USE_SENDFILE
11101 r = sendfile(in_fd, out_fd, pos, &
count,
NULL, 0);
11104 r = sendfile(in_fd, out_fd, pos, (
size_t)
count,
NULL, &sbytes, 0);
11106 if (r != 0 && sbytes == 0)
return r;
11120 #ifdef USE_SENDFILE
11140 use_pread = src_offset >= (
off_t)0;
11143 if (copy_length < (
off_t)0) {
11145 copy_length = src_size - src_offset;
11155 copy_length = src_size - cur;
11160 # if SIZEOF_OFF_T > SIZEOF_SIZE_T
11167 ss = simple_sendfile(stp->
dst_fd, stp->
src_fd, &src_offset, ss);
11175 if (0 < copy_length) {
11176 goto retry_sendfile;
11180 if (maygvl_copy_stream_continue_p(0, stp))
11181 goto retry_sendfile;
11189 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
11202 ret = maygvl_copy_stream_wait_read(0, stp);
11203 if (ret < 0)
return ret;
11205 ret = nogvl_copy_stream_wait_write(stp);
11206 if (ret < 0)
return ret;
11208 goto retry_sendfile;
11210 stp->
syserr =
"sendfile";
11219 maygvl_read(
int has_gvl,
int fd,
void *
buf,
size_t count)
11222 return rb_read_internal(fd,
buf,
count);
11232 if (offset < (
off_t)0) {
11247 if (maygvl_copy_stream_continue_p(has_gvl, stp))
11251 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
11255 int ret = maygvl_copy_stream_wait_read(has_gvl, stp);
11256 if (ret < 0)
return ret;
11265 stp->
syserr = offset < (
off_t)0 ?
"read" :
"pread";
11279 if (maygvl_copy_stream_continue_p(0, stp))
11282 int ret = nogvl_copy_stream_wait_write(stp);
11283 if (ret < 0)
return ret;
11310 use_eof = copy_length < (
off_t)0;
11312 use_pread = src_offset >= (
off_t)0;
11323 src_offset = (
off_t)-1;
11327 while (use_eof || 0 < copy_length) {
11328 if (!use_eof && copy_length < (
off_t)
sizeof(
buf)) {
11335 ss = maygvl_copy_stream_read(0, stp,
buf,
len, src_offset);
11340 ss = maygvl_copy_stream_read(0, stp,
buf,
len, (
off_t)-1);
11345 ret = nogvl_copy_stream_write(stp,
buf, ss);
11355 nogvl_copy_stream_func(
void *
arg)
11358 #if defined(USE_SENDFILE) || defined(USE_COPY_FILE_RANGE) || defined(HAVE_FCOPYFILE)
11362 #ifdef USE_COPY_FILE_RANGE
11363 ret = nogvl_copy_file_range(stp);
11368 #ifdef HAVE_FCOPYFILE
11369 ret = nogvl_fcopyfile(stp);
11374 #ifdef USE_SENDFILE
11375 ret = nogvl_copy_stream_sendfile(stp);
11380 nogvl_copy_stream_read_write(stp);
11382 #if defined(USE_SENDFILE) || defined(USE_COPY_FILE_RANGE) || defined(HAVE_FCOPYFILE)
11389 copy_stream_fallback_body(
VALUE arg)
11392 const int buflen = 16*1024;
11397 ID read_method = id_readpartial;
11401 read_method = id_read;
11416 l = buflen < rest ? buflen : (
long)rest;
11421 if (read_method == id_read &&
NIL_P(rc))
11433 if (off >= (
off_t)0)
11438 stp->
total += numwrote;
11465 rb_io_t *src_fptr = 0, *dst_fptr = 0;
11467 const int common_oflags = 0
11477 if (src_io ==
argf ||
11486 if (!
NIL_P(tmp_io)) {
11493 args[1] =
INT2NUM(O_RDONLY|common_oflags);
11503 if (stat_ret < 0) {
11511 if (dst_io ==
argf ||
11520 if (!
NIL_P(tmp_io)) {
11527 args[1] =
INT2NUM(O_WRONLY|O_CREAT|O_TRUNC|common_oflags);
11542 if (stat_ret < 0) {
11555 io_ascii8bit_binmode(dst_fptr);
11558 size_t len = src_fptr->
rbuf.len;
11578 if (dst_fptr && io_fflush(dst_fptr) < 0) {
11586 return copy_stream_fallback(stp);
11598 #ifdef HAVE_FCOPYFILE
11599 if (stp->copyfile_state) {
11600 copyfile_state_free(stp->copyfile_state);
11605 rb_io_close_m(stp->
src);
11608 rb_io_close_m(stp->
dst);
11688 rb_io_external_encoding(
VALUE io)
11713 rb_io_internal_encoding(
VALUE io)
11753 io_encoding_set(fptr, v1, v2, opt);
11762 rb_io_set_encoding(1, &val,
rb_stdin);
11763 rb_io_set_encoding(1, &val,
rb_stdout);
11764 rb_io_set_encoding(1, &val,
rb_stderr);
11884 return rb_io_tell(
ARGF.current_file);
11922 return rb_io_set_pos(
ARGF.current_file, offset);
11947 old_lineno =
RFILE(
ARGF.current_file)->fptr->lineno;
11948 ret = rb_io_rewind(
ARGF.current_file);
11949 if (!global_argf_p(
argf)) {
11950 ARGF.last_lineno =
ARGF.lineno -= old_lineno;
11972 return rb_io_fileno(
ARGF.current_file);
11992 return ARGF.current_file;
12083 if (!
NIL_P(length)) {
12105 if (
ARGF.next_p != -1) {
12111 else if (
argc >= 1) {
12215 tmp = io_getpartial(
argc,
argv,
ARGF.current_file, no_exception, nonblock);
12218 if (
ARGF.next_p == -1) {
12219 return io_nonblock_eof(no_exception);
12224 return io_nonblock_eof(no_exception);
12267 ch = rb_io_getc(
ARGF.current_file);
12347 ch = rb_io_getc(
ARGF.current_file);
12382 c = argf_getbyte(
argf);
12389 #define FOREACH_ARGF() while (next_argv())
12394 const VALUE current =
ARGF.current_file;
12396 if (
ARGF.init_p == -1 || current !=
ARGF.current_file) {
12402 #define ARGF_block_call(mid, argc, argv, func, argf) \
12403 rb_block_call_kw(ARGF.current_file, mid, argc, argv, \
12404 func, argf, rb_keyword_given_p())
12416 if (!global_argf_p(
argf)) {
12536 return argf_each_byte(
argf);
12575 return argf_each_char(
argf);
12614 return argf_each_codepoint(
argf);
12643 return ARGF.filename;
12647 argf_filename_getter(
ID id,
VALUE *var)
12649 return argf_filename(*var);
12674 return ARGF.current_file;
12734 if (
ARGF.init_p &&
ARGF.next_p == 0) {
12763 if (
ARGF.next_p != -1) {
12782 return rb_io_closed(
ARGF.current_file);
12816 return argf_inplace_mode_get(*var);
12857 argf_inplace_mode_set(*var, val);
12887 argf_argv_getter(
ID id,
VALUE *var)
12889 return argf_argv(*var);
12942 #if EAGAIN != EWOULDBLOCK
12959 #if EAGAIN != EWOULDBLOCK
12972 rb_bug(
"invalid read/write type passed to rb_readwrite_sys_fail: %d", writable);
12977 get_LAST_READ_LINE(
ID _x,
VALUE *_y)
13147 #define rb_intern(str) rb_intern_const(str)
13151 #include <sys/cygwin.h>
13152 static struct __cygwin_perfile pf[] =
13160 cygwin_internal(CW_PERFILE, pf);
13170 id_readpartial =
rb_intern(
"readpartial");
13171 id_set_encoding =
rb_intern(
"set_encoding");
13204 #if EAGAIN == EWOULDBLOCK
13205 rb_eEWOULDBLOCKWaitReadable = rb_eEAGAINWaitReadable;
13208 rb_eEWOULDBLOCKWaitWritable = rb_eEAGAINWaitWritable;
13452 rb_define_method(rb_cARGF,
"external_encoding", argf_external_encoding, 0);
13453 rb_define_method(rb_cARGF,
"internal_encoding", argf_internal_encoding, 0);
13474 #if defined (_WIN32) || defined(__CYGWIN__)
13511 #include "io.rbinc"