Ruby  2.7.2p137(2020-10-01revision5445e0435260b449decf2ac16f9d09bae3cafe72)
io.c
Go to the documentation of this file.
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/encoding.h"
15 #include "ruby/io.h"
16 #include "ruby/thread.h"
17 #include "internal.h"
18 #include "dln.h"
19 #include "encindex.h"
20 #include "id.h"
21 #include <ctype.h>
22 #include <errno.h>
23 #include "ruby_atomic.h"
24 #include "ccan/list/list.h"
25 
26 /* non-Linux poll may not work on all FDs */
27 #if defined(HAVE_POLL)
28 # if defined(__linux__)
29 # define USE_POLL 1
30 # endif
31 # if defined(__FreeBSD_version) && __FreeBSD_version >= 1100000
32 # define USE_POLL 1
33 # endif
34 #endif
35 
36 #ifndef USE_POLL
37 # define USE_POLL 0
38 #endif
39 
40 #if !USE_POLL
41 # include "vm_core.h"
42 #endif
43 
44 #include "builtin.h"
45 
46 #undef free
47 #define free(x) xfree(x)
48 
49 #if defined(DOSISH) || defined(__CYGWIN__)
50 #include <io.h>
51 #endif
52 
53 #include <sys/types.h>
54 #if defined HAVE_NET_SOCKET_H
55 # include <net/socket.h>
56 #elif defined HAVE_SYS_SOCKET_H
57 # include <sys/socket.h>
58 #endif
59 
60 #if defined(__BOW__) || defined(__CYGWIN__) || defined(_WIN32)
61 # define NO_SAFE_RENAME
62 #endif
63 
64 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__sun) || defined(_nec_ews)
65 # define USE_SETVBUF
66 #endif
67 
68 #ifdef __QNXNTO__
69 #include <unix.h>
70 #endif
71 
72 #include <sys/types.h>
73 #if defined(HAVE_SYS_IOCTL_H) && !defined(_WIN32)
74 #include <sys/ioctl.h>
75 #endif
76 #if defined(HAVE_FCNTL_H) || defined(_WIN32)
77 #include <fcntl.h>
78 #elif defined(HAVE_SYS_FCNTL_H)
79 #include <sys/fcntl.h>
80 #endif
81 
82 #if !HAVE_OFF_T && !defined(off_t)
83 # define off_t long
84 #endif
85 
86 #ifdef HAVE_SYS_TIME_H
87 # include <sys/time.h>
88 #endif
89 
90 #include <sys/stat.h>
91 
92 #if defined(HAVE_SYS_PARAM_H) || defined(__HIUX_MPP__)
93 # include <sys/param.h>
94 #endif
95 
96 #if !defined NOFILE
97 # define NOFILE 64
98 #endif
99 
100 #ifdef HAVE_UNISTD_H
101 #include <unistd.h>
102 #endif
103 
104 #ifdef HAVE_SYSCALL_H
105 #include <syscall.h>
106 #elif defined HAVE_SYS_SYSCALL_H
107 #include <sys/syscall.h>
108 #endif
109 
110 #ifdef HAVE_SYS_UIO_H
111 #include <sys/uio.h>
112 #endif
113 
114 #ifdef HAVE_SYS_WAIT_H
115 # include <sys/wait.h> /* for WNOHANG on BSD */
116 #endif
117 
118 #ifdef HAVE_COPYFILE_H
119 # include <copyfile.h>
120 #endif
121 
122 #include "ruby/util.h"
123 
124 #ifndef O_ACCMODE
125 #define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR)
126 #endif
127 
128 #if SIZEOF_OFF_T > SIZEOF_LONG && !defined(HAVE_LONG_LONG)
129 # error off_t is bigger than long, but you have no long long...
130 #endif
131 
132 #ifndef PIPE_BUF
133 # ifdef _POSIX_PIPE_BUF
134 # define PIPE_BUF _POSIX_PIPE_BUF
135 # else
136 # define PIPE_BUF 512 /* is this ok? */
137 # endif
138 #endif
139 
140 #ifndef EWOULDBLOCK
141 # define EWOULDBLOCK EAGAIN
142 #endif
143 
144 #if defined(HAVE___SYSCALL) && (defined(__APPLE__) || defined(__OpenBSD__))
145 /* Mac OS X and OpenBSD have __syscall but don't define it in headers */
146 off_t __syscall(quad_t number, ...);
147 #endif
148 
149 #define IO_RBUF_CAPA_MIN 8192
150 #define IO_CBUF_CAPA_MIN (128*1024)
151 #define IO_RBUF_CAPA_FOR(fptr) (NEED_READCONV(fptr) ? IO_CBUF_CAPA_MIN : IO_RBUF_CAPA_MIN)
152 #define IO_WBUF_CAPA_MIN 8192
153 
154 /* define system APIs */
155 #ifdef _WIN32
156 #undef open
157 #define open rb_w32_uopen
158 #undef rename
159 #define rename(f, t) rb_w32_urename((f), (t))
160 #endif
161 
162 #if defined(_WIN32)
163 # define RUBY_PIPE_NONBLOCK_DEFAULT (0)
164 #elif defined(O_NONBLOCK)
165  /* disabled for [Bug #15356] (Rack::Deflater + rails) failure: */
166 # define RUBY_PIPE_NONBLOCK_DEFAULT (0)
167 #else /* any platforms where O_NONBLOCK does not exist? */
168 # define RUBY_PIPE_NONBLOCK_DEFAULT (0)
169 #endif
170 
176 
177 static VALUE rb_eEAGAINWaitReadable;
178 static VALUE rb_eEAGAINWaitWritable;
179 static VALUE rb_eEWOULDBLOCKWaitReadable;
180 static VALUE rb_eEWOULDBLOCKWaitWritable;
181 static VALUE rb_eEINPROGRESSWaitWritable;
182 static VALUE rb_eEINPROGRESSWaitReadable;
183 
185 static VALUE orig_stdout, orig_stderr;
186 
191 
192 static VALUE argf;
193 
194 static ID id_write, id_read, id_getc, id_flush, id_readpartial, id_set_encoding;
195 static VALUE sym_mode, sym_perm, sym_flags, sym_extenc, sym_intenc, sym_encoding, sym_open_args;
196 static VALUE sym_textmode, sym_binmode, sym_autoclose;
197 static VALUE sym_SET, sym_CUR, sym_END;
198 static VALUE sym_wait_readable, sym_wait_writable;
199 #ifdef SEEK_DATA
200 static VALUE sym_DATA;
201 #endif
202 #ifdef SEEK_HOLE
203 static VALUE sym_HOLE;
204 #endif
205 
206 struct argf {
208  long last_lineno; /* $. */
209  long lineno;
212  struct rb_io_enc_t encs;
214 };
215 
216 static rb_atomic_t max_file_descriptor = NOFILE;
217 void
219 {
220  rb_atomic_t afd = (rb_atomic_t)fd;
221  rb_atomic_t max_fd = max_file_descriptor;
222  int err;
223 
224  if (fd < 0 || afd <= max_fd)
225  return;
226 
227 #if defined(HAVE_FCNTL) && defined(F_GETFL)
228  err = fcntl(fd, F_GETFL) == -1;
229 #else
230  {
231  struct stat buf;
232  err = fstat(fd, &buf) != 0;
233  }
234 #endif
235  if (err && errno == EBADF) {
236  rb_bug("rb_update_max_fd: invalid fd (%d) given.", fd);
237  }
238 
239  while (max_fd < afd) {
240  max_fd = ATOMIC_CAS(max_file_descriptor, max_fd, afd);
241  }
242 }
243 
244 void
246 {
247  /* MinGW don't have F_GETFD and FD_CLOEXEC. [ruby-core:40281] */
248 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
249  int flags, flags2, ret;
250  flags = fcntl(fd, F_GETFD); /* should not fail except EBADF. */
251  if (flags == -1) {
252  rb_bug("rb_maygvl_fd_fix_cloexec: fcntl(%d, F_GETFD) failed: %s", fd, strerror(errno));
253  }
254  if (fd <= 2)
255  flags2 = flags & ~FD_CLOEXEC; /* Clear CLOEXEC for standard file descriptors: 0, 1, 2. */
256  else
257  flags2 = flags | FD_CLOEXEC; /* Set CLOEXEC for non-standard file descriptors: 3, 4, 5, ... */
258  if (flags != flags2) {
259  ret = fcntl(fd, F_SETFD, flags2);
260  if (ret != 0) {
261  rb_bug("rb_maygvl_fd_fix_cloexec: fcntl(%d, F_SETFD, %d) failed: %s", fd, flags2, strerror(errno));
262  }
263  }
264 #endif
265 }
266 
267 void
269 {
271  rb_update_max_fd(fd);
272 }
273 
274 /* this is only called once */
275 static int
276 rb_fix_detect_o_cloexec(int fd)
277 {
278 #if defined(O_CLOEXEC) && defined(F_GETFD)
279  int flags = fcntl(fd, F_GETFD);
280 
281  if (flags == -1)
282  rb_bug("rb_fix_detect_o_cloexec: fcntl(%d, F_GETFD) failed: %s", fd, strerror(errno));
283 
284  if (flags & FD_CLOEXEC)
285  return 1;
286 #endif /* fall through if O_CLOEXEC does not work: */
288  return 0;
289 }
290 
291 int
292 rb_cloexec_open(const char *pathname, int flags, mode_t mode)
293 {
294  int ret;
295  static int o_cloexec_state = -1; /* <0: unknown, 0: ignored, >0: working */
296 
297 #ifdef O_CLOEXEC
298  /* O_CLOEXEC is available since Linux 2.6.23. Linux 2.6.18 silently ignore it. */
299  flags |= O_CLOEXEC;
300 #elif defined O_NOINHERIT
301  flags |= O_NOINHERIT;
302 #endif
303  ret = open(pathname, flags, mode);
304  if (ret < 0) return ret;
305  if (ret <= 2 || o_cloexec_state == 0) {
307  }
308  else if (o_cloexec_state > 0) {
309  return ret;
310  }
311  else {
312  o_cloexec_state = rb_fix_detect_o_cloexec(ret);
313  }
314  return ret;
315 }
316 
317 int
318 rb_cloexec_dup(int oldfd)
319 {
320  /* Don't allocate standard file descriptors: 0, 1, 2 */
321  return rb_cloexec_fcntl_dupfd(oldfd, 3);
322 }
323 
324 int
325 rb_cloexec_dup2(int oldfd, int newfd)
326 {
327  int ret;
328 
329  /* When oldfd == newfd, dup2 succeeds but dup3 fails with EINVAL.
330  * rb_cloexec_dup2 succeeds as dup2. */
331  if (oldfd == newfd) {
332  ret = newfd;
333  }
334  else {
335 #if defined(HAVE_DUP3) && defined(O_CLOEXEC)
336  static int try_dup3 = 1;
337  if (2 < newfd && try_dup3) {
338  ret = dup3(oldfd, newfd, O_CLOEXEC);
339  if (ret != -1)
340  return ret;
341  /* dup3 is available since Linux 2.6.27, glibc 2.9. */
342  if (errno == ENOSYS) {
343  try_dup3 = 0;
344  ret = dup2(oldfd, newfd);
345  }
346  }
347  else {
348  ret = dup2(oldfd, newfd);
349  }
350 #else
351  ret = dup2(oldfd, newfd);
352 #endif
353  if (ret < 0) return ret;
354  }
356  return ret;
357 }
358 
359 static int
360 rb_fd_set_nonblock(int fd)
361 {
362 #ifdef _WIN32
363  return rb_w32_set_nonblock(fd);
364 #elif defined(F_GETFL)
365  int oflags = fcntl(fd, F_GETFL);
366 
367  if (oflags == -1)
368  return -1;
369  if (oflags & O_NONBLOCK)
370  return 0;
371  oflags |= O_NONBLOCK;
372  return fcntl(fd, F_SETFL, oflags);
373 #endif
374  return 0;
375 }
376 
377 int
378 rb_cloexec_pipe(int fildes[2])
379 {
380  int ret;
381 
382 #if defined(HAVE_PIPE2)
383  static int try_pipe2 = 1;
384  if (try_pipe2) {
385  ret = pipe2(fildes, O_CLOEXEC | RUBY_PIPE_NONBLOCK_DEFAULT);
386  if (ret != -1)
387  return ret;
388  /* pipe2 is available since Linux 2.6.27, glibc 2.9. */
389  if (errno == ENOSYS) {
390  try_pipe2 = 0;
391  ret = pipe(fildes);
392  }
393  }
394  else {
395  ret = pipe(fildes);
396  }
397 #else
398  ret = pipe(fildes);
399 #endif
400  if (ret < 0) return ret;
401 #ifdef __CYGWIN__
402  if (ret == 0 && fildes[1] == -1) {
403  close(fildes[0]);
404  fildes[0] = -1;
405  errno = ENFILE;
406  return -1;
407  }
408 #endif
409  rb_maygvl_fd_fix_cloexec(fildes[0]);
410  rb_maygvl_fd_fix_cloexec(fildes[1]);
412  rb_fd_set_nonblock(fildes[0]);
413  rb_fd_set_nonblock(fildes[1]);
414  }
415  return ret;
416 }
417 
418 int
419 rb_cloexec_fcntl_dupfd(int fd, int minfd)
420 {
421  int ret;
422 
423 #if defined(HAVE_FCNTL) && defined(F_DUPFD_CLOEXEC) && defined(F_DUPFD)
424  static int try_dupfd_cloexec = 1;
425  if (try_dupfd_cloexec) {
426  ret = fcntl(fd, F_DUPFD_CLOEXEC, minfd);
427  if (ret != -1) {
428  if (ret <= 2)
430  return ret;
431  }
432  /* F_DUPFD_CLOEXEC is available since Linux 2.6.24. Linux 2.6.18 fails with EINVAL */
433  if (errno == EINVAL) {
434  ret = fcntl(fd, F_DUPFD, minfd);
435  if (ret != -1) {
436  try_dupfd_cloexec = 0;
437  }
438  }
439  }
440  else {
441  ret = fcntl(fd, F_DUPFD, minfd);
442  }
443 #elif defined(HAVE_FCNTL) && defined(F_DUPFD)
444  ret = fcntl(fd, F_DUPFD, minfd);
445 #elif defined(HAVE_DUP)
446  ret = dup(fd);
447  if (ret >= 0 && ret < minfd) {
448  const int prev_fd = ret;
449  ret = rb_cloexec_fcntl_dupfd(fd, minfd);
450  close(prev_fd);
451  }
452  return ret;
453 #else
454 # error "dup() or fcntl(F_DUPFD) must be supported."
455 #endif
456  if (ret < 0) return ret;
458  return ret;
459 }
460 
461 #define argf_of(obj) (*(struct argf *)DATA_PTR(obj))
462 #define ARGF argf_of(argf)
463 
464 #define GetWriteIO(io) rb_io_get_write_io(io)
465 
466 #define READ_DATA_PENDING(fptr) ((fptr)->rbuf.len)
467 #define READ_DATA_PENDING_COUNT(fptr) ((fptr)->rbuf.len)
468 #define READ_DATA_PENDING_PTR(fptr) ((fptr)->rbuf.ptr+(fptr)->rbuf.off)
469 #define READ_DATA_BUFFERED(fptr) READ_DATA_PENDING(fptr)
470 
471 #define READ_CHAR_PENDING(fptr) ((fptr)->cbuf.len)
472 #define READ_CHAR_PENDING_COUNT(fptr) ((fptr)->cbuf.len)
473 #define READ_CHAR_PENDING_PTR(fptr) ((fptr)->cbuf.ptr+(fptr)->cbuf.off)
474 
475 #if defined(_WIN32)
476 #define WAIT_FD_IN_WIN32(fptr) \
477  (rb_w32_io_cancelable_p((fptr)->fd) ? 0 : rb_thread_wait_fd((fptr)->fd))
478 #else
479 #define WAIT_FD_IN_WIN32(fptr)
480 #endif
481 
482 #define READ_CHECK(fptr) do {\
483  if (!READ_DATA_PENDING(fptr)) {\
484  WAIT_FD_IN_WIN32(fptr);\
485  rb_io_check_closed(fptr);\
486  }\
487 } while(0)
488 
489 #ifndef S_ISSOCK
490 # ifdef _S_ISSOCK
491 # define S_ISSOCK(m) _S_ISSOCK(m)
492 # else
493 # ifdef _S_IFSOCK
494 # define S_ISSOCK(m) (((m) & S_IFMT) == _S_IFSOCK)
495 # else
496 # ifdef S_IFSOCK
497 # define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
498 # endif
499 # endif
500 # endif
501 #endif
502 
503 static int io_fflush(rb_io_t *);
504 static rb_io_t *flush_before_seek(rb_io_t *fptr);
505 
506 #define NEED_NEWLINE_DECORATOR_ON_READ(fptr) ((fptr)->mode & FMODE_TEXTMODE)
507 #define NEED_NEWLINE_DECORATOR_ON_WRITE(fptr) ((fptr)->mode & FMODE_TEXTMODE)
508 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
509 /* Windows */
510 # define DEFAULT_TEXTMODE FMODE_TEXTMODE
511 # define TEXTMODE_NEWLINE_DECORATOR_ON_WRITE ECONV_CRLF_NEWLINE_DECORATOR
512 /*
513  * CRLF newline is set as default newline decorator.
514  * If only CRLF newline conversion is needed, we use binary IO process
515  * with OS's text mode for IO performance improvement.
516  * If encoding conversion is needed or a user sets text mode, we use encoding
517  * conversion IO process and universal newline decorator by default.
518  */
519 #define NEED_READCONV(fptr) ((fptr)->encs.enc2 != NULL || (fptr)->encs.ecflags & ~ECONV_CRLF_NEWLINE_DECORATOR)
520 #define WRITECONV_MASK ( \
521  (ECONV_DECORATOR_MASK & ~ECONV_CRLF_NEWLINE_DECORATOR)|\
522  ECONV_STATEFUL_DECORATOR_MASK|\
523  0)
524 #define NEED_WRITECONV(fptr) ( \
525  ((fptr)->encs.enc != NULL && (fptr)->encs.enc != rb_ascii8bit_encoding()) || \
526  ((fptr)->encs.ecflags & WRITECONV_MASK) || \
527  0)
528 #define SET_BINARY_MODE(fptr) setmode((fptr)->fd, O_BINARY)
529 
530 #define NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr) do {\
531  if (NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {\
532  if (((fptr)->mode & FMODE_READABLE) &&\
533  !((fptr)->encs.ecflags & ECONV_NEWLINE_DECORATOR_MASK)) {\
534  setmode((fptr)->fd, O_BINARY);\
535  }\
536  else {\
537  setmode((fptr)->fd, O_TEXT);\
538  }\
539  }\
540 } while(0)
541 
542 #define SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags) do {\
543  if ((enc2) && ((ecflags) & ECONV_DEFAULT_NEWLINE_DECORATOR)) {\
544  (ecflags) |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;\
545  }\
546 } while(0)
547 
548 /*
549  * IO unread with taking care of removed '\r' in text mode.
550  */
551 static void
552 io_unread(rb_io_t *fptr)
553 {
554  off_t r, pos;
555  ssize_t read_size;
556  long i;
557  long newlines = 0;
558  long extra_max;
559  char *p;
560  char *buf;
561 
562  rb_io_check_closed(fptr);
563  if (fptr->rbuf.len == 0 || fptr->mode & FMODE_DUPLEX) {
564  return;
565  }
566 
567  errno = 0;
568  if (!rb_w32_fd_is_text(fptr->fd)) {
569  r = lseek(fptr->fd, -fptr->rbuf.len, SEEK_CUR);
570  if (r < 0 && errno) {
571  if (errno == ESPIPE)
572  fptr->mode |= FMODE_DUPLEX;
573  return;
574  }
575 
576  fptr->rbuf.off = 0;
577  fptr->rbuf.len = 0;
578  return;
579  }
580 
581  pos = lseek(fptr->fd, 0, SEEK_CUR);
582  if (pos < 0 && errno) {
583  if (errno == ESPIPE)
584  fptr->mode |= FMODE_DUPLEX;
585  return;
586  }
587 
588  /* add extra offset for removed '\r' in rbuf */
589  extra_max = (long)(pos - fptr->rbuf.len);
590  p = fptr->rbuf.ptr + fptr->rbuf.off;
591 
592  /* if the end of rbuf is '\r', rbuf doesn't have '\r' within rbuf.len */
593  if (*(fptr->rbuf.ptr + fptr->rbuf.capa - 1) == '\r') {
594  newlines++;
595  }
596 
597  for (i = 0; i < fptr->rbuf.len; i++) {
598  if (*p == '\n') newlines++;
599  if (extra_max == newlines) break;
600  p++;
601  }
602 
603  buf = ALLOC_N(char, fptr->rbuf.len + newlines);
604  while (newlines >= 0) {
605  r = lseek(fptr->fd, pos - fptr->rbuf.len - newlines, SEEK_SET);
606  if (newlines == 0) break;
607  if (r < 0) {
608  newlines--;
609  continue;
610  }
611  read_size = _read(fptr->fd, buf, fptr->rbuf.len + newlines);
612  if (read_size < 0) {
613  int e = errno;
614  free(buf);
615  rb_syserr_fail_path(e, fptr->pathv);
616  }
617  if (read_size == fptr->rbuf.len) {
618  lseek(fptr->fd, r, SEEK_SET);
619  break;
620  }
621  else {
622  newlines--;
623  }
624  }
625  free(buf);
626  fptr->rbuf.off = 0;
627  fptr->rbuf.len = 0;
628  return;
629 }
630 
631 /*
632  * We use io_seek to back cursor position when changing mode from text to binary,
633  * but stdin and pipe cannot seek back. Stdin and pipe read should use encoding
634  * conversion for working properly with mode change.
635  *
636  * Return previous translation mode.
637  */
638 static inline int
639 set_binary_mode_with_seek_cur(rb_io_t *fptr)
640 {
641  if (!rb_w32_fd_is_text(fptr->fd)) return O_BINARY;
642 
643  if (fptr->rbuf.len == 0 || fptr->mode & FMODE_DUPLEX) {
644  return setmode(fptr->fd, O_BINARY);
645  }
646  flush_before_seek(fptr);
647  return setmode(fptr->fd, O_BINARY);
648 }
649 #define SET_BINARY_MODE_WITH_SEEK_CUR(fptr) set_binary_mode_with_seek_cur(fptr)
650 
651 #else
652 /* Unix */
653 # define DEFAULT_TEXTMODE 0
654 #define NEED_READCONV(fptr) ((fptr)->encs.enc2 != NULL || NEED_NEWLINE_DECORATOR_ON_READ(fptr))
655 #define NEED_WRITECONV(fptr) ( \
656  ((fptr)->encs.enc != NULL && (fptr)->encs.enc != rb_ascii8bit_encoding()) || \
657  NEED_NEWLINE_DECORATOR_ON_WRITE(fptr) || \
658  ((fptr)->encs.ecflags & (ECONV_DECORATOR_MASK|ECONV_STATEFUL_DECORATOR_MASK)) || \
659  0)
660 #define SET_BINARY_MODE(fptr) (void)(fptr)
661 #define NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr) (void)(fptr)
662 #define SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags) ((void)(enc2), (void)(ecflags))
663 #define SET_BINARY_MODE_WITH_SEEK_CUR(fptr) (void)(fptr)
664 #endif
665 
666 #if !defined HAVE_SHUTDOWN && !defined shutdown
667 #define shutdown(a,b) 0
668 #endif
669 
670 #if defined(_WIN32)
671 #define is_socket(fd, path) rb_w32_is_socket(fd)
672 #elif !defined(S_ISSOCK)
673 #define is_socket(fd, path) 0
674 #else
675 static int
676 is_socket(int fd, VALUE path)
677 {
678  struct stat sbuf;
679  if (fstat(fd, &sbuf) < 0)
680  rb_sys_fail_path(path);
681  return S_ISSOCK(sbuf.st_mode);
682 }
683 #endif
684 
685 static const char closed_stream[] = "closed stream";
686 
687 static void
688 io_fd_check_closed(int fd)
689 {
690  if (fd < 0) {
691  rb_thread_check_ints(); /* check for ruby_error_stream_closed */
692  rb_raise(rb_eIOError, closed_stream);
693  }
694 }
695 
696 void
698 {
699  rb_raise(rb_eEOFError, "end of file reached");
700 }
701 
702 VALUE
704 {
705  rb_check_frozen(io);
706  return io;
707 }
708 
709 void
711 {
712  if (!fptr) {
713  rb_raise(rb_eIOError, "uninitialized stream");
714  }
715 }
716 
717 void
719 {
721  io_fd_check_closed(fptr->fd);
722 }
723 
724 static rb_io_t *
725 rb_io_get_fptr(VALUE io)
726 {
727  rb_io_t *fptr = RFILE(io)->fptr;
729  return fptr;
730 }
731 
732 VALUE
734 {
735  return rb_convert_type_with_id(io, T_FILE, "IO", idTo_io);
736 }
737 
738 VALUE
740 {
741  return rb_check_convert_type_with_id(io, T_FILE, "IO", idTo_io);
742 }
743 
744 VALUE
746 {
747  VALUE write_io;
748  write_io = rb_io_get_fptr(io)->tied_io_for_writing;
749  if (write_io) {
750  return write_io;
751  }
752  return io;
753 }
754 
755 VALUE
757 {
758  VALUE write_io;
759  rb_io_t *fptr = rb_io_get_fptr(io);
760  if (!RTEST(w)) {
761  w = 0;
762  }
763  else {
764  GetWriteIO(w);
765  }
766  write_io = fptr->tied_io_for_writing;
767  fptr->tied_io_for_writing = w;
768  return write_io ? write_io : Qnil;
769 }
770 
771 /*
772  * call-seq:
773  * IO.try_convert(obj) -> io or nil
774  *
775  * Try to convert <i>obj</i> into an IO, using to_io method.
776  * Returns converted IO or +nil+ if <i>obj</i> cannot be converted
777  * for any reason.
778  *
779  * IO.try_convert(STDOUT) #=> STDOUT
780  * IO.try_convert("STDOUT") #=> nil
781  *
782  * require 'zlib'
783  * f = open("/tmp/zz.gz") #=> #<File:/tmp/zz.gz>
784  * z = Zlib::GzipReader.open(f) #=> #<Zlib::GzipReader:0x81d8744>
785  * IO.try_convert(z) #=> #<File:/tmp/zz.gz>
786  *
787  */
788 static VALUE
789 rb_io_s_try_convert(VALUE dummy, VALUE io)
790 {
791  return rb_io_check_io(io);
792 }
793 
794 #if !(defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32))
795 static void
796 io_unread(rb_io_t *fptr)
797 {
798  off_t r;
799  rb_io_check_closed(fptr);
800  if (fptr->rbuf.len == 0 || fptr->mode & FMODE_DUPLEX)
801  return;
802  /* xxx: target position may be negative if buffer is filled by ungetc */
803  errno = 0;
804  r = lseek(fptr->fd, -fptr->rbuf.len, SEEK_CUR);
805  if (r < 0 && errno) {
806  if (errno == ESPIPE)
807  fptr->mode |= FMODE_DUPLEX;
808  return;
809  }
810  fptr->rbuf.off = 0;
811  fptr->rbuf.len = 0;
812  return;
813 }
814 #endif
815 
816 static rb_encoding *io_input_encoding(rb_io_t *fptr);
817 
818 static void
819 io_ungetbyte(VALUE str, rb_io_t *fptr)
820 {
821  long len = RSTRING_LEN(str);
822 
823  if (fptr->rbuf.ptr == NULL) {
824  const int min_capa = IO_RBUF_CAPA_FOR(fptr);
825  fptr->rbuf.off = 0;
826  fptr->rbuf.len = 0;
827 #if SIZEOF_LONG > SIZEOF_INT
828  if (len > INT_MAX)
829  rb_raise(rb_eIOError, "ungetbyte failed");
830 #endif
831  if (len > min_capa)
832  fptr->rbuf.capa = (int)len;
833  else
834  fptr->rbuf.capa = min_capa;
835  fptr->rbuf.ptr = ALLOC_N(char, fptr->rbuf.capa);
836  }
837  if (fptr->rbuf.capa < len + fptr->rbuf.len) {
838  rb_raise(rb_eIOError, "ungetbyte failed");
839  }
840  if (fptr->rbuf.off < len) {
841  MEMMOVE(fptr->rbuf.ptr+fptr->rbuf.capa-fptr->rbuf.len,
842  fptr->rbuf.ptr+fptr->rbuf.off,
843  char, fptr->rbuf.len);
844  fptr->rbuf.off = fptr->rbuf.capa-fptr->rbuf.len;
845  }
846  fptr->rbuf.off-=(int)len;
847  fptr->rbuf.len+=(int)len;
848  MEMMOVE(fptr->rbuf.ptr+fptr->rbuf.off, RSTRING_PTR(str), char, len);
849 }
850 
851 static rb_io_t *
852 flush_before_seek(rb_io_t *fptr)
853 {
854  if (io_fflush(fptr) < 0)
855  rb_sys_fail(0);
856  io_unread(fptr);
857  errno = 0;
858  return fptr;
859 }
860 
861 #define io_seek(fptr, ofs, whence) (errno = 0, lseek(flush_before_seek(fptr)->fd, (ofs), (whence)))
862 #define io_tell(fptr) lseek(flush_before_seek(fptr)->fd, 0, SEEK_CUR)
863 
864 #ifndef SEEK_CUR
865 # define SEEK_SET 0
866 # define SEEK_CUR 1
867 # define SEEK_END 2
868 #endif
869 
870 void
872 {
873  rb_io_check_closed(fptr);
874  if (!(fptr->mode & FMODE_READABLE)) {
875  rb_raise(rb_eIOError, "not opened for reading");
876  }
877  if (fptr->wbuf.len) {
878  if (io_fflush(fptr) < 0)
879  rb_sys_fail(0);
880  }
881  if (fptr->tied_io_for_writing) {
882  rb_io_t *wfptr;
883  GetOpenFile(fptr->tied_io_for_writing, wfptr);
884  if (io_fflush(wfptr) < 0)
885  rb_sys_fail(0);
886  }
887 }
888 
889 void
891 {
893  if (READ_CHAR_PENDING(fptr)) {
894  rb_raise(rb_eIOError, "byte oriented read for character buffered IO");
895  }
896 }
897 
898 void
900 {
902 }
903 
904 static rb_encoding*
905 io_read_encoding(rb_io_t *fptr)
906 {
907  if (fptr->encs.enc) {
908  return fptr->encs.enc;
909  }
911 }
912 
913 static rb_encoding*
914 io_input_encoding(rb_io_t *fptr)
915 {
916  if (fptr->encs.enc2) {
917  return fptr->encs.enc2;
918  }
919  return io_read_encoding(fptr);
920 }
921 
922 void
924 {
925  rb_io_check_closed(fptr);
926  if (!(fptr->mode & FMODE_WRITABLE)) {
927  rb_raise(rb_eIOError, "not opened for writing");
928  }
929  if (fptr->rbuf.len) {
930  io_unread(fptr);
931  }
932 }
933 
934 int
936 {
937  /* This function is used for bytes and chars. Confusing. */
938  if (READ_CHAR_PENDING(fptr))
939  return 1; /* should raise? */
940  return READ_DATA_PENDING(fptr);
941 }
942 
943 void
945 {
946  if (!READ_DATA_PENDING(fptr)) {
947  rb_thread_wait_fd(fptr->fd);
948  }
949  return;
950 }
951 
952 int
954 {
955  if (err == EMFILE || err == ENFILE || err == ENOMEM) {
956  rb_gc();
957  return 1;
958  }
959  return 0;
960 }
961 
962 static int
963 ruby_dup(int orig)
964 {
965  int fd;
966 
967  fd = rb_cloexec_dup(orig);
968  if (fd < 0) {
969  int e = errno;
970  if (rb_gc_for_fd(e)) {
971  fd = rb_cloexec_dup(orig);
972  }
973  if (fd < 0) {
974  rb_syserr_fail(e, 0);
975  }
976  }
977  rb_update_max_fd(fd);
978  return fd;
979 }
980 
981 static VALUE
982 io_alloc(VALUE klass)
983 {
984  NEWOBJ_OF(io, struct RFile, klass, T_FILE);
985 
986  io->fptr = 0;
987 
988  return (VALUE)io;
989 }
990 
991 #ifndef S_ISREG
992 # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
993 #endif
994 
996  int fd;
997  int nonblock;
998  void *buf;
999  size_t capa;
1000 };
1001 
1003  int fd;
1004  const void *buf;
1005  size_t capa;
1006 };
1007 
1008 #ifdef HAVE_WRITEV
1009 struct io_internal_writev_struct {
1010  int fd;
1011  int iovcnt;
1012  const struct iovec *iov;
1013 };
1014 #endif
1015 
1016 static int nogvl_wait_for_single_fd(int fd, short events);
1017 static VALUE
1018 internal_read_func(void *ptr)
1019 {
1020  struct io_internal_read_struct *iis = ptr;
1021  ssize_t r;
1022 retry:
1023  r = read(iis->fd, iis->buf, iis->capa);
1024  if (r < 0 && !iis->nonblock) {
1025  int e = errno;
1026  if (e == EAGAIN || e == EWOULDBLOCK) {
1027  if (nogvl_wait_for_single_fd(iis->fd, RB_WAITFD_IN) != -1) {
1028  goto retry;
1029  }
1030  errno = e;
1031  }
1032  }
1033  return r;
1034 }
1035 
1036 #if defined __APPLE__
1037 # define do_write_retry(code) do {ret = code;} while (ret == -1 && errno == EPROTOTYPE)
1038 #else
1039 # define do_write_retry(code) ret = code
1040 #endif
1041 static VALUE
1042 internal_write_func(void *ptr)
1043 {
1044  struct io_internal_write_struct *iis = ptr;
1045  ssize_t ret;
1046  do_write_retry(write(iis->fd, iis->buf, iis->capa));
1047  return (VALUE)ret;
1048 }
1049 
1050 static void*
1051 internal_write_func2(void *ptr)
1052 {
1053  return (void*)internal_write_func(ptr);
1054 }
1055 
1056 #ifdef HAVE_WRITEV
1057 static VALUE
1058 internal_writev_func(void *ptr)
1059 {
1060  struct io_internal_writev_struct *iis = ptr;
1061  ssize_t ret;
1062  do_write_retry(writev(iis->fd, iis->iov, iis->iovcnt));
1063  return (VALUE)ret;
1064 }
1065 #endif
1066 
1067 static ssize_t
1068 rb_read_internal(int fd, void *buf, size_t count)
1069 {
1070  struct io_internal_read_struct iis;
1071 
1072  iis.fd = fd;
1073  iis.nonblock = 0;
1074  iis.buf = buf;
1075  iis.capa = count;
1076 
1077  return (ssize_t)rb_thread_io_blocking_region(internal_read_func, &iis, fd);
1078 }
1079 
1080 static ssize_t
1081 rb_write_internal(int fd, const void *buf, size_t count)
1082 {
1083  struct io_internal_write_struct iis;
1084  iis.fd = fd;
1085  iis.buf = buf;
1086  iis.capa = count;
1087 
1088  return (ssize_t)rb_thread_io_blocking_region(internal_write_func, &iis, fd);
1089 }
1090 
1091 static ssize_t
1092 rb_write_internal2(int fd, const void *buf, size_t count)
1093 {
1094  struct io_internal_write_struct iis;
1095  iis.fd = fd;
1096  iis.buf = buf;
1097  iis.capa = count;
1098 
1099  return (ssize_t)rb_thread_call_without_gvl2(internal_write_func2, &iis,
1100  RUBY_UBF_IO, NULL);
1101 }
1102 
1103 #ifdef HAVE_WRITEV
1104 static ssize_t
1105 rb_writev_internal(int fd, const struct iovec *iov, int iovcnt)
1106 {
1107  struct io_internal_writev_struct iis;
1108  iis.fd = fd;
1109  iis.iov = iov;
1110  iis.iovcnt = iovcnt;
1111 
1112  return (ssize_t)rb_thread_io_blocking_region(internal_writev_func, &iis, fd);
1113 }
1114 #endif
1115 
1116 static VALUE
1117 io_flush_buffer_sync(void *arg)
1118 {
1119  rb_io_t *fptr = arg;
1120  long l = fptr->wbuf.len;
1121  ssize_t r = write(fptr->fd, fptr->wbuf.ptr+fptr->wbuf.off, (size_t)l);
1122 
1123  if (fptr->wbuf.len <= r) {
1124  fptr->wbuf.off = 0;
1125  fptr->wbuf.len = 0;
1126  return 0;
1127  }
1128  if (0 <= r) {
1129  fptr->wbuf.off += (int)r;
1130  fptr->wbuf.len -= (int)r;
1131  errno = EAGAIN;
1132  }
1133  return (VALUE)-1;
1134 }
1135 
1136 static void*
1137 io_flush_buffer_sync2(void *arg)
1138 {
1139  VALUE result = io_flush_buffer_sync(arg);
1140 
1141  /*
1142  * rb_thread_call_without_gvl2 uses 0 as interrupted.
1143  * So, we need to avoid to use 0.
1144  */
1145  return !result ? (void*)1 : (void*)result;
1146 }
1147 
1148 static VALUE
1149 io_flush_buffer_async(VALUE arg)
1150 {
1151  rb_io_t *fptr = (rb_io_t *)arg;
1152  return rb_thread_io_blocking_region(io_flush_buffer_sync, fptr, fptr->fd);
1153 }
1154 
1155 static VALUE
1156 io_flush_buffer_async2(VALUE arg)
1157 {
1158  rb_io_t *fptr = (rb_io_t *)arg;
1159  VALUE ret;
1160 
1161  ret = (VALUE)rb_thread_call_without_gvl2(io_flush_buffer_sync2, fptr,
1162  RUBY_UBF_IO, NULL);
1163 
1164  if (!ret) {
1165  /* pending async interrupt is there. */
1166  errno = EAGAIN;
1167  return -1;
1168  }
1169  else if (ret == 1) {
1170  return 0;
1171  }
1172  return ret;
1173 }
1174 
1175 static inline int
1176 io_flush_buffer(rb_io_t *fptr)
1177 {
1178  if (fptr->write_lock) {
1179  if (rb_mutex_owned_p(fptr->write_lock))
1180  return (int)io_flush_buffer_async2((VALUE)fptr);
1181  else
1182  return (int)rb_mutex_synchronize(fptr->write_lock, io_flush_buffer_async2, (VALUE)fptr);
1183  }
1184  else {
1185  return (int)io_flush_buffer_async((VALUE)fptr);
1186  }
1187 }
1188 
1189 static int
1190 io_fflush(rb_io_t *fptr)
1191 {
1192  rb_io_check_closed(fptr);
1193  if (fptr->wbuf.len == 0)
1194  return 0;
1195  while (fptr->wbuf.len > 0 && io_flush_buffer(fptr) != 0) {
1196  if (!rb_io_wait_writable(fptr->fd))
1197  return -1;
1198  rb_io_check_closed(fptr);
1199  }
1200  return 0;
1201 }
1202 
1203 int
1205 {
1206  io_fd_check_closed(f);
1207  switch (errno) {
1208  case EINTR:
1209 #if defined(ERESTART)
1210  case ERESTART:
1211 #endif
1213  return TRUE;
1214 
1215  case EAGAIN:
1216 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
1217  case EWOULDBLOCK:
1218 #endif
1220  return TRUE;
1221 
1222  default:
1223  return FALSE;
1224  }
1225 }
1226 
1227 int
1229 {
1230  io_fd_check_closed(f);
1231  switch (errno) {
1232  case EINTR:
1233 #if defined(ERESTART)
1234  case ERESTART:
1235 #endif
1236  /*
1237  * In old Linux, several special files under /proc and /sys don't handle
1238  * select properly. Thus we need avoid to call if don't use O_NONBLOCK.
1239  * Otherwise, we face nasty hang up. Sigh.
1240  * e.g. http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=31b07093c44a7a442394d44423e21d783f5523b8
1241  * http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=31b07093c44a7a442394d44423e21d783f5523b8
1242  * In EINTR case, we only need to call RUBY_VM_CHECK_INTS_BLOCKING().
1243  * Then rb_thread_check_ints() is enough.
1244  */
1246  return TRUE;
1247 
1248  case EAGAIN:
1249 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
1250  case EWOULDBLOCK:
1251 #endif
1253  return TRUE;
1254 
1255  default:
1256  return FALSE;
1257  }
1258 }
1259 
1260 static void
1261 make_writeconv(rb_io_t *fptr)
1262 {
1263  if (!fptr->writeconv_initialized) {
1264  const char *senc, *denc;
1265  rb_encoding *enc;
1266  int ecflags;
1267  VALUE ecopts;
1268 
1269  fptr->writeconv_initialized = 1;
1270 
1271  ecflags = fptr->encs.ecflags & ~ECONV_NEWLINE_DECORATOR_READ_MASK;
1272  ecopts = fptr->encs.ecopts;
1273 
1274  if (!fptr->encs.enc || (fptr->encs.enc == rb_ascii8bit_encoding() && !fptr->encs.enc2)) {
1275  /* no encoding conversion */
1276  fptr->writeconv_pre_ecflags = 0;
1277  fptr->writeconv_pre_ecopts = Qnil;
1278  fptr->writeconv = rb_econv_open_opts("", "", ecflags, ecopts);
1279  if (!fptr->writeconv)
1280  rb_exc_raise(rb_econv_open_exc("", "", ecflags));
1281  fptr->writeconv_asciicompat = Qnil;
1282  }
1283  else {
1284  enc = fptr->encs.enc2 ? fptr->encs.enc2 : fptr->encs.enc;
1286  if (!senc && !(fptr->encs.ecflags & ECONV_STATEFUL_DECORATOR_MASK)) {
1287  /* single conversion */
1288  fptr->writeconv_pre_ecflags = ecflags;
1289  fptr->writeconv_pre_ecopts = ecopts;
1290  fptr->writeconv = NULL;
1291  fptr->writeconv_asciicompat = Qnil;
1292  }
1293  else {
1294  /* double conversion */
1296  fptr->writeconv_pre_ecopts = ecopts;
1297  if (senc) {
1298  denc = rb_enc_name(enc);
1299  fptr->writeconv_asciicompat = rb_str_new2(senc);
1300  }
1301  else {
1302  senc = denc = "";
1304  }
1306  ecopts = fptr->encs.ecopts;
1307  fptr->writeconv = rb_econv_open_opts(senc, denc, ecflags, ecopts);
1308  if (!fptr->writeconv)
1309  rb_exc_raise(rb_econv_open_exc(senc, denc, ecflags));
1310  }
1311  }
1312  }
1313 }
1314 
1315 /* writing functions */
1319  const char *ptr;
1320  long length;
1321 };
1322 
1323 struct write_arg {
1326  int nosync;
1327 };
1328 
1329 #ifdef HAVE_WRITEV
1330 static VALUE
1331 io_binwrite_string(VALUE arg)
1332 {
1333  struct binwrite_arg *p = (struct binwrite_arg *)arg;
1334  rb_io_t *fptr = p->fptr;
1335  long r;
1336 
1337  if (fptr->wbuf.len) {
1338  struct iovec iov[2];
1339 
1340  iov[0].iov_base = fptr->wbuf.ptr+fptr->wbuf.off;
1341  iov[0].iov_len = fptr->wbuf.len;
1342  iov[1].iov_base = (char *)p->ptr;
1343  iov[1].iov_len = p->length;
1344 
1345  r = rb_writev_internal(fptr->fd, iov, 2);
1346 
1347  if (r < 0)
1348  return r;
1349 
1350  if (fptr->wbuf.len <= r) {
1351  r -= fptr->wbuf.len;
1352  fptr->wbuf.off = 0;
1353  fptr->wbuf.len = 0;
1354  }
1355  else {
1356  fptr->wbuf.off += (int)r;
1357  fptr->wbuf.len -= (int)r;
1358  r = 0L;
1359  }
1360  }
1361  else {
1362  r = rb_write_internal(fptr->fd, p->ptr, p->length);
1363  }
1364 
1365  return r;
1366 }
1367 #else
1368 static VALUE
1369 io_binwrite_string(VALUE arg)
1370 {
1371  struct binwrite_arg *p = (struct binwrite_arg *)arg;
1372  rb_io_t *fptr = p->fptr;
1373  long l, len;
1374 
1375  l = len = p->length;
1376 
1377  if (fptr->wbuf.len) {
1378  if (fptr->wbuf.len+len <= fptr->wbuf.capa) {
1379  if (fptr->wbuf.capa < fptr->wbuf.off+fptr->wbuf.len+len) {
1380  MEMMOVE(fptr->wbuf.ptr, fptr->wbuf.ptr+fptr->wbuf.off, char, fptr->wbuf.len);
1381  fptr->wbuf.off = 0;
1382  }
1383  MEMMOVE(fptr->wbuf.ptr+fptr->wbuf.off+fptr->wbuf.len, p->ptr, char, len);
1384  fptr->wbuf.len += (int)len;
1385  l = 0;
1386  }
1387  if (io_fflush(fptr) < 0)
1388  return -2L; /* fail in fflush */
1389  if (l == 0)
1390  return len;
1391  }
1392 
1393  if (fptr->stdio_file != stderr && !rb_thread_fd_writable(fptr->fd))
1395 
1396  return rb_write_internal(p->fptr->fd, p->ptr, p->length);
1397 }
1398 #endif
1399 
1400 static long
1401 io_binwrite(VALUE str, const char *ptr, long len, rb_io_t *fptr, int nosync)
1402 {
1403  long n, r, offset = 0;
1404 
1405  /* don't write anything if current thread has a pending interrupt. */
1407 
1408  if ((n = len) <= 0) return n;
1409  if (fptr->wbuf.ptr == NULL && !(!nosync && (fptr->mode & FMODE_SYNC))) {
1410  fptr->wbuf.off = 0;
1411  fptr->wbuf.len = 0;
1412  fptr->wbuf.capa = IO_WBUF_CAPA_MIN;
1413  fptr->wbuf.ptr = ALLOC_N(char, fptr->wbuf.capa);
1416  }
1417  if ((!nosync && (fptr->mode & (FMODE_SYNC|FMODE_TTY))) ||
1418  (fptr->wbuf.ptr && fptr->wbuf.capa <= fptr->wbuf.len + len)) {
1419  struct binwrite_arg arg;
1420 
1421  arg.fptr = fptr;
1422  arg.str = str;
1423  retry:
1424  arg.ptr = ptr + offset;
1425  arg.length = n;
1426  if (fptr->write_lock) {
1427  r = rb_mutex_synchronize(fptr->write_lock, io_binwrite_string, (VALUE)&arg);
1428  }
1429  else {
1430  r = io_binwrite_string((VALUE)&arg);
1431  }
1432  /* xxx: other threads may modify given string. */
1433  if (r == n) return len;
1434  if (0 <= r) {
1435  offset += r;
1436  n -= r;
1437  errno = EAGAIN;
1438  }
1439  if (r == -2L)
1440  return -1L;
1441  if (rb_io_wait_writable(fptr->fd)) {
1443  if (offset < len)
1444  goto retry;
1445  }
1446  return -1L;
1447  }
1448 
1449  if (fptr->wbuf.off) {
1450  if (fptr->wbuf.len)
1451  MEMMOVE(fptr->wbuf.ptr, fptr->wbuf.ptr+fptr->wbuf.off, char, fptr->wbuf.len);
1452  fptr->wbuf.off = 0;
1453  }
1454  MEMMOVE(fptr->wbuf.ptr+fptr->wbuf.off+fptr->wbuf.len, ptr+offset, char, len);
1455  fptr->wbuf.len += (int)len;
1456  return len;
1457 }
1458 
1459 # define MODE_BTMODE(a,b,c) ((fmode & FMODE_BINMODE) ? (b) : \
1460  (fmode & FMODE_TEXTMODE) ? (c) : (a))
1461 
1462 #define MODE_BTXMODE(a, b, c, d, e, f) ((fmode & FMODE_EXCL) ? \
1463  MODE_BTMODE(d, e, f) : \
1464  MODE_BTMODE(a, b, c))
1465 
1466 static VALUE
1467 do_writeconv(VALUE str, rb_io_t *fptr, int *converted)
1468 {
1469  if (NEED_WRITECONV(fptr)) {
1470  VALUE common_encoding = Qnil;
1472 
1473  make_writeconv(fptr);
1474 
1475  if (fptr->writeconv) {
1476 #define fmode (fptr->mode)
1478  common_encoding = fptr->writeconv_asciicompat;
1480  rb_raise(rb_eArgError, "ASCII incompatible string written for text mode IO without encoding conversion: %s",
1482  }
1483 #undef fmode
1484  }
1485  else {
1486  if (fptr->encs.enc2)
1487  common_encoding = rb_enc_from_encoding(fptr->encs.enc2);
1488  else if (fptr->encs.enc != rb_ascii8bit_encoding())
1489  common_encoding = rb_enc_from_encoding(fptr->encs.enc);
1490  }
1491 
1492  if (!NIL_P(common_encoding)) {
1493  str = rb_str_encode(str, common_encoding,
1495  *converted = 1;
1496  }
1497 
1498  if (fptr->writeconv) {
1500  *converted = 1;
1501  }
1502  }
1503 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
1504 #define fmode (fptr->mode)
1505  else if (MODE_BTMODE(DEFAULT_TEXTMODE,0,1)) {
1506  if ((fptr->mode & FMODE_READABLE) &&
1508  setmode(fptr->fd, O_BINARY);
1509  }
1510  else {
1511  setmode(fptr->fd, O_TEXT);
1512  }
1514  rb_raise(rb_eArgError, "ASCII incompatible string written for text mode IO without encoding conversion: %s",
1516  }
1517  }
1518 #undef fmode
1519 #endif
1520  return str;
1521 }
1522 
1523 static long
1524 io_fwrite(VALUE str, rb_io_t *fptr, int nosync)
1525 {
1526  int converted = 0;
1527  VALUE tmp;
1528  long n, len;
1529  const char *ptr;
1530 #ifdef _WIN32
1531  if (fptr->mode & FMODE_TTY) {
1532  long len = rb_w32_write_console(str, fptr->fd);
1533  if (len > 0) return len;
1534  }
1535 #endif
1536  str = do_writeconv(str, fptr, &converted);
1537  if (converted)
1538  OBJ_FREEZE(str);
1539 
1541  RSTRING_GETMEM(tmp, ptr, len);
1542  n = io_binwrite(tmp, ptr, len, fptr, nosync);
1544 
1545  return n;
1546 }
1547 
1548 ssize_t
1549 rb_io_bufwrite(VALUE io, const void *buf, size_t size)
1550 {
1551  rb_io_t *fptr;
1552 
1553  GetOpenFile(io, fptr);
1555  return (ssize_t)io_binwrite(0, buf, (long)size, fptr, 0);
1556 }
1557 
1558 static VALUE
1559 io_write(VALUE io, VALUE str, int nosync)
1560 {
1561  rb_io_t *fptr;
1562  long n;
1563  VALUE tmp;
1564 
1565  io = GetWriteIO(io);
1567  tmp = rb_io_check_io(io);
1568  if (NIL_P(tmp)) {
1569  /* port is not IO, call write method for it. */
1570  return rb_funcall(io, id_write, 1, str);
1571  }
1572  io = tmp;
1573  if (RSTRING_LEN(str) == 0) return INT2FIX(0);
1574 
1575  GetOpenFile(io, fptr);
1577 
1578  n = io_fwrite(str, fptr, nosync);
1579  if (n < 0L) rb_sys_fail_path(fptr->pathv);
1580 
1581  return LONG2FIX(n);
1582 }
1583 
1584 #ifdef HAVE_WRITEV
1585 struct binwritev_arg {
1586  rb_io_t *fptr;
1587  const struct iovec *iov;
1588  int iovcnt;
1589 };
1590 
1591 static VALUE
1592 call_writev_internal(VALUE arg)
1593 {
1594  struct binwritev_arg *p = (struct binwritev_arg *)arg;
1595  return rb_writev_internal(p->fptr->fd, p->iov, p->iovcnt);
1596 }
1597 
1598 static long
1599 io_binwritev(struct iovec *iov, int iovcnt, rb_io_t *fptr)
1600 {
1601  int i;
1602  long r, total = 0, written_len = 0;
1603 
1604  /* don't write anything if current thread has a pending interrupt. */
1606 
1607  if (iovcnt == 0) return 0;
1608  for (i = 1; i < iovcnt; i++) total += iov[i].iov_len;
1609 
1610  if (fptr->wbuf.ptr == NULL && !(fptr->mode & FMODE_SYNC)) {
1611  fptr->wbuf.off = 0;
1612  fptr->wbuf.len = 0;
1613  fptr->wbuf.capa = IO_WBUF_CAPA_MIN;
1614  fptr->wbuf.ptr = ALLOC_N(char, fptr->wbuf.capa);
1615  fptr->write_lock = rb_mutex_new();
1616  rb_mutex_allow_trap(fptr->write_lock, 1);
1617  }
1618 
1619  if (fptr->wbuf.ptr && fptr->wbuf.len) {
1620  long offset = fptr->wbuf.off + fptr->wbuf.len;
1621  if (offset + total <= fptr->wbuf.capa) {
1622  for (i = 1; i < iovcnt; i++) {
1623  memcpy(fptr->wbuf.ptr+offset, iov[i].iov_base, iov[i].iov_len);
1624  offset += iov[i].iov_len;
1625  }
1626  fptr->wbuf.len += total;
1627  return total;
1628  }
1629  else {
1630  iov[0].iov_base = fptr->wbuf.ptr + fptr->wbuf.off;
1631  iov[0].iov_len = fptr->wbuf.len;
1632  }
1633  }
1634  else {
1635  iov++;
1636  if (!--iovcnt) return 0;
1637  }
1638 
1639  retry:
1640  if (fptr->write_lock) {
1641  struct binwritev_arg arg;
1642  arg.fptr = fptr;
1643  arg.iov = iov;
1644  arg.iovcnt = iovcnt;
1645  r = rb_mutex_synchronize(fptr->write_lock, call_writev_internal, (VALUE)&arg);
1646  }
1647  else {
1648  r = rb_writev_internal(fptr->fd, iov, iovcnt);
1649  }
1650 
1651  if (r >= 0) {
1652  written_len += r;
1653  if (fptr->wbuf.ptr && fptr->wbuf.len) {
1654  if (written_len < fptr->wbuf.len) {
1655  fptr->wbuf.off += r;
1656  fptr->wbuf.len -= r;
1657  }
1658  else {
1659  written_len -= fptr->wbuf.len;
1660  fptr->wbuf.off = 0;
1661  fptr->wbuf.len = 0;
1662  }
1663  }
1664  if (written_len == total) return total;
1665 
1666  while (r >= (ssize_t)iov->iov_len) {
1667  /* iovcnt > 0 */
1668  r -= iov->iov_len;
1669  iov->iov_len = 0;
1670  iov++;
1671  if (!--iovcnt) return total;
1672  /* defensive check: written_len should == total */
1673  }
1674  iov->iov_base = (char *)iov->iov_base + r;
1675  iov->iov_len -= r;
1676 
1677  errno = EAGAIN;
1678  }
1679  if (rb_io_wait_writable(fptr->fd)) {
1680  rb_io_check_closed(fptr);
1681  goto retry;
1682  }
1683 
1684  return -1L;
1685 }
1686 
1687 static long
1688 io_fwritev(int argc, VALUE *argv, rb_io_t *fptr)
1689 {
1690  int i, converted, iovcnt = argc + 1;
1691  long n;
1692  VALUE v1, v2, str, tmp, *tmp_array;
1693  struct iovec *iov;
1694 
1695  iov = ALLOCV_N(struct iovec, v1, iovcnt);
1696  tmp_array = ALLOCV_N(VALUE, v2, argc);
1697 
1698  for (i = 0; i < argc; i++) {
1699  str = rb_obj_as_string(argv[i]);
1700  converted = 0;
1701  str = do_writeconv(str, fptr, &converted);
1702  if (converted)
1703  OBJ_FREEZE(str);
1704 
1706  tmp_array[i] = tmp;
1707  /* iov[0] is reserved for buffer of fptr */
1708  iov[i+1].iov_base = RSTRING_PTR(tmp);
1709  iov[i+1].iov_len = RSTRING_LEN(tmp);
1710  }
1711 
1712  n = io_binwritev(iov, iovcnt, fptr);
1713  if (v1) ALLOCV_END(v1);
1714 
1715  for (i = 0; i < argc; i++) {
1716  rb_str_tmp_frozen_release(argv[i], tmp_array[i]);
1717  }
1718 
1719  if (v2) ALLOCV_END(v2);
1720 
1721  return n;
1722 }
1723 
1724 static int
1725 iovcnt_ok(int iovcnt)
1726 {
1727 #ifdef IOV_MAX
1728  return iovcnt < IOV_MAX;
1729 #else /* GNU/Hurd has writev, but no IOV_MAX */
1730  return 1;
1731 #endif
1732 }
1733 #endif /* HAVE_WRITEV */
1734 
1735 static VALUE
1736 io_writev(int argc, VALUE *argv, VALUE io)
1737 {
1738  rb_io_t *fptr;
1739  long n;
1740  VALUE tmp, total = INT2FIX(0);
1741  int i, cnt = 1;
1742 
1743  io = GetWriteIO(io);
1744  tmp = rb_io_check_io(io);
1745  if (NIL_P(tmp)) {
1746  /* port is not IO, call write method for it. */
1747  return rb_funcallv(io, id_write, argc, argv);
1748  }
1749  io = tmp;
1750 
1751  GetOpenFile(io, fptr);
1752  rb_io_check_writable(fptr);
1753 
1754  for (i = 0; i < argc; i += cnt) {
1755 #ifdef HAVE_WRITEV
1756  if ((fptr->mode & (FMODE_SYNC|FMODE_TTY)) && iovcnt_ok(cnt = argc - i)) {
1757  n = io_fwritev(cnt, &argv[i], fptr);
1758  }
1759  else
1760 #endif
1761  {
1762  cnt = 1;
1763  /* sync at last item */
1764  n = io_fwrite(rb_obj_as_string(argv[i]), fptr, (i < argc-1));
1765  }
1766  if (n < 0L) rb_sys_fail_path(fptr->pathv);
1767  total = rb_fix_plus(LONG2FIX(n), total);
1768  }
1769 
1770  return total;
1771 }
1772 
1773 /*
1774  * call-seq:
1775  * ios.write(string, ...) -> integer
1776  *
1777  * Writes the given strings to <em>ios</em>. The stream must be opened
1778  * for writing. Arguments that are not a string will be converted
1779  * to a string using <code>to_s</code>. Returns the number of bytes
1780  * written in total.
1781  *
1782  * count = $stdout.write("This is", " a test\n")
1783  * puts "That was #{count} bytes of data"
1784  *
1785  * <em>produces:</em>
1786  *
1787  * This is a test
1788  * That was 15 bytes of data
1789  */
1790 
1791 static VALUE
1792 io_write_m(int argc, VALUE *argv, VALUE io)
1793 {
1794  if (argc != 1) {
1795  return io_writev(argc, argv, io);
1796  }
1797  else {
1798  VALUE str = argv[0];
1799  return io_write(io, str, 0);
1800  }
1801 }
1802 
1803 VALUE
1805 {
1806  return rb_funcallv(io, id_write, 1, &str);
1807 }
1808 
1809 static VALUE
1810 rb_io_writev(VALUE io, int argc, VALUE *argv)
1811 {
1812  if (argc > 1 && rb_obj_method_arity(io, id_write) == 1) {
1813  if (io != rb_stderr && RTEST(ruby_verbose)) {
1814  VALUE klass = CLASS_OF(io);
1815  char sep = FL_TEST(klass, FL_SINGLETON) ? (klass = io, '.') : '#';
1816  rb_warning("%+"PRIsVALUE"%c""write is outdated interface"
1817  " which accepts just one argument",
1818  klass, sep);
1819  }
1820  do rb_io_write(io, *argv++); while (--argc);
1821  return argv[0]; /* unused right now */
1822  }
1823  return rb_funcallv(io, id_write, argc, argv);
1824 }
1825 
1826 /*
1827  * call-seq:
1828  * ios << obj -> ios
1829  *
1830  * String Output---Writes <i>obj</i> to <em>ios</em>.
1831  * <i>obj</i> will be converted to a string using
1832  * <code>to_s</code>.
1833  *
1834  * $stdout << "Hello " << "world!\n"
1835  *
1836  * <em>produces:</em>
1837  *
1838  * Hello world!
1839  */
1840 
1841 
1842 VALUE
1844 {
1845  rb_io_write(io, str);
1846  return io;
1847 }
1848 
1849 #ifdef HAVE_FSYNC
1850 static VALUE
1851 nogvl_fsync(void *ptr)
1852 {
1853  rb_io_t *fptr = ptr;
1854 
1855 #ifdef _WIN32
1856  if (GetFileType((HANDLE)rb_w32_get_osfhandle(fptr->fd)) != FILE_TYPE_DISK)
1857  return 0;
1858 #endif
1859  return (VALUE)fsync(fptr->fd);
1860 }
1861 #endif
1862 
1863 VALUE
1864 rb_io_flush_raw(VALUE io, int sync)
1865 {
1866  rb_io_t *fptr;
1867 
1868  if (!RB_TYPE_P(io, T_FILE)) {
1869  return rb_funcall(io, id_flush, 0);
1870  }
1871 
1872  io = GetWriteIO(io);
1873  GetOpenFile(io, fptr);
1874 
1875  if (fptr->mode & FMODE_WRITABLE) {
1876  if (io_fflush(fptr) < 0)
1877  rb_sys_fail(0);
1878  }
1879  if (fptr->mode & FMODE_READABLE) {
1880  io_unread(fptr);
1881  }
1882 
1883  return io;
1884 }
1885 
1886 /*
1887  * call-seq:
1888  * ios.flush -> ios
1889  *
1890  * Flushes any buffered data within <em>ios</em> to the underlying
1891  * operating system (note that this is Ruby internal buffering only;
1892  * the OS may buffer the data as well).
1893  *
1894  * $stdout.print "no newline"
1895  * $stdout.flush
1896  *
1897  * <em>produces:</em>
1898  *
1899  * no newline
1900  */
1901 
1902 VALUE
1904 {
1905  return rb_io_flush_raw(io, 1);
1906 }
1907 
1908 /*
1909  * call-seq:
1910  * ios.pos -> integer
1911  * ios.tell -> integer
1912  *
1913  * Returns the current offset (in bytes) of <em>ios</em>.
1914  *
1915  * f = File.new("testfile")
1916  * f.pos #=> 0
1917  * f.gets #=> "This is line one\n"
1918  * f.pos #=> 17
1919  */
1920 
1921 static VALUE
1922 rb_io_tell(VALUE io)
1923 {
1924  rb_io_t *fptr;
1925  off_t pos;
1926 
1927  GetOpenFile(io, fptr);
1928  pos = io_tell(fptr);
1929  if (pos < 0 && errno) rb_sys_fail_path(fptr->pathv);
1930  pos -= fptr->rbuf.len;
1931  return OFFT2NUM(pos);
1932 }
1933 
1934 static VALUE
1935 rb_io_seek(VALUE io, VALUE offset, int whence)
1936 {
1937  rb_io_t *fptr;
1938  off_t pos;
1939 
1940  pos = NUM2OFFT(offset);
1941  GetOpenFile(io, fptr);
1942  pos = io_seek(fptr, pos, whence);
1943  if (pos < 0 && errno) rb_sys_fail_path(fptr->pathv);
1944 
1945  return INT2FIX(0);
1946 }
1947 
1948 static int
1949 interpret_seek_whence(VALUE vwhence)
1950 {
1951  if (vwhence == sym_SET)
1952  return SEEK_SET;
1953  if (vwhence == sym_CUR)
1954  return SEEK_CUR;
1955  if (vwhence == sym_END)
1956  return SEEK_END;
1957 #ifdef SEEK_DATA
1958  if (vwhence == sym_DATA)
1959  return SEEK_DATA;
1960 #endif
1961 #ifdef SEEK_HOLE
1962  if (vwhence == sym_HOLE)
1963  return SEEK_HOLE;
1964 #endif
1965  return NUM2INT(vwhence);
1966 }
1967 
1968 /*
1969  * call-seq:
1970  * ios.seek(amount, whence=IO::SEEK_SET) -> 0
1971  *
1972  * Seeks to a given offset <i>anInteger</i> in the stream according to
1973  * the value of <i>whence</i>:
1974  *
1975  * :CUR or IO::SEEK_CUR | Seeks to _amount_ plus current position
1976  * ----------------------+--------------------------------------------------
1977  * :END or IO::SEEK_END | Seeks to _amount_ plus end of stream (you
1978  * | probably want a negative value for _amount_)
1979  * ----------------------+--------------------------------------------------
1980  * :SET or IO::SEEK_SET | Seeks to the absolute location given by _amount_
1981  *
1982  * Example:
1983  *
1984  * f = File.new("testfile")
1985  * f.seek(-13, IO::SEEK_END) #=> 0
1986  * f.readline #=> "And so on...\n"
1987  */
1988 
1989 static VALUE
1990 rb_io_seek_m(int argc, VALUE *argv, VALUE io)
1991 {
1992  VALUE offset, ptrname;
1993  int whence = SEEK_SET;
1994 
1995  if (rb_scan_args(argc, argv, "11", &offset, &ptrname) == 2) {
1996  whence = interpret_seek_whence(ptrname);
1997  }
1998 
1999  return rb_io_seek(io, offset, whence);
2000 }
2001 
2002 /*
2003  * call-seq:
2004  * ios.pos = integer -> integer
2005  *
2006  * Seeks to the given position (in bytes) in <em>ios</em>.
2007  * It is not guaranteed that seeking to the right position when <em>ios</em>
2008  * is textmode.
2009  *
2010  * f = File.new("testfile")
2011  * f.pos = 17
2012  * f.gets #=> "This is line two\n"
2013  */
2014 
2015 static VALUE
2016 rb_io_set_pos(VALUE io, VALUE offset)
2017 {
2018  rb_io_t *fptr;
2019  off_t pos;
2020 
2021  pos = NUM2OFFT(offset);
2022  GetOpenFile(io, fptr);
2023  pos = io_seek(fptr, pos, SEEK_SET);
2024  if (pos < 0 && errno) rb_sys_fail_path(fptr->pathv);
2025 
2026  return OFFT2NUM(pos);
2027 }
2028 
2029 static void clear_readconv(rb_io_t *fptr);
2030 
2031 /*
2032  * call-seq:
2033  * ios.rewind -> 0
2034  *
2035  * Positions <em>ios</em> to the beginning of input, resetting
2036  * #lineno to zero.
2037  *
2038  * f = File.new("testfile")
2039  * f.readline #=> "This is line one\n"
2040  * f.rewind #=> 0
2041  * f.lineno #=> 0
2042  * f.readline #=> "This is line one\n"
2043  *
2044  * Note that it cannot be used with streams such as pipes, ttys, and sockets.
2045  */
2046 
2047 static VALUE
2048 rb_io_rewind(VALUE io)
2049 {
2050  rb_io_t *fptr;
2051 
2052  GetOpenFile(io, fptr);
2053  if (io_seek(fptr, 0L, 0) < 0 && errno) rb_sys_fail_path(fptr->pathv);
2054  if (io == ARGF.current_file) {
2055  ARGF.lineno -= fptr->lineno;
2056  }
2057  fptr->lineno = 0;
2058  if (fptr->readconv) {
2059  clear_readconv(fptr);
2060  }
2061 
2062  return INT2FIX(0);
2063 }
2064 
2065 static int
2066 fptr_wait_readable(rb_io_t *fptr)
2067 {
2068  int ret = rb_io_wait_readable(fptr->fd);
2069 
2070  if (ret)
2071  rb_io_check_closed(fptr);
2072  return ret;
2073 }
2074 
2075 static int
2076 io_fillbuf(rb_io_t *fptr)
2077 {
2078  ssize_t r;
2079 
2080  if (fptr->rbuf.ptr == NULL) {
2081  fptr->rbuf.off = 0;
2082  fptr->rbuf.len = 0;
2083  fptr->rbuf.capa = IO_RBUF_CAPA_FOR(fptr);
2084  fptr->rbuf.ptr = ALLOC_N(char, fptr->rbuf.capa);
2085 #ifdef _WIN32
2086  fptr->rbuf.capa--;
2087 #endif
2088  }
2089  if (fptr->rbuf.len == 0) {
2090  retry:
2091  {
2092  r = rb_read_internal(fptr->fd, fptr->rbuf.ptr, fptr->rbuf.capa);
2093  }
2094  if (r < 0) {
2095  if (fptr_wait_readable(fptr))
2096  goto retry;
2097  {
2098  int e = errno;
2099  VALUE path = rb_sprintf("fd:%d ", fptr->fd);
2100  if (!NIL_P(fptr->pathv)) {
2101  rb_str_append(path, fptr->pathv);
2102  }
2103  rb_syserr_fail_path(e, path);
2104  }
2105  }
2106  if (r > 0) rb_io_check_closed(fptr);
2107  fptr->rbuf.off = 0;
2108  fptr->rbuf.len = (int)r; /* r should be <= rbuf_capa */
2109  if (r == 0)
2110  return -1; /* EOF */
2111  }
2112  return 0;
2113 }
2114 
2115 /*
2116  * call-seq:
2117  * ios.eof -> true or false
2118  * ios.eof? -> true or false
2119  *
2120  * Returns true if <em>ios</em> is at end of file that means
2121  * there are no more data to read.
2122  * The stream must be opened for reading or an IOError will be
2123  * raised.
2124  *
2125  * f = File.new("testfile")
2126  * dummy = f.readlines
2127  * f.eof #=> true
2128  *
2129  * If <em>ios</em> is a stream such as pipe or socket, IO#eof?
2130  * blocks until the other end sends some data or closes it.
2131  *
2132  * r, w = IO.pipe
2133  * Thread.new { sleep 1; w.close }
2134  * r.eof? #=> true after 1 second blocking
2135  *
2136  * r, w = IO.pipe
2137  * Thread.new { sleep 1; w.puts "a" }
2138  * r.eof? #=> false after 1 second blocking
2139  *
2140  * r, w = IO.pipe
2141  * r.eof? # blocks forever
2142  *
2143  * Note that IO#eof? reads data to the input byte buffer. So
2144  * IO#sysread may not behave as you intend with IO#eof?, unless you
2145  * call IO#rewind first (which is not available for some streams).
2146  */
2147 
2148 VALUE
2150 {
2151  rb_io_t *fptr;
2152 
2153  GetOpenFile(io, fptr);
2155 
2156  if (READ_CHAR_PENDING(fptr)) return Qfalse;
2157  if (READ_DATA_PENDING(fptr)) return Qfalse;
2158  READ_CHECK(fptr);
2159 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
2160  if (!NEED_READCONV(fptr) && NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {
2161  return eof(fptr->fd) ? Qtrue : Qfalse;
2162  }
2163 #endif
2164  if (io_fillbuf(fptr) < 0) {
2165  return Qtrue;
2166  }
2167  return Qfalse;
2168 }
2169 
2170 /*
2171  * call-seq:
2172  * ios.sync -> true or false
2173  *
2174  * Returns the current ``sync mode'' of <em>ios</em>. When sync mode is
2175  * true, all output is immediately flushed to the underlying operating
2176  * system and is not buffered by Ruby internally. See also
2177  * IO#fsync.
2178  *
2179  * f = File.new("testfile")
2180  * f.sync #=> false
2181  */
2182 
2183 static VALUE
2184 rb_io_sync(VALUE io)
2185 {
2186  rb_io_t *fptr;
2187 
2188  io = GetWriteIO(io);
2189  GetOpenFile(io, fptr);
2190  return (fptr->mode & FMODE_SYNC) ? Qtrue : Qfalse;
2191 }
2192 
2193 #ifdef HAVE_FSYNC
2194 
2195 /*
2196  * call-seq:
2197  * ios.sync = boolean -> boolean
2198  *
2199  * Sets the ``sync mode'' to <code>true</code> or <code>false</code>.
2200  * When sync mode is true, all output is immediately flushed to the
2201  * underlying operating system and is not buffered internally. Returns
2202  * the new state. See also IO#fsync.
2203  *
2204  * f = File.new("testfile")
2205  * f.sync = true
2206  */
2207 
2208 static VALUE
2209 rb_io_set_sync(VALUE io, VALUE sync)
2210 {
2211  rb_io_t *fptr;
2212 
2213  io = GetWriteIO(io);
2214  GetOpenFile(io, fptr);
2215  if (RTEST(sync)) {
2216  fptr->mode |= FMODE_SYNC;
2217  }
2218  else {
2219  fptr->mode &= ~FMODE_SYNC;
2220  }
2221  return sync;
2222 }
2223 
2224 /*
2225  * call-seq:
2226  * ios.fsync -> 0 or nil
2227  *
2228  * Immediately writes all buffered data in <em>ios</em> to disk.
2229  * Note that #fsync differs from using IO#sync=. The latter ensures
2230  * that data is flushed from Ruby's buffers, but does not guarantee
2231  * that the underlying operating system actually writes it to disk.
2232  *
2233  * NotImplementedError is raised
2234  * if the underlying operating system does not support <em>fsync(2)</em>.
2235  */
2236 
2237 static VALUE
2238 rb_io_fsync(VALUE io)
2239 {
2240  rb_io_t *fptr;
2241 
2242  io = GetWriteIO(io);
2243  GetOpenFile(io, fptr);
2244 
2245  if (io_fflush(fptr) < 0)
2246  rb_sys_fail(0);
2247  if ((int)rb_thread_io_blocking_region(nogvl_fsync, fptr, fptr->fd) < 0)
2248  rb_sys_fail_path(fptr->pathv);
2249  return INT2FIX(0);
2250 }
2251 #else
2252 # define rb_io_fsync rb_f_notimplement
2253 # define rb_io_sync rb_f_notimplement
2254 static VALUE
2255 rb_io_set_sync(VALUE io, VALUE sync)
2256 {
2257  rb_notimplement();
2258  UNREACHABLE;
2259 }
2260 #endif
2261 
2262 #ifdef HAVE_FDATASYNC
2263 static VALUE
2264 nogvl_fdatasync(void *ptr)
2265 {
2266  rb_io_t *fptr = ptr;
2267 
2268 #ifdef _WIN32
2269  if (GetFileType((HANDLE)rb_w32_get_osfhandle(fptr->fd)) != FILE_TYPE_DISK)
2270  return 0;
2271 #endif
2272  return (VALUE)fdatasync(fptr->fd);
2273 }
2274 
2275 /*
2276  * call-seq:
2277  * ios.fdatasync -> 0 or nil
2278  *
2279  * Immediately writes all buffered data in <em>ios</em> to disk.
2280  *
2281  * If the underlying operating system does not support <em>fdatasync(2)</em>,
2282  * IO#fsync is called instead (which might raise a
2283  * NotImplementedError).
2284  */
2285 
2286 static VALUE
2288 {
2289  rb_io_t *fptr;
2290 
2291  io = GetWriteIO(io);
2292  GetOpenFile(io, fptr);
2293 
2294  if (io_fflush(fptr) < 0)
2295  rb_sys_fail(0);
2296 
2297  if ((int)rb_thread_io_blocking_region(nogvl_fdatasync, fptr, fptr->fd) == 0)
2298  return INT2FIX(0);
2299 
2300  /* fall back */
2301  return rb_io_fsync(io);
2302 }
2303 #else
2304 #define rb_io_fdatasync rb_io_fsync
2305 #endif
2306 
2307 /*
2308  * call-seq:
2309  * ios.fileno -> integer
2310  * ios.to_i -> integer
2311  *
2312  * Returns an integer representing the numeric file descriptor for
2313  * <em>ios</em>.
2314  *
2315  * $stdin.fileno #=> 0
2316  * $stdout.fileno #=> 1
2317  */
2318 
2319 static VALUE
2320 rb_io_fileno(VALUE io)
2321 {
2322  rb_io_t *fptr = RFILE(io)->fptr;
2323  int fd;
2324 
2325  rb_io_check_closed(fptr);
2326  fd = fptr->fd;
2327  return INT2FIX(fd);
2328 }
2329 
2330 
2331 /*
2332  * call-seq:
2333  * ios.pid -> integer
2334  *
2335  * Returns the process ID of a child process associated with
2336  * <em>ios</em>. This will be set by IO.popen.
2337  *
2338  * pipe = IO.popen("-")
2339  * if pipe
2340  * $stderr.puts "In parent, child pid is #{pipe.pid}"
2341  * else
2342  * $stderr.puts "In child, pid is #{$$}"
2343  * end
2344  *
2345  * <em>produces:</em>
2346  *
2347  * In child, pid is 26209
2348  * In parent, child pid is 26209
2349  */
2350 
2351 static VALUE
2352 rb_io_pid(VALUE io)
2353 {
2354  rb_io_t *fptr;
2355 
2356  GetOpenFile(io, fptr);
2357  if (!fptr->pid)
2358  return Qnil;
2359  return PIDT2NUM(fptr->pid);
2360 }
2361 
2362 
2363 /*
2364  * call-seq:
2365  * ios.inspect -> string
2366  *
2367  * Return a string describing this IO object.
2368  */
2369 
2370 static VALUE
2371 rb_io_inspect(VALUE obj)
2372 {
2373  rb_io_t *fptr;
2374  VALUE result;
2375  static const char closed[] = " (closed)";
2376 
2377  fptr = RFILE(obj)->fptr;
2378  if (!fptr) return rb_any_to_s(obj);
2379  result = rb_str_new_cstr("#<");
2380  rb_str_append(result, rb_class_name(CLASS_OF(obj)));
2381  rb_str_cat2(result, ":");
2382  if (NIL_P(fptr->pathv)) {
2383  if (fptr->fd < 0) {
2384  rb_str_cat(result, closed+1, strlen(closed)-1);
2385  }
2386  else {
2387  rb_str_catf(result, "fd %d", fptr->fd);
2388  }
2389  }
2390  else {
2391  rb_str_append(result, fptr->pathv);
2392  if (fptr->fd < 0) {
2393  rb_str_cat(result, closed, strlen(closed));
2394  }
2395  }
2396  return rb_str_cat2(result, ">");
2397 }
2398 
2399 /*
2400  * call-seq:
2401  * ios.to_io -> ios
2402  *
2403  * Returns <em>ios</em>.
2404  */
2405 
2406 static VALUE
2407 rb_io_to_io(VALUE io)
2408 {
2409  return io;
2410 }
2411 
2412 /* reading functions */
2413 static long
2414 read_buffered_data(char *ptr, long len, rb_io_t *fptr)
2415 {
2416  int n;
2417 
2418  n = READ_DATA_PENDING_COUNT(fptr);
2419  if (n <= 0) return 0;
2420  if (n > len) n = (int)len;
2421  MEMMOVE(ptr, fptr->rbuf.ptr+fptr->rbuf.off, char, n);
2422  fptr->rbuf.off += n;
2423  fptr->rbuf.len -= n;
2424  return n;
2425 }
2426 
2427 static long
2428 io_bufread(char *ptr, long len, rb_io_t *fptr)
2429 {
2430  long offset = 0;
2431  long n = len;
2432  long c;
2433 
2434  if (READ_DATA_PENDING(fptr) == 0) {
2435  while (n > 0) {
2436  again:
2437  c = rb_read_internal(fptr->fd, ptr+offset, n);
2438  if (c == 0) break;
2439  if (c < 0) {
2440  if (fptr_wait_readable(fptr))
2441  goto again;
2442  return -1;
2443  }
2444  offset += c;
2445  if ((n -= c) <= 0) break;
2446  }
2447  return len - n;
2448  }
2449 
2450  while (n > 0) {
2451  c = read_buffered_data(ptr+offset, n, fptr);
2452  if (c > 0) {
2453  offset += c;
2454  if ((n -= c) <= 0) break;
2455  }
2456  rb_io_check_closed(fptr);
2457  if (io_fillbuf(fptr) < 0) {
2458  break;
2459  }
2460  }
2461  return len - n;
2462 }
2463 
2464 static int io_setstrbuf(VALUE *str, long len);
2465 
2466 struct bufread_arg {
2467  char *str_ptr;
2468  long len;
2470 };
2471 
2472 static VALUE
2473 bufread_call(VALUE arg)
2474 {
2475  struct bufread_arg *p = (struct bufread_arg *)arg;
2476  p->len = io_bufread(p->str_ptr, p->len, p->fptr);
2477  return Qundef;
2478 }
2479 
2480 static long
2481 io_fread(VALUE str, long offset, long size, rb_io_t *fptr)
2482 {
2483  long len;
2484  struct bufread_arg arg;
2485 
2486  io_setstrbuf(&str, offset + size);
2487  arg.str_ptr = RSTRING_PTR(str) + offset;
2488  arg.len = size;
2489  arg.fptr = fptr;
2490  rb_str_locktmp_ensure(str, bufread_call, (VALUE)&arg);
2491  len = arg.len;
2492  if (len < 0) rb_sys_fail_path(fptr->pathv);
2493  return len;
2494 }
2495 
2496 static long
2497 remain_size(rb_io_t *fptr)
2498 {
2499  struct stat st;
2500  off_t siz = READ_DATA_PENDING_COUNT(fptr);
2501  off_t pos;
2502 
2503  if (fstat(fptr->fd, &st) == 0 && S_ISREG(st.st_mode)
2504 #if defined(__HAIKU__)
2505  && (st.st_dev > 3)
2506 #endif
2507  )
2508  {
2509  if (io_fflush(fptr) < 0)
2510  rb_sys_fail(0);
2511  pos = lseek(fptr->fd, 0, SEEK_CUR);
2512  if (st.st_size >= pos && pos >= 0) {
2513  siz += st.st_size - pos;
2514  if (siz > LONG_MAX) {
2515  rb_raise(rb_eIOError, "file too big for single read");
2516  }
2517  }
2518  }
2519  else {
2520  siz += BUFSIZ;
2521  }
2522  return (long)siz;
2523 }
2524 
2525 static VALUE
2526 io_enc_str(VALUE str, rb_io_t *fptr)
2527 {
2528  rb_enc_associate(str, io_read_encoding(fptr));
2529  return str;
2530 }
2531 
2532 static void
2533 make_readconv(rb_io_t *fptr, int size)
2534 {
2535  if (!fptr->readconv) {
2536  int ecflags;
2537  VALUE ecopts;
2538  const char *sname, *dname;
2539  ecflags = fptr->encs.ecflags & ~ECONV_NEWLINE_DECORATOR_WRITE_MASK;
2540  ecopts = fptr->encs.ecopts;
2541  if (fptr->encs.enc2) {
2542  sname = rb_enc_name(fptr->encs.enc2);
2543  dname = rb_enc_name(fptr->encs.enc);
2544  }
2545  else {
2546  sname = dname = "";
2547  }
2548  fptr->readconv = rb_econv_open_opts(sname, dname, ecflags, ecopts);
2549  if (!fptr->readconv)
2550  rb_exc_raise(rb_econv_open_exc(sname, dname, ecflags));
2551  fptr->cbuf.off = 0;
2552  fptr->cbuf.len = 0;
2554  fptr->cbuf.capa = size;
2555  fptr->cbuf.ptr = ALLOC_N(char, fptr->cbuf.capa);
2556  }
2557 }
2558 
2559 #define MORE_CHAR_SUSPENDED Qtrue
2560 #define MORE_CHAR_FINISHED Qnil
2561 static VALUE
2562 fill_cbuf(rb_io_t *fptr, int ec_flags)
2563 {
2564  const unsigned char *ss, *sp, *se;
2565  unsigned char *ds, *dp, *de;
2566  rb_econv_result_t res;
2567  int putbackable;
2568  int cbuf_len0;
2569  VALUE exc;
2570 
2571  ec_flags |= ECONV_PARTIAL_INPUT;
2572 
2573  if (fptr->cbuf.len == fptr->cbuf.capa)
2574  return MORE_CHAR_SUSPENDED; /* cbuf full */
2575  if (fptr->cbuf.len == 0)
2576  fptr->cbuf.off = 0;
2577  else if (fptr->cbuf.off + fptr->cbuf.len == fptr->cbuf.capa) {
2578  memmove(fptr->cbuf.ptr, fptr->cbuf.ptr+fptr->cbuf.off, fptr->cbuf.len);
2579  fptr->cbuf.off = 0;
2580  }
2581 
2582  cbuf_len0 = fptr->cbuf.len;
2583 
2584  while (1) {
2585  ss = sp = (const unsigned char *)fptr->rbuf.ptr + fptr->rbuf.off;
2586  se = sp + fptr->rbuf.len;
2587  ds = dp = (unsigned char *)fptr->cbuf.ptr + fptr->cbuf.off + fptr->cbuf.len;
2588  de = (unsigned char *)fptr->cbuf.ptr + fptr->cbuf.capa;
2589  res = rb_econv_convert(fptr->readconv, &sp, se, &dp, de, ec_flags);
2590  fptr->rbuf.off += (int)(sp - ss);
2591  fptr->rbuf.len -= (int)(sp - ss);
2592  fptr->cbuf.len += (int)(dp - ds);
2593 
2594  putbackable = rb_econv_putbackable(fptr->readconv);
2595  if (putbackable) {
2596  rb_econv_putback(fptr->readconv, (unsigned char *)fptr->rbuf.ptr + fptr->rbuf.off - putbackable, putbackable);
2597  fptr->rbuf.off -= putbackable;
2598  fptr->rbuf.len += putbackable;
2599  }
2600 
2601  exc = rb_econv_make_exception(fptr->readconv);
2602  if (!NIL_P(exc))
2603  return exc;
2604 
2605  if (cbuf_len0 != fptr->cbuf.len)
2606  return MORE_CHAR_SUSPENDED;
2607 
2608  if (res == econv_finished) {
2609  return MORE_CHAR_FINISHED;
2610  }
2611 
2612  if (res == econv_source_buffer_empty) {
2613  if (fptr->rbuf.len == 0) {
2614  READ_CHECK(fptr);
2615  if (io_fillbuf(fptr) < 0) {
2616  if (!fptr->readconv) {
2617  return MORE_CHAR_FINISHED;
2618  }
2619  ds = dp = (unsigned char *)fptr->cbuf.ptr + fptr->cbuf.off + fptr->cbuf.len;
2620  de = (unsigned char *)fptr->cbuf.ptr + fptr->cbuf.capa;
2621  res = rb_econv_convert(fptr->readconv, NULL, NULL, &dp, de, 0);
2622  fptr->cbuf.len += (int)(dp - ds);
2624  break;
2625  }
2626  }
2627  }
2628  }
2629  if (cbuf_len0 != fptr->cbuf.len)
2630  return MORE_CHAR_SUSPENDED;
2631 
2632  return MORE_CHAR_FINISHED;
2633 }
2634 
2635 static VALUE
2636 more_char(rb_io_t *fptr)
2637 {
2638  VALUE v;
2639  v = fill_cbuf(fptr, ECONV_AFTER_OUTPUT);
2640  if (v != MORE_CHAR_SUSPENDED && v != MORE_CHAR_FINISHED)
2641  rb_exc_raise(v);
2642  return v;
2643 }
2644 
2645 static VALUE
2646 io_shift_cbuf(rb_io_t *fptr, int len, VALUE *strp)
2647 {
2648  VALUE str = Qnil;
2649  if (strp) {
2650  str = *strp;
2651  if (NIL_P(str)) {
2652  *strp = str = rb_str_new(fptr->cbuf.ptr+fptr->cbuf.off, len);
2653  }
2654  else {
2655  rb_str_cat(str, fptr->cbuf.ptr+fptr->cbuf.off, len);
2656  }
2657  rb_enc_associate(str, fptr->encs.enc);
2658  }
2659  fptr->cbuf.off += len;
2660  fptr->cbuf.len -= len;
2661  /* xxx: set coderange */
2662  if (fptr->cbuf.len == 0)
2663  fptr->cbuf.off = 0;
2664  else if (fptr->cbuf.capa/2 < fptr->cbuf.off) {
2665  memmove(fptr->cbuf.ptr, fptr->cbuf.ptr+fptr->cbuf.off, fptr->cbuf.len);
2666  fptr->cbuf.off = 0;
2667  }
2668  return str;
2669 }
2670 
2671 static int
2672 io_setstrbuf(VALUE *str, long len)
2673 {
2674 #ifdef _WIN32
2675  len = (len + 1) & ~1L; /* round up for wide char */
2676 #endif
2677  if (NIL_P(*str)) {
2678  *str = rb_str_new(0, len);
2679  return TRUE;
2680  }
2681  else {
2682  VALUE s = StringValue(*str);
2683  long clen = RSTRING_LEN(s);
2684  if (clen >= len) {
2685  rb_str_modify(s);
2686  return FALSE;
2687  }
2688  len -= clen;
2689  }
2691  return FALSE;
2692 }
2693 
2694 #define MAX_REALLOC_GAP 4096
2695 static void
2696 io_shrink_read_string(VALUE str, long n)
2697 {
2698  if (rb_str_capacity(str) - n > MAX_REALLOC_GAP) {
2699  rb_str_resize(str, n);
2700  }
2701 }
2702 
2703 static void
2704 io_set_read_length(VALUE str, long n, int shrinkable)
2705 {
2706  if (RSTRING_LEN(str) != n) {
2707  rb_str_modify(str);
2708  rb_str_set_len(str, n);
2709  if (shrinkable) io_shrink_read_string(str, n);
2710  }
2711 }
2712 
2713 static VALUE
2714 read_all(rb_io_t *fptr, long siz, VALUE str)
2715 {
2716  long bytes;
2717  long n;
2718  long pos;
2719  rb_encoding *enc;
2720  int cr;
2721  int shrinkable;
2722 
2723  if (NEED_READCONV(fptr)) {
2724  int first = !NIL_P(str);
2725  SET_BINARY_MODE(fptr);
2726  shrinkable = io_setstrbuf(&str,0);
2727  make_readconv(fptr, 0);
2728  while (1) {
2729  VALUE v;
2730  if (fptr->cbuf.len) {
2731  if (first) rb_str_set_len(str, first = 0);
2732  io_shift_cbuf(fptr, fptr->cbuf.len, &str);
2733  }
2734  v = fill_cbuf(fptr, 0);
2735  if (v != MORE_CHAR_SUSPENDED && v != MORE_CHAR_FINISHED) {
2736  if (fptr->cbuf.len) {
2737  if (first) rb_str_set_len(str, first = 0);
2738  io_shift_cbuf(fptr, fptr->cbuf.len, &str);
2739  }
2740  rb_exc_raise(v);
2741  }
2742  if (v == MORE_CHAR_FINISHED) {
2743  clear_readconv(fptr);
2744  if (first) rb_str_set_len(str, first = 0);
2745  if (shrinkable) io_shrink_read_string(str, RSTRING_LEN(str));
2746  return io_enc_str(str, fptr);
2747  }
2748  }
2749  }
2750 
2752  bytes = 0;
2753  pos = 0;
2754 
2755  enc = io_read_encoding(fptr);
2756  cr = 0;
2757 
2758  if (siz == 0) siz = BUFSIZ;
2759  shrinkable = io_setstrbuf(&str, siz);
2760  for (;;) {
2761  READ_CHECK(fptr);
2762  n = io_fread(str, bytes, siz - bytes, fptr);
2763  if (n == 0 && bytes == 0) {
2764  rb_str_set_len(str, 0);
2765  break;
2766  }
2767  bytes += n;
2768  rb_str_set_len(str, bytes);
2769  if (cr != ENC_CODERANGE_BROKEN)
2770  pos += rb_str_coderange_scan_restartable(RSTRING_PTR(str) + pos, RSTRING_PTR(str) + bytes, enc, &cr);
2771  if (bytes < siz) break;
2772  siz += BUFSIZ;
2773  rb_str_modify_expand(str, BUFSIZ);
2774  }
2775  if (shrinkable) io_shrink_read_string(str, RSTRING_LEN(str));
2776  str = io_enc_str(str, fptr);
2777  ENC_CODERANGE_SET(str, cr);
2778  return str;
2779 }
2780 
2781 void
2783 {
2784  if (rb_fd_set_nonblock(fptr->fd) != 0) {
2785  rb_sys_fail_path(fptr->pathv);
2786  }
2787 }
2788 
2789 static VALUE
2790 read_internal_call(VALUE arg)
2791 {
2792  struct io_internal_read_struct *iis = (struct io_internal_read_struct *)arg;
2793 
2794  return rb_thread_io_blocking_region(internal_read_func, iis, iis->fd);
2795 }
2796 
2797 static long
2798 read_internal_locktmp(VALUE str, struct io_internal_read_struct *iis)
2799 {
2800  return (long)rb_str_locktmp_ensure(str, read_internal_call, (VALUE)iis);
2801 }
2802 
2803 #define no_exception_p(opts) !rb_opts_exception_p((opts), TRUE)
2804 
2805 static VALUE
2806 io_getpartial(int argc, VALUE *argv, VALUE io, int no_exception, int nonblock)
2807 {
2808  rb_io_t *fptr;
2809  VALUE length, str;
2810  long n, len;
2811  struct io_internal_read_struct iis;
2812  int shrinkable;
2813 
2814  rb_scan_args(argc, argv, "11", &length, &str);
2815 
2816  if ((len = NUM2LONG(length)) < 0) {
2817  rb_raise(rb_eArgError, "negative length %ld given", len);
2818  }
2819 
2820  shrinkable = io_setstrbuf(&str, len);
2821 
2822  GetOpenFile(io, fptr);
2824 
2825  if (len == 0)
2826  return str;
2827 
2828  if (!nonblock)
2829  READ_CHECK(fptr);
2830  n = read_buffered_data(RSTRING_PTR(str), len, fptr);
2831  if (n <= 0) {
2832  again:
2833  if (nonblock) {
2834  rb_io_set_nonblock(fptr);
2835  }
2836  io_setstrbuf(&str, len);
2837  iis.fd = fptr->fd;
2838  iis.nonblock = nonblock;
2839  iis.buf = RSTRING_PTR(str);
2840  iis.capa = len;
2841  n = read_internal_locktmp(str, &iis);
2842  if (n < 0) {
2843  int e = errno;
2844  if (!nonblock && fptr_wait_readable(fptr))
2845  goto again;
2846  if (nonblock && (e == EWOULDBLOCK || e == EAGAIN)) {
2847  if (no_exception)
2848  return sym_wait_readable;
2849  else
2851  e, "read would block");
2852  }
2853  rb_syserr_fail_path(e, fptr->pathv);
2854  }
2855  }
2856  io_set_read_length(str, n, shrinkable);
2857 
2858  if (n == 0)
2859  return Qnil;
2860  else
2861  return str;
2862 }
2863 
2864 /*
2865  * call-seq:
2866  * ios.readpartial(maxlen) -> string
2867  * ios.readpartial(maxlen, outbuf) -> outbuf
2868  *
2869  * Reads at most <i>maxlen</i> bytes from the I/O stream.
2870  * It blocks only if <em>ios</em> has no data immediately available.
2871  * It doesn't block if some data available.
2872  *
2873  * If the optional _outbuf_ argument is present,
2874  * it must reference a String, which will receive the data.
2875  * The _outbuf_ will contain only the received data after the method call
2876  * even if it is not empty at the beginning.
2877  *
2878  * It raises EOFError on end of file.
2879  *
2880  * readpartial is designed for streams such as pipe, socket, tty, etc.
2881  * It blocks only when no data immediately available.
2882  * This means that it blocks only when following all conditions hold.
2883  * * the byte buffer in the IO object is empty.
2884  * * the content of the stream is empty.
2885  * * the stream is not reached to EOF.
2886  *
2887  * When readpartial blocks, it waits data or EOF on the stream.
2888  * If some data is reached, readpartial returns with the data.
2889  * If EOF is reached, readpartial raises EOFError.
2890  *
2891  * When readpartial doesn't blocks, it returns or raises immediately.
2892  * If the byte buffer is not empty, it returns the data in the buffer.
2893  * Otherwise if the stream has some content,
2894  * it returns the data in the stream.
2895  * Otherwise if the stream is reached to EOF, it raises EOFError.
2896  *
2897  * r, w = IO.pipe # buffer pipe content
2898  * w << "abc" # "" "abc".
2899  * r.readpartial(4096) #=> "abc" "" ""
2900  * r.readpartial(4096) # blocks because buffer and pipe is empty.
2901  *
2902  * r, w = IO.pipe # buffer pipe content
2903  * w << "abc" # "" "abc"
2904  * w.close # "" "abc" EOF
2905  * r.readpartial(4096) #=> "abc" "" EOF
2906  * r.readpartial(4096) # raises EOFError
2907  *
2908  * r, w = IO.pipe # buffer pipe content
2909  * w << "abc\ndef\n" # "" "abc\ndef\n"
2910  * r.gets #=> "abc\n" "def\n" ""
2911  * w << "ghi\n" # "def\n" "ghi\n"
2912  * r.readpartial(4096) #=> "def\n" "" "ghi\n"
2913  * r.readpartial(4096) #=> "ghi\n" "" ""
2914  *
2915  * Note that readpartial behaves similar to sysread.
2916  * The differences are:
2917  * * If the byte buffer is not empty, read from the byte buffer
2918  * instead of "sysread for buffered IO (IOError)".
2919  * * It doesn't cause Errno::EWOULDBLOCK and Errno::EINTR. When
2920  * readpartial meets EWOULDBLOCK and EINTR by read system call,
2921  * readpartial retry the system call.
2922  *
2923  * The latter means that readpartial is nonblocking-flag insensitive.
2924  * It blocks on the situation IO#sysread causes Errno::EWOULDBLOCK as
2925  * if the fd is blocking mode.
2926  *
2927  */
2928 
2929 static VALUE
2930 io_readpartial(int argc, VALUE *argv, VALUE io)
2931 {
2932  VALUE ret;
2933 
2934  ret = io_getpartial(argc, argv, io, Qnil, 0);
2935  if (NIL_P(ret))
2936  rb_eof_error();
2937  return ret;
2938 }
2939 
2940 static VALUE
2941 io_nonblock_eof(int no_exception)
2942 {
2943  if (!no_exception) {
2944  rb_eof_error();
2945  }
2946  return Qnil;
2947 }
2948 
2949 /* :nodoc: */
2950 static VALUE
2951 io_read_nonblock(rb_execution_context_t *ec, VALUE io, VALUE length, VALUE str, VALUE ex)
2952 {
2953  rb_io_t *fptr;
2954  long n, len;
2955  struct io_internal_read_struct iis;
2956  int shrinkable;
2957 
2958  if ((len = NUM2LONG(length)) < 0) {
2959  rb_raise(rb_eArgError, "negative length %ld given", len);
2960  }
2961 
2962  shrinkable = io_setstrbuf(&str, len);
2963  rb_bool_expected(ex, "exception");
2964 
2965  GetOpenFile(io, fptr);
2967 
2968  if (len == 0)
2969  return str;
2970 
2971  n = read_buffered_data(RSTRING_PTR(str), len, fptr);
2972  if (n <= 0) {
2973  rb_io_set_nonblock(fptr);
2974  shrinkable |= io_setstrbuf(&str, len);
2975  iis.fd = fptr->fd;
2976  iis.nonblock = 1;
2977  iis.buf = RSTRING_PTR(str);
2978  iis.capa = len;
2979  n = read_internal_locktmp(str, &iis);
2980  if (n < 0) {
2981  int e = errno;
2982  if ((e == EWOULDBLOCK || e == EAGAIN)) {
2983  if (!ex) return sym_wait_readable;
2985  e, "read would block");
2986  }
2987  rb_syserr_fail_path(e, fptr->pathv);
2988  }
2989  }
2990  io_set_read_length(str, n, shrinkable);
2991 
2992  if (n == 0) {
2993  if (!ex) return Qnil;
2994  rb_eof_error();
2995  }
2996 
2997  return str;
2998 }
2999 
3000 /* :nodoc: */
3001 static VALUE
3002 io_write_nonblock(rb_execution_context_t *ec, VALUE io, VALUE str, VALUE ex)
3003 {
3004  rb_io_t *fptr;
3005  long n;
3006 
3007  if (!RB_TYPE_P(str, T_STRING))
3009  rb_bool_expected(ex, "exception");
3010 
3011  io = GetWriteIO(io);
3012  GetOpenFile(io, fptr);
3013  rb_io_check_writable(fptr);
3014 
3015  if (io_fflush(fptr) < 0)
3016  rb_sys_fail(0);
3017 
3018  rb_io_set_nonblock(fptr);
3019  n = write(fptr->fd, RSTRING_PTR(str), RSTRING_LEN(str));
3020  RB_GC_GUARD(str);
3021 
3022  if (n < 0) {
3023  int e = errno;
3024  if (e == EWOULDBLOCK || e == EAGAIN) {
3025  if (!ex) {
3026  return sym_wait_writable;
3027  }
3028  else {
3029  rb_readwrite_syserr_fail(RB_IO_WAIT_WRITABLE, e, "write would block");
3030  }
3031  }
3032  rb_syserr_fail_path(e, fptr->pathv);
3033  }
3034 
3035  return LONG2FIX(n);
3036 }
3037 
3038 /*
3039  * call-seq:
3040  * ios.read([length [, outbuf]]) -> string, outbuf, or nil
3041  *
3042  * Reads _length_ bytes from the I/O stream.
3043  *
3044  * _length_ must be a non-negative integer or +nil+.
3045  *
3046  * If _length_ is a positive integer, +read+ tries to read
3047  * _length_ bytes without any conversion (binary mode).
3048  * It returns +nil+ if an EOF is encountered before anything can be read.
3049  * Fewer than _length_ bytes are returned if an EOF is encountered during
3050  * the read.
3051  * In the case of an integer _length_, the resulting string is always
3052  * in ASCII-8BIT encoding.
3053  *
3054  * If _length_ is omitted or is +nil+, it reads until EOF
3055  * and the encoding conversion is applied, if applicable.
3056  * A string is returned even if EOF is encountered before any data is read.
3057  *
3058  * If _length_ is zero, it returns an empty string (<code>""</code>).
3059  *
3060  * If the optional _outbuf_ argument is present,
3061  * it must reference a String, which will receive the data.
3062  * The _outbuf_ will contain only the received data after the method call
3063  * even if it is not empty at the beginning.
3064  *
3065  * When this method is called at end of file, it returns +nil+
3066  * or <code>""</code>, depending on _length_:
3067  * +read+, <code>read(nil)</code>, and <code>read(0)</code> return
3068  * <code>""</code>,
3069  * <code>read(<i>positive_integer</i>)</code> returns +nil+.
3070  *
3071  * f = File.new("testfile")
3072  * f.read(16) #=> "This is line one"
3073  *
3074  * # read whole file
3075  * open("file") do |f|
3076  * data = f.read # This returns a string even if the file is empty.
3077  * # ...
3078  * end
3079  *
3080  * # iterate over fixed length records
3081  * open("fixed-record-file") do |f|
3082  * while record = f.read(256)
3083  * # ...
3084  * end
3085  * end
3086  *
3087  * # iterate over variable length records,
3088  * # each record is prefixed by its 32-bit length
3089  * open("variable-record-file") do |f|
3090  * while len = f.read(4)
3091  * len = len.unpack("N")[0] # 32-bit length
3092  * record = f.read(len) # This returns a string even if len is 0.
3093  * end
3094  * end
3095  *
3096  * Note that this method behaves like the fread() function in C.
3097  * This means it retries to invoke read(2) system calls to read data
3098  * with the specified length (or until EOF).
3099  * This behavior is preserved even if <i>ios</i> is in non-blocking mode.
3100  * (This method is non-blocking flag insensitive as other methods.)
3101  * If you need the behavior like a single read(2) system call,
3102  * consider #readpartial, #read_nonblock, and #sysread.
3103  */
3104 
3105 static VALUE
3106 io_read(int argc, VALUE *argv, VALUE io)
3107 {
3108  rb_io_t *fptr;
3109  long n, len;
3110  VALUE length, str;
3111  int shrinkable;
3112 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
3113  int previous_mode;
3114 #endif
3115 
3116  rb_scan_args(argc, argv, "02", &length, &str);
3117 
3118  if (NIL_P(length)) {
3119  GetOpenFile(io, fptr);
3121  return read_all(fptr, remain_size(fptr), str);
3122  }
3123  len = NUM2LONG(length);
3124  if (len < 0) {
3125  rb_raise(rb_eArgError, "negative length %ld given", len);
3126  }
3127 
3128  shrinkable = io_setstrbuf(&str,len);
3129 
3130  GetOpenFile(io, fptr);
3132  if (len == 0) {
3133  io_set_read_length(str, 0, shrinkable);
3134  return str;
3135  }
3136 
3137  READ_CHECK(fptr);
3138 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
3139  previous_mode = set_binary_mode_with_seek_cur(fptr);
3140 #endif
3141  n = io_fread(str, 0, len, fptr);
3142  io_set_read_length(str, n, shrinkable);
3143 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
3144  if (previous_mode == O_TEXT) {
3145  setmode(fptr->fd, O_TEXT);
3146  }
3147 #endif
3148  if (n == 0) return Qnil;
3149 
3150  return str;
3151 }
3152 
3153 static void
3154 rscheck(const char *rsptr, long rslen, VALUE rs)
3155 {
3156  if (!rs) return;
3157  if (RSTRING_PTR(rs) != rsptr && RSTRING_LEN(rs) != rslen)
3158  rb_raise(rb_eRuntimeError, "rs modified");
3159 }
3160 
3161 static int
3162 appendline(rb_io_t *fptr, int delim, VALUE *strp, long *lp)
3163 {
3164  VALUE str = *strp;
3165  long limit = *lp;
3166 
3167  if (NEED_READCONV(fptr)) {
3168  SET_BINARY_MODE(fptr);
3169  make_readconv(fptr, 0);
3170  do {
3171  const char *p, *e;
3172  int searchlen = READ_CHAR_PENDING_COUNT(fptr);
3173  if (searchlen) {
3174  p = READ_CHAR_PENDING_PTR(fptr);
3175  if (0 < limit && limit < searchlen)
3176  searchlen = (int)limit;
3177  e = memchr(p, delim, searchlen);
3178  if (e) {
3179  int len = (int)(e-p+1);
3180  if (NIL_P(str))
3181  *strp = str = rb_str_new(p, len);
3182  else
3183  rb_str_buf_cat(str, p, len);
3184  fptr->cbuf.off += len;
3185  fptr->cbuf.len -= len;
3186  limit -= len;
3187  *lp = limit;
3188  return delim;
3189  }
3190 
3191  if (NIL_P(str))
3192  *strp = str = rb_str_new(p, searchlen);
3193  else
3194  rb_str_buf_cat(str, p, searchlen);
3195  fptr->cbuf.off += searchlen;
3196  fptr->cbuf.len -= searchlen;
3197  limit -= searchlen;
3198 
3199  if (limit == 0) {
3200  *lp = limit;
3201  return (unsigned char)RSTRING_PTR(str)[RSTRING_LEN(str)-1];
3202  }
3203  }
3204  } while (more_char(fptr) != MORE_CHAR_FINISHED);
3205  clear_readconv(fptr);
3206  *lp = limit;
3207  return EOF;
3208  }
3209 
3211  do {
3212  long pending = READ_DATA_PENDING_COUNT(fptr);
3213  if (pending > 0) {
3214  const char *p = READ_DATA_PENDING_PTR(fptr);
3215  const char *e;
3216  long last;
3217 
3218  if (limit > 0 && pending > limit) pending = limit;
3219  e = memchr(p, delim, pending);
3220  if (e) pending = e - p + 1;
3221  if (!NIL_P(str)) {
3222  last = RSTRING_LEN(str);
3223  rb_str_resize(str, last + pending);
3224  }
3225  else {
3226  last = 0;
3227  *strp = str = rb_str_buf_new(pending);
3228  rb_str_set_len(str, pending);
3229  }
3230  read_buffered_data(RSTRING_PTR(str) + last, pending, fptr); /* must not fail */
3231  limit -= pending;
3232  *lp = limit;
3233  if (e) return delim;
3234  if (limit == 0)
3235  return (unsigned char)RSTRING_PTR(str)[RSTRING_LEN(str)-1];
3236  }
3237  READ_CHECK(fptr);
3238  } while (io_fillbuf(fptr) >= 0);
3239  *lp = limit;
3240  return EOF;
3241 }
3242 
3243 static inline int
3244 swallow(rb_io_t *fptr, int term)
3245 {
3246  if (NEED_READCONV(fptr)) {
3247  rb_encoding *enc = io_read_encoding(fptr);
3248  int needconv = rb_enc_mbminlen(enc) != 1;
3249  SET_BINARY_MODE(fptr);
3250  make_readconv(fptr, 0);
3251  do {
3252  size_t cnt;
3253  while ((cnt = READ_CHAR_PENDING_COUNT(fptr)) > 0) {
3254  const char *p = READ_CHAR_PENDING_PTR(fptr);
3255  int i;
3256  if (!needconv) {
3257  if (*p != term) return TRUE;
3258  i = (int)cnt;
3259  while (--i && *++p == term);
3260  }
3261  else {
3262  const char *e = p + cnt;
3263  if (rb_enc_ascget(p, e, &i, enc) != term) return TRUE;
3264  while ((p += i) < e && rb_enc_ascget(p, e, &i, enc) == term);
3265  i = (int)(e - p);
3266  }
3267  io_shift_cbuf(fptr, (int)cnt - i, NULL);
3268  }
3269  } while (more_char(fptr) != MORE_CHAR_FINISHED);
3270  return FALSE;
3271  }
3272 
3274  do {
3275  size_t cnt;
3276  while ((cnt = READ_DATA_PENDING_COUNT(fptr)) > 0) {
3277  char buf[1024];
3278  const char *p = READ_DATA_PENDING_PTR(fptr);
3279  int i;
3280  if (cnt > sizeof buf) cnt = sizeof buf;
3281  if (*p != term) return TRUE;
3282  i = (int)cnt;
3283  while (--i && *++p == term);
3284  if (!read_buffered_data(buf, cnt - i, fptr)) /* must not fail */
3285  rb_sys_fail_path(fptr->pathv);
3286  }
3287  READ_CHECK(fptr);
3288  } while (io_fillbuf(fptr) == 0);
3289  return FALSE;
3290 }
3291 
3292 static VALUE
3293 rb_io_getline_fast(rb_io_t *fptr, rb_encoding *enc, int chomp)
3294 {
3295  VALUE str = Qnil;
3296  int len = 0;
3297  long pos = 0;
3298  int cr = 0;
3299 
3300  do {
3301  int pending = READ_DATA_PENDING_COUNT(fptr);
3302 
3303  if (pending > 0) {
3304  const char *p = READ_DATA_PENDING_PTR(fptr);
3305  const char *e;
3306  int chomplen = 0;
3307 
3308  e = memchr(p, '\n', pending);
3309  if (e) {
3310  pending = (int)(e - p + 1);
3311  if (chomp) {
3312  chomplen = (pending > 1 && *(e-1) == '\r') + 1;
3313  }
3314  }
3315  if (NIL_P(str)) {
3316  str = rb_str_new(p, pending - chomplen);
3317  fptr->rbuf.off += pending;
3318  fptr->rbuf.len -= pending;
3319  }
3320  else {
3321  rb_str_resize(str, len + pending - chomplen);
3322  read_buffered_data(RSTRING_PTR(str)+len, pending - chomplen, fptr);
3323  fptr->rbuf.off += chomplen;
3324  fptr->rbuf.len -= chomplen;
3325  if (pending == 1 && chomplen == 1 && len > 0) {
3326  if (RSTRING_PTR(str)[len-1] == '\r') {
3327  rb_str_resize(str, --len);
3328  break;
3329  }
3330  }
3331  }
3332  len += pending - chomplen;
3333  if (cr != ENC_CODERANGE_BROKEN)
3334  pos += rb_str_coderange_scan_restartable(RSTRING_PTR(str) + pos, RSTRING_PTR(str) + len, enc, &cr);
3335  if (e) break;
3336  }
3337  READ_CHECK(fptr);
3338  } while (io_fillbuf(fptr) >= 0);
3339  if (NIL_P(str)) return Qnil;
3340 
3341  str = io_enc_str(str, fptr);
3342  ENC_CODERANGE_SET(str, cr);
3343  fptr->lineno++;
3344 
3345  return str;
3346 }
3347 
3348 struct getline_arg {
3350  VALUE rs;
3351  long limit;
3352  unsigned int chomp: 1;
3353 };
3354 
3355 static void
3356 extract_getline_opts(VALUE opts, struct getline_arg *args)
3357 {
3358  int chomp = FALSE;
3359  if (!NIL_P(opts)) {
3360  static ID kwds[1];
3361  VALUE vchomp;
3362  if (!kwds[0]) {
3363  kwds[0] = rb_intern_const("chomp");
3364  }
3365  rb_get_kwargs(opts, kwds, 0, -2, &vchomp);
3366  chomp = (vchomp != Qundef) && RTEST(vchomp);
3367  }
3368  args->chomp = chomp;
3369 }
3370 
3371 static void
3372 extract_getline_args(int argc, VALUE *argv, struct getline_arg *args)
3373 {
3374  VALUE rs = rb_rs, lim = Qnil;
3375 
3376  if (argc == 1) {
3377  VALUE tmp = Qnil;
3378 
3379  if (NIL_P(argv[0]) || !NIL_P(tmp = rb_check_string_type(argv[0]))) {
3380  rs = tmp;
3381  }
3382  else {
3383  lim = argv[0];
3384  }
3385  }
3386  else if (2 <= argc) {
3387  rs = argv[0], lim = argv[1];
3388  if (!NIL_P(rs))
3389  StringValue(rs);
3390  }
3391  args->rs = rs;
3392  args->limit = NIL_P(lim) ? -1L : NUM2LONG(lim);
3393 }
3394 
3395 static void
3396 check_getline_args(VALUE *rsp, long *limit, VALUE io)
3397 {
3398  rb_io_t *fptr;
3399  VALUE rs = *rsp;
3400 
3401  if (!NIL_P(rs)) {
3402  rb_encoding *enc_rs, *enc_io;
3403 
3404  GetOpenFile(io, fptr);
3405  enc_rs = rb_enc_get(rs);
3406  enc_io = io_read_encoding(fptr);
3407  if (enc_io != enc_rs &&
3409  (RSTRING_LEN(rs) > 0 && !rb_enc_asciicompat(enc_io)))) {
3410  if (rs == rb_default_rs) {
3411  rs = rb_enc_str_new(0, 0, enc_io);
3412  rb_str_buf_cat_ascii(rs, "\n");
3413  *rsp = rs;
3414  }
3415  else {
3416  rb_raise(rb_eArgError, "encoding mismatch: %s IO with %s RS",
3417  rb_enc_name(enc_io),
3418  rb_enc_name(enc_rs));
3419  }
3420  }
3421  }
3422 }
3423 
3424 static void
3425 prepare_getline_args(int argc, VALUE *argv, struct getline_arg *args, VALUE io)
3426 {
3427  VALUE opts;
3428  argc = rb_scan_args(argc, argv, "02:", NULL, NULL, &opts);
3429  extract_getline_args(argc, argv, args);
3430  extract_getline_opts(opts, args);
3431  check_getline_args(&args->rs, &args->limit, io);
3432 }
3433 
3434 static VALUE
3435 rb_io_getline_0(VALUE rs, long limit, int chomp, rb_io_t *fptr)
3436 {
3437  VALUE str = Qnil;
3438  int nolimit = 0;
3439  rb_encoding *enc;
3440 
3442  if (NIL_P(rs) && limit < 0) {
3443  str = read_all(fptr, 0, Qnil);
3444  if (RSTRING_LEN(str) == 0) return Qnil;
3445  if (chomp) rb_str_chomp_string(str, rb_default_rs);
3446  }
3447  else if (limit == 0) {
3448  return rb_enc_str_new(0, 0, io_read_encoding(fptr));
3449  }
3450  else if (rs == rb_default_rs && limit < 0 && !NEED_READCONV(fptr) &&
3451  rb_enc_asciicompat(enc = io_read_encoding(fptr))) {
3453  return rb_io_getline_fast(fptr, enc, chomp);
3454  }
3455  else {
3456  int c, newline = -1;
3457  const char *rsptr = 0;
3458  long rslen = 0;
3459  int rspara = 0;
3460  int extra_limit = 16;
3461  int chomp_cr = chomp;
3462 
3463  SET_BINARY_MODE(fptr);
3464  enc = io_read_encoding(fptr);
3465 
3466  if (!NIL_P(rs)) {
3467  rslen = RSTRING_LEN(rs);
3468  if (rslen == 0) {
3469  rsptr = "\n\n";
3470  rslen = 2;
3471  rspara = 1;
3472  swallow(fptr, '\n');
3473  rs = 0;
3474  if (!rb_enc_asciicompat(enc)) {
3475  rs = rb_usascii_str_new(rsptr, rslen);
3476  rs = rb_str_encode(rs, rb_enc_from_encoding(enc), 0, Qnil);
3477  OBJ_FREEZE(rs);
3478  rsptr = RSTRING_PTR(rs);
3479  rslen = RSTRING_LEN(rs);
3480  }
3481  }
3482  else {
3483  rsptr = RSTRING_PTR(rs);
3484  }
3485  newline = (unsigned char)rsptr[rslen - 1];
3486  chomp_cr = chomp && rslen == 1 && newline == '\n';
3487  }
3488 
3489  /* MS - Optimization */
3490  while ((c = appendline(fptr, newline, &str, &limit)) != EOF) {
3491  const char *s, *p, *pp, *e;
3492 
3493  if (c == newline) {
3494  if (RSTRING_LEN(str) < rslen) continue;
3495  s = RSTRING_PTR(str);
3496  e = RSTRING_END(str);
3497  p = e - rslen;
3498  pp = rb_enc_left_char_head(s, p, e, enc);
3499  if (pp != p) continue;
3500  if (!rspara) rscheck(rsptr, rslen, rs);
3501  if (memcmp(p, rsptr, rslen) == 0) {
3502  if (chomp) {
3503  if (chomp_cr && p > s && *(p-1) == '\r') --p;
3504  rb_str_set_len(str, p - s);
3505  }
3506  break;
3507  }
3508  }
3509  if (limit == 0) {
3510  s = RSTRING_PTR(str);
3511  p = RSTRING_END(str);
3512  pp = rb_enc_left_char_head(s, p-1, p, enc);
3513  if (extra_limit &&
3515  /* relax the limit while incomplete character.
3516  * extra_limit limits the relax length */
3517  limit = 1;
3518  extra_limit--;
3519  }
3520  else {
3521  nolimit = 1;
3522  break;
3523  }
3524  }
3525  }
3526 
3527  if (rspara && c != EOF)
3528  swallow(fptr, '\n');
3529  if (!NIL_P(str))
3530  str = io_enc_str(str, fptr);
3531  }
3532 
3533  if (!NIL_P(str) && !nolimit) {
3534  fptr->lineno++;
3535  }
3536 
3537  return str;
3538 }
3539 
3540 static VALUE
3541 rb_io_getline_1(VALUE rs, long limit, int chomp, VALUE io)
3542 {
3543  rb_io_t *fptr;
3544  int old_lineno, new_lineno;
3545  VALUE str;
3546 
3547  GetOpenFile(io, fptr);
3548  old_lineno = fptr->lineno;
3549  str = rb_io_getline_0(rs, limit, chomp, fptr);
3550  if (!NIL_P(str) && (new_lineno = fptr->lineno) != old_lineno) {
3551  if (io == ARGF.current_file) {
3552  ARGF.lineno += new_lineno - old_lineno;
3553  ARGF.last_lineno = ARGF.lineno;
3554  }
3555  else {
3556  ARGF.last_lineno = new_lineno;
3557  }
3558  }
3559 
3560  return str;
3561 }
3562 
3563 static VALUE
3564 rb_io_getline(int argc, VALUE *argv, VALUE io)
3565 {
3566  struct getline_arg args;
3567 
3568  prepare_getline_args(argc, argv, &args, io);
3569  return rb_io_getline_1(args.rs, args.limit, args.chomp, io);
3570 }
3571 
3572 VALUE
3574 {
3575  return rb_io_getline_1(rb_default_rs, -1, FALSE, io);
3576 }
3577 
3578 VALUE
3580 {
3581  rb_io_t *fptr;
3582  GetOpenFile(io, fptr);
3583  return rb_io_getline_0(rb_default_rs, -1, FALSE, fptr);
3584 }
3585 
3586 /*
3587  * call-seq:
3588  * ios.gets(sep=$/ [, getline_args]) -> string or nil
3589  * ios.gets(limit [, getline_args]) -> string or nil
3590  * ios.gets(sep, limit [, getline_args]) -> string or nil
3591  *
3592  * Reads the next ``line'' from the I/O stream; lines are separated by
3593  * <i>sep</i>. A separator of +nil+ reads the entire
3594  * contents, and a zero-length separator reads the input a paragraph at
3595  * a time (two successive newlines in the input separate paragraphs).
3596  * The stream must be opened for reading or an IOError will be raised.
3597  * The line read in will be returned and also assigned to
3598  * <code>$_</code>. Returns +nil+ if called at end of file. If the
3599  * first argument is an integer, or optional second argument is given,
3600  * the returning string would not be longer than the given value in
3601  * bytes.
3602  *
3603  * File.new("testfile").gets #=> "This is line one\n"
3604  * $_ #=> "This is line one\n"
3605  *
3606  * File.new("testfile").gets(4)#=> "This"
3607  *
3608  * If IO contains multibyte characters byte then <code>gets(1)</code>
3609  * returns character entirely:
3610  *
3611  * # Russian characters take 2 bytes
3612  * File.write("testfile", "\u{442 435 441 442}")
3613  * File.open("testfile") {|f|f.gets(1)} #=> "\u0442"
3614  * File.open("testfile") {|f|f.gets(2)} #=> "\u0442"
3615  * File.open("testfile") {|f|f.gets(3)} #=> "\u0442\u0435"
3616  * File.open("testfile") {|f|f.gets(4)} #=> "\u0442\u0435"
3617  */
3618 
3619 static VALUE
3620 rb_io_gets_m(int argc, VALUE *argv, VALUE io)
3621 {
3622  VALUE str;
3623 
3624  str = rb_io_getline(argc, argv, io);
3626 
3627  return str;
3628 }
3629 
3630 /*
3631  * call-seq:
3632  * ios.lineno -> integer
3633  *
3634  * Returns the current line number in <em>ios</em>. The stream must be
3635  * opened for reading. #lineno counts the number of times #gets is called
3636  * rather than the number of newlines encountered. The two values will
3637  * differ if #gets is called with a separator other than newline.
3638  *
3639  * Methods that use <code>$/</code> like #each, #lines and #readline will
3640  * also increment #lineno.
3641  *
3642  * See also the <code>$.</code> variable.
3643  *
3644  * f = File.new("testfile")
3645  * f.lineno #=> 0
3646  * f.gets #=> "This is line one\n"
3647  * f.lineno #=> 1
3648  * f.gets #=> "This is line two\n"
3649  * f.lineno #=> 2
3650  */
3651 
3652 static VALUE
3653 rb_io_lineno(VALUE io)
3654 {
3655  rb_io_t *fptr;
3656 
3657  GetOpenFile(io, fptr);
3659  return INT2NUM(fptr->lineno);
3660 }
3661 
3662 /*
3663  * call-seq:
3664  * ios.lineno = integer -> integer
3665  *
3666  * Manually sets the current line number to the given value.
3667  * <code>$.</code> is updated only on the next read.
3668  *
3669  * f = File.new("testfile")
3670  * f.gets #=> "This is line one\n"
3671  * $. #=> 1
3672  * f.lineno = 1000
3673  * f.lineno #=> 1000
3674  * $. #=> 1 # lineno of last read
3675  * f.gets #=> "This is line two\n"
3676  * $. #=> 1001 # lineno of last read
3677  */
3678 
3679 static VALUE
3680 rb_io_set_lineno(VALUE io, VALUE lineno)
3681 {
3682  rb_io_t *fptr;
3683 
3684  GetOpenFile(io, fptr);
3686  fptr->lineno = NUM2INT(lineno);
3687  return lineno;
3688 }
3689 
3690 /*
3691  * call-seq:
3692  * ios.readline(sep=$/ [, getline_args]) -> string
3693  * ios.readline(limit [, getline_args]) -> string
3694  * ios.readline(sep, limit [, getline_args]) -> string
3695  *
3696  * Reads a line as with IO#gets, but raises an EOFError on end of file.
3697  */
3698 
3699 static VALUE
3700 rb_io_readline(int argc, VALUE *argv, VALUE io)
3701 {
3702  VALUE line = rb_io_gets_m(argc, argv, io);
3703 
3704  if (NIL_P(line)) {
3705  rb_eof_error();
3706  }
3707  return line;
3708 }
3709 
3710 static VALUE io_readlines(const struct getline_arg *arg, VALUE io);
3711 
3712 /*
3713  * call-seq:
3714  * ios.readlines(sep=$/ [, getline_args]) -> array
3715  * ios.readlines(limit [, getline_args]) -> array
3716  * ios.readlines(sep, limit [, getline_args]) -> array
3717  *
3718  * Reads all of the lines in <em>ios</em>, and returns them in
3719  * an array. Lines are separated by the optional <i>sep</i>. If
3720  * <i>sep</i> is +nil+, the rest of the stream is returned
3721  * as a single record.
3722  * If the first argument is an integer, or an
3723  * optional second argument is given, the returning string would not be
3724  * longer than the given value in bytes. The stream must be opened for
3725  * reading or an IOError will be raised.
3726  *
3727  * f = File.new("testfile")
3728  * f.readlines[0] #=> "This is line one\n"
3729  *
3730  * f = File.new("testfile", chomp: true)
3731  * f.readlines[0] #=> "This is line one"
3732  *
3733  * See IO.readlines for details about getline_args.
3734  */
3735 
3736 static VALUE
3737 rb_io_readlines(int argc, VALUE *argv, VALUE io)
3738 {
3739  struct getline_arg args;
3740 
3741  prepare_getline_args(argc, argv, &args, io);
3742  return io_readlines(&args, io);
3743 }
3744 
3745 static VALUE
3746 io_readlines(const struct getline_arg *arg, VALUE io)
3747 {
3748  VALUE line, ary;
3749 
3750  if (arg->limit == 0)
3751  rb_raise(rb_eArgError, "invalid limit: 0 for readlines");
3752  ary = rb_ary_new();
3753  while (!NIL_P(line = rb_io_getline_1(arg->rs, arg->limit, arg->chomp, io))) {
3754  rb_ary_push(ary, line);
3755  }
3756  return ary;
3757 }
3758 
3759 /*
3760  * call-seq:
3761  * ios.each(sep=$/ [, getline_args]) {|line| block } -> ios
3762  * ios.each(limit [, getline_args]) {|line| block } -> ios
3763  * ios.each(sep, limit [, getline_args]) {|line| block } -> ios
3764  * ios.each(...) -> an_enumerator
3765  *
3766  * ios.each_line(sep=$/ [, getline_args]) {|line| block } -> ios
3767  * ios.each_line(limit [, getline_args]) {|line| block } -> ios
3768  * ios.each_line(sep, limit [, getline_args]) {|line| block } -> ios
3769  * ios.each_line(...) -> an_enumerator
3770  *
3771  * Executes the block for every line in <em>ios</em>, where lines are
3772  * separated by <i>sep</i>. <em>ios</em> must be opened for
3773  * reading or an IOError will be raised.
3774  *
3775  * If no block is given, an enumerator is returned instead.
3776  *
3777  * f = File.new("testfile")
3778  * f.each {|line| puts "#{f.lineno}: #{line}" }
3779  *
3780  * <em>produces:</em>
3781  *
3782  * 1: This is line one
3783  * 2: This is line two
3784  * 3: This is line three
3785  * 4: And so on...
3786  *
3787  * See IO.readlines for details about getline_args.
3788  */
3789 
3790 static VALUE
3791 rb_io_each_line(int argc, VALUE *argv, VALUE io)
3792 {
3793  VALUE str;
3794  struct getline_arg args;
3795 
3797  prepare_getline_args(argc, argv, &args, io);
3798  if (args.limit == 0)
3799  rb_raise(rb_eArgError, "invalid limit: 0 for each_line");
3800  while (!NIL_P(str = rb_io_getline_1(args.rs, args.limit, args.chomp, io))) {
3801  rb_yield(str);
3802  }
3803  return io;
3804 }
3805 
3806 /*
3807  * This is a deprecated alias for #each_line.
3808  */
3809 
3810 static VALUE
3811 rb_io_lines(int argc, VALUE *argv, VALUE io)
3812 {
3813  rb_warn_deprecated("IO#lines", "#each_line");
3814  if (!rb_block_given_p())
3815  return rb_enumeratorize(io, ID2SYM(rb_intern("each_line")), argc, argv);
3816  return rb_io_each_line(argc, argv, io);
3817 }
3818 
3819 /*
3820  * call-seq:
3821  * ios.each_byte {|byte| block } -> ios
3822  * ios.each_byte -> an_enumerator
3823  *
3824  * Calls the given block once for each byte (0..255) in <em>ios</em>,
3825  * passing the byte as an argument. The stream must be opened for
3826  * reading or an IOError will be raised.
3827  *
3828  * If no block is given, an enumerator is returned instead.
3829  *
3830  * f = File.new("testfile")
3831  * checksum = 0
3832  * f.each_byte {|x| checksum ^= x } #=> #<File:testfile>
3833  * checksum #=> 12
3834  */
3835 
3836 static VALUE
3837 rb_io_each_byte(VALUE io)
3838 {
3839  rb_io_t *fptr;
3840 
3841  RETURN_ENUMERATOR(io, 0, 0);
3842  GetOpenFile(io, fptr);
3843 
3844  do {
3845  while (fptr->rbuf.len > 0) {
3846  char *p = fptr->rbuf.ptr + fptr->rbuf.off++;
3847  fptr->rbuf.len--;
3848  rb_yield(INT2FIX(*p & 0xff));
3849  errno = 0;
3850  }
3852  READ_CHECK(fptr);
3853  } while (io_fillbuf(fptr) >= 0);
3854  return io;
3855 }
3856 
3857 /*
3858  * This is a deprecated alias for #each_byte.
3859  */
3860 
3861 static VALUE
3862 rb_io_bytes(VALUE io)
3863 {
3864  rb_warn_deprecated("IO#bytes", "#each_byte");
3865  if (!rb_block_given_p())
3866  return rb_enumeratorize(io, ID2SYM(rb_intern("each_byte")), 0, 0);
3867  return rb_io_each_byte(io);
3868 }
3869 
3870 static VALUE
3871 io_getc(rb_io_t *fptr, rb_encoding *enc)
3872 {
3873  int r, n, cr = 0;
3874  VALUE str;
3875 
3876  if (NEED_READCONV(fptr)) {
3877  rb_encoding *read_enc = io_read_encoding(fptr);
3878 
3879  str = Qnil;
3880  SET_BINARY_MODE(fptr);
3881  make_readconv(fptr, 0);
3882 
3883  while (1) {
3884  if (fptr->cbuf.len) {
3885  r = rb_enc_precise_mbclen(fptr->cbuf.ptr+fptr->cbuf.off,
3886  fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
3887  read_enc);
3888  if (!MBCLEN_NEEDMORE_P(r))
3889  break;
3890  if (fptr->cbuf.len == fptr->cbuf.capa) {
3891  rb_raise(rb_eIOError, "too long character");
3892  }
3893  }
3894 
3895  if (more_char(fptr) == MORE_CHAR_FINISHED) {
3896  if (fptr->cbuf.len == 0) {
3897  clear_readconv(fptr);
3898  return Qnil;
3899  }
3900  /* return an unit of an incomplete character just before EOF */
3901  str = rb_enc_str_new(fptr->cbuf.ptr+fptr->cbuf.off, 1, read_enc);
3902  fptr->cbuf.off += 1;
3903  fptr->cbuf.len -= 1;
3904  if (fptr->cbuf.len == 0) clear_readconv(fptr);
3906  return str;
3907  }
3908  }
3909  if (MBCLEN_INVALID_P(r)) {
3910  r = rb_enc_mbclen(fptr->cbuf.ptr+fptr->cbuf.off,
3911  fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
3912  read_enc);
3913  io_shift_cbuf(fptr, r, &str);
3914  cr = ENC_CODERANGE_BROKEN;
3915  }
3916  else {
3917  io_shift_cbuf(fptr, MBCLEN_CHARFOUND_LEN(r), &str);
3918  cr = ENC_CODERANGE_VALID;
3919  if (MBCLEN_CHARFOUND_LEN(r) == 1 && rb_enc_asciicompat(read_enc) &&
3920  ISASCII(RSTRING_PTR(str)[0])) {
3921  cr = ENC_CODERANGE_7BIT;
3922  }
3923  }
3924  str = io_enc_str(str, fptr);
3925  ENC_CODERANGE_SET(str, cr);
3926  return str;
3927  }
3928 
3930  if (io_fillbuf(fptr) < 0) {
3931  return Qnil;
3932  }
3933  if (rb_enc_asciicompat(enc) && ISASCII(fptr->rbuf.ptr[fptr->rbuf.off])) {
3934  str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, 1);
3935  fptr->rbuf.off += 1;
3936  fptr->rbuf.len -= 1;
3937  cr = ENC_CODERANGE_7BIT;
3938  }
3939  else {
3940  r = rb_enc_precise_mbclen(fptr->rbuf.ptr+fptr->rbuf.off, fptr->rbuf.ptr+fptr->rbuf.off+fptr->rbuf.len, enc);
3941  if (MBCLEN_CHARFOUND_P(r) &&
3942  (n = MBCLEN_CHARFOUND_LEN(r)) <= fptr->rbuf.len) {
3943  str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, n);
3944  fptr->rbuf.off += n;
3945  fptr->rbuf.len -= n;
3946  cr = ENC_CODERANGE_VALID;
3947  }
3948  else if (MBCLEN_NEEDMORE_P(r)) {
3949  str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, fptr->rbuf.len);
3950  fptr->rbuf.len = 0;
3951  getc_needmore:
3952  if (io_fillbuf(fptr) != -1) {
3953  rb_str_cat(str, fptr->rbuf.ptr+fptr->rbuf.off, 1);
3954  fptr->rbuf.off++;
3955  fptr->rbuf.len--;
3957  if (MBCLEN_NEEDMORE_P(r)) {
3958  goto getc_needmore;
3959  }
3960  else if (MBCLEN_CHARFOUND_P(r)) {
3961  cr = ENC_CODERANGE_VALID;
3962  }
3963  }
3964  }
3965  else {
3966  str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, 1);
3967  fptr->rbuf.off++;
3968  fptr->rbuf.len--;
3969  }
3970  }
3971  if (!cr) cr = ENC_CODERANGE_BROKEN;
3972  str = io_enc_str(str, fptr);
3973  ENC_CODERANGE_SET(str, cr);
3974  return str;
3975 }
3976 
3977 /*
3978  * call-seq:
3979  * ios.each_char {|c| block } -> ios
3980  * ios.each_char -> an_enumerator
3981  *
3982  * Calls the given block once for each character in <em>ios</em>,
3983  * passing the character as an argument. The stream must be opened for
3984  * reading or an IOError will be raised.
3985  *
3986  * If no block is given, an enumerator is returned instead.
3987  *
3988  * f = File.new("testfile")
3989  * f.each_char {|c| print c, ' ' } #=> #<File:testfile>
3990  */
3991 
3992 static VALUE
3993 rb_io_each_char(VALUE io)
3994 {
3995  rb_io_t *fptr;
3996  rb_encoding *enc;
3997  VALUE c;
3998 
3999  RETURN_ENUMERATOR(io, 0, 0);
4000  GetOpenFile(io, fptr);
4002 
4003  enc = io_input_encoding(fptr);
4004  READ_CHECK(fptr);
4005  while (!NIL_P(c = io_getc(fptr, enc))) {
4006  rb_yield(c);
4007  }
4008  return io;
4009 }
4010 
4011 /*
4012  * This is a deprecated alias for #each_char.
4013  */
4014 
4015 static VALUE
4016 rb_io_chars(VALUE io)
4017 {
4018  rb_warn_deprecated("IO#chars", "#each_char");
4019  if (!rb_block_given_p())
4020  return rb_enumeratorize(io, ID2SYM(rb_intern("each_char")), 0, 0);
4021  return rb_io_each_char(io);
4022 }
4023 
4024 
4025 /*
4026  * call-seq:
4027  * ios.each_codepoint {|c| block } -> ios
4028  * ios.codepoints {|c| block } -> ios
4029  * ios.each_codepoint -> an_enumerator
4030  * ios.codepoints -> an_enumerator
4031  *
4032  * Passes the Integer ordinal of each character in <i>ios</i>,
4033  * passing the codepoint as an argument. The stream must be opened for
4034  * reading or an IOError will be raised.
4035  *
4036  * If no block is given, an enumerator is returned instead.
4037  *
4038  */
4039 
4040 static VALUE
4041 rb_io_each_codepoint(VALUE io)
4042 {
4043  rb_io_t *fptr;
4044  rb_encoding *enc;
4045  unsigned int c;
4046  int r, n;
4047 
4048  RETURN_ENUMERATOR(io, 0, 0);
4049  GetOpenFile(io, fptr);
4051 
4052  READ_CHECK(fptr);
4053  if (NEED_READCONV(fptr)) {
4054  SET_BINARY_MODE(fptr);
4055  r = 1; /* no invalid char yet */
4056  for (;;) {
4057  make_readconv(fptr, 0);
4058  for (;;) {
4059  if (fptr->cbuf.len) {
4060  if (fptr->encs.enc)
4061  r = rb_enc_precise_mbclen(fptr->cbuf.ptr+fptr->cbuf.off,
4062  fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
4063  fptr->encs.enc);
4064  else
4066  if (!MBCLEN_NEEDMORE_P(r))
4067  break;
4068  if (fptr->cbuf.len == fptr->cbuf.capa) {
4069  rb_raise(rb_eIOError, "too long character");
4070  }
4071  }
4072  if (more_char(fptr) == MORE_CHAR_FINISHED) {
4073  clear_readconv(fptr);
4074  if (!MBCLEN_CHARFOUND_P(r)) {
4075  enc = fptr->encs.enc;
4076  goto invalid;
4077  }
4078  return io;
4079  }
4080  }
4081  if (MBCLEN_INVALID_P(r)) {
4082  enc = fptr->encs.enc;
4083  goto invalid;
4084  }
4085  n = MBCLEN_CHARFOUND_LEN(r);
4086  if (fptr->encs.enc) {
4087  c = rb_enc_codepoint(fptr->cbuf.ptr+fptr->cbuf.off,
4088  fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
4089  fptr->encs.enc);
4090  }
4091  else {
4092  c = (unsigned char)fptr->cbuf.ptr[fptr->cbuf.off];
4093  }
4094  fptr->cbuf.off += n;
4095  fptr->cbuf.len -= n;
4096  rb_yield(UINT2NUM(c));
4097  }
4098  }
4100  enc = io_input_encoding(fptr);
4101  while (io_fillbuf(fptr) >= 0) {
4102  r = rb_enc_precise_mbclen(fptr->rbuf.ptr+fptr->rbuf.off,
4103  fptr->rbuf.ptr+fptr->rbuf.off+fptr->rbuf.len, enc);
4104  if (MBCLEN_CHARFOUND_P(r) &&
4105  (n = MBCLEN_CHARFOUND_LEN(r)) <= fptr->rbuf.len) {
4106  c = rb_enc_codepoint(fptr->rbuf.ptr+fptr->rbuf.off,
4107  fptr->rbuf.ptr+fptr->rbuf.off+fptr->rbuf.len, enc);
4108  fptr->rbuf.off += n;
4109  fptr->rbuf.len -= n;
4110  rb_yield(UINT2NUM(c));
4111  }
4112  else if (MBCLEN_INVALID_P(r)) {
4113  invalid:
4114  rb_raise(rb_eArgError, "invalid byte sequence in %s", rb_enc_name(enc));
4115  }
4116  else if (MBCLEN_NEEDMORE_P(r)) {
4117  char cbuf[8], *p = cbuf;
4118  int more = MBCLEN_NEEDMORE_LEN(r);
4119  if (more > numberof(cbuf)) goto invalid;
4120  more += n = fptr->rbuf.len;
4121  if (more > numberof(cbuf)) goto invalid;
4122  while ((n = (int)read_buffered_data(p, more, fptr)) > 0 &&
4123  (p += n, (more -= n) > 0)) {
4124  if (io_fillbuf(fptr) < 0) goto invalid;
4125  if ((n = fptr->rbuf.len) > more) n = more;
4126  }
4127  r = rb_enc_precise_mbclen(cbuf, p, enc);
4128  if (!MBCLEN_CHARFOUND_P(r)) goto invalid;
4129  c = rb_enc_codepoint(cbuf, p, enc);
4130  rb_yield(UINT2NUM(c));
4131  }
4132  else {
4133  continue;
4134  }
4135  }
4136  return io;
4137 }
4138 
4139 /*
4140  * This is a deprecated alias for #each_codepoint.
4141  */
4142 
4143 static VALUE
4144 rb_io_codepoints(VALUE io)
4145 {
4146  rb_warn_deprecated("IO#codepoints", "#each_codepoint");
4147  if (!rb_block_given_p())
4148  return rb_enumeratorize(io, ID2SYM(rb_intern("each_codepoint")), 0, 0);
4149  return rb_io_each_codepoint(io);
4150 }
4151 
4152 
4153 /*
4154  * call-seq:
4155  * ios.getc -> string or nil
4156  *
4157  * Reads a one-character string from <em>ios</em>. Returns
4158  * +nil+ if called at end of file.
4159  *
4160  * f = File.new("testfile")
4161  * f.getc #=> "h"
4162  * f.getc #=> "e"
4163  */
4164 
4165 static VALUE
4166 rb_io_getc(VALUE io)
4167 {
4168  rb_io_t *fptr;
4169  rb_encoding *enc;
4170 
4171  GetOpenFile(io, fptr);
4173 
4174  enc = io_input_encoding(fptr);
4175  READ_CHECK(fptr);
4176  return io_getc(fptr, enc);
4177 }
4178 
4179 /*
4180  * call-seq:
4181  * ios.readchar -> string
4182  *
4183  * Reads a one-character string from <em>ios</em>. Raises an
4184  * EOFError on end of file.
4185  *
4186  * f = File.new("testfile")
4187  * f.readchar #=> "h"
4188  * f.readchar #=> "e"
4189  */
4190 
4191 static VALUE
4192 rb_io_readchar(VALUE io)
4193 {
4194  VALUE c = rb_io_getc(io);
4195 
4196  if (NIL_P(c)) {
4197  rb_eof_error();
4198  }
4199  return c;
4200 }
4201 
4202 /*
4203  * call-seq:
4204  * ios.getbyte -> integer or nil
4205  *
4206  * Gets the next 8-bit byte (0..255) from <em>ios</em>. Returns
4207  * +nil+ if called at end of file.
4208  *
4209  * f = File.new("testfile")
4210  * f.getbyte #=> 84
4211  * f.getbyte #=> 104
4212  */
4213 
4214 VALUE
4216 {
4217  rb_io_t *fptr;
4218  int c;
4219 
4220  GetOpenFile(io, fptr);
4222  READ_CHECK(fptr);
4223  if (fptr->fd == 0 && (fptr->mode & FMODE_TTY) && RB_TYPE_P(rb_stdout, T_FILE)) {
4224  rb_io_t *ofp;
4225  GetOpenFile(rb_stdout, ofp);
4226  if (ofp->mode & FMODE_TTY) {
4228  }
4229  }
4230  if (io_fillbuf(fptr) < 0) {
4231  return Qnil;
4232  }
4233  fptr->rbuf.off++;
4234  fptr->rbuf.len--;
4235  c = (unsigned char)fptr->rbuf.ptr[fptr->rbuf.off-1];
4236  return INT2FIX(c & 0xff);
4237 }
4238 
4239 /*
4240  * call-seq:
4241  * ios.readbyte -> integer
4242  *
4243  * Reads a byte as with IO#getbyte, but raises an EOFError on end of
4244  * file.
4245  */
4246 
4247 static VALUE
4248 rb_io_readbyte(VALUE io)
4249 {
4250  VALUE c = rb_io_getbyte(io);
4251 
4252  if (NIL_P(c)) {
4253  rb_eof_error();
4254  }
4255  return c;
4256 }
4257 
4258 /*
4259  * call-seq:
4260  * ios.ungetbyte(string) -> nil
4261  * ios.ungetbyte(integer) -> nil
4262  *
4263  * Pushes back bytes (passed as a parameter) onto <em>ios</em>,
4264  * such that a subsequent buffered read will return it. Only one byte
4265  * may be pushed back before a subsequent read operation (that is,
4266  * you will be able to read only the last of several bytes that have been pushed
4267  * back). Has no effect with unbuffered reads (such as IO#sysread).
4268  *
4269  * f = File.new("testfile") #=> #<File:testfile>
4270  * b = f.getbyte #=> 0x38
4271  * f.ungetbyte(b) #=> nil
4272  * f.getbyte #=> 0x38
4273  */
4274 
4275 VALUE
4277 {
4278  rb_io_t *fptr;
4279 
4280  GetOpenFile(io, fptr);
4282  switch (TYPE(b)) {
4283  case T_NIL:
4284  return Qnil;
4285  case T_FIXNUM:
4286  case T_BIGNUM: ;
4287  VALUE v = rb_int_modulo(b, INT2FIX(256));
4288  unsigned char c = NUM2INT(v) & 0xFF;
4289  b = rb_str_new((const char *)&c, 1);
4290  break;
4291  default:
4292  SafeStringValue(b);
4293  }
4294  io_ungetbyte(b, fptr);
4295  return Qnil;
4296 }
4297 
4298 /*
4299  * call-seq:
4300  * ios.ungetc(string) -> nil
4301  *
4302  * Pushes back one character (passed as a parameter) onto <em>ios</em>,
4303  * such that a subsequent buffered character read will return it. Only one character
4304  * may be pushed back before a subsequent read operation (that is,
4305  * you will be able to read only the last of several characters that have been pushed
4306  * back). Has no effect with unbuffered reads (such as IO#sysread).
4307  *
4308  * f = File.new("testfile") #=> #<File:testfile>
4309  * c = f.getc #=> "8"
4310  * f.ungetc(c) #=> nil
4311  * f.getc #=> "8"
4312  */
4313 
4314 VALUE
4316 {
4317  rb_io_t *fptr;
4318  long len;
4319 
4320  GetOpenFile(io, fptr);
4322  if (NIL_P(c)) return Qnil;
4323  if (FIXNUM_P(c)) {
4324  c = rb_enc_uint_chr(FIX2UINT(c), io_read_encoding(fptr));
4325  }
4326  else if (RB_TYPE_P(c, T_BIGNUM)) {
4327  c = rb_enc_uint_chr(NUM2UINT(c), io_read_encoding(fptr));
4328  }
4329  else {
4330  SafeStringValue(c);
4331  }
4332  if (NEED_READCONV(fptr)) {
4333  SET_BINARY_MODE(fptr);
4334  len = RSTRING_LEN(c);
4335 #if SIZEOF_LONG > SIZEOF_INT
4336  if (len > INT_MAX)
4337  rb_raise(rb_eIOError, "ungetc failed");
4338 #endif
4339  make_readconv(fptr, (int)len);
4340  if (fptr->cbuf.capa - fptr->cbuf.len < len)
4341  rb_raise(rb_eIOError, "ungetc failed");
4342  if (fptr->cbuf.off < len) {
4343  MEMMOVE(fptr->cbuf.ptr+fptr->cbuf.capa-fptr->cbuf.len,
4344  fptr->cbuf.ptr+fptr->cbuf.off,
4345  char, fptr->cbuf.len);
4346  fptr->cbuf.off = fptr->cbuf.capa-fptr->cbuf.len;
4347  }
4348  fptr->cbuf.off -= (int)len;
4349  fptr->cbuf.len += (int)len;
4350  MEMMOVE(fptr->cbuf.ptr+fptr->cbuf.off, RSTRING_PTR(c), char, len);
4351  }
4352  else {
4354  io_ungetbyte(c, fptr);
4355  }
4356  return Qnil;
4357 }
4358 
4359 /*
4360  * call-seq:
4361  * ios.isatty -> true or false
4362  * ios.tty? -> true or false
4363  *
4364  * Returns <code>true</code> if <em>ios</em> is associated with a
4365  * terminal device (tty), <code>false</code> otherwise.
4366  *
4367  * File.new("testfile").isatty #=> false
4368  * File.new("/dev/tty").isatty #=> true
4369  */
4370 
4371 static VALUE
4372 rb_io_isatty(VALUE io)
4373 {
4374  rb_io_t *fptr;
4375 
4376  GetOpenFile(io, fptr);
4377  if (isatty(fptr->fd) == 0)
4378  return Qfalse;
4379  return Qtrue;
4380 }
4381 
4382 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
4383 /*
4384  * call-seq:
4385  * ios.close_on_exec? -> true or false
4386  *
4387  * Returns <code>true</code> if <em>ios</em> will be closed on exec.
4388  *
4389  * f = open("/dev/null")
4390  * f.close_on_exec? #=> false
4391  * f.close_on_exec = true
4392  * f.close_on_exec? #=> true
4393  * f.close_on_exec = false
4394  * f.close_on_exec? #=> false
4395  */
4396 
4397 static VALUE
4399 {
4400  rb_io_t *fptr;
4401  VALUE write_io;
4402  int fd, ret;
4403 
4404  write_io = GetWriteIO(io);
4405  if (io != write_io) {
4406  GetOpenFile(write_io, fptr);
4407  if (fptr && 0 <= (fd = fptr->fd)) {
4408  if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
4409  if (!(ret & FD_CLOEXEC)) return Qfalse;
4410  }
4411  }
4412 
4413  GetOpenFile(io, fptr);
4414  if (fptr && 0 <= (fd = fptr->fd)) {
4415  if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
4416  if (!(ret & FD_CLOEXEC)) return Qfalse;
4417  }
4418  return Qtrue;
4419 }
4420 #else
4421 #define rb_io_close_on_exec_p rb_f_notimplement
4422 #endif
4423 
4424 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
4425 /*
4426  * call-seq:
4427  * ios.close_on_exec = bool -> true or false
4428  *
4429  * Sets a close-on-exec flag.
4430  *
4431  * f = open("/dev/null")
4432  * f.close_on_exec = true
4433  * system("cat", "/proc/self/fd/#{f.fileno}") # cat: /proc/self/fd/3: No such file or directory
4434  * f.closed? #=> false
4435  *
4436  * Ruby sets close-on-exec flags of all file descriptors by default
4437  * since Ruby 2.0.0.
4438  * So you don't need to set by yourself.
4439  * Also, unsetting a close-on-exec flag can cause file descriptor leak
4440  * if another thread use fork() and exec() (via system() method for example).
4441  * If you really needs file descriptor inheritance to child process,
4442  * use spawn()'s argument such as fd=>fd.
4443  */
4444 
4445 static VALUE
4447 {
4448  int flag = RTEST(arg) ? FD_CLOEXEC : 0;
4449  rb_io_t *fptr;
4450  VALUE write_io;
4451  int fd, ret;
4452 
4453  write_io = GetWriteIO(io);
4454  if (io != write_io) {
4455  GetOpenFile(write_io, fptr);
4456  if (fptr && 0 <= (fd = fptr->fd)) {
4457  if ((ret = fcntl(fptr->fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
4458  if ((ret & FD_CLOEXEC) != flag) {
4459  ret = (ret & ~FD_CLOEXEC) | flag;
4460  ret = fcntl(fd, F_SETFD, ret);
4461  if (ret != 0) rb_sys_fail_path(fptr->pathv);
4462  }
4463  }
4464 
4465  }
4466 
4467  GetOpenFile(io, fptr);
4468  if (fptr && 0 <= (fd = fptr->fd)) {
4469  if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
4470  if ((ret & FD_CLOEXEC) != flag) {
4471  ret = (ret & ~FD_CLOEXEC) | flag;
4472  ret = fcntl(fd, F_SETFD, ret);
4473  if (ret != 0) rb_sys_fail_path(fptr->pathv);
4474  }
4475  }
4476  return Qnil;
4477 }
4478 #else
4479 #define rb_io_set_close_on_exec rb_f_notimplement
4480 #endif
4481 
4482 #define FMODE_PREP (1<<16)
4483 #define IS_PREP_STDIO(f) ((f)->mode & FMODE_PREP)
4484 #define PREP_STDIO_NAME(f) (RSTRING_PTR((f)->pathv))
4485 
4486 static VALUE
4487 finish_writeconv(rb_io_t *fptr, int noalloc)
4488 {
4489  unsigned char *ds, *dp, *de;
4490  rb_econv_result_t res;
4491 
4492  if (!fptr->wbuf.ptr) {
4493  unsigned char buf[1024];
4494  long r;
4495 
4497  while (res == econv_destination_buffer_full) {
4498  ds = dp = buf;
4499  de = buf + sizeof(buf);
4500  res = rb_econv_convert(fptr->writeconv, NULL, NULL, &dp, de, 0);
4501  while (dp-ds) {
4502  retry:
4503  if (fptr->write_lock && rb_mutex_owned_p(fptr->write_lock))
4504  r = rb_write_internal2(fptr->fd, ds, dp-ds);
4505  else
4506  r = rb_write_internal(fptr->fd, ds, dp-ds);
4507  if (r == dp-ds)
4508  break;
4509  if (0 <= r) {
4510  ds += r;
4511  }
4512  if (rb_io_wait_writable(fptr->fd)) {
4513  if (fptr->fd < 0)
4514  return noalloc ? Qtrue : rb_exc_new3(rb_eIOError, rb_str_new_cstr(closed_stream));
4515  goto retry;
4516  }
4517  return noalloc ? Qtrue : INT2NUM(errno);
4518  }
4519  if (res == econv_invalid_byte_sequence ||
4520  res == econv_incomplete_input ||
4521  res == econv_undefined_conversion) {
4522  return noalloc ? Qtrue : rb_econv_make_exception(fptr->writeconv);
4523  }
4524  }
4525 
4526  return Qnil;
4527  }
4528 
4530  while (res == econv_destination_buffer_full) {
4531  if (fptr->wbuf.len == fptr->wbuf.capa) {
4532  if (io_fflush(fptr) < 0)
4533  return noalloc ? Qtrue : INT2NUM(errno);
4534  }
4535 
4536  ds = dp = (unsigned char *)fptr->wbuf.ptr + fptr->wbuf.off + fptr->wbuf.len;
4537  de = (unsigned char *)fptr->wbuf.ptr + fptr->wbuf.capa;
4538  res = rb_econv_convert(fptr->writeconv, NULL, NULL, &dp, de, 0);
4539  fptr->wbuf.len += (int)(dp - ds);
4540  if (res == econv_invalid_byte_sequence ||
4541  res == econv_incomplete_input ||
4542  res == econv_undefined_conversion) {
4543  return noalloc ? Qtrue : rb_econv_make_exception(fptr->writeconv);
4544  }
4545  }
4546  return Qnil;
4547 }
4548 
4551  int noalloc;
4552 };
4553 
4554 static VALUE
4555 finish_writeconv_sync(VALUE arg)
4556 {
4557  struct finish_writeconv_arg *p = (struct finish_writeconv_arg *)arg;
4558  return finish_writeconv(p->fptr, p->noalloc);
4559 }
4560 
4561 static void*
4562 nogvl_close(void *ptr)
4563 {
4564  int *fd = ptr;
4565 
4566  return (void*)(intptr_t)close(*fd);
4567 }
4568 
4569 static int
4570 maygvl_close(int fd, int keepgvl)
4571 {
4572  if (keepgvl)
4573  return close(fd);
4574 
4575  /*
4576  * close() may block for certain file types (NFS, SO_LINGER sockets,
4577  * inotify), so let other threads run.
4578  */
4579  return (int)(intptr_t)rb_thread_call_without_gvl(nogvl_close, &fd, RUBY_UBF_IO, 0);
4580 }
4581 
4582 static void*
4583 nogvl_fclose(void *ptr)
4584 {
4585  FILE *file = ptr;
4586 
4587  return (void*)(intptr_t)fclose(file);
4588 }
4589 
4590 static int
4591 maygvl_fclose(FILE *file, int keepgvl)
4592 {
4593  if (keepgvl)
4594  return fclose(file);
4595 
4596  return (int)(intptr_t)rb_thread_call_without_gvl(nogvl_fclose, file, RUBY_UBF_IO, 0);
4597 }
4598 
4599 static void free_io_buffer(rb_io_buffer_t *buf);
4600 static void clear_codeconv(rb_io_t *fptr);
4601 
4602 static void
4603 fptr_finalize_flush(rb_io_t *fptr, int noraise, int keepgvl,
4604  struct list_head *busy)
4605 {
4606  VALUE err = Qnil;
4607  int fd = fptr->fd;
4608  FILE *stdio_file = fptr->stdio_file;
4609  int mode = fptr->mode;
4610 
4611  if (fptr->writeconv) {
4612  if (fptr->write_lock && !noraise) {
4613  struct finish_writeconv_arg arg;
4614  arg.fptr = fptr;
4615  arg.noalloc = noraise;
4616  err = rb_mutex_synchronize(fptr->write_lock, finish_writeconv_sync, (VALUE)&arg);
4617  }
4618  else {
4619  err = finish_writeconv(fptr, noraise);
4620  }
4621  }
4622  if (fptr->wbuf.len) {
4623  if (noraise) {
4624  io_flush_buffer_sync(fptr);
4625  }
4626  else {
4627  if (io_fflush(fptr) < 0 && NIL_P(err))
4628  err = INT2NUM(errno);
4629  }
4630  }
4631 
4632  fptr->fd = -1;
4633  fptr->stdio_file = 0;
4635 
4636  /*
4637  * ensure waiting_fd users do not hit EBADF, wait for them
4638  * to exit before we call close().
4639  */
4640  if (busy) {
4641  do rb_thread_schedule(); while (!list_empty(busy));
4642  }
4643 
4644  if (IS_PREP_STDIO(fptr) || fd <= 2) {
4645  /* need to keep FILE objects of stdin, stdout and stderr */
4646  }
4647  else if (stdio_file) {
4648  /* stdio_file is deallocated anyway
4649  * even if fclose failed. */
4650  if ((maygvl_fclose(stdio_file, noraise) < 0) && NIL_P(err))
4651  if (!noraise) err = INT2NUM(errno);
4652  }
4653  else if (0 <= fd) {
4654  /* fptr->fd may be closed even if close fails.
4655  * POSIX doesn't specify it.
4656  * We assumes it is closed. */
4657 
4658 
4659  keepgvl |= !(mode & FMODE_WRITABLE);
4660  keepgvl |= noraise;
4661  if ((maygvl_close(fd, keepgvl) < 0) && NIL_P(err))
4662  if (!noraise) err = INT2NUM(errno);
4663  }
4664 
4665  if (!NIL_P(err) && !noraise) {
4666  if (RB_INTEGER_TYPE_P(err))
4668  else
4669  rb_exc_raise(err);
4670  }
4671 }
4672 
4673 static void
4674 fptr_finalize(rb_io_t *fptr, int noraise)
4675 {
4676  fptr_finalize_flush(fptr, noraise, FALSE, 0);
4677  free_io_buffer(&fptr->rbuf);
4678  free_io_buffer(&fptr->wbuf);
4679  clear_codeconv(fptr);
4680 }
4681 
4682 static void
4683 rb_io_fptr_cleanup(rb_io_t *fptr, int noraise)
4684 {
4685  if (fptr->finalize) {
4686  (*fptr->finalize)(fptr, noraise);
4687  }
4688  else {
4689  fptr_finalize(fptr, noraise);
4690  }
4691 }
4692 
4693 static void
4694 free_io_buffer(rb_io_buffer_t *buf)
4695 {
4696  if (buf->ptr) {
4697  ruby_sized_xfree(buf->ptr, (size_t)buf->capa);
4698  buf->ptr = NULL;
4699  }
4700 }
4701 
4702 static void
4703 clear_readconv(rb_io_t *fptr)
4704 {
4705  if (fptr->readconv) {
4707  fptr->readconv = NULL;
4708  }
4709  free_io_buffer(&fptr->cbuf);
4710 }
4711 
4712 static void
4713 clear_writeconv(rb_io_t *fptr)
4714 {
4715  if (fptr->writeconv) {
4717  fptr->writeconv = NULL;
4718  }
4720 }
4721 
4722 static void
4723 clear_codeconv(rb_io_t *fptr)
4724 {
4725  clear_readconv(fptr);
4726  clear_writeconv(fptr);
4727 }
4728 
4729 void
4731 {
4732  rb_io_t *fptr = ptr;
4733 
4734  if (!ptr) return;
4735  fptr->pathv = Qnil;
4736  if (0 <= fptr->fd)
4737  rb_io_fptr_cleanup(fptr, TRUE);
4738  fptr->write_lock = 0;
4739  free_io_buffer(&fptr->rbuf);
4740  free_io_buffer(&fptr->wbuf);
4741  clear_codeconv(fptr);
4742  free(fptr);
4743 }
4744 
4745 #undef rb_io_fptr_finalize
4746 int
4748 {
4749  if (!fptr) {
4750  return 0;
4751  }
4752  else {
4754  return 1;
4755  }
4756 }
4757 #define rb_io_fptr_finalize(fptr) rb_io_fptr_finalize_internal(fptr)
4758 
4759 RUBY_FUNC_EXPORTED size_t
4761 {
4762  size_t size = sizeof(rb_io_t);
4763  size += fptr->rbuf.capa;
4764  size += fptr->wbuf.capa;
4765  size += fptr->cbuf.capa;
4768  return size;
4769 }
4770 
4771 #ifdef _WIN32
4772 /* keep GVL while closing to prevent crash on Windows */
4773 # define KEEPGVL TRUE
4774 #else
4775 # define KEEPGVL FALSE
4776 #endif
4777 
4778 int rb_notify_fd_close(int fd, struct list_head *);
4779 static rb_io_t *
4780 io_close_fptr(VALUE io)
4781 {
4782  rb_io_t *fptr;
4783  VALUE write_io;
4784  rb_io_t *write_fptr;
4785  struct list_head busy;
4786 
4787  list_head_init(&busy);
4788  write_io = GetWriteIO(io);
4789  if (io != write_io) {
4790  write_fptr = RFILE(write_io)->fptr;
4791  if (write_fptr && 0 <= write_fptr->fd) {
4792  rb_io_fptr_cleanup(write_fptr, TRUE);
4793  }
4794  }
4795 
4796  fptr = RFILE(io)->fptr;
4797  if (!fptr) return 0;
4798  if (fptr->fd < 0) return 0;
4799 
4800  if (rb_notify_fd_close(fptr->fd, &busy)) {
4801  /* calls close(fptr->fd): */
4802  fptr_finalize_flush(fptr, FALSE, KEEPGVL, &busy);
4803  }
4804  rb_io_fptr_cleanup(fptr, FALSE);
4805  return fptr;
4806 }
4807 
4808 static void
4809 fptr_waitpid(rb_io_t *fptr, int nohang)
4810 {
4811  int status;
4812  if (fptr->pid) {
4814  rb_waitpid(fptr->pid, &status, nohang ? WNOHANG : 0);
4815  fptr->pid = 0;
4816  }
4817 }
4818 
4819 VALUE
4821 {
4822  rb_io_t *fptr = io_close_fptr(io);
4823  if (fptr) fptr_waitpid(fptr, 0);
4824  return Qnil;
4825 }
4826 
4827 /*
4828  * call-seq:
4829  * ios.close -> nil
4830  *
4831  * Closes <em>ios</em> and flushes any pending writes to the operating
4832  * system. The stream is unavailable for any further data operations;
4833  * an IOError is raised if such an attempt is made. I/O streams are
4834  * automatically closed when they are claimed by the garbage collector.
4835  *
4836  * If <em>ios</em> is opened by IO.popen, #close sets
4837  * <code>$?</code>.
4838  *
4839  * Calling this method on closed IO object is just ignored since Ruby 2.3.
4840  */
4841 
4842 static VALUE
4843 rb_io_close_m(VALUE io)
4844 {
4845  rb_io_t *fptr = rb_io_get_fptr(io);
4846  if (fptr->fd < 0) {
4847  return Qnil;
4848  }
4849  rb_io_close(io);
4850  return Qnil;
4851 }
4852 
4853 static VALUE
4854 io_call_close(VALUE io)
4855 {
4856  rb_check_funcall(io, rb_intern("close"), 0, 0);
4857  return io;
4858 }
4859 
4860 static VALUE
4861 ignore_closed_stream(VALUE io, VALUE exc)
4862 {
4863  enum {mesg_len = sizeof(closed_stream)-1};
4864  VALUE mesg = rb_attr_get(exc, idMesg);
4865  if (!RB_TYPE_P(mesg, T_STRING) ||
4866  RSTRING_LEN(mesg) != mesg_len ||
4867  memcmp(RSTRING_PTR(mesg), closed_stream, mesg_len)) {
4868  rb_exc_raise(exc);
4869  }
4870  return io;
4871 }
4872 
4873 static VALUE
4874 io_close(VALUE io)
4875 {
4876  VALUE closed = rb_check_funcall(io, rb_intern("closed?"), 0, 0);
4877  if (closed != Qundef && RTEST(closed)) return io;
4878  rb_rescue2(io_call_close, io, ignore_closed_stream, io,
4879  rb_eIOError, (VALUE)0);
4880  return io;
4881 }
4882 
4883 /*
4884  * call-seq:
4885  * ios.closed? -> true or false
4886  *
4887  * Returns <code>true</code> if <em>ios</em> is completely closed (for
4888  * duplex streams, both reader and writer), <code>false</code>
4889  * otherwise.
4890  *
4891  * f = File.new("testfile")
4892  * f.close #=> nil
4893  * f.closed? #=> true
4894  * f = IO.popen("/bin/sh","r+")
4895  * f.close_write #=> nil
4896  * f.closed? #=> false
4897  * f.close_read #=> nil
4898  * f.closed? #=> true
4899  */
4900 
4901 
4902 static VALUE
4903 rb_io_closed(VALUE io)
4904 {
4905  rb_io_t *fptr;
4906  VALUE write_io;
4907  rb_io_t *write_fptr;
4908 
4909  write_io = GetWriteIO(io);
4910  if (io != write_io) {
4911  write_fptr = RFILE(write_io)->fptr;
4912  if (write_fptr && 0 <= write_fptr->fd) {
4913  return Qfalse;
4914  }
4915  }
4916 
4917  fptr = rb_io_get_fptr(io);
4918  return 0 <= fptr->fd ? Qfalse : Qtrue;
4919 }
4920 
4921 /*
4922  * call-seq:
4923  * ios.close_read -> nil
4924  *
4925  * Closes the read end of a duplex I/O stream (i.e., one that contains
4926  * both a read and a write stream, such as a pipe). Will raise an
4927  * IOError if the stream is not duplexed.
4928  *
4929  * f = IO.popen("/bin/sh","r+")
4930  * f.close_read
4931  * f.readlines
4932  *
4933  * <em>produces:</em>
4934  *
4935  * prog.rb:3:in `readlines': not opened for reading (IOError)
4936  * from prog.rb:3
4937  *
4938  * Calling this method on closed IO object is just ignored since Ruby 2.3.
4939  */
4940 
4941 static VALUE
4942 rb_io_close_read(VALUE io)
4943 {
4944  rb_io_t *fptr;
4945  VALUE write_io;
4946 
4947  fptr = rb_io_get_fptr(rb_io_taint_check(io));
4948  if (fptr->fd < 0) return Qnil;
4949  if (is_socket(fptr->fd, fptr->pathv)) {
4950 #ifndef SHUT_RD
4951 # define SHUT_RD 0
4952 #endif
4953  if (shutdown(fptr->fd, SHUT_RD) < 0)
4954  rb_sys_fail_path(fptr->pathv);
4955  fptr->mode &= ~FMODE_READABLE;
4956  if (!(fptr->mode & FMODE_WRITABLE))
4957  return rb_io_close(io);
4958  return Qnil;
4959  }
4960 
4961  write_io = GetWriteIO(io);
4962  if (io != write_io) {
4963  rb_io_t *wfptr;
4964  wfptr = rb_io_get_fptr(rb_io_taint_check(write_io));
4965  wfptr->pid = fptr->pid;
4966  fptr->pid = 0;
4967  RFILE(io)->fptr = wfptr;
4968  /* bind to write_io temporarily to get rid of memory/fd leak */
4969  fptr->tied_io_for_writing = 0;
4970  RFILE(write_io)->fptr = fptr;
4971  rb_io_fptr_cleanup(fptr, FALSE);
4972  /* should not finalize fptr because another thread may be reading it */
4973  return Qnil;
4974  }
4975 
4976  if ((fptr->mode & (FMODE_DUPLEX|FMODE_WRITABLE)) == FMODE_WRITABLE) {
4977  rb_raise(rb_eIOError, "closing non-duplex IO for reading");
4978  }
4979  return rb_io_close(io);
4980 }
4981 
4982 /*
4983  * call-seq:
4984  * ios.close_write -> nil
4985  *
4986  * Closes the write end of a duplex I/O stream (i.e., one that contains
4987  * both a read and a write stream, such as a pipe). Will raise an
4988  * IOError if the stream is not duplexed.
4989  *
4990  * f = IO.popen("/bin/sh","r+")
4991  * f.close_write
4992  * f.print "nowhere"
4993  *
4994  * <em>produces:</em>
4995  *
4996  * prog.rb:3:in `write': not opened for writing (IOError)
4997  * from prog.rb:3:in `print'
4998  * from prog.rb:3
4999  *
5000  * Calling this method on closed IO object is just ignored since Ruby 2.3.
5001  */
5002 
5003 static VALUE
5004 rb_io_close_write(VALUE io)
5005 {
5006  rb_io_t *fptr;
5007  VALUE write_io;
5008 
5009  write_io = GetWriteIO(io);
5010  fptr = rb_io_get_fptr(rb_io_taint_check(write_io));
5011  if (fptr->fd < 0) return Qnil;
5012  if (is_socket(fptr->fd, fptr->pathv)) {
5013 #ifndef SHUT_WR
5014 # define SHUT_WR 1
5015 #endif
5016  if (shutdown(fptr->fd, SHUT_WR) < 0)
5017  rb_sys_fail_path(fptr->pathv);
5018  fptr->mode &= ~FMODE_WRITABLE;
5019  if (!(fptr->mode & FMODE_READABLE))
5020  return rb_io_close(write_io);
5021  return Qnil;
5022  }
5023 
5024  if ((fptr->mode & (FMODE_DUPLEX|FMODE_READABLE)) == FMODE_READABLE) {
5025  rb_raise(rb_eIOError, "closing non-duplex IO for writing");
5026  }
5027 
5028  if (io != write_io) {
5029  fptr = rb_io_get_fptr(rb_io_taint_check(io));
5030  fptr->tied_io_for_writing = 0;
5031  }
5032  rb_io_close(write_io);
5033  return Qnil;
5034 }
5035 
5036 /*
5037  * call-seq:
5038  * ios.sysseek(offset, whence=IO::SEEK_SET) -> integer
5039  *
5040  * Seeks to a given <i>offset</i> in the stream according to the value
5041  * of <i>whence</i> (see IO#seek for values of <i>whence</i>). Returns
5042  * the new offset into the file.
5043  *
5044  * f = File.new("testfile")
5045  * f.sysseek(-13, IO::SEEK_END) #=> 53
5046  * f.sysread(10) #=> "And so on."
5047  */
5048 
5049 static VALUE
5050 rb_io_sysseek(int argc, VALUE *argv, VALUE io)
5051 {
5052  VALUE offset, ptrname;
5053  int whence = SEEK_SET;
5054  rb_io_t *fptr;
5055  off_t pos;
5056 
5057  if (rb_scan_args(argc, argv, "11", &offset, &ptrname) == 2) {
5058  whence = interpret_seek_whence(ptrname);
5059  }
5060  pos = NUM2OFFT(offset);
5061  GetOpenFile(io, fptr);
5062  if ((fptr->mode & FMODE_READABLE) &&
5063  (READ_DATA_BUFFERED(fptr) || READ_CHAR_PENDING(fptr))) {
5064  rb_raise(rb_eIOError, "sysseek for buffered IO");
5065  }
5066  if ((fptr->mode & FMODE_WRITABLE) && fptr->wbuf.len) {
5067  rb_warn("sysseek for buffered IO");
5068  }
5069  errno = 0;
5070  pos = lseek(fptr->fd, pos, whence);
5071  if (pos < 0 && errno) rb_sys_fail_path(fptr->pathv);
5072 
5073  return OFFT2NUM(pos);
5074 }
5075 
5076 /*
5077  * call-seq:
5078  * ios.syswrite(string) -> integer
5079  *
5080  * Writes the given string to <em>ios</em> using a low-level write.
5081  * Returns the number of bytes written. Do not mix with other methods
5082  * that write to <em>ios</em> or you may get unpredictable results.
5083  * Raises SystemCallError on error.
5084  *
5085  * f = File.new("out", "w")
5086  * f.syswrite("ABCDEF") #=> 6
5087  */
5088 
5089 static VALUE
5090 rb_io_syswrite(VALUE io, VALUE str)
5091 {
5092  VALUE tmp;
5093  rb_io_t *fptr;
5094  long n, len;
5095  const char *ptr;
5096 
5097  if (!RB_TYPE_P(str, T_STRING))
5099 
5100  io = GetWriteIO(io);
5101  GetOpenFile(io, fptr);
5102  rb_io_check_writable(fptr);
5103 
5104  if (fptr->wbuf.len) {
5105  rb_warn("syswrite for buffered IO");
5106  }
5107 
5109  RSTRING_GETMEM(tmp, ptr, len);
5110  n = rb_write_internal(fptr->fd, ptr, len);
5111  if (n < 0) rb_sys_fail_path(fptr->pathv);
5113 
5114  return LONG2FIX(n);
5115 }
5116 
5117 /*
5118  * call-seq:
5119  * ios.sysread(maxlen[, outbuf]) -> string
5120  *
5121  * Reads <i>maxlen</i> bytes from <em>ios</em> using a low-level
5122  * read and returns them as a string. Do not mix with other methods
5123  * that read from <em>ios</em> or you may get unpredictable results.
5124  *
5125  * If the optional _outbuf_ argument is present,
5126  * it must reference a String, which will receive the data.
5127  * The _outbuf_ will contain only the received data after the method call
5128  * even if it is not empty at the beginning.
5129  *
5130  * Raises SystemCallError on error and EOFError at end of file.
5131  *
5132  * f = File.new("testfile")
5133  * f.sysread(16) #=> "This is line one"
5134  */
5135 
5136 static VALUE
5137 rb_io_sysread(int argc, VALUE *argv, VALUE io)
5138 {
5139  VALUE len, str;
5140  rb_io_t *fptr;
5141  long n, ilen;
5142  struct io_internal_read_struct iis;
5143  int shrinkable;
5144 
5145  rb_scan_args(argc, argv, "11", &len, &str);
5146  ilen = NUM2LONG(len);
5147 
5148  shrinkable = io_setstrbuf(&str, ilen);
5149  if (ilen == 0) return str;
5150 
5151  GetOpenFile(io, fptr);
5153 
5154  if (READ_DATA_BUFFERED(fptr)) {
5155  rb_raise(rb_eIOError, "sysread for buffered IO");
5156  }
5157 
5158  /*
5159  * FIXME: removing rb_thread_wait_fd() here changes sysread semantics
5160  * on non-blocking IOs. However, it's still currently possible
5161  * for sysread to raise Errno::EAGAIN if another thread read()s
5162  * the IO after we return from rb_thread_wait_fd() but before
5163  * we call read()
5164  */
5165  rb_thread_wait_fd(fptr->fd);
5166 
5167  rb_io_check_closed(fptr);
5168 
5169  io_setstrbuf(&str, ilen);
5170  iis.fd = fptr->fd;
5171  iis.nonblock = 1; /* for historical reasons, maybe (see above) */
5172  iis.buf = RSTRING_PTR(str);
5173  iis.capa = ilen;
5174  n = read_internal_locktmp(str, &iis);
5175 
5176  if (n < 0) {
5177  rb_sys_fail_path(fptr->pathv);
5178  }
5179  io_set_read_length(str, n, shrinkable);
5180  if (n == 0 && ilen > 0) {
5181  rb_eof_error();
5182  }
5183 
5184  return str;
5185 }
5186 
5187 #if defined(HAVE_PREAD) || defined(HAVE_PWRITE)
5188 struct prdwr_internal_arg {
5189  int fd;
5190  void *buf;
5191  size_t count;
5192  off_t offset;
5193 };
5194 #endif /* HAVE_PREAD || HAVE_PWRITE */
5195 
5196 #if defined(HAVE_PREAD)
5197 static VALUE
5198 internal_pread_func(void *arg)
5199 {
5200  struct prdwr_internal_arg *p = arg;
5201  return (VALUE)pread(p->fd, p->buf, p->count, p->offset);
5202 }
5203 
5204 static VALUE
5205 pread_internal_call(VALUE arg)
5206 {
5207  struct prdwr_internal_arg *p = (struct prdwr_internal_arg *)arg;
5208  return rb_thread_io_blocking_region(internal_pread_func, p, p->fd);
5209 }
5210 
5211 /*
5212  * call-seq:
5213  * ios.pread(maxlen, offset[, outbuf]) -> string
5214  *
5215  * Reads <i>maxlen</i> bytes from <em>ios</em> using the pread system call
5216  * and returns them as a string without modifying the underlying
5217  * descriptor offset. This is advantageous compared to combining IO#seek
5218  * and IO#read in that it is atomic, allowing multiple threads/process to
5219  * share the same IO object for reading the file at various locations.
5220  * This bypasses any userspace buffering of the IO layer.
5221  * If the optional <i>outbuf</i> argument is present, it must
5222  * reference a String, which will receive the data.
5223  * Raises SystemCallError on error, EOFError at end of file and
5224  * NotImplementedError if platform does not implement the system call.
5225  *
5226  * File.write("testfile", "This is line one\nThis is line two\n")
5227  * File.open("testfile") do |f|
5228  * p f.read # => "This is line one\nThis is line two\n"
5229  * p f.pread(12, 0) # => "This is line"
5230  * p f.pread(9, 8) # => "line one\n"
5231  * end
5232  */
5233 static VALUE
5234 rb_io_pread(int argc, VALUE *argv, VALUE io)
5235 {
5236  VALUE len, offset, str;
5237  rb_io_t *fptr;
5238  ssize_t n;
5239  struct prdwr_internal_arg arg;
5240  int shrinkable;
5241 
5242  rb_scan_args(argc, argv, "21", &len, &offset, &str);
5243  arg.count = NUM2SIZET(len);
5244  arg.offset = NUM2OFFT(offset);
5245 
5246  shrinkable = io_setstrbuf(&str, (long)arg.count);
5247  if (arg.count == 0) return str;
5248  arg.buf = RSTRING_PTR(str);
5249 
5250  GetOpenFile(io, fptr);
5252 
5253  arg.fd = fptr->fd;
5254  rb_io_check_closed(fptr);
5255 
5257  n = (ssize_t)rb_ensure(pread_internal_call, (VALUE)&arg, rb_str_unlocktmp, str);
5258 
5259  if (n < 0) {
5260  rb_sys_fail_path(fptr->pathv);
5261  }
5262  io_set_read_length(str, n, shrinkable);
5263  if (n == 0 && arg.count > 0) {
5264  rb_eof_error();
5265  }
5266 
5267  return str;
5268 }
5269 #else
5270 # define rb_io_pread rb_f_notimplement
5271 #endif /* HAVE_PREAD */
5272 
5273 #if defined(HAVE_PWRITE)
5274 static VALUE
5275 internal_pwrite_func(void *ptr)
5276 {
5277  struct prdwr_internal_arg *arg = ptr;
5278 
5279  return (VALUE)pwrite(arg->fd, arg->buf, arg->count, arg->offset);
5280 }
5281 
5282 /*
5283  * call-seq:
5284  * ios.pwrite(string, offset) -> integer
5285  *
5286  * Writes the given string to <em>ios</em> at <i>offset</i> using pwrite()
5287  * system call. This is advantageous to combining IO#seek and IO#write
5288  * in that it is atomic, allowing multiple threads/process to share the
5289  * same IO object for reading the file at various locations.
5290  * This bypasses any userspace buffering of the IO layer.
5291  * Returns the number of bytes written.
5292  * Raises SystemCallError on error and NotImplementedError
5293  * if platform does not implement the system call.
5294  *
5295  * File.open("out", "w") do |f|
5296  * f.pwrite("ABCDEF", 3) #=> 6
5297  * end
5298  *
5299  * File.read("out") #=> "\u0000\u0000\u0000ABCDEF"
5300  */
5301 static VALUE
5302 rb_io_pwrite(VALUE io, VALUE str, VALUE offset)
5303 {
5304  rb_io_t *fptr;
5305  ssize_t n;
5306  struct prdwr_internal_arg arg;
5307  VALUE tmp;
5308 
5309  if (!RB_TYPE_P(str, T_STRING))
5311 
5312  arg.offset = NUM2OFFT(offset);
5313 
5314  io = GetWriteIO(io);
5315  GetOpenFile(io, fptr);
5316  rb_io_check_writable(fptr);
5317  arg.fd = fptr->fd;
5318 
5320  arg.buf = RSTRING_PTR(tmp);
5321  arg.count = (size_t)RSTRING_LEN(tmp);
5322 
5323  n = (ssize_t)rb_thread_io_blocking_region(internal_pwrite_func, &arg, fptr->fd);
5324  if (n < 0) rb_sys_fail_path(fptr->pathv);
5326 
5327  return SSIZET2NUM(n);
5328 }
5329 #else
5330 # define rb_io_pwrite rb_f_notimplement
5331 #endif /* HAVE_PWRITE */
5332 
5333 VALUE
5335 {
5336  rb_io_t *fptr;
5337 
5338  GetOpenFile(io, fptr);
5339  if (fptr->readconv)
5340  rb_econv_binmode(fptr->readconv);
5341  if (fptr->writeconv)
5342  rb_econv_binmode(fptr->writeconv);
5343  fptr->mode |= FMODE_BINMODE;
5344  fptr->mode &= ~FMODE_TEXTMODE;
5346 #ifdef O_BINARY
5347  if (!fptr->readconv) {
5349  }
5350  else {
5351  setmode(fptr->fd, O_BINARY);
5352  }
5353 #endif
5354  return io;
5355 }
5356 
5357 static void
5358 io_ascii8bit_binmode(rb_io_t *fptr)
5359 {
5360  if (fptr->readconv) {
5361  rb_econv_close(fptr->readconv);
5362  fptr->readconv = NULL;
5363  }
5364  if (fptr->writeconv) {
5365  rb_econv_close(fptr->writeconv);
5366  fptr->writeconv = NULL;
5367  }
5368  fptr->mode |= FMODE_BINMODE;
5369  fptr->mode &= ~FMODE_TEXTMODE;
5371 
5372  fptr->encs.enc = rb_ascii8bit_encoding();
5373  fptr->encs.enc2 = NULL;
5374  fptr->encs.ecflags = 0;
5375  fptr->encs.ecopts = Qnil;
5376  clear_codeconv(fptr);
5377 }
5378 
5379 VALUE
5381 {
5382  rb_io_t *fptr;
5383 
5384  GetOpenFile(io, fptr);
5385  io_ascii8bit_binmode(fptr);
5386 
5387  return io;
5388 }
5389 
5390 /*
5391  * call-seq:
5392  * ios.binmode -> ios
5393  *
5394  * Puts <em>ios</em> into binary mode.
5395  * Once a stream is in binary mode, it cannot be reset to nonbinary mode.
5396  *
5397  * - newline conversion disabled
5398  * - encoding conversion disabled
5399  * - content is treated as ASCII-8BIT
5400  */
5401 
5402 static VALUE
5403 rb_io_binmode_m(VALUE io)
5404 {
5405  VALUE write_io;
5406 
5408 
5409  write_io = GetWriteIO(io);
5410  if (write_io != io)
5411  rb_io_ascii8bit_binmode(write_io);
5412  return io;
5413 }
5414 
5415 /*
5416  * call-seq:
5417  * ios.binmode? -> true or false
5418  *
5419  * Returns <code>true</code> if <em>ios</em> is binmode.
5420  */
5421 static VALUE
5422 rb_io_binmode_p(VALUE io)
5423 {
5424  rb_io_t *fptr;
5425  GetOpenFile(io, fptr);
5426  return fptr->mode & FMODE_BINMODE ? Qtrue : Qfalse;
5427 }
5428 
5429 static const char*
5430 rb_io_fmode_modestr(int fmode)
5431 {
5432  if (fmode & FMODE_APPEND) {
5433  if ((fmode & FMODE_READWRITE) == FMODE_READWRITE) {
5434  return MODE_BTMODE("a+", "ab+", "at+");
5435  }
5436  return MODE_BTMODE("a", "ab", "at");
5437  }
5438  switch (fmode & FMODE_READWRITE) {
5439  default:
5440  rb_raise(rb_eArgError, "invalid access fmode 0x%x", fmode);
5441  case FMODE_READABLE:
5442  return MODE_BTMODE("r", "rb", "rt");
5443  case FMODE_WRITABLE:
5444  return MODE_BTXMODE("w", "wb", "wt", "wx", "wbx", "wtx");
5445  case FMODE_READWRITE:
5446  if (fmode & FMODE_CREATE) {
5447  return MODE_BTXMODE("w+", "wb+", "wt+", "w+x", "wb+x", "wt+x");
5448  }
5449  return MODE_BTMODE("r+", "rb+", "rt+");
5450  }
5451 }
5452 
5453 static const char bom_prefix[] = "bom|";
5454 static const char utf_prefix[] = "utf-";
5455 enum {bom_prefix_len = (int)sizeof(bom_prefix) - 1};
5456 enum {utf_prefix_len = (int)sizeof(utf_prefix) - 1};
5457 
5458 static int
5459 io_encname_bom_p(const char *name, long len)
5460 {
5461  return len > bom_prefix_len && STRNCASECMP(name, bom_prefix, bom_prefix_len) == 0;
5462 }
5463 
5464 int
5465 rb_io_modestr_fmode(const char *modestr)
5466 {
5467  int fmode = 0;
5468  const char *m = modestr, *p = NULL;
5469 
5470  switch (*m++) {
5471  case 'r':
5472  fmode |= FMODE_READABLE;
5473  break;
5474  case 'w':
5476  break;
5477  case 'a':
5479  break;
5480  default:
5481  error:
5482  rb_raise(rb_eArgError, "invalid access mode %s", modestr);
5483  }
5484 
5485  while (*m) {
5486  switch (*m++) {
5487  case 'b':
5488  fmode |= FMODE_BINMODE;
5489  break;
5490  case 't':
5491  fmode |= FMODE_TEXTMODE;
5492  break;
5493  case '+':
5495  break;
5496  case 'x':
5497  if (modestr[0] != 'w')
5498  goto error;
5499  fmode |= FMODE_EXCL;
5500  break;
5501  default:
5502  goto error;
5503  case ':':
5504  p = strchr(m, ':');
5505  if (io_encname_bom_p(m, p ? (long)(p - m) : (long)strlen(m)))
5507  goto finished;
5508  }
5509  }
5510 
5511  finished:
5512  if ((fmode & FMODE_BINMODE) && (fmode & FMODE_TEXTMODE))
5513  goto error;
5514 
5515  return fmode;
5516 }
5517 
5518 int
5520 {
5521  int fmode = 0;
5522 
5523  switch (oflags & O_ACCMODE) {
5524  case O_RDONLY:
5526  break;
5527  case O_WRONLY:
5529  break;
5530  case O_RDWR:
5532  break;
5533  }
5534 
5535  if (oflags & O_APPEND) {
5536  fmode |= FMODE_APPEND;
5537  }
5538  if (oflags & O_TRUNC) {
5539  fmode |= FMODE_TRUNC;
5540  }
5541  if (oflags & O_CREAT) {
5542  fmode |= FMODE_CREATE;
5543  }
5544  if (oflags & O_EXCL) {
5545  fmode |= FMODE_EXCL;
5546  }
5547 #ifdef O_BINARY
5548  if (oflags & O_BINARY) {
5549  fmode |= FMODE_BINMODE;
5550  }
5551 #endif
5552 
5553  return fmode;
5554 }
5555 
5556 static int
5557 rb_io_fmode_oflags(int fmode)
5558 {
5559  int oflags = 0;
5560 
5561  switch (fmode & FMODE_READWRITE) {
5562  case FMODE_READABLE:
5563  oflags |= O_RDONLY;
5564  break;
5565  case FMODE_WRITABLE:
5566  oflags |= O_WRONLY;
5567  break;
5568  case FMODE_READWRITE:
5569  oflags |= O_RDWR;
5570  break;
5571  }
5572 
5573  if (fmode & FMODE_APPEND) {
5574  oflags |= O_APPEND;
5575  }
5576  if (fmode & FMODE_TRUNC) {
5577  oflags |= O_TRUNC;
5578  }
5579  if (fmode & FMODE_CREATE) {
5580  oflags |= O_CREAT;
5581  }
5582  if (fmode & FMODE_EXCL) {
5583  oflags |= O_EXCL;
5584  }
5585 #ifdef O_BINARY
5586  if (fmode & FMODE_BINMODE) {
5587  oflags |= O_BINARY;
5588  }
5589 #endif
5590 
5591  return oflags;
5592 }
5593 
5594 int
5595 rb_io_modestr_oflags(const char *modestr)
5596 {
5597  return rb_io_fmode_oflags(rb_io_modestr_fmode(modestr));
5598 }
5599 
5600 static const char*
5601 rb_io_oflags_modestr(int oflags)
5602 {
5603 #ifdef O_BINARY
5604 # define MODE_BINARY(a,b) ((oflags & O_BINARY) ? (b) : (a))
5605 #else
5606 # define MODE_BINARY(a,b) (a)
5607 #endif
5608  int accmode;
5609  if (oflags & O_EXCL) {
5610  rb_raise(rb_eArgError, "exclusive access mode is not supported");
5611  }
5612  accmode = oflags & (O_RDONLY|O_WRONLY|O_RDWR);
5613  if (oflags & O_APPEND) {
5614  if (accmode == O_WRONLY) {
5615  return MODE_BINARY("a", "ab");
5616  }
5617  if (accmode == O_RDWR) {
5618  return MODE_BINARY("a+", "ab+");
5619  }
5620  }
5621  switch (accmode) {
5622  default:
5623  rb_raise(rb_eArgError, "invalid access oflags 0x%x", oflags);
5624  case O_RDONLY:
5625  return MODE_BINARY("r", "rb");
5626  case O_WRONLY:
5627  return MODE_BINARY("w", "wb");
5628  case O_RDWR:
5629  if (oflags & O_TRUNC) {
5630  return MODE_BINARY("w+", "wb+");
5631  }
5632  return MODE_BINARY("r+", "rb+");
5633  }
5634 }
5635 
5636 /*
5637  * Convert external/internal encodings to enc/enc2
5638  * NULL => use default encoding
5639  * Qnil => no encoding specified (internal only)
5640  */
5641 static void
5642 rb_io_ext_int_to_encs(rb_encoding *ext, rb_encoding *intern, rb_encoding **enc, rb_encoding **enc2, int fmode)
5643 {
5644  int default_ext = 0;
5645 
5646  if (ext == NULL) {
5648  default_ext = 1;
5649  }
5650  if (ext == rb_ascii8bit_encoding()) {
5651  /* If external is ASCII-8BIT, no transcoding */
5652  intern = NULL;
5653  }
5654  else if (intern == NULL) {
5655  intern = rb_default_internal_encoding();
5656  }
5657  if (intern == NULL || intern == (rb_encoding *)Qnil ||
5658  (!(fmode & FMODE_SETENC_BY_BOM) && (intern == ext))) {
5659  /* No internal encoding => use external + no transcoding */
5660  *enc = (default_ext && intern != ext) ? NULL : ext;
5661  *enc2 = NULL;
5662  }
5663  else {
5664  *enc = intern;
5665  *enc2 = ext;
5666  }
5667 }
5668 
5669 static void
5670 unsupported_encoding(const char *name, rb_encoding *enc)
5671 {
5672  rb_enc_warn(enc, "Unsupported encoding %s ignored", name);
5673 }
5674 
5675 static void
5676 parse_mode_enc(const char *estr, rb_encoding *estr_enc,
5677  rb_encoding **enc_p, rb_encoding **enc2_p, int *fmode_p)
5678 {
5679  const char *p;
5680  char encname[ENCODING_MAXNAMELEN+1];
5681  int idx, idx2;
5682  int fmode = fmode_p ? *fmode_p : 0;
5683  rb_encoding *ext_enc, *int_enc;
5684  long len;
5685 
5686  /* parse estr as "enc" or "enc2:enc" or "enc:-" */
5687 
5688  p = strrchr(estr, ':');
5689  len = p ? (p++ - estr) : (long)strlen(estr);
5690  if ((fmode & FMODE_SETENC_BY_BOM) || io_encname_bom_p(estr, len)) {
5691  estr += bom_prefix_len;
5692  len -= bom_prefix_len;
5693  if (!STRNCASECMP(estr, utf_prefix, utf_prefix_len)) {
5695  }
5696  else {
5697  rb_enc_warn(estr_enc, "BOM with non-UTF encoding %s is nonsense", estr);
5699  }
5700  }
5701  if (len == 0 || len > ENCODING_MAXNAMELEN) {
5702  idx = -1;
5703  }
5704  else {
5705  if (p) {
5706  memcpy(encname, estr, len);
5707  encname[len] = '\0';
5708  estr = encname;
5709  }
5710  idx = rb_enc_find_index(estr);
5711  }
5712  if (fmode_p) *fmode_p = fmode;
5713 
5714  if (idx >= 0)
5715  ext_enc = rb_enc_from_index(idx);
5716  else {
5717  if (idx != -2)
5718  unsupported_encoding(estr, estr_enc);
5719  ext_enc = NULL;
5720  }
5721 
5722  int_enc = NULL;
5723  if (p) {
5724  if (*p == '-' && *(p+1) == '\0') {
5725  /* Special case - "-" => no transcoding */
5726  int_enc = (rb_encoding *)Qnil;
5727  }
5728  else {
5729  idx2 = rb_enc_find_index(p);
5730  if (idx2 < 0)
5731  unsupported_encoding(p, estr_enc);
5732  else if (!(fmode & FMODE_SETENC_BY_BOM) && (idx2 == idx)) {
5733  int_enc = (rb_encoding *)Qnil;
5734  }
5735  else
5736  int_enc = rb_enc_from_index(idx2);
5737  }
5738  }
5739 
5740  rb_io_ext_int_to_encs(ext_enc, int_enc, enc_p, enc2_p, fmode);
5741 }
5742 
5743 int
5744 rb_io_extract_encoding_option(VALUE opt, rb_encoding **enc_p, rb_encoding **enc2_p, int *fmode_p)
5745 {
5746  VALUE encoding=Qnil, extenc=Qundef, intenc=Qundef, tmp;
5747  int extracted = 0;
5748  rb_encoding *extencoding = NULL;
5749  rb_encoding *intencoding = NULL;
5750 
5751  if (!NIL_P(opt)) {
5752  VALUE v;
5753  v = rb_hash_lookup2(opt, sym_encoding, Qnil);
5754  if (v != Qnil) encoding = v;
5755  v = rb_hash_lookup2(opt, sym_extenc, Qundef);
5756  if (v != Qnil) extenc = v;
5757  v = rb_hash_lookup2(opt, sym_intenc, Qundef);
5758  if (v != Qundef) intenc = v;
5759  }
5760  if ((extenc != Qundef || intenc != Qundef) && !NIL_P(encoding)) {
5761  if (!NIL_P(ruby_verbose)) {
5762  int idx = rb_to_encoding_index(encoding);
5763  if (idx >= 0) encoding = rb_enc_from_encoding(rb_enc_from_index(idx));
5764  rb_warn("Ignoring encoding parameter '%"PRIsVALUE"': %s_encoding is used",
5765  encoding, extenc == Qundef ? "internal" : "external");
5766  }
5767  encoding = Qnil;
5768  }
5769  if (extenc != Qundef && !NIL_P(extenc)) {
5770  extencoding = rb_to_encoding(extenc);
5771  }
5772  if (intenc != Qundef) {
5773  if (NIL_P(intenc)) {
5774  /* internal_encoding: nil => no transcoding */
5775  intencoding = (rb_encoding *)Qnil;
5776  }
5777  else if (!NIL_P(tmp = rb_check_string_type(intenc))) {
5778  char *p = StringValueCStr(tmp);
5779 
5780  if (*p == '-' && *(p+1) == '\0') {
5781  /* Special case - "-" => no transcoding */
5782  intencoding = (rb_encoding *)Qnil;
5783  }
5784  else {
5785  intencoding = rb_to_encoding(intenc);
5786  }
5787  }
5788  else {
5789  intencoding = rb_to_encoding(intenc);
5790  }
5791  if (extencoding == intencoding) {
5792  intencoding = (rb_encoding *)Qnil;
5793  }
5794  }
5795  if (!NIL_P(encoding)) {
5796  extracted = 1;
5797  if (!NIL_P(tmp = rb_check_string_type(encoding))) {
5798  parse_mode_enc(StringValueCStr(tmp), rb_enc_get(tmp),
5799  enc_p, enc2_p, fmode_p);
5800  }
5801  else {
5802  rb_io_ext_int_to_encs(rb_to_encoding(encoding), NULL, enc_p, enc2_p, 0);
5803  }
5804  }
5805  else if (extenc != Qundef || intenc != Qundef) {
5806  extracted = 1;
5807  rb_io_ext_int_to_encs(extencoding, intencoding, enc_p, enc2_p, 0);
5808  }
5809  return extracted;
5810 }
5811 
5812 typedef struct rb_io_enc_t convconfig_t;
5813 
5814 static void
5815 validate_enc_binmode(int *fmode_p, int ecflags, rb_encoding *enc, rb_encoding *enc2)
5816 {
5817  int fmode = *fmode_p;
5818 
5819  if ((fmode & FMODE_READABLE) &&
5820  !enc2 &&
5821  !(fmode & FMODE_BINMODE) &&
5823  rb_raise(rb_eArgError, "ASCII incompatible encoding needs binmode");
5824 
5825  if ((fmode & FMODE_BINMODE) && (ecflags & ECONV_NEWLINE_DECORATOR_MASK)) {
5826  rb_raise(rb_eArgError, "newline decorator with binary mode");
5827  }
5828  if (!(fmode & FMODE_BINMODE) &&
5830  fmode |= FMODE_TEXTMODE;
5831  *fmode_p = fmode;
5832  }
5833 #if !DEFAULT_TEXTMODE
5834  else if (!(ecflags & ECONV_NEWLINE_DECORATOR_MASK)) {
5835  fmode &= ~FMODE_TEXTMODE;
5836  *fmode_p = fmode;
5837  }
5838 #endif
5839 }
5840 
5841 static void
5842 extract_binmode(VALUE opthash, int *fmode)
5843 {
5844  if (!NIL_P(opthash)) {
5845  VALUE v;
5846  v = rb_hash_aref(opthash, sym_textmode);
5847  if (!NIL_P(v)) {
5848  if (*fmode & FMODE_TEXTMODE)
5849  rb_raise(rb_eArgError, "textmode specified twice");
5850  if (*fmode & FMODE_BINMODE)
5851  rb_raise(rb_eArgError, "both textmode and binmode specified");
5852  if (RTEST(v))
5853  *fmode |= FMODE_TEXTMODE;
5854  }
5855  v = rb_hash_aref(opthash, sym_binmode);
5856  if (!NIL_P(v)) {
5857  if (*fmode & FMODE_BINMODE)
5858  rb_raise(rb_eArgError, "binmode specified twice");
5859  if (*fmode & FMODE_TEXTMODE)
5860  rb_raise(rb_eArgError, "both textmode and binmode specified");
5861  if (RTEST(v))
5862  *fmode |= FMODE_BINMODE;
5863  }
5864 
5865  if ((*fmode & FMODE_BINMODE) && (*fmode & FMODE_TEXTMODE))
5866  rb_raise(rb_eArgError, "both textmode and binmode specified");
5867  }
5868 }
5869 
5870 void
5871 rb_io_extract_modeenc(VALUE *vmode_p, VALUE *vperm_p, VALUE opthash,
5872  int *oflags_p, int *fmode_p, convconfig_t *convconfig_p)
5873 {
5874  VALUE vmode;
5875  int oflags, fmode;
5876  rb_encoding *enc, *enc2;
5877  int ecflags;
5878  VALUE ecopts;
5879  int has_enc = 0, has_vmode = 0;
5880  VALUE intmode;
5881 
5882  vmode = *vmode_p;
5883 
5884  /* Set to defaults */
5885  rb_io_ext_int_to_encs(NULL, NULL, &enc, &enc2, 0);
5886 
5887  vmode_handle:
5888  if (NIL_P(vmode)) {
5890  oflags = O_RDONLY;
5891  }
5892  else if (!NIL_P(intmode = rb_check_to_integer(vmode, "to_int"))) {
5893  vmode = intmode;
5894  oflags = NUM2INT(intmode);
5895  fmode = rb_io_oflags_fmode(oflags);
5896  }
5897  else {
5898  const char *p;
5899 
5900  SafeStringValue(vmode);
5901  p = StringValueCStr(vmode);
5903  oflags = rb_io_fmode_oflags(fmode);
5904  p = strchr(p, ':');
5905  if (p) {
5906  has_enc = 1;
5907  parse_mode_enc(p+1, rb_enc_get(vmode), &enc, &enc2, &fmode);
5908  }
5909  else {
5910  rb_encoding *e;
5911 
5913  rb_io_ext_int_to_encs(e, NULL, &enc, &enc2, fmode);
5914  }
5915  }
5916 
5917  if (NIL_P(opthash)) {
5918  ecflags = (fmode & FMODE_READABLE) ?
5921 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
5922  ecflags |= (fmode & FMODE_WRITABLE) ?
5923  MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE,
5924  0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE) : 0;
5925 #endif
5927  ecopts = Qnil;
5928  }
5929  else {
5930  VALUE v;
5931  if (!has_vmode) {
5932  v = rb_hash_aref(opthash, sym_mode);
5933  if (!NIL_P(v)) {
5934  if (!NIL_P(vmode)) {
5935  rb_raise(rb_eArgError, "mode specified twice");
5936  }
5937  has_vmode = 1;
5938  vmode = v;
5939  goto vmode_handle;
5940  }
5941  }
5942  v = rb_hash_aref(opthash, sym_flags);
5943  if (!NIL_P(v)) {
5944  v = rb_to_int(v);
5945  oflags |= NUM2INT(v);
5946  vmode = INT2NUM(oflags);
5947  fmode = rb_io_oflags_fmode(oflags);
5948  }
5949  extract_binmode(opthash, &fmode);
5950  if (fmode & FMODE_BINMODE) {
5951 #ifdef O_BINARY
5952  oflags |= O_BINARY;
5953 #endif
5954  if (!has_enc)
5955  rb_io_ext_int_to_encs(rb_ascii8bit_encoding(), NULL, &enc, &enc2, fmode);
5956  }
5957 #if DEFAULT_TEXTMODE
5958  else if (NIL_P(vmode)) {
5960  }
5961 #endif
5962  v = rb_hash_aref(opthash, sym_perm);
5963  if (!NIL_P(v)) {
5964  if (vperm_p) {
5965  if (!NIL_P(*vperm_p)) {
5966  rb_raise(rb_eArgError, "perm specified twice");
5967  }
5968  *vperm_p = v;
5969  }
5970  else {
5971  /* perm no use, just ignore */
5972  }
5973  }
5974  ecflags = (fmode & FMODE_READABLE) ?
5977 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
5978  ecflags |= (fmode & FMODE_WRITABLE) ?
5979  MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE,
5980  0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE) : 0;
5981 #endif
5982 
5983  if (rb_io_extract_encoding_option(opthash, &enc, &enc2, &fmode)) {
5984  if (has_enc) {
5985  rb_raise(rb_eArgError, "encoding specified twice");
5986  }
5987  }
5989  ecflags = rb_econv_prepare_options(opthash, &ecopts, ecflags);
5990  }
5991 
5992  validate_enc_binmode(&fmode, ecflags, enc, enc2);
5993 
5994  *vmode_p = vmode;
5995 
5996  *oflags_p = oflags;
5997  *fmode_p = fmode;
5998  convconfig_p->enc = enc;
5999  convconfig_p->enc2 = enc2;
6000  convconfig_p->ecflags = ecflags;
6001  convconfig_p->ecopts = ecopts;
6002 }
6003 
6006  int oflags;
6008 };
6009 
6010 static void *
6011 sysopen_func(void *ptr)
6012 {
6013  const struct sysopen_struct *data = ptr;
6014  const char *fname = RSTRING_PTR(data->fname);
6015  return (void *)(VALUE)rb_cloexec_open(fname, data->oflags, data->perm);
6016 }
6017 
6018 static inline int
6019 rb_sysopen_internal(struct sysopen_struct *data)
6020 {
6021  int fd;
6022  fd = (int)(VALUE)rb_thread_call_without_gvl(sysopen_func, data, RUBY_UBF_IO, 0);
6023  if (0 <= fd)
6024  rb_update_max_fd(fd);
6025  return fd;
6026 }
6027 
6028 static int
6029 rb_sysopen(VALUE fname, int oflags, mode_t perm)
6030 {
6031  int fd;
6032  struct sysopen_struct data;
6033 
6035  StringValueCStr(data.fname);
6036  data.oflags = oflags;
6037  data.perm = perm;
6038 
6039  fd = rb_sysopen_internal(&data);
6040  if (fd < 0) {
6041  int e = errno;
6042  if (rb_gc_for_fd(e)) {
6043  fd = rb_sysopen_internal(&data);
6044  }
6045  if (fd < 0) {
6047  }
6048  }
6049  return fd;
6050 }
6051 
6052 FILE *
6053 rb_fdopen(int fd, const char *modestr)
6054 {
6055  FILE *file;
6056 
6057 #if defined(__sun)
6058  errno = 0;
6059 #endif
6060  file = fdopen(fd, modestr);
6061  if (!file) {
6062  int e = errno;
6063 #if defined(__sun)
6064  if (e == 0) {
6065  rb_gc();
6066  errno = 0;
6067  file = fdopen(fd, modestr);
6068  }
6069  else
6070 #endif
6071  if (rb_gc_for_fd(e)) {
6072  file = fdopen(fd, modestr);
6073  }
6074  if (!file) {
6075 #ifdef _WIN32
6076  if (e == 0) e = EINVAL;
6077 #elif defined(__sun)
6078  if (e == 0) e = EMFILE;
6079 #endif
6080  rb_syserr_fail(e, 0);
6081  }
6082  }
6083 
6084  /* xxx: should be _IONBF? A buffer in FILE may have trouble. */
6085 #ifdef USE_SETVBUF
6086  if (setvbuf(file, NULL, _IOFBF, 0) != 0)
6087  rb_warn("setvbuf() can't be honoured (fd=%d)", fd);
6088 #endif
6089  return file;
6090 }
6091 
6092 static int
6093 io_check_tty(rb_io_t *fptr)
6094 {
6095  int t = isatty(fptr->fd);
6096  if (t)
6097  fptr->mode |= FMODE_TTY|FMODE_DUPLEX;
6098  return t;
6099 }
6100 
6101 static VALUE rb_io_internal_encoding(VALUE);
6102 static void io_encoding_set(rb_io_t *, VALUE, VALUE, VALUE);
6103 
6104 static int
6105 io_strip_bom(VALUE io)
6106 {
6107  VALUE b1, b2, b3, b4;
6108  rb_io_t *fptr;
6109 
6110  GetOpenFile(io, fptr);
6111  if (!(fptr->mode & FMODE_READABLE)) return 0;
6112  if (NIL_P(b1 = rb_io_getbyte(io))) return 0;
6113  switch (b1) {
6114  case INT2FIX(0xEF):
6115  if (NIL_P(b2 = rb_io_getbyte(io))) break;
6116  if (b2 == INT2FIX(0xBB) && !NIL_P(b3 = rb_io_getbyte(io))) {
6117  if (b3 == INT2FIX(0xBF)) {
6118  return rb_utf8_encindex();
6119  }
6120  rb_io_ungetbyte(io, b3);
6121  }
6122  rb_io_ungetbyte(io, b2);
6123  break;
6124 
6125  case INT2FIX(0xFE):
6126  if (NIL_P(b2 = rb_io_getbyte(io))) break;
6127  if (b2 == INT2FIX(0xFF)) {
6128  return ENCINDEX_UTF_16BE;
6129  }
6130  rb_io_ungetbyte(io, b2);
6131  break;
6132 
6133  case INT2FIX(0xFF):
6134  if (NIL_P(b2 = rb_io_getbyte(io))) break;
6135  if (b2 == INT2FIX(0xFE)) {
6136  b3 = rb_io_getbyte(io);
6137  if (b3 == INT2FIX(0) && !NIL_P(b4 = rb_io_getbyte(io))) {
6138  if (b4 == INT2FIX(0)) {
6139  return ENCINDEX_UTF_32LE;
6140  }
6141  rb_io_ungetbyte(io, b4);
6142  }
6143  rb_io_ungetbyte(io, b3);
6144  return ENCINDEX_UTF_16LE;
6145  }
6146  rb_io_ungetbyte(io, b2);
6147  break;
6148 
6149  case INT2FIX(0):
6150  if (NIL_P(b2 = rb_io_getbyte(io))) break;
6151  if (b2 == INT2FIX(0) && !NIL_P(b3 = rb_io_getbyte(io))) {
6152  if (b3 == INT2FIX(0xFE) && !NIL_P(b4 = rb_io_getbyte(io))) {
6153  if (b4 == INT2FIX(0xFF)) {
6154  return ENCINDEX_UTF_32BE;
6155  }
6156  rb_io_ungetbyte(io, b4);
6157  }
6158  rb_io_ungetbyte(io, b3);
6159  }
6160  rb_io_ungetbyte(io, b2);
6161  break;
6162  }
6163  rb_io_ungetbyte(io, b1);
6164  return 0;
6165 }
6166 
6167 static rb_encoding *
6168 io_set_encoding_by_bom(VALUE io)
6169 {
6170  int idx = io_strip_bom(io);
6171  rb_io_t *fptr;
6172  rb_encoding *extenc = NULL;
6173 
6174  GetOpenFile(io, fptr);
6175  if (idx) {
6176  extenc = rb_enc_from_index(idx);
6177  io_encoding_set(fptr, rb_enc_from_encoding(extenc),
6178  rb_io_internal_encoding(io), Qnil);
6179  }
6180  else {
6181  fptr->encs.enc2 = NULL;
6182  }
6183  return extenc;
6184 }
6185 
6186 static VALUE
6187 rb_file_open_generic(VALUE io, VALUE filename, int oflags, int fmode,
6188  const convconfig_t *convconfig, mode_t perm)
6189 {
6190  VALUE pathv;
6191  rb_io_t *fptr;
6192  convconfig_t cc;
6193  if (!convconfig) {
6194  /* Set to default encodings */
6195  rb_io_ext_int_to_encs(NULL, NULL, &cc.enc, &cc.enc2, fmode);
6196  cc.ecflags = 0;
6197  cc.ecopts = Qnil;
6198  convconfig = &cc;
6199  }
6200  validate_enc_binmode(&fmode, convconfig->ecflags,
6201  convconfig->enc, convconfig->enc2);
6202 
6203  MakeOpenFile(io, fptr);
6204  fptr->mode = fmode;
6205  fptr->encs = *convconfig;
6206  pathv = rb_str_new_frozen(filename);
6207 #ifdef O_TMPFILE
6208  if (!(oflags & O_TMPFILE)) {
6209  fptr->pathv = pathv;
6210  }
6211 #else
6212  fptr->pathv = pathv;
6213 #endif
6214  fptr->fd = rb_sysopen(pathv, oflags, perm);
6215  io_check_tty(fptr);
6216  if (fmode & FMODE_SETENC_BY_BOM) io_set_encoding_by_bom(io);
6217 
6218  return io;
6219 }
6220 
6221 static VALUE
6222 rb_file_open_internal(VALUE io, VALUE filename, const char *modestr)
6223 {
6224  int fmode = rb_io_modestr_fmode(modestr);
6225  const char *p = strchr(modestr, ':');
6226  convconfig_t convconfig;
6227 
6228  if (p) {
6229  parse_mode_enc(p+1, rb_usascii_encoding(),
6230  &convconfig.enc, &convconfig.enc2, &fmode);
6231  convconfig.ecflags = 0;
6232  convconfig.ecopts = Qnil;
6233  }
6234  else {
6235  rb_encoding *e;
6236  /* Set to default encodings */
6237 
6239  rb_io_ext_int_to_encs(e, NULL, &convconfig.enc, &convconfig.enc2, fmode);
6240  convconfig.ecflags = 0;
6241  convconfig.ecopts = Qnil;
6242  }
6243 
6244  return rb_file_open_generic(io, filename,
6245  rb_io_fmode_oflags(fmode),
6246  fmode,
6247  &convconfig,
6248  0666);
6249 }
6250 
6251 VALUE
6252 rb_file_open_str(VALUE fname, const char *modestr)
6253 {
6255  return rb_file_open_internal(io_alloc(rb_cFile), fname, modestr);
6256 }
6257 
6258 VALUE
6259 rb_file_open(const char *fname, const char *modestr)
6260 {
6261  return rb_file_open_internal(io_alloc(rb_cFile), rb_str_new_cstr(fname), modestr);
6262 }
6263 
6264 #if defined(__CYGWIN__) || !defined(HAVE_WORKING_FORK)
6265 static struct pipe_list {
6266  rb_io_t *fptr;
6267  struct pipe_list *next;
6268 } *pipe_list;
6269 
6270 static void
6271 pipe_add_fptr(rb_io_t *fptr)
6272 {
6273  struct pipe_list *list;
6274 
6275  list = ALLOC(struct pipe_list);
6276  list->fptr = fptr;
6277  list->next = pipe_list;
6278  pipe_list = list;
6279 }
6280 
6281 static void
6282 pipe_del_fptr(rb_io_t *fptr)
6283 {
6284  struct pipe_list **prev = &pipe_list;
6285  struct pipe_list *tmp;
6286 
6287  while ((tmp = *prev) != 0) {
6288  if (tmp->fptr == fptr) {
6289  *prev = tmp->next;
6290  free(tmp);
6291  return;
6292  }
6293  prev = &tmp->next;
6294  }
6295 }
6296 
6297 #if defined (_WIN32) || defined(__CYGWIN__)
6298 static void
6299 pipe_atexit(void)
6300 {
6301  struct pipe_list *list = pipe_list;
6302  struct pipe_list *tmp;
6303 
6304  while (list) {
6305  tmp = list->next;
6306  rb_io_fptr_finalize(list->fptr);
6307  list = tmp;
6308  }
6309 }
6310 #endif
6311 
6312 static void
6313 pipe_finalize(rb_io_t *fptr, int noraise)
6314 {
6315 #if !defined(HAVE_WORKING_FORK) && !defined(_WIN32)
6316  int status = 0;
6317  if (fptr->stdio_file) {
6318  status = pclose(fptr->stdio_file);
6319  }
6320  fptr->fd = -1;
6321  fptr->stdio_file = 0;
6322  rb_last_status_set(status, fptr->pid);
6323 #else
6324  fptr_finalize(fptr, noraise);
6325 #endif
6326  pipe_del_fptr(fptr);
6327 }
6328 #endif
6329 
6330 static void
6331 fptr_copy_finalizer(rb_io_t *fptr, const rb_io_t *orig)
6332 {
6333 #if defined(__CYGWIN__) || !defined(HAVE_WORKING_FORK)
6334  void (*const old_finalize)(struct rb_io_t*,int) = fptr->finalize;
6335 
6336  if (old_finalize == orig->finalize) return;
6337 #endif
6338 
6339  fptr->finalize = orig->finalize;
6340 
6341 #if defined(__CYGWIN__) || !defined(HAVE_WORKING_FORK)
6342  if (old_finalize != pipe_finalize) {
6343  struct pipe_list *list;
6344  for (list = pipe_list; list; list = list->next) {
6345  if (list->fptr == fptr) break;
6346  }
6347  if (!list) pipe_add_fptr(fptr);
6348  }
6349  else {
6350  pipe_del_fptr(fptr);
6351  }
6352 #endif
6353 }
6354 
6355 void
6357 {
6359  fptr->mode |= FMODE_SYNC;
6360 }
6361 
6362 void
6364 {
6365  rb_io_synchronized(fptr);
6366 }
6367 
6368 int
6369 rb_pipe(int *pipes)
6370 {
6371  int ret;
6372  ret = rb_cloexec_pipe(pipes);
6373  if (ret < 0) {
6374  if (rb_gc_for_fd(errno)) {
6375  ret = rb_cloexec_pipe(pipes);
6376  }
6377  }
6378  if (ret == 0) {
6379  rb_update_max_fd(pipes[0]);
6380  rb_update_max_fd(pipes[1]);
6381  }
6382  return ret;
6383 }
6384 
6385 #ifdef _WIN32
6386 #define HAVE_SPAWNV 1
6387 #define spawnv(mode, cmd, args) rb_w32_uaspawn((mode), (cmd), (args))
6388 #define spawn(mode, cmd) rb_w32_uspawn((mode), (cmd), 0)
6389 #endif
6390 
6391 #if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
6392 struct popen_arg {
6393  VALUE execarg_obj;
6394  struct rb_execarg *eargp;
6395  int modef;
6396  int pair[2];
6397  int write_pair[2];
6398 };
6399 #endif
6400 
6401 #ifdef HAVE_WORKING_FORK
6402 static void
6403 popen_redirect(struct popen_arg *p)
6404 {
6405  if ((p->modef & FMODE_READABLE) && (p->modef & FMODE_WRITABLE)) {
6406  close(p->write_pair[1]);
6407  if (p->write_pair[0] != 0) {
6408  dup2(p->write_pair[0], 0);
6409  close(p->write_pair[0]);
6410  }
6411  close(p->pair[0]);
6412  if (p->pair[1] != 1) {
6413  dup2(p->pair[1], 1);
6414  close(p->pair[1]);
6415  }
6416  }
6417  else if (p->modef & FMODE_READABLE) {
6418  close(p->pair[0]);
6419  if (p->pair[1] != 1) {
6420  dup2(p->pair[1], 1);
6421  close(p->pair[1]);
6422  }
6423  }
6424  else {
6425  close(p->pair[1]);
6426  if (p->pair[0] != 0) {
6427  dup2(p->pair[0], 0);
6428  close(p->pair[0]);
6429  }
6430  }
6431 }
6432 
6433 #if defined(__linux__)
6434 /* Linux /proc/self/status contains a line: "FDSize:\t<nnn>\n"
6435  * Since /proc may not be available, linux_get_maxfd is just a hint.
6436  * This function, linux_get_maxfd, must be async-signal-safe.
6437  * I.e. opendir() is not usable.
6438  *
6439  * Note that memchr() and memcmp is *not* async-signal-safe in POSIX.
6440  * However they are easy to re-implement in async-signal-safe manner.
6441  * (Also note that there is missing/memcmp.c.)
6442  */
6443 static int
6444 linux_get_maxfd(void)
6445 {
6446  int fd;
6447  char buf[4096], *p, *np, *e;
6448  ssize_t ss;
6449  fd = rb_cloexec_open("/proc/self/status", O_RDONLY|O_NOCTTY, 0);
6450  if (fd < 0) return fd;
6451  ss = read(fd, buf, sizeof(buf));
6452  if (ss < 0) goto err;
6453  p = buf;
6454  e = buf + ss;
6455  while ((int)sizeof("FDSize:\t0\n")-1 <= e-p &&
6456  (np = memchr(p, '\n', e-p)) != NULL) {
6457  if (memcmp(p, "FDSize:", sizeof("FDSize:")-1) == 0) {
6458  int fdsize;
6459  p += sizeof("FDSize:")-1;
6460  *np = '\0';
6461  fdsize = (int)ruby_strtoul(p, (char **)NULL, 10);
6462  close(fd);
6463  return fdsize;
6464  }
6465  p = np+1;
6466  }
6467  /* fall through */
6468 
6469  err:
6470  close(fd);
6471  return (int)ss;
6472 }
6473 #endif
6474 
6475 /* This function should be async-signal-safe. */
6476 void
6477 rb_close_before_exec(int lowfd, int maxhint, VALUE noclose_fds)
6478 {
6479 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
6480  int fd, ret;
6481  int max = (int)max_file_descriptor;
6482 # ifdef F_MAXFD
6483  /* F_MAXFD is available since NetBSD 2.0. */
6484  ret = fcntl(0, F_MAXFD); /* async-signal-safe */
6485  if (ret != -1)
6486  maxhint = max = ret;
6487 # elif defined(__linux__)
6488  ret = linux_get_maxfd();
6489  if (maxhint < ret)
6490  maxhint = ret;
6491  /* maxhint = max = ret; if (ret == -1) abort(); // test */
6492 # endif
6493  if (max < maxhint)
6494  max = maxhint;
6495  for (fd = lowfd; fd <= max; fd++) {
6496  if (!NIL_P(noclose_fds) &&
6497  RTEST(rb_hash_lookup(noclose_fds, INT2FIX(fd)))) /* async-signal-safe */
6498  continue;
6499  ret = fcntl(fd, F_GETFD); /* async-signal-safe */
6500  if (ret != -1 && !(ret & FD_CLOEXEC)) {
6501  fcntl(fd, F_SETFD, ret|FD_CLOEXEC); /* async-signal-safe */
6502  }
6503 # define CONTIGUOUS_CLOSED_FDS 20
6504  if (ret != -1) {
6505  if (max < fd + CONTIGUOUS_CLOSED_FDS)
6506  max = fd + CONTIGUOUS_CLOSED_FDS;
6507  }
6508  }
6509 #endif
6510 }
6511 
6512 static int
6513 popen_exec(void *pp, char *errmsg, size_t errmsg_len)
6514 {
6515  struct popen_arg *p = (struct popen_arg*)pp;
6516 
6517  return rb_exec_async_signal_safe(p->eargp, errmsg, errmsg_len);
6518 }
6519 #endif
6520 
6521 #if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
6522 static VALUE
6523 rb_execarg_fixup_v(VALUE execarg_obj)
6524 {
6525  rb_execarg_parent_start(execarg_obj);
6526  return Qnil;
6527 }
6528 #else
6529 char *rb_execarg_commandline(const struct rb_execarg *eargp, VALUE *prog);
6530 #endif
6531 
6532 static VALUE
6533 pipe_open(VALUE execarg_obj, const char *modestr, int fmode,
6534  const convconfig_t *convconfig)
6535 {
6536  struct rb_execarg *eargp = NIL_P(execarg_obj) ? NULL : rb_execarg_get(execarg_obj);
6537  VALUE prog = eargp ? (eargp->use_shell ? eargp->invoke.sh.shell_script : eargp->invoke.cmd.command_name) : Qfalse ;
6538  rb_pid_t pid = 0;
6539  rb_io_t *fptr;
6540  VALUE port;
6541  rb_io_t *write_fptr;
6542  VALUE write_port;
6543 #if defined(HAVE_WORKING_FORK)
6544  int status;
6545  char errmsg[80] = { '\0' };
6546 #endif
6547 #if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
6548  int state;
6549  struct popen_arg arg;
6550 #endif
6551  int e = 0;
6552 #if defined(HAVE_SPAWNV)
6553 # if defined(HAVE_SPAWNVE)
6554 # define DO_SPAWN(cmd, args, envp) ((args) ? \
6555  spawnve(P_NOWAIT, (cmd), (args), (envp)) : \
6556  spawne(P_NOWAIT, (cmd), (envp)))
6557 # else
6558 # define DO_SPAWN(cmd, args, envp) ((args) ? \
6559  spawnv(P_NOWAIT, (cmd), (args)) : \
6560  spawn(P_NOWAIT, (cmd)))
6561 # endif
6562 # if !defined(HAVE_WORKING_FORK)
6563  char **args = NULL;
6564 # if defined(HAVE_SPAWNVE)
6565  char **envp = NULL;
6566 # endif
6567 # endif
6568 #endif
6569 #if !defined(HAVE_WORKING_FORK)
6570  struct rb_execarg sarg, *sargp = &sarg;
6571 #endif
6572  FILE *fp = 0;
6573  int fd = -1;
6574  int write_fd = -1;
6575 #if !defined(HAVE_WORKING_FORK)
6576  const char *cmd = 0;
6577 
6578  if (prog)
6579  cmd = StringValueCStr(prog);
6580 #endif
6581 
6582 #if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
6583  arg.execarg_obj = execarg_obj;
6584  arg.eargp = eargp;
6585  arg.modef = fmode;
6586  arg.pair[0] = arg.pair[1] = -1;
6587  arg.write_pair[0] = arg.write_pair[1] = -1;
6588 # if !defined(HAVE_WORKING_FORK)
6589  if (eargp && !eargp->use_shell) {
6590  args = ARGVSTR2ARGV(eargp->invoke.cmd.argv_str);
6591  }
6592 # endif
6593  switch (fmode & (FMODE_READABLE|FMODE_WRITABLE)) {
6595  if (rb_pipe(arg.write_pair) < 0)
6596  rb_sys_fail_str(prog);
6597  if (rb_pipe(arg.pair) < 0) {
6598  e = errno;
6599  close(arg.write_pair[0]);
6600  close(arg.write_pair[1]);
6601  rb_syserr_fail_str(e, prog);
6602  }
6603  if (eargp) {
6604  rb_execarg_addopt(execarg_obj, INT2FIX(0), INT2FIX(arg.write_pair[0]));
6605  rb_execarg_addopt(execarg_obj, INT2FIX(1), INT2FIX(arg.pair[1]));
6606  }
6607  break;
6608  case FMODE_READABLE:
6609  if (rb_pipe(arg.pair) < 0)
6610  rb_sys_fail_str(prog);
6611  if (eargp)
6612  rb_execarg_addopt(execarg_obj, INT2FIX(1), INT2FIX(arg.pair[1]));
6613  break;
6614  case FMODE_WRITABLE:
6615  if (rb_pipe(arg.pair) < 0)
6616  rb_sys_fail_str(prog);
6617  if (eargp)
6618  rb_execarg_addopt(execarg_obj, INT2FIX(0), INT2FIX(arg.pair[0]));
6619  break;
6620  default:
6621  rb_sys_fail_str(prog);
6622  }
6623  if (!NIL_P(execarg_obj)) {
6624  rb_protect(rb_execarg_fixup_v, execarg_obj, &state);
6625  if (state) {
6626  if (0 <= arg.write_pair[0]) close(arg.write_pair[0]);
6627  if (0 <= arg.write_pair[1]) close(arg.write_pair[1]);
6628  if (0 <= arg.pair[0]) close(arg.pair[0]);
6629  if (0 <= arg.pair[1]) close(arg.pair[1]);
6630  rb_execarg_parent_end(execarg_obj);
6631  rb_jump_tag(state);
6632  }
6633 
6634 # if defined(HAVE_WORKING_FORK)
6635  pid = rb_fork_async_signal_safe(&status, popen_exec, &arg, arg.eargp->redirect_fds, errmsg, sizeof(errmsg));
6636 # else
6637  rb_execarg_run_options(eargp, sargp, NULL, 0);
6638 # if defined(HAVE_SPAWNVE)
6639  if (eargp->envp_str) envp = (char **)RSTRING_PTR(eargp->envp_str);
6640 # endif
6641  while ((pid = DO_SPAWN(cmd, args, envp)) < 0) {
6642  /* exec failed */
6643  switch (e = errno) {
6644  case EAGAIN:
6645 # if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
6646  case EWOULDBLOCK:
6647 # endif
6648  rb_thread_sleep(1);
6649  continue;
6650  }
6651  break;
6652  }
6653  if (eargp)
6654  rb_execarg_run_options(sargp, NULL, NULL, 0);
6655 # endif
6656  rb_execarg_parent_end(execarg_obj);
6657  }
6658  else {
6659 # if defined(HAVE_WORKING_FORK)
6660  pid = rb_fork_ruby(&status);
6661  if (pid == 0) { /* child */
6662  rb_thread_atfork();
6663  popen_redirect(&arg);
6664  rb_io_synchronized(RFILE(orig_stdout)->fptr);
6665  rb_io_synchronized(RFILE(orig_stderr)->fptr);
6666  return Qnil;
6667  }
6668 # else
6669  rb_notimplement();
6670 # endif
6671  }
6672 
6673  /* parent */
6674  if (pid < 0) {
6675 # if defined(HAVE_WORKING_FORK)
6676  e = errno;
6677 # endif
6678  close(arg.pair[0]);
6679  close(arg.pair[1]);
6681  close(arg.write_pair[0]);
6682  close(arg.write_pair[1]);
6683  }
6684 # if defined(HAVE_WORKING_FORK)
6685  if (errmsg[0])
6686  rb_syserr_fail(e, errmsg);
6687 # endif
6688  rb_syserr_fail_str(e, prog);
6689  }
6690  if ((fmode & FMODE_READABLE) && (fmode & FMODE_WRITABLE)) {
6691  close(arg.pair[1]);
6692  fd = arg.pair[0];
6693  close(arg.write_pair[0]);
6694  write_fd = arg.write_pair[1];
6695  }
6696  else if (fmode & FMODE_READABLE) {
6697  close(arg.pair[1]);
6698  fd = arg.pair[0];
6699  }
6700  else {
6701  close(arg.pair[0]);
6702  fd = arg.pair[1];
6703  }
6704 #else
6705  cmd = rb_execarg_commandline(eargp, &prog);
6706  if (!NIL_P(execarg_obj)) {
6707  rb_execarg_parent_start(execarg_obj);
6708  rb_execarg_run_options(eargp, sargp, NULL, 0);
6709  }
6710  fp = popen(cmd, modestr);
6711  e = errno;
6712  if (eargp) {
6713  rb_execarg_parent_end(execarg_obj);
6714  rb_execarg_run_options(sargp, NULL, NULL, 0);
6715  }
6716  if (!fp) rb_syserr_fail_path(e, prog);
6717  fd = fileno(fp);
6718 #endif
6719 
6720  port = io_alloc(rb_cIO);
6721  MakeOpenFile(port, fptr);
6722  fptr->fd = fd;
6723  fptr->stdio_file = fp;
6724  fptr->mode = fmode | FMODE_SYNC|FMODE_DUPLEX;
6725  if (convconfig) {
6726  fptr->encs = *convconfig;
6727 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
6730  }
6731 #endif
6732  }
6733  else {
6734  if (NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {
6736  }
6737 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
6738  if (NEED_NEWLINE_DECORATOR_ON_WRITE(fptr)) {
6739  fptr->encs.ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
6740  }
6741 #endif
6742  }
6743  fptr->pid = pid;
6744 
6745  if (0 <= write_fd) {
6746  write_port = io_alloc(rb_cIO);
6747  MakeOpenFile(write_port, write_fptr);
6748  write_fptr->fd = write_fd;
6749  write_fptr->mode = (fmode & ~FMODE_READABLE)| FMODE_SYNC|FMODE_DUPLEX;
6750  fptr->mode &= ~FMODE_WRITABLE;
6751  fptr->tied_io_for_writing = write_port;
6752  rb_ivar_set(port, rb_intern("@tied_io_for_writing"), write_port);
6753  }
6754 
6755 #if defined (__CYGWIN__) || !defined(HAVE_WORKING_FORK)
6756  fptr->finalize = pipe_finalize;
6757  pipe_add_fptr(fptr);
6758 #endif
6759  return port;
6760 }
6761 
6762 static int
6763 is_popen_fork(VALUE prog)
6764 {
6765  if (RSTRING_LEN(prog) == 1 && RSTRING_PTR(prog)[0] == '-') {
6766 #if !defined(HAVE_WORKING_FORK)
6768  "fork() function is unimplemented on this machine");
6769 #else
6770  return TRUE;
6771 #endif
6772  }
6773  return FALSE;
6774 }
6775 
6776 static VALUE
6777 pipe_open_s(VALUE prog, const char *modestr, int fmode,
6778  const convconfig_t *convconfig)
6779 {
6780  int argc = 1;
6781  VALUE *argv = &prog;
6782  VALUE execarg_obj = Qnil;
6783 
6784  if (!is_popen_fork(prog))
6785  execarg_obj = rb_execarg_new(argc, argv, TRUE, FALSE);
6786  return pipe_open(execarg_obj, modestr, fmode, convconfig);
6787 }
6788 
6789 static VALUE
6790 pipe_close(VALUE io)
6791 {
6792  rb_io_t *fptr = io_close_fptr(io);
6793  if (fptr) {
6794  fptr_waitpid(fptr, rb_thread_to_be_killed(rb_thread_current()));
6795  }
6796  return Qnil;
6797 }
6798 
6799 /*
6800  * call-seq:
6801  * IO.popen([env,] cmd, mode="r" [, opt]) -> io
6802  * IO.popen([env,] cmd, mode="r" [, opt]) {|io| block } -> obj
6803  *
6804  * Runs the specified command as a subprocess; the subprocess's
6805  * standard input and output will be connected to the returned
6806  * IO object.
6807  *
6808  * The PID of the started process can be obtained by IO#pid method.
6809  *
6810  * _cmd_ is a string or an array as follows.
6811  *
6812  * cmd:
6813  * "-" : fork
6814  * commandline : command line string which is passed to a shell
6815  * [env, cmdname, arg1, ..., opts] : command name and zero or more arguments (no shell)
6816  * [env, [cmdname, argv0], arg1, ..., opts] : command name, argv[0] and zero or more arguments (no shell)
6817  * (env and opts are optional.)
6818  *
6819  * If _cmd_ is a +String+ ``<code>-</code>'',
6820  * then a new instance of Ruby is started as the subprocess.
6821  *
6822  * If <i>cmd</i> is an +Array+ of +String+,
6823  * then it will be used as the subprocess's +argv+ bypassing a shell.
6824  * The array can contain a hash at first for environments and
6825  * a hash at last for options similar to #spawn.
6826  *
6827  * The default mode for the new file object is ``r'',
6828  * but <i>mode</i> may be set to any of the modes listed in the description for class IO.
6829  * The last argument <i>opt</i> qualifies <i>mode</i>.
6830  *
6831  * # set IO encoding
6832  * IO.popen("nkf -e filename", :external_encoding=>"EUC-JP") {|nkf_io|
6833  * euc_jp_string = nkf_io.read
6834  * }
6835  *
6836  * # merge standard output and standard error using
6837  * # spawn option. See the document of Kernel.spawn.
6838  * IO.popen(["ls", "/", :err=>[:child, :out]]) {|ls_io|
6839  * ls_result_with_error = ls_io.read
6840  * }
6841  *
6842  * # spawn options can be mixed with IO options
6843  * IO.popen(["ls", "/"], :err=>[:child, :out]) {|ls_io|
6844  * ls_result_with_error = ls_io.read
6845  * }
6846  *
6847  * Raises exceptions which IO.pipe and Kernel.spawn raise.
6848  *
6849  * If a block is given, Ruby will run the command as a child connected
6850  * to Ruby with a pipe. Ruby's end of the pipe will be passed as a
6851  * parameter to the block.
6852  * At the end of block, Ruby closes the pipe and sets <code>$?</code>.
6853  * In this case IO.popen returns the value of the block.
6854  *
6855  * If a block is given with a _cmd_ of ``<code>-</code>'',
6856  * the block will be run in two separate processes: once in the parent,
6857  * and once in a child. The parent process will be passed the pipe
6858  * object as a parameter to the block, the child version of the block
6859  * will be passed +nil+, and the child's standard in and
6860  * standard out will be connected to the parent through the pipe. Not
6861  * available on all platforms.
6862  *
6863  * f = IO.popen("uname")
6864  * p f.readlines
6865  * f.close
6866  * puts "Parent is #{Process.pid}"
6867  * IO.popen("date") {|f| puts f.gets }
6868  * IO.popen("-") {|f| $stderr.puts "#{Process.pid} is here, f is #{f.inspect}"}
6869  * p $?
6870  * IO.popen(%w"sed -e s|^|<foo>| -e s&$&;zot;&", "r+") {|f|
6871  * f.puts "bar"; f.close_write; puts f.gets
6872  * }
6873  *
6874  * <em>produces:</em>
6875  *
6876  * ["Linux\n"]
6877  * Parent is 21346
6878  * Thu Jan 15 22:41:19 JST 2009
6879  * 21346 is here, f is #<IO:fd 3>
6880  * 21352 is here, f is nil
6881  * #<Process::Status: pid 21352 exit 0>
6882  * <foo>bar;zot;
6883  */
6884 
6885 static VALUE
6886 rb_io_s_popen(int argc, VALUE *argv, VALUE klass)
6887 {
6888  const char *modestr;
6889  VALUE pname, pmode = Qnil, port, tmp, opt = Qnil, env = Qnil, execarg_obj = Qnil;
6890  int oflags, fmode;
6891  convconfig_t convconfig;
6892 
6893  if (argc > 1 && !NIL_P(opt = rb_check_hash_type(argv[argc-1]))) --argc;
6894  if (argc > 1 && !NIL_P(env = rb_check_hash_type(argv[0]))) --argc, ++argv;
6895  switch (argc) {
6896  case 2:
6897  pmode = argv[1];
6898  case 1:
6899  pname = argv[0];
6900  break;
6901  default:
6902  {
6903  int ex = !NIL_P(opt);
6904  rb_error_arity(argc + ex, 1 + ex, 2 + ex);
6905  }
6906  }
6907 
6908  tmp = rb_check_array_type(pname);
6909  if (!NIL_P(tmp)) {
6910  long len = RARRAY_LEN(tmp);
6911 #if SIZEOF_LONG > SIZEOF_INT
6912  if (len > INT_MAX) {
6913  rb_raise(rb_eArgError, "too many arguments");
6914  }
6915 #endif
6916  execarg_obj = rb_execarg_new((int)len, RARRAY_CONST_PTR(tmp), FALSE, FALSE);
6917  RB_GC_GUARD(tmp);
6918  }
6919  else {
6920  SafeStringValue(pname);
6921  execarg_obj = Qnil;
6922  if (!is_popen_fork(pname))
6923  execarg_obj = rb_execarg_new(1, &pname, TRUE, FALSE);
6924  }
6925  if (!NIL_P(execarg_obj)) {
6926  if (!NIL_P(opt))
6927  opt = rb_execarg_extract_options(execarg_obj, opt);
6928  if (!NIL_P(env))
6929  rb_execarg_setenv(execarg_obj, env);
6930  }
6931  rb_io_extract_modeenc(&pmode, 0, opt, &oflags, &fmode, &convconfig);
6932  modestr = rb_io_oflags_modestr(oflags);
6933 
6934  port = pipe_open(execarg_obj, modestr, fmode, &convconfig);
6935  if (NIL_P(port)) {
6936  /* child */
6937  if (rb_block_given_p()) {
6938  rb_yield(Qnil);
6941  _exit(0);
6942  }
6943  return Qnil;
6944  }
6945  RBASIC_SET_CLASS(port, klass);
6946  if (rb_block_given_p()) {
6947  return rb_ensure(rb_yield, port, pipe_close, port);
6948  }
6949  return port;
6950 }
6951 
6952 static void
6953 rb_scan_open_args(int argc, const VALUE *argv,
6954  VALUE *fname_p, int *oflags_p, int *fmode_p,
6955  convconfig_t *convconfig_p, mode_t *perm_p)
6956 {
6957  VALUE opt, fname, vmode, vperm;
6958  int oflags, fmode;
6959  mode_t perm;
6960 
6961  argc = rb_scan_args(argc, argv, "12:", &fname, &vmode, &vperm, &opt);
6962  FilePathValue(fname);
6963 
6964  rb_io_extract_modeenc(&vmode, &vperm, opt, &oflags, &fmode, convconfig_p);
6965 
6966  perm = NIL_P(vperm) ? 0666 : NUM2MODET(vperm);
6967 
6968  *fname_p = fname;
6969  *oflags_p = oflags;
6970  *fmode_p = fmode;
6971  *perm_p = perm;
6972 }
6973 
6974 static VALUE
6975 rb_open_file(int argc, const VALUE *argv, VALUE io)
6976 {
6977  VALUE fname;
6978  int oflags, fmode;
6979  convconfig_t convconfig;
6980  mode_t perm;
6981 
6982  rb_scan_open_args(argc, argv, &fname, &oflags, &fmode, &convconfig, &perm);
6983  rb_file_open_generic(io, fname, oflags, fmode, &convconfig, perm);
6984 
6985  return io;
6986 }
6987 
6988 
6989 /*
6990  * Document-method: File::open
6991  *
6992  * call-seq:
6993  * File.open(filename, mode="r" [, opt]) -> file
6994  * File.open(filename [, mode [, perm]] [, opt]) -> file
6995  * File.open(filename, mode="r" [, opt]) {|file| block } -> obj
6996  * File.open(filename [, mode [, perm]] [, opt]) {|file| block } -> obj
6997  *
6998  * With no associated block, File.open is a synonym for
6999  * File.new. If the optional code block is given, it will
7000  * be passed the opened +file+ as an argument and the File object will
7001  * automatically be closed when the block terminates. The value of the block
7002  * will be returned from File.open.
7003  *
7004  * If a file is being created, its initial permissions may be set using the
7005  * +perm+ parameter. See File.new for further discussion.
7006  *
7007  * See IO.new for a description of the +mode+ and +opt+ parameters.
7008  */
7009 
7010 /*
7011  * Document-method: IO::open
7012  *
7013  * call-seq:
7014  * IO.open(fd, mode="r" [, opt]) -> io
7015  * IO.open(fd, mode="r" [, opt]) {|io| block } -> obj
7016  *
7017  * With no associated block, IO.open is a synonym for IO.new. If
7018  * the optional code block is given, it will be passed +io+ as an argument,
7019  * and the IO object will automatically be closed when the block terminates.
7020  * In this instance, IO.open returns the value of the block.
7021  *
7022  * See IO.new for a description of the +fd+, +mode+ and +opt+ parameters.
7023  */
7024 
7025 static VALUE
7026 rb_io_s_open(int argc, VALUE *argv, VALUE klass)
7027 {
7029 
7030  if (rb_block_given_p()) {
7031  return rb_ensure(rb_yield, io, io_close, io);
7032  }
7033 
7034  return io;
7035 }
7036 
7037 /*
7038  * call-seq:
7039  * IO.sysopen(path, [mode, [perm]]) -> integer
7040  *
7041  * Opens the given path, returning the underlying file descriptor as a
7042  * Integer.
7043  *
7044  * IO.sysopen("testfile") #=> 3
7045  */
7046 
7047 static VALUE
7048 rb_io_s_sysopen(int argc, VALUE *argv, VALUE _)
7049 {
7050  VALUE fname, vmode, vperm;
7051  VALUE intmode;
7052  int oflags, fd;
7053  mode_t perm;
7054 
7055  rb_scan_args(argc, argv, "12", &fname, &vmode, &vperm);
7056  FilePathValue(fname);
7057 
7058  if (NIL_P(vmode))
7059  oflags = O_RDONLY;
7060  else if (!NIL_P(intmode = rb_check_to_integer(vmode, "to_int")))
7061  oflags = NUM2INT(intmode);
7062  else {
7063  SafeStringValue(vmode);
7064  oflags = rb_io_modestr_oflags(StringValueCStr(vmode));
7065  }
7066  if (NIL_P(vperm)) perm = 0666;
7067  else perm = NUM2MODET(vperm);
7068 
7069  RB_GC_GUARD(fname) = rb_str_new4(fname);
7070  fd = rb_sysopen(fname, oflags, perm);
7071  return INT2NUM(fd);
7072 }
7073 
7074 static VALUE
7075 check_pipe_command(VALUE filename_or_command)
7076 {
7077  char *s = RSTRING_PTR(filename_or_command);
7078  long l = RSTRING_LEN(filename_or_command);
7079  char *e = s + l;
7080  int chlen;
7081 
7082  if (rb_enc_ascget(s, e, &chlen, rb_enc_get(filename_or_command)) == '|') {
7083  VALUE cmd = rb_str_new(s+chlen, l-chlen);
7084  return cmd;
7085  }
7086  return Qnil;
7087 }
7088 
7089 /*
7090  * call-seq:
7091  * open(path [, mode [, perm]] [, opt]) -> io or nil
7092  * open(path [, mode [, perm]] [, opt]) {|io| block } -> obj
7093  *
7094  * Creates an IO object connected to the given stream, file, or subprocess.
7095  *
7096  * If +path+ does not start with a pipe character (<code>|</code>), treat it
7097  * as the name of a file to open using the specified mode (defaulting to
7098  * "r").
7099  *
7100  * The +mode+ is either a string or an integer. If it is an integer, it
7101  * must be bitwise-or of open(2) flags, such as File::RDWR or File::EXCL. If
7102  * it is a string, it is either "fmode", "fmode:ext_enc", or
7103  * "fmode:ext_enc:int_enc".
7104  *
7105  * See the documentation of IO.new for full documentation of the +mode+ string
7106  * directives.
7107  *
7108  * If a file is being created, its initial permissions may be set using the
7109  * +perm+ parameter. See File.new and the open(2) and chmod(2) man pages for
7110  * a description of permissions.
7111  *
7112  * If a block is specified, it will be invoked with the IO object as a
7113  * parameter, and the IO will be automatically closed when the block
7114  * terminates. The call returns the value of the block.
7115  *
7116  * If +path+ starts with a pipe character (<code>"|"</code>), a subprocess is
7117  * created, connected to the caller by a pair of pipes. The returned IO
7118  * object may be used to write to the standard input and read from the
7119  * standard output of this subprocess.
7120  *
7121  * If the command following the pipe is a single minus sign
7122  * (<code>"|-"</code>), Ruby forks, and this subprocess is connected to the
7123  * parent. If the command is not <code>"-"</code>, the subprocess runs the
7124  * command.
7125  *
7126  * When the subprocess is Ruby (opened via <code>"|-"</code>), the +open+
7127  * call returns +nil+. If a block is associated with the open call, that
7128  * block will run twice --- once in the parent and once in the child.
7129  *
7130  * The block parameter will be an IO object in the parent and +nil+ in the
7131  * child. The parent's +IO+ object will be connected to the child's $stdin
7132  * and $stdout. The subprocess will be terminated at the end of the block.
7133  *
7134  * === Examples
7135  *
7136  * Reading from "testfile":
7137  *
7138  * open("testfile") do |f|
7139  * print f.gets
7140  * end
7141  *
7142  * Produces:
7143  *
7144  * This is line one
7145  *
7146  * Open a subprocess and read its output:
7147  *
7148  * cmd = open("|date")
7149  * print cmd.gets
7150  * cmd.close
7151  *
7152  * Produces:
7153  *
7154  * Wed Apr 9 08:56:31 CDT 2003
7155  *
7156  * Open a subprocess running the same Ruby program:
7157  *
7158  * f = open("|-", "w+")
7159  * if f.nil?
7160  * puts "in Child"
7161  * exit
7162  * else
7163  * puts "Got: #{f.gets}"
7164  * end
7165  *
7166  * Produces:
7167  *
7168  * Got: in Child
7169  *
7170  * Open a subprocess using a block to receive the IO object:
7171  *
7172  * open "|-" do |f|
7173  * if f then
7174  * # parent process
7175  * puts "Got: #{f.gets}"
7176  * else
7177  * # child process
7178  * puts "in Child"
7179  * end
7180  * end
7181  *
7182  * Produces:
7183  *
7184  * Got: in Child
7185  */
7186 
7187 static VALUE
7188 rb_f_open(int argc, VALUE *argv, VALUE _)
7189 {
7190  ID to_open = 0;
7191  int redirect = FALSE;
7192 
7193  if (argc >= 1) {
7194  CONST_ID(to_open, "to_open");
7195  if (rb_respond_to(argv[0], to_open)) {
7196  redirect = TRUE;
7197  }
7198  else {
7199  VALUE tmp = argv[0];
7200  FilePathValue(tmp);
7201  if (NIL_P(tmp)) {
7202  redirect = TRUE;
7203  }
7204  else {
7205  VALUE cmd = check_pipe_command(tmp);
7206  if (!NIL_P(cmd)) {
7207  argv[0] = cmd;
7208  return rb_io_s_popen(argc, argv, rb_cIO);
7209  }
7210  }
7211  }
7212  }
7213  if (redirect) {
7214  VALUE io = rb_funcallv_kw(argv[0], to_open, argc-1, argv+1, RB_PASS_CALLED_KEYWORDS);
7215 
7216  if (rb_block_given_p()) {
7217  return rb_ensure(rb_yield, io, io_close, io);
7218  }
7219  return io;
7220  }
7221  return rb_io_s_open(argc, argv, rb_cFile);
7222 }
7223 
7224 static VALUE rb_io_open_generic(VALUE, VALUE, int, int, const convconfig_t *, mode_t);
7225 
7226 static VALUE
7227 rb_io_open(VALUE io, VALUE filename, VALUE vmode, VALUE vperm, VALUE opt)
7228 {
7229  int oflags, fmode;
7230  convconfig_t convconfig;
7231  mode_t perm;
7232 
7233  rb_io_extract_modeenc(&vmode, &vperm, opt, &oflags, &fmode, &convconfig);
7234  perm = NIL_P(vperm) ? 0666 : NUM2MODET(vperm);
7235  return rb_io_open_generic(io, filename, oflags, fmode, &convconfig, perm);
7236 }
7237 
7238 static VALUE
7239 rb_io_open_generic(VALUE klass, VALUE filename, int oflags, int fmode,
7240  const convconfig_t *convconfig, mode_t perm)
7241 {
7242  VALUE cmd;
7243  if (klass == rb_cIO && !NIL_P(cmd = check_pipe_command(filename))) {
7244  return pipe_open_s(cmd, rb_io_oflags_modestr(oflags), fmode, convconfig);
7245  }
7246  else {
7247  return rb_file_open_generic(io_alloc(klass), filename,
7248  oflags, fmode, convconfig, perm);
7249  }
7250 }
7251 
7252 static VALUE
7253 io_reopen(VALUE io, VALUE nfile)
7254 {
7255  rb_io_t *fptr, *orig;
7256  int fd, fd2;
7257  off_t pos = 0;
7258 
7259  nfile = rb_io_get_io(nfile);
7260  GetOpenFile(io, fptr);
7261  GetOpenFile(nfile, orig);
7262 
7263  if (fptr == orig) return io;
7264  if (IS_PREP_STDIO(fptr)) {
7265  if ((fptr->stdio_file == stdin && !(orig->mode & FMODE_READABLE)) ||
7266  (fptr->stdio_file == stdout && !(orig->mode & FMODE_WRITABLE)) ||
7267  (fptr->stdio_file == stderr && !(orig->mode & FMODE_WRITABLE))) {
7269  "%s can't change access mode from \"%s\" to \"%s\"",
7270  PREP_STDIO_NAME(fptr), rb_io_fmode_modestr(fptr->mode),
7271  rb_io_fmode_modestr(orig->mode));
7272  }
7273  }
7274  if (fptr->mode & FMODE_WRITABLE) {
7275  if (io_fflush(fptr) < 0)
7276  rb_sys_fail(0);
7277  }
7278  else {
7279  flush_before_seek(fptr);
7280  }
7281  if (orig->mode & FMODE_READABLE) {
7282  pos = io_tell(orig);
7283  }
7284  if (orig->mode & FMODE_WRITABLE) {
7285  if (io_fflush(orig) < 0)
7286  rb_sys_fail(0);
7287  }
7288 
7289  /* copy rb_io_t structure */
7290  fptr->mode = orig->mode | (fptr->mode & FMODE_PREP);
7291  fptr->pid = orig->pid;
7292  fptr->lineno = orig->lineno;
7293  if (RTEST(orig->pathv)) fptr->pathv = orig->pathv;
7294  else if (!IS_PREP_STDIO(fptr)) fptr->pathv = Qnil;
7295  fptr_copy_finalizer(fptr, orig);
7296 
7297  fd = fptr->fd;
7298  fd2 = orig->fd;
7299  if (fd != fd2) {
7300  if (IS_PREP_STDIO(fptr) || fd <= 2 || !fptr->stdio_file) {
7301  /* need to keep FILE objects of stdin, stdout and stderr */
7302  if (rb_cloexec_dup2(fd2, fd) < 0)
7303  rb_sys_fail_path(orig->pathv);
7304  rb_update_max_fd(fd);
7305  }
7306  else {
7307  fclose(fptr->stdio_file);
7308  fptr->stdio_file = 0;
7309  fptr->fd = -1;
7310  if (rb_cloexec_dup2(fd2, fd) < 0)
7311  rb_sys_fail_path(orig->pathv);
7312  rb_update_max_fd(fd);
7313  fptr->fd = fd;
7314  }
7315  rb_thread_fd_close(fd);
7316  if ((orig->mode & FMODE_READABLE) && pos >= 0) {
7317  if (io_seek(fptr, pos, SEEK_SET) < 0 && errno) {
7318  rb_sys_fail_path(fptr->pathv);
7319  }
7320  if (io_seek(orig, pos, SEEK_SET) < 0 && errno) {
7321  rb_sys_fail_path(orig->pathv);
7322  }
7323  }
7324  }
7325 
7326  if (fptr->mode & FMODE_BINMODE) {
7327  rb_io_binmode(io);
7328  }
7329 
7330  RBASIC_SET_CLASS(io, rb_obj_class(nfile));
7331  return io;
7332 }
7333 
7334 #ifdef _WIN32
7335 int rb_freopen(VALUE fname, const char *mode, FILE *fp);
7336 #else
7337 static int
7338 rb_freopen(VALUE fname, const char *mode, FILE *fp)
7339 {
7340  if (!freopen(RSTRING_PTR(fname), mode, fp)) {
7341  RB_GC_GUARD(fname);
7342  return errno;
7343  }
7344  return 0;
7345 }
7346 #endif
7347 
7348 /*
7349  * call-seq:
7350  * ios.reopen(other_IO) -> ios
7351  * ios.reopen(path, mode [, opt]) -> ios
7352  *
7353  * Reassociates <em>ios</em> with the I/O stream given in
7354  * <i>other_IO</i> or to a new stream opened on <i>path</i>. This may
7355  * dynamically change the actual class of this stream.
7356  * The +mode+ and +opt+ parameters accept the same values as IO.open.
7357  *
7358  * f1 = File.new("testfile")
7359  * f2 = File.new("testfile")
7360  * f2.readlines[0] #=> "This is line one\n"
7361  * f2.reopen(f1) #=> #<File:testfile>
7362  * f2.readlines[0] #=> "This is line one\n"
7363  */
7364 
7365 static VALUE
7366 rb_io_reopen(int argc, VALUE *argv, VALUE file)
7367 {
7368  VALUE fname, nmode, opt;
7369  int oflags;
7370  rb_io_t *fptr;
7371 
7372  if (rb_scan_args(argc, argv, "11:", &fname, &nmode, &opt) == 1) {
7373  VALUE tmp = rb_io_check_io(fname);
7374  if (!NIL_P(tmp)) {
7375  return io_reopen(file, tmp);
7376  }
7377  }
7378 
7379  FilePathValue(fname);
7380  rb_io_taint_check(file);
7381  fptr = RFILE(file)->fptr;
7382  if (!fptr) {
7383  fptr = RFILE(file)->fptr = ZALLOC(rb_io_t);
7384  }
7385 
7386  if (!NIL_P(nmode) || !NIL_P(opt)) {
7387  int fmode;
7388  convconfig_t convconfig;
7389 
7390  rb_io_extract_modeenc(&nmode, 0, opt, &oflags, &fmode, &convconfig);
7391  if (IS_PREP_STDIO(fptr) &&
7392  ((fptr->mode & FMODE_READWRITE) & (fmode & FMODE_READWRITE)) !=
7393  (fptr->mode & FMODE_READWRITE)) {
7395  "%s can't change access mode from \"%s\" to \"%s\"",
7396  PREP_STDIO_NAME(fptr), rb_io_fmode_modestr(fptr->mode),
7397  rb_io_fmode_modestr(fmode));
7398  }
7399  fptr->mode = fmode;
7400  fptr->encs = convconfig;
7401  }
7402  else {
7403  oflags = rb_io_fmode_oflags(fptr->mode);
7404  }
7405 
7406  fptr->pathv = fname;
7407  if (fptr->fd < 0) {
7408  fptr->fd = rb_sysopen(fptr->pathv, oflags, 0666);
7409  fptr->stdio_file = 0;
7410  return file;
7411  }
7412 
7413  if (fptr->mode & FMODE_WRITABLE) {
7414  if (io_fflush(fptr) < 0)
7415  rb_sys_fail(0);
7416  }
7417  fptr->rbuf.off = fptr->rbuf.len = 0;
7418 
7419  if (fptr->stdio_file) {
7420  int e = rb_freopen(rb_str_encode_ospath(fptr->pathv),
7421  rb_io_oflags_modestr(oflags),
7422  fptr->stdio_file);
7423  if (e) rb_syserr_fail_path(e, fptr->pathv);
7424  fptr->fd = fileno(fptr->stdio_file);
7425  rb_fd_fix_cloexec(fptr->fd);
7426 #ifdef USE_SETVBUF
7427  if (setvbuf(fptr->stdio_file, NULL, _IOFBF, 0) != 0)
7428  rb_warn("setvbuf() can't be honoured for %"PRIsVALUE, fptr->pathv);
7429 #endif
7430  if (fptr->stdio_file == stderr) {
7431  if (setvbuf(fptr->stdio_file, NULL, _IONBF, BUFSIZ) != 0)
7432  rb_warn("setvbuf() can't be honoured for %"PRIsVALUE, fptr->pathv);
7433  }
7434  else if (fptr->stdio_file == stdout && isatty(fptr->fd)) {
7435  if (setvbuf(fptr->stdio_file, NULL, _IOLBF, BUFSIZ) != 0)
7436  rb_warn("setvbuf() can't be honoured for %"PRIsVALUE, fptr->pathv);
7437  }
7438  }
7439  else {
7440  int tmpfd = rb_sysopen(fptr->pathv, oflags, 0666);
7441  int err = 0;
7442  if (rb_cloexec_dup2(tmpfd, fptr->fd) < 0)
7443  err = errno;
7444  (void)close(tmpfd);
7445  if (err) {
7446  rb_syserr_fail_path(err, fptr->pathv);
7447  }
7448  }
7449 
7450  return file;
7451 }
7452 
7453 /* :nodoc: */
7454 static VALUE
7455 rb_io_init_copy(VALUE dest, VALUE io)
7456 {
7457  rb_io_t *fptr, *orig;
7458  int fd;
7459  VALUE write_io;
7460  off_t pos;
7461 
7462  io = rb_io_get_io(io);
7463  if (!OBJ_INIT_COPY(dest, io)) return dest;
7464  GetOpenFile(io, orig);
7465  MakeOpenFile(dest, fptr);
7466 
7467  rb_io_flush(io);
7468 
7469  /* copy rb_io_t structure */
7470  fptr->mode = orig->mode & ~FMODE_PREP;
7471  fptr->encs = orig->encs;
7472  fptr->pid = orig->pid;
7473  fptr->lineno = orig->lineno;
7474  if (!NIL_P(orig->pathv)) fptr->pathv = orig->pathv;
7475  fptr_copy_finalizer(fptr, orig);
7476 
7477  fd = ruby_dup(orig->fd);
7478  fptr->fd = fd;
7479  pos = io_tell(orig);
7480  if (0 <= pos)
7481  io_seek(fptr, pos, SEEK_SET);
7482  if (fptr->mode & FMODE_BINMODE) {
7483  rb_io_binmode(dest);
7484  }
7485 
7486  write_io = GetWriteIO(io);
7487  if (io != write_io) {
7488  write_io = rb_obj_dup(write_io);
7489  fptr->tied_io_for_writing = write_io;
7490  rb_ivar_set(dest, rb_intern("@tied_io_for_writing"), write_io);
7491  }
7492 
7493  return dest;
7494 }
7495 
7496 /*
7497  * call-seq:
7498  * ios.printf(format_string [, obj, ...]) -> nil
7499  *
7500  * Formats and writes to <em>ios</em>, converting parameters under
7501  * control of the format string. See Kernel#sprintf for details.
7502  */
7503 
7504 VALUE
7505 rb_io_printf(int argc, const VALUE *argv, VALUE out)
7506 {
7508  return Qnil;
7509 }
7510 
7511 /*
7512  * call-seq:
7513  * printf(io, string [, obj ... ]) -> nil
7514  * printf(string [, obj ... ]) -> nil
7515  *
7516  * Equivalent to:
7517  * io.write(sprintf(string, obj, ...))
7518  * or
7519  * $stdout.write(sprintf(string, obj, ...))
7520  */
7521 
7522 static VALUE
7523 rb_f_printf(int argc, VALUE *argv, VALUE _)
7524 {
7525  VALUE out;
7526 
7527  if (argc == 0) return Qnil;
7528  if (RB_TYPE_P(argv[0], T_STRING)) {
7529  out = rb_stdout;
7530  }
7531  else {
7532  out = argv[0];
7533  argv++;
7534  argc--;
7535  }
7537 
7538  return Qnil;
7539 }
7540 
7541 static void
7542 rb_output_fs_setter(VALUE val, ID id, VALUE *var)
7543 {
7544  rb_str_setter(val, id, &val);
7545  if (!NIL_P(val)) {
7546  rb_warn_deprecated("`$,'", NULL);
7547  }
7548  *var = val;
7549 }
7550 
7551 /*
7552  * call-seq:
7553  * ios.print -> nil
7554  * ios.print(obj, ...) -> nil
7555  *
7556  * Writes the given object(s) to <em>ios</em>. Returns +nil+.
7557  *
7558  * The stream must be opened for writing.
7559  * Each given object that isn't a string will be converted by calling
7560  * its <code>to_s</code> method.
7561  * When called without arguments, prints the contents of <code>$_</code>.
7562  *
7563  * If the output field separator (<code>$,</code>) is not +nil+,
7564  * it is inserted between objects.
7565  * If the output record separator (<code>$\</code>) is not +nil+,
7566  * it is appended to the output.
7567  *
7568  * $stdout.print("This is ", 100, " percent.\n")
7569  *
7570  * <em>produces:</em>
7571  *
7572  * This is 100 percent.
7573  */
7574 
7575 VALUE
7576 rb_io_print(int argc, const VALUE *argv, VALUE out)
7577 {
7578  int i;
7579  VALUE line;
7580 
7581  /* if no argument given, print `$_' */
7582  if (argc == 0) {
7583  argc = 1;
7584  line = rb_lastline_get();
7585  argv = &line;
7586  }
7587  for (i=0; i<argc; i++) {
7588  if (!NIL_P(rb_output_fs) && i>0) {
7589  rb_io_write(out, rb_output_fs);
7590  }
7591  rb_io_write(out, argv[i]);
7592  }
7593  if (argc > 0 && !NIL_P(rb_output_rs)) {
7594  rb_io_write(out, rb_output_rs);
7595  }
7596 
7597  return Qnil;
7598 }
7599 
7600 /*
7601  * call-seq:
7602  * print(obj, ...) -> nil
7603  *
7604  * Prints each object in turn to <code>$stdout</code>. If the output
7605  * field separator (<code>$,</code>) is not +nil+, its
7606  * contents will appear between each field. If the output record
7607  * separator (<code>$\</code>) is not +nil+, it will be
7608  * appended to the output. If no arguments are given, prints
7609  * <code>$_</code>. Objects that aren't strings will be converted by
7610  * calling their <code>to_s</code> method.
7611  *
7612  * print "cat", [1,2,3], 99, "\n"
7613  * $, = ", "
7614  * $\ = "\n"
7615  * print "cat", [1,2,3], 99
7616  *
7617  * <em>produces:</em>
7618  *
7619  * cat12399
7620  * cat, 1, 2, 3, 99
7621  */
7622 
7623 static VALUE
7624 rb_f_print(int argc, const VALUE *argv, VALUE _)
7625 {
7627  return Qnil;
7628 }
7629 
7630 /*
7631  * call-seq:
7632  * ios.putc(obj) -> obj
7633  *
7634  * If <i>obj</i> is Numeric, write the character whose code is the
7635  * least-significant byte of <i>obj</i>. If <i>obj</i> is String,
7636  * write the first character of <i>obj</i> to <em>ios</em>. Otherwise,
7637  * raise TypeError.
7638  *
7639  * $stdout.putc "A"
7640  * $stdout.putc 65
7641  *
7642  * <em>produces:</em>
7643  *
7644  * AA
7645  */
7646 
7647 static VALUE
7648 rb_io_putc(VALUE io, VALUE ch)
7649 {
7650  VALUE str;
7651  if (RB_TYPE_P(ch, T_STRING)) {
7652  str = rb_str_substr(ch, 0, 1);
7653  }
7654  else {
7655  char c = NUM2CHR(ch);
7656  str = rb_str_new(&c, 1);
7657  }
7658  rb_io_write(io, str);
7659  return ch;
7660 }
7661 
7662 /*
7663  * call-seq:
7664  * putc(int) -> int
7665  *
7666  * Equivalent to:
7667  *
7668  * $stdout.putc(int)
7669  *
7670  * Refer to the documentation for IO#putc for important information regarding
7671  * multi-byte characters.
7672  */
7673 
7674 static VALUE
7675 rb_f_putc(VALUE recv, VALUE ch)
7676 {
7677  if (recv == rb_stdout) {
7678  return rb_io_putc(recv, ch);
7679  }
7680  return rb_funcallv(rb_stdout, rb_intern("putc"), 1, &ch);
7681 }
7682 
7683 
7684 int
7686 {
7687  long len = RSTRING_LEN(str);
7688  const char *ptr = RSTRING_PTR(str);
7690  int n;
7691 
7692  if (len == 0) return 0;
7693  if ((n = rb_enc_mbminlen(enc)) == 1) {
7694  return ptr[len - 1] == c;
7695  }
7696  return rb_enc_ascget(ptr + ((len - 1) / n) * n, ptr + len, &n, enc) == c;
7697 }
7698 
7699 static VALUE
7700 io_puts_ary(VALUE ary, VALUE out, int recur)
7701 {
7702  VALUE tmp;
7703  long i;
7704 
7705  if (recur) {
7706  tmp = rb_str_new2("[...]");
7707  rb_io_puts(1, &tmp, out);
7708  return Qtrue;
7709  }
7710  ary = rb_check_array_type(ary);
7711  if (NIL_P(ary)) return Qfalse;
7712  for (i=0; i<RARRAY_LEN(ary); i++) {
7713  tmp = RARRAY_AREF(ary, i);
7714  rb_io_puts(1, &tmp, out);
7715  }
7716  return Qtrue;
7717 }
7718 
7719 /*
7720  * call-seq:
7721  * ios.puts(obj, ...) -> nil
7722  *
7723  * Writes the given object(s) to <em>ios</em>.
7724  * Writes a newline after any that do not already end
7725  * with a newline sequence. Returns +nil+.
7726  *
7727  * The stream must be opened for writing.
7728  * If called with an array argument, writes each element on a new line.
7729  * Each given object that isn't a string or array will be converted
7730  * by calling its +to_s+ method.
7731  * If called without arguments, outputs a single newline.
7732  *
7733  * $stdout.puts("this", "is", ["a", "test"])
7734  *
7735  * <em>produces:</em>
7736  *
7737  * this
7738  * is
7739  * a
7740  * test
7741  *
7742  * Note that +puts+ always uses newlines and is not affected
7743  * by the output record separator (<code>$\</code>).
7744  */
7745 
7746 VALUE
7747 rb_io_puts(int argc, const VALUE *argv, VALUE out)
7748 {
7749  int i, n;
7750  VALUE line, args[2];
7751 
7752  /* if no argument given, print newline. */
7753  if (argc == 0) {
7754  rb_io_write(out, rb_default_rs);
7755  return Qnil;
7756  }
7757  for (i=0; i<argc; i++) {
7758  if (RB_TYPE_P(argv[i], T_STRING)) {
7759  line = argv[i];
7760  goto string;
7761  }
7762  if (rb_exec_recursive(io_puts_ary, argv[i], out)) {
7763  continue;
7764  }
7765  line = rb_obj_as_string(argv[i]);
7766  string:
7767  n = 0;
7768  args[n++] = line;
7769  if (RSTRING_LEN(line) == 0 ||
7770  !rb_str_end_with_asciichar(line, '\n')) {
7771  args[n++] = rb_default_rs;
7772  }
7773  rb_io_writev(out, n, args);
7774  }
7775 
7776  return Qnil;
7777 }
7778 
7779 /*
7780  * call-seq:
7781  * puts(obj, ...) -> nil
7782  *
7783  * Equivalent to
7784  *
7785  * $stdout.puts(obj, ...)
7786  */
7787 
7788 static VALUE
7789 rb_f_puts(int argc, VALUE *argv, VALUE recv)
7790 {
7791  if (recv == rb_stdout) {
7792  return rb_io_puts(argc, argv, recv);
7793  }
7794  return rb_funcallv(rb_stdout, rb_intern("puts"), argc, argv);
7795 }
7796 
7797 void
7798 rb_p(VALUE obj) /* for debug print within C code */
7799 {
7800  VALUE args[2];
7801  args[0] = rb_obj_as_string(rb_inspect(obj));
7802  args[1] = rb_default_rs;
7803  if (RB_TYPE_P(rb_stdout, T_FILE) &&
7805  io_writev(2, args, rb_stdout);
7806  }
7807  else {
7808  rb_io_writev(rb_stdout, 2, args);
7809  }
7810 }
7811 
7812 struct rb_f_p_arg {
7813  int argc;
7815 };
7816 
7817 static VALUE
7818 rb_f_p_internal(VALUE arg)
7819 {
7820  struct rb_f_p_arg *arg1 = (struct rb_f_p_arg*)arg;
7821  int argc = arg1->argc;
7822  VALUE *argv = arg1->argv;
7823  int i;
7824  VALUE ret = Qnil;
7825 
7826  for (i=0; i<argc; i++) {
7827  rb_p(argv[i]);
7828  }
7829  if (argc == 1) {
7830  ret = argv[0];
7831  }
7832  else if (argc > 1) {
7833  ret = rb_ary_new4(argc, argv);
7834  }
7835  if (RB_TYPE_P(rb_stdout, T_FILE)) {
7837  }
7838  return ret;
7839 }
7840 
7841 /*
7842  * call-seq:
7843  * p(obj) -> obj
7844  * p(obj1, obj2, ...) -> [obj, ...]
7845  * p() -> nil
7846  *
7847  * For each object, directly writes _obj_.+inspect+ followed by a
7848  * newline to the program's standard output.
7849  *
7850  * S = Struct.new(:name, :state)
7851  * s = S['dave', 'TX']
7852  * p s
7853  *
7854  * <em>produces:</em>
7855  *
7856  * #<S name="dave", state="TX">
7857  */
7858 
7859 static VALUE
7860 rb_f_p(int argc, VALUE *argv, VALUE self)
7861 {
7862  struct rb_f_p_arg arg;
7863  arg.argc = argc;
7864  arg.argv = argv;
7865 
7866  return rb_uninterruptible(rb_f_p_internal, (VALUE)&arg);
7867 }
7868 
7869 /*
7870  * call-seq:
7871  * obj.display(port=$>) -> nil
7872  *
7873  * Prints <i>obj</i> on the given port (default <code>$></code>).
7874  * Equivalent to:
7875  *
7876  * def display(port=$>)
7877  * port.write self
7878  * nil
7879  * end
7880  *
7881  * For example:
7882  *
7883  * 1.display
7884  * "cat".display
7885  * [ 4, 5, 6 ].display
7886  * puts
7887  *
7888  * <em>produces:</em>
7889  *
7890  * 1cat[4, 5, 6]
7891  */
7892 
7893 static VALUE
7894 rb_obj_display(int argc, VALUE *argv, VALUE self)
7895 {
7896  VALUE out;
7897 
7898  out = (!rb_check_arity(argc, 0, 1) ? rb_stdout : argv[0]);
7899  rb_io_write(out, self);
7900 
7901  return Qnil;
7902 }
7903 
7904 static int
7905 rb_stderr_to_original_p(void)
7906 {
7907  return (rb_stderr == orig_stderr || RFILE(orig_stderr)->fptr->fd < 0);
7908 }
7909 
7910 void
7911 rb_write_error2(const char *mesg, long len)
7912 {
7913  if (rb_stderr_to_original_p()) {
7914 #ifdef _WIN32
7915  if (isatty(fileno(stderr))) {
7916  if (rb_w32_write_console(rb_str_new(mesg, len), fileno(stderr)) > 0) return;
7917  }
7918 #endif
7919  if (fwrite(mesg, sizeof(char), (size_t)len, stderr) < (size_t)len) {
7920  /* failed to write to stderr, what can we do? */
7921  return;
7922  }
7923  }
7924  else {
7926  }
7927 }
7928 
7929 void
7930 rb_write_error(const char *mesg)
7931 {
7932  rb_write_error2(mesg, strlen(mesg));
7933 }
7934 
7935 void
7937 {
7938  /* a stopgap measure for the time being */
7939  if (rb_stderr_to_original_p()) {
7940  size_t len = (size_t)RSTRING_LEN(mesg);
7941 #ifdef _WIN32
7942  if (isatty(fileno(stderr))) {
7943  if (rb_w32_write_console(mesg, fileno(stderr)) > 0) return;
7944  }
7945 #endif
7946  if (fwrite(RSTRING_PTR(mesg), sizeof(char), len, stderr) < len) {
7947  RB_GC_GUARD(mesg);
7948  return;
7949  }
7950  }
7951  else {
7952  /* may unlock GVL, and */
7953  rb_io_write(rb_stderr, mesg);
7954  }
7955 }
7956 
7957 int
7959 {
7960  if (rb_stderr_to_original_p())
7961  return isatty(fileno(stderr));
7962  return 0;
7963 }
7964 
7965 static void
7966 must_respond_to(ID mid, VALUE val, ID id)
7967 {
7968  if (!rb_respond_to(val, mid)) {
7969  rb_raise(rb_eTypeError, "%"PRIsVALUE" must have %"PRIsVALUE" method, %"PRIsVALUE" given",
7970  rb_id2str(id), rb_id2str(mid),
7971  rb_obj_class(val));
7972  }
7973 }
7974 
7975 static void
7976 stdout_setter(VALUE val, ID id, VALUE *variable)
7977 {
7978  must_respond_to(id_write, val, id);
7979  *variable = val;
7980 }
7981 
7982 static VALUE
7983 prep_io(int fd, int fmode, VALUE klass, const char *path)
7984 {
7985  rb_io_t *fp;
7986  VALUE io = io_alloc(klass);
7987 
7988  MakeOpenFile(io, fp);
7989  fp->fd = fd;
7990  fp->mode = fmode;
7991  if (!io_check_tty(fp)) {
7992 #ifdef __CYGWIN__
7993  fp->mode |= FMODE_BINMODE;
7994  setmode(fd, O_BINARY);
7995 #endif
7996  }
7997  if (path) fp->pathv = rb_obj_freeze(rb_str_new_cstr(path));
7998  rb_update_max_fd(fd);
7999 
8000  return io;
8001 }
8002 
8003 VALUE
8004 rb_io_fdopen(int fd, int oflags, const char *path)
8005 {
8006  VALUE klass = rb_cIO;
8007 
8008  if (path && strcmp(path, "-")) klass = rb_cFile;
8009  return prep_io(fd, rb_io_oflags_fmode(oflags), klass, path);
8010 }
8011 
8012 static VALUE
8013 prep_stdio(FILE *f, int fmode, VALUE klass, const char *path)
8014 {
8015  rb_io_t *fptr;
8016  VALUE io = prep_io(fileno(f), fmode|FMODE_PREP|DEFAULT_TEXTMODE, klass, path);
8017 
8018  GetOpenFile(io, fptr);
8020 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
8021  fptr->encs.ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
8022  if (fmode & FMODE_READABLE) {
8024  }
8025 #endif
8026  fptr->stdio_file = f;
8027 
8028  return io;
8029 }
8030 
8031 FILE *
8033 {
8034  if (!fptr->stdio_file) {
8035  int oflags = rb_io_fmode_oflags(fptr->mode) & ~O_EXCL;
8036  fptr->stdio_file = rb_fdopen(fptr->fd, rb_io_oflags_modestr(oflags));
8037  }
8038  return fptr->stdio_file;
8039 }
8040 
8041 static inline void
8042 rb_io_buffer_init(rb_io_buffer_t *buf)
8043 {
8044  buf->ptr = NULL;
8045  buf->off = 0;
8046  buf->len = 0;
8047  buf->capa = 0;
8048 }
8049 
8050 static inline rb_io_t *
8051 rb_io_fptr_new(void)
8052 {
8053  rb_io_t *fp = ALLOC(rb_io_t);
8054  fp->fd = -1;
8055  fp->stdio_file = NULL;
8056  fp->mode = 0;
8057  fp->pid = 0;
8058  fp->lineno = 0;
8059  fp->pathv = Qnil;
8060  fp->finalize = 0;
8061  rb_io_buffer_init(&fp->wbuf);
8062  rb_io_buffer_init(&fp->rbuf);
8063  rb_io_buffer_init(&fp->cbuf);
8064  fp->readconv = NULL;
8065  fp->writeconv = NULL;
8067  fp->writeconv_pre_ecflags = 0;
8068  fp->writeconv_pre_ecopts = Qnil;
8069  fp->writeconv_initialized = 0;
8070  fp->tied_io_for_writing = 0;
8071  fp->encs.enc = NULL;
8072  fp->encs.enc2 = NULL;
8073  fp->encs.ecflags = 0;
8074  fp->encs.ecopts = Qnil;
8075  fp->write_lock = 0;
8076  return fp;
8077 }
8078 
8079 rb_io_t *
8081 {
8082  rb_io_t *fp = 0;
8083 
8084  Check_Type(obj, T_FILE);
8085  if (RFILE(obj)->fptr) {
8086  rb_io_close(obj);
8087  rb_io_fptr_finalize(RFILE(obj)->fptr);
8088  RFILE(obj)->fptr = 0;
8089  }
8090  fp = rb_io_fptr_new();
8091  RFILE(obj)->fptr = fp;
8092  return fp;
8093 }
8094 
8095 /*
8096  * call-seq:
8097  * IO.new(fd [, mode] [, opt]) -> io
8098  *
8099  * Returns a new IO object (a stream) for the given integer file descriptor
8100  * +fd+ and +mode+ string. +opt+ may be used to specify parts of +mode+ in a
8101  * more readable fashion. See also IO.sysopen and IO.for_fd.
8102  *
8103  * IO.new is called by various File and IO opening methods such as IO::open,
8104  * Kernel#open, and File::open.
8105  *
8106  * === Open Mode
8107  *
8108  * When +mode+ is an integer it must be combination of the modes defined in
8109  * File::Constants (+File::RDONLY+, <code>File::WRONLY|File::CREAT</code>).
8110  * See the open(2) man page for more information.
8111  *
8112  * When +mode+ is a string it must be in one of the following forms:
8113  *
8114  * fmode
8115  * fmode ":" ext_enc
8116  * fmode ":" ext_enc ":" int_enc
8117  * fmode ":" "BOM|UTF-*"
8118  *
8119  * +fmode+ is an IO open mode string, +ext_enc+ is the external encoding for
8120  * the IO and +int_enc+ is the internal encoding.
8121  *
8122  * ==== IO Open Mode
8123  *
8124  * Ruby allows the following open modes:
8125  *
8126  * "r" Read-only, starts at beginning of file (default mode).
8127  *
8128  * "r+" Read-write, starts at beginning of file.
8129  *
8130  * "w" Write-only, truncates existing file
8131  * to zero length or creates a new file for writing.
8132  *
8133  * "w+" Read-write, truncates existing file to zero length
8134  * or creates a new file for reading and writing.
8135  *
8136  * "a" Write-only, each write call appends data at end of file.
8137  * Creates a new file for writing if file does not exist.
8138  *
8139  * "a+" Read-write, each write call appends data at end of file.
8140  * Creates a new file for reading and writing if file does
8141  * not exist.
8142  *
8143  * The following modes must be used separately, and along with one or more of
8144  * the modes seen above.
8145  *
8146  * "b" Binary file mode
8147  * Suppresses EOL <-> CRLF conversion on Windows. And
8148  * sets external encoding to ASCII-8BIT unless explicitly
8149  * specified.
8150  *
8151  * "t" Text file mode
8152  *
8153  * The exclusive access mode ("x") can be used together with "w" to ensure
8154  * the file is created. Errno::EEXIST is raised when it already exists.
8155  * It may not be supported with all kinds of streams (e.g. pipes).
8156  *
8157  * When the open mode of original IO is read only, the mode cannot be
8158  * changed to be writable. Similarly, the open mode cannot be changed from
8159  * write only to readable.
8160  *
8161  * When such a change is attempted the error is raised in different locations
8162  * according to the platform.
8163  *
8164  * === IO Encoding
8165  *
8166  * When +ext_enc+ is specified, strings read will be tagged by the encoding
8167  * when reading, and strings output will be converted to the specified
8168  * encoding when writing.
8169  *
8170  * When +ext_enc+ and +int_enc+ are specified read strings will be converted
8171  * from +ext_enc+ to +int_enc+ upon input, and written strings will be
8172  * converted from +int_enc+ to +ext_enc+ upon output. See Encoding for
8173  * further details of transcoding on input and output.
8174  *
8175  * If "BOM|UTF-8", "BOM|UTF-16LE" or "BOM|UTF16-BE" are used, Ruby checks for
8176  * a Unicode BOM in the input document to help determine the encoding. For
8177  * UTF-16 encodings the file open mode must be binary. When present, the BOM
8178  * is stripped and the external encoding from the BOM is used. When the BOM
8179  * is missing the given Unicode encoding is used as +ext_enc+. (The BOM-set
8180  * encoding option is case insensitive, so "bom|utf-8" is also valid.)
8181  *
8182  * === Options
8183  *
8184  * +opt+ can be used instead of +mode+ for improved readability. The
8185  * following keys are supported:
8186  *
8187  * :mode ::
8188  * Same as +mode+ parameter
8189  *
8190  * :flags ::
8191  * Specifies file open flags as integer.
8192  * If +mode+ parameter is given, this parameter will be bitwise-ORed.
8193  *
8194  * :\external_encoding ::
8195  * External encoding for the IO.
8196  *
8197  * :\internal_encoding ::
8198  * Internal encoding for the IO. "-" is a synonym for the default internal
8199  * encoding.
8200  *
8201  * If the value is +nil+ no conversion occurs.
8202  *
8203  * :encoding ::
8204  * Specifies external and internal encodings as "extern:intern".
8205  *
8206  * :textmode ::
8207  * If the value is truth value, same as "t" in argument +mode+.
8208  *
8209  * :binmode ::
8210  * If the value is truth value, same as "b" in argument +mode+.
8211  *
8212  * :autoclose ::
8213  * If the value is +false+, the +fd+ will be kept open after this IO
8214  * instance gets finalized.
8215  *
8216  * Also, +opt+ can have same keys in String#encode for controlling conversion
8217  * between the external encoding and the internal encoding.
8218  *
8219  * === Example 1
8220  *
8221  * fd = IO.sysopen("/dev/tty", "w")
8222  * a = IO.new(fd,"w")
8223  * $stderr.puts "Hello"
8224  * a.puts "World"
8225  *
8226  * Produces:
8227  *
8228  * Hello
8229  * World
8230  *
8231  * === Example 2
8232  *
8233  * require 'fcntl'
8234  *
8235  * fd = STDERR.fcntl(Fcntl::F_DUPFD)
8236  * io = IO.new(fd, mode: 'w:UTF-16LE', cr_newline: true)
8237  * io.puts "Hello, World!"
8238  *
8239  * fd = STDERR.fcntl(Fcntl::F_DUPFD)
8240  * io = IO.new(fd, mode: 'w', cr_newline: true,
8241  * external_encoding: Encoding::UTF_16LE)
8242  * io.puts "Hello, World!"
8243  *
8244  * Both of above print "Hello, World!" in UTF-16LE to standard error output
8245  * with converting EOL generated by #puts to CR.
8246  */
8247 
8248 static VALUE
8249 rb_io_initialize(int argc, VALUE *argv, VALUE io)
8250 {
8251  VALUE fnum, vmode;
8252  rb_io_t *fp;
8253  int fd, fmode, oflags = O_RDONLY;
8254  convconfig_t convconfig;
8255  VALUE opt;
8256 #if defined(HAVE_FCNTL) && defined(F_GETFL)
8257  int ofmode;
8258 #else
8259  struct stat st;
8260 #endif
8261 
8262 
8263  argc = rb_scan_args(argc, argv, "11:", &fnum, &vmode, &opt);
8264  rb_io_extract_modeenc(&vmode, 0, opt, &oflags, &fmode, &convconfig);
8265 
8266  fd = NUM2INT(fnum);
8267  if (rb_reserved_fd_p(fd)) {
8268  rb_raise(rb_eArgError, "The given fd is not accessible because RubyVM reserves it");
8269  }
8270 #if defined(HAVE_FCNTL) && defined(F_GETFL)
8271  oflags = fcntl(fd, F_GETFL);
8272  if (oflags == -1) rb_sys_fail(0);
8273 #else
8274  if (fstat(fd, &st) < 0) rb_sys_fail(0);
8275 #endif
8276  rb_update_max_fd(fd);
8277 #if defined(HAVE_FCNTL) && defined(F_GETFL)
8278  ofmode = rb_io_oflags_fmode(oflags);
8279  if (NIL_P(vmode)) {
8280  fmode = ofmode;
8281  }
8282  else if ((~ofmode & fmode) & FMODE_READWRITE) {
8283  VALUE error = INT2FIX(EINVAL);
8285  }
8286 #endif
8287  if (!NIL_P(opt) && rb_hash_aref(opt, sym_autoclose) == Qfalse) {
8288  fmode |= FMODE_PREP;
8289  }
8290  MakeOpenFile(io, fp);
8291  fp->fd = fd;
8292  fp->mode = fmode;
8293  fp->encs = convconfig;
8294  clear_codeconv(fp);
8295  io_check_tty(fp);
8296  if (fileno(stdin) == fd)
8297  fp->stdio_file = stdin;
8298  else if (fileno(stdout) == fd)
8299  fp->stdio_file = stdout;
8300  else if (fileno(stderr) == fd)
8301  fp->stdio_file = stderr;
8302 
8303  if (fmode & FMODE_SETENC_BY_BOM) io_set_encoding_by_bom(io);
8304  return io;
8305 }
8306 
8307 /*
8308  * call-seq:
8309  * ios.set_encoding_by_bom -> encoding or nil
8310  *
8311  * Checks if +ios+ starts with a BOM, and then consumes it and sets
8312  * the external encoding. Returns the result encoding if found, or
8313  * nil. If +ios+ is not binmode or its encoding has been set
8314  * already, an exception will be raised.
8315  *
8316  * File.write("bom.txt", "\u{FEFF}abc")
8317  * ios = File.open("bom.txt", "rb")
8318  * ios.set_encoding_by_bom #=> #<Encoding:UTF-8>
8319  *
8320  * File.write("nobom.txt", "abc")
8321  * ios = File.open("nobom.txt", "rb")
8322  * ios.set_encoding_by_bom #=> nil
8323  */
8324 
8325 static VALUE
8326 rb_io_set_encoding_by_bom(VALUE io)
8327 {
8328  rb_io_t *fptr;
8329 
8330  GetOpenFile(io, fptr);
8331  if (!(fptr->mode & FMODE_BINMODE)) {
8332  rb_raise(rb_eArgError, "ASCII incompatible encoding needs binmode");
8333  }
8334  if (fptr->encs.enc2) {
8335  rb_raise(rb_eArgError, "encoding conversion is set");
8336  }
8337  else if (fptr->encs.enc && fptr->encs.enc != rb_ascii8bit_encoding()) {
8338  rb_raise(rb_eArgError, "encoding is set to %s already",
8339  rb_enc_name(fptr->encs.enc));
8340  }
8341  if (!io_set_encoding_by_bom(io)) return Qnil;
8342  return rb_enc_from_encoding(fptr->encs.enc);
8343 }
8344 
8345 /*
8346  * call-seq:
8347  * File.new(filename, mode="r" [, opt]) -> file
8348  * File.new(filename [, mode [, perm]] [, opt]) -> file
8349  *
8350  * Opens the file named by +filename+ according to the given +mode+ and
8351  * returns a new File object.
8352  *
8353  * See IO.new for a description of +mode+ and +opt+.
8354  *
8355  * If a file is being created, permission bits may be given in +perm+. These
8356  * mode and permission bits are platform dependent; on Unix systems, see
8357  * open(2) and chmod(2) man pages for details.
8358  *
8359  * The new File object is buffered mode (or non-sync mode), unless
8360  * +filename+ is a tty.
8361  * See IO#flush, IO#fsync, IO#fdatasync, and IO#sync= about sync mode.
8362  *
8363  * === Examples
8364  *
8365  * f = File.new("testfile", "r")
8366  * f = File.new("newfile", "w+")
8367  * f = File.new("newfile", File::CREAT|File::TRUNC|File::RDWR, 0644)
8368  */
8369 
8370 static VALUE
8371 rb_file_initialize(int argc, VALUE *argv, VALUE io)
8372 {
8373  if (RFILE(io)->fptr) {
8374  rb_raise(rb_eRuntimeError, "reinitializing File");
8375  }
8376  if (0 < argc && argc < 3) {
8377  VALUE fd = rb_check_to_int(argv[0]);
8378 
8379  if (!NIL_P(fd)) {
8380  argv[0] = fd;
8381  return rb_io_initialize(argc, argv, io);
8382  }
8383  }
8384  rb_open_file(argc, argv, io);
8385 
8386  return io;
8387 }
8388 
8389 /* :nodoc: */
8390 static VALUE
8391 rb_io_s_new(int argc, VALUE *argv, VALUE klass)
8392 {
8393  if (rb_block_given_p()) {
8394  VALUE cname = rb_obj_as_string(klass);
8395 
8396  rb_warn("%"PRIsVALUE"::new() does not take block; use %"PRIsVALUE"::open() instead",
8397  cname, cname);
8398  }
8400 }
8401 
8402 
8403 /*
8404  * call-seq:
8405  * IO.for_fd(fd, mode [, opt]) -> io
8406  *
8407  * Synonym for IO.new.
8408  *
8409  */
8410 
8411 static VALUE
8412 rb_io_s_for_fd(int argc, VALUE *argv, VALUE klass)
8413 {
8414  VALUE io = rb_obj_alloc(klass);
8415  rb_io_initialize(argc, argv, io);
8416  return io;
8417 }
8418 
8419 /*
8420  * call-seq:
8421  * ios.autoclose? -> true or false
8422  *
8423  * Returns +true+ if the underlying file descriptor of _ios_ will be
8424  * closed automatically at its finalization, otherwise +false+.
8425  */
8426 
8427 static VALUE
8428 rb_io_autoclose_p(VALUE io)
8429 {
8430  rb_io_t *fptr = RFILE(io)->fptr;
8431  rb_io_check_closed(fptr);
8432  return (fptr->mode & FMODE_PREP) ? Qfalse : Qtrue;
8433 }
8434 
8435 /*
8436  * call-seq:
8437  * io.autoclose = bool -> true or false
8438  *
8439  * Sets auto-close flag.
8440  *
8441  * f = open("/dev/null")
8442  * IO.for_fd(f.fileno)
8443  * # ...
8444  * f.gets # may cause Errno::EBADF
8445  *
8446  * f = open("/dev/null")
8447  * IO.for_fd(f.fileno).autoclose = false
8448  * # ...
8449  * f.gets # won't cause Errno::EBADF
8450  */
8451 
8452 static VALUE
8453 rb_io_set_autoclose(VALUE io, VALUE autoclose)
8454 {
8455  rb_io_t *fptr;
8456  GetOpenFile(io, fptr);
8457  if (!RTEST(autoclose))
8458  fptr->mode |= FMODE_PREP;
8459  else
8460  fptr->mode &= ~FMODE_PREP;
8461  return autoclose;
8462 }
8463 
8464 static void
8465 argf_mark(void *ptr)
8466 {
8467  struct argf *p = ptr;
8468  rb_gc_mark(p->filename);
8470  rb_gc_mark(p->argv);
8471  rb_gc_mark(p->inplace);
8472  rb_gc_mark(p->encs.ecopts);
8473 }
8474 
8475 static size_t
8476 argf_memsize(const void *ptr)
8477 {
8478  const struct argf *p = ptr;
8479  size_t size = sizeof(*p);
8480  return size;
8481 }
8482 
8483 static const rb_data_type_t argf_type = {
8484  "ARGF",
8485  {argf_mark, RUBY_TYPED_DEFAULT_FREE, argf_memsize},
8487 };
8488 
8489 static inline void
8490 argf_init(struct argf *p, VALUE v)
8491 {
8492  p->filename = Qnil;
8493  p->current_file = Qnil;
8494  p->lineno = 0;
8495  p->argv = v;
8496 }
8497 
8498 static VALUE
8499 argf_alloc(VALUE klass)
8500 {
8501  struct argf *p;
8502  VALUE argf = TypedData_Make_Struct(klass, struct argf, &argf_type, p);
8503 
8504  argf_init(p, Qnil);
8505  return argf;
8506 }
8507 
8508 #undef rb_argv
8509 
8510 /* :nodoc: */
8511 static VALUE
8512 argf_initialize(VALUE argf, VALUE argv)
8513 {
8514  memset(&ARGF, 0, sizeof(ARGF));
8515  argf_init(&ARGF, argv);
8516 
8517  return argf;
8518 }
8519 
8520 /* :nodoc: */
8521 static VALUE
8522 argf_initialize_copy(VALUE argf, VALUE orig)
8523 {
8524  if (!OBJ_INIT_COPY(argf, orig)) return argf;
8525  ARGF = argf_of(orig);
8526  ARGF.argv = rb_obj_dup(ARGF.argv);
8527  return argf;
8528 }
8529 
8530 /*
8531  * call-seq:
8532  * ARGF.lineno = integer -> integer
8533  *
8534  * Sets the line number of +ARGF+ as a whole to the given +Integer+.
8535  *
8536  * +ARGF+ sets the line number automatically as you read data, so normally
8537  * you will not need to set it explicitly. To access the current line number
8538  * use +ARGF.lineno+.
8539  *
8540  * For example:
8541  *
8542  * ARGF.lineno #=> 0
8543  * ARGF.readline #=> "This is line 1\n"
8544  * ARGF.lineno #=> 1
8545  * ARGF.lineno = 0 #=> 0
8546  * ARGF.lineno #=> 0
8547  */
8548 static VALUE
8549 argf_set_lineno(VALUE argf, VALUE val)
8550 {
8551  ARGF.lineno = NUM2INT(val);
8552  ARGF.last_lineno = ARGF.lineno;
8553  return Qnil;
8554 }
8555 
8556 /*
8557  * call-seq:
8558  * ARGF.lineno -> integer
8559  *
8560  * Returns the current line number of ARGF as a whole. This value
8561  * can be set manually with +ARGF.lineno=+.
8562  *
8563  * For example:
8564  *
8565  * ARGF.lineno #=> 0
8566  * ARGF.readline #=> "This is line 1\n"
8567  * ARGF.lineno #=> 1
8568  */
8569 static VALUE
8570 argf_lineno(VALUE argf)
8571 {
8572  return INT2FIX(ARGF.lineno);
8573 }
8574 
8575 static VALUE
8576 argf_forward(int argc, VALUE *argv, VALUE argf)
8577 {
8578  return rb_funcall3(ARGF.current_file, rb_frame_this_func(), argc, argv);
8579 }
8580 
8581 #define next_argv() argf_next_argv(argf)
8582 #define ARGF_GENERIC_INPUT_P() \
8583  (ARGF.current_file == rb_stdin && !RB_TYPE_P(ARGF.current_file, T_FILE))
8584 #define ARGF_FORWARD(argc, argv) do {\
8585  if (ARGF_GENERIC_INPUT_P())\
8586  return argf_forward((argc), (argv), argf);\
8587 } while (0)
8588 #define NEXT_ARGF_FORWARD(argc, argv) do {\
8589  if (!next_argv()) return Qnil;\
8590  ARGF_FORWARD((argc), (argv));\
8591 } while (0)
8592 
8593 static void
8594 argf_close(VALUE argf)
8595 {
8596  VALUE file = ARGF.current_file;
8597  if (file == rb_stdin) return;
8598  if (RB_TYPE_P(file, T_FILE)) {
8599  rb_io_set_write_io(file, Qnil);
8600  }
8601  io_close(file);
8602  ARGF.init_p = -1;
8603 }
8604 
8605 static int
8606 argf_next_argv(VALUE argf)
8607 {
8608  char *fn;
8609  rb_io_t *fptr;
8610  int stdout_binmode = 0;
8611  int fmode;
8612 
8613  if (RB_TYPE_P(rb_stdout, T_FILE)) {
8614  GetOpenFile(rb_stdout, fptr);
8615  if (fptr->mode & FMODE_BINMODE)
8616  stdout_binmode = 1;
8617  }
8618 
8619  if (ARGF.init_p == 0) {
8620  if (!NIL_P(ARGF.argv) && RARRAY_LEN(ARGF.argv) > 0) {
8621  ARGF.next_p = 1;
8622  }
8623  else {
8624  ARGF.next_p = -1;
8625  }
8626  ARGF.init_p = 1;
8627  }
8628  else {
8629  if (NIL_P(ARGF.argv)) {
8630  ARGF.next_p = -1;
8631  }
8632  else if (ARGF.next_p == -1 && RARRAY_LEN(ARGF.argv) > 0) {
8633  ARGF.next_p = 1;
8634  }
8635  }
8636 
8637  if (ARGF.next_p == 1) {
8638  if (ARGF.init_p == 1) argf_close(argf);
8639  retry:
8640  if (RARRAY_LEN(ARGF.argv) > 0) {
8641  VALUE filename = rb_ary_shift(ARGF.argv);
8643  ARGF.filename = filename;
8645  fn = StringValueCStr(filename);
8646  if (RSTRING_LEN(filename) == 1 && fn[0] == '-') {
8647  ARGF.current_file = rb_stdin;
8648  if (ARGF.inplace) {
8649  rb_warn("Can't do inplace edit for stdio; skipping");
8650  goto retry;
8651  }
8652  }
8653  else {
8654  VALUE write_io = Qnil;
8655  int fr = rb_sysopen(filename, O_RDONLY, 0);
8656 
8657  if (ARGF.inplace) {
8658  struct stat st;
8659 #ifndef NO_SAFE_RENAME
8660  struct stat st2;
8661 #endif
8662  VALUE str;
8663  int fw;
8664 
8665  if (RB_TYPE_P(rb_stdout, T_FILE) && rb_stdout != orig_stdout) {
8667  }
8668  fstat(fr, &st);
8669  str = filename;
8670  if (!NIL_P(ARGF.inplace)) {
8671  VALUE suffix = ARGF.inplace;
8672  str = rb_str_dup(str);
8674  RSTRING_PTR(suffix), RSTRING_LEN(suffix),
8675  rb_enc_get(suffix), 0, Qnil))) {
8676  rb_str_append(str, suffix);
8677  }
8678 #ifdef NO_SAFE_RENAME
8679  (void)close(fr);
8680  (void)unlink(RSTRING_PTR(str));
8681  if (rename(fn, RSTRING_PTR(str)) < 0) {
8682  rb_warn("Can't rename %"PRIsVALUE" to %"PRIsVALUE": %s, skipping file",
8683  filename, str, strerror(errno));
8684  goto retry;
8685  }
8686  fr = rb_sysopen(str, O_RDONLY, 0);
8687 #else
8688  if (rename(fn, RSTRING_PTR(str)) < 0) {
8689  rb_warn("Can't rename %"PRIsVALUE" to %"PRIsVALUE": %s, skipping file",
8690  filename, str, strerror(errno));
8691  close(fr);
8692  goto retry;
8693  }
8694 #endif
8695  }
8696  else {
8697 #ifdef NO_SAFE_RENAME
8698  rb_fatal("Can't do inplace edit without backup");
8699 #else
8700  if (unlink(fn) < 0) {
8701  rb_warn("Can't remove %"PRIsVALUE": %s, skipping file",
8702  filename, strerror(errno));
8703  close(fr);
8704  goto retry;
8705  }
8706 #endif
8707  }
8708  fw = rb_sysopen(filename, O_WRONLY|O_CREAT|O_TRUNC, 0666);
8709 #ifndef NO_SAFE_RENAME
8710  fstat(fw, &st2);
8711 #ifdef HAVE_FCHMOD
8712  fchmod(fw, st.st_mode);
8713 #else
8714  chmod(fn, st.st_mode);
8715 #endif
8716  if (st.st_uid!=st2.st_uid || st.st_gid!=st2.st_gid) {
8717  int err;
8718 #ifdef HAVE_FCHOWN
8719  err = fchown(fw, st.st_uid, st.st_gid);
8720 #else
8721  err = chown(fn, st.st_uid, st.st_gid);
8722 #endif
8723  if (err && getuid() == 0 && st2.st_uid == 0) {
8724  const char *wkfn = RSTRING_PTR(filename);
8725  rb_warn("Can't set owner/group of %"PRIsVALUE" to same as %"PRIsVALUE": %s, skipping file",
8726  filename, str, strerror(errno));
8727  (void)close(fr);
8728  (void)close(fw);
8729  (void)unlink(wkfn);
8730  goto retry;
8731  }
8732  }
8733 #endif
8734  write_io = prep_io(fw, FMODE_WRITABLE, rb_cFile, fn);
8735  rb_stdout = write_io;
8736  if (stdout_binmode) rb_io_binmode(rb_stdout);
8737  }
8739  if (!ARGF.binmode) {
8741  }
8742  ARGF.current_file = prep_io(fr, fmode, rb_cFile, fn);
8743  if (!NIL_P(write_io)) {
8744  rb_io_set_write_io(ARGF.current_file, write_io);
8745  }
8746  RB_GC_GUARD(filename);
8747  }
8748  if (ARGF.binmode) rb_io_ascii8bit_binmode(ARGF.current_file);
8749  GetOpenFile(ARGF.current_file, fptr);
8750  if (ARGF.encs.enc) {
8751  fptr->encs = ARGF.encs;
8752  clear_codeconv(fptr);
8753  }
8754  else {
8756  if (!ARGF.binmode) {
8758 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
8759  fptr->encs.ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
8760 #endif
8761  }
8762  }
8763  ARGF.next_p = 0;
8764  }
8765  else {
8766  ARGF.next_p = 1;
8767  return FALSE;
8768  }
8769  }
8770  else if (ARGF.next_p == -1) {
8771  ARGF.current_file = rb_stdin;
8772  ARGF.filename = rb_str_new2("-");
8773  if (ARGF.inplace) {
8774  rb_warn("Can't do inplace edit for stdio");
8775  rb_stdout = orig_stdout;
8776  }
8777  }
8778  if (ARGF.init_p == -1) ARGF.init_p = 1;
8779  return TRUE;
8780 }
8781 
8782 static VALUE
8783 argf_getline(int argc, VALUE *argv, VALUE argf)
8784 {
8785  VALUE line;
8786  long lineno = ARGF.lineno;
8787 
8788  retry:
8789  if (!next_argv()) return Qnil;
8790  if (ARGF_GENERIC_INPUT_P()) {
8791  line = rb_funcall3(ARGF.current_file, idGets, argc, argv);
8792  }
8793  else {
8794  if (argc == 0 && rb_rs == rb_default_rs) {
8795  line = rb_io_gets(ARGF.current_file);
8796  }
8797  else {
8798  line = rb_io_getline(argc, argv, ARGF.current_file);
8799  }
8800  if (NIL_P(line) && ARGF.next_p != -1) {
8801  argf_close(argf);
8802  ARGF.next_p = 1;
8803  goto retry;
8804  }
8805  }
8806  if (!NIL_P(line)) {
8807  ARGF.lineno = ++lineno;
8808  ARGF.last_lineno = ARGF.lineno;
8809  }
8810  return line;
8811 }
8812 
8813 static VALUE
8814 argf_lineno_getter(ID id, VALUE *var)
8815 {
8816  VALUE argf = *var;
8817  return INT2FIX(ARGF.last_lineno);
8818 }
8819 
8820 static void
8821 argf_lineno_setter(VALUE val, ID id, VALUE *var)
8822 {
8823  VALUE argf = *var;
8824  int n = NUM2INT(val);
8825  ARGF.last_lineno = ARGF.lineno = n;
8826 }
8827 
8828 static VALUE argf_gets(int, VALUE *, VALUE);
8829 
8830 /*
8831  * call-seq:
8832  * gets(sep=$/ [, getline_args]) -> string or nil
8833  * gets(limit [, getline_args]) -> string or nil
8834  * gets(sep, limit [, getline_args]) -> string or nil
8835  *
8836  * Returns (and assigns to <code>$_</code>) the next line from the list
8837  * of files in +ARGV+ (or <code>$*</code>), or from standard input if
8838  * no files are present on the command line. Returns +nil+ at end of
8839  * file. The optional argument specifies the record separator. The
8840  * separator is included with the contents of each record. A separator
8841  * of +nil+ reads the entire contents, and a zero-length separator
8842  * reads the input one paragraph at a time, where paragraphs are
8843  * divided by two consecutive newlines. If the first argument is an
8844  * integer, or optional second argument is given, the returning string
8845  * would not be longer than the given value in bytes. If multiple
8846  * filenames are present in +ARGV+, <code>gets(nil)</code> will read
8847  * the contents one file at a time.
8848  *
8849  * ARGV << "testfile"
8850  * print while gets
8851  *
8852  * <em>produces:</em>
8853  *
8854  * This is line one
8855  * This is line two
8856  * This is line three
8857  * And so on...
8858  *
8859  * The style of programming using <code>$_</code> as an implicit
8860  * parameter is gradually losing favor in the Ruby community.
8861  */
8862 
8863 static VALUE
8864 rb_f_gets(int argc, VALUE *argv, VALUE recv)
8865 {
8866  if (recv == argf) {
8867  return argf_gets(argc, argv, argf);
8868  }
8869  return rb_funcallv(argf, idGets, argc, argv);
8870 }
8871 
8872 /*
8873  * call-seq:
8874  * ARGF.gets(sep=$/ [, getline_args]) -> string or nil
8875  * ARGF.gets(limit [, getline_args]) -> string or nil
8876  * ARGF.gets(sep, limit [, getline_args]) -> string or nil
8877  *
8878  * Returns the next line from the current file in +ARGF+.
8879  *
8880  * By default lines are assumed to be separated by <code>$/</code>;
8881  * to use a different character as a separator, supply it as a +String+
8882  * for the _sep_ argument.
8883  *
8884  * The optional _limit_ argument specifies how many characters of each line
8885  * to return. By default all characters are returned.
8886  *
8887  * See IO.readlines for details about getline_args.
8888  *
8889  */
8890 static VALUE
8891 argf_gets(int argc, VALUE *argv, VALUE argf)
8892 {
8893  VALUE line;
8894 
8895  line = argf_getline(argc, argv, argf);
8896  rb_lastline_set(line);
8897 
8898  return line;
8899 }
8900 
8901 VALUE
8902 rb_gets(void)
8903 {
8904  VALUE line;
8905 
8906  if (rb_rs != rb_default_rs) {
8907  return rb_f_gets(0, 0, argf);
8908  }
8909 
8910  retry:
8911  if (!next_argv()) return Qnil;
8912  line = rb_io_gets(ARGF.current_file);
8913  if (NIL_P(line) && ARGF.next_p != -1) {
8914  rb_io_close(ARGF.current_file);
8915  ARGF.next_p = 1;
8916  goto retry;
8917  }
8918  rb_lastline_set(line);
8919  if (!NIL_P(line)) {
8920  ARGF.lineno++;
8921  ARGF.last_lineno = ARGF.lineno;
8922  }
8923 
8924  return line;
8925 }
8926 
8927 static VALUE argf_readline(int, VALUE *, VALUE);
8928 
8929 /*
8930  * call-seq:
8931  * readline(sep=$/) -> string
8932  * readline(limit) -> string
8933  * readline(sep, limit) -> string
8934  *
8935  * Equivalent to Kernel::gets, except
8936  * +readline+ raises +EOFError+ at end of file.
8937  */
8938 
8939 static VALUE
8940 rb_f_readline(int argc, VALUE *argv, VALUE recv)
8941 {
8942  if (recv == argf) {
8943  return argf_readline(argc, argv, argf);
8944  }
8945  return rb_funcallv(argf, rb_intern("readline"), argc, argv);
8946 }
8947 
8948 
8949 /*
8950  * call-seq:
8951  * ARGF.readline(sep=$/) -> string
8952  * ARGF.readline(limit) -> string
8953  * ARGF.readline(sep, limit) -> string
8954  *
8955  * Returns the next line from the current file in +ARGF+.
8956  *
8957  * By default lines are assumed to be separated by <code>$/</code>;
8958  * to use a different character as a separator, supply it as a +String+
8959  * for the _sep_ argument.
8960  *
8961  * The optional _limit_ argument specifies how many characters of each line
8962  * to return. By default all characters are returned.
8963  *
8964  * An +EOFError+ is raised at the end of the file.
8965  */
8966 static VALUE
8967 argf_readline(int argc, VALUE *argv, VALUE argf)
8968 {
8969  VALUE line;
8970 
8971  if (!next_argv()) rb_eof_error();
8973  line = argf_gets(argc, argv, argf);
8974  if (NIL_P(line)) {
8975  rb_eof_error();
8976  }
8977 
8978  return line;
8979 }
8980 
8981 static VALUE argf_readlines(int, VALUE *, VALUE);
8982 
8983 /*
8984  * call-seq:
8985  * readlines(sep=$/) -> array
8986  * readlines(limit) -> array
8987  * readlines(sep, limit) -> array
8988  *
8989  * Returns an array containing the lines returned by calling
8990  * <code>Kernel.gets(<i>sep</i>)</code> until the end of file.
8991  */
8992 
8993 static VALUE
8994 rb_f_readlines(int argc, VALUE *argv, VALUE recv)
8995 {
8996  if (recv == argf) {
8997  return argf_readlines(argc, argv, argf);
8998  }
8999  return rb_funcallv(argf, rb_intern("readlines"), argc, argv);
9000 }
9001 
9002 /*
9003  * call-seq:
9004  * ARGF.readlines(sep=$/) -> array
9005  * ARGF.readlines(limit) -> array
9006  * ARGF.readlines(sep, limit) -> array
9007  *
9008  * ARGF.to_a(sep=$/) -> array
9009  * ARGF.to_a(limit) -> array
9010  * ARGF.to_a(sep, limit) -> array
9011  *
9012  * Reads +ARGF+'s current file in its entirety, returning an +Array+ of its
9013  * lines, one line per element. Lines are assumed to be separated by _sep_.
9014  *
9015  * lines = ARGF.readlines
9016  * lines[0] #=> "This is line one\n"
9017  */
9018 static VALUE
9019 argf_readlines(int argc, VALUE *argv, VALUE argf)
9020 {
9021  long lineno = ARGF.lineno;
9022  VALUE lines, ary;
9023 
9024  ary = rb_ary_new();
9025  while (next_argv()) {
9026  if (ARGF_GENERIC_INPUT_P()) {
9027  lines = rb_funcall3(ARGF.current_file, rb_intern("readlines"), argc, argv);
9028  }
9029  else {
9030  lines = rb_io_readlines(argc, argv, ARGF.current_file);
9031  argf_close(argf);
9032  }
9033  ARGF.next_p = 1;
9034  rb_ary_concat(ary, lines);
9035  ARGF.lineno = lineno + RARRAY_LEN(ary);
9036  ARGF.last_lineno = ARGF.lineno;
9037  }
9038  ARGF.init_p = 0;
9039  return ary;
9040 }
9041 
9042 /*
9043  * call-seq:
9044  * `cmd` -> string
9045  *
9046  * Returns the standard output of running _cmd_ in a subshell.
9047  * The built-in syntax <code>%x{...}</code> uses
9048  * this method. Sets <code>$?</code> to the process status.
9049  *
9050  * `date` #=> "Wed Apr 9 08:56:30 CDT 2003\n"
9051  * `ls testdir`.split[1] #=> "main.rb"
9052  * `echo oops && exit 99` #=> "oops\n"
9053  * $?.exitstatus #=> 99
9054  */
9055 
9056 static VALUE
9057 rb_f_backquote(VALUE obj, VALUE str)
9058 {
9059  VALUE port;
9060  VALUE result;
9061  rb_io_t *fptr;
9062 
9065  port = pipe_open_s(str, "r", FMODE_READABLE|DEFAULT_TEXTMODE, NULL);
9066  if (NIL_P(port)) return rb_str_new(0,0);
9067 
9068  GetOpenFile(port, fptr);
9069  result = read_all(fptr, remain_size(fptr), Qnil);
9070  rb_io_close(port);
9071  RFILE(port)->fptr = NULL;
9072  rb_io_fptr_finalize(fptr);
9073  rb_gc_force_recycle(port); /* also guards from premature GC */
9074 
9075  return result;
9076 }
9077 
9078 #ifdef HAVE_SYS_SELECT_H
9079 #include <sys/select.h>
9080 #endif
9081 
9082 static VALUE
9083 select_internal(VALUE read, VALUE write, VALUE except, struct timeval *tp, rb_fdset_t *fds)
9084 {
9085  VALUE res, list;
9086  rb_fdset_t *rp, *wp, *ep;
9087  rb_io_t *fptr;
9088  long i;
9089  int max = 0, n;
9090  int pending = 0;
9091  struct timeval timerec;
9092 
9093  if (!NIL_P(read)) {
9094  Check_Type(read, T_ARRAY);
9095  for (i=0; i<RARRAY_LEN(read); i++) {
9096  GetOpenFile(rb_io_get_io(RARRAY_AREF(read, i)), fptr);
9097  rb_fd_set(fptr->fd, &fds[0]);
9098  if (READ_DATA_PENDING(fptr) || READ_CHAR_PENDING(fptr)) { /* check for buffered data */
9099  pending++;
9100  rb_fd_set(fptr->fd, &fds[3]);
9101  }
9102  if (max < fptr->fd) max = fptr->fd;
9103  }
9104  if (pending) { /* no blocking if there's buffered data */
9105  timerec.tv_sec = timerec.tv_usec = 0;
9106  tp = &timerec;
9107  }
9108  rp = &fds[0];
9109  }
9110  else
9111  rp = 0;
9112 
9113  if (!NIL_P(write)) {
9114  Check_Type(write, T_ARRAY);
9115  for (i=0; i<RARRAY_LEN(write); i++) {
9116  VALUE write_io = GetWriteIO(rb_io_get_io(RARRAY_AREF(write, i)));
9117  GetOpenFile(write_io, fptr);
9118  rb_fd_set(fptr->fd, &fds[1]);
9119  if (max < fptr->fd) max = fptr->fd;
9120  }
9121  wp = &fds[1];
9122  }
9123  else
9124  wp = 0;
9125 
9126  if (!NIL_P(except)) {
9127  Check_Type(except, T_ARRAY);
9128  for (i=0; i<RARRAY_LEN(except); i++) {
9129  VALUE io = rb_io_get_io(RARRAY_AREF(except, i));
9130  VALUE write_io = GetWriteIO(io);
9131  GetOpenFile(io, fptr);
9132  rb_fd_set(fptr->fd, &fds[2]);
9133  if (max < fptr->fd) max = fptr->fd;
9134  if (io != write_io) {
9135  GetOpenFile(write_io, fptr);
9136  rb_fd_set(fptr->fd, &fds[2]);
9137  if (max < fptr->fd) max = fptr->fd;
9138  }
9139  }
9140  ep = &fds[2];
9141  }
9142  else {
9143  ep = 0;
9144  }
9145 
9146  max++;
9147 
9148  n = rb_thread_fd_select(max, rp, wp, ep, tp);
9149  if (n < 0) {
9150  rb_sys_fail(0);
9151  }
9152  if (!pending && n == 0) return Qnil; /* returns nil on timeout */
9153 
9154  res = rb_ary_new2(3);
9155  rb_ary_push(res, rp?rb_ary_new():rb_ary_new2(0));
9156  rb_ary_push(res, wp?rb_ary_new():rb_ary_new2(0));
9157  rb_ary_push(res, ep?rb_ary_new():rb_ary_new2(0));
9158 
9159  if (rp) {
9160  list = RARRAY_AREF(res, 0);
9161  for (i=0; i< RARRAY_LEN(read); i++) {
9162  VALUE obj = rb_ary_entry(read, i);
9163  VALUE io = rb_io_get_io(obj);
9164  GetOpenFile(io, fptr);
9165  if (rb_fd_isset(fptr->fd, &fds[0]) ||
9166  rb_fd_isset(fptr->fd, &fds[3])) {
9167  rb_ary_push(list, obj);
9168  }
9169  }
9170  }
9171 
9172  if (wp) {
9173  list = RARRAY_AREF(res, 1);
9174  for (i=0; i< RARRAY_LEN(write); i++) {
9175  VALUE obj = rb_ary_entry(write, i);
9176  VALUE io = rb_io_get_io(obj);
9177  VALUE write_io = GetWriteIO(io);
9178  GetOpenFile(write_io, fptr);
9179  if (rb_fd_isset(fptr->fd, &fds[1])) {
9180  rb_ary_push(list, obj);
9181  }
9182  }
9183  }
9184 
9185  if (ep) {
9186  list = RARRAY_AREF(res, 2);
9187  for (i=0; i< RARRAY_LEN(except); i++) {
9188  VALUE obj = rb_ary_entry(except, i);
9189  VALUE io = rb_io_get_io(obj);
9190  VALUE write_io = GetWriteIO(io);
9191  GetOpenFile(io, fptr);
9192  if (rb_fd_isset(fptr->fd, &fds[2])) {
9193  rb_ary_push(list, obj);
9194  }
9195  else if (io != write_io) {
9196  GetOpenFile(write_io, fptr);
9197  if (rb_fd_isset(fptr->fd, &fds[2])) {
9198  rb_ary_push(list, obj);
9199  }
9200  }
9201  }
9202  }
9203 
9204  return res; /* returns an empty array on interrupt */
9205 }
9206 
9207 struct select_args {
9209  struct timeval *timeout;
9211 };
9212 
9213 static VALUE
9214 select_call(VALUE arg)
9215 {
9216  struct select_args *p = (struct select_args *)arg;
9217 
9218  return select_internal(p->read, p->write, p->except, p->timeout, p->fdsets);
9219 }
9220 
9221 static VALUE
9222 select_end(VALUE arg)
9223 {
9224  struct select_args *p = (struct select_args *)arg;
9225  int i;
9226 
9227  for (i = 0; i < numberof(p->fdsets); ++i)
9228  rb_fd_term(&p->fdsets[i]);
9229  return Qnil;
9230 }
9231 
9232 static VALUE sym_normal, sym_sequential, sym_random,
9233  sym_willneed, sym_dontneed, sym_noreuse;
9234 
9235 #ifdef HAVE_POSIX_FADVISE
9236 struct io_advise_struct {
9237  int fd;
9238  int advice;
9239  off_t offset;
9240  off_t len;
9241 };
9242 
9243 static VALUE
9244 io_advise_internal(void *arg)
9245 {
9246  struct io_advise_struct *ptr = arg;
9247  return posix_fadvise(ptr->fd, ptr->offset, ptr->len, ptr->advice);
9248 }
9249 
9250 static VALUE
9251 io_advise_sym_to_const(VALUE sym)
9252 {
9253 #ifdef POSIX_FADV_NORMAL
9254  if (sym == sym_normal)
9255  return INT2NUM(POSIX_FADV_NORMAL);
9256 #endif
9257 
9258 #ifdef POSIX_FADV_RANDOM
9259  if (sym == sym_random)
9260  return INT2NUM(POSIX_FADV_RANDOM);
9261 #endif
9262 
9263 #ifdef POSIX_FADV_SEQUENTIAL
9264  if (sym == sym_sequential)
9265  return INT2NUM(POSIX_FADV_SEQUENTIAL);
9266 #endif
9267 
9268 #ifdef POSIX_FADV_WILLNEED
9269  if (sym == sym_willneed)
9270  return INT2NUM(POSIX_FADV_WILLNEED);
9271 #endif
9272 
9273 #ifdef POSIX_FADV_DONTNEED
9274  if (sym == sym_dontneed)
9275  return INT2NUM(POSIX_FADV_DONTNEED);
9276 #endif
9277 
9278 #ifdef POSIX_FADV_NOREUSE
9279  if (sym == sym_noreuse)
9280  return INT2NUM(POSIX_FADV_NOREUSE);
9281 #endif
9282 
9283  return Qnil;
9284 }
9285 
9286 static VALUE
9287 do_io_advise(rb_io_t *fptr, VALUE advice, off_t offset, off_t len)
9288 {
9289  int rv;
9290  struct io_advise_struct ias;
9291  VALUE num_adv;
9292 
9293  num_adv = io_advise_sym_to_const(advice);
9294 
9295  /*
9296  * The platform doesn't support this hint. We don't raise exception, instead
9297  * silently ignore it. Because IO::advise is only hint.
9298  */
9299  if (NIL_P(num_adv))
9300  return Qnil;
9301 
9302  ias.fd = fptr->fd;
9303  ias.advice = NUM2INT(num_adv);
9304  ias.offset = offset;
9305  ias.len = len;
9306 
9307  rv = (int)rb_thread_io_blocking_region(io_advise_internal, &ias, fptr->fd);
9308  if (rv && rv != ENOSYS) {
9309  /* posix_fadvise(2) doesn't set errno. On success it returns 0; otherwise
9310  it returns the error code. */
9311  VALUE message = rb_sprintf("%"PRIsVALUE" "
9312  "(%"PRI_OFFT_PREFIX"d, "
9313  "%"PRI_OFFT_PREFIX"d, "
9314  "%"PRIsVALUE")",
9315  fptr->pathv, offset, len, advice);
9316  rb_syserr_fail_str(rv, message);
9317  }
9318 
9319  return Qnil;
9320 }
9321 
9322 #endif /* HAVE_POSIX_FADVISE */
9323 
9324 static void
9325 advice_arg_check(VALUE advice)
9326 {
9327  if (!SYMBOL_P(advice))
9328  rb_raise(rb_eTypeError, "advice must be a Symbol");
9329 
9330  if (advice != sym_normal &&
9331  advice != sym_sequential &&
9332  advice != sym_random &&
9333  advice != sym_willneed &&
9334  advice != sym_dontneed &&
9335  advice != sym_noreuse) {
9336  rb_raise(rb_eNotImpError, "Unsupported advice: %+"PRIsVALUE, advice);
9337  }
9338 }
9339 
9340 /*
9341  * call-seq:
9342  * ios.advise(advice, offset=0, len=0) -> nil
9343  *
9344  * Announce an intention to access data from the current file in a
9345  * specific pattern. On platforms that do not support the
9346  * <em>posix_fadvise(2)</em> system call, this method is a no-op.
9347  *
9348  * _advice_ is one of the following symbols:
9349  *
9350  * :normal:: No advice to give; the default assumption for an open file.
9351  * :sequential:: The data will be accessed sequentially
9352  * with lower offsets read before higher ones.
9353  * :random:: The data will be accessed in random order.
9354  * :willneed:: The data will be accessed in the near future.
9355  * :dontneed:: The data will not be accessed in the near future.
9356  * :noreuse:: The data will only be accessed once.
9357  *
9358  * The semantics of a piece of advice are platform-dependent. See
9359  * <em>man 2 posix_fadvise</em> for details.
9360  *
9361  * "data" means the region of the current file that begins at
9362  * _offset_ and extends for _len_ bytes. If _len_ is 0, the region
9363  * ends at the last byte of the file. By default, both _offset_ and
9364  * _len_ are 0, meaning that the advice applies to the entire file.
9365  *
9366  * If an error occurs, one of the following exceptions will be raised:
9367  *
9368  * IOError:: The IO stream is closed.
9369  * Errno::EBADF::
9370  * The file descriptor of the current file is invalid.
9371  * Errno::EINVAL:: An invalid value for _advice_ was given.
9372  * Errno::ESPIPE::
9373  * The file descriptor of the current file refers to a FIFO or
9374  * pipe. (Linux raises Errno::EINVAL in this case).
9375  * TypeError::
9376  * Either _advice_ was not a Symbol, or one of the
9377  * other arguments was not an Integer.
9378  * RangeError:: One of the arguments given was too big/small.
9379  *
9380  * This list is not exhaustive; other Errno:: exceptions are also possible.
9381  */
9382 static VALUE
9383 rb_io_advise(int argc, VALUE *argv, VALUE io)
9384 {
9385  VALUE advice, offset, len;
9386  off_t off, l;
9387  rb_io_t *fptr;
9388 
9389  rb_scan_args(argc, argv, "12", &advice, &offset, &len);
9390  advice_arg_check(advice);
9391 
9392  io = GetWriteIO(io);
9393  GetOpenFile(io, fptr);
9394 
9395  off = NIL_P(offset) ? 0 : NUM2OFFT(offset);
9396  l = NIL_P(len) ? 0 : NUM2OFFT(len);
9397 
9398 #ifdef HAVE_POSIX_FADVISE
9399  return do_io_advise(fptr, advice, off, l);
9400 #else
9401  ((void)off, (void)l); /* Ignore all hint */
9402  return Qnil;
9403 #endif
9404 }
9405 
9406 /*
9407  * call-seq:
9408  * IO.select(read_array [, write_array [, error_array [, timeout]]]) -> array or nil
9409  *
9410  * Calls select(2) system call.
9411  * It monitors given arrays of IO objects, waits until one or more of
9412  * IO objects are ready for reading, are ready for writing, and have
9413  * pending exceptions respectively, and returns an array that contains
9414  * arrays of those IO objects. It will return +nil+ if optional
9415  * <i>timeout</i> value is given and no IO object is ready in
9416  * <i>timeout</i> seconds.
9417  *
9418  * IO.select peeks the buffer of IO objects for testing readability.
9419  * If the IO buffer is not empty, IO.select immediately notifies
9420  * readability. This "peek" only happens for IO objects. It does not
9421  * happen for IO-like objects such as OpenSSL::SSL::SSLSocket.
9422  *
9423  * The best way to use IO.select is invoking it after nonblocking
9424  * methods such as #read_nonblock, #write_nonblock, etc. The methods
9425  * raise an exception which is extended by IO::WaitReadable or
9426  * IO::WaitWritable. The modules notify how the caller should wait
9427  * with IO.select. If IO::WaitReadable is raised, the caller should
9428  * wait for reading. If IO::WaitWritable is raised, the caller should
9429  * wait for writing.
9430  *
9431  * So, blocking read (#readpartial) can be emulated using
9432  * #read_nonblock and IO.select as follows:
9433  *
9434  * begin
9435  * result = io_like.read_nonblock(maxlen)
9436  * rescue IO::WaitReadable
9437  * IO.select([io_like])
9438  * retry
9439  * rescue IO::WaitWritable
9440  * IO.select(nil, [io_like])
9441  * retry
9442  * end
9443  *
9444  * Especially, the combination of nonblocking methods and IO.select is
9445  * preferred for IO like objects such as OpenSSL::SSL::SSLSocket. It
9446  * has #to_io method to return underlying IO object. IO.select calls
9447  * #to_io to obtain the file descriptor to wait.
9448  *
9449  * This means that readability notified by IO.select doesn't mean
9450  * readability from OpenSSL::SSL::SSLSocket object.
9451  *
9452  * The most likely situation is that OpenSSL::SSL::SSLSocket buffers
9453  * some data. IO.select doesn't see the buffer. So IO.select can
9454  * block when OpenSSL::SSL::SSLSocket#readpartial doesn't block.
9455  *
9456  * However, several more complicated situations exist.
9457  *
9458  * SSL is a protocol which is sequence of records.
9459  * The record consists of multiple bytes.
9460  * So, the remote side of SSL sends a partial record, IO.select
9461  * notifies readability but OpenSSL::SSL::SSLSocket cannot decrypt a
9462  * byte and OpenSSL::SSL::SSLSocket#readpartial will block.
9463  *
9464  * Also, the remote side can request SSL renegotiation which forces
9465  * the local SSL engine to write some data.
9466  * This means OpenSSL::SSL::SSLSocket#readpartial may invoke #write
9467  * system call and it can block.
9468  * In such a situation, OpenSSL::SSL::SSLSocket#read_nonblock raises
9469  * IO::WaitWritable instead of blocking.
9470  * So, the caller should wait for ready for writability as above
9471  * example.
9472  *
9473  * The combination of nonblocking methods and IO.select is also useful
9474  * for streams such as tty, pipe socket socket when multiple processes
9475  * read from a stream.
9476  *
9477  * Finally, Linux kernel developers don't guarantee that
9478  * readability of select(2) means readability of following read(2) even
9479  * for a single process.
9480  * See select(2) manual on GNU/Linux system.
9481  *
9482  * Invoking IO.select before IO#readpartial works well as usual.
9483  * However it is not the best way to use IO.select.
9484  *
9485  * The writability notified by select(2) doesn't show
9486  * how many bytes are writable.
9487  * IO#write method blocks until given whole string is written.
9488  * So, <code>IO#write(two or more bytes)</code> can block after
9489  * writability is notified by IO.select. IO#write_nonblock is required
9490  * to avoid the blocking.
9491  *
9492  * Blocking write (#write) can be emulated using #write_nonblock and
9493  * IO.select as follows: IO::WaitReadable should also be rescued for
9494  * SSL renegotiation in OpenSSL::SSL::SSLSocket.
9495  *
9496  * while 0 < string.bytesize
9497  * begin
9498  * written = io_like.write_nonblock(string)
9499  * rescue IO::WaitReadable
9500  * IO.select([io_like])
9501  * retry
9502  * rescue IO::WaitWritable
9503  * IO.select(nil, [io_like])
9504  * retry
9505  * end
9506  * string = string.byteslice(written..-1)
9507  * end
9508  *
9509  * === Parameters
9510  * read_array:: an array of IO objects that wait until ready for read
9511  * write_array:: an array of IO objects that wait until ready for write
9512  * error_array:: an array of IO objects that wait for exceptions
9513  * timeout:: a numeric value in second
9514  *
9515  * === Example
9516  *
9517  * rp, wp = IO.pipe
9518  * mesg = "ping "
9519  * 100.times {
9520  * # IO.select follows IO#read. Not the best way to use IO.select.
9521  * rs, ws, = IO.select([rp], [wp])
9522  * if r = rs[0]
9523  * ret = r.read(5)
9524  * print ret
9525  * case ret
9526  * when /ping/
9527  * mesg = "pong\n"
9528  * when /pong/
9529  * mesg = "ping "
9530  * end
9531  * end
9532  * if w = ws[0]
9533  * w.write(mesg)
9534  * end
9535  * }
9536  *
9537  * <em>produces:</em>
9538  *
9539  * ping pong
9540  * ping pong
9541  * ping pong
9542  * (snipped)
9543  * ping
9544  */
9545 
9546 static VALUE
9547 rb_f_select(int argc, VALUE *argv, VALUE obj)
9548 {
9549  VALUE timeout;
9550  struct select_args args;
9551  struct timeval timerec;
9552  int i;
9553 
9554  rb_scan_args(argc, argv, "13", &args.read, &args.write, &args.except, &timeout);
9555  if (NIL_P(timeout)) {
9556  args.timeout = 0;
9557  }
9558  else {
9559  timerec = rb_time_interval(timeout);
9560  args.timeout = &timerec;
9561  }
9562 
9563  for (i = 0; i < numberof(args.fdsets); ++i)
9564  rb_fd_init(&args.fdsets[i]);
9565 
9566  return rb_ensure(select_call, (VALUE)&args, select_end, (VALUE)&args);
9567 }
9568 
9569 #if (defined(__linux__) && !defined(__ANDROID__)) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
9570  typedef unsigned long ioctl_req_t;
9571 # define NUM2IOCTLREQ(num) NUM2ULONG(num)
9572 #else
9573  typedef int ioctl_req_t;
9574 # define NUM2IOCTLREQ(num) ((int)NUM2LONG(num))
9575 #endif
9576 
9577 #ifdef HAVE_IOCTL
9578 struct ioctl_arg {
9579  int fd;
9580  ioctl_req_t cmd;
9581  long narg;
9582 };
9583 
9584 static VALUE
9585 nogvl_ioctl(void *ptr)
9586 {
9587  struct ioctl_arg *arg = ptr;
9588 
9589  return (VALUE)ioctl(arg->fd, arg->cmd, arg->narg);
9590 }
9591 
9592 static int
9593 do_ioctl(int fd, ioctl_req_t cmd, long narg)
9594 {
9595  int retval;
9596  struct ioctl_arg arg;
9597 
9598  arg.fd = fd;
9599  arg.cmd = cmd;
9600  arg.narg = narg;
9601 
9602  retval = (int)rb_thread_io_blocking_region(nogvl_ioctl, &arg, fd);
9603 
9604  return retval;
9605 }
9606 #endif
9607 
9608 #define DEFULT_IOCTL_NARG_LEN (256)
9609 
9610 #if defined(__linux__) && defined(_IOC_SIZE)
9611 static long
9612 linux_iocparm_len(ioctl_req_t cmd)
9613 {
9614  long len;
9615 
9616  if ((cmd & 0xFFFF0000) == 0) {
9617  /* legacy and unstructured ioctl number. */
9618  return DEFULT_IOCTL_NARG_LEN;
9619  }
9620 
9621  len = _IOC_SIZE(cmd);
9622 
9623  /* paranoia check for silly drivers which don't keep ioctl convention */
9624  if (len < DEFULT_IOCTL_NARG_LEN)
9626 
9627  return len;
9628 }
9629 #endif
9630 
9631 static long
9632 ioctl_narg_len(ioctl_req_t cmd)
9633 {
9634  long len;
9635 
9636 #ifdef IOCPARM_MASK
9637 #ifndef IOCPARM_LEN
9638 #define IOCPARM_LEN(x) (((x) >> 16) & IOCPARM_MASK)
9639 #endif
9640 #endif
9641 #ifdef IOCPARM_LEN
9642  len = IOCPARM_LEN(cmd); /* on BSDish systems we're safe */
9643 #elif defined(__linux__) && defined(_IOC_SIZE)
9644  len = linux_iocparm_len(cmd);
9645 #else
9646  /* otherwise guess at what's safe */
9648 #endif
9649 
9650  return len;
9651 }
9652 
9653 #ifdef HAVE_FCNTL
9654 #ifdef __linux__
9655 typedef long fcntl_arg_t;
9656 #else
9657 /* posix */
9658 typedef int fcntl_arg_t;
9659 #endif
9660 
9661 static long
9662 fcntl_narg_len(int cmd)
9663 {
9664  long len;
9665 
9666  switch (cmd) {
9667 #ifdef F_DUPFD
9668  case F_DUPFD:
9669  len = sizeof(fcntl_arg_t);
9670  break;
9671 #endif
9672 #ifdef F_DUP2FD /* bsd specific */
9673  case F_DUP2FD:
9674  len = sizeof(int);
9675  break;
9676 #endif
9677 #ifdef F_DUPFD_CLOEXEC /* linux specific */
9678  case F_DUPFD_CLOEXEC:
9679  len = sizeof(fcntl_arg_t);
9680  break;
9681 #endif
9682 #ifdef F_GETFD
9683  case F_GETFD:
9684  len = 1;
9685  break;
9686 #endif
9687 #ifdef F_SETFD
9688  case F_SETFD:
9689  len = sizeof(fcntl_arg_t);
9690  break;
9691 #endif
9692 #ifdef F_GETFL
9693  case F_GETFL:
9694  len = 1;
9695  break;
9696 #endif
9697 #ifdef F_SETFL
9698  case F_SETFL:
9699  len = sizeof(fcntl_arg_t);
9700  break;
9701 #endif
9702 #ifdef F_GETOWN
9703  case F_GETOWN:
9704  len = 1;
9705  break;
9706 #endif
9707 #ifdef F_SETOWN
9708  case F_SETOWN:
9709  len = sizeof(fcntl_arg_t);
9710  break;
9711 #endif
9712 #ifdef F_GETOWN_EX /* linux specific */
9713  case F_GETOWN_EX:
9714  len = sizeof(struct f_owner_ex);
9715  break;
9716 #endif
9717 #ifdef F_SETOWN_EX /* linux specific */
9718  case F_SETOWN_EX:
9719  len = sizeof(struct f_owner_ex);
9720  break;
9721 #endif
9722 #ifdef F_GETLK
9723  case F_GETLK:
9724  len = sizeof(struct flock);
9725  break;
9726 #endif
9727 #ifdef F_SETLK
9728  case F_SETLK:
9729  len = sizeof(struct flock);
9730  break;
9731 #endif
9732 #ifdef F_SETLKW
9733  case F_SETLKW:
9734  len = sizeof(struct flock);
9735  break;
9736 #endif
9737 #ifdef F_READAHEAD /* bsd specific */
9738  case F_READAHEAD:
9739  len = sizeof(int);
9740  break;
9741 #endif
9742 #ifdef F_RDAHEAD /* Darwin specific */
9743  case F_RDAHEAD:
9744  len = sizeof(int);
9745  break;
9746 #endif
9747 #ifdef F_GETSIG /* linux specific */
9748  case F_GETSIG:
9749  len = 1;
9750  break;
9751 #endif
9752 #ifdef F_SETSIG /* linux specific */
9753  case F_SETSIG:
9754  len = sizeof(fcntl_arg_t);
9755  break;
9756 #endif
9757 #ifdef F_GETLEASE /* linux specific */
9758  case F_GETLEASE:
9759  len = 1;
9760  break;
9761 #endif
9762 #ifdef F_SETLEASE /* linux specific */
9763  case F_SETLEASE:
9764  len = sizeof(fcntl_arg_t);
9765  break;
9766 #endif
9767 #ifdef F_NOTIFY /* linux specific */
9768  case F_NOTIFY:
9769  len = sizeof(fcntl_arg_t);
9770  break;
9771 #endif
9772 
9773  default:
9774  len = 256;
9775  break;
9776  }
9777 
9778  return len;
9779 }
9780 #else /* HAVE_FCNTL */
9781 static long
9782 fcntl_narg_len(int cmd)
9783 {
9784  return 0;
9785 }
9786 #endif /* HAVE_FCNTL */
9787 
9788 static long
9789 setup_narg(ioctl_req_t cmd, VALUE *argp, int io_p)
9790 {
9791  long narg = 0;
9792  VALUE arg = *argp;
9793 
9794  if (NIL_P(arg) || arg == Qfalse) {
9795  narg = 0;
9796  }
9797  else if (FIXNUM_P(arg)) {
9798  narg = FIX2LONG(arg);
9799  }
9800  else if (arg == Qtrue) {
9801  narg = 1;
9802  }
9803  else {
9804  VALUE tmp = rb_check_string_type(arg);
9805 
9806  if (NIL_P(tmp)) {
9807  narg = NUM2LONG(arg);
9808  }
9809  else {
9810  char *ptr;
9811  long len, slen;
9812 
9813  *argp = arg = tmp;
9814  if (io_p)
9815  len = ioctl_narg_len(cmd);
9816  else
9817  len = fcntl_narg_len((int)cmd);
9818  rb_str_modify(arg);
9819 
9820  slen = RSTRING_LEN(arg);
9821  /* expand for data + sentinel. */
9822  if (slen < len+1) {
9823  rb_str_resize(arg, len+1);
9824  MEMZERO(RSTRING_PTR(arg)+slen, char, len-slen);
9825  slen = len+1;
9826  }
9827  /* a little sanity check here */
9828  ptr = RSTRING_PTR(arg);
9829  ptr[slen - 1] = 17;
9830  narg = (long)(SIGNED_VALUE)ptr;
9831  }
9832  }
9833 
9834  return narg;
9835 }
9836 
9837 #ifdef HAVE_IOCTL
9838 static VALUE
9839 rb_ioctl(VALUE io, VALUE req, VALUE arg)
9840 {
9841  ioctl_req_t cmd = NUM2IOCTLREQ(req);
9842  rb_io_t *fptr;
9843  long narg;
9844  int retval;
9845 
9846  narg = setup_narg(cmd, &arg, 1);
9847  GetOpenFile(io, fptr);
9848  retval = do_ioctl(fptr->fd, cmd, narg);
9849  if (retval < 0) rb_sys_fail_path(fptr->pathv);
9850  if (RB_TYPE_P(arg, T_STRING)) {
9851  char *ptr;
9852  long slen;
9853  RSTRING_GETMEM(arg, ptr, slen);
9854  if (ptr[slen-1] != 17)
9855  rb_raise(rb_eArgError, "return value overflowed string");
9856  ptr[slen-1] = '\0';
9857  }
9858 
9859  return INT2NUM(retval);
9860 }
9861 
9862 /*
9863  * call-seq:
9864  * ios.ioctl(integer_cmd, arg) -> integer
9865  *
9866  * Provides a mechanism for issuing low-level commands to control or
9867  * query I/O devices. Arguments and results are platform dependent. If
9868  * <i>arg</i> is a number, its value is passed directly. If it is a
9869  * string, it is interpreted as a binary sequence of bytes. On Unix
9870  * platforms, see <code>ioctl(2)</code> for details. Not implemented on
9871  * all platforms.
9872  */
9873 
9874 static VALUE
9875 rb_io_ioctl(int argc, VALUE *argv, VALUE io)
9876 {
9877  VALUE req, arg;
9878 
9879  rb_scan_args(argc, argv, "11", &req, &arg);
9880  return rb_ioctl(io, req, arg);
9881 }
9882 #else
9883 #define rb_io_ioctl rb_f_notimplement
9884 #endif
9885 
9886 #ifdef HAVE_FCNTL
9887 struct fcntl_arg {
9888  int fd;
9889  int cmd;
9890  long narg;
9891 };
9892 
9893 static VALUE
9894 nogvl_fcntl(void *ptr)
9895 {
9896  struct fcntl_arg *arg = ptr;
9897 
9898 #if defined(F_DUPFD)
9899  if (arg->cmd == F_DUPFD)
9900  return (VALUE)rb_cloexec_fcntl_dupfd(arg->fd, (int)arg->narg);
9901 #endif
9902  return (VALUE)fcntl(arg->fd, arg->cmd, arg->narg);
9903 }
9904 
9905 static int
9906 do_fcntl(int fd, int cmd, long narg)
9907 {
9908  int retval;
9909  struct fcntl_arg arg;
9910 
9911  arg.fd = fd;
9912  arg.cmd = cmd;
9913  arg.narg = narg;
9914 
9915  retval = (int)rb_thread_io_blocking_region(nogvl_fcntl, &arg, fd);
9916  if (retval != -1) {
9917  switch (cmd) {
9918 #if defined(F_DUPFD)
9919  case F_DUPFD:
9920 #endif
9921 #if defined(F_DUPFD_CLOEXEC)
9922  case F_DUPFD_CLOEXEC:
9923 #endif
9924  rb_update_max_fd(retval);
9925  }
9926  }
9927 
9928  return retval;
9929 }
9930 
9931 static VALUE
9932 rb_fcntl(VALUE io, VALUE req, VALUE arg)
9933 {
9934  int cmd = NUM2INT(req);
9935  rb_io_t *fptr;
9936  long narg;
9937  int retval;
9938 
9939  narg = setup_narg(cmd, &arg, 0);
9940  GetOpenFile(io, fptr);
9941  retval = do_fcntl(fptr->fd, cmd, narg);
9942  if (retval < 0) rb_sys_fail_path(fptr->pathv);
9943  if (RB_TYPE_P(arg, T_STRING)) {
9944  char *ptr;
9945  long slen;
9946  RSTRING_GETMEM(arg, ptr, slen);
9947  if (ptr[slen-1] != 17)
9948  rb_raise(rb_eArgError, "return value overflowed string");
9949  ptr[slen-1] = '\0';
9950  }
9951 
9952  return INT2NUM(retval);
9953 }
9954 
9955 /*
9956  * call-seq:
9957  * ios.fcntl(integer_cmd, arg) -> integer
9958  *
9959  * Provides a mechanism for issuing low-level commands to control or
9960  * query file-oriented I/O streams. Arguments and results are platform
9961  * dependent. If <i>arg</i> is a number, its value is passed
9962  * directly. If it is a string, it is interpreted as a binary sequence
9963  * of bytes (Array#pack might be a useful way to build this string). On
9964  * Unix platforms, see <code>fcntl(2)</code> for details. Not
9965  * implemented on all platforms.
9966  */
9967 
9968 static VALUE
9969 rb_io_fcntl(int argc, VALUE *argv, VALUE io)
9970 {
9971  VALUE req, arg;
9972 
9973  rb_scan_args(argc, argv, "11", &req, &arg);
9974  return rb_fcntl(io, req, arg);
9975 }
9976 #else
9977 #define rb_io_fcntl rb_f_notimplement
9978 #endif
9979 
9980 #if defined(HAVE_SYSCALL) || defined(HAVE___SYSCALL)
9981 /*
9982  * call-seq:
9983  * syscall(num [, args...]) -> integer
9984  *
9985  * Calls the operating system function identified by _num_ and
9986  * returns the result of the function or raises SystemCallError if
9987  * it failed.
9988  *
9989  * Arguments for the function can follow _num_. They must be either
9990  * +String+ objects or +Integer+ objects. A +String+ object is passed
9991  * as a pointer to the byte sequence. An +Integer+ object is passed
9992  * as an integer whose bit size is same as a pointer.
9993  * Up to nine parameters may be passed.
9994  *
9995  * The function identified by _num_ is system
9996  * dependent. On some Unix systems, the numbers may be obtained from a
9997  * header file called <code>syscall.h</code>.
9998  *
9999  * syscall 4, 1, "hello\n", 6 # '4' is write(2) on our box
10000  *
10001  * <em>produces:</em>
10002  *
10003  * hello
10004  *
10005  * Calling +syscall+ on a platform which does not have any way to
10006  * an arbitrary system function just fails with NotImplementedError.
10007  *
10008  * *Note:*
10009  * +syscall+ is essentially unsafe and unportable.
10010  * Feel free to shoot your foot.
10011  * The DL (Fiddle) library is preferred for safer and a bit
10012  * more portable programming.
10013  */
10014 
10015 static VALUE
10017 {
10018  VALUE arg[8];
10019 #if SIZEOF_VOIDP == 8 && defined(HAVE___SYSCALL) && SIZEOF_INT != 8 /* mainly *BSD */
10020 # define SYSCALL __syscall
10021 # define NUM2SYSCALLID(x) NUM2LONG(x)
10022 # define RETVAL2NUM(x) LONG2NUM(x)
10023 # if SIZEOF_LONG == 8
10024  long num, retval = -1;
10025 # elif SIZEOF_LONG_LONG == 8
10026  long long num, retval = -1;
10027 # else
10028 # error ---->> it is asserted that __syscall takes the first argument and returns retval in 64bit signed integer. <<----
10029 # endif
10030 #elif defined(__linux__)
10031 # define SYSCALL syscall
10032 # define NUM2SYSCALLID(x) NUM2LONG(x)
10033 # define RETVAL2NUM(x) LONG2NUM(x)
10034  /*
10035  * Linux man page says, syscall(2) function prototype is below.
10036  *
10037  * int syscall(int number, ...);
10038  *
10039  * But, it's incorrect. Actual one takes and returned long. (see unistd.h)
10040  */
10041  long num, retval = -1;
10042 #else
10043 # define SYSCALL syscall
10044 # define NUM2SYSCALLID(x) NUM2INT(x)
10045 # define RETVAL2NUM(x) INT2NUM(x)
10046  int num, retval = -1;
10047 #endif
10048  int i;
10049 
10050  if (RTEST(ruby_verbose)) {
10051  rb_warning("We plan to remove a syscall function at future release. DL(Fiddle) provides safer alternative.");
10052  }
10053 
10054  if (argc == 0)
10055  rb_raise(rb_eArgError, "too few arguments for syscall");
10056  if (argc > numberof(arg))
10057  rb_raise(rb_eArgError, "too many arguments for syscall");
10058  num = NUM2SYSCALLID(argv[0]); ++argv;
10059  for (i = argc - 1; i--; ) {
10061 
10062  if (!NIL_P(v)) {
10063  SafeStringValue(v);
10064  rb_str_modify(v);
10065  arg[i] = (VALUE)StringValueCStr(v);
10066  }
10067  else {
10068  arg[i] = (VALUE)NUM2LONG(argv[i]);
10069  }
10070  }
10071 
10072  switch (argc) {
10073  case 1:
10074  retval = SYSCALL(num);
10075  break;
10076  case 2:
10077  retval = SYSCALL(num, arg[0]);
10078  break;
10079  case 3:
10080  retval = SYSCALL(num, arg[0],arg[1]);
10081  break;
10082  case 4:
10083  retval = SYSCALL(num, arg[0],arg[1],arg[2]);
10084  break;
10085  case 5:
10086  retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3]);
10087  break;
10088  case 6:
10089  retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4]);
10090  break;
10091  case 7:
10092  retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5]);
10093  break;
10094  case 8:
10095  retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6]);
10096  break;
10097  }
10098 
10099  if (retval == -1)
10100  rb_sys_fail(0);
10101  return RETVAL2NUM(retval);
10102 #undef SYSCALL
10103 #undef NUM2SYSCALLID
10104 #undef RETVAL2NUM
10105 }
10106 #else
10107 #define rb_f_syscall rb_f_notimplement
10108 #endif
10109 
10110 static VALUE
10111 io_new_instance(VALUE args)
10112 {
10113  return rb_class_new_instance(2, (VALUE*)args+1, *(VALUE*)args);
10114 }
10115 
10116 static rb_encoding *
10117 find_encoding(VALUE v)
10118 {
10119  rb_encoding *enc = rb_find_encoding(v);
10120  if (!enc) rb_warn("Unsupported encoding %"PRIsVALUE" ignored", v);
10121  return enc;
10122 }
10123 
10124 static void
10125 io_encoding_set(rb_io_t *fptr, VALUE v1, VALUE v2, VALUE opt)
10126 {
10127  rb_encoding *enc, *enc2;
10128  int ecflags = fptr->encs.ecflags;
10129  VALUE ecopts, tmp;
10130 
10131  if (!NIL_P(v2)) {
10132  enc2 = find_encoding(v1);
10133  tmp = rb_check_string_type(v2);
10134  if (!NIL_P(tmp)) {
10135  if (RSTRING_LEN(tmp) == 1 && RSTRING_PTR(tmp)[0] == '-') {
10136  /* Special case - "-" => no transcoding */
10137  enc = enc2;
10138  enc2 = NULL;
10139  }
10140  else
10141  enc = find_encoding(v2);
10142  if (enc == enc2) {
10143  /* Special case - "-" => no transcoding */
10144  enc2 = NULL;
10145  }
10146  }
10147  else {
10148  enc = find_encoding(v2);
10149  if (enc == enc2) {
10150  /* Special case - "-" => no transcoding */
10151  enc2 = NULL;
10152  }
10153  }
10155  ecflags = rb_econv_prepare_options(opt, &ecopts, ecflags);
10156  }
10157  else {
10158  if (NIL_P(v1)) {
10159  /* Set to default encodings */
10160  rb_io_ext_int_to_encs(NULL, NULL, &enc, &enc2, 0);
10162  ecopts = Qnil;
10163  }
10164  else {
10165  tmp = rb_check_string_type(v1);
10166  if (!NIL_P(tmp) && rb_enc_asciicompat(enc = rb_enc_get(tmp))) {
10167  parse_mode_enc(RSTRING_PTR(tmp), enc, &enc, &enc2, NULL);
10169  ecflags = rb_econv_prepare_options(opt, &ecopts, ecflags);
10170  }
10171  else {
10172  rb_io_ext_int_to_encs(find_encoding(v1), NULL, &enc, &enc2, 0);
10174  ecopts = Qnil;
10175  }
10176  }
10177  }
10178  validate_enc_binmode(&fptr->mode, ecflags, enc, enc2);
10179  fptr->encs.enc = enc;
10180  fptr->encs.enc2 = enc2;
10181  fptr->encs.ecflags = ecflags;
10182  fptr->encs.ecopts = ecopts;
10183  clear_codeconv(fptr);
10184 
10185 }
10186 
10192 };
10193 
10194 static VALUE
10195 io_encoding_set_v(VALUE v)
10196 {
10197  struct io_encoding_set_args *arg = (struct io_encoding_set_args *)v;
10198  io_encoding_set(arg->fptr, arg->v1, arg->v2, arg->opt);
10199  return Qnil;
10200 }
10201 
10202 static VALUE
10203 pipe_pair_close(VALUE rw)
10204 {
10205  VALUE *rwp = (VALUE *)rw;
10206  return rb_ensure(io_close, rwp[0], io_close, rwp[1]);
10207 }
10208 
10209 /*
10210  * call-seq:
10211  * IO.pipe -> [read_io, write_io]
10212  * IO.pipe(ext_enc) -> [read_io, write_io]
10213  * IO.pipe("ext_enc:int_enc" [, opt]) -> [read_io, write_io]
10214  * IO.pipe(ext_enc, int_enc [, opt]) -> [read_io, write_io]
10215  *
10216  * IO.pipe(...) {|read_io, write_io| ... }
10217  *
10218  * Creates a pair of pipe endpoints (connected to each other) and
10219  * returns them as a two-element array of IO objects:
10220  * <code>[</code> <i>read_io</i>, <i>write_io</i> <code>]</code>.
10221  *
10222  * If a block is given, the block is called and
10223  * returns the value of the block.
10224  * <i>read_io</i> and <i>write_io</i> are sent to the block as arguments.
10225  * If read_io and write_io are not closed when the block exits, they are closed.
10226  * i.e. closing read_io and/or write_io doesn't cause an error.
10227  *
10228  * Not available on all platforms.
10229  *
10230  * If an encoding (encoding name or encoding object) is specified as an optional argument,
10231  * read string from pipe is tagged with the encoding specified.
10232  * If the argument is a colon separated two encoding names "A:B",
10233  * the read string is converted from encoding A (external encoding)
10234  * to encoding B (internal encoding), then tagged with B.
10235  * If two optional arguments are specified, those must be
10236  * encoding objects or encoding names,
10237  * and the first one is the external encoding,
10238  * and the second one is the internal encoding.
10239  * If the external encoding and the internal encoding is specified,
10240  * optional hash argument specify the conversion option.
10241  *
10242  * In the example below, the two processes close the ends of the pipe
10243  * that they are not using. This is not just a cosmetic nicety. The
10244  * read end of a pipe will not generate an end of file condition if
10245  * there are any writers with the pipe still open. In the case of the
10246  * parent process, the <code>rd.read</code> will never return if it
10247  * does not first issue a <code>wr.close</code>.
10248  *
10249  * rd, wr = IO.pipe
10250  *
10251  * if fork
10252  * wr.close
10253  * puts "Parent got: <#{rd.read}>"
10254  * rd.close
10255  * Process.wait
10256  * else
10257  * rd.close
10258  * puts "Sending message to parent"
10259  * wr.write "Hi Dad"
10260  * wr.close
10261  * end
10262  *
10263  * <em>produces:</em>
10264  *
10265  * Sending message to parent
10266  * Parent got: <Hi Dad>
10267  */
10268 
10269 static VALUE
10270 rb_io_s_pipe(int argc, VALUE *argv, VALUE klass)
10271 {
10272  int pipes[2], state;
10273  VALUE r, w, args[3], v1, v2;
10274  VALUE opt;
10275  rb_io_t *fptr, *fptr2;
10276  struct io_encoding_set_args ies_args;
10277  int fmode = 0;
10278  VALUE ret;
10279 
10280  argc = rb_scan_args(argc, argv, "02:", &v1, &v2, &opt);
10281  if (rb_pipe(pipes) < 0)
10282  rb_sys_fail(0);
10283 
10284  args[0] = klass;
10285  args[1] = INT2NUM(pipes[0]);
10286  args[2] = INT2FIX(O_RDONLY);
10287  r = rb_protect(io_new_instance, (VALUE)args, &state);
10288  if (state) {
10289  close(pipes[0]);
10290  close(pipes[1]);
10291  rb_jump_tag(state);
10292  }
10293  GetOpenFile(r, fptr);
10294 
10295  ies_args.fptr = fptr;
10296  ies_args.v1 = v1;
10297  ies_args.v2 = v2;
10298  ies_args.opt = opt;
10299  rb_protect(io_encoding_set_v, (VALUE)&ies_args, &state);
10300  if (state) {
10301  close(pipes[1]);
10302  io_close(r);
10303  rb_jump_tag(state);
10304  }
10305 
10306  args[1] = INT2NUM(pipes[1]);
10307  args[2] = INT2FIX(O_WRONLY);
10308  w = rb_protect(io_new_instance, (VALUE)args, &state);
10309  if (state) {
10310  close(pipes[1]);
10311  if (!NIL_P(r)) rb_io_close(r);
10312  rb_jump_tag(state);
10313  }
10314  GetOpenFile(w, fptr2);
10315  rb_io_synchronized(fptr2);
10316 
10317  extract_binmode(opt, &fmode);
10318 
10319  if ((fmode & FMODE_BINMODE) && v1 == Qnil) {
10322  }
10323 
10324 #if DEFAULT_TEXTMODE
10325  if ((fptr->mode & FMODE_TEXTMODE) && (fmode & FMODE_BINMODE)) {
10326  fptr->mode &= ~FMODE_TEXTMODE;
10327  setmode(fptr->fd, O_BINARY);
10328  }
10329 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
10332  }
10333 #endif
10334 #endif
10335  fptr->mode |= fmode;
10336 #if DEFAULT_TEXTMODE
10337  if ((fptr2->mode & FMODE_TEXTMODE) && (fmode & FMODE_BINMODE)) {
10338  fptr2->mode &= ~FMODE_TEXTMODE;
10339  setmode(fptr2->fd, O_BINARY);
10340  }
10341 #endif
10342  fptr2->mode |= fmode;
10343 
10344  ret = rb_assoc_new(r, w);
10345  if (rb_block_given_p()) {
10346  VALUE rw[2];
10347  rw[0] = r;
10348  rw[1] = w;
10349  return rb_ensure(rb_yield, ret, pipe_pair_close, (VALUE)rw);
10350  }
10351  return ret;
10352 }
10353 
10354 struct foreach_arg {
10355  int argc;
10358 };
10359 
10360 static void
10361 open_key_args(VALUE klass, int argc, VALUE *argv, VALUE opt, struct foreach_arg *arg)
10362 {
10363  VALUE path, v;
10364  VALUE vmode = Qnil, vperm = Qnil;
10365 
10366  path = *argv++;
10367  argc--;
10368  FilePathValue(path);
10369  arg->io = 0;
10370  arg->argc = argc;
10371  arg->argv = argv;
10372  if (NIL_P(opt)) {
10373  vmode = INT2NUM(O_RDONLY);
10374  vperm = INT2FIX(0666);
10375  }
10376  else if (!NIL_P(v = rb_hash_aref(opt, sym_open_args))) {
10377  int n;
10378 
10379  v = rb_to_array_type(v);
10380  n = RARRAY_LENINT(v);
10381  rb_check_arity(n, 0, 3); /* rb_io_open */
10382  rb_scan_args_kw(RB_SCAN_ARGS_LAST_HASH_KEYWORDS, n, RARRAY_CONST_PTR(v), "02:", &vmode, &vperm, &opt);
10383  }
10384  arg->io = rb_io_open(klass, path, vmode, vperm, opt);
10385 }
10386 
10387 static VALUE
10388 io_s_foreach(VALUE v)
10389 {
10390  struct getline_arg *arg = (void *)v;
10391  VALUE str;
10392 
10393  while (!NIL_P(str = rb_io_getline_1(arg->rs, arg->limit, arg->chomp, arg->io))) {
10395  rb_yield(str);
10396  }
10398  return Qnil;
10399 }
10400 
10401 /*
10402  * call-seq:
10403  * IO.foreach(name, sep=$/ [, getline_args, open_args]) {|line| block } -> nil
10404  * IO.foreach(name, limit [, getline_args, open_args]) {|line| block } -> nil
10405  * IO.foreach(name, sep, limit [, getline_args, open_args]) {|line| block } -> nil
10406  * IO.foreach(...) -> an_enumerator
10407  *
10408  * Executes the block for every line in the named I/O port, where lines
10409  * are separated by <em>sep</em>.
10410  *
10411  * If no block is given, an enumerator is returned instead.
10412  *
10413  * IO.foreach("testfile") {|x| print "GOT ", x }
10414  *
10415  * <em>produces:</em>
10416  *
10417  * GOT This is line one
10418  * GOT This is line two
10419  * GOT This is line three
10420  * GOT And so on...
10421  *
10422  * If the last argument is a hash, it's the keyword argument to open.
10423  * See IO.readlines for details about getline_args.
10424  * And see also IO.read for details about open_args.
10425  *
10426  */
10427 
10428 static VALUE
10429 rb_io_s_foreach(int argc, VALUE *argv, VALUE self)
10430 {
10431  VALUE opt;
10432  int orig_argc = argc;
10433  struct foreach_arg arg;
10434  struct getline_arg garg;
10435 
10436  argc = rb_scan_args(argc, argv, "13:", NULL, NULL, NULL, NULL, &opt);
10437  RETURN_ENUMERATOR(self, orig_argc, argv);
10438  extract_getline_args(argc-1, argv+1, &garg);
10439  open_key_args(self, argc, argv, opt, &arg);
10440  if (NIL_P(arg.io)) return Qnil;
10441  extract_getline_opts(opt, &garg);
10442  check_getline_args(&garg.rs, &garg.limit, garg.io = arg.io);
10443  return rb_ensure(io_s_foreach, (VALUE)&garg, rb_io_close, arg.io);
10444 }
10445 
10446 static VALUE
10447 io_s_readlines(VALUE v)
10448 {
10449  struct getline_arg *arg = (void *)v;
10450  return io_readlines(arg, arg->io);
10451 }
10452 
10453 /*
10454  * call-seq:
10455  * IO.readlines(name, sep=$/ [, getline_args, open_args]) -> array
10456  * IO.readlines(name, limit [, getline_args, open_args]) -> array
10457  * IO.readlines(name, sep, limit [, getline_args, open_args]) -> array
10458  *
10459  * Reads the entire file specified by <i>name</i> as individual
10460  * lines, and returns those lines in an array. Lines are separated by
10461  * <i>sep</i>.
10462  *
10463  * a = IO.readlines("testfile")
10464  * a[0] #=> "This is line one\n"
10465  *
10466  * b = IO.readlines("testfile", chomp: true)
10467  * b[0] #=> "This is line one"
10468  *
10469  * If the last argument is a hash, it's the keyword argument to open.
10470  *
10471  * === Options for getline
10472  *
10473  * The options hash accepts the following keys:
10474  *
10475  * :chomp::
10476  * When the optional +chomp+ keyword argument has a true value,
10477  * <code>\n</code>, <code>\r</code>, and <code>\r\n</code>
10478  * will be removed from the end of each line.
10479  *
10480  * See also IO.read for details about open_args.
10481  */
10482 
10483 static VALUE
10484 rb_io_s_readlines(int argc, VALUE *argv, VALUE io)
10485 {
10486  VALUE opt;
10487  struct foreach_arg arg;
10488  struct getline_arg garg;
10489 
10490  argc = rb_scan_args(argc, argv, "13:", NULL, NULL, NULL, NULL, &opt);
10491  extract_getline_args(argc-1, argv+1, &garg);
10492  open_key_args(io, argc, argv, opt, &arg);
10493  if (NIL_P(arg.io)) return Qnil;
10494  extract_getline_opts(opt, &garg);
10495  check_getline_args(&garg.rs, &garg.limit, garg.io = arg.io);
10496  return rb_ensure(io_s_readlines, (VALUE)&garg, rb_io_close, arg.io);
10497 }
10498 
10499 static VALUE
10500 io_s_read(VALUE v)
10501 {
10502  struct foreach_arg *arg = (void *)v;
10503  return io_read(arg->argc, arg->argv, arg->io);
10504 }
10505 
10506 struct seek_arg {
10509  int mode;
10510 };
10511 
10512 static VALUE
10513 seek_before_access(VALUE argp)
10514 {
10515  struct seek_arg *arg = (struct seek_arg *)argp;
10516  rb_io_binmode(arg->io);
10517  return rb_io_seek(arg->io, arg->offset, arg->mode);
10518 }
10519 
10520 /*
10521  * call-seq:
10522  * IO.read(name, [length [, offset]] [, opt] ) -> string
10523  *
10524  * Opens the file, optionally seeks to the given +offset+, then returns
10525  * +length+ bytes (defaulting to the rest of the file). #read ensures
10526  * the file is closed before returning.
10527  *
10528  * If +name+ starts with a pipe character (<code>"|"</code>), a subprocess is
10529  * created in the same way as Kernel#open, and its output is returned.
10530  *
10531  * === Options
10532  *
10533  * The options hash accepts the following keys:
10534  *
10535  * :encoding::
10536  * string or encoding
10537  *
10538  * Specifies the encoding of the read string. +:encoding+ will be ignored
10539  * if +length+ is specified. See Encoding.aliases for possible encodings.
10540  *
10541  * :mode::
10542  * string or integer
10543  *
10544  * Specifies the <i>mode</i> argument for open(). It must start
10545  * with an "r", otherwise it will cause an error.
10546  * See IO.new for the list of possible modes.
10547  *
10548  * :open_args::
10549  * array
10550  *
10551  * Specifies arguments for open() as an array. This key can not be used
10552  * in combination with either +:encoding+ or +:mode+.
10553  *
10554  * Examples:
10555  *
10556  * IO.read("testfile") #=> "This is line one\nThis is line two\nThis is line three\nAnd so on...\n"
10557  * IO.read("testfile", 20) #=> "This is line one\nThi"
10558  * IO.read("testfile", 20, 10) #=> "ne one\nThis is line "
10559  * IO.read("binfile", mode: "rb") #=> "\xF7\x00\x00\x0E\x12"
10560  */
10561 
10562 static VALUE
10563 rb_io_s_read(int argc, VALUE *argv, VALUE io)
10564 {
10565  VALUE opt, offset;
10566  struct foreach_arg arg;
10567 
10568  argc = rb_scan_args(argc, argv, "13:", NULL, NULL, &offset, NULL, &opt);
10569  open_key_args(io, argc, argv, opt, &arg);
10570  if (NIL_P(arg.io)) return Qnil;
10571  if (!NIL_P(offset)) {
10572  struct seek_arg sarg;
10573  int state = 0;
10574  sarg.io = arg.io;
10575  sarg.offset = offset;
10576  sarg.mode = SEEK_SET;
10577  rb_protect(seek_before_access, (VALUE)&sarg, &state);
10578  if (state) {
10579  rb_io_close(arg.io);
10580  rb_jump_tag(state);
10581  }
10582  if (arg.argc == 2) arg.argc = 1;
10583  }
10584  return rb_ensure(io_s_read, (VALUE)&arg, rb_io_close, arg.io);
10585 }
10586 
10587 /*
10588  * call-seq:
10589  * IO.binread(name, [length [, offset]] ) -> string
10590  *
10591  * Opens the file, optionally seeks to the given <i>offset</i>, then
10592  * returns <i>length</i> bytes (defaulting to the rest of the file).
10593  * #binread ensures the file is closed before returning. The open mode
10594  * would be <code>"rb:ASCII-8BIT"</code>.
10595  *
10596  * IO.binread("testfile") #=> "This is line one\nThis is line two\nThis is line three\nAnd so on...\n"
10597  * IO.binread("testfile", 20) #=> "This is line one\nThi"
10598  * IO.binread("testfile", 20, 10) #=> "ne one\nThis is line "
10599  */
10600 
10601 static VALUE
10602 rb_io_s_binread(int argc, VALUE *argv, VALUE io)
10603 {
10604  VALUE offset;
10605  struct foreach_arg arg;
10606  enum {
10608  oflags = O_RDONLY
10609 #ifdef O_BINARY
10610  |O_BINARY
10611 #endif
10612  };
10613  convconfig_t convconfig = {NULL, NULL, 0, Qnil};
10614 
10615  rb_scan_args(argc, argv, "12", NULL, NULL, &offset);
10616  FilePathValue(argv[0]);
10617  convconfig.enc = rb_ascii8bit_encoding();
10618  arg.io = rb_io_open_generic(io, argv[0], oflags, fmode, &convconfig, 0);
10619  if (NIL_P(arg.io)) return Qnil;
10620  arg.argv = argv+1;
10621  arg.argc = (argc > 1) ? 1 : 0;
10622  if (!NIL_P(offset)) {
10623  struct seek_arg sarg;
10624  int state = 0;
10625  sarg.io = arg.io;
10626  sarg.offset = offset;
10627  sarg.mode = SEEK_SET;
10628  rb_protect(seek_before_access, (VALUE)&sarg, &state);
10629  if (state) {
10630  rb_io_close(arg.io);
10631  rb_jump_tag(state);
10632  }
10633  }
10634  return rb_ensure(io_s_read, (VALUE)&arg, rb_io_close, arg.io);
10635 }
10636 
10637 static VALUE
10638 io_s_write0(VALUE v)
10639 {
10640  struct write_arg *arg = (void * )v;
10641  return io_write(arg->io,arg->str,arg->nosync);
10642 }
10643 
10644 static VALUE
10645 io_s_write(int argc, VALUE *argv, VALUE klass, int binary)
10646 {
10647  VALUE string, offset, opt;
10648  struct foreach_arg arg;
10649  struct write_arg warg;
10650 
10651  rb_scan_args(argc, argv, "21:", NULL, &string, &offset, &opt);
10652 
10653  if (NIL_P(opt)) opt = rb_hash_new();
10654  else opt = rb_hash_dup(opt);
10655 
10656 
10657  if (NIL_P(rb_hash_aref(opt,sym_mode))) {
10658  int mode = O_WRONLY|O_CREAT;
10659 #ifdef O_BINARY
10660  if (binary) mode |= O_BINARY;
10661 #endif
10662  if (NIL_P(offset)) mode |= O_TRUNC;
10663  rb_hash_aset(opt,sym_mode,INT2NUM(mode));
10664  }
10665  open_key_args(klass, argc, argv, opt, &arg);
10666 
10667 #ifndef O_BINARY
10668  if (binary) rb_io_binmode_m(arg.io);
10669 #endif
10670 
10671  if (NIL_P(arg.io)) return Qnil;
10672  if (!NIL_P(offset)) {
10673  struct seek_arg sarg;
10674  int state = 0;
10675  sarg.io = arg.io;
10676  sarg.offset = offset;
10677  sarg.mode = SEEK_SET;
10678  rb_protect(seek_before_access, (VALUE)&sarg, &state);
10679  if (state) {
10680  rb_io_close(arg.io);
10681  rb_jump_tag(state);
10682  }
10683  }
10684 
10685  warg.io = arg.io;
10686  warg.str = string;
10687  warg.nosync = 0;
10688 
10689  return rb_ensure(io_s_write0, (VALUE)&warg, rb_io_close, arg.io);
10690 }
10691 
10692 /*
10693  * call-seq:
10694  * IO.write(name, string [, offset]) -> integer
10695  * IO.write(name, string [, offset] [, opt]) -> integer
10696  *
10697  * Opens the file, optionally seeks to the given <i>offset</i>, writes
10698  * <i>string</i>, then returns the length written. #write ensures the
10699  * file is closed before returning. If <i>offset</i> is not given in
10700  * write mode, the file is truncated. Otherwise, it is not truncated.
10701  *
10702  * IO.write("testfile", "0123456789", 20) #=> 10
10703  * # File could contain: "This is line one\nThi0123456789two\nThis is line three\nAnd so on...\n"
10704  * IO.write("testfile", "0123456789") #=> 10
10705  * # File would now read: "0123456789"
10706  *
10707  * If the last argument is a hash, it specifies options for the internal
10708  * open(). It accepts the following keys:
10709  *
10710  * :encoding::
10711  * string or encoding
10712  *
10713  * Specifies the encoding of the read string.
10714  * See Encoding.aliases for possible encodings.
10715  *
10716  * :mode::
10717  * string or integer
10718  *
10719  * Specifies the <i>mode</i> argument for open(). It must start
10720  * with "w", "a", or "r+", otherwise it will cause an error.
10721  * See IO.new for the list of possible modes.
10722  *
10723  * :perm::
10724  * integer
10725  *
10726  * Specifies the <i>perm</i> argument for open().
10727  *
10728  * :open_args::
10729  * array
10730  *
10731  * Specifies arguments for open() as an array.
10732  * This key can not be used in combination with other keys.
10733  */
10734 
10735 static VALUE
10736 rb_io_s_write(int argc, VALUE *argv, VALUE io)
10737 {
10738  return io_s_write(argc, argv, io, 0);
10739 }
10740 
10741 /*
10742  * call-seq:
10743  * IO.binwrite(name, string, [offset] ) -> integer
10744  * IO.binwrite(name, string, [offset], open_args ) -> integer
10745  *
10746  * Same as IO.write except opening the file in binary mode and
10747  * ASCII-8BIT encoding (<code>"wb:ASCII-8BIT"</code>).
10748  */
10749 
10750 static VALUE
10751 rb_io_s_binwrite(int argc, VALUE *argv, VALUE io)
10752 {
10753  return io_s_write(argc, argv, io, 1);
10754 }
10755 
10759  off_t copy_length; /* (off_t)-1 if not specified */
10760  off_t src_offset; /* (off_t)-1 if not specified */
10761 
10762  int src_fd;
10763  int dst_fd;
10764  unsigned close_src : 1;
10765  unsigned close_dst : 1;
10768  const char *syserr;
10769  const char *notimp;
10771  struct stat src_stat;
10772  struct stat dst_stat;
10773 #ifdef HAVE_FCOPYFILE
10774  copyfile_state_t copyfile_state;
10775 #endif
10776 };
10777 
10778 static void *
10779 exec_interrupts(void *arg)
10780 {
10781  VALUE th = (VALUE)arg;
10783  return NULL;
10784 }
10785 
10786 /*
10787  * returns TRUE if the preceding system call was interrupted
10788  * so we can continue. If the thread was interrupted, we
10789  * reacquire the GVL to execute interrupts before continuing.
10790  */
10791 static int
10792 maygvl_copy_stream_continue_p(int has_gvl, struct copy_stream_struct *stp)
10793 {
10794  switch (errno) {
10795  case EINTR:
10796 #if defined(ERESTART)
10797  case ERESTART:
10798 #endif
10799  if (rb_thread_interrupted(stp->th)) {
10800  if (has_gvl)
10802  else
10803  rb_thread_call_with_gvl(exec_interrupts, (void *)stp->th);
10804  }
10805  return TRUE;
10806  }
10807  return FALSE;
10808 }
10809 
10810 #if USE_POLL
10811 # define IOWAIT_SYSCALL "poll"
10812 STATIC_ASSERT(pollin_expected, POLLIN == RB_WAITFD_IN);
10813 STATIC_ASSERT(pollout_expected, POLLOUT == RB_WAITFD_OUT);
10814 static int
10815 nogvl_wait_for_single_fd(int fd, short events)
10816 {
10817  struct pollfd fds;
10818 
10819  fds.fd = fd;
10820  fds.events = events;
10821 
10822  return poll(&fds, 1, -1);
10823 }
10824 #else /* !USE_POLL */
10825 # define IOWAIT_SYSCALL "select"
10826 static int
10827 nogvl_wait_for_single_fd(int fd, short events)
10828 {
10829  rb_fdset_t fds;
10830  int ret;
10831 
10832  rb_fd_init(&fds);
10833  rb_fd_set(fd, &fds);
10834 
10835  switch (events) {
10836  case RB_WAITFD_IN:
10837  ret = rb_fd_select(fd + 1, &fds, 0, 0, 0);
10838  break;
10839  case RB_WAITFD_OUT:
10840  ret = rb_fd_select(fd + 1, 0, &fds, 0, 0);
10841  break;
10842  default:
10843  VM_UNREACHABLE(nogvl_wait_for_single_fd);
10844  }
10845 
10846  rb_fd_term(&fds);
10847  return ret;
10848 }
10849 #endif /* !USE_POLL */
10850 
10851 static int
10852 maygvl_copy_stream_wait_read(int has_gvl, struct copy_stream_struct *stp)
10853 {
10854  int ret;
10855 
10856  do {
10857  if (has_gvl) {
10859  }
10860  else {
10861  ret = nogvl_wait_for_single_fd(stp->src_fd, RB_WAITFD_IN);
10862  }
10863  } while (ret < 0 && maygvl_copy_stream_continue_p(has_gvl, stp));
10864 
10865  if (ret < 0) {
10866  stp->syserr = IOWAIT_SYSCALL;
10867  stp->error_no = errno;
10868  return ret;
10869  }
10870  return 0;
10871 }
10872 
10873 static int
10874 nogvl_copy_stream_wait_write(struct copy_stream_struct *stp)
10875 {
10876  int ret;
10877 
10878  do {
10879  ret = nogvl_wait_for_single_fd(stp->dst_fd, RB_WAITFD_OUT);
10880  } while (ret < 0 && maygvl_copy_stream_continue_p(0, stp));
10881 
10882  if (ret < 0) {
10883  stp->syserr = IOWAIT_SYSCALL;
10884  stp->error_no = errno;
10885  return ret;
10886  }
10887  return 0;
10888 }
10889 
10890 #if defined HAVE_COPY_FILE_RANGE || (defined __linux__ && defined __NR_copy_file_range)
10891 # define USE_COPY_FILE_RANGE
10892 #endif
10893 
10894 #ifdef USE_COPY_FILE_RANGE
10895 
10896 static ssize_t
10897 simple_copy_file_range(int in_fd, off_t *in_offset, int out_fd, off_t *out_offset, size_t count, unsigned int flags)
10898 {
10899 #ifdef HAVE_COPY_FILE_RANGE
10900  return copy_file_range(in_fd, in_offset, out_fd, out_offset, count, flags);
10901 #else
10902  return syscall(__NR_copy_file_range, in_fd, in_offset, out_fd, out_offset, count, flags);
10903 #endif
10904 }
10905 
10906 static int
10907 nogvl_copy_file_range(struct copy_stream_struct *stp)
10908 {
10909  ssize_t ss;
10910  off_t src_size;
10911  off_t copy_length, src_offset, *src_offset_ptr;
10912 
10913  if (!S_ISREG(stp->src_stat.st_mode))
10914  return 0;
10915 
10916  src_size = stp->src_stat.st_size;
10917  src_offset = stp->src_offset;
10918  if (src_offset >= (off_t)0) {
10919  src_offset_ptr = &src_offset;
10920  }
10921  else {
10922  src_offset_ptr = NULL; /* if src_offset_ptr is NULL, then bytes are read from in_fd starting from the file offset */
10923  }
10924 
10925  copy_length = stp->copy_length;
10926  if (copy_length < (off_t)0) {
10927  if (src_offset < (off_t)0) {
10928  off_t current_offset;
10929  errno = 0;
10930  current_offset = lseek(stp->src_fd, 0, SEEK_CUR);
10931  if (current_offset < (off_t)0 && errno) {
10932  stp->syserr = "lseek";
10933  stp->error_no = errno;
10934  return (int)current_offset;
10935  }
10936  copy_length = src_size - current_offset;
10937  }
10938  else {
10939  copy_length = src_size - src_offset;
10940  }
10941  }
10942 
10943  retry_copy_file_range:
10944 # if SIZEOF_OFF_T > SIZEOF_SIZE_T
10945  /* we are limited by the 32-bit ssize_t return value on 32-bit */
10946  ss = (copy_length > (off_t)SSIZE_MAX) ? SSIZE_MAX : (ssize_t)copy_length;
10947 # else
10948  ss = (ssize_t)copy_length;
10949 # endif
10950  ss = simple_copy_file_range(stp->src_fd, src_offset_ptr, stp->dst_fd, NULL, ss, 0);
10951  if (0 < ss) {
10952  stp->total += ss;
10953  copy_length -= ss;
10954  if (0 < copy_length) {
10955  goto retry_copy_file_range;
10956  }
10957  }
10958  if (ss < 0) {
10959  if (maygvl_copy_stream_continue_p(0, stp)) {
10960  goto retry_copy_file_range;
10961  }
10962  switch (errno) {
10963  case EINVAL:
10964  case EPERM: /* copy_file_range(2) doesn't exist (may happen in
10965  docker container) */
10966 #ifdef ENOSYS
10967  case ENOSYS:
10968 #endif
10969 #ifdef EXDEV
10970  case EXDEV: /* in_fd and out_fd are not on the same filesystem */
10971 #endif
10972  return 0;
10973  case EAGAIN:
10974 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
10975  case EWOULDBLOCK:
10976 #endif
10977  {
10978  int ret = nogvl_copy_stream_wait_write(stp);
10979  if (ret < 0) return ret;
10980  }
10981  goto retry_copy_file_range;
10982  case EBADF:
10983  {
10984  int e = errno;
10985  int flags = fcntl(stp->dst_fd, F_GETFL);
10986 
10987  if (flags != -1 && flags & O_APPEND) {
10988  return 0;
10989  }
10990  errno = e;
10991  }
10992  }
10993  stp->syserr = "copy_file_range";
10994  stp->error_no = errno;
10995  return (int)ss;
10996  }
10997  return 1;
10998 }
10999 #endif
11000 
11001 #ifdef HAVE_FCOPYFILE
11002 static int
11003 nogvl_fcopyfile(struct copy_stream_struct *stp)
11004 {
11005  off_t cur, ss = 0;
11006  const off_t src_offset = stp->src_offset;
11007  int ret;
11008 
11009  if (stp->copy_length >= (off_t)0) {
11010  /* copy_length can't be specified in fcopyfile(3) */
11011  return 0;
11012  }
11013 
11014  if (!S_ISREG(stp->src_stat.st_mode))
11015  return 0;
11016 
11017  if (!S_ISREG(stp->dst_stat.st_mode))
11018  return 0;
11019  if (lseek(stp->dst_fd, 0, SEEK_CUR) > (off_t)0) /* if dst IO was already written */
11020  return 0;
11021 
11022  if (src_offset > (off_t)0) {
11023  off_t r;
11024 
11025  /* get current offset */
11026  errno = 0;
11027  cur = lseek(stp->src_fd, 0, SEEK_CUR);
11028  if (cur < (off_t)0 && errno) {
11029  stp->error_no = errno;
11030  return 1;
11031  }
11032 
11033  errno = 0;
11034  r = lseek(stp->src_fd, src_offset, SEEK_SET);
11035  if (r < (off_t)0 && errno) {
11036  stp->error_no = errno;
11037  return 1;
11038  }
11039  }
11040 
11041  stp->copyfile_state = copyfile_state_alloc(); /* this will be freed by copy_stream_finalize() */
11042  ret = fcopyfile(stp->src_fd, stp->dst_fd, stp->copyfile_state, COPYFILE_DATA);
11043  copyfile_state_get(stp->copyfile_state, COPYFILE_STATE_COPIED, &ss); /* get copied bytes */
11044 
11045  if (ret == 0) { /* success */
11046  stp->total = ss;
11047  if (src_offset > (off_t)0) {
11048  off_t r;
11049  errno = 0;
11050  /* reset offset */
11051  r = lseek(stp->src_fd, cur, SEEK_SET);
11052  if (r < (off_t)0 && errno) {
11053  stp->error_no = errno;
11054  return 1;
11055  }
11056  }
11057  }
11058  else {
11059  switch (errno) {
11060  case ENOTSUP:
11061  case EPERM:
11062  case EINVAL:
11063  return 0;
11064  }
11065  stp->syserr = "fcopyfile";
11066  stp->error_no = errno;
11067  return (int)ret;
11068  }
11069  return 1;
11070 }
11071 #endif
11072 
11073 #ifdef HAVE_SENDFILE
11074 
11075 # ifdef __linux__
11076 # define USE_SENDFILE
11077 
11078 # ifdef HAVE_SYS_SENDFILE_H
11079 # include <sys/sendfile.h>
11080 # endif
11081 
11082 static ssize_t
11083 simple_sendfile(int out_fd, int in_fd, off_t *offset, off_t count)
11084 {
11085  return sendfile(out_fd, in_fd, offset, (size_t)count);
11086 }
11087 
11088 # elif 0 /* defined(__FreeBSD__) || defined(__DragonFly__) */ || defined(__APPLE__)
11089 /* This runs on FreeBSD8.1 r30210, but sendfiles blocks its execution
11090  * without cpuset -l 0.
11091  */
11092 # define USE_SENDFILE
11093 
11094 static ssize_t
11095 simple_sendfile(int out_fd, int in_fd, off_t *offset, off_t count)
11096 {
11097  int r;
11098  off_t pos = offset ? *offset : lseek(in_fd, 0, SEEK_CUR);
11099  off_t sbytes;
11100 # ifdef __APPLE__
11101  r = sendfile(in_fd, out_fd, pos, &count, NULL, 0);
11102  sbytes = count;
11103 # else
11104  r = sendfile(in_fd, out_fd, pos, (size_t)count, NULL, &sbytes, 0);
11105 # endif
11106  if (r != 0 && sbytes == 0) return r;
11107  if (offset) {
11108  *offset += sbytes;
11109  }
11110  else {
11111  lseek(in_fd, sbytes, SEEK_CUR);
11112  }
11113  return (ssize_t)sbytes;
11114 }
11115 
11116 # endif
11117 
11118 #endif
11119 
11120 #ifdef USE_SENDFILE
11121 static int
11122 nogvl_copy_stream_sendfile(struct copy_stream_struct *stp)
11123 {
11124  ssize_t ss;
11125  off_t src_size;
11126  off_t copy_length;
11127  off_t src_offset;
11128  int use_pread;
11129 
11130  if (!S_ISREG(stp->src_stat.st_mode))
11131  return 0;
11132 
11133  src_size = stp->src_stat.st_size;
11134 #ifndef __linux__
11135  if ((stp->dst_stat.st_mode & S_IFMT) != S_IFSOCK)
11136  return 0;
11137 #endif
11138 
11139  src_offset = stp->src_offset;
11140  use_pread = src_offset >= (off_t)0;
11141 
11142  copy_length = stp->copy_length;
11143  if (copy_length < (off_t)0) {
11144  if (use_pread)
11145  copy_length = src_size - src_offset;
11146  else {
11147  off_t cur;
11148  errno = 0;
11149  cur = lseek(stp->src_fd, 0, SEEK_CUR);
11150  if (cur < (off_t)0 && errno) {
11151  stp->syserr = "lseek";
11152  stp->error_no = errno;
11153  return (int)cur;
11154  }
11155  copy_length = src_size - cur;
11156  }
11157  }
11158 
11159  retry_sendfile:
11160 # if SIZEOF_OFF_T > SIZEOF_SIZE_T
11161  /* we are limited by the 32-bit ssize_t return value on 32-bit */
11162  ss = (copy_length > (off_t)SSIZE_MAX) ? SSIZE_MAX : (ssize_t)copy_length;
11163 # else
11164  ss = (ssize_t)copy_length;
11165 # endif
11166  if (use_pread) {
11167  ss = simple_sendfile(stp->dst_fd, stp->src_fd, &src_offset, ss);
11168  }
11169  else {
11170  ss = simple_sendfile(stp->dst_fd, stp->src_fd, NULL, ss);
11171  }
11172  if (0 < ss) {
11173  stp->total += ss;
11174  copy_length -= ss;
11175  if (0 < copy_length) {
11176  goto retry_sendfile;
11177  }
11178  }
11179  if (ss < 0) {
11180  if (maygvl_copy_stream_continue_p(0, stp))
11181  goto retry_sendfile;
11182  switch (errno) {
11183  case EINVAL:
11184 #ifdef ENOSYS
11185  case ENOSYS:
11186 #endif
11187  return 0;
11188  case EAGAIN:
11189 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
11190  case EWOULDBLOCK:
11191 #endif
11192  {
11193  int ret;
11194 #ifndef __linux__
11195  /*
11196  * Linux requires stp->src_fd to be a mmap-able (regular) file,
11197  * select() reports regular files to always be "ready", so
11198  * there is no need to select() on it.
11199  * Other OSes may have the same limitation for sendfile() which
11200  * allow us to bypass maygvl_copy_stream_wait_read()...
11201  */
11202  ret = maygvl_copy_stream_wait_read(0, stp);
11203  if (ret < 0) return ret;
11204 #endif
11205  ret = nogvl_copy_stream_wait_write(stp);
11206  if (ret < 0) return ret;
11207  }
11208  goto retry_sendfile;
11209  }
11210  stp->syserr = "sendfile";
11211  stp->error_no = errno;
11212  return (int)ss;
11213  }
11214  return 1;
11215 }
11216 #endif
11217 
11218 static ssize_t
11219 maygvl_read(int has_gvl, int fd, void *buf, size_t count)
11220 {
11221  if (has_gvl)
11222  return rb_read_internal(fd, buf, count);
11223  else
11224  return read(fd, buf, count);
11225 }
11226 
11227 static ssize_t
11228 maygvl_copy_stream_read(int has_gvl, struct copy_stream_struct *stp, char *buf, size_t len, off_t offset)
11229 {
11230  ssize_t ss;
11231  retry_read:
11232  if (offset < (off_t)0) {
11233  ss = maygvl_read(has_gvl, stp->src_fd, buf, len);
11234  }
11235  else {
11236 #ifdef HAVE_PREAD
11237  ss = pread(stp->src_fd, buf, len, offset);
11238 #else
11239  stp->notimp = "pread";
11240  return -1;
11241 #endif
11242  }
11243  if (ss == 0) {
11244  return 0;
11245  }
11246  if (ss < 0) {
11247  if (maygvl_copy_stream_continue_p(has_gvl, stp))
11248  goto retry_read;
11249  switch (errno) {
11250  case EAGAIN:
11251 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
11252  case EWOULDBLOCK:
11253 #endif
11254  {
11255  int ret = maygvl_copy_stream_wait_read(has_gvl, stp);
11256  if (ret < 0) return ret;
11257  }
11258  goto retry_read;
11259 #ifdef ENOSYS
11260  case ENOSYS:
11261  stp->notimp = "pread";
11262  return ss;
11263 #endif
11264  }
11265  stp->syserr = offset < (off_t)0 ? "read" : "pread";
11266  stp->error_no = errno;
11267  }
11268  return ss;
11269 }
11270 
11271 static int
11272 nogvl_copy_stream_write(struct copy_stream_struct *stp, char *buf, size_t len)
11273 {
11274  ssize_t ss;
11275  int off = 0;
11276  while (len) {
11277  ss = write(stp->dst_fd, buf+off, len);
11278  if (ss < 0) {
11279  if (maygvl_copy_stream_continue_p(0, stp))
11280  continue;
11281  if (errno == EAGAIN || errno == EWOULDBLOCK) {
11282  int ret = nogvl_copy_stream_wait_write(stp);
11283  if (ret < 0) return ret;
11284  continue;
11285  }
11286  stp->syserr = "write";
11287  stp->error_no = errno;
11288  return (int)ss;
11289  }
11290  off += (int)ss;
11291  len -= (int)ss;
11292  stp->total += ss;
11293  }
11294  return 0;
11295 }
11296 
11297 static void
11298 nogvl_copy_stream_read_write(struct copy_stream_struct *stp)
11299 {
11300  char buf[1024*16];
11301  size_t len;
11302  ssize_t ss;
11303  int ret;
11304  off_t copy_length;
11305  int use_eof;
11306  off_t src_offset;
11307  int use_pread;
11308 
11309  copy_length = stp->copy_length;
11310  use_eof = copy_length < (off_t)0;
11311  src_offset = stp->src_offset;
11312  use_pread = src_offset >= (off_t)0;
11313 
11314  if (use_pread && stp->close_src) {
11315  off_t r;
11316  errno = 0;
11317  r = lseek(stp->src_fd, src_offset, SEEK_SET);
11318  if (r < (off_t)0 && errno) {
11319  stp->syserr = "lseek";
11320  stp->error_no = errno;
11321  return;
11322  }
11323  src_offset = (off_t)-1;
11324  use_pread = 0;
11325  }
11326 
11327  while (use_eof || 0 < copy_length) {
11328  if (!use_eof && copy_length < (off_t)sizeof(buf)) {
11329  len = (size_t)copy_length;
11330  }
11331  else {
11332  len = sizeof(buf);
11333  }
11334  if (use_pread) {
11335  ss = maygvl_copy_stream_read(0, stp, buf, len, src_offset);
11336  if (0 < ss)
11337  src_offset += ss;
11338  }
11339  else {
11340  ss = maygvl_copy_stream_read(0, stp, buf, len, (off_t)-1);
11341  }
11342  if (ss <= 0) /* EOF or error */
11343  return;
11344 
11345  ret = nogvl_copy_stream_write(stp, buf, ss);
11346  if (ret < 0)
11347  return;
11348 
11349  if (!use_eof)
11350  copy_length -= ss;
11351  }
11352 }
11353 
11354 static void *
11355 nogvl_copy_stream_func(void *arg)
11356 {
11357  struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
11358 #if defined(USE_SENDFILE) || defined(USE_COPY_FILE_RANGE) || defined(HAVE_FCOPYFILE)
11359  int ret;
11360 #endif
11361 
11362 #ifdef USE_COPY_FILE_RANGE
11363  ret = nogvl_copy_file_range(stp);
11364  if (ret != 0)
11365  goto finish; /* error or success */
11366 #endif
11367 
11368 #ifdef HAVE_FCOPYFILE
11369  ret = nogvl_fcopyfile(stp);
11370  if (ret != 0)
11371  goto finish; /* error or success */
11372 #endif
11373 
11374 #ifdef USE_SENDFILE
11375  ret = nogvl_copy_stream_sendfile(stp);
11376  if (ret != 0)
11377  goto finish; /* error or success */
11378 #endif
11379 
11380  nogvl_copy_stream_read_write(stp);
11381 
11382 #if defined(USE_SENDFILE) || defined(USE_COPY_FILE_RANGE) || defined(HAVE_FCOPYFILE)
11383  finish:
11384 #endif
11385  return 0;
11386 }
11387 
11388 static VALUE
11389 copy_stream_fallback_body(VALUE arg)
11390 {
11391  struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
11392  const int buflen = 16*1024;
11393  VALUE n;
11394  VALUE buf = rb_str_buf_new(buflen);
11395  off_t rest = stp->copy_length;
11396  off_t off = stp->src_offset;
11397  ID read_method = id_readpartial;
11398 
11399  if (stp->src_fd < 0) {
11400  if (!rb_respond_to(stp->src, read_method)) {
11401  read_method = id_read;
11402  }
11403  }
11404 
11405  while (1) {
11406  long numwrote;
11407  long l;
11408  if (stp->copy_length < (off_t)0) {
11409  l = buflen;
11410  }
11411  else {
11412  if (rest == 0) {
11413  rb_str_resize(buf, 0);
11414  break;
11415  }
11416  l = buflen < rest ? buflen : (long)rest;
11417  }
11418  if (stp->src_fd < 0) {
11419  VALUE rc = rb_funcall(stp->src, read_method, 2, INT2FIX(l), buf);
11420 
11421  if (read_method == id_read && NIL_P(rc))
11422  break;
11423  }
11424  else {
11425  ssize_t ss;
11426  rb_str_resize(buf, buflen);
11427  ss = maygvl_copy_stream_read(1, stp, RSTRING_PTR(buf), l, off);
11428  rb_str_resize(buf, ss > 0 ? ss : 0);
11429  if (ss < 0)
11430  return Qnil;
11431  if (ss == 0)
11432  rb_eof_error();
11433  if (off >= (off_t)0)
11434  off += ss;
11435  }
11436  n = rb_io_write(stp->dst, buf);
11437  numwrote = NUM2LONG(n);
11438  stp->total += numwrote;
11439  rest -= numwrote;
11440  if (read_method == id_read && RSTRING_LEN(buf) == 0) {
11441  break;
11442  }
11443  }
11444 
11445  return Qnil;
11446 }
11447 
11448 static VALUE
11449 copy_stream_fallback(struct copy_stream_struct *stp)
11450 {
11451  if (stp->src_fd < 0 && stp->src_offset >= (off_t)0) {
11452  rb_raise(rb_eArgError, "cannot specify src_offset for non-IO");
11453  }
11454  rb_rescue2(copy_stream_fallback_body, (VALUE)stp,
11455  (VALUE (*) (VALUE, VALUE))0, (VALUE)0,
11456  rb_eEOFError, (VALUE)0);
11457  return Qnil;
11458 }
11459 
11460 static VALUE
11461 copy_stream_body(VALUE arg)
11462 {
11463  struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
11464  VALUE src_io = stp->src, dst_io = stp->dst;
11465  rb_io_t *src_fptr = 0, *dst_fptr = 0;
11466  int src_fd, dst_fd;
11467  const int common_oflags = 0
11468 #ifdef O_NOCTTY
11469  | O_NOCTTY
11470 #endif
11471  ;
11472 
11473  stp->th = rb_thread_current();
11474 
11475  stp->total = 0;
11476 
11477  if (src_io == argf ||
11478  !(RB_TYPE_P(src_io, T_FILE) ||
11479  RB_TYPE_P(src_io, T_STRING) ||
11480  rb_respond_to(src_io, rb_intern("to_path")))) {
11481  src_fd = -1;
11482  }
11483  else {
11484  int stat_ret;
11485  VALUE tmp_io = rb_io_check_io(src_io);
11486  if (!NIL_P(tmp_io)) {
11487  src_io = tmp_io;
11488  }
11489  else if (!RB_TYPE_P(src_io, T_FILE)) {
11490  VALUE args[2];
11491  FilePathValue(src_io);
11492  args[0] = src_io;
11493  args[1] = INT2NUM(O_RDONLY|common_oflags);
11494  src_io = rb_class_new_instance(2, args, rb_cFile);
11495  stp->src = src_io;
11496  stp->close_src = 1;
11497  }
11498  GetOpenFile(src_io, src_fptr);
11499  rb_io_check_byte_readable(src_fptr);
11500  src_fd = src_fptr->fd;
11501 
11502  stat_ret = fstat(src_fd, &stp->src_stat);
11503  if (stat_ret < 0) {
11504  stp->syserr = "fstat";
11505  stp->error_no = errno;
11506  return Qnil;
11507  }
11508  }
11509  stp->src_fd = src_fd;
11510 
11511  if (dst_io == argf ||
11512  !(RB_TYPE_P(dst_io, T_FILE) ||
11513  RB_TYPE_P(dst_io, T_STRING) ||
11514  rb_respond_to(dst_io, rb_intern("to_path")))) {
11515  dst_fd = -1;
11516  }
11517  else {
11518  int stat_ret;
11519  VALUE tmp_io = rb_io_check_io(dst_io);
11520  if (!NIL_P(tmp_io)) {
11521  dst_io = GetWriteIO(tmp_io);
11522  }
11523  else if (!RB_TYPE_P(dst_io, T_FILE)) {
11524  VALUE args[3];
11525  FilePathValue(dst_io);
11526  args[0] = dst_io;
11527  args[1] = INT2NUM(O_WRONLY|O_CREAT|O_TRUNC|common_oflags);
11528  args[2] = INT2FIX(0666);
11529  dst_io = rb_class_new_instance(3, args, rb_cFile);
11530  stp->dst = dst_io;
11531  stp->close_dst = 1;
11532  }
11533  else {
11534  dst_io = GetWriteIO(dst_io);
11535  stp->dst = dst_io;
11536  }
11537  GetOpenFile(dst_io, dst_fptr);
11538  rb_io_check_writable(dst_fptr);
11539  dst_fd = dst_fptr->fd;
11540 
11541  stat_ret = fstat(dst_fd, &stp->dst_stat);
11542  if (stat_ret < 0) {
11543  stp->syserr = "fstat";
11544  stp->error_no = errno;
11545  return Qnil;
11546  }
11547  }
11548  stp->dst_fd = dst_fd;
11549 
11550 #ifdef O_BINARY
11551  if (src_fptr)
11553 #endif
11554  if (dst_fptr)
11555  io_ascii8bit_binmode(dst_fptr);
11556 
11557  if (stp->src_offset < (off_t)0 && src_fptr && src_fptr->rbuf.len) {
11558  size_t len = src_fptr->rbuf.len;
11559  VALUE str;
11560  if (stp->copy_length >= (off_t)0 && stp->copy_length < (off_t)len) {
11561  len = (size_t)stp->copy_length;
11562  }
11563  str = rb_str_buf_new(len);
11565  read_buffered_data(RSTRING_PTR(str), len, src_fptr);
11566  if (dst_fptr) { /* IO or filename */
11567  if (io_binwrite(str, RSTRING_PTR(str), RSTRING_LEN(str), dst_fptr, 0) < 0)
11568  rb_sys_fail(0);
11569  }
11570  else /* others such as StringIO */
11571  rb_io_write(dst_io, str);
11572  rb_str_resize(str, 0);
11573  stp->total += len;
11574  if (stp->copy_length >= (off_t)0)
11575  stp->copy_length -= len;
11576  }
11577 
11578  if (dst_fptr && io_fflush(dst_fptr) < 0) {
11579  rb_raise(rb_eIOError, "flush failed");
11580  }
11581 
11582  if (stp->copy_length == 0)
11583  return Qnil;
11584 
11585  if (src_fd < 0 || dst_fd < 0) {
11586  return copy_stream_fallback(stp);
11587  }
11588 
11589  rb_thread_call_without_gvl(nogvl_copy_stream_func, (void*)stp, RUBY_UBF_IO, 0);
11590  return Qnil;
11591 }
11592 
11593 static VALUE
11594 copy_stream_finalize(VALUE arg)
11595 {
11596  struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
11597 
11598 #ifdef HAVE_FCOPYFILE
11599  if (stp->copyfile_state) {
11600  copyfile_state_free(stp->copyfile_state);
11601  }
11602 #endif
11603 
11604  if (stp->close_src) {
11605  rb_io_close_m(stp->src);
11606  }
11607  if (stp->close_dst) {
11608  rb_io_close_m(stp->dst);
11609  }
11610  if (stp->syserr) {
11611  rb_syserr_fail(stp->error_no, stp->syserr);
11612  }
11613  if (stp->notimp) {
11614  rb_raise(rb_eNotImpError, "%s() not implemented", stp->notimp);
11615  }
11616  return Qnil;
11617 }
11618 
11619 /*
11620  * call-seq:
11621  * IO.copy_stream(src, dst)
11622  * IO.copy_stream(src, dst, copy_length)
11623  * IO.copy_stream(src, dst, copy_length, src_offset)
11624  *
11625  * IO.copy_stream copies <i>src</i> to <i>dst</i>.
11626  * <i>src</i> and <i>dst</i> is either a filename or an IO-like object.
11627  * IO-like object for <i>src</i> should have #readpartial or #read
11628  * method. IO-like object for <i>dst</i> should have #write method.
11629  * (Specialized mechanisms, such as sendfile system call, may be used
11630  * on appropriate situation.)
11631  *
11632  * This method returns the number of bytes copied.
11633  *
11634  * If optional arguments are not given,
11635  * the start position of the copy is
11636  * the beginning of the filename or
11637  * the current file offset of the IO.
11638  * The end position of the copy is the end of file.
11639  *
11640  * If <i>copy_length</i> is given,
11641  * No more than <i>copy_length</i> bytes are copied.
11642  *
11643  * If <i>src_offset</i> is given,
11644  * it specifies the start position of the copy.
11645  *
11646  * When <i>src_offset</i> is specified and
11647  * <i>src</i> is an IO,
11648  * IO.copy_stream doesn't move the current file offset.
11649  *
11650  */
11651 static VALUE
11652 rb_io_s_copy_stream(int argc, VALUE *argv, VALUE io)
11653 {
11654  VALUE src, dst, length, src_offset;
11655  struct copy_stream_struct st;
11656 
11657  MEMZERO(&st, struct copy_stream_struct, 1);
11658 
11659  rb_scan_args(argc, argv, "22", &src, &dst, &length, &src_offset);
11660 
11661  st.src = src;
11662  st.dst = dst;
11663 
11664  if (NIL_P(length))
11665  st.copy_length = (off_t)-1;
11666  else
11667  st.copy_length = NUM2OFFT(length);
11668 
11669  if (NIL_P(src_offset))
11670  st.src_offset = (off_t)-1;
11671  else
11672  st.src_offset = NUM2OFFT(src_offset);
11673 
11674  rb_ensure(copy_stream_body, (VALUE)&st, copy_stream_finalize, (VALUE)&st);
11675 
11676  return OFFT2NUM(st.total);
11677 }
11678 
11679 /*
11680  * call-seq:
11681  * io.external_encoding -> encoding
11682  *
11683  * Returns the Encoding object that represents the encoding of the file.
11684  * If _io_ is in write mode and no encoding is specified, returns +nil+.
11685  */
11686 
11687 static VALUE
11688 rb_io_external_encoding(VALUE io)
11689 {
11690  rb_io_t *fptr;
11691 
11692  GetOpenFile(io, fptr);
11693  if (fptr->encs.enc2) {
11694  return rb_enc_from_encoding(fptr->encs.enc2);
11695  }
11696  if (fptr->mode & FMODE_WRITABLE) {
11697  if (fptr->encs.enc)
11698  return rb_enc_from_encoding(fptr->encs.enc);
11699  return Qnil;
11700  }
11701  return rb_enc_from_encoding(io_read_encoding(fptr));
11702 }
11703 
11704 /*
11705  * call-seq:
11706  * io.internal_encoding -> encoding
11707  *
11708  * Returns the Encoding of the internal string if conversion is
11709  * specified. Otherwise returns +nil+.
11710  */
11711 
11712 static VALUE
11713 rb_io_internal_encoding(VALUE io)
11714 {
11715  rb_io_t *fptr;
11716 
11717  GetOpenFile(io, fptr);
11718  if (!fptr->encs.enc2) return Qnil;
11719  return rb_enc_from_encoding(io_read_encoding(fptr));
11720 }
11721 
11722 /*
11723  * call-seq:
11724  * io.set_encoding(ext_enc) -> io
11725  * io.set_encoding("ext_enc:int_enc") -> io
11726  * io.set_encoding(ext_enc, int_enc) -> io
11727  * io.set_encoding("ext_enc:int_enc", opt) -> io
11728  * io.set_encoding(ext_enc, int_enc, opt) -> io
11729  *
11730  * If single argument is specified, read string from io is tagged
11731  * with the encoding specified. If encoding is a colon separated two
11732  * encoding names "A:B", the read string is converted from encoding A
11733  * (external encoding) to encoding B (internal encoding), then tagged
11734  * with B. If two arguments are specified, those must be encoding
11735  * objects or encoding names, and the first one is the external encoding, and the
11736  * second one is the internal encoding.
11737  * If the external encoding and the internal encoding is specified,
11738  * optional hash argument specify the conversion option.
11739  */
11740 
11741 static VALUE
11742 rb_io_set_encoding(int argc, VALUE *argv, VALUE io)
11743 {
11744  rb_io_t *fptr;
11745  VALUE v1, v2, opt;
11746 
11747  if (!RB_TYPE_P(io, T_FILE)) {
11748  return rb_funcallv(io, id_set_encoding, argc, argv);
11749  }
11750 
11751  argc = rb_scan_args(argc, argv, "11:", &v1, &v2, &opt);
11752  GetOpenFile(io, fptr);
11753  io_encoding_set(fptr, v1, v2, opt);
11754  return io;
11755 }
11756 
11757 void
11759 {
11760  VALUE val = Qnil;
11761 
11762  rb_io_set_encoding(1, &val, rb_stdin);
11763  rb_io_set_encoding(1, &val, rb_stdout);
11764  rb_io_set_encoding(1, &val, rb_stderr);
11765 }
11766 
11767 static inline int
11768 global_argf_p(VALUE arg)
11769 {
11770  return arg == argf;
11771 }
11772 
11773 /*
11774  * call-seq:
11775  * ARGF.external_encoding -> encoding
11776  *
11777  * Returns the external encoding for files read from +ARGF+ as an +Encoding+
11778  * object. The external encoding is the encoding of the text as stored in a
11779  * file. Contrast with +ARGF.internal_encoding+, which is the encoding used
11780  * to represent this text within Ruby.
11781  *
11782  * To set the external encoding use +ARGF.set_encoding+.
11783  *
11784  * For example:
11785  *
11786  * ARGF.external_encoding #=> #<Encoding:UTF-8>
11787  *
11788  */
11789 static VALUE
11790 argf_external_encoding(VALUE argf)
11791 {
11792  if (!RTEST(ARGF.current_file)) {
11794  }
11795  return rb_io_external_encoding(rb_io_check_io(ARGF.current_file));
11796 }
11797 
11798 /*
11799  * call-seq:
11800  * ARGF.internal_encoding -> encoding
11801  *
11802  * Returns the internal encoding for strings read from +ARGF+ as an
11803  * +Encoding+ object.
11804  *
11805  * If +ARGF.set_encoding+ has been called with two encoding names, the second
11806  * is returned. Otherwise, if +Encoding.default_external+ has been set, that
11807  * value is returned. Failing that, if a default external encoding was
11808  * specified on the command-line, that value is used. If the encoding is
11809  * unknown, +nil+ is returned.
11810  */
11811 static VALUE
11812 argf_internal_encoding(VALUE argf)
11813 {
11814  if (!RTEST(ARGF.current_file)) {
11816  }
11817  return rb_io_internal_encoding(rb_io_check_io(ARGF.current_file));
11818 }
11819 
11820 /*
11821  * call-seq:
11822  * ARGF.set_encoding(ext_enc) -> ARGF
11823  * ARGF.set_encoding("ext_enc:int_enc") -> ARGF
11824  * ARGF.set_encoding(ext_enc, int_enc) -> ARGF
11825  * ARGF.set_encoding("ext_enc:int_enc", opt) -> ARGF
11826  * ARGF.set_encoding(ext_enc, int_enc, opt) -> ARGF
11827  *
11828  * If single argument is specified, strings read from ARGF are tagged with
11829  * the encoding specified.
11830  *
11831  * If two encoding names separated by a colon are given, e.g. "ascii:utf-8",
11832  * the read string is converted from the first encoding (external encoding)
11833  * to the second encoding (internal encoding), then tagged with the second
11834  * encoding.
11835  *
11836  * If two arguments are specified, they must be encoding objects or encoding
11837  * names. Again, the first specifies the external encoding; the second
11838  * specifies the internal encoding.
11839  *
11840  * If the external encoding and the internal encoding are specified, the
11841  * optional +Hash+ argument can be used to adjust the conversion process. The
11842  * structure of this hash is explained in the String#encode documentation.
11843  *
11844  * For example:
11845  *
11846  * ARGF.set_encoding('ascii') # Tag the input as US-ASCII text
11847  * ARGF.set_encoding(Encoding::UTF_8) # Tag the input as UTF-8 text
11848  * ARGF.set_encoding('utf-8','ascii') # Transcode the input from US-ASCII
11849  * # to UTF-8.
11850  */
11851 static VALUE
11852 argf_set_encoding(int argc, VALUE *argv, VALUE argf)
11853 {
11854  rb_io_t *fptr;
11855 
11856  if (!next_argv()) {
11857  rb_raise(rb_eArgError, "no stream to set encoding");
11858  }
11859  rb_io_set_encoding(argc, argv, ARGF.current_file);
11860  GetOpenFile(ARGF.current_file, fptr);
11861  ARGF.encs = fptr->encs;
11862  return argf;
11863 }
11864 
11865 /*
11866  * call-seq:
11867  * ARGF.tell -> Integer
11868  * ARGF.pos -> Integer
11869  *
11870  * Returns the current offset (in bytes) of the current file in +ARGF+.
11871  *
11872  * ARGF.pos #=> 0
11873  * ARGF.gets #=> "This is line one\n"
11874  * ARGF.pos #=> 17
11875  *
11876  */
11877 static VALUE
11878 argf_tell(VALUE argf)
11879 {
11880  if (!next_argv()) {
11881  rb_raise(rb_eArgError, "no stream to tell");
11882  }
11883  ARGF_FORWARD(0, 0);
11884  return rb_io_tell(ARGF.current_file);
11885 }
11886 
11887 /*
11888  * call-seq:
11889  * ARGF.seek(amount, whence=IO::SEEK_SET) -> 0
11890  *
11891  * Seeks to offset _amount_ (an +Integer+) in the +ARGF+ stream according to
11892  * the value of _whence_. See IO#seek for further details.
11893  */
11894 static VALUE
11895 argf_seek_m(int argc, VALUE *argv, VALUE argf)
11896 {
11897  if (!next_argv()) {
11898  rb_raise(rb_eArgError, "no stream to seek");
11899  }
11901  return rb_io_seek_m(argc, argv, ARGF.current_file);
11902 }
11903 
11904 /*
11905  * call-seq:
11906  * ARGF.pos = position -> Integer
11907  *
11908  * Seeks to the position given by _position_ (in bytes) in +ARGF+.
11909  *
11910  * For example:
11911  *
11912  * ARGF.pos = 17
11913  * ARGF.gets #=> "This is line two\n"
11914  */
11915 static VALUE
11916 argf_set_pos(VALUE argf, VALUE offset)
11917 {
11918  if (!next_argv()) {
11919  rb_raise(rb_eArgError, "no stream to set position");
11920  }
11921  ARGF_FORWARD(1, &offset);
11922  return rb_io_set_pos(ARGF.current_file, offset);
11923 }
11924 
11925 /*
11926  * call-seq:
11927  * ARGF.rewind -> 0
11928  *
11929  * Positions the current file to the beginning of input, resetting
11930  * +ARGF.lineno+ to zero.
11931  *
11932  * ARGF.readline #=> "This is line one\n"
11933  * ARGF.rewind #=> 0
11934  * ARGF.lineno #=> 0
11935  * ARGF.readline #=> "This is line one\n"
11936  */
11937 static VALUE
11938 argf_rewind(VALUE argf)
11939 {
11940  VALUE ret;
11941  int old_lineno;
11942 
11943  if (!next_argv()) {
11944  rb_raise(rb_eArgError, "no stream to rewind");
11945  }
11946  ARGF_FORWARD(0, 0);
11947  old_lineno = RFILE(ARGF.current_file)->fptr->lineno;
11948  ret = rb_io_rewind(ARGF.current_file);
11949  if (!global_argf_p(argf)) {
11950  ARGF.last_lineno = ARGF.lineno -= old_lineno;
11951  }
11952  return ret;
11953 }
11954 
11955 /*
11956  * call-seq:
11957  * ARGF.fileno -> integer
11958  * ARGF.to_i -> integer
11959  *
11960  * Returns an integer representing the numeric file descriptor for
11961  * the current file. Raises an +ArgumentError+ if there isn't a current file.
11962  *
11963  * ARGF.fileno #=> 3
11964  */
11965 static VALUE
11966 argf_fileno(VALUE argf)
11967 {
11968  if (!next_argv()) {
11969  rb_raise(rb_eArgError, "no stream");
11970  }
11971  ARGF_FORWARD(0, 0);
11972  return rb_io_fileno(ARGF.current_file);
11973 }
11974 
11975 /*
11976  * call-seq:
11977  * ARGF.to_io -> IO
11978  *
11979  * Returns an +IO+ object representing the current file. This will be a
11980  * +File+ object unless the current file is a stream such as STDIN.
11981  *
11982  * For example:
11983  *
11984  * ARGF.to_io #=> #<File:glark.txt>
11985  * ARGF.to_io #=> #<IO:<STDIN>>
11986  */
11987 static VALUE
11988 argf_to_io(VALUE argf)
11989 {
11990  next_argv();
11991  ARGF_FORWARD(0, 0);
11992  return ARGF.current_file;
11993 }
11994 
11995 /*
11996  * call-seq:
11997  * ARGF.eof? -> true or false
11998  * ARGF.eof -> true or false
11999  *
12000  * Returns true if the current file in +ARGF+ is at end of file, i.e. it has
12001  * no data to read. The stream must be opened for reading or an +IOError+
12002  * will be raised.
12003  *
12004  * $ echo "eof" | ruby argf.rb
12005  *
12006  * ARGF.eof? #=> false
12007  * 3.times { ARGF.readchar }
12008  * ARGF.eof? #=> false
12009  * ARGF.readchar #=> "\n"
12010  * ARGF.eof? #=> true
12011  */
12012 
12013 static VALUE
12014 argf_eof(VALUE argf)
12015 {
12016  next_argv();
12017  if (RTEST(ARGF.current_file)) {
12018  if (ARGF.init_p == 0) return Qtrue;
12019  next_argv();
12020  ARGF_FORWARD(0, 0);
12021  if (rb_io_eof(ARGF.current_file)) {
12022  return Qtrue;
12023  }
12024  }
12025  return Qfalse;
12026 }
12027 
12028 /*
12029  * call-seq:
12030  * ARGF.read([length [, outbuf]]) -> string, outbuf, or nil
12031  *
12032  * Reads _length_ bytes from ARGF. The files named on the command line
12033  * are concatenated and treated as a single file by this method, so when
12034  * called without arguments the contents of this pseudo file are returned in
12035  * their entirety.
12036  *
12037  * _length_ must be a non-negative integer or +nil+.
12038  *
12039  * If _length_ is a positive integer, +read+ tries to read
12040  * _length_ bytes without any conversion (binary mode).
12041  * It returns +nil+ if an EOF is encountered before anything can be read.
12042  * Fewer than _length_ bytes are returned if an EOF is encountered during
12043  * the read.
12044  * In the case of an integer _length_, the resulting string is always
12045  * in ASCII-8BIT encoding.
12046  *
12047  * If _length_ is omitted or is +nil+, it reads until EOF
12048  * and the encoding conversion is applied, if applicable.
12049  * A string is returned even if EOF is encountered before any data is read.
12050  *
12051  * If _length_ is zero, it returns an empty string (<code>""</code>).
12052  *
12053  * If the optional _outbuf_ argument is present,
12054  * it must reference a String, which will receive the data.
12055  * The _outbuf_ will contain only the received data after the method call
12056  * even if it is not empty at the beginning.
12057  *
12058  * For example:
12059  *
12060  * $ echo "small" > small.txt
12061  * $ echo "large" > large.txt
12062  * $ ./glark.rb small.txt large.txt
12063  *
12064  * ARGF.read #=> "small\nlarge"
12065  * ARGF.read(200) #=> "small\nlarge"
12066  * ARGF.read(2) #=> "sm"
12067  * ARGF.read(0) #=> ""
12068  *
12069  * Note that this method behaves like the fread() function in C.
12070  * This means it retries to invoke read(2) system calls to read data
12071  * with the specified length.
12072  * If you need the behavior like a single read(2) system call,
12073  * consider ARGF#readpartial or ARGF#read_nonblock.
12074  */
12075 
12076 static VALUE
12077 argf_read(int argc, VALUE *argv, VALUE argf)
12078 {
12079  VALUE tmp, str, length;
12080  long len = 0;
12081 
12082  rb_scan_args(argc, argv, "02", &length, &str);
12083  if (!NIL_P(length)) {
12084  len = NUM2LONG(argv[0]);
12085  }
12086  if (!NIL_P(str)) {
12087  StringValue(str);
12088  rb_str_resize(str,0);
12089  argv[1] = Qnil;
12090  }
12091 
12092  retry:
12093  if (!next_argv()) {
12094  return str;
12095  }
12096  if (ARGF_GENERIC_INPUT_P()) {
12097  tmp = argf_forward(argc, argv, argf);
12098  }
12099  else {
12100  tmp = io_read(argc, argv, ARGF.current_file);
12101  }
12102  if (NIL_P(str)) str = tmp;
12103  else if (!NIL_P(tmp)) rb_str_append(str, tmp);
12104  if (NIL_P(tmp) || NIL_P(length)) {
12105  if (ARGF.next_p != -1) {
12106  argf_close(argf);
12107  ARGF.next_p = 1;
12108  goto retry;
12109  }
12110  }
12111  else if (argc >= 1) {
12112  long slen = RSTRING_LEN(str);
12113  if (slen < len) {
12114  len -= slen;
12115  argv[0] = INT2NUM(len);
12116  goto retry;
12117  }
12118  }
12119  return str;
12120 }
12121 
12123  int argc;
12126 };
12127 
12128 static VALUE
12129 argf_forward_call(VALUE arg)
12130 {
12131  struct argf_call_arg *p = (struct argf_call_arg *)arg;
12132  argf_forward(p->argc, p->argv, p->argf);
12133  return Qnil;
12134 }
12135 
12136 static VALUE argf_getpartial(int argc, VALUE *argv, VALUE argf, VALUE opts,
12137  int nonblock);
12138 
12139 /*
12140  * call-seq:
12141  * ARGF.readpartial(maxlen) -> string
12142  * ARGF.readpartial(maxlen, outbuf) -> outbuf
12143  *
12144  * Reads at most _maxlen_ bytes from the ARGF stream.
12145  *
12146  * If the optional _outbuf_ argument is present,
12147  * it must reference a String, which will receive the data.
12148  * The _outbuf_ will contain only the received data after the method call
12149  * even if it is not empty at the beginning.
12150  *
12151  * It raises EOFError on end of ARGF stream.
12152  * Since ARGF stream is a concatenation of multiple files,
12153  * internally EOF is occur for each file.
12154  * ARGF.readpartial returns empty strings for EOFs except the last one and
12155  * raises EOFError for the last one.
12156  *
12157  */
12158 
12159 static VALUE
12160 argf_readpartial(int argc, VALUE *argv, VALUE argf)
12161 {
12162  return argf_getpartial(argc, argv, argf, Qnil, 0);
12163 }
12164 
12165 /*
12166  * call-seq:
12167  * ARGF.read_nonblock(maxlen[, options]) -> string
12168  * ARGF.read_nonblock(maxlen, outbuf[, options]) -> outbuf
12169  *
12170  * Reads at most _maxlen_ bytes from the ARGF stream in non-blocking mode.
12171  */
12172 
12173 static VALUE
12174 argf_read_nonblock(int argc, VALUE *argv, VALUE argf)
12175 {
12176  VALUE opts;
12177 
12178  rb_scan_args(argc, argv, "11:", NULL, NULL, &opts);
12179 
12180  if (!NIL_P(opts))
12181  argc--;
12182 
12183  return argf_getpartial(argc, argv, argf, opts, 1);
12184 }
12185 
12186 static VALUE
12187 argf_getpartial(int argc, VALUE *argv, VALUE argf, VALUE opts, int nonblock)
12188 {
12189  VALUE tmp, str, length;
12190  int no_exception;
12191 
12192  rb_scan_args(argc, argv, "11", &length, &str);
12193  if (!NIL_P(str)) {
12194  StringValue(str);
12195  argv[1] = str;
12196  }
12197  no_exception = no_exception_p(opts);
12198 
12199  if (!next_argv()) {
12200  if (!NIL_P(str)) {
12201  rb_str_resize(str, 0);
12202  }
12203  rb_eof_error();
12204  }
12205  if (ARGF_GENERIC_INPUT_P()) {
12206  VALUE (*const rescue_does_nothing)(VALUE, VALUE) = 0;
12207  struct argf_call_arg arg;
12208  arg.argc = argc;
12209  arg.argv = argv;
12210  arg.argf = argf;
12211  tmp = rb_rescue2(argf_forward_call, (VALUE)&arg,
12212  rescue_does_nothing, Qnil, rb_eEOFError, (VALUE)0);
12213  }
12214  else {
12215  tmp = io_getpartial(argc, argv, ARGF.current_file, no_exception, nonblock);
12216  }
12217  if (NIL_P(tmp)) {
12218  if (ARGF.next_p == -1) {
12219  return io_nonblock_eof(no_exception);
12220  }
12221  argf_close(argf);
12222  ARGF.next_p = 1;
12223  if (RARRAY_LEN(ARGF.argv) == 0) {
12224  return io_nonblock_eof(no_exception);
12225  }
12226  if (NIL_P(str))
12227  str = rb_str_new(NULL, 0);
12228  return str;
12229  }
12230  return tmp;
12231 }
12232 
12233 /*
12234  * call-seq:
12235  * ARGF.getc -> String or nil
12236  *
12237  * Reads the next character from +ARGF+ and returns it as a +String+. Returns
12238  * +nil+ at the end of the stream.
12239  *
12240  * +ARGF+ treats the files named on the command line as a single file created
12241  * by concatenating their contents. After returning the last character of the
12242  * first file, it returns the first character of the second file, and so on.
12243  *
12244  * For example:
12245  *
12246  * $ echo "foo" > file
12247  * $ ruby argf.rb file
12248  *
12249  * ARGF.getc #=> "f"
12250  * ARGF.getc #=> "o"
12251  * ARGF.getc #=> "o"
12252  * ARGF.getc #=> "\n"
12253  * ARGF.getc #=> nil
12254  * ARGF.getc #=> nil
12255  */
12256 static VALUE
12257 argf_getc(VALUE argf)
12258 {
12259  VALUE ch;
12260 
12261  retry:
12262  if (!next_argv()) return Qnil;
12263  if (ARGF_GENERIC_INPUT_P()) {
12264  ch = rb_funcall3(ARGF.current_file, rb_intern("getc"), 0, 0);
12265  }
12266  else {
12267  ch = rb_io_getc(ARGF.current_file);
12268  }
12269  if (NIL_P(ch) && ARGF.next_p != -1) {
12270  argf_close(argf);
12271  ARGF.next_p = 1;
12272  goto retry;
12273  }
12274 
12275  return ch;
12276 }
12277 
12278 /*
12279  * call-seq:
12280  * ARGF.getbyte -> Integer or nil
12281  *
12282  * Gets the next 8-bit byte (0..255) from +ARGF+. Returns +nil+ if called at
12283  * the end of the stream.
12284  *
12285  * For example:
12286  *
12287  * $ echo "foo" > file
12288  * $ ruby argf.rb file
12289  *
12290  * ARGF.getbyte #=> 102
12291  * ARGF.getbyte #=> 111
12292  * ARGF.getbyte #=> 111
12293  * ARGF.getbyte #=> 10
12294  * ARGF.getbyte #=> nil
12295  */
12296 static VALUE
12297 argf_getbyte(VALUE argf)
12298 {
12299  VALUE ch;
12300 
12301  retry:
12302  if (!next_argv()) return Qnil;
12303  if (!RB_TYPE_P(ARGF.current_file, T_FILE)) {
12304  ch = rb_funcall3(ARGF.current_file, rb_intern("getbyte"), 0, 0);
12305  }
12306  else {
12307  ch = rb_io_getbyte(ARGF.current_file);
12308  }
12309  if (NIL_P(ch) && ARGF.next_p != -1) {
12310  argf_close(argf);
12311  ARGF.next_p = 1;
12312  goto retry;
12313  }
12314 
12315  return ch;
12316 }
12317 
12318 /*
12319  * call-seq:
12320  * ARGF.readchar -> String or nil
12321  *
12322  * Reads the next character from +ARGF+ and returns it as a +String+. Raises
12323  * an +EOFError+ after the last character of the last file has been read.
12324  *
12325  * For example:
12326  *
12327  * $ echo "foo" > file
12328  * $ ruby argf.rb file
12329  *
12330  * ARGF.readchar #=> "f"
12331  * ARGF.readchar #=> "o"
12332  * ARGF.readchar #=> "o"
12333  * ARGF.readchar #=> "\n"
12334  * ARGF.readchar #=> end of file reached (EOFError)
12335  */
12336 static VALUE
12337 argf_readchar(VALUE argf)
12338 {
12339  VALUE ch;
12340 
12341  retry:
12342  if (!next_argv()) rb_eof_error();
12343  if (!RB_TYPE_P(ARGF.current_file, T_FILE)) {
12344  ch = rb_funcall3(ARGF.current_file, rb_intern("getc"), 0, 0);
12345  }
12346  else {
12347  ch = rb_io_getc(ARGF.current_file);
12348  }
12349  if (NIL_P(ch) && ARGF.next_p != -1) {
12350  argf_close(argf);
12351  ARGF.next_p = 1;
12352  goto retry;
12353  }
12354 
12355  return ch;
12356 }
12357 
12358 /*
12359  * call-seq:
12360  * ARGF.readbyte -> Integer
12361  *
12362  * Reads the next 8-bit byte from ARGF and returns it as an +Integer+. Raises
12363  * an +EOFError+ after the last byte of the last file has been read.
12364  *
12365  * For example:
12366  *
12367  * $ echo "foo" > file
12368  * $ ruby argf.rb file
12369  *
12370  * ARGF.readbyte #=> 102
12371  * ARGF.readbyte #=> 111
12372  * ARGF.readbyte #=> 111
12373  * ARGF.readbyte #=> 10
12374  * ARGF.readbyte #=> end of file reached (EOFError)
12375  */
12376 static VALUE
12377 argf_readbyte(VALUE argf)
12378 {
12379  VALUE c;
12380 
12381  NEXT_ARGF_FORWARD(0, 0);
12382  c = argf_getbyte(argf);
12383  if (NIL_P(c)) {
12384  rb_eof_error();
12385  }
12386  return c;
12387 }
12388 
12389 #define FOREACH_ARGF() while (next_argv())
12390 
12391 static VALUE
12392 argf_block_call_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, argf))
12393 {
12394  const VALUE current = ARGF.current_file;
12396  if (ARGF.init_p == -1 || current != ARGF.current_file) {
12398  }
12399  return Qnil;
12400 }
12401 
12402 #define ARGF_block_call(mid, argc, argv, func, argf) \
12403  rb_block_call_kw(ARGF.current_file, mid, argc, argv, \
12404  func, argf, rb_keyword_given_p())
12405 
12406 static void
12407 argf_block_call(ID mid, int argc, VALUE *argv, VALUE argf)
12408 {
12409  VALUE ret = ARGF_block_call(mid, argc, argv, argf_block_call_i, argf);
12410  if (ret != Qundef) ARGF.next_p = 1;
12411 }
12412 
12413 static VALUE
12414 argf_block_call_line_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, argf))
12415 {
12416  if (!global_argf_p(argf)) {
12417  ARGF.last_lineno = ++ARGF.lineno;
12418  }
12419  return argf_block_call_i(i, argf, argc, argv, blockarg);
12420 }
12421 
12422 static void
12423 argf_block_call_line(ID mid, int argc, VALUE *argv, VALUE argf)
12424 {
12425  VALUE ret = ARGF_block_call(mid, argc, argv, argf_block_call_line_i, argf);
12426  if (ret != Qundef) ARGF.next_p = 1;
12427 }
12428 
12429 /*
12430  * call-seq:
12431  * ARGF.each(sep=$/) {|line| block } -> ARGF
12432  * ARGF.each(sep=$/, limit) {|line| block } -> ARGF
12433  * ARGF.each(...) -> an_enumerator
12434  *
12435  * ARGF.each_line(sep=$/) {|line| block } -> ARGF
12436  * ARGF.each_line(sep=$/, limit) {|line| block } -> ARGF
12437  * ARGF.each_line(...) -> an_enumerator
12438  *
12439  * Returns an enumerator which iterates over each line (separated by _sep_,
12440  * which defaults to your platform's newline character) of each file in
12441  * +ARGV+. If a block is supplied, each line in turn will be yielded to the
12442  * block, otherwise an enumerator is returned.
12443  * The optional _limit_ argument is an +Integer+ specifying the maximum
12444  * length of each line; longer lines will be split according to this limit.
12445  *
12446  * This method allows you to treat the files supplied on the command line as
12447  * a single file consisting of the concatenation of each named file. After
12448  * the last line of the first file has been returned, the first line of the
12449  * second file is returned. The +ARGF.filename+ and +ARGF.lineno+ methods can
12450  * be used to determine the filename of the current line and line number of
12451  * the whole input, respectively.
12452  *
12453  * For example, the following code prints out each line of each named file
12454  * prefixed with its line number, displaying the filename once per file:
12455  *
12456  * ARGF.each_line do |line|
12457  * puts ARGF.filename if ARGF.file.lineno == 1
12458  * puts "#{ARGF.file.lineno}: #{line}"
12459  * end
12460  *
12461  * While the following code prints only the first file's name at first, and
12462  * the contents with line number counted through all named files.
12463  *
12464  * ARGF.each_line do |line|
12465  * puts ARGF.filename if ARGF.lineno == 1
12466  * puts "#{ARGF.lineno}: #{line}"
12467  * end
12468  */
12469 static VALUE
12470 argf_each_line(int argc, VALUE *argv, VALUE argf)
12471 {
12473  FOREACH_ARGF() {
12474  argf_block_call_line(rb_intern("each_line"), argc, argv, argf);
12475  }
12476  return argf;
12477 }
12478 
12479 /*
12480  * This is a deprecated alias for #each_line.
12481  */
12482 
12483 static VALUE
12484 argf_lines(int argc, VALUE *argv, VALUE argf)
12485 {
12486  rb_warn_deprecated("ARGF#lines", "#each_line");
12487  if (!rb_block_given_p())
12488  return rb_enumeratorize(argf, ID2SYM(rb_intern("each_line")), argc, argv);
12489  return argf_each_line(argc, argv, argf);
12490 }
12491 
12492 /*
12493  * call-seq:
12494  * ARGF.bytes {|byte| block } -> ARGF
12495  * ARGF.bytes -> an_enumerator
12496  *
12497  * ARGF.each_byte {|byte| block } -> ARGF
12498  * ARGF.each_byte -> an_enumerator
12499  *
12500  * Iterates over each byte of each file in +ARGV+.
12501  * A byte is returned as an +Integer+ in the range 0..255.
12502  *
12503  * This method allows you to treat the files supplied on the command line as
12504  * a single file consisting of the concatenation of each named file. After
12505  * the last byte of the first file has been returned, the first byte of the
12506  * second file is returned. The +ARGF.filename+ method can be used to
12507  * determine the filename of the current byte.
12508  *
12509  * If no block is given, an enumerator is returned instead.
12510  *
12511  * For example:
12512  *
12513  * ARGF.bytes.to_a #=> [35, 32, ... 95, 10]
12514  *
12515  */
12516 static VALUE
12517 argf_each_byte(VALUE argf)
12518 {
12519  RETURN_ENUMERATOR(argf, 0, 0);
12520  FOREACH_ARGF() {
12521  argf_block_call(rb_intern("each_byte"), 0, 0, argf);
12522  }
12523  return argf;
12524 }
12525 
12526 /*
12527  * This is a deprecated alias for #each_byte.
12528  */
12529 
12530 static VALUE
12531 argf_bytes(VALUE argf)
12532 {
12533  rb_warn_deprecated("ARGF#bytes", "#each_byte");
12534  if (!rb_block_given_p())
12535  return rb_enumeratorize(argf, ID2SYM(rb_intern("each_byte")), 0, 0);
12536  return argf_each_byte(argf);
12537 }
12538 
12539 /*
12540  * call-seq:
12541  * ARGF.each_char {|char| block } -> ARGF
12542  * ARGF.each_char -> an_enumerator
12543  *
12544  * Iterates over each character of each file in +ARGF+.
12545  *
12546  * This method allows you to treat the files supplied on the command line as
12547  * a single file consisting of the concatenation of each named file. After
12548  * the last character of the first file has been returned, the first
12549  * character of the second file is returned. The +ARGF.filename+ method can
12550  * be used to determine the name of the file in which the current character
12551  * appears.
12552  *
12553  * If no block is given, an enumerator is returned instead.
12554  */
12555 static VALUE
12556 argf_each_char(VALUE argf)
12557 {
12558  RETURN_ENUMERATOR(argf, 0, 0);
12559  FOREACH_ARGF() {
12560  argf_block_call(rb_intern("each_char"), 0, 0, argf);
12561  }
12562  return argf;
12563 }
12564 
12565 /*
12566  * This is a deprecated alias for #each_char.
12567  */
12568 
12569 static VALUE
12570 argf_chars(VALUE argf)
12571 {
12572  rb_warn_deprecated("ARGF#chars", "#each_char");
12573  if (!rb_block_given_p())
12574  return rb_enumeratorize(argf, ID2SYM(rb_intern("each_char")), 0, 0);
12575  return argf_each_char(argf);
12576 }
12577 
12578 /*
12579  * call-seq:
12580  * ARGF.each_codepoint {|codepoint| block } -> ARGF
12581  * ARGF.each_codepoint -> an_enumerator
12582  *
12583  * Iterates over each codepoint of each file in +ARGF+.
12584  *
12585  * This method allows you to treat the files supplied on the command line as
12586  * a single file consisting of the concatenation of each named file. After
12587  * the last codepoint of the first file has been returned, the first
12588  * codepoint of the second file is returned. The +ARGF.filename+ method can
12589  * be used to determine the name of the file in which the current codepoint
12590  * appears.
12591  *
12592  * If no block is given, an enumerator is returned instead.
12593  */
12594 static VALUE
12595 argf_each_codepoint(VALUE argf)
12596 {
12597  RETURN_ENUMERATOR(argf, 0, 0);
12598  FOREACH_ARGF() {
12599  argf_block_call(rb_intern("each_codepoint"), 0, 0, argf);
12600  }
12601  return argf;
12602 }
12603 
12604 /*
12605  * This is a deprecated alias for #each_codepoint.
12606  */
12607 
12608 static VALUE
12609 argf_codepoints(VALUE argf)
12610 {
12611  rb_warn_deprecated("ARGF#codepoints", "#each_codepoint");
12612  if (!rb_block_given_p())
12613  return rb_enumeratorize(argf, ID2SYM(rb_intern("each_codepoint")), 0, 0);
12614  return argf_each_codepoint(argf);
12615 }
12616 
12617 /*
12618  * call-seq:
12619  * ARGF.filename -> String
12620  * ARGF.path -> String
12621  *
12622  * Returns the current filename. "-" is returned when the current file is
12623  * STDIN.
12624  *
12625  * For example:
12626  *
12627  * $ echo "foo" > foo
12628  * $ echo "bar" > bar
12629  * $ echo "glark" > glark
12630  *
12631  * $ ruby argf.rb foo bar glark
12632  *
12633  * ARGF.filename #=> "foo"
12634  * ARGF.read(5) #=> "foo\nb"
12635  * ARGF.filename #=> "bar"
12636  * ARGF.skip
12637  * ARGF.filename #=> "glark"
12638  */
12639 static VALUE
12640 argf_filename(VALUE argf)
12641 {
12642  next_argv();
12643  return ARGF.filename;
12644 }
12645 
12646 static VALUE
12647 argf_filename_getter(ID id, VALUE *var)
12648 {
12649  return argf_filename(*var);
12650 }
12651 
12652 /*
12653  * call-seq:
12654  * ARGF.file -> IO or File object
12655  *
12656  * Returns the current file as an +IO+ or +File+ object.
12657  * <code>$stdin</code> is returned when the current file is STDIN.
12658  *
12659  * For example:
12660  *
12661  * $ echo "foo" > foo
12662  * $ echo "bar" > bar
12663  *
12664  * $ ruby argf.rb foo bar
12665  *
12666  * ARGF.file #=> #<File:foo>
12667  * ARGF.read(5) #=> "foo\nb"
12668  * ARGF.file #=> #<File:bar>
12669  */
12670 static VALUE
12671 argf_file(VALUE argf)
12672 {
12673  next_argv();
12674  return ARGF.current_file;
12675 }
12676 
12677 /*
12678  * call-seq:
12679  * ARGF.binmode -> ARGF
12680  *
12681  * Puts +ARGF+ into binary mode. Once a stream is in binary mode, it cannot
12682  * be reset to non-binary mode. This option has the following effects:
12683  *
12684  * * Newline conversion is disabled.
12685  * * Encoding conversion is disabled.
12686  * * Content is treated as ASCII-8BIT.
12687  */
12688 static VALUE
12689 argf_binmode_m(VALUE argf)
12690 {
12691  ARGF.binmode = 1;
12692  next_argv();
12693  ARGF_FORWARD(0, 0);
12694  rb_io_ascii8bit_binmode(ARGF.current_file);
12695  return argf;
12696 }
12697 
12698 /*
12699  * call-seq:
12700  * ARGF.binmode? -> true or false
12701  *
12702  * Returns true if +ARGF+ is being read in binary mode; false otherwise.
12703  * To enable binary mode use +ARGF.binmode+.
12704  *
12705  * For example:
12706  *
12707  * ARGF.binmode? #=> false
12708  * ARGF.binmode
12709  * ARGF.binmode? #=> true
12710  */
12711 static VALUE
12712 argf_binmode_p(VALUE argf)
12713 {
12714  return ARGF.binmode ? Qtrue : Qfalse;
12715 }
12716 
12717 /*
12718  * call-seq:
12719  * ARGF.skip -> ARGF
12720  *
12721  * Sets the current file to the next file in ARGV. If there aren't any more
12722  * files it has no effect.
12723  *
12724  * For example:
12725  *
12726  * $ ruby argf.rb foo bar
12727  * ARGF.filename #=> "foo"
12728  * ARGF.skip
12729  * ARGF.filename #=> "bar"
12730  */
12731 static VALUE
12732 argf_skip(VALUE argf)
12733 {
12734  if (ARGF.init_p && ARGF.next_p == 0) {
12735  argf_close(argf);
12736  ARGF.next_p = 1;
12737  }
12738  return argf;
12739 }
12740 
12741 /*
12742  * call-seq:
12743  * ARGF.close -> ARGF
12744  *
12745  * Closes the current file and skips to the next file in ARGV. If there are
12746  * no more files to open, just closes the current file. +STDIN+ will not be
12747  * closed.
12748  *
12749  * For example:
12750  *
12751  * $ ruby argf.rb foo bar
12752  *
12753  * ARGF.filename #=> "foo"
12754  * ARGF.close
12755  * ARGF.filename #=> "bar"
12756  * ARGF.close
12757  */
12758 static VALUE
12759 argf_close_m(VALUE argf)
12760 {
12761  next_argv();
12762  argf_close(argf);
12763  if (ARGF.next_p != -1) {
12764  ARGF.next_p = 1;
12765  }
12766  ARGF.lineno = 0;
12767  return argf;
12768 }
12769 
12770 /*
12771  * call-seq:
12772  * ARGF.closed? -> true or false
12773  *
12774  * Returns _true_ if the current file has been closed; _false_ otherwise. Use
12775  * +ARGF.close+ to actually close the current file.
12776  */
12777 static VALUE
12778 argf_closed(VALUE argf)
12779 {
12780  next_argv();
12781  ARGF_FORWARD(0, 0);
12782  return rb_io_closed(ARGF.current_file);
12783 }
12784 
12785 /*
12786  * call-seq:
12787  * ARGF.to_s -> String
12788  *
12789  * Returns "ARGF".
12790  */
12791 static VALUE
12792 argf_to_s(VALUE argf)
12793 {
12794  return rb_str_new2("ARGF");
12795 }
12796 
12797 /*
12798  * call-seq:
12799  * ARGF.inplace_mode -> String
12800  *
12801  * Returns the file extension appended to the names of modified files under
12802  * in-place edit mode. This value can be set using +ARGF.inplace_mode=+ or
12803  * passing the +-i+ switch to the Ruby binary.
12804  */
12805 static VALUE
12806 argf_inplace_mode_get(VALUE argf)
12807 {
12808  if (!ARGF.inplace) return Qnil;
12809  if (NIL_P(ARGF.inplace)) return rb_str_new(0, 0);
12810  return rb_str_dup(ARGF.inplace);
12811 }
12812 
12813 static VALUE
12814 opt_i_get(ID id, VALUE *var)
12815 {
12816  return argf_inplace_mode_get(*var);
12817 }
12818 
12819 /*
12820  * call-seq:
12821  * ARGF.inplace_mode = ext -> ARGF
12822  *
12823  * Sets the filename extension for in-place editing mode to the given String.
12824  * Each file being edited has this value appended to its filename. The
12825  * modified file is saved under this new name.
12826  *
12827  * For example:
12828  *
12829  * $ ruby argf.rb file.txt
12830  *
12831  * ARGF.inplace_mode = '.bak'
12832  * ARGF.each_line do |line|
12833  * print line.sub("foo","bar")
12834  * end
12835  *
12836  * Each line of _file.txt_ has the first occurrence of "foo" replaced with
12837  * "bar", then the new line is written out to _file.txt.bak_.
12838  */
12839 static VALUE
12840 argf_inplace_mode_set(VALUE argf, VALUE val)
12841 {
12842  if (!RTEST(val)) {
12843  ARGF.inplace = Qfalse;
12844  }
12845  else if (StringValueCStr(val), !RSTRING_LEN(val)) {
12846  ARGF.inplace = Qnil;
12847  }
12848  else {
12849  ARGF.inplace = rb_str_new_frozen(val);
12850  }
12851  return argf;
12852 }
12853 
12854 static void
12855 opt_i_set(VALUE val, ID id, VALUE *var)
12856 {
12857  argf_inplace_mode_set(*var, val);
12858 }
12859 
12860 void
12861 ruby_set_inplace_mode(const char *suffix)
12862 {
12863  ARGF.inplace = !suffix ? Qfalse : !*suffix ? Qnil : rb_fstring_cstr(suffix);
12864 }
12865 
12866 /*
12867  * call-seq:
12868  * ARGF.argv -> ARGV
12869  *
12870  * Returns the +ARGV+ array, which contains the arguments passed to your
12871  * script, one per element.
12872  *
12873  * For example:
12874  *
12875  * $ ruby argf.rb -v glark.txt
12876  *
12877  * ARGF.argv #=> ["-v", "glark.txt"]
12878  *
12879  */
12880 static VALUE
12881 argf_argv(VALUE argf)
12882 {
12883  return ARGF.argv;
12884 }
12885 
12886 static VALUE
12887 argf_argv_getter(ID id, VALUE *var)
12888 {
12889  return argf_argv(*var);
12890 }
12891 
12892 VALUE
12894 {
12895  return ARGF.argv;
12896 }
12897 
12898 /*
12899  * call-seq:
12900  * ARGF.to_write_io -> io
12901  *
12902  * Returns IO instance tied to _ARGF_ for writing if inplace mode is
12903  * enabled.
12904  */
12905 static VALUE
12906 argf_write_io(VALUE argf)
12907 {
12908  if (!RTEST(ARGF.current_file)) {
12909  rb_raise(rb_eIOError, "not opened for writing");
12910  }
12911  return GetWriteIO(ARGF.current_file);
12912 }
12913 
12914 /*
12915  * call-seq:
12916  * ARGF.write(string) -> integer
12917  *
12918  * Writes _string_ if inplace mode.
12919  */
12920 static VALUE
12921 argf_write(VALUE argf, VALUE str)
12922 {
12923  return rb_io_write(argf_write_io(argf), str);
12924 }
12925 
12926 void
12927 rb_readwrite_sys_fail(enum rb_io_wait_readwrite writable, const char *mesg)
12928 {
12929  rb_readwrite_syserr_fail(writable, errno, mesg);
12930 }
12931 
12932 void
12933 rb_readwrite_syserr_fail(enum rb_io_wait_readwrite writable, int n, const char *mesg)
12934 {
12935  VALUE arg;
12936  arg = mesg ? rb_str_new2(mesg) : Qnil;
12937  if (writable == RB_IO_WAIT_WRITABLE) {
12938  switch (n) {
12939  case EAGAIN:
12940  rb_exc_raise(rb_class_new_instance(1, &arg, rb_eEAGAINWaitWritable));
12941  break;
12942 #if EAGAIN != EWOULDBLOCK
12943  case EWOULDBLOCK:
12944  rb_exc_raise(rb_class_new_instance(1, &arg, rb_eEWOULDBLOCKWaitWritable));
12945  break;
12946 #endif
12947  case EINPROGRESS:
12948  rb_exc_raise(rb_class_new_instance(1, &arg, rb_eEINPROGRESSWaitWritable));
12949  break;
12950  default:
12952  }
12953  }
12954  else if (writable == RB_IO_WAIT_READABLE) {
12955  switch (n) {
12956  case EAGAIN:
12957  rb_exc_raise(rb_class_new_instance(1, &arg, rb_eEAGAINWaitReadable));
12958  break;
12959 #if EAGAIN != EWOULDBLOCK
12960  case EWOULDBLOCK:
12961  rb_exc_raise(rb_class_new_instance(1, &arg, rb_eEWOULDBLOCKWaitReadable));
12962  break;
12963 #endif
12964  case EINPROGRESS:
12965  rb_exc_raise(rb_class_new_instance(1, &arg, rb_eEINPROGRESSWaitReadable));
12966  break;
12967  default:
12969  }
12970  }
12971  else {
12972  rb_bug("invalid read/write type passed to rb_readwrite_sys_fail: %d", writable);
12973  }
12974 }
12975 
12976 static VALUE
12977 get_LAST_READ_LINE(ID _x, VALUE *_y)
12978 {
12979  return rb_lastline_get();
12980 }
12981 
12982 static void
12983 set_LAST_READ_LINE(VALUE val, ID _x, VALUE *_y)
12984 {
12985  rb_lastline_set(val);
12986 }
12987 
12988 /*
12989  * Document-class: IOError
12990  *
12991  * Raised when an IO operation fails.
12992  *
12993  * File.open("/etc/hosts") {|f| f << "example"}
12994  * #=> IOError: not opened for writing
12995  *
12996  * File.open("/etc/hosts") {|f| f.close; f.read }
12997  * #=> IOError: closed stream
12998  *
12999  * Note that some IO failures raise <code>SystemCallError</code>s
13000  * and these are not subclasses of IOError:
13001  *
13002  * File.open("does/not/exist")
13003  * #=> Errno::ENOENT: No such file or directory - does/not/exist
13004  */
13005 
13006 /*
13007  * Document-class: EOFError
13008  *
13009  * Raised by some IO operations when reaching the end of file. Many IO
13010  * methods exist in two forms,
13011  *
13012  * one that returns +nil+ when the end of file is reached, the other
13013  * raises +EOFError+.
13014  *
13015  * +EOFError+ is a subclass of +IOError+.
13016  *
13017  * file = File.open("/etc/hosts")
13018  * file.read
13019  * file.gets #=> nil
13020  * file.readline #=> EOFError: end of file reached
13021  */
13022 
13023 /*
13024  * Document-class: ARGF
13025  *
13026  * +ARGF+ is a stream designed for use in scripts that process files given as
13027  * command-line arguments or passed in via STDIN.
13028  *
13029  * The arguments passed to your script are stored in the +ARGV+ Array, one
13030  * argument per element. +ARGF+ assumes that any arguments that aren't
13031  * filenames have been removed from +ARGV+. For example:
13032  *
13033  * $ ruby argf.rb --verbose file1 file2
13034  *
13035  * ARGV #=> ["--verbose", "file1", "file2"]
13036  * option = ARGV.shift #=> "--verbose"
13037  * ARGV #=> ["file1", "file2"]
13038  *
13039  * You can now use +ARGF+ to work with a concatenation of each of these named
13040  * files. For instance, +ARGF.read+ will return the contents of _file1_
13041  * followed by the contents of _file2_.
13042  *
13043  * After a file in +ARGV+ has been read +ARGF+ removes it from the Array.
13044  * Thus, after all files have been read +ARGV+ will be empty.
13045  *
13046  * You can manipulate +ARGV+ yourself to control what +ARGF+ operates on. If
13047  * you remove a file from +ARGV+, it is ignored by +ARGF+; if you add files to
13048  * +ARGV+, they are treated as if they were named on the command line. For
13049  * example:
13050  *
13051  * ARGV.replace ["file1"]
13052  * ARGF.readlines # Returns the contents of file1 as an Array
13053  * ARGV #=> []
13054  * ARGV.replace ["file2", "file3"]
13055  * ARGF.read # Returns the contents of file2 and file3
13056  *
13057  * If +ARGV+ is empty, +ARGF+ acts as if it contained STDIN, i.e. the data
13058  * piped to your script. For example:
13059  *
13060  * $ echo "glark" | ruby -e 'p ARGF.read'
13061  * "glark\n"
13062  */
13063 
13064 /*
13065  * The IO class is the basis for all input and output in Ruby.
13066  * An I/O stream may be <em>duplexed</em> (that is, bidirectional), and
13067  * so may use more than one native operating system stream.
13068  *
13069  * Many of the examples in this section use the File class, the only standard
13070  * subclass of IO. The two classes are closely associated. Like the File
13071  * class, the Socket library subclasses from IO (such as TCPSocket or
13072  * UDPSocket).
13073  *
13074  * The Kernel#open method can create an IO (or File) object for these types
13075  * of arguments:
13076  *
13077  * * A plain string represents a filename suitable for the underlying
13078  * operating system.
13079  *
13080  * * A string starting with <code>"|"</code> indicates a subprocess.
13081  * The remainder of the string following the <code>"|"</code> is
13082  * invoked as a process with appropriate input/output channels
13083  * connected to it.
13084  *
13085  * * A string equal to <code>"|-"</code> will create another Ruby
13086  * instance as a subprocess.
13087  *
13088  * The IO may be opened with different file modes (read-only, write-only) and
13089  * encodings for proper conversion. See IO.new for these options. See
13090  * Kernel#open for details of the various command formats described above.
13091  *
13092  * IO.popen, the Open3 library, or Process#spawn may also be used to
13093  * communicate with subprocesses through an IO.
13094  *
13095  * Ruby will convert pathnames between different operating system
13096  * conventions if possible. For instance, on a Windows system the
13097  * filename <code>"/gumby/ruby/test.rb"</code> will be opened as
13098  * <code>"\gumby\ruby\test.rb"</code>. When specifying a Windows-style
13099  * filename in a Ruby string, remember to escape the backslashes:
13100  *
13101  * "C:\\gumby\\ruby\\test.rb"
13102  *
13103  * Our examples here will use the Unix-style forward slashes;
13104  * File::ALT_SEPARATOR can be used to get the platform-specific separator
13105  * character.
13106  *
13107  * The global constant ARGF (also accessible as <code>$<</code>) provides an
13108  * IO-like stream which allows access to all files mentioned on the
13109  * command line (or STDIN if no files are mentioned). ARGF#path and its alias
13110  * ARGF#filename are provided to access the name of the file currently being
13111  * read.
13112  *
13113  * == io/console
13114  *
13115  * The io/console extension provides methods for interacting with the
13116  * console. The console can be accessed from IO.console or the standard
13117  * input/output/error IO objects.
13118  *
13119  * Requiring io/console adds the following methods:
13120  *
13121  * * IO::console
13122  * * IO#raw
13123  * * IO#raw!
13124  * * IO#cooked
13125  * * IO#cooked!
13126  * * IO#getch
13127  * * IO#echo=
13128  * * IO#echo?
13129  * * IO#noecho
13130  * * IO#winsize
13131  * * IO#winsize=
13132  * * IO#iflush
13133  * * IO#ioflush
13134  * * IO#oflush
13135  *
13136  * Example:
13137  *
13138  * require 'io/console'
13139  * rows, columns = $stdout.winsize
13140  * puts "Your screen is #{columns} wide and #{rows} tall"
13141  */
13142 
13143 void
13144 Init_IO(void)
13145 {
13146 #undef rb_intern
13147 #define rb_intern(str) rb_intern_const(str)
13148 
13149  VALUE rb_cARGF;
13150 #ifdef __CYGWIN__
13151 #include <sys/cygwin.h>
13152  static struct __cygwin_perfile pf[] =
13153  {
13154  {"", O_RDONLY | O_BINARY},
13155  {"", O_WRONLY | O_BINARY},
13156  {"", O_RDWR | O_BINARY},
13157  {"", O_APPEND | O_BINARY},
13158  {NULL, 0}
13159  };
13160  cygwin_internal(CW_PERFILE, pf);
13161 #endif
13162 
13164  rb_eEOFError = rb_define_class("EOFError", rb_eIOError);
13165 
13166  id_write = rb_intern("write");
13167  id_read = rb_intern("read");
13168  id_getc = rb_intern("getc");
13169  id_flush = rb_intern("flush");
13170  id_readpartial = rb_intern("readpartial");
13171  id_set_encoding = rb_intern("set_encoding");
13172 
13173  rb_define_global_function("syscall", rb_f_syscall, -1);
13174 
13175  rb_define_global_function("open", rb_f_open, -1);
13176  rb_define_global_function("printf", rb_f_printf, -1);
13177  rb_define_global_function("print", rb_f_print, -1);
13178  rb_define_global_function("putc", rb_f_putc, 1);
13179  rb_define_global_function("puts", rb_f_puts, -1);
13180  rb_define_global_function("gets", rb_f_gets, -1);
13181  rb_define_global_function("readline", rb_f_readline, -1);
13182  rb_define_global_function("select", rb_f_select, -1);
13183 
13184  rb_define_global_function("readlines", rb_f_readlines, -1);
13185 
13186  rb_define_global_function("`", rb_f_backquote, 1);
13187 
13188  rb_define_global_function("p", rb_f_p, -1);
13189  rb_define_method(rb_mKernel, "display", rb_obj_display, -1);
13190 
13193 
13194  /* exception to wait for reading. see IO.select. */
13195  rb_mWaitReadable = rb_define_module_under(rb_cIO, "WaitReadable");
13196  /* exception to wait for writing. see IO.select. */
13197  rb_mWaitWritable = rb_define_module_under(rb_cIO, "WaitWritable");
13198  /* exception to wait for reading by EAGAIN. see IO.select. */
13199  rb_eEAGAINWaitReadable = rb_define_class_under(rb_cIO, "EAGAINWaitReadable", rb_eEAGAIN);
13200  rb_include_module(rb_eEAGAINWaitReadable, rb_mWaitReadable);
13201  /* exception to wait for writing by EAGAIN. see IO.select. */
13202  rb_eEAGAINWaitWritable = rb_define_class_under(rb_cIO, "EAGAINWaitWritable", rb_eEAGAIN);
13203  rb_include_module(rb_eEAGAINWaitWritable, rb_mWaitWritable);
13204 #if EAGAIN == EWOULDBLOCK
13205  rb_eEWOULDBLOCKWaitReadable = rb_eEAGAINWaitReadable;
13206  /* same as IO::EAGAINWaitReadable */
13207  rb_define_const(rb_cIO, "EWOULDBLOCKWaitReadable", rb_eEAGAINWaitReadable);
13208  rb_eEWOULDBLOCKWaitWritable = rb_eEAGAINWaitWritable;
13209  /* same as IO::EAGAINWaitWritable */
13210  rb_define_const(rb_cIO, "EWOULDBLOCKWaitWritable", rb_eEAGAINWaitWritable);
13211 #else
13212  /* exception to wait for reading by EWOULDBLOCK. see IO.select. */
13213  rb_eEWOULDBLOCKWaitReadable = rb_define_class_under(rb_cIO, "EWOULDBLOCKWaitReadable", rb_eEWOULDBLOCK);
13214  rb_include_module(rb_eEWOULDBLOCKWaitReadable, rb_mWaitReadable);
13215  /* exception to wait for writing by EWOULDBLOCK. see IO.select. */
13216  rb_eEWOULDBLOCKWaitWritable = rb_define_class_under(rb_cIO, "EWOULDBLOCKWaitWritable", rb_eEWOULDBLOCK);
13217  rb_include_module(rb_eEWOULDBLOCKWaitWritable, rb_mWaitWritable);
13218 #endif
13219  /* exception to wait for reading by EINPROGRESS. see IO.select. */
13220  rb_eEINPROGRESSWaitReadable = rb_define_class_under(rb_cIO, "EINPROGRESSWaitReadable", rb_eEINPROGRESS);
13221  rb_include_module(rb_eEINPROGRESSWaitReadable, rb_mWaitReadable);
13222  /* exception to wait for writing by EINPROGRESS. see IO.select. */
13223  rb_eEINPROGRESSWaitWritable = rb_define_class_under(rb_cIO, "EINPROGRESSWaitWritable", rb_eEINPROGRESS);
13224  rb_include_module(rb_eEINPROGRESSWaitWritable, rb_mWaitWritable);
13225 
13226 #if 0
13227  /* This is necessary only for forcing rdoc handle File::open */
13228  rb_define_singleton_method(rb_cFile, "open", rb_io_s_open, -1);
13229 #endif
13230 
13231  rb_define_alloc_func(rb_cIO, io_alloc);
13232  rb_define_singleton_method(rb_cIO, "new", rb_io_s_new, -1);
13233  rb_define_singleton_method(rb_cIO, "open", rb_io_s_open, -1);
13234  rb_define_singleton_method(rb_cIO, "sysopen", rb_io_s_sysopen, -1);
13235  rb_define_singleton_method(rb_cIO, "for_fd", rb_io_s_for_fd, -1);
13236  rb_define_singleton_method(rb_cIO, "popen", rb_io_s_popen, -1);
13237  rb_define_singleton_method(rb_cIO, "foreach", rb_io_s_foreach, -1);
13238  rb_define_singleton_method(rb_cIO, "readlines", rb_io_s_readlines, -1);
13239  rb_define_singleton_method(rb_cIO, "read", rb_io_s_read, -1);
13240  rb_define_singleton_method(rb_cIO, "binread", rb_io_s_binread, -1);
13241  rb_define_singleton_method(rb_cIO, "write", rb_io_s_write, -1);
13242  rb_define_singleton_method(rb_cIO, "binwrite", rb_io_s_binwrite, -1);
13243  rb_define_singleton_method(rb_cIO, "select", rb_f_select, -1);
13244  rb_define_singleton_method(rb_cIO, "pipe", rb_io_s_pipe, -1);
13245  rb_define_singleton_method(rb_cIO, "try_convert", rb_io_s_try_convert, 1);
13246  rb_define_singleton_method(rb_cIO, "copy_stream", rb_io_s_copy_stream, -1);
13247 
13248  rb_define_method(rb_cIO, "initialize", rb_io_initialize, -1);
13249 
13250  rb_output_fs = Qnil;
13251  rb_define_hooked_variable("$,", &rb_output_fs, 0, rb_output_fs_setter);
13252 
13253  rb_default_rs = rb_fstring_lit("\n"); /* avoid modifying RS_default */
13255  rb_rs = rb_default_rs;
13256  rb_output_rs = Qnil;
13260 
13261  rb_define_virtual_variable("$_", get_LAST_READ_LINE, set_LAST_READ_LINE);
13262 
13263  rb_define_method(rb_cIO, "initialize_copy", rb_io_init_copy, 1);
13264  rb_define_method(rb_cIO, "reopen", rb_io_reopen, -1);
13265 
13266  rb_define_method(rb_cIO, "print", rb_io_print, -1);
13267  rb_define_method(rb_cIO, "putc", rb_io_putc, 1);
13268  rb_define_method(rb_cIO, "puts", rb_io_puts, -1);
13269  rb_define_method(rb_cIO, "printf", rb_io_printf, -1);
13270 
13271  rb_define_method(rb_cIO, "each", rb_io_each_line, -1);
13272  rb_define_method(rb_cIO, "each_line", rb_io_each_line, -1);
13273  rb_define_method(rb_cIO, "each_byte", rb_io_each_byte, 0);
13274  rb_define_method(rb_cIO, "each_char", rb_io_each_char, 0);
13275  rb_define_method(rb_cIO, "each_codepoint", rb_io_each_codepoint, 0);
13276  rb_define_method(rb_cIO, "lines", rb_io_lines, -1);
13277  rb_define_method(rb_cIO, "bytes", rb_io_bytes, 0);
13278  rb_define_method(rb_cIO, "chars", rb_io_chars, 0);
13279  rb_define_method(rb_cIO, "codepoints", rb_io_codepoints, 0);
13280 
13281  rb_define_method(rb_cIO, "syswrite", rb_io_syswrite, 1);
13282  rb_define_method(rb_cIO, "sysread", rb_io_sysread, -1);
13283 
13284  rb_define_method(rb_cIO, "pread", rb_io_pread, -1);
13285  rb_define_method(rb_cIO, "pwrite", rb_io_pwrite, 2);
13286 
13287  rb_define_method(rb_cIO, "fileno", rb_io_fileno, 0);
13288  rb_define_alias(rb_cIO, "to_i", "fileno");
13289  rb_define_method(rb_cIO, "to_io", rb_io_to_io, 0);
13290 
13291  rb_define_method(rb_cIO, "fsync", rb_io_fsync, 0);
13292  rb_define_method(rb_cIO, "fdatasync", rb_io_fdatasync, 0);
13293  rb_define_method(rb_cIO, "sync", rb_io_sync, 0);
13294  rb_define_method(rb_cIO, "sync=", rb_io_set_sync, 1);
13295 
13296  rb_define_method(rb_cIO, "lineno", rb_io_lineno, 0);
13297  rb_define_method(rb_cIO, "lineno=", rb_io_set_lineno, 1);
13298 
13299  rb_define_method(rb_cIO, "readlines", rb_io_readlines, -1);
13300 
13301  rb_define_method(rb_cIO, "readpartial", io_readpartial, -1);
13302  rb_define_method(rb_cIO, "read", io_read, -1);
13303  rb_define_method(rb_cIO, "write", io_write_m, -1);
13304  rb_define_method(rb_cIO, "gets", rb_io_gets_m, -1);
13305  rb_define_method(rb_cIO, "readline", rb_io_readline, -1);
13306  rb_define_method(rb_cIO, "getc", rb_io_getc, 0);
13307  rb_define_method(rb_cIO, "getbyte", rb_io_getbyte, 0);
13308  rb_define_method(rb_cIO, "readchar", rb_io_readchar, 0);
13309  rb_define_method(rb_cIO, "readbyte", rb_io_readbyte, 0);
13310  rb_define_method(rb_cIO, "ungetbyte",rb_io_ungetbyte, 1);
13311  rb_define_method(rb_cIO, "ungetc",rb_io_ungetc, 1);
13313  rb_define_method(rb_cIO, "flush", rb_io_flush, 0);
13314  rb_define_method(rb_cIO, "tell", rb_io_tell, 0);
13315  rb_define_method(rb_cIO, "seek", rb_io_seek_m, -1);
13316  /* Set I/O position from the beginning */
13317  rb_define_const(rb_cIO, "SEEK_SET", INT2FIX(SEEK_SET));
13318  /* Set I/O position from the current position */
13319  rb_define_const(rb_cIO, "SEEK_CUR", INT2FIX(SEEK_CUR));
13320  /* Set I/O position from the end */
13321  rb_define_const(rb_cIO, "SEEK_END", INT2FIX(SEEK_END));
13322 #ifdef SEEK_DATA
13323  /* Set I/O position to the next location containing data */
13324  rb_define_const(rb_cIO, "SEEK_DATA", INT2FIX(SEEK_DATA));
13325 #endif
13326 #ifdef SEEK_HOLE
13327  /* Set I/O position to the next hole */
13328  rb_define_const(rb_cIO, "SEEK_HOLE", INT2FIX(SEEK_HOLE));
13329 #endif
13330  rb_define_method(rb_cIO, "rewind", rb_io_rewind, 0);
13331  rb_define_method(rb_cIO, "pos", rb_io_tell, 0);
13332  rb_define_method(rb_cIO, "pos=", rb_io_set_pos, 1);
13333  rb_define_method(rb_cIO, "eof", rb_io_eof, 0);
13334  rb_define_method(rb_cIO, "eof?", rb_io_eof, 0);
13335 
13336  rb_define_method(rb_cIO, "close_on_exec?", rb_io_close_on_exec_p, 0);
13337  rb_define_method(rb_cIO, "close_on_exec=", rb_io_set_close_on_exec, 1);
13338 
13339  rb_define_method(rb_cIO, "close", rb_io_close_m, 0);
13340  rb_define_method(rb_cIO, "closed?", rb_io_closed, 0);
13341  rb_define_method(rb_cIO, "close_read", rb_io_close_read, 0);
13342  rb_define_method(rb_cIO, "close_write", rb_io_close_write, 0);
13343 
13344  rb_define_method(rb_cIO, "isatty", rb_io_isatty, 0);
13345  rb_define_method(rb_cIO, "tty?", rb_io_isatty, 0);
13346  rb_define_method(rb_cIO, "binmode", rb_io_binmode_m, 0);
13347  rb_define_method(rb_cIO, "binmode?", rb_io_binmode_p, 0);
13348  rb_define_method(rb_cIO, "sysseek", rb_io_sysseek, -1);
13349  rb_define_method(rb_cIO, "advise", rb_io_advise, -1);
13350 
13351  rb_define_method(rb_cIO, "ioctl", rb_io_ioctl, -1);
13352  rb_define_method(rb_cIO, "fcntl", rb_io_fcntl, -1);
13353  rb_define_method(rb_cIO, "pid", rb_io_pid, 0);
13354  rb_define_method(rb_cIO, "inspect", rb_io_inspect, 0);
13355 
13356  rb_define_method(rb_cIO, "external_encoding", rb_io_external_encoding, 0);
13357  rb_define_method(rb_cIO, "internal_encoding", rb_io_internal_encoding, 0);
13358  rb_define_method(rb_cIO, "set_encoding", rb_io_set_encoding, -1);
13359  rb_define_method(rb_cIO, "set_encoding_by_bom", rb_io_set_encoding_by_bom, 0);
13360 
13361  rb_define_method(rb_cIO, "autoclose?", rb_io_autoclose_p, 0);
13362  rb_define_method(rb_cIO, "autoclose=", rb_io_set_autoclose, 1);
13363 
13364  rb_define_variable("$stdin", &rb_stdin);
13365  rb_stdin = prep_stdio(stdin, FMODE_READABLE, rb_cIO, "<STDIN>");
13366  rb_define_hooked_variable("$stdout", &rb_stdout, 0, stdout_setter);
13367  rb_stdout = prep_stdio(stdout, FMODE_WRITABLE, rb_cIO, "<STDOUT>");
13368  rb_define_hooked_variable("$stderr", &rb_stderr, 0, stdout_setter);
13369  rb_stderr = prep_stdio(stderr, FMODE_WRITABLE|FMODE_SYNC, rb_cIO, "<STDERR>");
13370  rb_define_hooked_variable("$>", &rb_stdout, 0, stdout_setter);
13371  orig_stdout = rb_stdout;
13372  orig_stderr = rb_stderr;
13373 
13374  /* Holds the original stdin */
13375  rb_define_global_const("STDIN", rb_stdin);
13376  /* Holds the original stdout */
13377  rb_define_global_const("STDOUT", rb_stdout);
13378  /* Holds the original stderr */
13379  rb_define_global_const("STDERR", rb_stderr);
13380 
13381 #if 0
13382  /* Hack to get rdoc to regard ARGF as a class: */
13383  rb_cARGF = rb_define_class("ARGF", rb_cObject);
13384 #endif
13385 
13386  rb_cARGF = rb_class_new(rb_cObject);
13387  rb_set_class_path(rb_cARGF, rb_cObject, "ARGF.class");
13388  rb_define_alloc_func(rb_cARGF, argf_alloc);
13389 
13390  rb_include_module(rb_cARGF, rb_mEnumerable);
13391 
13392  rb_define_method(rb_cARGF, "initialize", argf_initialize, -2);
13393  rb_define_method(rb_cARGF, "initialize_copy", argf_initialize_copy, 1);
13394  rb_define_method(rb_cARGF, "to_s", argf_to_s, 0);
13395  rb_define_alias(rb_cARGF, "inspect", "to_s");
13396  rb_define_method(rb_cARGF, "argv", argf_argv, 0);
13397 
13398  rb_define_method(rb_cARGF, "fileno", argf_fileno, 0);
13399  rb_define_method(rb_cARGF, "to_i", argf_fileno, 0);
13400  rb_define_method(rb_cARGF, "to_io", argf_to_io, 0);
13401  rb_define_method(rb_cARGF, "to_write_io", argf_write_io, 0);
13402  rb_define_method(rb_cARGF, "each", argf_each_line, -1);
13403  rb_define_method(rb_cARGF, "each_line", argf_each_line, -1);
13404  rb_define_method(rb_cARGF, "each_byte", argf_each_byte, 0);
13405  rb_define_method(rb_cARGF, "each_char", argf_each_char, 0);
13406  rb_define_method(rb_cARGF, "each_codepoint", argf_each_codepoint, 0);
13407  rb_define_method(rb_cARGF, "lines", argf_lines, -1);
13408  rb_define_method(rb_cARGF, "bytes", argf_bytes, 0);
13409  rb_define_method(rb_cARGF, "chars", argf_chars, 0);
13410  rb_define_method(rb_cARGF, "codepoints", argf_codepoints, 0);
13411 
13412  rb_define_method(rb_cARGF, "read", argf_read, -1);
13413  rb_define_method(rb_cARGF, "readpartial", argf_readpartial, -1);
13414  rb_define_method(rb_cARGF, "read_nonblock", argf_read_nonblock, -1);
13415  rb_define_method(rb_cARGF, "readlines", argf_readlines, -1);
13416  rb_define_method(rb_cARGF, "to_a", argf_readlines, -1);
13417  rb_define_method(rb_cARGF, "gets", argf_gets, -1);
13418  rb_define_method(rb_cARGF, "readline", argf_readline, -1);
13419  rb_define_method(rb_cARGF, "getc", argf_getc, 0);
13420  rb_define_method(rb_cARGF, "getbyte", argf_getbyte, 0);
13421  rb_define_method(rb_cARGF, "readchar", argf_readchar, 0);
13422  rb_define_method(rb_cARGF, "readbyte", argf_readbyte, 0);
13423  rb_define_method(rb_cARGF, "tell", argf_tell, 0);
13424  rb_define_method(rb_cARGF, "seek", argf_seek_m, -1);
13425  rb_define_method(rb_cARGF, "rewind", argf_rewind, 0);
13426  rb_define_method(rb_cARGF, "pos", argf_tell, 0);
13427  rb_define_method(rb_cARGF, "pos=", argf_set_pos, 1);
13428  rb_define_method(rb_cARGF, "eof", argf_eof, 0);
13429  rb_define_method(rb_cARGF, "eof?", argf_eof, 0);
13430  rb_define_method(rb_cARGF, "binmode", argf_binmode_m, 0);
13431  rb_define_method(rb_cARGF, "binmode?", argf_binmode_p, 0);
13432 
13433  rb_define_method(rb_cARGF, "write", argf_write, 1);
13434  rb_define_method(rb_cARGF, "print", rb_io_print, -1);
13435  rb_define_method(rb_cARGF, "putc", rb_io_putc, 1);
13436  rb_define_method(rb_cARGF, "puts", rb_io_puts, -1);
13437  rb_define_method(rb_cARGF, "printf", rb_io_printf, -1);
13438 
13439  rb_define_method(rb_cARGF, "filename", argf_filename, 0);
13440  rb_define_method(rb_cARGF, "path", argf_filename, 0);
13441  rb_define_method(rb_cARGF, "file", argf_file, 0);
13442  rb_define_method(rb_cARGF, "skip", argf_skip, 0);
13443  rb_define_method(rb_cARGF, "close", argf_close_m, 0);
13444  rb_define_method(rb_cARGF, "closed?", argf_closed, 0);
13445 
13446  rb_define_method(rb_cARGF, "lineno", argf_lineno, 0);
13447  rb_define_method(rb_cARGF, "lineno=", argf_set_lineno, 1);
13448 
13449  rb_define_method(rb_cARGF, "inplace_mode", argf_inplace_mode_get, 0);
13450  rb_define_method(rb_cARGF, "inplace_mode=", argf_inplace_mode_set, 1);
13451 
13452  rb_define_method(rb_cARGF, "external_encoding", argf_external_encoding, 0);
13453  rb_define_method(rb_cARGF, "internal_encoding", argf_internal_encoding, 0);
13454  rb_define_method(rb_cARGF, "set_encoding", argf_set_encoding, -1);
13455 
13456  argf = rb_class_new_instance(0, 0, rb_cARGF);
13457 
13459  /*
13460  * ARGF is a stream designed for use in scripts that process files given
13461  * as command-line arguments or passed in via STDIN.
13462  *
13463  * See ARGF (the class) for more details.
13464  */
13465  rb_define_global_const("ARGF", argf);
13466 
13467  rb_define_hooked_variable("$.", &argf, argf_lineno_getter, argf_lineno_setter);
13468  rb_define_hooked_variable("$FILENAME", &argf, argf_filename_getter, rb_gvar_readonly_setter);
13469  ARGF.filename = rb_str_new2("-");
13470 
13471  rb_define_hooked_variable("$-i", &argf, opt_i_get, opt_i_set);
13472  rb_define_hooked_variable("$*", &argf, argf_argv_getter, rb_gvar_readonly_setter);
13473 
13474 #if defined (_WIN32) || defined(__CYGWIN__)
13475  atexit(pipe_atexit);
13476 #endif
13477 
13478  Init_File();
13479 
13480  rb_define_method(rb_cFile, "initialize", rb_file_initialize, -1);
13481 
13482  sym_mode = ID2SYM(rb_intern("mode"));
13483  sym_perm = ID2SYM(rb_intern("perm"));
13484  sym_flags = ID2SYM(rb_intern("flags"));
13485  sym_extenc = ID2SYM(rb_intern("external_encoding"));
13486  sym_intenc = ID2SYM(rb_intern("internal_encoding"));
13487  sym_encoding = ID2SYM(rb_id_encoding());
13488  sym_open_args = ID2SYM(rb_intern("open_args"));
13489  sym_textmode = ID2SYM(rb_intern("textmode"));
13490  sym_binmode = ID2SYM(rb_intern("binmode"));
13491  sym_autoclose = ID2SYM(rb_intern("autoclose"));
13492  sym_normal = ID2SYM(rb_intern("normal"));
13493  sym_sequential = ID2SYM(rb_intern("sequential"));
13494  sym_random = ID2SYM(rb_intern("random"));
13495  sym_willneed = ID2SYM(rb_intern("willneed"));
13496  sym_dontneed = ID2SYM(rb_intern("dontneed"));
13497  sym_noreuse = ID2SYM(rb_intern("noreuse"));
13498  sym_SET = ID2SYM(rb_intern("SET"));
13499  sym_CUR = ID2SYM(rb_intern("CUR"));
13500  sym_END = ID2SYM(rb_intern("END"));
13501 #ifdef SEEK_DATA
13502  sym_DATA = ID2SYM(rb_intern("DATA"));
13503 #endif
13504 #ifdef SEEK_HOLE
13505  sym_HOLE = ID2SYM(rb_intern("HOLE"));
13506 #endif
13507  sym_wait_readable = ID2SYM(rb_intern("wait_readable"));
13508  sym_wait_writable = ID2SYM(rb_intern("wait_writable"));
13509 }
13510 
13511 #include "io.rbinc"
13512 
13513 void
13515 {
13516  load_io();
13517 }
MODE_BINARY
#define MODE_BINARY(a, b)
rb_eEAGAIN
VALUE rb_eEAGAIN
Definition: error.c:54
RB_IO_WAIT_READABLE
@ RB_IO_WAIT_READABLE
Definition: ruby.h:1929
rb_mutex_synchronize
VALUE rb_mutex_synchronize(VALUE mutex, VALUE(*func)(VALUE arg), VALUE arg)
Definition: thread_sync.c:522
rb_econv_asciicompat_encoding
const char * rb_econv_asciicompat_encoding(const char *encname)
Definition: transcode.c:1769
rb_str_end_with_asciichar
int rb_str_end_with_asciichar(VALUE str, int c)
Definition: io.c:7685
rb_thread_fd_writable
int rb_thread_fd_writable(int)
Definition: thread.c:4048
rb_io_t::writeconv_pre_ecopts
VALUE writeconv_pre_ecopts
Definition: io.h:99
NUM2IOCTLREQ
#define NUM2IOCTLREQ(num)
Definition: io.c:9574
rb_get_kwargs
int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *values)
Definition: class.c:1886
READ_CHAR_PENDING_COUNT
#define READ_CHAR_PENDING_COUNT(fptr)
Definition: io.c:472
foreach_arg::argc
int argc
Definition: io.c:10355
ISASCII
#define ISASCII(c)
Definition: ruby.h:2304
rb_thread_call_without_gvl2
void * rb_thread_call_without_gvl2(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2)
Definition: thread.c:1581
rb_check_funcall
VALUE rb_check_funcall(VALUE, ID, int, const VALUE *)
Definition: vm_eval.c:505
rb_econv_prepare_options
int rb_econv_prepare_options(VALUE opthash, VALUE *ecopts, int ecflags)
Definition: transcode.c:2510
rb_define_class
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:649
econv_source_buffer_empty
@ econv_source_buffer_empty
Definition: encoding.h:301
rb_execarg_parent_end
void rb_execarg_parent_end(VALUE execarg_obj)
Definition: process.c:2855
READ_CHAR_PENDING_PTR
#define READ_CHAR_PENDING_PTR(fptr)
Definition: io.c:473
TypedData_Make_Struct
#define TypedData_Make_Struct(klass, type, data_type, sval)
Definition: ruby.h:1244
Check_Type
#define Check_Type(v, t)
Definition: ruby.h:595
argf::binmode
int8_t binmode
Definition: io.c:213
TRUE
#define TRUE
Definition: nkf.h:175
rb_check_convert_type_with_id
VALUE rb_check_convert_type_with_id(VALUE, int, const char *, ID)
Definition: object.c:2957
RSTRING_GETMEM
#define RSTRING_GETMEM(str, ptrvar, lenvar)
Definition: ruby.h:1018
RFILE
#define RFILE(obj)
Definition: ruby.h:1276
rb_thread_check_ints
void rb_thread_check_ints(void)
Definition: thread.c:1362
rb_include_module
void rb_include_module(VALUE klass, VALUE module)
Definition: class.c:869
S_ISREG
#define S_ISREG(m)
Definition: io.c:992
rb_io_t::writeconv_initialized
int writeconv_initialized
Definition: io.h:97
foreach_arg
Definition: io.c:10354
rb_assoc_new
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Definition: array.c:896
rb_str_new2
#define rb_str_new2
Definition: intern.h:903
getline_arg
Definition: stringio.c:1149
getline_arg::io
VALUE io
Definition: io.c:3349
rb_write_error_str
void rb_write_error_str(VALUE mesg)
Definition: io.c:7936
rb_enc_name
#define rb_enc_name(enc)
Definition: encoding.h:177
rb_method_basic_definition_p
int rb_method_basic_definition_p(VALUE, ID)
Definition: vm_method.c:2072
LONG_MAX
#define LONG_MAX
Definition: ruby.h:220
rb_cloexec_fcntl_dupfd
int rb_cloexec_fcntl_dupfd(int fd, int minfd)
Definition: io.c:419
select_args::write
VALUE write
Definition: io.c:9208
rb_io_t::write_lock
VALUE write_lock
Definition: io.h:101
rb_exc_new3
#define rb_exc_new3
Definition: intern.h:293
RB_PASS_CALLED_KEYWORDS
#define RB_PASS_CALLED_KEYWORDS
Definition: ruby.h:1980
env
#define env
rb_io_ungetc
VALUE rb_io_ungetc(VALUE io, VALUE c)
Definition: io.c:4315
MAX_REALLOC_GAP
#define MAX_REALLOC_GAP
Definition: io.c:2694
copy_stream_struct::close_dst
unsigned close_dst
Definition: io.c:10765
rb_mutex_owned_p
VALUE rb_mutex_owned_p(VALUE self)
Definition: thread_sync.c:345
MORE_CHAR_SUSPENDED
#define MORE_CHAR_SUSPENDED
Definition: io.c:2559
rb_io_getbyte
VALUE rb_io_getbyte(VALUE io)
Definition: io.c:4215
rb_enc_codepoint
#define rb_enc_codepoint(p, e, enc)
Definition: encoding.h:207
rb_hash_new
VALUE rb_hash_new(void)
Definition: hash.c:1523
rb_enc_mbclen
int rb_enc_mbclen(const char *p, const char *e, rb_encoding *enc)
Definition: encoding.c:1020
rb_gc_register_mark_object
void rb_gc_register_mark_object(VALUE obj)
Definition: gc.c:7066
rb_execarg_run_options
int rb_execarg_run_options(const struct rb_execarg *e, struct rb_execarg *s, char *errmsg, size_t errmsg_buflen)
Definition: process.c:3392
rb_stderr_tty_p
int rb_stderr_tty_p(void)
Definition: io.c:7958
rb_define_module_under
VALUE rb_define_module_under(VALUE outer, const char *name)
Definition: class.c:797
rb_execarg_parent_start
void rb_execarg_parent_start(VALUE execarg_obj)
Definition: process.c:2816
stat
#define stat(path, st)
Definition: win32.h:206
rb_warn
void rb_warn(const char *fmt,...)
Definition: error.c:315
ENC_CODERANGE_VALID
#define ENC_CODERANGE_VALID
Definition: encoding.h:105
rb_str_buf_new
VALUE rb_str_buf_new(long)
Definition: string.c:1315
rb_block_given_p
int rb_block_given_p(void)
Determines if the current method is given a block.
Definition: eval.c:898
MBCLEN_NEEDMORE_LEN
#define MBCLEN_NEEDMORE_LEN(ret)
Definition: encoding.h:195
rb_warning
void rb_warning(const char *fmt,...)
Definition: error.c:336
SET_BINARY_MODE
#define SET_BINARY_MODE(fptr)
Definition: io.c:660
rb_funcallv_kw
VALUE rb_funcallv_kw(VALUE, ID, int, const VALUE *, int)
Definition: vm_eval.c:962
io_encoding_set_args::fptr
rb_io_t * fptr
Definition: io.c:10188
rb_io_synchronized
void rb_io_synchronized(rb_io_t *fptr)
Definition: io.c:6356
rb_str_buf_cat_ascii
VALUE rb_str_buf_cat_ascii(VALUE, const char *)
Definition: string.c:2926
rb_io_oflags_fmode
int rb_io_oflags_fmode(int oflags)
Definition: io.c:5519
FMODE_TTY
#define FMODE_TTY
Definition: io.h:113
copy_stream_struct::dst_stat
struct stat dst_stat
Definition: io.c:10772
rb_gc_force_recycle
void rb_gc_force_recycle(VALUE obj)
Definition: gc.c:7014
INT2FIX
#define INT2FIX(i)
Definition: ruby.h:263
NEED_WRITECONV
#define NEED_WRITECONV(fptr)
Definition: io.c:655
ENCINDEX_UTF_16BE
#define ENCINDEX_UTF_16BE
Definition: encindex.h:45
strchr
char * strchr(char *, char)
next_argv
#define next_argv()
Definition: io.c:8581
copy_stream_struct::total
off_t total
Definition: io.c:10767
rp
#define rp(obj)
Definition: internal.h:1435
rb_funcallv
VALUE rb_funcallv(VALUE, ID, int, const VALUE *)
Calls a method.
Definition: vm_eval.c:956
copy_stream_struct::error_no
int error_no
Definition: io.c:10766
rb_file_open_str
VALUE rb_file_open_str(VALUE fname, const char *modestr)
Definition: io.c:6252
select_args::except
VALUE except
Definition: io.c:9208
rb_get_argv
VALUE rb_get_argv(void)
Definition: io.c:12893
rb_enc_uint_chr
VALUE rb_enc_uint_chr(unsigned int code, rb_encoding *enc)
Definition: numeric.c:3375
F_DUPFD_CLOEXEC
#define F_DUPFD_CLOEXEC
Definition: win32.h:609
O_CLOEXEC
#define O_CLOEXEC
Definition: dir.c:28
RSTRING_PTR
#define RSTRING_PTR(str)
Definition: ruby.h:1009
rb_str_substr
VALUE rb_str_substr(VALUE, long, long)
Definition: string.c:2584
rb_w32_write_console
long rb_w32_write_console(uintptr_t, int)
Definition: win32.c:7225
rb_io_check_io
VALUE rb_io_check_io(VALUE io)
Definition: io.c:739
NUM2LONG
#define NUM2LONG(x)
Definition: ruby.h:679
off_t
#define off_t
Definition: io.c:83
rb_attr_get
VALUE rb_attr_get(VALUE, ID)
Definition: variable.c:1084
rb_io_t::pathv
VALUE pathv
Definition: io.h:72
O_NONBLOCK
#define O_NONBLOCK
Definition: win32.h:611
rb_str_new
VALUE rb_str_new(const char *, long)
Definition: string.c:774
rb_io_addstr
VALUE rb_io_addstr(VALUE io, VALUE str)
Definition: io.c:1843
rb_econv_str_convert
VALUE rb_econv_str_convert(rb_econv_t *ec, VALUE src, int flags)
Definition: transcode.c:1860
rb_class_new_instance_kw
VALUE rb_class_new_instance_kw(int, const VALUE *, VALUE, int)
Definition: object.c:1931
rb_fork_async_signal_safe
rb_pid_t rb_fork_async_signal_safe(int *status, int(*chfunc)(void *, char *, size_t), void *charg, VALUE fds, char *errmsg, size_t errmsg_buflen)
memcpy
#define memcpy(d, s, n)
Definition: ffi_common.h:55
flock
int flock(int, int)
Definition: flock.c:125
rb_hash_aref
VALUE rb_hash_aref(VALUE hash, VALUE key)
Definition: hash.c:2037
ARGF_block_call
#define ARGF_block_call(mid, argc, argv, func, argf)
Definition: io.c:12402
rb_utf8_encindex
int rb_utf8_encindex(void)
Definition: encoding.c:1334
RB_WAITFD_IN
#define RB_WAITFD_IN
Definition: io.h:51
rb_write_error
void rb_write_error(const char *mesg)
Definition: io.c:7930
rb_io_buffer_t
struct rb_io_buffer_t rb_io_buffer_t
Definition: io.h:64
bufread_arg
Definition: io.c:2466
rb_default_external_encoding
rb_encoding * rb_default_external_encoding(void)
Definition: encoding.c:1427
rb_gvar_readonly_setter
void rb_gvar_readonly_setter(VALUE v, ID id, VALUE *_)
Definition: variable.c:412
rb_obj_as_string
VALUE rb_obj_as_string(VALUE)
Definition: string.c:1440
rb_io_t::finalize
void(* finalize)(struct rb_io_t *, int)
Definition: io.h:73
rb_eArgError
VALUE rb_eArgError
Definition: error.c:925
encoding.h
ruby_verbose
#define ruby_verbose
Definition: ruby.h:1925
rb_io_get_io
VALUE rb_io_get_io(VALUE io)
Definition: io.c:733
ZALLOC
#define ZALLOC(type)
Definition: ruby.h:1666
ONIGENC_CONSTRUCT_MBCLEN_CHARFOUND
#define ONIGENC_CONSTRUCT_MBCLEN_CHARFOUND(n)
Definition: onigmo.h:345
FMODE_TRUNC
#define FMODE_TRUNC
Definition: io.h:119
getline_arg::limit
long limit
Definition: stringio.c:1151
ARGF_GENERIC_INPUT_P
#define ARGF_GENERIC_INPUT_P()
Definition: io.c:8582
RB_TYPE_P
#define RB_TYPE_P(obj, type)
Definition: ruby.h:560
rb_mWaitWritable
VALUE rb_mWaitWritable
Definition: io.c:175
rb_intern_const
#define rb_intern_const(str)
Definition: ruby.h:1879
Init_IO_nonblock
void Init_IO_nonblock(void)
Definition: io.c:13514
io_tell
#define io_tell(fptr)
Definition: io.c:862
TYPE
#define TYPE(x)
Definition: ruby.h:554
rb_thread_current
VALUE rb_thread_current(void)
Definition: thread.c:2676
rb_enc_get
rb_encoding * rb_enc_get(VALUE obj)
Definition: encoding.c:872
rb_enc_asciicompat
#define rb_enc_asciicompat(enc)
Definition: encoding.h:245
do_write_retry
#define do_write_retry(code)
Definition: io.c:1039
rb_execarg_commandline
char * rb_execarg_commandline(const struct rb_execarg *eargp, VALUE *prog)
Definition: process.c:4324
rb_io_t::wbuf
rb_io_buffer_t wbuf
Definition: io.h:75
rb_enc_precise_mbclen
int rb_enc_precise_mbclen(const char *p, const char *e, rb_encoding *enc)
Definition: encoding.c:1032
rb_gc_for_fd
int rb_gc_for_fd(int err)
Definition: io.c:953
NEED_READCONV
#define NEED_READCONV(fptr)
Definition: io.c:654
rb_io_ascii8bit_binmode
VALUE rb_io_ascii8bit_binmode(VALUE io)
Definition: io.c:5380
StringValue
#define StringValue(v)
Definition: ruby.h:602
rb_sys_fail_path
#define rb_sys_fail_path(path)
Definition: internal.h:1630
rb_bool_expected
int rb_bool_expected(VALUE, const char *)
Definition: object.c:3112
id.h
SIGNED_VALUE
#define SIGNED_VALUE
Definition: ruby.h:104
rb_to_array_type
VALUE rb_to_array_type(VALUE ary)
Definition: array.c:902
rb_define_global_function
void rb_define_global_function(const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a global function.
Definition: class.c:1787
GetWriteIO
#define GetWriteIO(io)
Definition: io.c:464
EINPROGRESS
#define EINPROGRESS
Definition: win32.h:498
binwrite_arg::fptr
rb_io_t * fptr
Definition: io.c:1317
io_internal_write_struct
Definition: io.c:1002
rb_thread_sleep
void rb_thread_sleep(int)
Definition: thread.c:1385
rb_io_pwrite
#define rb_io_pwrite
Definition: io.c:5330
io_internal_read_struct::capa
size_t capa
Definition: io.c:999
UINT2NUM
#define UINT2NUM(x)
Definition: ruby.h:1610
rb_lastline_set
void rb_lastline_set(VALUE)
Definition: vm.c:1322
rb_inspect
VALUE rb_inspect(VALUE)
Convenient wrapper of Object::inspect.
Definition: object.c:551
rb_io_set_close_on_exec
#define rb_io_set_close_on_exec
Definition: io.c:4479
READ_DATA_BUFFERED
#define READ_DATA_BUFFERED(fptr)
Definition: io.c:469
rb_io_write
VALUE rb_io_write(VALUE io, VALUE str)
Definition: io.c:1804
rb_str_dup
VALUE rb_str_dup(VALUE)
Definition: string.c:1516
argv
char ** argv
Definition: ruby.c:223
F_DUPFD
#define F_DUPFD
Definition: win32.h:602
argf::argv
VALUE argv
Definition: io.c:210
rb_hash_lookup2
VALUE rb_hash_lookup2(VALUE hash, VALUE key, VALUE def)
Definition: hash.c:2050
rb_check_string_type
VALUE rb_check_string_type(VALUE)
Definition: string.c:2314
rb_io_gets_internal
VALUE rb_io_gets_internal(VALUE io)
Definition: io.c:3579
SEEK_CUR
#define SEEK_CUR
Definition: io.c:866
SHUT_WR
#define SHUT_WR
copy_stream_struct::src_fd
int src_fd
Definition: io.c:10762
rb_define_readonly_variable
void rb_define_readonly_variable(const char *, const VALUE *)
Definition: variable.c:505
rb_io_check_writable
void rb_io_check_writable(rb_io_t *fptr)
Definition: io.c:923
Qundef
#define Qundef
Definition: ruby.h:470
free
#define free(x)
Definition: io.c:47
rb_define_singleton_method
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
Definition: class.c:1755
rb_io_flush_raw
VALUE rb_io_flush_raw(VALUE io, int sync)
Definition: io.c:1864
rb_write_error2
void rb_write_error2(const char *mesg, long len)
Definition: io.c:7911
rb_str_modify
void rb_str_modify(VALUE)
Definition: string.c:2114
rb_define_method
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1551
ENC_CODERANGE_SET
#define ENC_CODERANGE_SET(obj, cr)
Definition: encoding.h:110
INT2NUM
#define INT2NUM(x)
Definition: ruby.h:1609
bufread_arg::fptr
rb_io_t * fptr
Definition: io.c:2469
rb_econv_convert
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)
Definition: transcode.c:1429
rb_str_cat2
VALUE rb_str_cat2(VALUE, const char *)
rb_ary_shift
VALUE rb_ary_shift(VALUE ary)
Definition: array.c:1294
io_internal_read_struct::nonblock
int nonblock
Definition: io.c:997
ptr
struct RIMemo * ptr
Definition: debug.c:65
READ_DATA_PENDING_PTR
#define READ_DATA_PENDING_PTR(fptr)
Definition: io.c:468
rb_io_eof
VALUE rb_io_eof(VALUE io)
Definition: io.c:2149
rb_io_enc_t
struct rb_io_enc_t rb_io_enc_t
Definition: io.h:104
utf_prefix_len
@ utf_prefix_len
Definition: io.c:5456
rb_str_setter
rb_gvar_setter_t rb_str_setter
Definition: intern.h:828
Qfalse
#define Qfalse
Definition: ruby.h:467
rb_hash_dup
VALUE rb_hash_dup(VALUE hash)
Definition: hash.c:1564
IO_CBUF_CAPA_MIN
#define IO_CBUF_CAPA_MIN
Definition: io.c:150
FMODE_DUPLEX
#define FMODE_DUPLEX
Definition: io.h:114
FilePathValue
#define FilePathValue(v)
Definition: ruby.h:624
rb_id2str
#define rb_id2str(id)
Definition: vm_backtrace.c:30
argf::last_lineno
long last_lineno
Definition: io.c:208
dp
#define dp(v)
Definition: vm_debug.h:21
chown
int chown(const char *, int, int)
Definition: win32.c:4763
rb_io_t::fd
int fd
Definition: io.h:68
sysopen_struct::perm
mode_t perm
Definition: io.c:6007
rb_set_class_path
void rb_set_class_path(VALUE, VALUE, const char *)
Definition: variable.c:218
rb_scan_args_kw
int rb_scan_args_kw(int kw_flag, int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:2180
NULL
#define NULL
Definition: _sdbm.c:101
rb_waitpid
rb_pid_t rb_waitpid(rb_pid_t pid, int *status, int flags)
Definition: process.c:1213
SafeStringValue
#define SafeStringValue(v)
Definition: ruby.h:607
rb_thread_interrupted
int rb_thread_interrupted(VALUE thval)
Definition: thread.c:1379
FL_TEST
#define FL_TEST(x, f)
Definition: ruby.h:1353
PRIsVALUE
#define PRIsVALUE
Definition: ruby.h:166
select_args::read
VALUE read
Definition: io.c:9208
rb_fd_select
#define rb_fd_select(n, rfds, wfds, efds, timeout)
Definition: intern.h:416
fcntl
int fcntl(int, int,...)
Definition: win32.c:4282
RBASIC_SET_CLASS
#define RBASIC_SET_CLASS(obj, cls)
Definition: internal.h:1989
rb_io_get_write_io
VALUE rb_io_get_write_io(VALUE io)
Definition: io.c:745
rb_readwrite_syserr_fail
void rb_readwrite_syserr_fail(enum rb_io_wait_readwrite writable, int n, const char *mesg)
Definition: io.c:12933
rb_enc_from_encoding
VALUE rb_enc_from_encoding(rb_encoding *encoding)
Definition: encoding.c:116
last
unsigned int last
Definition: nkf.c:4324
rb_io_t::rbuf
rb_io_buffer_t rbuf
Definition: io.h:75
rb_str_cat_conv_enc_opts
VALUE rb_str_cat_conv_enc_opts(VALUE newstr, long ofs, const char *ptr, long len, rb_encoding *from, int ecflags, VALUE ecopts)
Definition: string.c:943
rb_fatal
void rb_fatal(const char *fmt,...)
Definition: error.c:2722
FIX2LONG
#define FIX2LONG(x)
Definition: ruby.h:394
ID2SYM
#define ID2SYM(x)
Definition: ruby.h:414
strlen
size_t strlen(const char *)
OBJ_FREEZE
#define OBJ_FREEZE(x)
Definition: ruby.h:1377
rb_eof_error
void rb_eof_error(void)
Definition: io.c:697
rb_str_locktmp
VALUE rb_str_locktmp(VALUE)
rb_find_encoding
rb_encoding * rb_find_encoding(VALUE enc)
Definition: encoding.c:252
rb_io_t::pid
rb_pid_t pid
Definition: io.h:70
rb_cFile
VALUE rb_cFile
Definition: file.c:159
FMODE_BINMODE
#define FMODE_BINMODE
Definition: io.h:111
rb_io_modestr_fmode
int rb_io_modestr_fmode(const char *modestr)
Definition: io.c:5465
rb_define_alias
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
Definition: class.c:1800
L
#define L(x)
Definition: asm.h:125
rb_f_p_arg
Definition: io.c:7812
rb_respond_to
int rb_respond_to(VALUE, ID)
Definition: vm_method.c:2190
RB_BLOCK_CALL_FUNC_ARGLIST
#define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)
Definition: ruby.h:1964
rb_protect
VALUE rb_protect(VALUE(*proc)(VALUE), VALUE data, int *pstate)
Protects a function call from potential global escapes from the function.
Definition: eval.c:1072
rb_io_check_readable
void rb_io_check_readable(rb_io_t *fptr)
Definition: io.c:899
rb_check_arity
#define rb_check_arity
Definition: intern.h:347
RUBY_FUNC_EXPORTED
#define RUBY_FUNC_EXPORTED
Definition: defines.h:391
rb_econv_check_error
void rb_econv_check_error(rb_econv_t *ec)
Definition: transcode.c:4224
ENCODING_MAXNAMELEN
#define ENCODING_MAXNAMELEN
Definition: encoding.h:64
RARRAY_LENINT
#define RARRAY_LENINT(ary)
Definition: ruby.h:1071
rb_str_locktmp_ensure
VALUE rb_str_locktmp_ensure(VALUE str, VALUE(*func)(VALUE), VALUE arg)
Definition: string.c:2685
IO_WBUF_CAPA_MIN
#define IO_WBUF_CAPA_MIN
Definition: io.c:152
rb_str_capacity
size_t rb_str_capacity(VALUE str)
Definition: string.c:712
ALLOC_N
#define ALLOC_N(type, n)
Definition: ruby.h:1663
MBCLEN_INVALID_P
#define MBCLEN_INVALID_P(ret)
Definition: encoding.h:193
argf::lineno
long lineno
Definition: io.c:209
rb_str_resize
VALUE rb_str_resize(VALUE, long)
Definition: string.c:2709
rb_cloexec_dup
int rb_cloexec_dup(int oldfd)
Definition: io.c:318
copy_stream_struct::th
VALUE th
Definition: io.c:10770
RUBY_TYPED_DEFAULT_FREE
#define RUBY_TYPED_DEFAULT_FREE
Definition: ruby.h:1203
rb_io_t::rb_io_enc_t::ecflags
int ecflags
Definition: io.h:88
rb_raise
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2671
rb_io_fdopen
VALUE rb_io_fdopen(int fd, int oflags, const char *path)
Definition: io.c:8004
argf_call_arg
Definition: io.c:12122
copy_stream_struct
Definition: io.c:10756
FMODE_SYNC
#define FMODE_SYNC
Definition: io.h:112
sysopen_struct
Definition: io.c:6004
rb_id_encoding
ID rb_id_encoding(void)
Definition: encoding.c:759
getuid
rb_uid_t getuid(void)
Definition: win32.c:2765
rb_str_tmp_frozen_acquire
VALUE rb_str_tmp_frozen_acquire(VALUE str)
Definition: string.c:1210
rb_ary_entry
VALUE rb_ary_entry(VALUE ary, long offset)
Definition: array.c:1512
rb_notimplement
void rb_notimplement(void)
Definition: error.c:2714
T_FILE
#define T_FILE
Definition: ruby.h:534
WNOHANG
#define WNOHANG
Definition: win32.h:128
ruby_set_inplace_mode
void ruby_set_inplace_mode(const char *suffix)
Definition: io.c:12861
NUM2UINT
#define NUM2UINT(x)
Definition: ruby.h:716
rb_io_puts
VALUE rb_io_puts(int argc, const VALUE *argv, VALUE out)
Definition: io.c:7747
ruby::backward::cxxanyargs::rb_define_virtual_variable
void rb_define_virtual_variable(const char *q, type *w, void_type *e)
Define a function-backended global variable.
Definition: cxxanyargs.hpp:59
if
if((ID)(DISPID) nameid !=nameid)
Definition: win32ole.c:357
rb_io_extract_modeenc
void rb_io_extract_modeenc(VALUE *vmode_p, VALUE *vperm_p, VALUE opthash, int *oflags_p, int *fmode_p, convconfig_t *convconfig_p)
Definition: io.c:5871
NUM2CHR
#define NUM2CHR(x)
Definition: ruby.h:1647
io_internal_read_struct::fd
int fd
Definition: io.c:996
rb_obj_class
VALUE rb_obj_class(VALUE)
Equivalent to Object#class in Ruby.
Definition: object.c:217
rb_io_flush
VALUE rb_io_flush(VALUE io)
Definition: io.c:1903
rb_fix_plus
VALUE rb_fix_plus(VALUE x, VALUE y)
Definition: numeric.c:3604
rb_io_ioctl
#define rb_io_ioctl
Definition: io.c:9883
rb_fdopen
FILE * rb_fdopen(int fd, const char *modestr)
Definition: io.c:6053
rb_str_new4
#define rb_str_new4
Definition: intern.h:905
fstat
#define fstat(fd, st)
Definition: win32.h:207
rb_io_modestr_oflags
int rb_io_modestr_oflags(const char *modestr)
Definition: io.c:5595
rb_syserr_fail
void rb_syserr_fail(int e, const char *mesg)
Definition: error.c:2783
MODE_BTXMODE
#define MODE_BTXMODE(a, b, c, d, e, f)
Definition: io.c:1462
FMODE_READABLE
#define FMODE_READABLE
Definition: io.h:108
rb_ascii8bit_encoding
rb_encoding * rb_ascii8bit_encoding(void)
Definition: encoding.c:1316
ECONV_STATEFUL_DECORATOR_MASK
#define ECONV_STATEFUL_DECORATOR_MASK
Definition: encoding.h:407
strerror
RUBY_EXTERN char * strerror(int)
Definition: strerror.c:11
io_internal_write_struct::buf
const void * buf
Definition: io.c:1004
rb_econv_open_opts
rb_econv_t * rb_econv_open_opts(const char *source_encoding, const char *destination_encoding, int ecflags, VALUE ecopts)
Definition: transcode.c:2561
argf::encs
struct rb_io_enc_t encs
Definition: io.c:212
MBCLEN_CHARFOUND_LEN
#define MBCLEN_CHARFOUND_LEN(ret)
Definition: encoding.h:192
FMODE_PREP
#define FMODE_PREP
Definition: io.c:4482
Init_IO
void Init_IO(void)
Definition: io.c:13144
VM_UNREACHABLE
#define VM_UNREACHABLE(func)
Definition: vm_core.h:57
io_internal_write_struct::fd
int fd
Definition: io.c:1003
rb_thread_execute_interrupts
void rb_thread_execute_interrupts(VALUE th)
Definition: thread.c:2284
F_GETFD
#define F_GETFD
Definition: win32.h:603
RB_SCAN_ARGS_LAST_HASH_KEYWORDS
#define RB_SCAN_ARGS_LAST_HASH_KEYWORDS
Definition: ruby.h:1905
ID
unsigned long ID
Definition: ruby.h:103
io_encoding_set_args::v1
VALUE v1
Definition: io.c:10189
ALLOCV_END
#define ALLOCV_END(v)
Definition: ruby.h:1750
rb_check_frozen
#define rb_check_frozen(obj)
Definition: intern.h:319
rb_io_t::writeconv
rb_econv_t * writeconv
Definition: io.h:95
select_args
Definition: io.c:9207
rb_io_set_write_io
VALUE rb_io_set_write_io(VALUE io, VALUE w)
Definition: io.c:756
rb_io_t::readconv
rb_econv_t * readconv
Definition: io.h:92
rb_enc_left_char_head
#define rb_enc_left_char_head(s, p, e, enc)
Definition: encoding.h:222
rb_fstring_cstr
VALUE rb_fstring_cstr(const char *str)
Definition: string.c:410
SHUT_RD
#define SHUT_RD
rb_cloexec_pipe
int rb_cloexec_pipe(int fildes[2])
Definition: io.c:378
rb_output_rs
VALUE rb_output_rs
Definition: io.c:189
rb_thread_io_blocking_region
VALUE rb_thread_io_blocking_region(rb_blocking_function_t *func, void *data1, int fd)
Definition: thread.c:1595
IOWAIT_SYSCALL
#define IOWAIT_SYSCALL
Definition: io.c:10825
mode_t
#define mode_t
Definition: win32.h:119
IS_PREP_STDIO
#define IS_PREP_STDIO(f)
Definition: io.c:4483
rb_f_p_arg::argc
int argc
Definition: io.c:7813
rb_thread_wait_fd
void rb_thread_wait_fd(int)
Definition: thread.c:4042
binwrite_arg::length
long length
Definition: io.c:1320
write_arg::nosync
int nosync
Definition: io.c:1326
rb_convert_type_with_id
VALUE rb_convert_type_with_id(VALUE, int, const char *, ID)
Definition: object.c:2914
MORE_CHAR_FINISHED
#define MORE_CHAR_FINISHED
Definition: io.c:2560
ALLOCV_N
#define ALLOCV_N(type, v, n)
Definition: ruby.h:1749
rb_enc_from_index
rb_encoding * rb_enc_from_index(int index)
Definition: encoding.c:609
rb_frame_this_func
ID rb_frame_this_func(void)
The original name of the current method.
Definition: eval.c:1183
T_FIXNUM
#define T_FIXNUM
Definition: ruby.h:535
NUM2SIZET
#define NUM2SIZET(x)
Definition: ruby.h:769
fmode
#define fmode
FMODE_TEXTMODE
#define FMODE_TEXTMODE
Definition: io.h:120
rb_io_memsize
RUBY_FUNC_EXPORTED size_t rb_io_memsize(const rb_io_t *fptr)
Definition: io.c:4760
EWOULDBLOCK
#define EWOULDBLOCK
Definition: io.c:141
argf
Definition: io.c:206
rb_execarg_new
VALUE rb_execarg_new(int argc, const VALUE *argv, int accept_shell, int allow_exc_opt)
Definition: process.c:2633
RB_WAITFD_OUT
#define RB_WAITFD_OUT
Definition: io.h:53
rb_io_extract_encoding_option
int rb_io_extract_encoding_option(VALUE opt, rb_encoding **enc_p, rb_encoding **enc2_p, int *fmode_p)
Definition: io.c:5744
rb_io_t::cbuf
rb_io_buffer_t cbuf
Definition: io.h:93
rb_jump_tag
void rb_jump_tag(int tag)
Continues the exception caught by rb_protect() and rb_eval_string_protect().
Definition: eval.c:884
rb_file_open
VALUE rb_file_open(const char *fname, const char *modestr)
Definition: io.c:6259
memmove
RUBY_EXTERN void * memmove(void *, const void *, size_t)
Definition: memmove.c:7
RFile
Definition: ruby.h:1134
FMODE_EXCL
#define FMODE_EXCL
Definition: io.h:118
OnigEncodingTypeST
Definition: onigmo.h:160
rb_execarg::invoke
union rb_execarg::@9 invoke
sym
#define sym(x)
Definition: date_core.c:3716
rb_check_to_integer
VALUE rb_check_to_integer(VALUE, const char *)
Tries to convert val into Integer.
Definition: object.c:2999
rb_str_new_cstr
VALUE rb_str_new_cstr(const char *)
Definition: string.c:808
argf_call_arg::argf
VALUE argf
Definition: io.c:12125
rb_fd_set
#define rb_fd_set(n, f)
Definition: intern.h:405
rb_io_check_byte_readable
void rb_io_check_byte_readable(rb_io_t *fptr)
Definition: io.c:890
rb_pipe
int rb_pipe(int *pipes)
Definition: io.c:6369
sysopen_struct::oflags
int oflags
Definition: io.c:6006
ruby_strtoul
unsigned long ruby_strtoul(const char *str, char **endptr, int base)
Definition: util.c:130
ECONV_UNIVERSAL_NEWLINE_DECORATOR
#define ECONV_UNIVERSAL_NEWLINE_DECORATOR
Definition: encoding.h:402
rb_p
void rb_p(VALUE obj)
Definition: io.c:7798
len
uint8_t len
Definition: escape.c:17
econv_incomplete_input
@ econv_incomplete_input
Definition: encoding.h:304
rb_hash_lookup
VALUE rb_hash_lookup(VALUE hash, VALUE key)
Definition: hash.c:2063
FOREACH_ARGF
#define FOREACH_ARGF()
Definition: io.c:12389
ECONV_NEWLINE_DECORATOR_READ_MASK
#define ECONV_NEWLINE_DECORATOR_READ_MASK
Definition: encoding.h:400
rb_ary_push
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:1195
rb_execarg_get
struct rb_execarg * rb_execarg_get(VALUE execarg_obj)
Definition: process.c:2608
rb_io_fptr_finalize_internal
void rb_io_fptr_finalize_internal(void *ptr)
Definition: io.c:4730
rb_io_printf
VALUE rb_io_printf(int argc, const VALUE *argv, VALUE out)
Definition: io.c:7505
SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2
#define SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags)
Definition: io.c:662
FMODE_SETENC_BY_BOM
#define FMODE_SETENC_BY_BOM
Definition: io.h:122
rb_cloexec_dup2
int rb_cloexec_dup2(int oldfd, int newfd)
Definition: io.c:325
cnt
rb_atomic_t cnt[RUBY_NSIG]
Definition: signal.c:503
rb_econv_binmode
void rb_econv_binmode(rb_econv_t *ec)
Definition: transcode.c:1925
rb_obj_freeze
VALUE rb_obj_freeze(VALUE)
Make the object unmodifiable.
Definition: object.c:1080
io_seek
#define io_seek(fptr, ofs, whence)
Definition: io.c:861
RARRAY_AREF
#define RARRAY_AREF(a, i)
Definition: psych_emitter.c:7
rb_enc_mbminlen
#define rb_enc_mbminlen(enc)
Definition: encoding.h:180
term
const char term
Definition: id.c:37
vm_core.h
rb_eEOFError
VALUE rb_eEOFError
Definition: io.c:172
RUBY_UBF_IO
#define RUBY_UBF_IO
Definition: intern.h:945
io_internal_read_struct
Definition: io.c:995
econv_invalid_byte_sequence
@ econv_invalid_byte_sequence
Definition: encoding.h:298
SSIZE_MAX
#define SSIZE_MAX
Definition: ruby.h:323
rb_sys_fail
void rb_sys_fail(const char *mesg)
Definition: error.c:2795
rb_eTypeError
VALUE rb_eTypeError
Definition: error.c:924
rb_ary_concat
VALUE rb_ary_concat(VALUE x, VALUE y)
Definition: array.c:4069
rb_econv_putbackable
int rb_econv_putbackable(rb_econv_t *ec)
Definition: transcode.c:1725
argf::current_file
VALUE current_file
Definition: io.c:207
rb_stderr
VALUE rb_stderr
Definition: io.c:184
rb_io_t
struct rb_io_t rb_io_t
rb_update_max_fd
void rb_update_max_fd(int fd)
Definition: io.c:218
rb_fdset_t
fd_set rb_fdset_t
Definition: intern.h:403
rb_io_read_check
void rb_io_read_check(rb_io_t *fptr)
Definition: io.c:944
ALLOC
#define ALLOC(type)
Definition: ruby.h:1664
rb_time_interval
struct timeval rb_time_interval(VALUE num)
Definition: time.c:2669
rb_intern
#define rb_intern(str)
rb_f_sprintf
VALUE rb_f_sprintf(int, const VALUE *)
Definition: sprintf.c:198
rb_maygvl_fd_fix_cloexec
void rb_maygvl_fd_fix_cloexec(int fd)
Definition: io.c:245
rb_eRuntimeError
VALUE rb_eRuntimeError
Definition: error.c:922
rb_thread_call_without_gvl
void * rb_thread_call_without_gvl(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2)
rb_stdin
VALUE rb_stdin
Definition: io.c:184
rb_thread_fd_select
int rb_thread_fd_select(int, rb_fdset_t *, rb_fdset_t *, rb_fdset_t *, struct timeval *)
Definition: thread.c:4067
rb_execarg::envp_str
VALUE envp_str
Definition: internal.h:2038
RETURN_ENUMERATOR
#define RETURN_ENUMERATOR(obj, argc, argv)
Definition: intern.h:279
ECONV_AFTER_OUTPUT
#define ECONV_AFTER_OUTPUT
Definition: encoding.h:416
STRNCASECMP
#define STRNCASECMP(s1, s2, n)
Definition: ruby.h:2324
write_arg::io
VALUE io
Definition: io.c:1324
rb_uninterruptible
VALUE rb_uninterruptible(VALUE(*b_proc)(VALUE), VALUE data)
Definition: thread.c:5554
copy_stream_struct::src
VALUE src
Definition: io.c:10757
FMODE_READWRITE
#define FMODE_READWRITE
Definition: io.h:110
size
int size
Definition: encoding.c:58
rb_str_set_len
void rb_str_set_len(VALUE, long)
Definition: string.c:2692
FALSE
#define FALSE
Definition: nkf.h:174
rb_f_p_arg::argv
VALUE * argv
Definition: io.c:7814
argf::init_p
int8_t init_p
Definition: io.c:213
FIXNUM_P
#define FIXNUM_P(f)
Definition: ruby.h:396
ENCINDEX_UTF_32LE
#define ENCINDEX_UTF_32LE
Definition: encindex.h:48
ECONV_NEWLINE_DECORATOR_MASK
#define ECONV_NEWLINE_DECORATOR_MASK
Definition: encoding.h:399
rb_io_set_nonblock
void rb_io_set_nonblock(rb_io_t *fptr)
Definition: io.c:2782
rb_gc
void rb_gc(void)
Definition: gc.c:8682
rb_io_check_initialized
void rb_io_check_initialized(rb_io_t *fptr)
Definition: io.c:710
SEEK_END
#define SEEK_END
Definition: io.c:867
rb_eEWOULDBLOCK
VALUE rb_eEWOULDBLOCK
Definition: error.c:55
rb_to_int
VALUE rb_to_int(VALUE)
Converts val into Integer.
Definition: object.c:3021
O_ACCMODE
#define O_ACCMODE
Definition: io.c:125
READ_DATA_PENDING
#define READ_DATA_PENDING(fptr)
Definition: io.c:466
rb_int_modulo
VALUE rb_int_modulo(VALUE x, VALUE y)
Definition: numeric.c:3886
iovec::iov_base
void * iov_base
Definition: win32.h:226
PIDT2NUM
#define PIDT2NUM(v)
Definition: ruby.h:354
MBCLEN_NEEDMORE_P
#define MBCLEN_NEEDMORE_P(ret)
Definition: encoding.h:194
rb_rs
VALUE rb_rs
Definition: io.c:188
list
struct rb_encoding_entry * list
Definition: encoding.c:56
SET_BINARY_MODE_WITH_SEEK_CUR
#define SET_BINARY_MODE_WITH_SEEK_CUR(fptr)
Definition: io.c:663
rb_check_to_int
VALUE rb_check_to_int(VALUE)
Tries to convert val into Integer.
Definition: object.c:3036
rb_execarg_extract_options
VALUE rb_execarg_extract_options(VALUE execarg_obj, VALUE opthash)
Definition: process.c:2279
MEMZERO
#define MEMZERO(p, type, n)
Definition: ruby.h:1752
READ_CHECK
#define READ_CHECK(fptr)
Definition: io.c:482
rb_output_fs
VALUE rb_output_fs
Definition: io.c:187
rb_str_new_frozen
VALUE rb_str_new_frozen(VALUE)
Definition: string.c:1203
argf::next_p
int8_t next_p
Definition: io.c:213
rb_econv_putback
void rb_econv_putback(rb_econv_t *ec, unsigned char *p, int n)
Definition: transcode.c:1736
rb_scan_args
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:2159
bufread_arg::len
long len
Definition: io.c:2468
rb_execarg::use_shell
unsigned use_shell
Definition: internal.h:2041
memcmp
int memcmp(const void *s1, const void *s2, size_t len)
Definition: memcmp.c:7
FD_CLOEXEC
#define FD_CLOEXEC
Definition: win32.h:610
ECONV_NEWLINE_DECORATOR_WRITE_MASK
#define ECONV_NEWLINE_DECORATOR_WRITE_MASK
Definition: encoding.h:401
READ_DATA_PENDING_COUNT
#define READ_DATA_PENDING_COUNT(fptr)
Definition: io.c:467
rb_error_arity
MJIT_STATIC void rb_error_arity(int argc, int min, int max)
Definition: vm_insnhelper.c:387
rb_define_variable
void rb_define_variable(const char *, VALUE *)
Definition: variable.c:499
foreach_arg::argv
VALUE * argv
Definition: io.c:10356
rb_default_rs
VALUE rb_default_rs
Definition: io.c:190
rb_default_internal_encoding
rb_encoding * rb_default_internal_encoding(void)
Definition: encoding.c:1512
rb_notify_fd_close
int rb_notify_fd_close(int fd, struct list_head *)
Definition: thread.c:2364
rb_obj_dup
VALUE rb_obj_dup(VALUE)
Equivalent to Object#dup in Ruby.
Definition: object.c:420
ECONV_ERROR_HANDLER_MASK
#define ECONV_ERROR_HANDLER_MASK
Definition: encoding.h:392
rb_io_close
VALUE rb_io_close(VALUE io)
Definition: io.c:4820
convconfig_t
struct rb_io_enc_t convconfig_t
Definition: io.c:5812
CONST_ID
#define CONST_ID(var, str)
Definition: ruby.h:1841
io_encoding_set_args::opt
VALUE opt
Definition: io.c:10191
ENCINDEX_UTF_16LE
#define ENCINDEX_UTF_16LE
Definition: encindex.h:46
StringValueCStr
#define StringValueCStr(v)
Definition: ruby.h:604
O_BINARY
#define O_BINARY
Definition: _sdbm.c:87
rb_f_syscall
#define rb_f_syscall
Definition: io.c:10107
ENC_CODERANGE_BROKEN
#define ENC_CODERANGE_BROKEN
Definition: encoding.h:106
rb_check_array_type
VALUE rb_check_array_type(VALUE ary)
Definition: array.c:909
rb_econv_close
void rb_econv_close(rb_econv_t *ec)
Definition: transcode.c:1685
write_arg::str
VALUE str
Definition: io.c:1325
rb_yield_values2
VALUE rb_yield_values2(int n, const VALUE *argv)
Definition: vm_eval.c:1271
copy_stream_struct::notimp
const char * notimp
Definition: io.c:10769
rb_to_encoding_index
int rb_to_encoding_index(VALUE enc)
Definition: encoding.c:197
EPERM
#define EPERM
Definition: _sdbm.c:92
EOF
#define EOF
Definition: vsnprintf.c:203
foreach_arg::io
VALUE io
Definition: io.c:10357
rb_lastline_get
VALUE rb_lastline_get(void)
Definition: vm.c:1316
rb_close_before_exec
void rb_close_before_exec(int lowfd, int maxhint, VALUE noclose_fds)
NUM2MODET
#define NUM2MODET(v)
Definition: ruby.h:372
rb_eNotImpError
VALUE rb_eNotImpError
Definition: error.c:934
fchmod
int fchmod(int fd, int mode)
Definition: win32.c:7638
CLASS_OF
#define CLASS_OF(v)
Definition: ruby.h:484
rb_io_wait_readable
int rb_io_wait_readable(int f)
Definition: io.c:1204
rb_fd_term
#define rb_fd_term(f)
Definition: intern.h:414
rb_obj_method_arity
int rb_obj_method_arity(VALUE, ID)
Definition: proc.c:2652
rb_io_t::writeconv_asciicompat
VALUE writeconv_asciicompat
Definition: io.h:96
rb_w32_get_osfhandle
SOCKET rb_w32_get_osfhandle(int)
Definition: win32.c:1078
ruby::backward::cxxanyargs::rb_define_hooked_variable
void rb_define_hooked_variable(const char *q, VALUE *w, type *e, void_type *r)
Define a function-backended global variable.
Definition: cxxanyargs.hpp:106
rb_class_new
VALUE rb_class_new(VALUE super)
Creates a new class.
Definition: class.c:241
copy_stream_struct::src_stat
struct stat src_stat
Definition: io.c:10771
dup2
RUBY_EXTERN int dup2(int, int)
Definition: dup2.c:27
MBCLEN_CHARFOUND_P
#define MBCLEN_CHARFOUND_P(ret)
Definition: encoding.h:191
rb_io_wait_readwrite
rb_io_wait_readwrite
Definition: ruby.h:1929
rb_thread_schedule
void rb_thread_schedule(void)
Definition: thread.c:1408
RARRAY_LEN
#define RARRAY_LEN(a)
Definition: ruby.h:1070
ioctl
int ioctl(int, int,...)
Definition: win32.c:2811
no_exception_p
#define no_exception_p(opts)
Definition: io.c:2803
rb_io_t::lineno
int lineno
Definition: io.h:71
Init_File
void Init_File(void)
Definition: file.c:6435
rb_ary_new4
#define rb_ary_new4
Definition: intern.h:105
rb_check_hash_type
VALUE rb_check_hash_type(VALUE hash)
Definition: hash.c:1852
rb_cObject
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:2010
iovec
Definition: win32.h:225
bom_prefix_len
@ bom_prefix_len
Definition: io.c:5455
bufread_arg::str_ptr
char * str_ptr
Definition: io.c:2467
rb_ary_new2
#define rb_ary_new2
Definition: intern.h:103
buf
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:4322
rb_exc_raise
void rb_exc_raise(VALUE mesg)
Raises an exception in the current thread.
Definition: eval.c:668
rb_io_bufwrite
ssize_t rb_io_bufwrite(VALUE io, const void *buf, size_t size)
Definition: io.c:1549
T_BIGNUM
#define T_BIGNUM
Definition: ruby.h:533
rb_syserr_fail_path
#define rb_syserr_fail_path(err, path)
Definition: internal.h:1631
rb_stdout
VALUE rb_stdout
Definition: io.c:184
rb_thread_atfork
void rb_thread_atfork(void)
Definition: thread.c:4548
IO_RBUF_CAPA_FOR
#define IO_RBUF_CAPA_FOR(fptr)
Definition: io.c:151
seek_arg
Definition: io.c:10506
rb_str_append
VALUE rb_str_append(VALUE, VALUE)
Definition: string.c:2965
F_SETFD
#define F_SETFD
Definition: win32.h:604
rb_enc_str_coderange
int rb_enc_str_coderange(VALUE)
Definition: string.c:657
rb_bug
void rb_bug(const char *fmt,...)
Definition: error.c:636
rb_io_t::rb_io_enc_t::ecopts
VALUE ecopts
Definition: io.h:89
getline_arg::chomp
unsigned int chomp
Definition: stringio.c:1152
internal.h
OBJ_INIT_COPY
#define OBJ_INIT_COPY(obj, orig)
Definition: intern.h:331
rb_to_encoding
rb_encoding * rb_to_encoding(VALUE enc)
Definition: encoding.c:245
T_ARRAY
#define T_ARRAY
Definition: ruby.h:530
select_args::timeout
struct timeval * timeout
Definition: io.c:9209
rb_mKernel
RUBY_EXTERN VALUE rb_mKernel
Definition: ruby.h:1998
finish_writeconv_arg::noalloc
int noalloc
Definition: io.c:4551
f
#define f
io_internal_read_struct::buf
void * buf
Definition: io.c:998
F_SETFL
#define F_SETFL
Definition: win32.h:608
rb_io_t::mode
int mode
Definition: io.h:69
binwrite_arg
Definition: io.c:1316
STATIC_ASSERT
#define STATIC_ASSERT(name, expr)
Definition: internal.h:230
rb_funcall
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
Definition: vm_eval.c:922
rb_define_global_const
void rb_define_global_const(const char *, VALUE)
Definition: variable.c:2903
iovec::iov_len
size_t iov_len
Definition: win32.h:227
rb_fd_isset
#define rb_fd_isset(n, f)
Definition: intern.h:407
rb_io_taint_check
VALUE rb_io_taint_check(VALUE io)
Definition: io.c:703
UNREACHABLE
#define UNREACHABLE
Definition: ruby.h:63
ENCODING_GET
#define ENCODING_GET(obj)
Definition: encoding.h:62
rb_warn_deprecated
void rb_warn_deprecated(const char *fmt, const char *suggest,...)
Definition: error.c:366
rb_sprintf
VALUE rb_sprintf(const char *format,...)
Definition: sprintf.c:1197
FIX2UINT
#define FIX2UINT(x)
Definition: ruby.h:718
VALUE
unsigned long VALUE
Definition: ruby.h:102
ioctl_arg
#define ioctl_arg
Definition: wait.c:32
rb_execarg_setenv
void rb_execarg_setenv(VALUE execarg_obj, VALUE env)
Definition: process.c:2646
FMODE_APPEND
#define FMODE_APPEND
Definition: io.h:115
argf_call_arg::argc
int argc
Definition: io.c:12123
rb_io_read_pending
int rb_io_read_pending(rb_io_t *fptr)
Definition: io.c:935
strrchr
char * strrchr(const char *, const char)
T_NIL
#define T_NIL
Definition: ruby.h:522
fsync
#define fsync
Definition: win32.h:216
rb_fd_init
#define rb_fd_init(f)
Definition: intern.h:412
timeval
Definition: missing.h:53
rb_freopen
int rb_freopen(VALUE fname, const char *mode, FILE *file)
Definition: file.c:693
argf_call_arg::argv
VALUE * argv
Definition: io.c:12124
rb_obj_alloc
VALUE rb_obj_alloc(VALUE)
Allocates an instance of klass.
Definition: object.c:1895
str
char str[HTML_ESCAPE_MAX_LEN+1]
Definition: escape.c:18
rb_execarg
Definition: internal.h:2025
rb_enc_find_index
int rb_enc_find_index(const char *name)
Definition: encoding.c:693
rb_io_t::stdio_file
FILE * stdio_file
Definition: io.h:67
io_encoding_set_args::v2
VALUE v2
Definition: io.c:10190
binwrite_arg::str
VALUE str
Definition: io.c:1318
RARRAY_CONST_PTR
#define RARRAY_CONST_PTR(s)
Definition: psych_emitter.c:4
rb_readwrite_sys_fail
void rb_readwrite_sys_fail(enum rb_io_wait_readwrite writable, const char *mesg)
Definition: io.c:12927
RUBY_TYPED_FREE_IMMEDIATELY
#define RUBY_TYPED_FREE_IMMEDIATELY
Definition: ruby.h:1207
rb_fd_fix_cloexec
void rb_fd_fix_cloexec(int fd)
Definition: io.c:268
rb_cIO
VALUE rb_cIO
Definition: io.c:171
rb_last_status_clear
void rb_last_status_clear(void)
Definition: process.c:554
PREP_STDIO_NAME
#define PREP_STDIO_NAME(f)
Definition: io.c:4484
ARGVSTR2ARGV
#define ARGVSTR2ARGV(argv_str)
Definition: internal.h:2075
rb_w32_set_nonblock
int rb_w32_set_nonblock(int)
Definition: win32.c:4390
ARGF_FORWARD
#define ARGF_FORWARD(argc, argv)
Definition: io.c:8584
ENC_CODERANGE_7BIT
#define ENC_CODERANGE_7BIT
Definition: encoding.h:104
rb_stdio_set_default_encoding
void rb_stdio_set_default_encoding(void)
Definition: io.c:11758
rb_usascii_str_new
VALUE rb_usascii_str_new(const char *, long)
Definition: string.c:780
rb_wait_for_single_fd
int rb_wait_for_single_fd(int fd, int events, struct timeval *tv)
Definition: thread.c:4276
rb_enc_ascget
int rb_enc_ascget(const char *p, const char *e, int *len, rb_encoding *enc)
Definition: encoding.c:1044
econv_finished
@ econv_finished
Definition: encoding.h:302
rb_io_sync
#define rb_io_sync
Definition: io.c:2253
rb_hash_aset
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
Definition: hash.c:2852
FMODE_CREATE
#define FMODE_CREATE
Definition: io.h:116
rb_w32_fd_is_text
char rb_w32_fd_is_text(int)
Definition: win32.c:7756
rb_str_encode_ospath
VALUE rb_str_encode_ospath(VALUE path)
Definition: file.c:236
rb_io_fptr_finalize
#define rb_io_fptr_finalize(fptr)
Definition: io.c:4757
NIL_P
#define NIL_P(v)
Definition: ruby.h:482
argf_of
#define argf_of(obj)
Definition: io.c:461
rb_str_modify_expand
void rb_str_modify_expand(VALUE, long)
Definition: string.c:2122
fileno
#define fileno(p)
Definition: vsnprintf.c:219
io.h
rb_str_tmp_frozen_release
void rb_str_tmp_frozen_release(VALUE str, VALUE tmp)
Definition: string.c:1217
argc
int argc
Definition: ruby.c:222
rb_io_gets
VALUE rb_io_gets(VALUE io)
Definition: io.c:3573
rb_enc_warn
void rb_enc_warn(rb_encoding *enc, const char *fmt,...)
Definition: error.c:325
rb_funcall3
#define rb_funcall3
Definition: ruby.h:1896
rb_exec_recursive
VALUE rb_exec_recursive(VALUE(*)(VALUE, VALUE, int), VALUE, VALUE)
Definition: thread.c:5075
rb_io_fsync
#define rb_io_fsync
Definition: io.c:2252
rb_sys_fail_str
void rb_sys_fail_str(VALUE mesg)
Definition: error.c:2801
argf::inplace
VALUE inplace
Definition: io.c:211
econv_undefined_conversion
@ econv_undefined_conversion
Definition: encoding.h:299
rb_define_const
void rb_define_const(VALUE, const char *, VALUE)
Definition: variable.c:2891
recur
#define recur(fmt)
Definition: date_strptime.c:152
ioctl_req_t
int ioctl_req_t
Definition: io.c:9573
rb_eSystemCallError
VALUE rb_eSystemCallError
Definition: error.c:943
err
int err
Definition: win32.c:135
seek_arg::mode
int mode
Definition: io.c:10509
rb_thread_to_be_killed
int rb_thread_to_be_killed(VALUE thread)
Definition: thread.c:2472
encindex.h
KEEPGVL
#define KEEPGVL
Definition: io.c:4775
rb_io_make_open_file
rb_io_t * rb_io_make_open_file(VALUE obj)
Definition: io.c:8080
rb_execarg_addopt
int rb_execarg_addopt(VALUE execarg_obj, VALUE key, VALUE val)
Definition: process.c:2013
NOFILE
#define NOFILE
Definition: io.c:97
shutdown
#define shutdown(a, b)
Definition: io.c:667
rb_data_type_struct
Definition: ruby.h:1148
rb_io_fcntl
#define rb_io_fcntl
Definition: io.c:9977
MakeOpenFile
#define MakeOpenFile(obj, fp)
Definition: io.h:129
rb_gets
VALUE rb_gets(void)
Definition: io.c:8902
GetOpenFile
#define GetOpenFile(obj, fp)
Definition: io.h:127
rb_str_unlocktmp
VALUE rb_str_unlocktmp(VALUE)
Definition: string.c:2675
SEEK_SET
#define SEEK_SET
Definition: io.c:865
io_encoding_set_args
Definition: io.c:10187
econv_destination_buffer_full
@ econv_destination_buffer_full
Definition: encoding.h:300
NEED_NEWLINE_DECORATOR_ON_WRITE
#define NEED_NEWLINE_DECORATOR_ON_WRITE(fptr)
Definition: io.c:507
rb_io_wait_writable
int rb_io_wait_writable(int f)
Definition: io.c:1228
rb_gc_mark
void rb_gc_mark(VALUE ptr)
Definition: gc.c:5215
write_arg
Definition: io.c:1323
rb_io_t::rb_io_enc_t::enc
rb_encoding * enc
Definition: io.h:86
_
#define _(args)
Definition: dln.h:28
rb_iter_break_value
void rb_iter_break_value(VALUE val)
Definition: vm.c:1552
count
int count
Definition: encoding.c:57
Qtrue
#define Qtrue
Definition: ruby.h:468
rb_str_catf
VALUE rb_str_catf(VALUE str, const char *format,...)
Definition: sprintf.c:1237
errno
int errno
READ_CHAR_PENDING
#define READ_CHAR_PENDING(fptr)
Definition: io.c:471
NUM2OFFT
#define NUM2OFFT(x)
Definition: ruby.h:761
rb_rescue2
VALUE rb_rescue2(VALUE(*b_proc)(VALUE), VALUE data1, VALUE(*r_proc)(VALUE, VALUE), VALUE data2,...)
An equivalent of rescue clause.
Definition: eval.c:962
NEED_NEWLINE_DECORATOR_ON_READ
#define NEED_NEWLINE_DECORATOR_ON_READ(fptr)
Definition: io.c:506
rb_class_name
VALUE rb_class_name(VALUE)
Definition: variable.c:274
FMODE_WRITABLE
#define FMODE_WRITABLE
Definition: io.h:109
SYMBOL_P
#define SYMBOL_P(x)
Definition: ruby.h:413
rb_last_status_set
void rb_last_status_set(int status, rb_pid_t pid)
Definition: process.c:545
intptr_t
int intptr_t
Definition: win32.h:90
rb_mWaitReadable
VALUE rb_mWaitReadable
Definition: io.c:174
rb_eEINPROGRESS
VALUE rb_eEINPROGRESS
Definition: error.c:56
rb_io_check_char_readable
void rb_io_check_char_readable(rb_io_t *fptr)
Definition: io.c:871
rb_enumeratorize
VALUE rb_enumeratorize(VALUE obj, VALUE meth, int argc, const VALUE *argv)
Definition: enumerator.c:516
seek_arg::offset
VALUE offset
Definition: io.c:10508
rb_io_print
VALUE rb_io_print(int argc, const VALUE *argv, VALUE out)
Definition: io.c:7576
rb_class_new_instance
VALUE rb_class_new_instance(int, const VALUE *, VALUE)
Allocates and initializes an instance of klass.
Definition: object.c:1955
MEMMOVE
#define MEMMOVE(p1, p2, type, n)
Definition: ruby.h:1754
copy_stream_struct::src_offset
off_t src_offset
Definition: io.c:10760
ruby_atomic.h
rb_mutex_allow_trap
void rb_mutex_allow_trap(VALUE self, int val)
Definition: thread_sync.c:545
rb_io_t::tied_io_for_writing
VALUE tied_io_for_writing
Definition: io.h:77
LONG2FIX
#define LONG2FIX(i)
Definition: ruby.h:265
rb_ivar_set
VALUE rb_ivar_set(VALUE, ID, VALUE)
Definition: variable.c:1300
T_STRING
#define T_STRING
Definition: ruby.h:528
DEFULT_IOCTL_NARG_LEN
#define DEFULT_IOCTL_NARG_LEN
Definition: io.c:9608
rb_atomic_t
int rb_atomic_t
Definition: ruby_atomic.h:124
FL_SINGLETON
#define FL_SINGLETON
Definition: ruby.h:1278
ATOMIC_CAS
#define ATOMIC_CAS(var, oldval, newval)
Definition: ruby_atomic.h:136
rb_define_class_under
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:698
copy_stream_struct::dst_fd
int dst_fd
Definition: io.c:10763
rb_io_check_closed
void rb_io_check_closed(rb_io_t *fptr)
Definition: io.c:718
NEED_NEWLINE_DECORATOR_ON_READ_CHECK
#define NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr)
Definition: io.c:661
rb_econv_memsize
size_t rb_econv_memsize(rb_econv_t *ec)
Definition: transcode.c:1703
rb_str_encode
VALUE rb_str_encode(VALUE str, VALUE to, int ecflags, VALUE ecopts)
Definition: transcode.c:2870
copy_stream_struct::close_src
unsigned close_src
Definition: io.c:10764
rb_yield
VALUE rb_yield(VALUE)
Definition: vm_eval.c:1237
RB_INTEGER_TYPE_P
#define RB_INTEGER_TYPE_P(obj)
Definition: ruby_missing.h:15
rb_ensure
VALUE rb_ensure(VALUE(*b_proc)(VALUE), VALUE data1, VALUE(*e_proc)(VALUE), VALUE data2)
An equivalent to ensure clause.
Definition: eval.c:1115
finish_writeconv_arg
Definition: io.c:4549
rb_io_pread
#define rb_io_pread
Definition: io.c:5270
rb_io_t::encs
struct rb_io_t::rb_io_enc_t encs
binwrite_arg::ptr
const char * ptr
Definition: io.c:1319
RB_IO_WAIT_WRITABLE
@ RB_IO_WAIT_WRITABLE
Definition: ruby.h:1929
ENCINDEX_UTF_32BE
#define ENCINDEX_UTF_32BE
Definition: encindex.h:47
rb_ary_new
VALUE rb_ary_new(void)
Definition: array.c:723
NEWOBJ_OF
#define NEWOBJ_OF(obj, type, klass, flags)
Definition: ruby.h:785
rb_execarg::cmd
struct rb_execarg::@9::@11 cmd
builtin.h
NUM2INT
#define NUM2INT(x)
Definition: ruby.h:715
Qnil
#define Qnil
Definition: ruby.h:469
finish_writeconv_arg::fptr
rb_io_t * fptr
Definition: io.c:4550
select_args::fdsets
rb_fdset_t fdsets[4]
Definition: io.c:9210
rb_fstring_lit
#define rb_fstring_lit(str)
Definition: internal.h:2129
seek_arg::io
VALUE io
Definition: io.c:10507
copy_stream_struct::dst
VALUE dst
Definition: io.c:10758
rb_exec_async_signal_safe
int rb_exec_async_signal_safe(const struct rb_execarg *e, char *errmsg, size_t errmsg_buflen)
Definition: process.c:3523
thread.h
OFFT2NUM
#define OFFT2NUM(v)
Definition: ruby.h:285
rb_mEnumerable
VALUE rb_mEnumerable
Definition: enum.c:20
util.h
ECONV_DEFAULT_NEWLINE_DECORATOR
#define ECONV_DEFAULT_NEWLINE_DECORATOR
Definition: encoding.h:409
sysopen_struct::fname
VALUE fname
Definition: io.c:6005
rb_io_t
Definition: io.h:66
rb_str_chomp_string
VALUE rb_str_chomp_string(VALUE str, VALUE chomp)
Definition: string.c:8921
rb_eStandardError
VALUE rb_eStandardError
Definition: error.c:921
rb_econv_make_exception
VALUE rb_econv_make_exception(rb_econv_t *ec)
Definition: transcode.c:4218
RB_GC_GUARD
#define RB_GC_GUARD(v)
Definition: ruby.h:585
numberof
#define numberof(array)
Definition: etc.c:618
rb_reserved_fd_p
int rb_reserved_fd_p(int fd)
rb_str_coderange_scan_restartable
long rb_str_coderange_scan_restartable(const char *, const char *, rb_encoding *, int *)
Definition: string.c:567
rb_io_unbuffered
void rb_io_unbuffered(rb_io_t *fptr)
Definition: io.c:6363
rb_io_t::rb_io_enc_t::enc2
rb_encoding * enc2
Definition: io.h:87
rb_io_t::writeconv_pre_ecflags
int writeconv_pre_ecflags
Definition: io.h:98
RSTRING_LEN
#define RSTRING_LEN(str)
Definition: ruby.h:1005
rb_io_fdatasync
#define rb_io_fdatasync
Definition: io.c:2304
MODE_BTMODE
#define MODE_BTMODE(a, b, c)
Definition: io.c:1459
rb_io_close_on_exec_p
#define rb_io_close_on_exec_p
Definition: io.c:4421
rb_execarg::sh
struct rb_execarg::@9::@10 sh
rb_any_to_s
VALUE rb_any_to_s(VALUE)
Default implementation of #to_s.
Definition: object.c:527
rb_io_binmode
VALUE rb_io_binmode(VALUE io)
Definition: io.c:5334
rb_mutex_new
VALUE rb_mutex_new(void)
Definition: thread_sync.c:165
DEFAULT_TEXTMODE
#define DEFAULT_TEXTMODE
Definition: io.c:653
rb_enc_str_new
VALUE rb_enc_str_new(const char *, long, rb_encoding *)
Definition: string.c:796
RUBY_PIPE_NONBLOCK_DEFAULT
#define RUBY_PIPE_NONBLOCK_DEFAULT
Definition: io.c:168
argf::filename
VALUE filename
Definition: io.c:207
rb_str_cat
VALUE rb_str_cat(VALUE, const char *, long)
Definition: string.c:2812
NEXT_ARGF_FORWARD
#define NEXT_ARGF_FORWARD(argc, argv)
Definition: io.c:8588
rb_io_stdio_file
FILE * rb_io_stdio_file(rb_io_t *fptr)
Definition: io.c:8032
rb_enc_associate
VALUE rb_enc_associate(VALUE obj, rb_encoding *enc)
Definition: encoding.c:866
rb_eIOError
VALUE rb_eIOError
Definition: io.c:173
copy_stream_struct::copy_length
off_t copy_length
Definition: io.c:10759
rb_define_alloc_func
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
rb_thread_fd_close
void rb_thread_fd_close(int)
Definition: thread.c:2386
RTEST
#define RTEST(v)
Definition: ruby.h:481
getline_arg::rs
VALUE rs
Definition: stringio.c:1150
ARGF
#define ARGF
Definition: io.c:462
SSIZET2NUM
#define SSIZET2NUM(v)
Definition: ruby.h:296
rb_econv_result_t
rb_econv_result_t
Definition: encoding.h:297
ECONV_PARTIAL_INPUT
#define ECONV_PARTIAL_INPUT
Definition: encoding.h:415
rb_cloexec_open
int rb_cloexec_open(const char *pathname, int flags, mode_t mode)
Definition: io.c:292
rb_io_ungetbyte
VALUE rb_io_ungetbyte(VALUE io, VALUE b)
Definition: io.c:4276
rb_mod_sys_fail_str
void rb_mod_sys_fail_str(VALUE mod, VALUE mesg)
Definition: error.c:2843
__sFILE
Definition: vsnprintf.c:169
rb_str_buf_cat
VALUE rb_str_buf_cat(VALUE, const char *, long)
rb_thread_call_with_gvl
RUBY_SYMBOL_EXPORT_BEGIN void * rb_thread_call_with_gvl(void *(*func)(void *), void *data1)
Definition: thread.c:1662
rb_usascii_encoding
rb_encoding * rb_usascii_encoding(void)
Definition: encoding.c:1340
rb_syserr_fail_str
void rb_syserr_fail_str(int e, VALUE mesg)
Definition: error.c:2789
RSTRING_END
#define RSTRING_END(str)
Definition: ruby.h:1013
copy_stream_struct::syserr
const char * syserr
Definition: io.c:10768
ruby_sized_xfree
void ruby_sized_xfree(void *x, size_t size)
Definition: gc.c:10162
is_socket
#define is_socket(fd, path)
Definition: io.c:673
io_internal_write_struct::capa
size_t capa
Definition: io.c:1005
dln.h
name
const char * name
Definition: nkf.c:208
rb_econv_open_exc
VALUE rb_econv_open_exc(const char *senc, const char *denc, int ecflags)
Definition: transcode.c:2019
rb_execution_context_struct
Definition: vm_core.h:843
rb_fork_ruby
rb_pid_t rb_fork_ruby(int *status)