Ruby  2.5.0dev(2017-10-22revision60238)
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 "internal.h"
15 #include "ruby/io.h"
16 #include "ruby/thread.h"
17 #include "dln.h"
18 #include "encindex.h"
19 #include "id.h"
20 #include <ctype.h>
21 #include <errno.h>
22 #include "ruby_atomic.h"
23 
24 #undef free
25 #define free(x) xfree(x)
26 
27 #if defined(DOSISH) || defined(__CYGWIN__)
28 #include <io.h>
29 #endif
30 
31 #include <sys/types.h>
32 #if defined HAVE_NET_SOCKET_H
33 # include <net/socket.h>
34 #elif defined HAVE_SYS_SOCKET_H
35 # include <sys/socket.h>
36 #endif
37 
38 #if defined(__BOW__) || defined(__CYGWIN__) || defined(_WIN32)
39 # define NO_SAFE_RENAME
40 #endif
41 
42 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__sun) || defined(_nec_ews)
43 # define USE_SETVBUF
44 #endif
45 
46 #ifdef __QNXNTO__
47 #include "unix.h"
48 #endif
49 
50 #include <sys/types.h>
51 #if defined(HAVE_SYS_IOCTL_H) && !defined(_WIN32)
52 #include <sys/ioctl.h>
53 #endif
54 #if defined(HAVE_FCNTL_H) || defined(_WIN32)
55 #include <fcntl.h>
56 #elif defined(HAVE_SYS_FCNTL_H)
57 #include <sys/fcntl.h>
58 #endif
59 
60 #if !HAVE_OFF_T && !defined(off_t)
61 # define off_t long
62 #endif
63 
64 #ifdef HAVE_SYS_TIME_H
65 # include <sys/time.h>
66 #endif
67 
68 #include <sys/stat.h>
69 
70 #if defined(HAVE_SYS_PARAM_H) || defined(__HIUX_MPP__)
71 # include <sys/param.h>
72 #endif
73 
74 #if !defined NOFILE
75 # define NOFILE 64
76 #endif
77 
78 #ifdef HAVE_UNISTD_H
79 #include <unistd.h>
80 #endif
81 
82 #ifdef HAVE_SYSCALL_H
83 #include <syscall.h>
84 #elif defined HAVE_SYS_SYSCALL_H
85 #include <sys/syscall.h>
86 #endif
87 
88 #ifdef HAVE_SYS_UIO_H
89 #include <sys/uio.h>
90 #endif
91 
92 #ifdef HAVE_SYS_WAIT_H
93 # include <sys/wait.h> /* for WNOHANG on BSD */
94 #endif
95 
96 #include "ruby/util.h"
97 
98 #ifndef O_ACCMODE
99 #define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR)
100 #endif
101 
102 #if SIZEOF_OFF_T > SIZEOF_LONG && !defined(HAVE_LONG_LONG)
103 # error off_t is bigger than long, but you have no long long...
104 #endif
105 
106 #ifndef PIPE_BUF
107 # ifdef _POSIX_PIPE_BUF
108 # define PIPE_BUF _POSIX_PIPE_BUF
109 # else
110 # define PIPE_BUF 512 /* is this ok? */
111 # endif
112 #endif
113 
114 #ifndef EWOULDBLOCK
115 # define EWOULDBLOCK EAGAIN
116 #endif
117 
118 #if defined(HAVE___SYSCALL) && (defined(__APPLE__) || defined(__OpenBSD__))
119 /* Mac OS X and OpenBSD have __syscall but don't define it in headers */
120 off_t __syscall(quad_t number, ...);
121 #endif
122 
123 #ifdef __native_client__
124 # undef F_GETFD
125 # ifdef NACL_NEWLIB
126 # undef HAVE_IOCTL
127 # endif
128 #endif
129 
130 #define IO_RBUF_CAPA_MIN 8192
131 #define IO_CBUF_CAPA_MIN (128*1024)
132 #define IO_RBUF_CAPA_FOR(fptr) (NEED_READCONV(fptr) ? IO_CBUF_CAPA_MIN : IO_RBUF_CAPA_MIN)
133 #define IO_WBUF_CAPA_MIN 8192
134 
135 /* define system APIs */
136 #ifdef _WIN32
137 #undef open
138 #define open rb_w32_uopen
139 #undef rename
140 #define rename(f, t) rb_w32_urename((f), (t))
141 #endif
142 
148 
149 static VALUE rb_eEAGAINWaitReadable;
150 static VALUE rb_eEAGAINWaitWritable;
151 static VALUE rb_eEWOULDBLOCKWaitReadable;
152 static VALUE rb_eEWOULDBLOCKWaitWritable;
153 static VALUE rb_eEINPROGRESSWaitWritable;
154 static VALUE rb_eEINPROGRESSWaitReadable;
155 
157 static VALUE orig_stdout, orig_stderr;
158 
163 
164 static VALUE argf;
165 
166 #define id_exception idException
167 static ID id_write, id_read, id_getc, id_flush, id_readpartial, id_set_encoding;
168 static VALUE sym_mode, sym_perm, sym_flags, sym_extenc, sym_intenc, sym_encoding, sym_open_args;
169 static VALUE sym_textmode, sym_binmode, sym_autoclose;
170 static VALUE sym_SET, sym_CUR, sym_END;
171 static VALUE sym_wait_readable, sym_wait_writable;
172 #ifdef SEEK_DATA
173 static VALUE sym_DATA;
174 #endif
175 #ifdef SEEK_HOLE
176 static VALUE sym_HOLE;
177 #endif
178 
179 struct argf {
181  long last_lineno; /* $. */
182  long lineno;
185  struct rb_io_enc_t encs;
187 };
188 
189 static rb_atomic_t max_file_descriptor = NOFILE;
190 void
192 {
193  struct stat buf;
194  rb_atomic_t afd = (rb_atomic_t)fd;
195  rb_atomic_t max_fd = max_file_descriptor;
196 
197  if (afd <= max_fd)
198  return;
199 
200  if (fstat(fd, &buf) != 0 && errno == EBADF) {
201  rb_bug("rb_update_max_fd: invalid fd (%d) given.", fd);
202  }
203 
204  while (max_fd < afd) {
205  max_fd = ATOMIC_CAS(max_file_descriptor, max_fd, afd);
206  }
207 }
208 
209 void
211 {
212  /* MinGW don't have F_GETFD and FD_CLOEXEC. [ruby-core:40281] */
213 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
214  int flags, flags2, ret;
215  flags = fcntl(fd, F_GETFD); /* should not fail except EBADF. */
216  if (flags == -1) {
217  rb_bug("rb_maygvl_fd_fix_cloexec: fcntl(%d, F_GETFD) failed: %s", fd, strerror(errno));
218  }
219  if (fd <= 2)
220  flags2 = flags & ~FD_CLOEXEC; /* Clear CLOEXEC for standard file descriptors: 0, 1, 2. */
221  else
222  flags2 = flags | FD_CLOEXEC; /* Set CLOEXEC for non-standard file descriptors: 3, 4, 5, ... */
223  if (flags != flags2) {
224  ret = fcntl(fd, F_SETFD, flags2);
225  if (ret == -1) {
226  rb_bug("rb_maygvl_fd_fix_cloexec: fcntl(%d, F_SETFD, %d) failed: %s", fd, flags2, strerror(errno));
227  }
228  }
229 #endif
230 }
231 
232 void
234 {
236  rb_update_max_fd(fd);
237 }
238 
239 /* this is only called once */
240 static int
241 rb_fix_detect_o_cloexec(int fd)
242 {
243 #if defined(O_CLOEXEC) && defined(F_GETFD)
244  int flags = fcntl(fd, F_GETFD);
245 
246  if (flags == -1)
247  rb_bug("rb_fix_detect_o_cloexec: fcntl(%d, F_GETFD) failed: %s", fd, strerror(errno));
248 
249  if (flags & FD_CLOEXEC)
250  return 1;
251 #endif /* fall through if O_CLOEXEC does not work: */
253  return 0;
254 }
255 
256 int
257 rb_cloexec_open(const char *pathname, int flags, mode_t mode)
258 {
259  int ret;
260  static int o_cloexec_state = -1; /* <0: unknown, 0: ignored, >0: working */
261 
262 #ifdef O_CLOEXEC
263  /* O_CLOEXEC is available since Linux 2.6.23. Linux 2.6.18 silently ignore it. */
264  flags |= O_CLOEXEC;
265 #elif defined O_NOINHERIT
266  flags |= O_NOINHERIT;
267 #endif
268  ret = open(pathname, flags, mode);
269  if (ret == -1) return -1;
270  if (ret <= 2 || o_cloexec_state == 0) {
272  }
273  else if (o_cloexec_state > 0) {
274  return ret;
275  }
276  else {
277  o_cloexec_state = rb_fix_detect_o_cloexec(ret);
278  }
279  return ret;
280 }
281 
282 int
283 rb_cloexec_dup(int oldfd)
284 {
285  /* Don't allocate standard file descriptors: 0, 1, 2 */
286  return rb_cloexec_fcntl_dupfd(oldfd, 3);
287 }
288 
289 int
290 rb_cloexec_dup2(int oldfd, int newfd)
291 {
292  int ret;
293 
294  /* When oldfd == newfd, dup2 succeeds but dup3 fails with EINVAL.
295  * rb_cloexec_dup2 succeeds as dup2. */
296  if (oldfd == newfd) {
297  ret = newfd;
298  }
299  else {
300 #if defined(HAVE_DUP3) && defined(O_CLOEXEC)
301  static int try_dup3 = 1;
302  if (2 < newfd && try_dup3) {
303  ret = dup3(oldfd, newfd, O_CLOEXEC);
304  if (ret != -1)
305  return ret;
306  /* dup3 is available since Linux 2.6.27, glibc 2.9. */
307  if (errno == ENOSYS) {
308  try_dup3 = 0;
309  ret = dup2(oldfd, newfd);
310  }
311  }
312  else {
313  ret = dup2(oldfd, newfd);
314  }
315 #else
316  ret = dup2(oldfd, newfd);
317 #endif
318  if (ret == -1) return -1;
319  }
321  return ret;
322 }
323 
324 int
325 rb_cloexec_pipe(int fildes[2])
326 {
327  int ret;
328 
329 #if defined(HAVE_PIPE2)
330  static int try_pipe2 = 1;
331  if (try_pipe2) {
332  ret = pipe2(fildes, O_CLOEXEC);
333  if (ret != -1)
334  return ret;
335  /* pipe2 is available since Linux 2.6.27, glibc 2.9. */
336  if (errno == ENOSYS) {
337  try_pipe2 = 0;
338  ret = pipe(fildes);
339  }
340  }
341  else {
342  ret = pipe(fildes);
343  }
344 #else
345  ret = pipe(fildes);
346 #endif
347  if (ret == -1) return -1;
348 #ifdef __CYGWIN__
349  if (ret == 0 && fildes[1] == -1) {
350  close(fildes[0]);
351  fildes[0] = -1;
352  errno = ENFILE;
353  return -1;
354  }
355 #endif
356  rb_maygvl_fd_fix_cloexec(fildes[0]);
357  rb_maygvl_fd_fix_cloexec(fildes[1]);
358  return ret;
359 }
360 
361 int
362 rb_cloexec_fcntl_dupfd(int fd, int minfd)
363 {
364  int ret;
365 
366 #if defined(HAVE_FCNTL) && defined(F_DUPFD_CLOEXEC) && defined(F_DUPFD)
367  static int try_dupfd_cloexec = 1;
368  if (try_dupfd_cloexec) {
369  ret = fcntl(fd, F_DUPFD_CLOEXEC, minfd);
370  if (ret != -1) {
371  if (ret <= 2)
373  return ret;
374  }
375  /* F_DUPFD_CLOEXEC is available since Linux 2.6.24. Linux 2.6.18 fails with EINVAL */
376  if (errno == EINVAL) {
377  ret = fcntl(fd, F_DUPFD, minfd);
378  if (ret != -1) {
379  try_dupfd_cloexec = 0;
380  }
381  }
382  }
383  else {
384  ret = fcntl(fd, F_DUPFD, minfd);
385  }
386 #elif defined(HAVE_FCNTL) && defined(F_DUPFD)
387  ret = fcntl(fd, F_DUPFD, minfd);
388 #elif defined(HAVE_DUP)
389  ret = dup(fd);
390  if (ret != -1 && ret < minfd) {
391  const int prev_fd = ret;
392  ret = rb_cloexec_fcntl_dupfd(fd, minfd);
393  close(prev_fd);
394  }
395  return ret;
396 #else
397 # error "dup() or fcntl(F_DUPFD) must be supported."
398 #endif
399  if (ret == -1) return -1;
401  return ret;
402 }
403 
404 #define argf_of(obj) (*(struct argf *)DATA_PTR(obj))
405 #define ARGF argf_of(argf)
406 
407 #define GetWriteIO(io) rb_io_get_write_io(io)
408 
409 #define READ_DATA_PENDING(fptr) ((fptr)->rbuf.len)
410 #define READ_DATA_PENDING_COUNT(fptr) ((fptr)->rbuf.len)
411 #define READ_DATA_PENDING_PTR(fptr) ((fptr)->rbuf.ptr+(fptr)->rbuf.off)
412 #define READ_DATA_BUFFERED(fptr) READ_DATA_PENDING(fptr)
413 
414 #define READ_CHAR_PENDING(fptr) ((fptr)->cbuf.len)
415 #define READ_CHAR_PENDING_COUNT(fptr) ((fptr)->cbuf.len)
416 #define READ_CHAR_PENDING_PTR(fptr) ((fptr)->cbuf.ptr+(fptr)->cbuf.off)
417 
418 #if defined(_WIN32)
419 #define WAIT_FD_IN_WIN32(fptr) \
420  (rb_w32_io_cancelable_p((fptr)->fd) ? 0 : rb_thread_wait_fd((fptr)->fd))
421 #else
422 #define WAIT_FD_IN_WIN32(fptr)
423 #endif
424 
425 #define READ_CHECK(fptr) do {\
426  if (!READ_DATA_PENDING(fptr)) {\
427  WAIT_FD_IN_WIN32(fptr);\
428  rb_io_check_closed(fptr);\
429  }\
430 } while(0)
431 
432 #ifndef S_ISSOCK
433 # ifdef _S_ISSOCK
434 # define S_ISSOCK(m) _S_ISSOCK(m)
435 # else
436 # ifdef _S_IFSOCK
437 # define S_ISSOCK(m) (((m) & S_IFMT) == _S_IFSOCK)
438 # else
439 # ifdef S_IFSOCK
440 # define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
441 # endif
442 # endif
443 # endif
444 #endif
445 
446 static int io_fflush(rb_io_t *);
447 static rb_io_t *flush_before_seek(rb_io_t *fptr);
448 
449 #define NEED_NEWLINE_DECORATOR_ON_READ(fptr) ((fptr)->mode & FMODE_TEXTMODE)
450 #define NEED_NEWLINE_DECORATOR_ON_WRITE(fptr) ((fptr)->mode & FMODE_TEXTMODE)
451 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
452 /* Windows */
453 # define DEFAULT_TEXTMODE FMODE_TEXTMODE
454 # define TEXTMODE_NEWLINE_DECORATOR_ON_WRITE ECONV_CRLF_NEWLINE_DECORATOR
455 /*
456  * CRLF newline is set as default newline decorator.
457  * If only CRLF newline conversion is needed, we use binary IO process
458  * with OS's text mode for IO performance improvement.
459  * If encoding conversion is needed or a user sets text mode, we use encoding
460  * conversion IO process and universal newline decorator by default.
461  */
462 #define NEED_READCONV(fptr) ((fptr)->encs.enc2 != NULL || (fptr)->encs.ecflags & ~ECONV_CRLF_NEWLINE_DECORATOR)
463 #define NEED_WRITECONV(fptr) (((fptr)->encs.enc != NULL && (fptr)->encs.enc != rb_ascii8bit_encoding()) || ((fptr)->encs.ecflags & ((ECONV_DECORATOR_MASK & ~ECONV_CRLF_NEWLINE_DECORATOR)|ECONV_STATEFUL_DECORATOR_MASK)))
464 #define SET_BINARY_MODE(fptr) setmode((fptr)->fd, O_BINARY)
465 
466 #define NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr) do {\
467  if (NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {\
468  if (((fptr)->mode & FMODE_READABLE) &&\
469  !((fptr)->encs.ecflags & ECONV_NEWLINE_DECORATOR_MASK)) {\
470  setmode((fptr)->fd, O_BINARY);\
471  }\
472  else {\
473  setmode((fptr)->fd, O_TEXT);\
474  }\
475  }\
476 } while(0)
477 
478 #define SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags) do {\
479  if ((enc2) && ((ecflags) & ECONV_DEFAULT_NEWLINE_DECORATOR)) {\
480  (ecflags) |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;\
481  }\
482 } while(0)
483 
484 /*
485  * IO unread with taking care of removed '\r' in text mode.
486  */
487 static void
488 io_unread(rb_io_t *fptr)
489 {
490  off_t r, pos;
491  ssize_t read_size;
492  long i;
493  long newlines = 0;
494  long extra_max;
495  char *p;
496  char *buf;
497 
498  rb_io_check_closed(fptr);
499  if (fptr->rbuf.len == 0 || fptr->mode & FMODE_DUPLEX) {
500  return;
501  }
502 
503  errno = 0;
504  if (!rb_w32_fd_is_text(fptr->fd)) {
505  r = lseek(fptr->fd, -fptr->rbuf.len, SEEK_CUR);
506  if (r < 0 && errno) {
507  if (errno == ESPIPE)
508  fptr->mode |= FMODE_DUPLEX;
509  return;
510  }
511 
512  fptr->rbuf.off = 0;
513  fptr->rbuf.len = 0;
514  return;
515  }
516 
517  pos = lseek(fptr->fd, 0, SEEK_CUR);
518  if (pos < 0 && errno) {
519  if (errno == ESPIPE)
520  fptr->mode |= FMODE_DUPLEX;
521  return;
522  }
523 
524  /* add extra offset for removed '\r' in rbuf */
525  extra_max = (long)(pos - fptr->rbuf.len);
526  p = fptr->rbuf.ptr + fptr->rbuf.off;
527 
528  /* if the end of rbuf is '\r', rbuf doesn't have '\r' within rbuf.len */
529  if (*(fptr->rbuf.ptr + fptr->rbuf.capa - 1) == '\r') {
530  newlines++;
531  }
532 
533  for (i = 0; i < fptr->rbuf.len; i++) {
534  if (*p == '\n') newlines++;
535  if (extra_max == newlines) break;
536  p++;
537  }
538 
539  buf = ALLOC_N(char, fptr->rbuf.len + newlines);
540  while (newlines >= 0) {
541  r = lseek(fptr->fd, pos - fptr->rbuf.len - newlines, SEEK_SET);
542  if (newlines == 0) break;
543  if (r < 0) {
544  newlines--;
545  continue;
546  }
547  read_size = _read(fptr->fd, buf, fptr->rbuf.len + newlines);
548  if (read_size < 0) {
549  int e = errno;
550  free(buf);
551  rb_syserr_fail_path(e, fptr->pathv);
552  }
553  if (read_size == fptr->rbuf.len) {
554  lseek(fptr->fd, r, SEEK_SET);
555  break;
556  }
557  else {
558  newlines--;
559  }
560  }
561  free(buf);
562  fptr->rbuf.off = 0;
563  fptr->rbuf.len = 0;
564  return;
565 }
566 
567 /*
568  * We use io_seek to back cursor position when changing mode from text to binary,
569  * but stdin and pipe cannot seek back. Stdin and pipe read should use encoding
570  * conversion for working properly with mode change.
571  *
572  * Return previous translation mode.
573  */
574 static inline int
575 set_binary_mode_with_seek_cur(rb_io_t *fptr)
576 {
577  if (!rb_w32_fd_is_text(fptr->fd)) return O_BINARY;
578 
579  if (fptr->rbuf.len == 0 || fptr->mode & FMODE_DUPLEX) {
580  return setmode(fptr->fd, O_BINARY);
581  }
582  flush_before_seek(fptr);
583  return setmode(fptr->fd, O_BINARY);
584 }
585 #define SET_BINARY_MODE_WITH_SEEK_CUR(fptr) set_binary_mode_with_seek_cur(fptr)
586 
587 #else
588 /* Unix */
589 # define DEFAULT_TEXTMODE 0
590 #define NEED_READCONV(fptr) ((fptr)->encs.enc2 != NULL || NEED_NEWLINE_DECORATOR_ON_READ(fptr))
591 #define NEED_WRITECONV(fptr) (((fptr)->encs.enc != NULL && (fptr)->encs.enc != rb_ascii8bit_encoding()) || NEED_NEWLINE_DECORATOR_ON_WRITE(fptr) || ((fptr)->encs.ecflags & (ECONV_DECORATOR_MASK|ECONV_STATEFUL_DECORATOR_MASK)))
592 #define SET_BINARY_MODE(fptr) (void)(fptr)
593 #define NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr) (void)(fptr)
594 #define SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags) ((void)(enc2), (void)(ecflags))
595 #define SET_BINARY_MODE_WITH_SEEK_CUR(fptr) (void)(fptr)
596 #endif
597 
598 #if !defined HAVE_SHUTDOWN && !defined shutdown
599 #define shutdown(a,b) 0
600 #endif
601 
602 #if defined(_WIN32)
603 #define is_socket(fd, path) rb_w32_is_socket(fd)
604 #elif !defined(S_ISSOCK)
605 #define is_socket(fd, path) 0
606 #else
607 static int
608 is_socket(int fd, VALUE path)
609 {
610  struct stat sbuf;
611  if (fstat(fd, &sbuf) < 0)
612  rb_sys_fail_path(path);
613  return S_ISSOCK(sbuf.st_mode);
614 }
615 #endif
616 
617 static const char closed_stream[] = "closed stream";
618 
619 void
621 {
622  rb_raise(rb_eEOFError, "end of file reached");
623 }
624 
625 VALUE
627 {
628  rb_check_frozen(io);
629  return io;
630 }
631 
632 void
634 {
635  if (!fptr) {
636  rb_raise(rb_eIOError, "uninitialized stream");
637  }
638 }
639 
640 void
642 {
644  if (fptr->fd < 0) {
645  rb_raise(rb_eIOError, closed_stream);
646  }
647 }
648 
649 static rb_io_t *
650 rb_io_get_fptr(VALUE io)
651 {
652  rb_io_t *fptr = RFILE(io)->fptr;
654  return fptr;
655 }
656 
657 VALUE
659 {
660  return rb_convert_type_with_id(io, T_FILE, "IO", idTo_io);
661 }
662 
663 VALUE
665 {
666  return rb_check_convert_type_with_id(io, T_FILE, "IO", idTo_io);
667 }
668 
669 VALUE
671 {
672  VALUE write_io;
673  write_io = rb_io_get_fptr(io)->tied_io_for_writing;
674  if (write_io) {
675  return write_io;
676  }
677  return io;
678 }
679 
680 VALUE
682 {
683  VALUE write_io;
684  rb_io_t *fptr = rb_io_get_fptr(io);
685  if (!RTEST(w)) {
686  w = 0;
687  }
688  else {
689  GetWriteIO(w);
690  }
691  write_io = fptr->tied_io_for_writing;
692  fptr->tied_io_for_writing = w;
693  return write_io ? write_io : Qnil;
694 }
695 
696 /*
697  * call-seq:
698  * IO.try_convert(obj) -> io or nil
699  *
700  * Try to convert <i>obj</i> into an IO, using to_io method.
701  * Returns converted IO or +nil+ if <i>obj</i> cannot be converted
702  * for any reason.
703  *
704  * IO.try_convert(STDOUT) #=> STDOUT
705  * IO.try_convert("STDOUT") #=> nil
706  *
707  * require 'zlib'
708  * f = open("/tmp/zz.gz") #=> #<File:/tmp/zz.gz>
709  * z = Zlib::GzipReader.open(f) #=> #<Zlib::GzipReader:0x81d8744>
710  * IO.try_convert(z) #=> #<File:/tmp/zz.gz>
711  *
712  */
713 static VALUE
714 rb_io_s_try_convert(VALUE dummy, VALUE io)
715 {
716  return rb_io_check_io(io);
717 }
718 
719 #if !(defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32))
720 static void
721 io_unread(rb_io_t *fptr)
722 {
723  off_t r;
724  rb_io_check_closed(fptr);
725  if (fptr->rbuf.len == 0 || fptr->mode & FMODE_DUPLEX)
726  return;
727  /* xxx: target position may be negative if buffer is filled by ungetc */
728  errno = 0;
729  r = lseek(fptr->fd, -fptr->rbuf.len, SEEK_CUR);
730  if (r < 0 && errno) {
731  if (errno == ESPIPE)
732  fptr->mode |= FMODE_DUPLEX;
733  return;
734  }
735  fptr->rbuf.off = 0;
736  fptr->rbuf.len = 0;
737  return;
738 }
739 #endif
740 
741 static rb_encoding *io_input_encoding(rb_io_t *fptr);
742 
743 static void
744 io_ungetbyte(VALUE str, rb_io_t *fptr)
745 {
746  long len = RSTRING_LEN(str);
747 
748  if (fptr->rbuf.ptr == NULL) {
749  const int min_capa = IO_RBUF_CAPA_FOR(fptr);
750  fptr->rbuf.off = 0;
751  fptr->rbuf.len = 0;
752 #if SIZEOF_LONG > SIZEOF_INT
753  if (len > INT_MAX)
754  rb_raise(rb_eIOError, "ungetbyte failed");
755 #endif
756  if (len > min_capa)
757  fptr->rbuf.capa = (int)len;
758  else
759  fptr->rbuf.capa = min_capa;
760  fptr->rbuf.ptr = ALLOC_N(char, fptr->rbuf.capa);
761  }
762  if (fptr->rbuf.capa < len + fptr->rbuf.len) {
763  rb_raise(rb_eIOError, "ungetbyte failed");
764  }
765  if (fptr->rbuf.off < len) {
766  MEMMOVE(fptr->rbuf.ptr+fptr->rbuf.capa-fptr->rbuf.len,
767  fptr->rbuf.ptr+fptr->rbuf.off,
768  char, fptr->rbuf.len);
769  fptr->rbuf.off = fptr->rbuf.capa-fptr->rbuf.len;
770  }
771  fptr->rbuf.off-=(int)len;
772  fptr->rbuf.len+=(int)len;
773  MEMMOVE(fptr->rbuf.ptr+fptr->rbuf.off, RSTRING_PTR(str), char, len);
774 }
775 
776 static rb_io_t *
777 flush_before_seek(rb_io_t *fptr)
778 {
779  if (io_fflush(fptr) < 0)
780  rb_sys_fail(0);
781  io_unread(fptr);
782  errno = 0;
783  return fptr;
784 }
785 
786 #define io_seek(fptr, ofs, whence) (errno = 0, lseek(flush_before_seek(fptr)->fd, (ofs), (whence)))
787 #define io_tell(fptr) lseek(flush_before_seek(fptr)->fd, 0, SEEK_CUR)
788 
789 #ifndef SEEK_CUR
790 # define SEEK_SET 0
791 # define SEEK_CUR 1
792 # define SEEK_END 2
793 #endif
794 
795 void
797 {
798  rb_io_check_closed(fptr);
799  if (!(fptr->mode & FMODE_READABLE)) {
800  rb_raise(rb_eIOError, "not opened for reading");
801  }
802  if (fptr->wbuf.len) {
803  if (io_fflush(fptr) < 0)
804  rb_sys_fail(0);
805  }
806  if (fptr->tied_io_for_writing) {
807  rb_io_t *wfptr;
808  GetOpenFile(fptr->tied_io_for_writing, wfptr);
809  if (io_fflush(wfptr) < 0)
810  rb_sys_fail(0);
811  }
812 }
813 
814 void
816 {
818  if (READ_CHAR_PENDING(fptr)) {
819  rb_raise(rb_eIOError, "byte oriented read for character buffered IO");
820  }
821 }
822 
823 void
825 {
827 }
828 
829 static rb_encoding*
830 io_read_encoding(rb_io_t *fptr)
831 {
832  if (fptr->encs.enc) {
833  return fptr->encs.enc;
834  }
836 }
837 
838 static rb_encoding*
839 io_input_encoding(rb_io_t *fptr)
840 {
841  if (fptr->encs.enc2) {
842  return fptr->encs.enc2;
843  }
844  return io_read_encoding(fptr);
845 }
846 
847 void
849 {
850  rb_io_check_closed(fptr);
851  if (!(fptr->mode & FMODE_WRITABLE)) {
852  rb_raise(rb_eIOError, "not opened for writing");
853  }
854  if (fptr->rbuf.len) {
855  io_unread(fptr);
856  }
857 }
858 
859 int
861 {
862  /* This function is used for bytes and chars. Confusing. */
863  if (READ_CHAR_PENDING(fptr))
864  return 1; /* should raise? */
865  return READ_DATA_PENDING(fptr);
866 }
867 
868 void
870 {
871  if (!READ_DATA_PENDING(fptr)) {
872  rb_thread_wait_fd(fptr->fd);
873  }
874  return;
875 }
876 
877 int
879 {
880  if (err == EMFILE || err == ENFILE || err == ENOMEM) {
881  rb_gc();
882  return 1;
883  }
884  return 0;
885 }
886 
887 static int
888 ruby_dup(int orig)
889 {
890  int fd;
891 
892  fd = rb_cloexec_dup(orig);
893  if (fd < 0) {
894  int e = errno;
895  if (rb_gc_for_fd(e)) {
896  fd = rb_cloexec_dup(orig);
897  }
898  if (fd < 0) {
899  rb_syserr_fail(e, 0);
900  }
901  }
902  rb_update_max_fd(fd);
903  return fd;
904 }
905 
906 static VALUE
907 io_alloc(VALUE klass)
908 {
909  NEWOBJ_OF(io, struct RFile, klass, T_FILE);
910 
911  io->fptr = 0;
912 
913  return (VALUE)io;
914 }
915 
916 #ifndef S_ISREG
917 # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
918 #endif
919 
921  int fd;
922  void *buf;
923  size_t capa;
924 };
925 
927  int fd;
928  const void *buf;
929  size_t capa;
930 };
931 
932 #ifdef HAVE_WRITEV
933 struct io_internal_writev_struct {
934  int fd;
935  int iovcnt;
936  const struct iovec *iov;
937 };
938 #endif
939 
940 static VALUE
941 internal_read_func(void *ptr)
942 {
943  struct io_internal_read_struct *iis = ptr;
944  return read(iis->fd, iis->buf, iis->capa);
945 }
946 
947 static VALUE
948 internal_write_func(void *ptr)
949 {
950  struct io_internal_write_struct *iis = ptr;
951  return write(iis->fd, iis->buf, iis->capa);
952 }
953 
954 static void*
955 internal_write_func2(void *ptr)
956 {
957  struct io_internal_write_struct *iis = ptr;
958  return (void*)(intptr_t)write(iis->fd, iis->buf, iis->capa);
959 }
960 
961 #ifdef HAVE_WRITEV
962 static VALUE
963 internal_writev_func(void *ptr)
964 {
965  struct io_internal_writev_struct *iis = ptr;
966  return writev(iis->fd, iis->iov, iis->iovcnt);
967 }
968 #endif
969 
970 static ssize_t
971 rb_read_internal(int fd, void *buf, size_t count)
972 {
973  struct io_internal_read_struct iis;
974  iis.fd = fd;
975  iis.buf = buf;
976  iis.capa = count;
977 
978  return (ssize_t)rb_thread_io_blocking_region(internal_read_func, &iis, fd);
979 }
980 
981 static ssize_t
982 rb_write_internal(int fd, const void *buf, size_t count)
983 {
984  struct io_internal_write_struct iis;
985  iis.fd = fd;
986  iis.buf = buf;
987  iis.capa = count;
988 
989  return (ssize_t)rb_thread_io_blocking_region(internal_write_func, &iis, fd);
990 }
991 
992 static ssize_t
993 rb_write_internal2(int fd, const void *buf, size_t count)
994 {
995  struct io_internal_write_struct iis;
996  iis.fd = fd;
997  iis.buf = buf;
998  iis.capa = count;
999 
1000  return (ssize_t)rb_thread_call_without_gvl2(internal_write_func2, &iis,
1001  RUBY_UBF_IO, NULL);
1002 }
1003 
1004 #ifdef HAVE_WRITEV
1005 static ssize_t
1006 rb_writev_internal(int fd, const struct iovec *iov, int iovcnt)
1007 {
1008  struct io_internal_writev_struct iis;
1009  iis.fd = fd;
1010  iis.iov = iov;
1011  iis.iovcnt = iovcnt;
1012 
1013  return (ssize_t)rb_thread_io_blocking_region(internal_writev_func, &iis, fd);
1014 }
1015 #endif
1016 
1017 static VALUE
1018 io_flush_buffer_sync(void *arg)
1019 {
1020  rb_io_t *fptr = arg;
1021  long l = fptr->wbuf.len;
1022  ssize_t r = write(fptr->fd, fptr->wbuf.ptr+fptr->wbuf.off, (size_t)l);
1023 
1024  if (fptr->wbuf.len <= r) {
1025  fptr->wbuf.off = 0;
1026  fptr->wbuf.len = 0;
1027  return 0;
1028  }
1029  if (0 <= r) {
1030  fptr->wbuf.off += (int)r;
1031  fptr->wbuf.len -= (int)r;
1032  errno = EAGAIN;
1033  }
1034  return (VALUE)-1;
1035 }
1036 
1037 static void*
1038 io_flush_buffer_sync2(void *arg)
1039 {
1040  VALUE result = io_flush_buffer_sync(arg);
1041 
1042  /*
1043  * rb_thread_call_without_gvl2 uses 0 as interrupted.
1044  * So, we need to avoid to use 0.
1045  */
1046  return !result ? (void*)1 : (void*)result;
1047 }
1048 
1049 static VALUE
1050 io_flush_buffer_async(VALUE arg)
1051 {
1052  rb_io_t *fptr = (rb_io_t *)arg;
1053  return rb_thread_io_blocking_region(io_flush_buffer_sync, fptr, fptr->fd);
1054 }
1055 
1056 static VALUE
1057 io_flush_buffer_async2(VALUE arg)
1058 {
1059  rb_io_t *fptr = (rb_io_t *)arg;
1060  VALUE ret;
1061 
1062  ret = (VALUE)rb_thread_call_without_gvl2(io_flush_buffer_sync2, fptr,
1063  RUBY_UBF_IO, NULL);
1064 
1065  if (!ret) {
1066  /* pending async interrupt is there. */
1067  errno = EAGAIN;
1068  return -1;
1069  }
1070  else if (ret == 1) {
1071  return 0;
1072  }
1073  return ret;
1074 }
1075 
1076 static inline int
1077 io_flush_buffer(rb_io_t *fptr)
1078 {
1079  if (fptr->write_lock) {
1080  if (rb_mutex_owned_p(fptr->write_lock))
1081  return (int)io_flush_buffer_async2((VALUE)fptr);
1082  else
1083  return (int)rb_mutex_synchronize(fptr->write_lock, io_flush_buffer_async2, (VALUE)fptr);
1084  }
1085  else {
1086  return (int)io_flush_buffer_async((VALUE)fptr);
1087  }
1088 }
1089 
1090 static int
1091 io_fflush(rb_io_t *fptr)
1092 {
1093  rb_io_check_closed(fptr);
1094  if (fptr->wbuf.len == 0)
1095  return 0;
1096  rb_io_check_closed(fptr);
1097  while (fptr->wbuf.len > 0 && io_flush_buffer(fptr) != 0) {
1098  if (!rb_io_wait_writable(fptr->fd))
1099  return -1;
1100  rb_io_check_closed(fptr);
1101  }
1102  return 0;
1103 }
1104 
1105 int
1107 {
1108  if (f < 0) {
1109  rb_raise(rb_eIOError, closed_stream);
1110  }
1111  switch (errno) {
1112  case EINTR:
1113 #if defined(ERESTART)
1114  case ERESTART:
1115 #endif
1117  return TRUE;
1118 
1119  case EAGAIN:
1120 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
1121  case EWOULDBLOCK:
1122 #endif
1123  rb_thread_wait_fd(f);
1124  return TRUE;
1125 
1126  default:
1127  return FALSE;
1128  }
1129 }
1130 
1131 int
1133 {
1134  if (f < 0) {
1135  rb_raise(rb_eIOError, closed_stream);
1136  }
1137  switch (errno) {
1138  case EINTR:
1139 #if defined(ERESTART)
1140  case ERESTART:
1141 #endif
1142  /*
1143  * In old Linux, several special files under /proc and /sys don't handle
1144  * select properly. Thus we need avoid to call if don't use O_NONBLOCK.
1145  * Otherwise, we face nasty hang up. Sigh.
1146  * e.g. http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=31b07093c44a7a442394d44423e21d783f5523b8
1147  * http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=31b07093c44a7a442394d44423e21d783f5523b8
1148  * In EINTR case, we only need to call RUBY_VM_CHECK_INTS_BLOCKING().
1149  * Then rb_thread_check_ints() is enough.
1150  */
1152  return TRUE;
1153 
1154  case EAGAIN:
1155 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
1156  case EWOULDBLOCK:
1157 #endif
1159  return TRUE;
1160 
1161  default:
1162  return FALSE;
1163  }
1164 }
1165 
1166 static void
1167 make_writeconv(rb_io_t *fptr)
1168 {
1169  if (!fptr->writeconv_initialized) {
1170  const char *senc, *denc;
1171  rb_encoding *enc;
1172  int ecflags;
1173  VALUE ecopts;
1174 
1175  fptr->writeconv_initialized = 1;
1176 
1177  ecflags = fptr->encs.ecflags & ~ECONV_NEWLINE_DECORATOR_READ_MASK;
1178  ecopts = fptr->encs.ecopts;
1179 
1180  if (!fptr->encs.enc || (fptr->encs.enc == rb_ascii8bit_encoding() && !fptr->encs.enc2)) {
1181  /* no encoding conversion */
1182  fptr->writeconv_pre_ecflags = 0;
1183  fptr->writeconv_pre_ecopts = Qnil;
1184  fptr->writeconv = rb_econv_open_opts("", "", ecflags, ecopts);
1185  if (!fptr->writeconv)
1186  rb_exc_raise(rb_econv_open_exc("", "", ecflags));
1187  fptr->writeconv_asciicompat = Qnil;
1188  }
1189  else {
1190  enc = fptr->encs.enc2 ? fptr->encs.enc2 : fptr->encs.enc;
1192  if (!senc && !(fptr->encs.ecflags & ECONV_STATEFUL_DECORATOR_MASK)) {
1193  /* single conversion */
1194  fptr->writeconv_pre_ecflags = ecflags;
1195  fptr->writeconv_pre_ecopts = ecopts;
1196  fptr->writeconv = NULL;
1197  fptr->writeconv_asciicompat = Qnil;
1198  }
1199  else {
1200  /* double conversion */
1202  fptr->writeconv_pre_ecopts = ecopts;
1203  if (senc) {
1204  denc = rb_enc_name(enc);
1205  fptr->writeconv_asciicompat = rb_str_new2(senc);
1206  }
1207  else {
1208  senc = denc = "";
1210  }
1212  ecopts = fptr->encs.ecopts;
1213  fptr->writeconv = rb_econv_open_opts(senc, denc, ecflags, ecopts);
1214  if (!fptr->writeconv)
1215  rb_exc_raise(rb_econv_open_exc(senc, denc, ecflags));
1216  }
1217  }
1218  }
1219 }
1220 
1221 /* writing functions */
1225  const char *ptr;
1226  long length;
1227 };
1228 
1229 struct write_arg {
1232  int nosync;
1233 };
1234 
1235 #ifdef HAVE_WRITEV
1236 static VALUE
1237 io_binwrite_string(VALUE arg)
1238 {
1239  struct binwrite_arg *p = (struct binwrite_arg *)arg;
1240  rb_io_t *fptr = p->fptr;
1241  long r;
1242 
1243  if (fptr->wbuf.len) {
1244  struct iovec iov[2];
1245 
1246  iov[0].iov_base = fptr->wbuf.ptr+fptr->wbuf.off;
1247  iov[0].iov_len = fptr->wbuf.len;
1248  iov[1].iov_base = (char *)p->ptr;
1249  iov[1].iov_len = p->length;
1250 
1251  r = rb_writev_internal(fptr->fd, iov, 2);
1252 
1253  if (r == -1)
1254  return -1;
1255 
1256  if (fptr->wbuf.len <= r) {
1257  r -= fptr->wbuf.len;
1258  fptr->wbuf.off = 0;
1259  fptr->wbuf.len = 0;
1260  }
1261  else {
1262  fptr->wbuf.off += (int)r;
1263  fptr->wbuf.len -= (int)r;
1264  r = 0L;
1265  }
1266  }
1267  else {
1268  r = rb_write_internal(fptr->fd, p->ptr, p->length);
1269  }
1270 
1271  return r;
1272 }
1273 #else
1274 static VALUE
1275 io_binwrite_string(VALUE arg)
1276 {
1277  struct binwrite_arg *p = (struct binwrite_arg *)arg;
1278  rb_io_t *fptr = p->fptr;
1279  long l, len;
1280 
1281  l = len = p->length;
1282 
1283  if (fptr->wbuf.len) {
1284  if (fptr->wbuf.len+len <= fptr->wbuf.capa) {
1285  if (fptr->wbuf.capa < fptr->wbuf.off+fptr->wbuf.len+len) {
1286  MEMMOVE(fptr->wbuf.ptr, fptr->wbuf.ptr+fptr->wbuf.off, char, fptr->wbuf.len);
1287  fptr->wbuf.off = 0;
1288  }
1289  MEMMOVE(fptr->wbuf.ptr+fptr->wbuf.off+fptr->wbuf.len, p->ptr, char, len);
1290  fptr->wbuf.len += (int)len;
1291  l = 0;
1292  }
1293  if (io_fflush(fptr) < 0)
1294  return -2L; /* fail in fflush */
1295  if (l == 0)
1296  return len;
1297  }
1298 
1299  if (fptr->stdio_file != stderr && !rb_thread_fd_writable(fptr->fd))
1300  rb_io_check_closed(fptr);
1301 
1302  return rb_write_internal(p->fptr->fd, p->ptr, p->length);
1303 }
1304 #endif
1305 
1306 static long
1307 io_binwrite(VALUE str, const char *ptr, long len, rb_io_t *fptr, int nosync)
1308 {
1309  long n, r, offset = 0;
1310 
1311  /* don't write anything if current thread has a pending interrupt. */
1313 
1314  if ((n = len) <= 0) return n;
1315  if (fptr->wbuf.ptr == NULL && !(!nosync && (fptr->mode & FMODE_SYNC))) {
1316  fptr->wbuf.off = 0;
1317  fptr->wbuf.len = 0;
1318  fptr->wbuf.capa = IO_WBUF_CAPA_MIN;
1319  fptr->wbuf.ptr = ALLOC_N(char, fptr->wbuf.capa);
1320  fptr->write_lock = rb_mutex_new();
1321  rb_mutex_allow_trap(fptr->write_lock, 1);
1322  }
1323  if ((!nosync && (fptr->mode & (FMODE_SYNC|FMODE_TTY))) ||
1324  (fptr->wbuf.ptr && fptr->wbuf.capa <= fptr->wbuf.len + len)) {
1325  struct binwrite_arg arg;
1326 
1327  arg.fptr = fptr;
1328  arg.str = str;
1329  retry:
1330  arg.ptr = ptr + offset;
1331  arg.length = n;
1332  if (fptr->write_lock) {
1333  r = rb_mutex_synchronize(fptr->write_lock, io_binwrite_string, (VALUE)&arg);
1334  }
1335  else {
1336  r = io_binwrite_string((VALUE)&arg);
1337  }
1338  /* xxx: other threads may modify given string. */
1339  if (r == n) return len;
1340  if (0 <= r) {
1341  offset += r;
1342  n -= r;
1343  errno = EAGAIN;
1344  }
1345  if (r == -2L)
1346  return -1L;
1347  if (rb_io_wait_writable(fptr->fd)) {
1348  rb_io_check_closed(fptr);
1349  if (offset < len)
1350  goto retry;
1351  }
1352  return -1L;
1353  }
1354 
1355  if (fptr->wbuf.off) {
1356  if (fptr->wbuf.len)
1357  MEMMOVE(fptr->wbuf.ptr, fptr->wbuf.ptr+fptr->wbuf.off, char, fptr->wbuf.len);
1358  fptr->wbuf.off = 0;
1359  }
1360  MEMMOVE(fptr->wbuf.ptr+fptr->wbuf.off+fptr->wbuf.len, ptr+offset, char, len);
1361  fptr->wbuf.len += (int)len;
1362  return len;
1363 }
1364 
1365 # define MODE_BTMODE(a,b,c) ((fmode & FMODE_BINMODE) ? (b) : \
1366  (fmode & FMODE_TEXTMODE) ? (c) : (a))
1367 static VALUE
1368 do_writeconv(VALUE str, rb_io_t *fptr, int *converted)
1369 {
1370  if (NEED_WRITECONV(fptr)) {
1371  VALUE common_encoding = Qnil;
1372  SET_BINARY_MODE(fptr);
1373 
1374  make_writeconv(fptr);
1375 
1376  if (fptr->writeconv) {
1377 #define fmode (fptr->mode)
1378  if (!NIL_P(fptr->writeconv_asciicompat))
1379  common_encoding = fptr->writeconv_asciicompat;
1380  else if (MODE_BTMODE(DEFAULT_TEXTMODE,0,1) && !rb_enc_asciicompat(rb_enc_get(str))) {
1381  rb_raise(rb_eArgError, "ASCII incompatible string written for text mode IO without encoding conversion: %s",
1382  rb_enc_name(rb_enc_get(str)));
1383  }
1384 #undef fmode
1385  }
1386  else {
1387  if (fptr->encs.enc2)
1388  common_encoding = rb_enc_from_encoding(fptr->encs.enc2);
1389  else if (fptr->encs.enc != rb_ascii8bit_encoding())
1390  common_encoding = rb_enc_from_encoding(fptr->encs.enc);
1391  }
1392 
1393  if (!NIL_P(common_encoding)) {
1394  str = rb_str_encode(str, common_encoding,
1396  *converted = 1;
1397  }
1398 
1399  if (fptr->writeconv) {
1401  *converted = 1;
1402  }
1403  }
1404 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
1405 #define fmode (fptr->mode)
1406  else if (MODE_BTMODE(DEFAULT_TEXTMODE,0,1)) {
1407  if ((fptr->mode & FMODE_READABLE) &&
1409  setmode(fptr->fd, O_BINARY);
1410  }
1411  else {
1412  setmode(fptr->fd, O_TEXT);
1413  }
1414  if (!rb_enc_asciicompat(rb_enc_get(str))) {
1415  rb_raise(rb_eArgError, "ASCII incompatible string written for text mode IO without encoding conversion: %s",
1416  rb_enc_name(rb_enc_get(str)));
1417  }
1418  }
1419 #undef fmode
1420 #endif
1421  return str;
1422 }
1423 
1424 static long
1425 io_fwrite(VALUE str, rb_io_t *fptr, int nosync)
1426 {
1427  int converted = 0;
1428  VALUE tmp;
1429  long n, len;
1430  const char *ptr;
1431 #ifdef _WIN32
1432  if (fptr->mode & FMODE_TTY) {
1433  long len = rb_w32_write_console(str, fptr->fd);
1434  if (len > 0) return len;
1435  }
1436 #endif
1437  str = do_writeconv(str, fptr, &converted);
1438  if (converted)
1439  OBJ_FREEZE(str);
1440 
1442  RSTRING_GETMEM(tmp, ptr, len);
1443  n = io_binwrite(tmp, ptr, len, fptr, nosync);
1445 
1446  return n;
1447 }
1448 
1449 ssize_t
1450 rb_io_bufwrite(VALUE io, const void *buf, size_t size)
1451 {
1452  rb_io_t *fptr;
1453 
1454  GetOpenFile(io, fptr);
1455  rb_io_check_writable(fptr);
1456  return (ssize_t)io_binwrite(0, buf, (long)size, fptr, 0);
1457 }
1458 
1459 static VALUE
1460 io_write(VALUE io, VALUE str, int nosync)
1461 {
1462  rb_io_t *fptr;
1463  long n;
1464  VALUE tmp;
1465 
1466  io = GetWriteIO(io);
1468  tmp = rb_io_check_io(io);
1469  if (NIL_P(tmp)) {
1470  /* port is not IO, call write method for it. */
1471  return rb_funcall(io, id_write, 1, str);
1472  }
1473  io = tmp;
1474  if (RSTRING_LEN(str) == 0) return INT2FIX(0);
1475 
1476  GetOpenFile(io, fptr);
1477  rb_io_check_writable(fptr);
1478 
1479  n = io_fwrite(str, fptr, nosync);
1480  if (n == -1L) rb_sys_fail_path(fptr->pathv);
1481 
1482  return LONG2FIX(n);
1483 }
1484 
1485 /*
1486  * call-seq:
1487  * ios.write(string) -> integer
1488  *
1489  * Writes the given string to <em>ios</em>. The stream must be opened
1490  * for writing. If the argument is not a string, it will be converted
1491  * to a string using <code>to_s</code>. Returns the number of bytes
1492  * written.
1493  *
1494  * count = $stdout.write("This is a test\n")
1495  * puts "That was #{count} bytes of data"
1496  *
1497  * <em>produces:</em>
1498  *
1499  * This is a test
1500  * That was 15 bytes of data
1501  */
1502 
1503 static VALUE
1504 io_write_m(VALUE io, VALUE str)
1505 {
1506  return io_write(io, str, 0);
1507 }
1508 
1509 VALUE
1511 {
1512  return rb_funcallv(io, id_write, 1, &str);
1513 }
1514 
1515 /*
1516  * call-seq:
1517  * ios << obj -> ios
1518  *
1519  * String Output---Writes <i>obj</i> to <em>ios</em>.
1520  * <i>obj</i> will be converted to a string using
1521  * <code>to_s</code>.
1522  *
1523  * $stdout << "Hello " << "world!\n"
1524  *
1525  * <em>produces:</em>
1526  *
1527  * Hello world!
1528  */
1529 
1530 
1531 VALUE
1533 {
1534  rb_io_write(io, str);
1535  return io;
1536 }
1537 
1538 #ifdef HAVE_FSYNC
1539 static VALUE
1540 nogvl_fsync(void *ptr)
1541 {
1542  rb_io_t *fptr = ptr;
1543 
1544 #ifdef _WIN32
1545  if (GetFileType((HANDLE)rb_w32_get_osfhandle(fptr->fd)) != FILE_TYPE_DISK)
1546  return 0;
1547 #endif
1548  return (VALUE)fsync(fptr->fd);
1549 }
1550 #endif
1551 
1552 VALUE
1553 rb_io_flush_raw(VALUE io, int sync)
1554 {
1555  rb_io_t *fptr;
1556 
1557  if (!RB_TYPE_P(io, T_FILE)) {
1558  return rb_funcall(io, id_flush, 0);
1559  }
1560 
1561  io = GetWriteIO(io);
1562  GetOpenFile(io, fptr);
1563 
1564  if (fptr->mode & FMODE_WRITABLE) {
1565  if (io_fflush(fptr) < 0)
1566  rb_sys_fail(0);
1567  }
1568  if (fptr->mode & FMODE_READABLE) {
1569  io_unread(fptr);
1570  }
1571 
1572  return io;
1573 }
1574 
1575 /*
1576  * call-seq:
1577  * ios.flush -> ios
1578  *
1579  * Flushes any buffered data within <em>ios</em> to the underlying
1580  * operating system (note that this is Ruby internal buffering only;
1581  * the OS may buffer the data as well).
1582  *
1583  * $stdout.print "no newline"
1584  * $stdout.flush
1585  *
1586  * <em>produces:</em>
1587  *
1588  * no newline
1589  */
1590 
1591 VALUE
1593 {
1594  return rb_io_flush_raw(io, 1);
1595 }
1596 
1597 /*
1598  * call-seq:
1599  * ios.pos -> integer
1600  * ios.tell -> integer
1601  *
1602  * Returns the current offset (in bytes) of <em>ios</em>.
1603  *
1604  * f = File.new("testfile")
1605  * f.pos #=> 0
1606  * f.gets #=> "This is line one\n"
1607  * f.pos #=> 17
1608  */
1609 
1610 static VALUE
1611 rb_io_tell(VALUE io)
1612 {
1613  rb_io_t *fptr;
1614  off_t pos;
1615 
1616  GetOpenFile(io, fptr);
1617  pos = io_tell(fptr);
1618  if (pos < 0 && errno) rb_sys_fail_path(fptr->pathv);
1619  pos -= fptr->rbuf.len;
1620  return OFFT2NUM(pos);
1621 }
1622 
1623 static VALUE
1624 rb_io_seek(VALUE io, VALUE offset, int whence)
1625 {
1626  rb_io_t *fptr;
1627  off_t pos;
1628 
1629  pos = NUM2OFFT(offset);
1630  GetOpenFile(io, fptr);
1631  pos = io_seek(fptr, pos, whence);
1632  if (pos < 0 && errno) rb_sys_fail_path(fptr->pathv);
1633 
1634  return INT2FIX(0);
1635 }
1636 
1637 static int
1638 interpret_seek_whence(VALUE vwhence)
1639 {
1640  if (vwhence == sym_SET)
1641  return SEEK_SET;
1642  if (vwhence == sym_CUR)
1643  return SEEK_CUR;
1644  if (vwhence == sym_END)
1645  return SEEK_END;
1646 #ifdef SEEK_DATA
1647  if (vwhence == sym_DATA)
1648  return SEEK_DATA;
1649 #endif
1650 #ifdef SEEK_HOLE
1651  if (vwhence == sym_HOLE)
1652  return SEEK_HOLE;
1653 #endif
1654  return NUM2INT(vwhence);
1655 }
1656 
1657 /*
1658  * call-seq:
1659  * ios.seek(amount, whence=IO::SEEK_SET) -> 0
1660  *
1661  * Seeks to a given offset <i>anInteger</i> in the stream according to
1662  * the value of <i>whence</i>:
1663  *
1664  * :CUR or IO::SEEK_CUR | Seeks to _amount_ plus current position
1665  * ----------------------+--------------------------------------------------
1666  * :END or IO::SEEK_END | Seeks to _amount_ plus end of stream (you
1667  * | probably want a negative value for _amount_)
1668  * ----------------------+--------------------------------------------------
1669  * :SET or IO::SEEK_SET | Seeks to the absolute location given by _amount_
1670  *
1671  * Example:
1672  *
1673  * f = File.new("testfile")
1674  * f.seek(-13, IO::SEEK_END) #=> 0
1675  * f.readline #=> "And so on...\n"
1676  */
1677 
1678 static VALUE
1679 rb_io_seek_m(int argc, VALUE *argv, VALUE io)
1680 {
1681  VALUE offset, ptrname;
1682  int whence = SEEK_SET;
1683 
1684  if (rb_scan_args(argc, argv, "11", &offset, &ptrname) == 2) {
1685  whence = interpret_seek_whence(ptrname);
1686  }
1687 
1688  return rb_io_seek(io, offset, whence);
1689 }
1690 
1691 /*
1692  * call-seq:
1693  * ios.pos = integer -> integer
1694  *
1695  * Seeks to the given position (in bytes) in <em>ios</em>.
1696  * It is not guaranteed that seeking to the right position when <em>ios</em>
1697  * is textmode.
1698  *
1699  * f = File.new("testfile")
1700  * f.pos = 17
1701  * f.gets #=> "This is line two\n"
1702  */
1703 
1704 static VALUE
1705 rb_io_set_pos(VALUE io, VALUE offset)
1706 {
1707  rb_io_t *fptr;
1708  off_t pos;
1709 
1710  pos = NUM2OFFT(offset);
1711  GetOpenFile(io, fptr);
1712  pos = io_seek(fptr, pos, SEEK_SET);
1713  if (pos < 0 && errno) rb_sys_fail_path(fptr->pathv);
1714 
1715  return OFFT2NUM(pos);
1716 }
1717 
1718 static void clear_readconv(rb_io_t *fptr);
1719 
1720 /*
1721  * call-seq:
1722  * ios.rewind -> 0
1723  *
1724  * Positions <em>ios</em> to the beginning of input, resetting
1725  * <code>lineno</code> to zero.
1726  *
1727  * f = File.new("testfile")
1728  * f.readline #=> "This is line one\n"
1729  * f.rewind #=> 0
1730  * f.lineno #=> 0
1731  * f.readline #=> "This is line one\n"
1732  *
1733  * Note that it cannot be used with streams such as pipes, ttys, and sockets.
1734  */
1735 
1736 static VALUE
1737 rb_io_rewind(VALUE io)
1738 {
1739  rb_io_t *fptr;
1740 
1741  GetOpenFile(io, fptr);
1742  if (io_seek(fptr, 0L, 0) < 0 && errno) rb_sys_fail_path(fptr->pathv);
1743  if (io == ARGF.current_file) {
1744  ARGF.lineno -= fptr->lineno;
1745  }
1746  fptr->lineno = 0;
1747  if (fptr->readconv) {
1748  clear_readconv(fptr);
1749  }
1750 
1751  return INT2FIX(0);
1752 }
1753 
1754 static int
1755 io_fillbuf(rb_io_t *fptr)
1756 {
1757  ssize_t r;
1758 
1759  if (fptr->rbuf.ptr == NULL) {
1760  fptr->rbuf.off = 0;
1761  fptr->rbuf.len = 0;
1762  fptr->rbuf.capa = IO_RBUF_CAPA_FOR(fptr);
1763  fptr->rbuf.ptr = ALLOC_N(char, fptr->rbuf.capa);
1764 #ifdef _WIN32
1765  fptr->rbuf.capa--;
1766 #endif
1767  }
1768  if (fptr->rbuf.len == 0) {
1769  retry:
1770  {
1771  r = rb_read_internal(fptr->fd, fptr->rbuf.ptr, fptr->rbuf.capa);
1772  }
1773  if (r < 0) {
1774  if (rb_io_wait_readable(fptr->fd))
1775  goto retry;
1776  {
1777  int e = errno;
1778  VALUE path = rb_sprintf("fd:%d ", fptr->fd);
1779  if (!NIL_P(fptr->pathv)) {
1780  rb_str_append(path, fptr->pathv);
1781  }
1782  rb_syserr_fail_path(e, path);
1783  }
1784  }
1785  if (r > 0) rb_io_check_closed(fptr);
1786  fptr->rbuf.off = 0;
1787  fptr->rbuf.len = (int)r; /* r should be <= rbuf_capa */
1788  if (r == 0)
1789  return -1; /* EOF */
1790  }
1791  return 0;
1792 }
1793 
1794 /*
1795  * call-seq:
1796  * ios.eof -> true or false
1797  * ios.eof? -> true or false
1798  *
1799  * Returns true if <em>ios</em> is at end of file that means
1800  * there are no more data to read.
1801  * The stream must be opened for reading or an <code>IOError</code> will be
1802  * raised.
1803  *
1804  * f = File.new("testfile")
1805  * dummy = f.readlines
1806  * f.eof #=> true
1807  *
1808  * If <em>ios</em> is a stream such as pipe or socket, <code>IO#eof?</code>
1809  * blocks until the other end sends some data or closes it.
1810  *
1811  * r, w = IO.pipe
1812  * Thread.new { sleep 1; w.close }
1813  * r.eof? #=> true after 1 second blocking
1814  *
1815  * r, w = IO.pipe
1816  * Thread.new { sleep 1; w.puts "a" }
1817  * r.eof? #=> false after 1 second blocking
1818  *
1819  * r, w = IO.pipe
1820  * r.eof? # blocks forever
1821  *
1822  * Note that <code>IO#eof?</code> reads data to the input byte buffer.
1823  * So <code>IO#sysread</code> may not behave as you intend with
1824  * <code>IO#eof?</code>, unless you call <code>IO#rewind</code>
1825  * first (which is not available for some streams).
1826  */
1827 
1828 VALUE
1830 {
1831  rb_io_t *fptr;
1832 
1833  GetOpenFile(io, fptr);
1835 
1836  if (READ_CHAR_PENDING(fptr)) return Qfalse;
1837  if (READ_DATA_PENDING(fptr)) return Qfalse;
1838  READ_CHECK(fptr);
1839 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
1840  if (!NEED_READCONV(fptr) && NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {
1841  return eof(fptr->fd) ? Qtrue : Qfalse;
1842  }
1843 #endif
1844  if (io_fillbuf(fptr) < 0) {
1845  return Qtrue;
1846  }
1847  return Qfalse;
1848 }
1849 
1850 /*
1851  * call-seq:
1852  * ios.sync -> true or false
1853  *
1854  * Returns the current ``sync mode'' of <em>ios</em>. When sync mode is
1855  * true, all output is immediately flushed to the underlying operating
1856  * system and is not buffered by Ruby internally. See also
1857  * <code>IO#fsync</code>.
1858  *
1859  * f = File.new("testfile")
1860  * f.sync #=> false
1861  */
1862 
1863 static VALUE
1864 rb_io_sync(VALUE io)
1865 {
1866  rb_io_t *fptr;
1867 
1868  io = GetWriteIO(io);
1869  GetOpenFile(io, fptr);
1870  return (fptr->mode & FMODE_SYNC) ? Qtrue : Qfalse;
1871 }
1872 
1873 #ifdef HAVE_FSYNC
1874 
1875 /*
1876  * call-seq:
1877  * ios.sync = boolean -> boolean
1878  *
1879  * Sets the ``sync mode'' to <code>true</code> or <code>false</code>.
1880  * When sync mode is true, all output is immediately flushed to the
1881  * underlying operating system and is not buffered internally. Returns
1882  * the new state. See also <code>IO#fsync</code>.
1883  *
1884  * f = File.new("testfile")
1885  * f.sync = true
1886  */
1887 
1888 static VALUE
1889 rb_io_set_sync(VALUE io, VALUE sync)
1890 {
1891  rb_io_t *fptr;
1892 
1893  io = GetWriteIO(io);
1894  GetOpenFile(io, fptr);
1895  if (RTEST(sync)) {
1896  fptr->mode |= FMODE_SYNC;
1897  }
1898  else {
1899  fptr->mode &= ~FMODE_SYNC;
1900  }
1901  return sync;
1902 }
1903 
1904 /*
1905  * call-seq:
1906  * ios.fsync -> 0 or nil
1907  *
1908  * Immediately writes all buffered data in <em>ios</em> to disk.
1909  * Note that <code>fsync</code> differs from
1910  * using <code>IO#sync=</code>. The latter ensures that data is flushed
1911  * from Ruby's buffers, but does not guarantee that the underlying
1912  * operating system actually writes it to disk.
1913  *
1914  * <code>NotImplementedError</code> is raised
1915  * if the underlying operating system does not support <em>fsync(2)</em>.
1916  */
1917 
1918 static VALUE
1919 rb_io_fsync(VALUE io)
1920 {
1921  rb_io_t *fptr;
1922 
1923  io = GetWriteIO(io);
1924  GetOpenFile(io, fptr);
1925 
1926  if (io_fflush(fptr) < 0)
1927  rb_sys_fail(0);
1928  if ((int)rb_thread_io_blocking_region(nogvl_fsync, fptr, fptr->fd) < 0)
1929  rb_sys_fail_path(fptr->pathv);
1930  return INT2FIX(0);
1931 }
1932 #else
1933 # define rb_io_fsync rb_f_notimplement
1934 # define rb_io_sync rb_f_notimplement
1935 static VALUE
1936 rb_io_set_sync(VALUE io, VALUE sync)
1937 {
1938  rb_notimplement();
1939  UNREACHABLE;
1940 }
1941 #endif
1942 
1943 #ifdef HAVE_FDATASYNC
1944 static VALUE
1945 nogvl_fdatasync(void *ptr)
1946 {
1947  rb_io_t *fptr = ptr;
1948 
1949 #ifdef _WIN32
1950  if (GetFileType((HANDLE)rb_w32_get_osfhandle(fptr->fd)) != FILE_TYPE_DISK)
1951  return 0;
1952 #endif
1953  return (VALUE)fdatasync(fptr->fd);
1954 }
1955 
1956 /*
1957  * call-seq:
1958  * ios.fdatasync -> 0 or nil
1959  *
1960  * Immediately writes all buffered data in <em>ios</em> to disk.
1961  *
1962  * If the underlying operating system does not support <em>fdatasync(2)</em>,
1963  * <code>IO#fsync</code> is called instead (which might raise a
1964  * <code>NotImplementedError</code>).
1965  */
1966 
1967 static VALUE
1969 {
1970  rb_io_t *fptr;
1971 
1972  io = GetWriteIO(io);
1973  GetOpenFile(io, fptr);
1974 
1975  if (io_fflush(fptr) < 0)
1976  rb_sys_fail(0);
1977 
1978  if ((int)rb_thread_io_blocking_region(nogvl_fdatasync, fptr, fptr->fd) == 0)
1979  return INT2FIX(0);
1980 
1981  /* fall back */
1982  return rb_io_fsync(io);
1983 }
1984 #else
1985 #define rb_io_fdatasync rb_io_fsync
1986 #endif
1987 
1988 /*
1989  * call-seq:
1990  * ios.fileno -> integer
1991  * ios.to_i -> integer
1992  *
1993  * Returns an integer representing the numeric file descriptor for
1994  * <em>ios</em>.
1995  *
1996  * $stdin.fileno #=> 0
1997  * $stdout.fileno #=> 1
1998  */
1999 
2000 static VALUE
2001 rb_io_fileno(VALUE io)
2002 {
2003  rb_io_t *fptr = RFILE(io)->fptr;
2004  int fd;
2005 
2006  rb_io_check_closed(fptr);
2007  fd = fptr->fd;
2008  return INT2FIX(fd);
2009 }
2010 
2011 
2012 /*
2013  * call-seq:
2014  * ios.pid -> integer
2015  *
2016  * Returns the process ID of a child process associated with
2017  * <em>ios</em>. This will be set by <code>IO.popen</code>.
2018  *
2019  * pipe = IO.popen("-")
2020  * if pipe
2021  * $stderr.puts "In parent, child pid is #{pipe.pid}"
2022  * else
2023  * $stderr.puts "In child, pid is #{$$}"
2024  * end
2025  *
2026  * <em>produces:</em>
2027  *
2028  * In child, pid is 26209
2029  * In parent, child pid is 26209
2030  */
2031 
2032 static VALUE
2033 rb_io_pid(VALUE io)
2034 {
2035  rb_io_t *fptr;
2036 
2037  GetOpenFile(io, fptr);
2038  if (!fptr->pid)
2039  return Qnil;
2040  return PIDT2NUM(fptr->pid);
2041 }
2042 
2043 
2044 /*
2045  * call-seq:
2046  * ios.inspect -> string
2047  *
2048  * Return a string describing this IO object.
2049  */
2050 
2051 static VALUE
2052 rb_io_inspect(VALUE obj)
2053 {
2054  rb_io_t *fptr;
2055  VALUE result;
2056  static const char closed[] = " (closed)";
2057 
2058  fptr = RFILE(obj)->fptr;
2059  if (!fptr) return rb_any_to_s(obj);
2060  result = rb_str_new_cstr("#<");
2061  rb_str_append(result, rb_class_name(CLASS_OF(obj)));
2062  rb_str_cat2(result, ":");
2063  if (NIL_P(fptr->pathv)) {
2064  if (fptr->fd < 0) {
2065  rb_str_cat(result, closed+1, strlen(closed)-1);
2066  }
2067  else {
2068  rb_str_catf(result, "fd %d", fptr->fd);
2069  }
2070  }
2071  else {
2072  rb_str_append(result, fptr->pathv);
2073  if (fptr->fd < 0) {
2074  rb_str_cat(result, closed, strlen(closed));
2075  }
2076  }
2077  return rb_str_cat2(result, ">");
2078 }
2079 
2080 /*
2081  * call-seq:
2082  * ios.to_io -> ios
2083  *
2084  * Returns <em>ios</em>.
2085  */
2086 
2087 static VALUE
2088 rb_io_to_io(VALUE io)
2089 {
2090  return io;
2091 }
2092 
2093 /* reading functions */
2094 static long
2095 read_buffered_data(char *ptr, long len, rb_io_t *fptr)
2096 {
2097  int n;
2098 
2099  n = READ_DATA_PENDING_COUNT(fptr);
2100  if (n <= 0) return 0;
2101  if (n > len) n = (int)len;
2102  MEMMOVE(ptr, fptr->rbuf.ptr+fptr->rbuf.off, char, n);
2103  fptr->rbuf.off += n;
2104  fptr->rbuf.len -= n;
2105  return n;
2106 }
2107 
2108 static long
2109 io_bufread(char *ptr, long len, rb_io_t *fptr)
2110 {
2111  long offset = 0;
2112  long n = len;
2113  long c;
2114 
2115  if (READ_DATA_PENDING(fptr) == 0) {
2116  while (n > 0) {
2117  again:
2118  c = rb_read_internal(fptr->fd, ptr+offset, n);
2119  if (c == 0) break;
2120  if (c < 0) {
2121  if (rb_io_wait_readable(fptr->fd))
2122  goto again;
2123  return -1;
2124  }
2125  offset += c;
2126  if ((n -= c) <= 0) break;
2127  }
2128  return len - n;
2129  }
2130 
2131  while (n > 0) {
2132  c = read_buffered_data(ptr+offset, n, fptr);
2133  if (c > 0) {
2134  offset += c;
2135  if ((n -= c) <= 0) break;
2136  }
2137  rb_io_check_closed(fptr);
2138  if (io_fillbuf(fptr) < 0) {
2139  break;
2140  }
2141  }
2142  return len - n;
2143 }
2144 
2145 static int io_setstrbuf(VALUE *str, long len);
2146 
2147 struct bufread_arg {
2148  char *str_ptr;
2149  long len;
2151 };
2152 
2153 static VALUE
2154 bufread_call(VALUE arg)
2155 {
2156  struct bufread_arg *p = (struct bufread_arg *)arg;
2157  p->len = io_bufread(p->str_ptr, p->len, p->fptr);
2158  return Qundef;
2159 }
2160 
2161 static long
2162 io_fread(VALUE str, long offset, long size, rb_io_t *fptr)
2163 {
2164  long len;
2165  struct bufread_arg arg;
2166 
2167  io_setstrbuf(&str, offset + size);
2168  arg.str_ptr = RSTRING_PTR(str) + offset;
2169  arg.len = size;
2170  arg.fptr = fptr;
2171  rb_str_locktmp_ensure(str, bufread_call, (VALUE)&arg);
2172  len = arg.len;
2173  if (len < 0) rb_sys_fail_path(fptr->pathv);
2174  return len;
2175 }
2176 
2177 ssize_t
2178 rb_io_bufread(VALUE io, void *buf, size_t size)
2179 {
2180  rb_io_t *fptr;
2181 
2182  GetOpenFile(io, fptr);
2183  rb_io_check_readable(fptr);
2184  return (ssize_t)io_bufread(buf, (long)size, fptr);
2185 }
2186 
2187 static long
2188 remain_size(rb_io_t *fptr)
2189 {
2190  struct stat st;
2191  off_t siz = READ_DATA_PENDING_COUNT(fptr);
2192  off_t pos;
2193 
2194  if (fstat(fptr->fd, &st) == 0 && S_ISREG(st.st_mode)
2195 #if defined(__HAIKU__)
2196  && (st.st_dev > 3)
2197 #endif
2198  )
2199  {
2200  if (io_fflush(fptr) < 0)
2201  rb_sys_fail(0);
2202  pos = lseek(fptr->fd, 0, SEEK_CUR);
2203  if (st.st_size >= pos && pos >= 0) {
2204  siz += st.st_size - pos;
2205  if (siz > LONG_MAX) {
2206  rb_raise(rb_eIOError, "file too big for single read");
2207  }
2208  }
2209  }
2210  else {
2211  siz += BUFSIZ;
2212  }
2213  return (long)siz;
2214 }
2215 
2216 static VALUE
2217 io_enc_str(VALUE str, rb_io_t *fptr)
2218 {
2219  OBJ_TAINT(str);
2220  rb_enc_associate(str, io_read_encoding(fptr));
2221  return str;
2222 }
2223 
2224 static void
2225 make_readconv(rb_io_t *fptr, int size)
2226 {
2227  if (!fptr->readconv) {
2228  int ecflags;
2229  VALUE ecopts;
2230  const char *sname, *dname;
2231  ecflags = fptr->encs.ecflags & ~ECONV_NEWLINE_DECORATOR_WRITE_MASK;
2232  ecopts = fptr->encs.ecopts;
2233  if (fptr->encs.enc2) {
2234  sname = rb_enc_name(fptr->encs.enc2);
2235  dname = rb_enc_name(fptr->encs.enc);
2236  }
2237  else {
2238  sname = dname = "";
2239  }
2240  fptr->readconv = rb_econv_open_opts(sname, dname, ecflags, ecopts);
2241  if (!fptr->readconv)
2242  rb_exc_raise(rb_econv_open_exc(sname, dname, ecflags));
2243  fptr->cbuf.off = 0;
2244  fptr->cbuf.len = 0;
2245  if (size < IO_CBUF_CAPA_MIN) size = IO_CBUF_CAPA_MIN;
2246  fptr->cbuf.capa = size;
2247  fptr->cbuf.ptr = ALLOC_N(char, fptr->cbuf.capa);
2248  }
2249 }
2250 
2251 #define MORE_CHAR_SUSPENDED Qtrue
2252 #define MORE_CHAR_FINISHED Qnil
2253 static VALUE
2254 fill_cbuf(rb_io_t *fptr, int ec_flags)
2255 {
2256  const unsigned char *ss, *sp, *se;
2257  unsigned char *ds, *dp, *de;
2258  rb_econv_result_t res;
2259  int putbackable;
2260  int cbuf_len0;
2261  VALUE exc;
2262 
2263  ec_flags |= ECONV_PARTIAL_INPUT;
2264 
2265  if (fptr->cbuf.len == fptr->cbuf.capa)
2266  return MORE_CHAR_SUSPENDED; /* cbuf full */
2267  if (fptr->cbuf.len == 0)
2268  fptr->cbuf.off = 0;
2269  else if (fptr->cbuf.off + fptr->cbuf.len == fptr->cbuf.capa) {
2270  memmove(fptr->cbuf.ptr, fptr->cbuf.ptr+fptr->cbuf.off, fptr->cbuf.len);
2271  fptr->cbuf.off = 0;
2272  }
2273 
2274  cbuf_len0 = fptr->cbuf.len;
2275 
2276  while (1) {
2277  ss = sp = (const unsigned char *)fptr->rbuf.ptr + fptr->rbuf.off;
2278  se = sp + fptr->rbuf.len;
2279  ds = dp = (unsigned char *)fptr->cbuf.ptr + fptr->cbuf.off + fptr->cbuf.len;
2280  de = (unsigned char *)fptr->cbuf.ptr + fptr->cbuf.capa;
2281  res = rb_econv_convert(fptr->readconv, &sp, se, &dp, de, ec_flags);
2282  fptr->rbuf.off += (int)(sp - ss);
2283  fptr->rbuf.len -= (int)(sp - ss);
2284  fptr->cbuf.len += (int)(dp - ds);
2285 
2286  putbackable = rb_econv_putbackable(fptr->readconv);
2287  if (putbackable) {
2288  rb_econv_putback(fptr->readconv, (unsigned char *)fptr->rbuf.ptr + fptr->rbuf.off - putbackable, putbackable);
2289  fptr->rbuf.off -= putbackable;
2290  fptr->rbuf.len += putbackable;
2291  }
2292 
2293  exc = rb_econv_make_exception(fptr->readconv);
2294  if (!NIL_P(exc))
2295  return exc;
2296 
2297  if (cbuf_len0 != fptr->cbuf.len)
2298  return MORE_CHAR_SUSPENDED;
2299 
2300  if (res == econv_finished) {
2301  return MORE_CHAR_FINISHED;
2302  }
2303 
2304  if (res == econv_source_buffer_empty) {
2305  if (fptr->rbuf.len == 0) {
2306  READ_CHECK(fptr);
2307  if (io_fillbuf(fptr) == -1) {
2308  if (!fptr->readconv) {
2309  return MORE_CHAR_FINISHED;
2310  }
2311  ds = dp = (unsigned char *)fptr->cbuf.ptr + fptr->cbuf.off + fptr->cbuf.len;
2312  de = (unsigned char *)fptr->cbuf.ptr + fptr->cbuf.capa;
2313  res = rb_econv_convert(fptr->readconv, NULL, NULL, &dp, de, 0);
2314  fptr->cbuf.len += (int)(dp - ds);
2316  break;
2317  }
2318  }
2319  }
2320  }
2321  if (cbuf_len0 != fptr->cbuf.len)
2322  return MORE_CHAR_SUSPENDED;
2323 
2324  return MORE_CHAR_FINISHED;
2325 }
2326 
2327 static VALUE
2328 more_char(rb_io_t *fptr)
2329 {
2330  VALUE v;
2331  v = fill_cbuf(fptr, ECONV_AFTER_OUTPUT);
2332  if (v != MORE_CHAR_SUSPENDED && v != MORE_CHAR_FINISHED)
2333  rb_exc_raise(v);
2334  return v;
2335 }
2336 
2337 static VALUE
2338 io_shift_cbuf(rb_io_t *fptr, int len, VALUE *strp)
2339 {
2340  VALUE str = Qnil;
2341  if (strp) {
2342  str = *strp;
2343  if (NIL_P(str)) {
2344  *strp = str = rb_str_new(fptr->cbuf.ptr+fptr->cbuf.off, len);
2345  }
2346  else {
2347  rb_str_cat(str, fptr->cbuf.ptr+fptr->cbuf.off, len);
2348  }
2349  OBJ_TAINT(str);
2350  rb_enc_associate(str, fptr->encs.enc);
2351  }
2352  fptr->cbuf.off += len;
2353  fptr->cbuf.len -= len;
2354  /* xxx: set coderange */
2355  if (fptr->cbuf.len == 0)
2356  fptr->cbuf.off = 0;
2357  else if (fptr->cbuf.capa/2 < fptr->cbuf.off) {
2358  memmove(fptr->cbuf.ptr, fptr->cbuf.ptr+fptr->cbuf.off, fptr->cbuf.len);
2359  fptr->cbuf.off = 0;
2360  }
2361  return str;
2362 }
2363 
2364 static int
2365 io_setstrbuf(VALUE *str, long len)
2366 {
2367 #ifdef _WIN32
2368  len = (len + 1) & ~1L; /* round up for wide char */
2369 #endif
2370  if (NIL_P(*str)) {
2371  *str = rb_str_new(0, len);
2372  return TRUE;
2373  }
2374  else {
2375  VALUE s = StringValue(*str);
2376  long clen = RSTRING_LEN(s);
2377  if (clen >= len) {
2378  rb_str_modify(s);
2379  return FALSE;
2380  }
2381  len -= clen;
2382  }
2383  rb_str_modify_expand(*str, len);
2384  return FALSE;
2385 }
2386 
2387 #define MAX_REALLOC_GAP 4096
2388 static void
2389 io_shrink_read_string(VALUE str, long n)
2390 {
2391  if (rb_str_capacity(str) - n > MAX_REALLOC_GAP) {
2392  rb_str_resize(str, n);
2393  }
2394 }
2395 
2396 static void
2397 io_set_read_length(VALUE str, long n, int shrinkable)
2398 {
2399  if (RSTRING_LEN(str) != n) {
2400  rb_str_modify(str);
2401  rb_str_set_len(str, n);
2402  if (shrinkable) io_shrink_read_string(str, n);
2403  }
2404 }
2405 
2406 static VALUE
2407 read_all(rb_io_t *fptr, long siz, VALUE str)
2408 {
2409  long bytes;
2410  long n;
2411  long pos;
2412  rb_encoding *enc;
2413  int cr;
2414  int shrinkable;
2415 
2416  if (NEED_READCONV(fptr)) {
2417  int first = !NIL_P(str);
2418  SET_BINARY_MODE(fptr);
2419  shrinkable = io_setstrbuf(&str,0);
2420  make_readconv(fptr, 0);
2421  while (1) {
2422  VALUE v;
2423  if (fptr->cbuf.len) {
2424  if (first) rb_str_set_len(str, first = 0);
2425  io_shift_cbuf(fptr, fptr->cbuf.len, &str);
2426  }
2427  v = fill_cbuf(fptr, 0);
2428  if (v != MORE_CHAR_SUSPENDED && v != MORE_CHAR_FINISHED) {
2429  if (fptr->cbuf.len) {
2430  if (first) rb_str_set_len(str, first = 0);
2431  io_shift_cbuf(fptr, fptr->cbuf.len, &str);
2432  }
2433  rb_exc_raise(v);
2434  }
2435  if (v == MORE_CHAR_FINISHED) {
2436  clear_readconv(fptr);
2437  if (first) rb_str_set_len(str, first = 0);
2438  if (shrinkable) io_shrink_read_string(str, RSTRING_LEN(str));
2439  return io_enc_str(str, fptr);
2440  }
2441  }
2442  }
2443 
2445  bytes = 0;
2446  pos = 0;
2447 
2448  enc = io_read_encoding(fptr);
2449  cr = 0;
2450 
2451  if (siz == 0) siz = BUFSIZ;
2452  shrinkable = io_setstrbuf(&str, siz);
2453  for (;;) {
2454  READ_CHECK(fptr);
2455  n = io_fread(str, bytes, siz - bytes, fptr);
2456  if (n == 0 && bytes == 0) {
2457  rb_str_set_len(str, 0);
2458  break;
2459  }
2460  bytes += n;
2461  rb_str_set_len(str, bytes);
2462  if (cr != ENC_CODERANGE_BROKEN)
2463  pos += rb_str_coderange_scan_restartable(RSTRING_PTR(str) + pos, RSTRING_PTR(str) + bytes, enc, &cr);
2464  if (bytes < siz) break;
2465  siz += BUFSIZ;
2466  rb_str_modify_expand(str, BUFSIZ);
2467  }
2468  if (shrinkable) io_shrink_read_string(str, RSTRING_LEN(str));
2469  str = io_enc_str(str, fptr);
2470  ENC_CODERANGE_SET(str, cr);
2471  return str;
2472 }
2473 
2474 void
2476 {
2477 #ifdef _WIN32
2478  if (rb_w32_set_nonblock(fptr->fd) != 0) {
2479  rb_sys_fail_path(fptr->pathv);
2480  }
2481 #else
2482  int oflags;
2483 #ifdef F_GETFL
2484  oflags = fcntl(fptr->fd, F_GETFL);
2485  if (oflags == -1) {
2486  rb_sys_fail_path(fptr->pathv);
2487  }
2488 #else
2489  oflags = 0;
2490 #endif
2491  if ((oflags & O_NONBLOCK) == 0) {
2492  oflags |= O_NONBLOCK;
2493  if (fcntl(fptr->fd, F_SETFL, oflags) == -1) {
2494  rb_sys_fail_path(fptr->pathv);
2495  }
2496  }
2497 #endif
2498 }
2499 
2501  int fd;
2502  char *str_ptr;
2503  long len;
2504 };
2505 
2506 static VALUE
2507 read_internal_call(VALUE arg)
2508 {
2509  struct read_internal_arg *p = (struct read_internal_arg *)arg;
2510  p->len = rb_read_internal(p->fd, p->str_ptr, p->len);
2511  return Qundef;
2512 }
2513 
2514 static int
2515 no_exception_p(VALUE opts)
2516 {
2517  VALUE except;
2518  ID id = id_exception;
2519 
2520  rb_get_kwargs(opts, &id, 0, 1, &except);
2521  return except == Qfalse;
2522 }
2523 
2524 static VALUE
2525 io_getpartial(int argc, VALUE *argv, VALUE io, VALUE opts, int nonblock)
2526 {
2527  rb_io_t *fptr;
2528  VALUE length, str;
2529  long n, len;
2530  struct read_internal_arg arg;
2531  int shrinkable;
2532 
2533  rb_scan_args(argc, argv, "11", &length, &str);
2534 
2535  if ((len = NUM2LONG(length)) < 0) {
2536  rb_raise(rb_eArgError, "negative length %ld given", len);
2537  }
2538 
2539  shrinkable = io_setstrbuf(&str, len);
2540  OBJ_TAINT(str);
2541 
2542  GetOpenFile(io, fptr);
2544 
2545  if (len == 0)
2546  return str;
2547 
2548  if (!nonblock)
2549  READ_CHECK(fptr);
2550  n = read_buffered_data(RSTRING_PTR(str), len, fptr);
2551  if (n <= 0) {
2552  again:
2553  if (nonblock) {
2554  rb_io_set_nonblock(fptr);
2555  }
2556  io_setstrbuf(&str, len);
2557  arg.fd = fptr->fd;
2558  arg.str_ptr = RSTRING_PTR(str);
2559  arg.len = len;
2560  rb_str_locktmp_ensure(str, read_internal_call, (VALUE)&arg);
2561  n = arg.len;
2562  if (n < 0) {
2563  int e = errno;
2564  if (!nonblock && rb_io_wait_readable(fptr->fd))
2565  goto again;
2566  if (nonblock && (e == EWOULDBLOCK || e == EAGAIN)) {
2567  if (no_exception_p(opts))
2568  return sym_wait_readable;
2569  else
2571  e, "read would block");
2572  }
2573  rb_syserr_fail_path(e, fptr->pathv);
2574  }
2575  }
2576  io_set_read_length(str, n, shrinkable);
2577 
2578  if (n == 0)
2579  return Qnil;
2580  else
2581  return str;
2582 }
2583 
2584 /*
2585  * call-seq:
2586  * ios.readpartial(maxlen) -> string
2587  * ios.readpartial(maxlen, outbuf) -> outbuf
2588  *
2589  * Reads at most <i>maxlen</i> bytes from the I/O stream.
2590  * It blocks only if <em>ios</em> has no data immediately available.
2591  * It doesn't block if some data available.
2592  *
2593  * If the optional _outbuf_ argument is present,
2594  * it must reference a String, which will receive the data.
2595  * The _outbuf_ will contain only the received data after the method call
2596  * even if it is not empty at the beginning.
2597  *
2598  * It raises <code>EOFError</code> on end of file.
2599  *
2600  * readpartial is designed for streams such as pipe, socket, tty, etc.
2601  * It blocks only when no data immediately available.
2602  * This means that it blocks only when following all conditions hold.
2603  * * the byte buffer in the IO object is empty.
2604  * * the content of the stream is empty.
2605  * * the stream is not reached to EOF.
2606  *
2607  * When readpartial blocks, it waits data or EOF on the stream.
2608  * If some data is reached, readpartial returns with the data.
2609  * If EOF is reached, readpartial raises EOFError.
2610  *
2611  * When readpartial doesn't blocks, it returns or raises immediately.
2612  * If the byte buffer is not empty, it returns the data in the buffer.
2613  * Otherwise if the stream has some content,
2614  * it returns the data in the stream.
2615  * Otherwise if the stream is reached to EOF, it raises EOFError.
2616  *
2617  * r, w = IO.pipe # buffer pipe content
2618  * w << "abc" # "" "abc".
2619  * r.readpartial(4096) #=> "abc" "" ""
2620  * r.readpartial(4096) # blocks because buffer and pipe is empty.
2621  *
2622  * r, w = IO.pipe # buffer pipe content
2623  * w << "abc" # "" "abc"
2624  * w.close # "" "abc" EOF
2625  * r.readpartial(4096) #=> "abc" "" EOF
2626  * r.readpartial(4096) # raises EOFError
2627  *
2628  * r, w = IO.pipe # buffer pipe content
2629  * w << "abc\ndef\n" # "" "abc\ndef\n"
2630  * r.gets #=> "abc\n" "def\n" ""
2631  * w << "ghi\n" # "def\n" "ghi\n"
2632  * r.readpartial(4096) #=> "def\n" "" "ghi\n"
2633  * r.readpartial(4096) #=> "ghi\n" "" ""
2634  *
2635  * Note that readpartial behaves similar to sysread.
2636  * The differences are:
2637  * * If the byte buffer is not empty, read from the byte buffer instead of "sysread for buffered IO (IOError)".
2638  * * It doesn't cause Errno::EWOULDBLOCK and Errno::EINTR. When readpartial meets EWOULDBLOCK and EINTR by read system call, readpartial retry the system call.
2639  *
2640  * The latter means that readpartial is nonblocking-flag insensitive.
2641  * It blocks on the situation IO#sysread causes Errno::EWOULDBLOCK as if the fd is blocking mode.
2642  *
2643  */
2644 
2645 static VALUE
2646 io_readpartial(int argc, VALUE *argv, VALUE io)
2647 {
2648  VALUE ret;
2649 
2650  ret = io_getpartial(argc, argv, io, Qnil, 0);
2651  if (NIL_P(ret))
2652  rb_eof_error();
2653  return ret;
2654 }
2655 
2656 static VALUE
2657 io_nonblock_eof(VALUE opts)
2658 {
2659  if (!no_exception_p(opts)) {
2660  rb_eof_error();
2661  }
2662  return Qnil;
2663 }
2664 
2665 /* :nodoc: */
2666 static VALUE
2667 io_read_nonblock(VALUE io, VALUE length, VALUE str, VALUE ex)
2668 {
2669  rb_io_t *fptr;
2670  long n, len;
2671  struct read_internal_arg arg;
2672  int shrinkable;
2673 
2674  if ((len = NUM2LONG(length)) < 0) {
2675  rb_raise(rb_eArgError, "negative length %ld given", len);
2676  }
2677 
2678  shrinkable = io_setstrbuf(&str, len);
2679  OBJ_TAINT(str);
2680  GetOpenFile(io, fptr);
2682 
2683  if (len == 0)
2684  return str;
2685 
2686  n = read_buffered_data(RSTRING_PTR(str), len, fptr);
2687  if (n <= 0) {
2688  rb_io_set_nonblock(fptr);
2689  shrinkable |= io_setstrbuf(&str, len);
2690  arg.fd = fptr->fd;
2691  arg.str_ptr = RSTRING_PTR(str);
2692  arg.len = len;
2693  rb_str_locktmp_ensure(str, read_internal_call, (VALUE)&arg);
2694  n = arg.len;
2695  if (n < 0) {
2696  int e = errno;
2697  if ((e == EWOULDBLOCK || e == EAGAIN)) {
2698  if (ex == Qfalse) return sym_wait_readable;
2700  e, "read would block");
2701  }
2702  rb_syserr_fail_path(e, fptr->pathv);
2703  }
2704  }
2705  io_set_read_length(str, n, shrinkable);
2706 
2707  if (n == 0) {
2708  if (ex == Qfalse) return Qnil;
2709  rb_eof_error();
2710  }
2711 
2712  return str;
2713 }
2714 
2715 /* :nodoc: */
2716 static VALUE
2717 io_write_nonblock(VALUE io, VALUE str, VALUE ex)
2718 {
2719  rb_io_t *fptr;
2720  long n;
2721 
2722  if (!RB_TYPE_P(str, T_STRING))
2723  str = rb_obj_as_string(str);
2724 
2725  io = GetWriteIO(io);
2726  GetOpenFile(io, fptr);
2727  rb_io_check_writable(fptr);
2728 
2729  if (io_fflush(fptr) < 0)
2730  rb_sys_fail(0);
2731 
2732  rb_io_set_nonblock(fptr);
2733  n = write(fptr->fd, RSTRING_PTR(str), RSTRING_LEN(str));
2734 
2735  if (n == -1) {
2736  int e = errno;
2737  if (e == EWOULDBLOCK || e == EAGAIN) {
2738  if (ex == Qfalse) {
2739  return sym_wait_writable;
2740  }
2741  else {
2742  rb_readwrite_syserr_fail(RB_IO_WAIT_WRITABLE, e, "write would block");
2743  }
2744  }
2745  rb_syserr_fail_path(e, fptr->pathv);
2746  }
2747 
2748  return LONG2FIX(n);
2749 }
2750 
2751 /*
2752  * call-seq:
2753  * ios.read([length [, outbuf]]) -> string, outbuf, or nil
2754  *
2755  * Reads _length_ bytes from the I/O stream.
2756  *
2757  * _length_ must be a non-negative integer or +nil+.
2758  *
2759  * If _length_ is a positive integer, +read+ tries to read
2760  * _length_ bytes without any conversion (binary mode).
2761  * It returns +nil+ if an EOF is encountered before anything can be read.
2762  * Fewer than _length_ bytes are returned if an EOF is encountered during
2763  * the read.
2764  * In the case of an integer _length_, the resulting string is always
2765  * in ASCII-8BIT encoding.
2766  *
2767  * If _length_ is omitted or is +nil+, it reads until EOF
2768  * and the encoding conversion is applied, if applicable.
2769  * A string is returned even if EOF is encountered before any data is read.
2770  *
2771  * If _length_ is zero, it returns an empty string (<code>""</code>).
2772  *
2773  * If the optional _outbuf_ argument is present,
2774  * it must reference a String, which will receive the data.
2775  * The _outbuf_ will contain only the received data after the method call
2776  * even if it is not empty at the beginning.
2777  *
2778  * When this method is called at end of file, it returns +nil+
2779  * or <code>""</code>, depending on _length_:
2780  * +read+, <code>read(nil)</code>, and <code>read(0)</code> return
2781  * <code>""</code>,
2782  * <code>read(<i>positive_integer</i>)</code> returns +nil+.
2783  *
2784  * f = File.new("testfile")
2785  * f.read(16) #=> "This is line one"
2786  *
2787  * # read whole file
2788  * open("file") do |f|
2789  * data = f.read # This returns a string even if the file is empty.
2790  * # ...
2791  * end
2792  *
2793  * # iterate over fixed length records
2794  * open("fixed-record-file") do |f|
2795  * while record = f.read(256)
2796  * # ...
2797  * end
2798  * end
2799  *
2800  * # iterate over variable length records,
2801  * # each record is prefixed by its 32-bit length
2802  * open("variable-record-file") do |f|
2803  * while len = f.read(4)
2804  * len = len.unpack("N")[0] # 32-bit length
2805  * record = f.read(len) # This returns a string even if len is 0.
2806  * end
2807  * end
2808  *
2809  * Note that this method behaves like the fread() function in C.
2810  * This means it retries to invoke read(2) system calls to read data
2811  * with the specified length (or until EOF).
2812  * This behavior is preserved even if <i>ios</i> is in non-blocking mode.
2813  * (This method is non-blocking flag insensitive as other methods.)
2814  * If you need the behavior like a single read(2) system call,
2815  * consider #readpartial, #read_nonblock, and #sysread.
2816  */
2817 
2818 static VALUE
2819 io_read(int argc, VALUE *argv, VALUE io)
2820 {
2821  rb_io_t *fptr;
2822  long n, len;
2823  VALUE length, str;
2824  int shrinkable;
2825 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
2826  int previous_mode;
2827 #endif
2828 
2829  rb_scan_args(argc, argv, "02", &length, &str);
2830 
2831  if (NIL_P(length)) {
2832  GetOpenFile(io, fptr);
2834  return read_all(fptr, remain_size(fptr), str);
2835  }
2836  len = NUM2LONG(length);
2837  if (len < 0) {
2838  rb_raise(rb_eArgError, "negative length %ld given", len);
2839  }
2840 
2841  shrinkable = io_setstrbuf(&str,len);
2842 
2843  GetOpenFile(io, fptr);
2845  if (len == 0) {
2846  io_set_read_length(str, 0, shrinkable);
2847  return str;
2848  }
2849 
2850  READ_CHECK(fptr);
2851 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
2852  previous_mode = set_binary_mode_with_seek_cur(fptr);
2853 #endif
2854  n = io_fread(str, 0, len, fptr);
2855  io_set_read_length(str, n, shrinkable);
2856 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
2857  if (previous_mode == O_TEXT) {
2858  setmode(fptr->fd, O_TEXT);
2859  }
2860 #endif
2861  if (n == 0) return Qnil;
2862  OBJ_TAINT(str);
2863 
2864  return str;
2865 }
2866 
2867 static void
2868 rscheck(const char *rsptr, long rslen, VALUE rs)
2869 {
2870  if (!rs) return;
2871  if (RSTRING_PTR(rs) != rsptr && RSTRING_LEN(rs) != rslen)
2872  rb_raise(rb_eRuntimeError, "rs modified");
2873 }
2874 
2875 static int
2876 appendline(rb_io_t *fptr, int delim, VALUE *strp, long *lp)
2877 {
2878  VALUE str = *strp;
2879  long limit = *lp;
2880 
2881  if (NEED_READCONV(fptr)) {
2882  SET_BINARY_MODE(fptr);
2883  make_readconv(fptr, 0);
2884  do {
2885  const char *p, *e;
2886  int searchlen = READ_CHAR_PENDING_COUNT(fptr);
2887  if (searchlen) {
2888  p = READ_CHAR_PENDING_PTR(fptr);
2889  if (0 < limit && limit < searchlen)
2890  searchlen = (int)limit;
2891  e = memchr(p, delim, searchlen);
2892  if (e) {
2893  int len = (int)(e-p+1);
2894  if (NIL_P(str))
2895  *strp = str = rb_str_new(p, len);
2896  else
2897  rb_str_buf_cat(str, p, len);
2898  fptr->cbuf.off += len;
2899  fptr->cbuf.len -= len;
2900  limit -= len;
2901  *lp = limit;
2902  return delim;
2903  }
2904 
2905  if (NIL_P(str))
2906  *strp = str = rb_str_new(p, searchlen);
2907  else
2908  rb_str_buf_cat(str, p, searchlen);
2909  fptr->cbuf.off += searchlen;
2910  fptr->cbuf.len -= searchlen;
2911  limit -= searchlen;
2912 
2913  if (limit == 0) {
2914  *lp = limit;
2915  return (unsigned char)RSTRING_PTR(str)[RSTRING_LEN(str)-1];
2916  }
2917  }
2918  } while (more_char(fptr) != MORE_CHAR_FINISHED);
2919  clear_readconv(fptr);
2920  *lp = limit;
2921  return EOF;
2922  }
2923 
2925  do {
2926  long pending = READ_DATA_PENDING_COUNT(fptr);
2927  if (pending > 0) {
2928  const char *p = READ_DATA_PENDING_PTR(fptr);
2929  const char *e;
2930  long last;
2931 
2932  if (limit > 0 && pending > limit) pending = limit;
2933  e = memchr(p, delim, pending);
2934  if (e) pending = e - p + 1;
2935  if (!NIL_P(str)) {
2936  last = RSTRING_LEN(str);
2937  rb_str_resize(str, last + pending);
2938  }
2939  else {
2940  last = 0;
2941  *strp = str = rb_str_buf_new(pending);
2942  rb_str_set_len(str, pending);
2943  }
2944  read_buffered_data(RSTRING_PTR(str) + last, pending, fptr); /* must not fail */
2945  limit -= pending;
2946  *lp = limit;
2947  if (e) return delim;
2948  if (limit == 0)
2949  return (unsigned char)RSTRING_PTR(str)[RSTRING_LEN(str)-1];
2950  }
2951  READ_CHECK(fptr);
2952  } while (io_fillbuf(fptr) >= 0);
2953  *lp = limit;
2954  return EOF;
2955 }
2956 
2957 static inline int
2958 swallow(rb_io_t *fptr, int term)
2959 {
2960  if (NEED_READCONV(fptr)) {
2961  rb_encoding *enc = io_read_encoding(fptr);
2962  int needconv = rb_enc_mbminlen(enc) != 1;
2963  SET_BINARY_MODE(fptr);
2964  make_readconv(fptr, 0);
2965  do {
2966  size_t cnt;
2967  while ((cnt = READ_CHAR_PENDING_COUNT(fptr)) > 0) {
2968  const char *p = READ_CHAR_PENDING_PTR(fptr);
2969  int i;
2970  if (!needconv) {
2971  if (*p != term) return TRUE;
2972  i = (int)cnt;
2973  while (--i && *++p == term);
2974  }
2975  else {
2976  const char *e = p + cnt;
2977  if (rb_enc_ascget(p, e, &i, enc) != term) return TRUE;
2978  while ((p += i) < e && rb_enc_ascget(p, e, &i, enc) == term);
2979  i = (int)(e - p);
2980  }
2981  io_shift_cbuf(fptr, (int)cnt - i, NULL);
2982  }
2983  } while (more_char(fptr) != MORE_CHAR_FINISHED);
2984  return FALSE;
2985  }
2986 
2988  do {
2989  size_t cnt;
2990  while ((cnt = READ_DATA_PENDING_COUNT(fptr)) > 0) {
2991  char buf[1024];
2992  const char *p = READ_DATA_PENDING_PTR(fptr);
2993  int i;
2994  if (cnt > sizeof buf) cnt = sizeof buf;
2995  if (*p != term) return TRUE;
2996  i = (int)cnt;
2997  while (--i && *++p == term);
2998  if (!read_buffered_data(buf, cnt - i, fptr)) /* must not fail */
2999  rb_sys_fail_path(fptr->pathv);
3000  }
3001  READ_CHECK(fptr);
3002  } while (io_fillbuf(fptr) == 0);
3003  return FALSE;
3004 }
3005 
3006 static VALUE
3007 rb_io_getline_fast(rb_io_t *fptr, rb_encoding *enc, int chomp)
3008 {
3009  VALUE str = Qnil;
3010  int len = 0;
3011  long pos = 0;
3012  int cr = 0;
3013 
3014  do {
3015  int pending = READ_DATA_PENDING_COUNT(fptr);
3016 
3017  if (pending > 0) {
3018  const char *p = READ_DATA_PENDING_PTR(fptr);
3019  const char *e;
3020  int chomplen = 0;
3021 
3022  e = memchr(p, '\n', pending);
3023  if (e) {
3024  pending = (int)(e - p + 1);
3025  if (chomp) {
3026  chomplen = (pending > 1 && *(e-1) == '\r') + 1;
3027  }
3028  }
3029  if (NIL_P(str)) {
3030  str = rb_str_new(p, pending - chomplen);
3031  fptr->rbuf.off += pending;
3032  fptr->rbuf.len -= pending;
3033  }
3034  else {
3035  rb_str_resize(str, len + pending - chomplen);
3036  read_buffered_data(RSTRING_PTR(str)+len, pending - chomplen, fptr);
3037  fptr->rbuf.off += chomplen;
3038  fptr->rbuf.len -= chomplen;
3039  }
3040  len += pending - chomplen;
3041  if (cr != ENC_CODERANGE_BROKEN)
3042  pos += rb_str_coderange_scan_restartable(RSTRING_PTR(str) + pos, RSTRING_PTR(str) + len, enc, &cr);
3043  if (e) break;
3044  }
3045  READ_CHECK(fptr);
3046  } while (io_fillbuf(fptr) >= 0);
3047  if (NIL_P(str)) return Qnil;
3048 
3049  str = io_enc_str(str, fptr);
3050  ENC_CODERANGE_SET(str, cr);
3051  fptr->lineno++;
3052 
3053  return str;
3054 }
3055 
3056 struct getline_arg {
3058  VALUE rs;
3059  long limit;
3060  unsigned int chomp: 1;
3061 };
3062 
3063 static void
3064 extract_getline_opts(VALUE opts, struct getline_arg *args)
3065 {
3066  int chomp = FALSE;
3067  if (!NIL_P(opts)) {
3068  static ID kwds[1];
3069  VALUE vchomp;
3070  if (!kwds[0]) {
3071  kwds[0] = rb_intern_const("chomp");
3072  }
3073  rb_get_kwargs(opts, kwds, 0, -2, &vchomp);
3074  chomp = (vchomp != Qundef) && RTEST(vchomp);
3075  }
3076  args->chomp = chomp;
3077 }
3078 
3079 static void
3080 extract_getline_args(int argc, VALUE *argv, struct getline_arg *args)
3081 {
3082  VALUE rs = rb_rs, lim = Qnil;
3083 
3084  if (argc == 1) {
3085  VALUE tmp = Qnil;
3086 
3087  if (NIL_P(argv[0]) || !NIL_P(tmp = rb_check_string_type(argv[0]))) {
3088  rs = tmp;
3089  }
3090  else {
3091  lim = argv[0];
3092  }
3093  }
3094  else if (2 <= argc) {
3095  rs = argv[0], lim = argv[1];
3096  if (!NIL_P(rs))
3097  StringValue(rs);
3098  }
3099  args->rs = rs;
3100  args->limit = NIL_P(lim) ? -1L : NUM2LONG(lim);
3101 }
3102 
3103 static void
3104 check_getline_args(VALUE *rsp, long *limit, VALUE io)
3105 {
3106  rb_io_t *fptr;
3107  VALUE rs = *rsp;
3108 
3109  if (!NIL_P(rs)) {
3110  rb_encoding *enc_rs, *enc_io;
3111 
3112  GetOpenFile(io, fptr);
3113  enc_rs = rb_enc_get(rs);
3114  enc_io = io_read_encoding(fptr);
3115  if (enc_io != enc_rs &&
3117  (RSTRING_LEN(rs) > 0 && !rb_enc_asciicompat(enc_io)))) {
3118  if (rs == rb_default_rs) {
3119  rs = rb_enc_str_new(0, 0, enc_io);
3120  rb_str_buf_cat_ascii(rs, "\n");
3121  *rsp = rs;
3122  }
3123  else {
3124  rb_raise(rb_eArgError, "encoding mismatch: %s IO with %s RS",
3125  rb_enc_name(enc_io),
3126  rb_enc_name(enc_rs));
3127  }
3128  }
3129  }
3130 }
3131 
3132 static void
3133 prepare_getline_args(int argc, VALUE *argv, struct getline_arg *args, VALUE io)
3134 {
3135  VALUE opts;
3136  argc = rb_scan_args(argc, argv, "02:", NULL, NULL, &opts);
3137  extract_getline_args(argc, argv, args);
3138  extract_getline_opts(opts, args);
3139  check_getline_args(&args->rs, &args->limit, io);
3140 }
3141 
3142 static VALUE
3143 rb_io_getline_0(VALUE rs, long limit, int chomp, rb_io_t *fptr)
3144 {
3145  VALUE str = Qnil;
3146  int nolimit = 0;
3147  rb_encoding *enc;
3148 
3150  if (NIL_P(rs) && limit < 0) {
3151  str = read_all(fptr, 0, Qnil);
3152  if (RSTRING_LEN(str) == 0) return Qnil;
3153  if (chomp) rb_str_chomp_string(str, rb_default_rs);
3154  }
3155  else if (limit == 0) {
3156  return rb_enc_str_new(0, 0, io_read_encoding(fptr));
3157  }
3158  else if (rs == rb_default_rs && limit < 0 && !NEED_READCONV(fptr) &&
3159  rb_enc_asciicompat(enc = io_read_encoding(fptr))) {
3161  return rb_io_getline_fast(fptr, enc, chomp);
3162  }
3163  else {
3164  int c, newline = -1;
3165  const char *rsptr = 0;
3166  long rslen = 0;
3167  int rspara = 0;
3168  int extra_limit = 16;
3169  int chomp_cr = chomp;
3170 
3171  SET_BINARY_MODE(fptr);
3172  enc = io_read_encoding(fptr);
3173 
3174  if (!NIL_P(rs)) {
3175  rslen = RSTRING_LEN(rs);
3176  if (rslen == 0) {
3177  rsptr = "\n\n";
3178  rslen = 2;
3179  rspara = 1;
3180  swallow(fptr, '\n');
3181  rs = 0;
3182  if (!rb_enc_asciicompat(enc)) {
3183  rs = rb_usascii_str_new(rsptr, rslen);
3184  rs = rb_str_encode(rs, rb_enc_from_encoding(enc), 0, Qnil);
3185  OBJ_FREEZE(rs);
3186  rsptr = RSTRING_PTR(rs);
3187  rslen = RSTRING_LEN(rs);
3188  }
3189  }
3190  else {
3191  rsptr = RSTRING_PTR(rs);
3192  }
3193  newline = (unsigned char)rsptr[rslen - 1];
3194  chomp_cr = chomp && rslen == 1 && newline == '\n';
3195  }
3196 
3197  /* MS - Optimization */
3198  while ((c = appendline(fptr, newline, &str, &limit)) != EOF) {
3199  const char *s, *p, *pp, *e;
3200 
3201  if (c == newline) {
3202  if (RSTRING_LEN(str) < rslen) continue;
3203  s = RSTRING_PTR(str);
3204  e = RSTRING_END(str);
3205  p = e - rslen;
3206  pp = rb_enc_left_char_head(s, p, e, enc);
3207  if (pp != p) continue;
3208  if (!rspara) rscheck(rsptr, rslen, rs);
3209  if (memcmp(p, rsptr, rslen) == 0) {
3210  if (chomp) {
3211  if (chomp_cr && p > s && *(p-1) == '\r') --p;
3212  rb_str_set_len(str, p - s);
3213  }
3214  break;
3215  }
3216  }
3217  if (limit == 0) {
3218  s = RSTRING_PTR(str);
3219  p = RSTRING_END(str);
3220  pp = rb_enc_left_char_head(s, p-1, p, enc);
3221  if (extra_limit &&
3223  /* relax the limit while incomplete character.
3224  * extra_limit limits the relax length */
3225  limit = 1;
3226  extra_limit--;
3227  }
3228  else {
3229  nolimit = 1;
3230  break;
3231  }
3232  }
3233  }
3234 
3235  if (rspara && c != EOF)
3236  swallow(fptr, '\n');
3237  if (!NIL_P(str))
3238  str = io_enc_str(str, fptr);
3239  }
3240 
3241  if (!NIL_P(str) && !nolimit) {
3242  fptr->lineno++;
3243  }
3244 
3245  return str;
3246 }
3247 
3248 static VALUE
3249 rb_io_getline_1(VALUE rs, long limit, int chomp, VALUE io)
3250 {
3251  rb_io_t *fptr;
3252  int old_lineno, new_lineno;
3253  VALUE str;
3254 
3255  GetOpenFile(io, fptr);
3256  old_lineno = fptr->lineno;
3257  str = rb_io_getline_0(rs, limit, chomp, fptr);
3258  if (!NIL_P(str) && (new_lineno = fptr->lineno) != old_lineno) {
3259  if (io == ARGF.current_file) {
3260  ARGF.lineno += new_lineno - old_lineno;
3261  ARGF.last_lineno = ARGF.lineno;
3262  }
3263  else {
3264  ARGF.last_lineno = new_lineno;
3265  }
3266  }
3267 
3268  return str;
3269 }
3270 
3271 static VALUE
3272 rb_io_getline(int argc, VALUE *argv, VALUE io)
3273 {
3274  struct getline_arg args;
3275 
3276  prepare_getline_args(argc, argv, &args, io);
3277  return rb_io_getline_1(args.rs, args.limit, args.chomp, io);
3278 }
3279 
3280 VALUE
3282 {
3283  return rb_io_getline_1(rb_default_rs, -1, FALSE, io);
3284 }
3285 
3286 VALUE
3288 {
3289  rb_io_t *fptr;
3290  GetOpenFile(io, fptr);
3291  return rb_io_getline_0(rb_default_rs, -1, FALSE, fptr);
3292 }
3293 
3294 /*
3295  * call-seq:
3296  * ios.gets(sep=$/ [, getline_args]) -> string or nil
3297  * ios.gets(limit [, getline_args]) -> string or nil
3298  * ios.gets(sep, limit [, getline_args]) -> string or nil
3299  *
3300  * Reads the next ``line'' from the I/O stream; lines are separated by
3301  * <i>sep</i>. A separator of +nil+ reads the entire
3302  * contents, and a zero-length separator reads the input a paragraph at
3303  * a time (two successive newlines in the input separate paragraphs).
3304  * The stream must be opened for reading or an <code>IOError</code>
3305  * will be raised. The line read in will be returned and also assigned
3306  * to <code>$_</code>. Returns +nil+ if called at end of
3307  * file. If the first argument is an integer, or optional second
3308  * argument is given, the returning string would not be longer than the
3309  * given value in bytes.
3310  *
3311  * File.new("testfile").gets #=> "This is line one\n"
3312  * $_ #=> "This is line one\n"
3313  *
3314  * File.new("testfile").gets(4)#=> "This"
3315  *
3316  * If IO contains multibyte characters byte then <code>gets(1)</code>
3317  * returns character entirely:
3318  *
3319  * # Russian characters take 2 bytes
3320  * File.write("testfile", "\u{442 435 441 442}")
3321  * File.open("testfile") {|f|f.gets(1)} #=> "\u0442"
3322  * File.open("testfile") {|f|f.gets(2)} #=> "\u0442"
3323  * File.open("testfile") {|f|f.gets(3)} #=> "\u0442\u0435"
3324  * File.open("testfile") {|f|f.gets(4)} #=> "\u0442\u0435"
3325  */
3326 
3327 static VALUE
3328 rb_io_gets_m(int argc, VALUE *argv, VALUE io)
3329 {
3330  VALUE str;
3331 
3332  str = rb_io_getline(argc, argv, io);
3333  rb_lastline_set(str);
3334 
3335  return str;
3336 }
3337 
3338 /*
3339  * call-seq:
3340  * ios.lineno -> integer
3341  *
3342  * Returns the current line number in <em>ios</em>. The stream must be
3343  * opened for reading. <code>lineno</code> counts the number of times
3344  * #gets is called rather than the number of newlines encountered. The two
3345  * values will differ if #gets is called with a separator other than newline.
3346  *
3347  * Methods that use <code>$/</code> like #each, #lines and #readline will
3348  * also increment <code>lineno</code>.
3349  *
3350  * See also the <code>$.</code> variable.
3351  *
3352  * f = File.new("testfile")
3353  * f.lineno #=> 0
3354  * f.gets #=> "This is line one\n"
3355  * f.lineno #=> 1
3356  * f.gets #=> "This is line two\n"
3357  * f.lineno #=> 2
3358  */
3359 
3360 static VALUE
3361 rb_io_lineno(VALUE io)
3362 {
3363  rb_io_t *fptr;
3364 
3365  GetOpenFile(io, fptr);
3367  return INT2NUM(fptr->lineno);
3368 }
3369 
3370 /*
3371  * call-seq:
3372  * ios.lineno = integer -> integer
3373  *
3374  * Manually sets the current line number to the given value.
3375  * <code>$.</code> is updated only on the next read.
3376  *
3377  * f = File.new("testfile")
3378  * f.gets #=> "This is line one\n"
3379  * $. #=> 1
3380  * f.lineno = 1000
3381  * f.lineno #=> 1000
3382  * $. #=> 1 # lineno of last read
3383  * f.gets #=> "This is line two\n"
3384  * $. #=> 1001 # lineno of last read
3385  */
3386 
3387 static VALUE
3388 rb_io_set_lineno(VALUE io, VALUE lineno)
3389 {
3390  rb_io_t *fptr;
3391 
3392  GetOpenFile(io, fptr);
3394  fptr->lineno = NUM2INT(lineno);
3395  return lineno;
3396 }
3397 
3398 /*
3399  * call-seq:
3400  * ios.readline(sep=$/ [, getline_args]) -> string
3401  * ios.readline(limit [, getline_args]) -> string
3402  * ios.readline(sep, limit [, getline_args]) -> string
3403  *
3404  * Reads a line as with <code>IO#gets</code>, but raises an
3405  * <code>EOFError</code> on end of file.
3406  */
3407 
3408 static VALUE
3409 rb_io_readline(int argc, VALUE *argv, VALUE io)
3410 {
3411  VALUE line = rb_io_gets_m(argc, argv, io);
3412 
3413  if (NIL_P(line)) {
3414  rb_eof_error();
3415  }
3416  return line;
3417 }
3418 
3419 static VALUE io_readlines(const struct getline_arg *arg, VALUE io);
3420 
3421 /*
3422  * call-seq:
3423  * ios.readlines(sep=$/ [, getline_args]) -> array
3424  * ios.readlines(limit [, getline_args]) -> array
3425  * ios.readlines(sep, limit [, getline_args]) -> array
3426  *
3427  * Reads all of the lines in <em>ios</em>, and returns them in
3428  * <i>anArray</i>. Lines are separated by the optional <i>sep</i>. If
3429  * <i>sep</i> is +nil+, the rest of the stream is returned
3430  * as a single record.
3431  * If the first argument is an integer, or
3432  * optional second argument is given, the returning string would not be
3433  * longer than the given value in bytes. The stream must be opened for
3434  * reading or an <code>IOError</code> will be raised.
3435  *
3436  * f = File.new("testfile")
3437  * f.readlines[0] #=> "This is line one\n"
3438  *
3439  * See <code>IO.readlines</code> for detail about getline_args.
3440  */
3441 
3442 static VALUE
3443 rb_io_readlines(int argc, VALUE *argv, VALUE io)
3444 {
3445  struct getline_arg args;
3446 
3447  prepare_getline_args(argc, argv, &args, io);
3448  return io_readlines(&args, io);
3449 }
3450 
3451 static VALUE
3452 io_readlines(const struct getline_arg *arg, VALUE io)
3453 {
3454  VALUE line, ary;
3455 
3456  if (arg->limit == 0)
3457  rb_raise(rb_eArgError, "invalid limit: 0 for readlines");
3458  ary = rb_ary_new();
3459  while (!NIL_P(line = rb_io_getline_1(arg->rs, arg->limit, arg->chomp, io))) {
3460  rb_ary_push(ary, line);
3461  }
3462  return ary;
3463 }
3464 
3465 /*
3466  * call-seq:
3467  * ios.each(sep=$/ [, getline_args]) {|line| block } -> ios
3468  * ios.each(limit [, getline_args]) {|line| block } -> ios
3469  * ios.each(sep, limit [, getline_args]) {|line| block } -> ios
3470  * ios.each(...) -> an_enumerator
3471  *
3472  * ios.each_line(sep=$/ [, getline_args]) {|line| block } -> ios
3473  * ios.each_line(limit [, getline_args]) {|line| block } -> ios
3474  * ios.each_line(sep, limit [, getline_args]) {|line| block } -> ios
3475  * ios.each_line(...) -> an_enumerator
3476  *
3477  * Executes the block for every line in <em>ios</em>, where lines are
3478  * separated by <i>sep</i>. <em>ios</em> must be opened for
3479  * reading or an <code>IOError</code> will be raised.
3480  *
3481  * If no block is given, an enumerator is returned instead.
3482  *
3483  * f = File.new("testfile")
3484  * f.each {|line| puts "#{f.lineno}: #{line}" }
3485  *
3486  * <em>produces:</em>
3487  *
3488  * 1: This is line one
3489  * 2: This is line two
3490  * 3: This is line three
3491  * 4: And so on...
3492  *
3493  * See <code>IO.readlines</code> for detail about getline_args.
3494  */
3495 
3496 static VALUE
3497 rb_io_each_line(int argc, VALUE *argv, VALUE io)
3498 {
3499  VALUE str;
3500  struct getline_arg args;
3501 
3502  RETURN_ENUMERATOR(io, argc, argv);
3503  prepare_getline_args(argc, argv, &args, io);
3504  if (args.limit == 0)
3505  rb_raise(rb_eArgError, "invalid limit: 0 for each_line");
3506  while (!NIL_P(str = rb_io_getline_1(args.rs, args.limit, args.chomp, io))) {
3507  rb_yield(str);
3508  }
3509  return io;
3510 }
3511 
3512 /*
3513  * This is a deprecated alias for <code>each_line</code>.
3514  */
3515 
3516 static VALUE
3517 rb_io_lines(int argc, VALUE *argv, VALUE io)
3518 {
3519  rb_warn("IO#lines is deprecated; use #each_line instead");
3520  if (!rb_block_given_p())
3521  return rb_enumeratorize(io, ID2SYM(rb_intern("each_line")), argc, argv);
3522  return rb_io_each_line(argc, argv, io);
3523 }
3524 
3525 /*
3526  * call-seq:
3527  * ios.each_byte {|byte| block } -> ios
3528  * ios.each_byte -> an_enumerator
3529  *
3530  * Calls the given block once for each byte (0..255) in <em>ios</em>,
3531  * passing the byte as an argument. The stream must be opened for
3532  * reading or an <code>IOError</code> will be raised.
3533  *
3534  * If no block is given, an enumerator is returned instead.
3535  *
3536  * f = File.new("testfile")
3537  * checksum = 0
3538  * f.each_byte {|x| checksum ^= x } #=> #<File:testfile>
3539  * checksum #=> 12
3540  */
3541 
3542 static VALUE
3543 rb_io_each_byte(VALUE io)
3544 {
3545  rb_io_t *fptr;
3546 
3547  RETURN_ENUMERATOR(io, 0, 0);
3548  GetOpenFile(io, fptr);
3549 
3550  do {
3551  while (fptr->rbuf.len > 0) {
3552  char *p = fptr->rbuf.ptr + fptr->rbuf.off++;
3553  fptr->rbuf.len--;
3554  rb_yield(INT2FIX(*p & 0xff));
3555  errno = 0;
3556  }
3558  READ_CHECK(fptr);
3559  } while (io_fillbuf(fptr) >= 0);
3560  return io;
3561 }
3562 
3563 /*
3564  * This is a deprecated alias for <code>each_byte</code>.
3565  */
3566 
3567 static VALUE
3568 rb_io_bytes(VALUE io)
3569 {
3570  rb_warn("IO#bytes is deprecated; use #each_byte instead");
3571  if (!rb_block_given_p())
3572  return rb_enumeratorize(io, ID2SYM(rb_intern("each_byte")), 0, 0);
3573  return rb_io_each_byte(io);
3574 }
3575 
3576 static VALUE
3577 io_getc(rb_io_t *fptr, rb_encoding *enc)
3578 {
3579  int r, n, cr = 0;
3580  VALUE str;
3581 
3582  if (NEED_READCONV(fptr)) {
3583  rb_encoding *read_enc = io_read_encoding(fptr);
3584 
3585  str = Qnil;
3586  SET_BINARY_MODE(fptr);
3587  make_readconv(fptr, 0);
3588 
3589  while (1) {
3590  if (fptr->cbuf.len) {
3591  r = rb_enc_precise_mbclen(fptr->cbuf.ptr+fptr->cbuf.off,
3592  fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
3593  read_enc);
3594  if (!MBCLEN_NEEDMORE_P(r))
3595  break;
3596  if (fptr->cbuf.len == fptr->cbuf.capa) {
3597  rb_raise(rb_eIOError, "too long character");
3598  }
3599  }
3600 
3601  if (more_char(fptr) == MORE_CHAR_FINISHED) {
3602  if (fptr->cbuf.len == 0) {
3603  clear_readconv(fptr);
3604  return Qnil;
3605  }
3606  /* return an unit of an incomplete character just before EOF */
3607  str = rb_enc_str_new(fptr->cbuf.ptr+fptr->cbuf.off, 1, read_enc);
3608  fptr->cbuf.off += 1;
3609  fptr->cbuf.len -= 1;
3610  if (fptr->cbuf.len == 0) clear_readconv(fptr);
3612  return str;
3613  }
3614  }
3615  if (MBCLEN_INVALID_P(r)) {
3616  r = rb_enc_mbclen(fptr->cbuf.ptr+fptr->cbuf.off,
3617  fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
3618  read_enc);
3619  io_shift_cbuf(fptr, r, &str);
3620  cr = ENC_CODERANGE_BROKEN;
3621  }
3622  else {
3623  io_shift_cbuf(fptr, MBCLEN_CHARFOUND_LEN(r), &str);
3624  cr = ENC_CODERANGE_VALID;
3625  if (MBCLEN_CHARFOUND_LEN(r) == 1 && rb_enc_asciicompat(read_enc) &&
3626  ISASCII(RSTRING_PTR(str)[0])) {
3627  cr = ENC_CODERANGE_7BIT;
3628  }
3629  }
3630  str = io_enc_str(str, fptr);
3631  ENC_CODERANGE_SET(str, cr);
3632  return str;
3633  }
3634 
3636  if (io_fillbuf(fptr) < 0) {
3637  return Qnil;
3638  }
3639  if (rb_enc_asciicompat(enc) && ISASCII(fptr->rbuf.ptr[fptr->rbuf.off])) {
3640  str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, 1);
3641  fptr->rbuf.off += 1;
3642  fptr->rbuf.len -= 1;
3643  cr = ENC_CODERANGE_7BIT;
3644  }
3645  else {
3646  r = rb_enc_precise_mbclen(fptr->rbuf.ptr+fptr->rbuf.off, fptr->rbuf.ptr+fptr->rbuf.off+fptr->rbuf.len, enc);
3647  if (MBCLEN_CHARFOUND_P(r) &&
3648  (n = MBCLEN_CHARFOUND_LEN(r)) <= fptr->rbuf.len) {
3649  str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, n);
3650  fptr->rbuf.off += n;
3651  fptr->rbuf.len -= n;
3652  cr = ENC_CODERANGE_VALID;
3653  }
3654  else if (MBCLEN_NEEDMORE_P(r)) {
3655  str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, fptr->rbuf.len);
3656  fptr->rbuf.len = 0;
3657  getc_needmore:
3658  if (io_fillbuf(fptr) != -1) {
3659  rb_str_cat(str, fptr->rbuf.ptr+fptr->rbuf.off, 1);
3660  fptr->rbuf.off++;
3661  fptr->rbuf.len--;
3662  r = rb_enc_precise_mbclen(RSTRING_PTR(str), RSTRING_PTR(str)+RSTRING_LEN(str), enc);
3663  if (MBCLEN_NEEDMORE_P(r)) {
3664  goto getc_needmore;
3665  }
3666  else if (MBCLEN_CHARFOUND_P(r)) {
3667  cr = ENC_CODERANGE_VALID;
3668  }
3669  }
3670  }
3671  else {
3672  str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, 1);
3673  fptr->rbuf.off++;
3674  fptr->rbuf.len--;
3675  }
3676  }
3677  if (!cr) cr = ENC_CODERANGE_BROKEN;
3678  str = io_enc_str(str, fptr);
3679  ENC_CODERANGE_SET(str, cr);
3680  return str;
3681 }
3682 
3683 /*
3684  * call-seq:
3685  * ios.each_char {|c| block } -> ios
3686  * ios.each_char -> an_enumerator
3687  *
3688  * Calls the given block once for each character in <em>ios</em>,
3689  * passing the character as an argument. The stream must be opened for
3690  * reading or an <code>IOError</code> will be raised.
3691  *
3692  * If no block is given, an enumerator is returned instead.
3693  *
3694  * f = File.new("testfile")
3695  * f.each_char {|c| print c, ' ' } #=> #<File:testfile>
3696  */
3697 
3698 static VALUE
3699 rb_io_each_char(VALUE io)
3700 {
3701  rb_io_t *fptr;
3702  rb_encoding *enc;
3703  VALUE c;
3704 
3705  RETURN_ENUMERATOR(io, 0, 0);
3706  GetOpenFile(io, fptr);
3708 
3709  enc = io_input_encoding(fptr);
3710  READ_CHECK(fptr);
3711  while (!NIL_P(c = io_getc(fptr, enc))) {
3712  rb_yield(c);
3713  }
3714  return io;
3715 }
3716 
3717 /*
3718  * This is a deprecated alias for <code>each_char</code>.
3719  */
3720 
3721 static VALUE
3722 rb_io_chars(VALUE io)
3723 {
3724  rb_warn("IO#chars is deprecated; use #each_char instead");
3725  if (!rb_block_given_p())
3726  return rb_enumeratorize(io, ID2SYM(rb_intern("each_char")), 0, 0);
3727  return rb_io_each_char(io);
3728 }
3729 
3730 
3731 /*
3732  * call-seq:
3733  * ios.each_codepoint {|c| block } -> ios
3734  * ios.codepoints {|c| block } -> ios
3735  * ios.each_codepoint -> an_enumerator
3736  * ios.codepoints -> an_enumerator
3737  *
3738  * Passes the <code>Integer</code> ordinal of each character in <i>ios</i>,
3739  * passing the codepoint as an argument. The stream must be opened for
3740  * reading or an <code>IOError</code> will be raised.
3741  *
3742  * If no block is given, an enumerator is returned instead.
3743  *
3744  */
3745 
3746 static VALUE
3747 rb_io_each_codepoint(VALUE io)
3748 {
3749  rb_io_t *fptr;
3750  rb_encoding *enc;
3751  unsigned int c;
3752  int r, n;
3753 
3754  RETURN_ENUMERATOR(io, 0, 0);
3755  GetOpenFile(io, fptr);
3757 
3758  READ_CHECK(fptr);
3759  if (NEED_READCONV(fptr)) {
3760  SET_BINARY_MODE(fptr);
3761  r = 1; /* no invalid char yet */
3762  for (;;) {
3763  make_readconv(fptr, 0);
3764  for (;;) {
3765  if (fptr->cbuf.len) {
3766  if (fptr->encs.enc)
3767  r = rb_enc_precise_mbclen(fptr->cbuf.ptr+fptr->cbuf.off,
3768  fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
3769  fptr->encs.enc);
3770  else
3772  if (!MBCLEN_NEEDMORE_P(r))
3773  break;
3774  if (fptr->cbuf.len == fptr->cbuf.capa) {
3775  rb_raise(rb_eIOError, "too long character");
3776  }
3777  }
3778  if (more_char(fptr) == MORE_CHAR_FINISHED) {
3779  clear_readconv(fptr);
3780  if (!MBCLEN_CHARFOUND_P(r)) {
3781  enc = fptr->encs.enc;
3782  goto invalid;
3783  }
3784  return io;
3785  }
3786  }
3787  if (MBCLEN_INVALID_P(r)) {
3788  enc = fptr->encs.enc;
3789  goto invalid;
3790  }
3791  n = MBCLEN_CHARFOUND_LEN(r);
3792  if (fptr->encs.enc) {
3793  c = rb_enc_codepoint(fptr->cbuf.ptr+fptr->cbuf.off,
3794  fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
3795  fptr->encs.enc);
3796  }
3797  else {
3798  c = (unsigned char)fptr->cbuf.ptr[fptr->cbuf.off];
3799  }
3800  fptr->cbuf.off += n;
3801  fptr->cbuf.len -= n;
3802  rb_yield(UINT2NUM(c));
3803  }
3804  }
3806  enc = io_input_encoding(fptr);
3807  while (io_fillbuf(fptr) >= 0) {
3808  r = rb_enc_precise_mbclen(fptr->rbuf.ptr+fptr->rbuf.off,
3809  fptr->rbuf.ptr+fptr->rbuf.off+fptr->rbuf.len, enc);
3810  if (MBCLEN_CHARFOUND_P(r) &&
3811  (n = MBCLEN_CHARFOUND_LEN(r)) <= fptr->rbuf.len) {
3812  c = rb_enc_codepoint(fptr->rbuf.ptr+fptr->rbuf.off,
3813  fptr->rbuf.ptr+fptr->rbuf.off+fptr->rbuf.len, enc);
3814  fptr->rbuf.off += n;
3815  fptr->rbuf.len -= n;
3816  rb_yield(UINT2NUM(c));
3817  }
3818  else if (MBCLEN_INVALID_P(r)) {
3819  invalid:
3820  rb_raise(rb_eArgError, "invalid byte sequence in %s", rb_enc_name(enc));
3821  }
3822  else if (MBCLEN_NEEDMORE_P(r)) {
3823  char cbuf[8], *p = cbuf;
3824  int more = MBCLEN_NEEDMORE_LEN(r);
3825  if (more > numberof(cbuf)) goto invalid;
3826  more += n = fptr->rbuf.len;
3827  if (more > numberof(cbuf)) goto invalid;
3828  while ((n = (int)read_buffered_data(p, more, fptr)) > 0 &&
3829  (p += n, (more -= n) > 0)) {
3830  if (io_fillbuf(fptr) < 0) goto invalid;
3831  if ((n = fptr->rbuf.len) > more) n = more;
3832  }
3833  r = rb_enc_precise_mbclen(cbuf, p, enc);
3834  if (!MBCLEN_CHARFOUND_P(r)) goto invalid;
3835  c = rb_enc_codepoint(cbuf, p, enc);
3836  rb_yield(UINT2NUM(c));
3837  }
3838  else {
3839  continue;
3840  }
3841  }
3842  return io;
3843 }
3844 
3845 /*
3846  * This is a deprecated alias for <code>each_codepoint</code>.
3847  */
3848 
3849 static VALUE
3850 rb_io_codepoints(VALUE io)
3851 {
3852  rb_warn("IO#codepoints is deprecated; use #each_codepoint instead");
3853  if (!rb_block_given_p())
3854  return rb_enumeratorize(io, ID2SYM(rb_intern("each_codepoint")), 0, 0);
3855  return rb_io_each_codepoint(io);
3856 }
3857 
3858 
3859 /*
3860  * call-seq:
3861  * ios.getc -> string or nil
3862  *
3863  * Reads a one-character string from <em>ios</em>. Returns
3864  * +nil+ if called at end of file.
3865  *
3866  * f = File.new("testfile")
3867  * f.getc #=> "h"
3868  * f.getc #=> "e"
3869  */
3870 
3871 static VALUE
3872 rb_io_getc(VALUE io)
3873 {
3874  rb_io_t *fptr;
3875  rb_encoding *enc;
3876 
3877  GetOpenFile(io, fptr);
3879 
3880  enc = io_input_encoding(fptr);
3881  READ_CHECK(fptr);
3882  return io_getc(fptr, enc);
3883 }
3884 
3885 /*
3886  * call-seq:
3887  * ios.readchar -> string
3888  *
3889  * Reads a one-character string from <em>ios</em>. Raises an
3890  * <code>EOFError</code> on end of file.
3891  *
3892  * f = File.new("testfile")
3893  * f.readchar #=> "h"
3894  * f.readchar #=> "e"
3895  */
3896 
3897 static VALUE
3898 rb_io_readchar(VALUE io)
3899 {
3900  VALUE c = rb_io_getc(io);
3901 
3902  if (NIL_P(c)) {
3903  rb_eof_error();
3904  }
3905  return c;
3906 }
3907 
3908 /*
3909  * call-seq:
3910  * ios.getbyte -> integer or nil
3911  *
3912  * Gets the next 8-bit byte (0..255) from <em>ios</em>. Returns
3913  * +nil+ if called at end of file.
3914  *
3915  * f = File.new("testfile")
3916  * f.getbyte #=> 84
3917  * f.getbyte #=> 104
3918  */
3919 
3920 VALUE
3922 {
3923  rb_io_t *fptr;
3924  int c;
3925 
3926  GetOpenFile(io, fptr);
3928  READ_CHECK(fptr);
3929  if (fptr->fd == 0 && (fptr->mode & FMODE_TTY) && RB_TYPE_P(rb_stdout, T_FILE)) {
3930  rb_io_t *ofp;
3931  GetOpenFile(rb_stdout, ofp);
3932  if (ofp->mode & FMODE_TTY) {
3934  }
3935  }
3936  if (io_fillbuf(fptr) < 0) {
3937  return Qnil;
3938  }
3939  fptr->rbuf.off++;
3940  fptr->rbuf.len--;
3941  c = (unsigned char)fptr->rbuf.ptr[fptr->rbuf.off-1];
3942  return INT2FIX(c & 0xff);
3943 }
3944 
3945 /*
3946  * call-seq:
3947  * ios.readbyte -> integer
3948  *
3949  * Reads a byte as with <code>IO#getbyte</code>, but raises an
3950  * <code>EOFError</code> on end of file.
3951  */
3952 
3953 static VALUE
3954 rb_io_readbyte(VALUE io)
3955 {
3956  VALUE c = rb_io_getbyte(io);
3957 
3958  if (NIL_P(c)) {
3959  rb_eof_error();
3960  }
3961  return c;
3962 }
3963 
3964 /*
3965  * call-seq:
3966  * ios.ungetbyte(string) -> nil
3967  * ios.ungetbyte(integer) -> nil
3968  *
3969  * Pushes back bytes (passed as a parameter) onto <em>ios</em>,
3970  * such that a subsequent buffered read will return it. Only one byte
3971  * may be pushed back before a subsequent read operation (that is,
3972  * you will be able to read only the last of several bytes that have been pushed
3973  * back). Has no effect with unbuffered reads (such as <code>IO#sysread</code>).
3974  *
3975  * f = File.new("testfile") #=> #<File:testfile>
3976  * b = f.getbyte #=> 0x38
3977  * f.ungetbyte(b) #=> nil
3978  * f.getbyte #=> 0x38
3979  */
3980 
3981 VALUE
3983 {
3984  rb_io_t *fptr;
3985 
3986  GetOpenFile(io, fptr);
3988  if (NIL_P(b)) return Qnil;
3989  if (FIXNUM_P(b)) {
3990  char cc = FIX2INT(b);
3991  b = rb_str_new(&cc, 1);
3992  }
3993  else {
3994  SafeStringValue(b);
3995  }
3996  io_ungetbyte(b, fptr);
3997  return Qnil;
3998 }
3999 
4000 /*
4001  * call-seq:
4002  * ios.ungetc(string) -> nil
4003  *
4004  * Pushes back one character (passed as a parameter) onto <em>ios</em>,
4005  * such that a subsequent buffered character read will return it. Only one character
4006  * may be pushed back before a subsequent read operation (that is,
4007  * you will be able to read only the last of several characters that have been pushed
4008  * back). Has no effect with unbuffered reads (such as <code>IO#sysread</code>).
4009  *
4010  * f = File.new("testfile") #=> #<File:testfile>
4011  * c = f.getc #=> "8"
4012  * f.ungetc(c) #=> nil
4013  * f.getc #=> "8"
4014  */
4015 
4016 VALUE
4018 {
4019  rb_io_t *fptr;
4020  long len;
4021 
4022  GetOpenFile(io, fptr);
4024  if (NIL_P(c)) return Qnil;
4025  if (FIXNUM_P(c)) {
4026  c = rb_enc_uint_chr(FIX2UINT(c), io_read_encoding(fptr));
4027  }
4028  else if (RB_TYPE_P(c, T_BIGNUM)) {
4029  c = rb_enc_uint_chr(NUM2UINT(c), io_read_encoding(fptr));
4030  }
4031  else {
4032  SafeStringValue(c);
4033  }
4034  if (NEED_READCONV(fptr)) {
4035  SET_BINARY_MODE(fptr);
4036  len = RSTRING_LEN(c);
4037 #if SIZEOF_LONG > SIZEOF_INT
4038  if (len > INT_MAX)
4039  rb_raise(rb_eIOError, "ungetc failed");
4040 #endif
4041  make_readconv(fptr, (int)len);
4042  if (fptr->cbuf.capa - fptr->cbuf.len < len)
4043  rb_raise(rb_eIOError, "ungetc failed");
4044  if (fptr->cbuf.off < len) {
4045  MEMMOVE(fptr->cbuf.ptr+fptr->cbuf.capa-fptr->cbuf.len,
4046  fptr->cbuf.ptr+fptr->cbuf.off,
4047  char, fptr->cbuf.len);
4048  fptr->cbuf.off = fptr->cbuf.capa-fptr->cbuf.len;
4049  }
4050  fptr->cbuf.off -= (int)len;
4051  fptr->cbuf.len += (int)len;
4052  MEMMOVE(fptr->cbuf.ptr+fptr->cbuf.off, RSTRING_PTR(c), char, len);
4053  }
4054  else {
4056  io_ungetbyte(c, fptr);
4057  }
4058  return Qnil;
4059 }
4060 
4061 /*
4062  * call-seq:
4063  * ios.isatty -> true or false
4064  * ios.tty? -> true or false
4065  *
4066  * Returns <code>true</code> if <em>ios</em> is associated with a
4067  * terminal device (tty), <code>false</code> otherwise.
4068  *
4069  * File.new("testfile").isatty #=> false
4070  * File.new("/dev/tty").isatty #=> true
4071  */
4072 
4073 static VALUE
4074 rb_io_isatty(VALUE io)
4075 {
4076  rb_io_t *fptr;
4077 
4078  GetOpenFile(io, fptr);
4079  if (isatty(fptr->fd) == 0)
4080  return Qfalse;
4081  return Qtrue;
4082 }
4083 
4084 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
4085 /*
4086  * call-seq:
4087  * ios.close_on_exec? -> true or false
4088  *
4089  * Returns <code>true</code> if <em>ios</em> will be closed on exec.
4090  *
4091  * f = open("/dev/null")
4092  * f.close_on_exec? #=> false
4093  * f.close_on_exec = true
4094  * f.close_on_exec? #=> true
4095  * f.close_on_exec = false
4096  * f.close_on_exec? #=> false
4097  */
4098 
4099 static VALUE
4101 {
4102  rb_io_t *fptr;
4103  VALUE write_io;
4104  int fd, ret;
4105 
4106  write_io = GetWriteIO(io);
4107  if (io != write_io) {
4108  GetOpenFile(write_io, fptr);
4109  if (fptr && 0 <= (fd = fptr->fd)) {
4110  if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
4111  if (!(ret & FD_CLOEXEC)) return Qfalse;
4112  }
4113  }
4114 
4115  GetOpenFile(io, fptr);
4116  if (fptr && 0 <= (fd = fptr->fd)) {
4117  if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
4118  if (!(ret & FD_CLOEXEC)) return Qfalse;
4119  }
4120  return Qtrue;
4121 }
4122 #else
4123 #define rb_io_close_on_exec_p rb_f_notimplement
4124 #endif
4125 
4126 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
4127 /*
4128  * call-seq:
4129  * ios.close_on_exec = bool -> true or false
4130  *
4131  * Sets a close-on-exec flag.
4132  *
4133  * f = open("/dev/null")
4134  * f.close_on_exec = true
4135  * system("cat", "/proc/self/fd/#{f.fileno}") # cat: /proc/self/fd/3: No such file or directory
4136  * f.closed? #=> false
4137  *
4138  * Ruby sets close-on-exec flags of all file descriptors by default
4139  * since Ruby 2.0.0.
4140  * So you don't need to set by yourself.
4141  * Also, unsetting a close-on-exec flag can cause file descriptor leak
4142  * if another thread use fork() and exec() (via system() method for example).
4143  * If you really needs file descriptor inheritance to child process,
4144  * use spawn()'s argument such as fd=>fd.
4145  */
4146 
4147 static VALUE
4149 {
4150  int flag = RTEST(arg) ? FD_CLOEXEC : 0;
4151  rb_io_t *fptr;
4152  VALUE write_io;
4153  int fd, ret;
4154 
4155  write_io = GetWriteIO(io);
4156  if (io != write_io) {
4157  GetOpenFile(write_io, fptr);
4158  if (fptr && 0 <= (fd = fptr->fd)) {
4159  if ((ret = fcntl(fptr->fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
4160  if ((ret & FD_CLOEXEC) != flag) {
4161  ret = (ret & ~FD_CLOEXEC) | flag;
4162  ret = fcntl(fd, F_SETFD, ret);
4163  if (ret == -1) rb_sys_fail_path(fptr->pathv);
4164  }
4165  }
4166 
4167  }
4168 
4169  GetOpenFile(io, fptr);
4170  if (fptr && 0 <= (fd = fptr->fd)) {
4171  if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
4172  if ((ret & FD_CLOEXEC) != flag) {
4173  ret = (ret & ~FD_CLOEXEC) | flag;
4174  ret = fcntl(fd, F_SETFD, ret);
4175  if (ret == -1) rb_sys_fail_path(fptr->pathv);
4176  }
4177  }
4178  return Qnil;
4179 }
4180 #else
4181 #define rb_io_set_close_on_exec rb_f_notimplement
4182 #endif
4183 
4184 #define FMODE_PREP (1<<16)
4185 #define IS_PREP_STDIO(f) ((f)->mode & FMODE_PREP)
4186 #define PREP_STDIO_NAME(f) (RSTRING_PTR((f)->pathv))
4187 
4188 static VALUE
4189 finish_writeconv(rb_io_t *fptr, int noalloc)
4190 {
4191  unsigned char *ds, *dp, *de;
4192  rb_econv_result_t res;
4193 
4194  if (!fptr->wbuf.ptr) {
4195  unsigned char buf[1024];
4196  long r;
4197 
4199  while (res == econv_destination_buffer_full) {
4200  ds = dp = buf;
4201  de = buf + sizeof(buf);
4202  res = rb_econv_convert(fptr->writeconv, NULL, NULL, &dp, de, 0);
4203  while (dp-ds) {
4204  retry:
4205  if (fptr->write_lock && rb_mutex_owned_p(fptr->write_lock))
4206  r = rb_write_internal2(fptr->fd, ds, dp-ds);
4207  else
4208  r = rb_write_internal(fptr->fd, ds, dp-ds);
4209  if (r == dp-ds)
4210  break;
4211  if (0 <= r) {
4212  ds += r;
4213  }
4214  if (rb_io_wait_writable(fptr->fd)) {
4215  if (fptr->fd < 0)
4216  return noalloc ? Qtrue : rb_exc_new3(rb_eIOError, rb_str_new_cstr(closed_stream));
4217  goto retry;
4218  }
4219  return noalloc ? Qtrue : INT2NUM(errno);
4220  }
4221  if (res == econv_invalid_byte_sequence ||
4222  res == econv_incomplete_input ||
4223  res == econv_undefined_conversion) {
4224  return noalloc ? Qtrue : rb_econv_make_exception(fptr->writeconv);
4225  }
4226  }
4227 
4228  return Qnil;
4229  }
4230 
4232  while (res == econv_destination_buffer_full) {
4233  if (fptr->wbuf.len == fptr->wbuf.capa) {
4234  if (io_fflush(fptr) < 0)
4235  return noalloc ? Qtrue : INT2NUM(errno);
4236  }
4237 
4238  ds = dp = (unsigned char *)fptr->wbuf.ptr + fptr->wbuf.off + fptr->wbuf.len;
4239  de = (unsigned char *)fptr->wbuf.ptr + fptr->wbuf.capa;
4240  res = rb_econv_convert(fptr->writeconv, NULL, NULL, &dp, de, 0);
4241  fptr->wbuf.len += (int)(dp - ds);
4242  if (res == econv_invalid_byte_sequence ||
4243  res == econv_incomplete_input ||
4244  res == econv_undefined_conversion) {
4245  return noalloc ? Qtrue : rb_econv_make_exception(fptr->writeconv);
4246  }
4247  }
4248  return Qnil;
4249 }
4250 
4253  int noalloc;
4254 };
4255 
4256 static VALUE
4257 finish_writeconv_sync(VALUE arg)
4258 {
4259  struct finish_writeconv_arg *p = (struct finish_writeconv_arg *)arg;
4260  return finish_writeconv(p->fptr, p->noalloc);
4261 }
4262 
4263 static void*
4264 nogvl_close(void *ptr)
4265 {
4266  int *fd = ptr;
4267 
4268  return (void*)(intptr_t)close(*fd);
4269 }
4270 
4271 static int
4272 maygvl_close(int fd, int keepgvl)
4273 {
4274  if (keepgvl)
4275  return close(fd);
4276 
4277  /*
4278  * close() may block for certain file types (NFS, SO_LINGER sockets,
4279  * inotify), so let other threads run.
4280  */
4281  return (int)(intptr_t)rb_thread_call_without_gvl(nogvl_close, &fd, RUBY_UBF_IO, 0);
4282 }
4283 
4284 static void*
4285 nogvl_fclose(void *ptr)
4286 {
4287  FILE *file = ptr;
4288 
4289  return (void*)(intptr_t)fclose(file);
4290 }
4291 
4292 static int
4293 maygvl_fclose(FILE *file, int keepgvl)
4294 {
4295  if (keepgvl)
4296  return fclose(file);
4297 
4298  return (int)(intptr_t)rb_thread_call_without_gvl(nogvl_fclose, file, RUBY_UBF_IO, 0);
4299 }
4300 
4301 static void free_io_buffer(rb_io_buffer_t *buf);
4302 static void clear_codeconv(rb_io_t *fptr);
4303 
4304 static void
4305 fptr_finalize_flush(rb_io_t *fptr, int noraise, int keepgvl)
4306 {
4307  VALUE err = Qnil;
4308  int fd = fptr->fd;
4309  FILE *stdio_file = fptr->stdio_file;
4310  int mode = fptr->mode;
4311 
4312  if (fptr->writeconv) {
4313  if (fptr->write_lock && !noraise) {
4314  struct finish_writeconv_arg arg;
4315  arg.fptr = fptr;
4316  arg.noalloc = noraise;
4317  err = rb_mutex_synchronize(fptr->write_lock, finish_writeconv_sync, (VALUE)&arg);
4318  }
4319  else {
4320  err = finish_writeconv(fptr, noraise);
4321  }
4322  }
4323  if (fptr->wbuf.len) {
4324  if (noraise) {
4325  if ((int)io_flush_buffer_sync(fptr) < 0 && NIL_P(err))
4326  err = Qtrue;
4327  }
4328  else {
4329  if (io_fflush(fptr) < 0 && NIL_P(err))
4330  err = INT2NUM(errno);
4331  }
4332  }
4333 
4334  fptr->fd = -1;
4335  fptr->stdio_file = 0;
4336  fptr->mode &= ~(FMODE_READABLE|FMODE_WRITABLE);
4337 
4338  if (IS_PREP_STDIO(fptr) || fd <= 2) {
4339  /* need to keep FILE objects of stdin, stdout and stderr */
4340  }
4341  else if (stdio_file) {
4342  /* stdio_file is deallocated anyway
4343  * even if fclose failed. */
4344  if ((maygvl_fclose(stdio_file, noraise) < 0) && NIL_P(err))
4345  err = noraise ? Qtrue : INT2NUM(errno);
4346  }
4347  else if (0 <= fd) {
4348  /* fptr->fd may be closed even if close fails.
4349  * POSIX doesn't specify it.
4350  * We assumes it is closed. */
4351 
4352 
4353  keepgvl |= !(mode & FMODE_WRITABLE);
4354  keepgvl |= noraise;
4355  if ((maygvl_close(fd, keepgvl) < 0) && NIL_P(err))
4356  err = noraise ? Qtrue : INT2NUM(errno);
4357  }
4358 
4359  if (!NIL_P(err) && !noraise) {
4360  if (RB_INTEGER_TYPE_P(err))
4361  rb_syserr_fail_path(NUM2INT(err), fptr->pathv);
4362  else
4363  rb_exc_raise(err);
4364  }
4365 }
4366 
4367 static void
4368 fptr_finalize(rb_io_t *fptr, int noraise)
4369 {
4370  fptr_finalize_flush(fptr, noraise, FALSE);
4371  free_io_buffer(&fptr->rbuf);
4372  free_io_buffer(&fptr->wbuf);
4373  clear_codeconv(fptr);
4374 }
4375 
4376 static void
4377 rb_io_fptr_cleanup(rb_io_t *fptr, int noraise)
4378 {
4379  if (fptr->finalize) {
4380  (*fptr->finalize)(fptr, noraise);
4381  }
4382  else {
4383  fptr_finalize(fptr, noraise);
4384  }
4385 }
4386 
4387 static void
4388 free_io_buffer(rb_io_buffer_t *buf)
4389 {
4390  if (buf->ptr) {
4391  ruby_sized_xfree(buf->ptr, (size_t)buf->capa);
4392  buf->ptr = NULL;
4393  }
4394 }
4395 
4396 static void
4397 clear_readconv(rb_io_t *fptr)
4398 {
4399  if (fptr->readconv) {
4400  rb_econv_close(fptr->readconv);
4401  fptr->readconv = NULL;
4402  }
4403  free_io_buffer(&fptr->cbuf);
4404 }
4405 
4406 static void
4407 clear_writeconv(rb_io_t *fptr)
4408 {
4409  if (fptr->writeconv) {
4410  rb_econv_close(fptr->writeconv);
4411  fptr->writeconv = NULL;
4412  }
4413  fptr->writeconv_initialized = 0;
4414 }
4415 
4416 static void
4417 clear_codeconv(rb_io_t *fptr)
4418 {
4419  clear_readconv(fptr);
4420  clear_writeconv(fptr);
4421 }
4422 
4423 int
4425 {
4426  if (!fptr) return 0;
4427  fptr->pathv = Qnil;
4428  if (0 <= fptr->fd)
4429  rb_io_fptr_cleanup(fptr, TRUE);
4430  fptr->write_lock = 0;
4431  free_io_buffer(&fptr->rbuf);
4432  free_io_buffer(&fptr->wbuf);
4433  clear_codeconv(fptr);
4434  free(fptr);
4435  return 1;
4436 }
4437 
4438 RUBY_FUNC_EXPORTED size_t
4440 {
4441  size_t size = sizeof(rb_io_t);
4442  size += fptr->rbuf.capa;
4443  size += fptr->wbuf.capa;
4444  size += fptr->cbuf.capa;
4445  if (fptr->readconv) size += rb_econv_memsize(fptr->readconv);
4446  if (fptr->writeconv) size += rb_econv_memsize(fptr->writeconv);
4447  return size;
4448 }
4449 
4450 #ifdef _WIN32
4451 /* keep GVL while closing to prevent crash on Windows */
4452 # define KEEPGVL TRUE
4453 #else
4454 # define KEEPGVL FALSE
4455 #endif
4456 
4457 int rb_notify_fd_close(int fd);
4458 static rb_io_t *
4459 io_close_fptr(VALUE io)
4460 {
4461  rb_io_t *fptr;
4462  int fd;
4463  VALUE write_io;
4464  rb_io_t *write_fptr;
4465  int busy;
4466 
4467  write_io = GetWriteIO(io);
4468  if (io != write_io) {
4469  write_fptr = RFILE(write_io)->fptr;
4470  if (write_fptr && 0 <= write_fptr->fd) {
4471  rb_io_fptr_cleanup(write_fptr, TRUE);
4472  }
4473  }
4474 
4475  fptr = RFILE(io)->fptr;
4476  if (!fptr) return 0;
4477  if (fptr->fd < 0) return 0;
4478 
4479  fd = fptr->fd;
4480  busy = rb_notify_fd_close(fd);
4481  if (busy) {
4482  fptr_finalize_flush(fptr, FALSE, KEEPGVL);
4483  do rb_thread_schedule(); while (rb_notify_fd_close(fd));
4484  }
4485  rb_io_fptr_cleanup(fptr, FALSE);
4486  return fptr;
4487 }
4488 
4489 static void
4490 fptr_waitpid(rb_io_t *fptr, int nohang)
4491 {
4492  int status;
4493  if (fptr->pid) {
4495  rb_waitpid(fptr->pid, &status, nohang ? WNOHANG : 0);
4496  fptr->pid = 0;
4497  }
4498 }
4499 
4500 VALUE
4502 {
4503  rb_io_t *fptr = io_close_fptr(io);
4504  if (fptr) fptr_waitpid(fptr, 0);
4505  return Qnil;
4506 }
4507 
4508 /*
4509  * call-seq:
4510  * ios.close -> nil
4511  *
4512  * Closes <em>ios</em> and flushes any pending writes to the operating
4513  * system. The stream is unavailable for any further data operations;
4514  * an <code>IOError</code> is raised if such an attempt is made. I/O
4515  * streams are automatically closed when they are claimed by the
4516  * garbage collector.
4517  *
4518  * If <em>ios</em> is opened by <code>IO.popen</code>,
4519  * <code>close</code> sets <code>$?</code>.
4520  *
4521  * Calling this method on closed IO object is just ignored since Ruby 2.3.
4522  */
4523 
4524 static VALUE
4525 rb_io_close_m(VALUE io)
4526 {
4527  rb_io_t *fptr = rb_io_get_fptr(io);
4528  if (fptr->fd < 0) {
4529  return Qnil;
4530  }
4531  rb_io_close(io);
4532  return Qnil;
4533 }
4534 
4535 static VALUE
4536 io_call_close(VALUE io)
4537 {
4538  rb_check_funcall(io, rb_intern("close"), 0, 0);
4539  return io;
4540 }
4541 
4542 static VALUE
4543 ignore_closed_stream(VALUE io, VALUE exc)
4544 {
4545  enum {mesg_len = sizeof(closed_stream)-1};
4546  VALUE mesg = rb_attr_get(exc, rb_intern("mesg"));
4547  if (!RB_TYPE_P(mesg, T_STRING) ||
4548  RSTRING_LEN(mesg) != mesg_len ||
4549  memcmp(RSTRING_PTR(mesg), closed_stream, mesg_len)) {
4550  rb_exc_raise(exc);
4551  }
4552  return io;
4553 }
4554 
4555 static VALUE
4556 io_close(VALUE io)
4557 {
4558  VALUE closed = rb_check_funcall(io, rb_intern("closed?"), 0, 0);
4559  if (closed != Qundef && RTEST(closed)) return io;
4560  rb_rescue2(io_call_close, io, ignore_closed_stream, io,
4561  rb_eIOError, (VALUE)0);
4562  return io;
4563 }
4564 
4565 /*
4566  * call-seq:
4567  * ios.closed? -> true or false
4568  *
4569  * Returns <code>true</code> if <em>ios</em> is completely closed (for
4570  * duplex streams, both reader and writer), <code>false</code>
4571  * otherwise.
4572  *
4573  * f = File.new("testfile")
4574  * f.close #=> nil
4575  * f.closed? #=> true
4576  * f = IO.popen("/bin/sh","r+")
4577  * f.close_write #=> nil
4578  * f.closed? #=> false
4579  * f.close_read #=> nil
4580  * f.closed? #=> true
4581  */
4582 
4583 
4584 static VALUE
4585 rb_io_closed(VALUE io)
4586 {
4587  rb_io_t *fptr;
4588  VALUE write_io;
4589  rb_io_t *write_fptr;
4590 
4591  write_io = GetWriteIO(io);
4592  if (io != write_io) {
4593  write_fptr = RFILE(write_io)->fptr;
4594  if (write_fptr && 0 <= write_fptr->fd) {
4595  return Qfalse;
4596  }
4597  }
4598 
4599  fptr = rb_io_get_fptr(io);
4600  return 0 <= fptr->fd ? Qfalse : Qtrue;
4601 }
4602 
4603 /*
4604  * call-seq:
4605  * ios.close_read -> nil
4606  *
4607  * Closes the read end of a duplex I/O stream (i.e., one that contains
4608  * both a read and a write stream, such as a pipe). Will raise an
4609  * <code>IOError</code> if the stream is not duplexed.
4610  *
4611  * f = IO.popen("/bin/sh","r+")
4612  * f.close_read
4613  * f.readlines
4614  *
4615  * <em>produces:</em>
4616  *
4617  * prog.rb:3:in `readlines': not opened for reading (IOError)
4618  * from prog.rb:3
4619  */
4620 
4621 static VALUE
4622 rb_io_close_read(VALUE io)
4623 {
4624  rb_io_t *fptr;
4625  VALUE write_io;
4626 
4627  fptr = rb_io_get_fptr(rb_io_taint_check(io));
4628  if (fptr->fd < 0) return Qnil;
4629  if (is_socket(fptr->fd, fptr->pathv)) {
4630 #ifndef SHUT_RD
4631 # define SHUT_RD 0
4632 #endif
4633  if (shutdown(fptr->fd, SHUT_RD) < 0)
4634  rb_sys_fail_path(fptr->pathv);
4635  fptr->mode &= ~FMODE_READABLE;
4636  if (!(fptr->mode & FMODE_WRITABLE))
4637  return rb_io_close(io);
4638  return Qnil;
4639  }
4640 
4641  write_io = GetWriteIO(io);
4642  if (io != write_io) {
4643  rb_io_t *wfptr;
4644  wfptr = rb_io_get_fptr(rb_io_taint_check(write_io));
4645  wfptr->pid = fptr->pid;
4646  fptr->pid = 0;
4647  RFILE(io)->fptr = wfptr;
4648  /* bind to write_io temporarily to get rid of memory/fd leak */
4649  fptr->tied_io_for_writing = 0;
4650  RFILE(write_io)->fptr = fptr;
4651  rb_io_fptr_cleanup(fptr, FALSE);
4652  /* should not finalize fptr because another thread may be reading it */
4653  return Qnil;
4654  }
4655 
4656  if ((fptr->mode & (FMODE_DUPLEX|FMODE_WRITABLE)) == FMODE_WRITABLE) {
4657  rb_raise(rb_eIOError, "closing non-duplex IO for reading");
4658  }
4659  return rb_io_close(io);
4660 }
4661 
4662 /*
4663  * call-seq:
4664  * ios.close_write -> nil
4665  *
4666  * Closes the write end of a duplex I/O stream (i.e., one that contains
4667  * both a read and a write stream, such as a pipe). Will raise an
4668  * <code>IOError</code> if the stream is not duplexed.
4669  *
4670  * f = IO.popen("/bin/sh","r+")
4671  * f.close_write
4672  * f.print "nowhere"
4673  *
4674  * <em>produces:</em>
4675  *
4676  * prog.rb:3:in `write': not opened for writing (IOError)
4677  * from prog.rb:3:in `print'
4678  * from prog.rb:3
4679  */
4680 
4681 static VALUE
4682 rb_io_close_write(VALUE io)
4683 {
4684  rb_io_t *fptr;
4685  VALUE write_io;
4686 
4687  write_io = GetWriteIO(io);
4688  fptr = rb_io_get_fptr(rb_io_taint_check(write_io));
4689  if (fptr->fd < 0) return Qnil;
4690  if (is_socket(fptr->fd, fptr->pathv)) {
4691 #ifndef SHUT_WR
4692 # define SHUT_WR 1
4693 #endif
4694  if (shutdown(fptr->fd, SHUT_WR) < 0)
4695  rb_sys_fail_path(fptr->pathv);
4696  fptr->mode &= ~FMODE_WRITABLE;
4697  if (!(fptr->mode & FMODE_READABLE))
4698  return rb_io_close(write_io);
4699  return Qnil;
4700  }
4701 
4702  if ((fptr->mode & (FMODE_DUPLEX|FMODE_READABLE)) == FMODE_READABLE) {
4703  rb_raise(rb_eIOError, "closing non-duplex IO for writing");
4704  }
4705 
4706  if (io != write_io) {
4707  fptr = rb_io_get_fptr(rb_io_taint_check(io));
4708  fptr->tied_io_for_writing = 0;
4709  }
4710  rb_io_close(write_io);
4711  return Qnil;
4712 }
4713 
4714 /*
4715  * call-seq:
4716  * ios.sysseek(offset, whence=IO::SEEK_SET) -> integer
4717  *
4718  * Seeks to a given <i>offset</i> in the stream according to the value
4719  * of <i>whence</i> (see <code>IO#seek</code> for values of
4720  * <i>whence</i>). Returns the new offset into the file.
4721  *
4722  * f = File.new("testfile")
4723  * f.sysseek(-13, IO::SEEK_END) #=> 53
4724  * f.sysread(10) #=> "And so on."
4725  */
4726 
4727 static VALUE
4728 rb_io_sysseek(int argc, VALUE *argv, VALUE io)
4729 {
4730  VALUE offset, ptrname;
4731  int whence = SEEK_SET;
4732  rb_io_t *fptr;
4733  off_t pos;
4734 
4735  if (rb_scan_args(argc, argv, "11", &offset, &ptrname) == 2) {
4736  whence = interpret_seek_whence(ptrname);
4737  }
4738  pos = NUM2OFFT(offset);
4739  GetOpenFile(io, fptr);
4740  if ((fptr->mode & FMODE_READABLE) &&
4741  (READ_DATA_BUFFERED(fptr) || READ_CHAR_PENDING(fptr))) {
4742  rb_raise(rb_eIOError, "sysseek for buffered IO");
4743  }
4744  if ((fptr->mode & FMODE_WRITABLE) && fptr->wbuf.len) {
4745  rb_warn("sysseek for buffered IO");
4746  }
4747  errno = 0;
4748  pos = lseek(fptr->fd, pos, whence);
4749  if (pos == -1 && errno) rb_sys_fail_path(fptr->pathv);
4750 
4751  return OFFT2NUM(pos);
4752 }
4753 
4754 /*
4755  * call-seq:
4756  * ios.syswrite(string) -> integer
4757  *
4758  * Writes the given string to <em>ios</em> using a low-level write.
4759  * Returns the number of bytes written. Do not mix with other methods
4760  * that write to <em>ios</em> or you may get unpredictable results.
4761  * Raises <code>SystemCallError</code> on error.
4762  *
4763  * f = File.new("out", "w")
4764  * f.syswrite("ABCDEF") #=> 6
4765  */
4766 
4767 static VALUE
4768 rb_io_syswrite(VALUE io, VALUE str)
4769 {
4770  VALUE tmp;
4771  rb_io_t *fptr;
4772  long n, len;
4773  const char *ptr;
4774 
4775  if (!RB_TYPE_P(str, T_STRING))
4776  str = rb_obj_as_string(str);
4777 
4778  io = GetWriteIO(io);
4779  GetOpenFile(io, fptr);
4780  rb_io_check_writable(fptr);
4781 
4782  if (fptr->wbuf.len) {
4783  rb_warn("syswrite for buffered IO");
4784  }
4785 
4786  tmp = rb_str_tmp_frozen_acquire(str);
4787  RSTRING_GETMEM(tmp, ptr, len);
4788  n = rb_write_internal(fptr->fd, ptr, len);
4789  if (n == -1) rb_sys_fail_path(fptr->pathv);
4790  rb_str_tmp_frozen_release(str, tmp);
4791 
4792  return LONG2FIX(n);
4793 }
4794 
4795 /*
4796  * call-seq:
4797  * ios.sysread(maxlen[, outbuf]) -> string
4798  *
4799  * Reads <i>maxlen</i> bytes from <em>ios</em> using a low-level
4800  * read and returns them as a string. Do not mix with other methods
4801  * that read from <em>ios</em> or you may get unpredictable results.
4802  *
4803  * If the optional _outbuf_ argument is present,
4804  * it must reference a String, which will receive the data.
4805  * The _outbuf_ will contain only the received data after the method call
4806  * even if it is not empty at the beginning.
4807  *
4808  * Raises <code>SystemCallError</code> on error and
4809  * <code>EOFError</code> at end of file.
4810  *
4811  * f = File.new("testfile")
4812  * f.sysread(16) #=> "This is line one"
4813  */
4814 
4815 static VALUE
4816 rb_io_sysread(int argc, VALUE *argv, VALUE io)
4817 {
4818  VALUE len, str;
4819  rb_io_t *fptr;
4820  long n, ilen;
4821  struct read_internal_arg arg;
4822  int shrinkable;
4823 
4824  rb_scan_args(argc, argv, "11", &len, &str);
4825  ilen = NUM2LONG(len);
4826 
4827  shrinkable = io_setstrbuf(&str, ilen);
4828  if (ilen == 0) return str;
4829 
4830  GetOpenFile(io, fptr);
4832 
4833  if (READ_DATA_BUFFERED(fptr)) {
4834  rb_raise(rb_eIOError, "sysread for buffered IO");
4835  }
4836 
4837  /*
4838  * FIXME: removing rb_thread_wait_fd() here changes sysread semantics
4839  * on non-blocking IOs. However, it's still currently possible
4840  * for sysread to raise Errno::EAGAIN if another thread read()s
4841  * the IO after we return from rb_thread_wait_fd() but before
4842  * we call read()
4843  */
4844  rb_thread_wait_fd(fptr->fd);
4845 
4846  rb_io_check_closed(fptr);
4847 
4848  io_setstrbuf(&str, ilen);
4849  rb_str_locktmp(str);
4850  arg.fd = fptr->fd;
4851  arg.str_ptr = RSTRING_PTR(str);
4852  arg.len = ilen;
4853  rb_ensure(read_internal_call, (VALUE)&arg, rb_str_unlocktmp, str);
4854  n = arg.len;
4855 
4856  if (n == -1) {
4857  rb_sys_fail_path(fptr->pathv);
4858  }
4859  io_set_read_length(str, n, shrinkable);
4860  if (n == 0 && ilen > 0) {
4861  rb_eof_error();
4862  }
4863  OBJ_TAINT(str);
4864 
4865  return str;
4866 }
4867 
4868 #if defined(HAVE_PREAD) || defined(HAVE_PWRITE)
4869 struct prdwr_internal_arg {
4870  int fd;
4871  void *buf;
4872  size_t count;
4873  off_t offset;
4874 };
4875 #endif /* HAVE_PREAD || HAVE_PWRITE */
4876 
4877 #if defined(HAVE_PREAD)
4878 static VALUE
4879 internal_pread_func(void *arg)
4880 {
4881  struct prdwr_internal_arg *p = arg;
4882  return (VALUE)pread(p->fd, p->buf, p->count, p->offset);
4883 }
4884 
4885 static VALUE
4886 pread_internal_call(VALUE arg)
4887 {
4888  struct prdwr_internal_arg *p = (struct prdwr_internal_arg *)arg;
4889  return rb_thread_io_blocking_region(internal_pread_func, p, p->fd);
4890 }
4891 
4892 /*
4893  * call-seq:
4894  * ios.pread(maxlen, offset[, outbuf]) -> string
4895  *
4896  * Reads <i>maxlen</i> bytes from <em>ios</em> using the pread system call
4897  * and returns them as a string without modifying the underlying
4898  * descriptor offset. This is advantageous compared to combining IO#seek
4899  * and IO#read in that it is atomic, allowing multiple threads/process to
4900  * share the same IO object for reading the file at various locations.
4901  * This bypasses any userspace buffering of the IO layer.
4902  * If the optional <i>outbuf</i> argument is present, it must
4903  * reference a String, which will receive the data.
4904  * Raises <code>SystemCallError</code> on error, <code>EOFError</code>
4905  * at end of file and <code>NotImplementedError</code> if platform does not
4906  * implement the system call.
4907  *
4908  * f = File.new("testfile")
4909  * f.read #=> "This is line one\nThis is line two\n"
4910  * f.pread(12, 0) #=> "This is line"
4911  * f.pread(9, 8) #=> "line one\n"
4912  */
4913 static VALUE
4914 rb_io_pread(int argc, VALUE *argv, VALUE io)
4915 {
4916  VALUE len, offset, str;
4917  rb_io_t *fptr;
4918  ssize_t n;
4919  struct prdwr_internal_arg arg;
4920  int shrinkable;
4921 
4922  rb_scan_args(argc, argv, "21", &len, &offset, &str);
4923  arg.count = NUM2SIZET(len);
4924  arg.offset = NUM2OFFT(offset);
4925 
4926  shrinkable = io_setstrbuf(&str, (long)arg.count);
4927  if (arg.count == 0) return str;
4928  arg.buf = RSTRING_PTR(str);
4929 
4930  GetOpenFile(io, fptr);
4932 
4933  arg.fd = fptr->fd;
4934  rb_io_check_closed(fptr);
4935 
4936  rb_str_locktmp(str);
4937  n = (ssize_t)rb_ensure(pread_internal_call, (VALUE)&arg, rb_str_unlocktmp, str);
4938 
4939  if (n == -1) {
4940  rb_sys_fail_path(fptr->pathv);
4941  }
4942  io_set_read_length(str, n, shrinkable);
4943  if (n == 0 && arg.count > 0) {
4944  rb_eof_error();
4945  }
4946  OBJ_TAINT(str);
4947 
4948  return str;
4949 }
4950 #else
4951 # define rb_io_pread rb_f_notimplement
4952 #endif /* HAVE_PREAD */
4953 
4954 #if defined(HAVE_PWRITE)
4955 static VALUE
4956 internal_pwrite_func(void *ptr)
4957 {
4958  struct prdwr_internal_arg *arg = ptr;
4959 
4960  return (VALUE)pwrite(arg->fd, arg->buf, arg->count, arg->offset);
4961 }
4962 
4963 /*
4964  * call-seq:
4965  * ios.pwrite(string, offset) -> integer
4966  *
4967  * Writes the given string to <em>ios</em> at <i>offset</i> using pwrite()
4968  * system call. This is advantageous to combining IO#seek and IO#write
4969  * in that it is atomic, allowing multiple threads/process to share the
4970  * same IO object for reading the file at various locations.
4971  * This bypasses any userspace buffering of the IO layer.
4972  * Returns the number of bytes written.
4973  * Raises <code>SystemCallError</code> on error and <code>NotImplementedError</code>
4974  * if platform does not implement the system call.
4975  *
4976  * f = File.new("out", "w")
4977  * f.pwrite("ABCDEF", 3) #=> 6
4978  *
4979  * File.read("out") #=> "\u0000\u0000\u0000ABCDEF"
4980  */
4981 static VALUE
4982 rb_io_pwrite(VALUE io, VALUE str, VALUE offset)
4983 {
4984  rb_io_t *fptr;
4985  ssize_t n;
4986  struct prdwr_internal_arg arg;
4987 
4988  if (!RB_TYPE_P(str, T_STRING))
4989  str = rb_obj_as_string(str);
4990 
4991  arg.buf = RSTRING_PTR(str);
4992  arg.count = (size_t)RSTRING_LEN(str);
4993  arg.offset = NUM2OFFT(offset);
4994 
4995  io = GetWriteIO(io);
4996  GetOpenFile(io, fptr);
4997  rb_io_check_writable(fptr);
4998  arg.fd = fptr->fd;
4999 
5000  n = (ssize_t)rb_thread_io_blocking_region(internal_pwrite_func, &arg, fptr->fd);
5001  RB_GC_GUARD(str);
5002 
5003  if (n == -1) rb_sys_fail_path(fptr->pathv);
5004 
5005  return SSIZET2NUM(n);
5006 }
5007 #else
5008 # define rb_io_pwrite rb_f_notimplement
5009 #endif /* HAVE_PWRITE */
5010 
5011 VALUE
5013 {
5014  rb_io_t *fptr;
5015 
5016  GetOpenFile(io, fptr);
5017  if (fptr->readconv)
5018  rb_econv_binmode(fptr->readconv);
5019  if (fptr->writeconv)
5020  rb_econv_binmode(fptr->writeconv);
5021  fptr->mode |= FMODE_BINMODE;
5022  fptr->mode &= ~FMODE_TEXTMODE;
5024 #ifdef O_BINARY
5025  if (!fptr->readconv) {
5027  }
5028  else {
5029  setmode(fptr->fd, O_BINARY);
5030  }
5031 #endif
5032  return io;
5033 }
5034 
5035 static void
5036 io_ascii8bit_binmode(rb_io_t *fptr)
5037 {
5038  if (fptr->readconv) {
5039  rb_econv_close(fptr->readconv);
5040  fptr->readconv = NULL;
5041  }
5042  if (fptr->writeconv) {
5043  rb_econv_close(fptr->writeconv);
5044  fptr->writeconv = NULL;
5045  }
5046  fptr->mode |= FMODE_BINMODE;
5047  fptr->mode &= ~FMODE_TEXTMODE;
5049 
5050  fptr->encs.enc = rb_ascii8bit_encoding();
5051  fptr->encs.enc2 = NULL;
5052  fptr->encs.ecflags = 0;
5053  fptr->encs.ecopts = Qnil;
5054  clear_codeconv(fptr);
5055 }
5056 
5057 VALUE
5059 {
5060  rb_io_t *fptr;
5061 
5062  GetOpenFile(io, fptr);
5063  io_ascii8bit_binmode(fptr);
5064 
5065  return io;
5066 }
5067 
5068 /*
5069  * call-seq:
5070  * ios.binmode -> ios
5071  *
5072  * Puts <em>ios</em> into binary mode.
5073  * Once a stream is in binary mode, it cannot be reset to nonbinary mode.
5074  *
5075  * - newline conversion disabled
5076  * - encoding conversion disabled
5077  * - content is treated as ASCII-8BIT
5078  */
5079 
5080 static VALUE
5081 rb_io_binmode_m(VALUE io)
5082 {
5083  VALUE write_io;
5084 
5086 
5087  write_io = GetWriteIO(io);
5088  if (write_io != io)
5089  rb_io_ascii8bit_binmode(write_io);
5090  return io;
5091 }
5092 
5093 /*
5094  * call-seq:
5095  * ios.binmode? -> true or false
5096  *
5097  * Returns <code>true</code> if <em>ios</em> is binmode.
5098  */
5099 static VALUE
5100 rb_io_binmode_p(VALUE io)
5101 {
5102  rb_io_t *fptr;
5103  GetOpenFile(io, fptr);
5104  return fptr->mode & FMODE_BINMODE ? Qtrue : Qfalse;
5105 }
5106 
5107 static const char*
5108 rb_io_fmode_modestr(int fmode)
5109 {
5110  if (fmode & FMODE_APPEND) {
5111  if ((fmode & FMODE_READWRITE) == FMODE_READWRITE) {
5112  return MODE_BTMODE("a+", "ab+", "at+");
5113  }
5114  return MODE_BTMODE("a", "ab", "at");
5115  }
5116  switch (fmode & FMODE_READWRITE) {
5117  default:
5118  rb_raise(rb_eArgError, "invalid access fmode 0x%x", fmode);
5119  case FMODE_READABLE:
5120  return MODE_BTMODE("r", "rb", "rt");
5121  case FMODE_WRITABLE:
5122  return MODE_BTMODE("w", "wb", "wt");
5123  case FMODE_READWRITE:
5124  if (fmode & FMODE_CREATE) {
5125  return MODE_BTMODE("w+", "wb+", "wt+");
5126  }
5127  return MODE_BTMODE("r+", "rb+", "rt+");
5128  }
5129 }
5130 
5131 static const char bom_prefix[] = "bom|";
5132 static const char utf_prefix[] = "utf-";
5133 enum {bom_prefix_len = (int)sizeof(bom_prefix) - 1};
5134 enum {utf_prefix_len = (int)sizeof(utf_prefix) - 1};
5135 
5136 static int
5137 io_encname_bom_p(const char *name, long len)
5138 {
5139  return len > bom_prefix_len && STRNCASECMP(name, bom_prefix, bom_prefix_len) == 0;
5140 }
5141 
5142 int
5143 rb_io_modestr_fmode(const char *modestr)
5144 {
5145  int fmode = 0;
5146  const char *m = modestr, *p = NULL;
5147 
5148  switch (*m++) {
5149  case 'r':
5150  fmode |= FMODE_READABLE;
5151  break;
5152  case 'w':
5154  break;
5155  case 'a':
5157  break;
5158  default:
5159  error:
5160  rb_raise(rb_eArgError, "invalid access mode %s", modestr);
5161  }
5162 
5163  while (*m) {
5164  switch (*m++) {
5165  case 'b':
5166  fmode |= FMODE_BINMODE;
5167  break;
5168  case 't':
5169  fmode |= FMODE_TEXTMODE;
5170  break;
5171  case '+':
5172  fmode |= FMODE_READWRITE;
5173  break;
5174  default:
5175  goto error;
5176  case ':':
5177  p = strchr(m, ':');
5178  if (io_encname_bom_p(m, p ? (long)(p - m) : (long)strlen(m)))
5179  fmode |= FMODE_SETENC_BY_BOM;
5180  goto finished;
5181  }
5182  }
5183 
5184  finished:
5185  if ((fmode & FMODE_BINMODE) && (fmode & FMODE_TEXTMODE))
5186  goto error;
5187 
5188  return fmode;
5189 }
5190 
5191 int
5193 {
5194  int fmode = 0;
5195 
5196  switch (oflags & O_ACCMODE) {
5197  case O_RDONLY:
5198  fmode = FMODE_READABLE;
5199  break;
5200  case O_WRONLY:
5201  fmode = FMODE_WRITABLE;
5202  break;
5203  case O_RDWR:
5204  fmode = FMODE_READWRITE;
5205  break;
5206  }
5207 
5208  if (oflags & O_APPEND) {
5209  fmode |= FMODE_APPEND;
5210  }
5211  if (oflags & O_TRUNC) {
5212  fmode |= FMODE_TRUNC;
5213  }
5214  if (oflags & O_CREAT) {
5215  fmode |= FMODE_CREATE;
5216  }
5217 #ifdef O_BINARY
5218  if (oflags & O_BINARY) {
5219  fmode |= FMODE_BINMODE;
5220  }
5221 #endif
5222 
5223  return fmode;
5224 }
5225 
5226 static int
5227 rb_io_fmode_oflags(int fmode)
5228 {
5229  int oflags = 0;
5230 
5231  switch (fmode & FMODE_READWRITE) {
5232  case FMODE_READABLE:
5233  oflags |= O_RDONLY;
5234  break;
5235  case FMODE_WRITABLE:
5236  oflags |= O_WRONLY;
5237  break;
5238  case FMODE_READWRITE:
5239  oflags |= O_RDWR;
5240  break;
5241  }
5242 
5243  if (fmode & FMODE_APPEND) {
5244  oflags |= O_APPEND;
5245  }
5246  if (fmode & FMODE_TRUNC) {
5247  oflags |= O_TRUNC;
5248  }
5249  if (fmode & FMODE_CREATE) {
5250  oflags |= O_CREAT;
5251  }
5252 #ifdef O_BINARY
5253  if (fmode & FMODE_BINMODE) {
5254  oflags |= O_BINARY;
5255  }
5256 #endif
5257 
5258  return oflags;
5259 }
5260 
5261 int
5262 rb_io_modestr_oflags(const char *modestr)
5263 {
5264  return rb_io_fmode_oflags(rb_io_modestr_fmode(modestr));
5265 }
5266 
5267 static const char*
5268 rb_io_oflags_modestr(int oflags)
5269 {
5270 #ifdef O_BINARY
5271 # define MODE_BINARY(a,b) ((oflags & O_BINARY) ? (b) : (a))
5272 #else
5273 # define MODE_BINARY(a,b) (a)
5274 #endif
5275  int accmode = oflags & (O_RDONLY|O_WRONLY|O_RDWR);
5276  if (oflags & O_APPEND) {
5277  if (accmode == O_WRONLY) {
5278  return MODE_BINARY("a", "ab");
5279  }
5280  if (accmode == O_RDWR) {
5281  return MODE_BINARY("a+", "ab+");
5282  }
5283  }
5284  switch (oflags & (O_RDONLY|O_WRONLY|O_RDWR)) {
5285  default:
5286  rb_raise(rb_eArgError, "invalid access oflags 0x%x", oflags);
5287  case O_RDONLY:
5288  return MODE_BINARY("r", "rb");
5289  case O_WRONLY:
5290  return MODE_BINARY("w", "wb");
5291  case O_RDWR:
5292  if (oflags & O_TRUNC) {
5293  return MODE_BINARY("w+", "wb+");
5294  }
5295  return MODE_BINARY("r+", "rb+");
5296  }
5297 }
5298 
5299 /*
5300  * Convert external/internal encodings to enc/enc2
5301  * NULL => use default encoding
5302  * Qnil => no encoding specified (internal only)
5303  */
5304 static void
5305 rb_io_ext_int_to_encs(rb_encoding *ext, rb_encoding *intern, rb_encoding **enc, rb_encoding **enc2, int fmode)
5306 {
5307  int default_ext = 0;
5308 
5309  if (ext == NULL) {
5311  default_ext = 1;
5312  }
5313  if (ext == rb_ascii8bit_encoding()) {
5314  /* If external is ASCII-8BIT, no transcoding */
5315  intern = NULL;
5316  }
5317  else if (intern == NULL) {
5318  intern = rb_default_internal_encoding();
5319  }
5320  if (intern == NULL || intern == (rb_encoding *)Qnil ||
5321  (!(fmode & FMODE_SETENC_BY_BOM) && (intern == ext))) {
5322  /* No internal encoding => use external + no transcoding */
5323  *enc = (default_ext && intern != ext) ? NULL : ext;
5324  *enc2 = NULL;
5325  }
5326  else {
5327  *enc = intern;
5328  *enc2 = ext;
5329  }
5330 }
5331 
5332 static void
5333 unsupported_encoding(const char *name, rb_encoding *enc)
5334 {
5335  rb_enc_warn(enc, "Unsupported encoding %s ignored", name);
5336 }
5337 
5338 static void
5339 parse_mode_enc(const char *estr, rb_encoding *estr_enc,
5340  rb_encoding **enc_p, rb_encoding **enc2_p, int *fmode_p)
5341 {
5342  const char *p;
5343  char encname[ENCODING_MAXNAMELEN+1];
5344  int idx, idx2;
5345  int fmode = fmode_p ? *fmode_p : 0;
5346  rb_encoding *ext_enc, *int_enc;
5347  long len;
5348 
5349  /* parse estr as "enc" or "enc2:enc" or "enc:-" */
5350 
5351  p = strrchr(estr, ':');
5352  len = p ? (p++ - estr) : (long)strlen(estr);
5353  if ((fmode & FMODE_SETENC_BY_BOM) || io_encname_bom_p(estr, len)) {
5354  estr += bom_prefix_len;
5355  len -= bom_prefix_len;
5356  if (!STRNCASECMP(estr, utf_prefix, utf_prefix_len)) {
5357  fmode |= FMODE_SETENC_BY_BOM;
5358  }
5359  else {
5360  rb_enc_warn(estr_enc, "BOM with non-UTF encoding %s is nonsense", estr);
5361  fmode &= ~FMODE_SETENC_BY_BOM;
5362  }
5363  }
5364  if (len == 0 || len > ENCODING_MAXNAMELEN) {
5365  idx = -1;
5366  }
5367  else {
5368  if (p) {
5369  memcpy(encname, estr, len);
5370  encname[len] = '\0';
5371  estr = encname;
5372  }
5373  idx = rb_enc_find_index(estr);
5374  }
5375  if (fmode_p) *fmode_p = fmode;
5376 
5377  if (idx >= 0)
5378  ext_enc = rb_enc_from_index(idx);
5379  else {
5380  if (idx != -2)
5381  unsupported_encoding(estr, estr_enc);
5382  ext_enc = NULL;
5383  }
5384 
5385  int_enc = NULL;
5386  if (p) {
5387  if (*p == '-' && *(p+1) == '\0') {
5388  /* Special case - "-" => no transcoding */
5389  int_enc = (rb_encoding *)Qnil;
5390  }
5391  else {
5392  idx2 = rb_enc_find_index(p);
5393  if (idx2 < 0)
5394  unsupported_encoding(p, estr_enc);
5395  else if (!(fmode & FMODE_SETENC_BY_BOM) && (idx2 == idx)) {
5396  int_enc = (rb_encoding *)Qnil;
5397  }
5398  else
5399  int_enc = rb_enc_from_index(idx2);
5400  }
5401  }
5402 
5403  rb_io_ext_int_to_encs(ext_enc, int_enc, enc_p, enc2_p, fmode);
5404 }
5405 
5406 int
5407 rb_io_extract_encoding_option(VALUE opt, rb_encoding **enc_p, rb_encoding **enc2_p, int *fmode_p)
5408 {
5409  VALUE encoding=Qnil, extenc=Qundef, intenc=Qundef, tmp;
5410  int extracted = 0;
5411  rb_encoding *extencoding = NULL;
5412  rb_encoding *intencoding = NULL;
5413 
5414  if (!NIL_P(opt)) {
5415  VALUE v;
5416  v = rb_hash_lookup2(opt, sym_encoding, Qnil);
5417  if (v != Qnil) encoding = v;
5418  v = rb_hash_lookup2(opt, sym_extenc, Qundef);
5419  if (v != Qnil) extenc = v;
5420  v = rb_hash_lookup2(opt, sym_intenc, Qundef);
5421  if (v != Qundef) intenc = v;
5422  }
5423  if ((extenc != Qundef || intenc != Qundef) && !NIL_P(encoding)) {
5424  if (!NIL_P(ruby_verbose)) {
5425  int idx = rb_to_encoding_index(encoding);
5426  if (idx >= 0) encoding = rb_enc_from_encoding(rb_enc_from_index(idx));
5427  rb_warn("Ignoring encoding parameter '%"PRIsVALUE"': %s_encoding is used",
5428  encoding, extenc == Qundef ? "internal" : "external");
5429  }
5430  encoding = Qnil;
5431  }
5432  if (extenc != Qundef && !NIL_P(extenc)) {
5433  extencoding = rb_to_encoding(extenc);
5434  }
5435  if (intenc != Qundef) {
5436  if (NIL_P(intenc)) {
5437  /* internal_encoding: nil => no transcoding */
5438  intencoding = (rb_encoding *)Qnil;
5439  }
5440  else if (!NIL_P(tmp = rb_check_string_type(intenc))) {
5441  char *p = StringValueCStr(tmp);
5442 
5443  if (*p == '-' && *(p+1) == '\0') {
5444  /* Special case - "-" => no transcoding */
5445  intencoding = (rb_encoding *)Qnil;
5446  }
5447  else {
5448  intencoding = rb_to_encoding(intenc);
5449  }
5450  }
5451  else {
5452  intencoding = rb_to_encoding(intenc);
5453  }
5454  if (extencoding == intencoding) {
5455  intencoding = (rb_encoding *)Qnil;
5456  }
5457  }
5458  if (!NIL_P(encoding)) {
5459  extracted = 1;
5460  if (!NIL_P(tmp = rb_check_string_type(encoding))) {
5461  parse_mode_enc(StringValueCStr(tmp), rb_enc_get(tmp),
5462  enc_p, enc2_p, fmode_p);
5463  }
5464  else {
5465  rb_io_ext_int_to_encs(rb_to_encoding(encoding), NULL, enc_p, enc2_p, 0);
5466  }
5467  }
5468  else if (extenc != Qundef || intenc != Qundef) {
5469  extracted = 1;
5470  rb_io_ext_int_to_encs(extencoding, intencoding, enc_p, enc2_p, 0);
5471  }
5472  return extracted;
5473 }
5474 
5475 typedef struct rb_io_enc_t convconfig_t;
5476 
5477 static void
5478 validate_enc_binmode(int *fmode_p, int ecflags, rb_encoding *enc, rb_encoding *enc2)
5479 {
5480  int fmode = *fmode_p;
5481 
5482  if ((fmode & FMODE_READABLE) &&
5483  !enc2 &&
5484  !(fmode & FMODE_BINMODE) &&
5486  rb_raise(rb_eArgError, "ASCII incompatible encoding needs binmode");
5487 
5488  if ((fmode & FMODE_BINMODE) && (ecflags & ECONV_NEWLINE_DECORATOR_MASK)) {
5489  rb_raise(rb_eArgError, "newline decorator with binary mode");
5490  }
5491  if (!(fmode & FMODE_BINMODE) &&
5492  (DEFAULT_TEXTMODE || (ecflags & ECONV_NEWLINE_DECORATOR_MASK))) {
5493  fmode |= FMODE_TEXTMODE;
5494  *fmode_p = fmode;
5495  }
5496 #if !DEFAULT_TEXTMODE
5497  else if (!(ecflags & ECONV_NEWLINE_DECORATOR_MASK)) {
5498  fmode &= ~FMODE_TEXTMODE;
5499  *fmode_p = fmode;
5500  }
5501 #endif
5502 }
5503 
5504 static void
5505 extract_binmode(VALUE opthash, int *fmode)
5506 {
5507  if (!NIL_P(opthash)) {
5508  VALUE v;
5509  v = rb_hash_aref(opthash, sym_textmode);
5510  if (!NIL_P(v)) {
5511  if (*fmode & FMODE_TEXTMODE)
5512  rb_raise(rb_eArgError, "textmode specified twice");
5513  if (*fmode & FMODE_BINMODE)
5514  rb_raise(rb_eArgError, "both textmode and binmode specified");
5515  if (RTEST(v))
5516  *fmode |= FMODE_TEXTMODE;
5517  }
5518  v = rb_hash_aref(opthash, sym_binmode);
5519  if (!NIL_P(v)) {
5520  if (*fmode & FMODE_BINMODE)
5521  rb_raise(rb_eArgError, "binmode specified twice");
5522  if (*fmode & FMODE_TEXTMODE)
5523  rb_raise(rb_eArgError, "both textmode and binmode specified");
5524  if (RTEST(v))
5525  *fmode |= FMODE_BINMODE;
5526  }
5527 
5528  if ((*fmode & FMODE_BINMODE) && (*fmode & FMODE_TEXTMODE))
5529  rb_raise(rb_eArgError, "both textmode and binmode specified");
5530  }
5531 }
5532 
5533 static void
5534 rb_io_extract_modeenc(VALUE *vmode_p, VALUE *vperm_p, VALUE opthash,
5535  int *oflags_p, int *fmode_p, convconfig_t *convconfig_p)
5536 {
5537  VALUE vmode;
5538  int oflags, fmode;
5539  rb_encoding *enc, *enc2;
5540  int ecflags;
5541  VALUE ecopts;
5542  int has_enc = 0, has_vmode = 0;
5543  VALUE intmode;
5544 
5545  vmode = *vmode_p;
5546 
5547  /* Set to defaults */
5548  rb_io_ext_int_to_encs(NULL, NULL, &enc, &enc2, 0);
5549 
5550  vmode_handle:
5551  if (NIL_P(vmode)) {
5552  fmode = FMODE_READABLE;
5553  oflags = O_RDONLY;
5554  }
5555  else if (!NIL_P(intmode = rb_check_to_integer(vmode, "to_int"))) {
5556  vmode = intmode;
5557  oflags = NUM2INT(intmode);
5558  fmode = rb_io_oflags_fmode(oflags);
5559  }
5560  else {
5561  const char *p;
5562 
5563  SafeStringValue(vmode);
5564  p = StringValueCStr(vmode);
5565  fmode = rb_io_modestr_fmode(p);
5566  oflags = rb_io_fmode_oflags(fmode);
5567  p = strchr(p, ':');
5568  if (p) {
5569  has_enc = 1;
5570  parse_mode_enc(p+1, rb_enc_get(vmode), &enc, &enc2, &fmode);
5571  }
5572  else {
5573  rb_encoding *e;
5574 
5575  e = (fmode & FMODE_BINMODE) ? rb_ascii8bit_encoding() : NULL;
5576  rb_io_ext_int_to_encs(e, NULL, &enc, &enc2, fmode);
5577  }
5578  }
5579 
5580  if (NIL_P(opthash)) {
5581  ecflags = (fmode & FMODE_READABLE) ?
5584 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
5585  ecflags |= (fmode & FMODE_WRITABLE) ?
5586  MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE,
5587  0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE) : 0;
5588 #endif
5590  ecopts = Qnil;
5591  }
5592  else {
5593  VALUE v;
5594  if (!has_vmode) {
5595  v = rb_hash_aref(opthash, sym_mode);
5596  if (!NIL_P(v)) {
5597  if (!NIL_P(vmode)) {
5598  rb_raise(rb_eArgError, "mode specified twice");
5599  }
5600  has_vmode = 1;
5601  vmode = v;
5602  goto vmode_handle;
5603  }
5604  }
5605  v = rb_hash_aref(opthash, sym_flags);
5606  if (!NIL_P(v)) {
5607  v = rb_to_int(v);
5608  oflags |= NUM2INT(v);
5609  vmode = INT2NUM(oflags);
5610  fmode = rb_io_oflags_fmode(oflags);
5611  }
5612  extract_binmode(opthash, &fmode);
5613  if (fmode & FMODE_BINMODE) {
5614 #ifdef O_BINARY
5615  oflags |= O_BINARY;
5616 #endif
5617  if (!has_enc)
5618  rb_io_ext_int_to_encs(rb_ascii8bit_encoding(), NULL, &enc, &enc2, fmode);
5619  }
5620 #if DEFAULT_TEXTMODE
5621  else if (NIL_P(vmode)) {
5622  fmode |= DEFAULT_TEXTMODE;
5623  }
5624 #endif
5625  v = rb_hash_aref(opthash, sym_perm);
5626  if (!NIL_P(v)) {
5627  if (vperm_p) {
5628  if (!NIL_P(*vperm_p)) {
5629  rb_raise(rb_eArgError, "perm specified twice");
5630  }
5631  *vperm_p = v;
5632  }
5633  else {
5634  /* perm no use, just ignore */
5635  }
5636  }
5637  ecflags = (fmode & FMODE_READABLE) ?
5640 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
5641  ecflags |= (fmode & FMODE_WRITABLE) ?
5642  MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE,
5643  0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE) : 0;
5644 #endif
5645 
5646  if (rb_io_extract_encoding_option(opthash, &enc, &enc2, &fmode)) {
5647  if (has_enc) {
5648  rb_raise(rb_eArgError, "encoding specified twice");
5649  }
5650  }
5652  ecflags = rb_econv_prepare_options(opthash, &ecopts, ecflags);
5653  }
5654 
5655  validate_enc_binmode(&fmode, ecflags, enc, enc2);
5656 
5657  *vmode_p = vmode;
5658 
5659  *oflags_p = oflags;
5660  *fmode_p = fmode;
5661  convconfig_p->enc = enc;
5662  convconfig_p->enc2 = enc2;
5663  convconfig_p->ecflags = ecflags;
5664  convconfig_p->ecopts = ecopts;
5665 }
5666 
5669  int oflags;
5671 };
5672 
5673 static void *
5674 sysopen_func(void *ptr)
5675 {
5676  const struct sysopen_struct *data = ptr;
5677  const char *fname = RSTRING_PTR(data->fname);
5678  return (void *)(VALUE)rb_cloexec_open(fname, data->oflags, data->perm);
5679 }
5680 
5681 static inline int
5682 rb_sysopen_internal(struct sysopen_struct *data)
5683 {
5684  int fd;
5685  fd = (int)(VALUE)rb_thread_call_without_gvl(sysopen_func, data, RUBY_UBF_IO, 0);
5686  if (0 <= fd)
5687  rb_update_max_fd(fd);
5688  return fd;
5689 }
5690 
5691 static int
5692 rb_sysopen(VALUE fname, int oflags, mode_t perm)
5693 {
5694  int fd;
5695  struct sysopen_struct data;
5696 
5697  data.fname = rb_str_encode_ospath(fname);
5698  StringValueCStr(data.fname);
5699  data.oflags = oflags;
5700  data.perm = perm;
5701 
5702  fd = rb_sysopen_internal(&data);
5703  if (fd < 0) {
5704  int e = errno;
5705  if (rb_gc_for_fd(e)) {
5706  fd = rb_sysopen_internal(&data);
5707  }
5708  if (fd < 0) {
5709  rb_syserr_fail_path(e, fname);
5710  }
5711  }
5712  return fd;
5713 }
5714 
5715 FILE *
5716 rb_fdopen(int fd, const char *modestr)
5717 {
5718  FILE *file;
5719 
5720 #if defined(__sun)
5721  errno = 0;
5722 #endif
5723  file = fdopen(fd, modestr);
5724  if (!file) {
5725  int e = errno;
5726 #if defined(__sun)
5727  if (e == 0) {
5728  rb_gc();
5729  errno = 0;
5730  file = fdopen(fd, modestr);
5731  }
5732  else
5733 #endif
5734  if (rb_gc_for_fd(e)) {
5735  file = fdopen(fd, modestr);
5736  }
5737  if (!file) {
5738 #ifdef _WIN32
5739  if (e == 0) e = EINVAL;
5740 #elif defined(__sun)
5741  if (e == 0) e = EMFILE;
5742 #endif
5743  rb_syserr_fail(e, 0);
5744  }
5745  }
5746 
5747  /* xxx: should be _IONBF? A buffer in FILE may have trouble. */
5748 #ifdef USE_SETVBUF
5749  if (setvbuf(file, NULL, _IOFBF, 0) != 0)
5750  rb_warn("setvbuf() can't be honoured (fd=%d)", fd);
5751 #endif
5752  return file;
5753 }
5754 
5755 static int
5756 io_check_tty(rb_io_t *fptr)
5757 {
5758  int t = isatty(fptr->fd);
5759  if (t)
5760  fptr->mode |= FMODE_TTY|FMODE_DUPLEX;
5761  return t;
5762 }
5763 
5764 static VALUE rb_io_internal_encoding(VALUE);
5765 static void io_encoding_set(rb_io_t *, VALUE, VALUE, VALUE);
5766 
5767 static int
5768 io_strip_bom(VALUE io)
5769 {
5770  VALUE b1, b2, b3, b4;
5771 
5772  if (NIL_P(b1 = rb_io_getbyte(io))) return 0;
5773  switch (b1) {
5774  case INT2FIX(0xEF):
5775  if (NIL_P(b2 = rb_io_getbyte(io))) break;
5776  if (b2 == INT2FIX(0xBB) && !NIL_P(b3 = rb_io_getbyte(io))) {
5777  if (b3 == INT2FIX(0xBF)) {
5778  return rb_utf8_encindex();
5779  }
5780  rb_io_ungetbyte(io, b3);
5781  }
5782  rb_io_ungetbyte(io, b2);
5783  break;
5784 
5785  case INT2FIX(0xFE):
5786  if (NIL_P(b2 = rb_io_getbyte(io))) break;
5787  if (b2 == INT2FIX(0xFF)) {
5788  return ENCINDEX_UTF_16BE;
5789  }
5790  rb_io_ungetbyte(io, b2);
5791  break;
5792 
5793  case INT2FIX(0xFF):
5794  if (NIL_P(b2 = rb_io_getbyte(io))) break;
5795  if (b2 == INT2FIX(0xFE)) {
5796  b3 = rb_io_getbyte(io);
5797  if (b3 == INT2FIX(0) && !NIL_P(b4 = rb_io_getbyte(io))) {
5798  if (b4 == INT2FIX(0)) {
5799  return ENCINDEX_UTF_32LE;
5800  }
5801  rb_io_ungetbyte(io, b4);
5802  rb_io_ungetbyte(io, b3);
5803  }
5804  else {
5805  rb_io_ungetbyte(io, b3);
5806  return ENCINDEX_UTF_16LE;
5807  }
5808  }
5809  rb_io_ungetbyte(io, b2);
5810  break;
5811 
5812  case INT2FIX(0):
5813  if (NIL_P(b2 = rb_io_getbyte(io))) break;
5814  if (b2 == INT2FIX(0) && !NIL_P(b3 = rb_io_getbyte(io))) {
5815  if (b3 == INT2FIX(0xFE) && !NIL_P(b4 = rb_io_getbyte(io))) {
5816  if (b4 == INT2FIX(0xFF)) {
5817  return ENCINDEX_UTF_32BE;
5818  }
5819  rb_io_ungetbyte(io, b4);
5820  }
5821  rb_io_ungetbyte(io, b3);
5822  }
5823  rb_io_ungetbyte(io, b2);
5824  break;
5825  }
5826  rb_io_ungetbyte(io, b1);
5827  return 0;
5828 }
5829 
5830 static void
5831 io_set_encoding_by_bom(VALUE io)
5832 {
5833  int idx = io_strip_bom(io);
5834  rb_io_t *fptr;
5835 
5836  GetOpenFile(io, fptr);
5837  if (idx) {
5838  io_encoding_set(fptr, rb_enc_from_encoding(rb_enc_from_index(idx)),
5839  rb_io_internal_encoding(io), Qnil);
5840  }
5841  else {
5842  fptr->encs.enc2 = NULL;
5843  }
5844 }
5845 
5846 static VALUE
5847 rb_file_open_generic(VALUE io, VALUE filename, int oflags, int fmode,
5848  const convconfig_t *convconfig, mode_t perm)
5849 {
5850  VALUE pathv;
5851  rb_io_t *fptr;
5852  convconfig_t cc;
5853  if (!convconfig) {
5854  /* Set to default encodings */
5855  rb_io_ext_int_to_encs(NULL, NULL, &cc.enc, &cc.enc2, fmode);
5856  cc.ecflags = 0;
5857  cc.ecopts = Qnil;
5858  convconfig = &cc;
5859  }
5860  validate_enc_binmode(&fmode, convconfig->ecflags,
5861  convconfig->enc, convconfig->enc2);
5862 
5863  MakeOpenFile(io, fptr);
5864  fptr->mode = fmode;
5865  fptr->encs = *convconfig;
5866  pathv = rb_str_new_frozen(filename);
5867 #ifdef O_TMPFILE
5868  if (!(oflags & O_TMPFILE)) {
5869  fptr->pathv = pathv;
5870  }
5871 #else
5872  fptr->pathv = pathv;
5873 #endif
5874  fptr->fd = rb_sysopen(pathv, oflags, perm);
5875  io_check_tty(fptr);
5876  if (fmode & FMODE_SETENC_BY_BOM) io_set_encoding_by_bom(io);
5877 
5878  return io;
5879 }
5880 
5881 static VALUE
5882 rb_file_open_internal(VALUE io, VALUE filename, const char *modestr)
5883 {
5884  int fmode = rb_io_modestr_fmode(modestr);
5885  const char *p = strchr(modestr, ':');
5886  convconfig_t convconfig;
5887 
5888  if (p) {
5889  parse_mode_enc(p+1, rb_usascii_encoding(),
5890  &convconfig.enc, &convconfig.enc2, &fmode);
5891  }
5892  else {
5893  rb_encoding *e;
5894  /* Set to default encodings */
5895 
5896  e = (fmode & FMODE_BINMODE) ? rb_ascii8bit_encoding() : NULL;
5897  rb_io_ext_int_to_encs(e, NULL, &convconfig.enc, &convconfig.enc2, fmode);
5898  convconfig.ecflags = 0;
5899  convconfig.ecopts = Qnil;
5900  }
5901 
5902  return rb_file_open_generic(io, filename,
5903  rb_io_fmode_oflags(fmode),
5904  fmode,
5905  &convconfig,
5906  0666);
5907 }
5908 
5909 VALUE
5910 rb_file_open_str(VALUE fname, const char *modestr)
5911 {
5912  FilePathValue(fname);
5913  return rb_file_open_internal(io_alloc(rb_cFile), fname, modestr);
5914 }
5915 
5916 VALUE
5917 rb_file_open(const char *fname, const char *modestr)
5918 {
5919  return rb_file_open_internal(io_alloc(rb_cFile), rb_str_new_cstr(fname), modestr);
5920 }
5921 
5922 #if defined(__CYGWIN__) || !defined(HAVE_WORKING_FORK)
5923 static struct pipe_list {
5924  rb_io_t *fptr;
5925  struct pipe_list *next;
5926 } *pipe_list;
5927 
5928 static void
5929 pipe_add_fptr(rb_io_t *fptr)
5930 {
5931  struct pipe_list *list;
5932 
5933  list = ALLOC(struct pipe_list);
5934  list->fptr = fptr;
5935  list->next = pipe_list;
5936  pipe_list = list;
5937 }
5938 
5939 static void
5940 pipe_del_fptr(rb_io_t *fptr)
5941 {
5942  struct pipe_list *list = pipe_list;
5943  struct pipe_list *tmp;
5944 
5945  if (list->fptr == fptr) {
5946  pipe_list = list->next;
5947  free(list);
5948  return;
5949  }
5950 
5951  while (list->next) {
5952  if (list->next->fptr == fptr) {
5953  tmp = list->next;
5954  list->next = list->next->next;
5955  free(tmp);
5956  return;
5957  }
5958  list = list->next;
5959  }
5960 }
5961 
5962 #if defined (_WIN32) || defined(__CYGWIN__)
5963 static void
5964 pipe_atexit(void)
5965 {
5966  struct pipe_list *list = pipe_list;
5967  struct pipe_list *tmp;
5968 
5969  while (list) {
5970  tmp = list->next;
5971  rb_io_fptr_finalize(list->fptr);
5972  list = tmp;
5973  }
5974 }
5975 #endif
5976 
5977 static void
5978 pipe_finalize(rb_io_t *fptr, int noraise)
5979 {
5980 #if !defined(HAVE_WORKING_FORK) && !defined(_WIN32)
5981  int status = 0;
5982  if (fptr->stdio_file) {
5983  status = pclose(fptr->stdio_file);
5984  }
5985  fptr->fd = -1;
5986  fptr->stdio_file = 0;
5987  rb_last_status_set(status, fptr->pid);
5988 #else
5989  fptr_finalize(fptr, noraise);
5990 #endif
5991  pipe_del_fptr(fptr);
5992 }
5993 #endif
5994 
5995 void
5997 {
5999  fptr->mode |= FMODE_SYNC;
6000 }
6001 
6002 void
6004 {
6005  rb_io_synchronized(fptr);
6006 }
6007 
6008 int
6009 rb_pipe(int *pipes)
6010 {
6011  int ret;
6012  ret = rb_cloexec_pipe(pipes);
6013  if (ret == -1) {
6014  if (rb_gc_for_fd(errno)) {
6015  ret = rb_cloexec_pipe(pipes);
6016  }
6017  }
6018  if (ret == 0) {
6019  rb_update_max_fd(pipes[0]);
6020  rb_update_max_fd(pipes[1]);
6021  }
6022  return ret;
6023 }
6024 
6025 #ifdef _WIN32
6026 #define HAVE_SPAWNV 1
6027 #define spawnv(mode, cmd, args) rb_w32_uaspawn((mode), (cmd), (args))
6028 #define spawn(mode, cmd) rb_w32_uspawn((mode), (cmd), 0)
6029 #endif
6030 
6031 #if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
6032 struct popen_arg {
6033  VALUE execarg_obj;
6034  struct rb_execarg *eargp;
6035  int modef;
6036  int pair[2];
6037  int write_pair[2];
6038 };
6039 #endif
6040 
6041 #ifdef HAVE_WORKING_FORK
6042 static void
6043 popen_redirect(struct popen_arg *p)
6044 {
6045  if ((p->modef & FMODE_READABLE) && (p->modef & FMODE_WRITABLE)) {
6046  close(p->write_pair[1]);
6047  if (p->write_pair[0] != 0) {
6048  dup2(p->write_pair[0], 0);
6049  close(p->write_pair[0]);
6050  }
6051  close(p->pair[0]);
6052  if (p->pair[1] != 1) {
6053  dup2(p->pair[1], 1);
6054  close(p->pair[1]);
6055  }
6056  }
6057  else if (p->modef & FMODE_READABLE) {
6058  close(p->pair[0]);
6059  if (p->pair[1] != 1) {
6060  dup2(p->pair[1], 1);
6061  close(p->pair[1]);
6062  }
6063  }
6064  else {
6065  close(p->pair[1]);
6066  if (p->pair[0] != 0) {
6067  dup2(p->pair[0], 0);
6068  close(p->pair[0]);
6069  }
6070  }
6071 }
6072 
6073 #if defined(__linux__)
6074 /* Linux /proc/self/status contains a line: "FDSize:\t<nnn>\n"
6075  * Since /proc may not be available, linux_get_maxfd is just a hint.
6076  * This function, linux_get_maxfd, must be async-signal-safe.
6077  * I.e. opendir() is not usable.
6078  *
6079  * Note that memchr() and memcmp is *not* async-signal-safe in POSIX.
6080  * However they are easy to re-implement in async-signal-safe manner.
6081  * (Also note that there is missing/memcmp.c.)
6082  */
6083 static int
6084 linux_get_maxfd(void)
6085 {
6086  int fd;
6087  char buf[4096], *p, *np, *e;
6088  ssize_t ss;
6089  fd = rb_cloexec_open("/proc/self/status", O_RDONLY|O_NOCTTY, 0);
6090  if (fd == -1) return -1;
6091  ss = read(fd, buf, sizeof(buf));
6092  if (ss == -1) goto err;
6093  p = buf;
6094  e = buf + ss;
6095  while ((int)sizeof("FDSize:\t0\n")-1 <= e-p &&
6096  (np = memchr(p, '\n', e-p)) != NULL) {
6097  if (memcmp(p, "FDSize:", sizeof("FDSize:")-1) == 0) {
6098  int fdsize;
6099  p += sizeof("FDSize:")-1;
6100  *np = '\0';
6101  fdsize = (int)ruby_strtoul(p, (char **)NULL, 10);
6102  close(fd);
6103  return fdsize;
6104  }
6105  p = np+1;
6106  }
6107  /* fall through */
6108 
6109  err:
6110  close(fd);
6111  return -1;
6112 }
6113 #endif
6114 
6115 /* This function should be async-signal-safe. */
6116 void
6117 rb_close_before_exec(int lowfd, int maxhint, VALUE noclose_fds)
6118 {
6119 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
6120  int fd, ret;
6121  int max = (int)max_file_descriptor;
6122 # ifdef F_MAXFD
6123  /* F_MAXFD is available since NetBSD 2.0. */
6124  ret = fcntl(0, F_MAXFD); /* async-signal-safe */
6125  if (ret != -1)
6126  maxhint = max = ret;
6127 # elif defined(__linux__)
6128  ret = linux_get_maxfd();
6129  if (maxhint < ret)
6130  maxhint = ret;
6131  /* maxhint = max = ret; if (ret == -1) abort(); // test */
6132 # endif
6133  if (max < maxhint)
6134  max = maxhint;
6135  for (fd = lowfd; fd <= max; fd++) {
6136  if (!NIL_P(noclose_fds) &&
6137  RTEST(rb_hash_lookup(noclose_fds, INT2FIX(fd)))) /* async-signal-safe */
6138  continue;
6139  ret = fcntl(fd, F_GETFD); /* async-signal-safe */
6140  if (ret != -1 && !(ret & FD_CLOEXEC)) {
6141  fcntl(fd, F_SETFD, ret|FD_CLOEXEC); /* async-signal-safe */
6142  }
6143 # define CONTIGUOUS_CLOSED_FDS 20
6144  if (ret != -1) {
6145  if (max < fd + CONTIGUOUS_CLOSED_FDS)
6146  max = fd + CONTIGUOUS_CLOSED_FDS;
6147  }
6148  }
6149 #endif
6150 }
6151 
6152 static int
6153 popen_exec(void *pp, char *errmsg, size_t errmsg_len)
6154 {
6155  struct popen_arg *p = (struct popen_arg*)pp;
6156 
6157  return rb_exec_async_signal_safe(p->eargp, errmsg, errmsg_len);
6158 }
6159 #endif
6160 
6161 #if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
6162 static VALUE
6163 rb_execarg_fixup_v(VALUE execarg_obj)
6164 {
6165  rb_execarg_parent_start(execarg_obj);
6166  return Qnil;
6167 }
6168 #else
6169 char *rb_execarg_commandline(const struct rb_execarg *eargp, VALUE *prog);
6170 #endif
6171 
6172 static VALUE
6173 pipe_open(VALUE execarg_obj, const char *modestr, int fmode,
6174  const convconfig_t *convconfig)
6175 {
6176  struct rb_execarg *eargp = NIL_P(execarg_obj) ? NULL : rb_execarg_get(execarg_obj);
6177  VALUE prog = eargp ? (eargp->use_shell ? eargp->invoke.sh.shell_script : eargp->invoke.cmd.command_name) : Qfalse ;
6178  rb_pid_t pid = 0;
6179  rb_io_t *fptr;
6180  VALUE port;
6181  rb_io_t *write_fptr;
6182  VALUE write_port;
6183 #if defined(HAVE_WORKING_FORK)
6184  int status;
6185  char errmsg[80] = { '\0' };
6186 #endif
6187 #if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
6188  int state;
6189  struct popen_arg arg;
6190 #endif
6191  int e = 0;
6192 #if defined(HAVE_SPAWNV)
6193 # if defined(HAVE_SPAWNVE)
6194 # define DO_SPAWN(cmd, args, envp) ((args) ? \
6195  spawnve(P_NOWAIT, (cmd), (args), (envp)) : \
6196  spawne(P_NOWAIT, (cmd), (envp)))
6197 # else
6198 # define DO_SPAWN(cmd, args, envp) ((args) ? \
6199  spawnv(P_NOWAIT, (cmd), (args)) : \
6200  spawn(P_NOWAIT, (cmd)))
6201 # endif
6202 # if !defined(HAVE_WORKING_FORK)
6203  char **args = NULL;
6204 # if defined(HAVE_SPAWNVE)
6205  char **envp = NULL;
6206 # endif
6207 # endif
6208 #endif
6209 #if !defined(HAVE_WORKING_FORK)
6210  struct rb_execarg sarg, *sargp = &sarg;
6211 #endif
6212  FILE *fp = 0;
6213  int fd = -1;
6214  int write_fd = -1;
6215 #if !defined(HAVE_WORKING_FORK)
6216  const char *cmd = 0;
6217 
6218  if (prog)
6219  cmd = StringValueCStr(prog);
6220 #endif
6221 
6222 #if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
6223  arg.execarg_obj = execarg_obj;
6224  arg.eargp = eargp;
6225  arg.modef = fmode;
6226  arg.pair[0] = arg.pair[1] = -1;
6227  arg.write_pair[0] = arg.write_pair[1] = -1;
6228 # if !defined(HAVE_WORKING_FORK)
6229  if (eargp && !eargp->use_shell) {
6230  args = ARGVSTR2ARGV(eargp->invoke.cmd.argv_str);
6231  }
6232 # endif
6233  switch (fmode & (FMODE_READABLE|FMODE_WRITABLE)) {
6234  case FMODE_READABLE|FMODE_WRITABLE:
6235  if (rb_pipe(arg.write_pair) < 0)
6236  rb_sys_fail_str(prog);
6237  if (rb_pipe(arg.pair) < 0) {
6238  e = errno;
6239  close(arg.write_pair[0]);
6240  close(arg.write_pair[1]);
6241  rb_syserr_fail_str(e, prog);
6242  }
6243  if (eargp) {
6244  rb_execarg_addopt(execarg_obj, INT2FIX(0), INT2FIX(arg.write_pair[0]));
6245  rb_execarg_addopt(execarg_obj, INT2FIX(1), INT2FIX(arg.pair[1]));
6246  }
6247  break;
6248  case FMODE_READABLE:
6249  if (rb_pipe(arg.pair) < 0)
6250  rb_sys_fail_str(prog);
6251  if (eargp)
6252  rb_execarg_addopt(execarg_obj, INT2FIX(1), INT2FIX(arg.pair[1]));
6253  break;
6254  case FMODE_WRITABLE:
6255  if (rb_pipe(arg.pair) < 0)
6256  rb_sys_fail_str(prog);
6257  if (eargp)
6258  rb_execarg_addopt(execarg_obj, INT2FIX(0), INT2FIX(arg.pair[0]));
6259  break;
6260  default:
6261  rb_sys_fail_str(prog);
6262  }
6263  if (!NIL_P(execarg_obj)) {
6264  rb_protect(rb_execarg_fixup_v, execarg_obj, &state);
6265  if (state) {
6266  if (0 <= arg.write_pair[0]) close(arg.write_pair[0]);
6267  if (0 <= arg.write_pair[1]) close(arg.write_pair[1]);
6268  if (0 <= arg.pair[0]) close(arg.pair[0]);
6269  if (0 <= arg.pair[1]) close(arg.pair[1]);
6270  rb_execarg_parent_end(execarg_obj);
6271  rb_jump_tag(state);
6272  }
6273 
6274 # if defined(HAVE_WORKING_FORK)
6275  pid = rb_fork_async_signal_safe(&status, popen_exec, &arg, arg.eargp->redirect_fds, errmsg, sizeof(errmsg));
6276 # else
6277  rb_execarg_run_options(eargp, sargp, NULL, 0);
6278 # if defined(HAVE_SPAWNVE)
6279  if (eargp->envp_str) envp = (char **)RSTRING_PTR(eargp->envp_str);
6280 # endif
6281  while ((pid = DO_SPAWN(cmd, args, envp)) == -1) {
6282  /* exec failed */
6283  switch (e = errno) {
6284  case EAGAIN:
6285 # if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
6286  case EWOULDBLOCK:
6287 # endif
6288  rb_thread_sleep(1);
6289  continue;
6290  }
6291  break;
6292  }
6293  if (eargp)
6294  rb_execarg_run_options(sargp, NULL, NULL, 0);
6295 # endif
6296  rb_execarg_parent_end(execarg_obj);
6297  }
6298  else {
6299 # if defined(HAVE_WORKING_FORK)
6300  pid = rb_fork_ruby(&status);
6301  if (pid == 0) { /* child */
6302  rb_thread_atfork();
6303  popen_redirect(&arg);
6304  rb_io_synchronized(RFILE(orig_stdout)->fptr);
6305  rb_io_synchronized(RFILE(orig_stderr)->fptr);
6306  return Qnil;
6307  }
6308 # else
6309  rb_notimplement();
6310 # endif
6311  }
6312 
6313  /* parent */
6314  if (pid == -1) {
6315 # if defined(HAVE_WORKING_FORK)
6316  e = errno;
6317 # endif
6318  close(arg.pair[0]);
6319  close(arg.pair[1]);
6320  if ((fmode & (FMODE_READABLE|FMODE_WRITABLE)) == (FMODE_READABLE|FMODE_WRITABLE)) {
6321  close(arg.write_pair[0]);
6322  close(arg.write_pair[1]);
6323  }
6324 # if defined(HAVE_WORKING_FORK)
6325  if (errmsg[0])
6326  rb_syserr_fail(e, errmsg);
6327 # endif
6328  rb_syserr_fail_str(e, prog);
6329  }
6330  if ((fmode & FMODE_READABLE) && (fmode & FMODE_WRITABLE)) {
6331  close(arg.pair[1]);
6332  fd = arg.pair[0];
6333  close(arg.write_pair[0]);
6334  write_fd = arg.write_pair[1];
6335  }
6336  else if (fmode & FMODE_READABLE) {
6337  close(arg.pair[1]);
6338  fd = arg.pair[0];
6339  }
6340  else {
6341  close(arg.pair[0]);
6342  fd = arg.pair[1];
6343  }
6344 #else
6345  cmd = rb_execarg_commandline(eargp, &prog);
6346  if (!NIL_P(execarg_obj)) {
6347  rb_execarg_parent_start(execarg_obj);
6348  rb_execarg_run_options(eargp, sargp, NULL, 0);
6349  }
6350  fp = popen(cmd, modestr);
6351  e = errno;
6352  if (eargp) {
6353  rb_execarg_parent_end(execarg_obj);
6354  rb_execarg_run_options(sargp, NULL, NULL, 0);
6355  }
6356  if (!fp) rb_syserr_fail_path(e, prog);
6357  fd = fileno(fp);
6358 #endif
6359 
6360  port = io_alloc(rb_cIO);
6361  MakeOpenFile(port, fptr);
6362  fptr->fd = fd;
6363  fptr->stdio_file = fp;
6364  fptr->mode = fmode | FMODE_SYNC|FMODE_DUPLEX;
6365  if (convconfig) {
6366  fptr->encs = *convconfig;
6367 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
6370  }
6371 #endif
6372  }
6373  else {
6374  if (NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {
6376  }
6377 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
6378  if (NEED_NEWLINE_DECORATOR_ON_WRITE(fptr)) {
6379  fptr->encs.ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
6380  }
6381 #endif
6382  }
6383  fptr->pid = pid;
6384 
6385  if (0 <= write_fd) {
6386  write_port = io_alloc(rb_cIO);
6387  MakeOpenFile(write_port, write_fptr);
6388  write_fptr->fd = write_fd;
6389  write_fptr->mode = (fmode & ~FMODE_READABLE)| FMODE_SYNC|FMODE_DUPLEX;
6390  fptr->mode &= ~FMODE_WRITABLE;
6391  fptr->tied_io_for_writing = write_port;
6392  rb_ivar_set(port, rb_intern("@tied_io_for_writing"), write_port);
6393  }
6394 
6395 #if defined (__CYGWIN__) || !defined(HAVE_WORKING_FORK)
6396  fptr->finalize = pipe_finalize;
6397  pipe_add_fptr(fptr);
6398 #endif
6399  return port;
6400 }
6401 
6402 static int
6403 is_popen_fork(VALUE prog)
6404 {
6405  if (RSTRING_LEN(prog) == 1 && RSTRING_PTR(prog)[0] == '-') {
6406 #if !defined(HAVE_WORKING_FORK)
6408  "fork() function is unimplemented on this machine");
6409 #else
6410  return TRUE;
6411 #endif
6412  }
6413  return FALSE;
6414 }
6415 
6416 static VALUE
6417 pipe_open_s(VALUE prog, const char *modestr, int fmode,
6418  const convconfig_t *convconfig)
6419 {
6420  int argc = 1;
6421  VALUE *argv = &prog;
6422  VALUE execarg_obj = Qnil;
6423 
6424  if (!is_popen_fork(prog))
6425  execarg_obj = rb_execarg_new(argc, argv, TRUE);
6426  return pipe_open(execarg_obj, modestr, fmode, convconfig);
6427 }
6428 
6429 static VALUE
6430 pipe_close(VALUE io)
6431 {
6432  rb_io_t *fptr = io_close_fptr(io);
6433  if (fptr) {
6434  fptr_waitpid(fptr, rb_thread_to_be_killed(rb_thread_current()));
6435  }
6436  return Qnil;
6437 }
6438 
6439 /*
6440  * call-seq:
6441  * IO.popen([env,] cmd, mode="r" [, opt]) -> io
6442  * IO.popen([env,] cmd, mode="r" [, opt]) {|io| block } -> obj
6443  *
6444  * Runs the specified command as a subprocess; the subprocess's
6445  * standard input and output will be connected to the returned
6446  * <code>IO</code> object.
6447  *
6448  * The PID of the started process can be obtained by IO#pid method.
6449  *
6450  * _cmd_ is a string or an array as follows.
6451  *
6452  * cmd:
6453  * "-" : fork
6454  * commandline : command line string which is passed to a shell
6455  * [env, cmdname, arg1, ..., opts] : command name and zero or more arguments (no shell)
6456  * [env, [cmdname, argv0], arg1, ..., opts] : command name, argv[0] and zero or more arguments (no shell)
6457  * (env and opts are optional.)
6458  *
6459  * If _cmd_ is a +String+ ``<code>-</code>'',
6460  * then a new instance of Ruby is started as the subprocess.
6461  *
6462  * If <i>cmd</i> is an +Array+ of +String+,
6463  * then it will be used as the subprocess's +argv+ bypassing a shell.
6464  * The array can contain a hash at first for environments and
6465  * a hash at last for options similar to <code>spawn</code>.
6466  *
6467  * The default mode for the new file object is ``r'',
6468  * but <i>mode</i> may be set to any of the modes listed in the description for class IO.
6469  * The last argument <i>opt</i> qualifies <i>mode</i>.
6470  *
6471  * # set IO encoding
6472  * IO.popen("nkf -e filename", :external_encoding=>"EUC-JP") {|nkf_io|
6473  * euc_jp_string = nkf_io.read
6474  * }
6475  *
6476  * # merge standard output and standard error using
6477  * # spawn option. See the document of Kernel.spawn.
6478  * IO.popen(["ls", "/", :err=>[:child, :out]]) {|ls_io|
6479  * ls_result_with_error = ls_io.read
6480  * }
6481  *
6482  * # spawn options can be mixed with IO options
6483  * IO.popen(["ls", "/"], :err=>[:child, :out]) {|ls_io|
6484  * ls_result_with_error = ls_io.read
6485  * }
6486  *
6487  * Raises exceptions which <code>IO.pipe</code> and
6488  * <code>Kernel.spawn</code> raise.
6489  *
6490  * If a block is given, Ruby will run the command as a child connected
6491  * to Ruby with a pipe. Ruby's end of the pipe will be passed as a
6492  * parameter to the block.
6493  * At the end of block, Ruby closes the pipe and sets <code>$?</code>.
6494  * In this case <code>IO.popen</code> returns
6495  * the value of the block.
6496  *
6497  * If a block is given with a _cmd_ of ``<code>-</code>'',
6498  * the block will be run in two separate processes: once in the parent,
6499  * and once in a child. The parent process will be passed the pipe
6500  * object as a parameter to the block, the child version of the block
6501  * will be passed +nil+, and the child's standard in and
6502  * standard out will be connected to the parent through the pipe. Not
6503  * available on all platforms.
6504  *
6505  * f = IO.popen("uname")
6506  * p f.readlines
6507  * f.close
6508  * puts "Parent is #{Process.pid}"
6509  * IO.popen("date") {|f| puts f.gets }
6510  * IO.popen("-") {|f| $stderr.puts "#{Process.pid} is here, f is #{f.inspect}"}
6511  * p $?
6512  * IO.popen(%w"sed -e s|^|<foo>| -e s&$&;zot;&", "r+") {|f|
6513  * f.puts "bar"; f.close_write; puts f.gets
6514  * }
6515  *
6516  * <em>produces:</em>
6517  *
6518  * ["Linux\n"]
6519  * Parent is 21346
6520  * Thu Jan 15 22:41:19 JST 2009
6521  * 21346 is here, f is #<IO:fd 3>
6522  * 21352 is here, f is nil
6523  * #<Process::Status: pid 21352 exit 0>
6524  * <foo>bar;zot;
6525  */
6526 
6527 static VALUE
6528 rb_io_s_popen(int argc, VALUE *argv, VALUE klass)
6529 {
6530  const char *modestr;
6531  VALUE pname, pmode = Qnil, port, tmp, opt = Qnil, env = Qnil, execarg_obj = Qnil;
6532  int oflags, fmode;
6533  convconfig_t convconfig;
6534 
6535  if (argc > 1 && !NIL_P(opt = rb_check_hash_type(argv[argc-1]))) --argc;
6536  if (argc > 1 && !NIL_P(env = rb_check_hash_type(argv[0]))) --argc, ++argv;
6537  switch (argc) {
6538  case 2:
6539  pmode = argv[1];
6540  case 1:
6541  pname = argv[0];
6542  break;
6543  default:
6544  {
6545  int ex = !NIL_P(opt);
6546  rb_error_arity(argc + ex, 1 + ex, 2 + ex);
6547  }
6548  }
6549 
6550  tmp = rb_check_array_type(pname);
6551  if (!NIL_P(tmp)) {
6552  long len = RARRAY_LEN(tmp);
6553 #if SIZEOF_LONG > SIZEOF_INT
6554  if (len > INT_MAX) {
6555  rb_raise(rb_eArgError, "too many arguments");
6556  }
6557 #endif
6558  execarg_obj = rb_execarg_new((int)len, RARRAY_CONST_PTR(tmp), FALSE);
6559  RB_GC_GUARD(tmp);
6560  }
6561  else {
6562  SafeStringValue(pname);
6563  execarg_obj = Qnil;
6564  if (!is_popen_fork(pname))
6565  execarg_obj = rb_execarg_new(1, &pname, TRUE);
6566  }
6567  if (!NIL_P(execarg_obj)) {
6568  if (!NIL_P(opt))
6569  opt = rb_execarg_extract_options(execarg_obj, opt);
6570  if (!NIL_P(env))
6571  rb_execarg_setenv(execarg_obj, env);
6572  }
6573  rb_io_extract_modeenc(&pmode, 0, opt, &oflags, &fmode, &convconfig);
6574  modestr = rb_io_oflags_modestr(oflags);
6575 
6576  port = pipe_open(execarg_obj, modestr, fmode, &convconfig);
6577  if (NIL_P(port)) {
6578  /* child */
6579  if (rb_block_given_p()) {
6580  rb_yield(Qnil);
6583  _exit(0);
6584  }
6585  return Qnil;
6586  }
6587  RBASIC_SET_CLASS(port, klass);
6588  if (rb_block_given_p()) {
6589  return rb_ensure(rb_yield, port, pipe_close, port);
6590  }
6591  return port;
6592 }
6593 
6594 static void
6595 rb_scan_open_args(int argc, const VALUE *argv,
6596  VALUE *fname_p, int *oflags_p, int *fmode_p,
6597  convconfig_t *convconfig_p, mode_t *perm_p)
6598 {
6599  VALUE opt, fname, vmode, vperm;
6600  int oflags, fmode;
6601  mode_t perm;
6602 
6603  argc = rb_scan_args(argc, argv, "12:", &fname, &vmode, &vperm, &opt);
6604  FilePathValue(fname);
6605 
6606  rb_io_extract_modeenc(&vmode, &vperm, opt, &oflags, &fmode, convconfig_p);
6607 
6608  perm = NIL_P(vperm) ? 0666 : NUM2MODET(vperm);
6609 
6610  *fname_p = fname;
6611  *oflags_p = oflags;
6612  *fmode_p = fmode;
6613  *perm_p = perm;
6614 }
6615 
6616 static VALUE
6617 rb_open_file(int argc, const VALUE *argv, VALUE io)
6618 {
6619  VALUE fname;
6620  int oflags, fmode;
6621  convconfig_t convconfig;
6622  mode_t perm;
6623 
6624  rb_scan_open_args(argc, argv, &fname, &oflags, &fmode, &convconfig, &perm);
6625  rb_file_open_generic(io, fname, oflags, fmode, &convconfig, perm);
6626 
6627  return io;
6628 }
6629 
6630 
6631 /*
6632  * Document-method: File::open
6633  *
6634  * call-seq:
6635  * File.open(filename, mode="r" [, opt]) -> file
6636  * File.open(filename [, mode [, perm]] [, opt]) -> file
6637  * File.open(filename, mode="r" [, opt]) {|file| block } -> obj
6638  * File.open(filename [, mode [, perm]] [, opt]) {|file| block } -> obj
6639  *
6640  * With no associated block, <code>File.open</code> is a synonym for
6641  * File.new. If the optional code block is given, it will
6642  * be passed the opened +file+ as an argument and the File object will
6643  * automatically be closed when the block terminates. The value of the block
6644  * will be returned from <code>File.open</code>.
6645  *
6646  * If a file is being created, its initial permissions may be set using the
6647  * +perm+ parameter. See File.new for further discussion.
6648  *
6649  * See IO.new for a description of the +mode+ and +opt+ parameters.
6650  */
6651 
6652 /*
6653  * Document-method: IO::open
6654  *
6655  * call-seq:
6656  * IO.open(fd, mode="r" [, opt]) -> io
6657  * IO.open(fd, mode="r" [, opt]) {|io| block } -> obj
6658  *
6659  * With no associated block, <code>IO.open</code> is a synonym for IO.new. If
6660  * the optional code block is given, it will be passed +io+ as an argument,
6661  * and the IO object will automatically be closed when the block terminates.
6662  * In this instance, IO.open returns the value of the block.
6663  *
6664  * See IO.new for a description of the +fd+, +mode+ and +opt+ parameters.
6665  */
6666 
6667 static VALUE
6668 rb_io_s_open(int argc, VALUE *argv, VALUE klass)
6669 {
6670  VALUE io = rb_class_new_instance(argc, argv, klass);
6671 
6672  if (rb_block_given_p()) {
6673  return rb_ensure(rb_yield, io, io_close, io);
6674  }
6675 
6676  return io;
6677 }
6678 
6679 /*
6680  * call-seq:
6681  * IO.sysopen(path, [mode, [perm]]) -> integer
6682  *
6683  * Opens the given path, returning the underlying file descriptor as a
6684  * <code>Integer</code>.
6685  *
6686  * IO.sysopen("testfile") #=> 3
6687  */
6688 
6689 static VALUE
6690 rb_io_s_sysopen(int argc, VALUE *argv)
6691 {
6692  VALUE fname, vmode, vperm;
6693  VALUE intmode;
6694  int oflags, fd;
6695  mode_t perm;
6696 
6697  rb_scan_args(argc, argv, "12", &fname, &vmode, &vperm);
6698  FilePathValue(fname);
6699 
6700  if (NIL_P(vmode))
6701  oflags = O_RDONLY;
6702  else if (!NIL_P(intmode = rb_check_to_integer(vmode, "to_int")))
6703  oflags = NUM2INT(intmode);
6704  else {
6705  SafeStringValue(vmode);
6706  oflags = rb_io_modestr_oflags(StringValueCStr(vmode));
6707  }
6708  if (NIL_P(vperm)) perm = 0666;
6709  else perm = NUM2MODET(vperm);
6710 
6711  RB_GC_GUARD(fname) = rb_str_new4(fname);
6712  fd = rb_sysopen(fname, oflags, perm);
6713  return INT2NUM(fd);
6714 }
6715 
6716 static VALUE
6717 check_pipe_command(VALUE filename_or_command)
6718 {
6719  char *s = RSTRING_PTR(filename_or_command);
6720  long l = RSTRING_LEN(filename_or_command);
6721  char *e = s + l;
6722  int chlen;
6723 
6724  if (rb_enc_ascget(s, e, &chlen, rb_enc_get(filename_or_command)) == '|') {
6725  VALUE cmd = rb_str_new(s+chlen, l-chlen);
6726  OBJ_INFECT(cmd, filename_or_command);
6727  return cmd;
6728  }
6729  return Qnil;
6730 }
6731 
6732 /*
6733  * call-seq:
6734  * open(path [, mode [, perm]] [, opt]) -> io or nil
6735  * open(path [, mode [, perm]] [, opt]) {|io| block } -> obj
6736  *
6737  * Creates an IO object connected to the given stream, file, or subprocess.
6738  *
6739  * If +path+ does not start with a pipe character (<code>|</code>), treat it
6740  * as the name of a file to open using the specified mode (defaulting to
6741  * "r").
6742  *
6743  * The +mode+ is either a string or an integer. If it is an integer, it
6744  * must be bitwise-or of open(2) flags, such as File::RDWR or File::EXCL. If
6745  * it is a string, it is either "fmode", "fmode:ext_enc", or
6746  * "fmode:ext_enc:int_enc".
6747  *
6748  * See the documentation of IO.new for full documentation of the +mode+ string
6749  * directives.
6750  *
6751  * If a file is being created, its initial permissions may be set using the
6752  * +perm+ parameter. See File.new and the open(2) and chmod(2) man pages for
6753  * a description of permissions.
6754  *
6755  * If a block is specified, it will be invoked with the IO object as a
6756  * parameter, and the IO will be automatically closed when the block
6757  * terminates. The call returns the value of the block.
6758  *
6759  * If +path+ starts with a pipe character (<code>"|"</code>), a subprocess is
6760  * created, connected to the caller by a pair of pipes. The returned IO
6761  * object may be used to write to the standard input and read from the
6762  * standard output of this subprocess.
6763  *
6764  * If the command following the pipe is a single minus sign
6765  * (<code>"|-"</code>), Ruby forks, and this subprocess is connected to the
6766  * parent. If the command is not <code>"-"</code>, the subprocess runs the
6767  * command.
6768  *
6769  * When the subprocess is Ruby (opened via <code>"|-"</code>), the +open+
6770  * call returns +nil+. If a block is associated with the open call, that
6771  * block will run twice --- once in the parent and once in the child.
6772  *
6773  * The block parameter will be an IO object in the parent and +nil+ in the
6774  * child. The parent's +IO+ object will be connected to the child's $stdin
6775  * and $stdout. The subprocess will be terminated at the end of the block.
6776  *
6777  * === Examples
6778  *
6779  * Reading from "testfile":
6780  *
6781  * open("testfile") do |f|
6782  * print f.gets
6783  * end
6784  *
6785  * Produces:
6786  *
6787  * This is line one
6788  *
6789  * Open a subprocess and read its output:
6790  *
6791  * cmd = open("|date")
6792  * print cmd.gets
6793  * cmd.close
6794  *
6795  * Produces:
6796  *
6797  * Wed Apr 9 08:56:31 CDT 2003
6798  *
6799  * Open a subprocess running the same Ruby program:
6800  *
6801  * f = open("|-", "w+")
6802  * if f.nil?
6803  * puts "in Child"
6804  * exit
6805  * else
6806  * puts "Got: #{f.gets}"
6807  * end
6808  *
6809  * Produces:
6810  *
6811  * Got: in Child
6812  *
6813  * Open a subprocess using a block to receive the IO object:
6814  *
6815  * open "|-" do |f|
6816  * if f then
6817  * # parent process
6818  * puts "Got: #{f.gets}"
6819  * else
6820  * # child process
6821  * puts "in Child"
6822  * end
6823  * end
6824  *
6825  * Produces:
6826  *
6827  * Got: in Child
6828  */
6829 
6830 static VALUE
6831 rb_f_open(int argc, VALUE *argv)
6832 {
6833  ID to_open = 0;
6834  int redirect = FALSE;
6835 
6836  if (argc >= 1) {
6837  CONST_ID(to_open, "to_open");
6838  if (rb_respond_to(argv[0], to_open)) {
6839  redirect = TRUE;
6840  }
6841  else {
6842  VALUE tmp = argv[0];
6843  FilePathValue(tmp);
6844  if (NIL_P(tmp)) {
6845  redirect = TRUE;
6846  }
6847  else {
6848  VALUE cmd = check_pipe_command(tmp);
6849  if (!NIL_P(cmd)) {
6850  argv[0] = cmd;
6851  return rb_io_s_popen(argc, argv, rb_cIO);
6852  }
6853  }
6854  }
6855  }
6856  if (redirect) {
6857  VALUE io = rb_funcallv(argv[0], to_open, argc-1, argv+1);
6858 
6859  if (rb_block_given_p()) {
6860  return rb_ensure(rb_yield, io, io_close, io);
6861  }
6862  return io;
6863  }
6864  return rb_io_s_open(argc, argv, rb_cFile);
6865 }
6866 
6867 static VALUE rb_io_open_generic(VALUE, int, int, const convconfig_t *, mode_t);
6868 
6869 static VALUE
6870 rb_io_open(VALUE filename, VALUE vmode, VALUE vperm, VALUE opt)
6871 {
6872  int oflags, fmode;
6873  convconfig_t convconfig;
6874  mode_t perm;
6875 
6876  rb_io_extract_modeenc(&vmode, &vperm, opt, &oflags, &fmode, &convconfig);
6877  perm = NIL_P(vperm) ? 0666 : NUM2MODET(vperm);
6878  return rb_io_open_generic(filename, oflags, fmode, &convconfig, perm);
6879 }
6880 
6881 static VALUE
6882 rb_io_open_generic(VALUE filename, int oflags, int fmode,
6883  const convconfig_t *convconfig, mode_t perm)
6884 {
6885  VALUE cmd;
6886  if (!NIL_P(cmd = check_pipe_command(filename))) {
6887  return pipe_open_s(cmd, rb_io_oflags_modestr(oflags), fmode, convconfig);
6888  }
6889  else {
6890  return rb_file_open_generic(io_alloc(rb_cFile), filename,
6891  oflags, fmode, convconfig, perm);
6892  }
6893 }
6894 
6895 static VALUE
6896 rb_io_open_with_args(int argc, const VALUE *argv)
6897 {
6898  VALUE io;
6899 
6900  io = io_alloc(rb_cFile);
6901  rb_open_file(argc, argv, io);
6902  return io;
6903 }
6904 
6905 static VALUE
6906 io_reopen(VALUE io, VALUE nfile)
6907 {
6908  rb_io_t *fptr, *orig;
6909  int fd, fd2;
6910  off_t pos = 0;
6911 
6912  nfile = rb_io_get_io(nfile);
6913  GetOpenFile(io, fptr);
6914  GetOpenFile(nfile, orig);
6915 
6916  if (fptr == orig) return io;
6917  if (IS_PREP_STDIO(fptr)) {
6918  if ((fptr->stdio_file == stdin && !(orig->mode & FMODE_READABLE)) ||
6919  (fptr->stdio_file == stdout && !(orig->mode & FMODE_WRITABLE)) ||
6920  (fptr->stdio_file == stderr && !(orig->mode & FMODE_WRITABLE))) {
6922  "%s can't change access mode from \"%s\" to \"%s\"",
6923  PREP_STDIO_NAME(fptr), rb_io_fmode_modestr(fptr->mode),
6924  rb_io_fmode_modestr(orig->mode));
6925  }
6926  }
6927  if (fptr->mode & FMODE_WRITABLE) {
6928  if (io_fflush(fptr) < 0)
6929  rb_sys_fail(0);
6930  }
6931  else {
6932  io_tell(fptr);
6933  }
6934  if (orig->mode & FMODE_READABLE) {
6935  pos = io_tell(orig);
6936  }
6937  if (orig->mode & FMODE_WRITABLE) {
6938  if (io_fflush(orig) < 0)
6939  rb_sys_fail(0);
6940  }
6941 
6942  /* copy rb_io_t structure */
6943  fptr->mode = orig->mode | (fptr->mode & FMODE_PREP);
6944  fptr->pid = orig->pid;
6945  fptr->lineno = orig->lineno;
6946  if (RTEST(orig->pathv)) fptr->pathv = orig->pathv;
6947  else if (!IS_PREP_STDIO(fptr)) fptr->pathv = Qnil;
6948  fptr->finalize = orig->finalize;
6949 #if defined (__CYGWIN__) || !defined(HAVE_WORKING_FORK)
6950  if (fptr->finalize == pipe_finalize)
6951  pipe_add_fptr(fptr);
6952 #endif
6953 
6954  fd = fptr->fd;
6955  fd2 = orig->fd;
6956  if (fd != fd2) {
6957  if (IS_PREP_STDIO(fptr) || fd <= 2 || !fptr->stdio_file) {
6958  /* need to keep FILE objects of stdin, stdout and stderr */
6959  if (rb_cloexec_dup2(fd2, fd) < 0)
6960  rb_sys_fail_path(orig->pathv);
6961  rb_update_max_fd(fd);
6962  }
6963  else {
6964  fclose(fptr->stdio_file);
6965  fptr->stdio_file = 0;
6966  fptr->fd = -1;
6967  if (rb_cloexec_dup2(fd2, fd) < 0)
6968  rb_sys_fail_path(orig->pathv);
6969  rb_update_max_fd(fd);
6970  fptr->fd = fd;
6971  }
6972  rb_notify_fd_close(fd);
6973  if ((orig->mode & FMODE_READABLE) && pos >= 0) {
6974  if (io_seek(fptr, pos, SEEK_SET) < 0 && errno) {
6975  rb_sys_fail_path(fptr->pathv);
6976  }
6977  if (io_seek(orig, pos, SEEK_SET) < 0 && errno) {
6978  rb_sys_fail_path(orig->pathv);
6979  }
6980  }
6981  }
6982 
6983  if (fptr->mode & FMODE_BINMODE) {
6984  rb_io_binmode(io);
6985  }
6986 
6987  RBASIC_SET_CLASS(io, rb_obj_class(nfile));
6988  return io;
6989 }
6990 
6991 #ifdef _WIN32
6992 int rb_freopen(VALUE fname, const char *mode, FILE *fp);
6993 #else
6994 static int
6995 rb_freopen(VALUE fname, const char *mode, FILE *fp)
6996 {
6997  if (!freopen(RSTRING_PTR(fname), mode, fp)) {
6998  RB_GC_GUARD(fname);
6999  return errno;
7000  }
7001  return 0;
7002 }
7003 #endif
7004 
7005 /*
7006  * call-seq:
7007  * ios.reopen(other_IO) -> ios
7008  * ios.reopen(path, mode_str) -> ios
7009  *
7010  * Reassociates <em>ios</em> with the I/O stream given in
7011  * <i>other_IO</i> or to a new stream opened on <i>path</i>. This may
7012  * dynamically change the actual class of this stream.
7013  *
7014  * f1 = File.new("testfile")
7015  * f2 = File.new("testfile")
7016  * f2.readlines[0] #=> "This is line one\n"
7017  * f2.reopen(f1) #=> #<File:testfile>
7018  * f2.readlines[0] #=> "This is line one\n"
7019  */
7020 
7021 static VALUE
7022 rb_io_reopen(int argc, VALUE *argv, VALUE file)
7023 {
7024  VALUE fname, nmode, opt;
7025  int oflags;
7026  rb_io_t *fptr;
7027 
7028  if (rb_scan_args(argc, argv, "11:", &fname, &nmode, &opt) == 1) {
7029  VALUE tmp = rb_io_check_io(fname);
7030  if (!NIL_P(tmp)) {
7031  return io_reopen(file, tmp);
7032  }
7033  }
7034 
7035  FilePathValue(fname);
7036  rb_io_taint_check(file);
7037  fptr = RFILE(file)->fptr;
7038  if (!fptr) {
7039  fptr = RFILE(file)->fptr = ZALLOC(rb_io_t);
7040  }
7041 
7042  if (!NIL_P(nmode) || !NIL_P(opt)) {
7043  int fmode;
7044  convconfig_t convconfig;
7045 
7046  rb_io_extract_modeenc(&nmode, 0, opt, &oflags, &fmode, &convconfig);
7047  if (IS_PREP_STDIO(fptr) &&
7048  ((fptr->mode & FMODE_READWRITE) & (fmode & FMODE_READWRITE)) !=
7049  (fptr->mode & FMODE_READWRITE)) {
7051  "%s can't change access mode from \"%s\" to \"%s\"",
7052  PREP_STDIO_NAME(fptr), rb_io_fmode_modestr(fptr->mode),
7053  rb_io_fmode_modestr(fmode));
7054  }
7055  fptr->mode = fmode;
7056  fptr->encs = convconfig;
7057  }
7058  else {
7059  oflags = rb_io_fmode_oflags(fptr->mode);
7060  }
7061 
7062  fptr->pathv = fname;
7063  if (fptr->fd < 0) {
7064  fptr->fd = rb_sysopen(fptr->pathv, oflags, 0666);
7065  fptr->stdio_file = 0;
7066  return file;
7067  }
7068 
7069  if (fptr->mode & FMODE_WRITABLE) {
7070  if (io_fflush(fptr) < 0)
7071  rb_sys_fail(0);
7072  }
7073  fptr->rbuf.off = fptr->rbuf.len = 0;
7074 
7075  if (fptr->stdio_file) {
7076  int e = rb_freopen(rb_str_encode_ospath(fptr->pathv),
7077  rb_io_oflags_modestr(oflags),
7078  fptr->stdio_file);
7079  if (e) rb_syserr_fail_path(e, fptr->pathv);
7080  fptr->fd = fileno(fptr->stdio_file);
7081  rb_fd_fix_cloexec(fptr->fd);
7082 #ifdef USE_SETVBUF
7083  if (setvbuf(fptr->stdio_file, NULL, _IOFBF, 0) != 0)
7084  rb_warn("setvbuf() can't be honoured for %"PRIsVALUE, fptr->pathv);
7085 #endif
7086  if (fptr->stdio_file == stderr) {
7087  if (setvbuf(fptr->stdio_file, NULL, _IONBF, BUFSIZ) != 0)
7088  rb_warn("setvbuf() can't be honoured for %"PRIsVALUE, fptr->pathv);
7089  }
7090  else if (fptr->stdio_file == stdout && isatty(fptr->fd)) {
7091  if (setvbuf(fptr->stdio_file, NULL, _IOLBF, BUFSIZ) != 0)
7092  rb_warn("setvbuf() can't be honoured for %"PRIsVALUE, fptr->pathv);
7093  }
7094  }
7095  else {
7096  int tmpfd = rb_sysopen(fptr->pathv, oflags, 0666);
7097  int err = 0;
7098  if (rb_cloexec_dup2(tmpfd, fptr->fd) < 0)
7099  err = errno;
7100  (void)close(tmpfd);
7101  if (err) {
7102  rb_syserr_fail_path(err, fptr->pathv);
7103  }
7104  }
7105 
7106  return file;
7107 }
7108 
7109 /* :nodoc: */
7110 static VALUE
7111 rb_io_init_copy(VALUE dest, VALUE io)
7112 {
7113  rb_io_t *fptr, *orig;
7114  int fd;
7115  VALUE write_io;
7116  off_t pos;
7117 
7118  io = rb_io_get_io(io);
7119  if (!OBJ_INIT_COPY(dest, io)) return dest;
7120  GetOpenFile(io, orig);
7121  MakeOpenFile(dest, fptr);
7122 
7123  rb_io_flush(io);
7124 
7125  /* copy rb_io_t structure */
7126  fptr->mode = orig->mode & ~FMODE_PREP;
7127  fptr->encs = orig->encs;
7128  fptr->pid = orig->pid;
7129  fptr->lineno = orig->lineno;
7130  if (!NIL_P(orig->pathv)) fptr->pathv = orig->pathv;
7131  fptr->finalize = orig->finalize;
7132 #if defined (__CYGWIN__) || !defined(HAVE_WORKING_FORK)
7133  if (fptr->finalize == pipe_finalize)
7134  pipe_add_fptr(fptr);
7135 #endif
7136 
7137  fd = ruby_dup(orig->fd);
7138  fptr->fd = fd;
7139  pos = io_tell(orig);
7140  if (0 <= pos)
7141  io_seek(fptr, pos, SEEK_SET);
7142  if (fptr->mode & FMODE_BINMODE) {
7143  rb_io_binmode(dest);
7144  }
7145 
7146  write_io = GetWriteIO(io);
7147  if (io != write_io) {
7148  write_io = rb_obj_dup(write_io);
7149  fptr->tied_io_for_writing = write_io;
7150  rb_ivar_set(dest, rb_intern("@tied_io_for_writing"), write_io);
7151  }
7152 
7153  return dest;
7154 }
7155 
7156 /*
7157  * call-seq:
7158  * ios.printf(format_string [, obj, ...]) -> nil
7159  *
7160  * Formats and writes to <em>ios</em>, converting parameters under
7161  * control of the format string. See <code>Kernel#sprintf</code>
7162  * for details.
7163  */
7164 
7165 VALUE
7166 rb_io_printf(int argc, const VALUE *argv, VALUE out)
7167 {
7168  rb_io_write(out, rb_f_sprintf(argc, argv));
7169  return Qnil;
7170 }
7171 
7172 /*
7173  * call-seq:
7174  * printf(io, string [, obj ... ]) -> nil
7175  * printf(string [, obj ... ]) -> nil
7176  *
7177  * Equivalent to:
7178  * io.write(sprintf(string, obj, ...))
7179  * or
7180  * $stdout.write(sprintf(string, obj, ...))
7181  */
7182 
7183 static VALUE
7184 rb_f_printf(int argc, VALUE *argv)
7185 {
7186  VALUE out;
7187 
7188  if (argc == 0) return Qnil;
7189  if (RB_TYPE_P(argv[0], T_STRING)) {
7190  out = rb_stdout;
7191  }
7192  else {
7193  out = argv[0];
7194  argv++;
7195  argc--;
7196  }
7197  rb_io_write(out, rb_f_sprintf(argc, argv));
7198 
7199  return Qnil;
7200 }
7201 
7202 /*
7203  * call-seq:
7204  * ios.print -> nil
7205  * ios.print(obj, ...) -> nil
7206  *
7207  * Writes the given object(s) to <em>ios</em>. Returns +nil+.
7208  *
7209  * The stream must be opened for writing.
7210  * Each given object that isn't a string will be converted by calling
7211  * its <code>to_s</code> method.
7212  * When called without arguments, prints the contents of <code>$_</code>.
7213  *
7214  * If the output field separator (<code>$,</code>) is not +nil+,
7215  * it is inserted between objects.
7216  * If the output record separator (<code>$\</code>) is not +nil+,
7217  * it is appended to the output.
7218  *
7219  * $stdout.print("This is ", 100, " percent.\n")
7220  *
7221  * <em>produces:</em>
7222  *
7223  * This is 100 percent.
7224  */
7225 
7226 VALUE
7227 rb_io_print(int argc, const VALUE *argv, VALUE out)
7228 {
7229  int i;
7230  VALUE line;
7231 
7232  /* if no argument given, print `$_' */
7233  if (argc == 0) {
7234  argc = 1;
7235  line = rb_lastline_get();
7236  argv = &line;
7237  }
7238  for (i=0; i<argc; i++) {
7239  if (!NIL_P(rb_output_fs) && i>0) {
7240  rb_io_write(out, rb_output_fs);
7241  }
7242  rb_io_write(out, argv[i]);
7243  }
7244  if (argc > 0 && !NIL_P(rb_output_rs)) {
7245  rb_io_write(out, rb_output_rs);
7246  }
7247 
7248  return Qnil;
7249 }
7250 
7251 /*
7252  * call-seq:
7253  * print(obj, ...) -> nil
7254  *
7255  * Prints each object in turn to <code>$stdout</code>. If the output
7256  * field separator (<code>$,</code>) is not +nil+, its
7257  * contents will appear between each field. If the output record
7258  * separator (<code>$\</code>) is not +nil+, it will be
7259  * appended to the output. If no arguments are given, prints
7260  * <code>$_</code>. Objects that aren't strings will be converted by
7261  * calling their <code>to_s</code> method.
7262  *
7263  * print "cat", [1,2,3], 99, "\n"
7264  * $, = ", "
7265  * $\ = "\n"
7266  * print "cat", [1,2,3], 99
7267  *
7268  * <em>produces:</em>
7269  *
7270  * cat12399
7271  * cat, 1, 2, 3, 99
7272  */
7273 
7274 static VALUE
7275 rb_f_print(int argc, const VALUE *argv)
7276 {
7277  rb_io_print(argc, argv, rb_stdout);
7278  return Qnil;
7279 }
7280 
7281 /*
7282  * call-seq:
7283  * ios.putc(obj) -> obj
7284  *
7285  * If <i>obj</i> is <code>Numeric</code>, write the character whose code is
7286  * the least-significant byte of <i>obj</i>, otherwise write the first byte
7287  * of the string representation of <i>obj</i> to <em>ios</em>. Note: This
7288  * method is not safe for use with multi-byte characters as it will truncate
7289  * them.
7290  *
7291  * $stdout.putc "A"
7292  * $stdout.putc 65
7293  *
7294  * <em>produces:</em>
7295  *
7296  * AA
7297  */
7298 
7299 static VALUE
7300 rb_io_putc(VALUE io, VALUE ch)
7301 {
7302  VALUE str;
7303  if (RB_TYPE_P(ch, T_STRING)) {
7304  str = rb_str_substr(ch, 0, 1);
7305  }
7306  else {
7307  char c = NUM2CHR(ch);
7308  str = rb_str_new(&c, 1);
7309  }
7310  rb_io_write(io, str);
7311  return ch;
7312 }
7313 
7314 /*
7315  * call-seq:
7316  * putc(int) -> int
7317  *
7318  * Equivalent to:
7319  *
7320  * $stdout.putc(int)
7321  *
7322  * Refer to the documentation for IO#putc for important information regarding
7323  * multi-byte characters.
7324  */
7325 
7326 static VALUE
7327 rb_f_putc(VALUE recv, VALUE ch)
7328 {
7329  if (recv == rb_stdout) {
7330  return rb_io_putc(recv, ch);
7331  }
7332  return rb_funcallv(rb_stdout, rb_intern("putc"), 1, &ch);
7333 }
7334 
7335 
7336 int
7338 {
7339  long len = RSTRING_LEN(str);
7340  const char *ptr = RSTRING_PTR(str);
7342  int n;
7343 
7344  if (len == 0) return 0;
7345  if ((n = rb_enc_mbminlen(enc)) == 1) {
7346  return ptr[len - 1] == c;
7347  }
7348  return rb_enc_ascget(ptr + ((len - 1) / n) * n, ptr + len, &n, enc) == c;
7349 }
7350 
7351 static VALUE
7352 io_puts_ary(VALUE ary, VALUE out, int recur)
7353 {
7354  VALUE tmp;
7355  long i;
7356 
7357  if (recur) {
7358  tmp = rb_str_new2("[...]");
7359  rb_io_puts(1, &tmp, out);
7360  return Qtrue;
7361  }
7362  ary = rb_check_array_type(ary);
7363  if (NIL_P(ary)) return Qfalse;
7364  for (i=0; i<RARRAY_LEN(ary); i++) {
7365  tmp = RARRAY_AREF(ary, i);
7366  rb_io_puts(1, &tmp, out);
7367  }
7368  return Qtrue;
7369 }
7370 
7371 /*
7372  * call-seq:
7373  * ios.puts(obj, ...) -> nil
7374  *
7375  * Writes the given object(s) to <em>ios</em>.
7376  * Writes a newline after any that do not already end
7377  * with a newline sequence. Returns +nil+.
7378  *
7379  * The stream must be opened for writing.
7380  * If called with an array argument, writes each element on a new line.
7381  * Each given object that isn't a string or array will be converted
7382  * by calling its +to_s+ method.
7383  * If called without arguments, outputs a single newline.
7384  *
7385  * $stdout.puts("this", "is", ["a", "test"])
7386  *
7387  * <em>produces:</em>
7388  *
7389  * this
7390  * is
7391  * a
7392  * test
7393  *
7394  * Note that +puts+ always uses newlines and is not affected
7395  * by the output record separator (<code>$\</code>).
7396  */
7397 
7398 VALUE
7399 rb_io_puts(int argc, const VALUE *argv, VALUE out)
7400 {
7401  int i;
7402  VALUE line;
7403 
7404  /* if no argument given, print newline. */
7405  if (argc == 0) {
7406  rb_io_write(out, rb_default_rs);
7407  return Qnil;
7408  }
7409  for (i=0; i<argc; i++) {
7410  if (RB_TYPE_P(argv[i], T_STRING)) {
7411  line = argv[i];
7412  goto string;
7413  }
7414  if (rb_exec_recursive(io_puts_ary, argv[i], out)) {
7415  continue;
7416  }
7417  line = rb_obj_as_string(argv[i]);
7418  string:
7419  rb_io_write(out, line);
7420  if (RSTRING_LEN(line) == 0 ||
7421  !rb_str_end_with_asciichar(line, '\n')) {
7422  rb_io_write(out, rb_default_rs);
7423  }
7424  }
7425 
7426  return Qnil;
7427 }
7428 
7429 /*
7430  * call-seq:
7431  * puts(obj, ...) -> nil
7432  *
7433  * Equivalent to
7434  *
7435  * $stdout.puts(obj, ...)
7436  */
7437 
7438 static VALUE
7439 rb_f_puts(int argc, VALUE *argv, VALUE recv)
7440 {
7441  if (recv == rb_stdout) {
7442  return rb_io_puts(argc, argv, recv);
7443  }
7444  return rb_funcallv(rb_stdout, rb_intern("puts"), argc, argv);
7445 }
7446 
7447 void
7448 rb_p(VALUE obj) /* for debug print within C code */
7449 {
7450  VALUE str = rb_obj_as_string(rb_inspect(obj));
7451  if (RB_TYPE_P(rb_stdout, T_FILE) &&
7453  io_write(rb_stdout, str, 1);
7454  io_write(rb_stdout, rb_default_rs, 0);
7455  }
7456  else {
7457  rb_io_write(rb_stdout, str);
7459  }
7460 }
7461 
7462 struct rb_f_p_arg {
7463  int argc;
7465 };
7466 
7467 static VALUE
7468 rb_f_p_internal(VALUE arg)
7469 {
7470  struct rb_f_p_arg *arg1 = (struct rb_f_p_arg*)arg;
7471  int argc = arg1->argc;
7472  VALUE *argv = arg1->argv;
7473  int i;
7474  VALUE ret = Qnil;
7475 
7476  for (i=0; i<argc; i++) {
7477  rb_p(argv[i]);
7478  }
7479  if (argc == 1) {
7480  ret = argv[0];
7481  }
7482  else if (argc > 1) {
7483  ret = rb_ary_new4(argc, argv);
7484  }
7485  if (RB_TYPE_P(rb_stdout, T_FILE)) {
7487  }
7488  return ret;
7489 }
7490 
7491 /*
7492  * call-seq:
7493  * p(obj) -> obj
7494  * p(obj1, obj2, ...) -> [obj, ...]
7495  * p() -> nil
7496  *
7497  * For each object, directly writes _obj_.+inspect+ followed by a
7498  * newline to the program's standard output.
7499  *
7500  * S = Struct.new(:name, :state)
7501  * s = S['dave', 'TX']
7502  * p s
7503  *
7504  * <em>produces:</em>
7505  *
7506  * #<S name="dave", state="TX">
7507  */
7508 
7509 static VALUE
7510 rb_f_p(int argc, VALUE *argv, VALUE self)
7511 {
7512  struct rb_f_p_arg arg;
7513  arg.argc = argc;
7514  arg.argv = argv;
7515 
7516  return rb_uninterruptible(rb_f_p_internal, (VALUE)&arg);
7517 }
7518 
7519 /*
7520  * call-seq:
7521  * obj.display(port=$>) -> nil
7522  *
7523  * Prints <i>obj</i> on the given port (default <code>$></code>).
7524  * Equivalent to:
7525  *
7526  * def display(port=$>)
7527  * port.write self
7528  * nil
7529  * end
7530  *
7531  * For example:
7532  *
7533  * 1.display
7534  * "cat".display
7535  * [ 4, 5, 6 ].display
7536  * puts
7537  *
7538  * <em>produces:</em>
7539  *
7540  * 1cat[4, 5, 6]
7541  */
7542 
7543 static VALUE
7544 rb_obj_display(int argc, VALUE *argv, VALUE self)
7545 {
7546  VALUE out;
7547 
7548  if (argc == 0) {
7549  out = rb_stdout;
7550  }
7551  else {
7552  rb_scan_args(argc, argv, "01", &out);
7553  }
7554  rb_io_write(out, self);
7555 
7556  return Qnil;
7557 }
7558 
7559 void
7560 rb_write_error2(const char *mesg, long len)
7561 {
7562  if (rb_stderr == orig_stderr || RFILE(orig_stderr)->fptr->fd < 0) {
7563  if (fwrite(mesg, sizeof(char), (size_t)len, stderr) < (size_t)len) {
7564  /* failed to write to stderr, what can we do? */
7565  return;
7566  }
7567  }
7568  else {
7569  rb_io_write(rb_stderr, rb_str_new(mesg, len));
7570  }
7571 }
7572 
7573 void
7574 rb_write_error(const char *mesg)
7575 {
7576  rb_write_error2(mesg, strlen(mesg));
7577 }
7578 
7579 void
7581 {
7582  /* a stopgap measure for the time being */
7583  if (rb_stderr == orig_stderr || RFILE(orig_stderr)->fptr->fd < 0) {
7584  size_t len = (size_t)RSTRING_LEN(mesg);
7585 #ifdef _WIN32
7586  if (isatty(fileno(stderr))) {
7587  if (rb_w32_write_console(mesg, fileno(stderr)) > 0) return;
7588  }
7589 #endif
7590  if (fwrite(RSTRING_PTR(mesg), sizeof(char), len, stderr) < len) {
7591  RB_GC_GUARD(mesg);
7592  return;
7593  }
7594  }
7595  else {
7596  /* may unlock GVL, and */
7597  rb_io_write(rb_stderr, mesg);
7598  }
7599 }
7600 
7601 int
7603 {
7604  if (rb_stderr == orig_stderr || RFILE(orig_stderr)->fptr->fd < 0)
7605  return isatty(fileno(stderr));
7606  return 0;
7607 }
7608 
7609 static void
7610 must_respond_to(ID mid, VALUE val, ID id)
7611 {
7612  if (!rb_respond_to(val, mid)) {
7613  rb_raise(rb_eTypeError, "%"PRIsVALUE" must have %"PRIsVALUE" method, %"PRIsVALUE" given",
7614  rb_id2str(id), rb_id2str(mid),
7615  rb_obj_class(val));
7616  }
7617 }
7618 
7619 static void
7620 stdout_setter(VALUE val, ID id, VALUE *variable)
7621 {
7622  must_respond_to(id_write, val, id);
7623  *variable = val;
7624 }
7625 
7626 static VALUE
7627 prep_io(int fd, int fmode, VALUE klass, const char *path)
7628 {
7629  rb_io_t *fp;
7630  VALUE io = io_alloc(klass);
7631 
7632  MakeOpenFile(io, fp);
7633  fp->fd = fd;
7634  fp->mode = fmode;
7635  if (!io_check_tty(fp)) {
7636 #ifdef __CYGWIN__
7637  fp->mode |= FMODE_BINMODE;
7638  setmode(fd, O_BINARY);
7639 #endif
7640  }
7641  if (path) fp->pathv = rb_obj_freeze(rb_str_new_cstr(path));
7642  rb_update_max_fd(fd);
7643 
7644  return io;
7645 }
7646 
7647 VALUE
7648 rb_io_fdopen(int fd, int oflags, const char *path)
7649 {
7650  VALUE klass = rb_cIO;
7651 
7652  if (path && strcmp(path, "-")) klass = rb_cFile;
7653  return prep_io(fd, rb_io_oflags_fmode(oflags), klass, path);
7654 }
7655 
7656 static VALUE
7657 prep_stdio(FILE *f, int fmode, VALUE klass, const char *path)
7658 {
7659  rb_io_t *fptr;
7660  VALUE io = prep_io(fileno(f), fmode|FMODE_PREP|DEFAULT_TEXTMODE, klass, path);
7661 
7662  GetOpenFile(io, fptr);
7664 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
7665  fptr->encs.ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
7666  if (fmode & FMODE_READABLE) {
7668  }
7669 #endif
7670  fptr->stdio_file = f;
7671 
7672  return io;
7673 }
7674 
7675 FILE *
7677 {
7678  if (!fptr->stdio_file) {
7679  int oflags = rb_io_fmode_oflags(fptr->mode);
7680  fptr->stdio_file = rb_fdopen(fptr->fd, rb_io_oflags_modestr(oflags));
7681  }
7682  return fptr->stdio_file;
7683 }
7684 
7685 static inline void
7686 rb_io_buffer_init(rb_io_buffer_t *buf)
7687 {
7688  buf->ptr = NULL;
7689  buf->off = 0;
7690  buf->len = 0;
7691  buf->capa = 0;
7692 }
7693 
7694 static inline rb_io_t *
7695 rb_io_fptr_new(void)
7696 {
7697  rb_io_t *fp = ALLOC(rb_io_t);
7698  fp->fd = -1;
7699  fp->stdio_file = NULL;
7700  fp->mode = 0;
7701  fp->pid = 0;
7702  fp->lineno = 0;
7703  fp->pathv = Qnil;
7704  fp->finalize = 0;
7705  rb_io_buffer_init(&fp->wbuf);
7706  rb_io_buffer_init(&fp->rbuf);
7707  rb_io_buffer_init(&fp->cbuf);
7708  fp->readconv = NULL;
7709  fp->writeconv = NULL;
7711  fp->writeconv_pre_ecflags = 0;
7712  fp->writeconv_pre_ecopts = Qnil;
7713  fp->writeconv_initialized = 0;
7714  fp->tied_io_for_writing = 0;
7715  fp->encs.enc = NULL;
7716  fp->encs.enc2 = NULL;
7717  fp->encs.ecflags = 0;
7718  fp->encs.ecopts = Qnil;
7719  fp->write_lock = 0;
7720  return fp;
7721 }
7722 
7723 rb_io_t *
7725 {
7726  rb_io_t *fp = 0;
7727 
7728  Check_Type(obj, T_FILE);
7729  if (RFILE(obj)->fptr) {
7730  rb_io_close(obj);
7731  rb_io_fptr_finalize(RFILE(obj)->fptr);
7732  RFILE(obj)->fptr = 0;
7733  }
7734  fp = rb_io_fptr_new();
7735  RFILE(obj)->fptr = fp;
7736  return fp;
7737 }
7738 
7739 /*
7740  * call-seq:
7741  * IO.new(fd [, mode] [, opt]) -> io
7742  *
7743  * Returns a new IO object (a stream) for the given integer file descriptor
7744  * +fd+ and +mode+ string. +opt+ may be used to specify parts of +mode+ in a
7745  * more readable fashion. See also IO.sysopen and IO.for_fd.
7746  *
7747  * IO.new is called by various File and IO opening methods such as IO::open,
7748  * Kernel#open, and File::open.
7749  *
7750  * === Open Mode
7751  *
7752  * When +mode+ is an integer it must be combination of the modes defined in
7753  * File::Constants (+File::RDONLY+, <code>File::WRONLY|File::CREAT</code>).
7754  * See the open(2) man page for more information.
7755  *
7756  * When +mode+ is a string it must be in one of the following forms:
7757  *
7758  * fmode
7759  * fmode ":" ext_enc
7760  * fmode ":" ext_enc ":" int_enc
7761  * fmode ":" "BOM|UTF-*"
7762  *
7763  * +fmode+ is an IO open mode string, +ext_enc+ is the external encoding for
7764  * the IO and +int_enc+ is the internal encoding.
7765  *
7766  * ==== IO Open Mode
7767  *
7768  * Ruby allows the following open modes:
7769  *
7770  * "r" Read-only, starts at beginning of file (default mode).
7771  *
7772  * "r+" Read-write, starts at beginning of file.
7773  *
7774  * "w" Write-only, truncates existing file
7775  * to zero length or creates a new file for writing.
7776  *
7777  * "w+" Read-write, truncates existing file to zero length
7778  * or creates a new file for reading and writing.
7779  *
7780  * "a" Write-only, each write call appends data at end of file.
7781  * Creates a new file for writing if file does not exist.
7782  *
7783  * "a+" Read-write, each write call appends data at end of file.
7784  * Creates a new file for reading and writing if file does
7785  * not exist.
7786  *
7787  * The following modes must be used separately, and along with one or more of
7788  * the modes seen above.
7789  *
7790  * "b" Binary file mode
7791  * Suppresses EOL <-> CRLF conversion on Windows. And
7792  * sets external encoding to ASCII-8BIT unless explicitly
7793  * specified.
7794  *
7795  * "t" Text file mode
7796  *
7797  * When the open mode of original IO is read only, the mode cannot be
7798  * changed to be writable. Similarly, the open mode cannot be changed from
7799  * write only to readable.
7800  *
7801  * When such a change is attempted the error is raised in different locations
7802  * according to the platform.
7803  *
7804  * === IO Encoding
7805  *
7806  * When +ext_enc+ is specified, strings read will be tagged by the encoding
7807  * when reading, and strings output will be converted to the specified
7808  * encoding when writing.
7809  *
7810  * When +ext_enc+ and +int_enc+ are specified read strings will be converted
7811  * from +ext_enc+ to +int_enc+ upon input, and written strings will be
7812  * converted from +int_enc+ to +ext_enc+ upon output. See Encoding for
7813  * further details of transcoding on input and output.
7814  *
7815  * If "BOM|UTF-8", "BOM|UTF-16LE" or "BOM|UTF16-BE" are used, Ruby checks for
7816  * a Unicode BOM in the input document to help determine the encoding. For
7817  * UTF-16 encodings the file open mode must be binary. When present, the BOM
7818  * is stripped and the external encoding from the BOM is used. When the BOM
7819  * is missing the given Unicode encoding is used as +ext_enc+. (The BOM-set
7820  * encoding option is case insensitive, so "bom|utf-8" is also valid.)
7821  *
7822  * === Options
7823  *
7824  * +opt+ can be used instead of +mode+ for improved readability. The
7825  * following keys are supported:
7826  *
7827  * :mode ::
7828  * Same as +mode+ parameter
7829  *
7830  * :flags ::
7831  * Specifies file open flags as integer.
7832  * If +mode+ parameter is given, this parameter will be bitwise-ORed.
7833  *
7834  * :\external_encoding ::
7835  * External encoding for the IO. "-" is a synonym for the default external
7836  * encoding.
7837  *
7838  * :\internal_encoding ::
7839  * Internal encoding for the IO. "-" is a synonym for the default internal
7840  * encoding.
7841  *
7842  * If the value is +nil+ no conversion occurs.
7843  *
7844  * :encoding ::
7845  * Specifies external and internal encodings as "extern:intern".
7846  *
7847  * :textmode ::
7848  * If the value is truth value, same as "t" in argument +mode+.
7849  *
7850  * :binmode ::
7851  * If the value is truth value, same as "b" in argument +mode+.
7852  *
7853  * :autoclose ::
7854  * If the value is +false+, the +fd+ will be kept open after this IO
7855  * instance gets finalized.
7856  *
7857  * Also, +opt+ can have same keys in String#encode for controlling conversion
7858  * between the external encoding and the internal encoding.
7859  *
7860  * === Example 1
7861  *
7862  * fd = IO.sysopen("/dev/tty", "w")
7863  * a = IO.new(fd,"w")
7864  * $stderr.puts "Hello"
7865  * a.puts "World"
7866  *
7867  * Produces:
7868  *
7869  * Hello
7870  * World
7871  *
7872  * === Example 2
7873  *
7874  * require 'fcntl'
7875  *
7876  * fd = STDERR.fcntl(Fcntl::F_DUPFD)
7877  * io = IO.new(fd, mode: 'w:UTF-16LE', cr_newline: true)
7878  * io.puts "Hello, World!"
7879  *
7880  * fd = STDERR.fcntl(Fcntl::F_DUPFD)
7881  * io = IO.new(fd, mode: 'w', cr_newline: true,
7882  * external_encoding: Encoding::UTF_16LE)
7883  * io.puts "Hello, World!"
7884  *
7885  * Both of above print "Hello, World!" in UTF-16LE to standard error output
7886  * with converting EOL generated by <code>puts</code> to CR.
7887  */
7888 
7889 static VALUE
7890 rb_io_initialize(int argc, VALUE *argv, VALUE io)
7891 {
7892  VALUE fnum, vmode;
7893  rb_io_t *fp;
7894  int fd, fmode, oflags = O_RDONLY;
7895  convconfig_t convconfig;
7896  VALUE opt;
7897 #if defined(HAVE_FCNTL) && defined(F_GETFL)
7898  int ofmode;
7899 #else
7900  struct stat st;
7901 #endif
7902 
7903 
7904  argc = rb_scan_args(argc, argv, "11:", &fnum, &vmode, &opt);
7905  rb_io_extract_modeenc(&vmode, 0, opt, &oflags, &fmode, &convconfig);
7906 
7907  fd = NUM2INT(fnum);
7908  if (rb_reserved_fd_p(fd)) {
7909  rb_raise(rb_eArgError, "The given fd is not accessible because RubyVM reserves it");
7910  }
7911 #if defined(HAVE_FCNTL) && defined(F_GETFL)
7912  oflags = fcntl(fd, F_GETFL);
7913  if (oflags == -1) rb_sys_fail(0);
7914 #else
7915  if (fstat(fd, &st) == -1) rb_sys_fail(0);
7916 #endif
7917  rb_update_max_fd(fd);
7918 #if defined(HAVE_FCNTL) && defined(F_GETFL)
7919  ofmode = rb_io_oflags_fmode(oflags);
7920  if (NIL_P(vmode)) {
7921  fmode = ofmode;
7922  }
7923  else if ((~ofmode & fmode) & FMODE_READWRITE) {
7924  VALUE error = INT2FIX(EINVAL);
7926  }
7927 #endif
7928  if (!NIL_P(opt) && rb_hash_aref(opt, sym_autoclose) == Qfalse) {
7929  fmode |= FMODE_PREP;
7930  }
7931  MakeOpenFile(io, fp);
7932  fp->fd = fd;
7933  fp->mode = fmode;
7934  fp->encs = convconfig;
7935  clear_codeconv(fp);
7936  io_check_tty(fp);
7937  if (fileno(stdin) == fd)
7938  fp->stdio_file = stdin;
7939  else if (fileno(stdout) == fd)
7940  fp->stdio_file = stdout;
7941  else if (fileno(stderr) == fd)
7942  fp->stdio_file = stderr;
7943 
7944  if (fmode & FMODE_SETENC_BY_BOM) io_set_encoding_by_bom(io);
7945  return io;
7946 }
7947 
7948 /*
7949  * call-seq:
7950  * File.new(filename, mode="r" [, opt]) -> file
7951  * File.new(filename [, mode [, perm]] [, opt]) -> file
7952  *
7953  * Opens the file named by +filename+ according to the given +mode+ and
7954  * returns a new File object.
7955  *
7956  * See IO.new for a description of +mode+ and +opt+.
7957  *
7958  * If a file is being created, permission bits may be given in +perm+. These
7959  * mode and permission bits are platform dependent; on Unix systems, see
7960  * open(2) and chmod(2) man pages for details.
7961  *
7962  * The new File object is buffered mode (or non-sync mode), unless
7963  * +filename+ is a tty.
7964  * See IO#flush, IO#fsync, IO#fdatasync, and <code>IO#sync=</code>
7965  * about sync mode.
7966  *
7967  * === Examples
7968  *
7969  * f = File.new("testfile", "r")
7970  * f = File.new("newfile", "w+")
7971  * f = File.new("newfile", File::CREAT|File::TRUNC|File::RDWR, 0644)
7972  */
7973 
7974 static VALUE
7975 rb_file_initialize(int argc, VALUE *argv, VALUE io)
7976 {
7977  if (RFILE(io)->fptr) {
7978  rb_raise(rb_eRuntimeError, "reinitializing File");
7979  }
7980  if (0 < argc && argc < 3) {
7981  VALUE fd = rb_check_to_int(argv[0]);
7982 
7983  if (!NIL_P(fd)) {
7984  argv[0] = fd;
7985  return rb_io_initialize(argc, argv, io);
7986  }
7987  }
7988  rb_open_file(argc, argv, io);
7989 
7990  return io;
7991 }
7992 
7993 /* :nodoc: */
7994 static VALUE
7995 rb_io_s_new(int argc, VALUE *argv, VALUE klass)
7996 {
7997  if (rb_block_given_p()) {
7998  VALUE cname = rb_obj_as_string(klass);
7999 
8000  rb_warn("%"PRIsVALUE"::new() does not take block; use %"PRIsVALUE"::open() instead",
8001  cname, cname);
8002  }
8003  return rb_class_new_instance(argc, argv, klass);
8004 }
8005 
8006 
8007 /*
8008  * call-seq:
8009  * IO.for_fd(fd, mode [, opt]) -> io
8010  *
8011  * Synonym for <code>IO.new</code>.
8012  *
8013  */
8014 
8015 static VALUE
8016 rb_io_s_for_fd(int argc, VALUE *argv, VALUE klass)
8017 {
8018  VALUE io = rb_obj_alloc(klass);
8019  rb_io_initialize(argc, argv, io);
8020  return io;
8021 }
8022 
8023 /*
8024  * call-seq:
8025  * ios.autoclose? -> true or false
8026  *
8027  * Returns +true+ if the underlying file descriptor of _ios_ will be
8028  * closed automatically at its finalization, otherwise +false+.
8029  */
8030 
8031 static VALUE
8032 rb_io_autoclose_p(VALUE io)
8033 {
8034  rb_io_t *fptr = RFILE(io)->fptr;
8035  rb_io_check_closed(fptr);
8036  return (fptr->mode & FMODE_PREP) ? Qfalse : Qtrue;
8037 }
8038 
8039 /*
8040  * call-seq:
8041  * io.autoclose = bool -> true or false
8042  *
8043  * Sets auto-close flag.
8044  *
8045  * f = open("/dev/null")
8046  * IO.for_fd(f.fileno)
8047  * # ...
8048  * f.gets # may cause IOError
8049  *
8050  * f = open("/dev/null")
8051  * IO.for_fd(f.fileno).autoclose = true
8052  * # ...
8053  * f.gets # won't cause IOError
8054  */
8055 
8056 static VALUE
8057 rb_io_set_autoclose(VALUE io, VALUE autoclose)
8058 {
8059  rb_io_t *fptr;
8060  GetOpenFile(io, fptr);
8061  if (!RTEST(autoclose))
8062  fptr->mode |= FMODE_PREP;
8063  else
8064  fptr->mode &= ~FMODE_PREP;
8065  return io;
8066 }
8067 
8068 static void
8069 argf_mark(void *ptr)
8070 {
8071  struct argf *p = ptr;
8072  rb_gc_mark(p->filename);
8074  rb_gc_mark(p->argv);
8075  rb_gc_mark(p->inplace);
8076  rb_gc_mark(p->encs.ecopts);
8077 }
8078 
8079 static size_t
8080 argf_memsize(const void *ptr)
8081 {
8082  const struct argf *p = ptr;
8083  size_t size = sizeof(*p);
8084  return size;
8085 }
8086 
8087 static const rb_data_type_t argf_type = {
8088  "ARGF",
8089  {argf_mark, RUBY_TYPED_DEFAULT_FREE, argf_memsize},
8091 };
8092 
8093 static inline void
8094 argf_init(struct argf *p, VALUE v)
8095 {
8096  p->filename = Qnil;
8097  p->current_file = Qnil;
8098  p->lineno = 0;
8099  p->argv = v;
8100 }
8101 
8102 static VALUE
8103 argf_alloc(VALUE klass)
8104 {
8105  struct argf *p;
8106  VALUE argf = TypedData_Make_Struct(klass, struct argf, &argf_type, p);
8107 
8108  argf_init(p, Qnil);
8109  return argf;
8110 }
8111 
8112 #undef rb_argv
8113 
8114 /* :nodoc: */
8115 static VALUE
8116 argf_initialize(VALUE argf, VALUE argv)
8117 {
8118  memset(&ARGF, 0, sizeof(ARGF));
8119  argf_init(&ARGF, argv);
8120 
8121  return argf;
8122 }
8123 
8124 /* :nodoc: */
8125 static VALUE
8126 argf_initialize_copy(VALUE argf, VALUE orig)
8127 {
8128  if (!OBJ_INIT_COPY(argf, orig)) return argf;
8129  ARGF = argf_of(orig);
8130  ARGF.argv = rb_obj_dup(ARGF.argv);
8131  return argf;
8132 }
8133 
8134 /*
8135  * call-seq:
8136  * ARGF.lineno = integer -> integer
8137  *
8138  * Sets the line number of +ARGF+ as a whole to the given +Integer+.
8139  *
8140  * +ARGF+ sets the line number automatically as you read data, so normally
8141  * you will not need to set it explicitly. To access the current line number
8142  * use +ARGF.lineno+.
8143  *
8144  * For example:
8145  *
8146  * ARGF.lineno #=> 0
8147  * ARGF.readline #=> "This is line 1\n"
8148  * ARGF.lineno #=> 1
8149  * ARGF.lineno = 0 #=> 0
8150  * ARGF.lineno #=> 0
8151  */
8152 static VALUE
8153 argf_set_lineno(VALUE argf, VALUE val)
8154 {
8155  ARGF.lineno = NUM2INT(val);
8156  ARGF.last_lineno = ARGF.lineno;
8157  return Qnil;
8158 }
8159 
8160 /*
8161  * call-seq:
8162  * ARGF.lineno -> integer
8163  *
8164  * Returns the current line number of ARGF as a whole. This value
8165  * can be set manually with +ARGF.lineno=+.
8166  *
8167  * For example:
8168  *
8169  * ARGF.lineno #=> 0
8170  * ARGF.readline #=> "This is line 1\n"
8171  * ARGF.lineno #=> 1
8172  */
8173 static VALUE
8174 argf_lineno(VALUE argf)
8175 {
8176  return INT2FIX(ARGF.lineno);
8177 }
8178 
8179 static VALUE
8180 argf_forward(int argc, VALUE *argv, VALUE argf)
8181 {
8182  return rb_funcall3(ARGF.current_file, rb_frame_this_func(), argc, argv);
8183 }
8184 
8185 #define next_argv() argf_next_argv(argf)
8186 #define ARGF_GENERIC_INPUT_P() \
8187  (ARGF.current_file == rb_stdin && !RB_TYPE_P(ARGF.current_file, T_FILE))
8188 #define ARGF_FORWARD(argc, argv) do {\
8189  if (ARGF_GENERIC_INPUT_P())\
8190  return argf_forward((argc), (argv), argf);\
8191 } while (0)
8192 #define NEXT_ARGF_FORWARD(argc, argv) do {\
8193  if (!next_argv()) return Qnil;\
8194  ARGF_FORWARD((argc), (argv));\
8195 } while (0)
8196 
8197 static void
8198 argf_close(VALUE argf)
8199 {
8200  VALUE file = ARGF.current_file;
8201  if (file == rb_stdin) return;
8202  if (RB_TYPE_P(file, T_FILE)) {
8203  rb_io_set_write_io(file, Qnil);
8204  }
8205  io_close(file);
8206  ARGF.init_p = -1;
8207 }
8208 
8209 static int
8210 argf_next_argv(VALUE argf)
8211 {
8212  char *fn;
8213  rb_io_t *fptr;
8214  int stdout_binmode = 0;
8215  int fmode;
8216 
8217  if (RB_TYPE_P(rb_stdout, T_FILE)) {
8218  GetOpenFile(rb_stdout, fptr);
8219  if (fptr->mode & FMODE_BINMODE)
8220  stdout_binmode = 1;
8221  }
8222 
8223  if (ARGF.init_p == 0) {
8224  if (!NIL_P(ARGF.argv) && RARRAY_LEN(ARGF.argv) > 0) {
8225  ARGF.next_p = 1;
8226  }
8227  else {
8228  ARGF.next_p = -1;
8229  }
8230  ARGF.init_p = 1;
8231  }
8232  else {
8233  if (NIL_P(ARGF.argv)) {
8234  ARGF.next_p = -1;
8235  }
8236  else if (ARGF.next_p == -1 && RARRAY_LEN(ARGF.argv) > 0) {
8237  ARGF.next_p = 1;
8238  }
8239  }
8240 
8241  if (ARGF.next_p == 1) {
8242  if (ARGF.init_p == 1) argf_close(argf);
8243  retry:
8244  if (RARRAY_LEN(ARGF.argv) > 0) {
8245  VALUE filename = rb_ary_shift(ARGF.argv);
8246  FilePathValue(filename);
8247  ARGF.filename = filename;
8248  fn = StringValueCStr(filename);
8249  if (RSTRING_LEN(filename) == 1 && fn[0] == '-') {
8250  ARGF.current_file = rb_stdin;
8251  if (ARGF.inplace) {
8252  rb_warn("Can't do inplace edit for stdio; skipping");
8253  goto retry;
8254  }
8255  }
8256  else {
8257  VALUE write_io = Qnil;
8258  int fr = rb_sysopen(filename, O_RDONLY, 0);
8259 
8260  if (ARGF.inplace) {
8261  struct stat st;
8262 #ifndef NO_SAFE_RENAME
8263  struct stat st2;
8264 #endif
8265  VALUE str;
8266  int fw;
8267 
8268  if (RB_TYPE_P(rb_stdout, T_FILE) && rb_stdout != orig_stdout) {
8270  }
8271  fstat(fr, &st);
8272  str = filename;
8273  if (!NIL_P(ARGF.inplace)) {
8274  VALUE suffix = ARGF.inplace;
8275  str = rb_str_dup(str);
8277  RSTRING_PTR(suffix), RSTRING_LEN(suffix),
8278  rb_enc_get(suffix), 0, Qnil))) {
8279  rb_str_append(str, suffix);
8280  }
8281 #ifdef NO_SAFE_RENAME
8282  (void)close(fr);
8283  (void)unlink(RSTRING_PTR(str));
8284  if (rename(fn, RSTRING_PTR(str)) < 0) {
8285  rb_warn("Can't rename %"PRIsVALUE" to %"PRIsVALUE": %s, skipping file",
8286  filename, str, strerror(errno));
8287  goto retry;
8288  }
8289  fr = rb_sysopen(str, O_RDONLY, 0);
8290 #else
8291  if (rename(fn, RSTRING_PTR(str)) < 0) {
8292  rb_warn("Can't rename %"PRIsVALUE" to %"PRIsVALUE": %s, skipping file",
8293  filename, str, strerror(errno));
8294  close(fr);
8295  goto retry;
8296  }
8297 #endif
8298  }
8299  else {
8300 #ifdef NO_SAFE_RENAME
8301  rb_fatal("Can't do inplace edit without backup");
8302 #else
8303  if (unlink(fn) < 0) {
8304  rb_warn("Can't remove %"PRIsVALUE": %s, skipping file",
8305  filename, strerror(errno));
8306  close(fr);
8307  goto retry;
8308  }
8309 #endif
8310  }
8311  fw = rb_sysopen(filename, O_WRONLY|O_CREAT|O_TRUNC, 0666);
8312 #ifndef NO_SAFE_RENAME
8313  fstat(fw, &st2);
8314 #ifdef HAVE_FCHMOD
8315  fchmod(fw, st.st_mode);
8316 #else
8317  chmod(fn, st.st_mode);
8318 #endif
8319  if (st.st_uid!=st2.st_uid || st.st_gid!=st2.st_gid) {
8320  int err;
8321 #ifdef HAVE_FCHOWN
8322  err = fchown(fw, st.st_uid, st.st_gid);
8323 #else
8324  err = chown(fn, st.st_uid, st.st_gid);
8325 #endif
8326  if (err && getuid() == 0 && st2.st_uid == 0) {
8327  const char *wkfn = RSTRING_PTR(filename);
8328  rb_warn("Can't set owner/group of %"PRIsVALUE" to same as %"PRIsVALUE": %s, skipping file",
8329  filename, str, strerror(errno));
8330  (void)close(fr);
8331  (void)close(fw);
8332  (void)unlink(wkfn);
8333  goto retry;
8334  }
8335  }
8336 #endif
8337  write_io = prep_io(fw, FMODE_WRITABLE, rb_cFile, fn);
8338  rb_stdout = write_io;
8339  if (stdout_binmode) rb_io_binmode(rb_stdout);
8340  }
8341  fmode = FMODE_READABLE;
8342  if (!ARGF.binmode) {
8343  fmode |= DEFAULT_TEXTMODE;
8344  }
8345  ARGF.current_file = prep_io(fr, fmode, rb_cFile, fn);
8346  if (!NIL_P(write_io)) {
8347  rb_io_set_write_io(ARGF.current_file, write_io);
8348  }
8349  }
8350  if (ARGF.binmode) rb_io_ascii8bit_binmode(ARGF.current_file);
8351  GetOpenFile(ARGF.current_file, fptr);
8352  if (ARGF.encs.enc) {
8353  fptr->encs = ARGF.encs;
8354  clear_codeconv(fptr);
8355  }
8356  else {
8357  fptr->encs.ecflags &= ~ECONV_NEWLINE_DECORATOR_MASK;
8358  if (!ARGF.binmode) {
8360 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
8361  fptr->encs.ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
8362 #endif
8363  }
8364  }
8365  ARGF.next_p = 0;
8366  }
8367  else {
8368  ARGF.next_p = 1;
8369  return FALSE;
8370  }
8371  }
8372  else if (ARGF.next_p == -1) {
8373  ARGF.current_file = rb_stdin;
8374  ARGF.filename = rb_str_new2("-");
8375  if (ARGF.inplace) {
8376  rb_warn("Can't do inplace edit for stdio");
8377  rb_stdout = orig_stdout;
8378  }
8379  }
8380  if (ARGF.init_p == -1) ARGF.init_p = 1;
8381  return TRUE;
8382 }
8383 
8384 static VALUE
8385 argf_getline(int argc, VALUE *argv, VALUE argf)
8386 {
8387  VALUE line;
8388  long lineno = ARGF.lineno;
8389 
8390  retry:
8391  if (!next_argv()) return Qnil;
8392  if (ARGF_GENERIC_INPUT_P()) {
8393  line = rb_funcall3(ARGF.current_file, idGets, argc, argv);
8394  }
8395  else {
8396  if (argc == 0 && rb_rs == rb_default_rs) {
8397  line = rb_io_gets(ARGF.current_file);
8398  }
8399  else {
8400  line = rb_io_getline(argc, argv, ARGF.current_file);
8401  }
8402  if (NIL_P(line) && ARGF.next_p != -1) {
8403  argf_close(argf);
8404  ARGF.next_p = 1;
8405  goto retry;
8406  }
8407  }
8408  if (!NIL_P(line)) {
8409  ARGF.lineno = ++lineno;
8410  ARGF.last_lineno = ARGF.lineno;
8411  }
8412  return line;
8413 }
8414 
8415 static VALUE
8416 argf_lineno_getter(ID id, VALUE *var)
8417 {
8418  VALUE argf = *var;
8419  return INT2FIX(ARGF.last_lineno);
8420 }
8421 
8422 static void
8423 argf_lineno_setter(VALUE val, ID id, VALUE *var)
8424 {
8425  VALUE argf = *var;
8426  int n = NUM2INT(val);
8427  ARGF.last_lineno = ARGF.lineno = n;
8428 }
8429 
8430 static VALUE argf_gets(int, VALUE *, VALUE);
8431 
8432 /*
8433  * call-seq:
8434  * gets(sep=$/ [, getline_args]) -> string or nil
8435  * gets(limit [, getline_args]) -> string or nil
8436  * gets(sep, limit [, getline_args]) -> string or nil
8437  *
8438  * Returns (and assigns to <code>$_</code>) the next line from the list
8439  * of files in +ARGV+ (or <code>$*</code>), or from standard input if
8440  * no files are present on the command line. Returns +nil+ at end of
8441  * file. The optional argument specifies the record separator. The
8442  * separator is included with the contents of each record. A separator
8443  * of +nil+ reads the entire contents, and a zero-length separator
8444  * reads the input one paragraph at a time, where paragraphs are
8445  * divided by two consecutive newlines. If the first argument is an
8446  * integer, or optional second argument is given, the returning string
8447  * would not be longer than the given value in bytes. If multiple
8448  * filenames are present in +ARGV+, <code>gets(nil)</code> will read
8449  * the contents one file at a time.
8450  *
8451  * ARGV << "testfile"
8452  * print while gets
8453  *
8454  * <em>produces:</em>
8455  *
8456  * This is line one
8457  * This is line two
8458  * This is line three
8459  * And so on...
8460  *
8461  * The style of programming using <code>$_</code> as an implicit
8462  * parameter is gradually losing favor in the Ruby community.
8463  */
8464 
8465 static VALUE
8466 rb_f_gets(int argc, VALUE *argv, VALUE recv)
8467 {
8468  if (recv == argf) {
8469  return argf_gets(argc, argv, argf);
8470  }
8471  return rb_funcallv(argf, idGets, argc, argv);
8472 }
8473 
8474 /*
8475  * call-seq:
8476  * ARGF.gets(sep=$/ [, getline_args]) -> string or nil
8477  * ARGF.gets(limit [, getline_args]) -> string or nil
8478  * ARGF.gets(sep, limit [, getline_args]) -> string or nil
8479  *
8480  * Returns the next line from the current file in +ARGF+.
8481  *
8482  * By default lines are assumed to be separated by <code>$/</code>;
8483  * to use a different character as a separator, supply it as a +String+
8484  * for the _sep_ argument.
8485  *
8486  * The optional _limit_ argument specifies how many characters of each line
8487  * to return. By default all characters are returned.
8488  *
8489  * See <code>IO.readlines</code> for detail about getline_args.
8490  *
8491  */
8492 static VALUE
8493 argf_gets(int argc, VALUE *argv, VALUE argf)
8494 {
8495  VALUE line;
8496 
8497  line = argf_getline(argc, argv, argf);
8498  rb_lastline_set(line);
8499 
8500  return line;
8501 }
8502 
8503 VALUE
8504 rb_gets(void)
8505 {
8506  VALUE line;
8507 
8508  if (rb_rs != rb_default_rs) {
8509  return rb_f_gets(0, 0, argf);
8510  }
8511 
8512  retry:
8513  if (!next_argv()) return Qnil;
8514  line = rb_io_gets(ARGF.current_file);
8515  if (NIL_P(line) && ARGF.next_p != -1) {
8516  rb_io_close(ARGF.current_file);
8517  ARGF.next_p = 1;
8518  goto retry;
8519  }
8520  rb_lastline_set(line);
8521  if (!NIL_P(line)) {
8522  ARGF.lineno++;
8523  ARGF.last_lineno = ARGF.lineno;
8524  }
8525 
8526  return line;
8527 }
8528 
8529 static VALUE argf_readline(int, VALUE *, VALUE);
8530 
8531 /*
8532  * call-seq:
8533  * readline(sep=$/) -> string
8534  * readline(limit) -> string
8535  * readline(sep, limit) -> string
8536  *
8537  * Equivalent to <code>Kernel::gets</code>, except
8538  * +readline+ raises +EOFError+ at end of file.
8539  */
8540 
8541 static VALUE
8542 rb_f_readline(int argc, VALUE *argv, VALUE recv)
8543 {
8544  if (recv == argf) {
8545  return argf_readline(argc, argv, argf);
8546  }
8547  return rb_funcallv(argf, rb_intern("readline"), argc, argv);
8548 }
8549 
8550 
8551 /*
8552  * call-seq:
8553  * ARGF.readline(sep=$/) -> string
8554  * ARGF.readline(limit) -> string
8555  * ARGF.readline(sep, limit) -> string
8556  *
8557  * Returns the next line from the current file in +ARGF+.
8558  *
8559  * By default lines are assumed to be separated by <code>$/</code>;
8560  * to use a different character as a separator, supply it as a +String+
8561  * for the _sep_ argument.
8562  *
8563  * The optional _limit_ argument specifies how many characters of each line
8564  * to return. By default all characters are returned.
8565  *
8566  * An +EOFError+ is raised at the end of the file.
8567  */
8568 static VALUE
8569 argf_readline(int argc, VALUE *argv, VALUE argf)
8570 {
8571  VALUE line;
8572 
8573  if (!next_argv()) rb_eof_error();
8574  ARGF_FORWARD(argc, argv);
8575  line = argf_gets(argc, argv, argf);
8576  if (NIL_P(line)) {
8577  rb_eof_error();
8578  }
8579 
8580  return line;
8581 }
8582 
8583 static VALUE argf_readlines(int, VALUE *, VALUE);
8584 
8585 /*
8586  * call-seq:
8587  * readlines(sep=$/) -> array
8588  * readlines(limit) -> array
8589  * readlines(sep, limit) -> array
8590  *
8591  * Returns an array containing the lines returned by calling
8592  * <code>Kernel.gets(<i>sep</i>)</code> until the end of file.
8593  */
8594 
8595 static VALUE
8596 rb_f_readlines(int argc, VALUE *argv, VALUE recv)
8597 {
8598  if (recv == argf) {
8599  return argf_readlines(argc, argv, argf);
8600  }
8601  return rb_funcallv(argf, rb_intern("readlines"), argc, argv);
8602 }
8603 
8604 /*
8605  * call-seq:
8606  * ARGF.readlines(sep=$/) -> array
8607  * ARGF.readlines(limit) -> array
8608  * ARGF.readlines(sep, limit) -> array
8609  *
8610  * ARGF.to_a(sep=$/) -> array
8611  * ARGF.to_a(limit) -> array
8612  * ARGF.to_a(sep, limit) -> array
8613  *
8614  * Reads +ARGF+'s current file in its entirety, returning an +Array+ of its
8615  * lines, one line per element. Lines are assumed to be separated by _sep_.
8616  *
8617  * lines = ARGF.readlines
8618  * lines[0] #=> "This is line one\n"
8619  */
8620 static VALUE
8621 argf_readlines(int argc, VALUE *argv, VALUE argf)
8622 {
8623  long lineno = ARGF.lineno;
8624  VALUE lines, ary;
8625 
8626  ary = rb_ary_new();
8627  while (next_argv()) {
8628  if (ARGF_GENERIC_INPUT_P()) {
8629  lines = rb_funcall3(ARGF.current_file, rb_intern("readlines"), argc, argv);
8630  }
8631  else {
8632  lines = rb_io_readlines(argc, argv, ARGF.current_file);
8633  argf_close(argf);
8634  }
8635  ARGF.next_p = 1;
8636  rb_ary_concat(ary, lines);
8637  ARGF.lineno = lineno + RARRAY_LEN(ary);
8638  ARGF.last_lineno = ARGF.lineno;
8639  }
8640  ARGF.init_p = 0;
8641  return ary;
8642 }
8643 
8644 /*
8645  * call-seq:
8646  * `cmd` -> string
8647  *
8648  * Returns the standard output of running _cmd_ in a subshell.
8649  * The built-in syntax <code>%x{...}</code> uses
8650  * this method. Sets <code>$?</code> to the process status.
8651  *
8652  * `date` #=> "Wed Apr 9 08:56:30 CDT 2003\n"
8653  * `ls testdir`.split[1] #=> "main.rb"
8654  * `echo oops && exit 99` #=> "oops\n"
8655  * $?.exitstatus #=> 99
8656  */
8657 
8658 static VALUE
8659 rb_f_backquote(VALUE obj, VALUE str)
8660 {
8661  VALUE port;
8662  VALUE result;
8663  rb_io_t *fptr;
8664 
8665  SafeStringValue(str);
8667  port = pipe_open_s(str, "r", FMODE_READABLE|DEFAULT_TEXTMODE, NULL);
8668  if (NIL_P(port)) return rb_str_new(0,0);
8669 
8670  GetOpenFile(port, fptr);
8671  result = read_all(fptr, remain_size(fptr), Qnil);
8672  rb_io_close(port);
8673  rb_io_fptr_finalize(fptr);
8674  rb_gc_force_recycle(port); /* also guards from premature GC */
8675 
8676  return result;
8677 }
8678 
8679 #ifdef HAVE_SYS_SELECT_H
8680 #include <sys/select.h>
8681 #endif
8682 
8683 static VALUE
8684 select_internal(VALUE read, VALUE write, VALUE except, struct timeval *tp, rb_fdset_t *fds)
8685 {
8686  VALUE res, list;
8687  rb_fdset_t *rp, *wp, *ep;
8688  rb_io_t *fptr;
8689  long i;
8690  int max = 0, n;
8691  int pending = 0;
8692  struct timeval timerec;
8693 
8694  if (!NIL_P(read)) {
8695  Check_Type(read, T_ARRAY);
8696  for (i=0; i<RARRAY_LEN(read); i++) {
8697  GetOpenFile(rb_io_get_io(RARRAY_AREF(read, i)), fptr);
8698  rb_fd_set(fptr->fd, &fds[0]);
8699  if (READ_DATA_PENDING(fptr) || READ_CHAR_PENDING(fptr)) { /* check for buffered data */
8700  pending++;
8701  rb_fd_set(fptr->fd, &fds[3]);
8702  }
8703  if (max < fptr->fd) max = fptr->fd;
8704  }
8705  if (pending) { /* no blocking if there's buffered data */
8706  timerec.tv_sec = timerec.tv_usec = 0;
8707  tp = &timerec;
8708  }
8709  rp = &fds[0];
8710  }
8711  else
8712  rp = 0;
8713 
8714  if (!NIL_P(write)) {
8715  Check_Type(write, T_ARRAY);
8716  for (i=0; i<RARRAY_LEN(write); i++) {
8717  VALUE write_io = GetWriteIO(rb_io_get_io(RARRAY_AREF(write, i)));
8718  GetOpenFile(write_io, fptr);
8719  rb_fd_set(fptr->fd, &fds[1]);
8720  if (max < fptr->fd) max = fptr->fd;
8721  }
8722  wp = &fds[1];
8723  }
8724  else
8725  wp = 0;
8726 
8727  if (!NIL_P(except)) {
8728  Check_Type(except, T_ARRAY);
8729  for (i=0; i<RARRAY_LEN(except); i++) {
8730  VALUE io = rb_io_get_io(RARRAY_AREF(except, i));
8731  VALUE write_io = GetWriteIO(io);
8732  GetOpenFile(io, fptr);
8733  rb_fd_set(fptr->fd, &fds[2]);
8734  if (max < fptr->fd) max = fptr->fd;
8735  if (io != write_io) {
8736  GetOpenFile(write_io, fptr);
8737  rb_fd_set(fptr->fd, &fds[2]);
8738  if (max < fptr->fd) max = fptr->fd;
8739  }
8740  }
8741  ep = &fds[2];
8742  }
8743  else {
8744  ep = 0;
8745  }
8746 
8747  max++;
8748 
8749  n = rb_thread_fd_select(max, rp, wp, ep, tp);
8750  if (n < 0) {
8751  rb_sys_fail(0);
8752  }
8753  if (!pending && n == 0) return Qnil; /* returns nil on timeout */
8754 
8755  res = rb_ary_new2(3);
8756  rb_ary_push(res, rp?rb_ary_new():rb_ary_new2(0));
8757  rb_ary_push(res, wp?rb_ary_new():rb_ary_new2(0));
8758  rb_ary_push(res, ep?rb_ary_new():rb_ary_new2(0));
8759 
8760  if (rp) {
8761  list = RARRAY_AREF(res, 0);
8762  for (i=0; i< RARRAY_LEN(read); i++) {
8763  VALUE obj = rb_ary_entry(read, i);
8764  VALUE io = rb_io_get_io(obj);
8765  GetOpenFile(io, fptr);
8766  if (rb_fd_isset(fptr->fd, &fds[0]) ||
8767  rb_fd_isset(fptr->fd, &fds[3])) {
8768  rb_ary_push(list, obj);
8769  }
8770  }
8771  }
8772 
8773  if (wp) {
8774  list = RARRAY_AREF(res, 1);
8775  for (i=0; i< RARRAY_LEN(write); i++) {
8776  VALUE obj = rb_ary_entry(write, i);
8777  VALUE io = rb_io_get_io(obj);
8778  VALUE write_io = GetWriteIO(io);
8779  GetOpenFile(write_io, fptr);
8780  if (rb_fd_isset(fptr->fd, &fds[1])) {
8781  rb_ary_push(list, obj);
8782  }
8783  }
8784  }
8785 
8786  if (ep) {
8787  list = RARRAY_AREF(res, 2);
8788  for (i=0; i< RARRAY_LEN(except); i++) {
8789  VALUE obj = rb_ary_entry(except, i);
8790  VALUE io = rb_io_get_io(obj);
8791  VALUE write_io = GetWriteIO(io);
8792  GetOpenFile(io, fptr);
8793  if (rb_fd_isset(fptr->fd, &fds[2])) {
8794  rb_ary_push(list, obj);
8795  }
8796  else if (io != write_io) {
8797  GetOpenFile(write_io, fptr);
8798  if (rb_fd_isset(fptr->fd, &fds[2])) {
8799  rb_ary_push(list, obj);
8800  }
8801  }
8802  }
8803  }
8804 
8805  return res; /* returns an empty array on interrupt */
8806 }
8807 
8808 struct select_args {
8809  VALUE read, write, except;
8810  struct timeval *timeout;
8811  rb_fdset_t fdsets[4];
8812 };
8813 
8814 static VALUE
8815 select_call(VALUE arg)
8816 {
8817  struct select_args *p = (struct select_args *)arg;
8818 
8819  return select_internal(p->read, p->write, p->except, p->timeout, p->fdsets);
8820 }
8821 
8822 static VALUE
8823 select_end(VALUE arg)
8824 {
8825  struct select_args *p = (struct select_args *)arg;
8826  int i;
8827 
8828  for (i = 0; i < numberof(p->fdsets); ++i)
8829  rb_fd_term(&p->fdsets[i]);
8830  return Qnil;
8831 }
8832 
8833 static VALUE sym_normal, sym_sequential, sym_random,
8834  sym_willneed, sym_dontneed, sym_noreuse;
8835 
8836 #ifdef HAVE_POSIX_FADVISE
8837 struct io_advise_struct {
8838  int fd;
8839  int advice;
8840  off_t offset;
8841  off_t len;
8842 };
8843 
8844 static VALUE
8845 io_advise_internal(void *arg)
8846 {
8847  struct io_advise_struct *ptr = arg;
8848  return posix_fadvise(ptr->fd, ptr->offset, ptr->len, ptr->advice);
8849 }
8850 
8851 static VALUE
8852 io_advise_sym_to_const(VALUE sym)
8853 {
8854 #ifdef POSIX_FADV_NORMAL
8855  if (sym == sym_normal)
8856  return INT2NUM(POSIX_FADV_NORMAL);
8857 #endif
8858 
8859 #ifdef POSIX_FADV_RANDOM
8860  if (sym == sym_random)
8861  return INT2NUM(POSIX_FADV_RANDOM);
8862 #endif
8863 
8864 #ifdef POSIX_FADV_SEQUENTIAL
8865  if (sym == sym_sequential)
8866  return INT2NUM(POSIX_FADV_SEQUENTIAL);
8867 #endif
8868 
8869 #ifdef POSIX_FADV_WILLNEED
8870  if (sym == sym_willneed)
8871  return INT2NUM(POSIX_FADV_WILLNEED);
8872 #endif
8873 
8874 #ifdef POSIX_FADV_DONTNEED
8875  if (sym == sym_dontneed)
8876  return INT2NUM(POSIX_FADV_DONTNEED);
8877 #endif
8878 
8879 #ifdef POSIX_FADV_NOREUSE
8880  if (sym == sym_noreuse)
8881  return INT2NUM(POSIX_FADV_NOREUSE);
8882 #endif
8883 
8884  return Qnil;
8885 }
8886 
8887 static VALUE
8888 do_io_advise(rb_io_t *fptr, VALUE advice, off_t offset, off_t len)
8889 {
8890  int rv;
8891  struct io_advise_struct ias;
8892  VALUE num_adv;
8893 
8894  num_adv = io_advise_sym_to_const(advice);
8895 
8896  /*
8897  * The platform doesn't support this hint. We don't raise exception, instead
8898  * silently ignore it. Because IO::advise is only hint.
8899  */
8900  if (NIL_P(num_adv))
8901  return Qnil;
8902 
8903  ias.fd = fptr->fd;
8904  ias.advice = NUM2INT(num_adv);
8905  ias.offset = offset;
8906  ias.len = len;
8907 
8908  rv = (int)rb_thread_io_blocking_region(io_advise_internal, &ias, fptr->fd);
8909  if (rv && rv != ENOSYS) {
8910  /* posix_fadvise(2) doesn't set errno. On success it returns 0; otherwise
8911  it returns the error code. */
8912  VALUE message = rb_sprintf("%"PRIsVALUE" "
8913  "(%"PRI_OFFT_PREFIX"d, "
8914  "%"PRI_OFFT_PREFIX"d, "
8915  "%"PRIsVALUE")",
8916  fptr->pathv, offset, len, advice);
8917  rb_syserr_fail_str(rv, message);
8918  }
8919 
8920  return Qnil;
8921 }
8922 
8923 #endif /* HAVE_POSIX_FADVISE */
8924 
8925 static void
8926 advice_arg_check(VALUE advice)
8927 {
8928  if (!SYMBOL_P(advice))
8929  rb_raise(rb_eTypeError, "advice must be a Symbol");
8930 
8931  if (advice != sym_normal &&
8932  advice != sym_sequential &&
8933  advice != sym_random &&
8934  advice != sym_willneed &&
8935  advice != sym_dontneed &&
8936  advice != sym_noreuse) {
8937  rb_raise(rb_eNotImpError, "Unsupported advice: %+"PRIsVALUE, advice);
8938  }
8939 }
8940 
8941 /*
8942  * call-seq:
8943  * ios.advise(advice, offset=0, len=0) -> nil
8944  *
8945  * Announce an intention to access data from the current file in a
8946  * specific pattern. On platforms that do not support the
8947  * <em>posix_fadvise(2)</em> system call, this method is a no-op.
8948  *
8949  * _advice_ is one of the following symbols:
8950  *
8951  * :normal:: No advice to give; the default assumption for an open file.
8952  * :sequential:: The data will be accessed sequentially
8953  * with lower offsets read before higher ones.
8954  * :random:: The data will be accessed in random order.
8955  * :willneed:: The data will be accessed in the near future.
8956  * :dontneed:: The data will not be accessed in the near future.
8957  * :noreuse:: The data will only be accessed once.
8958  *
8959  * The semantics of a piece of advice are platform-dependent. See
8960  * <em>man 2 posix_fadvise</em> for details.
8961  *
8962  * "data" means the region of the current file that begins at
8963  * _offset_ and extends for _len_ bytes. If _len_ is 0, the region
8964  * ends at the last byte of the file. By default, both _offset_ and
8965  * _len_ are 0, meaning that the advice applies to the entire file.
8966  *
8967  * If an error occurs, one of the following exceptions will be raised:
8968  *
8969  * <code>IOError</code>:: The <code>IO</code> stream is closed.
8970  * <code>Errno::EBADF</code>::
8971  * The file descriptor of the current file is invalid.
8972  * <code>Errno::EINVAL</code>:: An invalid value for _advice_ was given.
8973  * <code>Errno::ESPIPE</code>::
8974  * The file descriptor of the current file refers to a FIFO or
8975  * pipe. (Linux raises <code>Errno::EINVAL</code> in this case).
8976  * <code>TypeError</code>::
8977  * Either _advice_ was not a Symbol, or one of the
8978  * other arguments was not an <code>Integer</code>.
8979  * <code>RangeError</code>:: One of the arguments given was too big/small.
8980  *
8981  * This list is not exhaustive; other Errno:: exceptions are also possible.
8982  */
8983 static VALUE
8984 rb_io_advise(int argc, VALUE *argv, VALUE io)
8985 {
8986  VALUE advice, offset, len;
8987  off_t off, l;
8988  rb_io_t *fptr;
8989 
8990  rb_scan_args(argc, argv, "12", &advice, &offset, &len);
8991  advice_arg_check(advice);
8992 
8993  io = GetWriteIO(io);
8994  GetOpenFile(io, fptr);
8995 
8996  off = NIL_P(offset) ? 0 : NUM2OFFT(offset);
8997  l = NIL_P(len) ? 0 : NUM2OFFT(len);
8998 
8999 #ifdef HAVE_POSIX_FADVISE
9000  return do_io_advise(fptr, advice, off, l);
9001 #else
9002  ((void)off, (void)l); /* Ignore all hint */
9003  return Qnil;
9004 #endif
9005 }
9006 
9007 /*
9008  * call-seq:
9009  * IO.select(read_array [, write_array [, error_array [, timeout]]]) -> array or nil
9010  *
9011  * Calls select(2) system call.
9012  * It monitors given arrays of <code>IO</code> objects, waits until one or more
9013  * of <code>IO</code> objects are ready for reading, are ready for writing,
9014  * and have pending exceptions respectively, and returns an array that
9015  * contains arrays of those IO objects. It will return +nil+
9016  * if optional <i>timeout</i> value is given and no <code>IO</code> object
9017  * is ready in <i>timeout</i> seconds.
9018  *
9019  * <code>IO.select</code> peeks the buffer of <code>IO</code> objects for testing readability.
9020  * If the <code>IO</code> buffer is not empty,
9021  * <code>IO.select</code> immediately notifies readability.
9022  * This "peek" only happens for <code>IO</code> objects.
9023  * It does not happen for IO-like objects such as OpenSSL::SSL::SSLSocket.
9024  *
9025  * The best way to use <code>IO.select</code> is invoking it
9026  * after nonblocking methods such as <code>read_nonblock</code>, <code>write_nonblock</code>, etc.
9027  * The methods raise an exception which is extended by
9028  * <code>IO::WaitReadable</code> or <code>IO::WaitWritable</code>.
9029  * The modules notify how the caller should wait with <code>IO.select</code>.
9030  * If <code>IO::WaitReadable</code> is raised, the caller should wait for reading.
9031  * If <code>IO::WaitWritable</code> is raised, the caller should wait for writing.
9032  *
9033  * So, blocking read (<code>readpartial</code>) can be emulated using
9034  * <code>read_nonblock</code> and <code>IO.select</code> as follows:
9035  *
9036  * begin
9037  * result = io_like.read_nonblock(maxlen)
9038  * rescue IO::WaitReadable
9039  * IO.select([io_like])
9040  * retry
9041  * rescue IO::WaitWritable
9042  * IO.select(nil, [io_like])
9043  * retry
9044  * end
9045  *
9046  * Especially, the combination of nonblocking methods and
9047  * <code>IO.select</code> is preferred for <code>IO</code> like
9048  * objects such as <code>OpenSSL::SSL::SSLSocket</code>.
9049  * It has <code>to_io</code> method to return underlying <code>IO</code> object.
9050  * <code>IO.select</code> calls <code>to_io</code> to obtain the file descriptor to wait.
9051  *
9052  * This means that readability notified by <code>IO.select</code> doesn't mean
9053  * readability from <code>OpenSSL::SSL::SSLSocket</code> object.
9054  *
9055  * The most likely situation is that <code>OpenSSL::SSL::SSLSocket</code> buffers some data.
9056  * <code>IO.select</code> doesn't see the buffer.
9057  * So <code>IO.select</code> can block when <code>OpenSSL::SSL::SSLSocket#readpartial</code> doesn't block.
9058  *
9059  * However, several more complicated situations exist.
9060  *
9061  * SSL is a protocol which is sequence of records.
9062  * The record consists of multiple bytes.
9063  * So, the remote side of SSL sends a partial record,
9064  * <code>IO.select</code> notifies readability but
9065  * <code>OpenSSL::SSL::SSLSocket</code> cannot decrypt a byte and
9066  * <code>OpenSSL::SSL::SSLSocket#readpartial</code> will blocks.
9067  *
9068  * Also, the remote side can request SSL renegotiation which forces
9069  * the local SSL engine to write some data.
9070  * This means <code>OpenSSL::SSL::SSLSocket#readpartial</code> may
9071  * invoke <code>write</code> system call and it can block.
9072  * In such a situation, <code>OpenSSL::SSL::SSLSocket#read_nonblock</code>
9073  * raises IO::WaitWritable instead of blocking.
9074  * So, the caller should wait for ready for writability as above example.
9075  *
9076  * The combination of nonblocking methods and <code>IO.select</code> is
9077  * also useful for streams such as tty, pipe socket socket when
9078  * multiple processes read from a stream.
9079  *
9080  * Finally, Linux kernel developers don't guarantee that
9081  * readability of select(2) means readability of following read(2) even
9082  * for a single process.
9083  * See select(2) manual on GNU/Linux system.
9084  *
9085  * Invoking <code>IO.select</code> before <code>IO#readpartial</code> works well as usual.
9086  * However it is not the best way to use <code>IO.select</code>.
9087  *
9088  * The writability notified by select(2) doesn't show
9089  * how many bytes writable.
9090  * <code>IO#write</code> method blocks until given whole string is written.
9091  * So, <code>IO#write(two or more bytes)</code> can block after writability is notified by <code>IO.select</code>.
9092  * <code>IO#write_nonblock</code> is required to avoid the blocking.
9093  *
9094  * Blocking write (<code>write</code>) can be emulated using
9095  * <code>write_nonblock</code> and <code>IO.select</code> as follows:
9096  * IO::WaitReadable should also be rescued for SSL renegotiation in <code>OpenSSL::SSL::SSLSocket</code>.
9097  *
9098  * while 0 < string.bytesize
9099  * begin
9100  * written = io_like.write_nonblock(string)
9101  * rescue IO::WaitReadable
9102  * IO.select([io_like])
9103  * retry
9104  * rescue IO::WaitWritable
9105  * IO.select(nil, [io_like])
9106  * retry
9107  * end
9108  * string = string.byteslice(written..-1)
9109  * end
9110  *
9111  * === Parameters
9112  * read_array:: an array of <code>IO</code> objects that wait until ready for read
9113  * write_array:: an array of <code>IO</code> objects that wait until ready for write
9114  * error_array:: an array of <code>IO</code> objects that wait for exceptions
9115  * timeout:: a numeric value in second
9116  *
9117  * === Example
9118  *
9119  * rp, wp = IO.pipe
9120  * mesg = "ping "
9121  * 100.times {
9122  * # IO.select follows IO#read. Not the best way to use IO.select.
9123  * rs, ws, = IO.select([rp], [wp])
9124  * if r = rs[0]
9125  * ret = r.read(5)
9126  * print ret
9127  * case ret
9128  * when /ping/
9129  * mesg = "pong\n"
9130  * when /pong/
9131  * mesg = "ping "
9132  * end
9133  * end
9134  * if w = ws[0]
9135  * w.write(mesg)
9136  * end
9137  * }
9138  *
9139  * <em>produces:</em>
9140  *
9141  * ping pong
9142  * ping pong
9143  * ping pong
9144  * (snipped)
9145  * ping
9146  */
9147 
9148 static VALUE
9149 rb_f_select(int argc, VALUE *argv, VALUE obj)
9150 {
9151  VALUE timeout;
9152  struct select_args args;
9153  struct timeval timerec;
9154  int i;
9155 
9156  rb_scan_args(argc, argv, "13", &args.read, &args.write, &args.except, &timeout);
9157  if (NIL_P(timeout)) {
9158  args.timeout = 0;
9159  }
9160  else {
9161  timerec = rb_time_interval(timeout);
9162  args.timeout = &timerec;
9163  }
9164 
9165  for (i = 0; i < numberof(args.fdsets); ++i)
9166  rb_fd_init(&args.fdsets[i]);
9167 
9168  return rb_ensure(select_call, (VALUE)&args, select_end, (VALUE)&args);
9169 }
9170 
9171 #if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
9172  typedef unsigned long ioctl_req_t;
9173 # define NUM2IOCTLREQ(num) NUM2ULONG(num)
9174 #else
9175  typedef int ioctl_req_t;
9176 # define NUM2IOCTLREQ(num) NUM2INT(num)
9177 #endif
9178 
9179 #ifdef HAVE_IOCTL
9180 struct ioctl_arg {
9181  int fd;
9182  ioctl_req_t cmd;
9183  long narg;
9184 };
9185 
9186 static VALUE
9187 nogvl_ioctl(void *ptr)
9188 {
9189  struct ioctl_arg *arg = ptr;
9190 
9191  return (VALUE)ioctl(arg->fd, arg->cmd, arg->narg);
9192 }
9193 
9194 static int
9195 do_ioctl(int fd, ioctl_req_t cmd, long narg)
9196 {
9197  int retval;
9198  struct ioctl_arg arg;
9199 
9200  arg.fd = fd;
9201  arg.cmd = cmd;
9202  arg.narg = narg;
9203 
9204  retval = (int)rb_thread_io_blocking_region(nogvl_ioctl, &arg, fd);
9205 
9206  return retval;
9207 }
9208 #endif
9209 
9210 #define DEFULT_IOCTL_NARG_LEN (256)
9211 
9212 #if defined(__linux__) && defined(_IOC_SIZE)
9213 static long
9214 linux_iocparm_len(ioctl_req_t cmd)
9215 {
9216  long len;
9217 
9218  if ((cmd & 0xFFFF0000) == 0) {
9219  /* legacy and unstructured ioctl number. */
9220  return DEFULT_IOCTL_NARG_LEN;
9221  }
9222 
9223  len = _IOC_SIZE(cmd);
9224 
9225  /* paranoia check for silly drivers which don't keep ioctl convention */
9226  if (len < DEFULT_IOCTL_NARG_LEN)
9227  len = DEFULT_IOCTL_NARG_LEN;
9228 
9229  return len;
9230 }
9231 #endif
9232 
9233 static long
9234 ioctl_narg_len(ioctl_req_t cmd)
9235 {
9236  long len;
9237 
9238 #ifdef IOCPARM_MASK
9239 #ifndef IOCPARM_LEN
9240 #define IOCPARM_LEN(x) (((x) >> 16) & IOCPARM_MASK)
9241 #endif
9242 #endif
9243 #ifdef IOCPARM_LEN
9244  len = IOCPARM_LEN(cmd); /* on BSDish systems we're safe */
9245 #elif defined(__linux__) && defined(_IOC_SIZE)
9246  len = linux_iocparm_len(cmd);
9247 #else
9248  /* otherwise guess at what's safe */
9249  len = DEFULT_IOCTL_NARG_LEN;
9250 #endif
9251 
9252  return len;
9253 }
9254 
9255 #ifdef HAVE_FCNTL
9256 #ifdef __linux__
9257 typedef long fcntl_arg_t;
9258 #else
9259 /* posix */
9260 typedef int fcntl_arg_t;
9261 #endif
9262 
9263 #if defined __native_client__ && !defined __GLIBC__
9264 // struct flock is currently missing the NaCl newlib headers
9265 // TODO(sbc): remove this once it gets added.
9266 #undef F_GETLK
9267 #undef F_SETLK
9268 #undef F_SETLKW
9269 #endif
9270 
9271 static long
9272 fcntl_narg_len(int cmd)
9273 {
9274  long len;
9275 
9276  switch (cmd) {
9277 #ifdef F_DUPFD
9278  case F_DUPFD:
9279  len = sizeof(fcntl_arg_t);
9280  break;
9281 #endif
9282 #ifdef F_DUP2FD /* bsd specific */
9283  case F_DUP2FD:
9284  len = sizeof(int);
9285  break;
9286 #endif
9287 #ifdef F_DUPFD_CLOEXEC /* linux specific */
9288  case F_DUPFD_CLOEXEC:
9289  len = sizeof(fcntl_arg_t);
9290  break;
9291 #endif
9292 #ifdef F_GETFD
9293  case F_GETFD:
9294  len = 1;
9295  break;
9296 #endif
9297 #ifdef F_SETFD
9298  case F_SETFD:
9299  len = sizeof(fcntl_arg_t);
9300  break;
9301 #endif
9302 #ifdef F_GETFL
9303  case F_GETFL:
9304  len = 1;
9305  break;
9306 #endif
9307 #ifdef F_SETFL
9308  case F_SETFL:
9309  len = sizeof(fcntl_arg_t);
9310  break;
9311 #endif
9312 #ifdef F_GETOWN
9313  case F_GETOWN:
9314  len = 1;
9315  break;
9316 #endif
9317 #ifdef F_SETOWN
9318  case F_SETOWN:
9319  len = sizeof(fcntl_arg_t);
9320  break;
9321 #endif
9322 #ifdef F_GETOWN_EX /* linux specific */
9323  case F_GETOWN_EX:
9324  len = sizeof(struct f_owner_ex);
9325  break;
9326 #endif
9327 #ifdef F_SETOWN_EX /* linux specific */
9328  case F_SETOWN_EX:
9329  len = sizeof(struct f_owner_ex);
9330  break;
9331 #endif
9332 #ifdef F_GETLK
9333  case F_GETLK:
9334  len = sizeof(struct flock);
9335  break;
9336 #endif
9337 #ifdef F_SETLK
9338  case F_SETLK:
9339  len = sizeof(struct flock);
9340  break;
9341 #endif
9342 #ifdef F_SETLKW
9343  case F_SETLKW:
9344  len = sizeof(struct flock);
9345  break;
9346 #endif
9347 #ifdef F_READAHEAD /* bsd specific */
9348  case F_READAHEAD:
9349  len = sizeof(int);
9350  break;
9351 #endif
9352 #ifdef F_RDAHEAD /* Darwin specific */
9353  case F_RDAHEAD:
9354  len = sizeof(int);
9355  break;
9356 #endif
9357 #ifdef F_GETSIG /* linux specific */
9358  case F_GETSIG:
9359  len = 1;
9360  break;
9361 #endif
9362 #ifdef F_SETSIG /* linux specific */
9363  case F_SETSIG:
9364  len = sizeof(fcntl_arg_t);
9365  break;
9366 #endif
9367 #ifdef F_GETLEASE /* linux specific */
9368  case F_GETLEASE:
9369  len = 1;
9370  break;
9371 #endif
9372 #ifdef F_SETLEASE /* linux specific */
9373  case F_SETLEASE:
9374  len = sizeof(fcntl_arg_t);
9375  break;
9376 #endif
9377 #ifdef F_NOTIFY /* linux specific */
9378  case F_NOTIFY:
9379  len = sizeof(fcntl_arg_t);
9380  break;
9381 #endif
9382 
9383  default:
9384  len = 256;
9385  break;
9386  }
9387 
9388  return len;
9389 }
9390 #else /* HAVE_FCNTL */
9391 static long
9392 fcntl_narg_len(int cmd)
9393 {
9394  return 0;
9395 }
9396 #endif /* HAVE_FCNTL */
9397 
9398 static long
9399 setup_narg(ioctl_req_t cmd, VALUE *argp, int io_p)
9400 {
9401  long narg = 0;
9402  VALUE arg = *argp;
9403 
9404  if (NIL_P(arg) || arg == Qfalse) {
9405  narg = 0;
9406  }
9407  else if (FIXNUM_P(arg)) {
9408  narg = FIX2LONG(arg);
9409  }
9410  else if (arg == Qtrue) {
9411  narg = 1;
9412  }
9413  else {
9414  VALUE tmp = rb_check_string_type(arg);
9415 
9416  if (NIL_P(tmp)) {
9417  narg = NUM2LONG(arg);
9418  }
9419  else {
9420  char *ptr;
9421  long len, slen;
9422 
9423  *argp = arg = tmp;
9424  if (io_p)
9425  len = ioctl_narg_len(cmd);
9426  else
9427  len = fcntl_narg_len((int)cmd);
9428  rb_str_modify(arg);
9429 
9430  slen = RSTRING_LEN(arg);
9431  /* expand for data + sentinel. */
9432  if (slen < len+1) {
9433  rb_str_resize(arg, len+1);
9434  MEMZERO(RSTRING_PTR(arg)+slen, char, len-slen);
9435  slen = len+1;
9436  }
9437  /* a little sanity check here */
9438  ptr = RSTRING_PTR(arg);
9439  ptr[slen - 1] = 17;
9440  narg = (long)(SIGNED_VALUE)ptr;
9441  }
9442  }
9443 
9444  return narg;
9445 }
9446 
9447 #ifdef HAVE_IOCTL
9448 static VALUE
9449 rb_ioctl(VALUE io, VALUE req, VALUE arg)
9450 {
9451  ioctl_req_t cmd = NUM2IOCTLREQ(req);
9452  rb_io_t *fptr;
9453  long narg;
9454  int retval;
9455 
9456  narg = setup_narg(cmd, &arg, 1);
9457  GetOpenFile(io, fptr);
9458  retval = do_ioctl(fptr->fd, cmd, narg);
9459  if (retval < 0) rb_sys_fail_path(fptr->pathv);
9460  if (RB_TYPE_P(arg, T_STRING)) {
9461  char *ptr;
9462  long slen;
9463  RSTRING_GETMEM(arg, ptr, slen);
9464  if (ptr[slen-1] != 17)
9465  rb_raise(rb_eArgError, "return value overflowed string");
9466  ptr[slen-1] = '\0';
9467  }
9468 
9469  return INT2NUM(retval);
9470 }
9471 
9472 /*
9473  * call-seq:
9474  * ios.ioctl(integer_cmd, arg) -> integer
9475  *
9476  * Provides a mechanism for issuing low-level commands to control or
9477  * query I/O devices. Arguments and results are platform dependent. If
9478  * <i>arg</i> is a number, its value is passed directly. If it is a
9479  * string, it is interpreted as a binary sequence of bytes. On Unix
9480  * platforms, see <code>ioctl(2)</code> for details. Not implemented on
9481  * all platforms.
9482  */
9483 
9484 static VALUE
9485 rb_io_ioctl(int argc, VALUE *argv, VALUE io)
9486 {
9487  VALUE req, arg;
9488 
9489  rb_scan_args(argc, argv, "11", &req, &arg);
9490  return rb_ioctl(io, req, arg);
9491 }
9492 #else
9493 #define rb_io_ioctl rb_f_notimplement
9494 #endif
9495 
9496 #ifdef HAVE_FCNTL
9497 struct fcntl_arg {
9498  int fd;
9499  int cmd;
9500  long narg;
9501 };
9502 
9503 static VALUE
9504 nogvl_fcntl(void *ptr)
9505 {
9506  struct fcntl_arg *arg = ptr;
9507 
9508 #if defined(F_DUPFD)
9509  if (arg->cmd == F_DUPFD)
9510  return (VALUE)rb_cloexec_fcntl_dupfd(arg->fd, (int)arg->narg);
9511 #endif
9512  return (VALUE)fcntl(arg->fd, arg->cmd, arg->narg);
9513 }
9514 
9515 static int
9516 do_fcntl(int fd, int cmd, long narg)
9517 {
9518  int retval;
9519  struct fcntl_arg arg;
9520 
9521  arg.fd = fd;
9522  arg.cmd = cmd;
9523  arg.narg = narg;
9524 
9525  retval = (int)rb_thread_io_blocking_region(nogvl_fcntl, &arg, fd);
9526  if (retval != -1) {
9527  switch (cmd) {
9528 #if defined(F_DUPFD)
9529  case F_DUPFD:
9530 #endif
9531 #if defined(F_DUPFD_CLOEXEC)
9532  case F_DUPFD_CLOEXEC:
9533 #endif
9534  rb_update_max_fd(retval);
9535  }
9536  }
9537 
9538  return retval;
9539 }
9540 
9541 static VALUE
9542 rb_fcntl(VALUE io, VALUE req, VALUE arg)
9543 {
9544  int cmd = NUM2INT(req);
9545  rb_io_t *fptr;
9546  long narg;
9547  int retval;
9548 
9549  narg = setup_narg(cmd, &arg, 0);
9550  GetOpenFile(io, fptr);
9551  retval = do_fcntl(fptr->fd, cmd, narg);
9552  if (retval < 0) rb_sys_fail_path(fptr->pathv);
9553  if (RB_TYPE_P(arg, T_STRING)) {
9554  char *ptr;
9555  long slen;
9556  RSTRING_GETMEM(arg, ptr, slen);
9557  if (ptr[slen-1] != 17)
9558  rb_raise(rb_eArgError, "return value overflowed string");
9559  ptr[slen-1] = '\0';
9560  }
9561 
9562  return INT2NUM(retval);
9563 }
9564 
9565 /*
9566  * call-seq:
9567  * ios.fcntl(integer_cmd, arg) -> integer
9568  *
9569  * Provides a mechanism for issuing low-level commands to control or
9570  * query file-oriented I/O streams. Arguments and results are platform
9571  * dependent. If <i>arg</i> is a number, its value is passed
9572  * directly. If it is a string, it is interpreted as a binary sequence
9573  * of bytes (<code>Array#pack</code> might be a useful way to build this
9574  * string). On Unix platforms, see <code>fcntl(2)</code> for details.
9575  * Not implemented on all platforms.
9576  */
9577 
9578 static VALUE
9579 rb_io_fcntl(int argc, VALUE *argv, VALUE io)
9580 {
9581  VALUE req, arg;
9582 
9583  rb_scan_args(argc, argv, "11", &req, &arg);
9584  return rb_fcntl(io, req, arg);
9585 }
9586 #else
9587 #define rb_io_fcntl rb_f_notimplement
9588 #endif
9589 
9590 #if defined(HAVE_SYSCALL) || defined(HAVE___SYSCALL)
9591 /*
9592  * call-seq:
9593  * syscall(num [, args...]) -> integer
9594  *
9595  * Calls the operating system function identified by _num_ and
9596  * returns the result of the function or raises SystemCallError if
9597  * it failed.
9598  *
9599  * Arguments for the function can follow _num_. They must be either
9600  * +String+ objects or +Integer+ objects. A +String+ object is passed
9601  * as a pointer to the byte sequence. An +Integer+ object is passed
9602  * as an integer whose bit size is same as a pointer.
9603  * Up to nine parameters may be passed.
9604  *
9605  * The function identified by _num_ is system
9606  * dependent. On some Unix systems, the numbers may be obtained from a
9607  * header file called <code>syscall.h</code>.
9608  *
9609  * syscall 4, 1, "hello\n", 6 # '4' is write(2) on our box
9610  *
9611  * <em>produces:</em>
9612  *
9613  * hello
9614  *
9615  * Calling +syscall+ on a platform which does not have any way to
9616  * an arbitrary system function just fails with NotImplementedError.
9617  *
9618  * *Note:*
9619  * +syscall+ is essentially unsafe and unportable.
9620  * Feel free to shoot your foot.
9621  * The DL (Fiddle) library is preferred for safer and a bit
9622  * more portable programming.
9623  */
9624 
9625 static VALUE
9626 rb_f_syscall(int argc, VALUE *argv)
9627 {
9628  VALUE arg[8];
9629 #if SIZEOF_VOIDP == 8 && defined(HAVE___SYSCALL) && SIZEOF_INT != 8 /* mainly *BSD */
9630 # define SYSCALL __syscall
9631 # define NUM2SYSCALLID(x) NUM2LONG(x)
9632 # define RETVAL2NUM(x) LONG2NUM(x)
9633 # if SIZEOF_LONG == 8
9634  long num, retval = -1;
9635 # elif SIZEOF_LONG_LONG == 8
9636  long long num, retval = -1;
9637 # else
9638 # error ---->> it is asserted that __syscall takes the first argument and returns retval in 64bit signed integer. <<----
9639 # endif
9640 #elif defined(__linux__)
9641 # define SYSCALL syscall
9642 # define NUM2SYSCALLID(x) NUM2LONG(x)
9643 # define RETVAL2NUM(x) LONG2NUM(x)
9644  /*
9645  * Linux man page says, syscall(2) function prototype is below.
9646  *
9647  * int syscall(int number, ...);
9648  *
9649  * But, it's incorrect. Actual one takes and returned long. (see unistd.h)
9650  */
9651  long num, retval = -1;
9652 #else
9653 # define SYSCALL syscall
9654 # define NUM2SYSCALLID(x) NUM2INT(x)
9655 # define RETVAL2NUM(x) INT2NUM(x)
9656  int num, retval = -1;
9657 #endif
9658  int i;
9659 
9660  if (RTEST(ruby_verbose)) {
9661  rb_warning("We plan to remove a syscall function at future release. DL(Fiddle) provides safer alternative.");
9662  }
9663 
9664  if (argc == 0)
9665  rb_raise(rb_eArgError, "too few arguments for syscall");
9666  if (argc > numberof(arg))
9667  rb_raise(rb_eArgError, "too many arguments for syscall");
9668  num = NUM2SYSCALLID(argv[0]); ++argv;
9669  for (i = argc - 1; i--; ) {
9670  VALUE v = rb_check_string_type(argv[i]);
9671 
9672  if (!NIL_P(v)) {
9673  SafeStringValue(v);
9674  rb_str_modify(v);
9675  arg[i] = (VALUE)StringValueCStr(v);
9676  }
9677  else {
9678  arg[i] = (VALUE)NUM2LONG(argv[i]);
9679  }
9680  }
9681 
9682  switch (argc) {
9683  case 1:
9684  retval = SYSCALL(num);
9685  break;
9686  case 2:
9687  retval = SYSCALL(num, arg[0]);
9688  break;
9689  case 3:
9690  retval = SYSCALL(num, arg[0],arg[1]);
9691  break;
9692  case 4:
9693  retval = SYSCALL(num, arg[0],arg[1],arg[2]);
9694  break;
9695  case 5:
9696  retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3]);
9697  break;
9698  case 6:
9699  retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4]);
9700  break;
9701  case 7:
9702  retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5]);
9703  break;
9704  case 8:
9705  retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6]);
9706  break;
9707  }
9708 
9709  if (retval == -1)
9710  rb_sys_fail(0);
9711  return RETVAL2NUM(retval);
9712 #undef SYSCALL
9713 #undef NUM2SYSCALLID
9714 #undef RETVAL2NUM
9715 }
9716 #else
9717 #define rb_f_syscall rb_f_notimplement
9718 #endif
9719 
9720 static VALUE
9721 io_new_instance(VALUE args)
9722 {
9723  return rb_class_new_instance(2, (VALUE*)args+1, *(VALUE*)args);
9724 }
9725 
9726 static rb_encoding *
9727 find_encoding(VALUE v)
9728 {
9729  rb_encoding *enc = rb_find_encoding(v);
9730  if (!enc) rb_warn("Unsupported encoding %"PRIsVALUE" ignored", v);
9731  return enc;
9732 }
9733 
9734 static void
9735 io_encoding_set(rb_io_t *fptr, VALUE v1, VALUE v2, VALUE opt)
9736 {
9737  rb_encoding *enc, *enc2;
9738  int ecflags = fptr->encs.ecflags;
9739  VALUE ecopts, tmp;
9740 
9741  if (!NIL_P(v2)) {
9742  enc2 = find_encoding(v1);
9743  tmp = rb_check_string_type(v2);
9744  if (!NIL_P(tmp)) {
9745  if (RSTRING_LEN(tmp) == 1 && RSTRING_PTR(tmp)[0] == '-') {
9746  /* Special case - "-" => no transcoding */
9747  enc = enc2;
9748  enc2 = NULL;
9749  }
9750  else
9751  enc = find_encoding(v2);
9752  if (enc == enc2) {
9753  /* Special case - "-" => no transcoding */
9754  enc2 = NULL;
9755  }
9756  }
9757  else {
9758  enc = find_encoding(v2);
9759  if (enc == enc2) {
9760  /* Special case - "-" => no transcoding */
9761  enc2 = NULL;
9762  }
9763  }
9765  ecflags = rb_econv_prepare_options(opt, &ecopts, ecflags);
9766  }
9767  else {
9768  if (NIL_P(v1)) {
9769  /* Set to default encodings */
9770  rb_io_ext_int_to_encs(NULL, NULL, &enc, &enc2, 0);
9772  ecopts = Qnil;
9773  }
9774  else {
9775  tmp = rb_check_string_type(v1);
9776  if (!NIL_P(tmp) && rb_enc_asciicompat(enc = rb_enc_get(tmp))) {
9777  parse_mode_enc(RSTRING_PTR(tmp), enc, &enc, &enc2, NULL);
9779  ecflags = rb_econv_prepare_options(opt, &ecopts, ecflags);
9780  }
9781  else {
9782  rb_io_ext_int_to_encs(find_encoding(v1), NULL, &enc, &enc2, 0);
9784  ecopts = Qnil;
9785  }
9786  }
9787  }
9788  validate_enc_binmode(&fptr->mode, ecflags, enc, enc2);
9789  fptr->encs.enc = enc;
9790  fptr->encs.enc2 = enc2;
9791  fptr->encs.ecflags = ecflags;
9792  fptr->encs.ecopts = ecopts;
9793  clear_codeconv(fptr);
9794 
9795 }
9796 
9802 };
9803 
9804 static VALUE
9805 io_encoding_set_v(VALUE v)
9806 {
9807  struct io_encoding_set_args *arg = (struct io_encoding_set_args *)v;
9808  io_encoding_set(arg->fptr, arg->v1, arg->v2, arg->opt);
9809  return Qnil;
9810 }
9811 
9812 static VALUE
9813 pipe_pair_close(VALUE rw)
9814 {
9815  VALUE *rwp = (VALUE *)rw;
9816  return rb_ensure(io_close, rwp[0], io_close, rwp[1]);
9817 }
9818 
9819 /*
9820  * call-seq:
9821  * IO.pipe -> [read_io, write_io]
9822  * IO.pipe(ext_enc) -> [read_io, write_io]
9823  * IO.pipe("ext_enc:int_enc" [, opt]) -> [read_io, write_io]
9824  * IO.pipe(ext_enc, int_enc [, opt]) -> [read_io, write_io]
9825  *
9826  * IO.pipe(...) {|read_io, write_io| ... }
9827  *
9828  * Creates a pair of pipe endpoints (connected to each other) and
9829  * returns them as a two-element array of <code>IO</code> objects:
9830  * <code>[</code> <i>read_io</i>, <i>write_io</i> <code>]</code>.
9831  *
9832  * If a block is given, the block is called and
9833  * returns the value of the block.
9834  * <i>read_io</i> and <i>write_io</i> are sent to the block as arguments.
9835  * If read_io and write_io are not closed when the block exits, they are closed.
9836  * i.e. closing read_io and/or write_io doesn't cause an error.
9837  *
9838  * Not available on all platforms.
9839  *
9840  * If an encoding (encoding name or encoding object) is specified as an optional argument,
9841  * read string from pipe is tagged with the encoding specified.
9842  * If the argument is a colon separated two encoding names "A:B",
9843  * the read string is converted from encoding A (external encoding)
9844  * to encoding B (internal encoding), then tagged with B.
9845  * If two optional arguments are specified, those must be
9846  * encoding objects or encoding names,
9847  * and the first one is the external encoding,
9848  * and the second one is the internal encoding.
9849  * If the external encoding and the internal encoding is specified,
9850  * optional hash argument specify the conversion option.
9851  *
9852  * In the example below, the two processes close the ends of the pipe
9853  * that they are not using. This is not just a cosmetic nicety. The
9854  * read end of a pipe will not generate an end of file condition if
9855  * there are any writers with the pipe still open. In the case of the
9856  * parent process, the <code>rd.read</code> will never return if it
9857  * does not first issue a <code>wr.close</code>.
9858  *
9859  * rd, wr = IO.pipe
9860  *
9861  * if fork
9862  * wr.close
9863  * puts "Parent got: <#{rd.read}>"
9864  * rd.close
9865  * Process.wait
9866  * else
9867  * rd.close
9868  * puts "Sending message to parent"
9869  * wr.write "Hi Dad"
9870  * wr.close
9871  * end
9872  *
9873  * <em>produces:</em>
9874  *
9875  * Sending message to parent
9876  * Parent got: <Hi Dad>
9877  */
9878 
9879 static VALUE
9880 rb_io_s_pipe(int argc, VALUE *argv, VALUE klass)
9881 {
9882  int pipes[2], state;
9883  VALUE r, w, args[3], v1, v2;
9884  VALUE opt;
9885  rb_io_t *fptr, *fptr2;
9886  struct io_encoding_set_args ies_args;
9887  int fmode = 0;
9888  VALUE ret;
9889 
9890  argc = rb_scan_args(argc, argv, "02:", &v1, &v2, &opt);
9891  if (rb_pipe(pipes) == -1)
9892  rb_sys_fail(0);
9893 
9894  args[0] = klass;
9895  args[1] = INT2NUM(pipes[0]);
9896  args[2] = INT2FIX(O_RDONLY);
9897  r = rb_protect(io_new_instance, (VALUE)args, &state);
9898  if (state) {
9899  close(pipes[0]);
9900  close(pipes[1]);
9901  rb_jump_tag(state);
9902  }
9903  GetOpenFile(r, fptr);
9904 
9905  ies_args.fptr = fptr;
9906  ies_args.v1 = v1;
9907  ies_args.v2 = v2;
9908  ies_args.opt = opt;
9909  rb_protect(io_encoding_set_v, (VALUE)&ies_args, &state);
9910  if (state) {
9911  close(pipes[1]);
9912  io_close(r);
9913  rb_jump_tag(state);
9914  }
9915 
9916  args[1] = INT2NUM(pipes[1]);
9917  args[2] = INT2FIX(O_WRONLY);
9918  w = rb_protect(io_new_instance, (VALUE)args, &state);
9919  if (state) {
9920  close(pipes[1]);
9921  if (!NIL_P(r)) rb_io_close(r);
9922  rb_jump_tag(state);
9923  }
9924  GetOpenFile(w, fptr2);
9925  rb_io_synchronized(fptr2);
9926 
9927  extract_binmode(opt, &fmode);
9928 #if DEFAULT_TEXTMODE
9929  if ((fptr->mode & FMODE_TEXTMODE) && (fmode & FMODE_BINMODE)) {
9930  fptr->mode &= ~FMODE_TEXTMODE;
9931  setmode(fptr->fd, O_BINARY);
9932  }
9933 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
9936  }
9937 #endif
9938 #endif
9939  fptr->mode |= fmode;
9940 #if DEFAULT_TEXTMODE
9941  if ((fptr2->mode & FMODE_TEXTMODE) && (fmode & FMODE_BINMODE)) {
9942  fptr2->mode &= ~FMODE_TEXTMODE;
9943  setmode(fptr2->fd, O_BINARY);
9944  }
9945 #endif
9946  fptr2->mode |= fmode;
9947 
9948  ret = rb_assoc_new(r, w);
9949  if (rb_block_given_p()) {
9950  VALUE rw[2];
9951  rw[0] = r;
9952  rw[1] = w;
9953  return rb_ensure(rb_yield, ret, pipe_pair_close, (VALUE)rw);
9954  }
9955  return ret;
9956 }
9957 
9958 struct foreach_arg {
9959  int argc;
9962 };
9963 
9964 static void
9965 open_key_args(int argc, VALUE *argv, VALUE opt, struct foreach_arg *arg)
9966 {
9967  VALUE path, v;
9968 
9969  path = *argv++;
9970  argc--;
9971  FilePathValue(path);
9972  arg->io = 0;
9973  arg->argc = argc;
9974  arg->argv = argv;
9975  if (NIL_P(opt)) {
9976  arg->io = rb_io_open(path, INT2NUM(O_RDONLY), INT2FIX(0666), Qnil);
9977  return;
9978  }
9979  v = rb_hash_aref(opt, sym_open_args);
9980  if (!NIL_P(v)) {
9981  VALUE args;
9982  long n;
9983 
9984  v = rb_convert_type_with_id(v, T_ARRAY, "Array", idTo_ary);
9985  n = RARRAY_LEN(v) + 1;
9986 #if SIZEOF_LONG > SIZEOF_INT
9987  if (n > INT_MAX) {
9988  rb_raise(rb_eArgError, "too many arguments");
9989  }
9990 #endif
9991  args = rb_ary_tmp_new(n);
9992  rb_ary_push(args, path);
9993  rb_ary_concat(args, v);
9994  arg->io = rb_io_open_with_args((int)n, RARRAY_CONST_PTR(args));
9995  rb_ary_clear(args); /* prevent from GC */
9996  return;
9997  }
9998  arg->io = rb_io_open(path, Qnil, Qnil, opt);
9999 }
10000 
10001 static VALUE
10002 io_s_foreach(struct getline_arg *arg)
10003 {
10004  VALUE str;
10005 
10006  while (!NIL_P(str = rb_io_getline_1(arg->rs, arg->limit, arg->chomp, arg->io))) {
10007  rb_lastline_set(str);
10008  rb_yield(str);
10009  }
10011  return Qnil;
10012 }
10013 
10014 /*
10015  * call-seq:
10016  * IO.foreach(name, sep=$/ [, getline_args, open_args]) {|line| block } -> nil
10017  * IO.foreach(name, limit [, getline_args, open_args]) {|line| block } -> nil
10018  * IO.foreach(name, sep, limit [, getline_args, open_args]) {|line| block } -> nil
10019  * IO.foreach(...) -> an_enumerator
10020  *
10021  * Executes the block for every line in the named I/O port, where lines
10022  * are separated by <em>sep</em>.
10023  *
10024  * If no block is given, an enumerator is returned instead.
10025  *
10026  * IO.foreach("testfile") {|x| print "GOT ", x }
10027  *
10028  * <em>produces:</em>
10029  *
10030  * GOT This is line one
10031  * GOT This is line two
10032  * GOT This is line three
10033  * GOT And so on...
10034  *
10035  * If the last argument is a hash, it's the keyword argument to open.
10036  * See <code>IO.readlines</code> for detail about getline_args.
10037  * And see also <code>IO.read</code> for detail about open_args.
10038  *
10039  */
10040 
10041 static VALUE
10042 rb_io_s_foreach(int argc, VALUE *argv, VALUE self)
10043 {
10044  VALUE opt;
10045  int orig_argc = argc;
10046  struct foreach_arg arg;
10047  struct getline_arg garg;
10048 
10049  argc = rb_scan_args(argc, argv, "13:", NULL, NULL, NULL, NULL, &opt);
10050  RETURN_ENUMERATOR(self, orig_argc, argv);
10051  extract_getline_args(argc-1, argv+1, &garg);
10052  open_key_args(argc, argv, opt, &arg);
10053  if (NIL_P(arg.io)) return Qnil;
10054  extract_getline_opts(opt, &garg);
10055  check_getline_args(&garg.rs, &garg.limit, garg.io = arg.io);
10056  return rb_ensure(io_s_foreach, (VALUE)&garg, rb_io_close, arg.io);
10057 }
10058 
10059 static VALUE
10060 io_s_readlines(struct getline_arg *arg)
10061 {
10062  return io_readlines(arg, arg->io);
10063 }
10064 
10065 /*
10066  * call-seq:
10067  * IO.readlines(name, sep=$/ [, getline_args, open_args]) -> array
10068  * IO.readlines(name, limit [, getline_args, open_args]) -> array
10069  * IO.readlines(name, sep, limit [, getline_args, open_args]) -> array
10070  *
10071  * Reads the entire file specified by <i>name</i> as individual
10072  * lines, and returns those lines in an array. Lines are separated by
10073  * <i>sep</i>.
10074  *
10075  * a = IO.readlines("testfile")
10076  * a[0] #=> "This is line one\n"
10077  *
10078  * If the last argument is a hash, it's the keyword argument to open.
10079  *
10080  * === Option for getline
10081  *
10082  * The options hash accepts the following keys:
10083  *
10084  * :chomp::
10085  * Specifies the boolean. It will remove \n, \r, and \r\n
10086  * from the end of each lines if it's true
10087  *
10088  * And see also <code>IO.read</code> for detail about open_args.
10089  *
10090  */
10091 
10092 static VALUE
10093 rb_io_s_readlines(int argc, VALUE *argv, VALUE io)
10094 {
10095  VALUE opt;
10096  struct foreach_arg arg;
10097  struct getline_arg garg;
10098 
10099  argc = rb_scan_args(argc, argv, "13:", NULL, NULL, NULL, NULL, &opt);
10100  extract_getline_args(argc-1, argv+1, &garg);
10101  open_key_args(argc, argv, opt, &arg);
10102  if (NIL_P(arg.io)) return Qnil;
10103  extract_getline_opts(opt, &garg);
10104  check_getline_args(&garg.rs, &garg.limit, garg.io = arg.io);
10105  return rb_ensure(io_s_readlines, (VALUE)&garg, rb_io_close, arg.io);
10106 }
10107 
10108 static VALUE
10109 io_s_read(struct foreach_arg *arg)
10110 {
10111  return io_read(arg->argc, arg->argv, arg->io);
10112 }
10113 
10114 struct seek_arg {
10117  int mode;
10118 };
10119 
10120 static VALUE
10121 seek_before_access(VALUE argp)
10122 {
10123  struct seek_arg *arg = (struct seek_arg *)argp;
10124  rb_io_binmode(arg->io);
10125  return rb_io_seek(arg->io, arg->offset, arg->mode);
10126 }
10127 
10128 /*
10129  * call-seq:
10130  * IO.read(name, [length [, offset]] [, opt] ) -> string
10131  *
10132  * Opens the file, optionally seeks to the given +offset+, then returns
10133  * +length+ bytes (defaulting to the rest of the file). <code>read</code>
10134  * ensures the file is closed before returning.
10135  *
10136  * If +name+ starts with a pipe character (<code>"|"</code>), a subprocess is
10137  * created in the same way as Kernel#open, and its output is returned.
10138  *
10139  * === Options
10140  *
10141  * The options hash accepts the following keys:
10142  *
10143  * :encoding::
10144  * string or encoding
10145  *
10146  * Specifies the encoding of the read string. +:encoding+ will be ignored
10147  * if +length+ is specified. See Encoding.aliases for possible encodings.
10148  *
10149  * :mode::
10150  * string or integer
10151  *
10152  * Specifies the <i>mode</i> argument for open(). It must start
10153  * with an "r", otherwise it will cause an error.
10154  * See IO.new for the list of possible modes.
10155  *
10156  * :open_args::
10157  * array
10158  *
10159  * Specifies arguments for open() as an array. This key can not be used
10160  * in combination with either +:encoding+ or +:mode+.
10161  *
10162  * Examples:
10163  *
10164  * IO.read("testfile") #=> "This is line one\nThis is line two\nThis is line three\nAnd so on...\n"
10165  * IO.read("testfile", 20) #=> "This is line one\nThi"
10166  * IO.read("testfile", 20, 10) #=> "ne one\nThis is line "
10167  * IO.read("binfile", mode: "rb") #=> "\xF7\x00\x00\x0E\x12"
10168  */
10169 
10170 static VALUE
10171 rb_io_s_read(int argc, VALUE *argv, VALUE io)
10172 {
10173  VALUE opt, offset;
10174  struct foreach_arg arg;
10175 
10176  argc = rb_scan_args(argc, argv, "13:", NULL, NULL, &offset, NULL, &opt);
10177  open_key_args(argc, argv, opt, &arg);
10178  if (NIL_P(arg.io)) return Qnil;
10179  if (!NIL_P(offset)) {
10180  struct seek_arg sarg;
10181  int state = 0;
10182  sarg.io = arg.io;
10183  sarg.offset = offset;
10184  sarg.mode = SEEK_SET;
10185  rb_protect(seek_before_access, (VALUE)&sarg, &state);
10186  if (state) {
10187  rb_io_close(arg.io);
10188  rb_jump_tag(state);
10189  }
10190  if (arg.argc == 2) arg.argc = 1;
10191  }
10192  return rb_ensure(io_s_read, (VALUE)&arg, rb_io_close, arg.io);
10193 }
10194 
10195 /*
10196  * call-seq:
10197  * IO.binread(name, [length [, offset]] ) -> string
10198  *
10199  * Opens the file, optionally seeks to the given <i>offset</i>, then returns
10200  * <i>length</i> bytes (defaulting to the rest of the file).
10201  * <code>binread</code> ensures the file is closed before returning.
10202  * The open mode would be "rb:ASCII-8BIT".
10203  *
10204  * IO.binread("testfile") #=> "This is line one\nThis is line two\nThis is line three\nAnd so on...\n"
10205  * IO.binread("testfile", 20) #=> "This is line one\nThi"
10206  * IO.binread("testfile", 20, 10) #=> "ne one\nThis is line "
10207  */
10208 
10209 static VALUE
10210 rb_io_s_binread(int argc, VALUE *argv, VALUE io)
10211 {
10212  VALUE offset;
10213  struct foreach_arg arg;
10214  enum {
10215  fmode = FMODE_READABLE|FMODE_BINMODE,
10216  oflags = O_RDONLY
10217 #ifdef O_BINARY
10218  |O_BINARY
10219 #endif
10220  };
10221  convconfig_t convconfig = {NULL, NULL, 0, Qnil};
10222 
10223  rb_scan_args(argc, argv, "12", NULL, NULL, &offset);
10224  FilePathValue(argv[0]);
10225  convconfig.enc = rb_ascii8bit_encoding();
10226  arg.io = rb_io_open_generic(argv[0], oflags, fmode, &convconfig, 0);
10227  if (NIL_P(arg.io)) return Qnil;
10228  arg.argv = argv+1;
10229  arg.argc = (argc > 1) ? 1 : 0;
10230  if (!NIL_P(offset)) {
10231  struct seek_arg sarg;
10232  int state = 0;
10233  sarg.io = arg.io;
10234  sarg.offset = offset;
10235  sarg.mode = SEEK_SET;
10236  rb_protect(seek_before_access, (VALUE)&sarg, &state);
10237  if (state) {
10238  rb_io_close(arg.io);
10239  rb_jump_tag(state);
10240  }
10241  }
10242  return rb_ensure(io_s_read, (VALUE)&arg, rb_io_close, arg.io);
10243 }
10244 
10245 static VALUE
10246 io_s_write0(struct write_arg *arg)
10247 {
10248  return io_write(arg->io,arg->str,arg->nosync);
10249 }
10250 
10251 static VALUE
10252 io_s_write(int argc, VALUE *argv, int binary)
10253 {
10254  VALUE string, offset, opt;
10255  struct foreach_arg arg;
10256  struct write_arg warg;
10257 
10258  rb_scan_args(argc, argv, "21:", NULL, &string, &offset, &opt);
10259 
10260  if (NIL_P(opt)) opt = rb_hash_new();
10261  else opt = rb_hash_dup(opt);
10262 
10263 
10264  if (NIL_P(rb_hash_aref(opt,sym_mode))) {
10265  int mode = O_WRONLY|O_CREAT;
10266 #ifdef O_BINARY
10267  if (binary) mode |= O_BINARY;
10268 #endif
10269  if (NIL_P(offset)) mode |= O_TRUNC;
10270  rb_hash_aset(opt,sym_mode,INT2NUM(mode));
10271  }
10272  open_key_args(argc,argv,opt,&arg);
10273 
10274 #ifndef O_BINARY
10275  if (binary) rb_io_binmode_m(arg.io);
10276 #endif
10277 
10278  if (NIL_P(arg.io)) return Qnil;
10279  if (!NIL_P(offset)) {
10280  struct seek_arg sarg;
10281  int state = 0;
10282  sarg.io = arg.io;
10283  sarg.offset = offset;
10284  sarg.mode = SEEK_SET;
10285  rb_protect(seek_before_access, (VALUE)&sarg, &state);
10286  if (state) {
10287  rb_io_close(arg.io);
10288  rb_jump_tag(state);
10289  }
10290  }
10291 
10292  warg.io = arg.io;
10293  warg.str = string;
10294  warg.nosync = 0;
10295 
10296  return rb_ensure(io_s_write0, (VALUE)&warg, rb_io_close, arg.io);
10297 }
10298 
10299 /*
10300  * call-seq:
10301  * IO.write(name, string [, offset]) -> integer
10302  * IO.write(name, string [, offset] [, opt]) -> integer
10303  *
10304  * Opens the file, optionally seeks to the given <i>offset</i>, writes
10305  * <i>string</i>, then returns the length written.
10306  * <code>write</code> ensures the file is closed before returning.
10307  * If <i>offset</i> is not given in write mode, the file is truncated.
10308  * Otherwise, it is not truncated.
10309  *
10310  * IO.write("testfile", "0123456789", 20) #=> 10
10311  * # File could contain: "This is line one\nThi0123456789two\nThis is line three\nAnd so on...\n"
10312  * IO.write("testfile", "0123456789") #=> 10
10313  * # File would now read: "0123456789"
10314  *
10315  * If the last argument is a hash, it specifies options for the internal
10316  * open(). It accepts the following keys:
10317  *
10318  * :encoding::
10319  * string or encoding
10320  *
10321  * Specifies the encoding of the read string.
10322  * See Encoding.aliases for possible encodings.
10323  *
10324  * :mode::
10325  * string or integer
10326  *
10327  * Specifies the <i>mode</i> argument for open(). It must start
10328  * with "w", "a", or "r+", otherwise it will cause an error.
10329  * See IO.new for the list of possible modes.
10330  *
10331  * :perm::
10332  * integer
10333  *
10334  * Specifies the <i>perm</i> argument for open().
10335  *
10336  * :open_args::
10337  * array
10338  *
10339  * Specifies arguments for open() as an array.
10340  * This key can not be used in combination with other keys.
10341  */
10342 
10343 static VALUE
10344 rb_io_s_write(int argc, VALUE *argv, VALUE io)
10345 {
10346  return io_s_write(argc, argv, 0);
10347 }
10348 
10349 /*
10350  * call-seq:
10351  * IO.binwrite(name, string, [offset] ) -> integer
10352  * IO.binwrite(name, string, [offset], open_args ) -> integer
10353  *
10354  * Same as <code>IO.write</code> except opening the file in binary mode
10355  * and ASCII-8BIT encoding ("wb:ASCII-8BIT").
10356  */
10357 
10358 static VALUE
10359 rb_io_s_binwrite(int argc, VALUE *argv, VALUE io)
10360 {
10361  return io_s_write(argc, argv, 1);
10362 }
10363 
10367  off_t copy_length; /* (off_t)-1 if not specified */
10368  off_t src_offset; /* (off_t)-1 if not specified */
10369 
10370  int src_fd;
10371  int dst_fd;
10375  const char *syserr;
10377  const char *notimp;
10380 };
10381 
10382 static void *
10383 exec_interrupts(void *arg)
10384 {
10385  VALUE th = (VALUE)arg;
10387  return NULL;
10388 }
10389 
10390 /*
10391  * returns TRUE if the preceding system call was interrupted
10392  * so we can continue. If the thread was interrupted, we
10393  * reacquire the GVL to execute interrupts before continuing.
10394  */
10395 static int
10396 maygvl_copy_stream_continue_p(int has_gvl, struct copy_stream_struct *stp)
10397 {
10398  switch (errno) {
10399  case EINTR:
10400 #if defined(ERESTART)
10401  case ERESTART:
10402 #endif
10403  if (rb_thread_interrupted(stp->th)) {
10404  if (has_gvl)
10406  else
10407  rb_thread_call_with_gvl(exec_interrupts, (void *)stp->th);
10408  }
10409  return TRUE;
10410  }
10411  return FALSE;
10412 }
10413 
10414 /* non-Linux poll may not work on all FDs */
10415 #if defined(HAVE_POLL) && defined(__linux__)
10416 # define USE_POLL 1
10417 # define IOWAIT_SYSCALL "poll"
10418 #else
10419 # define IOWAIT_SYSCALL "select"
10420 # define USE_POLL 0
10421 #endif
10422 
10423 #if USE_POLL
10424 static int
10425 nogvl_wait_for_single_fd(int fd, short events)
10426 {
10427  struct pollfd fds;
10428 
10429  fds.fd = fd;
10430  fds.events = events;
10431 
10432  return poll(&fds, 1, -1);
10433 }
10434 
10435 static int
10436 maygvl_copy_stream_wait_read(int has_gvl, struct copy_stream_struct *stp)
10437 {
10438  int ret;
10439 
10440  do {
10441  if (has_gvl) {
10443  }
10444  else {
10445  ret = nogvl_wait_for_single_fd(stp->src_fd, POLLIN);
10446  }
10447  } while (ret == -1 && maygvl_copy_stream_continue_p(has_gvl, stp));
10448 
10449  if (ret == -1) {
10450  stp->syserr = "poll";
10451  stp->error_no = errno;
10452  return -1;
10453  }
10454  return 0;
10455 }
10456 #else /* !USE_POLL */
10457 static int
10458 maygvl_select(int has_gvl, int n, rb_fdset_t *rfds, rb_fdset_t *wfds, rb_fdset_t *efds, struct timeval *timeout)
10459 {
10460  if (has_gvl)
10461  return rb_thread_fd_select(n, rfds, wfds, efds, timeout);
10462  else
10463  return rb_fd_select(n, rfds, wfds, efds, timeout);
10464 }
10465 
10466 static int
10467 maygvl_copy_stream_wait_read(int has_gvl, struct copy_stream_struct *stp)
10468 {
10469  int ret;
10470 
10471  do {
10472  rb_fd_zero(&stp->fds);
10473  rb_fd_set(stp->src_fd, &stp->fds);
10474  ret = maygvl_select(has_gvl, rb_fd_max(&stp->fds), &stp->fds, NULL, NULL, NULL);
10475  } while (ret == -1 && maygvl_copy_stream_continue_p(has_gvl, stp));
10476 
10477  if (ret == -1) {
10478  stp->syserr = "select";
10479  stp->error_no = errno;
10480  return -1;
10481  }
10482  return 0;
10483 }
10484 #endif /* !USE_POLL */
10485 
10486 static int
10487 nogvl_copy_stream_wait_write(struct copy_stream_struct *stp)
10488 {
10489  int ret;
10490 
10491  do {
10492 #if USE_POLL
10493  ret = nogvl_wait_for_single_fd(stp->dst_fd, POLLOUT);
10494 #else
10495  rb_fd_zero(&stp->fds);
10496  rb_fd_set(stp->dst_fd, &stp->fds);
10497  ret = rb_fd_select(rb_fd_max(&stp->fds), NULL, &stp->fds, NULL, NULL);
10498 #endif
10499  } while (ret == -1 && maygvl_copy_stream_continue_p(0, stp));
10500 
10501  if (ret == -1) {
10502  stp->syserr = IOWAIT_SYSCALL;
10503  stp->error_no = errno;
10504  return -1;
10505  }
10506  return 0;
10507 }
10508 
10509 #if defined __linux__ && defined __NR_copy_file_range
10510 # define USE_COPY_FILE_RANGE
10511 #endif
10512 
10513 #ifdef USE_COPY_FILE_RANGE
10514 
10515 static ssize_t
10516 simple_copy_file_range(int in_fd, off_t *in_offset, int out_fd, off_t *out_offset, size_t count, unsigned int flags)
10517 {
10518  return syscall(__NR_copy_file_range, in_fd, in_offset, out_fd, out_offset, count, flags);
10519 }
10520 
10521 static int
10522 nogvl_copy_file_range(struct copy_stream_struct *stp)
10523 {
10524  struct stat src_stat, dst_stat;
10525  ssize_t ss;
10526  int ret;
10527 
10528  off_t copy_length, src_offset, *src_offset_ptr;
10529 
10530  ret = fstat(stp->src_fd, &src_stat);
10531  if (ret == -1) {
10532  stp->syserr = "fstat";
10533  stp->error_no = errno;
10534  return -1;
10535  }
10536  if (!S_ISREG(src_stat.st_mode))
10537  return 0;
10538 
10539  ret = fstat(stp->dst_fd, &dst_stat);
10540  if (ret == -1) {
10541  stp->syserr = "fstat";
10542  stp->error_no = errno;
10543  return -1;
10544  }
10545 
10546  src_offset = stp->src_offset;
10547  if (src_offset != (off_t)-1) {
10548  src_offset_ptr = &src_offset;
10549  }
10550  else {
10551  src_offset_ptr = NULL; /* if src_offset_ptr is NULL, then bytes are read from in_fd starting from the file offset */
10552  }
10553 
10554  copy_length = stp->copy_length;
10555  if (copy_length == (off_t)-1) {
10556  if (src_offset == (off_t)-1) {
10557  off_t current_offset;
10558  errno = 0;
10559  current_offset = lseek(stp->src_fd, 0, SEEK_CUR);
10560  if (current_offset == (off_t)-1 && errno) {
10561  stp->syserr = "lseek";
10562  stp->error_no = errno;
10563  return -1;
10564  }
10565  copy_length = src_stat.st_size - current_offset;
10566  }
10567  else {
10568  copy_length = src_stat.st_size - src_offset;
10569  }
10570  }
10571 
10572  retry_copy_file_range:
10573 # if SIZEOF_OFF_T > SIZEOF_SIZE_T
10574  /* we are limited by the 32-bit ssize_t return value on 32-bit */
10575  ss = (copy_length > (off_t)SSIZE_MAX) ? SSIZE_MAX : (ssize_t)copy_length;
10576 # else
10577  ss = (ssize_t)copy_length;
10578 # endif
10579  ss = simple_copy_file_range(stp->src_fd, src_offset_ptr, stp->dst_fd, NULL, ss, 0);
10580  if (0 < ss) {
10581  stp->total += ss;
10582  copy_length -= ss;
10583  if (0 < copy_length) {
10584  goto retry_copy_file_range;
10585  }
10586  }
10587  if (ss == -1) {
10588  if (maygvl_copy_stream_continue_p(0, stp)) {
10589  goto retry_copy_file_range;
10590  }
10591  switch (errno) {
10592  case EINVAL:
10593 #ifdef ENOSYS
10594  case ENOSYS:
10595 #endif
10596 #ifdef EXDEV
10597  case EXDEV: /* in_fd and out_fd are not on the same filesystem */
10598 #endif
10599  return 0;
10600  case EAGAIN:
10601 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
10602  case EWOULDBLOCK:
10603 #endif
10604  if (nogvl_copy_stream_wait_write(stp) == -1)
10605  return -1;
10606  goto retry_copy_file_range;
10607  }
10608  stp->syserr = "copy_file_range";
10609  stp->error_no = errno;
10610  return -1;
10611  }
10612  return 1;
10613 }
10614 #endif
10615 
10616 #ifdef HAVE_SENDFILE
10617 
10618 # ifdef __linux__
10619 # define USE_SENDFILE
10620 
10621 # ifdef HAVE_SYS_SENDFILE_H
10622 # include <sys/sendfile.h>
10623 # endif
10624 
10625 static ssize_t
10626 simple_sendfile(int out_fd, int in_fd, off_t *offset, off_t count)
10627 {
10628  return sendfile(out_fd, in_fd, offset, (size_t)count);
10629 }
10630 
10631 # elif 0 /* defined(__FreeBSD__) || defined(__DragonFly__) */ || defined(__APPLE__)
10632 /* This runs on FreeBSD8.1 r30210, but sendfiles blocks its execution
10633  * without cpuset -l 0.
10634  */
10635 # define USE_SENDFILE
10636 
10637 static ssize_t
10638 simple_sendfile(int out_fd, int in_fd, off_t *offset, off_t count)
10639 {
10640  int r;
10641  off_t pos = offset ? *offset : lseek(in_fd, 0, SEEK_CUR);
10642  off_t sbytes;
10643 # ifdef __APPLE__
10644  r = sendfile(in_fd, out_fd, pos, &count, NULL, 0);
10645  sbytes = count;
10646 # else
10647  r = sendfile(in_fd, out_fd, pos, (size_t)count, NULL, &sbytes, 0);
10648 # endif
10649  if (r != 0 && sbytes == 0) return -1;
10650  if (offset) {
10651  *offset += sbytes;
10652  }
10653  else {
10654  lseek(in_fd, sbytes, SEEK_CUR);
10655  }
10656  return (ssize_t)sbytes;
10657 }
10658 
10659 # endif
10660 
10661 #endif
10662 
10663 #ifdef USE_SENDFILE
10664 static int
10665 nogvl_copy_stream_sendfile(struct copy_stream_struct *stp)
10666 {
10667  struct stat src_stat, dst_stat;
10668  ssize_t ss;
10669  int ret;
10670 
10671  off_t copy_length;
10672  off_t src_offset;
10673  int use_pread;
10674 
10675  ret = fstat(stp->src_fd, &src_stat);
10676  if (ret == -1) {
10677  stp->syserr = "fstat";
10678  stp->error_no = errno;
10679  return -1;
10680  }
10681  if (!S_ISREG(src_stat.st_mode))
10682  return 0;
10683 
10684  ret = fstat(stp->dst_fd, &dst_stat);
10685  if (ret == -1) {
10686  stp->syserr = "fstat";
10687  stp->error_no = errno;
10688  return -1;
10689  }
10690 #ifndef __linux__
10691  if ((dst_stat.st_mode & S_IFMT) != S_IFSOCK)
10692  return 0;
10693 #endif
10694 
10695  src_offset = stp->src_offset;
10696  use_pread = src_offset != (off_t)-1;
10697 
10698  copy_length = stp->copy_length;
10699  if (copy_length == (off_t)-1) {
10700  if (use_pread)
10701  copy_length = src_stat.st_size - src_offset;
10702  else {
10703  off_t cur;
10704  errno = 0;
10705  cur = lseek(stp->src_fd, 0, SEEK_CUR);
10706  if (cur == (off_t)-1 && errno) {
10707  stp->syserr = "lseek";
10708  stp->error_no = errno;
10709  return -1;
10710  }
10711  copy_length = src_stat.st_size - cur;
10712  }
10713  }
10714 
10715  retry_sendfile:
10716 # if SIZEOF_OFF_T > SIZEOF_SIZE_T
10717  /* we are limited by the 32-bit ssize_t return value on 32-bit */
10718  ss = (copy_length > (off_t)SSIZE_MAX) ? SSIZE_MAX : (ssize_t)copy_length;
10719 # else
10720  ss = (ssize_t)copy_length;
10721 # endif
10722  if (use_pread) {
10723  ss = simple_sendfile(stp->dst_fd, stp->src_fd, &src_offset, ss);
10724  }
10725  else {
10726  ss = simple_sendfile(stp->dst_fd, stp->src_fd, NULL, ss);
10727  }
10728  if (0 < ss) {
10729  stp->total += ss;
10730  copy_length -= ss;
10731  if (0 < copy_length) {
10732  goto retry_sendfile;
10733  }
10734  }
10735  if (ss == -1) {
10736  if (maygvl_copy_stream_continue_p(0, stp))
10737  goto retry_sendfile;
10738  switch (errno) {
10739  case EINVAL:
10740 #ifdef ENOSYS
10741  case ENOSYS:
10742 #endif
10743  return 0;
10744  case EAGAIN:
10745 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
10746  case EWOULDBLOCK:
10747 #endif
10748 #ifndef __linux__
10749  /*
10750  * Linux requires stp->src_fd to be a mmap-able (regular) file,
10751  * select() reports regular files to always be "ready", so
10752  * there is no need to select() on it.
10753  * Other OSes may have the same limitation for sendfile() which
10754  * allow us to bypass maygvl_copy_stream_wait_read()...
10755  */
10756  if (maygvl_copy_stream_wait_read(0, stp) == -1)
10757  return -1;
10758 #endif
10759  if (nogvl_copy_stream_wait_write(stp) == -1)
10760  return -1;
10761  goto retry_sendfile;
10762  }
10763  stp->syserr = "sendfile";
10764  stp->error_no = errno;
10765  return -1;
10766  }
10767  return 1;
10768 }
10769 #endif
10770 
10771 static ssize_t
10772 maygvl_read(int has_gvl, int fd, void *buf, size_t count)
10773 {
10774  if (has_gvl)
10775  return rb_read_internal(fd, buf, count);
10776  else
10777  return read(fd, buf, count);
10778 }
10779 
10780 static ssize_t
10781 maygvl_copy_stream_read(int has_gvl, struct copy_stream_struct *stp, char *buf, size_t len, off_t offset)
10782 {
10783  ssize_t ss;
10784  retry_read:
10785  if (offset == (off_t)-1) {
10786  ss = maygvl_read(has_gvl, stp->src_fd, buf, len);
10787  }
10788  else {
10789 #ifdef HAVE_PREAD
10790  ss = pread(stp->src_fd, buf, len, offset);
10791 #else
10792  stp->notimp = "pread";
10793  return -1;
10794 #endif
10795  }
10796  if (ss == 0) {
10797  return 0;
10798  }
10799  if (ss == -1) {
10800  if (maygvl_copy_stream_continue_p(has_gvl, stp))
10801  goto retry_read;
10802  switch (errno) {
10803  case EAGAIN:
10804 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
10805  case EWOULDBLOCK:
10806 #endif
10807  if (maygvl_copy_stream_wait_read(has_gvl, stp) == -1)
10808  return -1;
10809  goto retry_read;
10810 #ifdef ENOSYS
10811  case ENOSYS:
10812  stp->notimp = "pread";
10813  return -1;
10814 #endif
10815  }
10816  stp->syserr = offset == (off_t)-1 ? "read" : "pread";
10817  stp->error_no = errno;
10818  return -1;
10819  }
10820  return ss;
10821 }
10822 
10823 static int
10824 nogvl_copy_stream_write(struct copy_stream_struct *stp, char *buf, size_t len)
10825 {
10826  ssize_t ss;
10827  int off = 0;
10828  while (len) {
10829  ss = write(stp->dst_fd, buf+off, len);
10830  if (ss == -1) {
10831  if (maygvl_copy_stream_continue_p(0, stp))
10832  continue;
10833  if (errno == EAGAIN || errno == EWOULDBLOCK) {
10834  if (nogvl_copy_stream_wait_write(stp) == -1)
10835  return -1;
10836  continue;
10837  }
10838  stp->syserr = "write";
10839  stp->error_no = errno;
10840  return -1;
10841  }
10842  off += (int)ss;
10843  len -= (int)ss;
10844  stp->total += ss;
10845  }
10846  return 0;
10847 }
10848 
10849 static void
10850 nogvl_copy_stream_read_write(struct copy_stream_struct *stp)
10851 {
10852  char buf[1024*16];
10853  size_t len;
10854  ssize_t ss;
10855  int ret;
10856  off_t copy_length;
10857  int use_eof;
10858  off_t src_offset;
10859  int use_pread;
10860 
10861  copy_length = stp->copy_length;
10862  use_eof = copy_length == (off_t)-1;
10863  src_offset = stp->src_offset;
10864  use_pread = src_offset != (off_t)-1;
10865 
10866  if (use_pread && stp->close_src) {
10867  off_t r;
10868  errno = 0;
10869  r = lseek(stp->src_fd, src_offset, SEEK_SET);
10870  if (r == (off_t)-1 && errno) {
10871  stp->syserr = "lseek";
10872  stp->error_no = errno;
10873  return;
10874  }
10875  src_offset = (off_t)-1;
10876  use_pread = 0;
10877  }
10878 
10879  while (use_eof || 0 < copy_length) {
10880  if (!use_eof && copy_length < (off_t)sizeof(buf)) {
10881  len = (size_t)copy_length;
10882  }
10883  else {
10884  len = sizeof(buf);
10885  }
10886  if (use_pread) {
10887  ss = maygvl_copy_stream_read(0, stp, buf, len, src_offset);
10888  if (0 < ss)
10889  src_offset += ss;
10890  }
10891  else {
10892  ss = maygvl_copy_stream_read(0, stp, buf, len, (off_t)-1);
10893  }
10894  if (ss <= 0) /* EOF or error */
10895  return;
10896 
10897  ret = nogvl_copy_stream_write(stp, buf, ss);
10898  if (ret < 0)
10899  return;
10900 
10901  if (!use_eof)
10902  copy_length -= ss;
10903  }
10904 }
10905 
10906 static void *
10907 nogvl_copy_stream_func(void *arg)
10908 {
10909  struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
10910 #ifdef USE_SENDFILE
10911  int ret;
10912 #endif
10913 
10914 #ifdef USE_COPY_FILE_RANGE
10915  ret = nogvl_copy_file_range(stp);
10916  if (ret != 0)
10917  goto finish; /* error or success */
10918 #endif
10919 
10920 #ifdef USE_SENDFILE
10921  ret = nogvl_copy_stream_sendfile(stp);
10922  if (ret != 0)
10923  goto finish; /* error or success */
10924 #endif
10925 
10926  nogvl_copy_stream_read_write(stp);
10927 
10928 #ifdef USE_SENDFILE
10929  finish:
10930 #endif
10931  return 0;
10932 }
10933 
10934 static VALUE
10935 copy_stream_fallback_body(VALUE arg)
10936 {
10937  struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
10938  const int buflen = 16*1024;
10939  VALUE n;
10940  VALUE buf = rb_str_buf_new(buflen);
10941  off_t rest = stp->copy_length;
10942  off_t off = stp->src_offset;
10943  ID read_method = id_readpartial;
10944 
10945  if (stp->src_fd == -1) {
10946  if (!rb_respond_to(stp->src, read_method)) {
10947  read_method = id_read;
10948  }
10949  }
10950 
10951  while (1) {
10952  long numwrote;
10953  long l;
10954  if (stp->copy_length == (off_t)-1) {
10955  l = buflen;
10956  }
10957  else {
10958  if (rest == 0)
10959  break;
10960  l = buflen < rest ? buflen : (long)rest;
10961  }
10962  if (stp->src_fd == -1) {
10963  VALUE rc = rb_funcall(stp->src, read_method, 2, INT2FIX(l), buf);
10964 
10965  if (read_method == id_read && NIL_P(rc))
10966  break;
10967  }
10968  else {
10969  ssize_t ss;
10970  rb_str_resize(buf, buflen);
10971  ss = maygvl_copy_stream_read(1, stp, RSTRING_PTR(buf), l, off);
10972  rb_str_resize(buf, ss > 0 ? ss : 0);
10973  if (ss == -1)
10974  return Qnil;
10975  if (ss == 0)
10976  rb_eof_error();
10977  if (off != (off_t)-1)
10978  off += ss;
10979  }
10980  n = rb_io_write(stp->dst, buf);
10981  numwrote = NUM2LONG(n);
10982  stp->total += numwrote;
10983  rest -= numwrote;
10984  if (read_method == id_read && RSTRING_LEN(buf) == 0) {
10985  break;
10986  }
10987  }
10988 
10989  return Qnil;
10990 }
10991 
10992 static VALUE
10993 copy_stream_fallback(struct copy_stream_struct *stp)
10994 {
10995  if (stp->src_fd == -1 && stp->src_offset != (off_t)-1) {
10996  rb_raise(rb_eArgError, "cannot specify src_offset for non-IO");
10997  }
10998  rb_rescue2(copy_stream_fallback_body, (VALUE)stp,
10999  (VALUE (*) (ANYARGS))0, (VALUE)0,
11000  rb_eEOFError, (VALUE)0);
11001  return Qnil;
11002 }
11003 
11004 static VALUE
11005 copy_stream_body(VALUE arg)
11006 {
11007  struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
11008  VALUE src_io = stp->src, dst_io = stp->dst;
11009  rb_io_t *src_fptr = 0, *dst_fptr = 0;
11010  int src_fd, dst_fd;
11011  const int common_oflags = 0
11012 #ifdef O_NOCTTY
11013  | O_NOCTTY
11014 #endif
11015  ;
11016 
11017  stp->th = rb_thread_current();
11018 
11019  stp->total = 0;
11020 
11021  if (src_io == argf ||
11022  !(RB_TYPE_P(src_io, T_FILE) ||
11023  RB_TYPE_P(src_io, T_STRING) ||
11024  rb_respond_to(src_io, rb_intern("to_path")))) {
11025  src_fd = -1;
11026  }
11027  else {
11028  VALUE tmp_io = rb_io_check_io(src_io);
11029  if (!NIL_P(tmp_io)) {
11030  src_io = tmp_io;
11031  }
11032  else if (!RB_TYPE_P(src_io, T_FILE)) {
11033  VALUE args[2];
11034  FilePathValue(src_io);
11035  args[0] = src_io;
11036  args[1] = INT2NUM(O_RDONLY|common_oflags);
11037  src_io = rb_class_new_instance(2, args, rb_cFile);
11038  stp->src = src_io;
11039  stp->close_src = 1;
11040  }
11041  GetOpenFile(src_io, src_fptr);
11042  rb_io_check_byte_readable(src_fptr);
11043  src_fd = src_fptr->fd;
11044  }
11045  stp->src_fd = src_fd;
11046 
11047  if (dst_io == argf ||
11048  !(RB_TYPE_P(dst_io, T_FILE) ||
11049  RB_TYPE_P(dst_io, T_STRING) ||
11050  rb_respond_to(dst_io, rb_intern("to_path")))) {
11051  dst_fd = -1;
11052  }
11053  else {
11054  VALUE tmp_io = rb_io_check_io(dst_io);
11055  if (!NIL_P(tmp_io)) {
11056  dst_io = GetWriteIO(tmp_io);
11057  }
11058  else if (!RB_TYPE_P(dst_io, T_FILE)) {
11059  VALUE args[3];
11060  FilePathValue(dst_io);
11061  args[0] = dst_io;
11062  args[1] = INT2NUM(O_WRONLY|O_CREAT|O_TRUNC|common_oflags);
11063  args[2] = INT2FIX(0666);
11064  dst_io = rb_class_new_instance(3, args, rb_cFile);
11065  stp->dst = dst_io;
11066  stp->close_dst = 1;
11067  }
11068  else {
11069  dst_io = GetWriteIO(dst_io);
11070  stp->dst = dst_io;
11071  }
11072  GetOpenFile(dst_io, dst_fptr);
11073  rb_io_check_writable(dst_fptr);
11074  dst_fd = dst_fptr->fd;
11075  }
11076  stp->dst_fd = dst_fd;
11077 
11078 #ifdef O_BINARY
11079  if (src_fptr)
11081 #endif
11082  if (dst_fptr)
11083  io_ascii8bit_binmode(dst_fptr);
11084 
11085  if (stp->src_offset == (off_t)-1 && src_fptr && src_fptr->rbuf.len) {
11086  size_t len = src_fptr->rbuf.len;
11087  VALUE str;
11088  if (stp->copy_length != (off_t)-1 && stp->copy_length < (off_t)len) {
11089  len = (size_t)stp->copy_length;
11090  }
11091  str = rb_str_buf_new(len);
11092  rb_str_resize(str,len);
11093  read_buffered_data(RSTRING_PTR(str), len, src_fptr);
11094  if (dst_fptr) { /* IO or filename */
11095  if (io_binwrite(str, RSTRING_PTR(str), RSTRING_LEN(str), dst_fptr, 0) < 0)
11096  rb_sys_fail(0);
11097  }
11098  else /* others such as StringIO */
11099  rb_io_write(dst_io, str);
11100  stp->total += len;
11101  if (stp->copy_length != (off_t)-1)
11102  stp->copy_length -= len;
11103  }
11104 
11105  if (dst_fptr && io_fflush(dst_fptr) < 0) {
11106  rb_raise(rb_eIOError, "flush failed");
11107  }
11108 
11109  if (stp->copy_length == 0)
11110  return Qnil;
11111 
11112  if (src_fd == -1 || dst_fd == -1) {
11113  return copy_stream_fallback(stp);
11114  }
11115 
11116  rb_fd_set(src_fd, &stp->fds);
11117  rb_fd_set(dst_fd, &stp->fds);
11118 
11119  rb_thread_call_without_gvl(nogvl_copy_stream_func, (void*)stp, RUBY_UBF_IO, 0);
11120  return Qnil;
11121 }
11122 
11123 static VALUE
11124 copy_stream_finalize(VALUE arg)
11125 {
11126  struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
11127  if (stp->close_src) {
11128  rb_io_close_m(stp->src);
11129  }
11130  if (stp->close_dst) {
11131  rb_io_close_m(stp->dst);
11132  }
11133  rb_fd_term(&stp->fds);
11134  if (stp->syserr) {
11135  rb_syserr_fail(stp->error_no, stp->syserr);
11136  }
11137  if (stp->notimp) {
11138  rb_raise(rb_eNotImpError, "%s() not implemented", stp->notimp);
11139  }
11140  return Qnil;
11141 }
11142 
11143 /*
11144  * call-seq:
11145  * IO.copy_stream(src, dst)
11146  * IO.copy_stream(src, dst, copy_length)
11147  * IO.copy_stream(src, dst, copy_length, src_offset)
11148  *
11149  * IO.copy_stream copies <i>src</i> to <i>dst</i>.
11150  * <i>src</i> and <i>dst</i> is either a filename or an IO-like object.
11151  * IO-like object for <i>src</i> should have <code>readpartial</code> or
11152  * <code>read</code> method.
11153  * IO-like object for <i>dst</i> should have <code>write</code> method.
11154  * (Specialized mechanisms, such as sendfile system call, may be used
11155  * on appropriate situation.)
11156  *
11157  * This method returns the number of bytes copied.
11158  *
11159  * If optional arguments are not given,
11160  * the start position of the copy is
11161  * the beginning of the filename or
11162  * the current file offset of the IO.
11163  * The end position of the copy is the end of file.
11164  *
11165  * If <i>copy_length</i> is given,
11166  * No more than <i>copy_length</i> bytes are copied.
11167  *
11168  * If <i>src_offset</i> is given,
11169  * it specifies the start position of the copy.
11170  *
11171  * When <i>src_offset</i> is specified and
11172  * <i>src</i> is an IO,
11173  * IO.copy_stream doesn't move the current file offset.
11174  *
11175  */
11176 static VALUE
11177 rb_io_s_copy_stream(int argc, VALUE *argv, VALUE io)
11178 {
11179  VALUE src, dst, length, src_offset;
11180  struct copy_stream_struct st;
11181 
11182  MEMZERO(&st, struct copy_stream_struct, 1);
11183 
11184  rb_scan_args(argc, argv, "22", &src, &dst, &length, &src_offset);
11185 
11186  st.src = src;
11187  st.dst = dst;
11188 
11189  if (NIL_P(length))
11190  st.copy_length = (off_t)-1;
11191  else
11192  st.copy_length = NUM2OFFT(length);
11193 
11194  if (NIL_P(src_offset))
11195  st.src_offset = (off_t)-1;
11196  else
11197  st.src_offset = NUM2OFFT(src_offset);
11198 
11199  rb_fd_init(&st.fds);
11200  rb_ensure(copy_stream_body, (VALUE)&st, copy_stream_finalize, (VALUE)&st);
11201 
11202  return OFFT2NUM(st.total);
11203 }
11204 
11205 /*
11206  * call-seq:
11207  * io.external_encoding -> encoding
11208  *
11209  * Returns the Encoding object that represents the encoding of the file.
11210  * If _io_ is in write mode and no encoding is specified, returns +nil+.
11211  */
11212 
11213 static VALUE
11214 rb_io_external_encoding(VALUE io)
11215 {
11216  rb_io_t *fptr;
11217 
11218  GetOpenFile(io, fptr);
11219  if (fptr->encs.enc2) {
11220  return rb_enc_from_encoding(fptr->encs.enc2);
11221  }
11222  if (fptr->mode & FMODE_WRITABLE) {
11223  if (fptr->encs.enc)
11224  return rb_enc_from_encoding(fptr->encs.enc);
11225  return Qnil;
11226  }
11227  return rb_enc_from_encoding(io_read_encoding(fptr));
11228 }
11229 
11230 /*
11231  * call-seq:
11232  * io.internal_encoding -> encoding
11233  *
11234  * Returns the Encoding of the internal string if conversion is
11235  * specified. Otherwise returns +nil+.
11236  */
11237 
11238 static VALUE
11239 rb_io_internal_encoding(VALUE io)
11240 {
11241  rb_io_t *fptr;
11242 
11243  GetOpenFile(io, fptr);
11244  if (!fptr->encs.enc2) return Qnil;
11245  return rb_enc_from_encoding(io_read_encoding(fptr));
11246 }
11247 
11248 /*
11249  * call-seq:
11250  * io.set_encoding(ext_enc) -> io
11251  * io.set_encoding("ext_enc:int_enc") -> io
11252  * io.set_encoding(ext_enc, int_enc) -> io
11253  * io.set_encoding("ext_enc:int_enc", opt) -> io
11254  * io.set_encoding(ext_enc, int_enc, opt) -> io
11255  *
11256  * If single argument is specified, read string from io is tagged
11257  * with the encoding specified. If encoding is a colon separated two
11258  * encoding names "A:B", the read string is converted from encoding A
11259  * (external encoding) to encoding B (internal encoding), then tagged
11260  * with B. If two arguments are specified, those must be encoding
11261  * objects or encoding names, and the first one is the external encoding, and the
11262  * second one is the internal encoding.
11263  * If the external encoding and the internal encoding is specified,
11264  * optional hash argument specify the conversion option.
11265  */
11266 
11267 static VALUE
11268 rb_io_set_encoding(int argc, VALUE *argv, VALUE io)
11269 {
11270  rb_io_t *fptr;
11271  VALUE v1, v2, opt;
11272 
11273  if (!RB_TYPE_P(io, T_FILE)) {
11274  return rb_funcallv(io, id_set_encoding, argc, argv);
11275  }
11276 
11277  argc = rb_scan_args(argc, argv, "11:", &v1, &v2, &opt);
11278  GetOpenFile(io, fptr);
11279  io_encoding_set(fptr, v1, v2, opt);
11280  return io;
11281 }
11282 
11283 void
11285 {
11286  VALUE val = Qnil;
11287 
11288  rb_io_set_encoding(1, &val, rb_stdin);
11289  rb_io_set_encoding(1, &val, rb_stdout);
11290  rb_io_set_encoding(1, &val, rb_stderr);
11291 }
11292 
11293 static inline int
11294 global_argf_p(VALUE arg)
11295 {
11296  return arg == argf;
11297 }
11298 
11299 /*
11300  * call-seq:
11301  * ARGF.external_encoding -> encoding
11302  *
11303  * Returns the external encoding for files read from +ARGF+ as an +Encoding+
11304  * object. The external encoding is the encoding of the text as stored in a
11305  * file. Contrast with +ARGF.internal_encoding+, which is the encoding used
11306  * to represent this text within Ruby.
11307  *
11308  * To set the external encoding use +ARGF.set_encoding+.
11309  *
11310  * For example:
11311  *
11312  * ARGF.external_encoding #=> #<Encoding:UTF-8>
11313  *
11314  */
11315 static VALUE
11316 argf_external_encoding(VALUE argf)
11317 {
11318  if (!RTEST(ARGF.current_file)) {
11320  }
11321  return rb_io_external_encoding(rb_io_check_io(ARGF.current_file));
11322 }
11323 
11324 /*
11325  * call-seq:
11326  * ARGF.internal_encoding -> encoding
11327  *
11328  * Returns the internal encoding for strings read from +ARGF+ as an
11329  * +Encoding+ object.
11330  *
11331  * If +ARGF.set_encoding+ has been called with two encoding names, the second
11332  * is returned. Otherwise, if +Encoding.default_external+ has been set, that
11333  * value is returned. Failing that, if a default external encoding was
11334  * specified on the command-line, that value is used. If the encoding is
11335  * unknown, +nil+ is returned.
11336  */
11337 static VALUE
11338 argf_internal_encoding(VALUE argf)
11339 {
11340  if (!RTEST(ARGF.current_file)) {
11342  }
11343  return rb_io_internal_encoding(rb_io_check_io(ARGF.current_file));
11344 }
11345 
11346 /*
11347  * call-seq:
11348  * ARGF.set_encoding(ext_enc) -> ARGF
11349  * ARGF.set_encoding("ext_enc:int_enc") -> ARGF
11350  * ARGF.set_encoding(ext_enc, int_enc) -> ARGF
11351  * ARGF.set_encoding("ext_enc:int_enc", opt) -> ARGF
11352  * ARGF.set_encoding(ext_enc, int_enc, opt) -> ARGF
11353  *
11354  * If single argument is specified, strings read from ARGF are tagged with
11355  * the encoding specified.
11356  *
11357  * If two encoding names separated by a colon are given, e.g. "ascii:utf-8",
11358  * the read string is converted from the first encoding (external encoding)
11359  * to the second encoding (internal encoding), then tagged with the second
11360  * encoding.
11361  *
11362  * If two arguments are specified, they must be encoding objects or encoding
11363  * names. Again, the first specifies the external encoding; the second
11364  * specifies the internal encoding.
11365  *
11366  * If the external encoding and the internal encoding are specified, the
11367  * optional +Hash+ argument can be used to adjust the conversion process. The
11368  * structure of this hash is explained in the String#encode documentation.
11369  *
11370  * For example:
11371  *
11372  * ARGF.set_encoding('ascii') # Tag the input as US-ASCII text
11373  * ARGF.set_encoding(Encoding::UTF_8) # Tag the input as UTF-8 text
11374  * ARGF.set_encoding('utf-8','ascii') # Transcode the input from US-ASCII
11375  * # to UTF-8.
11376  */
11377 static VALUE
11378 argf_set_encoding(int argc, VALUE *argv, VALUE argf)
11379 {
11380  rb_io_t *fptr;
11381 
11382  if (!next_argv()) {
11383  rb_raise(rb_eArgError, "no stream to set encoding");
11384  }
11385  rb_io_set_encoding(argc, argv, ARGF.current_file);
11386  GetOpenFile(ARGF.current_file, fptr);
11387  ARGF.encs = fptr->encs;
11388  return argf;
11389 }
11390 
11391 /*
11392  * call-seq:
11393  * ARGF.tell -> Integer
11394  * ARGF.pos -> Integer
11395  *
11396  * Returns the current offset (in bytes) of the current file in +ARGF+.
11397  *
11398  * ARGF.pos #=> 0
11399  * ARGF.gets #=> "This is line one\n"
11400  * ARGF.pos #=> 17
11401  *
11402  */
11403 static VALUE
11404 argf_tell(VALUE argf)
11405 {
11406  if (!next_argv()) {
11407  rb_raise(rb_eArgError, "no stream to tell");
11408  }
11409  ARGF_FORWARD(0, 0);
11410  return rb_io_tell(ARGF.current_file);
11411 }
11412 
11413 /*
11414  * call-seq:
11415  * ARGF.seek(amount, whence=IO::SEEK_SET) -> 0
11416  *
11417  * Seeks to offset _amount_ (an +Integer+) in the +ARGF+ stream according to
11418  * the value of _whence_. See IO#seek for further details.
11419  */
11420 static VALUE
11421 argf_seek_m(int argc, VALUE *argv, VALUE argf)
11422 {
11423  if (!next_argv()) {
11424  rb_raise(rb_eArgError, "no stream to seek");
11425  }
11426  ARGF_FORWARD(argc, argv);
11427  return rb_io_seek_m(argc, argv, ARGF.current_file);
11428 }
11429 
11430 /*
11431  * call-seq:
11432  * ARGF.pos = position -> Integer
11433  *
11434  * Seeks to the position given by _position_ (in bytes) in +ARGF+.
11435  *
11436  * For example:
11437  *
11438  * ARGF.pos = 17
11439  * ARGF.gets #=> "This is line two\n"
11440  */
11441 static VALUE
11442 argf_set_pos(VALUE argf, VALUE offset)
11443 {
11444  if (!next_argv()) {
11445  rb_raise(rb_eArgError, "no stream to set position");
11446  }
11447  ARGF_FORWARD(1, &offset);
11448  return rb_io_set_pos(ARGF.current_file, offset);
11449 }
11450 
11451 /*
11452  * call-seq:
11453  * ARGF.rewind -> 0
11454  *
11455  * Positions the current file to the beginning of input, resetting
11456  * +ARGF.lineno+ to zero.
11457  *
11458  * ARGF.readline #=> "This is line one\n"
11459  * ARGF.rewind #=> 0
11460  * ARGF.lineno #=> 0
11461  * ARGF.readline #=> "This is line one\n"
11462  */
11463 static VALUE
11464 argf_rewind(VALUE argf)
11465 {
11466  VALUE ret;
11467  int old_lineno;
11468 
11469  if (!next_argv()) {
11470  rb_raise(rb_eArgError, "no stream to rewind");
11471  }
11472  ARGF_FORWARD(0, 0);
11473  old_lineno = RFILE(ARGF.current_file)->fptr->lineno;
11474  ret = rb_io_rewind(ARGF.current_file);
11475  if (!global_argf_p(argf)) {
11476  ARGF.last_lineno = ARGF.lineno -= old_lineno;
11477  }
11478  return ret;
11479 }
11480 
11481 /*
11482  * call-seq:
11483  * ARGF.fileno -> integer
11484  * ARGF.to_i -> integer
11485  *
11486  * Returns an integer representing the numeric file descriptor for
11487  * the current file. Raises an +ArgumentError+ if there isn't a current file.
11488  *
11489  * ARGF.fileno #=> 3
11490  */
11491 static VALUE
11492 argf_fileno(VALUE argf)
11493 {
11494  if (!next_argv()) {
11495  rb_raise(rb_eArgError, "no stream");
11496  }
11497  ARGF_FORWARD(0, 0);
11498  return rb_io_fileno(ARGF.current_file);
11499 }
11500 
11501 /*
11502  * call-seq:
11503  * ARGF.to_io -> IO
11504  *
11505  * Returns an +IO+ object representing the current file. This will be a
11506  * +File+ object unless the current file is a stream such as STDIN.
11507  *
11508  * For example:
11509  *
11510  * ARGF.to_io #=> #<File:glark.txt>
11511  * ARGF.to_io #=> #<IO:<STDIN>>
11512  */
11513 static VALUE
11514 argf_to_io(VALUE argf)
11515 {
11516  next_argv();
11517  ARGF_FORWARD(0, 0);
11518  return ARGF.current_file;
11519 }
11520 
11521 /*
11522  * call-seq:
11523  * ARGF.eof? -> true or false
11524  * ARGF.eof -> true or false
11525  *
11526  * Returns true if the current file in +ARGF+ is at end of file, i.e. it has
11527  * no data to read. The stream must be opened for reading or an +IOError+
11528  * will be raised.
11529  *
11530  * $ echo "eof" | ruby argf.rb
11531  *
11532  * ARGF.eof? #=> false
11533  * 3.times { ARGF.readchar }
11534  * ARGF.eof? #=> false
11535  * ARGF.readchar #=> "\n"
11536  * ARGF.eof? #=> true
11537  */
11538 
11539 static VALUE
11540 argf_eof(VALUE argf)
11541 {
11542  next_argv();
11543  if (RTEST(ARGF.current_file)) {
11544  if (ARGF.init_p == 0) return Qtrue;
11545  next_argv();
11546  ARGF_FORWARD(0, 0);
11547  if (rb_io_eof(ARGF.current_file)) {
11548  return Qtrue;
11549  }
11550  }
11551  return Qfalse;
11552 }
11553 
11554 /*
11555  * call-seq:
11556  * ARGF.read([length [, outbuf]]) -> string, outbuf, or nil
11557  *
11558  * Reads _length_ bytes from ARGF. The files named on the command line
11559  * are concatenated and treated as a single file by this method, so when
11560  * called without arguments the contents of this pseudo file are returned in
11561  * their entirety.
11562  *
11563  * _length_ must be a non-negative integer or +nil+.
11564  *
11565  * If _length_ is a positive integer, +read+ tries to read
11566  * _length_ bytes without any conversion (binary mode).
11567  * It returns +nil+ if an EOF is encountered before anything can be read.
11568  * Fewer than _length_ bytes are returned if an EOF is encountered during
11569  * the read.
11570  * In the case of an integer _length_, the resulting string is always
11571  * in ASCII-8BIT encoding.
11572  *
11573  * If _length_ is omitted or is +nil+, it reads until EOF
11574  * and the encoding conversion is applied, if applicable.
11575  * A string is returned even if EOF is encountered before any data is read.
11576  *
11577  * If _length_ is zero, it returns an empty string (<code>""</code>).
11578  *
11579  * If the optional _outbuf_ argument is present,
11580  * it must reference a String, which will receive the data.
11581  * The _outbuf_ will contain only the received data after the method call
11582  * even if it is not empty at the beginning.
11583  *
11584  * For example:
11585  *
11586  * $ echo "small" > small.txt
11587  * $ echo "large" > large.txt
11588  * $ ./glark.rb small.txt large.txt
11589  *
11590  * ARGF.read #=> "small\nlarge"
11591  * ARGF.read(200) #=> "small\nlarge"
11592  * ARGF.read(2) #=> "sm"
11593  * ARGF.read(0) #=> ""
11594  *
11595  * Note that this method behaves like the fread() function in C.
11596  * This means it retries to invoke read(2) system calls to read data
11597  * with the specified length.
11598  * If you need the behavior like a single read(2) system call,
11599  * consider ARGF#readpartial or ARGF#read_nonblock.
11600  */
11601 
11602 static VALUE
11603 argf_read(int argc, VALUE *argv, VALUE argf)
11604 {
11605  VALUE tmp, str, length;
11606  long len = 0;
11607 
11608  rb_scan_args(argc, argv, "02", &length, &str);
11609  if (!NIL_P(length)) {
11610  len = NUM2LONG(argv[0]);
11611  }
11612  if (!NIL_P(str)) {
11613  StringValue(str);
11614  rb_str_resize(str,0);
11615  argv[1] = Qnil;
11616  }
11617 
11618  retry:
11619  if (!next_argv()) {
11620  return str;
11621  }
11622  if (ARGF_GENERIC_INPUT_P()) {
11623  tmp = argf_forward(argc, argv, argf);
11624  }
11625  else {
11626  tmp = io_read(argc, argv, ARGF.current_file);
11627  }
11628  if (NIL_P(str)) str = tmp;
11629  else if (!NIL_P(tmp)) rb_str_append(str, tmp);
11630  if (NIL_P(tmp) || NIL_P(length)) {
11631  if (ARGF.next_p != -1) {
11632  argf_close(argf);
11633  ARGF.next_p = 1;
11634  goto retry;
11635  }
11636  }
11637  else if (argc >= 1) {
11638  long slen = RSTRING_LEN(str);
11639  if (slen < len) {
11640  len -= slen;
11641  argv[0] = INT2NUM(len);
11642  goto retry;
11643  }
11644  }
11645  return str;
11646 }
11647 
11649  int argc;
11652 };
11653 
11654 static VALUE
11655 argf_forward_call(VALUE arg)
11656 {
11657  struct argf_call_arg *p = (struct argf_call_arg *)arg;
11658  argf_forward(p->argc, p->argv, p->argf);
11659  return Qnil;
11660 }
11661 
11662 static VALUE argf_getpartial(int argc, VALUE *argv, VALUE argf, VALUE opts,
11663  int nonblock);
11664 
11665 /*
11666  * call-seq:
11667  * ARGF.readpartial(maxlen) -> string
11668  * ARGF.readpartial(maxlen, outbuf) -> outbuf
11669  *
11670  * Reads at most _maxlen_ bytes from the ARGF stream.
11671  *
11672  * If the optional _outbuf_ argument is present,
11673  * it must reference a String, which will receive the data.
11674  * The _outbuf_ will contain only the received data after the method call
11675  * even if it is not empty at the beginning.
11676  *
11677  * It raises <code>EOFError</code> on end of ARGF stream.
11678  * Since ARGF stream is a concatenation of multiple files,
11679  * internally EOF is occur for each file.
11680  * ARGF.readpartial returns empty strings for EOFs except the last one and
11681  * raises <code>EOFError</code> for the last one.
11682  *
11683  */
11684 
11685 static VALUE
11686 argf_readpartial(int argc, VALUE *argv, VALUE argf)
11687 {
11688  return argf_getpartial(argc, argv, argf, Qnil, 0);
11689 }
11690 
11691 /*
11692  * call-seq:
11693  * ARGF.read_nonblock(maxlen) -> string
11694  * ARGF.read_nonblock(maxlen, outbuf) -> outbuf
11695  *
11696  * Reads at most _maxlen_ bytes from the ARGF stream in non-blocking mode.
11697  */
11698 
11699 static VALUE
11700 argf_read_nonblock(int argc, VALUE *argv, VALUE argf)
11701 {
11702  VALUE opts;
11703 
11704  rb_scan_args(argc, argv, "11:", NULL, NULL, &opts);
11705 
11706  if (!NIL_P(opts))
11707  argc--;
11708 
11709  return argf_getpartial(argc, argv, argf, opts, 1);
11710 }
11711 
11712 static VALUE
11713 argf_getpartial(int argc, VALUE *argv, VALUE argf, VALUE opts, int nonblock)
11714 {
11715  VALUE tmp, str, length;
11716 
11717  rb_scan_args(argc, argv, "11", &length, &str);
11718  if (!NIL_P(str)) {
11719  StringValue(str);
11720  argv[1] = str;
11721  }
11722 
11723  if (!next_argv()) {
11724  if (!NIL_P(str)) {
11725  rb_str_resize(str, 0);
11726  }
11727  rb_eof_error();
11728  }
11729  if (ARGF_GENERIC_INPUT_P()) {
11730  struct argf_call_arg arg;
11731  arg.argc = argc;
11732  arg.argv = argv;
11733  arg.argf = argf;
11734  tmp = rb_rescue2(argf_forward_call, (VALUE)&arg,
11736  }
11737  else {
11738  tmp = io_getpartial(argc, argv, ARGF.current_file, opts, nonblock);
11739  }
11740  if (NIL_P(tmp)) {
11741  if (ARGF.next_p == -1) {
11742  return io_nonblock_eof(opts);
11743  }
11744  argf_close(argf);
11745  ARGF.next_p = 1;
11746  if (RARRAY_LEN(ARGF.argv) == 0) {
11747  return io_nonblock_eof(opts);
11748  }
11749  if (NIL_P(str))
11750  str = rb_str_new(NULL, 0);
11751  return str;
11752  }
11753  return tmp;
11754 }
11755 
11756 /*
11757  * call-seq:
11758  * ARGF.getc -> String or nil
11759  *
11760  * Reads the next character from +ARGF+ and returns it as a +String+. Returns
11761  * +nil+ at the end of the stream.
11762  *
11763  * +ARGF+ treats the files named on the command line as a single file created
11764  * by concatenating their contents. After returning the last character of the
11765  * first file, it returns the first character of the second file, and so on.
11766  *
11767  * For example:
11768  *
11769  * $ echo "foo" > file
11770  * $ ruby argf.rb file
11771  *
11772  * ARGF.getc #=> "f"
11773  * ARGF.getc #=> "o"
11774  * ARGF.getc #=> "o"
11775  * ARGF.getc #=> "\n"
11776  * ARGF.getc #=> nil
11777  * ARGF.getc #=> nil
11778  */
11779 static VALUE
11780 argf_getc(VALUE argf)
11781 {
11782  VALUE ch;
11783 
11784  retry:
11785  if (!next_argv()) return Qnil;
11786  if (ARGF_GENERIC_INPUT_P()) {
11787  ch = rb_funcall3(ARGF.current_file, rb_intern("getc"), 0, 0);
11788  }
11789  else {
11790  ch = rb_io_getc(ARGF.current_file);
11791  }
11792  if (NIL_P(ch) && ARGF.next_p != -1) {
11793  argf_close(argf);
11794  ARGF.next_p = 1;
11795  goto retry;
11796  }
11797 
11798  return ch;
11799 }
11800 
11801 /*
11802  * call-seq:
11803  * ARGF.getbyte -> Integer or nil
11804  *
11805  * Gets the next 8-bit byte (0..255) from +ARGF+. Returns +nil+ if called at
11806  * the end of the stream.
11807  *
11808  * For example:
11809  *
11810  * $ echo "foo" > file
11811  * $ ruby argf.rb file
11812  *
11813  * ARGF.getbyte #=> 102
11814  * ARGF.getbyte #=> 111
11815  * ARGF.getbyte #=> 111
11816  * ARGF.getbyte #=> 10
11817  * ARGF.getbyte #=> nil
11818  */
11819 static VALUE
11820 argf_getbyte(VALUE argf)
11821 {
11822  VALUE ch;
11823 
11824  retry:
11825  if (!next_argv()) return Qnil;
11826  if (!RB_TYPE_P(ARGF.current_file, T_FILE)) {
11827  ch = rb_funcall3(ARGF.current_file, rb_intern("getbyte"), 0, 0);
11828  }
11829  else {
11830  ch = rb_io_getbyte(ARGF.current_file);
11831  }
11832  if (NIL_P(ch) && ARGF.next_p != -1) {
11833  argf_close(argf);
11834  ARGF.next_p = 1;
11835  goto retry;
11836  }
11837 
11838  return ch;
11839 }
11840 
11841 /*
11842  * call-seq:
11843  * ARGF.readchar -> String or nil
11844  *
11845  * Reads the next character from +ARGF+ and returns it as a +String+. Raises
11846  * an +EOFError+ after the last character of the last file has been read.
11847  *
11848  * For example:
11849  *
11850  * $ echo "foo" > file
11851  * $ ruby argf.rb file
11852  *
11853  * ARGF.readchar #=> "f"
11854  * ARGF.readchar #=> "o"
11855  * ARGF.readchar #=> "o"
11856  * ARGF.readchar #=> "\n"
11857  * ARGF.readchar #=> end of file reached (EOFError)
11858  */
11859 static VALUE
11860 argf_readchar(VALUE argf)
11861 {
11862  VALUE ch;
11863 
11864  retry:
11865  if (!next_argv()) rb_eof_error();
11866  if (!RB_TYPE_P(ARGF.current_file, T_FILE)) {
11867  ch = rb_funcall3(ARGF.current_file, rb_intern("getc"), 0, 0);
11868  }
11869  else {
11870  ch = rb_io_getc(ARGF.current_file);
11871  }
11872  if (NIL_P(ch) && ARGF.next_p != -1) {
11873  argf_close(argf);
11874  ARGF.next_p = 1;
11875  goto retry;
11876  }
11877 
11878  return ch;
11879 }
11880 
11881 /*
11882  * call-seq:
11883  * ARGF.readbyte -> Integer
11884  *
11885  * Reads the next 8-bit byte from ARGF and returns it as an +Integer+. Raises
11886  * an +EOFError+ after the last byte of the last file has been read.
11887  *
11888  * For example:
11889  *
11890  * $ echo "foo" > file
11891  * $ ruby argf.rb file
11892  *
11893  * ARGF.readbyte #=> 102
11894  * ARGF.readbyte #=> 111
11895  * ARGF.readbyte #=> 111
11896  * ARGF.readbyte #=> 10
11897  * ARGF.readbyte #=> end of file reached (EOFError)
11898  */
11899 static VALUE
11900 argf_readbyte(VALUE argf)
11901 {
11902  VALUE c;
11903 
11904  NEXT_ARGF_FORWARD(0, 0);
11905  c = argf_getbyte(argf);
11906  if (NIL_P(c)) {
11907  rb_eof_error();
11908  }
11909  return c;
11910 }
11911 
11912 #define FOREACH_ARGF() while (next_argv())
11913 
11914 static VALUE
11915 argf_block_call_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, argf))
11916 {
11917  const VALUE current = ARGF.current_file;
11918  rb_yield_values2(argc, argv);
11919  if (ARGF.init_p == -1 || current != ARGF.current_file) {
11921  }
11922  return Qnil;
11923 }
11924 
11925 static void
11926 argf_block_call(ID mid, int argc, VALUE *argv, VALUE argf)
11927 {
11928  VALUE ret = rb_block_call(ARGF.current_file, mid, argc, argv, argf_block_call_i, argf);
11929  if (ret != Qundef) ARGF.next_p = 1;
11930 }
11931 
11932 static VALUE
11933 argf_block_call_line_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, argf))
11934 {
11935  if (!global_argf_p(argf)) {
11936  ARGF.last_lineno = ++ARGF.lineno;
11937  }
11938  return argf_block_call_i(i, argf, argc, argv, blockarg);
11939 }
11940 
11941 static void
11942 argf_block_call_line(ID mid, int argc, VALUE *argv, VALUE argf)
11943 {
11944  VALUE ret = rb_block_call(ARGF.current_file, mid, argc, argv, argf_block_call_line_i, argf);
11945  if (ret != Qundef) ARGF.next_p = 1;
11946 }
11947 
11948 /*
11949  * call-seq:
11950  * ARGF.each(sep=$/) {|line| block } -> ARGF
11951  * ARGF.each(sep=$/, limit) {|line| block } -> ARGF
11952  * ARGF.each(...) -> an_enumerator
11953  *
11954  * ARGF.each_line(sep=$/) {|line| block } -> ARGF
11955  * ARGF.each_line(sep=$/, limit) {|line| block } -> ARGF
11956  * ARGF.each_line(...) -> an_enumerator
11957  *
11958  * Returns an enumerator which iterates over each line (separated by _sep_,
11959  * which defaults to your platform's newline character) of each file in
11960  * +ARGV+. If a block is supplied, each line in turn will be yielded to the
11961  * block, otherwise an enumerator is returned.
11962  * The optional _limit_ argument is an +Integer+ specifying the maximum
11963  * length of each line; longer lines will be split according to this limit.
11964  *
11965  * This method allows you to treat the files supplied on the command line as
11966  * a single file consisting of the concatenation of each named file. After
11967  * the last line of the first file has been returned, the first line of the
11968  * second file is returned. The +ARGF.filename+ and +ARGF.lineno+ methods can
11969  * be used to determine the filename and line number, respectively, of the
11970  * current line.
11971  *
11972  * For example, the following code prints out each line of each named file
11973  * prefixed with its line number, displaying the filename once per file:
11974  *
11975  * ARGF.each_line do |line|
11976  * puts ARGF.filename if ARGF.lineno == 1
11977  * puts "#{ARGF.lineno}: #{line}"
11978  * end
11979  */
11980 static VALUE
11981 argf_each_line(int argc, VALUE *argv, VALUE argf)
11982 {
11983  RETURN_ENUMERATOR(argf, argc, argv);
11984  FOREACH_ARGF() {
11985  argf_block_call_line(rb_intern("each_line"), argc, argv, argf);
11986  }
11987  return argf;
11988 }
11989 
11990 /*
11991  * This is a deprecated alias for <code>each_line</code>.
11992  */
11993 
11994 static VALUE
11995 argf_lines(int argc, VALUE *argv, VALUE argf)
11996 {
11997  rb_warn("ARGF#lines is deprecated; use #each_line instead");
11998  if (!rb_block_given_p())
11999  return rb_enumeratorize(argf, ID2SYM(rb_intern("each_line")), argc, argv);
12000  return argf_each_line(argc, argv, argf);
12001 }
12002 
12003 /*
12004  * call-seq:
12005  * ARGF.bytes {|byte| block } -> ARGF
12006  * ARGF.bytes -> an_enumerator
12007  *
12008  * ARGF.each_byte {|byte| block } -> ARGF
12009  * ARGF.each_byte -> an_enumerator
12010  *
12011  * Iterates over each byte of each file in +ARGV+.
12012  * A byte is returned as an +Integer+ in the range 0..255.
12013  *
12014  * This method allows you to treat the files supplied on the command line as
12015  * a single file consisting of the concatenation of each named file. After
12016  * the last byte of the first file has been returned, the first byte of the
12017  * second file is returned. The +ARGF.filename+ method can be used to
12018  * determine the filename of the current byte.
12019  *
12020  * If no block is given, an enumerator is returned instead.
12021  *
12022  * For example:
12023  *
12024  * ARGF.bytes.to_a #=> [35, 32, ... 95, 10]
12025  *
12026  */
12027 static VALUE
12028 argf_each_byte(VALUE argf)
12029 {
12030  RETURN_ENUMERATOR(argf, 0, 0);
12031  FOREACH_ARGF() {
12032  argf_block_call(rb_intern("each_byte"), 0, 0, argf);
12033  }
12034  return argf;
12035 }
12036 
12037 /*
12038  * This is a deprecated alias for <code>each_byte</code>.
12039  */
12040 
12041 static VALUE
12042 argf_bytes(VALUE argf)
12043 {
12044  rb_warn("ARGF#bytes is deprecated; use #each_byte instead");
12045  if (!rb_block_given_p())
12046  return rb_enumeratorize(argf, ID2SYM(rb_intern("each_byte")), 0, 0);
12047  return argf_each_byte(argf);
12048 }
12049 
12050 /*
12051  * call-seq:
12052  * ARGF.each_char {|char| block } -> ARGF
12053  * ARGF.each_char -> an_enumerator
12054  *
12055  * Iterates over each character of each file in +ARGF+.
12056  *
12057  * This method allows you to treat the files supplied on the command line as
12058  * a single file consisting of the concatenation of each named file. After
12059  * the last character of the first file has been returned, the first
12060  * character of the second file is returned. The +ARGF.filename+ method can
12061  * be used to determine the name of the file in which the current character
12062  * appears.
12063  *
12064  * If no block is given, an enumerator is returned instead.
12065  */
12066 static VALUE
12067 argf_each_char(VALUE argf)
12068 {
12069  RETURN_ENUMERATOR(argf, 0, 0);
12070  FOREACH_ARGF() {
12071  argf_block_call(rb_intern("each_char"), 0, 0, argf);
12072  }
12073  return argf;
12074 }
12075 
12076 /*
12077  * This is a deprecated alias for <code>each_char</code>.
12078  */
12079 
12080 static VALUE
12081 argf_chars(VALUE argf)
12082 {
12083  rb_warn("ARGF#chars is deprecated; use #each_char instead");
12084  if (!rb_block_given_p())
12085  return rb_enumeratorize(argf, ID2SYM(rb_intern("each_char")), 0, 0);
12086  return argf_each_char(argf);
12087 }
12088 
12089 /*
12090  * call-seq:
12091  * ARGF.each_codepoint {|codepoint| block } -> ARGF
12092  * ARGF.each_codepoint -> an_enumerator
12093  *
12094  * Iterates over each codepoint of each file in +ARGF+.
12095  *
12096  * This method allows you to treat the files supplied on the command line as
12097  * a single file consisting of the concatenation of each named file. After
12098  * the last codepoint of the first file has been returned, the first
12099  * codepoint of the second file is returned. The +ARGF.filename+ method can
12100  * be used to determine the name of the file in which the current codepoint
12101  * appears.
12102  *
12103  * If no block is given, an enumerator is returned instead.
12104  */
12105 static VALUE
12106 argf_each_codepoint(VALUE argf)
12107 {
12108  RETURN_ENUMERATOR(argf, 0, 0);
12109  FOREACH_ARGF() {
12110  argf_block_call(rb_intern("each_codepoint"), 0, 0, argf);
12111  }
12112  return argf;
12113 }
12114 
12115 /*
12116  * This is a deprecated alias for <code>each_codepoint</code>.
12117  */
12118 
12119 static VALUE
12120 argf_codepoints(VALUE argf)
12121 {
12122  rb_warn("ARGF#codepoints is deprecated; use #each_codepoint instead");
12123  if (!rb_block_given_p())
12124  return rb_enumeratorize(argf, ID2SYM(rb_intern("each_codepoint")), 0, 0);
12125  return argf_each_codepoint(argf);
12126 }
12127 
12128 /*
12129  * call-seq:
12130  * ARGF.filename -> String
12131  * ARGF.path -> String
12132  *
12133  * Returns the current filename. "-" is returned when the current file is
12134  * STDIN.
12135  *
12136  * For example:
12137  *
12138  * $ echo "foo" > foo
12139  * $ echo "bar" > bar
12140  * $ echo "glark" > glark
12141  *
12142  * $ ruby argf.rb foo bar glark
12143  *
12144  * ARGF.filename #=> "foo"
12145  * ARGF.read(5) #=> "foo\nb"
12146  * ARGF.filename #=> "bar"
12147  * ARGF.skip
12148  * ARGF.filename #=> "glark"
12149  */
12150 static VALUE
12151 argf_filename(VALUE argf)
12152 {
12153  next_argv();
12154  return ARGF.filename;
12155 }
12156 
12157 static VALUE
12158 argf_filename_getter(ID id, VALUE *var)
12159 {
12160  return argf_filename(*var);
12161 }
12162 
12163 /*
12164  * call-seq:
12165  * ARGF.file -> IO or File object
12166  *
12167  * Returns the current file as an +IO+ or +File+ object.
12168  * <code>$stdin</code> is returned when the current file is STDIN.
12169  *
12170  * For example:
12171  *
12172  * $ echo "foo" > foo
12173  * $ echo "bar" > bar
12174  *
12175  * $ ruby argf.rb foo bar
12176  *
12177  * ARGF.file #=> #<File:foo>
12178  * ARGF.read(5) #=> "foo\nb"
12179  * ARGF.file #=> #<File:bar>
12180  */
12181 static VALUE
12182 argf_file(VALUE argf)
12183 {
12184  next_argv();
12185  return ARGF.current_file;
12186 }
12187 
12188 /*
12189  * call-seq:
12190  * ARGF.binmode -> ARGF
12191  *
12192  * Puts +ARGF+ into binary mode. Once a stream is in binary mode, it cannot
12193  * be reset to non-binary mode. This option has the following effects:
12194  *
12195  * * Newline conversion is disabled.
12196  * * Encoding conversion is disabled.
12197  * * Content is treated as ASCII-8BIT.
12198  */
12199 static VALUE
12200 argf_binmode_m(VALUE argf)
12201 {
12202  ARGF.binmode = 1;
12203  next_argv();
12204  ARGF_FORWARD(0, 0);
12205  rb_io_ascii8bit_binmode(ARGF.current_file);
12206  return argf;
12207 }
12208 
12209 /*
12210  * call-seq:
12211  * ARGF.binmode? -> true or false
12212  *
12213  * Returns true if +ARGF+ is being read in binary mode; false otherwise.
12214  * To enable binary mode use +ARGF.binmode+.
12215  *
12216  * For example:
12217  *
12218  * ARGF.binmode? #=> false
12219  * ARGF.binmode
12220  * ARGF.binmode? #=> true
12221  */
12222 static VALUE
12223 argf_binmode_p(VALUE argf)
12224 {
12225  return ARGF.binmode ? Qtrue : Qfalse;
12226 }
12227 
12228 /*
12229  * call-seq:
12230  * ARGF.skip -> ARGF
12231  *
12232  * Sets the current file to the next file in ARGV. If there aren't any more
12233  * files it has no effect.
12234  *
12235  * For example:
12236  *
12237  * $ ruby argf.rb foo bar
12238  * ARGF.filename #=> "foo"
12239  * ARGF.skip
12240  * ARGF.filename #=> "bar"
12241  */
12242 static VALUE
12243 argf_skip(VALUE argf)
12244 {
12245  if (ARGF.init_p && ARGF.next_p == 0) {
12246  argf_close(argf);
12247  ARGF.next_p = 1;
12248  }
12249  return argf;
12250 }
12251 
12252 /*
12253  * call-seq:
12254  * ARGF.close -> ARGF
12255  *
12256  * Closes the current file and skips to the next file in ARGV. If there are
12257  * no more files to open, just closes the current file. +STDIN+ will not be
12258  * closed.
12259  *
12260  * For example:
12261  *
12262  * $ ruby argf.rb foo bar
12263  *
12264  * ARGF.filename #=> "foo"
12265  * ARGF.close
12266  * ARGF.filename #=> "bar"
12267  * ARGF.close
12268  */
12269 static VALUE
12270 argf_close_m(VALUE argf)
12271 {
12272  next_argv();
12273  argf_close(argf);
12274  if (ARGF.next_p != -1) {
12275  ARGF.next_p = 1;
12276  }
12277  ARGF.lineno = 0;
12278  return argf;
12279 }
12280 
12281 /*
12282  * call-seq:
12283  * ARGF.closed? -> true or false
12284  *
12285  * Returns _true_ if the current file has been closed; _false_ otherwise. Use
12286  * +ARGF.close+ to actually close the current file.
12287  */
12288 static VALUE
12289 argf_closed(VALUE argf)
12290 {
12291  next_argv();
12292  ARGF_FORWARD(0, 0);
12293  return rb_io_closed(ARGF.current_file);
12294 }
12295 
12296 /*
12297  * call-seq:
12298  * ARGF.to_s -> String
12299  *
12300  * Returns "ARGF".
12301  */
12302 static VALUE
12303 argf_to_s(VALUE argf)
12304 {
12305  return rb_str_new2("ARGF");
12306 }
12307 
12308 /*
12309  * call-seq:
12310  * ARGF.inplace_mode -> String
12311  *
12312  * Returns the file extension appended to the names of modified files under
12313  * in-place edit mode. This value can be set using +ARGF.inplace_mode=+ or
12314  * passing the +-i+ switch to the Ruby binary.
12315  */
12316 static VALUE
12317 argf_inplace_mode_get(VALUE argf)
12318 {
12319  if (!ARGF.inplace) return Qnil;
12320  if (NIL_P(ARGF.inplace)) return rb_str_new(0, 0);
12321  return rb_str_dup(ARGF.inplace);
12322 }
12323 
12324 static VALUE
12325 opt_i_get(ID id, VALUE *var)
12326 {
12327  return argf_inplace_mode_get(*var);
12328 }
12329 
12330 /*
12331  * call-seq:
12332  * ARGF.inplace_mode = ext -> ARGF
12333  *
12334  * Sets the filename extension for in-place editing mode to the given String.
12335  * Each file being edited has this value appended to its filename. The
12336  * modified file is saved under this new name.
12337  *
12338  * For example:
12339  *
12340  * $ ruby argf.rb file.txt
12341  *
12342  * ARGF.inplace_mode = '.bak'
12343  * ARGF.each_line do |line|
12344  * print line.sub("foo","bar")
12345  * end
12346  *
12347  * Each line of _file.txt_ has the first occurrence of "foo" replaced with
12348  * "bar", then the new line is written out to _file.txt.bak_.
12349  */
12350 static VALUE
12351 argf_inplace_mode_set(VALUE argf, VALUE val)
12352 {
12353  if (rb_safe_level() >= 1 && OBJ_TAINTED(val))
12355 
12356  if (!RTEST(val)) {
12357  ARGF.inplace = Qfalse;
12358  }
12359  else if (StringValueCStr(val), !RSTRING_LEN(val)) {
12360  ARGF.inplace = Qnil;
12361  }
12362  else {
12363  ARGF.inplace = rb_str_new_frozen(val);
12364  }
12365  return argf;
12366 }
12367 
12368 static void
12369 opt_i_set(VALUE val, ID id, VALUE *var)
12370 {
12371  argf_inplace_mode_set(*var, val);
12372 }
12373 
12374 const char *
12376 {
12377  return RSTRING_PTR(ARGF.inplace);
12378 }
12379 
12380 void
12381 ruby_set_inplace_mode(const char *suffix)
12382 {
12383  ARGF.inplace = !suffix ? Qfalse : !*suffix ? Qnil : rb_fstring_cstr(suffix);
12384 }
12385 
12386 /*
12387  * call-seq:
12388  * ARGF.argv -> ARGV
12389  *
12390  * Returns the +ARGV+ array, which contains the arguments passed to your
12391  * script, one per element.
12392  *
12393  * For example:
12394  *
12395  * $ ruby argf.rb -v glark.txt
12396  *
12397  * ARGF.argv #=> ["-v", "glark.txt"]
12398  *
12399  */
12400 static VALUE
12401 argf_argv(VALUE argf)
12402 {
12403  return ARGF.argv;
12404 }
12405 
12406 static VALUE
12407 argf_argv_getter(ID id, VALUE *var)
12408 {
12409  return argf_argv(*var);
12410 }
12411 
12412 VALUE
12414 {
12415  return ARGF.argv;
12416 }
12417 
12418 /*
12419  * call-seq:
12420  * ARGF.to_write_io -> io
12421  *
12422  * Returns IO instance tied to _ARGF_ for writing if inplace mode is
12423  * enabled.
12424  */
12425 static VALUE
12426 argf_write_io(VALUE argf)
12427 {
12428  if (!RTEST(ARGF.current_file)) {
12429  rb_raise(rb_eIOError, "not opened for writing");
12430  }
12431  return GetWriteIO(ARGF.current_file);
12432 }
12433 
12434 /*
12435  * call-seq:
12436  * ARGF.write(string) -> integer
12437  *
12438  * Writes _string_ if inplace mode.
12439  */
12440 static VALUE
12441 argf_write(VALUE argf, VALUE str)
12442 {
12443  return rb_io_write(argf_write_io(argf), str);
12444 }
12445 
12446 void
12447 rb_readwrite_sys_fail(enum rb_io_wait_readwrite writable, const char *mesg)
12448 {
12449  rb_readwrite_syserr_fail(writable, errno, mesg);
12450 }
12451 
12452 void
12453 rb_readwrite_syserr_fail(enum rb_io_wait_readwrite writable, int n, const char *mesg)
12454 {
12455  VALUE arg;
12456  arg = mesg ? rb_str_new2(mesg) : Qnil;
12457  if (writable == RB_IO_WAIT_WRITABLE) {
12458  switch (n) {
12459  case EAGAIN:
12460  rb_exc_raise(rb_class_new_instance(1, &arg, rb_eEAGAINWaitWritable));
12461  break;
12462 #if EAGAIN != EWOULDBLOCK
12463  case EWOULDBLOCK:
12464  rb_exc_raise(rb_class_new_instance(1, &arg, rb_eEWOULDBLOCKWaitWritable));
12465  break;
12466 #endif
12467  case EINPROGRESS:
12468  rb_exc_raise(rb_class_new_instance(1, &arg, rb_eEINPROGRESSWaitWritable));
12469  break;
12470  default:
12472  }
12473  }
12474  else if (writable == RB_IO_WAIT_READABLE) {
12475  switch (n) {
12476  case EAGAIN:
12477  rb_exc_raise(rb_class_new_instance(1, &arg, rb_eEAGAINWaitReadable));
12478  break;
12479 #if EAGAIN != EWOULDBLOCK
12480  case EWOULDBLOCK:
12481  rb_exc_raise(rb_class_new_instance(1, &arg, rb_eEWOULDBLOCKWaitReadable));
12482  break;
12483 #endif
12484  case EINPROGRESS:
12485  rb_exc_raise(rb_class_new_instance(1, &arg, rb_eEINPROGRESSWaitReadable));
12486  break;
12487  default:
12489  }
12490  }
12491  else {
12492  rb_bug("invalid read/write type passed to rb_readwrite_sys_fail: %d", writable);
12493  }
12494 }
12495 
12496 /*
12497  * Document-class: IOError
12498  *
12499  * Raised when an IO operation fails.
12500  *
12501  * File.open("/etc/hosts") {|f| f << "example"}
12502  * #=> IOError: not opened for writing
12503  *
12504  * File.open("/etc/hosts") {|f| f.close; f.read }
12505  * #=> IOError: closed stream
12506  *
12507  * Note that some IO failures raise <code>SystemCallError</code>s
12508  * and these are not subclasses of IOError:
12509  *
12510  * File.open("does/not/exist")
12511  * #=> Errno::ENOENT: No such file or directory - does/not/exist
12512  */
12513 
12514 /*
12515  * Document-class: EOFError
12516  *
12517  * Raised by some IO operations when reaching the end of file. Many IO
12518  * methods exist in two forms,
12519  *
12520  * one that returns +nil+ when the end of file is reached, the other
12521  * raises +EOFError+.
12522  *
12523  * +EOFError+ is a subclass of +IOError+.
12524  *
12525  * file = File.open("/etc/hosts")
12526  * file.read
12527  * file.gets #=> nil
12528  * file.readline #=> EOFError: end of file reached
12529  */
12530 
12531 /*
12532  * Document-class: ARGF
12533  *
12534  * +ARGF+ is a stream designed for use in scripts that process files given as
12535  * command-line arguments or passed in via STDIN.
12536  *
12537  * The arguments passed to your script are stored in the +ARGV+ Array, one
12538  * argument per element. +ARGF+ assumes that any arguments that aren't
12539  * filenames have been removed from +ARGV+. For example:
12540  *
12541  * $ ruby argf.rb --verbose file1 file2
12542  *
12543  * ARGV #=> ["--verbose", "file1", "file2"]
12544  * option = ARGV.shift #=> "--verbose"
12545  * ARGV #=> ["file1", "file2"]
12546  *
12547  * You can now use +ARGF+ to work with a concatenation of each of these named
12548  * files. For instance, +ARGF.read+ will return the contents of _file1_
12549  * followed by the contents of _file2_.
12550  *
12551  * After a file in +ARGV+ has been read +ARGF+ removes it from the Array.
12552  * Thus, after all files have been read +ARGV+ will be empty.
12553  *
12554  * You can manipulate +ARGV+ yourself to control what +ARGF+ operates on. If
12555  * you remove a file from +ARGV+, it is ignored by +ARGF+; if you add files to
12556  * +ARGV+, they are treated as if they were named on the command line. For
12557  * example:
12558  *
12559  * ARGV.replace ["file1"]
12560  * ARGF.readlines # Returns the contents of file1 as an Array
12561  * ARGV #=> []
12562  * ARGV.replace ["file2", "file3"]
12563  * ARGF.read # Returns the contents of file2 and file3
12564  *
12565  * If +ARGV+ is empty, +ARGF+ acts as if it contained STDIN, i.e. the data
12566  * piped to your script. For example:
12567  *
12568  * $ echo "glark" | ruby -e 'p ARGF.read'
12569  * "glark\n"
12570  */
12571 
12572 /*
12573  * The IO class is the basis for all input and output in Ruby.
12574  * An I/O stream may be <em>duplexed</em> (that is, bidirectional), and
12575  * so may use more than one native operating system stream.
12576  *
12577  * Many of the examples in this section use the File class, the only standard
12578  * subclass of IO. The two classes are closely associated. Like the File
12579  * class, the Socket library subclasses from IO (such as TCPSocket or
12580  * UDPSocket).
12581  *
12582  * The Kernel#open method can create an IO (or File) object for these types
12583  * of arguments:
12584  *
12585  * * A plain string represents a filename suitable for the underlying
12586  * operating system.
12587  *
12588  * * A string starting with <code>"|"</code> indicates a subprocess.
12589  * The remainder of the string following the <code>"|"</code> is
12590  * invoked as a process with appropriate input/output channels
12591  * connected to it.
12592  *
12593  * * A string equal to <code>"|-"</code> will create another Ruby
12594  * instance as a subprocess.
12595  *
12596  * The IO may be opened with different file modes (read-only, write-only) and
12597  * encodings for proper conversion. See IO.new for these options. See
12598  * Kernel#open for details of the various command formats described above.
12599  *
12600  * IO.popen, the Open3 library, or Process#spawn may also be used to
12601  * communicate with subprocesses through an IO.
12602  *
12603  * Ruby will convert pathnames between different operating system
12604  * conventions if possible. For instance, on a Windows system the
12605  * filename <code>"/gumby/ruby/test.rb"</code> will be opened as
12606  * <code>"\gumby\ruby\test.rb"</code>. When specifying a Windows-style
12607  * filename in a Ruby string, remember to escape the backslashes:
12608  *
12609  * "C:\\gumby\\ruby\\test.rb"
12610  *
12611  * Our examples here will use the Unix-style forward slashes;
12612  * File::ALT_SEPARATOR can be used to get the platform-specific separator
12613  * character.
12614  *
12615  * The global constant ARGF (also accessible as <code>$<</code>) provides an
12616  * IO-like stream which allows access to all files mentioned on the
12617  * command line (or STDIN if no files are mentioned). ARGF#path and its alias
12618  * ARGF#filename are provided to access the name of the file currently being
12619  * read.
12620  *
12621  * == io/console
12622  *
12623  * The io/console extension provides methods for interacting with the
12624  * console. The console can be accessed from IO.console or the standard
12625  * input/output/error IO objects.
12626  *
12627  * Requiring io/console adds the following methods:
12628  *
12629  * * IO::console
12630  * * IO#raw
12631  * * IO#raw!
12632  * * IO#cooked
12633  * * IO#cooked!
12634  * * IO#getch
12635  * * IO#echo=
12636  * * IO#echo?
12637  * * IO#noecho
12638  * * IO#winsize
12639  * * IO#winsize=
12640  * * IO#iflush
12641  * * IO#ioflush
12642  * * IO#oflush
12643  *
12644  * Example:
12645  *
12646  * require 'io/console'
12647  * rows, columns = $stdout.winsize
12648  * puts "Your screen is #{columns} wide and #{rows} tall"
12649  */
12650 
12651 void
12652 Init_IO(void)
12653 {
12654 #undef rb_intern
12655 #define rb_intern(str) rb_intern_const(str)
12656 
12657  VALUE rb_cARGF;
12658 #ifdef __CYGWIN__
12659 #include <sys/cygwin.h>
12660  static struct __cygwin_perfile pf[] =
12661  {
12662  {"", O_RDONLY | O_BINARY},
12663  {"", O_WRONLY | O_BINARY},
12664  {"", O_RDWR | O_BINARY},
12665  {"", O_APPEND | O_BINARY},
12666  {NULL, 0}
12667  };
12668  cygwin_internal(CW_PERFILE, pf);
12669 #endif
12670 
12672  rb_eEOFError = rb_define_class("EOFError", rb_eIOError);
12673 
12674  id_write = rb_intern("write");
12675  id_read = rb_intern("read");
12676  id_getc = rb_intern("getc");
12677  id_flush = rb_intern("flush");
12678  id_readpartial = rb_intern("readpartial");
12679  id_set_encoding = rb_intern("set_encoding");
12680 
12681  rb_define_global_function("syscall", rb_f_syscall, -1);
12682 
12683  rb_define_global_function("open", rb_f_open, -1);
12684  rb_define_global_function("printf", rb_f_printf, -1);
12685  rb_define_global_function("print", rb_f_print, -1);
12686  rb_define_global_function("putc", rb_f_putc, 1);
12687  rb_define_global_function("puts", rb_f_puts, -1);
12688  rb_define_global_function("gets", rb_f_gets, -1);
12689  rb_define_global_function("readline", rb_f_readline, -1);
12690  rb_define_global_function("select", rb_f_select, -1);
12691 
12692  rb_define_global_function("readlines", rb_f_readlines, -1);
12693 
12694  rb_define_global_function("`", rb_f_backquote, 1);
12695 
12696  rb_define_global_function("p", rb_f_p, -1);
12697  rb_define_method(rb_mKernel, "display", rb_obj_display, -1);
12698 
12701 
12702  rb_mWaitReadable = rb_define_module_under(rb_cIO, "WaitReadable");
12703  rb_mWaitWritable = rb_define_module_under(rb_cIO, "WaitWritable");
12704  rb_eEAGAINWaitReadable = rb_define_class_under(rb_cIO, "EAGAINWaitReadable", rb_eEAGAIN);
12705  rb_include_module(rb_eEAGAINWaitReadable, rb_mWaitReadable);
12706  rb_eEAGAINWaitWritable = rb_define_class_under(rb_cIO, "EAGAINWaitWritable", rb_eEAGAIN);
12707  rb_include_module(rb_eEAGAINWaitWritable, rb_mWaitWritable);
12708 #if EAGAIN == EWOULDBLOCK
12709  rb_eEWOULDBLOCKWaitReadable = rb_eEAGAINWaitReadable;
12710  /* same as IO::EAGAINWaitReadable */
12711  rb_define_const(rb_cIO, "EWOULDBLOCKWaitReadable", rb_eEAGAINWaitReadable);
12712  rb_eEWOULDBLOCKWaitWritable = rb_eEAGAINWaitWritable;
12713  /* same as IO::EAGAINWaitWritable */
12714  rb_define_const(rb_cIO, "EWOULDBLOCKWaitWritable", rb_eEAGAINWaitWritable);
12715 #else
12716  rb_eEWOULDBLOCKWaitReadable = rb_define_class_under(rb_cIO, "EWOULDBLOCKWaitReadable", rb_eEWOULDBLOCK);
12717  rb_include_module(rb_eEWOULDBLOCKWaitReadable, rb_mWaitReadable);
12718  rb_eEWOULDBLOCKWaitWritable = rb_define_class_under(rb_cIO, "EWOULDBLOCKWaitWritable", rb_eEWOULDBLOCK);
12719  rb_include_module(rb_eEWOULDBLOCKWaitWritable, rb_mWaitWritable);
12720 #endif
12721  rb_eEINPROGRESSWaitReadable = rb_define_class_under(rb_cIO, "EINPROGRESSWaitReadable", rb_eEINPROGRESS);
12722  rb_include_module(rb_eEINPROGRESSWaitReadable, rb_mWaitReadable);
12723  rb_eEINPROGRESSWaitWritable = rb_define_class_under(rb_cIO, "EINPROGRESSWaitWritable", rb_eEINPROGRESS);
12724  rb_include_module(rb_eEINPROGRESSWaitWritable, rb_mWaitWritable);
12725 
12726 #if 0
12727  /* This is necessary only for forcing rdoc handle File::open */
12728  rb_define_singleton_method(rb_cFile, "open", rb_io_s_open, -1);
12729 #endif
12730 
12731  rb_define_alloc_func(rb_cIO, io_alloc);
12732  rb_define_singleton_method(rb_cIO, "new", rb_io_s_new, -1);
12733  rb_define_singleton_method(rb_cIO, "open", rb_io_s_open, -1);
12734  rb_define_singleton_method(rb_cIO, "sysopen", rb_io_s_sysopen, -1);
12735  rb_define_singleton_method(rb_cIO, "for_fd", rb_io_s_for_fd, -1);
12736  rb_define_singleton_method(rb_cIO, "popen", rb_io_s_popen, -1);
12737  rb_define_singleton_method(rb_cIO, "foreach", rb_io_s_foreach, -1);
12738  rb_define_singleton_method(rb_cIO, "readlines", rb_io_s_readlines, -1);
12739  rb_define_singleton_method(rb_cIO, "read", rb_io_s_read, -1);
12740  rb_define_singleton_method(rb_cIO, "binread", rb_io_s_binread, -1);
12741  rb_define_singleton_method(rb_cIO, "write", rb_io_s_write, -1);
12742  rb_define_singleton_method(rb_cIO, "binwrite", rb_io_s_binwrite, -1);
12743  rb_define_singleton_method(rb_cIO, "select", rb_f_select, -1);
12744  rb_define_singleton_method(rb_cIO, "pipe", rb_io_s_pipe, -1);
12745  rb_define_singleton_method(rb_cIO, "try_convert", rb_io_s_try_convert, 1);
12746  rb_define_singleton_method(rb_cIO, "copy_stream", rb_io_s_copy_stream, -1);
12747 
12748  rb_define_method(rb_cIO, "initialize", rb_io_initialize, -1);
12749 
12750  rb_output_fs = Qnil;
12752 
12753  rb_default_rs = rb_fstring_cstr("\n"); /* avoid modifying RS_default */
12755  rb_rs = rb_default_rs;
12756  rb_output_rs = Qnil;
12760 
12762 
12763  rb_define_method(rb_cIO, "initialize_copy", rb_io_init_copy, 1);
12764  rb_define_method(rb_cIO, "reopen", rb_io_reopen, -1);
12765 
12766  rb_define_method(rb_cIO, "print", rb_io_print, -1);
12767  rb_define_method(rb_cIO, "putc", rb_io_putc, 1);
12768  rb_define_method(rb_cIO, "puts", rb_io_puts, -1);
12769  rb_define_method(rb_cIO, "printf", rb_io_printf, -1);
12770 
12771  rb_define_method(rb_cIO, "each", rb_io_each_line, -1);
12772  rb_define_method(rb_cIO, "each_line", rb_io_each_line, -1);
12773  rb_define_method(rb_cIO, "each_byte", rb_io_each_byte, 0);
12774  rb_define_method(rb_cIO, "each_char", rb_io_each_char, 0);
12775  rb_define_method(rb_cIO, "each_codepoint", rb_io_each_codepoint, 0);
12776  rb_define_method(rb_cIO, "lines", rb_io_lines, -1);
12777  rb_define_method(rb_cIO, "bytes", rb_io_bytes, 0);
12778  rb_define_method(rb_cIO, "chars", rb_io_chars, 0);
12779  rb_define_method(rb_cIO, "codepoints", rb_io_codepoints, 0);
12780 
12781  rb_define_method(rb_cIO, "syswrite", rb_io_syswrite, 1);
12782  rb_define_method(rb_cIO, "sysread", rb_io_sysread, -1);
12783 
12784  rb_define_method(rb_cIO, "pread", rb_io_pread, -1);
12785  rb_define_method(rb_cIO, "pwrite", rb_io_pwrite, 2);
12786 
12787  rb_define_method(rb_cIO, "fileno", rb_io_fileno, 0);
12788  rb_define_alias(rb_cIO, "to_i", "fileno");
12789  rb_define_method(rb_cIO, "to_io", rb_io_to_io, 0);
12790 
12791  rb_define_method(rb_cIO, "fsync", rb_io_fsync, 0);
12792  rb_define_method(rb_cIO, "fdatasync", rb_io_fdatasync, 0);
12793  rb_define_method(rb_cIO, "sync", rb_io_sync, 0);
12794  rb_define_method(rb_cIO, "sync=", rb_io_set_sync, 1);
12795 
12796  rb_define_method(rb_cIO, "lineno", rb_io_lineno, 0);
12797  rb_define_method(rb_cIO, "lineno=", rb_io_set_lineno, 1);
12798 
12799  rb_define_method(rb_cIO, "readlines", rb_io_readlines, -1);
12800 
12801  /* for prelude.rb use only: */
12802  rb_define_private_method(rb_cIO, "__read_nonblock", io_read_nonblock, 3);
12803  rb_define_private_method(rb_cIO, "__write_nonblock", io_write_nonblock, 2);
12804 
12805  rb_define_method(rb_cIO, "readpartial", io_readpartial, -1);
12806  rb_define_method(rb_cIO, "read", io_read, -1);
12807  rb_define_method(rb_cIO, "write", io_write_m, 1);
12808  rb_define_method(rb_cIO, "gets", rb_io_gets_m, -1);
12809  rb_define_method(rb_cIO, "readline", rb_io_readline, -1);
12810  rb_define_method(rb_cIO, "getc", rb_io_getc, 0);
12811  rb_define_method(rb_cIO, "getbyte", rb_io_getbyte, 0);
12812  rb_define_method(rb_cIO, "readchar", rb_io_readchar, 0);
12813  rb_define_method(rb_cIO, "readbyte", rb_io_readbyte, 0);
12814  rb_define_method(rb_cIO, "ungetbyte",rb_io_ungetbyte, 1);
12815  rb_define_method(rb_cIO, "ungetc",rb_io_ungetc, 1);
12817  rb_define_method(rb_cIO, "flush", rb_io_flush, 0);
12818  rb_define_method(rb_cIO, "tell", rb_io_tell, 0);
12819  rb_define_method(rb_cIO, "seek", rb_io_seek_m, -1);
12820  /* Set I/O position from the beginning */
12821  rb_define_const(rb_cIO, "SEEK_SET", INT2FIX(SEEK_SET));
12822  /* Set I/O position from the current position */
12823  rb_define_const(rb_cIO, "SEEK_CUR", INT2FIX(SEEK_CUR));
12824  /* Set I/O position from the end */
12825  rb_define_const(rb_cIO, "SEEK_END", INT2FIX(SEEK_END));
12826 #ifdef SEEK_DATA
12827  /* Set I/O position to the next location containing data */
12828  rb_define_const(rb_cIO, "SEEK_DATA", INT2FIX(SEEK_DATA));
12829 #endif
12830 #ifdef SEEK_HOLE
12831  /* Set I/O position to the next hole */
12832  rb_define_const(rb_cIO, "SEEK_HOLE", INT2FIX(SEEK_HOLE));
12833 #endif
12834  rb_define_method(rb_cIO, "rewind", rb_io_rewind, 0);
12835  rb_define_method(rb_cIO, "pos", rb_io_tell, 0);
12836  rb_define_method(rb_cIO, "pos=", rb_io_set_pos, 1);
12837  rb_define_method(rb_cIO, "eof", rb_io_eof, 0);
12838  rb_define_method(rb_cIO, "eof?", rb_io_eof, 0);
12839 
12840  rb_define_method(rb_cIO, "close_on_exec?", rb_io_close_on_exec_p, 0);
12841  rb_define_method(rb_cIO, "close_on_exec=", rb_io_set_close_on_exec, 1);
12842 
12843  rb_define_method(rb_cIO, "close", rb_io_close_m, 0);
12844  rb_define_method(rb_cIO, "closed?", rb_io_closed, 0);
12845  rb_define_method(rb_cIO, "close_read", rb_io_close_read, 0);
12846  rb_define_method(rb_cIO, "close_write", rb_io_close_write, 0);
12847 
12848  rb_define_method(rb_cIO, "isatty", rb_io_isatty, 0);
12849  rb_define_method(rb_cIO, "tty?", rb_io_isatty, 0);
12850  rb_define_method(rb_cIO, "binmode", rb_io_binmode_m, 0);
12851  rb_define_method(rb_cIO, "binmode?", rb_io_binmode_p, 0);
12852  rb_define_method(rb_cIO, "sysseek", rb_io_sysseek, -1);
12853  rb_define_method(rb_cIO, "advise", rb_io_advise, -1);
12854 
12855  rb_define_method(rb_cIO, "ioctl", rb_io_ioctl, -1);
12856  rb_define_method(rb_cIO, "fcntl", rb_io_fcntl, -1);
12857  rb_define_method(rb_cIO, "pid", rb_io_pid, 0);
12858  rb_define_method(rb_cIO, "inspect", rb_io_inspect, 0);
12859 
12860  rb_define_method(rb_cIO, "external_encoding", rb_io_external_encoding, 0);
12861  rb_define_method(rb_cIO, "internal_encoding", rb_io_internal_encoding, 0);
12862  rb_define_method(rb_cIO, "set_encoding", rb_io_set_encoding, -1);
12863 
12864  rb_define_method(rb_cIO, "autoclose?", rb_io_autoclose_p, 0);
12865  rb_define_method(rb_cIO, "autoclose=", rb_io_set_autoclose, 1);
12866 
12867  rb_define_variable("$stdin", &rb_stdin);
12868  rb_stdin = prep_stdio(stdin, FMODE_READABLE, rb_cIO, "<STDIN>");
12869  rb_define_hooked_variable("$stdout", &rb_stdout, 0, stdout_setter);
12870  rb_stdout = prep_stdio(stdout, FMODE_WRITABLE, rb_cIO, "<STDOUT>");
12871  rb_define_hooked_variable("$stderr", &rb_stderr, 0, stdout_setter);
12872  rb_stderr = prep_stdio(stderr, FMODE_WRITABLE|FMODE_SYNC, rb_cIO, "<STDERR>");
12873  rb_define_hooked_variable("$>", &rb_stdout, 0, stdout_setter);
12874  orig_stdout = rb_stdout;
12875  orig_stderr = rb_stderr;
12876 
12877  /* Holds the original stdin */
12878  rb_define_global_const("STDIN", rb_stdin);
12879  /* Holds the original stdout */
12880  rb_define_global_const("STDOUT", rb_stdout);
12881  /* Holds the original stderr */
12882  rb_define_global_const("STDERR", rb_stderr);
12883 
12884 #if 0
12885  /* Hack to get rdoc to regard ARGF as a class: */
12886  rb_cARGF = rb_define_class("ARGF", rb_cObject);
12887 #endif
12888 
12889  rb_cARGF = rb_class_new(rb_cObject);
12890  rb_set_class_path(rb_cARGF, rb_cObject, "ARGF.class");
12891  rb_define_alloc_func(rb_cARGF, argf_alloc);
12892 
12893  rb_include_module(rb_cARGF, rb_mEnumerable);
12894 
12895  rb_define_method(rb_cARGF, "initialize", argf_initialize, -2);
12896  rb_define_method(rb_cARGF, "initialize_copy", argf_initialize_copy, 1);
12897  rb_define_method(rb_cARGF, "to_s", argf_to_s, 0);
12898  rb_define_alias(rb_cARGF, "inspect", "to_s");
12899  rb_define_method(rb_cARGF, "argv", argf_argv, 0);
12900 
12901  rb_define_method(rb_cARGF, "fileno", argf_fileno, 0);
12902  rb_define_method(rb_cARGF, "to_i", argf_fileno, 0);
12903  rb_define_method(rb_cARGF, "to_io", argf_to_io, 0);
12904  rb_define_method(rb_cARGF, "to_write_io", argf_write_io, 0);
12905  rb_define_method(rb_cARGF, "each", argf_each_line, -1);
12906  rb_define_method(rb_cARGF, "each_line", argf_each_line, -1);
12907  rb_define_method(rb_cARGF, "each_byte", argf_each_byte, 0);
12908  rb_define_method(rb_cARGF, "each_char", argf_each_char, 0);
12909  rb_define_method(rb_cARGF, "each_codepoint", argf_each_codepoint, 0);
12910  rb_define_method(rb_cARGF, "lines", argf_lines, -1);
12911  rb_define_method(rb_cARGF, "bytes", argf_bytes, 0);
12912  rb_define_method(rb_cARGF, "chars", argf_chars, 0);
12913  rb_define_method(rb_cARGF, "codepoints", argf_codepoints, 0);
12914 
12915  rb_define_method(rb_cARGF, "read", argf_read, -1);
12916  rb_define_method(rb_cARGF, "readpartial", argf_readpartial, -1);
12917  rb_define_method(rb_cARGF, "read_nonblock", argf_read_nonblock, -1);
12918  rb_define_method(rb_cARGF, "readlines", argf_readlines, -1);
12919  rb_define_method(rb_cARGF, "to_a", argf_readlines, -1);
12920  rb_define_method(rb_cARGF, "gets", argf_gets, -1);
12921  rb_define_method(rb_cARGF, "readline", argf_readline, -1);
12922  rb_define_method(rb_cARGF, "getc", argf_getc, 0);
12923  rb_define_method(rb_cARGF, "getbyte", argf_getbyte, 0);
12924  rb_define_method(rb_cARGF, "readchar", argf_readchar, 0);
12925  rb_define_method(rb_cARGF, "readbyte", argf_readbyte, 0);
12926  rb_define_method(rb_cARGF, "tell", argf_tell, 0);
12927  rb_define_method(rb_cARGF, "seek", argf_seek_m, -1);
12928  rb_define_method(rb_cARGF, "rewind", argf_rewind, 0);
12929  rb_define_method(rb_cARGF, "pos", argf_tell, 0);
12930  rb_define_method(rb_cARGF, "pos=", argf_set_pos, 1);
12931  rb_define_method(rb_cARGF, "eof", argf_eof, 0);
12932  rb_define_method(rb_cARGF, "eof?", argf_eof, 0);
12933  rb_define_method(rb_cARGF, "binmode", argf_binmode_m, 0);
12934  rb_define_method(rb_cARGF, "binmode?", argf_binmode_p, 0);
12935 
12936  rb_define_method(rb_cARGF, "write", argf_write, 1);
12937  rb_define_method(rb_cARGF, "print", rb_io_print, -1);
12938  rb_define_method(rb_cARGF, "putc", rb_io_putc, 1);
12939  rb_define_method(rb_cARGF, "puts", rb_io_puts, -1);
12940  rb_define_method(rb_cARGF, "printf", rb_io_printf, -1);
12941 
12942  rb_define_method(rb_cARGF, "filename", argf_filename, 0);
12943  rb_define_method(rb_cARGF, "path", argf_filename, 0);
12944  rb_define_method(rb_cARGF, "file", argf_file, 0);
12945  rb_define_method(rb_cARGF, "skip", argf_skip, 0);
12946  rb_define_method(rb_cARGF, "close", argf_close_m, 0);
12947  rb_define_method(rb_cARGF, "closed?", argf_closed, 0);
12948 
12949  rb_define_method(rb_cARGF, "lineno", argf_lineno, 0);
12950  rb_define_method(rb_cARGF, "lineno=", argf_set_lineno, 1);
12951 
12952  rb_define_method(rb_cARGF, "inplace_mode", argf_inplace_mode_get, 0);
12953  rb_define_method(rb_cARGF, "inplace_mode=", argf_inplace_mode_set, 1);
12954 
12955  rb_define_method(rb_cARGF, "external_encoding", argf_external_encoding, 0);
12956  rb_define_method(rb_cARGF, "internal_encoding", argf_internal_encoding, 0);
12957  rb_define_method(rb_cARGF, "set_encoding", argf_set_encoding, -1);
12958 
12959  argf = rb_class_new_instance(0, 0, rb_cARGF);
12960 
12961  rb_define_readonly_variable("$<", &argf);
12962  /*
12963  * ARGF is a stream designed for use in scripts that process files given
12964  * as command-line arguments or passed in via STDIN.
12965  *
12966  * See ARGF (the class) for more details.
12967  */
12968  rb_define_global_const("ARGF", argf);
12969 
12970  rb_define_hooked_variable("$.", &argf, argf_lineno_getter, argf_lineno_setter);
12971  rb_define_hooked_variable("$FILENAME", &argf, argf_filename_getter, rb_gvar_readonly_setter);
12972  ARGF.filename = rb_str_new2("-");
12973 
12974  rb_define_hooked_variable("$-i", &argf, opt_i_get, opt_i_set);
12975  rb_define_hooked_variable("$*", &argf, argf_argv_getter, rb_gvar_readonly_setter);
12976 
12977 #if defined (_WIN32) || defined(__CYGWIN__)
12978  atexit(pipe_atexit);
12979 #endif
12980 
12981  Init_File();
12982 
12983  rb_define_method(rb_cFile, "initialize", rb_file_initialize, -1);
12984 
12985  sym_mode = ID2SYM(rb_intern("mode"));
12986  sym_perm = ID2SYM(rb_intern("perm"));
12987  sym_flags = ID2SYM(rb_intern("flags"));
12988  sym_extenc = ID2SYM(rb_intern("external_encoding"));
12989  sym_intenc = ID2SYM(rb_intern("internal_encoding"));
12990  sym_encoding = ID2SYM(rb_id_encoding());
12991  sym_open_args = ID2SYM(rb_intern("open_args"));
12992  sym_textmode = ID2SYM(rb_intern("textmode"));
12993  sym_binmode = ID2SYM(rb_intern("binmode"));
12994  sym_autoclose = ID2SYM(rb_intern("autoclose"));
12995  sym_normal = ID2SYM(rb_intern("normal"));
12996  sym_sequential = ID2SYM(rb_intern("sequential"));
12997  sym_random = ID2SYM(rb_intern("random"));
12998  sym_willneed = ID2SYM(rb_intern("willneed"));
12999  sym_dontneed = ID2SYM(rb_intern("dontneed"));
13000  sym_noreuse = ID2SYM(rb_intern("noreuse"));
13001  sym_SET = ID2SYM(rb_intern("SET"));
13002  sym_CUR = ID2SYM(rb_intern("CUR"));
13003  sym_END = ID2SYM(rb_intern("END"));
13004 #ifdef SEEK_DATA
13005  sym_DATA = ID2SYM(rb_intern("DATA"));
13006 #endif
13007 #ifdef SEEK_HOLE
13008  sym_HOLE = ID2SYM(rb_intern("HOLE"));
13009 #endif
13010  sym_wait_readable = ID2SYM(rb_intern("wait_readable"));
13011  sym_wait_writable = ID2SYM(rb_intern("wait_writable"));
13012 }
#define STRNCASECMP(s1, s2, n)
Definition: ruby.h:2159
#define ioctl_arg
Definition: wait.c:32
void rb_define_global_const(const char *, VALUE)
Definition: variable.c:2702
size_t iov_len
Definition: win32.h:204
struct timeval rb_time_interval(VALUE num)
Definition: time.c:2299
void rb_define_readonly_variable(const char *, const VALUE *)
Definition: variable.c:642
unsigned long ruby_strtoul(const char *str, char **endptr, int base)
Definition: util.c:117
void rb_gc(void)
Definition: gc.c:6727
void rb_fatal(const char *fmt,...)
Definition: error.c:2338
#define WNOHANG
Definition: win32.h:128
VALUE rb_econv_open_exc(const char *senc, const char *denc, int ecflags)
Definition: transcode.c:2033
void rb_execarg_setenv(VALUE execarg_obj, VALUE env)
Definition: process.c:2293
void rb_thread_schedule(void)
Definition: thread.c:1266
const char * rb_econv_asciicompat_encoding(const char *encname)
Definition: transcode.c:1782
int rb_pipe(int *pipes)
Definition: io.c:6009
VALUE rb_io_getbyte(VALUE io)
Definition: io.c:3921
int rb_io_wait_writable(int f)
Definition: io.c:1132
#define MBCLEN_CHARFOUND_P(ret)
Definition: encoding.h:185
void rb_thread_atfork(void)
Definition: thread.c:4186
#define ECONV_NEWLINE_DECORATOR_WRITE_MASK
Definition: encoding.h:395
VALUE rb_protect(VALUE(*proc)(VALUE), VALUE data, int *pstate)
Protects a function call from potential global escapes from the function.
Definition: eval.c:992
VALUE argf
Definition: io.c:11651
void rb_warn(const char *fmt,...)
Definition: error.c:246
void rb_bug(const char *fmt,...)
Definition: error.c:521
#define rb_str_new4
Definition: intern.h:837
rb_econv_result_t
Definition: encoding.h:291
VALUE rb_ary_entry(VALUE ary, long offset)
Definition: array.c:1215
#define MBCLEN_CHARFOUND_LEN(ret)
Definition: encoding.h:186
#define F_SETFD
Definition: win32.h:583
#define RARRAY_LEN(a)
Definition: ruby.h:1019
void rb_syserr_fail(int e, const char *mesg)
Definition: error.c:2391
#define F_DUPFD_CLOEXEC
Definition: win32.h:588
#define FALSE
Definition: nkf.h:174
#define RUBY_TYPED_FREE_IMMEDIATELY
Definition: ruby.h:1138
int ioctl(int, int,...)
Definition: win32.c:2756
#define FMODE_READWRITE
Definition: io.h:104
long rb_str_coderange_scan_restartable(const char *, const char *, rb_encoding *, int *)
Definition: string.c:531
#define SSIZE_MAX
Definition: ruby.h:292
size_t strlen(const char *)
#define INT2NUM(x)
Definition: ruby.h:1538
void rb_readwrite_sys_fail(enum rb_io_wait_readwrite writable, const char *mesg)
Definition: io.c:12447
VALUE rb_cIO
Definition: io.c:143
void rb_io_check_writable(rb_io_t *fptr)
Definition: io.c:848
void * iov_base
Definition: win32.h:203
int rb_io_modestr_fmode(const char *modestr)
Definition: io.c:5143
VALUE rb_stderr
Definition: io.c:156
VALUE rb_file_open_str(VALUE fname, const char *modestr)
Definition: io.c:5910
void rb_define_virtual_variable(const char *, VALUE(*)(ANYARGS), void(*)(ANYARGS))
Definition: variable.c:648
VALUE rb_hash_dup(VALUE hash)
Definition: hash.c:449
void rb_mod_sys_fail_str(VALUE mod, VALUE mesg)
Definition: error.c:2451
VALUE rb_check_to_int(VALUE)
Tries to convert val into Integer.
Definition: object.c:3099
#define NUM2INT(x)
Definition: ruby.h:684
int count
Definition: encoding.c:56
#define ENCINDEX_UTF_16LE
Definition: encindex.h:46
#define NUM2UINT(x)
Definition: ruby.h:685
void rb_str_tmp_frozen_release(VALUE str, VALUE tmp)
Definition: string.c:1183
rb_uid_t getuid(void)
Definition: win32.c:2710
VALUE rb_io_eof(VALUE io)
Definition: io.c:1829
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
Definition: class.c:1716
void rb_syserr_fail_str(int e, VALUE mesg)
Definition: error.c:2397
char * rb_execarg_commandline(const struct rb_execarg *eargp, VALUE *prog)
Definition: process.c:3900
int rb_block_given_p(void)
Determines if the current method is given a block.
Definition: eval.c:835
int rb_cloexec_open(const char *pathname, int flags, mode_t mode)
Definition: io.c:257
int rb_w32_set_nonblock(int)
Definition: win32.c:4374
int ioctl_req_t
Definition: io.c:9175
VALUE fname
Definition: io.c:5668
VALUE rb_f_sprintf(int, const VALUE *)
Definition: sprintf.c:458
#define FilePathValue(v)
Definition: ruby.h:594
VALUE str
Definition: io.c:1224
void rb_io_set_nonblock(rb_io_t *fptr)
Definition: io.c:2475
#define CLASS_OF(v)
Definition: ruby.h:453
VALUE rb_fstring_cstr(const char *str)
Definition: string.c:388
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2284
VALUE rb_str_cat(VALUE, const char *, long)
Definition: string.c:2746
#define PIDT2NUM(v)
Definition: ruby.h:323
void rb_jump_tag(int tag)
Continues the exception caught by rb_protect() and rb_eval_string_protect().
Definition: eval.c:821
#define ARGF_FORWARD(argc, argv)
Definition: io.c:8188
int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *values)
Definition: class.c:1847
struct rb_io_t rb_io_t
rb_fdset_t fdsets[4]
Definition: io.c:8811
#define Qtrue
Definition: ruby.h:437
rb_io_buffer_t cbuf
Definition: io.h:89
VALUE rb_io_binmode(VALUE io)
Definition: io.c:5012
VALUE ecopts
Definition: io.h:85
int rb_execarg_run_options(const struct rb_execarg *e, struct rb_execarg *s, char *errmsg, size_t errmsg_buflen)
Definition: process.c:3021
Definition: io.h:62
#define OBJ_INIT_COPY(obj, orig)
Definition: intern.h:283
#define ENC_CODERANGE_SET(obj, cr)
Definition: encoding.h:106
#define READ_DATA_PENDING_COUNT(fptr)
Definition: io.c:410
VALUE rb_ary_shift(VALUE ary)
Definition: array.c:1019
#define rb_id2str(id)
Definition: vm_backtrace.c:29
char * str_ptr
Definition: io.c:2148
int rb_exec_async_signal_safe(const struct rb_execarg *e, char *errmsg, size_t errmsg_buflen)
Definition: process.c:3150
#define OBJ_FREEZE(x)
Definition: ruby.h:1306
#define ECONV_ERROR_HANDLER_MASK
Definition: encoding.h:386
#define IO_WBUF_CAPA_MIN
Definition: io.c:133
#define F_DUPFD
Definition: win32.h:581
void * rb_thread_call_without_gvl2(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2)
Definition: thread.c:1422
#define FMODE_WRITABLE
Definition: io.h:103
rb_encoding * rb_to_encoding(VALUE enc)
Definition: encoding.c:246
void rb_fd_fix_cloexec(int fd)
Definition: io.c:233
#define FMODE_READABLE
Definition: io.h:102
void rb_econv_close(rb_econv_t *ec)
Definition: transcode.c:1698
VALUE rs
Definition: stringio.c:994
VALUE rb_eEAGAIN
Definition: error.c:52
VALUE rb_str_unlocktmp(VALUE)
Definition: string.c:2610
void rb_define_private_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1527
int argc
Definition: io.c:11649
#define rb_io_pread
Definition: io.c:4951
VALUE rb_enc_from_encoding(rb_encoding *encoding)
Definition: encoding.c:117
SOCKET rb_w32_get_osfhandle(int)
Definition: win32.c:1064
#define O_ACCMODE
Definition: io.c:99
#define UNREACHABLE
Definition: ruby.h:46
VALUE * argv
Definition: io.c:11650
rb_encoding * rb_default_internal_encoding(void)
Definition: encoding.c:1510
VALUE rb_check_convert_type_with_id(VALUE, int, const char *, ID)
Definition: object.c:3022
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:924
VALUE rb_cFile
Definition: file.c:139
void rb_close_before_exec(int lowfd, int maxhint, VALUE noclose_fds)
#define rb_io_fcntl
Definition: io.c:9587
if(len<=MAX_WORD_LENGTH &&len >=MIN_WORD_LENGTH)
Definition: zonetab.h:883
int fcntl(int, int,...)
Definition: win32.c:4297
int rb_stderr_tty_p(void)
Definition: io.c:7602
void rb_p(VALUE obj)
Definition: io.c:7448
VALUE rb_ary_tmp_new(long capa)
Definition: array.c:544
#define free(x)
Definition: io.c:25
#define rb_fd_zero(f)
Definition: intern.h:347
int rb_thread_fd_select(int, rb_fdset_t *, rb_fdset_t *, rb_fdset_t *, struct timeval *)
Definition: thread.c:3789
void ruby_sized_xfree(void *x, size_t size)
Definition: gc.c:8077
rb_pid_t rb_fork_ruby(int *status)
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
Definition: vm_eval.c:774
#define ENCINDEX_UTF_16BE
Definition: encindex.h:45
int8_t binmode
Definition: io.c:186
VALUE rb_str_locktmp_ensure(VALUE str, VALUE(*func)(VALUE), VALUE arg)
Definition: string.c:2620
void rb_str_set_len(VALUE, long)
Definition: string.c:2627
int writeconv_pre_ecflags
Definition: io.h:94
rb_io_t * fptr
Definition: io.c:2150
#define RBASIC_SET_CLASS(obj, cls)
Definition: internal.h:1471
int rb_enc_str_coderange(VALUE)
Definition: string.c:621
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:693
int rb_cloexec_dup2(int oldfd, int newfd)
Definition: io.c:290
#define Check_Type(v, t)
Definition: ruby.h:562
#define SET_BINARY_MODE_WITH_SEEK_CUR(fptr)
Definition: io.c:595
VALUE rb_obj_dup(VALUE)
call-seq: obj.dup -> an_object
Definition: object.c:526
int writeconv_initialized
Definition: io.h:93
#define RSTRING_GETMEM(str, ptrvar, lenvar)
Definition: ruby.h:984
#define FMODE_CREATE
Definition: io.h:110
VALUE rb_enc_associate(VALUE obj, rb_encoding *enc)
Definition: encoding.c:854
VALUE rb_ary_clear(VALUE ary)
Definition: array.c:3501
VALUE rb_exec_recursive(VALUE(*)(VALUE, VALUE, int), VALUE, VALUE)
Definition: thread.c:4709
#define NEED_WRITECONV(fptr)
Definition: io.c:591
long lineno
Definition: io.c:182
#define RB_GC_GUARD(v)
Definition: ruby.h:552
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
#define FMODE_DUPLEX
Definition: io.h:108
VALUE rb_obj_alloc(VALUE)
Allocates an instance of klass.
Definition: object.c:2121
int rb_io_modestr_oflags(const char *modestr)
Definition: io.c:5262
VALUE rb_execarg_new(int argc, const VALUE *argv, int accept_shell)
Definition: process.c:2257
#define ENCODING_MAXNAMELEN
Definition: encoding.h:60
int rb_enc_mbclen(const char *p, const char *e, rb_encoding *enc)
Definition: encoding.c:1008
#define FMODE_BINMODE
Definition: io.h:105
VALUE rb_thread_io_blocking_region(rb_blocking_function_t *func, void *data1, int fd)
Definition: thread.c:1436
void rb_mutex_allow_trap(VALUE self, int val)
Definition: thread_sync.c:511
VALUE io
Definition: io.c:3057
#define FMODE_APPEND
Definition: io.h:109
void rb_include_module(VALUE klass, VALUE module)
Definition: class.c:864
#define MORE_CHAR_FINISHED
Definition: io.c:2252
VALUE rb_block_call(VALUE, ID, int, const VALUE *, rb_block_call_func_t, VALUE)
int rb_notify_fd_close(int fd)
Definition: thread.c:2193
void rb_gc_mark(VALUE ptr)
Definition: gc.c:4464
VALUE rb_hash_lookup(VALUE hash, VALUE key)
Definition: hash.c:853
#define T_ARRAY
Definition: ruby.h:498
off_t copy_length
Definition: io.c:10367
#define KEEPGVL
Definition: io.c:4454
#define RFILE(obj)
Definition: ruby.h:1206
Definition: io.c:179
void rb_define_global_function(const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a global function.
Definition: class.c:1745
time_t tv_sec
Definition: missing.h:54
ID rb_id_encoding(void)
Definition: encoding.c:753
void rb_io_check_initialized(rb_io_t *fptr)
Definition: io.c:633
unsigned int last
Definition: nkf.c:4311
VALUE rb_ensure(VALUE(*b_proc)(ANYARGS), VALUE data1, VALUE(*e_proc)(ANYARGS), VALUE data2)
An equivalent to ensure clause.
Definition: eval.c:1035
void rb_gc_force_recycle(VALUE obj)
Definition: gc.c:6175
VALUE writeconv_pre_ecopts
Definition: io.h:95
#define IOWAIT_SYSCALL
Definition: io.c:10419
#define EINPROGRESS
Definition: win32.h:477
const char * syserr
Definition: io.c:10375
void rb_update_max_fd(int fd)
Definition: io.c:191
#define FIXNUM_P(f)
Definition: ruby.h:365
VALUE rb_inspect(VALUE)
Convenient wrapper of Object::inspect.
Definition: object.c:656
#define SSIZET2NUM(v)
Definition: ruby.h:265
rb_encoding * enc2
Definition: io.h:83
RUBY_FUNC_EXPORTED size_t rb_io_memsize(const rb_io_t *fptr)
Definition: io.c:4439
VALUE rb_stdin
Definition: io.c:156
#define GetOpenFile(obj, fp)
Definition: io.h:120
VALUE envp_str
Definition: internal.h:1529
int argc
Definition: io.c:7463
VALUE rb_rescue2(VALUE(*b_proc)(ANYARGS), VALUE data1, VALUE(*r_proc)(ANYARGS), VALUE data2,...)
An equivalent of rescue clause.
Definition: eval.c:895
unsigned int chomp
Definition: stringio.c:996
VALUE rb_io_ascii8bit_binmode(VALUE io)
Definition: io.c:5058
#define io_tell(fptr)
Definition: io.c:787
const char * ptr
Definition: io.c:1225
VALUE argv
Definition: io.c:183
VALUE rb_mutex_new(void)
Definition: thread_sync.c:161
#define ENC_CODERANGE_7BIT
Definition: encoding.h:100
#define rb_ary_new2
Definition: intern.h:90
#define GetWriteIO(io)
Definition: io.c:407
const char term
Definition: id.c:37
RUBY_EXTERN void * memmove(void *, const void *, size_t)
Definition: memmove.c:7
int rb_gc_for_fd(int err)
Definition: io.c:878
long last_lineno
Definition: io.c:181
#define rb_fd_set(n, f)
Definition: intern.h:348
int rb_io_extract_encoding_option(VALUE opt, rb_encoding **enc_p, rb_encoding **enc2_p, int *fmode_p)
Definition: io.c:5407
VALUE rb_eArgError
Definition: error.c:802
#define sym(x)
Definition: date_core.c:3721
VALUE rb_io_write(VALUE io, VALUE str)
Definition: io.c:1510
VALUE rb_str_buf_cat(VALUE, const char *, long)
rb_io_t * rb_io_make_open_file(VALUE obj)
Definition: io.c:7724
int mode
Definition: io.h:65
#define NEWOBJ_OF(obj, type, klass, flags)
Definition: ruby.h:754
#define rb_fd_isset(n, f)
Definition: intern.h:350
#define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)
Definition: ruby.h:1851
VALUE rb_io_gets_internal(VALUE io)
Definition: io.c:3287
#define SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags)
Definition: io.c:594
#define rb_io_set_close_on_exec
Definition: io.c:4181
VALUE rb_io_close(VALUE io)
Definition: io.c:4501
VALUE rb_io_flush_raw(VALUE io, int sync)
Definition: io.c:1553
VALUE rb_obj_class(VALUE)
call-seq: obj.class -> class
Definition: object.c:277
#define RB_TYPE_P(obj, type)
Definition: ruby.h:527
#define fmode
VALUE current_file
Definition: io.c:180
int rb_thread_fd_writable(int)
Definition: thread.c:3782
VALUE rb_econv_make_exception(rb_econv_t *ec)
Definition: transcode.c:4225
#define O_CLOEXEC
#define MEMZERO(p, type, n)
Definition: ruby.h:1660
void rb_econv_check_error(rb_econv_t *ec)
Definition: transcode.c:4231
rb_encoding * enc
Definition: io.h:82
VALUE rb_lastline_get(void)
Definition: vm.c:1241
int rb_to_encoding_index(VALUE enc)
Definition: encoding.c:198
rb_encoding * rb_default_external_encoding(void)
Definition: encoding.c:1425
void rb_str_setter(VALUE, ID, VALUE *)
Definition: string.c:9469
void rb_maygvl_fd_fix_cloexec(int fd)
Definition: io.c:210
void rb_thread_sleep(int)
Definition: thread.c:1243
fd_set rb_fdset_t
Definition: intern.h:346
off_t src_offset
Definition: io.c:10368
#define rb_fd_term(f)
Definition: intern.h:357
struct rb_execarg * rb_execarg_get(VALUE execarg_obj)
Definition: process.c:2268
#define ECONV_NEWLINE_DECORATOR_READ_MASK
Definition: encoding.h:394
long len
Definition: io.c:2149
VALUE rb_class_name(VALUE)
Definition: variable.c:444
VALUE rb_str_chomp_string(VALUE str, VALUE chomp)
Definition: string.c:8342
#define ALLOC_N(type, n)
Definition: ruby.h:1587
const void * buf
Definition: io.c:928
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
Definition: hash.c:1616
void rb_io_unbuffered(rb_io_t *fptr)
Definition: io.c:6003
VALUE rb_convert_type_with_id(VALUE, int, const char *, ID)
Definition: object.c:2979
void rb_write_error2(const char *mesg, long len)
Definition: io.c:7560
void Init_File(void)
Definition: file.c:6081
VALUE rb_str_encode_ospath(VALUE path)
Definition: file.c:232
#define F_SETFL
Definition: win32.h:587
VALUE rb_str_substr(VALUE, long, long)
Definition: string.c:2517
int nosync
Definition: io.c:1232
#define val
long tv_usec
Definition: missing.h:55
VALUE rb_stdout
Definition: io.c:156
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:1893
#define PREP_STDIO_NAME(f)
Definition: io.c:4186
#define FMODE_SETENC_BY_BOM
Definition: io.h:115
#define MBCLEN_NEEDMORE_P(ret)
Definition: encoding.h:188
#define RSTRING_END(str)
Definition: ruby.h:979
FILE * rb_io_stdio_file(rb_io_t *fptr)
Definition: io.c:7676
int rb_io_oflags_fmode(int oflags)
Definition: io.c:5192
VALUE rb_str_cat2(VALUE, const char *)
VALUE rb_obj_as_string(VALUE)
Definition: string.c:1410
#define ECONV_STATEFUL_DECORATOR_MASK
Definition: encoding.h:401
VALUE rb_ary_new(void)
Definition: array.c:499
#define dp(v)
Definition: vm_debug.h:21
rb_econv_t * rb_econv_open_opts(const char *source_encoding, const char *destination_encoding, int ecflags, VALUE ecopts)
Definition: transcode.c:2575
#define UINT2NUM(x)
Definition: ruby.h:1539
VALUE rb_io_get_write_io(VALUE io)
Definition: io.c:670
VALUE rb_io_print(int argc, const VALUE *argv, VALUE out)
Definition: io.c:7227
VALUE rb_execarg_extract_options(VALUE execarg_obj, VALUE opthash)
Definition: process.c:1928
#define ARGF_GENERIC_INPUT_P()
Definition: io.c:8186
#define ECONV_PARTIAL_INPUT
Definition: encoding.h:409
struct rb_execarg::@81::@83 cmd
VALUE rb_io_ungetbyte(VALUE io, VALUE b)
Definition: io.c:3982
VALUE rb_any_to_s(VALUE)
call-seq: obj.to_s -> string
Definition: object.c:631
#define ECONV_AFTER_OUTPUT
Definition: encoding.h:410
long limit
Definition: stringio.c:995
RUBY_EXTERN VALUE rb_mKernel
Definition: ruby.h:1881
VALUE rb_thread_current(void)
Definition: thread.c:2494
VALUE rb_check_to_integer(VALUE, const char *)
Tries to convert val into Integer.
Definition: object.c:3062
int rb_cloexec_fcntl_dupfd(int fd, int minfd)
Definition: io.c:362
#define NIL_P(v)
Definition: ruby.h:451
#define ISASCII(c)
Definition: ruby.h:2142
VALUE rb_io_flush(VALUE io)
Definition: io.c:1592
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:646
const char * ruby_get_inplace_mode(void)
Definition: io.c:12375
int chown(const char *, int, int)
Definition: win32.c:4757
#define ECONV_DEFAULT_NEWLINE_DECORATOR
Definition: encoding.h:403
int fd
Definition: io.h:64
VALUE rb_mutex_synchronize(VALUE mutex, VALUE(*func)(VALUE arg), VALUE arg)
Definition: thread_sync.c:488
#define MODE_BINARY(a, b)
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)
void rb_define_const(VALUE, const char *, VALUE)
Definition: variable.c:2691
int rb_io_wait_readable(int f)
Definition: io.c:1106
int8_t next_p
Definition: io.c:186
rb_atomic_t cnt[RUBY_NSIG]
Definition: signal.c:525
VALUE rb_io_check_io(VALUE io)
Definition: io.c:664
void rb_lastline_set(VALUE)
Definition: vm.c:1247
VALUE str
Definition: io.c:1231
#define MBCLEN_NEEDMORE_LEN(ret)
Definition: encoding.h:189
#define rb_io_fdatasync
Definition: io.c:1985
struct rb_io_t::rb_io_enc_t encs
void Init_IO(void)
Definition: io.c:12652
void rb_notimplement(void)
Definition: error.c:2330
#define NUM2IOCTLREQ(num)
Definition: io.c:9176
int argc
Definition: ruby.c:187
struct rb_execarg::@81::@82 sh
#define READ_DATA_PENDING(fptr)
Definition: io.c:409
VALUE writeconv_asciicompat
Definition: io.h:92
#define FMODE_TRUNC
Definition: io.h:112
#define Qfalse
Definition: ruby.h:436
const char * notimp
Definition: io.c:10377
rb_pid_t pid
Definition: io.h:66
#define T_BIGNUM
Definition: ruby.h:501
#define LONG_MAX
Definition: ruby.h:189
#define NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr)
Definition: io.c:593
void rb_gc_register_mark_object(VALUE obj)
Definition: gc.c:6227
#define rb_io_ioctl
Definition: io.c:9493
VALUE rb_io_get_io(VALUE io)
Definition: io.c:658
#define RUBY_FUNC_EXPORTED
Definition: defines.h:263
union rb_execarg::@81 invoke
#define ENC_CODERANGE_BROKEN
Definition: encoding.h:102
#define rb_ary_new4
Definition: intern.h:92
#define rb_str_new2
Definition: intern.h:835
#define ARGF
Definition: io.c:405
int err
Definition: win32.c:135
#define rb_enc_codepoint(p, e, enc)
Definition: encoding.h:201
#define argf_of(obj)
Definition: io.c:404
#define rb_enc_mbminlen(enc)
Definition: encoding.h:174
Definition: io.c:1229
rb_io_wait_readwrite
Definition: ruby.h:1817
VALUE rb_io_gets(VALUE io)
Definition: io.c:3281
int rb_cloexec_dup(int oldfd)
Definition: io.c:283
#define F_GETFD
Definition: win32.h:582
VALUE * argv
Definition: io.c:7464
#define rb_f_syscall
Definition: io.c:9717
void * rb_thread_call_without_gvl(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2)
#define ENC_CODERANGE_VALID
Definition: encoding.h:101
#define ATOMIC_CAS(var, oldval, newval)
Definition: ruby_atomic.h:132
#define numberof(array)
Definition: etc.c:618
#define ALLOC(type)
Definition: ruby.h:1588
#define EOF
Definition: vsnprintf.c:203
#define ONIGENC_CONSTRUCT_MBCLEN_CHARFOUND(n)
Definition: onigmo.h:345
VALUE read
Definition: io.c:8809
VALUE rb_str_resize(VALUE, long)
Definition: string.c:2644
void rb_sys_fail(const char *mesg)
Definition: error.c:2403
#define DEFAULT_TEXTMODE
Definition: io.c:589
#define NUM2OFFT(x)
Definition: ruby.h:730
#define IO_CBUF_CAPA_MIN
Definition: io.c:131
rb_encoding * rb_find_encoding(VALUE enc)
Definition: encoding.c:253
int rb_enc_ascget(const char *p, const char *e, int *len, rb_encoding *enc)
Definition: encoding.c:1032
#define NEXT_ARGF_FORWARD(argc, argv)
Definition: io.c:8192
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
Definition: class.c:1758
int rb_cloexec_pipe(int fildes[2])
Definition: io.c:325
#define ZALLOC(type)
Definition: ruby.h:1590
#define RSTRING_LEN(str)
Definition: ruby.h:971
VALUE rb_get_argv(void)
Definition: io.c:12413
VALUE rb_yield(VALUE)
Definition: vm_eval.c:973
void ruby_set_inplace_mode(const char *suffix)
Definition: io.c:12381
rb_io_buffer_t wbuf
Definition: io.h:71
#define RARRAY_CONST_PTR(a)
Definition: ruby.h:1021
VALUE rb_io_puts(int argc, const VALUE *argv, VALUE out)
Definition: io.c:7399
int errno
#define TRUE
Definition: nkf.h:175
VALUE rb_obj_freeze(VALUE)
call-seq: obj.freeze -> obj
Definition: object.c:1331
#define off_t
Definition: io.c:61
#define S_ISREG(m)
Definition: io.c:917
void rb_last_status_clear(void)
Definition: process.c:494
VALUE rb_mEnumerable
Definition: enum.c:19
VALUE rb_sprintf(const char *format,...)
Definition: sprintf.c:1452
rb_io_t * fptr
Definition: io.c:1223
#define id_exception
Definition: io.c:166
void rb_execarg_parent_start(VALUE execarg_obj)
Definition: process.c:2457
int rb_enc_precise_mbclen(const char *p, const char *e, rb_encoding *enc)
Definition: encoding.c:1020
#define IO_RBUF_CAPA_FOR(fptr)
Definition: io.c:132
void rb_gvar_readonly_setter(VALUE v, ID id, void *d, struct rb_global_variable *g)
Definition: variable.c:572
#define NEED_READCONV(fptr)
Definition: io.c:590
#define rb_enc_name(enc)
Definition: encoding.h:171
void rb_last_status_set(int status, rb_pid_t pid)
Definition: process.c:485
struct rb_io_enc_t encs
Definition: io.c:185
#define MEMMOVE(p1, p2, type, n)
Definition: ruby.h:1662
VALUE rb_hash_new(void)
Definition: hash.c:424
#define NUM2CHR(x)
Definition: ruby.h:1575
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1908
void rb_write_error_str(VALUE mesg)
Definition: io.c:7580
void rb_str_modify_expand(VALUE, long)
Definition: string.c:2054
void rb_thread_execute_interrupts(VALUE th)
Definition: thread.c:2107
VALUE rb_ivar_set(VALUE, ID, VALUE)
Definition: variable.c:1315
Definition: ruby.h:1063
VALUE rb_check_hash_type(VALUE hash)
Definition: hash.c:722
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:4309
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Definition: array.c:639
#define PRIsVALUE
Definition: ruby.h:135
unsigned long ID
Definition: ruby.h:86
void rb_thread_wait_fd(int)
Definition: thread.c:3776
rb_encoding * rb_usascii_encoding(void)
Definition: encoding.c:1335
VALUE tied_io_for_writing
Definition: io.h:73
#define RUBY_METHOD_FUNC(func)
Definition: ruby.h:1708
#define Qnil
Definition: ruby.h:438
int8_t init_p
Definition: io.c:186
#define FMODE_TEXTMODE
Definition: io.h:113
void rb_exc_raise(VALUE mesg)
Raises an exception in the current thread.
Definition: eval.c:615
VALUE rb_enc_uint_chr(unsigned int code, rb_encoding *enc)
Definition: numeric.c:3283
VALUE rb_io_printf(int argc, const VALUE *argv, VALUE out)
Definition: io.c:7166
#define EWOULDBLOCK
Definition: io.c:115
#define mode_t
Definition: win32.h:119
VALUE rb_eStandardError
Definition: error.c:799
void rb_readwrite_syserr_fail(enum rb_io_wait_readwrite writable, int n, const char *mesg)
Definition: io.c:12453
size_t rb_econv_memsize(rb_econv_t *)
Definition: transcode.c:1716
unsigned long VALUE
Definition: ruby.h:85
#define IS_PREP_STDIO(f)
Definition: io.c:4185
#define OBJ_TAINTED(x)
Definition: ruby.h:1296
VALUE rb_gets(void)
Definition: io.c:8504
VALUE rb_eSystemCallError
Definition: error.c:819
VALUE rb_eNotImpError
Definition: error.c:811
char * strchr(char *, char)
int intptr_t
Definition: win32.h:90
#define NEED_NEWLINE_DECORATOR_ON_WRITE(fptr)
Definition: io.c:450
VALUE rb_eTypeError
Definition: error.c:801
char * str_ptr
Definition: io.c:2502
int rb_utf8_encindex(void)
Definition: encoding.c:1329
#define FIX2INT(x)
Definition: ruby.h:686
Definition: win32.h:202
#define ECONV_NEWLINE_DECORATOR_MASK
Definition: encoding.h:393
int rb_wait_for_single_fd(int fd, int events, struct timeval *tv)
Definition: thread.c:3989
VALUE rb_rs
Definition: io.c:160
VALUE inplace
Definition: io.c:184
void rb_io_synchronized(rb_io_t *fptr)
Definition: io.c:5996
VALUE rb_check_funcall(VALUE, ID, int, const VALUE *)
Definition: vm_eval.c:389
rb_fdset_t fds
Definition: io.c:10378
#define rb_enc_asciicompat(enc)
Definition: encoding.h:239
VALUE rb_str_new_cstr(const char *)
Definition: string.c:771
int memcmp(const void *s1, const void *s2, size_t len)
Definition: memcmp.c:7
VALUE rb_uninterruptible(VALUE(*b_proc)(ANYARGS), VALUE data)
Definition: thread.c:5128
VALUE rb_str_dup(VALUE)
Definition: string.c:1488
struct rb_io_buffer_t rb_io_buffer_t
Definition: io.h:60
int rb_reserved_fd_p(int fd)
void rb_define_hooked_variable(const char *, VALUE *, VALUE(*)(ANYARGS), void(*)(ANYARGS))
Definition: variable.c:617
#define rb_funcallv
Definition: console.c:21
#define READ_DATA_BUFFERED(fptr)
Definition: io.c:412
#define rb_io_close_on_exec_p
Definition: io.c:4123
int rb_respond_to(VALUE, ID)
Definition: vm_method.c:1994
struct timeval * timeout
Definition: io.c:8810
int rb_thread_to_be_killed(VALUE thread)
Definition: thread.c:2302
register unsigned int len
Definition: zonetab.h:51
VALUE rb_define_module_under(VALUE outer, const char *name)
Definition: class.c:790
#define StringValueCStr(v)
Definition: ruby.h:571
rb_econv_t * readconv
Definition: io.h:88
int rb_str_end_with_asciichar(VALUE str, int c)
Definition: io.c:7337
#define shutdown(a, b)
Definition: io.c:599
#define rb_fd_max(f)
Definition: intern.h:358
#define SEEK_END
Definition: io.c:792
void rb_iter_break_value(VALUE val)
Definition: vm.c:1497
#define recur(fmt)
#define rb_io_pwrite
Definition: io.c:5008
int argc
Definition: io.c:9959
int rb_econv_putbackable(rb_econv_t *ec)
Definition: transcode.c:1738
#define RSTRING_PTR(str)
Definition: ruby.h:975
VALUE write_lock
Definition: io.h:97
#define rb_exc_new3
Definition: intern.h:244
void rb_str_modify(VALUE)
Definition: string.c:2046
#define ENCODING_GET(obj)
Definition: encoding.h:58
rb_encoding * rb_enc_get(VALUE obj)
Definition: encoding.c:860
VALUE io
Definition: io.c:1230
void rb_insecure_operation(void)
Definition: safe.c:104
int size
Definition: encoding.c:57
VALUE rb_yield_values2(int n, const VALUE *argv)
Definition: vm_eval.c:1007
#define f
int rb_freopen(VALUE fname, const char *mode, FILE *file)
Definition: file.c:674
VALUE rb_hash_lookup2(VALUE hash, VALUE key, VALUE def)
Definition: hash.c:842
#define INT2FIX(i)
Definition: ruby.h:232
#define MBCLEN_INVALID_P(ret)
Definition: encoding.h:187
int rb_safe_level(void)
Definition: safe.c:35
#define RARRAY_AREF(a, i)
Definition: ruby.h:1033
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:1442
int rb_io_fptr_finalize(rb_io_t *fptr)
Definition: io.c:4424
VALUE rb_mWaitReadable
Definition: io.c:146
VALUE rb_eEINPROGRESS
Definition: error.c:54
VALUE io
Definition: io.c:9961
VALUE rb_io_fdopen(int fd, int oflags, const char *path)
Definition: io.c:7648
VALUE rb_str_buf_cat_ascii(VALUE, const char *)
Definition: string.c:2860
VALUE rb_eIOError
Definition: io.c:145
#define rb_intern(str)
#define ANYARGS
Definition: defines.h:173
#define NUM2SIZET(x)
Definition: ruby.h:738
VALUE rb_eRuntimeError
Definition: error.c:800
VALUE rb_check_array_type(VALUE ary)
Definition: array.c:651
RUBY_SYMBOL_EXPORT_BEGIN void * rb_thread_call_with_gvl(void *(*func)(void *), void *data1)
Definition: thread.c:1501
VALUE rb_hash_aref(VALUE hash, VALUE key)
Definition: hash.c:831
void rb_error_arity(int argc, int min, int max)
ID rb_frame_this_func(void)
The original name of the current method.
Definition: eval.c:1103
#define FD_CLOEXEC
Definition: win32.h:589
#define rb_fd_select(n, rfds, wfds, efds, timeout)
Definition: intern.h:359
VALUE rb_str_catf(VALUE str, const char *format,...)
Definition: sprintf.c:1492
VALUE rb_enumeratorize(VALUE obj, VALUE meth, int argc, const VALUE *argv)
Definition: enumerator.c:450
long rb_w32_write_console(uintptr_t, int)
Definition: win32.c:7237
VALUE rb_check_string_type(VALUE)
Definition: string.c:2246
#define is_socket(fd, path)
Definition: io.c:605
#define rb_funcall3
Definition: ruby.h:1792
RUBY_EXTERN char * strerror(int)
Definition: strerror.c:11
#define LONG2FIX(i)
Definition: ruby.h:234
VALUE rb_eEWOULDBLOCK
Definition: error.c:53
VALUE pathv
Definition: io.h:68
#define O_NONBLOCK
Definition: win32.h:590
#define ARGVSTR2ARGV(argv_str)
Definition: internal.h:1564
#define RTEST(v)
Definition: ruby.h:450
void rb_thread_check_ints(void)
Definition: thread.c:1219
void rb_warning(const char *fmt,...)
Definition: error.c:267
#define T_STRING
Definition: ruby.h:496
VALUE rb_eEOFError
Definition: io.c:144
VALUE rb_str_locktmp(VALUE)
VALUE offset
Definition: io.c:10116
VALUE rb_class_new_instance(int, const VALUE *, VALUE)
Allocates and initializes an instance of klass.
Definition: object.c:2170
struct rb_encoding_entry * list
Definition: encoding.c:55
size_t rb_str_capacity(VALUE str)
Definition: string.c:675
int flock(int, int)
Definition: flock.c:125
#define OBJ_INFECT(x, s)
Definition: ruby.h:1302
int rb_method_basic_definition_p(VALUE, ID)
Definition: vm_method.c:1879
void rb_define_variable(const char *, VALUE *)
Definition: variable.c:636
#define READ_CHECK(fptr)
Definition: io.c:425
#define T_FILE
Definition: ruby.h:502
#define fsync
Definition: win32.h:193
void rb_io_check_readable(rb_io_t *fptr)
Definition: io.c:824
FILE * rb_fdopen(int fd, const char *modestr)
Definition: io.c:5716
void(* finalize)(struct rb_io_t *, int)
Definition: io.h:69
#define TypedData_Make_Struct(klass, type, data_type, sval)
Definition: ruby.h:1175
#define rb_enc_left_char_head(s, p, e, enc)
Definition: encoding.h:216
VALUE rb_ary_concat(VALUE x, VALUE y)
Definition: array.c:3703
long length
Definition: io.c:1226
#define RETURN_ENUMERATOR(obj, argc, argv)
Definition: intern.h:238
rb_io_t * fptr
Definition: io.c:4252
#define SafeStringValue(v)
Definition: ruby.h:574
void rb_enc_warn(rb_encoding *enc, const char *fmt,...)
Definition: error.c:256
int rb_atomic_t
Definition: ruby_atomic.h:120
#define FOREACH_ARGF()
Definition: io.c:11912
#define FMODE_PREP
Definition: io.c:4184
VALUE rb_enc_str_new(const char *, long, rb_encoding *)
Definition: string.c:759
#define rb_sys_fail_path(path)
Definition: internal.h:1216
#define OFFT2NUM(v)
Definition: ruby.h:254
VALUE rb_io_addstr(VALUE io, VALUE str)
Definition: io.c:1532
int oflags
Definition: io.c:5669
void rb_set_class_path(VALUE, VALUE, const char *)
Definition: variable.c:367
int rb_thread_interrupted(VALUE thval)
Definition: thread.c:1237
VALUE rb_io_taint_check(VALUE io)
Definition: io.c:626
const char * name
Definition: nkf.c:208
int rb_execarg_addopt(VALUE execarg_obj, VALUE key, VALUE val)
Definition: process.c:1669
#define ID2SYM(x)
Definition: ruby.h:383
#define NUM2MODET(v)
Definition: ruby.h:341
#define READ_CHAR_PENDING_PTR(fptr)
Definition: io.c:416
#define FMODE_SYNC
Definition: io.h:106
#define FMODE_TTY
Definition: io.h:107
#define MakeOpenFile(obj, fp)
Definition: io.h:122
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:915
#define SHUT_WR
#define SHUT_RD
VALUE rb_default_rs
Definition: io.c:162
#define MORE_CHAR_SUSPENDED
Definition: io.c:2251
RUBY_EXTERN int dup2(int, int)
Definition: dup2.c:27
VALUE rb_str_new_frozen(VALUE)
Definition: string.c:1158
rb_io_buffer_t rbuf
Definition: io.h:71
#define rb_fd_init(f)
Definition: intern.h:355
struct rb_io_enc_t convconfig_t
Definition: io.c:5475
unsigned use_shell
Definition: internal.h:1532
rb_encoding * rb_ascii8bit_encoding(void)
Definition: encoding.c:1305
#define FIX2UINT(x)
Definition: ruby.h:687
int rb_enc_find_index(const char *name)
Definition: encoding.c:704
#define rb_syserr_fail_path(err, path)
Definition: internal.h:1217
#define rb_io_fsync
Definition: io.c:1933
#define fileno(p)
Definition: vsnprintf.c:219
int rb_io_read_pending(rb_io_t *fptr)
Definition: io.c:860
#define rb_check_frozen(obj)
Definition: intern.h:271
#define NEED_NEWLINE_DECORATOR_ON_READ(fptr)
Definition: io.c:449
#define CONST_ID(var, str)
Definition: ruby.h:1743
FILE * stdio_file
Definition: io.h:63
ssize_t rb_io_bufread(VALUE io, void *buf, size_t size)
Definition: io.c:2178
VALUE rb_str_tmp_frozen_acquire(VALUE str)
Definition: string.c:1170
#define RUBY_TYPED_DEFAULT_FREE
Definition: ruby.h:1134
#define MODE_BTMODE(a, b, c)
Definition: io.c:1365
#define rb_intern_const(str)
Definition: ruby.h:1777
VALUE filename
Definition: io.c:180
void rb_execarg_parent_end(VALUE execarg_obj)
Definition: process.c:2496
VALUE rb_str_encode(VALUE str, VALUE to, int ecflags, VALUE ecopts)
Definition: transcode.c:2884
char rb_w32_fd_is_text(int)
Definition: win32.c:7690
#define io_seek(fptr, ofs, whence)
Definition: io.c:786
#define RB_WAITFD_IN
Definition: io.h:47
int fchmod(int fd, int mode)
Definition: win32.c:7572
VALUE write
Definition: io.c:8809
VALUE rb_output_rs
Definition: io.c:161
VALUE * argv
Definition: io.c:9960
#define READ_CHAR_PENDING_COUNT(fptr)
Definition: io.c:415
void rb_stdio_set_default_encoding(void)
Definition: io.c:11284
int lineno
Definition: io.h:67
VALUE rb_str_buf_new(long)
Definition: string.c:1282
VALUE rb_usascii_str_new(const char *, long)
Definition: string.c:743
VALUE rb_mWaitWritable
Definition: io.c:147
void rb_io_read_check(rb_io_t *fptr)
Definition: io.c:869
#define fstat(fd, st)
Definition: win32.h:184
#define SYMBOL_P(x)
Definition: ruby.h:382
#define stat(path, st)
Definition: win32.h:183
VALUE except
Definition: io.c:8809
#define RB_INTEGER_TYPE_P(obj)
Definition: ruby_missing.h:15
#define rb_io_sync
Definition: io.c:1934
#define DEFULT_IOCTL_NARG_LEN
Definition: io.c:9210
#define env
mode_t perm
Definition: io.c:5670
ssize_t rb_io_bufwrite(VALUE io, const void *buf, size_t size)
Definition: io.c:1450
#define NULL
Definition: _sdbm.c:102
#define FIX2LONG(x)
Definition: ruby.h:363
#define Qundef
Definition: ruby.h:439
#define READ_CHAR_PENDING(fptr)
Definition: io.c:414
#define READ_DATA_PENDING_PTR(fptr)
Definition: io.c:411
void rb_sys_fail_str(VALUE mesg)
Definition: error.c:2409
#define OBJ_TAINT(x)
Definition: ruby.h:1298
rb_pid_t rb_waitpid(rb_pid_t pid, int *status, int flags)
Definition: process.c:902
VALUE rb_class_new(VALUE super)
Creates a new class.
Definition: class.c:242
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1515
#define ruby_verbose
Definition: ruby.h:1813
VALUE rb_str_append(VALUE, VALUE)
Definition: string.c:2900
VALUE rb_file_open(const char *fname, const char *modestr)
Definition: io.c:5917
#define ENCINDEX_UTF_32LE
Definition: encindex.h:48
#define NOFILE
Definition: io.c:75
rb_io_t * fptr
Definition: io.c:9798
void rb_io_check_byte_readable(rb_io_t *fptr)
Definition: io.c:815
void rb_io_check_char_readable(rb_io_t *fptr)
Definition: io.c:796
#define next_argv()
Definition: io.c:8185
int rb_econv_prepare_options(VALUE opthash, VALUE *ecopts, int ecflags)
Definition: transcode.c:2524
void rb_econv_binmode(rb_econv_t *ec)
Definition: transcode.c:1939
#define ENCINDEX_UTF_32BE
Definition: encindex.h:47
#define SEEK_SET
Definition: io.c:790
#define ECONV_UNIVERSAL_NEWLINE_DECORATOR
Definition: encoding.h:396
#define O_BINARY
Definition: _sdbm.c:88
int mode
Definition: io.c:10117
#define NUM2LONG(x)
Definition: ruby.h:648
#define MAX_REALLOC_GAP
Definition: io.c:2387
VALUE rb_io_set_write_io(VALUE io, VALUE w)
Definition: io.c:681
VALUE rb_io_ungetc(VALUE io, VALUE c)
Definition: io.c:4017
VALUE rb_output_fs
Definition: io.c:159
VALUE rb_mutex_owned_p(VALUE self)
Definition: thread_sync.c:306
VALUE rb_to_int(VALUE)
Converts val into Integer.
Definition: object.c:3084
void rb_econv_putback(rb_econv_t *ec, unsigned char *p, int n)
Definition: transcode.c:1749
void rb_io_check_closed(rb_io_t *fptr)
Definition: io.c:641
VALUE rb_attr_get(VALUE, ID)
Definition: variable.c:1224
#define SEEK_CUR
Definition: io.c:791
#define SET_BINARY_MODE(fptr)
Definition: io.c:592
char * strrchr(const char *, const char)
VALUE rb_econv_str_convert(rb_econv_t *ec, VALUE src, int flags)
Definition: transcode.c:1874
VALUE io
Definition: io.c:10115
#define StringValue(v)
Definition: ruby.h:569
rb_econv_t * writeconv
Definition: io.h:91
void rb_write_error(const char *mesg)
Definition: io.c:7574
Definition: io.c:10114
#define RUBY_UBF_IO
Definition: intern.h:877
rb_encoding * rb_enc_from_index(int index)
Definition: encoding.c:616
VALUE rb_str_new(const char *, long)
Definition: string.c:737
#define SIGNED_VALUE
Definition: ruby.h:87
void rb_eof_error(void)
Definition: io.c:620