Ruby  3.1.4p223 (2023-03-30 revision HEAD)
io.c
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 #ifdef _WIN32
20 # include "ruby/ruby.h"
21 # include "ruby/io.h"
22 #endif
23 
24 #include <ctype.h>
25 #include <errno.h>
26 #include <stddef.h>
27 
28 /* non-Linux poll may not work on all FDs */
29 #if defined(HAVE_POLL)
30 # if defined(__linux__)
31 # define USE_POLL 1
32 # endif
33 # if defined(__FreeBSD_version) && __FreeBSD_version >= 1100000
34 # define USE_POLL 1
35 # endif
36 #endif
37 
38 #ifndef USE_POLL
39 # define USE_POLL 0
40 #endif
41 
42 #undef free
43 #define free(x) xfree(x)
44 
45 #if defined(DOSISH) || defined(__CYGWIN__)
46 #include <io.h>
47 #endif
48 
49 #include <sys/types.h>
50 #if defined HAVE_NET_SOCKET_H
51 # include <net/socket.h>
52 #elif defined HAVE_SYS_SOCKET_H
53 # include <sys/socket.h>
54 #endif
55 
56 #if defined(__BOW__) || defined(__CYGWIN__) || defined(_WIN32)
57 # define NO_SAFE_RENAME
58 #endif
59 
60 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__sun) || defined(_nec_ews)
61 # define USE_SETVBUF
62 #endif
63 
64 #ifdef __QNXNTO__
65 #include <unix.h>
66 #endif
67 
68 #include <sys/types.h>
69 #if defined(HAVE_SYS_IOCTL_H) && !defined(_WIN32)
70 #include <sys/ioctl.h>
71 #endif
72 #if defined(HAVE_FCNTL_H) || defined(_WIN32)
73 #include <fcntl.h>
74 #elif defined(HAVE_SYS_FCNTL_H)
75 #include <sys/fcntl.h>
76 #endif
77 
78 #if !HAVE_OFF_T && !defined(off_t)
79 # define off_t long
80 #endif
81 
82 #ifdef HAVE_SYS_TIME_H
83 # include <sys/time.h>
84 #endif
85 
86 #include <sys/stat.h>
87 
88 #if defined(HAVE_SYS_PARAM_H) || defined(__HIUX_MPP__)
89 # include <sys/param.h>
90 #endif
91 
92 #if !defined NOFILE
93 # define NOFILE 64
94 #endif
95 
96 #ifdef HAVE_UNISTD_H
97 #include <unistd.h>
98 #endif
99 
100 #ifdef HAVE_SYSCALL_H
101 #include <syscall.h>
102 #elif defined HAVE_SYS_SYSCALL_H
103 #include <sys/syscall.h>
104 #endif
105 
106 #ifdef HAVE_SYS_UIO_H
107 #include <sys/uio.h>
108 #endif
109 
110 #ifdef HAVE_SYS_WAIT_H
111 # include <sys/wait.h> /* for WNOHANG on BSD */
112 #endif
113 
114 #ifdef HAVE_COPYFILE_H
115 # include <copyfile.h>
116 #endif
117 
118 #include "ruby/internal/stdbool.h"
119 #include "ccan/list/list.h"
120 #include "dln.h"
121 #include "encindex.h"
122 #include "id.h"
123 #include "internal.h"
124 #include "internal/encoding.h"
125 #include "internal/error.h"
126 #include "internal/inits.h"
127 #include "internal/io.h"
128 #include "internal/numeric.h"
129 #include "internal/object.h"
130 #include "internal/process.h"
131 #include "internal/thread.h"
132 #include "internal/transcode.h"
133 #include "internal/variable.h"
134 #include "ruby/io.h"
135 #include "ruby/io/buffer.h"
136 #include "ruby/thread.h"
137 #include "ruby/util.h"
138 #include "ruby_atomic.h"
139 #include "ruby/ractor.h"
140 
141 #if !USE_POLL
142 # include "vm_core.h"
143 #endif
144 
145 #include "builtin.h"
146 
147 #ifndef O_ACCMODE
148 #define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR)
149 #endif
150 
151 #if SIZEOF_OFF_T > SIZEOF_LONG && !defined(HAVE_LONG_LONG)
152 # error off_t is bigger than long, but you have no long long...
153 #endif
154 
155 #ifndef PIPE_BUF
156 # ifdef _POSIX_PIPE_BUF
157 # define PIPE_BUF _POSIX_PIPE_BUF
158 # else
159 # define PIPE_BUF 512 /* is this ok? */
160 # endif
161 #endif
162 
163 #ifndef EWOULDBLOCK
164 # define EWOULDBLOCK EAGAIN
165 #endif
166 
167 #if defined(HAVE___SYSCALL) && (defined(__APPLE__) || defined(__OpenBSD__))
168 /* Mac OS X and OpenBSD have __syscall but don't define it in headers */
169 off_t __syscall(quad_t number, ...);
170 #endif
171 
172 #define IO_RBUF_CAPA_MIN 8192
173 #define IO_CBUF_CAPA_MIN (128*1024)
174 #define IO_RBUF_CAPA_FOR(fptr) (NEED_READCONV(fptr) ? IO_CBUF_CAPA_MIN : IO_RBUF_CAPA_MIN)
175 #define IO_WBUF_CAPA_MIN 8192
176 
177 /* define system APIs */
178 #ifdef _WIN32
179 #undef open
180 #define open rb_w32_uopen
181 #undef rename
182 #define rename(f, t) rb_w32_urename((f), (t))
183 #endif
184 
190 
191 static VALUE rb_eEAGAINWaitReadable;
192 static VALUE rb_eEAGAINWaitWritable;
193 static VALUE rb_eEWOULDBLOCKWaitReadable;
194 static VALUE rb_eEWOULDBLOCKWaitWritable;
195 static VALUE rb_eEINPROGRESSWaitWritable;
196 static VALUE rb_eEINPROGRESSWaitReadable;
197 
199 static VALUE orig_stdout, orig_stderr;
200 
205 
206 static VALUE argf;
207 
208 static ID id_write, id_read, id_getc, id_flush, id_readpartial, id_set_encoding, id_fileno;
209 static VALUE sym_mode, sym_perm, sym_flags, sym_extenc, sym_intenc, sym_encoding, sym_open_args;
210 static VALUE sym_textmode, sym_binmode, sym_autoclose;
211 static VALUE sym_SET, sym_CUR, sym_END;
212 static VALUE sym_wait_readable, sym_wait_writable;
213 #ifdef SEEK_DATA
214 static VALUE sym_DATA;
215 #endif
216 #ifdef SEEK_HOLE
217 static VALUE sym_HOLE;
218 #endif
219 
220 static VALUE prep_io(int fd, int fmode, VALUE klass, const char *path);
221 
222 struct argf {
223  VALUE filename, current_file;
224  long last_lineno; /* $. */
225  long lineno;
226  VALUE argv;
227  VALUE inplace;
228  struct rb_io_enc_t encs;
229  int8_t init_p, next_p, binmode;
230 };
231 
232 static rb_atomic_t max_file_descriptor = NOFILE;
233 void
235 {
236  rb_atomic_t afd = (rb_atomic_t)fd;
237  rb_atomic_t max_fd = max_file_descriptor;
238  int err;
239 
240  if (fd < 0 || afd <= max_fd)
241  return;
242 
243 #if defined(HAVE_FCNTL) && defined(F_GETFL)
244  err = fcntl(fd, F_GETFL) == -1;
245 #else
246  {
247  struct stat buf;
248  err = fstat(fd, &buf) != 0;
249  }
250 #endif
251  if (err && errno == EBADF) {
252  rb_bug("rb_update_max_fd: invalid fd (%d) given.", fd);
253  }
254 
255  while (max_fd < afd) {
256  max_fd = ATOMIC_CAS(max_file_descriptor, max_fd, afd);
257  }
258 }
259 
260 void
261 rb_maygvl_fd_fix_cloexec(int fd)
262 {
263  /* MinGW don't have F_GETFD and FD_CLOEXEC. [ruby-core:40281] */
264 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
265  int flags, flags2, ret;
266  flags = fcntl(fd, F_GETFD); /* should not fail except EBADF. */
267  if (flags == -1) {
268  rb_bug("rb_maygvl_fd_fix_cloexec: fcntl(%d, F_GETFD) failed: %s", fd, strerror(errno));
269  }
270  if (fd <= 2)
271  flags2 = flags & ~FD_CLOEXEC; /* Clear CLOEXEC for standard file descriptors: 0, 1, 2. */
272  else
273  flags2 = flags | FD_CLOEXEC; /* Set CLOEXEC for non-standard file descriptors: 3, 4, 5, ... */
274  if (flags != flags2) {
275  ret = fcntl(fd, F_SETFD, flags2);
276  if (ret != 0) {
277  rb_bug("rb_maygvl_fd_fix_cloexec: fcntl(%d, F_SETFD, %d) failed: %s", fd, flags2, strerror(errno));
278  }
279  }
280 #endif
281 }
282 
283 void
285 {
286  rb_maygvl_fd_fix_cloexec(fd);
287  rb_update_max_fd(fd);
288 }
289 
290 /* this is only called once */
291 static int
292 rb_fix_detect_o_cloexec(int fd)
293 {
294 #if defined(O_CLOEXEC) && defined(F_GETFD)
295  int flags = fcntl(fd, F_GETFD);
296 
297  if (flags == -1)
298  rb_bug("rb_fix_detect_o_cloexec: fcntl(%d, F_GETFD) failed: %s", fd, strerror(errno));
299 
300  if (flags & FD_CLOEXEC)
301  return 1;
302 #endif /* fall through if O_CLOEXEC does not work: */
303  rb_maygvl_fd_fix_cloexec(fd);
304  return 0;
305 }
306 
307 static inline bool
308 io_again_p(int e)
309 {
310  return (e == EWOULDBLOCK) || (e == EAGAIN);
311 }
312 
313 int
314 rb_cloexec_open(const char *pathname, int flags, mode_t mode)
315 {
316  int ret;
317  static int o_cloexec_state = -1; /* <0: unknown, 0: ignored, >0: working */
318 
319  static const int retry_interval = 0;
320  static const int retry_max_count = 10000;
321 
322  int retry_count = 0;
323 
324 #ifdef O_CLOEXEC
325  /* O_CLOEXEC is available since Linux 2.6.23. Linux 2.6.18 silently ignore it. */
326  flags |= O_CLOEXEC;
327 #elif defined O_NOINHERIT
328  flags |= O_NOINHERIT;
329 #endif
330 
331  while ((ret = open(pathname, flags, mode)) == -1) {
332  int e = errno;
333  if (!io_again_p(e)) break;
334  if (retry_count++ >= retry_max_count) break;
335 
336  sleep(retry_interval);
337  }
338 
339  if (ret < 0) return ret;
340  if (ret <= 2 || o_cloexec_state == 0) {
341  rb_maygvl_fd_fix_cloexec(ret);
342  }
343  else if (o_cloexec_state > 0) {
344  return ret;
345  }
346  else {
347  o_cloexec_state = rb_fix_detect_o_cloexec(ret);
348  }
349  return ret;
350 }
351 
352 int
353 rb_cloexec_dup(int oldfd)
354 {
355  /* Don't allocate standard file descriptors: 0, 1, 2 */
356  return rb_cloexec_fcntl_dupfd(oldfd, 3);
357 }
358 
359 int
360 rb_cloexec_dup2(int oldfd, int newfd)
361 {
362  int ret;
363 
364  /* When oldfd == newfd, dup2 succeeds but dup3 fails with EINVAL.
365  * rb_cloexec_dup2 succeeds as dup2. */
366  if (oldfd == newfd) {
367  ret = newfd;
368  }
369  else {
370 #if defined(HAVE_DUP3) && defined(O_CLOEXEC)
371  static int try_dup3 = 1;
372  if (2 < newfd && try_dup3) {
373  ret = dup3(oldfd, newfd, O_CLOEXEC);
374  if (ret != -1)
375  return ret;
376  /* dup3 is available since Linux 2.6.27, glibc 2.9. */
377  if (errno == ENOSYS) {
378  try_dup3 = 0;
379  ret = dup2(oldfd, newfd);
380  }
381  }
382  else {
383  ret = dup2(oldfd, newfd);
384  }
385 #else
386  ret = dup2(oldfd, newfd);
387 #endif
388  if (ret < 0) return ret;
389  }
390  rb_maygvl_fd_fix_cloexec(ret);
391  return ret;
392 }
393 
394 static int
395 rb_fd_set_nonblock(int fd)
396 {
397 #ifdef _WIN32
398  return rb_w32_set_nonblock(fd);
399 #elif defined(F_GETFL)
400  int oflags = fcntl(fd, F_GETFL);
401 
402  if (oflags == -1)
403  return -1;
404  if (oflags & O_NONBLOCK)
405  return 0;
406  oflags |= O_NONBLOCK;
407  return fcntl(fd, F_SETFL, oflags);
408 #endif
409  return 0;
410 }
411 
412 int
413 rb_cloexec_pipe(int descriptors[2])
414 {
415 #ifdef HAVE_PIPE2
416  int result = pipe2(descriptors, O_CLOEXEC | O_NONBLOCK);
417 #else
418  int result = pipe(descriptors);
419 #endif
420 
421  if (result < 0)
422  return result;
423 
424 #ifdef __CYGWIN__
425  if (result == 0 && descriptors[1] == -1) {
426  close(descriptors[0]);
427  descriptors[0] = -1;
428  errno = ENFILE;
429  return -1;
430  }
431 #endif
432 
433 #ifndef HAVE_PIPE2
434  rb_maygvl_fd_fix_cloexec(descriptors[0]);
435  rb_maygvl_fd_fix_cloexec(descriptors[1]);
436 
437 #ifndef _WIN32
438  rb_fd_set_nonblock(descriptors[0]);
439  rb_fd_set_nonblock(descriptors[1]);
440 #endif
441 #endif
442 
443  return result;
444 }
445 
446 int
447 rb_cloexec_fcntl_dupfd(int fd, int minfd)
448 {
449  int ret;
450 
451 #if defined(HAVE_FCNTL) && defined(F_DUPFD_CLOEXEC) && defined(F_DUPFD)
452  static int try_dupfd_cloexec = 1;
453  if (try_dupfd_cloexec) {
454  ret = fcntl(fd, F_DUPFD_CLOEXEC, minfd);
455  if (ret != -1) {
456  if (ret <= 2)
457  rb_maygvl_fd_fix_cloexec(ret);
458  return ret;
459  }
460  /* F_DUPFD_CLOEXEC is available since Linux 2.6.24. Linux 2.6.18 fails with EINVAL */
461  if (errno == EINVAL) {
462  ret = fcntl(fd, F_DUPFD, minfd);
463  if (ret != -1) {
464  try_dupfd_cloexec = 0;
465  }
466  }
467  }
468  else {
469  ret = fcntl(fd, F_DUPFD, minfd);
470  }
471 #elif defined(HAVE_FCNTL) && defined(F_DUPFD)
472  ret = fcntl(fd, F_DUPFD, minfd);
473 #else
474  ret = dup(fd);
475  if (ret >= 0 && ret < minfd) {
476  const int prev_fd = ret;
477  ret = rb_cloexec_fcntl_dupfd(fd, minfd);
478  close(prev_fd);
479  }
480  return ret;
481 #endif
482  if (ret < 0) return ret;
483  rb_maygvl_fd_fix_cloexec(ret);
484  return ret;
485 }
486 
487 #define argf_of(obj) (*(struct argf *)DATA_PTR(obj))
488 #define ARGF argf_of(argf)
489 
490 #define GetWriteIO(io) rb_io_get_write_io(io)
491 
492 #define READ_DATA_PENDING(fptr) ((fptr)->rbuf.len)
493 #define READ_DATA_PENDING_COUNT(fptr) ((fptr)->rbuf.len)
494 #define READ_DATA_PENDING_PTR(fptr) ((fptr)->rbuf.ptr+(fptr)->rbuf.off)
495 #define READ_DATA_BUFFERED(fptr) READ_DATA_PENDING(fptr)
496 
497 #define READ_CHAR_PENDING(fptr) ((fptr)->cbuf.len)
498 #define READ_CHAR_PENDING_COUNT(fptr) ((fptr)->cbuf.len)
499 #define READ_CHAR_PENDING_PTR(fptr) ((fptr)->cbuf.ptr+(fptr)->cbuf.off)
500 
501 #if defined(_WIN32)
502 #define WAIT_FD_IN_WIN32(fptr) \
503  (rb_w32_io_cancelable_p((fptr)->fd) ? Qnil : rb_io_wait(fptr->self, RB_INT2NUM(RUBY_IO_READABLE), Qnil))
504 #else
505 #define WAIT_FD_IN_WIN32(fptr)
506 #endif
507 
508 #define READ_CHECK(fptr) do {\
509  if (!READ_DATA_PENDING(fptr)) {\
510  WAIT_FD_IN_WIN32(fptr);\
511  rb_io_check_closed(fptr);\
512  }\
513 } while(0)
514 
515 #ifndef S_ISSOCK
516 # ifdef _S_ISSOCK
517 # define S_ISSOCK(m) _S_ISSOCK(m)
518 # else
519 # ifdef _S_IFSOCK
520 # define S_ISSOCK(m) (((m) & S_IFMT) == _S_IFSOCK)
521 # else
522 # ifdef S_IFSOCK
523 # define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
524 # endif
525 # endif
526 # endif
527 #endif
528 
529 static int io_fflush(rb_io_t *);
530 static rb_io_t *flush_before_seek(rb_io_t *fptr);
531 
532 #define FMODE_PREP (1<<16)
533 #define FMODE_SIGNAL_ON_EPIPE (1<<17)
534 
535 #define fptr_signal_on_epipe(fptr) \
536  (((fptr)->mode & FMODE_SIGNAL_ON_EPIPE) != 0)
537 
538 #define fptr_set_signal_on_epipe(fptr, flag) \
539  ((flag) ? \
540  (fptr)->mode |= FMODE_SIGNAL_ON_EPIPE : \
541  (fptr)->mode &= ~FMODE_SIGNAL_ON_EPIPE)
542 
543 extern ID ruby_static_id_signo;
544 
545 NORETURN(static void raise_on_write(rb_io_t *fptr, int e, VALUE errinfo));
546 static void
547 raise_on_write(rb_io_t *fptr, int e, VALUE errinfo)
548 {
549 #if defined EPIPE
550  if (fptr_signal_on_epipe(fptr) && (e == EPIPE)) {
551  const VALUE sig =
552 # if defined SIGPIPE
553  INT2FIX(SIGPIPE) - INT2FIX(0) +
554 # endif
555  INT2FIX(0);
556  rb_ivar_set(errinfo, ruby_static_id_signo, sig);
557  }
558 #endif
559  rb_exc_raise(errinfo);
560 }
561 
562 #define rb_sys_fail_on_write(fptr) \
563  do { \
564  int e = errno; \
565  raise_on_write(fptr, e, rb_syserr_new_path(e, (fptr)->pathv)); \
566  } while (0)
567 
568 #define NEED_NEWLINE_DECORATOR_ON_READ(fptr) ((fptr)->mode & FMODE_TEXTMODE)
569 #define NEED_NEWLINE_DECORATOR_ON_WRITE(fptr) ((fptr)->mode & FMODE_TEXTMODE)
570 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
571 # define RUBY_CRLF_ENVIRONMENT 1
572 #else
573 # define RUBY_CRLF_ENVIRONMENT 0
574 #endif
575 
576 #if RUBY_CRLF_ENVIRONMENT
577 /* Windows */
578 # define DEFAULT_TEXTMODE FMODE_TEXTMODE
579 # define TEXTMODE_NEWLINE_DECORATOR_ON_WRITE ECONV_CRLF_NEWLINE_DECORATOR
580 /*
581  * CRLF newline is set as default newline decorator.
582  * If only CRLF newline conversion is needed, we use binary IO process
583  * with OS's text mode for IO performance improvement.
584  * If encoding conversion is needed or a user sets text mode, we use encoding
585  * conversion IO process and universal newline decorator by default.
586  */
587 #define NEED_READCONV(fptr) ((fptr)->encs.enc2 != NULL || (fptr)->encs.ecflags & ~ECONV_CRLF_NEWLINE_DECORATOR)
588 #define WRITECONV_MASK ( \
589  (ECONV_DECORATOR_MASK & ~ECONV_CRLF_NEWLINE_DECORATOR)|\
590  ECONV_STATEFUL_DECORATOR_MASK|\
591  0)
592 #define NEED_WRITECONV(fptr) ( \
593  ((fptr)->encs.enc != NULL && (fptr)->encs.enc != rb_ascii8bit_encoding()) || \
594  ((fptr)->encs.ecflags & WRITECONV_MASK) || \
595  0)
596 #define SET_BINARY_MODE(fptr) setmode((fptr)->fd, O_BINARY)
597 
598 #define NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr) do {\
599  if (NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {\
600  if (((fptr)->mode & FMODE_READABLE) &&\
601  !((fptr)->encs.ecflags & ECONV_NEWLINE_DECORATOR_MASK)) {\
602  setmode((fptr)->fd, O_BINARY);\
603  }\
604  else {\
605  setmode((fptr)->fd, O_TEXT);\
606  }\
607  }\
608 } while(0)
609 
610 #define SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags) do {\
611  if ((enc2) && ((ecflags) & ECONV_DEFAULT_NEWLINE_DECORATOR)) {\
612  (ecflags) |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;\
613  }\
614 } while(0)
615 
616 /*
617  * IO unread with taking care of removed '\r' in text mode.
618  */
619 static void
620 io_unread(rb_io_t *fptr)
621 {
622  off_t r, pos;
623  ssize_t read_size;
624  long i;
625  long newlines = 0;
626  long extra_max;
627  char *p;
628  char *buf;
629 
630  rb_io_check_closed(fptr);
631  if (fptr->rbuf.len == 0 || fptr->mode & FMODE_DUPLEX) {
632  return;
633  }
634 
635  errno = 0;
636  if (!rb_w32_fd_is_text(fptr->fd)) {
637  r = lseek(fptr->fd, -fptr->rbuf.len, SEEK_CUR);
638  if (r < 0 && errno) {
639  if (errno == ESPIPE)
640  fptr->mode |= FMODE_DUPLEX;
641  return;
642  }
643 
644  fptr->rbuf.off = 0;
645  fptr->rbuf.len = 0;
646  return;
647  }
648 
649  pos = lseek(fptr->fd, 0, SEEK_CUR);
650  if (pos < 0 && errno) {
651  if (errno == ESPIPE)
652  fptr->mode |= FMODE_DUPLEX;
653  return;
654  }
655 
656  /* add extra offset for removed '\r' in rbuf */
657  extra_max = (long)(pos - fptr->rbuf.len);
658  p = fptr->rbuf.ptr + fptr->rbuf.off;
659 
660  /* if the end of rbuf is '\r', rbuf doesn't have '\r' within rbuf.len */
661  if (*(fptr->rbuf.ptr + fptr->rbuf.capa - 1) == '\r') {
662  newlines++;
663  }
664 
665  for (i = 0; i < fptr->rbuf.len; i++) {
666  if (*p == '\n') newlines++;
667  if (extra_max == newlines) break;
668  p++;
669  }
670 
671  buf = ALLOC_N(char, fptr->rbuf.len + newlines);
672  while (newlines >= 0) {
673  r = lseek(fptr->fd, pos - fptr->rbuf.len - newlines, SEEK_SET);
674  if (newlines == 0) break;
675  if (r < 0) {
676  newlines--;
677  continue;
678  }
679  read_size = _read(fptr->fd, buf, fptr->rbuf.len + newlines);
680  if (read_size < 0) {
681  int e = errno;
682  free(buf);
683  rb_syserr_fail_path(e, fptr->pathv);
684  }
685  if (read_size == fptr->rbuf.len) {
686  lseek(fptr->fd, r, SEEK_SET);
687  break;
688  }
689  else {
690  newlines--;
691  }
692  }
693  free(buf);
694  fptr->rbuf.off = 0;
695  fptr->rbuf.len = 0;
696  return;
697 }
698 
699 /*
700  * We use io_seek to back cursor position when changing mode from text to binary,
701  * but stdin and pipe cannot seek back. Stdin and pipe read should use encoding
702  * conversion for working properly with mode change.
703  *
704  * Return previous translation mode.
705  */
706 static inline int
707 set_binary_mode_with_seek_cur(rb_io_t *fptr)
708 {
709  if (!rb_w32_fd_is_text(fptr->fd)) return O_BINARY;
710 
711  if (fptr->rbuf.len == 0 || fptr->mode & FMODE_DUPLEX) {
712  return setmode(fptr->fd, O_BINARY);
713  }
714  flush_before_seek(fptr);
715  return setmode(fptr->fd, O_BINARY);
716 }
717 #define SET_BINARY_MODE_WITH_SEEK_CUR(fptr) set_binary_mode_with_seek_cur(fptr)
718 
719 #else
720 /* Unix */
721 # define DEFAULT_TEXTMODE 0
722 #define NEED_READCONV(fptr) ((fptr)->encs.enc2 != NULL || NEED_NEWLINE_DECORATOR_ON_READ(fptr))
723 #define NEED_WRITECONV(fptr) ( \
724  ((fptr)->encs.enc != NULL && (fptr)->encs.enc != rb_ascii8bit_encoding()) || \
725  NEED_NEWLINE_DECORATOR_ON_WRITE(fptr) || \
726  ((fptr)->encs.ecflags & (ECONV_DECORATOR_MASK|ECONV_STATEFUL_DECORATOR_MASK)) || \
727  0)
728 #define SET_BINARY_MODE(fptr) (void)(fptr)
729 #define NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr) (void)(fptr)
730 #define SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags) ((void)(enc2), (void)(ecflags))
731 #define SET_BINARY_MODE_WITH_SEEK_CUR(fptr) (void)(fptr)
732 #endif
733 
734 #if !defined HAVE_SHUTDOWN && !defined shutdown
735 #define shutdown(a,b) 0
736 #endif
737 
738 #if defined(_WIN32)
739 #define is_socket(fd, path) rb_w32_is_socket(fd)
740 #elif !defined(S_ISSOCK)
741 #define is_socket(fd, path) 0
742 #else
743 static int
744 is_socket(int fd, VALUE path)
745 {
746  struct stat sbuf;
747  if (fstat(fd, &sbuf) < 0)
748  rb_sys_fail_path(path);
749  return S_ISSOCK(sbuf.st_mode);
750 }
751 #endif
752 
753 static const char closed_stream[] = "closed stream";
754 
755 static void
756 io_fd_check_closed(int fd)
757 {
758  if (fd < 0) {
759  rb_thread_check_ints(); /* check for ruby_error_stream_closed */
760  rb_raise(rb_eIOError, closed_stream);
761  }
762 }
763 
764 void
765 rb_eof_error(void)
766 {
767  rb_raise(rb_eEOFError, "end of file reached");
768 }
769 
770 VALUE
772 {
773  rb_check_frozen(io);
774  return io;
775 }
776 
777 void
779 {
780  if (!fptr) {
781  rb_raise(rb_eIOError, "uninitialized stream");
782  }
783 }
784 
785 void
787 {
789  io_fd_check_closed(fptr->fd);
790 }
791 
792 static rb_io_t *
793 rb_io_get_fptr(VALUE io)
794 {
795  rb_io_t *fptr = RFILE(io)->fptr;
797  return fptr;
798 }
799 
800 VALUE
802 {
803  return rb_convert_type_with_id(io, T_FILE, "IO", idTo_io);
804 }
805 
806 VALUE
808 {
809  return rb_check_convert_type_with_id(io, T_FILE, "IO", idTo_io);
810 }
811 
812 VALUE
814 {
815  VALUE write_io;
816  write_io = rb_io_get_fptr(io)->tied_io_for_writing;
817  if (write_io) {
818  return write_io;
819  }
820  return io;
821 }
822 
823 VALUE
825 {
826  VALUE write_io;
827  rb_io_t *fptr = rb_io_get_fptr(io);
828  if (!RTEST(w)) {
829  w = 0;
830  }
831  else {
832  GetWriteIO(w);
833  }
834  write_io = fptr->tied_io_for_writing;
835  fptr->tied_io_for_writing = w;
836  return write_io ? write_io : Qnil;
837 }
838 
839 /*
840  * call-seq:
841  * IO.try_convert(object) -> new_io or nil
842  *
843  * Attempts to convert +object+ into an \IO object via method +to_io+;
844  * returns the new \IO object if successful, or +nil+ otherwise:
845  *
846  * IO.try_convert(STDOUT) # => #<IO:<STDOUT>>
847  * IO.try_convert(ARGF) # => #<IO:<STDIN>>
848  * IO.try_convert('STDOUT') # => nil
849  *
850  */
851 static VALUE
852 rb_io_s_try_convert(VALUE dummy, VALUE io)
853 {
854  return rb_io_check_io(io);
855 }
856 
857 #if !RUBY_CRLF_ENVIRONMENT
858 static void
859 io_unread(rb_io_t *fptr)
860 {
861  off_t r;
862  rb_io_check_closed(fptr);
863  if (fptr->rbuf.len == 0 || fptr->mode & FMODE_DUPLEX)
864  return;
865  /* xxx: target position may be negative if buffer is filled by ungetc */
866  errno = 0;
867  r = lseek(fptr->fd, -fptr->rbuf.len, SEEK_CUR);
868  if (r < 0 && errno) {
869  if (errno == ESPIPE)
870  fptr->mode |= FMODE_DUPLEX;
871  return;
872  }
873  fptr->rbuf.off = 0;
874  fptr->rbuf.len = 0;
875  return;
876 }
877 #endif
878 
879 static rb_encoding *io_input_encoding(rb_io_t *fptr);
880 
881 static void
882 io_ungetbyte(VALUE str, rb_io_t *fptr)
883 {
884  long len = RSTRING_LEN(str);
885 
886  if (fptr->rbuf.ptr == NULL) {
887  const int min_capa = IO_RBUF_CAPA_FOR(fptr);
888  fptr->rbuf.off = 0;
889  fptr->rbuf.len = 0;
890 #if SIZEOF_LONG > SIZEOF_INT
891  if (len > INT_MAX)
892  rb_raise(rb_eIOError, "ungetbyte failed");
893 #endif
894  if (len > min_capa)
895  fptr->rbuf.capa = (int)len;
896  else
897  fptr->rbuf.capa = min_capa;
898  fptr->rbuf.ptr = ALLOC_N(char, fptr->rbuf.capa);
899  }
900  if (fptr->rbuf.capa < len + fptr->rbuf.len) {
901  rb_raise(rb_eIOError, "ungetbyte failed");
902  }
903  if (fptr->rbuf.off < len) {
904  MEMMOVE(fptr->rbuf.ptr+fptr->rbuf.capa-fptr->rbuf.len,
905  fptr->rbuf.ptr+fptr->rbuf.off,
906  char, fptr->rbuf.len);
907  fptr->rbuf.off = fptr->rbuf.capa-fptr->rbuf.len;
908  }
909  fptr->rbuf.off-=(int)len;
910  fptr->rbuf.len+=(int)len;
911  MEMMOVE(fptr->rbuf.ptr+fptr->rbuf.off, RSTRING_PTR(str), char, len);
912 }
913 
914 static rb_io_t *
915 flush_before_seek(rb_io_t *fptr)
916 {
917  if (io_fflush(fptr) < 0)
918  rb_sys_fail_on_write(fptr);
919  io_unread(fptr);
920  errno = 0;
921  return fptr;
922 }
923 
924 #define io_seek(fptr, ofs, whence) (errno = 0, lseek(flush_before_seek(fptr)->fd, (ofs), (whence)))
925 #define io_tell(fptr) lseek(flush_before_seek(fptr)->fd, 0, SEEK_CUR)
926 
927 #ifndef SEEK_CUR
928 # define SEEK_SET 0
929 # define SEEK_CUR 1
930 # define SEEK_END 2
931 #endif
932 
933 void
935 {
936  rb_io_check_closed(fptr);
937  if (!(fptr->mode & FMODE_READABLE)) {
938  rb_raise(rb_eIOError, "not opened for reading");
939  }
940  if (fptr->wbuf.len) {
941  if (io_fflush(fptr) < 0)
942  rb_sys_fail_on_write(fptr);
943  }
944  if (fptr->tied_io_for_writing) {
945  rb_io_t *wfptr;
946  GetOpenFile(fptr->tied_io_for_writing, wfptr);
947  if (io_fflush(wfptr) < 0)
948  rb_sys_fail_on_write(wfptr);
949  }
950 }
951 
952 void
954 {
956  if (READ_CHAR_PENDING(fptr)) {
957  rb_raise(rb_eIOError, "byte oriented read for character buffered IO");
958  }
959 }
960 
961 void
963 {
965 }
966 
967 static rb_encoding*
968 io_read_encoding(rb_io_t *fptr)
969 {
970  if (fptr->encs.enc) {
971  return fptr->encs.enc;
972  }
974 }
975 
976 static rb_encoding*
977 io_input_encoding(rb_io_t *fptr)
978 {
979  if (fptr->encs.enc2) {
980  return fptr->encs.enc2;
981  }
982  return io_read_encoding(fptr);
983 }
984 
985 void
987 {
988  rb_io_check_closed(fptr);
989  if (!(fptr->mode & FMODE_WRITABLE)) {
990  rb_raise(rb_eIOError, "not opened for writing");
991  }
992  if (fptr->rbuf.len) {
993  io_unread(fptr);
994  }
995 }
996 
997 int
998 rb_io_read_pending(rb_io_t *fptr)
999 {
1000  /* This function is used for bytes and chars. Confusing. */
1001  if (READ_CHAR_PENDING(fptr))
1002  return 1; /* should raise? */
1003  return READ_DATA_PENDING(fptr);
1004 }
1005 
1006 void
1008 {
1009  if (!READ_DATA_PENDING(fptr)) {
1011  }
1012  return;
1013 }
1014 
1015 int
1016 rb_gc_for_fd(int err)
1017 {
1018  if (err == EMFILE || err == ENFILE || err == ENOMEM) {
1019  rb_gc();
1020  return 1;
1021  }
1022  return 0;
1023 }
1024 
1025 static int
1026 ruby_dup(int orig)
1027 {
1028  int fd;
1029 
1030  fd = rb_cloexec_dup(orig);
1031  if (fd < 0) {
1032  int e = errno;
1033  if (rb_gc_for_fd(e)) {
1034  fd = rb_cloexec_dup(orig);
1035  }
1036  if (fd < 0) {
1037  rb_syserr_fail(e, 0);
1038  }
1039  }
1040  rb_update_max_fd(fd);
1041  return fd;
1042 }
1043 
1044 static VALUE
1045 io_alloc(VALUE klass)
1046 {
1047  NEWOBJ_OF(io, struct RFile, klass, T_FILE);
1048 
1049  io->fptr = 0;
1050 
1051  return (VALUE)io;
1052 }
1053 
1054 #ifndef S_ISREG
1055 # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
1056 #endif
1057 
1059  VALUE th;
1060  rb_io_t *fptr;
1061  int nonblock;
1062  void *buf;
1063  size_t capa;
1064 };
1065 
1067  int fd;
1068  const void *buf;
1069  size_t capa;
1070 };
1071 
1072 #ifdef HAVE_WRITEV
1073 struct io_internal_writev_struct {
1074  int fd;
1075  int iovcnt;
1076  const struct iovec *iov;
1077 };
1078 #endif
1079 
1080 static int nogvl_wait_for(VALUE th, rb_io_t *fptr, short events);
1081 static VALUE
1082 internal_read_func(void *ptr)
1083 {
1084  struct io_internal_read_struct *iis = ptr;
1085  ssize_t r;
1086 retry:
1087  r = read(iis->fptr->fd, iis->buf, iis->capa);
1088  if (r < 0 && !iis->nonblock) {
1089  int e = errno;
1090  if (io_again_p(e)) {
1091  if (nogvl_wait_for(iis->th, iis->fptr, RB_WAITFD_IN) != -1) {
1092  goto retry;
1093  }
1094  errno = e;
1095  }
1096  }
1097  return r;
1098 }
1099 
1100 #if defined __APPLE__
1101 # define do_write_retry(code) do {ret = code;} while (ret == -1 && errno == EPROTOTYPE)
1102 #else
1103 # define do_write_retry(code) ret = code
1104 #endif
1105 static VALUE
1106 internal_write_func(void *ptr)
1107 {
1108  struct io_internal_write_struct *iis = ptr;
1109  ssize_t ret;
1110  do_write_retry(write(iis->fd, iis->buf, iis->capa));
1111  return (VALUE)ret;
1112 }
1113 
1114 static void*
1115 internal_write_func2(void *ptr)
1116 {
1117  return (void*)internal_write_func(ptr);
1118 }
1119 
1120 #ifdef HAVE_WRITEV
1121 static VALUE
1122 internal_writev_func(void *ptr)
1123 {
1124  struct io_internal_writev_struct *iis = ptr;
1125  ssize_t ret;
1126  do_write_retry(writev(iis->fd, iis->iov, iis->iovcnt));
1127  return (VALUE)ret;
1128 }
1129 #endif
1130 
1131 static ssize_t
1132 rb_read_internal(rb_io_t *fptr, void *buf, size_t count)
1133 {
1134  VALUE scheduler = rb_fiber_scheduler_current();
1135  if (scheduler != Qnil) {
1136  VALUE result = rb_fiber_scheduler_io_read_memory(scheduler, fptr->self, buf, count, 0);
1137 
1138  if (result != Qundef) {
1139  return rb_fiber_scheduler_io_result_apply(result);
1140  }
1141  }
1142 
1143  struct io_internal_read_struct iis = {
1144  .th = rb_thread_current(),
1145  .fptr = fptr,
1146  .nonblock = 0,
1147  .buf = buf,
1148  .capa = count
1149  };
1150 
1151  return (ssize_t)rb_thread_io_blocking_region(internal_read_func, &iis, fptr->fd);
1152 }
1153 
1154 static ssize_t
1155 rb_write_internal(rb_io_t *fptr, const void *buf, size_t count)
1156 {
1157  VALUE scheduler = rb_fiber_scheduler_current();
1158  if (scheduler != Qnil) {
1159  VALUE result = rb_fiber_scheduler_io_write_memory(scheduler, fptr->self, buf, count, 0);
1160 
1161  if (result != Qundef) {
1162  return rb_fiber_scheduler_io_result_apply(result);
1163  }
1164  }
1165 
1166  struct io_internal_write_struct iis = {
1167  .fd = fptr->fd,
1168  .buf = buf,
1169  .capa = count
1170  };
1171 
1172  if (fptr->write_lock && rb_mutex_owned_p(fptr->write_lock))
1173  return (ssize_t)rb_thread_call_without_gvl2(internal_write_func2, &iis, RUBY_UBF_IO, NULL);
1174  else
1175  return (ssize_t)rb_thread_io_blocking_region(internal_write_func, &iis, fptr->fd);
1176 }
1177 
1178 #ifdef HAVE_WRITEV
1179 static ssize_t
1180 rb_writev_internal(rb_io_t *fptr, const struct iovec *iov, int iovcnt)
1181 {
1182  VALUE scheduler = rb_fiber_scheduler_current();
1183  if (scheduler != Qnil) {
1184  for (int i = 0; i < iovcnt; i += 1) {
1185  VALUE result = rb_fiber_scheduler_io_write_memory(scheduler, fptr->self, iov[i].iov_base, iov[i].iov_len, 0);
1186 
1187  if (result != Qundef) {
1188  return rb_fiber_scheduler_io_result_apply(result);
1189  }
1190  }
1191  }
1192 
1193  struct io_internal_writev_struct iis = {
1194  .fd = fptr->fd,
1195  .iov = iov,
1196  .iovcnt = iovcnt,
1197  };
1198 
1199  return (ssize_t)rb_thread_io_blocking_region(internal_writev_func, &iis, fptr->fd);
1200 }
1201 #endif
1202 
1203 static VALUE
1204 io_flush_buffer_sync(void *arg)
1205 {
1206  rb_io_t *fptr = arg;
1207  long l = fptr->wbuf.len;
1208  ssize_t r = write(fptr->fd, fptr->wbuf.ptr+fptr->wbuf.off, (size_t)l);
1209 
1210  if (fptr->wbuf.len <= r) {
1211  fptr->wbuf.off = 0;
1212  fptr->wbuf.len = 0;
1213  return 0;
1214  }
1215  if (0 <= r) {
1216  fptr->wbuf.off += (int)r;
1217  fptr->wbuf.len -= (int)r;
1218  errno = EAGAIN;
1219  }
1220  return (VALUE)-1;
1221 }
1222 
1223 static void*
1224 io_flush_buffer_sync2(void *arg)
1225 {
1226  VALUE result = io_flush_buffer_sync(arg);
1227 
1228  /*
1229  * rb_thread_call_without_gvl2 uses 0 as interrupted.
1230  * So, we need to avoid to use 0.
1231  */
1232  return !result ? (void*)1 : (void*)result;
1233 }
1234 
1235 static VALUE
1236 io_flush_buffer_async(VALUE arg)
1237 {
1238  rb_io_t *fptr = (rb_io_t *)arg;
1239  return rb_thread_io_blocking_region(io_flush_buffer_sync, fptr, fptr->fd);
1240 }
1241 
1242 static VALUE
1243 io_flush_buffer_async2(VALUE arg)
1244 {
1245  rb_io_t *fptr = (rb_io_t *)arg;
1246  VALUE ret;
1247 
1248  ret = (VALUE)rb_thread_call_without_gvl2(io_flush_buffer_sync2, fptr, RUBY_UBF_IO, NULL);
1249 
1250  if (!ret) {
1251  /* pending async interrupt is there. */
1252  errno = EAGAIN;
1253  return -1;
1254  }
1255  else if (ret == 1) {
1256  return 0;
1257  }
1258  return ret;
1259 }
1260 
1261 static inline int
1262 io_flush_buffer(rb_io_t *fptr)
1263 {
1264  if (fptr->write_lock) {
1265  if (rb_mutex_owned_p(fptr->write_lock))
1266  return (int)io_flush_buffer_async2((VALUE)fptr);
1267  else
1268  return (int)rb_mutex_synchronize(fptr->write_lock, io_flush_buffer_async2, (VALUE)fptr);
1269  }
1270  else {
1271  return (int)io_flush_buffer_async((VALUE)fptr);
1272  }
1273 }
1274 
1275 static int
1276 io_fflush(rb_io_t *fptr)
1277 {
1278  rb_io_check_closed(fptr);
1279 
1280  if (fptr->wbuf.len == 0)
1281  return 0;
1282 
1283  while (fptr->wbuf.len > 0 && io_flush_buffer(fptr) != 0) {
1284  if (!rb_io_maybe_wait_writable(errno, fptr->self, Qnil))
1285  return -1;
1286 
1287  rb_io_check_closed(fptr);
1288  }
1289 
1290  return 0;
1291 }
1292 
1293 VALUE
1294 rb_io_wait(VALUE io, VALUE events, VALUE timeout)
1295 {
1296  VALUE scheduler = rb_fiber_scheduler_current();
1297 
1298  if (scheduler != Qnil) {
1299  return rb_fiber_scheduler_io_wait(scheduler, io, events, timeout);
1300  }
1301 
1302  rb_io_t * fptr = NULL;
1303  RB_IO_POINTER(io, fptr);
1304 
1305  struct timeval tv_storage;
1306  struct timeval *tv = NULL;
1307 
1308  if (timeout != Qnil) {
1309  tv_storage = rb_time_interval(timeout);
1310  tv = &tv_storage;
1311  }
1312 
1313  int ready = rb_thread_wait_for_single_fd(fptr->fd, RB_NUM2INT(events), tv);
1314 
1315  if (ready < 0) {
1316  rb_sys_fail(0);
1317  }
1318 
1319  // Not sure if this is necessary:
1320  rb_io_check_closed(fptr);
1321 
1322  if (ready) {
1323  return RB_INT2NUM(ready);
1324  }
1325  else {
1326  return Qfalse;
1327  }
1328 }
1329 
1330 static VALUE
1331 io_from_fd(int fd)
1332 {
1333  return prep_io(fd, FMODE_PREP, rb_cIO, NULL);
1334 }
1335 
1336 static int
1337 io_wait_for_single_fd(int fd, int events, struct timeval *timeout)
1338 {
1339  VALUE scheduler = rb_fiber_scheduler_current();
1340 
1341  if (scheduler != Qnil) {
1342  return RTEST(
1343  rb_fiber_scheduler_io_wait(scheduler, io_from_fd(fd), RB_INT2NUM(events), rb_fiber_scheduler_make_timeout(timeout))
1344  );
1345  }
1346 
1347  return rb_thread_wait_for_single_fd(fd, events, timeout);
1348 }
1349 
1350 int
1352 {
1353  io_fd_check_closed(f);
1354 
1355  VALUE scheduler = rb_fiber_scheduler_current();
1356 
1357  switch (errno) {
1358  case EINTR:
1359 #if defined(ERESTART)
1360  case ERESTART:
1361 #endif
1363  return TRUE;
1364 
1365  case EAGAIN:
1366 #if EWOULDBLOCK != EAGAIN
1367  case EWOULDBLOCK:
1368 #endif
1369  if (scheduler != Qnil) {
1370  return RTEST(
1371  rb_fiber_scheduler_io_wait_readable(scheduler, io_from_fd(f))
1372  );
1373  }
1374  else {
1375  io_wait_for_single_fd(f, RUBY_IO_READABLE, NULL);
1376  }
1377  return TRUE;
1378 
1379  default:
1380  return FALSE;
1381  }
1382 }
1383 
1384 int
1386 {
1387  io_fd_check_closed(f);
1388 
1389  VALUE scheduler = rb_fiber_scheduler_current();
1390 
1391  switch (errno) {
1392  case EINTR:
1393 #if defined(ERESTART)
1394  case ERESTART:
1395 #endif
1396  /*
1397  * In old Linux, several special files under /proc and /sys don't handle
1398  * select properly. Thus we need avoid to call if don't use O_NONBLOCK.
1399  * Otherwise, we face nasty hang up. Sigh.
1400  * e.g. http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=31b07093c44a7a442394d44423e21d783f5523b8
1401  * http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=31b07093c44a7a442394d44423e21d783f5523b8
1402  * In EINTR case, we only need to call RUBY_VM_CHECK_INTS_BLOCKING().
1403  * Then rb_thread_check_ints() is enough.
1404  */
1406  return TRUE;
1407 
1408  case EAGAIN:
1409 #if EWOULDBLOCK != EAGAIN
1410  case EWOULDBLOCK:
1411 #endif
1412  if (scheduler != Qnil) {
1413  return RTEST(
1414  rb_fiber_scheduler_io_wait_writable(scheduler, io_from_fd(f))
1415  );
1416  }
1417  else {
1418  io_wait_for_single_fd(f, RUBY_IO_WRITABLE, NULL);
1419  }
1420  return TRUE;
1421 
1422  default:
1423  return FALSE;
1424  }
1425 }
1426 
1427 int
1428 rb_wait_for_single_fd(int fd, int events, struct timeval *timeout)
1429 {
1430  return io_wait_for_single_fd(fd, events, timeout);
1431 }
1432 
1433 int
1435 {
1436  return rb_wait_for_single_fd(fd, RUBY_IO_READABLE, NULL);
1437 }
1438 
1439 int
1441 {
1442  return rb_wait_for_single_fd(fd, RUBY_IO_WRITABLE, NULL);
1443 }
1444 
1445 VALUE
1446 rb_io_maybe_wait(int error, VALUE io, VALUE events, VALUE timeout)
1447 {
1448  // fptr->fd can be set to -1 at any time by another thread when the GVL is
1449  // released. Many code, e.g. `io_bufread` didn't check this correctly and
1450  // instead relies on `read(-1) -> -1` which causes this code path. We then
1451  // check here whether the IO was in fact closed. Probably it's better to
1452  // check that `fptr->fd != -1` before using it in syscall.
1453  rb_io_check_closed(RFILE(io)->fptr);
1454 
1455  switch (error) {
1456  // In old Linux, several special files under /proc and /sys don't handle
1457  // select properly. Thus we need avoid to call if don't use O_NONBLOCK.
1458  // Otherwise, we face nasty hang up. Sigh.
1459  // e.g. http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=31b07093c44a7a442394d44423e21d783f5523b8
1460  // http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=31b07093c44a7a442394d44423e21d783f5523b8
1461  // In EINTR case, we only need to call RUBY_VM_CHECK_INTS_BLOCKING().
1462  // Then rb_thread_check_ints() is enough.
1463  case EINTR:
1464 #if defined(ERESTART)
1465  case ERESTART:
1466 #endif
1467  // We might have pending interrupts since the previous syscall was interrupted:
1469 
1470  // The operation was interrupted, so retry it immediately:
1471  return events;
1472 
1473  case EAGAIN:
1474 #if EWOULDBLOCK != EAGAIN
1475  case EWOULDBLOCK:
1476 #endif
1477  // The operation would block, so wait for the specified events:
1478  return rb_io_wait(io, events, timeout);
1479 
1480  default:
1481  // Non-specific error, no event is ready:
1482  return Qfalse;
1483  }
1484 }
1485 
1486 int
1487 rb_io_maybe_wait_readable(int error, VALUE io, VALUE timeout)
1488 {
1489  VALUE result = rb_io_maybe_wait(error, io, RB_INT2NUM(RUBY_IO_READABLE), timeout);
1490 
1491  if (RTEST(result)) {
1492  return RB_NUM2INT(result);
1493  }
1494  else {
1495  return 0;
1496  }
1497 }
1498 
1499 int
1500 rb_io_maybe_wait_writable(int error, VALUE io, VALUE timeout)
1501 {
1502  VALUE result = rb_io_maybe_wait(error, io, RB_INT2NUM(RUBY_IO_WRITABLE), timeout);
1503 
1504  if (RTEST(result)) {
1505  return RB_NUM2INT(result);
1506  }
1507  else {
1508  return 0;
1509  }
1510 }
1511 
1512 static void
1513 make_writeconv(rb_io_t *fptr)
1514 {
1515  if (!fptr->writeconv_initialized) {
1516  const char *senc, *denc;
1517  rb_encoding *enc;
1518  int ecflags;
1519  VALUE ecopts;
1520 
1521  fptr->writeconv_initialized = 1;
1522 
1523  ecflags = fptr->encs.ecflags & ~ECONV_NEWLINE_DECORATOR_READ_MASK;
1524  ecopts = fptr->encs.ecopts;
1525 
1526  if (!fptr->encs.enc || (fptr->encs.enc == rb_ascii8bit_encoding() && !fptr->encs.enc2)) {
1527  /* no encoding conversion */
1528  fptr->writeconv_pre_ecflags = 0;
1529  fptr->writeconv_pre_ecopts = Qnil;
1530  fptr->writeconv = rb_econv_open_opts("", "", ecflags, ecopts);
1531  if (!fptr->writeconv)
1532  rb_exc_raise(rb_econv_open_exc("", "", ecflags));
1533  fptr->writeconv_asciicompat = Qnil;
1534  }
1535  else {
1536  enc = fptr->encs.enc2 ? fptr->encs.enc2 : fptr->encs.enc;
1538  if (!senc && !(fptr->encs.ecflags & ECONV_STATEFUL_DECORATOR_MASK)) {
1539  /* single conversion */
1540  fptr->writeconv_pre_ecflags = ecflags;
1541  fptr->writeconv_pre_ecopts = ecopts;
1542  fptr->writeconv = NULL;
1543  fptr->writeconv_asciicompat = Qnil;
1544  }
1545  else {
1546  /* double conversion */
1548  fptr->writeconv_pre_ecopts = ecopts;
1549  if (senc) {
1550  denc = rb_enc_name(enc);
1551  fptr->writeconv_asciicompat = rb_str_new2(senc);
1552  }
1553  else {
1554  senc = denc = "";
1556  }
1558  ecopts = fptr->encs.ecopts;
1559  fptr->writeconv = rb_econv_open_opts(senc, denc, ecflags, ecopts);
1560  if (!fptr->writeconv)
1561  rb_exc_raise(rb_econv_open_exc(senc, denc, ecflags));
1562  }
1563  }
1564  }
1565 }
1566 
1567 /* writing functions */
1569  rb_io_t *fptr;
1570  VALUE str;
1571  const char *ptr;
1572  long length;
1573 };
1574 
1575 struct write_arg {
1576  VALUE io;
1577  VALUE str;
1578  int nosync;
1579 };
1580 
1581 #ifdef HAVE_WRITEV
1582 static VALUE
1583 io_binwrite_string(VALUE arg)
1584 {
1585  struct binwrite_arg *p = (struct binwrite_arg *)arg;
1586  rb_io_t *fptr = p->fptr;
1587  long r;
1588 
1589  if (fptr->wbuf.len) {
1590  struct iovec iov[2];
1591 
1592  iov[0].iov_base = fptr->wbuf.ptr+fptr->wbuf.off;
1593  iov[0].iov_len = fptr->wbuf.len;
1594  iov[1].iov_base = (char *)p->ptr;
1595  iov[1].iov_len = p->length;
1596 
1597  r = rb_writev_internal(fptr, iov, 2);
1598 
1599  if (r < 0)
1600  return r;
1601 
1602  if (fptr->wbuf.len <= r) {
1603  r -= fptr->wbuf.len;
1604  fptr->wbuf.off = 0;
1605  fptr->wbuf.len = 0;
1606  }
1607  else {
1608  fptr->wbuf.off += (int)r;
1609  fptr->wbuf.len -= (int)r;
1610  r = 0L;
1611  }
1612  }
1613  else {
1614  r = rb_write_internal(fptr, p->ptr, p->length);
1615  }
1616 
1617  return r;
1618 }
1619 #else
1620 static VALUE
1621 io_binwrite_string(VALUE arg)
1622 {
1623  struct binwrite_arg *p = (struct binwrite_arg *)arg;
1624  rb_io_t *fptr = p->fptr;
1625  long l, len;
1626 
1627  l = len = p->length;
1628 
1629  if (fptr->wbuf.len) {
1630  if (fptr->wbuf.len+len <= fptr->wbuf.capa) {
1631  if (fptr->wbuf.capa < fptr->wbuf.off+fptr->wbuf.len+len) {
1632  MEMMOVE(fptr->wbuf.ptr, fptr->wbuf.ptr+fptr->wbuf.off, char, fptr->wbuf.len);
1633  fptr->wbuf.off = 0;
1634  }
1635  MEMMOVE(fptr->wbuf.ptr+fptr->wbuf.off+fptr->wbuf.len, p->ptr, char, len);
1636  fptr->wbuf.len += (int)len;
1637  l = 0;
1638  }
1639  if (io_fflush(fptr) < 0)
1640  return -2L; /* fail in fflush */
1641  if (l == 0)
1642  return len;
1643  }
1644 
1645  return rb_write_internal(p->fptr, p->ptr, p->length);
1646 }
1647 #endif
1648 
1649 static long
1650 io_binwrite(VALUE str, const char *ptr, long len, rb_io_t *fptr, int nosync)
1651 {
1652  long n, r, offset = 0;
1653 
1654  /* don't write anything if current thread has a pending interrupt. */
1656 
1657  if ((n = len) <= 0) return n;
1658 
1659  if (fptr->wbuf.ptr == NULL && !(!nosync && (fptr->mode & FMODE_SYNC))) {
1660  fptr->wbuf.off = 0;
1661  fptr->wbuf.len = 0;
1662  fptr->wbuf.capa = IO_WBUF_CAPA_MIN;
1663  fptr->wbuf.ptr = ALLOC_N(char, fptr->wbuf.capa);
1664  fptr->write_lock = rb_mutex_new();
1665  rb_mutex_allow_trap(fptr->write_lock, 1);
1666  }
1667 
1668  if ((!nosync && (fptr->mode & (FMODE_SYNC|FMODE_TTY))) ||
1669  (fptr->wbuf.ptr && fptr->wbuf.capa <= fptr->wbuf.len + len)) {
1670  struct binwrite_arg arg;
1671 
1672  arg.fptr = fptr;
1673  arg.str = str;
1674  retry:
1675  arg.ptr = ptr + offset;
1676  arg.length = n;
1677 
1678  if (fptr->write_lock) {
1679  r = rb_mutex_synchronize(fptr->write_lock, io_binwrite_string, (VALUE)&arg);
1680  }
1681  else {
1682  r = io_binwrite_string((VALUE)&arg);
1683  }
1684 
1685  /* xxx: other threads may modify given string. */
1686  if (r == n) return len;
1687  if (0 <= r) {
1688  offset += r;
1689  n -= r;
1690  errno = EAGAIN;
1691  }
1692 
1693  if (r == -2L)
1694  return -1L;
1695  if (rb_io_maybe_wait_writable(errno, fptr->self, Qnil)) {
1696  rb_io_check_closed(fptr);
1697 
1698  if (offset < len)
1699  goto retry;
1700  }
1701 
1702  return -1L;
1703  }
1704 
1705  if (fptr->wbuf.off) {
1706  if (fptr->wbuf.len)
1707  MEMMOVE(fptr->wbuf.ptr, fptr->wbuf.ptr+fptr->wbuf.off, char, fptr->wbuf.len);
1708  fptr->wbuf.off = 0;
1709  }
1710 
1711  MEMMOVE(fptr->wbuf.ptr+fptr->wbuf.off+fptr->wbuf.len, ptr+offset, char, len);
1712  fptr->wbuf.len += (int)len;
1713 
1714  return len;
1715 }
1716 
1717 # define MODE_BTMODE(a,b,c) ((fmode & FMODE_BINMODE) ? (b) : \
1718  (fmode & FMODE_TEXTMODE) ? (c) : (a))
1719 
1720 #define MODE_BTXMODE(a, b, c, d, e, f) ((fmode & FMODE_EXCL) ? \
1721  MODE_BTMODE(d, e, f) : \
1722  MODE_BTMODE(a, b, c))
1723 
1724 static VALUE
1725 do_writeconv(VALUE str, rb_io_t *fptr, int *converted)
1726 {
1727  if (NEED_WRITECONV(fptr)) {
1728  VALUE common_encoding = Qnil;
1729  SET_BINARY_MODE(fptr);
1730 
1731  make_writeconv(fptr);
1732 
1733  if (fptr->writeconv) {
1734 #define fmode (fptr->mode)
1735  if (!NIL_P(fptr->writeconv_asciicompat))
1736  common_encoding = fptr->writeconv_asciicompat;
1737  else if (MODE_BTMODE(DEFAULT_TEXTMODE,0,1) && !rb_enc_asciicompat(rb_enc_get(str))) {
1738  rb_raise(rb_eArgError, "ASCII incompatible string written for text mode IO without encoding conversion: %s",
1739  rb_enc_name(rb_enc_get(str)));
1740  }
1741 #undef fmode
1742  }
1743  else {
1744  if (fptr->encs.enc2)
1745  common_encoding = rb_enc_from_encoding(fptr->encs.enc2);
1746  else if (fptr->encs.enc != rb_ascii8bit_encoding())
1747  common_encoding = rb_enc_from_encoding(fptr->encs.enc);
1748  }
1749 
1750  if (!NIL_P(common_encoding)) {
1751  str = rb_str_encode(str, common_encoding,
1753  *converted = 1;
1754  }
1755 
1756  if (fptr->writeconv) {
1758  *converted = 1;
1759  }
1760  }
1761 #if RUBY_CRLF_ENVIRONMENT
1762 #define fmode (fptr->mode)
1763  else if (MODE_BTMODE(DEFAULT_TEXTMODE,0,1)) {
1764  if ((fptr->mode & FMODE_READABLE) &&
1766  setmode(fptr->fd, O_BINARY);
1767  }
1768  else {
1769  setmode(fptr->fd, O_TEXT);
1770  }
1771  if (!rb_enc_asciicompat(rb_enc_get(str))) {
1772  rb_raise(rb_eArgError, "ASCII incompatible string written for text mode IO without encoding conversion: %s",
1773  rb_enc_name(rb_enc_get(str)));
1774  }
1775  }
1776 #undef fmode
1777 #endif
1778  return str;
1779 }
1780 
1781 static long
1782 io_fwrite(VALUE str, rb_io_t *fptr, int nosync)
1783 {
1784  int converted = 0;
1785  VALUE tmp;
1786  long n, len;
1787  const char *ptr;
1788 #ifdef _WIN32
1789  if (fptr->mode & FMODE_TTY) {
1790  long len = rb_w32_write_console(str, fptr->fd);
1791  if (len > 0) return len;
1792  }
1793 #endif
1794  str = do_writeconv(str, fptr, &converted);
1795  if (converted)
1796  OBJ_FREEZE(str);
1797 
1798  tmp = rb_str_tmp_frozen_acquire(str);
1799  RSTRING_GETMEM(tmp, ptr, len);
1800  n = io_binwrite(tmp, ptr, len, fptr, nosync);
1801  rb_str_tmp_frozen_release(str, tmp);
1802 
1803  return n;
1804 }
1805 
1806 ssize_t
1807 rb_io_bufwrite(VALUE io, const void *buf, size_t size)
1808 {
1809  rb_io_t *fptr;
1810 
1811  GetOpenFile(io, fptr);
1812  rb_io_check_writable(fptr);
1813  return (ssize_t)io_binwrite(0, buf, (long)size, fptr, 0);
1814 }
1815 
1816 static VALUE
1817 io_write(VALUE io, VALUE str, int nosync)
1818 {
1819  rb_io_t *fptr;
1820  long n;
1821  VALUE tmp;
1822 
1823  io = GetWriteIO(io);
1824  str = rb_obj_as_string(str);
1825  tmp = rb_io_check_io(io);
1826  if (NIL_P(tmp)) {
1827  /* port is not IO, call write method for it. */
1828  return rb_funcall(io, id_write, 1, str);
1829  }
1830  io = tmp;
1831  if (RSTRING_LEN(str) == 0) return INT2FIX(0);
1832 
1833  GetOpenFile(io, fptr);
1834  rb_io_check_writable(fptr);
1835 
1836  n = io_fwrite(str, fptr, nosync);
1837  if (n < 0L) rb_sys_fail_on_write(fptr);
1838 
1839  return LONG2FIX(n);
1840 }
1841 
1842 #ifdef HAVE_WRITEV
1843 struct binwritev_arg {
1844  rb_io_t *fptr;
1845  const struct iovec *iov;
1846  int iovcnt;
1847 };
1848 
1849 static VALUE
1850 call_writev_internal(VALUE arg)
1851 {
1852  struct binwritev_arg *p = (struct binwritev_arg *)arg;
1853  return rb_writev_internal(p->fptr, p->iov, p->iovcnt);
1854 }
1855 
1856 static long
1857 io_binwritev(struct iovec *iov, int iovcnt, rb_io_t *fptr)
1858 {
1859  int i;
1860  long r, total = 0, written_len = 0;
1861 
1862  /* don't write anything if current thread has a pending interrupt. */
1864 
1865  if (iovcnt == 0) return 0;
1866  for (i = 1; i < iovcnt; i++) total += iov[i].iov_len;
1867 
1868  if (fptr->wbuf.ptr == NULL && !(fptr->mode & FMODE_SYNC)) {
1869  fptr->wbuf.off = 0;
1870  fptr->wbuf.len = 0;
1871  fptr->wbuf.capa = IO_WBUF_CAPA_MIN;
1872  fptr->wbuf.ptr = ALLOC_N(char, fptr->wbuf.capa);
1873  fptr->write_lock = rb_mutex_new();
1874  rb_mutex_allow_trap(fptr->write_lock, 1);
1875  }
1876 
1877  if (fptr->wbuf.ptr && fptr->wbuf.len) {
1878  long offset = fptr->wbuf.off + fptr->wbuf.len;
1879  if (offset + total <= fptr->wbuf.capa) {
1880  for (i = 1; i < iovcnt; i++) {
1881  memcpy(fptr->wbuf.ptr+offset, iov[i].iov_base, iov[i].iov_len);
1882  offset += iov[i].iov_len;
1883  }
1884  fptr->wbuf.len += total;
1885  return total;
1886  }
1887  else {
1888  iov[0].iov_base = fptr->wbuf.ptr + fptr->wbuf.off;
1889  iov[0].iov_len = fptr->wbuf.len;
1890  }
1891  }
1892  else {
1893  iov++;
1894  if (!--iovcnt) return 0;
1895  }
1896 
1897  retry:
1898  if (fptr->write_lock) {
1899  struct binwritev_arg arg;
1900  arg.fptr = fptr;
1901  arg.iov = iov;
1902  arg.iovcnt = iovcnt;
1903  r = rb_mutex_synchronize(fptr->write_lock, call_writev_internal, (VALUE)&arg);
1904  }
1905  else {
1906  r = rb_writev_internal(fptr, iov, iovcnt);
1907  }
1908 
1909  if (r >= 0) {
1910  written_len += r;
1911  if (fptr->wbuf.ptr && fptr->wbuf.len) {
1912  if (written_len < fptr->wbuf.len) {
1913  fptr->wbuf.off += r;
1914  fptr->wbuf.len -= r;
1915  }
1916  else {
1917  written_len -= fptr->wbuf.len;
1918  fptr->wbuf.off = 0;
1919  fptr->wbuf.len = 0;
1920  }
1921  }
1922  if (written_len == total) return total;
1923 
1924  while (r >= (ssize_t)iov->iov_len) {
1925  /* iovcnt > 0 */
1926  r -= iov->iov_len;
1927  iov->iov_len = 0;
1928  iov++;
1929  if (!--iovcnt) return total;
1930  /* defensive check: written_len should == total */
1931  }
1932  iov->iov_base = (char *)iov->iov_base + r;
1933  iov->iov_len -= r;
1934 
1935  errno = EAGAIN;
1936  }
1937  if (rb_io_maybe_wait_writable(errno, fptr->self, Qnil)) {
1938  rb_io_check_closed(fptr);
1939  goto retry;
1940  }
1941 
1942  return -1L;
1943 }
1944 
1945 static long
1946 io_fwritev(int argc, const VALUE *argv, rb_io_t *fptr)
1947 {
1948  int i, converted, iovcnt = argc + 1;
1949  long n;
1950  VALUE v1, v2, str, tmp, *tmp_array;
1951  struct iovec *iov;
1952 
1953  iov = ALLOCV_N(struct iovec, v1, iovcnt);
1954  tmp_array = ALLOCV_N(VALUE, v2, argc);
1955 
1956  for (i = 0; i < argc; i++) {
1957  str = rb_obj_as_string(argv[i]);
1958  converted = 0;
1959  str = do_writeconv(str, fptr, &converted);
1960  if (converted)
1961  OBJ_FREEZE(str);
1962 
1963  tmp = rb_str_tmp_frozen_acquire(str);
1964  tmp_array[i] = tmp;
1965  /* iov[0] is reserved for buffer of fptr */
1966  iov[i+1].iov_base = RSTRING_PTR(tmp);
1967  iov[i+1].iov_len = RSTRING_LEN(tmp);
1968  }
1969 
1970  n = io_binwritev(iov, iovcnt, fptr);
1971  if (v1) ALLOCV_END(v1);
1972 
1973  for (i = 0; i < argc; i++) {
1974  rb_str_tmp_frozen_release(argv[i], tmp_array[i]);
1975  }
1976 
1977  if (v2) ALLOCV_END(v2);
1978 
1979  return n;
1980 }
1981 
1982 static int
1983 iovcnt_ok(int iovcnt)
1984 {
1985 #ifdef IOV_MAX
1986  return iovcnt < IOV_MAX;
1987 #else /* GNU/Hurd has writev, but no IOV_MAX */
1988  return 1;
1989 #endif
1990 }
1991 #endif /* HAVE_WRITEV */
1992 
1993 static VALUE
1994 io_writev(int argc, const VALUE *argv, VALUE io)
1995 {
1996  rb_io_t *fptr;
1997  long n;
1998  VALUE tmp, total = INT2FIX(0);
1999  int i, cnt = 1;
2000 
2001  io = GetWriteIO(io);
2002  tmp = rb_io_check_io(io);
2003  if (NIL_P(tmp)) {
2004  /* port is not IO, call write method for it. */
2005  return rb_funcallv(io, id_write, argc, argv);
2006  }
2007  io = tmp;
2008 
2009  GetOpenFile(io, fptr);
2010  rb_io_check_writable(fptr);
2011 
2012  for (i = 0; i < argc; i += cnt) {
2013 #ifdef HAVE_WRITEV
2014  if ((fptr->mode & (FMODE_SYNC|FMODE_TTY)) && iovcnt_ok(cnt = argc - i)) {
2015  n = io_fwritev(cnt, &argv[i], fptr);
2016  }
2017  else
2018 #endif
2019  {
2020  cnt = 1;
2021  /* sync at last item */
2022  n = io_fwrite(rb_obj_as_string(argv[i]), fptr, (i < argc-1));
2023  }
2024  if (n < 0L) rb_sys_fail_on_write(fptr);
2025  total = rb_fix_plus(LONG2FIX(n), total);
2026  }
2027 
2028  return total;
2029 }
2030 
2031 /*
2032  * call-seq:
2033  * write(*objects) -> integer
2034  *
2035  * Writes each of the given +objects+ to +self+,
2036  * which must be opened for writing (see {Modes}[#class-IO-label-Modes]);
2037  * returns the total number bytes written;
2038  * each of +objects+ that is not a string is converted via method +to_s+:
2039  *
2040  * $stdout.write('Hello', ', ', 'World!', "\n") # => 14
2041  * $stdout.write('foo', :bar, 2, "\n") # => 8
2042  *
2043  * Output:
2044  *
2045  * Hello, World!
2046  * foobar2
2047  *
2048  */
2049 
2050 static VALUE
2051 io_write_m(int argc, VALUE *argv, VALUE io)
2052 {
2053  if (argc != 1) {
2054  return io_writev(argc, argv, io);
2055  }
2056  else {
2057  VALUE str = argv[0];
2058  return io_write(io, str, 0);
2059  }
2060 }
2061 
2062 VALUE
2064 {
2065  return rb_funcallv(io, id_write, 1, &str);
2066 }
2067 
2068 static VALUE
2069 rb_io_writev(VALUE io, int argc, const VALUE *argv)
2070 {
2071  if (argc > 1 && rb_obj_method_arity(io, id_write) == 1) {
2072  if (io != rb_ractor_stderr() && RTEST(ruby_verbose)) {
2073  VALUE klass = CLASS_OF(io);
2074  char sep = FL_TEST(klass, FL_SINGLETON) ? (klass = io, '.') : '#';
2075  rb_category_warning(RB_WARN_CATEGORY_DEPRECATED, "%+"PRIsVALUE"%c""write is outdated interface"
2076  " which accepts just one argument",
2077  klass, sep);
2078  }
2079  do rb_io_write(io, *argv++); while (--argc);
2080  return argv[0]; /* unused right now */
2081  }
2082  return rb_funcallv(io, id_write, argc, argv);
2083 }
2084 
2085 /*
2086  * call-seq:
2087  * self << object -> self
2088  *
2089  * Writes the given +object+ to +self+,
2090  * which must be opened for writing (see {Modes}[#class-IO-label-Modes]);
2091  * returns +self+;
2092  * if +object+ is not a string, it is converted via method +to_s+:
2093  *
2094  * $stdout << 'Hello' << ', ' << 'World!' << "\n"
2095  * $stdout << 'foo' << :bar << 2 << "\n"
2096  *
2097  * Output:
2098  *
2099  * Hello, World!
2100  * foobar2
2101  *
2102  */
2103 
2104 
2105 VALUE
2107 {
2108  rb_io_write(io, str);
2109  return io;
2110 }
2111 
2112 #ifdef HAVE_FSYNC
2113 static VALUE
2114 nogvl_fsync(void *ptr)
2115 {
2116  rb_io_t *fptr = ptr;
2117 
2118 #ifdef _WIN32
2119  if (GetFileType((HANDLE)rb_w32_get_osfhandle(fptr->fd)) != FILE_TYPE_DISK)
2120  return 0;
2121 #endif
2122  return (VALUE)fsync(fptr->fd);
2123 }
2124 #endif
2125 
2126 VALUE
2127 rb_io_flush_raw(VALUE io, int sync)
2128 {
2129  rb_io_t *fptr;
2130 
2131  if (!RB_TYPE_P(io, T_FILE)) {
2132  return rb_funcall(io, id_flush, 0);
2133  }
2134 
2135  io = GetWriteIO(io);
2136  GetOpenFile(io, fptr);
2137 
2138  if (fptr->mode & FMODE_WRITABLE) {
2139  if (io_fflush(fptr) < 0)
2140  rb_sys_fail_on_write(fptr);
2141  }
2142  if (fptr->mode & FMODE_READABLE) {
2143  io_unread(fptr);
2144  }
2145 
2146  return io;
2147 }
2148 
2149 /*
2150  * call-seq:
2151  * flush -> self
2152  *
2153  * Flushes data buffered in +self+ to the operating system
2154  * (but does not necessarily flush data buffered in the operating system):
2155  *
2156  * $stdout.print 'no newline' # Not necessarily flushed.
2157  * $stdout.flush # Flushed.
2158  *
2159  */
2160 
2161 VALUE
2163 {
2164  return rb_io_flush_raw(io, 1);
2165 }
2166 
2167 /*
2168  * call-seq:
2169  * tell -> integer
2170  *
2171  * Returns the current position (in bytes) in +self+
2172  * (see {Position}[#class-IO-label-Position]):
2173  *
2174  * f = File.new('t.txt')
2175  * f.tell # => 0
2176  * f.readline # => "This is line one.\n"
2177  * f.tell # => 19
2178  *
2179  * Related: IO#pos=, IO#seek.
2180  *
2181  * IO#pos is an alias for IO#tell.
2182  *
2183  */
2184 
2185 static VALUE
2186 rb_io_tell(VALUE io)
2187 {
2188  rb_io_t *fptr;
2189  off_t pos;
2190 
2191  GetOpenFile(io, fptr);
2192  pos = io_tell(fptr);
2193  if (pos < 0 && errno) rb_sys_fail_path(fptr->pathv);
2194  pos -= fptr->rbuf.len;
2195  return OFFT2NUM(pos);
2196 }
2197 
2198 static VALUE
2199 rb_io_seek(VALUE io, VALUE offset, int whence)
2200 {
2201  rb_io_t *fptr;
2202  off_t pos;
2203 
2204  pos = NUM2OFFT(offset);
2205  GetOpenFile(io, fptr);
2206  pos = io_seek(fptr, pos, whence);
2207  if (pos < 0 && errno) rb_sys_fail_path(fptr->pathv);
2208 
2209  return INT2FIX(0);
2210 }
2211 
2212 static int
2213 interpret_seek_whence(VALUE vwhence)
2214 {
2215  if (vwhence == sym_SET)
2216  return SEEK_SET;
2217  if (vwhence == sym_CUR)
2218  return SEEK_CUR;
2219  if (vwhence == sym_END)
2220  return SEEK_END;
2221 #ifdef SEEK_DATA
2222  if (vwhence == sym_DATA)
2223  return SEEK_DATA;
2224 #endif
2225 #ifdef SEEK_HOLE
2226  if (vwhence == sym_HOLE)
2227  return SEEK_HOLE;
2228 #endif
2229  return NUM2INT(vwhence);
2230 }
2231 
2232 /*
2233  * call-seq:
2234  * seek(offset, whence = IO::SEEK_SET) -> 0
2235  *
2236  * Seeks to the position given by integer +offset+
2237  * (see {Position}[#class-IO-label-Position])
2238  * and constant +whence+, which is one of:
2239  *
2240  * - +:CUR+ or <tt>IO::SEEK_CUR</tt>:
2241  * Repositions the stream to its current position plus the given +offset+:
2242  *
2243  * f = File.open('t.txt')
2244  * f.tell # => 0
2245  * f.seek(20, :CUR) # => 0
2246  * f.tell # => 20
2247  * f.seek(-10, :CUR) # => 0
2248  * f.tell # => 10
2249  *
2250  * - +:END+ or <tt>IO::SEEK_END</tt>:
2251  * Repositions the stream to its end plus the given +offset+:
2252  *
2253  * f = File.open('t.txt')
2254  * f.tell # => 0
2255  * f.seek(0, :END) # => 0 # Repositions to stream end.
2256  * f.tell # => 70
2257  * f.seek(-20, :END) # => 0
2258  * f.tell # => 50
2259  * f.seek(-40, :END) # => 0
2260  * f.tell # => 30
2261  *
2262  * - +:SET+ or <tt>IO:SEEK_SET</tt>:
2263  * Repositions the stream to the given +offset+:
2264  *
2265  * f = File.open('t.txt')
2266  * f.tell # => 0
2267  * f.seek(20, :SET) # => 0
2268  * f.tell # => 20
2269  * f.seek(40, :SET) # => 0
2270  * f.tell # => 40
2271  *
2272  * Related: IO#pos=, IO#tell.
2273  *
2274  */
2275 
2276 static VALUE
2277 rb_io_seek_m(int argc, VALUE *argv, VALUE io)
2278 {
2279  VALUE offset, ptrname;
2280  int whence = SEEK_SET;
2281 
2282  if (rb_scan_args(argc, argv, "11", &offset, &ptrname) == 2) {
2283  whence = interpret_seek_whence(ptrname);
2284  }
2285 
2286  return rb_io_seek(io, offset, whence);
2287 }
2288 
2289 /*
2290  * call-seq:
2291  * pos = new_position -> new_position
2292  *
2293  * Seeks to the given +new_position+ (in bytes);
2294  * see {Position}[#class-IO-label-Position]:
2295  *
2296  * f = File.open('t.txt')
2297  * f.tell # => 0
2298  * f.pos = 20 # => 20
2299  * f.tell # => 20
2300  *
2301  * Related: IO#seek, IO#tell.
2302  *
2303  */
2304 
2305 static VALUE
2306 rb_io_set_pos(VALUE io, VALUE offset)
2307 {
2308  rb_io_t *fptr;
2309  off_t pos;
2310 
2311  pos = NUM2OFFT(offset);
2312  GetOpenFile(io, fptr);
2313  pos = io_seek(fptr, pos, SEEK_SET);
2314  if (pos < 0 && errno) rb_sys_fail_path(fptr->pathv);
2315 
2316  return OFFT2NUM(pos);
2317 }
2318 
2319 static void clear_readconv(rb_io_t *fptr);
2320 
2321 /*
2322  * call-seq:
2323  * rewind -> 0
2324  *
2325  * Repositions the stream to its beginning,
2326  * setting both the position and the line number to zero;
2327  * see {Position}[#class-IO-label-Position]
2328  * and {Line Number}[#class-IO-label-Line+Number]:
2329  *
2330  * f = File.open('t.txt')
2331  * f.tell # => 0
2332  * f.lineno # => 0
2333  * f.readline # => "This is line one.\n"
2334  * f.tell # => 19
2335  * f.lineno # => 1
2336  * f.rewind # => 0
2337  * f.tell # => 0
2338  * f.lineno # => 0
2339  *
2340  * Note that this method cannot be used with streams such as pipes, ttys, and sockets.
2341  *
2342  */
2343 
2344 static VALUE
2345 rb_io_rewind(VALUE io)
2346 {
2347  rb_io_t *fptr;
2348 
2349  GetOpenFile(io, fptr);
2350  if (io_seek(fptr, 0L, 0) < 0 && errno) rb_sys_fail_path(fptr->pathv);
2351  if (io == ARGF.current_file) {
2352  ARGF.lineno -= fptr->lineno;
2353  }
2354  fptr->lineno = 0;
2355  if (fptr->readconv) {
2356  clear_readconv(fptr);
2357  }
2358 
2359  return INT2FIX(0);
2360 }
2361 
2362 static int
2363 fptr_wait_readable(rb_io_t *fptr)
2364 {
2365  int ret = rb_io_maybe_wait_readable(errno, fptr->self, Qnil);
2366 
2367  if (ret)
2368  rb_io_check_closed(fptr);
2369 
2370  return ret;
2371 }
2372 
2373 static int
2374 io_fillbuf(rb_io_t *fptr)
2375 {
2376  ssize_t r;
2377 
2378  if (fptr->rbuf.ptr == NULL) {
2379  fptr->rbuf.off = 0;
2380  fptr->rbuf.len = 0;
2381  fptr->rbuf.capa = IO_RBUF_CAPA_FOR(fptr);
2382  fptr->rbuf.ptr = ALLOC_N(char, fptr->rbuf.capa);
2383 #ifdef _WIN32
2384  fptr->rbuf.capa--;
2385 #endif
2386  }
2387  if (fptr->rbuf.len == 0) {
2388  retry:
2389  r = rb_read_internal(fptr, fptr->rbuf.ptr, fptr->rbuf.capa);
2390 
2391  if (r < 0) {
2392  if (fptr_wait_readable(fptr))
2393  goto retry;
2394 
2395  int e = errno;
2396  VALUE path = rb_sprintf("fd:%d ", fptr->fd);
2397  if (!NIL_P(fptr->pathv)) {
2398  rb_str_append(path, fptr->pathv);
2399  }
2400 
2401  rb_syserr_fail_path(e, path);
2402  }
2403  if (r > 0) rb_io_check_closed(fptr);
2404  fptr->rbuf.off = 0;
2405  fptr->rbuf.len = (int)r; /* r should be <= rbuf_capa */
2406  if (r == 0)
2407  return -1; /* EOF */
2408  }
2409  return 0;
2410 }
2411 
2412 /*
2413  * call-seq:
2414  * eof -> true or false
2415  *
2416  * Returns +true+ if the stream is positioned at its end, +false+ otherwise;
2417  * see {Position}[#class-IO-label-Position]:
2418  *
2419  * f = File.open('t.txt')
2420  * f.eof # => false
2421  * f.seek(0, :END) # => 0
2422  * f.eof # => true
2423  *
2424  * Raises an exception unless the stream is opened for reading;
2425  * see {Mode}[#class-IO-label-Mode].
2426  *
2427  * If +self+ is a stream such as pipe or socket, this method
2428  * blocks until the other end sends some data or closes it:
2429  *
2430  * r, w = IO.pipe
2431  * Thread.new { sleep 1; w.close }
2432  * r.eof? # => true # After 1-second wait.
2433  *
2434  * r, w = IO.pipe
2435  * Thread.new { sleep 1; w.puts "a" }
2436  * r.eof? # => false # After 1-second wait.
2437  *
2438  * r, w = IO.pipe
2439  * r.eof? # blocks forever
2440  *
2441  * Note that this method reads data to the input byte buffer. So
2442  * IO#sysread may not behave as you intend with IO#eof?, unless you
2443  * call IO#rewind first (which is not available for some streams).
2444  *
2445  * I#eof? is an alias for IO#eof.
2446  *
2447  */
2448 
2449 VALUE
2451 {
2452  rb_io_t *fptr;
2453 
2454  GetOpenFile(io, fptr);
2456 
2457  if (READ_CHAR_PENDING(fptr)) return Qfalse;
2458  if (READ_DATA_PENDING(fptr)) return Qfalse;
2459  READ_CHECK(fptr);
2460 #if RUBY_CRLF_ENVIRONMENT
2461  if (!NEED_READCONV(fptr) && NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {
2462  return RBOOL(eof(fptr->fd));;
2463  }
2464 #endif
2465  return RBOOL(io_fillbuf(fptr) < 0);
2466 }
2467 
2468 /*
2469  * call-seq:
2470  * sync -> true or false
2471  *
2472  * Returns the current sync mode of the stream.
2473  * When sync mode is true, all output is immediately flushed to the underlying
2474  * operating system and is not buffered by Ruby internally. See also #fsync.
2475  *
2476  * f = File.open('t.tmp', 'w')
2477  * f.sync # => false
2478  * f.sync = true
2479  * f.sync # => true
2480  *
2481  */
2482 
2483 static VALUE
2484 rb_io_sync(VALUE io)
2485 {
2486  rb_io_t *fptr;
2487 
2488  io = GetWriteIO(io);
2489  GetOpenFile(io, fptr);
2490  return RBOOL(fptr->mode & FMODE_SYNC);
2491 }
2492 
2493 #ifdef HAVE_FSYNC
2494 
2495 /*
2496  * call-seq:
2497  * sync = boolean -> boolean
2498  *
2499  * Sets the _sync_ _mode_ for the stream to the given value;
2500  * returns the given value.
2501  *
2502  * Values for the sync mode:
2503  *
2504  * - +true+: All output is immediately flushed to the
2505  * underlying operating system and is not buffered internally.
2506  * - +false+: Output may be buffered internally.
2507  *
2508  * Example;
2509  *
2510  * f = File.open('t.tmp', 'w')
2511  * f.sync # => false
2512  * f.sync = true
2513  * f.sync # => true
2514  *
2515  * Related: IO#fsync.
2516  *
2517  */
2518 
2519 static VALUE
2520 rb_io_set_sync(VALUE io, VALUE sync)
2521 {
2522  rb_io_t *fptr;
2523 
2524  io = GetWriteIO(io);
2525  GetOpenFile(io, fptr);
2526  if (RTEST(sync)) {
2527  fptr->mode |= FMODE_SYNC;
2528  }
2529  else {
2530  fptr->mode &= ~FMODE_SYNC;
2531  }
2532  return sync;
2533 }
2534 
2535 /*
2536  * call-seq:
2537  * fsync -> 0
2538  *
2539  * Immediately writes to disk all data buffered in the stream,
2540  * via the operating system's <tt>fsync(2)</tt>.
2541 
2542  * Note this difference:
2543  *
2544  * - IO#sync=: Ensures that data is flushed from the stream's internal buffers,
2545  * but does not guarantee that the operating system actually writes the data to disk.
2546  * - IO#fsync: Ensures both that data is flushed from internal buffers,
2547  * and that data is written to disk.
2548  *
2549  * Raises an exception if the operating system does not support <tt>fsync(2)</tt>.
2550  *
2551  */
2552 
2553 static VALUE
2554 rb_io_fsync(VALUE io)
2555 {
2556  rb_io_t *fptr;
2557 
2558  io = GetWriteIO(io);
2559  GetOpenFile(io, fptr);
2560 
2561  if (io_fflush(fptr) < 0)
2562  rb_sys_fail_on_write(fptr);
2563  if ((int)rb_thread_io_blocking_region(nogvl_fsync, fptr, fptr->fd) < 0)
2564  rb_sys_fail_path(fptr->pathv);
2565  return INT2FIX(0);
2566 }
2567 #else
2568 # define rb_io_fsync rb_f_notimplement
2569 # define rb_io_sync rb_f_notimplement
2570 static VALUE
2571 rb_io_set_sync(VALUE io, VALUE sync)
2572 {
2573  rb_notimplement();
2574  UNREACHABLE;
2575 }
2576 #endif
2577 
2578 #ifdef HAVE_FDATASYNC
2579 static VALUE
2580 nogvl_fdatasync(void *ptr)
2581 {
2582  rb_io_t *fptr = ptr;
2583 
2584 #ifdef _WIN32
2585  if (GetFileType((HANDLE)rb_w32_get_osfhandle(fptr->fd)) != FILE_TYPE_DISK)
2586  return 0;
2587 #endif
2588  return (VALUE)fdatasync(fptr->fd);
2589 }
2590 
2591 /*
2592  * call-seq:
2593  * fdatasync -> 0
2594  *
2595  * Immediately writes to disk all data buffered in the stream,
2596  * via the operating system's: <tt>fdatasync(2)</tt>, if supported,
2597  * otherwise via <tt>fsync(2)</tt>, if supported;
2598  * otherwise raises an exception.
2599  *
2600  */
2601 
2602 static VALUE
2603 rb_io_fdatasync(VALUE io)
2604 {
2605  rb_io_t *fptr;
2606 
2607  io = GetWriteIO(io);
2608  GetOpenFile(io, fptr);
2609 
2610  if (io_fflush(fptr) < 0)
2611  rb_sys_fail_on_write(fptr);
2612 
2613  if ((int)rb_thread_io_blocking_region(nogvl_fdatasync, fptr, fptr->fd) == 0)
2614  return INT2FIX(0);
2615 
2616  /* fall back */
2617  return rb_io_fsync(io);
2618 }
2619 #else
2620 #define rb_io_fdatasync rb_io_fsync
2621 #endif
2622 
2623 /*
2624  * call-seq:
2625  * fileno -> integer
2626  *
2627  * Returns the integer file descriptor for the stream:
2628  *
2629  * $stdin.fileno # => 0
2630  * $stdout.fileno # => 1
2631  * $stderr.fileno # => 2
2632  * File.open('t.txt').fileno # => 10
2633  *
2634  * IO#to_i is an alias for IO#fileno.
2635  *
2636  */
2637 
2638 static VALUE
2639 rb_io_fileno(VALUE io)
2640 {
2641  rb_io_t *fptr = RFILE(io)->fptr;
2642  int fd;
2643 
2644  rb_io_check_closed(fptr);
2645  fd = fptr->fd;
2646  return INT2FIX(fd);
2647 }
2648 
2649 int
2651 {
2652  if (RB_TYPE_P(io, T_FILE)) {
2653  rb_io_t *fptr = RFILE(io)->fptr;
2654  rb_io_check_closed(fptr);
2655  return fptr->fd;
2656  }
2657  else {
2658  return RB_NUM2INT(rb_funcall(io, id_fileno, 0));
2659  }
2660 }
2661 
2662 /*
2663  * call-seq:
2664  * pid -> integer or nil
2665  *
2666  * Returns the process ID of a child process associated with the stream,
2667  * which will have been set by IO#popen, or +nil+ if the stream was not
2668  * created by IO#popen:
2669  *
2670  * pipe = IO.popen("-")
2671  * if pipe
2672  * $stderr.puts "In parent, child pid is #{pipe.pid}"
2673  * else
2674  * $stderr.puts "In child, pid is #{$$}"
2675  * end
2676  *
2677  * Output:
2678  *
2679  * In child, pid is 26209
2680  * In parent, child pid is 26209
2681  *
2682  */
2683 
2684 static VALUE
2685 rb_io_pid(VALUE io)
2686 {
2687  rb_io_t *fptr;
2688 
2689  GetOpenFile(io, fptr);
2690  if (!fptr->pid)
2691  return Qnil;
2692  return PIDT2NUM(fptr->pid);
2693 }
2694 
2695 
2696 /*
2697  * call-seq:
2698  * inspect -> string
2699  *
2700  * Returns a string representation of +self+:
2701  *
2702  * f = File.open('t.txt')
2703  * f.inspect # => "#<File:t.txt>"
2704  *
2705  */
2706 
2707 static VALUE
2708 rb_io_inspect(VALUE obj)
2709 {
2710  rb_io_t *fptr;
2711  VALUE result;
2712  static const char closed[] = " (closed)";
2713 
2714  fptr = RFILE(obj)->fptr;
2715  if (!fptr) return rb_any_to_s(obj);
2716  result = rb_str_new_cstr("#<");
2717  rb_str_append(result, rb_class_name(CLASS_OF(obj)));
2718  rb_str_cat2(result, ":");
2719  if (NIL_P(fptr->pathv)) {
2720  if (fptr->fd < 0) {
2721  rb_str_cat(result, closed+1, strlen(closed)-1);
2722  }
2723  else {
2724  rb_str_catf(result, "fd %d", fptr->fd);
2725  }
2726  }
2727  else {
2728  rb_str_append(result, fptr->pathv);
2729  if (fptr->fd < 0) {
2730  rb_str_cat(result, closed, strlen(closed));
2731  }
2732  }
2733  return rb_str_cat2(result, ">");
2734 }
2735 
2736 /*
2737  * call-seq:
2738  * to_io -> self
2739  *
2740  * Returns +self+.
2741  *
2742  */
2743 
2744 static VALUE
2745 rb_io_to_io(VALUE io)
2746 {
2747  return io;
2748 }
2749 
2750 /* reading functions */
2751 static long
2752 read_buffered_data(char *ptr, long len, rb_io_t *fptr)
2753 {
2754  int n;
2755 
2756  n = READ_DATA_PENDING_COUNT(fptr);
2757  if (n <= 0) return 0;
2758  if (n > len) n = (int)len;
2759  MEMMOVE(ptr, fptr->rbuf.ptr+fptr->rbuf.off, char, n);
2760  fptr->rbuf.off += n;
2761  fptr->rbuf.len -= n;
2762  return n;
2763 }
2764 
2765 static long
2766 io_bufread(char *ptr, long len, rb_io_t *fptr)
2767 {
2768  long offset = 0;
2769  long n = len;
2770  long c;
2771 
2772  if (READ_DATA_PENDING(fptr) == 0) {
2773  while (n > 0) {
2774  again:
2775  rb_io_check_closed(fptr);
2776  c = rb_read_internal(fptr, ptr+offset, n);
2777  if (c == 0) break;
2778  if (c < 0) {
2779  if (fptr_wait_readable(fptr))
2780  goto again;
2781  return -1;
2782  }
2783  offset += c;
2784  if ((n -= c) <= 0) break;
2785  }
2786  return len - n;
2787  }
2788 
2789  while (n > 0) {
2790  c = read_buffered_data(ptr+offset, n, fptr);
2791  if (c > 0) {
2792  offset += c;
2793  if ((n -= c) <= 0) break;
2794  }
2795  rb_io_check_closed(fptr);
2796  if (io_fillbuf(fptr) < 0) {
2797  break;
2798  }
2799  }
2800  return len - n;
2801 }
2802 
2803 static int io_setstrbuf(VALUE *str, long len);
2804 
2805 struct bufread_arg {
2806  char *str_ptr;
2807  long len;
2808  rb_io_t *fptr;
2809 };
2810 
2811 static VALUE
2812 bufread_call(VALUE arg)
2813 {
2814  struct bufread_arg *p = (struct bufread_arg *)arg;
2815  p->len = io_bufread(p->str_ptr, p->len, p->fptr);
2816  return Qundef;
2817 }
2818 
2819 static long
2820 io_fread(VALUE str, long offset, long size, rb_io_t *fptr)
2821 {
2822  long len;
2823  struct bufread_arg arg;
2824 
2825  io_setstrbuf(&str, offset + size);
2826  arg.str_ptr = RSTRING_PTR(str) + offset;
2827  arg.len = size;
2828  arg.fptr = fptr;
2829  rb_str_locktmp_ensure(str, bufread_call, (VALUE)&arg);
2830  len = arg.len;
2831  if (len < 0) rb_sys_fail_path(fptr->pathv);
2832  return len;
2833 }
2834 
2835 static long
2836 remain_size(rb_io_t *fptr)
2837 {
2838  struct stat st;
2839  off_t siz = READ_DATA_PENDING_COUNT(fptr);
2840  off_t pos;
2841 
2842  if (fstat(fptr->fd, &st) == 0 && S_ISREG(st.st_mode)
2843 #if defined(__HAIKU__)
2844  && (st.st_dev > 3)
2845 #endif
2846  )
2847  {
2848  if (io_fflush(fptr) < 0)
2849  rb_sys_fail_on_write(fptr);
2850  pos = lseek(fptr->fd, 0, SEEK_CUR);
2851  if (st.st_size >= pos && pos >= 0) {
2852  siz += st.st_size - pos;
2853  if (siz > LONG_MAX) {
2854  rb_raise(rb_eIOError, "file too big for single read");
2855  }
2856  }
2857  }
2858  else {
2859  siz += BUFSIZ;
2860  }
2861  return (long)siz;
2862 }
2863 
2864 static VALUE
2865 io_enc_str(VALUE str, rb_io_t *fptr)
2866 {
2867  rb_enc_associate(str, io_read_encoding(fptr));
2868  return str;
2869 }
2870 
2871 static void
2872 make_readconv(rb_io_t *fptr, int size)
2873 {
2874  if (!fptr->readconv) {
2875  int ecflags;
2876  VALUE ecopts;
2877  const char *sname, *dname;
2878  ecflags = fptr->encs.ecflags & ~ECONV_NEWLINE_DECORATOR_WRITE_MASK;
2879  ecopts = fptr->encs.ecopts;
2880  if (fptr->encs.enc2) {
2881  sname = rb_enc_name(fptr->encs.enc2);
2882  dname = rb_enc_name(fptr->encs.enc);
2883  }
2884  else {
2885  sname = dname = "";
2886  }
2887  fptr->readconv = rb_econv_open_opts(sname, dname, ecflags, ecopts);
2888  if (!fptr->readconv)
2889  rb_exc_raise(rb_econv_open_exc(sname, dname, ecflags));
2890  fptr->cbuf.off = 0;
2891  fptr->cbuf.len = 0;
2892  if (size < IO_CBUF_CAPA_MIN) size = IO_CBUF_CAPA_MIN;
2893  fptr->cbuf.capa = size;
2894  fptr->cbuf.ptr = ALLOC_N(char, fptr->cbuf.capa);
2895  }
2896 }
2897 
2898 #define MORE_CHAR_SUSPENDED Qtrue
2899 #define MORE_CHAR_FINISHED Qnil
2900 static VALUE
2901 fill_cbuf(rb_io_t *fptr, int ec_flags)
2902 {
2903  const unsigned char *ss, *sp, *se;
2904  unsigned char *ds, *dp, *de;
2905  rb_econv_result_t res;
2906  int putbackable;
2907  int cbuf_len0;
2908  VALUE exc;
2909 
2910  ec_flags |= ECONV_PARTIAL_INPUT;
2911 
2912  if (fptr->cbuf.len == fptr->cbuf.capa)
2913  return MORE_CHAR_SUSPENDED; /* cbuf full */
2914  if (fptr->cbuf.len == 0)
2915  fptr->cbuf.off = 0;
2916  else if (fptr->cbuf.off + fptr->cbuf.len == fptr->cbuf.capa) {
2917  memmove(fptr->cbuf.ptr, fptr->cbuf.ptr+fptr->cbuf.off, fptr->cbuf.len);
2918  fptr->cbuf.off = 0;
2919  }
2920 
2921  cbuf_len0 = fptr->cbuf.len;
2922 
2923  while (1) {
2924  ss = sp = (const unsigned char *)fptr->rbuf.ptr + fptr->rbuf.off;
2925  se = sp + fptr->rbuf.len;
2926  ds = dp = (unsigned char *)fptr->cbuf.ptr + fptr->cbuf.off + fptr->cbuf.len;
2927  de = (unsigned char *)fptr->cbuf.ptr + fptr->cbuf.capa;
2928  res = rb_econv_convert(fptr->readconv, &sp, se, &dp, de, ec_flags);
2929  fptr->rbuf.off += (int)(sp - ss);
2930  fptr->rbuf.len -= (int)(sp - ss);
2931  fptr->cbuf.len += (int)(dp - ds);
2932 
2933  putbackable = rb_econv_putbackable(fptr->readconv);
2934  if (putbackable) {
2935  rb_econv_putback(fptr->readconv, (unsigned char *)fptr->rbuf.ptr + fptr->rbuf.off - putbackable, putbackable);
2936  fptr->rbuf.off -= putbackable;
2937  fptr->rbuf.len += putbackable;
2938  }
2939 
2940  exc = rb_econv_make_exception(fptr->readconv);
2941  if (!NIL_P(exc))
2942  return exc;
2943 
2944  if (cbuf_len0 != fptr->cbuf.len)
2945  return MORE_CHAR_SUSPENDED;
2946 
2947  if (res == econv_finished) {
2948  return MORE_CHAR_FINISHED;
2949  }
2950 
2951  if (res == econv_source_buffer_empty) {
2952  if (fptr->rbuf.len == 0) {
2953  READ_CHECK(fptr);
2954  if (io_fillbuf(fptr) < 0) {
2955  if (!fptr->readconv) {
2956  return MORE_CHAR_FINISHED;
2957  }
2958  ds = dp = (unsigned char *)fptr->cbuf.ptr + fptr->cbuf.off + fptr->cbuf.len;
2959  de = (unsigned char *)fptr->cbuf.ptr + fptr->cbuf.capa;
2960  res = rb_econv_convert(fptr->readconv, NULL, NULL, &dp, de, 0);
2961  fptr->cbuf.len += (int)(dp - ds);
2963  break;
2964  }
2965  }
2966  }
2967  }
2968  if (cbuf_len0 != fptr->cbuf.len)
2969  return MORE_CHAR_SUSPENDED;
2970 
2971  return MORE_CHAR_FINISHED;
2972 }
2973 
2974 static VALUE
2975 more_char(rb_io_t *fptr)
2976 {
2977  VALUE v;
2978  v = fill_cbuf(fptr, ECONV_AFTER_OUTPUT);
2979  if (v != MORE_CHAR_SUSPENDED && v != MORE_CHAR_FINISHED)
2980  rb_exc_raise(v);
2981  return v;
2982 }
2983 
2984 static VALUE
2985 io_shift_cbuf(rb_io_t *fptr, int len, VALUE *strp)
2986 {
2987  VALUE str = Qnil;
2988  if (strp) {
2989  str = *strp;
2990  if (NIL_P(str)) {
2991  *strp = str = rb_str_new(fptr->cbuf.ptr+fptr->cbuf.off, len);
2992  }
2993  else {
2994  rb_str_cat(str, fptr->cbuf.ptr+fptr->cbuf.off, len);
2995  }
2996  rb_enc_associate(str, fptr->encs.enc);
2997  }
2998  fptr->cbuf.off += len;
2999  fptr->cbuf.len -= len;
3000  /* xxx: set coderange */
3001  if (fptr->cbuf.len == 0)
3002  fptr->cbuf.off = 0;
3003  else if (fptr->cbuf.capa/2 < fptr->cbuf.off) {
3004  memmove(fptr->cbuf.ptr, fptr->cbuf.ptr+fptr->cbuf.off, fptr->cbuf.len);
3005  fptr->cbuf.off = 0;
3006  }
3007  return str;
3008 }
3009 
3010 static int
3011 io_setstrbuf(VALUE *str, long len)
3012 {
3013 #ifdef _WIN32
3014  len = (len + 1) & ~1L; /* round up for wide char */
3015 #endif
3016  if (NIL_P(*str)) {
3017  *str = rb_str_new(0, len);
3018  return TRUE;
3019  }
3020  else {
3021  VALUE s = StringValue(*str);
3022  long clen = RSTRING_LEN(s);
3023  if (clen >= len) {
3024  rb_str_modify(s);
3025  return FALSE;
3026  }
3027  len -= clen;
3028  }
3029  rb_str_modify_expand(*str, len);
3030  return FALSE;
3031 }
3032 
3033 #define MAX_REALLOC_GAP 4096
3034 static void
3035 io_shrink_read_string(VALUE str, long n)
3036 {
3037  if (rb_str_capacity(str) - n > MAX_REALLOC_GAP) {
3038  rb_str_resize(str, n);
3039  }
3040 }
3041 
3042 static void
3043 io_set_read_length(VALUE str, long n, int shrinkable)
3044 {
3045  if (RSTRING_LEN(str) != n) {
3046  rb_str_modify(str);
3047  rb_str_set_len(str, n);
3048  if (shrinkable) io_shrink_read_string(str, n);
3049  }
3050 }
3051 
3052 static VALUE
3053 read_all(rb_io_t *fptr, long siz, VALUE str)
3054 {
3055  long bytes;
3056  long n;
3057  long pos;
3058  rb_encoding *enc;
3059  int cr;
3060  int shrinkable;
3061 
3062  if (NEED_READCONV(fptr)) {
3063  int first = !NIL_P(str);
3064  SET_BINARY_MODE(fptr);
3065  shrinkable = io_setstrbuf(&str,0);
3066  make_readconv(fptr, 0);
3067  while (1) {
3068  VALUE v;
3069  if (fptr->cbuf.len) {
3070  if (first) rb_str_set_len(str, first = 0);
3071  io_shift_cbuf(fptr, fptr->cbuf.len, &str);
3072  }
3073  v = fill_cbuf(fptr, 0);
3074  if (v != MORE_CHAR_SUSPENDED && v != MORE_CHAR_FINISHED) {
3075  if (fptr->cbuf.len) {
3076  if (first) rb_str_set_len(str, first = 0);
3077  io_shift_cbuf(fptr, fptr->cbuf.len, &str);
3078  }
3079  rb_exc_raise(v);
3080  }
3081  if (v == MORE_CHAR_FINISHED) {
3082  clear_readconv(fptr);
3083  if (first) rb_str_set_len(str, first = 0);
3084  if (shrinkable) io_shrink_read_string(str, RSTRING_LEN(str));
3085  return io_enc_str(str, fptr);
3086  }
3087  }
3088  }
3089 
3090  NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
3091  bytes = 0;
3092  pos = 0;
3093 
3094  enc = io_read_encoding(fptr);
3095  cr = 0;
3096 
3097  if (siz == 0) siz = BUFSIZ;
3098  shrinkable = io_setstrbuf(&str, siz);
3099  for (;;) {
3100  READ_CHECK(fptr);
3101  n = io_fread(str, bytes, siz - bytes, fptr);
3102  if (n == 0 && bytes == 0) {
3103  rb_str_set_len(str, 0);
3104  break;
3105  }
3106  bytes += n;
3107  rb_str_set_len(str, bytes);
3108  if (cr != ENC_CODERANGE_BROKEN)
3109  pos += rb_str_coderange_scan_restartable(RSTRING_PTR(str) + pos, RSTRING_PTR(str) + bytes, enc, &cr);
3110  if (bytes < siz) break;
3111  siz += BUFSIZ;
3112  rb_str_modify_expand(str, BUFSIZ);
3113  }
3114  if (shrinkable) io_shrink_read_string(str, RSTRING_LEN(str));
3115  str = io_enc_str(str, fptr);
3116  ENC_CODERANGE_SET(str, cr);
3117  return str;
3118 }
3119 
3120 void
3122 {
3123  if (rb_fd_set_nonblock(fptr->fd) != 0) {
3124  rb_sys_fail_path(fptr->pathv);
3125  }
3126 }
3127 
3128 static VALUE
3129 read_internal_call(VALUE arg)
3130 {
3131  struct io_internal_read_struct *iis = (struct io_internal_read_struct *)arg;
3132 
3133  VALUE scheduler = rb_fiber_scheduler_current();
3134  if (scheduler != Qnil) {
3135  VALUE result = rb_fiber_scheduler_io_read_memory(scheduler, iis->fptr->self, iis->buf, iis->capa, 0);
3136 
3137  if (result != Qundef) {
3138  // This is actually returned as a pseudo-VALUE and later cast to a long:
3139  return (VALUE)rb_fiber_scheduler_io_result_apply(result);
3140  }
3141  }
3142 
3143  return rb_thread_io_blocking_region(internal_read_func, iis, iis->fptr->fd);
3144 }
3145 
3146 static long
3147 read_internal_locktmp(VALUE str, struct io_internal_read_struct *iis)
3148 {
3149  return (long)rb_str_locktmp_ensure(str, read_internal_call, (VALUE)iis);
3150 }
3151 
3152 #define no_exception_p(opts) !rb_opts_exception_p((opts), TRUE)
3153 
3154 static VALUE
3155 io_getpartial(int argc, VALUE *argv, VALUE io, int no_exception, int nonblock)
3156 {
3157  rb_io_t *fptr;
3158  VALUE length, str;
3159  long n, len;
3160  struct io_internal_read_struct iis;
3161  int shrinkable;
3162 
3163  rb_scan_args(argc, argv, "11", &length, &str);
3164 
3165  if ((len = NUM2LONG(length)) < 0) {
3166  rb_raise(rb_eArgError, "negative length %ld given", len);
3167  }
3168 
3169  shrinkable = io_setstrbuf(&str, len);
3170 
3171  GetOpenFile(io, fptr);
3173 
3174  if (len == 0) {
3175  io_set_read_length(str, 0, shrinkable);
3176  return str;
3177  }
3178 
3179  if (!nonblock)
3180  READ_CHECK(fptr);
3181  n = read_buffered_data(RSTRING_PTR(str), len, fptr);
3182  if (n <= 0) {
3183  again:
3184  if (nonblock) {
3185  rb_io_set_nonblock(fptr);
3186  }
3187  io_setstrbuf(&str, len);
3188  iis.th = rb_thread_current();
3189  iis.fptr = fptr;
3190  iis.nonblock = nonblock;
3191  iis.buf = RSTRING_PTR(str);
3192  iis.capa = len;
3193  n = read_internal_locktmp(str, &iis);
3194  if (n < 0) {
3195  int e = errno;
3196  if (!nonblock && fptr_wait_readable(fptr))
3197  goto again;
3198  if (nonblock && (io_again_p(e))) {
3199  if (no_exception)
3200  return sym_wait_readable;
3201  else
3202  rb_readwrite_syserr_fail(RB_IO_WAIT_READABLE,
3203  e, "read would block");
3204  }
3205  rb_syserr_fail_path(e, fptr->pathv);
3206  }
3207  }
3208  io_set_read_length(str, n, shrinkable);
3209 
3210  if (n == 0)
3211  return Qnil;
3212  else
3213  return str;
3214 }
3215 
3216 /*
3217  * call-seq:
3218  * readpartial(maxlen) -> string
3219  * readpartial(maxlen, out_string) -> out_string
3220  *
3221  * Reads up to +maxlen+ bytes from the stream;
3222  * returns a string (either a new string or the given +out_string+).
3223  * Its encoding is:
3224  *
3225  * - The unchanged encoding of +out_string+, if +out_string+ is given.
3226  * - ASCII-8BIT, otherwise.
3227  *
3228  * - Contains +maxlen+ bytes from the stream, if available.
3229  * - Otherwise contains all available bytes, if any available.
3230  * - Otherwise is an empty string.
3231  *
3232  * With the single non-negative integer argument +maxlen+ given,
3233  * returns a new string:
3234  *
3235  * f = File.new('t.txt')
3236  * f.readpartial(30) # => "This is line one.\nThis is the"
3237  * f.readpartial(30) # => " second line.\nThis is the thi"
3238  * f.readpartial(30) # => "rd line.\n"
3239  * f.eof # => true
3240  * f.readpartial(30) # Raises EOFError.
3241  *
3242  * With both argument +maxlen+ and string argument +out_string+ given,
3243  * returns modified +out_string+:
3244  *
3245  * f = File.new('t.txt')
3246  * s = 'foo'
3247  * f.readpartial(30, s) # => "This is line one.\nThis is the"
3248  * s = 'bar'
3249  * f.readpartial(0, s) # => ""
3250  *
3251  * This method is useful for a stream such as a pipe, a socket, or a tty.
3252  * It blocks only when no data is immediately available.
3253  * This means that it blocks only when _all_ of the following are true:
3254  *
3255  * - The byte buffer in the stream is empty.
3256  * - The content of the stream is empty.
3257  * - The stream is not at EOF.
3258  *
3259  * When blocked, the method waits for either more data or EOF on the stream:
3260  *
3261  * - If more data is read, the method returns the data.
3262  * - If EOF is reached, the method raises EOFError.
3263  *
3264  * When not blocked, the method responds immediately:
3265  *
3266  * - Returns data from the buffer if there is any.
3267  * - Otherwise returns data from the stream if there is any.
3268  * - Otherwise raises EOFError if the stream has reached EOF.
3269  *
3270  * Note that this method is similar to sysread. The differences are:
3271  *
3272  * - If the byte buffer is not empty, read from the byte buffer
3273  * instead of "sysread for buffered IO (IOError)".
3274  * - It doesn't cause Errno::EWOULDBLOCK and Errno::EINTR. When
3275  * readpartial meets EWOULDBLOCK and EINTR by read system call,
3276  * readpartial retries the system call.
3277  *
3278  * The latter means that readpartial is non-blocking-flag insensitive.
3279  * It blocks on the situation IO#sysread causes Errno::EWOULDBLOCK as
3280  * if the fd is blocking mode.
3281  *
3282  * Examples:
3283  *
3284  * # # Returned Buffer Content Pipe Content
3285  * r, w = IO.pipe #
3286  * w << 'abc' # "" "abc".
3287  * r.readpartial(4096) # => "abc" "" ""
3288  * r.readpartial(4096) # (Blocks because buffer and pipe are empty.)
3289  *
3290  * # # Returned Buffer Content Pipe Content
3291  * r, w = IO.pipe #
3292  * w << 'abc' # "" "abc"
3293  * w.close # "" "abc" EOF
3294  * r.readpartial(4096) # => "abc" "" EOF
3295  * r.readpartial(4096) # raises EOFError
3296  *
3297  * # # Returned Buffer Content Pipe Content
3298  * r, w = IO.pipe #
3299  * w << "abc\ndef\n" # "" "abc\ndef\n"
3300  * r.gets # => "abc\n" "def\n" ""
3301  * w << "ghi\n" # "def\n" "ghi\n"
3302  * r.readpartial(4096) # => "def\n" "" "ghi\n"
3303  * r.readpartial(4096) # => "ghi\n" "" ""
3304  *
3305  */
3306 
3307 static VALUE
3308 io_readpartial(int argc, VALUE *argv, VALUE io)
3309 {
3310  VALUE ret;
3311 
3312  ret = io_getpartial(argc, argv, io, Qnil, 0);
3313  if (NIL_P(ret))
3314  rb_eof_error();
3315  return ret;
3316 }
3317 
3318 static VALUE
3319 io_nonblock_eof(int no_exception)
3320 {
3321  if (!no_exception) {
3322  rb_eof_error();
3323  }
3324  return Qnil;
3325 }
3326 
3327 /* :nodoc: */
3328 static VALUE
3329 io_read_nonblock(rb_execution_context_t *ec, VALUE io, VALUE length, VALUE str, VALUE ex)
3330 {
3331  rb_io_t *fptr;
3332  long n, len;
3333  struct io_internal_read_struct iis;
3334  int shrinkable;
3335 
3336  if ((len = NUM2LONG(length)) < 0) {
3337  rb_raise(rb_eArgError, "negative length %ld given", len);
3338  }
3339 
3340  shrinkable = io_setstrbuf(&str, len);
3341  rb_bool_expected(ex, "exception");
3342 
3343  GetOpenFile(io, fptr);
3345 
3346  if (len == 0) {
3347  io_set_read_length(str, 0, shrinkable);
3348  return str;
3349  }
3350 
3351  n = read_buffered_data(RSTRING_PTR(str), len, fptr);
3352  if (n <= 0) {
3353  rb_io_set_nonblock(fptr);
3354  shrinkable |= io_setstrbuf(&str, len);
3355  iis.fptr = fptr;
3356  iis.nonblock = 1;
3357  iis.buf = RSTRING_PTR(str);
3358  iis.capa = len;
3359  n = read_internal_locktmp(str, &iis);
3360  if (n < 0) {
3361  int e = errno;
3362  if (io_again_p(e)) {
3363  if (!ex) return sym_wait_readable;
3364  rb_readwrite_syserr_fail(RB_IO_WAIT_READABLE,
3365  e, "read would block");
3366  }
3367  rb_syserr_fail_path(e, fptr->pathv);
3368  }
3369  }
3370  io_set_read_length(str, n, shrinkable);
3371 
3372  if (n == 0) {
3373  if (!ex) return Qnil;
3374  rb_eof_error();
3375  }
3376 
3377  return str;
3378 }
3379 
3380 /* :nodoc: */
3381 static VALUE
3382 io_write_nonblock(rb_execution_context_t *ec, VALUE io, VALUE str, VALUE ex)
3383 {
3384  rb_io_t *fptr;
3385  long n;
3386 
3387  if (!RB_TYPE_P(str, T_STRING))
3388  str = rb_obj_as_string(str);
3389  rb_bool_expected(ex, "exception");
3390 
3391  io = GetWriteIO(io);
3392  GetOpenFile(io, fptr);
3393  rb_io_check_writable(fptr);
3394 
3395  if (io_fflush(fptr) < 0)
3396  rb_sys_fail_on_write(fptr);
3397 
3398  rb_io_set_nonblock(fptr);
3399  n = write(fptr->fd, RSTRING_PTR(str), RSTRING_LEN(str));
3400  RB_GC_GUARD(str);
3401 
3402  if (n < 0) {
3403  int e = errno;
3404  if (io_again_p(e)) {
3405  if (!ex) {
3406  return sym_wait_writable;
3407  }
3408  else {
3409  rb_readwrite_syserr_fail(RB_IO_WAIT_WRITABLE, e, "write would block");
3410  }
3411  }
3412  rb_syserr_fail_path(e, fptr->pathv);
3413  }
3414 
3415  return LONG2FIX(n);
3416 }
3417 
3418 /*
3419  * call-seq:
3420  * read(maxlen = nil) -> string or nil
3421  * read(maxlen = nil, out_string) -> out_string or nil
3422  *
3423  * Reads bytes from the stream (in binary mode):
3424  *
3425  * - If +maxlen+ is +nil+, reads all bytes.
3426  * - Otherwise reads +maxlen+ bytes, if available.
3427  * - Otherwise reads all bytes.
3428  *
3429  * Returns a string (either a new string or the given +out_string+)
3430  * containing the bytes read.
3431  * The encoding of the string depends on both +maxLen+ and +out_string+:
3432  *
3433  * - +maxlen+ is +nil+: uses internal encoding of +self+
3434  * (regardless of whether +out_string+ was given).
3435  * - +maxlen+ not +nil+:
3436  *
3437  * - +out_string+ given: encoding of +out_string+ not modified.
3438  * - +out_string+ not given: ASCII-8BIT is used.
3439  *
3440  * <b>Without Argument +out_string+</b>
3441  *
3442  * When argument +out_string+ is omitted,
3443  * the returned value is a new string:
3444  *
3445  * f = File.new('t.txt')
3446  * f.read
3447  * # => "This is line one.\nThis is the second line.\nThis is the third line.\n"
3448  * f.rewind
3449  * f.read(40) # => "This is line one.\r\nThis is the second li"
3450  * f.read(40) # => "ne.\r\nThis is the third line.\r\n"
3451  * f.read(40) # => nil
3452  *
3453  * If +maxlen+ is zero, returns an empty string.
3454  *
3455  * <b> With Argument +out_string+</b>
3456  *
3457  * When argument +out_string+ is given,
3458  * the returned value is +out_string+, whose content is replaced:
3459  *
3460  * f = File.new('t.txt')
3461  * s = 'foo' # => "foo"
3462  * f.read(nil, s) # => "This is line one.\nThis is the second line.\nThis is the third line.\n"
3463  * s # => "This is line one.\nThis is the second line.\nThis is the third line.\n"
3464  * f.rewind
3465  * s = 'bar'
3466  * f.read(40, s) # => "This is line one.\r\nThis is the second li"
3467  * s # => "This is line one.\r\nThis is the second li"
3468  * s = 'baz'
3469  * f.read(40, s) # => "ne.\r\nThis is the third line.\r\n"
3470  * s # => "ne.\r\nThis is the third line.\r\n"
3471  * s = 'bat'
3472  * f.read(40, s) # => nil
3473  * s # => ""
3474  *
3475  * Note that this method behaves like the fread() function in C.
3476  * This means it retries to invoke read(2) system calls to read data
3477  * with the specified maxlen (or until EOF).
3478  *
3479  * This behavior is preserved even if the stream is in non-blocking mode.
3480  * (This method is non-blocking-flag insensitive as other methods.)
3481  *
3482  * If you need the behavior like a single read(2) system call,
3483  * consider #readpartial, #read_nonblock, and #sysread.
3484  *
3485  */
3486 
3487 static VALUE
3488 io_read(int argc, VALUE *argv, VALUE io)
3489 {
3490  rb_io_t *fptr;
3491  long n, len;
3492  VALUE length, str;
3493  int shrinkable;
3494 #if RUBY_CRLF_ENVIRONMENT
3495  int previous_mode;
3496 #endif
3497 
3498  rb_scan_args(argc, argv, "02", &length, &str);
3499 
3500  if (NIL_P(length)) {
3501  GetOpenFile(io, fptr);
3503  return read_all(fptr, remain_size(fptr), str);
3504  }
3505  len = NUM2LONG(length);
3506  if (len < 0) {
3507  rb_raise(rb_eArgError, "negative length %ld given", len);
3508  }
3509 
3510  shrinkable = io_setstrbuf(&str,len);
3511 
3512  GetOpenFile(io, fptr);
3514  if (len == 0) {
3515  io_set_read_length(str, 0, shrinkable);
3516  return str;
3517  }
3518 
3519  READ_CHECK(fptr);
3520 #if RUBY_CRLF_ENVIRONMENT
3521  previous_mode = set_binary_mode_with_seek_cur(fptr);
3522 #endif
3523  n = io_fread(str, 0, len, fptr);
3524  io_set_read_length(str, n, shrinkable);
3525 #if RUBY_CRLF_ENVIRONMENT
3526  if (previous_mode == O_TEXT) {
3527  setmode(fptr->fd, O_TEXT);
3528  }
3529 #endif
3530  if (n == 0) return Qnil;
3531 
3532  return str;
3533 }
3534 
3535 static void
3536 rscheck(const char *rsptr, long rslen, VALUE rs)
3537 {
3538  if (!rs) return;
3539  if (RSTRING_PTR(rs) != rsptr && RSTRING_LEN(rs) != rslen)
3540  rb_raise(rb_eRuntimeError, "rs modified");
3541 }
3542 
3543 static int
3544 appendline(rb_io_t *fptr, int delim, VALUE *strp, long *lp)
3545 {
3546  VALUE str = *strp;
3547  long limit = *lp;
3548 
3549  if (NEED_READCONV(fptr)) {
3550  SET_BINARY_MODE(fptr);
3551  make_readconv(fptr, 0);
3552  do {
3553  const char *p, *e;
3554  int searchlen = READ_CHAR_PENDING_COUNT(fptr);
3555  if (searchlen) {
3556  p = READ_CHAR_PENDING_PTR(fptr);
3557  if (0 < limit && limit < searchlen)
3558  searchlen = (int)limit;
3559  e = memchr(p, delim, searchlen);
3560  if (e) {
3561  int len = (int)(e-p+1);
3562  if (NIL_P(str))
3563  *strp = str = rb_str_new(p, len);
3564  else
3565  rb_str_buf_cat(str, p, len);
3566  fptr->cbuf.off += len;
3567  fptr->cbuf.len -= len;
3568  limit -= len;
3569  *lp = limit;
3570  return delim;
3571  }
3572 
3573  if (NIL_P(str))
3574  *strp = str = rb_str_new(p, searchlen);
3575  else
3576  rb_str_buf_cat(str, p, searchlen);
3577  fptr->cbuf.off += searchlen;
3578  fptr->cbuf.len -= searchlen;
3579  limit -= searchlen;
3580 
3581  if (limit == 0) {
3582  *lp = limit;
3583  return (unsigned char)RSTRING_PTR(str)[RSTRING_LEN(str)-1];
3584  }
3585  }
3586  } while (more_char(fptr) != MORE_CHAR_FINISHED);
3587  clear_readconv(fptr);
3588  *lp = limit;
3589  return EOF;
3590  }
3591 
3592  NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
3593  do {
3594  long pending = READ_DATA_PENDING_COUNT(fptr);
3595  if (pending > 0) {
3596  const char *p = READ_DATA_PENDING_PTR(fptr);
3597  const char *e;
3598  long last;
3599 
3600  if (limit > 0 && pending > limit) pending = limit;
3601  e = memchr(p, delim, pending);
3602  if (e) pending = e - p + 1;
3603  if (!NIL_P(str)) {
3604  last = RSTRING_LEN(str);
3605  rb_str_resize(str, last + pending);
3606  }
3607  else {
3608  last = 0;
3609  *strp = str = rb_str_buf_new(pending);
3610  rb_str_set_len(str, pending);
3611  }
3612  read_buffered_data(RSTRING_PTR(str) + last, pending, fptr); /* must not fail */
3613  limit -= pending;
3614  *lp = limit;
3615  if (e) return delim;
3616  if (limit == 0)
3617  return (unsigned char)RSTRING_PTR(str)[RSTRING_LEN(str)-1];
3618  }
3619  READ_CHECK(fptr);
3620  } while (io_fillbuf(fptr) >= 0);
3621  *lp = limit;
3622  return EOF;
3623 }
3624 
3625 static inline int
3626 swallow(rb_io_t *fptr, int term)
3627 {
3628  if (NEED_READCONV(fptr)) {
3629  rb_encoding *enc = io_read_encoding(fptr);
3630  int needconv = rb_enc_mbminlen(enc) != 1;
3631  SET_BINARY_MODE(fptr);
3632  make_readconv(fptr, 0);
3633  do {
3634  size_t cnt;
3635  while ((cnt = READ_CHAR_PENDING_COUNT(fptr)) > 0) {
3636  const char *p = READ_CHAR_PENDING_PTR(fptr);
3637  int i;
3638  if (!needconv) {
3639  if (*p != term) return TRUE;
3640  i = (int)cnt;
3641  while (--i && *++p == term);
3642  }
3643  else {
3644  const char *e = p + cnt;
3645  if (rb_enc_ascget(p, e, &i, enc) != term) return TRUE;
3646  while ((p += i) < e && rb_enc_ascget(p, e, &i, enc) == term);
3647  i = (int)(e - p);
3648  }
3649  io_shift_cbuf(fptr, (int)cnt - i, NULL);
3650  }
3651  } while (more_char(fptr) != MORE_CHAR_FINISHED);
3652  return FALSE;
3653  }
3654 
3655  NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
3656  do {
3657  size_t cnt;
3658  while ((cnt = READ_DATA_PENDING_COUNT(fptr)) > 0) {
3659  char buf[1024];
3660  const char *p = READ_DATA_PENDING_PTR(fptr);
3661  int i;
3662  if (cnt > sizeof buf) cnt = sizeof buf;
3663  if (*p != term) return TRUE;
3664  i = (int)cnt;
3665  while (--i && *++p == term);
3666  if (!read_buffered_data(buf, cnt - i, fptr)) /* must not fail */
3667  rb_sys_fail_path(fptr->pathv);
3668  }
3669  READ_CHECK(fptr);
3670  } while (io_fillbuf(fptr) == 0);
3671  return FALSE;
3672 }
3673 
3674 static VALUE
3675 rb_io_getline_fast(rb_io_t *fptr, rb_encoding *enc, int chomp)
3676 {
3677  VALUE str = Qnil;
3678  int len = 0;
3679  long pos = 0;
3680  int cr = 0;
3681 
3682  do {
3683  int pending = READ_DATA_PENDING_COUNT(fptr);
3684 
3685  if (pending > 0) {
3686  const char *p = READ_DATA_PENDING_PTR(fptr);
3687  const char *e;
3688  int chomplen = 0;
3689 
3690  e = memchr(p, '\n', pending);
3691  if (e) {
3692  pending = (int)(e - p + 1);
3693  if (chomp) {
3694  chomplen = (pending > 1 && *(e-1) == '\r') + 1;
3695  }
3696  }
3697  if (NIL_P(str)) {
3698  str = rb_str_new(p, pending - chomplen);
3699  fptr->rbuf.off += pending;
3700  fptr->rbuf.len -= pending;
3701  }
3702  else {
3703  rb_str_resize(str, len + pending - chomplen);
3704  read_buffered_data(RSTRING_PTR(str)+len, pending - chomplen, fptr);
3705  fptr->rbuf.off += chomplen;
3706  fptr->rbuf.len -= chomplen;
3707  if (pending == 1 && chomplen == 1 && len > 0) {
3708  if (RSTRING_PTR(str)[len-1] == '\r') {
3709  rb_str_resize(str, --len);
3710  break;
3711  }
3712  }
3713  }
3714  len += pending - chomplen;
3715  if (cr != ENC_CODERANGE_BROKEN)
3716  pos += rb_str_coderange_scan_restartable(RSTRING_PTR(str) + pos, RSTRING_PTR(str) + len, enc, &cr);
3717  if (e) break;
3718  }
3719  READ_CHECK(fptr);
3720  } while (io_fillbuf(fptr) >= 0);
3721  if (NIL_P(str)) return Qnil;
3722 
3723  str = io_enc_str(str, fptr);
3724  ENC_CODERANGE_SET(str, cr);
3725  fptr->lineno++;
3726 
3727  return str;
3728 }
3729 
3730 struct getline_arg {
3731  VALUE io;
3732  VALUE rs;
3733  long limit;
3734  unsigned int chomp: 1;
3735 };
3736 
3737 static void
3738 extract_getline_opts(VALUE opts, struct getline_arg *args)
3739 {
3740  int chomp = FALSE;
3741  if (!NIL_P(opts)) {
3742  static ID kwds[1];
3743  VALUE vchomp;
3744  if (!kwds[0]) {
3745  kwds[0] = rb_intern_const("chomp");
3746  }
3747  rb_get_kwargs(opts, kwds, 0, -2, &vchomp);
3748  chomp = (vchomp != Qundef) && RTEST(vchomp);
3749  }
3750  args->chomp = chomp;
3751 }
3752 
3753 static void
3754 extract_getline_args(int argc, VALUE *argv, struct getline_arg *args)
3755 {
3756  VALUE rs = rb_rs, lim = Qnil;
3757 
3758  if (argc == 1) {
3759  VALUE tmp = Qnil;
3760 
3761  if (NIL_P(argv[0]) || !NIL_P(tmp = rb_check_string_type(argv[0]))) {
3762  rs = tmp;
3763  }
3764  else {
3765  lim = argv[0];
3766  }
3767  }
3768  else if (2 <= argc) {
3769  rs = argv[0], lim = argv[1];
3770  if (!NIL_P(rs))
3771  StringValue(rs);
3772  }
3773  args->rs = rs;
3774  args->limit = NIL_P(lim) ? -1L : NUM2LONG(lim);
3775 }
3776 
3777 static void
3778 check_getline_args(VALUE *rsp, long *limit, VALUE io)
3779 {
3780  rb_io_t *fptr;
3781  VALUE rs = *rsp;
3782 
3783  if (!NIL_P(rs)) {
3784  rb_encoding *enc_rs, *enc_io;
3785 
3786  GetOpenFile(io, fptr);
3787  enc_rs = rb_enc_get(rs);
3788  enc_io = io_read_encoding(fptr);
3789  if (enc_io != enc_rs &&
3791  (RSTRING_LEN(rs) > 0 && !rb_enc_asciicompat(enc_io)))) {
3792  if (rs == rb_default_rs) {
3793  rs = rb_enc_str_new(0, 0, enc_io);
3794  rb_str_buf_cat_ascii(rs, "\n");
3795  *rsp = rs;
3796  }
3797  else {
3798  rb_raise(rb_eArgError, "encoding mismatch: %s IO with %s RS",
3799  rb_enc_name(enc_io),
3800  rb_enc_name(enc_rs));
3801  }
3802  }
3803  }
3804 }
3805 
3806 static void
3807 prepare_getline_args(int argc, VALUE *argv, struct getline_arg *args, VALUE io)
3808 {
3809  VALUE opts;
3810  argc = rb_scan_args(argc, argv, "02:", NULL, NULL, &opts);
3811  extract_getline_args(argc, argv, args);
3812  extract_getline_opts(opts, args);
3813  check_getline_args(&args->rs, &args->limit, io);
3814 }
3815 
3816 static VALUE
3817 rb_io_getline_0(VALUE rs, long limit, int chomp, rb_io_t *fptr)
3818 {
3819  VALUE str = Qnil;
3820  int nolimit = 0;
3821  rb_encoding *enc;
3822 
3824  if (NIL_P(rs) && limit < 0) {
3825  str = read_all(fptr, 0, Qnil);
3826  if (RSTRING_LEN(str) == 0) return Qnil;
3827  if (chomp) rb_str_chomp_string(str, rb_default_rs);
3828  }
3829  else if (limit == 0) {
3830  return rb_enc_str_new(0, 0, io_read_encoding(fptr));
3831  }
3832  else if (rs == rb_default_rs && limit < 0 && !NEED_READCONV(fptr) &&
3833  rb_enc_asciicompat(enc = io_read_encoding(fptr))) {
3834  NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
3835  return rb_io_getline_fast(fptr, enc, chomp);
3836  }
3837  else {
3838  int c, newline = -1;
3839  const char *rsptr = 0;
3840  long rslen = 0;
3841  int rspara = 0;
3842  int extra_limit = 16;
3843  int chomp_cr = chomp;
3844 
3845  SET_BINARY_MODE(fptr);
3846  enc = io_read_encoding(fptr);
3847 
3848  if (!NIL_P(rs)) {
3849  rslen = RSTRING_LEN(rs);
3850  if (rslen == 0) {
3851  rsptr = "\n\n";
3852  rslen = 2;
3853  rspara = 1;
3854  swallow(fptr, '\n');
3855  rs = 0;
3856  if (!rb_enc_asciicompat(enc)) {
3857  rs = rb_usascii_str_new(rsptr, rslen);
3858  rs = rb_str_encode(rs, rb_enc_from_encoding(enc), 0, Qnil);
3859  OBJ_FREEZE(rs);
3860  rsptr = RSTRING_PTR(rs);
3861  rslen = RSTRING_LEN(rs);
3862  }
3863  }
3864  else {
3865  rsptr = RSTRING_PTR(rs);
3866  }
3867  newline = (unsigned char)rsptr[rslen - 1];
3868  chomp_cr = chomp && rslen == 1 && newline == '\n';
3869  }
3870 
3871  /* MS - Optimization */
3872  while ((c = appendline(fptr, newline, &str, &limit)) != EOF) {
3873  const char *s, *p, *pp, *e;
3874 
3875  if (c == newline) {
3876  if (RSTRING_LEN(str) < rslen) continue;
3877  s = RSTRING_PTR(str);
3878  e = RSTRING_END(str);
3879  p = e - rslen;
3880  pp = rb_enc_left_char_head(s, p, e, enc);
3881  if (pp != p) continue;
3882  if (!rspara) rscheck(rsptr, rslen, rs);
3883  if (memcmp(p, rsptr, rslen) == 0) {
3884  if (chomp) {
3885  if (chomp_cr && p > s && *(p-1) == '\r') --p;
3886  rb_str_set_len(str, p - s);
3887  }
3888  break;
3889  }
3890  }
3891  if (limit == 0) {
3892  s = RSTRING_PTR(str);
3893  p = RSTRING_END(str);
3894  pp = rb_enc_left_char_head(s, p-1, p, enc);
3895  if (extra_limit &&
3897  /* relax the limit while incomplete character.
3898  * extra_limit limits the relax length */
3899  limit = 1;
3900  extra_limit--;
3901  }
3902  else {
3903  nolimit = 1;
3904  break;
3905  }
3906  }
3907  }
3908 
3909  if (rspara && c != EOF)
3910  swallow(fptr, '\n');
3911  if (!NIL_P(str))
3912  str = io_enc_str(str, fptr);
3913  }
3914 
3915  if (!NIL_P(str) && !nolimit) {
3916  fptr->lineno++;
3917  }
3918 
3919  return str;
3920 }
3921 
3922 static VALUE
3923 rb_io_getline_1(VALUE rs, long limit, int chomp, VALUE io)
3924 {
3925  rb_io_t *fptr;
3926  int old_lineno, new_lineno;
3927  VALUE str;
3928 
3929  GetOpenFile(io, fptr);
3930  old_lineno = fptr->lineno;
3931  str = rb_io_getline_0(rs, limit, chomp, fptr);
3932  if (!NIL_P(str) && (new_lineno = fptr->lineno) != old_lineno) {
3933  if (io == ARGF.current_file) {
3934  ARGF.lineno += new_lineno - old_lineno;
3935  ARGF.last_lineno = ARGF.lineno;
3936  }
3937  else {
3938  ARGF.last_lineno = new_lineno;
3939  }
3940  }
3941 
3942  return str;
3943 }
3944 
3945 static VALUE
3946 rb_io_getline(int argc, VALUE *argv, VALUE io)
3947 {
3948  struct getline_arg args;
3949 
3950  prepare_getline_args(argc, argv, &args, io);
3951  return rb_io_getline_1(args.rs, args.limit, args.chomp, io);
3952 }
3953 
3954 VALUE
3956 {
3957  return rb_io_getline_1(rb_default_rs, -1, FALSE, io);
3958 }
3959 
3960 VALUE
3961 rb_io_gets_internal(VALUE io)
3962 {
3963  rb_io_t *fptr;
3964  GetOpenFile(io, fptr);
3965  return rb_io_getline_0(rb_default_rs, -1, FALSE, fptr);
3966 }
3967 
3968 /*
3969  * call-seq:
3970  * gets(sep = $/, **getline_opts) -> string or nil
3971  * gets(limit, **getline_opts) -> string or nil
3972  * gets(sep, limit, **getline_opts) -> string or nil
3973  *
3974  * Reads and returns data from the stream;
3975  * assigns the return value to <tt>$_</tt>.
3976  *
3977  * With no arguments given, returns the next line
3978  * as determined by line separator <tt>$/</tt>, or +nil+ if none:
3979  *
3980  * f = File.open('t.txt')
3981  * f.gets # => "This is line one.\n"
3982  * $_ # => "This is line one.\n"
3983  * f.gets # => "This is the second line.\n"
3984  * f.gets # => "This is the third line.\n"
3985  * f.gets # => nil
3986  *
3987  * With string argument +sep+ given, but not argument +limit+,
3988  * returns the next line as determined by line separator +sep+,
3989  * or +nil+ if none:
3990  *
3991  * f = File.open('t.txt')
3992  * f.gets(' is') # => "This is"
3993  * f.gets(' is') # => " line one.\nThis is"
3994  * f.gets(' is') # => " the second line.\nThis is"
3995  * f.gets(' is') # => " the third line.\n"
3996  * f.gets(' is') # => nil
3997  *
3998  * Note two special values for +sep+:
3999  *
4000  * - +nil+: The entire stream is read and returned.
4001  * - <tt>''</tt> (empty string): The next "paragraph" is read and returned,
4002  * the paragraph separator being two successive line separators.
4003  *
4004  * With integer argument +limit+ given,
4005  * returns up to <tt>limit+1</tt> bytes:
4006  *
4007  * # Text with 1-byte characters.
4008  * File.open('t.txt') {|f| f.gets(1) } # => "T"
4009  * File.open('t.txt') {|f| f.gets(2) } # => "Th"
4010  * File.open('t.txt') {|f| f.gets(3) } # => "Thi"
4011  * File.open('t.txt') {|f| f.gets(4) } # => "This"
4012  * # No more than one line.
4013  * File.open('t.txt') {|f| f.gets(17) } # => "This is line one."
4014  * File.open('t.txt') {|f| f.gets(18) } # => "This is line one.\n"
4015  * File.open('t.txt') {|f| f.gets(19) } # => "This is line one.\n"
4016  *
4017  * # Text with 2-byte characters, which will not be split.
4018  * File.open('t.rus') {|f| f.gets(1).size } # => 1
4019  * File.open('t.rus') {|f| f.gets(2).size } # => 1
4020  * File.open('t.rus') {|f| f.gets(3).size } # => 2
4021  * File.open('t.rus') {|f| f.gets(4).size } # => 2
4022  *
4023  * With arguments +sep+ and +limit+,
4024  * combines the two behaviors above:
4025  *
4026  * - Returns the next line as determined by line separator +sep+,
4027  * or +nil+ if none.
4028  * - But returns no more than <tt>limit+1</tt> bytes.
4029  *
4030  * For all forms above, trailing optional keyword arguments may be given;
4031  * see {Getline Options}[#class-IO-label-Getline+Options]:
4032  *
4033  * f = File.open('t.txt')
4034  * # Chomp the lines.
4035  * f.gets(chomp: true) # => "This is line one."
4036  * f.gets(chomp: true) # => "This is the second line."
4037  * f.gets(chomp: true) # => "This is the third line."
4038  * f.gets(chomp: true) # => nil
4039  *
4040  */
4041 
4042 static VALUE
4043 rb_io_gets_m(int argc, VALUE *argv, VALUE io)
4044 {
4045  VALUE str;
4046 
4047  str = rb_io_getline(argc, argv, io);
4048  rb_lastline_set(str);
4049 
4050  return str;
4051 }
4052 
4053 /*
4054  * call-seq:
4055  * ios.lineno -> integer
4056  *
4057  * Returns the current line number in <em>ios</em>. The stream must be
4058  * opened for reading. #lineno counts the number of times #gets is called
4059  * rather than the number of newlines encountered. The two values will
4060  * differ if #gets is called with a separator other than newline.
4061  *
4062  * Methods that use <code>$/</code> like #each, #lines and #readline will
4063  * also increment #lineno.
4064  *
4065  * See also the <code>$.</code> variable.
4066  *
4067  * f = File.new("testfile")
4068  * f.lineno #=> 0
4069  * f.gets #=> "This is line one\n"
4070  * f.lineno #=> 1
4071  * f.gets #=> "This is line two\n"
4072  * f.lineno #=> 2
4073  */
4074 
4075 static VALUE
4076 rb_io_lineno(VALUE io)
4077 {
4078  rb_io_t *fptr;
4079 
4080  GetOpenFile(io, fptr);
4082  return INT2NUM(fptr->lineno);
4083 }
4084 
4085 /*
4086  * call-seq:
4087  * ios.lineno = integer -> integer
4088  *
4089  * Manually sets the current line number to the given value.
4090  * <code>$.</code> is updated only on the next read.
4091  *
4092  * f = File.new("testfile")
4093  * f.gets #=> "This is line one\n"
4094  * $. #=> 1
4095  * f.lineno = 1000
4096  * f.lineno #=> 1000
4097  * $. #=> 1 # lineno of last read
4098  * f.gets #=> "This is line two\n"
4099  * $. #=> 1001 # lineno of last read
4100  */
4101 
4102 static VALUE
4103 rb_io_set_lineno(VALUE io, VALUE lineno)
4104 {
4105  rb_io_t *fptr;
4106 
4107  GetOpenFile(io, fptr);
4109  fptr->lineno = NUM2INT(lineno);
4110  return lineno;
4111 }
4112 
4113 /*
4114  * call-seq:
4115  * ios.readline(sep=$/ [, getline_args]) -> string
4116  * ios.readline(limit [, getline_args]) -> string
4117  * ios.readline(sep, limit [, getline_args]) -> string
4118  *
4119  * Reads a line as with IO#gets, but raises an EOFError on end of file.
4120  */
4121 
4122 static VALUE
4123 rb_io_readline(int argc, VALUE *argv, VALUE io)
4124 {
4125  VALUE line = rb_io_gets_m(argc, argv, io);
4126 
4127  if (NIL_P(line)) {
4128  rb_eof_error();
4129  }
4130  return line;
4131 }
4132 
4133 static VALUE io_readlines(const struct getline_arg *arg, VALUE io);
4134 
4135 /*
4136  * call-seq:
4137  * ios.readlines(sep=$/ [, getline_args]) -> array
4138  * ios.readlines(limit [, getline_args]) -> array
4139  * ios.readlines(sep, limit [, getline_args]) -> array
4140  *
4141  * Reads all of the lines in <em>ios</em>, and returns them in
4142  * an array. Lines are separated by the optional <i>sep</i>. If
4143  * <i>sep</i> is +nil+, the rest of the stream is returned
4144  * as a single record.
4145  * If the first argument is an integer, or an
4146  * optional second argument is given, the returning string would not be
4147  * longer than the given value in bytes. The stream must be opened for
4148  * reading or an IOError will be raised.
4149  *
4150  * f = File.new("testfile")
4151  * f.readlines[0] #=> "This is line one\n"
4152  *
4153  * f = File.new("testfile", chomp: true)
4154  * f.readlines[0] #=> "This is line one"
4155  *
4156  * See IO.readlines for details about getline_args.
4157  */
4158 
4159 static VALUE
4160 rb_io_readlines(int argc, VALUE *argv, VALUE io)
4161 {
4162  struct getline_arg args;
4163 
4164  prepare_getline_args(argc, argv, &args, io);
4165  return io_readlines(&args, io);
4166 }
4167 
4168 static VALUE
4169 io_readlines(const struct getline_arg *arg, VALUE io)
4170 {
4171  VALUE line, ary;
4172 
4173  if (arg->limit == 0)
4174  rb_raise(rb_eArgError, "invalid limit: 0 for readlines");
4175  ary = rb_ary_new();
4176  while (!NIL_P(line = rb_io_getline_1(arg->rs, arg->limit, arg->chomp, io))) {
4177  rb_ary_push(ary, line);
4178  }
4179  return ary;
4180 }
4181 
4182 /*
4183  * call-seq:
4184  * ios.each(sep=$/ [, getline_args]) {|line| block } -> ios
4185  * ios.each(limit [, getline_args]) {|line| block } -> ios
4186  * ios.each(sep, limit [, getline_args]) {|line| block } -> ios
4187  * ios.each(...) -> an_enumerator
4188  *
4189  * ios.each_line(sep=$/ [, getline_args]) {|line| block } -> ios
4190  * ios.each_line(limit [, getline_args]) {|line| block } -> ios
4191  * ios.each_line(sep, limit [, getline_args]) {|line| block } -> ios
4192  * ios.each_line(...) -> an_enumerator
4193  *
4194  * Executes the block for every line in <em>ios</em>, where lines are
4195  * separated by <i>sep</i>. <em>ios</em> must be opened for
4196  * reading or an IOError will be raised.
4197  *
4198  * If no block is given, an enumerator is returned instead.
4199  *
4200  * f = File.new("testfile")
4201  * f.each {|line| puts "#{f.lineno}: #{line}" }
4202  *
4203  * <em>produces:</em>
4204  *
4205  * 1: This is line one
4206  * 2: This is line two
4207  * 3: This is line three
4208  * 4: And so on...
4209  *
4210  * See IO.readlines for details about getline_args.
4211  */
4212 
4213 static VALUE
4214 rb_io_each_line(int argc, VALUE *argv, VALUE io)
4215 {
4216  VALUE str;
4217  struct getline_arg args;
4218 
4219  RETURN_ENUMERATOR(io, argc, argv);
4220  prepare_getline_args(argc, argv, &args, io);
4221  if (args.limit == 0)
4222  rb_raise(rb_eArgError, "invalid limit: 0 for each_line");
4223  while (!NIL_P(str = rb_io_getline_1(args.rs, args.limit, args.chomp, io))) {
4224  rb_yield(str);
4225  }
4226  return io;
4227 }
4228 
4229 /*
4230  * call-seq:
4231  * ios.each_byte {|byte| block } -> ios
4232  * ios.each_byte -> an_enumerator
4233  *
4234  * Calls the given block once for each byte (0..255) in <em>ios</em>,
4235  * passing the byte as an argument. The stream must be opened for
4236  * reading or an IOError will be raised.
4237  *
4238  * If no block is given, an enumerator is returned instead.
4239  *
4240  * f = File.new("testfile")
4241  * checksum = 0
4242  * f.each_byte {|x| checksum ^= x } #=> #<File:testfile>
4243  * checksum #=> 12
4244  */
4245 
4246 static VALUE
4247 rb_io_each_byte(VALUE io)
4248 {
4249  rb_io_t *fptr;
4250 
4251  RETURN_ENUMERATOR(io, 0, 0);
4252  GetOpenFile(io, fptr);
4253 
4254  do {
4255  while (fptr->rbuf.len > 0) {
4256  char *p = fptr->rbuf.ptr + fptr->rbuf.off++;
4257  fptr->rbuf.len--;
4258  rb_yield(INT2FIX(*p & 0xff));
4260  errno = 0;
4261  }
4262  READ_CHECK(fptr);
4263  } while (io_fillbuf(fptr) >= 0);
4264  return io;
4265 }
4266 
4267 static VALUE
4268 io_getc(rb_io_t *fptr, rb_encoding *enc)
4269 {
4270  int r, n, cr = 0;
4271  VALUE str;
4272 
4273  if (NEED_READCONV(fptr)) {
4274  rb_encoding *read_enc = io_read_encoding(fptr);
4275 
4276  str = Qnil;
4277  SET_BINARY_MODE(fptr);
4278  make_readconv(fptr, 0);
4279 
4280  while (1) {
4281  if (fptr->cbuf.len) {
4282  r = rb_enc_precise_mbclen(fptr->cbuf.ptr+fptr->cbuf.off,
4283  fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
4284  read_enc);
4285  if (!MBCLEN_NEEDMORE_P(r))
4286  break;
4287  if (fptr->cbuf.len == fptr->cbuf.capa) {
4288  rb_raise(rb_eIOError, "too long character");
4289  }
4290  }
4291 
4292  if (more_char(fptr) == MORE_CHAR_FINISHED) {
4293  if (fptr->cbuf.len == 0) {
4294  clear_readconv(fptr);
4295  return Qnil;
4296  }
4297  /* return an unit of an incomplete character just before EOF */
4298  str = rb_enc_str_new(fptr->cbuf.ptr+fptr->cbuf.off, 1, read_enc);
4299  fptr->cbuf.off += 1;
4300  fptr->cbuf.len -= 1;
4301  if (fptr->cbuf.len == 0) clear_readconv(fptr);
4303  return str;
4304  }
4305  }
4306  if (MBCLEN_INVALID_P(r)) {
4307  r = rb_enc_mbclen(fptr->cbuf.ptr+fptr->cbuf.off,
4308  fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
4309  read_enc);
4310  io_shift_cbuf(fptr, r, &str);
4311  cr = ENC_CODERANGE_BROKEN;
4312  }
4313  else {
4314  io_shift_cbuf(fptr, MBCLEN_CHARFOUND_LEN(r), &str);
4315  cr = ENC_CODERANGE_VALID;
4316  if (MBCLEN_CHARFOUND_LEN(r) == 1 && rb_enc_asciicompat(read_enc) &&
4317  ISASCII(RSTRING_PTR(str)[0])) {
4318  cr = ENC_CODERANGE_7BIT;
4319  }
4320  }
4321  str = io_enc_str(str, fptr);
4322  ENC_CODERANGE_SET(str, cr);
4323  return str;
4324  }
4325 
4326  NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
4327  if (io_fillbuf(fptr) < 0) {
4328  return Qnil;
4329  }
4330  if (rb_enc_asciicompat(enc) && ISASCII(fptr->rbuf.ptr[fptr->rbuf.off])) {
4331  str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, 1);
4332  fptr->rbuf.off += 1;
4333  fptr->rbuf.len -= 1;
4334  cr = ENC_CODERANGE_7BIT;
4335  }
4336  else {
4337  r = rb_enc_precise_mbclen(fptr->rbuf.ptr+fptr->rbuf.off, fptr->rbuf.ptr+fptr->rbuf.off+fptr->rbuf.len, enc);
4338  if (MBCLEN_CHARFOUND_P(r) &&
4339  (n = MBCLEN_CHARFOUND_LEN(r)) <= fptr->rbuf.len) {
4340  str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, n);
4341  fptr->rbuf.off += n;
4342  fptr->rbuf.len -= n;
4343  cr = ENC_CODERANGE_VALID;
4344  }
4345  else if (MBCLEN_NEEDMORE_P(r)) {
4346  str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, fptr->rbuf.len);
4347  fptr->rbuf.len = 0;
4348  getc_needmore:
4349  if (io_fillbuf(fptr) != -1) {
4350  rb_str_cat(str, fptr->rbuf.ptr+fptr->rbuf.off, 1);
4351  fptr->rbuf.off++;
4352  fptr->rbuf.len--;
4353  r = rb_enc_precise_mbclen(RSTRING_PTR(str), RSTRING_PTR(str)+RSTRING_LEN(str), enc);
4354  if (MBCLEN_NEEDMORE_P(r)) {
4355  goto getc_needmore;
4356  }
4357  else if (MBCLEN_CHARFOUND_P(r)) {
4358  cr = ENC_CODERANGE_VALID;
4359  }
4360  }
4361  }
4362  else {
4363  str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, 1);
4364  fptr->rbuf.off++;
4365  fptr->rbuf.len--;
4366  }
4367  }
4368  if (!cr) cr = ENC_CODERANGE_BROKEN;
4369  str = io_enc_str(str, fptr);
4370  ENC_CODERANGE_SET(str, cr);
4371  return str;
4372 }
4373 
4374 /*
4375  * call-seq:
4376  * ios.each_char {|c| block } -> ios
4377  * ios.each_char -> an_enumerator
4378  *
4379  * Calls the given block once for each character in <em>ios</em>,
4380  * passing the character as an argument. The stream must be opened for
4381  * reading or an IOError will be raised.
4382  *
4383  * If no block is given, an enumerator is returned instead.
4384  *
4385  * f = File.new("testfile")
4386  * f.each_char {|c| print c, ' ' } #=> #<File:testfile>
4387  */
4388 
4389 static VALUE
4390 rb_io_each_char(VALUE io)
4391 {
4392  rb_io_t *fptr;
4393  rb_encoding *enc;
4394  VALUE c;
4395 
4396  RETURN_ENUMERATOR(io, 0, 0);
4397  GetOpenFile(io, fptr);
4399 
4400  enc = io_input_encoding(fptr);
4401  READ_CHECK(fptr);
4402  while (!NIL_P(c = io_getc(fptr, enc))) {
4403  rb_yield(c);
4404  }
4405  return io;
4406 }
4407 
4408 /*
4409  * call-seq:
4410  * ios.each_codepoint {|c| block } -> ios
4411  * ios.each_codepoint -> an_enumerator
4412  *
4413  * Passes the Integer ordinal of each character in <i>ios</i>,
4414  * passing the codepoint as an argument. The stream must be opened for
4415  * reading or an IOError will be raised.
4416  *
4417  * If no block is given, an enumerator is returned instead.
4418  *
4419  */
4420 
4421 static VALUE
4422 rb_io_each_codepoint(VALUE io)
4423 {
4424  rb_io_t *fptr;
4425  rb_encoding *enc;
4426  unsigned int c;
4427  int r, n;
4428 
4429  RETURN_ENUMERATOR(io, 0, 0);
4430  GetOpenFile(io, fptr);
4432 
4433  READ_CHECK(fptr);
4434  if (NEED_READCONV(fptr)) {
4435  SET_BINARY_MODE(fptr);
4436  r = 1; /* no invalid char yet */
4437  for (;;) {
4438  make_readconv(fptr, 0);
4439  for (;;) {
4440  if (fptr->cbuf.len) {
4441  if (fptr->encs.enc)
4442  r = rb_enc_precise_mbclen(fptr->cbuf.ptr+fptr->cbuf.off,
4443  fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
4444  fptr->encs.enc);
4445  else
4446  r = ONIGENC_CONSTRUCT_MBCLEN_CHARFOUND(1);
4447  if (!MBCLEN_NEEDMORE_P(r))
4448  break;
4449  if (fptr->cbuf.len == fptr->cbuf.capa) {
4450  rb_raise(rb_eIOError, "too long character");
4451  }
4452  }
4453  if (more_char(fptr) == MORE_CHAR_FINISHED) {
4454  clear_readconv(fptr);
4455  if (!MBCLEN_CHARFOUND_P(r)) {
4456  enc = fptr->encs.enc;
4457  goto invalid;
4458  }
4459  return io;
4460  }
4461  }
4462  if (MBCLEN_INVALID_P(r)) {
4463  enc = fptr->encs.enc;
4464  goto invalid;
4465  }
4466  n = MBCLEN_CHARFOUND_LEN(r);
4467  if (fptr->encs.enc) {
4468  c = rb_enc_codepoint(fptr->cbuf.ptr+fptr->cbuf.off,
4469  fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
4470  fptr->encs.enc);
4471  }
4472  else {
4473  c = (unsigned char)fptr->cbuf.ptr[fptr->cbuf.off];
4474  }
4475  fptr->cbuf.off += n;
4476  fptr->cbuf.len -= n;
4477  rb_yield(UINT2NUM(c));
4479  }
4480  }
4481  NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
4482  enc = io_input_encoding(fptr);
4483  while (io_fillbuf(fptr) >= 0) {
4484  r = rb_enc_precise_mbclen(fptr->rbuf.ptr+fptr->rbuf.off,
4485  fptr->rbuf.ptr+fptr->rbuf.off+fptr->rbuf.len, enc);
4486  if (MBCLEN_CHARFOUND_P(r) &&
4487  (n = MBCLEN_CHARFOUND_LEN(r)) <= fptr->rbuf.len) {
4488  c = rb_enc_codepoint(fptr->rbuf.ptr+fptr->rbuf.off,
4489  fptr->rbuf.ptr+fptr->rbuf.off+fptr->rbuf.len, enc);
4490  fptr->rbuf.off += n;
4491  fptr->rbuf.len -= n;
4492  rb_yield(UINT2NUM(c));
4493  }
4494  else if (MBCLEN_INVALID_P(r)) {
4495  goto invalid;
4496  }
4497  else if (MBCLEN_NEEDMORE_P(r)) {
4498  char cbuf[8], *p = cbuf;
4499  int more = MBCLEN_NEEDMORE_LEN(r);
4500  if (more > numberof(cbuf)) goto invalid;
4501  more += n = fptr->rbuf.len;
4502  if (more > numberof(cbuf)) goto invalid;
4503  while ((n = (int)read_buffered_data(p, more, fptr)) > 0 &&
4504  (p += n, (more -= n) > 0)) {
4505  if (io_fillbuf(fptr) < 0) goto invalid;
4506  if ((n = fptr->rbuf.len) > more) n = more;
4507  }
4508  r = rb_enc_precise_mbclen(cbuf, p, enc);
4509  if (!MBCLEN_CHARFOUND_P(r)) goto invalid;
4510  c = rb_enc_codepoint(cbuf, p, enc);
4511  rb_yield(UINT2NUM(c));
4512  }
4513  else {
4514  continue;
4515  }
4517  }
4518  return io;
4519 
4520  invalid:
4521  rb_raise(rb_eArgError, "invalid byte sequence in %s", rb_enc_name(enc));
4523 }
4524 
4525 /*
4526  * call-seq:
4527  * ios.getc -> string or nil
4528  *
4529  * Reads a one-character string from <em>ios</em>. Returns
4530  * +nil+ if called at end of file.
4531  *
4532  * f = File.new("testfile")
4533  * f.getc #=> "h"
4534  * f.getc #=> "e"
4535  */
4536 
4537 static VALUE
4538 rb_io_getc(VALUE io)
4539 {
4540  rb_io_t *fptr;
4541  rb_encoding *enc;
4542 
4543  GetOpenFile(io, fptr);
4545 
4546  enc = io_input_encoding(fptr);
4547  READ_CHECK(fptr);
4548  return io_getc(fptr, enc);
4549 }
4550 
4551 /*
4552  * call-seq:
4553  * ios.readchar -> string
4554  *
4555  * Reads a one-character string from <em>ios</em>. Raises an
4556  * EOFError on end of file.
4557  *
4558  * f = File.new("testfile")
4559  * f.readchar #=> "h"
4560  * f.readchar #=> "e"
4561  */
4562 
4563 static VALUE
4564 rb_io_readchar(VALUE io)
4565 {
4566  VALUE c = rb_io_getc(io);
4567 
4568  if (NIL_P(c)) {
4569  rb_eof_error();
4570  }
4571  return c;
4572 }
4573 
4574 /*
4575  * call-seq:
4576  * ios.getbyte -> integer or nil
4577  *
4578  * Gets the next 8-bit byte (0..255) from <em>ios</em>. Returns
4579  * +nil+ if called at end of file.
4580  *
4581  * f = File.new("testfile")
4582  * f.getbyte #=> 84
4583  * f.getbyte #=> 104
4584  */
4585 
4586 VALUE
4588 {
4589  rb_io_t *fptr;
4590  int c;
4591 
4592  GetOpenFile(io, fptr);
4594  READ_CHECK(fptr);
4595  VALUE r_stdout = rb_ractor_stdout();
4596  if (fptr->fd == 0 && (fptr->mode & FMODE_TTY) && RB_TYPE_P(r_stdout, T_FILE)) {
4597  rb_io_t *ofp;
4598  GetOpenFile(r_stdout, ofp);
4599  if (ofp->mode & FMODE_TTY) {
4600  rb_io_flush(r_stdout);
4601  }
4602  }
4603  if (io_fillbuf(fptr) < 0) {
4604  return Qnil;
4605  }
4606  fptr->rbuf.off++;
4607  fptr->rbuf.len--;
4608  c = (unsigned char)fptr->rbuf.ptr[fptr->rbuf.off-1];
4609  return INT2FIX(c & 0xff);
4610 }
4611 
4612 /*
4613  * call-seq:
4614  * ios.readbyte -> integer
4615  *
4616  * Reads a byte as with IO#getbyte, but raises an EOFError on end of
4617  * file.
4618  */
4619 
4620 static VALUE
4621 rb_io_readbyte(VALUE io)
4622 {
4623  VALUE c = rb_io_getbyte(io);
4624 
4625  if (NIL_P(c)) {
4626  rb_eof_error();
4627  }
4628  return c;
4629 }
4630 
4631 /*
4632  * call-seq:
4633  * ios.ungetbyte(string) -> nil
4634  * ios.ungetbyte(integer) -> nil
4635  *
4636  * Pushes back bytes (passed as a parameter) onto <em>ios</em>,
4637  * such that a subsequent buffered read will return it.
4638  * It is only guaranteed to support a single byte, and only if ungetbyte
4639  * or ungetc has not already been called on <em>ios</em> since the previous
4640  * read of at least a single byte from <em>ios</em>.
4641  * However, it can support additional bytes if there is space in the
4642  * internal buffer to allow for it.
4643  *
4644  * f = File.new("testfile") #=> #<File:testfile>
4645  * b = f.getbyte #=> 0x38
4646  * f.ungetbyte(b) #=> nil
4647  * f.getbyte #=> 0x38
4648  *
4649  * If given an integer, only uses the lower 8 bits of the integer as the byte
4650  * to push.
4651  *
4652  * f = File.new("testfile") #=> #<File:testfile>
4653  * f.ungetbyte(0x102) #=> nil
4654  * f.getbyte #=> 0x2
4655  *
4656  * Calling this method prepends to the existing buffer, even if the method
4657  * has already been called previously:
4658  *
4659  * f = File.new("testfile") #=> #<File:testfile>
4660  * f.ungetbyte("ab") #=> nil
4661  * f.ungetbyte("cd") #=> nil
4662  * f.read(5) #=> "cdab8"
4663  *
4664  * Has no effect with unbuffered reads (such as IO#sysread).
4665  */
4666 
4667 VALUE
4669 {
4670  rb_io_t *fptr;
4671 
4672  GetOpenFile(io, fptr);
4674  switch (TYPE(b)) {
4675  case T_NIL:
4676  return Qnil;
4677  case T_FIXNUM:
4678  case T_BIGNUM: ;
4679  VALUE v = rb_int_modulo(b, INT2FIX(256));
4680  unsigned char c = NUM2INT(v) & 0xFF;
4681  b = rb_str_new((const char *)&c, 1);
4682  break;
4683  default:
4684  SafeStringValue(b);
4685  }
4686  io_ungetbyte(b, fptr);
4687  return Qnil;
4688 }
4689 
4690 /*
4691  * call-seq:
4692  * ios.ungetc(integer) -> nil
4693  * ios.ungetc(string) -> nil
4694  *
4695  * Pushes back characters (passed as a parameter) onto <em>ios</em>,
4696  * such that a subsequent buffered read will return it.
4697  * It is only guaranteed to support a single byte, and only if ungetbyte
4698  * or ungetc has not already been called on <em>ios</em> since the previous
4699  * read of at least a single byte from <em>ios</em>.
4700  * However, it can support additional bytes if there is space in the
4701  * internal buffer to allow for it.
4702  *
4703  * f = File.new("testfile") #=> #<File:testfile>
4704  * c = f.getc #=> "8"
4705  * f.ungetc(c) #=> nil
4706  * f.getc #=> "8"
4707  *
4708  * If given an integer, the integer must represent a valid codepoint in the
4709  * external encoding of <em>ios</em>.
4710  *
4711  * Calling this method prepends to the existing buffer, even if the method
4712  * has already been called previously:
4713  *
4714  * f = File.new("testfile") #=> #<File:testfile>
4715  * f.ungetc("ab") #=> nil
4716  * f.ungetc("cd") #=> nil
4717  * f.read(5) #=> "cdab8"
4718  *
4719  * Has no effect with unbuffered reads (such as IO#sysread).
4720  */
4721 
4722 VALUE
4724 {
4725  rb_io_t *fptr;
4726  long len;
4727 
4728  GetOpenFile(io, fptr);
4730  if (FIXNUM_P(c)) {
4731  c = rb_enc_uint_chr(FIX2UINT(c), io_read_encoding(fptr));
4732  }
4733  else if (RB_BIGNUM_TYPE_P(c)) {
4734  c = rb_enc_uint_chr(NUM2UINT(c), io_read_encoding(fptr));
4735  }
4736  else {
4737  SafeStringValue(c);
4738  }
4739  if (NEED_READCONV(fptr)) {
4740  SET_BINARY_MODE(fptr);
4741  len = RSTRING_LEN(c);
4742 #if SIZEOF_LONG > SIZEOF_INT
4743  if (len > INT_MAX)
4744  rb_raise(rb_eIOError, "ungetc failed");
4745 #endif
4746  make_readconv(fptr, (int)len);
4747  if (fptr->cbuf.capa - fptr->cbuf.len < len)
4748  rb_raise(rb_eIOError, "ungetc failed");
4749  if (fptr->cbuf.off < len) {
4750  MEMMOVE(fptr->cbuf.ptr+fptr->cbuf.capa-fptr->cbuf.len,
4751  fptr->cbuf.ptr+fptr->cbuf.off,
4752  char, fptr->cbuf.len);
4753  fptr->cbuf.off = fptr->cbuf.capa-fptr->cbuf.len;
4754  }
4755  fptr->cbuf.off -= (int)len;
4756  fptr->cbuf.len += (int)len;
4757  MEMMOVE(fptr->cbuf.ptr+fptr->cbuf.off, RSTRING_PTR(c), char, len);
4758  }
4759  else {
4760  NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
4761  io_ungetbyte(c, fptr);
4762  }
4763  return Qnil;
4764 }
4765 
4766 /*
4767  * call-seq:
4768  * ios.isatty -> true or false
4769  * ios.tty? -> true or false
4770  *
4771  * Returns <code>true</code> if <em>ios</em> is associated with a
4772  * terminal device (tty), <code>false</code> otherwise.
4773  *
4774  * File.new("testfile").isatty #=> false
4775  * File.new("/dev/tty").isatty #=> true
4776  */
4777 
4778 static VALUE
4779 rb_io_isatty(VALUE io)
4780 {
4781  rb_io_t *fptr;
4782 
4783  GetOpenFile(io, fptr);
4784  return RBOOL(isatty(fptr->fd) != 0);
4785 }
4786 
4787 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
4788 /*
4789  * call-seq:
4790  * ios.close_on_exec? -> true or false
4791  *
4792  * Returns <code>true</code> if <em>ios</em> will be closed on exec.
4793  *
4794  * f = open("/dev/null")
4795  * f.close_on_exec? #=> false
4796  * f.close_on_exec = true
4797  * f.close_on_exec? #=> true
4798  * f.close_on_exec = false
4799  * f.close_on_exec? #=> false
4800  */
4801 
4802 static VALUE
4803 rb_io_close_on_exec_p(VALUE io)
4804 {
4805  rb_io_t *fptr;
4806  VALUE write_io;
4807  int fd, ret;
4808 
4809  write_io = GetWriteIO(io);
4810  if (io != write_io) {
4811  GetOpenFile(write_io, fptr);
4812  if (fptr && 0 <= (fd = fptr->fd)) {
4813  if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
4814  if (!(ret & FD_CLOEXEC)) return Qfalse;
4815  }
4816  }
4817 
4818  GetOpenFile(io, fptr);
4819  if (fptr && 0 <= (fd = fptr->fd)) {
4820  if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
4821  if (!(ret & FD_CLOEXEC)) return Qfalse;
4822  }
4823  return Qtrue;
4824 }
4825 #else
4826 #define rb_io_close_on_exec_p rb_f_notimplement
4827 #endif
4828 
4829 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
4830 /*
4831  * call-seq:
4832  * ios.close_on_exec = bool -> true or false
4833  *
4834  * Sets a close-on-exec flag.
4835  *
4836  * f = open("/dev/null")
4837  * f.close_on_exec = true
4838  * system("cat", "/proc/self/fd/#{f.fileno}") # cat: /proc/self/fd/3: No such file or directory
4839  * f.closed? #=> false
4840  *
4841  * Ruby sets close-on-exec flags of all file descriptors by default
4842  * since Ruby 2.0.0.
4843  * So you don't need to set by yourself.
4844  * Also, unsetting a close-on-exec flag can cause file descriptor leak
4845  * if another thread use fork() and exec() (via system() method for example).
4846  * If you really needs file descriptor inheritance to child process,
4847  * use spawn()'s argument such as fd=>fd.
4848  */
4849 
4850 static VALUE
4851 rb_io_set_close_on_exec(VALUE io, VALUE arg)
4852 {
4853  int flag = RTEST(arg) ? FD_CLOEXEC : 0;
4854  rb_io_t *fptr;
4855  VALUE write_io;
4856  int fd, ret;
4857 
4858  write_io = GetWriteIO(io);
4859  if (io != write_io) {
4860  GetOpenFile(write_io, fptr);
4861  if (fptr && 0 <= (fd = fptr->fd)) {
4862  if ((ret = fcntl(fptr->fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
4863  if ((ret & FD_CLOEXEC) != flag) {
4864  ret = (ret & ~FD_CLOEXEC) | flag;
4865  ret = fcntl(fd, F_SETFD, ret);
4866  if (ret != 0) rb_sys_fail_path(fptr->pathv);
4867  }
4868  }
4869 
4870  }
4871 
4872  GetOpenFile(io, fptr);
4873  if (fptr && 0 <= (fd = fptr->fd)) {
4874  if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
4875  if ((ret & FD_CLOEXEC) != flag) {
4876  ret = (ret & ~FD_CLOEXEC) | flag;
4877  ret = fcntl(fd, F_SETFD, ret);
4878  if (ret != 0) rb_sys_fail_path(fptr->pathv);
4879  }
4880  }
4881  return Qnil;
4882 }
4883 #else
4884 #define rb_io_set_close_on_exec rb_f_notimplement
4885 #endif
4886 
4887 #define IS_PREP_STDIO(f) ((f)->mode & FMODE_PREP)
4888 #define PREP_STDIO_NAME(f) (RSTRING_PTR((f)->pathv))
4889 
4890 static VALUE
4891 finish_writeconv(rb_io_t *fptr, int noalloc)
4892 {
4893  unsigned char *ds, *dp, *de;
4894  rb_econv_result_t res;
4895 
4896  if (!fptr->wbuf.ptr) {
4897  unsigned char buf[1024];
4898  long r;
4899 
4901  while (res == econv_destination_buffer_full) {
4902  ds = dp = buf;
4903  de = buf + sizeof(buf);
4904  res = rb_econv_convert(fptr->writeconv, NULL, NULL, &dp, de, 0);
4905  while (dp-ds) {
4906  retry:
4907  r = rb_write_internal(fptr, ds, dp-ds);
4908  if (r == dp-ds)
4909  break;
4910  if (0 <= r) {
4911  ds += r;
4912  }
4913  if (rb_io_maybe_wait_writable(errno, fptr->self, Qnil)) {
4914  if (fptr->fd < 0)
4915  return noalloc ? Qtrue : rb_exc_new3(rb_eIOError, rb_str_new_cstr(closed_stream));
4916  goto retry;
4917  }
4918  return noalloc ? Qtrue : INT2NUM(errno);
4919  }
4920  if (res == econv_invalid_byte_sequence ||
4921  res == econv_incomplete_input ||
4922  res == econv_undefined_conversion) {
4923  return noalloc ? Qtrue : rb_econv_make_exception(fptr->writeconv);
4924  }
4925  }
4926 
4927  return Qnil;
4928  }
4929 
4931  while (res == econv_destination_buffer_full) {
4932  if (fptr->wbuf.len == fptr->wbuf.capa) {
4933  if (io_fflush(fptr) < 0)
4934  return noalloc ? Qtrue : INT2NUM(errno);
4935  }
4936 
4937  ds = dp = (unsigned char *)fptr->wbuf.ptr + fptr->wbuf.off + fptr->wbuf.len;
4938  de = (unsigned char *)fptr->wbuf.ptr + fptr->wbuf.capa;
4939  res = rb_econv_convert(fptr->writeconv, NULL, NULL, &dp, de, 0);
4940  fptr->wbuf.len += (int)(dp - ds);
4941  if (res == econv_invalid_byte_sequence ||
4942  res == econv_incomplete_input ||
4943  res == econv_undefined_conversion) {
4944  return noalloc ? Qtrue : rb_econv_make_exception(fptr->writeconv);
4945  }
4946  }
4947  return Qnil;
4948 }
4949 
4951  rb_io_t *fptr;
4952  int noalloc;
4953 };
4954 
4955 static VALUE
4956 finish_writeconv_sync(VALUE arg)
4957 {
4958  struct finish_writeconv_arg *p = (struct finish_writeconv_arg *)arg;
4959  return finish_writeconv(p->fptr, p->noalloc);
4960 }
4961 
4962 static void*
4963 nogvl_close(void *ptr)
4964 {
4965  int *fd = ptr;
4966 
4967  return (void*)(intptr_t)close(*fd);
4968 }
4969 
4970 static int
4971 maygvl_close(int fd, int keepgvl)
4972 {
4973  if (keepgvl)
4974  return close(fd);
4975 
4976  /*
4977  * close() may block for certain file types (NFS, SO_LINGER sockets,
4978  * inotify), so let other threads run.
4979  */
4980  return (int)(intptr_t)rb_thread_call_without_gvl(nogvl_close, &fd, RUBY_UBF_IO, 0);
4981 }
4982 
4983 static void*
4984 nogvl_fclose(void *ptr)
4985 {
4986  FILE *file = ptr;
4987 
4988  return (void*)(intptr_t)fclose(file);
4989 }
4990 
4991 static int
4992 maygvl_fclose(FILE *file, int keepgvl)
4993 {
4994  if (keepgvl)
4995  return fclose(file);
4996 
4997  return (int)(intptr_t)rb_thread_call_without_gvl(nogvl_fclose, file, RUBY_UBF_IO, 0);
4998 }
4999 
5000 static void free_io_buffer(rb_io_buffer_t *buf);
5001 static void clear_codeconv(rb_io_t *fptr);
5002 
5003 static void
5004 fptr_finalize_flush(rb_io_t *fptr, int noraise, int keepgvl,
5005  struct list_head *busy)
5006 {
5007  VALUE err = Qnil;
5008  int fd = fptr->fd;
5009  FILE *stdio_file = fptr->stdio_file;
5010  int mode = fptr->mode;
5011 
5012  if (fptr->writeconv) {
5013  if (fptr->write_lock && !noraise) {
5014  struct finish_writeconv_arg arg;
5015  arg.fptr = fptr;
5016  arg.noalloc = noraise;
5017  err = rb_mutex_synchronize(fptr->write_lock, finish_writeconv_sync, (VALUE)&arg);
5018  }
5019  else {
5020  err = finish_writeconv(fptr, noraise);
5021  }
5022  }
5023  if (fptr->wbuf.len) {
5024  if (noraise) {
5025  io_flush_buffer_sync(fptr);
5026  }
5027  else {
5028  if (io_fflush(fptr) < 0 && NIL_P(err))
5029  err = INT2NUM(errno);
5030  }
5031  }
5032 
5033  int done = 0;
5034 
5035  if (IS_PREP_STDIO(fptr) || fd <= 2) {
5036  // Need to keep FILE objects of stdin, stdout and stderr, so we are done:
5037  done = 1;
5038  }
5039 
5040  fptr->fd = -1;
5041  fptr->stdio_file = 0;
5042  fptr->mode &= ~(FMODE_READABLE|FMODE_WRITABLE);
5043 
5044  // Ensure waiting_fd users do not hit EBADF.
5045  if (busy) {
5046  // Wait for them to exit before we call close().
5047  do rb_thread_schedule(); while (!list_empty(busy));
5048  }
5049 
5050  // Disable for now.
5051  // if (!done && fd >= 0) {
5052  // VALUE scheduler = rb_fiber_scheduler_current();
5053  // if (scheduler != Qnil) {
5054  // VALUE result = rb_fiber_scheduler_io_close(scheduler, fptr->self);
5055  // if (result != Qundef) done = 1;
5056  // }
5057  // }
5058 
5059  if (!done && stdio_file) {
5060  // stdio_file is deallocated anyway even if fclose failed.
5061  if ((maygvl_fclose(stdio_file, noraise) < 0) && NIL_P(err))
5062  if (!noraise) err = INT2NUM(errno);
5063 
5064  done = 1;
5065  }
5066 
5067  if (!done && fd >= 0) {
5068  // fptr->fd may be closed even if close fails. POSIX doesn't specify it.
5069  // We assumes it is closed.
5070 
5071  keepgvl |= !(mode & FMODE_WRITABLE);
5072  keepgvl |= noraise;
5073  if ((maygvl_close(fd, keepgvl) < 0) && NIL_P(err))
5074  if (!noraise) err = INT2NUM(errno);
5075 
5076  done = 1;
5077  }
5078 
5079  if (!NIL_P(err) && !noraise) {
5080  if (RB_INTEGER_TYPE_P(err))
5081  rb_syserr_fail_path(NUM2INT(err), fptr->pathv);
5082  else
5083  rb_exc_raise(err);
5084  }
5085 }
5086 
5087 static void
5088 fptr_finalize(rb_io_t *fptr, int noraise)
5089 {
5090  fptr_finalize_flush(fptr, noraise, FALSE, 0);
5091  free_io_buffer(&fptr->rbuf);
5092  free_io_buffer(&fptr->wbuf);
5093  clear_codeconv(fptr);
5094 }
5095 
5096 static void
5097 rb_io_fptr_cleanup(rb_io_t *fptr, int noraise)
5098 {
5099  if (fptr->finalize) {
5100  (*fptr->finalize)(fptr, noraise);
5101  }
5102  else {
5103  fptr_finalize(fptr, noraise);
5104  }
5105 }
5106 
5107 static void
5108 free_io_buffer(rb_io_buffer_t *buf)
5109 {
5110  if (buf->ptr) {
5111  ruby_sized_xfree(buf->ptr, (size_t)buf->capa);
5112  buf->ptr = NULL;
5113  }
5114 }
5115 
5116 static void
5117 clear_readconv(rb_io_t *fptr)
5118 {
5119  if (fptr->readconv) {
5120  rb_econv_close(fptr->readconv);
5121  fptr->readconv = NULL;
5122  }
5123  free_io_buffer(&fptr->cbuf);
5124 }
5125 
5126 static void
5127 clear_writeconv(rb_io_t *fptr)
5128 {
5129  if (fptr->writeconv) {
5130  rb_econv_close(fptr->writeconv);
5131  fptr->writeconv = NULL;
5132  }
5133  fptr->writeconv_initialized = 0;
5134 }
5135 
5136 static void
5137 clear_codeconv(rb_io_t *fptr)
5138 {
5139  clear_readconv(fptr);
5140  clear_writeconv(fptr);
5141 }
5142 
5143 void
5144 rb_io_fptr_finalize_internal(void *ptr)
5145 {
5146  rb_io_t *fptr = ptr;
5147 
5148  if (!ptr) return;
5149  fptr->pathv = Qnil;
5150  if (0 <= fptr->fd)
5151  rb_io_fptr_cleanup(fptr, TRUE);
5152  fptr->write_lock = 0;
5153  free_io_buffer(&fptr->rbuf);
5154  free_io_buffer(&fptr->wbuf);
5155  clear_codeconv(fptr);
5156  free(fptr);
5157 }
5158 
5159 #undef rb_io_fptr_finalize
5160 int
5162 {
5163  if (!fptr) {
5164  return 0;
5165  }
5166  else {
5167  rb_io_fptr_finalize_internal(fptr);
5168  return 1;
5169  }
5170 }
5171 #define rb_io_fptr_finalize(fptr) rb_io_fptr_finalize_internal(fptr)
5172 
5173 RUBY_FUNC_EXPORTED size_t
5174 rb_io_memsize(const rb_io_t *fptr)
5175 {
5176  size_t size = sizeof(rb_io_t);
5177  size += fptr->rbuf.capa;
5178  size += fptr->wbuf.capa;
5179  size += fptr->cbuf.capa;
5180  if (fptr->readconv) size += rb_econv_memsize(fptr->readconv);
5181  if (fptr->writeconv) size += rb_econv_memsize(fptr->writeconv);
5182  return size;
5183 }
5184 
5185 #ifdef _WIN32
5186 /* keep GVL while closing to prevent crash on Windows */
5187 # define KEEPGVL TRUE
5188 #else
5189 # define KEEPGVL FALSE
5190 #endif
5191 
5192 int rb_notify_fd_close(int fd, struct list_head *);
5193 static rb_io_t *
5194 io_close_fptr(VALUE io)
5195 {
5196  rb_io_t *fptr;
5197  VALUE write_io;
5198  rb_io_t *write_fptr;
5199  struct list_head busy;
5200 
5201  list_head_init(&busy);
5202  write_io = GetWriteIO(io);
5203  if (io != write_io) {
5204  write_fptr = RFILE(write_io)->fptr;
5205  if (write_fptr && 0 <= write_fptr->fd) {
5206  rb_io_fptr_cleanup(write_fptr, TRUE);
5207  }
5208  }
5209 
5210  fptr = RFILE(io)->fptr;
5211  if (!fptr) return 0;
5212  if (fptr->fd < 0) return 0;
5213 
5214  if (rb_notify_fd_close(fptr->fd, &busy)) {
5215  /* calls close(fptr->fd): */
5216  fptr_finalize_flush(fptr, FALSE, KEEPGVL, &busy);
5217  }
5218  rb_io_fptr_cleanup(fptr, FALSE);
5219  return fptr;
5220 }
5221 
5222 static void
5223 fptr_waitpid(rb_io_t *fptr, int nohang)
5224 {
5225  int status;
5226  if (fptr->pid) {
5227  rb_last_status_clear();
5228  rb_waitpid(fptr->pid, &status, nohang ? WNOHANG : 0);
5229  fptr->pid = 0;
5230  }
5231 }
5232 
5233 VALUE
5235 {
5236  rb_io_t *fptr = io_close_fptr(io);
5237  if (fptr) fptr_waitpid(fptr, 0);
5238  return Qnil;
5239 }
5240 
5241 /*
5242  * call-seq:
5243  * ios.close -> nil
5244  *
5245  * Closes <em>ios</em> and flushes any pending writes to the operating
5246  * system. The stream is unavailable for any further data operations;
5247  * an IOError is raised if such an attempt is made. I/O streams are
5248  * automatically closed when they are claimed by the garbage collector.
5249  *
5250  * If <em>ios</em> is opened by IO.popen, #close sets
5251  * <code>$?</code>.
5252  *
5253  * Calling this method on closed IO object is just ignored since Ruby 2.3.
5254  */
5255 
5256 static VALUE
5257 rb_io_close_m(VALUE io)
5258 {
5259  rb_io_t *fptr = rb_io_get_fptr(io);
5260  if (fptr->fd < 0) {
5261  return Qnil;
5262  }
5263  rb_io_close(io);
5264  return Qnil;
5265 }
5266 
5267 static VALUE
5268 io_call_close(VALUE io)
5269 {
5270  rb_check_funcall(io, rb_intern("close"), 0, 0);
5271  return io;
5272 }
5273 
5274 static VALUE
5275 ignore_closed_stream(VALUE io, VALUE exc)
5276 {
5277  enum {mesg_len = sizeof(closed_stream)-1};
5278  VALUE mesg = rb_attr_get(exc, idMesg);
5279  if (!RB_TYPE_P(mesg, T_STRING) ||
5280  RSTRING_LEN(mesg) != mesg_len ||
5281  memcmp(RSTRING_PTR(mesg), closed_stream, mesg_len)) {
5282  rb_exc_raise(exc);
5283  }
5284  return io;
5285 }
5286 
5287 static VALUE
5288 io_close(VALUE io)
5289 {
5290  VALUE closed = rb_check_funcall(io, rb_intern("closed?"), 0, 0);
5291  if (closed != Qundef && RTEST(closed)) return io;
5292  rb_rescue2(io_call_close, io, ignore_closed_stream, io,
5293  rb_eIOError, (VALUE)0);
5294  return io;
5295 }
5296 
5297 /*
5298  * call-seq:
5299  * ios.closed? -> true or false
5300  *
5301  * Returns <code>true</code> if <em>ios</em> is completely closed (for
5302  * duplex streams, both reader and writer), <code>false</code>
5303  * otherwise.
5304  *
5305  * f = File.new("testfile")
5306  * f.close #=> nil
5307  * f.closed? #=> true
5308  * f = IO.popen("/bin/sh","r+")
5309  * f.close_write #=> nil
5310  * f.closed? #=> false
5311  * f.close_read #=> nil
5312  * f.closed? #=> true
5313  */
5314 
5315 
5316 static VALUE
5317 rb_io_closed(VALUE io)
5318 {
5319  rb_io_t *fptr;
5320  VALUE write_io;
5321  rb_io_t *write_fptr;
5322 
5323  write_io = GetWriteIO(io);
5324  if (io != write_io) {
5325  write_fptr = RFILE(write_io)->fptr;
5326  if (write_fptr && 0 <= write_fptr->fd) {
5327  return Qfalse;
5328  }
5329  }
5330 
5331  fptr = rb_io_get_fptr(io);
5332  return RBOOL(0 > fptr->fd);
5333 }
5334 
5335 /*
5336  * call-seq:
5337  * ios.close_read -> nil
5338  *
5339  * Closes the read end of a duplex I/O stream (i.e., one that contains
5340  * both a read and a write stream, such as a pipe). Will raise an
5341  * IOError if the stream is not duplexed.
5342  *
5343  * f = IO.popen("/bin/sh","r+")
5344  * f.close_read
5345  * f.readlines
5346  *
5347  * <em>produces:</em>
5348  *
5349  * prog.rb:3:in `readlines': not opened for reading (IOError)
5350  * from prog.rb:3
5351  *
5352  * Calling this method on closed IO object is just ignored since Ruby 2.3.
5353  */
5354 
5355 static VALUE
5356 rb_io_close_read(VALUE io)
5357 {
5358  rb_io_t *fptr;
5359  VALUE write_io;
5360 
5361  fptr = rb_io_get_fptr(rb_io_taint_check(io));
5362  if (fptr->fd < 0) return Qnil;
5363  if (is_socket(fptr->fd, fptr->pathv)) {
5364 #ifndef SHUT_RD
5365 # define SHUT_RD 0
5366 #endif
5367  if (shutdown(fptr->fd, SHUT_RD) < 0)
5368  rb_sys_fail_path(fptr->pathv);
5369  fptr->mode &= ~FMODE_READABLE;
5370  if (!(fptr->mode & FMODE_WRITABLE))
5371  return rb_io_close(io);
5372  return Qnil;
5373  }
5374 
5375  write_io = GetWriteIO(io);
5376  if (io != write_io) {
5377  rb_io_t *wfptr;
5378  wfptr = rb_io_get_fptr(rb_io_taint_check(write_io));
5379  wfptr->pid = fptr->pid;
5380  fptr->pid = 0;
5381  RFILE(io)->fptr = wfptr;
5382  /* bind to write_io temporarily to get rid of memory/fd leak */
5383  fptr->tied_io_for_writing = 0;
5384  RFILE(write_io)->fptr = fptr;
5385  rb_io_fptr_cleanup(fptr, FALSE);
5386  /* should not finalize fptr because another thread may be reading it */
5387  return Qnil;
5388  }
5389 
5390  if ((fptr->mode & (FMODE_DUPLEX|FMODE_WRITABLE)) == FMODE_WRITABLE) {
5391  rb_raise(rb_eIOError, "closing non-duplex IO for reading");
5392  }
5393  return rb_io_close(io);
5394 }
5395 
5396 /*
5397  * call-seq:
5398  * ios.close_write -> nil
5399  *
5400  * Closes the write end of a duplex I/O stream (i.e., one that contains
5401  * both a read and a write stream, such as a pipe). Will raise an
5402  * IOError if the stream is not duplexed.
5403  *
5404  * f = IO.popen("/bin/sh","r+")
5405  * f.close_write
5406  * f.print "nowhere"
5407  *
5408  * <em>produces:</em>
5409  *
5410  * prog.rb:3:in `write': not opened for writing (IOError)
5411  * from prog.rb:3:in `print'
5412  * from prog.rb:3
5413  *
5414  * Calling this method on closed IO object is just ignored since Ruby 2.3.
5415  */
5416 
5417 static VALUE
5418 rb_io_close_write(VALUE io)
5419 {
5420  rb_io_t *fptr;
5421  VALUE write_io;
5422 
5423  write_io = GetWriteIO(io);
5424  fptr = rb_io_get_fptr(rb_io_taint_check(write_io));
5425  if (fptr->fd < 0) return Qnil;
5426  if (is_socket(fptr->fd, fptr->pathv)) {
5427 #ifndef SHUT_WR
5428 # define SHUT_WR 1
5429 #endif
5430  if (shutdown(fptr->fd, SHUT_WR) < 0)
5431  rb_sys_fail_path(fptr->pathv);
5432  fptr->mode &= ~FMODE_WRITABLE;
5433  if (!(fptr->mode & FMODE_READABLE))
5434  return rb_io_close(write_io);
5435  return Qnil;
5436  }
5437 
5438  if ((fptr->mode & (FMODE_DUPLEX|FMODE_READABLE)) == FMODE_READABLE) {
5439  rb_raise(rb_eIOError, "closing non-duplex IO for writing");
5440  }
5441 
5442  if (io != write_io) {
5443  fptr = rb_io_get_fptr(rb_io_taint_check(io));
5444  fptr->tied_io_for_writing = 0;
5445  }
5446  rb_io_close(write_io);
5447  return Qnil;
5448 }
5449 
5450 /*
5451  * call-seq:
5452  * ios.sysseek(offset, whence=IO::SEEK_SET) -> integer
5453  *
5454  * Seeks to a given <i>offset</i> in the stream according to the value
5455  * of <i>whence</i> (see IO#seek for values of <i>whence</i>). Returns
5456  * the new offset into the file.
5457  *
5458  * f = File.new("testfile")
5459  * f.sysseek(-13, IO::SEEK_END) #=> 53
5460  * f.sysread(10) #=> "And so on."
5461  */
5462 
5463 static VALUE
5464 rb_io_sysseek(int argc, VALUE *argv, VALUE io)
5465 {
5466  VALUE offset, ptrname;
5467  int whence = SEEK_SET;
5468  rb_io_t *fptr;
5469  off_t pos;
5470 
5471  if (rb_scan_args(argc, argv, "11", &offset, &ptrname) == 2) {
5472  whence = interpret_seek_whence(ptrname);
5473  }
5474  pos = NUM2OFFT(offset);
5475  GetOpenFile(io, fptr);
5476  if ((fptr->mode & FMODE_READABLE) &&
5477  (READ_DATA_BUFFERED(fptr) || READ_CHAR_PENDING(fptr))) {
5478  rb_raise(rb_eIOError, "sysseek for buffered IO");
5479  }
5480  if ((fptr->mode & FMODE_WRITABLE) && fptr->wbuf.len) {
5481  rb_warn("sysseek for buffered IO");
5482  }
5483  errno = 0;
5484  pos = lseek(fptr->fd, pos, whence);
5485  if (pos < 0 && errno) rb_sys_fail_path(fptr->pathv);
5486 
5487  return OFFT2NUM(pos);
5488 }
5489 
5490 /*
5491  * call-seq:
5492  * ios.syswrite(string) -> integer
5493  *
5494  * Writes the given string to <em>ios</em> using a low-level write.
5495  * Returns the number of bytes written. Do not mix with other methods
5496  * that write to <em>ios</em> or you may get unpredictable results.
5497  * Raises SystemCallError on error.
5498  *
5499  * f = File.new("out", "w")
5500  * f.syswrite("ABCDEF") #=> 6
5501  */
5502 
5503 static VALUE
5504 rb_io_syswrite(VALUE io, VALUE str)
5505 {
5506  VALUE tmp;
5507  rb_io_t *fptr;
5508  long n, len;
5509  const char *ptr;
5510 
5511  if (!RB_TYPE_P(str, T_STRING))
5512  str = rb_obj_as_string(str);
5513 
5514  io = GetWriteIO(io);
5515  GetOpenFile(io, fptr);
5516  rb_io_check_writable(fptr);
5517 
5518  if (fptr->wbuf.len) {
5519  rb_warn("syswrite for buffered IO");
5520  }
5521 
5522  tmp = rb_str_tmp_frozen_acquire(str);
5523  RSTRING_GETMEM(tmp, ptr, len);
5524  n = rb_write_internal(fptr, ptr, len);
5525  if (n < 0) rb_sys_fail_path(fptr->pathv);
5526  rb_str_tmp_frozen_release(str, tmp);
5527 
5528  return LONG2FIX(n);
5529 }
5530 
5531 /*
5532  * call-seq:
5533  * ios.sysread(maxlen[, outbuf]) -> string
5534  *
5535  * Reads <i>maxlen</i> bytes from <em>ios</em> using a low-level
5536  * read and returns them as a string. Do not mix with other methods
5537  * that read from <em>ios</em> or you may get unpredictable results.
5538  *
5539  * If the optional _outbuf_ argument is present,
5540  * it must reference a String, which will receive the data.
5541  * The _outbuf_ will contain only the received data after the method call
5542  * even if it is not empty at the beginning.
5543  *
5544  * Raises SystemCallError on error and EOFError at end of file.
5545  *
5546  * f = File.new("testfile")
5547  * f.sysread(16) #=> "This is line one"
5548  */
5549 
5550 static VALUE
5551 rb_io_sysread(int argc, VALUE *argv, VALUE io)
5552 {
5553  VALUE len, str;
5554  rb_io_t *fptr;
5555  long n, ilen;
5556  struct io_internal_read_struct iis;
5557  int shrinkable;
5558 
5559  rb_scan_args(argc, argv, "11", &len, &str);
5560  ilen = NUM2LONG(len);
5561 
5562  shrinkable = io_setstrbuf(&str, ilen);
5563  if (ilen == 0) return str;
5564 
5565  GetOpenFile(io, fptr);
5567 
5568  if (READ_DATA_BUFFERED(fptr)) {
5569  rb_raise(rb_eIOError, "sysread for buffered IO");
5570  }
5571 
5572  rb_io_check_closed(fptr);
5573 
5574  io_setstrbuf(&str, ilen);
5575  iis.th = rb_thread_current();
5576  iis.fptr = fptr;
5577  iis.nonblock = 0;
5578  iis.buf = RSTRING_PTR(str);
5579  iis.capa = ilen;
5580  n = read_internal_locktmp(str, &iis);
5581 
5582  if (n < 0) {
5583  rb_sys_fail_path(fptr->pathv);
5584  }
5585 
5586  io_set_read_length(str, n, shrinkable);
5587 
5588  if (n == 0 && ilen > 0) {
5589  rb_eof_error();
5590  }
5591 
5592  return str;
5593 }
5594 
5595 #if defined(HAVE_PREAD) || defined(HAVE_PWRITE)
5596 struct prdwr_internal_arg {
5597  int fd;
5598  void *buf;
5599  size_t count;
5600  off_t offset;
5601 };
5602 #endif /* HAVE_PREAD || HAVE_PWRITE */
5603 
5604 #if defined(HAVE_PREAD)
5605 static VALUE
5606 internal_pread_func(void *arg)
5607 {
5608  struct prdwr_internal_arg *p = arg;
5609  return (VALUE)pread(p->fd, p->buf, p->count, p->offset);
5610 }
5611 
5612 static VALUE
5613 pread_internal_call(VALUE arg)
5614 {
5615  struct prdwr_internal_arg *p = (struct prdwr_internal_arg *)arg;
5616  return rb_thread_io_blocking_region(internal_pread_func, p, p->fd);
5617 }
5618 
5619 /*
5620  * call-seq:
5621  * ios.pread(maxlen, offset[, outbuf]) -> string
5622  *
5623  * Reads <i>maxlen</i> bytes from <em>ios</em> using the pread system call
5624  * and returns them as a string without modifying the underlying
5625  * descriptor offset. This is advantageous compared to combining IO#seek
5626  * and IO#read in that it is atomic, allowing multiple threads/process to
5627  * share the same IO object for reading the file at various locations.
5628  * This bypasses any userspace buffering of the IO layer.
5629  * If the optional <i>outbuf</i> argument is present, it must
5630  * reference a String, which will receive the data.
5631  * Raises SystemCallError on error, EOFError at end of file and
5632  * NotImplementedError if platform does not implement the system call.
5633  *
5634  * File.write("testfile", "This is line one\nThis is line two\n")
5635  * File.open("testfile") do |f|
5636  * p f.read # => "This is line one\nThis is line two\n"
5637  * p f.pread(12, 0) # => "This is line"
5638  * p f.pread(9, 8) # => "line one\n"
5639  * end
5640  */
5641 static VALUE
5642 rb_io_pread(int argc, VALUE *argv, VALUE io)
5643 {
5644  VALUE len, offset, str;
5645  rb_io_t *fptr;
5646  ssize_t n;
5647  struct prdwr_internal_arg arg;
5648  int shrinkable;
5649 
5650  rb_scan_args(argc, argv, "21", &len, &offset, &str);
5651  arg.count = NUM2SIZET(len);
5652  arg.offset = NUM2OFFT(offset);
5653 
5654  shrinkable = io_setstrbuf(&str, (long)arg.count);
5655  if (arg.count == 0) return str;
5656  arg.buf = RSTRING_PTR(str);
5657 
5658  GetOpenFile(io, fptr);
5660 
5661  arg.fd = fptr->fd;
5662  rb_io_check_closed(fptr);
5663 
5664  rb_str_locktmp(str);
5665  n = (ssize_t)rb_ensure(pread_internal_call, (VALUE)&arg, rb_str_unlocktmp, str);
5666 
5667  if (n < 0) {
5668  rb_sys_fail_path(fptr->pathv);
5669  }
5670  io_set_read_length(str, n, shrinkable);
5671  if (n == 0 && arg.count > 0) {
5672  rb_eof_error();
5673  }
5674 
5675  return str;
5676 }
5677 #else
5678 # define rb_io_pread rb_f_notimplement
5679 #endif /* HAVE_PREAD */
5680 
5681 #if defined(HAVE_PWRITE)
5682 static VALUE
5683 internal_pwrite_func(void *ptr)
5684 {
5685  struct prdwr_internal_arg *arg = ptr;
5686 
5687  return (VALUE)pwrite(arg->fd, arg->buf, arg->count, arg->offset);
5688 }
5689 
5690 /*
5691  * call-seq:
5692  * ios.pwrite(string, offset) -> integer
5693  *
5694  * Writes the given string to <em>ios</em> at <i>offset</i> using pwrite()
5695  * system call. This is advantageous to combining IO#seek and IO#write
5696  * in that it is atomic, allowing multiple threads/process to share the
5697  * same IO object for reading the file at various locations.
5698  * This bypasses any userspace buffering of the IO layer.
5699  * Returns the number of bytes written.
5700  * Raises SystemCallError on error and NotImplementedError
5701  * if platform does not implement the system call.
5702  *
5703  * File.open("out", "w") do |f|
5704  * f.pwrite("ABCDEF", 3) #=> 6
5705  * end
5706  *
5707  * File.read("out") #=> "\u0000\u0000\u0000ABCDEF"
5708  */
5709 static VALUE
5710 rb_io_pwrite(VALUE io, VALUE str, VALUE offset)
5711 {
5712  rb_io_t *fptr;
5713  ssize_t n;
5714  struct prdwr_internal_arg arg;
5715  VALUE tmp;
5716 
5717  if (!RB_TYPE_P(str, T_STRING))
5718  str = rb_obj_as_string(str);
5719 
5720  arg.offset = NUM2OFFT(offset);
5721 
5722  io = GetWriteIO(io);
5723  GetOpenFile(io, fptr);
5724  rb_io_check_writable(fptr);
5725  arg.fd = fptr->fd;
5726 
5727  tmp = rb_str_tmp_frozen_acquire(str);
5728  arg.buf = RSTRING_PTR(tmp);
5729  arg.count = (size_t)RSTRING_LEN(tmp);
5730 
5731  n = (ssize_t)rb_thread_io_blocking_region(internal_pwrite_func, &arg, fptr->fd);
5732  if (n < 0) rb_sys_fail_path(fptr->pathv);
5733  rb_str_tmp_frozen_release(str, tmp);
5734 
5735  return SSIZET2NUM(n);
5736 }
5737 #else
5738 # define rb_io_pwrite rb_f_notimplement
5739 #endif /* HAVE_PWRITE */
5740 
5741 VALUE
5743 {
5744  rb_io_t *fptr;
5745 
5746  GetOpenFile(io, fptr);
5747  if (fptr->readconv)
5748  rb_econv_binmode(fptr->readconv);
5749  if (fptr->writeconv)
5750  rb_econv_binmode(fptr->writeconv);
5751  fptr->mode |= FMODE_BINMODE;
5752  fptr->mode &= ~FMODE_TEXTMODE;
5754 #ifdef O_BINARY
5755  if (!fptr->readconv) {
5756  SET_BINARY_MODE_WITH_SEEK_CUR(fptr);
5757  }
5758  else {
5759  setmode(fptr->fd, O_BINARY);
5760  }
5761 #endif
5762  return io;
5763 }
5764 
5765 static void
5766 io_ascii8bit_binmode(rb_io_t *fptr)
5767 {
5768  if (fptr->readconv) {
5769  rb_econv_close(fptr->readconv);
5770  fptr->readconv = NULL;
5771  }
5772  if (fptr->writeconv) {
5773  rb_econv_close(fptr->writeconv);
5774  fptr->writeconv = NULL;
5775  }
5776  fptr->mode |= FMODE_BINMODE;
5777  fptr->mode &= ~FMODE_TEXTMODE;
5778  SET_BINARY_MODE_WITH_SEEK_CUR(fptr);
5779 
5780  fptr->encs.enc = rb_ascii8bit_encoding();
5781  fptr->encs.enc2 = NULL;
5782  fptr->encs.ecflags = 0;
5783  fptr->encs.ecopts = Qnil;
5784  clear_codeconv(fptr);
5785 }
5786 
5787 VALUE
5789 {
5790  rb_io_t *fptr;
5791 
5792  GetOpenFile(io, fptr);
5793  io_ascii8bit_binmode(fptr);
5794 
5795  return io;
5796 }
5797 
5798 /*
5799  * call-seq:
5800  * ios.binmode -> ios
5801  *
5802  * Puts <em>ios</em> into binary mode.
5803  * Once a stream is in binary mode, it cannot be reset to nonbinary mode.
5804  *
5805  * - newline conversion disabled
5806  * - encoding conversion disabled
5807  * - content is treated as ASCII-8BIT
5808  */
5809 
5810 static VALUE
5811 rb_io_binmode_m(VALUE io)
5812 {
5813  VALUE write_io;
5814 
5816 
5817  write_io = GetWriteIO(io);
5818  if (write_io != io)
5819  rb_io_ascii8bit_binmode(write_io);
5820  return io;
5821 }
5822 
5823 /*
5824  * call-seq:
5825  * ios.binmode? -> true or false
5826  *
5827  * Returns <code>true</code> if <em>ios</em> is binmode.
5828  */
5829 static VALUE
5830 rb_io_binmode_p(VALUE io)
5831 {
5832  rb_io_t *fptr;
5833  GetOpenFile(io, fptr);
5834  return RBOOL(fptr->mode & FMODE_BINMODE);
5835 }
5836 
5837 static const char*
5838 rb_io_fmode_modestr(int fmode)
5839 {
5840  if (fmode & FMODE_APPEND) {
5841  if ((fmode & FMODE_READWRITE) == FMODE_READWRITE) {
5842  return MODE_BTMODE("a+", "ab+", "at+");
5843  }
5844  return MODE_BTMODE("a", "ab", "at");
5845  }
5846  switch (fmode & FMODE_READWRITE) {
5847  default:
5848  rb_raise(rb_eArgError, "invalid access fmode 0x%x", fmode);
5849  case FMODE_READABLE:
5850  return MODE_BTMODE("r", "rb", "rt");
5851  case FMODE_WRITABLE:
5852  return MODE_BTXMODE("w", "wb", "wt", "wx", "wbx", "wtx");
5853  case FMODE_READWRITE:
5854  if (fmode & FMODE_CREATE) {
5855  return MODE_BTXMODE("w+", "wb+", "wt+", "w+x", "wb+x", "wt+x");
5856  }
5857  return MODE_BTMODE("r+", "rb+", "rt+");
5858  }
5859 }
5860 
5861 static const char bom_prefix[] = "bom|";
5862 static const char utf_prefix[] = "utf-";
5863 enum {bom_prefix_len = (int)sizeof(bom_prefix) - 1};
5864 enum {utf_prefix_len = (int)sizeof(utf_prefix) - 1};
5865 
5866 static int
5867 io_encname_bom_p(const char *name, long len)
5868 {
5869  return len > bom_prefix_len && STRNCASECMP(name, bom_prefix, bom_prefix_len) == 0;
5870 }
5871 
5872 int
5873 rb_io_modestr_fmode(const char *modestr)
5874 {
5875  int fmode = 0;
5876  const char *m = modestr, *p = NULL;
5877 
5878  switch (*m++) {
5879  case 'r':
5880  fmode |= FMODE_READABLE;
5881  break;
5882  case 'w':
5884  break;
5885  case 'a':
5887  break;
5888  default:
5889  goto error;
5890  }
5891 
5892  while (*m) {
5893  switch (*m++) {
5894  case 'b':
5895  fmode |= FMODE_BINMODE;
5896  break;
5897  case 't':
5898  fmode |= FMODE_TEXTMODE;
5899  break;
5900  case '+':
5901  fmode |= FMODE_READWRITE;
5902  break;
5903  case 'x':
5904  if (modestr[0] != 'w')
5905  goto error;
5906  fmode |= FMODE_EXCL;
5907  break;
5908  default:
5909  goto error;
5910  case ':':
5911  p = strchr(m, ':');
5912  if (io_encname_bom_p(m, p ? (long)(p - m) : (long)strlen(m)))
5913  fmode |= FMODE_SETENC_BY_BOM;
5914  goto finished;
5915  }
5916  }
5917 
5918  finished:
5919  if ((fmode & FMODE_BINMODE) && (fmode & FMODE_TEXTMODE))
5920  goto error;
5921 
5922  return fmode;
5923 
5924  error:
5925  rb_raise(rb_eArgError, "invalid access mode %s", modestr);
5927 }
5928 
5929 int
5930 rb_io_oflags_fmode(int oflags)
5931 {
5932  int fmode = 0;
5933 
5934  switch (oflags & O_ACCMODE) {
5935  case O_RDONLY:
5936  fmode = FMODE_READABLE;
5937  break;
5938  case O_WRONLY:
5939  fmode = FMODE_WRITABLE;
5940  break;
5941  case O_RDWR:
5942  fmode = FMODE_READWRITE;
5943  break;
5944  }
5945 
5946  if (oflags & O_APPEND) {
5947  fmode |= FMODE_APPEND;
5948  }
5949  if (oflags & O_TRUNC) {
5950  fmode |= FMODE_TRUNC;
5951  }
5952  if (oflags & O_CREAT) {
5953  fmode |= FMODE_CREATE;
5954  }
5955  if (oflags & O_EXCL) {
5956  fmode |= FMODE_EXCL;
5957  }
5958 #ifdef O_BINARY
5959  if (oflags & O_BINARY) {
5960  fmode |= FMODE_BINMODE;
5961  }
5962 #endif
5963 
5964  return fmode;
5965 }
5966 
5967 static int
5968 rb_io_fmode_oflags(int fmode)
5969 {
5970  int oflags = 0;
5971 
5972  switch (fmode & FMODE_READWRITE) {
5973  case FMODE_READABLE:
5974  oflags |= O_RDONLY;
5975  break;
5976  case FMODE_WRITABLE:
5977  oflags |= O_WRONLY;
5978  break;
5979  case FMODE_READWRITE:
5980  oflags |= O_RDWR;
5981  break;
5982  }
5983 
5984  if (fmode & FMODE_APPEND) {
5985  oflags |= O_APPEND;
5986  }
5987  if (fmode & FMODE_TRUNC) {
5988  oflags |= O_TRUNC;
5989  }
5990  if (fmode & FMODE_CREATE) {
5991  oflags |= O_CREAT;
5992  }
5993  if (fmode & FMODE_EXCL) {
5994  oflags |= O_EXCL;
5995  }
5996 #ifdef O_BINARY
5997  if (fmode & FMODE_BINMODE) {
5998  oflags |= O_BINARY;
5999  }
6000 #endif
6001 
6002  return oflags;
6003 }
6004 
6005 int
6006 rb_io_modestr_oflags(const char *modestr)
6007 {
6008  return rb_io_fmode_oflags(rb_io_modestr_fmode(modestr));
6009 }
6010 
6011 static const char*
6012 rb_io_oflags_modestr(int oflags)
6013 {
6014 #ifdef O_BINARY
6015 # define MODE_BINARY(a,b) ((oflags & O_BINARY) ? (b) : (a))
6016 #else
6017 # define MODE_BINARY(a,b) (a)
6018 #endif
6019  int accmode;
6020  if (oflags & O_EXCL) {
6021  rb_raise(rb_eArgError, "exclusive access mode is not supported");
6022  }
6023  accmode = oflags & (O_RDONLY|O_WRONLY|O_RDWR);
6024  if (oflags & O_APPEND) {
6025  if (accmode == O_WRONLY) {
6026  return MODE_BINARY("a", "ab");
6027  }
6028  if (accmode == O_RDWR) {
6029  return MODE_BINARY("a+", "ab+");
6030  }
6031  }
6032  switch (accmode) {
6033  default:
6034  rb_raise(rb_eArgError, "invalid access oflags 0x%x", oflags);
6035  case O_RDONLY:
6036  return MODE_BINARY("r", "rb");
6037  case O_WRONLY:
6038  return MODE_BINARY("w", "wb");
6039  case O_RDWR:
6040  if (oflags & O_TRUNC) {
6041  return MODE_BINARY("w+", "wb+");
6042  }
6043  return MODE_BINARY("r+", "rb+");
6044  }
6045 }
6046 
6047 /*
6048  * Convert external/internal encodings to enc/enc2
6049  * NULL => use default encoding
6050  * Qnil => no encoding specified (internal only)
6051  */
6052 static void
6053 rb_io_ext_int_to_encs(rb_encoding *ext, rb_encoding *intern, rb_encoding **enc, rb_encoding **enc2, int fmode)
6054 {
6055  int default_ext = 0;
6056 
6057  if (ext == NULL) {
6059  default_ext = 1;
6060  }
6061  if (ext == rb_ascii8bit_encoding()) {
6062  /* If external is ASCII-8BIT, no transcoding */
6063  intern = NULL;
6064  }
6065  else if (intern == NULL) {
6066  intern = rb_default_internal_encoding();
6067  }
6068  if (intern == NULL || intern == (rb_encoding *)Qnil ||
6069  (!(fmode & FMODE_SETENC_BY_BOM) && (intern == ext))) {
6070  /* No internal encoding => use external + no transcoding */
6071  *enc = (default_ext && intern != ext) ? NULL : ext;
6072  *enc2 = NULL;
6073  }
6074  else {
6075  *enc = intern;
6076  *enc2 = ext;
6077  }
6078 }
6079 
6080 static void
6081 unsupported_encoding(const char *name, rb_encoding *enc)
6082 {
6083  rb_enc_warn(enc, "Unsupported encoding %s ignored", name);
6084 }
6085 
6086 static void
6087 parse_mode_enc(const char *estr, rb_encoding *estr_enc,
6088  rb_encoding **enc_p, rb_encoding **enc2_p, int *fmode_p)
6089 {
6090  const char *p;
6091  char encname[ENCODING_MAXNAMELEN+1];
6092  int idx, idx2;
6093  int fmode = fmode_p ? *fmode_p : 0;
6094  rb_encoding *ext_enc, *int_enc;
6095  long len;
6096 
6097  /* parse estr as "enc" or "enc2:enc" or "enc:-" */
6098 
6099  p = strrchr(estr, ':');
6100  len = p ? (p++ - estr) : (long)strlen(estr);
6101  if ((fmode & FMODE_SETENC_BY_BOM) || io_encname_bom_p(estr, len)) {
6102  estr += bom_prefix_len;
6103  len -= bom_prefix_len;
6104  if (!STRNCASECMP(estr, utf_prefix, utf_prefix_len)) {
6105  fmode |= FMODE_SETENC_BY_BOM;
6106  }
6107  else {
6108  rb_enc_warn(estr_enc, "BOM with non-UTF encoding %s is nonsense", estr);
6109  fmode &= ~FMODE_SETENC_BY_BOM;
6110  }
6111  }
6112  if (len == 0 || len > ENCODING_MAXNAMELEN) {
6113  idx = -1;
6114  }
6115  else {
6116  if (p) {
6117  memcpy(encname, estr, len);
6118  encname[len] = '\0';
6119  estr = encname;
6120  }
6121  idx = rb_enc_find_index(estr);
6122  }
6123  if (fmode_p) *fmode_p = fmode;
6124 
6125  if (idx >= 0)
6126  ext_enc = rb_enc_from_index(idx);
6127  else {
6128  if (idx != -2)
6129  unsupported_encoding(estr, estr_enc);
6130  ext_enc = NULL;
6131  }
6132 
6133  int_enc = NULL;
6134  if (p) {
6135  if (*p == '-' && *(p+1) == '\0') {
6136  /* Special case - "-" => no transcoding */
6137  int_enc = (rb_encoding *)Qnil;
6138  }
6139  else {
6140  idx2 = rb_enc_find_index(p);
6141  if (idx2 < 0)
6142  unsupported_encoding(p, estr_enc);
6143  else if (!(fmode & FMODE_SETENC_BY_BOM) && (idx2 == idx)) {
6144  int_enc = (rb_encoding *)Qnil;
6145  }
6146  else
6147  int_enc = rb_enc_from_index(idx2);
6148  }
6149  }
6150 
6151  rb_io_ext_int_to_encs(ext_enc, int_enc, enc_p, enc2_p, fmode);
6152 }
6153 
6154 int
6155 rb_io_extract_encoding_option(VALUE opt, rb_encoding **enc_p, rb_encoding **enc2_p, int *fmode_p)
6156 {
6157  VALUE encoding=Qnil, extenc=Qundef, intenc=Qundef, tmp;
6158  int extracted = 0;
6159  rb_encoding *extencoding = NULL;
6160  rb_encoding *intencoding = NULL;
6161 
6162  if (!NIL_P(opt)) {
6163  VALUE v;
6164  v = rb_hash_lookup2(opt, sym_encoding, Qnil);
6165  if (v != Qnil) encoding = v;
6166  v = rb_hash_lookup2(opt, sym_extenc, Qundef);
6167  if (v != Qnil) extenc = v;
6168  v = rb_hash_lookup2(opt, sym_intenc, Qundef);
6169  if (v != Qundef) intenc = v;
6170  }
6171  if ((extenc != Qundef || intenc != Qundef) && !NIL_P(encoding)) {
6172  if (!NIL_P(ruby_verbose)) {
6173  int idx = rb_to_encoding_index(encoding);
6174  if (idx >= 0) encoding = rb_enc_from_encoding(rb_enc_from_index(idx));
6175  rb_warn("Ignoring encoding parameter '%"PRIsVALUE"': %s_encoding is used",
6176  encoding, extenc == Qundef ? "internal" : "external");
6177  }
6178  encoding = Qnil;
6179  }
6180  if (extenc != Qundef && !NIL_P(extenc)) {
6181  extencoding = rb_to_encoding(extenc);
6182  }
6183  if (intenc != Qundef) {
6184  if (NIL_P(intenc)) {
6185  /* internal_encoding: nil => no transcoding */
6186  intencoding = (rb_encoding *)Qnil;
6187  }
6188  else if (!NIL_P(tmp = rb_check_string_type(intenc))) {
6189  char *p = StringValueCStr(tmp);
6190 
6191  if (*p == '-' && *(p+1) == '\0') {
6192  /* Special case - "-" => no transcoding */
6193  intencoding = (rb_encoding *)Qnil;
6194  }
6195  else {
6196  intencoding = rb_to_encoding(intenc);
6197  }
6198  }
6199  else {
6200  intencoding = rb_to_encoding(intenc);
6201  }
6202  if (extencoding == intencoding) {
6203  intencoding = (rb_encoding *)Qnil;
6204  }
6205  }
6206  if (!NIL_P(encoding)) {
6207  extracted = 1;
6208  if (!NIL_P(tmp = rb_check_string_type(encoding))) {
6209  parse_mode_enc(StringValueCStr(tmp), rb_enc_get(tmp),
6210  enc_p, enc2_p, fmode_p);
6211  }
6212  else {
6213  rb_io_ext_int_to_encs(rb_to_encoding(encoding), NULL, enc_p, enc2_p, 0);
6214  }
6215  }
6216  else if (extenc != Qundef || intenc != Qundef) {
6217  extracted = 1;
6218  rb_io_ext_int_to_encs(extencoding, intencoding, enc_p, enc2_p, 0);
6219  }
6220  return extracted;
6221 }
6222 
6223 typedef struct rb_io_enc_t convconfig_t;
6224 
6225 static void
6226 validate_enc_binmode(int *fmode_p, int ecflags, rb_encoding *enc, rb_encoding *enc2)
6227 {
6228  int fmode = *fmode_p;
6229 
6230  if ((fmode & FMODE_READABLE) &&
6231  !enc2 &&
6232  !(fmode & FMODE_BINMODE) &&
6234  rb_raise(rb_eArgError, "ASCII incompatible encoding needs binmode");
6235 
6236  if ((fmode & FMODE_BINMODE) && (ecflags & ECONV_NEWLINE_DECORATOR_MASK)) {
6237  rb_raise(rb_eArgError, "newline decorator with binary mode");
6238  }
6239  if (!(fmode & FMODE_BINMODE) &&
6240  (DEFAULT_TEXTMODE || (ecflags & ECONV_NEWLINE_DECORATOR_MASK))) {
6241  fmode |= FMODE_TEXTMODE;
6242  *fmode_p = fmode;
6243  }
6244 #if !DEFAULT_TEXTMODE
6245  else if (!(ecflags & ECONV_NEWLINE_DECORATOR_MASK)) {
6246  fmode &= ~FMODE_TEXTMODE;
6247  *fmode_p = fmode;
6248  }
6249 #endif
6250 }
6251 
6252 static void
6253 extract_binmode(VALUE opthash, int *fmode)
6254 {
6255  if (!NIL_P(opthash)) {
6256  VALUE v;
6257  v = rb_hash_aref(opthash, sym_textmode);
6258  if (!NIL_P(v)) {
6259  if (*fmode & FMODE_TEXTMODE)
6260  rb_raise(rb_eArgError, "textmode specified twice");
6261  if (*fmode & FMODE_BINMODE)
6262  rb_raise(rb_eArgError, "both textmode and binmode specified");
6263  if (RTEST(v))
6264  *fmode |= FMODE_TEXTMODE;
6265  }
6266  v = rb_hash_aref(opthash, sym_binmode);
6267  if (!NIL_P(v)) {
6268  if (*fmode & FMODE_BINMODE)
6269  rb_raise(rb_eArgError, "binmode specified twice");
6270  if (*fmode & FMODE_TEXTMODE)
6271  rb_raise(rb_eArgError, "both textmode and binmode specified");
6272  if (RTEST(v))
6273  *fmode |= FMODE_BINMODE;
6274  }
6275 
6276  if ((*fmode & FMODE_BINMODE) && (*fmode & FMODE_TEXTMODE))
6277  rb_raise(rb_eArgError, "both textmode and binmode specified");
6278  }
6279 }
6280 
6281 void
6282 rb_io_extract_modeenc(VALUE *vmode_p, VALUE *vperm_p, VALUE opthash,
6283  int *oflags_p, int *fmode_p, convconfig_t *convconfig_p)
6284 {
6285  VALUE vmode;
6286  int oflags, fmode;
6287  rb_encoding *enc, *enc2;
6288  int ecflags;
6289  VALUE ecopts;
6290  int has_enc = 0, has_vmode = 0;
6291  VALUE intmode;
6292 
6293  vmode = *vmode_p;
6294 
6295  /* Set to defaults */
6296  rb_io_ext_int_to_encs(NULL, NULL, &enc, &enc2, 0);
6297 
6298  vmode_handle:
6299  if (NIL_P(vmode)) {
6300  fmode = FMODE_READABLE;
6301  oflags = O_RDONLY;
6302  }
6303  else if (!NIL_P(intmode = rb_check_to_integer(vmode, "to_int"))) {
6304  vmode = intmode;
6305  oflags = NUM2INT(intmode);
6306  fmode = rb_io_oflags_fmode(oflags);
6307  }
6308  else {
6309  const char *p;
6310 
6311  SafeStringValue(vmode);
6312  p = StringValueCStr(vmode);
6313  fmode = rb_io_modestr_fmode(p);
6314  oflags = rb_io_fmode_oflags(fmode);
6315  p = strchr(p, ':');
6316  if (p) {
6317  has_enc = 1;
6318  parse_mode_enc(p+1, rb_enc_get(vmode), &enc, &enc2, &fmode);
6319  }
6320  else {
6321  rb_encoding *e;
6322 
6323  e = (fmode & FMODE_BINMODE) ? rb_ascii8bit_encoding() : NULL;
6324  rb_io_ext_int_to_encs(e, NULL, &enc, &enc2, fmode);
6325  }
6326  }
6327 
6328  if (NIL_P(opthash)) {
6329  ecflags = (fmode & FMODE_READABLE) ?
6330  MODE_BTMODE(ECONV_DEFAULT_NEWLINE_DECORATOR,
6332 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
6333  ecflags |= (fmode & FMODE_WRITABLE) ?
6334  MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE,
6335  0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE) : 0;
6336 #endif
6337  SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
6338  ecopts = Qnil;
6339  if (fmode & FMODE_BINMODE) {
6340 #ifdef O_BINARY
6341  oflags |= O_BINARY;
6342 #endif
6343  if (!has_enc)
6344  rb_io_ext_int_to_encs(rb_ascii8bit_encoding(), NULL, &enc, &enc2, fmode);
6345  }
6346 #if DEFAULT_TEXTMODE
6347  else if (NIL_P(vmode)) {
6348  fmode |= DEFAULT_TEXTMODE;
6349  }
6350 #endif
6351  }
6352  else {
6353  VALUE v;
6354  if (!has_vmode) {
6355  v = rb_hash_aref(opthash, sym_mode);
6356  if (!NIL_P(v)) {
6357  if (!NIL_P(vmode)) {
6358  rb_raise(rb_eArgError, "mode specified twice");
6359  }
6360  has_vmode = 1;
6361  vmode = v;
6362  goto vmode_handle;
6363  }
6364  }
6365  v = rb_hash_aref(opthash, sym_flags);
6366  if (!NIL_P(v)) {
6367  v = rb_to_int(v);
6368  oflags |= NUM2INT(v);
6369  vmode = INT2NUM(oflags);
6370  fmode = rb_io_oflags_fmode(oflags);
6371  }
6372  extract_binmode(opthash, &fmode);
6373  if (fmode & FMODE_BINMODE) {
6374 #ifdef O_BINARY
6375  oflags |= O_BINARY;
6376 #endif
6377  if (!has_enc)
6378  rb_io_ext_int_to_encs(rb_ascii8bit_encoding(), NULL, &enc, &enc2, fmode);
6379  }
6380 #if DEFAULT_TEXTMODE
6381  else if (NIL_P(vmode)) {
6382  fmode |= DEFAULT_TEXTMODE;
6383  }
6384 #endif
6385  v = rb_hash_aref(opthash, sym_perm);
6386  if (!NIL_P(v)) {
6387  if (vperm_p) {
6388  if (!NIL_P(*vperm_p)) {
6389  rb_raise(rb_eArgError, "perm specified twice");
6390  }
6391  *vperm_p = v;
6392  }
6393  else {
6394  /* perm no use, just ignore */
6395  }
6396  }
6397  ecflags = (fmode & FMODE_READABLE) ?
6398  MODE_BTMODE(ECONV_DEFAULT_NEWLINE_DECORATOR,
6400 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
6401  ecflags |= (fmode & FMODE_WRITABLE) ?
6402  MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE,
6403  0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE) : 0;
6404 #endif
6405 
6406  if (rb_io_extract_encoding_option(opthash, &enc, &enc2, &fmode)) {
6407  if (has_enc) {
6408  rb_raise(rb_eArgError, "encoding specified twice");
6409  }
6410  }
6411  SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
6412  ecflags = rb_econv_prepare_options(opthash, &ecopts, ecflags);
6413  }
6414 
6415  validate_enc_binmode(&fmode, ecflags, enc, enc2);
6416 
6417  *vmode_p = vmode;
6418 
6419  *oflags_p = oflags;
6420  *fmode_p = fmode;
6421  convconfig_p->enc = enc;
6422  convconfig_p->enc2 = enc2;
6423  convconfig_p->ecflags = ecflags;
6424  convconfig_p->ecopts = ecopts;
6425 }
6426 
6428  VALUE fname;
6429  int oflags;
6430  mode_t perm;
6431 };
6432 
6433 static void *
6434 sysopen_func(void *ptr)
6435 {
6436  const struct sysopen_struct *data = ptr;
6437  const char *fname = RSTRING_PTR(data->fname);
6438  return (void *)(VALUE)rb_cloexec_open(fname, data->oflags, data->perm);
6439 }
6440 
6441 static inline int
6442 rb_sysopen_internal(struct sysopen_struct *data)
6443 {
6444  int fd;
6445  fd = (int)(VALUE)rb_thread_call_without_gvl(sysopen_func, data, RUBY_UBF_IO, 0);
6446  if (0 <= fd)
6447  rb_update_max_fd(fd);
6448  return fd;
6449 }
6450 
6451 static int
6452 rb_sysopen(VALUE fname, int oflags, mode_t perm)
6453 {
6454  int fd;
6455  struct sysopen_struct data;
6456 
6457  data.fname = rb_str_encode_ospath(fname);
6458  StringValueCStr(data.fname);
6459  data.oflags = oflags;
6460  data.perm = perm;
6461 
6462  fd = rb_sysopen_internal(&data);
6463  if (fd < 0) {
6464  int e = errno;
6465  if (rb_gc_for_fd(e)) {
6466  fd = rb_sysopen_internal(&data);
6467  }
6468  if (fd < 0) {
6469  rb_syserr_fail_path(e, fname);
6470  }
6471  }
6472  return fd;
6473 }
6474 
6475 FILE *
6476 rb_fdopen(int fd, const char *modestr)
6477 {
6478  FILE *file;
6479 
6480 #if defined(__sun)
6481  errno = 0;
6482 #endif
6483  file = fdopen(fd, modestr);
6484  if (!file) {
6485  int e = errno;
6486 #if defined(__sun)
6487  if (e == 0) {
6488  rb_gc();
6489  errno = 0;
6490  file = fdopen(fd, modestr);
6491  }
6492  else
6493 #endif
6494  if (rb_gc_for_fd(e)) {
6495  file = fdopen(fd, modestr);
6496  }
6497  if (!file) {
6498 #ifdef _WIN32
6499  if (e == 0) e = EINVAL;
6500 #elif defined(__sun)
6501  if (e == 0) e = EMFILE;
6502 #endif
6503  rb_syserr_fail(e, 0);
6504  }
6505  }
6506 
6507  /* xxx: should be _IONBF? A buffer in FILE may have trouble. */
6508 #ifdef USE_SETVBUF
6509  if (setvbuf(file, NULL, _IOFBF, 0) != 0)
6510  rb_warn("setvbuf() can't be honoured (fd=%d)", fd);
6511 #endif
6512  return file;
6513 }
6514 
6515 static int
6516 io_check_tty(rb_io_t *fptr)
6517 {
6518  int t = isatty(fptr->fd);
6519  if (t)
6520  fptr->mode |= FMODE_TTY|FMODE_DUPLEX;
6521  return t;
6522 }
6523 
6524 static VALUE rb_io_internal_encoding(VALUE);
6525 static void io_encoding_set(rb_io_t *, VALUE, VALUE, VALUE);
6526 
6527 static int
6528 io_strip_bom(VALUE io)
6529 {
6530  VALUE b1, b2, b3, b4;
6531  rb_io_t *fptr;
6532 
6533  GetOpenFile(io, fptr);
6534  if (!(fptr->mode & FMODE_READABLE)) return 0;
6535  if (NIL_P(b1 = rb_io_getbyte(io))) return 0;
6536  switch (b1) {
6537  case INT2FIX(0xEF):
6538  if (NIL_P(b2 = rb_io_getbyte(io))) break;
6539  if (b2 == INT2FIX(0xBB) && !NIL_P(b3 = rb_io_getbyte(io))) {
6540  if (b3 == INT2FIX(0xBF)) {
6541  return rb_utf8_encindex();
6542  }
6543  rb_io_ungetbyte(io, b3);
6544  }
6545  rb_io_ungetbyte(io, b2);
6546  break;
6547 
6548  case INT2FIX(0xFE):
6549  if (NIL_P(b2 = rb_io_getbyte(io))) break;
6550  if (b2 == INT2FIX(0xFF)) {
6551  return ENCINDEX_UTF_16BE;
6552  }
6553  rb_io_ungetbyte(io, b2);
6554  break;
6555 
6556  case INT2FIX(0xFF):
6557  if (NIL_P(b2 = rb_io_getbyte(io))) break;
6558  if (b2 == INT2FIX(0xFE)) {
6559  b3 = rb_io_getbyte(io);
6560  if (b3 == INT2FIX(0) && !NIL_P(b4 = rb_io_getbyte(io))) {
6561  if (b4 == INT2FIX(0)) {
6562  return ENCINDEX_UTF_32LE;
6563  }
6564  rb_io_ungetbyte(io, b4);
6565  }
6566  rb_io_ungetbyte(io, b3);
6567  return ENCINDEX_UTF_16LE;
6568  }
6569  rb_io_ungetbyte(io, b2);
6570  break;
6571 
6572  case INT2FIX(0):
6573  if (NIL_P(b2 = rb_io_getbyte(io))) break;
6574  if (b2 == INT2FIX(0) && !NIL_P(b3 = rb_io_getbyte(io))) {
6575  if (b3 == INT2FIX(0xFE) && !NIL_P(b4 = rb_io_getbyte(io))) {
6576  if (b4 == INT2FIX(0xFF)) {
6577  return ENCINDEX_UTF_32BE;
6578  }
6579  rb_io_ungetbyte(io, b4);
6580  }
6581  rb_io_ungetbyte(io, b3);
6582  }
6583  rb_io_ungetbyte(io, b2);
6584  break;
6585  }
6586  rb_io_ungetbyte(io, b1);
6587  return 0;
6588 }
6589 
6590 static rb_encoding *
6591 io_set_encoding_by_bom(VALUE io)
6592 {
6593  int idx = io_strip_bom(io);
6594  rb_io_t *fptr;
6595  rb_encoding *extenc = NULL;
6596 
6597  GetOpenFile(io, fptr);
6598  if (idx) {
6599  extenc = rb_enc_from_index(idx);
6600  io_encoding_set(fptr, rb_enc_from_encoding(extenc),
6601  rb_io_internal_encoding(io), Qnil);
6602  }
6603  else {
6604  fptr->encs.enc2 = NULL;
6605  }
6606  return extenc;
6607 }
6608 
6609 static VALUE
6610 rb_file_open_generic(VALUE io, VALUE filename, int oflags, int fmode,
6611  const convconfig_t *convconfig, mode_t perm)
6612 {
6613  VALUE pathv;
6614  rb_io_t *fptr;
6615  convconfig_t cc;
6616  if (!convconfig) {
6617  /* Set to default encodings */
6618  rb_io_ext_int_to_encs(NULL, NULL, &cc.enc, &cc.enc2, fmode);
6619  cc.ecflags = 0;
6620  cc.ecopts = Qnil;
6621  convconfig = &cc;
6622  }
6623  validate_enc_binmode(&fmode, convconfig->ecflags,
6624  convconfig->enc, convconfig->enc2);
6625 
6626  MakeOpenFile(io, fptr);
6627  fptr->mode = fmode;
6628  fptr->encs = *convconfig;
6629  pathv = rb_str_new_frozen(filename);
6630 #ifdef O_TMPFILE
6631  if (!(oflags & O_TMPFILE)) {
6632  fptr->pathv = pathv;
6633  }
6634 #else
6635  fptr->pathv = pathv;
6636 #endif
6637  fptr->fd = rb_sysopen(pathv, oflags, perm);
6638  io_check_tty(fptr);
6639  if (fmode & FMODE_SETENC_BY_BOM) io_set_encoding_by_bom(io);
6640 
6641  return io;
6642 }
6643 
6644 static VALUE
6645 rb_file_open_internal(VALUE io, VALUE filename, const char *modestr)
6646 {
6647  int fmode = rb_io_modestr_fmode(modestr);
6648  const char *p = strchr(modestr, ':');
6649  convconfig_t convconfig;
6650 
6651  if (p) {
6652  parse_mode_enc(p+1, rb_usascii_encoding(),
6653  &convconfig.enc, &convconfig.enc2, &fmode);
6654  convconfig.ecflags = 0;
6655  convconfig.ecopts = Qnil;
6656  }
6657  else {
6658  rb_encoding *e;
6659  /* Set to default encodings */
6660 
6661  e = (fmode & FMODE_BINMODE) ? rb_ascii8bit_encoding() : NULL;
6662  rb_io_ext_int_to_encs(e, NULL, &convconfig.enc, &convconfig.enc2, fmode);
6663  convconfig.ecflags = 0;
6664  convconfig.ecopts = Qnil;
6665  }
6666 
6667  return rb_file_open_generic(io, filename,
6668  rb_io_fmode_oflags(fmode),
6669  fmode,
6670  &convconfig,
6671  0666);
6672 }
6673 
6674 VALUE
6675 rb_file_open_str(VALUE fname, const char *modestr)
6676 {
6677  FilePathValue(fname);
6678  return rb_file_open_internal(io_alloc(rb_cFile), fname, modestr);
6679 }
6680 
6681 VALUE
6682 rb_file_open(const char *fname, const char *modestr)
6683 {
6684  return rb_file_open_internal(io_alloc(rb_cFile), rb_str_new_cstr(fname), modestr);
6685 }
6686 
6687 #if defined(__CYGWIN__) || !defined(HAVE_WORKING_FORK)
6688 static struct pipe_list {
6689  rb_io_t *fptr;
6690  struct pipe_list *next;
6691 } *pipe_list;
6692 
6693 static void
6694 pipe_add_fptr(rb_io_t *fptr)
6695 {
6696  struct pipe_list *list;
6697 
6698  list = ALLOC(struct pipe_list);
6699  list->fptr = fptr;
6700  list->next = pipe_list;
6701  pipe_list = list;
6702 }
6703 
6704 static void
6705 pipe_del_fptr(rb_io_t *fptr)
6706 {
6707  struct pipe_list **prev = &pipe_list;
6708  struct pipe_list *tmp;
6709 
6710  while ((tmp = *prev) != 0) {
6711  if (tmp->fptr == fptr) {
6712  *prev = tmp->next;
6713  free(tmp);
6714  return;
6715  }
6716  prev = &tmp->next;
6717  }
6718 }
6719 
6720 #if defined (_WIN32) || defined(__CYGWIN__)
6721 static void
6722 pipe_atexit(void)
6723 {
6724  struct pipe_list *list = pipe_list;
6725  struct pipe_list *tmp;
6726 
6727  while (list) {
6728  tmp = list->next;
6729  rb_io_fptr_finalize(list->fptr);
6730  list = tmp;
6731  }
6732 }
6733 #endif
6734 
6735 static void
6736 pipe_finalize(rb_io_t *fptr, int noraise)
6737 {
6738 #if !defined(HAVE_WORKING_FORK) && !defined(_WIN32)
6739  int status = 0;
6740  if (fptr->stdio_file) {
6741  status = pclose(fptr->stdio_file);
6742  }
6743  fptr->fd = -1;
6744  fptr->stdio_file = 0;
6745  rb_last_status_set(status, fptr->pid);
6746 #else
6747  fptr_finalize(fptr, noraise);
6748 #endif
6749  pipe_del_fptr(fptr);
6750 }
6751 #endif
6752 
6753 static void
6754 fptr_copy_finalizer(rb_io_t *fptr, const rb_io_t *orig)
6755 {
6756 #if defined(__CYGWIN__) || !defined(HAVE_WORKING_FORK)
6757  void (*const old_finalize)(struct rb_io_t*,int) = fptr->finalize;
6758 
6759  if (old_finalize == orig->finalize) return;
6760 #endif
6761 
6762  fptr->finalize = orig->finalize;
6763 
6764 #if defined(__CYGWIN__) || !defined(HAVE_WORKING_FORK)
6765  if (old_finalize != pipe_finalize) {
6766  struct pipe_list *list;
6767  for (list = pipe_list; list; list = list->next) {
6768  if (list->fptr == fptr) break;
6769  }
6770  if (!list) pipe_add_fptr(fptr);
6771  }
6772  else {
6773  pipe_del_fptr(fptr);
6774  }
6775 #endif
6776 }
6777 
6778 void
6780 {
6782  fptr->mode |= FMODE_SYNC;
6783 }
6784 
6785 void
6786 rb_io_unbuffered(rb_io_t *fptr)
6787 {
6788  rb_io_synchronized(fptr);
6789 }
6790 
6791 int
6792 rb_pipe(int *pipes)
6793 {
6794  int ret;
6795  ret = rb_cloexec_pipe(pipes);
6796  if (ret < 0) {
6797  if (rb_gc_for_fd(errno)) {
6798  ret = rb_cloexec_pipe(pipes);
6799  }
6800  }
6801  if (ret == 0) {
6802  rb_update_max_fd(pipes[0]);
6803  rb_update_max_fd(pipes[1]);
6804  }
6805  return ret;
6806 }
6807 
6808 #ifdef _WIN32
6809 #define HAVE_SPAWNV 1
6810 #define spawnv(mode, cmd, args) rb_w32_uaspawn((mode), (cmd), (args))
6811 #define spawn(mode, cmd) rb_w32_uspawn((mode), (cmd), 0)
6812 #endif
6813 
6814 #if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
6815 struct popen_arg {
6816  VALUE execarg_obj;
6817  struct rb_execarg *eargp;
6818  int modef;
6819  int pair[2];
6820  int write_pair[2];
6821 };
6822 #endif
6823 
6824 #ifdef HAVE_WORKING_FORK
6825 # ifndef __EMSCRIPTEN__
6826 static void
6827 popen_redirect(struct popen_arg *p)
6828 {
6829  if ((p->modef & FMODE_READABLE) && (p->modef & FMODE_WRITABLE)) {
6830  close(p->write_pair[1]);
6831  if (p->write_pair[0] != 0) {
6832  dup2(p->write_pair[0], 0);
6833  close(p->write_pair[0]);
6834  }
6835  close(p->pair[0]);
6836  if (p->pair[1] != 1) {
6837  dup2(p->pair[1], 1);
6838  close(p->pair[1]);
6839  }
6840  }
6841  else if (p->modef & FMODE_READABLE) {
6842  close(p->pair[0]);
6843  if (p->pair[1] != 1) {
6844  dup2(p->pair[1], 1);
6845  close(p->pair[1]);
6846  }
6847  }
6848  else {
6849  close(p->pair[1]);
6850  if (p->pair[0] != 0) {
6851  dup2(p->pair[0], 0);
6852  close(p->pair[0]);
6853  }
6854  }
6855 }
6856 # endif
6857 
6858 #if defined(__linux__)
6859 /* Linux /proc/self/status contains a line: "FDSize:\t<nnn>\n"
6860  * Since /proc may not be available, linux_get_maxfd is just a hint.
6861  * This function, linux_get_maxfd, must be async-signal-safe.
6862  * I.e. opendir() is not usable.
6863  *
6864  * Note that memchr() and memcmp is *not* async-signal-safe in POSIX.
6865  * However they are easy to re-implement in async-signal-safe manner.
6866  * (Also note that there is missing/memcmp.c.)
6867  */
6868 static int
6869 linux_get_maxfd(void)
6870 {
6871  int fd;
6872  char buf[4096], *p, *np, *e;
6873  ssize_t ss;
6874  fd = rb_cloexec_open("/proc/self/status", O_RDONLY|O_NOCTTY, 0);
6875  if (fd < 0) return fd;
6876  ss = read(fd, buf, sizeof(buf));
6877  if (ss < 0) goto err;
6878  p = buf;
6879  e = buf + ss;
6880  while ((int)sizeof("FDSize:\t0\n")-1 <= e-p &&
6881  (np = memchr(p, '\n', e-p)) != NULL) {
6882  if (memcmp(p, "FDSize:", sizeof("FDSize:")-1) == 0) {
6883  int fdsize;
6884  p += sizeof("FDSize:")-1;
6885  *np = '\0';
6886  fdsize = (int)ruby_strtoul(p, (char **)NULL, 10);
6887  close(fd);
6888  return fdsize;
6889  }
6890  p = np+1;
6891  }
6892  /* fall through */
6893 
6894  err:
6895  close(fd);
6896  return (int)ss;
6897 }
6898 #endif
6899 
6900 /* This function should be async-signal-safe. */
6901 void
6902 rb_close_before_exec(int lowfd, int maxhint, VALUE noclose_fds)
6903 {
6904 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
6905  int fd, ret;
6906  int max = (int)max_file_descriptor;
6907 # ifdef F_MAXFD
6908  /* F_MAXFD is available since NetBSD 2.0. */
6909  ret = fcntl(0, F_MAXFD); /* async-signal-safe */
6910  if (ret != -1)
6911  maxhint = max = ret;
6912 # elif defined(__linux__)
6913  ret = linux_get_maxfd();
6914  if (maxhint < ret)
6915  maxhint = ret;
6916  /* maxhint = max = ret; if (ret == -1) abort(); // test */
6917 # endif
6918  if (max < maxhint)
6919  max = maxhint;
6920  for (fd = lowfd; fd <= max; fd++) {
6921  if (!NIL_P(noclose_fds) &&
6922  RTEST(rb_hash_lookup(noclose_fds, INT2FIX(fd)))) /* async-signal-safe */
6923  continue;
6924  ret = fcntl(fd, F_GETFD); /* async-signal-safe */
6925  if (ret != -1 && !(ret & FD_CLOEXEC)) {
6926  fcntl(fd, F_SETFD, ret|FD_CLOEXEC); /* async-signal-safe */
6927  }
6928 # define CONTIGUOUS_CLOSED_FDS 20
6929  if (ret != -1) {
6930  if (max < fd + CONTIGUOUS_CLOSED_FDS)
6931  max = fd + CONTIGUOUS_CLOSED_FDS;
6932  }
6933  }
6934 #endif
6935 }
6936 
6937 # ifndef __EMSCRIPTEN__
6938 static int
6939 popen_exec(void *pp, char *errmsg, size_t errmsg_len)
6940 {
6941  struct popen_arg *p = (struct popen_arg*)pp;
6942 
6943  return rb_exec_async_signal_safe(p->eargp, errmsg, errmsg_len);
6944 }
6945 # endif
6946 #endif
6947 
6948 #if (defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)) && !defined __EMSCRIPTEN__
6949 static VALUE
6950 rb_execarg_fixup_v(VALUE execarg_obj)
6951 {
6952  rb_execarg_parent_start(execarg_obj);
6953  return Qnil;
6954 }
6955 #else
6956 char *rb_execarg_commandline(const struct rb_execarg *eargp, VALUE *prog);
6957 #endif
6958 
6959 #ifndef __EMSCRIPTEN__
6960 static VALUE
6961 pipe_open(VALUE execarg_obj, const char *modestr, int fmode,
6962  const convconfig_t *convconfig)
6963 {
6964  struct rb_execarg *eargp = NIL_P(execarg_obj) ? NULL : rb_execarg_get(execarg_obj);
6965  VALUE prog = eargp ? (eargp->use_shell ? eargp->invoke.sh.shell_script : eargp->invoke.cmd.command_name) : Qfalse ;
6966  rb_pid_t pid = 0;
6967  rb_io_t *fptr;
6968  VALUE port;
6969  rb_io_t *write_fptr;
6970  VALUE write_port;
6971 #if defined(HAVE_WORKING_FORK)
6972  int status;
6973  char errmsg[80] = { '\0' };
6974 #endif
6975 #if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
6976  int state;
6977  struct popen_arg arg;
6978 #endif
6979  int e = 0;
6980 #if defined(HAVE_SPAWNV)
6981 # if defined(HAVE_SPAWNVE)
6982 # define DO_SPAWN(cmd, args, envp) ((args) ? \
6983  spawnve(P_NOWAIT, (cmd), (args), (envp)) : \
6984  spawne(P_NOWAIT, (cmd), (envp)))
6985 # else
6986 # define DO_SPAWN(cmd, args, envp) ((args) ? \
6987  spawnv(P_NOWAIT, (cmd), (args)) : \
6988  spawn(P_NOWAIT, (cmd)))
6989 # endif
6990 # if !defined(HAVE_WORKING_FORK)
6991  char **args = NULL;
6992 # if defined(HAVE_SPAWNVE)
6993  char **envp = NULL;
6994 # endif
6995 # endif
6996 #endif
6997 #if !defined(HAVE_WORKING_FORK)
6998  struct rb_execarg sarg, *sargp = &sarg;
6999 #endif
7000  FILE *fp = 0;
7001  int fd = -1;
7002  int write_fd = -1;
7003 #if !defined(HAVE_WORKING_FORK)
7004  const char *cmd = 0;
7005 
7006  if (prog)
7007  cmd = StringValueCStr(prog);
7008 #endif
7009 
7010 #if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
7011  arg.execarg_obj = execarg_obj;
7012  arg.eargp = eargp;
7013  arg.modef = fmode;
7014  arg.pair[0] = arg.pair[1] = -1;
7015  arg.write_pair[0] = arg.write_pair[1] = -1;
7016 # if !defined(HAVE_WORKING_FORK)
7017  if (eargp && !eargp->use_shell) {
7018  args = ARGVSTR2ARGV(eargp->invoke.cmd.argv_str);
7019  }
7020 # endif
7021  switch (fmode & (FMODE_READABLE|FMODE_WRITABLE)) {
7023  if (rb_pipe(arg.write_pair) < 0)
7024  rb_sys_fail_str(prog);
7025  if (rb_pipe(arg.pair) < 0) {
7026  e = errno;
7027  close(arg.write_pair[0]);
7028  close(arg.write_pair[1]);
7029  rb_syserr_fail_str(e, prog);
7030  }
7031  if (eargp) {
7032  rb_execarg_addopt(execarg_obj, INT2FIX(0), INT2FIX(arg.write_pair[0]));
7033  rb_execarg_addopt(execarg_obj, INT2FIX(1), INT2FIX(arg.pair[1]));
7034  }
7035  break;
7036  case FMODE_READABLE:
7037  if (rb_pipe(arg.pair) < 0)
7038  rb_sys_fail_str(prog);
7039  if (eargp)
7040  rb_execarg_addopt(execarg_obj, INT2FIX(1), INT2FIX(arg.pair[1]));
7041  break;
7042  case FMODE_WRITABLE:
7043  if (rb_pipe(arg.pair) < 0)
7044  rb_sys_fail_str(prog);
7045  if (eargp)
7046  rb_execarg_addopt(execarg_obj, INT2FIX(0), INT2FIX(arg.pair[0]));
7047  break;
7048  default:
7049  rb_sys_fail_str(prog);
7050  }
7051  if (!NIL_P(execarg_obj)) {
7052  rb_protect(rb_execarg_fixup_v, execarg_obj, &state);
7053  if (state) {
7054  if (0 <= arg.write_pair[0]) close(arg.write_pair[0]);
7055  if (0 <= arg.write_pair[1]) close(arg.write_pair[1]);
7056  if (0 <= arg.pair[0]) close(arg.pair[0]);
7057  if (0 <= arg.pair[1]) close(arg.pair[1]);
7058  rb_execarg_parent_end(execarg_obj);
7059  rb_jump_tag(state);
7060  }
7061 
7062 # if defined(HAVE_WORKING_FORK)
7063  pid = rb_fork_async_signal_safe(&status, popen_exec, &arg, arg.eargp->redirect_fds, errmsg, sizeof(errmsg));
7064 # else
7065  rb_execarg_run_options(eargp, sargp, NULL, 0);
7066 # if defined(HAVE_SPAWNVE)
7067  if (eargp->envp_str) envp = (char **)RSTRING_PTR(eargp->envp_str);
7068 # endif
7069  while ((pid = DO_SPAWN(cmd, args, envp)) < 0) {
7070  /* exec failed */
7071  switch (e = errno) {
7072  case EAGAIN:
7073 # if EWOULDBLOCK != EAGAIN
7074  case EWOULDBLOCK:
7075 # endif
7076  rb_thread_sleep(1);
7077  continue;
7078  }
7079  break;
7080  }
7081  if (eargp)
7082  rb_execarg_run_options(sargp, NULL, NULL, 0);
7083 # endif
7084  rb_execarg_parent_end(execarg_obj);
7085  }
7086  else {
7087 # if defined(HAVE_WORKING_FORK)
7088  pid = rb_call_proc__fork();
7089  if (pid == 0) { /* child */
7090  popen_redirect(&arg);
7091  rb_io_synchronized(RFILE(orig_stdout)->fptr);
7092  rb_io_synchronized(RFILE(orig_stderr)->fptr);
7093  return Qnil;
7094  }
7095 # else
7096  rb_notimplement();
7097 # endif
7098  }
7099 
7100  /* parent */
7101  if (pid < 0) {
7102 # if defined(HAVE_WORKING_FORK)
7103  e = errno;
7104 # endif
7105  close(arg.pair[0]);
7106  close(arg.pair[1]);
7108  close(arg.write_pair[0]);
7109  close(arg.write_pair[1]);
7110  }
7111 # if defined(HAVE_WORKING_FORK)
7112  if (errmsg[0])
7113  rb_syserr_fail(e, errmsg);
7114 # endif
7115  rb_syserr_fail_str(e, prog);
7116  }
7117  if ((fmode & FMODE_READABLE) && (fmode & FMODE_WRITABLE)) {
7118  close(arg.pair[1]);
7119  fd = arg.pair[0];
7120  close(arg.write_pair[0]);
7121  write_fd = arg.write_pair[1];
7122  }
7123  else if (fmode & FMODE_READABLE) {
7124  close(arg.pair[1]);
7125  fd = arg.pair[0];
7126  }
7127  else {
7128  close(arg.pair[0]);
7129  fd = arg.pair[1];
7130  }
7131 #else
7132  cmd = rb_execarg_commandline(eargp, &prog);
7133  if (!NIL_P(execarg_obj)) {
7134  rb_execarg_parent_start(execarg_obj);
7135  rb_execarg_run_options(eargp, sargp, NULL, 0);
7136  }
7137  fp = popen(cmd, modestr);
7138  e = errno;
7139  if (eargp) {
7140  rb_execarg_parent_end(execarg_obj);
7141  rb_execarg_run_options(sargp, NULL, NULL, 0);
7142  }
7143  if (!fp) rb_syserr_fail_path(e, prog);
7144  fd = fileno(fp);
7145 #endif
7146 
7147  port = io_alloc(rb_cIO);
7148  MakeOpenFile(port, fptr);
7149  fptr->fd = fd;
7150  fptr->stdio_file = fp;
7151  fptr->mode = fmode | FMODE_SYNC|FMODE_DUPLEX;
7152  if (convconfig) {
7153  fptr->encs = *convconfig;
7154 #if RUBY_CRLF_ENVIRONMENT
7157  }
7158 #endif
7159  }
7160  else {
7161  if (NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {
7163  }
7164 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
7165  if (NEED_NEWLINE_DECORATOR_ON_WRITE(fptr)) {
7166  fptr->encs.ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
7167  }
7168 #endif
7169  }
7170  fptr->pid = pid;
7171 
7172  if (0 <= write_fd) {
7173  write_port = io_alloc(rb_cIO);
7174  MakeOpenFile(write_port, write_fptr);
7175  write_fptr->fd = write_fd;
7176  write_fptr->mode = (fmode & ~FMODE_READABLE)| FMODE_SYNC|FMODE_DUPLEX;
7177  fptr->mode &= ~FMODE_WRITABLE;
7178  fptr->tied_io_for_writing = write_port;
7179  rb_ivar_set(port, rb_intern("@tied_io_for_writing"), write_port);
7180  }
7181 
7182 #if defined (__CYGWIN__) || !defined(HAVE_WORKING_FORK)
7183  fptr->finalize = pipe_finalize;
7184  pipe_add_fptr(fptr);
7185 #endif
7186  return port;
7187 }
7188 #else
7189 static VALUE
7190 pipe_open(VALUE execarg_obj, const char *modestr, int fmode,
7191  const convconfig_t *convconfig)
7192 {
7193  rb_raise(rb_eNotImpError, "popen() is not available");
7194 }
7195 #endif
7196 
7197 static int
7198 is_popen_fork(VALUE prog)
7199 {
7200  if (RSTRING_LEN(prog) == 1 && RSTRING_PTR(prog)[0] == '-') {
7201 #if !defined(HAVE_WORKING_FORK)
7203  "fork() function is unimplemented on this machine");
7204 #else
7205  return TRUE;
7206 #endif
7207  }
7208  return FALSE;
7209 }
7210 
7211 static VALUE
7212 pipe_open_s(VALUE prog, const char *modestr, int fmode,
7213  const convconfig_t *convconfig)
7214 {
7215  int argc = 1;
7216  VALUE *argv = &prog;
7217  VALUE execarg_obj = Qnil;
7218 
7219  if (!is_popen_fork(prog))
7220  execarg_obj = rb_execarg_new(argc, argv, TRUE, FALSE);
7221  return pipe_open(execarg_obj, modestr, fmode, convconfig);
7222 }
7223 
7224 static VALUE
7225 pipe_close(VALUE io)
7226 {
7227  rb_io_t *fptr = io_close_fptr(io);
7228  if (fptr) {
7229  fptr_waitpid(fptr, rb_thread_to_be_killed(rb_thread_current()));
7230  }
7231  return Qnil;
7232 }
7233 
7234 static VALUE popen_finish(VALUE port, VALUE klass);
7235 
7236 /*
7237  * call-seq:
7238  * IO.popen([env,] cmd, mode="r" [, opt]) -> io
7239  * IO.popen([env,] cmd, mode="r" [, opt]) {|io| block } -> obj
7240  *
7241  * Runs the specified command as a subprocess; the subprocess's
7242  * standard input and output will be connected to the returned
7243  * IO object.
7244  *
7245  * The PID of the started process can be obtained by IO#pid method.
7246  *
7247  * _cmd_ is a string or an array as follows.
7248  *
7249  * cmd:
7250  * "-" : fork
7251  * commandline : command line string which is passed to a shell
7252  * [env, cmdname, arg1, ..., opts] : command name and zero or more arguments (no shell)
7253  * [env, [cmdname, argv0], arg1, ..., opts] : command name, argv[0] and zero or more arguments (no shell)
7254  * (env and opts are optional.)
7255  *
7256  * If _cmd_ is a +String+ ``<code>-</code>'',
7257  * then a new instance of Ruby is started as the subprocess.
7258  *
7259  * If <i>cmd</i> is an +Array+ of +String+,
7260  * then it will be used as the subprocess's +argv+ bypassing a shell.
7261  * The array can contain a hash at first for environments and
7262  * a hash at last for options similar to #spawn.
7263  *
7264  * The default mode for the new file object is ``r'',
7265  * but <i>mode</i> may be set to any of the modes listed in the description for class IO.
7266  * The last argument <i>opt</i> qualifies <i>mode</i>.
7267  *
7268  * # set IO encoding
7269  * IO.popen("nkf -e filename", :external_encoding=>"EUC-JP") {|nkf_io|
7270  * euc_jp_string = nkf_io.read
7271  * }
7272  *
7273  * # merge standard output and standard error using
7274  * # spawn option. See the document of Kernel.spawn.
7275  * IO.popen(["ls", "/", :err=>[:child, :out]]) {|ls_io|
7276  * ls_result_with_error = ls_io.read
7277  * }
7278  *
7279  * # spawn options can be mixed with IO options
7280  * IO.popen(["ls", "/"], :err=>[:child, :out]) {|ls_io|
7281  * ls_result_with_error = ls_io.read
7282  * }
7283  *
7284  * Raises exceptions which IO.pipe and Kernel.spawn raise.
7285  *
7286  * If a block is given, Ruby will run the command as a child connected
7287  * to Ruby with a pipe. Ruby's end of the pipe will be passed as a
7288  * parameter to the block.
7289  * At the end of block, Ruby closes the pipe and sets <code>$?</code>.
7290  * In this case IO.popen returns the value of the block.
7291  *
7292  * If a block is given with a _cmd_ of ``<code>-</code>'',
7293  * the block will be run in two separate processes: once in the parent,
7294  * and once in a child. The parent process will be passed the pipe
7295  * object as a parameter to the block, the child version of the block
7296  * will be passed +nil+, and the child's standard in and
7297  * standard out will be connected to the parent through the pipe. Not
7298  * available on all platforms.
7299  *
7300  * f = IO.popen("uname")
7301  * p f.readlines
7302  * f.close
7303  * puts "Parent is #{Process.pid}"
7304  * IO.popen("date") {|f| puts f.gets }
7305  * IO.popen("-") {|f| $stderr.puts "#{Process.pid} is here, f is #{f.inspect}"}
7306  * p $?
7307  * IO.popen(%w"sed -e s|^|<foo>| -e s&$&;zot;&", "r+") {|f|
7308  * f.puts "bar"; f.close_write; puts f.gets
7309  * }
7310  *
7311  * <em>produces:</em>
7312  *
7313  * ["Linux\n"]
7314  * Parent is 21346
7315  * Thu Jan 15 22:41:19 JST 2009
7316  * 21346 is here, f is #<IO:fd 3>
7317  * 21352 is here, f is nil
7318  * #<Process::Status: pid 21352 exit 0>
7319  * <foo>bar;zot;
7320  */
7321 
7322 static VALUE
7323 rb_io_s_popen(int argc, VALUE *argv, VALUE klass)
7324 {
7325  VALUE pname, pmode = Qnil, opt = Qnil, env = Qnil;
7326 
7327  if (argc > 1 && !NIL_P(opt = rb_check_hash_type(argv[argc-1]))) --argc;
7328  if (argc > 1 && !NIL_P(env = rb_check_hash_type(argv[0]))) --argc, ++argv;
7329  switch (argc) {
7330  case 2:
7331  pmode = argv[1];
7332  case 1:
7333  pname = argv[0];
7334  break;
7335  default:
7336  {
7337  int ex = !NIL_P(opt);
7338  rb_error_arity(argc + ex, 1 + ex, 2 + ex);
7339  }
7340  }
7341  return popen_finish(rb_io_popen(pname, pmode, env, opt), klass);
7342 }
7343 
7344 VALUE
7345 rb_io_popen(VALUE pname, VALUE pmode, VALUE env, VALUE opt)
7346 {
7347  const char *modestr;
7348  VALUE tmp, execarg_obj = Qnil;
7349  int oflags, fmode;
7350  convconfig_t convconfig;
7351 
7352  tmp = rb_check_array_type(pname);
7353  if (!NIL_P(tmp)) {
7354  long len = RARRAY_LEN(tmp);
7355 #if SIZEOF_LONG > SIZEOF_INT
7356  if (len > INT_MAX) {
7357  rb_raise(rb_eArgError, "too many arguments");
7358  }
7359 #endif
7360  execarg_obj = rb_execarg_new((int)len, RARRAY_CONST_PTR(tmp), FALSE, FALSE);
7361  RB_GC_GUARD(tmp);
7362  }
7363  else {
7364  SafeStringValue(pname);
7365  execarg_obj = Qnil;
7366  if (!is_popen_fork(pname))
7367  execarg_obj = rb_execarg_new(1, &pname, TRUE, FALSE);
7368  }
7369  if (!NIL_P(execarg_obj)) {
7370  if (!NIL_P(opt))
7371  opt = rb_execarg_extract_options(execarg_obj, opt);
7372  if (!NIL_P(env))
7373  rb_execarg_setenv(execarg_obj, env);
7374  }
7375  rb_io_extract_modeenc(&pmode, 0, opt, &oflags, &fmode, &convconfig);
7376  modestr = rb_io_oflags_modestr(oflags);
7377 
7378  return pipe_open(execarg_obj, modestr, fmode, &convconfig);
7379 }
7380 
7381 static VALUE
7382 popen_finish(VALUE port, VALUE klass)
7383 {
7384  if (NIL_P(port)) {
7385  /* child */
7386  if (rb_block_given_p()) {
7387  rb_yield(Qnil);
7390  _exit(0);
7391  }
7392  return Qnil;
7393  }
7394  RBASIC_SET_CLASS(port, klass);
7395  if (rb_block_given_p()) {
7396  return rb_ensure(rb_yield, port, pipe_close, port);
7397  }
7398  return port;
7399 }
7400 
7401 static void
7402 rb_scan_open_args(int argc, const VALUE *argv,
7403  VALUE *fname_p, int *oflags_p, int *fmode_p,
7404  convconfig_t *convconfig_p, mode_t *perm_p)
7405 {
7406  VALUE opt, fname, vmode, vperm;
7407  int oflags, fmode;
7408  mode_t perm;
7409 
7410  argc = rb_scan_args(argc, argv, "12:", &fname, &vmode, &vperm, &opt);
7411  FilePathValue(fname);
7412 
7413  rb_io_extract_modeenc(&vmode, &vperm, opt, &oflags, &fmode, convconfig_p);
7414 
7415  perm = NIL_P(vperm) ? 0666 : NUM2MODET(vperm);
7416 
7417  *fname_p = fname;
7418  *oflags_p = oflags;
7419  *fmode_p = fmode;
7420  *perm_p = perm;
7421 }
7422 
7423 static VALUE
7424 rb_open_file(int argc, const VALUE *argv, VALUE io)
7425 {
7426  VALUE fname;
7427  int oflags, fmode;
7428  convconfig_t convconfig;
7429  mode_t perm;
7430 
7431  rb_scan_open_args(argc, argv, &fname, &oflags, &fmode, &convconfig, &perm);
7432  rb_file_open_generic(io, fname, oflags, fmode, &convconfig, perm);
7433 
7434  return io;
7435 }
7436 
7437 
7438 /*
7439  * Document-method: File::open
7440  *
7441  * call-seq:
7442  * File.open(filename, mode="r" [, opt]) -> file
7443  * File.open(filename [, mode [, perm]] [, opt]) -> file
7444  * File.open(filename, mode="r" [, opt]) {|file| block } -> obj
7445  * File.open(filename [, mode [, perm]] [, opt]) {|file| block } -> obj
7446  *
7447  * With no associated block, File.open is a synonym for
7448  * File.new. If the optional code block is given, it will
7449  * be passed the opened +file+ as an argument and the File object will
7450  * automatically be closed when the block terminates. The value of the block
7451  * will be returned from File.open.
7452  *
7453  * If a file is being created, its initial permissions may be set using the
7454  * +perm+ parameter. See File.new for further discussion.
7455  *
7456  * See IO.new for a description of the +mode+ and +opt+ parameters.
7457  */
7458 
7459 /*
7460  * Document-method: IO::open
7461  *
7462  * call-seq:
7463  * IO.open(fd, mode="r" [, opt]) -> io
7464  * IO.open(fd, mode="r" [, opt]) {|io| block } -> obj
7465  *
7466  * With no associated block, IO.open is a synonym for IO.new. If
7467  * the optional code block is given, it will be passed +io+ as an argument,
7468  * and the IO object will automatically be closed when the block terminates.
7469  * In this instance, IO.open returns the value of the block.
7470  *
7471  * See IO.new for a description of the +fd+, +mode+ and +opt+ parameters.
7472  */
7473 
7474 static VALUE
7475 rb_io_s_open(int argc, VALUE *argv, VALUE klass)
7476 {
7477  VALUE io = rb_class_new_instance_kw(argc, argv, klass, RB_PASS_CALLED_KEYWORDS);
7478 
7479  if (rb_block_given_p()) {
7480  return rb_ensure(rb_yield, io, io_close, io);
7481  }
7482 
7483  return io;
7484 }
7485 
7486 /*
7487  * call-seq:
7488  * IO.sysopen(path, [mode, [perm]]) -> integer
7489  *
7490  * Opens the given path, returning the underlying file descriptor as a
7491  * Integer.
7492  *
7493  * IO.sysopen("testfile") #=> 3
7494  */
7495 
7496 static VALUE
7497 rb_io_s_sysopen(int argc, VALUE *argv, VALUE _)
7498 {
7499  VALUE fname, vmode, vperm;
7500  VALUE intmode;
7501  int oflags, fd;
7502  mode_t perm;
7503 
7504  rb_scan_args(argc, argv, "12", &fname, &vmode, &vperm);
7505  FilePathValue(fname);
7506 
7507  if (NIL_P(vmode))
7508  oflags = O_RDONLY;
7509  else if (!NIL_P(intmode = rb_check_to_integer(vmode, "to_int")))
7510  oflags = NUM2INT(intmode);
7511  else {
7512  SafeStringValue(vmode);
7513  oflags = rb_io_modestr_oflags(StringValueCStr(vmode));
7514  }
7515  if (NIL_P(vperm)) perm = 0666;
7516  else perm = NUM2MODET(vperm);
7517 
7518  RB_GC_GUARD(fname) = rb_str_new4(fname);
7519  fd = rb_sysopen(fname, oflags, perm);
7520  return INT2NUM(fd);
7521 }
7522 
7523 static VALUE
7524 check_pipe_command(VALUE filename_or_command)
7525 {
7526  char *s = RSTRING_PTR(filename_or_command);
7527  long l = RSTRING_LEN(filename_or_command);
7528  char *e = s + l;
7529  int chlen;
7530 
7531  if (rb_enc_ascget(s, e, &chlen, rb_enc_get(filename_or_command)) == '|') {
7532  VALUE cmd = rb_str_new(s+chlen, l-chlen);
7533  return cmd;
7534  }
7535  return Qnil;
7536 }
7537 
7538 /*
7539  * call-seq:
7540  * open(path [, mode [, perm]] [, opt]) -> io or nil
7541  * open(path [, mode [, perm]] [, opt]) {|io| block } -> obj
7542  *
7543  * Creates an IO object connected to the given stream, file, or subprocess.
7544  *
7545  * If +path+ does not start with a pipe character (<code>|</code>), treat it
7546  * as the name of a file to open using the specified mode (defaulting to
7547  * "r").
7548  *
7549  * The +mode+ is either a string or an integer. If it is an integer, it
7550  * must be bitwise-or of open(2) flags, such as File::RDWR or File::EXCL. If
7551  * it is a string, it is either "fmode", "fmode:ext_enc", or
7552  * "fmode:ext_enc:int_enc".
7553  *
7554  * See the documentation of IO.new for full documentation of the +mode+ string
7555  * directives.
7556  *
7557  * If a file is being created, its initial permissions may be set using the
7558  * +perm+ parameter. See File.new and the open(2) and chmod(2) man pages for
7559  * a description of permissions.
7560  *
7561  * If a block is specified, it will be invoked with the IO object as a
7562  * parameter, and the IO will be automatically closed when the block
7563  * terminates. The call returns the value of the block.
7564  *
7565  * If +path+ starts with a pipe character (<code>"|"</code>), a subprocess is
7566  * created, connected to the caller by a pair of pipes. The returned IO
7567  * object may be used to write to the standard input and read from the
7568  * standard output of this subprocess.
7569  *
7570  * If the command following the pipe is a single minus sign
7571  * (<code>"|-"</code>), Ruby forks, and this subprocess is connected to the
7572  * parent. If the command is not <code>"-"</code>, the subprocess runs the
7573  * command. Note that the command may be processed by shell if it contains
7574  * shell metacharacters.
7575  *
7576  * When the subprocess is Ruby (opened via <code>"|-"</code>), the +open+
7577  * call returns +nil+. If a block is associated with the open call, that
7578  * block will run twice --- once in the parent and once in the child.
7579  *
7580  * The block parameter will be an IO object in the parent and +nil+ in the
7581  * child. The parent's +IO+ object will be connected to the child's $stdin
7582  * and $stdout. The subprocess will be terminated at the end of the block.
7583  *
7584  * === Examples
7585  *
7586  * Reading from "testfile":
7587  *
7588  * open("testfile") do |f|
7589  * print f.gets
7590  * end
7591  *
7592  * Produces:
7593  *
7594  * This is line one
7595  *
7596  * Open a subprocess and read its output:
7597  *
7598  * cmd = open("|date")
7599  * print cmd.gets
7600  * cmd.close
7601  *
7602  * Produces:
7603  *
7604  * Wed Apr 9 08:56:31 CDT 2003
7605  *
7606  * Open a subprocess running the same Ruby program:
7607  *
7608  * f = open("|-", "w+")
7609  * if f.nil?
7610  * puts "in Child"
7611  * exit
7612  * else
7613  * puts "Got: #{f.gets}"
7614  * end
7615  *
7616  * Produces:
7617  *
7618  * Got: in Child
7619  *
7620  * Open a subprocess using a block to receive the IO object:
7621  *
7622  * open "|-" do |f|
7623  * if f then
7624  * # parent process
7625  * puts "Got: #{f.gets}"
7626  * else
7627  * # child process
7628  * puts "in Child"
7629  * end
7630  * end
7631  *
7632  * Produces:
7633  *
7634  * Got: in Child
7635  */
7636 
7637 static VALUE
7638 rb_f_open(int argc, VALUE *argv, VALUE _)
7639 {
7640  ID to_open = 0;
7641  int redirect = FALSE;
7642 
7643  if (argc >= 1) {
7644  CONST_ID(to_open, "to_open");
7645  if (rb_respond_to(argv[0], to_open)) {
7646  redirect = TRUE;
7647  }
7648  else {
7649  VALUE tmp = argv[0];
7650  FilePathValue(tmp);
7651  if (NIL_P(tmp)) {
7652  redirect = TRUE;
7653  }
7654  else {
7655  VALUE cmd = check_pipe_command(tmp);
7656  if (!NIL_P(cmd)) {
7657  argv[0] = cmd;
7658  return rb_io_s_popen(argc, argv, rb_cIO);
7659  }
7660  }
7661  }
7662  }
7663  if (redirect) {
7664  VALUE io = rb_funcallv_kw(argv[0], to_open, argc-1, argv+1, RB_PASS_CALLED_KEYWORDS);
7665 
7666  if (rb_block_given_p()) {
7667  return rb_ensure(rb_yield, io, io_close, io);
7668  }
7669  return io;
7670  }
7671  return rb_io_s_open(argc, argv, rb_cFile);
7672 }
7673 
7674 static VALUE rb_io_open_generic(VALUE, VALUE, int, int, const convconfig_t *, mode_t);
7675 
7676 static VALUE
7677 rb_io_open(VALUE io, VALUE filename, VALUE vmode, VALUE vperm, VALUE opt)
7678 {
7679  int oflags, fmode;
7680  convconfig_t convconfig;
7681  mode_t perm;
7682 
7683  rb_io_extract_modeenc(&vmode, &vperm, opt, &oflags, &fmode, &convconfig);
7684  perm = NIL_P(vperm) ? 0666 : NUM2MODET(vperm);
7685  return rb_io_open_generic(io, filename, oflags, fmode, &convconfig, perm);
7686 }
7687 
7688 static VALUE
7689 rb_io_open_generic(VALUE klass, VALUE filename, int oflags, int fmode,
7690  const convconfig_t *convconfig, mode_t perm)
7691 {
7692  VALUE cmd;
7693  if (klass == rb_cIO && !NIL_P(cmd = check_pipe_command(filename))) {
7694  return pipe_open_s(cmd, rb_io_oflags_modestr(oflags), fmode, convconfig);
7695  }
7696  else {
7697  return rb_file_open_generic(io_alloc(klass), filename,
7698  oflags, fmode, convconfig, perm);
7699  }
7700 }
7701 
7702 static VALUE
7703 io_reopen(VALUE io, VALUE nfile)
7704 {
7705  rb_io_t *fptr, *orig;
7706  int fd, fd2;
7707  off_t pos = 0;
7708 
7709  nfile = rb_io_get_io(nfile);
7710  GetOpenFile(io, fptr);
7711  GetOpenFile(nfile, orig);
7712 
7713  if (fptr == orig) return io;
7714  if (IS_PREP_STDIO(fptr)) {
7715  if ((fptr->stdio_file == stdin && !(orig->mode & FMODE_READABLE)) ||
7716  (fptr->stdio_file == stdout && !(orig->mode & FMODE_WRITABLE)) ||
7717  (fptr->stdio_file == stderr && !(orig->mode & FMODE_WRITABLE))) {
7719  "%s can't change access mode from \"%s\" to \"%s\"",
7720  PREP_STDIO_NAME(fptr), rb_io_fmode_modestr(fptr->mode),
7721  rb_io_fmode_modestr(orig->mode));
7722  }
7723  }
7724  if (fptr->mode & FMODE_WRITABLE) {
7725  if (io_fflush(fptr) < 0)
7726  rb_sys_fail_on_write(fptr);
7727  }
7728  else {
7729  flush_before_seek(fptr);
7730  }
7731  if (orig->mode & FMODE_READABLE) {
7732  pos = io_tell(orig);
7733  }
7734  if (orig->mode & FMODE_WRITABLE) {
7735  if (io_fflush(orig) < 0)
7736  rb_sys_fail_on_write(fptr);
7737  }
7738 
7739  /* copy rb_io_t structure */
7740  fptr->mode = orig->mode | (fptr->mode & FMODE_PREP);
7741  fptr->pid = orig->pid;
7742  fptr->lineno = orig->lineno;
7743  if (RTEST(orig->pathv)) fptr->pathv = orig->pathv;
7744  else if (!IS_PREP_STDIO(fptr)) fptr->pathv = Qnil;
7745  fptr_copy_finalizer(fptr, orig);
7746 
7747  fd = fptr->fd;
7748  fd2 = orig->fd;
7749  if (fd != fd2) {
7750  if (IS_PREP_STDIO(fptr) || fd <= 2 || !fptr->stdio_file) {
7751  /* need to keep FILE objects of stdin, stdout and stderr */
7752  if (rb_cloexec_dup2(fd2, fd) < 0)
7753  rb_sys_fail_path(orig->pathv);
7754  rb_update_max_fd(fd);
7755  }
7756  else {
7757  fclose(fptr->stdio_file);
7758  fptr->stdio_file = 0;
7759  fptr->fd = -1;
7760  if (rb_cloexec_dup2(fd2, fd) < 0)
7761  rb_sys_fail_path(orig->pathv);
7762  rb_update_max_fd(fd);
7763  fptr->fd = fd;
7764  }
7765  rb_thread_fd_close(fd);
7766  if ((orig->mode & FMODE_READABLE) && pos >= 0) {
7767  if (io_seek(fptr, pos, SEEK_SET) < 0 && errno) {
7768  rb_sys_fail_path(fptr->pathv);
7769  }
7770  if (io_seek(orig, pos, SEEK_SET) < 0 && errno) {
7771  rb_sys_fail_path(orig->pathv);
7772  }
7773  }
7774  }
7775 
7776  if (fptr->mode & FMODE_BINMODE) {
7777  rb_io_binmode(io);
7778  }
7779 
7780  RBASIC_SET_CLASS(io, rb_obj_class(nfile));
7781  return io;
7782 }
7783 
7784 #ifdef _WIN32
7785 int rb_freopen(VALUE fname, const char *mode, FILE *fp);
7786 #else
7787 static int
7788 rb_freopen(VALUE fname, const char *mode, FILE *fp)
7789 {
7790  if (!freopen(RSTRING_PTR(fname), mode, fp)) {
7791  RB_GC_GUARD(fname);
7792  return errno;
7793  }
7794  return 0;
7795 }
7796 #endif
7797 
7798 /*
7799  * call-seq:
7800  * ios.reopen(other_IO) -> ios
7801  * ios.reopen(path, mode [, opt]) -> ios
7802  *
7803  * Reassociates <em>ios</em> with the I/O stream given in
7804  * <i>other_IO</i> or to a new stream opened on <i>path</i>. This may
7805  * dynamically change the actual class of this stream.
7806  * The +mode+ and +opt+ parameters accept the same values as IO.open.
7807  *
7808  * f1 = File.new("testfile")
7809  * f2 = File.new("testfile")
7810  * f2.readlines[0] #=> "This is line one\n"
7811  * f2.reopen(f1) #=> #<File:testfile>
7812  * f2.readlines[0] #=> "This is line one\n"
7813  */
7814 
7815 static VALUE
7816 rb_io_reopen(int argc, VALUE *argv, VALUE file)
7817 {
7818  VALUE fname, nmode, opt;
7819  int oflags;
7820  rb_io_t *fptr;
7821 
7822  if (rb_scan_args(argc, argv, "11:", &fname, &nmode, &opt) == 1) {
7823  VALUE tmp = rb_io_check_io(fname);
7824  if (!NIL_P(tmp)) {
7825  return io_reopen(file, tmp);
7826  }
7827  }
7828 
7829  FilePathValue(fname);
7830  rb_io_taint_check(file);
7831  fptr = RFILE(file)->fptr;
7832  if (!fptr) {
7833  fptr = RFILE(file)->fptr = ZALLOC(rb_io_t);
7834  }
7835 
7836  if (!NIL_P(nmode) || !NIL_P(opt)) {
7837  int fmode;
7838  convconfig_t convconfig;
7839 
7840  rb_io_extract_modeenc(&nmode, 0, opt, &oflags, &fmode, &convconfig);
7841  if (IS_PREP_STDIO(fptr) &&
7842  ((fptr->mode & FMODE_READWRITE) & (fmode & FMODE_READWRITE)) !=
7843  (fptr->mode & FMODE_READWRITE)) {
7845  "%s can't change access mode from \"%s\" to \"%s\"",
7846  PREP_STDIO_NAME(fptr), rb_io_fmode_modestr(fptr->mode),
7847  rb_io_fmode_modestr(fmode));
7848  }
7849  fptr->mode = fmode;
7850  fptr->encs = convconfig;
7851  }
7852  else {
7853  oflags = rb_io_fmode_oflags(fptr->mode);
7854  }
7855 
7856  fptr->pathv = fname;
7857  if (fptr->fd < 0) {
7858  fptr->fd = rb_sysopen(fptr->pathv, oflags, 0666);
7859  fptr->stdio_file = 0;
7860  return file;
7861  }
7862 
7863  if (fptr->mode & FMODE_WRITABLE) {
7864  if (io_fflush(fptr) < 0)
7865  rb_sys_fail_on_write(fptr);
7866  }
7867  fptr->rbuf.off = fptr->rbuf.len = 0;
7868 
7869  if (fptr->stdio_file) {
7870  int e = rb_freopen(rb_str_encode_ospath(fptr->pathv),
7871  rb_io_oflags_modestr(oflags),
7872  fptr->stdio_file);
7873  if (e) rb_syserr_fail_path(e, fptr->pathv);
7874  fptr->fd = fileno(fptr->stdio_file);
7875  rb_fd_fix_cloexec(fptr->fd);
7876 #ifdef USE_SETVBUF
7877  if (setvbuf(fptr->stdio_file, NULL, _IOFBF, 0) != 0)
7878  rb_warn("setvbuf() can't be honoured for %"PRIsVALUE, fptr->pathv);
7879 #endif
7880  if (fptr->stdio_file == stderr) {
7881  if (setvbuf(fptr->stdio_file, NULL, _IONBF, BUFSIZ) != 0)
7882  rb_warn("setvbuf() can't be honoured for %"PRIsVALUE, fptr->pathv);
7883  }
7884  else if (fptr->stdio_file == stdout && isatty(fptr->fd)) {
7885  if (setvbuf(fptr->stdio_file, NULL, _IOLBF, BUFSIZ) != 0)
7886  rb_warn("setvbuf() can't be honoured for %"PRIsVALUE, fptr->pathv);
7887  }
7888  }
7889  else {
7890  int tmpfd = rb_sysopen(fptr->pathv, oflags, 0666);
7891  int err = 0;
7892  if (rb_cloexec_dup2(tmpfd, fptr->fd) < 0)
7893  err = errno;
7894  (void)close(tmpfd);
7895  if (err) {
7896  rb_syserr_fail_path(err, fptr->pathv);
7897  }
7898  }
7899 
7900  return file;
7901 }
7902 
7903 /* :nodoc: */
7904 static VALUE
7905 rb_io_init_copy(VALUE dest, VALUE io)
7906 {
7907  rb_io_t *fptr, *orig;
7908  int fd;
7909  VALUE write_io;
7910  off_t pos;
7911 
7912  io = rb_io_get_io(io);
7913  if (!OBJ_INIT_COPY(dest, io)) return dest;
7914  GetOpenFile(io, orig);
7915  MakeOpenFile(dest, fptr);
7916 
7917  rb_io_flush(io);
7918 
7919  /* copy rb_io_t structure */
7920  fptr->mode = orig->mode & ~FMODE_PREP;
7921  fptr->encs = orig->encs;
7922  fptr->pid = orig->pid;
7923  fptr->lineno = orig->lineno;
7924  if (!NIL_P(orig->pathv)) fptr->pathv = orig->pathv;
7925  fptr_copy_finalizer(fptr, orig);
7926 
7927  fd = ruby_dup(orig->fd);
7928  fptr->fd = fd;
7929  pos = io_tell(orig);
7930  if (0 <= pos)
7931  io_seek(fptr, pos, SEEK_SET);
7932  if (fptr->mode & FMODE_BINMODE) {
7933  rb_io_binmode(dest);
7934  }
7935 
7936  write_io = GetWriteIO(io);
7937  if (io != write_io) {
7938  write_io = rb_obj_dup(write_io);
7939  fptr->tied_io_for_writing = write_io;
7940  rb_ivar_set(dest, rb_intern("@tied_io_for_writing"), write_io);
7941  }
7942 
7943  return dest;
7944 }
7945 
7946 /*
7947  * call-seq:
7948  * ios.printf(format_string [, obj, ...]) -> nil
7949  *
7950  * Formats and writes to <em>ios</em>, converting parameters under
7951  * control of the format string. See Kernel#sprintf for details.
7952  */
7953 
7954 VALUE
7955 rb_io_printf(int argc, const VALUE *argv, VALUE out)
7956 {
7957  rb_io_write(out, rb_f_sprintf(argc, argv));
7958  return Qnil;
7959 }
7960 
7961 /*
7962  * call-seq:
7963  * printf(io, string [, obj ... ]) -> nil
7964  * printf(string [, obj ... ]) -> nil
7965  *
7966  * Equivalent to:
7967  * io.write(sprintf(string, obj, ...))
7968  * or
7969  * $stdout.write(sprintf(string, obj, ...))
7970  */
7971 
7972 static VALUE
7973 rb_f_printf(int argc, VALUE *argv, VALUE _)
7974 {
7975  VALUE out;
7976 
7977  if (argc == 0) return Qnil;
7978  if (RB_TYPE_P(argv[0], T_STRING)) {
7979  out = rb_ractor_stdout();
7980  }
7981  else {
7982  out = argv[0];
7983  argv++;
7984  argc--;
7985  }
7986  rb_io_write(out, rb_f_sprintf(argc, argv));
7987 
7988  return Qnil;
7989 }
7990 
7991 static void
7992 deprecated_str_setter(VALUE val, ID id, VALUE *var)
7993 {
7994  rb_str_setter(val, id, &val);
7995  if (!NIL_P(val)) {
7996  rb_warn_deprecated("`%s'", NULL, rb_id2name(id));
7997  }
7998  *var = val;
7999 }
8000 
8001 /*
8002  * call-seq:
8003  * ios.print -> nil
8004  * ios.print(obj, ...) -> nil
8005  *
8006  * Writes the given object(s) to <em>ios</em>. Returns +nil+.
8007  *
8008  * The stream must be opened for writing.
8009  * Each given object that isn't a string will be converted by calling
8010  * its <code>to_s</code> method.
8011  * When called without arguments, prints the contents of <code>$_</code>.
8012  *
8013  * If the output field separator (<code>$,</code>) is not +nil+,
8014  * it is inserted between objects.
8015  * If the output record separator (<code>$\</code>) is not +nil+,
8016  * it is appended to the output.
8017  *
8018  * $stdout.print("This is ", 100, " percent.\n")
8019  *
8020  * <em>produces:</em>
8021  *
8022  * This is 100 percent.
8023  */
8024 
8025 VALUE
8026 rb_io_print(int argc, const VALUE *argv, VALUE out)
8027 {
8028  int i;
8029  VALUE line;
8030 
8031  /* if no argument given, print `$_' */
8032  if (argc == 0) {
8033  argc = 1;
8034  line = rb_lastline_get();
8035  argv = &line;
8036  }
8037  if (argc > 1 && !NIL_P(rb_output_fs)) {
8038  rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "$, is set to non-nil value");
8039  }
8040  for (i=0; i<argc; i++) {
8041  if (!NIL_P(rb_output_fs) && i>0) {
8042  rb_io_write(out, rb_output_fs);
8043  }
8044  rb_io_write(out, argv[i]);
8045  }
8046  if (argc > 0 && !NIL_P(rb_output_rs)) {
8047  rb_io_write(out, rb_output_rs);
8048  }
8049 
8050  return Qnil;
8051 }
8052 
8053 /*
8054  * call-seq:
8055  * print(obj, ...) -> nil
8056  *
8057  * Prints each object in turn to <code>$stdout</code>. If the output
8058  * field separator (<code>$,</code>) is not +nil+, its
8059  * contents will appear between each field. If the output record
8060  * separator (<code>$\</code>) is not +nil+, it will be
8061  * appended to the output. If no arguments are given, prints
8062  * <code>$_</code>. Objects that aren't strings will be converted by
8063  * calling their <code>to_s</code> method.
8064  *
8065  * print "cat", [1,2,3], 99, "\n"
8066  * $, = ", "
8067  * $\ = "\n"
8068  * print "cat", [1,2,3], 99
8069  *
8070  * <em>produces:</em>
8071  *
8072  * cat12399
8073  * cat, 1, 2, 3, 99
8074  */
8075 
8076 static VALUE
8077 rb_f_print(int argc, const VALUE *argv, VALUE _)
8078 {
8079  rb_io_print(argc, argv, rb_ractor_stdout());
8080  return Qnil;
8081 }
8082 
8083 /*
8084  * call-seq:
8085  * ios.putc(obj) -> obj
8086  *
8087  * If <i>obj</i> is Numeric, write the character whose code is the
8088  * least-significant byte of <i>obj</i>. If <i>obj</i> is String,
8089  * write the first character of <i>obj</i> to <em>ios</em>. Otherwise,
8090  * raise TypeError.
8091  *
8092  * $stdout.putc "A"
8093  * $stdout.putc 65
8094  *
8095  * <em>produces:</em>
8096  *
8097  * AA
8098  */
8099 
8100 static VALUE
8101 rb_io_putc(VALUE io, VALUE ch)
8102 {
8103  VALUE str;
8104  if (RB_TYPE_P(ch, T_STRING)) {
8105  str = rb_str_substr(ch, 0, 1);
8106  }
8107  else {
8108  char c = NUM2CHR(ch);
8109  str = rb_str_new(&c, 1);
8110  }
8111  rb_io_write(io, str);
8112  return ch;
8113 }
8114 
8115 #define forward(obj, id, argc, argv) \
8116  rb_funcallv_kw(obj, id, argc, argv, RB_PASS_CALLED_KEYWORDS)
8117 #define forward_public(obj, id, argc, argv) \
8118  rb_funcallv_public_kw(obj, id, argc, argv, RB_PASS_CALLED_KEYWORDS)
8119 #define forward_current(id, argc, argv) \
8120  forward_public(ARGF.current_file, id, argc, argv)
8121 
8122 /*
8123  * call-seq:
8124  * putc(int) -> int
8125  *
8126  * Equivalent to:
8127  *
8128  * $stdout.putc(int)
8129  *
8130  * Refer to the documentation for IO#putc for important information regarding
8131  * multi-byte characters.
8132  */
8133 
8134 static VALUE
8135 rb_f_putc(VALUE recv, VALUE ch)
8136 {
8137  VALUE r_stdout = rb_ractor_stdout();
8138  if (recv == r_stdout) {
8139  return rb_io_putc(recv, ch);
8140  }
8141  return forward(r_stdout, rb_intern("putc"), 1, &ch);
8142 }
8143 
8144 
8145 int
8146 rb_str_end_with_asciichar(VALUE str, int c)
8147 {
8148  long len = RSTRING_LEN(str);
8149  const char *ptr = RSTRING_PTR(str);
8151  int n;
8152 
8153  if (len == 0) return 0;
8154  if ((n = rb_enc_mbminlen(enc)) == 1) {
8155  return ptr[len - 1] == c;
8156  }
8157  return rb_enc_ascget(ptr + ((len - 1) / n) * n, ptr + len, &n, enc) == c;
8158 }
8159 
8160 static VALUE
8161 io_puts_ary(VALUE ary, VALUE out, int recur)
8162 {
8163  VALUE tmp;
8164  long i;
8165 
8166  if (recur) {
8167  tmp = rb_str_new2("[...]");
8168  rb_io_puts(1, &tmp, out);
8169  return Qtrue;
8170  }
8171  ary = rb_check_array_type(ary);
8172  if (NIL_P(ary)) return Qfalse;
8173  for (i=0; i<RARRAY_LEN(ary); i++) {
8174  tmp = RARRAY_AREF(ary, i);
8175  rb_io_puts(1, &tmp, out);
8176  }
8177  return Qtrue;
8178 }
8179 
8180 /*
8181  * call-seq:
8182  * ios.puts(obj, ...) -> nil
8183  *
8184  * Writes the given object(s) to <em>ios</em>.
8185  * Writes a newline after any that do not already end
8186  * with a newline sequence. Returns +nil+.
8187  *
8188  * The stream must be opened for writing.
8189  * If called with an array argument, writes each element on a new line.
8190  * Each given object that isn't a string or array will be converted
8191  * by calling its +to_s+ method.
8192  * If called without arguments, outputs a single newline.
8193  *
8194  * $stdout.puts("this", "is", ["a", "test"])
8195  *
8196  * <em>produces:</em>
8197  *
8198  * this
8199  * is
8200  * a
8201  * test
8202  *
8203  * Note that +puts+ always uses newlines and is not affected
8204  * by the output record separator (<code>$\</code>).
8205  */
8206 
8207 VALUE
8208 rb_io_puts(int argc, const VALUE *argv, VALUE out)
8209 {
8210  int i, n;
8211  VALUE line, args[2];
8212 
8213  /* if no argument given, print newline. */
8214  if (argc == 0) {
8215  rb_io_write(out, rb_default_rs);
8216  return Qnil;
8217  }
8218  for (i=0; i<argc; i++) {
8219  if (RB_TYPE_P(argv[i], T_STRING)) {
8220  line = argv[i];
8221  goto string;
8222  }
8223  if (rb_exec_recursive(io_puts_ary, argv[i], out)) {
8224  continue;
8225  }
8226  line = rb_obj_as_string(argv[i]);
8227  string:
8228  n = 0;
8229  args[n++] = line;
8230  if (RSTRING_LEN(line) == 0 ||
8231  !rb_str_end_with_asciichar(line, '\n')) {
8232  args[n++] = rb_default_rs;
8233  }
8234  rb_io_writev(out, n, args);
8235  }
8236 
8237  return Qnil;
8238 }
8239 
8240 /*
8241  * call-seq:
8242  * puts(obj, ...) -> nil
8243  *
8244  * Equivalent to
8245  *
8246  * $stdout.puts(obj, ...)
8247  */
8248 
8249 static VALUE
8250 rb_f_puts(int argc, VALUE *argv, VALUE recv)
8251 {
8252  VALUE r_stdout = rb_ractor_stdout();
8253  if (recv == r_stdout) {
8254  return rb_io_puts(argc, argv, recv);
8255  }
8256  return forward(r_stdout, rb_intern("puts"), argc, argv);
8257 }
8258 
8259 static VALUE
8260 rb_p_write(VALUE str)
8261 {
8262  VALUE args[2];
8263  args[0] = str;
8264  args[1] = rb_default_rs;
8265  VALUE r_stdout = rb_ractor_stdout();
8266  if (RB_TYPE_P(r_stdout, T_FILE) &&
8267  rb_method_basic_definition_p(CLASS_OF(r_stdout), id_write)) {
8268  io_writev(2, args, r_stdout);
8269  }
8270  else {
8271  rb_io_writev(r_stdout, 2, args);
8272  }
8273  return Qnil;
8274 }
8275 
8276 void
8277 rb_p(VALUE obj) /* for debug print within C code */
8278 {
8279  rb_p_write(rb_obj_as_string(rb_inspect(obj)));
8280 }
8281 
8282 static VALUE
8283 rb_p_result(int argc, const VALUE *argv)
8284 {
8285  VALUE ret = Qnil;
8286 
8287  if (argc == 1) {
8288  ret = argv[0];
8289  }
8290  else if (argc > 1) {
8291  ret = rb_ary_new4(argc, argv);
8292  }
8293  VALUE r_stdout = rb_ractor_stdout();
8294  if (RB_TYPE_P(r_stdout, T_FILE)) {
8295  rb_io_flush(r_stdout);
8296  }
8297  return ret;
8298 }
8299 
8300 /*
8301  * call-seq:
8302  * p(obj) -> obj
8303  * p(obj1, obj2, ...) -> [obj, ...]
8304  * p() -> nil
8305  *
8306  * For each object, directly writes _obj_.+inspect+ followed by a
8307  * newline to the program's standard output.
8308  *
8309  * S = Struct.new(:name, :state)
8310  * s = S['dave', 'TX']
8311  * p s
8312  *
8313  * <em>produces:</em>
8314  *
8315  * #<S name="dave", state="TX">
8316  */
8317 
8318 static VALUE
8319 rb_f_p(int argc, VALUE *argv, VALUE self)
8320 {
8321  int i;
8322  for (i=0; i<argc; i++) {
8323  VALUE inspected = rb_obj_as_string(rb_inspect(argv[i]));
8324  rb_uninterruptible(rb_p_write, inspected);
8325  }
8326  return rb_p_result(argc, argv);
8327 }
8328 
8329 /*
8330  * call-seq:
8331  * obj.display(port=$>) -> nil
8332  *
8333  * Prints <i>obj</i> on the given port (default <code>$></code>).
8334  * Equivalent to:
8335  *
8336  * def display(port=$>)
8337  * port.write self
8338  * nil
8339  * end
8340  *
8341  * For example:
8342  *
8343  * 1.display
8344  * "cat".display
8345  * [ 4, 5, 6 ].display
8346  * puts
8347  *
8348  * <em>produces:</em>
8349  *
8350  * 1cat[4, 5, 6]
8351  */
8352 
8353 static VALUE
8354 rb_obj_display(int argc, VALUE *argv, VALUE self)
8355 {
8356  VALUE out;
8357 
8358  out = (!rb_check_arity(argc, 0, 1) ? rb_ractor_stdout() : argv[0]);
8359  rb_io_write(out, self);
8360 
8361  return Qnil;
8362 }
8363 
8364 static int
8365 rb_stderr_to_original_p(VALUE err)
8366 {
8367  return (err == orig_stderr || RFILE(orig_stderr)->fptr->fd < 0);
8368 }
8369 
8370 void
8371 rb_write_error2(const char *mesg, long len)
8372 {
8373  VALUE out = rb_ractor_stderr();
8374  if (rb_stderr_to_original_p(out)) {
8375 #ifdef _WIN32
8376  if (isatty(fileno(stderr))) {
8377  if (rb_w32_write_console(rb_str_new(mesg, len), fileno(stderr)) > 0) return;
8378  }
8379 #endif
8380  if (fwrite(mesg, sizeof(char), (size_t)len, stderr) < (size_t)len) {
8381  /* failed to write to stderr, what can we do? */
8382  return;
8383  }
8384  }
8385  else {
8386  rb_io_write(out, rb_str_new(mesg, len));
8387  }
8388 }
8389 
8390 void
8391 rb_write_error(const char *mesg)
8392 {
8393  rb_write_error2(mesg, strlen(mesg));
8394 }
8395 
8396 void
8397 rb_write_error_str(VALUE mesg)
8398 {
8399  VALUE out = rb_ractor_stderr();
8400  /* a stopgap measure for the time being */
8401  if (rb_stderr_to_original_p(out)) {
8402  size_t len = (size_t)RSTRING_LEN(mesg);
8403 #ifdef _WIN32
8404  if (isatty(fileno(stderr))) {
8405  if (rb_w32_write_console(mesg, fileno(stderr)) > 0) return;
8406  }
8407 #endif
8408  if (fwrite(RSTRING_PTR(mesg), sizeof(char), len, stderr) < len) {
8409  RB_GC_GUARD(mesg);
8410  return;
8411  }
8412  }
8413  else {
8414  /* may unlock GVL, and */
8415  rb_io_write(out, mesg);
8416  }
8417 }
8418 
8419 int
8420 rb_stderr_tty_p(void)
8421 {
8422  if (rb_stderr_to_original_p(rb_ractor_stderr()))
8423  return isatty(fileno(stderr));
8424  return 0;
8425 }
8426 
8427 static void
8428 must_respond_to(ID mid, VALUE val, ID id)
8429 {
8430  if (!rb_respond_to(val, mid)) {
8431  rb_raise(rb_eTypeError, "%"PRIsVALUE" must have %"PRIsVALUE" method, %"PRIsVALUE" given",
8432  rb_id2str(id), rb_id2str(mid),
8433  rb_obj_class(val));
8434  }
8435 }
8436 
8437 static void
8438 stdin_setter(VALUE val, ID id, VALUE *ptr)
8439 {
8440  rb_ractor_stdin_set(val);
8441 }
8442 
8443 static VALUE
8444 stdin_getter(ID id, VALUE *ptr)
8445 {
8446  return rb_ractor_stdin();
8447 }
8448 
8449 static void
8450 stdout_setter(VALUE val, ID id, VALUE *ptr)
8451 {
8452  must_respond_to(id_write, val, id);
8453  rb_ractor_stdout_set(val);
8454 }
8455 
8456 static VALUE
8457 stdout_getter(ID id, VALUE *ptr)
8458 {
8459  return rb_ractor_stdout();
8460 }
8461 
8462 static void
8463 stderr_setter(VALUE val, ID id, VALUE *ptr)
8464 {
8465  must_respond_to(id_write, val, id);
8466  rb_ractor_stderr_set(val);
8467 }
8468 
8469 static VALUE
8470 stderr_getter(ID id, VALUE *ptr)
8471 {
8472  return rb_ractor_stderr();
8473 }
8474 
8475 static VALUE
8476 prep_io(int fd, int fmode, VALUE klass, const char *path)
8477 {
8478  rb_io_t *fp;
8479  VALUE io = io_alloc(klass);
8480 
8481  MakeOpenFile(io, fp);
8482  fp->self = io;
8483  fp->fd = fd;
8484  fp->mode = fmode;
8485  if (!io_check_tty(fp)) {
8486 #ifdef __CYGWIN__
8487  fp->mode |= FMODE_BINMODE;
8488  setmode(fd, O_BINARY);
8489 #endif
8490  }
8491  if (path) fp->pathv = rb_obj_freeze(rb_str_new_cstr(path));
8492  rb_update_max_fd(fd);
8493 
8494  return io;
8495 }
8496 
8497 VALUE
8498 rb_io_fdopen(int fd, int oflags, const char *path)
8499 {
8500  VALUE klass = rb_cIO;
8501 
8502  if (path && strcmp(path, "-")) klass = rb_cFile;
8503  return prep_io(fd, rb_io_oflags_fmode(oflags), klass, path);
8504 }
8505 
8506 static VALUE
8507 prep_stdio(FILE *f, int fmode, VALUE klass, const char *path)
8508 {
8509  rb_io_t *fptr;
8510  VALUE io = prep_io(fileno(f), fmode|FMODE_PREP|DEFAULT_TEXTMODE, klass, path);
8511 
8512  GetOpenFile(io, fptr);
8514 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
8515  fptr->encs.ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
8516  if (fmode & FMODE_READABLE) {
8518  }
8519 #endif
8520  fptr->stdio_file = f;
8521 
8522  return io;
8523 }
8524 
8525 VALUE
8526 rb_io_prep_stdin(void)
8527 {
8528  return prep_stdio(stdin, FMODE_READABLE, rb_cIO, "<STDIN>");
8529 }
8530 
8531 VALUE
8532 rb_io_prep_stdout(void)
8533 {
8534  return prep_stdio(stdout, FMODE_WRITABLE|FMODE_SIGNAL_ON_EPIPE, rb_cIO, "<STDOUT>");
8535 }
8536 
8537 VALUE
8538 rb_io_prep_stderr(void)
8539 {
8540  return prep_stdio(stderr, FMODE_WRITABLE|FMODE_SYNC, rb_cIO, "<STDERR>");
8541 }
8542 
8543 FILE *
8545 {
8546  if (!fptr->stdio_file) {
8547  int oflags = rb_io_fmode_oflags(fptr->mode) & ~O_EXCL;
8548  fptr->stdio_file = rb_fdopen(fptr->fd, rb_io_oflags_modestr(oflags));
8549  }
8550  return fptr->stdio_file;
8551 }
8552 
8553 static inline void
8554 rb_io_buffer_init(rb_io_buffer_t *buf)
8555 {
8556  buf->ptr = NULL;
8557  buf->off = 0;
8558  buf->len = 0;
8559  buf->capa = 0;
8560 }
8561 
8562 static inline rb_io_t *
8563 rb_io_fptr_new(void)
8564 {
8565  rb_io_t *fp = ALLOC(rb_io_t);
8566  fp->self = Qnil;
8567  fp->fd = -1;
8568  fp->stdio_file = NULL;
8569  fp->mode = 0;
8570  fp->pid = 0;
8571  fp->lineno = 0;
8572  fp->pathv = Qnil;
8573  fp->finalize = 0;
8574  rb_io_buffer_init(&fp->wbuf);
8575  rb_io_buffer_init(&fp->rbuf);
8576  rb_io_buffer_init(&fp->cbuf);
8577  fp->readconv = NULL;
8578  fp->writeconv = NULL;
8580  fp->writeconv_pre_ecflags = 0;
8581  fp->writeconv_pre_ecopts = Qnil;
8582  fp->writeconv_initialized = 0;
8583  fp->tied_io_for_writing = 0;
8584  fp->encs.enc = NULL;
8585  fp->encs.enc2 = NULL;
8586  fp->encs.ecflags = 0;
8587  fp->encs.ecopts = Qnil;
8588  fp->write_lock = 0;
8589  return fp;
8590 }
8591 
8592 rb_io_t *
8593 rb_io_make_open_file(VALUE obj)
8594 {
8595  rb_io_t *fp = 0;
8596 
8597  Check_Type(obj, T_FILE);
8598  if (RFILE(obj)->fptr) {
8599  rb_io_close(obj);
8600  rb_io_fptr_finalize(RFILE(obj)->fptr);
8601  RFILE(obj)->fptr = 0;
8602  }
8603  fp = rb_io_fptr_new();
8604  fp->self = obj;
8605  RFILE(obj)->fptr = fp;
8606  return fp;
8607 }
8608 
8609 /*
8610  * call-seq:
8611  * IO.new(fd [, mode] [, opt]) -> io
8612  *
8613  * Returns a new IO object (a stream) for the given integer file descriptor
8614  * +fd+ and +mode+ string. +opt+ may be used to specify parts of +mode+ in a
8615  * more readable fashion. See also IO.sysopen and IO.for_fd.
8616  *
8617  * IO.new is called by various File and IO opening methods such as IO::open,
8618  * Kernel#open, and File::open.
8619  *
8620  * === Open Mode
8621  *
8622  * When +mode+ is an integer it must be combination of the modes defined in
8623  * File::Constants (+File::RDONLY+, <code>File::WRONLY|File::CREAT</code>).
8624  * See the open(2) man page for more information.
8625  *
8626  * When +mode+ is a string it must be in one of the following forms:
8627  *
8628  * fmode
8629  * fmode ":" ext_enc
8630  * fmode ":" ext_enc ":" int_enc
8631  * fmode ":" "BOM|UTF-*"
8632  *
8633  * +fmode+ is an IO open mode string, +ext_enc+ is the external encoding for
8634  * the IO and +int_enc+ is the internal encoding.
8635  *
8636  * ==== IO Open Mode
8637  *
8638  * Ruby allows the following open modes:
8639  *
8640  * "r" Read-only, starts at beginning of file (default mode).
8641  *
8642  * "r+" Read-write, starts at beginning of file.
8643  *
8644  * "w" Write-only, truncates existing file
8645  * to zero length or creates a new file for writing.
8646  *
8647  * "w+" Read-write, truncates existing file to zero length
8648  * or creates a new file for reading and writing.
8649  *
8650  * "a" Write-only, each write call appends data at end of file.
8651  * Creates a new file for writing if file does not exist.
8652  *
8653  * "a+" Read-write, each write call appends data at end of file.
8654  * Creates a new file for reading and writing if file does
8655  * not exist.
8656  *
8657  * The following modes must be used separately, and along with one or more of
8658  * the modes seen above.
8659  *
8660  * "b" Binary file mode
8661  * Suppresses EOL <-> CRLF conversion on Windows. And
8662  * sets external encoding to ASCII-8BIT unless explicitly
8663  * specified.
8664  *
8665  * "t" Text file mode
8666  *
8667  * The exclusive access mode ("x") can be used together with "w" to ensure
8668  * the file is created. Errno::EEXIST is raised when it already exists.
8669  * It may not be supported with all kinds of streams (e.g. pipes).
8670  *
8671  * When the open mode of original IO is read only, the mode cannot be
8672  * changed to be writable. Similarly, the open mode cannot be changed from
8673  * write only to readable.
8674  *
8675  * When such a change is attempted the error is raised in different locations
8676  * according to the platform.
8677  *
8678  * === IO Encoding
8679  *
8680  * When +ext_enc+ is specified, strings read will be tagged by the encoding
8681  * when reading, and strings output will be converted to the specified
8682  * encoding when writing.
8683  *
8684  * When +ext_enc+ and +int_enc+ are specified read strings will be converted
8685  * from +ext_enc+ to +int_enc+ upon input, and written strings will be
8686  * converted from +int_enc+ to +ext_enc+ upon output. See Encoding for
8687  * further details of transcoding on input and output.
8688  *
8689  * If "BOM|UTF-8", "BOM|UTF-16LE" or "BOM|UTF16-BE" are used, Ruby checks for
8690  * a Unicode BOM in the input document to help determine the encoding. For
8691  * UTF-16 encodings the file open mode must be binary. When present, the BOM
8692  * is stripped and the external encoding from the BOM is used. When the BOM
8693  * is missing the given Unicode encoding is used as +ext_enc+. (The BOM-set
8694  * encoding option is case insensitive, so "bom|utf-8" is also valid.)
8695  *
8696  * === Options
8697  *
8698  * +opt+ can be used instead of +mode+ for improved readability. The
8699  * following keys are supported:
8700  *
8701  * :mode ::
8702  * Same as +mode+ parameter
8703  *
8704  * :flags ::
8705  * Specifies file open flags as integer.
8706  * If +mode+ parameter is given, this parameter will be bitwise-ORed.
8707  *
8708  * :\external_encoding ::
8709  * External encoding for the IO.
8710  *
8711  * :\internal_encoding ::
8712  * Internal encoding for the IO. "-" is a synonym for the default internal
8713  * encoding.
8714  *
8715  * If the value is +nil+ no conversion occurs.
8716  *
8717  * :encoding ::
8718  * Specifies external and internal encodings as "extern:intern".
8719  *
8720  * :textmode ::
8721  * If the value is truth value, same as "t" in argument +mode+.
8722  *
8723  * :binmode ::
8724  * If the value is truth value, same as "b" in argument +mode+.
8725  *
8726  * :autoclose ::
8727  * If the value is +false+, the +fd+ will be kept open after this IO
8728  * instance gets finalized.
8729  *
8730  * Also, +opt+ can have same keys in String#encode for controlling conversion
8731  * between the external encoding and the internal encoding.
8732  *
8733  * === Example 1
8734  *
8735  * fd = IO.sysopen("/dev/tty", "w")
8736  * a = IO.new(fd,"w")
8737  * $stderr.puts "Hello"
8738  * a.puts "World"
8739  *
8740  * Produces:
8741  *
8742  * Hello
8743  * World
8744  *
8745  * === Example 2
8746  *
8747  * require 'fcntl'
8748  *
8749  * fd = STDERR.fcntl(Fcntl::F_DUPFD)
8750  * io = IO.new(fd, mode: 'w:UTF-16LE', cr_newline: true)
8751  * io.puts "Hello, World!"
8752  *
8753  * fd = STDERR.fcntl(Fcntl::F_DUPFD)
8754  * io = IO.new(fd, mode: 'w', cr_newline: true,
8755  * external_encoding: Encoding::UTF_16LE)
8756  * io.puts "Hello, World!"
8757  *
8758  * Both of above print "Hello, World!" in UTF-16LE to standard error output
8759  * with converting EOL generated by #puts to CR.
8760  */
8761 
8762 static VALUE
8763 rb_io_initialize(int argc, VALUE *argv, VALUE io)
8764 {
8765  VALUE fnum, vmode;
8766  rb_io_t *fp;
8767  int fd, fmode, oflags = O_RDONLY;
8768  convconfig_t convconfig;
8769  VALUE opt;
8770 #if defined(HAVE_FCNTL) && defined(F_GETFL)
8771  int ofmode;
8772 #else
8773  struct stat st;
8774 #endif
8775 
8776 
8777  argc = rb_scan_args(argc, argv, "11:", &fnum, &vmode, &opt);
8778  rb_io_extract_modeenc(&vmode, 0, opt, &oflags, &fmode, &convconfig);
8779 
8780  fd = NUM2INT(fnum);
8781  if (rb_reserved_fd_p(fd)) {
8782  rb_raise(rb_eArgError, "The given fd is not accessible because RubyVM reserves it");
8783  }
8784 #if defined(HAVE_FCNTL) && defined(F_GETFL)
8785  oflags = fcntl(fd, F_GETFL);
8786  if (oflags == -1) rb_sys_fail(0);
8787 #else
8788  if (fstat(fd, &st) < 0) rb_sys_fail(0);
8789 #endif
8790  rb_update_max_fd(fd);
8791 #if defined(HAVE_FCNTL) && defined(F_GETFL)
8792  ofmode = rb_io_oflags_fmode(oflags);
8793  if (NIL_P(vmode)) {
8794  fmode = ofmode;
8795  }
8796  else if ((~ofmode & fmode) & FMODE_READWRITE) {
8797  VALUE error = INT2FIX(EINVAL);
8799  }
8800 #endif
8801  if (!NIL_P(opt) && rb_hash_aref(opt, sym_autoclose) == Qfalse) {
8802  fmode |= FMODE_PREP;
8803  }
8804  MakeOpenFile(io, fp);
8805  fp->self = io;
8806  fp->fd = fd;
8807  fp->mode = fmode;
8808  fp->encs = convconfig;
8809  clear_codeconv(fp);
8810  io_check_tty(fp);
8811  if (fileno(stdin) == fd)
8812  fp->stdio_file = stdin;
8813  else if (fileno(stdout) == fd)
8814  fp->stdio_file = stdout;
8815  else if (fileno(stderr) == fd)
8816  fp->stdio_file = stderr;
8817 
8818  if (fmode & FMODE_SETENC_BY_BOM) io_set_encoding_by_bom(io);
8819  return io;
8820 }
8821 
8822 /*
8823  * call-seq:
8824  * ios.set_encoding_by_bom -> encoding or nil
8825  *
8826  * Checks if +ios+ starts with a BOM, and then consumes it and sets
8827  * the external encoding. Returns the result encoding if found, or
8828  * nil. If +ios+ is not binmode or its encoding has been set
8829  * already, an exception will be raised.
8830  *
8831  * File.write("bom.txt", "\u{FEFF}abc")
8832  * ios = File.open("bom.txt", "rb")
8833  * ios.set_encoding_by_bom #=> #<Encoding:UTF-8>
8834  *
8835  * File.write("nobom.txt", "abc")
8836  * ios = File.open("nobom.txt", "rb")
8837  * ios.set_encoding_by_bom #=> nil
8838  */
8839 
8840 static VALUE
8841 rb_io_set_encoding_by_bom(VALUE io)
8842 {
8843  rb_io_t *fptr;
8844 
8845  GetOpenFile(io, fptr);
8846  if (!(fptr->mode & FMODE_BINMODE)) {
8847  rb_raise(rb_eArgError, "ASCII incompatible encoding needs binmode");
8848  }
8849  if (fptr->encs.enc2) {
8850  rb_raise(rb_eArgError, "encoding conversion is set");
8851  }
8852  else if (fptr->encs.enc && fptr->encs.enc != rb_ascii8bit_encoding()) {
8853  rb_raise(rb_eArgError, "encoding is set to %s already",
8854  rb_enc_name(fptr->encs.enc));
8855  }
8856  if (!io_set_encoding_by_bom(io)) return Qnil;
8857  return rb_enc_from_encoding(fptr->encs.enc);
8858 }
8859 
8860 /*
8861  * call-seq:
8862  * File.new(filename, mode="r" [, opt]) -> file
8863  * File.new(filename [, mode [, perm]] [, opt]) -> file
8864  *
8865  * Opens the file named by +filename+ according to the given +mode+ and
8866  * returns a new File object.
8867  *
8868  * See IO.new for a description of +mode+ and +opt+.
8869  *
8870  * If a file is being created, permission bits may be given in +perm+. These
8871  * mode and permission bits are platform dependent; on Unix systems, see
8872  * open(2) and chmod(2) man pages for details.
8873  *
8874  * The new File object is buffered mode (or non-sync mode), unless
8875  * +filename+ is a tty.
8876  * See IO#flush, IO#fsync, IO#fdatasync, and IO#sync= about sync mode.
8877  *
8878  * === Examples
8879  *
8880  * f = File.new("testfile", "r")
8881  * f = File.new("newfile", "w+")
8882  * f = File.new("newfile", File::CREAT|File::TRUNC|File::RDWR, 0644)
8883  */
8884 
8885 static VALUE
8886 rb_file_initialize(int argc, VALUE *argv, VALUE io)
8887 {
8888  if (RFILE(io)->fptr) {
8889  rb_raise(rb_eRuntimeError, "reinitializing File");
8890  }
8891  if (0 < argc && argc < 3) {
8892  VALUE fd = rb_check_to_int(argv[0]);
8893 
8894  if (!NIL_P(fd)) {
8895  argv[0] = fd;
8896  return rb_io_initialize(argc, argv, io);
8897  }
8898  }
8899  rb_open_file(argc, argv, io);
8900 
8901  return io;
8902 }
8903 
8904 /* :nodoc: */
8905 static VALUE
8906 rb_io_s_new(int argc, VALUE *argv, VALUE klass)
8907 {
8908  if (rb_block_given_p()) {
8909  VALUE cname = rb_obj_as_string(klass);
8910 
8911  rb_warn("%"PRIsVALUE"::new() does not take block; use %"PRIsVALUE"::open() instead",
8912  cname, cname);
8913  }
8914  return rb_class_new_instance_kw(argc, argv, klass, RB_PASS_CALLED_KEYWORDS);
8915 }
8916 
8917 
8918 /*
8919  * call-seq:
8920  * IO.for_fd(fd, mode [, opt]) -> io
8921  *
8922  * Synonym for IO.new.
8923  *
8924  */
8925 
8926 static VALUE
8927 rb_io_s_for_fd(int argc, VALUE *argv, VALUE klass)
8928 {
8929  VALUE io = rb_obj_alloc(klass);
8930  rb_io_initialize(argc, argv, io);
8931  return io;
8932 }
8933 
8934 /*
8935  * call-seq:
8936  * ios.autoclose? -> true or false
8937  *
8938  * Returns +true+ if the underlying file descriptor of _ios_ will be
8939  * closed automatically at its finalization, otherwise +false+.
8940  */
8941 
8942 static VALUE
8943 rb_io_autoclose_p(VALUE io)
8944 {
8945  rb_io_t *fptr = RFILE(io)->fptr;
8946  rb_io_check_closed(fptr);
8947  return (fptr->mode & FMODE_PREP) ? Qfalse : Qtrue;
8948 }
8949 
8950 /*
8951  * call-seq:
8952  * io.autoclose = bool -> true or false
8953  *
8954  * Sets auto-close flag.
8955  *
8956  * f = open("/dev/null")
8957  * IO.for_fd(f.fileno)
8958  * # ...
8959  * f.gets # may cause Errno::EBADF
8960  *
8961  * f = open("/dev/null")
8962  * IO.for_fd(f.fileno).autoclose = false
8963  * # ...
8964  * f.gets # won't cause Errno::EBADF
8965  */
8966 
8967 static VALUE
8968 rb_io_set_autoclose(VALUE io, VALUE autoclose)
8969 {
8970  rb_io_t *fptr;
8971  GetOpenFile(io, fptr);
8972  if (!RTEST(autoclose))
8973  fptr->mode |= FMODE_PREP;
8974  else
8975  fptr->mode &= ~FMODE_PREP;
8976  return autoclose;
8977 }
8978 
8979 static void
8980 argf_mark(void *ptr)
8981 {
8982  struct argf *p = ptr;
8983  rb_gc_mark(p->filename);
8984  rb_gc_mark(p->current_file);
8985  rb_gc_mark(p->argv);
8986  rb_gc_mark(p->inplace);
8987  rb_gc_mark(p->encs.ecopts);
8988 }
8989 
8990 static size_t
8991 argf_memsize(const void *ptr)
8992 {
8993  const struct argf *p = ptr;
8994  size_t size = sizeof(*p);
8995  return size;
8996 }
8997 
8998 static const rb_data_type_t argf_type = {
8999  "ARGF",
9000  {argf_mark, RUBY_TYPED_DEFAULT_FREE, argf_memsize},
9001  0, 0, RUBY_TYPED_FREE_IMMEDIATELY
9002 };
9003 
9004 static inline void
9005 argf_init(struct argf *p, VALUE v)
9006 {
9007  p->filename = Qnil;
9008  p->current_file = Qnil;
9009  p->lineno = 0;
9010  p->argv = v;
9011 }
9012 
9013 static VALUE
9014 argf_alloc(VALUE klass)
9015 {
9016  struct argf *p;
9017  VALUE argf = TypedData_Make_Struct(klass, struct argf, &argf_type, p);
9018 
9019  argf_init(p, Qnil);
9020  return argf;
9021 }
9022 
9023 #undef rb_argv
9024 
9025 /* :nodoc: */
9026 static VALUE
9027 argf_initialize(VALUE argf, VALUE argv)
9028 {
9029  memset(&ARGF, 0, sizeof(ARGF));
9030  argf_init(&ARGF, argv);
9031 
9032  return argf;
9033 }
9034 
9035 /* :nodoc: */
9036 static VALUE
9037 argf_initialize_copy(VALUE argf, VALUE orig)
9038 {
9039  if (!OBJ_INIT_COPY(argf, orig)) return argf;
9040  ARGF = argf_of(orig);
9041  ARGF.argv = rb_obj_dup(ARGF.argv);
9042  return argf;
9043 }
9044 
9045 /*
9046  * call-seq:
9047  * ARGF.lineno = integer -> integer
9048  *
9049  * Sets the line number of +ARGF+ as a whole to the given +Integer+.
9050  *
9051  * +ARGF+ sets the line number automatically as you read data, so normally
9052  * you will not need to set it explicitly. To access the current line number
9053  * use +ARGF.lineno+.
9054  *
9055  * For example:
9056  *
9057  * ARGF.lineno #=> 0
9058  * ARGF.readline #=> "This is line 1\n"
9059  * ARGF.lineno #=> 1
9060  * ARGF.lineno = 0 #=> 0
9061  * ARGF.lineno #=> 0
9062  */
9063 static VALUE
9064 argf_set_lineno(VALUE argf, VALUE val)
9065 {
9066  ARGF.lineno = NUM2INT(val);
9067  ARGF.last_lineno = ARGF.lineno;
9068  return Qnil;
9069 }
9070 
9071 /*
9072  * call-seq:
9073  * ARGF.lineno -> integer
9074  *
9075  * Returns the current line number of ARGF as a whole. This value
9076  * can be set manually with +ARGF.lineno=+.
9077  *
9078  * For example:
9079  *
9080  * ARGF.lineno #=> 0
9081  * ARGF.readline #=> "This is line 1\n"
9082  * ARGF.lineno #=> 1
9083  */
9084 static VALUE
9085 argf_lineno(VALUE argf)
9086 {
9087  return INT2FIX(ARGF.lineno);
9088 }
9089 
9090 static VALUE
9091 argf_forward(int argc, VALUE *argv, VALUE argf)
9092 {
9093  return forward_current(rb_frame_this_func(), argc, argv);
9094 }
9095 
9096 #define next_argv() argf_next_argv(argf)
9097 #define ARGF_GENERIC_INPUT_P() \
9098  (ARGF.current_file == rb_stdin && !RB_TYPE_P(ARGF.current_file, T_FILE))
9099 #define ARGF_FORWARD(argc, argv) do {\
9100  if (ARGF_GENERIC_INPUT_P())\
9101  return argf_forward((argc), (argv), argf);\
9102 } while (0)
9103 #define NEXT_ARGF_FORWARD(argc, argv) do {\
9104  if (!next_argv()) return Qnil;\
9105  ARGF_FORWARD((argc), (argv));\
9106 } while (0)
9107 
9108 static void
9109 argf_close(VALUE argf)
9110 {
9111  VALUE file = ARGF.current_file;
9112  if (file == rb_stdin) return;
9113  if (RB_TYPE_P(file, T_FILE)) {
9114  rb_io_set_write_io(file, Qnil);
9115  }
9116  io_close(file);
9117  ARGF.init_p = -1;
9118 }
9119 
9120 static int
9121 argf_next_argv(VALUE argf)
9122 {
9123  char *fn;
9124  rb_io_t *fptr;
9125  int stdout_binmode = 0;
9126  int fmode;
9127 
9128  VALUE r_stdout = rb_ractor_stdout();
9129 
9130  if (RB_TYPE_P(r_stdout, T_FILE)) {
9131  GetOpenFile(r_stdout, fptr);
9132  if (fptr->mode & FMODE_BINMODE)
9133  stdout_binmode = 1;
9134  }
9135 
9136  if (ARGF.init_p == 0) {
9137  if (!NIL_P(ARGF.argv) && RARRAY_LEN(ARGF.argv) > 0) {
9138  ARGF.next_p = 1;
9139  }
9140  else {
9141  ARGF.next_p = -1;
9142  }
9143  ARGF.init_p = 1;
9144  }
9145  else {
9146  if (NIL_P(ARGF.argv)) {
9147  ARGF.next_p = -1;
9148  }
9149  else if (ARGF.next_p == -1 && RARRAY_LEN(ARGF.argv) > 0) {
9150  ARGF.next_p = 1;
9151  }
9152  }
9153 
9154  if (ARGF.next_p == 1) {
9155  if (ARGF.init_p == 1) argf_close(argf);
9156  retry:
9157  if (RARRAY_LEN(ARGF.argv) > 0) {
9158  VALUE filename = rb_ary_shift(ARGF.argv);
9159  FilePathValue(filename);
9160  ARGF.filename = filename;
9161  filename = rb_str_encode_ospath(filename);
9162  fn = StringValueCStr(filename);
9163  if (RSTRING_LEN(filename) == 1 && fn[0] == '-') {
9164  ARGF.current_file = rb_stdin;
9165  if (ARGF.inplace) {
9166  rb_warn("Can't do inplace edit for stdio; skipping");
9167  goto retry;
9168  }
9169  }
9170  else {
9171  VALUE write_io = Qnil;
9172  int fr = rb_sysopen(filename, O_RDONLY, 0);
9173 
9174  if (ARGF.inplace) {
9175  struct stat st;
9176 #ifndef NO_SAFE_RENAME
9177  struct stat st2;
9178 #endif
9179  VALUE str;
9180  int fw;
9181 
9182  if (RB_TYPE_P(r_stdout, T_FILE) && r_stdout != orig_stdout) {
9183  rb_io_close(r_stdout);
9184  }
9185  fstat(fr, &st);
9186  str = filename;
9187  if (!NIL_P(ARGF.inplace)) {
9188  VALUE suffix = ARGF.inplace;
9189  str = rb_str_dup(str);
9190  if (NIL_P(rb_str_cat_conv_enc_opts(str, RSTRING_LEN(str),
9191  RSTRING_PTR(suffix), RSTRING_LEN(suffix),
9192  rb_enc_get(suffix), 0, Qnil))) {
9193  rb_str_append(str, suffix);
9194  }
9195 #ifdef NO_SAFE_RENAME
9196  (void)close(fr);
9197  (void)unlink(RSTRING_PTR(str));
9198  if (rename(fn, RSTRING_PTR(str)) < 0) {
9199  rb_warn("Can't rename %"PRIsVALUE" to %"PRIsVALUE": %s, skipping file",
9200  filename, str, strerror(errno));
9201  goto retry;
9202  }
9203  fr = rb_sysopen(str, O_RDONLY, 0);
9204 #else
9205  if (rename(fn, RSTRING_PTR(str)) < 0) {
9206  rb_warn("Can't rename %"PRIsVALUE" to %"PRIsVALUE": %s, skipping file",
9207  filename, str, strerror(errno));
9208  close(fr);
9209  goto retry;
9210  }
9211 #endif
9212  }
9213  else {
9214 #ifdef NO_SAFE_RENAME
9215  rb_fatal("Can't do inplace edit without backup");
9216 #else
9217  if (unlink(fn) < 0) {
9218  rb_warn("Can't remove %"PRIsVALUE": %s, skipping file",
9219  filename, strerror(errno));
9220  close(fr);
9221  goto retry;
9222  }
9223 #endif
9224  }
9225  fw = rb_sysopen(filename, O_WRONLY|O_CREAT|O_TRUNC, 0666);
9226 #ifndef NO_SAFE_RENAME
9227  fstat(fw, &st2);
9228 #ifdef HAVE_FCHMOD
9229  fchmod(fw, st.st_mode);
9230 #else
9231  chmod(fn, st.st_mode);
9232 #endif
9233  if (st.st_uid!=st2.st_uid || st.st_gid!=st2.st_gid) {
9234  int err;
9235 #ifdef HAVE_FCHOWN
9236  err = fchown(fw, st.st_uid, st.st_gid);
9237 #else
9238  err = chown(fn, st.st_uid, st.st_gid);
9239 #endif
9240  if (err && getuid() == 0 && st2.st_uid == 0) {
9241  const char *wkfn = RSTRING_PTR(filename);
9242  rb_warn("Can't set owner/group of %"PRIsVALUE" to same as %"PRIsVALUE": %s, skipping file",
9243  filename, str, strerror(errno));
9244  (void)close(fr);
9245  (void)close(fw);
9246  (void)unlink(wkfn);
9247  goto retry;
9248  }
9249  }
9250 #endif
9251  write_io = prep_io(fw, FMODE_WRITABLE, rb_cFile, fn);
9252  rb_ractor_stdout_set(write_io);
9253  if (stdout_binmode) rb_io_binmode(rb_stdout);
9254  }
9255  fmode = FMODE_READABLE;
9256  if (!ARGF.binmode) {
9257  fmode |= DEFAULT_TEXTMODE;
9258  }
9259  ARGF.current_file = prep_io(fr, fmode, rb_cFile, fn);
9260  if (!NIL_P(write_io)) {
9261  rb_io_set_write_io(ARGF.current_file, write_io);
9262  }
9263  RB_GC_GUARD(filename);
9264  }
9265  if (ARGF.binmode) rb_io_ascii8bit_binmode(ARGF.current_file);
9266  GetOpenFile(ARGF.current_file, fptr);
9267  if (ARGF.encs.enc) {
9268  fptr->encs = ARGF.encs;
9269  clear_codeconv(fptr);
9270  }
9271  else {
9273  if (!ARGF.binmode) {
9275 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
9276  fptr->encs.ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
9277 #endif
9278  }
9279  }
9280  ARGF.next_p = 0;
9281  }
9282  else {
9283  ARGF.next_p = 1;
9284  return FALSE;
9285  }
9286  }
9287  else if (ARGF.next_p == -1) {
9288  ARGF.current_file = rb_stdin;
9289  ARGF.filename = rb_str_new2("-");
9290  if (ARGF.inplace) {
9291  rb_warn("Can't do inplace edit for stdio");
9292  rb_ractor_stdout_set(orig_stdout);
9293  }
9294  }
9295  if (ARGF.init_p == -1) ARGF.init_p = 1;
9296  return TRUE;
9297 }
9298 
9299 static VALUE
9300 argf_getline(int argc, VALUE *argv, VALUE argf)
9301 {
9302  VALUE line;
9303  long lineno = ARGF.lineno;
9304 
9305  retry:
9306  if (!next_argv()) return Qnil;
9307  if (ARGF_GENERIC_INPUT_P()) {
9308  line = forward_current(idGets, argc, argv);
9309  }
9310  else {
9311  if (argc == 0 && rb_rs == rb_default_rs) {
9312  line = rb_io_gets(ARGF.current_file);
9313  }
9314  else {
9315  line = rb_io_getline(argc, argv, ARGF.current_file);
9316  }
9317  if (NIL_P(line) && ARGF.next_p != -1) {
9318  argf_close(argf);
9319  ARGF.next_p = 1;
9320  goto retry;
9321  }
9322  }
9323  if (!NIL_P(line)) {
9324  ARGF.lineno = ++lineno;
9325  ARGF.last_lineno = ARGF.lineno;
9326  }
9327  return line;
9328 }
9329 
9330 static VALUE
9331 argf_lineno_getter(ID id, VALUE *var)
9332 {
9333  VALUE argf = *var;
9334  return INT2FIX(ARGF.last_lineno);
9335 }
9336 
9337 static void
9338 argf_lineno_setter(VALUE val, ID id, VALUE *var)
9339 {
9340  VALUE argf = *var;
9341  int n = NUM2INT(val);
9342  ARGF.last_lineno = ARGF.lineno = n;
9343 }
9344 
9345 static VALUE argf_gets(int, VALUE *, VALUE);
9346 
9347 /*
9348  * call-seq:
9349  * gets(sep=$/ [, getline_args]) -> string or nil
9350  * gets(limit [, getline_args]) -> string or nil
9351  * gets(sep, limit [, getline_args]) -> string or nil
9352  *
9353  * Returns (and assigns to <code>$_</code>) the next line from the list
9354  * of files in +ARGV+ (or <code>$*</code>), or from standard input if
9355  * no files are present on the command line. Returns +nil+ at end of
9356  * file. The optional argument specifies the record separator. The
9357  * separator is included with the contents of each record. A separator
9358  * of +nil+ reads the entire contents, and a zero-length separator
9359  * reads the input one paragraph at a time, where paragraphs are
9360  * divided by two consecutive newlines. If the first argument is an
9361  * integer, or optional second argument is given, the returning string
9362  * would not be longer than the given value in bytes. If multiple
9363  * filenames are present in +ARGV+, <code>gets(nil)</code> will read
9364  * the contents one file at a time.
9365  *
9366  * ARGV << "testfile"
9367  * print while gets
9368  *
9369  * <em>produces:</em>
9370  *
9371  * This is line one
9372  * This is line two
9373  * This is line three
9374  * And so on...
9375  *
9376  * The style of programming using <code>$_</code> as an implicit
9377  * parameter is gradually losing favor in the Ruby community.
9378  */
9379 
9380 static VALUE
9381 rb_f_gets(int argc, VALUE *argv, VALUE recv)
9382 {
9383  if (recv == argf) {
9384  return argf_gets(argc, argv, argf);
9385  }
9386  return forward(argf, idGets, argc, argv);
9387 }
9388 
9389 /*
9390  * call-seq:
9391  * ARGF.gets(sep=$/ [, getline_args]) -> string or nil
9392  * ARGF.gets(limit [, getline_args]) -> string or nil
9393  * ARGF.gets(sep, limit [, getline_args]) -> string or nil
9394  *
9395  * Returns the next line from the current file in +ARGF+.
9396  *
9397  * By default lines are assumed to be separated by <code>$/</code>;
9398  * to use a different character as a separator, supply it as a +String+
9399  * for the _sep_ argument.
9400  *
9401  * The optional _limit_ argument specifies how many characters of each line
9402  * to return. By default all characters are returned.
9403  *
9404  * See IO.readlines for details about getline_args.
9405  *
9406  */
9407 static VALUE
9408 argf_gets(int argc, VALUE *argv, VALUE argf)
9409 {
9410  VALUE line;
9411 
9412  line = argf_getline(argc, argv, argf);
9413  rb_lastline_set(line);
9414 
9415  return line;
9416 }
9417 
9418 VALUE
9419 rb_gets(void)
9420 {
9421  VALUE line;
9422 
9423  if (rb_rs != rb_default_rs) {
9424  return rb_f_gets(0, 0, argf);
9425  }
9426 
9427  retry:
9428  if (!next_argv()) return Qnil;
9429  line = rb_io_gets(ARGF.current_file);
9430  if (NIL_P(line) && ARGF.next_p != -1) {
9431  rb_io_close(ARGF.current_file);
9432  ARGF.next_p = 1;
9433  goto retry;
9434  }
9435  rb_lastline_set(line);
9436  if (!NIL_P(line)) {
9437  ARGF.lineno++;
9438  ARGF.last_lineno = ARGF.lineno;
9439  }
9440 
9441  return line;
9442 }
9443 
9444 static VALUE argf_readline(int, VALUE *, VALUE);
9445 
9446 /*
9447  * call-seq:
9448  * readline(sep=$/) -> string
9449  * readline(limit) -> string
9450  * readline(sep, limit) -> string
9451  *
9452  * Equivalent to Kernel::gets, except
9453  * +readline+ raises +EOFError+ at end of file.
9454  */
9455 
9456 static VALUE
9457 rb_f_readline(int argc, VALUE *argv, VALUE recv)
9458 {
9459  if (recv == argf) {
9460  return argf_readline(argc, argv, argf);
9461  }
9462  return forward(argf, rb_intern("readline"), argc, argv);
9463 }
9464 
9465 
9466 /*
9467  * call-seq:
9468  * ARGF.readline(sep=$/) -> string
9469  * ARGF.readline(limit) -> string
9470  * ARGF.readline(sep, limit) -> string
9471  *
9472  * Returns the next line from the current file in +ARGF+.
9473  *
9474  * By default lines are assumed to be separated by <code>$/</code>;
9475  * to use a different character as a separator, supply it as a +String+
9476  * for the _sep_ argument.
9477  *
9478  * The optional _limit_ argument specifies how many characters of each line
9479  * to return. By default all characters are returned.
9480  *
9481  * An +EOFError+ is raised at the end of the file.
9482  */
9483 static VALUE
9484 argf_readline(int argc, VALUE *argv, VALUE argf)
9485 {
9486  VALUE line;
9487 
9488  if (!next_argv()) rb_eof_error();
9489  ARGF_FORWARD(argc, argv);
9490  line = argf_gets(argc, argv, argf);
9491  if (NIL_P(line)) {
9492  rb_eof_error();
9493  }
9494 
9495  return line;
9496 }
9497 
9498 static VALUE argf_readlines(int, VALUE *, VALUE);
9499 
9500 /*
9501  * call-seq:
9502  * readlines(sep=$/) -> array
9503  * readlines(limit) -> array
9504  * readlines(sep, limit) -> array
9505  *
9506  * Returns an array containing the lines returned by calling
9507  * <code>Kernel.gets(<i>sep</i>)</code> until the end of file.
9508  */
9509 
9510 static VALUE
9511 rb_f_readlines(int argc, VALUE *argv, VALUE recv)
9512 {
9513  if (recv == argf) {
9514  return argf_readlines(argc, argv, argf);
9515  }
9516  return forward(argf, rb_intern("readlines"), argc, argv);
9517 }
9518 
9519 /*
9520  * call-seq:
9521  * ARGF.readlines(sep = $/) -> array
9522  * ARGF.readlines(limit) -> array
9523  * ARGF.readlines(sep, limit) -> array
9524  *
9525  * ARGF.to_a(sep = $/) -> array
9526  * ARGF.to_a(limit) -> array
9527  * ARGF.to_a(sep, limit) -> array
9528  *
9529  * Reads each file in +ARGF+ in its entirety, returning an +Array+ containing
9530  * lines from the files. Lines are assumed to be separated by _sep_.
9531  *
9532  * lines = ARGF.readlines
9533  * lines[0] #=> "This is line one\n"
9534  */
9535 static VALUE
9536 argf_readlines(int argc, VALUE *argv, VALUE argf)
9537 {
9538  long lineno = ARGF.lineno;
9539  VALUE lines, ary;
9540 
9541  ary = rb_ary_new();
9542  while (next_argv()) {
9543  if (ARGF_GENERIC_INPUT_P()) {
9544  lines = forward_current(rb_intern("readlines"), argc, argv);
9545  }
9546  else {
9547  lines = rb_io_readlines(argc, argv, ARGF.current_file);
9548  argf_close(argf);
9549  }
9550  ARGF.next_p = 1;
9551  rb_ary_concat(ary, lines);
9552  ARGF.lineno = lineno + RARRAY_LEN(ary);
9553  ARGF.last_lineno = ARGF.lineno;
9554  }
9555  ARGF.init_p = 0;
9556  return ary;
9557 }
9558 
9559 /*
9560  * call-seq:
9561  * `cmd` -> string
9562  *
9563  * Returns the standard output of running _cmd_ in a subshell.
9564  * The built-in syntax <code>%x{...}</code> uses
9565  * this method. Sets <code>$?</code> to the process status.
9566  *
9567  * `date` #=> "Wed Apr 9 08:56:30 CDT 2003\n"
9568  * `ls testdir`.split[1] #=> "main.rb"
9569  * `echo oops && exit 99` #=> "oops\n"
9570  * $?.exitstatus #=> 99
9571  */
9572 
9573 static VALUE
9574 rb_f_backquote(VALUE obj, VALUE str)
9575 {
9576  VALUE port;
9577  VALUE result;
9578  rb_io_t *fptr;
9579 
9580  SafeStringValue(str);
9581  rb_last_status_clear();
9582  port = pipe_open_s(str, "r", FMODE_READABLE|DEFAULT_TEXTMODE, NULL);
9583  if (NIL_P(port)) return rb_str_new(0,0);
9584 
9585  GetOpenFile(port, fptr);
9586  result = read_all(fptr, remain_size(fptr), Qnil);
9587  rb_io_close(port);
9588  RFILE(port)->fptr = NULL;
9589  rb_io_fptr_finalize(fptr);
9590  RB_GC_GUARD(port);
9591 
9592  return result;
9593 }
9594 
9595 #ifdef HAVE_SYS_SELECT_H
9596 #include <sys/select.h>
9597 #endif
9598 
9599 static VALUE
9600 select_internal(VALUE read, VALUE write, VALUE except, struct timeval *tp, rb_fdset_t *fds)
9601 {
9602  VALUE res, list;
9603  rb_fdset_t *rp, *wp, *ep;
9604  rb_io_t *fptr;
9605  long i;
9606  int max = 0, n;
9607  int pending = 0;
9608  struct timeval timerec;
9609 
9610  if (!NIL_P(read)) {
9611  Check_Type(read, T_ARRAY);
9612  for (i=0; i<RARRAY_LEN(read); i++) {
9613  GetOpenFile(rb_io_get_io(RARRAY_AREF(read, i)), fptr);
9614  rb_fd_set(fptr->fd, &fds[0]);
9615  if (READ_DATA_PENDING(fptr) || READ_CHAR_PENDING(fptr)) { /* check for buffered data */
9616  pending++;
9617  rb_fd_set(fptr->fd, &fds[3]);
9618  }
9619  if (max < fptr->fd) max = fptr->fd;
9620  }
9621  if (pending) { /* no blocking if there's buffered data */
9622  timerec.tv_sec = timerec.tv_usec = 0;
9623  tp = &timerec;
9624  }
9625  rp = &fds[0];
9626  }
9627  else
9628  rp = 0;
9629 
9630  if (!NIL_P(write)) {
9631  Check_Type(write, T_ARRAY);
9632  for (i=0; i<RARRAY_LEN(write); i++) {
9633  VALUE write_io = GetWriteIO(rb_io_get_io(RARRAY_AREF(write, i)));
9634  GetOpenFile(write_io, fptr);
9635  rb_fd_set(fptr->fd, &fds[1]);
9636  if (max < fptr->fd) max = fptr->fd;
9637  }
9638  wp = &fds[1];
9639  }
9640  else
9641  wp = 0;
9642 
9643  if (!NIL_P(except)) {
9644  Check_Type(except, T_ARRAY);
9645  for (i=0; i<RARRAY_LEN(except); i++) {
9646  VALUE io = rb_io_get_io(RARRAY_AREF(except, i));
9647  VALUE write_io = GetWriteIO(io);
9648  GetOpenFile(io, fptr);
9649  rb_fd_set(fptr->fd, &fds[2]);
9650  if (max < fptr->fd) max = fptr->fd;
9651  if (io != write_io) {
9652  GetOpenFile(write_io, fptr);
9653  rb_fd_set(fptr->fd, &fds[2]);
9654  if (max < fptr->fd) max = fptr->fd;
9655  }
9656  }
9657  ep = &fds[2];
9658  }
9659  else {
9660  ep = 0;
9661  }
9662 
9663  max++;
9664 
9665  n = rb_thread_fd_select(max, rp, wp, ep, tp);
9666  if (n < 0) {
9667  rb_sys_fail(0);
9668  }
9669  if (!pending && n == 0) return Qnil; /* returns nil on timeout */
9670 
9671  res = rb_ary_new2(3);
9672  rb_ary_push(res, rp?rb_ary_new():rb_ary_new2(0));
9673  rb_ary_push(res, wp?rb_ary_new():rb_ary_new2(0));
9674  rb_ary_push(res, ep?rb_ary_new():rb_ary_new2(0));
9675 
9676  if (rp) {
9677  list = RARRAY_AREF(res, 0);
9678  for (i=0; i< RARRAY_LEN(read); i++) {
9679  VALUE obj = rb_ary_entry(read, i);
9680  VALUE io = rb_io_get_io(obj);
9681  GetOpenFile(io, fptr);
9682  if (rb_fd_isset(fptr->fd, &fds[0]) ||
9683  rb_fd_isset(fptr->fd, &fds[3])) {
9684  rb_ary_push(list, obj);
9685  }
9686  }
9687  }
9688 
9689  if (wp) {
9690  list = RARRAY_AREF(res, 1);
9691  for (i=0; i< RARRAY_LEN(write); i++) {
9692  VALUE obj = rb_ary_entry(write, i);
9693  VALUE io = rb_io_get_io(obj);
9694  VALUE write_io = GetWriteIO(io);
9695  GetOpenFile(write_io, fptr);
9696  if (rb_fd_isset(fptr->fd, &fds[1])) {
9697  rb_ary_push(list, obj);
9698  }
9699  }
9700  }
9701 
9702  if (ep) {
9703  list = RARRAY_AREF(res, 2);
9704  for (i=0; i< RARRAY_LEN(except); i++) {
9705  VALUE obj = rb_ary_entry(except, i);
9706  VALUE io = rb_io_get_io(obj);
9707  VALUE write_io = GetWriteIO(io);
9708  GetOpenFile(io, fptr);
9709  if (rb_fd_isset(fptr->fd, &fds[2])) {
9710  rb_ary_push(list, obj);
9711  }
9712  else if (io != write_io) {
9713  GetOpenFile(write_io, fptr);
9714  if (rb_fd_isset(fptr->fd, &fds[2])) {
9715  rb_ary_push(list, obj);
9716  }
9717  }
9718  }
9719  }
9720 
9721  return res; /* returns an empty array on interrupt */
9722 }
9723 
9724 struct select_args {
9725  VALUE read, write, except;
9726  struct timeval *timeout;
9727  rb_fdset_t fdsets[4];
9728 };
9729 
9730 static VALUE
9731 select_call(VALUE arg)
9732 {
9733  struct select_args *p = (struct select_args *)arg;
9734 
9735  return select_internal(p->read, p->write, p->except, p->timeout, p->fdsets);
9736 }
9737 
9738 static VALUE
9739 select_end(VALUE arg)
9740 {
9741  struct select_args *p = (struct select_args *)arg;
9742  int i;
9743 
9744  for (i = 0; i < numberof(p->fdsets); ++i)
9745  rb_fd_term(&p->fdsets[i]);
9746  return Qnil;
9747 }
9748 
9749 static VALUE sym_normal, sym_sequential, sym_random,
9750  sym_willneed, sym_dontneed, sym_noreuse;
9751 
9752 #ifdef HAVE_POSIX_FADVISE
9753 struct io_advise_struct {
9754  int fd;
9755  int advice;
9756  off_t offset;
9757  off_t len;
9758 };
9759 
9760 static VALUE
9761 io_advise_internal(void *arg)
9762 {
9763  struct io_advise_struct *ptr = arg;
9764  return posix_fadvise(ptr->fd, ptr->offset, ptr->len, ptr->advice);
9765 }
9766 
9767 static VALUE
9768 io_advise_sym_to_const(VALUE sym)
9769 {
9770 #ifdef POSIX_FADV_NORMAL
9771  if (sym == sym_normal)
9772  return INT2NUM(POSIX_FADV_NORMAL);
9773 #endif
9774 
9775 #ifdef POSIX_FADV_RANDOM
9776  if (sym == sym_random)
9777  return INT2NUM(POSIX_FADV_RANDOM);
9778 #endif
9779 
9780 #ifdef POSIX_FADV_SEQUENTIAL
9781  if (sym == sym_sequential)
9782  return INT2NUM(POSIX_FADV_SEQUENTIAL);
9783 #endif
9784 
9785 #ifdef POSIX_FADV_WILLNEED
9786  if (sym == sym_willneed)
9787  return INT2NUM(POSIX_FADV_WILLNEED);
9788 #endif
9789 
9790 #ifdef POSIX_FADV_DONTNEED
9791  if (sym == sym_dontneed)
9792  return INT2NUM(POSIX_FADV_DONTNEED);
9793 #endif
9794 
9795 #ifdef POSIX_FADV_NOREUSE
9796  if (sym == sym_noreuse)
9797  return INT2NUM(POSIX_FADV_NOREUSE);
9798 #endif
9799 
9800  return Qnil;
9801 }
9802 
9803 static VALUE
9804 do_io_advise(rb_io_t *fptr, VALUE advice, off_t offset, off_t len)
9805 {
9806  int rv;
9807  struct io_advise_struct ias;
9808  VALUE num_adv;
9809 
9810  num_adv = io_advise_sym_to_const(advice);
9811 
9812  /*
9813  * The platform doesn't support this hint. We don't raise exception, instead
9814  * silently ignore it. Because IO::advise is only hint.
9815  */
9816  if (NIL_P(num_adv))
9817  return Qnil;
9818 
9819  ias.fd = fptr->fd;
9820  ias.advice = NUM2INT(num_adv);
9821  ias.offset = offset;
9822  ias.len = len;
9823 
9824  rv = (int)rb_thread_io_blocking_region(io_advise_internal, &ias, fptr->fd);
9825  if (rv && rv != ENOSYS) {
9826  /* posix_fadvise(2) doesn't set errno. On success it returns 0; otherwise
9827  it returns the error code. */
9828  VALUE message = rb_sprintf("%"PRIsVALUE" "
9829  "(%"PRI_OFFT_PREFIX"d, "
9830  "%"PRI_OFFT_PREFIX"d, "
9831  "%"PRIsVALUE")",
9832  fptr->pathv, offset, len, advice);
9833  rb_syserr_fail_str(rv, message);
9834  }
9835 
9836  return Qnil;
9837 }
9838 
9839 #endif /* HAVE_POSIX_FADVISE */
9840 
9841 static void
9842 advice_arg_check(VALUE advice)
9843 {
9844  if (!SYMBOL_P(advice))
9845  rb_raise(rb_eTypeError, "advice must be a Symbol");
9846 
9847  if (advice != sym_normal &&
9848  advice != sym_sequential &&
9849  advice != sym_random &&
9850  advice != sym_willneed &&
9851  advice != sym_dontneed &&
9852  advice != sym_noreuse) {
9853  rb_raise(rb_eNotImpError, "Unsupported advice: %+"PRIsVALUE, advice);
9854  }
9855 }
9856 
9857 /*
9858  * call-seq:
9859  * ios.advise(advice, offset=0, len=0) -> nil
9860  *
9861  * Announce an intention to access data from the current file in a
9862  * specific pattern. On platforms that do not support the
9863  * <em>posix_fadvise(2)</em> system call, this method is a no-op.
9864  *
9865  * _advice_ is one of the following symbols:
9866  *
9867  * :normal:: No advice to give; the default assumption for an open file.
9868  * :sequential:: The data will be accessed sequentially
9869  * with lower offsets read before higher ones.
9870  * :random:: The data will be accessed in random order.
9871  * :willneed:: The data will be accessed in the near future.
9872  * :dontneed:: The data will not be accessed in the near future.
9873  * :noreuse:: The data will only be accessed once.
9874  *
9875  * The semantics of a piece of advice are platform-dependent. See
9876  * <em>man 2 posix_fadvise</em> for details.
9877  *
9878  * "data" means the region of the current file that begins at
9879  * _offset_ and extends for _len_ bytes. If _len_ is 0, the region
9880  * ends at the last byte of the file. By default, both _offset_ and
9881  * _len_ are 0, meaning that the advice applies to the entire file.
9882  *
9883  * If an error occurs, one of the following exceptions will be raised:
9884  *
9885  * IOError:: The IO stream is closed.
9886  * Errno::EBADF::
9887  * The file descriptor of the current file is invalid.
9888  * Errno::EINVAL:: An invalid value for _advice_ was given.
9889  * Errno::ESPIPE::
9890  * The file descriptor of the current file refers to a FIFO or
9891  * pipe. (Linux raises Errno::EINVAL in this case).
9892  * TypeError::
9893  * Either _advice_ was not a Symbol, or one of the
9894  * other arguments was not an Integer.
9895  * RangeError:: One of the arguments given was too big/small.
9896  *
9897  * This list is not exhaustive; other Errno:: exceptions are also possible.
9898  */
9899 static VALUE
9900 rb_io_advise(int argc, VALUE *argv, VALUE io)
9901 {
9902  VALUE advice, offset, len;
9903  off_t off, l;
9904  rb_io_t *fptr;
9905 
9906  rb_scan_args(argc, argv, "12", &advice, &offset, &len);
9907  advice_arg_check(advice);
9908 
9909  io = GetWriteIO(io);
9910  GetOpenFile(io, fptr);
9911 
9912  off = NIL_P(offset) ? 0 : NUM2OFFT(offset);
9913  l = NIL_P(len) ? 0 : NUM2OFFT(len);
9914 
9915 #ifdef HAVE_POSIX_FADVISE
9916  return do_io_advise(fptr, advice, off, l);
9917 #else
9918  ((void)off, (void)l); /* Ignore all hint */
9919  return Qnil;
9920 #endif
9921 }
9922 
9923 /*
9924  * call-seq:
9925  * IO.select(read_array [, write_array [, error_array [, timeout]]]) -> array or nil
9926  *
9927  * Calls select(2) system call.
9928  * It monitors given arrays of IO objects, waits until one or more of
9929  * IO objects are ready for reading, are ready for writing, and have
9930  * pending exceptions respectively, and returns an array that contains
9931  * arrays of those IO objects. It will return +nil+ if optional
9932  * <i>timeout</i> value is given and no IO object is ready in
9933  * <i>timeout</i> seconds.
9934  *
9935  * IO.select peeks the buffer of IO objects for testing readability.
9936  * If the IO buffer is not empty, IO.select immediately notifies
9937  * readability. This "peek" only happens for IO objects. It does not
9938  * happen for IO-like objects such as OpenSSL::SSL::SSLSocket.
9939  *
9940  * The best way to use IO.select is invoking it after nonblocking
9941  * methods such as #read_nonblock, #write_nonblock, etc. The methods
9942  * raise an exception which is extended by IO::WaitReadable or
9943  * IO::WaitWritable. The modules notify how the caller should wait
9944  * with IO.select. If IO::WaitReadable is raised, the caller should
9945  * wait for reading. If IO::WaitWritable is raised, the caller should
9946  * wait for writing.
9947  *
9948  * So, blocking read (#readpartial) can be emulated using
9949  * #read_nonblock and IO.select as follows:
9950  *
9951  * begin
9952  * result = io_like.read_nonblock(maxlen)
9953  * rescue IO::WaitReadable
9954  * IO.select([io_like])
9955  * retry
9956  * rescue IO::WaitWritable
9957  * IO.select(nil, [io_like])
9958  * retry
9959  * end
9960  *
9961  * Especially, the combination of nonblocking methods and IO.select is
9962  * preferred for IO like objects such as OpenSSL::SSL::SSLSocket. It
9963  * has #to_io method to return underlying IO object. IO.select calls
9964  * #to_io to obtain the file descriptor to wait.
9965  *
9966  * This means that readability notified by IO.select doesn't mean
9967  * readability from OpenSSL::SSL::SSLSocket object.
9968  *
9969  * The most likely situation is that OpenSSL::SSL::SSLSocket buffers
9970  * some data. IO.select doesn't see the buffer. So IO.select can
9971  * block when OpenSSL::SSL::SSLSocket#readpartial doesn't block.
9972  *
9973  * However, several more complicated situations exist.
9974  *
9975  * SSL is a protocol which is sequence of records.
9976  * The record consists of multiple bytes.
9977  * So, the remote side of SSL sends a partial record, IO.select
9978  * notifies readability but OpenSSL::SSL::SSLSocket cannot decrypt a
9979  * byte and OpenSSL::SSL::SSLSocket#readpartial will block.
9980  *
9981  * Also, the remote side can request SSL renegotiation which forces
9982  * the local SSL engine to write some data.
9983  * This means OpenSSL::SSL::SSLSocket#readpartial may invoke #write
9984  * system call and it can block.
9985  * In such a situation, OpenSSL::SSL::SSLSocket#read_nonblock raises
9986  * IO::WaitWritable instead of blocking.
9987  * So, the caller should wait for ready for writability as above
9988  * example.
9989  *
9990  * The combination of nonblocking methods and IO.select is also useful
9991  * for streams such as tty, pipe socket socket when multiple processes
9992  * read from a stream.
9993  *
9994  * Finally, Linux kernel developers don't guarantee that
9995  * readability of select(2) means readability of following read(2) even
9996  * for a single process.
9997  * See select(2) manual on GNU/Linux system.
9998  *
9999  * Invoking IO.select before IO#readpartial works well as usual.
10000  * However it is not the best way to use IO.select.
10001  *
10002  * The writability notified by select(2) doesn't show
10003  * how many bytes are writable.
10004  * IO#write method blocks until given whole string is written.
10005  * So, <code>IO#write(two or more bytes)</code> can block after
10006  * writability is notified by IO.select. IO#write_nonblock is required
10007  * to avoid the blocking.
10008  *
10009  * Blocking write (#write) can be emulated using #write_nonblock and
10010  * IO.select as follows: IO::WaitReadable should also be rescued for
10011  * SSL renegotiation in OpenSSL::SSL::SSLSocket.
10012  *
10013  * while 0 < string.bytesize
10014  * begin
10015  * written = io_like.write_nonblock(string)
10016  * rescue IO::WaitReadable
10017  * IO.select([io_like])
10018  * retry
10019  * rescue IO::WaitWritable
10020  * IO.select(nil, [io_like])
10021  * retry
10022  * end
10023  * string = string.byteslice(written..-1)
10024  * end
10025  *
10026  * === Parameters
10027  * read_array:: an array of IO objects that wait until ready for read
10028  * write_array:: an array of IO objects that wait until ready for write
10029  * error_array:: an array of IO objects that wait for exceptions
10030  * timeout:: a numeric value in second
10031  *
10032  * === Example
10033  *
10034  * rp, wp = IO.pipe
10035  * mesg = "ping "
10036  * 100.times {
10037  * # IO.select follows IO#read. Not the best way to use IO.select.
10038  * rs, ws, = IO.select([rp], [wp])
10039  * if r = rs[0]
10040  * ret = r.read(5)
10041  * print ret
10042  * case ret
10043  * when /ping/
10044  * mesg = "pong\n"
10045  * when /pong/
10046  * mesg = "ping "
10047  * end
10048  * end
10049  * if w = ws[0]
10050  * w.write(mesg)
10051  * end
10052  * }
10053  *
10054  * <em>produces:</em>
10055  *
10056  * ping pong
10057  * ping pong
10058  * ping pong
10059  * (snipped)
10060  * ping
10061  */
10062 
10063 static VALUE
10064 rb_f_select(int argc, VALUE *argv, VALUE obj)
10065 {
10066  VALUE timeout;
10067  struct select_args args;
10068  struct timeval timerec;
10069  int i;
10070 
10071  rb_scan_args(argc, argv, "13", &args.read, &args.write, &args.except, &timeout);
10072  if (NIL_P(timeout)) {
10073  args.timeout = 0;
10074  }
10075  else {
10076  timerec = rb_time_interval(timeout);
10077  args.timeout = &timerec;
10078  }
10079 
10080  for (i = 0; i < numberof(args.fdsets); ++i)
10081  rb_fd_init(&args.fdsets[i]);
10082 
10083  return rb_ensure(select_call, (VALUE)&args, select_end, (VALUE)&args);
10084 }
10085 
10086 #ifdef IOCTL_REQ_TYPE
10087  typedef IOCTL_REQ_TYPE ioctl_req_t;
10088 #else
10089  typedef int ioctl_req_t;
10090 # define NUM2IOCTLREQ(num) ((int)NUM2LONG(num))
10091 #endif
10092 
10093 #ifdef HAVE_IOCTL
10094 struct ioctl_arg {
10095  int fd;
10096  ioctl_req_t cmd;
10097  long narg;
10098 };
10099 
10100 static VALUE
10101 nogvl_ioctl(void *ptr)
10102 {
10103  struct ioctl_arg *arg = ptr;
10104 
10105  return (VALUE)ioctl(arg->fd, arg->cmd, arg->narg);
10106 }
10107 
10108 static int
10109 do_ioctl(int fd, ioctl_req_t cmd, long narg)
10110 {
10111  int retval;
10112  struct ioctl_arg arg;
10113 
10114  arg.fd = fd;
10115  arg.cmd = cmd;
10116  arg.narg = narg;
10117 
10118  retval = (int)rb_thread_io_blocking_region(nogvl_ioctl, &arg, fd);
10119 
10120  return retval;
10121 }
10122 #endif
10123 
10124 #define DEFAULT_IOCTL_NARG_LEN (256)
10125 
10126 #if defined(__linux__) && defined(_IOC_SIZE)
10127 static long
10128 linux_iocparm_len(ioctl_req_t cmd)
10129 {
10130  long len;
10131 
10132  if ((cmd & 0xFFFF0000) == 0) {
10133  /* legacy and unstructured ioctl number. */
10134  return DEFAULT_IOCTL_NARG_LEN;
10135  }
10136 
10137  len = _IOC_SIZE(cmd);
10138 
10139  /* paranoia check for silly drivers which don't keep ioctl convention */
10140  if (len < DEFAULT_IOCTL_NARG_LEN)
10141  len = DEFAULT_IOCTL_NARG_LEN;
10142 
10143  return len;
10144 }
10145 #endif
10146 
10147 static long
10148 ioctl_narg_len(ioctl_req_t cmd)
10149 {
10150  long len;
10151 
10152 #ifdef IOCPARM_MASK
10153 #ifndef IOCPARM_LEN
10154 #define IOCPARM_LEN(x) (((x) >> 16) & IOCPARM_MASK)
10155 #endif
10156 #endif
10157 #ifdef IOCPARM_LEN
10158  len = IOCPARM_LEN(cmd); /* on BSDish systems we're safe */
10159 #elif defined(__linux__) && defined(_IOC_SIZE)
10160  len = linux_iocparm_len(cmd);
10161 #else
10162  /* otherwise guess at what's safe */
10163  len = DEFAULT_IOCTL_NARG_LEN;
10164 #endif
10165 
10166  return len;
10167 }
10168 
10169 #ifdef HAVE_FCNTL
10170 #ifdef __linux__
10171 typedef long fcntl_arg_t;
10172 #else
10173 /* posix */
10174 typedef int fcntl_arg_t;
10175 #endif
10176 
10177 static long
10178 fcntl_narg_len(ioctl_req_t cmd)
10179 {
10180  long len;
10181 
10182  switch (cmd) {
10183 #ifdef F_DUPFD
10184  case F_DUPFD:
10185  len = sizeof(fcntl_arg_t);
10186  break;
10187 #endif
10188 #ifdef F_DUP2FD /* bsd specific */
10189  case F_DUP2FD:
10190  len = sizeof(int);
10191  break;
10192 #endif
10193 #ifdef F_DUPFD_CLOEXEC /* linux specific */
10194  case F_DUPFD_CLOEXEC:
10195  len = sizeof(fcntl_arg_t);
10196  break;
10197 #endif
10198 #ifdef F_GETFD
10199  case F_GETFD:
10200  len = 1;
10201  break;
10202 #endif
10203 #ifdef F_SETFD
10204  case F_SETFD:
10205  len = sizeof(fcntl_arg_t);
10206  break;
10207 #endif
10208 #ifdef F_GETFL
10209  case F_GETFL:
10210  len = 1;
10211  break;
10212 #endif
10213 #ifdef F_SETFL
10214  case F_SETFL:
10215  len = sizeof(fcntl_arg_t);
10216  break;
10217 #endif
10218 #ifdef F_GETOWN
10219  case F_GETOWN:
10220  len = 1;
10221  break;
10222 #endif
10223 #ifdef F_SETOWN
10224  case F_SETOWN:
10225  len = sizeof(fcntl_arg_t);
10226  break;
10227 #endif
10228 #ifdef F_GETOWN_EX /* linux specific */
10229  case F_GETOWN_EX:
10230  len = sizeof(struct f_owner_ex);
10231  break;
10232 #endif
10233 #ifdef F_SETOWN_EX /* linux specific */
10234  case F_SETOWN_EX:
10235  len = sizeof(struct f_owner_ex);
10236  break;
10237 #endif
10238 #ifdef F_GETLK
10239  case F_GETLK:
10240  len = sizeof(struct flock);
10241  break;
10242 #endif
10243 #ifdef F_SETLK
10244  case F_SETLK:
10245  len = sizeof(struct flock);
10246  break;
10247 #endif
10248 #ifdef F_SETLKW
10249  case F_SETLKW:
10250  len = sizeof(struct flock);
10251  break;
10252 #endif
10253 #ifdef F_READAHEAD /* bsd specific */
10254  case F_READAHEAD:
10255  len = sizeof(int);
10256  break;
10257 #endif
10258 #ifdef F_RDAHEAD /* Darwin specific */
10259  case F_RDAHEAD:
10260  len = sizeof(int);
10261  break;
10262 #endif
10263 #ifdef F_GETSIG /* linux specific */
10264  case F_GETSIG:
10265  len = 1;
10266  break;
10267 #endif
10268 #ifdef F_SETSIG /* linux specific */
10269  case F_SETSIG:
10270  len = sizeof(fcntl_arg_t);
10271  break;
10272 #endif
10273 #ifdef F_GETLEASE /* linux specific */
10274  case F_GETLEASE:
10275  len = 1;
10276  break;
10277 #endif
10278 #ifdef F_SETLEASE /* linux specific */
10279  case F_SETLEASE:
10280  len = sizeof(fcntl_arg_t);
10281  break;
10282 #endif
10283 #ifdef F_NOTIFY /* linux specific */
10284  case F_NOTIFY:
10285  len = sizeof(fcntl_arg_t);
10286  break;
10287 #endif
10288 
10289  default:
10290  len = 256;
10291  break;
10292  }
10293 
10294  return len;
10295 }
10296 #else /* HAVE_FCNTL */
10297 static long
10298 fcntl_narg_len(ioctl_req_t cmd)
10299 {
10300  return 0;
10301 }
10302 #endif /* HAVE_FCNTL */
10303 
10304 #define NARG_SENTINEL 17
10305 
10306 static long
10307 setup_narg(ioctl_req_t cmd, VALUE *argp, long (*narg_len)(ioctl_req_t))
10308 {
10309  long narg = 0;
10310  VALUE arg = *argp;
10311 
10312  if (!RTEST(arg)) {
10313  narg = 0;
10314  }
10315  else if (FIXNUM_P(arg)) {
10316  narg = FIX2LONG(arg);
10317  }
10318  else if (arg == Qtrue) {
10319  narg = 1;
10320  }
10321  else {
10322  VALUE tmp = rb_check_string_type(arg);
10323 
10324  if (NIL_P(tmp)) {
10325  narg = NUM2LONG(arg);
10326  }
10327  else {
10328  char *ptr;
10329  long len, slen;
10330 
10331  *argp = arg = tmp;
10332  len = narg_len(cmd);
10333  rb_str_modify(arg);
10334 
10335  slen = RSTRING_LEN(arg);
10336  /* expand for data + sentinel. */
10337  if (slen < len+1) {
10338  rb_str_resize(arg, len+1);
10339  MEMZERO(RSTRING_PTR(arg)+slen, char, len-slen);
10340  slen = len+1;
10341  }
10342  /* a little sanity check here */
10343  ptr = RSTRING_PTR(arg);
10344  ptr[slen - 1] = NARG_SENTINEL;
10345  narg = (long)(SIGNED_VALUE)ptr;
10346  }
10347  }
10348 
10349  return narg;
10350 }
10351 
10352 static VALUE
10353 finish_narg(int retval, VALUE arg, const rb_io_t *fptr)
10354 {
10355  if (retval < 0) rb_sys_fail_path(fptr->pathv);
10356  if (RB_TYPE_P(arg, T_STRING)) {
10357  char *ptr;
10358  long slen;
10359  RSTRING_GETMEM(arg, ptr, slen);
10360  if (ptr[slen-1] != NARG_SENTINEL)
10361  rb_raise(rb_eArgError, "return value overflowed string");
10362  ptr[slen-1] = '\0';
10363  }
10364 
10365  return INT2NUM(retval);
10366 }
10367 
10368 #ifdef HAVE_IOCTL
10369 static VALUE
10370 rb_ioctl(VALUE io, VALUE req, VALUE arg)
10371 {
10372  ioctl_req_t cmd = NUM2IOCTLREQ(req);
10373  rb_io_t *fptr;
10374  long narg;
10375  int retval;
10376 
10377  narg = setup_narg(cmd, &arg, ioctl_narg_len);
10378  GetOpenFile(io, fptr);
10379  retval = do_ioctl(fptr->fd, cmd, narg);
10380  return finish_narg(retval, arg, fptr);
10381 }
10382 
10383 /*
10384  * call-seq:
10385  * ios.ioctl(integer_cmd, arg) -> integer
10386  *
10387  * Provides a mechanism for issuing low-level commands to control or
10388  * query I/O devices. Arguments and results are platform dependent. If
10389  * <i>arg</i> is a number, its value is passed directly. If it is a
10390  * string, it is interpreted as a binary sequence of bytes. On Unix
10391  * platforms, see <code>ioctl(2)</code> for details. Not implemented on
10392  * all platforms.
10393  */
10394 
10395 static VALUE
10396 rb_io_ioctl(int argc, VALUE *argv, VALUE io)
10397 {
10398  VALUE req, arg;
10399 
10400  rb_scan_args(argc, argv, "11", &req, &arg);
10401  return rb_ioctl(io, req, arg);
10402 }
10403 #else
10404 #define rb_io_ioctl rb_f_notimplement
10405 #endif
10406 
10407 #ifdef HAVE_FCNTL
10408 struct fcntl_arg {
10409  int fd;
10410  int cmd;
10411  long narg;
10412 };
10413 
10414 static VALUE
10415 nogvl_fcntl(void *ptr)
10416 {
10417  struct fcntl_arg *arg = ptr;
10418 
10419 #if defined(F_DUPFD)
10420  if (arg->cmd == F_DUPFD)
10421  return (VALUE)rb_cloexec_fcntl_dupfd(arg->fd, (int)arg->narg);
10422 #endif
10423  return (VALUE)fcntl(arg->fd, arg->cmd, arg->narg);
10424 }
10425 
10426 static int
10427 do_fcntl(int fd, int cmd, long narg)
10428 {
10429  int retval;
10430  struct fcntl_arg arg;
10431 
10432  arg.fd = fd;
10433  arg.cmd = cmd;
10434  arg.narg = narg;
10435 
10436  retval = (int)rb_thread_io_blocking_region(nogvl_fcntl, &arg, fd);
10437  if (retval != -1) {
10438  switch (cmd) {
10439 #if defined(F_DUPFD)
10440  case F_DUPFD:
10441 #endif
10442 #if defined(F_DUPFD_CLOEXEC)
10443  case F_DUPFD_CLOEXEC:
10444 #endif
10445  rb_update_max_fd(retval);
10446  }
10447  }
10448 
10449  return retval;
10450 }
10451 
10452 static VALUE
10453 rb_fcntl(VALUE io, VALUE req, VALUE arg)
10454 {
10455  int cmd = NUM2INT(req);
10456  rb_io_t *fptr;
10457  long narg;
10458  int retval;
10459 
10460  narg = setup_narg(cmd, &arg, fcntl_narg_len);
10461  GetOpenFile(io, fptr);
10462  retval = do_fcntl(fptr->fd, cmd, narg);
10463  return finish_narg(retval, arg, fptr);
10464 }
10465 
10466 /*
10467  * call-seq:
10468  * ios.fcntl(integer_cmd, arg) -> integer
10469  *
10470  * Provides a mechanism for issuing low-level commands to control or
10471  * query file-oriented I/O streams. Arguments and results are platform
10472  * dependent. If <i>arg</i> is a number, its value is passed
10473  * directly. If it is a string, it is interpreted as a binary sequence
10474  * of bytes (Array#pack might be a useful way to build this string). On
10475  * Unix platforms, see <code>fcntl(2)</code> for details. Not
10476  * implemented on all platforms.
10477  */
10478 
10479 static VALUE
10480 rb_io_fcntl(int argc, VALUE *argv, VALUE io)
10481 {
10482  VALUE req, arg;
10483 
10484  rb_scan_args(argc, argv, "11", &req, &arg);
10485  return rb_fcntl(io, req, arg);
10486 }
10487 #else
10488 #define rb_io_fcntl rb_f_notimplement
10489 #endif
10490 
10491 #if defined(HAVE_SYSCALL) || defined(HAVE___SYSCALL)
10492 /*
10493  * call-seq:
10494  * syscall(num [, args...]) -> integer
10495  *
10496  * Calls the operating system function identified by _num_ and
10497  * returns the result of the function or raises SystemCallError if
10498  * it failed.
10499  *
10500  * Arguments for the function can follow _num_. They must be either
10501  * +String+ objects or +Integer+ objects. A +String+ object is passed
10502  * as a pointer to the byte sequence. An +Integer+ object is passed
10503  * as an integer whose bit size is the same as a pointer.
10504  * Up to nine parameters may be passed.
10505  *
10506  * The function identified by _num_ is system
10507  * dependent. On some Unix systems, the numbers may be obtained from a
10508  * header file called <code>syscall.h</code>.
10509  *
10510  * syscall 4, 1, "hello\n", 6 # '4' is write(2) on our box
10511  *
10512  * <em>produces:</em>
10513  *
10514  * hello
10515  *
10516  * Calling +syscall+ on a platform which does not have any way to
10517  * an arbitrary system function just fails with NotImplementedError.
10518  *
10519  * *Note:*
10520  * +syscall+ is essentially unsafe and unportable.
10521  * Feel free to shoot your foot.
10522  * The DL (Fiddle) library is preferred for safer and a bit
10523  * more portable programming.
10524  */
10525 
10526 static VALUE
10527 rb_f_syscall(int argc, VALUE *argv, VALUE _)
10528 {
10529  VALUE arg[8];
10530 #if SIZEOF_VOIDP == 8 && defined(HAVE___SYSCALL) && SIZEOF_INT != 8 /* mainly *BSD */
10531 # define SYSCALL __syscall
10532 # define NUM2SYSCALLID(x) NUM2LONG(x)
10533 # define RETVAL2NUM(x) LONG2NUM(x)
10534 # if SIZEOF_LONG == 8
10535  long num, retval = -1;
10536 # elif SIZEOF_LONG_LONG == 8
10537  long long num, retval = -1;
10538 # else
10539 # error ---->> it is asserted that __syscall takes the first argument and returns retval in 64bit signed integer. <<----
10540 # endif
10541 #elif defined(__linux__)
10542 # define SYSCALL syscall
10543 # define NUM2SYSCALLID(x) NUM2LONG(x)
10544 # define RETVAL2NUM(x) LONG2NUM(x)
10545  /*
10546  * Linux man page says, syscall(2) function prototype is below.
10547  *
10548  * int syscall(int number, ...);
10549  *
10550  * But, it's incorrect. Actual one takes and returned long. (see unistd.h)
10551  */
10552  long num, retval = -1;
10553 #else
10554 # define SYSCALL syscall
10555 # define NUM2SYSCALLID(x) NUM2INT(x)
10556 # define RETVAL2NUM(x) INT2NUM(x)
10557  int num, retval = -1;
10558 #endif
10559  int i;
10560 
10561  if (RTEST(ruby_verbose)) {
10563  "We plan to remove a syscall function at future release. DL(Fiddle) provides safer alternative.");
10564  }
10565 
10566  if (argc == 0)
10567  rb_raise(rb_eArgError, "too few arguments for syscall");
10568  if (argc > numberof(arg))
10569  rb_raise(rb_eArgError, "too many arguments for syscall");
10570  num = NUM2SYSCALLID(argv[0]); ++argv;
10571  for (i = argc - 1; i--; ) {
10572  VALUE v = rb_check_string_type(argv[i]);
10573 
10574  if (!NIL_P(v)) {
10575  SafeStringValue(v);
10576  rb_str_modify(v);
10577  arg[i] = (VALUE)StringValueCStr(v);
10578  }
10579  else {
10580  arg[i] = (VALUE)NUM2LONG(argv[i]);
10581  }
10582  }
10583 
10584  switch (argc) {
10585  case 1:
10586  retval = SYSCALL(num);
10587  break;
10588  case 2:
10589  retval = SYSCALL(num, arg[0]);
10590  break;
10591  case 3:
10592  retval = SYSCALL(num, arg[0],arg[1]);
10593  break;
10594  case 4:
10595  retval = SYSCALL(num, arg[0],arg[1],arg[2]);
10596  break;
10597  case 5:
10598  retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3]);
10599  break;
10600  case 6:
10601  retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4]);
10602  break;
10603  case 7:
10604  retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5]);
10605  break;
10606  case 8:
10607  retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6]);
10608  break;
10609  }
10610 
10611  if (retval == -1)
10612  rb_sys_fail(0);
10613  return RETVAL2NUM(retval);
10614 #undef SYSCALL
10615 #undef NUM2SYSCALLID
10616 #undef RETVAL2NUM
10617 }
10618 #else
10619 #define rb_f_syscall rb_f_notimplement
10620 #endif
10621 
10622 static VALUE
10623 io_new_instance(VALUE args)
10624 {
10625  return rb_class_new_instance(2, (VALUE*)args+1, *(VALUE*)args);
10626 }
10627 
10628 static rb_encoding *
10629 find_encoding(VALUE v)
10630 {
10631  rb_encoding *enc = rb_find_encoding(v);
10632  if (!enc) rb_warn("Unsupported encoding %"PRIsVALUE" ignored", v);
10633  return enc;
10634 }
10635 
10636 static void
10637 io_encoding_set(rb_io_t *fptr, VALUE v1, VALUE v2, VALUE opt)
10638 {
10639  rb_encoding *enc, *enc2;
10640  int ecflags = fptr->encs.ecflags;
10641  VALUE ecopts, tmp;
10642 
10643  if (!NIL_P(v2)) {
10644  enc2 = find_encoding(v1);
10645  tmp = rb_check_string_type(v2);
10646  if (!NIL_P(tmp)) {
10647  if (RSTRING_LEN(tmp) == 1 && RSTRING_PTR(tmp)[0] == '-') {
10648  /* Special case - "-" => no transcoding */
10649  enc = enc2;
10650  enc2 = NULL;
10651  }
10652  else
10653  enc = find_encoding(v2);
10654  if (enc == enc2) {
10655  /* Special case - "-" => no transcoding */
10656  enc2 = NULL;
10657  }
10658  }
10659  else {
10660  enc = find_encoding(v2);
10661  if (enc == enc2) {
10662  /* Special case - "-" => no transcoding */
10663  enc2 = NULL;
10664  }
10665  }
10666  SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
10667  ecflags = rb_econv_prepare_options(opt, &ecopts, ecflags);
10668  }
10669  else {
10670  if (NIL_P(v1)) {
10671  /* Set to default encodings */
10672  rb_io_ext_int_to_encs(NULL, NULL, &enc, &enc2, 0);
10673  SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
10674  ecopts = Qnil;
10675  }
10676  else {
10677  tmp = rb_check_string_type(v1);
10678  if (!NIL_P(tmp) && rb_enc_asciicompat(enc = rb_enc_get(tmp))) {
10679  parse_mode_enc(RSTRING_PTR(tmp), enc, &enc, &enc2, NULL);
10680  SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
10681  ecflags = rb_econv_prepare_options(opt, &ecopts, ecflags);
10682  }
10683  else {
10684  rb_io_ext_int_to_encs(find_encoding(v1), NULL, &enc, &enc2, 0);
10685  SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
10686  ecopts = Qnil;
10687  }
10688  }
10689  }
10690  validate_enc_binmode(&fptr->mode, ecflags, enc, enc2);
10691  fptr->encs.enc = enc;
10692  fptr->encs.enc2 = enc2;
10693  fptr->encs.ecflags = ecflags;
10694  fptr->encs.ecopts = ecopts;
10695  clear_codeconv(fptr);
10696 
10697 }
10698 
10700  rb_io_t *fptr;
10701  VALUE v1;
10702  VALUE v2;
10703  VALUE opt;
10704 };
10705 
10706 static VALUE
10707 io_encoding_set_v(VALUE v)
10708 {
10709  struct io_encoding_set_args *arg = (struct io_encoding_set_args *)v;
10710  io_encoding_set(arg->fptr, arg->v1, arg->v2, arg->opt);
10711  return Qnil;
10712 }
10713 
10714 static VALUE
10715 pipe_pair_close(VALUE rw)
10716 {
10717  VALUE *rwp = (VALUE *)rw;
10718  return rb_ensure(io_close, rwp[0], io_close, rwp[1]);
10719 }
10720 
10721 /*
10722  * call-seq:
10723  * IO.pipe -> [read_io, write_io]
10724  * IO.pipe(ext_enc) -> [read_io, write_io]
10725  * IO.pipe("ext_enc:int_enc" [, opt]) -> [read_io, write_io]
10726  * IO.pipe(ext_enc, int_enc [, opt]) -> [read_io, write_io]
10727  *
10728  * IO.pipe(...) {|read_io, write_io| ... }
10729  *
10730  * Creates a pair of pipe endpoints (connected to each other) and
10731  * returns them as a two-element array of IO objects:
10732  * <code>[</code> <i>read_io</i>, <i>write_io</i> <code>]</code>.
10733  *
10734  * If a block is given, the block is called and
10735  * returns the value of the block.
10736  * <i>read_io</i> and <i>write_io</i> are sent to the block as arguments.
10737  * If read_io and write_io are not closed when the block exits, they are closed.
10738  * i.e. closing read_io and/or write_io doesn't cause an error.
10739  *
10740  * Not available on all platforms.
10741  *
10742  * If an encoding (encoding name or encoding object) is specified as an optional argument,
10743  * read string from pipe is tagged with the encoding specified.
10744  * If the argument is a colon separated two encoding names "A:B",
10745  * the read string is converted from encoding A (external encoding)
10746  * to encoding B (internal encoding), then tagged with B.
10747  * If two optional arguments are specified, those must be
10748  * encoding objects or encoding names,
10749  * and the first one is the external encoding,
10750  * and the second one is the internal encoding.
10751  * If the external encoding and the internal encoding is specified,
10752  * optional hash argument specify the conversion option.
10753  *
10754  * In the example below, the two processes close the ends of the pipe
10755  * that they are not using. This is not just a cosmetic nicety. The
10756  * read end of a pipe will not generate an end of file condition if
10757  * there are any writers with the pipe still open. In the case of the
10758  * parent process, the <code>rd.read</code> will never return if it
10759  * does not first issue a <code>wr.close</code>.
10760  *
10761  * rd, wr = IO.pipe
10762  *
10763  * if fork
10764  * wr.close
10765  * puts "Parent got: <#{rd.read}>"
10766  * rd.close
10767  * Process.wait
10768  * else
10769  * rd.close
10770  * puts "Sending message to parent"
10771  * wr.write "Hi Dad"
10772  * wr.close
10773  * end
10774  *
10775  * <em>produces:</em>
10776  *
10777  * Sending message to parent
10778  * Parent got: <Hi Dad>
10779  */
10780 
10781 static VALUE
10782 rb_io_s_pipe(int argc, VALUE *argv, VALUE klass)
10783 {
10784  int pipes[2], state;
10785  VALUE r, w, args[3], v1, v2;
10786  VALUE opt;
10787  rb_io_t *fptr, *fptr2;
10788  struct io_encoding_set_args ies_args;
10789  int fmode = 0;
10790  VALUE ret;
10791 
10792  argc = rb_scan_args(argc, argv, "02:", &v1, &v2, &opt);
10793  if (rb_pipe(pipes) < 0)
10794  rb_sys_fail(0);
10795 
10796  args[0] = klass;
10797  args[1] = INT2NUM(pipes[0]);
10798  args[2] = INT2FIX(O_RDONLY);
10799  r = rb_protect(io_new_instance, (VALUE)args, &state);
10800  if (state) {
10801  close(pipes[0]);
10802  close(pipes[1]);
10803  rb_jump_tag(state);
10804  }
10805  GetOpenFile(r, fptr);
10806 
10807  ies_args.fptr = fptr;
10808  ies_args.v1 = v1;
10809  ies_args.v2 = v2;
10810  ies_args.opt = opt;
10811  rb_protect(io_encoding_set_v, (VALUE)&ies_args, &state);
10812  if (state) {
10813  close(pipes[1]);
10814  io_close(r);
10815  rb_jump_tag(state);
10816  }
10817 
10818  args[1] = INT2NUM(pipes[1]);
10819  args[2] = INT2FIX(O_WRONLY);
10820  w = rb_protect(io_new_instance, (VALUE)args, &state);
10821  if (state) {
10822  close(pipes[1]);
10823  if (!NIL_P(r)) rb_io_close(r);
10824  rb_jump_tag(state);
10825  }
10826  GetOpenFile(w, fptr2);
10827  rb_io_synchronized(fptr2);
10828 
10829  extract_binmode(opt, &fmode);
10830 
10831  if ((fmode & FMODE_BINMODE) && NIL_P(v1)) {
10834  }
10835 
10836 #if DEFAULT_TEXTMODE
10837  if ((fptr->mode & FMODE_TEXTMODE) && (fmode & FMODE_BINMODE)) {
10838  fptr->mode &= ~FMODE_TEXTMODE;
10839  setmode(fptr->fd, O_BINARY);
10840  }
10841 #if RUBY_CRLF_ENVIRONMENT
10844  }
10845 #endif
10846 #endif
10847  fptr->mode |= fmode;
10848 #if DEFAULT_TEXTMODE
10849  if ((fptr2->mode & FMODE_TEXTMODE) && (fmode & FMODE_BINMODE)) {
10850  fptr2->mode &= ~FMODE_TEXTMODE;
10851  setmode(fptr2->fd, O_BINARY);
10852  }
10853 #endif
10854  fptr2->mode |= fmode;
10855 
10856  ret = rb_assoc_new(r, w);
10857  if (rb_block_given_p()) {
10858  VALUE rw[2];
10859  rw[0] = r;
10860  rw[1] = w;
10861  return rb_ensure(rb_yield, ret, pipe_pair_close, (VALUE)rw);
10862  }
10863  return ret;
10864 }
10865 
10866 struct foreach_arg {
10867  int argc;
10868  VALUE *argv;
10869  VALUE io;
10870 };
10871 
10872 static void
10873 open_key_args(VALUE klass, int argc, VALUE *argv, VALUE opt, struct foreach_arg *arg)
10874 {
10875  VALUE path, v;
10876  VALUE vmode = Qnil, vperm = Qnil;
10877 
10878  path = *argv++;
10879  argc--;
10880  FilePathValue(path);
10881  arg->io = 0;
10882  arg->argc = argc;
10883  arg->argv = argv;
10884  if (NIL_P(opt)) {
10885  vmode = INT2NUM(O_RDONLY);
10886  vperm = INT2FIX(0666);
10887  }
10888  else if (!NIL_P(v = rb_hash_aref(opt, sym_open_args))) {
10889  int n;
10890 
10891  v = rb_to_array_type(v);
10892  n = RARRAY_LENINT(v);
10893  rb_check_arity(n, 0, 3); /* rb_io_open */
10894  rb_scan_args_kw(RB_SCAN_ARGS_LAST_HASH_KEYWORDS, n, RARRAY_CONST_PTR(v), "02:", &vmode, &vperm, &opt);
10895  }
10896  arg->io = rb_io_open(klass, path, vmode, vperm, opt);
10897 }
10898 
10899 static VALUE
10900 io_s_foreach(VALUE v)
10901 {
10902  struct getline_arg *arg = (void *)v;
10903  VALUE str;
10904 
10905  while (!NIL_P(str = rb_io_getline_1(arg->rs, arg->limit, arg->chomp, arg->io))) {
10906  rb_lastline_set(str);
10907  rb_yield(str);
10908  }
10910  return Qnil;
10911 }
10912 
10913 /*
10914  * call-seq:
10915  * IO.foreach(name, sep=$/ [, getline_args, open_args]) {|line| block } -> nil
10916  * IO.foreach(name, limit [, getline_args, open_args]) {|line| block } -> nil
10917  * IO.foreach(name, sep, limit [, getline_args, open_args]) {|line| block } -> nil
10918  * IO.foreach(...) -> an_enumerator
10919  * File.foreach(name, sep=$/ [, getline_args, open_args]) {|line| block } -> nil
10920  * File.foreach(name, limit [, getline_args, open_args]) {|line| block } -> nil
10921  * File.foreach(name, sep, limit [, getline_args, open_args]) {|line| block } -> nil
10922  * File.foreach(...) -> an_enumerator
10923  *
10924  * Executes the block for every line in the named I/O port, where lines
10925  * are separated by <em>sep</em>.
10926  *
10927  * If no block is given, an enumerator is returned instead.
10928  *
10929  * If +name+ starts with a pipe character (<code>"|"</code>) and the receiver
10930  * is the IO class, a subprocess is created in the same way as Kernel#open,
10931  * and its output is returned.
10932  * Consider to use File.foreach to disable the behavior of subprocess invocation.
10933  *
10934  * File.foreach("testfile") {|x| print "GOT ", x }
10935  * IO.foreach("| cat testfile") {|x| print "GOT ", x }
10936  *
10937  * <em>produces:</em>
10938  *
10939  * GOT This is line one
10940  * GOT This is line two
10941  * GOT This is line three
10942  * GOT And so on...
10943  *
10944  * If the last argument is a hash, it's the keyword argument to open.
10945  * See IO.readlines for details about getline_args.
10946  * And see also IO.read for details about open_args.
10947  *
10948  */
10949 
10950 static VALUE
10951 rb_io_s_foreach(int argc, VALUE *argv, VALUE self)
10952 {
10953  VALUE opt;
10954  int orig_argc = argc;
10955  struct foreach_arg arg;
10956  struct getline_arg garg;
10957 
10958  argc = rb_scan_args(argc, argv, "13:", NULL, NULL, NULL, NULL, &opt);
10959  RETURN_ENUMERATOR(self, orig_argc, argv);
10960  extract_getline_args(argc-1, argv+1, &garg);
10961  open_key_args(self, argc, argv, opt, &arg);
10962  if (NIL_P(arg.io)) return Qnil;
10963  extract_getline_opts(opt, &garg);
10964  check_getline_args(&garg.rs, &garg.limit, garg.io = arg.io);
10965  return rb_ensure(io_s_foreach, (VALUE)&garg, rb_io_close, arg.io);
10966 }
10967 
10968 static VALUE
10969 io_s_readlines(VALUE v)
10970 {
10971  struct getline_arg *arg = (void *)v;
10972  return io_readlines(arg, arg->io);
10973 }
10974 
10975 /*
10976  * call-seq:
10977  * IO.readlines(name, sep=$/ [, getline_args, open_args]) -> array
10978  * IO.readlines(name, limit [, getline_args, open_args]) -> array
10979  * IO.readlines(name, sep, limit [, getline_args, open_args]) -> array
10980  * File.readlines(name, sep=$/ [, getline_args, open_args]) -> array
10981  * File.readlines(name, limit [, getline_args, open_args]) -> array
10982  * File.readlines(name, sep, limit [, getline_args, open_args]) -> array
10983  *
10984  * Reads the entire file specified by <i>name</i> as individual
10985  * lines, and returns those lines in an array. Lines are separated by
10986  * <i>sep</i>.
10987  *
10988  * If +name+ starts with a pipe character (<code>"|"</code>) and the receiver
10989  * is the IO class, a subprocess is created in the same way as Kernel#open,
10990  * and its output is returned.
10991  * Consider to use File.readlines to disable the behavior of subprocess invocation.
10992  *
10993  * a = File.readlines("testfile")
10994  * a[0] #=> "This is line one\n"
10995  *
10996  * b = File.readlines("testfile", chomp: true)
10997  * b[0] #=> "This is line one"
10998  *
10999  * IO.readlines("|ls -a") #=> [".\n", "..\n", ...]
11000  *
11001  * If the last argument is a hash, it's the keyword argument to open.
11002  *
11003  * === Options for getline
11004  *
11005  * The options hash accepts the following keys:
11006  *
11007  * :chomp::
11008  * When the optional +chomp+ keyword argument has a true value,
11009  * <code>\n</code>, <code>\r</code>, and <code>\r\n</code>
11010  * will be removed from the end of each line.
11011  *
11012  * See also IO.read for details about +name+ and open_args.
11013  */
11014 
11015 static VALUE
11016 rb_io_s_readlines(int argc, VALUE *argv, VALUE io)
11017 {
11018  VALUE opt;
11019  struct foreach_arg arg;
11020  struct getline_arg garg;
11021 
11022  argc = rb_scan_args(argc, argv, "13:", NULL, NULL, NULL, NULL, &opt);
11023  extract_getline_args(argc-1, argv+1, &garg);
11024  open_key_args(io, argc, argv, opt, &arg);
11025  if (NIL_P(arg.io)) return Qnil;
11026  extract_getline_opts(opt, &garg);
11027  check_getline_args(&garg.rs, &garg.limit, garg.io = arg.io);
11028  return rb_ensure(io_s_readlines, (VALUE)&garg, rb_io_close, arg.io);
11029 }
11030 
11031 static VALUE
11032 io_s_read(VALUE v)
11033 {
11034  struct foreach_arg *arg = (void *)v;
11035  return io_read(arg->argc, arg->argv, arg->io);
11036 }
11037 
11038 struct seek_arg {
11039  VALUE io;
11040  VALUE offset;
11041  int mode;
11042 };
11043 
11044 static VALUE
11045 seek_before_access(VALUE argp)
11046 {
11047  struct seek_arg *arg = (struct seek_arg *)argp;
11048  rb_io_binmode(arg->io);
11049  return rb_io_seek(arg->io, arg->offset, arg->mode);
11050 }
11051 
11052 /*
11053  * call-seq:
11054  * IO.read(name, [length [, offset]] [, opt]) -> string
11055  * File.read(name, [length [, offset]] [, opt]) -> string
11056  *
11057  * Opens the file, optionally seeks to the given +offset+, then returns
11058  * +length+ bytes (defaulting to the rest of the file). #read ensures
11059  * the file is closed before returning.
11060  *
11061  * If +name+ starts with a pipe character (<code>"|"</code>) and the receiver
11062  * is the IO class, a subprocess is created in the same way as Kernel#open,
11063  * and its output is returned.
11064  * Consider to use File.read to disable the behavior of subprocess invocation.
11065  *
11066  * === Options
11067  *
11068  * The options hash accepts the following keys:
11069  *
11070  * :encoding::
11071  * string or encoding
11072  *
11073  * Specifies the encoding of the read string. +:encoding+ will be ignored
11074  * if +length+ is specified. See Encoding.aliases for possible encodings.
11075  *
11076  * :mode::
11077  * string or integer
11078  *
11079  * Specifies the <i>mode</i> argument for open(). It must start
11080  * with an "r", otherwise it will cause an error.
11081  * See IO.new for the list of possible modes.
11082  *
11083  * :open_args::
11084  * array
11085  *
11086  * Specifies arguments for open() as an array. This key can not be used
11087  * in combination with either +:encoding+ or +:mode+.
11088  *
11089  * Examples:
11090  *
11091  * File.read("testfile") #=> "This is line one\nThis is line two\nThis is line three\nAnd so on...\n"
11092  * File.read("testfile", 20) #=> "This is line one\nThi"
11093  * File.read("testfile", 20, 10) #=> "ne one\nThis is line "
11094  * File.read("binfile", mode: "rb") #=> "\xF7\x00\x00\x0E\x12"
11095  * IO.read("|ls -a") #=> ".\n..\n"...
11096  */
11097 
11098 static VALUE
11099 rb_io_s_read(int argc, VALUE *argv, VALUE io)
11100 {
11101  VALUE opt, offset;
11102  struct foreach_arg arg;
11103 
11104  argc = rb_scan_args(argc, argv, "13:", NULL, NULL, &offset, NULL, &opt);
11105  open_key_args(io, argc, argv, opt, &arg);
11106  if (NIL_P(arg.io)) return Qnil;
11107  if (!NIL_P(offset)) {
11108  struct seek_arg sarg;
11109  int state = 0;
11110  sarg.io = arg.io;
11111  sarg.offset = offset;
11112  sarg.mode = SEEK_SET;
11113  rb_protect(seek_before_access, (VALUE)&sarg, &state);
11114  if (state) {
11115  rb_io_close(arg.io);
11116  rb_jump_tag(state);
11117  }
11118  if (arg.argc == 2) arg.argc = 1;
11119  }
11120  return rb_ensure(io_s_read, (VALUE)&arg, rb_io_close, arg.io);
11121 }
11122 
11123 /*
11124  * call-seq:
11125  * IO.binread(name, [length [, offset]]) -> string
11126  * File.binread(name, [length [, offset]]) -> string
11127  *
11128  * Opens the file, optionally seeks to the given <i>offset</i>, then
11129  * returns <i>length</i> bytes (defaulting to the rest of the file).
11130  * #binread ensures the file is closed before returning. The open mode
11131  * would be <code>"rb:ASCII-8BIT"</code>.
11132  *
11133  * If +name+ starts with a pipe character (<code>"|"</code>) and the receiver
11134  * is the IO class, a subprocess is created in the same way as Kernel#open,
11135  * and its output is returned.
11136  * Consider to use File.binread to disable the behavior of subprocess invocation.
11137  *
11138  * File.binread("testfile") #=> "This is line one\nThis is line two\nThis is line three\nAnd so on...\n"
11139  * File.binread("testfile", 20) #=> "This is line one\nThi"
11140  * File.binread("testfile", 20, 10) #=> "ne one\nThis is line "
11141  * IO.binread("| cat testfile") #=> "This is line one\nThis is line two\nThis is line three\nAnd so on...\n"
11142  *
11143  * See also IO.read for details about +name+ and open_args.
11144  */
11145 
11146 static VALUE
11147 rb_io_s_binread(int argc, VALUE *argv, VALUE io)
11148 {
11149  VALUE offset;
11150  struct foreach_arg arg;
11151  enum {
11152  fmode = FMODE_READABLE|FMODE_BINMODE,
11153  oflags = O_RDONLY
11154 #ifdef O_BINARY
11155  |O_BINARY
11156 #endif
11157  };
11158  convconfig_t convconfig = {NULL, NULL, 0, Qnil};
11159 
11160  rb_scan_args(argc, argv, "12", NULL, NULL, &offset);
11161  FilePathValue(argv[0]);
11162  convconfig.enc = rb_ascii8bit_encoding();
11163  arg.io = rb_io_open_generic(io, argv[0], oflags, fmode, &convconfig, 0);
11164  if (NIL_P(arg.io)) return Qnil;
11165  arg.argv = argv+1;
11166  arg.argc = (argc > 1) ? 1 : 0;
11167  if (!NIL_P(offset)) {
11168  struct seek_arg sarg;
11169  int state = 0;
11170  sarg.io = arg.io;
11171  sarg.offset = offset;
11172  sarg.mode = SEEK_SET;
11173  rb_protect(seek_before_access, (VALUE)&sarg, &state);
11174  if (state) {
11175  rb_io_close(arg.io);
11176  rb_jump_tag(state);
11177  }
11178  }
11179  return rb_ensure(io_s_read, (VALUE)&arg, rb_io_close, arg.io);
11180 }
11181 
11182 static VALUE
11183 io_s_write0(VALUE v)
11184 {
11185  struct write_arg *arg = (void *)v;
11186  return io_write(arg->io,arg->str,arg->nosync);
11187 }
11188 
11189 static VALUE
11190 io_s_write(int argc, VALUE *argv, VALUE klass, int binary)
11191 {
11192  VALUE string, offset, opt;
11193  struct foreach_arg arg;
11194  struct write_arg warg;
11195 
11196  rb_scan_args(argc, argv, "21:", NULL, &string, &offset, &opt);
11197 
11198  if (NIL_P(opt)) opt = rb_hash_new();
11199  else opt = rb_hash_dup(opt);
11200 
11201 
11202  if (NIL_P(rb_hash_aref(opt,sym_mode))) {
11203  int mode = O_WRONLY|O_CREAT;
11204 #ifdef O_BINARY
11205  if (binary) mode |= O_BINARY;
11206 #endif
11207  if (NIL_P(offset)) mode |= O_TRUNC;
11208  rb_hash_aset(opt,sym_mode,INT2NUM(mode));
11209  }
11210  open_key_args(klass, argc, argv, opt, &arg);
11211 
11212 #ifndef O_BINARY
11213  if (binary) rb_io_binmode_m(arg.io);
11214 #endif
11215 
11216  if (NIL_P(arg.io)) return Qnil;
11217  if (!NIL_P(offset)) {
11218  struct seek_arg sarg;
11219  int state = 0;
11220  sarg.io = arg.io;
11221  sarg.offset = offset;
11222  sarg.mode = SEEK_SET;
11223  rb_protect(seek_before_access, (VALUE)&sarg, &state);
11224  if (state) {
11225  rb_io_close(arg.io);
11226  rb_jump_tag(state);
11227  }
11228  }
11229 
11230  warg.io = arg.io;
11231  warg.str = string;
11232  warg.nosync = 0;
11233 
11234  return rb_ensure(io_s_write0, (VALUE)&warg, rb_io_close, arg.io);
11235 }
11236 
11237 /*
11238  * call-seq:
11239  * IO.write(name, string [, offset]) -> integer
11240  * IO.write(name, string [, offset] [, opt]) -> integer
11241  * File.write(name, string [, offset]) -> integer
11242  * File.write(name, string [, offset] [, opt]) -> integer
11243  *
11244  * Opens the file, optionally seeks to the given <i>offset</i>, writes
11245  * <i>string</i>, then returns the length written. #write ensures the
11246  * file is closed before returning. If <i>offset</i> is not given in
11247  * write mode, the file is truncated. Otherwise, it is not truncated.
11248  *
11249  * If +name+ starts with a pipe character (<code>"|"</code>) and the receiver
11250  * is the IO class, a subprocess is created in the same way as Kernel#open,
11251  * and its output is returned.
11252  * Consider to use File.write to disable the behavior of subprocess invocation.
11253  *
11254  * File.write("testfile", "0123456789", 20) #=> 10
11255  * # File could contain: "This is line one\nThi0123456789two\nThis is line three\nAnd so on...\n"
11256  * File.write("testfile", "0123456789") #=> 10
11257  * # File would now read: "0123456789"
11258  * IO.write("|tr a-z A-Z", "abc") #=> 3
11259  * # Prints "ABC" to the standard output
11260  *
11261  * If the last argument is a hash, it specifies options for the internal
11262  * open(). It accepts the following keys:
11263  *
11264  * :encoding::
11265  * string or encoding
11266  *
11267  * Specifies the encoding of the read string.
11268  * See Encoding.aliases for possible encodings.
11269  *
11270  * :mode::
11271  * string or integer
11272  *
11273  * Specifies the <i>mode</i> argument for open(). It must start
11274  * with "w", "a", or "r+", otherwise it will cause an error.
11275  * See IO.new for the list of possible modes.
11276  *
11277  * :perm::
11278  * integer
11279  *
11280  * Specifies the <i>perm</i> argument for open().
11281  *
11282  * :open_args::
11283  * array
11284  *
11285  * Specifies arguments for open() as an array.
11286  * This key can not be used in combination with other keys.
11287  *
11288  * See also IO.read for details about +name+ and open_args.
11289  */
11290 
11291 static VALUE
11292 rb_io_s_write(int argc, VALUE *argv, VALUE io)
11293 {
11294  return io_s_write(argc, argv, io, 0);
11295 }
11296 
11297 /*
11298  * call-seq:
11299  * IO.binwrite(name, string, [offset]) -> integer
11300  * IO.binwrite(name, string, [offset], open_args) -> integer
11301  * File.binwrite(name, string, [offset]) -> integer
11302  * File.binwrite(name, string, [offset], open_args) -> integer
11303  *
11304  * Same as IO.write except opening the file in binary mode and
11305  * ASCII-8BIT encoding (<code>"wb:ASCII-8BIT"</code>).
11306  *
11307  * If +name+ starts with a pipe character (<code>"|"</code>) and the receiver
11308  * is the IO class, a subprocess is created in the same way as Kernel#open,
11309  * and its output is returned.
11310  * Consider to use File.binwrite to disable the behavior of subprocess invocation.
11311  *
11312  * See also IO.read for details about +name+ and open_args.
11313  */
11314 
11315 static VALUE
11316 rb_io_s_binwrite(int argc, VALUE *argv, VALUE io)
11317 {
11318  return io_s_write(argc, argv, io, 1);
11319 }
11320 
11322  VALUE src;
11323  VALUE dst;
11324  off_t copy_length; /* (off_t)-1 if not specified */
11325  off_t src_offset; /* (off_t)-1 if not specified */
11326 
11327  rb_io_t *src_fptr;
11328  rb_io_t *dst_fptr;
11329  unsigned close_src : 1;
11330  unsigned close_dst : 1;
11331  int error_no;
11332  off_t total;
11333  const char *syserr;
11334  const char *notimp;
11335  VALUE th;
11336  struct stat src_stat;
11337  struct stat dst_stat;
11338 #ifdef HAVE_FCOPYFILE
11339  copyfile_state_t copyfile_state;
11340 #endif
11341 };
11342 
11343 static void *
11344 exec_interrupts(void *arg)
11345 {
11346  VALUE th = (VALUE)arg;
11347  rb_thread_execute_interrupts(th);
11348  return NULL;
11349 }
11350 
11351 /*
11352  * returns TRUE if the preceding system call was interrupted
11353  * so we can continue. If the thread was interrupted, we
11354  * reacquire the GVL to execute interrupts before continuing.
11355  */
11356 static int
11357 maygvl_copy_stream_continue_p(int has_gvl, struct copy_stream_struct *stp)
11358 {
11359  switch (errno) {
11360  case EINTR:
11361 #if defined(ERESTART)
11362  case ERESTART:
11363 #endif
11364  if (rb_thread_interrupted(stp->th)) {
11365  if (has_gvl)
11366  rb_thread_execute_interrupts(stp->th);
11367  else
11368  rb_thread_call_with_gvl(exec_interrupts, (void *)stp->th);
11369  }
11370  return TRUE;
11371  }
11372  return FALSE;
11373 }
11374 
11376  VALUE scheduler;
11377 
11378  rb_io_t *fptr;
11379  short events;
11380 
11381  VALUE result;
11382 };
11383 
11384 static void *
11385 rb_thread_fiber_scheduler_wait_for(void * _args)
11386 {
11387  struct wait_for_single_fd *args = (struct wait_for_single_fd *)_args;
11388 
11389  args->result = rb_fiber_scheduler_io_wait(args->scheduler, args->fptr->self, INT2NUM(args->events), Qnil);
11390 
11391  return NULL;
11392 }
11393 
11394 #if USE_POLL
11395 # define IOWAIT_SYSCALL "poll"
11396 STATIC_ASSERT(pollin_expected, POLLIN == RB_WAITFD_IN);
11397 STATIC_ASSERT(pollout_expected, POLLOUT == RB_WAITFD_OUT);
11398 static int
11399 nogvl_wait_for(VALUE th, rb_io_t *fptr, short events)
11400 {
11402  if (scheduler != Qnil) {
11403  struct wait_for_single_fd args = {.scheduler = scheduler, .fptr = fptr, .events = events};
11404  rb_thread_call_with_gvl(rb_thread_fiber_scheduler_wait_for, &args);
11405  return RTEST(args.result);
11406  }
11407 
11408  int fd = fptr->fd;
11409  if (fd == -1) return 0;
11410 
11411  struct pollfd fds;
11412 
11413  fds.fd = fd;
11414  fds.events = events;
11415 
11416  return poll(&fds, 1, -1);
11417 }
11418 #else /* !USE_POLL */
11419 # define IOWAIT_SYSCALL "select"
11420 static int
11421 nogvl_wait_for(VALUE th, rb_io_t *fptr, short events)
11422 {
11424  if (scheduler != Qnil) {
11425  struct wait_for_single_fd args = {.scheduler = scheduler, .fptr = fptr, .events = events};
11426  rb_thread_call_with_gvl(rb_thread_fiber_scheduler_wait_for, &args);
11427  return RTEST(args.result);
11428  }
11429 
11430  int fd = fptr->fd;
11431  if (fd == -1) return 0;
11432 
11433  rb_fdset_t fds;
11434  int ret;
11435 
11436  rb_fd_init(&fds);
11437  rb_fd_set(fd, &fds);
11438 
11439  switch (events) {
11440  case RB_WAITFD_IN:
11441  ret = rb_fd_select(fd + 1, &fds, 0, 0, 0);
11442  break;
11443  case RB_WAITFD_OUT:
11444  ret = rb_fd_select(fd + 1, 0, &fds, 0, 0);
11445  break;
11446  default:
11447  VM_UNREACHABLE(nogvl_wait_for);
11448  }
11449 
11450  rb_fd_term(&fds);
11451  return ret;
11452 }
11453 #endif /* !USE_POLL */
11454 
11455 static int
11456 maygvl_copy_stream_wait_read(int has_gvl, struct copy_stream_struct *stp)
11457 {
11458  int ret;
11459 
11460  do {
11461  if (has_gvl) {
11463  }
11464  else {
11465  ret = nogvl_wait_for(stp->th, stp->src_fptr, RB_WAITFD_IN);
11466  }
11467  } while (ret < 0 && maygvl_copy_stream_continue_p(has_gvl, stp));
11468 
11469  if (ret < 0) {
11470  stp->syserr = IOWAIT_SYSCALL;
11471  stp->error_no = errno;
11472  return ret;
11473  }
11474  return 0;
11475 }
11476 
11477 static int
11478 nogvl_copy_stream_wait_write(struct copy_stream_struct *stp)
11479 {
11480  int ret;
11481 
11482  do {
11483  ret = nogvl_wait_for(stp->th, stp->dst_fptr, RB_WAITFD_OUT);
11484  } while (ret < 0 && maygvl_copy_stream_continue_p(0, stp));
11485 
11486  if (ret < 0) {
11487  stp->syserr = IOWAIT_SYSCALL;
11488  stp->error_no = errno;
11489  return ret;
11490  }
11491  return 0;
11492 }
11493 
11494 #ifdef USE_COPY_FILE_RANGE
11495 
11496 static ssize_t
11497 simple_copy_file_range(int in_fd, off_t *in_offset, int out_fd, off_t *out_offset, size_t count, unsigned int flags)
11498 {
11499 #ifdef HAVE_COPY_FILE_RANGE
11500  return copy_file_range(in_fd, in_offset, out_fd, out_offset, count, flags);
11501 #else
11502  return syscall(__NR_copy_file_range, in_fd, in_offset, out_fd, out_offset, count, flags);
11503 #endif
11504 }
11505 
11506 static int
11507 nogvl_copy_file_range(struct copy_stream_struct *stp)
11508 {
11509  ssize_t ss;
11510  off_t src_size;
11511  off_t copy_length, src_offset, *src_offset_ptr;
11512 
11513  if (!S_ISREG(stp->src_stat.st_mode))
11514  return 0;
11515 
11516  src_size = stp->src_stat.st_size;
11517  src_offset = stp->src_offset;
11518  if (src_offset >= (off_t)0) {
11519  src_offset_ptr = &src_offset;
11520  }
11521  else {
11522  src_offset_ptr = NULL; /* if src_offset_ptr is NULL, then bytes are read from in_fd starting from the file offset */
11523  }
11524 
11525  copy_length = stp->copy_length;
11526  if (copy_length < (off_t)0) {
11527  if (src_offset < (off_t)0) {
11528  off_t current_offset;
11529  errno = 0;
11530  current_offset = lseek(stp->src_fptr->fd, 0, SEEK_CUR);
11531  if (current_offset < (off_t)0 && errno) {
11532  stp->syserr = "lseek";
11533  stp->error_no = errno;
11534  return (int)current_offset;
11535  }
11536  copy_length = src_size - current_offset;
11537  }
11538  else {
11539  copy_length = src_size - src_offset;
11540  }
11541  }
11542 
11543  retry_copy_file_range:
11544 # if SIZEOF_OFF_T > SIZEOF_SIZE_T
11545  /* we are limited by the 32-bit ssize_t return value on 32-bit */
11546  ss = (copy_length > (off_t)SSIZE_MAX) ? SSIZE_MAX : (ssize_t)copy_length;
11547 # else
11548  ss = (ssize_t)copy_length;
11549 # endif
11550  ss = simple_copy_file_range(stp->src_fptr->fd, src_offset_ptr, stp->dst_fptr->fd, NULL, ss, 0);
11551  if (0 < ss) {
11552  stp->total += ss;
11553  copy_length -= ss;
11554  if (0 < copy_length) {
11555  goto retry_copy_file_range;
11556  }
11557  }
11558  if (ss < 0) {
11559  if (maygvl_copy_stream_continue_p(0, stp)) {
11560  goto retry_copy_file_range;
11561  }
11562  switch (errno) {
11563  case EINVAL:
11564  case EPERM: /* copy_file_range(2) doesn't exist (may happen in
11565  docker container) */
11566 #ifdef ENOSYS
11567  case ENOSYS:
11568 #endif
11569 #ifdef EXDEV
11570  case EXDEV: /* in_fd and out_fd are not on the same filesystem */
11571 #endif
11572  return 0;
11573  case EAGAIN:
11574 #if EWOULDBLOCK != EAGAIN
11575  case EWOULDBLOCK:
11576 #endif
11577  {
11578  int ret = nogvl_copy_stream_wait_write(stp);
11579  if (ret < 0) return ret;
11580  }
11581  goto retry_copy_file_range;
11582  case EBADF:
11583  {
11584  int e = errno;
11585  int flags = fcntl(stp->dst_fptr->fd, F_GETFL);
11586 
11587  if (flags != -1 && flags & O_APPEND) {
11588  return 0;
11589  }
11590  errno = e;
11591  }
11592  }
11593  stp->syserr = "copy_file_range";
11594  stp->error_no = errno;
11595  return (int)ss;
11596  }
11597  return 1;
11598 }
11599 #endif
11600 
11601 #ifdef HAVE_FCOPYFILE
11602 static int
11603 nogvl_fcopyfile(struct copy_stream_struct *stp)
11604 {
11605  off_t cur, ss = 0;
11606  const off_t src_offset = stp->src_offset;
11607  int ret;
11608 
11609  if (stp->copy_length >= (off_t)0) {
11610  /* copy_length can't be specified in fcopyfile(3) */
11611  return 0;
11612  }
11613 
11614  if (!S_ISREG(stp->src_stat.st_mode))
11615  return 0;
11616 
11617  if (!S_ISREG(stp->dst_stat.st_mode))
11618  return 0;
11619  if (lseek(stp->dst_fptr->fd, 0, SEEK_CUR) > (off_t)0) /* if dst IO was already written */
11620  return 0;
11621  if (fcntl(stp->dst_fptr->fd, F_GETFL) & O_APPEND) {
11622  /* fcopyfile(3) appends src IO to dst IO and then truncates
11623  * dst IO to src IO's original size. */
11624  off_t end = lseek(stp->dst_fptr->fd, 0, SEEK_END);
11625  lseek(stp->dst_fptr->fd, 0, SEEK_SET);
11626  if (end > (off_t)0) return 0;
11627  }
11628 
11629  if (src_offset > (off_t)0) {
11630  off_t r;
11631 
11632  /* get current offset */
11633  errno = 0;
11634  cur = lseek(stp->src_fptr->fd, 0, SEEK_CUR);
11635  if (cur < (off_t)0 && errno) {
11636  stp->error_no = errno;
11637  return 1;
11638  }
11639 
11640  errno = 0;
11641  r = lseek(stp->src_fptr->fd, src_offset, SEEK_SET);
11642  if (r < (off_t)0 && errno) {
11643  stp->error_no = errno;
11644  return 1;
11645  }
11646  }
11647 
11648  stp->copyfile_state = copyfile_state_alloc(); /* this will be freed by copy_stream_finalize() */
11649  ret = fcopyfile(stp->src_fptr->fd, stp->dst_fptr->fd, stp->copyfile_state, COPYFILE_DATA);
11650  copyfile_state_get(stp->copyfile_state, COPYFILE_STATE_COPIED, &ss); /* get copied bytes */
11651 
11652  if (ret == 0) { /* success */
11653  stp->total = ss;
11654  if (src_offset > (off_t)0) {
11655  off_t r;
11656  errno = 0;
11657  /* reset offset */
11658  r = lseek(stp->src_fptr->fd, cur, SEEK_SET);
11659  if (r < (off_t)0 && errno) {
11660  stp->error_no = errno;
11661  return 1;
11662  }
11663  }
11664  }
11665  else {
11666  switch (errno) {
11667  case ENOTSUP:
11668  case EPERM:
11669  case EINVAL:
11670  return 0;
11671  }
11672  stp->syserr = "fcopyfile";
11673  stp->error_no = errno;
11674  return (int)ret;
11675  }
11676  return 1;
11677 }
11678 #endif
11679 
11680 #ifdef HAVE_SENDFILE
11681 
11682 # ifdef __linux__
11683 # define USE_SENDFILE
11684 
11685 # ifdef HAVE_SYS_SENDFILE_H
11686 # include <sys/sendfile.h>
11687 # endif
11688 
11689 static ssize_t
11690 simple_sendfile(int out_fd, int in_fd, off_t *offset, off_t count)
11691 {
11692  return sendfile(out_fd, in_fd, offset, (size_t)count);
11693 }
11694 
11695 # elif 0 /* defined(__FreeBSD__) || defined(__DragonFly__) */ || defined(__APPLE__)
11696 /* This runs on FreeBSD8.1 r30210, but sendfiles blocks its execution
11697  * without cpuset -l 0.
11698  */
11699 # define USE_SENDFILE
11700 
11701 static ssize_t
11702 simple_sendfile(int out_fd, int in_fd, off_t *offset, off_t count)
11703 {
11704  int r;
11705  off_t pos = offset ? *offset : lseek(in_fd, 0, SEEK_CUR);
11706  off_t sbytes;
11707 # ifdef __APPLE__
11708  r = sendfile(in_fd, out_fd, pos, &count, NULL, 0);
11709  sbytes = count;
11710 # else
11711  r = sendfile(in_fd, out_fd, pos, (size_t)count, NULL, &sbytes, 0);
11712 # endif
11713  if (r != 0 && sbytes == 0) return r;
11714  if (offset) {
11715  *offset += sbytes;
11716  }
11717  else {
11718  lseek(in_fd, sbytes, SEEK_CUR);
11719  }
11720  return (ssize_t)sbytes;
11721 }
11722 
11723 # endif
11724 
11725 #endif
11726 
11727 #ifdef USE_SENDFILE
11728 static int
11729 nogvl_copy_stream_sendfile(struct copy_stream_struct *stp)
11730 {
11731  ssize_t ss;
11732  off_t src_size;
11733  off_t copy_length;
11734  off_t src_offset;
11735  int use_pread;
11736 
11737  if (!S_ISREG(stp->src_stat.st_mode))
11738  return 0;
11739 
11740  src_size = stp->src_stat.st_size;
11741 #ifndef __linux__
11742  if ((stp->dst_stat.st_mode & S_IFMT) != S_IFSOCK)
11743  return 0;
11744 #endif
11745 
11746  src_offset = stp->src_offset;
11747  use_pread = src_offset >= (off_t)0;
11748 
11749  copy_length = stp->copy_length;
11750  if (copy_length < (off_t)0) {
11751  if (use_pread)
11752  copy_length = src_size - src_offset;
11753  else {
11754  off_t cur;
11755  errno = 0;
11756  cur = lseek(stp->src_fptr->fd, 0, SEEK_CUR);
11757  if (cur < (off_t)0 && errno) {
11758  stp->syserr = "lseek";
11759  stp->error_no = errno;
11760  return (int)cur;
11761  }
11762  copy_length = src_size - cur;
11763  }
11764  }
11765 
11766  retry_sendfile:
11767 # if SIZEOF_OFF_T > SIZEOF_SIZE_T
11768  /* we are limited by the 32-bit ssize_t return value on 32-bit */
11769  ss = (copy_length > (off_t)SSIZE_MAX) ? SSIZE_MAX : (ssize_t)copy_length;
11770 # else
11771  ss = (ssize_t)copy_length;
11772 # endif
11773  if (use_pread) {
11774  ss = simple_sendfile(stp->dst_fptr->fd, stp->src_fptr->fd, &src_offset, ss);
11775  }
11776  else {
11777  ss = simple_sendfile(stp->dst_fptr->fd, stp->src_fptr->fd, NULL, ss);
11778  }
11779  if (0 < ss) {
11780  stp->total += ss;
11781  copy_length -= ss;
11782  if (0 < copy_length) {
11783  goto retry_sendfile;
11784  }
11785  }
11786  if (ss < 0) {
11787  if (maygvl_copy_stream_continue_p(0, stp))
11788  goto retry_sendfile;
11789  switch (errno) {
11790  case EINVAL:
11791 #ifdef ENOSYS
11792  case ENOSYS:
11793 #endif
11794 #ifdef EOPNOTSUP
11795  /* some RedHat kernels may return EOPNOTSUP on an NFS mount.
11796  see also: [Feature #16965] */
11797  case EOPNOTSUP:
11798 #endif
11799  return 0;
11800  case EAGAIN:
11801 #if EWOULDBLOCK != EAGAIN
11802  case EWOULDBLOCK:
11803 #endif
11804  {
11805  int ret;
11806 #ifndef __linux__
11807  /*
11808  * Linux requires stp->src_fptr->fd to be a mmap-able (regular) file,
11809  * select() reports regular files to always be "ready", so
11810  * there is no need to select() on it.
11811  * Other OSes may have the same limitation for sendfile() which
11812  * allow us to bypass maygvl_copy_stream_wait_read()...
11813  */
11814  ret = maygvl_copy_stream_wait_read(0, stp);
11815  if (ret < 0) return ret;
11816 #endif
11817  ret = nogvl_copy_stream_wait_write(stp);
11818  if (ret < 0) return ret;
11819  }
11820  goto retry_sendfile;
11821  }
11822  stp->syserr = "sendfile";
11823  stp->error_no = errno;
11824  return (int)ss;
11825  }
11826  return 1;
11827 }
11828 #endif
11829 
11830 static ssize_t
11831 maygvl_read(int has_gvl, rb_io_t *fptr, void *buf, size_t count)
11832 {
11833  if (has_gvl)
11834  return rb_read_internal(fptr, buf, count);
11835  else
11836  return read(fptr->fd, buf, count);
11837 }
11838 
11839 static ssize_t
11840 maygvl_copy_stream_read(int has_gvl, struct copy_stream_struct *stp, char *buf, size_t len, off_t offset)
11841 {
11842  ssize_t ss;
11843  retry_read:
11844  if (offset < (off_t)0) {
11845  ss = maygvl_read(has_gvl, stp->src_fptr, buf, len);
11846  }
11847  else {
11848 #ifdef HAVE_PREAD
11849  ss = pread(stp->src_fptr->fd, buf, len, offset);
11850 #else
11851  stp->notimp = "pread";
11852  return -1;
11853 #endif
11854  }
11855  if (ss == 0) {
11856  return 0;
11857  }
11858  if (ss < 0) {
11859  if (maygvl_copy_stream_continue_p(has_gvl, stp))
11860  goto retry_read;
11861  switch (errno) {
11862  case EAGAIN:
11863 #if EWOULDBLOCK != EAGAIN
11864  case EWOULDBLOCK:
11865 #endif
11866  {
11867  int ret = maygvl_copy_stream_wait_read(has_gvl, stp);
11868  if (ret < 0) return ret;
11869  }
11870  goto retry_read;
11871 #ifdef ENOSYS
11872  case ENOSYS:
11873  stp->notimp = "pread";
11874  return ss;
11875 #endif
11876  }
11877  stp->syserr = offset < (off_t)0 ? "read" : "pread";
11878  stp->error_no = errno;
11879  }
11880  return ss;
11881 }
11882 
11883 static int
11884 nogvl_copy_stream_write(struct copy_stream_struct *stp, char *buf, size_t len)
11885 {
11886  ssize_t ss;
11887  int off = 0;
11888  while (len) {
11889  ss = write(stp->dst_fptr->fd, buf+off, len);
11890  if (ss < 0) {
11891  if (maygvl_copy_stream_continue_p(0, stp))
11892  continue;
11893  if (io_again_p(errno)) {
11894  int ret = nogvl_copy_stream_wait_write(stp);
11895  if (ret < 0) return ret;
11896  continue;
11897  }
11898  stp->syserr = "write";
11899  stp->error_no = errno;
11900  return (int)ss;
11901  }
11902  off += (int)ss;
11903  len -= (int)ss;
11904  stp->total += ss;
11905  }
11906  return 0;
11907 }
11908 
11909 static void
11910 nogvl_copy_stream_read_write(struct copy_stream_struct *stp)
11911 {
11912  char buf[1024*16];
11913  size_t len;
11914  ssize_t ss;
11915  int ret;
11916  off_t copy_length;
11917  int use_eof;
11918  off_t src_offset;
11919  int use_pread;
11920 
11921  copy_length = stp->copy_length;
11922  use_eof = copy_length < (off_t)0;
11923  src_offset = stp->src_offset;
11924  use_pread = src_offset >= (off_t)0;
11925 
11926  if (use_pread && stp->close_src) {
11927  off_t r;
11928  errno = 0;
11929  r = lseek(stp->src_fptr->fd, src_offset, SEEK_SET);
11930  if (r < (off_t)0 && errno) {
11931  stp->syserr = "lseek";
11932  stp->error_no = errno;
11933  return;
11934  }
11935  src_offset = (off_t)-1;
11936  use_pread = 0;
11937  }
11938 
11939  while (use_eof || 0 < copy_length) {
11940  if (!use_eof && copy_length < (off_t)sizeof(buf)) {
11941  len = (size_t)copy_length;
11942  }
11943  else {
11944  len = sizeof(buf);
11945  }
11946  if (use_pread) {
11947  ss = maygvl_copy_stream_read(0, stp, buf, len, src_offset);
11948  if (0 < ss)
11949  src_offset += ss;
11950  }
11951  else {
11952  ss = maygvl_copy_stream_read(0, stp, buf, len, (off_t)-1);
11953  }
11954  if (ss <= 0) /* EOF or error */
11955  return;
11956 
11957  ret = nogvl_copy_stream_write(stp, buf, ss);
11958  if (ret < 0)
11959  return;
11960 
11961  if (!use_eof)
11962  copy_length -= ss;
11963  }
11964 }
11965 
11966 static void *
11967 nogvl_copy_stream_func(void *arg)
11968 {
11969  struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
11970 #if defined(USE_SENDFILE) || defined(USE_COPY_FILE_RANGE) || defined(HAVE_FCOPYFILE)
11971  int ret;
11972 #endif
11973 
11974 #ifdef USE_COPY_FILE_RANGE
11975  ret = nogvl_copy_file_range(stp);
11976  if (ret != 0)
11977  goto finish; /* error or success */
11978 #endif
11979 
11980 #ifdef HAVE_FCOPYFILE
11981  ret = nogvl_fcopyfile(stp);
11982  if (ret != 0)
11983  goto finish; /* error or success */
11984 #endif
11985 
11986 #ifdef USE_SENDFILE
11987  ret = nogvl_copy_stream_sendfile(stp);
11988  if (ret != 0)
11989  goto finish; /* error or success */
11990 #endif
11991 
11992  nogvl_copy_stream_read_write(stp);
11993 
11994 #if defined(USE_SENDFILE) || defined(USE_COPY_FILE_RANGE) || defined(HAVE_FCOPYFILE)
11995  finish:
11996 #endif
11997  return 0;
11998 }
11999 
12000 static VALUE
12001 copy_stream_fallback_body(VALUE arg)
12002 {
12003  struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
12004  const int buflen = 16*1024;
12005  VALUE n;
12006  VALUE buf = rb_str_buf_new(buflen);
12007  off_t rest = stp->copy_length;
12008  off_t off = stp->src_offset;
12009  ID read_method = id_readpartial;
12010 
12011  if (!stp->src_fptr) {
12012  if (!rb_respond_to(stp->src, read_method)) {
12013  read_method = id_read;
12014  }
12015  }
12016 
12017  while (1) {
12018  long numwrote;
12019  long l;
12020  if (stp->copy_length < (off_t)0) {
12021  l = buflen;
12022  }
12023  else {
12024  if (rest == 0) {
12025  rb_str_resize(buf, 0);
12026  break;
12027  }
12028  l = buflen < rest ? buflen : (long)rest;
12029  }
12030  if (!stp->src_fptr) {
12031  VALUE rc = rb_funcall(stp->src, read_method, 2, INT2FIX(l), buf);
12032 
12033  if (read_method == id_read && NIL_P(rc))
12034  break;
12035  }
12036  else {
12037  ssize_t ss;
12038  rb_str_resize(buf, buflen);
12039  ss = maygvl_copy_stream_read(1, stp, RSTRING_PTR(buf), l, off);
12040  rb_str_resize(buf, ss > 0 ? ss : 0);
12041  if (ss < 0)
12042  return Qnil;
12043  if (ss == 0)
12044  rb_eof_error();
12045  if (off >= (off_t)0)
12046  off += ss;
12047  }
12048  n = rb_io_write(stp->dst, buf);
12049  numwrote = NUM2LONG(n);
12050  stp->total += numwrote;
12051  rest -= numwrote;
12052  if (read_method == id_read && RSTRING_LEN(buf) == 0) {
12053  break;
12054  }
12055  }
12056 
12057  return Qnil;
12058 }
12059 
12060 static VALUE
12061 copy_stream_fallback(struct copy_stream_struct *stp)
12062 {
12063  if (!stp->src_fptr && stp->src_offset >= (off_t)0) {
12064  rb_raise(rb_eArgError, "cannot specify src_offset for non-IO");
12065  }
12066  rb_rescue2(copy_stream_fallback_body, (VALUE)stp,
12067  (VALUE (*) (VALUE, VALUE))0, (VALUE)0,
12068  rb_eEOFError, (VALUE)0);
12069  return Qnil;
12070 }
12071 
12072 static VALUE
12073 copy_stream_body(VALUE arg)
12074 {
12075  struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
12076  VALUE src_io = stp->src, dst_io = stp->dst;
12077  const int common_oflags = 0
12078 #ifdef O_NOCTTY
12079  | O_NOCTTY
12080 #endif
12081  ;
12082 
12083  stp->th = rb_thread_current();
12084 
12085  stp->total = 0;
12086 
12087  if (src_io == argf ||
12088  !(RB_TYPE_P(src_io, T_FILE) ||
12089  RB_TYPE_P(src_io, T_STRING) ||
12090  rb_respond_to(src_io, rb_intern("to_path")))) {
12091  stp->src_fptr = NULL;
12092  }
12093  else {
12094  int stat_ret;
12095  VALUE tmp_io = rb_io_check_io(src_io);
12096  if (!NIL_P(tmp_io)) {
12097  src_io = tmp_io;
12098  }
12099  else if (!RB_TYPE_P(src_io, T_FILE)) {
12100  VALUE args[2];
12101  FilePathValue(src_io);
12102  args[0] = src_io;
12103  args[1] = INT2NUM(O_RDONLY|common_oflags);
12104  src_io = rb_class_new_instance(2, args, rb_cFile);
12105  stp->src = src_io;
12106  stp->close_src = 1;
12107  }
12108  RB_IO_POINTER(src_io, stp->src_fptr);
12109  rb_io_check_byte_readable(stp->src_fptr);
12110 
12111  stat_ret = fstat(stp->src_fptr->fd, &stp->src_stat);
12112  if (stat_ret < 0) {
12113  stp->syserr = "fstat";
12114  stp->error_no = errno;
12115  return Qnil;
12116  }
12117  }
12118 
12119  if (dst_io == argf ||
12120  !(RB_TYPE_P(dst_io, T_FILE) ||
12121  RB_TYPE_P(dst_io, T_STRING) ||
12122  rb_respond_to(dst_io, rb_intern("to_path")))) {
12123  stp->dst_fptr = NULL;
12124  }
12125  else {
12126  int stat_ret;
12127  VALUE tmp_io = rb_io_check_io(dst_io);
12128  if (!NIL_P(tmp_io)) {
12129  dst_io = GetWriteIO(tmp_io);
12130  }
12131  else if (!RB_TYPE_P(dst_io, T_FILE)) {
12132  VALUE args[3];
12133  FilePathValue(dst_io);
12134  args[0] = dst_io;
12135  args[1] = INT2NUM(O_WRONLY|O_CREAT|O_TRUNC|common_oflags);
12136  args[2] = INT2FIX(0666);
12137  dst_io = rb_class_new_instance(3, args, rb_cFile);
12138  stp->dst = dst_io;
12139  stp->close_dst = 1;
12140  }
12141  else {
12142  dst_io = GetWriteIO(dst_io);
12143  stp->dst = dst_io;
12144  }
12145  RB_IO_POINTER(dst_io, stp->dst_fptr);
12146  rb_io_check_writable(stp->dst_fptr);
12147 
12148  stat_ret = fstat(stp->dst_fptr->fd, &stp->dst_stat);
12149  if (stat_ret < 0) {
12150  stp->syserr = "fstat";
12151  stp->error_no = errno;
12152  return Qnil;
12153  }
12154  }
12155 
12156 #ifdef O_BINARY
12157  if (stp->src_fptr)
12158  SET_BINARY_MODE_WITH_SEEK_CUR(stp->src_fptr);
12159 #endif
12160  if (stp->dst_fptr)
12161  io_ascii8bit_binmode(stp->dst_fptr);
12162 
12163  if (stp->src_offset < (off_t)0 && stp->src_fptr && stp->src_fptr->rbuf.len) {
12164  size_t len = stp->src_fptr->rbuf.len;
12165  VALUE str;
12166  if (stp->copy_length >= (off_t)0 && stp->copy_length < (off_t)len) {
12167  len = (size_t)stp->copy_length;
12168  }
12169  str = rb_str_buf_new(len);
12170  rb_str_resize(str,len);
12171  read_buffered_data(RSTRING_PTR(str), len, stp->src_fptr);
12172  if (stp->dst_fptr) { /* IO or filename */
12173  if (io_binwrite(str, RSTRING_PTR(str), RSTRING_LEN(str), stp->dst_fptr, 0) < 0)
12174  rb_sys_fail_on_write(stp->dst_fptr);
12175  }
12176  else /* others such as StringIO */
12177  rb_io_write(dst_io, str);
12178  rb_str_resize(str, 0);
12179  stp->total += len;
12180  if (stp->copy_length >= (off_t)0)
12181  stp->copy_length -= len;
12182  }
12183 
12184  if (stp->dst_fptr && io_fflush(stp->dst_fptr) < 0) {
12185  rb_raise(rb_eIOError, "flush failed");
12186  }
12187 
12188  if (stp->copy_length == 0)
12189  return Qnil;
12190 
12191  if (stp->src_fptr == NULL || stp->dst_fptr == NULL) {
12192  return copy_stream_fallback(stp);
12193  }
12194 
12195  rb_thread_call_without_gvl(nogvl_copy_stream_func, (void*)stp, RUBY_UBF_IO, 0);
12196  return Qnil;
12197 }
12198 
12199 static VALUE
12200 copy_stream_finalize(VALUE arg)
12201 {
12202  struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
12203 
12204 #ifdef HAVE_FCOPYFILE
12205  if (stp->copyfile_state) {
12206  copyfile_state_free(stp->copyfile_state);
12207  }
12208 #endif
12209 
12210  if (stp->close_src) {
12211  rb_io_close_m(stp->src);
12212  }
12213  if (stp->close_dst) {
12214  rb_io_close_m(stp->dst);
12215  }
12216  if (stp->syserr) {
12217  rb_syserr_fail(stp->error_no, stp->syserr);
12218  }
12219  if (stp->notimp) {
12220  rb_raise(rb_eNotImpError, "%s() not implemented", stp->notimp);
12221  }
12222  return Qnil;
12223 }
12224 
12225 /*
12226  * call-seq:
12227  * IO.copy_stream(src, dst)
12228  * IO.copy_stream(src, dst, copy_length)
12229  * IO.copy_stream(src, dst, copy_length, src_offset)
12230  *
12231  * IO.copy_stream copies <i>src</i> to <i>dst</i>.
12232  * <i>src</i> and <i>dst</i> is either a filename or an IO-like object.
12233  * IO-like object for <i>src</i> should have #readpartial or #read
12234  * method. IO-like object for <i>dst</i> should have #write method.
12235  * (Specialized mechanisms, such as sendfile system call, may be used
12236  * on appropriate situation.)
12237  *
12238  * This method returns the number of bytes copied.
12239  *
12240  * If optional arguments are not given,
12241  * the start position of the copy is
12242  * the beginning of the filename or
12243  * the current file offset of the IO.
12244  * The end position of the copy is the end of file.
12245  *
12246  * If <i>copy_length</i> is given,
12247  * No more than <i>copy_length</i> bytes are copied.
12248  *
12249  * If <i>src_offset</i> is given,
12250  * it specifies the start position of the copy.
12251  *
12252  * When <i>src_offset</i> is specified and
12253  * <i>src</i> is an IO,
12254  * IO.copy_stream doesn't move the current file offset.
12255  *
12256  */
12257 static VALUE
12258 rb_io_s_copy_stream(int argc, VALUE *argv, VALUE io)
12259 {
12260  VALUE src, dst, length, src_offset;
12261  struct copy_stream_struct st;
12262 
12263  MEMZERO(&st, struct copy_stream_struct, 1);
12264 
12265  rb_scan_args(argc, argv, "22", &src, &dst, &length, &src_offset);
12266 
12267  st.src = src;
12268  st.dst = dst;
12269 
12270  st.src_fptr = NULL;
12271  st.dst_fptr = NULL;
12272 
12273  if (NIL_P(length))
12274  st.copy_length = (off_t)-1;
12275  else
12276  st.copy_length = NUM2OFFT(length);
12277 
12278  if (NIL_P(src_offset))
12279  st.src_offset = (off_t)-1;
12280  else
12281  st.src_offset = NUM2OFFT(src_offset);
12282 
12283  rb_ensure(copy_stream_body, (VALUE)&st, copy_stream_finalize, (VALUE)&st);
12284 
12285  return OFFT2NUM(st.total);
12286 }
12287 
12288 /*
12289  * call-seq:
12290  * io.external_encoding -> encoding
12291  *
12292  * Returns the Encoding object that represents the encoding of the file.
12293  * If _io_ is in write mode and no encoding is specified, returns +nil+.
12294  */
12295 
12296 static VALUE
12297 rb_io_external_encoding(VALUE io)
12298 {
12299  rb_io_t *fptr = RFILE(rb_io_taint_check(io))->fptr;
12300 
12301  if (fptr->encs.enc2) {
12302  return rb_enc_from_encoding(fptr->encs.enc2);
12303  }
12304  if (fptr->mode & FMODE_WRITABLE) {
12305  if (fptr->encs.enc)
12306  return rb_enc_from_encoding(fptr->encs.enc);
12307  return Qnil;
12308  }
12309  return rb_enc_from_encoding(io_read_encoding(fptr));
12310 }
12311 
12312 /*
12313  * call-seq:
12314  * io.internal_encoding -> encoding
12315  *
12316  * Returns the Encoding of the internal string if conversion is
12317  * specified. Otherwise returns +nil+.
12318  */
12319 
12320 static VALUE
12321 rb_io_internal_encoding(VALUE io)
12322 {
12323  rb_io_t *fptr = RFILE(rb_io_taint_check(io))->fptr;
12324 
12325  if (!fptr->encs.enc2) return Qnil;
12326  return rb_enc_from_encoding(io_read_encoding(fptr));
12327 }
12328 
12329 /*
12330  * call-seq:
12331  * io.set_encoding(ext_enc) -> io
12332  * io.set_encoding("ext_enc:int_enc") -> io
12333  * io.set_encoding(ext_enc, int_enc) -> io
12334  * io.set_encoding("ext_enc:int_enc", opt) -> io
12335  * io.set_encoding(ext_enc, int_enc, opt) -> io
12336  *
12337  * If single argument is specified, read string from io is tagged
12338  * with the encoding specified. If encoding is a colon separated two
12339  * encoding names "A:B", the read string is converted from encoding A
12340  * (external encoding) to encoding B (internal encoding), then tagged
12341  * with B. If two arguments are specified, those must be encoding
12342  * objects or encoding names, and the first one is the external encoding, and the
12343  * second one is the internal encoding.
12344  * If the external encoding and the internal encoding is specified,
12345  * optional hash argument specify the conversion option.
12346  */
12347 
12348 static VALUE
12349 rb_io_set_encoding(int argc, VALUE *argv, VALUE io)
12350 {
12351  rb_io_t *fptr;
12352  VALUE v1, v2, opt;
12353 
12354  if (!RB_TYPE_P(io, T_FILE)) {
12355  return forward(io, id_set_encoding, argc, argv);
12356  }
12357 
12358  argc = rb_scan_args(argc, argv, "11:", &v1, &v2, &opt);
12359  GetOpenFile(io, fptr);
12360  io_encoding_set(fptr, v1, v2, opt);
12361  return io;
12362 }
12363 
12364 void
12365 rb_stdio_set_default_encoding(void)
12366 {
12367  VALUE val = Qnil;
12368 
12369 #ifdef _WIN32
12370  if (isatty(fileno(stdin))) {
12371  rb_encoding *external = rb_locale_encoding();
12373  if (!internal) internal = rb_default_external_encoding();
12374  io_encoding_set(RFILE(rb_stdin)->fptr,
12375  rb_enc_from_encoding(external),
12376  rb_enc_from_encoding(internal),
12377  Qnil);
12378  }
12379  else
12380 #endif
12381  rb_io_set_encoding(1, &val, rb_stdin);
12382  rb_io_set_encoding(1, &val, rb_stdout);
12383  rb_io_set_encoding(1, &val, rb_stderr);
12384 }
12385 
12386 static inline int
12387 global_argf_p(VALUE arg)
12388 {
12389  return arg == argf;
12390 }
12391 
12392 /*
12393  * call-seq:
12394  * ARGF.external_encoding -> encoding
12395  *
12396  * Returns the external encoding for files read from +ARGF+ as an +Encoding+
12397  * object. The external encoding is the encoding of the text as stored in a
12398  * file. Contrast with +ARGF.internal_encoding+, which is the encoding used
12399  * to represent this text within Ruby.
12400  *
12401  * To set the external encoding use +ARGF.set_encoding+.
12402  *
12403  * For example:
12404  *
12405  * ARGF.external_encoding #=> #<Encoding:UTF-8>
12406  *
12407  */
12408 static VALUE
12409 argf_external_encoding(VALUE argf)
12410 {
12411  if (!RTEST(ARGF.current_file)) {
12413  }
12414  return rb_io_external_encoding(rb_io_check_io(ARGF.current_file));
12415 }
12416 
12417 /*
12418  * call-seq:
12419  * ARGF.internal_encoding -> encoding
12420  *
12421  * Returns the internal encoding for strings read from +ARGF+ as an
12422  * +Encoding+ object.
12423  *
12424  * If +ARGF.set_encoding+ has been called with two encoding names, the second
12425  * is returned. Otherwise, if +Encoding.default_external+ has been set, that
12426  * value is returned. Failing that, if a default external encoding was
12427  * specified on the command-line, that value is used. If the encoding is
12428  * unknown, +nil+ is returned.
12429  */
12430 static VALUE
12431 argf_internal_encoding(VALUE argf)
12432 {
12433  if (!RTEST(ARGF.current_file)) {
12435  }
12436  return rb_io_internal_encoding(rb_io_check_io(ARGF.current_file));
12437 }
12438 
12439 /*
12440  * call-seq:
12441  * ARGF.set_encoding(ext_enc) -> ARGF
12442  * ARGF.set_encoding("ext_enc:int_enc") -> ARGF
12443  * ARGF.set_encoding(ext_enc, int_enc) -> ARGF
12444  * ARGF.set_encoding("ext_enc:int_enc", opt) -> ARGF
12445  * ARGF.set_encoding(ext_enc, int_enc, opt) -> ARGF
12446  *
12447  * If single argument is specified, strings read from ARGF are tagged with
12448  * the encoding specified.
12449  *
12450  * If two encoding names separated by a colon are given, e.g. "ascii:utf-8",
12451  * the read string is converted from the first encoding (external encoding)
12452  * to the second encoding (internal encoding), then tagged with the second
12453  * encoding.
12454  *
12455  * If two arguments are specified, they must be encoding objects or encoding
12456  * names. Again, the first specifies the external encoding; the second
12457  * specifies the internal encoding.
12458  *
12459  * If the external encoding and the internal encoding are specified, the
12460  * optional +Hash+ argument can be used to adjust the conversion process. The
12461  * structure of this hash is explained in the String#encode documentation.
12462  *
12463  * For example:
12464  *
12465  * ARGF.set_encoding('ascii') # Tag the input as US-ASCII text
12466  * ARGF.set_encoding(Encoding::UTF_8) # Tag the input as UTF-8 text
12467  * ARGF.set_encoding('utf-8','ascii') # Transcode the input from US-ASCII
12468  * # to UTF-8.
12469  */
12470 static VALUE
12471 argf_set_encoding(int argc, VALUE *argv, VALUE argf)
12472 {
12473  rb_io_t *fptr;
12474 
12475  if (!next_argv()) {
12476  rb_raise(rb_eArgError, "no stream to set encoding");
12477  }
12478  rb_io_set_encoding(argc, argv, ARGF.current_file);
12479  GetOpenFile(ARGF.current_file, fptr);
12480  ARGF.encs = fptr->encs;
12481  return argf;
12482 }
12483 
12484 /*
12485  * call-seq:
12486  * ARGF.tell -> Integer
12487  * ARGF.pos -> Integer
12488  *
12489  * Returns the current offset (in bytes) of the current file in +ARGF+.
12490  *
12491  * ARGF.pos #=> 0
12492  * ARGF.gets #=> "This is line one\n"
12493  * ARGF.pos #=> 17
12494  *
12495  */
12496 static VALUE
12497 argf_tell(VALUE argf)
12498 {
12499  if (!next_argv()) {
12500  rb_raise(rb_eArgError, "no stream to tell");
12501  }
12502  ARGF_FORWARD(0, 0);
12503  return rb_io_tell(ARGF.current_file);
12504 }
12505 
12506 /*
12507  * call-seq:
12508  * ARGF.seek(amount, whence=IO::SEEK_SET) -> 0
12509  *
12510  * Seeks to offset _amount_ (an +Integer+) in the +ARGF+ stream according to
12511  * the value of _whence_. See IO#seek for further details.
12512  */
12513 static VALUE
12514 argf_seek_m(int argc, VALUE *argv, VALUE argf)
12515 {
12516  if (!next_argv()) {
12517  rb_raise(rb_eArgError, "no stream to seek");
12518  }
12519  ARGF_FORWARD(argc, argv);
12520  return rb_io_seek_m(argc, argv, ARGF.current_file);
12521 }
12522 
12523 /*
12524  * call-seq:
12525  * ARGF.pos = position -> Integer
12526  *
12527  * Seeks to the position given by _position_ (in bytes) in +ARGF+.
12528  *
12529  * For example:
12530  *
12531  * ARGF.pos = 17
12532  * ARGF.gets #=> "This is line two\n"
12533  */
12534 static VALUE
12535 argf_set_pos(VALUE argf, VALUE offset)
12536 {
12537  if (!next_argv()) {
12538  rb_raise(rb_eArgError, "no stream to set position");
12539  }
12540  ARGF_FORWARD(1, &offset);
12541  return rb_io_set_pos(ARGF.current_file, offset);
12542 }
12543 
12544 /*
12545  * call-seq:
12546  * ARGF.rewind -> 0
12547  *
12548  * Positions the current file to the beginning of input, resetting
12549  * +ARGF.lineno+ to zero.
12550  *
12551  * ARGF.readline #=> "This is line one\n"
12552  * ARGF.rewind #=> 0
12553  * ARGF.lineno #=> 0
12554  * ARGF.readline #=> "This is line one\n"
12555  */
12556 static VALUE
12557 argf_rewind(VALUE argf)
12558 {
12559  VALUE ret;
12560  int old_lineno;
12561 
12562  if (!next_argv()) {
12563  rb_raise(rb_eArgError, "no stream to rewind");
12564  }
12565  ARGF_FORWARD(0, 0);
12566  old_lineno = RFILE(ARGF.current_file)->fptr->lineno;
12567  ret = rb_io_rewind(ARGF.current_file);
12568  if (!global_argf_p(argf)) {
12569  ARGF.last_lineno = ARGF.lineno -= old_lineno;
12570  }
12571  return ret;
12572 }
12573 
12574 /*
12575  * call-seq:
12576  * ARGF.fileno -> integer
12577  * ARGF.to_i -> integer
12578  *
12579  * Returns an integer representing the numeric file descriptor for
12580  * the current file. Raises an +ArgumentError+ if there isn't a current file.
12581  *
12582  * ARGF.fileno #=> 3
12583  */
12584 static VALUE
12585 argf_fileno(VALUE argf)
12586 {
12587  if (!next_argv()) {
12588  rb_raise(rb_eArgError, "no stream");
12589  }
12590  ARGF_FORWARD(0, 0);
12591  return rb_io_fileno(ARGF.current_file);
12592 }
12593 
12594 /*
12595  * call-seq:
12596  * ARGF.to_io -> IO
12597  *
12598  * Returns an +IO+ object representing the current file. This will be a
12599  * +File+ object unless the current file is a stream such as STDIN.
12600  *
12601  * For example:
12602  *
12603  * ARGF.to_io #=> #<File:glark.txt>
12604  * ARGF.to_io #=> #<IO:<STDIN>>
12605  */
12606 static VALUE
12607 argf_to_io(VALUE argf)
12608 {
12609  next_argv();
12610  ARGF_FORWARD(0, 0);
12611  return ARGF.current_file;
12612 }
12613 
12614 /*
12615  * call-seq:
12616  * ARGF.eof? -> true or false
12617  * ARGF.eof -> true or false
12618  *
12619  * Returns true if the current file in +ARGF+ is at end of file, i.e. it has
12620  * no data to read. The stream must be opened for reading or an +IOError+
12621  * will be raised.
12622  *
12623  * $ echo "eof" | ruby argf.rb
12624  *
12625  * ARGF.eof? #=> false
12626  * 3.times { ARGF.readchar }
12627  * ARGF.eof? #=> false
12628  * ARGF.readchar #=> "\n"
12629  * ARGF.eof? #=> true
12630  */
12631 
12632 static VALUE
12633 argf_eof(VALUE argf)
12634 {
12635  next_argv();
12636  if (RTEST(ARGF.current_file)) {
12637  if (ARGF.init_p == 0) return Qtrue;
12638  next_argv();
12639  ARGF_FORWARD(0, 0);
12640  if (rb_io_eof(ARGF.current_file)) {
12641  return Qtrue;
12642  }
12643  }
12644  return Qfalse;
12645 }
12646 
12647 /*
12648  * call-seq:
12649  * ARGF.read([length [, outbuf]]) -> string, outbuf, or nil
12650  *
12651  * Reads _length_ bytes from ARGF. The files named on the command line
12652  * are concatenated and treated as a single file by this method, so when
12653  * called without arguments the contents of this pseudo file are returned in
12654  * their entirety.
12655  *
12656  * _length_ must be a non-negative integer or +nil+.
12657  *
12658  * If _length_ is a positive integer, +read+ tries to read
12659  * _length_ bytes without any conversion (binary mode).
12660  * It returns +nil+ if an EOF is encountered before anything can be read.
12661  * Fewer than _length_ bytes are returned if an EOF is encountered during
12662  * the read.
12663  * In the case of an integer _length_, the resulting string is always
12664  * in ASCII-8BIT encoding.
12665  *
12666  * If _length_ is omitted or is +nil+, it reads until EOF
12667  * and the encoding conversion is applied, if applicable.
12668  * A string is returned even if EOF is encountered before any data is read.
12669  *
12670  * If _length_ is zero, it returns an empty string (<code>""</code>).
12671  *
12672  * If the optional _outbuf_ argument is present,
12673  * it must reference a String, which will receive the data.
12674  * The _outbuf_ will contain only the received data after the method call
12675  * even if it is not empty at the beginning.
12676  *
12677  * For example:
12678  *
12679  * $ echo "small" > small.txt
12680  * $ echo "large" > large.txt
12681  * $ ./glark.rb small.txt large.txt
12682  *
12683  * ARGF.read #=> "small\nlarge"
12684  * ARGF.read(200) #=> "small\nlarge"
12685  * ARGF.read(2) #=> "sm"
12686  * ARGF.read(0) #=> ""
12687  *
12688  * Note that this method behaves like the fread() function in C.
12689  * This means it retries to invoke read(2) system calls to read data
12690  * with the specified length.
12691  * If you need the behavior like a single read(2) system call,
12692  * consider ARGF#readpartial or ARGF#read_nonblock.
12693  */
12694 
12695 static VALUE
12696 argf_read(int argc, VALUE *argv, VALUE argf)
12697 {
12698  VALUE tmp, str, length;
12699  long len = 0;
12700 
12701  rb_scan_args(argc, argv, "02", &length, &str);
12702  if (!NIL_P(length)) {
12703  len = NUM2LONG(argv[0]);
12704  }
12705  if (!NIL_P(str)) {
12706  StringValue(str);
12707  rb_str_resize(str,0);
12708  argv[1] = Qnil;
12709  }
12710 
12711  retry:
12712  if (!next_argv()) {
12713  return str;
12714  }
12715  if (ARGF_GENERIC_INPUT_P()) {
12716  tmp = argf_forward(argc, argv, argf);
12717  }
12718  else {
12719  tmp = io_read(argc, argv, ARGF.current_file);
12720  }
12721  if (NIL_P(str)) str = tmp;
12722  else if (!NIL_P(tmp)) rb_str_append(str, tmp);
12723  if (NIL_P(tmp) || NIL_P(length)) {
12724  if (ARGF.next_p != -1) {
12725  argf_close(argf);
12726  ARGF.next_p = 1;
12727  goto retry;
12728  }
12729  }
12730  else if (argc >= 1) {
12731  long slen = RSTRING_LEN(str);
12732  if (slen < len) {
12733  argv[0] = LONG2NUM(len - slen);
12734  goto retry;
12735  }
12736  }
12737  return str;
12738 }
12739 
12741  int argc;
12742  VALUE *argv;
12743  VALUE argf;
12744 };
12745 
12746 static VALUE
12747 argf_forward_call(VALUE arg)
12748 {
12749  struct argf_call_arg *p = (struct argf_call_arg *)arg;
12750  argf_forward(p->argc, p->argv, p->argf);
12751  return Qnil;
12752 }
12753 
12754 static VALUE argf_getpartial(int argc, VALUE *argv, VALUE argf, VALUE opts,
12755  int nonblock);
12756 
12757 /*
12758  * call-seq:
12759  * ARGF.readpartial(maxlen) -> string
12760  * ARGF.readpartial(maxlen, outbuf) -> outbuf
12761  *
12762  * Reads at most _maxlen_ bytes from the ARGF stream.
12763  *
12764  * If the optional _outbuf_ argument is present,
12765  * it must reference a String, which will receive the data.
12766  * The _outbuf_ will contain only the received data after the method call
12767  * even if it is not empty at the beginning.
12768  *
12769  * It raises EOFError on end of ARGF stream.
12770  * Since ARGF stream is a concatenation of multiple files,
12771  * internally EOF is occur for each file.
12772  * ARGF.readpartial returns empty strings for EOFs except the last one and
12773  * raises EOFError for the last one.
12774  *
12775  */
12776 
12777 static VALUE
12778 argf_readpartial(int argc, VALUE *argv, VALUE argf)
12779 {
12780  return argf_getpartial(argc, argv, argf, Qnil, 0);
12781 }
12782 
12783 /*
12784  * call-seq:
12785  * ARGF.read_nonblock(maxlen[, options]) -> string
12786  * ARGF.read_nonblock(maxlen, outbuf[, options]) -> outbuf
12787  *
12788  * Reads at most _maxlen_ bytes from the ARGF stream in non-blocking mode.
12789  */
12790 
12791 static VALUE
12792 argf_read_nonblock(int argc, VALUE *argv, VALUE argf)
12793 {
12794  VALUE opts;
12795 
12796  rb_scan_args(argc, argv, "11:", NULL, NULL, &opts);
12797 
12798  if (!NIL_P(opts))
12799  argc--;
12800 
12801  return argf_getpartial(argc, argv, argf, opts, 1);
12802 }
12803 
12804 static VALUE
12805 argf_getpartial(int argc, VALUE *argv, VALUE argf, VALUE opts, int nonblock)
12806 {
12807  VALUE tmp, str, length;
12808  int no_exception;
12809 
12810  rb_scan_args(argc, argv, "11", &length, &str);
12811  if (!NIL_P(str)) {
12812  StringValue(str);
12813  argv[1] = str;
12814  }
12815  no_exception = no_exception_p(opts);
12816 
12817  if (!next_argv()) {
12818  if (!NIL_P(str)) {
12819  rb_str_resize(str, 0);
12820  }
12821  rb_eof_error();
12822  }
12823  if (ARGF_GENERIC_INPUT_P()) {
12824  VALUE (*const rescue_does_nothing)(VALUE, VALUE) = 0;
12825  struct argf_call_arg arg;
12826  arg.argc = argc;
12827  arg.argv = argv;
12828  arg.argf = argf;
12829  tmp = rb_rescue2(argf_forward_call, (VALUE)&arg,
12830  rescue_does_nothing, Qnil, rb_eEOFError, (VALUE)0);
12831  }
12832  else {
12833  tmp = io_getpartial(argc, argv, ARGF.current_file, no_exception, nonblock);
12834  }
12835  if (NIL_P(tmp)) {
12836  if (ARGF.next_p == -1) {
12837  return io_nonblock_eof(no_exception);
12838  }
12839  argf_close(argf);
12840  ARGF.next_p = 1;
12841  if (RARRAY_LEN(ARGF.argv) == 0) {
12842  return io_nonblock_eof(no_exception);
12843  }
12844  if (NIL_P(str))
12845  str = rb_str_new(NULL, 0);
12846  return str;
12847  }
12848  return tmp;
12849 }
12850 
12851 /*
12852  * call-seq:
12853  * ARGF.getc -> String or nil
12854  *
12855  * Reads the next character from +ARGF+ and returns it as a +String+. Returns
12856  * +nil+ at the end of the stream.
12857  *
12858  * +ARGF+ treats the files named on the command line as a single file created
12859  * by concatenating their contents. After returning the last character of the
12860  * first file, it returns the first character of the second file, and so on.
12861  *
12862  * For example:
12863  *
12864  * $ echo "foo" > file
12865  * $ ruby argf.rb file
12866  *
12867  * ARGF.getc #=> "f"
12868  * ARGF.getc #=> "o"
12869  * ARGF.getc #=> "o"
12870  * ARGF.getc #=> "\n"
12871  * ARGF.getc #=> nil
12872  * ARGF.getc #=> nil
12873  */
12874 static VALUE
12875 argf_getc(VALUE argf)
12876 {
12877  VALUE ch;
12878 
12879  retry:
12880  if (!next_argv()) return Qnil;
12881  if (ARGF_GENERIC_INPUT_P()) {
12882  ch = forward_current(rb_intern("getc"), 0, 0);
12883  }
12884  else {
12885  ch = rb_io_getc(ARGF.current_file);
12886  }
12887  if (NIL_P(ch) && ARGF.next_p != -1) {
12888  argf_close(argf);
12889  ARGF.next_p = 1;
12890  goto retry;
12891  }
12892 
12893  return ch;
12894 }
12895 
12896 /*
12897  * call-seq:
12898  * ARGF.getbyte -> Integer or nil
12899  *
12900  * Gets the next 8-bit byte (0..255) from +ARGF+. Returns +nil+ if called at
12901  * the end of the stream.
12902  *
12903  * For example:
12904  *
12905  * $ echo "foo" > file
12906  * $ ruby argf.rb file
12907  *
12908  * ARGF.getbyte #=> 102
12909  * ARGF.getbyte #=> 111
12910  * ARGF.getbyte #=> 111
12911  * ARGF.getbyte #=> 10
12912  * ARGF.getbyte #=> nil
12913  */
12914 static VALUE
12915 argf_getbyte(VALUE argf)
12916 {
12917  VALUE ch;
12918 
12919  retry:
12920  if (!next_argv()) return Qnil;
12921  if (!RB_TYPE_P(ARGF.current_file, T_FILE)) {
12922  ch = forward_current(rb_intern("getbyte"), 0, 0);
12923  }
12924  else {
12925  ch = rb_io_getbyte(ARGF.current_file);
12926  }
12927  if (NIL_P(ch) && ARGF.next_p != -1) {
12928  argf_close(argf);
12929  ARGF.next_p = 1;
12930  goto retry;
12931  }
12932 
12933  return ch;
12934 }
12935 
12936 /*
12937  * call-seq:
12938  * ARGF.readchar -> String or nil
12939  *
12940  * Reads the next character from +ARGF+ and returns it as a +String+. Raises
12941  * an +EOFError+ after the last character of the last file has been read.
12942  *
12943  * For example:
12944  *
12945  * $ echo "foo" > file
12946  * $ ruby argf.rb file
12947  *
12948  * ARGF.readchar #=> "f"
12949  * ARGF.readchar #=> "o"
12950  * ARGF.readchar #=> "o"
12951  * ARGF.readchar #=> "\n"
12952  * ARGF.readchar #=> end of file reached (EOFError)
12953  */
12954 static VALUE
12955 argf_readchar(VALUE argf)
12956 {
12957  VALUE ch;
12958 
12959  retry:
12960  if (!next_argv()) rb_eof_error();
12961  if (!RB_TYPE_P(ARGF.current_file, T_FILE)) {
12962  ch = forward_current(rb_intern("getc"), 0, 0);
12963  }
12964  else {
12965  ch = rb_io_getc(ARGF.current_file);
12966  }
12967  if (NIL_P(ch) && ARGF.next_p != -1) {
12968  argf_close(argf);
12969  ARGF.next_p = 1;
12970  goto retry;
12971  }
12972 
12973  return ch;
12974 }
12975 
12976 /*
12977  * call-seq:
12978  * ARGF.readbyte -> Integer
12979  *
12980  * Reads the next 8-bit byte from ARGF and returns it as an +Integer+. Raises
12981  * an +EOFError+ after the last byte of the last file has been read.
12982  *
12983  * For example:
12984  *
12985  * $ echo "foo" > file
12986  * $ ruby argf.rb file
12987  *
12988  * ARGF.readbyte #=> 102
12989  * ARGF.readbyte #=> 111
12990  * ARGF.readbyte #=> 111
12991  * ARGF.readbyte #=> 10
12992  * ARGF.readbyte #=> end of file reached (EOFError)
12993  */
12994 static VALUE
12995 argf_readbyte(VALUE argf)
12996 {
12997  VALUE c;
12998 
12999  NEXT_ARGF_FORWARD(0, 0);
13000  c = argf_getbyte(argf);
13001  if (NIL_P(c)) {
13002  rb_eof_error();
13003  }
13004  return c;
13005 }
13006 
13007 #define FOREACH_ARGF() while (next_argv())
13008 
13009 static VALUE
13010 argf_block_call_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, argf))
13011 {
13012  const VALUE current = ARGF.current_file;
13013  rb_yield_values2(argc, argv);
13014  if (ARGF.init_p == -1 || current != ARGF.current_file) {
13016  }
13017  return Qnil;
13018 }
13019 
13020 #define ARGF_block_call(mid, argc, argv, func, argf) \
13021  rb_block_call_kw(ARGF.current_file, mid, argc, argv, \
13022  func, argf, rb_keyword_given_p())
13023 
13024 static void
13025 argf_block_call(ID mid, int argc, VALUE *argv, VALUE argf)
13026 {
13027  VALUE ret = ARGF_block_call(mid, argc, argv, argf_block_call_i, argf);
13028  if (ret != Qundef) ARGF.next_p = 1;
13029 }
13030 
13031 static VALUE
13032 argf_block_call_line_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, argf))
13033 {
13034  if (!global_argf_p(argf)) {
13035  ARGF.last_lineno = ++ARGF.lineno;
13036  }
13037  return argf_block_call_i(i, argf, argc, argv, blockarg);
13038 }
13039 
13040 static void
13041 argf_block_call_line(ID mid, int argc, VALUE *argv, VALUE argf)
13042 {
13043  VALUE ret = ARGF_block_call(mid, argc, argv, argf_block_call_line_i, argf);
13044  if (ret != Qundef) ARGF.next_p = 1;
13045 }
13046 
13047 /*
13048  * call-seq:
13049  * ARGF.each(sep=$/) {|line| block } -> ARGF
13050  * ARGF.each(sep=$/, limit) {|line| block } -> ARGF
13051  * ARGF.each(...) -> an_enumerator
13052  *
13053  * ARGF.each_line(sep=$/) {|line| block } -> ARGF
13054  * ARGF.each_line(sep=$/, limit) {|line| block } -> ARGF
13055  * ARGF.each_line(...) -> an_enumerator
13056  *
13057  * Returns an enumerator which iterates over each line (separated by _sep_,
13058  * which defaults to your platform's newline character) of each file in
13059  * +ARGV+. If a block is supplied, each line in turn will be yielded to the
13060  * block, otherwise an enumerator is returned.
13061  * The optional _limit_ argument is an +Integer+ specifying the maximum
13062  * length of each line; longer lines will be split according to this limit.
13063  *
13064  * This method allows you to treat the files supplied on the command line as
13065  * a single file consisting of the concatenation of each named file. After
13066  * the last line of the first file has been returned, the first line of the
13067  * second file is returned. The +ARGF.filename+ and +ARGF.lineno+ methods can
13068  * be used to determine the filename of the current line and line number of
13069  * the whole input, respectively.
13070  *
13071  * For example, the following code prints out each line of each named file
13072  * prefixed with its line number, displaying the filename once per file:
13073  *
13074  * ARGF.each_line do |line|
13075  * puts ARGF.filename if ARGF.file.lineno == 1
13076  * puts "#{ARGF.file.lineno}: #{line}"
13077  * end
13078  *
13079  * While the following code prints only the first file's name at first, and
13080  * the contents with line number counted through all named files.
13081  *
13082  * ARGF.each_line do |line|
13083  * puts ARGF.filename if ARGF.lineno == 1
13084  * puts "#{ARGF.lineno}: #{line}"
13085  * end
13086  */
13087 static VALUE
13088 argf_each_line(int argc, VALUE *argv, VALUE argf)
13089 {
13090  RETURN_ENUMERATOR(argf, argc, argv);
13091  FOREACH_ARGF() {
13092  argf_block_call_line(rb_intern("each_line"), argc, argv, argf);
13093  }
13094  return argf;
13095 }
13096 
13097 /*
13098  * call-seq:
13099  * ARGF.each_byte {|byte| block } -> ARGF
13100  * ARGF.each_byte -> an_enumerator
13101  *
13102  * Iterates over each byte of each file in +ARGV+.
13103  * A byte is returned as an +Integer+ in the range 0..255.
13104  *
13105  * This method allows you to treat the files supplied on the command line as
13106  * a single file consisting of the concatenation of each named file. After
13107  * the last byte of the first file has been returned, the first byte of the
13108  * second file is returned. The +ARGF.filename+ method can be used to
13109  * determine the filename of the current byte.
13110  *
13111  * If no block is given, an enumerator is returned instead.
13112  *
13113  * For example:
13114  *
13115  * ARGF.bytes.to_a #=> [35, 32, ... 95, 10]
13116  *
13117  */
13118 static VALUE
13119 argf_each_byte(VALUE argf)
13120 {
13121  RETURN_ENUMERATOR(argf, 0, 0);
13122  FOREACH_ARGF() {
13123  argf_block_call(rb_intern("each_byte"), 0, 0, argf);
13124  }
13125  return argf;
13126 }
13127 
13128 /*
13129  * call-seq:
13130  * ARGF.each_char {|char| block } -> ARGF
13131  * ARGF.each_char -> an_enumerator
13132  *
13133  * Iterates over each character of each file in +ARGF+.
13134  *
13135  * This method allows you to treat the files supplied on the command line as
13136  * a single file consisting of the concatenation of each named file. After
13137  * the last character of the first file has been returned, the first
13138  * character of the second file is returned. The +ARGF.filename+ method can
13139  * be used to determine the name of the file in which the current character
13140  * appears.
13141  *
13142  * If no block is given, an enumerator is returned instead.
13143  */
13144 static VALUE
13145 argf_each_char(VALUE argf)
13146 {
13147  RETURN_ENUMERATOR(argf, 0, 0);
13148  FOREACH_ARGF() {
13149  argf_block_call(rb_intern("each_char"), 0, 0, argf);
13150  }
13151  return argf;
13152 }
13153 
13154 /*
13155  * call-seq:
13156  * ARGF.each_codepoint {|codepoint| block } -> ARGF
13157  * ARGF.each_codepoint -> an_enumerator
13158  *
13159  * Iterates over each codepoint of each file in +ARGF+.
13160  *
13161  * This method allows you to treat the files supplied on the command line as
13162  * a single file consisting of the concatenation of each named file. After
13163  * the last codepoint of the first file has been returned, the first
13164  * codepoint of the second file is returned. The +ARGF.filename+ method can
13165  * be used to determine the name of the file in which the current codepoint
13166  * appears.
13167  *
13168  * If no block is given, an enumerator is returned instead.
13169  */
13170 static VALUE
13171 argf_each_codepoint(VALUE argf)
13172 {
13173  RETURN_ENUMERATOR(argf, 0, 0);
13174  FOREACH_ARGF() {
13175  argf_block_call(rb_intern("each_codepoint"), 0, 0, argf);
13176  }
13177  return argf;
13178 }
13179 
13180 /*
13181  * call-seq:
13182  * ARGF.filename -> String
13183  * ARGF.path -> String
13184  *
13185  * Returns the current filename. "-" is returned when the current file is
13186  * STDIN.
13187  *
13188  * For example:
13189  *
13190  * $ echo "foo" > foo
13191  * $ echo "bar" > bar
13192  * $ echo "glark" > glark
13193  *
13194  * $ ruby argf.rb foo bar glark
13195  *
13196  * ARGF.filename #=> "foo"
13197  * ARGF.read(5) #=> "foo\nb"
13198  * ARGF.filename #=> "bar"
13199  * ARGF.skip
13200  * ARGF.filename #=> "glark"
13201  */
13202 static VALUE
13203 argf_filename(VALUE argf)
13204 {
13205  next_argv();
13206  return ARGF.filename;
13207 }
13208 
13209 static VALUE
13210 argf_filename_getter(ID id, VALUE *var)
13211 {
13212  return argf_filename(*var);
13213 }
13214 
13215 /*
13216  * call-seq:
13217  * ARGF.file -> IO or File object
13218  *
13219  * Returns the current file as an +IO+ or +File+ object.
13220  * <code>$stdin</code> is returned when the current file is STDIN.
13221  *
13222  * For example:
13223  *
13224  * $ echo "foo" > foo
13225  * $ echo "bar" > bar
13226  *
13227  * $ ruby argf.rb foo bar
13228  *
13229  * ARGF.file #=> #<File:foo>
13230  * ARGF.read(5) #=> "foo\nb"
13231  * ARGF.file #=> #<File:bar>
13232  */
13233 static VALUE
13234 argf_file(VALUE argf)
13235 {
13236  next_argv();
13237  return ARGF.current_file;
13238 }
13239 
13240 /*
13241  * call-seq:
13242  * ARGF.binmode -> ARGF
13243  *
13244  * Puts +ARGF+ into binary mode. Once a stream is in binary mode, it cannot
13245  * be reset to non-binary mode. This option has the following effects:
13246  *
13247  * * Newline conversion is disabled.
13248  * * Encoding conversion is disabled.
13249  * * Content is treated as ASCII-8BIT.
13250  */
13251 static VALUE
13252 argf_binmode_m(VALUE argf)
13253 {
13254  ARGF.binmode = 1;
13255  next_argv();
13256  ARGF_FORWARD(0, 0);
13257  rb_io_ascii8bit_binmode(ARGF.current_file);
13258  return argf;
13259 }
13260 
13261 /*
13262  * call-seq:
13263  * ARGF.binmode? -> true or false
13264  *
13265  * Returns true if +ARGF+ is being read in binary mode; false otherwise.
13266  * To enable binary mode use +ARGF.binmode+.
13267  *
13268  * For example:
13269  *
13270  * ARGF.binmode? #=> false
13271  * ARGF.binmode
13272  * ARGF.binmode? #=> true
13273  */
13274 static VALUE
13275 argf_binmode_p(VALUE argf)
13276 {
13277  return RBOOL(ARGF.binmode);
13278 }
13279 
13280 /*
13281  * call-seq:
13282  * ARGF.skip -> ARGF
13283  *
13284  * Sets the current file to the next file in ARGV. If there aren't any more
13285  * files it has no effect.
13286  *
13287  * For example:
13288  *
13289  * $ ruby argf.rb foo bar
13290  * ARGF.filename #=> "foo"
13291  * ARGF.skip
13292  * ARGF.filename #=> "bar"
13293  */
13294 static VALUE
13295 argf_skip(VALUE argf)
13296 {
13297  if (ARGF.init_p && ARGF.next_p == 0) {
13298  argf_close(argf);
13299  ARGF.next_p = 1;
13300  }
13301  return argf;
13302 }
13303 
13304 /*
13305  * call-seq:
13306  * ARGF.close -> ARGF
13307  *
13308  * Closes the current file and skips to the next file in ARGV. If there are
13309  * no more files to open, just closes the current file. +STDIN+ will not be
13310  * closed.
13311  *
13312  * For example:
13313  *
13314  * $ ruby argf.rb foo bar
13315  *
13316  * ARGF.filename #=> "foo"
13317  * ARGF.close
13318  * ARGF.filename #=> "bar"
13319  * ARGF.close
13320  */
13321 static VALUE
13322 argf_close_m(VALUE argf)
13323 {
13324  next_argv();
13325  argf_close(argf);
13326  if (ARGF.next_p != -1) {
13327  ARGF.next_p = 1;
13328  }
13329  ARGF.lineno = 0;
13330  return argf;
13331 }
13332 
13333 /*
13334  * call-seq:
13335  * ARGF.closed? -> true or false
13336  *
13337  * Returns _true_ if the current file has been closed; _false_ otherwise. Use
13338  * +ARGF.close+ to actually close the current file.
13339  */
13340 static VALUE
13341 argf_closed(VALUE argf)
13342 {
13343  next_argv();
13344  ARGF_FORWARD(0, 0);
13345  return rb_io_closed(ARGF.current_file);
13346 }
13347 
13348 /*
13349  * call-seq:
13350  * ARGF.to_s -> String
13351  *
13352  * Returns "ARGF".
13353  */
13354 static VALUE
13355 argf_to_s(VALUE argf)
13356 {
13357  return rb_str_new2("ARGF");
13358 }
13359 
13360 /*
13361  * call-seq:
13362  * ARGF.inplace_mode -> String
13363  *
13364  * Returns the file extension appended to the names of modified files under
13365  * in-place edit mode. This value can be set using +ARGF.inplace_mode=+ or
13366  * passing the +-i+ switch to the Ruby binary.
13367  */
13368 static VALUE
13369 argf_inplace_mode_get(VALUE argf)
13370 {
13371  if (!ARGF.inplace) return Qnil;
13372  if (NIL_P(ARGF.inplace)) return rb_str_new(0, 0);
13373  return rb_str_dup(ARGF.inplace);
13374 }
13375 
13376 static VALUE
13377 opt_i_get(ID id, VALUE *var)
13378 {
13379  return argf_inplace_mode_get(*var);
13380 }
13381 
13382 /*
13383  * call-seq:
13384  * ARGF.inplace_mode = ext -> ARGF
13385  *
13386  * Sets the filename extension for in-place editing mode to the given String.
13387  * Each file being edited has this value appended to its filename. The
13388  * modified file is saved under this new name.
13389  *
13390  * For example:
13391  *
13392  * $ ruby argf.rb file.txt
13393  *
13394  * ARGF.inplace_mode = '.bak'
13395  * ARGF.each_line do |line|
13396  * print line.sub("foo","bar")
13397  * end
13398  *
13399  * Each line of _file.txt_ has the first occurrence of "foo" replaced with
13400  * "bar", then the new line is written out to _file.txt.bak_.
13401  */
13402 static VALUE
13403 argf_inplace_mode_set(VALUE argf, VALUE val)
13404 {
13405  if (!RTEST(val)) {
13406  ARGF.inplace = Qfalse;
13407  }
13408  else if (StringValueCStr(val), !RSTRING_LEN(val)) {
13409  ARGF.inplace = Qnil;
13410  }
13411  else {
13412  ARGF.inplace = rb_str_new_frozen(val);
13413  }
13414  return argf;
13415 }
13416 
13417 static void
13418 opt_i_set(VALUE val, ID id, VALUE *var)
13419 {
13420  argf_inplace_mode_set(*var, val);
13421 }
13422 
13423 void
13424 ruby_set_inplace_mode(const char *suffix)
13425 {
13426  ARGF.inplace = !suffix ? Qfalse : !*suffix ? Qnil : rb_str_new(suffix, strlen(suffix));
13427 }
13428 
13429 /*
13430  * call-seq:
13431  * ARGF.argv -> ARGV
13432  *
13433  * Returns the +ARGV+ array, which contains the arguments passed to your
13434  * script, one per element.
13435  *
13436  * For example:
13437  *
13438  * $ ruby argf.rb -v glark.txt
13439  *
13440  * ARGF.argv #=> ["-v", "glark.txt"]
13441  *
13442  */
13443 static VALUE
13444 argf_argv(VALUE argf)
13445 {
13446  return ARGF.argv;
13447 }
13448 
13449 static VALUE
13450 argf_argv_getter(ID id, VALUE *var)
13451 {
13452  return argf_argv(*var);
13453 }
13454 
13455 VALUE
13457 {
13458  return ARGF.argv;
13459 }
13460 
13461 /*
13462  * call-seq:
13463  * ARGF.to_write_io -> io
13464  *
13465  * Returns IO instance tied to _ARGF_ for writing if inplace mode is
13466  * enabled.
13467  */
13468 static VALUE
13469 argf_write_io(VALUE argf)
13470 {
13471  if (!RTEST(ARGF.current_file)) {
13472  rb_raise(rb_eIOError, "not opened for writing");
13473  }
13474  return GetWriteIO(ARGF.current_file);
13475 }
13476 
13477 /*
13478  * call-seq:
13479  * ARGF.write(string) -> integer
13480  *
13481  * Writes _string_ if inplace mode.
13482  */
13483 static VALUE
13484 argf_write(VALUE argf, VALUE str)
13485 {
13486  return rb_io_write(argf_write_io(argf), str);
13487 }
13488 
13489 void
13490 rb_readwrite_sys_fail(enum rb_io_wait_readwrite waiting, const char *mesg)
13491 {
13492  rb_readwrite_syserr_fail(waiting, errno, mesg);
13493 }
13494 
13495 void
13496 rb_readwrite_syserr_fail(enum rb_io_wait_readwrite waiting, int n, const char *mesg)
13497 {
13498  VALUE arg, c = Qnil;
13499  arg = mesg ? rb_str_new2(mesg) : Qnil;
13500  switch (waiting) {
13501  case RB_IO_WAIT_WRITABLE:
13502  switch (n) {
13503  case EAGAIN:
13504  c = rb_eEAGAINWaitWritable;
13505  break;
13506 #if EAGAIN != EWOULDBLOCK
13507  case EWOULDBLOCK:
13508  c = rb_eEWOULDBLOCKWaitWritable;
13509  break;
13510 #endif
13511  case EINPROGRESS:
13512  c = rb_eEINPROGRESSWaitWritable;
13513  break;
13514  default:
13516  }
13517  break;
13518  case RB_IO_WAIT_READABLE:
13519  switch (n) {
13520  case EAGAIN:
13521  c = rb_eEAGAINWaitReadable;
13522  break;
13523 #if EAGAIN != EWOULDBLOCK
13524  case EWOULDBLOCK:
13525  c = rb_eEWOULDBLOCKWaitReadable;
13526  break;
13527 #endif
13528  case EINPROGRESS:
13529  c = rb_eEINPROGRESSWaitReadable;
13530  break;
13531  default:
13533  }
13534  break;
13535  default:
13536  rb_bug("invalid read/write type passed to rb_readwrite_sys_fail: %d", waiting);
13537  }
13538  rb_exc_raise(rb_class_new_instance(1, &arg, c));
13539 }
13540 
13541 static VALUE
13542 get_LAST_READ_LINE(ID _x, VALUE *_y)
13543 {
13544  return rb_lastline_get();
13545 }
13546 
13547 static void
13548 set_LAST_READ_LINE(VALUE val, ID _x, VALUE *_y)
13549 {
13550  rb_lastline_set(val);
13551 }
13552 
13553 /*
13554  * Document-class: IOError
13555  *
13556  * Raised when an IO operation fails.
13557  *
13558  * File.open("/etc/hosts") {|f| f << "example"}
13559  * #=> IOError: not opened for writing
13560  *
13561  * File.open("/etc/hosts") {|f| f.close; f.read }
13562  * #=> IOError: closed stream
13563  *
13564  * Note that some IO failures raise <code>SystemCallError</code>s
13565  * and these are not subclasses of IOError:
13566  *
13567  * File.open("does/not/exist")
13568  * #=> Errno::ENOENT: No such file or directory - does/not/exist
13569  */
13570 
13571 /*
13572  * Document-class: EOFError
13573  *
13574  * Raised by some IO operations when reaching the end of file. Many IO
13575  * methods exist in two forms,
13576  *
13577  * one that returns +nil+ when the end of file is reached, the other
13578  * raises +EOFError+.
13579  *
13580  * +EOFError+ is a subclass of +IOError+.
13581  *
13582  * file = File.open("/etc/hosts")
13583  * file.read
13584  * file.gets #=> nil
13585  * file.readline #=> EOFError: end of file reached
13586  */
13587 
13588 /*
13589  * Document-class: ARGF
13590  *
13591  * +ARGF+ is a stream designed for use in scripts that process files given as
13592  * command-line arguments or passed in via STDIN.
13593  *
13594  * The arguments passed to your script are stored in the +ARGV+ Array, one
13595  * argument per element. +ARGF+ assumes that any arguments that aren't
13596  * filenames have been removed from +ARGV+. For example:
13597  *
13598  * $ ruby argf.rb --verbose file1 file2
13599  *
13600  * ARGV #=> ["--verbose", "file1", "file2"]
13601  * option = ARGV.shift #=> "--verbose"
13602  * ARGV #=> ["file1", "file2"]
13603  *
13604  * You can now use +ARGF+ to work with a concatenation of each of these named
13605  * files. For instance, +ARGF.read+ will return the contents of _file1_
13606  * followed by the contents of _file2_.
13607  *
13608  * After a file in +ARGV+ has been read +ARGF+ removes it from the Array.
13609  * Thus, after all files have been read +ARGV+ will be empty.
13610  *
13611  * You can manipulate +ARGV+ yourself to control what +ARGF+ operates on. If
13612  * you remove a file from +ARGV+, it is ignored by +ARGF+; if you add files to
13613  * +ARGV+, they are treated as if they were named on the command line. For
13614  * example:
13615  *
13616  * ARGV.replace ["file1"]
13617  * ARGF.readlines # Returns the contents of file1 as an Array
13618  * ARGV #=> []
13619  * ARGV.replace ["file2", "file3"]
13620  * ARGF.read # Returns the contents of file2 and file3
13621  *
13622  * If +ARGV+ is empty, +ARGF+ acts as if it contained STDIN, i.e. the data
13623  * piped to your script. For example:
13624  *
13625  * $ echo "glark" | ruby -e 'p ARGF.read'
13626  * "glark\n"
13627  */
13628 
13629 /*
13630  * The IO class is the basis for all input and output in Ruby.
13631  * An I/O stream may be <em>duplexed</em> (that is, bidirectional), and
13632  * so may use more than one native operating system stream.
13633  *
13634  * Many of the examples in this section use the File class, the only standard
13635  * subclass of IO. The two classes are closely associated. Like the File
13636  * class, the Socket library subclasses from IO (such as TCPSocket or
13637  * UDPSocket).
13638  *
13639  * The Kernel#open method can create an IO (or File) object for these types
13640  * of arguments:
13641  *
13642  * * A plain string represents a filename suitable for the underlying
13643  * operating system.
13644  *
13645  * * A string starting with <code>"|"</code> indicates a subprocess.
13646  * The remainder of the string following the <code>"|"</code> is
13647  * invoked as a process with appropriate input/output channels
13648  * connected to it.
13649  *
13650  * * A string equal to <code>"|-"</code> will create another Ruby
13651  * instance as a subprocess.
13652  *
13653  * The IO may be opened with different file modes (read-only, write-only) and
13654  * encodings for proper conversion. See IO.new for these options. See
13655  * Kernel#open for details of the various command formats described above.
13656  *
13657  * IO.popen, the Open3 library, or Process#spawn may also be used to
13658  * communicate with subprocesses through an IO.
13659  *
13660  * Ruby will convert pathnames between different operating system
13661  * conventions if possible. For instance, on a Windows system the
13662  * filename <code>"/gumby/ruby/test.rb"</code> will be opened as
13663  * <code>"\gumby\ruby\test.rb"</code>. When specifying a Windows-style
13664  * filename in a Ruby string, remember to escape the backslashes:
13665  *
13666  * "C:\\gumby\\ruby\\test.rb"
13667  *
13668  * Our examples here will use the Unix-style forward slashes;
13669  * File::ALT_SEPARATOR can be used to get the platform-specific separator
13670  * character.
13671  *
13672  * The global constant ARGF (also accessible as <code>$<</code>) provides an
13673  * IO-like stream which allows access to all files mentioned on the
13674  * command line (or STDIN if no files are mentioned). ARGF#path and its alias
13675  * ARGF#filename are provided to access the name of the file currently being
13676  * read.
13677  *
13678  * == io/console
13679  *
13680  * The io/console extension provides methods for interacting with the
13681  * console. The console can be accessed from IO.console or the standard
13682  * input/output/error IO objects.
13683  *
13684  * Requiring io/console adds the following methods:
13685  *
13686  * * IO::console
13687  * * IO#raw
13688  * * IO#raw!
13689  * * IO#cooked
13690  * * IO#cooked!
13691  * * IO#getch
13692  * * IO#echo=
13693  * * IO#echo?
13694  * * IO#noecho
13695  * * IO#winsize
13696  * * IO#winsize=
13697  * * IO#iflush
13698  * * IO#ioflush
13699  * * IO#oflush
13700  *
13701  * Example:
13702  *
13703  * require 'io/console'
13704  * rows, columns = $stdout.winsize
13705  * puts "Your screen is #{columns} wide and #{rows} tall"
13706  *
13707  * == Example Files
13708  *
13709  * Many examples here use these filenames and their corresponding files:
13710  *
13711  * - <tt>t.txt</tt>: A text-only file that is assumed to exist via:
13712  *
13713  * text = <<~EOT
13714  * This is line one.
13715  * This is the second line.
13716  * This is the third line.
13717  * EOT
13718  * File.write('t.txt', text)
13719  *
13720  * - <tt>t.dat</tt>: A data file that is assumed to exist via:
13721  *
13722  * data = "\u9990\u9991\u9992\u9993\u9994"
13723  * f = File.open('t.dat', 'wb:UTF-16')
13724  * f.write(data)
13725  * f.close
13726  *
13727  * - <tt>t.rus</tt>: A Russian-language text file that is assumed to exist via:
13728  *
13729  * File.write('t.rus', "\u{442 435 441 442}")
13730  *
13731  * - <tt>t.tmp</tt>: A file that is assumed _not_ to exist.
13732  *
13733  * == Modes
13734  *
13735  * A number of \IO method calls must or may specify a _mode_ for the stream;
13736  * the mode determines how stream is to be accessible, including:
13737  *
13738  * - Whether the stream is to be read-only, write-only, or read-write.
13739  * - Whether the stream is positioned at its beginning or its end.
13740  * - Whether the stream treats data as text-only or binary.
13741  * - The external and internal encodings.
13742  *
13743  * === Mode Specified as an \Integer
13744  *
13745  * When +mode+ is an integer it must be one or more (combined by bitwise OR (<tt>|</tt>)
13746  * of the modes defined in File::Constants:
13747  *
13748  * - +File::RDONLY+: Open for reading only.
13749  * - +File::WRONLY+: Open for writing only.
13750  * - +File::RDWR+: Open for reading and writing.
13751  * - +File::APPEND+: Open for appending only.
13752  * - +File::CREAT+: Create file if it does not exist.
13753  * - +File::EXCL+: Raise an exception if +File::CREAT+ is given and the file exists.
13754  *
13755  * Examples:
13756  *
13757  * File.new('t.txt', File::RDONLY)
13758  * File.new('t.tmp', File::RDWR | File::CREAT | File::EXCL)
13759  *
13760  * Note: Method IO#set_encoding does not allow the mode to be specified as an integer.
13761  *
13762  * === Mode Specified As a \String
13763  *
13764  * When +mode+ is a string it must begin with one of the following:
13765  *
13766  * - <tt>'r'</tt>: Read-only stream, positioned at the beginning;
13767  * the stream cannot be changed to writable.
13768  * - <tt>'w'</tt>: Write-only stream, positioned at the beginning;
13769  * the stream cannot be changed to readable.
13770  * - <tt>'a'</tt>: Write-only stream, positioned at the end;
13771  * every write appends to the end;
13772  * the stream cannot be changed to readable.
13773  * - <tt>'r+'</tt>: Read-write stream, positioned at the beginning.
13774  * - <tt>'w+'</tt>: Read-write stream, positioned at the end.
13775  * - <tt>'a+'</tt>: Read-write stream, positioned at the end.
13776  *
13777  * For a writable file stream (that is, any except read-only),
13778  * the file is truncated to zero if it exists,
13779  * and is created if it does not exist.
13780  *
13781  * Examples:
13782  *
13783  * File.open('t.txt', 'r')
13784  * File.open('t.tmp', 'w')
13785  *
13786  * Either of the following may be suffixed to any of the above:
13787  *
13788  * - <tt>'t'</tt>: Text data; sets the default external encoding to +Encoding::UTF_8+;
13789  * on Windows, enables conversion between EOL and CRLF.
13790  * - <tt>'b'</tt>: Binary data; sets the default external encoding to +Encoding::ASCII_8BIT+;
13791  * on Windows, suppresses conversion between EOL and CRLF.
13792  *
13793  * If neither is given, the stream defaults to text data.
13794  *
13795  * Examples:
13796  *
13797  * File.open('t.txt', 'rt')
13798  * File.open('t.dat', 'rb')
13799  *
13800  * The following may be suffixed to any writable mode above:
13801  *
13802  * - <tt>'x'</tt>: Creates the file if it does not exist;
13803  * raises an exception if the file exists.
13804  *
13805  * Example:
13806  *
13807  * File.open('t.tmp', 'wx')
13808  *
13809  * Finally, the mode string may specify encodings --
13810  * either external encoding only or both external and internal encodings --
13811  * by appending one or both encoding names, separated by colons:
13812  *
13813  * f = File.new('t.dat', 'rb')
13814  * f.external_encoding # => #<Encoding:ASCII-8BIT>
13815  * f.internal_encoding # => nil
13816  * f = File.new('t.dat', 'rb:UTF-16')
13817  * f.external_encoding # => #<Encoding:UTF-16 (dummy)>
13818  * f.internal_encoding # => nil
13819  * f = File.new('t.dat', 'rb:UTF-16:UTF-16')
13820  * f.external_encoding # => #<Encoding:UTF-16 (dummy)>
13821  * f.internal_encoding # => #<Encoding:UTF-16>
13822  *
13823  * The numerous encoding names are available in array Encoding.name_list:
13824  *
13825  * Encoding.name_list.size # => 175
13826  * Encoding.name_list.take(3) # => ["ASCII-8BIT", "UTF-8", "US-ASCII"]
13827  *
13828  * == Encodings
13829  *
13830  * When the external encoding is set,
13831  * strings read are tagged by that encoding
13832  * when reading, and strings written are converted to that
13833  * encoding when writing.
13834  *
13835  * When both external and internal encodings are set,
13836  * strings read are converted from external to internal encoding,
13837  * and strings written are converted from internal to external encoding.
13838  * For further details about transcoding input and output, see Encoding.
13839  *
13840  * If the external encoding is <tt>'BOM|UTF-8'</tt>, <tt>'BOM|UTF-16LE'</tt>
13841  * or <tt>'BOM|UTF16-BE'</tt>, Ruby checks for
13842  * a Unicode BOM in the input document to help determine the encoding. For
13843  * UTF-16 encodings the file open mode must be binary.
13844  * If the BOM is found, it is stripped and the external encoding from the BOM is used.
13845  *
13846  * Note that the BOM-style encoding option is case insensitive,
13847  * so 'bom|utf-8' is also valid.)
13848  *
13849  * == Open Options
13850  *
13851  * A number of \IO methods accept an optional parameter +opts+,
13852  * which determines how a new stream is to be opened:
13853  *
13854  * - +:mode+: Stream mode.
13855  * - +:flags+: \Integer file open flags;
13856  * If +mode+ is also given, the two are bitwise-ORed.
13857  * - +:external_encoding+: External encoding for the stream.
13858  * - +:internal_encoding+: Internal encoding for the stream.
13859  * <tt>'-'</tt> is a synonym for the default internal encoding.
13860  * If the value is +nil+ no conversion occurs.
13861  * - +:encoding+: Specifies external and internal encodings as <tt>'extern:intern'</tt>.
13862  * - +:textmode+: If a truthy value, specifies the mode as text-only, binary otherwise.
13863  * - +:binmode+: If a truthy value, specifies the mode as binary, text-only otherwise.
13864  * - +:autoclose+: If a truthy value, specifies that the +fd+ will close
13865  * when the stream closes; otherwise it remains open.
13866  *
13867  * Also available are the options offered in String#encode,
13868  * which may control conversion between external internal encoding.
13869  *
13870  * == Getline Options
13871  *
13872  * A number of \IO methods accept optional keyword arguments
13873  * that determine how a stream is to be treated:
13874  *
13875  * - +:chomp+: If +true+, line separators are omitted; default is +false+.
13876  *
13877  * == Position
13878  *
13879  * An \IO stream has a _position_, which is the non-negative integer offset
13880  * (in bytes) in the stream where the next read or write will occur.
13881  *
13882  * Note that a text stream may have multi-byte characters,
13883  * so a text stream whose position is +n+ (_bytes_) may not have +n+ _characters_
13884  * preceding the current position -- there may be fewer.
13885  *
13886  * A new stream is initially positioned:
13887  *
13888  * - At the beginning (position +0+)
13889  * if its mode is <tt>'r'</tt>, <tt>'w'</tt>, or <tt>'r+'</tt>.
13890  * - At the end (position <tt>self.size</tt>)
13891  * if its mode is <tt>'a'</tt>, <tt>'w+'</tt>, or <tt>'a+'</tt>.
13892  *
13893  * Methods to query the position:
13894  *
13895  * - IO#tell and its alias IO#pos return the position for an open stream.
13896  * - IO#eof? and its alias IO#eof return whether the position is at the end
13897  * of a readable stream.
13898  *
13899  * Reading from a stream usually changes its position:
13900  *
13901  * f = File.open('t.txt')
13902  * f.tell # => 0
13903  * f.readline # => "This is line one.\n"
13904  * f.tell # => 19
13905  * f.readline # => "This is the second line.\n"
13906  * f.tell # => 45
13907  * f.eof? # => false
13908  * f.readline # => "Here's the third line.\n"
13909  * f.eof? # => true
13910  *
13911  *
13912  * Writing to a stream usually changes its position:
13913  *
13914  * f = File.open('t.tmp', 'w')
13915  * f.tell # => 0
13916  * f.write('foo') # => 3
13917  * f.tell # => 3
13918  * f.write('bar') # => 3
13919  * f.tell # => 6
13920  *
13921  *
13922  * Iterating over a stream usually changes its position:
13923  *
13924  * f = File.open('t.txt')
13925  * f.each do |line|
13926  * p "position=#{f.pos} eof?=#{f.eof?} line=#{line}"
13927  * end
13928  *
13929  * Output:
13930  *
13931  * "position=19 eof?=false line=This is line one.\n"
13932  * "position=45 eof?=false line=This is the second line.\n"
13933  * "position=70 eof?=true line=This is the third line.\n"
13934  *
13935  * The position may also be changed by certain other methods:
13936  *
13937  * - IO#pos= and IO#seek change the position to a specified offset.
13938  * - IO#rewind changes the position to the beginning.
13939  *
13940  * == Line Number
13941  *
13942  * A readable \IO stream has a _line_ _number_,
13943  * which is the non-negative integer line number
13944  * in the stream where the next read will occur.
13945  *
13946  * A new stream is initially has line number +0+.
13947  *
13948  * \Method IO#lineno returns the line number.
13949  *
13950  * Reading lines from a stream usually changes its line number:
13951  *
13952  * f = File.open('t.txt', 'r')
13953  * f.lineno # => 0
13954  * f.readline # => "This is line one.\n"
13955  * f.lineno # => 1
13956  * f.readline # => "This is the second line.\n"
13957  * f.lineno # => 2
13958  * f.readline # => "Here's the third line.\n"
13959  * f.lineno # => 3
13960  * f.eof? # => true
13961  *
13962  * Iterating over lines in a stream usually changes its line number:
13963  *
13964  * f = File.open('t.txt')
13965  * f.each_line do |line|
13966  * p "position=#{f.pos} eof?=#{f.eof?} line=#{line}"
13967  * end
13968  *
13969  * Output:
13970  *
13971  * "position=19 eof?=false line=This is line one.\n"
13972  * "position=45 eof?=false line=This is the second line.\n"
13973  * "position=70 eof?=true line=This is the third line.\n"
13974  *
13975  * == What's Here
13976  *
13977  * First, what's elsewhere. \Class \IO:
13978  *
13979  * - Inherits from {class Object}[Object.html#class-Object-label-What-27s+Here].
13980  * - Includes {module Enumerable}[Enumerable.html#module-Enumerable-label-What-27s+Here],
13981  * which provides dozens of additional methods.
13982  *
13983  * Here, class \IO provides methods that are useful for:
13984  *
13985  * - {Creating}[#class-IO-label-Creating]
13986  * - {Reading}[#class-IO-label-Reading]
13987  * - {Writing}[#class-IO-label-Writing]
13988  * - {Positioning}[#class-IO-label-Positioning]
13989  * - {Iterating}[#class-IO-label-Iterating]
13990  * - {Settings}[#class-IO-label-Settings]
13991  * - {Querying}[#class-IO-label-Querying]
13992  * - {Buffering}[#class-IO-label-Buffering]
13993  * - {Low-Level Access}[#class-IO-label-Low-Level+Access]
13994  * - {Other}[#class-IO-label-Other]
13995  *
13996  * === Creating
13997  *
13998  * - ::new (aliased as ::for_fd):: Creates and returns a new \IO object for the given
13999  * integer file descriptor.
14000  * - ::open:: Creates a new \IO object.
14001  * - ::pipe:: Creates a connected pair of reader and writer \IO objects.
14002  * - ::popen:: Creates an \IO object to interact with a subprocess.
14003  * - ::select:: Selects which given \IO instances are ready for reading,
14004  * writing, or have pending exceptions.
14005  *
14006  * === Reading
14007  *
14008  * - ::binread:: Returns a binary string with all or a subset of bytes
14009  * from the given file.
14010  * - ::read:: Returns a string with all or a subset of bytes from the given file.
14011  * - ::readlines:: Returns an array of strings, which are the lines from the given file.
14012  * - #getbyte:: Returns the next 8-bit byte read from +self+ as an integer.
14013  * - #getc:: Returns the next character read from +self+ as a string.
14014  * - #gets:: Returns the line read from +self+.
14015  * - #pread:: Returns all or the next _n_ bytes read from +self+,
14016  * not updating the receiver's offset.
14017  * - #read:: Returns all remaining or the next _n_ bytes read from +self+
14018  * for a given _n_.
14019  * - #read_nonblock:: the next _n_ bytes read from +self+ for a given _n_,
14020  * in non-block mode.
14021  * - #readbyte:: Returns the next byte read from +self+;
14022  * same as #getbyte, but raises an exception on end-of-file.
14023  * - #readchar:: Returns the next character read from +self+;
14024  * same as #getc, but raises an exception on end-of-file.
14025  * - #readline:: Returns the next line read from +self+;
14026  * same as #getline, but raises an exception of end-of-file.
14027  * - #readlines:: Returns an array of all lines read read from +self+.
14028  * - #readpartial:: Returns up to the given number of bytes from +self+.
14029  *
14030  * === Writing
14031  *
14032  * - ::binwrite:: Writes the given string to the file at the given filepath,
14033  in binary mode.
14034  * - ::write:: Writes the given string to +self+.
14035  * - {::<<}[#method-i-3C-3C]:: Appends the given string to +self+.
14036  * - #print:: Prints last read line or given objects to +self+.
14037  * - #printf:: Writes to +self+ based on the given format string and objects.
14038  * - #putc:: Writes a character to +self+.
14039  * - #puts:: Writes lines to +self+, making sure line ends with a newline.
14040  * - #pwrite:: Writes the given string at the given offset,
14041  * not updating the receiver's offset.
14042  * - #write:: Writes one or more given strings to +self+.
14043  * - #write_nonblock:: Writes one or more given strings to +self+ in non-blocking mode.
14044  *
14045  * === Positioning
14046  *
14047  * - #lineno:: Returns the current line number in +self+.
14048  * - #lineno=:: Sets the line number is +self+.
14049  * - #pos (aliased as #tell):: Returns the current byte offset in +self+.
14050  * - #pos=:: Sets the byte offset in +self+.
14051  * - #reopen:: Reassociates +self+ with a new or existing \IO stream.
14052  * - #rewind:: Positions +self+ to the beginning of input.
14053  * - #seek:: Sets the offset for +self+ relative to given position.
14054  *
14055  * === Iterating
14056  *
14057  * - ::foreach:: Yields each line of given file to the block.
14058  * - #each (aliased as #each_line):: Calls the given block
14059  * with each successive line in +self+.
14060  * - #each_byte:: Calls the given block with each successive byte in +self+
14061  * as an integer.
14062  * - #each_char:: Calls the given block with each successive character in +self+
14063  * as a string.
14064  * - #each_codepoint:: Calls the given block with each successive codepoint in +self+
14065  * as an integer.
14066  *
14067  * === Settings
14068  *
14069  * - #autoclose=:: Sets whether +self+ auto-closes.
14070  * - #binmode:: Sets +self+ to binary mode.
14071  * - #close:: Closes +self+.
14072  * - #close_on_exec=:: Sets the close-on-exec flag.
14073  * - #close_read:: Closes +self+ for reading.
14074  * - #close_write:: Closes +self+ for writing.
14075  * - #set_encoding:: Sets the encoding for +self+.
14076  * - #set_encoding_by_bom:: Sets the encoding for +self+, based on its
14077  * Unicode byte-order-mark.
14078  * - #sync=:: Sets the sync-mode to the given value.
14079  *
14080  * === Querying
14081  *
14082  * - #autoclose?:: Returns whether +self+ auto-closes.
14083  * - #binmode?:: Returns whether +self+ is in binary mode.
14084  * - #close_on_exec?:: Returns the close-on-exec flag for +self+.
14085  * - #closed?:: Returns whether +self+ is closed.
14086  * - #eof? (aliased as #eof):: Returns whether +self+ is at end-of-file.
14087  * - #external_encoding:: Returns the external encoding object for +self+.
14088  * - #fileno (aliased as #to_i):: Returns the integer file descriptor for +self+
14089  * - #internal_encoding:: Returns the internal encoding object for +self+.
14090  * - #pid:: Returns the process ID of a child process associated with +self+,
14091  * if +self+ was created by ::popen.
14092  * - #stat:: Returns the File::Stat object containing status information for +self+.
14093  * - #sync:: Returns whether +self+ is in sync-mode.
14094  * - #tty (aliased as #isatty):: Returns whether +self+ is a terminal.
14095  *
14096  * === Buffering
14097  *
14098  * - #fdatasync:: Immediately writes all buffered data in +self+ to disk.
14099  * - #flush:: Flushes any buffered data within +self+ to the underlying
14100  * operating system.
14101  * - #fsync:: Immediately writes all buffered data and attributes in +self+ to disk.
14102  * - #ungetbyte:: Prepends buffer for +self+ with given integer byte or string.
14103  * - #ungetc:: Prepends buffer for +self+ with given string.
14104  *
14105  * === Low-Level Access
14106  *
14107  * - ::sysopen:: Opens the file given by its path,
14108  * returning the integer file descriptor.
14109  * - #advise:: Announces the intention to access data from +self+ in a specific way.
14110  * - #fcntl:: Passes a low-level command to the file specified
14111  * by the given file descriptor.
14112  * - #ioctl:: Passes a low-level command to the device specified
14113  * by the given file descriptor.
14114  * - #sysread:: Returns up to the next _n_ bytes read from self using a low-level read.
14115  * - #sysseek:: Sets the offset for +self+.
14116  * - #syswrite:: Writes the given string to +self+ using a low-level write.
14117  *
14118  * === Other
14119  *
14120  * - ::copy_stream:: Copies data from a source to a destination,
14121  * each of which is a filepath or an \IO-like object.
14122  * - ::try_convert:: Returns a new \IO object resulting from converting
14123  * the given object.
14124  * - #inspect:: Returns the string representation of +self+.
14125  *
14126  */
14127 
14128 void
14129 Init_IO(void)
14130 {
14131  VALUE rb_cARGF;
14132 #ifdef __CYGWIN__
14133 #include <sys/cygwin.h>
14134  static struct __cygwin_perfile pf[] =
14135  {
14136  {"", O_RDONLY | O_BINARY},
14137  {"", O_WRONLY | O_BINARY},
14138  {"", O_RDWR | O_BINARY},
14139  {"", O_APPEND | O_BINARY},
14140  {NULL, 0}
14141  };
14142  cygwin_internal(CW_PERFILE, pf);
14143 #endif
14144 
14146  rb_eEOFError = rb_define_class("EOFError", rb_eIOError);
14147 
14148  id_write = rb_intern_const("write");
14149  id_read = rb_intern_const("read");
14150  id_getc = rb_intern_const("getc");
14151  id_flush = rb_intern_const("flush");
14152  id_readpartial = rb_intern_const("readpartial");
14153  id_set_encoding = rb_intern_const("set_encoding");
14154  id_fileno = rb_intern_const("fileno");
14155 
14156  rb_define_global_function("syscall", rb_f_syscall, -1);
14157 
14158  rb_define_global_function("open", rb_f_open, -1);
14159  rb_define_global_function("printf", rb_f_printf, -1);
14160  rb_define_global_function("print", rb_f_print, -1);
14161  rb_define_global_function("putc", rb_f_putc, 1);
14162  rb_define_global_function("puts", rb_f_puts, -1);
14163  rb_define_global_function("gets", rb_f_gets, -1);
14164  rb_define_global_function("readline", rb_f_readline, -1);
14165  rb_define_global_function("select", rb_f_select, -1);
14166 
14167  rb_define_global_function("readlines", rb_f_readlines, -1);
14168 
14169  rb_define_global_function("`", rb_f_backquote, 1);
14170 
14171  rb_define_global_function("p", rb_f_p, -1);
14172  rb_define_method(rb_mKernel, "display", rb_obj_display, -1);
14173 
14174  rb_cIO = rb_define_class("IO", rb_cObject);
14176 
14180 
14181  /* exception to wait for reading. see IO.select. */
14182  rb_mWaitReadable = rb_define_module_under(rb_cIO, "WaitReadable");
14183  /* exception to wait for writing. see IO.select. */
14184  rb_mWaitWritable = rb_define_module_under(rb_cIO, "WaitWritable");
14185  /* exception to wait for reading by EAGAIN. see IO.select. */
14186  rb_eEAGAINWaitReadable = rb_define_class_under(rb_cIO, "EAGAINWaitReadable", rb_eEAGAIN);
14187  rb_include_module(rb_eEAGAINWaitReadable, rb_mWaitReadable);
14188  /* exception to wait for writing by EAGAIN. see IO.select. */
14189  rb_eEAGAINWaitWritable = rb_define_class_under(rb_cIO, "EAGAINWaitWritable", rb_eEAGAIN);
14190  rb_include_module(rb_eEAGAINWaitWritable, rb_mWaitWritable);
14191 #if EAGAIN == EWOULDBLOCK
14192  rb_eEWOULDBLOCKWaitReadable = rb_eEAGAINWaitReadable;
14193  /* same as IO::EAGAINWaitReadable */
14194  rb_define_const(rb_cIO, "EWOULDBLOCKWaitReadable", rb_eEAGAINWaitReadable);
14195  rb_eEWOULDBLOCKWaitWritable = rb_eEAGAINWaitWritable;
14196  /* same as IO::EAGAINWaitWritable */
14197  rb_define_const(rb_cIO, "EWOULDBLOCKWaitWritable", rb_eEAGAINWaitWritable);
14198 #else
14199  /* exception to wait for reading by EWOULDBLOCK. see IO.select. */
14200  rb_eEWOULDBLOCKWaitReadable = rb_define_class_under(rb_cIO, "EWOULDBLOCKWaitReadable", rb_eEWOULDBLOCK);
14201  rb_include_module(rb_eEWOULDBLOCKWaitReadable, rb_mWaitReadable);
14202  /* exception to wait for writing by EWOULDBLOCK. see IO.select. */
14203  rb_eEWOULDBLOCKWaitWritable = rb_define_class_under(rb_cIO, "EWOULDBLOCKWaitWritable", rb_eEWOULDBLOCK);
14204  rb_include_module(rb_eEWOULDBLOCKWaitWritable, rb_mWaitWritable);
14205 #endif
14206  /* exception to wait for reading by EINPROGRESS. see IO.select. */
14207  rb_eEINPROGRESSWaitReadable = rb_define_class_under(rb_cIO, "EINPROGRESSWaitReadable", rb_eEINPROGRESS);
14208  rb_include_module(rb_eEINPROGRESSWaitReadable, rb_mWaitReadable);
14209  /* exception to wait for writing by EINPROGRESS. see IO.select. */
14210  rb_eEINPROGRESSWaitWritable = rb_define_class_under(rb_cIO, "EINPROGRESSWaitWritable", rb_eEINPROGRESS);
14211  rb_include_module(rb_eEINPROGRESSWaitWritable, rb_mWaitWritable);
14212 
14213 #if 0
14214  /* This is necessary only for forcing rdoc handle File::open */
14215  rb_define_singleton_method(rb_cFile, "open", rb_io_s_open, -1);
14216 #endif
14217 
14218  rb_define_alloc_func(rb_cIO, io_alloc);
14219  rb_define_singleton_method(rb_cIO, "new", rb_io_s_new, -1);
14220  rb_define_singleton_method(rb_cIO, "open", rb_io_s_open, -1);
14221  rb_define_singleton_method(rb_cIO, "sysopen", rb_io_s_sysopen, -1);
14222  rb_define_singleton_method(rb_cIO, "for_fd", rb_io_s_for_fd, -1);
14223  rb_define_singleton_method(rb_cIO, "popen", rb_io_s_popen, -1);
14224  rb_define_singleton_method(rb_cIO, "foreach", rb_io_s_foreach, -1);
14225  rb_define_singleton_method(rb_cIO, "readlines", rb_io_s_readlines, -1);
14226  rb_define_singleton_method(rb_cIO, "read", rb_io_s_read, -1);
14227  rb_define_singleton_method(rb_cIO, "binread", rb_io_s_binread, -1);
14228  rb_define_singleton_method(rb_cIO, "write", rb_io_s_write, -1);
14229  rb_define_singleton_method(rb_cIO, "binwrite", rb_io_s_binwrite, -1);
14230  rb_define_singleton_method(rb_cIO, "select", rb_f_select, -1);
14231  rb_define_singleton_method(rb_cIO, "pipe", rb_io_s_pipe, -1);
14232  rb_define_singleton_method(rb_cIO, "try_convert", rb_io_s_try_convert, 1);
14233  rb_define_singleton_method(rb_cIO, "copy_stream", rb_io_s_copy_stream, -1);
14234 
14235  rb_define_method(rb_cIO, "initialize", rb_io_initialize, -1);
14236 
14237  rb_output_fs = Qnil;
14238  rb_define_hooked_variable("$,", &rb_output_fs, 0, deprecated_str_setter);
14239 
14240  rb_default_rs = rb_fstring_lit("\n"); /* avoid modifying RS_default */
14242  rb_rs = rb_default_rs;
14243  rb_output_rs = Qnil;
14244  rb_define_hooked_variable("$/", &rb_rs, 0, deprecated_str_setter);
14245  rb_define_hooked_variable("$-0", &rb_rs, 0, deprecated_str_setter);
14246  rb_define_hooked_variable("$\\", &rb_output_rs, 0, deprecated_str_setter);
14247 
14248  rb_define_virtual_variable("$_", get_LAST_READ_LINE, set_LAST_READ_LINE);
14249  rb_gvar_ractor_local("$_");
14250 
14251  rb_define_method(rb_cIO, "initialize_copy", rb_io_init_copy, 1);
14252  rb_define_method(rb_cIO, "reopen", rb_io_reopen, -1);
14253 
14254  rb_define_method(rb_cIO, "print", rb_io_print, -1);
14255  rb_define_method(rb_cIO, "putc", rb_io_putc, 1);
14256  rb_define_method(rb_cIO, "puts", rb_io_puts, -1);
14257  rb_define_method(rb_cIO, "printf", rb_io_printf, -1);
14258 
14259  rb_define_method(rb_cIO, "each", rb_io_each_line, -1);
14260  rb_define_method(rb_cIO, "each_line", rb_io_each_line, -1);
14261  rb_define_method(rb_cIO, "each_byte", rb_io_each_byte, 0);
14262  rb_define_method(rb_cIO, "each_char", rb_io_each_char, 0);
14263  rb_define_method(rb_cIO, "each_codepoint", rb_io_each_codepoint, 0);
14264 
14265  rb_define_method(rb_cIO, "syswrite", rb_io_syswrite, 1);
14266  rb_define_method(rb_cIO, "sysread", rb_io_sysread, -1);
14267 
14268  rb_define_method(rb_cIO, "pread", rb_io_pread, -1);
14269  rb_define_method(rb_cIO, "pwrite", rb_io_pwrite, 2);
14270 
14271  rb_define_method(rb_cIO, "fileno", rb_io_fileno, 0);
14272  rb_define_alias(rb_cIO, "to_i", "fileno");
14273  rb_define_method(rb_cIO, "to_io", rb_io_to_io, 0);
14274 
14275  rb_define_method(rb_cIO, "fsync", rb_io_fsync, 0);
14276  rb_define_method(rb_cIO, "fdatasync", rb_io_fdatasync, 0);
14277  rb_define_method(rb_cIO, "sync", rb_io_sync, 0);
14278  rb_define_method(rb_cIO, "sync=", rb_io_set_sync, 1);
14279 
14280  rb_define_method(rb_cIO, "lineno", rb_io_lineno, 0);
14281  rb_define_method(rb_cIO, "lineno=", rb_io_set_lineno, 1);
14282 
14283  rb_define_method(rb_cIO, "readlines", rb_io_readlines, -1);
14284 
14285  rb_define_method(rb_cIO, "readpartial", io_readpartial, -1);
14286  rb_define_method(rb_cIO, "read", io_read, -1);
14287  rb_define_method(rb_cIO, "write", io_write_m, -1);
14288  rb_define_method(rb_cIO, "gets", rb_io_gets_m, -1);
14289  rb_define_method(rb_cIO, "readline", rb_io_readline, -1);
14290  rb_define_method(rb_cIO, "getc", rb_io_getc, 0);
14291  rb_define_method(rb_cIO, "getbyte", rb_io_getbyte, 0);
14292  rb_define_method(rb_cIO, "readchar", rb_io_readchar, 0);
14293  rb_define_method(rb_cIO, "readbyte", rb_io_readbyte, 0);
14294  rb_define_method(rb_cIO, "ungetbyte",rb_io_ungetbyte, 1);
14295  rb_define_method(rb_cIO, "ungetc",rb_io_ungetc, 1);
14297  rb_define_method(rb_cIO, "flush", rb_io_flush, 0);
14298  rb_define_method(rb_cIO, "tell", rb_io_tell, 0);
14299  rb_define_method(rb_cIO, "seek", rb_io_seek_m, -1);
14300  /* Set I/O position from the beginning */
14301  rb_define_const(rb_cIO, "SEEK_SET", INT2FIX(SEEK_SET));
14302  /* Set I/O position from the current position */
14303  rb_define_const(rb_cIO, "SEEK_CUR", INT2FIX(SEEK_CUR));
14304  /* Set I/O position from the end */
14305  rb_define_const(rb_cIO, "SEEK_END", INT2FIX(SEEK_END));
14306 #ifdef SEEK_DATA
14307  /* Set I/O position to the next location containing data */
14308  rb_define_const(rb_cIO, "SEEK_DATA", INT2FIX(SEEK_DATA));
14309 #endif
14310 #ifdef SEEK_HOLE
14311  /* Set I/O position to the next hole */
14312  rb_define_const(rb_cIO, "SEEK_HOLE", INT2FIX(SEEK_HOLE));
14313 #endif
14314  rb_define_method(rb_cIO, "rewind", rb_io_rewind, 0);
14315  rb_define_method(rb_cIO, "pos", rb_io_tell, 0);
14316  rb_define_method(rb_cIO, "pos=", rb_io_set_pos, 1);
14317  rb_define_method(rb_cIO, "eof", rb_io_eof, 0);
14318  rb_define_method(rb_cIO, "eof?", rb_io_eof, 0);
14319 
14320  rb_define_method(rb_cIO, "close_on_exec?", rb_io_close_on_exec_p, 0);
14321  rb_define_method(rb_cIO, "close_on_exec=", rb_io_set_close_on_exec, 1);
14322 
14323  rb_define_method(rb_cIO, "close", rb_io_close_m, 0);
14324  rb_define_method(rb_cIO, "closed?", rb_io_closed, 0);
14325  rb_define_method(rb_cIO, "close_read", rb_io_close_read, 0);
14326  rb_define_method(rb_cIO, "close_write", rb_io_close_write, 0);
14327 
14328  rb_define_method(rb_cIO, "isatty", rb_io_isatty, 0);
14329  rb_define_method(rb_cIO, "tty?", rb_io_isatty, 0);
14330  rb_define_method(rb_cIO, "binmode", rb_io_binmode_m, 0);
14331  rb_define_method(rb_cIO, "binmode?", rb_io_binmode_p, 0);
14332  rb_define_method(rb_cIO, "sysseek", rb_io_sysseek, -1);
14333  rb_define_method(rb_cIO, "advise", rb_io_advise, -1);
14334 
14335  rb_define_method(rb_cIO, "ioctl", rb_io_ioctl, -1);
14336  rb_define_method(rb_cIO, "fcntl", rb_io_fcntl, -1);
14337  rb_define_method(rb_cIO, "pid", rb_io_pid, 0);
14338  rb_define_method(rb_cIO, "inspect", rb_io_inspect, 0);
14339 
14340  rb_define_method(rb_cIO, "external_encoding", rb_io_external_encoding, 0);
14341  rb_define_method(rb_cIO, "internal_encoding", rb_io_internal_encoding, 0);
14342  rb_define_method(rb_cIO, "set_encoding", rb_io_set_encoding, -1);
14343  rb_define_method(rb_cIO, "set_encoding_by_bom", rb_io_set_encoding_by_bom, 0);
14344 
14345  rb_define_method(rb_cIO, "autoclose?", rb_io_autoclose_p, 0);
14346  rb_define_method(rb_cIO, "autoclose=", rb_io_set_autoclose, 1);
14347 
14348  rb_define_virtual_variable("$stdin", stdin_getter, stdin_setter);
14349  rb_define_virtual_variable("$stdout", stdout_getter, stdout_setter);
14350  rb_define_virtual_variable("$>", stdout_getter, stdout_setter);
14351  rb_define_virtual_variable("$stderr", stderr_getter, stderr_setter);
14352 
14353  rb_gvar_ractor_local("$stdin");
14354  rb_gvar_ractor_local("$stdout");
14355  rb_gvar_ractor_local("$>");
14356  rb_gvar_ractor_local("$stderr");
14357 
14358  rb_stdin = rb_io_prep_stdin();
14359  rb_stdout = rb_io_prep_stdout();
14360  rb_stderr = rb_io_prep_stderr();
14361 
14365 
14366  orig_stdout = rb_stdout;
14367  orig_stderr = rb_stderr;
14368 
14369  /* Holds the original stdin */
14370  rb_define_global_const("STDIN", rb_stdin);
14371  /* Holds the original stdout */
14372  rb_define_global_const("STDOUT", rb_stdout);
14373  /* Holds the original stderr */
14374  rb_define_global_const("STDERR", rb_stderr);
14375 
14376 #if 0
14377  /* Hack to get rdoc to regard ARGF as a class: */
14378  rb_cARGF = rb_define_class("ARGF", rb_cObject);
14379 #endif
14380 
14381  rb_cARGF = rb_class_new(rb_cObject);
14382  rb_set_class_path(rb_cARGF, rb_cObject, "ARGF.class");
14383  rb_define_alloc_func(rb_cARGF, argf_alloc);
14384 
14385  rb_include_module(rb_cARGF, rb_mEnumerable);
14386 
14387  rb_define_method(rb_cARGF, "initialize", argf_initialize, -2);
14388  rb_define_method(rb_cARGF, "initialize_copy", argf_initialize_copy, 1);
14389  rb_define_method(rb_cARGF, "to_s", argf_to_s, 0);
14390  rb_define_alias(rb_cARGF, "inspect", "to_s");
14391  rb_define_method(rb_cARGF, "argv", argf_argv, 0);
14392 
14393  rb_define_method(rb_cARGF, "fileno", argf_fileno, 0);
14394  rb_define_method(rb_cARGF, "to_i", argf_fileno, 0);
14395  rb_define_method(rb_cARGF, "to_io", argf_to_io, 0);
14396  rb_define_method(rb_cARGF, "to_write_io", argf_write_io, 0);
14397  rb_define_method(rb_cARGF, "each", argf_each_line, -1);
14398  rb_define_method(rb_cARGF, "each_line", argf_each_line, -1);
14399  rb_define_method(rb_cARGF, "each_byte", argf_each_byte, 0);
14400  rb_define_method(rb_cARGF, "each_char", argf_each_char, 0);
14401  rb_define_method(rb_cARGF, "each_codepoint", argf_each_codepoint, 0);
14402 
14403  rb_define_method(rb_cARGF, "read", argf_read, -1);
14404  rb_define_method(rb_cARGF, "readpartial", argf_readpartial, -1);
14405  rb_define_method(rb_cARGF, "read_nonblock", argf_read_nonblock, -1);
14406  rb_define_method(rb_cARGF, "readlines", argf_readlines, -1);
14407  rb_define_method(rb_cARGF, "to_a", argf_readlines, -1);
14408  rb_define_method(rb_cARGF, "gets", argf_gets, -1);
14409  rb_define_method(rb_cARGF, "readline", argf_readline, -1);
14410  rb_define_method(rb_cARGF, "getc", argf_getc, 0);
14411  rb_define_method(rb_cARGF, "getbyte", argf_getbyte, 0);
14412  rb_define_method(rb_cARGF, "readchar", argf_readchar, 0);
14413  rb_define_method(rb_cARGF, "readbyte", argf_readbyte, 0);
14414  rb_define_method(rb_cARGF, "tell", argf_tell, 0);
14415  rb_define_method(rb_cARGF, "seek", argf_seek_m, -1);
14416  rb_define_method(rb_cARGF, "rewind", argf_rewind, 0);
14417  rb_define_method(rb_cARGF, "pos", argf_tell, 0);
14418  rb_define_method(rb_cARGF, "pos=", argf_set_pos, 1);
14419  rb_define_method(rb_cARGF, "eof", argf_eof, 0);
14420  rb_define_method(rb_cARGF, "eof?", argf_eof, 0);
14421  rb_define_method(rb_cARGF, "binmode", argf_binmode_m, 0);
14422  rb_define_method(rb_cARGF, "binmode?", argf_binmode_p, 0);
14423 
14424  rb_define_method(rb_cARGF, "write", argf_write, 1);
14425  rb_define_method(rb_cARGF, "print", rb_io_print, -1);
14426  rb_define_method(rb_cARGF, "putc", rb_io_putc, 1);
14427  rb_define_method(rb_cARGF, "puts", rb_io_puts, -1);
14428  rb_define_method(rb_cARGF, "printf", rb_io_printf, -1);
14429 
14430  rb_define_method(rb_cARGF, "filename", argf_filename, 0);
14431  rb_define_method(rb_cARGF, "path", argf_filename, 0);
14432  rb_define_method(rb_cARGF, "file", argf_file, 0);
14433  rb_define_method(rb_cARGF, "skip", argf_skip, 0);
14434  rb_define_method(rb_cARGF, "close", argf_close_m, 0);
14435  rb_define_method(rb_cARGF, "closed?", argf_closed, 0);
14436 
14437  rb_define_method(rb_cARGF, "lineno", argf_lineno, 0);
14438  rb_define_method(rb_cARGF, "lineno=", argf_set_lineno, 1);
14439 
14440  rb_define_method(rb_cARGF, "inplace_mode", argf_inplace_mode_get, 0);
14441  rb_define_method(rb_cARGF, "inplace_mode=", argf_inplace_mode_set, 1);
14442 
14443  rb_define_method(rb_cARGF, "external_encoding", argf_external_encoding, 0);
14444  rb_define_method(rb_cARGF, "internal_encoding", argf_internal_encoding, 0);
14445  rb_define_method(rb_cARGF, "set_encoding", argf_set_encoding, -1);
14446 
14447  argf = rb_class_new_instance(0, 0, rb_cARGF);
14448 
14450  /*
14451  * ARGF is a stream designed for use in scripts that process files given
14452  * as command-line arguments or passed in via STDIN.
14453  *
14454  * See ARGF (the class) for more details.
14455  */
14456  rb_define_global_const("ARGF", argf);
14457 
14458  rb_define_hooked_variable("$.", &argf, argf_lineno_getter, argf_lineno_setter);
14459  rb_define_hooked_variable("$FILENAME", &argf, argf_filename_getter, rb_gvar_readonly_setter);
14460  ARGF.filename = rb_str_new2("-");
14461 
14462  rb_define_hooked_variable("$-i", &argf, opt_i_get, opt_i_set);
14463  rb_gvar_ractor_local("$-i");
14464 
14465  rb_define_hooked_variable("$*", &argf, argf_argv_getter, rb_gvar_readonly_setter);
14466 
14467 #if defined (_WIN32) || defined(__CYGWIN__)
14468  atexit(pipe_atexit);
14469 #endif
14470 
14471  Init_File();
14472 
14473  rb_define_method(rb_cFile, "initialize", rb_file_initialize, -1);
14474 
14475  sym_mode = ID2SYM(rb_intern_const("mode"));
14476  sym_perm = ID2SYM(rb_intern_const("perm"));
14477  sym_flags = ID2SYM(rb_intern_const("flags"));
14478  sym_extenc = ID2SYM(rb_intern_const("external_encoding"));
14479  sym_intenc = ID2SYM(rb_intern_const("internal_encoding"));
14480  sym_encoding = ID2SYM(rb_id_encoding());
14481  sym_open_args = ID2SYM(rb_intern_const("open_args"));
14482  sym_textmode = ID2SYM(rb_intern_const("textmode"));
14483  sym_binmode = ID2SYM(rb_intern_const("binmode"));
14484  sym_autoclose = ID2SYM(rb_intern_const("autoclose"));
14485  sym_normal = ID2SYM(rb_intern_const("normal"));
14486  sym_sequential = ID2SYM(rb_intern_const("sequential"));
14487  sym_random = ID2SYM(rb_intern_const("random"));
14488  sym_willneed = ID2SYM(rb_intern_const("willneed"));
14489  sym_dontneed = ID2SYM(rb_intern_const("dontneed"));
14490  sym_noreuse = ID2SYM(rb_intern_const("noreuse"));
14491  sym_SET = ID2SYM(rb_intern_const("SET"));
14492  sym_CUR = ID2SYM(rb_intern_const("CUR"));
14493  sym_END = ID2SYM(rb_intern_const("END"));
14494 #ifdef SEEK_DATA
14495  sym_DATA = ID2SYM(rb_intern_const("DATA"));
14496 #endif
14497 #ifdef SEEK_HOLE
14498  sym_HOLE = ID2SYM(rb_intern_const("HOLE"));
14499 #endif
14500  sym_wait_readable = ID2SYM(rb_intern_const("wait_readable"));
14501  sym_wait_writable = ID2SYM(rb_intern_const("wait_writable"));
14502 }
14503 
14504 #include "io.rbinc"
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:133
#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:1043
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:837
VALUE rb_class_new(VALUE super)
Creates a new, anonymous class.
Definition: class.c:275
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:869
VALUE rb_define_module_under(VALUE outer, const char *name)
Defines a module under the namespace of outer.
Definition: class.c:972
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
Definition: class.c:2116
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:2419
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:2406
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a method.
Definition: class.c:1914
int rb_block_given_p(void)
Determines if the current method is given a block.
Definition: eval.c:854
int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *values)
Keyword argument deconstructor.
Definition: class.c:2195
void rb_define_global_function(const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a global function.
Definition: class.c:2110
#define ECONV_AFTER_OUTPUT
Old name of RUBY_ECONV_AFTER_OUTPUT.
Definition: transcode.h:551
#define rb_str_new2
Old name of rb_str_new_cstr.
Definition: string.h:1738
#define TYPE(_)
Old name of rb_type.
Definition: value_type.h:107
#define NEWOBJ_OF
Old name of RB_NEWOBJ_OF.
Definition: newobj.h:61
#define FL_SINGLETON
Old name of RUBY_FL_SINGLETON.
Definition: fl_type.h:58
#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:529
#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:394
#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:30
#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:143
#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:31
#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:396
#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:653
#define ECONV_NEWLINE_DECORATOR_WRITE_MASK
Old name of RUBY_ECONV_NEWLINE_DECORATOR_WRITE_MASK.
Definition: transcode.h:528
#define ENCODING_MAXNAMELEN
Old name of RUBY_ENCODING_MAXNAMELEN.
Definition: encoding.h:110
#define MBCLEN_NEEDMORE_LEN(ret)
Old name of ONIGENC_MBCLEN_NEEDMORE_LEN.
Definition: encoding.h:536
#define ENCODING_GET(obj)
Old name of RB_ENCODING_GET.
Definition: encoding.h:108
#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:393
#define MBCLEN_CHARFOUND_LEN(ret)
Old name of ONIGENC_MBCLEN_CHARFOUND_LEN.
Definition: encoding.h:533
#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:534
#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:534
#define Qtrue
Old name of RUBY_Qtrue.
#define MBCLEN_NEEDMORE_P(ret)
Old name of ONIGENC_MBCLEN_NEEDMORE_P.
Definition: encoding.h:535
#define ECONV_PARTIAL_INPUT
Old name of RUBY_ECONV_PARTIAL_INPUT.
Definition: transcode.h:550
#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:519
#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:399
#define MBCLEN_CHARFOUND_P(ret)
Old name of ONIGENC_MBCLEN_CHARFOUND_P.
Definition: encoding.h:532
#define ECONV_NEWLINE_DECORATOR_READ_MASK
Old name of RUBY_ECONV_NEWLINE_DECORATOR_READ_MASK.
Definition: transcode.h:527
#define NUM2CHR
Old name of RB_NUM2CHR.
Definition: char.h:33
#define FL_TEST
Old name of RB_FL_TEST.
Definition: fl_type.h:139
#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:526
#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:651
#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:1740
#define ALLOCV_END
Old name of RB_ALLOCV_END.
Definition: memory.h:400
#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:536
void rb_notimplement(void)
Definition: error.c:3068
void rb_category_warn(rb_warning_category_t category, const char *fmt,...)
Identical to rb_category_warning(), except it reports always regardless of runtime -W flag.
Definition: error.c:428
void rb_raise(VALUE exc, const char *fmt,...)
Exception entry point.
Definition: error.c:3025
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:460
VALUE rb_rescue2(VALUE(*b_proc)(VALUE), VALUE data1, VALUE(*r_proc)(VALUE, VALUE), VALUE data2,...)
An equivalent of rescue clause.
Definition: eval.c:883
VALUE rb_eNotImpError
NotImplementedError exception.
Definition: error.c:1109
void rb_exc_raise(VALUE mesg)
Raises an exception in the current thread.
Definition: eval.c:675
void rb_syserr_fail(int e, const char *mesg)
Raises appropriate exception that represents a C errno.
Definition: error.c:3137
void rb_bug(const char *fmt,...)
Interpreter panic switch.
Definition: error.c:802
void rb_sys_fail(const char *mesg)
Converts a C errno into a Ruby exception, then raises it.
Definition: error.c:3149
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:13496
VALUE rb_eIOError
IOError exception.
Definition: io.c:187
VALUE rb_eStandardError
StandardError exception.
Definition: error.c:1096
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:3225
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:3143
#define ruby_verbose
This variable controls whether the interpreter is in debug mode.
Definition: error.h:459
VALUE rb_eTypeError
TypeError exception.
Definition: error.c:1099
VALUE rb_eEOFError
EOFError exception.
Definition: io.c:186
void rb_fatal(const char *fmt,...)
Raises the unsung "fatal" exception.
Definition: error.c:3076
void rb_readwrite_sys_fail(enum rb_io_wait_readwrite waiting, const char *mesg)
Raises appropriate exception using the parameters.
Definition: io.c:13490
void rb_iter_break_value(VALUE val)
Identical to rb_iter_break(), except it additionally takes the "value" of this breakage.
Definition: vm.c:1827
rb_io_wait_readwrite
for rb_readwrite_sys_fail first argument
Definition: error.h:57
VALUE rb_eRuntimeError
RuntimeError exception.
Definition: error.c:1097
void rb_warn(const char *fmt,...)
Identical to rb_warning(), except it reports always regardless of runtime -W flag.
Definition: error.c:418
VALUE rb_eArgError
ArgumentError exception.
Definition: error.c:1100
VALUE rb_ensure(VALUE(*b_proc)(VALUE), VALUE data1, VALUE(*e_proc)(VALUE), VALUE data2)
An equivalent to ensure clause.
Definition: eval.c:983
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:3155
VALUE rb_eSystemCallError
SystemCallError exception.
Definition: error.c:1119
@ RB_WARN_CATEGORY_DEPRECATED
Warning is for deprecated features.
Definition: error.h:48
VALUE rb_mKernel
Kernel module.
Definition: object.c:49
VALUE rb_check_to_int(VALUE val)
Identical to rb_check_to_integer(), except it uses #to_int for conversion.
Definition: object.c:3004
VALUE rb_any_to_s(VALUE obj)
Generates a textual representation of the given object.
Definition: object.c:553
VALUE rb_obj_alloc(VALUE klass)
Allocates an instance of the given class.
Definition: object.c:1909
VALUE rb_class_new_instance(int argc, const VALUE *argv, VALUE klass)
Allocates, then initialises an instance of the given class.
Definition: object.c:1950
VALUE rb_cIO
IO class.
Definition: io.c:185
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:1938
VALUE rb_mEnumerable
Enumerable module.
Definition: enum.c:27
VALUE rb_stdin
STDIN constant.
Definition: io.c:198
VALUE rb_stderr
STDERR constant.
Definition: io.c:198
VALUE rb_obj_class(VALUE obj)
Queries the class of an object.
Definition: object.c:188
VALUE rb_obj_dup(VALUE obj)
Duplicates the given object.
Definition: object.c:451
VALUE rb_inspect(VALUE obj)
Generates a human-readable textual representation of the given object.
Definition: object.c:564
VALUE rb_mWaitReadable
IO::WaitReadable module.
Definition: io.c:188
VALUE rb_mWaitWritable
IO::WaitReadable module.
Definition: io.c:189
VALUE rb_obj_freeze(VALUE obj)
Just calls rb_obj_freeze_inline() inside.
Definition: object.c:1161
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:2985
VALUE rb_cFile
File class.
Definition: file.c:174
VALUE rb_stdout
STDOUT constant.
Definition: io.c:198
VALUE rb_to_int(VALUE val)
Identical to rb_check_to_int(), except it raises in case of conversion mismatch.
Definition: object.c:2998
rb_encoding * rb_locale_encoding(void)
Queries the encoding that represents the current locale.
Definition: encoding.c:1573
rb_encoding * rb_default_external_encoding(void)
Queries the "default external" encoding.
Definition: encoding.c:1637
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:1234
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:267
VALUE rb_enc_associate(VALUE obj, rb_encoding *enc)
Identical to rb_enc_associate(), except it takes an encoding itself instead of its index.
Definition: encoding.c:1066
rb_encoding * rb_usascii_encoding(void)
Queries the encoding that represents US-ASCII.
Definition: encoding.c:1539
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:697
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:1533
rb_encoding * rb_default_internal_encoding(void)
Queries the "default internal" encoding.
Definition: encoding.c:1724
rb_encoding * rb_find_encoding(VALUE obj)
Identical to rb_to_encoding_index(), except the return type.
Definition: encoding.c:336
rb_encoding * rb_to_encoding(VALUE obj)
Identical to rb_find_encoding(), except it raises an exception instead of returning NULL.
Definition: encoding.c:329
rb_encoding * rb_ascii8bit_encoding(void)
Queries the encoding that represents ASCII-8BIT a.k.a.
Definition: encoding.c:1515
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:188
static bool rb_enc_asciicompat(rb_encoding *enc)
Queries if the passed encoding is in some sense compatible with ASCII.
Definition: encoding.h:782
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:587
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:414
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:1222
rb_encoding * rb_enc_get(VALUE obj)
Identical to rb_enc_get_index(), except the return type.
Definition: encoding.c:1072
static const char * rb_enc_name(rb_encoding *enc)
Queries the (canonical) name of the passed encoding.
Definition: encoding.h:433
int rb_enc_find_index(const char *name)
Queries the index of the encoding.
Definition: encoding.c:881
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:448
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:1246
int rb_enc_str_coderange(VALUE str)
Scans the passed string to collect its code range.
Definition: string.c:776
VALUE rb_enc_uint_chr(unsigned int code, rb_encoding *enc)
Encodes the passed code point into a series of bytes.
Definition: numeric.c:3751
VALUE rb_enc_str_new(const char *ptr, long len, rb_encoding *enc)
Identical to rb_enc_str_new(), except it additionally takes an encoding.
Definition: string.c:940
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:668
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:2563
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:2065
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:1449
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:1745
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:1906
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:1971
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:2929
VALUE rb_econv_make_exception(rb_econv_t *ec)
This function makes sense right after rb_econv_convert() returns.
Definition: transcode.c:4281
void rb_econv_check_error(rb_econv_t *ec)
This is a rb_econv_make_exception() + rb_exc_raise() combo.
Definition: transcode.c:4287
const char * rb_econv_asciicompat_encoding(const char *encname)
Queries the passed encoding's corresponding ASCII compatible encoding.
Definition: transcode.c:1789
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:2614
void rb_econv_close(rb_econv_t *ec)
Destructs a converter.
Definition: transcode.c:1705
void rb_econv_putback(rb_econv_t *ec, unsigned char *p, int n)
Puts back the bytes.
Definition: transcode.c:1756
VALUE rb_funcall(VALUE recv, ID mid, int n,...)
Calls a method.
Definition: vm_eval.c:1102
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:1069
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:1061
void rb_global_variable(VALUE *)
An alias for rb_gc_register_address().
Definition: gc.c:8743
void rb_gc_register_mark_object(VALUE object)
Inform the garbage collector that object is a live Ruby object that should not be moved.
Definition: gc.c:8687
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:4790
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:1420
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:989
VALUE rb_ary_new(void)
Allocates a new, empty array.
Definition: array.c:750
VALUE rb_ary_push(VALUE ary, VALUE elem)
Special case of rb_ary_cat() that it adds only one element.
Definition: array.c:1308
VALUE rb_ary_entry(VALUE ary, long off)
Queries an element of an array.
Definition: array.c:1679
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Identical to rb_ary_new_from_values(), except it expects exactly two parameters.
Definition: array.c:976
#define RETURN_ENUMERATOR(obj, argc, argv)
Identical to RETURN_SIZED_ENUMERATOR(), except its size is unknown.
Definition: enumerator.h:239
#define rb_check_frozen
Just another name of rb_check_frozen.
Definition: error.h:278
static int rb_check_arity(int argc, int min, int max)
Ensures that the passed integer is in the passed range.
Definition: error.h:294
ID rb_frame_this_func(void)
Queries the name of the Ruby level method that is calling this function.
Definition: eval.c:1039
void rb_jump_tag(int state)
This function is to re-throw global escapes.
Definition: eval.c:845
VALUE rb_str_encode_ospath(VALUE path)
Converts a string into an "OS Path" encoding, if any.
Definition: file.c:251
void rb_gc_mark(VALUE obj)
Marks an object.
Definition: gc.c:6775
void rb_gc(void)
Triggers a GC process.
Definition: gc.c:10293
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:1896
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:2095
VALUE rb_hash_aref(VALUE hash, VALUE key)
Queries the given key in the given hash table.
Definition: hash.c:2082
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:2903
VALUE rb_hash_lookup(VALUE hash, VALUE key)
Identical to rb_hash_aref(), except it always returns RUBY_Qnil for misshits.
Definition: hash.c:2108
VALUE rb_hash_dup(VALUE hash)
Duplicates a hash.
Definition: hash.c:1585
VALUE rb_hash_new(void)
Creates a new, empty hash object.
Definition: hash.c:1529
VALUE rb_io_printf(int argc, const VALUE *argv, VALUE io)
This is a rb_f_sprintf() + rb_io_write() combo.
Definition: io.c:7955
VALUE rb_io_gets(VALUE io)
Reads a "line" from the given IO.
Definition: io.c:3955
int rb_cloexec_pipe(int fildes[2])
Opens a pipe with closing on exec.
Definition: io.c:413
VALUE rb_rs
The record separator character for inputs, or the $/.
Definition: io.c:202
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:8026
VALUE rb_io_addstr(VALUE io, VALUE str)
Identical to rb_io_write(), except it always returns the passed IO.
Definition: io.c:2106
void rb_write_error(const char *str)
Writes the given error message to somewhere applicable.
Definition: io.c:8391
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:4668
VALUE rb_io_getbyte(VALUE io)
Reads a byte from the given IO.
Definition: io.c:4587
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:8208
int rb_cloexec_dup2(int oldfd, int newfd)
Identical to rb_cloexec_dup(), except you can specify the destination file descriptor.
Definition: io.c:360
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:8498
void rb_update_max_fd(int fd)
Informs the interpreter that the passed fd can be the max.
Definition: io.c:234
VALUE rb_io_write(VALUE io, VALUE str)
Writes the given string to the given IO.
Definition: io.c:2063
int rb_cloexec_open(const char *pathname, int flags, mode_t mode)
Opens a file that closes on exec.
Definition: io.c:314
VALUE rb_output_rs
The record separator character for outputs, or the $\.
Definition: io.c:203
VALUE rb_io_eof(VALUE io)
Queries if the passed IO is at the end of file.
Definition: io.c:2450
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:8371
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:284
VALUE rb_io_flush(VALUE io)
Flushes any buffered data within the passed IO to the underlying operating system.
Definition: io.c:2162
VALUE rb_io_ascii8bit_binmode(VALUE io)
Forces no conversions be applied to the passed IO.
Definition: io.c:5788
VALUE rb_io_binmode(VALUE io)
Sets the binmode.
Definition: io.c:5742
VALUE rb_io_ungetc(VALUE io, VALUE c)
"Unget"s a string.
Definition: io.c:4723
int rb_pipe(int *pipes)
This is an rb_cloexec_pipe() + rb_update_max_fd() combo.
Definition: io.c:6792
VALUE rb_gets(void)
Much like rb_io_gets(), but it reads from the mysterious ARGF object.
Definition: io.c:9419
int rb_cloexec_fcntl_dupfd(int fd, int minfd)
Duplicates a file descriptor with closing on exec.
Definition: io.c:447
VALUE rb_output_fs
The field separator character for outputs, or the $,.
Definition: io.c:201
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:6675
int rb_cloexec_dup(int oldfd)
Identical to rb_cloexec_fcntl_dupfd(), except it implies minfd is 3.
Definition: io.c:353
VALUE rb_file_open(const char *fname, const char *fmode)
Opens a file located at the given path.
Definition: io.c:6682
VALUE rb_io_close(VALUE io)
Closes the IO.
Definition: io.c:5234
VALUE rb_default_rs
This is the default value of rb_rs, i.e.
Definition: io.c:204
void rb_lastline_set(VALUE str)
Updates $_.
Definition: vm.c:1598
VALUE rb_lastline_get(void)
Queries the last line, or the $_.
Definition: vm.c:1592
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:2825
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:1426
void rb_last_status_set(int status, rb_pid_t pid)
Sets the "last status", or the $?.
Definition: process.c:663
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:3317
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:828
VALUE rb_str_new_frozen(VALUE str)
Creates a frozen copy of the string, if necessary.
Definition: string.c:1356
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:1808
void rb_str_modify(VALUE str)
Declares that the string is about to be modified.
Definition: string.c:2459
VALUE rb_str_cat(VALUE dst, const char *src, long srclen)
Destructively appends the passed contents to the string.
Definition: string.c:3161
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:924
rb_gvar_setter_t rb_str_setter
This is a rb_gvar_setter_t that refutes non-string assignments.
Definition: string.h:1177
void rb_str_set_len(VALUE str, long len)
Overwrites the length of the string.
Definition: string.c:3039
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:3278
VALUE rb_str_new(const char *ptr, long len)
Allocates an instance of rb_cString.
Definition: string.c:918
VALUE rb_check_string_type(VALUE obj)
Try converting an object to its stringised representation using its to_str method,...
Definition: string.c:2659
VALUE rb_str_substr(VALUE str, long beg, long len)
This is the implementation of two-argumented String#slice.
Definition: string.c:2931
VALUE rb_str_unlocktmp(VALUE str)
Releases a lock formerly obtained by rb_str_locktmp().
Definition: string.c:3022
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:952
VALUE rb_str_resize(VALUE str, long len)
Overwrites the length of the string.
Definition: string.c:3056
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:2467
VALUE rb_str_buf_new(long capa)
Allocates a "string buffer".
Definition: string.c:1506
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:1657
int rb_thread_interrupted(VALUE thval)
Checks if the thread's execution was recently interrupted.
Definition: thread.c:1590
VALUE rb_mutex_new(void)
Creates a mutex.
Definition: thread_sync.c:172
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:1440
#define RUBY_UBF_IO
A special UBF for blocking IO operations.
Definition: thread.h:382
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:2627
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:601
void rb_thread_check_ints(void)
Checks for interrupts.
Definition: thread.c:1573
VALUE rb_thread_current(void)
Obtains the "current" thread.
Definition: thread.c:2904
int rb_thread_wait_fd(int fd)
Blocks the current thread until the given file descriptor is ready to be read.
Definition: io.c:1434
void rb_thread_schedule(void)
Tries to switch to another thread.
Definition: thread.c:1619
void rb_thread_sleep(int sec)
Blocks for the given period of time.
Definition: thread.c:1596
struct timeval rb_time_interval(VALUE num)
Creates a "time interval".
Definition: time.c:2656
VALUE rb_attr_get(VALUE obj, ID name)
Identical to rb_ivar_get()
Definition: variable.c:1293
void rb_set_class_path(VALUE klass, VALUE space, const char *name)
Names a class.
Definition: variable.c:235
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:1575
VALUE rb_class_name(VALUE obj)
Queries the name of the given object's class.
Definition: variable.c:294
int rb_respond_to(VALUE obj, ID mid)
Queries if the object responds to the method.
Definition: vm_method.c:2765
int rb_method_basic_definition_p(VALUE klass, ID mid)
Well...
Definition: vm_method.c:2643
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:664
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:941
ID rb_intern(const char *name)
Finds or creates a symbol of the given name.
Definition: symbol.c:782
VALUE rb_id2str(ID id)
Identical to rb_id2name(), except it returns a Ruby's String instead of C's.
Definition: symbol.c:935
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:3265
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:588
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:594
void rb_define_const(VALUE klass, const char *name, VALUE val)
Defines a Ruby level constant under a namespace.
Definition: variable.c:3253
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:563
#define FMODE_READABLE
The IO is opened for reading.
Definition: io.h:232
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:5873
VALUE rb_io_get_io(VALUE io)
Identical to rb_io_check_io(), except it raises exceptions on conversion failures.
Definition: io.c:801
VALUE rb_io_taint_check(VALUE obj)
Definition: io.c:771
void rb_io_read_check(rb_io_t *fptr)
Blocks until there is a pending read in the passed IO.
Definition: io.c:1007
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:6006
#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:321
#define FMODE_READWRITE
The IO is opened for both read/write.
Definition: io.h:238
#define GetOpenFile
This is an old name of RB_IO_POINTER.
Definition: io.h:343
void rb_io_check_byte_readable(rb_io_t *fptr)
Asserts that an IO is opened for byte-based reading.
Definition: io.c:953
#define FMODE_TTY
The IO is a TTY.
Definition: io.h:262
#define FMODE_CREATE
The IO is opened for creating.
Definition: io.h:285
void rb_io_check_readable(rb_io_t *fptr)
Just another name of rb_io_check_byte_readable.
Definition: io.c:962
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:6155
struct rb_io_t rb_io_t
Ruby's IO, metadata and buffers.
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:8544
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:1428
struct rb_io_enc_t rb_io_enc_t
Just another name of rb_io_enc_t.
Definition: io.h:214
int rb_io_descriptor(VALUE io)
Returns an integer representing the numeric file descriptor for io.
Definition: io.c:2650
#define FMODE_WRITABLE
The IO is opened for writing.
Definition: io.h:235
#define FMODE_APPEND
The IO is opened for appending.
Definition: io.h:277
#define MakeOpenFile
This is an old name of RB_IO_OPEN.
Definition: io.h:366
#define FMODE_DUPLEX
Ruby eventually detects that the IO is bidirectional.
Definition: io.h:270
#define FMODE_BINMODE
The IO is in "binary mode".
Definition: io.h:249
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:1487
#define RB_IO_POINTER(obj, fp)
Queries the underlying IO pointer.
Definition: io.h:337
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:1446
#define FMODE_SYNC
The IO is in "sync mode".
Definition: io.h:256
void rb_io_check_initialized(rb_io_t *fptr)
Asserts that the passed IO is initialised.
Definition: io.c:778
#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:293
#define FMODE_TEXTMODE
The IO is in "text mode".
Definition: io.h:313
int rb_io_fptr_finalize(rb_io_t *fptr)
Destroys the given IO.
Definition: io.c:5161
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:807
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:6476
ssize_t rb_io_bufwrite(VALUE io, const void *buf, size_t size)
Buffered write to the passed IO.
Definition: io.c:1807
void rb_io_check_char_readable(rb_io_t *fptr)
Asserts that an IO is opened for character-based reading.
Definition: io.c:934
#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:299
VALUE rb_io_get_write_io(VALUE io)
Queries the tied IO for writing.
Definition: io.c:813
void rb_io_set_nonblock(rb_io_t *fptr)
Sets an IO to a "nonblock mode".
Definition: io.c:3121
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:6282
int rb_io_wait_writable(int fd)
Blocks until the passed file descriptor gets writable.
Definition: io.c:1385
VALUE rb_io_set_write_io(VALUE io, VALUE w)
Assigns the tied IO for writing.
Definition: io.c:824
void rb_io_check_writable(rb_io_t *fptr)
Asserts that an IO is opened for writing.
Definition: io.c:986
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:1500
void rb_io_check_closed(rb_io_t *fptr)
This badly named function asserts that the passed IO is open.
Definition: io.c:786
@ RUBY_IO_READABLE
IO::READABLE
Definition: io.h:67
@ RUBY_IO_PRIORITY
IO::PRIORITY
Definition: io.h:69
@ RUBY_IO_WRITABLE
IO::WRITABLE
Definition: io.h:68
int rb_io_wait_readable(int fd)
Blocks until the passed file descriptor gets readable.
Definition: io.c:1351
void rb_io_synchronized(rb_io_t *fptr)
Sets FMODE_SYNC.
Definition: io.c:6779
VALUE rb_io_wait(VALUE io, VALUE events, VALUE timeout)
Blocks until the passed IO is ready for the passed events.
Definition: io.c:1294
void * rb_thread_call_without_gvl2(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2)
Identical to rb_thread_call_without_gvl(), except it does not interface with signals etc.
Definition: thread.c:1797
void * rb_thread_call_with_gvl(void *(*func)(void *), void *data1)
(Re-)acquires the GVL.
Definition: thread.c:1888
void * rb_thread_call_without_gvl(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2)
Allows the passed function to run in parallel with other Ruby threads.
#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:1201
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:1241
#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:1391
VALUE rb_yield(VALUE val)
Yields the block.
Definition: vm_eval.c:1357
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:354
#define RB_GC_GUARD(v)
Prevents premature destruction of local objects.
Definition: memory.h:161
#define MEMMOVE(p1, p2, type, n)
Handy macro to call memmove.
Definition: memory.h:378
#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
VALUE rb_ractor_stderr(void)
Queries the standard error of the current Ractor that is calling this function.
Definition: ractor.c:2146
VALUE rb_ractor_stdin(void)
Queries the standard input of the current Ractor that is calling this function.
Definition: ractor.c:2122
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:2182
VALUE rb_ractor_stdout(void)
Queries the standard output of the current Ractor that is calling this function.
Definition: ractor.c:2134
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:2170
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:2158
#define RARRAY_LEN
Just another name of rb_array_len.
Definition: rarray.h:68
static int RARRAY_LENINT(VALUE ary)
Identical to rb_array_len(), except it differs for the return type.
Definition: rarray.h:324
#define RARRAY_AREF(a, i)
Definition: rarray.h:588
#define RARRAY_CONST_PTR
Just another name of rb_array_const_ptr.
Definition: rarray.h:69
#define RFILE(obj)
Convenient casting macro.
Definition: rfile.h:50
#define SafeStringValue(v)
Definition: rstring.h:104
#define StringValue(v)
Ensures that the parameter object is a String.
Definition: rstring.h:72
static char * RSTRING_END(VALUE str)
Queries the end of the contents pointer of the string.
Definition: rstring.h:527
static char * RSTRING_PTR(VALUE str)
Queries the contents pointer of the string.
Definition: rstring.h:497
#define RSTRING_GETMEM(str, ptrvar, lenvar)
Convenient macro to obtain the contents and length at once.
Definition: rstring.h:573
static long RSTRING_LEN(VALUE str)
Queries the length of the string.
Definition: rstring.h:483
#define StringValueCStr(v)
Identical to StringValuePtr, except it additionally checks for the contents for viability as a C stri...
Definition: rstring.h:95
#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:489
VALUE rb_get_argv(void)
Queries the arguments passed to the current process that you can access from Ruby as ARGV.
Definition: io.c:13456
void rb_p(VALUE obj)
Inspects an object.
Definition: io.c:8277
#define FilePathValue(v)
Ensures that the parameter object is a path.
Definition: ruby.h:90
#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:126
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:153
VALUE rb_fiber_scheduler_io_wait_readable(VALUE scheduler, VALUE io)
Nonblocking wait until the passed IO is ready for reading.
Definition: scheduler.c:223
VALUE rb_fiber_scheduler_io_wait(VALUE scheduler, VALUE io, VALUE events, VALUE timeout)
Nonblocking version of rb_io_wait().
Definition: scheduler.c:217
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:66
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:131
VALUE rb_fiber_scheduler_io_wait_writable(VALUE scheduler, VALUE io)
Nonblocking wait until the passed IO is ready for writing.
Definition: scheduler.c:229
VALUE rb_fiber_scheduler_io_write_memory(VALUE scheduler, VALUE io, const void *buffer, size_t size, size_t length)
Nonblocking write to the passed IO using a native buffer.
Definition: scheduler.c:288
VALUE rb_fiber_scheduler_io_read_memory(VALUE scheduler, VALUE io, void *buffer, size_t size, size_t length)
Nonblocking read from the passed IO using a native buffer.
Definition: scheduler.c:275
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:4299
#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:222
Definition: win32.h:218
Definition: io.c:6688
This is the struct that holds necessary info for a struct.
Definition: rtypeddata.h:190
The data structure which wraps the fd_set bitmap used by select(2).
Definition: largesize.h:74
IO buffers.
Definition: io.h:89
int len
Length of the buffer.
Definition: io.h:89
char * ptr
Pointer to the underlying memory region, of at least capa bytes.
Definition: io.h:89
int off
Offset inside of ptr.
Definition: io.h:89
int capa
Designed capacity of the buffer.
Definition: io.h:89
int ecflags
Flags.
Definition: io.h:156
rb_encoding * enc
Internal encoding.
Definition: io.h:146
rb_encoding * enc2
External encoding.
Definition: io.h:149
VALUE ecopts
Flags as Ruby hash.
Definition: io.h:165
Ruby's IO, metadata and buffers.
Definition: io.h:95
int fd
file descriptor.
Definition: io.h:104
struct rb_io_t::rb_io_enc_t encs
Decomposed encoding flags.
int lineno
number of lines read
Definition: io.h:113
rb_econv_t * writeconv
Encoding converter used when writing to this IO.
Definition: io.h:178
rb_pid_t pid
child's pid (for pipes)
Definition: io.h:110
rb_io_buffer_t wbuf
Write buffer.
Definition: io.h:122
rb_econv_t * readconv
Encoding converter used when reading from this IO.
Definition: io.h:169
VALUE writeconv_asciicompat
This is, when set, an instance of rb_cString which holds the "common" encoding.
Definition: io.h:186
FILE * stdio_file
stdio ptr for read/write, if available.
Definition: io.h:101
int writeconv_initialized
Whether rb_io_t::writeconv is already set up.
Definition: io.h:189
VALUE pathv
pathname for file
Definition: io.h:116
int mode
mode flags: FMODE_XXXs
Definition: io.h:107
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:195
VALUE write_lock
This is a Ruby level mutex.
Definition: io.h:210
rb_io_buffer_t cbuf
rb_io_ungetc() destination.
Definition: io.h:175
VALUE self
The IO's Ruby level counterpart.
Definition: io.h:98
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:201
VALUE tied_io_for_writing
Duplex IO object, if set.
Definition: io.h:135
void(* finalize)(struct rb_io_t *, int)
finalize proc
Definition: io.h:119
rb_io_buffer_t rbuf
(Byte) read buffer.
Definition: io.h:128
Definition: io.c:11038
Definition: io.c:1575
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 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:432
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:375