Ruby  3.4.0dev (2024-11-05 revision 348a53415339076afc4a02fcd09f3ae36e9c4c61)
io.c (348a53415339076afc4a02fcd09f3ae36e9c4c61)
1 /**********************************************************************
2 
3  io.c -
4 
5  $Author$
6  created at: Fri Oct 15 18:08:59 JST 1993
7 
8  Copyright (C) 1993-2007 Yukihiro Matsumoto
9  Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
10  Copyright (C) 2000 Information-technology Promotion Agency, Japan
11 
12 **********************************************************************/
13 
14 #include "ruby/internal/config.h"
15 
16 #include "ruby/fiber/scheduler.h"
17 #include "ruby/io/buffer.h"
18 
19 #include <ctype.h>
20 #include <errno.h>
21 #include <stddef.h>
22 
23 /* non-Linux poll may not work on all FDs */
24 #if defined(HAVE_POLL)
25 # if defined(__linux__)
26 # define USE_POLL 1
27 # endif
28 # if defined(__FreeBSD_version) && __FreeBSD_version >= 1100000
29 # define USE_POLL 1
30 # endif
31 #endif
32 
33 #ifndef USE_POLL
34 # define USE_POLL 0
35 #endif
36 
37 #undef free
38 #define free(x) xfree(x)
39 
40 #if defined(DOSISH) || defined(__CYGWIN__)
41 #include <io.h>
42 #endif
43 
44 #include <sys/types.h>
45 #if defined HAVE_NET_SOCKET_H
46 # include <net/socket.h>
47 #elif defined HAVE_SYS_SOCKET_H
48 # include <sys/socket.h>
49 #endif
50 
51 #if defined(__BOW__) || defined(__CYGWIN__) || defined(_WIN32)
52 # define NO_SAFE_RENAME
53 #endif
54 
55 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__sun) || defined(_nec_ews)
56 # define USE_SETVBUF
57 #endif
58 
59 #ifdef __QNXNTO__
60 #include <unix.h>
61 #endif
62 
63 #include <sys/types.h>
64 #if defined(HAVE_SYS_IOCTL_H) && !defined(_WIN32)
65 #include <sys/ioctl.h>
66 #endif
67 #if defined(HAVE_FCNTL_H) || defined(_WIN32)
68 #include <fcntl.h>
69 #elif defined(HAVE_SYS_FCNTL_H)
70 #include <sys/fcntl.h>
71 #endif
72 
73 #ifdef HAVE_SYS_TIME_H
74 # include <sys/time.h>
75 #endif
76 
77 #include <sys/stat.h>
78 
79 #if defined(HAVE_SYS_PARAM_H) || defined(__HIUX_MPP__)
80 # include <sys/param.h>
81 #endif
82 
83 #if !defined NOFILE
84 # define NOFILE 64
85 #endif
86 
87 #ifdef HAVE_UNISTD_H
88 #include <unistd.h>
89 #endif
90 
91 #ifdef HAVE_SYSCALL_H
92 #include <syscall.h>
93 #elif defined HAVE_SYS_SYSCALL_H
94 #include <sys/syscall.h>
95 #endif
96 
97 #ifdef HAVE_SYS_UIO_H
98 #include <sys/uio.h>
99 #endif
100 
101 #ifdef HAVE_SYS_WAIT_H
102 # include <sys/wait.h> /* for WNOHANG on BSD */
103 #endif
104 
105 #ifdef HAVE_COPYFILE_H
106 # include <copyfile.h>
107 
108 # ifndef COPYFILE_STATE_COPIED
109 /*
110  * Some OSes (e.g., OSX < 10.6) implement fcopyfile() but not
111  * COPYFILE_STATE_COPIED. Since the only use of the former here
112  * requires the latter, we disable the former when the latter is undefined.
113  */
114 # undef HAVE_FCOPYFILE
115 # endif
116 
117 #endif
118 
119 #include "ruby/internal/stdbool.h"
120 #include "ccan/list/list.h"
121 #include "dln.h"
122 #include "encindex.h"
123 #include "id.h"
124 #include "internal.h"
125 #include "internal/class.h"
126 #include "internal/encoding.h"
127 #include "internal/error.h"
128 #include "internal/inits.h"
129 #include "internal/io.h"
130 #include "internal/numeric.h"
131 #include "internal/object.h"
132 #include "internal/process.h"
133 #include "internal/thread.h"
134 #include "internal/transcode.h"
135 #include "internal/variable.h"
136 #include "ruby/io.h"
137 #include "ruby/io/buffer.h"
138 #include "ruby/missing.h"
139 #include "ruby/thread.h"
140 #include "ruby/util.h"
141 #include "ruby_atomic.h"
142 #include "ruby/ractor.h"
143 
144 #if !USE_POLL
145 # include "vm_core.h"
146 #endif
147 
148 #include "builtin.h"
149 
150 #ifndef O_ACCMODE
151 #define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR)
152 #endif
153 
154 #ifndef PIPE_BUF
155 # ifdef _POSIX_PIPE_BUF
156 # define PIPE_BUF _POSIX_PIPE_BUF
157 # else
158 # define PIPE_BUF 512 /* is this ok? */
159 # endif
160 #endif
161 
162 #ifndef EWOULDBLOCK
163 # define EWOULDBLOCK EAGAIN
164 #endif
165 
166 #if defined(HAVE___SYSCALL) && (defined(__APPLE__) || defined(__OpenBSD__))
167 /* Mac OS X and OpenBSD have __syscall but don't define it in headers */
168 off_t __syscall(quad_t number, ...);
169 #endif
170 
171 #define IO_RBUF_CAPA_MIN 8192
172 #define IO_CBUF_CAPA_MIN (128*1024)
173 #define IO_RBUF_CAPA_FOR(fptr) (NEED_READCONV(fptr) ? IO_CBUF_CAPA_MIN : IO_RBUF_CAPA_MIN)
174 #define IO_WBUF_CAPA_MIN 8192
175 
176 #define IO_MAX_BUFFER_GROWTH 8 * 1024 * 1024 // 8MB
177 
178 /* define system APIs */
179 #ifdef _WIN32
180 #undef open
181 #define open rb_w32_uopen
182 #undef rename
183 #define rename(f, t) rb_w32_urename((f), (t))
184 #include "win32/file.h"
185 #endif
186 
193 
194 static VALUE rb_eEAGAINWaitReadable;
195 static VALUE rb_eEAGAINWaitWritable;
196 static VALUE rb_eEWOULDBLOCKWaitReadable;
197 static VALUE rb_eEWOULDBLOCKWaitWritable;
198 static VALUE rb_eEINPROGRESSWaitWritable;
199 static VALUE rb_eEINPROGRESSWaitReadable;
200 
202 static VALUE orig_stdout, orig_stderr;
203 
208 
209 static VALUE argf;
210 
211 static ID id_write, id_read, id_getc, id_flush, id_readpartial, id_set_encoding, id_fileno;
212 static VALUE sym_mode, sym_perm, sym_flags, sym_extenc, sym_intenc, sym_encoding, sym_open_args;
213 static VALUE sym_textmode, sym_binmode, sym_autoclose;
214 static VALUE sym_SET, sym_CUR, sym_END;
215 static VALUE sym_wait_readable, sym_wait_writable;
216 #ifdef SEEK_DATA
217 static VALUE sym_DATA;
218 #endif
219 #ifdef SEEK_HOLE
220 static VALUE sym_HOLE;
221 #endif
222 
223 static VALUE prep_io(int fd, int fmode, VALUE klass, const char *path);
224 
225 VALUE
226 rb_io_blocking_region_wait(struct rb_io *io, rb_blocking_function_t *function, void *argument, enum rb_io_event events)
227 {
228  return rb_thread_io_blocking_call(function, argument, io->fd, events);
229 }
230 
231 VALUE rb_io_blocking_region(struct rb_io *io, rb_blocking_function_t *function, void *argument)
232 {
233  return rb_io_blocking_region_wait(io, function, argument, 0);
234 }
235 
236 struct argf {
237  VALUE filename, current_file;
238  long last_lineno; /* $. */
239  long lineno;
240  VALUE argv;
241  VALUE inplace;
242  struct rb_io_encoding encs;
243  int8_t init_p, next_p, binmode;
244 };
245 
246 static rb_atomic_t max_file_descriptor = NOFILE;
247 void
249 {
250  rb_atomic_t afd = (rb_atomic_t)fd;
251  rb_atomic_t max_fd = max_file_descriptor;
252  int err;
253 
254  if (fd < 0 || afd <= max_fd)
255  return;
256 
257 #if defined(HAVE_FCNTL) && defined(F_GETFL)
258  err = fcntl(fd, F_GETFL) == -1;
259 #else
260  {
261  struct stat buf;
262  err = fstat(fd, &buf) != 0;
263  }
264 #endif
265  if (err && errno == EBADF) {
266  rb_bug("rb_update_max_fd: invalid fd (%d) given.", fd);
267  }
268 
269  while (max_fd < afd) {
270  max_fd = ATOMIC_CAS(max_file_descriptor, max_fd, afd);
271  }
272 }
273 
274 void
275 rb_maygvl_fd_fix_cloexec(int fd)
276 {
277  /* MinGW don't have F_GETFD and FD_CLOEXEC. [ruby-core:40281] */
278 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
279  int flags, flags2, ret;
280  flags = fcntl(fd, F_GETFD); /* should not fail except EBADF. */
281  if (flags == -1) {
282  rb_bug("rb_maygvl_fd_fix_cloexec: fcntl(%d, F_GETFD) failed: %s", fd, strerror(errno));
283  }
284  if (fd <= 2)
285  flags2 = flags & ~FD_CLOEXEC; /* Clear CLOEXEC for standard file descriptors: 0, 1, 2. */
286  else
287  flags2 = flags | FD_CLOEXEC; /* Set CLOEXEC for non-standard file descriptors: 3, 4, 5, ... */
288  if (flags != flags2) {
289  ret = fcntl(fd, F_SETFD, flags2);
290  if (ret != 0) {
291  rb_bug("rb_maygvl_fd_fix_cloexec: fcntl(%d, F_SETFD, %d) failed: %s", fd, flags2, strerror(errno));
292  }
293  }
294 #endif
295 }
296 
297 void
299 {
300  rb_maygvl_fd_fix_cloexec(fd);
301  rb_update_max_fd(fd);
302 }
303 
304 /* this is only called once */
305 static int
306 rb_fix_detect_o_cloexec(int fd)
307 {
308 #if defined(O_CLOEXEC) && defined(F_GETFD)
309  int flags = fcntl(fd, F_GETFD);
310 
311  if (flags == -1)
312  rb_bug("rb_fix_detect_o_cloexec: fcntl(%d, F_GETFD) failed: %s", fd, strerror(errno));
313 
314  if (flags & FD_CLOEXEC)
315  return 1;
316 #endif /* fall through if O_CLOEXEC does not work: */
317  rb_maygvl_fd_fix_cloexec(fd);
318  return 0;
319 }
320 
321 static inline bool
322 io_again_p(int e)
323 {
324  return (e == EWOULDBLOCK) || (e == EAGAIN);
325 }
326 
327 int
328 rb_cloexec_open(const char *pathname, int flags, mode_t mode)
329 {
330  int ret;
331  static int o_cloexec_state = -1; /* <0: unknown, 0: ignored, >0: working */
332 
333  static const int retry_interval = 0;
334  static const int retry_max_count = 10000;
335 
336  int retry_count = 0;
337 
338 #ifdef O_CLOEXEC
339  /* O_CLOEXEC is available since Linux 2.6.23. Linux 2.6.18 silently ignore it. */
340  flags |= O_CLOEXEC;
341 #elif defined O_NOINHERIT
342  flags |= O_NOINHERIT;
343 #endif
344 
345  while ((ret = open(pathname, flags, mode)) == -1) {
346  int e = errno;
347  if (!io_again_p(e)) break;
348  if (retry_count++ >= retry_max_count) break;
349 
350  sleep(retry_interval);
351  }
352 
353  if (ret < 0) return ret;
354  if (ret <= 2 || o_cloexec_state == 0) {
355  rb_maygvl_fd_fix_cloexec(ret);
356  }
357  else if (o_cloexec_state > 0) {
358  return ret;
359  }
360  else {
361  o_cloexec_state = rb_fix_detect_o_cloexec(ret);
362  }
363  return ret;
364 }
365 
366 int
367 rb_cloexec_dup(int oldfd)
368 {
369  /* Don't allocate standard file descriptors: 0, 1, 2 */
370  return rb_cloexec_fcntl_dupfd(oldfd, 3);
371 }
372 
373 int
374 rb_cloexec_dup2(int oldfd, int newfd)
375 {
376  int ret;
377 
378  /* When oldfd == newfd, dup2 succeeds but dup3 fails with EINVAL.
379  * rb_cloexec_dup2 succeeds as dup2. */
380  if (oldfd == newfd) {
381  ret = newfd;
382  }
383  else {
384 #if defined(HAVE_DUP3) && defined(O_CLOEXEC)
385  static int try_dup3 = 1;
386  if (2 < newfd && try_dup3) {
387  ret = dup3(oldfd, newfd, O_CLOEXEC);
388  if (ret != -1)
389  return ret;
390  /* dup3 is available since Linux 2.6.27, glibc 2.9. */
391  if (errno == ENOSYS) {
392  try_dup3 = 0;
393  ret = dup2(oldfd, newfd);
394  }
395  }
396  else {
397  ret = dup2(oldfd, newfd);
398  }
399 #else
400  ret = dup2(oldfd, newfd);
401 #endif
402  if (ret < 0) return ret;
403  }
404  rb_maygvl_fd_fix_cloexec(ret);
405  return ret;
406 }
407 
408 static int
409 rb_fd_set_nonblock(int fd)
410 {
411 #ifdef _WIN32
412  return rb_w32_set_nonblock(fd);
413 #elif defined(F_GETFL)
414  int oflags = fcntl(fd, F_GETFL);
415 
416  if (oflags == -1)
417  return -1;
418  if (oflags & O_NONBLOCK)
419  return 0;
420  oflags |= O_NONBLOCK;
421  return fcntl(fd, F_SETFL, oflags);
422 #endif
423  return 0;
424 }
425 
426 int
427 rb_cloexec_pipe(int descriptors[2])
428 {
429 #ifdef HAVE_PIPE2
430  int result = pipe2(descriptors, O_CLOEXEC | O_NONBLOCK);
431 #else
432  int result = pipe(descriptors);
433 #endif
434 
435  if (result < 0)
436  return result;
437 
438 #ifdef __CYGWIN__
439  if (result == 0 && descriptors[1] == -1) {
440  close(descriptors[0]);
441  descriptors[0] = -1;
442  errno = ENFILE;
443  return -1;
444  }
445 #endif
446 
447 #ifndef HAVE_PIPE2
448  rb_maygvl_fd_fix_cloexec(descriptors[0]);
449  rb_maygvl_fd_fix_cloexec(descriptors[1]);
450 
451 #ifndef _WIN32
452  rb_fd_set_nonblock(descriptors[0]);
453  rb_fd_set_nonblock(descriptors[1]);
454 #endif
455 #endif
456 
457  return result;
458 }
459 
460 int
461 rb_cloexec_fcntl_dupfd(int fd, int minfd)
462 {
463  int ret;
464 
465 #if defined(HAVE_FCNTL) && defined(F_DUPFD_CLOEXEC) && defined(F_DUPFD)
466  static int try_dupfd_cloexec = 1;
467  if (try_dupfd_cloexec) {
468  ret = fcntl(fd, F_DUPFD_CLOEXEC, minfd);
469  if (ret != -1) {
470  if (ret <= 2)
471  rb_maygvl_fd_fix_cloexec(ret);
472  return ret;
473  }
474  /* F_DUPFD_CLOEXEC is available since Linux 2.6.24. Linux 2.6.18 fails with EINVAL */
475  if (errno == EINVAL) {
476  ret = fcntl(fd, F_DUPFD, minfd);
477  if (ret != -1) {
478  try_dupfd_cloexec = 0;
479  }
480  }
481  }
482  else {
483  ret = fcntl(fd, F_DUPFD, minfd);
484  }
485 #elif defined(HAVE_FCNTL) && defined(F_DUPFD)
486  ret = fcntl(fd, F_DUPFD, minfd);
487 #else
488  ret = dup(fd);
489  if (ret >= 0 && ret < minfd) {
490  const int prev_fd = ret;
491  ret = rb_cloexec_fcntl_dupfd(fd, minfd);
492  close(prev_fd);
493  }
494  return ret;
495 #endif
496  if (ret < 0) return ret;
497  rb_maygvl_fd_fix_cloexec(ret);
498  return ret;
499 }
500 
501 #define argf_of(obj) (*(struct argf *)DATA_PTR(obj))
502 #define ARGF argf_of(argf)
503 
504 #define GetWriteIO(io) rb_io_get_write_io(io)
505 
506 #define READ_DATA_PENDING(fptr) ((fptr)->rbuf.len)
507 #define READ_DATA_PENDING_COUNT(fptr) ((fptr)->rbuf.len)
508 #define READ_DATA_PENDING_PTR(fptr) ((fptr)->rbuf.ptr+(fptr)->rbuf.off)
509 #define READ_DATA_BUFFERED(fptr) READ_DATA_PENDING(fptr)
510 
511 #define READ_CHAR_PENDING(fptr) ((fptr)->cbuf.len)
512 #define READ_CHAR_PENDING_COUNT(fptr) ((fptr)->cbuf.len)
513 #define READ_CHAR_PENDING_PTR(fptr) ((fptr)->cbuf.ptr+(fptr)->cbuf.off)
514 
515 #if defined(_WIN32)
516 #define WAIT_FD_IN_WIN32(fptr) \
517  (rb_w32_io_cancelable_p((fptr)->fd) ? Qnil : rb_io_wait(fptr->self, RB_INT2NUM(RUBY_IO_READABLE), RUBY_IO_TIMEOUT_DEFAULT))
518 #else
519 #define WAIT_FD_IN_WIN32(fptr)
520 #endif
521 
522 #define READ_CHECK(fptr) do {\
523  if (!READ_DATA_PENDING(fptr)) {\
524  WAIT_FD_IN_WIN32(fptr);\
525  rb_io_check_closed(fptr);\
526  }\
527 } while(0)
528 
529 #ifndef S_ISSOCK
530 # ifdef _S_ISSOCK
531 # define S_ISSOCK(m) _S_ISSOCK(m)
532 # else
533 # ifdef _S_IFSOCK
534 # define S_ISSOCK(m) (((m) & S_IFMT) == _S_IFSOCK)
535 # else
536 # ifdef S_IFSOCK
537 # define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
538 # endif
539 # endif
540 # endif
541 #endif
542 
543 static int io_fflush(rb_io_t *);
544 static rb_io_t *flush_before_seek(rb_io_t *fptr);
545 
546 #define FMODE_SIGNAL_ON_EPIPE (1<<17)
547 
548 #define fptr_signal_on_epipe(fptr) \
549  (((fptr)->mode & FMODE_SIGNAL_ON_EPIPE) != 0)
550 
551 #define fptr_set_signal_on_epipe(fptr, flag) \
552  ((flag) ? \
553  (fptr)->mode |= FMODE_SIGNAL_ON_EPIPE : \
554  (fptr)->mode &= ~FMODE_SIGNAL_ON_EPIPE)
555 
556 extern ID ruby_static_id_signo;
557 
558 NORETURN(static void rb_sys_fail_on_write(rb_io_t *fptr));
559 static void
560 rb_sys_fail_on_write(rb_io_t *fptr)
561 {
562  int e = errno;
563  VALUE errinfo = rb_syserr_new_path(e, (fptr)->pathv);
564 #if defined EPIPE
565  if (fptr_signal_on_epipe(fptr) && (e == EPIPE)) {
566  const VALUE sig =
567 # if defined SIGPIPE
568  INT2FIX(SIGPIPE) - INT2FIX(0) +
569 # endif
570  INT2FIX(0);
571  rb_ivar_set(errinfo, ruby_static_id_signo, sig);
572  }
573 #endif
574  rb_exc_raise(errinfo);
575 }
576 
577 #define NEED_NEWLINE_DECORATOR_ON_READ(fptr) ((fptr)->mode & FMODE_TEXTMODE)
578 #define NEED_NEWLINE_DECORATOR_ON_WRITE(fptr) ((fptr)->mode & FMODE_TEXTMODE)
579 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
580 # define RUBY_CRLF_ENVIRONMENT 1
581 #else
582 # define RUBY_CRLF_ENVIRONMENT 0
583 #endif
584 
585 #if RUBY_CRLF_ENVIRONMENT
586 /* Windows */
587 # define DEFAULT_TEXTMODE FMODE_TEXTMODE
588 # define TEXTMODE_NEWLINE_DECORATOR_ON_WRITE ECONV_CRLF_NEWLINE_DECORATOR
589 /*
590  * CRLF newline is set as default newline decorator.
591  * If only CRLF newline conversion is needed, we use binary IO process
592  * with OS's text mode for IO performance improvement.
593  * If encoding conversion is needed or a user sets text mode, we use encoding
594  * conversion IO process and universal newline decorator by default.
595  */
596 #define NEED_READCONV(fptr) ((fptr)->encs.enc2 != NULL || (fptr)->encs.ecflags & ~ECONV_CRLF_NEWLINE_DECORATOR)
597 #define WRITECONV_MASK ( \
598  (ECONV_DECORATOR_MASK & ~ECONV_CRLF_NEWLINE_DECORATOR)|\
599  ECONV_STATEFUL_DECORATOR_MASK|\
600  0)
601 #define NEED_WRITECONV(fptr) ( \
602  ((fptr)->encs.enc != NULL && (fptr)->encs.enc != rb_ascii8bit_encoding()) || \
603  ((fptr)->encs.ecflags & WRITECONV_MASK) || \
604  0)
605 #define SET_BINARY_MODE(fptr) setmode((fptr)->fd, O_BINARY)
606 
607 #define NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr) do {\
608  if (NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {\
609  if (((fptr)->mode & FMODE_READABLE) &&\
610  !((fptr)->encs.ecflags & ECONV_NEWLINE_DECORATOR_MASK)) {\
611  setmode((fptr)->fd, O_BINARY);\
612  }\
613  else {\
614  setmode((fptr)->fd, O_TEXT);\
615  }\
616  }\
617 } while(0)
618 
619 #define SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags) do {\
620  if ((enc2) && ((ecflags) & ECONV_DEFAULT_NEWLINE_DECORATOR)) {\
621  (ecflags) |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;\
622  }\
623 } while(0)
624 
625 /*
626  * IO unread with taking care of removed '\r' in text mode.
627  */
628 static void
629 io_unread(rb_io_t *fptr)
630 {
631  rb_off_t r, pos;
632  ssize_t read_size;
633  long i;
634  long newlines = 0;
635  long extra_max;
636  char *p;
637  char *buf;
638 
639  rb_io_check_closed(fptr);
640  if (fptr->rbuf.len == 0 || fptr->mode & FMODE_DUPLEX) {
641  return;
642  }
643 
644  errno = 0;
645  if (!rb_w32_fd_is_text(fptr->fd)) {
646  r = lseek(fptr->fd, -fptr->rbuf.len, SEEK_CUR);
647  if (r < 0 && errno) {
648  if (errno == ESPIPE)
649  fptr->mode |= FMODE_DUPLEX;
650  return;
651  }
652 
653  fptr->rbuf.off = 0;
654  fptr->rbuf.len = 0;
655  return;
656  }
657 
658  pos = lseek(fptr->fd, 0, SEEK_CUR);
659  if (pos < 0 && errno) {
660  if (errno == ESPIPE)
661  fptr->mode |= FMODE_DUPLEX;
662  return;
663  }
664 
665  /* add extra offset for removed '\r' in rbuf */
666  extra_max = (long)(pos - fptr->rbuf.len);
667  p = fptr->rbuf.ptr + fptr->rbuf.off;
668 
669  /* if the end of rbuf is '\r', rbuf doesn't have '\r' within rbuf.len */
670  if (*(fptr->rbuf.ptr + fptr->rbuf.capa - 1) == '\r') {
671  newlines++;
672  }
673 
674  for (i = 0; i < fptr->rbuf.len; i++) {
675  if (*p == '\n') newlines++;
676  if (extra_max == newlines) break;
677  p++;
678  }
679 
680  buf = ALLOC_N(char, fptr->rbuf.len + newlines);
681  while (newlines >= 0) {
682  r = lseek(fptr->fd, pos - fptr->rbuf.len - newlines, SEEK_SET);
683  if (newlines == 0) break;
684  if (r < 0) {
685  newlines--;
686  continue;
687  }
688  read_size = _read(fptr->fd, buf, fptr->rbuf.len + newlines);
689  if (read_size < 0) {
690  int e = errno;
691  free(buf);
692  rb_syserr_fail_path(e, fptr->pathv);
693  }
694  if (read_size == fptr->rbuf.len) {
695  lseek(fptr->fd, r, SEEK_SET);
696  break;
697  }
698  else {
699  newlines--;
700  }
701  }
702  free(buf);
703  fptr->rbuf.off = 0;
704  fptr->rbuf.len = 0;
705  return;
706 }
707 
708 /*
709  * We use io_seek to back cursor position when changing mode from text to binary,
710  * but stdin and pipe cannot seek back. Stdin and pipe read should use encoding
711  * conversion for working properly with mode change.
712  *
713  * Return previous translation mode.
714  */
715 static inline int
716 set_binary_mode_with_seek_cur(rb_io_t *fptr)
717 {
718  if (!rb_w32_fd_is_text(fptr->fd)) return O_BINARY;
719 
720  if (fptr->rbuf.len == 0 || fptr->mode & FMODE_DUPLEX) {
721  return setmode(fptr->fd, O_BINARY);
722  }
723  flush_before_seek(fptr);
724  return setmode(fptr->fd, O_BINARY);
725 }
726 #define SET_BINARY_MODE_WITH_SEEK_CUR(fptr) set_binary_mode_with_seek_cur(fptr)
727 
728 #else
729 /* Unix */
730 # define DEFAULT_TEXTMODE 0
731 #define NEED_READCONV(fptr) ((fptr)->encs.enc2 != NULL || NEED_NEWLINE_DECORATOR_ON_READ(fptr))
732 #define NEED_WRITECONV(fptr) ( \
733  ((fptr)->encs.enc != NULL && (fptr)->encs.enc != rb_ascii8bit_encoding()) || \
734  NEED_NEWLINE_DECORATOR_ON_WRITE(fptr) || \
735  ((fptr)->encs.ecflags & (ECONV_DECORATOR_MASK|ECONV_STATEFUL_DECORATOR_MASK)) || \
736  0)
737 #define SET_BINARY_MODE(fptr) (void)(fptr)
738 #define NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr) (void)(fptr)
739 #define SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags) ((void)(enc2), (void)(ecflags))
740 #define SET_BINARY_MODE_WITH_SEEK_CUR(fptr) (void)(fptr)
741 #endif
742 
743 #if !defined HAVE_SHUTDOWN && !defined shutdown
744 #define shutdown(a,b) 0
745 #endif
746 
747 #if defined(_WIN32)
748 #define is_socket(fd, path) rb_w32_is_socket(fd)
749 #elif !defined(S_ISSOCK)
750 #define is_socket(fd, path) 0
751 #else
752 static int
753 is_socket(int fd, VALUE path)
754 {
755  struct stat sbuf;
756  if (fstat(fd, &sbuf) < 0)
757  rb_sys_fail_path(path);
758  return S_ISSOCK(sbuf.st_mode);
759 }
760 #endif
761 
762 static const char closed_stream[] = "closed stream";
763 
764 static void
765 io_fd_check_closed(int fd)
766 {
767  if (fd < 0) {
768  rb_thread_check_ints(); /* check for ruby_error_stream_closed */
769  rb_raise(rb_eIOError, closed_stream);
770  }
771 }
772 
773 void
774 rb_eof_error(void)
775 {
776  rb_raise(rb_eEOFError, "end of file reached");
777 }
778 
779 VALUE
781 {
782  rb_check_frozen(io);
783  return io;
784 }
785 
786 void
788 {
789  if (!fptr) {
790  rb_raise(rb_eIOError, "uninitialized stream");
791  }
792 }
793 
794 void
796 {
798  io_fd_check_closed(fptr->fd);
799 }
800 
801 static rb_io_t *
802 rb_io_get_fptr(VALUE io)
803 {
804  rb_io_t *fptr = RFILE(io)->fptr;
806  return fptr;
807 }
808 
809 VALUE
811 {
812  return rb_convert_type_with_id(io, T_FILE, "IO", idTo_io);
813 }
814 
815 VALUE
817 {
818  return rb_check_convert_type_with_id(io, T_FILE, "IO", idTo_io);
819 }
820 
821 VALUE
823 {
824  VALUE write_io;
825  write_io = rb_io_get_fptr(io)->tied_io_for_writing;
826  if (write_io) {
827  return write_io;
828  }
829  return io;
830 }
831 
832 VALUE
834 {
835  VALUE write_io;
836  rb_io_t *fptr = rb_io_get_fptr(io);
837  if (!RTEST(w)) {
838  w = 0;
839  }
840  else {
841  GetWriteIO(w);
842  }
843  write_io = fptr->tied_io_for_writing;
844  fptr->tied_io_for_writing = w;
845  return write_io ? write_io : Qnil;
846 }
847 
848 /*
849  * call-seq:
850  * timeout -> duration or nil
851  *
852  * Get the internal timeout duration or nil if it was not set.
853  *
854  */
855 VALUE
857 {
858  rb_io_t *fptr = rb_io_get_fptr(self);
859 
860  return fptr->timeout;
861 }
862 
863 /*
864  * call-seq:
865  * timeout = duration -> duration
866  * timeout = nil -> nil
867  *
868  * Sets the internal timeout to the specified duration or nil. The timeout
869  * applies to all blocking operations where possible.
870  *
871  * When the operation performs longer than the timeout set, IO::TimeoutError
872  * is raised.
873  *
874  * This affects the following methods (but is not limited to): #gets, #puts,
875  * #read, #write, #wait_readable and #wait_writable. This also affects
876  * blocking socket operations like Socket#accept and Socket#connect.
877  *
878  * Some operations like File#open and IO#close are not affected by the
879  * timeout. A timeout during a write operation may leave the IO in an
880  * inconsistent state, e.g. data was partially written. Generally speaking, a
881  * timeout is a last ditch effort to prevent an application from hanging on
882  * slow I/O operations, such as those that occur during a slowloris attack.
883  */
884 VALUE
886 {
887  // Validate it:
888  if (RTEST(timeout)) {
889  rb_time_interval(timeout);
890  }
891 
892  rb_io_t *fptr = rb_io_get_fptr(self);
893 
894  fptr->timeout = timeout;
895 
896  return self;
897 }
898 
899 /*
900  * call-seq:
901  * IO.try_convert(object) -> new_io or nil
902  *
903  * Attempts to convert +object+ into an \IO object via method +to_io+;
904  * returns the new \IO object if successful, or +nil+ otherwise:
905  *
906  * IO.try_convert(STDOUT) # => #<IO:<STDOUT>>
907  * IO.try_convert(ARGF) # => #<IO:<STDIN>>
908  * IO.try_convert('STDOUT') # => nil
909  *
910  */
911 static VALUE
912 rb_io_s_try_convert(VALUE dummy, VALUE io)
913 {
914  return rb_io_check_io(io);
915 }
916 
917 #if !RUBY_CRLF_ENVIRONMENT
918 static void
919 io_unread(rb_io_t *fptr)
920 {
921  rb_off_t r;
922  rb_io_check_closed(fptr);
923  if (fptr->rbuf.len == 0 || fptr->mode & FMODE_DUPLEX)
924  return;
925  /* xxx: target position may be negative if buffer is filled by ungetc */
926  errno = 0;
927  r = lseek(fptr->fd, -fptr->rbuf.len, SEEK_CUR);
928  if (r < 0 && errno) {
929  if (errno == ESPIPE)
930  fptr->mode |= FMODE_DUPLEX;
931  return;
932  }
933  fptr->rbuf.off = 0;
934  fptr->rbuf.len = 0;
935  return;
936 }
937 #endif
938 
939 static rb_encoding *io_input_encoding(rb_io_t *fptr);
940 
941 static void
942 io_ungetbyte(VALUE str, rb_io_t *fptr)
943 {
944  long len = RSTRING_LEN(str);
945 
946  if (fptr->rbuf.ptr == NULL) {
947  const int min_capa = IO_RBUF_CAPA_FOR(fptr);
948  fptr->rbuf.off = 0;
949  fptr->rbuf.len = 0;
950 #if SIZEOF_LONG > SIZEOF_INT
951  if (len > INT_MAX)
952  rb_raise(rb_eIOError, "ungetbyte failed");
953 #endif
954  if (len > min_capa)
955  fptr->rbuf.capa = (int)len;
956  else
957  fptr->rbuf.capa = min_capa;
958  fptr->rbuf.ptr = ALLOC_N(char, fptr->rbuf.capa);
959  }
960  if (fptr->rbuf.capa < len + fptr->rbuf.len) {
961  rb_raise(rb_eIOError, "ungetbyte failed");
962  }
963  if (fptr->rbuf.off < len) {
964  MEMMOVE(fptr->rbuf.ptr+fptr->rbuf.capa-fptr->rbuf.len,
965  fptr->rbuf.ptr+fptr->rbuf.off,
966  char, fptr->rbuf.len);
967  fptr->rbuf.off = fptr->rbuf.capa-fptr->rbuf.len;
968  }
969  fptr->rbuf.off-=(int)len;
970  fptr->rbuf.len+=(int)len;
971  MEMMOVE(fptr->rbuf.ptr+fptr->rbuf.off, RSTRING_PTR(str), char, len);
972 }
973 
974 static rb_io_t *
975 flush_before_seek(rb_io_t *fptr)
976 {
977  if (io_fflush(fptr) < 0)
978  rb_sys_fail_on_write(fptr);
979  io_unread(fptr);
980  errno = 0;
981  return fptr;
982 }
983 
984 #define io_seek(fptr, ofs, whence) (errno = 0, lseek(flush_before_seek(fptr)->fd, (ofs), (whence)))
985 #define io_tell(fptr) lseek(flush_before_seek(fptr)->fd, 0, SEEK_CUR)
986 
987 #ifndef SEEK_CUR
988 # define SEEK_SET 0
989 # define SEEK_CUR 1
990 # define SEEK_END 2
991 #endif
992 
993 void
995 {
996  rb_io_check_closed(fptr);
997  if (!(fptr->mode & FMODE_READABLE)) {
998  rb_raise(rb_eIOError, "not opened for reading");
999  }
1000  if (fptr->wbuf.len) {
1001  if (io_fflush(fptr) < 0)
1002  rb_sys_fail_on_write(fptr);
1003  }
1004  if (fptr->tied_io_for_writing) {
1005  rb_io_t *wfptr;
1006  GetOpenFile(fptr->tied_io_for_writing, wfptr);
1007  if (io_fflush(wfptr) < 0)
1008  rb_sys_fail_on_write(wfptr);
1009  }
1010 }
1011 
1012 void
1014 {
1016  if (READ_CHAR_PENDING(fptr)) {
1017  rb_raise(rb_eIOError, "byte oriented read for character buffered IO");
1018  }
1019 }
1020 
1021 void
1023 {
1025 }
1026 
1027 static rb_encoding*
1028 io_read_encoding(rb_io_t *fptr)
1029 {
1030  if (fptr->encs.enc) {
1031  return fptr->encs.enc;
1032  }
1034 }
1035 
1036 static rb_encoding*
1037 io_input_encoding(rb_io_t *fptr)
1038 {
1039  if (fptr->encs.enc2) {
1040  return fptr->encs.enc2;
1041  }
1042  return io_read_encoding(fptr);
1043 }
1044 
1045 void
1047 {
1048  rb_io_check_closed(fptr);
1049  if (!(fptr->mode & FMODE_WRITABLE)) {
1050  rb_raise(rb_eIOError, "not opened for writing");
1051  }
1052  if (fptr->rbuf.len) {
1053  io_unread(fptr);
1054  }
1055 }
1056 
1057 int
1058 rb_io_read_pending(rb_io_t *fptr)
1059 {
1060  /* This function is used for bytes and chars. Confusing. */
1061  if (READ_CHAR_PENDING(fptr))
1062  return 1; /* should raise? */
1063  return READ_DATA_PENDING(fptr);
1064 }
1065 
1066 void
1068 {
1069  if (!READ_DATA_PENDING(fptr)) {
1070  rb_io_wait(fptr->self, RB_INT2NUM(RUBY_IO_READABLE), RUBY_IO_TIMEOUT_DEFAULT);
1071  }
1072  return;
1073 }
1074 
1075 int
1076 rb_gc_for_fd(int err)
1077 {
1078  if (err == EMFILE || err == ENFILE || err == ENOMEM) {
1079  rb_gc();
1080  return 1;
1081  }
1082  return 0;
1083 }
1084 
1085 /* try `expr` upto twice while it returns false and `errno`
1086  * is to GC. Each `errno`s are available as `first_errno` and
1087  * `retried_errno` respectively */
1088 #define TRY_WITH_GC(expr) \
1089  for (int first_errno, retried_errno = 0, retried = 0; \
1090  (!retried && \
1091  !(expr) && \
1092  (!rb_gc_for_fd(first_errno = errno) || !(expr)) && \
1093  (retried_errno = errno, 1)); \
1094  (void)retried_errno, retried = 1)
1095 
1096 static int
1097 ruby_dup(int orig)
1098 {
1099  int fd = -1;
1100 
1101  TRY_WITH_GC((fd = rb_cloexec_dup(orig)) >= 0) {
1102  rb_syserr_fail(first_errno, 0);
1103  }
1104  rb_update_max_fd(fd);
1105  return fd;
1106 }
1107 
1108 static VALUE
1109 io_alloc(VALUE klass)
1110 {
1111  NEWOBJ_OF(io, struct RFile, klass, T_FILE, sizeof(struct RFile), 0);
1112 
1113  io->fptr = 0;
1114 
1115  return (VALUE)io;
1116 }
1117 
1118 #ifndef S_ISREG
1119 # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
1120 #endif
1121 
1123  VALUE th;
1124  rb_io_t *fptr;
1125  int nonblock;
1126  int fd;
1127 
1128  void *buf;
1129  size_t capa;
1130  struct timeval *timeout;
1131 };
1132 
1134  VALUE th;
1135  rb_io_t *fptr;
1136  int nonblock;
1137  int fd;
1138 
1139  const void *buf;
1140  size_t capa;
1141  struct timeval *timeout;
1142 };
1143 
1144 #ifdef HAVE_WRITEV
1145 struct io_internal_writev_struct {
1146  VALUE th;
1147  rb_io_t *fptr;
1148  int nonblock;
1149  int fd;
1150 
1151  int iovcnt;
1152  const struct iovec *iov;
1153  struct timeval *timeout;
1154 };
1155 #endif
1156 
1157 static int nogvl_wait_for(VALUE th, rb_io_t *fptr, short events, struct timeval *timeout);
1158 
1164 static inline int
1165 io_internal_wait(VALUE thread, rb_io_t *fptr, int error, int events, struct timeval *timeout)
1166 {
1167  if (!timeout && rb_thread_mn_schedulable(thread)) {
1168  RUBY_ASSERT(errno == EWOULDBLOCK || errno == EAGAIN);
1169  return -1;
1170  }
1171 
1172  int ready = nogvl_wait_for(thread, fptr, events, timeout);
1173 
1174  if (ready > 0) {
1175  return ready;
1176  }
1177  else if (ready == 0) {
1178  errno = ETIMEDOUT;
1179  return -1;
1180  }
1181 
1182  errno = error;
1183  return -1;
1184 }
1185 
1186 static VALUE
1187 internal_read_func(void *ptr)
1188 {
1189  struct io_internal_read_struct *iis = ptr;
1190  ssize_t result;
1191 
1192  if (iis->timeout && !iis->nonblock) {
1193  if (io_internal_wait(iis->th, iis->fptr, 0, RB_WAITFD_IN, iis->timeout) == -1) {
1194  return -1;
1195  }
1196  }
1197 
1198  retry:
1199  result = read(iis->fd, iis->buf, iis->capa);
1200 
1201  if (result < 0 && !iis->nonblock) {
1202  if (io_again_p(errno)) {
1203  if (io_internal_wait(iis->th, iis->fptr, errno, RB_WAITFD_IN, iis->timeout) == -1) {
1204  return -1;
1205  }
1206  else {
1207  goto retry;
1208  }
1209  }
1210  }
1211 
1212  return result;
1213 }
1214 
1215 #if defined __APPLE__
1216 # define do_write_retry(code) do {result = code;} while (result == -1 && errno == EPROTOTYPE)
1217 #else
1218 # define do_write_retry(code) result = code
1219 #endif
1220 
1221 static VALUE
1222 internal_write_func(void *ptr)
1223 {
1224  struct io_internal_write_struct *iis = ptr;
1225  ssize_t result;
1226 
1227  if (iis->timeout && !iis->nonblock) {
1228  if (io_internal_wait(iis->th, iis->fptr, 0, RB_WAITFD_OUT, iis->timeout) == -1) {
1229  return -1;
1230  }
1231  }
1232 
1233  retry:
1234  do_write_retry(write(iis->fd, iis->buf, iis->capa));
1235 
1236  if (result < 0 && !iis->nonblock) {
1237  int e = errno;
1238  if (io_again_p(e)) {
1239  if (io_internal_wait(iis->th, iis->fptr, errno, RB_WAITFD_OUT, iis->timeout) == -1) {
1240  return -1;
1241  }
1242  else {
1243  goto retry;
1244  }
1245  }
1246  }
1247 
1248  return result;
1249 }
1250 
1251 #ifdef HAVE_WRITEV
1252 static VALUE
1253 internal_writev_func(void *ptr)
1254 {
1255  struct io_internal_writev_struct *iis = ptr;
1256  ssize_t result;
1257 
1258  if (iis->timeout && !iis->nonblock) {
1259  if (io_internal_wait(iis->th, iis->fptr, 0, RB_WAITFD_OUT, iis->timeout) == -1) {
1260  return -1;
1261  }
1262  }
1263 
1264  retry:
1265  do_write_retry(writev(iis->fd, iis->iov, iis->iovcnt));
1266 
1267  if (result < 0 && !iis->nonblock) {
1268  if (io_again_p(errno)) {
1269  if (io_internal_wait(iis->th, iis->fptr, errno, RB_WAITFD_OUT, iis->timeout) == -1) {
1270  return -1;
1271  }
1272  else {
1273  goto retry;
1274  }
1275  }
1276  }
1277 
1278  return result;
1279 }
1280 #endif
1281 
1282 static ssize_t
1283 rb_io_read_memory(rb_io_t *fptr, void *buf, size_t count)
1284 {
1285  VALUE scheduler = rb_fiber_scheduler_current();
1286  if (scheduler != Qnil) {
1287  VALUE result = rb_fiber_scheduler_io_read_memory(scheduler, fptr->self, buf, count, 0);
1288 
1289  if (!UNDEF_P(result)) {
1290  return rb_fiber_scheduler_io_result_apply(result);
1291  }
1292  }
1293 
1294  struct io_internal_read_struct iis = {
1295  .th = rb_thread_current(),
1296  .fptr = fptr,
1297  .nonblock = 0,
1298  .fd = fptr->fd,
1299 
1300  .buf = buf,
1301  .capa = count,
1302  .timeout = NULL,
1303  };
1304 
1305  struct timeval timeout_storage;
1306 
1307  if (fptr->timeout != Qnil) {
1308  timeout_storage = rb_time_interval(fptr->timeout);
1309  iis.timeout = &timeout_storage;
1310  }
1311 
1312  return (ssize_t)rb_io_blocking_region_wait(fptr, internal_read_func, &iis, RUBY_IO_READABLE);
1313 }
1314 
1315 static ssize_t
1316 rb_io_write_memory(rb_io_t *fptr, const void *buf, size_t count)
1317 {
1318  VALUE scheduler = rb_fiber_scheduler_current();
1319  if (scheduler != Qnil) {
1320  VALUE result = rb_fiber_scheduler_io_write_memory(scheduler, fptr->self, buf, count, 0);
1321 
1322  if (!UNDEF_P(result)) {
1323  return rb_fiber_scheduler_io_result_apply(result);
1324  }
1325  }
1326 
1327  struct io_internal_write_struct iis = {
1328  .th = rb_thread_current(),
1329  .fptr = fptr,
1330  .nonblock = 0,
1331  .fd = fptr->fd,
1332 
1333  .buf = buf,
1334  .capa = count,
1335  .timeout = NULL
1336  };
1337 
1338  struct timeval timeout_storage;
1339 
1340  if (fptr->timeout != Qnil) {
1341  timeout_storage = rb_time_interval(fptr->timeout);
1342  iis.timeout = &timeout_storage;
1343  }
1344 
1345  return (ssize_t)rb_io_blocking_region_wait(fptr, internal_write_func, &iis, RUBY_IO_WRITABLE);
1346 }
1347 
1348 #ifdef HAVE_WRITEV
1349 static ssize_t
1350 rb_writev_internal(rb_io_t *fptr, const struct iovec *iov, int iovcnt)
1351 {
1352  if (!iovcnt) return 0;
1353 
1354  VALUE scheduler = rb_fiber_scheduler_current();
1355  if (scheduler != Qnil) {
1356  // This path assumes at least one `iov`:
1357  VALUE result = rb_fiber_scheduler_io_write_memory(scheduler, fptr->self, iov[0].iov_base, iov[0].iov_len, 0);
1358 
1359  if (!UNDEF_P(result)) {
1360  return rb_fiber_scheduler_io_result_apply(result);
1361  }
1362  }
1363 
1364  struct io_internal_writev_struct iis = {
1365  .th = rb_thread_current(),
1366  .fptr = fptr,
1367  .nonblock = 0,
1368  .fd = fptr->fd,
1369 
1370  .iov = iov,
1371  .iovcnt = iovcnt,
1372  .timeout = NULL
1373  };
1374 
1375  struct timeval timeout_storage;
1376 
1377  if (fptr->timeout != Qnil) {
1378  timeout_storage = rb_time_interval(fptr->timeout);
1379  iis.timeout = &timeout_storage;
1380  }
1381 
1382  return (ssize_t)rb_io_blocking_region_wait(fptr, internal_writev_func, &iis, RUBY_IO_WRITABLE);
1383 }
1384 #endif
1385 
1386 static VALUE
1387 io_flush_buffer_sync(void *arg)
1388 {
1389  rb_io_t *fptr = arg;
1390  long l = fptr->wbuf.len;
1391  ssize_t r = write(fptr->fd, fptr->wbuf.ptr+fptr->wbuf.off, (size_t)l);
1392 
1393  if (fptr->wbuf.len <= r) {
1394  fptr->wbuf.off = 0;
1395  fptr->wbuf.len = 0;
1396  return 0;
1397  }
1398 
1399  if (0 <= r) {
1400  fptr->wbuf.off += (int)r;
1401  fptr->wbuf.len -= (int)r;
1402  errno = EAGAIN;
1403  }
1404 
1405  return (VALUE)-1;
1406 }
1407 
1408 static VALUE
1409 io_flush_buffer_async(VALUE arg)
1410 {
1411  rb_io_t *fptr = (rb_io_t *)arg;
1412  return rb_io_blocking_region_wait(fptr, io_flush_buffer_sync, fptr, RUBY_IO_WRITABLE);
1413 }
1414 
1415 static inline int
1416 io_flush_buffer(rb_io_t *fptr)
1417 {
1418  if (!NIL_P(fptr->write_lock) && rb_mutex_owned_p(fptr->write_lock)) {
1419  return (int)io_flush_buffer_async((VALUE)fptr);
1420  }
1421  else {
1422  return (int)rb_mutex_synchronize(fptr->write_lock, io_flush_buffer_async, (VALUE)fptr);
1423  }
1424 }
1425 
1426 static int
1427 io_fflush(rb_io_t *fptr)
1428 {
1429  rb_io_check_closed(fptr);
1430 
1431  if (fptr->wbuf.len == 0)
1432  return 0;
1433 
1434  while (fptr->wbuf.len > 0 && io_flush_buffer(fptr) != 0) {
1435  if (!rb_io_maybe_wait_writable(errno, fptr->self, RUBY_IO_TIMEOUT_DEFAULT))
1436  return -1;
1437 
1438  rb_io_check_closed(fptr);
1439  }
1440 
1441  return 0;
1442 }
1443 
1444 VALUE
1445 rb_io_wait(VALUE io, VALUE events, VALUE timeout)
1446 {
1447  VALUE scheduler = rb_fiber_scheduler_current();
1448 
1449  if (scheduler != Qnil) {
1450  return rb_fiber_scheduler_io_wait(scheduler, io, events, timeout);
1451  }
1452 
1453  rb_io_t * fptr = NULL;
1454  RB_IO_POINTER(io, fptr);
1455 
1456  struct timeval tv_storage;
1457  struct timeval *tv = NULL;
1458 
1459  if (NIL_OR_UNDEF_P(timeout)) {
1460  timeout = fptr->timeout;
1461  }
1462 
1463  if (timeout != Qnil) {
1464  tv_storage = rb_time_interval(timeout);
1465  tv = &tv_storage;
1466  }
1467 
1468  int ready = rb_thread_wait_for_single_fd(fptr->fd, RB_NUM2INT(events), tv);
1469 
1470  if (ready < 0) {
1471  rb_sys_fail(0);
1472  }
1473 
1474  // Not sure if this is necessary:
1475  rb_io_check_closed(fptr);
1476 
1477  if (ready) {
1478  return RB_INT2NUM(ready);
1479  }
1480  else {
1481  return Qfalse;
1482  }
1483 }
1484 
1485 static VALUE
1486 io_from_fd(int fd)
1487 {
1488  return prep_io(fd, FMODE_EXTERNAL, rb_cIO, NULL);
1489 }
1490 
1491 static int
1492 io_wait_for_single_fd(int fd, int events, struct timeval *timeout)
1493 {
1494  VALUE scheduler = rb_fiber_scheduler_current();
1495 
1496  if (scheduler != Qnil) {
1497  return RTEST(
1498  rb_fiber_scheduler_io_wait(scheduler, io_from_fd(fd), RB_INT2NUM(events), rb_fiber_scheduler_make_timeout(timeout))
1499  );
1500  }
1501 
1502  return rb_thread_wait_for_single_fd(fd, events, timeout);
1503 }
1504 
1505 int
1507 {
1508  io_fd_check_closed(f);
1509 
1510  VALUE scheduler = rb_fiber_scheduler_current();
1511 
1512  switch (errno) {
1513  case EINTR:
1514 #if defined(ERESTART)
1515  case ERESTART:
1516 #endif
1518  return TRUE;
1519 
1520  case EAGAIN:
1521 #if EWOULDBLOCK != EAGAIN
1522  case EWOULDBLOCK:
1523 #endif
1524  if (scheduler != Qnil) {
1525  return RTEST(
1526  rb_fiber_scheduler_io_wait_readable(scheduler, io_from_fd(f))
1527  );
1528  }
1529  else {
1530  io_wait_for_single_fd(f, RUBY_IO_READABLE, NULL);
1531  }
1532  return TRUE;
1533 
1534  default:
1535  return FALSE;
1536  }
1537 }
1538 
1539 int
1541 {
1542  io_fd_check_closed(f);
1543 
1544  VALUE scheduler = rb_fiber_scheduler_current();
1545 
1546  switch (errno) {
1547  case EINTR:
1548 #if defined(ERESTART)
1549  case ERESTART:
1550 #endif
1551  /*
1552  * In old Linux, several special files under /proc and /sys don't handle
1553  * select properly. Thus we need avoid to call if don't use O_NONBLOCK.
1554  * Otherwise, we face nasty hang up. Sigh.
1555  * e.g. https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=31b07093c44a7a442394d44423e21d783f5523b8
1556  * https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=31b07093c44a7a442394d44423e21d783f5523b8
1557  * In EINTR case, we only need to call RUBY_VM_CHECK_INTS_BLOCKING().
1558  * Then rb_thread_check_ints() is enough.
1559  */
1561  return TRUE;
1562 
1563  case EAGAIN:
1564 #if EWOULDBLOCK != EAGAIN
1565  case EWOULDBLOCK:
1566 #endif
1567  if (scheduler != Qnil) {
1568  return RTEST(
1569  rb_fiber_scheduler_io_wait_writable(scheduler, io_from_fd(f))
1570  );
1571  }
1572  else {
1573  io_wait_for_single_fd(f, RUBY_IO_WRITABLE, NULL);
1574  }
1575  return TRUE;
1576 
1577  default:
1578  return FALSE;
1579  }
1580 }
1581 
1582 int
1583 rb_wait_for_single_fd(int fd, int events, struct timeval *timeout)
1584 {
1585  return io_wait_for_single_fd(fd, events, timeout);
1586 }
1587 
1588 int
1590 {
1591  return rb_wait_for_single_fd(fd, RUBY_IO_READABLE, NULL);
1592 }
1593 
1594 int
1596 {
1597  return rb_wait_for_single_fd(fd, RUBY_IO_WRITABLE, NULL);
1598 }
1599 
1600 VALUE
1601 rb_io_maybe_wait(int error, VALUE io, VALUE events, VALUE timeout)
1602 {
1603  // fptr->fd can be set to -1 at any time by another thread when the GVL is
1604  // released. Many code, e.g. `io_bufread` didn't check this correctly and
1605  // instead relies on `read(-1) -> -1` which causes this code path. We then
1606  // check here whether the IO was in fact closed. Probably it's better to
1607  // check that `fptr->fd != -1` before using it in syscall.
1608  rb_io_check_closed(RFILE(io)->fptr);
1609 
1610  switch (error) {
1611  // In old Linux, several special files under /proc and /sys don't handle
1612  // select properly. Thus we need avoid to call if don't use O_NONBLOCK.
1613  // Otherwise, we face nasty hang up. Sigh.
1614  // e.g. https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=31b07093c44a7a442394d44423e21d783f5523b8
1615  // https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=31b07093c44a7a442394d44423e21d783f5523b8
1616  // In EINTR case, we only need to call RUBY_VM_CHECK_INTS_BLOCKING().
1617  // Then rb_thread_check_ints() is enough.
1618  case EINTR:
1619 #if defined(ERESTART)
1620  case ERESTART:
1621 #endif
1622  // We might have pending interrupts since the previous syscall was interrupted:
1624 
1625  // The operation was interrupted, so retry it immediately:
1626  return events;
1627 
1628  case EAGAIN:
1629 #if EWOULDBLOCK != EAGAIN
1630  case EWOULDBLOCK:
1631 #endif
1632  // The operation would block, so wait for the specified events:
1633  return rb_io_wait(io, events, timeout);
1634 
1635  default:
1636  // Non-specific error, no event is ready:
1637  return Qnil;
1638  }
1639 }
1640 
1641 int
1642 rb_io_maybe_wait_readable(int error, VALUE io, VALUE timeout)
1643 {
1644  VALUE result = rb_io_maybe_wait(error, io, RB_INT2NUM(RUBY_IO_READABLE), timeout);
1645 
1646  if (RTEST(result)) {
1647  return RB_NUM2INT(result);
1648  }
1649  else if (result == RUBY_Qfalse) {
1650  rb_raise(rb_eIOTimeoutError, "Timed out waiting for IO to become readable!");
1651  }
1652 
1653  return 0;
1654 }
1655 
1656 int
1657 rb_io_maybe_wait_writable(int error, VALUE io, VALUE timeout)
1658 {
1659  VALUE result = rb_io_maybe_wait(error, io, RB_INT2NUM(RUBY_IO_WRITABLE), timeout);
1660 
1661  if (RTEST(result)) {
1662  return RB_NUM2INT(result);
1663  }
1664  else if (result == RUBY_Qfalse) {
1665  rb_raise(rb_eIOTimeoutError, "Timed out waiting for IO to become writable!");
1666  }
1667 
1668  return 0;
1669 }
1670 
1671 static void
1672 make_writeconv(rb_io_t *fptr)
1673 {
1674  if (!fptr->writeconv_initialized) {
1675  const char *senc, *denc;
1676  rb_encoding *enc;
1677  int ecflags;
1678  VALUE ecopts;
1679 
1680  fptr->writeconv_initialized = 1;
1681 
1682  ecflags = fptr->encs.ecflags & ~ECONV_NEWLINE_DECORATOR_READ_MASK;
1683  ecopts = fptr->encs.ecopts;
1684 
1685  if (!fptr->encs.enc || (rb_is_ascii8bit_enc(fptr->encs.enc) && !fptr->encs.enc2)) {
1686  /* no encoding conversion */
1687  fptr->writeconv_pre_ecflags = 0;
1688  fptr->writeconv_pre_ecopts = Qnil;
1689  fptr->writeconv = rb_econv_open_opts("", "", ecflags, ecopts);
1690  if (!fptr->writeconv)
1691  rb_exc_raise(rb_econv_open_exc("", "", ecflags));
1692  fptr->writeconv_asciicompat = Qnil;
1693  }
1694  else {
1695  enc = fptr->encs.enc2 ? fptr->encs.enc2 : fptr->encs.enc;
1697  if (!senc && !(fptr->encs.ecflags & ECONV_STATEFUL_DECORATOR_MASK)) {
1698  /* single conversion */
1699  fptr->writeconv_pre_ecflags = ecflags;
1700  fptr->writeconv_pre_ecopts = ecopts;
1701  fptr->writeconv = NULL;
1702  fptr->writeconv_asciicompat = Qnil;
1703  }
1704  else {
1705  /* double conversion */
1707  fptr->writeconv_pre_ecopts = ecopts;
1708  if (senc) {
1709  denc = rb_enc_name(enc);
1710  fptr->writeconv_asciicompat = rb_str_new2(senc);
1711  }
1712  else {
1713  senc = denc = "";
1715  }
1717  ecopts = fptr->encs.ecopts;
1718  fptr->writeconv = rb_econv_open_opts(senc, denc, ecflags, ecopts);
1719  if (!fptr->writeconv)
1720  rb_exc_raise(rb_econv_open_exc(senc, denc, ecflags));
1721  }
1722  }
1723  }
1724 }
1725 
1726 /* writing functions */
1728  rb_io_t *fptr;
1729  const char *ptr;
1730  long length;
1731 };
1732 
1733 struct write_arg {
1734  VALUE io;
1735  VALUE str;
1736  int nosync;
1737 };
1738 
1739 #ifdef HAVE_WRITEV
1740 static ssize_t
1741 io_binwrite_string_internal(rb_io_t *fptr, const char *ptr, long length)
1742 {
1743  if (fptr->wbuf.len) {
1744  struct iovec iov[2];
1745 
1746  iov[0].iov_base = fptr->wbuf.ptr+fptr->wbuf.off;
1747  iov[0].iov_len = fptr->wbuf.len;
1748  iov[1].iov_base = (void*)ptr;
1749  iov[1].iov_len = length;
1750 
1751  ssize_t result = rb_writev_internal(fptr, iov, 2);
1752 
1753  if (result < 0)
1754  return result;
1755 
1756  if (result >= fptr->wbuf.len) {
1757  // We wrote more than the internal buffer:
1758  result -= fptr->wbuf.len;
1759  fptr->wbuf.off = 0;
1760  fptr->wbuf.len = 0;
1761  }
1762  else {
1763  // We only wrote less data than the internal buffer:
1764  fptr->wbuf.off += (int)result;
1765  fptr->wbuf.len -= (int)result;
1766 
1767  result = 0;
1768  }
1769 
1770  return result;
1771  }
1772  else {
1773  return rb_io_write_memory(fptr, ptr, length);
1774  }
1775 }
1776 #else
1777 static ssize_t
1778 io_binwrite_string_internal(rb_io_t *fptr, const char *ptr, long length)
1779 {
1780  long remaining = length;
1781 
1782  if (fptr->wbuf.len) {
1783  if (fptr->wbuf.len+length <= fptr->wbuf.capa) {
1784  if (fptr->wbuf.capa < fptr->wbuf.off+fptr->wbuf.len+length) {
1785  MEMMOVE(fptr->wbuf.ptr, fptr->wbuf.ptr+fptr->wbuf.off, char, fptr->wbuf.len);
1786  fptr->wbuf.off = 0;
1787  }
1788 
1789  MEMMOVE(fptr->wbuf.ptr+fptr->wbuf.off+fptr->wbuf.len, ptr, char, length);
1790  fptr->wbuf.len += (int)length;
1791 
1792  // We copied the entire incoming data to the internal buffer:
1793  remaining = 0;
1794  }
1795 
1796  // Flush the internal buffer:
1797  if (io_fflush(fptr) < 0) {
1798  return -1;
1799  }
1800 
1801  // If all the data was buffered, we are done:
1802  if (remaining == 0) {
1803  return length;
1804  }
1805  }
1806 
1807  // Otherwise, we should write the data directly:
1808  return rb_io_write_memory(fptr, ptr, length);
1809 }
1810 #endif
1811 
1812 static VALUE
1813 io_binwrite_string(VALUE arg)
1814 {
1815  struct binwrite_arg *p = (struct binwrite_arg *)arg;
1816 
1817  const char *ptr = p->ptr;
1818  size_t remaining = p->length;
1819 
1820  while (remaining) {
1821  // Write as much as possible:
1822  ssize_t result = io_binwrite_string_internal(p->fptr, ptr, remaining);
1823 
1824  if (result == 0) {
1825  // If only the internal buffer is written, result will be zero [bytes of given data written]. This means we
1826  // should try again immediately.
1827  }
1828  else if (result > 0) {
1829  if ((size_t)result == remaining) break;
1830  ptr += result;
1831  remaining -= result;
1832  }
1833  // Wait for it to become writable:
1834  else if (rb_io_maybe_wait_writable(errno, p->fptr->self, RUBY_IO_TIMEOUT_DEFAULT)) {
1835  rb_io_check_closed(p->fptr);
1836  }
1837  else {
1838  // The error was unrelated to waiting for it to become writable, so we fail:
1839  return -1;
1840  }
1841  }
1842 
1843  return p->length;
1844 }
1845 
1846 inline static void
1847 io_allocate_write_buffer(rb_io_t *fptr, int sync)
1848 {
1849  if (fptr->wbuf.ptr == NULL && !(sync && (fptr->mode & FMODE_SYNC))) {
1850  fptr->wbuf.off = 0;
1851  fptr->wbuf.len = 0;
1852  fptr->wbuf.capa = IO_WBUF_CAPA_MIN;
1853  fptr->wbuf.ptr = ALLOC_N(char, fptr->wbuf.capa);
1854  }
1855 
1856  if (NIL_P(fptr->write_lock)) {
1857  fptr->write_lock = rb_mutex_new();
1858  rb_mutex_allow_trap(fptr->write_lock, 1);
1859  }
1860 }
1861 
1862 static inline int
1863 io_binwrite_requires_flush_write(rb_io_t *fptr, long len, int nosync)
1864 {
1865  // If the requested operation was synchronous and the output mode is synchronous or a TTY:
1866  if (!nosync && (fptr->mode & (FMODE_SYNC|FMODE_TTY)))
1867  return 1;
1868 
1869  // If the amount of data we want to write exceeds the internal buffer:
1870  if (fptr->wbuf.ptr && fptr->wbuf.capa <= fptr->wbuf.len + len)
1871  return 1;
1872 
1873  // Otherwise, we can append to the internal buffer:
1874  return 0;
1875 }
1876 
1877 static long
1878 io_binwrite(const char *ptr, long len, rb_io_t *fptr, int nosync)
1879 {
1880  if (len <= 0) return len;
1881 
1882  // Don't write anything if current thread has a pending interrupt:
1884 
1885  io_allocate_write_buffer(fptr, !nosync);
1886 
1887  if (io_binwrite_requires_flush_write(fptr, len, nosync)) {
1888  struct binwrite_arg arg;
1889 
1890  arg.fptr = fptr;
1891  arg.ptr = ptr;
1892  arg.length = len;
1893 
1894  if (!NIL_P(fptr->write_lock)) {
1895  return rb_mutex_synchronize(fptr->write_lock, io_binwrite_string, (VALUE)&arg);
1896  }
1897  else {
1898  return io_binwrite_string((VALUE)&arg);
1899  }
1900  }
1901  else {
1902  if (fptr->wbuf.off) {
1903  if (fptr->wbuf.len)
1904  MEMMOVE(fptr->wbuf.ptr, fptr->wbuf.ptr+fptr->wbuf.off, char, fptr->wbuf.len);
1905  fptr->wbuf.off = 0;
1906  }
1907 
1908  MEMMOVE(fptr->wbuf.ptr+fptr->wbuf.off+fptr->wbuf.len, ptr, char, len);
1909  fptr->wbuf.len += (int)len;
1910 
1911  return len;
1912  }
1913 }
1914 
1915 # define MODE_BTMODE(a,b,c) ((fmode & FMODE_BINMODE) ? (b) : \
1916  (fmode & FMODE_TEXTMODE) ? (c) : (a))
1917 
1918 #define MODE_BTXMODE(a, b, c, d, e, f) ((fmode & FMODE_EXCL) ? \
1919  MODE_BTMODE(d, e, f) : \
1920  MODE_BTMODE(a, b, c))
1921 
1922 static VALUE
1923 do_writeconv(VALUE str, rb_io_t *fptr, int *converted)
1924 {
1925  if (NEED_WRITECONV(fptr)) {
1926  VALUE common_encoding = Qnil;
1927  SET_BINARY_MODE(fptr);
1928 
1929  make_writeconv(fptr);
1930 
1931  if (fptr->writeconv) {
1932 #define fmode (fptr->mode)
1933  if (!NIL_P(fptr->writeconv_asciicompat))
1934  common_encoding = fptr->writeconv_asciicompat;
1935  else if (MODE_BTMODE(DEFAULT_TEXTMODE,0,1) && !rb_enc_asciicompat(rb_enc_get(str))) {
1936  rb_raise(rb_eArgError, "ASCII incompatible string written for text mode IO without encoding conversion: %s",
1937  rb_enc_name(rb_enc_get(str)));
1938  }
1939 #undef fmode
1940  }
1941  else {
1942  if (fptr->encs.enc2)
1943  common_encoding = rb_enc_from_encoding(fptr->encs.enc2);
1944  else if (fptr->encs.enc != rb_ascii8bit_encoding())
1945  common_encoding = rb_enc_from_encoding(fptr->encs.enc);
1946  }
1947 
1948  if (!NIL_P(common_encoding)) {
1949  str = rb_str_encode(str, common_encoding,
1951  *converted = 1;
1952  }
1953 
1954  if (fptr->writeconv) {
1956  *converted = 1;
1957  }
1958  }
1959 #if RUBY_CRLF_ENVIRONMENT
1960 #define fmode (fptr->mode)
1961  else if (MODE_BTMODE(DEFAULT_TEXTMODE,0,1)) {
1962  if ((fptr->mode & FMODE_READABLE) &&
1964  setmode(fptr->fd, O_BINARY);
1965  }
1966  else {
1967  setmode(fptr->fd, O_TEXT);
1968  }
1969  if (!rb_enc_asciicompat(rb_enc_get(str))) {
1970  rb_raise(rb_eArgError, "ASCII incompatible string written for text mode IO without encoding conversion: %s",
1971  rb_enc_name(rb_enc_get(str)));
1972  }
1973  }
1974 #undef fmode
1975 #endif
1976  return str;
1977 }
1978 
1979 static long
1980 io_fwrite(VALUE str, rb_io_t *fptr, int nosync)
1981 {
1982  int converted = 0;
1983  VALUE tmp;
1984  long n, len;
1985  const char *ptr;
1986 
1987 #ifdef _WIN32
1988  if (fptr->mode & FMODE_TTY) {
1989  long len = rb_w32_write_console(str, fptr->fd);
1990  if (len > 0) return len;
1991  }
1992 #endif
1993 
1994  str = do_writeconv(str, fptr, &converted);
1995  if (converted)
1996  OBJ_FREEZE(str);
1997 
1998  tmp = rb_str_tmp_frozen_no_embed_acquire(str);
1999  RSTRING_GETMEM(tmp, ptr, len);
2000  n = io_binwrite(ptr, len, fptr, nosync);
2001  rb_str_tmp_frozen_release(str, tmp);
2002 
2003  return n;
2004 }
2005 
2006 ssize_t
2007 rb_io_bufwrite(VALUE io, const void *buf, size_t size)
2008 {
2009  rb_io_t *fptr;
2010 
2011  GetOpenFile(io, fptr);
2012  rb_io_check_writable(fptr);
2013  return (ssize_t)io_binwrite(buf, (long)size, fptr, 0);
2014 }
2015 
2016 static VALUE
2017 io_write(VALUE io, VALUE str, int nosync)
2018 {
2019  rb_io_t *fptr;
2020  long n;
2021  VALUE tmp;
2022 
2023  io = GetWriteIO(io);
2024  str = rb_obj_as_string(str);
2025  tmp = rb_io_check_io(io);
2026 
2027  if (NIL_P(tmp)) {
2028  /* port is not IO, call write method for it. */
2029  return rb_funcall(io, id_write, 1, str);
2030  }
2031 
2032  io = tmp;
2033  if (RSTRING_LEN(str) == 0) return INT2FIX(0);
2034 
2035  GetOpenFile(io, fptr);
2036  rb_io_check_writable(fptr);
2037 
2038  n = io_fwrite(str, fptr, nosync);
2039  if (n < 0L) rb_sys_fail_on_write(fptr);
2040 
2041  return LONG2FIX(n);
2042 }
2043 
2044 #ifdef HAVE_WRITEV
2045 struct binwritev_arg {
2046  rb_io_t *fptr;
2047  struct iovec *iov;
2048  int iovcnt;
2049  size_t total;
2050 };
2051 
2052 static VALUE
2053 io_binwritev_internal(VALUE arg)
2054 {
2055  struct binwritev_arg *p = (struct binwritev_arg *)arg;
2056 
2057  size_t remaining = p->total;
2058  size_t offset = 0;
2059 
2060  rb_io_t *fptr = p->fptr;
2061  struct iovec *iov = p->iov;
2062  int iovcnt = p->iovcnt;
2063 
2064  while (remaining) {
2065  long result = rb_writev_internal(fptr, iov, iovcnt);
2066 
2067  if (result >= 0) {
2068  offset += result;
2069  if (fptr->wbuf.ptr && fptr->wbuf.len) {
2070  if (offset < (size_t)fptr->wbuf.len) {
2071  fptr->wbuf.off += result;
2072  fptr->wbuf.len -= result;
2073  }
2074  else {
2075  offset -= (size_t)fptr->wbuf.len;
2076  fptr->wbuf.off = 0;
2077  fptr->wbuf.len = 0;
2078  }
2079  }
2080 
2081  if (offset == p->total) {
2082  return p->total;
2083  }
2084 
2085  while (result >= (ssize_t)iov->iov_len) {
2086  /* iovcnt > 0 */
2087  result -= iov->iov_len;
2088  iov->iov_len = 0;
2089  iov++;
2090 
2091  if (!--iovcnt) {
2092  // I don't believe this code path can ever occur.
2093  return offset;
2094  }
2095  }
2096 
2097  iov->iov_base = (char *)iov->iov_base + result;
2098  iov->iov_len -= result;
2099  }
2100  else if (rb_io_maybe_wait_writable(errno, fptr->self, RUBY_IO_TIMEOUT_DEFAULT)) {
2101  rb_io_check_closed(fptr);
2102  }
2103  else {
2104  return -1;
2105  }
2106  }
2107 
2108  return offset;
2109 }
2110 
2111 static long
2112 io_binwritev(struct iovec *iov, int iovcnt, rb_io_t *fptr)
2113 {
2114  // Don't write anything if current thread has a pending interrupt:
2116 
2117  if (iovcnt == 0) return 0;
2118 
2119  size_t total = 0;
2120  for (int i = 1; i < iovcnt; i++) total += iov[i].iov_len;
2121 
2122  io_allocate_write_buffer(fptr, 1);
2123 
2124  if (fptr->wbuf.ptr && fptr->wbuf.len) {
2125  // The end of the buffered data:
2126  size_t offset = fptr->wbuf.off + fptr->wbuf.len;
2127 
2128  if (offset + total <= (size_t)fptr->wbuf.capa) {
2129  for (int i = 1; i < iovcnt; i++) {
2130  memcpy(fptr->wbuf.ptr+offset, iov[i].iov_base, iov[i].iov_len);
2131  offset += iov[i].iov_len;
2132  }
2133 
2134  fptr->wbuf.len += total;
2135 
2136  return total;
2137  }
2138  else {
2139  iov[0].iov_base = fptr->wbuf.ptr + fptr->wbuf.off;
2140  iov[0].iov_len = fptr->wbuf.len;
2141  }
2142  }
2143  else {
2144  // The first iov is reserved for the internal buffer, and it's empty.
2145  iov++;
2146 
2147  if (!--iovcnt) {
2148  // If there are no other io vectors we are done.
2149  return 0;
2150  }
2151  }
2152 
2153  struct binwritev_arg arg;
2154  arg.fptr = fptr;
2155  arg.iov = iov;
2156  arg.iovcnt = iovcnt;
2157  arg.total = total;
2158 
2159  if (!NIL_P(fptr->write_lock)) {
2160  return rb_mutex_synchronize(fptr->write_lock, io_binwritev_internal, (VALUE)&arg);
2161  }
2162  else {
2163  return io_binwritev_internal((VALUE)&arg);
2164  }
2165 }
2166 
2167 static long
2168 io_fwritev(int argc, const VALUE *argv, rb_io_t *fptr)
2169 {
2170  int i, converted, iovcnt = argc + 1;
2171  long n;
2172  VALUE v1, v2, str, tmp, *tmp_array;
2173  struct iovec *iov;
2174 
2175  iov = ALLOCV_N(struct iovec, v1, iovcnt);
2176  tmp_array = ALLOCV_N(VALUE, v2, argc);
2177 
2178  for (i = 0; i < argc; i++) {
2179  str = rb_obj_as_string(argv[i]);
2180  converted = 0;
2181  str = do_writeconv(str, fptr, &converted);
2182 
2183  if (converted)
2184  OBJ_FREEZE(str);
2185 
2186  tmp = rb_str_tmp_frozen_acquire(str);
2187  tmp_array[i] = tmp;
2188 
2189  /* iov[0] is reserved for buffer of fptr */
2190  iov[i+1].iov_base = RSTRING_PTR(tmp);
2191  iov[i+1].iov_len = RSTRING_LEN(tmp);
2192  }
2193 
2194  n = io_binwritev(iov, iovcnt, fptr);
2195  if (v1) ALLOCV_END(v1);
2196 
2197  for (i = 0; i < argc; i++) {
2198  rb_str_tmp_frozen_release(argv[i], tmp_array[i]);
2199  }
2200 
2201  if (v2) ALLOCV_END(v2);
2202 
2203  return n;
2204 }
2205 
2206 static int
2207 iovcnt_ok(int iovcnt)
2208 {
2209 #ifdef IOV_MAX
2210  return iovcnt < IOV_MAX;
2211 #else /* GNU/Hurd has writev, but no IOV_MAX */
2212  return 1;
2213 #endif
2214 }
2215 #endif /* HAVE_WRITEV */
2216 
2217 static VALUE
2218 io_writev(int argc, const VALUE *argv, VALUE io)
2219 {
2220  rb_io_t *fptr;
2221  long n;
2222  VALUE tmp, total = INT2FIX(0);
2223  int i, cnt = 1;
2224 
2225  io = GetWriteIO(io);
2226  tmp = rb_io_check_io(io);
2227 
2228  if (NIL_P(tmp)) {
2229  /* port is not IO, call write method for it. */
2230  return rb_funcallv(io, id_write, argc, argv);
2231  }
2232 
2233  io = tmp;
2234 
2235  GetOpenFile(io, fptr);
2236  rb_io_check_writable(fptr);
2237 
2238  for (i = 0; i < argc; i += cnt) {
2239 #ifdef HAVE_WRITEV
2240  if ((fptr->mode & (FMODE_SYNC|FMODE_TTY)) && iovcnt_ok(cnt = argc - i)) {
2241  n = io_fwritev(cnt, &argv[i], fptr);
2242  }
2243  else
2244 #endif
2245  {
2246  cnt = 1;
2247  /* sync at last item */
2248  n = io_fwrite(rb_obj_as_string(argv[i]), fptr, (i < argc-1));
2249  }
2250 
2251  if (n < 0L)
2252  rb_sys_fail_on_write(fptr);
2253 
2254  total = rb_fix_plus(LONG2FIX(n), total);
2255  }
2256 
2257  return total;
2258 }
2259 
2260 /*
2261  * call-seq:
2262  * write(*objects) -> integer
2263  *
2264  * Writes each of the given +objects+ to +self+,
2265  * which must be opened for writing
2266  * (see {Access Modes}[rdoc-ref:File@Access+Modes]);
2267  * returns the total number bytes written;
2268  * each of +objects+ that is not a string is converted via method +to_s+:
2269  *
2270  * $stdout.write('Hello', ', ', 'World!', "\n") # => 14
2271  * $stdout.write('foo', :bar, 2, "\n") # => 8
2272  *
2273  * Output:
2274  *
2275  * Hello, World!
2276  * foobar2
2277  *
2278  * Related: IO#read.
2279  */
2280 
2281 static VALUE
2282 io_write_m(int argc, VALUE *argv, VALUE io)
2283 {
2284  if (argc != 1) {
2285  return io_writev(argc, argv, io);
2286  }
2287  else {
2288  VALUE str = argv[0];
2289  return io_write(io, str, 0);
2290  }
2291 }
2292 
2293 VALUE
2295 {
2296  return rb_funcallv(io, id_write, 1, &str);
2297 }
2298 
2299 static VALUE
2300 rb_io_writev(VALUE io, int argc, const VALUE *argv)
2301 {
2302  if (argc > 1 && rb_obj_method_arity(io, id_write) == 1) {
2303  if (io != rb_ractor_stderr() && RTEST(ruby_verbose)) {
2304  VALUE klass = CLASS_OF(io);
2305  char sep = RCLASS_SINGLETON_P(klass) ? (klass = io, '.') : '#';
2307  RB_WARN_CATEGORY_DEPRECATED, "%+"PRIsVALUE"%c""write is outdated interface"
2308  " which accepts just one argument",
2309  klass, sep
2310  );
2311  }
2312 
2313  do rb_io_write(io, *argv++); while (--argc);
2314 
2315  return Qnil;
2316  }
2317 
2318  return rb_funcallv(io, id_write, argc, argv);
2319 }
2320 
2321 /*
2322  * call-seq:
2323  * self << object -> self
2324  *
2325  * Writes the given +object+ to +self+,
2326  * which must be opened for writing (see {Access Modes}[rdoc-ref:File@Access+Modes]);
2327  * returns +self+;
2328  * if +object+ is not a string, it is converted via method +to_s+:
2329  *
2330  * $stdout << 'Hello' << ', ' << 'World!' << "\n"
2331  * $stdout << 'foo' << :bar << 2 << "\n"
2332  *
2333  * Output:
2334  *
2335  * Hello, World!
2336  * foobar2
2337  *
2338  */
2339 
2340 
2341 VALUE
2343 {
2344  rb_io_write(io, str);
2345  return io;
2346 }
2347 
2348 #ifdef HAVE_FSYNC
2349 static VALUE
2350 nogvl_fsync(void *ptr)
2351 {
2352  rb_io_t *fptr = ptr;
2353 
2354 #ifdef _WIN32
2355  if (GetFileType((HANDLE)rb_w32_get_osfhandle(fptr->fd)) != FILE_TYPE_DISK)
2356  return 0;
2357 #endif
2358  return (VALUE)fsync(fptr->fd);
2359 }
2360 #endif
2361 
2362 VALUE
2363 rb_io_flush_raw(VALUE io, int sync)
2364 {
2365  rb_io_t *fptr;
2366 
2367  if (!RB_TYPE_P(io, T_FILE)) {
2368  return rb_funcall(io, id_flush, 0);
2369  }
2370 
2371  io = GetWriteIO(io);
2372  GetOpenFile(io, fptr);
2373 
2374  if (fptr->mode & FMODE_WRITABLE) {
2375  if (io_fflush(fptr) < 0)
2376  rb_sys_fail_on_write(fptr);
2377  }
2378  if (fptr->mode & FMODE_READABLE) {
2379  io_unread(fptr);
2380  }
2381 
2382  return io;
2383 }
2384 
2385 /*
2386  * call-seq:
2387  * flush -> self
2388  *
2389  * Flushes data buffered in +self+ to the operating system
2390  * (but does not necessarily flush data buffered in the operating system):
2391  *
2392  * $stdout.print 'no newline' # Not necessarily flushed.
2393  * $stdout.flush # Flushed.
2394  *
2395  */
2396 
2397 VALUE
2399 {
2400  return rb_io_flush_raw(io, 1);
2401 }
2402 
2403 /*
2404  * call-seq:
2405  * tell -> integer
2406  *
2407  * Returns the current position (in bytes) in +self+
2408  * (see {Position}[rdoc-ref:IO@Position]):
2409  *
2410  * f = File.open('t.txt')
2411  * f.tell # => 0
2412  * f.gets # => "First line\n"
2413  * f.tell # => 12
2414  * f.close
2415  *
2416  * Related: IO#pos=, IO#seek.
2417  */
2418 
2419 static VALUE
2420 rb_io_tell(VALUE io)
2421 {
2422  rb_io_t *fptr;
2423  rb_off_t pos;
2424 
2425  GetOpenFile(io, fptr);
2426  pos = io_tell(fptr);
2427  if (pos < 0 && errno) rb_sys_fail_path(fptr->pathv);
2428  pos -= fptr->rbuf.len;
2429  return OFFT2NUM(pos);
2430 }
2431 
2432 static VALUE
2433 rb_io_seek(VALUE io, VALUE offset, int whence)
2434 {
2435  rb_io_t *fptr;
2436  rb_off_t pos;
2437 
2438  pos = NUM2OFFT(offset);
2439  GetOpenFile(io, fptr);
2440  pos = io_seek(fptr, pos, whence);
2441  if (pos < 0 && errno) rb_sys_fail_path(fptr->pathv);
2442 
2443  return INT2FIX(0);
2444 }
2445 
2446 static int
2447 interpret_seek_whence(VALUE vwhence)
2448 {
2449  if (vwhence == sym_SET)
2450  return SEEK_SET;
2451  if (vwhence == sym_CUR)
2452  return SEEK_CUR;
2453  if (vwhence == sym_END)
2454  return SEEK_END;
2455 #ifdef SEEK_DATA
2456  if (vwhence == sym_DATA)
2457  return SEEK_DATA;
2458 #endif
2459 #ifdef SEEK_HOLE
2460  if (vwhence == sym_HOLE)
2461  return SEEK_HOLE;
2462 #endif
2463  return NUM2INT(vwhence);
2464 }
2465 
2466 /*
2467  * call-seq:
2468  * seek(offset, whence = IO::SEEK_SET) -> 0
2469  *
2470  * Seeks to the position given by integer +offset+
2471  * (see {Position}[rdoc-ref:IO@Position])
2472  * and constant +whence+, which is one of:
2473  *
2474  * - +:CUR+ or <tt>IO::SEEK_CUR</tt>:
2475  * Repositions the stream to its current position plus the given +offset+:
2476  *
2477  * f = File.open('t.txt')
2478  * f.tell # => 0
2479  * f.seek(20, :CUR) # => 0
2480  * f.tell # => 20
2481  * f.seek(-10, :CUR) # => 0
2482  * f.tell # => 10
2483  * f.close
2484  *
2485  * - +:END+ or <tt>IO::SEEK_END</tt>:
2486  * Repositions the stream to its end plus the given +offset+:
2487  *
2488  * f = File.open('t.txt')
2489  * f.tell # => 0
2490  * f.seek(0, :END) # => 0 # Repositions to stream end.
2491  * f.tell # => 52
2492  * f.seek(-20, :END) # => 0
2493  * f.tell # => 32
2494  * f.seek(-40, :END) # => 0
2495  * f.tell # => 12
2496  * f.close
2497  *
2498  * - +:SET+ or <tt>IO:SEEK_SET</tt>:
2499  * Repositions the stream to the given +offset+:
2500  *
2501  * f = File.open('t.txt')
2502  * f.tell # => 0
2503  * f.seek(20, :SET) # => 0
2504  * f.tell # => 20
2505  * f.seek(40, :SET) # => 0
2506  * f.tell # => 40
2507  * f.close
2508  *
2509  * Related: IO#pos=, IO#tell.
2510  *
2511  */
2512 
2513 static VALUE
2514 rb_io_seek_m(int argc, VALUE *argv, VALUE io)
2515 {
2516  VALUE offset, ptrname;
2517  int whence = SEEK_SET;
2518 
2519  if (rb_scan_args(argc, argv, "11", &offset, &ptrname) == 2) {
2520  whence = interpret_seek_whence(ptrname);
2521  }
2522 
2523  return rb_io_seek(io, offset, whence);
2524 }
2525 
2526 /*
2527  * call-seq:
2528  * pos = new_position -> new_position
2529  *
2530  * Seeks to the given +new_position+ (in bytes);
2531  * see {Position}[rdoc-ref:IO@Position]:
2532  *
2533  * f = File.open('t.txt')
2534  * f.tell # => 0
2535  * f.pos = 20 # => 20
2536  * f.tell # => 20
2537  * f.close
2538  *
2539  * Related: IO#seek, IO#tell.
2540  *
2541  */
2542 
2543 static VALUE
2544 rb_io_set_pos(VALUE io, VALUE offset)
2545 {
2546  rb_io_t *fptr;
2547  rb_off_t pos;
2548 
2549  pos = NUM2OFFT(offset);
2550  GetOpenFile(io, fptr);
2551  pos = io_seek(fptr, pos, SEEK_SET);
2552  if (pos < 0 && errno) rb_sys_fail_path(fptr->pathv);
2553 
2554  return OFFT2NUM(pos);
2555 }
2556 
2557 static void clear_readconv(rb_io_t *fptr);
2558 
2559 /*
2560  * call-seq:
2561  * rewind -> 0
2562  *
2563  * Repositions the stream to its beginning,
2564  * setting both the position and the line number to zero;
2565  * see {Position}[rdoc-ref:IO@Position]
2566  * and {Line Number}[rdoc-ref:IO@Line+Number]:
2567  *
2568  * f = File.open('t.txt')
2569  * f.tell # => 0
2570  * f.lineno # => 0
2571  * f.gets # => "First line\n"
2572  * f.tell # => 12
2573  * f.lineno # => 1
2574  * f.rewind # => 0
2575  * f.tell # => 0
2576  * f.lineno # => 0
2577  * f.close
2578  *
2579  * Note that this method cannot be used with streams such as pipes, ttys, and sockets.
2580  *
2581  */
2582 
2583 static VALUE
2584 rb_io_rewind(VALUE io)
2585 {
2586  rb_io_t *fptr;
2587 
2588  GetOpenFile(io, fptr);
2589  if (io_seek(fptr, 0L, 0) < 0 && errno) rb_sys_fail_path(fptr->pathv);
2590  if (io == ARGF.current_file) {
2591  ARGF.lineno -= fptr->lineno;
2592  }
2593  fptr->lineno = 0;
2594  if (fptr->readconv) {
2595  clear_readconv(fptr);
2596  }
2597 
2598  return INT2FIX(0);
2599 }
2600 
2601 static int
2602 fptr_wait_readable(rb_io_t *fptr)
2603 {
2604  int result = rb_io_maybe_wait_readable(errno, fptr->self, RUBY_IO_TIMEOUT_DEFAULT);
2605 
2606  if (result)
2607  rb_io_check_closed(fptr);
2608 
2609  return result;
2610 }
2611 
2612 static int
2613 io_fillbuf(rb_io_t *fptr)
2614 {
2615  ssize_t r;
2616 
2617  if (fptr->rbuf.ptr == NULL) {
2618  fptr->rbuf.off = 0;
2619  fptr->rbuf.len = 0;
2620  fptr->rbuf.capa = IO_RBUF_CAPA_FOR(fptr);
2621  fptr->rbuf.ptr = ALLOC_N(char, fptr->rbuf.capa);
2622 #ifdef _WIN32
2623  fptr->rbuf.capa--;
2624 #endif
2625  }
2626  if (fptr->rbuf.len == 0) {
2627  retry:
2628  r = rb_io_read_memory(fptr, fptr->rbuf.ptr, fptr->rbuf.capa);
2629 
2630  if (r < 0) {
2631  if (fptr_wait_readable(fptr))
2632  goto retry;
2633 
2634  int e = errno;
2635  VALUE path = rb_sprintf("fd:%d ", fptr->fd);
2636  if (!NIL_P(fptr->pathv)) {
2637  rb_str_append(path, fptr->pathv);
2638  }
2639 
2640  rb_syserr_fail_path(e, path);
2641  }
2642  if (r > 0) rb_io_check_closed(fptr);
2643  fptr->rbuf.off = 0;
2644  fptr->rbuf.len = (int)r; /* r should be <= rbuf_capa */
2645  if (r == 0)
2646  return -1; /* EOF */
2647  }
2648  return 0;
2649 }
2650 
2651 /*
2652  * call-seq:
2653  * eof -> true or false
2654  *
2655  * Returns +true+ if the stream is positioned at its end, +false+ otherwise;
2656  * see {Position}[rdoc-ref:IO@Position]:
2657  *
2658  * f = File.open('t.txt')
2659  * f.eof # => false
2660  * f.seek(0, :END) # => 0
2661  * f.eof # => true
2662  * f.close
2663  *
2664  * Raises an exception unless the stream is opened for reading;
2665  * see {Mode}[rdoc-ref:File@Access+Modes].
2666  *
2667  * If +self+ is a stream such as pipe or socket, this method
2668  * blocks until the other end sends some data or closes it:
2669  *
2670  * r, w = IO.pipe
2671  * Thread.new { sleep 1; w.close }
2672  * r.eof? # => true # After 1-second wait.
2673  *
2674  * r, w = IO.pipe
2675  * Thread.new { sleep 1; w.puts "a" }
2676  * r.eof? # => false # After 1-second wait.
2677  *
2678  * r, w = IO.pipe
2679  * r.eof? # blocks forever
2680  *
2681  * Note that this method reads data to the input byte buffer. So
2682  * IO#sysread may not behave as you intend with IO#eof?, unless you
2683  * call IO#rewind first (which is not available for some streams).
2684  */
2685 
2686 VALUE
2688 {
2689  rb_io_t *fptr;
2690 
2691  GetOpenFile(io, fptr);
2693 
2694  if (READ_CHAR_PENDING(fptr)) return Qfalse;
2695  if (READ_DATA_PENDING(fptr)) return Qfalse;
2696  READ_CHECK(fptr);
2697 #if RUBY_CRLF_ENVIRONMENT
2698  if (!NEED_READCONV(fptr) && NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {
2699  return RBOOL(eof(fptr->fd));
2700  }
2701 #endif
2702  return RBOOL(io_fillbuf(fptr) < 0);
2703 }
2704 
2705 /*
2706  * call-seq:
2707  * sync -> true or false
2708  *
2709  * Returns the current sync mode of the stream.
2710  * When sync mode is true, all output is immediately flushed to the underlying
2711  * operating system and is not buffered by Ruby internally. See also #fsync.
2712  *
2713  * f = File.open('t.tmp', 'w')
2714  * f.sync # => false
2715  * f.sync = true
2716  * f.sync # => true
2717  * f.close
2718  *
2719  */
2720 
2721 static VALUE
2722 rb_io_sync(VALUE io)
2723 {
2724  rb_io_t *fptr;
2725 
2726  io = GetWriteIO(io);
2727  GetOpenFile(io, fptr);
2728  return RBOOL(fptr->mode & FMODE_SYNC);
2729 }
2730 
2731 #ifdef HAVE_FSYNC
2732 
2733 /*
2734  * call-seq:
2735  * sync = boolean -> boolean
2736  *
2737  * Sets the _sync_ _mode_ for the stream to the given value;
2738  * returns the given value.
2739  *
2740  * Values for the sync mode:
2741  *
2742  * - +true+: All output is immediately flushed to the
2743  * underlying operating system and is not buffered internally.
2744  * - +false+: Output may be buffered internally.
2745  *
2746  * Example;
2747  *
2748  * f = File.open('t.tmp', 'w')
2749  * f.sync # => false
2750  * f.sync = true
2751  * f.sync # => true
2752  * f.close
2753  *
2754  * Related: IO#fsync.
2755  *
2756  */
2757 
2758 static VALUE
2759 rb_io_set_sync(VALUE io, VALUE sync)
2760 {
2761  rb_io_t *fptr;
2762 
2763  io = GetWriteIO(io);
2764  GetOpenFile(io, fptr);
2765  if (RTEST(sync)) {
2766  fptr->mode |= FMODE_SYNC;
2767  }
2768  else {
2769  fptr->mode &= ~FMODE_SYNC;
2770  }
2771  return sync;
2772 }
2773 
2774 /*
2775  * call-seq:
2776  * fsync -> 0
2777  *
2778  * Immediately writes to disk all data buffered in the stream,
2779  * via the operating system's <tt>fsync(2)</tt>.
2780 
2781  * Note this difference:
2782  *
2783  * - IO#sync=: Ensures that data is flushed from the stream's internal buffers,
2784  * but does not guarantee that the operating system actually writes the data to disk.
2785  * - IO#fsync: Ensures both that data is flushed from internal buffers,
2786  * and that data is written to disk.
2787  *
2788  * Raises an exception if the operating system does not support <tt>fsync(2)</tt>.
2789  *
2790  */
2791 
2792 static VALUE
2793 rb_io_fsync(VALUE io)
2794 {
2795  rb_io_t *fptr;
2796 
2797  io = GetWriteIO(io);
2798  GetOpenFile(io, fptr);
2799 
2800  if (io_fflush(fptr) < 0)
2801  rb_sys_fail_on_write(fptr);
2802 
2803  if ((int)rb_io_blocking_region(fptr, nogvl_fsync, fptr))
2804  rb_sys_fail_path(fptr->pathv);
2805 
2806  return INT2FIX(0);
2807 }
2808 #else
2809 # define rb_io_fsync rb_f_notimplement
2810 # define rb_io_sync rb_f_notimplement
2811 static VALUE
2812 rb_io_set_sync(VALUE io, VALUE sync)
2813 {
2814  rb_notimplement();
2815  UNREACHABLE;
2816 }
2817 #endif
2818 
2819 #ifdef HAVE_FDATASYNC
2820 static VALUE
2821 nogvl_fdatasync(void *ptr)
2822 {
2823  rb_io_t *fptr = ptr;
2824 
2825 #ifdef _WIN32
2826  if (GetFileType((HANDLE)rb_w32_get_osfhandle(fptr->fd)) != FILE_TYPE_DISK)
2827  return 0;
2828 #endif
2829  return (VALUE)fdatasync(fptr->fd);
2830 }
2831 
2832 /*
2833  * call-seq:
2834  * fdatasync -> 0
2835  *
2836  * Immediately writes to disk all data buffered in the stream,
2837  * via the operating system's: <tt>fdatasync(2)</tt>, if supported,
2838  * otherwise via <tt>fsync(2)</tt>, if supported;
2839  * otherwise raises an exception.
2840  *
2841  */
2842 
2843 static VALUE
2844 rb_io_fdatasync(VALUE io)
2845 {
2846  rb_io_t *fptr;
2847 
2848  io = GetWriteIO(io);
2849  GetOpenFile(io, fptr);
2850 
2851  if (io_fflush(fptr) < 0)
2852  rb_sys_fail_on_write(fptr);
2853 
2854  if ((int)rb_io_blocking_region(fptr, nogvl_fdatasync, fptr) == 0)
2855  return INT2FIX(0);
2856 
2857  /* fall back */
2858  return rb_io_fsync(io);
2859 }
2860 #else
2861 #define rb_io_fdatasync rb_io_fsync
2862 #endif
2863 
2864 /*
2865  * call-seq:
2866  * fileno -> integer
2867  *
2868  * Returns the integer file descriptor for the stream:
2869  *
2870  * $stdin.fileno # => 0
2871  * $stdout.fileno # => 1
2872  * $stderr.fileno # => 2
2873  * File.open('t.txt').fileno # => 10
2874  * f.close
2875  *
2876  */
2877 
2878 static VALUE
2879 rb_io_fileno(VALUE io)
2880 {
2881  rb_io_t *fptr = RFILE(io)->fptr;
2882  int fd;
2883 
2884  rb_io_check_closed(fptr);
2885  fd = fptr->fd;
2886  return INT2FIX(fd);
2887 }
2888 
2889 int
2891 {
2892  if (RB_TYPE_P(io, T_FILE)) {
2893  rb_io_t *fptr = RFILE(io)->fptr;
2894  rb_io_check_closed(fptr);
2895  return fptr->fd;
2896  }
2897  else {
2898  VALUE fileno = rb_check_funcall(io, id_fileno, 0, NULL);
2899  if (!UNDEF_P(fileno)) {
2900  return RB_NUM2INT(fileno);
2901  }
2902  }
2903 
2904  rb_raise(rb_eTypeError, "expected IO or #fileno, %"PRIsVALUE" given", rb_obj_class(io));
2905 
2906  UNREACHABLE_RETURN(-1);
2907 }
2908 
2909 int
2911 {
2912  rb_io_t *fptr;
2913  GetOpenFile(io, fptr);
2914  return fptr->mode;
2915 }
2916 
2917 /*
2918  * call-seq:
2919  * pid -> integer or nil
2920  *
2921  * Returns the process ID of a child process associated with the stream,
2922  * which will have been set by IO#popen, or +nil+ if the stream was not
2923  * created by IO#popen:
2924  *
2925  * pipe = IO.popen("-")
2926  * if pipe
2927  * $stderr.puts "In parent, child pid is #{pipe.pid}"
2928  * else
2929  * $stderr.puts "In child, pid is #{$$}"
2930  * end
2931  *
2932  * Output:
2933  *
2934  * In child, pid is 26209
2935  * In parent, child pid is 26209
2936  *
2937  */
2938 
2939 static VALUE
2940 rb_io_pid(VALUE io)
2941 {
2942  rb_io_t *fptr;
2943 
2944  GetOpenFile(io, fptr);
2945  if (!fptr->pid)
2946  return Qnil;
2947  return PIDT2NUM(fptr->pid);
2948 }
2949 
2950 /*
2951  * call-seq:
2952  * path -> string or nil
2953  *
2954  * Returns the path associated with the IO, or +nil+ if there is no path
2955  * associated with the IO. It is not guaranteed that the path exists on
2956  * the filesystem.
2957  *
2958  * $stdin.path # => "<STDIN>"
2959  *
2960  * File.open("testfile") {|f| f.path} # => "testfile"
2961  */
2962 
2963 VALUE
2965 {
2966  rb_io_t *fptr = RFILE(io)->fptr;
2967 
2968  if (!fptr)
2969  return Qnil;
2970 
2971  return rb_obj_dup(fptr->pathv);
2972 }
2973 
2974 /*
2975  * call-seq:
2976  * inspect -> string
2977  *
2978  * Returns a string representation of +self+:
2979  *
2980  * f = File.open('t.txt')
2981  * f.inspect # => "#<File:t.txt>"
2982  * f.close
2983  *
2984  */
2985 
2986 static VALUE
2987 rb_io_inspect(VALUE obj)
2988 {
2989  rb_io_t *fptr;
2990  VALUE result;
2991  static const char closed[] = " (closed)";
2992 
2993  fptr = RFILE(obj)->fptr;
2994  if (!fptr) return rb_any_to_s(obj);
2995  result = rb_str_new_cstr("#<");
2996  rb_str_append(result, rb_class_name(CLASS_OF(obj)));
2997  rb_str_cat2(result, ":");
2998  if (NIL_P(fptr->pathv)) {
2999  if (fptr->fd < 0) {
3000  rb_str_cat(result, closed+1, strlen(closed)-1);
3001  }
3002  else {
3003  rb_str_catf(result, "fd %d", fptr->fd);
3004  }
3005  }
3006  else {
3007  rb_str_append(result, fptr->pathv);
3008  if (fptr->fd < 0) {
3009  rb_str_cat(result, closed, strlen(closed));
3010  }
3011  }
3012  return rb_str_cat2(result, ">");
3013 }
3014 
3015 /*
3016  * call-seq:
3017  * to_io -> self
3018  *
3019  * Returns +self+.
3020  *
3021  */
3022 
3023 static VALUE
3024 rb_io_to_io(VALUE io)
3025 {
3026  return io;
3027 }
3028 
3029 /* reading functions */
3030 static long
3031 read_buffered_data(char *ptr, long len, rb_io_t *fptr)
3032 {
3033  int n;
3034 
3035  n = READ_DATA_PENDING_COUNT(fptr);
3036  if (n <= 0) return 0;
3037  if (n > len) n = (int)len;
3038  MEMMOVE(ptr, fptr->rbuf.ptr+fptr->rbuf.off, char, n);
3039  fptr->rbuf.off += n;
3040  fptr->rbuf.len -= n;
3041  return n;
3042 }
3043 
3044 static long
3045 io_bufread(char *ptr, long len, rb_io_t *fptr)
3046 {
3047  long offset = 0;
3048  long n = len;
3049  long c;
3050 
3051  if (READ_DATA_PENDING(fptr) == 0) {
3052  while (n > 0) {
3053  again:
3054  rb_io_check_closed(fptr);
3055  c = rb_io_read_memory(fptr, ptr+offset, n);
3056  if (c == 0) break;
3057  if (c < 0) {
3058  if (fptr_wait_readable(fptr))
3059  goto again;
3060  return -1;
3061  }
3062  offset += c;
3063  if ((n -= c) <= 0) break;
3064  }
3065  return len - n;
3066  }
3067 
3068  while (n > 0) {
3069  c = read_buffered_data(ptr+offset, n, fptr);
3070  if (c > 0) {
3071  offset += c;
3072  if ((n -= c) <= 0) break;
3073  }
3074  rb_io_check_closed(fptr);
3075  if (io_fillbuf(fptr) < 0) {
3076  break;
3077  }
3078  }
3079  return len - n;
3080 }
3081 
3082 static int io_setstrbuf(VALUE *str, long len);
3083 
3084 struct bufread_arg {
3085  char *str_ptr;
3086  long len;
3087  rb_io_t *fptr;
3088 };
3089 
3090 static VALUE
3091 bufread_call(VALUE arg)
3092 {
3093  struct bufread_arg *p = (struct bufread_arg *)arg;
3094  p->len = io_bufread(p->str_ptr, p->len, p->fptr);
3095  return Qundef;
3096 }
3097 
3098 static long
3099 io_fread(VALUE str, long offset, long size, rb_io_t *fptr)
3100 {
3101  long len;
3102  struct bufread_arg arg;
3103 
3104  io_setstrbuf(&str, offset + size);
3105  arg.str_ptr = RSTRING_PTR(str) + offset;
3106  arg.len = size;
3107  arg.fptr = fptr;
3108  rb_str_locktmp_ensure(str, bufread_call, (VALUE)&arg);
3109  len = arg.len;
3110  if (len < 0) rb_sys_fail_path(fptr->pathv);
3111  return len;
3112 }
3113 
3114 static long
3115 remain_size(rb_io_t *fptr)
3116 {
3117  struct stat st;
3118  rb_off_t siz = READ_DATA_PENDING_COUNT(fptr);
3119  rb_off_t pos;
3120 
3121  if (fstat(fptr->fd, &st) == 0 && S_ISREG(st.st_mode)
3122 #if defined(__HAIKU__)
3123  && (st.st_dev > 3)
3124 #endif
3125  )
3126  {
3127  if (io_fflush(fptr) < 0)
3128  rb_sys_fail_on_write(fptr);
3129  pos = lseek(fptr->fd, 0, SEEK_CUR);
3130  if (st.st_size >= pos && pos >= 0) {
3131  siz += st.st_size - pos;
3132  if (siz > LONG_MAX) {
3133  rb_raise(rb_eIOError, "file too big for single read");
3134  }
3135  }
3136  }
3137  else {
3138  siz += BUFSIZ;
3139  }
3140  return (long)siz;
3141 }
3142 
3143 static VALUE
3144 io_enc_str(VALUE str, rb_io_t *fptr)
3145 {
3146  rb_enc_associate(str, io_read_encoding(fptr));
3147  return str;
3148 }
3149 
3150 static rb_encoding *io_read_encoding(rb_io_t *fptr);
3151 
3152 static void
3153 make_readconv(rb_io_t *fptr, int size)
3154 {
3155  if (!fptr->readconv) {
3156  int ecflags;
3157  VALUE ecopts;
3158  const char *sname, *dname;
3159  ecflags = fptr->encs.ecflags & ~ECONV_NEWLINE_DECORATOR_WRITE_MASK;
3160  ecopts = fptr->encs.ecopts;
3161  if (fptr->encs.enc2) {
3162  sname = rb_enc_name(fptr->encs.enc2);
3163  dname = rb_enc_name(io_read_encoding(fptr));
3164  }
3165  else {
3166  sname = dname = "";
3167  }
3168  fptr->readconv = rb_econv_open_opts(sname, dname, ecflags, ecopts);
3169  if (!fptr->readconv)
3170  rb_exc_raise(rb_econv_open_exc(sname, dname, ecflags));
3171  fptr->cbuf.off = 0;
3172  fptr->cbuf.len = 0;
3173  if (size < IO_CBUF_CAPA_MIN) size = IO_CBUF_CAPA_MIN;
3174  fptr->cbuf.capa = size;
3175  fptr->cbuf.ptr = ALLOC_N(char, fptr->cbuf.capa);
3176  }
3177 }
3178 
3179 #define MORE_CHAR_SUSPENDED Qtrue
3180 #define MORE_CHAR_FINISHED Qnil
3181 static VALUE
3182 fill_cbuf(rb_io_t *fptr, int ec_flags)
3183 {
3184  const unsigned char *ss, *sp, *se;
3185  unsigned char *ds, *dp, *de;
3186  rb_econv_result_t res;
3187  int putbackable;
3188  int cbuf_len0;
3189  VALUE exc;
3190 
3191  ec_flags |= ECONV_PARTIAL_INPUT;
3192 
3193  if (fptr->cbuf.len == fptr->cbuf.capa)
3194  return MORE_CHAR_SUSPENDED; /* cbuf full */
3195  if (fptr->cbuf.len == 0)
3196  fptr->cbuf.off = 0;
3197  else if (fptr->cbuf.off + fptr->cbuf.len == fptr->cbuf.capa) {
3198  memmove(fptr->cbuf.ptr, fptr->cbuf.ptr+fptr->cbuf.off, fptr->cbuf.len);
3199  fptr->cbuf.off = 0;
3200  }
3201 
3202  cbuf_len0 = fptr->cbuf.len;
3203 
3204  while (1) {
3205  ss = sp = (const unsigned char *)fptr->rbuf.ptr + fptr->rbuf.off;
3206  se = sp + fptr->rbuf.len;
3207  ds = dp = (unsigned char *)fptr->cbuf.ptr + fptr->cbuf.off + fptr->cbuf.len;
3208  de = (unsigned char *)fptr->cbuf.ptr + fptr->cbuf.capa;
3209  res = rb_econv_convert(fptr->readconv, &sp, se, &dp, de, ec_flags);
3210  fptr->rbuf.off += (int)(sp - ss);
3211  fptr->rbuf.len -= (int)(sp - ss);
3212  fptr->cbuf.len += (int)(dp - ds);
3213 
3214  putbackable = rb_econv_putbackable(fptr->readconv);
3215  if (putbackable) {
3216  rb_econv_putback(fptr->readconv, (unsigned char *)fptr->rbuf.ptr + fptr->rbuf.off - putbackable, putbackable);
3217  fptr->rbuf.off -= putbackable;
3218  fptr->rbuf.len += putbackable;
3219  }
3220 
3221  exc = rb_econv_make_exception(fptr->readconv);
3222  if (!NIL_P(exc))
3223  return exc;
3224 
3225  if (cbuf_len0 != fptr->cbuf.len)
3226  return MORE_CHAR_SUSPENDED;
3227 
3228  if (res == econv_finished) {
3229  return MORE_CHAR_FINISHED;
3230  }
3231 
3232  if (res == econv_source_buffer_empty) {
3233  if (fptr->rbuf.len == 0) {
3234  READ_CHECK(fptr);
3235  if (io_fillbuf(fptr) < 0) {
3236  if (!fptr->readconv) {
3237  return MORE_CHAR_FINISHED;
3238  }
3239  ds = dp = (unsigned char *)fptr->cbuf.ptr + fptr->cbuf.off + fptr->cbuf.len;
3240  de = (unsigned char *)fptr->cbuf.ptr + fptr->cbuf.capa;
3241  res = rb_econv_convert(fptr->readconv, NULL, NULL, &dp, de, 0);
3242  fptr->cbuf.len += (int)(dp - ds);
3244  break;
3245  }
3246  }
3247  }
3248  }
3249  if (cbuf_len0 != fptr->cbuf.len)
3250  return MORE_CHAR_SUSPENDED;
3251 
3252  return MORE_CHAR_FINISHED;
3253 }
3254 
3255 static VALUE
3256 more_char(rb_io_t *fptr)
3257 {
3258  VALUE v;
3259  v = fill_cbuf(fptr, ECONV_AFTER_OUTPUT);
3260  if (v != MORE_CHAR_SUSPENDED && v != MORE_CHAR_FINISHED)
3261  rb_exc_raise(v);
3262  return v;
3263 }
3264 
3265 static VALUE
3266 io_shift_cbuf(rb_io_t *fptr, int len, VALUE *strp)
3267 {
3268  VALUE str = Qnil;
3269  if (strp) {
3270  str = *strp;
3271  if (NIL_P(str)) {
3272  *strp = str = rb_str_new(fptr->cbuf.ptr+fptr->cbuf.off, len);
3273  }
3274  else {
3275  rb_str_cat(str, fptr->cbuf.ptr+fptr->cbuf.off, len);
3276  }
3277  rb_enc_associate(str, fptr->encs.enc);
3278  }
3279  fptr->cbuf.off += len;
3280  fptr->cbuf.len -= len;
3281  /* xxx: set coderange */
3282  if (fptr->cbuf.len == 0)
3283  fptr->cbuf.off = 0;
3284  else if (fptr->cbuf.capa/2 < fptr->cbuf.off) {
3285  memmove(fptr->cbuf.ptr, fptr->cbuf.ptr+fptr->cbuf.off, fptr->cbuf.len);
3286  fptr->cbuf.off = 0;
3287  }
3288  return str;
3289 }
3290 
3291 static int
3292 io_setstrbuf(VALUE *str, long len)
3293 {
3294 #ifdef _WIN32
3295  if (len > 0)
3296  len = (len + 1) & ~1L; /* round up for wide char */
3297 #endif
3298  if (NIL_P(*str)) {
3299  *str = rb_str_new(0, len);
3300  return TRUE;
3301  }
3302  else {
3303  VALUE s = StringValue(*str);
3304  rb_str_modify(s);
3305 
3306  long clen = RSTRING_LEN(s);
3307  if (clen >= len) {
3308  return FALSE;
3309  }
3310  len -= clen;
3311  }
3312  if ((rb_str_capacity(*str) - (size_t)RSTRING_LEN(*str)) < (size_t)len) {
3313  rb_str_modify_expand(*str, len);
3314  }
3315  return FALSE;
3316 }
3317 
3318 #define MAX_REALLOC_GAP 4096
3319 static void
3320 io_shrink_read_string(VALUE str, long n)
3321 {
3322  if (rb_str_capacity(str) - n > MAX_REALLOC_GAP) {
3323  rb_str_resize(str, n);
3324  }
3325 }
3326 
3327 static void
3328 io_set_read_length(VALUE str, long n, int shrinkable)
3329 {
3330  if (RSTRING_LEN(str) != n) {
3331  rb_str_modify(str);
3332  rb_str_set_len(str, n);
3333  if (shrinkable) io_shrink_read_string(str, n);
3334  }
3335 }
3336 
3337 static VALUE
3338 read_all(rb_io_t *fptr, long siz, VALUE str)
3339 {
3340  long bytes;
3341  long n;
3342  long pos;
3343  rb_encoding *enc;
3344  int cr;
3345  int shrinkable;
3346 
3347  if (NEED_READCONV(fptr)) {
3348  int first = !NIL_P(str);
3349  SET_BINARY_MODE(fptr);
3350  shrinkable = io_setstrbuf(&str,0);
3351  make_readconv(fptr, 0);
3352  while (1) {
3353  VALUE v;
3354  if (fptr->cbuf.len) {
3355  if (first) rb_str_set_len(str, first = 0);
3356  io_shift_cbuf(fptr, fptr->cbuf.len, &str);
3357  }
3358  v = fill_cbuf(fptr, 0);
3359  if (v != MORE_CHAR_SUSPENDED && v != MORE_CHAR_FINISHED) {
3360  if (fptr->cbuf.len) {
3361  if (first) rb_str_set_len(str, first = 0);
3362  io_shift_cbuf(fptr, fptr->cbuf.len, &str);
3363  }
3364  rb_exc_raise(v);
3365  }
3366  if (v == MORE_CHAR_FINISHED) {
3367  clear_readconv(fptr);
3368  if (first) rb_str_set_len(str, first = 0);
3369  if (shrinkable) io_shrink_read_string(str, RSTRING_LEN(str));
3370  return io_enc_str(str, fptr);
3371  }
3372  }
3373  }
3374 
3375  NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
3376  bytes = 0;
3377  pos = 0;
3378 
3379  enc = io_read_encoding(fptr);
3380  cr = 0;
3381 
3382  if (siz == 0) siz = BUFSIZ;
3383  shrinkable = io_setstrbuf(&str, siz);
3384  for (;;) {
3385  READ_CHECK(fptr);
3386  n = io_fread(str, bytes, siz - bytes, fptr);
3387  if (n == 0 && bytes == 0) {
3388  rb_str_set_len(str, 0);
3389  break;
3390  }
3391  bytes += n;
3392  rb_str_set_len(str, bytes);
3393  if (cr != ENC_CODERANGE_BROKEN)
3394  pos += rb_str_coderange_scan_restartable(RSTRING_PTR(str) + pos, RSTRING_PTR(str) + bytes, enc, &cr);
3395  if (bytes < siz) break;
3396  siz += BUFSIZ;
3397 
3398  size_t capa = rb_str_capacity(str);
3399  if (capa < (size_t)RSTRING_LEN(str) + BUFSIZ) {
3400  if (capa < BUFSIZ) {
3401  capa = BUFSIZ;
3402  }
3403  else if (capa > IO_MAX_BUFFER_GROWTH) {
3404  capa = IO_MAX_BUFFER_GROWTH;
3405  }
3406  rb_str_modify_expand(str, capa);
3407  }
3408  }
3409  if (shrinkable) io_shrink_read_string(str, RSTRING_LEN(str));
3410  str = io_enc_str(str, fptr);
3411  ENC_CODERANGE_SET(str, cr);
3412  return str;
3413 }
3414 
3415 void
3417 {
3418  if (rb_fd_set_nonblock(fptr->fd) != 0) {
3419  rb_sys_fail_path(fptr->pathv);
3420  }
3421 }
3422 
3423 static VALUE
3424 io_read_memory_call(VALUE arg)
3425 {
3426  struct io_internal_read_struct *iis = (struct io_internal_read_struct *)arg;
3427 
3428  VALUE scheduler = rb_fiber_scheduler_current();
3429  if (scheduler != Qnil) {
3430  VALUE result = rb_fiber_scheduler_io_read_memory(scheduler, iis->fptr->self, iis->buf, iis->capa, 0);
3431 
3432  if (!UNDEF_P(result)) {
3433  // This is actually returned as a pseudo-VALUE and later cast to a long:
3434  return (VALUE)rb_fiber_scheduler_io_result_apply(result);
3435  }
3436  }
3437 
3438  if (iis->nonblock) {
3439  return rb_io_blocking_region(iis->fptr, internal_read_func, iis);
3440  }
3441  else {
3442  return rb_io_blocking_region_wait(iis->fptr, internal_read_func, iis, RUBY_IO_READABLE);
3443  }
3444 }
3445 
3446 static long
3447 io_read_memory_locktmp(VALUE str, struct io_internal_read_struct *iis)
3448 {
3449  return (long)rb_str_locktmp_ensure(str, io_read_memory_call, (VALUE)iis);
3450 }
3451 
3452 #define no_exception_p(opts) !rb_opts_exception_p((opts), TRUE)
3453 
3454 static VALUE
3455 io_getpartial(int argc, VALUE *argv, VALUE io, int no_exception, int nonblock)
3456 {
3457  rb_io_t *fptr;
3458  VALUE length, str;
3459  long n, len;
3460  struct io_internal_read_struct iis;
3461  int shrinkable;
3462 
3463  rb_scan_args(argc, argv, "11", &length, &str);
3464 
3465  if ((len = NUM2LONG(length)) < 0) {
3466  rb_raise(rb_eArgError, "negative length %ld given", len);
3467  }
3468 
3469  shrinkable = io_setstrbuf(&str, len);
3470 
3471  GetOpenFile(io, fptr);
3473 
3474  if (len == 0) {
3475  io_set_read_length(str, 0, shrinkable);
3476  return str;
3477  }
3478 
3479  if (!nonblock)
3480  READ_CHECK(fptr);
3481  n = read_buffered_data(RSTRING_PTR(str), len, fptr);
3482  if (n <= 0) {
3483  again:
3484  if (nonblock) {
3485  rb_io_set_nonblock(fptr);
3486  }
3487  io_setstrbuf(&str, len);
3488  iis.th = rb_thread_current();
3489  iis.fptr = fptr;
3490  iis.nonblock = nonblock;
3491  iis.fd = fptr->fd;
3492  iis.buf = RSTRING_PTR(str);
3493  iis.capa = len;
3494  iis.timeout = NULL;
3495  n = io_read_memory_locktmp(str, &iis);
3496  if (n < 0) {
3497  int e = errno;
3498  if (!nonblock && fptr_wait_readable(fptr))
3499  goto again;
3500  if (nonblock && (io_again_p(e))) {
3501  if (no_exception)
3502  return sym_wait_readable;
3503  else
3504  rb_readwrite_syserr_fail(RB_IO_WAIT_READABLE,
3505  e, "read would block");
3506  }
3507  rb_syserr_fail_path(e, fptr->pathv);
3508  }
3509  }
3510  io_set_read_length(str, n, shrinkable);
3511 
3512  if (n == 0)
3513  return Qnil;
3514  else
3515  return str;
3516 }
3517 
3518 /*
3519  * call-seq:
3520  * readpartial(maxlen) -> string
3521  * readpartial(maxlen, out_string) -> out_string
3522  *
3523  * Reads up to +maxlen+ bytes from the stream;
3524  * returns a string (either a new string or the given +out_string+).
3525  * Its encoding is:
3526  *
3527  * - The unchanged encoding of +out_string+, if +out_string+ is given.
3528  * - ASCII-8BIT, otherwise.
3529  *
3530  * - Contains +maxlen+ bytes from the stream, if available.
3531  * - Otherwise contains all available bytes, if any available.
3532  * - Otherwise is an empty string.
3533  *
3534  * With the single non-negative integer argument +maxlen+ given,
3535  * returns a new string:
3536  *
3537  * f = File.new('t.txt')
3538  * f.readpartial(20) # => "First line\nSecond l"
3539  * f.readpartial(20) # => "ine\n\nFourth line\n"
3540  * f.readpartial(20) # => "Fifth line\n"
3541  * f.readpartial(20) # Raises EOFError.
3542  * f.close
3543  *
3544  * With both argument +maxlen+ and string argument +out_string+ given,
3545  * returns modified +out_string+:
3546  *
3547  * f = File.new('t.txt')
3548  * s = 'foo'
3549  * f.readpartial(20, s) # => "First line\nSecond l"
3550  * s = 'bar'
3551  * f.readpartial(0, s) # => ""
3552  * f.close
3553  *
3554  * This method is useful for a stream such as a pipe, a socket, or a tty.
3555  * It blocks only when no data is immediately available.
3556  * This means that it blocks only when _all_ of the following are true:
3557  *
3558  * - The byte buffer in the stream is empty.
3559  * - The content of the stream is empty.
3560  * - The stream is not at EOF.
3561  *
3562  * When blocked, the method waits for either more data or EOF on the stream:
3563  *
3564  * - If more data is read, the method returns the data.
3565  * - If EOF is reached, the method raises EOFError.
3566  *
3567  * When not blocked, the method responds immediately:
3568  *
3569  * - Returns data from the buffer if there is any.
3570  * - Otherwise returns data from the stream if there is any.
3571  * - Otherwise raises EOFError if the stream has reached EOF.
3572  *
3573  * Note that this method is similar to sysread. The differences are:
3574  *
3575  * - If the byte buffer is not empty, read from the byte buffer
3576  * instead of "sysread for buffered IO (IOError)".
3577  * - It doesn't cause Errno::EWOULDBLOCK and Errno::EINTR. When
3578  * readpartial meets EWOULDBLOCK and EINTR by read system call,
3579  * readpartial retries the system call.
3580  *
3581  * The latter means that readpartial is non-blocking-flag insensitive.
3582  * It blocks on the situation IO#sysread causes Errno::EWOULDBLOCK as
3583  * if the fd is blocking mode.
3584  *
3585  * Examples:
3586  *
3587  * # # Returned Buffer Content Pipe Content
3588  * r, w = IO.pipe #
3589  * w << 'abc' # "" "abc".
3590  * r.readpartial(4096) # => "abc" "" ""
3591  * r.readpartial(4096) # (Blocks because buffer and pipe are empty.)
3592  *
3593  * # # Returned Buffer Content Pipe Content
3594  * r, w = IO.pipe #
3595  * w << 'abc' # "" "abc"
3596  * w.close # "" "abc" EOF
3597  * r.readpartial(4096) # => "abc" "" EOF
3598  * r.readpartial(4096) # raises EOFError
3599  *
3600  * # # Returned Buffer Content Pipe Content
3601  * r, w = IO.pipe #
3602  * w << "abc\ndef\n" # "" "abc\ndef\n"
3603  * r.gets # => "abc\n" "def\n" ""
3604  * w << "ghi\n" # "def\n" "ghi\n"
3605  * r.readpartial(4096) # => "def\n" "" "ghi\n"
3606  * r.readpartial(4096) # => "ghi\n" "" ""
3607  *
3608  */
3609 
3610 static VALUE
3611 io_readpartial(int argc, VALUE *argv, VALUE io)
3612 {
3613  VALUE ret;
3614 
3615  ret = io_getpartial(argc, argv, io, Qnil, 0);
3616  if (NIL_P(ret))
3617  rb_eof_error();
3618  return ret;
3619 }
3620 
3621 static VALUE
3622 io_nonblock_eof(int no_exception)
3623 {
3624  if (!no_exception) {
3625  rb_eof_error();
3626  }
3627  return Qnil;
3628 }
3629 
3630 /* :nodoc: */
3631 static VALUE
3632 io_read_nonblock(rb_execution_context_t *ec, VALUE io, VALUE length, VALUE str, VALUE ex)
3633 {
3634  rb_io_t *fptr;
3635  long n, len;
3636  struct io_internal_read_struct iis;
3637  int shrinkable;
3638 
3639  if ((len = NUM2LONG(length)) < 0) {
3640  rb_raise(rb_eArgError, "negative length %ld given", len);
3641  }
3642 
3643  shrinkable = io_setstrbuf(&str, len);
3644  rb_bool_expected(ex, "exception", TRUE);
3645 
3646  GetOpenFile(io, fptr);
3648 
3649  if (len == 0) {
3650  io_set_read_length(str, 0, shrinkable);
3651  return str;
3652  }
3653 
3654  n = read_buffered_data(RSTRING_PTR(str), len, fptr);
3655  if (n <= 0) {
3656  rb_fd_set_nonblock(fptr->fd);
3657  shrinkable |= io_setstrbuf(&str, len);
3658  iis.fptr = fptr;
3659  iis.nonblock = 1;
3660  iis.fd = fptr->fd;
3661  iis.buf = RSTRING_PTR(str);
3662  iis.capa = len;
3663  iis.timeout = NULL;
3664  n = io_read_memory_locktmp(str, &iis);
3665  if (n < 0) {
3666  int e = errno;
3667  if (io_again_p(e)) {
3668  if (!ex) return sym_wait_readable;
3669  rb_readwrite_syserr_fail(RB_IO_WAIT_READABLE,
3670  e, "read would block");
3671  }
3672  rb_syserr_fail_path(e, fptr->pathv);
3673  }
3674  }
3675  io_set_read_length(str, n, shrinkable);
3676 
3677  if (n == 0) {
3678  if (!ex) return Qnil;
3679  rb_eof_error();
3680  }
3681 
3682  return str;
3683 }
3684 
3685 /* :nodoc: */
3686 static VALUE
3687 io_write_nonblock(rb_execution_context_t *ec, VALUE io, VALUE str, VALUE ex)
3688 {
3689  rb_io_t *fptr;
3690  long n;
3691 
3692  if (!RB_TYPE_P(str, T_STRING))
3693  str = rb_obj_as_string(str);
3694  rb_bool_expected(ex, "exception", TRUE);
3695 
3696  io = GetWriteIO(io);
3697  GetOpenFile(io, fptr);
3698  rb_io_check_writable(fptr);
3699 
3700  if (io_fflush(fptr) < 0)
3701  rb_sys_fail_on_write(fptr);
3702 
3703  rb_fd_set_nonblock(fptr->fd);
3704  n = write(fptr->fd, RSTRING_PTR(str), RSTRING_LEN(str));
3705  RB_GC_GUARD(str);
3706 
3707  if (n < 0) {
3708  int e = errno;
3709  if (io_again_p(e)) {
3710  if (!ex) {
3711  return sym_wait_writable;
3712  }
3713  else {
3714  rb_readwrite_syserr_fail(RB_IO_WAIT_WRITABLE, e, "write would block");
3715  }
3716  }
3717  rb_syserr_fail_path(e, fptr->pathv);
3718  }
3719 
3720  return LONG2FIX(n);
3721 }
3722 
3723 /*
3724  * call-seq:
3725  * read(maxlen = nil, out_string = nil) -> new_string, out_string, or nil
3726  *
3727  * Reads bytes from the stream; the stream must be opened for reading
3728  * (see {Access Modes}[rdoc-ref:File@Access+Modes]):
3729  *
3730  * - If +maxlen+ is +nil+, reads all bytes using the stream's data mode.
3731  * - Otherwise reads up to +maxlen+ bytes in binary mode.
3732  *
3733  * Returns a string (either a new string or the given +out_string+)
3734  * containing the bytes read.
3735  * The encoding of the string depends on both +maxLen+ and +out_string+:
3736  *
3737  * - +maxlen+ is +nil+: uses internal encoding of +self+
3738  * (regardless of whether +out_string+ was given).
3739  * - +maxlen+ not +nil+:
3740  *
3741  * - +out_string+ given: encoding of +out_string+ not modified.
3742  * - +out_string+ not given: ASCII-8BIT is used.
3743  *
3744  * <b>Without Argument +out_string+</b>
3745  *
3746  * When argument +out_string+ is omitted,
3747  * the returned value is a new string:
3748  *
3749  * f = File.new('t.txt')
3750  * f.read
3751  * # => "First line\nSecond line\n\nFourth line\nFifth line\n"
3752  * f.rewind
3753  * f.read(30) # => "First line\r\nSecond line\r\n\r\nFou"
3754  * f.read(30) # => "rth line\r\nFifth line\r\n"
3755  * f.read(30) # => nil
3756  * f.close
3757  *
3758  * If +maxlen+ is zero, returns an empty string.
3759  *
3760  * <b> With Argument +out_string+</b>
3761  *
3762  * When argument +out_string+ is given,
3763  * the returned value is +out_string+, whose content is replaced:
3764  *
3765  * f = File.new('t.txt')
3766  * s = 'foo' # => "foo"
3767  * f.read(nil, s) # => "First line\nSecond line\n\nFourth line\nFifth line\n"
3768  * s # => "First line\nSecond line\n\nFourth line\nFifth line\n"
3769  * f.rewind
3770  * s = 'bar'
3771  * f.read(30, s) # => "First line\r\nSecond line\r\n\r\nFou"
3772  * s # => "First line\r\nSecond line\r\n\r\nFou"
3773  * s = 'baz'
3774  * f.read(30, s) # => "rth line\r\nFifth line\r\n"
3775  * s # => "rth line\r\nFifth line\r\n"
3776  * s = 'bat'
3777  * f.read(30, s) # => nil
3778  * s # => ""
3779  * f.close
3780  *
3781  * Note that this method behaves like the fread() function in C.
3782  * This means it retries to invoke read(2) system calls to read data
3783  * with the specified maxlen (or until EOF).
3784  *
3785  * This behavior is preserved even if the stream is in non-blocking mode.
3786  * (This method is non-blocking-flag insensitive as other methods.)
3787  *
3788  * If you need the behavior like a single read(2) system call,
3789  * consider #readpartial, #read_nonblock, and #sysread.
3790  *
3791  * Related: IO#write.
3792  */
3793 
3794 static VALUE
3795 io_read(int argc, VALUE *argv, VALUE io)
3796 {
3797  rb_io_t *fptr;
3798  long n, len;
3799  VALUE length, str;
3800  int shrinkable;
3801 #if RUBY_CRLF_ENVIRONMENT
3802  int previous_mode;
3803 #endif
3804 
3805  rb_scan_args(argc, argv, "02", &length, &str);
3806 
3807  if (NIL_P(length)) {
3808  GetOpenFile(io, fptr);
3810  return read_all(fptr, remain_size(fptr), str);
3811  }
3812  len = NUM2LONG(length);
3813  if (len < 0) {
3814  rb_raise(rb_eArgError, "negative length %ld given", len);
3815  }
3816 
3817  shrinkable = io_setstrbuf(&str,len);
3818 
3819  GetOpenFile(io, fptr);
3821  if (len == 0) {
3822  io_set_read_length(str, 0, shrinkable);
3823  return str;
3824  }
3825 
3826  READ_CHECK(fptr);
3827 #if RUBY_CRLF_ENVIRONMENT
3828  previous_mode = set_binary_mode_with_seek_cur(fptr);
3829 #endif
3830  n = io_fread(str, 0, len, fptr);
3831  io_set_read_length(str, n, shrinkable);
3832 #if RUBY_CRLF_ENVIRONMENT
3833  if (previous_mode == O_TEXT) {
3834  setmode(fptr->fd, O_TEXT);
3835  }
3836 #endif
3837  if (n == 0) return Qnil;
3838 
3839  return str;
3840 }
3841 
3842 static void
3843 rscheck(const char *rsptr, long rslen, VALUE rs)
3844 {
3845  if (!rs) return;
3846  if (RSTRING_PTR(rs) != rsptr && RSTRING_LEN(rs) != rslen)
3847  rb_raise(rb_eRuntimeError, "rs modified");
3848 }
3849 
3850 static int
3851 appendline(rb_io_t *fptr, int delim, VALUE *strp, long *lp)
3852 {
3853  VALUE str = *strp;
3854  long limit = *lp;
3855 
3856  if (NEED_READCONV(fptr)) {
3857  SET_BINARY_MODE(fptr);
3858  make_readconv(fptr, 0);
3859  do {
3860  const char *p, *e;
3861  int searchlen = READ_CHAR_PENDING_COUNT(fptr);
3862  if (searchlen) {
3863  p = READ_CHAR_PENDING_PTR(fptr);
3864  if (0 < limit && limit < searchlen)
3865  searchlen = (int)limit;
3866  e = memchr(p, delim, searchlen);
3867  if (e) {
3868  int len = (int)(e-p+1);
3869  if (NIL_P(str))
3870  *strp = str = rb_str_new(p, len);
3871  else
3872  rb_str_buf_cat(str, p, len);
3873  fptr->cbuf.off += len;
3874  fptr->cbuf.len -= len;
3875  limit -= len;
3876  *lp = limit;
3877  return delim;
3878  }
3879 
3880  if (NIL_P(str))
3881  *strp = str = rb_str_new(p, searchlen);
3882  else
3883  rb_str_buf_cat(str, p, searchlen);
3884  fptr->cbuf.off += searchlen;
3885  fptr->cbuf.len -= searchlen;
3886  limit -= searchlen;
3887 
3888  if (limit == 0) {
3889  *lp = limit;
3890  return (unsigned char)RSTRING_PTR(str)[RSTRING_LEN(str)-1];
3891  }
3892  }
3893  } while (more_char(fptr) != MORE_CHAR_FINISHED);
3894  clear_readconv(fptr);
3895  *lp = limit;
3896  return EOF;
3897  }
3898 
3899  NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
3900  do {
3901  long pending = READ_DATA_PENDING_COUNT(fptr);
3902  if (pending > 0) {
3903  const char *p = READ_DATA_PENDING_PTR(fptr);
3904  const char *e;
3905  long last;
3906 
3907  if (limit > 0 && pending > limit) pending = limit;
3908  e = memchr(p, delim, pending);
3909  if (e) pending = e - p + 1;
3910  if (!NIL_P(str)) {
3911  last = RSTRING_LEN(str);
3912  rb_str_resize(str, last + pending);
3913  }
3914  else {
3915  last = 0;
3916  *strp = str = rb_str_buf_new(pending);
3917  rb_str_set_len(str, pending);
3918  }
3919  read_buffered_data(RSTRING_PTR(str) + last, pending, fptr); /* must not fail */
3920  limit -= pending;
3921  *lp = limit;
3922  if (e) return delim;
3923  if (limit == 0)
3924  return (unsigned char)RSTRING_PTR(str)[RSTRING_LEN(str)-1];
3925  }
3926  READ_CHECK(fptr);
3927  } while (io_fillbuf(fptr) >= 0);
3928  *lp = limit;
3929  return EOF;
3930 }
3931 
3932 static inline int
3933 swallow(rb_io_t *fptr, int term)
3934 {
3935  if (NEED_READCONV(fptr)) {
3936  rb_encoding *enc = io_read_encoding(fptr);
3937  int needconv = rb_enc_mbminlen(enc) != 1;
3938  SET_BINARY_MODE(fptr);
3939  make_readconv(fptr, 0);
3940  do {
3941  size_t cnt;
3942  while ((cnt = READ_CHAR_PENDING_COUNT(fptr)) > 0) {
3943  const char *p = READ_CHAR_PENDING_PTR(fptr);
3944  int i;
3945  if (!needconv) {
3946  if (*p != term) return TRUE;
3947  i = (int)cnt;
3948  while (--i && *++p == term);
3949  }
3950  else {
3951  const char *e = p + cnt;
3952  if (rb_enc_ascget(p, e, &i, enc) != term) return TRUE;
3953  while ((p += i) < e && rb_enc_ascget(p, e, &i, enc) == term);
3954  i = (int)(e - p);
3955  }
3956  io_shift_cbuf(fptr, (int)cnt - i, NULL);
3957  }
3958  } while (more_char(fptr) != MORE_CHAR_FINISHED);
3959  return FALSE;
3960  }
3961 
3962  NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
3963  do {
3964  size_t cnt;
3965  while ((cnt = READ_DATA_PENDING_COUNT(fptr)) > 0) {
3966  char buf[1024];
3967  const char *p = READ_DATA_PENDING_PTR(fptr);
3968  int i;
3969  if (cnt > sizeof buf) cnt = sizeof buf;
3970  if (*p != term) return TRUE;
3971  i = (int)cnt;
3972  while (--i && *++p == term);
3973  if (!read_buffered_data(buf, cnt - i, fptr)) /* must not fail */
3974  rb_sys_fail_path(fptr->pathv);
3975  }
3976  READ_CHECK(fptr);
3977  } while (io_fillbuf(fptr) == 0);
3978  return FALSE;
3979 }
3980 
3981 static VALUE
3982 rb_io_getline_fast(rb_io_t *fptr, rb_encoding *enc, int chomp)
3983 {
3984  VALUE str = Qnil;
3985  int len = 0;
3986  long pos = 0;
3987  int cr = 0;
3988 
3989  do {
3990  int pending = READ_DATA_PENDING_COUNT(fptr);
3991 
3992  if (pending > 0) {
3993  const char *p = READ_DATA_PENDING_PTR(fptr);
3994  const char *e;
3995  int chomplen = 0;
3996 
3997  e = memchr(p, '\n', pending);
3998  if (e) {
3999  pending = (int)(e - p + 1);
4000  if (chomp) {
4001  chomplen = (pending > 1 && *(e-1) == '\r') + 1;
4002  }
4003  }
4004  if (NIL_P(str)) {
4005  str = rb_str_new(p, pending - chomplen);
4006  fptr->rbuf.off += pending;
4007  fptr->rbuf.len -= pending;
4008  }
4009  else {
4010  rb_str_resize(str, len + pending - chomplen);
4011  read_buffered_data(RSTRING_PTR(str)+len, pending - chomplen, fptr);
4012  fptr->rbuf.off += chomplen;
4013  fptr->rbuf.len -= chomplen;
4014  if (pending == 1 && chomplen == 1 && len > 0) {
4015  if (RSTRING_PTR(str)[len-1] == '\r') {
4016  rb_str_resize(str, --len);
4017  break;
4018  }
4019  }
4020  }
4021  len += pending - chomplen;
4022  if (cr != ENC_CODERANGE_BROKEN)
4023  pos += rb_str_coderange_scan_restartable(RSTRING_PTR(str) + pos, RSTRING_PTR(str) + len, enc, &cr);
4024  if (e) break;
4025  }
4026  READ_CHECK(fptr);
4027  } while (io_fillbuf(fptr) >= 0);
4028  if (NIL_P(str)) return Qnil;
4029 
4030  str = io_enc_str(str, fptr);
4031  ENC_CODERANGE_SET(str, cr);
4032  fptr->lineno++;
4033 
4034  return str;
4035 }
4036 
4037 struct getline_arg {
4038  VALUE io;
4039  VALUE rs;
4040  long limit;
4041  unsigned int chomp: 1;
4042 };
4043 
4044 static void
4045 extract_getline_opts(VALUE opts, struct getline_arg *args)
4046 {
4047  int chomp = FALSE;
4048  if (!NIL_P(opts)) {
4049  static ID kwds[1];
4050  VALUE vchomp;
4051  if (!kwds[0]) {
4052  kwds[0] = rb_intern_const("chomp");
4053  }
4054  rb_get_kwargs(opts, kwds, 0, -2, &vchomp);
4055  chomp = (!UNDEF_P(vchomp)) && RTEST(vchomp);
4056  }
4057  args->chomp = chomp;
4058 }
4059 
4060 static void
4061 extract_getline_args(int argc, VALUE *argv, struct getline_arg *args)
4062 {
4063  VALUE rs = rb_rs, lim = Qnil;
4064 
4065  if (argc == 1) {
4066  VALUE tmp = Qnil;
4067 
4068  if (NIL_P(argv[0]) || !NIL_P(tmp = rb_check_string_type(argv[0]))) {
4069  rs = tmp;
4070  }
4071  else {
4072  lim = argv[0];
4073  }
4074  }
4075  else if (2 <= argc) {
4076  rs = argv[0], lim = argv[1];
4077  if (!NIL_P(rs))
4078  StringValue(rs);
4079  }
4080  args->rs = rs;
4081  args->limit = NIL_P(lim) ? -1L : NUM2LONG(lim);
4082 }
4083 
4084 static void
4085 check_getline_args(VALUE *rsp, long *limit, VALUE io)
4086 {
4087  rb_io_t *fptr;
4088  VALUE rs = *rsp;
4089 
4090  if (!NIL_P(rs)) {
4091  rb_encoding *enc_rs, *enc_io;
4092 
4093  GetOpenFile(io, fptr);
4094  enc_rs = rb_enc_get(rs);
4095  enc_io = io_read_encoding(fptr);
4096  if (enc_io != enc_rs &&
4097  (!is_ascii_string(rs) ||
4098  (RSTRING_LEN(rs) > 0 && !rb_enc_asciicompat(enc_io)))) {
4099  if (rs == rb_default_rs) {
4100  rs = rb_enc_str_new(0, 0, enc_io);
4101  rb_str_buf_cat_ascii(rs, "\n");
4102  *rsp = rs;
4103  }
4104  else {
4105  rb_raise(rb_eArgError, "encoding mismatch: %s IO with %s RS",
4106  rb_enc_name(enc_io),
4107  rb_enc_name(enc_rs));
4108  }
4109  }
4110  }
4111 }
4112 
4113 static void
4114 prepare_getline_args(int argc, VALUE *argv, struct getline_arg *args, VALUE io)
4115 {
4116  VALUE opts;
4117  argc = rb_scan_args(argc, argv, "02:", NULL, NULL, &opts);
4118  extract_getline_args(argc, argv, args);
4119  extract_getline_opts(opts, args);
4120  check_getline_args(&args->rs, &args->limit, io);
4121 }
4122 
4123 static VALUE
4124 rb_io_getline_0(VALUE rs, long limit, int chomp, rb_io_t *fptr)
4125 {
4126  VALUE str = Qnil;
4127  int nolimit = 0;
4128  rb_encoding *enc;
4129 
4131  if (NIL_P(rs) && limit < 0) {
4132  str = read_all(fptr, 0, Qnil);
4133  if (RSTRING_LEN(str) == 0) return Qnil;
4134  }
4135  else if (limit == 0) {
4136  return rb_enc_str_new(0, 0, io_read_encoding(fptr));
4137  }
4138  else if (rs == rb_default_rs && limit < 0 && !NEED_READCONV(fptr) &&
4139  rb_enc_asciicompat(enc = io_read_encoding(fptr))) {
4140  NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
4141  return rb_io_getline_fast(fptr, enc, chomp);
4142  }
4143  else {
4144  int c, newline = -1;
4145  const char *rsptr = 0;
4146  long rslen = 0;
4147  int rspara = 0;
4148  int extra_limit = 16;
4149  int chomp_cr = chomp;
4150 
4151  SET_BINARY_MODE(fptr);
4152  enc = io_read_encoding(fptr);
4153 
4154  if (!NIL_P(rs)) {
4155  rslen = RSTRING_LEN(rs);
4156  if (rslen == 0) {
4157  rsptr = "\n\n";
4158  rslen = 2;
4159  rspara = 1;
4160  swallow(fptr, '\n');
4161  rs = 0;
4162  if (!rb_enc_asciicompat(enc)) {
4163  rs = rb_usascii_str_new(rsptr, rslen);
4164  rs = rb_str_encode(rs, rb_enc_from_encoding(enc), 0, Qnil);
4165  OBJ_FREEZE(rs);
4166  rsptr = RSTRING_PTR(rs);
4167  rslen = RSTRING_LEN(rs);
4168  }
4169  }
4170  else {
4171  rsptr = RSTRING_PTR(rs);
4172  }
4173  newline = (unsigned char)rsptr[rslen - 1];
4174  chomp_cr = chomp && rslen == 1 && newline == '\n';
4175  }
4176 
4177  /* MS - Optimization */
4178  while ((c = appendline(fptr, newline, &str, &limit)) != EOF) {
4179  const char *s, *p, *pp, *e;
4180 
4181  if (c == newline) {
4182  if (RSTRING_LEN(str) < rslen) continue;
4183  s = RSTRING_PTR(str);
4184  e = RSTRING_END(str);
4185  p = e - rslen;
4186  if (!at_char_boundary(s, p, e, enc)) continue;
4187  if (!rspara) rscheck(rsptr, rslen, rs);
4188  if (memcmp(p, rsptr, rslen) == 0) {
4189  if (chomp) {
4190  if (chomp_cr && p > s && *(p-1) == '\r') --p;
4191  rb_str_set_len(str, p - s);
4192  }
4193  break;
4194  }
4195  }
4196  if (limit == 0) {
4197  s = RSTRING_PTR(str);
4198  p = RSTRING_END(str);
4199  pp = rb_enc_left_char_head(s, p-1, p, enc);
4200  if (extra_limit &&
4202  /* relax the limit while incomplete character.
4203  * extra_limit limits the relax length */
4204  limit = 1;
4205  extra_limit--;
4206  }
4207  else {
4208  nolimit = 1;
4209  break;
4210  }
4211  }
4212  }
4213 
4214  if (rspara && c != EOF)
4215  swallow(fptr, '\n');
4216  if (!NIL_P(str))
4217  str = io_enc_str(str, fptr);
4218  }
4219 
4220  if (!NIL_P(str) && !nolimit) {
4221  fptr->lineno++;
4222  }
4223 
4224  return str;
4225 }
4226 
4227 static VALUE
4228 rb_io_getline_1(VALUE rs, long limit, int chomp, VALUE io)
4229 {
4230  rb_io_t *fptr;
4231  int old_lineno, new_lineno;
4232  VALUE str;
4233 
4234  GetOpenFile(io, fptr);
4235  old_lineno = fptr->lineno;
4236  str = rb_io_getline_0(rs, limit, chomp, fptr);
4237  if (!NIL_P(str) && (new_lineno = fptr->lineno) != old_lineno) {
4238  if (io == ARGF.current_file) {
4239  ARGF.lineno += new_lineno - old_lineno;
4240  ARGF.last_lineno = ARGF.lineno;
4241  }
4242  else {
4243  ARGF.last_lineno = new_lineno;
4244  }
4245  }
4246 
4247  return str;
4248 }
4249 
4250 static VALUE
4251 rb_io_getline(int argc, VALUE *argv, VALUE io)
4252 {
4253  struct getline_arg args;
4254 
4255  prepare_getline_args(argc, argv, &args, io);
4256  return rb_io_getline_1(args.rs, args.limit, args.chomp, io);
4257 }
4258 
4259 VALUE
4261 {
4262  return rb_io_getline_1(rb_default_rs, -1, FALSE, io);
4263 }
4264 
4265 VALUE
4266 rb_io_gets_internal(VALUE io)
4267 {
4268  rb_io_t *fptr;
4269  GetOpenFile(io, fptr);
4270  return rb_io_getline_0(rb_default_rs, -1, FALSE, fptr);
4271 }
4272 
4273 /*
4274  * call-seq:
4275  * gets(sep = $/, chomp: false) -> string or nil
4276  * gets(limit, chomp: false) -> string or nil
4277  * gets(sep, limit, chomp: false) -> string or nil
4278  *
4279  * Reads and returns a line from the stream;
4280  * assigns the return value to <tt>$_</tt>.
4281  * See {Line IO}[rdoc-ref:IO@Line+IO].
4282  *
4283  * With no arguments given, returns the next line
4284  * as determined by line separator <tt>$/</tt>, or +nil+ if none:
4285  *
4286  * f = File.open('t.txt')
4287  * f.gets # => "First line\n"
4288  * $_ # => "First line\n"
4289  * f.gets # => "\n"
4290  * f.gets # => "Fourth line\n"
4291  * f.gets # => "Fifth line\n"
4292  * f.gets # => nil
4293  * f.close
4294  *
4295  * With only string argument +sep+ given,
4296  * returns the next line as determined by line separator +sep+,
4297  * or +nil+ if none;
4298  * see {Line Separator}[rdoc-ref:IO@Line+Separator]:
4299  *
4300  * f = File.new('t.txt')
4301  * f.gets('l') # => "First l"
4302  * f.gets('li') # => "ine\nSecond li"
4303  * f.gets('lin') # => "ne\n\nFourth lin"
4304  * f.gets # => "e\n"
4305  * f.close
4306  *
4307  * The two special values for +sep+ are honored:
4308  *
4309  * f = File.new('t.txt')
4310  * # Get all.
4311  * f.gets(nil) # => "First line\nSecond line\n\nFourth line\nFifth line\n"
4312  * f.rewind
4313  * # Get paragraph (up to two line separators).
4314  * f.gets('') # => "First line\nSecond line\n\n"
4315  * f.close
4316  *
4317  * With only integer argument +limit+ given,
4318  * limits the number of bytes in the line;
4319  * see {Line Limit}[rdoc-ref:IO@Line+Limit]:
4320  *
4321  * # No more than one line.
4322  * File.open('t.txt') {|f| f.gets(10) } # => "First line"
4323  * File.open('t.txt') {|f| f.gets(11) } # => "First line\n"
4324  * File.open('t.txt') {|f| f.gets(12) } # => "First line\n"
4325  *
4326  * With arguments +sep+ and +limit+ given,
4327  * combines the two behaviors
4328  * (see {Line Separator and Line Limit}[rdoc-ref:IO@Line+Separator+and+Line+Limit]).
4329  *
4330  * Optional keyword argument +chomp+ specifies whether line separators
4331  * are to be omitted:
4332  *
4333  * f = File.open('t.txt')
4334  * # Chomp the lines.
4335  * f.gets(chomp: true) # => "First line"
4336  * f.gets(chomp: true) # => "Second line"
4337  * f.gets(chomp: true) # => ""
4338  * f.gets(chomp: true) # => "Fourth line"
4339  * f.gets(chomp: true) # => "Fifth line"
4340  * f.gets(chomp: true) # => nil
4341  * f.close
4342  *
4343  */
4344 
4345 static VALUE
4346 rb_io_gets_m(int argc, VALUE *argv, VALUE io)
4347 {
4348  VALUE str;
4349 
4350  str = rb_io_getline(argc, argv, io);
4351  rb_lastline_set(str);
4352 
4353  return str;
4354 }
4355 
4356 /*
4357  * call-seq:
4358  * lineno -> integer
4359  *
4360  * Returns the current line number for the stream;
4361  * see {Line Number}[rdoc-ref:IO@Line+Number].
4362  *
4363  */
4364 
4365 static VALUE
4366 rb_io_lineno(VALUE io)
4367 {
4368  rb_io_t *fptr;
4369 
4370  GetOpenFile(io, fptr);
4372  return INT2NUM(fptr->lineno);
4373 }
4374 
4375 /*
4376  * call-seq:
4377  * lineno = integer -> integer
4378  *
4379  * Sets and returns the line number for the stream;
4380  * see {Line Number}[rdoc-ref:IO@Line+Number].
4381  *
4382  */
4383 
4384 static VALUE
4385 rb_io_set_lineno(VALUE io, VALUE lineno)
4386 {
4387  rb_io_t *fptr;
4388 
4389  GetOpenFile(io, fptr);
4391  fptr->lineno = NUM2INT(lineno);
4392  return lineno;
4393 }
4394 
4395 /* :nodoc: */
4396 static VALUE
4397 io_readline(rb_execution_context_t *ec, VALUE io, VALUE sep, VALUE lim, VALUE chomp)
4398 {
4399  long limit = -1;
4400  if (NIL_P(lim)) {
4401  VALUE tmp = Qnil;
4402  // If sep is specified, but it's not a string and not nil, then assume
4403  // it's the limit (it should be an integer)
4404  if (!NIL_P(sep) && NIL_P(tmp = rb_check_string_type(sep))) {
4405  // If the user has specified a non-nil / non-string value
4406  // for the separator, we assume it's the limit and set the
4407  // separator to default: rb_rs.
4408  lim = sep;
4409  limit = NUM2LONG(lim);
4410  sep = rb_rs;
4411  }
4412  else {
4413  sep = tmp;
4414  }
4415  }
4416  else {
4417  if (!NIL_P(sep)) StringValue(sep);
4418  limit = NUM2LONG(lim);
4419  }
4420 
4421  check_getline_args(&sep, &limit, io);
4422 
4423  VALUE line = rb_io_getline_1(sep, limit, RTEST(chomp), io);
4424  rb_lastline_set_up(line, 1);
4425 
4426  if (NIL_P(line)) {
4427  rb_eof_error();
4428  }
4429  return line;
4430 }
4431 
4432 static VALUE io_readlines(const struct getline_arg *arg, VALUE io);
4433 
4434 /*
4435  * call-seq:
4436  * readlines(sep = $/, chomp: false) -> array
4437  * readlines(limit, chomp: false) -> array
4438  * readlines(sep, limit, chomp: false) -> array
4439  *
4440  * Reads and returns all remaining line from the stream;
4441  * does not modify <tt>$_</tt>.
4442  * See {Line IO}[rdoc-ref:IO@Line+IO].
4443  *
4444  * With no arguments given, returns lines
4445  * as determined by line separator <tt>$/</tt>, or +nil+ if none:
4446  *
4447  * f = File.new('t.txt')
4448  * f.readlines
4449  * # => ["First line\n", "Second line\n", "\n", "Fourth line\n", "Fifth line\n"]
4450  * f.readlines # => []
4451  * f.close
4452  *
4453  * With only string argument +sep+ given,
4454  * returns lines as determined by line separator +sep+,
4455  * or +nil+ if none;
4456  * see {Line Separator}[rdoc-ref:IO@Line+Separator]:
4457  *
4458  * f = File.new('t.txt')
4459  * f.readlines('li')
4460  * # => ["First li", "ne\nSecond li", "ne\n\nFourth li", "ne\nFifth li", "ne\n"]
4461  * f.close
4462  *
4463  * The two special values for +sep+ are honored:
4464  *
4465  * f = File.new('t.txt')
4466  * # Get all into one string.
4467  * f.readlines(nil)
4468  * # => ["First line\nSecond line\n\nFourth line\nFifth line\n"]
4469  * # Get paragraphs (up to two line separators).
4470  * f.rewind
4471  * f.readlines('')
4472  * # => ["First line\nSecond line\n\n", "Fourth line\nFifth line\n"]
4473  * f.close
4474  *
4475  * With only integer argument +limit+ given,
4476  * limits the number of bytes in each line;
4477  * see {Line Limit}[rdoc-ref:IO@Line+Limit]:
4478  *
4479  * f = File.new('t.txt')
4480  * f.readlines(8)
4481  * # => ["First li", "ne\n", "Second l", "ine\n", "\n", "Fourth l", "ine\n", "Fifth li", "ne\n"]
4482  * f.close
4483  *
4484  * With arguments +sep+ and +limit+ given,
4485  * combines the two behaviors
4486  * (see {Line Separator and Line Limit}[rdoc-ref:IO@Line+Separator+and+Line+Limit]).
4487  *
4488  * Optional keyword argument +chomp+ specifies whether line separators
4489  * are to be omitted:
4490  *
4491  * f = File.new('t.txt')
4492  * f.readlines(chomp: true)
4493  * # => ["First line", "Second line", "", "Fourth line", "Fifth line"]
4494  * f.close
4495  *
4496  */
4497 
4498 static VALUE
4499 rb_io_readlines(int argc, VALUE *argv, VALUE io)
4500 {
4501  struct getline_arg args;
4502 
4503  prepare_getline_args(argc, argv, &args, io);
4504  return io_readlines(&args, io);
4505 }
4506 
4507 static VALUE
4508 io_readlines(const struct getline_arg *arg, VALUE io)
4509 {
4510  VALUE line, ary;
4511 
4512  if (arg->limit == 0)
4513  rb_raise(rb_eArgError, "invalid limit: 0 for readlines");
4514  ary = rb_ary_new();
4515  while (!NIL_P(line = rb_io_getline_1(arg->rs, arg->limit, arg->chomp, io))) {
4516  rb_ary_push(ary, line);
4517  }
4518  return ary;
4519 }
4520 
4521 /*
4522  * call-seq:
4523  * each_line(sep = $/, chomp: false) {|line| ... } -> self
4524  * each_line(limit, chomp: false) {|line| ... } -> self
4525  * each_line(sep, limit, chomp: false) {|line| ... } -> self
4526  * each_line -> enumerator
4527  *
4528  * Calls the block with each remaining line read from the stream;
4529  * returns +self+.
4530  * Does nothing if already at end-of-stream;
4531  * See {Line IO}[rdoc-ref:IO@Line+IO].
4532  *
4533  * With no arguments given, reads lines
4534  * as determined by line separator <tt>$/</tt>:
4535  *
4536  * f = File.new('t.txt')
4537  * f.each_line {|line| p line }
4538  * f.each_line {|line| fail 'Cannot happen' }
4539  * f.close
4540  *
4541  * Output:
4542  *
4543  * "First line\n"
4544  * "Second line\n"
4545  * "\n"
4546  * "Fourth line\n"
4547  * "Fifth line\n"
4548  *
4549  * With only string argument +sep+ given,
4550  * reads lines as determined by line separator +sep+;
4551  * see {Line Separator}[rdoc-ref:IO@Line+Separator]:
4552  *
4553  * f = File.new('t.txt')
4554  * f.each_line('li') {|line| p line }
4555  * f.close
4556  *
4557  * Output:
4558  *
4559  * "First li"
4560  * "ne\nSecond li"
4561  * "ne\n\nFourth li"
4562  * "ne\nFifth li"
4563  * "ne\n"
4564  *
4565  * The two special values for +sep+ are honored:
4566  *
4567  * f = File.new('t.txt')
4568  * # Get all into one string.
4569  * f.each_line(nil) {|line| p line }
4570  * f.close
4571  *
4572  * Output:
4573  *
4574  * "First line\nSecond line\n\nFourth line\nFifth line\n"
4575  *
4576  * f.rewind
4577  * # Get paragraphs (up to two line separators).
4578  * f.each_line('') {|line| p line }
4579  *
4580  * Output:
4581  *
4582  * "First line\nSecond line\n\n"
4583  * "Fourth line\nFifth line\n"
4584  *
4585  * With only integer argument +limit+ given,
4586  * limits the number of bytes in each line;
4587  * see {Line Limit}[rdoc-ref:IO@Line+Limit]:
4588  *
4589  * f = File.new('t.txt')
4590  * f.each_line(8) {|line| p line }
4591  * f.close
4592  *
4593  * Output:
4594  *
4595  * "First li"
4596  * "ne\n"
4597  * "Second l"
4598  * "ine\n"
4599  * "\n"
4600  * "Fourth l"
4601  * "ine\n"
4602  * "Fifth li"
4603  * "ne\n"
4604  *
4605  * With arguments +sep+ and +limit+ given,
4606  * combines the two behaviors
4607  * (see {Line Separator and Line Limit}[rdoc-ref:IO@Line+Separator+and+Line+Limit]).
4608  *
4609  * Optional keyword argument +chomp+ specifies whether line separators
4610  * are to be omitted:
4611  *
4612  * f = File.new('t.txt')
4613  * f.each_line(chomp: true) {|line| p line }
4614  * f.close
4615  *
4616  * Output:
4617  *
4618  * "First line"
4619  * "Second line"
4620  * ""
4621  * "Fourth line"
4622  * "Fifth line"
4623  *
4624  * Returns an Enumerator if no block is given.
4625  */
4626 
4627 static VALUE
4628 rb_io_each_line(int argc, VALUE *argv, VALUE io)
4629 {
4630  VALUE str;
4631  struct getline_arg args;
4632 
4633  RETURN_ENUMERATOR(io, argc, argv);
4634  prepare_getline_args(argc, argv, &args, io);
4635  if (args.limit == 0)
4636  rb_raise(rb_eArgError, "invalid limit: 0 for each_line");
4637  while (!NIL_P(str = rb_io_getline_1(args.rs, args.limit, args.chomp, io))) {
4638  rb_yield(str);
4639  }
4640  return io;
4641 }
4642 
4643 /*
4644  * call-seq:
4645  * each_byte {|byte| ... } -> self
4646  * each_byte -> enumerator
4647  *
4648  * Calls the given block with each byte (0..255) in the stream; returns +self+.
4649  * See {Byte IO}[rdoc-ref:IO@Byte+IO].
4650  *
4651  * f = File.new('t.rus')
4652  * a = []
4653  * f.each_byte {|b| a << b }
4654  * a # => [209, 130, 208, 181, 209, 129, 209, 130]
4655  * f.close
4656  *
4657  * Returns an Enumerator if no block is given.
4658  *
4659  * Related: IO#each_char, IO#each_codepoint.
4660  *
4661  */
4662 
4663 static VALUE
4664 rb_io_each_byte(VALUE io)
4665 {
4666  rb_io_t *fptr;
4667 
4668  RETURN_ENUMERATOR(io, 0, 0);
4669  GetOpenFile(io, fptr);
4670 
4671  do {
4672  while (fptr->rbuf.len > 0) {
4673  char *p = fptr->rbuf.ptr + fptr->rbuf.off++;
4674  fptr->rbuf.len--;
4675  rb_yield(INT2FIX(*p & 0xff));
4677  errno = 0;
4678  }
4679  READ_CHECK(fptr);
4680  } while (io_fillbuf(fptr) >= 0);
4681  return io;
4682 }
4683 
4684 static VALUE
4685 io_getc(rb_io_t *fptr, rb_encoding *enc)
4686 {
4687  int r, n, cr = 0;
4688  VALUE str;
4689 
4690  if (NEED_READCONV(fptr)) {
4691  rb_encoding *read_enc = io_read_encoding(fptr);
4692 
4693  str = Qnil;
4694  SET_BINARY_MODE(fptr);
4695  make_readconv(fptr, 0);
4696 
4697  while (1) {
4698  if (fptr->cbuf.len) {
4699  r = rb_enc_precise_mbclen(fptr->cbuf.ptr+fptr->cbuf.off,
4700  fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
4701  read_enc);
4702  if (!MBCLEN_NEEDMORE_P(r))
4703  break;
4704  if (fptr->cbuf.len == fptr->cbuf.capa) {
4705  rb_raise(rb_eIOError, "too long character");
4706  }
4707  }
4708 
4709  if (more_char(fptr) == MORE_CHAR_FINISHED) {
4710  if (fptr->cbuf.len == 0) {
4711  clear_readconv(fptr);
4712  return Qnil;
4713  }
4714  /* return an unit of an incomplete character just before EOF */
4715  str = rb_enc_str_new(fptr->cbuf.ptr+fptr->cbuf.off, 1, read_enc);
4716  fptr->cbuf.off += 1;
4717  fptr->cbuf.len -= 1;
4718  if (fptr->cbuf.len == 0) clear_readconv(fptr);
4720  return str;
4721  }
4722  }
4723  if (MBCLEN_INVALID_P(r)) {
4724  r = rb_enc_mbclen(fptr->cbuf.ptr+fptr->cbuf.off,
4725  fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
4726  read_enc);
4727  io_shift_cbuf(fptr, r, &str);
4728  cr = ENC_CODERANGE_BROKEN;
4729  }
4730  else {
4731  io_shift_cbuf(fptr, MBCLEN_CHARFOUND_LEN(r), &str);
4732  cr = ENC_CODERANGE_VALID;
4733  if (MBCLEN_CHARFOUND_LEN(r) == 1 && rb_enc_asciicompat(read_enc) &&
4734  ISASCII(RSTRING_PTR(str)[0])) {
4735  cr = ENC_CODERANGE_7BIT;
4736  }
4737  }
4738  str = io_enc_str(str, fptr);
4739  ENC_CODERANGE_SET(str, cr);
4740  return str;
4741  }
4742 
4743  NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
4744  if (io_fillbuf(fptr) < 0) {
4745  return Qnil;
4746  }
4747  if (rb_enc_asciicompat(enc) && ISASCII(fptr->rbuf.ptr[fptr->rbuf.off])) {
4748  str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, 1);
4749  fptr->rbuf.off += 1;
4750  fptr->rbuf.len -= 1;
4751  cr = ENC_CODERANGE_7BIT;
4752  }
4753  else {
4754  r = rb_enc_precise_mbclen(fptr->rbuf.ptr+fptr->rbuf.off, fptr->rbuf.ptr+fptr->rbuf.off+fptr->rbuf.len, enc);
4755  if (MBCLEN_CHARFOUND_P(r) &&
4756  (n = MBCLEN_CHARFOUND_LEN(r)) <= fptr->rbuf.len) {
4757  str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, n);
4758  fptr->rbuf.off += n;
4759  fptr->rbuf.len -= n;
4760  cr = ENC_CODERANGE_VALID;
4761  }
4762  else if (MBCLEN_NEEDMORE_P(r)) {
4763  str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, fptr->rbuf.len);
4764  fptr->rbuf.len = 0;
4765  getc_needmore:
4766  if (io_fillbuf(fptr) != -1) {
4767  rb_str_cat(str, fptr->rbuf.ptr+fptr->rbuf.off, 1);
4768  fptr->rbuf.off++;
4769  fptr->rbuf.len--;
4770  r = rb_enc_precise_mbclen(RSTRING_PTR(str), RSTRING_PTR(str)+RSTRING_LEN(str), enc);
4771  if (MBCLEN_NEEDMORE_P(r)) {
4772  goto getc_needmore;
4773  }
4774  else if (MBCLEN_CHARFOUND_P(r)) {
4775  cr = ENC_CODERANGE_VALID;
4776  }
4777  }
4778  }
4779  else {
4780  str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, 1);
4781  fptr->rbuf.off++;
4782  fptr->rbuf.len--;
4783  }
4784  }
4785  if (!cr) cr = ENC_CODERANGE_BROKEN;
4786  str = io_enc_str(str, fptr);
4787  ENC_CODERANGE_SET(str, cr);
4788  return str;
4789 }
4790 
4791 /*
4792  * call-seq:
4793  * each_char {|c| ... } -> self
4794  * each_char -> enumerator
4795  *
4796  * Calls the given block with each character in the stream; returns +self+.
4797  * See {Character IO}[rdoc-ref:IO@Character+IO].
4798  *
4799  * f = File.new('t.rus')
4800  * a = []
4801  * f.each_char {|c| a << c.ord }
4802  * a # => [1090, 1077, 1089, 1090]
4803  * f.close
4804  *
4805  * Returns an Enumerator if no block is given.
4806  *
4807  * Related: IO#each_byte, IO#each_codepoint.
4808  *
4809  */
4810 
4811 static VALUE
4812 rb_io_each_char(VALUE io)
4813 {
4814  rb_io_t *fptr;
4815  rb_encoding *enc;
4816  VALUE c;
4817 
4818  RETURN_ENUMERATOR(io, 0, 0);
4819  GetOpenFile(io, fptr);
4821 
4822  enc = io_input_encoding(fptr);
4823  READ_CHECK(fptr);
4824  while (!NIL_P(c = io_getc(fptr, enc))) {
4825  rb_yield(c);
4826  }
4827  return io;
4828 }
4829 
4830 /*
4831  * call-seq:
4832  * each_codepoint {|c| ... } -> self
4833  * each_codepoint -> enumerator
4834  *
4835  * Calls the given block with each codepoint in the stream; returns +self+:
4836  *
4837  * f = File.new('t.rus')
4838  * a = []
4839  * f.each_codepoint {|c| a << c }
4840  * a # => [1090, 1077, 1089, 1090]
4841  * f.close
4842  *
4843  * Returns an Enumerator if no block is given.
4844  *
4845  * Related: IO#each_byte, IO#each_char.
4846  *
4847  */
4848 
4849 static VALUE
4850 rb_io_each_codepoint(VALUE io)
4851 {
4852  rb_io_t *fptr;
4853  rb_encoding *enc;
4854  unsigned int c;
4855  int r, n;
4856 
4857  RETURN_ENUMERATOR(io, 0, 0);
4858  GetOpenFile(io, fptr);
4860 
4861  READ_CHECK(fptr);
4862  if (NEED_READCONV(fptr)) {
4863  SET_BINARY_MODE(fptr);
4864  r = 1; /* no invalid char yet */
4865  for (;;) {
4866  make_readconv(fptr, 0);
4867  for (;;) {
4868  if (fptr->cbuf.len) {
4869  if (fptr->encs.enc)
4870  r = rb_enc_precise_mbclen(fptr->cbuf.ptr+fptr->cbuf.off,
4871  fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
4872  fptr->encs.enc);
4873  else
4874  r = ONIGENC_CONSTRUCT_MBCLEN_CHARFOUND(1);
4875  if (!MBCLEN_NEEDMORE_P(r))
4876  break;
4877  if (fptr->cbuf.len == fptr->cbuf.capa) {
4878  rb_raise(rb_eIOError, "too long character");
4879  }
4880  }
4881  if (more_char(fptr) == MORE_CHAR_FINISHED) {
4882  clear_readconv(fptr);
4883  if (!MBCLEN_CHARFOUND_P(r)) {
4884  enc = fptr->encs.enc;
4885  goto invalid;
4886  }
4887  return io;
4888  }
4889  }
4890  if (MBCLEN_INVALID_P(r)) {
4891  enc = fptr->encs.enc;
4892  goto invalid;
4893  }
4894  n = MBCLEN_CHARFOUND_LEN(r);
4895  if (fptr->encs.enc) {
4896  c = rb_enc_codepoint(fptr->cbuf.ptr+fptr->cbuf.off,
4897  fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
4898  fptr->encs.enc);
4899  }
4900  else {
4901  c = (unsigned char)fptr->cbuf.ptr[fptr->cbuf.off];
4902  }
4903  fptr->cbuf.off += n;
4904  fptr->cbuf.len -= n;
4905  rb_yield(UINT2NUM(c));
4907  }
4908  }
4909  NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
4910  enc = io_input_encoding(fptr);
4911  while (io_fillbuf(fptr) >= 0) {
4912  r = rb_enc_precise_mbclen(fptr->rbuf.ptr+fptr->rbuf.off,
4913  fptr->rbuf.ptr+fptr->rbuf.off+fptr->rbuf.len, enc);
4914  if (MBCLEN_CHARFOUND_P(r) &&
4915  (n = MBCLEN_CHARFOUND_LEN(r)) <= fptr->rbuf.len) {
4916  c = rb_enc_codepoint(fptr->rbuf.ptr+fptr->rbuf.off,
4917  fptr->rbuf.ptr+fptr->rbuf.off+fptr->rbuf.len, enc);
4918  fptr->rbuf.off += n;
4919  fptr->rbuf.len -= n;
4920  rb_yield(UINT2NUM(c));
4921  }
4922  else if (MBCLEN_INVALID_P(r)) {
4923  goto invalid;
4924  }
4925  else if (MBCLEN_NEEDMORE_P(r)) {
4926  char cbuf[8], *p = cbuf;
4927  int more = MBCLEN_NEEDMORE_LEN(r);
4928  if (more > numberof(cbuf)) goto invalid;
4929  more += n = fptr->rbuf.len;
4930  if (more > numberof(cbuf)) goto invalid;
4931  while ((n = (int)read_buffered_data(p, more, fptr)) > 0 &&
4932  (p += n, (more -= n) > 0)) {
4933  if (io_fillbuf(fptr) < 0) goto invalid;
4934  if ((n = fptr->rbuf.len) > more) n = more;
4935  }
4936  r = rb_enc_precise_mbclen(cbuf, p, enc);
4937  if (!MBCLEN_CHARFOUND_P(r)) goto invalid;
4938  c = rb_enc_codepoint(cbuf, p, enc);
4939  rb_yield(UINT2NUM(c));
4940  }
4941  else {
4942  continue;
4943  }
4945  }
4946  return io;
4947 
4948  invalid:
4949  rb_raise(rb_eArgError, "invalid byte sequence in %s", rb_enc_name(enc));
4951 }
4952 
4953 /*
4954  * call-seq:
4955  * getc -> character or nil
4956  *
4957  * Reads and returns the next 1-character string from the stream;
4958  * returns +nil+ if already at end-of-stream.
4959  * See {Character IO}[rdoc-ref:IO@Character+IO].
4960  *
4961  * f = File.open('t.txt')
4962  * f.getc # => "F"
4963  * f.close
4964  * f = File.open('t.rus')
4965  * f.getc.ord # => 1090
4966  * f.close
4967  *
4968  * Related: IO#readchar (may raise EOFError).
4969  *
4970  */
4971 
4972 static VALUE
4973 rb_io_getc(VALUE io)
4974 {
4975  rb_io_t *fptr;
4976  rb_encoding *enc;
4977 
4978  GetOpenFile(io, fptr);
4980 
4981  enc = io_input_encoding(fptr);
4982  READ_CHECK(fptr);
4983  return io_getc(fptr, enc);
4984 }
4985 
4986 /*
4987  * call-seq:
4988  * readchar -> string
4989  *
4990  * Reads and returns the next 1-character string from the stream;
4991  * raises EOFError if already at end-of-stream.
4992  * See {Character IO}[rdoc-ref:IO@Character+IO].
4993  *
4994  * f = File.open('t.txt')
4995  * f.readchar # => "F"
4996  * f.close
4997  * f = File.open('t.rus')
4998  * f.readchar.ord # => 1090
4999  * f.close
5000  *
5001  * Related: IO#getc (will not raise EOFError).
5002  *
5003  */
5004 
5005 static VALUE
5006 rb_io_readchar(VALUE io)
5007 {
5008  VALUE c = rb_io_getc(io);
5009 
5010  if (NIL_P(c)) {
5011  rb_eof_error();
5012  }
5013  return c;
5014 }
5015 
5016 /*
5017  * call-seq:
5018  * getbyte -> integer or nil
5019  *
5020  * Reads and returns the next byte (in range 0..255) from the stream;
5021  * returns +nil+ if already at end-of-stream.
5022  * See {Byte IO}[rdoc-ref:IO@Byte+IO].
5023  *
5024  * f = File.open('t.txt')
5025  * f.getbyte # => 70
5026  * f.close
5027  * f = File.open('t.rus')
5028  * f.getbyte # => 209
5029  * f.close
5030  *
5031  * Related: IO#readbyte (may raise EOFError).
5032  */
5033 
5034 VALUE
5036 {
5037  rb_io_t *fptr;
5038  int c;
5039 
5040  GetOpenFile(io, fptr);
5042  READ_CHECK(fptr);
5043  VALUE r_stdout = rb_ractor_stdout();
5044  if (fptr->fd == 0 && (fptr->mode & FMODE_TTY) && RB_TYPE_P(r_stdout, T_FILE)) {
5045  rb_io_t *ofp;
5046  GetOpenFile(r_stdout, ofp);
5047  if (ofp->mode & FMODE_TTY) {
5048  rb_io_flush(r_stdout);
5049  }
5050  }
5051  if (io_fillbuf(fptr) < 0) {
5052  return Qnil;
5053  }
5054  fptr->rbuf.off++;
5055  fptr->rbuf.len--;
5056  c = (unsigned char)fptr->rbuf.ptr[fptr->rbuf.off-1];
5057  return INT2FIX(c & 0xff);
5058 }
5059 
5060 /*
5061  * call-seq:
5062  * readbyte -> integer
5063  *
5064  * Reads and returns the next byte (in range 0..255) from the stream;
5065  * raises EOFError if already at end-of-stream.
5066  * See {Byte IO}[rdoc-ref:IO@Byte+IO].
5067  *
5068  * f = File.open('t.txt')
5069  * f.readbyte # => 70
5070  * f.close
5071  * f = File.open('t.rus')
5072  * f.readbyte # => 209
5073  * f.close
5074  *
5075  * Related: IO#getbyte (will not raise EOFError).
5076  *
5077  */
5078 
5079 static VALUE
5080 rb_io_readbyte(VALUE io)
5081 {
5082  VALUE c = rb_io_getbyte(io);
5083 
5084  if (NIL_P(c)) {
5085  rb_eof_error();
5086  }
5087  return c;
5088 }
5089 
5090 /*
5091  * call-seq:
5092  * ungetbyte(integer) -> nil
5093  * ungetbyte(string) -> nil
5094  *
5095  * Pushes back ("unshifts") the given data onto the stream's buffer,
5096  * placing the data so that it is next to be read; returns +nil+.
5097  * See {Byte IO}[rdoc-ref:IO@Byte+IO].
5098  *
5099  * Note that:
5100  *
5101  * - Calling the method has no effect with unbuffered reads (such as IO#sysread).
5102  * - Calling #rewind on the stream discards the pushed-back data.
5103  *
5104  * When argument +integer+ is given, uses only its low-order byte:
5105  *
5106  * File.write('t.tmp', '012')
5107  * f = File.open('t.tmp')
5108  * f.ungetbyte(0x41) # => nil
5109  * f.read # => "A012"
5110  * f.rewind
5111  * f.ungetbyte(0x4243) # => nil
5112  * f.read # => "C012"
5113  * f.close
5114  *
5115  * When argument +string+ is given, uses all bytes:
5116  *
5117  * File.write('t.tmp', '012')
5118  * f = File.open('t.tmp')
5119  * f.ungetbyte('A') # => nil
5120  * f.read # => "A012"
5121  * f.rewind
5122  * f.ungetbyte('BCDE') # => nil
5123  * f.read # => "BCDE012"
5124  * f.close
5125  *
5126  */
5127 
5128 VALUE
5130 {
5131  rb_io_t *fptr;
5132 
5133  GetOpenFile(io, fptr);
5135  switch (TYPE(b)) {
5136  case T_NIL:
5137  return Qnil;
5138  case T_FIXNUM:
5139  case T_BIGNUM: ;
5140  VALUE v = rb_int_modulo(b, INT2FIX(256));
5141  unsigned char c = NUM2INT(v) & 0xFF;
5142  b = rb_str_new((const char *)&c, 1);
5143  break;
5144  default:
5145  StringValue(b);
5146  }
5147  io_ungetbyte(b, fptr);
5148  return Qnil;
5149 }
5150 
5151 /*
5152  * call-seq:
5153  * ungetc(integer) -> nil
5154  * ungetc(string) -> nil
5155  *
5156  * Pushes back ("unshifts") the given data onto the stream's buffer,
5157  * placing the data so that it is next to be read; returns +nil+.
5158  * See {Character IO}[rdoc-ref:IO@Character+IO].
5159  *
5160  * Note that:
5161  *
5162  * - Calling the method has no effect with unbuffered reads (such as IO#sysread).
5163  * - Calling #rewind on the stream discards the pushed-back data.
5164  *
5165  * When argument +integer+ is given, interprets the integer as a character:
5166  *
5167  * File.write('t.tmp', '012')
5168  * f = File.open('t.tmp')
5169  * f.ungetc(0x41) # => nil
5170  * f.read # => "A012"
5171  * f.rewind
5172  * f.ungetc(0x0442) # => nil
5173  * f.getc.ord # => 1090
5174  * f.close
5175  *
5176  * When argument +string+ is given, uses all characters:
5177  *
5178  * File.write('t.tmp', '012')
5179  * f = File.open('t.tmp')
5180  * f.ungetc('A') # => nil
5181  * f.read # => "A012"
5182  * f.rewind
5183  * f.ungetc("\u0442\u0435\u0441\u0442") # => nil
5184  * f.getc.ord # => 1090
5185  * f.getc.ord # => 1077
5186  * f.getc.ord # => 1089
5187  * f.getc.ord # => 1090
5188  * f.close
5189  *
5190  */
5191 
5192 VALUE
5194 {
5195  rb_io_t *fptr;
5196  long len;
5197 
5198  GetOpenFile(io, fptr);
5200  if (FIXNUM_P(c)) {
5201  c = rb_enc_uint_chr(FIX2UINT(c), io_read_encoding(fptr));
5202  }
5203  else if (RB_BIGNUM_TYPE_P(c)) {
5204  c = rb_enc_uint_chr(NUM2UINT(c), io_read_encoding(fptr));
5205  }
5206  else {
5207  StringValue(c);
5208  }
5209  if (NEED_READCONV(fptr)) {
5210  SET_BINARY_MODE(fptr);
5211  len = RSTRING_LEN(c);
5212 #if SIZEOF_LONG > SIZEOF_INT
5213  if (len > INT_MAX)
5214  rb_raise(rb_eIOError, "ungetc failed");
5215 #endif
5216  make_readconv(fptr, (int)len);
5217  if (fptr->cbuf.capa - fptr->cbuf.len < len)
5218  rb_raise(rb_eIOError, "ungetc failed");
5219  if (fptr->cbuf.off < len) {
5220  MEMMOVE(fptr->cbuf.ptr+fptr->cbuf.capa-fptr->cbuf.len,
5221  fptr->cbuf.ptr+fptr->cbuf.off,
5222  char, fptr->cbuf.len);
5223  fptr->cbuf.off = fptr->cbuf.capa-fptr->cbuf.len;
5224  }
5225  fptr->cbuf.off -= (int)len;
5226  fptr->cbuf.len += (int)len;
5227  MEMMOVE(fptr->cbuf.ptr+fptr->cbuf.off, RSTRING_PTR(c), char, len);
5228  }
5229  else {
5230  NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
5231  io_ungetbyte(c, fptr);
5232  }
5233  return Qnil;
5234 }
5235 
5236 /*
5237  * call-seq:
5238  * isatty -> true or false
5239  *
5240  * Returns +true+ if the stream is associated with a terminal device (tty),
5241  * +false+ otherwise:
5242  *
5243  * f = File.new('t.txt').isatty #=> false
5244  * f.close
5245  * f = File.new('/dev/tty').isatty #=> true
5246  * f.close
5247  *
5248  */
5249 
5250 static VALUE
5251 rb_io_isatty(VALUE io)
5252 {
5253  rb_io_t *fptr;
5254 
5255  GetOpenFile(io, fptr);
5256  return RBOOL(isatty(fptr->fd) != 0);
5257 }
5258 
5259 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
5260 /*
5261  * call-seq:
5262  * close_on_exec? -> true or false
5263  *
5264  * Returns +true+ if the stream will be closed on exec, +false+ otherwise:
5265  *
5266  * f = File.open('t.txt')
5267  * f.close_on_exec? # => true
5268  * f.close_on_exec = false
5269  * f.close_on_exec? # => false
5270  * f.close
5271  *
5272  */
5273 
5274 static VALUE
5275 rb_io_close_on_exec_p(VALUE io)
5276 {
5277  rb_io_t *fptr;
5278  VALUE write_io;
5279  int fd, ret;
5280 
5281  write_io = GetWriteIO(io);
5282  if (io != write_io) {
5283  GetOpenFile(write_io, fptr);
5284  if (fptr && 0 <= (fd = fptr->fd)) {
5285  if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
5286  if (!(ret & FD_CLOEXEC)) return Qfalse;
5287  }
5288  }
5289 
5290  GetOpenFile(io, fptr);
5291  if (fptr && 0 <= (fd = fptr->fd)) {
5292  if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
5293  if (!(ret & FD_CLOEXEC)) return Qfalse;
5294  }
5295  return Qtrue;
5296 }
5297 #else
5298 #define rb_io_close_on_exec_p rb_f_notimplement
5299 #endif
5300 
5301 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
5302 /*
5303  * call-seq:
5304  * self.close_on_exec = bool -> true or false
5305  *
5306  * Sets a close-on-exec flag.
5307  *
5308  * f = File.open(File::NULL)
5309  * f.close_on_exec = true
5310  * system("cat", "/proc/self/fd/#{f.fileno}") # cat: /proc/self/fd/3: No such file or directory
5311  * f.closed? #=> false
5312  *
5313  * Ruby sets close-on-exec flags of all file descriptors by default
5314  * since Ruby 2.0.0.
5315  * So you don't need to set by yourself.
5316  * Also, unsetting a close-on-exec flag can cause file descriptor leak
5317  * if another thread use fork() and exec() (via system() method for example).
5318  * If you really needs file descriptor inheritance to child process,
5319  * use spawn()'s argument such as fd=>fd.
5320  */
5321 
5322 static VALUE
5323 rb_io_set_close_on_exec(VALUE io, VALUE arg)
5324 {
5325  int flag = RTEST(arg) ? FD_CLOEXEC : 0;
5326  rb_io_t *fptr;
5327  VALUE write_io;
5328  int fd, ret;
5329 
5330  write_io = GetWriteIO(io);
5331  if (io != write_io) {
5332  GetOpenFile(write_io, fptr);
5333  if (fptr && 0 <= (fd = fptr->fd)) {
5334  if ((ret = fcntl(fptr->fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
5335  if ((ret & FD_CLOEXEC) != flag) {
5336  ret = (ret & ~FD_CLOEXEC) | flag;
5337  ret = fcntl(fd, F_SETFD, ret);
5338  if (ret != 0) rb_sys_fail_path(fptr->pathv);
5339  }
5340  }
5341 
5342  }
5343 
5344  GetOpenFile(io, fptr);
5345  if (fptr && 0 <= (fd = fptr->fd)) {
5346  if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
5347  if ((ret & FD_CLOEXEC) != flag) {
5348  ret = (ret & ~FD_CLOEXEC) | flag;
5349  ret = fcntl(fd, F_SETFD, ret);
5350  if (ret != 0) rb_sys_fail_path(fptr->pathv);
5351  }
5352  }
5353  return Qnil;
5354 }
5355 #else
5356 #define rb_io_set_close_on_exec rb_f_notimplement
5357 #endif
5358 
5359 #define RUBY_IO_EXTERNAL_P(f) ((f)->mode & FMODE_EXTERNAL)
5360 #define PREP_STDIO_NAME(f) (RSTRING_PTR((f)->pathv))
5361 
5362 static VALUE
5363 finish_writeconv(rb_io_t *fptr, int noalloc)
5364 {
5365  unsigned char *ds, *dp, *de;
5366  rb_econv_result_t res;
5367 
5368  if (!fptr->wbuf.ptr) {
5369  unsigned char buf[1024];
5370 
5372  while (res == econv_destination_buffer_full) {
5373  ds = dp = buf;
5374  de = buf + sizeof(buf);
5375  res = rb_econv_convert(fptr->writeconv, NULL, NULL, &dp, de, 0);
5376  while (dp-ds) {
5377  size_t remaining = dp-ds;
5378  long result = rb_io_write_memory(fptr, ds, remaining);
5379 
5380  if (result > 0) {
5381  ds += result;
5382  if ((size_t)result == remaining) break;
5383  }
5384  else if (rb_io_maybe_wait_writable(errno, fptr->self, RUBY_IO_TIMEOUT_DEFAULT)) {
5385  if (fptr->fd < 0)
5386  return noalloc ? Qtrue : rb_exc_new3(rb_eIOError, rb_str_new_cstr(closed_stream));
5387  }
5388  else {
5389  return noalloc ? Qtrue : INT2NUM(errno);
5390  }
5391  }
5392  if (res == econv_invalid_byte_sequence ||
5393  res == econv_incomplete_input ||
5394  res == econv_undefined_conversion) {
5395  return noalloc ? Qtrue : rb_econv_make_exception(fptr->writeconv);
5396  }
5397  }
5398 
5399  return Qnil;
5400  }
5401 
5403  while (res == econv_destination_buffer_full) {
5404  if (fptr->wbuf.len == fptr->wbuf.capa) {
5405  if (io_fflush(fptr) < 0) {
5406  return noalloc ? Qtrue : INT2NUM(errno);
5407  }
5408  }
5409 
5410  ds = dp = (unsigned char *)fptr->wbuf.ptr + fptr->wbuf.off + fptr->wbuf.len;
5411  de = (unsigned char *)fptr->wbuf.ptr + fptr->wbuf.capa;
5412  res = rb_econv_convert(fptr->writeconv, NULL, NULL, &dp, de, 0);
5413  fptr->wbuf.len += (int)(dp - ds);
5414  if (res == econv_invalid_byte_sequence ||
5415  res == econv_incomplete_input ||
5416  res == econv_undefined_conversion) {
5417  return noalloc ? Qtrue : rb_econv_make_exception(fptr->writeconv);
5418  }
5419  }
5420  return Qnil;
5421 }
5422 
5424  rb_io_t *fptr;
5425  int noalloc;
5426 };
5427 
5428 static VALUE
5429 finish_writeconv_sync(VALUE arg)
5430 {
5431  struct finish_writeconv_arg *p = (struct finish_writeconv_arg *)arg;
5432  return finish_writeconv(p->fptr, p->noalloc);
5433 }
5434 
5435 static void*
5436 nogvl_close(void *ptr)
5437 {
5438  int *fd = ptr;
5439 
5440  return (void*)(intptr_t)close(*fd);
5441 }
5442 
5443 static int
5444 maygvl_close(int fd, int keepgvl)
5445 {
5446  if (keepgvl)
5447  return close(fd);
5448 
5449  /*
5450  * close() may block for certain file types (NFS, SO_LINGER sockets,
5451  * inotify), so let other threads run.
5452  */
5453  return IO_WITHOUT_GVL_INT(nogvl_close, &fd);
5454 }
5455 
5456 static void*
5457 nogvl_fclose(void *ptr)
5458 {
5459  FILE *file = ptr;
5460 
5461  return (void*)(intptr_t)fclose(file);
5462 }
5463 
5464 static int
5465 maygvl_fclose(FILE *file, int keepgvl)
5466 {
5467  if (keepgvl)
5468  return fclose(file);
5469 
5470  return IO_WITHOUT_GVL_INT(nogvl_fclose, file);
5471 }
5472 
5473 static void free_io_buffer(rb_io_buffer_t *buf);
5474 static void clear_codeconv(rb_io_t *fptr);
5475 
5476 static void
5477 fptr_finalize_flush(rb_io_t *fptr, int noraise, int keepgvl,
5478  struct rb_io_close_wait_list *busy)
5479 {
5480  VALUE error = Qnil;
5481  int fd = fptr->fd;
5482  FILE *stdio_file = fptr->stdio_file;
5483  int mode = fptr->mode;
5484 
5485  if (fptr->writeconv) {
5486  if (!NIL_P(fptr->write_lock) && !noraise) {
5487  struct finish_writeconv_arg arg;
5488  arg.fptr = fptr;
5489  arg.noalloc = noraise;
5490  error = rb_mutex_synchronize(fptr->write_lock, finish_writeconv_sync, (VALUE)&arg);
5491  }
5492  else {
5493  error = finish_writeconv(fptr, noraise);
5494  }
5495  }
5496  if (fptr->wbuf.len) {
5497  if (noraise) {
5498  io_flush_buffer_sync(fptr);
5499  }
5500  else {
5501  if (io_fflush(fptr) < 0 && NIL_P(error)) {
5502  error = INT2NUM(errno);
5503  }
5504  }
5505  }
5506 
5507  int done = 0;
5508 
5509  if (RUBY_IO_EXTERNAL_P(fptr) || fd <= 2) {
5510  // Need to keep FILE objects of stdin, stdout and stderr, so we are done:
5511  done = 1;
5512  }
5513 
5514  fptr->fd = -1;
5515  fptr->stdio_file = 0;
5516  fptr->mode &= ~(FMODE_READABLE|FMODE_WRITABLE);
5517 
5518  // Ensure waiting_fd users do not hit EBADF.
5519  if (busy) {
5520  // Wait for them to exit before we call close().
5521  rb_notify_fd_close_wait(busy);
5522  }
5523 
5524  // Disable for now.
5525  // if (!done && fd >= 0) {
5526  // VALUE scheduler = rb_fiber_scheduler_current();
5527  // if (scheduler != Qnil) {
5528  // VALUE result = rb_fiber_scheduler_io_close(scheduler, fptr->self);
5529  // if (!UNDEF_P(result)) done = 1;
5530  // }
5531  // }
5532 
5533  if (!done && stdio_file) {
5534  // stdio_file is deallocated anyway even if fclose failed.
5535  if ((maygvl_fclose(stdio_file, noraise) < 0) && NIL_P(error)) {
5536  if (!noraise) {
5537  error = INT2NUM(errno);
5538  }
5539  }
5540 
5541  done = 1;
5542  }
5543 
5544  if (!done && fd >= 0) {
5545  // fptr->fd may be closed even if close fails. POSIX doesn't specify it.
5546  // We assumes it is closed.
5547 
5548  keepgvl |= !(mode & FMODE_WRITABLE);
5549  keepgvl |= noraise;
5550  if ((maygvl_close(fd, keepgvl) < 0) && NIL_P(error)) {
5551  if (!noraise) {
5552  error = INT2NUM(errno);
5553  }
5554  }
5555 
5556  done = 1;
5557  }
5558 
5559  if (!NIL_P(error) && !noraise) {
5560  if (RB_INTEGER_TYPE_P(error))
5561  rb_syserr_fail_path(NUM2INT(error), fptr->pathv);
5562  else
5563  rb_exc_raise(error);
5564  }
5565 }
5566 
5567 static void
5568 fptr_finalize(rb_io_t *fptr, int noraise)
5569 {
5570  fptr_finalize_flush(fptr, noraise, FALSE, 0);
5571  free_io_buffer(&fptr->rbuf);
5572  free_io_buffer(&fptr->wbuf);
5573  clear_codeconv(fptr);
5574 }
5575 
5576 static void
5577 rb_io_fptr_cleanup(rb_io_t *fptr, int noraise)
5578 {
5579  if (fptr->finalize) {
5580  (*fptr->finalize)(fptr, noraise);
5581  }
5582  else {
5583  fptr_finalize(fptr, noraise);
5584  }
5585 }
5586 
5587 static void
5588 free_io_buffer(rb_io_buffer_t *buf)
5589 {
5590  if (buf->ptr) {
5591  ruby_sized_xfree(buf->ptr, (size_t)buf->capa);
5592  buf->ptr = NULL;
5593  }
5594 }
5595 
5596 static void
5597 clear_readconv(rb_io_t *fptr)
5598 {
5599  if (fptr->readconv) {
5600  rb_econv_close(fptr->readconv);
5601  fptr->readconv = NULL;
5602  }
5603  free_io_buffer(&fptr->cbuf);
5604 }
5605 
5606 static void
5607 clear_writeconv(rb_io_t *fptr)
5608 {
5609  if (fptr->writeconv) {
5610  rb_econv_close(fptr->writeconv);
5611  fptr->writeconv = NULL;
5612  }
5613  fptr->writeconv_initialized = 0;
5614 }
5615 
5616 static void
5617 clear_codeconv(rb_io_t *fptr)
5618 {
5619  clear_readconv(fptr);
5620  clear_writeconv(fptr);
5621 }
5622 
5623 static void
5624 rb_io_fptr_cleanup_all(rb_io_t *fptr)
5625 {
5626  fptr->pathv = Qnil;
5627  if (0 <= fptr->fd)
5628  rb_io_fptr_cleanup(fptr, TRUE);
5629  fptr->write_lock = Qnil;
5630  free_io_buffer(&fptr->rbuf);
5631  free_io_buffer(&fptr->wbuf);
5632  clear_codeconv(fptr);
5633 }
5634 
5635 void
5636 rb_io_fptr_finalize_internal(void *ptr)
5637 {
5638  if (!ptr) return;
5639  rb_io_fptr_cleanup_all(ptr);
5640  free(ptr);
5641 }
5642 
5643 #undef rb_io_fptr_finalize
5644 int
5646 {
5647  if (!fptr) {
5648  return 0;
5649  }
5650  else {
5651  rb_io_fptr_finalize_internal(fptr);
5652  return 1;
5653  }
5654 }
5655 #define rb_io_fptr_finalize(fptr) rb_io_fptr_finalize_internal(fptr)
5656 
5657 size_t
5658 rb_io_memsize(const rb_io_t *fptr)
5659 {
5660  size_t size = sizeof(rb_io_t);
5661  size += fptr->rbuf.capa;
5662  size += fptr->wbuf.capa;
5663  size += fptr->cbuf.capa;
5664  if (fptr->readconv) size += rb_econv_memsize(fptr->readconv);
5665  if (fptr->writeconv) size += rb_econv_memsize(fptr->writeconv);
5666  return size;
5667 }
5668 
5669 #ifdef _WIN32
5670 /* keep GVL while closing to prevent crash on Windows */
5671 # define KEEPGVL TRUE
5672 #else
5673 # define KEEPGVL FALSE
5674 #endif
5675 
5676 static rb_io_t *
5677 io_close_fptr(VALUE io)
5678 {
5679  rb_io_t *fptr;
5680  VALUE write_io;
5681  rb_io_t *write_fptr;
5682  struct rb_io_close_wait_list busy;
5683 
5684  write_io = GetWriteIO(io);
5685  if (io != write_io) {
5686  write_fptr = RFILE(write_io)->fptr;
5687  if (write_fptr && 0 <= write_fptr->fd) {
5688  rb_io_fptr_cleanup(write_fptr, TRUE);
5689  }
5690  }
5691 
5692  fptr = RFILE(io)->fptr;
5693  if (!fptr) return 0;
5694  if (fptr->fd < 0) return 0;
5695 
5696  if (rb_notify_fd_close(fptr->fd, &busy)) {
5697  /* calls close(fptr->fd): */
5698  fptr_finalize_flush(fptr, FALSE, KEEPGVL, &busy);
5699  }
5700  rb_io_fptr_cleanup(fptr, FALSE);
5701  return fptr;
5702 }
5703 
5704 static void
5705 fptr_waitpid(rb_io_t *fptr, int nohang)
5706 {
5707  int status;
5708  if (fptr->pid) {
5709  rb_last_status_clear();
5710  rb_waitpid(fptr->pid, &status, nohang ? WNOHANG : 0);
5711  fptr->pid = 0;
5712  }
5713 }
5714 
5715 VALUE
5717 {
5718  rb_io_t *fptr = io_close_fptr(io);
5719  if (fptr) fptr_waitpid(fptr, 0);
5720  return Qnil;
5721 }
5722 
5723 /*
5724  * call-seq:
5725  * close -> nil
5726  *
5727  * Closes the stream for both reading and writing
5728  * if open for either or both; returns +nil+.
5729  * See {Open and Closed Streams}[rdoc-ref:IO@Open+and+Closed+Streams].
5730  *
5731  * If the stream is open for writing, flushes any buffered writes
5732  * to the operating system before closing.
5733  *
5734  * If the stream was opened by IO.popen, sets global variable <tt>$?</tt>
5735  * (child exit status).
5736  *
5737  * It is not an error to close an IO object that has already been closed.
5738  * It just returns nil.
5739  *
5740  * Example:
5741  *
5742  * IO.popen('ruby', 'r+') do |pipe|
5743  * puts pipe.closed?
5744  * pipe.close
5745  * puts $?
5746  * puts pipe.closed?
5747  * end
5748  *
5749  * Output:
5750  *
5751  * false
5752  * pid 13760 exit 0
5753  * true
5754  *
5755  * Related: IO#close_read, IO#close_write, IO#closed?.
5756  */
5757 
5758 static VALUE
5759 rb_io_close_m(VALUE io)
5760 {
5761  rb_io_t *fptr = rb_io_get_fptr(io);
5762  if (fptr->fd < 0) {
5763  return Qnil;
5764  }
5765  rb_io_close(io);
5766  return Qnil;
5767 }
5768 
5769 static VALUE
5770 io_call_close(VALUE io)
5771 {
5772  rb_check_funcall(io, rb_intern("close"), 0, 0);
5773  return io;
5774 }
5775 
5776 static VALUE
5777 ignore_closed_stream(VALUE io, VALUE exc)
5778 {
5779  enum {mesg_len = sizeof(closed_stream)-1};
5780  VALUE mesg = rb_attr_get(exc, idMesg);
5781  if (!RB_TYPE_P(mesg, T_STRING) ||
5782  RSTRING_LEN(mesg) != mesg_len ||
5783  memcmp(RSTRING_PTR(mesg), closed_stream, mesg_len)) {
5784  rb_exc_raise(exc);
5785  }
5786  return io;
5787 }
5788 
5789 static VALUE
5790 io_close(VALUE io)
5791 {
5792  VALUE closed = rb_check_funcall(io, rb_intern("closed?"), 0, 0);
5793  if (!UNDEF_P(closed) && RTEST(closed)) return io;
5794  rb_rescue2(io_call_close, io, ignore_closed_stream, io,
5795  rb_eIOError, (VALUE)0);
5796  return io;
5797 }
5798 
5799 /*
5800  * call-seq:
5801  * closed? -> true or false
5802  *
5803  * Returns +true+ if the stream is closed for both reading and writing,
5804  * +false+ otherwise.
5805  * See {Open and Closed Streams}[rdoc-ref:IO@Open+and+Closed+Streams].
5806  *
5807  * IO.popen('ruby', 'r+') do |pipe|
5808  * puts pipe.closed?
5809  * pipe.close_read
5810  * puts pipe.closed?
5811  * pipe.close_write
5812  * puts pipe.closed?
5813  * end
5814  *
5815  * Output:
5816  *
5817  * false
5818  * false
5819  * true
5820  *
5821  * Related: IO#close_read, IO#close_write, IO#close.
5822  */
5823 VALUE
5825 {
5826  rb_io_t *fptr;
5827  VALUE write_io;
5828  rb_io_t *write_fptr;
5829 
5830  write_io = GetWriteIO(io);
5831  if (io != write_io) {
5832  write_fptr = RFILE(write_io)->fptr;
5833  if (write_fptr && 0 <= write_fptr->fd) {
5834  return Qfalse;
5835  }
5836  }
5837 
5838  fptr = rb_io_get_fptr(io);
5839  return RBOOL(0 > fptr->fd);
5840 }
5841 
5842 /*
5843  * call-seq:
5844  * close_read -> nil
5845  *
5846  * Closes the stream for reading if open for reading;
5847  * returns +nil+.
5848  * See {Open and Closed Streams}[rdoc-ref:IO@Open+and+Closed+Streams].
5849  *
5850  * If the stream was opened by IO.popen and is also closed for writing,
5851  * sets global variable <tt>$?</tt> (child exit status).
5852  *
5853  * Example:
5854  *
5855  * IO.popen('ruby', 'r+') do |pipe|
5856  * puts pipe.closed?
5857  * pipe.close_write
5858  * puts pipe.closed?
5859  * pipe.close_read
5860  * puts $?
5861  * puts pipe.closed?
5862  * end
5863  *
5864  * Output:
5865  *
5866  * false
5867  * false
5868  * pid 14748 exit 0
5869  * true
5870  *
5871  * Related: IO#close, IO#close_write, IO#closed?.
5872  */
5873 
5874 static VALUE
5875 rb_io_close_read(VALUE io)
5876 {
5877  rb_io_t *fptr;
5878  VALUE write_io;
5879 
5880  fptr = rb_io_get_fptr(rb_io_taint_check(io));
5881  if (fptr->fd < 0) return Qnil;
5882  if (is_socket(fptr->fd, fptr->pathv)) {
5883 #ifndef SHUT_RD
5884 # define SHUT_RD 0
5885 #endif
5886  if (shutdown(fptr->fd, SHUT_RD) < 0)
5887  rb_sys_fail_path(fptr->pathv);
5888  fptr->mode &= ~FMODE_READABLE;
5889  if (!(fptr->mode & FMODE_WRITABLE))
5890  return rb_io_close(io);
5891  return Qnil;
5892  }
5893 
5894  write_io = GetWriteIO(io);
5895  if (io != write_io) {
5896  rb_io_t *wfptr;
5897  wfptr = rb_io_get_fptr(rb_io_taint_check(write_io));
5898  wfptr->pid = fptr->pid;
5899  fptr->pid = 0;
5900  RFILE(io)->fptr = wfptr;
5901  /* bind to write_io temporarily to get rid of memory/fd leak */
5902  fptr->tied_io_for_writing = 0;
5903  RFILE(write_io)->fptr = fptr;
5904  rb_io_fptr_cleanup(fptr, FALSE);
5905  /* should not finalize fptr because another thread may be reading it */
5906  return Qnil;
5907  }
5908 
5909  if ((fptr->mode & (FMODE_DUPLEX|FMODE_WRITABLE)) == FMODE_WRITABLE) {
5910  rb_raise(rb_eIOError, "closing non-duplex IO for reading");
5911  }
5912  return rb_io_close(io);
5913 }
5914 
5915 /*
5916  * call-seq:
5917  * close_write -> nil
5918  *
5919  * Closes the stream for writing if open for writing;
5920  * returns +nil+.
5921  * See {Open and Closed Streams}[rdoc-ref:IO@Open+and+Closed+Streams].
5922  *
5923  * Flushes any buffered writes to the operating system before closing.
5924  *
5925  * If the stream was opened by IO.popen and is also closed for reading,
5926  * sets global variable <tt>$?</tt> (child exit status).
5927  *
5928  * IO.popen('ruby', 'r+') do |pipe|
5929  * puts pipe.closed?
5930  * pipe.close_read
5931  * puts pipe.closed?
5932  * pipe.close_write
5933  * puts $?
5934  * puts pipe.closed?
5935  * end
5936  *
5937  * Output:
5938  *
5939  * false
5940  * false
5941  * pid 15044 exit 0
5942  * true
5943  *
5944  * Related: IO#close, IO#close_read, IO#closed?.
5945  */
5946 
5947 static VALUE
5948 rb_io_close_write(VALUE io)
5949 {
5950  rb_io_t *fptr;
5951  VALUE write_io;
5952 
5953  write_io = GetWriteIO(io);
5954  fptr = rb_io_get_fptr(rb_io_taint_check(write_io));
5955  if (fptr->fd < 0) return Qnil;
5956  if (is_socket(fptr->fd, fptr->pathv)) {
5957 #ifndef SHUT_WR
5958 # define SHUT_WR 1
5959 #endif
5960  if (shutdown(fptr->fd, SHUT_WR) < 0)
5961  rb_sys_fail_path(fptr->pathv);
5962  fptr->mode &= ~FMODE_WRITABLE;
5963  if (!(fptr->mode & FMODE_READABLE))
5964  return rb_io_close(write_io);
5965  return Qnil;
5966  }
5967 
5968  if ((fptr->mode & (FMODE_DUPLEX|FMODE_READABLE)) == FMODE_READABLE) {
5969  rb_raise(rb_eIOError, "closing non-duplex IO for writing");
5970  }
5971 
5972  if (io != write_io) {
5973  fptr = rb_io_get_fptr(rb_io_taint_check(io));
5974  fptr->tied_io_for_writing = 0;
5975  }
5976  rb_io_close(write_io);
5977  return Qnil;
5978 }
5979 
5980 /*
5981  * call-seq:
5982  * sysseek(offset, whence = IO::SEEK_SET) -> integer
5983  *
5984  * Behaves like IO#seek, except that it:
5985  *
5986  * - Uses low-level system functions.
5987  * - Returns the new position.
5988  *
5989  */
5990 
5991 static VALUE
5992 rb_io_sysseek(int argc, VALUE *argv, VALUE io)
5993 {
5994  VALUE offset, ptrname;
5995  int whence = SEEK_SET;
5996  rb_io_t *fptr;
5997  rb_off_t pos;
5998 
5999  if (rb_scan_args(argc, argv, "11", &offset, &ptrname) == 2) {
6000  whence = interpret_seek_whence(ptrname);
6001  }
6002  pos = NUM2OFFT(offset);
6003  GetOpenFile(io, fptr);
6004  if ((fptr->mode & FMODE_READABLE) &&
6005  (READ_DATA_BUFFERED(fptr) || READ_CHAR_PENDING(fptr))) {
6006  rb_raise(rb_eIOError, "sysseek for buffered IO");
6007  }
6008  if ((fptr->mode & FMODE_WRITABLE) && fptr->wbuf.len) {
6009  rb_warn("sysseek for buffered IO");
6010  }
6011  errno = 0;
6012  pos = lseek(fptr->fd, pos, whence);
6013  if (pos < 0 && errno) rb_sys_fail_path(fptr->pathv);
6014 
6015  return OFFT2NUM(pos);
6016 }
6017 
6018 /*
6019  * call-seq:
6020  * syswrite(object) -> integer
6021  *
6022  * Writes the given +object+ to self, which must be opened for writing (see Modes);
6023  * returns the number bytes written.
6024  * If +object+ is not a string is converted via method to_s:
6025  *
6026  * f = File.new('t.tmp', 'w')
6027  * f.syswrite('foo') # => 3
6028  * f.syswrite(30) # => 2
6029  * f.syswrite(:foo) # => 3
6030  * f.close
6031  *
6032  * This methods should not be used with other stream-writer methods.
6033  *
6034  */
6035 
6036 static VALUE
6037 rb_io_syswrite(VALUE io, VALUE str)
6038 {
6039  VALUE tmp;
6040  rb_io_t *fptr;
6041  long n, len;
6042  const char *ptr;
6043 
6044  if (!RB_TYPE_P(str, T_STRING))
6045  str = rb_obj_as_string(str);
6046 
6047  io = GetWriteIO(io);
6048  GetOpenFile(io, fptr);
6049  rb_io_check_writable(fptr);
6050 
6051  if (fptr->wbuf.len) {
6052  rb_warn("syswrite for buffered IO");
6053  }
6054 
6055  tmp = rb_str_tmp_frozen_acquire(str);
6056  RSTRING_GETMEM(tmp, ptr, len);
6057  n = rb_io_write_memory(fptr, ptr, len);
6058  if (n < 0) rb_sys_fail_path(fptr->pathv);
6059  rb_str_tmp_frozen_release(str, tmp);
6060 
6061  return LONG2FIX(n);
6062 }
6063 
6064 /*
6065  * call-seq:
6066  * sysread(maxlen) -> string
6067  * sysread(maxlen, out_string) -> string
6068  *
6069  * Behaves like IO#readpartial, except that it uses low-level system functions.
6070  *
6071  * This method should not be used with other stream-reader methods.
6072  *
6073  */
6074 
6075 static VALUE
6076 rb_io_sysread(int argc, VALUE *argv, VALUE io)
6077 {
6078  VALUE len, str;
6079  rb_io_t *fptr;
6080  long n, ilen;
6081  struct io_internal_read_struct iis;
6082  int shrinkable;
6083 
6084  rb_scan_args(argc, argv, "11", &len, &str);
6085  ilen = NUM2LONG(len);
6086 
6087  shrinkable = io_setstrbuf(&str, ilen);
6088  if (ilen == 0) return str;
6089 
6090  GetOpenFile(io, fptr);
6092 
6093  if (READ_DATA_BUFFERED(fptr)) {
6094  rb_raise(rb_eIOError, "sysread for buffered IO");
6095  }
6096 
6097  rb_io_check_closed(fptr);
6098 
6099  io_setstrbuf(&str, ilen);
6100  iis.th = rb_thread_current();
6101  iis.fptr = fptr;
6102  iis.nonblock = 0;
6103  iis.fd = fptr->fd;
6104  iis.buf = RSTRING_PTR(str);
6105  iis.capa = ilen;
6106  iis.timeout = NULL;
6107  n = io_read_memory_locktmp(str, &iis);
6108 
6109  if (n < 0) {
6110  rb_sys_fail_path(fptr->pathv);
6111  }
6112 
6113  io_set_read_length(str, n, shrinkable);
6114 
6115  if (n == 0 && ilen > 0) {
6116  rb_eof_error();
6117  }
6118 
6119  return str;
6120 }
6121 
6123  struct rb_io *io;
6124  int fd;
6125  void *buf;
6126  size_t count;
6127  rb_off_t offset;
6128 };
6129 
6130 static VALUE
6131 internal_pread_func(void *_arg)
6132 {
6133  struct prdwr_internal_arg *arg = _arg;
6134 
6135  return (VALUE)pread(arg->fd, arg->buf, arg->count, arg->offset);
6136 }
6137 
6138 static VALUE
6139 pread_internal_call(VALUE _arg)
6140 {
6141  struct prdwr_internal_arg *arg = (struct prdwr_internal_arg *)_arg;
6142 
6143  VALUE scheduler = rb_fiber_scheduler_current();
6144  if (scheduler != Qnil) {
6145  VALUE result = rb_fiber_scheduler_io_pread_memory(scheduler, arg->io->self, arg->offset, arg->buf, arg->count, 0);
6146 
6147  if (!UNDEF_P(result)) {
6148  return rb_fiber_scheduler_io_result_apply(result);
6149  }
6150  }
6151 
6152  return rb_io_blocking_region_wait(arg->io, internal_pread_func, arg, RUBY_IO_READABLE);
6153 }
6154 
6155 /*
6156  * call-seq:
6157  * pread(maxlen, offset) -> string
6158  * pread(maxlen, offset, out_string) -> string
6159  *
6160  * Behaves like IO#readpartial, except that it:
6161  *
6162  * - Reads at the given +offset+ (in bytes).
6163  * - Disregards, and does not modify, the stream's position
6164  * (see {Position}[rdoc-ref:IO@Position]).
6165  * - Bypasses any user space buffering in the stream.
6166  *
6167  * Because this method does not disturb the stream's state
6168  * (its position, in particular), +pread+ allows multiple threads and processes
6169  * to use the same \IO object for reading at various offsets.
6170  *
6171  * f = File.open('t.txt')
6172  * f.read # => "First line\nSecond line\n\nFourth line\nFifth line\n"
6173  * f.pos # => 52
6174  * # Read 12 bytes at offset 0.
6175  * f.pread(12, 0) # => "First line\n"
6176  * # Read 9 bytes at offset 8.
6177  * f.pread(9, 8) # => "ne\nSecon"
6178  * f.close
6179  *
6180  * Not available on some platforms.
6181  *
6182  */
6183 static VALUE
6184 rb_io_pread(int argc, VALUE *argv, VALUE io)
6185 {
6186  VALUE len, offset, str;
6187  rb_io_t *fptr;
6188  ssize_t n;
6189  struct prdwr_internal_arg arg;
6190  int shrinkable;
6191 
6192  rb_scan_args(argc, argv, "21", &len, &offset, &str);
6193  arg.count = NUM2SIZET(len);
6194  arg.offset = NUM2OFFT(offset);
6195 
6196  shrinkable = io_setstrbuf(&str, (long)arg.count);
6197  if (arg.count == 0) return str;
6198  arg.buf = RSTRING_PTR(str);
6199 
6200  GetOpenFile(io, fptr);
6202 
6203  arg.io = fptr;
6204  arg.fd = fptr->fd;
6205  rb_io_check_closed(fptr);
6206 
6207  rb_str_locktmp(str);
6208  n = (ssize_t)rb_ensure(pread_internal_call, (VALUE)&arg, rb_str_unlocktmp, str);
6209 
6210  if (n < 0) {
6211  rb_sys_fail_path(fptr->pathv);
6212  }
6213  io_set_read_length(str, n, shrinkable);
6214  if (n == 0 && arg.count > 0) {
6215  rb_eof_error();
6216  }
6217 
6218  return str;
6219 }
6220 
6221 static VALUE
6222 internal_pwrite_func(void *_arg)
6223 {
6224  struct prdwr_internal_arg *arg = _arg;
6225 
6226  VALUE scheduler = rb_fiber_scheduler_current();
6227  if (scheduler != Qnil) {
6228  VALUE result = rb_fiber_scheduler_io_pwrite_memory(scheduler, arg->io->self, arg->offset, arg->buf, arg->count, 0);
6229 
6230  if (!UNDEF_P(result)) {
6231  return rb_fiber_scheduler_io_result_apply(result);
6232  }
6233  }
6234 
6235 
6236  return (VALUE)pwrite(arg->fd, arg->buf, arg->count, arg->offset);
6237 }
6238 
6239 /*
6240  * call-seq:
6241  * pwrite(object, offset) -> integer
6242  *
6243  * Behaves like IO#write, except that it:
6244  *
6245  * - Writes at the given +offset+ (in bytes).
6246  * - Disregards, and does not modify, the stream's position
6247  * (see {Position}[rdoc-ref:IO@Position]).
6248  * - Bypasses any user space buffering in the stream.
6249  *
6250  * Because this method does not disturb the stream's state
6251  * (its position, in particular), +pwrite+ allows multiple threads and processes
6252  * to use the same \IO object for writing at various offsets.
6253  *
6254  * f = File.open('t.tmp', 'w+')
6255  * # Write 6 bytes at offset 3.
6256  * f.pwrite('ABCDEF', 3) # => 6
6257  * f.rewind
6258  * f.read # => "\u0000\u0000\u0000ABCDEF"
6259  * f.close
6260  *
6261  * Not available on some platforms.
6262  *
6263  */
6264 static VALUE
6265 rb_io_pwrite(VALUE io, VALUE str, VALUE offset)
6266 {
6267  rb_io_t *fptr;
6268  ssize_t n;
6269  struct prdwr_internal_arg arg;
6270  VALUE tmp;
6271 
6272  if (!RB_TYPE_P(str, T_STRING))
6273  str = rb_obj_as_string(str);
6274 
6275  arg.offset = NUM2OFFT(offset);
6276 
6277  io = GetWriteIO(io);
6278  GetOpenFile(io, fptr);
6279  rb_io_check_writable(fptr);
6280 
6281  arg.io = fptr;
6282  arg.fd = fptr->fd;
6283 
6284  tmp = rb_str_tmp_frozen_acquire(str);
6285  arg.buf = RSTRING_PTR(tmp);
6286  arg.count = (size_t)RSTRING_LEN(tmp);
6287 
6288  n = (ssize_t)rb_io_blocking_region_wait(fptr, internal_pwrite_func, &arg, RUBY_IO_WRITABLE);
6289  if (n < 0) rb_sys_fail_path(fptr->pathv);
6290  rb_str_tmp_frozen_release(str, tmp);
6291 
6292  return SSIZET2NUM(n);
6293 }
6294 
6295 VALUE
6297 {
6298  rb_io_t *fptr;
6299 
6300  GetOpenFile(io, fptr);
6301  if (fptr->readconv)
6302  rb_econv_binmode(fptr->readconv);
6303  if (fptr->writeconv)
6304  rb_econv_binmode(fptr->writeconv);
6305  fptr->mode |= FMODE_BINMODE;
6306  fptr->mode &= ~FMODE_TEXTMODE;
6308 #ifdef O_BINARY
6309  if (!fptr->readconv) {
6310  SET_BINARY_MODE_WITH_SEEK_CUR(fptr);
6311  }
6312  else {
6313  setmode(fptr->fd, O_BINARY);
6314  }
6315 #endif
6316  return io;
6317 }
6318 
6319 static void
6320 io_ascii8bit_binmode(rb_io_t *fptr)
6321 {
6322  if (fptr->readconv) {
6323  rb_econv_close(fptr->readconv);
6324  fptr->readconv = NULL;
6325  }
6326  if (fptr->writeconv) {
6327  rb_econv_close(fptr->writeconv);
6328  fptr->writeconv = NULL;
6329  }
6330  fptr->mode |= FMODE_BINMODE;
6331  fptr->mode &= ~FMODE_TEXTMODE;
6332  SET_BINARY_MODE_WITH_SEEK_CUR(fptr);
6333 
6334  fptr->encs.enc = rb_ascii8bit_encoding();
6335  fptr->encs.enc2 = NULL;
6336  fptr->encs.ecflags = 0;
6337  fptr->encs.ecopts = Qnil;
6338  clear_codeconv(fptr);
6339 }
6340 
6341 VALUE
6343 {
6344  rb_io_t *fptr;
6345 
6346  GetOpenFile(io, fptr);
6347  io_ascii8bit_binmode(fptr);
6348 
6349  return io;
6350 }
6351 
6352 /*
6353  * call-seq:
6354  * binmode -> self
6355  *
6356  * Sets the stream's data mode as binary
6357  * (see {Data Mode}[rdoc-ref:File@Data+Mode]).
6358  *
6359  * A stream's data mode may not be changed from binary to text.
6360  *
6361  */
6362 
6363 static VALUE
6364 rb_io_binmode_m(VALUE io)
6365 {
6366  VALUE write_io;
6367 
6369 
6370  write_io = GetWriteIO(io);
6371  if (write_io != io)
6372  rb_io_ascii8bit_binmode(write_io);
6373  return io;
6374 }
6375 
6376 /*
6377  * call-seq:
6378  * binmode? -> true or false
6379  *
6380  * Returns +true+ if the stream is on binary mode, +false+ otherwise.
6381  * See {Data Mode}[rdoc-ref:File@Data+Mode].
6382  *
6383  */
6384 static VALUE
6385 rb_io_binmode_p(VALUE io)
6386 {
6387  rb_io_t *fptr;
6388  GetOpenFile(io, fptr);
6389  return RBOOL(fptr->mode & FMODE_BINMODE);
6390 }
6391 
6392 static const char*
6393 rb_io_fmode_modestr(int fmode)
6394 {
6395  if (fmode & FMODE_APPEND) {
6396  if ((fmode & FMODE_READWRITE) == FMODE_READWRITE) {
6397  return MODE_BTMODE("a+", "ab+", "at+");
6398  }
6399  return MODE_BTMODE("a", "ab", "at");
6400  }
6401  switch (fmode & FMODE_READWRITE) {
6402  default:
6403  rb_raise(rb_eArgError, "invalid access fmode 0x%x", fmode);
6404  case FMODE_READABLE:
6405  return MODE_BTMODE("r", "rb", "rt");
6406  case FMODE_WRITABLE:
6407  return MODE_BTXMODE("w", "wb", "wt", "wx", "wbx", "wtx");
6408  case FMODE_READWRITE:
6409  if (fmode & FMODE_CREATE) {
6410  return MODE_BTXMODE("w+", "wb+", "wt+", "w+x", "wb+x", "wt+x");
6411  }
6412  return MODE_BTMODE("r+", "rb+", "rt+");
6413  }
6414 }
6415 
6416 static const char bom_prefix[] = "bom|";
6417 static const char utf_prefix[] = "utf-";
6418 enum {bom_prefix_len = (int)sizeof(bom_prefix) - 1};
6419 enum {utf_prefix_len = (int)sizeof(utf_prefix) - 1};
6420 
6421 static int
6422 io_encname_bom_p(const char *name, long len)
6423 {
6424  return len > bom_prefix_len && STRNCASECMP(name, bom_prefix, bom_prefix_len) == 0;
6425 }
6426 
6427 int
6428 rb_io_modestr_fmode(const char *modestr)
6429 {
6430  int fmode = 0;
6431  const char *m = modestr, *p = NULL;
6432 
6433  switch (*m++) {
6434  case 'r':
6435  fmode |= FMODE_READABLE;
6436  break;
6437  case 'w':
6439  break;
6440  case 'a':
6442  break;
6443  default:
6444  goto error;
6445  }
6446 
6447  while (*m) {
6448  switch (*m++) {
6449  case 'b':
6450  fmode |= FMODE_BINMODE;
6451  break;
6452  case 't':
6453  fmode |= FMODE_TEXTMODE;
6454  break;
6455  case '+':
6456  fmode |= FMODE_READWRITE;
6457  break;
6458  case 'x':
6459  if (modestr[0] != 'w')
6460  goto error;
6461  fmode |= FMODE_EXCL;
6462  break;
6463  default:
6464  goto error;
6465  case ':':
6466  p = strchr(m, ':');
6467  if (io_encname_bom_p(m, p ? (long)(p - m) : (long)strlen(m)))
6468  fmode |= FMODE_SETENC_BY_BOM;
6469  goto finished;
6470  }
6471  }
6472 
6473  finished:
6474  if ((fmode & FMODE_BINMODE) && (fmode & FMODE_TEXTMODE))
6475  goto error;
6476 
6477  return fmode;
6478 
6479  error:
6480  rb_raise(rb_eArgError, "invalid access mode %s", modestr);
6482 }
6483 
6484 int
6485 rb_io_oflags_fmode(int oflags)
6486 {
6487  int fmode = 0;
6488 
6489  switch (oflags & O_ACCMODE) {
6490  case O_RDONLY:
6491  fmode = FMODE_READABLE;
6492  break;
6493  case O_WRONLY:
6494  fmode = FMODE_WRITABLE;
6495  break;
6496  case O_RDWR:
6497  fmode = FMODE_READWRITE;
6498  break;
6499  }
6500 
6501  if (oflags & O_APPEND) {
6502  fmode |= FMODE_APPEND;
6503  }
6504  if (oflags & O_TRUNC) {
6505  fmode |= FMODE_TRUNC;
6506  }
6507  if (oflags & O_CREAT) {
6508  fmode |= FMODE_CREATE;
6509  }
6510  if (oflags & O_EXCL) {
6511  fmode |= FMODE_EXCL;
6512  }
6513 #ifdef O_BINARY
6514  if (oflags & O_BINARY) {
6515  fmode |= FMODE_BINMODE;
6516  }
6517 #endif
6518 
6519  return fmode;
6520 }
6521 
6522 static int
6523 rb_io_fmode_oflags(int fmode)
6524 {
6525  int oflags = 0;
6526 
6527  switch (fmode & FMODE_READWRITE) {
6528  case FMODE_READABLE:
6529  oflags |= O_RDONLY;
6530  break;
6531  case FMODE_WRITABLE:
6532  oflags |= O_WRONLY;
6533  break;
6534  case FMODE_READWRITE:
6535  oflags |= O_RDWR;
6536  break;
6537  }
6538 
6539  if (fmode & FMODE_APPEND) {
6540  oflags |= O_APPEND;
6541  }
6542  if (fmode & FMODE_TRUNC) {
6543  oflags |= O_TRUNC;
6544  }
6545  if (fmode & FMODE_CREATE) {
6546  oflags |= O_CREAT;
6547  }
6548  if (fmode & FMODE_EXCL) {
6549  oflags |= O_EXCL;
6550  }
6551 #ifdef O_BINARY
6552  if (fmode & FMODE_BINMODE) {
6553  oflags |= O_BINARY;
6554  }
6555 #endif
6556 
6557  return oflags;
6558 }
6559 
6560 int
6561 rb_io_modestr_oflags(const char *modestr)
6562 {
6563  return rb_io_fmode_oflags(rb_io_modestr_fmode(modestr));
6564 }
6565 
6566 static const char*
6567 rb_io_oflags_modestr(int oflags)
6568 {
6569 #ifdef O_BINARY
6570 # define MODE_BINARY(a,b) ((oflags & O_BINARY) ? (b) : (a))
6571 #else
6572 # define MODE_BINARY(a,b) (a)
6573 #endif
6574  int accmode;
6575  if (oflags & O_EXCL) {
6576  rb_raise(rb_eArgError, "exclusive access mode is not supported");
6577  }
6578  accmode = oflags & (O_RDONLY|O_WRONLY|O_RDWR);
6579  if (oflags & O_APPEND) {
6580  if (accmode == O_WRONLY) {
6581  return MODE_BINARY("a", "ab");
6582  }
6583  if (accmode == O_RDWR) {
6584  return MODE_BINARY("a+", "ab+");
6585  }
6586  }
6587  switch (accmode) {
6588  default:
6589  rb_raise(rb_eArgError, "invalid access oflags 0x%x", oflags);
6590  case O_RDONLY:
6591  return MODE_BINARY("r", "rb");
6592  case O_WRONLY:
6593  return MODE_BINARY("w", "wb");
6594  case O_RDWR:
6595  if (oflags & O_TRUNC) {
6596  return MODE_BINARY("w+", "wb+");
6597  }
6598  return MODE_BINARY("r+", "rb+");
6599  }
6600 }
6601 
6602 /*
6603  * Convert external/internal encodings to enc/enc2
6604  * NULL => use default encoding
6605  * Qnil => no encoding specified (internal only)
6606  */
6607 static void
6608 rb_io_ext_int_to_encs(rb_encoding *ext, rb_encoding *intern, rb_encoding **enc, rb_encoding **enc2, int fmode)
6609 {
6610  int default_ext = 0;
6611 
6612  if (ext == NULL) {
6614  default_ext = 1;
6615  }
6616  if (rb_is_ascii8bit_enc(ext)) {
6617  /* If external is ASCII-8BIT, no transcoding */
6618  intern = NULL;
6619  }
6620  else if (intern == NULL) {
6621  intern = rb_default_internal_encoding();
6622  }
6623  if (intern == NULL || intern == (rb_encoding *)Qnil ||
6624  (!(fmode & FMODE_SETENC_BY_BOM) && (intern == ext))) {
6625  /* No internal encoding => use external + no transcoding */
6626  *enc = (default_ext && intern != ext) ? NULL : ext;
6627  *enc2 = NULL;
6628  }
6629  else {
6630  *enc = intern;
6631  *enc2 = ext;
6632  }
6633 }
6634 
6635 static void
6636 unsupported_encoding(const char *name, rb_encoding *enc)
6637 {
6638  rb_enc_warn(enc, "Unsupported encoding %s ignored", name);
6639 }
6640 
6641 static void
6642 parse_mode_enc(const char *estr, rb_encoding *estr_enc,
6643  rb_encoding **enc_p, rb_encoding **enc2_p, int *fmode_p)
6644 {
6645  const char *p;
6646  char encname[ENCODING_MAXNAMELEN+1];
6647  int idx, idx2;
6648  int fmode = fmode_p ? *fmode_p : 0;
6649  rb_encoding *ext_enc, *int_enc;
6650  long len;
6651 
6652  /* parse estr as "enc" or "enc2:enc" or "enc:-" */
6653 
6654  p = strrchr(estr, ':');
6655  len = p ? (p++ - estr) : (long)strlen(estr);
6656  if ((fmode & FMODE_SETENC_BY_BOM) || io_encname_bom_p(estr, len)) {
6657  estr += bom_prefix_len;
6658  len -= bom_prefix_len;
6659  if (!STRNCASECMP(estr, utf_prefix, utf_prefix_len)) {
6660  fmode |= FMODE_SETENC_BY_BOM;
6661  }
6662  else {
6663  rb_enc_warn(estr_enc, "BOM with non-UTF encoding %s is nonsense", estr);
6664  fmode &= ~FMODE_SETENC_BY_BOM;
6665  }
6666  }
6667  if (len == 0 || len > ENCODING_MAXNAMELEN) {
6668  idx = -1;
6669  }
6670  else {
6671  if (p) {
6672  memcpy(encname, estr, len);
6673  encname[len] = '\0';
6674  estr = encname;
6675  }
6676  idx = rb_enc_find_index(estr);
6677  }
6678  if (fmode_p) *fmode_p = fmode;
6679 
6680  if (idx >= 0)
6681  ext_enc = rb_enc_from_index(idx);
6682  else {
6683  if (idx != -2)
6684  unsupported_encoding(estr, estr_enc);
6685  ext_enc = NULL;
6686  }
6687 
6688  int_enc = NULL;
6689  if (p) {
6690  if (*p == '-' && *(p+1) == '\0') {
6691  /* Special case - "-" => no transcoding */
6692  int_enc = (rb_encoding *)Qnil;
6693  }
6694  else {
6695  idx2 = rb_enc_find_index(p);
6696  if (idx2 < 0)
6697  unsupported_encoding(p, estr_enc);
6698  else if (!(fmode & FMODE_SETENC_BY_BOM) && (idx2 == idx)) {
6699  int_enc = (rb_encoding *)Qnil;
6700  }
6701  else
6702  int_enc = rb_enc_from_index(idx2);
6703  }
6704  }
6705 
6706  rb_io_ext_int_to_encs(ext_enc, int_enc, enc_p, enc2_p, fmode);
6707 }
6708 
6709 int
6710 rb_io_extract_encoding_option(VALUE opt, rb_encoding **enc_p, rb_encoding **enc2_p, int *fmode_p)
6711 {
6712  VALUE encoding=Qnil, extenc=Qundef, intenc=Qundef, tmp;
6713  int extracted = 0;
6714  rb_encoding *extencoding = NULL;
6715  rb_encoding *intencoding = NULL;
6716 
6717  if (!NIL_P(opt)) {
6718  VALUE v;
6719  v = rb_hash_lookup2(opt, sym_encoding, Qnil);
6720  if (v != Qnil) encoding = v;
6721  v = rb_hash_lookup2(opt, sym_extenc, Qundef);
6722  if (v != Qnil) extenc = v;
6723  v = rb_hash_lookup2(opt, sym_intenc, Qundef);
6724  if (!UNDEF_P(v)) intenc = v;
6725  }
6726  if ((!UNDEF_P(extenc) || !UNDEF_P(intenc)) && !NIL_P(encoding)) {
6727  if (!NIL_P(ruby_verbose)) {
6728  int idx = rb_to_encoding_index(encoding);
6729  if (idx >= 0) encoding = rb_enc_from_encoding(rb_enc_from_index(idx));
6730  rb_warn("Ignoring encoding parameter '%"PRIsVALUE"': %s_encoding is used",
6731  encoding, UNDEF_P(extenc) ? "internal" : "external");
6732  }
6733  encoding = Qnil;
6734  }
6735  if (!UNDEF_P(extenc) && !NIL_P(extenc)) {
6736  extencoding = rb_to_encoding(extenc);
6737  }
6738  if (!UNDEF_P(intenc)) {
6739  if (NIL_P(intenc)) {
6740  /* internal_encoding: nil => no transcoding */
6741  intencoding = (rb_encoding *)Qnil;
6742  }
6743  else if (!NIL_P(tmp = rb_check_string_type(intenc))) {
6744  char *p = StringValueCStr(tmp);
6745 
6746  if (*p == '-' && *(p+1) == '\0') {
6747  /* Special case - "-" => no transcoding */
6748  intencoding = (rb_encoding *)Qnil;
6749  }
6750  else {
6751  intencoding = rb_to_encoding(intenc);
6752  }
6753  }
6754  else {
6755  intencoding = rb_to_encoding(intenc);
6756  }
6757  if (extencoding == intencoding) {
6758  intencoding = (rb_encoding *)Qnil;
6759  }
6760  }
6761  if (!NIL_P(encoding)) {
6762  extracted = 1;
6763  if (!NIL_P(tmp = rb_check_string_type(encoding))) {
6764  parse_mode_enc(StringValueCStr(tmp), rb_enc_get(tmp),
6765  enc_p, enc2_p, fmode_p);
6766  }
6767  else {
6768  rb_io_ext_int_to_encs(rb_to_encoding(encoding), NULL, enc_p, enc2_p, 0);
6769  }
6770  }
6771  else if (!UNDEF_P(extenc) || !UNDEF_P(intenc)) {
6772  extracted = 1;
6773  rb_io_ext_int_to_encs(extencoding, intencoding, enc_p, enc2_p, 0);
6774  }
6775  return extracted;
6776 }
6777 
6778 static void
6779 validate_enc_binmode(int *fmode_p, int ecflags, rb_encoding *enc, rb_encoding *enc2)
6780 {
6781  int fmode = *fmode_p;
6782 
6783  if ((fmode & FMODE_READABLE) &&
6784  !enc2 &&
6785  !(fmode & FMODE_BINMODE) &&
6787  rb_raise(rb_eArgError, "ASCII incompatible encoding needs binmode");
6788 
6789  if ((fmode & FMODE_BINMODE) && (ecflags & ECONV_NEWLINE_DECORATOR_MASK)) {
6790  rb_raise(rb_eArgError, "newline decorator with binary mode");
6791  }
6792  if (!(fmode & FMODE_BINMODE) &&
6793  (DEFAULT_TEXTMODE || (ecflags & ECONV_NEWLINE_DECORATOR_MASK))) {
6794  fmode |= FMODE_TEXTMODE;
6795  *fmode_p = fmode;
6796  }
6797 #if !DEFAULT_TEXTMODE
6798  else if (!(ecflags & ECONV_NEWLINE_DECORATOR_MASK)) {
6799  fmode &= ~FMODE_TEXTMODE;
6800  *fmode_p = fmode;
6801  }
6802 #endif
6803 }
6804 
6805 static void
6806 extract_binmode(VALUE opthash, int *fmode)
6807 {
6808  if (!NIL_P(opthash)) {
6809  VALUE v;
6810  v = rb_hash_aref(opthash, sym_textmode);
6811  if (!NIL_P(v)) {
6812  if (*fmode & FMODE_TEXTMODE)
6813  rb_raise(rb_eArgError, "textmode specified twice");
6814  if (*fmode & FMODE_BINMODE)
6815  rb_raise(rb_eArgError, "both textmode and binmode specified");
6816  if (RTEST(v))
6817  *fmode |= FMODE_TEXTMODE;
6818  }
6819  v = rb_hash_aref(opthash, sym_binmode);
6820  if (!NIL_P(v)) {
6821  if (*fmode & FMODE_BINMODE)
6822  rb_raise(rb_eArgError, "binmode specified twice");
6823  if (*fmode & FMODE_TEXTMODE)
6824  rb_raise(rb_eArgError, "both textmode and binmode specified");
6825  if (RTEST(v))
6826  *fmode |= FMODE_BINMODE;
6827  }
6828 
6829  if ((*fmode & FMODE_BINMODE) && (*fmode & FMODE_TEXTMODE))
6830  rb_raise(rb_eArgError, "both textmode and binmode specified");
6831  }
6832 }
6833 
6834 void
6835 rb_io_extract_modeenc(VALUE *vmode_p, VALUE *vperm_p, VALUE opthash,
6836  int *oflags_p, int *fmode_p, struct rb_io_encoding *convconfig_p)
6837 {
6838  VALUE vmode;
6839  int oflags, fmode;
6840  rb_encoding *enc, *enc2;
6841  int ecflags;
6842  VALUE ecopts;
6843  int has_enc = 0, has_vmode = 0;
6844  VALUE intmode;
6845 
6846  vmode = *vmode_p;
6847 
6848  /* Set to defaults */
6849  rb_io_ext_int_to_encs(NULL, NULL, &enc, &enc2, 0);
6850 
6851  vmode_handle:
6852  if (NIL_P(vmode)) {
6853  fmode = FMODE_READABLE;
6854  oflags = O_RDONLY;
6855  }
6856  else if (!NIL_P(intmode = rb_check_to_integer(vmode, "to_int"))) {
6857  vmode = intmode;
6858  oflags = NUM2INT(intmode);
6859  fmode = rb_io_oflags_fmode(oflags);
6860  }
6861  else {
6862  const char *p;
6863 
6864  StringValue(vmode);
6865  p = StringValueCStr(vmode);
6866  fmode = rb_io_modestr_fmode(p);
6867  oflags = rb_io_fmode_oflags(fmode);
6868  p = strchr(p, ':');
6869  if (p) {
6870  has_enc = 1;
6871  parse_mode_enc(p+1, rb_enc_get(vmode), &enc, &enc2, &fmode);
6872  }
6873  else {
6874  rb_encoding *e;
6875 
6876  e = (fmode & FMODE_BINMODE) ? rb_ascii8bit_encoding() : NULL;
6877  rb_io_ext_int_to_encs(e, NULL, &enc, &enc2, fmode);
6878  }
6879  }
6880 
6881  if (NIL_P(opthash)) {
6882  ecflags = (fmode & FMODE_READABLE) ?
6883  MODE_BTMODE(ECONV_DEFAULT_NEWLINE_DECORATOR,
6885 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
6886  ecflags |= (fmode & FMODE_WRITABLE) ?
6887  MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE,
6888  0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE) : 0;
6889 #endif
6890  SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
6891  ecopts = Qnil;
6892  if (fmode & FMODE_BINMODE) {
6893 #ifdef O_BINARY
6894  oflags |= O_BINARY;
6895 #endif
6896  if (!has_enc)
6897  rb_io_ext_int_to_encs(rb_ascii8bit_encoding(), NULL, &enc, &enc2, fmode);
6898  }
6899 #if DEFAULT_TEXTMODE
6900  else if (NIL_P(vmode)) {
6901  fmode |= DEFAULT_TEXTMODE;
6902  }
6903 #endif
6904  }
6905  else {
6906  VALUE v;
6907  if (!has_vmode) {
6908  v = rb_hash_aref(opthash, sym_mode);
6909  if (!NIL_P(v)) {
6910  if (!NIL_P(vmode)) {
6911  rb_raise(rb_eArgError, "mode specified twice");
6912  }
6913  has_vmode = 1;
6914  vmode = v;
6915  goto vmode_handle;
6916  }
6917  }
6918  v = rb_hash_aref(opthash, sym_flags);
6919  if (!NIL_P(v)) {
6920  v = rb_to_int(v);
6921  oflags |= NUM2INT(v);
6922  vmode = INT2NUM(oflags);
6923  fmode = rb_io_oflags_fmode(oflags);
6924  }
6925  extract_binmode(opthash, &fmode);
6926  if (fmode & FMODE_BINMODE) {
6927 #ifdef O_BINARY
6928  oflags |= O_BINARY;
6929 #endif
6930  if (!has_enc)
6931  rb_io_ext_int_to_encs(rb_ascii8bit_encoding(), NULL, &enc, &enc2, fmode);
6932  }
6933 #if DEFAULT_TEXTMODE
6934  else if (NIL_P(vmode)) {
6935  fmode |= DEFAULT_TEXTMODE;
6936  }
6937 #endif
6938  v = rb_hash_aref(opthash, sym_perm);
6939  if (!NIL_P(v)) {
6940  if (vperm_p) {
6941  if (!NIL_P(*vperm_p)) {
6942  rb_raise(rb_eArgError, "perm specified twice");
6943  }
6944  *vperm_p = v;
6945  }
6946  else {
6947  /* perm no use, just ignore */
6948  }
6949  }
6950  ecflags = (fmode & FMODE_READABLE) ?
6951  MODE_BTMODE(ECONV_DEFAULT_NEWLINE_DECORATOR,
6953 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
6954  ecflags |= (fmode & FMODE_WRITABLE) ?
6955  MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE,
6956  0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE) : 0;
6957 #endif
6958 
6959  if (rb_io_extract_encoding_option(opthash, &enc, &enc2, &fmode)) {
6960  if (has_enc) {
6961  rb_raise(rb_eArgError, "encoding specified twice");
6962  }
6963  }
6964  SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
6965  ecflags = rb_econv_prepare_options(opthash, &ecopts, ecflags);
6966  }
6967 
6968  validate_enc_binmode(&fmode, ecflags, enc, enc2);
6969 
6970  *vmode_p = vmode;
6971 
6972  *oflags_p = oflags;
6973  *fmode_p = fmode;
6974  convconfig_p->enc = enc;
6975  convconfig_p->enc2 = enc2;
6976  convconfig_p->ecflags = ecflags;
6977  convconfig_p->ecopts = ecopts;
6978 }
6979 
6981  VALUE fname;
6982  int oflags;
6983  mode_t perm;
6984 };
6985 
6986 static void *
6987 sysopen_func(void *ptr)
6988 {
6989  const struct sysopen_struct *data = ptr;
6990  const char *fname = RSTRING_PTR(data->fname);
6991  return (void *)(VALUE)rb_cloexec_open(fname, data->oflags, data->perm);
6992 }
6993 
6994 static inline int
6995 rb_sysopen_internal(struct sysopen_struct *data)
6996 {
6997  int fd;
6998  do {
6999  fd = IO_WITHOUT_GVL_INT(sysopen_func, data);
7000  } while (fd < 0 && errno == EINTR);
7001  if (0 <= fd)
7002  rb_update_max_fd(fd);
7003  return fd;
7004 }
7005 
7006 static int
7007 rb_sysopen(VALUE fname, int oflags, mode_t perm)
7008 {
7009  int fd = -1;
7010  struct sysopen_struct data;
7011 
7012  data.fname = rb_str_encode_ospath(fname);
7013  StringValueCStr(data.fname);
7014  data.oflags = oflags;
7015  data.perm = perm;
7016 
7017  TRY_WITH_GC((fd = rb_sysopen_internal(&data)) >= 0) {
7018  rb_syserr_fail_path(first_errno, fname);
7019  }
7020  return fd;
7021 }
7022 
7023 static inline FILE *
7024 fdopen_internal(int fd, const char *modestr)
7025 {
7026  FILE *file;
7027 
7028 #if defined(__sun)
7029  errno = 0;
7030 #endif
7031  file = fdopen(fd, modestr);
7032  if (!file) {
7033 #ifdef _WIN32
7034  if (errno == 0) errno = EINVAL;
7035 #elif defined(__sun)
7036  if (errno == 0) errno = EMFILE;
7037 #endif
7038  }
7039  return file;
7040 }
7041 
7042 FILE *
7043 rb_fdopen(int fd, const char *modestr)
7044 {
7045  FILE *file = 0;
7046 
7047  TRY_WITH_GC((file = fdopen_internal(fd, modestr)) != 0) {
7048  rb_syserr_fail(first_errno, 0);
7049  }
7050 
7051  /* xxx: should be _IONBF? A buffer in FILE may have trouble. */
7052 #ifdef USE_SETVBUF
7053  if (setvbuf(file, NULL, _IOFBF, 0) != 0)
7054  rb_warn("setvbuf() can't be honoured (fd=%d)", fd);
7055 #endif
7056  return file;
7057 }
7058 
7059 static int
7060 io_check_tty(rb_io_t *fptr)
7061 {
7062  int t = isatty(fptr->fd);
7063  if (t)
7064  fptr->mode |= FMODE_TTY|FMODE_DUPLEX;
7065  return t;
7066 }
7067 
7068 static VALUE rb_io_internal_encoding(VALUE);
7069 static void io_encoding_set(rb_io_t *, VALUE, VALUE, VALUE);
7070 
7071 static int
7072 io_strip_bom(VALUE io)
7073 {
7074  VALUE b1, b2, b3, b4;
7075  rb_io_t *fptr;
7076 
7077  GetOpenFile(io, fptr);
7078  if (!(fptr->mode & FMODE_READABLE)) return 0;
7079  if (NIL_P(b1 = rb_io_getbyte(io))) return 0;
7080  switch (b1) {
7081  case INT2FIX(0xEF):
7082  if (NIL_P(b2 = rb_io_getbyte(io))) break;
7083  if (b2 == INT2FIX(0xBB) && !NIL_P(b3 = rb_io_getbyte(io))) {
7084  if (b3 == INT2FIX(0xBF)) {
7085  return rb_utf8_encindex();
7086  }
7087  rb_io_ungetbyte(io, b3);
7088  }
7089  rb_io_ungetbyte(io, b2);
7090  break;
7091 
7092  case INT2FIX(0xFE):
7093  if (NIL_P(b2 = rb_io_getbyte(io))) break;
7094  if (b2 == INT2FIX(0xFF)) {
7095  return ENCINDEX_UTF_16BE;
7096  }
7097  rb_io_ungetbyte(io, b2);
7098  break;
7099 
7100  case INT2FIX(0xFF):
7101  if (NIL_P(b2 = rb_io_getbyte(io))) break;
7102  if (b2 == INT2FIX(0xFE)) {
7103  b3 = rb_io_getbyte(io);
7104  if (b3 == INT2FIX(0) && !NIL_P(b4 = rb_io_getbyte(io))) {
7105  if (b4 == INT2FIX(0)) {
7106  return ENCINDEX_UTF_32LE;
7107  }
7108  rb_io_ungetbyte(io, b4);
7109  }
7110  rb_io_ungetbyte(io, b3);
7111  return ENCINDEX_UTF_16LE;
7112  }
7113  rb_io_ungetbyte(io, b2);
7114  break;
7115 
7116  case INT2FIX(0):
7117  if (NIL_P(b2 = rb_io_getbyte(io))) break;
7118  if (b2 == INT2FIX(0) && !NIL_P(b3 = rb_io_getbyte(io))) {
7119  if (b3 == INT2FIX(0xFE) && !NIL_P(b4 = rb_io_getbyte(io))) {
7120  if (b4 == INT2FIX(0xFF)) {
7121  return ENCINDEX_UTF_32BE;
7122  }
7123  rb_io_ungetbyte(io, b4);
7124  }
7125  rb_io_ungetbyte(io, b3);
7126  }
7127  rb_io_ungetbyte(io, b2);
7128  break;
7129  }
7130  rb_io_ungetbyte(io, b1);
7131  return 0;
7132 }
7133 
7134 static rb_encoding *
7135 io_set_encoding_by_bom(VALUE io)
7136 {
7137  int idx = io_strip_bom(io);
7138  rb_io_t *fptr;
7139  rb_encoding *extenc = NULL;
7140 
7141  GetOpenFile(io, fptr);
7142  if (idx) {
7143  extenc = rb_enc_from_index(idx);
7144  io_encoding_set(fptr, rb_enc_from_encoding(extenc),
7145  rb_io_internal_encoding(io), Qnil);
7146  }
7147  else {
7148  fptr->encs.enc2 = NULL;
7149  }
7150  return extenc;
7151 }
7152 
7153 static VALUE
7154 rb_file_open_generic(VALUE io, VALUE filename, int oflags, int fmode,
7155  const struct rb_io_encoding *convconfig, mode_t perm)
7156 {
7157  VALUE pathv;
7158  rb_io_t *fptr;
7159  struct rb_io_encoding cc;
7160  if (!convconfig) {
7161  /* Set to default encodings */
7162  rb_io_ext_int_to_encs(NULL, NULL, &cc.enc, &cc.enc2, fmode);
7163  cc.ecflags = 0;
7164  cc.ecopts = Qnil;
7165  convconfig = &cc;
7166  }
7167  validate_enc_binmode(&fmode, convconfig->ecflags,
7168  convconfig->enc, convconfig->enc2);
7169 
7170  MakeOpenFile(io, fptr);
7171  fptr->mode = fmode;
7172  fptr->encs = *convconfig;
7173  pathv = rb_str_new_frozen(filename);
7174 #ifdef O_TMPFILE
7175  if (!(oflags & O_TMPFILE)) {
7176  fptr->pathv = pathv;
7177  }
7178 #else
7179  fptr->pathv = pathv;
7180 #endif
7181  fptr->fd = rb_sysopen(pathv, oflags, perm);
7182  io_check_tty(fptr);
7183  if (fmode & FMODE_SETENC_BY_BOM) io_set_encoding_by_bom(io);
7184 
7185  return io;
7186 }
7187 
7188 static VALUE
7189 rb_file_open_internal(VALUE io, VALUE filename, const char *modestr)
7190 {
7191  int fmode = rb_io_modestr_fmode(modestr);
7192  const char *p = strchr(modestr, ':');
7193  struct rb_io_encoding convconfig;
7194 
7195  if (p) {
7196  parse_mode_enc(p+1, rb_usascii_encoding(),
7197  &convconfig.enc, &convconfig.enc2, &fmode);
7198  }
7199  else {
7200  rb_encoding *e;
7201  /* Set to default encodings */
7202 
7203  e = (fmode & FMODE_BINMODE) ? rb_ascii8bit_encoding() : NULL;
7204  rb_io_ext_int_to_encs(e, NULL, &convconfig.enc, &convconfig.enc2, fmode);
7205  }
7206 
7207  convconfig.ecflags = (fmode & FMODE_READABLE) ?
7208  MODE_BTMODE(ECONV_DEFAULT_NEWLINE_DECORATOR,
7210 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
7211  convconfig.ecflags |= (fmode & FMODE_WRITABLE) ?
7212  MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE,
7213  0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE) : 0;
7214 #endif
7215  SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(convconfig.enc2, convconfig.ecflags);
7216  convconfig.ecopts = Qnil;
7217 
7218  return rb_file_open_generic(io, filename,
7219  rb_io_fmode_oflags(fmode),
7220  fmode,
7221  &convconfig,
7222  0666);
7223 }
7224 
7225 VALUE
7226 rb_file_open_str(VALUE fname, const char *modestr)
7227 {
7228  FilePathValue(fname);
7229  return rb_file_open_internal(io_alloc(rb_cFile), fname, modestr);
7230 }
7231 
7232 VALUE
7233 rb_file_open(const char *fname, const char *modestr)
7234 {
7235  return rb_file_open_internal(io_alloc(rb_cFile), rb_str_new_cstr(fname), modestr);
7236 }
7237 
7238 #if defined(__CYGWIN__) || !defined(HAVE_WORKING_FORK)
7239 static struct pipe_list {
7240  rb_io_t *fptr;
7241  struct pipe_list *next;
7242 } *pipe_list;
7243 
7244 static void
7245 pipe_add_fptr(rb_io_t *fptr)
7246 {
7247  struct pipe_list *list;
7248 
7249  list = ALLOC(struct pipe_list);
7250  list->fptr = fptr;
7251  list->next = pipe_list;
7252  pipe_list = list;
7253 }
7254 
7255 static void
7256 pipe_del_fptr(rb_io_t *fptr)
7257 {
7258  struct pipe_list **prev = &pipe_list;
7259  struct pipe_list *tmp;
7260 
7261  while ((tmp = *prev) != 0) {
7262  if (tmp->fptr == fptr) {
7263  *prev = tmp->next;
7264  free(tmp);
7265  return;
7266  }
7267  prev = &tmp->next;
7268  }
7269 }
7270 
7271 #if defined (_WIN32) || defined(__CYGWIN__)
7272 static void
7273 pipe_atexit(void)
7274 {
7275  struct pipe_list *list = pipe_list;
7276  struct pipe_list *tmp;
7277 
7278  while (list) {
7279  tmp = list->next;
7280  rb_io_fptr_finalize(list->fptr);
7281  list = tmp;
7282  }
7283 }
7284 #endif
7285 
7286 static void
7287 pipe_finalize(rb_io_t *fptr, int noraise)
7288 {
7289 #if !defined(HAVE_WORKING_FORK) && !defined(_WIN32)
7290  int status = 0;
7291  if (fptr->stdio_file) {
7292  status = pclose(fptr->stdio_file);
7293  }
7294  fptr->fd = -1;
7295  fptr->stdio_file = 0;
7296  rb_last_status_set(status, fptr->pid);
7297 #else
7298  fptr_finalize(fptr, noraise);
7299 #endif
7300  pipe_del_fptr(fptr);
7301 }
7302 #endif
7303 
7304 static void
7305 fptr_copy_finalizer(rb_io_t *fptr, const rb_io_t *orig)
7306 {
7307 #if defined(__CYGWIN__) || !defined(HAVE_WORKING_FORK)
7308  void (*const old_finalize)(struct rb_io*,int) = fptr->finalize;
7309 
7310  if (old_finalize == orig->finalize) return;
7311 #endif
7312 
7313  fptr->finalize = orig->finalize;
7314 
7315 #if defined(__CYGWIN__) || !defined(HAVE_WORKING_FORK)
7316  if (old_finalize != pipe_finalize) {
7317  struct pipe_list *list;
7318  for (list = pipe_list; list; list = list->next) {
7319  if (list->fptr == fptr) break;
7320  }
7321  if (!list) pipe_add_fptr(fptr);
7322  }
7323  else {
7324  pipe_del_fptr(fptr);
7325  }
7326 #endif
7327 }
7328 
7329 void
7331 {
7333  fptr->mode |= FMODE_SYNC;
7334 }
7335 
7336 void
7337 rb_io_unbuffered(rb_io_t *fptr)
7338 {
7339  rb_io_synchronized(fptr);
7340 }
7341 
7342 int
7343 rb_pipe(int *pipes)
7344 {
7345  int ret;
7346  TRY_WITH_GC((ret = rb_cloexec_pipe(pipes)) >= 0);
7347  if (ret == 0) {
7348  rb_update_max_fd(pipes[0]);
7349  rb_update_max_fd(pipes[1]);
7350  }
7351  return ret;
7352 }
7353 
7354 #ifdef _WIN32
7355 #define HAVE_SPAWNV 1
7356 #define spawnv(mode, cmd, args) rb_w32_uaspawn((mode), (cmd), (args))
7357 #define spawn(mode, cmd) rb_w32_uspawn((mode), (cmd), 0)
7358 #endif
7359 
7360 #if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
7361 struct popen_arg {
7362  VALUE execarg_obj;
7363  struct rb_execarg *eargp;
7364  int modef;
7365  int pair[2];
7366  int write_pair[2];
7367 };
7368 #endif
7369 
7370 #ifdef HAVE_WORKING_FORK
7371 # ifndef __EMSCRIPTEN__
7372 static void
7373 popen_redirect(struct popen_arg *p)
7374 {
7375  if ((p->modef & FMODE_READABLE) && (p->modef & FMODE_WRITABLE)) {
7376  close(p->write_pair[1]);
7377  if (p->write_pair[0] != 0) {
7378  dup2(p->write_pair[0], 0);
7379  close(p->write_pair[0]);
7380  }
7381  close(p->pair[0]);
7382  if (p->pair[1] != 1) {
7383  dup2(p->pair[1], 1);
7384  close(p->pair[1]);
7385  }
7386  }
7387  else if (p->modef & FMODE_READABLE) {
7388  close(p->pair[0]);
7389  if (p->pair[1] != 1) {
7390  dup2(p->pair[1], 1);
7391  close(p->pair[1]);
7392  }
7393  }
7394  else {
7395  close(p->pair[1]);
7396  if (p->pair[0] != 0) {
7397  dup2(p->pair[0], 0);
7398  close(p->pair[0]);
7399  }
7400  }
7401 }
7402 # endif
7403 
7404 #if defined(__linux__)
7405 /* Linux /proc/self/status contains a line: "FDSize:\t<nnn>\n"
7406  * Since /proc may not be available, linux_get_maxfd is just a hint.
7407  * This function, linux_get_maxfd, must be async-signal-safe.
7408  * I.e. opendir() is not usable.
7409  *
7410  * Note that memchr() and memcmp is *not* async-signal-safe in POSIX.
7411  * However they are easy to re-implement in async-signal-safe manner.
7412  * (Also note that there is missing/memcmp.c.)
7413  */
7414 static int
7415 linux_get_maxfd(void)
7416 {
7417  int fd;
7418  char buf[4096], *p, *np, *e;
7419  ssize_t ss;
7420  fd = rb_cloexec_open("/proc/self/status", O_RDONLY|O_NOCTTY, 0);
7421  if (fd < 0) return fd;
7422  ss = read(fd, buf, sizeof(buf));
7423  if (ss < 0) goto err;
7424  p = buf;
7425  e = buf + ss;
7426  while ((int)sizeof("FDSize:\t0\n")-1 <= e-p &&
7427  (np = memchr(p, '\n', e-p)) != NULL) {
7428  if (memcmp(p, "FDSize:", sizeof("FDSize:")-1) == 0) {
7429  int fdsize;
7430  p += sizeof("FDSize:")-1;
7431  *np = '\0';
7432  fdsize = (int)ruby_strtoul(p, (char **)NULL, 10);
7433  close(fd);
7434  return fdsize;
7435  }
7436  p = np+1;
7437  }
7438  /* fall through */
7439 
7440  err:
7441  close(fd);
7442  return (int)ss;
7443 }
7444 #endif
7445 
7446 /* This function should be async-signal-safe. */
7447 void
7448 rb_close_before_exec(int lowfd, int maxhint, VALUE noclose_fds)
7449 {
7450 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
7451  int fd, ret;
7452  int max = (int)max_file_descriptor;
7453 # ifdef F_MAXFD
7454  /* F_MAXFD is available since NetBSD 2.0. */
7455  ret = fcntl(0, F_MAXFD); /* async-signal-safe */
7456  if (ret != -1)
7457  maxhint = max = ret;
7458 # elif defined(__linux__)
7459  ret = linux_get_maxfd();
7460  if (maxhint < ret)
7461  maxhint = ret;
7462  /* maxhint = max = ret; if (ret == -1) abort(); // test */
7463 # endif
7464  if (max < maxhint)
7465  max = maxhint;
7466  for (fd = lowfd; fd <= max; fd++) {
7467  if (!NIL_P(noclose_fds) &&
7468  RTEST(rb_hash_lookup(noclose_fds, INT2FIX(fd)))) /* async-signal-safe */
7469  continue;
7470  ret = fcntl(fd, F_GETFD); /* async-signal-safe */
7471  if (ret != -1 && !(ret & FD_CLOEXEC)) {
7472  fcntl(fd, F_SETFD, ret|FD_CLOEXEC); /* async-signal-safe */
7473  }
7474 # define CONTIGUOUS_CLOSED_FDS 20
7475  if (ret != -1) {
7476  if (max < fd + CONTIGUOUS_CLOSED_FDS)
7477  max = fd + CONTIGUOUS_CLOSED_FDS;
7478  }
7479  }
7480 #endif
7481 }
7482 
7483 # ifndef __EMSCRIPTEN__
7484 static int
7485 popen_exec(void *pp, char *errmsg, size_t errmsg_len)
7486 {
7487  struct popen_arg *p = (struct popen_arg*)pp;
7488 
7489  return rb_exec_async_signal_safe(p->eargp, errmsg, errmsg_len);
7490 }
7491 # endif
7492 #endif
7493 
7494 #if (defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)) && !defined __EMSCRIPTEN__
7495 static VALUE
7496 rb_execarg_fixup_v(VALUE execarg_obj)
7497 {
7498  rb_execarg_parent_start(execarg_obj);
7499  return Qnil;
7500 }
7501 #else
7502 char *rb_execarg_commandline(const struct rb_execarg *eargp, VALUE *prog);
7503 #endif
7504 
7505 #ifndef __EMSCRIPTEN__
7506 static VALUE
7507 pipe_open(VALUE execarg_obj, const char *modestr, int fmode,
7508  const struct rb_io_encoding *convconfig)
7509 {
7510  struct rb_execarg *eargp = NIL_P(execarg_obj) ? NULL : rb_execarg_get(execarg_obj);
7511  VALUE prog = eargp ? (eargp->use_shell ? eargp->invoke.sh.shell_script : eargp->invoke.cmd.command_name) : Qfalse ;
7512  rb_pid_t pid = 0;
7513  rb_io_t *fptr;
7514  VALUE port;
7515  rb_io_t *write_fptr;
7516  VALUE write_port;
7517 #if defined(HAVE_WORKING_FORK)
7518  int status;
7519  char errmsg[80] = { '\0' };
7520 #endif
7521 #if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
7522  int state;
7523  struct popen_arg arg;
7524 #endif
7525  int e = 0;
7526 #if defined(HAVE_SPAWNV)
7527 # if defined(HAVE_SPAWNVE)
7528 # define DO_SPAWN(cmd, args, envp) ((args) ? \
7529  spawnve(P_NOWAIT, (cmd), (args), (envp)) : \
7530  spawne(P_NOWAIT, (cmd), (envp)))
7531 # else
7532 # define DO_SPAWN(cmd, args, envp) ((args) ? \
7533  spawnv(P_NOWAIT, (cmd), (args)) : \
7534  spawn(P_NOWAIT, (cmd)))
7535 # endif
7536 # if !defined(HAVE_WORKING_FORK)
7537  char **args = NULL;
7538 # if defined(HAVE_SPAWNVE)
7539  char **envp = NULL;
7540 # endif
7541 # endif
7542 #endif
7543 #if !defined(HAVE_WORKING_FORK)
7544  struct rb_execarg sarg, *sargp = &sarg;
7545 #endif
7546  FILE *fp = 0;
7547  int fd = -1;
7548  int write_fd = -1;
7549 #if !defined(HAVE_WORKING_FORK)
7550  const char *cmd = 0;
7551 
7552  if (prog)
7553  cmd = StringValueCStr(prog);
7554 #endif
7555 
7556 #if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
7557  arg.execarg_obj = execarg_obj;
7558  arg.eargp = eargp;
7559  arg.modef = fmode;
7560  arg.pair[0] = arg.pair[1] = -1;
7561  arg.write_pair[0] = arg.write_pair[1] = -1;
7562 # if !defined(HAVE_WORKING_FORK)
7563  if (eargp && !eargp->use_shell) {
7564  args = ARGVSTR2ARGV(eargp->invoke.cmd.argv_str);
7565  }
7566 # endif
7567  switch (fmode & (FMODE_READABLE|FMODE_WRITABLE)) {
7569  if (rb_pipe(arg.write_pair) < 0)
7570  rb_sys_fail_str(prog);
7571  if (rb_pipe(arg.pair) < 0) {
7572  e = errno;
7573  close(arg.write_pair[0]);
7574  close(arg.write_pair[1]);
7575  rb_syserr_fail_str(e, prog);
7576  }
7577  if (eargp) {
7578  rb_execarg_addopt(execarg_obj, INT2FIX(0), INT2FIX(arg.write_pair[0]));
7579  rb_execarg_addopt(execarg_obj, INT2FIX(1), INT2FIX(arg.pair[1]));
7580  }
7581  break;
7582  case FMODE_READABLE:
7583  if (rb_pipe(arg.pair) < 0)
7584  rb_sys_fail_str(prog);
7585  if (eargp)
7586  rb_execarg_addopt(execarg_obj, INT2FIX(1), INT2FIX(arg.pair[1]));
7587  break;
7588  case FMODE_WRITABLE:
7589  if (rb_pipe(arg.pair) < 0)
7590  rb_sys_fail_str(prog);
7591  if (eargp)
7592  rb_execarg_addopt(execarg_obj, INT2FIX(0), INT2FIX(arg.pair[0]));
7593  break;
7594  default:
7595  rb_sys_fail_str(prog);
7596  }
7597  if (!NIL_P(execarg_obj)) {
7598  rb_protect(rb_execarg_fixup_v, execarg_obj, &state);
7599  if (state) {
7600  if (0 <= arg.write_pair[0]) close(arg.write_pair[0]);
7601  if (0 <= arg.write_pair[1]) close(arg.write_pair[1]);
7602  if (0 <= arg.pair[0]) close(arg.pair[0]);
7603  if (0 <= arg.pair[1]) close(arg.pair[1]);
7604  rb_execarg_parent_end(execarg_obj);
7605  rb_jump_tag(state);
7606  }
7607 
7608 # if defined(HAVE_WORKING_FORK)
7609  pid = rb_fork_async_signal_safe(&status, popen_exec, &arg, arg.eargp->redirect_fds, errmsg, sizeof(errmsg));
7610 # else
7611  rb_execarg_run_options(eargp, sargp, NULL, 0);
7612 # if defined(HAVE_SPAWNVE)
7613  if (eargp->envp_str) envp = (char **)RSTRING_PTR(eargp->envp_str);
7614 # endif
7615  while ((pid = DO_SPAWN(cmd, args, envp)) < 0) {
7616  /* exec failed */
7617  switch (e = errno) {
7618  case EAGAIN:
7619 # if EWOULDBLOCK != EAGAIN
7620  case EWOULDBLOCK:
7621 # endif
7622  rb_thread_sleep(1);
7623  continue;
7624  }
7625  break;
7626  }
7627  if (eargp)
7628  rb_execarg_run_options(sargp, NULL, NULL, 0);
7629 # endif
7630  rb_execarg_parent_end(execarg_obj);
7631  }
7632  else {
7633 # if defined(HAVE_WORKING_FORK)
7634  pid = rb_call_proc__fork();
7635  if (pid == 0) { /* child */
7636  popen_redirect(&arg);
7637  rb_io_synchronized(RFILE(orig_stdout)->fptr);
7638  rb_io_synchronized(RFILE(orig_stderr)->fptr);
7639  return Qnil;
7640  }
7641 # else
7642  rb_notimplement();
7643 # endif
7644  }
7645 
7646  /* parent */
7647  if (pid < 0) {
7648 # if defined(HAVE_WORKING_FORK)
7649  e = errno;
7650 # endif
7651  close(arg.pair[0]);
7652  close(arg.pair[1]);
7654  close(arg.write_pair[0]);
7655  close(arg.write_pair[1]);
7656  }
7657 # if defined(HAVE_WORKING_FORK)
7658  if (errmsg[0])
7659  rb_syserr_fail(e, errmsg);
7660 # endif
7661  rb_syserr_fail_str(e, prog);
7662  }
7663  if ((fmode & FMODE_READABLE) && (fmode & FMODE_WRITABLE)) {
7664  close(arg.pair[1]);
7665  fd = arg.pair[0];
7666  close(arg.write_pair[0]);
7667  write_fd = arg.write_pair[1];
7668  }
7669  else if (fmode & FMODE_READABLE) {
7670  close(arg.pair[1]);
7671  fd = arg.pair[0];
7672  }
7673  else {
7674  close(arg.pair[0]);
7675  fd = arg.pair[1];
7676  }
7677 #else
7678  cmd = rb_execarg_commandline(eargp, &prog);
7679  if (!NIL_P(execarg_obj)) {
7680  rb_execarg_parent_start(execarg_obj);
7681  rb_execarg_run_options(eargp, sargp, NULL, 0);
7682  }
7683  fp = popen(cmd, modestr);
7684  e = errno;
7685  if (eargp) {
7686  rb_execarg_parent_end(execarg_obj);
7687  rb_execarg_run_options(sargp, NULL, NULL, 0);
7688  }
7689  if (!fp) rb_syserr_fail_path(e, prog);
7690  fd = fileno(fp);
7691 #endif
7692 
7693  port = io_alloc(rb_cIO);
7694  MakeOpenFile(port, fptr);
7695  fptr->fd = fd;
7696  fptr->stdio_file = fp;
7697  fptr->mode = fmode | FMODE_SYNC|FMODE_DUPLEX;
7698  if (convconfig) {
7699  fptr->encs = *convconfig;
7700 #if RUBY_CRLF_ENVIRONMENT
7703  }
7704 #endif
7705  }
7706  else {
7707  if (NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {
7709  }
7710 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
7711  if (NEED_NEWLINE_DECORATOR_ON_WRITE(fptr)) {
7712  fptr->encs.ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
7713  }
7714 #endif
7715  }
7716  fptr->pid = pid;
7717 
7718  if (0 <= write_fd) {
7719  write_port = io_alloc(rb_cIO);
7720  MakeOpenFile(write_port, write_fptr);
7721  write_fptr->fd = write_fd;
7722  write_fptr->mode = (fmode & ~FMODE_READABLE)| FMODE_SYNC|FMODE_DUPLEX;
7723  fptr->mode &= ~FMODE_WRITABLE;
7724  fptr->tied_io_for_writing = write_port;
7725  rb_ivar_set(port, rb_intern("@tied_io_for_writing"), write_port);
7726  }
7727 
7728 #if defined (__CYGWIN__) || !defined(HAVE_WORKING_FORK)
7729  fptr->finalize = pipe_finalize;
7730  pipe_add_fptr(fptr);
7731 #endif
7732  return port;
7733 }
7734 #else
7735 static VALUE
7736 pipe_open(VALUE execarg_obj, const char *modestr, int fmode,
7737  const struct rb_io_encoding *convconfig)
7738 {
7739  rb_raise(rb_eNotImpError, "popen() is not available");
7740 }
7741 #endif
7742 
7743 static int
7744 is_popen_fork(VALUE prog)
7745 {
7746  if (RSTRING_LEN(prog) == 1 && RSTRING_PTR(prog)[0] == '-') {
7747 #if !defined(HAVE_WORKING_FORK)
7749  "fork() function is unimplemented on this machine");
7750 #else
7751  return TRUE;
7752 #endif
7753  }
7754  return FALSE;
7755 }
7756 
7757 static VALUE
7758 pipe_open_s(VALUE prog, const char *modestr, int fmode,
7759  const struct rb_io_encoding *convconfig)
7760 {
7761  int argc = 1;
7762  VALUE *argv = &prog;
7763  VALUE execarg_obj = Qnil;
7764 
7765  if (!is_popen_fork(prog))
7766  execarg_obj = rb_execarg_new(argc, argv, TRUE, FALSE);
7767  return pipe_open(execarg_obj, modestr, fmode, convconfig);
7768 }
7769 
7770 static VALUE
7771 pipe_close(VALUE io)
7772 {
7773  rb_io_t *fptr = io_close_fptr(io);
7774  if (fptr) {
7775  fptr_waitpid(fptr, rb_thread_to_be_killed(rb_thread_current()));
7776  }
7777  return Qnil;
7778 }
7779 
7780 static VALUE popen_finish(VALUE port, VALUE klass);
7781 
7782 /*
7783  * call-seq:
7784  * IO.popen(env = {}, cmd, mode = 'r', **opts) -> io
7785  * IO.popen(env = {}, cmd, mode = 'r', **opts) {|io| ... } -> object
7786  *
7787  * Executes the given command +cmd+ as a subprocess
7788  * whose $stdin and $stdout are connected to a new stream +io+.
7789  *
7790  * This method has potential security vulnerabilities if called with untrusted input;
7791  * see {Command Injection}[rdoc-ref:command_injection.rdoc].
7792  *
7793  * If no block is given, returns the new stream,
7794  * which depending on given +mode+ may be open for reading, writing, or both.
7795  * The stream should be explicitly closed (eventually) to avoid resource leaks.
7796  *
7797  * If a block is given, the stream is passed to the block
7798  * (again, open for reading, writing, or both);
7799  * when the block exits, the stream is closed,
7800  * and the block's value is assigned to global variable <tt>$?</tt> and returned.
7801  *
7802  * Optional argument +mode+ may be any valid \IO mode.
7803  * See {Access Modes}[rdoc-ref:File@Access+Modes].
7804  *
7805  * Required argument +cmd+ determines which of the following occurs:
7806  *
7807  * - The process forks.
7808  * - A specified program runs in a shell.
7809  * - A specified program runs with specified arguments.
7810  * - A specified program runs with specified arguments and a specified +argv0+.
7811  *
7812  * Each of these is detailed below.
7813  *
7814  * The optional hash argument +env+ specifies name/value pairs that are to be added
7815  * to the environment variables for the subprocess:
7816  *
7817  * IO.popen({'FOO' => 'bar'}, 'ruby', 'r+') do |pipe|
7818  * pipe.puts 'puts ENV["FOO"]'
7819  * pipe.close_write
7820  * pipe.gets
7821  * end => "bar\n"
7822  *
7823  * Optional keyword arguments +opts+ specify:
7824  *
7825  * - {Open options}[rdoc-ref:IO@Open+Options].
7826  * - {Encoding options}[rdoc-ref:encodings.rdoc@Encoding+Options].
7827  * - Options for Kernel#spawn.
7828  *
7829  * <b>Forked \Process</b>
7830  *
7831  * When argument +cmd+ is the 1-character string <tt>'-'</tt>, causes the process to fork:
7832  * IO.popen('-') do |pipe|
7833  * if pipe
7834  * $stderr.puts "In parent, child pid is #{pipe.pid}\n"
7835  * else
7836  * $stderr.puts "In child, pid is #{$$}\n"
7837  * end
7838  * end
7839  *
7840  * Output:
7841  *
7842  * In parent, child pid is 26253
7843  * In child, pid is 26253
7844  *
7845  * Note that this is not supported on all platforms.
7846  *
7847  * <b>Shell Subprocess</b>
7848  *
7849  * When argument +cmd+ is a single string (but not <tt>'-'</tt>),
7850  * the program named +cmd+ is run as a shell command:
7851  *
7852  * IO.popen('uname') do |pipe|
7853  * pipe.readlines
7854  * end
7855  *
7856  * Output:
7857  *
7858  * ["Linux\n"]
7859  *
7860  * Another example:
7861  *
7862  * IO.popen('/bin/sh', 'r+') do |pipe|
7863  * pipe.puts('ls')
7864  * pipe.close_write
7865  * $stderr.puts pipe.readlines.size
7866  * end
7867  *
7868  * Output:
7869  *
7870  * 213
7871  *
7872  * <b>Program Subprocess</b>
7873  *
7874  * When argument +cmd+ is an array of strings,
7875  * the program named <tt>cmd[0]</tt> is run with all elements of +cmd+ as its arguments:
7876  *
7877  * IO.popen(['du', '..', '.']) do |pipe|
7878  * $stderr.puts pipe.readlines.size
7879  * end
7880  *
7881  * Output:
7882  *
7883  * 1111
7884  *
7885  * <b>Program Subprocess with <tt>argv0</tt></b>
7886  *
7887  * When argument +cmd+ is an array whose first element is a 2-element string array
7888  * and whose remaining elements (if any) are strings:
7889  *
7890  * - <tt>cmd[0][0]</tt> (the first string in the nested array) is the name of a program that is run.
7891  * - <tt>cmd[0][1]</tt> (the second string in the nested array) is set as the program's <tt>argv[0]</tt>.
7892  * - <tt>cmd[1..-1]</tt> (the strings in the outer array) are the program's arguments.
7893  *
7894  * Example (sets <tt>$0</tt> to 'foo'):
7895  *
7896  * IO.popen([['/bin/sh', 'foo'], '-c', 'echo $0']).read # => "foo\n"
7897  *
7898  * <b>Some Special Examples</b>
7899  *
7900  * # Set IO encoding.
7901  * IO.popen("nkf -e filename", :external_encoding=>"EUC-JP") {|nkf_io|
7902  * euc_jp_string = nkf_io.read
7903  * }
7904  *
7905  * # Merge standard output and standard error using Kernel#spawn option. See Kernel#spawn.
7906  * IO.popen(["ls", "/", :err=>[:child, :out]]) do |io|
7907  * ls_result_with_error = io.read
7908  * end
7909  *
7910  * # Use mixture of spawn options and IO options.
7911  * IO.popen(["ls", "/"], :err=>[:child, :out]) do |io|
7912  * ls_result_with_error = io.read
7913  * end
7914  *
7915  * f = IO.popen("uname")
7916  * p f.readlines
7917  * f.close
7918  * puts "Parent is #{Process.pid}"
7919  * IO.popen("date") {|f| puts f.gets }
7920  * IO.popen("-") {|f| $stderr.puts "#{Process.pid} is here, f is #{f.inspect}"}
7921  * p $?
7922  * IO.popen(%w"sed -e s|^|<foo>| -e s&$&;zot;&", "r+") {|f|
7923  * f.puts "bar"; f.close_write; puts f.gets
7924  * }
7925  *
7926  * Output (from last section):
7927  *
7928  * ["Linux\n"]
7929  * Parent is 21346
7930  * Thu Jan 15 22:41:19 JST 2009
7931  * 21346 is here, f is #<IO:fd 3>
7932  * 21352 is here, f is nil
7933  * #<Process::Status: pid 21352 exit 0>
7934  * <foo>bar;zot;
7935  *
7936  * Raises exceptions that IO.pipe and Kernel.spawn raise.
7937  *
7938  */
7939 
7940 static VALUE
7941 rb_io_s_popen(int argc, VALUE *argv, VALUE klass)
7942 {
7943  VALUE pname, pmode = Qnil, opt = Qnil, env = Qnil;
7944 
7945  if (argc > 1 && !NIL_P(opt = rb_check_hash_type(argv[argc-1]))) --argc;
7946  if (argc > 1 && !NIL_P(env = rb_check_hash_type(argv[0]))) --argc, ++argv;
7947  switch (argc) {
7948  case 2:
7949  pmode = argv[1];
7950  case 1:
7951  pname = argv[0];
7952  break;
7953  default:
7954  {
7955  int ex = !NIL_P(opt);
7956  rb_error_arity(argc + ex, 1 + ex, 2 + ex);
7957  }
7958  }
7959  return popen_finish(rb_io_popen(pname, pmode, env, opt), klass);
7960 }
7961 
7962 VALUE
7963 rb_io_popen(VALUE pname, VALUE pmode, VALUE env, VALUE opt)
7964 {
7965  const char *modestr;
7966  VALUE tmp, execarg_obj = Qnil;
7967  int oflags, fmode;
7968  struct rb_io_encoding convconfig;
7969 
7970  tmp = rb_check_array_type(pname);
7971  if (!NIL_P(tmp)) {
7972  long len = RARRAY_LEN(tmp);
7973 #if SIZEOF_LONG > SIZEOF_INT
7974  if (len > INT_MAX) {
7975  rb_raise(rb_eArgError, "too many arguments");
7976  }
7977 #endif
7978  execarg_obj = rb_execarg_new((int)len, RARRAY_CONST_PTR(tmp), FALSE, FALSE);
7979  RB_GC_GUARD(tmp);
7980  }
7981  else {
7982  StringValue(pname);
7983  execarg_obj = Qnil;
7984  if (!is_popen_fork(pname))
7985  execarg_obj = rb_execarg_new(1, &pname, TRUE, FALSE);
7986  }
7987  if (!NIL_P(execarg_obj)) {
7988  if (!NIL_P(opt))
7989  opt = rb_execarg_extract_options(execarg_obj, opt);
7990  if (!NIL_P(env))
7991  rb_execarg_setenv(execarg_obj, env);
7992  }
7993  rb_io_extract_modeenc(&pmode, 0, opt, &oflags, &fmode, &convconfig);
7994  modestr = rb_io_oflags_modestr(oflags);
7995 
7996  return pipe_open(execarg_obj, modestr, fmode, &convconfig);
7997 }
7998 
7999 static VALUE
8000 popen_finish(VALUE port, VALUE klass)
8001 {
8002  if (NIL_P(port)) {
8003  /* child */
8004  if (rb_block_given_p()) {
8005  rb_yield(Qnil);
8008  _exit(0);
8009  }
8010  return Qnil;
8011  }
8012  RBASIC_SET_CLASS(port, klass);
8013  if (rb_block_given_p()) {
8014  return rb_ensure(rb_yield, port, pipe_close, port);
8015  }
8016  return port;
8017 }
8018 
8019 #if defined(HAVE_WORKING_FORK) && !defined(__EMSCRIPTEN__)
8020 struct popen_writer_arg {
8021  char *const *argv;
8022  struct popen_arg popen;
8023 };
8024 
8025 static int
8026 exec_popen_writer(void *arg, char *errmsg, size_t buflen)
8027 {
8028  struct popen_writer_arg *pw = arg;
8029  pw->popen.modef = FMODE_WRITABLE;
8030  popen_redirect(&pw->popen);
8031  execv(pw->argv[0], pw->argv);
8032  strlcpy(errmsg, strerror(errno), buflen);
8033  return -1;
8034 }
8035 #endif
8036 
8037 FILE *
8038 ruby_popen_writer(char *const *argv, rb_pid_t *pid)
8039 {
8040 #if (defined(HAVE_WORKING_FORK) && !defined(__EMSCRIPTEN__)) || defined(_WIN32)
8041 # ifdef HAVE_WORKING_FORK
8042  struct popen_writer_arg pw;
8043  int *const write_pair = pw.popen.pair;
8044 # else
8045  int write_pair[2];
8046 # endif
8047 
8048  int result = rb_cloexec_pipe(write_pair);
8049  *pid = -1;
8050  if (result == 0) {
8051 # ifdef HAVE_WORKING_FORK
8052  pw.argv = argv;
8053  int status;
8054  char errmsg[80] = {'\0'};
8055  *pid = rb_fork_async_signal_safe(&status, exec_popen_writer, &pw, Qnil, errmsg, sizeof(errmsg));
8056 # else
8057  *pid = rb_w32_uspawn_process(P_NOWAIT, argv[0], argv, write_pair[0], -1, -1, 0);
8058  const char *errmsg = (*pid < 0) ? strerror(errno) : NULL;
8059 # endif
8060  close(write_pair[0]);
8061  if (*pid < 0) {
8062  close(write_pair[1]);
8063  fprintf(stderr, "ruby_popen_writer(%s): %s\n", argv[0], errmsg);
8064  }
8065  else {
8066  return fdopen(write_pair[1], "w");
8067  }
8068  }
8069 #endif
8070  return NULL;
8071 }
8072 
8073 static VALUE
8074 rb_open_file(VALUE io, VALUE fname, VALUE vmode, VALUE vperm, VALUE opt)
8075 {
8076  struct rb_io_encoding convconfig;
8077  int oflags, fmode;
8078  mode_t perm;
8079 
8080  FilePathValue(fname);
8081 
8082  rb_io_extract_modeenc(&vmode, &vperm, opt, &oflags, &fmode, &convconfig);
8083  perm = NIL_P(vperm) ? 0666 : NUM2MODET(vperm);
8084 
8085  rb_file_open_generic(io, fname, oflags, fmode, &convconfig, perm);
8086 
8087  return io;
8088 }
8089 
8090 /*
8091  * Document-method: File::open
8092  *
8093  * call-seq:
8094  * File.open(path, mode = 'r', perm = 0666, **opts) -> file
8095  * File.open(path, mode = 'r', perm = 0666, **opts) {|f| ... } -> object
8096  *
8097  * Creates a new File object, via File.new with the given arguments.
8098  *
8099  * With no block given, returns the File object.
8100  *
8101  * With a block given, calls the block with the File object
8102  * and returns the block's value.
8103  *
8104  */
8105 
8106 /*
8107  * Document-method: IO::open
8108  *
8109  * call-seq:
8110  * IO.open(fd, mode = 'r', **opts) -> io
8111  * IO.open(fd, mode = 'r', **opts) {|io| ... } -> object
8112  *
8113  * Creates a new \IO object, via IO.new with the given arguments.
8114  *
8115  * With no block given, returns the \IO object.
8116  *
8117  * With a block given, calls the block with the \IO object
8118  * and returns the block's value.
8119  *
8120  */
8121 
8122 static VALUE
8123 rb_io_s_open(int argc, VALUE *argv, VALUE klass)
8124 {
8125  VALUE io = rb_class_new_instance_kw(argc, argv, klass, RB_PASS_CALLED_KEYWORDS);
8126 
8127  if (rb_block_given_p()) {
8128  return rb_ensure(rb_yield, io, io_close, io);
8129  }
8130 
8131  return io;
8132 }
8133 
8134 /*
8135  * call-seq:
8136  * IO.sysopen(path, mode = 'r', perm = 0666) -> integer
8137  *
8138  * Opens the file at the given path with the given mode and permissions;
8139  * returns the integer file descriptor.
8140  *
8141  * If the file is to be readable, it must exist;
8142  * if the file is to be writable and does not exist,
8143  * it is created with the given permissions:
8144  *
8145  * File.write('t.tmp', '') # => 0
8146  * IO.sysopen('t.tmp') # => 8
8147  * IO.sysopen('t.tmp', 'w') # => 9
8148  *
8149  *
8150  */
8151 
8152 static VALUE
8153 rb_io_s_sysopen(int argc, VALUE *argv, VALUE _)
8154 {
8155  VALUE fname, vmode, vperm;
8156  VALUE intmode;
8157  int oflags, fd;
8158  mode_t perm;
8159 
8160  rb_scan_args(argc, argv, "12", &fname, &vmode, &vperm);
8161  FilePathValue(fname);
8162 
8163  if (NIL_P(vmode))
8164  oflags = O_RDONLY;
8165  else if (!NIL_P(intmode = rb_check_to_integer(vmode, "to_int")))
8166  oflags = NUM2INT(intmode);
8167  else {
8168  StringValue(vmode);
8169  oflags = rb_io_modestr_oflags(StringValueCStr(vmode));
8170  }
8171  if (NIL_P(vperm)) perm = 0666;
8172  else perm = NUM2MODET(vperm);
8173 
8174  RB_GC_GUARD(fname) = rb_str_new4(fname);
8175  fd = rb_sysopen(fname, oflags, perm);
8176  return INT2NUM(fd);
8177 }
8178 
8179 static VALUE
8180 check_pipe_command(VALUE filename_or_command)
8181 {
8182  char *s = RSTRING_PTR(filename_or_command);
8183  long l = RSTRING_LEN(filename_or_command);
8184  char *e = s + l;
8185  int chlen;
8186 
8187  if (rb_enc_ascget(s, e, &chlen, rb_enc_get(filename_or_command)) == '|') {
8188  VALUE cmd = rb_str_new(s+chlen, l-chlen);
8189  return cmd;
8190  }
8191  return Qnil;
8192 }
8193 
8194 /*
8195  * call-seq:
8196  * open(path, mode = 'r', perm = 0666, **opts) -> io or nil
8197  * open(path, mode = 'r', perm = 0666, **opts) {|io| ... } -> obj
8198  *
8199  * Creates an IO object connected to the given file.
8200  *
8201  * This method has potential security vulnerabilities if called with untrusted input;
8202  * see {Command Injection}[rdoc-ref:command_injection.rdoc].
8203  *
8204  * With no block given, file stream is returned:
8205  *
8206  * open('t.txt') # => #<File:t.txt>
8207  *
8208  * With a block given, calls the block with the open file stream,
8209  * then closes the stream:
8210  *
8211  * open('t.txt') {|f| p f } # => #<File:t.txt (closed)>
8212  *
8213  * Output:
8214  *
8215  * #<File:t.txt>
8216  *
8217  * See File.open for details.
8218  *
8219  */
8220 
8221 static VALUE
8222 rb_f_open(int argc, VALUE *argv, VALUE _)
8223 {
8224  ID to_open = 0;
8225  int redirect = FALSE;
8226 
8227  if (argc >= 1) {
8228  CONST_ID(to_open, "to_open");
8229  if (rb_respond_to(argv[0], to_open)) {
8230  redirect = TRUE;
8231  }
8232  else {
8233  VALUE tmp = argv[0];
8234  FilePathValue(tmp);
8235  if (NIL_P(tmp)) {
8236  redirect = TRUE;
8237  }
8238  else {
8239  VALUE cmd = check_pipe_command(tmp);
8240  if (!NIL_P(cmd)) {
8241  // TODO: when removed in 4.0, update command_injection.rdoc
8242  rb_warn_deprecated_to_remove_at(4.0, "Calling Kernel#open with a leading '|'", "IO.popen");
8243  argv[0] = cmd;
8244  return rb_io_s_popen(argc, argv, rb_cIO);
8245  }
8246  }
8247  }
8248  }
8249  if (redirect) {
8250  VALUE io = rb_funcallv_kw(argv[0], to_open, argc-1, argv+1, RB_PASS_CALLED_KEYWORDS);
8251 
8252  if (rb_block_given_p()) {
8253  return rb_ensure(rb_yield, io, io_close, io);
8254  }
8255  return io;
8256  }
8257  return rb_io_s_open(argc, argv, rb_cFile);
8258 }
8259 
8260 static VALUE rb_io_open_generic(VALUE, VALUE, int, int, const struct rb_io_encoding *, mode_t);
8261 
8262 static VALUE
8263 rb_io_open(VALUE io, VALUE filename, VALUE vmode, VALUE vperm, VALUE opt)
8264 {
8265  int oflags, fmode;
8266  struct rb_io_encoding convconfig;
8267  mode_t perm;
8268 
8269  rb_io_extract_modeenc(&vmode, &vperm, opt, &oflags, &fmode, &convconfig);
8270  perm = NIL_P(vperm) ? 0666 : NUM2MODET(vperm);
8271  return rb_io_open_generic(io, filename, oflags, fmode, &convconfig, perm);
8272 }
8273 
8274 static VALUE
8275 rb_io_open_generic(VALUE klass, VALUE filename, int oflags, int fmode,
8276  const struct rb_io_encoding *convconfig, mode_t perm)
8277 {
8278  VALUE cmd;
8279  if (klass == rb_cIO && !NIL_P(cmd = check_pipe_command(filename))) {
8280  // TODO: when removed in 4.0, update command_injection.rdoc
8281  rb_warn_deprecated_to_remove_at(4.0, "IO process creation with a leading '|'", "IO.popen");
8282  return pipe_open_s(cmd, rb_io_oflags_modestr(oflags), fmode, convconfig);
8283  }
8284  else {
8285  return rb_file_open_generic(io_alloc(klass), filename,
8286  oflags, fmode, convconfig, perm);
8287  }
8288 }
8289 
8290 static VALUE
8291 io_reopen(VALUE io, VALUE nfile)
8292 {
8293  rb_io_t *fptr, *orig;
8294  int fd, fd2;
8295  rb_off_t pos = 0;
8296 
8297  nfile = rb_io_get_io(nfile);
8298  GetOpenFile(io, fptr);
8299  GetOpenFile(nfile, orig);
8300 
8301  if (fptr == orig) return io;
8302  if (RUBY_IO_EXTERNAL_P(fptr)) {
8303  if ((fptr->stdio_file == stdin && !(orig->mode & FMODE_READABLE)) ||
8304  (fptr->stdio_file == stdout && !(orig->mode & FMODE_WRITABLE)) ||
8305  (fptr->stdio_file == stderr && !(orig->mode & FMODE_WRITABLE))) {
8307  "%s can't change access mode from \"%s\" to \"%s\"",
8308  PREP_STDIO_NAME(fptr), rb_io_fmode_modestr(fptr->mode),
8309  rb_io_fmode_modestr(orig->mode));
8310  }
8311  }
8312  if (fptr->mode & FMODE_WRITABLE) {
8313  if (io_fflush(fptr) < 0)
8314  rb_sys_fail_on_write(fptr);
8315  }
8316  else {
8317  flush_before_seek(fptr);
8318  }
8319  if (orig->mode & FMODE_READABLE) {
8320  pos = io_tell(orig);
8321  }
8322  if (orig->mode & FMODE_WRITABLE) {
8323  if (io_fflush(orig) < 0)
8324  rb_sys_fail_on_write(fptr);
8325  }
8326 
8327  /* copy rb_io_t structure */
8328  fptr->mode = orig->mode | (fptr->mode & FMODE_EXTERNAL);
8329  fptr->pid = orig->pid;
8330  fptr->lineno = orig->lineno;
8331  if (RTEST(orig->pathv)) fptr->pathv = orig->pathv;
8332  else if (!RUBY_IO_EXTERNAL_P(fptr)) fptr->pathv = Qnil;
8333  fptr_copy_finalizer(fptr, orig);
8334 
8335  fd = fptr->fd;
8336  fd2 = orig->fd;
8337  if (fd != fd2) {
8338  if (RUBY_IO_EXTERNAL_P(fptr) || fd <= 2 || !fptr->stdio_file) {
8339  /* need to keep FILE objects of stdin, stdout and stderr */
8340  if (rb_cloexec_dup2(fd2, fd) < 0)
8341  rb_sys_fail_path(orig->pathv);
8342  rb_update_max_fd(fd);
8343  }
8344  else {
8345  fclose(fptr->stdio_file);
8346  fptr->stdio_file = 0;
8347  fptr->fd = -1;
8348  if (rb_cloexec_dup2(fd2, fd) < 0)
8349  rb_sys_fail_path(orig->pathv);
8350  rb_update_max_fd(fd);
8351  fptr->fd = fd;
8352  }
8353  rb_thread_fd_close(fd);
8354  if ((orig->mode & FMODE_READABLE) && pos >= 0) {
8355  if (io_seek(fptr, pos, SEEK_SET) < 0 && errno) {
8356  rb_sys_fail_path(fptr->pathv);
8357  }
8358  if (io_seek(orig, pos, SEEK_SET) < 0 && errno) {
8359  rb_sys_fail_path(orig->pathv);
8360  }
8361  }
8362  }
8363 
8364  if (fptr->mode & FMODE_BINMODE) {
8365  rb_io_binmode(io);
8366  }
8367 
8368  RBASIC_SET_CLASS(io, rb_obj_class(nfile));
8369  return io;
8370 }
8371 
8372 #ifdef _WIN32
8373 int rb_freopen(VALUE fname, const char *mode, FILE *fp);
8374 #else
8375 static int
8376 rb_freopen(VALUE fname, const char *mode, FILE *fp)
8377 {
8378  if (!freopen(RSTRING_PTR(fname), mode, fp)) {
8379  RB_GC_GUARD(fname);
8380  return errno;
8381  }
8382  return 0;
8383 }
8384 #endif
8385 
8386 /*
8387  * call-seq:
8388  * reopen(other_io) -> self
8389  * reopen(path, mode = 'r', **opts) -> self
8390  *
8391  * Reassociates the stream with another stream,
8392  * which may be of a different class.
8393  * This method may be used to redirect an existing stream
8394  * to a new destination.
8395  *
8396  * With argument +other_io+ given, reassociates with that stream:
8397  *
8398  * # Redirect $stdin from a file.
8399  * f = File.open('t.txt')
8400  * $stdin.reopen(f)
8401  * f.close
8402  *
8403  * # Redirect $stdout to a file.
8404  * f = File.open('t.tmp', 'w')
8405  * $stdout.reopen(f)
8406  * f.close
8407  *
8408  * With argument +path+ given, reassociates with a new stream to that file path:
8409  *
8410  * $stdin.reopen('t.txt')
8411  * $stdout.reopen('t.tmp', 'w')
8412  *
8413  * Optional keyword arguments +opts+ specify:
8414  *
8415  * - {Open Options}[rdoc-ref:IO@Open+Options].
8416  * - {Encoding options}[rdoc-ref:encodings.rdoc@Encoding+Options].
8417  *
8418  */
8419 
8420 static VALUE
8421 rb_io_reopen(int argc, VALUE *argv, VALUE file)
8422 {
8423  VALUE fname, nmode, opt;
8424  int oflags;
8425  rb_io_t *fptr;
8426 
8427  if (rb_scan_args(argc, argv, "11:", &fname, &nmode, &opt) == 1) {
8428  VALUE tmp = rb_io_check_io(fname);
8429  if (!NIL_P(tmp)) {
8430  return io_reopen(file, tmp);
8431  }
8432  }
8433 
8434  FilePathValue(fname);
8435  rb_io_taint_check(file);
8436  fptr = RFILE(file)->fptr;
8437  if (!fptr) {
8438  fptr = RFILE(file)->fptr = ZALLOC(rb_io_t);
8439  }
8440 
8441  if (!NIL_P(nmode) || !NIL_P(opt)) {
8442  int fmode;
8443  struct rb_io_encoding convconfig;
8444 
8445  rb_io_extract_modeenc(&nmode, 0, opt, &oflags, &fmode, &convconfig);
8446  if (RUBY_IO_EXTERNAL_P(fptr) &&
8447  ((fptr->mode & FMODE_READWRITE) & (fmode & FMODE_READWRITE)) !=
8448  (fptr->mode & FMODE_READWRITE)) {
8450  "%s can't change access mode from \"%s\" to \"%s\"",
8451  PREP_STDIO_NAME(fptr), rb_io_fmode_modestr(fptr->mode),
8452  rb_io_fmode_modestr(fmode));
8453  }
8454  fptr->mode = fmode;
8455  fptr->encs = convconfig;
8456  }
8457  else {
8458  oflags = rb_io_fmode_oflags(fptr->mode);
8459  }
8460 
8461  fptr->pathv = fname;
8462  if (fptr->fd < 0) {
8463  fptr->fd = rb_sysopen(fptr->pathv, oflags, 0666);
8464  fptr->stdio_file = 0;
8465  return file;
8466  }
8467 
8468  if (fptr->mode & FMODE_WRITABLE) {
8469  if (io_fflush(fptr) < 0)
8470  rb_sys_fail_on_write(fptr);
8471  }
8472  fptr->rbuf.off = fptr->rbuf.len = 0;
8473 
8474  if (fptr->stdio_file) {
8475  int e = rb_freopen(rb_str_encode_ospath(fptr->pathv),
8476  rb_io_oflags_modestr(oflags),
8477  fptr->stdio_file);
8478  if (e) rb_syserr_fail_path(e, fptr->pathv);
8479  fptr->fd = fileno(fptr->stdio_file);
8480  rb_fd_fix_cloexec(fptr->fd);
8481 #ifdef USE_SETVBUF
8482  if (setvbuf(fptr->stdio_file, NULL, _IOFBF, 0) != 0)
8483  rb_warn("setvbuf() can't be honoured for %"PRIsVALUE, fptr->pathv);
8484 #endif
8485  if (fptr->stdio_file == stderr) {
8486  if (setvbuf(fptr->stdio_file, NULL, _IONBF, BUFSIZ) != 0)
8487  rb_warn("setvbuf() can't be honoured for %"PRIsVALUE, fptr->pathv);
8488  }
8489  else if (fptr->stdio_file == stdout && isatty(fptr->fd)) {
8490  if (setvbuf(fptr->stdio_file, NULL, _IOLBF, BUFSIZ) != 0)
8491  rb_warn("setvbuf() can't be honoured for %"PRIsVALUE, fptr->pathv);
8492  }
8493  }
8494  else {
8495  int tmpfd = rb_sysopen(fptr->pathv, oflags, 0666);
8496  int err = 0;
8497  if (rb_cloexec_dup2(tmpfd, fptr->fd) < 0)
8498  err = errno;
8499  (void)close(tmpfd);
8500  if (err) {
8501  rb_syserr_fail_path(err, fptr->pathv);
8502  }
8503  }
8504 
8505  return file;
8506 }
8507 
8508 /* :nodoc: */
8509 static VALUE
8510 rb_io_init_copy(VALUE dest, VALUE io)
8511 {
8512  rb_io_t *fptr, *orig;
8513  int fd;
8514  VALUE write_io;
8515  rb_off_t pos;
8516 
8517  io = rb_io_get_io(io);
8518  if (!OBJ_INIT_COPY(dest, io)) return dest;
8519  GetOpenFile(io, orig);
8520  MakeOpenFile(dest, fptr);
8521 
8522  rb_io_flush(io);
8523 
8524  /* copy rb_io_t structure */
8525  fptr->mode = orig->mode & ~FMODE_EXTERNAL;
8526  fptr->encs = orig->encs;
8527  fptr->pid = orig->pid;
8528  fptr->lineno = orig->lineno;
8529  fptr->timeout = orig->timeout;
8530  if (!NIL_P(orig->pathv)) fptr->pathv = orig->pathv;
8531  fptr_copy_finalizer(fptr, orig);
8532 
8533  fd = ruby_dup(orig->fd);
8534  fptr->fd = fd;
8535  pos = io_tell(orig);
8536  if (0 <= pos)
8537  io_seek(fptr, pos, SEEK_SET);
8538  if (fptr->mode & FMODE_BINMODE) {
8539  rb_io_binmode(dest);
8540  }
8541 
8542  write_io = GetWriteIO(io);
8543  if (io != write_io) {
8544  write_io = rb_obj_dup(write_io);
8545  fptr->tied_io_for_writing = write_io;
8546  rb_ivar_set(dest, rb_intern("@tied_io_for_writing"), write_io);
8547  }
8548 
8549  return dest;
8550 }
8551 
8552 /*
8553  * call-seq:
8554  * printf(format_string, *objects) -> nil
8555  *
8556  * Formats and writes +objects+ to the stream.
8557  *
8558  * For details on +format_string+, see
8559  * {Format Specifications}[rdoc-ref:format_specifications.rdoc].
8560  *
8561  */
8562 
8563 VALUE
8564 rb_io_printf(int argc, const VALUE *argv, VALUE out)
8565 {
8566  rb_io_write(out, rb_f_sprintf(argc, argv));
8567  return Qnil;
8568 }
8569 
8570 /*
8571  * call-seq:
8572  * printf(format_string, *objects) -> nil
8573  * printf(io, format_string, *objects) -> nil
8574  *
8575  * Equivalent to:
8576  *
8577  * io.write(sprintf(format_string, *objects))
8578  *
8579  * For details on +format_string+, see
8580  * {Format Specifications}[rdoc-ref:format_specifications.rdoc].
8581  *
8582  * With the single argument +format_string+, formats +objects+ into the string,
8583  * then writes the formatted string to $stdout:
8584  *
8585  * printf('%4.4d %10s %2.2f', 24, 24, 24.0)
8586  *
8587  * Output (on $stdout):
8588  *
8589  * 0024 24 24.00#
8590  *
8591  * With arguments +io+ and +format_string+, formats +objects+ into the string,
8592  * then writes the formatted string to +io+:
8593  *
8594  * printf($stderr, '%4.4d %10s %2.2f', 24, 24, 24.0)
8595  *
8596  * Output (on $stderr):
8597  *
8598  * 0024 24 24.00# => nil
8599  *
8600  * With no arguments, does nothing.
8601  *
8602  */
8603 
8604 static VALUE
8605 rb_f_printf(int argc, VALUE *argv, VALUE _)
8606 {
8607  VALUE out;
8608 
8609  if (argc == 0) return Qnil;
8610  if (RB_TYPE_P(argv[0], T_STRING)) {
8611  out = rb_ractor_stdout();
8612  }
8613  else {
8614  out = argv[0];
8615  argv++;
8616  argc--;
8617  }
8618  rb_io_write(out, rb_f_sprintf(argc, argv));
8619 
8620  return Qnil;
8621 }
8622 
8623 static void
8624 deprecated_str_setter(VALUE val, ID id, VALUE *var)
8625 {
8626  rb_str_setter(val, id, &val);
8627  if (!NIL_P(val)) {
8628  rb_warn_deprecated("'%s'", NULL, rb_id2name(id));
8629  }
8630  *var = val;
8631 }
8632 
8633 /*
8634  * call-seq:
8635  * print(*objects) -> nil
8636  *
8637  * Writes the given objects to the stream; returns +nil+.
8638  * Appends the output record separator <tt>$OUTPUT_RECORD_SEPARATOR</tt>
8639  * (<tt>$\</tt>), if it is not +nil+.
8640  * See {Line IO}[rdoc-ref:IO@Line+IO].
8641  *
8642  * With argument +objects+ given, for each object:
8643  *
8644  * - Converts via its method +to_s+ if not a string.
8645  * - Writes to the stream.
8646  * - If not the last object, writes the output field separator
8647  * <tt>$OUTPUT_FIELD_SEPARATOR</tt> (<tt>$,</tt>) if it is not +nil+.
8648  *
8649  * With default separators:
8650  *
8651  * f = File.open('t.tmp', 'w+')
8652  * objects = [0, 0.0, Rational(0, 1), Complex(0, 0), :zero, 'zero']
8653  * p $OUTPUT_RECORD_SEPARATOR
8654  * p $OUTPUT_FIELD_SEPARATOR
8655  * f.print(*objects)
8656  * f.rewind
8657  * p f.read
8658  * f.close
8659  *
8660  * Output:
8661  *
8662  * nil
8663  * nil
8664  * "00.00/10+0izerozero"
8665  *
8666  * With specified separators:
8667  *
8668  * $\ = "\n"
8669  * $, = ','
8670  * f.rewind
8671  * f.print(*objects)
8672  * f.rewind
8673  * p f.read
8674  *
8675  * Output:
8676  *
8677  * "0,0.0,0/1,0+0i,zero,zero\n"
8678  *
8679  * With no argument given, writes the content of <tt>$_</tt>
8680  * (which is usually the most recent user input):
8681  *
8682  * f = File.open('t.tmp', 'w+')
8683  * gets # Sets $_ to the most recent user input.
8684  * f.print
8685  * f.close
8686  *
8687  */
8688 
8689 VALUE
8690 rb_io_print(int argc, const VALUE *argv, VALUE out)
8691 {
8692  int i;
8693  VALUE line;
8694 
8695  /* if no argument given, print `$_' */
8696  if (argc == 0) {
8697  argc = 1;
8698  line = rb_lastline_get();
8699  argv = &line;
8700  }
8701  if (argc > 1 && !NIL_P(rb_output_fs)) {
8702  rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "$, is set to non-nil value");
8703  }
8704  for (i=0; i<argc; i++) {
8705  if (!NIL_P(rb_output_fs) && i>0) {
8706  rb_io_write(out, rb_output_fs);
8707  }
8708  rb_io_write(out, argv[i]);
8709  }
8710  if (argc > 0 && !NIL_P(rb_output_rs)) {
8711  rb_io_write(out, rb_output_rs);
8712  }
8713 
8714  return Qnil;
8715 }
8716 
8717 /*
8718  * call-seq:
8719  * print(*objects) -> nil
8720  *
8721  * Equivalent to <tt>$stdout.print(*objects)</tt>,
8722  * this method is the straightforward way to write to <tt>$stdout</tt>.
8723  *
8724  * Writes the given objects to <tt>$stdout</tt>; returns +nil+.
8725  * Appends the output record separator <tt>$OUTPUT_RECORD_SEPARATOR</tt>
8726  * <tt>$\</tt>), if it is not +nil+.
8727  *
8728  * With argument +objects+ given, for each object:
8729  *
8730  * - Converts via its method +to_s+ if not a string.
8731  * - Writes to <tt>stdout</tt>.
8732  * - If not the last object, writes the output field separator
8733  * <tt>$OUTPUT_FIELD_SEPARATOR</tt> (<tt>$,</tt> if it is not +nil+.
8734  *
8735  * With default separators:
8736  *
8737  * objects = [0, 0.0, Rational(0, 1), Complex(0, 0), :zero, 'zero']
8738  * $OUTPUT_RECORD_SEPARATOR
8739  * $OUTPUT_FIELD_SEPARATOR
8740  * print(*objects)
8741  *
8742  * Output:
8743  *
8744  * nil
8745  * nil
8746  * 00.00/10+0izerozero
8747  *
8748  * With specified separators:
8749  *
8750  * $OUTPUT_RECORD_SEPARATOR = "\n"
8751  * $OUTPUT_FIELD_SEPARATOR = ','
8752  * print(*objects)
8753  *
8754  * Output:
8755  *
8756  * 0,0.0,0/1,0+0i,zero,zero
8757  *
8758  * With no argument given, writes the content of <tt>$_</tt>
8759  * (which is usually the most recent user input):
8760  *
8761  * gets # Sets $_ to the most recent user input.
8762  * print # Prints $_.
8763  *
8764  */
8765 
8766 static VALUE
8767 rb_f_print(int argc, const VALUE *argv, VALUE _)
8768 {
8769  rb_io_print(argc, argv, rb_ractor_stdout());
8770  return Qnil;
8771 }
8772 
8773 /*
8774  * call-seq:
8775  * putc(object) -> object
8776  *
8777  * Writes a character to the stream.
8778  * See {Character IO}[rdoc-ref:IO@Character+IO].
8779  *
8780  * If +object+ is numeric, converts to integer if necessary,
8781  * then writes the character whose code is the
8782  * least significant byte;
8783  * if +object+ is a string, writes the first character:
8784  *
8785  * $stdout.putc "A"
8786  * $stdout.putc 65
8787  *
8788  * Output:
8789  *
8790  * AA
8791  *
8792  */
8793 
8794 static VALUE
8795 rb_io_putc(VALUE io, VALUE ch)
8796 {
8797  VALUE str;
8798  if (RB_TYPE_P(ch, T_STRING)) {
8799  str = rb_str_substr(ch, 0, 1);
8800  }
8801  else {
8802  char c = NUM2CHR(ch);
8803  str = rb_str_new(&c, 1);
8804  }
8805  rb_io_write(io, str);
8806  return ch;
8807 }
8808 
8809 #define forward(obj, id, argc, argv) \
8810  rb_funcallv_kw(obj, id, argc, argv, RB_PASS_CALLED_KEYWORDS)
8811 #define forward_public(obj, id, argc, argv) \
8812  rb_funcallv_public_kw(obj, id, argc, argv, RB_PASS_CALLED_KEYWORDS)
8813 #define forward_current(id, argc, argv) \
8814  forward_public(ARGF.current_file, id, argc, argv)
8815 
8816 /*
8817  * call-seq:
8818  * putc(int) -> int
8819  *
8820  * Equivalent to:
8821  *
8822  * $stdout.putc(int)
8823  *
8824  * See IO#putc for important information regarding multi-byte characters.
8825  *
8826  */
8827 
8828 static VALUE
8829 rb_f_putc(VALUE recv, VALUE ch)
8830 {
8831  VALUE r_stdout = rb_ractor_stdout();
8832  if (recv == r_stdout) {
8833  return rb_io_putc(recv, ch);
8834  }
8835  return forward(r_stdout, rb_intern("putc"), 1, &ch);
8836 }
8837 
8838 
8839 int
8840 rb_str_end_with_asciichar(VALUE str, int c)
8841 {
8842  long len = RSTRING_LEN(str);
8843  const char *ptr = RSTRING_PTR(str);
8845  int n;
8846 
8847  if (len == 0) return 0;
8848  if ((n = rb_enc_mbminlen(enc)) == 1) {
8849  return ptr[len - 1] == c;
8850  }
8851  return rb_enc_ascget(ptr + ((len - 1) / n) * n, ptr + len, &n, enc) == c;
8852 }
8853 
8854 static VALUE
8855 io_puts_ary(VALUE ary, VALUE out, int recur)
8856 {
8857  VALUE tmp;
8858  long i;
8859 
8860  if (recur) {
8861  tmp = rb_str_new2("[...]");
8862  rb_io_puts(1, &tmp, out);
8863  return Qtrue;
8864  }
8865  ary = rb_check_array_type(ary);
8866  if (NIL_P(ary)) return Qfalse;
8867  for (i=0; i<RARRAY_LEN(ary); i++) {
8868  tmp = RARRAY_AREF(ary, i);
8869  rb_io_puts(1, &tmp, out);
8870  }
8871  return Qtrue;
8872 }
8873 
8874 /*
8875  * call-seq:
8876  * puts(*objects) -> nil
8877  *
8878  * Writes the given +objects+ to the stream, which must be open for writing;
8879  * returns +nil+.\
8880  * Writes a newline after each that does not already end with a newline sequence.
8881  * If called without arguments, writes a newline.
8882  * See {Line IO}[rdoc-ref:IO@Line+IO].
8883  *
8884  * Note that each added newline is the character <tt>"\n"<//tt>,
8885  * not the output record separator (<tt>$\</tt>).
8886  *
8887  * Treatment for each object:
8888  *
8889  * - String: writes the string.
8890  * - Neither string nor array: writes <tt>object.to_s</tt>.
8891  * - Array: writes each element of the array; arrays may be nested.
8892  *
8893  * To keep these examples brief, we define this helper method:
8894  *
8895  * def show(*objects)
8896  * # Puts objects to file.
8897  * f = File.new('t.tmp', 'w+')
8898  * f.puts(objects)
8899  * # Return file content.
8900  * f.rewind
8901  * p f.read
8902  * f.close
8903  * end
8904  *
8905  * # Strings without newlines.
8906  * show('foo', 'bar', 'baz') # => "foo\nbar\nbaz\n"
8907  * # Strings, some with newlines.
8908  * show("foo\n", 'bar', "baz\n") # => "foo\nbar\nbaz\n"
8909  *
8910  * # Neither strings nor arrays:
8911  * show(0, 0.0, Rational(0, 1), Complex(9, 0), :zero)
8912  * # => "0\n0.0\n0/1\n9+0i\nzero\n"
8913  *
8914  * # Array of strings.
8915  * show(['foo', "bar\n", 'baz']) # => "foo\nbar\nbaz\n"
8916  * # Nested arrays.
8917  * show([[[0, 1], 2, 3], 4, 5]) # => "0\n1\n2\n3\n4\n5\n"
8918  *
8919  */
8920 
8921 VALUE
8922 rb_io_puts(int argc, const VALUE *argv, VALUE out)
8923 {
8924  VALUE line, args[2];
8925 
8926  /* if no argument given, print newline. */
8927  if (argc == 0) {
8928  rb_io_write(out, rb_default_rs);
8929  return Qnil;
8930  }
8931  for (int i = 0; i < argc; i++) {
8932  // Convert the argument to a string:
8933  if (RB_TYPE_P(argv[i], T_STRING)) {
8934  line = argv[i];
8935  }
8936  else if (rb_exec_recursive(io_puts_ary, argv[i], out)) {
8937  continue;
8938  }
8939  else {
8940  line = rb_obj_as_string(argv[i]);
8941  }
8942 
8943  // Write the line:
8944  int n = 0;
8945  if (RSTRING_LEN(line) == 0) {
8946  args[n++] = rb_default_rs;
8947  }
8948  else {
8949  args[n++] = line;
8950  if (!rb_str_end_with_asciichar(line, '\n')) {
8951  args[n++] = rb_default_rs;
8952  }
8953  }
8954 
8955  rb_io_writev(out, n, args);
8956  }
8957 
8958  return Qnil;
8959 }
8960 
8961 /*
8962  * call-seq:
8963  * puts(*objects) -> nil
8964  *
8965  * Equivalent to
8966  *
8967  * $stdout.puts(objects)
8968  */
8969 
8970 static VALUE
8971 rb_f_puts(int argc, VALUE *argv, VALUE recv)
8972 {
8973  VALUE r_stdout = rb_ractor_stdout();
8974  if (recv == r_stdout) {
8975  return rb_io_puts(argc, argv, recv);
8976  }
8977  return forward(r_stdout, rb_intern("puts"), argc, argv);
8978 }
8979 
8980 static VALUE
8981 rb_p_write(VALUE str)
8982 {
8983  VALUE args[2];
8984  args[0] = str;
8985  args[1] = rb_default_rs;
8986  VALUE r_stdout = rb_ractor_stdout();
8987  if (RB_TYPE_P(r_stdout, T_FILE) &&
8988  rb_method_basic_definition_p(CLASS_OF(r_stdout), id_write)) {
8989  io_writev(2, args, r_stdout);
8990  }
8991  else {
8992  rb_io_writev(r_stdout, 2, args);
8993  }
8994  return Qnil;
8995 }
8996 
8997 void
8998 rb_p(VALUE obj) /* for debug print within C code */
8999 {
9000  rb_p_write(rb_obj_as_string(rb_inspect(obj)));
9001 }
9002 
9003 static VALUE
9004 rb_p_result(int argc, const VALUE *argv)
9005 {
9006  VALUE ret = Qnil;
9007 
9008  if (argc == 1) {
9009  ret = argv[0];
9010  }
9011  else if (argc > 1) {
9012  ret = rb_ary_new4(argc, argv);
9013  }
9014  VALUE r_stdout = rb_ractor_stdout();
9015  if (RB_TYPE_P(r_stdout, T_FILE)) {
9016  rb_uninterruptible(rb_io_flush, r_stdout);
9017  }
9018  return ret;
9019 }
9020 
9021 /*
9022  * call-seq:
9023  * p(object) -> obj
9024  * p(*objects) -> array of objects
9025  * p -> nil
9026  *
9027  * For each object +obj+, executes:
9028  *
9029  * $stdout.write(obj.inspect, "\n")
9030  *
9031  * With one object given, returns the object;
9032  * with multiple objects given, returns an array containing the objects;
9033  * with no object given, returns +nil+.
9034  *
9035  * Examples:
9036  *
9037  * r = Range.new(0, 4)
9038  * p r # => 0..4
9039  * p [r, r, r] # => [0..4, 0..4, 0..4]
9040  * p # => nil
9041  *
9042  * Output:
9043  *
9044  * 0..4
9045  * [0..4, 0..4, 0..4]
9046  *
9047  * Kernel#p is designed for debugging purposes.
9048  * Ruby implementations may define Kernel#p to be uninterruptible
9049  * in whole or in part.
9050  * On CRuby, Kernel#p's writing of data is uninterruptible.
9051  */
9052 
9053 static VALUE
9054 rb_f_p(int argc, VALUE *argv, VALUE self)
9055 {
9056  int i;
9057  for (i=0; i<argc; i++) {
9058  VALUE inspected = rb_obj_as_string(rb_inspect(argv[i]));
9059  rb_uninterruptible(rb_p_write, inspected);
9060  }
9061  return rb_p_result(argc, argv);
9062 }
9063 
9064 /*
9065  * call-seq:
9066  * display(port = $>) -> nil
9067  *
9068  * Writes +self+ on the given port:
9069  *
9070  * 1.display
9071  * "cat".display
9072  * [ 4, 5, 6 ].display
9073  * puts
9074  *
9075  * Output:
9076  *
9077  * 1cat[4, 5, 6]
9078  *
9079  */
9080 
9081 static VALUE
9082 rb_obj_display(int argc, VALUE *argv, VALUE self)
9083 {
9084  VALUE out;
9085 
9086  out = (!rb_check_arity(argc, 0, 1) ? rb_ractor_stdout() : argv[0]);
9087  rb_io_write(out, self);
9088 
9089  return Qnil;
9090 }
9091 
9092 static int
9093 rb_stderr_to_original_p(VALUE err)
9094 {
9095  return (err == orig_stderr || RFILE(orig_stderr)->fptr->fd < 0);
9096 }
9097 
9098 void
9099 rb_write_error2(const char *mesg, long len)
9100 {
9101  VALUE out = rb_ractor_stderr();
9102  if (rb_stderr_to_original_p(out)) {
9103 #ifdef _WIN32
9104  if (isatty(fileno(stderr))) {
9105  if (rb_w32_write_console(rb_str_new(mesg, len), fileno(stderr)) > 0) return;
9106  }
9107 #endif
9108  if (fwrite(mesg, sizeof(char), (size_t)len, stderr) < (size_t)len) {
9109  /* failed to write to stderr, what can we do? */
9110  return;
9111  }
9112  }
9113  else {
9114  rb_io_write(out, rb_str_new(mesg, len));
9115  }
9116 }
9117 
9118 void
9119 rb_write_error(const char *mesg)
9120 {
9121  rb_write_error2(mesg, strlen(mesg));
9122 }
9123 
9124 void
9125 rb_write_error_str(VALUE mesg)
9126 {
9127  VALUE out = rb_ractor_stderr();
9128  /* a stopgap measure for the time being */
9129  if (rb_stderr_to_original_p(out)) {
9130  size_t len = (size_t)RSTRING_LEN(mesg);
9131 #ifdef _WIN32
9132  if (isatty(fileno(stderr))) {
9133  if (rb_w32_write_console(mesg, fileno(stderr)) > 0) return;
9134  }
9135 #endif
9136  if (fwrite(RSTRING_PTR(mesg), sizeof(char), len, stderr) < len) {
9137  RB_GC_GUARD(mesg);
9138  return;
9139  }
9140  }
9141  else {
9142  /* may unlock GVL, and */
9143  rb_io_write(out, mesg);
9144  }
9145 }
9146 
9147 int
9148 rb_stderr_tty_p(void)
9149 {
9150  if (rb_stderr_to_original_p(rb_ractor_stderr()))
9151  return isatty(fileno(stderr));
9152  return 0;
9153 }
9154 
9155 static void
9156 must_respond_to(ID mid, VALUE val, ID id)
9157 {
9158  if (!rb_respond_to(val, mid)) {
9159  rb_raise(rb_eTypeError, "%"PRIsVALUE" must have %"PRIsVALUE" method, %"PRIsVALUE" given",
9160  rb_id2str(id), rb_id2str(mid),
9161  rb_obj_class(val));
9162  }
9163 }
9164 
9165 static void
9166 stdin_setter(VALUE val, ID id, VALUE *ptr)
9167 {
9168  rb_ractor_stdin_set(val);
9169 }
9170 
9171 static VALUE
9172 stdin_getter(ID id, VALUE *ptr)
9173 {
9174  return rb_ractor_stdin();
9175 }
9176 
9177 static void
9178 stdout_setter(VALUE val, ID id, VALUE *ptr)
9179 {
9180  must_respond_to(id_write, val, id);
9181  rb_ractor_stdout_set(val);
9182 }
9183 
9184 static VALUE
9185 stdout_getter(ID id, VALUE *ptr)
9186 {
9187  return rb_ractor_stdout();
9188 }
9189 
9190 static void
9191 stderr_setter(VALUE val, ID id, VALUE *ptr)
9192 {
9193  must_respond_to(id_write, val, id);
9194  rb_ractor_stderr_set(val);
9195 }
9196 
9197 static VALUE
9198 stderr_getter(ID id, VALUE *ptr)
9199 {
9200  return rb_ractor_stderr();
9201 }
9202 
9203 static VALUE
9204 allocate_and_open_new_file(VALUE klass)
9205 {
9206  VALUE self = io_alloc(klass);
9207  rb_io_make_open_file(self);
9208  return self;
9209 }
9210 
9211 VALUE
9212 rb_io_open_descriptor(VALUE klass, int descriptor, int mode, VALUE path, VALUE timeout, struct rb_io_encoding *encoding)
9213 {
9214  int state;
9215  VALUE self = rb_protect(allocate_and_open_new_file, klass, &state);
9216  if (state) {
9217  /* if we raised an exception allocating an IO object, but the caller
9218  intended to transfer ownership of this FD to us, close the fd before
9219  raising the exception. Otherwise, we would leak a FD - the caller
9220  expects GC to close the file, but we never got around to assigning
9221  it to a rb_io. */
9222  if (!(mode & FMODE_EXTERNAL)) {
9223  maygvl_close(descriptor, 0);
9224  }
9225  rb_jump_tag(state);
9226  }
9227 
9228 
9229  rb_io_t *io = RFILE(self)->fptr;
9230  io->self = self;
9231  io->fd = descriptor;
9232  io->mode = mode;
9233 
9234  /* At this point, Ruby fully owns the descriptor, and will close it when
9235  the IO gets GC'd (unless FMODE_EXTERNAL was set), no matter what happens
9236  in the rest of this method. */
9237 
9238  if (NIL_P(path)) {
9239  io->pathv = Qnil;
9240  }
9241  else {
9242  StringValue(path);
9243  io->pathv = rb_str_new_frozen(path);
9244  }
9245 
9246  io->timeout = timeout;
9247 
9248  if (encoding) {
9249  io->encs = *encoding;
9250  }
9251 
9252  rb_update_max_fd(descriptor);
9253 
9254  return self;
9255 }
9256 
9257 static VALUE
9258 prep_io(int fd, int fmode, VALUE klass, const char *path)
9259 {
9260  VALUE path_value = Qnil;
9261  rb_encoding *e;
9262  struct rb_io_encoding convconfig;
9263 
9264  if (path) {
9265  path_value = rb_obj_freeze(rb_str_new_cstr(path));
9266  }
9267 
9268  e = (fmode & FMODE_BINMODE) ? rb_ascii8bit_encoding() : NULL;
9269  rb_io_ext_int_to_encs(e, NULL, &convconfig.enc, &convconfig.enc2, fmode);
9270  convconfig.ecflags = (fmode & FMODE_READABLE) ?
9271  MODE_BTMODE(ECONV_DEFAULT_NEWLINE_DECORATOR,
9273 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
9274  convconfig.ecflags |= (fmode & FMODE_WRITABLE) ?
9275  MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE,
9276  0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE) : 0;
9277 #endif
9278  SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(convconfig.enc2, convconfig.ecflags);
9279  convconfig.ecopts = Qnil;
9280 
9281  VALUE self = rb_io_open_descriptor(klass, fd, fmode, path_value, Qnil, &convconfig);
9282  rb_io_t*io = RFILE(self)->fptr;
9283 
9284  if (!io_check_tty(io)) {
9285 #ifdef __CYGWIN__
9286  io->mode |= FMODE_BINMODE;
9287  setmode(fd, O_BINARY);
9288 #endif
9289  }
9290 
9291  return self;
9292 }
9293 
9294 VALUE
9295 rb_io_fdopen(int fd, int oflags, const char *path)
9296 {
9297  VALUE klass = rb_cIO;
9298 
9299  if (path && strcmp(path, "-")) klass = rb_cFile;
9300  return prep_io(fd, rb_io_oflags_fmode(oflags), klass, path);
9301 }
9302 
9303 static VALUE
9304 prep_stdio(FILE *f, int fmode, VALUE klass, const char *path)
9305 {
9306  rb_io_t *fptr;
9307  VALUE io = prep_io(fileno(f), fmode|FMODE_EXTERNAL|DEFAULT_TEXTMODE, klass, path);
9308 
9309  GetOpenFile(io, fptr);
9311 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
9312  fptr->encs.ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
9313  if (fmode & FMODE_READABLE) {
9315  }
9316 #endif
9317  fptr->stdio_file = f;
9318 
9319  return io;
9320 }
9321 
9322 VALUE
9323 rb_io_prep_stdin(void)
9324 {
9325  return prep_stdio(stdin, FMODE_READABLE, rb_cIO, "<STDIN>");
9326 }
9327 
9328 VALUE
9329 rb_io_prep_stdout(void)
9330 {
9331  return prep_stdio(stdout, FMODE_WRITABLE|FMODE_SIGNAL_ON_EPIPE, rb_cIO, "<STDOUT>");
9332 }
9333 
9334 VALUE
9335 rb_io_prep_stderr(void)
9336 {
9337  return prep_stdio(stderr, FMODE_WRITABLE|FMODE_SYNC, rb_cIO, "<STDERR>");
9338 }
9339 
9340 FILE *
9342 {
9343  if (!fptr->stdio_file) {
9344  int oflags = rb_io_fmode_oflags(fptr->mode) & ~O_EXCL;
9345  fptr->stdio_file = rb_fdopen(fptr->fd, rb_io_oflags_modestr(oflags));
9346  }
9347  return fptr->stdio_file;
9348 }
9349 
9350 static inline void
9351 rb_io_buffer_init(struct rb_io_internal_buffer *buf)
9352 {
9353  buf->ptr = NULL;
9354  buf->off = 0;
9355  buf->len = 0;
9356  buf->capa = 0;
9357 }
9358 
9359 static inline rb_io_t *
9360 rb_io_fptr_new(void)
9361 {
9362  rb_io_t *fp = ALLOC(rb_io_t);
9363  fp->self = Qnil;
9364  fp->fd = -1;
9365  fp->stdio_file = NULL;
9366  fp->mode = 0;
9367  fp->pid = 0;
9368  fp->lineno = 0;
9369  fp->pathv = Qnil;
9370  fp->finalize = 0;
9371  rb_io_buffer_init(&fp->wbuf);
9372  rb_io_buffer_init(&fp->rbuf);
9373  rb_io_buffer_init(&fp->cbuf);
9374  fp->readconv = NULL;
9375  fp->writeconv = NULL;
9377  fp->writeconv_pre_ecflags = 0;
9378  fp->writeconv_pre_ecopts = Qnil;
9379  fp->writeconv_initialized = 0;
9380  fp->tied_io_for_writing = 0;
9381  fp->encs.enc = NULL;
9382  fp->encs.enc2 = NULL;
9383  fp->encs.ecflags = 0;
9384  fp->encs.ecopts = Qnil;
9385  fp->write_lock = Qnil;
9386  fp->timeout = Qnil;
9387  return fp;
9388 }
9389 
9390 rb_io_t *
9391 rb_io_make_open_file(VALUE obj)
9392 {
9393  rb_io_t *fp = 0;
9394 
9395  Check_Type(obj, T_FILE);
9396  if (RFILE(obj)->fptr) {
9397  rb_io_close(obj);
9398  rb_io_fptr_finalize(RFILE(obj)->fptr);
9399  RFILE(obj)->fptr = 0;
9400  }
9401  fp = rb_io_fptr_new();
9402  fp->self = obj;
9403  RFILE(obj)->fptr = fp;
9404  return fp;
9405 }
9406 
9407 static VALUE io_initialize(VALUE io, VALUE fnum, VALUE vmode, VALUE opt);
9408 
9409 /*
9410  * call-seq:
9411  * IO.new(fd, mode = 'r', **opts) -> io
9412  *
9413  * Creates and returns a new \IO object (file stream) from a file descriptor.
9414  *
9415  * \IO.new may be useful for interaction with low-level libraries.
9416  * For higher-level interactions, it may be simpler to create
9417  * the file stream using File.open.
9418  *
9419  * Argument +fd+ must be a valid file descriptor (integer):
9420  *
9421  * path = 't.tmp'
9422  * fd = IO.sysopen(path) # => 3
9423  * IO.new(fd) # => #<IO:fd 3>
9424  *
9425  * The new \IO object does not inherit encoding
9426  * (because the integer file descriptor does not have an encoding):
9427  *
9428  * fd = IO.sysopen('t.rus', 'rb')
9429  * io = IO.new(fd)
9430  * io.external_encoding # => #<Encoding:UTF-8> # Not ASCII-8BIT.
9431  *
9432  * Optional argument +mode+ (defaults to 'r') must specify a valid mode;
9433  * see {Access Modes}[rdoc-ref:File@Access+Modes]:
9434  *
9435  * IO.new(fd, 'w') # => #<IO:fd 3>
9436  * IO.new(fd, File::WRONLY) # => #<IO:fd 3>
9437  *
9438  * Optional keyword arguments +opts+ specify:
9439  *
9440  * - {Open Options}[rdoc-ref:IO@Open+Options].
9441  * - {Encoding options}[rdoc-ref:encodings.rdoc@Encoding+Options].
9442  *
9443  * Examples:
9444  *
9445  * IO.new(fd, internal_encoding: nil) # => #<IO:fd 3>
9446  * IO.new(fd, autoclose: true) # => #<IO:fd 3>
9447  *
9448  */
9449 
9450 static VALUE
9451 rb_io_initialize(int argc, VALUE *argv, VALUE io)
9452 {
9453  VALUE fnum, vmode;
9454  VALUE opt;
9455 
9456  rb_scan_args(argc, argv, "11:", &fnum, &vmode, &opt);
9457  return io_initialize(io, fnum, vmode, opt);
9458 }
9459 
9460 static VALUE
9461 io_initialize(VALUE io, VALUE fnum, VALUE vmode, VALUE opt)
9462 {
9463  rb_io_t *fp;
9464  int fd, fmode, oflags = O_RDONLY;
9465  struct rb_io_encoding convconfig;
9466 #if defined(HAVE_FCNTL) && defined(F_GETFL)
9467  int ofmode;
9468 #else
9469  struct stat st;
9470 #endif
9471 
9472  rb_io_extract_modeenc(&vmode, 0, opt, &oflags, &fmode, &convconfig);
9473 
9474  fd = NUM2INT(fnum);
9475  if (rb_reserved_fd_p(fd)) {
9476  rb_raise(rb_eArgError, "The given fd is not accessible because RubyVM reserves it");
9477  }
9478 #if defined(HAVE_FCNTL) && defined(F_GETFL)
9479  oflags = fcntl(fd, F_GETFL);
9480  if (oflags == -1) rb_sys_fail(0);
9481 #else
9482  if (fstat(fd, &st) < 0) rb_sys_fail(0);
9483 #endif
9484  rb_update_max_fd(fd);
9485 #if defined(HAVE_FCNTL) && defined(F_GETFL)
9486  ofmode = rb_io_oflags_fmode(oflags);
9487  if (NIL_P(vmode)) {
9488  fmode = ofmode;
9489  }
9490  else if ((~ofmode & fmode) & FMODE_READWRITE) {
9491  VALUE error = INT2FIX(EINVAL);
9493  }
9494 #endif
9495  VALUE path = Qnil;
9496 
9497  if (!NIL_P(opt)) {
9498  if (rb_hash_aref(opt, sym_autoclose) == Qfalse) {
9499  fmode |= FMODE_EXTERNAL;
9500  }
9501 
9502  path = rb_hash_aref(opt, RB_ID2SYM(idPath));
9503  if (!NIL_P(path)) {
9504  StringValue(path);
9505  path = rb_str_new_frozen(path);
9506  }
9507  }
9508 
9509  MakeOpenFile(io, fp);
9510  fp->self = io;
9511  fp->fd = fd;
9512  fp->mode = fmode;
9513  fp->encs = convconfig;
9514  fp->pathv = path;
9515  fp->timeout = Qnil;
9516  clear_codeconv(fp);
9517  io_check_tty(fp);
9518  if (fileno(stdin) == fd)
9519  fp->stdio_file = stdin;
9520  else if (fileno(stdout) == fd)
9521  fp->stdio_file = stdout;
9522  else if (fileno(stderr) == fd)
9523  fp->stdio_file = stderr;
9524 
9525  if (fmode & FMODE_SETENC_BY_BOM) io_set_encoding_by_bom(io);
9526  return io;
9527 }
9528 
9529 /*
9530  * call-seq:
9531  * set_encoding_by_bom -> encoding or nil
9532  *
9533  * If the stream begins with a BOM
9534  * ({byte order marker}[https://en.wikipedia.org/wiki/Byte_order_mark]),
9535  * consumes the BOM and sets the external encoding accordingly;
9536  * returns the result encoding if found, or +nil+ otherwise:
9537  *
9538  * File.write('t.tmp', "\u{FEFF}abc")
9539  * io = File.open('t.tmp', 'rb')
9540  * io.set_encoding_by_bom # => #<Encoding:UTF-8>
9541  * io.close
9542  *
9543  * File.write('t.tmp', 'abc')
9544  * io = File.open('t.tmp', 'rb')
9545  * io.set_encoding_by_bom # => nil
9546  * io.close
9547  *
9548  * Raises an exception if the stream is not binmode
9549  * or its encoding has already been set.
9550  *
9551  */
9552 
9553 static VALUE
9554 rb_io_set_encoding_by_bom(VALUE io)
9555 {
9556  rb_io_t *fptr;
9557 
9558  GetOpenFile(io, fptr);
9559  if (!(fptr->mode & FMODE_BINMODE)) {
9560  rb_raise(rb_eArgError, "ASCII incompatible encoding needs binmode");
9561  }
9562  if (fptr->encs.enc2) {
9563  rb_raise(rb_eArgError, "encoding conversion is set");
9564  }
9565  else if (fptr->encs.enc && fptr->encs.enc != rb_ascii8bit_encoding()) {
9566  rb_raise(rb_eArgError, "encoding is set to %s already",
9567  rb_enc_name(fptr->encs.enc));
9568  }
9569  if (!io_set_encoding_by_bom(io)) return Qnil;
9570  return rb_enc_from_encoding(fptr->encs.enc);
9571 }
9572 
9573 /*
9574  * call-seq:
9575  * File.new(path, mode = 'r', perm = 0666, **opts) -> file
9576  *
9577  * Opens the file at the given +path+ according to the given +mode+;
9578  * creates and returns a new File object for that file.
9579  *
9580  * The new File object is buffered mode (or non-sync mode), unless
9581  * +filename+ is a tty.
9582  * See IO#flush, IO#fsync, IO#fdatasync, and IO#sync=.
9583  *
9584  * Argument +path+ must be a valid file path:
9585  *
9586  * f = File.new('/etc/fstab')
9587  * f.close
9588  * f = File.new('t.txt')
9589  * f.close
9590  *
9591  * Optional argument +mode+ (defaults to 'r') must specify a valid mode;
9592  * see {Access Modes}[rdoc-ref:File@Access+Modes]:
9593  *
9594  * f = File.new('t.tmp', 'w')
9595  * f.close
9596  * f = File.new('t.tmp', File::RDONLY)
9597  * f.close
9598  *
9599  * Optional argument +perm+ (defaults to 0666) must specify valid permissions
9600  * see {File Permissions}[rdoc-ref:File@File+Permissions]:
9601  *
9602  * f = File.new('t.tmp', File::CREAT, 0644)
9603  * f.close
9604  * f = File.new('t.tmp', File::CREAT, 0444)
9605  * f.close
9606  *
9607  * Optional keyword arguments +opts+ specify:
9608  *
9609  * - {Open Options}[rdoc-ref:IO@Open+Options].
9610  * - {Encoding options}[rdoc-ref:encodings.rdoc@Encoding+Options].
9611  *
9612  */
9613 
9614 static VALUE
9615 rb_file_initialize(int argc, VALUE *argv, VALUE io)
9616 {
9617  if (RFILE(io)->fptr) {
9618  rb_raise(rb_eRuntimeError, "reinitializing File");
9619  }
9620  VALUE fname, vmode, vperm, opt;
9621  int posargc = rb_scan_args(argc, argv, "12:", &fname, &vmode, &vperm, &opt);
9622  if (posargc < 3) { /* perm is File only */
9623  VALUE fd = rb_check_to_int(fname);
9624 
9625  if (!NIL_P(fd)) {
9626  return io_initialize(io, fd, vmode, opt);
9627  }
9628  }
9629  return rb_open_file(io, fname, vmode, vperm, opt);
9630 }
9631 
9632 /* :nodoc: */
9633 static VALUE
9634 rb_io_s_new(int argc, VALUE *argv, VALUE klass)
9635 {
9636  if (rb_block_given_p()) {
9637  VALUE cname = rb_obj_as_string(klass);
9638 
9639  rb_warn("%"PRIsVALUE"::new() does not take block; use %"PRIsVALUE"::open() instead",
9640  cname, cname);
9641  }
9642  return rb_class_new_instance_kw(argc, argv, klass, RB_PASS_CALLED_KEYWORDS);
9643 }
9644 
9645 
9646 /*
9647  * call-seq:
9648  * IO.for_fd(fd, mode = 'r', **opts) -> io
9649  *
9650  * Synonym for IO.new.
9651  *
9652  */
9653 
9654 static VALUE
9655 rb_io_s_for_fd(int argc, VALUE *argv, VALUE klass)
9656 {
9657  VALUE io = rb_obj_alloc(klass);
9658  rb_io_initialize(argc, argv, io);
9659  return io;
9660 }
9661 
9662 /*
9663  * call-seq:
9664  * ios.autoclose? -> true or false
9665  *
9666  * Returns +true+ if the underlying file descriptor of _ios_ will be
9667  * closed at its finalization or at calling #close, otherwise +false+.
9668  */
9669 
9670 static VALUE
9671 rb_io_autoclose_p(VALUE io)
9672 {
9673  rb_io_t *fptr = RFILE(io)->fptr;
9674  rb_io_check_closed(fptr);
9675  return RBOOL(!(fptr->mode & FMODE_EXTERNAL));
9676 }
9677 
9678 /*
9679  * call-seq:
9680  * io.autoclose = bool -> true or false
9681  *
9682  * Sets auto-close flag.
9683  *
9684  * f = File.open(File::NULL)
9685  * IO.for_fd(f.fileno).close
9686  * f.gets # raises Errno::EBADF
9687  *
9688  * f = File.open(File::NULL)
9689  * g = IO.for_fd(f.fileno)
9690  * g.autoclose = false
9691  * g.close
9692  * f.gets # won't cause Errno::EBADF
9693  */
9694 
9695 static VALUE
9696 rb_io_set_autoclose(VALUE io, VALUE autoclose)
9697 {
9698  rb_io_t *fptr;
9699  GetOpenFile(io, fptr);
9700  if (!RTEST(autoclose))
9701  fptr->mode |= FMODE_EXTERNAL;
9702  else
9703  fptr->mode &= ~FMODE_EXTERNAL;
9704  return autoclose;
9705 }
9706 
9707 static VALUE
9708 io_wait_event(VALUE io, int event, VALUE timeout, int return_io)
9709 {
9710  VALUE result = rb_io_wait(io, RB_INT2NUM(event), timeout);
9711 
9712  if (!RB_TEST(result)) {
9713  return Qnil;
9714  }
9715 
9716  int mask = RB_NUM2INT(result);
9717 
9718  if (mask & event) {
9719  if (return_io)
9720  return io;
9721  else
9722  return result;
9723  }
9724  else {
9725  return Qfalse;
9726  }
9727 }
9728 
9729 /*
9730  * call-seq:
9731  * io.wait_readable -> truthy or falsy
9732  * io.wait_readable(timeout) -> truthy or falsy
9733  *
9734  * Waits until IO is readable and returns a truthy value, or a falsy
9735  * value when times out. Returns a truthy value immediately when
9736  * buffered data is available.
9737  */
9738 
9739 static VALUE
9740 io_wait_readable(int argc, VALUE *argv, VALUE io)
9741 {
9742  rb_io_t *fptr;
9743 
9744  RB_IO_POINTER(io, fptr);
9745  rb_io_check_readable(fptr);
9746 
9747  if (rb_io_read_pending(fptr)) return Qtrue;
9748 
9749  rb_check_arity(argc, 0, 1);
9750  VALUE timeout = (argc == 1 ? argv[0] : Qnil);
9751 
9752  return io_wait_event(io, RUBY_IO_READABLE, timeout, 1);
9753 }
9754 
9755 /*
9756  * call-seq:
9757  * io.wait_writable -> truthy or falsy
9758  * io.wait_writable(timeout) -> truthy or falsy
9759  *
9760  * Waits until IO is writable and returns a truthy value or a falsy
9761  * value when times out.
9762  */
9763 static VALUE
9764 io_wait_writable(int argc, VALUE *argv, VALUE io)
9765 {
9766  rb_io_t *fptr;
9767 
9768  RB_IO_POINTER(io, fptr);
9769  rb_io_check_writable(fptr);
9770 
9771  rb_check_arity(argc, 0, 1);
9772  VALUE timeout = (argc == 1 ? argv[0] : Qnil);
9773 
9774  return io_wait_event(io, RUBY_IO_WRITABLE, timeout, 1);
9775 }
9776 
9777 /*
9778  * call-seq:
9779  * io.wait_priority -> truthy or falsy
9780  * io.wait_priority(timeout) -> truthy or falsy
9781  *
9782  * Waits until IO is priority and returns a truthy value or a falsy
9783  * value when times out. Priority data is sent and received using
9784  * the Socket::MSG_OOB flag and is typically limited to streams.
9785  */
9786 static VALUE
9787 io_wait_priority(int argc, VALUE *argv, VALUE io)
9788 {
9789  rb_io_t *fptr = NULL;
9790 
9791  RB_IO_POINTER(io, fptr);
9792  rb_io_check_readable(fptr);
9793 
9794  if (rb_io_read_pending(fptr)) return Qtrue;
9795 
9796  rb_check_arity(argc, 0, 1);
9797  VALUE timeout = argc == 1 ? argv[0] : Qnil;
9798 
9799  return io_wait_event(io, RUBY_IO_PRIORITY, timeout, 1);
9800 }
9801 
9802 static int
9803 wait_mode_sym(VALUE mode)
9804 {
9805  if (mode == ID2SYM(rb_intern("r"))) {
9806  return RB_WAITFD_IN;
9807  }
9808  if (mode == ID2SYM(rb_intern("read"))) {
9809  return RB_WAITFD_IN;
9810  }
9811  if (mode == ID2SYM(rb_intern("readable"))) {
9812  return RB_WAITFD_IN;
9813  }
9814  if (mode == ID2SYM(rb_intern("w"))) {
9815  return RB_WAITFD_OUT;
9816  }
9817  if (mode == ID2SYM(rb_intern("write"))) {
9818  return RB_WAITFD_OUT;
9819  }
9820  if (mode == ID2SYM(rb_intern("writable"))) {
9821  return RB_WAITFD_OUT;
9822  }
9823  if (mode == ID2SYM(rb_intern("rw"))) {
9824  return RB_WAITFD_IN|RB_WAITFD_OUT;
9825  }
9826  if (mode == ID2SYM(rb_intern("read_write"))) {
9827  return RB_WAITFD_IN|RB_WAITFD_OUT;
9828  }
9829  if (mode == ID2SYM(rb_intern("readable_writable"))) {
9830  return RB_WAITFD_IN|RB_WAITFD_OUT;
9831  }
9832 
9833  rb_raise(rb_eArgError, "unsupported mode: %"PRIsVALUE, mode);
9834 }
9835 
9836 static inline enum rb_io_event
9837 io_event_from_value(VALUE value)
9838 {
9839  int events = RB_NUM2INT(value);
9840 
9841  if (events <= 0) rb_raise(rb_eArgError, "Events must be positive integer!");
9842 
9843  return events;
9844 }
9845 
9846 /*
9847  * call-seq:
9848  * io.wait(events, timeout) -> event mask, false or nil
9849  * io.wait(timeout = nil, mode = :read) -> self, true, or false
9850  *
9851  * Waits until the IO becomes ready for the specified events and returns the
9852  * subset of events that become ready, or a falsy value when times out.
9853  *
9854  * The events can be a bit mask of +IO::READABLE+, +IO::WRITABLE+ or
9855  * +IO::PRIORITY+.
9856  *
9857  * Returns an event mask (truthy value) immediately when buffered data is available.
9858  *
9859  * Optional parameter +mode+ is one of +:read+, +:write+, or
9860  * +:read_write+.
9861  */
9862 
9863 static VALUE
9864 io_wait(int argc, VALUE *argv, VALUE io)
9865 {
9866  VALUE timeout = Qundef;
9867  enum rb_io_event events = 0;
9868  int return_io = 0;
9869 
9870  // The documented signature for this method is actually incorrect.
9871  // A single timeout is allowed in any position, and multiple symbols can be given.
9872  // Whether this is intentional or not, I don't know, and as such I consider this to
9873  // be a legacy/slow path.
9874  if (argc != 2 || (RB_SYMBOL_P(argv[0]) || RB_SYMBOL_P(argv[1]))) {
9875  // We'd prefer to return the actual mask, but this form would return the io itself:
9876  return_io = 1;
9877 
9878  // Slow/messy path:
9879  for (int i = 0; i < argc; i += 1) {
9880  if (RB_SYMBOL_P(argv[i])) {
9881  events |= wait_mode_sym(argv[i]);
9882  }
9883  else if (UNDEF_P(timeout)) {
9884  rb_time_interval(timeout = argv[i]);
9885  }
9886  else {
9887  rb_raise(rb_eArgError, "timeout given more than once");
9888  }
9889  }
9890 
9891  if (UNDEF_P(timeout)) timeout = Qnil;
9892 
9893  if (events == 0) {
9894  events = RUBY_IO_READABLE;
9895  }
9896  }
9897  else /* argc == 2 and neither are symbols */ {
9898  // This is the fast path:
9899  events = io_event_from_value(argv[0]);
9900  timeout = argv[1];
9901  }
9902 
9903  if (events & RUBY_IO_READABLE) {
9904  rb_io_t *fptr = NULL;
9905  RB_IO_POINTER(io, fptr);
9906 
9907  if (rb_io_read_pending(fptr)) {
9908  // This was the original behaviour:
9909  if (return_io) return Qtrue;
9910  // New behaviour always returns an event mask:
9911  else return RB_INT2NUM(RUBY_IO_READABLE);
9912  }
9913  }
9914 
9915  return io_wait_event(io, events, timeout, return_io);
9916 }
9917 
9918 static void
9919 argf_mark(void *ptr)
9920 {
9921  struct argf *p = ptr;
9922  rb_gc_mark(p->filename);
9923  rb_gc_mark(p->current_file);
9924  rb_gc_mark(p->argv);
9925  rb_gc_mark(p->inplace);
9926  rb_gc_mark(p->encs.ecopts);
9927 }
9928 
9929 static size_t
9930 argf_memsize(const void *ptr)
9931 {
9932  const struct argf *p = ptr;
9933  size_t size = sizeof(*p);
9934  return size;
9935 }
9936 
9937 static const rb_data_type_t argf_type = {
9938  "ARGF",
9939  {argf_mark, RUBY_TYPED_DEFAULT_FREE, argf_memsize},
9940  0, 0, RUBY_TYPED_FREE_IMMEDIATELY
9941 };
9942 
9943 static inline void
9944 argf_init(struct argf *p, VALUE v)
9945 {
9946  p->filename = Qnil;
9947  p->current_file = Qnil;
9948  p->lineno = 0;
9949  p->argv = v;
9950 }
9951 
9952 static VALUE
9953 argf_alloc(VALUE klass)
9954 {
9955  struct argf *p;
9956  VALUE argf = TypedData_Make_Struct(klass, struct argf, &argf_type, p);
9957 
9958  argf_init(p, Qnil);
9959  return argf;
9960 }
9961 
9962 #undef rb_argv
9963 
9964 /* :nodoc: */
9965 static VALUE
9966 argf_initialize(VALUE argf, VALUE argv)
9967 {
9968  memset(&ARGF, 0, sizeof(ARGF));
9969  argf_init(&ARGF, argv);
9970 
9971  return argf;
9972 }
9973 
9974 /* :nodoc: */
9975 static VALUE
9976 argf_initialize_copy(VALUE argf, VALUE orig)
9977 {
9978  if (!OBJ_INIT_COPY(argf, orig)) return argf;
9979  ARGF = argf_of(orig);
9980  ARGF.argv = rb_obj_dup(ARGF.argv);
9981  return argf;
9982 }
9983 
9984 /*
9985  * call-seq:
9986  * ARGF.lineno = integer -> integer
9987  *
9988  * Sets the line number of ARGF as a whole to the given Integer.
9989  *
9990  * ARGF sets the line number automatically as you read data, so normally
9991  * you will not need to set it explicitly. To access the current line number
9992  * use ARGF.lineno.
9993  *
9994  * For example:
9995  *
9996  * ARGF.lineno #=> 0
9997  * ARGF.readline #=> "This is line 1\n"
9998  * ARGF.lineno #=> 1
9999  * ARGF.lineno = 0 #=> 0
10000  * ARGF.lineno #=> 0
10001  */
10002 static VALUE
10003 argf_set_lineno(VALUE argf, VALUE val)
10004 {
10005  ARGF.lineno = NUM2INT(val);
10006  ARGF.last_lineno = ARGF.lineno;
10007  return val;
10008 }
10009 
10010 /*
10011  * call-seq:
10012  * ARGF.lineno -> integer
10013  *
10014  * Returns the current line number of ARGF as a whole. This value
10015  * can be set manually with ARGF.lineno=.
10016  *
10017  * For example:
10018  *
10019  * ARGF.lineno #=> 0
10020  * ARGF.readline #=> "This is line 1\n"
10021  * ARGF.lineno #=> 1
10022  */
10023 static VALUE
10024 argf_lineno(VALUE argf)
10025 {
10026  return INT2FIX(ARGF.lineno);
10027 }
10028 
10029 static VALUE
10030 argf_forward(int argc, VALUE *argv, VALUE argf)
10031 {
10032  return forward_current(rb_frame_this_func(), argc, argv);
10033 }
10034 
10035 #define next_argv() argf_next_argv(argf)
10036 #define ARGF_GENERIC_INPUT_P() \
10037  (ARGF.current_file == rb_stdin && !RB_TYPE_P(ARGF.current_file, T_FILE))
10038 #define ARGF_FORWARD(argc, argv) do {\
10039  if (ARGF_GENERIC_INPUT_P())\
10040  return argf_forward((argc), (argv), argf);\
10041 } while (0)
10042 #define NEXT_ARGF_FORWARD(argc, argv) do {\
10043  if (!next_argv()) return Qnil;\
10044  ARGF_FORWARD((argc), (argv));\
10045 } while (0)
10046 
10047 static void
10048 argf_close(VALUE argf)
10049 {
10050  VALUE file = ARGF.current_file;
10051  if (file == rb_stdin) return;
10052  if (RB_TYPE_P(file, T_FILE)) {
10053  rb_io_set_write_io(file, Qnil);
10054  }
10055  io_close(file);
10056  ARGF.init_p = -1;
10057 }
10058 
10059 static int
10060 argf_next_argv(VALUE argf)
10061 {
10062  char *fn;
10063  rb_io_t *fptr;
10064  int stdout_binmode = 0;
10065  int fmode;
10066 
10067  VALUE r_stdout = rb_ractor_stdout();
10068 
10069  if (RB_TYPE_P(r_stdout, T_FILE)) {
10070  GetOpenFile(r_stdout, fptr);
10071  if (fptr->mode & FMODE_BINMODE)
10072  stdout_binmode = 1;
10073  }
10074 
10075  if (ARGF.init_p == 0) {
10076  if (!NIL_P(ARGF.argv) && RARRAY_LEN(ARGF.argv) > 0) {
10077  ARGF.next_p = 1;
10078  }
10079  else {
10080  ARGF.next_p = -1;
10081  }
10082  ARGF.init_p = 1;
10083  }
10084  else {
10085  if (NIL_P(ARGF.argv)) {
10086  ARGF.next_p = -1;
10087  }
10088  else if (ARGF.next_p == -1 && RARRAY_LEN(ARGF.argv) > 0) {
10089  ARGF.next_p = 1;
10090  }
10091  }
10092 
10093  if (ARGF.next_p == 1) {
10094  if (ARGF.init_p == 1) argf_close(argf);
10095  retry:
10096  if (RARRAY_LEN(ARGF.argv) > 0) {
10097  VALUE filename = rb_ary_shift(ARGF.argv);
10098  FilePathValue(filename);
10099  ARGF.filename = filename;
10100  filename = rb_str_encode_ospath(filename);
10101  fn = StringValueCStr(filename);
10102  if (RSTRING_LEN(filename) == 1 && fn[0] == '-') {
10103  ARGF.current_file = rb_stdin;
10104  if (ARGF.inplace) {
10105  rb_warn("Can't do inplace edit for stdio; skipping");
10106  goto retry;
10107  }
10108  }
10109  else {
10110  VALUE write_io = Qnil;
10111  int fr = rb_sysopen(filename, O_RDONLY, 0);
10112 
10113  if (ARGF.inplace) {
10114  struct stat st;
10115 #ifndef NO_SAFE_RENAME
10116  struct stat st2;
10117 #endif
10118  VALUE str;
10119  int fw;
10120 
10121  if (RB_TYPE_P(r_stdout, T_FILE) && r_stdout != orig_stdout) {
10122  rb_io_close(r_stdout);
10123  }
10124  fstat(fr, &st);
10125  str = filename;
10126  if (!NIL_P(ARGF.inplace)) {
10127  VALUE suffix = ARGF.inplace;
10128  str = rb_str_dup(str);
10129  if (NIL_P(rb_str_cat_conv_enc_opts(str, RSTRING_LEN(str),
10130  RSTRING_PTR(suffix), RSTRING_LEN(suffix),
10131  rb_enc_get(suffix), 0, Qnil))) {
10132  rb_str_append(str, suffix);
10133  }
10134 #ifdef NO_SAFE_RENAME
10135  (void)close(fr);
10136  (void)unlink(RSTRING_PTR(str));
10137  if (rename(fn, RSTRING_PTR(str)) < 0) {
10138  rb_warn("Can't rename %"PRIsVALUE" to %"PRIsVALUE": %s, skipping file",
10139  filename, str, strerror(errno));
10140  goto retry;
10141  }
10142  fr = rb_sysopen(str, O_RDONLY, 0);
10143 #else
10144  if (rename(fn, RSTRING_PTR(str)) < 0) {
10145  rb_warn("Can't rename %"PRIsVALUE" to %"PRIsVALUE": %s, skipping file",
10146  filename, str, strerror(errno));
10147  close(fr);
10148  goto retry;
10149  }
10150 #endif
10151  }
10152  else {
10153 #ifdef NO_SAFE_RENAME
10154  rb_fatal("Can't do inplace edit without backup");
10155 #else
10156  if (unlink(fn) < 0) {
10157  rb_warn("Can't remove %"PRIsVALUE": %s, skipping file",
10158  filename, strerror(errno));
10159  close(fr);
10160  goto retry;
10161  }
10162 #endif
10163  }
10164  fw = rb_sysopen(filename, O_WRONLY|O_CREAT|O_TRUNC, 0666);
10165 #ifndef NO_SAFE_RENAME
10166  fstat(fw, &st2);
10167 #ifdef HAVE_FCHMOD
10168  fchmod(fw, st.st_mode);
10169 #else
10170  chmod(fn, st.st_mode);
10171 #endif
10172  if (st.st_uid!=st2.st_uid || st.st_gid!=st2.st_gid) {
10173  int err;
10174 #ifdef HAVE_FCHOWN
10175  err = fchown(fw, st.st_uid, st.st_gid);
10176 #else
10177  err = chown(fn, st.st_uid, st.st_gid);
10178 #endif
10179  if (err && getuid() == 0 && st2.st_uid == 0) {
10180  const char *wkfn = RSTRING_PTR(filename);
10181  rb_warn("Can't set owner/group of %"PRIsVALUE" to same as %"PRIsVALUE": %s, skipping file",
10182  filename, str, strerror(errno));
10183  (void)close(fr);
10184  (void)close(fw);
10185  (void)unlink(wkfn);
10186  goto retry;
10187  }
10188  }
10189 #endif
10190  write_io = prep_io(fw, FMODE_WRITABLE, rb_cFile, fn);
10191  rb_ractor_stdout_set(write_io);
10192  if (stdout_binmode) rb_io_binmode(rb_stdout);
10193  }
10194  fmode = FMODE_READABLE;
10195  if (!ARGF.binmode) {
10196  fmode |= DEFAULT_TEXTMODE;
10197  }
10198  ARGF.current_file = prep_io(fr, fmode, rb_cFile, fn);
10199  if (!NIL_P(write_io)) {
10200  rb_io_set_write_io(ARGF.current_file, write_io);
10201  }
10202  RB_GC_GUARD(filename);
10203  }
10204  if (ARGF.binmode) rb_io_ascii8bit_binmode(ARGF.current_file);
10205  GetOpenFile(ARGF.current_file, fptr);
10206  if (ARGF.encs.enc) {
10207  fptr->encs = ARGF.encs;
10208  clear_codeconv(fptr);
10209  }
10210  else {
10212  if (!ARGF.binmode) {
10214 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
10215  fptr->encs.ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
10216 #endif
10217  }
10218  }
10219  ARGF.next_p = 0;
10220  }
10221  else {
10222  ARGF.next_p = 1;
10223  return FALSE;
10224  }
10225  }
10226  else if (ARGF.next_p == -1) {
10227  ARGF.current_file = rb_stdin;
10228  ARGF.filename = rb_str_new2("-");
10229  if (ARGF.inplace) {
10230  rb_warn("Can't do inplace edit for stdio");
10231  rb_ractor_stdout_set(orig_stdout);
10232  }
10233  }
10234  if (ARGF.init_p == -1) ARGF.init_p = 1;
10235  return TRUE;
10236 }
10237 
10238 static VALUE
10239 argf_getline(int argc, VALUE *argv, VALUE argf)
10240 {
10241  VALUE line;
10242  long lineno = ARGF.lineno;
10243 
10244  retry:
10245  if (!next_argv()) return Qnil;
10246  if (ARGF_GENERIC_INPUT_P()) {
10247  line = forward_current(idGets, argc, argv);
10248  }
10249  else {
10250  if (argc == 0 && rb_rs == rb_default_rs) {
10251  line = rb_io_gets(ARGF.current_file);
10252  }
10253  else {
10254  line = rb_io_getline(argc, argv, ARGF.current_file);
10255  }
10256  if (NIL_P(line) && ARGF.next_p != -1) {
10257  argf_close(argf);
10258  ARGF.next_p = 1;
10259  goto retry;
10260  }
10261  }
10262  if (!NIL_P(line)) {
10263  ARGF.lineno = ++lineno;
10264  ARGF.last_lineno = ARGF.lineno;
10265  }
10266  return line;
10267 }
10268 
10269 static VALUE
10270 argf_lineno_getter(ID id, VALUE *var)
10271 {
10272  VALUE argf = *var;
10273  return INT2FIX(ARGF.last_lineno);
10274 }
10275 
10276 static void
10277 argf_lineno_setter(VALUE val, ID id, VALUE *var)
10278 {
10279  VALUE argf = *var;
10280  int n = NUM2INT(val);
10281  ARGF.last_lineno = ARGF.lineno = n;
10282 }
10283 
10284 void
10285 rb_reset_argf_lineno(long n)
10286 {
10287  ARGF.last_lineno = ARGF.lineno = n;
10288 }
10289 
10290 static VALUE argf_gets(int, VALUE *, VALUE);
10291 
10292 /*
10293  * call-seq:
10294  * gets(sep=$/ [, getline_args]) -> string or nil
10295  * gets(limit [, getline_args]) -> string or nil
10296  * gets(sep, limit [, getline_args]) -> string or nil
10297  *
10298  * Returns (and assigns to <code>$_</code>) the next line from the list
10299  * of files in +ARGV+ (or <code>$*</code>), or from standard input if
10300  * no files are present on the command line. Returns +nil+ at end of
10301  * file. The optional argument specifies the record separator. The
10302  * separator is included with the contents of each record. A separator
10303  * of +nil+ reads the entire contents, and a zero-length separator
10304  * reads the input one paragraph at a time, where paragraphs are
10305  * divided by two consecutive newlines. If the first argument is an
10306  * integer, or optional second argument is given, the returning string
10307  * would not be longer than the given value in bytes. If multiple
10308  * filenames are present in +ARGV+, <code>gets(nil)</code> will read
10309  * the contents one file at a time.
10310  *
10311  * ARGV << "testfile"
10312  * print while gets
10313  *
10314  * <em>produces:</em>
10315  *
10316  * This is line one
10317  * This is line two
10318  * This is line three
10319  * And so on...
10320  *
10321  * The style of programming using <code>$_</code> as an implicit
10322  * parameter is gradually losing favor in the Ruby community.
10323  */
10324 
10325 static VALUE
10326 rb_f_gets(int argc, VALUE *argv, VALUE recv)
10327 {
10328  if (recv == argf) {
10329  return argf_gets(argc, argv, argf);
10330  }
10331  return forward(argf, idGets, argc, argv);
10332 }
10333 
10334 /*
10335  * call-seq:
10336  * ARGF.gets(sep=$/ [, getline_args]) -> string or nil
10337  * ARGF.gets(limit [, getline_args]) -> string or nil
10338  * ARGF.gets(sep, limit [, getline_args]) -> string or nil
10339  *
10340  * Returns the next line from the current file in ARGF.
10341  *
10342  * By default lines are assumed to be separated by <code>$/</code>;
10343  * to use a different character as a separator, supply it as a String
10344  * for the _sep_ argument.
10345  *
10346  * The optional _limit_ argument specifies how many characters of each line
10347  * to return. By default all characters are returned.
10348  *
10349  * See IO.readlines for details about getline_args.
10350  *
10351  */
10352 static VALUE
10353 argf_gets(int argc, VALUE *argv, VALUE argf)
10354 {
10355  VALUE line;
10356 
10357  line = argf_getline(argc, argv, argf);
10358  rb_lastline_set(line);
10359 
10360  return line;
10361 }
10362 
10363 VALUE
10364 rb_gets(void)
10365 {
10366  VALUE line;
10367 
10368  if (rb_rs != rb_default_rs) {
10369  return rb_f_gets(0, 0, argf);
10370  }
10371 
10372  retry:
10373  if (!next_argv()) return Qnil;
10374  line = rb_io_gets(ARGF.current_file);
10375  if (NIL_P(line) && ARGF.next_p != -1) {
10376  rb_io_close(ARGF.current_file);
10377  ARGF.next_p = 1;
10378  goto retry;
10379  }
10380  rb_lastline_set(line);
10381  if (!NIL_P(line)) {
10382  ARGF.lineno++;
10383  ARGF.last_lineno = ARGF.lineno;
10384  }
10385 
10386  return line;
10387 }
10388 
10389 static VALUE argf_readline(int, VALUE *, VALUE);
10390 
10391 /*
10392  * call-seq:
10393  * readline(sep = $/, chomp: false) -> string
10394  * readline(limit, chomp: false) -> string
10395  * readline(sep, limit, chomp: false) -> string
10396  *
10397  * Equivalent to method Kernel#gets, except that it raises an exception
10398  * if called at end-of-stream:
10399  *
10400  * $ cat t.txt | ruby -e "p readlines; readline"
10401  * ["First line\n", "Second line\n", "\n", "Fourth line\n", "Fifth line\n"]
10402  * in `readline': end of file reached (EOFError)
10403  *
10404  * Optional keyword argument +chomp+ specifies whether line separators
10405  * are to be omitted.
10406  */
10407 
10408 static VALUE
10409 rb_f_readline(int argc, VALUE *argv, VALUE recv)
10410 {
10411  if (recv == argf) {
10412  return argf_readline(argc, argv, argf);
10413  }
10414  return forward(argf, rb_intern("readline"), argc, argv);
10415 }
10416 
10417 
10418 /*
10419  * call-seq:
10420  * ARGF.readline(sep=$/) -> string
10421  * ARGF.readline(limit) -> string
10422  * ARGF.readline(sep, limit) -> string
10423  *
10424  * Returns the next line from the current file in ARGF.
10425  *
10426  * By default lines are assumed to be separated by <code>$/</code>;
10427  * to use a different character as a separator, supply it as a String
10428  * for the _sep_ argument.
10429  *
10430  * The optional _limit_ argument specifies how many characters of each line
10431  * to return. By default all characters are returned.
10432  *
10433  * An EOFError is raised at the end of the file.
10434  */
10435 static VALUE
10436 argf_readline(int argc, VALUE *argv, VALUE argf)
10437 {
10438  VALUE line;
10439 
10440  if (!next_argv()) rb_eof_error();
10441  ARGF_FORWARD(argc, argv);
10442  line = argf_gets(argc, argv, argf);
10443  if (NIL_P(line)) {
10444  rb_eof_error();
10445  }
10446 
10447  return line;
10448 }
10449 
10450 static VALUE argf_readlines(int, VALUE *, VALUE);
10451 
10452 /*
10453  * call-seq:
10454  * readlines(sep = $/, chomp: false, **enc_opts) -> array
10455  * readlines(limit, chomp: false, **enc_opts) -> array
10456  * readlines(sep, limit, chomp: false, **enc_opts) -> array
10457  *
10458  * Returns an array containing the lines returned by calling
10459  * Kernel#gets until the end-of-stream is reached;
10460  * (see {Line IO}[rdoc-ref:IO@Line+IO]).
10461  *
10462  * With only string argument +sep+ given,
10463  * returns the remaining lines as determined by line separator +sep+,
10464  * or +nil+ if none;
10465  * see {Line Separator}[rdoc-ref:IO@Line+Separator]:
10466  *
10467  * # Default separator.
10468  * $ cat t.txt | ruby -e "p readlines"
10469  * ["First line\n", "Second line\n", "\n", "Fourth line\n", "Fifth line\n"]
10470  *
10471  * # Specified separator.
10472  * $ cat t.txt | ruby -e "p readlines 'li'"
10473  * ["First li", "ne\nSecond li", "ne\n\nFourth li", "ne\nFifth li", "ne\n"]
10474  *
10475  * # Get-all separator.
10476  * $ cat t.txt | ruby -e "p readlines nil"
10477  * ["First line\nSecond line\n\nFourth line\nFifth line\n"]
10478  *
10479  * # Get-paragraph separator.
10480  * $ cat t.txt | ruby -e "p readlines ''"
10481  * ["First line\nSecond line\n\n", "Fourth line\nFifth line\n"]
10482  *
10483  * With only integer argument +limit+ given,
10484  * limits the number of bytes in the line;
10485  * see {Line Limit}[rdoc-ref:IO@Line+Limit]:
10486  *
10487  * $cat t.txt | ruby -e "p readlines 10"
10488  * ["First line", "\n", "Second lin", "e\n", "\n", "Fourth lin", "e\n", "Fifth line", "\n"]
10489  *
10490  * $cat t.txt | ruby -e "p readlines 11"
10491  * ["First line\n", "Second line", "\n", "\n", "Fourth line", "\n", "Fifth line\n"]
10492  *
10493  * $cat t.txt | ruby -e "p readlines 12"
10494  * ["First line\n", "Second line\n", "\n", "Fourth line\n", "Fifth line\n"]
10495  *
10496  * With arguments +sep+ and +limit+ given,
10497  * combines the two behaviors
10498  * (see {Line Separator and Line Limit}[rdoc-ref:IO@Line+Separator+and+Line+Limit]).
10499  *
10500  * Optional keyword argument +chomp+ specifies whether line separators
10501  * are to be omitted:
10502  *
10503  * $ cat t.txt | ruby -e "p readlines(chomp: true)"
10504  * ["First line", "Second line", "", "Fourth line", "Fifth line"]
10505  *
10506  * Optional keyword arguments +enc_opts+ specify encoding options;
10507  * see {Encoding options}[rdoc-ref:encodings.rdoc@Encoding+Options].
10508  *
10509  */
10510 
10511 static VALUE
10512 rb_f_readlines(int argc, VALUE *argv, VALUE recv)
10513 {
10514  if (recv == argf) {
10515  return argf_readlines(argc, argv, argf);
10516  }
10517  return forward(argf, rb_intern("readlines"), argc, argv);
10518 }
10519 
10520 /*
10521  * call-seq:
10522  * ARGF.readlines(sep = $/, chomp: false) -> array
10523  * ARGF.readlines(limit, chomp: false) -> array
10524  * ARGF.readlines(sep, limit, chomp: false) -> array
10525  *
10526  * ARGF.to_a(sep = $/, chomp: false) -> array
10527  * ARGF.to_a(limit, chomp: false) -> array
10528  * ARGF.to_a(sep, limit, chomp: false) -> array
10529  *
10530  * Reads each file in ARGF in its entirety, returning an Array containing
10531  * lines from the files. Lines are assumed to be separated by _sep_.
10532  *
10533  * lines = ARGF.readlines
10534  * lines[0] #=> "This is line one\n"
10535  *
10536  * See +IO.readlines+ for a full description of all options.
10537  */
10538 static VALUE
10539 argf_readlines(int argc, VALUE *argv, VALUE argf)
10540 {
10541  long lineno = ARGF.lineno;
10542  VALUE lines, ary;
10543 
10544  ary = rb_ary_new();
10545  while (next_argv()) {
10546  if (ARGF_GENERIC_INPUT_P()) {
10547  lines = forward_current(rb_intern("readlines"), argc, argv);
10548  }
10549  else {
10550  lines = rb_io_readlines(argc, argv, ARGF.current_file);
10551  argf_close(argf);
10552  }
10553  ARGF.next_p = 1;
10554  rb_ary_concat(ary, lines);
10555  ARGF.lineno = lineno + RARRAY_LEN(ary);
10556  ARGF.last_lineno = ARGF.lineno;
10557  }
10558  ARGF.init_p = 0;
10559  return ary;
10560 }
10561 
10562 /*
10563  * call-seq:
10564  * `command` -> string
10565  *
10566  * Returns the <tt>$stdout</tt> output from running +command+ in a subshell;
10567  * sets global variable <tt>$?</tt> to the process status.
10568  *
10569  * This method has potential security vulnerabilities if called with untrusted input;
10570  * see {Command Injection}[rdoc-ref:command_injection.rdoc].
10571  *
10572  * Examples:
10573  *
10574  * $ `date` # => "Wed Apr 9 08:56:30 CDT 2003\n"
10575  * $ `echo oops && exit 99` # => "oops\n"
10576  * $ $? # => #<Process::Status: pid 17088 exit 99>
10577  * $ $?.status # => 99>
10578  *
10579  * The built-in syntax <tt>%x{...}</tt> uses this method.
10580  *
10581  */
10582 
10583 static VALUE
10584 rb_f_backquote(VALUE obj, VALUE str)
10585 {
10586  VALUE port;
10587  VALUE result;
10588  rb_io_t *fptr;
10589 
10590  StringValue(str);
10591  rb_last_status_clear();
10592  port = pipe_open_s(str, "r", FMODE_READABLE|DEFAULT_TEXTMODE, NULL);
10593  if (NIL_P(port)) return rb_str_new(0,0);
10594 
10595  GetOpenFile(port, fptr);
10596  result = read_all(fptr, remain_size(fptr), Qnil);
10597  rb_io_close(port);
10598  rb_io_fptr_cleanup_all(fptr);
10599  RB_GC_GUARD(port);
10600 
10601  return result;
10602 }
10603 
10604 #ifdef HAVE_SYS_SELECT_H
10605 #include <sys/select.h>
10606 #endif
10607 
10608 static VALUE
10609 select_internal(VALUE read, VALUE write, VALUE except, struct timeval *tp, rb_fdset_t *fds)
10610 {
10611  VALUE res, list;
10612  rb_fdset_t *rp, *wp, *ep;
10613  rb_io_t *fptr;
10614  long i;
10615  int max = 0, n;
10616  int pending = 0;
10617  struct timeval timerec;
10618 
10619  if (!NIL_P(read)) {
10620  Check_Type(read, T_ARRAY);
10621  for (i=0; i<RARRAY_LEN(read); i++) {
10622  GetOpenFile(rb_io_get_io(RARRAY_AREF(read, i)), fptr);
10623  rb_fd_set(fptr->fd, &fds[0]);
10624  if (READ_DATA_PENDING(fptr) || READ_CHAR_PENDING(fptr)) { /* check for buffered data */
10625  pending++;
10626  rb_fd_set(fptr->fd, &fds[3]);
10627  }
10628  if (max < fptr->fd) max = fptr->fd;
10629  }
10630  if (pending) { /* no blocking if there's buffered data */
10631  timerec.tv_sec = timerec.tv_usec = 0;
10632  tp = &timerec;
10633  }
10634  rp = &fds[0];
10635  }
10636  else
10637  rp = 0;
10638 
10639  if (!NIL_P(write)) {
10640  Check_Type(write, T_ARRAY);
10641  for (i=0; i<RARRAY_LEN(write); i++) {
10642  VALUE write_io = GetWriteIO(rb_io_get_io(RARRAY_AREF(write, i)));
10643  GetOpenFile(write_io, fptr);
10644  rb_fd_set(fptr->fd, &fds[1]);
10645  if (max < fptr->fd) max = fptr->fd;
10646  }
10647  wp = &fds[1];
10648  }
10649  else
10650  wp = 0;
10651 
10652  if (!NIL_P(except)) {
10653  Check_Type(except, T_ARRAY);
10654  for (i=0; i<RARRAY_LEN(except); i++) {
10655  VALUE io = rb_io_get_io(RARRAY_AREF(except, i));
10656  VALUE write_io = GetWriteIO(io);
10657  GetOpenFile(io, fptr);
10658  rb_fd_set(fptr->fd, &fds[2]);
10659  if (max < fptr->fd) max = fptr->fd;
10660  if (io != write_io) {
10661  GetOpenFile(write_io, fptr);
10662  rb_fd_set(fptr->fd, &fds[2]);
10663  if (max < fptr->fd) max = fptr->fd;
10664  }
10665  }
10666  ep = &fds[2];
10667  }
10668  else {
10669  ep = 0;
10670  }
10671 
10672  max++;
10673 
10674  n = rb_thread_fd_select(max, rp, wp, ep, tp);
10675  if (n < 0) {
10676  rb_sys_fail(0);
10677  }
10678  if (!pending && n == 0) return Qnil; /* returns nil on timeout */
10679 
10680  res = rb_ary_new2(3);
10681  rb_ary_push(res, rp?rb_ary_new():rb_ary_new2(0));
10682  rb_ary_push(res, wp?rb_ary_new():rb_ary_new2(0));
10683  rb_ary_push(res, ep?rb_ary_new():rb_ary_new2(0));
10684 
10685  if (rp) {
10686  list = RARRAY_AREF(res, 0);
10687  for (i=0; i< RARRAY_LEN(read); i++) {
10688  VALUE obj = rb_ary_entry(read, i);
10689  VALUE io = rb_io_get_io(obj);
10690  GetOpenFile(io, fptr);
10691  if (rb_fd_isset(fptr->fd, &fds[0]) ||
10692  rb_fd_isset(fptr->fd, &fds[3])) {
10693  rb_ary_push(list, obj);
10694  }
10695  }
10696  }
10697 
10698  if (wp) {
10699  list = RARRAY_AREF(res, 1);
10700  for (i=0; i< RARRAY_LEN(write); i++) {
10701  VALUE obj = rb_ary_entry(write, i);
10702  VALUE io = rb_io_get_io(obj);
10703  VALUE write_io = GetWriteIO(io);
10704  GetOpenFile(write_io, fptr);
10705  if (rb_fd_isset(fptr->fd, &fds[1])) {
10706  rb_ary_push(list, obj);
10707  }
10708  }
10709  }
10710 
10711  if (ep) {
10712  list = RARRAY_AREF(res, 2);
10713  for (i=0; i< RARRAY_LEN(except); i++) {
10714  VALUE obj = rb_ary_entry(except, i);
10715  VALUE io = rb_io_get_io(obj);
10716  VALUE write_io = GetWriteIO(io);
10717  GetOpenFile(io, fptr);
10718  if (rb_fd_isset(fptr->fd, &fds[2])) {
10719  rb_ary_push(list, obj);
10720  }
10721  else if (io != write_io) {
10722  GetOpenFile(write_io, fptr);
10723  if (rb_fd_isset(fptr->fd, &fds[2])) {
10724  rb_ary_push(list, obj);
10725  }
10726  }
10727  }
10728  }
10729 
10730  return res; /* returns an empty array on interrupt */
10731 }
10732 
10733 struct select_args {
10734  VALUE read, write, except;
10735  struct timeval *timeout;
10736  rb_fdset_t fdsets[4];
10737 };
10738 
10739 static VALUE
10740 select_call(VALUE arg)
10741 {
10742  struct select_args *p = (struct select_args *)arg;
10743 
10744  return select_internal(p->read, p->write, p->except, p->timeout, p->fdsets);
10745 }
10746 
10747 static VALUE
10748 select_end(VALUE arg)
10749 {
10750  struct select_args *p = (struct select_args *)arg;
10751  int i;
10752 
10753  for (i = 0; i < numberof(p->fdsets); ++i)
10754  rb_fd_term(&p->fdsets[i]);
10755  return Qnil;
10756 }
10757 
10758 static VALUE sym_normal, sym_sequential, sym_random,
10759  sym_willneed, sym_dontneed, sym_noreuse;
10760 
10761 #ifdef HAVE_POSIX_FADVISE
10762 struct io_advise_struct {
10763  int fd;
10764  int advice;
10765  rb_off_t offset;
10766  rb_off_t len;
10767 };
10768 
10769 static VALUE
10770 io_advise_internal(void *arg)
10771 {
10772  struct io_advise_struct *ptr = arg;
10773  return posix_fadvise(ptr->fd, ptr->offset, ptr->len, ptr->advice);
10774 }
10775 
10776 static VALUE
10777 io_advise_sym_to_const(VALUE sym)
10778 {
10779 #ifdef POSIX_FADV_NORMAL
10780  if (sym == sym_normal)
10781  return INT2NUM(POSIX_FADV_NORMAL);
10782 #endif
10783 
10784 #ifdef POSIX_FADV_RANDOM
10785  if (sym == sym_random)
10786  return INT2NUM(POSIX_FADV_RANDOM);
10787 #endif
10788 
10789 #ifdef POSIX_FADV_SEQUENTIAL
10790  if (sym == sym_sequential)
10791  return INT2NUM(POSIX_FADV_SEQUENTIAL);
10792 #endif
10793 
10794 #ifdef POSIX_FADV_WILLNEED
10795  if (sym == sym_willneed)
10796  return INT2NUM(POSIX_FADV_WILLNEED);
10797 #endif
10798 
10799 #ifdef POSIX_FADV_DONTNEED
10800  if (sym == sym_dontneed)
10801  return INT2NUM(POSIX_FADV_DONTNEED);
10802 #endif
10803 
10804 #ifdef POSIX_FADV_NOREUSE
10805  if (sym == sym_noreuse)
10806  return INT2NUM(POSIX_FADV_NOREUSE);
10807 #endif
10808 
10809  return Qnil;
10810 }
10811 
10812 static VALUE
10813 do_io_advise(rb_io_t *fptr, VALUE advice, rb_off_t offset, rb_off_t len)
10814 {
10815  int rv;
10816  struct io_advise_struct ias;
10817  VALUE num_adv;
10818 
10819  num_adv = io_advise_sym_to_const(advice);
10820 
10821  /*
10822  * The platform doesn't support this hint. We don't raise exception, instead
10823  * silently ignore it. Because IO::advise is only hint.
10824  */
10825  if (NIL_P(num_adv))
10826  return Qnil;
10827 
10828  ias.fd = fptr->fd;
10829  ias.advice = NUM2INT(num_adv);
10830  ias.offset = offset;
10831  ias.len = len;
10832 
10833  rv = (int)rb_io_blocking_region(fptr, io_advise_internal, &ias);
10834  if (rv && rv != ENOSYS) {
10835  /* posix_fadvise(2) doesn't set errno. On success it returns 0; otherwise
10836  it returns the error code. */
10837  VALUE message = rb_sprintf("%"PRIsVALUE" "
10838  "(%"PRI_OFFT_PREFIX"d, "
10839  "%"PRI_OFFT_PREFIX"d, "
10840  "%"PRIsVALUE")",
10841  fptr->pathv, offset, len, advice);
10842  rb_syserr_fail_str(rv, message);
10843  }
10844 
10845  return Qnil;
10846 }
10847 
10848 #endif /* HAVE_POSIX_FADVISE */
10849 
10850 static void
10851 advice_arg_check(VALUE advice)
10852 {
10853  if (!SYMBOL_P(advice))
10854  rb_raise(rb_eTypeError, "advice must be a Symbol");
10855 
10856  if (advice != sym_normal &&
10857  advice != sym_sequential &&
10858  advice != sym_random &&
10859  advice != sym_willneed &&
10860  advice != sym_dontneed &&
10861  advice != sym_noreuse) {
10862  rb_raise(rb_eNotImpError, "Unsupported advice: %+"PRIsVALUE, advice);
10863  }
10864 }
10865 
10866 /*
10867  * call-seq:
10868  * advise(advice, offset = 0, len = 0) -> nil
10869  *
10870  * Invokes Posix system call
10871  * {posix_fadvise(2)}[https://linux.die.net/man/2/posix_fadvise],
10872  * which announces an intention to access data from the current file
10873  * in a particular manner.
10874  *
10875  * The arguments and results are platform-dependent.
10876  *
10877  * The relevant data is specified by:
10878  *
10879  * - +offset+: The offset of the first byte of data.
10880  * - +len+: The number of bytes to be accessed;
10881  * if +len+ is zero, or is larger than the number of bytes remaining,
10882  * all remaining bytes will be accessed.
10883  *
10884  * Argument +advice+ is one of the following symbols:
10885  *
10886  * - +:normal+: The application has no advice to give
10887  * about its access pattern for the specified data.
10888  * If no advice is given for an open file, this is the default assumption.
10889  * - +:sequential+: The application expects to access the specified data sequentially
10890  * (with lower offsets read before higher ones).
10891  * - +:random+: The specified data will be accessed in random order.
10892  * - +:noreuse+: The specified data will be accessed only once.
10893  * - +:willneed+: The specified data will be accessed in the near future.
10894  * - +:dontneed+: The specified data will not be accessed in the near future.
10895  *
10896  * Not implemented on all platforms.
10897  *
10898  */
10899 static VALUE
10900 rb_io_advise(int argc, VALUE *argv, VALUE io)
10901 {
10902  VALUE advice, offset, len;
10903  rb_off_t off, l;
10904  rb_io_t *fptr;
10905 
10906  rb_scan_args(argc, argv, "12", &advice, &offset, &len);
10907  advice_arg_check(advice);
10908 
10909  io = GetWriteIO(io);
10910  GetOpenFile(io, fptr);
10911 
10912  off = NIL_P(offset) ? 0 : NUM2OFFT(offset);
10913  l = NIL_P(len) ? 0 : NUM2OFFT(len);
10914 
10915 #ifdef HAVE_POSIX_FADVISE
10916  return do_io_advise(fptr, advice, off, l);
10917 #else
10918  ((void)off, (void)l); /* Ignore all hint */
10919  return Qnil;
10920 #endif
10921 }
10922 
10923 /*
10924  * call-seq:
10925  * IO.select(read_ios, write_ios = [], error_ios = [], timeout = nil) -> array or nil
10926  *
10927  * Invokes system call {select(2)}[https://linux.die.net/man/2/select],
10928  * which monitors multiple file descriptors,
10929  * waiting until one or more of the file descriptors
10930  * becomes ready for some class of I/O operation.
10931  *
10932  * Not implemented on all platforms.
10933  *
10934  * Each of the arguments +read_ios+, +write_ios+, and +error_ios+
10935  * is an array of IO objects.
10936  *
10937  * Argument +timeout+ is a numeric value (such as integer or float) timeout
10938  * interval in seconds.
10939  *
10940  * The method monitors the \IO objects given in all three arrays,
10941  * waiting for some to be ready;
10942  * returns a 3-element array whose elements are:
10943  *
10944  * - An array of the objects in +read_ios+ that are ready for reading.
10945  * - An array of the objects in +write_ios+ that are ready for writing.
10946  * - An array of the objects in +error_ios+ have pending exceptions.
10947  *
10948  * If no object becomes ready within the given +timeout+, +nil+ is returned.
10949  *
10950  * \IO.select peeks the buffer of \IO objects for testing readability.
10951  * If the \IO buffer is not empty, \IO.select immediately notifies
10952  * readability. This "peek" only happens for \IO objects. It does not
10953  * happen for IO-like objects such as OpenSSL::SSL::SSLSocket.
10954  *
10955  * The best way to use \IO.select is invoking it after non-blocking
10956  * methods such as #read_nonblock, #write_nonblock, etc. The methods
10957  * raise an exception which is extended by IO::WaitReadable or
10958  * IO::WaitWritable. The modules notify how the caller should wait
10959  * with \IO.select. If IO::WaitReadable is raised, the caller should
10960  * wait for reading. If IO::WaitWritable is raised, the caller should
10961  * wait for writing.
10962  *
10963  * So, blocking read (#readpartial) can be emulated using
10964  * #read_nonblock and \IO.select as follows:
10965  *
10966  * begin
10967  * result = io_like.read_nonblock(maxlen)
10968  * rescue IO::WaitReadable
10969  * IO.select([io_like])
10970  * retry
10971  * rescue IO::WaitWritable
10972  * IO.select(nil, [io_like])
10973  * retry
10974  * end
10975  *
10976  * Especially, the combination of non-blocking methods and \IO.select is
10977  * preferred for IO like objects such as OpenSSL::SSL::SSLSocket. It
10978  * has #to_io method to return underlying IO object. IO.select calls
10979  * #to_io to obtain the file descriptor to wait.
10980  *
10981  * This means that readability notified by \IO.select doesn't mean
10982  * readability from OpenSSL::SSL::SSLSocket object.
10983  *
10984  * The most likely situation is that OpenSSL::SSL::SSLSocket buffers
10985  * some data. \IO.select doesn't see the buffer. So \IO.select can
10986  * block when OpenSSL::SSL::SSLSocket#readpartial doesn't block.
10987  *
10988  * However, several more complicated situations exist.
10989  *
10990  * SSL is a protocol which is sequence of records.
10991  * The record consists of multiple bytes.
10992  * So, the remote side of SSL sends a partial record, IO.select
10993  * notifies readability but OpenSSL::SSL::SSLSocket cannot decrypt a
10994  * byte and OpenSSL::SSL::SSLSocket#readpartial will block.
10995  *
10996  * Also, the remote side can request SSL renegotiation which forces
10997  * the local SSL engine to write some data.
10998  * This means OpenSSL::SSL::SSLSocket#readpartial may invoke #write
10999  * system call and it can block.
11000  * In such a situation, OpenSSL::SSL::SSLSocket#read_nonblock raises
11001  * IO::WaitWritable instead of blocking.
11002  * So, the caller should wait for ready for writability as above
11003  * example.
11004  *
11005  * The combination of non-blocking methods and \IO.select is also useful
11006  * for streams such as tty, pipe socket socket when multiple processes
11007  * read from a stream.
11008  *
11009  * Finally, Linux kernel developers don't guarantee that
11010  * readability of select(2) means readability of following read(2) even
11011  * for a single process;
11012  * see {select(2)}[https://linux.die.net/man/2/select]
11013  *
11014  * Invoking \IO.select before IO#readpartial works well as usual.
11015  * However it is not the best way to use \IO.select.
11016  *
11017  * The writability notified by select(2) doesn't show
11018  * how many bytes are writable.
11019  * IO#write method blocks until given whole string is written.
11020  * So, <tt>IO#write(two or more bytes)</tt> can block after
11021  * writability is notified by \IO.select. IO#write_nonblock is required
11022  * to avoid the blocking.
11023  *
11024  * Blocking write (#write) can be emulated using #write_nonblock and
11025  * IO.select as follows: IO::WaitReadable should also be rescued for
11026  * SSL renegotiation in OpenSSL::SSL::SSLSocket.
11027  *
11028  * while 0 < string.bytesize
11029  * begin
11030  * written = io_like.write_nonblock(string)
11031  * rescue IO::WaitReadable
11032  * IO.select([io_like])
11033  * retry
11034  * rescue IO::WaitWritable
11035  * IO.select(nil, [io_like])
11036  * retry
11037  * end
11038  * string = string.byteslice(written..-1)
11039  * end
11040  *
11041  * Example:
11042  *
11043  * rp, wp = IO.pipe
11044  * mesg = "ping "
11045  * 100.times {
11046  * # IO.select follows IO#read. Not the best way to use IO.select.
11047  * rs, ws, = IO.select([rp], [wp])
11048  * if r = rs[0]
11049  * ret = r.read(5)
11050  * print ret
11051  * case ret
11052  * when /ping/
11053  * mesg = "pong\n"
11054  * when /pong/
11055  * mesg = "ping "
11056  * end
11057  * end
11058  * if w = ws[0]
11059  * w.write(mesg)
11060  * end
11061  * }
11062  *
11063  * Output:
11064  *
11065  * ping pong
11066  * ping pong
11067  * ping pong
11068  * (snipped)
11069  * ping
11070  *
11071  */
11072 
11073 static VALUE
11074 rb_f_select(int argc, VALUE *argv, VALUE obj)
11075 {
11076  VALUE scheduler = rb_fiber_scheduler_current();
11077  if (scheduler != Qnil) {
11078  // It's optionally supported.
11079  VALUE result = rb_fiber_scheduler_io_selectv(scheduler, argc, argv);
11080  if (!UNDEF_P(result)) return result;
11081  }
11082 
11083  VALUE timeout;
11084  struct select_args args;
11085  struct timeval timerec;
11086  int i;
11087 
11088  rb_scan_args(argc, argv, "13", &args.read, &args.write, &args.except, &timeout);
11089  if (NIL_P(timeout)) {
11090  args.timeout = 0;
11091  }
11092  else {
11093  timerec = rb_time_interval(timeout);
11094  args.timeout = &timerec;
11095  }
11096 
11097  for (i = 0; i < numberof(args.fdsets); ++i)
11098  rb_fd_init(&args.fdsets[i]);
11099 
11100  return rb_ensure(select_call, (VALUE)&args, select_end, (VALUE)&args);
11101 }
11102 
11103 #ifdef IOCTL_REQ_TYPE
11104  typedef IOCTL_REQ_TYPE ioctl_req_t;
11105 #else
11106  typedef int ioctl_req_t;
11107 # define NUM2IOCTLREQ(num) ((int)NUM2LONG(num))
11108 #endif
11109 
11110 #ifdef HAVE_IOCTL
11111 struct ioctl_arg {
11112  int fd;
11113  ioctl_req_t cmd;
11114  long narg;
11115 };
11116 
11117 static VALUE
11118 nogvl_ioctl(void *ptr)
11119 {
11120  struct ioctl_arg *arg = ptr;
11121 
11122  return (VALUE)ioctl(arg->fd, arg->cmd, arg->narg);
11123 }
11124 
11125 static int
11126 do_ioctl(struct rb_io *io, ioctl_req_t cmd, long narg)
11127 {
11128  int retval;
11129  struct ioctl_arg arg;
11130 
11131  arg.fd = io->fd;
11132  arg.cmd = cmd;
11133  arg.narg = narg;
11134 
11135  retval = (int)rb_io_blocking_region(io, nogvl_ioctl, &arg);
11136 
11137  return retval;
11138 }
11139 #endif
11140 
11141 #define DEFAULT_IOCTL_NARG_LEN (256)
11142 
11143 #if defined(__linux__) && defined(_IOC_SIZE)
11144 static long
11145 linux_iocparm_len(ioctl_req_t cmd)
11146 {
11147  long len;
11148 
11149  if ((cmd & 0xFFFF0000) == 0) {
11150  /* legacy and unstructured ioctl number. */
11151  return DEFAULT_IOCTL_NARG_LEN;
11152  }
11153 
11154  len = _IOC_SIZE(cmd);
11155 
11156  /* paranoia check for silly drivers which don't keep ioctl convention */
11157  if (len < DEFAULT_IOCTL_NARG_LEN)
11158  len = DEFAULT_IOCTL_NARG_LEN;
11159 
11160  return len;
11161 }
11162 #endif
11163 
11164 #ifdef HAVE_IOCTL
11165 static long
11166 ioctl_narg_len(ioctl_req_t cmd)
11167 {
11168  long len;
11169 
11170 #ifdef IOCPARM_MASK
11171 #ifndef IOCPARM_LEN
11172 #define IOCPARM_LEN(x) (((x) >> 16) & IOCPARM_MASK)
11173 #endif
11174 #endif
11175 #ifdef IOCPARM_LEN
11176  len = IOCPARM_LEN(cmd); /* on BSDish systems we're safe */
11177 #elif defined(__linux__) && defined(_IOC_SIZE)
11178  len = linux_iocparm_len(cmd);
11179 #else
11180  /* otherwise guess at what's safe */
11181  len = DEFAULT_IOCTL_NARG_LEN;
11182 #endif
11183 
11184  return len;
11185 }
11186 #endif
11187 
11188 #ifdef HAVE_FCNTL
11189 #ifdef __linux__
11190 typedef long fcntl_arg_t;
11191 #else
11192 /* posix */
11193 typedef int fcntl_arg_t;
11194 #endif
11195 
11196 static long
11197 fcntl_narg_len(ioctl_req_t cmd)
11198 {
11199  long len;
11200 
11201  switch (cmd) {
11202 #ifdef F_DUPFD
11203  case F_DUPFD:
11204  len = sizeof(fcntl_arg_t);
11205  break;
11206 #endif
11207 #ifdef F_DUP2FD /* bsd specific */
11208  case F_DUP2FD:
11209  len = sizeof(int);
11210  break;
11211 #endif
11212 #ifdef F_DUPFD_CLOEXEC /* linux specific */
11213  case F_DUPFD_CLOEXEC:
11214  len = sizeof(fcntl_arg_t);
11215  break;
11216 #endif
11217 #ifdef F_GETFD
11218  case F_GETFD:
11219  len = 1;
11220  break;
11221 #endif
11222 #ifdef F_SETFD
11223  case F_SETFD:
11224  len = sizeof(fcntl_arg_t);
11225  break;
11226 #endif
11227 #ifdef F_GETFL
11228  case F_GETFL:
11229  len = 1;
11230  break;
11231 #endif
11232 #ifdef F_SETFL
11233  case F_SETFL:
11234  len = sizeof(fcntl_arg_t);
11235  break;
11236 #endif
11237 #ifdef F_GETOWN
11238  case F_GETOWN:
11239  len = 1;
11240  break;
11241 #endif
11242 #ifdef F_SETOWN
11243  case F_SETOWN:
11244  len = sizeof(fcntl_arg_t);
11245  break;
11246 #endif
11247 #ifdef F_GETOWN_EX /* linux specific */
11248  case F_GETOWN_EX:
11249  len = sizeof(struct f_owner_ex);
11250  break;
11251 #endif
11252 #ifdef F_SETOWN_EX /* linux specific */
11253  case F_SETOWN_EX:
11254  len = sizeof(struct f_owner_ex);
11255  break;
11256 #endif
11257 #ifdef F_GETLK
11258  case F_GETLK:
11259  len = sizeof(struct flock);
11260  break;
11261 #endif
11262 #ifdef F_SETLK
11263  case F_SETLK:
11264  len = sizeof(struct flock);
11265  break;
11266 #endif
11267 #ifdef F_SETLKW
11268  case F_SETLKW:
11269  len = sizeof(struct flock);
11270  break;
11271 #endif
11272 #ifdef F_READAHEAD /* bsd specific */
11273  case F_READAHEAD:
11274  len = sizeof(int);
11275  break;
11276 #endif
11277 #ifdef F_RDAHEAD /* Darwin specific */
11278  case F_RDAHEAD:
11279  len = sizeof(int);
11280  break;
11281 #endif
11282 #ifdef F_GETSIG /* linux specific */
11283  case F_GETSIG:
11284  len = 1;
11285  break;
11286 #endif
11287 #ifdef F_SETSIG /* linux specific */
11288  case F_SETSIG:
11289  len = sizeof(fcntl_arg_t);
11290  break;
11291 #endif
11292 #ifdef F_GETLEASE /* linux specific */
11293  case F_GETLEASE:
11294  len = 1;
11295  break;
11296 #endif
11297 #ifdef F_SETLEASE /* linux specific */
11298  case F_SETLEASE:
11299  len = sizeof(fcntl_arg_t);
11300  break;
11301 #endif
11302 #ifdef F_NOTIFY /* linux specific */
11303  case F_NOTIFY:
11304  len = sizeof(fcntl_arg_t);
11305  break;
11306 #endif
11307 
11308  default:
11309  len = 256;
11310  break;
11311  }
11312 
11313  return len;
11314 }
11315 #else /* HAVE_FCNTL */
11316 static long
11317 fcntl_narg_len(ioctl_req_t cmd)
11318 {
11319  return 0;
11320 }
11321 #endif /* HAVE_FCNTL */
11322 
11323 #define NARG_SENTINEL 17
11324 
11325 static long
11326 setup_narg(ioctl_req_t cmd, VALUE *argp, long (*narg_len)(ioctl_req_t))
11327 {
11328  long narg = 0;
11329  VALUE arg = *argp;
11330 
11331  if (!RTEST(arg)) {
11332  narg = 0;
11333  }
11334  else if (FIXNUM_P(arg)) {
11335  narg = FIX2LONG(arg);
11336  }
11337  else if (arg == Qtrue) {
11338  narg = 1;
11339  }
11340  else {
11341  VALUE tmp = rb_check_string_type(arg);
11342 
11343  if (NIL_P(tmp)) {
11344  narg = NUM2LONG(arg);
11345  }
11346  else {
11347  char *ptr;
11348  long len, slen;
11349 
11350  *argp = arg = tmp;
11351  len = narg_len(cmd);
11352  rb_str_modify(arg);
11353 
11354  slen = RSTRING_LEN(arg);
11355  /* expand for data + sentinel. */
11356  if (slen < len+1) {
11357  rb_str_resize(arg, len+1);
11358  MEMZERO(RSTRING_PTR(arg)+slen, char, len-slen);
11359  slen = len+1;
11360  }
11361  /* a little sanity check here */
11362  ptr = RSTRING_PTR(arg);
11363  ptr[slen - 1] = NARG_SENTINEL;
11364  narg = (long)(SIGNED_VALUE)ptr;
11365  }
11366  }
11367 
11368  return narg;
11369 }
11370 
11371 static VALUE
11372 finish_narg(int retval, VALUE arg, const rb_io_t *fptr)
11373 {
11374  if (retval < 0) rb_sys_fail_path(fptr->pathv);
11375  if (RB_TYPE_P(arg, T_STRING)) {
11376  char *ptr;
11377  long slen;
11378  RSTRING_GETMEM(arg, ptr, slen);
11379  if (ptr[slen-1] != NARG_SENTINEL)
11380  rb_raise(rb_eArgError, "return value overflowed string");
11381  ptr[slen-1] = '\0';
11382  }
11383 
11384  return INT2NUM(retval);
11385 }
11386 
11387 #ifdef HAVE_IOCTL
11388 static VALUE
11389 rb_ioctl(VALUE io, VALUE req, VALUE arg)
11390 {
11391  ioctl_req_t cmd = NUM2IOCTLREQ(req);
11392  rb_io_t *fptr;
11393  long narg;
11394  int retval;
11395 
11396  narg = setup_narg(cmd, &arg, ioctl_narg_len);
11397  GetOpenFile(io, fptr);
11398  retval = do_ioctl(fptr, cmd, narg);
11399  return finish_narg(retval, arg, fptr);
11400 }
11401 
11402 /*
11403  * call-seq:
11404  * ioctl(integer_cmd, argument) -> integer
11405  *
11406  * Invokes Posix system call {ioctl(2)}[https://linux.die.net/man/2/ioctl],
11407  * which issues a low-level command to an I/O device.
11408  *
11409  * Issues a low-level command to an I/O device.
11410  * The arguments and returned value are platform-dependent.
11411  * The effect of the call is platform-dependent.
11412  *
11413  * If argument +argument+ is an integer, it is passed directly;
11414  * if it is a string, it is interpreted as a binary sequence of bytes.
11415  *
11416  * Not implemented on all platforms.
11417  *
11418  */
11419 
11420 static VALUE
11421 rb_io_ioctl(int argc, VALUE *argv, VALUE io)
11422 {
11423  VALUE req, arg;
11424 
11425  rb_scan_args(argc, argv, "11", &req, &arg);
11426  return rb_ioctl(io, req, arg);
11427 }
11428 #else
11429 #define rb_io_ioctl rb_f_notimplement
11430 #endif
11431 
11432 #ifdef HAVE_FCNTL
11433 struct fcntl_arg {
11434  int fd;
11435  int cmd;
11436  long narg;
11437 };
11438 
11439 static VALUE
11440 nogvl_fcntl(void *ptr)
11441 {
11442  struct fcntl_arg *arg = ptr;
11443 
11444 #if defined(F_DUPFD)
11445  if (arg->cmd == F_DUPFD)
11446  return (VALUE)rb_cloexec_fcntl_dupfd(arg->fd, (int)arg->narg);
11447 #endif
11448  return (VALUE)fcntl(arg->fd, arg->cmd, arg->narg);
11449 }
11450 
11451 static int
11452 do_fcntl(struct rb_io *io, int cmd, long narg)
11453 {
11454  int retval;
11455  struct fcntl_arg arg;
11456 
11457  arg.fd = io->fd;
11458  arg.cmd = cmd;
11459  arg.narg = narg;
11460 
11461  retval = (int)rb_io_blocking_region(io, nogvl_fcntl, &arg);
11462  if (retval != -1) {
11463  switch (cmd) {
11464 #if defined(F_DUPFD)
11465  case F_DUPFD:
11466 #endif
11467 #if defined(F_DUPFD_CLOEXEC)
11468  case F_DUPFD_CLOEXEC:
11469 #endif
11470  rb_update_max_fd(retval);
11471  }
11472  }
11473 
11474  return retval;
11475 }
11476 
11477 static VALUE
11478 rb_fcntl(VALUE io, VALUE req, VALUE arg)
11479 {
11480  int cmd = NUM2INT(req);
11481  rb_io_t *fptr;
11482  long narg;
11483  int retval;
11484 
11485  narg = setup_narg(cmd, &arg, fcntl_narg_len);
11486  GetOpenFile(io, fptr);
11487  retval = do_fcntl(fptr, cmd, narg);
11488  return finish_narg(retval, arg, fptr);
11489 }
11490 
11491 /*
11492  * call-seq:
11493  * fcntl(integer_cmd, argument) -> integer
11494  *
11495  * Invokes Posix system call {fcntl(2)}[https://linux.die.net/man/2/fcntl],
11496  * which provides a mechanism for issuing low-level commands to control or query
11497  * a file-oriented I/O stream. Arguments and results are platform
11498  * dependent.
11499  *
11500  * If +argument+ is a number, its value is passed directly;
11501  * if it is a string, it is interpreted as a binary sequence of bytes.
11502  * (Array#pack might be a useful way to build this string.)
11503  *
11504  * Not implemented on all platforms.
11505  *
11506  */
11507 
11508 static VALUE
11509 rb_io_fcntl(int argc, VALUE *argv, VALUE io)
11510 {
11511  VALUE req, arg;
11512 
11513  rb_scan_args(argc, argv, "11", &req, &arg);
11514  return rb_fcntl(io, req, arg);
11515 }
11516 #else
11517 #define rb_io_fcntl rb_f_notimplement
11518 #endif
11519 
11520 #if defined(HAVE_SYSCALL) || defined(HAVE___SYSCALL)
11521 /*
11522  * call-seq:
11523  * syscall(integer_callno, *arguments) -> integer
11524  *
11525  * Invokes Posix system call {syscall(2)}[https://linux.die.net/man/2/syscall],
11526  * which calls a specified function.
11527  *
11528  * Calls the operating system function identified by +integer_callno+;
11529  * returns the result of the function or raises SystemCallError if it failed.
11530  * The effect of the call is platform-dependent.
11531  * The arguments and returned value are platform-dependent.
11532  *
11533  * For each of +arguments+: if it is an integer, it is passed directly;
11534  * if it is a string, it is interpreted as a binary sequence of bytes.
11535  * There may be as many as nine such arguments.
11536  *
11537  * Arguments +integer_callno+ and +argument+, as well as the returned value,
11538  * are platform-dependent.
11539  *
11540  * Note: Method +syscall+ is essentially unsafe and unportable.
11541  * The DL (Fiddle) library is preferred for safer and a bit
11542  * more portable programming.
11543  *
11544  * Not implemented on all platforms.
11545  *
11546  */
11547 
11548 static VALUE
11549 rb_f_syscall(int argc, VALUE *argv, VALUE _)
11550 {
11551  VALUE arg[8];
11552 #if SIZEOF_VOIDP == 8 && defined(HAVE___SYSCALL) && SIZEOF_INT != 8 /* mainly *BSD */
11553 # define SYSCALL __syscall
11554 # define NUM2SYSCALLID(x) NUM2LONG(x)
11555 # define RETVAL2NUM(x) LONG2NUM(x)
11556 # if SIZEOF_LONG == 8
11557  long num, retval = -1;
11558 # elif SIZEOF_LONG_LONG == 8
11559  long long num, retval = -1;
11560 # else
11561 # error ---->> it is asserted that __syscall takes the first argument and returns retval in 64bit signed integer. <<----
11562 # endif
11563 #elif defined(__linux__)
11564 # define SYSCALL syscall
11565 # define NUM2SYSCALLID(x) NUM2LONG(x)
11566 # define RETVAL2NUM(x) LONG2NUM(x)
11567  /*
11568  * Linux man page says, syscall(2) function prototype is below.
11569  *
11570  * int syscall(int number, ...);
11571  *
11572  * But, it's incorrect. Actual one takes and returned long. (see unistd.h)
11573  */
11574  long num, retval = -1;
11575 #else
11576 # define SYSCALL syscall
11577 # define NUM2SYSCALLID(x) NUM2INT(x)
11578 # define RETVAL2NUM(x) INT2NUM(x)
11579  int num, retval = -1;
11580 #endif
11581  int i;
11582 
11583  if (RTEST(ruby_verbose)) {
11585  "We plan to remove a syscall function at future release. DL(Fiddle) provides safer alternative.");
11586  }
11587 
11588  if (argc == 0)
11589  rb_raise(rb_eArgError, "too few arguments for syscall");
11590  if (argc > numberof(arg))
11591  rb_raise(rb_eArgError, "too many arguments for syscall");
11592  num = NUM2SYSCALLID(argv[0]); ++argv;
11593  for (i = argc - 1; i--; ) {
11594  VALUE v = rb_check_string_type(argv[i]);
11595 
11596  if (!NIL_P(v)) {
11597  StringValue(v);
11598  rb_str_modify(v);
11599  arg[i] = (VALUE)StringValueCStr(v);
11600  }
11601  else {
11602  arg[i] = (VALUE)NUM2LONG(argv[i]);
11603  }
11604  }
11605 
11606  switch (argc) {
11607  case 1:
11608  retval = SYSCALL(num);
11609  break;
11610  case 2:
11611  retval = SYSCALL(num, arg[0]);
11612  break;
11613  case 3:
11614  retval = SYSCALL(num, arg[0],arg[1]);
11615  break;
11616  case 4:
11617  retval = SYSCALL(num, arg[0],arg[1],arg[2]);
11618  break;
11619  case 5:
11620  retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3]);
11621  break;
11622  case 6:
11623  retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4]);
11624  break;
11625  case 7:
11626  retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5]);
11627  break;
11628  case 8:
11629  retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6]);
11630  break;
11631  }
11632 
11633  if (retval == -1)
11634  rb_sys_fail(0);
11635  return RETVAL2NUM(retval);
11636 #undef SYSCALL
11637 #undef NUM2SYSCALLID
11638 #undef RETVAL2NUM
11639 }
11640 #else
11641 #define rb_f_syscall rb_f_notimplement
11642 #endif
11643 
11644 static VALUE
11645 io_new_instance(VALUE args)
11646 {
11647  return rb_class_new_instance(2, (VALUE*)args+1, *(VALUE*)args);
11648 }
11649 
11650 static rb_encoding *
11651 find_encoding(VALUE v)
11652 {
11653  rb_encoding *enc = rb_find_encoding(v);
11654  if (!enc) rb_warn("Unsupported encoding %"PRIsVALUE" ignored", v);
11655  return enc;
11656 }
11657 
11658 static void
11659 io_encoding_set(rb_io_t *fptr, VALUE v1, VALUE v2, VALUE opt)
11660 {
11661  rb_encoding *enc, *enc2;
11662  int ecflags = fptr->encs.ecflags;
11663  VALUE ecopts, tmp;
11664 
11665  if (!NIL_P(v2)) {
11666  enc2 = find_encoding(v1);
11667  tmp = rb_check_string_type(v2);
11668  if (!NIL_P(tmp)) {
11669  if (RSTRING_LEN(tmp) == 1 && RSTRING_PTR(tmp)[0] == '-') {
11670  /* Special case - "-" => no transcoding */
11671  enc = enc2;
11672  enc2 = NULL;
11673  }
11674  else
11675  enc = find_encoding(v2);
11676  if (enc == enc2) {
11677  /* Special case - "-" => no transcoding */
11678  enc2 = NULL;
11679  }
11680  }
11681  else {
11682  enc = find_encoding(v2);
11683  if (enc == enc2) {
11684  /* Special case - "-" => no transcoding */
11685  enc2 = NULL;
11686  }
11687  }
11688  if (enc2 == rb_ascii8bit_encoding()) {
11689  /* If external is ASCII-8BIT, no transcoding */
11690  enc = enc2;
11691  enc2 = NULL;
11692  }
11693  SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
11694  ecflags = rb_econv_prepare_options(opt, &ecopts, ecflags);
11695  }
11696  else {
11697  if (NIL_P(v1)) {
11698  /* Set to default encodings */
11699  rb_io_ext_int_to_encs(NULL, NULL, &enc, &enc2, 0);
11700  SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
11701  ecopts = Qnil;
11702  }
11703  else {
11704  tmp = rb_check_string_type(v1);
11705  if (!NIL_P(tmp) && rb_enc_asciicompat(enc = rb_enc_get(tmp))) {
11706  parse_mode_enc(RSTRING_PTR(tmp), enc, &enc, &enc2, NULL);
11707  SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
11708  ecflags = rb_econv_prepare_options(opt, &ecopts, ecflags);
11709  }
11710  else {
11711  rb_io_ext_int_to_encs(find_encoding(v1), NULL, &enc, &enc2, 0);
11712  SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
11713  ecopts = Qnil;
11714  }
11715  }
11716  }
11717  validate_enc_binmode(&fptr->mode, ecflags, enc, enc2);
11718  fptr->encs.enc = enc;
11719  fptr->encs.enc2 = enc2;
11720  fptr->encs.ecflags = ecflags;
11721  fptr->encs.ecopts = ecopts;
11722  clear_codeconv(fptr);
11723 
11724 }
11725 
11727  rb_io_t *fptr;
11728  VALUE v1;
11729  VALUE v2;
11730  VALUE opt;
11731 };
11732 
11733 static VALUE
11734 io_encoding_set_v(VALUE v)
11735 {
11736  struct io_encoding_set_args *arg = (struct io_encoding_set_args *)v;
11737  io_encoding_set(arg->fptr, arg->v1, arg->v2, arg->opt);
11738  return Qnil;
11739 }
11740 
11741 static VALUE
11742 pipe_pair_close(VALUE rw)
11743 {
11744  VALUE *rwp = (VALUE *)rw;
11745  return rb_ensure(io_close, rwp[0], io_close, rwp[1]);
11746 }
11747 
11748 /*
11749  * call-seq:
11750  * IO.pipe(**opts) -> [read_io, write_io]
11751  * IO.pipe(enc, **opts) -> [read_io, write_io]
11752  * IO.pipe(ext_enc, int_enc, **opts) -> [read_io, write_io]
11753  * IO.pipe(**opts) {|read_io, write_io| ...} -> object
11754  * IO.pipe(enc, **opts) {|read_io, write_io| ...} -> object
11755  * IO.pipe(ext_enc, int_enc, **opts) {|read_io, write_io| ...} -> object
11756  *
11757  * Creates a pair of pipe endpoints, +read_io+ and +write_io+,
11758  * connected to each other.
11759  *
11760  * If argument +enc_string+ is given, it must be a string containing one of:
11761  *
11762  * - The name of the encoding to be used as the external encoding.
11763  * - The colon-separated names of two encodings to be used as the external
11764  * and internal encodings.
11765  *
11766  * If argument +int_enc+ is given, it must be an Encoding object
11767  * or encoding name string that specifies the internal encoding to be used;
11768  * if argument +ext_enc+ is also given, it must be an Encoding object
11769  * or encoding name string that specifies the external encoding to be used.
11770  *
11771  * The string read from +read_io+ is tagged with the external encoding;
11772  * if an internal encoding is also specified, the string is converted
11773  * to, and tagged with, that encoding.
11774  *
11775  * If any encoding is specified,
11776  * optional hash arguments specify the conversion option.
11777  *
11778  * Optional keyword arguments +opts+ specify:
11779  *
11780  * - {Open Options}[rdoc-ref:IO@Open+Options].
11781  * - {Encoding Options}[rdoc-ref:encodings.rdoc@Encoding+Options].
11782  *
11783  * With no block given, returns the two endpoints in an array:
11784  *
11785  * IO.pipe # => [#<IO:fd 4>, #<IO:fd 5>]
11786  *
11787  * With a block given, calls the block with the two endpoints;
11788  * closes both endpoints and returns the value of the block:
11789  *
11790  * IO.pipe {|read_io, write_io| p read_io; p write_io }
11791  *
11792  * Output:
11793  *
11794  * #<IO:fd 6>
11795  * #<IO:fd 7>
11796  *
11797  * Not available on all platforms.
11798  *
11799  * In the example below, the two processes close the ends of the pipe
11800  * that they are not using. This is not just a cosmetic nicety. The
11801  * read end of a pipe will not generate an end of file condition if
11802  * there are any writers with the pipe still open. In the case of the
11803  * parent process, the <tt>rd.read</tt> will never return if it
11804  * does not first issue a <tt>wr.close</tt>:
11805  *
11806  * rd, wr = IO.pipe
11807  *
11808  * if fork
11809  * wr.close
11810  * puts "Parent got: <#{rd.read}>"
11811  * rd.close
11812  * Process.wait
11813  * else
11814  * rd.close
11815  * puts 'Sending message to parent'
11816  * wr.write "Hi Dad"
11817  * wr.close
11818  * end
11819  *
11820  * <em>produces:</em>
11821  *
11822  * Sending message to parent
11823  * Parent got: <Hi Dad>
11824  *
11825  */
11826 
11827 static VALUE
11828 rb_io_s_pipe(int argc, VALUE *argv, VALUE klass)
11829 {
11830  int pipes[2], state;
11831  VALUE r, w, args[3], v1, v2;
11832  VALUE opt;
11833  rb_io_t *fptr, *fptr2;
11834  struct io_encoding_set_args ies_args;
11835  int fmode = 0;
11836  VALUE ret;
11837 
11838  argc = rb_scan_args(argc, argv, "02:", &v1, &v2, &opt);
11839  if (rb_pipe(pipes) < 0)
11840  rb_sys_fail(0);
11841 
11842  args[0] = klass;
11843  args[1] = INT2NUM(pipes[0]);
11844  args[2] = INT2FIX(O_RDONLY);
11845  r = rb_protect(io_new_instance, (VALUE)args, &state);
11846  if (state) {
11847  close(pipes[0]);
11848  close(pipes[1]);
11849  rb_jump_tag(state);
11850  }
11851  GetOpenFile(r, fptr);
11852 
11853  ies_args.fptr = fptr;
11854  ies_args.v1 = v1;
11855  ies_args.v2 = v2;
11856  ies_args.opt = opt;
11857  rb_protect(io_encoding_set_v, (VALUE)&ies_args, &state);
11858  if (state) {
11859  close(pipes[1]);
11860  io_close(r);
11861  rb_jump_tag(state);
11862  }
11863 
11864  args[1] = INT2NUM(pipes[1]);
11865  args[2] = INT2FIX(O_WRONLY);
11866  w = rb_protect(io_new_instance, (VALUE)args, &state);
11867  if (state) {
11868  close(pipes[1]);
11869  if (!NIL_P(r)) rb_io_close(r);
11870  rb_jump_tag(state);
11871  }
11872  GetOpenFile(w, fptr2);
11873  rb_io_synchronized(fptr2);
11874 
11875  extract_binmode(opt, &fmode);
11876 
11877  if ((fmode & FMODE_BINMODE) && NIL_P(v1)) {
11880  }
11881 
11882 #if DEFAULT_TEXTMODE
11883  if ((fptr->mode & FMODE_TEXTMODE) && (fmode & FMODE_BINMODE)) {
11884  fptr->mode &= ~FMODE_TEXTMODE;
11885  setmode(fptr->fd, O_BINARY);
11886  }
11887 #if RUBY_CRLF_ENVIRONMENT
11890  }
11891 #endif
11892 #endif
11893  fptr->mode |= fmode;
11894 #if DEFAULT_TEXTMODE
11895  if ((fptr2->mode & FMODE_TEXTMODE) && (fmode & FMODE_BINMODE)) {
11896  fptr2->mode &= ~FMODE_TEXTMODE;
11897  setmode(fptr2->fd, O_BINARY);
11898  }
11899 #endif
11900  fptr2->mode |= fmode;
11901 
11902  ret = rb_assoc_new(r, w);
11903  if (rb_block_given_p()) {
11904  VALUE rw[2];
11905  rw[0] = r;
11906  rw[1] = w;
11907  return rb_ensure(rb_yield, ret, pipe_pair_close, (VALUE)rw);
11908  }
11909  return ret;
11910 }
11911 
11912 struct foreach_arg {
11913  int argc;
11914  VALUE *argv;
11915  VALUE io;
11916 };
11917 
11918 static void
11919 open_key_args(VALUE klass, int argc, VALUE *argv, VALUE opt, struct foreach_arg *arg)
11920 {
11921  VALUE path, v;
11922  VALUE vmode = Qnil, vperm = Qnil;
11923 
11924  path = *argv++;
11925  argc--;
11926  FilePathValue(path);
11927  arg->io = 0;
11928  arg->argc = argc;
11929  arg->argv = argv;
11930  if (NIL_P(opt)) {
11931  vmode = INT2NUM(O_RDONLY);
11932  vperm = INT2FIX(0666);
11933  }
11934  else if (!NIL_P(v = rb_hash_aref(opt, sym_open_args))) {
11935  int n;
11936 
11937  v = rb_to_array_type(v);
11938  n = RARRAY_LENINT(v);
11939  rb_check_arity(n, 0, 3); /* rb_io_open */
11940  rb_scan_args_kw(RB_SCAN_ARGS_LAST_HASH_KEYWORDS, n, RARRAY_CONST_PTR(v), "02:", &vmode, &vperm, &opt);
11941  }
11942  arg->io = rb_io_open(klass, path, vmode, vperm, opt);
11943 }
11944 
11945 static VALUE
11946 io_s_foreach(VALUE v)
11947 {
11948  struct getline_arg *arg = (void *)v;
11949  VALUE str;
11950 
11951  if (arg->limit == 0)
11952  rb_raise(rb_eArgError, "invalid limit: 0 for foreach");
11953  while (!NIL_P(str = rb_io_getline_1(arg->rs, arg->limit, arg->chomp, arg->io))) {
11954  rb_lastline_set(str);
11955  rb_yield(str);
11956  }
11958  return Qnil;
11959 }
11960 
11961 /*
11962  * call-seq:
11963  * IO.foreach(path, sep = $/, **opts) {|line| block } -> nil
11964  * IO.foreach(path, limit, **opts) {|line| block } -> nil
11965  * IO.foreach(path, sep, limit, **opts) {|line| block } -> nil
11966  * IO.foreach(...) -> an_enumerator
11967  *
11968  * Calls the block with each successive line read from the stream.
11969  *
11970  * When called from class \IO (but not subclasses of \IO),
11971  * this method has potential security vulnerabilities if called with untrusted input;
11972  * see {Command Injection}[rdoc-ref:command_injection.rdoc].
11973  *
11974  * The first argument must be a string that is the path to a file.
11975  *
11976  * With only argument +path+ given, parses lines from the file at the given +path+,
11977  * as determined by the default line separator,
11978  * and calls the block with each successive line:
11979  *
11980  * File.foreach('t.txt') {|line| p line }
11981  *
11982  * Output: the same as above.
11983  *
11984  * For both forms, command and path, the remaining arguments are the same.
11985  *
11986  * With argument +sep+ given, parses lines as determined by that line separator
11987  * (see {Line Separator}[rdoc-ref:IO@Line+Separator]):
11988  *
11989  * File.foreach('t.txt', 'li') {|line| p line }
11990  *
11991  * Output:
11992  *
11993  * "First li"
11994  * "ne\nSecond li"
11995  * "ne\n\nThird li"
11996  * "ne\nFourth li"
11997  * "ne\n"
11998  *
11999  * Each paragraph:
12000  *
12001  * File.foreach('t.txt', '') {|paragraph| p paragraph }
12002  *
12003  * Output:
12004  *
12005  * "First line\nSecond line\n\n"
12006  * "Third line\nFourth line\n"
12007  *
12008  * With argument +limit+ given, parses lines as determined by the default
12009  * line separator and the given line-length limit
12010  * (see {Line Separator}[rdoc-ref:IO@Line+Separator] and {Line Limit}[rdoc-ref:IO@Line+Limit]):
12011  *
12012  * File.foreach('t.txt', 7) {|line| p line }
12013  *
12014  * Output:
12015  *
12016  * "First l"
12017  * "ine\n"
12018  * "Second "
12019  * "line\n"
12020  * "\n"
12021  * "Third l"
12022  * "ine\n"
12023  * "Fourth l"
12024  * "line\n"
12025  *
12026  * With arguments +sep+ and +limit+ given,
12027  * combines the two behaviors
12028  * (see {Line Separator and Line Limit}[rdoc-ref:IO@Line+Separator+and+Line+Limit]).
12029  *
12030  * Optional keyword arguments +opts+ specify:
12031  *
12032  * - {Open Options}[rdoc-ref:IO@Open+Options].
12033  * - {Encoding options}[rdoc-ref:encodings.rdoc@Encoding+Options].
12034  * - {Line Options}[rdoc-ref:IO@Line+IO].
12035  *
12036  * Returns an Enumerator if no block is given.
12037  *
12038  */
12039 
12040 static VALUE
12041 rb_io_s_foreach(int argc, VALUE *argv, VALUE self)
12042 {
12043  VALUE opt;
12044  int orig_argc = argc;
12045  struct foreach_arg arg;
12046  struct getline_arg garg;
12047 
12048  argc = rb_scan_args(argc, argv, "12:", NULL, NULL, NULL, &opt);
12049  RETURN_ENUMERATOR(self, orig_argc, argv);
12050  extract_getline_args(argc-1, argv+1, &garg);
12051  open_key_args(self, argc, argv, opt, &arg);
12052  if (NIL_P(arg.io)) return Qnil;
12053  extract_getline_opts(opt, &garg);
12054  check_getline_args(&garg.rs, &garg.limit, garg.io = arg.io);
12055  return rb_ensure(io_s_foreach, (VALUE)&garg, rb_io_close, arg.io);
12056 }
12057 
12058 static VALUE
12059 io_s_readlines(VALUE v)
12060 {
12061  struct getline_arg *arg = (void *)v;
12062  return io_readlines(arg, arg->io);
12063 }
12064 
12065 /*
12066  * call-seq:
12067  * IO.readlines(path, sep = $/, **opts) -> array
12068  * IO.readlines(path, limit, **opts) -> array
12069  * IO.readlines(path, sep, limit, **opts) -> array
12070  *
12071  * Returns an array of all lines read from the stream.
12072  *
12073  * When called from class \IO (but not subclasses of \IO),
12074  * this method has potential security vulnerabilities if called with untrusted input;
12075  * see {Command Injection}[rdoc-ref:command_injection.rdoc].
12076  *
12077  * The first argument must be a string that is the path to a file.
12078  *
12079  * With only argument +path+ given, parses lines from the file at the given +path+,
12080  * as determined by the default line separator,
12081  * and returns those lines in an array:
12082  *
12083  * IO.readlines('t.txt')
12084  * # => ["First line\n", "Second line\n", "\n", "Third line\n", "Fourth line\n"]
12085  *
12086  * With argument +sep+ given, parses lines as determined by that line separator
12087  * (see {Line Separator}[rdoc-ref:IO@Line+Separator]):
12088  *
12089  * # Ordinary separator.
12090  * IO.readlines('t.txt', 'li')
12091  * # =>["First li", "ne\nSecond li", "ne\n\nThird li", "ne\nFourth li", "ne\n"]
12092  * # Get-paragraphs separator.
12093  * IO.readlines('t.txt', '')
12094  * # => ["First line\nSecond line\n\n", "Third line\nFourth line\n"]
12095  * # Get-all separator.
12096  * IO.readlines('t.txt', nil)
12097  * # => ["First line\nSecond line\n\nThird line\nFourth line\n"]
12098  *
12099  * With argument +limit+ given, parses lines as determined by the default
12100  * line separator and the given line-length limit
12101  * (see {Line Separator}[rdoc-ref:IO@Line+Separator] and {Line Limit}[rdoc-ref:IO@Line+Limit]:
12102  *
12103  * IO.readlines('t.txt', 7)
12104  * # => ["First l", "ine\n", "Second ", "line\n", "\n", "Third l", "ine\n", "Fourth ", "line\n"]
12105  *
12106  * With arguments +sep+ and +limit+ given,
12107  * combines the two behaviors
12108  * (see {Line Separator and Line Limit}[rdoc-ref:IO@Line+Separator+and+Line+Limit]).
12109  *
12110  * Optional keyword arguments +opts+ specify:
12111  *
12112  * - {Open Options}[rdoc-ref:IO@Open+Options].
12113  * - {Encoding options}[rdoc-ref:encodings.rdoc@Encoding+Options].
12114  * - {Line Options}[rdoc-ref:IO@Line+IO].
12115  *
12116  */
12117 
12118 static VALUE
12119 rb_io_s_readlines(int argc, VALUE *argv, VALUE io)
12120 {
12121  VALUE opt;
12122  struct foreach_arg arg;
12123  struct getline_arg garg;
12124 
12125  argc = rb_scan_args(argc, argv, "12:", NULL, NULL, NULL, &opt);
12126  extract_getline_args(argc-1, argv+1, &garg);
12127  open_key_args(io, argc, argv, opt, &arg);
12128  if (NIL_P(arg.io)) return Qnil;
12129  extract_getline_opts(opt, &garg);
12130  check_getline_args(&garg.rs, &garg.limit, garg.io = arg.io);
12131  return rb_ensure(io_s_readlines, (VALUE)&garg, rb_io_close, arg.io);
12132 }
12133 
12134 static VALUE
12135 io_s_read(VALUE v)
12136 {
12137  struct foreach_arg *arg = (void *)v;
12138  return io_read(arg->argc, arg->argv, arg->io);
12139 }
12140 
12141 struct seek_arg {
12142  VALUE io;
12143  VALUE offset;
12144  int mode;
12145 };
12146 
12147 static VALUE
12148 seek_before_access(VALUE argp)
12149 {
12150  struct seek_arg *arg = (struct seek_arg *)argp;
12151  rb_io_binmode(arg->io);
12152  return rb_io_seek(arg->io, arg->offset, arg->mode);
12153 }
12154 
12155 /*
12156  * call-seq:
12157  * IO.read(path, length = nil, offset = 0, **opts) -> string or nil
12158  *
12159  * Opens the stream, reads and returns some or all of its content,
12160  * and closes the stream; returns +nil+ if no bytes were read.
12161  *
12162  * When called from class \IO (but not subclasses of \IO),
12163  * this method has potential security vulnerabilities if called with untrusted input;
12164  * see {Command Injection}[rdoc-ref:command_injection.rdoc].
12165  *
12166  * The first argument must be a string that is the path to a file.
12167  *
12168  * With only argument +path+ given, reads in text mode and returns the entire content
12169  * of the file at the given path:
12170  *
12171  * IO.read('t.txt')
12172  * # => "First line\nSecond line\n\nThird line\nFourth line\n"
12173  *
12174  * On Windows, text mode can terminate reading and leave bytes in the file
12175  * unread when encountering certain special bytes. Consider using
12176  * IO.binread if all bytes in the file should be read.
12177  *
12178  * With argument +length+, returns +length+ bytes if available:
12179  *
12180  * IO.read('t.txt', 7) # => "First l"
12181  * IO.read('t.txt', 700)
12182  * # => "First line\r\nSecond line\r\n\r\nFourth line\r\nFifth line\r\n"
12183  *
12184  * With arguments +length+ and +offset+, returns +length+ bytes
12185  * if available, beginning at the given +offset+:
12186  *
12187  * IO.read('t.txt', 10, 2) # => "rst line\nS"
12188  * IO.read('t.txt', 10, 200) # => nil
12189  *
12190  * Optional keyword arguments +opts+ specify:
12191  *
12192  * - {Open Options}[rdoc-ref:IO@Open+Options].
12193  * - {Encoding options}[rdoc-ref:encodings.rdoc@Encoding+Options].
12194  *
12195  */
12196 
12197 static VALUE
12198 rb_io_s_read(int argc, VALUE *argv, VALUE io)
12199 {
12200  VALUE opt, offset;
12201  long off;
12202  struct foreach_arg arg;
12203 
12204  argc = rb_scan_args(argc, argv, "13:", NULL, NULL, &offset, NULL, &opt);
12205  if (!NIL_P(offset) && (off = NUM2LONG(offset)) < 0) {
12206  rb_raise(rb_eArgError, "negative offset %ld given", off);
12207  }
12208  open_key_args(io, argc, argv, opt, &arg);
12209  if (NIL_P(arg.io)) return Qnil;
12210  if (!NIL_P(offset)) {
12211  struct seek_arg sarg;
12212  int state = 0;
12213  sarg.io = arg.io;
12214  sarg.offset = offset;
12215  sarg.mode = SEEK_SET;
12216  rb_protect(seek_before_access, (VALUE)&sarg, &state);
12217  if (state) {
12218  rb_io_close(arg.io);
12219  rb_jump_tag(state);
12220  }
12221  if (arg.argc == 2) arg.argc = 1;
12222  }
12223  return rb_ensure(io_s_read, (VALUE)&arg, rb_io_close, arg.io);
12224 }
12225 
12226 /*
12227  * call-seq:
12228  * IO.binread(path, length = nil, offset = 0) -> string or nil
12229  *
12230  * Behaves like IO.read, except that the stream is opened in binary mode
12231  * with ASCII-8BIT encoding.
12232  *
12233  * When called from class \IO (but not subclasses of \IO),
12234  * this method has potential security vulnerabilities if called with untrusted input;
12235  * see {Command Injection}[rdoc-ref:command_injection.rdoc].
12236  *
12237  */
12238 
12239 static VALUE
12240 rb_io_s_binread(int argc, VALUE *argv, VALUE io)
12241 {
12242  VALUE offset;
12243  struct foreach_arg arg;
12244  enum {
12245  fmode = FMODE_READABLE|FMODE_BINMODE,
12246  oflags = O_RDONLY
12247 #ifdef O_BINARY
12248  |O_BINARY
12249 #endif
12250  };
12251  struct rb_io_encoding convconfig = {NULL, NULL, 0, Qnil};
12252 
12253  rb_scan_args(argc, argv, "12", NULL, NULL, &offset);
12254  FilePathValue(argv[0]);
12255  convconfig.enc = rb_ascii8bit_encoding();
12256  arg.io = rb_io_open_generic(io, argv[0], oflags, fmode, &convconfig, 0);
12257  if (NIL_P(arg.io)) return Qnil;
12258  arg.argv = argv+1;
12259  arg.argc = (argc > 1) ? 1 : 0;
12260  if (!NIL_P(offset)) {
12261  struct seek_arg sarg;
12262  int state = 0;
12263  sarg.io = arg.io;
12264  sarg.offset = offset;
12265  sarg.mode = SEEK_SET;
12266  rb_protect(seek_before_access, (VALUE)&sarg, &state);
12267  if (state) {
12268  rb_io_close(arg.io);
12269  rb_jump_tag(state);
12270  }
12271  }
12272  return rb_ensure(io_s_read, (VALUE)&arg, rb_io_close, arg.io);
12273 }
12274 
12275 static VALUE
12276 io_s_write0(VALUE v)
12277 {
12278  struct write_arg *arg = (void *)v;
12279  return io_write(arg->io,arg->str,arg->nosync);
12280 }
12281 
12282 static VALUE
12283 io_s_write(int argc, VALUE *argv, VALUE klass, int binary)
12284 {
12285  VALUE string, offset, opt;
12286  struct foreach_arg arg;
12287  struct write_arg warg;
12288 
12289  rb_scan_args(argc, argv, "21:", NULL, &string, &offset, &opt);
12290 
12291  if (NIL_P(opt)) opt = rb_hash_new();
12292  else opt = rb_hash_dup(opt);
12293 
12294 
12295  if (NIL_P(rb_hash_aref(opt,sym_mode))) {
12296  int mode = O_WRONLY|O_CREAT;
12297 #ifdef O_BINARY
12298  if (binary) mode |= O_BINARY;
12299 #endif
12300  if (NIL_P(offset)) mode |= O_TRUNC;
12301  rb_hash_aset(opt,sym_mode,INT2NUM(mode));
12302  }
12303  open_key_args(klass, argc, argv, opt, &arg);
12304 
12305 #ifndef O_BINARY
12306  if (binary) rb_io_binmode_m(arg.io);
12307 #endif
12308 
12309  if (NIL_P(arg.io)) return Qnil;
12310  if (!NIL_P(offset)) {
12311  struct seek_arg sarg;
12312  int state = 0;
12313  sarg.io = arg.io;
12314  sarg.offset = offset;
12315  sarg.mode = SEEK_SET;
12316  rb_protect(seek_before_access, (VALUE)&sarg, &state);
12317  if (state) {
12318  rb_io_close(arg.io);
12319  rb_jump_tag(state);
12320  }
12321  }
12322 
12323  warg.io = arg.io;
12324  warg.str = string;
12325  warg.nosync = 0;
12326 
12327  return rb_ensure(io_s_write0, (VALUE)&warg, rb_io_close, arg.io);
12328 }
12329 
12330 /*
12331  * call-seq:
12332  * IO.write(path, data, offset = 0, **opts) -> integer
12333  *
12334  * Opens the stream, writes the given +data+ to it,
12335  * and closes the stream; returns the number of bytes written.
12336  *
12337  * When called from class \IO (but not subclasses of \IO),
12338  * this method has potential security vulnerabilities if called with untrusted input;
12339  * see {Command Injection}[rdoc-ref:command_injection.rdoc].
12340  *
12341  * The first argument must be a string that is the path to a file.
12342  *
12343  * With only argument +path+ given, writes the given +data+ to the file at that path:
12344  *
12345  * IO.write('t.tmp', 'abc') # => 3
12346  * File.read('t.tmp') # => "abc"
12347  *
12348  * If +offset+ is zero (the default), the file is overwritten:
12349  *
12350  * IO.write('t.tmp', 'A') # => 1
12351  * File.read('t.tmp') # => "A"
12352  *
12353  * If +offset+ in within the file content, the file is partly overwritten:
12354  *
12355  * IO.write('t.tmp', 'abcdef') # => 3
12356  * File.read('t.tmp') # => "abcdef"
12357  * # Offset within content.
12358  * IO.write('t.tmp', '012', 2) # => 3
12359  * File.read('t.tmp') # => "ab012f"
12360  *
12361  * If +offset+ is outside the file content,
12362  * the file is padded with null characters <tt>"\u0000"</tt>:
12363  *
12364  * IO.write('t.tmp', 'xyz', 10) # => 3
12365  * File.read('t.tmp') # => "ab012f\u0000\u0000\u0000\u0000xyz"
12366  *
12367  * Optional keyword arguments +opts+ specify:
12368  *
12369  * - {Open Options}[rdoc-ref:IO@Open+Options].
12370  * - {Encoding options}[rdoc-ref:encodings.rdoc@Encoding+Options].
12371  *
12372  */
12373 
12374 static VALUE
12375 rb_io_s_write(int argc, VALUE *argv, VALUE io)
12376 {
12377  return io_s_write(argc, argv, io, 0);
12378 }
12379 
12380 /*
12381  * call-seq:
12382  * IO.binwrite(path, string, offset = 0) -> integer
12383  *
12384  * Behaves like IO.write, except that the stream is opened in binary mode
12385  * with ASCII-8BIT encoding.
12386  *
12387  * When called from class \IO (but not subclasses of \IO),
12388  * this method has potential security vulnerabilities if called with untrusted input;
12389  * see {Command Injection}[rdoc-ref:command_injection.rdoc].
12390  *
12391  */
12392 
12393 static VALUE
12394 rb_io_s_binwrite(int argc, VALUE *argv, VALUE io)
12395 {
12396  return io_s_write(argc, argv, io, 1);
12397 }
12398 
12400  VALUE src;
12401  VALUE dst;
12402  rb_off_t copy_length; /* (rb_off_t)-1 if not specified */
12403  rb_off_t src_offset; /* (rb_off_t)-1 if not specified */
12404 
12405  rb_io_t *src_fptr;
12406  rb_io_t *dst_fptr;
12407  unsigned close_src : 1;
12408  unsigned close_dst : 1;
12409  int error_no;
12410  rb_off_t total;
12411  const char *syserr;
12412  const char *notimp;
12413  VALUE th;
12414  struct stat src_stat;
12415  struct stat dst_stat;
12416 #ifdef HAVE_FCOPYFILE
12417  copyfile_state_t copyfile_state;
12418 #endif
12419 };
12420 
12421 static void *
12422 exec_interrupts(void *arg)
12423 {
12424  VALUE th = (VALUE)arg;
12425  rb_thread_execute_interrupts(th);
12426  return NULL;
12427 }
12428 
12429 /*
12430  * returns TRUE if the preceding system call was interrupted
12431  * so we can continue. If the thread was interrupted, we
12432  * reacquire the GVL to execute interrupts before continuing.
12433  */
12434 static int
12435 maygvl_copy_stream_continue_p(int has_gvl, struct copy_stream_struct *stp)
12436 {
12437  switch (errno) {
12438  case EINTR:
12439 #if defined(ERESTART)
12440  case ERESTART:
12441 #endif
12442  if (rb_thread_interrupted(stp->th)) {
12443  if (has_gvl)
12444  rb_thread_execute_interrupts(stp->th);
12445  else
12446  rb_thread_call_with_gvl(exec_interrupts, (void *)stp->th);
12447  }
12448  return TRUE;
12449  }
12450  return FALSE;
12451 }
12452 
12454  VALUE scheduler;
12455 
12456  rb_io_t *fptr;
12457  short events;
12458 
12459  VALUE result;
12460 };
12461 
12462 static void *
12463 fiber_scheduler_wait_for(void * _arguments)
12464 {
12465  struct fiber_scheduler_wait_for_arguments *arguments = (struct fiber_scheduler_wait_for_arguments *)_arguments;
12466 
12467  arguments->result = rb_fiber_scheduler_io_wait(arguments->scheduler, arguments->fptr->self, INT2NUM(arguments->events), RUBY_IO_TIMEOUT_DEFAULT);
12468 
12469  return NULL;
12470 }
12471 
12472 #if USE_POLL
12473 # define IOWAIT_SYSCALL "poll"
12474 STATIC_ASSERT(pollin_expected, POLLIN == RB_WAITFD_IN);
12475 STATIC_ASSERT(pollout_expected, POLLOUT == RB_WAITFD_OUT);
12476 static int
12477 nogvl_wait_for(VALUE th, rb_io_t *fptr, short events, struct timeval *timeout)
12478 {
12480  if (scheduler != Qnil) {
12481  struct fiber_scheduler_wait_for_arguments args = {.scheduler = scheduler, .fptr = fptr, .events = events};
12482  rb_thread_call_with_gvl(fiber_scheduler_wait_for, &args);
12483  return RTEST(args.result);
12484  }
12485 
12486  int fd = fptr->fd;
12487  if (fd == -1) return 0;
12488 
12489  struct pollfd fds;
12490 
12491  fds.fd = fd;
12492  fds.events = events;
12493 
12494  int timeout_milliseconds = -1;
12495 
12496  if (timeout) {
12497  timeout_milliseconds = (int)(timeout->tv_sec * 1000) + (int)(timeout->tv_usec / 1000);
12498  }
12499 
12500  return poll(&fds, 1, timeout_milliseconds);
12501 }
12502 #else /* !USE_POLL */
12503 # define IOWAIT_SYSCALL "select"
12504 static int
12505 nogvl_wait_for(VALUE th, rb_io_t *fptr, short events, struct timeval *timeout)
12506 {
12508  if (scheduler != Qnil) {
12509  struct fiber_scheduler_wait_for_arguments args = {.scheduler = scheduler, .fptr = fptr, .events = events};
12510  rb_thread_call_with_gvl(fiber_scheduler_wait_for, &args);
12511  return RTEST(args.result);
12512  }
12513 
12514  int fd = fptr->fd;
12515 
12516  if (fd == -1) {
12517  errno = EBADF;
12518  return -1;
12519  }
12520 
12521  rb_fdset_t fds;
12522  int ret;
12523 
12524  rb_fd_init(&fds);
12525  rb_fd_set(fd, &fds);
12526 
12527  switch (events) {
12528  case RB_WAITFD_IN:
12529  ret = rb_fd_select(fd + 1, &fds, 0, 0, timeout);
12530  break;
12531  case RB_WAITFD_OUT:
12532  ret = rb_fd_select(fd + 1, 0, &fds, 0, timeout);
12533  break;
12534  default:
12535  VM_UNREACHABLE(nogvl_wait_for);
12536  }
12537 
12538  rb_fd_term(&fds);
12539 
12540  // On timeout, this returns 0.
12541  return ret;
12542 }
12543 #endif /* !USE_POLL */
12544 
12545 static int
12546 maygvl_copy_stream_wait_read(int has_gvl, struct copy_stream_struct *stp)
12547 {
12548  int ret;
12549 
12550  do {
12551  if (has_gvl) {
12553  }
12554  else {
12555  ret = nogvl_wait_for(stp->th, stp->src_fptr, RB_WAITFD_IN, NULL);
12556  }
12557  } while (ret < 0 && maygvl_copy_stream_continue_p(has_gvl, stp));
12558 
12559  if (ret < 0) {
12560  stp->syserr = IOWAIT_SYSCALL;
12561  stp->error_no = errno;
12562  return ret;
12563  }
12564  return 0;
12565 }
12566 
12567 static int
12568 nogvl_copy_stream_wait_write(struct copy_stream_struct *stp)
12569 {
12570  int ret;
12571 
12572  do {
12573  ret = nogvl_wait_for(stp->th, stp->dst_fptr, RB_WAITFD_OUT, NULL);
12574  } while (ret < 0 && maygvl_copy_stream_continue_p(0, stp));
12575 
12576  if (ret < 0) {
12577  stp->syserr = IOWAIT_SYSCALL;
12578  stp->error_no = errno;
12579  return ret;
12580  }
12581  return 0;
12582 }
12583 
12584 #ifdef USE_COPY_FILE_RANGE
12585 
12586 static ssize_t
12587 simple_copy_file_range(int in_fd, rb_off_t *in_offset, int out_fd, rb_off_t *out_offset, size_t count, unsigned int flags)
12588 {
12589 #ifdef HAVE_COPY_FILE_RANGE
12590  return copy_file_range(in_fd, in_offset, out_fd, out_offset, count, flags);
12591 #else
12592  return syscall(__NR_copy_file_range, in_fd, in_offset, out_fd, out_offset, count, flags);
12593 #endif
12594 }
12595 
12596 static int
12597 nogvl_copy_file_range(struct copy_stream_struct *stp)
12598 {
12599  ssize_t ss;
12600  rb_off_t src_size;
12601  rb_off_t copy_length, src_offset, *src_offset_ptr;
12602 
12603  if (!S_ISREG(stp->src_stat.st_mode))
12604  return 0;
12605 
12606  src_size = stp->src_stat.st_size;
12607  src_offset = stp->src_offset;
12608  if (src_offset >= (rb_off_t)0) {
12609  src_offset_ptr = &src_offset;
12610  }
12611  else {
12612  src_offset_ptr = NULL; /* if src_offset_ptr is NULL, then bytes are read from in_fd starting from the file offset */
12613  }
12614 
12615  copy_length = stp->copy_length;
12616  if (copy_length < (rb_off_t)0) {
12617  if (src_offset < (rb_off_t)0) {
12618  rb_off_t current_offset;
12619  errno = 0;
12620  current_offset = lseek(stp->src_fptr->fd, 0, SEEK_CUR);
12621  if (current_offset < (rb_off_t)0 && errno) {
12622  stp->syserr = "lseek";
12623  stp->error_no = errno;
12624  return (int)current_offset;
12625  }
12626  copy_length = src_size - current_offset;
12627  }
12628  else {
12629  copy_length = src_size - src_offset;
12630  }
12631  }
12632 
12633  retry_copy_file_range:
12634 # if SIZEOF_OFF_T > SIZEOF_SIZE_T
12635  /* we are limited by the 32-bit ssize_t return value on 32-bit */
12636  ss = (copy_length > (rb_off_t)SSIZE_MAX) ? SSIZE_MAX : (ssize_t)copy_length;
12637 # else
12638  ss = (ssize_t)copy_length;
12639 # endif
12640  ss = simple_copy_file_range(stp->src_fptr->fd, src_offset_ptr, stp->dst_fptr->fd, NULL, ss, 0);
12641  if (0 < ss) {
12642  stp->total += ss;
12643  copy_length -= ss;
12644  if (0 < copy_length) {
12645  goto retry_copy_file_range;
12646  }
12647  }
12648  if (ss < 0) {
12649  if (maygvl_copy_stream_continue_p(0, stp)) {
12650  goto retry_copy_file_range;
12651  }
12652  switch (errno) {
12653  case EINVAL:
12654  case EPERM: /* copy_file_range(2) doesn't exist (may happen in
12655  docker container) */
12656 #ifdef ENOSYS
12657  case ENOSYS:
12658 #endif
12659 #ifdef EXDEV
12660  case EXDEV: /* in_fd and out_fd are not on the same filesystem */
12661 #endif
12662  return 0;
12663  case EAGAIN:
12664 #if EWOULDBLOCK != EAGAIN
12665  case EWOULDBLOCK:
12666 #endif
12667  {
12668  int ret = nogvl_copy_stream_wait_write(stp);
12669  if (ret < 0) return ret;
12670  }
12671  goto retry_copy_file_range;
12672  case EBADF:
12673  {
12674  int e = errno;
12675  int flags = fcntl(stp->dst_fptr->fd, F_GETFL);
12676 
12677  if (flags != -1 && flags & O_APPEND) {
12678  return 0;
12679  }
12680  errno = e;
12681  }
12682  }
12683  stp->syserr = "copy_file_range";
12684  stp->error_no = errno;
12685  return (int)ss;
12686  }
12687  return 1;
12688 }
12689 #endif
12690 
12691 #ifdef HAVE_FCOPYFILE
12692 static int
12693 nogvl_fcopyfile(struct copy_stream_struct *stp)
12694 {
12695  rb_off_t cur, ss = 0;
12696  const rb_off_t src_offset = stp->src_offset;
12697  int ret;
12698 
12699  if (stp->copy_length >= (rb_off_t)0) {
12700  /* copy_length can't be specified in fcopyfile(3) */
12701  return 0;
12702  }
12703 
12704  if (!S_ISREG(stp->src_stat.st_mode))
12705  return 0;
12706 
12707  if (!S_ISREG(stp->dst_stat.st_mode))
12708  return 0;
12709  if (lseek(stp->dst_fptr->fd, 0, SEEK_CUR) > (rb_off_t)0) /* if dst IO was already written */
12710  return 0;
12711  if (fcntl(stp->dst_fptr->fd, F_GETFL) & O_APPEND) {
12712  /* fcopyfile(3) appends src IO to dst IO and then truncates
12713  * dst IO to src IO's original size. */
12714  rb_off_t end = lseek(stp->dst_fptr->fd, 0, SEEK_END);
12715  lseek(stp->dst_fptr->fd, 0, SEEK_SET);
12716  if (end > (rb_off_t)0) return 0;
12717  }
12718 
12719  if (src_offset > (rb_off_t)0) {
12720  rb_off_t r;
12721 
12722  /* get current offset */
12723  errno = 0;
12724  cur = lseek(stp->src_fptr->fd, 0, SEEK_CUR);
12725  if (cur < (rb_off_t)0 && errno) {
12726  stp->error_no = errno;
12727  return 1;
12728  }
12729 
12730  errno = 0;
12731  r = lseek(stp->src_fptr->fd, src_offset, SEEK_SET);
12732  if (r < (rb_off_t)0 && errno) {
12733  stp->error_no = errno;
12734  return 1;
12735  }
12736  }
12737 
12738  stp->copyfile_state = copyfile_state_alloc(); /* this will be freed by copy_stream_finalize() */
12739  ret = fcopyfile(stp->src_fptr->fd, stp->dst_fptr->fd, stp->copyfile_state, COPYFILE_DATA);
12740  copyfile_state_get(stp->copyfile_state, COPYFILE_STATE_COPIED, &ss); /* get copied bytes */
12741 
12742  if (ret == 0) { /* success */
12743  stp->total = ss;
12744  if (src_offset > (rb_off_t)0) {
12745  rb_off_t r;
12746  errno = 0;
12747  /* reset offset */
12748  r = lseek(stp->src_fptr->fd, cur, SEEK_SET);
12749  if (r < (rb_off_t)0 && errno) {
12750  stp->error_no = errno;
12751  return 1;
12752  }
12753  }
12754  }
12755  else {
12756  switch (errno) {
12757  case ENOTSUP:
12758  case EPERM:
12759  case EINVAL:
12760  return 0;
12761  }
12762  stp->syserr = "fcopyfile";
12763  stp->error_no = errno;
12764  return (int)ret;
12765  }
12766  return 1;
12767 }
12768 #endif
12769 
12770 #ifdef HAVE_SENDFILE
12771 
12772 # ifdef __linux__
12773 # define USE_SENDFILE
12774 
12775 # ifdef HAVE_SYS_SENDFILE_H
12776 # include <sys/sendfile.h>
12777 # endif
12778 
12779 static ssize_t
12780 simple_sendfile(int out_fd, int in_fd, rb_off_t *offset, rb_off_t count)
12781 {
12782  return sendfile(out_fd, in_fd, offset, (size_t)count);
12783 }
12784 
12785 # elif 0 /* defined(__FreeBSD__) || defined(__DragonFly__) */ || defined(__APPLE__)
12786 /* This runs on FreeBSD8.1 r30210, but sendfiles blocks its execution
12787  * without cpuset -l 0.
12788  */
12789 # define USE_SENDFILE
12790 
12791 static ssize_t
12792 simple_sendfile(int out_fd, int in_fd, rb_off_t *offset, rb_off_t count)
12793 {
12794  int r;
12795  rb_off_t pos = offset ? *offset : lseek(in_fd, 0, SEEK_CUR);
12796  rb_off_t sbytes;
12797 # ifdef __APPLE__
12798  r = sendfile(in_fd, out_fd, pos, &count, NULL, 0);
12799  sbytes = count;
12800 # else
12801  r = sendfile(in_fd, out_fd, pos, (size_t)count, NULL, &sbytes, 0);
12802 # endif
12803  if (r != 0 && sbytes == 0) return r;
12804  if (offset) {
12805  *offset += sbytes;
12806  }
12807  else {
12808  lseek(in_fd, sbytes, SEEK_CUR);
12809  }
12810  return (ssize_t)sbytes;
12811 }
12812 
12813 # endif
12814 
12815 #endif
12816 
12817 #ifdef USE_SENDFILE
12818 static int
12819 nogvl_copy_stream_sendfile(struct copy_stream_struct *stp)
12820 {
12821  ssize_t ss;
12822  rb_off_t src_size;
12823  rb_off_t copy_length;
12824  rb_off_t src_offset;
12825  int use_pread;
12826 
12827  if (!S_ISREG(stp->src_stat.st_mode))
12828  return 0;
12829 
12830  src_size = stp->src_stat.st_size;
12831 #ifndef __linux__
12832  if ((stp->dst_stat.st_mode & S_IFMT) != S_IFSOCK)
12833  return 0;
12834 #endif
12835 
12836  src_offset = stp->src_offset;
12837  use_pread = src_offset >= (rb_off_t)0;
12838 
12839  copy_length = stp->copy_length;
12840  if (copy_length < (rb_off_t)0) {
12841  if (use_pread)
12842  copy_length = src_size - src_offset;
12843  else {
12844  rb_off_t cur;
12845  errno = 0;
12846  cur = lseek(stp->src_fptr->fd, 0, SEEK_CUR);
12847  if (cur < (rb_off_t)0 && errno) {
12848  stp->syserr = "lseek";
12849  stp->error_no = errno;
12850  return (int)cur;
12851  }
12852  copy_length = src_size - cur;
12853  }
12854  }
12855 
12856  retry_sendfile:
12857 # if SIZEOF_OFF_T > SIZEOF_SIZE_T
12858  /* we are limited by the 32-bit ssize_t return value on 32-bit */
12859  ss = (copy_length > (rb_off_t)SSIZE_MAX) ? SSIZE_MAX : (ssize_t)copy_length;
12860 # else
12861  ss = (ssize_t)copy_length;
12862 # endif
12863  if (use_pread) {
12864  ss = simple_sendfile(stp->dst_fptr->fd, stp->src_fptr->fd, &src_offset, ss);
12865  }
12866  else {
12867  ss = simple_sendfile(stp->dst_fptr->fd, stp->src_fptr->fd, NULL, ss);
12868  }
12869  if (0 < ss) {
12870  stp->total += ss;
12871  copy_length -= ss;
12872  if (0 < copy_length) {
12873  goto retry_sendfile;
12874  }
12875  }
12876  if (ss < 0) {
12877  if (maygvl_copy_stream_continue_p(0, stp))
12878  goto retry_sendfile;
12879  switch (errno) {
12880  case EINVAL:
12881 #ifdef ENOSYS
12882  case ENOSYS:
12883 #endif
12884 #ifdef EOPNOTSUP
12885  /* some RedHat kernels may return EOPNOTSUP on an NFS mount.
12886  see also: [Feature #16965] */
12887  case EOPNOTSUP:
12888 #endif
12889  return 0;
12890  case EAGAIN:
12891 #if EWOULDBLOCK != EAGAIN
12892  case EWOULDBLOCK:
12893 #endif
12894  {
12895  int ret;
12896 #ifndef __linux__
12897  /*
12898  * Linux requires stp->src_fptr->fd to be a mmap-able (regular) file,
12899  * select() reports regular files to always be "ready", so
12900  * there is no need to select() on it.
12901  * Other OSes may have the same limitation for sendfile() which
12902  * allow us to bypass maygvl_copy_stream_wait_read()...
12903  */
12904  ret = maygvl_copy_stream_wait_read(0, stp);
12905  if (ret < 0) return ret;
12906 #endif
12907  ret = nogvl_copy_stream_wait_write(stp);
12908  if (ret < 0) return ret;
12909  }
12910  goto retry_sendfile;
12911  }
12912  stp->syserr = "sendfile";
12913  stp->error_no = errno;
12914  return (int)ss;
12915  }
12916  return 1;
12917 }
12918 #endif
12919 
12920 static ssize_t
12921 maygvl_read(int has_gvl, rb_io_t *fptr, void *buf, size_t count)
12922 {
12923  if (has_gvl)
12924  return rb_io_read_memory(fptr, buf, count);
12925  else
12926  return read(fptr->fd, buf, count);
12927 }
12928 
12929 static ssize_t
12930 maygvl_copy_stream_read(int has_gvl, struct copy_stream_struct *stp, char *buf, size_t len, rb_off_t offset)
12931 {
12932  ssize_t ss;
12933  retry_read:
12934  if (offset < (rb_off_t)0) {
12935  ss = maygvl_read(has_gvl, stp->src_fptr, buf, len);
12936  }
12937  else {
12938  ss = pread(stp->src_fptr->fd, buf, len, offset);
12939  }
12940  if (ss == 0) {
12941  return 0;
12942  }
12943  if (ss < 0) {
12944  if (maygvl_copy_stream_continue_p(has_gvl, stp))
12945  goto retry_read;
12946  switch (errno) {
12947  case EAGAIN:
12948 #if EWOULDBLOCK != EAGAIN
12949  case EWOULDBLOCK:
12950 #endif
12951  {
12952  int ret = maygvl_copy_stream_wait_read(has_gvl, stp);
12953  if (ret < 0) return ret;
12954  }
12955  goto retry_read;
12956 #ifdef ENOSYS
12957  case ENOSYS:
12958  stp->notimp = "pread";
12959  return ss;
12960 #endif
12961  }
12962  stp->syserr = offset < (rb_off_t)0 ? "read" : "pread";
12963  stp->error_no = errno;
12964  }
12965  return ss;
12966 }
12967 
12968 static int
12969 nogvl_copy_stream_write(struct copy_stream_struct *stp, char *buf, size_t len)
12970 {
12971  ssize_t ss;
12972  int off = 0;
12973  while (len) {
12974  ss = write(stp->dst_fptr->fd, buf+off, len);
12975  if (ss < 0) {
12976  if (maygvl_copy_stream_continue_p(0, stp))
12977  continue;
12978  if (io_again_p(errno)) {
12979  int ret = nogvl_copy_stream_wait_write(stp);
12980  if (ret < 0) return ret;
12981  continue;
12982  }
12983  stp->syserr = "write";
12984  stp->error_no = errno;
12985  return (int)ss;
12986  }
12987  off += (int)ss;
12988  len -= (int)ss;
12989  stp->total += ss;
12990  }
12991  return 0;
12992 }
12993 
12994 static void
12995 nogvl_copy_stream_read_write(struct copy_stream_struct *stp)
12996 {
12997  char buf[1024*16];
12998  size_t len;
12999  ssize_t ss;
13000  int ret;
13001  rb_off_t copy_length;
13002  rb_off_t src_offset;
13003  int use_eof;
13004  int use_pread;
13005 
13006  copy_length = stp->copy_length;
13007  use_eof = copy_length < (rb_off_t)0;
13008  src_offset = stp->src_offset;
13009  use_pread = src_offset >= (rb_off_t)0;
13010 
13011  if (use_pread && stp->close_src) {
13012  rb_off_t r;
13013  errno = 0;
13014  r = lseek(stp->src_fptr->fd, src_offset, SEEK_SET);
13015  if (r < (rb_off_t)0 && errno) {
13016  stp->syserr = "lseek";
13017  stp->error_no = errno;
13018  return;
13019  }
13020  src_offset = (rb_off_t)-1;
13021  use_pread = 0;
13022  }
13023 
13024  while (use_eof || 0 < copy_length) {
13025  if (!use_eof && copy_length < (rb_off_t)sizeof(buf)) {
13026  len = (size_t)copy_length;
13027  }
13028  else {
13029  len = sizeof(buf);
13030  }
13031  if (use_pread) {
13032  ss = maygvl_copy_stream_read(0, stp, buf, len, src_offset);
13033  if (0 < ss)
13034  src_offset += ss;
13035  }
13036  else {
13037  ss = maygvl_copy_stream_read(0, stp, buf, len, (rb_off_t)-1);
13038  }
13039  if (ss <= 0) /* EOF or error */
13040  return;
13041 
13042  ret = nogvl_copy_stream_write(stp, buf, ss);
13043  if (ret < 0)
13044  return;
13045 
13046  if (!use_eof)
13047  copy_length -= ss;
13048  }
13049 }
13050 
13051 static void *
13052 nogvl_copy_stream_func(void *arg)
13053 {
13054  struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
13055 #if defined(USE_SENDFILE) || defined(USE_COPY_FILE_RANGE) || defined(HAVE_FCOPYFILE)
13056  int ret;
13057 #endif
13058 
13059 #ifdef USE_COPY_FILE_RANGE
13060  ret = nogvl_copy_file_range(stp);
13061  if (ret != 0)
13062  goto finish; /* error or success */
13063 #endif
13064 
13065 #ifdef HAVE_FCOPYFILE
13066  ret = nogvl_fcopyfile(stp);
13067  if (ret != 0)
13068  goto finish; /* error or success */
13069 #endif
13070 
13071 #ifdef USE_SENDFILE
13072  ret = nogvl_copy_stream_sendfile(stp);
13073  if (ret != 0)
13074  goto finish; /* error or success */
13075 #endif
13076 
13077  nogvl_copy_stream_read_write(stp);
13078 
13079 #if defined(USE_SENDFILE) || defined(USE_COPY_FILE_RANGE) || defined(HAVE_FCOPYFILE)
13080  finish:
13081 #endif
13082  return 0;
13083 }
13084 
13085 static VALUE
13086 copy_stream_fallback_body(VALUE arg)
13087 {
13088  struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
13089  const int buflen = 16*1024;
13090  VALUE n;
13091  VALUE buf = rb_str_buf_new(buflen);
13092  rb_off_t rest = stp->copy_length;
13093  rb_off_t off = stp->src_offset;
13094  ID read_method = id_readpartial;
13095 
13096  if (!stp->src_fptr) {
13097  if (!rb_respond_to(stp->src, read_method)) {
13098  read_method = id_read;
13099  }
13100  }
13101 
13102  while (1) {
13103  long numwrote;
13104  long l;
13105  if (stp->copy_length < (rb_off_t)0) {
13106  l = buflen;
13107  }
13108  else {
13109  if (rest == 0) {
13110  rb_str_resize(buf, 0);
13111  break;
13112  }
13113  l = buflen < rest ? buflen : (long)rest;
13114  }
13115  if (!stp->src_fptr) {
13116  VALUE rc = rb_funcall(stp->src, read_method, 2, INT2FIX(l), buf);
13117 
13118  if (read_method == id_read && NIL_P(rc))
13119  break;
13120  }
13121  else {
13122  ssize_t ss;
13123  rb_str_resize(buf, buflen);
13124  ss = maygvl_copy_stream_read(1, stp, RSTRING_PTR(buf), l, off);
13125  rb_str_resize(buf, ss > 0 ? ss : 0);
13126  if (ss < 0)
13127  return Qnil;
13128  if (ss == 0)
13129  rb_eof_error();
13130  if (off >= (rb_off_t)0)
13131  off += ss;
13132  }
13133  n = rb_io_write(stp->dst, buf);
13134  numwrote = NUM2LONG(n);
13135  stp->total += numwrote;
13136  rest -= numwrote;
13137  if (read_method == id_read && RSTRING_LEN(buf) == 0) {
13138  break;
13139  }
13140  }
13141 
13142  return Qnil;
13143 }
13144 
13145 static VALUE
13146 copy_stream_fallback(struct copy_stream_struct *stp)
13147 {
13148  if (!stp->src_fptr && stp->src_offset >= (rb_off_t)0) {
13149  rb_raise(rb_eArgError, "cannot specify src_offset for non-IO");
13150  }
13151  rb_rescue2(copy_stream_fallback_body, (VALUE)stp,
13152  (VALUE (*) (VALUE, VALUE))0, (VALUE)0,
13153  rb_eEOFError, (VALUE)0);
13154  return Qnil;
13155 }
13156 
13157 static VALUE
13158 copy_stream_body(VALUE arg)
13159 {
13160  struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
13161  VALUE src_io = stp->src, dst_io = stp->dst;
13162  const int common_oflags = 0
13163 #ifdef O_NOCTTY
13164  | O_NOCTTY
13165 #endif
13166  ;
13167 
13168  stp->th = rb_thread_current();
13169 
13170  stp->total = 0;
13171 
13172  if (src_io == argf ||
13173  !(RB_TYPE_P(src_io, T_FILE) ||
13174  RB_TYPE_P(src_io, T_STRING) ||
13175  rb_respond_to(src_io, rb_intern("to_path")))) {
13176  stp->src_fptr = NULL;
13177  }
13178  else {
13179  int stat_ret;
13180  VALUE tmp_io = rb_io_check_io(src_io);
13181  if (!NIL_P(tmp_io)) {
13182  src_io = tmp_io;
13183  }
13184  else if (!RB_TYPE_P(src_io, T_FILE)) {
13185  VALUE args[2];
13186  FilePathValue(src_io);
13187  args[0] = src_io;
13188  args[1] = INT2NUM(O_RDONLY|common_oflags);
13189  src_io = rb_class_new_instance(2, args, rb_cFile);
13190  stp->src = src_io;
13191  stp->close_src = 1;
13192  }
13193  RB_IO_POINTER(src_io, stp->src_fptr);
13194  rb_io_check_byte_readable(stp->src_fptr);
13195 
13196  stat_ret = fstat(stp->src_fptr->fd, &stp->src_stat);
13197  if (stat_ret < 0) {
13198  stp->syserr = "fstat";
13199  stp->error_no = errno;
13200  return Qnil;
13201  }
13202  }
13203 
13204  if (dst_io == argf ||
13205  !(RB_TYPE_P(dst_io, T_FILE) ||
13206  RB_TYPE_P(dst_io, T_STRING) ||
13207  rb_respond_to(dst_io, rb_intern("to_path")))) {
13208  stp->dst_fptr = NULL;
13209  }
13210  else {
13211  int stat_ret;
13212  VALUE tmp_io = rb_io_check_io(dst_io);
13213  if (!NIL_P(tmp_io)) {
13214  dst_io = GetWriteIO(tmp_io);
13215  }
13216  else if (!RB_TYPE_P(dst_io, T_FILE)) {
13217  VALUE args[3];
13218  FilePathValue(dst_io);
13219  args[0] = dst_io;
13220  args[1] = INT2NUM(O_WRONLY|O_CREAT|O_TRUNC|common_oflags);
13221  args[2] = INT2FIX(0666);
13222  dst_io = rb_class_new_instance(3, args, rb_cFile);
13223  stp->dst = dst_io;
13224  stp->close_dst = 1;
13225  }
13226  else {
13227  dst_io = GetWriteIO(dst_io);
13228  stp->dst = dst_io;
13229  }
13230  RB_IO_POINTER(dst_io, stp->dst_fptr);
13231  rb_io_check_writable(stp->dst_fptr);
13232 
13233  stat_ret = fstat(stp->dst_fptr->fd, &stp->dst_stat);
13234  if (stat_ret < 0) {
13235  stp->syserr = "fstat";
13236  stp->error_no = errno;
13237  return Qnil;
13238  }
13239  }
13240 
13241 #ifdef O_BINARY
13242  if (stp->src_fptr)
13243  SET_BINARY_MODE_WITH_SEEK_CUR(stp->src_fptr);
13244 #endif
13245  if (stp->dst_fptr)
13246  io_ascii8bit_binmode(stp->dst_fptr);
13247 
13248  if (stp->src_offset < (rb_off_t)0 && stp->src_fptr && stp->src_fptr->rbuf.len) {
13249  size_t len = stp->src_fptr->rbuf.len;
13250  VALUE str;
13251  if (stp->copy_length >= (rb_off_t)0 && stp->copy_length < (rb_off_t)len) {
13252  len = (size_t)stp->copy_length;
13253  }
13254  str = rb_str_buf_new(len);
13255  rb_str_resize(str,len);
13256  read_buffered_data(RSTRING_PTR(str), len, stp->src_fptr);
13257  if (stp->dst_fptr) { /* IO or filename */
13258  if (io_binwrite(RSTRING_PTR(str), RSTRING_LEN(str), stp->dst_fptr, 0) < 0)
13259  rb_sys_fail_on_write(stp->dst_fptr);
13260  }
13261  else /* others such as StringIO */
13262  rb_io_write(dst_io, str);
13263  rb_str_resize(str, 0);
13264  stp->total += len;
13265  if (stp->copy_length >= (rb_off_t)0)
13266  stp->copy_length -= len;
13267  }
13268 
13269  if (stp->dst_fptr && io_fflush(stp->dst_fptr) < 0) {
13270  rb_raise(rb_eIOError, "flush failed");
13271  }
13272 
13273  if (stp->copy_length == 0)
13274  return Qnil;
13275 
13276  if (stp->src_fptr == NULL || stp->dst_fptr == NULL) {
13277  return copy_stream_fallback(stp);
13278  }
13279 
13280  IO_WITHOUT_GVL(nogvl_copy_stream_func, stp);
13281  return Qnil;
13282 }
13283 
13284 static VALUE
13285 copy_stream_finalize(VALUE arg)
13286 {
13287  struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
13288 
13289 #ifdef HAVE_FCOPYFILE
13290  if (stp->copyfile_state) {
13291  copyfile_state_free(stp->copyfile_state);
13292  }
13293 #endif
13294 
13295  if (stp->close_src) {
13296  rb_io_close_m(stp->src);
13297  }
13298  if (stp->close_dst) {
13299  rb_io_close_m(stp->dst);
13300  }
13301  if (stp->syserr) {
13302  rb_syserr_fail(stp->error_no, stp->syserr);
13303  }
13304  if (stp->notimp) {
13305  rb_raise(rb_eNotImpError, "%s() not implemented", stp->notimp);
13306  }
13307  return Qnil;
13308 }
13309 
13310 /*
13311  * call-seq:
13312  * IO.copy_stream(src, dst, src_length = nil, src_offset = 0) -> integer
13313  *
13314  * Copies from the given +src+ to the given +dst+,
13315  * returning the number of bytes copied.
13316  *
13317  * - The given +src+ must be one of the following:
13318  *
13319  * - The path to a readable file, from which source data is to be read.
13320  * - An \IO-like object, opened for reading and capable of responding
13321  * to method +:readpartial+ or method +:read+.
13322  *
13323  * - The given +dst+ must be one of the following:
13324  *
13325  * - The path to a writable file, to which data is to be written.
13326  * - An \IO-like object, opened for writing and capable of responding
13327  * to method +:write+.
13328  *
13329  * The examples here use file <tt>t.txt</tt> as source:
13330  *
13331  * File.read('t.txt')
13332  * # => "First line\nSecond line\n\nThird line\nFourth line\n"
13333  * File.read('t.txt').size # => 47
13334  *
13335  * If only arguments +src+ and +dst+ are given,
13336  * the entire source stream is copied:
13337  *
13338  * # Paths.
13339  * IO.copy_stream('t.txt', 't.tmp') # => 47
13340  *
13341  * # IOs (recall that a File is also an IO).
13342  * src_io = File.open('t.txt', 'r') # => #<File:t.txt>
13343  * dst_io = File.open('t.tmp', 'w') # => #<File:t.tmp>
13344  * IO.copy_stream(src_io, dst_io) # => 47
13345  * src_io.close
13346  * dst_io.close
13347  *
13348  * With argument +src_length+ a non-negative integer,
13349  * no more than that many bytes are copied:
13350  *
13351  * IO.copy_stream('t.txt', 't.tmp', 10) # => 10
13352  * File.read('t.tmp') # => "First line"
13353  *
13354  * With argument +src_offset+ also given,
13355  * the source stream is read beginning at that offset:
13356  *
13357  * IO.copy_stream('t.txt', 't.tmp', 11, 11) # => 11
13358  * IO.read('t.tmp') # => "Second line"
13359  *
13360  */
13361 static VALUE
13362 rb_io_s_copy_stream(int argc, VALUE *argv, VALUE io)
13363 {
13364  VALUE src, dst, length, src_offset;
13365  struct copy_stream_struct st;
13366 
13367  MEMZERO(&st, struct copy_stream_struct, 1);
13368 
13369  rb_scan_args(argc, argv, "22", &src, &dst, &length, &src_offset);
13370 
13371  st.src = src;
13372  st.dst = dst;
13373 
13374  st.src_fptr = NULL;
13375  st.dst_fptr = NULL;
13376 
13377  if (NIL_P(length))
13378  st.copy_length = (rb_off_t)-1;
13379  else
13380  st.copy_length = NUM2OFFT(length);
13381 
13382  if (NIL_P(src_offset))
13383  st.src_offset = (rb_off_t)-1;
13384  else
13385  st.src_offset = NUM2OFFT(src_offset);
13386 
13387  rb_ensure(copy_stream_body, (VALUE)&st, copy_stream_finalize, (VALUE)&st);
13388 
13389  return OFFT2NUM(st.total);
13390 }
13391 
13392 /*
13393  * call-seq:
13394  * external_encoding -> encoding or nil
13395  *
13396  * Returns the Encoding object that represents the encoding of the stream,
13397  * or +nil+ if the stream is in write mode and no encoding is specified.
13398  *
13399  * See {Encodings}[rdoc-ref:File@Encodings].
13400  *
13401  */
13402 
13403 static VALUE
13404 rb_io_external_encoding(VALUE io)
13405 {
13406  rb_io_t *fptr = RFILE(rb_io_taint_check(io))->fptr;
13407 
13408  if (fptr->encs.enc2) {
13409  return rb_enc_from_encoding(fptr->encs.enc2);
13410  }
13411  if (fptr->mode & FMODE_WRITABLE) {
13412  if (fptr->encs.enc)
13413  return rb_enc_from_encoding(fptr->encs.enc);
13414  return Qnil;
13415  }
13416  return rb_enc_from_encoding(io_read_encoding(fptr));
13417 }
13418 
13419 /*
13420  * call-seq:
13421  * internal_encoding -> encoding or nil
13422  *
13423  * Returns the Encoding object that represents the encoding of the internal string,
13424  * if conversion is specified,
13425  * or +nil+ otherwise.
13426  *
13427  * See {Encodings}[rdoc-ref:File@Encodings].
13428  *
13429  */
13430 
13431 static VALUE
13432 rb_io_internal_encoding(VALUE io)
13433 {
13434  rb_io_t *fptr = RFILE(rb_io_taint_check(io))->fptr;
13435 
13436  if (!fptr->encs.enc2) return Qnil;
13437  return rb_enc_from_encoding(io_read_encoding(fptr));
13438 }
13439 
13440 /*
13441  * call-seq:
13442  * set_encoding(ext_enc) -> self
13443  * set_encoding(ext_enc, int_enc, **enc_opts) -> self
13444  * set_encoding('ext_enc:int_enc', **enc_opts) -> self
13445  *
13446  * See {Encodings}[rdoc-ref:File@Encodings].
13447  *
13448  * Argument +ext_enc+, if given, must be an Encoding object
13449  * or a String with the encoding name;
13450  * it is assigned as the encoding for the stream.
13451  *
13452  * Argument +int_enc+, if given, must be an Encoding object
13453  * or a String with the encoding name;
13454  * it is assigned as the encoding for the internal string.
13455  *
13456  * Argument <tt>'ext_enc:int_enc'</tt>, if given, is a string
13457  * containing two colon-separated encoding names;
13458  * corresponding Encoding objects are assigned as the external
13459  * and internal encodings for the stream.
13460  *
13461  * If the external encoding of a string is binary/ASCII-8BIT,
13462  * the internal encoding of the string is set to nil, since no
13463  * transcoding is needed.
13464  *
13465  * Optional keyword arguments +enc_opts+ specify
13466  * {Encoding options}[rdoc-ref:encodings.rdoc@Encoding+Options].
13467  *
13468  */
13469 
13470 static VALUE
13471 rb_io_set_encoding(int argc, VALUE *argv, VALUE io)
13472 {
13473  rb_io_t *fptr;
13474  VALUE v1, v2, opt;
13475 
13476  if (!RB_TYPE_P(io, T_FILE)) {
13477  return forward(io, id_set_encoding, argc, argv);
13478  }
13479 
13480  argc = rb_scan_args(argc, argv, "11:", &v1, &v2, &opt);
13481  GetOpenFile(io, fptr);
13482  io_encoding_set(fptr, v1, v2, opt);
13483  return io;
13484 }
13485 
13486 void
13487 rb_stdio_set_default_encoding(void)
13488 {
13489  VALUE val = Qnil;
13490 
13491 #ifdef _WIN32
13492  if (isatty(fileno(stdin))) {
13493  rb_encoding *external = rb_locale_encoding();
13495  if (!internal) internal = rb_default_external_encoding();
13496  io_encoding_set(RFILE(rb_stdin)->fptr,
13497  rb_enc_from_encoding(external),
13498  rb_enc_from_encoding(internal),
13499  Qnil);
13500  }
13501  else
13502 #endif
13503  rb_io_set_encoding(1, &val, rb_stdin);
13504  rb_io_set_encoding(1, &val, rb_stdout);
13505  rb_io_set_encoding(1, &val, rb_stderr);
13506 }
13507 
13508 static inline int
13509 global_argf_p(VALUE arg)
13510 {
13511  return arg == argf;
13512 }
13513 
13514 typedef VALUE (*argf_encoding_func)(VALUE io);
13515 
13516 static VALUE
13517 argf_encoding(VALUE argf, argf_encoding_func func)
13518 {
13519  if (!RTEST(ARGF.current_file)) {
13520  return rb_enc_default_external();
13521  }
13522  return func(rb_io_check_io(ARGF.current_file));
13523 }
13524 
13525 /*
13526  * call-seq:
13527  * ARGF.external_encoding -> encoding
13528  *
13529  * Returns the external encoding for files read from ARGF as an Encoding
13530  * object. The external encoding is the encoding of the text as stored in a
13531  * file. Contrast with ARGF.internal_encoding, which is the encoding used to
13532  * represent this text within Ruby.
13533  *
13534  * To set the external encoding use ARGF.set_encoding.
13535  *
13536  * For example:
13537  *
13538  * ARGF.external_encoding #=> #<Encoding:UTF-8>
13539  *
13540  */
13541 static VALUE
13542 argf_external_encoding(VALUE argf)
13543 {
13544  return argf_encoding(argf, rb_io_external_encoding);
13545 }
13546 
13547 /*
13548  * call-seq:
13549  * ARGF.internal_encoding -> encoding
13550  *
13551  * Returns the internal encoding for strings read from ARGF as an
13552  * Encoding object.
13553  *
13554  * If ARGF.set_encoding has been called with two encoding names, the second
13555  * is returned. Otherwise, if +Encoding.default_external+ has been set, that
13556  * value is returned. Failing that, if a default external encoding was
13557  * specified on the command-line, that value is used. If the encoding is
13558  * unknown, +nil+ is returned.
13559  */
13560 static VALUE
13561 argf_internal_encoding(VALUE argf)
13562 {
13563  return argf_encoding(argf, rb_io_internal_encoding);
13564 }
13565 
13566 /*
13567  * call-seq:
13568  * ARGF.set_encoding(ext_enc) -> ARGF
13569  * ARGF.set_encoding("ext_enc:int_enc") -> ARGF
13570  * ARGF.set_encoding(ext_enc, int_enc) -> ARGF
13571  * ARGF.set_encoding("ext_enc:int_enc", opt) -> ARGF
13572  * ARGF.set_encoding(ext_enc, int_enc, opt) -> ARGF
13573  *
13574  * If single argument is specified, strings read from ARGF are tagged with
13575  * the encoding specified.
13576  *
13577  * If two encoding names separated by a colon are given, e.g. "ascii:utf-8",
13578  * the read string is converted from the first encoding (external encoding)
13579  * to the second encoding (internal encoding), then tagged with the second
13580  * encoding.
13581  *
13582  * If two arguments are specified, they must be encoding objects or encoding
13583  * names. Again, the first specifies the external encoding; the second
13584  * specifies the internal encoding.
13585  *
13586  * If the external encoding and the internal encoding are specified, the
13587  * optional Hash argument can be used to adjust the conversion process. The
13588  * structure of this hash is explained in the String#encode documentation.
13589  *
13590  * For example:
13591  *
13592  * ARGF.set_encoding('ascii') # Tag the input as US-ASCII text
13593  * ARGF.set_encoding(Encoding::UTF_8) # Tag the input as UTF-8 text
13594  * ARGF.set_encoding('utf-8','ascii') # Transcode the input from US-ASCII
13595  * # to UTF-8.
13596  */
13597 static VALUE
13598 argf_set_encoding(int argc, VALUE *argv, VALUE argf)
13599 {
13600  rb_io_t *fptr;
13601 
13602  if (!next_argv()) {
13603  rb_raise(rb_eArgError, "no stream to set encoding");
13604  }
13605  rb_io_set_encoding(argc, argv, ARGF.current_file);
13606  GetOpenFile(ARGF.current_file, fptr);
13607  ARGF.encs = fptr->encs;
13608  return argf;
13609 }
13610 
13611 /*
13612  * call-seq:
13613  * ARGF.tell -> Integer
13614  * ARGF.pos -> Integer
13615  *
13616  * Returns the current offset (in bytes) of the current file in ARGF.
13617  *
13618  * ARGF.pos #=> 0
13619  * ARGF.gets #=> "This is line one\n"
13620  * ARGF.pos #=> 17
13621  *
13622  */
13623 static VALUE
13624 argf_tell(VALUE argf)
13625 {
13626  if (!next_argv()) {
13627  rb_raise(rb_eArgError, "no stream to tell");
13628  }
13629  ARGF_FORWARD(0, 0);
13630  return rb_io_tell(ARGF.current_file);
13631 }
13632 
13633 /*
13634  * call-seq:
13635  * ARGF.seek(amount, whence=IO::SEEK_SET) -> 0
13636  *
13637  * Seeks to offset _amount_ (an Integer) in the ARGF stream according to
13638  * the value of _whence_. See IO#seek for further details.
13639  */
13640 static VALUE
13641 argf_seek_m(int argc, VALUE *argv, VALUE argf)
13642 {
13643  if (!next_argv()) {
13644  rb_raise(rb_eArgError, "no stream to seek");
13645  }
13646  ARGF_FORWARD(argc, argv);
13647  return rb_io_seek_m(argc, argv, ARGF.current_file);
13648 }
13649 
13650 /*
13651  * call-seq:
13652  * ARGF.pos = position -> Integer
13653  *
13654  * Seeks to the position given by _position_ (in bytes) in ARGF.
13655  *
13656  * For example:
13657  *
13658  * ARGF.pos = 17
13659  * ARGF.gets #=> "This is line two\n"
13660  */
13661 static VALUE
13662 argf_set_pos(VALUE argf, VALUE offset)
13663 {
13664  if (!next_argv()) {
13665  rb_raise(rb_eArgError, "no stream to set position");
13666  }
13667  ARGF_FORWARD(1, &offset);
13668  return rb_io_set_pos(ARGF.current_file, offset);
13669 }
13670 
13671 /*
13672  * call-seq:
13673  * ARGF.rewind -> 0
13674  *
13675  * Positions the current file to the beginning of input, resetting
13676  * ARGF.lineno to zero.
13677  *
13678  * ARGF.readline #=> "This is line one\n"
13679  * ARGF.rewind #=> 0
13680  * ARGF.lineno #=> 0
13681  * ARGF.readline #=> "This is line one\n"
13682  */
13683 static VALUE
13684 argf_rewind(VALUE argf)
13685 {
13686  VALUE ret;
13687  int old_lineno;
13688 
13689  if (!next_argv()) {
13690  rb_raise(rb_eArgError, "no stream to rewind");
13691  }
13692  ARGF_FORWARD(0, 0);
13693  old_lineno = RFILE(ARGF.current_file)->fptr->lineno;
13694  ret = rb_io_rewind(ARGF.current_file);
13695  if (!global_argf_p(argf)) {
13696  ARGF.last_lineno = ARGF.lineno -= old_lineno;
13697  }
13698  return ret;
13699 }
13700 
13701 /*
13702  * call-seq:
13703  * ARGF.fileno -> integer
13704  * ARGF.to_i -> integer
13705  *
13706  * Returns an integer representing the numeric file descriptor for
13707  * the current file. Raises an ArgumentError if there isn't a current file.
13708  *
13709  * ARGF.fileno #=> 3
13710  */
13711 static VALUE
13712 argf_fileno(VALUE argf)
13713 {
13714  if (!next_argv()) {
13715  rb_raise(rb_eArgError, "no stream");
13716  }
13717  ARGF_FORWARD(0, 0);
13718  return rb_io_fileno(ARGF.current_file);
13719 }
13720 
13721 /*
13722  * call-seq:
13723  * ARGF.to_io -> IO
13724  *
13725  * Returns an IO object representing the current file. This will be a
13726  * File object unless the current file is a stream such as STDIN.
13727  *
13728  * For example:
13729  *
13730  * ARGF.to_io #=> #<File:glark.txt>
13731  * ARGF.to_io #=> #<IO:<STDIN>>
13732  */
13733 static VALUE
13734 argf_to_io(VALUE argf)
13735 {
13736  next_argv();
13737  ARGF_FORWARD(0, 0);
13738  return ARGF.current_file;
13739 }
13740 
13741 /*
13742  * call-seq:
13743  * ARGF.eof? -> true or false
13744  * ARGF.eof -> true or false
13745  *
13746  * Returns true if the current file in ARGF is at end of file, i.e. it has
13747  * no data to read. The stream must be opened for reading or an IOError
13748  * will be raised.
13749  *
13750  * $ echo "eof" | ruby argf.rb
13751  *
13752  * ARGF.eof? #=> false
13753  * 3.times { ARGF.readchar }
13754  * ARGF.eof? #=> false
13755  * ARGF.readchar #=> "\n"
13756  * ARGF.eof? #=> true
13757  */
13758 
13759 static VALUE
13760 argf_eof(VALUE argf)
13761 {
13762  next_argv();
13763  if (RTEST(ARGF.current_file)) {
13764  if (ARGF.init_p == 0) return Qtrue;
13765  next_argv();
13766  ARGF_FORWARD(0, 0);
13767  if (rb_io_eof(ARGF.current_file)) {
13768  return Qtrue;
13769  }
13770  }
13771  return Qfalse;
13772 }
13773 
13774 /*
13775  * call-seq:
13776  * ARGF.read([length [, outbuf]]) -> string, outbuf, or nil
13777  *
13778  * Reads _length_ bytes from ARGF. The files named on the command line
13779  * are concatenated and treated as a single file by this method, so when
13780  * called without arguments the contents of this pseudo file are returned in
13781  * their entirety.
13782  *
13783  * _length_ must be a non-negative integer or +nil+.
13784  *
13785  * If _length_ is a positive integer, +read+ tries to read
13786  * _length_ bytes without any conversion (binary mode).
13787  * It returns +nil+ if an EOF is encountered before anything can be read.
13788  * Fewer than _length_ bytes are returned if an EOF is encountered during
13789  * the read.
13790  * In the case of an integer _length_, the resulting string is always
13791  * in ASCII-8BIT encoding.
13792  *
13793  * If _length_ is omitted or is +nil+, it reads until EOF
13794  * and the encoding conversion is applied, if applicable.
13795  * A string is returned even if EOF is encountered before any data is read.
13796  *
13797  * If _length_ is zero, it returns an empty string (<code>""</code>).
13798  *
13799  * If the optional _outbuf_ argument is present,
13800  * it must reference a String, which will receive the data.
13801  * The _outbuf_ will contain only the received data after the method call
13802  * even if it is not empty at the beginning.
13803  *
13804  * For example:
13805  *
13806  * $ echo "small" > small.txt
13807  * $ echo "large" > large.txt
13808  * $ ./glark.rb small.txt large.txt
13809  *
13810  * ARGF.read #=> "small\nlarge"
13811  * ARGF.read(200) #=> "small\nlarge"
13812  * ARGF.read(2) #=> "sm"
13813  * ARGF.read(0) #=> ""
13814  *
13815  * Note that this method behaves like the fread() function in C.
13816  * This means it retries to invoke read(2) system calls to read data
13817  * with the specified length.
13818  * If you need the behavior like a single read(2) system call,
13819  * consider ARGF#readpartial or ARGF#read_nonblock.
13820  */
13821 
13822 static VALUE
13823 argf_read(int argc, VALUE *argv, VALUE argf)
13824 {
13825  VALUE tmp, str, length;
13826  long len = 0;
13827 
13828  rb_scan_args(argc, argv, "02", &length, &str);
13829  if (!NIL_P(length)) {
13830  len = NUM2LONG(argv[0]);
13831  }
13832  if (!NIL_P(str)) {
13833  StringValue(str);
13834  rb_str_resize(str,0);
13835  argv[1] = Qnil;
13836  }
13837 
13838  retry:
13839  if (!next_argv()) {
13840  return str;
13841  }
13842  if (ARGF_GENERIC_INPUT_P()) {
13843  tmp = argf_forward(argc, argv, argf);
13844  }
13845  else {
13846  tmp = io_read(argc, argv, ARGF.current_file);
13847  }
13848  if (NIL_P(str)) str = tmp;
13849  else if (!NIL_P(tmp)) rb_str_append(str, tmp);
13850  if (NIL_P(tmp) || NIL_P(length)) {
13851  if (ARGF.next_p != -1) {
13852  argf_close(argf);
13853  ARGF.next_p = 1;
13854  goto retry;
13855  }
13856  }
13857  else if (argc >= 1) {
13858  long slen = RSTRING_LEN(str);
13859  if (slen < len) {
13860  argv[0] = LONG2NUM(len - slen);
13861  goto retry;
13862  }
13863  }
13864  return str;
13865 }
13866 
13868  int argc;
13869  VALUE *argv;
13870  VALUE argf;
13871 };
13872 
13873 static VALUE
13874 argf_forward_call(VALUE arg)
13875 {
13876  struct argf_call_arg *p = (struct argf_call_arg *)arg;
13877  argf_forward(p->argc, p->argv, p->argf);
13878  return Qnil;
13879 }
13880 
13881 static VALUE argf_getpartial(int argc, VALUE *argv, VALUE argf, VALUE opts,
13882  int nonblock);
13883 
13884 /*
13885  * call-seq:
13886  * ARGF.readpartial(maxlen) -> string
13887  * ARGF.readpartial(maxlen, outbuf) -> outbuf
13888  *
13889  * Reads at most _maxlen_ bytes from the ARGF stream.
13890  *
13891  * If the optional _outbuf_ argument is present,
13892  * it must reference a String, which will receive the data.
13893  * The _outbuf_ will contain only the received data after the method call
13894  * even if it is not empty at the beginning.
13895  *
13896  * It raises EOFError on end of ARGF stream.
13897  * Since ARGF stream is a concatenation of multiple files,
13898  * internally EOF is occur for each file.
13899  * ARGF.readpartial returns empty strings for EOFs except the last one and
13900  * raises EOFError for the last one.
13901  *
13902  */
13903 
13904 static VALUE
13905 argf_readpartial(int argc, VALUE *argv, VALUE argf)
13906 {
13907  return argf_getpartial(argc, argv, argf, Qnil, 0);
13908 }
13909 
13910 /*
13911  * call-seq:
13912  * ARGF.read_nonblock(maxlen[, options]) -> string
13913  * ARGF.read_nonblock(maxlen, outbuf[, options]) -> outbuf
13914  *
13915  * Reads at most _maxlen_ bytes from the ARGF stream in non-blocking mode.
13916  */
13917 
13918 static VALUE
13919 argf_read_nonblock(int argc, VALUE *argv, VALUE argf)
13920 {
13921  VALUE opts;
13922 
13923  rb_scan_args(argc, argv, "11:", NULL, NULL, &opts);
13924 
13925  if (!NIL_P(opts))
13926  argc--;
13927 
13928  return argf_getpartial(argc, argv, argf, opts, 1);
13929 }
13930 
13931 static VALUE
13932 argf_getpartial(int argc, VALUE *argv, VALUE argf, VALUE opts, int nonblock)
13933 {
13934  VALUE tmp, str, length;
13935  int no_exception;
13936 
13937  rb_scan_args(argc, argv, "11", &length, &str);
13938  if (!NIL_P(str)) {
13939  StringValue(str);
13940  argv[1] = str;
13941  }
13942  no_exception = no_exception_p(opts);
13943 
13944  if (!next_argv()) {
13945  if (!NIL_P(str)) {
13946  rb_str_resize(str, 0);
13947  }
13948  rb_eof_error();
13949  }
13950  if (ARGF_GENERIC_INPUT_P()) {
13951  VALUE (*const rescue_does_nothing)(VALUE, VALUE) = 0;
13952  struct argf_call_arg arg;
13953  arg.argc = argc;
13954  arg.argv = argv;
13955  arg.argf = argf;
13956  tmp = rb_rescue2(argf_forward_call, (VALUE)&arg,
13957  rescue_does_nothing, Qnil, rb_eEOFError, (VALUE)0);
13958  }
13959  else {
13960  tmp = io_getpartial(argc, argv, ARGF.current_file, no_exception, nonblock);
13961  }
13962  if (NIL_P(tmp)) {
13963  if (ARGF.next_p == -1) {
13964  return io_nonblock_eof(no_exception);
13965  }
13966  argf_close(argf);
13967  ARGF.next_p = 1;
13968  if (RARRAY_LEN(ARGF.argv) == 0) {
13969  return io_nonblock_eof(no_exception);
13970  }
13971  if (NIL_P(str))
13972  str = rb_str_new(NULL, 0);
13973  return str;
13974  }
13975  return tmp;
13976 }
13977 
13978 /*
13979  * call-seq:
13980  * ARGF.getc -> String or nil
13981  *
13982  * Reads the next character from ARGF and returns it as a String. Returns
13983  * +nil+ at the end of the stream.
13984  *
13985  * ARGF treats the files named on the command line as a single file created
13986  * by concatenating their contents. After returning the last character of the
13987  * first file, it returns the first character of the second file, and so on.
13988  *
13989  * For example:
13990  *
13991  * $ echo "foo" > file
13992  * $ ruby argf.rb file
13993  *
13994  * ARGF.getc #=> "f"
13995  * ARGF.getc #=> "o"
13996  * ARGF.getc #=> "o"
13997  * ARGF.getc #=> "\n"
13998  * ARGF.getc #=> nil
13999  * ARGF.getc #=> nil
14000  */
14001 static VALUE
14002 argf_getc(VALUE argf)
14003 {
14004  VALUE ch;
14005 
14006  retry:
14007  if (!next_argv()) return Qnil;
14008  if (ARGF_GENERIC_INPUT_P()) {
14009  ch = forward_current(rb_intern("getc"), 0, 0);
14010  }
14011  else {
14012  ch = rb_io_getc(ARGF.current_file);
14013  }
14014  if (NIL_P(ch) && ARGF.next_p != -1) {
14015  argf_close(argf);
14016  ARGF.next_p = 1;
14017  goto retry;
14018  }
14019 
14020  return ch;
14021 }
14022 
14023 /*
14024  * call-seq:
14025  * ARGF.getbyte -> Integer or nil
14026  *
14027  * Gets the next 8-bit byte (0..255) from ARGF. Returns +nil+ if called at
14028  * the end of the stream.
14029  *
14030  * For example:
14031  *
14032  * $ echo "foo" > file
14033  * $ ruby argf.rb file
14034  *
14035  * ARGF.getbyte #=> 102
14036  * ARGF.getbyte #=> 111
14037  * ARGF.getbyte #=> 111
14038  * ARGF.getbyte #=> 10
14039  * ARGF.getbyte #=> nil
14040  */
14041 static VALUE
14042 argf_getbyte(VALUE argf)
14043 {
14044  VALUE ch;
14045 
14046  retry:
14047  if (!next_argv()) return Qnil;
14048  if (!RB_TYPE_P(ARGF.current_file, T_FILE)) {
14049  ch = forward_current(rb_intern("getbyte"), 0, 0);
14050  }
14051  else {
14052  ch = rb_io_getbyte(ARGF.current_file);
14053  }
14054  if (NIL_P(ch) && ARGF.next_p != -1) {
14055  argf_close(argf);
14056  ARGF.next_p = 1;
14057  goto retry;
14058  }
14059 
14060  return ch;
14061 }
14062 
14063 /*
14064  * call-seq:
14065  * ARGF.readchar -> String or nil
14066  *
14067  * Reads the next character from ARGF and returns it as a String. Raises
14068  * an EOFError after the last character of the last file has been read.
14069  *
14070  * For example:
14071  *
14072  * $ echo "foo" > file
14073  * $ ruby argf.rb file
14074  *
14075  * ARGF.readchar #=> "f"
14076  * ARGF.readchar #=> "o"
14077  * ARGF.readchar #=> "o"
14078  * ARGF.readchar #=> "\n"
14079  * ARGF.readchar #=> end of file reached (EOFError)
14080  */
14081 static VALUE
14082 argf_readchar(VALUE argf)
14083 {
14084  VALUE ch;
14085 
14086  retry:
14087  if (!next_argv()) rb_eof_error();
14088  if (!RB_TYPE_P(ARGF.current_file, T_FILE)) {
14089  ch = forward_current(rb_intern("getc"), 0, 0);
14090  }
14091  else {
14092  ch = rb_io_getc(ARGF.current_file);
14093  }
14094  if (NIL_P(ch) && ARGF.next_p != -1) {
14095  argf_close(argf);
14096  ARGF.next_p = 1;
14097  goto retry;
14098  }
14099 
14100  return ch;
14101 }
14102 
14103 /*
14104  * call-seq:
14105  * ARGF.readbyte -> Integer
14106  *
14107  * Reads the next 8-bit byte from ARGF and returns it as an Integer. Raises
14108  * an EOFError after the last byte of the last file has been read.
14109  *
14110  * For example:
14111  *
14112  * $ echo "foo" > file
14113  * $ ruby argf.rb file
14114  *
14115  * ARGF.readbyte #=> 102
14116  * ARGF.readbyte #=> 111
14117  * ARGF.readbyte #=> 111
14118  * ARGF.readbyte #=> 10
14119  * ARGF.readbyte #=> end of file reached (EOFError)
14120  */
14121 static VALUE
14122 argf_readbyte(VALUE argf)
14123 {
14124  VALUE c;
14125 
14126  NEXT_ARGF_FORWARD(0, 0);
14127  c = argf_getbyte(argf);
14128  if (NIL_P(c)) {
14129  rb_eof_error();
14130  }
14131  return c;
14132 }
14133 
14134 #define FOREACH_ARGF() while (next_argv())
14135 
14136 static VALUE
14137 argf_block_call_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, argf))
14138 {
14139  const VALUE current = ARGF.current_file;
14140  rb_yield_values2(argc, argv);
14141  if (ARGF.init_p == -1 || current != ARGF.current_file) {
14143  }
14144  return Qnil;
14145 }
14146 
14147 #define ARGF_block_call(mid, argc, argv, func, argf) \
14148  rb_block_call_kw(ARGF.current_file, mid, argc, argv, \
14149  func, argf, rb_keyword_given_p())
14150 
14151 static void
14152 argf_block_call(ID mid, int argc, VALUE *argv, VALUE argf)
14153 {
14154  VALUE ret = ARGF_block_call(mid, argc, argv, argf_block_call_i, argf);
14155  if (!UNDEF_P(ret)) ARGF.next_p = 1;
14156 }
14157 
14158 static VALUE
14159 argf_block_call_line_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, argf))
14160 {
14161  if (!global_argf_p(argf)) {
14162  ARGF.last_lineno = ++ARGF.lineno;
14163  }
14164  return argf_block_call_i(i, argf, argc, argv, blockarg);
14165 }
14166 
14167 static void
14168 argf_block_call_line(ID mid, int argc, VALUE *argv, VALUE argf)
14169 {
14170  VALUE ret = ARGF_block_call(mid, argc, argv, argf_block_call_line_i, argf);
14171  if (!UNDEF_P(ret)) ARGF.next_p = 1;
14172 }
14173 
14174 /*
14175  * call-seq:
14176  * ARGF.each(sep=$/) {|line| block } -> ARGF
14177  * ARGF.each(sep=$/, limit) {|line| block } -> ARGF
14178  * ARGF.each(...) -> an_enumerator
14179  *
14180  * ARGF.each_line(sep=$/) {|line| block } -> ARGF
14181  * ARGF.each_line(sep=$/, limit) {|line| block } -> ARGF
14182  * ARGF.each_line(...) -> an_enumerator
14183  *
14184  * Returns an enumerator which iterates over each line (separated by _sep_,
14185  * which defaults to your platform's newline character) of each file in
14186  * +ARGV+. If a block is supplied, each line in turn will be yielded to the
14187  * block, otherwise an enumerator is returned.
14188  * The optional _limit_ argument is an Integer specifying the maximum
14189  * length of each line; longer lines will be split according to this limit.
14190  *
14191  * This method allows you to treat the files supplied on the command line as
14192  * a single file consisting of the concatenation of each named file. After
14193  * the last line of the first file has been returned, the first line of the
14194  * second file is returned. The ARGF.filename and ARGF.lineno methods can be
14195  * used to determine the filename of the current line and line number of the
14196  * whole input, respectively.
14197  *
14198  * For example, the following code prints out each line of each named file
14199  * prefixed with its line number, displaying the filename once per file:
14200  *
14201  * ARGF.each_line do |line|
14202  * puts ARGF.filename if ARGF.file.lineno == 1
14203  * puts "#{ARGF.file.lineno}: #{line}"
14204  * end
14205  *
14206  * While the following code prints only the first file's name at first, and
14207  * the contents with line number counted through all named files.
14208  *
14209  * ARGF.each_line do |line|
14210  * puts ARGF.filename if ARGF.lineno == 1
14211  * puts "#{ARGF.lineno}: #{line}"
14212  * end
14213  */
14214 static VALUE
14215 argf_each_line(int argc, VALUE *argv, VALUE argf)
14216 {
14217  RETURN_ENUMERATOR(argf, argc, argv);
14218  FOREACH_ARGF() {
14219  argf_block_call_line(rb_intern("each_line"), argc, argv, argf);
14220  }
14221  return argf;
14222 }
14223 
14224 /*
14225  * call-seq:
14226  * ARGF.each_byte {|byte| block } -> ARGF
14227  * ARGF.each_byte -> an_enumerator
14228  *
14229  * Iterates over each byte of each file in +ARGV+.
14230  * A byte is returned as an Integer in the range 0..255.
14231  *
14232  * This method allows you to treat the files supplied on the command line as
14233  * a single file consisting of the concatenation of each named file. After
14234  * the last byte of the first file has been returned, the first byte of the
14235  * second file is returned. The ARGF.filename method can be used to
14236  * determine the filename of the current byte.
14237  *
14238  * If no block is given, an enumerator is returned instead.
14239  *
14240  * For example:
14241  *
14242  * ARGF.bytes.to_a #=> [35, 32, ... 95, 10]
14243  *
14244  */
14245 static VALUE
14246 argf_each_byte(VALUE argf)
14247 {
14248  RETURN_ENUMERATOR(argf, 0, 0);
14249  FOREACH_ARGF() {
14250  argf_block_call(rb_intern("each_byte"), 0, 0, argf);
14251  }
14252  return argf;
14253 }
14254 
14255 /*
14256  * call-seq:
14257  * ARGF.each_char {|char| block } -> ARGF
14258  * ARGF.each_char -> an_enumerator
14259  *
14260  * Iterates over each character of each file in ARGF.
14261  *
14262  * This method allows you to treat the files supplied on the command line as
14263  * a single file consisting of the concatenation of each named file. After
14264  * the last character of the first file has been returned, the first
14265  * character of the second file is returned. The ARGF.filename method can
14266  * be used to determine the name of the file in which the current character
14267  * appears.
14268  *
14269  * If no block is given, an enumerator is returned instead.
14270  */
14271 static VALUE
14272 argf_each_char(VALUE argf)
14273 {
14274  RETURN_ENUMERATOR(argf, 0, 0);
14275  FOREACH_ARGF() {
14276  argf_block_call(rb_intern("each_char"), 0, 0, argf);
14277  }
14278  return argf;
14279 }
14280 
14281 /*
14282  * call-seq:
14283  * ARGF.each_codepoint {|codepoint| block } -> ARGF
14284  * ARGF.each_codepoint -> an_enumerator
14285  *
14286  * Iterates over each codepoint of each file in ARGF.
14287  *
14288  * This method allows you to treat the files supplied on the command line as
14289  * a single file consisting of the concatenation of each named file. After
14290  * the last codepoint of the first file has been returned, the first
14291  * codepoint of the second file is returned. The ARGF.filename method can
14292  * be used to determine the name of the file in which the current codepoint
14293  * appears.
14294  *
14295  * If no block is given, an enumerator is returned instead.
14296  */
14297 static VALUE
14298 argf_each_codepoint(VALUE argf)
14299 {
14300  RETURN_ENUMERATOR(argf, 0, 0);
14301  FOREACH_ARGF() {
14302  argf_block_call(rb_intern("each_codepoint"), 0, 0, argf);
14303  }
14304  return argf;
14305 }
14306 
14307 /*
14308  * call-seq:
14309  * ARGF.filename -> String
14310  * ARGF.path -> String
14311  *
14312  * Returns the current filename. "-" is returned when the current file is
14313  * STDIN.
14314  *
14315  * For example:
14316  *
14317  * $ echo "foo" > foo
14318  * $ echo "bar" > bar
14319  * $ echo "glark" > glark
14320  *
14321  * $ ruby argf.rb foo bar glark
14322  *
14323  * ARGF.filename #=> "foo"
14324  * ARGF.read(5) #=> "foo\nb"
14325  * ARGF.filename #=> "bar"
14326  * ARGF.skip
14327  * ARGF.filename #=> "glark"
14328  */
14329 static VALUE
14330 argf_filename(VALUE argf)
14331 {
14332  next_argv();
14333  return ARGF.filename;
14334 }
14335 
14336 static VALUE
14337 argf_filename_getter(ID id, VALUE *var)
14338 {
14339  return argf_filename(*var);
14340 }
14341 
14342 /*
14343  * call-seq:
14344  * ARGF.file -> IO or File object
14345  *
14346  * Returns the current file as an IO or File object.
14347  * <code>$stdin</code> is returned when the current file is STDIN.
14348  *
14349  * For example:
14350  *
14351  * $ echo "foo" > foo
14352  * $ echo "bar" > bar
14353  *
14354  * $ ruby argf.rb foo bar
14355  *
14356  * ARGF.file #=> #<File:foo>
14357  * ARGF.read(5) #=> "foo\nb"
14358  * ARGF.file #=> #<File:bar>
14359  */
14360 static VALUE
14361 argf_file(VALUE argf)
14362 {
14363  next_argv();
14364  return ARGF.current_file;
14365 }
14366 
14367 /*
14368  * call-seq:
14369  * ARGF.binmode -> ARGF
14370  *
14371  * Puts ARGF into binary mode. Once a stream is in binary mode, it cannot
14372  * be reset to non-binary mode. This option has the following effects:
14373  *
14374  * * Newline conversion is disabled.
14375  * * Encoding conversion is disabled.
14376  * * Content is treated as ASCII-8BIT.
14377  */
14378 static VALUE
14379 argf_binmode_m(VALUE argf)
14380 {
14381  ARGF.binmode = 1;
14382  next_argv();
14383  ARGF_FORWARD(0, 0);
14384  rb_io_ascii8bit_binmode(ARGF.current_file);
14385  return argf;
14386 }
14387 
14388 /*
14389  * call-seq:
14390  * ARGF.binmode? -> true or false
14391  *
14392  * Returns true if ARGF is being read in binary mode; false otherwise.
14393  * To enable binary mode use ARGF.binmode.
14394  *
14395  * For example:
14396  *
14397  * ARGF.binmode? #=> false
14398  * ARGF.binmode
14399  * ARGF.binmode? #=> true
14400  */
14401 static VALUE
14402 argf_binmode_p(VALUE argf)
14403 {
14404  return RBOOL(ARGF.binmode);
14405 }
14406 
14407 /*
14408  * call-seq:
14409  * ARGF.skip -> ARGF
14410  *
14411  * Sets the current file to the next file in ARGV. If there aren't any more
14412  * files it has no effect.
14413  *
14414  * For example:
14415  *
14416  * $ ruby argf.rb foo bar
14417  * ARGF.filename #=> "foo"
14418  * ARGF.skip
14419  * ARGF.filename #=> "bar"
14420  */
14421 static VALUE
14422 argf_skip(VALUE argf)
14423 {
14424  if (ARGF.init_p && ARGF.next_p == 0) {
14425  argf_close(argf);
14426  ARGF.next_p = 1;
14427  }
14428  return argf;
14429 }
14430 
14431 /*
14432  * call-seq:
14433  * ARGF.close -> ARGF
14434  *
14435  * Closes the current file and skips to the next file in ARGV. If there are
14436  * no more files to open, just closes the current file. STDIN will not be
14437  * closed.
14438  *
14439  * For example:
14440  *
14441  * $ ruby argf.rb foo bar
14442  *
14443  * ARGF.filename #=> "foo"
14444  * ARGF.close
14445  * ARGF.filename #=> "bar"
14446  * ARGF.close
14447  */
14448 static VALUE
14449 argf_close_m(VALUE argf)
14450 {
14451  next_argv();
14452  argf_close(argf);
14453  if (ARGF.next_p != -1) {
14454  ARGF.next_p = 1;
14455  }
14456  ARGF.lineno = 0;
14457  return argf;
14458 }
14459 
14460 /*
14461  * call-seq:
14462  * ARGF.closed? -> true or false
14463  *
14464  * Returns _true_ if the current file has been closed; _false_ otherwise. Use
14465  * ARGF.close to actually close the current file.
14466  */
14467 static VALUE
14468 argf_closed(VALUE argf)
14469 {
14470  next_argv();
14471  ARGF_FORWARD(0, 0);
14472  return rb_io_closed_p(ARGF.current_file);
14473 }
14474 
14475 /*
14476  * call-seq:
14477  * ARGF.to_s -> String
14478  *
14479  * Returns "ARGF".
14480  */
14481 static VALUE
14482 argf_to_s(VALUE argf)
14483 {
14484  return rb_str_new2("ARGF");
14485 }
14486 
14487 /*
14488  * call-seq:
14489  * ARGF.inplace_mode -> String
14490  *
14491  * Returns the file extension appended to the names of backup copies of
14492  * modified files under in-place edit mode. This value can be set using
14493  * ARGF.inplace_mode= or passing the +-i+ switch to the Ruby binary.
14494  */
14495 static VALUE
14496 argf_inplace_mode_get(VALUE argf)
14497 {
14498  if (!ARGF.inplace) return Qnil;
14499  if (NIL_P(ARGF.inplace)) return rb_str_new(0, 0);
14500  return rb_str_dup(ARGF.inplace);
14501 }
14502 
14503 static VALUE
14504 opt_i_get(ID id, VALUE *var)
14505 {
14506  return argf_inplace_mode_get(*var);
14507 }
14508 
14509 /*
14510  * call-seq:
14511  * ARGF.inplace_mode = ext -> ARGF
14512  *
14513  * Sets the filename extension for in-place editing mode to the given String.
14514  * The backup copy of each file being edited has this value appended to its
14515  * filename.
14516  *
14517  * For example:
14518  *
14519  * $ ruby argf.rb file.txt
14520  *
14521  * ARGF.inplace_mode = '.bak'
14522  * ARGF.each_line do |line|
14523  * print line.sub("foo","bar")
14524  * end
14525  *
14526  * First, _file.txt.bak_ is created as a backup copy of _file.txt_.
14527  * Then, each line of _file.txt_ has the first occurrence of "foo" replaced with
14528  * "bar".
14529  */
14530 static VALUE
14531 argf_inplace_mode_set(VALUE argf, VALUE val)
14532 {
14533  if (!RTEST(val)) {
14534  ARGF.inplace = Qfalse;
14535  }
14536  else if (StringValueCStr(val), !RSTRING_LEN(val)) {
14537  ARGF.inplace = Qnil;
14538  }
14539  else {
14540  ARGF.inplace = rb_str_new_frozen(val);
14541  }
14542  return argf;
14543 }
14544 
14545 static void
14546 opt_i_set(VALUE val, ID id, VALUE *var)
14547 {
14548  argf_inplace_mode_set(*var, val);
14549 }
14550 
14551 void
14552 ruby_set_inplace_mode(const char *suffix)
14553 {
14554  ARGF.inplace = !suffix ? Qfalse : !*suffix ? Qnil : rb_str_new(suffix, strlen(suffix));
14555 }
14556 
14557 /*
14558  * call-seq:
14559  * ARGF.argv -> ARGV
14560  *
14561  * Returns the +ARGV+ array, which contains the arguments passed to your
14562  * script, one per element.
14563  *
14564  * For example:
14565  *
14566  * $ ruby argf.rb -v glark.txt
14567  *
14568  * ARGF.argv #=> ["-v", "glark.txt"]
14569  *
14570  */
14571 static VALUE
14572 argf_argv(VALUE argf)
14573 {
14574  return ARGF.argv;
14575 }
14576 
14577 static VALUE
14578 argf_argv_getter(ID id, VALUE *var)
14579 {
14580  return argf_argv(*var);
14581 }
14582 
14583 VALUE
14585 {
14586  return ARGF.argv;
14587 }
14588 
14589 /*
14590  * call-seq:
14591  * ARGF.to_write_io -> io
14592  *
14593  * Returns IO instance tied to _ARGF_ for writing if inplace mode is
14594  * enabled.
14595  */
14596 static VALUE
14597 argf_write_io(VALUE argf)
14598 {
14599  if (!RTEST(ARGF.current_file)) {
14600  rb_raise(rb_eIOError, "not opened for writing");
14601  }
14602  return GetWriteIO(ARGF.current_file);
14603 }
14604 
14605 /*
14606  * call-seq:
14607  * ARGF.write(*objects) -> integer
14608  *
14609  * Writes each of the given +objects+ if inplace mode.
14610  */
14611 static VALUE
14612 argf_write(int argc, VALUE *argv, VALUE argf)
14613 {
14614  return rb_io_writev(argf_write_io(argf), argc, argv);
14615 }
14616 
14617 void
14618 rb_readwrite_sys_fail(enum rb_io_wait_readwrite waiting, const char *mesg)
14619 {
14620  rb_readwrite_syserr_fail(waiting, errno, mesg);
14621 }
14622 
14623 void
14624 rb_readwrite_syserr_fail(enum rb_io_wait_readwrite waiting, int n, const char *mesg)
14625 {
14626  VALUE arg, c = Qnil;
14627  arg = mesg ? rb_str_new2(mesg) : Qnil;
14628  switch (waiting) {
14629  case RB_IO_WAIT_WRITABLE:
14630  switch (n) {
14631  case EAGAIN:
14632  c = rb_eEAGAINWaitWritable;
14633  break;
14634 #if EAGAIN != EWOULDBLOCK
14635  case EWOULDBLOCK:
14636  c = rb_eEWOULDBLOCKWaitWritable;
14637  break;
14638 #endif
14639  case EINPROGRESS:
14640  c = rb_eEINPROGRESSWaitWritable;
14641  break;
14642  default:
14644  }
14645  break;
14646  case RB_IO_WAIT_READABLE:
14647  switch (n) {
14648  case EAGAIN:
14649  c = rb_eEAGAINWaitReadable;
14650  break;
14651 #if EAGAIN != EWOULDBLOCK
14652  case EWOULDBLOCK:
14653  c = rb_eEWOULDBLOCKWaitReadable;
14654  break;
14655 #endif
14656  case EINPROGRESS:
14657  c = rb_eEINPROGRESSWaitReadable;
14658  break;
14659  default:
14661  }
14662  break;
14663  default:
14664  rb_bug("invalid read/write type passed to rb_readwrite_sys_fail: %d", waiting);
14665  }
14666  rb_exc_raise(rb_class_new_instance(1, &arg, c));
14667 }
14668 
14669 static VALUE
14670 get_LAST_READ_LINE(ID _x, VALUE *_y)
14671 {
14672  return rb_lastline_get();
14673 }
14674 
14675 static void
14676 set_LAST_READ_LINE(VALUE val, ID _x, VALUE *_y)
14677 {
14678  rb_lastline_set(val);
14679 }
14680 
14681 /*
14682  * Document-class: IOError
14683  *
14684  * Raised when an IO operation fails.
14685  *
14686  * File.open("/etc/hosts") {|f| f << "example"}
14687  * #=> IOError: not opened for writing
14688  *
14689  * File.open("/etc/hosts") {|f| f.close; f.read }
14690  * #=> IOError: closed stream
14691  *
14692  * Note that some IO failures raise <code>SystemCallError</code>s
14693  * and these are not subclasses of IOError:
14694  *
14695  * File.open("does/not/exist")
14696  * #=> Errno::ENOENT: No such file or directory - does/not/exist
14697  */
14698 
14699 /*
14700  * Document-class: EOFError
14701  *
14702  * Raised by some IO operations when reaching the end of file. Many IO
14703  * methods exist in two forms,
14704  *
14705  * one that returns +nil+ when the end of file is reached, the other
14706  * raises EOFError.
14707  *
14708  * EOFError is a subclass of IOError.
14709  *
14710  * file = File.open("/etc/hosts")
14711  * file.read
14712  * file.gets #=> nil
14713  * file.readline #=> EOFError: end of file reached
14714  * file.close
14715  */
14716 
14717 /*
14718  * Document-class: ARGF
14719  *
14720  * == \ARGF and +ARGV+
14721  *
14722  * The \ARGF object works with the array at global variable +ARGV+
14723  * to make <tt>$stdin</tt> and file streams available in the Ruby program:
14724  *
14725  * - **ARGV** may be thought of as the <b>argument vector</b> array.
14726  *
14727  * Initially, it contains the command-line arguments and options
14728  * that are passed to the Ruby program;
14729  * the program can modify that array as it likes.
14730  *
14731  * - **ARGF** may be thought of as the <b>argument files</b> object.
14732  *
14733  * It can access file streams and/or the <tt>$stdin</tt> stream,
14734  * based on what it finds in +ARGV+.
14735  * This provides a convenient way for the command line
14736  * to specify streams for a Ruby program to read.
14737  *
14738  * == Reading
14739  *
14740  * \ARGF may read from _source_ streams,
14741  * which at any particular time are determined by the content of +ARGV+.
14742  *
14743  * === Simplest Case
14744  *
14745  * When the <i>very first</i> \ARGF read occurs with an empty +ARGV+ (<tt>[]</tt>),
14746  * the source is <tt>$stdin</tt>:
14747  *
14748  * - \File +t.rb+:
14749  *
14750  * p ['ARGV', ARGV]
14751  * p ['ARGF.read', ARGF.read]
14752  *
14753  * - Commands and outputs
14754  * (see below for the content of files +foo.txt+ and +bar.txt+):
14755  *
14756  * $ echo "Open the pod bay doors, Hal." | ruby t.rb
14757  * ["ARGV", []]
14758  * ["ARGF.read", "Open the pod bay doors, Hal.\n"]
14759  *
14760  * $ cat foo.txt bar.txt | ruby t.rb
14761  * ["ARGV", []]
14762  * ["ARGF.read", "Foo 0\nFoo 1\nBar 0\nBar 1\nBar 2\nBar 3\n"]
14763  *
14764  * === About the Examples
14765  *
14766  * Many examples here assume the existence of files +foo.txt+ and +bar.txt+:
14767  *
14768  * $ cat foo.txt
14769  * Foo 0
14770  * Foo 1
14771  * $ cat bar.txt
14772  * Bar 0
14773  * Bar 1
14774  * Bar 2
14775  * Bar 3
14776  *
14777  * === Sources in +ARGV+
14778  *
14779  * For any \ARGF read _except_ the {simplest case}[rdoc-ref:ARGF@Simplest+Case]
14780  * (that is, _except_ for the <i>very first</i> \ARGF read with an empty +ARGV+),
14781  * the sources are found in +ARGV+.
14782  *
14783  * \ARGF assumes that each element in array +ARGV+ is a potential source,
14784  * and is one of:
14785  *
14786  * - The string path to a file that may be opened as a stream.
14787  * - The character <tt>'-'</tt>, meaning stream <tt>$stdin</tt>.
14788  *
14789  * Each element that is _not_ one of these
14790  * should be removed from +ARGV+ before \ARGF accesses that source.
14791  *
14792  * In the following example:
14793  *
14794  * - Filepaths +foo.txt+ and +bar.txt+ may be retained as potential sources.
14795  * - Options <tt>--xyzzy</tt> and <tt>--mojo</tt> should be removed.
14796  *
14797  * Example:
14798  *
14799  * - \File +t.rb+:
14800  *
14801  * # Print arguments (and options, if any) found on command line.
14802  * p ['ARGV', ARGV]
14803  *
14804  * - Command and output:
14805  *
14806  * $ ruby t.rb --xyzzy --mojo foo.txt bar.txt
14807  * ["ARGV", ["--xyzzy", "--mojo", "foo.txt", "bar.txt"]]
14808  *
14809  * \ARGF's stream access considers the elements of +ARGV+, left to right:
14810  *
14811  * - \File +t.rb+:
14812  *
14813  * p "ARGV: #{ARGV}"
14814  * p "Line: #{ARGF.read}" # Read everything from all specified streams.
14815  *
14816  * - Command and output:
14817  *
14818  * $ ruby t.rb foo.txt bar.txt
14819  * "ARGV: [\"foo.txt\", \"bar.txt\"]"
14820  * "Read: Foo 0\nFoo 1\nBar 0\nBar 1\nBar 2\nBar 3\n"
14821  *
14822  * Because the value at +ARGV+ is an ordinary array,
14823  * you can manipulate it to control which sources \ARGF considers:
14824  *
14825  * - If you remove an element from +ARGV+, \ARGF will not consider the corresponding source.
14826  * - If you add an element to +ARGV+, \ARGF will consider the corresponding source.
14827  *
14828  * Each element in +ARGV+ is removed when its corresponding source is accessed;
14829  * when all sources have been accessed, the array is empty:
14830  *
14831  * - \File +t.rb+:
14832  *
14833  * until ARGV.empty? && ARGF.eof?
14834  * p "ARGV: #{ARGV}"
14835  * p "Line: #{ARGF.readline}" # Read each line from each specified stream.
14836  * end
14837  *
14838  * - Command and output:
14839  *
14840  * $ ruby t.rb foo.txt bar.txt
14841  * "ARGV: [\"foo.txt\", \"bar.txt\"]"
14842  * "Line: Foo 0\n"
14843  * "ARGV: [\"bar.txt\"]"
14844  * "Line: Foo 1\n"
14845  * "ARGV: [\"bar.txt\"]"
14846  * "Line: Bar 0\n"
14847  * "ARGV: []"
14848  * "Line: Bar 1\n"
14849  * "ARGV: []"
14850  * "Line: Bar 2\n"
14851  * "ARGV: []"
14852  * "Line: Bar 3\n"
14853  *
14854  * ==== Filepaths in +ARGV+
14855  *
14856  * The +ARGV+ array may contain filepaths the specify sources for \ARGF reading.
14857  *
14858  * This program prints what it reads from files at the paths specified
14859  * on the command line:
14860  *
14861  * - \File +t.rb+:
14862  *
14863  * p ['ARGV', ARGV]
14864  * # Read and print all content from the specified sources.
14865  * p ['ARGF.read', ARGF.read]
14866  *
14867  * - Command and output:
14868  *
14869  * $ ruby t.rb foo.txt bar.txt
14870  * ["ARGV", [foo.txt, bar.txt]
14871  * ["ARGF.read", "Foo 0\nFoo 1\nBar 0\nBar 1\nBar 2\nBar 3\n"]
14872  *
14873  * ==== Specifying <tt>$stdin</tt> in +ARGV+
14874  *
14875  * To specify stream <tt>$stdin</tt> in +ARGV+, us the character <tt>'-'</tt>:
14876  *
14877  * - \File +t.rb+:
14878  *
14879  * p ['ARGV', ARGV]
14880  * p ['ARGF.read', ARGF.read]
14881  *
14882  * - Command and output:
14883  *
14884  * $ echo "Open the pod bay doors, Hal." | ruby t.rb -
14885  * ["ARGV", ["-"]]
14886  * ["ARGF.read", "Open the pod bay doors, Hal.\n"]
14887  *
14888  * When no character <tt>'-'</tt> is given, stream <tt>$stdin</tt> is ignored
14889  * (exception:
14890  * see {Specifying $stdin in ARGV}[rdoc-ref:ARGF@Specifying+-24stdin+in+ARGV]):
14891  *
14892  * - Command and output:
14893  *
14894  * $ echo "Open the pod bay doors, Hal." | ruby t.rb foo.txt bar.txt
14895  * "ARGV: [\"foo.txt\", \"bar.txt\"]"
14896  * "Read: Foo 0\nFoo 1\nBar 0\nBar 1\nBar 2\nBar 3\n"
14897  *
14898  * ==== Mixtures and Repetitions in +ARGV+
14899  *
14900  * For an \ARGF reader, +ARGV+ may contain any mixture of filepaths
14901  * and character <tt>'-'</tt>, including repetitions.
14902  *
14903  * ==== Modifications to +ARGV+
14904  *
14905  * The running Ruby program may make any modifications to the +ARGV+ array;
14906  * the current value of +ARGV+ affects \ARGF reading.
14907  *
14908  * ==== Empty +ARGV+
14909  *
14910  * For an empty +ARGV+, an \ARGF read method either returns +nil+
14911  * or raises an exception, depending on the specific method.
14912  *
14913  * === More Read Methods
14914  *
14915  * As seen above, method ARGF#read reads the content of all sources
14916  * into a single string.
14917  * Other \ARGF methods provide other ways to access that content;
14918  * these include:
14919  *
14920  * - Byte access: #each_byte, #getbyte, #readbyte.
14921  * - Character access: #each_char, #getc, #readchar.
14922  * - Codepoint access: #each_codepoint.
14923  * - Line access: #each_line, #gets, #readline, #readlines.
14924  * - Source access: #read, #read_nonblock, #readpartial.
14925  *
14926  * === About \Enumerable
14927  *
14928  * \ARGF includes module Enumerable.
14929  * Virtually all methods in \Enumerable call method <tt>#each</tt> in the including class.
14930  *
14931  * <b>Note well</b>: In \ARGF, method #each returns data from the _sources_,
14932  * _not_ from +ARGV+;
14933  * therefore, for example, <tt>ARGF#entries</tt> returns an array of lines from the sources,
14934  * not an array of the strings from +ARGV+:
14935  *
14936  * - \File +t.rb+:
14937  *
14938  * p ['ARGV', ARGV]
14939  * p ['ARGF.entries', ARGF.entries]
14940  *
14941  * - Command and output:
14942  *
14943  * $ ruby t.rb foo.txt bar.txt
14944  * ["ARGV", ["foo.txt", "bar.txt"]]
14945  * ["ARGF.entries", ["Foo 0\n", "Foo 1\n", "Bar 0\n", "Bar 1\n", "Bar 2\n", "Bar 3\n"]]
14946  *
14947  * == Writing
14948  *
14949  * If <i>inplace mode</i> is in effect,
14950  * \ARGF may write to target streams,
14951  * which at any particular time are determined by the content of ARGV.
14952  *
14953  * Methods about inplace mode:
14954  *
14955  * - #inplace_mode
14956  * - #inplace_mode=
14957  * - #to_write_io
14958  *
14959  * Methods for writing:
14960  *
14961  * - #print
14962  * - #printf
14963  * - #putc
14964  * - #puts
14965  * - #write
14966  *
14967  */
14968 
14969 /*
14970  * An instance of class \IO (commonly called a _stream_)
14971  * represents an input/output stream in the underlying operating system.
14972  * \Class \IO is the basis for input and output in Ruby.
14973  *
14974  * \Class File is the only class in the Ruby core that is a subclass of \IO.
14975  * Some classes in the Ruby standard library are also subclasses of \IO;
14976  * these include TCPSocket and UDPSocket.
14977  *
14978  * The global constant ARGF (also accessible as <tt>$<</tt>)
14979  * provides an IO-like stream that allows access to all file paths
14980  * found in ARGV (or found in STDIN if ARGV is empty).
14981  * ARGF is not itself a subclass of \IO.
14982  *
14983  * \Class StringIO provides an IO-like stream that handles a String.
14984  * StringIO is not itself a subclass of \IO.
14985  *
14986  * Important objects based on \IO include:
14987  *
14988  * - $stdin.
14989  * - $stdout.
14990  * - $stderr.
14991  * - Instances of class File.
14992  *
14993  * An instance of \IO may be created using:
14994  *
14995  * - IO.new: returns a new \IO object for the given integer file descriptor.
14996  * - IO.open: passes a new \IO object to the given block.
14997  * - IO.popen: returns a new \IO object that is connected to the $stdin and $stdout
14998  * of a newly-launched subprocess.
14999  * - Kernel#open: Returns a new \IO object connected to a given source:
15000  * stream, file, or subprocess.
15001  *
15002  * Like a File stream, an \IO stream has:
15003  *
15004  * - A read/write mode, which may be read-only, write-only, or read/write;
15005  * see {Read/Write Mode}[rdoc-ref:File@Read-2FWrite+Mode].
15006  * - A data mode, which may be text-only or binary;
15007  * see {Data Mode}[rdoc-ref:File@Data+Mode].
15008  * - Internal and external encodings;
15009  * see {Encodings}[rdoc-ref:File@Encodings].
15010  *
15011  * And like other \IO streams, it has:
15012  *
15013  * - A position, which determines where in the stream the next
15014  * read or write is to occur;
15015  * see {Position}[rdoc-ref:IO@Position].
15016  * - A line number, which is a special, line-oriented, "position"
15017  * (different from the position mentioned above);
15018  * see {Line Number}[rdoc-ref:IO@Line+Number].
15019  *
15020  * == Extension <tt>io/console</tt>
15021  *
15022  * Extension <tt>io/console</tt> provides numerous methods
15023  * for interacting with the console;
15024  * requiring it adds numerous methods to class \IO.
15025  *
15026  * == Example Files
15027  *
15028  * Many examples here use these variables:
15029  *
15030  * :include: doc/examples/files.rdoc
15031  *
15032  * == Open Options
15033  *
15034  * A number of \IO methods accept optional keyword arguments
15035  * that determine how a new stream is to be opened:
15036  *
15037  * - +:mode+: Stream mode.
15038  * - +:flags+: Integer file open flags;
15039  * If +mode+ is also given, the two are bitwise-ORed.
15040  * - +:external_encoding+: External encoding for the stream.
15041  * - +:internal_encoding+: Internal encoding for the stream.
15042  * <tt>'-'</tt> is a synonym for the default internal encoding.
15043  * If the value is +nil+ no conversion occurs.
15044  * - +:encoding+: Specifies external and internal encodings as <tt>'extern:intern'</tt>.
15045  * - +:textmode+: If a truthy value, specifies the mode as text-only, binary otherwise.
15046  * - +:binmode+: If a truthy value, specifies the mode as binary, text-only otherwise.
15047  * - +:autoclose+: If a truthy value, specifies that the +fd+ will close
15048  * when the stream closes; otherwise it remains open.
15049  * - +:path:+ If a string value is provided, it is used in #inspect and is available as
15050  * #path method.
15051  *
15052  * Also available are the options offered in String#encode,
15053  * which may control conversion between external and internal encoding.
15054  *
15055  * == Basic \IO
15056  *
15057  * You can perform basic stream \IO with these methods,
15058  * which typically operate on multi-byte strings:
15059  *
15060  * - IO#read: Reads and returns some or all of the remaining bytes from the stream.
15061  * - IO#write: Writes zero or more strings to the stream;
15062  * each given object that is not already a string is converted via +to_s+.
15063  *
15064  * === Position
15065  *
15066  * An \IO stream has a nonnegative integer _position_,
15067  * which is the byte offset at which the next read or write is to occur.
15068  * A new stream has position zero (and line number zero);
15069  * method +rewind+ resets the position (and line number) to zero.
15070  *
15071  * The relevant methods:
15072  *
15073  * - IO#tell (aliased as +#pos+): Returns the current position (in bytes) in the stream.
15074  * - IO#pos=: Sets the position of the stream to a given integer +new_position+ (in bytes).
15075  * - IO#seek: Sets the position of the stream to a given integer +offset+ (in bytes),
15076  * relative to a given position +whence+
15077  * (indicating the beginning, end, or current position).
15078  * - IO#rewind: Positions the stream at the beginning (also resetting the line number).
15079  *
15080  * === Open and Closed Streams
15081  *
15082  * A new \IO stream may be open for reading, open for writing, or both.
15083  *
15084  * A stream is automatically closed when claimed by the garbage collector.
15085  *
15086  * Attempted reading or writing on a closed stream raises an exception.
15087  *
15088  * The relevant methods:
15089  *
15090  * - IO#close: Closes the stream for both reading and writing.
15091  * - IO#close_read: Closes the stream for reading.
15092  * - IO#close_write: Closes the stream for writing.
15093  * - IO#closed?: Returns whether the stream is closed.
15094  *
15095  * === End-of-Stream
15096  *
15097  * You can query whether a stream is positioned at its end:
15098  *
15099  * - IO#eof? (also aliased as +#eof+): Returns whether the stream is at end-of-stream.
15100  *
15101  * You can reposition to end-of-stream by using method IO#seek:
15102  *
15103  * f = File.new('t.txt')
15104  * f.eof? # => false
15105  * f.seek(0, :END)
15106  * f.eof? # => true
15107  * f.close
15108  *
15109  * Or by reading all stream content (which is slower than using IO#seek):
15110  *
15111  * f.rewind
15112  * f.eof? # => false
15113  * f.read # => "First line\nSecond line\n\nFourth line\nFifth line\n"
15114  * f.eof? # => true
15115  *
15116  * == Line \IO
15117  *
15118  * \Class \IO supports line-oriented
15119  * {input}[rdoc-ref:IO@Line+Input] and {output}[rdoc-ref:IO@Line+Output]
15120  *
15121  * === Line Input
15122  *
15123  * \Class \IO supports line-oriented input for
15124  * {files}[rdoc-ref:IO@File+Line+Input] and {IO streams}[rdoc-ref:IO@Stream+Line+Input]
15125  *
15126  * ==== \File Line Input
15127  *
15128  * You can read lines from a file using these methods:
15129  *
15130  * - IO.foreach: Reads each line and passes it to the given block.
15131  * - IO.readlines: Reads and returns all lines in an array.
15132  *
15133  * For each of these methods:
15134  *
15135  * - You can specify {open options}[rdoc-ref:IO@Open+Options].
15136  * - Line parsing depends on the effective <i>line separator</i>;
15137  * see {Line Separator}[rdoc-ref:IO@Line+Separator].
15138  * - The length of each returned line depends on the effective <i>line limit</i>;
15139  * see {Line Limit}[rdoc-ref:IO@Line+Limit].
15140  *
15141  * ==== Stream Line Input
15142  *
15143  * You can read lines from an \IO stream using these methods:
15144  *
15145  * - IO#each_line: Reads each remaining line, passing it to the given block.
15146  * - IO#gets: Returns the next line.
15147  * - IO#readline: Like #gets, but raises an exception at end-of-stream.
15148  * - IO#readlines: Returns all remaining lines in an array.
15149  *
15150  * For each of these methods:
15151  *
15152  * - Reading may begin mid-line,
15153  * depending on the stream's _position_;
15154  * see {Position}[rdoc-ref:IO@Position].
15155  * - Line parsing depends on the effective <i>line separator</i>;
15156  * see {Line Separator}[rdoc-ref:IO@Line+Separator].
15157  * - The length of each returned line depends on the effective <i>line limit</i>;
15158  * see {Line Limit}[rdoc-ref:IO@Line+Limit].
15159  *
15160  * ===== Line Separator
15161  *
15162  * Each of the {line input methods}[rdoc-ref:IO@Line+Input] uses a <i>line separator</i>:
15163  * the string that determines what is considered a line;
15164  * it is sometimes called the <i>input record separator</i>.
15165  *
15166  * The default line separator is taken from global variable <tt>$/</tt>,
15167  * whose initial value is <tt>"\n"</tt>.
15168  *
15169  * Generally, the line to be read next is all data
15170  * from the current {position}[rdoc-ref:IO@Position]
15171  * to the next line separator
15172  * (but see {Special Line Separator Values}[rdoc-ref:IO@Special+Line+Separator+Values]):
15173  *
15174  * f = File.new('t.txt')
15175  * # Method gets with no sep argument returns the next line, according to $/.
15176  * f.gets # => "First line\n"
15177  * f.gets # => "Second line\n"
15178  * f.gets # => "\n"
15179  * f.gets # => "Fourth line\n"
15180  * f.gets # => "Fifth line\n"
15181  * f.close
15182  *
15183  * You can use a different line separator by passing argument +sep+:
15184  *
15185  * f = File.new('t.txt')
15186  * f.gets('l') # => "First l"
15187  * f.gets('li') # => "ine\nSecond li"
15188  * f.gets('lin') # => "ne\n\nFourth lin"
15189  * f.gets # => "e\n"
15190  * f.close
15191  *
15192  * Or by setting global variable <tt>$/</tt>:
15193  *
15194  * f = File.new('t.txt')
15195  * $/ = 'l'
15196  * f.gets # => "First l"
15197  * f.gets # => "ine\nSecond l"
15198  * f.gets # => "ine\n\nFourth l"
15199  * f.close
15200  *
15201  * ===== Special Line Separator Values
15202  *
15203  * Each of the {line input methods}[rdoc-ref:IO@Line+Input]
15204  * accepts two special values for parameter +sep+:
15205  *
15206  * - +nil+: The entire stream is to be read ("slurped") into a single string:
15207  *
15208  * f = File.new('t.txt')
15209  * f.gets(nil) # => "First line\nSecond line\n\nFourth line\nFifth line\n"
15210  * f.close
15211  *
15212  * - <tt>''</tt> (the empty string): The next "paragraph" is to be read
15213  * (paragraphs being separated by two consecutive line separators):
15214  *
15215  * f = File.new('t.txt')
15216  * f.gets('') # => "First line\nSecond line\n\n"
15217  * f.gets('') # => "Fourth line\nFifth line\n"
15218  * f.close
15219  *
15220  * ===== Line Limit
15221  *
15222  * Each of the {line input methods}[rdoc-ref:IO@Line+Input]
15223  * uses an integer <i>line limit</i>,
15224  * which restricts the number of bytes that may be returned.
15225  * (A multi-byte character will not be split, and so a returned line may be slightly longer
15226  * than the limit).
15227  *
15228  * The default limit value is <tt>-1</tt>;
15229  * any negative limit value means that there is no limit.
15230  *
15231  * If there is no limit, the line is determined only by +sep+.
15232  *
15233  * # Text with 1-byte characters.
15234  * File.open('t.txt') {|f| f.gets(1) } # => "F"
15235  * File.open('t.txt') {|f| f.gets(2) } # => "Fi"
15236  * File.open('t.txt') {|f| f.gets(3) } # => "Fir"
15237  * File.open('t.txt') {|f| f.gets(4) } # => "Firs"
15238  * # No more than one line.
15239  * File.open('t.txt') {|f| f.gets(10) } # => "First line"
15240  * File.open('t.txt') {|f| f.gets(11) } # => "First line\n"
15241  * File.open('t.txt') {|f| f.gets(12) } # => "First line\n"
15242  *
15243  * # Text with 2-byte characters, which will not be split.
15244  * File.open('t.rus') {|f| f.gets(1).size } # => 1
15245  * File.open('t.rus') {|f| f.gets(2).size } # => 1
15246  * File.open('t.rus') {|f| f.gets(3).size } # => 2
15247  * File.open('t.rus') {|f| f.gets(4).size } # => 2
15248  *
15249  * ===== Line Separator and Line Limit
15250  *
15251  * With arguments +sep+ and +limit+ given, combines the two behaviors:
15252  *
15253  * - Returns the next line as determined by line separator +sep+.
15254  * - But returns no more bytes than are allowed by the limit +limit+.
15255  *
15256  * Example:
15257  *
15258  * File.open('t.txt') {|f| f.gets('li', 20) } # => "First li"
15259  * File.open('t.txt') {|f| f.gets('li', 2) } # => "Fi"
15260  *
15261  * ===== Line Number
15262  *
15263  * A readable \IO stream has a non-negative integer <i>line number</i>:
15264  *
15265  * - IO#lineno: Returns the line number.
15266  * - IO#lineno=: Resets and returns the line number.
15267  *
15268  * Unless modified by a call to method IO#lineno=,
15269  * the line number is the number of lines read
15270  * by certain line-oriented methods,
15271  * according to the effective {line separator}[rdoc-ref:IO@Line+Separator]:
15272  *
15273  * - IO.foreach: Increments the line number on each call to the block.
15274  * - IO#each_line: Increments the line number on each call to the block.
15275  * - IO#gets: Increments the line number.
15276  * - IO#readline: Increments the line number.
15277  * - IO#readlines: Increments the line number for each line read.
15278  *
15279  * A new stream is initially has line number zero (and position zero);
15280  * method +rewind+ resets the line number (and position) to zero:
15281  *
15282  * f = File.new('t.txt')
15283  * f.lineno # => 0
15284  * f.gets # => "First line\n"
15285  * f.lineno # => 1
15286  * f.rewind
15287  * f.lineno # => 0
15288  * f.close
15289  *
15290  * Reading lines from a stream usually changes its line number:
15291  *
15292  * f = File.new('t.txt', 'r')
15293  * f.lineno # => 0
15294  * f.readline # => "This is line one.\n"
15295  * f.lineno # => 1
15296  * f.readline # => "This is the second line.\n"
15297  * f.lineno # => 2
15298  * f.readline # => "Here's the third line.\n"
15299  * f.lineno # => 3
15300  * f.eof? # => true
15301  * f.close
15302  *
15303  * Iterating over lines in a stream usually changes its line number:
15304  *
15305  * File.open('t.txt') do |f|
15306  * f.each_line do |line|
15307  * p "position=#{f.pos} eof?=#{f.eof?} lineno=#{f.lineno}"
15308  * end
15309  * end
15310  *
15311  * Output:
15312  *
15313  * "position=11 eof?=false lineno=1"
15314  * "position=23 eof?=false lineno=2"
15315  * "position=24 eof?=false lineno=3"
15316  * "position=36 eof?=false lineno=4"
15317  * "position=47 eof?=true lineno=5"
15318  *
15319  * Unlike the stream's {position}[rdoc-ref:IO@Position],
15320  * the line number does not affect where the next read or write will occur:
15321  *
15322  * f = File.new('t.txt')
15323  * f.lineno = 1000
15324  * f.lineno # => 1000
15325  * f.gets # => "First line\n"
15326  * f.lineno # => 1001
15327  * f.close
15328  *
15329  * Associated with the line number is the global variable <tt>$.</tt>:
15330  *
15331  * - When a stream is opened, <tt>$.</tt> is not set;
15332  * its value is left over from previous activity in the process:
15333  *
15334  * $. = 41
15335  * f = File.new('t.txt')
15336  * $. = 41
15337  * # => 41
15338  * f.close
15339  *
15340  * - When a stream is read, <tt>$.</tt> is set to the line number for that stream:
15341  *
15342  * f0 = File.new('t.txt')
15343  * f1 = File.new('t.dat')
15344  * f0.readlines # => ["First line\n", "Second line\n", "\n", "Fourth line\n", "Fifth line\n"]
15345  * $. # => 5
15346  * f1.readlines # => ["\xFE\xFF\x99\x90\x99\x91\x99\x92\x99\x93\x99\x94"]
15347  * $. # => 1
15348  * f0.close
15349  * f1.close
15350  *
15351  * - Methods IO#rewind and IO#seek do not affect <tt>$.</tt>:
15352  *
15353  * f = File.new('t.txt')
15354  * f.readlines # => ["First line\n", "Second line\n", "\n", "Fourth line\n", "Fifth line\n"]
15355  * $. # => 5
15356  * f.rewind
15357  * f.seek(0, :SET)
15358  * $. # => 5
15359  * f.close
15360  *
15361  * === Line Output
15362  *
15363  * You can write to an \IO stream line-by-line using this method:
15364  *
15365  * - IO#puts: Writes objects to the stream.
15366  *
15367  * == Character \IO
15368  *
15369  * You can process an \IO stream character-by-character using these methods:
15370  *
15371  * - IO#getc: Reads and returns the next character from the stream.
15372  * - IO#readchar: Like #getc, but raises an exception at end-of-stream.
15373  * - IO#ungetc: Pushes back ("unshifts") a character or integer onto the stream.
15374  * - IO#putc: Writes a character to the stream.
15375  * - IO#each_char: Reads each remaining character in the stream,
15376  * passing the character to the given block.
15377  * == Byte \IO
15378  *
15379  * You can process an \IO stream byte-by-byte using these methods:
15380  *
15381  * - IO#getbyte: Returns the next 8-bit byte as an integer in range 0..255.
15382  * - IO#readbyte: Like #getbyte, but raises an exception if at end-of-stream.
15383  * - IO#ungetbyte: Pushes back ("unshifts") a byte back onto the stream.
15384  * - IO#each_byte: Reads each remaining byte in the stream,
15385  * passing the byte to the given block.
15386  *
15387  * == Codepoint \IO
15388  *
15389  * You can process an \IO stream codepoint-by-codepoint:
15390  *
15391  * - IO#each_codepoint: Reads each remaining codepoint, passing it to the given block.
15392  *
15393  * == What's Here
15394  *
15395  * First, what's elsewhere. \Class \IO:
15396  *
15397  * - Inherits from {class Object}[rdoc-ref:Object@What-27s+Here].
15398  * - Includes {module Enumerable}[rdoc-ref:Enumerable@What-27s+Here],
15399  * which provides dozens of additional methods.
15400  *
15401  * Here, class \IO provides methods that are useful for:
15402  *
15403  * - {Creating}[rdoc-ref:IO@Creating]
15404  * - {Reading}[rdoc-ref:IO@Reading]
15405  * - {Writing}[rdoc-ref:IO@Writing]
15406  * - {Positioning}[rdoc-ref:IO@Positioning]
15407  * - {Iterating}[rdoc-ref:IO@Iterating]
15408  * - {Settings}[rdoc-ref:IO@Settings]
15409  * - {Querying}[rdoc-ref:IO@Querying]
15410  * - {Buffering}[rdoc-ref:IO@Buffering]
15411  * - {Low-Level Access}[rdoc-ref:IO@Low-Level+Access]
15412  * - {Other}[rdoc-ref:IO@Other]
15413  *
15414  * === Creating
15415  *
15416  * - ::new (aliased as ::for_fd): Creates and returns a new \IO object for the given
15417  * integer file descriptor.
15418  * - ::open: Creates a new \IO object.
15419  * - ::pipe: Creates a connected pair of reader and writer \IO objects.
15420  * - ::popen: Creates an \IO object to interact with a subprocess.
15421  * - ::select: Selects which given \IO instances are ready for reading,
15422  * writing, or have pending exceptions.
15423  *
15424  * === Reading
15425  *
15426  * - ::binread: Returns a binary string with all or a subset of bytes
15427  * from the given file.
15428  * - ::read: Returns a string with all or a subset of bytes from the given file.
15429  * - ::readlines: Returns an array of strings, which are the lines from the given file.
15430  * - #getbyte: Returns the next 8-bit byte read from +self+ as an integer.
15431  * - #getc: Returns the next character read from +self+ as a string.
15432  * - #gets: Returns the line read from +self+.
15433  * - #pread: Returns all or the next _n_ bytes read from +self+,
15434  * not updating the receiver's offset.
15435  * - #read: Returns all remaining or the next _n_ bytes read from +self+
15436  * for a given _n_.
15437  * - #read_nonblock: the next _n_ bytes read from +self+ for a given _n_,
15438  * in non-block mode.
15439  * - #readbyte: Returns the next byte read from +self+;
15440  * same as #getbyte, but raises an exception on end-of-stream.
15441  * - #readchar: Returns the next character read from +self+;
15442  * same as #getc, but raises an exception on end-of-stream.
15443  * - #readline: Returns the next line read from +self+;
15444  * same as #getline, but raises an exception of end-of-stream.
15445  * - #readlines: Returns an array of all lines read read from +self+.
15446  * - #readpartial: Returns up to the given number of bytes from +self+.
15447  *
15448  * === Writing
15449  *
15450  * - ::binwrite: Writes the given string to the file at the given filepath,
15451  * in binary mode.
15452  * - ::write: Writes the given string to +self+.
15453  * - #<<: Appends the given string to +self+.
15454  * - #print: Prints last read line or given objects to +self+.
15455  * - #printf: Writes to +self+ based on the given format string and objects.
15456  * - #putc: Writes a character to +self+.
15457  * - #puts: Writes lines to +self+, making sure line ends with a newline.
15458  * - #pwrite: Writes the given string at the given offset,
15459  * not updating the receiver's offset.
15460  * - #write: Writes one or more given strings to +self+.
15461  * - #write_nonblock: Writes one or more given strings to +self+ in non-blocking mode.
15462  *
15463  * === Positioning
15464  *
15465  * - #lineno: Returns the current line number in +self+.
15466  * - #lineno=: Sets the line number is +self+.
15467  * - #pos (aliased as #tell): Returns the current byte offset in +self+.
15468  * - #pos=: Sets the byte offset in +self+.
15469  * - #reopen: Reassociates +self+ with a new or existing \IO stream.
15470  * - #rewind: Positions +self+ to the beginning of input.
15471  * - #seek: Sets the offset for +self+ relative to given position.
15472  *
15473  * === Iterating
15474  *
15475  * - ::foreach: Yields each line of given file to the block.
15476  * - #each (aliased as #each_line): Calls the given block
15477  * with each successive line in +self+.
15478  * - #each_byte: Calls the given block with each successive byte in +self+
15479  * as an integer.
15480  * - #each_char: Calls the given block with each successive character in +self+
15481  * as a string.
15482  * - #each_codepoint: Calls the given block with each successive codepoint in +self+
15483  * as an integer.
15484  *
15485  * === Settings
15486  *
15487  * - #autoclose=: Sets whether +self+ auto-closes.
15488  * - #binmode: Sets +self+ to binary mode.
15489  * - #close: Closes +self+.
15490  * - #close_on_exec=: Sets the close-on-exec flag.
15491  * - #close_read: Closes +self+ for reading.
15492  * - #close_write: Closes +self+ for writing.
15493  * - #set_encoding: Sets the encoding for +self+.
15494  * - #set_encoding_by_bom: Sets the encoding for +self+, based on its
15495  * Unicode byte-order-mark.
15496  * - #sync=: Sets the sync-mode to the given value.
15497  *
15498  * === Querying
15499  *
15500  * - #autoclose?: Returns whether +self+ auto-closes.
15501  * - #binmode?: Returns whether +self+ is in binary mode.
15502  * - #close_on_exec?: Returns the close-on-exec flag for +self+.
15503  * - #closed?: Returns whether +self+ is closed.
15504  * - #eof? (aliased as #eof): Returns whether +self+ is at end-of-stream.
15505  * - #external_encoding: Returns the external encoding object for +self+.
15506  * - #fileno (aliased as #to_i): Returns the integer file descriptor for +self+
15507  * - #internal_encoding: Returns the internal encoding object for +self+.
15508  * - #pid: Returns the process ID of a child process associated with +self+,
15509  * if +self+ was created by ::popen.
15510  * - #stat: Returns the File::Stat object containing status information for +self+.
15511  * - #sync: Returns whether +self+ is in sync-mode.
15512  * - #tty? (aliased as #isatty): Returns whether +self+ is a terminal.
15513  *
15514  * === Buffering
15515  *
15516  * - #fdatasync: Immediately writes all buffered data in +self+ to disk.
15517  * - #flush: Flushes any buffered data within +self+ to the underlying
15518  * operating system.
15519  * - #fsync: Immediately writes all buffered data and attributes in +self+ to disk.
15520  * - #ungetbyte: Prepends buffer for +self+ with given integer byte or string.
15521  * - #ungetc: Prepends buffer for +self+ with given string.
15522  *
15523  * === Low-Level Access
15524  *
15525  * - ::sysopen: Opens the file given by its path,
15526  * returning the integer file descriptor.
15527  * - #advise: Announces the intention to access data from +self+ in a specific way.
15528  * - #fcntl: Passes a low-level command to the file specified
15529  * by the given file descriptor.
15530  * - #ioctl: Passes a low-level command to the device specified
15531  * by the given file descriptor.
15532  * - #sysread: Returns up to the next _n_ bytes read from self using a low-level read.
15533  * - #sysseek: Sets the offset for +self+.
15534  * - #syswrite: Writes the given string to +self+ using a low-level write.
15535  *
15536  * === Other
15537  *
15538  * - ::copy_stream: Copies data from a source to a destination,
15539  * each of which is a filepath or an \IO-like object.
15540  * - ::try_convert: Returns a new \IO object resulting from converting
15541  * the given object.
15542  * - #inspect: Returns the string representation of +self+.
15543  *
15544  */
15545 
15546 void
15547 Init_IO(void)
15548 {
15549  VALUE rb_cARGF;
15550 #ifdef __CYGWIN__
15551 #include <sys/cygwin.h>
15552  static struct __cygwin_perfile pf[] =
15553  {
15554  {"", O_RDONLY | O_BINARY},
15555  {"", O_WRONLY | O_BINARY},
15556  {"", O_RDWR | O_BINARY},
15557  {"", O_APPEND | O_BINARY},
15558  {NULL, 0}
15559  };
15560  cygwin_internal(CW_PERFILE, pf);
15561 #endif
15562 
15564  rb_eEOFError = rb_define_class("EOFError", rb_eIOError);
15565 
15566  id_write = rb_intern_const("write");
15567  id_read = rb_intern_const("read");
15568  id_getc = rb_intern_const("getc");
15569  id_flush = rb_intern_const("flush");
15570  id_readpartial = rb_intern_const("readpartial");
15571  id_set_encoding = rb_intern_const("set_encoding");
15572  id_fileno = rb_intern_const("fileno");
15573 
15574  rb_define_global_function("syscall", rb_f_syscall, -1);
15575 
15576  rb_define_global_function("open", rb_f_open, -1);
15577  rb_define_global_function("printf", rb_f_printf, -1);
15578  rb_define_global_function("print", rb_f_print, -1);
15579  rb_define_global_function("putc", rb_f_putc, 1);
15580  rb_define_global_function("puts", rb_f_puts, -1);
15581  rb_define_global_function("gets", rb_f_gets, -1);
15582  rb_define_global_function("readline", rb_f_readline, -1);
15583  rb_define_global_function("select", rb_f_select, -1);
15584 
15585  rb_define_global_function("readlines", rb_f_readlines, -1);
15586 
15587  rb_define_global_function("`", rb_f_backquote, 1);
15588 
15589  rb_define_global_function("p", rb_f_p, -1);
15590  rb_define_method(rb_mKernel, "display", rb_obj_display, -1);
15591 
15592  rb_cIO = rb_define_class("IO", rb_cObject);
15594 
15595  /* Can be raised by IO operations when IO#timeout= is set. */
15597 
15598  /* Readable event mask for IO#wait. */
15600  /* Writable event mask for IO#wait. */
15602  /* Priority event mask for IO#wait. */
15604 
15605  /* exception to wait for reading. see IO.select. */
15606  rb_mWaitReadable = rb_define_module_under(rb_cIO, "WaitReadable");
15607  /* exception to wait for writing. see IO.select. */
15608  rb_mWaitWritable = rb_define_module_under(rb_cIO, "WaitWritable");
15609  /* exception to wait for reading by EAGAIN. see IO.select. */
15610  rb_eEAGAINWaitReadable = rb_define_class_under(rb_cIO, "EAGAINWaitReadable", rb_eEAGAIN);
15611  rb_include_module(rb_eEAGAINWaitReadable, rb_mWaitReadable);
15612  /* exception to wait for writing by EAGAIN. see IO.select. */
15613  rb_eEAGAINWaitWritable = rb_define_class_under(rb_cIO, "EAGAINWaitWritable", rb_eEAGAIN);
15614  rb_include_module(rb_eEAGAINWaitWritable, rb_mWaitWritable);
15615 #if EAGAIN == EWOULDBLOCK
15616  rb_eEWOULDBLOCKWaitReadable = rb_eEAGAINWaitReadable;
15617  /* same as IO::EAGAINWaitReadable */
15618  rb_define_const(rb_cIO, "EWOULDBLOCKWaitReadable", rb_eEAGAINWaitReadable);
15619  rb_eEWOULDBLOCKWaitWritable = rb_eEAGAINWaitWritable;
15620  /* same as IO::EAGAINWaitWritable */
15621  rb_define_const(rb_cIO, "EWOULDBLOCKWaitWritable", rb_eEAGAINWaitWritable);
15622 #else
15623  /* exception to wait for reading by EWOULDBLOCK. see IO.select. */
15624  rb_eEWOULDBLOCKWaitReadable = rb_define_class_under(rb_cIO, "EWOULDBLOCKWaitReadable", rb_eEWOULDBLOCK);
15625  rb_include_module(rb_eEWOULDBLOCKWaitReadable, rb_mWaitReadable);
15626  /* exception to wait for writing by EWOULDBLOCK. see IO.select. */
15627  rb_eEWOULDBLOCKWaitWritable = rb_define_class_under(rb_cIO, "EWOULDBLOCKWaitWritable", rb_eEWOULDBLOCK);
15628  rb_include_module(rb_eEWOULDBLOCKWaitWritable, rb_mWaitWritable);
15629 #endif
15630  /* exception to wait for reading by EINPROGRESS. see IO.select. */
15631  rb_eEINPROGRESSWaitReadable = rb_define_class_under(rb_cIO, "EINPROGRESSWaitReadable", rb_eEINPROGRESS);
15632  rb_include_module(rb_eEINPROGRESSWaitReadable, rb_mWaitReadable);
15633  /* exception to wait for writing by EINPROGRESS. see IO.select. */
15634  rb_eEINPROGRESSWaitWritable = rb_define_class_under(rb_cIO, "EINPROGRESSWaitWritable", rb_eEINPROGRESS);
15635  rb_include_module(rb_eEINPROGRESSWaitWritable, rb_mWaitWritable);
15636 
15637 #if 0
15638  /* This is necessary only for forcing rdoc handle File::open */
15639  rb_define_singleton_method(rb_cFile, "open", rb_io_s_open, -1);
15640 #endif
15641 
15642  rb_define_alloc_func(rb_cIO, io_alloc);
15643  rb_define_singleton_method(rb_cIO, "new", rb_io_s_new, -1);
15644  rb_define_singleton_method(rb_cIO, "open", rb_io_s_open, -1);
15645  rb_define_singleton_method(rb_cIO, "sysopen", rb_io_s_sysopen, -1);
15646  rb_define_singleton_method(rb_cIO, "for_fd", rb_io_s_for_fd, -1);
15647  rb_define_singleton_method(rb_cIO, "popen", rb_io_s_popen, -1);
15648  rb_define_singleton_method(rb_cIO, "foreach", rb_io_s_foreach, -1);
15649  rb_define_singleton_method(rb_cIO, "readlines", rb_io_s_readlines, -1);
15650  rb_define_singleton_method(rb_cIO, "read", rb_io_s_read, -1);
15651  rb_define_singleton_method(rb_cIO, "binread", rb_io_s_binread, -1);
15652  rb_define_singleton_method(rb_cIO, "write", rb_io_s_write, -1);
15653  rb_define_singleton_method(rb_cIO, "binwrite", rb_io_s_binwrite, -1);
15654  rb_define_singleton_method(rb_cIO, "select", rb_f_select, -1);
15655  rb_define_singleton_method(rb_cIO, "pipe", rb_io_s_pipe, -1);
15656  rb_define_singleton_method(rb_cIO, "try_convert", rb_io_s_try_convert, 1);
15657  rb_define_singleton_method(rb_cIO, "copy_stream", rb_io_s_copy_stream, -1);
15658 
15659  rb_define_method(rb_cIO, "initialize", rb_io_initialize, -1);
15660 
15661  rb_output_fs = Qnil;
15662  rb_define_hooked_variable("$,", &rb_output_fs, 0, deprecated_str_setter);
15663 
15664  rb_default_rs = rb_fstring_lit("\n"); /* avoid modifying RS_default */
15665  rb_vm_register_global_object(rb_default_rs);
15666  rb_rs = rb_default_rs;
15667  rb_output_rs = Qnil;
15668  rb_define_hooked_variable("$/", &rb_rs, 0, deprecated_str_setter);
15669  rb_define_hooked_variable("$-0", &rb_rs, 0, deprecated_str_setter);
15670  rb_define_hooked_variable("$\\", &rb_output_rs, 0, deprecated_str_setter);
15671 
15672  rb_define_virtual_variable("$_", get_LAST_READ_LINE, set_LAST_READ_LINE);
15673  rb_gvar_ractor_local("$_");
15674 
15675  rb_define_method(rb_cIO, "initialize_copy", rb_io_init_copy, 1);
15676  rb_define_method(rb_cIO, "reopen", rb_io_reopen, -1);
15677 
15678  rb_define_method(rb_cIO, "print", rb_io_print, -1);
15679  rb_define_method(rb_cIO, "putc", rb_io_putc, 1);
15680  rb_define_method(rb_cIO, "puts", rb_io_puts, -1);
15681  rb_define_method(rb_cIO, "printf", rb_io_printf, -1);
15682 
15683  rb_define_method(rb_cIO, "each", rb_io_each_line, -1);
15684  rb_define_method(rb_cIO, "each_line", rb_io_each_line, -1);
15685  rb_define_method(rb_cIO, "each_byte", rb_io_each_byte, 0);
15686  rb_define_method(rb_cIO, "each_char", rb_io_each_char, 0);
15687  rb_define_method(rb_cIO, "each_codepoint", rb_io_each_codepoint, 0);
15688 
15689  rb_define_method(rb_cIO, "syswrite", rb_io_syswrite, 1);
15690  rb_define_method(rb_cIO, "sysread", rb_io_sysread, -1);
15691 
15692  rb_define_method(rb_cIO, "pread", rb_io_pread, -1);
15693  rb_define_method(rb_cIO, "pwrite", rb_io_pwrite, 2);
15694 
15695  rb_define_method(rb_cIO, "fileno", rb_io_fileno, 0);
15696  rb_define_alias(rb_cIO, "to_i", "fileno");
15697  rb_define_method(rb_cIO, "to_io", rb_io_to_io, 0);
15698 
15699  rb_define_method(rb_cIO, "timeout", rb_io_timeout, 0);
15700  rb_define_method(rb_cIO, "timeout=", rb_io_set_timeout, 1);
15701 
15702  rb_define_method(rb_cIO, "fsync", rb_io_fsync, 0);
15703  rb_define_method(rb_cIO, "fdatasync", rb_io_fdatasync, 0);
15704  rb_define_method(rb_cIO, "sync", rb_io_sync, 0);
15705  rb_define_method(rb_cIO, "sync=", rb_io_set_sync, 1);
15706 
15707  rb_define_method(rb_cIO, "lineno", rb_io_lineno, 0);
15708  rb_define_method(rb_cIO, "lineno=", rb_io_set_lineno, 1);
15709 
15710  rb_define_method(rb_cIO, "readlines", rb_io_readlines, -1);
15711 
15712  rb_define_method(rb_cIO, "readpartial", io_readpartial, -1);
15713  rb_define_method(rb_cIO, "read", io_read, -1);
15714  rb_define_method(rb_cIO, "write", io_write_m, -1);
15715  rb_define_method(rb_cIO, "gets", rb_io_gets_m, -1);
15716  rb_define_method(rb_cIO, "getc", rb_io_getc, 0);
15717  rb_define_method(rb_cIO, "getbyte", rb_io_getbyte, 0);
15718  rb_define_method(rb_cIO, "readchar", rb_io_readchar, 0);
15719  rb_define_method(rb_cIO, "readbyte", rb_io_readbyte, 0);
15720  rb_define_method(rb_cIO, "ungetbyte",rb_io_ungetbyte, 1);
15721  rb_define_method(rb_cIO, "ungetc",rb_io_ungetc, 1);
15723  rb_define_method(rb_cIO, "flush", rb_io_flush, 0);
15724  rb_define_method(rb_cIO, "tell", rb_io_tell, 0);
15725  rb_define_method(rb_cIO, "seek", rb_io_seek_m, -1);
15726  /* Set I/O position from the beginning */
15727  rb_define_const(rb_cIO, "SEEK_SET", INT2FIX(SEEK_SET));
15728  /* Set I/O position from the current position */
15729  rb_define_const(rb_cIO, "SEEK_CUR", INT2FIX(SEEK_CUR));
15730  /* Set I/O position from the end */
15731  rb_define_const(rb_cIO, "SEEK_END", INT2FIX(SEEK_END));
15732 #ifdef SEEK_DATA
15733  /* Set I/O position to the next location containing data */
15734  rb_define_const(rb_cIO, "SEEK_DATA", INT2FIX(SEEK_DATA));
15735 #endif
15736 #ifdef SEEK_HOLE
15737  /* Set I/O position to the next hole */
15738  rb_define_const(rb_cIO, "SEEK_HOLE", INT2FIX(SEEK_HOLE));
15739 #endif
15740  rb_define_method(rb_cIO, "rewind", rb_io_rewind, 0);
15741  rb_define_method(rb_cIO, "pos", rb_io_tell, 0);
15742  rb_define_method(rb_cIO, "pos=", rb_io_set_pos, 1);
15743  rb_define_method(rb_cIO, "eof", rb_io_eof, 0);
15744  rb_define_method(rb_cIO, "eof?", rb_io_eof, 0);
15745 
15746  rb_define_method(rb_cIO, "close_on_exec?", rb_io_close_on_exec_p, 0);
15747  rb_define_method(rb_cIO, "close_on_exec=", rb_io_set_close_on_exec, 1);
15748 
15749  rb_define_method(rb_cIO, "close", rb_io_close_m, 0);
15750  rb_define_method(rb_cIO, "closed?", rb_io_closed_p, 0);
15751  rb_define_method(rb_cIO, "close_read", rb_io_close_read, 0);
15752  rb_define_method(rb_cIO, "close_write", rb_io_close_write, 0);
15753 
15754  rb_define_method(rb_cIO, "isatty", rb_io_isatty, 0);
15755  rb_define_method(rb_cIO, "tty?", rb_io_isatty, 0);
15756  rb_define_method(rb_cIO, "binmode", rb_io_binmode_m, 0);
15757  rb_define_method(rb_cIO, "binmode?", rb_io_binmode_p, 0);
15758  rb_define_method(rb_cIO, "sysseek", rb_io_sysseek, -1);
15759  rb_define_method(rb_cIO, "advise", rb_io_advise, -1);
15760 
15761  rb_define_method(rb_cIO, "ioctl", rb_io_ioctl, -1);
15762  rb_define_method(rb_cIO, "fcntl", rb_io_fcntl, -1);
15763  rb_define_method(rb_cIO, "pid", rb_io_pid, 0);
15764 
15765  rb_define_method(rb_cIO, "path", rb_io_path, 0);
15766  rb_define_method(rb_cIO, "to_path", rb_io_path, 0);
15767 
15768  rb_define_method(rb_cIO, "inspect", rb_io_inspect, 0);
15769 
15770  rb_define_method(rb_cIO, "external_encoding", rb_io_external_encoding, 0);
15771  rb_define_method(rb_cIO, "internal_encoding", rb_io_internal_encoding, 0);
15772  rb_define_method(rb_cIO, "set_encoding", rb_io_set_encoding, -1);
15773  rb_define_method(rb_cIO, "set_encoding_by_bom", rb_io_set_encoding_by_bom, 0);
15774 
15775  rb_define_method(rb_cIO, "autoclose?", rb_io_autoclose_p, 0);
15776  rb_define_method(rb_cIO, "autoclose=", rb_io_set_autoclose, 1);
15777 
15778  rb_define_method(rb_cIO, "wait", io_wait, -1);
15779 
15780  rb_define_method(rb_cIO, "wait_readable", io_wait_readable, -1);
15781  rb_define_method(rb_cIO, "wait_writable", io_wait_writable, -1);
15782  rb_define_method(rb_cIO, "wait_priority", io_wait_priority, -1);
15783 
15784  rb_define_virtual_variable("$stdin", stdin_getter, stdin_setter);
15785  rb_define_virtual_variable("$stdout", stdout_getter, stdout_setter);
15786  rb_define_virtual_variable("$>", stdout_getter, stdout_setter);
15787  rb_define_virtual_variable("$stderr", stderr_getter, stderr_setter);
15788 
15789  rb_gvar_ractor_local("$stdin");
15790  rb_gvar_ractor_local("$stdout");
15791  rb_gvar_ractor_local("$>");
15792  rb_gvar_ractor_local("$stderr");
15793 
15795  rb_stdin = rb_io_prep_stdin();
15797  rb_stdout = rb_io_prep_stdout();
15799  rb_stderr = rb_io_prep_stderr();
15800 
15801  orig_stdout = rb_stdout;
15802  orig_stderr = rb_stderr;
15803 
15804  /* Holds the original stdin */
15805  rb_define_global_const("STDIN", rb_stdin);
15806  /* Holds the original stdout */
15807  rb_define_global_const("STDOUT", rb_stdout);
15808  /* Holds the original stderr */
15809  rb_define_global_const("STDERR", rb_stderr);
15810 
15811 #if 0
15812  /* Hack to get rdoc to regard ARGF as a class: */
15813  rb_cARGF = rb_define_class("ARGF", rb_cObject);
15814 #endif
15815 
15816  rb_cARGF = rb_class_new(rb_cObject);
15817  rb_set_class_path(rb_cARGF, rb_cObject, "ARGF.class");
15818  rb_define_alloc_func(rb_cARGF, argf_alloc);
15819 
15820  rb_include_module(rb_cARGF, rb_mEnumerable);
15821 
15822  rb_define_method(rb_cARGF, "initialize", argf_initialize, -2);
15823  rb_define_method(rb_cARGF, "initialize_copy", argf_initialize_copy, 1);
15824  rb_define_method(rb_cARGF, "to_s", argf_to_s, 0);
15825  rb_define_alias(rb_cARGF, "inspect", "to_s");
15826  rb_define_method(rb_cARGF, "argv", argf_argv, 0);
15827 
15828  rb_define_method(rb_cARGF, "fileno", argf_fileno, 0);
15829  rb_define_method(rb_cARGF, "to_i", argf_fileno, 0);
15830  rb_define_method(rb_cARGF, "to_io", argf_to_io, 0);
15831  rb_define_method(rb_cARGF, "to_write_io", argf_write_io, 0);
15832  rb_define_method(rb_cARGF, "each", argf_each_line, -1);
15833  rb_define_method(rb_cARGF, "each_line", argf_each_line, -1);
15834  rb_define_method(rb_cARGF, "each_byte", argf_each_byte, 0);
15835  rb_define_method(rb_cARGF, "each_char", argf_each_char, 0);
15836  rb_define_method(rb_cARGF, "each_codepoint", argf_each_codepoint, 0);
15837 
15838  rb_define_method(rb_cARGF, "read", argf_read, -1);
15839  rb_define_method(rb_cARGF, "readpartial", argf_readpartial, -1);
15840  rb_define_method(rb_cARGF, "read_nonblock", argf_read_nonblock, -1);
15841  rb_define_method(rb_cARGF, "readlines", argf_readlines, -1);
15842  rb_define_method(rb_cARGF, "to_a", argf_readlines, -1);
15843  rb_define_method(rb_cARGF, "gets", argf_gets, -1);
15844  rb_define_method(rb_cARGF, "readline", argf_readline, -1);
15845  rb_define_method(rb_cARGF, "getc", argf_getc, 0);
15846  rb_define_method(rb_cARGF, "getbyte", argf_getbyte, 0);
15847  rb_define_method(rb_cARGF, "readchar", argf_readchar, 0);
15848  rb_define_method(rb_cARGF, "readbyte", argf_readbyte, 0);
15849  rb_define_method(rb_cARGF, "tell", argf_tell, 0);
15850  rb_define_method(rb_cARGF, "seek", argf_seek_m, -1);
15851  rb_define_method(rb_cARGF, "rewind", argf_rewind, 0);
15852  rb_define_method(rb_cARGF, "pos", argf_tell, 0);
15853  rb_define_method(rb_cARGF, "pos=", argf_set_pos, 1);
15854  rb_define_method(rb_cARGF, "eof", argf_eof, 0);
15855  rb_define_method(rb_cARGF, "eof?", argf_eof, 0);
15856  rb_define_method(rb_cARGF, "binmode", argf_binmode_m, 0);
15857  rb_define_method(rb_cARGF, "binmode?", argf_binmode_p, 0);
15858 
15859  rb_define_method(rb_cARGF, "write", argf_write, -1);
15860  rb_define_method(rb_cARGF, "print", rb_io_print, -1);
15861  rb_define_method(rb_cARGF, "putc", rb_io_putc, 1);
15862  rb_define_method(rb_cARGF, "puts", rb_io_puts, -1);
15863  rb_define_method(rb_cARGF, "printf", rb_io_printf, -1);
15864 
15865  rb_define_method(rb_cARGF, "filename", argf_filename, 0);
15866  rb_define_method(rb_cARGF, "path", argf_filename, 0);
15867  rb_define_method(rb_cARGF, "file", argf_file, 0);
15868  rb_define_method(rb_cARGF, "skip", argf_skip, 0);
15869  rb_define_method(rb_cARGF, "close", argf_close_m, 0);
15870  rb_define_method(rb_cARGF, "closed?", argf_closed, 0);
15871 
15872  rb_define_method(rb_cARGF, "lineno", argf_lineno, 0);
15873  rb_define_method(rb_cARGF, "lineno=", argf_set_lineno, 1);
15874 
15875  rb_define_method(rb_cARGF, "inplace_mode", argf_inplace_mode_get, 0);
15876  rb_define_method(rb_cARGF, "inplace_mode=", argf_inplace_mode_set, 1);
15877 
15878  rb_define_method(rb_cARGF, "external_encoding", argf_external_encoding, 0);
15879  rb_define_method(rb_cARGF, "internal_encoding", argf_internal_encoding, 0);
15880  rb_define_method(rb_cARGF, "set_encoding", argf_set_encoding, -1);
15881 
15882  argf = rb_class_new_instance(0, 0, rb_cARGF);
15883 
15885  /*
15886  * ARGF is a stream designed for use in scripts that process files given
15887  * as command-line arguments or passed in via STDIN.
15888  *
15889  * See ARGF (the class) for more details.
15890  */
15891  rb_define_global_const("ARGF", argf);
15892 
15893  rb_define_hooked_variable("$.", &argf, argf_lineno_getter, argf_lineno_setter);
15894  rb_define_hooked_variable("$FILENAME", &argf, argf_filename_getter, rb_gvar_readonly_setter);
15895  ARGF.filename = rb_str_new2("-");
15896 
15897  rb_define_hooked_variable("$-i", &argf, opt_i_get, opt_i_set);
15898  rb_gvar_ractor_local("$-i");
15899 
15900  rb_define_hooked_variable("$*", &argf, argf_argv_getter, rb_gvar_readonly_setter);
15901 
15902 #if defined (_WIN32) || defined(__CYGWIN__)
15903  atexit(pipe_atexit);
15904 #endif
15905 
15906  Init_File();
15907 
15908  rb_define_method(rb_cFile, "initialize", rb_file_initialize, -1);
15909 
15910  sym_mode = ID2SYM(rb_intern_const("mode"));
15911  sym_perm = ID2SYM(rb_intern_const("perm"));
15912  sym_flags = ID2SYM(rb_intern_const("flags"));
15913  sym_extenc = ID2SYM(rb_intern_const("external_encoding"));
15914  sym_intenc = ID2SYM(rb_intern_const("internal_encoding"));
15915  sym_encoding = ID2SYM(rb_id_encoding());
15916  sym_open_args = ID2SYM(rb_intern_const("open_args"));
15917  sym_textmode = ID2SYM(rb_intern_const("textmode"));
15918  sym_binmode = ID2SYM(rb_intern_const("binmode"));
15919  sym_autoclose = ID2SYM(rb_intern_const("autoclose"));
15920  sym_normal = ID2SYM(rb_intern_const("normal"));
15921  sym_sequential = ID2SYM(rb_intern_const("sequential"));
15922  sym_random = ID2SYM(rb_intern_const("random"));
15923  sym_willneed = ID2SYM(rb_intern_const("willneed"));
15924  sym_dontneed = ID2SYM(rb_intern_const("dontneed"));
15925  sym_noreuse = ID2SYM(rb_intern_const("noreuse"));
15926  sym_SET = ID2SYM(rb_intern_const("SET"));
15927  sym_CUR = ID2SYM(rb_intern_const("CUR"));
15928  sym_END = ID2SYM(rb_intern_const("END"));
15929 #ifdef SEEK_DATA
15930  sym_DATA = ID2SYM(rb_intern_const("DATA"));
15931 #endif
15932 #ifdef SEEK_HOLE
15933  sym_HOLE = ID2SYM(rb_intern_const("HOLE"));
15934 #endif
15935  sym_wait_readable = ID2SYM(rb_intern_const("wait_readable"));
15936  sym_wait_writable = ID2SYM(rb_intern_const("wait_writable"));
15937 }
15938 
15939 #include "io.rbinc"
#define RUBY_ASSERT(...)
Asserts that the given expression is truthy if and only if RUBY_DEBUG is truthy.
Definition: assert.h:219
std::atomic< unsigned > rb_atomic_t
Type that is eligible for atomic operations.
Definition: atomic.h:69
unsigned long ruby_strtoul(const char *str, char **endptr, int base)
Our own locale-insensitive version of strtoul(3).
Definition: util.c:138
#define rb_define_singleton_method(klass, mid, func, arity)
Defines klass.mid.
Definition: cxxanyargs.hpp:685
void rb_include_module(VALUE klass, VALUE module)
Includes a module to a class.
Definition: class.c:1187
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:980
VALUE rb_class_new(VALUE super)
Creates a new, anonymous class.
Definition: class.c:359
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:1012
VALUE rb_define_module_under(VALUE outer, const char *name)
Defines a module under the namespace of outer.
Definition: class.c:1119
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
Definition: class.c:2345
int rb_scan_args_kw(int kw_flag, int argc, const VALUE *argv, const char *fmt,...)
Identical to rb_scan_args(), except it also accepts kw_splat.
Definition: class.c:2648
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Retrieves argument from argc and argv to given VALUE references according to the format string.
Definition: class.c:2635
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a method.
Definition: class.c:2142
int rb_block_given_p(void)
Determines if the current method is given a block.
Definition: eval.c:916
int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *values)
Keyword argument deconstructor.
Definition: class.c:2424
void rb_define_global_function(const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a global function.
Definition: class.c:2339
#define ECONV_AFTER_OUTPUT
Old name of RUBY_ECONV_AFTER_OUTPUT.
Definition: transcode.h:555
#define rb_str_new2
Old name of rb_str_new_cstr.
Definition: string.h:1675
#define TYPE(_)
Old name of rb_type.
Definition: value_type.h:108
#define RB_INTEGER_TYPE_P
Old name of rb_integer_type_p.
Definition: value_type.h:87
#define ENC_CODERANGE_7BIT
Old name of RUBY_ENC_CODERANGE_7BIT.
Definition: coderange.h:180
#define T_FILE
Old name of RUBY_T_FILE.
Definition: value_type.h:62
#define ENC_CODERANGE_VALID
Old name of RUBY_ENC_CODERANGE_VALID.
Definition: coderange.h:181
#define ECONV_UNIVERSAL_NEWLINE_DECORATOR
Old name of RUBY_ECONV_UNIVERSAL_NEWLINE_DECORATOR.
Definition: transcode.h:532
#define OBJ_INIT_COPY(obj, orig)
Old name of RB_OBJ_INIT_COPY.
Definition: object.h:41
#define ALLOC
Old name of RB_ALLOC.
Definition: memory.h:395
#define T_STRING
Old name of RUBY_T_STRING.
Definition: value_type.h:78
#define Qundef
Old name of RUBY_Qundef.
#define INT2FIX
Old name of RB_INT2FIX.
Definition: long.h:48
#define T_NIL
Old name of RUBY_T_NIL.
Definition: value_type.h:72
#define UNREACHABLE
Old name of RBIMPL_UNREACHABLE.
Definition: assume.h:28
#define ID2SYM
Old name of RB_ID2SYM.
Definition: symbol.h:44
#define T_BIGNUM
Old name of RUBY_T_BIGNUM.
Definition: value_type.h:57
#define OBJ_FREEZE
Old name of RB_OBJ_FREEZE.
Definition: fl_type.h:135
#define T_FIXNUM
Old name of RUBY_T_FIXNUM.
Definition: value_type.h:63
#define UNREACHABLE_RETURN
Old name of RBIMPL_UNREACHABLE_RETURN.
Definition: assume.h:29
#define FIX2UINT
Old name of RB_FIX2UINT.
Definition: int.h:42
#define SSIZET2NUM
Old name of RB_SSIZE2NUM.
Definition: size_t.h:64
#define ZALLOC
Old name of RB_ZALLOC.
Definition: memory.h:397
#define CLASS_OF
Old name of rb_class_of.
Definition: globals.h:203
#define rb_ary_new4
Old name of rb_ary_new_from_values.
Definition: array.h:659
#define ECONV_NEWLINE_DECORATOR_WRITE_MASK
Old name of RUBY_ECONV_NEWLINE_DECORATOR_WRITE_MASK.
Definition: transcode.h:531
#define ENCODING_MAXNAMELEN
Old name of RUBY_ENCODING_MAXNAMELEN.
Definition: encoding.h:111
#define MBCLEN_NEEDMORE_LEN(ret)
Old name of ONIGENC_MBCLEN_NEEDMORE_LEN.
Definition: encoding.h:520
#define ENCODING_GET(obj)
Old name of RB_ENCODING_GET.
Definition: encoding.h:109
#define LONG2FIX
Old name of RB_INT2FIX.
Definition: long.h:49
#define NUM2UINT
Old name of RB_NUM2UINT.
Definition: int.h:45
#define ALLOC_N
Old name of RB_ALLOC_N.
Definition: memory.h:394
#define MBCLEN_CHARFOUND_LEN(ret)
Old name of ONIGENC_MBCLEN_CHARFOUND_LEN.
Definition: encoding.h:517
#define LONG2NUM
Old name of RB_LONG2NUM.
Definition: long.h:50
#define rb_exc_new3
Old name of rb_exc_new_str.
Definition: error.h:38
#define STRNCASECMP
Old name of st_locale_insensitive_strncasecmp.
Definition: ctype.h:103
#define MBCLEN_INVALID_P(ret)
Old name of ONIGENC_MBCLEN_INVALID_P.
Definition: encoding.h:518
#define ISASCII
Old name of rb_isascii.
Definition: ctype.h:85
#define ECONV_STATEFUL_DECORATOR_MASK
Old name of RUBY_ECONV_STATEFUL_DECORATOR_MASK.
Definition: transcode.h:538
#define Qtrue
Old name of RUBY_Qtrue.
#define MBCLEN_NEEDMORE_P(ret)
Old name of ONIGENC_MBCLEN_NEEDMORE_P.
Definition: encoding.h:519
#define ECONV_PARTIAL_INPUT
Old name of RUBY_ECONV_PARTIAL_INPUT.
Definition: transcode.h:554
#define NUM2INT
Old name of RB_NUM2INT.
Definition: int.h:44
#define ECONV_ERROR_HANDLER_MASK
Old name of RUBY_ECONV_ERROR_HANDLER_MASK.
Definition: transcode.h:522
#define INT2NUM
Old name of RB_INT2NUM.
Definition: int.h:43
#define Qnil
Old name of RUBY_Qnil.
#define Qfalse
Old name of RUBY_Qfalse.
#define FIX2LONG
Old name of RB_FIX2LONG.
Definition: long.h:46
#define ENC_CODERANGE_BROKEN
Old name of RUBY_ENC_CODERANGE_BROKEN.
Definition: coderange.h:182
#define T_ARRAY
Old name of RUBY_T_ARRAY.
Definition: value_type.h:56
#define NIL_P
Old name of RB_NIL_P.
#define ALLOCV_N
Old name of RB_ALLOCV_N.
Definition: memory.h:400
#define MBCLEN_CHARFOUND_P(ret)
Old name of ONIGENC_MBCLEN_CHARFOUND_P.
Definition: encoding.h:516
#define ECONV_NEWLINE_DECORATOR_READ_MASK
Old name of RUBY_ECONV_NEWLINE_DECORATOR_READ_MASK.
Definition: transcode.h:530
#define NUM2CHR
Old name of RB_NUM2CHR.
Definition: char.h:33
#define NUM2LONG
Old name of RB_NUM2LONG.
Definition: long.h:51
#define UINT2NUM
Old name of RB_UINT2NUM.
Definition: int.h:46
#define FIXNUM_P
Old name of RB_FIXNUM_P.
#define ECONV_NEWLINE_DECORATOR_MASK
Old name of RUBY_ECONV_NEWLINE_DECORATOR_MASK.
Definition: transcode.h:529
#define CONST_ID
Old name of RUBY_CONST_ID.
Definition: symbol.h:47
#define rb_ary_new2
Old name of rb_ary_new_capa.
Definition: array.h:657
#define NUM2SIZET
Old name of RB_NUM2SIZE.
Definition: size_t.h:61
#define ENC_CODERANGE_SET(obj, cr)
Old name of RB_ENC_CODERANGE_SET.
Definition: coderange.h:186
#define rb_str_new4
Old name of rb_str_new_frozen.
Definition: string.h:1677
#define ALLOCV_END
Old name of RB_ALLOCV_END.
Definition: memory.h:401
#define SYMBOL_P
Old name of RB_SYMBOL_P.
Definition: value_type.h:88
#define ECONV_DEFAULT_NEWLINE_DECORATOR
Old name of RUBY_ECONV_DEFAULT_NEWLINE_DECORATOR.
Definition: transcode.h:540
void rb_notimplement(void)
Definition: error.c:3670
void rb_category_warn(rb_warning_category_t category, const char *fmt,...)
Identical to rb_category_warning(), except it reports unless $VERBOSE is nil.
Definition: error.c:475
void rb_raise(VALUE exc, const char *fmt,...)
Exception entry point.
Definition: error.c:3627
void rb_category_warning(rb_warning_category_t category, const char *fmt,...)
Identical to rb_warning(), except it takes additional "category" parameter.
Definition: error.c:507
VALUE rb_rescue2(VALUE(*b_proc)(VALUE), VALUE data1, VALUE(*r_proc)(VALUE, VALUE), VALUE data2,...)
An equivalent of rescue clause.
Definition: eval.c:945
VALUE rb_eNotImpError
NotImplementedError exception.
Definition: error.c:1413
void rb_exc_raise(VALUE mesg)
Raises an exception in the current thread.
Definition: eval.c:676
void rb_syserr_fail(int e, const char *mesg)
Raises appropriate exception that represents a C errno.
Definition: error.c:3739
void rb_bug(const char *fmt,...)
Interpreter panic switch.
Definition: error.c:1088
void rb_sys_fail(const char *mesg)
Converts a C errno into a Ruby exception, then raises it.
Definition: error.c:3752
void rb_readwrite_syserr_fail(enum rb_io_wait_readwrite waiting, int n, const char *mesg)
Identical to rb_readwrite_sys_fail(), except it does not depend on C global variable errno.
Definition: io.c:14624
VALUE rb_eIOError
IOError exception.
Definition: io.c:189
VALUE rb_eStandardError
StandardError exception.
Definition: error.c:1400
void rb_mod_syserr_fail_str(VALUE mod, int e, VALUE mesg)
Identical to rb_mod_syserr_fail(), except it takes the message in Ruby's String instead of C's.
Definition: error.c:3829
void rb_syserr_fail_str(int e, VALUE mesg)
Identical to rb_syserr_fail(), except it takes the message in Ruby's String instead of C's.
Definition: error.c:3745
#define ruby_verbose
This variable controls whether the interpreter is in debug mode.
Definition: error.h:471
VALUE rb_eTypeError
TypeError exception.
Definition: error.c:1403
VALUE rb_eEOFError
EOFError exception.
Definition: io.c:188
void rb_fatal(const char *fmt,...)
Raises the unsung "fatal" exception.
Definition: error.c:3678
void rb_readwrite_sys_fail(enum rb_io_wait_readwrite waiting, const char *mesg)
Raises appropriate exception using the parameters.
Definition: io.c:14618
void rb_iter_break_value(VALUE val)
Identical to rb_iter_break(), except it additionally takes the "value" of this breakage.
Definition: vm.c:2073
rb_io_wait_readwrite
for rb_readwrite_sys_fail first argument
Definition: error.h:69
VALUE rb_eRuntimeError
RuntimeError exception.
Definition: error.c:1401
void rb_warn(const char *fmt,...)
Identical to rb_warning(), except it reports unless $VERBOSE is nil.
Definition: error.c:465
VALUE rb_eArgError
ArgumentError exception.
Definition: error.c:1404
VALUE rb_ensure(VALUE(*b_proc)(VALUE), VALUE data1, VALUE(*e_proc)(VALUE), VALUE data2)
An equivalent to ensure clause.
Definition: eval.c:1045
void rb_sys_fail_str(VALUE mesg)
Identical to rb_sys_fail(), except it takes the message in Ruby's String instead of C's.
Definition: error.c:3759
VALUE rb_eSystemCallError
SystemCallError exception.
Definition: error.c:1423
@ RB_WARN_CATEGORY_DEPRECATED
Warning is for deprecated features.
Definition: error.h:48
VALUE rb_mKernel
Kernel module.
Definition: object.c:65
VALUE rb_check_to_int(VALUE val)
Identical to rb_check_to_integer(), except it uses #to_int for conversion.
Definition: object.c:3192
VALUE rb_any_to_s(VALUE obj)
Generates a textual representation of the given object.
Definition: object.c:667
VALUE rb_obj_alloc(VALUE klass)
Allocates an instance of the given class.
Definition: object.c:2091
VALUE rb_class_new_instance(int argc, const VALUE *argv, VALUE klass)
Allocates, then initialises an instance of the given class.
Definition: object.c:2132
VALUE rb_cIO
IO class.
Definition: io.c:187
VALUE rb_class_new_instance_kw(int argc, const VALUE *argv, VALUE klass, int kw_splat)
Identical to rb_class_new_instance(), except you can specify how to handle the last element of the gi...
Definition: object.c:2120
VALUE rb_mEnumerable
Enumerable module.
Definition: enum.c:27
VALUE rb_stdin
STDIN constant.
Definition: io.c:201
VALUE rb_stderr
STDERR constant.
Definition: io.c:201
VALUE rb_obj_class(VALUE obj)
Queries the class of an object.
Definition: object.c:247
VALUE rb_obj_dup(VALUE obj)
Duplicates the given object.
Definition: object.c:574
VALUE rb_inspect(VALUE obj)
Generates a human-readable textual representation of the given object.
Definition: object.c:678
VALUE rb_mWaitReadable
IO::WaitReadable module.
Definition: io.c:191
VALUE rb_mWaitWritable
IO::WaitReadable module.
Definition: io.c:192
VALUE rb_obj_freeze(VALUE obj)
Just calls rb_obj_freeze_inline() inside.
Definition: object.c:1258
VALUE rb_check_to_integer(VALUE val, const char *mid)
Identical to rb_check_convert_type(), except the return value type is fixed to rb_cInteger.
Definition: object.c:3173
VALUE rb_cFile
File class.
Definition: file.c:175
VALUE rb_stdout
STDOUT constant.
Definition: io.c:201
VALUE rb_to_int(VALUE val)
Identical to rb_check_to_int(), except it raises in case of conversion mismatch.
Definition: object.c:3186
rb_encoding * rb_locale_encoding(void)
Queries the encoding that represents the current locale.
Definition: encoding.c:1508
rb_encoding * rb_default_external_encoding(void)
Queries the "default external" encoding.
Definition: encoding.c:1574
int rb_enc_precise_mbclen(const char *p, const char *e, rb_encoding *enc)
Queries the number of bytes of the character at the passed pointer.
Definition: encoding.c:1176
int rb_to_encoding_index(VALUE obj)
Obtains a encoding index from a wider range of objects (than rb_enc_find_index()).
Definition: encoding.c:261
VALUE rb_enc_associate(VALUE obj, rb_encoding *enc)
Identical to rb_enc_associate_index(), except it takes an encoding itself instead of its index.
Definition: encoding.c:1007
rb_encoding * rb_usascii_encoding(void)
Queries the encoding that represents US-ASCII.
Definition: encoding.c:1472
static char * rb_enc_left_char_head(const char *s, const char *p, const char *e, rb_encoding *enc)
Queries the left boundary of a character.
Definition: encoding.h:683
int rb_utf8_encindex(void)
Identical to rb_utf8_encoding(), except it returns the encoding's index instead of the encoding itsel...
Definition: encoding.c:1466
rb_encoding * rb_default_internal_encoding(void)
Queries the "default internal" encoding.
Definition: encoding.c:1661
rb_encoding * rb_find_encoding(VALUE obj)
Identical to rb_to_encoding_index(), except the return type.
Definition: encoding.c:330
rb_encoding * rb_to_encoding(VALUE obj)
Identical to rb_find_encoding(), except it raises an exception instead of returning NULL.
Definition: encoding.c:323
rb_encoding * rb_ascii8bit_encoding(void)
Queries the encoding that represents ASCII-8BIT a.k.a.
Definition: encoding.c:1448
VALUE rb_enc_default_external(void)
Identical to rb_default_external_encoding(), except it returns the Ruby-level counterpart instance of...
Definition: encoding.c:1588
VALUE rb_enc_from_encoding(rb_encoding *enc)
Queries the Ruby-level counterpart instance of rb_cEncoding that corresponds to the passed encoding.
Definition: encoding.c:182
static bool rb_enc_asciicompat(rb_encoding *enc)
Queries if the passed encoding is in some sense compatible with ASCII.
Definition: encoding.h:768
static unsigned int rb_enc_codepoint(const char *p, const char *e, rb_encoding *enc)
Queries the code point of character pointed by the passed pointer.
Definition: encoding.h:571
rb_encoding * rb_enc_from_index(int idx)
Identical to rb_find_encoding(), except it takes an encoding index instead of a Ruby object.
Definition: encoding.c:402
int rb_enc_mbclen(const char *p, const char *e, rb_encoding *enc)
Queries the number of bytes of the character at the passed pointer.
Definition: encoding.c:1164
rb_encoding * rb_enc_get(VALUE obj)
Identical to rb_enc_get_index(), except the return type.
Definition: encoding.c:1013
static const char * rb_enc_name(rb_encoding *enc)
Queries the (canonical) name of the passed encoding.
Definition: encoding.h:417
int rb_enc_find_index(const char *name)
Queries the index of the encoding.
Definition: encoding.c:824
static int rb_enc_mbminlen(rb_encoding *enc)
Queries the minimum number of bytes that the passed encoding needs to represent a character.
Definition: encoding.h:432
int rb_enc_ascget(const char *p, const char *e, int *len, rb_encoding *enc)
Queries the code point of character pointed by the passed pointer.
Definition: encoding.c:1188
VALUE rb_enc_uint_chr(unsigned int code, rb_encoding *enc)
Encodes the passed code point into a series of bytes.
Definition: numeric.c:3803
VALUE rb_enc_str_new(const char *ptr, long len, rb_encoding *enc)
Identical to rb_str_new(), except it additionally takes an encoding.
Definition: string.c:1042
long rb_str_coderange_scan_restartable(const char *str, const char *end, rb_encoding *enc, int *cr)
Scans the passed string until it finds something odd.
Definition: string.c:764
int rb_econv_prepare_options(VALUE opthash, VALUE *ecopts, int ecflags)
Identical to rb_econv_prepare_opts(), except it additionally takes the initial value of flags.
Definition: transcode.c:2600
VALUE rb_econv_open_exc(const char *senc, const char *denc, int ecflags)
Creates a rb_eConverterNotFoundError exception object (but does not raise).
Definition: transcode.c:2097
rb_econv_result_t rb_econv_convert(rb_econv_t *ec, const unsigned char **source_buffer_ptr, const unsigned char *source_buffer_end, unsigned char **destination_buffer_ptr, unsigned char *destination_buffer_end, int flags)
Converts a string from an encoding to another.
Definition: transcode.c:1475
rb_econv_result_t
return value of rb_econv_convert()
Definition: transcode.h:30
@ econv_incomplete_input
The conversion stopped in middle of reading a character, possibly due to a partial read of a socket e...
Definition: transcode.h:69
@ econv_finished
The conversion stopped after converting everything.
Definition: transcode.h:57
@ econv_undefined_conversion
The conversion stopped when it found a character in the input which cannot be representable in the ou...
Definition: transcode.h:41
@ econv_source_buffer_empty
The conversion stopped because there is no input.
Definition: transcode.h:51
@ econv_destination_buffer_full
The conversion stopped because there is no destination.
Definition: transcode.h:46
@ econv_invalid_byte_sequence
The conversion stopped when it found an invalid sequence.
Definition: transcode.h:35
int rb_econv_putbackable(rb_econv_t *ec)
Queries if rb_econv_putback() makes sense, i.e.
Definition: transcode.c:1770
VALUE rb_econv_str_convert(rb_econv_t *ec, VALUE src, int flags)
Identical to rb_econv_convert(), except it takes Ruby's string instead of C's pointer.
Definition: transcode.c:1931
void rb_econv_binmode(rb_econv_t *ec)
This badly named function does not set the destination encoding to binary, but instead just nullifies...
Definition: transcode.c:1996
VALUE rb_str_encode(VALUE str, VALUE to, int ecflags, VALUE ecopts)
Converts the contents of the passed string from its encoding to the passed one.
Definition: transcode.c:2914
VALUE rb_econv_make_exception(rb_econv_t *ec)
This function makes sense right after rb_econv_convert() returns.
Definition: transcode.c:4272
void rb_econv_check_error(rb_econv_t *ec)
This is a rb_econv_make_exception() + rb_exc_raise() combo.
Definition: transcode.c:4278
const char * rb_econv_asciicompat_encoding(const char *encname)
Queries the passed encoding's corresponding ASCII compatible encoding.
Definition: transcode.c:1814
rb_econv_t * rb_econv_open_opts(const char *source_encoding, const char *destination_encoding, int ecflags, VALUE ecopts)
Identical to rb_econv_open(), except it additionally takes a hash of optional strings.
Definition: transcode.c:2651
void rb_econv_close(rb_econv_t *ec)
Destructs a converter.
Definition: transcode.c:1731
void rb_econv_putback(rb_econv_t *ec, unsigned char *p, int n)
Puts back the bytes.
Definition: transcode.c:1781
VALUE rb_funcall(VALUE recv, ID mid, int n,...)
Calls a method.
Definition: vm_eval.c:1099
VALUE rb_funcallv_kw(VALUE recv, ID mid, int argc, const VALUE *argv, int kw_splat)
Identical to rb_funcallv(), except you can specify how to handle the last element of the given array.
Definition: vm_eval.c:1066
VALUE rb_funcallv(VALUE recv, ID mid, int argc, const VALUE *argv)
Identical to rb_funcall(), except it takes the method arguments as a C array.
Definition: vm_eval.c:1058
void rb_gc_mark(VALUE obj)
Marks an object.
Definition: gc.c:2094
void rb_gc(void)
Triggers a GC process.
Definition: gc.c:3370
void rb_global_variable(VALUE *)
An alias for rb_gc_register_address().
Definition: gc.c:2842
Defines RBIMPL_HAS_BUILTIN.
VALUE rb_ary_concat(VALUE lhs, VALUE rhs)
Destructively appends the contents of latter into the end of former.
Definition: array.c:4981
VALUE rb_ary_shift(VALUE ary)
Destructively deletes an element from the beginning of the passed array and returns what was deleted.
Definition: array.c:1496
VALUE rb_check_array_type(VALUE obj)
Try converting an object to its array representation using its to_ary method, if any.
Definition: array.c:1014
VALUE rb_ary_new(void)
Allocates a new, empty array.
Definition: array.c:747
VALUE rb_ary_push(VALUE ary, VALUE elem)
Special case of rb_ary_cat() that it adds only one element.
Definition: array.c:1384
VALUE rb_ary_entry(VALUE ary, long off)
Queries an element of an array.
Definition: array.c:1737
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Identical to rb_ary_new_from_values(), except it expects exactly two parameters.
Definition: array.c:1001
#define RETURN_ENUMERATOR(obj, argc, argv)
Identical to RETURN_SIZED_ENUMERATOR(), except its size is unknown.
Definition: enumerator.h:239
static int rb_check_arity(int argc, int min, int max)
Ensures that the passed integer is in the passed range.
Definition: error.h:284
ID rb_frame_this_func(void)
Queries the name of the Ruby level method that is calling this function.
Definition: eval.c:1094
void rb_jump_tag(int state)
This function is to re-throw global escapes.
Definition: eval.c:907
VALUE rb_str_encode_ospath(VALUE path)
Converts a string into an "OS Path" encoding, if any.
Definition: file.c:252
VALUE rb_check_hash_type(VALUE obj)
Try converting an object to its hash representation using its to_hash method, if any.
Definition: hash.c:1864
VALUE rb_hash_lookup2(VALUE hash, VALUE key, VALUE def)
Identical to rb_hash_lookup(), except you can specify what to return on misshits.
Definition: hash.c:2086
VALUE rb_hash_aref(VALUE hash, VALUE key)
Queries the given key in the given hash table.
Definition: hash.c:2073
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
Inserts or replaces ("upsert"s) the objects into the given hash table.
Definition: hash.c:2893
VALUE rb_hash_lookup(VALUE hash, VALUE key)
Identical to rb_hash_aref(), except it always returns RUBY_Qnil for misshits.
Definition: hash.c:2099
VALUE rb_hash_dup(VALUE hash)
Duplicates a hash.
Definition: hash.c:1563
VALUE rb_hash_new(void)
Creates a new, empty hash object.
Definition: hash.c:1475
VALUE rb_io_printf(int argc, const VALUE *argv, VALUE io)
This is a rb_f_sprintf() + rb_io_write() combo.
Definition: io.c:8564
VALUE rb_io_gets(VALUE io)
Reads a "line" from the given IO.
Definition: io.c:4260
int rb_cloexec_pipe(int fildes[2])
Opens a pipe with closing on exec.
Definition: io.c:427
VALUE rb_rs
The record separator character for inputs, or the $/.
Definition: io.c:205
VALUE rb_io_print(int argc, const VALUE *argv, VALUE io)
Iterates over the passed array to apply rb_io_write() individually.
Definition: io.c:8690
VALUE rb_io_addstr(VALUE io, VALUE str)
Identical to rb_io_write(), except it always returns the passed IO.
Definition: io.c:2342
void rb_write_error(const char *str)
Writes the given error message to somewhere applicable.
Definition: io.c:9119
VALUE rb_io_ungetbyte(VALUE io, VALUE b)
Identical to rb_io_ungetc(), except it doesn't take the encoding of the passed IO into account.
Definition: io.c:5129
VALUE rb_io_getbyte(VALUE io)
Reads a byte from the given IO.
Definition: io.c:5035
VALUE rb_io_puts(int argc, const VALUE *argv, VALUE io)
Iterates over the passed array to apply rb_io_write() individually.
Definition: io.c:8922
int rb_cloexec_dup2(int oldfd, int newfd)
Identical to rb_cloexec_dup(), except you can specify the destination file descriptor.
Definition: io.c:374
VALUE rb_io_fdopen(int fd, int flags, const char *path)
Creates an IO instance whose backend is the given file descriptor.
Definition: io.c:9295
void rb_update_max_fd(int fd)
Informs the interpreter that the passed fd can be the max.
Definition: io.c:248
VALUE rb_io_write(VALUE io, VALUE str)
Writes the given string to the given IO.
Definition: io.c:2294
int rb_cloexec_open(const char *pathname, int flags, mode_t mode)
Opens a file that closes on exec.
Definition: io.c:328
VALUE rb_output_rs
The record separator character for outputs, or the $\.
Definition: io.c:206
VALUE rb_io_eof(VALUE io)
Queries if the passed IO is at the end of file.
Definition: io.c:2687
void rb_write_error2(const char *str, long len)
Identical to rb_write_error(), except it additionally takes the message's length.
Definition: io.c:9099
void rb_close_before_exec(int lowfd, int maxhint, VALUE noclose_fds)
Closes everything.
int rb_reserved_fd_p(int fd)
Queries if the given FD is reserved or not.
void rb_fd_fix_cloexec(int fd)
Sets or clears the close-on-exec flag of the passed file descriptor to the desired state.
Definition: io.c:298
VALUE rb_io_flush(VALUE io)
Flushes any buffered data within the passed IO to the underlying operating system.
Definition: io.c:2398
VALUE rb_io_ascii8bit_binmode(VALUE io)
Forces no conversions be applied to the passed IO.
Definition: io.c:6342
VALUE rb_io_binmode(VALUE io)
Sets the binmode.
Definition: io.c:6296
VALUE rb_io_ungetc(VALUE io, VALUE c)
"Unget"s a string.
Definition: io.c:5193
int rb_pipe(int *pipes)
This is an rb_cloexec_pipe() + rb_update_max_fd() combo.
Definition: io.c:7343
VALUE rb_gets(void)
Much like rb_io_gets(), but it reads from the mysterious ARGF object.
Definition: io.c:10364
int rb_cloexec_fcntl_dupfd(int fd, int minfd)
Duplicates a file descriptor with closing on exec.
Definition: io.c:461
VALUE rb_output_fs
The field separator character for outputs, or the $,.
Definition: io.c:204
VALUE rb_file_open_str(VALUE fname, const char *fmode)
Identical to rb_file_open(), except it takes the pathname as a Ruby's string instead of C's.
Definition: io.c:7226
int rb_cloexec_dup(int oldfd)
Identical to rb_cloexec_fcntl_dupfd(), except it implies minfd is 3.
Definition: io.c:367
VALUE rb_file_open(const char *fname, const char *fmode)
Opens a file located at the given path.
Definition: io.c:7233
VALUE rb_io_close(VALUE io)
Closes the IO.
Definition: io.c:5716
VALUE rb_default_rs
This is the default value of rb_rs, i.e.
Definition: io.c:207
void rb_lastline_set(VALUE str)
Updates $_.
Definition: vm.c:1835
VALUE rb_lastline_get(void)
Queries the last line, or the $_.
Definition: vm.c:1829
int rb_obj_method_arity(VALUE obj, ID mid)
Identical to rb_mod_method_arity(), except it searches for singleton methods rather than instance met...
Definition: proc.c:2900
VALUE rb_protect(VALUE(*func)(VALUE args), VALUE args, int *state)
Protects a function call from potential global escapes from the function.
rb_pid_t rb_waitpid(rb_pid_t pid, int *status, int flags)
Waits for a process, with releasing GVL.
Definition: process.c:1269
void rb_last_status_set(int status, rb_pid_t pid)
Sets the "last status", or the $?.
Definition: process.c:682
VALUE rb_str_append(VALUE dst, VALUE src)
Identical to rb_str_buf_append(), except it converts the right hand side before concatenating.
Definition: string.c:3662
VALUE rb_str_buf_cat(VALUE, const char *, long)
Just another name of rb_str_cat.
size_t rb_str_capacity(VALUE str)
Queries the capacity of the given string.
Definition: string.c:934
VALUE rb_str_new_frozen(VALUE str)
Creates a frozen copy of the string, if necessary.
Definition: string.c:1446
VALUE rb_str_cat2(VALUE, const char *)
Just another name of rb_str_cat_cstr.
VALUE rb_str_dup(VALUE str)
Duplicates a string.
Definition: string.c:1911
void rb_str_modify(VALUE str)
Declares that the string is about to be modified.
Definition: string.c:2642
VALUE rb_str_cat(VALUE dst, const char *src, long srclen)
Destructively appends the passed contents to the string.
Definition: string.c:3430
VALUE rb_str_locktmp(VALUE str)
Obtains a "temporary lock" of the string.
VALUE rb_usascii_str_new(const char *ptr, long len)
Identical to rb_str_new(), except it generates a string of "US ASCII" encoding.
Definition: string.c:1026
rb_gvar_setter_t rb_str_setter
This is a rb_gvar_setter_t that refutes non-string assignments.
Definition: string.h:1146
void rb_str_set_len(VALUE str, long len)
Overwrites the length of the string.
Definition: string.c:3254
VALUE rb_str_buf_cat_ascii(VALUE dst, const char *src)
Identical to rb_str_cat_cstr(), except it additionally assumes the source string be a NUL terminated ...
Definition: string.c:3604
VALUE rb_str_new(const char *ptr, long len)
Allocates an instance of rb_cString.
Definition: string.c:1020
VALUE rb_check_string_type(VALUE obj)
Try converting an object to its stringised representation using its to_str method,...
Definition: string.c:2845
VALUE rb_str_substr(VALUE str, long beg, long len)
This is the implementation of two-argumented String#slice.
Definition: string.c:3141
VALUE rb_str_unlocktmp(VALUE str)
Releases a lock formerly obtained by rb_str_locktmp().
Definition: string.c:3237
VALUE rb_str_new_cstr(const char *ptr)
Identical to rb_str_new(), except it assumes the passed pointer is a pointer to a C string.
Definition: string.c:1054
VALUE rb_str_resize(VALUE str, long len)
Overwrites the length of the string.
Definition: string.c:3302
void rb_str_modify_expand(VALUE str, long capa)
Identical to rb_str_modify(), except it additionally expands the capacity of the receiver.
Definition: string.c:2650
VALUE rb_str_buf_new(long capa)
Allocates a "string buffer".
Definition: string.c:1627
VALUE rb_obj_as_string(VALUE obj)
Try converting an object to its stringised representation using its to_s method, if any.
Definition: string.c:1770
int rb_thread_interrupted(VALUE thval)
Checks if the thread's execution was recently interrupted.
Definition: thread.c:1433
VALUE rb_mutex_new(void)
Creates a mutex.
Definition: thread_sync.c:191
int rb_thread_fd_writable(int fd)
Identical to rb_thread_wait_fd(), except it blocks the current thread until the given file descriptor...
Definition: io.c:1595
VALUE rb_exec_recursive(VALUE(*f)(VALUE g, VALUE h, int r), VALUE g, VALUE h)
"Recursion" API entry point.
void rb_thread_fd_close(int fd)
Notifies a closing of a file descriptor to other threads.
Definition: thread.c:2678
VALUE rb_mutex_synchronize(VALUE mutex, VALUE(*func)(VALUE arg), VALUE arg)
Obtains the lock, runs the passed function, and releases the lock when it completes.
Definition: thread_sync.c:634
void rb_thread_check_ints(void)
Checks for interrupts.
Definition: thread.c:1416
VALUE rb_thread_current(void)
Obtains the "current" thread.
Definition: thread.c:2955
int rb_thread_wait_fd(int fd)
Blocks the current thread until the given file descriptor is ready to be read.
Definition: io.c:1589
void rb_thread_sleep(int sec)
Blocks for the given period of time.
Definition: thread.c:1439
struct timeval rb_time_interval(VALUE num)
Creates a "time interval".
Definition: time.c:2890
VALUE rb_attr_get(VALUE obj, ID name)
Identical to rb_ivar_get()
Definition: variable.c:1358
void rb_set_class_path(VALUE klass, VALUE space, const char *name)
Names a class.
Definition: variable.c:353
VALUE rb_ivar_set(VALUE obj, ID name, VALUE val)
Identical to rb_iv_set(), except it accepts the name as an ID instead of a C string.
Definition: variable.c:1859
VALUE rb_class_name(VALUE obj)
Queries the name of the given object's class.
Definition: variable.c:412
int rb_respond_to(VALUE obj, ID mid)
Queries if the object responds to the method.
Definition: vm_method.c:2955
int rb_method_basic_definition_p(VALUE klass, ID mid)
Well...
Definition: vm_method.c:2833
VALUE rb_check_funcall(VALUE recv, ID mid, int argc, const VALUE *argv)
Identical to rb_funcallv(), except it returns RUBY_Qundef instead of raising rb_eNoMethodError.
Definition: vm_eval.c:668
void rb_define_alloc_func(VALUE klass, rb_alloc_func_t func)
Sets the allocator function of a class.
static ID rb_intern_const(const char *str)
This is a "tiny optimisation" over rb_intern().
Definition: symbol.h:276
const char * rb_id2name(ID id)
Retrieves the name mapped to the given id.
Definition: symbol.c:992
ID rb_intern(const char *name)
Finds or creates a symbol of the given name.
Definition: symbol.c:823
#define RB_ID2SYM
Just another name of rb_id2sym.
Definition: symbol.h:42
VALUE rb_id2str(ID id)
Identical to rb_id2name(), except it returns a Ruby's String instead of C's.
Definition: symbol.c:986
void rb_define_global_const(const char *name, VALUE val)
Identical to rb_define_const(), except it defines that of "global", i.e.
Definition: variable.c:3727
void rb_define_readonly_variable(const char *name, const VALUE *var)
Identical to rb_define_variable(), except it does not allow Ruby programs to assign values to such gl...
Definition: variable.c:732
rb_gvar_setter_t rb_gvar_readonly_setter
This function just raises rb_eNameError.
Definition: variable.h:135
void rb_define_virtual_variable(const char *name, rb_gvar_getter_t *getter, rb_gvar_setter_t *setter)
Defines a global variable that is purely function-backended.
Definition: variable.c:738
void rb_define_const(VALUE klass, const char *name, VALUE val)
Defines a Ruby level constant under a namespace.
Definition: variable.c:3713
void rb_define_hooked_variable(const char *name, VALUE *var, rb_gvar_getter_t *getter, rb_gvar_setter_t *setter)
Identical to rb_define_virtual_variable(), but can also specify a storage.
Definition: variable.c:707
#define FMODE_READABLE
The IO is opened for reading.
Definition: io.h:270
int rb_io_modestr_fmode(const char *modestr)
Maps a file mode string (that rb_file_open() takes) into a mixture of FMODE_ flags.
Definition: io.c:6428
VALUE rb_io_get_io(VALUE io)
Identical to rb_io_check_io(), except it raises exceptions on conversion failures.
Definition: io.c:810
VALUE rb_io_timeout(VALUE io)
Get the timeout associated with the specified io object.
Definition: io.c:856
VALUE rb_io_taint_check(VALUE obj)
Definition: io.c:780
void rb_io_read_check(rb_io_t *fptr)
Blocks until there is a pending read in the passed IO.
Definition: io.c:1067
int rb_io_modestr_oflags(const char *modestr)
Identical to rb_io_modestr_fmode(), except it returns a mixture of O_ flags.
Definition: io.c:6561
#define FMODE_SETENC_BY_BOM
This flag amends the encoding of the IO so that the BOM of the contents of the IO takes effect.
Definition: io.h:368
int rb_io_mode(VALUE io)
Get the mode of the IO.
Definition: io.c:2910
rb_io_event
Type of events that an IO can wait.
Definition: io.h:81
@ RUBY_IO_READABLE
IO::READABLE
Definition: io.h:82
@ RUBY_IO_PRIORITY
IO::PRIORITY
Definition: io.h:84
@ RUBY_IO_WRITABLE
IO::WRITABLE
Definition: io.h:83
#define FMODE_READWRITE
The IO is opened for both read/write.
Definition: io.h:276
#define FMODE_EXTERNAL
This flag means that an IO object is wrapping an "external" file descriptor, which is owned by someth...
Definition: io.h:360
#define GetOpenFile
This is an old name of RB_IO_POINTER.
Definition: io.h:402
void rb_io_check_byte_readable(rb_io_t *fptr)
Asserts that an IO is opened for byte-based reading.
Definition: io.c:1013
#define FMODE_TTY
The IO is a TTY.
Definition: io.h:300
#define FMODE_CREATE
The IO is opened for creating.
Definition: io.h:323
void rb_io_check_readable(rb_io_t *fptr)
Just another name of rb_io_check_byte_readable.
Definition: io.c:1022
int rb_io_extract_encoding_option(VALUE opt, rb_encoding **enc_p, rb_encoding **enc2_p, int *fmode_p)
This function breaks down the option hash that IO#initialize takes into components.
Definition: io.c:6710
FILE * rb_io_stdio_file(rb_io_t *fptr)
Finds or creates a stdio's file structure from a Ruby's one.
Definition: io.c:9341
int rb_wait_for_single_fd(int fd, int events, struct timeval *tv)
Blocks until the passed file descriptor is ready for the passed events.
Definition: io.c:1583
int rb_io_descriptor(VALUE io)
Returns an integer representing the numeric file descriptor for io.
Definition: io.c:2890
#define FMODE_WRITABLE
The IO is opened for writing.
Definition: io.h:273
#define FMODE_APPEND
The IO is opened for appending.
Definition: io.h:315
#define MakeOpenFile
This is an old name of RB_IO_OPEN.
Definition: io.h:425
#define FMODE_DUPLEX
Ruby eventually detects that the IO is bidirectional.
Definition: io.h:308
#define FMODE_BINMODE
The IO is in "binary mode".
Definition: io.h:287
int rb_io_maybe_wait_readable(int error, VALUE io, VALUE timeout)
Blocks until the passed IO is ready for reading, if that makes sense for the passed errno.
Definition: io.c:1642
int capa
Designed capacity of the buffer.
Definition: io.h:11
#define RB_IO_POINTER(obj, fp)
Queries the underlying IO pointer.
Definition: io.h:396
VALUE rb_io_maybe_wait(int error, VALUE io, VALUE events, VALUE timeout)
Identical to rb_io_wait() except it additionally takes previous errno.
Definition: io.c:1601
VALUE rb_eIOTimeoutError
Indicates that a timeout has occurred while performing an IO operation.
Definition: io.c:190
char * ptr
Pointer to the underlying memory region, of at least capa bytes.
Definition: io.h:2
#define FMODE_SYNC
The IO is in "sync mode".
Definition: io.h:294
int off
Offset inside of ptr.
Definition: io.h:5
VALUE rb_io_path(VALUE io)
Returns the path for the given IO.
Definition: io.c:2964
void rb_io_check_initialized(rb_io_t *fptr)
Asserts that the passed IO is initialised.
Definition: io.c:787
#define FMODE_EXCL
This flag amends the effect of FMODE_CREATE, so that if there already is a file at the given path the...
Definition: io.h:331
#define FMODE_TEXTMODE
The IO is in "text mode".
Definition: io.h:351
int rb_io_fptr_finalize(rb_io_t *fptr)
Destroys the given IO.
Definition: io.c:5645
VALUE rb_io_check_io(VALUE io)
Try converting an object to its IO representation using its to_io method, if any.
Definition: io.c:816
VALUE rb_io_closed_p(VALUE io)
Returns whether or not the underlying IO is closed.
Definition: io.c:5824
FILE * rb_fdopen(int fd, const char *modestr)
Identical to rb_io_stdio_file(), except it takes file descriptors instead of Ruby's IO.
Definition: io.c:7043
VALUE rb_io_set_timeout(VALUE io, VALUE timeout)
Set the timeout associated with the specified io object.
Definition: io.c:885
ssize_t rb_io_bufwrite(VALUE io, const void *buf, size_t size)
Buffered write to the passed IO.
Definition: io.c:2007
void rb_io_check_char_readable(rb_io_t *fptr)
Asserts that an IO is opened for character-based reading.
Definition: io.c:994
#define FMODE_TRUNC
This flag amends the effect of FMODE_CREATE, so that if there already is a file at the given path it ...
Definition: io.h:337
VALUE rb_io_get_write_io(VALUE io)
Queries the tied IO for writing.
Definition: io.c:822
void rb_io_set_nonblock(rb_io_t *fptr)
Instructs the OS to put its internal file structure into "nonblocking mode".
Definition: io.c:3416
void rb_io_extract_modeenc(VALUE *vmode_p, VALUE *vperm_p, VALUE opthash, int *oflags_p, int *fmode_p, rb_io_enc_t *convconfig_p)
This function can be seen as an extended version of rb_io_extract_encoding_option() that not only con...
Definition: io.c:6835
int rb_io_wait_writable(int fd)
Blocks until the passed file descriptor gets writable.
Definition: io.c:1540
VALUE rb_io_open_descriptor(VALUE klass, int descriptor, int mode, VALUE path, VALUE timeout, struct rb_io_encoding *encoding)
Allocate a new IO object, with the given file descriptor.
Definition: io.c:9212
VALUE rb_io_set_write_io(VALUE io, VALUE w)
Assigns the tied IO for writing.
Definition: io.c:833
void rb_io_check_writable(rb_io_t *fptr)
Asserts that an IO is opened for writing.
Definition: io.c:1046
int rb_io_maybe_wait_writable(int error, VALUE io, VALUE timeout)
Blocks until the passed IO is ready for writing, if that makes sense for the passed errno.
Definition: io.c:1657
void rb_io_check_closed(rb_io_t *fptr)
This badly named function asserts that the passed IO is open.
Definition: io.c:795
int rb_io_wait_readable(int fd)
Blocks until the passed file descriptor gets readable.
Definition: io.c:1506
void rb_io_synchronized(rb_io_t *fptr)
Sets FMODE_SYNC.
Definition: io.c:7330
VALUE rb_io_wait(VALUE io, VALUE events, VALUE timeout)
Blocks until the passed IO is ready for the passed events.
Definition: io.c:1445
int len
Length of the buffer.
Definition: io.h:8
VALUE rb_ractor_stderr(void)
Queries the standard error of the current Ractor that is calling this function.
Definition: ractor.c:2711
VALUE rb_ractor_stdin(void)
Queries the standard input of the current Ractor that is calling this function.
Definition: ractor.c:2687
void rb_ractor_stderr_set(VALUE io)
Assigns an IO to the standard error of the Ractor that is calling this function.
Definition: ractor.c:2747
VALUE rb_ractor_stdout(void)
Queries the standard output of the current Ractor that is calling this function.
Definition: ractor.c:2699
void rb_ractor_stdout_set(VALUE io)
Assigns an IO to the standard output of the Ractor that is calling this function.
Definition: ractor.c:2735
void rb_ractor_stdin_set(VALUE io)
Assigns an IO to the standard input of the Ractor that is calling this function.
Definition: ractor.c:2723
void * rb_thread_call_with_gvl(void *(*func)(void *), void *data1)
(Re-)acquires the GVL.
Definition: thread.c:1889
#define RB_NUM2INT
Just another name of rb_num2int_inline.
Definition: int.h:38
#define RB_INT2NUM
Just another name of rb_int2num_inline.
Definition: int.h:37
VALUE rb_f_sprintf(int argc, const VALUE *argv)
Identical to rb_str_format(), except how the arguments are arranged.
Definition: sprintf.c:208
VALUE rb_sprintf(const char *fmt,...)
Ruby's extended sprintf(3).
Definition: sprintf.c:1217
VALUE rb_str_catf(VALUE dst, const char *fmt,...)
Identical to rb_sprintf(), except it renders the output to the specified object rather than creating ...
Definition: sprintf.c:1240
#define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)
Shim for block function parameters.
Definition: iterator.h:58
VALUE rb_yield_values2(int n, const VALUE *argv)
Identical to rb_yield_values(), except it takes the parameters as a C array instead of variadic argum...
Definition: vm_eval.c:1388
VALUE rb_yield(VALUE val)
Yields the block.
Definition: vm_eval.c:1354
int rb_fd_select(int nfds, rb_fdset_t *rfds, rb_fdset_t *wfds, rb_fdset_t *efds, struct timeval *timeout)
Waits for multiple file descriptors at once.
int rb_fd_isset(int fd, const rb_fdset_t *f)
Queries if the given FD is in the given set.
void rb_fd_term(rb_fdset_t *f)
Destroys the rb_fdset_t, releasing any memory and resources it used.
#define MEMZERO(p, type, n)
Handy macro to erase a region of memory.
Definition: memory.h:355
#define RB_GC_GUARD(v)
Prevents premature destruction of local objects.
Definition: memory.h:162
#define MEMMOVE(p1, p2, type, n)
Handy macro to call memmove.
Definition: memory.h:379
#define NUM2MODET
Converts a C's mode_t into an instance of rb_cInteger.
Definition: mode_t.h:28
#define PRI_OFFT_PREFIX
A rb_sprintf() format prefix to be used for an off_t parameter.
Definition: off_t.h:55
#define OFFT2NUM
Converts a C's off_t into an instance of rb_cInteger.
Definition: off_t.h:33
#define NUM2OFFT
Converts an instance of rb_cNumeric into C's off_t.
Definition: off_t.h:44
#define PIDT2NUM
Converts a C's pid_t into an instance of rb_cInteger.
Definition: pid_t.h:28
#define rb_fd_init
Initialises the :given :rb_fdset_t.
Definition: posix.h:63
#define rb_fd_set
Sets the given fd to the rb_fdset_t.
Definition: posix.h:54
#define RARRAY_LEN
Just another name of rb_array_len.
Definition: rarray.h:51
static int RARRAY_LENINT(VALUE ary)
Identical to rb_array_len(), except it differs for the return type.
Definition: rarray.h:281
#define RARRAY_AREF(a, i)
Definition: rarray.h:403
#define RARRAY_CONST_PTR
Just another name of rb_array_const_ptr.
Definition: rarray.h:52
#define RFILE(obj)
Convenient casting macro.
Definition: rfile.h:50
#define StringValue(v)
Ensures that the parameter object is a String.
Definition: rstring.h:66
static char * RSTRING_END(VALUE str)
Queries the end of the contents pointer of the string.
Definition: rstring.h:442
static char * RSTRING_PTR(VALUE str)
Queries the contents pointer of the string.
Definition: rstring.h:416
#define RSTRING_GETMEM(str, ptrvar, lenvar)
Convenient macro to obtain the contents and length at once.
Definition: rstring.h:488
static long RSTRING_LEN(VALUE str)
Queries the length of the string.
Definition: rstring.h:367
#define StringValueCStr(v)
Identical to StringValuePtr, except it additionally checks for the contents for viability as a C stri...
Definition: rstring.h:89
#define RUBY_TYPED_DEFAULT_FREE
This is a value you can set to rb_data_type_struct::dfree.
Definition: rtypeddata.h:79
#define TypedData_Make_Struct(klass, type, data_type, sval)
Identical to TypedData_Wrap_Struct, except it allocates a new data region internally instead of takin...
Definition: rtypeddata.h:497
VALUE rb_get_argv(void)
Queries the arguments passed to the current process that you can access from Ruby as ARGV.
Definition: io.c:14584
void rb_p(VALUE obj)
Inspects an object.
Definition: io.c:8998
#define FilePathValue(v)
Ensures that the parameter object is a path.
Definition: ruby.h:90
#define errno
Ractor-aware version of errno.
Definition: ruby.h:388
#define RB_SCAN_ARGS_LAST_HASH_KEYWORDS
Treat a final argument as keywords if it is a hash, and not as keywords otherwise.
Definition: scan_args.h:59
#define RB_PASS_CALLED_KEYWORDS
Pass keywords if current method is called with keywords, useful for argument delegation.
Definition: scan_args.h:78
Scheduler APIs.
VALUE rb_fiber_scheduler_current(void)
Identical to rb_fiber_scheduler_get(), except it also returns RUBY_Qnil in case of a blocking fiber.
Definition: scheduler.c:226
VALUE rb_fiber_scheduler_io_pread_memory(VALUE scheduler, VALUE io, rb_off_t from, void *base, size_t size, size_t length)
Non-blocking pread from the passed IO using a native buffer.
Definition: scheduler.c:630
VALUE rb_fiber_scheduler_make_timeout(struct timeval *timeout)
Converts the passed timeout to an expression that rb_fiber_scheduler_block() etc.
Definition: scheduler.c:269
VALUE rb_fiber_scheduler_io_wait_readable(VALUE scheduler, VALUE io)
Non-blocking wait until the passed IO is ready for reading.
Definition: scheduler.c:442
VALUE rb_fiber_scheduler_io_read_memory(VALUE scheduler, VALUE io, void *base, size_t size, size_t length)
Non-blocking read from the passed IO using a native buffer.
Definition: scheduler.c:606
VALUE rb_fiber_scheduler_io_wait(VALUE scheduler, VALUE io, VALUE events, VALUE timeout)
Non-blocking version of rb_io_wait().
Definition: scheduler.c:436
static ssize_t rb_fiber_scheduler_io_result_apply(VALUE result)
Apply an io result to the local thread, returning the value of the original system call that created ...
Definition: scheduler.h:70
VALUE rb_fiber_scheduler_io_selectv(VALUE scheduler, int argc, VALUE *argv)
Non-blocking version of IO.select, argv variant.
Definition: scheduler.c:472
VALUE rb_fiber_scheduler_io_pwrite_memory(VALUE scheduler, VALUE io, rb_off_t from, const void *base, size_t size, size_t length)
Non-blocking pwrite to the passed IO using a native buffer.
Definition: scheduler.c:642
VALUE rb_fiber_scheduler_current_for_thread(VALUE thread)
Identical to rb_fiber_scheduler_current(), except it queries for that of the passed thread instead of...
Definition: scheduler.c:231
VALUE rb_fiber_scheduler_io_write_memory(VALUE scheduler, VALUE io, const void *base, size_t size, size_t length)
Non-blocking write to the passed IO using a native buffer.
Definition: scheduler.c:618
VALUE rb_fiber_scheduler_io_wait_writable(VALUE scheduler, VALUE io)
Non-blocking wait until the passed IO is ready for writing.
Definition: scheduler.c:448
int rb_thread_fd_select(int nfds, rb_fdset_t *rfds, rb_fdset_t *wfds, rb_fdset_t *efds, struct timeval *timeout)
Waits for multiple file descriptors at once.
Definition: thread.c:4306
static bool RB_TEST(VALUE obj)
Emulates Ruby's "if" statement.
@ RUBY_Qfalse
#define RTEST
This is an old name of RB_TEST.
#define _(args)
This was a transition path from K&R to ANSI.
Definition: stdarg.h:35
C99 shim for <stdbool.h>
Ruby's File and IO.
Definition: rfile.h:35
Definition: io.c:236
Definition: win32.h:219
Definition: io.c:7239
This is the struct that holds necessary info for a struct.
Definition: rtypeddata.h:200
The data structure which wraps the fd_set bitmap used by select(2).
Definition: largesize.h:71
Decomposed encoding flags (e.g.
Definition: io.h:119
int ecflags
Flags.
Definition: io.h:129
VALUE ecopts
Flags as Ruby hash.
Definition: io.h:137
rb_encoding * enc2
External encoding.
Definition: io.h:123
rb_encoding * enc
Internal encoding.
Definition: io.h:121
IO buffers.
Definition: io.h:94
char * ptr
Pointer to the underlying memory region, of at least capa bytes.
Definition: io.h:97
int off
Offset inside of ptr.
Definition: io.h:100
int len
Length of the buffer.
Definition: io.h:103
int capa
Designed capacity of the buffer.
Definition: io.h:106
Ruby's IO, metadata and buffers.
Definition: io.h:143
int mode
mode flags: FMODE_XXXs
Definition: io.h:158
rb_io_buffer_t wbuf
Write buffer.
Definition: io.h:178
void(* finalize)(struct rb_io *, int)
finalize proc
Definition: io.h:174
rb_econv_t * readconv
Encoding converter used when reading from this IO.
Definition: io.h:200
rb_econv_t * writeconv
Encoding converter used when writing to this IO.
Definition: io.h:211
struct rb_io_encoding encs
Decomposed encoding flags.
Definition: io.h:196
VALUE self
The IO's Ruby level counterpart.
Definition: io.h:146
VALUE write_lock
This is a Ruby level mutex.
Definition: io.h:248
VALUE timeout
The timeout associated with this IO when performing blocking operations.
Definition: io.h:254
FILE * stdio_file
stdio ptr for read/write, if available.
Definition: io.h:150
VALUE writeconv_pre_ecopts
Value of ::rb_io_t::rb_io_enc_t::ecopts stored right before initialising rb_io_t::writeconv.
Definition: io.h:238
VALUE tied_io_for_writing
Duplex IO object, if set.
Definition: io.h:193
int writeconv_initialized
Whether rb_io_t::writeconv is already set up.
Definition: io.h:224
int fd
file descriptor.
Definition: io.h:154
rb_io_buffer_t rbuf
(Byte) read buffer.
Definition: io.h:185
int lineno
number of lines read
Definition: io.h:166
VALUE writeconv_asciicompat
This is, when set, an instance of rb_cString which holds the "common" encoding.
Definition: io.h:220
rb_io_buffer_t cbuf
rb_io_ungetc() destination.
Definition: io.h:207
rb_pid_t pid
child's pid (for pipes)
Definition: io.h:162
int writeconv_pre_ecflags
Value of ::rb_io_t::rb_io_enc_t::ecflags stored right before initialising rb_io_t::writeconv.
Definition: io.h:231
VALUE pathv
pathname for file
Definition: io.h:170
Definition: io.c:12141
Definition: io.c:1733
intptr_t SIGNED_VALUE
A signed integer type that has the same width with VALUE.
Definition: value.h:63
uintptr_t ID
Type that represents a Ruby identifier such as a variable name.
Definition: value.h:52
uintptr_t VALUE
Type that represents a Ruby object.
Definition: value.h:40
static bool RB_SYMBOL_P(VALUE obj)
Queries if the object is an instance of rb_cSymbol.
Definition: value_type.h:307
static void Check_Type(VALUE v, enum ruby_value_type t)
Identical to RB_TYPE_P(), except it raises exceptions on predication failure.
Definition: value_type.h:433
static bool RB_TYPE_P(VALUE obj, enum ruby_value_type t)
Queries if the given object is of given type.
Definition: value_type.h:376