Ruby  2.7.1p83(2020-03-31revisiona0c7c23c9cec0d0ffcba012279cd652d28ad5bf3)
io.c
Go to the documentation of this file.
1 /**********************************************************************
2 
3  io.c -
4 
5  $Author$
6  created at: Fri Oct 15 18:08:59 JST 1993
7 
8  Copyright (C) 1993-2007 Yukihiro Matsumoto
9  Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
10  Copyright (C) 2000 Information-technology Promotion Agency, Japan
11 
12 **********************************************************************/
13 
14 #include "ruby/encoding.h"
15 #include "ruby/io.h"
16 #include "ruby/thread.h"
17 #include "internal.h"
18 #include "dln.h"
19 #include "encindex.h"
20 #include "id.h"
21 #include <ctype.h>
22 #include <errno.h>
23 #include "ruby_atomic.h"
24 #include "ccan/list/list.h"
25 
26 /* non-Linux poll may not work on all FDs */
27 #if defined(HAVE_POLL)
28 # if defined(__linux__)
29 # define USE_POLL 1
30 # endif
31 # if defined(__FreeBSD_version) && __FreeBSD_version >= 1100000
32 # define USE_POLL 1
33 # endif
34 #endif
35 
36 #ifndef USE_POLL
37 # define USE_POLL 0
38 #endif
39 
40 #if !USE_POLL
41 # include "vm_core.h"
42 #endif
43 
44 #include "builtin.h"
45 
46 #undef free
47 #define free(x) xfree(x)
48 
49 #if defined(DOSISH) || defined(__CYGWIN__)
50 #include <io.h>
51 #endif
52 
53 #include <sys/types.h>
54 #if defined HAVE_NET_SOCKET_H
55 # include <net/socket.h>
56 #elif defined HAVE_SYS_SOCKET_H
57 # include <sys/socket.h>
58 #endif
59 
60 #if defined(__BOW__) || defined(__CYGWIN__) || defined(_WIN32)
61 # define NO_SAFE_RENAME
62 #endif
63 
64 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__sun) || defined(_nec_ews)
65 # define USE_SETVBUF
66 #endif
67 
68 #ifdef __QNXNTO__
69 #include <unix.h>
70 #endif
71 
72 #include <sys/types.h>
73 #if defined(HAVE_SYS_IOCTL_H) && !defined(_WIN32)
74 #include <sys/ioctl.h>
75 #endif
76 #if defined(HAVE_FCNTL_H) || defined(_WIN32)
77 #include <fcntl.h>
78 #elif defined(HAVE_SYS_FCNTL_H)
79 #include <sys/fcntl.h>
80 #endif
81 
82 #if !HAVE_OFF_T && !defined(off_t)
83 # define off_t long
84 #endif
85 
86 #ifdef HAVE_SYS_TIME_H
87 # include <sys/time.h>
88 #endif
89 
90 #include <sys/stat.h>
91 
92 #if defined(HAVE_SYS_PARAM_H) || defined(__HIUX_MPP__)
93 # include <sys/param.h>
94 #endif
95 
96 #if !defined NOFILE
97 # define NOFILE 64
98 #endif
99 
100 #ifdef HAVE_UNISTD_H
101 #include <unistd.h>
102 #endif
103 
104 #ifdef HAVE_SYSCALL_H
105 #include <syscall.h>
106 #elif defined HAVE_SYS_SYSCALL_H
107 #include <sys/syscall.h>
108 #endif
109 
110 #ifdef HAVE_SYS_UIO_H
111 #include <sys/uio.h>
112 #endif
113 
114 #ifdef HAVE_SYS_WAIT_H
115 # include <sys/wait.h> /* for WNOHANG on BSD */
116 #endif
117 
118 #ifdef HAVE_COPYFILE_H
119 # include <copyfile.h>
120 #endif
121 
122 #include "ruby/util.h"
123 
124 #ifndef O_ACCMODE
125 #define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR)
126 #endif
127 
128 #if SIZEOF_OFF_T > SIZEOF_LONG && !defined(HAVE_LONG_LONG)
129 # error off_t is bigger than long, but you have no long long...
130 #endif
131 
132 #ifndef PIPE_BUF
133 # ifdef _POSIX_PIPE_BUF
134 # define PIPE_BUF _POSIX_PIPE_BUF
135 # else
136 # define PIPE_BUF 512 /* is this ok? */
137 # endif
138 #endif
139 
140 #ifndef EWOULDBLOCK
141 # define EWOULDBLOCK EAGAIN
142 #endif
143 
144 #if defined(HAVE___SYSCALL) && (defined(__APPLE__) || defined(__OpenBSD__))
145 /* Mac OS X and OpenBSD have __syscall but don't define it in headers */
146 off_t __syscall(quad_t number, ...);
147 #endif
148 
149 #define IO_RBUF_CAPA_MIN 8192
150 #define IO_CBUF_CAPA_MIN (128*1024)
151 #define IO_RBUF_CAPA_FOR(fptr) (NEED_READCONV(fptr) ? IO_CBUF_CAPA_MIN : IO_RBUF_CAPA_MIN)
152 #define IO_WBUF_CAPA_MIN 8192
153 
154 /* define system APIs */
155 #ifdef _WIN32
156 #undef open
157 #define open rb_w32_uopen
158 #undef rename
159 #define rename(f, t) rb_w32_urename((f), (t))
160 #endif
161 
162 #if defined(_WIN32)
163 # define RUBY_PIPE_NONBLOCK_DEFAULT (0)
164 #elif defined(O_NONBLOCK)
165  /* disabled for [Bug #15356] (Rack::Deflater + rails) failure: */
166 # define RUBY_PIPE_NONBLOCK_DEFAULT (0)
167 #else /* any platforms where O_NONBLOCK does not exist? */
168 # define RUBY_PIPE_NONBLOCK_DEFAULT (0)
169 #endif
170 
176 
177 static VALUE rb_eEAGAINWaitReadable;
178 static VALUE rb_eEAGAINWaitWritable;
179 static VALUE rb_eEWOULDBLOCKWaitReadable;
180 static VALUE rb_eEWOULDBLOCKWaitWritable;
181 static VALUE rb_eEINPROGRESSWaitWritable;
182 static VALUE rb_eEINPROGRESSWaitReadable;
183 
185 static VALUE orig_stdout, orig_stderr;
186 
191 
192 static VALUE argf;
193 
194 static ID id_write, id_read, id_getc, id_flush, id_readpartial, id_set_encoding;
195 static VALUE sym_mode, sym_perm, sym_flags, sym_extenc, sym_intenc, sym_encoding, sym_open_args;
196 static VALUE sym_textmode, sym_binmode, sym_autoclose;
197 static VALUE sym_SET, sym_CUR, sym_END;
198 static VALUE sym_wait_readable, sym_wait_writable;
199 #ifdef SEEK_DATA
200 static VALUE sym_DATA;
201 #endif
202 #ifdef SEEK_HOLE
203 static VALUE sym_HOLE;
204 #endif
205 
206 struct argf {
208  long last_lineno; /* $. */
209  long lineno;
214 };
215 
216 static rb_atomic_t max_file_descriptor = NOFILE;
217 void
219 {
220  rb_atomic_t afd = (rb_atomic_t)fd;
221  rb_atomic_t max_fd = max_file_descriptor;
222  int err;
223 
224  if (fd < 0 || afd <= max_fd)
225  return;
226 
227 #if defined(HAVE_FCNTL) && defined(F_GETFL)
228  err = fcntl(fd, F_GETFL) == -1;
229 #else
230  {
231  struct stat buf;
232  err = fstat(fd, &buf) != 0;
233  }
234 #endif
235  if (err && errno == EBADF) {
236  rb_bug("rb_update_max_fd: invalid fd (%d) given.", fd);
237  }
238 
239  while (max_fd < afd) {
240  max_fd = ATOMIC_CAS(max_file_descriptor, max_fd, afd);
241  }
242 }
243 
244 void
246 {
247  /* MinGW don't have F_GETFD and FD_CLOEXEC. [ruby-core:40281] */
248 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
249  int flags, flags2, ret;
250  flags = fcntl(fd, F_GETFD); /* should not fail except EBADF. */
251  if (flags == -1) {
252  rb_bug("rb_maygvl_fd_fix_cloexec: fcntl(%d, F_GETFD) failed: %s", fd, strerror(errno));
253  }
254  if (fd <= 2)
255  flags2 = flags & ~FD_CLOEXEC; /* Clear CLOEXEC for standard file descriptors: 0, 1, 2. */
256  else
257  flags2 = flags | FD_CLOEXEC; /* Set CLOEXEC for non-standard file descriptors: 3, 4, 5, ... */
258  if (flags != flags2) {
259  ret = fcntl(fd, F_SETFD, flags2);
260  if (ret != 0) {
261  rb_bug("rb_maygvl_fd_fix_cloexec: fcntl(%d, F_SETFD, %d) failed: %s", fd, flags2, strerror(errno));
262  }
263  }
264 #endif
265 }
266 
267 void
269 {
271  rb_update_max_fd(fd);
272 }
273 
274 /* this is only called once */
275 static int
276 rb_fix_detect_o_cloexec(int fd)
277 {
278 #if defined(O_CLOEXEC) && defined(F_GETFD)
279  int flags = fcntl(fd, F_GETFD);
280 
281  if (flags == -1)
282  rb_bug("rb_fix_detect_o_cloexec: fcntl(%d, F_GETFD) failed: %s", fd, strerror(errno));
283 
284  if (flags & FD_CLOEXEC)
285  return 1;
286 #endif /* fall through if O_CLOEXEC does not work: */
288  return 0;
289 }
290 
291 int
292 rb_cloexec_open(const char *pathname, int flags, mode_t mode)
293 {
294  int ret;
295  static int o_cloexec_state = -1; /* <0: unknown, 0: ignored, >0: working */
296 
297 #ifdef O_CLOEXEC
298  /* O_CLOEXEC is available since Linux 2.6.23. Linux 2.6.18 silently ignore it. */
299  flags |= O_CLOEXEC;
300 #elif defined O_NOINHERIT
301  flags |= O_NOINHERIT;
302 #endif
303  ret = open(pathname, flags, mode);
304  if (ret < 0) return ret;
305  if (ret <= 2 || o_cloexec_state == 0) {
307  }
308  else if (o_cloexec_state > 0) {
309  return ret;
310  }
311  else {
312  o_cloexec_state = rb_fix_detect_o_cloexec(ret);
313  }
314  return ret;
315 }
316 
317 int
318 rb_cloexec_dup(int oldfd)
319 {
320  /* Don't allocate standard file descriptors: 0, 1, 2 */
321  return rb_cloexec_fcntl_dupfd(oldfd, 3);
322 }
323 
324 int
325 rb_cloexec_dup2(int oldfd, int newfd)
326 {
327  int ret;
328 
329  /* When oldfd == newfd, dup2 succeeds but dup3 fails with EINVAL.
330  * rb_cloexec_dup2 succeeds as dup2. */
331  if (oldfd == newfd) {
332  ret = newfd;
333  }
334  else {
335 #if defined(HAVE_DUP3) && defined(O_CLOEXEC)
336  static int try_dup3 = 1;
337  if (2 < newfd && try_dup3) {
338  ret = dup3(oldfd, newfd, O_CLOEXEC);
339  if (ret != -1)
340  return ret;
341  /* dup3 is available since Linux 2.6.27, glibc 2.9. */
342  if (errno == ENOSYS) {
343  try_dup3 = 0;
344  ret = dup2(oldfd, newfd);
345  }
346  }
347  else {
348  ret = dup2(oldfd, newfd);
349  }
350 #else
351  ret = dup2(oldfd, newfd);
352 #endif
353  if (ret < 0) return ret;
354  }
356  return ret;
357 }
358 
359 static int
360 rb_fd_set_nonblock(int fd)
361 {
362 #ifdef _WIN32
363  return rb_w32_set_nonblock(fd);
364 #elif defined(F_GETFL)
365  int oflags = fcntl(fd, F_GETFL);
366 
367  if (oflags == -1)
368  return -1;
369  if (oflags & O_NONBLOCK)
370  return 0;
371  oflags |= O_NONBLOCK;
372  return fcntl(fd, F_SETFL, oflags);
373 #endif
374  return 0;
375 }
376 
377 int
378 rb_cloexec_pipe(int fildes[2])
379 {
380  int ret;
381 
382 #if defined(HAVE_PIPE2)
383  static int try_pipe2 = 1;
384  if (try_pipe2) {
385  ret = pipe2(fildes, O_CLOEXEC | RUBY_PIPE_NONBLOCK_DEFAULT);
386  if (ret != -1)
387  return ret;
388  /* pipe2 is available since Linux 2.6.27, glibc 2.9. */
389  if (errno == ENOSYS) {
390  try_pipe2 = 0;
391  ret = pipe(fildes);
392  }
393  }
394  else {
395  ret = pipe(fildes);
396  }
397 #else
398  ret = pipe(fildes);
399 #endif
400  if (ret < 0) return ret;
401 #ifdef __CYGWIN__
402  if (ret == 0 && fildes[1] == -1) {
403  close(fildes[0]);
404  fildes[0] = -1;
405  errno = ENFILE;
406  return -1;
407  }
408 #endif
409  rb_maygvl_fd_fix_cloexec(fildes[0]);
410  rb_maygvl_fd_fix_cloexec(fildes[1]);
412  rb_fd_set_nonblock(fildes[0]);
413  rb_fd_set_nonblock(fildes[1]);
414  }
415  return ret;
416 }
417 
418 int
419 rb_cloexec_fcntl_dupfd(int fd, int minfd)
420 {
421  int ret;
422 
423 #if defined(HAVE_FCNTL) && defined(F_DUPFD_CLOEXEC) && defined(F_DUPFD)
424  static int try_dupfd_cloexec = 1;
425  if (try_dupfd_cloexec) {
426  ret = fcntl(fd, F_DUPFD_CLOEXEC, minfd);
427  if (ret != -1) {
428  if (ret <= 2)
430  return ret;
431  }
432  /* F_DUPFD_CLOEXEC is available since Linux 2.6.24. Linux 2.6.18 fails with EINVAL */
433  if (errno == EINVAL) {
434  ret = fcntl(fd, F_DUPFD, minfd);
435  if (ret != -1) {
436  try_dupfd_cloexec = 0;
437  }
438  }
439  }
440  else {
441  ret = fcntl(fd, F_DUPFD, minfd);
442  }
443 #elif defined(HAVE_FCNTL) && defined(F_DUPFD)
444  ret = fcntl(fd, F_DUPFD, minfd);
445 #elif defined(HAVE_DUP)
446  ret = dup(fd);
447  if (ret >= 0 && ret < minfd) {
448  const int prev_fd = ret;
449  ret = rb_cloexec_fcntl_dupfd(fd, minfd);
450  close(prev_fd);
451  }
452  return ret;
453 #else
454 # error "dup() or fcntl(F_DUPFD) must be supported."
455 #endif
456  if (ret < 0) return ret;
458  return ret;
459 }
460 
461 #define argf_of(obj) (*(struct argf *)DATA_PTR(obj))
462 #define ARGF argf_of(argf)
463 
464 #define GetWriteIO(io) rb_io_get_write_io(io)
465 
466 #define READ_DATA_PENDING(fptr) ((fptr)->rbuf.len)
467 #define READ_DATA_PENDING_COUNT(fptr) ((fptr)->rbuf.len)
468 #define READ_DATA_PENDING_PTR(fptr) ((fptr)->rbuf.ptr+(fptr)->rbuf.off)
469 #define READ_DATA_BUFFERED(fptr) READ_DATA_PENDING(fptr)
470 
471 #define READ_CHAR_PENDING(fptr) ((fptr)->cbuf.len)
472 #define READ_CHAR_PENDING_COUNT(fptr) ((fptr)->cbuf.len)
473 #define READ_CHAR_PENDING_PTR(fptr) ((fptr)->cbuf.ptr+(fptr)->cbuf.off)
474 
475 #if defined(_WIN32)
476 #define WAIT_FD_IN_WIN32(fptr) \
477  (rb_w32_io_cancelable_p((fptr)->fd) ? 0 : rb_thread_wait_fd((fptr)->fd))
478 #else
479 #define WAIT_FD_IN_WIN32(fptr)
480 #endif
481 
482 #define READ_CHECK(fptr) do {\
483  if (!READ_DATA_PENDING(fptr)) {\
484  WAIT_FD_IN_WIN32(fptr);\
485  rb_io_check_closed(fptr);\
486  }\
487 } while(0)
488 
489 #ifndef S_ISSOCK
490 # ifdef _S_ISSOCK
491 # define S_ISSOCK(m) _S_ISSOCK(m)
492 # else
493 # ifdef _S_IFSOCK
494 # define S_ISSOCK(m) (((m) & S_IFMT) == _S_IFSOCK)
495 # else
496 # ifdef S_IFSOCK
497 # define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
498 # endif
499 # endif
500 # endif
501 #endif
502 
503 static int io_fflush(rb_io_t *);
504 static rb_io_t *flush_before_seek(rb_io_t *fptr);
505 
506 #define NEED_NEWLINE_DECORATOR_ON_READ(fptr) ((fptr)->mode & FMODE_TEXTMODE)
507 #define NEED_NEWLINE_DECORATOR_ON_WRITE(fptr) ((fptr)->mode & FMODE_TEXTMODE)
508 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
509 /* Windows */
510 # define DEFAULT_TEXTMODE FMODE_TEXTMODE
511 # define TEXTMODE_NEWLINE_DECORATOR_ON_WRITE ECONV_CRLF_NEWLINE_DECORATOR
512 /*
513  * CRLF newline is set as default newline decorator.
514  * If only CRLF newline conversion is needed, we use binary IO process
515  * with OS's text mode for IO performance improvement.
516  * If encoding conversion is needed or a user sets text mode, we use encoding
517  * conversion IO process and universal newline decorator by default.
518  */
519 #define NEED_READCONV(fptr) ((fptr)->encs.enc2 != NULL || (fptr)->encs.ecflags & ~ECONV_CRLF_NEWLINE_DECORATOR)
520 #define WRITECONV_MASK ( \
521  (ECONV_DECORATOR_MASK & ~ECONV_CRLF_NEWLINE_DECORATOR)|\
522  ECONV_STATEFUL_DECORATOR_MASK|\
523  0)
524 #define NEED_WRITECONV(fptr) ( \
525  ((fptr)->encs.enc != NULL && (fptr)->encs.enc != rb_ascii8bit_encoding()) || \
526  ((fptr)->encs.ecflags & WRITECONV_MASK) || \
527  0)
528 #define SET_BINARY_MODE(fptr) setmode((fptr)->fd, O_BINARY)
529 
530 #define NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr) do {\
531  if (NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {\
532  if (((fptr)->mode & FMODE_READABLE) &&\
533  !((fptr)->encs.ecflags & ECONV_NEWLINE_DECORATOR_MASK)) {\
534  setmode((fptr)->fd, O_BINARY);\
535  }\
536  else {\
537  setmode((fptr)->fd, O_TEXT);\
538  }\
539  }\
540 } while(0)
541 
542 #define SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags) do {\
543  if ((enc2) && ((ecflags) & ECONV_DEFAULT_NEWLINE_DECORATOR)) {\
544  (ecflags) |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;\
545  }\
546 } while(0)
547 
548 /*
549  * IO unread with taking care of removed '\r' in text mode.
550  */
551 static void
552 io_unread(rb_io_t *fptr)
553 {
554  off_t r, pos;
555  ssize_t read_size;
556  long i;
557  long newlines = 0;
558  long extra_max;
559  char *p;
560  char *buf;
561 
562  rb_io_check_closed(fptr);
563  if (fptr->rbuf.len == 0 || fptr->mode & FMODE_DUPLEX) {
564  return;
565  }
566 
567  errno = 0;
568  if (!rb_w32_fd_is_text(fptr->fd)) {
569  r = lseek(fptr->fd, -fptr->rbuf.len, SEEK_CUR);
570  if (r < 0 && errno) {
571  if (errno == ESPIPE)
572  fptr->mode |= FMODE_DUPLEX;
573  return;
574  }
575 
576  fptr->rbuf.off = 0;
577  fptr->rbuf.len = 0;
578  return;
579  }
580 
581  pos = lseek(fptr->fd, 0, SEEK_CUR);
582  if (pos < 0 && errno) {
583  if (errno == ESPIPE)
584  fptr->mode |= FMODE_DUPLEX;
585  return;
586  }
587 
588  /* add extra offset for removed '\r' in rbuf */
589  extra_max = (long)(pos - fptr->rbuf.len);
590  p = fptr->rbuf.ptr + fptr->rbuf.off;
591 
592  /* if the end of rbuf is '\r', rbuf doesn't have '\r' within rbuf.len */
593  if (*(fptr->rbuf.ptr + fptr->rbuf.capa - 1) == '\r') {
594  newlines++;
595  }
596 
597  for (i = 0; i < fptr->rbuf.len; i++) {
598  if (*p == '\n') newlines++;
599  if (extra_max == newlines) break;
600  p++;
601  }
602 
603  buf = ALLOC_N(char, fptr->rbuf.len + newlines);
604  while (newlines >= 0) {
605  r = lseek(fptr->fd, pos - fptr->rbuf.len - newlines, SEEK_SET);
606  if (newlines == 0) break;
607  if (r < 0) {
608  newlines--;
609  continue;
610  }
611  read_size = _read(fptr->fd, buf, fptr->rbuf.len + newlines);
612  if (read_size < 0) {
613  int e = errno;
614  free(buf);
615  rb_syserr_fail_path(e, fptr->pathv);
616  }
617  if (read_size == fptr->rbuf.len) {
618  lseek(fptr->fd, r, SEEK_SET);
619  break;
620  }
621  else {
622  newlines--;
623  }
624  }
625  free(buf);
626  fptr->rbuf.off = 0;
627  fptr->rbuf.len = 0;
628  return;
629 }
630 
631 /*
632  * We use io_seek to back cursor position when changing mode from text to binary,
633  * but stdin and pipe cannot seek back. Stdin and pipe read should use encoding
634  * conversion for working properly with mode change.
635  *
636  * Return previous translation mode.
637  */
638 static inline int
639 set_binary_mode_with_seek_cur(rb_io_t *fptr)
640 {
641  if (!rb_w32_fd_is_text(fptr->fd)) return O_BINARY;
642 
643  if (fptr->rbuf.len == 0 || fptr->mode & FMODE_DUPLEX) {
644  return setmode(fptr->fd, O_BINARY);
645  }
646  flush_before_seek(fptr);
647  return setmode(fptr->fd, O_BINARY);
648 }
649 #define SET_BINARY_MODE_WITH_SEEK_CUR(fptr) set_binary_mode_with_seek_cur(fptr)
650 
651 #else
652 /* Unix */
653 # define DEFAULT_TEXTMODE 0
654 #define NEED_READCONV(fptr) ((fptr)->encs.enc2 != NULL || NEED_NEWLINE_DECORATOR_ON_READ(fptr))
655 #define NEED_WRITECONV(fptr) ( \
656  ((fptr)->encs.enc != NULL && (fptr)->encs.enc != rb_ascii8bit_encoding()) || \
657  NEED_NEWLINE_DECORATOR_ON_WRITE(fptr) || \
658  ((fptr)->encs.ecflags & (ECONV_DECORATOR_MASK|ECONV_STATEFUL_DECORATOR_MASK)) || \
659  0)
660 #define SET_BINARY_MODE(fptr) (void)(fptr)
661 #define NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr) (void)(fptr)
662 #define SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags) ((void)(enc2), (void)(ecflags))
663 #define SET_BINARY_MODE_WITH_SEEK_CUR(fptr) (void)(fptr)
664 #endif
665 
666 #if !defined HAVE_SHUTDOWN && !defined shutdown
667 #define shutdown(a,b) 0
668 #endif
669 
670 #if defined(_WIN32)
671 #define is_socket(fd, path) rb_w32_is_socket(fd)
672 #elif !defined(S_ISSOCK)
673 #define is_socket(fd, path) 0
674 #else
675 static int
676 is_socket(int fd, VALUE path)
677 {
678  struct stat sbuf;
679  if (fstat(fd, &sbuf) < 0)
681  return S_ISSOCK(sbuf.st_mode);
682 }
683 #endif
684 
685 static const char closed_stream[] = "closed stream";
686 
687 static void
688 io_fd_check_closed(int fd)
689 {
690  if (fd < 0) {
691  rb_thread_check_ints(); /* check for ruby_error_stream_closed */
692  rb_raise(rb_eIOError, closed_stream);
693  }
694 }
695 
696 void
698 {
699  rb_raise(rb_eEOFError, "end of file reached");
700 }
701 
702 VALUE
704 {
705  rb_check_frozen(io);
706  return io;
707 }
708 
709 void
711 {
712  if (!fptr) {
713  rb_raise(rb_eIOError, "uninitialized stream");
714  }
715 }
716 
717 void
719 {
721  io_fd_check_closed(fptr->fd);
722 }
723 
724 static rb_io_t *
725 rb_io_get_fptr(VALUE io)
726 {
727  rb_io_t *fptr = RFILE(io)->fptr;
729  return fptr;
730 }
731 
732 VALUE
734 {
735  return rb_convert_type_with_id(io, T_FILE, "IO", idTo_io);
736 }
737 
738 VALUE
740 {
741  return rb_check_convert_type_with_id(io, T_FILE, "IO", idTo_io);
742 }
743 
744 VALUE
746 {
747  VALUE write_io;
748  write_io = rb_io_get_fptr(io)->tied_io_for_writing;
749  if (write_io) {
750  return write_io;
751  }
752  return io;
753 }
754 
755 VALUE
757 {
758  VALUE write_io;
759  rb_io_t *fptr = rb_io_get_fptr(io);
760  if (!RTEST(w)) {
761  w = 0;
762  }
763  else {
764  GetWriteIO(w);
765  }
766  write_io = fptr->tied_io_for_writing;
767  fptr->tied_io_for_writing = w;
768  return write_io ? write_io : Qnil;
769 }
770 
771 /*
772  * call-seq:
773  * IO.try_convert(obj) -> io or nil
774  *
775  * Try to convert <i>obj</i> into an IO, using to_io method.
776  * Returns converted IO or +nil+ if <i>obj</i> cannot be converted
777  * for any reason.
778  *
779  * IO.try_convert(STDOUT) #=> STDOUT
780  * IO.try_convert("STDOUT") #=> nil
781  *
782  * require 'zlib'
783  * f = open("/tmp/zz.gz") #=> #<File:/tmp/zz.gz>
784  * z = Zlib::GzipReader.open(f) #=> #<Zlib::GzipReader:0x81d8744>
785  * IO.try_convert(z) #=> #<File:/tmp/zz.gz>
786  *
787  */
788 static VALUE
789 rb_io_s_try_convert(VALUE dummy, VALUE io)
790 {
791  return rb_io_check_io(io);
792 }
793 
794 #if !(defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32))
795 static void
796 io_unread(rb_io_t *fptr)
797 {
798  off_t r;
799  rb_io_check_closed(fptr);
800  if (fptr->rbuf.len == 0 || fptr->mode & FMODE_DUPLEX)
801  return;
802  /* xxx: target position may be negative if buffer is filled by ungetc */
803  errno = 0;
804  r = lseek(fptr->fd, -fptr->rbuf.len, SEEK_CUR);
805  if (r < 0 && errno) {
806  if (errno == ESPIPE)
807  fptr->mode |= FMODE_DUPLEX;
808  return;
809  }
810  fptr->rbuf.off = 0;
811  fptr->rbuf.len = 0;
812  return;
813 }
814 #endif
815 
816 static rb_encoding *io_input_encoding(rb_io_t *fptr);
817 
818 static void
819 io_ungetbyte(VALUE str, rb_io_t *fptr)
820 {
821  long len = RSTRING_LEN(str);
822 
823  if (fptr->rbuf.ptr == NULL) {
824  const int min_capa = IO_RBUF_CAPA_FOR(fptr);
825  fptr->rbuf.off = 0;
826  fptr->rbuf.len = 0;
827 #if SIZEOF_LONG > SIZEOF_INT
828  if (len > INT_MAX)
829  rb_raise(rb_eIOError, "ungetbyte failed");
830 #endif
831  if (len > min_capa)
832  fptr->rbuf.capa = (int)len;
833  else
834  fptr->rbuf.capa = min_capa;
835  fptr->rbuf.ptr = ALLOC_N(char, fptr->rbuf.capa);
836  }
837  if (fptr->rbuf.capa < len + fptr->rbuf.len) {
838  rb_raise(rb_eIOError, "ungetbyte failed");
839  }
840  if (fptr->rbuf.off < len) {
841  MEMMOVE(fptr->rbuf.ptr+fptr->rbuf.capa-fptr->rbuf.len,
842  fptr->rbuf.ptr+fptr->rbuf.off,
843  char, fptr->rbuf.len);
844  fptr->rbuf.off = fptr->rbuf.capa-fptr->rbuf.len;
845  }
846  fptr->rbuf.off-=(int)len;
847  fptr->rbuf.len+=(int)len;
848  MEMMOVE(fptr->rbuf.ptr+fptr->rbuf.off, RSTRING_PTR(str), char, len);
849 }
850 
851 static rb_io_t *
852 flush_before_seek(rb_io_t *fptr)
853 {
854  if (io_fflush(fptr) < 0)
855  rb_sys_fail(0);
856  io_unread(fptr);
857  errno = 0;
858  return fptr;
859 }
860 
861 #define io_seek(fptr, ofs, whence) (errno = 0, lseek(flush_before_seek(fptr)->fd, (ofs), (whence)))
862 #define io_tell(fptr) lseek(flush_before_seek(fptr)->fd, 0, SEEK_CUR)
863 
864 #ifndef SEEK_CUR
865 # define SEEK_SET 0
866 # define SEEK_CUR 1
867 # define SEEK_END 2
868 #endif
869 
870 void
872 {
873  rb_io_check_closed(fptr);
874  if (!(fptr->mode & FMODE_READABLE)) {
875  rb_raise(rb_eIOError, "not opened for reading");
876  }
877  if (fptr->wbuf.len) {
878  if (io_fflush(fptr) < 0)
879  rb_sys_fail(0);
880  }
881  if (fptr->tied_io_for_writing) {
882  rb_io_t *wfptr;
883  GetOpenFile(fptr->tied_io_for_writing, wfptr);
884  if (io_fflush(wfptr) < 0)
885  rb_sys_fail(0);
886  }
887 }
888 
889 void
891 {
893  if (READ_CHAR_PENDING(fptr)) {
894  rb_raise(rb_eIOError, "byte oriented read for character buffered IO");
895  }
896 }
897 
898 void
900 {
902 }
903 
904 static rb_encoding*
905 io_read_encoding(rb_io_t *fptr)
906 {
907  if (fptr->encs.enc) {
908  return fptr->encs.enc;
909  }
911 }
912 
913 static rb_encoding*
914 io_input_encoding(rb_io_t *fptr)
915 {
916  if (fptr->encs.enc2) {
917  return fptr->encs.enc2;
918  }
919  return io_read_encoding(fptr);
920 }
921 
922 void
924 {
925  rb_io_check_closed(fptr);
926  if (!(fptr->mode & FMODE_WRITABLE)) {
927  rb_raise(rb_eIOError, "not opened for writing");
928  }
929  if (fptr->rbuf.len) {
930  io_unread(fptr);
931  }
932 }
933 
934 int
936 {
937  /* This function is used for bytes and chars. Confusing. */
938  if (READ_CHAR_PENDING(fptr))
939  return 1; /* should raise? */
940  return READ_DATA_PENDING(fptr);
941 }
942 
943 void
945 {
946  if (!READ_DATA_PENDING(fptr)) {
947  rb_thread_wait_fd(fptr->fd);
948  }
949  return;
950 }
951 
952 int
954 {
955  if (err == EMFILE || err == ENFILE || err == ENOMEM) {
956  rb_gc();
957  return 1;
958  }
959  return 0;
960 }
961 
962 static int
963 ruby_dup(int orig)
964 {
965  int fd;
966 
967  fd = rb_cloexec_dup(orig);
968  if (fd < 0) {
969  int e = errno;
970  if (rb_gc_for_fd(e)) {
971  fd = rb_cloexec_dup(orig);
972  }
973  if (fd < 0) {
974  rb_syserr_fail(e, 0);
975  }
976  }
977  rb_update_max_fd(fd);
978  return fd;
979 }
980 
981 static VALUE
982 io_alloc(VALUE klass)
983 {
984  NEWOBJ_OF(io, struct RFile, klass, T_FILE);
985 
986  io->fptr = 0;
987 
988  return (VALUE)io;
989 }
990 
991 #ifndef S_ISREG
992 # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
993 #endif
994 
996  int fd;
997  int nonblock;
998  void *buf;
999  size_t capa;
1000 };
1001 
1003  int fd;
1004  const void *buf;
1005  size_t capa;
1006 };
1007 
1008 #ifdef HAVE_WRITEV
1009 struct io_internal_writev_struct {
1010  int fd;
1011  int iovcnt;
1012  const struct iovec *iov;
1013 };
1014 #endif
1015 
1016 static int nogvl_wait_for_single_fd(int fd, short events);
1017 static VALUE
1018 internal_read_func(void *ptr)
1019 {
1020  struct io_internal_read_struct *iis = ptr;
1021  ssize_t r;
1022 retry:
1023  r = read(iis->fd, iis->buf, iis->capa);
1024  if (r < 0 && !iis->nonblock) {
1025  int e = errno;
1026  if (e == EAGAIN || e == EWOULDBLOCK) {
1027  if (nogvl_wait_for_single_fd(iis->fd, RB_WAITFD_IN) != -1) {
1028  goto retry;
1029  }
1030  errno = e;
1031  }
1032  }
1033  return r;
1034 }
1035 
1036 #if defined __APPLE__
1037 # define do_write_retry(code) do {ret = code;} while (ret == -1 && errno == EPROTOTYPE)
1038 #else
1039 # define do_write_retry(code) ret = code
1040 #endif
1041 static VALUE
1042 internal_write_func(void *ptr)
1043 {
1044  struct io_internal_write_struct *iis = ptr;
1045  ssize_t ret;
1046  do_write_retry(write(iis->fd, iis->buf, iis->capa));
1047  return (VALUE)ret;
1048 }
1049 
1050 static void*
1051 internal_write_func2(void *ptr)
1052 {
1053  return (void*)internal_write_func(ptr);
1054 }
1055 
1056 #ifdef HAVE_WRITEV
1057 static VALUE
1058 internal_writev_func(void *ptr)
1059 {
1060  struct io_internal_writev_struct *iis = ptr;
1061  ssize_t ret;
1062  do_write_retry(writev(iis->fd, iis->iov, iis->iovcnt));
1063  return (VALUE)ret;
1064 }
1065 #endif
1066 
1067 static ssize_t
1068 rb_read_internal(int fd, void *buf, size_t count)
1069 {
1070  struct io_internal_read_struct iis;
1071 
1072  iis.fd = fd;
1073  iis.nonblock = 0;
1074  iis.buf = buf;
1075  iis.capa = count;
1076 
1077  return (ssize_t)rb_thread_io_blocking_region(internal_read_func, &iis, fd);
1078 }
1079 
1080 static ssize_t
1081 rb_write_internal(int fd, const void *buf, size_t count)
1082 {
1083  struct io_internal_write_struct iis;
1084  iis.fd = fd;
1085  iis.buf = buf;
1086  iis.capa = count;
1087 
1088  return (ssize_t)rb_thread_io_blocking_region(internal_write_func, &iis, fd);
1089 }
1090 
1091 static ssize_t
1092 rb_write_internal2(int fd, const void *buf, size_t count)
1093 {
1094  struct io_internal_write_struct iis;
1095  iis.fd = fd;
1096  iis.buf = buf;
1097  iis.capa = count;
1098 
1099  return (ssize_t)rb_thread_call_without_gvl2(internal_write_func2, &iis,
1100  RUBY_UBF_IO, NULL);
1101 }
1102 
1103 #ifdef HAVE_WRITEV
1104 static ssize_t
1105 rb_writev_internal(int fd, const struct iovec *iov, int iovcnt)
1106 {
1107  struct io_internal_writev_struct iis;
1108  iis.fd = fd;
1109  iis.iov = iov;
1110  iis.iovcnt = iovcnt;
1111 
1112  return (ssize_t)rb_thread_io_blocking_region(internal_writev_func, &iis, fd);
1113 }
1114 #endif
1115 
1116 static VALUE
1117 io_flush_buffer_sync(void *arg)
1118 {
1119  rb_io_t *fptr = arg;
1120  long l = fptr->wbuf.len;
1121  ssize_t r = write(fptr->fd, fptr->wbuf.ptr+fptr->wbuf.off, (size_t)l);
1122 
1123  if (fptr->wbuf.len <= r) {
1124  fptr->wbuf.off = 0;
1125  fptr->wbuf.len = 0;
1126  return 0;
1127  }
1128  if (0 <= r) {
1129  fptr->wbuf.off += (int)r;
1130  fptr->wbuf.len -= (int)r;
1131  errno = EAGAIN;
1132  }
1133  return (VALUE)-1;
1134 }
1135 
1136 static void*
1137 io_flush_buffer_sync2(void *arg)
1138 {
1139  VALUE result = io_flush_buffer_sync(arg);
1140 
1141  /*
1142  * rb_thread_call_without_gvl2 uses 0 as interrupted.
1143  * So, we need to avoid to use 0.
1144  */
1145  return !result ? (void*)1 : (void*)result;
1146 }
1147 
1148 static VALUE
1149 io_flush_buffer_async(VALUE arg)
1150 {
1151  rb_io_t *fptr = (rb_io_t *)arg;
1152  return rb_thread_io_blocking_region(io_flush_buffer_sync, fptr, fptr->fd);
1153 }
1154 
1155 static VALUE
1156 io_flush_buffer_async2(VALUE arg)
1157 {
1158  rb_io_t *fptr = (rb_io_t *)arg;
1159  VALUE ret;
1160 
1161  ret = (VALUE)rb_thread_call_without_gvl2(io_flush_buffer_sync2, fptr,
1162  RUBY_UBF_IO, NULL);
1163 
1164  if (!ret) {
1165  /* pending async interrupt is there. */
1166  errno = EAGAIN;
1167  return -1;
1168  }
1169  else if (ret == 1) {
1170  return 0;
1171  }
1172  return ret;
1173 }
1174 
1175 static inline int
1176 io_flush_buffer(rb_io_t *fptr)
1177 {
1178  if (fptr->write_lock) {
1179  if (rb_mutex_owned_p(fptr->write_lock))
1180  return (int)io_flush_buffer_async2((VALUE)fptr);
1181  else
1182  return (int)rb_mutex_synchronize(fptr->write_lock, io_flush_buffer_async2, (VALUE)fptr);
1183  }
1184  else {
1185  return (int)io_flush_buffer_async((VALUE)fptr);
1186  }
1187 }
1188 
1189 static int
1190 io_fflush(rb_io_t *fptr)
1191 {
1192  rb_io_check_closed(fptr);
1193  if (fptr->wbuf.len == 0)
1194  return 0;
1195  while (fptr->wbuf.len > 0 && io_flush_buffer(fptr) != 0) {
1196  if (!rb_io_wait_writable(fptr->fd))
1197  return -1;
1198  rb_io_check_closed(fptr);
1199  }
1200  return 0;
1201 }
1202 
1203 int
1205 {
1206  io_fd_check_closed(f);
1207  switch (errno) {
1208  case EINTR:
1209 #if defined(ERESTART)
1210  case ERESTART:
1211 #endif
1213  return TRUE;
1214 
1215  case EAGAIN:
1216 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
1217  case EWOULDBLOCK:
1218 #endif
1220  return TRUE;
1221 
1222  default:
1223  return FALSE;
1224  }
1225 }
1226 
1227 int
1229 {
1230  io_fd_check_closed(f);
1231  switch (errno) {
1232  case EINTR:
1233 #if defined(ERESTART)
1234  case ERESTART:
1235 #endif
1236  /*
1237  * In old Linux, several special files under /proc and /sys don't handle
1238  * select properly. Thus we need avoid to call if don't use O_NONBLOCK.
1239  * Otherwise, we face nasty hang up. Sigh.
1240  * e.g. http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=31b07093c44a7a442394d44423e21d783f5523b8
1241  * http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=31b07093c44a7a442394d44423e21d783f5523b8
1242  * In EINTR case, we only need to call RUBY_VM_CHECK_INTS_BLOCKING().
1243  * Then rb_thread_check_ints() is enough.
1244  */
1246  return TRUE;
1247 
1248  case EAGAIN:
1249 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
1250  case EWOULDBLOCK:
1251 #endif
1253  return TRUE;
1254 
1255  default:
1256  return FALSE;
1257  }
1258 }
1259 
1260 static void
1261 make_writeconv(rb_io_t *fptr)
1262 {
1263  if (!fptr->writeconv_initialized) {
1264  const char *senc, *denc;
1265  rb_encoding *enc;
1266  int ecflags;
1267  VALUE ecopts;
1268 
1269  fptr->writeconv_initialized = 1;
1270 
1271  ecflags = fptr->encs.ecflags & ~ECONV_NEWLINE_DECORATOR_READ_MASK;
1272  ecopts = fptr->encs.ecopts;
1273 
1274  if (!fptr->encs.enc || (fptr->encs.enc == rb_ascii8bit_encoding() && !fptr->encs.enc2)) {
1275  /* no encoding conversion */
1276  fptr->writeconv_pre_ecflags = 0;
1277  fptr->writeconv_pre_ecopts = Qnil;
1278  fptr->writeconv = rb_econv_open_opts("", "", ecflags, ecopts);
1279  if (!fptr->writeconv)
1280  rb_exc_raise(rb_econv_open_exc("", "", ecflags));
1281  fptr->writeconv_asciicompat = Qnil;
1282  }
1283  else {
1284  enc = fptr->encs.enc2 ? fptr->encs.enc2 : fptr->encs.enc;
1286  if (!senc && !(fptr->encs.ecflags & ECONV_STATEFUL_DECORATOR_MASK)) {
1287  /* single conversion */
1288  fptr->writeconv_pre_ecflags = ecflags;
1289  fptr->writeconv_pre_ecopts = ecopts;
1290  fptr->writeconv = NULL;
1291  fptr->writeconv_asciicompat = Qnil;
1292  }
1293  else {
1294  /* double conversion */
1296  fptr->writeconv_pre_ecopts = ecopts;
1297  if (senc) {
1298  denc = rb_enc_name(enc);
1299  fptr->writeconv_asciicompat = rb_str_new2(senc);
1300  }
1301  else {
1302  senc = denc = "";
1304  }
1306  ecopts = fptr->encs.ecopts;
1307  fptr->writeconv = rb_econv_open_opts(senc, denc, ecflags, ecopts);
1308  if (!fptr->writeconv)
1309  rb_exc_raise(rb_econv_open_exc(senc, denc, ecflags));
1310  }
1311  }
1312  }
1313 }
1314 
1315 /* writing functions */
1319  const char *ptr;
1320  long length;
1321 };
1322 
1323 struct write_arg {
1326  int nosync;
1327 };
1328 
1329 #ifdef HAVE_WRITEV
1330 static VALUE
1331 io_binwrite_string(VALUE arg)
1332 {
1333  struct binwrite_arg *p = (struct binwrite_arg *)arg;
1334  rb_io_t *fptr = p->fptr;
1335  long r;
1336 
1337  if (fptr->wbuf.len) {
1338  struct iovec iov[2];
1339 
1340  iov[0].iov_base = fptr->wbuf.ptr+fptr->wbuf.off;
1341  iov[0].iov_len = fptr->wbuf.len;
1342  iov[1].iov_base = (char *)p->ptr;
1343  iov[1].iov_len = p->length;
1344 
1345  r = rb_writev_internal(fptr->fd, iov, 2);
1346 
1347  if (r < 0)
1348  return r;
1349 
1350  if (fptr->wbuf.len <= r) {
1351  r -= fptr->wbuf.len;
1352  fptr->wbuf.off = 0;
1353  fptr->wbuf.len = 0;
1354  }
1355  else {
1356  fptr->wbuf.off += (int)r;
1357  fptr->wbuf.len -= (int)r;
1358  r = 0L;
1359  }
1360  }
1361  else {
1362  r = rb_write_internal(fptr->fd, p->ptr, p->length);
1363  }
1364 
1365  return r;
1366 }
1367 #else
1368 static VALUE
1369 io_binwrite_string(VALUE arg)
1370 {
1371  struct binwrite_arg *p = (struct binwrite_arg *)arg;
1372  rb_io_t *fptr = p->fptr;
1373  long l, len;
1374 
1375  l = len = p->length;
1376 
1377  if (fptr->wbuf.len) {
1378  if (fptr->wbuf.len+len <= fptr->wbuf.capa) {
1379  if (fptr->wbuf.capa < fptr->wbuf.off+fptr->wbuf.len+len) {
1380  MEMMOVE(fptr->wbuf.ptr, fptr->wbuf.ptr+fptr->wbuf.off, char, fptr->wbuf.len);
1381  fptr->wbuf.off = 0;
1382  }
1383  MEMMOVE(fptr->wbuf.ptr+fptr->wbuf.off+fptr->wbuf.len, p->ptr, char, len);
1384  fptr->wbuf.len += (int)len;
1385  l = 0;
1386  }
1387  if (io_fflush(fptr) < 0)
1388  return -2L; /* fail in fflush */
1389  if (l == 0)
1390  return len;
1391  }
1392 
1395 
1396  return rb_write_internal(p->fptr->fd, p->ptr, p->length);
1397 }
1398 #endif
1399 
1400 static long
1401 io_binwrite(VALUE str, const char *ptr, long len, rb_io_t *fptr, int nosync)
1402 {
1403  long n, r, offset = 0;
1404 
1405  /* don't write anything if current thread has a pending interrupt. */
1407 
1408  if ((n = len) <= 0) return n;
1409  if (fptr->wbuf.ptr == NULL && !(!nosync && (fptr->mode & FMODE_SYNC))) {
1410  fptr->wbuf.off = 0;
1411  fptr->wbuf.len = 0;
1412  fptr->wbuf.capa = IO_WBUF_CAPA_MIN;
1413  fptr->wbuf.ptr = ALLOC_N(char, fptr->wbuf.capa);
1416  }
1417  if ((!nosync && (fptr->mode & (FMODE_SYNC|FMODE_TTY))) ||
1418  (fptr->wbuf.ptr && fptr->wbuf.capa <= fptr->wbuf.len + len)) {
1419  struct binwrite_arg arg;
1420 
1421  arg.fptr = fptr;
1422  arg.str = str;
1423  retry:
1424  arg.ptr = ptr + offset;
1425  arg.length = n;
1426  if (fptr->write_lock) {
1427  r = rb_mutex_synchronize(fptr->write_lock, io_binwrite_string, (VALUE)&arg);
1428  }
1429  else {
1430  r = io_binwrite_string((VALUE)&arg);
1431  }
1432  /* xxx: other threads may modify given string. */
1433  if (r == n) return len;
1434  if (0 <= r) {
1435  offset += r;
1436  n -= r;
1437  errno = EAGAIN;
1438  }
1439  if (r == -2L)
1440  return -1L;
1441  if (rb_io_wait_writable(fptr->fd)) {
1443  if (offset < len)
1444  goto retry;
1445  }
1446  return -1L;
1447  }
1448 
1449  if (fptr->wbuf.off) {
1450  if (fptr->wbuf.len)
1451  MEMMOVE(fptr->wbuf.ptr, fptr->wbuf.ptr+fptr->wbuf.off, char, fptr->wbuf.len);
1452  fptr->wbuf.off = 0;
1453  }
1454  MEMMOVE(fptr->wbuf.ptr+fptr->wbuf.off+fptr->wbuf.len, ptr+offset, char, len);
1455  fptr->wbuf.len += (int)len;
1456  return len;
1457 }
1458 
1459 # define MODE_BTMODE(a,b,c) ((fmode & FMODE_BINMODE) ? (b) : \
1460  (fmode & FMODE_TEXTMODE) ? (c) : (a))
1461 
1462 #define MODE_BTXMODE(a, b, c, d, e, f) ((fmode & FMODE_EXCL) ? \
1463  MODE_BTMODE(d, e, f) : \
1464  MODE_BTMODE(a, b, c))
1465 
1466 static VALUE
1467 do_writeconv(VALUE str, rb_io_t *fptr, int *converted)
1468 {
1469  if (NEED_WRITECONV(fptr)) {
1470  VALUE common_encoding = Qnil;
1472 
1473  make_writeconv(fptr);
1474 
1475  if (fptr->writeconv) {
1476 #define fmode (fptr->mode)
1478  common_encoding = fptr->writeconv_asciicompat;
1480  rb_raise(rb_eArgError, "ASCII incompatible string written for text mode IO without encoding conversion: %s",
1482  }
1483 #undef fmode
1484  }
1485  else {
1486  if (fptr->encs.enc2)
1487  common_encoding = rb_enc_from_encoding(fptr->encs.enc2);
1488  else if (fptr->encs.enc != rb_ascii8bit_encoding())
1489  common_encoding = rb_enc_from_encoding(fptr->encs.enc);
1490  }
1491 
1492  if (!NIL_P(common_encoding)) {
1493  str = rb_str_encode(str, common_encoding,
1495  *converted = 1;
1496  }
1497 
1498  if (fptr->writeconv) {
1500  *converted = 1;
1501  }
1502  }
1503 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
1504 #define fmode (fptr->mode)
1505  else if (MODE_BTMODE(DEFAULT_TEXTMODE,0,1)) {
1506  if ((fptr->mode & FMODE_READABLE) &&
1508  setmode(fptr->fd, O_BINARY);
1509  }
1510  else {
1511  setmode(fptr->fd, O_TEXT);
1512  }
1514  rb_raise(rb_eArgError, "ASCII incompatible string written for text mode IO without encoding conversion: %s",
1516  }
1517  }
1518 #undef fmode
1519 #endif
1520  return str;
1521 }
1522 
1523 static long
1524 io_fwrite(VALUE str, rb_io_t *fptr, int nosync)
1525 {
1526  int converted = 0;
1527  VALUE tmp;
1528  long n, len;
1529  const char *ptr;
1530 #ifdef _WIN32
1531  if (fptr->mode & FMODE_TTY) {
1532  long len = rb_w32_write_console(str, fptr->fd);
1533  if (len > 0) return len;
1534  }
1535 #endif
1536  str = do_writeconv(str, fptr, &converted);
1537  if (converted)
1538  OBJ_FREEZE(str);
1539 
1541  RSTRING_GETMEM(tmp, ptr, len);
1542  n = io_binwrite(tmp, ptr, len, fptr, nosync);
1544 
1545  return n;
1546 }
1547 
1548 ssize_t
1549 rb_io_bufwrite(VALUE io, const void *buf, size_t size)
1550 {
1551  rb_io_t *fptr;
1552 
1553  GetOpenFile(io, fptr);
1555  return (ssize_t)io_binwrite(0, buf, (long)size, fptr, 0);
1556 }
1557 
1558 static VALUE
1559 io_write(VALUE io, VALUE str, int nosync)
1560 {
1561  rb_io_t *fptr;
1562  long n;
1563  VALUE tmp;
1564 
1565  io = GetWriteIO(io);
1567  tmp = rb_io_check_io(io);
1568  if (NIL_P(tmp)) {
1569  /* port is not IO, call write method for it. */
1570  return rb_funcall(io, id_write, 1, str);
1571  }
1572  io = tmp;
1573  if (RSTRING_LEN(str) == 0) return INT2FIX(0);
1574 
1575  GetOpenFile(io, fptr);
1577 
1578  n = io_fwrite(str, fptr, nosync);
1579  if (n < 0L) rb_sys_fail_path(fptr->pathv);
1580 
1581  return LONG2FIX(n);
1582 }
1583 
1584 #ifdef HAVE_WRITEV
1585 struct binwritev_arg {
1586  rb_io_t *fptr;
1587  const struct iovec *iov;
1588  int iovcnt;
1589 };
1590 
1591 static VALUE
1592 call_writev_internal(VALUE arg)
1593 {
1594  struct binwritev_arg *p = (struct binwritev_arg *)arg;
1595  return rb_writev_internal(p->fptr->fd, p->iov, p->iovcnt);
1596 }
1597 
1598 static long
1599 io_binwritev(struct iovec *iov, int iovcnt, rb_io_t *fptr)
1600 {
1601  int i;
1602  long r, total = 0, written_len = 0;
1603 
1604  /* don't write anything if current thread has a pending interrupt. */
1606 
1607  if (iovcnt == 0) return 0;
1608  for (i = 1; i < iovcnt; i++) total += iov[i].iov_len;
1609 
1610  if (fptr->wbuf.ptr == NULL && !(fptr->mode & FMODE_SYNC)) {
1611  fptr->wbuf.off = 0;
1612  fptr->wbuf.len = 0;
1613  fptr->wbuf.capa = IO_WBUF_CAPA_MIN;
1614  fptr->wbuf.ptr = ALLOC_N(char, fptr->wbuf.capa);
1615  fptr->write_lock = rb_mutex_new();
1616  rb_mutex_allow_trap(fptr->write_lock, 1);
1617  }
1618 
1619  if (fptr->wbuf.ptr && fptr->wbuf.len) {
1620  long offset = fptr->wbuf.off + fptr->wbuf.len;
1621  if (offset + total <= fptr->wbuf.capa) {
1622  for (i = 1; i < iovcnt; i++) {
1623  memcpy(fptr->wbuf.ptr+offset, iov[i].iov_base, iov[i].iov_len);
1624  offset += iov[i].iov_len;
1625  }
1626  fptr->wbuf.len += total;
1627  return total;
1628  }
1629  else {
1630  iov[0].iov_base = fptr->wbuf.ptr + fptr->wbuf.off;
1631  iov[0].iov_len = fptr->wbuf.len;
1632  }
1633  }
1634  else {
1635  iov++;
1636  if (!--iovcnt) return 0;
1637  }
1638 
1639  retry:
1640  if (fptr->write_lock) {
1641  struct binwritev_arg arg;
1642  arg.fptr = fptr;
1643  arg.iov = iov;
1644  arg.iovcnt = iovcnt;
1645  r = rb_mutex_synchronize(fptr->write_lock, call_writev_internal, (VALUE)&arg);
1646  }
1647  else {
1648  r = rb_writev_internal(fptr->fd, iov, iovcnt);
1649  }
1650 
1651  if (r >= 0) {
1652  written_len += r;
1653  if (fptr->wbuf.ptr && fptr->wbuf.len) {
1654  if (written_len < fptr->wbuf.len) {
1655  fptr->wbuf.off += r;
1656  fptr->wbuf.len -= r;
1657  }
1658  else {
1659  written_len -= fptr->wbuf.len;
1660  fptr->wbuf.off = 0;
1661  fptr->wbuf.len = 0;
1662  }
1663  }
1664  if (written_len == total) return total;
1665 
1666  while (r >= (ssize_t)iov->iov_len) {
1667  /* iovcnt > 0 */
1668  r -= iov->iov_len;
1669  iov->iov_len = 0;
1670  iov++;
1671  if (!--iovcnt) return total;
1672  /* defensive check: written_len should == total */
1673  }
1674  iov->iov_base = (char *)iov->iov_base + r;
1675  iov->iov_len -= r;
1676 
1677  errno = EAGAIN;
1678  }
1679  if (rb_io_wait_writable(fptr->fd)) {
1680  rb_io_check_closed(fptr);
1681  goto retry;
1682  }
1683 
1684  return -1L;
1685 }
1686 
1687 static long
1688 io_fwritev(int argc, VALUE *argv, rb_io_t *fptr)
1689 {
1690  int i, converted, iovcnt = argc + 1;
1691  long n;
1692  VALUE v1, v2, str, tmp, *tmp_array;
1693  struct iovec *iov;
1694 
1695  iov = ALLOCV_N(struct iovec, v1, iovcnt);
1696  tmp_array = ALLOCV_N(VALUE, v2, argc);
1697 
1698  for (i = 0; i < argc; i++) {
1699  str = rb_obj_as_string(argv[i]);
1700  converted = 0;
1701  str = do_writeconv(str, fptr, &converted);
1702  if (converted)
1703  OBJ_FREEZE(str);
1704 
1706  tmp_array[i] = tmp;
1707  /* iov[0] is reserved for buffer of fptr */
1708  iov[i+1].iov_base = RSTRING_PTR(tmp);
1709  iov[i+1].iov_len = RSTRING_LEN(tmp);
1710  }
1711 
1712  n = io_binwritev(iov, iovcnt, fptr);
1713  if (v1) ALLOCV_END(v1);
1714 
1715  for (i = 0; i < argc; i++) {
1716  rb_str_tmp_frozen_release(argv[i], tmp_array[i]);
1717  }
1718 
1719  if (v2) ALLOCV_END(v2);
1720 
1721  return n;
1722 }
1723 
1724 static int
1725 iovcnt_ok(int iovcnt)
1726 {
1727 #ifdef IOV_MAX
1728  return iovcnt < IOV_MAX;
1729 #else /* GNU/Hurd has writev, but no IOV_MAX */
1730  return 1;
1731 #endif
1732 }
1733 #endif /* HAVE_WRITEV */
1734 
1735 static VALUE
1736 io_writev(int argc, VALUE *argv, VALUE io)
1737 {
1738  rb_io_t *fptr;
1739  long n;
1740  VALUE tmp, total = INT2FIX(0);
1741  int i, cnt = 1;
1742 
1743  io = GetWriteIO(io);
1744  tmp = rb_io_check_io(io);
1745  if (NIL_P(tmp)) {
1746  /* port is not IO, call write method for it. */
1747  return rb_funcallv(io, id_write, argc, argv);
1748  }
1749  io = tmp;
1750 
1751  GetOpenFile(io, fptr);
1752  rb_io_check_writable(fptr);
1753 
1754  for (i = 0; i < argc; i += cnt) {
1755 #ifdef HAVE_WRITEV
1756  if ((fptr->mode & (FMODE_SYNC|FMODE_TTY)) && iovcnt_ok(cnt = argc - i)) {
1757  n = io_fwritev(cnt, &argv[i], fptr);
1758  }
1759  else
1760 #endif
1761  {
1762  cnt = 1;
1763  /* sync at last item */
1764  n = io_fwrite(rb_obj_as_string(argv[i]), fptr, (i < argc-1));
1765  }
1766  if (n < 0L) rb_sys_fail_path(fptr->pathv);
1767  total = rb_fix_plus(LONG2FIX(n), total);
1768  }
1769 
1770  return total;
1771 }
1772 
1773 /*
1774  * call-seq:
1775  * ios.write(string, ...) -> integer
1776  *
1777  * Writes the given strings to <em>ios</em>. The stream must be opened
1778  * for writing. Arguments that are not a string will be converted
1779  * to a string using <code>to_s</code>. Returns the number of bytes
1780  * written in total.
1781  *
1782  * count = $stdout.write("This is", " a test\n")
1783  * puts "That was #{count} bytes of data"
1784  *
1785  * <em>produces:</em>
1786  *
1787  * This is a test
1788  * That was 15 bytes of data
1789  */
1790 
1791 static VALUE
1792 io_write_m(int argc, VALUE *argv, VALUE io)
1793 {
1794  if (argc != 1) {
1795  return io_writev(argc, argv, io);
1796  }
1797  else {
1798  VALUE str = argv[0];
1799  return io_write(io, str, 0);
1800  }
1801 }
1802 
1803 VALUE
1805 {
1806  return rb_funcallv(io, id_write, 1, &str);
1807 }
1808 
1809 static VALUE
1810 rb_io_writev(VALUE io, int argc, VALUE *argv)
1811 {
1812  if (argc > 1 && rb_obj_method_arity(io, id_write) == 1) {
1813  if (io != rb_stderr && RTEST(ruby_verbose)) {
1814  VALUE klass = CLASS_OF(io);
1815  char sep = FL_TEST(klass, FL_SINGLETON) ? (klass = io, '.') : '#';
1816  rb_warning("%+"PRIsVALUE"%c""write is outdated interface"
1817  " which accepts just one argument",
1818  klass, sep);
1819  }
1820  do rb_io_write(io, *argv++); while (--argc);
1821  return argv[0]; /* unused right now */
1822  }
1823  return rb_funcallv(io, id_write, argc, argv);
1824 }
1825 
1826 /*
1827  * call-seq:
1828  * ios << obj -> ios
1829  *
1830  * String Output---Writes <i>obj</i> to <em>ios</em>.
1831  * <i>obj</i> will be converted to a string using
1832  * <code>to_s</code>.
1833  *
1834  * $stdout << "Hello " << "world!\n"
1835  *
1836  * <em>produces:</em>
1837  *
1838  * Hello world!
1839  */
1840 
1841 
1842 VALUE
1844 {
1845  rb_io_write(io, str);
1846  return io;
1847 }
1848 
1849 #ifdef HAVE_FSYNC
1850 static VALUE
1851 nogvl_fsync(void *ptr)
1852 {
1853  rb_io_t *fptr = ptr;
1854 
1855 #ifdef _WIN32
1856  if (GetFileType((HANDLE)rb_w32_get_osfhandle(fptr->fd)) != FILE_TYPE_DISK)
1857  return 0;
1858 #endif
1859  return (VALUE)fsync(fptr->fd);
1860 }
1861 #endif
1862 
1863 VALUE
1865 {
1866  rb_io_t *fptr;
1867 
1868  if (!RB_TYPE_P(io, T_FILE)) {
1869  return rb_funcall(io, id_flush, 0);
1870  }
1871 
1872  io = GetWriteIO(io);
1873  GetOpenFile(io, fptr);
1874 
1875  if (fptr->mode & FMODE_WRITABLE) {
1876  if (io_fflush(fptr) < 0)
1877  rb_sys_fail(0);
1878  }
1879  if (fptr->mode & FMODE_READABLE) {
1880  io_unread(fptr);
1881  }
1882 
1883  return io;
1884 }
1885 
1886 /*
1887  * call-seq:
1888  * ios.flush -> ios
1889  *
1890  * Flushes any buffered data within <em>ios</em> to the underlying
1891  * operating system (note that this is Ruby internal buffering only;
1892  * the OS may buffer the data as well).
1893  *
1894  * $stdout.print "no newline"
1895  * $stdout.flush
1896  *
1897  * <em>produces:</em>
1898  *
1899  * no newline
1900  */
1901 
1902 VALUE
1904 {
1905  return rb_io_flush_raw(io, 1);
1906 }
1907 
1908 /*
1909  * call-seq:
1910  * ios.pos -> integer
1911  * ios.tell -> integer
1912  *
1913  * Returns the current offset (in bytes) of <em>ios</em>.
1914  *
1915  * f = File.new("testfile")
1916  * f.pos #=> 0
1917  * f.gets #=> "This is line one\n"
1918  * f.pos #=> 17
1919  */
1920 
1921 static VALUE
1922 rb_io_tell(VALUE io)
1923 {
1924  rb_io_t *fptr;
1925  off_t pos;
1926 
1927  GetOpenFile(io, fptr);
1928  pos = io_tell(fptr);
1929  if (pos < 0 && errno) rb_sys_fail_path(fptr->pathv);
1930  pos -= fptr->rbuf.len;
1931  return OFFT2NUM(pos);
1932 }
1933 
1934 static VALUE
1935 rb_io_seek(VALUE io, VALUE offset, int whence)
1936 {
1937  rb_io_t *fptr;
1938  off_t pos;
1939 
1940  pos = NUM2OFFT(offset);
1941  GetOpenFile(io, fptr);
1942  pos = io_seek(fptr, pos, whence);
1943  if (pos < 0 && errno) rb_sys_fail_path(fptr->pathv);
1944 
1945  return INT2FIX(0);
1946 }
1947 
1948 static int
1949 interpret_seek_whence(VALUE vwhence)
1950 {
1951  if (vwhence == sym_SET)
1952  return SEEK_SET;
1953  if (vwhence == sym_CUR)
1954  return SEEK_CUR;
1955  if (vwhence == sym_END)
1956  return SEEK_END;
1957 #ifdef SEEK_DATA
1958  if (vwhence == sym_DATA)
1959  return SEEK_DATA;
1960 #endif
1961 #ifdef SEEK_HOLE
1962  if (vwhence == sym_HOLE)
1963  return SEEK_HOLE;
1964 #endif
1965  return NUM2INT(vwhence);
1966 }
1967 
1968 /*
1969  * call-seq:
1970  * ios.seek(amount, whence=IO::SEEK_SET) -> 0
1971  *
1972  * Seeks to a given offset <i>anInteger</i> in the stream according to
1973  * the value of <i>whence</i>:
1974  *
1975  * :CUR or IO::SEEK_CUR | Seeks to _amount_ plus current position
1976  * ----------------------+--------------------------------------------------
1977  * :END or IO::SEEK_END | Seeks to _amount_ plus end of stream (you
1978  * | probably want a negative value for _amount_)
1979  * ----------------------+--------------------------------------------------
1980  * :SET or IO::SEEK_SET | Seeks to the absolute location given by _amount_
1981  *
1982  * Example:
1983  *
1984  * f = File.new("testfile")
1985  * f.seek(-13, IO::SEEK_END) #=> 0
1986  * f.readline #=> "And so on...\n"
1987  */
1988 
1989 static VALUE
1990 rb_io_seek_m(int argc, VALUE *argv, VALUE io)
1991 {
1992  VALUE offset, ptrname;
1993  int whence = SEEK_SET;
1994 
1995  if (rb_scan_args(argc, argv, "11", &offset, &ptrname) == 2) {
1996  whence = interpret_seek_whence(ptrname);
1997  }
1998 
1999  return rb_io_seek(io, offset, whence);
2000 }
2001 
2002 /*
2003  * call-seq:
2004  * ios.pos = integer -> integer
2005  *
2006  * Seeks to the given position (in bytes) in <em>ios</em>.
2007  * It is not guaranteed that seeking to the right position when <em>ios</em>
2008  * is textmode.
2009  *
2010  * f = File.new("testfile")
2011  * f.pos = 17
2012  * f.gets #=> "This is line two\n"
2013  */
2014 
2015 static VALUE
2016 rb_io_set_pos(VALUE io, VALUE offset)
2017 {
2018  rb_io_t *fptr;
2019  off_t pos;
2020 
2021  pos = NUM2OFFT(offset);
2022  GetOpenFile(io, fptr);
2023  pos = io_seek(fptr, pos, SEEK_SET);
2024  if (pos < 0 && errno) rb_sys_fail_path(fptr->pathv);
2025 
2026  return OFFT2NUM(pos);
2027 }
2028 
2029 static void clear_readconv(rb_io_t *fptr);
2030 
2031 /*
2032  * call-seq:
2033  * ios.rewind -> 0
2034  *
2035  * Positions <em>ios</em> to the beginning of input, resetting
2036  * #lineno to zero.
2037  *
2038  * f = File.new("testfile")
2039  * f.readline #=> "This is line one\n"
2040  * f.rewind #=> 0
2041  * f.lineno #=> 0
2042  * f.readline #=> "This is line one\n"
2043  *
2044  * Note that it cannot be used with streams such as pipes, ttys, and sockets.
2045  */
2046 
2047 static VALUE
2048 rb_io_rewind(VALUE io)
2049 {
2050  rb_io_t *fptr;
2051 
2052  GetOpenFile(io, fptr);
2053  if (io_seek(fptr, 0L, 0) < 0 && errno) rb_sys_fail_path(fptr->pathv);
2054  if (io == ARGF.current_file) {
2055  ARGF.lineno -= fptr->lineno;
2056  }
2057  fptr->lineno = 0;
2058  if (fptr->readconv) {
2059  clear_readconv(fptr);
2060  }
2061 
2062  return INT2FIX(0);
2063 }
2064 
2065 static int
2066 fptr_wait_readable(rb_io_t *fptr)
2067 {
2068  int ret = rb_io_wait_readable(fptr->fd);
2069 
2070  if (ret)
2071  rb_io_check_closed(fptr);
2072  return ret;
2073 }
2074 
2075 static int
2076 io_fillbuf(rb_io_t *fptr)
2077 {
2078  ssize_t r;
2079 
2080  if (fptr->rbuf.ptr == NULL) {
2081  fptr->rbuf.off = 0;
2082  fptr->rbuf.len = 0;
2083  fptr->rbuf.capa = IO_RBUF_CAPA_FOR(fptr);
2084  fptr->rbuf.ptr = ALLOC_N(char, fptr->rbuf.capa);
2085 #ifdef _WIN32
2086  fptr->rbuf.capa--;
2087 #endif
2088  }
2089  if (fptr->rbuf.len == 0) {
2090  retry:
2091  {
2092  r = rb_read_internal(fptr->fd, fptr->rbuf.ptr, fptr->rbuf.capa);
2093  }
2094  if (r < 0) {
2095  if (fptr_wait_readable(fptr))
2096  goto retry;
2097  {
2098  int e = errno;
2099  VALUE path = rb_sprintf("fd:%d ", fptr->fd);
2100  if (!NIL_P(fptr->pathv)) {
2101  rb_str_append(path, fptr->pathv);
2102  }
2104  }
2105  }
2106  if (r > 0) rb_io_check_closed(fptr);
2107  fptr->rbuf.off = 0;
2108  fptr->rbuf.len = (int)r; /* r should be <= rbuf_capa */
2109  if (r == 0)
2110  return -1; /* EOF */
2111  }
2112  return 0;
2113 }
2114 
2115 /*
2116  * call-seq:
2117  * ios.eof -> true or false
2118  * ios.eof? -> true or false
2119  *
2120  * Returns true if <em>ios</em> is at end of file that means
2121  * there are no more data to read.
2122  * The stream must be opened for reading or an IOError will be
2123  * raised.
2124  *
2125  * f = File.new("testfile")
2126  * dummy = f.readlines
2127  * f.eof #=> true
2128  *
2129  * If <em>ios</em> is a stream such as pipe or socket, IO#eof?
2130  * blocks until the other end sends some data or closes it.
2131  *
2132  * r, w = IO.pipe
2133  * Thread.new { sleep 1; w.close }
2134  * r.eof? #=> true after 1 second blocking
2135  *
2136  * r, w = IO.pipe
2137  * Thread.new { sleep 1; w.puts "a" }
2138  * r.eof? #=> false after 1 second blocking
2139  *
2140  * r, w = IO.pipe
2141  * r.eof? # blocks forever
2142  *
2143  * Note that IO#eof? reads data to the input byte buffer. So
2144  * IO#sysread may not behave as you intend with IO#eof?, unless you
2145  * call IO#rewind first (which is not available for some streams).
2146  */
2147 
2148 VALUE
2150 {
2151  rb_io_t *fptr;
2152 
2153  GetOpenFile(io, fptr);
2155 
2156  if (READ_CHAR_PENDING(fptr)) return Qfalse;
2157  if (READ_DATA_PENDING(fptr)) return Qfalse;
2158  READ_CHECK(fptr);
2159 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
2160  if (!NEED_READCONV(fptr) && NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {
2161  return eof(fptr->fd) ? Qtrue : Qfalse;
2162  }
2163 #endif
2164  if (io_fillbuf(fptr) < 0) {
2165  return Qtrue;
2166  }
2167  return Qfalse;
2168 }
2169 
2170 /*
2171  * call-seq:
2172  * ios.sync -> true or false
2173  *
2174  * Returns the current ``sync mode'' of <em>ios</em>. When sync mode is
2175  * true, all output is immediately flushed to the underlying operating
2176  * system and is not buffered by Ruby internally. See also
2177  * IO#fsync.
2178  *
2179  * f = File.new("testfile")
2180  * f.sync #=> false
2181  */
2182 
2183 static VALUE
2184 rb_io_sync(VALUE io)
2185 {
2186  rb_io_t *fptr;
2187 
2188  io = GetWriteIO(io);
2189  GetOpenFile(io, fptr);
2190  return (fptr->mode & FMODE_SYNC) ? Qtrue : Qfalse;
2191 }
2192 
2193 #ifdef HAVE_FSYNC
2194 
2195 /*
2196  * call-seq:
2197  * ios.sync = boolean -> boolean
2198  *
2199  * Sets the ``sync mode'' to <code>true</code> or <code>false</code>.
2200  * When sync mode is true, all output is immediately flushed to the
2201  * underlying operating system and is not buffered internally. Returns
2202  * the new state. See also IO#fsync.
2203  *
2204  * f = File.new("testfile")
2205  * f.sync = true
2206  */
2207 
2208 static VALUE
2209 rb_io_set_sync(VALUE io, VALUE sync)
2210 {
2211  rb_io_t *fptr;
2212 
2213  io = GetWriteIO(io);
2214  GetOpenFile(io, fptr);
2215  if (RTEST(sync)) {
2216  fptr->mode |= FMODE_SYNC;
2217  }
2218  else {
2219  fptr->mode &= ~FMODE_SYNC;
2220  }
2221  return sync;
2222 }
2223 
2224 /*
2225  * call-seq:
2226  * ios.fsync -> 0 or nil
2227  *
2228  * Immediately writes all buffered data in <em>ios</em> to disk.
2229  * Note that #fsync differs from using IO#sync=. The latter ensures
2230  * that data is flushed from Ruby's buffers, but does not guarantee
2231  * that the underlying operating system actually writes it to disk.
2232  *
2233  * NotImplementedError is raised
2234  * if the underlying operating system does not support <em>fsync(2)</em>.
2235  */
2236 
2237 static VALUE
2238 rb_io_fsync(VALUE io)
2239 {
2240  rb_io_t *fptr;
2241 
2242  io = GetWriteIO(io);
2243  GetOpenFile(io, fptr);
2244 
2245  if (io_fflush(fptr) < 0)
2246  rb_sys_fail(0);
2247  if ((int)rb_thread_io_blocking_region(nogvl_fsync, fptr, fptr->fd) < 0)
2248  rb_sys_fail_path(fptr->pathv);
2249  return INT2FIX(0);
2250 }
2251 #else
2252 # define rb_io_fsync rb_f_notimplement
2253 # define rb_io_sync rb_f_notimplement
2254 static VALUE
2255 rb_io_set_sync(VALUE io, VALUE sync)
2256 {
2257  rb_notimplement();
2258  UNREACHABLE;
2259 }
2260 #endif
2261 
2262 #ifdef HAVE_FDATASYNC
2263 static VALUE
2264 nogvl_fdatasync(void *ptr)
2265 {
2266  rb_io_t *fptr = ptr;
2267 
2268 #ifdef _WIN32
2269  if (GetFileType((HANDLE)rb_w32_get_osfhandle(fptr->fd)) != FILE_TYPE_DISK)
2270  return 0;
2271 #endif
2272  return (VALUE)fdatasync(fptr->fd);
2273 }
2274 
2275 /*
2276  * call-seq:
2277  * ios.fdatasync -> 0 or nil
2278  *
2279  * Immediately writes all buffered data in <em>ios</em> to disk.
2280  *
2281  * If the underlying operating system does not support <em>fdatasync(2)</em>,
2282  * IO#fsync is called instead (which might raise a
2283  * NotImplementedError).
2284  */
2285 
2286 static VALUE
2288 {
2289  rb_io_t *fptr;
2290 
2291  io = GetWriteIO(io);
2292  GetOpenFile(io, fptr);
2293 
2294  if (io_fflush(fptr) < 0)
2295  rb_sys_fail(0);
2296 
2297  if ((int)rb_thread_io_blocking_region(nogvl_fdatasync, fptr, fptr->fd) == 0)
2298  return INT2FIX(0);
2299 
2300  /* fall back */
2301  return rb_io_fsync(io);
2302 }
2303 #else
2304 #define rb_io_fdatasync rb_io_fsync
2305 #endif
2306 
2307 /*
2308  * call-seq:
2309  * ios.fileno -> integer
2310  * ios.to_i -> integer
2311  *
2312  * Returns an integer representing the numeric file descriptor for
2313  * <em>ios</em>.
2314  *
2315  * $stdin.fileno #=> 0
2316  * $stdout.fileno #=> 1
2317  */
2318 
2319 static VALUE
2320 rb_io_fileno(VALUE io)
2321 {
2322  rb_io_t *fptr = RFILE(io)->fptr;
2323  int fd;
2324 
2325  rb_io_check_closed(fptr);
2326  fd = fptr->fd;
2327  return INT2FIX(fd);
2328 }
2329 
2330 
2331 /*
2332  * call-seq:
2333  * ios.pid -> integer
2334  *
2335  * Returns the process ID of a child process associated with
2336  * <em>ios</em>. This will be set by IO.popen.
2337  *
2338  * pipe = IO.popen("-")
2339  * if pipe
2340  * $stderr.puts "In parent, child pid is #{pipe.pid}"
2341  * else
2342  * $stderr.puts "In child, pid is #{$$}"
2343  * end
2344  *
2345  * <em>produces:</em>
2346  *
2347  * In child, pid is 26209
2348  * In parent, child pid is 26209
2349  */
2350 
2351 static VALUE
2352 rb_io_pid(VALUE io)
2353 {
2354  rb_io_t *fptr;
2355 
2356  GetOpenFile(io, fptr);
2357  if (!fptr->pid)
2358  return Qnil;
2359  return PIDT2NUM(fptr->pid);
2360 }
2361 
2362 
2363 /*
2364  * call-seq:
2365  * ios.inspect -> string
2366  *
2367  * Return a string describing this IO object.
2368  */
2369 
2370 static VALUE
2371 rb_io_inspect(VALUE obj)
2372 {
2373  rb_io_t *fptr;
2374  VALUE result;
2375  static const char closed[] = " (closed)";
2376 
2377  fptr = RFILE(obj)->fptr;
2378  if (!fptr) return rb_any_to_s(obj);
2379  result = rb_str_new_cstr("#<");
2381  rb_str_cat2(result, ":");
2382  if (NIL_P(fptr->pathv)) {
2383  if (fptr->fd < 0) {
2384  rb_str_cat(result, closed+1, strlen(closed)-1);
2385  }
2386  else {
2387  rb_str_catf(result, "fd %d", fptr->fd);
2388  }
2389  }
2390  else {
2391  rb_str_append(result, fptr->pathv);
2392  if (fptr->fd < 0) {
2393  rb_str_cat(result, closed, strlen(closed));
2394  }
2395  }
2396  return rb_str_cat2(result, ">");
2397 }
2398 
2399 /*
2400  * call-seq:
2401  * ios.to_io -> ios
2402  *
2403  * Returns <em>ios</em>.
2404  */
2405 
2406 static VALUE
2407 rb_io_to_io(VALUE io)
2408 {
2409  return io;
2410 }
2411 
2412 /* reading functions */
2413 static long
2414 read_buffered_data(char *ptr, long len, rb_io_t *fptr)
2415 {
2416  int n;
2417 
2418  n = READ_DATA_PENDING_COUNT(fptr);
2419  if (n <= 0) return 0;
2420  if (n > len) n = (int)len;
2421  MEMMOVE(ptr, fptr->rbuf.ptr+fptr->rbuf.off, char, n);
2422  fptr->rbuf.off += n;
2423  fptr->rbuf.len -= n;
2424  return n;
2425 }
2426 
2427 static long
2428 io_bufread(char *ptr, long len, rb_io_t *fptr)
2429 {
2430  long offset = 0;
2431  long n = len;
2432  long c;
2433 
2434  if (READ_DATA_PENDING(fptr) == 0) {
2435  while (n > 0) {
2436  again:
2437  c = rb_read_internal(fptr->fd, ptr+offset, n);
2438  if (c == 0) break;
2439  if (c < 0) {
2440  if (fptr_wait_readable(fptr))
2441  goto again;
2442  return -1;
2443  }
2444  offset += c;
2445  if ((n -= c) <= 0) break;
2446  }
2447  return len - n;
2448  }
2449 
2450  while (n > 0) {
2451  c = read_buffered_data(ptr+offset, n, fptr);
2452  if (c > 0) {
2453  offset += c;
2454  if ((n -= c) <= 0) break;
2455  }
2456  rb_io_check_closed(fptr);
2457  if (io_fillbuf(fptr) < 0) {
2458  break;
2459  }
2460  }
2461  return len - n;
2462 }
2463 
2464 static int io_setstrbuf(VALUE *str, long len);
2465 
2466 struct bufread_arg {
2467  char *str_ptr;
2468  long len;
2470 };
2471 
2472 static VALUE
2473 bufread_call(VALUE arg)
2474 {
2475  struct bufread_arg *p = (struct bufread_arg *)arg;
2476  p->len = io_bufread(p->str_ptr, p->len, p->fptr);
2477  return Qundef;
2478 }
2479 
2480 static long
2481 io_fread(VALUE str, long offset, long size, rb_io_t *fptr)
2482 {
2483  long len;
2484  struct bufread_arg arg;
2485 
2486  io_setstrbuf(&str, offset + size);
2487  arg.str_ptr = RSTRING_PTR(str) + offset;
2488  arg.len = size;
2489  arg.fptr = fptr;
2490  rb_str_locktmp_ensure(str, bufread_call, (VALUE)&arg);
2491  len = arg.len;
2492  if (len < 0) rb_sys_fail_path(fptr->pathv);
2493  return len;
2494 }
2495 
2496 static long
2497 remain_size(rb_io_t *fptr)
2498 {
2499  struct stat st;
2500  off_t siz = READ_DATA_PENDING_COUNT(fptr);
2501  off_t pos;
2502 
2503  if (fstat(fptr->fd, &st) == 0 && S_ISREG(st.st_mode)
2504 #if defined(__HAIKU__)
2505  && (st.st_dev > 3)
2506 #endif
2507  )
2508  {
2509  if (io_fflush(fptr) < 0)
2510  rb_sys_fail(0);
2511  pos = lseek(fptr->fd, 0, SEEK_CUR);
2512  if (st.st_size >= pos && pos >= 0) {
2513  siz += st.st_size - pos;
2514  if (siz > LONG_MAX) {
2515  rb_raise(rb_eIOError, "file too big for single read");
2516  }
2517  }
2518  }
2519  else {
2520  siz += BUFSIZ;
2521  }
2522  return (long)siz;
2523 }
2524 
2525 static VALUE
2526 io_enc_str(VALUE str, rb_io_t *fptr)
2527 {
2528  rb_enc_associate(str, io_read_encoding(fptr));
2529  return str;
2530 }
2531 
2532 static void
2533 make_readconv(rb_io_t *fptr, int size)
2534 {
2535  if (!fptr->readconv) {
2536  int ecflags;
2537  VALUE ecopts;
2538  const char *sname, *dname;
2539  ecflags = fptr->encs.ecflags & ~ECONV_NEWLINE_DECORATOR_WRITE_MASK;
2540  ecopts = fptr->encs.ecopts;
2541  if (fptr->encs.enc2) {
2542  sname = rb_enc_name(fptr->encs.enc2);
2543  dname = rb_enc_name(fptr->encs.enc);
2544  }
2545  else {
2546  sname = dname = "";
2547  }
2548  fptr->readconv = rb_econv_open_opts(sname, dname, ecflags, ecopts);
2549  if (!fptr->readconv)
2550  rb_exc_raise(rb_econv_open_exc(sname, dname, ecflags));
2551  fptr->cbuf.off = 0;
2552  fptr->cbuf.len = 0;
2554  fptr->cbuf.capa = size;
2555  fptr->cbuf.ptr = ALLOC_N(char, fptr->cbuf.capa);
2556  }
2557 }
2558 
2559 #define MORE_CHAR_SUSPENDED Qtrue
2560 #define MORE_CHAR_FINISHED Qnil
2561 static VALUE
2562 fill_cbuf(rb_io_t *fptr, int ec_flags)
2563 {
2564  const unsigned char *ss, *sp, *se;
2565  unsigned char *ds, *dp, *de;
2566  rb_econv_result_t res;
2567  int putbackable;
2568  int cbuf_len0;
2569  VALUE exc;
2570 
2571  ec_flags |= ECONV_PARTIAL_INPUT;
2572 
2573  if (fptr->cbuf.len == fptr->cbuf.capa)
2574  return MORE_CHAR_SUSPENDED; /* cbuf full */
2575  if (fptr->cbuf.len == 0)
2576  fptr->cbuf.off = 0;
2577  else if (fptr->cbuf.off + fptr->cbuf.len == fptr->cbuf.capa) {
2578  memmove(fptr->cbuf.ptr, fptr->cbuf.ptr+fptr->cbuf.off, fptr->cbuf.len);
2579  fptr->cbuf.off = 0;
2580  }
2581 
2582  cbuf_len0 = fptr->cbuf.len;
2583 
2584  while (1) {
2585  ss = sp = (const unsigned char *)fptr->rbuf.ptr + fptr->rbuf.off;
2586  se = sp + fptr->rbuf.len;
2587  ds = dp = (unsigned char *)fptr->cbuf.ptr + fptr->cbuf.off + fptr->cbuf.len;
2588  de = (unsigned char *)fptr->cbuf.ptr + fptr->cbuf.capa;
2589  res = rb_econv_convert(fptr->readconv, &sp, se, &dp, de, ec_flags);
2590  fptr->rbuf.off += (int)(sp - ss);
2591  fptr->rbuf.len -= (int)(sp - ss);
2592  fptr->cbuf.len += (int)(dp - ds);
2593 
2594  putbackable = rb_econv_putbackable(fptr->readconv);
2595  if (putbackable) {
2596  rb_econv_putback(fptr->readconv, (unsigned char *)fptr->rbuf.ptr + fptr->rbuf.off - putbackable, putbackable);
2597  fptr->rbuf.off -= putbackable;
2598  fptr->rbuf.len += putbackable;
2599  }
2600 
2602  if (!NIL_P(exc))
2603  return exc;
2604 
2605  if (cbuf_len0 != fptr->cbuf.len)
2606  return MORE_CHAR_SUSPENDED;
2607 
2608  if (res == econv_finished) {
2609  return MORE_CHAR_FINISHED;
2610  }
2611 
2612  if (res == econv_source_buffer_empty) {
2613  if (fptr->rbuf.len == 0) {
2614  READ_CHECK(fptr);
2615  if (io_fillbuf(fptr) < 0) {
2616  if (!fptr->readconv) {
2617  return MORE_CHAR_FINISHED;
2618  }
2619  ds = dp = (unsigned char *)fptr->cbuf.ptr + fptr->cbuf.off + fptr->cbuf.len;
2620  de = (unsigned char *)fptr->cbuf.ptr + fptr->cbuf.capa;
2621  res = rb_econv_convert(fptr->readconv, NULL, NULL, &dp, de, 0);
2622  fptr->cbuf.len += (int)(dp - ds);
2624  break;
2625  }
2626  }
2627  }
2628  }
2629  if (cbuf_len0 != fptr->cbuf.len)
2630  return MORE_CHAR_SUSPENDED;
2631 
2632  return MORE_CHAR_FINISHED;
2633 }
2634 
2635 static VALUE
2636 more_char(rb_io_t *fptr)
2637 {
2638  VALUE v;
2639  v = fill_cbuf(fptr, ECONV_AFTER_OUTPUT);
2641  rb_exc_raise(v);
2642  return v;
2643 }
2644 
2645 static VALUE
2646 io_shift_cbuf(rb_io_t *fptr, int len, VALUE *strp)
2647 {
2648  VALUE str = Qnil;
2649  if (strp) {
2650  str = *strp;
2651  if (NIL_P(str)) {
2652  *strp = str = rb_str_new(fptr->cbuf.ptr+fptr->cbuf.off, len);
2653  }
2654  else {
2655  rb_str_cat(str, fptr->cbuf.ptr+fptr->cbuf.off, len);
2656  }
2657  rb_enc_associate(str, fptr->encs.enc);
2658  }
2659  fptr->cbuf.off += len;
2660  fptr->cbuf.len -= len;
2661  /* xxx: set coderange */
2662  if (fptr->cbuf.len == 0)
2663  fptr->cbuf.off = 0;
2664  else if (fptr->cbuf.capa/2 < fptr->cbuf.off) {
2665  memmove(fptr->cbuf.ptr, fptr->cbuf.ptr+fptr->cbuf.off, fptr->cbuf.len);
2666  fptr->cbuf.off = 0;
2667  }
2668  return str;
2669 }
2670 
2671 static int
2672 io_setstrbuf(VALUE *str, long len)
2673 {
2674 #ifdef _WIN32
2675  len = (len + 1) & ~1L; /* round up for wide char */
2676 #endif
2677  if (NIL_P(*str)) {
2678  *str = rb_str_new(0, len);
2679  return TRUE;
2680  }
2681  else {
2682  VALUE s = StringValue(*str);
2683  long clen = RSTRING_LEN(s);
2684  if (clen >= len) {
2685  rb_str_modify(s);
2686  return FALSE;
2687  }
2688  len -= clen;
2689  }
2691  return FALSE;
2692 }
2693 
2694 #define MAX_REALLOC_GAP 4096
2695 static void
2696 io_shrink_read_string(VALUE str, long n)
2697 {
2698  if (rb_str_capacity(str) - n > MAX_REALLOC_GAP) {
2699  rb_str_resize(str, n);
2700  }
2701 }
2702 
2703 static void
2704 io_set_read_length(VALUE str, long n, int shrinkable)
2705 {
2706  if (RSTRING_LEN(str) != n) {
2707  rb_str_modify(str);
2708  rb_str_set_len(str, n);
2709  if (shrinkable) io_shrink_read_string(str, n);
2710  }
2711 }
2712 
2713 static VALUE
2714 read_all(rb_io_t *fptr, long siz, VALUE str)
2715 {
2716  long bytes;
2717  long n;
2718  long pos;
2719  rb_encoding *enc;
2720  int cr;
2721  int shrinkable;
2722 
2723  if (NEED_READCONV(fptr)) {
2724  int first = !NIL_P(str);
2725  SET_BINARY_MODE(fptr);
2726  shrinkable = io_setstrbuf(&str,0);
2727  make_readconv(fptr, 0);
2728  while (1) {
2729  VALUE v;
2730  if (fptr->cbuf.len) {
2731  if (first) rb_str_set_len(str, first = 0);
2732  io_shift_cbuf(fptr, fptr->cbuf.len, &str);
2733  }
2734  v = fill_cbuf(fptr, 0);
2735  if (v != MORE_CHAR_SUSPENDED && v != MORE_CHAR_FINISHED) {
2736  if (fptr->cbuf.len) {
2737  if (first) rb_str_set_len(str, first = 0);
2738  io_shift_cbuf(fptr, fptr->cbuf.len, &str);
2739  }
2740  rb_exc_raise(v);
2741  }
2742  if (v == MORE_CHAR_FINISHED) {
2743  clear_readconv(fptr);
2744  if (first) rb_str_set_len(str, first = 0);
2745  if (shrinkable) io_shrink_read_string(str, RSTRING_LEN(str));
2746  return io_enc_str(str, fptr);
2747  }
2748  }
2749  }
2750 
2752  bytes = 0;
2753  pos = 0;
2754 
2755  enc = io_read_encoding(fptr);
2756  cr = 0;
2757 
2758  if (siz == 0) siz = BUFSIZ;
2759  shrinkable = io_setstrbuf(&str, siz);
2760  for (;;) {
2761  READ_CHECK(fptr);
2762  n = io_fread(str, bytes, siz - bytes, fptr);
2763  if (n == 0 && bytes == 0) {
2764  rb_str_set_len(str, 0);
2765  break;
2766  }
2767  bytes += n;
2768  rb_str_set_len(str, bytes);
2769  if (cr != ENC_CODERANGE_BROKEN)
2770  pos += rb_str_coderange_scan_restartable(RSTRING_PTR(str) + pos, RSTRING_PTR(str) + bytes, enc, &cr);
2771  if (bytes < siz) break;
2772  siz += BUFSIZ;
2774  }
2775  if (shrinkable) io_shrink_read_string(str, RSTRING_LEN(str));
2776  str = io_enc_str(str, fptr);
2777  ENC_CODERANGE_SET(str, cr);
2778  return str;
2779 }
2780 
2781 void
2783 {
2784  if (rb_fd_set_nonblock(fptr->fd) != 0) {
2785  rb_sys_fail_path(fptr->pathv);
2786  }
2787 }
2788 
2789 static VALUE
2790 read_internal_call(VALUE arg)
2791 {
2792  struct io_internal_read_struct *iis = (struct io_internal_read_struct *)arg;
2793 
2794  return rb_thread_io_blocking_region(internal_read_func, iis, iis->fd);
2795 }
2796 
2797 static long
2798 read_internal_locktmp(VALUE str, struct io_internal_read_struct *iis)
2799 {
2800  return (long)rb_str_locktmp_ensure(str, read_internal_call, (VALUE)iis);
2801 }
2802 
2803 #define no_exception_p(opts) !rb_opts_exception_p((opts), TRUE)
2804 
2805 static VALUE
2806 io_getpartial(int argc, VALUE *argv, VALUE io, int no_exception, int nonblock)
2807 {
2808  rb_io_t *fptr;
2809  VALUE length, str;
2810  long n, len;
2811  struct io_internal_read_struct iis;
2812  int shrinkable;
2813 
2814  rb_scan_args(argc, argv, "11", &length, &str);
2815 
2816  if ((len = NUM2LONG(length)) < 0) {
2817  rb_raise(rb_eArgError, "negative length %ld given", len);
2818  }
2819 
2820  shrinkable = io_setstrbuf(&str, len);
2821 
2822  GetOpenFile(io, fptr);
2824 
2825  if (len == 0)
2826  return str;
2827 
2828  if (!nonblock)
2829  READ_CHECK(fptr);
2830  n = read_buffered_data(RSTRING_PTR(str), len, fptr);
2831  if (n <= 0) {
2832  again:
2833  if (nonblock) {
2834  rb_io_set_nonblock(fptr);
2835  }
2836  io_setstrbuf(&str, len);
2837  iis.fd = fptr->fd;
2838  iis.nonblock = nonblock;
2839  iis.buf = RSTRING_PTR(str);
2840  iis.capa = len;
2841  n = read_internal_locktmp(str, &iis);
2842  if (n < 0) {
2843  int e = errno;
2844  if (!nonblock && fptr_wait_readable(fptr))
2845  goto again;
2846  if (nonblock && (e == EWOULDBLOCK || e == EAGAIN)) {
2847  if (no_exception)
2848  return sym_wait_readable;
2849  else
2851  e, "read would block");
2852  }
2853  rb_syserr_fail_path(e, fptr->pathv);
2854  }
2855  }
2856  io_set_read_length(str, n, shrinkable);
2857 
2858  if (n == 0)
2859  return Qnil;
2860  else
2861  return str;
2862 }
2863 
2864 /*
2865  * call-seq:
2866  * ios.readpartial(maxlen) -> string
2867  * ios.readpartial(maxlen, outbuf) -> outbuf
2868  *
2869  * Reads at most <i>maxlen</i> bytes from the I/O stream.
2870  * It blocks only if <em>ios</em> has no data immediately available.
2871  * It doesn't block if some data available.
2872  *
2873  * If the optional _outbuf_ argument is present,
2874  * it must reference a String, which will receive the data.
2875  * The _outbuf_ will contain only the received data after the method call
2876  * even if it is not empty at the beginning.
2877  *
2878  * It raises EOFError on end of file.
2879  *
2880  * readpartial is designed for streams such as pipe, socket, tty, etc.
2881  * It blocks only when no data immediately available.
2882  * This means that it blocks only when following all conditions hold.
2883  * * the byte buffer in the IO object is empty.
2884  * * the content of the stream is empty.
2885  * * the stream is not reached to EOF.
2886  *
2887  * When readpartial blocks, it waits data or EOF on the stream.
2888  * If some data is reached, readpartial returns with the data.
2889  * If EOF is reached, readpartial raises EOFError.
2890  *
2891  * When readpartial doesn't blocks, it returns or raises immediately.
2892  * If the byte buffer is not empty, it returns the data in the buffer.
2893  * Otherwise if the stream has some content,
2894  * it returns the data in the stream.
2895  * Otherwise if the stream is reached to EOF, it raises EOFError.
2896  *
2897  * r, w = IO.pipe # buffer pipe content
2898  * w << "abc" # "" "abc".
2899  * r.readpartial(4096) #=> "abc" "" ""
2900  * r.readpartial(4096) # blocks because buffer and pipe is empty.
2901  *
2902  * r, w = IO.pipe # buffer pipe content
2903  * w << "abc" # "" "abc"
2904  * w.close # "" "abc" EOF
2905  * r.readpartial(4096) #=> "abc" "" EOF
2906  * r.readpartial(4096) # raises EOFError
2907  *
2908  * r, w = IO.pipe # buffer pipe content
2909  * w << "abc\ndef\n" # "" "abc\ndef\n"
2910  * r.gets #=> "abc\n" "def\n" ""
2911  * w << "ghi\n" # "def\n" "ghi\n"
2912  * r.readpartial(4096) #=> "def\n" "" "ghi\n"
2913  * r.readpartial(4096) #=> "ghi\n" "" ""
2914  *
2915  * Note that readpartial behaves similar to sysread.
2916  * The differences are:
2917  * * If the byte buffer is not empty, read from the byte buffer
2918  * instead of "sysread for buffered IO (IOError)".
2919  * * It doesn't cause Errno::EWOULDBLOCK and Errno::EINTR. When
2920  * readpartial meets EWOULDBLOCK and EINTR by read system call,
2921  * readpartial retry the system call.
2922  *
2923  * The latter means that readpartial is nonblocking-flag insensitive.
2924  * It blocks on the situation IO#sysread causes Errno::EWOULDBLOCK as
2925  * if the fd is blocking mode.
2926  *
2927  */
2928 
2929 static VALUE
2930 io_readpartial(int argc, VALUE *argv, VALUE io)
2931 {
2932  VALUE ret;
2933 
2934  ret = io_getpartial(argc, argv, io, Qnil, 0);
2935  if (NIL_P(ret))
2936  rb_eof_error();
2937  return ret;
2938 }
2939 
2940 static VALUE
2941 io_nonblock_eof(int no_exception)
2942 {
2943  if (!no_exception) {
2944  rb_eof_error();
2945  }
2946  return Qnil;
2947 }
2948 
2949 /* :nodoc: */
2950 static VALUE
2951 io_read_nonblock(rb_execution_context_t *ec, VALUE io, VALUE length, VALUE str, VALUE ex)
2952 {
2953  rb_io_t *fptr;
2954  long n, len;
2955  struct io_internal_read_struct iis;
2956  int shrinkable;
2957 
2958  if ((len = NUM2LONG(length)) < 0) {
2959  rb_raise(rb_eArgError, "negative length %ld given", len);
2960  }
2961 
2962  shrinkable = io_setstrbuf(&str, len);
2963  rb_bool_expected(ex, "exception");
2964 
2965  GetOpenFile(io, fptr);
2967 
2968  if (len == 0)
2969  return str;
2970 
2971  n = read_buffered_data(RSTRING_PTR(str), len, fptr);
2972  if (n <= 0) {
2973  rb_io_set_nonblock(fptr);
2974  shrinkable |= io_setstrbuf(&str, len);
2975  iis.fd = fptr->fd;
2976  iis.nonblock = 1;
2977  iis.buf = RSTRING_PTR(str);
2978  iis.capa = len;
2979  n = read_internal_locktmp(str, &iis);
2980  if (n < 0) {
2981  int e = errno;
2982  if ((e == EWOULDBLOCK || e == EAGAIN)) {
2983  if (!ex) return sym_wait_readable;
2985  e, "read would block");
2986  }
2987  rb_syserr_fail_path(e, fptr->pathv);
2988  }
2989  }
2990  io_set_read_length(str, n, shrinkable);
2991 
2992  if (n == 0) {
2993  if (!ex) return Qnil;
2994  rb_eof_error();
2995  }
2996 
2997  return str;
2998 }
2999 
3000 /* :nodoc: */
3001 static VALUE
3002 io_write_nonblock(rb_execution_context_t *ec, VALUE io, VALUE str, VALUE ex)
3003 {
3004  rb_io_t *fptr;
3005  long n;
3006 
3007  if (!RB_TYPE_P(str, T_STRING))
3009  rb_bool_expected(ex, "exception");
3010 
3011  io = GetWriteIO(io);
3012  GetOpenFile(io, fptr);
3013  rb_io_check_writable(fptr);
3014 
3015  if (io_fflush(fptr) < 0)
3016  rb_sys_fail(0);
3017 
3018  rb_io_set_nonblock(fptr);
3019  n = write(fptr->fd, RSTRING_PTR(str), RSTRING_LEN(str));
3020  RB_GC_GUARD(str);
3021 
3022  if (n < 0) {
3023  int e = errno;
3024  if (e == EWOULDBLOCK || e == EAGAIN) {
3025  if (!ex) {
3026  return sym_wait_writable;
3027  }
3028  else {
3029  rb_readwrite_syserr_fail(RB_IO_WAIT_WRITABLE, e, "write would block");
3030  }
3031  }
3032  rb_syserr_fail_path(e, fptr->pathv);
3033  }
3034 
3035  return LONG2FIX(n);
3036 }
3037 
3038 /*
3039  * call-seq:
3040  * ios.read([length [, outbuf]]) -> string, outbuf, or nil
3041  *
3042  * Reads _length_ bytes from the I/O stream.
3043  *
3044  * _length_ must be a non-negative integer or +nil+.
3045  *
3046  * If _length_ is a positive integer, +read+ tries to read
3047  * _length_ bytes without any conversion (binary mode).
3048  * It returns +nil+ if an EOF is encountered before anything can be read.
3049  * Fewer than _length_ bytes are returned if an EOF is encountered during
3050  * the read.
3051  * In the case of an integer _length_, the resulting string is always
3052  * in ASCII-8BIT encoding.
3053  *
3054  * If _length_ is omitted or is +nil+, it reads until EOF
3055  * and the encoding conversion is applied, if applicable.
3056  * A string is returned even if EOF is encountered before any data is read.
3057  *
3058  * If _length_ is zero, it returns an empty string (<code>""</code>).
3059  *
3060  * If the optional _outbuf_ argument is present,
3061  * it must reference a String, which will receive the data.
3062  * The _outbuf_ will contain only the received data after the method call
3063  * even if it is not empty at the beginning.
3064  *
3065  * When this method is called at end of file, it returns +nil+
3066  * or <code>""</code>, depending on _length_:
3067  * +read+, <code>read(nil)</code>, and <code>read(0)</code> return
3068  * <code>""</code>,
3069  * <code>read(<i>positive_integer</i>)</code> returns +nil+.
3070  *
3071  * f = File.new("testfile")
3072  * f.read(16) #=> "This is line one"
3073  *
3074  * # read whole file
3075  * open("file") do |f|
3076  * data = f.read # This returns a string even if the file is empty.
3077  * # ...
3078  * end
3079  *
3080  * # iterate over fixed length records
3081  * open("fixed-record-file") do |f|
3082  * while record = f.read(256)
3083  * # ...
3084  * end
3085  * end
3086  *
3087  * # iterate over variable length records,
3088  * # each record is prefixed by its 32-bit length
3089  * open("variable-record-file") do |f|
3090  * while len = f.read(4)
3091  * len = len.unpack("N")[0] # 32-bit length
3092  * record = f.read(len) # This returns a string even if len is 0.
3093  * end
3094  * end
3095  *
3096  * Note that this method behaves like the fread() function in C.
3097  * This means it retries to invoke read(2) system calls to read data
3098  * with the specified length (or until EOF).
3099  * This behavior is preserved even if <i>ios</i> is in non-blocking mode.
3100  * (This method is non-blocking flag insensitive as other methods.)
3101  * If you need the behavior like a single read(2) system call,
3102  * consider #readpartial, #read_nonblock, and #sysread.
3103  */
3104 
3105 static VALUE
3106 io_read(int argc, VALUE *argv, VALUE io)
3107 {
3108  rb_io_t *fptr;
3109  long n, len;
3110  VALUE length, str;
3111  int shrinkable;
3112 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
3113  int previous_mode;
3114 #endif
3115 
3116  rb_scan_args(argc, argv, "02", &length, &str);
3117 
3118  if (NIL_P(length)) {
3119  GetOpenFile(io, fptr);
3121  return read_all(fptr, remain_size(fptr), str);
3122  }
3123  len = NUM2LONG(length);
3124  if (len < 0) {
3125  rb_raise(rb_eArgError, "negative length %ld given", len);
3126  }
3127 
3128  shrinkable = io_setstrbuf(&str,len);
3129 
3130  GetOpenFile(io, fptr);
3132  if (len == 0) {
3133  io_set_read_length(str, 0, shrinkable);
3134  return str;
3135  }
3136 
3137  READ_CHECK(fptr);
3138 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
3139  previous_mode = set_binary_mode_with_seek_cur(fptr);
3140 #endif
3141  n = io_fread(str, 0, len, fptr);
3142  io_set_read_length(str, n, shrinkable);
3143 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
3144  if (previous_mode == O_TEXT) {
3145  setmode(fptr->fd, O_TEXT);
3146  }
3147 #endif
3148  if (n == 0) return Qnil;
3149 
3150  return str;
3151 }
3152 
3153 static void
3154 rscheck(const char *rsptr, long rslen, VALUE rs)
3155 {
3156  if (!rs) return;
3157  if (RSTRING_PTR(rs) != rsptr && RSTRING_LEN(rs) != rslen)
3158  rb_raise(rb_eRuntimeError, "rs modified");
3159 }
3160 
3161 static int
3162 appendline(rb_io_t *fptr, int delim, VALUE *strp, long *lp)
3163 {
3164  VALUE str = *strp;
3165  long limit = *lp;
3166 
3167  if (NEED_READCONV(fptr)) {
3168  SET_BINARY_MODE(fptr);
3169  make_readconv(fptr, 0);
3170  do {
3171  const char *p, *e;
3172  int searchlen = READ_CHAR_PENDING_COUNT(fptr);
3173  if (searchlen) {
3174  p = READ_CHAR_PENDING_PTR(fptr);
3175  if (0 < limit && limit < searchlen)
3176  searchlen = (int)limit;
3177  e = memchr(p, delim, searchlen);
3178  if (e) {
3179  int len = (int)(e-p+1);
3180  if (NIL_P(str))
3181  *strp = str = rb_str_new(p, len);
3182  else
3183  rb_str_buf_cat(str, p, len);
3184  fptr->cbuf.off += len;
3185  fptr->cbuf.len -= len;
3186  limit -= len;
3187  *lp = limit;
3188  return delim;
3189  }
3190 
3191  if (NIL_P(str))
3192  *strp = str = rb_str_new(p, searchlen);
3193  else
3194  rb_str_buf_cat(str, p, searchlen);
3195  fptr->cbuf.off += searchlen;
3196  fptr->cbuf.len -= searchlen;
3197  limit -= searchlen;
3198 
3199  if (limit == 0) {
3200  *lp = limit;
3201  return (unsigned char)RSTRING_PTR(str)[RSTRING_LEN(str)-1];
3202  }
3203  }
3204  } while (more_char(fptr) != MORE_CHAR_FINISHED);
3205  clear_readconv(fptr);
3206  *lp = limit;
3207  return EOF;
3208  }
3209 
3211  do {
3212  long pending = READ_DATA_PENDING_COUNT(fptr);
3213  if (pending > 0) {
3214  const char *p = READ_DATA_PENDING_PTR(fptr);
3215  const char *e;
3216  long last;
3217 
3218  if (limit > 0 && pending > limit) pending = limit;
3219  e = memchr(p, delim, pending);
3220  if (e) pending = e - p + 1;
3221  if (!NIL_P(str)) {
3222  last = RSTRING_LEN(str);
3223  rb_str_resize(str, last + pending);
3224  }
3225  else {
3226  last = 0;
3227  *strp = str = rb_str_buf_new(pending);
3228  rb_str_set_len(str, pending);
3229  }
3230  read_buffered_data(RSTRING_PTR(str) + last, pending, fptr); /* must not fail */
3231  limit -= pending;
3232  *lp = limit;
3233  if (e) return delim;
3234  if (limit == 0)
3235  return (unsigned char)RSTRING_PTR(str)[RSTRING_LEN(str)-1];
3236  }
3237  READ_CHECK(fptr);
3238  } while (io_fillbuf(fptr) >= 0);
3239  *lp = limit;
3240  return EOF;
3241 }
3242 
3243 static inline int
3244 swallow(rb_io_t *fptr, int term)
3245 {
3246  if (NEED_READCONV(fptr)) {
3247  rb_encoding *enc = io_read_encoding(fptr);
3248  int needconv = rb_enc_mbminlen(enc) != 1;
3249  SET_BINARY_MODE(fptr);
3250  make_readconv(fptr, 0);
3251  do {
3252  size_t cnt;
3253  while ((cnt = READ_CHAR_PENDING_COUNT(fptr)) > 0) {
3254  const char *p = READ_CHAR_PENDING_PTR(fptr);
3255  int i;
3256  if (!needconv) {
3257  if (*p != term) return TRUE;
3258  i = (int)cnt;
3259  while (--i && *++p == term);
3260  }
3261  else {
3262  const char *e = p + cnt;
3263  if (rb_enc_ascget(p, e, &i, enc) != term) return TRUE;
3264  while ((p += i) < e && rb_enc_ascget(p, e, &i, enc) == term);
3265  i = (int)(e - p);
3266  }
3267  io_shift_cbuf(fptr, (int)cnt - i, NULL);
3268  }
3269  } while (more_char(fptr) != MORE_CHAR_FINISHED);
3270  return FALSE;
3271  }
3272 
3274  do {
3275  size_t cnt;
3276  while ((cnt = READ_DATA_PENDING_COUNT(fptr)) > 0) {
3277  char buf[1024];
3278  const char *p = READ_DATA_PENDING_PTR(fptr);
3279  int i;
3280  if (cnt > sizeof buf) cnt = sizeof buf;
3281  if (*p != term) return TRUE;
3282  i = (int)cnt;
3283  while (--i && *++p == term);
3284  if (!read_buffered_data(buf, cnt - i, fptr)) /* must not fail */
3285  rb_sys_fail_path(fptr->pathv);
3286  }
3287  READ_CHECK(fptr);
3288  } while (io_fillbuf(fptr) == 0);
3289  return FALSE;
3290 }
3291 
3292 static VALUE
3293 rb_io_getline_fast(rb_io_t *fptr, rb_encoding *enc, int chomp)
3294 {
3295  VALUE str = Qnil;
3296  int len = 0;
3297  long pos = 0;
3298  int cr = 0;
3299 
3300  do {
3301  int pending = READ_DATA_PENDING_COUNT(fptr);
3302 
3303  if (pending > 0) {
3304  const char *p = READ_DATA_PENDING_PTR(fptr);
3305  const char *e;
3306  int chomplen = 0;
3307 
3308  e = memchr(p, '\n', pending);
3309  if (e) {
3310  pending = (int)(e - p + 1);
3311  if (chomp) {
3312  chomplen = (pending > 1 && *(e-1) == '\r') + 1;
3313  }
3314  }
3315  if (NIL_P(str)) {
3316  str = rb_str_new(p, pending - chomplen);
3317  fptr->rbuf.off += pending;
3318  fptr->rbuf.len -= pending;
3319  }
3320  else {
3321  rb_str_resize(str, len + pending - chomplen);
3322  read_buffered_data(RSTRING_PTR(str)+len, pending - chomplen, fptr);
3323  fptr->rbuf.off += chomplen;
3324  fptr->rbuf.len -= chomplen;
3325  if (pending == 1 && chomplen == 1 && len > 0) {
3326  if (RSTRING_PTR(str)[len-1] == '\r') {
3327  rb_str_resize(str, --len);
3328  break;
3329  }
3330  }
3331  }
3332  len += pending - chomplen;
3333  if (cr != ENC_CODERANGE_BROKEN)
3334  pos += rb_str_coderange_scan_restartable(RSTRING_PTR(str) + pos, RSTRING_PTR(str) + len, enc, &cr);
3335  if (e) break;
3336  }
3337  READ_CHECK(fptr);
3338  } while (io_fillbuf(fptr) >= 0);
3339  if (NIL_P(str)) return Qnil;
3340 
3341  str = io_enc_str(str, fptr);
3342  ENC_CODERANGE_SET(str, cr);
3343  fptr->lineno++;
3344 
3345  return str;
3346 }
3347 
3348 struct getline_arg {
3350  VALUE rs;
3351  long limit;
3352  unsigned int chomp: 1;
3353 };
3354 
3355 static void
3356 extract_getline_opts(VALUE opts, struct getline_arg *args)
3357 {
3358  int chomp = FALSE;
3359  if (!NIL_P(opts)) {
3360  static ID kwds[1];
3361  VALUE vchomp;
3362  if (!kwds[0]) {
3363  kwds[0] = rb_intern_const("chomp");
3364  }
3365  rb_get_kwargs(opts, kwds, 0, -2, &vchomp);
3366  chomp = (vchomp != Qundef) && RTEST(vchomp);
3367  }
3368  args->chomp = chomp;
3369 }
3370 
3371 static void
3372 extract_getline_args(int argc, VALUE *argv, struct getline_arg *args)
3373 {
3374  VALUE rs = rb_rs, lim = Qnil;
3375 
3376  if (argc == 1) {
3377  VALUE tmp = Qnil;
3378 
3379  if (NIL_P(argv[0]) || !NIL_P(tmp = rb_check_string_type(argv[0]))) {
3380  rs = tmp;
3381  }
3382  else {
3383  lim = argv[0];
3384  }
3385  }
3386  else if (2 <= argc) {
3387  rs = argv[0], lim = argv[1];
3388  if (!NIL_P(rs))
3389  StringValue(rs);
3390  }
3391  args->rs = rs;
3392  args->limit = NIL_P(lim) ? -1L : NUM2LONG(lim);
3393 }
3394 
3395 static void
3396 check_getline_args(VALUE *rsp, long *limit, VALUE io)
3397 {
3398  rb_io_t *fptr;
3399  VALUE rs = *rsp;
3400 
3401  if (!NIL_P(rs)) {
3402  rb_encoding *enc_rs, *enc_io;
3403 
3404  GetOpenFile(io, fptr);
3405  enc_rs = rb_enc_get(rs);
3406  enc_io = io_read_encoding(fptr);
3407  if (enc_io != enc_rs &&
3409  (RSTRING_LEN(rs) > 0 && !rb_enc_asciicompat(enc_io)))) {
3410  if (rs == rb_default_rs) {
3411  rs = rb_enc_str_new(0, 0, enc_io);
3412  rb_str_buf_cat_ascii(rs, "\n");
3413  *rsp = rs;
3414  }
3415  else {
3416  rb_raise(rb_eArgError, "encoding mismatch: %s IO with %s RS",
3417  rb_enc_name(enc_io),
3418  rb_enc_name(enc_rs));
3419  }
3420  }
3421  }
3422 }
3423 
3424 static void
3425 prepare_getline_args(int argc, VALUE *argv, struct getline_arg *args, VALUE io)
3426 {
3427  VALUE opts;
3428  argc = rb_scan_args(argc, argv, "02:", NULL, NULL, &opts);
3429  extract_getline_args(argc, argv, args);
3430  extract_getline_opts(opts, args);
3431  check_getline_args(&args->rs, &args->limit, io);
3432 }
3433 
3434 static VALUE
3435 rb_io_getline_0(VALUE rs, long limit, int chomp, rb_io_t *fptr)
3436 {
3437  VALUE str = Qnil;
3438  int nolimit = 0;
3439  rb_encoding *enc;
3440 
3442  if (NIL_P(rs) && limit < 0) {
3443  str = read_all(fptr, 0, Qnil);
3444  if (RSTRING_LEN(str) == 0) return Qnil;
3445  if (chomp) rb_str_chomp_string(str, rb_default_rs);
3446  }
3447  else if (limit == 0) {
3448  return rb_enc_str_new(0, 0, io_read_encoding(fptr));
3449  }
3450  else if (rs == rb_default_rs && limit < 0 && !NEED_READCONV(fptr) &&
3451  rb_enc_asciicompat(enc = io_read_encoding(fptr))) {
3453  return rb_io_getline_fast(fptr, enc, chomp);
3454  }
3455  else {
3456  int c, newline = -1;
3457  const char *rsptr = 0;
3458  long rslen = 0;
3459  int rspara = 0;
3460  int extra_limit = 16;
3461  int chomp_cr = chomp;
3462 
3463  SET_BINARY_MODE(fptr);
3464  enc = io_read_encoding(fptr);
3465 
3466  if (!NIL_P(rs)) {
3467  rslen = RSTRING_LEN(rs);
3468  if (rslen == 0) {
3469  rsptr = "\n\n";
3470  rslen = 2;
3471  rspara = 1;
3472  swallow(fptr, '\n');
3473  rs = 0;
3474  if (!rb_enc_asciicompat(enc)) {
3475  rs = rb_usascii_str_new(rsptr, rslen);
3476  rs = rb_str_encode(rs, rb_enc_from_encoding(enc), 0, Qnil);
3477  OBJ_FREEZE(rs);
3478  rsptr = RSTRING_PTR(rs);
3479  rslen = RSTRING_LEN(rs);
3480  }
3481  }
3482  else {
3483  rsptr = RSTRING_PTR(rs);
3484  }
3485  newline = (unsigned char)rsptr[rslen - 1];
3486  chomp_cr = chomp && rslen == 1 && newline == '\n';
3487  }
3488 
3489  /* MS - Optimization */
3490  while ((c = appendline(fptr, newline, &str, &limit)) != EOF) {
3491  const char *s, *p, *pp, *e;
3492 
3493  if (c == newline) {
3494  if (RSTRING_LEN(str) < rslen) continue;
3495  s = RSTRING_PTR(str);
3496  e = RSTRING_END(str);
3497  p = e - rslen;
3498  pp = rb_enc_left_char_head(s, p, e, enc);
3499  if (pp != p) continue;
3500  if (!rspara) rscheck(rsptr, rslen, rs);
3501  if (memcmp(p, rsptr, rslen) == 0) {
3502  if (chomp) {
3503  if (chomp_cr && p > s && *(p-1) == '\r') --p;
3504  rb_str_set_len(str, p - s);
3505  }
3506  break;
3507  }
3508  }
3509  if (limit == 0) {
3510  s = RSTRING_PTR(str);
3511  p = RSTRING_END(str);
3512  pp = rb_enc_left_char_head(s, p-1, p, enc);
3513  if (extra_limit &&
3515  /* relax the limit while incomplete character.
3516  * extra_limit limits the relax length */
3517  limit = 1;
3518  extra_limit--;
3519  }
3520  else {
3521  nolimit = 1;
3522  break;
3523  }
3524  }
3525  }
3526 
3527  if (rspara && c != EOF)
3528  swallow(fptr, '\n');
3529  if (!NIL_P(str))
3530  str = io_enc_str(str, fptr);
3531  }
3532 
3533  if (!NIL_P(str) && !nolimit) {
3534  fptr->lineno++;
3535  }
3536 
3537  return str;
3538 }
3539 
3540 static VALUE
3541 rb_io_getline_1(VALUE rs, long limit, int chomp, VALUE io)
3542 {
3543  rb_io_t *fptr;
3544  int old_lineno, new_lineno;
3545  VALUE str;
3546 
3547  GetOpenFile(io, fptr);
3548  old_lineno = fptr->lineno;
3549  str = rb_io_getline_0(rs, limit, chomp, fptr);
3550  if (!NIL_P(str) && (new_lineno = fptr->lineno) != old_lineno) {
3551  if (io == ARGF.current_file) {
3552  ARGF.lineno += new_lineno - old_lineno;
3553  ARGF.last_lineno = ARGF.lineno;
3554  }
3555  else {
3556  ARGF.last_lineno = new_lineno;
3557  }
3558  }
3559 
3560  return str;
3561 }
3562 
3563 static VALUE
3564 rb_io_getline(int argc, VALUE *argv, VALUE io)
3565 {
3566  struct getline_arg args;
3567 
3568  prepare_getline_args(argc, argv, &args, io);
3569  return rb_io_getline_1(args.rs, args.limit, args.chomp, io);
3570 }
3571 
3572 VALUE
3574 {
3575  return rb_io_getline_1(rb_default_rs, -1, FALSE, io);
3576 }
3577 
3578 VALUE
3580 {
3581  rb_io_t *fptr;
3582  GetOpenFile(io, fptr);
3583  return rb_io_getline_0(rb_default_rs, -1, FALSE, fptr);
3584 }
3585 
3586 /*
3587  * call-seq:
3588  * ios.gets(sep=$/ [, getline_args]) -> string or nil
3589  * ios.gets(limit [, getline_args]) -> string or nil
3590  * ios.gets(sep, limit [, getline_args]) -> string or nil
3591  *
3592  * Reads the next ``line'' from the I/O stream; lines are separated by
3593  * <i>sep</i>. A separator of +nil+ reads the entire
3594  * contents, and a zero-length separator reads the input a paragraph at
3595  * a time (two successive newlines in the input separate paragraphs).
3596  * The stream must be opened for reading or an IOError will be raised.
3597  * The line read in will be returned and also assigned to
3598  * <code>$_</code>. Returns +nil+ if called at end of file. If the
3599  * first argument is an integer, or optional second argument is given,
3600  * the returning string would not be longer than the given value in
3601  * bytes.
3602  *
3603  * File.new("testfile").gets #=> "This is line one\n"
3604  * $_ #=> "This is line one\n"
3605  *
3606  * File.new("testfile").gets(4)#=> "This"
3607  *
3608  * If IO contains multibyte characters byte then <code>gets(1)</code>
3609  * returns character entirely:
3610  *
3611  * # Russian characters take 2 bytes
3612  * File.write("testfile", "\u{442 435 441 442}")
3613  * File.open("testfile") {|f|f.gets(1)} #=> "\u0442"
3614  * File.open("testfile") {|f|f.gets(2)} #=> "\u0442"
3615  * File.open("testfile") {|f|f.gets(3)} #=> "\u0442\u0435"
3616  * File.open("testfile") {|f|f.gets(4)} #=> "\u0442\u0435"
3617  */
3618 
3619 static VALUE
3620 rb_io_gets_m(int argc, VALUE *argv, VALUE io)
3621 {
3622  VALUE str;
3623 
3624  str = rb_io_getline(argc, argv, io);
3626 
3627  return str;
3628 }
3629 
3630 /*
3631  * call-seq:
3632  * ios.lineno -> integer
3633  *
3634  * Returns the current line number in <em>ios</em>. The stream must be
3635  * opened for reading. #lineno counts the number of times #gets is called
3636  * rather than the number of newlines encountered. The two values will
3637  * differ if #gets is called with a separator other than newline.
3638  *
3639  * Methods that use <code>$/</code> like #each, #lines and #readline will
3640  * also increment #lineno.
3641  *
3642  * See also the <code>$.</code> variable.
3643  *
3644  * f = File.new("testfile")
3645  * f.lineno #=> 0
3646  * f.gets #=> "This is line one\n"
3647  * f.lineno #=> 1
3648  * f.gets #=> "This is line two\n"
3649  * f.lineno #=> 2
3650  */
3651 
3652 static VALUE
3653 rb_io_lineno(VALUE io)
3654 {
3655  rb_io_t *fptr;
3656 
3657  GetOpenFile(io, fptr);
3659  return INT2NUM(fptr->lineno);
3660 }
3661 
3662 /*
3663  * call-seq:
3664  * ios.lineno = integer -> integer
3665  *
3666  * Manually sets the current line number to the given value.
3667  * <code>$.</code> is updated only on the next read.
3668  *
3669  * f = File.new("testfile")
3670  * f.gets #=> "This is line one\n"
3671  * $. #=> 1
3672  * f.lineno = 1000
3673  * f.lineno #=> 1000
3674  * $. #=> 1 # lineno of last read
3675  * f.gets #=> "This is line two\n"
3676  * $. #=> 1001 # lineno of last read
3677  */
3678 
3679 static VALUE
3680 rb_io_set_lineno(VALUE io, VALUE lineno)
3681 {
3682  rb_io_t *fptr;
3683 
3684  GetOpenFile(io, fptr);
3686  fptr->lineno = NUM2INT(lineno);
3687  return lineno;
3688 }
3689 
3690 /*
3691  * call-seq:
3692  * ios.readline(sep=$/ [, getline_args]) -> string
3693  * ios.readline(limit [, getline_args]) -> string
3694  * ios.readline(sep, limit [, getline_args]) -> string
3695  *
3696  * Reads a line as with IO#gets, but raises an EOFError on end of file.
3697  */
3698 
3699 static VALUE
3700 rb_io_readline(int argc, VALUE *argv, VALUE io)
3701 {
3702  VALUE line = rb_io_gets_m(argc, argv, io);
3703 
3704  if (NIL_P(line)) {
3705  rb_eof_error();
3706  }
3707  return line;
3708 }
3709 
3710 static VALUE io_readlines(const struct getline_arg *arg, VALUE io);
3711 
3712 /*
3713  * call-seq:
3714  * ios.readlines(sep=$/ [, getline_args]) -> array
3715  * ios.readlines(limit [, getline_args]) -> array
3716  * ios.readlines(sep, limit [, getline_args]) -> array
3717  *
3718  * Reads all of the lines in <em>ios</em>, and returns them in
3719  * an array. Lines are separated by the optional <i>sep</i>. If
3720  * <i>sep</i> is +nil+, the rest of the stream is returned
3721  * as a single record.
3722  * If the first argument is an integer, or an
3723  * optional second argument is given, the returning string would not be
3724  * longer than the given value in bytes. The stream must be opened for
3725  * reading or an IOError will be raised.
3726  *
3727  * f = File.new("testfile")
3728  * f.readlines[0] #=> "This is line one\n"
3729  *
3730  * f = File.new("testfile", chomp: true)
3731  * f.readlines[0] #=> "This is line one"
3732  *
3733  * See IO.readlines for details about getline_args.
3734  */
3735 
3736 static VALUE
3737 rb_io_readlines(int argc, VALUE *argv, VALUE io)
3738 {
3739  struct getline_arg args;
3740 
3741  prepare_getline_args(argc, argv, &args, io);
3742  return io_readlines(&args, io);
3743 }
3744 
3745 static VALUE
3746 io_readlines(const struct getline_arg *arg, VALUE io)
3747 {
3748  VALUE line, ary;
3749 
3750  if (arg->limit == 0)
3751  rb_raise(rb_eArgError, "invalid limit: 0 for readlines");
3752  ary = rb_ary_new();
3753  while (!NIL_P(line = rb_io_getline_1(arg->rs, arg->limit, arg->chomp, io))) {
3754  rb_ary_push(ary, line);
3755  }
3756  return ary;
3757 }
3758 
3759 /*
3760  * call-seq:
3761  * ios.each(sep=$/ [, getline_args]) {|line| block } -> ios
3762  * ios.each(limit [, getline_args]) {|line| block } -> ios
3763  * ios.each(sep, limit [, getline_args]) {|line| block } -> ios
3764  * ios.each(...) -> an_enumerator
3765  *
3766  * ios.each_line(sep=$/ [, getline_args]) {|line| block } -> ios
3767  * ios.each_line(limit [, getline_args]) {|line| block } -> ios
3768  * ios.each_line(sep, limit [, getline_args]) {|line| block } -> ios
3769  * ios.each_line(...) -> an_enumerator
3770  *
3771  * Executes the block for every line in <em>ios</em>, where lines are
3772  * separated by <i>sep</i>. <em>ios</em> must be opened for
3773  * reading or an IOError will be raised.
3774  *
3775  * If no block is given, an enumerator is returned instead.
3776  *
3777  * f = File.new("testfile")
3778  * f.each {|line| puts "#{f.lineno}: #{line}" }
3779  *
3780  * <em>produces:</em>
3781  *
3782  * 1: This is line one
3783  * 2: This is line two
3784  * 3: This is line three
3785  * 4: And so on...
3786  *
3787  * See IO.readlines for details about getline_args.
3788  */
3789 
3790 static VALUE
3791 rb_io_each_line(int argc, VALUE *argv, VALUE io)
3792 {
3793  VALUE str;
3794  struct getline_arg args;
3795 
3797  prepare_getline_args(argc, argv, &args, io);
3798  if (args.limit == 0)
3799  rb_raise(rb_eArgError, "invalid limit: 0 for each_line");
3800  while (!NIL_P(str = rb_io_getline_1(args.rs, args.limit, args.chomp, io))) {
3801  rb_yield(str);
3802  }
3803  return io;
3804 }
3805 
3806 /*
3807  * This is a deprecated alias for #each_line.
3808  */
3809 
3810 static VALUE
3811 rb_io_lines(int argc, VALUE *argv, VALUE io)
3812 {
3813  rb_warn_deprecated("IO#lines", "#each_line");
3814  if (!rb_block_given_p())
3815  return rb_enumeratorize(io, ID2SYM(rb_intern("each_line")), argc, argv);
3816  return rb_io_each_line(argc, argv, io);
3817 }
3818 
3819 /*
3820  * call-seq:
3821  * ios.each_byte {|byte| block } -> ios
3822  * ios.each_byte -> an_enumerator
3823  *
3824  * Calls the given block once for each byte (0..255) in <em>ios</em>,
3825  * passing the byte as an argument. The stream must be opened for
3826  * reading or an IOError will be raised.
3827  *
3828  * If no block is given, an enumerator is returned instead.
3829  *
3830  * f = File.new("testfile")
3831  * checksum = 0
3832  * f.each_byte {|x| checksum ^= x } #=> #<File:testfile>
3833  * checksum #=> 12
3834  */
3835 
3836 static VALUE
3837 rb_io_each_byte(VALUE io)
3838 {
3839  rb_io_t *fptr;
3840 
3841  RETURN_ENUMERATOR(io, 0, 0);
3842  GetOpenFile(io, fptr);
3843 
3844  do {
3845  while (fptr->rbuf.len > 0) {
3846  char *p = fptr->rbuf.ptr + fptr->rbuf.off++;
3847  fptr->rbuf.len--;
3848  rb_yield(INT2FIX(*p & 0xff));
3849  errno = 0;
3850  }
3852  READ_CHECK(fptr);
3853  } while (io_fillbuf(fptr) >= 0);
3854  return io;
3855 }
3856 
3857 /*
3858  * This is a deprecated alias for #each_byte.
3859  */
3860 
3861 static VALUE
3862 rb_io_bytes(VALUE io)
3863 {
3864  rb_warn_deprecated("IO#bytes", "#each_byte");
3865  if (!rb_block_given_p())
3866  return rb_enumeratorize(io, ID2SYM(rb_intern("each_byte")), 0, 0);
3867  return rb_io_each_byte(io);
3868 }
3869 
3870 static VALUE
3871 io_getc(rb_io_t *fptr, rb_encoding *enc)
3872 {
3873  int r, n, cr = 0;
3874  VALUE str;
3875 
3876  if (NEED_READCONV(fptr)) {
3877  rb_encoding *read_enc = io_read_encoding(fptr);
3878 
3879  str = Qnil;
3880  SET_BINARY_MODE(fptr);
3881  make_readconv(fptr, 0);
3882 
3883  while (1) {
3884  if (fptr->cbuf.len) {
3885  r = rb_enc_precise_mbclen(fptr->cbuf.ptr+fptr->cbuf.off,
3886  fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
3887  read_enc);
3888  if (!MBCLEN_NEEDMORE_P(r))
3889  break;
3890  if (fptr->cbuf.len == fptr->cbuf.capa) {
3891  rb_raise(rb_eIOError, "too long character");
3892  }
3893  }
3894 
3895  if (more_char(fptr) == MORE_CHAR_FINISHED) {
3896  if (fptr->cbuf.len == 0) {
3897  clear_readconv(fptr);
3898  return Qnil;
3899  }
3900  /* return an unit of an incomplete character just before EOF */
3901  str = rb_enc_str_new(fptr->cbuf.ptr+fptr->cbuf.off, 1, read_enc);
3902  fptr->cbuf.off += 1;
3903  fptr->cbuf.len -= 1;
3904  if (fptr->cbuf.len == 0) clear_readconv(fptr);
3906  return str;
3907  }
3908  }
3909  if (MBCLEN_INVALID_P(r)) {
3910  r = rb_enc_mbclen(fptr->cbuf.ptr+fptr->cbuf.off,
3911  fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
3912  read_enc);
3913  io_shift_cbuf(fptr, r, &str);
3914  cr = ENC_CODERANGE_BROKEN;
3915  }
3916  else {
3917  io_shift_cbuf(fptr, MBCLEN_CHARFOUND_LEN(r), &str);
3918  cr = ENC_CODERANGE_VALID;
3919  if (MBCLEN_CHARFOUND_LEN(r) == 1 && rb_enc_asciicompat(read_enc) &&
3920  ISASCII(RSTRING_PTR(str)[0])) {
3921  cr = ENC_CODERANGE_7BIT;
3922  }
3923  }
3924  str = io_enc_str(str, fptr);
3925  ENC_CODERANGE_SET(str, cr);
3926  return str;
3927  }
3928 
3930  if (io_fillbuf(fptr) < 0) {
3931  return Qnil;
3932  }
3933  if (rb_enc_asciicompat(enc) && ISASCII(fptr->rbuf.ptr[fptr->rbuf.off])) {
3934  str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, 1);
3935  fptr->rbuf.off += 1;
3936  fptr->rbuf.len -= 1;
3937  cr = ENC_CODERANGE_7BIT;
3938  }
3939  else {
3940  r = rb_enc_precise_mbclen(fptr->rbuf.ptr+fptr->rbuf.off, fptr->rbuf.ptr+fptr->rbuf.off+fptr->rbuf.len, enc);
3941  if (MBCLEN_CHARFOUND_P(r) &&
3942  (n = MBCLEN_CHARFOUND_LEN(r)) <= fptr->rbuf.len) {
3943  str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, n);
3944  fptr->rbuf.off += n;
3945  fptr->rbuf.len -= n;
3946  cr = ENC_CODERANGE_VALID;
3947  }
3948  else if (MBCLEN_NEEDMORE_P(r)) {
3949  str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, fptr->rbuf.len);
3950  fptr->rbuf.len = 0;
3951  getc_needmore:
3952  if (io_fillbuf(fptr) != -1) {
3953  rb_str_cat(str, fptr->rbuf.ptr+fptr->rbuf.off, 1);
3954  fptr->rbuf.off++;
3955  fptr->rbuf.len--;
3957  if (MBCLEN_NEEDMORE_P(r)) {
3958  goto getc_needmore;
3959  }
3960  else if (MBCLEN_CHARFOUND_P(r)) {
3961  cr = ENC_CODERANGE_VALID;
3962  }
3963  }
3964  }
3965  else {
3966  str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, 1);
3967  fptr->rbuf.off++;
3968  fptr->rbuf.len--;
3969  }
3970  }
3971  if (!cr) cr = ENC_CODERANGE_BROKEN;
3972  str = io_enc_str(str, fptr);
3973  ENC_CODERANGE_SET(str, cr);
3974  return str;
3975 }
3976 
3977 /*
3978  * call-seq:
3979  * ios.each_char {|c| block } -> ios
3980  * ios.each_char -> an_enumerator
3981  *
3982  * Calls the given block once for each character in <em>ios</em>,
3983  * passing the character as an argument. The stream must be opened for
3984  * reading or an IOError will be raised.
3985  *
3986  * If no block is given, an enumerator is returned instead.
3987  *
3988  * f = File.new("testfile")
3989  * f.each_char {|c| print c, ' ' } #=> #<File:testfile>
3990  */
3991 
3992 static VALUE
3993 rb_io_each_char(VALUE io)
3994 {
3995  rb_io_t *fptr;
3996  rb_encoding *enc;
3997  VALUE c;
3998 
3999  RETURN_ENUMERATOR(io, 0, 0);
4000  GetOpenFile(io, fptr);
4002 
4003  enc = io_input_encoding(fptr);
4004  READ_CHECK(fptr);
4005  while (!NIL_P(c = io_getc(fptr, enc))) {
4006  rb_yield(c);
4007  }
4008  return io;
4009 }
4010 
4011 /*
4012  * This is a deprecated alias for #each_char.
4013  */
4014 
4015 static VALUE
4016 rb_io_chars(VALUE io)
4017 {
4018  rb_warn_deprecated("IO#chars", "#each_char");
4019  if (!rb_block_given_p())
4020  return rb_enumeratorize(io, ID2SYM(rb_intern("each_char")), 0, 0);
4021  return rb_io_each_char(io);
4022 }
4023 
4024 
4025 /*
4026  * call-seq:
4027  * ios.each_codepoint {|c| block } -> ios
4028  * ios.codepoints {|c| block } -> ios
4029  * ios.each_codepoint -> an_enumerator
4030  * ios.codepoints -> an_enumerator
4031  *
4032  * Passes the Integer ordinal of each character in <i>ios</i>,
4033  * passing the codepoint as an argument. The stream must be opened for
4034  * reading or an IOError will be raised.
4035  *
4036  * If no block is given, an enumerator is returned instead.
4037  *
4038  */
4039 
4040 static VALUE
4041 rb_io_each_codepoint(VALUE io)
4042 {
4043  rb_io_t *fptr;
4044  rb_encoding *enc;
4045  unsigned int c;
4046  int r, n;
4047 
4048  RETURN_ENUMERATOR(io, 0, 0);
4049  GetOpenFile(io, fptr);
4051 
4052  READ_CHECK(fptr);
4053  if (NEED_READCONV(fptr)) {
4054  SET_BINARY_MODE(fptr);
4055  r = 1; /* no invalid char yet */
4056  for (;;) {
4057  make_readconv(fptr, 0);
4058  for (;;) {
4059  if (fptr->cbuf.len) {
4060  if (fptr->encs.enc)
4061  r = rb_enc_precise_mbclen(fptr->cbuf.ptr+fptr->cbuf.off,
4062  fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
4063  fptr->encs.enc);
4064  else
4066  if (!MBCLEN_NEEDMORE_P(r))
4067  break;
4068  if (fptr->cbuf.len == fptr->cbuf.capa) {
4069  rb_raise(rb_eIOError, "too long character");
4070  }
4071  }
4072  if (more_char(fptr) == MORE_CHAR_FINISHED) {
4073  clear_readconv(fptr);
4074  if (!MBCLEN_CHARFOUND_P(r)) {
4075  enc = fptr->encs.enc;
4076  goto invalid;
4077  }
4078  return io;
4079  }
4080  }
4081  if (MBCLEN_INVALID_P(r)) {
4082  enc = fptr->encs.enc;
4083  goto invalid;
4084  }
4085  n = MBCLEN_CHARFOUND_LEN(r);
4086  if (fptr->encs.enc) {
4087  c = rb_enc_codepoint(fptr->cbuf.ptr+fptr->cbuf.off,
4088  fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
4089  fptr->encs.enc);
4090  }
4091  else {
4092  c = (unsigned char)fptr->cbuf.ptr[fptr->cbuf.off];
4093  }
4094  fptr->cbuf.off += n;
4095  fptr->cbuf.len -= n;
4096  rb_yield(UINT2NUM(c));
4097  }
4098  }
4100  enc = io_input_encoding(fptr);
4101  while (io_fillbuf(fptr) >= 0) {
4102  r = rb_enc_precise_mbclen(fptr->rbuf.ptr+fptr->rbuf.off,
4103  fptr->rbuf.ptr+fptr->rbuf.off+fptr->rbuf.len, enc);
4104  if (MBCLEN_CHARFOUND_P(r) &&
4105  (n = MBCLEN_CHARFOUND_LEN(r)) <= fptr->rbuf.len) {
4106  c = rb_enc_codepoint(fptr->rbuf.ptr+fptr->rbuf.off,
4107  fptr->rbuf.ptr+fptr->rbuf.off+fptr->rbuf.len, enc);
4108  fptr->rbuf.off += n;
4109  fptr->rbuf.len -= n;
4110  rb_yield(UINT2NUM(c));
4111  }
4112  else if (MBCLEN_INVALID_P(r)) {
4113  invalid:
4114  rb_raise(rb_eArgError, "invalid byte sequence in %s", rb_enc_name(enc));
4115  }
4116  else if (MBCLEN_NEEDMORE_P(r)) {
4117  char cbuf[8], *p = cbuf;
4118  int more = MBCLEN_NEEDMORE_LEN(r);
4119  if (more > numberof(cbuf)) goto invalid;
4120  more += n = fptr->rbuf.len;
4121  if (more > numberof(cbuf)) goto invalid;
4122  while ((n = (int)read_buffered_data(p, more, fptr)) > 0 &&
4123  (p += n, (more -= n) > 0)) {
4124  if (io_fillbuf(fptr) < 0) goto invalid;
4125  if ((n = fptr->rbuf.len) > more) n = more;
4126  }
4127  r = rb_enc_precise_mbclen(cbuf, p, enc);
4128  if (!MBCLEN_CHARFOUND_P(r)) goto invalid;
4129  c = rb_enc_codepoint(cbuf, p, enc);
4130  rb_yield(UINT2NUM(c));
4131  }
4132  else {
4133  continue;
4134  }
4135  }
4136  return io;
4137 }
4138 
4139 /*
4140  * This is a deprecated alias for #each_codepoint.
4141  */
4142 
4143 static VALUE
4144 rb_io_codepoints(VALUE io)
4145 {
4146  rb_warn_deprecated("IO#codepoints", "#each_codepoint");
4147  if (!rb_block_given_p())
4148  return rb_enumeratorize(io, ID2SYM(rb_intern("each_codepoint")), 0, 0);
4149  return rb_io_each_codepoint(io);
4150 }
4151 
4152 
4153 /*
4154  * call-seq:
4155  * ios.getc -> string or nil
4156  *
4157  * Reads a one-character string from <em>ios</em>. Returns
4158  * +nil+ if called at end of file.
4159  *
4160  * f = File.new("testfile")
4161  * f.getc #=> "h"
4162  * f.getc #=> "e"
4163  */
4164 
4165 static VALUE
4166 rb_io_getc(VALUE io)
4167 {
4168  rb_io_t *fptr;
4169  rb_encoding *enc;
4170 
4171  GetOpenFile(io, fptr);
4173 
4174  enc = io_input_encoding(fptr);
4175  READ_CHECK(fptr);
4176  return io_getc(fptr, enc);
4177 }
4178 
4179 /*
4180  * call-seq:
4181  * ios.readchar -> string
4182  *
4183  * Reads a one-character string from <em>ios</em>. Raises an
4184  * EOFError on end of file.
4185  *
4186  * f = File.new("testfile")
4187  * f.readchar #=> "h"
4188  * f.readchar #=> "e"
4189  */
4190 
4191 static VALUE
4192 rb_io_readchar(VALUE io)
4193 {
4194  VALUE c = rb_io_getc(io);
4195 
4196  if (NIL_P(c)) {
4197  rb_eof_error();
4198  }
4199  return c;
4200 }
4201 
4202 /*
4203  * call-seq:
4204  * ios.getbyte -> integer or nil
4205  *
4206  * Gets the next 8-bit byte (0..255) from <em>ios</em>. Returns
4207  * +nil+ if called at end of file.
4208  *
4209  * f = File.new("testfile")
4210  * f.getbyte #=> 84
4211  * f.getbyte #=> 104
4212  */
4213 
4214 VALUE
4216 {
4217  rb_io_t *fptr;
4218  int c;
4219 
4220  GetOpenFile(io, fptr);
4222  READ_CHECK(fptr);
4223  if (fptr->fd == 0 && (fptr->mode & FMODE_TTY) && RB_TYPE_P(rb_stdout, T_FILE)) {
4224  rb_io_t *ofp;
4225  GetOpenFile(rb_stdout, ofp);
4226  if (ofp->mode & FMODE_TTY) {
4228  }
4229  }
4230  if (io_fillbuf(fptr) < 0) {
4231  return Qnil;
4232  }
4233  fptr->rbuf.off++;
4234  fptr->rbuf.len--;
4235  c = (unsigned char)fptr->rbuf.ptr[fptr->rbuf.off-1];
4236  return INT2FIX(c & 0xff);
4237 }
4238 
4239 /*
4240  * call-seq:
4241  * ios.readbyte -> integer
4242  *
4243  * Reads a byte as with IO#getbyte, but raises an EOFError on end of
4244  * file.
4245  */
4246 
4247 static VALUE
4248 rb_io_readbyte(VALUE io)
4249 {
4250  VALUE c = rb_io_getbyte(io);
4251 
4252  if (NIL_P(c)) {
4253  rb_eof_error();
4254  }
4255  return c;
4256 }
4257 
4258 /*
4259  * call-seq:
4260  * ios.ungetbyte(string) -> nil
4261  * ios.ungetbyte(integer) -> nil
4262  *
4263  * Pushes back bytes (passed as a parameter) onto <em>ios</em>,
4264  * such that a subsequent buffered read will return it. Only one byte
4265  * may be pushed back before a subsequent read operation (that is,
4266  * you will be able to read only the last of several bytes that have been pushed
4267  * back). Has no effect with unbuffered reads (such as IO#sysread).
4268  *
4269  * f = File.new("testfile") #=> #<File:testfile>
4270  * b = f.getbyte #=> 0x38
4271  * f.ungetbyte(b) #=> nil
4272  * f.getbyte #=> 0x38
4273  */
4274 
4275 VALUE
4277 {
4278  rb_io_t *fptr;
4279 
4280  GetOpenFile(io, fptr);
4282  switch (TYPE(b)) {
4283  case T_NIL:
4284  return Qnil;
4285  case T_FIXNUM:
4286  case T_BIGNUM: ;
4287  VALUE v = rb_int_modulo(b, INT2FIX(256));
4288  unsigned char c = NUM2INT(v) & 0xFF;
4289  b = rb_str_new((const char *)&c, 1);
4290  break;
4291  default:
4292  SafeStringValue(b);
4293  }
4294  io_ungetbyte(b, fptr);
4295  return Qnil;
4296 }
4297 
4298 /*
4299  * call-seq:
4300  * ios.ungetc(string) -> nil
4301  *
4302  * Pushes back one character (passed as a parameter) onto <em>ios</em>,
4303  * such that a subsequent buffered character read will return it. Only one character
4304  * may be pushed back before a subsequent read operation (that is,
4305  * you will be able to read only the last of several characters that have been pushed
4306  * back). Has no effect with unbuffered reads (such as IO#sysread).
4307  *
4308  * f = File.new("testfile") #=> #<File:testfile>
4309  * c = f.getc #=> "8"
4310  * f.ungetc(c) #=> nil
4311  * f.getc #=> "8"
4312  */
4313 
4314 VALUE
4316 {
4317  rb_io_t *fptr;
4318  long len;
4319 
4320  GetOpenFile(io, fptr);
4322  if (NIL_P(c)) return Qnil;
4323  if (FIXNUM_P(c)) {
4324  c = rb_enc_uint_chr(FIX2UINT(c), io_read_encoding(fptr));
4325  }
4326  else if (RB_TYPE_P(c, T_BIGNUM)) {
4327  c = rb_enc_uint_chr(NUM2UINT(c), io_read_encoding(fptr));
4328  }
4329  else {
4330  SafeStringValue(c);
4331  }
4332  if (NEED_READCONV(fptr)) {
4333  SET_BINARY_MODE(fptr);
4334  len = RSTRING_LEN(c);
4335 #if SIZEOF_LONG > SIZEOF_INT
4336  if (len > INT_MAX)
4337  rb_raise(rb_eIOError, "ungetc failed");
4338 #endif
4339  make_readconv(fptr, (int)len);
4340  if (fptr->cbuf.capa - fptr->cbuf.len < len)
4341  rb_raise(rb_eIOError, "ungetc failed");
4342  if (fptr->cbuf.off < len) {
4343  MEMMOVE(fptr->cbuf.ptr+fptr->cbuf.capa-fptr->cbuf.len,
4344  fptr->cbuf.ptr+fptr->cbuf.off,
4345  char, fptr->cbuf.len);
4346  fptr->cbuf.off = fptr->cbuf.capa-fptr->cbuf.len;
4347  }
4348  fptr->cbuf.off -= (int)len;
4349  fptr->cbuf.len += (int)len;
4350  MEMMOVE(fptr->cbuf.ptr+fptr->cbuf.off, RSTRING_PTR(c), char, len);
4351  }
4352  else {
4354  io_ungetbyte(c, fptr);
4355  }
4356  return Qnil;
4357 }
4358 
4359 /*
4360  * call-seq:
4361  * ios.isatty -> true or false
4362  * ios.tty? -> true or false
4363  *
4364  * Returns <code>true</code> if <em>ios</em> is associated with a
4365  * terminal device (tty), <code>false</code> otherwise.
4366  *
4367  * File.new("testfile").isatty #=> false
4368  * File.new("/dev/tty").isatty #=> true
4369  */
4370 
4371 static VALUE
4372 rb_io_isatty(VALUE io)
4373 {
4374  rb_io_t *fptr;
4375 
4376  GetOpenFile(io, fptr);
4377  if (isatty(fptr->fd) == 0)
4378  return Qfalse;
4379  return Qtrue;
4380 }
4381 
4382 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
4383 /*
4384  * call-seq:
4385  * ios.close_on_exec? -> true or false
4386  *
4387  * Returns <code>true</code> if <em>ios</em> will be closed on exec.
4388  *
4389  * f = open("/dev/null")
4390  * f.close_on_exec? #=> false
4391  * f.close_on_exec = true
4392  * f.close_on_exec? #=> true
4393  * f.close_on_exec = false
4394  * f.close_on_exec? #=> false
4395  */
4396 
4397 static VALUE
4399 {
4400  rb_io_t *fptr;
4401  VALUE write_io;
4402  int fd, ret;
4403 
4404  write_io = GetWriteIO(io);
4405  if (io != write_io) {
4406  GetOpenFile(write_io, fptr);
4407  if (fptr && 0 <= (fd = fptr->fd)) {
4408  if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
4409  if (!(ret & FD_CLOEXEC)) return Qfalse;
4410  }
4411  }
4412 
4413  GetOpenFile(io, fptr);
4414  if (fptr && 0 <= (fd = fptr->fd)) {
4415  if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
4416  if (!(ret & FD_CLOEXEC)) return Qfalse;
4417  }
4418  return Qtrue;
4419 }
4420 #else
4421 #define rb_io_close_on_exec_p rb_f_notimplement
4422 #endif
4423 
4424 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
4425 /*
4426  * call-seq:
4427  * ios.close_on_exec = bool -> true or false
4428  *
4429  * Sets a close-on-exec flag.
4430  *
4431  * f = open("/dev/null")
4432  * f.close_on_exec = true
4433  * system("cat", "/proc/self/fd/#{f.fileno}") # cat: /proc/self/fd/3: No such file or directory
4434  * f.closed? #=> false
4435  *
4436  * Ruby sets close-on-exec flags of all file descriptors by default
4437  * since Ruby 2.0.0.
4438  * So you don't need to set by yourself.
4439  * Also, unsetting a close-on-exec flag can cause file descriptor leak
4440  * if another thread use fork() and exec() (via system() method for example).
4441  * If you really needs file descriptor inheritance to child process,
4442  * use spawn()'s argument such as fd=>fd.
4443  */
4444 
4445 static VALUE
4447 {
4448  int flag = RTEST(arg) ? FD_CLOEXEC : 0;
4449  rb_io_t *fptr;
4450  VALUE write_io;
4451  int fd, ret;
4452 
4453  write_io = GetWriteIO(io);
4454  if (io != write_io) {
4455  GetOpenFile(write_io, fptr);
4456  if (fptr && 0 <= (fd = fptr->fd)) {
4457  if ((ret = fcntl(fptr->fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
4458  if ((ret & FD_CLOEXEC) != flag) {
4459  ret = (ret & ~FD_CLOEXEC) | flag;
4460  ret = fcntl(fd, F_SETFD, ret);
4461  if (ret != 0) rb_sys_fail_path(fptr->pathv);
4462  }
4463  }
4464 
4465  }
4466 
4467  GetOpenFile(io, fptr);
4468  if (fptr && 0 <= (fd = fptr->fd)) {
4469  if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
4470  if ((ret & FD_CLOEXEC) != flag) {
4471  ret = (ret & ~FD_CLOEXEC) | flag;
4472  ret = fcntl(fd, F_SETFD, ret);
4473  if (ret != 0) rb_sys_fail_path(fptr->pathv);
4474  }
4475  }
4476  return Qnil;
4477 }
4478 #else
4479 #define rb_io_set_close_on_exec rb_f_notimplement
4480 #endif
4481 
4482 #define FMODE_PREP (1<<16)
4483 #define IS_PREP_STDIO(f) ((f)->mode & FMODE_PREP)
4484 #define PREP_STDIO_NAME(f) (RSTRING_PTR((f)->pathv))
4485 
4486 static VALUE
4487 finish_writeconv(rb_io_t *fptr, int noalloc)
4488 {
4489  unsigned char *ds, *dp, *de;
4490  rb_econv_result_t res;
4491 
4492  if (!fptr->wbuf.ptr) {
4493  unsigned char buf[1024];
4494  long r;
4495 
4497  while (res == econv_destination_buffer_full) {
4498  ds = dp = buf;
4499  de = buf + sizeof(buf);
4500  res = rb_econv_convert(fptr->writeconv, NULL, NULL, &dp, de, 0);
4501  while (dp-ds) {
4502  retry:
4503  if (fptr->write_lock && rb_mutex_owned_p(fptr->write_lock))
4504  r = rb_write_internal2(fptr->fd, ds, dp-ds);
4505  else
4506  r = rb_write_internal(fptr->fd, ds, dp-ds);
4507  if (r == dp-ds)
4508  break;
4509  if (0 <= r) {
4510  ds += r;
4511  }
4512  if (rb_io_wait_writable(fptr->fd)) {
4513  if (fptr->fd < 0)
4514  return noalloc ? Qtrue : rb_exc_new3(rb_eIOError, rb_str_new_cstr(closed_stream));
4515  goto retry;
4516  }
4517  return noalloc ? Qtrue : INT2NUM(errno);
4518  }
4519  if (res == econv_invalid_byte_sequence ||
4520  res == econv_incomplete_input ||
4521  res == econv_undefined_conversion) {
4522  return noalloc ? Qtrue : rb_econv_make_exception(fptr->writeconv);
4523  }
4524  }
4525 
4526  return Qnil;
4527  }
4528 
4530  while (res == econv_destination_buffer_full) {
4531  if (fptr->wbuf.len == fptr->wbuf.capa) {
4532  if (io_fflush(fptr) < 0)
4533  return noalloc ? Qtrue : INT2NUM(errno);
4534  }
4535 
4536  ds = dp = (unsigned char *)fptr->wbuf.ptr + fptr->wbuf.off + fptr->wbuf.len;
4537  de = (unsigned char *)fptr->wbuf.ptr + fptr->wbuf.capa;
4538  res = rb_econv_convert(fptr->writeconv, NULL, NULL, &dp, de, 0);
4539  fptr->wbuf.len += (int)(dp - ds);
4540  if (res == econv_invalid_byte_sequence ||
4541  res == econv_incomplete_input ||
4542  res == econv_undefined_conversion) {
4543  return noalloc ? Qtrue : rb_econv_make_exception(fptr->writeconv);
4544  }
4545  }
4546  return Qnil;
4547 }
4548 
4551  int noalloc;
4552 };
4553 
4554 static VALUE
4555 finish_writeconv_sync(VALUE arg)
4556 {
4557  struct finish_writeconv_arg *p = (struct finish_writeconv_arg *)arg;
4558  return finish_writeconv(p->fptr, p->noalloc);
4559 }
4560 
4561 static void*
4562 nogvl_close(void *ptr)
4563 {
4564  int *fd = ptr;
4565 
4566  return (void*)(intptr_t)close(*fd);
4567 }
4568 
4569 static int
4570 maygvl_close(int fd, int keepgvl)
4571 {
4572  if (keepgvl)
4573  return close(fd);
4574 
4575  /*
4576  * close() may block for certain file types (NFS, SO_LINGER sockets,
4577  * inotify), so let other threads run.
4578  */
4579  return (int)(intptr_t)rb_thread_call_without_gvl(nogvl_close, &fd, RUBY_UBF_IO, 0);
4580 }
4581 
4582 static void*
4583 nogvl_fclose(void *ptr)
4584 {
4585  FILE *file = ptr;
4586 
4587  return (void*)(intptr_t)fclose(file);
4588 }
4589 
4590 static int
4591 maygvl_fclose(FILE *file, int keepgvl)
4592 {
4593  if (keepgvl)
4594  return fclose(file);
4595 
4596  return (int)(intptr_t)rb_thread_call_without_gvl(nogvl_fclose, file, RUBY_UBF_IO, 0);
4597 }
4598 
4599 static void free_io_buffer(rb_io_buffer_t *buf);
4600 static void clear_codeconv(rb_io_t *fptr);
4601 
4602 static void
4603 fptr_finalize_flush(rb_io_t *fptr, int noraise, int keepgvl,
4604  struct list_head *busy)
4605 {
4606  VALUE err = Qnil;
4607  int fd = fptr->fd;
4608  FILE *stdio_file = fptr->stdio_file;
4609  int mode = fptr->mode;
4610 
4611  if (fptr->writeconv) {
4612  if (fptr->write_lock && !noraise) {
4613  struct finish_writeconv_arg arg;
4614  arg.fptr = fptr;
4615  arg.noalloc = noraise;
4616  err = rb_mutex_synchronize(fptr->write_lock, finish_writeconv_sync, (VALUE)&arg);
4617  }
4618  else {
4619  err = finish_writeconv(fptr, noraise);
4620  }
4621  }
4622  if (fptr->wbuf.len) {
4623  if (noraise) {
4624  io_flush_buffer_sync(fptr);
4625  }
4626  else {
4627  if (io_fflush(fptr) < 0 && NIL_P(err))
4628  err = INT2NUM(errno);
4629  }
4630  }
4631 
4632  fptr->fd = -1;
4633  fptr->stdio_file = 0;
4635 
4636  /*
4637  * ensure waiting_fd users do not hit EBADF, wait for them
4638  * to exit before we call close().
4639  */
4640  if (busy) {
4641  do rb_thread_schedule(); while (!list_empty(busy));
4642  }
4643 
4644  if (IS_PREP_STDIO(fptr) || fd <= 2) {
4645  /* need to keep FILE objects of stdin, stdout and stderr */
4646  }
4647  else if (stdio_file) {
4648  /* stdio_file is deallocated anyway
4649  * even if fclose failed. */
4650  if ((maygvl_fclose(stdio_file, noraise) < 0) && NIL_P(err))
4651  if (!noraise) err = INT2NUM(errno);
4652  }
4653  else if (0 <= fd) {
4654  /* fptr->fd may be closed even if close fails.
4655  * POSIX doesn't specify it.
4656  * We assumes it is closed. */
4657 
4658 
4659  keepgvl |= !(mode & FMODE_WRITABLE);
4660  keepgvl |= noraise;
4661  if ((maygvl_close(fd, keepgvl) < 0) && NIL_P(err))
4662  if (!noraise) err = INT2NUM(errno);
4663  }
4664 
4665  if (!NIL_P(err) && !noraise) {
4666  if (RB_INTEGER_TYPE_P(err))
4668  else
4669  rb_exc_raise(err);
4670  }
4671 }
4672 
4673 static void
4674 fptr_finalize(rb_io_t *fptr, int noraise)
4675 {
4676  fptr_finalize_flush(fptr, noraise, FALSE, 0);
4677  free_io_buffer(&fptr->rbuf);
4678  free_io_buffer(&fptr->wbuf);
4679  clear_codeconv(fptr);
4680 }
4681 
4682 static void
4683 rb_io_fptr_cleanup(rb_io_t *fptr, int noraise)
4684 {
4685  if (fptr->finalize) {
4686  (*fptr->finalize)(fptr, noraise);
4687  }
4688  else {
4689  fptr_finalize(fptr, noraise);
4690  }
4691 }
4692 
4693 static void
4694 free_io_buffer(rb_io_buffer_t *buf)
4695 {
4696  if (buf->ptr) {
4697  ruby_sized_xfree(buf->ptr, (size_t)buf->capa);
4698  buf->ptr = NULL;
4699  }
4700 }
4701 
4702 static void
4703 clear_readconv(rb_io_t *fptr)
4704 {
4705  if (fptr->readconv) {
4707  fptr->readconv = NULL;
4708  }
4709  free_io_buffer(&fptr->cbuf);
4710 }
4711 
4712 static void
4713 clear_writeconv(rb_io_t *fptr)
4714 {
4715  if (fptr->writeconv) {
4717  fptr->writeconv = NULL;
4718  }
4720 }
4721 
4722 static void
4723 clear_codeconv(rb_io_t *fptr)
4724 {
4725  clear_readconv(fptr);
4726  clear_writeconv(fptr);
4727 }
4728 
4729 void
4731 {
4732  rb_io_t *fptr = ptr;
4733 
4734  if (!ptr) return;
4735  fptr->pathv = Qnil;
4736  if (0 <= fptr->fd)
4737  rb_io_fptr_cleanup(fptr, TRUE);
4738  fptr->write_lock = 0;
4739  free_io_buffer(&fptr->rbuf);
4740  free_io_buffer(&fptr->wbuf);
4741  clear_codeconv(fptr);
4742  free(fptr);
4743 }
4744 
4745 #undef rb_io_fptr_finalize
4746 int
4748 {
4749  if (!fptr) {
4750  return 0;
4751  }
4752  else {
4754  return 1;
4755  }
4756 }
4757 #define rb_io_fptr_finalize(fptr) rb_io_fptr_finalize_internal(fptr)
4758 
4759 RUBY_FUNC_EXPORTED size_t
4761 {
4762  size_t size = sizeof(rb_io_t);
4763  size += fptr->rbuf.capa;
4764  size += fptr->wbuf.capa;
4765  size += fptr->cbuf.capa;
4768  return size;
4769 }
4770 
4771 #ifdef _WIN32
4772 /* keep GVL while closing to prevent crash on Windows */
4773 # define KEEPGVL TRUE
4774 #else
4775 # define KEEPGVL FALSE
4776 #endif
4777 
4778 int rb_notify_fd_close(int fd, struct list_head *);
4779 static rb_io_t *
4780 io_close_fptr(VALUE io)
4781 {
4782  rb_io_t *fptr;
4783  VALUE write_io;
4784  rb_io_t *write_fptr;
4785  struct list_head busy;
4786 
4787  list_head_init(&busy);
4788  write_io = GetWriteIO(io);
4789  if (io != write_io) {
4790  write_fptr = RFILE(write_io)->fptr;
4791  if (write_fptr && 0 <= write_fptr->fd) {
4792  rb_io_fptr_cleanup(write_fptr, TRUE);
4793  }
4794  }
4795 
4796  fptr = RFILE(io)->fptr;
4797  if (!fptr) return 0;
4798  if (fptr->fd < 0) return 0;
4799 
4800  if (rb_notify_fd_close(fptr->fd, &busy)) {
4801  /* calls close(fptr->fd): */
4802  fptr_finalize_flush(fptr, FALSE, KEEPGVL, &busy);
4803  }
4804  rb_io_fptr_cleanup(fptr, FALSE);
4805  return fptr;
4806 }
4807 
4808 static void
4809 fptr_waitpid(rb_io_t *fptr, int nohang)
4810 {
4811  int status;
4812  if (fptr->pid) {
4814  rb_waitpid(fptr->pid, &status, nohang ? WNOHANG : 0);
4815  fptr->pid = 0;
4816  }
4817 }
4818 
4819 VALUE
4821 {
4822  rb_io_t *fptr = io_close_fptr(io);
4823  if (fptr) fptr_waitpid(fptr, 0);
4824  return Qnil;
4825 }
4826 
4827 /*
4828  * call-seq:
4829  * ios.close -> nil
4830  *
4831  * Closes <em>ios</em> and flushes any pending writes to the operating
4832  * system. The stream is unavailable for any further data operations;
4833  * an IOError is raised if such an attempt is made. I/O streams are
4834  * automatically closed when they are claimed by the garbage collector.
4835  *
4836  * If <em>ios</em> is opened by IO.popen, #close sets
4837  * <code>$?</code>.
4838  *
4839  * Calling this method on closed IO object is just ignored since Ruby 2.3.
4840  */
4841 
4842 static VALUE
4843 rb_io_close_m(VALUE io)
4844 {
4845  rb_io_t *fptr = rb_io_get_fptr(io);
4846  if (fptr->fd < 0) {
4847  return Qnil;
4848  }
4849  rb_io_close(io);
4850  return Qnil;
4851 }
4852 
4853 static VALUE
4854 io_call_close(VALUE io)
4855 {
4856  rb_check_funcall(io, rb_intern("close"), 0, 0);
4857  return io;
4858 }
4859 
4860 static VALUE
4861 ignore_closed_stream(VALUE io, VALUE exc)
4862 {
4863  enum {mesg_len = sizeof(closed_stream)-1};
4864  VALUE mesg = rb_attr_get(exc, idMesg);
4865  if (!RB_TYPE_P(mesg, T_STRING) ||
4866  RSTRING_LEN(mesg) != mesg_len ||
4867  memcmp(RSTRING_PTR(mesg), closed_stream, mesg_len)) {
4868  rb_exc_raise(exc);
4869  }
4870  return io;
4871 }
4872 
4873 static VALUE
4874 io_close(VALUE io)
4875 {
4876  VALUE closed = rb_check_funcall(io, rb_intern("closed?"), 0, 0);
4877  if (closed != Qundef && RTEST(closed)) return io;
4878  rb_rescue2(io_call_close, io, ignore_closed_stream, io,
4879  rb_eIOError, (VALUE)0);
4880  return io;
4881 }
4882 
4883 /*
4884  * call-seq:
4885  * ios.closed? -> true or false
4886  *
4887  * Returns <code>true</code> if <em>ios</em> is completely closed (for
4888  * duplex streams, both reader and writer), <code>false</code>
4889  * otherwise.
4890  *
4891  * f = File.new("testfile")
4892  * f.close #=> nil
4893  * f.closed? #=> true
4894  * f = IO.popen("/bin/sh","r+")
4895  * f.close_write #=> nil
4896  * f.closed? #=> false
4897  * f.close_read #=> nil
4898  * f.closed? #=> true
4899  */
4900 
4901 
4902 static VALUE
4903 rb_io_closed(VALUE io)
4904 {
4905  rb_io_t *fptr;
4906  VALUE write_io;
4907  rb_io_t *write_fptr;
4908 
4909  write_io = GetWriteIO(io);
4910  if (io != write_io) {
4911  write_fptr = RFILE(write_io)->fptr;
4912  if (write_fptr && 0 <= write_fptr->fd) {
4913  return Qfalse;
4914  }
4915  }
4916 
4917  fptr = rb_io_get_fptr(io);
4918  return 0 <= fptr->fd ? Qfalse : Qtrue;
4919 }
4920 
4921 /*
4922  * call-seq:
4923  * ios.close_read -> nil
4924  *
4925  * Closes the read end of a duplex I/O stream (i.e., one that contains
4926  * both a read and a write stream, such as a pipe). Will raise an
4927  * IOError if the stream is not duplexed.
4928  *
4929  * f = IO.popen("/bin/sh","r+")
4930  * f.close_read
4931  * f.readlines
4932  *
4933  * <em>produces:</em>
4934  *
4935  * prog.rb:3:in `readlines': not opened for reading (IOError)
4936  * from prog.rb:3
4937  *
4938  * Calling this method on closed IO object is just ignored since Ruby 2.3.
4939  */
4940 
4941 static VALUE
4942 rb_io_close_read(VALUE io)
4943 {
4944  rb_io_t *fptr;
4945  VALUE write_io;
4946 
4947  fptr = rb_io_get_fptr(rb_io_taint_check(io));
4948  if (fptr->fd < 0) return Qnil;
4949  if (is_socket(fptr->fd, fptr->pathv)) {
4950 #ifndef SHUT_RD
4951 # define SHUT_RD 0
4952 #endif
4953  if (shutdown(fptr->fd, SHUT_RD) < 0)
4954  rb_sys_fail_path(fptr->pathv);
4955  fptr->mode &= ~FMODE_READABLE;
4956  if (!(fptr->mode & FMODE_WRITABLE))
4957  return rb_io_close(io);
4958  return Qnil;
4959  }
4960 
4961  write_io = GetWriteIO(io);
4962  if (io != write_io) {
4963  rb_io_t *wfptr;
4964  wfptr = rb_io_get_fptr(rb_io_taint_check(write_io));
4965  wfptr->pid = fptr->pid;
4966  fptr->pid = 0;
4967  RFILE(io)->fptr = wfptr;
4968  /* bind to write_io temporarily to get rid of memory/fd leak */
4969  fptr->tied_io_for_writing = 0;
4970  RFILE(write_io)->fptr = fptr;
4971  rb_io_fptr_cleanup(fptr, FALSE);
4972  /* should not finalize fptr because another thread may be reading it */
4973  return Qnil;
4974  }
4975 
4976  if ((fptr->mode & (FMODE_DUPLEX|FMODE_WRITABLE)) == FMODE_WRITABLE) {
4977  rb_raise(rb_eIOError, "closing non-duplex IO for reading");
4978  }
4979  return rb_io_close(io);
4980 }
4981 
4982 /*
4983  * call-seq:
4984  * ios.close_write -> nil
4985  *
4986  * Closes the write end of a duplex I/O stream (i.e., one that contains
4987  * both a read and a write stream, such as a pipe). Will raise an
4988  * IOError if the stream is not duplexed.
4989  *
4990  * f = IO.popen("/bin/sh","r+")
4991  * f.close_write
4992  * f.print "nowhere"
4993  *
4994  * <em>produces:</em>
4995  *
4996  * prog.rb:3:in `write': not opened for writing (IOError)
4997  * from prog.rb:3:in `print'
4998  * from prog.rb:3
4999  *
5000  * Calling this method on closed IO object is just ignored since Ruby 2.3.
5001  */
5002 
5003 static VALUE
5004 rb_io_close_write(VALUE io)
5005 {
5006  rb_io_t *fptr;
5007  VALUE write_io;
5008 
5009  write_io = GetWriteIO(io);
5010  fptr = rb_io_get_fptr(rb_io_taint_check(write_io));
5011  if (fptr->fd < 0) return Qnil;
5012  if (is_socket(fptr->fd, fptr->pathv)) {
5013 #ifndef SHUT_WR
5014 # define SHUT_WR 1
5015 #endif
5016  if (shutdown(fptr->fd, SHUT_WR) < 0)
5017  rb_sys_fail_path(fptr->pathv);
5018  fptr->mode &= ~FMODE_WRITABLE;
5019  if (!(fptr->mode & FMODE_READABLE))
5020  return rb_io_close(write_io);
5021  return Qnil;
5022  }
5023 
5024  if ((fptr->mode & (FMODE_DUPLEX|FMODE_READABLE)) == FMODE_READABLE) {
5025  rb_raise(rb_eIOError, "closing non-duplex IO for writing");
5026  }
5027 
5028  if (io != write_io) {
5029  fptr = rb_io_get_fptr(rb_io_taint_check(io));
5030  fptr->tied_io_for_writing = 0;
5031  }
5032  rb_io_close(write_io);
5033  return Qnil;
5034 }
5035 
5036 /*
5037  * call-seq:
5038  * ios.sysseek(offset, whence=IO::SEEK_SET) -> integer
5039  *
5040  * Seeks to a given <i>offset</i> in the stream according to the value
5041  * of <i>whence</i> (see IO#seek for values of <i>whence</i>). Returns
5042  * the new offset into the file.
5043  *
5044  * f = File.new("testfile")
5045  * f.sysseek(-13, IO::SEEK_END) #=> 53
5046  * f.sysread(10) #=> "And so on."
5047  */
5048 
5049 static VALUE
5050 rb_io_sysseek(int argc, VALUE *argv, VALUE io)
5051 {
5052  VALUE offset, ptrname;
5053  int whence = SEEK_SET;
5054  rb_io_t *fptr;
5055  off_t pos;
5056 
5057  if (rb_scan_args(argc, argv, "11", &offset, &ptrname) == 2) {
5058  whence = interpret_seek_whence(ptrname);
5059  }
5060  pos = NUM2OFFT(offset);
5061  GetOpenFile(io, fptr);
5062  if ((fptr->mode & FMODE_READABLE) &&
5063  (READ_DATA_BUFFERED(fptr) || READ_CHAR_PENDING(fptr))) {
5064  rb_raise(rb_eIOError, "sysseek for buffered IO");
5065  }
5066  if ((fptr->mode & FMODE_WRITABLE) && fptr->wbuf.len) {
5067  rb_warn("sysseek for buffered IO");
5068  }
5069  errno = 0;
5070  pos = lseek(fptr->fd, pos, whence);
5071  if (pos < 0 && errno) rb_sys_fail_path(fptr->pathv);
5072 
5073  return OFFT2NUM(pos);
5074 }
5075 
5076 /*
5077  * call-seq:
5078  * ios.syswrite(string) -> integer
5079  *
5080  * Writes the given string to <em>ios</em> using a low-level write.
5081  * Returns the number of bytes written. Do not mix with other methods
5082  * that write to <em>ios</em> or you may get unpredictable results.
5083  * Raises SystemCallError on error.
5084  *
5085  * f = File.new("out", "w")
5086  * f.syswrite("ABCDEF") #=> 6
5087  */
5088 
5089 static VALUE
5090 rb_io_syswrite(VALUE io, VALUE str)
5091 {
5092  VALUE tmp;
5093  rb_io_t *fptr;
5094  long n, len;
5095  const char *ptr;
5096 
5097  if (!RB_TYPE_P(str, T_STRING))
5099 
5100  io = GetWriteIO(io);
5101  GetOpenFile(io, fptr);
5102  rb_io_check_writable(fptr);
5103 
5104  if (fptr->wbuf.len) {
5105  rb_warn("syswrite for buffered IO");
5106  }
5107 
5109  RSTRING_GETMEM(tmp, ptr, len);
5110  n = rb_write_internal(fptr->fd, ptr, len);
5111  if (n < 0) rb_sys_fail_path(fptr->pathv);
5113 
5114  return LONG2FIX(n);
5115 }
5116 
5117 /*
5118  * call-seq:
5119  * ios.sysread(maxlen[, outbuf]) -> string
5120  *
5121  * Reads <i>maxlen</i> bytes from <em>ios</em> using a low-level
5122  * read and returns them as a string. Do not mix with other methods
5123  * that read from <em>ios</em> or you may get unpredictable results.
5124  *
5125  * If the optional _outbuf_ argument is present,
5126  * it must reference a String, which will receive the data.
5127  * The _outbuf_ will contain only the received data after the method call
5128  * even if it is not empty at the beginning.
5129  *
5130  * Raises SystemCallError on error and EOFError at end of file.
5131  *
5132  * f = File.new("testfile")
5133  * f.sysread(16) #=> "This is line one"
5134  */
5135 
5136 static VALUE
5137 rb_io_sysread(int argc, VALUE *argv, VALUE io)
5138 {
5139  VALUE len, str;
5140  rb_io_t *fptr;
5141  long n, ilen;
5142  struct io_internal_read_struct iis;
5143  int shrinkable;
5144 
5145  rb_scan_args(argc, argv, "11", &len, &str);
5146  ilen = NUM2LONG(len);
5147 
5148  shrinkable = io_setstrbuf(&str, ilen);
5149  if (ilen == 0) return str;
5150 
5151  GetOpenFile(io, fptr);
5153 
5154  if (READ_DATA_BUFFERED(fptr)) {
5155  rb_raise(rb_eIOError, "sysread for buffered IO");
5156  }
5157 
5158  /*
5159  * FIXME: removing rb_thread_wait_fd() here changes sysread semantics
5160  * on non-blocking IOs. However, it's still currently possible
5161  * for sysread to raise Errno::EAGAIN if another thread read()s
5162  * the IO after we return from rb_thread_wait_fd() but before
5163  * we call read()
5164  */
5165  rb_thread_wait_fd(fptr->fd);
5166 
5167  rb_io_check_closed(fptr);
5168 
5169  io_setstrbuf(&str, ilen);
5170  iis.fd = fptr->fd;
5171  iis.nonblock = 1; /* for historical reasons, maybe (see above) */
5172  iis.buf = RSTRING_PTR(str);
5173  iis.capa = ilen;
5174  n = read_internal_locktmp(str, &iis);
5175 
5176  if (n < 0) {
5177  rb_sys_fail_path(fptr->pathv);
5178  }
5179  io_set_read_length(str, n, shrinkable);
5180  if (n == 0 && ilen > 0) {
5181  rb_eof_error();
5182  }
5183 
5184  return str;
5185 }
5186 
5187 #if defined(HAVE_PREAD) || defined(HAVE_PWRITE)
5188 struct prdwr_internal_arg {
5189  int fd;
5190  void *buf;
5191  size_t count;
5192  off_t offset;
5193 };
5194 #endif /* HAVE_PREAD || HAVE_PWRITE */
5195 
5196 #if defined(HAVE_PREAD)
5197 static VALUE
5198 internal_pread_func(void *arg)
5199 {
5200  struct prdwr_internal_arg *p = arg;
5201  return (VALUE)pread(p->fd, p->buf, p->count, p->offset);
5202 }
5203 
5204 static VALUE
5205 pread_internal_call(VALUE arg)
5206 {
5207  struct prdwr_internal_arg *p = (struct prdwr_internal_arg *)arg;
5208  return rb_thread_io_blocking_region(internal_pread_func, p, p->fd);
5209 }
5210 
5211 /*
5212  * call-seq:
5213  * ios.pread(maxlen, offset[, outbuf]) -> string
5214  *
5215  * Reads <i>maxlen</i> bytes from <em>ios</em> using the pread system call
5216  * and returns them as a string without modifying the underlying
5217  * descriptor offset. This is advantageous compared to combining IO#seek
5218  * and IO#read in that it is atomic, allowing multiple threads/process to
5219  * share the same IO object for reading the file at various locations.
5220  * This bypasses any userspace buffering of the IO layer.
5221  * If the optional <i>outbuf</i> argument is present, it must
5222  * reference a String, which will receive the data.
5223  * Raises SystemCallError on error, EOFError at end of file and
5224  * NotImplementedError if platform does not implement the system call.
5225  *
5226  * File.write("testfile", "This is line one\nThis is line two\n")
5227  * File.open("testfile") do |f|
5228  * p f.read # => "This is line one\nThis is line two\n"
5229  * p f.pread(12, 0) # => "This is line"
5230  * p f.pread(9, 8) # => "line one\n"
5231  * end
5232  */
5233 static VALUE
5234 rb_io_pread(int argc, VALUE *argv, VALUE io)
5235 {
5236  VALUE len, offset, str;
5237  rb_io_t *fptr;
5238  ssize_t n;
5239  struct prdwr_internal_arg arg;
5240  int shrinkable;
5241 
5242  rb_scan_args(argc, argv, "21", &len, &offset, &str);
5243  arg.count = NUM2SIZET(len);
5244  arg.offset = NUM2OFFT(offset);
5245 
5246  shrinkable = io_setstrbuf(&str, (long)arg.count);
5247  if (arg.count == 0) return str;
5248  arg.buf = RSTRING_PTR(str);
5249 
5250  GetOpenFile(io, fptr);
5252 
5253  arg.fd = fptr->fd;
5254  rb_io_check_closed(fptr);
5255 
5257  n = (ssize_t)rb_ensure(pread_internal_call, (VALUE)&arg, rb_str_unlocktmp, str);
5258 
5259  if (n < 0) {
5260  rb_sys_fail_path(fptr->pathv);
5261  }
5262  io_set_read_length(str, n, shrinkable);
5263  if (n == 0 && arg.count > 0) {
5264  rb_eof_error();
5265  }
5266 
5267  return str;
5268 }
5269 #else
5270 # define rb_io_pread rb_f_notimplement
5271 #endif /* HAVE_PREAD */
5272 
5273 #if defined(HAVE_PWRITE)
5274 static VALUE
5275 internal_pwrite_func(void *ptr)
5276 {
5277  struct prdwr_internal_arg *arg = ptr;
5278 
5279  return (VALUE)pwrite(arg->fd, arg->buf, arg->count, arg->offset);
5280 }
5281 
5282 /*
5283  * call-seq:
5284  * ios.pwrite(string, offset) -> integer
5285  *
5286  * Writes the given string to <em>ios</em> at <i>offset</i> using pwrite()
5287  * system call. This is advantageous to combining IO#seek and IO#write
5288  * in that it is atomic, allowing multiple threads/process to share the
5289  * same IO object for reading the file at various locations.
5290  * This bypasses any userspace buffering of the IO layer.
5291  * Returns the number of bytes written.
5292  * Raises SystemCallError on error and NotImplementedError
5293  * if platform does not implement the system call.
5294  *
5295  * File.open("out", "w") do |f|
5296  * f.pwrite("ABCDEF", 3) #=> 6
5297  * end
5298  *
5299  * File.read("out") #=> "\u0000\u0000\u0000ABCDEF"
5300  */
5301 static VALUE
5302 rb_io_pwrite(VALUE io, VALUE str, VALUE offset)
5303 {
5304  rb_io_t *fptr;
5305  ssize_t n;
5306  struct prdwr_internal_arg arg;
5307  VALUE tmp;
5308 
5309  if (!RB_TYPE_P(str, T_STRING))
5311 
5312  arg.offset = NUM2OFFT(offset);
5313 
5314  io = GetWriteIO(io);
5315  GetOpenFile(io, fptr);
5316  rb_io_check_writable(fptr);
5317  arg.fd = fptr->fd;
5318 
5320  arg.buf = RSTRING_PTR(tmp);
5321  arg.count = (size_t)RSTRING_LEN(tmp);
5322 
5323  n = (ssize_t)rb_thread_io_blocking_region(internal_pwrite_func, &arg, fptr->fd);
5324  if (n < 0) rb_sys_fail_path(fptr->pathv);
5326 
5327  return SSIZET2NUM(n);
5328 }
5329 #else
5330 # define rb_io_pwrite rb_f_notimplement
5331 #endif /* HAVE_PWRITE */
5332 
5333 VALUE
5335 {
5336  rb_io_t *fptr;
5337 
5338  GetOpenFile(io, fptr);
5339  if (fptr->readconv)
5340  rb_econv_binmode(fptr->readconv);
5341  if (fptr->writeconv)
5342  rb_econv_binmode(fptr->writeconv);
5343  fptr->mode |= FMODE_BINMODE;
5344  fptr->mode &= ~FMODE_TEXTMODE;
5346 #ifdef O_BINARY
5347  if (!fptr->readconv) {
5349  }
5350  else {
5351  setmode(fptr->fd, O_BINARY);
5352  }
5353 #endif
5354  return io;
5355 }
5356 
5357 static void
5358 io_ascii8bit_binmode(rb_io_t *fptr)
5359 {
5360  if (fptr->readconv) {
5361  rb_econv_close(fptr->readconv);
5362  fptr->readconv = NULL;
5363  }
5364  if (fptr->writeconv) {
5365  rb_econv_close(fptr->writeconv);
5366  fptr->writeconv = NULL;
5367  }
5368  fptr->mode |= FMODE_BINMODE;
5369  fptr->mode &= ~FMODE_TEXTMODE;
5371 
5372  fptr->encs.enc = rb_ascii8bit_encoding();
5373  fptr->encs.enc2 = NULL;
5374  fptr->encs.ecflags = 0;
5375  fptr->encs.ecopts = Qnil;
5376  clear_codeconv(fptr);
5377 }
5378 
5379 VALUE
5381 {
5382  rb_io_t *fptr;
5383 
5384  GetOpenFile(io, fptr);
5385  io_ascii8bit_binmode(fptr);
5386 
5387  return io;
5388 }
5389 
5390 /*
5391  * call-seq:
5392  * ios.binmode -> ios
5393  *
5394  * Puts <em>ios</em> into binary mode.
5395  * Once a stream is in binary mode, it cannot be reset to nonbinary mode.
5396  *
5397  * - newline conversion disabled
5398  * - encoding conversion disabled
5399  * - content is treated as ASCII-8BIT
5400  */
5401 
5402 static VALUE
5403 rb_io_binmode_m(VALUE io)
5404 {
5405  VALUE write_io;
5406 
5408 
5409  write_io = GetWriteIO(io);
5410  if (write_io != io)
5411  rb_io_ascii8bit_binmode(write_io);
5412  return io;
5413 }
5414 
5415 /*
5416  * call-seq:
5417  * ios.binmode? -> true or false
5418  *
5419  * Returns <code>true</code> if <em>ios</em> is binmode.
5420  */
5421 static VALUE
5422 rb_io_binmode_p(VALUE io)
5423 {
5424  rb_io_t *fptr;
5425  GetOpenFile(io, fptr);
5426  return fptr->mode & FMODE_BINMODE ? Qtrue : Qfalse;
5427 }
5428 
5429 static const char*
5430 rb_io_fmode_modestr(int fmode)
5431 {
5432  if (fmode & FMODE_APPEND) {
5433  if ((fmode & FMODE_READWRITE) == FMODE_READWRITE) {
5434  return MODE_BTMODE("a+", "ab+", "at+");
5435  }
5436  return MODE_BTMODE("a", "ab", "at");
5437  }
5438  switch (fmode & FMODE_READWRITE) {
5439  default:
5440  rb_raise(rb_eArgError, "invalid access fmode 0x%x", fmode);
5441  case FMODE_READABLE:
5442  return MODE_BTMODE("r", "rb", "rt");
5443  case FMODE_WRITABLE:
5444  return MODE_BTXMODE("w", "wb", "wt", "wx", "wbx", "wtx");
5445  case FMODE_READWRITE:
5446  if (fmode & FMODE_CREATE) {
5447  return MODE_BTXMODE("w+", "wb+", "wt+", "w+x", "wb+x", "wt+x");
5448  }
5449  return MODE_BTMODE("r+", "rb+", "rt+");
5450  }
5451 }
5452 
5453 static const char bom_prefix[] = "bom|";
5454 static const char utf_prefix[] = "utf-";
5455 enum {bom_prefix_len = (int)sizeof(bom_prefix) - 1};
5456 enum {utf_prefix_len = (int)sizeof(utf_prefix) - 1};
5457 
5458 static int
5459 io_encname_bom_p(const char *name, long len)
5460 {
5461  return len > bom_prefix_len && STRNCASECMP(name, bom_prefix, bom_prefix_len) == 0;
5462 }
5463 
5464 int
5465 rb_io_modestr_fmode(const char *modestr)
5466 {
5467  int fmode = 0;
5468  const char *m = modestr, *p = NULL;
5469 
5470  switch (*m++) {
5471  case 'r':
5472  fmode |= FMODE_READABLE;
5473  break;
5474  case 'w':
5476  break;
5477  case 'a':
5479  break;
5480  default:
5481  error:
5482  rb_raise(rb_eArgError, "invalid access mode %s", modestr);
5483  }
5484 
5485  while (*m) {
5486  switch (*m++) {
5487  case 'b':
5488  fmode |= FMODE_BINMODE;
5489  break;
5490  case 't':
5491  fmode |= FMODE_TEXTMODE;
5492  break;
5493  case '+':
5495  break;
5496  case 'x':
5497  if (modestr[0] != 'w')
5498  goto error;
5499  fmode |= FMODE_EXCL;
5500  break;
5501  default:
5502  goto error;
5503  case ':':
5504  p = strchr(m, ':');
5505  if (io_encname_bom_p(m, p ? (long)(p - m) : (long)strlen(m)))
5507  goto finished;
5508  }
5509  }
5510 
5511  finished:
5512  if ((fmode & FMODE_BINMODE) && (fmode & FMODE_TEXTMODE))
5513  goto error;
5514 
5515  return fmode;
5516 }
5517 
5518 int
5520 {
5521  int fmode = 0;
5522 
5523  switch (oflags & O_ACCMODE) {
5524  case O_RDONLY:
5526  break;
5527  case O_WRONLY:
5529  break;
5530  case O_RDWR:
5532  break;
5533  }
5534 
5535  if (oflags & O_APPEND) {
5536  fmode |= FMODE_APPEND;
5537  }
5538  if (oflags & O_TRUNC) {
5539  fmode |= FMODE_TRUNC;
5540  }
5541  if (oflags & O_CREAT) {
5542  fmode |= FMODE_CREATE;
5543  }
5544  if (oflags & O_EXCL) {
5545  fmode |= FMODE_EXCL;
5546  }
5547 #ifdef O_BINARY
5548  if (oflags & O_BINARY) {
5549  fmode |= FMODE_BINMODE;
5550  }
5551 #endif
5552 
5553  return fmode;
5554 }
5555 
5556 static int
5557 rb_io_fmode_oflags(int fmode)
5558 {
5559  int oflags = 0;
5560 
5561  switch (fmode & FMODE_READWRITE) {
5562  case FMODE_READABLE:
5563  oflags |= O_RDONLY;
5564  break;
5565  case FMODE_WRITABLE:
5566  oflags |= O_WRONLY;
5567  break;
5568  case FMODE_READWRITE:
5569  oflags |= O_RDWR;
5570  break;
5571  }
5572 
5573  if (fmode & FMODE_APPEND) {
5574  oflags |= O_APPEND;
5575  }
5576  if (fmode & FMODE_TRUNC) {
5577  oflags |= O_TRUNC;
5578  }
5579  if (fmode & FMODE_CREATE) {
5580  oflags |= O_CREAT;
5581  }
5582  if (fmode & FMODE_EXCL) {
5583  oflags |= O_EXCL;
5584  }
5585 #ifdef O_BINARY
5586  if (fmode & FMODE_BINMODE) {
5587  oflags |= O_BINARY;
5588  }
5589 #endif
5590 
5591  return oflags;
5592 }
5593 
5594 int
5595 rb_io_modestr_oflags(const char *modestr)
5596 {
5597  return rb_io_fmode_oflags(rb_io_modestr_fmode(modestr));
5598 }
5599 
5600 static const char*
5601 rb_io_oflags_modestr(int oflags)
5602 {
5603 #ifdef O_BINARY
5604 # define MODE_BINARY(a,b) ((oflags & O_BINARY) ? (b) : (a))
5605 #else
5606 # define MODE_BINARY(a,b) (a)
5607 #endif
5608  int accmode;
5609  if (oflags & O_EXCL) {
5610  rb_raise(rb_eArgError, "exclusive access mode is not supported");
5611  }
5612  accmode = oflags & (O_RDONLY|O_WRONLY|O_RDWR);
5613  if (oflags & O_APPEND) {
5614  if (accmode == O_WRONLY) {
5615  return MODE_BINARY("a", "ab");
5616  }
5617  if (accmode == O_RDWR) {
5618  return MODE_BINARY("a+", "ab+");
5619  }
5620  }
5621  switch (accmode) {
5622  default:
5623  rb_raise(rb_eArgError, "invalid access oflags 0x%x", oflags);
5624  case O_RDONLY:
5625  return MODE_BINARY("r", "rb");
5626  case O_WRONLY:
5627  return MODE_BINARY("w", "wb");
5628  case O_RDWR:
5629  if (oflags & O_TRUNC) {
5630  return MODE_BINARY("w+", "wb+");
5631  }
5632  return MODE_BINARY("r+", "rb+");
5633  }
5634 }
5635 
5636 /*
5637  * Convert external/internal encodings to enc/enc2
5638  * NULL => use default encoding
5639  * Qnil => no encoding specified (internal only)
5640  */
5641 static void
5642 rb_io_ext_int_to_encs(rb_encoding *ext, rb_encoding *intern, rb_encoding **enc, rb_encoding **enc2, int fmode)
5643 {
5644  int default_ext = 0;
5645 
5646  if (ext == NULL) {
5648  default_ext = 1;
5649  }
5650  if (ext == rb_ascii8bit_encoding()) {
5651  /* If external is ASCII-8BIT, no transcoding */
5652  intern = NULL;
5653  }
5654  else if (intern == NULL) {
5655  intern = rb_default_internal_encoding();
5656  }
5657  if (intern == NULL || intern == (rb_encoding *)Qnil ||
5658  (!(fmode & FMODE_SETENC_BY_BOM) && (intern == ext))) {
5659  /* No internal encoding => use external + no transcoding */
5660  *enc = (default_ext && intern != ext) ? NULL : ext;
5661  *enc2 = NULL;
5662  }
5663  else {
5664  *enc = intern;
5665  *enc2 = ext;
5666  }
5667 }
5668 
5669 static void
5670 unsupported_encoding(const char *name, rb_encoding *enc)
5671 {
5672  rb_enc_warn(enc, "Unsupported encoding %s ignored", name);
5673 }
5674 
5675 static void
5676 parse_mode_enc(const char *estr, rb_encoding *estr_enc,
5677  rb_encoding **enc_p, rb_encoding **enc2_p, int *fmode_p)
5678 {
5679  const char *p;
5680  char encname[ENCODING_MAXNAMELEN+1];
5681  int idx, idx2;
5682  int fmode = fmode_p ? *fmode_p : 0;
5683  rb_encoding *ext_enc, *int_enc;
5684  long len;
5685 
5686  /* parse estr as "enc" or "enc2:enc" or "enc:-" */
5687 
5688  p = strrchr(estr, ':');
5689  len = p ? (p++ - estr) : (long)strlen(estr);
5690  if ((fmode & FMODE_SETENC_BY_BOM) || io_encname_bom_p(estr, len)) {
5691  estr += bom_prefix_len;
5692  len -= bom_prefix_len;
5693  if (!STRNCASECMP(estr, utf_prefix, utf_prefix_len)) {
5695  }
5696  else {
5697  rb_enc_warn(estr_enc, "BOM with non-UTF encoding %s is nonsense", estr);
5699  }
5700  }
5701  if (len == 0 || len > ENCODING_MAXNAMELEN) {
5702  idx = -1;
5703  }
5704  else {
5705  if (p) {
5706  memcpy(encname, estr, len);
5707  encname[len] = '\0';
5708  estr = encname;
5709  }
5710  idx = rb_enc_find_index(estr);
5711  }
5712  if (fmode_p) *fmode_p = fmode;
5713 
5714  if (idx >= 0)
5715  ext_enc = rb_enc_from_index(idx);
5716  else {
5717  if (idx != -2)
5718  unsupported_encoding(estr, estr_enc);
5719  ext_enc = NULL;
5720  }
5721 
5722  int_enc = NULL;
5723  if (p) {
5724  if (*p == '-' && *(p+1) == '\0') {
5725  /* Special case - "-" => no transcoding */
5726  int_enc = (rb_encoding *)Qnil;
5727  }
5728  else {
5729  idx2 = rb_enc_find_index(p);
5730  if (idx2 < 0)
5731  unsupported_encoding(p, estr_enc);
5732  else if (!(fmode & FMODE_SETENC_BY_BOM) && (idx2 == idx)) {
5733  int_enc = (rb_encoding *)Qnil;
5734  }
5735  else
5736  int_enc = rb_enc_from_index(idx2);
5737  }
5738  }
5739 
5740  rb_io_ext_int_to_encs(ext_enc, int_enc, enc_p, enc2_p, fmode);
5741 }
5742 
5743 int
5744 rb_io_extract_encoding_option(VALUE opt, rb_encoding **enc_p, rb_encoding **enc2_p, int *fmode_p)
5745 {
5746  VALUE encoding=Qnil, extenc=Qundef, intenc=Qundef, tmp;
5747  int extracted = 0;
5748  rb_encoding *extencoding = NULL;
5749  rb_encoding *intencoding = NULL;
5750 
5751  if (!NIL_P(opt)) {
5752  VALUE v;
5753  v = rb_hash_lookup2(opt, sym_encoding, Qnil);
5754  if (v != Qnil) encoding = v;
5755  v = rb_hash_lookup2(opt, sym_extenc, Qundef);
5756  if (v != Qnil) extenc = v;
5757  v = rb_hash_lookup2(opt, sym_intenc, Qundef);
5758  if (v != Qundef) intenc = v;
5759  }
5760  if ((extenc != Qundef || intenc != Qundef) && !NIL_P(encoding)) {
5761  if (!NIL_P(ruby_verbose)) {
5762  int idx = rb_to_encoding_index(encoding);
5763  if (idx >= 0) encoding = rb_enc_from_encoding(rb_enc_from_index(idx));
5764  rb_warn("Ignoring encoding parameter '%"PRIsVALUE"': %s_encoding is used",
5765  encoding, extenc == Qundef ? "internal" : "external");
5766  }
5767  encoding = Qnil;
5768  }
5769  if (extenc != Qundef && !NIL_P(extenc)) {
5770  extencoding = rb_to_encoding(extenc);
5771  }
5772  if (intenc != Qundef) {
5773  if (NIL_P(intenc)) {
5774  /* internal_encoding: nil => no transcoding */
5775  intencoding = (rb_encoding *)Qnil;
5776  }
5777  else if (!NIL_P(tmp = rb_check_string_type(intenc))) {
5778  char *p = StringValueCStr(tmp);
5779 
5780  if (*p == '-' && *(p+1) == '\0') {
5781  /* Special case - "-" => no transcoding */
5782  intencoding = (rb_encoding *)Qnil;
5783  }
5784  else {
5785  intencoding = rb_to_encoding(intenc);
5786  }
5787  }
5788  else {
5789  intencoding = rb_to_encoding(intenc);
5790  }
5791  if (extencoding == intencoding) {
5792  intencoding = (rb_encoding *)Qnil;
5793  }
5794  }
5795  if (!NIL_P(encoding)) {
5796  extracted = 1;
5797  if (!NIL_P(tmp = rb_check_string_type(encoding))) {
5798  parse_mode_enc(StringValueCStr(tmp), rb_enc_get(tmp),
5799  enc_p, enc2_p, fmode_p);
5800  }
5801  else {
5802  rb_io_ext_int_to_encs(rb_to_encoding(encoding), NULL, enc_p, enc2_p, 0);
5803  }
5804  }
5805  else if (extenc != Qundef || intenc != Qundef) {
5806  extracted = 1;
5807  rb_io_ext_int_to_encs(extencoding, intencoding, enc_p, enc2_p, 0);
5808  }
5809  return extracted;
5810 }
5811 
5812 typedef struct rb_io_enc_t convconfig_t;
5813 
5814 static void
5815 validate_enc_binmode(int *fmode_p, int ecflags, rb_encoding *enc, rb_encoding *enc2)
5816 {
5817  int fmode = *fmode_p;
5818 
5819  if ((fmode & FMODE_READABLE) &&
5820  !enc2 &&
5821  !(fmode & FMODE_BINMODE) &&
5823  rb_raise(rb_eArgError, "ASCII incompatible encoding needs binmode");
5824 
5825  if ((fmode & FMODE_BINMODE) && (ecflags & ECONV_NEWLINE_DECORATOR_MASK)) {
5826  rb_raise(rb_eArgError, "newline decorator with binary mode");
5827  }
5828  if (!(fmode & FMODE_BINMODE) &&
5830  fmode |= FMODE_TEXTMODE;
5831  *fmode_p = fmode;
5832  }
5833 #if !DEFAULT_TEXTMODE
5834  else if (!(ecflags & ECONV_NEWLINE_DECORATOR_MASK)) {
5835  fmode &= ~FMODE_TEXTMODE;
5836  *fmode_p = fmode;
5837  }
5838 #endif
5839 }
5840 
5841 static void
5842 extract_binmode(VALUE opthash, int *fmode)
5843 {
5844  if (!NIL_P(opthash)) {
5845  VALUE v;
5846  v = rb_hash_aref(opthash, sym_textmode);
5847  if (!NIL_P(v)) {
5848  if (*fmode & FMODE_TEXTMODE)
5849  rb_raise(rb_eArgError, "textmode specified twice");
5850  if (*fmode & FMODE_BINMODE)
5851  rb_raise(rb_eArgError, "both textmode and binmode specified");
5852  if (RTEST(v))
5853  *fmode |= FMODE_TEXTMODE;
5854  }
5855  v = rb_hash_aref(opthash, sym_binmode);
5856  if (!NIL_P(v)) {
5857  if (*fmode & FMODE_BINMODE)
5858  rb_raise(rb_eArgError, "binmode specified twice");
5859  if (*fmode & FMODE_TEXTMODE)
5860  rb_raise(rb_eArgError, "both textmode and binmode specified");
5861  if (RTEST(v))
5862  *fmode |= FMODE_BINMODE;
5863  }
5864 
5865  if ((*fmode & FMODE_BINMODE) && (*fmode & FMODE_TEXTMODE))
5866  rb_raise(rb_eArgError, "both textmode and binmode specified");
5867  }
5868 }
5869 
5870 void
5871 rb_io_extract_modeenc(VALUE *vmode_p, VALUE *vperm_p, VALUE opthash,
5872  int *oflags_p, int *fmode_p, convconfig_t *convconfig_p)
5873 {
5874  VALUE vmode;
5875  int oflags, fmode;
5876  rb_encoding *enc, *enc2;
5877  int ecflags;
5878  VALUE ecopts;
5879  int has_enc = 0, has_vmode = 0;
5880  VALUE intmode;
5881 
5882  vmode = *vmode_p;
5883 
5884  /* Set to defaults */
5885  rb_io_ext_int_to_encs(NULL, NULL, &enc, &enc2, 0);
5886 
5887  vmode_handle:
5888  if (NIL_P(vmode)) {
5890  oflags = O_RDONLY;
5891  }
5892  else if (!NIL_P(intmode = rb_check_to_integer(vmode, "to_int"))) {
5893  vmode = intmode;
5894  oflags = NUM2INT(intmode);
5895  fmode = rb_io_oflags_fmode(oflags);
5896  }
5897  else {
5898  const char *p;
5899 
5900  SafeStringValue(vmode);
5901  p = StringValueCStr(vmode);
5903  oflags = rb_io_fmode_oflags(fmode);
5904  p = strchr(p, ':');
5905  if (p) {
5906  has_enc = 1;
5907  parse_mode_enc(p+1, rb_enc_get(vmode), &enc, &enc2, &fmode);
5908  }
5909  else {
5910  rb_encoding *e;
5911 
5913  rb_io_ext_int_to_encs(e, NULL, &enc, &enc2, fmode);
5914  }
5915  }
5916 
5917  if (NIL_P(opthash)) {
5918  ecflags = (fmode & FMODE_READABLE) ?
5921 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
5922  ecflags |= (fmode & FMODE_WRITABLE) ?
5923  MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE,
5924  0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE) : 0;
5925 #endif
5927  ecopts = Qnil;
5928  }
5929  else {
5930  VALUE v;
5931  if (!has_vmode) {
5932  v = rb_hash_aref(opthash, sym_mode);
5933  if (!NIL_P(v)) {
5934  if (!NIL_P(vmode)) {
5935  rb_raise(rb_eArgError, "mode specified twice");
5936  }
5937  has_vmode = 1;
5938  vmode = v;
5939  goto vmode_handle;
5940  }
5941  }
5942  v = rb_hash_aref(opthash, sym_flags);
5943  if (!NIL_P(v)) {
5944  v = rb_to_int(v);
5945  oflags |= NUM2INT(v);
5946  vmode = INT2NUM(oflags);
5947  fmode = rb_io_oflags_fmode(oflags);
5948  }
5949  extract_binmode(opthash, &fmode);
5950  if (fmode & FMODE_BINMODE) {
5951 #ifdef O_BINARY
5952  oflags |= O_BINARY;
5953 #endif
5954  if (!has_enc)
5955  rb_io_ext_int_to_encs(rb_ascii8bit_encoding(), NULL, &enc, &enc2, fmode);
5956  }
5957 #if DEFAULT_TEXTMODE
5958  else if (NIL_P(vmode)) {
5960  }
5961 #endif
5962  v = rb_hash_aref(opthash, sym_perm);
5963  if (!NIL_P(v)) {
5964  if (vperm_p) {
5965  if (!NIL_P(*vperm_p)) {
5966  rb_raise(rb_eArgError, "perm specified twice");
5967  }
5968  *vperm_p = v;
5969  }
5970  else {
5971  /* perm no use, just ignore */
5972  }
5973  }
5974  ecflags = (fmode & FMODE_READABLE) ?
5977 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
5978  ecflags |= (fmode & FMODE_WRITABLE) ?
5979  MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE,
5980  0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE) : 0;
5981 #endif
5982 
5983  if (rb_io_extract_encoding_option(opthash, &enc, &enc2, &fmode)) {
5984  if (has_enc) {
5985  rb_raise(rb_eArgError, "encoding specified twice");
5986  }
5987  }
5989  ecflags = rb_econv_prepare_options(opthash, &ecopts, ecflags);
5990  }
5991 
5992  validate_enc_binmode(&fmode, ecflags, enc, enc2);
5993 
5994  *vmode_p = vmode;
5995 
5996  *oflags_p = oflags;
5997  *fmode_p = fmode;
5998  convconfig_p->enc = enc;
5999  convconfig_p->enc2 = enc2;
6000  convconfig_p->ecflags = ecflags;
6001  convconfig_p->ecopts = ecopts;
6002 }
6003 
6006  int oflags;
6008 };
6009 
6010 static void *
6011 sysopen_func(void *ptr)
6012 {
6013  const struct sysopen_struct *data = ptr;
6014  const char *fname = RSTRING_PTR(data->fname);
6015  return (void *)(VALUE)rb_cloexec_open(fname, data->oflags, data->perm);
6016 }
6017 
6018 static inline int
6019 rb_sysopen_internal(struct sysopen_struct *data)
6020 {
6021  int fd;
6022  fd = (int)(VALUE)rb_thread_call_without_gvl(sysopen_func, data, RUBY_UBF_IO, 0);
6023  if (0 <= fd)
6024  rb_update_max_fd(fd);
6025  return fd;
6026 }
6027 
6028 static int
6029 rb_sysopen(VALUE fname, int oflags, mode_t perm)
6030 {
6031  int fd;
6032  struct sysopen_struct data;
6033 
6035  StringValueCStr(data.fname);
6036  data.oflags = oflags;
6037  data.perm = perm;
6038 
6039  fd = rb_sysopen_internal(&data);
6040  if (fd < 0) {
6041  int e = errno;
6042  if (rb_gc_for_fd(e)) {
6043  fd = rb_sysopen_internal(&data);
6044  }
6045  if (fd < 0) {
6047  }
6048  }
6049  return fd;
6050 }
6051 
6052 FILE *
6053 rb_fdopen(int fd, const char *modestr)
6054 {
6055  FILE *file;
6056 
6057 #if defined(__sun)
6058  errno = 0;
6059 #endif
6060  file = fdopen(fd, modestr);
6061  if (!file) {
6062  int e = errno;
6063 #if defined(__sun)
6064  if (e == 0) {
6065  rb_gc();
6066  errno = 0;
6067  file = fdopen(fd, modestr);
6068  }
6069  else
6070 #endif
6071  if (rb_gc_for_fd(e)) {
6072  file = fdopen(fd, modestr);
6073  }
6074  if (!file) {
6075 #ifdef _WIN32
6076  if (e == 0) e = EINVAL;
6077 #elif defined(__sun)
6078  if (e == 0) e = EMFILE;
6079 #endif
6080  rb_syserr_fail(e, 0);
6081  }
6082  }
6083 
6084  /* xxx: should be _IONBF? A buffer in FILE may have trouble. */
6085 #ifdef USE_SETVBUF
6086  if (setvbuf(file, NULL, _IOFBF, 0) != 0)
6087  rb_warn("setvbuf() can't be honoured (fd=%d)", fd);
6088 #endif
6089  return file;
6090 }
6091 
6092 static int
6093 io_check_tty(rb_io_t *fptr)
6094 {
6095  int t = isatty(fptr->fd);
6096  if (t)
6097  fptr->mode |= FMODE_TTY|FMODE_DUPLEX;
6098  return t;
6099 }
6100 
6101 static VALUE rb_io_internal_encoding(VALUE);
6102 static void io_encoding_set(rb_io_t *, VALUE, VALUE, VALUE);
6103 
6104 static int
6105 io_strip_bom(VALUE io)
6106 {
6107  VALUE b1, b2, b3, b4;
6108  rb_io_t *fptr;
6109 
6110  GetOpenFile(io, fptr);
6111  if (!(fptr->mode & FMODE_READABLE)) return 0;
6112  if (NIL_P(b1 = rb_io_getbyte(io))) return 0;
6113  switch (b1) {
6114  case INT2FIX(0xEF):
6115  if (NIL_P(b2 = rb_io_getbyte(io))) break;
6116  if (b2 == INT2FIX(0xBB) && !NIL_P(b3 = rb_io_getbyte(io))) {
6117  if (b3 == INT2FIX(0xBF)) {
6118  return rb_utf8_encindex();
6119  }
6120  rb_io_ungetbyte(io, b3);
6121  }
6122  rb_io_ungetbyte(io, b2);
6123  break;
6124 
6125  case INT2FIX(0xFE):
6126  if (NIL_P(b2 = rb_io_getbyte(io))) break;
6127  if (b2 == INT2FIX(0xFF)) {
6128  return ENCINDEX_UTF_16BE;
6129  }
6130  rb_io_ungetbyte(io, b2);
6131  break;
6132 
6133  case INT2FIX(0xFF):
6134  if (NIL_P(b2 = rb_io_getbyte(io))) break;
6135  if (b2 == INT2FIX(0xFE)) {
6136  b3 = rb_io_getbyte(io);
6137  if (b3 == INT2FIX(0) && !NIL_P(b4 = rb_io_getbyte(io))) {
6138  if (b4 == INT2FIX(0)) {
6139  return ENCINDEX_UTF_32LE;
6140  }
6141  rb_io_ungetbyte(io, b4);
6142  }
6143  rb_io_ungetbyte(io, b3);
6144  return ENCINDEX_UTF_16LE;
6145  }
6146  rb_io_ungetbyte(io, b2);
6147  break;
6148 
6149  case INT2FIX(0):
6150  if (NIL_P(b2 = rb_io_getbyte(io))) break;
6151  if (b2 == INT2FIX(0) && !NIL_P(b3 = rb_io_getbyte(io))) {
6152  if (b3 == INT2FIX(0xFE) && !NIL_P(b4 = rb_io_getbyte(io))) {
6153  if (b4 == INT2FIX(0xFF)) {
6154  return ENCINDEX_UTF_32BE;
6155  }
6156  rb_io_ungetbyte(io, b4);
6157  }
6158  rb_io_ungetbyte(io, b3);
6159  }
6160  rb_io_ungetbyte(io, b2);
6161  break;
6162  }
6163  rb_io_ungetbyte(io, b1);
6164  return 0;
6165 }
6166 
6167 static rb_encoding *
6168 io_set_encoding_by_bom(VALUE io)
6169 {
6170  int idx = io_strip_bom(io);
6171  rb_io_t *fptr;
6172  rb_encoding *extenc = NULL;
6173 
6174  GetOpenFile(io, fptr);
6175  if (idx) {
6176  extenc = rb_enc_from_index(idx);
6177  io_encoding_set(fptr, rb_enc_from_encoding(extenc),
6178  rb_io_internal_encoding(io), Qnil);
6179  }
6180  else {
6181  fptr->encs.enc2 = NULL;
6182  }
6183  return extenc;
6184 }
6185 
6186 static VALUE
6187 rb_file_open_generic(VALUE io, VALUE filename, int oflags, int fmode,
6188  const convconfig_t *convconfig, mode_t perm)
6189 {
6190  VALUE pathv;
6191  rb_io_t *fptr;
6192  convconfig_t cc;
6193  if (!convconfig) {
6194  /* Set to default encodings */
6195  rb_io_ext_int_to_encs(NULL, NULL, &cc.enc, &cc.enc2, fmode);
6196  cc.ecflags = 0;
6197  cc.ecopts = Qnil;
6198  convconfig = &cc;
6199  }
6200  validate_enc_binmode(&fmode, convconfig->ecflags,
6201  convconfig->enc, convconfig->enc2);
6202 
6203  MakeOpenFile(io, fptr);
6204  fptr->mode = fmode;
6205  fptr->encs = *convconfig;
6206  pathv = rb_str_new_frozen(filename);
6207 #ifdef O_TMPFILE
6208  if (!(oflags & O_TMPFILE)) {
6209  fptr->pathv = pathv;
6210  }
6211 #else
6212  fptr->pathv = pathv;
6213 #endif
6214  fptr->fd = rb_sysopen(pathv, oflags, perm);
6215  io_check_tty(fptr);
6216  if (fmode & FMODE_SETENC_BY_BOM) io_set_encoding_by_bom(io);
6217 
6218  return io;
6219 }
6220 
6221 static VALUE
6222 rb_file_open_internal(VALUE io, VALUE filename, const char *modestr)
6223 {
6224  int fmode = rb_io_modestr_fmode(modestr);
6225  const char *p = strchr(modestr, ':');
6226  convconfig_t convconfig;
6227 
6228  if (p) {
6229  parse_mode_enc(p+1, rb_usascii_encoding(),
6230  &convconfig.enc, &convconfig.enc2, &fmode);
6231  convconfig.ecflags = 0;
6232  convconfig.ecopts = Qnil;
6233  }
6234  else {
6235  rb_encoding *e;
6236  /* Set to default encodings */
6237 
6239  rb_io_ext_int_to_encs(e, NULL, &convconfig.enc, &convconfig.enc2, fmode);
6240  convconfig.ecflags = 0;
6241  convconfig.ecopts = Qnil;
6242  }
6243 
6244  return rb_file_open_generic(io, filename,
6245  rb_io_fmode_oflags(fmode),
6246  fmode,
6247  &convconfig,
6248  0666);
6249 }
6250 
6251 VALUE
6252 rb_file_open_str(VALUE fname, const char *modestr)
6253 {
6255  return rb_file_open_internal(io_alloc(rb_cFile), fname, modestr);
6256 }
6257 
6258 VALUE
6259 rb_file_open(const char *fname, const char *modestr)
6260 {
6261  return rb_file_open_internal(io_alloc(rb_cFile), rb_str_new_cstr(fname), modestr);
6262 }
6263 
6264 #if defined(__CYGWIN__) || !defined(HAVE_WORKING_FORK)
6265 static struct pipe_list {
6266  rb_io_t *fptr;
6267  struct pipe_list *next;
6268 } *pipe_list;
6269 
6270 static void
6271 pipe_add_fptr(rb_io_t *fptr)
6272 {
6273  struct pipe_list *list;
6274 
6275  list = ALLOC(struct pipe_list);
6276  list->fptr = fptr;
6277  list->next = pipe_list;
6278  pipe_list = list;
6279 }
6280 
6281 static void
6282 pipe_del_fptr(rb_io_t *fptr)
6283 {
6284  struct pipe_list **prev = &pipe_list;
6285  struct pipe_list *tmp;
6286 
6287  while ((tmp = *prev) != 0) {
6288  if (tmp->fptr == fptr) {
6289  *prev = tmp->next;
6290  free(tmp);
6291  return;
6292  }
6293  prev = &tmp->next;
6294  }
6295 }
6296 
6297 #if defined (_WIN32) || defined(__CYGWIN__)
6298 static void
6299 pipe_atexit(void)
6300 {
6301  struct pipe_list *list = pipe_list;
6302  struct pipe_list *tmp;
6303 
6304  while (list) {
6305  tmp = list->next;
6306  rb_io_fptr_finalize(list->fptr);
6307  list = tmp;
6308  }
6309 }
6310 #endif
6311 
6312 static void
6313 pipe_finalize(rb_io_t *fptr, int noraise)
6314 {
6315 #if !defined(HAVE_WORKING_FORK) && !defined(_WIN32)
6316  int status = 0;
6317  if (fptr->stdio_file) {
6318  status = pclose(fptr->stdio_file);
6319  }
6320  fptr->fd = -1;
6321  fptr->stdio_file = 0;
6322  rb_last_status_set(status, fptr->pid);
6323 #else
6324  fptr_finalize(fptr, noraise);
6325 #endif
6326  pipe_del_fptr(fptr);
6327 }
6328 #endif
6329 
6330 static void
6331 fptr_copy_finalizer(rb_io_t *fptr, const rb_io_t *orig)
6332 {
6333 #if defined(__CYGWIN__) || !defined(HAVE_WORKING_FORK)
6334  void (*const old_finalize)(struct rb_io_t*,int) = fptr->finalize;
6335 
6336  if (old_finalize == orig->finalize) return;
6337 #endif
6338 
6339  fptr->finalize = orig->finalize;
6340 
6341 #if defined(__CYGWIN__) || !defined(HAVE_WORKING_FORK)
6342  if (old_finalize != pipe_finalize) {
6343  struct pipe_list *list;
6344  for (list = pipe_list; list; list = list->next) {
6345  if (list->fptr == fptr) break;
6346  }
6347  if (!list) pipe_add_fptr(fptr);
6348  }
6349  else {
6350  pipe_del_fptr(fptr);
6351  }
6352 #endif
6353 }
6354 
6355 void
6357 {
6359  fptr->mode |= FMODE_SYNC;
6360 }
6361 
6362 void
6364 {
6365  rb_io_synchronized(fptr);
6366 }
6367 
6368 int
6369 rb_pipe(int *pipes)
6370 {
6371  int ret;
6372  ret = rb_cloexec_pipe(pipes);
6373  if (ret < 0) {
6374  if (rb_gc_for_fd(errno)) {
6375  ret = rb_cloexec_pipe(pipes);
6376  }
6377  }
6378  if (ret == 0) {
6379  rb_update_max_fd(pipes[0]);
6380  rb_update_max_fd(pipes[1]);
6381  }
6382  return ret;
6383 }
6384 
6385 #ifdef _WIN32
6386 #define HAVE_SPAWNV 1
6387 #define spawnv(mode, cmd, args) rb_w32_uaspawn((mode), (cmd), (args))
6388 #define spawn(mode, cmd) rb_w32_uspawn((mode), (cmd), 0)
6389 #endif
6390 
6391 #if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
6392 struct popen_arg {
6393  VALUE execarg_obj;
6394  struct rb_execarg *eargp;
6395  int modef;
6396  int pair[2];
6397  int write_pair[2];
6398 };
6399 #endif
6400 
6401 #ifdef HAVE_WORKING_FORK
6402 static void
6403 popen_redirect(struct popen_arg *p)
6404 {
6405  if ((p->modef & FMODE_READABLE) && (p->modef & FMODE_WRITABLE)) {
6406  close(p->write_pair[1]);
6407  if (p->write_pair[0] != 0) {
6408  dup2(p->write_pair[0], 0);
6409  close(p->write_pair[0]);
6410  }
6411  close(p->pair[0]);
6412  if (p->pair[1] != 1) {
6413  dup2(p->pair[1], 1);
6414  close(p->pair[1]);
6415  }
6416  }
6417  else if (p->modef & FMODE_READABLE) {
6418  close(p->pair[0]);
6419  if (p->pair[1] != 1) {
6420  dup2(p->pair[1], 1);
6421  close(p->pair[1]);
6422  }
6423  }
6424  else {
6425  close(p->pair[1]);
6426  if (p->pair[0] != 0) {
6427  dup2(p->pair[0], 0);
6428  close(p->pair[0]);
6429  }
6430  }
6431 }
6432 
6433 #if defined(__linux__)
6434 /* Linux /proc/self/status contains a line: "FDSize:\t<nnn>\n"
6435  * Since /proc may not be available, linux_get_maxfd is just a hint.
6436  * This function, linux_get_maxfd, must be async-signal-safe.
6437  * I.e. opendir() is not usable.
6438  *
6439  * Note that memchr() and memcmp is *not* async-signal-safe in POSIX.
6440  * However they are easy to re-implement in async-signal-safe manner.
6441  * (Also note that there is missing/memcmp.c.)
6442  */
6443 static int
6444 linux_get_maxfd(void)
6445 {
6446  int fd;
6447  char buf[4096], *p, *np, *e;
6448  ssize_t ss;
6449  fd = rb_cloexec_open("/proc/self/status", O_RDONLY|O_NOCTTY, 0);
6450  if (fd < 0) return fd;
6451  ss = read(fd, buf, sizeof(buf));
6452  if (ss < 0) goto err;
6453  p = buf;
6454  e = buf + ss;
6455  while ((int)sizeof("FDSize:\t0\n")-1 <= e-p &&
6456  (np = memchr(p, '\n', e-p)) != NULL) {
6457  if (memcmp(p, "FDSize:", sizeof("FDSize:")-1) == 0) {
6458  int fdsize;
6459  p += sizeof("FDSize:")-1;
6460  *np = '\0';
6461  fdsize = (int)ruby_strtoul(p, (char **)NULL, 10);
6462  close(fd);
6463  return fdsize;
6464  }
6465  p = np+1;
6466  }
6467  /* fall through */
6468 
6469  err:
6470  close(fd);
6471  return (int)ss;
6472 }
6473 #endif
6474 
6475 /* This function should be async-signal-safe. */
6476 void
6477 rb_close_before_exec(int lowfd, int maxhint, VALUE noclose_fds)
6478 {
6479 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
6480  int fd, ret;
6481  int max = (int)max_file_descriptor;
6482 # ifdef F_MAXFD
6483  /* F_MAXFD is available since NetBSD 2.0. */
6484  ret = fcntl(0, F_MAXFD); /* async-signal-safe */
6485  if (ret != -1)
6486  maxhint = max = ret;
6487 # elif defined(__linux__)
6488  ret = linux_get_maxfd();
6489  if (maxhint < ret)
6490  maxhint = ret;
6491  /* maxhint = max = ret; if (ret == -1) abort(); // test */
6492 # endif
6493  if (max < maxhint)
6494  max = maxhint;
6495  for (fd = lowfd; fd <= max; fd++) {
6496  if (!NIL_P(noclose_fds) &&
6497  RTEST(rb_hash_lookup(noclose_fds, INT2FIX(fd)))) /* async-signal-safe */
6498  continue;
6499  ret = fcntl(fd, F_GETFD); /* async-signal-safe */
6500  if (ret != -1 && !(ret & FD_CLOEXEC)) {
6501  fcntl(fd, F_SETFD, ret|FD_CLOEXEC); /* async-signal-safe */
6502  }
6503 # define CONTIGUOUS_CLOSED_FDS 20
6504  if (ret != -1) {
6505  if (max < fd + CONTIGUOUS_CLOSED_FDS)
6506  max = fd + CONTIGUOUS_CLOSED_FDS;
6507  }
6508  }
6509 #endif
6510 }
6511 
6512 static int
6513 popen_exec(void *pp, char *errmsg, size_t errmsg_len)
6514 {
6515  struct popen_arg *p = (struct popen_arg*)pp;
6516 
6517  return rb_exec_async_signal_safe(p->eargp, errmsg, errmsg_len);
6518 }
6519 #endif
6520 
6521 #if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
6522 static VALUE
6523 rb_execarg_fixup_v(VALUE execarg_obj)
6524 {
6525  rb_execarg_parent_start(execarg_obj);
6526  return Qnil;
6527 }
6528 #else
6529 char *rb_execarg_commandline(const struct rb_execarg *eargp, VALUE *prog);
6530 #endif
6531 
6532 static VALUE
6533 pipe_open(VALUE execarg_obj, const char *modestr, int fmode,
6534  const convconfig_t *convconfig)
6535 {
6536  struct rb_execarg *eargp = NIL_P(execarg_obj) ? NULL : rb_execarg_get(execarg_obj);
6537  VALUE prog = eargp ? (eargp->use_shell ? eargp->invoke.sh.shell_script : eargp->invoke.cmd.command_name) : Qfalse ;
6538  rb_pid_t pid = 0;
6539  rb_io_t *fptr;
6540  VALUE port;
6541  rb_io_t *write_fptr;
6542  VALUE write_port;
6543 #if defined(HAVE_WORKING_FORK)
6544  int status;
6545  char errmsg[80] = { '\0' };
6546 #endif
6547 #if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
6548  int state;
6549  struct popen_arg arg;
6550 #endif
6551  int e = 0;
6552 #if defined(HAVE_SPAWNV)
6553 # if defined(HAVE_SPAWNVE)
6554 # define DO_SPAWN(cmd, args, envp) ((args) ? \
6555  spawnve(P_NOWAIT, (cmd), (args), (envp)) : \
6556  spawne(P_NOWAIT, (cmd), (envp)))
6557 # else
6558 # define DO_SPAWN(cmd, args, envp) ((args) ? \
6559  spawnv(P_NOWAIT, (cmd), (args)) : \
6560  spawn(P_NOWAIT, (cmd)))
6561 # endif
6562 # if !defined(HAVE_WORKING_FORK)
6563  char **args = NULL;
6564 # if defined(HAVE_SPAWNVE)
6565  char **envp = NULL;
6566 # endif
6567 # endif
6568 #endif
6569 #if !defined(HAVE_WORKING_FORK)
6570  struct rb_execarg sarg, *sargp = &sarg;
6571 #endif
6572  FILE *fp = 0;
6573  int fd = -1;
6574  int write_fd = -1;
6575 #if !defined(HAVE_WORKING_FORK)
6576  const char *cmd = 0;
6577 
6578  if (prog)
6579  cmd = StringValueCStr(prog);
6580 #endif
6581 
6582 #if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
6583  arg.execarg_obj = execarg_obj;
6584  arg.eargp = eargp;
6585  arg.modef = fmode;
6586  arg.pair[0] = arg.pair[1] = -1;
6587  arg.write_pair[0] = arg.write_pair[1] = -1;
6588 # if !defined(HAVE_WORKING_FORK)
6589  if (eargp && !eargp->use_shell) {
6590  args = ARGVSTR2ARGV(eargp->invoke.cmd.argv_str);
6591  }
6592 # endif
6593  switch (fmode & (FMODE_READABLE|FMODE_WRITABLE)) {
6595  if (rb_pipe(arg.write_pair) < 0)
6596  rb_sys_fail_str(prog);
6597  if (rb_pipe(arg.pair) < 0) {
6598  e = errno;
6599  close(arg.write_pair[0]);
6600  close(arg.write_pair[1]);
6601  rb_syserr_fail_str(e, prog);
6602  }
6603  if (eargp) {
6604  rb_execarg_addopt(execarg_obj, INT2FIX(0), INT2FIX(arg.write_pair[0]));
6605  rb_execarg_addopt(execarg_obj, INT2FIX(1), INT2FIX(arg.pair[1]));
6606  }
6607  break;
6608  case FMODE_READABLE:
6609  if (rb_pipe(arg.pair) < 0)
6610  rb_sys_fail_str(prog);
6611  if (eargp)
6612  rb_execarg_addopt(execarg_obj, INT2FIX(1), INT2FIX(arg.pair[1]));
6613  break;
6614  case FMODE_WRITABLE:
6615  if (rb_pipe(arg.pair) < 0)
6616  rb_sys_fail_str(prog);
6617  if (eargp)
6618  rb_execarg_addopt(execarg_obj, INT2FIX(0), INT2FIX(arg.pair[0]));
6619  break;
6620  default:
6621  rb_sys_fail_str(prog);
6622  }
6623  if (!NIL_P(execarg_obj)) {
6624  rb_protect(rb_execarg_fixup_v, execarg_obj, &state);
6625  if (state) {
6626  if (0 <= arg.write_pair[0]) close(arg.write_pair[0]);
6627  if (0 <= arg.write_pair[1]) close(arg.write_pair[1]);
6628  if (0 <= arg.pair[0]) close(arg.pair[0]);
6629  if (0 <= arg.pair[1]) close(arg.pair[1]);
6630  rb_execarg_parent_end(execarg_obj);
6631  rb_jump_tag(state);
6632  }
6633 
6634 # if defined(HAVE_WORKING_FORK)
6635  pid = rb_fork_async_signal_safe(&status, popen_exec, &arg, arg.eargp->redirect_fds, errmsg, sizeof(errmsg));
6636 # else
6637  rb_execarg_run_options(eargp, sargp, NULL, 0);
6638 # if defined(HAVE_SPAWNVE)
6639  if (eargp->envp_str) envp = (char **)RSTRING_PTR(eargp->envp_str);
6640 # endif
6641  while ((pid = DO_SPAWN(cmd, args, envp)) < 0) {
6642  /* exec failed */
6643  switch (e = errno) {
6644  case EAGAIN:
6645 # if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
6646  case EWOULDBLOCK:
6647 # endif
6648  rb_thread_sleep(1);
6649  continue;
6650  }
6651  break;
6652  }
6653  if (eargp)
6654  rb_execarg_run_options(sargp, NULL, NULL, 0);
6655 # endif
6656  rb_execarg_parent_end(execarg_obj);
6657  }
6658  else {
6659 # if defined(HAVE_WORKING_FORK)
6660  pid = rb_fork_ruby(&status);
6661  if (pid == 0) { /* child */
6662  rb_thread_atfork();
6663  popen_redirect(&arg);
6664  rb_io_synchronized(RFILE(orig_stdout)->fptr);
6665  rb_io_synchronized(RFILE(orig_stderr)->fptr);
6666  return Qnil;
6667  }
6668 # else
6669  rb_notimplement();
6670 # endif
6671  }
6672 
6673  /* parent */
6674  if (pid < 0) {
6675 # if defined(HAVE_WORKING_FORK)
6676  e = errno;
6677 # endif
6678  close(arg.pair[0]);
6679  close(arg.pair[1]);
6681  close(arg.write_pair[0]);
6682  close(arg.write_pair[1]);
6683  }
6684 # if defined(HAVE_WORKING_FORK)
6685  if (errmsg[0])
6686  rb_syserr_fail(e, errmsg);
6687 # endif
6688  rb_syserr_fail_str(e, prog);
6689  }
6690  if ((fmode & FMODE_READABLE) && (fmode & FMODE_WRITABLE)) {
6691  close(arg.pair[1]);
6692  fd = arg.pair[0];
6693  close(arg.write_pair[0]);
6694  write_fd = arg.write_pair[1];
6695  }
6696  else if (fmode & FMODE_READABLE) {
6697  close(arg.pair[1]);
6698  fd = arg.pair[0];
6699  }
6700  else {
6701  close(arg.pair[0]);
6702  fd = arg.pair[1];
6703  }
6704 #else
6705  cmd = rb_execarg_commandline(eargp, &prog);
6706  if (!NIL_P(execarg_obj)) {
6707  rb_execarg_parent_start(execarg_obj);
6708  rb_execarg_run_options(eargp, sargp, NULL, 0);
6709  }
6710  fp = popen(cmd, modestr);
6711  e = errno;
6712  if (eargp) {
6713  rb_execarg_parent_end(execarg_obj);
6714  rb_execarg_run_options(sargp, NULL, NULL, 0);
6715  }
6716  if (!fp) rb_syserr_fail_path(e, prog);
6717  fd = fileno(fp);
6718 #endif
6719 
6720  port = io_alloc(rb_cIO);
6721  MakeOpenFile(port, fptr);
6722  fptr->fd = fd;
6723  fptr->stdio_file = fp;
6724  fptr->mode = fmode | FMODE_SYNC|FMODE_DUPLEX;
6725  if (convconfig) {
6726  fptr->encs = *convconfig;
6727 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
6730  }
6731 #endif
6732  }
6733  else {
6734  if (NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {
6736  }
6737 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
6738  if (NEED_NEWLINE_DECORATOR_ON_WRITE(fptr)) {
6739  fptr->encs.ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
6740  }
6741 #endif
6742  }
6743  fptr->pid = pid;
6744 
6745  if (0 <= write_fd) {
6746  write_port = io_alloc(rb_cIO);
6747  MakeOpenFile(write_port, write_fptr);
6748  write_fptr->fd = write_fd;
6749  write_fptr->mode = (fmode & ~FMODE_READABLE)| FMODE_SYNC|FMODE_DUPLEX;
6750  fptr->mode &= ~FMODE_WRITABLE;
6751  fptr->tied_io_for_writing = write_port;
6752  rb_ivar_set(port, rb_intern("@tied_io_for_writing"), write_port);
6753  }
6754 
6755 #if defined (__CYGWIN__) || !defined(HAVE_WORKING_FORK)
6756  fptr->finalize = pipe_finalize;
6757  pipe_add_fptr(fptr);
6758 #endif
6759  return port;
6760 }
6761 
6762 static int
6763 is_popen_fork(VALUE prog)
6764 {
6765  if (RSTRING_LEN(prog) == 1 && RSTRING_PTR(prog)[0] == '-') {
6766 #if !defined(HAVE_WORKING_FORK)
6768  "fork() function is unimplemented on this machine");
6769 #else
6770  return TRUE;
6771 #endif
6772  }
6773  return FALSE;
6774 }
6775 
6776 static VALUE
6777 pipe_open_s(VALUE prog, const char *modestr, int fmode,
6778  const convconfig_t *convconfig)
6779 {
6780  int argc = 1;
6781  VALUE *argv = &prog;
6782  VALUE execarg_obj = Qnil;
6783 
6784  if (!is_popen_fork(prog))
6785  execarg_obj = rb_execarg_new(argc, argv, TRUE, FALSE);
6786  return pipe_open(execarg_obj, modestr, fmode, convconfig);
6787 }
6788 
6789 static VALUE
6790 pipe_close(VALUE io)
6791 {
6792  rb_io_t *fptr = io_close_fptr(io);
6793  if (fptr) {
6794  fptr_waitpid(fptr, rb_thread_to_be_killed(rb_thread_current()));
6795  }
6796  return Qnil;
6797 }
6798 
6799 /*
6800  * call-seq:
6801  * IO.popen([env,] cmd, mode="r" [, opt]) -> io
6802  * IO.popen([env,] cmd, mode="r" [, opt]) {|io| block } -> obj
6803  *
6804  * Runs the specified command as a subprocess; the subprocess's
6805  * standard input and output will be connected to the returned
6806  * IO object.
6807  *
6808  * The PID of the started process can be obtained by IO#pid method.
6809  *
6810  * _cmd_ is a string or an array as follows.
6811  *
6812  * cmd:
6813  * "-" : fork
6814  * commandline : command line string which is passed to a shell
6815  * [env, cmdname, arg1, ..., opts] : command name and zero or more arguments (no shell)
6816  * [env, [cmdname, argv0], arg1, ..., opts] : command name, argv[0] and zero or more arguments (no shell)
6817  * (env and opts are optional.)
6818  *
6819  * If _cmd_ is a +String+ ``<code>-</code>'',
6820  * then a new instance of Ruby is started as the subprocess.
6821  *
6822  * If <i>cmd</i> is an +Array+ of +String+,
6823  * then it will be used as the subprocess's +argv+ bypassing a shell.
6824  * The array can contain a hash at first for environments and
6825  * a hash at last for options similar to #spawn.
6826  *
6827  * The default mode for the new file object is ``r'',
6828  * but <i>mode</i> may be set to any of the modes listed in the description for class IO.
6829  * The last argument <i>opt</i> qualifies <i>mode</i>.
6830  *
6831  * # set IO encoding
6832  * IO.popen("nkf -e filename", :external_encoding=>"EUC-JP") {|nkf_io|
6833  * euc_jp_string = nkf_io.read
6834  * }
6835  *
6836  * # merge standard output and standard error using
6837  * # spawn option. See the document of Kernel.spawn.
6838  * IO.popen(["ls", "/", :err=>[:child, :out]]) {|ls_io|
6839  * ls_result_with_error = ls_io.read
6840  * }
6841  *
6842  * # spawn options can be mixed with IO options
6843  * IO.popen(["ls", "/"], :err=>[:child, :out]) {|ls_io|
6844  * ls_result_with_error = ls_io.read
6845  * }
6846  *
6847  * Raises exceptions which IO.pipe and Kernel.spawn raise.
6848  *
6849  * If a block is given, Ruby will run the command as a child connected
6850  * to Ruby with a pipe. Ruby's end of the pipe will be passed as a
6851  * parameter to the block.
6852  * At the end of block, Ruby closes the pipe and sets <code>$?</code>.
6853  * In this case IO.popen returns the value of the block.
6854  *
6855  * If a block is given with a _cmd_ of ``<code>-</code>'',
6856  * the block will be run in two separate processes: once in the parent,
6857  * and once in a child. The parent process will be passed the pipe
6858  * object as a parameter to the block, the child version of the block
6859  * will be passed +nil+, and the child's standard in and
6860  * standard out will be connected to the parent through the pipe. Not
6861  * available on all platforms.
6862  *
6863  * f = IO.popen("uname")
6864  * p f.readlines
6865  * f.close
6866  * puts "Parent is #{Process.pid}"
6867  * IO.popen("date") {|f| puts f.gets }
6868  * IO.popen("-") {|f| $stderr.puts "#{Process.pid} is here, f is #{f.inspect}"}
6869  * p $?
6870  * IO.popen(%w"sed -e s|^|<foo>| -e s&$&;zot;&", "r+") {|f|
6871  * f.puts "bar"; f.close_write; puts f.gets
6872  * }
6873  *
6874  * <em>produces:</em>
6875  *
6876  * ["Linux\n"]
6877  * Parent is 21346
6878  * Thu Jan 15 22:41:19 JST 2009
6879  * 21346 is here, f is #<IO:fd 3>
6880  * 21352 is here, f is nil
6881  * #<Process::Status: pid 21352 exit 0>
6882  * <foo>bar;zot;
6883  */
6884 
6885 static VALUE
6886 rb_io_s_popen(int argc, VALUE *argv, VALUE klass)
6887 {
6888  const char *modestr;
6889  VALUE pname, pmode = Qnil, port, tmp, opt = Qnil, env = Qnil, execarg_obj = Qnil;
6890  int oflags, fmode;
6891  convconfig_t convconfig;
6892 
6893  if (argc > 1 && !NIL_P(opt = rb_check_hash_type(argv[argc-1]))) --argc;
6894  if (argc > 1 && !NIL_P(env = rb_check_hash_type(argv[0]))) --argc, ++argv;
6895  switch (argc) {
6896  case 2:
6897  pmode = argv[1];
6898  case 1:
6899  pname = argv[0];
6900  break;
6901  default:
6902  {
6903  int ex = !NIL_P(opt);
6904  rb_error_arity(argc + ex, 1 + ex, 2 + ex);
6905  }
6906  }
6907 
6908  tmp = rb_check_array_type(pname);
6909  if (!NIL_P(tmp)) {
6910  long len = RARRAY_LEN(tmp);
6911 #if SIZEOF_LONG > SIZEOF_INT
6912  if (len > INT_MAX) {
6913  rb_raise(rb_eArgError, "too many arguments");
6914  }
6915 #endif
6916  execarg_obj = rb_execarg_new((int)len, RARRAY_CONST_PTR(tmp), FALSE, FALSE);
6917  RB_GC_GUARD(tmp);
6918  }
6919  else {
6920  SafeStringValue(pname);
6921  execarg_obj = Qnil;
6922  if (!is_popen_fork(pname))
6923  execarg_obj = rb_execarg_new(1, &pname, TRUE, FALSE);
6924  }
6925  if (!NIL_P(execarg_obj)) {
6926  if (!NIL_P(opt))
6927  opt = rb_execarg_extract_options(execarg_obj, opt);
6928  if (!NIL_P(env))
6929  rb_execarg_setenv(execarg_obj, env);
6930  }
6931  rb_io_extract_modeenc(&pmode, 0, opt, &oflags, &fmode, &convconfig);
6932  modestr = rb_io_oflags_modestr(oflags);
6933 
6934  port = pipe_open(execarg_obj, modestr, fmode, &convconfig);
6935  if (NIL_P(port)) {
6936  /* child */
6937  if (rb_block_given_p()) {
6938  rb_yield(Qnil);
6941  _exit(0);
6942  }
6943  return Qnil;
6944  }
6945  RBASIC_SET_CLASS(port, klass);
6946  if (rb_block_given_p()) {
6947  return rb_ensure(rb_yield, port, pipe_close, port);
6948  }
6949  return port;
6950 }
6951 
6952 static void
6953 rb_scan_open_args(int argc, const VALUE *argv,
6954  VALUE *fname_p, int *oflags_p, int *fmode_p,
6955  convconfig_t *convconfig_p, mode_t *perm_p)
6956 {
6957  VALUE opt, fname, vmode, vperm;
6958  int oflags, fmode;
6959  mode_t perm;
6960 
6961  argc = rb_scan_args(argc, argv, "12:", &fname, &vmode, &vperm, &opt);
6962  FilePathValue(fname);
6963 
6964  rb_io_extract_modeenc(&vmode, &vperm, opt, &oflags, &fmode, convconfig_p);
6965 
6966  perm = NIL_P(vperm) ? 0666 : NUM2MODET(vperm);
6967 
6968  *fname_p = fname;
6969  *oflags_p = oflags;
6970  *fmode_p = fmode;
6971  *perm_p = perm;
6972 }
6973 
6974 static VALUE
6975 rb_open_file(int argc, const VALUE *argv, VALUE io)
6976 {
6977  VALUE fname;
6978  int oflags, fmode;
6979  convconfig_t convconfig;
6980  mode_t perm;
6981 
6982  rb_scan_open_args(argc, argv, &fname, &oflags, &fmode, &convconfig, &perm);
6983  rb_file_open_generic(io, fname, oflags, fmode, &convconfig, perm);
6984 
6985  return io;
6986 }
6987 
6988 
6989 /*
6990  * Document-method: File::open
6991  *
6992  * call-seq:
6993  * File.open(filename, mode="r" [, opt]) -> file
6994  * File.open(filename [, mode [, perm]] [, opt]) -> file
6995  * File.open(filename, mode="r" [, opt]) {|file| block } -> obj
6996  * File.open(filename [, mode [, perm]] [, opt]) {|file| block } -> obj
6997  *
6998  * With no associated block, File.open is a synonym for
6999  * File.new. If the optional code block is given, it will
7000  * be passed the opened +file+ as an argument and the File object will
7001  * automatically be closed when the block terminates. The value of the block
7002  * will be returned from File.open.
7003  *
7004  * If a file is being created, its initial permissions may be set using the
7005  * +perm+ parameter. See File.new for further discussion.
7006  *
7007  * See IO.new for a description of the +mode+ and +opt+ parameters.
7008  */
7009 
7010 /*
7011  * Document-method: IO::open
7012  *
7013  * call-seq:
7014  * IO.open(fd, mode="r" [, opt]) -> io
7015  * IO.open(fd, mode="r" [, opt]) {|io| block } -> obj
7016  *
7017  * With no associated block, IO.open is a synonym for IO.new. If
7018  * the optional code block is given, it will be passed +io+ as an argument,
7019  * and the IO object will automatically be closed when the block terminates.
7020  * In this instance, IO.open returns the value of the block.
7021  *
7022  * See IO.new for a description of the +fd+, +mode+ and +opt+ parameters.
7023  */
7024 
7025 static VALUE
7026 rb_io_s_open(int argc, VALUE *argv, VALUE klass)
7027 {
7029 
7030  if (rb_block_given_p()) {
7031  return rb_ensure(rb_yield, io, io_close, io);
7032  }
7033 
7034  return io;
7035 }
7036 
7037 /*
7038  * call-seq:
7039  * IO.sysopen(path, [mode, [perm]]) -> integer
7040  *
7041  * Opens the given path, returning the underlying file descriptor as a
7042  * Integer.
7043  *
7044  * IO.sysopen("testfile") #=> 3
7045  */
7046 
7047 static VALUE
7048 rb_io_s_sysopen(int argc, VALUE *argv, VALUE _)
7049 {
7050  VALUE fname, vmode, vperm;
7051  VALUE intmode;
7052  int oflags, fd;
7053  mode_t perm;
7054 
7055  rb_scan_args(argc, argv, "12", &fname, &vmode, &vperm);
7056  FilePathValue(fname);
7057 
7058  if (NIL_P(vmode))
7059  oflags = O_RDONLY;
7060  else if (!NIL_P(intmode = rb_check_to_integer(vmode, "to_int")))
7061  oflags = NUM2INT(intmode);
7062  else {
7063  SafeStringValue(vmode);
7064  oflags = rb_io_modestr_oflags(StringValueCStr(vmode));
7065  }
7066  if (NIL_P(vperm)) perm = 0666;
7067  else perm = NUM2MODET(vperm);
7068 
7069  RB_GC_GUARD(fname) = rb_str_new4(fname);
7070  fd = rb_sysopen(fname, oflags, perm);
7071  return INT2NUM(fd);
7072 }
7073 
7074 static VALUE
7075 check_pipe_command(VALUE filename_or_command)
7076 {
7077  char *s = RSTRING_PTR(filename_or_command);
7078  long l = RSTRING_LEN(filename_or_command);
7079  char *e = s + l;
7080  int chlen;
7081 
7082  if (rb_enc_ascget(s, e, &chlen, rb_enc_get(filename_or_command)) == '|') {
7083  VALUE cmd = rb_str_new(s+chlen, l-chlen);
7084  return cmd;
7085  }
7086  return Qnil;
7087 }
7088 
7089 /*
7090  * call-seq:
7091  * open(path [, mode [, perm]] [, opt]) -> io or nil
7092  * open(path [, mode [, perm]] [, opt]) {|io| block } -> obj
7093  *
7094  * Creates an IO object connected to the given stream, file, or subprocess.
7095  *
7096  * If +path+ does not start with a pipe character (<code>|</code>), treat it
7097  * as the name of a file to open using the specified mode (defaulting to
7098  * "r").
7099  *
7100  * The +mode+ is either a string or an integer. If it is an integer, it
7101  * must be bitwise-or of open(2) flags, such as File::RDWR or File::EXCL. If
7102  * it is a string, it is either "fmode", "fmode:ext_enc", or
7103  * "fmode:ext_enc:int_enc".
7104  *
7105  * See the documentation of IO.new for full documentation of the +mode+ string
7106  * directives.
7107  *
7108  * If a file is being created, its initial permissions may be set using the
7109  * +perm+ parameter. See File.new and the open(2) and chmod(2) man pages for
7110  * a description of permissions.
7111  *
7112  * If a block is specified, it will be invoked with the IO object as a
7113  * parameter, and the IO will be automatically closed when the block
7114  * terminates. The call returns the value of the block.
7115  *
7116  * If +path+ starts with a pipe character (<code>"|"</code>), a subprocess is
7117  * created, connected to the caller by a pair of pipes. The returned IO
7118  * object may be used to write to the standard input and read from the
7119  * standard output of this subprocess.
7120  *
7121  * If the command following the pipe is a single minus sign
7122  * (<code>"|-"</code>), Ruby forks, and this subprocess is connected to the
7123  * parent. If the command is not <code>"-"</code>, the subprocess runs the
7124  * command.
7125  *
7126  * When the subprocess is Ruby (opened via <code>"|-"</code>), the +open+
7127  * call returns +nil+. If a block is associated with the open call, that
7128  * block will run twice --- once in the parent and once in the child.
7129  *
7130  * The block parameter will be an IO object in the parent and +nil+ in the
7131  * child. The parent's +IO+ object will be connected to the child's $stdin
7132  * and $stdout. The subprocess will be terminated at the end of the block.
7133  *
7134  * === Examples
7135  *
7136  * Reading from "testfile":
7137  *
7138  * open("testfile") do |f|
7139  * print f.gets
7140  * end
7141  *
7142  * Produces:
7143  *
7144  * This is line one
7145  *
7146  * Open a subprocess and read its output:
7147  *
7148  * cmd = open("|date")
7149  * print cmd.gets
7150  * cmd.close
7151  *
7152  * Produces:
7153  *
7154  * Wed Apr 9 08:56:31 CDT 2003
7155  *
7156  * Open a subprocess running the same Ruby program:
7157  *
7158  * f = open("|-", "w+")
7159  * if f.nil?
7160  * puts "in Child"
7161  * exit
7162  * else
7163  * puts "Got: #{f.gets}"
7164  * end
7165  *
7166  * Produces:
7167  *
7168  * Got: in Child
7169  *
7170  * Open a subprocess using a block to receive the IO object:
7171  *
7172  * open "|-" do |f|
7173  * if f then
7174  * # parent process
7175  * puts "Got: #{f.gets}"
7176  * else
7177  * # child process
7178  * puts "in Child"
7179  * end
7180  * end
7181  *
7182  * Produces:
7183  *
7184  * Got: in Child
7185  */
7186 
7187 static VALUE
7188 rb_f_open(int argc, VALUE *argv, VALUE _)
7189 {
7190  ID to_open = 0;
7191  int redirect = FALSE;
7192 
7193  if (argc >= 1) {
7194  CONST_ID(to_open, "to_open");
7195  if (rb_respond_to(argv[0], to_open)) {
7196  redirect = TRUE;
7197  }
7198  else {
7199  VALUE tmp = argv[0];
7200  FilePathValue(tmp);
7201  if (NIL_P(tmp)) {
7202  redirect = TRUE;
7203  }
7204  else {
7205  VALUE cmd = check_pipe_command(tmp);
7206  if (!NIL_P(cmd)) {
7207  argv[0] = cmd;
7208  return rb_io_s_popen(argc, argv, rb_cIO);
7209  }
7210  }
7211  }
7212  }
7213  if (redirect) {
7214  VALUE io = rb_funcallv_kw(argv[0], to_open, argc-1, argv+1, RB_PASS_CALLED_KEYWORDS);
7215 
7216  if (rb_block_given_p()) {
7217  return rb_ensure(rb_yield, io, io_close, io);
7218  }
7219  return io;
7220  }
7221  return rb_io_s_open(argc, argv, rb_cFile);
7222 }
7223 
7224 static VALUE rb_io_open_generic(VALUE, VALUE, int, int, const convconfig_t *, mode_t);
7225 
7226 static VALUE
7227 rb_io_open(VALUE io, VALUE filename, VALUE vmode, VALUE vperm, VALUE opt)
7228 {
7229  int oflags, fmode;
7230  convconfig_t convconfig;
7231  mode_t perm;
7232 
7233  rb_io_extract_modeenc(&vmode, &vperm, opt, &oflags, &fmode, &convconfig);
7234  perm = NIL_P(vperm) ? 0666 : NUM2MODET(vperm);
7235  return rb_io_open_generic(io, filename, oflags, fmode, &convconfig, perm);
7236 }
7237 
7238 static VALUE
7239 rb_io_open_generic(VALUE klass, VALUE filename, int oflags, int fmode,
7240  const convconfig_t *convconfig, mode_t perm)
7241 {
7242  VALUE cmd;
7243  if (klass == rb_cIO && !NIL_P(cmd = check_pipe_command(filename))) {
7244  return pipe_open_s(cmd, rb_io_oflags_modestr(oflags), fmode, convconfig);
7245  }
7246  else {
7247  return rb_file_open_generic(io_alloc(klass), filename,
7248  oflags, fmode, convconfig, perm);
7249  }
7250 }
7251 
7252 static VALUE
7253 io_reopen(VALUE io, VALUE nfile)
7254 {
7255  rb_io_t *fptr, *orig;
7256  int fd, fd2;
7257  off_t pos = 0;
7258 
7259  nfile = rb_io_get_io(nfile);
7260  GetOpenFile(io, fptr);
7261  GetOpenFile(nfile, orig);
7262 
7263  if (fptr == orig) return io;
7264  if (IS_PREP_STDIO(fptr)) {
7265  if ((fptr->stdio_file == stdin && !(orig->mode & FMODE_READABLE)) ||
7266  (fptr->stdio_file == stdout && !(orig->mode & FMODE_WRITABLE)) ||
7267  (fptr->stdio_file == stderr && !(orig->mode & FMODE_WRITABLE))) {
7269  "%s can't change access mode from \"%s\" to \"%s\"",
7270  PREP_STDIO_NAME(fptr), rb_io_fmode_modestr(fptr->mode),
7271  rb_io_fmode_modestr(orig->mode));
7272  }
7273  }
7274  if (fptr->mode & FMODE_WRITABLE) {
7275  if (io_fflush(fptr) < 0)
7276  rb_sys_fail(0);
7277  }
7278  else {
7279  flush_before_seek(fptr);
7280  }
7281  if (orig->mode & FMODE_READABLE) {
7282  pos = io_tell(orig);
7283  }
7284  if (orig->mode & FMODE_WRITABLE) {
7285  if (io_fflush(orig) < 0)
7286  rb_sys_fail(0);
7287  }
7288 
7289  /* copy rb_io_t structure */
7290  fptr->mode = orig->mode | (fptr->mode & FMODE_PREP);
7291  fptr->pid = orig->pid;
7292  fptr->lineno = orig->lineno;
7293  if (RTEST(orig->pathv)) fptr->pathv = orig->pathv;
7294  else if (!IS_PREP_STDIO(fptr)) fptr->pathv = Qnil;
7295  fptr_copy_finalizer(fptr, orig);
7296 
7297  fd = fptr->fd;
7298  fd2 = orig->fd;
7299  if (fd != fd2) {
7300  if (IS_PREP_STDIO(fptr) || fd <= 2 || !fptr->stdio_file) {
7301  /* need to keep FILE objects of stdin, stdout and stderr */
7302  if (rb_cloexec_dup2(fd2, fd) < 0)
7303  rb_sys_fail_path(orig->pathv);
7304  rb_update_max_fd(fd);
7305  }
7306  else {
7307  fclose(fptr->stdio_file);
7308  fptr->stdio_file = 0;
7309  fptr->fd = -1;
7310  if (rb_cloexec_dup2(fd2, fd) < 0)
7311  rb_sys_fail_path(orig->pathv);
7312  rb_update_max_fd(fd);
7313  fptr->fd = fd;
7314  }
7315  rb_thread_fd_close(fd);
7316  if ((orig->mode & FMODE_READABLE) && pos >= 0) {
7317  if (io_seek(fptr, pos, SEEK_SET) < 0 && errno) {
7318  rb_sys_fail_path(fptr->pathv);
7319  }
7320  if (io_seek(orig, pos, SEEK_SET) < 0 && errno) {
7321  rb_sys_fail_path(orig->pathv);
7322  }
7323  }
7324  }
7325 
7326  if (fptr->mode & FMODE_BINMODE) {
7327  rb_io_binmode(io);
7328  }
7329 
7330  RBASIC_SET_CLASS(io, rb_obj_class(nfile));
7331  return io;
7332 }
7333 
7334 #ifdef _WIN32
7335 int rb_freopen(VALUE fname, const char *mode, FILE *fp);
7336 #else
7337 static int
7338 rb_freopen(VALUE fname, const char *mode, FILE *fp)
7339 {
7340  if (!freopen(RSTRING_PTR(fname), mode, fp)) {
7341  RB_GC_GUARD(fname);
7342  return errno;
7343  }
7344  return 0;
7345 }
7346 #endif
7347 
7348 /*
7349  * call-seq:
7350  * ios.reopen(other_IO) -> ios
7351  * ios.reopen(path, mode [, opt]) -> ios
7352  *
7353  * Reassociates <em>ios</em> with the I/O stream given in
7354  * <i>other_IO</i> or to a new stream opened on <i>path</i>. This may
7355  * dynamically change the actual class of this stream.
7356  * The +mode+ and +opt+ parameters accept the same values as IO.open.
7357  *
7358  * f1 = File.new("testfile")
7359  * f2 = File.new("testfile")
7360  * f2.readlines[0] #=> "This is line one\n"
7361  * f2.reopen(f1) #=> #<File:testfile>
7362  * f2.readlines[0] #=> "This is line one\n"
7363  */
7364 
7365 static VALUE
7366 rb_io_reopen(int argc, VALUE *argv, VALUE file)
7367 {
7368  VALUE fname, nmode, opt;
7369  int oflags;
7370  rb_io_t *fptr;
7371 
7372  if (rb_scan_args(argc, argv, "11:", &fname, &nmode, &opt) == 1) {
7373  VALUE tmp = rb_io_check_io(fname);
7374  if (!NIL_P(tmp)) {
7375  return io_reopen(file, tmp);
7376  }
7377  }
7378 
7379  FilePathValue(fname);
7380  rb_io_taint_check(file);
7381  fptr = RFILE(file)->fptr;
7382  if (!fptr) {
7383  fptr = RFILE(file)->fptr = ZALLOC(rb_io_t);
7384  }
7385 
7386  if (!NIL_P(nmode) || !NIL_P(opt)) {
7387  int fmode;
7388  convconfig_t convconfig;
7389 
7390  rb_io_extract_modeenc(&nmode, 0, opt, &oflags, &fmode, &convconfig);
7391  if (IS_PREP_STDIO(fptr) &&
7392  ((fptr->mode & FMODE_READWRITE) & (fmode & FMODE_READWRITE)) !=
7393  (fptr->mode & FMODE_READWRITE)) {
7395  "%s can't change access mode from \"%s\" to \"%s\"",
7396  PREP_STDIO_NAME(fptr), rb_io_fmode_modestr(fptr->mode),
7397  rb_io_fmode_modestr(fmode));
7398  }
7399  fptr->mode = fmode;
7400  fptr->encs = convconfig;
7401  }
7402  else {
7403  oflags = rb_io_fmode_oflags(fptr->mode);
7404  }
7405 
7406  fptr->pathv = fname;
7407  if (fptr->fd < 0) {
7408  fptr->fd = rb_sysopen(fptr->pathv, oflags, 0666);
7409  fptr->stdio_file = 0;
7410  return file;
7411  }
7412 
7413  if (fptr->mode & FMODE_WRITABLE) {
7414  if (io_fflush(fptr) < 0)
7415  rb_sys_fail(0);
7416  }
7417  fptr->rbuf.off = fptr->rbuf.len = 0;
7418 
7419  if (fptr->stdio_file) {
7420  int e = rb_freopen(rb_str_encode_ospath(fptr->pathv),
7421  rb_io_oflags_modestr(oflags),
7422  fptr->stdio_file);
7423  if (e) rb_syserr_fail_path(e, fptr->pathv);
7424  fptr->fd = fileno(fptr->stdio_file);
7425  rb_fd_fix_cloexec(fptr->fd);
7426 #ifdef USE_SETVBUF
7427  if (setvbuf(fptr->stdio_file, NULL, _IOFBF, 0) != 0)
7428  rb_warn("setvbuf() can't be honoured for %"PRIsVALUE, fptr->pathv);
7429 #endif
7430  if (fptr->stdio_file == stderr) {
7431  if (setvbuf(fptr->stdio_file, NULL, _IONBF, BUFSIZ) != 0)
7432  rb_warn("setvbuf() can't be honoured for %"PRIsVALUE, fptr->pathv);
7433  }
7434  else if (fptr->stdio_file == stdout && isatty(fptr->fd)) {
7435  if (setvbuf(fptr->stdio_file, NULL, _IOLBF, BUFSIZ) != 0)
7436  rb_warn("setvbuf() can't be honoured for %"PRIsVALUE, fptr->pathv);
7437  }
7438  }
7439  else {
7440  int tmpfd = rb_sysopen(fptr->pathv, oflags, 0666);
7441  int err = 0;
7442  if (rb_cloexec_dup2(tmpfd, fptr->fd) < 0)
7443  err = errno;
7444  (void)close(tmpfd);
7445  if (err) {
7446  rb_syserr_fail_path(err, fptr->pathv);
7447  }
7448  }
7449 
7450  return file;
7451 }
7452 
7453 /* :nodoc: */
7454 static VALUE
7455 rb_io_init_copy(VALUE dest, VALUE io)
7456 {
7457  rb_io_t *fptr, *orig;
7458  int fd;
7459  VALUE write_io;
7460  off_t pos;
7461 
7462  io = rb_io_get_io(io);
7463  if (!OBJ_INIT_COPY(dest, io)) return dest;
7464  GetOpenFile(io, orig);
7465  MakeOpenFile(dest, fptr);
7466 
7467  rb_io_flush(io);
7468 
7469  /* copy rb_io_t structure */
7470  fptr->mode = orig->mode & ~FMODE_PREP;
7471  fptr->encs = orig->encs;
7472  fptr->pid = orig->pid;
7473  fptr->lineno = orig->lineno;
7474  if (!NIL_P(orig->pathv)) fptr->pathv = orig->pathv;
7475  fptr_copy_finalizer(fptr, orig);
7476 
7477  fd = ruby_dup(orig->fd);
7478  fptr->fd = fd;
7479  pos = io_tell(orig);
7480  if (0 <= pos)
7481  io_seek(fptr, pos, SEEK_SET);
7482  if (fptr->mode & FMODE_BINMODE) {
7483  rb_io_binmode(dest);
7484  }
7485 
7486  write_io = GetWriteIO(io);
7487  if (io != write_io) {
7488  write_io = rb_obj_dup(write_io);
7489  fptr->tied_io_for_writing = write_io;
7490  rb_ivar_set(dest, rb_intern("@tied_io_for_writing"), write_io);
7491  }
7492 
7493  return dest;
7494 }
7495 
7496 /*
7497  * call-seq:
7498  * ios.printf(format_string [, obj, ...]) -> nil
7499  *
7500  * Formats and writes to <em>ios</em>, converting parameters under
7501  * control of the format string. See Kernel#sprintf for details.
7502  */
7503 
7504 VALUE
7505 rb_io_printf(int argc, const VALUE *argv, VALUE out)
7506 {
7508  return Qnil;
7509 }
7510 
7511 /*
7512  * call-seq:
7513  * printf(io, string [, obj ... ]) -> nil
7514  * printf(string [, obj ... ]) -> nil
7515  *
7516  * Equivalent to:
7517  * io.write(sprintf(string, obj, ...))
7518  * or
7519  * $stdout.write(sprintf(string, obj, ...))
7520  */
7521 
7522 static VALUE
7523 rb_f_printf(int argc, VALUE *argv, VALUE _)
7524 {
7525  VALUE out;
7526 
7527  if (argc == 0) return Qnil;
7528  if (RB_TYPE_P(argv[0], T_STRING)) {
7529  out = rb_stdout;
7530  }
7531  else {
7532  out = argv[0];
7533  argv++;
7534  argc--;
7535  }
7537 
7538  return Qnil;
7539 }
7540 
7541 static void
7542 rb_output_fs_setter(VALUE val, ID id, VALUE *var)
7543 {
7544  rb_str_setter(val, id, &val);
7545  if (!NIL_P(val)) {
7546  rb_warn_deprecated("`$,'", NULL);
7547  }
7548  *var = val;
7549 }
7550 
7551 /*
7552  * call-seq:
7553  * ios.print -> nil
7554  * ios.print(obj, ...) -> nil
7555  *
7556  * Writes the given object(s) to <em>ios</em>. Returns +nil+.
7557  *
7558  * The stream must be opened for writing.
7559  * Each given object that isn't a string will be converted by calling
7560  * its <code>to_s</code> method.
7561  * When called without arguments, prints the contents of <code>$_</code>.
7562  *
7563  * If the output field separator (<code>$,</code>) is not +nil+,
7564  * it is inserted between objects.
7565  * If the output record separator (<code>$\</code>) is not +nil+,
7566  * it is appended to the output.
7567  *
7568  * $stdout.print("This is ", 100, " percent.\n")
7569  *
7570  * <em>produces:</em>
7571  *
7572  * This is 100 percent.
7573  */
7574 
7575 VALUE
7576 rb_io_print(int argc, const VALUE *argv, VALUE out)
7577 {
7578  int i;
7579  VALUE line;
7580 
7581  /* if no argument given, print `$_' */
7582  if (argc == 0) {
7583  argc = 1;
7584  line = rb_lastline_get();
7585  argv = &line;
7586  }
7587  for (i=0; i<argc; i++) {
7588  if (!NIL_P(rb_output_fs) && i>0) {
7589  rb_io_write(out, rb_output_fs);
7590  }
7591  rb_io_write(out, argv[i]);
7592  }
7593  if (argc > 0 && !NIL_P(rb_output_rs)) {
7594  rb_io_write(out, rb_output_rs);
7595  }
7596 
7597  return Qnil;
7598 }
7599 
7600 /*
7601  * call-seq:
7602  * print(obj, ...) -> nil
7603  *
7604  * Prints each object in turn to <code>$stdout</code>. If the output
7605  * field separator (<code>$,</code>) is not +nil+, its
7606  * contents will appear between each field. If the output record
7607  * separator (<code>$\</code>) is not +nil+, it will be
7608  * appended to the output. If no arguments are given, prints
7609  * <code>$_</code>. Objects that aren't strings will be converted by
7610  * calling their <code>to_s</code> method.
7611  *
7612  * print "cat", [1,2,3], 99, "\n"
7613  * $, = ", "
7614  * $\ = "\n"
7615  * print "cat", [1,2,3], 99
7616  *
7617  * <em>produces:</em>
7618  *
7619  * cat12399
7620  * cat, 1, 2, 3, 99
7621  */
7622 
7623 static VALUE
7624 rb_f_print(int argc, const VALUE *argv, VALUE _)
7625 {
7627  return Qnil;
7628 }
7629 
7630 /*
7631  * call-seq:
7632  * ios.putc(obj) -> obj
7633  *
7634  * If <i>obj</i> is Numeric, write the character whose code is the
7635  * least-significant byte of <i>obj</i>. If <i>obj</i> is String,
7636  * write the first character of <i>obj</i> to <em>ios</em>. Otherwise,
7637  * raise TypeError.
7638  *
7639  * $stdout.putc "A"
7640  * $stdout.putc 65
7641  *
7642  * <em>produces:</em>
7643  *
7644  * AA
7645  */
7646 
7647 static VALUE
7648 rb_io_putc(VALUE io, VALUE ch)
7649 {
7650  VALUE str;
7651  if (RB_TYPE_P(ch, T_STRING)) {
7652  str = rb_str_substr(ch, 0, 1);
7653  }
7654  else {
7655  char c = NUM2CHR(ch);
7656  str = rb_str_new(&c, 1);
7657  }
7658  rb_io_write(io, str);
7659  return ch;
7660 }
7661 
7662 /*
7663  * call-seq:
7664  * putc(int) -> int
7665  *
7666  * Equivalent to:
7667  *
7668  * $stdout.putc(int)
7669  *
7670  * Refer to the documentation for IO#putc for important information regarding
7671  * multi-byte characters.
7672  */
7673 
7674 static VALUE
7675 rb_f_putc(VALUE recv, VALUE ch)
7676 {
7677  if (recv == rb_stdout) {
7678  return rb_io_putc(recv, ch);
7679  }
7680  return rb_funcallv(rb_stdout, rb_intern("putc"), 1, &ch);
7681 }
7682 
7683 
7684 int
7686 {
7687  long len = RSTRING_LEN(str);
7688  const char *ptr = RSTRING_PTR(str);
7690  int n;
7691 
7692  if (len == 0) return 0;
7693  if ((n = rb_enc_mbminlen(enc)) == 1) {
7694  return ptr[len - 1] == c;
7695  }
7696  return rb_enc_ascget(ptr + ((len - 1) / n) * n, ptr + len, &n, enc) == c;
7697 }
7698 
7699 static VALUE
7700 io_puts_ary(VALUE ary, VALUE out, int recur)
7701 {
7702  VALUE tmp;
7703  long i;
7704 
7705  if (recur) {
7706  tmp = rb_str_new2("[...]");
7707  rb_io_puts(1, &tmp, out);
7708  return Qtrue;
7709  }
7710  ary = rb_check_array_type(ary);
7711  if (NIL_P(ary)) return Qfalse;
7712  for (i=0; i<RARRAY_LEN(ary); i++) {
7713  tmp = RARRAY_AREF(ary, i);
7714  rb_io_puts(1, &tmp, out);
7715  }
7716  return Qtrue;
7717 }
7718 
7719 /*
7720  * call-seq:
7721  * ios.puts(obj, ...) -> nil
7722  *
7723  * Writes the given object(s) to <em>ios</em>.
7724  * Writes a newline after any that do not already end
7725  * with a newline sequence. Returns +nil+.
7726  *
7727  * The stream must be opened for writing.
7728  * If called with an array argument, writes each element on a new line.
7729  * Each given object that isn't a string or array will be converted
7730  * by calling its +to_s+ method.
7731  * If called without arguments, outputs a single newline.
7732  *
7733  * $stdout.puts("this", "is", ["a", "test"])
7734  *
7735  * <em>produces:</em>
7736  *
7737  * this
7738  * is
7739  * a
7740  * test
7741  *
7742  * Note that +puts+ always uses newlines and is not affected
7743  * by the output record separator (<code>$\</code>).
7744  */
7745 
7746 VALUE
7747 rb_io_puts(int argc, const VALUE *argv, VALUE out)
7748 {
7749  int i, n;
7750  VALUE line, args[2];
7751 
7752  /* if no argument given, print newline. */
7753  if (argc == 0) {
7754  rb_io_write(out, rb_default_rs);
7755  return Qnil;
7756  }
7757  for (i=0; i<argc; i++) {
7758  if (RB_TYPE_P(argv[i], T_STRING)) {
7759  line = argv[i];
7760  goto string;
7761  }
7762  if (rb_exec_recursive(io_puts_ary, argv[i], out)) {
7763  continue;
7764  }
7765  line = rb_obj_as_string(argv[i]);
7766  string:
7767  n = 0;
7768  args[n++] = line;
7769  if (RSTRING_LEN(line) == 0 ||
7770  !rb_str_end_with_asciichar(line, '\n')) {
7771  args[n++] = rb_default_rs;
7772  }
7773  rb_io_writev(out, n, args);
7774  }
7775 
7776  return Qnil;
7777 }
7778 
7779 /*
7780  * call-seq:
7781  * puts(obj, ...) -> nil
7782  *
7783  * Equivalent to
7784  *
7785  * $stdout.puts(obj, ...)
7786  */
7787 
7788 static VALUE
7789 rb_f_puts(int argc, VALUE *argv, VALUE recv)
7790 {
7791  if (recv == rb_stdout) {
7792  return rb_io_puts(argc, argv, recv);
7793  }
7794  return rb_funcallv(rb_stdout, rb_intern("puts"), argc, argv);
7795 }
7796 
7797 void
7798 rb_p(VALUE obj) /* for debug print within C code */
7799 {
7800  VALUE args[2];
7801  args[0] = rb_obj_as_string(rb_inspect(obj));
7802  args[1] = rb_default_rs;
7803  if (RB_TYPE_P(rb_stdout, T_FILE) &&
7805  io_writev(2, args, rb_stdout);
7806  }
7807  else {
7808  rb_io_writev(rb_stdout, 2, args);
7809  }
7810 }
7811 
7812 struct rb_f_p_arg {
7813  int argc;
7815 };
7816 
7817 static VALUE
7818 rb_f_p_internal(VALUE arg)
7819 {
7820  struct rb_f_p_arg *arg1 = (struct rb_f_p_arg*)arg;
7821  int argc = arg1->argc;
7822  VALUE *argv = arg1->argv;
7823  int i;
7824  VALUE ret = Qnil;
7825 
7826  for (i=0; i<argc; i++) {
7827  rb_p(argv[i]);
7828  }
7829  if (argc == 1) {
7830  ret = argv[0];
7831  }
7832  else if (argc > 1) {
7833  ret = rb_ary_new4(argc, argv);
7834  }
7835  if (RB_TYPE_P(rb_stdout, T_FILE)) {
7837  }
7838  return ret;
7839 }
7840 
7841 /*
7842  * call-seq:
7843  * p(obj) -> obj
7844  * p(obj1, obj2, ...) -> [obj, ...]
7845  * p() -> nil
7846  *
7847  * For each object, directly writes _obj_.+inspect+ followed by a
7848  * newline to the program's standard output.
7849  *
7850  * S = Struct.new(:name, :state)
7851  * s = S['dave', 'TX']
7852  * p s
7853  *
7854  * <em>produces:</em>
7855  *
7856  * #<S name="dave", state="TX">
7857  */
7858 
7859 static VALUE
7860 rb_f_p(int argc, VALUE *argv, VALUE self)
7861 {
7862  struct rb_f_p_arg arg;
7863  arg.argc = argc;
7864  arg.argv = argv;
7865 
7866  return rb_uninterruptible(rb_f_p_internal, (VALUE)&arg);
7867 }
7868 
7869 /*
7870  * call-seq:
7871  * obj.display(port=$>) -> nil
7872  *
7873  * Prints <i>obj</i> on the given port (default <code>$></code>).
7874  * Equivalent to:
7875  *
7876  * def display(port=$>)
7877  * port.write self
7878  * nil
7879  * end
7880  *
7881  * For example:
7882  *
7883  * 1.display
7884  * "cat".display
7885  * [ 4, 5, 6 ].display
7886  * puts
7887  *
7888  * <em>produces:</em>
7889  *
7890  * 1cat[4, 5, 6]
7891  */
7892 
7893 static VALUE
7894 rb_obj_display(int argc, VALUE *argv, VALUE self)
7895 {
7896  VALUE out;
7897 
7898  out = (!rb_check_arity(argc, 0, 1) ? rb_stdout : argv[0]);
7899  rb_io_write(out, self);
7900 
7901  return Qnil;
7902 }
7903 
7904 static int
7905 rb_stderr_to_original_p(void)
7906 {
7907  return (rb_stderr == orig_stderr || RFILE(orig_stderr)->fptr->fd < 0);
7908 }
7909 
7910 void
7911 rb_write_error2(const char *mesg, long len)
7912 {
7913  if (rb_stderr_to_original_p()) {
7914 #ifdef _WIN32
7915  if (isatty(fileno(stderr))) {
7916  if (rb_w32_write_console(rb_str_new(mesg, len), fileno(stderr)) > 0) return;
7917  }
7918 #endif
7919  if (fwrite(mesg, sizeof(char), (size_t)len, stderr) < (size_t)len) {
7920  /* failed to write to stderr, what can we do? */
7921  return;
7922  }
7923  }
7924  else {
7926  }
7927 }
7928 
7929 void
7930 rb_write_error(const char *mesg)
7931 {
7932  rb_write_error2(mesg, strlen(mesg));
7933 }
7934 
7935 void
7937 {
7938  /* a stopgap measure for the time being */
7939  if (rb_stderr_to_original_p()) {
7940  size_t len = (size_t)RSTRING_LEN(mesg);
7941 #ifdef _WIN32
7942  if (isatty(fileno(stderr))) {
7943  if (rb_w32_write_console(mesg, fileno(stderr)) > 0) return;
7944  }
7945 #endif
7946  if (fwrite(RSTRING_PTR(mesg), sizeof(char), len, stderr) < len) {
7947  RB_GC_GUARD(mesg);
7948  return;
7949  }
7950  }
7951  else {
7952  /* may unlock GVL, and */
7953  rb_io_write(rb_stderr, mesg);
7954  }
7955 }
7956 
7957 int
7959 {
7960  if (rb_stderr_to_original_p())
7961  return isatty(fileno(stderr));
7962  return 0;
7963 }
7964 
7965 static void
7966 must_respond_to(ID mid, VALUE val, ID id)
7967 {
7968  if (!rb_respond_to(val, mid)) {
7969  rb_raise(rb_eTypeError, "%"PRIsVALUE" must have %"PRIsVALUE" method, %"PRIsVALUE" given",
7970  rb_id2str(id), rb_id2str(mid),
7971  rb_obj_class(val));
7972  }
7973 }
7974 
7975 static void
7976 stdout_setter(VALUE val, ID id, VALUE *variable)
7977 {
7978  must_respond_to(id_write, val, id);
7979  *variable = val;
7980 }
7981 
7982 static VALUE
7983 prep_io(int fd, int fmode, VALUE klass, const char *path)
7984 {
7985  rb_io_t *fp;
7986  VALUE io = io_alloc(klass);
7987 
7988  MakeOpenFile(io, fp);
7989  fp->fd = fd;
7990  fp->mode = fmode;
7991  if (!io_check_tty(fp)) {
7992 #ifdef __CYGWIN__
7993  fp->mode |= FMODE_BINMODE;
7994  setmode(fd, O_BINARY);
7995 #endif
7996  }
7998  rb_update_max_fd(fd);
7999 
8000  return io;
8001 }
8002 
8003 VALUE
8004 rb_io_fdopen(int fd, int oflags, const char *path)
8005 {
8006  VALUE klass = rb_cIO;
8007 
8008  if (path && strcmp(path, "-")) klass = rb_cFile;
8009  return prep_io(fd, rb_io_oflags_fmode(oflags), klass, path);
8010 }
8011 
8012 static VALUE
8013 prep_stdio(FILE *f, int fmode, VALUE klass, const char *path)
8014 {
8015  rb_io_t *fptr;
8017 
8018  GetOpenFile(io, fptr);
8020 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
8021  fptr->encs.ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
8022  if (fmode & FMODE_READABLE) {
8024  }
8025 #endif
8026  fptr->stdio_file = f;
8027 
8028  return io;
8029 }
8030 
8031 FILE *
8033 {
8034  if (!fptr->stdio_file) {
8035  int oflags = rb_io_fmode_oflags(fptr->mode) & ~O_EXCL;
8036  fptr->stdio_file = rb_fdopen(fptr->fd, rb_io_oflags_modestr(oflags));
8037  }
8038  return fptr->stdio_file;
8039 }
8040 
8041 static inline void
8042 rb_io_buffer_init(rb_io_buffer_t *buf)
8043 {
8044  buf->ptr = NULL;
8045  buf->off = 0;
8046  buf->len = 0;
8047  buf->capa = 0;
8048 }
8049 
8050 static inline rb_io_t *
8051 rb_io_fptr_new(void)
8052 {
8053  rb_io_t *fp = ALLOC(rb_io_t);
8054  fp->fd = -1;
8055  fp->stdio_file = NULL;
8056  fp->mode = 0;
8057  fp->pid = 0;
8058  fp->lineno = 0;
8059  fp->pathv = Qnil;
8060  fp->finalize = 0;
8061  rb_io_buffer_init(&fp->wbuf);
8062  rb_io_buffer_init(&fp->rbuf);
8063  rb_io_buffer_init(&fp->cbuf);
8064  fp->readconv = NULL;
8065  fp->writeconv = NULL;
8067  fp->writeconv_pre_ecflags = 0;
8068  fp->writeconv_pre_ecopts = Qnil;
8069  fp->writeconv_initialized = 0;
8070  fp->tied_io_for_writing = 0;
8071  fp->encs.enc = NULL;
8072  fp->encs.enc2 = NULL;
8073  fp->encs.ecflags = 0;
8074  fp->encs.ecopts = Qnil;
8075  fp->write_lock = 0;
8076  return fp;
8077 }
8078 
8079 rb_io_t *
8081 {
8082  rb_io_t *fp = 0;
8083 
8084  Check_Type(obj, T_FILE);
8085  if (RFILE(obj)->fptr) {
8086  rb_io_close(obj);
8087  rb_io_fptr_finalize(RFILE(obj)->fptr);
8088  RFILE(obj)->fptr = 0;
8089  }
8090  fp = rb_io_fptr_new();
8091  RFILE(obj)->fptr = fp;
8092  return fp;
8093 }
8094 
8095 /*
8096  * call-seq:
8097  * IO.new(fd [, mode] [, opt]) -> io
8098  *
8099  * Returns a new IO object (a stream) for the given integer file descriptor
8100  * +fd+ and +mode+ string. +opt+ may be used to specify parts of +mode+ in a
8101  * more readable fashion. See also IO.sysopen and IO.for_fd.
8102  *
8103  * IO.new is called by various File and IO opening methods such as IO::open,
8104  * Kernel#open, and File::open.
8105  *
8106  * === Open Mode
8107  *
8108  * When +mode+ is an integer it must be combination of the modes defined in
8109  * File::Constants (+File::RDONLY+, <code>File::WRONLY|File::CREAT</code>).
8110  * See the open(2) man page for more information.
8111  *
8112  * When +mode+ is a string it must be in one of the following forms:
8113  *
8114  * fmode
8115  * fmode ":" ext_enc
8116  * fmode ":" ext_enc ":" int_enc
8117  * fmode ":" "BOM|UTF-*"
8118  *
8119  * +fmode+ is an IO open mode string, +ext_enc+ is the external encoding for
8120  * the IO and +int_enc+ is the internal encoding.
8121  *
8122  * ==== IO Open Mode
8123  *
8124  * Ruby allows the following open modes:
8125  *
8126  * "r" Read-only, starts at beginning of file (default mode).
8127  *
8128  * "r+" Read-write, starts at beginning of file.
8129  *
8130  * "w" Write-only, truncates existing file
8131  * to zero length or creates a new file for writing.
8132  *
8133  * "w+" Read-write, truncates existing file to zero length
8134  * or creates a new file for reading and writing.
8135  *
8136  * "a" Write-only, each write call appends data at end of file.
8137  * Creates a new file for writing if file does not exist.
8138  *
8139  * "a+" Read-write, each write call appends data at end of file.
8140  * Creates a new file for reading and writing if file does
8141  * not exist.
8142  *
8143  * The following modes must be used separately, and along with one or more of
8144  * the modes seen above.
8145  *
8146  * "b" Binary file mode
8147  * Suppresses EOL <-> CRLF conversion on Windows. And
8148  * sets external encoding to ASCII-8BIT unless explicitly
8149  * specified.
8150  *
8151  * "t" Text file mode
8152  *
8153  * The exclusive access mode ("x") can be used together with "w" to ensure
8154  * the file is created. Errno::EEXIST is raised when it already exists.
8155  * It may not be supported with all kinds of streams (e.g. pipes).
8156  *
8157  * When the open mode of original IO is read only, the mode cannot be
8158  * changed to be writable. Similarly, the open mode cannot be changed from
8159  * write only to readable.
8160  *
8161  * When such a change is attempted the error is raised in different locations
8162  * according to the platform.
8163  *
8164  * === IO Encoding
8165  *
8166  * When +ext_enc+ is specified, strings read will be tagged by the encoding
8167  * when reading, and strings output will be converted to the specified
8168  * encoding when writing.
8169  *
8170  * When +ext_enc+ and +int_enc+ are specified read strings will be converted
8171  * from +ext_enc+ to +int_enc+ upon input, and written strings will be
8172  * converted from +int_enc+ to +ext_enc+ upon output. See Encoding for
8173  * further details of transcoding on input and output.
8174  *
8175  * If "BOM|UTF-8", "BOM|UTF-16LE" or "BOM|UTF16-BE" are used, Ruby checks for
8176  * a Unicode BOM in the input document to help determine the encoding. For
8177  * UTF-16 encodings the file open mode must be binary. When present, the BOM
8178  * is stripped and the external encoding from the BOM is used. When the BOM
8179  * is missing the given Unicode encoding is used as +ext_enc+. (The BOM-set
8180  * encoding option is case insensitive, so "bom|utf-8" is also valid.)
8181  *
8182  * === Options
8183  *
8184  * +opt+ can be used instead of +mode+ for improved readability. The
8185  * following keys are supported:
8186  *
8187  * :mode ::
8188  * Same as +mode+ parameter
8189  *
8190  * :flags ::
8191  * Specifies file open flags as integer.
8192  * If +mode+ parameter is given, this parameter will be bitwise-ORed.
8193  *
8194  * :\external_encoding ::
8195  * External encoding for the IO.
8196  *
8197  * :\internal_encoding ::
8198  * Internal encoding for the IO. "-" is a synonym for the default internal
8199  * encoding.
8200  *
8201  * If the value is +nil+ no conversion occurs.
8202  *
8203  * :encoding ::
8204  * Specifies external and internal encodings as "extern:intern".
8205  *
8206  * :textmode ::
8207  * If the value is truth value, same as "t" in argument +mode+.
8208  *
8209  * :binmode ::
8210  * If the value is truth value, same as "b" in argument +mode+.
8211  *
8212  * :autoclose ::
8213  * If the value is +false+, the +fd+ will be kept open after this IO
8214  * instance gets finalized.
8215  *
8216  * Also, +opt+ can have same keys in String#encode for controlling conversion
8217  * between the external encoding and the internal encoding.
8218  *
8219  * === Example 1
8220  *
8221  * fd = IO.sysopen("/dev/tty", "w")
8222  * a = IO.new(fd,"w")
8223  * $stderr.puts "Hello"
8224  * a.puts "World"
8225  *
8226  * Produces:
8227  *
8228  * Hello
8229  * World
8230  *
8231  * === Example 2
8232  *
8233  * require 'fcntl'
8234  *
8235  * fd = STDERR.fcntl(Fcntl::F_DUPFD)
8236  * io = IO.new(fd, mode: 'w:UTF-16LE', cr_newline: true)
8237  * io.puts "Hello, World!"
8238  *
8239  * fd = STDERR.fcntl(Fcntl::F_DUPFD)
8240  * io = IO.new(fd, mode: 'w', cr_newline: true,
8241  * external_encoding: Encoding::UTF_16LE)
8242  * io.puts "Hello, World!"
8243  *
8244  * Both of above print "Hello, World!" in UTF-16LE to standard error output
8245  * with converting EOL generated by #puts to CR.
8246  */
8247 
8248 static VALUE
8249 rb_io_initialize(int argc, VALUE *argv, VALUE io)
8250 {
8251  VALUE fnum, vmode;
8252  rb_io_t *fp;
8253  int fd, fmode, oflags = O_RDONLY;
8254  convconfig_t convconfig;
8255  VALUE opt;
8256 #if defined(HAVE_FCNTL) && defined(F_GETFL)
8257  int ofmode;
8258 #else
8259  struct stat st;
8260 #endif
8261 
8262 
8263  argc = rb_scan_args(argc, argv, "11:", &fnum, &vmode, &opt);
8264  rb_io_extract_modeenc(&vmode, 0, opt, &oflags, &fmode, &convconfig);
8265 
8266  fd = NUM2INT(fnum);
8267  if (rb_reserved_fd_p(fd)) {
8268  rb_raise(rb_eArgError, "The given fd is not accessible because RubyVM reserves it");
8269  }
8270 #if defined(HAVE_FCNTL) && defined(F_GETFL)
8271  oflags = fcntl(fd, F_GETFL);
8272  if (oflags == -1) rb_sys_fail(0);
8273 #else
8274  if (fstat(fd, &st) < 0) rb_sys_fail(0);
8275 #endif
8276  rb_update_max_fd(fd);
8277 #if defined(HAVE_FCNTL) && defined(F_GETFL)
8278  ofmode = rb_io_oflags_fmode(oflags);
8279  if (NIL_P(vmode)) {
8280  fmode = ofmode;
8281  }
8282  else if ((~ofmode & fmode) & FMODE_READWRITE) {
8285  }
8286 #endif
8287  if (!NIL_P(opt) && rb_hash_aref(opt, sym_autoclose) == Qfalse) {
8288  fmode |= FMODE_PREP;
8289  }
8290  MakeOpenFile(io, fp);
8291  fp->fd = fd;
8292  fp->mode = fmode;
8293  fp->encs = convconfig;
8294  clear_codeconv(fp);
8295  io_check_tty(fp);
8296  if (fileno(stdin) == fd)
8297  fp->stdio_file = stdin;
8298  else if (fileno(stdout) == fd)
8299  fp->stdio_file = stdout;
8300  else if (fileno(stderr) == fd)
8301  fp->stdio_file = stderr;
8302 
8303  if (fmode & FMODE_SETENC_BY_BOM) io_set_encoding_by_bom(io);
8304  return io;
8305 }
8306 
8307 /*
8308  * call-seq:
8309  * ios.set_encoding_by_bom -> encoding or nil
8310  *
8311  * Checks if +ios+ starts with a BOM, and then consumes it and sets
8312  * the external encoding. Returns the result encoding if found, or
8313  * nil. If +ios+ is not binmode or its encoding has been set
8314  * already, an exception will be raised.
8315  *
8316  * File.write("bom.txt", "\u{FEFF}abc")
8317  * ios = File.open("bom.txt", "rb")
8318  * ios.set_encoding_by_bom #=> #<Encoding:UTF-8>
8319  *
8320  * File.write("nobom.txt", "abc")
8321  * ios = File.open("nobom.txt", "rb")
8322  * ios.set_encoding_by_bom #=> nil
8323  */
8324 
8325 static VALUE
8326 rb_io_set_encoding_by_bom(VALUE io)
8327 {
8328  rb_io_t *fptr;
8329 
8330  GetOpenFile(io, fptr);
8331  if (!(fptr->mode & FMODE_BINMODE)) {
8332  rb_raise(rb_eArgError, "ASCII incompatible encoding needs binmode");
8333  }
8334  if (fptr->encs.enc2) {
8335  rb_raise(rb_eArgError, "encoding conversion is set");
8336  }
8337  else if (fptr->encs.enc && fptr->encs.enc != rb_ascii8bit_encoding()) {
8338  rb_raise(rb_eArgError, "encoding is set to %s already",
8339  rb_enc_name(fptr->encs.enc));
8340  }
8341  if (!io_set_encoding_by_bom(io)) return Qnil;
8342  return rb_enc_from_encoding(fptr->encs.enc);
8343 }
8344 
8345 /*
8346  * call-seq:
8347  * File.new(filename, mode="r" [, opt]) -> file
8348  * File.new(filename [, mode [, perm]] [, opt]) -> file
8349  *
8350  * Opens the file named by +filename+ according to the given +mode+ and
8351  * returns a new File object.
8352  *
8353  * See IO.new for a description of +mode+ and +opt+.
8354  *
8355  * If a file is being created, permission bits may be given in +perm+. These
8356  * mode and permission bits are platform dependent; on Unix systems, see
8357  * open(2) and chmod(2) man pages for details.
8358  *
8359  * The new File object is buffered mode (or non-sync mode), unless
8360  * +filename+ is a tty.
8361  * See IO#flush, IO#fsync, IO#fdatasync, and IO#sync= about sync mode.
8362  *
8363  * === Examples
8364  *
8365  * f = File.new("testfile", "r")
8366  * f = File.new("newfile", "w+")
8367  * f = File.new("newfile", File::CREAT|File::TRUNC|File::RDWR, 0644)
8368  */
8369 
8370 static VALUE
8371 rb_file_initialize(int argc, VALUE *argv, VALUE io)
8372 {
8373  if (RFILE(io)->fptr) {
8374  rb_raise(rb_eRuntimeError, "reinitializing File");
8375  }
8376  if (0 < argc && argc < 3) {
8377  VALUE fd = rb_check_to_int(argv[0]);
8378 
8379  if (!NIL_P(fd)) {
8380  argv[0] = fd;
8381  return rb_io_initialize(argc, argv, io);
8382  }
8383  }
8384  rb_open_file(argc, argv, io);
8385 
8386  return io;
8387 }
8388 
8389 /* :nodoc: */
8390 static VALUE
8391 rb_io_s_new(int argc, VALUE *argv, VALUE klass)
8392 {
8393  if (rb_block_given_p()) {
8394  VALUE cname = rb_obj_as_string(klass);
8395 
8396  rb_warn("%"PRIsVALUE"::new() does not take block; use %"PRIsVALUE"::open() instead",
8397  cname, cname);
8398  }
8400 }
8401 
8402 
8403 /*
8404  * call-seq:
8405  * IO.for_fd(fd, mode [, opt]) -> io
8406  *
8407  * Synonym for IO.new.
8408  *
8409  */
8410 
8411 static VALUE
8412 rb_io_s_for_fd(int argc, VALUE *argv, VALUE klass)
8413 {
8414  VALUE io = rb_obj_alloc(klass);
8415  rb_io_initialize(argc, argv, io);
8416  return io;
8417 }
8418 
8419 /*
8420  * call-seq:
8421  * ios.autoclose? -> true or false
8422  *
8423  * Returns +true+ if the underlying file descriptor of _ios_ will be
8424  * closed automatically at its finalization, otherwise +false+.
8425  */
8426 
8427 static VALUE
8428 rb_io_autoclose_p(VALUE io)
8429 {
8430  rb_io_t *fptr = RFILE(io)->fptr;
8431  rb_io_check_closed(fptr);
8432  return (fptr->mode & FMODE_PREP) ? Qfalse : Qtrue;
8433 }
8434 
8435 /*
8436  * call-seq:
8437  * io.autoclose = bool -> true or false
8438  *
8439  * Sets auto-close flag.
8440  *
8441  * f = open("/dev/null")
8442  * IO.for_fd(f.fileno)
8443  * # ...
8444  * f.gets # may cause Errno::EBADF
8445  *
8446  * f = open("/dev/null")
8447  * IO.for_fd(f.fileno).autoclose = false
8448  * # ...
8449  * f.gets # won't cause Errno::EBADF
8450  */
8451 
8452 static VALUE
8453 rb_io_set_autoclose(VALUE io, VALUE autoclose)
8454 {
8455  rb_io_t *fptr;
8456  GetOpenFile(io, fptr);
8457  if (!RTEST(autoclose))
8458  fptr->mode |= FMODE_PREP;
8459  else
8460  fptr->mode &= ~FMODE_PREP;
8461  return autoclose;
8462 }
8463 
8464 static void
8465 argf_mark(void *ptr)
8466 {
8467  struct argf *p = ptr;
8468  rb_gc_mark(p->filename);
8470  rb_gc_mark(p->argv);
8471  rb_gc_mark(p->inplace);
8472  rb_gc_mark(p->encs.ecopts);
8473 }
8474 
8475 static size_t
8476 argf_memsize(const void *ptr)
8477 {
8478  const struct argf *p = ptr;
8479  size_t size = sizeof(*p);
8480  return size;
8481 }
8482 
8483 static const rb_data_type_t argf_type = {
8484  "ARGF",
8485  {argf_mark, RUBY_TYPED_DEFAULT_FREE, argf_memsize},
8487 };
8488 
8489 static inline void
8490 argf_init(struct argf *p, VALUE v)
8491 {
8492  p->filename = Qnil;
8493  p->current_file = Qnil;
8494  p->lineno = 0;
8495  p->argv = v;
8496 }
8497 
8498 static VALUE
8499 argf_alloc(VALUE klass)
8500 {
8501  struct argf *p;
8502  VALUE argf = TypedData_Make_Struct(klass, struct argf, &argf_type, p);
8503 
8504  argf_init(p, Qnil);
8505  return argf;
8506 }
8507 
8508 #undef rb_argv
8509 
8510 /* :nodoc: */
8511 static VALUE
8512 argf_initialize(VALUE argf, VALUE argv)
8513 {
8514  memset(&ARGF, 0, sizeof(ARGF));
8515  argf_init(&ARGF, argv);
8516 
8517  return argf;
8518 }
8519 
8520 /* :nodoc: */
8521 static VALUE
8522 argf_initialize_copy(VALUE argf, VALUE orig)
8523 {
8524  if (!OBJ_INIT_COPY(argf, orig)) return argf;
8525  ARGF = argf_of(orig);
8526  ARGF.argv = rb_obj_dup(ARGF.argv);
8527  return argf;
8528 }
8529 
8530 /*
8531  * call-seq:
8532  * ARGF.lineno = integer -> integer
8533  *
8534  * Sets the line number of +ARGF+ as a whole to the given +Integer+.
8535  *
8536  * +ARGF+ sets the line number automatically as you read data, so normally
8537  * you will not need to set it explicitly. To access the current line number
8538  * use +ARGF.lineno+.
8539  *
8540  * For example:
8541  *
8542  * ARGF.lineno #=> 0
8543  * ARGF.readline #=> "This is line 1\n"
8544  * ARGF.lineno #=> 1
8545  * ARGF.lineno = 0 #=> 0
8546  * ARGF.lineno #=> 0
8547  */
8548 static VALUE
8549 argf_set_lineno(VALUE argf, VALUE val)
8550 {
8551  ARGF.lineno = NUM2INT(val);
8552  ARGF.last_lineno = ARGF.lineno;
8553  return Qnil;
8554 }
8555 
8556 /*
8557  * call-seq:
8558  * ARGF.lineno -> integer
8559  *
8560  * Returns the current line number of ARGF as a whole. This value
8561  * can be set manually with +ARGF.lineno=+.
8562  *
8563  * For example:
8564  *
8565  * ARGF.lineno #=> 0
8566  * ARGF.readline #=> "This is line 1\n"
8567  * ARGF.lineno #=> 1
8568  */
8569 static VALUE
8570 argf_lineno(VALUE argf)
8571 {
8572  return INT2FIX(ARGF.lineno);
8573 }
8574 
8575 static VALUE
8576 argf_forward(int argc, VALUE *argv, VALUE argf)
8577 {
8578  return rb_funcall3(ARGF.current_file, rb_frame_this_func(), argc, argv);
8579 }
8580 
8581 #define next_argv() argf_next_argv(argf)
8582 #define ARGF_GENERIC_INPUT_P() \
8583  (ARGF.current_file == rb_stdin && !RB_TYPE_P(ARGF.current_file, T_FILE))
8584 #define ARGF_FORWARD(argc, argv) do {\
8585  if (ARGF_GENERIC_INPUT_P())\
8586  return argf_forward((argc), (argv), argf);\
8587 } while (0)
8588 #define NEXT_ARGF_FORWARD(argc, argv) do {\
8589  if (!next_argv()) return Qnil;\
8590  ARGF_FORWARD((argc), (argv));\
8591 } while (0)
8592 
8593 static void
8594 argf_close(VALUE argf)
8595 {
8596  VALUE file = ARGF.current_file;
8597  if (file == rb_stdin) return;
8598  if (RB_TYPE_P(file, T_FILE)) {
8599  rb_io_set_write_io(file, Qnil);
8600  }
8601  io_close(file);
8602  ARGF.init_p = -1;
8603 }
8604 
8605 static int
8606 argf_next_argv(VALUE argf)
8607 {
8608  char *fn;
8609  rb_io_t *fptr;
8610  int stdout_binmode = 0;
8611  int fmode;
8612 
8613  if (RB_TYPE_P(rb_stdout, T_FILE)) {
8614  GetOpenFile(rb_stdout, fptr);
8615  if (fptr->mode & FMODE_BINMODE)
8616  stdout_binmode = 1;
8617  }
8618 
8619  if (ARGF.init_p == 0) {
8620  if (!NIL_P(ARGF.argv) && RARRAY_LEN(ARGF.argv) > 0) {
8621  ARGF.next_p = 1;
8622  }
8623  else {
8624  ARGF.next_p = -1;
8625  }
8626  ARGF.init_p = 1;
8627  }
8628  else {
8629  if (NIL_P(ARGF.argv)) {
8630  ARGF.next_p = -1;
8631  }
8632  else if (ARGF.next_p == -1 && RARRAY_LEN(ARGF.argv) > 0) {
8633  ARGF.next_p = 1;
8634  }
8635  }
8636 
8637  if (ARGF.next_p == 1) {
8638  if (ARGF.init_p == 1) argf_close(argf);
8639  retry:
8640  if (RARRAY_LEN(ARGF.argv) > 0) {
8641  VALUE filename = rb_ary_shift(ARGF.argv);
8643  ARGF.filename = filename;
8645  fn = StringValueCStr(filename);
8646  if (RSTRING_LEN(filename) == 1 && fn[0] == '-') {
8647  ARGF.current_file = rb_stdin;
8648  if (ARGF.inplace) {
8649  rb_warn("Can't do inplace edit for stdio; skipping");
8650  goto retry;
8651  }
8652  }
8653  else {
8654  VALUE write_io = Qnil;
8655  int fr = rb_sysopen(filename, O_RDONLY, 0);
8656 
8657  if (ARGF.inplace) {
8658  struct stat st;
8659 #ifndef NO_SAFE_RENAME
8660  struct stat st2;
8661 #endif
8662  VALUE str;
8663  int fw;
8664 
8665  if (RB_TYPE_P(rb_stdout, T_FILE) && rb_stdout != orig_stdout) {
8667  }
8668  fstat(fr, &st);
8669  str = filename;
8670  if (!NIL_P(ARGF.inplace)) {
8671  VALUE suffix = ARGF.inplace;
8672  str = rb_str_dup(str);
8674  RSTRING_PTR(suffix), RSTRING_LEN(suffix),
8675  rb_enc_get(suffix), 0, Qnil))) {
8676  rb_str_append(str, suffix);
8677  }
8678 #ifdef NO_SAFE_RENAME
8679  (void)close(fr);
8681  if (rename(fn, RSTRING_PTR(str)) < 0) {
8682  rb_warn("Can't rename %"PRIsVALUE" to %"PRIsVALUE": %s, skipping file",
8683  filename, str, strerror(errno));
8684  goto retry;
8685  }
8686  fr = rb_sysopen(str, O_RDONLY, 0);
8687 #else
8688  if (rename(fn, RSTRING_PTR(str)) < 0) {
8689  rb_warn("Can't rename %"PRIsVALUE" to %"PRIsVALUE": %s, skipping file",
8690  filename, str, strerror(errno));
8691  close(fr);
8692  goto retry;
8693  }
8694 #endif
8695  }
8696  else {
8697 #ifdef NO_SAFE_RENAME
8698  rb_fatal("Can't do inplace edit without backup");
8699 #else
8700  if (unlink(fn) < 0) {
8701  rb_warn("Can't remove %"PRIsVALUE": %s, skipping file",
8702  filename, strerror(errno));
8703  close(fr);
8704  goto retry;
8705  }
8706 #endif
8707  }
8708  fw = rb_sysopen(filename, O_WRONLY|O_CREAT|O_TRUNC, 0666);
8709 #ifndef NO_SAFE_RENAME
8710  fstat(fw, &st2);
8711 #ifdef HAVE_FCHMOD
8712  fchmod(fw, st.st_mode);
8713 #else
8714  chmod(fn, st.st_mode);
8715 #endif
8716  if (st.st_uid!=st2.st_uid || st.st_gid!=st2.st_gid) {
8717  int err;
8718 #ifdef HAVE_FCHOWN
8719  err = fchown(fw, st.st_uid, st.st_gid);
8720 #else
8721  err = chown(fn, st.st_uid, st.st_gid);
8722 #endif
8723  if (err && getuid() == 0 && st2.st_uid == 0) {
8724  const char *wkfn = RSTRING_PTR(filename);
8725  rb_warn("Can't set owner/group of %"PRIsVALUE" to same as %"PRIsVALUE": %s, skipping file",
8726  filename, str, strerror(errno));
8727  (void)close(fr);
8728  (void)close(fw);
8729  (void)unlink(wkfn);
8730  goto retry;
8731  }
8732  }
8733 #endif
8734  write_io = prep_io(fw, FMODE_WRITABLE, rb_cFile, fn);
8735  rb_stdout = write_io;
8736  if (stdout_binmode) rb_io_binmode(rb_stdout);
8737  }
8739  if (!ARGF.binmode) {
8741  }
8742  ARGF.current_file = prep_io(fr, fmode, rb_cFile, fn);
8743  if (!NIL_P(write_io)) {
8744  rb_io_set_write_io(ARGF.current_file, write_io);
8745  }
8746  RB_GC_GUARD(filename);
8747  }
8748  if (ARGF.binmode) rb_io_ascii8bit_binmode(ARGF.current_file);
8749  GetOpenFile(ARGF.current_file, fptr);
8750  if (ARGF.encs.enc) {
8751  fptr->encs = ARGF.encs;
8752  clear_codeconv(fptr);
8753  }
8754  else {
8756  if (!ARGF.binmode) {
8758 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
8759  fptr->encs.ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
8760 #endif
8761  }
8762  }
8763  ARGF.next_p = 0;
8764  }
8765  else {
8766  ARGF.next_p = 1;
8767  return FALSE;
8768  }
8769  }
8770  else if (ARGF.next_p == -1) {
8771  ARGF.current_file = rb_stdin;
8772  ARGF.filename = rb_str_new2("-");
8773  if (ARGF.inplace) {
8774  rb_warn("Can't do inplace edit for stdio");
8775  rb_stdout = orig_stdout;
8776  }
8777  }
8778  if (ARGF.init_p == -1) ARGF.init_p = 1;
8779  return TRUE;
8780 }
8781 
8782 static VALUE
8783 argf_getline(int argc, VALUE *argv, VALUE argf)
8784 {
8785  VALUE line;
8786  long lineno = ARGF.lineno;
8787 
8788  retry:
8789  if (!next_argv()) return Qnil;
8790  if (ARGF_GENERIC_INPUT_P()) {
8791  line = rb_funcall3(ARGF.current_file, idGets, argc, argv);
8792  }
8793  else {
8794  if (argc == 0 && rb_rs == rb_default_rs) {
8795  line = rb_io_gets(ARGF.current_file);
8796  }
8797  else {
8798  line = rb_io_getline(argc, argv, ARGF.current_file);
8799  }
8800  if (NIL_P(line) && ARGF.next_p != -1) {
8801  argf_close(argf);
8802  ARGF.next_p = 1;
8803  goto retry;
8804  }
8805  }
8806  if (!NIL_P(line)) {
8807  ARGF.lineno = ++lineno;
8808  ARGF.last_lineno = ARGF.lineno;
8809  }
8810  return line;
8811 }
8812 
8813 static VALUE
8814 argf_lineno_getter(ID id, VALUE *var)
8815 {
8816  VALUE argf = *var;
8817  return INT2FIX(ARGF.last_lineno);
8818 }
8819 
8820 static void
8821 argf_lineno_setter(VALUE val, ID id, VALUE *var)
8822 {
8823  VALUE argf = *var;
8824  int n = NUM2INT(val);
8825  ARGF.last_lineno = ARGF.lineno = n;
8826 }
8827 
8828 static VALUE argf_gets(int, VALUE *, VALUE);
8829 
8830 /*
8831  * call-seq:
8832  * gets(sep=$/ [, getline_args]) -> string or nil
8833  * gets(limit [, getline_args]) -> string or nil
8834  * gets(sep, limit [, getline_args]) -> string or nil
8835  *
8836  * Returns (and assigns to <code>$_</code>) the next line from the list
8837  * of files in +ARGV+ (or <code>$*</code>), or from standard input if
8838  * no files are present on the command line. Returns +nil+ at end of
8839  * file. The optional argument specifies the record separator. The
8840  * separator is included with the contents of each record. A separator
8841  * of +nil+ reads the entire contents, and a zero-length separator
8842  * reads the input one paragraph at a time, where paragraphs are
8843  * divided by two consecutive newlines. If the first argument is an
8844  * integer, or optional second argument is given, the returning string
8845  * would not be longer than the given value in bytes. If multiple
8846  * filenames are present in +ARGV+, <code>gets(nil)</code> will read
8847  * the contents one file at a time.
8848  *
8849  * ARGV << "testfile"
8850  * print while gets
8851  *
8852  * <em>produces:</em>
8853  *
8854  * This is line one
8855  * This is line two
8856  * This is line three
8857  * And so on...
8858  *
8859  * The style of programming using <code>$_</code> as an implicit
8860  * parameter is gradually losing favor in the Ruby community.
8861  */
8862 
8863 static VALUE
8864 rb_f_gets(int argc, VALUE *argv, VALUE recv)
8865 {
8866  if (recv == argf) {
8867  return argf_gets(argc, argv, argf);
8868  }
8869  return rb_funcallv(argf, idGets, argc, argv);
8870 }
8871 
8872 /*
8873  * call-seq:
8874  * ARGF.gets(sep=$/ [, getline_args]) -> string or nil
8875  * ARGF.gets(limit [, getline_args]) -> string or nil
8876  * ARGF.gets(sep, limit [, getline_args]) -> string or nil
8877  *
8878  * Returns the next line from the current file in +ARGF+.
8879  *
8880  * By default lines are assumed to be separated by <code>$/</code>;
8881  * to use a different character as a separator, supply it as a +String+
8882  * for the _sep_ argument.
8883  *
8884  * The optional _limit_ argument specifies how many characters of each line
8885  * to return. By default all characters are returned.
8886  *
8887  * See IO.readlines for details about getline_args.
8888  *
8889  */
8890 static VALUE
8891 argf_gets(int argc, VALUE *argv, VALUE argf)
8892 {
8893  VALUE line;
8894 
8895  line = argf_getline(argc, argv, argf);
8896  rb_lastline_set(line);
8897 
8898  return line;
8899 }
8900 
8901 VALUE
8902 rb_gets(void)
8903 {
8904  VALUE line;
8905 
8906  if (rb_rs != rb_default_rs) {
8907  return rb_f_gets(0, 0, argf);
8908  }
8909 
8910  retry:
8911  if (!next_argv()) return Qnil;
8912  line = rb_io_gets(ARGF.current_file);
8913  if (NIL_P(line) && ARGF.next_p != -1) {
8914  rb_io_close(ARGF.current_file);
8915  ARGF.next_p = 1;
8916  goto retry;
8917  }
8918  rb_lastline_set(line);
8919  if (!NIL_P(line)) {
8920  ARGF.lineno++;
8921  ARGF.last_lineno = ARGF.lineno;
8922  }
8923 
8924  return line;
8925 }
8926 
8927 static VALUE argf_readline(int, VALUE *, VALUE);
8928 
8929 /*
8930  * call-seq:
8931  * readline(sep=$/) -> string
8932  * readline(limit) -> string
8933  * readline(sep, limit) -> string
8934  *
8935  * Equivalent to Kernel::gets, except
8936  * +readline+ raises +EOFError+ at end of file.
8937  */
8938 
8939 static VALUE
8940 rb_f_readline(int argc, VALUE *argv, VALUE recv)
8941 {
8942  if (recv == argf) {
8943  return argf_readline(argc, argv, argf);
8944  }
8945  return rb_funcallv(argf, rb_intern("readline"), argc, argv);
8946 }
8947 
8948 
8949 /*
8950  * call-seq:
8951  * ARGF.readline(sep=$/) -> string
8952  * ARGF.readline(limit) -> string
8953  * ARGF.readline(sep, limit) -> string
8954  *
8955  * Returns the next line from the current file in +ARGF+.
8956  *
8957  * By default lines are assumed to be separated by <code>$/</code>;
8958  * to use a different character as a separator, supply it as a +String+
8959  * for the _sep_ argument.
8960  *
8961  * The optional _limit_ argument specifies how many characters of each line
8962  * to return. By default all characters are returned.
8963  *
8964  * An +EOFError+ is raised at the end of the file.
8965  */
8966 static VALUE
8967 argf_readline(int argc, VALUE *argv, VALUE argf)
8968 {
8969  VALUE line;
8970 
8971  if (!next_argv()) rb_eof_error();
8973  line = argf_gets(argc, argv, argf);
8974  if (NIL_P(line)) {
8975  rb_eof_error();
8976  }
8977 
8978  return line;
8979 }
8980 
8981 static VALUE argf_readlines(int, VALUE *, VALUE);
8982 
8983 /*
8984  * call-seq:
8985  * readlines(sep=$/) -> array
8986  * readlines(limit) -> array
8987  * readlines(sep, limit) -> array
8988  *
8989  * Returns an array containing the lines returned by calling
8990  * <code>Kernel.gets(<i>sep</i>)</code> until the end of file.
8991  */
8992 
8993 static VALUE
8994 rb_f_readlines(int argc, VALUE *argv, VALUE recv)
8995 {
8996  if (recv == argf) {
8997  return argf_readlines(argc, argv, argf);
8998  }
8999  return rb_funcallv(argf, rb_intern("readlines"), argc, argv);
9000 }
9001 
9002 /*
9003  * call-seq:
9004  * ARGF.readlines(sep=$/) -> array
9005  * ARGF.readlines(limit) -> array
9006  * ARGF.readlines(sep, limit) -> array
9007  *
9008  * ARGF.to_a(sep=$/) -> array
9009  * ARGF.to_a(limit) -> array
9010  * ARGF.to_a(sep, limit) -> array
9011  *
9012  * Reads +ARGF+'s current file in its entirety, returning an +Array+ of its
9013  * lines, one line per element. Lines are assumed to be separated by _sep_.
9014  *
9015  * lines = ARGF.readlines
9016  * lines[0] #=> "This is line one\n"
9017  */
9018 static VALUE
9019 argf_readlines(int argc, VALUE *argv, VALUE argf)
9020 {
9021  long lineno = ARGF.lineno;
9022  VALUE lines, ary;
9023 
9024  ary = rb_ary_new();
9025  while (next_argv()) {
9026  if (ARGF_GENERIC_INPUT_P()) {
9027  lines = rb_funcall3(ARGF.current_file, rb_intern("readlines"), argc, argv);
9028  }
9029  else {
9030  lines = rb_io_readlines(argc, argv, ARGF.current_file);
9031  argf_close(argf);
9032  }
9033  ARGF.next_p = 1;
9034  rb_ary_concat(ary, lines);
9035  ARGF.lineno = lineno + RARRAY_LEN(ary);
9036  ARGF.last_lineno = ARGF.lineno;
9037  }
9038  ARGF.init_p = 0;
9039  return ary;
9040 }
9041 
9042 /*
9043  * call-seq:
9044  * `cmd` -> string
9045  *
9046  * Returns the standard output of running _cmd_ in a subshell.
9047  * The built-in syntax <code>%x{...}</code> uses
9048  * this method. Sets <code>$?</code> to the process status.
9049  *
9050  * `date` #=> "Wed Apr 9 08:56:30 CDT 2003\n"
9051  * `ls testdir`.split[1] #=> "main.rb"
9052  * `echo oops && exit 99` #=> "oops\n"
9053  * $?.exitstatus #=> 99
9054  */
9055 
9056 static VALUE
9057 rb_f_backquote(VALUE obj, VALUE str)
9058 {
9059  VALUE port;
9060  VALUE result;
9061  rb_io_t *fptr;
9062 
9065  port = pipe_open_s(str, "r", FMODE_READABLE|DEFAULT_TEXTMODE, NULL);
9066  if (NIL_P(port)) return rb_str_new(0,0);
9067 
9068  GetOpenFile(port, fptr);
9069  result = read_all(fptr, remain_size(fptr), Qnil);
9070  rb_io_close(port);
9071  RFILE(port)->fptr = NULL;
9072  rb_io_fptr_finalize(fptr);
9073  rb_gc_force_recycle(port); /* also guards from premature GC */
9074 
9075  return result;
9076 }
9077 
9078 #ifdef HAVE_SYS_SELECT_H
9079 #include <sys/select.h>
9080 #endif
9081 
9082 static VALUE
9083 select_internal(VALUE read, VALUE write, VALUE except, struct timeval *tp, rb_fdset_t *fds)
9084 {
9085  VALUE res, list;
9086  rb_fdset_t *rp, *wp, *ep;
9087  rb_io_t *fptr;
9088  long i;
9089  int max = 0, n;
9090  int pending = 0;
9091  struct timeval timerec;
9092 
9093  if (!NIL_P(read)) {
9095  for (i=0; i<RARRAY_LEN(read); i++) {
9097  rb_fd_set(fptr->fd, &fds[0]);
9098  if (READ_DATA_PENDING(fptr) || READ_CHAR_PENDING(fptr)) { /* check for buffered data */
9099  pending++;
9100  rb_fd_set(fptr->fd, &fds[3]);
9101  }
9102  if (max < fptr->fd) max = fptr->fd;
9103  }
9104  if (pending) { /* no blocking if there's buffered data */
9105  timerec.tv_sec = timerec.tv_usec = 0;
9106  tp = &timerec;
9107  }
9108  rp = &fds[0];
9109  }
9110  else
9111  rp = 0;
9112 
9113  if (!NIL_P(write)) {
9115  for (i=0; i<RARRAY_LEN(write); i++) {
9117  GetOpenFile(write_io, fptr);
9118  rb_fd_set(fptr->fd, &fds[1]);
9119  if (max < fptr->fd) max = fptr->fd;
9120  }
9121  wp = &fds[1];
9122  }
9123  else
9124  wp = 0;
9125 
9126  if (!NIL_P(except)) {
9127  Check_Type(except, T_ARRAY);
9128  for (i=0; i<RARRAY_LEN(except); i++) {
9129  VALUE io = rb_io_get_io(RARRAY_AREF(except, i));
9130  VALUE write_io = GetWriteIO(io);
9131  GetOpenFile(io, fptr);
9132  rb_fd_set(fptr->fd, &fds[2]);
9133  if (max < fptr->fd) max = fptr->fd;
9134  if (io != write_io) {
9135  GetOpenFile(write_io, fptr);
9136  rb_fd_set(fptr->fd, &fds[2]);
9137  if (max < fptr->fd) max = fptr->fd;
9138  }
9139  }
9140  ep = &fds[2];
9141  }
9142  else {
9143  ep = 0;
9144  }
9145 
9146  max++;
9147 
9148  n = rb_thread_fd_select(max, rp, wp, ep, tp);
9149  if (n < 0) {
9150  rb_sys_fail(0);
9151  }
9152  if (!pending && n == 0) return Qnil; /* returns nil on timeout */
9153 
9154  res = rb_ary_new2(3);
9155  rb_ary_push(res, rp?rb_ary_new():rb_ary_new2(0));
9156  rb_ary_push(res, wp?rb_ary_new():rb_ary_new2(0));
9157  rb_ary_push(res, ep?rb_ary_new():rb_ary_new2(0));
9158 
9159  if (rp) {
9160  list = RARRAY_AREF(res, 0);
9161  for (i=0; i< RARRAY_LEN(read); i++) {
9162  VALUE obj = rb_ary_entry(read, i);
9163  VALUE io = rb_io_get_io(obj);
9164  GetOpenFile(io, fptr);
9165  if (rb_fd_isset(fptr->fd, &fds[0]) ||
9166  rb_fd_isset(fptr->fd, &fds[3])) {
9167  rb_ary_push(list, obj);
9168  }
9169  }
9170  }
9171 
9172  if (wp) {
9173  list = RARRAY_AREF(res, 1);
9174  for (i=0; i< RARRAY_LEN(write); i++) {
9176  VALUE io = rb_io_get_io(obj);
9177  VALUE write_io = GetWriteIO(io);
9178  GetOpenFile(write_io, fptr);
9179  if (rb_fd_isset(fptr->fd, &fds[1])) {
9180  rb_ary_push(list, obj);
9181  }
9182  }
9183  }
9184 
9185  if (ep) {
9186  list = RARRAY_AREF(res, 2);
9187  for (i=0; i< RARRAY_LEN(except); i++) {
9188  VALUE obj = rb_ary_entry(except, i);
9189  VALUE io = rb_io_get_io(obj);
9190  VALUE write_io = GetWriteIO(io);
9191  GetOpenFile(io, fptr);
9192  if (rb_fd_isset(fptr->fd, &fds[2])) {
9193  rb_ary_push(list, obj);
9194  }
9195  else if (io != write_io) {
9196  GetOpenFile(write_io, fptr);
9197  if (rb_fd_isset(fptr->fd, &fds[2])) {
9198  rb_ary_push(list, obj);
9199  }
9200  }
9201  }
9202  }
9203 
9204  return res; /* returns an empty array on interrupt */
9205 }
9206 
9207 struct select_args {
9209  struct timeval *timeout;
9211 };
9212 
9213 static VALUE
9214 select_call(VALUE arg)
9215 {
9216  struct select_args *p = (struct select_args *)arg;
9217 
9218  return select_internal(p->read, p->write, p->except, p->timeout, p->fdsets);
9219 }
9220 
9221 static VALUE
9222 select_end(VALUE arg)
9223 {
9224  struct select_args *p = (struct select_args *)arg;
9225  int i;
9226 
9227  for (i = 0; i < numberof(p->fdsets); ++i)
9228  rb_fd_term(&p->fdsets[i]);
9229  return Qnil;
9230 }
9231 
9232 static VALUE sym_normal, sym_sequential, sym_random,
9233  sym_willneed, sym_dontneed, sym_noreuse;
9234 
9235 #ifdef HAVE_POSIX_FADVISE
9236 struct io_advise_struct {
9237  int fd;
9238  int advice;
9239  off_t offset;
9240  off_t len;
9241 };
9242 
9243 static VALUE
9244 io_advise_internal(void *arg)
9245 {
9246  struct io_advise_struct *ptr = arg;
9247  return posix_fadvise(ptr->fd, ptr->offset, ptr->len, ptr->advice);
9248 }
9249 
9250 static VALUE
9251 io_advise_sym_to_const(VALUE sym)
9252 {
9253 #ifdef POSIX_FADV_NORMAL
9254  if (sym == sym_normal)
9255  return INT2NUM(POSIX_FADV_NORMAL);
9256 #endif
9257 
9258 #ifdef POSIX_FADV_RANDOM
9259  if (sym == sym_random)
9260  return INT2NUM(POSIX_FADV_RANDOM);
9261 #endif
9262 
9263 #ifdef POSIX_FADV_SEQUENTIAL
9264  if (sym == sym_sequential)
9265  return INT2NUM(POSIX_FADV_SEQUENTIAL);
9266 #endif
9267 
9268 #ifdef POSIX_FADV_WILLNEED
9269  if (sym == sym_willneed)
9270  return INT2NUM(POSIX_FADV_WILLNEED);
9271 #endif
9272 
9273 #ifdef POSIX_FADV_DONTNEED
9274  if (sym == sym_dontneed)
9275  return INT2NUM(POSIX_FADV_DONTNEED);
9276 #endif
9277 
9278 #ifdef POSIX_FADV_NOREUSE
9279  if (sym == sym_noreuse)
9280  return INT2NUM(POSIX_FADV_NOREUSE);
9281 #endif
9282 
9283  return Qnil;
9284 }
9285 
9286 static VALUE
9287 do_io_advise(rb_io_t *fptr, VALUE advice, off_t offset, off_t len)
9288 {
9289  int rv;
9290  struct io_advise_struct ias;
9291  VALUE num_adv;
9292 
9293  num_adv = io_advise_sym_to_const(advice);
9294 
9295  /*
9296  * The platform doesn't support this hint. We don't raise exception, instead
9297  * silently ignore it. Because IO::advise is only hint.
9298  */
9299  if (NIL_P(num_adv))
9300  return Qnil;
9301 
9302  ias.fd = fptr->fd;
9303  ias.advice = NUM2INT(num_adv);
9304  ias.offset = offset;
9305  ias.len = len;
9306 
9307  rv = (int)rb_thread_io_blocking_region(io_advise_internal, &ias, fptr->fd);
9308  if (rv && rv != ENOSYS) {
9309  /* posix_fadvise(2) doesn't set errno. On success it returns 0; otherwise
9310  it returns the error code. */
9311  VALUE message = rb_sprintf("%"PRIsVALUE" "
9312  "(%"PRI_OFFT_PREFIX"d, "
9313  "%"PRI_OFFT_PREFIX"d, "
9314  "%"PRIsVALUE")",
9315  fptr->pathv, offset, len, advice);
9316  rb_syserr_fail_str(rv, message);
9317  }
9318 
9319  return Qnil;
9320 }
9321 
9322 #endif /* HAVE_POSIX_FADVISE */
9323 
9324 static void
9325 advice_arg_check(VALUE advice)
9326 {
9327  if (!SYMBOL_P(advice))
9328  rb_raise(rb_eTypeError, "advice must be a Symbol");
9329 
9330  if (advice != sym_normal &&
9331  advice != sym_sequential &&
9332  advice != sym_random &&
9333  advice != sym_willneed &&
9334  advice != sym_dontneed &&
9335  advice != sym_noreuse) {
9336  rb_raise(rb_eNotImpError, "Unsupported advice: %+"PRIsVALUE, advice);
9337  }
9338 }
9339 
9340 /*
9341  * call-seq:
9342  * ios.advise(advice, offset=0, len=0) -> nil
9343  *
9344  * Announce an intention to access data from the current file in a
9345  * specific pattern. On platforms that do not support the
9346  * <em>posix_fadvise(2)</em> system call, this method is a no-op.
9347  *
9348  * _advice_ is one of the following symbols:
9349  *
9350  * :normal:: No advice to give; the default assumption for an open file.
9351  * :sequential:: The data will be accessed sequentially
9352  * with lower offsets read before higher ones.
9353  * :random:: The data will be accessed in random order.
9354  * :willneed:: The data will be accessed in the near future.
9355  * :dontneed:: The data will not be accessed in the near future.
9356  * :noreuse:: The data will only be accessed once.
9357  *
9358  * The semantics of a piece of advice are platform-dependent. See
9359  * <em>man 2 posix_fadvise</em> for details.
9360  *
9361  * "data" means the region of the current file that begins at
9362  * _offset_ and extends for _len_ bytes. If _len_ is 0, the region
9363  * ends at the last byte of the file. By default, both _offset_ and
9364  * _len_ are 0, meaning that the advice applies to the entire file.
9365  *
9366  * If an error occurs, one of the following exceptions will be raised:
9367  *
9368  * IOError:: The IO stream is closed.
9369  * Errno::EBADF::
9370  * The file descriptor of the current file is invalid.
9371  * Errno::EINVAL:: An invalid value for _advice_ was given.
9372  * Errno::ESPIPE::
9373  * The file descriptor of the current file refers to a FIFO or
9374  * pipe. (Linux raises Errno::EINVAL in this case).
9375  * TypeError::
9376  * Either _advice_ was not a Symbol, or one of the
9377  * other arguments was not an Integer.
9378  * RangeError:: One of the arguments given was too big/small.
9379  *
9380  * This list is not exhaustive; other Errno:: exceptions are also possible.
9381  */
9382 static VALUE
9383 rb_io_advise(int argc, VALUE *argv, VALUE io)
9384 {
9385  VALUE advice, offset, len;
9386  off_t off, l;
9387  rb_io_t *fptr;
9388 
9389  rb_scan_args(argc, argv, "12", &advice, &offset, &len);
9390  advice_arg_check(advice);
9391 
9392  io = GetWriteIO(io);
9393  GetOpenFile(io, fptr);
9394 
9395  off = NIL_P(offset) ? 0 : NUM2OFFT(offset);
9396  l = NIL_P(len) ? 0 : NUM2OFFT(len);
9397 
9398 #ifdef HAVE_POSIX_FADVISE
9399  return do_io_advise(fptr, advice, off, l);
9400 #else
9401  ((void)off, (void)l); /* Ignore all hint */
9402  return Qnil;
9403 #endif
9404 }
9405 
9406 /*
9407  * call-seq:
9408  * IO.select(read_array [, write_array [, error_array [, timeout]]]) -> array or nil
9409  *
9410  * Calls select(2) system call.
9411  * It monitors given arrays of IO objects, waits until one or more of
9412  * IO objects are ready for reading, are ready for writing, and have
9413  * pending exceptions respectively, and returns an array that contains
9414  * arrays of those IO objects. It will return +nil+ if optional
9415  * <i>timeout</i> value is given and no IO object is ready in
9416  * <i>timeout</i> seconds.
9417  *
9418  * IO.select peeks the buffer of IO objects for testing readability.
9419  * If the IO buffer is not empty, IO.select immediately notifies
9420  * readability. This "peek" only happens for IO objects. It does not
9421  * happen for IO-like objects such as OpenSSL::SSL::SSLSocket.
9422  *
9423  * The best way to use IO.select is invoking it after nonblocking
9424  * methods such as #read_nonblock, #write_nonblock, etc. The methods
9425  * raise an exception which is extended by IO::WaitReadable or
9426  * IO::WaitWritable. The modules notify how the caller should wait
9427  * with IO.select. If IO::WaitReadable is raised, the caller should
9428  * wait for reading. If IO::WaitWritable is raised, the caller should
9429  * wait for writing.
9430  *
9431  * So, blocking read (#readpartial) can be emulated using
9432  * #read_nonblock and IO.select as follows:
9433  *
9434  * begin
9435  * result = io_like.read_nonblock(maxlen)
9436  * rescue IO::WaitReadable
9437  * IO.select([io_like])
9438  * retry
9439  * rescue IO::WaitWritable
9440  * IO.select(nil, [io_like])
9441  * retry
9442  * end
9443  *
9444  * Especially, the combination of nonblocking methods and IO.select is
9445  * preferred for IO like objects such as OpenSSL::SSL::SSLSocket. It
9446  * has #to_io method to return underlying IO object. IO.select calls
9447  * #to_io to obtain the file descriptor to wait.
9448  *
9449  * This means that readability notified by IO.select doesn't mean
9450  * readability from OpenSSL::SSL::SSLSocket object.
9451  *
9452  * The most likely situation is that OpenSSL::SSL::SSLSocket buffers
9453  * some data. IO.select doesn't see the buffer. So IO.select can
9454  * block when OpenSSL::SSL::SSLSocket#readpartial doesn't block.
9455  *
9456  * However, several more complicated situations exist.
9457  *
9458  * SSL is a protocol which is sequence of records.
9459  * The record consists of multiple bytes.
9460  * So, the remote side of SSL sends a partial record, IO.select
9461  * notifies readability but OpenSSL::SSL::SSLSocket cannot decrypt a
9462  * byte and OpenSSL::SSL::SSLSocket#readpartial will block.
9463  *
9464  * Also, the remote side can request SSL renegotiation which forces
9465  * the local SSL engine to write some data.
9466  * This means OpenSSL::SSL::SSLSocket#readpartial may invoke #write
9467  * system call and it can block.
9468  * In such a situation, OpenSSL::SSL::SSLSocket#read_nonblock raises
9469  * IO::WaitWritable instead of blocking.
9470  * So, the caller should wait for ready for writability as above
9471  * example.
9472  *
9473  * The combination of nonblocking methods and IO.select is also useful
9474  * for streams such as tty, pipe socket socket when multiple processes
9475  * read from a stream.
9476  *
9477  * Finally, Linux kernel developers don't guarantee that
9478  * readability of select(2) means readability of following read(2) even
9479  * for a single process.
9480  * See select(2) manual on GNU/Linux system.
9481  *
9482  * Invoking IO.select before IO#readpartial works well as usual.
9483  * However it is not the best way to use IO.select.
9484  *
9485  * The writability notified by select(2) doesn't show
9486  * how many bytes are writable.
9487  * IO#write method blocks until given whole string is written.
9488  * So, <code>IO#write(two or more bytes)</code> can block after
9489  * writability is notified by IO.select. IO#write_nonblock is required
9490  * to avoid the blocking.
9491  *
9492  * Blocking write (#write) can be emulated using #write_nonblock and
9493  * IO.select as follows: IO::WaitReadable should also be rescued for
9494  * SSL renegotiation in OpenSSL::SSL::SSLSocket.
9495  *
9496  * while 0 < string.bytesize
9497  * begin
9498  * written = io_like.write_nonblock(string)
9499  * rescue IO::WaitReadable
9500  * IO.select([io_like])
9501  * retry
9502  * rescue IO::WaitWritable
9503  * IO.select(nil, [io_like])
9504  * retry
9505  * end
9506  * string = string.byteslice(written..-1)
9507  * end
9508  *
9509  * === Parameters
9510  * read_array:: an array of IO objects that wait until ready for read
9511  * write_array:: an array of IO objects that wait until ready for write
9512  * error_array:: an array of IO objects that wait for exceptions
9513  * timeout:: a numeric value in second
9514  *
9515  * === Example
9516  *
9517  * rp, wp = IO.pipe
9518  * mesg = "ping "
9519  * 100.times {
9520  * # IO.select follows IO#read. Not the best way to use IO.select.
9521  * rs, ws, = IO.select([rp], [wp])
9522  * if r = rs[0]
9523  * ret = r.read(5)
9524  * print ret
9525  * case ret
9526  * when /ping/
9527  * mesg = "pong\n"
9528  * when /pong/
9529  * mesg = "ping "
9530  * end
9531  * end
9532  * if w = ws[0]
9533  * w.write(mesg)
9534  * end
9535  * }
9536  *
9537  * <em>produces:</em>
9538  *
9539  * ping pong
9540  * ping pong
9541  * ping pong
9542  * (snipped)
9543  * ping
9544  */
9545 
9546 static VALUE
9547 rb_f_select(int argc, VALUE *argv, VALUE obj)
9548 {
9549  VALUE timeout;
9550  struct select_args args;
9551  struct timeval timerec;
9552  int i;
9553 
9554  rb_scan_args(argc, argv, "13", &args.read, &args.write, &args.except, &timeout);
9555  if (NIL_P(timeout)) {
9556  args.timeout = 0;
9557  }
9558  else {
9559  timerec = rb_time_interval(timeout);
9560  args.timeout = &timerec;
9561  }
9562 
9563  for (i = 0; i < numberof(args.fdsets); ++i)
9564  rb_fd_init(&args.fdsets[i]);
9565 
9566  return rb_ensure(select_call, (VALUE)&args, select_end, (VALUE)&args);
9567 }
9568 
9569 #if (defined(__linux__) && !defined(__ANDROID__)) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
9570  typedef unsigned long ioctl_req_t;
9571 # define NUM2IOCTLREQ(num) NUM2ULONG(num)
9572 #else
9573  typedef int ioctl_req_t;
9574 # define NUM2IOCTLREQ(num) ((int)NUM2LONG(num))
9575 #endif
9576 
9577 #ifdef HAVE_IOCTL
9578 struct ioctl_arg {
9579  int fd;
9580  ioctl_req_t cmd;
9581  long narg;
9582 };
9583 
9584 static VALUE
9585 nogvl_ioctl(void *ptr)
9586 {
9587  struct ioctl_arg *arg = ptr;
9588 
9589  return (VALUE)ioctl(arg->fd, arg->cmd, arg->narg);
9590 }
9591 
9592 static int
9593 do_ioctl(int fd, ioctl_req_t cmd, long narg)
9594 {
9595  int retval;
9596  struct ioctl_arg arg;
9597 
9598  arg.fd = fd;
9599  arg.cmd = cmd;
9600  arg.narg = narg;
9601 
9602  retval = (int)rb_thread_io_blocking_region(nogvl_ioctl, &arg, fd);
9603 
9604  return retval;
9605 }
9606 #endif
9607 
9608 #define DEFULT_IOCTL_NARG_LEN (256)
9609 
9610 #if defined(__linux__) && defined(_IOC_SIZE)
9611 static long
9612 linux_iocparm_len(ioctl_req_t cmd)
9613 {
9614  long len;
9615 
9616  if ((cmd & 0xFFFF0000) == 0) {
9617  /* legacy and unstructured ioctl number. */
9618  return DEFULT_IOCTL_NARG_LEN;
9619  }
9620 
9621  len = _IOC_SIZE(cmd);
9622 
9623  /* paranoia check for silly drivers which don't keep ioctl convention */
9624  if (len < DEFULT_IOCTL_NARG_LEN)
9626 
9627  return len;
9628 }
9629 #endif
9630 
9631 static long
9632 ioctl_narg_len(ioctl_req_t cmd)
9633 {
9634  long len;
9635 
9636 #ifdef IOCPARM_MASK
9637 #ifndef IOCPARM_LEN
9638 #define IOCPARM_LEN(x) (((x) >> 16) & IOCPARM_MASK)
9639 #endif
9640 #endif
9641 #ifdef IOCPARM_LEN
9642  len = IOCPARM_LEN(cmd); /* on BSDish systems we're safe */
9643 #elif defined(__linux__) && defined(_IOC_SIZE)
9644  len = linux_iocparm_len(cmd);
9645 #else
9646  /* otherwise guess at what's safe */
9648 #endif
9649 
9650  return len;
9651 }
9652 
9653 #ifdef HAVE_FCNTL
9654 #ifdef __linux__
9655 typedef long fcntl_arg_t;
9656 #else
9657 /* posix */
9658 typedef int fcntl_arg_t;
9659 #endif
9660 
9661 static long
9662 fcntl_narg_len(int cmd)
9663 {
9664  long len;
9665 
9666  switch (cmd) {
9667 #ifdef F_DUPFD
9668  case F_DUPFD:
9669  len = sizeof(fcntl_arg_t);
9670  break;
9671 #endif
9672 #ifdef F_DUP2FD /* bsd specific */
9673  case F_DUP2FD:
9674  len = sizeof(int);
9675  break;
9676 #endif
9677 #ifdef F_DUPFD_CLOEXEC /* linux specific */
9678  case F_DUPFD_CLOEXEC:
9679  len = sizeof(fcntl_arg_t);
9680  break;
9681 #endif
9682 #ifdef F_GETFD
9683  case F_GETFD:
9684  len = 1;
9685  break;
9686 #endif
9687 #ifdef F_SETFD
9688  case F_SETFD:
9689  len = sizeof(fcntl_arg_t);
9690  break;
9691 #endif
9692 #ifdef F_GETFL
9693  case F_GETFL:
9694  len = 1;
9695  break;
9696 #endif
9697 #ifdef F_SETFL
9698  case F_SETFL:
9699  len = sizeof(fcntl_arg_t);
9700  break;
9701 #endif
9702 #ifdef F_GETOWN
9703  case F_GETOWN:
9704  len = 1;
9705  break;
9706 #endif
9707 #ifdef F_SETOWN
9708  case F_SETOWN:
9709  len = sizeof(fcntl_arg_t);
9710  break;
9711 #endif
9712 #ifdef F_GETOWN_EX /* linux specific */
9713  case F_GETOWN_EX:
9714  len = sizeof(struct f_owner_ex);
9715  break;
9716 #endif
9717 #ifdef F_SETOWN_EX /* linux specific */
9718  case F_SETOWN_EX:
9719  len = sizeof(struct f_owner_ex);
9720  break;
9721 #endif
9722 #ifdef F_GETLK
9723  case F_GETLK:
9724  len = sizeof(struct flock);
9725  break;
9726 #endif
9727 #ifdef F_SETLK
9728  case F_SETLK:
9729  len = sizeof(struct flock);
9730  break;
9731 #endif
9732 #ifdef F_SETLKW
9733  case F_SETLKW:
9734  len = sizeof(struct flock);
9735  break;
9736 #endif
9737 #ifdef F_READAHEAD /* bsd specific */
9738  case F_READAHEAD:
9739  len = sizeof(int);
9740  break;
9741 #endif
9742 #ifdef F_RDAHEAD /* Darwin specific */
9743  case F_RDAHEAD:
9744  len = sizeof(int);
9745  break;
9746 #endif
9747 #ifdef F_GETSIG /* linux specific */
9748  case F_GETSIG:
9749  len = 1;
9750  break;
9751 #endif
9752 #ifdef F_SETSIG /* linux specific */
9753  case F_SETSIG:
9754  len = sizeof(fcntl_arg_t);
9755  break;
9756 #endif
9757 #ifdef F_GETLEASE /* linux specific */
9758  case F_GETLEASE:
9759  len = 1;
9760  break;
9761 #endif
9762 #ifdef F_SETLEASE /* linux specific */
9763  case F_SETLEASE:
9764  len = sizeof(fcntl_arg_t);
9765  break;
9766 #endif
9767 #ifdef F_NOTIFY /* linux specific */
9768  case F_NOTIFY:
9769  len = sizeof(fcntl_arg_t);
9770  break;
9771 #endif
9772 
9773  default:
9774  len = 256;
9775  break;
9776  }
9777 
9778  return len;
9779 }
9780 #else /* HAVE_FCNTL */
9781 static long
9782 fcntl_narg_len(int cmd)
9783 {
9784  return 0;
9785 }
9786 #endif /* HAVE_FCNTL */
9787 
9788 static long
9789 setup_narg(ioctl_req_t cmd, VALUE *argp, int io_p)
9790 {
9791  long narg = 0;
9792  VALUE arg = *argp;
9793 
9794  if (NIL_P(arg) || arg == Qfalse) {
9795  narg = 0;
9796  }
9797  else if (FIXNUM_P(arg)) {
9798  narg = FIX2LONG(arg);
9799  }
9800  else if (arg == Qtrue) {
9801  narg = 1;
9802  }
9803  else {
9805 
9806  if (NIL_P(tmp)) {
9807  narg = NUM2LONG(arg);
9808  }
9809  else {
9810  char *ptr;
9811  long len, slen;
9812 
9813  *argp = arg = tmp;
9814  if (io_p)
9815  len = ioctl_narg_len(cmd);
9816  else
9817  len = fcntl_narg_len((int)cmd);
9818  rb_str_modify(arg);
9819 
9820  slen = RSTRING_LEN(arg);
9821  /* expand for data + sentinel. */
9822  if (slen < len+1) {
9823  rb_str_resize(arg, len+1);
9824  MEMZERO(RSTRING_PTR(arg)+slen, char, len-slen);
9825  slen = len+1;
9826  }
9827  /* a little sanity check here */
9828  ptr = RSTRING_PTR(arg);
9829  ptr[slen - 1] = 17;
9830  narg = (long)(SIGNED_VALUE)ptr;
9831  }
9832  }
9833 
9834  return narg;
9835 }
9836 
9837 #ifdef HAVE_IOCTL
9838 static VALUE
9839 rb_ioctl(VALUE io, VALUE req, VALUE arg)
9840 {
9841  ioctl_req_t cmd = NUM2IOCTLREQ(req);
9842  rb_io_t *fptr;
9843  long narg;
9844  int retval;
9845 
9846  narg = setup_narg(cmd, &arg, 1);
9847  GetOpenFile(io, fptr);
9848  retval = do_ioctl(fptr->fd, cmd, narg);
9849  if (retval < 0) rb_sys_fail_path(fptr->pathv);
9850  if (RB_TYPE_P(arg, T_STRING)) {
9851  char *ptr;
9852  long slen;
9853  RSTRING_GETMEM(arg, ptr, slen);
9854  if (ptr[slen-1] != 17)
9855  rb_raise(rb_eArgError, "return value overflowed string");
9856  ptr[slen-1] = '\0';
9857  }
9858 
9859  return INT2NUM(retval);
9860 }
9861 
9862 /*
9863  * call-seq:
9864  * ios.ioctl(integer_cmd, arg) -> integer
9865  *
9866  * Provides a mechanism for issuing low-level commands to control or
9867  * query I/O devices. Arguments and results are platform dependent. If
9868  * <i>arg</i> is a number, its value is passed directly. If it is a
9869  * string, it is interpreted as a binary sequence of bytes. On Unix
9870  * platforms, see <code>ioctl(2)</code> for details. Not implemented on
9871  * all platforms.
9872  */
9873 
9874 static VALUE
9875 rb_io_ioctl(int argc, VALUE *argv, VALUE io)
9876 {
9877  VALUE req, arg;
9878 
9879  rb_scan_args(argc, argv, "11", &req, &arg);
9880  return rb_ioctl(io, req, arg);
9881 }
9882 #else
9883 #define rb_io_ioctl rb_f_notimplement
9884 #endif
9885 
9886 #ifdef HAVE_FCNTL
9887 struct fcntl_arg {
9888  int fd;
9889  int cmd;
9890  long narg;
9891 };
9892 
9893 static VALUE
9894 nogvl_fcntl(void *ptr)
9895 {
9896  struct fcntl_arg *arg = ptr;
9897 
9898 #if defined(F_DUPFD)
9899  if (arg->cmd == F_DUPFD)
9900  return (VALUE)rb_cloexec_fcntl_dupfd(arg->fd, (int)arg->narg);
9901 #endif
9902  return (VALUE)fcntl(arg->fd, arg->cmd, arg->narg);
9903 }
9904 
9905 static int
9906 do_fcntl(int fd, int cmd, long narg)
9907 {
9908  int retval;
9909  struct fcntl_arg arg;
9910 
9911  arg.fd = fd;
9912  arg.cmd = cmd;
9913  arg.narg = narg;
9914 
9915  retval = (int)rb_thread_io_blocking_region(nogvl_fcntl, &arg, fd);
9916  if (retval != -1) {
9917  switch (cmd) {
9918 #if defined(F_DUPFD)
9919  case F_DUPFD:
9920 #endif
9921 #if defined(F_DUPFD_CLOEXEC)
9922  case F_DUPFD_CLOEXEC:
9923 #endif
9924  rb_update_max_fd(retval);
9925  }
9926  }
9927 
9928  return retval;
9929 }
9930 
9931 static VALUE
9932 rb_fcntl(VALUE io, VALUE req, VALUE arg)
9933 {
9934  int cmd = NUM2INT(req);
9935  rb_io_t *fptr;
9936  long narg;
9937  int retval;
9938 
9939  narg = setup_narg(cmd, &arg, 0);
9940  GetOpenFile(io, fptr);
9941  retval = do_fcntl(fptr->fd, cmd, narg);
9942  if (retval < 0) rb_sys_fail_path(fptr->pathv);
9943  if (RB_TYPE_P(arg, T_STRING)) {
9944  char *ptr;
9945  long slen;
9946  RSTRING_GETMEM(arg, ptr, slen);
9947  if (ptr[slen-1] != 17)
9948  rb_raise(rb_eArgError, "return value overflowed string");
9949  ptr[slen-1] = '\0';
9950  }
9951 
9952  return INT2NUM(retval);
9953 }
9954 
9955 /*
9956  * call-seq:
9957  * ios.fcntl(integer_cmd, arg) -> integer
9958  *
9959  * Provides a mechanism for issuing low-level commands to control or
9960  * query file-oriented I/O streams. Arguments and results are platform
9961  * dependent. If <i>arg</i> is a number, its value is passed
9962  * directly. If it is a string, it is interpreted as a binary sequence
9963  * of bytes (Array#pack might be a useful way to build this string). On
9964  * Unix platforms, see <code>fcntl(2)</code> for details. Not
9965  * implemented on all platforms.
9966  */
9967 
9968 static VALUE
9969 rb_io_fcntl(int argc, VALUE *argv, VALUE io)
9970 {
9971  VALUE req, arg;
9972 
9973  rb_scan_args(argc, argv, "11", &req, &arg);
9974  return rb_fcntl(io, req, arg);
9975 }
9976 #else
9977 #define rb_io_fcntl rb_f_notimplement
9978 #endif
9979 
9980 #if defined(HAVE_SYSCALL) || defined(HAVE___SYSCALL)
9981 /*
9982  * call-seq:
9983  * syscall(num [, args...]) -> integer
9984  *
9985  * Calls the operating system function identified by _num_ and
9986  * returns the result of the function or raises SystemCallError if
9987  * it failed.
9988  *
9989  * Arguments for the function can follow _num_. They must be either
9990  * +String+ objects or +Integer+ objects. A +String+ object is passed
9991  * as a pointer to the byte sequence. An +Integer+ object is passed
9992  * as an integer whose bit size is same as a pointer.
9993  * Up to nine parameters may be passed.
9994  *
9995  * The function identified by _num_ is system
9996  * dependent. On some Unix systems, the numbers may be obtained from a
9997  * header file called <code>syscall.h</code>.
9998  *
9999  * syscall 4, 1, "hello\n", 6 # '4' is write(2) on our box
10000  *
10001  * <em>produces:</em>
10002  *
10003  * hello
10004  *
10005  * Calling +syscall+ on a platform which does not have any way to
10006  * an arbitrary system function just fails with NotImplementedError.
10007  *
10008  * *Note:*
10009  * +syscall+ is essentially unsafe and unportable.
10010  * Feel free to shoot your foot.
10011  * The DL (Fiddle) library is preferred for safer and a bit
10012  * more portable programming.
10013  */
10014 
10015 static VALUE
10017 {
10018  VALUE arg[8];
10019 #if SIZEOF_VOIDP == 8 && defined(HAVE___SYSCALL) && SIZEOF_INT != 8 /* mainly *BSD */
10020 # define SYSCALL __syscall
10021 # define NUM2SYSCALLID(x) NUM2LONG(x)
10022 # define RETVAL2NUM(x) LONG2NUM(x)
10023 # if SIZEOF_LONG == 8
10024  long num, retval = -1;
10025 # elif SIZEOF_LONG_LONG == 8
10026  long long num, retval = -1;
10027 # else
10028 # error ---->> it is asserted that __syscall takes the first argument and returns retval in 64bit signed integer. <<----
10029 # endif
10030 #elif defined(__linux__)
10031 # define SYSCALL syscall
10032 # define NUM2SYSCALLID(x) NUM2LONG(x)
10033 # define RETVAL2NUM(x) LONG2NUM(x)
10034  /*
10035  * Linux man page says, syscall(2) function prototype is below.
10036  *
10037  * int syscall(int number, ...);
10038  *
10039  * But, it's incorrect. Actual one takes and returned long. (see unistd.h)
10040  */
10041  long num, retval = -1;
10042 #else
10043 # define SYSCALL syscall
10044 # define NUM2SYSCALLID(x) NUM2INT(x)
10045 # define RETVAL2NUM(x) INT2NUM(x)
10046  int num, retval = -1;
10047 #endif
10048  int i;
10049 
10050  if (RTEST(ruby_verbose)) {
10051  rb_warning("We plan to remove a syscall function at future release. DL(Fiddle) provides safer alternative.");
10052  }
10053 
10054  if (argc == 0)
10055  rb_raise(rb_eArgError, "too few arguments for syscall");
10056  if (argc > numberof(arg))
10057  rb_raise(rb_eArgError, "too many arguments for syscall");
10058  num = NUM2SYSCALLID(argv[0]); ++argv;
10059  for (i = argc - 1; i--; ) {
10061 
10062  if (!NIL_P(v)) {
10063  SafeStringValue(v);
10064  rb_str_modify(v);
10065  arg[i] = (VALUE)StringValueCStr(v);
10066  }
10067  else {
10068  arg[i] = (VALUE)NUM2LONG(argv[i]);
10069  }
10070  }
10071 
10072  switch (argc) {
10073  case 1:
10074  retval = SYSCALL(num);
10075  break;
10076  case 2:
10077  retval = SYSCALL(num, arg[0]);
10078  break;
10079  case 3:
10080  retval = SYSCALL(num, arg[0],arg[1]);
10081  break;
10082  case 4:
10083  retval = SYSCALL(num, arg[0],arg[1],arg[2]);
10084  break;
10085  case 5:
10086  retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3]);
10087  break;
10088  case 6:
10089  retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4]);
10090  break;
10091  case 7:
10092  retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5]);
10093  break;
10094  case 8:
10095  retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6]);
10096  break;
10097  }
10098 
10099  if (retval == -1)
10100  rb_sys_fail(0);
10101  return RETVAL2NUM(retval);
10102 #undef SYSCALL
10103 #undef NUM2SYSCALLID
10104 #undef RETVAL2NUM
10105 }
10106 #else
10107 #define rb_f_syscall rb_f_notimplement
10108 #endif
10109 
10110 static VALUE
10111 io_new_instance(VALUE args)
10112 {
10113  return rb_class_new_instance(2, (VALUE*)args+1, *(VALUE*)args);
10114 }
10115 
10116 static rb_encoding *
10117 find_encoding(VALUE v)
10118 {
10119  rb_encoding *enc = rb_find_encoding(v);
10120  if (!enc) rb_warn("Unsupported encoding %"PRIsVALUE" ignored", v);
10121  return enc;
10122 }
10123 
10124 static void
10125 io_encoding_set(rb_io_t *fptr, VALUE v1, VALUE v2, VALUE opt)
10126 {
10127  rb_encoding *enc, *enc2;
10128  int ecflags = fptr->encs.ecflags;
10129  VALUE ecopts, tmp;
10130 
10131  if (!NIL_P(v2)) {
10132  enc2 = find_encoding(v1);
10133  tmp = rb_check_string_type(v2);
10134  if (!NIL_P(tmp)) {
10135  if (RSTRING_LEN(tmp) == 1 && RSTRING_PTR(tmp)[0] == '-') {
10136  /* Special case - "-" => no transcoding */
10137  enc = enc2;
10138  enc2 = NULL;
10139  }
10140  else
10141  enc = find_encoding(v2);
10142  if (enc == enc2) {
10143  /* Special case - "-" => no transcoding */
10144  enc2 = NULL;
10145  }
10146  }
10147  else {
10148  enc = find_encoding(v2);
10149  if (enc == enc2) {
10150  /* Special case - "-" => no transcoding */
10151  enc2 = NULL;
10152  }
10153  }
10155  ecflags = rb_econv_prepare_options(opt, &ecopts, ecflags);
10156  }
10157  else {
10158  if (NIL_P(v1)) {
10159  /* Set to default encodings */
10160  rb_io_ext_int_to_encs(NULL, NULL, &enc, &enc2, 0);
10162  ecopts = Qnil;
10163  }
10164  else {
10165  tmp = rb_check_string_type(v1);
10166  if (!NIL_P(tmp) && rb_enc_asciicompat(enc = rb_enc_get(tmp))) {
10167  parse_mode_enc(RSTRING_PTR(tmp), enc, &enc, &enc2, NULL);
10169  ecflags = rb_econv_prepare_options(opt, &ecopts, ecflags);
10170  }
10171  else {
10172  rb_io_ext_int_to_encs(find_encoding(v1), NULL, &enc, &enc2, 0);
10174  ecopts = Qnil;
10175  }
10176  }
10177  }
10178  validate_enc_binmode(&fptr->mode, ecflags, enc, enc2);
10179  fptr->encs.enc = enc;
10180  fptr->encs.enc2 = enc2;
10181  fptr->encs.ecflags = ecflags;
10182  fptr->encs.ecopts = ecopts;
10183  clear_codeconv(fptr);
10184 
10185 }
10186 
10192 };
10193 
10194 static VALUE
10195 io_encoding_set_v(VALUE v)
10196 {
10197  struct io_encoding_set_args *arg = (struct io_encoding_set_args *)v;
10198  io_encoding_set(arg->fptr, arg->v1, arg->v2, arg->opt);
10199  return Qnil;
10200 }
10201 
10202 static VALUE
10203 pipe_pair_close(VALUE rw)
10204 {
10205  VALUE *rwp = (VALUE *)rw;
10206  return rb_ensure(io_close, rwp[0], io_close, rwp[1]);
10207 }
10208 
10209 /*
10210  * call-seq:
10211  * IO.pipe -> [read_io, write_io]
10212  * IO.pipe(ext_enc) -> [read_io, write_io]
10213  * IO.pipe("ext_enc:int_enc" [, opt]) -> [read_io, write_io]
10214  * IO.pipe(ext_enc, int_enc [, opt]) -> [read_io, write_io]
10215  *
10216  * IO.pipe(...) {|read_io, write_io| ... }
10217  *
10218  * Creates a pair of pipe endpoints (connected to each other) and
10219  * returns them as a two-element array of IO objects:
10220  * <code>[</code> <i>read_io</i>, <i>write_io</i> <code>]</code>.
10221  *
10222  * If a block is given, the block is called and
10223  * returns the value of the block.
10224  * <i>read_io</i> and <i>write_io</i> are sent to the block as arguments.
10225  * If read_io and write_io are not closed when the block exits, they are closed.
10226  * i.e. closing read_io and/or write_io doesn't cause an error.
10227  *
10228  * Not available on all platforms.
10229  *
10230  * If an encoding (encoding name or encoding object) is specified as an optional argument,
10231  * read string from pipe is tagged with the encoding specified.
10232  * If the argument is a colon separated two encoding names "A:B",
10233  * the read string is converted from encoding A (external encoding)
10234  * to encoding B (internal encoding), then tagged with B.
10235  * If two optional arguments are specified, those must be
10236  * encoding objects or encoding names,
10237  * and the first one is the external encoding,
10238  * and the second one is the internal encoding.
10239  * If the external encoding and the internal encoding is specified,
10240  * optional hash argument specify the conversion option.
10241  *
10242  * In the example below, the two processes close the ends of the pipe
10243  * that they are not using. This is not just a cosmetic nicety. The
10244  * read end of a pipe will not generate an end of file condition if
10245  * there are any writers with the pipe still open. In the case of the
10246  * parent process, the <code>rd.read</code> will never return if it
10247  * does not first issue a <code>wr.close</code>.
10248  *
10249  * rd, wr = IO.pipe
10250  *
10251  * if fork
10252  * wr.close
10253  * puts "Parent got: <#{rd.read}>"
10254  * rd.close
10255  * Process.wait
10256  * else
10257  * rd.close
10258  * puts "Sending message to parent"
10259  * wr.write "Hi Dad"
10260  * wr.close
10261  * end
10262  *
10263  * <em>produces:</em>
10264  *
10265  * Sending message to parent
10266  * Parent got: <Hi Dad>
10267  */
10268 
10269 static VALUE
10270 rb_io_s_pipe(int argc, VALUE *argv, VALUE klass)
10271 {
10272  int pipes[2], state;
10273  VALUE r, w, args[3], v1, v2;
10274  VALUE opt;
10275  rb_io_t *fptr, *fptr2;
10276  struct io_encoding_set_args ies_args;
10277  int fmode = 0;
10278  VALUE ret;
10279 
10280  argc = rb_scan_args(argc, argv, "02:", &v1, &v2, &opt);
10281  if (rb_pipe(pipes) < 0)
10282  rb_sys_fail(0);
10283 
10284  args[0] = klass;
10285  args[1] = INT2NUM(pipes[0]);
10286  args[2] = INT2FIX(O_RDONLY);
10287  r = rb_protect(io_new_instance, (VALUE)args, &state);
10288  if (state) {
10289  close(pipes[0]);
10290  close(pipes[1]);
10291  rb_jump_tag(state);
10292  }
10293  GetOpenFile(r, fptr);
10294 
10295  ies_args.fptr = fptr;
10296  ies_args.v1 = v1;
10297  ies_args.v2 = v2;
10298  ies_args.opt = opt;
10299  rb_protect(io_encoding_set_v, (VALUE)&ies_args, &state);
10300  if (state) {
10301  close(pipes[1]);
10302  io_close(r);
10303  rb_jump_tag(state);
10304  }
10305 
10306  args[1] = INT2NUM(pipes[1]);
10307  args[2] = INT2FIX(O_WRONLY);
10308  w = rb_protect(io_new_instance, (VALUE)args, &state);
10309  if (state) {
10310  close(pipes[1]);
10311  if (!NIL_P(r)) rb_io_close(r);
10312  rb_jump_tag(state);
10313  }
10314  GetOpenFile(w, fptr2);
10315  rb_io_synchronized(fptr2);
10316 
10317  extract_binmode(opt, &fmode);
10318 
10319  if ((fmode & FMODE_BINMODE) && v1 == Qnil) {
10322  }
10323 
10324 #if DEFAULT_TEXTMODE
10325  if ((fptr->mode & FMODE_TEXTMODE) && (fmode & FMODE_BINMODE)) {
10326  fptr->mode &= ~FMODE_TEXTMODE;
10327  setmode(fptr->fd, O_BINARY);
10328  }
10329 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
10332  }
10333 #endif
10334 #endif
10335  fptr->mode |= fmode;
10336 #if DEFAULT_TEXTMODE
10337  if ((fptr2->mode & FMODE_TEXTMODE) && (fmode & FMODE_BINMODE)) {
10338  fptr2->mode &= ~FMODE_TEXTMODE;
10339  setmode(fptr2->fd, O_BINARY);
10340  }
10341 #endif
10342  fptr2->mode |= fmode;
10343 
10344  ret = rb_assoc_new(r, w);
10345  if (rb_block_given_p()) {
10346  VALUE rw[2];
10347  rw[0] = r;
10348  rw[1] = w;
10349  return rb_ensure(rb_yield, ret, pipe_pair_close, (VALUE)rw);
10350  }
10351  return ret;
10352 }
10353 
10354 struct foreach_arg {
10355  int argc;
10358 };
10359 
10360 static void
10361 open_key_args(VALUE klass, int argc, VALUE *argv, VALUE opt, struct foreach_arg *arg)
10362 {
10363  VALUE path, v;
10364  VALUE vmode = Qnil, vperm = Qnil;
10365 
10366  path = *argv++;
10367  argc--;
10369  arg->io = 0;
10370  arg->argc = argc;
10371  arg->argv = argv;
10372  if (NIL_P(opt)) {
10373  vmode = INT2NUM(O_RDONLY);
10374  vperm = INT2FIX(0666);
10375  }
10376  else if (!NIL_P(v = rb_hash_aref(opt, sym_open_args))) {
10377  int n;
10378 
10379  v = rb_to_array_type(v);
10380  n = RARRAY_LENINT(v);
10381  rb_check_arity(n, 0, 3); /* rb_io_open */
10382  rb_scan_args_kw(RB_SCAN_ARGS_LAST_HASH_KEYWORDS, n, RARRAY_CONST_PTR(v), "02:", &vmode, &vperm, &opt);
10383  }
10384  arg->io = rb_io_open(klass, path, vmode, vperm, opt);
10385 }
10386 
10387 static VALUE
10388 io_s_foreach(VALUE v)
10389 {
10390  struct getline_arg *arg = (void *)v;
10391  VALUE str;
10392 
10393  while (!NIL_P(str = rb_io_getline_1(arg->rs, arg->limit, arg->chomp, arg->io))) {
10395  rb_yield(str);
10396  }
10398  return Qnil;
10399 }
10400 
10401 /*
10402  * call-seq:
10403  * IO.foreach(name, sep=$/ [, getline_args, open_args]) {|line| block } -> nil
10404  * IO.foreach(name, limit [, getline_args, open_args]) {|line| block } -> nil
10405  * IO.foreach(name, sep, limit [, getline_args, open_args]) {|line| block } -> nil
10406  * IO.foreach(...) -> an_enumerator
10407  *
10408  * Executes the block for every line in the named I/O port, where lines
10409  * are separated by <em>sep</em>.
10410  *
10411  * If no block is given, an enumerator is returned instead.
10412  *
10413  * IO.foreach("testfile") {|x| print "GOT ", x }
10414  *
10415  * <em>produces:</em>
10416  *
10417  * GOT This is line one
10418  * GOT This is line two
10419  * GOT This is line three
10420  * GOT And so on...
10421  *
10422  * If the last argument is a hash, it's the keyword argument to open.
10423  * See IO.readlines for details about getline_args.
10424  * And see also IO.read for details about open_args.
10425  *
10426  */
10427 
10428 static VALUE
10429 rb_io_s_foreach(int argc, VALUE *argv, VALUE self)
10430 {
10431  VALUE opt;
10432  int orig_argc = argc;
10433  struct foreach_arg arg;
10434  struct getline_arg garg;
10435 
10436  argc = rb_scan_args(argc, argv, "13:", NULL, NULL, NULL, NULL, &opt);
10437  RETURN_ENUMERATOR(self, orig_argc, argv);
10438  extract_getline_args(argc-1, argv+1, &garg);
10439  open_key_args(self, argc, argv, opt, &arg);
10440  if (NIL_P(arg.io)) return Qnil;
10441  extract_getline_opts(opt, &garg);
10442  check_getline_args(&garg.rs, &garg.limit, garg.io = arg.io);
10443  return rb_ensure(io_s_foreach, (VALUE)&garg, rb_io_close, arg.io);
10444 }
10445 
10446 static VALUE
10447 io_s_readlines(VALUE v)
10448 {
10449  struct getline_arg *arg = (void *)v;
10450  return io_readlines(arg, arg->io);
10451 }
10452 
10453 /*
10454  * call-seq:
10455  * IO.readlines(name, sep=$/ [, getline_args, open_args]) -> array
10456  * IO.readlines(name, limit [, getline_args, open_args]) -> array
10457  * IO.readlines(name, sep, limit [, getline_args, open_args]) -> array
10458  *
10459  * Reads the entire file specified by <i>name</i> as individual
10460  * lines, and returns those lines in an array. Lines are separated by
10461  * <i>sep</i>.
10462  *
10463  * a = IO.readlines("testfile")
10464  * a[0] #=> "This is line one\n"
10465  *
10466  * b = IO.readlines("testfile", chomp: true)
10467  * b[0] #=> "This is line one"
10468  *
10469  * If the last argument is a hash, it's the keyword argument to open.
10470  *
10471  * === Options for getline
10472  *
10473  * The options hash accepts the following keys:
10474  *
10475  * :chomp::
10476  * When the optional +chomp+ keyword argument has a true value,
10477  * <code>\n</code>, <code>\r</code>, and <code>\r\n</code>
10478  * will be removed from the end of each line.
10479  *
10480  * See also IO.read for details about open_args.
10481  */
10482 
10483 static VALUE
10484 rb_io_s_readlines(int argc, VALUE *argv, VALUE io)
10485 {
10486  VALUE opt;
10487  struct foreach_arg arg;
10488  struct getline_arg garg;
10489 
10490  argc = rb_scan_args(argc, argv, "13:", NULL, NULL, NULL, NULL, &opt);
10491  extract_getline_args(argc-1, argv+1, &garg);
10492  open_key_args(io, argc, argv, opt, &arg);
10493  if (NIL_P(arg.io)) return Qnil;
10494  extract_getline_opts(opt, &garg);
10495  check_getline_args(&garg.rs, &garg.limit, garg.io = arg.io);
10496  return rb_ensure(io_s_readlines, (VALUE)&garg, rb_io_close, arg.io);
10497 }
10498 
10499 static VALUE
10500 io_s_read(VALUE v)
10501 {
10502  struct foreach_arg *arg = (void *)v;
10503  return io_read(arg->argc, arg->argv, arg->io);
10504 }
10505 
10506 struct seek_arg {
10509  int mode;
10510 };
10511 
10512 static VALUE
10513 seek_before_access(VALUE argp)
10514 {
10515  struct seek_arg *arg = (struct seek_arg *)argp;
10516  rb_io_binmode(arg->io);
10517  return rb_io_seek(arg->io, arg->offset, arg->mode);
10518 }
10519 
10520 /*
10521  * call-seq:
10522  * IO.read(name, [length [, offset]] [, opt] ) -> string
10523  *
10524  * Opens the file, optionally seeks to the given +offset+, then returns
10525  * +length+ bytes (defaulting to the rest of the file). #read ensures
10526  * the file is closed before returning.
10527  *
10528  * If +name+ starts with a pipe character (<code>"|"</code>), a subprocess is
10529  * created in the same way as Kernel#open, and its output is returned.
10530  *
10531  * === Options
10532  *
10533  * The options hash accepts the following keys:
10534  *
10535  * :encoding::
10536  * string or encoding
10537  *
10538  * Specifies the encoding of the read string. +:encoding+ will be ignored
10539  * if +length+ is specified. See Encoding.aliases for possible encodings.
10540  *
10541  * :mode::
10542  * string or integer
10543  *
10544  * Specifies the <i>mode</i> argument for open(). It must start
10545  * with an "r", otherwise it will cause an error.
10546  * See IO.new for the list of possible modes.
10547  *
10548  * :open_args::
10549  * array
10550  *
10551  * Specifies arguments for open() as an array. This key can not be used
10552  * in combination with either +:encoding+ or +:mode+.
10553  *
10554  * Examples:
10555  *
10556  * IO.read("testfile") #=> "This is line one\nThis is line two\nThis is line three\nAnd so on...\n"
10557  * IO.read("testfile", 20) #=> "This is line one\nThi"
10558  * IO.read("testfile", 20, 10) #=> "ne one\nThis is line "
10559  * IO.read("binfile", mode: "rb") #=> "\xF7\x00\x00\x0E\x12"
10560  */
10561 
10562 static VALUE
10563 rb_io_s_read(int argc, VALUE *argv, VALUE io)
10564 {
10565  VALUE opt, offset;
10566  struct foreach_arg arg;
10567 
10568  argc = rb_scan_args(argc, argv, "13:", NULL, NULL, &offset, NULL, &opt);
10569  open_key_args(io, argc, argv, opt, &arg);
10570  if (NIL_P(arg.io)) return Qnil;
10571  if (!NIL_P(offset)) {
10572  struct seek_arg sarg;
10573  int state = 0;
10574  sarg.io = arg.io;
10575  sarg.offset = offset;
10576  sarg.mode = SEEK_SET;
10577  rb_protect(seek_before_access, (VALUE)&sarg, &state);
10578  if (state) {
10579  rb_io_close(arg.io);
10580  rb_jump_tag(state);
10581  }
10582  if (arg.argc == 2) arg.argc = 1;
10583  }
10584  return rb_ensure(io_s_read, (VALUE)&arg, rb_io_close, arg.io);
10585 }
10586 
10587 /*
10588  * call-seq:
10589  * IO.binread(name, [length [, offset]] ) -> string
10590  *
10591  * Opens the file, optionally seeks to the given <i>offset</i>, then
10592  * returns <i>length</i> bytes (defaulting to the rest of the file).
10593  * #binread ensures the file is closed before returning. The open mode
10594  * would be <code>"rb:ASCII-8BIT"</code>.
10595  *
10596  * IO.binread("testfile") #=> "This is line one\nThis is line two\nThis is line three\nAnd so on...\n"
10597  * IO.binread("testfile", 20) #=> "This is line one\nThi"
10598  * IO.binread("testfile", 20, 10) #=> "ne one\nThis is line "
10599  */
10600 
10601 static VALUE
10602 rb_io_s_binread(int argc, VALUE *argv, VALUE io)
10603 {
10604  VALUE offset;
10605  struct foreach_arg arg;
10606  enum {
10608  oflags = O_RDONLY
10609 #ifdef O_BINARY
10610  |O_BINARY
10611 #endif
10612  };
10613  convconfig_t convconfig = {NULL, NULL, 0, Qnil};
10614 
10615  rb_scan_args(argc, argv, "12", NULL, NULL, &offset);
10616  FilePathValue(argv[0]);
10617  convconfig.enc = rb_ascii8bit_encoding();
10618  arg.io = rb_io_open_generic(io, argv[0], oflags, fmode, &convconfig, 0);
10619  if (NIL_P(arg.io)) return Qnil;
10620  arg.argv = argv+1;
10621  arg.argc = (argc > 1) ? 1 : 0;
10622  if (!NIL_P(offset)) {
10623  struct seek_arg sarg;
10624  int state = 0;
10625  sarg.io = arg.io;
10626  sarg.offset = offset;
10627  sarg.mode = SEEK_SET;
10628  rb_protect(seek_before_access, (VALUE)&sarg, &state);
10629  if (state) {
10630  rb_io_close(arg.io);
10631  rb_jump_tag(state);
10632  }
10633  }
10634  return rb_ensure(io_s_read, (VALUE)&arg, rb_io_close, arg.io);
10635 }
10636 
10637 static VALUE
10638 io_s_write0(VALUE v)
10639 {
10640  struct write_arg *arg = (void * )v;
10641  return io_write(arg->io,arg->str,arg->nosync);
10642 }
10643 
10644 static VALUE
10645 io_s_write(int argc, VALUE *argv, VALUE klass, int binary)
10646 {
10647  VALUE string, offset, opt;
10648  struct foreach_arg arg;
10649  struct write_arg warg;
10650 
10651  rb_scan_args(argc, argv, "21:", NULL, &string, &offset, &opt);
10652 
10653  if (NIL_P(opt)) opt = rb_hash_new();
10654  else opt = rb_hash_dup(opt);
10655 
10656 
10657  if (NIL_P(rb_hash_aref(opt,sym_mode))) {
10658  int mode = O_WRONLY|O_CREAT;
10659 #ifdef O_BINARY
10660  if (binary) mode |= O_BINARY;
10661 #endif
10662  if (NIL_P(offset)) mode |= O_TRUNC;
10663  rb_hash_aset(opt,sym_mode,INT2NUM(mode));
10664  }
10665  open_key_args(klass, argc, argv, opt, &arg);
10666 
10667 #ifndef O_BINARY
10668  if (binary) rb_io_binmode_m(arg.io);
10669 #endif
10670 
10671  if (NIL_P(arg.io)) return Qnil;
10672  if (!NIL_P(offset)) {
10673  struct seek_arg sarg;
10674  int state = 0;
10675  sarg.io = arg.io;
10676  sarg.offset = offset;
10677  sarg.mode = SEEK_SET;
10678  rb_protect(seek_before_access, (VALUE)&sarg, &state);
10679  if (state) {
10680  rb_io_close(arg.io);
10681  rb_jump_tag(state);
10682  }
10683  }
10684 
10685  warg.io = arg.io;
10686  warg.str = string;
10687  warg.nosync = 0;
10688 
10689  return rb_ensure(io_s_write0, (VALUE)&warg, rb_io_close, arg.io);
10690 }
10691 
10692 /*
10693  * call-seq:
10694  * IO.write(name, string [, offset]) -> integer
10695  * IO.write(name, string [, offset] [, opt]) -> integer
10696  *
10697  * Opens the file, optionally seeks to the given <i>offset</i>, writes
10698  * <i>string</i>, then returns the length written. #write ensures the
10699  * file is closed before returning. If <i>offset</i> is not given in
10700  * write mode, the file is truncated. Otherwise, it is not truncated.
10701  *
10702  * IO.write("testfile", "0123456789", 20) #=> 10
10703  * # File could contain: "This is line one\nThi0123456789two\nThis is line three\nAnd so on...\n"
10704  * IO.write("testfile", "0123456789") #=> 10
10705  * # File would now read: "0123456789"
10706  *
10707  * If the last argument is a hash, it specifies options for the internal
10708  * open(). It accepts the following keys:
10709  *
10710  * :encoding::
10711  * string or encoding
10712  *
10713  * Specifies the encoding of the read string.
10714  * See Encoding.aliases for possible encodings.
10715  *
10716  * :mode::
10717  * string or integer
10718  *
10719  * Specifies the <i>mode</i> argument for open(). It must start
10720  * with "w", "a", or "r+", otherwise it will cause an error.
10721  * See IO.new for the list of possible modes.
10722  *
10723  * :perm::
10724  * integer
10725  *
10726  * Specifies the <i>perm</i> argument for open().
10727  *
10728  * :open_args::
10729  * array
10730  *
10731  * Specifies arguments for open() as an array.
10732  * This key can not be used in combination with other keys.
10733  */
10734 
10735 static VALUE
10736 rb_io_s_write(int argc, VALUE *argv, VALUE io)
10737 {
10738  return io_s_write(argc, argv, io, 0);
10739 }
10740 
10741 /*
10742  * call-seq:
10743  * IO.binwrite(name, string, [offset] ) -> integer
10744  * IO.binwrite(name, string, [offset], open_args ) -> integer
10745  *
10746  * Same as IO.write except opening the file in binary mode and
10747  * ASCII-8BIT encoding (<code>"wb:ASCII-8BIT"</code>).
10748  */
10749 
10750 static VALUE
10751 rb_io_s_binwrite(int argc, VALUE *argv, VALUE io)
10752 {
10753  return io_s_write(argc, argv, io, 1);
10754 }
10755 
10759  off_t copy_length; /* (off_t)-1 if not specified */
10760  off_t src_offset; /* (off_t)-1 if not specified */
10761 
10762  int src_fd;
10763  int dst_fd;
10764  unsigned close_src : 1;
10765  unsigned close_dst : 1;
10768  const char *syserr;
10769  const char *notimp;
10771  struct stat src_stat;
10772  struct stat dst_stat;
10773 #ifdef HAVE_FCOPYFILE
10774  copyfile_state_t copyfile_state;
10775 #endif
10776 };
10777 
10778 static void *
10779 exec_interrupts(void *arg)
10780 {
10781  VALUE th = (VALUE)arg;
10783  return NULL;
10784 }
10785 
10786 /*
10787  * returns TRUE if the preceding system call was interrupted
10788  * so we can continue. If the thread was interrupted, we
10789  * reacquire the GVL to execute interrupts before continuing.
10790  */
10791 static int
10792 maygvl_copy_stream_continue_p(int has_gvl, struct copy_stream_struct *stp)
10793 {
10794  switch (errno) {
10795  case EINTR:
10796 #if defined(ERESTART)
10797  case ERESTART:
10798 #endif
10799  if (rb_thread_interrupted(stp->th)) {
10800  if (has_gvl)
10802  else
10803  rb_thread_call_with_gvl(exec_interrupts, (void *)stp->th);
10804  }
10805  return TRUE;
10806  }
10807  return FALSE;
10808 }
10809 
10810 #if USE_POLL
10811 # define IOWAIT_SYSCALL "poll"
10812 STATIC_ASSERT(pollin_expected, POLLIN == RB_WAITFD_IN);
10813 STATIC_ASSERT(pollout_expected, POLLOUT == RB_WAITFD_OUT);
10814 static int
10815 nogvl_wait_for_single_fd(int fd, short events)
10816 {
10817  struct pollfd fds;
10818 
10819  fds.fd = fd;
10820  fds.events = events;
10821 
10822  return poll(&fds, 1, -1);
10823 }
10824 #else /* !USE_POLL */
10825 # define IOWAIT_SYSCALL "select"
10826 static int
10827 nogvl_wait_for_single_fd(int fd, short events)
10828 {
10829  rb_fdset_t fds;
10830  int ret;
10831 
10832  rb_fd_init(&fds);
10833  rb_fd_set(fd, &fds);
10834 
10835  switch (events) {
10836  case RB_WAITFD_IN:
10837  ret = rb_fd_select(fd + 1, &fds, 0, 0, 0);
10838  break;
10839  case RB_WAITFD_OUT:
10840  ret = rb_fd_select(fd + 1, 0, &fds, 0, 0);
10841  break;
10842  default:
10843  VM_UNREACHABLE(nogvl_wait_for_single_fd);
10844  }
10845 
10846  rb_fd_term(&fds);
10847  return ret;
10848 }
10849 #endif /* !USE_POLL */
10850 
10851 static int
10852 maygvl_copy_stream_wait_read(int has_gvl, struct copy_stream_struct *stp)
10853 {
10854  int ret;
10855 
10856  do {
10857  if (has_gvl) {
10859  }
10860  else {
10861  ret = nogvl_wait_for_single_fd(stp->src_fd, RB_WAITFD_IN);
10862  }
10863  } while (ret < 0 && maygvl_copy_stream_continue_p(has_gvl, stp));
10864 
10865  if (ret < 0) {
10866  stp->syserr = IOWAIT_SYSCALL;
10867  stp->error_no = errno;
10868  return ret;
10869  }
10870  return 0;
10871 }
10872 
10873 static int
10874 nogvl_copy_stream_wait_write(struct copy_stream_struct *stp)
10875 {
10876  int ret;
10877 
10878  do {
10879  ret = nogvl_wait_for_single_fd(stp->dst_fd, RB_WAITFD_OUT);
10880  } while (ret < 0 && maygvl_copy_stream_continue_p(0, stp));
10881 
10882  if (ret < 0) {
10883  stp->syserr = IOWAIT_SYSCALL;
10884  stp->error_no = errno;
10885  return ret;
10886  }
10887  return 0;
10888 }
10889 
10890 #if defined HAVE_COPY_FILE_RANGE || (defined __linux__ && defined __NR_copy_file_range)
10891 # define USE_COPY_FILE_RANGE
10892 #endif
10893 
10894 #ifdef USE_COPY_FILE_RANGE
10895 
10896 static ssize_t
10897 simple_copy_file_range(int in_fd, off_t *in_offset, int out_fd, off_t *out_offset, size_t count, unsigned int flags)
10898 {
10899 #ifdef HAVE_COPY_FILE_RANGE
10900  return copy_file_range(in_fd, in_offset, out_fd, out_offset, count, flags);
10901 #else
10902  return syscall(__NR_copy_file_range, in_fd, in_offset, out_fd, out_offset, count, flags);
10903 #endif
10904 }
10905 
10906 static int
10907 nogvl_copy_file_range(struct copy_stream_struct *stp)
10908 {
10909  ssize_t ss;
10910  off_t src_size;
10911  off_t copy_length, src_offset, *src_offset_ptr;
10912 
10913  if (!S_ISREG(stp->src_stat.st_mode))
10914  return 0;
10915 
10916  src_size = stp->src_stat.st_size;
10917  src_offset = stp->src_offset;
10918  if (src_offset >= (off_t)0) {
10919  src_offset_ptr = &src_offset;
10920  }
10921  else {
10922  src_offset_ptr = NULL; /* if src_offset_ptr is NULL, then bytes are read from in_fd starting from the file offset */
10923  }
10924 
10925  copy_length = stp->copy_length;
10926  if (copy_length < (off_t)0) {
10927  if (src_offset < (off_t)0) {
10928  off_t current_offset;
10929  errno = 0;
10930  current_offset = lseek(stp->src_fd, 0, SEEK_CUR);
10931  if (current_offset < (off_t)0 && errno) {
10932  stp->syserr = "lseek";
10933  stp->error_no = errno;
10934  return (int)current_offset;
10935  }
10936  copy_length = src_size - current_offset;
10937  }
10938  else {
10939  copy_length = src_size - src_offset;
10940  }
10941  }
10942 
10943  retry_copy_file_range:
10944 # if SIZEOF_OFF_T > SIZEOF_SIZE_T
10945  /* we are limited by the 32-bit ssize_t return value on 32-bit */
10946  ss = (copy_length > (off_t)SSIZE_MAX) ? SSIZE_MAX : (ssize_t)copy_length;
10947 # else
10948  ss = (ssize_t)copy_length;
10949 # endif
10950  ss = simple_copy_file_range(stp->src_fd, src_offset_ptr, stp->dst_fd, NULL, ss, 0);
10951  if (0 < ss) {
10952  stp->total += ss;
10953  copy_length -= ss;
10954  if (0 < copy_length) {
10955  goto retry_copy_file_range;
10956  }
10957  }
10958  if (ss < 0) {
10959  if (maygvl_copy_stream_continue_p(0, stp)) {
10960  goto retry_copy_file_range;
10961  }
10962  switch (errno) {
10963  case EINVAL:
10964  case EPERM: /* copy_file_range(2) doesn't exist (may happen in
10965  docker container) */
10966 #ifdef ENOSYS
10967  case ENOSYS:
10968 #endif
10969 #ifdef EXDEV
10970  case EXDEV: /* in_fd and out_fd are not on the same filesystem */
10971 #endif
10972  return 0;
10973  case EAGAIN:
10974 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
10975  case EWOULDBLOCK:
10976 #endif
10977  {
10978  int ret = nogvl_copy_stream_wait_write(stp);
10979  if (ret < 0) return ret;
10980  }
10981  goto retry_copy_file_range;
10982  case EBADF:
10983  {
10984  int e = errno;
10985  int flags = fcntl(stp->dst_fd, F_GETFL);
10986 
10987  if (flags != -1 && flags & O_APPEND) {
10988  return 0;
10989  }
10990  errno = e;
10991  }
10992  }
10993  stp->syserr = "copy_file_range";
10994  stp->error_no = errno;
10995  return (int)ss;
10996  }
10997  return 1;
10998 }
10999 #endif
11000 
11001 #ifdef HAVE_FCOPYFILE
11002 static int
11003 nogvl_fcopyfile(struct copy_stream_struct *stp)
11004 {
11005  off_t cur, ss = 0;
11006  const off_t src_offset = stp->src_offset;
11007  int ret;
11008 
11009  if (stp->copy_length >= (off_t)0) {
11010  /* copy_length can't be specified in fcopyfile(3) */
11011  return 0;
11012  }
11013 
11014  if (!S_ISREG(stp->src_stat.st_mode))
11015  return 0;
11016 
11017  if (!S_ISREG(stp->dst_stat.st_mode))
11018  return 0;
11019  if (lseek(stp->dst_fd, 0, SEEK_CUR) > (off_t)0) /* if dst IO was already written */
11020  return 0;
11021 
11022  if (src_offset > (off_t)0) {
11023  off_t r;
11024 
11025  /* get current offset */
11026  errno = 0;
11027  cur = lseek(stp->src_fd, 0, SEEK_CUR);
11028  if (cur < (off_t)0 && errno) {
11029  stp->error_no = errno;
11030  return 1;
11031  }
11032 
11033  errno = 0;
11034  r = lseek(stp->src_fd, src_offset, SEEK_SET);
11035  if (r < (off_t)0 && errno) {
11036  stp->error_no = errno;
11037  return 1;
11038  }
11039  }
11040 
11041  stp->copyfile_state = copyfile_state_alloc(); /* this will be freed by copy_stream_finalize() */
11042  ret = fcopyfile(stp->src_fd, stp->dst_fd, stp->copyfile_state, COPYFILE_DATA);
11043  copyfile_state_get(stp->copyfile_state, COPYFILE_STATE_COPIED, &ss); /* get copied bytes */
11044 
11045  if (ret == 0) { /* success */
11046  stp->total = ss;
11047  if (src_offset > (off_t)0) {
11048  off_t r;
11049  errno = 0;
11050  /* reset offset */
11051  r = lseek(stp->src_fd, cur, SEEK_SET);
11052  if (r < (off_t)0 && errno) {
11053  stp->error_no = errno;
11054  return 1;
11055  }
11056  }
11057  }
11058  else {
11059  switch (errno) {
11060  case ENOTSUP:
11061  case EPERM:
11062  case EINVAL:
11063  return 0;
11064  }
11065  stp->syserr = "fcopyfile";
11066  stp->error_no = errno;
11067  return (int)ret;
11068  }
11069  return 1;
11070 }
11071 #endif
11072 
11073 #ifdef HAVE_SENDFILE
11074 
11075 # ifdef __linux__
11076 # define USE_SENDFILE
11077 
11078 # ifdef HAVE_SYS_SENDFILE_H
11079 # include <sys/sendfile.h>
11080 # endif
11081 
11082 static ssize_t
11083 simple_sendfile(int out_fd, int in_fd, off_t *offset, off_t count)
11084 {
11085  return sendfile(out_fd, in_fd, offset, (size_t)count);
11086 }
11087 
11088 # elif 0 /* defined(__FreeBSD__) || defined(__DragonFly__) */ || defined(__APPLE__)
11089 /* This runs on FreeBSD8.1 r30210, but sendfiles blocks its execution
11090  * without cpuset -l 0.
11091  */
11092 # define USE_SENDFILE
11093 
11094 static ssize_t
11095 simple_sendfile(int out_fd, int in_fd, off_t *offset, off_t count)
11096 {
11097  int r;
11098  off_t pos = offset ? *offset : lseek(in_fd, 0, SEEK_CUR);
11099  off_t sbytes;
11100 # ifdef __APPLE__
11101  r = sendfile(in_fd, out_fd, pos, &count, NULL, 0);
11102  sbytes = count;
11103 # else
11104  r = sendfile(in_fd, out_fd, pos, (size_t)count, NULL, &sbytes, 0);
11105 # endif
11106  if (r != 0 && sbytes == 0) return r;
11107  if (offset) {
11108  *offset += sbytes;
11109  }
11110  else {
11111  lseek(in_fd, sbytes, SEEK_CUR);
11112  }
11113  return (ssize_t)sbytes;
11114 }
11115 
11116 # endif
11117 
11118 #endif
11119 
11120 #ifdef USE_SENDFILE
11121 static int
11122 nogvl_copy_stream_sendfile(struct copy_stream_struct *stp)
11123 {
11124  ssize_t ss;
11125  off_t src_size;
11126  off_t copy_length;
11127  off_t src_offset;
11128  int use_pread;
11129 
11130  if (!S_ISREG(stp->src_stat.st_mode))
11131  return 0;
11132 
11133  src_size = stp->src_stat.st_size;
11134 #ifndef __linux__
11135  if ((stp->dst_stat.st_mode & S_IFMT) != S_IFSOCK)
11136  return 0;
11137 #endif
11138 
11139  src_offset = stp->src_offset;
11140  use_pread = src_offset >= (off_t)0;
11141 
11142  copy_length = stp->copy_length;
11143  if (copy_length < (off_t)0) {
11144  if (use_pread)
11145  copy_length = src_size - src_offset;
11146  else {
11147  off_t cur;
11148  errno = 0;
11149  cur = lseek(stp->src_fd, 0, SEEK_CUR);
11150  if (cur < (off_t)0 && errno) {
11151  stp->syserr = "lseek";
11152  stp->error_no = errno;
11153  return (int)cur;
11154  }
11155  copy_length = src_size - cur;
11156  }
11157  }
11158 
11159  retry_sendfile:
11160 # if SIZEOF_OFF_T > SIZEOF_SIZE_T
11161  /* we are limited by the 32-bit ssize_t return value on 32-bit */
11162  ss = (copy_length > (off_t)SSIZE_MAX) ? SSIZE_MAX : (ssize_t)copy_length;
11163 # else
11164  ss = (ssize_t)copy_length;
11165 # endif
11166  if (use_pread) {
11167  ss = simple_sendfile(stp->dst_fd, stp->src_fd, &src_offset, ss);
11168  }
11169  else {
11170  ss = simple_sendfile(stp->dst_fd, stp->src_fd, NULL, ss);
11171  }
11172  if (0 < ss) {
11173  stp->total += ss;
11174  copy_length -= ss;
11175  if (0 < copy_length) {
11176  goto retry_sendfile;
11177  }
11178  }
11179  if (ss < 0) {
11180  if (maygvl_copy_stream_continue_p(0, stp))
11181  goto retry_sendfile;
11182  switch (errno) {
11183  case EINVAL:
11184 #ifdef ENOSYS
11185  case ENOSYS:
11186 #endif
11187  return 0;
11188  case EAGAIN:
11189 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
11190  case EWOULDBLOCK:
11191 #endif
11192  {
11193  int ret;
11194 #ifndef __linux__
11195  /*
11196  * Linux requires stp->src_fd to be a mmap-able (regular) file,
11197  * select() reports regular files to always be "ready", so
11198  * there is no need to select() on it.
11199  * Other OSes may have the same limitation for sendfile() which
11200  * allow us to bypass maygvl_copy_stream_wait_read()...
11201  */
11202  ret = maygvl_copy_stream_wait_read(0, stp);
11203  if (ret < 0) return ret;
11204 #endif
11205  ret = nogvl_copy_stream_wait_write(stp);
11206  if (ret < 0) return ret;
11207  }
11208  goto retry_sendfile;
11209  }
11210  stp->syserr = "sendfile";
11211  stp->error_no = errno;
11212  return (int)ss;
11213  }
11214  return 1;
11215 }
11216 #endif
11217 
11218 static ssize_t
11219 maygvl_read(int has_gvl, int fd, void *buf, size_t count)
11220 {
11221  if (has_gvl)
11222  return rb_read_internal(fd, buf, count);
11223  else
11224  return read(fd, buf, count);
11225 }
11226 
11227 static ssize_t
11228 maygvl_copy_stream_read(int has_gvl, struct copy_stream_struct *stp, char *buf, size_t len, off_t offset)
11229 {
11230  ssize_t ss;
11231  retry_read:
11232  if (offset < (off_t)0) {
11233  ss = maygvl_read(has_gvl, stp->src_fd, buf, len);
11234  }
11235  else {
11236 #ifdef HAVE_PREAD
11237  ss = pread(stp->src_fd, buf, len, offset);
11238 #else
11239  stp->notimp = "pread";
11240  return -1;
11241 #endif
11242  }
11243  if (ss == 0) {
11244  return 0;
11245  }
11246  if (ss < 0) {
11247  if (maygvl_copy_stream_continue_p(has_gvl, stp))
11248  goto retry_read;
11249  switch (errno) {
11250  case EAGAIN:
11251 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
11252  case EWOULDBLOCK:
11253 #endif
11254  {
11255  int ret = maygvl_copy_stream_wait_read(has_gvl, stp);
11256  if (ret < 0) return ret;
11257  }
11258  goto retry_read;
11259 #ifdef ENOSYS
11260  case ENOSYS:
11261  stp->notimp = "pread";
11262  return ss;
11263 #endif
11264  }
11265  stp->syserr = offset < (off_t)0 ? "read" : "pread";
11266  stp->error_no = errno;
11267  }
11268  return ss;
11269 }
11270 
11271 static int
11272 nogvl_copy_stream_write(struct copy_stream_struct *stp, char *buf, size_t len)
11273 {
11274  ssize_t ss;
11275  int off = 0;
11276  while (len) {
11277  ss = write(stp->dst_fd, buf+off, len);
11278  if (ss < 0) {
11279  if (maygvl_copy_stream_continue_p(0, stp))
11280  continue;
11281  if (errno == EAGAIN || errno == EWOULDBLOCK) {
11282  int ret = nogvl_copy_stream_wait_write(stp);
11283  if (ret < 0) return ret;
11284  continue;
11285  }
11286  stp->syserr = "write";
11287  stp->error_no = errno;
11288  return (int)ss;
11289  }
11290  off += (int)ss;
11291  len -= (int)ss;
11292  stp->total += ss;
11293  }
11294  return 0;
11295 }
11296 
11297 static void
11298 nogvl_copy_stream_read_write(struct copy_stream_struct *stp)
11299 {
11300  char buf[1024*16];
11301  size_t len;
11302  ssize_t ss;
11303  int ret;
11304  off_t copy_length;
11305  int use_eof;
11306  off_t src_offset;
11307  int use_pread;
11308 
11309  copy_length = stp->copy_length;
11310  use_eof = copy_length < (off_t)0;
11311  src_offset = stp->src_offset;
11312  use_pread = src_offset >= (off_t)0;
11313 
11314  if (use_pread && stp->close_src) {
11315  off_t r;
11316  errno = 0;
11317  r = lseek(stp->src_fd, src_offset, SEEK_SET);
11318  if (r < (off_t)0 && errno) {
11319  stp->syserr = "lseek";
11320  stp->error_no = errno;
11321  return;
11322  }
11323  src_offset = (off_t)-1;
11324  use_pread = 0;
11325  }
11326 
11327  while (use_eof || 0 < copy_length) {
11328  if (!use_eof && copy_length < (off_t)sizeof(buf)) {
11329  len = (size_t)copy_length;
11330  }
11331  else {
11332  len = sizeof(buf);
11333  }
11334  if (use_pread) {
11335  ss = maygvl_copy_stream_read(0, stp, buf, len, src_offset);
11336  if (0 < ss)
11337  src_offset += ss;
11338  }
11339  else {
11340  ss = maygvl_copy_stream_read(0, stp, buf, len, (off_t)-1);
11341  }
11342  if (ss <= 0) /* EOF or error */
11343  return;
11344 
11345  ret = nogvl_copy_stream_write(stp, buf, ss);
11346  if (ret < 0)
11347  return;
11348 
11349  if (!use_eof)
11350  copy_length -= ss;
11351  }
11352 }
11353 
11354 static void *
11355 nogvl_copy_stream_func(void *arg)
11356 {
11357  struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
11358 #if defined(USE_SENDFILE) || defined(USE_COPY_FILE_RANGE) || defined(HAVE_FCOPYFILE)
11359  int ret;
11360 #endif
11361 
11362 #ifdef USE_COPY_FILE_RANGE
11363  ret = nogvl_copy_file_range(stp);
11364  if (ret != 0)
11365  goto finish; /* error or success */
11366 #endif
11367 
11368 #ifdef HAVE_FCOPYFILE
11369  ret = nogvl_fcopyfile(stp);
11370  if (ret != 0)
11371  goto finish; /* error or success */
11372 #endif
11373 
11374 #ifdef USE_SENDFILE
11375  ret = nogvl_copy_stream_sendfile(stp);
11376  if (ret != 0)
11377  goto finish; /* error or success */
11378 #endif
11379 
11380  nogvl_copy_stream_read_write(stp);
11381 
11382 #if defined(USE_SENDFILE) || defined(USE_COPY_FILE_RANGE) || defined(HAVE_FCOPYFILE)
11383  finish:
11384 #endif
11385  return 0;
11386 }
11387 
11388 static VALUE
11389 copy_stream_fallback_body(VALUE arg)
11390 {
11391  struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
11392  const int buflen = 16*1024;
11393  VALUE n;
11394  VALUE buf = rb_str_buf_new(buflen);
11395  off_t rest = stp->copy_length;
11396  off_t off = stp->src_offset;
11397  ID read_method = id_readpartial;
11398 
11399  if (stp->src_fd < 0) {
11400  if (!rb_respond_to(stp->src, read_method)) {
11401  read_method = id_read;
11402  }
11403  }
11404 
11405  while (1) {
11406  long numwrote;
11407  long l;
11408  if (stp->copy_length < (off_t)0) {
11409  l = buflen;
11410  }
11411  else {
11412  if (rest == 0) {
11413  rb_str_resize(buf, 0);
11414  break;
11415  }
11416  l = buflen < rest ? buflen : (long)rest;
11417  }
11418  if (stp->src_fd < 0) {
11419  VALUE rc = rb_funcall(stp->src, read_method, 2, INT2FIX(l), buf);
11420 
11421  if (read_method == id_read && NIL_P(rc))
11422  break;
11423  }
11424  else {
11425  ssize_t ss;
11426  rb_str_resize(buf, buflen);
11427  ss = maygvl_copy_stream_read(1, stp, RSTRING_PTR(buf), l, off);
11428  rb_str_resize(buf, ss > 0 ? ss : 0);
11429  if (ss < 0)
11430  return Qnil;
11431  if (ss == 0)
11432  rb_eof_error();
11433  if (off >= (off_t)0)
11434  off += ss;
11435  }
11436  n = rb_io_write(stp->dst, buf);
11437  numwrote = NUM2LONG(n);
11438  stp->total += numwrote;
11439  rest -= numwrote;
11440  if (read_method == id_read && RSTRING_LEN(buf) == 0) {
11441  break;
11442  }
11443  }
11444 
11445  return Qnil;
11446 }
11447 
11448 static VALUE
11449 copy_stream_fallback(struct copy_stream_struct *stp)
11450 {
11451  if (stp->src_fd < 0 && stp->src_offset >= (off_t)0) {
11452  rb_raise(rb_eArgError, "cannot specify src_offset for non-IO");
11453  }
11454  rb_rescue2(copy_stream_fallback_body, (VALUE)stp,
11455  (VALUE (*) (VALUE, VALUE))0, (VALUE)0,
11456  rb_eEOFError, (VALUE)0);
11457  return Qnil;
11458 }
11459 
11460 static VALUE
11461 copy_stream_body(VALUE arg)
11462 {
11463  struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
11464  VALUE src_io = stp->src, dst_io = stp->dst;
11465  rb_io_t *src_fptr = 0, *dst_fptr = 0;
11466  int src_fd, dst_fd;
11467  const int common_oflags = 0
11468 #ifdef O_NOCTTY
11469  | O_NOCTTY
11470 #endif
11471  ;
11472 
11473  stp->th = rb_thread_current();
11474 
11475  stp->total = 0;
11476 
11477  if (src_io == argf ||
11478  !(RB_TYPE_P(src_io, T_FILE) ||
11479  RB_TYPE_P(src_io, T_STRING) ||
11480  rb_respond_to(src_io, rb_intern("to_path")))) {
11481  src_fd = -1;
11482  }
11483  else {
11484  int stat_ret;
11485  VALUE tmp_io = rb_io_check_io(src_io);
11486  if (!NIL_P(tmp_io)) {
11487  src_io = tmp_io;
11488  }
11489  else if (!RB_TYPE_P(src_io, T_FILE)) {
11490  VALUE args[2];
11491  FilePathValue(src_io);
11492  args[0] = src_io;
11493  args[1] = INT2NUM(O_RDONLY|common_oflags);
11494  src_io = rb_class_new_instance(2, args, rb_cFile);
11495  stp->src = src_io;
11496  stp->close_src = 1;
11497  }
11498  GetOpenFile(src_io, src_fptr);
11499  rb_io_check_byte_readable(src_fptr);
11500  src_fd = src_fptr->fd;
11501 
11502  stat_ret = fstat(src_fd, &stp->src_stat);
11503  if (stat_ret < 0) {
11504  stp->syserr = "fstat";
11505  stp->error_no = errno;
11506  return Qnil;
11507  }
11508  }
11509  stp->src_fd = src_fd;
11510 
11511  if (dst_io == argf ||
11512  !(RB_TYPE_P(dst_io, T_FILE) ||
11513  RB_TYPE_P(dst_io, T_STRING) ||
11514  rb_respond_to(dst_io, rb_intern("to_path")))) {
11515  dst_fd = -1;
11516  }
11517  else {
11518  int stat_ret;
11519  VALUE tmp_io = rb_io_check_io(dst_io);
11520  if (!NIL_P(tmp_io)) {
11521  dst_io = GetWriteIO(tmp_io);
11522  }
11523  else if (!RB_TYPE_P(dst_io, T_FILE)) {
11524  VALUE args[3];
11525  FilePathValue(dst_io);
11526  args[0] = dst_io;
11527  args[1] = INT2NUM(O_WRONLY|O_CREAT|O_TRUNC|common_oflags);
11528  args[2] = INT2FIX(0666);
11529  dst_io = rb_class_new_instance(3, args, rb_cFile);
11530  stp->dst = dst_io;
11531  stp->close_dst = 1;
11532  }
11533  else {
11534  dst_io = GetWriteIO(dst_io);
11535  stp->dst = dst_io;
11536  }
11537  GetOpenFile(dst_io, dst_fptr);
11538  rb_io_check_writable(dst_fptr);
11539  dst_fd = dst_fptr->fd;
11540 
11541  stat_ret = fstat(dst_fd, &stp->dst_stat);
11542  if (stat_ret < 0) {
11543  stp->syserr = "fstat";
11544  stp->error_no = errno;
11545  return Qnil;
11546  }
11547  }
11548  stp->dst_fd = dst_fd;
11549 
11550 #ifdef O_BINARY
11551  if (src_fptr)
11553 #endif
11554  if (dst_fptr)
11555  io_ascii8bit_binmode(dst_fptr);
11556 
11557  if (stp->src_offset < (off_t)0 && src_fptr && src_fptr->rbuf.len) {
11558  size_t len = src_fptr->rbuf.len;
11559  VALUE str;
11560  if (stp->copy_length >= (off_t)0 && stp->copy_length < (off_t)len) {
11561  len = (size_t)stp->copy_length;
11562  }
11563  str = rb_str_buf_new(len);
11565  read_buffered_data(RSTRING_PTR(str), len, src_fptr);
11566  if (dst_fptr) { /* IO or filename */
11567  if (io_binwrite(str, RSTRING_PTR(str), RSTRING_LEN(str), dst_fptr, 0) < 0)
11568  rb_sys_fail(0);
11569  }
11570  else /* others such as StringIO */
11571  rb_io_write(dst_io, str);
11572  rb_str_resize(str, 0);
11573  stp->total += len;
11574  if (stp->copy_length >= (off_t)0)
11575  stp->copy_length -= len;
11576  }
11577 
11578  if (dst_fptr && io_fflush(dst_fptr) < 0) {
11579  rb_raise(rb_eIOError, "flush failed");
11580  }
11581 
11582  if (stp->copy_length == 0)
11583  return Qnil;
11584 
11585  if (src_fd < 0 || dst_fd < 0) {
11586  return copy_stream_fallback(stp);
11587  }
11588 
11589  rb_thread_call_without_gvl(nogvl_copy_stream_func, (void*)stp, RUBY_UBF_IO, 0);
11590  return Qnil;
11591 }
11592 
11593 static VALUE
11594 copy_stream_finalize(VALUE arg)
11595 {
11596  struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
11597 
11598 #ifdef HAVE_FCOPYFILE
11599  if (stp->copyfile_state) {
11600  copyfile_state_free(stp->copyfile_state);
11601  }
11602 #endif
11603 
11604  if (stp->close_src) {
11605  rb_io_close_m(stp->src);
11606  }
11607  if (stp->close_dst) {
11608  rb_io_close_m(stp->dst);
11609  }
11610  if (stp->syserr) {
11611  rb_syserr_fail(stp->error_no, stp->syserr);
11612  }
11613  if (stp->notimp) {
11614  rb_raise(rb_eNotImpError, "%s() not implemented", stp->notimp);
11615  }
11616  return Qnil;
11617 }
11618 
11619 /*
11620  * call-seq:
11621  * IO.copy_stream(src, dst)
11622  * IO.copy_stream(src, dst, copy_length)
11623  * IO.copy_stream(src, dst, copy_length, src_offset)
11624  *
11625  * IO.copy_stream copies <i>src</i> to <i>dst</i>.
11626  * <i>src</i> and <i>dst</i> is either a filename or an IO-like object.
11627  * IO-like object for <i>src</i> should have #readpartial or #read
11628  * method. IO-like object for <i>dst</i> should have #write method.
11629  * (Specialized mechanisms, such as sendfile system call, may be used
11630  * on appropriate situation.)
11631  *
11632  * This method returns the number of bytes copied.
11633  *
11634  * If optional arguments are not given,
11635  * the start position of the copy is
11636  * the beginning of the filename or
11637  * the current file offset of the IO.
11638  * The end position of the copy is the end of file.
11639  *
11640  * If <i>copy_length</i> is given,
11641  * No more than <i>copy_length</i> bytes are copied.
11642  *
11643  * If <i>src_offset</i> is given,
11644  * it specifies the start position of the copy.
11645  *
11646  * When <i>src_offset</i> is specified and
11647  * <i>src</i> is an IO,
11648  * IO.copy_stream doesn't move the current file offset.
11649  *
11650  */
11651 static VALUE
11652 rb_io_s_copy_stream(int argc, VALUE *argv, VALUE io)
11653 {
11654  VALUE src, dst, length, src_offset;
11655  struct copy_stream_struct st;
11656 
11657  MEMZERO(&st, struct copy_stream_struct, 1);
11658 
11659  rb_scan_args(argc, argv, "22", &src, &dst, &length, &src_offset);
11660 
11661  st.src = src;
11662  st.dst = dst;
11663 
11664  if (NIL_P(length))
11665  st.copy_length = (off_t)-1;
11666  else
11667  st.copy_length = NUM2OFFT(length);
11668 
11669  if (NIL_P(src_offset))
11670  st.src_offset = (off_t)-1;
11671  else
11672  st.src_offset = NUM2OFFT(src_offset);
11673 
11674  rb_ensure(copy_stream_body, (VALUE)&st, copy_stream_finalize, (VALUE)&st);
11675 
11676  return OFFT2NUM(st.total);
11677 }
11678 
11679 /*
11680  * call-seq:
11681  * io.external_encoding -> encoding
11682  *
11683  * Returns the Encoding object that represents the encoding of the file.
11684  * If _io_ is in write mode and no encoding is specified, returns +nil+.
11685  */
11686 
11687 static VALUE
11688 rb_io_external_encoding(VALUE io)
11689 {
11690  rb_io_t *fptr;
11691 
11692  GetOpenFile(io, fptr);
11693  if (fptr->encs.enc2) {
11694  return rb_enc_from_encoding(fptr->encs.enc2);
11695  }
11696  if (fptr->mode & FMODE_WRITABLE) {
11697  if (fptr->encs.enc)
11698  return rb_enc_from_encoding(fptr->encs.enc);
11699  return Qnil;
11700  }
11701  return rb_enc_from_encoding(io_read_encoding(fptr));
11702 }
11703 
11704 /*
11705  * call-seq:
11706  * io.internal_encoding -> encoding
11707  *
11708  * Returns the Encoding of the internal string if conversion is
11709  * specified. Otherwise returns +nil+.
11710  */
11711 
11712 static VALUE
11713 rb_io_internal_encoding(VALUE io)
11714 {
11715  rb_io_t *fptr;
11716 
11717  GetOpenFile(io, fptr);
11718  if (!fptr->encs.enc2) return Qnil;
11719  return rb_enc_from_encoding(io_read_encoding(fptr));
11720 }
11721 
11722 /*
11723  * call-seq:
11724  * io.set_encoding(ext_enc) -> io
11725  * io.set_encoding("ext_enc:int_enc") -> io
11726  * io.set_encoding(ext_enc, int_enc) -> io
11727  * io.set_encoding("ext_enc:int_enc", opt) -> io
11728  * io.set_encoding(ext_enc, int_enc, opt) -> io
11729  *
11730  * If single argument is specified, read string from io is tagged
11731  * with the encoding specified. If encoding is a colon separated two
11732  * encoding names "A:B", the read string is converted from encoding A
11733  * (external encoding) to encoding B (internal encoding), then tagged
11734  * with B. If two arguments are specified, those must be encoding
11735  * objects or encoding names, and the first one is the external encoding, and the
11736  * second one is the internal encoding.
11737  * If the external encoding and the internal encoding is specified,
11738  * optional hash argument specify the conversion option.
11739  */
11740 
11741 static VALUE
11742 rb_io_set_encoding(int argc, VALUE *argv, VALUE io)
11743 {
11744  rb_io_t *fptr;
11745  VALUE v1, v2, opt;
11746 
11747  if (!RB_TYPE_P(io, T_FILE)) {
11748  return rb_funcallv(io, id_set_encoding, argc, argv);
11749  }
11750 
11751  argc = rb_scan_args(argc, argv, "11:", &v1, &v2, &opt);
11752  GetOpenFile(io, fptr);
11753  io_encoding_set(fptr, v1, v2, opt);
11754  return io;
11755 }
11756 
11757 void
11759 {
11760  VALUE val = Qnil;
11761 
11762  rb_io_set_encoding(1, &val, rb_stdin);
11763  rb_io_set_encoding(1, &val, rb_stdout);
11764  rb_io_set_encoding(1, &val, rb_stderr);
11765 }
11766 
11767 static inline int
11768 global_argf_p(VALUE arg)
11769 {
11770  return arg == argf;
11771 }
11772 
11773 /*
11774  * call-seq:
11775  * ARGF.external_encoding -> encoding
11776  *
11777  * Returns the external encoding for files read from +ARGF+ as an +Encoding+
11778  * object. The external encoding is the encoding of the text as stored in a
11779  * file. Contrast with +ARGF.internal_encoding+, which is the encoding used
11780  * to represent this text within Ruby.
11781  *
11782  * To set the external encoding use +ARGF.set_encoding+.
11783  *
11784  * For example:
11785  *
11786  * ARGF.external_encoding #=> #<Encoding:UTF-8>
11787  *
11788  */
11789 static VALUE
11790 argf_external_encoding(VALUE argf)
11791 {
11792  if (!RTEST(ARGF.current_file)) {
11794  }
11795  return rb_io_external_encoding(rb_io_check_io(ARGF.current_file));
11796 }
11797 
11798 /*
11799  * call-seq:
11800  * ARGF.internal_encoding -> encoding
11801  *
11802  * Returns the internal encoding for strings read from +ARGF+ as an
11803  * +Encoding+ object.
11804  *
11805  * If +ARGF.set_encoding+ has been called with two encoding names, the second
11806  * is returned. Otherwise, if +Encoding.default_external+ has been set, that
11807  * value is returned. Failing that, if a default external encoding was
11808  * specified on the command-line, that value is used. If the encoding is
11809  * unknown, +nil+ is returned.
11810  */
11811 static VALUE
11812 argf_internal_encoding(VALUE argf)
11813 {
11814  if (!RTEST(ARGF.current_file)) {
11816  }
11817  return rb_io_internal_encoding(rb_io_check_io(ARGF.current_file));
11818 }
11819 
11820 /*
11821  * call-seq:
11822  * ARGF.set_encoding(ext_enc) -> ARGF
11823  * ARGF.set_encoding("ext_enc:int_enc") -> ARGF
11824  * ARGF.set_encoding(ext_enc, int_enc) -> ARGF
11825  * ARGF.set_encoding("ext_enc:int_enc", opt) -> ARGF
11826  * ARGF.set_encoding(ext_enc, int_enc, opt) -> ARGF
11827  *
11828  * If single argument is specified, strings read from ARGF are tagged with
11829  * the encoding specified.
11830  *
11831  * If two encoding names separated by a colon are given, e.g. "ascii:utf-8",
11832  * the read string is converted from the first encoding (external encoding)
11833  * to the second encoding (internal encoding), then tagged with the second
11834  * encoding.
11835  *
11836  * If two arguments are specified, they must be encoding objects or encoding
11837  * names. Again, the first specifies the external encoding; the second
11838  * specifies the internal encoding.
11839  *
11840  * If the external encoding and the internal encoding are specified, the
11841  * optional +Hash+ argument can be used to adjust the conversion process. The
11842  * structure of this hash is explained in the String#encode documentation.
11843  *
11844  * For example:
11845  *
11846  * ARGF.set_encoding('ascii') # Tag the input as US-ASCII text
11847  * ARGF.set_encoding(Encoding::UTF_8) # Tag the input as UTF-8 text
11848  * ARGF.set_encoding('utf-8','ascii') # Transcode the input from US-ASCII
11849  * # to UTF-8.
11850  */
11851 static VALUE
11852 argf_set_encoding(int argc, VALUE *argv, VALUE argf)
11853 {
11854  rb_io_t *fptr;
11855 
11856  if (!next_argv()) {
11857  rb_raise(rb_eArgError, "no stream to set encoding");
11858  }
11859  rb_io_set_encoding(argc, argv, ARGF.current_file);
11860  GetOpenFile(ARGF.current_file, fptr);
11861  ARGF.encs = fptr->encs;
11862  return argf;
11863 }
11864 
11865 /*
11866  * call-seq:
11867  * ARGF.tell -> Integer
11868  * ARGF.pos -> Integer
11869  *
11870  * Returns the current offset (in bytes) of the current file in +ARGF+.
11871  *
11872  * ARGF.pos #=> 0
11873  * ARGF.gets #=> "This is line one\n"
11874  * ARGF.pos #=> 17
11875  *
11876  */
11877 static VALUE
11878 argf_tell(VALUE argf)
11879 {
11880  if (!next_argv()) {
11881  rb_raise(rb_eArgError, "no stream to tell");
11882  }
11883  ARGF_FORWARD(0, 0);
11884  return rb_io_tell(ARGF.current_file);
11885 }
11886 
11887 /*
11888  * call-seq:
11889  * ARGF.seek(amount, whence=IO::SEEK_SET) -> 0
11890  *
11891  * Seeks to offset _amount_ (an +Integer+) in the +ARGF+ stream according to
11892  * the value of _whence_. See IO#seek for further details.
11893  */
11894 static VALUE
11895 argf_seek_m(int argc, VALUE *argv, VALUE argf)
11896 {
11897  if (!next_argv()) {
11898  rb_raise(rb_eArgError, "no stream to seek");
11899  }
11901  return rb_io_seek_m(argc, argv, ARGF.current_file);
11902 }
11903 
11904 /*
11905  * call-seq:
11906  * ARGF.pos = position -> Integer
11907  *
11908  * Seeks to the position given by _position_ (in bytes) in +ARGF+.
11909  *
11910  * For example:
11911  *
11912  * ARGF.pos = 17
11913  * ARGF.gets #=> "This is line two\n"
11914  */
11915 static VALUE
11916 argf_set_pos(VALUE argf, VALUE offset)
11917 {
11918  if (!next_argv()) {
11919  rb_raise(rb_eArgError, "no stream to set position");
11920  }
11921  ARGF_FORWARD(1, &offset);
11922  return rb_io_set_pos(ARGF.current_file, offset);
11923 }
11924 
11925 /*
11926  * call-seq:
11927  * ARGF.rewind -> 0
11928  *
11929  * Positions the current file to the beginning of input, resetting
11930  * +ARGF.lineno+ to zero.
11931  *
11932  * ARGF.readline #=> "This is line one\n"
11933  * ARGF.rewind #=> 0
11934  * ARGF.lineno #=> 0
11935  * ARGF.readline #=> "This is line one\n"
11936  */
11937 static VALUE
11938 argf_rewind(VALUE argf)
11939 {
11940  VALUE ret;
11941  int old_lineno;
11942 
11943  if (!next_argv()) {
11944  rb_raise(rb_eArgError, "no stream to rewind");
11945  }
11946  ARGF_FORWARD(0, 0);
11947  old_lineno = RFILE(ARGF.current_file)->fptr->lineno;
11948  ret = rb_io_rewind(ARGF.current_file);
11949  if (!global_argf_p(argf)) {
11950  ARGF.last_lineno = ARGF.lineno -= old_lineno;
11951  }
11952  return ret;
11953 }
11954 
11955 /*
11956  * call-seq:
11957  * ARGF.fileno -> integer
11958  * ARGF.to_i -> integer
11959  *
11960  * Returns an integer representing the numeric file descriptor for
11961  * the current file. Raises an +ArgumentError+ if there isn't a current file.
11962  *
11963  * ARGF.fileno #=> 3
11964  */
11965 static VALUE
11966 argf_fileno(VALUE argf)
11967 {
11968  if (!next_argv()) {
11969  rb_raise(rb_eArgError, "no stream");
11970  }
11971  ARGF_FORWARD(0, 0);
11972  return rb_io_fileno(ARGF.current_file);
11973 }
11974 
11975 /*
11976  * call-seq:
11977  * ARGF.to_io -> IO
11978  *
11979  * Returns an +IO+ object representing the current file. This will be a
11980  * +File+ object unless the current file is a stream such as STDIN.
11981  *
11982  * For example:
11983  *
11984  * ARGF.to_io #=> #<File:glark.txt>
11985  * ARGF.to_io #=> #<IO:<STDIN>>
11986  */
11987 static VALUE
11988 argf_to_io(VALUE argf)
11989 {
11990  next_argv();
11991  ARGF_FORWARD(0, 0);
11992  return ARGF.current_file;
11993 }
11994 
11995 /*
11996  * call-seq:
11997  * ARGF.eof? -> true or false
11998  * ARGF.eof -> true or false
11999  *
12000  * Returns true if the current file in +ARGF+ is at end of file, i.e. it has
12001  * no data to read. The stream must be opened for reading or an +IOError+
12002  * will be raised.
12003  *
12004  * $ echo "eof" | ruby argf.rb
12005  *
12006  * ARGF.eof? #=> false
12007  * 3.times { ARGF.readchar }
12008  * ARGF.eof? #=> false
12009  * ARGF.readchar #=> "\n"
12010  * ARGF.eof? #=> true
12011  */
12012 
12013 static VALUE
12014 argf_eof(VALUE argf)
12015 {
12016  next_argv();
12017  if (RTEST(ARGF.current_file)) {
12018  if (ARGF.init_p == 0) return Qtrue;
12019  next_argv();
12020  ARGF_FORWARD(0, 0);
12021  if (rb_io_eof(ARGF.current_file)) {
12022  return Qtrue;
12023  }
12024  }
12025  return Qfalse;
12026 }
12027 
12028 /*
12029  * call-seq:
12030  * ARGF.read([length [, outbuf]]) -> string, outbuf, or nil
12031  *
12032  * Reads _length_ bytes from ARGF. The files named on the command line
12033  * are concatenated and treated as a single file by this method, so when
12034  * called without arguments the contents of this pseudo file are returned in
12035  * their entirety.
12036  *
12037  * _length_ must be a non-negative integer or +nil+.
12038  *
12039  * If _length_ is a positive integer, +read+ tries to read
12040  * _length_ bytes without any conversion (binary mode).
12041  * It returns +nil+ if an EOF is encountered before anything can be read.
12042  * Fewer than _length_ bytes are returned if an EOF is encountered during
12043  * the read.
12044  * In the case of an integer _length_, the resulting string is always
12045  * in ASCII-8BIT encoding.
12046  *
12047  * If _length_ is omitted or is +nil+, it reads until EOF
12048  * and the encoding conversion is applied, if applicable.
12049  * A string is returned even if EOF is encountered before any data is read.
12050  *
12051  * If _length_ is zero, it returns an empty string (<code>""</code>).
12052  *
12053  * If the optional _outbuf_ argument is present,
12054  * it must reference a String, which will receive the data.
12055  * The _outbuf_ will contain only the received data after the method call
12056  * even if it is not empty at the beginning.
12057  *
12058  * For example:
12059  *
12060  * $ echo "small" > small.txt
12061  * $ echo "large" > large.txt
12062  * $ ./glark.rb small.txt large.txt
12063  *
12064  * ARGF.read #=> "small\nlarge"
12065  * ARGF.read(200) #=> "small\nlarge"
12066  * ARGF.read(2) #=> "sm"
12067  * ARGF.read(0) #=> ""
12068  *
12069  * Note that this method behaves like the fread() function in C.
12070  * This means it retries to invoke read(2) system calls to read data
12071  * with the specified length.
12072  * If you need the behavior like a single read(2) system call,
12073  * consider ARGF#readpartial or ARGF#read_nonblock.
12074  */
12075 
12076 static VALUE
12077 argf_read(int argc, VALUE *argv, VALUE argf)
12078 {
12079  VALUE tmp, str, length;
12080  long len = 0;
12081 
12082  rb_scan_args(argc, argv, "02", &length, &str);
12083  if (!NIL_P(length)) {
12084  len = NUM2LONG(argv[0]);
12085  }
12086  if (!NIL_P(str)) {
12087  StringValue(str);
12088  rb_str_resize(str,0);
12089  argv[1] = Qnil;
12090  }
12091 
12092  retry:
12093  if (!next_argv()) {
12094  return str;
12095  }
12096  if (ARGF_GENERIC_INPUT_P()) {
12097  tmp = argf_forward(argc, argv, argf);
12098  }
12099  else {
12100  tmp = io_read(argc, argv, ARGF.current_file);
12101  }
12102  if (NIL_P(str)) str = tmp;
12103  else if (!NIL_P(tmp)) rb_str_append(str, tmp);
12104  if (NIL_P(tmp) || NIL_P(length)) {
12105  if (ARGF.next_p != -1) {
12106  argf_close(argf);
12107  ARGF.next_p = 1;
12108  goto retry;
12109  }
12110  }
12111  else if (argc >= 1) {
12112  long slen = RSTRING_LEN(str);
12113  if (slen < len) {
12114  len -= slen;
12115  argv[0] = INT2NUM(len);
12116  goto retry;
12117  }
12118  }
12119  return str;
12120 }
12121 
12123  int argc;
12126 };
12127 
12128 static VALUE
12129 argf_forward_call(VALUE arg)
12130 {
12131  struct argf_call_arg *p = (struct argf_call_arg *)arg;
12132  argf_forward(p->argc, p->argv, p->argf);
12133  return Qnil;
12134 }
12135 
12136 static VALUE argf_getpartial(int argc, VALUE *argv, VALUE argf, VALUE opts,
12137  int nonblock);
12138 
12139 /*
12140  * call-seq:
12141  * ARGF.readpartial(maxlen) -> string
12142  * ARGF.readpartial(maxlen, outbuf) -> outbuf
12143  *
12144  * Reads at most _maxlen_ bytes from the ARGF stream.
12145  *
12146  * If the optional _outbuf_ argument is present,
12147  * it must reference a String, which will receive the data.
12148  * The _outbuf_ will contain only the received data after the method call
12149  * even if it is not empty at the beginning.
12150  *
12151  * It raises EOFError on end of ARGF stream.
12152  * Since ARGF stream is a concatenation of multiple files,
12153  * internally EOF is occur for each file.
12154  * ARGF.readpartial returns empty strings for EOFs except the last one and
12155  * raises EOFError for the last one.
12156  *
12157  */
12158 
12159 static VALUE
12160 argf_readpartial(int argc, VALUE *argv, VALUE argf)
12161 {
12162  return argf_getpartial(argc, argv, argf, Qnil, 0);
12163 }
12164 
12165 /*
12166  * call-seq:
12167  * ARGF.read_nonblock(maxlen[, options]) -> string
12168  * ARGF.read_nonblock(maxlen, outbuf[, options]) -> outbuf
12169  *
12170  * Reads at most _maxlen_ bytes from the ARGF stream in non-blocking mode.
12171  */
12172 
12173 static VALUE
12174 argf_read_nonblock(int argc, VALUE *argv, VALUE argf)
12175 {
12176  VALUE opts;
12177 
12178  rb_scan_args(argc, argv, "11:", NULL, NULL, &opts);
12179 
12180  if (!NIL_P(opts))
12181  argc--;
12182 
12183  return argf_getpartial(argc, argv, argf, opts, 1);
12184 }
12185 
12186 static VALUE
12187 argf_getpartial(int argc, VALUE *argv, VALUE argf, VALUE opts, int nonblock)
12188 {
12189  VALUE tmp, str, length;
12190  int no_exception;
12191 
12192  rb_scan_args(argc, argv, "11", &length, &str);
12193  if (!NIL_P(str)) {
12194  StringValue(str);
12195  argv[1] = str;
12196  }
12197  no_exception = no_exception_p(opts);
12198 
12199  if (!next_argv()) {
12200  if (!NIL_P(str)) {
12201  rb_str_resize(str, 0);
12202  }
12203  rb_eof_error();
12204  }
12205  if (ARGF_GENERIC_INPUT_P()) {
12206  VALUE (*const rescue_does_nothing)(VALUE, VALUE) = 0;
12207  struct argf_call_arg arg;
12208  arg.argc = argc;
12209  arg.argv = argv;
12210  arg.argf = argf;
12211  tmp = rb_rescue2(argf_forward_call, (VALUE)&arg,
12212  rescue_does_nothing, Qnil, rb_eEOFError, (VALUE)0);
12213  }
12214  else {
12215  tmp = io_getpartial(argc, argv, ARGF.current_file, no_exception, nonblock);
12216  }
12217  if (NIL_P(tmp)) {
12218  if (ARGF.next_p == -1) {
12219  return io_nonblock_eof(no_exception);
12220  }
12221  argf_close(argf);
12222  ARGF.next_p = 1;
12223  if (RARRAY_LEN(ARGF.argv) == 0) {
12224  return io_nonblock_eof(no_exception);
12225  }
12226  if (NIL_P(str))
12227  str = rb_str_new(NULL, 0);
12228  return str;
12229  }
12230  return tmp;
12231 }
12232 
12233 /*
12234  * call-seq:
12235  * ARGF.getc -> String or nil
12236  *
12237  * Reads the next character from +ARGF+ and returns it as a +String+. Returns
12238  * +nil+ at the end of the stream.
12239  *
12240  * +ARGF+ treats the files named on the command line as a single file created
12241  * by concatenating their contents. After returning the last character of the
12242  * first file, it returns the first character of the second file, and so on.
12243  *
12244  * For example:
12245  *
12246  * $ echo "foo" > file
12247  * $ ruby argf.rb file
12248  *
12249  * ARGF.getc #=> "f"
12250  * ARGF.getc #=> "o"
12251  * ARGF.getc #=> "o"
12252  * ARGF.getc #=> "\n"
12253  * ARGF.getc #=> nil
12254  * ARGF.getc #=> nil
12255  */
12256 static VALUE
12257 argf_getc(VALUE argf)
12258 {
12259  VALUE ch;
12260 
12261  retry:
12262  if (!next_argv()) return Qnil;
12263  if (ARGF_GENERIC_INPUT_P()) {
12264  ch = rb_funcall3(ARGF.current_file, rb_intern("getc"), 0, 0);
12265  }
12266  else {
12267  ch = rb_io_getc(ARGF.current_file);
12268  }
12269  if (NIL_P(ch) && ARGF.next_p != -1) {
12270  argf_close(argf);
12271  ARGF.next_p = 1;
12272  goto retry;
12273  }
12274 
12275  return ch;
12276 }
12277 
12278 /*
12279  * call-seq:
12280  * ARGF.getbyte -> Integer or nil
12281  *
12282  * Gets the next 8-bit byte (0..255) from +ARGF+. Returns +nil+ if called at
12283  * the end of the stream.
12284  *
12285  * For example:
12286  *
12287  * $ echo "foo" > file
12288  * $ ruby argf.rb file
12289  *
12290  * ARGF.getbyte #=> 102
12291  * ARGF.getbyte #=> 111
12292  * ARGF.getbyte #=> 111
12293  * ARGF.getbyte #=> 10
12294  * ARGF.getbyte #=> nil
12295  */
12296 static VALUE
12297 argf_getbyte(VALUE argf)
12298 {
12299  VALUE ch;
12300 
12301  retry:
12302  if (!next_argv()) return Qnil;
12303  if (!RB_TYPE_P(ARGF.current_file, T_FILE)) {
12304  ch = rb_funcall3(ARGF.current_file, rb_intern("getbyte"), 0, 0);
12305  }
12306  else {
12307  ch = rb_io_getbyte(ARGF.current_file);
12308  }
12309  if (NIL_P(ch) && ARGF.next_p != -1) {
12310  argf_close(argf);
12311  ARGF.next_p = 1;
12312  goto retry;
12313  }
12314 
12315  return ch;
12316 }
12317 
12318 /*
12319  * call-seq:
12320  * ARGF.readchar -> String or nil
12321  *
12322  * Reads the next character from +ARGF+ and returns it as a +String+. Raises
12323  * an +EOFError+ after the last character of the last file has been read.
12324  *
12325  * For example:
12326  *
12327  * $ echo "foo" > file
12328  * $ ruby argf.rb file
12329  *
12330  * ARGF.readchar #=> "f"
12331  * ARGF.readchar #=> "o"
12332  * ARGF.readchar #=> "o"
12333  * ARGF.readchar #=> "\n"
12334  * ARGF.readchar #=> end of file reached (EOFError)
12335  */
12336 static VALUE
12337 argf_readchar(VALUE argf)
12338 {
12339  VALUE ch;
12340 
12341  retry:
12342  if (!next_argv()) rb_eof_error();
12343  if (!RB_TYPE_P(ARGF.current_file, T_FILE)) {
12344  ch = rb_funcall3(ARGF.current_file, rb_intern("getc"), 0, 0);
12345  }
12346  else {
12347  ch = rb_io_getc(ARGF.current_file);
12348  }
12349  if (NIL_P(ch) && ARGF.next_p != -1) {
12350  argf_close(argf);
12351  ARGF.next_p = 1;
12352  goto retry;
12353  }
12354 
12355  return ch;
12356 }
12357 
12358 /*
12359  * call-seq:
12360  * ARGF.readbyte -> Integer
12361  *
12362  * Reads the next 8-bit byte from ARGF and returns it as an +Integer+. Raises
12363  * an +EOFError+ after the last byte of the last file has been read.
12364  *
12365  * For example:
12366  *
12367  * $ echo "foo" > file
12368  * $ ruby argf.rb file
12369  *
12370  * ARGF.readbyte #=> 102
12371  * ARGF.readbyte #=> 111
12372  * ARGF.readbyte #=> 111
12373  * ARGF.readbyte #=> 10
12374  * ARGF.readbyte #=> end of file reached (EOFError)
12375  */
12376 static VALUE
12377 argf_readbyte(VALUE argf)
12378 {
12379  VALUE c;
12380 
12381  NEXT_ARGF_FORWARD(0, 0);
12382  c = argf_getbyte(argf);
12383  if (NIL_P(c)) {
12384  rb_eof_error();
12385  }
12386  return c;
12387 }
12388 
12389 #define FOREACH_ARGF() while (next_argv())
12390 
12391 static VALUE
12392 argf_block_call_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, argf))
12393 {
12394  const VALUE current = ARGF.current_file;
12396  if (ARGF.init_p == -1 || current != ARGF.current_file) {
12398  }
12399  return Qnil;
12400 }
12401 
12402 #define ARGF_block_call(mid, argc, argv, func, argf) \
12403  rb_block_call_kw(ARGF.current_file, mid, argc, argv, \
12404  func, argf, rb_keyword_given_p())
12405 
12406 static void
12407 argf_block_call(ID mid, int argc, VALUE *argv, VALUE argf)
12408 {
12409  VALUE ret = ARGF_block_call(mid, argc, argv, argf_block_call_i, argf);
12410  if (ret != Qundef) ARGF.next_p = 1;
12411 }
12412 
12413 static VALUE
12414 argf_block_call_line_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, argf))
12415 {
12416  if (!global_argf_p(argf)) {
12417  ARGF.last_lineno = ++ARGF.lineno;
12418  }
12419  return argf_block_call_i(i, argf, argc, argv, blockarg);
12420 }
12421 
12422 static void
12423 argf_block_call_line(ID mid, int argc, VALUE *argv, VALUE argf)
12424 {
12425  VALUE ret = ARGF_block_call(mid, argc, argv, argf_block_call_line_i, argf);
12426  if (ret != Qundef) ARGF.next_p = 1;
12427 }
12428 
12429 /*
12430  * call-seq:
12431  * ARGF.each(sep=$/) {|line| block } -> ARGF
12432  * ARGF.each(sep=$/, limit) {|line| block } -> ARGF
12433  * ARGF.each(...) -> an_enumerator
12434  *
12435  * ARGF.each_line(sep=$/) {|line| block } -> ARGF
12436  * ARGF.each_line(sep=$/, limit) {|line| block } -> ARGF
12437  * ARGF.each_line(...) -> an_enumerator
12438  *
12439  * Returns an enumerator which iterates over each line (separated by _sep_,
12440  * which defaults to your platform's newline character) of each file in
12441  * +ARGV+. If a block is supplied, each line in turn will be yielded to the
12442  * block, otherwise an enumerator is returned.
12443  * The optional _limit_ argument is an +Integer+ specifying the maximum
12444  * length of each line; longer lines will be split according to this limit.
12445  *
12446  * This method allows you to treat the files supplied on the command line as
12447  * a single file consisting of the concatenation of each named file. After
12448  * the last line of the first file has been returned, the first line of the
12449  * second file is returned. The +ARGF.filename+ and +ARGF.lineno+ methods can
12450  * be used to determine the filename of the current line and line number of
12451  * the whole input, respectively.
12452  *
12453  * For example, the following code prints out each line of each named file
12454  * prefixed with its line number, displaying the filename once per file:
12455  *
12456  * ARGF.each_line do |line|
12457  * puts ARGF.filename if ARGF.file.lineno == 1
12458  * puts "#{ARGF.file.lineno}: #{line}"
12459  * end
12460  *
12461  * While the following code prints only the first file's name at first, and
12462  * the contents with line number counted through all named files.
12463  *
12464  * ARGF.each_line do |line|
12465  * puts ARGF.filename if ARGF.lineno == 1
12466  * puts "#{ARGF.lineno}: #{line}"
12467  * end
12468  */
12469 static VALUE
12470 argf_each_line(int argc, VALUE *argv, VALUE argf)
12471 {
12473  FOREACH_ARGF() {
12474  argf_block_call_line(rb_intern("each_line"), argc, argv, argf);
12475  }
12476  return argf;
12477 }
12478 
12479 /*
12480  * This is a deprecated alias for #each_line.
12481  */
12482 
12483 static VALUE
12484 argf_lines(int argc, VALUE *argv, VALUE argf)
12485 {
12486  rb_warn_deprecated("ARGF#lines", "#each_line");
12487  if (!rb_block_given_p())
12488  return rb_enumeratorize(argf, ID2SYM(rb_intern("each_line")), argc, argv);
12489  return argf_each_line(argc, argv, argf);
12490 }
12491 
12492 /*
12493  * call-seq:
12494  * ARGF.bytes {|byte| block } -> ARGF
12495  * ARGF.bytes -> an_enumerator
12496  *
12497  * ARGF.each_byte {|byte| block } -> ARGF
12498  * ARGF.each_byte -> an_enumerator
12499  *
12500  * Iterates over each byte of each file in +ARGV+.
12501  * A byte is returned as an +Integer+ in the range 0..255.
12502  *
12503  * This method allows you to treat the files supplied on the command line as
12504  * a single file consisting of the concatenation of each named file. After
12505  * the last byte of the first file has been returned, the first byte of the
12506  * second file is returned. The +ARGF.filename+ method can be used to
12507  * determine the filename of the current byte.
12508  *
12509  * If no block is given, an enumerator is returned instead.
12510  *
12511  * For example:
12512  *
12513  * ARGF.bytes.to_a #=> [35, 32, ... 95, 10]
12514  *
12515  */
12516 static VALUE
12517 argf_each_byte(VALUE argf)
12518 {
12519  RETURN_ENUMERATOR(argf, 0, 0);
12520  FOREACH_ARGF() {
12521  argf_block_call(rb_intern("each_byte"), 0, 0, argf);
12522  }
12523  return argf;
12524 }
12525 
12526 /*
12527  * This is a deprecated alias for #each_byte.
12528  */
12529 
12530 static VALUE
12531 argf_bytes(VALUE argf)
12532 {
12533  rb_warn_deprecated("ARGF#bytes", "#each_byte");
12534  if (!rb_block_given_p())
12535  return rb_enumeratorize(argf, ID2SYM(rb_intern("each_byte")), 0, 0);
12536  return argf_each_byte(argf);
12537 }
12538 
12539 /*
12540  * call-seq:
12541  * ARGF.each_char {|char| block } -> ARGF
12542  * ARGF.each_char -> an_enumerator
12543  *
12544  * Iterates over each character of each file in +ARGF+.
12545  *
12546  * This method allows you to treat the files supplied on the command line as
12547  * a single file consisting of the concatenation of each named file. After
12548  * the last character of the first file has been returned, the first
12549  * character of the second file is returned. The +ARGF.filename+ method can
12550  * be used to determine the name of the file in which the current character
12551  * appears.
12552  *
12553  * If no block is given, an enumerator is returned instead.
12554  */
12555 static VALUE
12556 argf_each_char(VALUE argf)
12557 {
12558  RETURN_ENUMERATOR(argf, 0, 0);
12559  FOREACH_ARGF() {
12560  argf_block_call(rb_intern("each_char"), 0, 0, argf);
12561  }
12562  return argf;
12563 }
12564 
12565 /*
12566  * This is a deprecated alias for #each_char.
12567  */
12568 
12569 static VALUE
12570 argf_chars(VALUE argf)
12571 {
12572  rb_warn_deprecated("ARGF#chars", "#each_char");
12573  if (!rb_block_given_p())
12574  return rb_enumeratorize(argf, ID2SYM(rb_intern("each_char")), 0, 0);
12575  return argf_each_char(argf);
12576 }
12577 
12578 /*
12579  * call-seq:
12580  * ARGF.each_codepoint {|codepoint| block } -> ARGF
12581  * ARGF.each_codepoint -> an_enumerator
12582  *
12583  * Iterates over each codepoint of each file in +ARGF+.
12584  *
12585  * This method allows you to treat the files supplied on the command line as
12586  * a single file consisting of the concatenation of each named file. After
12587  * the last codepoint of the first file has been returned, the first
12588  * codepoint of the second file is returned. The +ARGF.filename+ method can
12589  * be used to determine the name of the file in which the current codepoint
12590  * appears.
12591  *
12592  * If no block is given, an enumerator is returned instead.
12593  */
12594 static VALUE
12595 argf_each_codepoint(VALUE argf)
12596 {
12597  RETURN_ENUMERATOR(argf, 0, 0);
12598  FOREACH_ARGF() {
12599  argf_block_call(rb_intern("each_codepoint"), 0, 0, argf);
12600  }
12601  return argf;
12602 }
12603 
12604 /*
12605  * This is a deprecated alias for #each_codepoint.
12606  */
12607 
12608 static VALUE
12609 argf_codepoints(VALUE argf)
12610 {
12611  rb_warn_deprecated("ARGF#codepoints", "#each_codepoint");
12612  if (!rb_block_given_p())
12613  return rb_enumeratorize(argf, ID2SYM(rb_intern("each_codepoint")), 0, 0);
12614  return argf_each_codepoint(argf);
12615 }
12616 
12617 /*
12618  * call-seq:
12619  * ARGF.filename -> String
12620  * ARGF.path -> String
12621  *
12622  * Returns the current filename. "-" is returned when the current file is
12623  * STDIN.
12624  *
12625  * For example:
12626  *
12627  * $ echo "foo" > foo
12628  * $ echo "bar" > bar
12629  * $ echo "glark" > glark
12630  *
12631  * $ ruby argf.rb foo bar glark
12632  *
12633  * ARGF.filename #=> "foo"
12634  * ARGF.read(5) #=> "foo\nb"
12635  * ARGF.filename #=> "bar"
12636  * ARGF.skip
12637  * ARGF.filename #=> "glark"
12638  */
12639 static VALUE
12640 argf_filename(VALUE argf)
12641 {
12642  next_argv();
12643  return ARGF.filename;
12644 }
12645 
12646 static VALUE
12647 argf_filename_getter(ID id, VALUE *var)
12648 {
12649  return argf_filename(*var);
12650 }
12651 
12652 /*
12653  * call-seq:
12654  * ARGF.file -> IO or File object
12655  *
12656  * Returns the current file as an +IO+ or +File+ object.
12657  * <code>$stdin</code> is returned when the current file is STDIN.
12658  *
12659  * For example:
12660  *
12661  * $ echo "foo" > foo
12662  * $ echo "bar" > bar
12663  *
12664  * $ ruby argf.rb foo bar
12665  *
12666  * ARGF.file #=> #<File:foo>
12667  * ARGF.read(5) #=> "foo\nb"
12668  * ARGF.file #=> #<File:bar>
12669  */
12670 static VALUE
12671 argf_file(VALUE argf)
12672 {
12673  next_argv();
12674  return ARGF.current_file;
12675 }
12676 
12677 /*
12678  * call-seq:
12679  * ARGF.binmode -> ARGF
12680  *
12681  * Puts +ARGF+ into binary mode. Once a stream is in binary mode, it cannot
12682  * be reset to non-binary mode. This option has the following effects:
12683  *
12684  * * Newline conversion is disabled.
12685  * * Encoding conversion is disabled.
12686  * * Content is treated as ASCII-8BIT.
12687  */
12688 static VALUE
12689 argf_binmode_m(VALUE argf)
12690 {
12691  ARGF.binmode = 1;
12692  next_argv();
12693  ARGF_FORWARD(0, 0);
12694  rb_io_ascii8bit_binmode(ARGF.current_file);
12695  return argf;
12696 }
12697 
12698 /*
12699  * call-seq:
12700  * ARGF.binmode? -> true or false
12701  *
12702  * Returns true if +ARGF+ is being read in binary mode; false otherwise.
12703  * To enable binary mode use +ARGF.binmode+.
12704  *
12705  * For example:
12706  *
12707  * ARGF.binmode? #=> false
12708  * ARGF.binmode
12709  * ARGF.binmode? #=> true
12710  */
12711 static VALUE
12712 argf_binmode_p(VALUE argf)
12713 {
12714  return ARGF.binmode ? Qtrue : Qfalse;
12715 }
12716 
12717 /*
12718  * call-seq:
12719  * ARGF.skip -> ARGF
12720  *
12721  * Sets the current file to the next file in ARGV. If there aren't any more
12722  * files it has no effect.
12723  *
12724  * For example:
12725  *
12726  * $ ruby argf.rb foo bar
12727  * ARGF.filename #=> "foo"
12728  * ARGF.skip
12729  * ARGF.filename #=> "bar"
12730  */
12731 static VALUE
12732 argf_skip(VALUE argf)
12733 {
12734  if (ARGF.init_p && ARGF.next_p == 0) {
12735  argf_close(argf);
12736  ARGF.next_p = 1;
12737  }
12738  return argf;
12739 }
12740 
12741 /*
12742  * call-seq:
12743  * ARGF.close -> ARGF
12744  *
12745  * Closes the current file and skips to the next file in ARGV. If there are
12746  * no more files to open, just closes the current file. +STDIN+ will not be
12747  * closed.
12748  *
12749  * For example:
12750  *
12751  * $ ruby argf.rb foo bar
12752  *
12753  * ARGF.filename #=> "foo"
12754  * ARGF.close
12755  * ARGF.filename #=> "bar"
12756  * ARGF.close
12757  */
12758 static VALUE
12759 argf_close_m(VALUE argf)
12760 {
12761  next_argv();
12762  argf_close(argf);
12763  if (ARGF.next_p != -1) {
12764  ARGF.next_p = 1;
12765  }
12766  ARGF.lineno = 0;
12767  return argf;
12768 }
12769 
12770 /*
12771  * call-seq:
12772  * ARGF.closed? -> true or false
12773  *
12774  * Returns _true_ if the current file has been closed; _false_ otherwise. Use
12775  * +ARGF.close+ to actually close the current file.
12776  */
12777 static VALUE
12778 argf_closed(VALUE argf)
12779 {
12780  next_argv();
12781  ARGF_FORWARD(0, 0);
12782  return rb_io_closed(ARGF.current_file);
12783 }
12784 
12785 /*
12786  * call-seq:
12787  * ARGF.to_s -> String
12788  *
12789  * Returns "ARGF".
12790  */
12791 static VALUE
12792 argf_to_s(VALUE argf)
12793 {
12794  return rb_str_new2("ARGF");
12795 }
12796 
12797 /*
12798  * call-seq:
12799  * ARGF.inplace_mode -> String
12800  *
12801  * Returns the file extension appended to the names of modified files under
12802  * in-place edit mode. This value can be set using +ARGF.inplace_mode=+ or
12803  * passing the +-i+ switch to the Ruby binary.
12804  */
12805 static VALUE
12806 argf_inplace_mode_get(VALUE argf)
12807 {
12808  if (!ARGF.inplace) return Qnil;
12809  if (NIL_P(ARGF.inplace)) return rb_str_new(0, 0);
12810  return rb_str_dup(ARGF.inplace);
12811 }
12812 
12813 static VALUE
12814 opt_i_get(ID id, VALUE *var)
12815 {
12816  return argf_inplace_mode_get(*var);
12817 }
12818 
12819 /*
12820  * call-seq:
12821  * ARGF.inplace_mode = ext -> ARGF
12822  *
12823  * Sets the filename extension for in-place editing mode to the given String.
12824  * Each file being edited has this value appended to its filename. The
12825  * modified file is saved under this new name.
12826  *
12827  * For example:
12828  *
12829  * $ ruby argf.rb file.txt
12830  *
12831  * ARGF.inplace_mode = '.bak'
12832  * ARGF.each_line do |line|
12833  * print line.sub("foo","bar")
12834  * end
12835  *
12836  * Each line of _file.txt_ has the first occurrence of "foo" replaced with
12837  * "bar", then the new line is written out to _file.txt.bak_.
12838  */
12839 static VALUE
12840 argf_inplace_mode_set(VALUE argf, VALUE val)
12841 {
12842  if (!RTEST(val)) {
12843  ARGF.inplace = Qfalse;
12844  }
12845  else if (StringValueCStr(val), !RSTRING_LEN(val)) {
12846  ARGF.inplace = Qnil;
12847  }
12848  else {
12849  ARGF.inplace = rb_str_new_frozen(val);
12850  }
12851  return argf;
12852 }
12853 
12854 static void
12855 opt_i_set(VALUE val, ID id, VALUE *var)
12856 {
12857  argf_inplace_mode_set(*var, val);
12858 }
12859 
12860 void
12861 ruby_set_inplace_mode(const char *suffix)
12862 {
12863  ARGF.inplace = !suffix ? Qfalse : !*suffix ? Qnil : rb_fstring_cstr(suffix);
12864 }
12865 
12866 /*
12867  * call-seq:
12868  * ARGF.argv -> ARGV
12869  *
12870  * Returns the +ARGV+ array, which contains the arguments passed to your
12871  * script, one per element.
12872  *
12873  * For example:
12874  *
12875  * $ ruby argf.rb -v glark.txt
12876  *
12877  * ARGF.argv #=> ["-v", "glark.txt"]
12878  *
12879  */
12880 static VALUE
12881 argf_argv(VALUE argf)
12882 {
12883  return ARGF.argv;
12884 }
12885 
12886 static VALUE
12887 argf_argv_getter(ID id, VALUE *var)
12888 {
12889  return argf_argv(*var);
12890 }
12891 
12892 VALUE
12894 {
12895  return ARGF.argv;
12896 }
12897 
12898 /*
12899  * call-seq:
12900  * ARGF.to_write_io -> io
12901  *
12902  * Returns IO instance tied to _ARGF_ for writing if inplace mode is
12903  * enabled.
12904  */
12905 static VALUE
12906 argf_write_io(VALUE argf)
12907 {
12908  if (!RTEST(ARGF.current_file)) {
12909  rb_raise(rb_eIOError, "not opened for writing");
12910  }
12911  return GetWriteIO(ARGF.current_file);
12912 }
12913 
12914 /*
12915  * call-seq:
12916  * ARGF.write(string) -> integer
12917  *
12918  * Writes _string_ if inplace mode.
12919  */
12920 static VALUE
12921 argf_write(VALUE argf, VALUE str)
12922 {
12923  return rb_io_write(argf_write_io(argf), str);
12924 }
12925 
12926 void
12927 rb_readwrite_sys_fail(enum rb_io_wait_readwrite writable, const char *mesg)
12928 {
12929  rb_readwrite_syserr_fail(writable, errno, mesg);
12930 }
12931 
12932 void
12933 rb_readwrite_syserr_fail(enum rb_io_wait_readwrite writable, int n, const char *mesg)
12934 {
12935  VALUE arg;
12936  arg = mesg ? rb_str_new2(mesg) : Qnil;
12937  if (writable == RB_IO_WAIT_WRITABLE) {
12938  switch (n) {
12939  case EAGAIN:
12940  rb_exc_raise(rb_class_new_instance(1, &arg, rb_eEAGAINWaitWritable));
12941  break;
12942 #if EAGAIN != EWOULDBLOCK
12943  case EWOULDBLOCK:
12944  rb_exc_raise(rb_class_new_instance(1, &arg, rb_eEWOULDBLOCKWaitWritable));
12945  break;
12946 #endif
12947  case EINPROGRESS:
12948  rb_exc_raise(rb_class_new_instance(1, &arg, rb_eEINPROGRESSWaitWritable));
12949  break;
12950  default:
12952  }
12953  }
12954  else if (writable == RB_IO_WAIT_READABLE) {
12955  switch (n) {
12956  case EAGAIN:
12957  rb_exc_raise(rb_class_new_instance(1, &arg, rb_eEAGAINWaitReadable));
12958  break;
12959 #if EAGAIN != EWOULDBLOCK
12960  case EWOULDBLOCK:
12961  rb_exc_raise(rb_class_new_instance(1, &arg, rb_eEWOULDBLOCKWaitReadable));
12962  break;
12963 #endif
12964  case EINPROGRESS:
12965  rb_exc_raise(rb_class_new_instance(1, &arg, rb_eEINPROGRESSWaitReadable));
12966  break;
12967  default:
12969  }
12970  }
12971  else {
12972  rb_bug("invalid read/write type passed to rb_readwrite_sys_fail: %d", writable);
12973  }
12974 }
12975 
12976 static VALUE
12977 get_LAST_READ_LINE(ID _x, VALUE *_y)
12978 {
12979  return rb_lastline_get();
12980 }
12981 
12982 static void
12983 set_LAST_READ_LINE(VALUE val, ID _x, VALUE *_y)
12984 {
12985  rb_lastline_set(val);
12986 }
12987 
12988 /*
12989  * Document-class: IOError
12990  *
12991  * Raised when an IO operation fails.
12992  *
12993  * File.open("/etc/hosts") {|f| f << "example"}
12994  * #=> IOError: not opened for writing
12995  *
12996  * File.open("/etc/hosts") {|f| f.close; f.read }
12997  * #=> IOError: closed stream
12998  *
12999  * Note that some IO failures raise <code>SystemCallError</code>s
13000  * and these are not subclasses of IOError:
13001  *
13002  * File.open("does/not/exist")
13003  * #=> Errno::ENOENT: No such file or directory - does/not/exist
13004  */
13005 
13006 /*
13007  * Document-class: EOFError
13008  *
13009  * Raised by some IO operations when reaching the end of file. Many IO
13010  * methods exist in two forms,
13011  *
13012  * one that returns +nil+ when the end of file is reached, the other
13013  * raises +EOFError+.
13014  *
13015  * +EOFError+ is a subclass of +IOError+.
13016  *
13017  * file = File.open("/etc/hosts")
13018  * file.read
13019  * file.gets #=> nil
13020  * file.readline #=> EOFError: end of file reached
13021  */
13022 
13023 /*
13024  * Document-class: ARGF
13025  *
13026  * +ARGF+ is a stream designed for use in scripts that process files given as
13027  * command-line arguments or passed in via STDIN.
13028  *
13029  * The arguments passed to your script are stored in the +ARGV+ Array, one
13030  * argument per element. +ARGF+ assumes that any arguments that aren't
13031  * filenames have been removed from +ARGV+. For example:
13032  *
13033  * $ ruby argf.rb --verbose file1 file2
13034  *
13035  * ARGV #=> ["--verbose", "file1", "file2"]
13036  * option = ARGV.shift #=> "--verbose"
13037  * ARGV #=> ["file1", "file2"]
13038  *
13039  * You can now use +ARGF+ to work with a concatenation of each of these named
13040  * files. For instance, +ARGF.read+ will return the contents of _file1_
13041  * followed by the contents of _file2_.
13042  *
13043  * After a file in +ARGV+ has been read +ARGF+ removes it from the Array.
13044  * Thus, after all files have been read +ARGV+ will be empty.
13045  *
13046  * You can manipulate +ARGV+ yourself to control what +ARGF+ operates on. If
13047  * you remove a file from +ARGV+, it is ignored by +ARGF+; if you add files to
13048  * +ARGV+, they are treated as if they were named on the command line. For
13049  * example:
13050  *
13051  * ARGV.replace ["file1"]
13052  * ARGF.readlines # Returns the contents of file1 as an Array
13053  * ARGV #=> []
13054  * ARGV.replace ["file2", "file3"]
13055  * ARGF.read # Returns the contents of file2 and file3
13056  *
13057  * If +ARGV+ is empty, +ARGF+ acts as if it contained STDIN, i.e. the data
13058  * piped to your script. For example:
13059  *
13060  * $ echo "glark" | ruby -e 'p ARGF.read'
13061  * "glark\n"
13062  */
13063 
13064 /*
13065  * The IO class is the basis for all input and output in Ruby.
13066  * An I/O stream may be <em>duplexed</em> (that is, bidirectional), and
13067  * so may use more than one native operating system stream.
13068  *
13069  * Many of the examples in this section use the File class, the only standard
13070  * subclass of IO. The two classes are closely associated. Like the File
13071  * class, the Socket library subclasses from IO (such as TCPSocket or
13072  * UDPSocket).
13073  *
13074  * The Kernel#open method can create an IO (or File) object for these types
13075  * of arguments:
13076  *
13077  * * A plain string represents a filename suitable for the underlying
13078  * operating system.
13079  *
13080  * * A string starting with <code>"|"</code> indicates a subprocess.
13081  * The remainder of the string following the <code>"|"</code> is
13082  * invoked as a process with appropriate input/output channels
13083  * connected to it.
13084  *
13085  * * A string equal to <code>"|-"</code> will create another Ruby
13086  * instance as a subprocess.
13087  *
13088  * The IO may be opened with different file modes (read-only, write-only) and
13089  * encodings for proper conversion. See IO.new for these options. See
13090  * Kernel#open for details of the various command formats described above.
13091  *
13092  * IO.popen, the Open3 library, or Process#spawn may also be used to
13093  * communicate with subprocesses through an IO.
13094  *
13095  * Ruby will convert pathnames between different operating system
13096  * conventions if possible. For instance, on a Windows system the
13097  * filename <code>"/gumby/ruby/test.rb"</code> will be opened as
13098  * <code>"\gumby\ruby\test.rb"</code>. When specifying a Windows-style
13099  * filename in a Ruby string, remember to escape the backslashes:
13100  *
13101  * "C:\\gumby\\ruby\\test.rb"
13102  *
13103  * Our examples here will use the Unix-style forward slashes;
13104  * File::ALT_SEPARATOR can be used to get the platform-specific separator
13105  * character.
13106  *
13107  * The global constant ARGF (also accessible as <code>$<</code>) provides an
13108  * IO-like stream which allows access to all files mentioned on the
13109  * command line (or STDIN if no files are mentioned). ARGF#path and its alias
13110  * ARGF#filename are provided to access the name of the file currently being
13111  * read.
13112  *
13113  * == io/console
13114  *
13115  * The io/console extension provides methods for interacting with the
13116  * console. The console can be accessed from IO.console or the standard
13117  * input/output/error IO objects.
13118  *
13119  * Requiring io/console adds the following methods:
13120  *
13121  * * IO::console
13122  * * IO#raw
13123  * * IO#raw!
13124  * * IO#cooked
13125  * * IO#cooked!
13126  * * IO#getch
13127  * * IO#echo=
13128  * * IO#echo?
13129  * * IO#noecho
13130  * * IO#winsize
13131  * * IO#winsize=
13132  * * IO#iflush
13133  * * IO#ioflush
13134  * * IO#oflush
13135  *
13136  * Example:
13137  *
13138  * require 'io/console'
13139  * rows, columns = $stdout.winsize
13140  * puts "Your screen is #{columns} wide and #{rows} tall"
13141  */
13142 
13143 void
13144 Init_IO(void)
13145 {
13146 #undef rb_intern
13147 #define rb_intern(str) rb_intern_const(str)
13148 
13149  VALUE rb_cARGF;
13150 #ifdef __CYGWIN__
13151 #include <sys/cygwin.h>
13152  static struct __cygwin_perfile pf[] =
13153  {
13154  {"", O_RDONLY | O_BINARY},
13155  {"", O_WRONLY | O_BINARY},
13156  {"", O_RDWR | O_BINARY},
13157  {"", O_APPEND | O_BINARY},
13158  {NULL, 0}
13159  };
13160  cygwin_internal(CW_PERFILE, pf);
13161 #endif
13162 
13164  rb_eEOFError = rb_define_class("EOFError", rb_eIOError);
13165 
13166  id_write = rb_intern("write");
13167  id_read = rb_intern("read");
13168  id_getc = rb_intern("getc");
13169  id_flush = rb_intern("flush");
13170  id_readpartial = rb_intern("readpartial");
13171  id_set_encoding = rb_intern("set_encoding");
13172 
13173  rb_define_global_function("syscall", rb_f_syscall, -1);
13174 
13175  rb_define_global_function("open", rb_f_open, -1);
13176  rb_define_global_function("printf", rb_f_printf, -1);
13177  rb_define_global_function("print", rb_f_print, -1);
13178  rb_define_global_function("putc", rb_f_putc, 1);
13179  rb_define_global_function("puts", rb_f_puts, -1);
13180  rb_define_global_function("gets", rb_f_gets, -1);
13181  rb_define_global_function("readline", rb_f_readline, -1);
13182  rb_define_global_function("select", rb_f_select, -1);
13183 
13184  rb_define_global_function("readlines", rb_f_readlines, -1);
13185 
13186  rb_define_global_function("`", rb_f_backquote, 1);
13187 
13188  rb_define_global_function("p", rb_f_p, -1);
13189  rb_define_method(rb_mKernel, "display", rb_obj_display, -1);
13190 
13193 
13194  /* exception to wait for reading. see IO.select. */
13195  rb_mWaitReadable = rb_define_module_under(rb_cIO, "WaitReadable");
13196  /* exception to wait for writing. see IO.select. */
13197  rb_mWaitWritable = rb_define_module_under(rb_cIO, "WaitWritable");
13198  /* exception to wait for reading by EAGAIN. see IO.select. */
13199  rb_eEAGAINWaitReadable = rb_define_class_under(rb_cIO, "EAGAINWaitReadable", rb_eEAGAIN);
13200  rb_include_module(rb_eEAGAINWaitReadable, rb_mWaitReadable);
13201  /* exception to wait for writing by EAGAIN. see IO.select. */
13202  rb_eEAGAINWaitWritable = rb_define_class_under(rb_cIO, "EAGAINWaitWritable", rb_eEAGAIN);
13203  rb_include_module(rb_eEAGAINWaitWritable, rb_mWaitWritable);
13204 #if EAGAIN == EWOULDBLOCK
13205  rb_eEWOULDBLOCKWaitReadable = rb_eEAGAINWaitReadable;
13206  /* same as IO::EAGAINWaitReadable */
13207  rb_define_const(rb_cIO, "EWOULDBLOCKWaitReadable", rb_eEAGAINWaitReadable);
13208  rb_eEWOULDBLOCKWaitWritable = rb_eEAGAINWaitWritable;
13209  /* same as IO::EAGAINWaitWritable */
13210  rb_define_const(rb_cIO, "EWOULDBLOCKWaitWritable", rb_eEAGAINWaitWritable);
13211 #else
13212  /* exception to wait for reading by EWOULDBLOCK. see IO.select. */
13213  rb_eEWOULDBLOCKWaitReadable = rb_define_class_under(rb_cIO, "EWOULDBLOCKWaitReadable", rb_eEWOULDBLOCK);
13214  rb_include_module(rb_eEWOULDBLOCKWaitReadable, rb_mWaitReadable);
13215  /* exception to wait for writing by EWOULDBLOCK. see IO.select. */
13216  rb_eEWOULDBLOCKWaitWritable = rb_define_class_under(rb_cIO, "EWOULDBLOCKWaitWritable", rb_eEWOULDBLOCK);
13217  rb_include_module(rb_eEWOULDBLOCKWaitWritable, rb_mWaitWritable);
13218 #endif
13219  /* exception to wait for reading by EINPROGRESS. see IO.select. */
13220  rb_eEINPROGRESSWaitReadable = rb_define_class_under(rb_cIO, "EINPROGRESSWaitReadable", rb_eEINPROGRESS);
13221  rb_include_module(rb_eEINPROGRESSWaitReadable, rb_mWaitReadable);
13222  /* exception to wait for writing by EINPROGRESS. see IO.select. */
13223  rb_eEINPROGRESSWaitWritable = rb_define_class_under(rb_cIO, "EINPROGRESSWaitWritable", rb_eEINPROGRESS);
13224  rb_include_module(rb_eEINPROGRESSWaitWritable, rb_mWaitWritable);
13225 
13226 #if 0
13227  /* This is necessary only for forcing rdoc handle File::open */
13228  rb_define_singleton_method(rb_cFile, "open", rb_io_s_open, -1);
13229 #endif
13230 
13231  rb_define_alloc_func(rb_cIO, io_alloc);
13232  rb_define_singleton_method(rb_cIO, "new", rb_io_s_new, -1);
13233  rb_define_singleton_method(rb_cIO, "open", rb_io_s_open, -1);
13234  rb_define_singleton_method(rb_cIO, "sysopen", rb_io_s_sysopen, -1);
13235  rb_define_singleton_method(rb_cIO, "for_fd", rb_io_s_for_fd, -1);
13236  rb_define_singleton_method(rb_cIO, "popen", rb_io_s_popen, -1);
13237  rb_define_singleton_method(rb_cIO, "foreach", rb_io_s_foreach, -1);
13238  rb_define_singleton_method(rb_cIO, "readlines", rb_io_s_readlines, -1);
13239  rb_define_singleton_method(rb_cIO, "read", rb_io_s_read, -1);
13240  rb_define_singleton_method(rb_cIO, "binread", rb_io_s_binread, -1);
13241  rb_define_singleton_method(rb_cIO, "write", rb_io_s_write, -1);
13242  rb_define_singleton_method(rb_cIO, "binwrite", rb_io_s_binwrite, -1);
13243  rb_define_singleton_method(rb_cIO, "select", rb_f_select, -1);
13244  rb_define_singleton_method(rb_cIO, "pipe", rb_io_s_pipe, -1);
13245  rb_define_singleton_method(rb_cIO, "try_convert", rb_io_s_try_convert, 1);
13246  rb_define_singleton_method(rb_cIO, "copy_stream", rb_io_s_copy_stream, -1);
13247 
13248  rb_define_method(rb_cIO, "initialize", rb_io_initialize, -1);
13249 
13250  rb_output_fs = Qnil;
13251  rb_define_hooked_variable("$,", &rb_output_fs, 0, rb_output_fs_setter);
13252 
13253  rb_default_rs = rb_fstring_lit("\n"); /* avoid modifying RS_default */
13255  rb_rs = rb_default_rs;
13256  rb_output_rs = Qnil;
13260 
13261  rb_define_virtual_variable("$_", get_LAST_READ_LINE, set_LAST_READ_LINE);
13262 
13263  rb_define_method(rb_cIO, "initialize_copy", rb_io_init_copy, 1);
13264  rb_define_method(rb_cIO, "reopen", rb_io_reopen, -1);
13265 
13266  rb_define_method(rb_cIO, "print", rb_io_print, -1);
13267  rb_define_method(rb_cIO, "putc", rb_io_putc, 1);
13268  rb_define_method(rb_cIO, "puts", rb_io_puts, -1);
13269  rb_define_method(rb_cIO, "printf", rb_io_printf, -1);
13270 
13271  rb_define_method(rb_cIO, "each", rb_io_each_line, -1);
13272  rb_define_method(rb_cIO, "each_line", rb_io_each_line, -1);
13273  rb_define_method(rb_cIO, "each_byte", rb_io_each_byte, 0);
13274  rb_define_method(rb_cIO, "each_char", rb_io_each_char, 0);
13275  rb_define_method(rb_cIO, "each_codepoint", rb_io_each_codepoint, 0);
13276  rb_define_method(rb_cIO, "lines", rb_io_lines, -1);
13277  rb_define_method(rb_cIO, "bytes", rb_io_bytes, 0);
13278  rb_define_method(rb_cIO, "chars", rb_io_chars, 0);
13279  rb_define_method(rb_cIO, "codepoints", rb_io_codepoints, 0);
13280 
13281  rb_define_method(rb_cIO, "syswrite", rb_io_syswrite, 1);
13282  rb_define_method(rb_cIO, "sysread", rb_io_sysread, -1);
13283 
13284  rb_define_method(rb_cIO, "pread", rb_io_pread, -1);
13285  rb_define_method(rb_cIO, "pwrite", rb_io_pwrite, 2);
13286 
13287  rb_define_method(rb_cIO, "fileno", rb_io_fileno, 0);
13288  rb_define_alias(rb_cIO, "to_i", "fileno");
13289  rb_define_method(rb_cIO, "to_io", rb_io_to_io, 0);
13290 
13291  rb_define_method(rb_cIO, "fsync", rb_io_fsync, 0);
13292  rb_define_method(rb_cIO, "fdatasync", rb_io_fdatasync, 0);
13293  rb_define_method(rb_cIO, "sync", rb_io_sync, 0);
13294  rb_define_method(rb_cIO, "sync=", rb_io_set_sync, 1);
13295 
13296  rb_define_method(rb_cIO, "lineno", rb_io_lineno, 0);
13297  rb_define_method(rb_cIO, "lineno=", rb_io_set_lineno, 1);
13298 
13299  rb_define_method(rb_cIO, "readlines", rb_io_readlines, -1);
13300 
13301  rb_define_method(rb_cIO, "readpartial", io_readpartial, -1);
13302  rb_define_method(rb_cIO, "read", io_read, -1);
13303  rb_define_method(rb_cIO, "write", io_write_m, -1);
13304  rb_define_method(rb_cIO, "gets", rb_io_gets_m, -1);
13305  rb_define_method(rb_cIO, "readline", rb_io_readline, -1);
13306  rb_define_method(rb_cIO, "getc", rb_io_getc, 0);
13307  rb_define_method(rb_cIO, "getbyte", rb_io_getbyte, 0);
13308  rb_define_method(rb_cIO, "readchar", rb_io_readchar, 0);
13309  rb_define_method(rb_cIO, "readbyte", rb_io_readbyte, 0);
13310  rb_define_method(rb_cIO, "ungetbyte",rb_io_ungetbyte, 1);
13311  rb_define_method(rb_cIO, "ungetc",rb_io_ungetc, 1);
13313  rb_define_method(rb_cIO, "flush", rb_io_flush, 0);
13314  rb_define_method(rb_cIO, "tell", rb_io_tell, 0);
13315  rb_define_method(rb_cIO, "seek", rb_io_seek_m, -1);
13316  /* Set I/O position from the beginning */
13317  rb_define_const(rb_cIO, "SEEK_SET", INT2FIX(SEEK_SET));
13318  /* Set I/O position from the current position */
13319  rb_define_const(rb_cIO, "SEEK_CUR", INT2FIX(SEEK_CUR));
13320  /* Set I/O position from the end */
13321  rb_define_const(rb_cIO, "SEEK_END", INT2FIX(SEEK_END));
13322 #ifdef SEEK_DATA
13323  /* Set I/O position to the next location containing data */
13324  rb_define_const(rb_cIO, "SEEK_DATA", INT2FIX(SEEK_DATA));
13325 #endif
13326 #ifdef SEEK_HOLE
13327  /* Set I/O position to the next hole */
13328  rb_define_const(rb_cIO, "SEEK_HOLE", INT2FIX(SEEK_HOLE));
13329 #endif
13330  rb_define_method(rb_cIO, "rewind", rb_io_rewind, 0);
13331  rb_define_method(rb_cIO, "pos", rb_io_tell, 0);
13332  rb_define_method(rb_cIO, "pos=", rb_io_set_pos, 1);
13333  rb_define_method(rb_cIO, "eof", rb_io_eof, 0);
13334  rb_define_method(rb_cIO, "eof?", rb_io_eof, 0);
13335 
13336  rb_define_method(rb_cIO, "close_on_exec?", rb_io_close_on_exec_p, 0);
13337  rb_define_method(rb_cIO, "close_on_exec=", rb_io_set_close_on_exec, 1);
13338 
13339  rb_define_method(rb_cIO, "close", rb_io_close_m, 0);
13340  rb_define_method(rb_cIO, "closed?", rb_io_closed, 0);
13341  rb_define_method(rb_cIO, "close_read", rb_io_close_read, 0);
13342  rb_define_method(rb_cIO, "close_write", rb_io_close_write, 0);
13343 
13344  rb_define_method(rb_cIO, "isatty", rb_io_isatty, 0);
13345  rb_define_method(rb_cIO, "tty?", rb_io_isatty, 0);
13346  rb_define_method(rb_cIO, "binmode", rb_io_binmode_m, 0);
13347  rb_define_method(rb_cIO, "binmode?", rb_io_binmode_p, 0);
13348  rb_define_method(rb_cIO, "sysseek", rb_io_sysseek, -1);
13349  rb_define_method(rb_cIO, "advise", rb_io_advise, -1);
13350 
13351  rb_define_method(rb_cIO, "ioctl", rb_io_ioctl, -1);
13352  rb_define_method(rb_cIO, "fcntl", rb_io_fcntl, -1);
13353  rb_define_method(rb_cIO, "pid", rb_io_pid, 0);
13354  rb_define_method(rb_cIO, "inspect", rb_io_inspect, 0);
13355 
13356  rb_define_method(rb_cIO, "external_encoding", rb_io_external_encoding, 0);
13357  rb_define_method(rb_cIO, "internal_encoding", rb_io_internal_encoding, 0);
13358  rb_define_method(rb_cIO, "set_encoding", rb_io_set_encoding, -1);
13359  rb_define_method(rb_cIO, "set_encoding_by_bom", rb_io_set_encoding_by_bom, 0);
13360 
13361  rb_define_method(rb_cIO, "autoclose?", rb_io_autoclose_p, 0);
13362  rb_define_method(rb_cIO, "autoclose=", rb_io_set_autoclose, 1);
13363 
13364  rb_define_variable("$stdin", &rb_stdin);
13365  rb_stdin = prep_stdio(stdin, FMODE_READABLE, rb_cIO, "<STDIN>");
13366  rb_define_hooked_variable("$stdout", &rb_stdout, 0, stdout_setter);
13367  rb_stdout = prep_stdio(stdout, FMODE_WRITABLE, rb_cIO, "<STDOUT>");
13368  rb_define_hooked_variable("$stderr", &rb_stderr, 0, stdout_setter);
13369  rb_stderr = prep_stdio(stderr, FMODE_WRITABLE|FMODE_SYNC, rb_cIO, "<STDERR>");
13370  rb_define_hooked_variable("$>", &rb_stdout, 0, stdout_setter);
13371  orig_stdout = rb_stdout;
13372  orig_stderr = rb_stderr;
13373 
13374  /* Holds the original stdin */
13375  rb_define_global_const("STDIN", rb_stdin);
13376  /* Holds the original stdout */
13377  rb_define_global_const("STDOUT", rb_stdout);
13378  /* Holds the original stderr */
13379  rb_define_global_const("STDERR", rb_stderr);
13380 
13381 #if 0
13382  /* Hack to get rdoc to regard ARGF as a class: */
13383  rb_cARGF = rb_define_class("ARGF", rb_cObject);
13384 #endif
13385 
13386  rb_cARGF = rb_class_new(rb_cObject);
13387  rb_set_class_path(rb_cARGF, rb_cObject, "ARGF.class");
13388  rb_define_alloc_func(rb_cARGF, argf_alloc);
13389 
13390  rb_include_module(rb_cARGF, rb_mEnumerable);
13391 
13392  rb_define_method(rb_cARGF, "initialize", argf_initialize, -2);
13393  rb_define_method(rb_cARGF, "initialize_copy", argf_initialize_copy, 1);
13394  rb_define_method(rb_cARGF, "to_s", argf_to_s, 0);
13395  rb_define_alias(rb_cARGF, "inspect", "to_s");
13396  rb_define_method(rb_cARGF, "argv", argf_argv, 0);
13397 
13398  rb_define_method(rb_cARGF, "fileno", argf_fileno, 0);
13399  rb_define_method(rb_cARGF, "to_i", argf_fileno, 0);
13400  rb_define_method(rb_cARGF, "to_io", argf_to_io, 0);
13401  rb_define_method(rb_cARGF, "to_write_io", argf_write_io, 0);
13402  rb_define_method(rb_cARGF, "each", argf_each_line, -1);
13403  rb_define_method(rb_cARGF, "each_line", argf_each_line, -1);
13404  rb_define_method(rb_cARGF, "each_byte", argf_each_byte, 0);
13405  rb_define_method(rb_cARGF, "each_char", argf_each_char, 0);
13406  rb_define_method(rb_cARGF, "each_codepoint", argf_each_codepoint, 0);
13407  rb_define_method(rb_cARGF, "lines", argf_lines, -1);
13408  rb_define_method(rb_cARGF, "bytes", argf_bytes, 0);
13409  rb_define_method(rb_cARGF, "chars", argf_chars, 0);
13410  rb_define_method(rb_cARGF, "codepoints", argf_codepoints, 0);
13411 
13412  rb_define_method(rb_cARGF, "read", argf_read, -1);
13413  rb_define_method(rb_cARGF, "readpartial", argf_readpartial, -1);
13414  rb_define_method(rb_cARGF, "read_nonblock", argf_read_nonblock, -1);
13415  rb_define_method(rb_cARGF, "readlines", argf_readlines, -1);
13416  rb_define_method(rb_cARGF, "to_a", argf_readlines, -1);
13417  rb_define_method(rb_cARGF, "gets", argf_gets, -1);
13418  rb_define_method(rb_cARGF, "readline", argf_readline, -1);
13419  rb_define_method(rb_cARGF, "getc", argf_getc, 0);
13420  rb_define_method(rb_cARGF, "getbyte", argf_getbyte, 0);
13421  rb_define_method(rb_cARGF, "readchar", argf_readchar, 0);
13422  rb_define_method(rb_cARGF, "readbyte", argf_readbyte, 0);
13423  rb_define_method(rb_cARGF, "tell", argf_tell, 0);
13424  rb_define_method(rb_cARGF, "seek", argf_seek_m, -1);
13425  rb_define_method(rb_cARGF, "rewind", argf_rewind, 0);
13426  rb_define_method(rb_cARGF, "pos", argf_tell, 0);
13427  rb_define_method(rb_cARGF, "pos=", argf_set_pos, 1);
13428  rb_define_method(rb_cARGF, "eof", argf_eof, 0);
13429  rb_define_method(rb_cARGF, "eof?", argf_eof, 0);
13430  rb_define_method(rb_cARGF, "binmode", argf_binmode_m, 0);
13431  rb_define_method(rb_cARGF, "binmode?", argf_binmode_p, 0);
13432 
13433  rb_define_method(rb_cARGF, "write", argf_write, 1);
13434  rb_define_method(rb_cARGF, "print", rb_io_print, -1);
13435  rb_define_method(rb_cARGF, "putc", rb_io_putc, 1);
13436  rb_define_method(rb_cARGF, "puts", rb_io_puts, -1);
13437  rb_define_method(rb_cARGF, "printf", rb_io_printf, -1);
13438 
13439  rb_define_method(rb_cARGF, "filename", argf_filename, 0);
13440  rb_define_method(rb_cARGF, "path", argf_filename, 0);
13441  rb_define_method(rb_cARGF, "file", argf_file, 0);
13442  rb_define_method(rb_cARGF, "skip", argf_skip, 0);
13443  rb_define_method(rb_cARGF, "close", argf_close_m, 0);
13444  rb_define_method(rb_cARGF, "closed?", argf_closed, 0);
13445 
13446  rb_define_method(rb_cARGF, "lineno", argf_lineno, 0);
13447  rb_define_method(rb_cARGF, "lineno=", argf_set_lineno, 1);
13448 
13449  rb_define_method(rb_cARGF, "inplace_mode", argf_inplace_mode_get, 0);
13450  rb_define_method(rb_cARGF, "inplace_mode=", argf_inplace_mode_set, 1);
13451 
13452  rb_define_method(rb_cARGF, "external_encoding", argf_external_encoding, 0);
13453  rb_define_method(rb_cARGF, "internal_encoding", argf_internal_encoding, 0);
13454  rb_define_method(rb_cARGF, "set_encoding", argf_set_encoding, -1);
13455 
13456  argf = rb_class_new_instance(0, 0, rb_cARGF);
13457 
13459  /*
13460  * ARGF is a stream designed for use in scripts that process files given
13461  * as command-line arguments or passed in via STDIN.
13462  *
13463  * See ARGF (the class) for more details.
13464  */
13465  rb_define_global_const("ARGF", argf);
13466 
13467  rb_define_hooked_variable("$.", &argf, argf_lineno_getter, argf_lineno_setter);
13468  rb_define_hooked_variable("$FILENAME", &argf, argf_filename_getter, rb_gvar_readonly_setter);
13469  ARGF.filename = rb_str_new2("-");
13470 
13471  rb_define_hooked_variable("$-i", &argf, opt_i_get, opt_i_set);
13472  rb_define_hooked_variable("$*", &argf, argf_argv_getter, rb_gvar_readonly_setter);
13473 
13474 #if defined (_WIN32) || defined(__CYGWIN__)
13475  atexit(pipe_atexit);
13476 #endif
13477 
13478  Init_File();
13479 
13480  rb_define_method(rb_cFile, "initialize", rb_file_initialize, -1);
13481 
13482  sym_mode = ID2SYM(rb_intern("mode"));
13483  sym_perm = ID2SYM(rb_intern("perm"));
13484  sym_flags = ID2SYM(rb_intern("flags"));
13485  sym_extenc = ID2SYM(rb_intern("external_encoding"));
13486  sym_intenc = ID2SYM(rb_intern("internal_encoding"));
13487  sym_encoding = ID2SYM(rb_id_encoding());
13488  sym_open_args = ID2SYM(rb_intern("open_args"));
13489  sym_textmode = ID2SYM(rb_intern("textmode"));
13490  sym_binmode = ID2SYM(rb_intern("binmode"));
13491  sym_autoclose = ID2SYM(rb_intern("autoclose"));
13492  sym_normal = ID2SYM(rb_intern("normal"));
13493  sym_sequential = ID2SYM(rb_intern("sequential"));
13494  sym_random = ID2SYM(rb_intern("random"));
13495  sym_willneed = ID2SYM(rb_intern("willneed"));
13496  sym_dontneed = ID2SYM(rb_intern("dontneed"));
13497  sym_noreuse = ID2SYM(rb_intern("noreuse"));
13498  sym_SET = ID2SYM(rb_intern("SET"));
13499  sym_CUR = ID2SYM(rb_intern("CUR"));
13500  sym_END = ID2SYM(rb_intern("END"));
13501 #ifdef SEEK_DATA
13502  sym_DATA = ID2SYM(rb_intern("DATA"));
13503 #endif
13504 #ifdef SEEK_HOLE
13505  sym_HOLE = ID2SYM(rb_intern("HOLE"));
13506 #endif
13507  sym_wait_readable = ID2SYM(rb_intern("wait_readable"));
13508  sym_wait_writable = ID2SYM(rb_intern("wait_writable"));
13509 }
13510 
13511 #include "io.rbinc"
13512 
13513 void
13515 {
13516  load_io();
13517 }
MODE_BINARY
#define MODE_BINARY(a, b)
rb_eEAGAIN
VALUE rb_eEAGAIN
Definition: error.c:54
strcmp
int strcmp(const char *, const char *)
rb_mutex_synchronize
VALUE rb_mutex_synchronize(VALUE mutex, VALUE(*func)(VALUE arg), VALUE arg)
Definition: thread_sync.c:522
rb_econv_asciicompat_encoding
const char * rb_econv_asciicompat_encoding(const char *encname)
Definition: transcode.c:1769
rb_str_end_with_asciichar
int rb_str_end_with_asciichar(VALUE str, int c)
Definition: io.c:7685
flock
Definition: rb_mjit_min_header-2.7.1.h:1401
rb_thread_fd_writable
int rb_thread_fd_writable(int)
Definition: thread.c:4048
rb_io_t::writeconv_pre_ecopts
VALUE writeconv_pre_ecopts
Definition: io.h:99
NUM2IOCTLREQ
#define NUM2IOCTLREQ(num)
Definition: io.c:9574
rb_get_kwargs
int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *values)
Definition: class.c:1886
READ_CHAR_PENDING_COUNT
#define READ_CHAR_PENDING_COUNT(fptr)
Definition: io.c:472
i
uint32_t i
Definition: rb_mjit_min_header-2.7.1.h:5464
foreach_arg::argc
int argc
Definition: io.c:10355
ISASCII
#define ISASCII(c)
Definition: ruby.h:2304
ID
unsigned long ID
Definition: ruby.h:103
rb_thread_call_without_gvl2
void * rb_thread_call_without_gvl2(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2)
Definition: thread.c:1581
rb_check_funcall
VALUE rb_check_funcall(VALUE, ID, int, const VALUE *)
Definition: vm_eval.c:505
rb_econv_prepare_options
int rb_econv_prepare_options(VALUE opthash, VALUE *ecopts, int ecflags)
Definition: transcode.c:2510
rb_define_class
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:649
econv_source_buffer_empty
@ econv_source_buffer_empty
Definition: encoding.h:301
rb_execarg_parent_end
void rb_execarg_parent_end(VALUE execarg_obj)
Definition: process.c:2855
obj
const VALUE VALUE obj
Definition: rb_mjit_min_header-2.7.1.h:5742
stat::st_size
off_t st_size
Definition: rb_mjit_min_header-2.7.1.h:2393
READ_CHAR_PENDING_PTR
#define READ_CHAR_PENDING_PTR(fptr)
Definition: io.c:473
chmod
int chmod(const char *__path, mode_t __mode)
TypedData_Make_Struct
#define TypedData_Make_Struct(klass, type, data_type, sval)
Definition: ruby.h:1244
Check_Type
#define Check_Type(v, t)
Definition: ruby.h:595
argf::binmode
int8_t binmode
Definition: io.c:213
TRUE
#define TRUE
Definition: nkf.h:175
stat
Definition: rb_mjit_min_header-2.7.1.h:2384
rb_check_convert_type_with_id
VALUE rb_check_convert_type_with_id(VALUE, int, const char *, ID)
Definition: object.c:2957
RSTRING_GETMEM
#define RSTRING_GETMEM(str, ptrvar, lenvar)
Definition: ruby.h:1018
long
#define long
Definition: rb_mjit_min_header-2.7.1.h:2880
RFILE
#define RFILE(obj)
Definition: ruby.h:1276
rb_thread_check_ints
void rb_thread_check_ints(void)
Definition: thread.c:1362
rb_include_module
void rb_include_module(VALUE klass, VALUE module)
Definition: class.c:869
S_ISREG
#define S_ISREG(m)
Definition: io.c:992
rb_io_t::writeconv_initialized
int writeconv_initialized
Definition: io.h:97
_IONBF
#define _IONBF
Definition: rb_mjit_min_header-2.7.1.h:1472
foreach_arg
Definition: io.c:10354
rb_assoc_new
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Definition: array.c:896
stdout
#define stdout
Definition: rb_mjit_min_header-2.7.1.h:1484
rb_str_new2
#define rb_str_new2
Definition: intern.h:903
getline_arg
Definition: stringio.c:1149
getline_arg::io
VALUE io
Definition: io.c:3349
rb_fd_term
void rb_fd_term(rb_fdset_t *)
rb_write_error_str
void rb_write_error_str(VALUE mesg)
Definition: io.c:7936
rb_enc_name
#define rb_enc_name(enc)
Definition: encoding.h:177
pipe
int pipe(int __fildes[2])
klass
VALUE klass
Definition: rb_mjit_min_header-2.7.1.h:13259
LONG_MAX
#define LONG_MAX
Definition: ruby.h:220
rb_cloexec_fcntl_dupfd
int rb_cloexec_fcntl_dupfd(int fd, int minfd)
Definition: io.c:419
select_args::write
VALUE write
Definition: io.c:9208
rb_io_t::write_lock
VALUE write_lock
Definition: io.h:101
rb_exc_new3
#define rb_exc_new3
Definition: intern.h:293
RB_PASS_CALLED_KEYWORDS
#define RB_PASS_CALLED_KEYWORDS
Definition: ruby.h:1980
env
#define env
rb_io_ungetc
VALUE rb_io_ungetc(VALUE io, VALUE c)
Definition: io.c:4315
MAX_REALLOC_GAP
#define MAX_REALLOC_GAP
Definition: io.c:2694
copy_stream_struct::close_dst
unsigned close_dst
Definition: io.c:10765
rb_mutex_owned_p
VALUE rb_mutex_owned_p(VALUE self)
Definition: thread_sync.c:345
MORE_CHAR_SUSPENDED
#define MORE_CHAR_SUSPENDED
Definition: io.c:2559
rb_io_getbyte
VALUE rb_io_getbyte(VALUE io)
Definition: io.c:4215
rb_enc_codepoint
#define rb_enc_codepoint(p, e, enc)
Definition: encoding.h:207
rb_hash_new
VALUE rb_hash_new(void)
Definition: hash.c:1523
rb_enc_mbclen
int rb_enc_mbclen(const char *p, const char *e, rb_encoding *enc)
Definition: encoding.c:1020
rb_gc_register_mark_object
void rb_gc_register_mark_object(VALUE obj)
Definition: gc.c:7065
rb_execarg_run_options
int rb_execarg_run_options(const struct rb_execarg *e, struct rb_execarg *s, char *errmsg, size_t errmsg_buflen)
Definition: process.c:3392
rb_stderr_tty_p
int rb_stderr_tty_p(void)
Definition: io.c:7958
rb_define_module_under
VALUE rb_define_module_under(VALUE outer, const char *name)
Definition: class.c:797
rb_execarg_parent_start
void rb_execarg_parent_start(VALUE execarg_obj)
Definition: process.c:2816
ENFILE
#define ENFILE
Definition: rb_mjit_min_header-2.7.1.h:10965
rb_warn
void rb_warn(const char *fmt,...)
Definition: error.c:313
ENC_CODERANGE_VALID
#define ENC_CODERANGE_VALID
Definition: encoding.h:105
rb_str_buf_new
VALUE rb_str_buf_new(long)
Definition: string.c:1315
rb_block_given_p
int rb_block_given_p(void)
Determines if the current method is given a block.
Definition: eval.c:898
MBCLEN_NEEDMORE_LEN
#define MBCLEN_NEEDMORE_LEN(ret)
Definition: encoding.h:195
rb_warning
void rb_warning(const char *fmt,...)
Definition: error.c:334
SET_BINARY_MODE
#define SET_BINARY_MODE(fptr)
Definition: io.c:660
rb_funcallv_kw
VALUE rb_funcallv_kw(VALUE, ID, int, const VALUE *, int)
Definition: vm_eval.c:962
S_ISSOCK
#define S_ISSOCK(m)
Definition: rb_mjit_min_header-2.7.1.h:2453
io_encoding_set_args::fptr
rb_io_t * fptr
Definition: io.c:10188
rb_io_synchronized
void rb_io_synchronized(rb_io_t *fptr)
Definition: io.c:6356
rb_str_buf_cat_ascii
VALUE rb_str_buf_cat_ascii(VALUE, const char *)
Definition: string.c:2926
rb_io_oflags_fmode
int rb_io_oflags_fmode(int oflags)
Definition: io.c:5519
FMODE_TTY
#define FMODE_TTY
Definition: io.h:113
copy_stream_struct::dst_stat
struct stat dst_stat
Definition: io.c:10772
RB_IO_WAIT_WRITABLE
#define RB_IO_WAIT_WRITABLE
Definition: ruby.h:1931
rb_funcall
#define rb_funcall(recv, mid, argc,...)
Definition: rb_mjit_min_header-2.7.1.h:6585
rb_gc_force_recycle
void rb_gc_force_recycle(VALUE obj)
Definition: gc.c:7013
INT2FIX
#define INT2FIX(i)
Definition: ruby.h:263
n
const char size_t n
Definition: rb_mjit_min_header-2.7.1.h:5456
NEED_WRITECONV
#define NEED_WRITECONV(fptr)
Definition: io.c:655
ENCINDEX_UTF_16BE
#define ENCINDEX_UTF_16BE
Definition: encindex.h:45
strchr
char * strchr(char *, char)
dup3
int dup3(int __fildes, int __fildes2, int flags)
next_argv
#define next_argv()
Definition: io.c:8581
copy_stream_struct::total
off_t total
Definition: io.c:10767
rp
#define rp(obj)
Definition: internal.h:1435
copy_stream_struct::error_no
int error_no
Definition: io.c:10766
rb_file_open_str
VALUE rb_file_open_str(VALUE fname, const char *modestr)
Definition: io.c:6252
select_args::except
VALUE except
Definition: io.c:9208
rb_get_argv
VALUE rb_get_argv(void)
Definition: io.c:12893
rb_enc_uint_chr
VALUE rb_enc_uint_chr(unsigned int code, rb_encoding *enc)
Definition: numeric.c:3375
F_DUPFD_CLOEXEC
#define F_DUPFD_CLOEXEC
Definition: win32.h:609
st
enum ruby_tag_type st
Definition: rb_mjit_min_header-2.7.1.h:11116
O_CLOEXEC
#define O_CLOEXEC
Definition: dir.c:28
RSTRING_PTR
#define RSTRING_PTR(str)
Definition: ruby.h:1009
rb_str_substr
VALUE rb_str_substr(VALUE, long, long)
Definition: string.c:2584
rb_w32_write_console
long rb_w32_write_console(uintptr_t, int)
Definition: win32.c:7225
rb_io_check_io
VALUE rb_io_check_io(VALUE io)
Definition: io.c:739
NUM2LONG
#define NUM2LONG(x)
Definition: ruby.h:679
off_t
#define off_t
Definition: io.c:83
rb_attr_get
VALUE rb_attr_get(VALUE, ID)
Definition: variable.c:1084
rb_io_t::pathv
VALUE pathv
Definition: io.h:72
O_NONBLOCK
#define O_NONBLOCK
Definition: win32.h:611
rb_str_new_cstr
#define rb_str_new_cstr(str)
Definition: rb_mjit_min_header-2.7.1.h:6117
rb_io_addstr
VALUE rb_io_addstr(VALUE io, VALUE str)
Definition: io.c:1843
rb_econv_str_convert
VALUE rb_econv_str_convert(rb_econv_t *ec, VALUE src, int flags)
Definition: transcode.c:1860
rb_class_new_instance_kw
VALUE rb_class_new_instance_kw(int, const VALUE *, VALUE, int)
Definition: object.c:1931
rb_fork_async_signal_safe
rb_pid_t rb_fork_async_signal_safe(int *status, int(*chfunc)(void *, char *, size_t), void *charg, VALUE fds, char *errmsg, size_t errmsg_buflen)
rb_hash_aref
VALUE rb_hash_aref(VALUE hash, VALUE key)
Definition: hash.c:2032
EINVAL
#define EINVAL
Definition: rb_mjit_min_header-2.7.1.h:10964
ARGF_block_call
#define ARGF_block_call(mid, argc, argv, func, argf)
Definition: io.c:12402
rb_utf8_encindex
int rb_utf8_encindex(void)
Definition: encoding.c:1334
RB_WAITFD_IN
#define RB_WAITFD_IN
Definition: io.h:51
rb_write_error
void rb_write_error(const char *mesg)
Definition: io.c:7930
rb_io_buffer_t
struct rb_io_buffer_t rb_io_buffer_t
Definition: io.h:64
bufread_arg
Definition: io.c:2466
rb_default_external_encoding
rb_encoding * rb_default_external_encoding(void)
Definition: encoding.c:1427
rb_gvar_readonly_setter
void rb_gvar_readonly_setter(VALUE v, ID id, VALUE *_)
Definition: variable.c:412
VALUE
unsigned long VALUE
Definition: ruby.h:102
rb_obj_as_string
VALUE rb_obj_as_string(VALUE)
Definition: string.c:1440
rb_io_t::finalize
void(* finalize)(struct rb_io_t *, int)
Definition: io.h:73
rb_eArgError
VALUE rb_eArgError
Definition: error.c:923
encoding.h
ruby_verbose
#define ruby_verbose
Definition: ruby.h:1925
rb_io_get_io
VALUE rb_io_get_io(VALUE io)
Definition: io.c:733
ZALLOC
#define ZALLOC(type)
Definition: ruby.h:1666
ONIGENC_CONSTRUCT_MBCLEN_CHARFOUND
#define ONIGENC_CONSTRUCT_MBCLEN_CHARFOUND(n)
Definition: onigmo.h:345
FMODE_TRUNC
#define FMODE_TRUNC
Definition: io.h:119
getline_arg::limit
long limit
Definition: stringio.c:1151
ARGF_GENERIC_INPUT_P
#define ARGF_GENERIC_INPUT_P()
Definition: io.c:8582
RB_TYPE_P
#define RB_TYPE_P(obj, type)
Definition: ruby.h:560
rb_intern_const
#define rb_intern_const(str)
Definition: ruby.h:1879
Init_IO_nonblock
void Init_IO_nonblock(void)
Definition: io.c:13514
io_tell
#define io_tell(fptr)
Definition: io.c:862
TYPE
#define TYPE(x)
Definition: ruby.h:554
rb_thread_current
VALUE rb_thread_current(void)
Definition: thread.c:2676
rb_fd_init
void rb_fd_init(rb_fdset_t *)
rb_enc_get
rb_encoding * rb_enc_get(VALUE obj)
Definition: encoding.c:872
rb_enc_asciicompat
#define rb_enc_asciicompat(enc)
Definition: encoding.h:245
do_write_retry
#define do_write_retry(code)
Definition: io.c:1039
S_IFMT
#define S_IFMT
Definition: rb_mjit_min_header-2.7.1.h:2424
rb_execarg_commandline
char * rb_execarg_commandline(const struct rb_execarg *eargp, VALUE *prog)
Definition: process.c:4324
rb_io_t::wbuf
rb_io_buffer_t wbuf
Definition: io.h:75
rb_enc_precise_mbclen
int rb_enc_precise_mbclen(const char *p, const char *e, rb_encoding *enc)
Definition: encoding.c:1032
rb_gc_for_fd
int rb_gc_for_fd(int err)
Definition: io.c:953
NEED_READCONV
#define NEED_READCONV(fptr)
Definition: io.c:654
rb_io_ascii8bit_binmode
VALUE rb_io_ascii8bit_binmode(VALUE io)
Definition: io.c:5380
rb_sys_fail_path
#define rb_sys_fail_path(path)
Definition: internal.h:1629
rb_bool_expected
int rb_bool_expected(VALUE, const char *)
Definition: object.c:3112
id.h
EBADF
#define EBADF
Definition: rb_mjit_min_header-2.7.1.h:10951
SIGNED_VALUE
#define SIGNED_VALUE
Definition: ruby.h:104
rb_to_array_type
VALUE rb_to_array_type(VALUE ary)
Definition: array.c:902
rb_define_global_function
void rb_define_global_function(const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a global function.
Definition: class.c:1787
GetWriteIO
#define GetWriteIO(io)
Definition: io.c:464
EINPROGRESS
#define EINPROGRESS
Definition: win32.h:498
binwrite_arg::fptr
rb_io_t * fptr
Definition: io.c:1317
io_internal_write_struct
Definition: io.c:1002
rb_thread_sleep
void rb_thread_sleep(int)
Definition: thread.c:1385
rb_io_pwrite
#define rb_io_pwrite
Definition: io.c:5330
io_internal_read_struct::capa
size_t capa
Definition: io.c:999
UINT2NUM
#define UINT2NUM(x)
Definition: ruby.h:1610
rb_lastline_set
void rb_lastline_set(VALUE)
Definition: vm.c:1322
rb_inspect
VALUE rb_inspect(VALUE)
Convenient wrapper of Object::inspect.
Definition: object.c:551
rb_io_set_close_on_exec
#define rb_io_set_close_on_exec
Definition: io.c:4479
READ_DATA_BUFFERED
#define READ_DATA_BUFFERED(fptr)
Definition: io.c:469
rb_io_write
VALUE rb_io_write(VALUE io, VALUE str)
Definition: io.c:1804
arg
VALUE arg
Definition: rb_mjit_min_header-2.7.1.h:5601
IOV_MAX
#define IOV_MAX
Definition: rb_mjit_min_header-2.7.1.h:4089
rb_stdin
VALUE rb_stdin
Definition: io.c:184
rb_str_dup
VALUE rb_str_dup(VALUE)
Definition: string.c:1516
F_DUPFD
#define F_DUPFD
Definition: win32.h:602
argf::argv
VALUE argv
Definition: io.c:210
rb_str_cat2
#define rb_str_cat2
Definition: intern.h:912
rb_hash_lookup2
VALUE rb_hash_lookup2(VALUE hash, VALUE key, VALUE def)
Definition: hash.c:2045
rb_check_string_type
VALUE rb_check_string_type(VALUE)
Definition: string.c:2314
rb_io_gets_internal
VALUE rb_io_gets_internal(VALUE io)
Definition: io.c:3579
SEEK_CUR
#define SEEK_CUR
Definition: io.c:866
SHUT_WR
#define SHUT_WR
fclose
int fclose(FILE *)
copy_stream_struct::src_fd
int src_fd
Definition: io.c:10762
rb_fd_isset
int rb_fd_isset(int, const rb_fdset_t *)
rb_define_readonly_variable
void rb_define_readonly_variable(const char *, const VALUE *)
Definition: variable.c:505
rb_io_check_writable
void rb_io_check_writable(rb_io_t *fptr)
Definition: io.c:923
idTo_io
@ idTo_io
Definition: rb_mjit_min_header-2.7.1.h:8724
rb_mWaitReadable
VALUE rb_mWaitReadable
Definition: io.c:174
Qundef
#define Qundef
Definition: ruby.h:470
free
#define free(x)
Definition: io.c:47
rb_define_singleton_method
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
Definition: class.c:1755
rb_io_flush_raw
VALUE rb_io_flush_raw(VALUE io, int sync)
Definition: io.c:1864
rb_write_error2
void rb_write_error2(const char *mesg, long len)
Definition: io.c:7911
rb_str_modify
void rb_str_modify(VALUE)
Definition: string.c:2114
rb_define_method
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1551
ENC_CODERANGE_SET
#define ENC_CODERANGE_SET(obj, cr)
Definition: encoding.h:110
INT2NUM
#define INT2NUM(x)
Definition: ruby.h:1609
bufread_arg::fptr
rb_io_t * fptr
Definition: io.c:2469
rb_eIOError
VALUE rb_eIOError
Definition: io.c:173
rb_econv_convert
rb_econv_result_t rb_econv_convert(rb_econv_t *ec, const unsigned char **source_buffer_ptr, const unsigned char *source_buffer_end, unsigned char **destination_buffer_ptr, unsigned char *destination_buffer_end, int flags)
Definition: transcode.c:1429
rb_ary_shift
VALUE rb_ary_shift(VALUE ary)
Definition: array.c:1294
io_internal_read_struct::nonblock
int nonblock
Definition: io.c:997
ptr
struct RIMemo * ptr
Definition: debug.c:74
READ_DATA_PENDING_PTR
#define READ_DATA_PENDING_PTR(fptr)
Definition: io.c:468
int8_t
__int8_t int8_t
Definition: rb_mjit_min_header-2.7.1.h:1165
rb_io_eof
VALUE rb_io_eof(VALUE io)
Definition: io.c:2149
rb_str_new
#define rb_str_new(str, len)
Definition: rb_mjit_min_header-2.7.1.h:6116
rb_io_enc_t
struct rb_io_enc_t rb_io_enc_t
Definition: io.h:104
rb_str_setter
rb_gvar_setter_t rb_str_setter
Definition: intern.h:828
Qfalse
#define Qfalse
Definition: ruby.h:467
rb_hash_dup
VALUE rb_hash_dup(VALUE hash)
Definition: hash.c:1559
IO_CBUF_CAPA_MIN
#define IO_CBUF_CAPA_MIN
Definition: io.c:150
FMODE_DUPLEX
#define FMODE_DUPLEX
Definition: io.h:114
FilePathValue
#define FilePathValue(v)
Definition: ruby.h:624
rb_id2str
#define rb_id2str(id)
Definition: vm_backtrace.c:30
argf::last_lineno
long last_lineno
Definition: io.c:208
setvbuf
int setvbuf(FILE *__restrict, char *__restrict, int, size_t)
fchown
int fchown(int __fildes, uid_t __owner, gid_t __group)
dp
#define dp(v)
Definition: vm_debug.h:21
chown
int chown(const char *, int, int)
Definition: win32.c:4763
rb_io_t::fd
int fd
Definition: io.h:68
sysopen_struct::perm
mode_t perm
Definition: io.c:6007
rb_set_class_path
void rb_set_class_path(VALUE, VALUE, const char *)
Definition: variable.c:218
rb_scan_args_kw
int rb_scan_args_kw(int kw_flag, int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:2180
stdin
#define stdin
Definition: rb_mjit_min_header-2.7.1.h:1483
NULL
#define NULL
Definition: _sdbm.c:101
char
#define char
Definition: rb_mjit_min_header-2.7.1.h:2876
rb_waitpid
rb_pid_t rb_waitpid(rb_pid_t pid, int *status, int flags)
Definition: process.c:1213
SafeStringValue
#define SafeStringValue(v)
Definition: ruby.h:607
rb_thread_interrupted
int rb_thread_interrupted(VALUE thval)
Definition: thread.c:1379
FL_TEST
#define FL_TEST(x, f)
Definition: ruby.h:1353
rb_execarg::cmd
struct rb_execarg::@110::@112 cmd
PRIsVALUE
#define PRIsVALUE
Definition: ruby.h:166
select_args::read
VALUE read
Definition: io.c:9208
fcntl
int fcntl(int, int,...)
Definition: win32.c:4282
RBASIC_SET_CLASS
#define RBASIC_SET_CLASS(obj, cls)
Definition: internal.h:1988
rb_io_get_write_io
VALUE rb_io_get_write_io(VALUE io)
Definition: io.c:745
rb_readwrite_syserr_fail
void rb_readwrite_syserr_fail(enum rb_io_wait_readwrite writable, int n, const char *mesg)
Definition: io.c:12933
rb_enc_from_encoding
VALUE rb_enc_from_encoding(rb_encoding *encoding)
Definition: encoding.c:116
last
unsigned int last
Definition: nkf.c:4324
rb_io_t::rbuf
rb_io_buffer_t rbuf
Definition: io.h:75
rb_str_cat_conv_enc_opts
VALUE rb_str_cat_conv_enc_opts(VALUE newstr, long ofs, const char *ptr, long len, rb_encoding *from, int ecflags, VALUE ecopts)
Definition: string.c:943
rb_fatal
void rb_fatal(const char *fmt,...)
Definition: error.c:2720
rb_pid_t
#define rb_pid_t
Definition: rb_mjit_min_header-2.7.1.h:99
FIX2LONG
#define FIX2LONG(x)
Definition: ruby.h:394
ID2SYM
#define ID2SYM(x)
Definition: ruby.h:414
strlen
size_t strlen(const char *)
OBJ_FREEZE
#define OBJ_FREEZE(x)
Definition: ruby.h:1377
rb_eof_error
void rb_eof_error(void)
Definition: io.c:697
idMesg
@ idMesg
Definition: rb_mjit_min_header-2.7.1.h:8733
rb_str_locktmp
VALUE rb_str_locktmp(VALUE)
rb_find_encoding
rb_encoding * rb_find_encoding(VALUE enc)
Definition: encoding.c:252
off_t
__off_t off_t
Definition: rb_mjit_min_header-2.7.1.h:1317
rb_io_t::pid
rb_pid_t pid
Definition: io.h:70
rb_cFile
VALUE rb_cFile
Definition: file.c:159
FMODE_BINMODE
#define FMODE_BINMODE
Definition: io.h:111
rb_io_modestr_fmode
int rb_io_modestr_fmode(const char *modestr)
Definition: io.c:5465
freopen
FILE * freopen(const char *__restrict, const char *__restrict, FILE *__restrict)
rb_define_alias
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
Definition: class.c:1800
L
#define L(x)
Definition: asm.h:125
rb_f_p_arg
Definition: io.c:7812
rb_respond_to
int rb_respond_to(VALUE, ID)
Definition: vm_method.c:2190
RB_BLOCK_CALL_FUNC_ARGLIST
#define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)
Definition: ruby.h:1964
rb_protect
VALUE rb_protect(VALUE(*proc)(VALUE), VALUE data, int *pstate)
Protects a function call from potential global escapes from the function.
Definition: eval.c:1072
rb_io_check_readable
void rb_io_check_readable(rb_io_t *fptr)
Definition: io.c:899
rb_check_arity
#define rb_check_arity
Definition: intern.h:347
RUBY_FUNC_EXPORTED
#define RUBY_FUNC_EXPORTED
Definition: defines.h:391
rb_econv_check_error
void rb_econv_check_error(rb_econv_t *ec)
Definition: transcode.c:4224
ENCODING_MAXNAMELEN
#define ENCODING_MAXNAMELEN
Definition: encoding.h:64
RARRAY_LENINT
#define RARRAY_LENINT(ary)
Definition: ruby.h:1071
rb_str_locktmp_ensure
VALUE rb_str_locktmp_ensure(VALUE str, VALUE(*func)(VALUE), VALUE arg)
Definition: string.c:2685
IO_WBUF_CAPA_MIN
#define IO_WBUF_CAPA_MIN
Definition: io.c:152
rb_str_capacity
size_t rb_str_capacity(VALUE str)
Definition: string.c:712
ALLOC_N
#define ALLOC_N(type, n)
Definition: ruby.h:1663
MBCLEN_INVALID_P
#define MBCLEN_INVALID_P(ret)
Definition: encoding.h:193
argf::lineno
long lineno
Definition: io.c:209
rb_str_resize
VALUE rb_str_resize(VALUE, long)
Definition: string.c:2709
exc
const rb_iseq_t const VALUE exc
Definition: rb_mjit_min_header-2.7.1.h:13509
rb_cloexec_dup
int rb_cloexec_dup(int oldfd)
Definition: io.c:318
copy_stream_struct::th
VALUE th
Definition: io.c:10770
S_IFSOCK
#define S_IFSOCK
Definition: rb_mjit_min_header-2.7.1.h:2430
rb_fdset_t
Definition: rb_mjit_min_header-2.7.1.h:5705
RUBY_TYPED_DEFAULT_FREE
#define RUBY_TYPED_DEFAULT_FREE
Definition: ruby.h:1203
rb_io_t::rb_io_enc_t::ecflags
int ecflags
Definition: io.h:88
rb_raise
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2669
rb_io_fdopen
VALUE rb_io_fdopen(int fd, int oflags, const char *path)
Definition: io.c:8004
argf_call_arg
Definition: io.c:12122
mode_t
__mode_t mode_t
Definition: rb_mjit_min_header-2.7.1.h:1331
copy_stream_struct
Definition: io.c:10756
FMODE_SYNC
#define FMODE_SYNC
Definition: io.h:112
sysopen_struct
Definition: io.c:6004
rb_id_encoding
ID rb_id_encoding(void)
Definition: encoding.c:759
getuid
rb_uid_t getuid(void)
Definition: win32.c:2765
rb_str_tmp_frozen_acquire
VALUE rb_str_tmp_frozen_acquire(VALUE str)
Definition: string.c:1210
rb_ary_entry
VALUE rb_ary_entry(VALUE ary, long offset)
Definition: array.c:1512
rb_notimplement
void rb_notimplement(void)
Definition: error.c:2712
rb_usascii_str_new
#define rb_usascii_str_new(str, len)
Definition: rb_mjit_min_header-2.7.1.h:6118
T_FILE
#define T_FILE
Definition: ruby.h:534
WNOHANG
#define WNOHANG
Definition: win32.h:128
ruby_set_inplace_mode
void ruby_set_inplace_mode(const char *suffix)
Definition: io.c:12861
NUM2UINT
#define NUM2UINT(x)
Definition: ruby.h:716
rb_io_puts
VALUE rb_io_puts(int argc, const VALUE *argv, VALUE out)
Definition: io.c:7747
if
if((ID)(DISPID) nameid !=nameid)
Definition: win32ole.c:357
rb_io_extract_modeenc
void rb_io_extract_modeenc(VALUE *vmode_p, VALUE *vperm_p, VALUE opthash, int *oflags_p, int *fmode_p, convconfig_t *convconfig_p)
Definition: io.c:5871
void
void
Definition: rb_mjit_min_header-2.7.1.h:13278
_exit
void _exit(int __status) __attribute__((__noreturn__))
NUM2CHR
#define NUM2CHR(x)
Definition: ruby.h:1647
io_internal_read_struct::fd
int fd
Definition: io.c:996
rb_obj_class
VALUE rb_obj_class(VALUE)
Equivalent to Object#class in Ruby.
Definition: object.c:217
rb_io_flush
VALUE rb_io_flush(VALUE io)
Definition: io.c:1903
rb_fix_plus
VALUE rb_fix_plus(VALUE x, VALUE y)
Definition: numeric.c:3604
rb_io_ioctl
#define rb_io_ioctl
Definition: io.c:9883
rb_fdopen
FILE * rb_fdopen(int fd, const char *modestr)
Definition: io.c:6053
rb_str_new4
#define rb_str_new4
Definition: intern.h:905
rb_io_modestr_oflags
int rb_io_modestr_oflags(const char *modestr)
Definition: io.c:5595
rb_syserr_fail
void rb_syserr_fail(int e, const char *mesg)
Definition: error.c:2781
MODE_BTXMODE
#define MODE_BTXMODE(a, b, c, d, e, f)
Definition: io.c:1462
FMODE_READABLE
#define FMODE_READABLE
Definition: io.h:108
rb_ascii8bit_encoding
rb_encoding * rb_ascii8bit_encoding(void)
Definition: encoding.c:1316
ECONV_STATEFUL_DECORATOR_MASK
#define ECONV_STATEFUL_DECORATOR_MASK
Definition: encoding.h:407
strerror
RUBY_EXTERN char * strerror(int)
Definition: strerror.c:11
io_internal_write_struct::buf
const void * buf
Definition: io.c:1004
rb_econv_open_opts
rb_econv_t * rb_econv_open_opts(const char *source_encoding, const char *destination_encoding, int ecflags, VALUE ecopts)
Definition: transcode.c:2561
argf::encs
struct rb_io_enc_t encs
Definition: io.c:212
MBCLEN_CHARFOUND_LEN
#define MBCLEN_CHARFOUND_LEN(ret)
Definition: encoding.h:192
FMODE_PREP
#define FMODE_PREP
Definition: io.c:4482
Init_IO
void Init_IO(void)
Definition: io.c:13144
VM_UNREACHABLE
#define VM_UNREACHABLE(func)
Definition: vm_core.h:57
io_internal_write_struct::fd
int fd
Definition: io.c:1003
rb_thread_execute_interrupts
void rb_thread_execute_interrupts(VALUE th)
Definition: thread.c:2284
F_GETFD
#define F_GETFD
Definition: win32.h:603
RB_SCAN_ARGS_LAST_HASH_KEYWORDS
#define RB_SCAN_ARGS_LAST_HASH_KEYWORDS
Definition: ruby.h:1905
io_encoding_set_args::v1
VALUE v1
Definition: io.c:10189
rb_encoding
const typedef OnigEncodingType rb_encoding
Definition: encoding.h:115
ALLOCV_END
#define ALLOCV_END(v)
Definition: ruby.h:1750
rb_check_frozen
#define rb_check_frozen(obj)
Definition: intern.h:319
EMFILE
#define EMFILE
Definition: rb_mjit_min_header-2.7.1.h:10966
rb_io_t::writeconv
rb_econv_t * writeconv
Definition: io.h:95
select_args
Definition: io.c:9207
ESPIPE
#define ESPIPE
Definition: rb_mjit_min_header-2.7.1.h:10971
rb_io_set_write_io
VALUE rb_io_set_write_io(VALUE io, VALUE w)
Definition: io.c:756
rb_io_t::readconv
rb_econv_t * readconv
Definition: io.h:92
rb_enc_left_char_head
#define rb_enc_left_char_head(s, p, e, enc)
Definition: encoding.h:222
SHUT_RD
#define SHUT_RD
rb_cloexec_pipe
int rb_cloexec_pipe(int fildes[2])
Definition: io.c:378
rb_output_rs
VALUE rb_output_rs
Definition: io.c:189
rb_thread_io_blocking_region
VALUE rb_thread_io_blocking_region(rb_blocking_function_t *func, void *data1, int fd)
Definition: thread.c:1595
IOWAIT_SYSCALL
#define IOWAIT_SYSCALL
Definition: io.c:10825
IS_PREP_STDIO
#define IS_PREP_STDIO(f)
Definition: io.c:4483
rb_f_p_arg::argc
int argc
Definition: io.c:7813
list_head
Definition: rb_mjit_min_header-2.7.1.h:8980
rb_thread_wait_fd
void rb_thread_wait_fd(int)
Definition: thread.c:4042
binwrite_arg::length
long length
Definition: io.c:1320
write_arg::nosync
int nosync
Definition: io.c:1326
rb_convert_type_with_id
VALUE rb_convert_type_with_id(VALUE, int, const char *, ID)
Definition: object.c:2914
MORE_CHAR_FINISHED
#define MORE_CHAR_FINISHED
Definition: io.c:2560
ALLOCV_N
#define ALLOCV_N(type, v, n)
Definition: ruby.h:1749
rb_enc_from_index
rb_encoding * rb_enc_from_index(int index)
Definition: encoding.c:609
rb_frame_this_func
ID rb_frame_this_func(void)
The original name of the current method.
Definition: eval.c:1183
T_FIXNUM
#define T_FIXNUM
Definition: ruby.h:535
NUM2SIZET
#define NUM2SIZET(x)
Definition: ruby.h:769
fmode
#define fmode
FMODE_TEXTMODE
#define FMODE_TEXTMODE
Definition: io.h:120
rb_io_memsize
RUBY_FUNC_EXPORTED size_t rb_io_memsize(const rb_io_t *fptr)
Definition: io.c:4760
EWOULDBLOCK
#define EWOULDBLOCK
Definition: io.c:141
argf
Definition: io.c:206
rb_execarg_new
VALUE rb_execarg_new(int argc, const VALUE *argv, int accept_shell, int allow_exc_opt)
Definition: process.c:2633
RB_WAITFD_OUT
#define RB_WAITFD_OUT
Definition: io.h:53
pwrite
ssize_t pwrite(int __fd, const void *__buf, size_t __nbytes, off_t __offset)
rb_fd_set
void rb_fd_set(int, rb_fdset_t *)
rb_io_extract_encoding_option
int rb_io_extract_encoding_option(VALUE opt, rb_encoding **enc_p, rb_encoding **enc2_p, int *fmode_p)
Definition: io.c:5744
rb_io_t::cbuf
rb_io_buffer_t cbuf
Definition: io.h:93
rb_jump_tag
void rb_jump_tag(int tag)
Continues the exception caught by rb_protect() and rb_eval_string_protect().
Definition: eval.c:884
rb_file_open
VALUE rb_file_open(const char *fname, const char *modestr)
Definition: io.c:6259
RFile
Definition: ruby.h:1134
rb_method_basic_definition_p
#define rb_method_basic_definition_p(klass, mid)
Definition: rb_mjit_min_header-2.7.1.h:7905
FMODE_EXCL
#define FMODE_EXCL
Definition: io.h:118
sym
#define sym(x)
Definition: date_core.c:3716
rb_eEOFError
VALUE rb_eEOFError
Definition: io.c:172
rb_check_to_integer
VALUE rb_check_to_integer(VALUE, const char *)
Tries to convert val into Integer.
Definition: object.c:2999
argf_call_arg::argf
VALUE argf
Definition: io.c:12125
rb_io_check_byte_readable
void rb_io_check_byte_readable(rb_io_t *fptr)
Definition: io.c:890
rb_pipe
int rb_pipe(int *pipes)
Definition: io.c:6369
sysopen_struct::oflags
int oflags
Definition: io.c:6006
ruby_strtoul
unsigned long ruby_strtoul(const char *str, char **endptr, int base)
Definition: util.c:130
ECONV_UNIVERSAL_NEWLINE_DECORATOR
#define ECONV_UNIVERSAL_NEWLINE_DECORATOR
Definition: encoding.h:402
rb_p
void rb_p(VALUE obj)
Definition: io.c:7798
econv_incomplete_input
@ econv_incomplete_input
Definition: encoding.h:304
rb_hash_lookup
VALUE rb_hash_lookup(VALUE hash, VALUE key)
Definition: hash.c:2058
FOREACH_ARGF
#define FOREACH_ARGF()
Definition: io.c:12389
ECONV_NEWLINE_DECORATOR_READ_MASK
#define ECONV_NEWLINE_DECORATOR_READ_MASK
Definition: encoding.h:400
rb_ary_push
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:1195
rb_execarg_get
struct rb_execarg * rb_execarg_get(VALUE execarg_obj)
Definition: process.c:2608
rb_io_fptr_finalize_internal
void rb_io_fptr_finalize_internal(void *ptr)
Definition: io.c:4730
rb_io_printf
VALUE rb_io_printf(int argc, const VALUE *argv, VALUE out)
Definition: io.c:7505
SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2
#define SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags)
Definition: io.c:662
FMODE_SETENC_BY_BOM
#define FMODE_SETENC_BY_BOM
Definition: io.h:122
rb_cloexec_dup2
int rb_cloexec_dup2(int oldfd, int newfd)
Definition: io.c:325
cnt
rb_atomic_t cnt[RUBY_NSIG]
Definition: signal.c:503
rb_econv_binmode
void rb_econv_binmode(rb_econv_t *ec)
Definition: transcode.c:1925
rb_obj_freeze
VALUE rb_obj_freeze(VALUE)
Make the object unmodifiable.
Definition: object.c:1080
io_seek
#define io_seek(fptr, ofs, whence)
Definition: io.c:861
fsync
int fsync(int __fd)
rb_enc_mbminlen
#define rb_enc_mbminlen(enc)
Definition: encoding.h:180
term
const char term
Definition: id.c:37
dup
int dup(int __fildes)
vm_core.h
RUBY_UBF_IO
#define RUBY_UBF_IO
Definition: intern.h:945
io_internal_read_struct
Definition: io.c:995
econv_invalid_byte_sequence
@ econv_invalid_byte_sequence
Definition: encoding.h:298
SSIZE_MAX
#define SSIZE_MAX
Definition: ruby.h:323
rb_sys_fail
void rb_sys_fail(const char *mesg)
Definition: error.c:2793
rb_eTypeError
VALUE rb_eTypeError
Definition: error.c:922
unlink
int unlink(const char *__path)
rb_ary_concat
VALUE rb_ary_concat(VALUE x, VALUE y)
Definition: array.c:4069
rb_econv_putbackable
int rb_econv_putbackable(rb_econv_t *ec)
Definition: transcode.c:1725
argf::current_file
VALUE current_file
Definition: io.c:207
rb_stderr
VALUE rb_stderr
Definition: io.c:184
rb_io_t
struct rb_io_t rb_io_t
rb_update_max_fd
void rb_update_max_fd(int fd)
Definition: io.c:218
rb_io_read_check
void rb_io_read_check(rb_io_t *fptr)
Definition: io.c:944
ALLOC
#define ALLOC(type)
Definition: ruby.h:1664
rb_time_interval
struct timeval rb_time_interval(VALUE num)
Definition: time.c:2669
rb_intern
#define rb_intern(str)
rb_f_sprintf
VALUE rb_f_sprintf(int, const VALUE *)
Definition: sprintf.c:198
rb_maygvl_fd_fix_cloexec
void rb_maygvl_fd_fix_cloexec(int fd)
Definition: io.c:245
rb_eRuntimeError
VALUE rb_eRuntimeError
Definition: error.c:920
rb_thread_call_without_gvl
void * rb_thread_call_without_gvl(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2)
size_t
long unsigned int size_t
Definition: rb_mjit_min_header-2.7.1.h:666
rb_thread_fd_select
int rb_thread_fd_select(int, rb_fdset_t *, rb_fdset_t *, rb_fdset_t *, struct timeval *)
Definition: thread.c:4067
rb_execarg::envp_str
VALUE envp_str
Definition: internal.h:2037
RETURN_ENUMERATOR
#define RETURN_ENUMERATOR(obj, argc, argv)
Definition: intern.h:279
ENOSYS
#define ENOSYS
Definition: rb_mjit_min_header-2.7.1.h:11022
ECONV_AFTER_OUTPUT
#define ECONV_AFTER_OUTPUT
Definition: encoding.h:416
RARRAY_AREF
#define RARRAY_AREF(a, i)
Definition: ruby.h:1101
STRNCASECMP
#define STRNCASECMP(s1, s2, n)
Definition: ruby.h:2324
write_arg::io
VALUE io
Definition: io.c:1324
rb_uninterruptible
VALUE rb_uninterruptible(VALUE(*b_proc)(VALUE), VALUE data)
Definition: thread.c:5554
copy_stream_struct::src
VALUE src
Definition: io.c:10757
fdopen
int int int int int int int int char char int int int int int int int int int char char int int int int int int int int FILE * fdopen(int, const char *)
FMODE_READWRITE
#define FMODE_READWRITE
Definition: io.h:110
size
int size
Definition: encoding.c:58
EXDEV
#define EXDEV
Definition: rb_mjit_min_header-2.7.1.h:10960
isatty
int isatty(int __fildes)
rb_str_set_len
void rb_str_set_len(VALUE, long)
Definition: string.c:2692
FALSE
#define FALSE
Definition: nkf.h:174
EINTR
#define EINTR
Definition: rb_mjit_min_header-2.7.1.h:10946
rb_f_p_arg::argv
VALUE * argv
Definition: io.c:7814
argf::init_p
int8_t init_p
Definition: io.c:213
FIXNUM_P
#define FIXNUM_P(f)
Definition: ruby.h:396
ENCINDEX_UTF_32LE
#define ENCINDEX_UTF_32LE
Definition: encindex.h:48
ECONV_NEWLINE_DECORATOR_MASK
#define ECONV_NEWLINE_DECORATOR_MASK
Definition: encoding.h:399
rb_io_set_nonblock
void rb_io_set_nonblock(rb_io_t *fptr)
Definition: io.c:2782
rb_fd_select
int rb_fd_select(int, rb_fdset_t *, rb_fdset_t *, rb_fdset_t *, struct timeval *)
rb_gc
void rb_gc(void)
Definition: gc.c:8681
rb_io_check_initialized
void rb_io_check_initialized(rb_io_t *fptr)
Definition: io.c:710
SEEK_END
#define SEEK_END
Definition: io.c:867
rb_eEWOULDBLOCK
VALUE rb_eEWOULDBLOCK
Definition: error.c:55
rb_to_int
VALUE rb_to_int(VALUE)
Converts val into Integer.
Definition: object.c:3021
write
_ssize_t write(int __fd, const void *__buf, size_t __nbyte)
O_ACCMODE
#define O_ACCMODE
Definition: io.c:125
READ_DATA_PENDING
#define READ_DATA_PENDING(fptr)
Definition: io.c:466
rb_int_modulo
VALUE rb_int_modulo(VALUE x, VALUE y)
Definition: numeric.c:3886
iovec::iov_base
void * iov_base
Definition: win32.h:226
PIDT2NUM
#define PIDT2NUM(v)
Definition: ruby.h:354
MBCLEN_NEEDMORE_P
#define MBCLEN_NEEDMORE_P(ret)
Definition: encoding.h:194
rb_rs
VALUE rb_rs
Definition: io.c:188
list
struct rb_encoding_entry * list
Definition: encoding.c:56
SET_BINARY_MODE_WITH_SEEK_CUR
#define SET_BINARY_MODE_WITH_SEEK_CUR(fptr)
Definition: io.c:663
rb_check_to_int
VALUE rb_check_to_int(VALUE)
Tries to convert val into Integer.
Definition: object.c:3036
rb_execarg_extract_options
VALUE rb_execarg_extract_options(VALUE execarg_obj, VALUE opthash)
Definition: process.c:2279
MEMZERO
#define MEMZERO(p, type, n)
Definition: ruby.h:1752
READ_CHECK
#define READ_CHECK(fptr)
Definition: io.c:482
rb_output_fs
VALUE rb_output_fs
Definition: io.c:187
rb_str_new_frozen
VALUE rb_str_new_frozen(VALUE)
Definition: string.c:1203
argf::next_p
int8_t next_p
Definition: io.c:213
rb_econv_putback
void rb_econv_putback(rb_econv_t *ec, unsigned char *p, int n)
Definition: transcode.c:1736
bufread_arg::len
long len
Definition: io.c:2468
stat::st_mode
mode_t st_mode
Definition: rb_mjit_min_header-2.7.1.h:2388
rb_execarg::use_shell
unsigned use_shell
Definition: internal.h:2040
memcmp
int memcmp(const void *s1, const void *s2, size_t len)
Definition: memcmp.c:7
FD_CLOEXEC
#define FD_CLOEXEC
Definition: win32.h:610
ECONV_NEWLINE_DECORATOR_WRITE_MASK
#define ECONV_NEWLINE_DECORATOR_WRITE_MASK
Definition: encoding.h:401
READ_DATA_PENDING_COUNT
#define READ_DATA_PENDING_COUNT(fptr)
Definition: io.c:467
rb_error_arity
MJIT_STATIC void rb_error_arity(int argc, int min, int max)
Definition: vm_insnhelper.c:387
rb_define_variable
void rb_define_variable(const char *, VALUE *)
Definition: variable.c:499
foreach_arg::argv
VALUE * argv
Definition: io.c:10356
rb_default_rs
VALUE rb_default_rs
Definition: io.c:190
rb_default_internal_encoding
rb_encoding * rb_default_internal_encoding(void)
Definition: encoding.c:1512
rb_notify_fd_close
int rb_notify_fd_close(int fd, struct list_head *)
Definition: thread.c:2364
fileno
int fileno(FILE *)
rb_obj_dup
VALUE rb_obj_dup(VALUE)
Equivalent to Object#dup in Ruby.
Definition: object.c:420
ECONV_ERROR_HANDLER_MASK
#define ECONV_ERROR_HANDLER_MASK
Definition: encoding.h:392
rb_io_close
VALUE rb_io_close(VALUE io)
Definition: io.c:4820
convconfig_t
struct rb_io_enc_t convconfig_t
Definition: io.c:5812
CONST_ID
#define CONST_ID(var, str)
Definition: ruby.h:1841
io_encoding_set_args::opt
VALUE opt
Definition: io.c:10191
fwrite
size_t fwrite(const void *__restrict, size_t _size, size_t _n, FILE *)
fstat
int fstat(int __fd, struct stat *__sbuf)
ENCINDEX_UTF_16LE
#define ENCINDEX_UTF_16LE
Definition: encindex.h:46
StringValueCStr
#define StringValueCStr(v)
Definition: ruby.h:604
O_BINARY
#define O_BINARY
Definition: _sdbm.c:87
rb_f_syscall
#define rb_f_syscall
Definition: io.c:10107
ENC_CODERANGE_BROKEN
#define ENC_CODERANGE_BROKEN
Definition: encoding.h:106
rb_check_array_type
VALUE rb_check_array_type(VALUE ary)
Definition: array.c:909
rb_econv_close
void rb_econv_close(rb_econv_t *ec)
Definition: transcode.c:1685
write_arg::str
VALUE str
Definition: io.c:1325
rb_yield_values2
VALUE rb_yield_values2(int n, const VALUE *argv)
Definition: vm_eval.c:1271
path
VALUE path
Definition: rb_mjit_min_header-2.7.1.h:7353
copy_stream_struct::notimp
const char * notimp
Definition: io.c:10769
rb_to_encoding_index
int rb_to_encoding_index(VALUE enc)
Definition: encoding.c:197
EPERM
#define EPERM
Definition: _sdbm.c:92
EOF
#define EOF
Definition: vsnprintf.c:203
foreach_arg::io
VALUE io
Definition: io.c:10357
memchr
void * memchr(const void *, int, size_t)
RARRAY_CONST_PTR
#define RARRAY_CONST_PTR(a)
Definition: ruby.h:1072
rb_lastline_get
VALUE rb_lastline_get(void)
Definition: vm.c:1316
BUFSIZ
#define BUFSIZ
Definition: rb_mjit_min_header-2.7.1.h:1474
rb_close_before_exec
void rb_close_before_exec(int lowfd, int maxhint, VALUE noclose_fds)
NUM2MODET
#define NUM2MODET(v)
Definition: ruby.h:372
rb_eNotImpError
VALUE rb_eNotImpError
Definition: error.c:932
fchmod
int fchmod(int fd, int mode)
Definition: win32.c:7638
CLASS_OF
#define CLASS_OF(v)
Definition: ruby.h:484
rb_io_wait_readable
int rb_io_wait_readable(int f)
Definition: io.c:1204
rb_obj_method_arity
int rb_obj_method_arity(VALUE, ID)
Definition: proc.c:2640
rb_io_t::writeconv_asciicompat
VALUE writeconv_asciicompat
Definition: io.h:96
rb_w32_get_osfhandle
SOCKET rb_w32_get_osfhandle(int)
Definition: win32.c:1078
rb_class_new
VALUE rb_class_new(VALUE super)
Creates a new class.
Definition: class.c:241
copy_stream_struct::src_stat
struct stat src_stat
Definition: io.c:10771
dup2
RUBY_EXTERN int dup2(int, int)
Definition: dup2.c:27
MBCLEN_CHARFOUND_P
#define MBCLEN_CHARFOUND_P(ret)
Definition: encoding.h:191
rb_io_wait_readwrite
rb_io_wait_readwrite
Definition: ruby.h:1929
rb_thread_schedule
void rb_thread_schedule(void)
Definition: thread.c:1408
RARRAY_LEN
#define RARRAY_LEN(a)
Definition: ruby.h:1070
ioctl
int ioctl(int, int,...)
Definition: win32.c:2811
no_exception_p
#define no_exception_p(opts)
Definition: io.c:2803
rb_io_t::lineno
int lineno
Definition: io.h:71
rb_scan_args
#define rb_scan_args(argc, argvp, fmt,...)
Definition: rb_mjit_min_header-2.7.1.h:6372
Init_File
void Init_File(void)
Definition: file.c:6435
rb_ary_new4
#define rb_ary_new4
Definition: intern.h:105
rb_check_hash_type
VALUE rb_check_hash_type(VALUE hash)
Definition: hash.c:1847
rb_cObject
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:2010
iovec
Definition: win32.h:225
bufread_arg::str_ptr
char * str_ptr
Definition: io.c:2467
rb_ary_new2
#define rb_ary_new2
Definition: intern.h:103
buf
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:4322
rb_exc_raise
void rb_exc_raise(VALUE mesg)
Raises an exception in the current thread.
Definition: eval.c:668
rb_io_bufwrite
ssize_t rb_io_bufwrite(VALUE io, const void *buf, size_t size)
Definition: io.c:1549
T_BIGNUM
#define T_BIGNUM
Definition: ruby.h:533
rb_syserr_fail_path
#define rb_syserr_fail_path(err, path)
Definition: internal.h:1630
rb_stdout
VALUE rb_stdout
Definition: io.c:184
rb_thread_atfork
void rb_thread_atfork(void)
Definition: thread.c:4548
IO_RBUF_CAPA_FOR
#define IO_RBUF_CAPA_FOR(fptr)
Definition: io.c:151
seek_arg
Definition: io.c:10506
rb_str_append
VALUE rb_str_append(VALUE, VALUE)
Definition: string.c:2965
F_SETFD
#define F_SETFD
Definition: win32.h:604
rb_enc_str_coderange
int rb_enc_str_coderange(VALUE)
Definition: string.c:657
pipe2
int pipe2(int __fildes[2], int flags)
rb_bug
void rb_bug(const char *fmt,...)
Definition: error.c:634
StringValue
use StringValue() instead")))
rb_io_t::rb_io_enc_t::ecopts
VALUE ecopts
Definition: io.h:89
getline_arg::chomp
unsigned int chomp
Definition: stringio.c:1152
internal.h
OBJ_INIT_COPY
#define OBJ_INIT_COPY(obj, orig)
Definition: intern.h:331
rb_to_encoding
rb_encoding * rb_to_encoding(VALUE enc)
Definition: encoding.c:245
error
const rb_iseq_t const char * error
Definition: rb_mjit_min_header-2.7.1.h:13511
T_ARRAY
#define T_ARRAY
Definition: ruby.h:530
select_args::timeout
struct timeval * timeout
Definition: io.c:9209
rb_mKernel
RUBY_EXTERN VALUE rb_mKernel
Definition: ruby.h:1998
finish_writeconv_arg::noalloc
int noalloc
Definition: io.c:4551
argv
char ** argv
Definition: ruby.c:223
f
#define f
io_internal_read_struct::buf
void * buf
Definition: io.c:998
F_SETFL
#define F_SETFL
Definition: win32.h:608
rb_io_t::mode
int mode
Definition: io.h:69
binwrite_arg
Definition: io.c:1316
STATIC_ASSERT
#define STATIC_ASSERT(name, expr)
Definition: internal.h:230
rb_define_global_const
void rb_define_global_const(const char *, VALUE)
Definition: variable.c:2892
iovec::iov_len
size_t iov_len
Definition: win32.h:227
rb_io_taint_check
VALUE rb_io_taint_check(VALUE io)
Definition: io.c:703
UNREACHABLE
#define UNREACHABLE
Definition: ruby.h:63
ENCODING_GET
#define ENCODING_GET(obj)
Definition: encoding.h:62
rb_warn_deprecated
void rb_warn_deprecated(const char *fmt, const char *suggest,...)
Definition: error.c:364
rb_sprintf
VALUE rb_sprintf(const char *format,...)
Definition: sprintf.c:1197
FIX2UINT
#define FIX2UINT(x)
Definition: ruby.h:718
ioctl_arg
#define ioctl_arg
Definition: wait.c:32
rb_execarg_setenv
void rb_execarg_setenv(VALUE execarg_obj, VALUE env)
Definition: process.c:2646
FMODE_APPEND
#define FMODE_APPEND
Definition: io.h:115
rb_execarg::sh
struct rb_execarg::@110::@111 sh
argf_call_arg::argc
int argc
Definition: io.c:12123
_IOFBF
#define _IOFBF
Definition: rb_mjit_min_header-2.7.1.h:1470
rb_io_read_pending
int rb_io_read_pending(rb_io_t *fptr)
Definition: io.c:935
strrchr
char * strrchr(const char *, const char)
T_NIL
#define T_NIL
Definition: ruby.h:522
timeval
Definition: missing.h:53
rb_freopen
int rb_freopen(VALUE fname, const char *mode, FILE *file)
Definition: file.c:693
argf_call_arg::argv
VALUE * argv
Definition: io.c:12124
rb_obj_alloc
VALUE rb_obj_alloc(VALUE)
Allocates an instance of klass.
Definition: object.c:1895
str
char str[HTML_ESCAPE_MAX_LEN+1]
Definition: escape.c:18
cc
const struct rb_call_cache * cc
Definition: rb_mjit_min_header-2.7.1.h:13233
rb_execarg
Definition: internal.h:2024
ssize_t
_ssize_t ssize_t
Definition: rb_mjit_min_header-2.7.1.h:1329
close
int close(int __fildes)
rb_enc_find_index
int rb_enc_find_index(const char *name)
Definition: encoding.c:693
rb_io_t::stdio_file
FILE * stdio_file
Definition: io.h:67
fdatasync
int fdatasync(int __fd)
io_encoding_set_args::v2
VALUE v2
Definition: io.c:10190
binwrite_arg::str
VALUE str
Definition: io.c:1318
rb_readwrite_sys_fail
void rb_readwrite_sys_fail(enum rb_io_wait_readwrite writable, const char *mesg)
Definition: io.c:12927
RUBY_TYPED_FREE_IMMEDIATELY
#define RUBY_TYPED_FREE_IMMEDIATELY
Definition: ruby.h:1207
rb_fd_fix_cloexec
void rb_fd_fix_cloexec(int fd)
Definition: io.c:268
rb_last_status_clear
void rb_last_status_clear(void)
Definition: process.c:554
PREP_STDIO_NAME
#define PREP_STDIO_NAME(f)
Definition: io.c:4484
memset
void * memset(void *, int, size_t)
ARGVSTR2ARGV
#define ARGVSTR2ARGV(argv_str)
Definition: internal.h:2074
rb_w32_set_nonblock
int rb_w32_set_nonblock(int)
Definition: win32.c:4390
ARGF_FORWARD
#define ARGF_FORWARD(argc, argv)
Definition: io.c:8584
ENC_CODERANGE_7BIT
#define ENC_CODERANGE_7BIT
Definition: encoding.h:104
rb_stdio_set_default_encoding
void rb_stdio_set_default_encoding(void)
Definition: io.c:11758
read
_ssize_t read(int __fd, void *__buf, size_t __nbyte)
rb_wait_for_single_fd
int rb_wait_for_single_fd(int fd, int events, struct timeval *tv)
Definition: thread.c:4276
rb_enc_ascget
int rb_enc_ascget(const char *p, const char *e, int *len, rb_encoding *enc)
Definition: encoding.c:1044
econv_finished
@ econv_finished
Definition: encoding.h:302
rb_io_sync
#define rb_io_sync
Definition: io.c:2253
rb_hash_aset
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
Definition: hash.c:2847
int
__inline__ int
Definition: rb_mjit_min_header-2.7.1.h:2839
rb_fstring_cstr
#define rb_fstring_cstr(str)
Definition: rb_mjit_min_header-2.7.1.h:7723
FMODE_CREATE
#define FMODE_CREATE
Definition: io.h:116
rb_w32_fd_is_text
char rb_w32_fd_is_text(int)
Definition: win32.c:7756
rb_str_encode_ospath
VALUE rb_str_encode_ospath(VALUE path)
Definition: file.c:236
rb_io_fptr_finalize
#define rb_io_fptr_finalize(fptr)
Definition: io.c:4757
NIL_P
#define NIL_P(v)
Definition: ruby.h:482
lseek
off_t lseek(int __fildes, off_t __offset, int __whence)
memcpy
void * memcpy(void *__restrict, const void *__restrict, size_t)
argf_of
#define argf_of(obj)
Definition: io.c:461
rb_str_modify_expand
void rb_str_modify_expand(VALUE, long)
Definition: string.c:2122
io.h
rb_str_tmp_frozen_release
void rb_str_tmp_frozen_release(VALUE str, VALUE tmp)
Definition: string.c:1217
argc
int argc
Definition: ruby.c:222
rb_io_gets
VALUE rb_io_gets(VALUE io)
Definition: io.c:3573
rb_enc_warn
void rb_enc_warn(rb_encoding *enc, const char *fmt,...)
Definition: error.c:323
ENOTSUP
#define ENOTSUP
Definition: rb_mjit_min_header-2.7.1.h:11059
rb_funcall3
#define rb_funcall3
Definition: ruby.h:1896
rb_exec_recursive
VALUE rb_exec_recursive(VALUE(*)(VALUE, VALUE, int), VALUE, VALUE)
Definition: thread.c:5075
rb_io_fsync
#define rb_io_fsync
Definition: io.c:2252
rb_sys_fail_str
void rb_sys_fail_str(VALUE mesg)
Definition: error.c:2799
argf::inplace
VALUE inplace
Definition: io.c:211
econv_undefined_conversion
@ econv_undefined_conversion
Definition: encoding.h:299
rb_define_const
void rb_define_const(VALUE, const char *, VALUE)
Definition: variable.c:2880
recur
#define recur(fmt)
Definition: date_strptime.c:152
ioctl_req_t
int ioctl_req_t
Definition: io.c:9573
rb_eSystemCallError
VALUE rb_eSystemCallError
Definition: error.c:941
err
int err
Definition: win32.c:135
seek_arg::mode
int mode
Definition: io.c:10509
rb_thread_to_be_killed
int rb_thread_to_be_killed(VALUE thread)
Definition: thread.c:2472
rb_mWaitWritable
VALUE rb_mWaitWritable
Definition: io.c:175
encindex.h
KEEPGVL
#define KEEPGVL
Definition: io.c:4775
rb_io_make_open_file
rb_io_t * rb_io_make_open_file(VALUE obj)
Definition: io.c:8080
rb_execarg_addopt
int rb_execarg_addopt(VALUE execarg_obj, VALUE key, VALUE val)
Definition: process.c:2013
NOFILE
#define NOFILE
Definition: io.c:97
shutdown
#define shutdown(a, b)
Definition: io.c:667
popen
FILE * popen(const char *, const char *)
memmove
#define memmove(dst, src, len)
Definition: rb_mjit_min_header-2.7.1.h:2848
rb_data_type_struct
Definition: ruby.h:1148
rb_io_fcntl
#define rb_io_fcntl
Definition: io.c:9977
MakeOpenFile
#define MakeOpenFile(obj, fp)
Definition: io.h:129
rb_execarg::invoke
union rb_execarg::@110 invoke
rb_gets
VALUE rb_gets(void)
Definition: io.c:8902
GetOpenFile
#define GetOpenFile(obj, fp)
Definition: io.h:127
rb_str_unlocktmp
VALUE rb_str_unlocktmp(VALUE)
Definition: string.c:2675
SEEK_SET
#define SEEK_SET
Definition: io.c:865
io_encoding_set_args
Definition: io.c:10187
v
int VALUE v
Definition: rb_mjit_min_header-2.7.1.h:12337
ENOMEM
#define ENOMEM
Definition: rb_mjit_min_header-2.7.1.h:10954
econv_destination_buffer_full
@ econv_destination_buffer_full
Definition: encoding.h:300
NEED_NEWLINE_DECORATOR_ON_WRITE
#define NEED_NEWLINE_DECORATOR_ON_WRITE(fptr)
Definition: io.c:507
rb_io_wait_writable
int rb_io_wait_writable(int f)
Definition: io.c:1228
rb_gc_mark
void rb_gc_mark(VALUE ptr)
Definition: gc.c:5214
ruby_sized_xfree
#define ruby_sized_xfree(ptr, size)
Definition: rb_mjit_min_header-2.7.1.h:7372
write_arg
Definition: io.c:1323
rb_io_t::rb_io_enc_t::enc
rb_encoding * enc
Definition: io.h:86
_
#define _(args)
Definition: dln.h:28
rb_iter_break_value
void rb_iter_break_value(VALUE val)
Definition: vm.c:1552
count
int count
Definition: encoding.c:57
Qtrue
#define Qtrue
Definition: ruby.h:468
rb_str_catf
VALUE rb_str_catf(VALUE str, const char *format,...)
Definition: sprintf.c:1237
errno
int errno
READ_CHAR_PENDING
#define READ_CHAR_PENDING(fptr)
Definition: io.c:471
NUM2OFFT
#define NUM2OFFT(x)
Definition: ruby.h:761
rb_rescue2
VALUE rb_rescue2(VALUE(*b_proc)(VALUE), VALUE data1, VALUE(*r_proc)(VALUE, VALUE), VALUE data2,...)
An equivalent of rescue clause.
Definition: eval.c:962
NEED_NEWLINE_DECORATOR_ON_READ
#define NEED_NEWLINE_DECORATOR_ON_READ(fptr)
Definition: io.c:506
rb_class_name
VALUE rb_class_name(VALUE)
Definition: variable.c:274
utf_prefix_len
@ utf_prefix_len
Definition: io.c:5456
EAGAIN
#define EAGAIN
Definition: rb_mjit_min_header-2.7.1.h:10953
FMODE_WRITABLE
#define FMODE_WRITABLE
Definition: io.h:109
len
uint8_t len
Definition: escape.c:17
RB_IO_WAIT_READABLE
#define RB_IO_WAIT_READABLE
Definition: ruby.h:1930
SYMBOL_P
#define SYMBOL_P(x)
Definition: ruby.h:413
pclose
int pclose(FILE *)
rb_last_status_set
void rb_last_status_set(int status, rb_pid_t pid)
Definition: process.c:545
intptr_t
int intptr_t
Definition: win32.h:90
sync
void sync(void)
rb_eEINPROGRESS
VALUE rb_eEINPROGRESS
Definition: error.c:56
rb_io_check_char_readable
void rb_io_check_char_readable(rb_io_t *fptr)
Definition: io.c:871
rb_enumeratorize
VALUE rb_enumeratorize(VALUE obj, VALUE meth, int argc, const VALUE *argv)
Definition: enumerator.c:516
seek_arg::offset
VALUE offset
Definition: io.c:10508
pread
ssize_t pread(int __fd, void *__buf, size_t __nbytes, off_t __offset)
rb_io_print
VALUE rb_io_print(int argc, const VALUE *argv, VALUE out)
Definition: io.c:7576
rb_class_new_instance
VALUE rb_class_new_instance(int, const VALUE *, VALUE)
Allocates and initializes an instance of klass.
Definition: object.c:1955
MEMMOVE
#define MEMMOVE(p1, p2, type, n)
Definition: ruby.h:1754
copy_stream_struct::src_offset
off_t src_offset
Definition: io.c:10760
ruby_atomic.h
rb_mutex_allow_trap
void rb_mutex_allow_trap(VALUE self, int val)
Definition: thread_sync.c:545
rb_io_t::tied_io_for_writing
VALUE tied_io_for_writing
Definition: io.h:77
LONG2FIX
#define LONG2FIX(i)
Definition: ruby.h:265
rb_ivar_set
VALUE rb_ivar_set(VALUE, ID, VALUE)
Definition: variable.c:1300
T_STRING
#define T_STRING
Definition: ruby.h:528
DEFULT_IOCTL_NARG_LEN
#define DEFULT_IOCTL_NARG_LEN
Definition: io.c:9608
rb_atomic_t
int rb_atomic_t
Definition: ruby_atomic.h:124
FL_SINGLETON
#define FL_SINGLETON
Definition: ruby.h:1278
ATOMIC_CAS
#define ATOMIC_CAS(var, oldval, newval)
Definition: ruby_atomic.h:136
list_empty
#define list_empty(h)
Definition: rb_mjit_min_header-2.7.1.h:9035
rb_define_class_under
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:698
copy_stream_struct::dst_fd
int dst_fd
Definition: io.c:10763
rb_io_check_closed
void rb_io_check_closed(rb_io_t *fptr)
Definition: io.c:718
NEED_NEWLINE_DECORATOR_ON_READ_CHECK
#define NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr)
Definition: io.c:661
atexit
int atexit(void(*__func)(void))
stderr
#define stderr
Definition: rb_mjit_min_header-2.7.1.h:1485
ruby::backward::cxxanyargs::rb_define_hooked_variable
void rb_define_hooked_variable(const char *q, VALUE *w, type *e, void_type *r)
Define a function-backended global variable.
Definition: cxxanyargs.hpp:106
rb_econv_memsize
size_t rb_econv_memsize(rb_econv_t *ec)
Definition: transcode.c:1703
rb_str_encode
VALUE rb_str_encode(VALUE str, VALUE to, int ecflags, VALUE ecopts)
Definition: transcode.c:2870
copy_stream_struct::close_src
unsigned close_src
Definition: io.c:10764
rb_yield
VALUE rb_yield(VALUE)
Definition: vm_eval.c:1237
RB_INTEGER_TYPE_P
#define RB_INTEGER_TYPE_P(obj)
Definition: ruby_missing.h:15
rb_ensure
VALUE rb_ensure(VALUE(*b_proc)(VALUE), VALUE data1, VALUE(*e_proc)(VALUE), VALUE data2)
An equivalent to ensure clause.
Definition: eval.c:1115
finish_writeconv_arg
Definition: io.c:4549
rb_io_pread
#define rb_io_pread
Definition: io.c:5270
rb_io_t::encs
struct rb_io_t::rb_io_enc_t encs
binwrite_arg::ptr
const char * ptr
Definition: io.c:1319
_IOLBF
#define _IOLBF
Definition: rb_mjit_min_header-2.7.1.h:1471
ENCINDEX_UTF_32BE
#define ENCINDEX_UTF_32BE
Definition: encindex.h:47
rb_ary_new
VALUE rb_ary_new(void)
Definition: array.c:723
NEWOBJ_OF
#define NEWOBJ_OF(obj, type, klass, flags)
Definition: ruby.h:785
ruby::backward::cxxanyargs::rb_define_virtual_variable
void rb_define_virtual_variable(const char *q, type *w, void_type *e)
Define a function-backended global variable.
Definition: cxxanyargs.hpp:59
builtin.h
NUM2INT
#define NUM2INT(x)
Definition: ruby.h:715
Qnil
#define Qnil
Definition: ruby.h:469
finish_writeconv_arg::fptr
rb_io_t * fptr
Definition: io.c:4550
select_args::fdsets
rb_fdset_t fdsets[4]
Definition: io.c:9210
rb_fstring_lit
#define rb_fstring_lit(str)
Definition: internal.h:2128
seek_arg::io
VALUE io
Definition: io.c:10507
rb_str_buf_cat
#define rb_str_buf_cat
Definition: intern.h:910
copy_stream_struct::dst
VALUE dst
Definition: io.c:10758
rb_exec_async_signal_safe
int rb_exec_async_signal_safe(const struct rb_execarg *e, char *errmsg, size_t errmsg_buflen)
Definition: process.c:3523
thread.h
OFFT2NUM
#define OFFT2NUM(v)
Definition: ruby.h:285
rb_mEnumerable
VALUE rb_mEnumerable
Definition: enum.c:20
util.h
ECONV_DEFAULT_NEWLINE_DECORATOR
#define ECONV_DEFAULT_NEWLINE_DECORATOR
Definition: encoding.h:409
sysopen_struct::fname
VALUE fname
Definition: io.c:6005
rb_io_t
Definition: io.h:66
rb_str_chomp_string
VALUE rb_str_chomp_string(VALUE str, VALUE chomp)
Definition: string.c:8921
rb_eStandardError
VALUE rb_eStandardError
Definition: error.c:919
rb_econv_make_exception
VALUE rb_econv_make_exception(rb_econv_t *ec)
Definition: transcode.c:4218
RB_GC_GUARD
#define RB_GC_GUARD(v)
Definition: ruby.h:585
numberof
#define numberof(array)
Definition: etc.c:618
rb_reserved_fd_p
int rb_reserved_fd_p(int fd)
rb_str_coderange_scan_restartable
long rb_str_coderange_scan_restartable(const char *, const char *, rb_encoding *, int *)
Definition: string.c:567
rb_io_unbuffered
void rb_io_unbuffered(rb_io_t *fptr)
Definition: io.c:6363
rb_io_t::rb_io_enc_t::enc2
rb_encoding * enc2
Definition: io.h:87
rename
int rename(const char *, const char *)
rb_io_t::writeconv_pre_ecflags
int writeconv_pre_ecflags
Definition: io.h:98
RSTRING_LEN
#define RSTRING_LEN(str)
Definition: ruby.h:1005
rb_io_fdatasync
#define rb_io_fdatasync
Definition: io.c:2304
bom_prefix_len
@ bom_prefix_len
Definition: io.c:5455
MODE_BTMODE
#define MODE_BTMODE(a, b, c)
Definition: io.c:1459
rb_io_close_on_exec_p
#define rb_io_close_on_exec_p
Definition: io.c:4421
INT_MAX
#define INT_MAX
Definition: rb_mjit_min_header-2.7.1.h:4052
rb_any_to_s
VALUE rb_any_to_s(VALUE)
Default implementation of #to_s.
Definition: object.c:527
rb_io_binmode
VALUE rb_io_binmode(VALUE io)
Definition: io.c:5334
rb_mutex_new
VALUE rb_mutex_new(void)
Definition: thread_sync.c:165
DEFAULT_TEXTMODE
#define DEFAULT_TEXTMODE
Definition: io.c:653
rb_enc_str_new
VALUE rb_enc_str_new(const char *, long, rb_encoding *)
Definition: string.c:796
RUBY_PIPE_NONBLOCK_DEFAULT
#define RUBY_PIPE_NONBLOCK_DEFAULT
Definition: io.c:168
argf::filename
VALUE filename
Definition: io.c:207
rb_str_cat
VALUE rb_str_cat(VALUE, const char *, long)
Definition: string.c:2812
NEXT_ARGF_FORWARD
#define NEXT_ARGF_FORWARD(argc, argv)
Definition: io.c:8588
rb_io_stdio_file
FILE * rb_io_stdio_file(rb_io_t *fptr)
Definition: io.c:8032
rb_enc_associate
VALUE rb_enc_associate(VALUE obj, rb_encoding *enc)
Definition: encoding.c:866
copy_stream_struct::copy_length
off_t copy_length
Definition: io.c:10759
rb_define_alloc_func
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
rb_thread_fd_close
void rb_thread_fd_close(int)
Definition: thread.c:2386
RTEST
#define RTEST(v)
Definition: ruby.h:481
getline_arg::rs
VALUE rs
Definition: stringio.c:1150
ARGF
#define ARGF
Definition: io.c:462
SSIZET2NUM
#define SSIZET2NUM(v)
Definition: ruby.h:296
rb_econv_result_t
rb_econv_result_t
Definition: encoding.h:297
ECONV_PARTIAL_INPUT
#define ECONV_PARTIAL_INPUT
Definition: encoding.h:415
rb_cIO
VALUE rb_cIO
Definition: io.c:171
rb_cloexec_open
int rb_cloexec_open(const char *pathname, int flags, mode_t mode)
Definition: io.c:292
rb_io_ungetbyte
VALUE rb_io_ungetbyte(VALUE io, VALUE b)
Definition: io.c:4276
rb_mod_sys_fail_str
void rb_mod_sys_fail_str(VALUE mod, VALUE mesg)
Definition: error.c:2841
__sFILE
Definition: vsnprintf.c:169
rb_thread_call_with_gvl
RUBY_SYMBOL_EXPORT_BEGIN void * rb_thread_call_with_gvl(void *(*func)(void *), void *data1)
Definition: thread.c:1662
rb_usascii_encoding
rb_encoding * rb_usascii_encoding(void)
Definition: encoding.c:1340
rb_syserr_fail_str
void rb_syserr_fail_str(int e, VALUE mesg)
Definition: error.c:2787
RSTRING_END
#define RSTRING_END(str)
Definition: ruby.h:1013
copy_stream_struct::syserr
const char * syserr
Definition: io.c:10768
src
__inline__ const void *__restrict src
Definition: rb_mjit_min_header-2.7.1.h:2836
is_socket
#define is_socket(fd, path)
Definition: io.c:673
io_internal_write_struct::capa
size_t capa
Definition: io.c:1005
idGets
@ idGets
Definition: rb_mjit_min_header-2.7.1.h:8706
dln.h
name
const char * name
Definition: nkf.c:208
rb_econv_open_exc
VALUE rb_econv_open_exc(const char *senc, const char *denc, int ecflags)
Definition: transcode.c:2019
rb_execution_context_struct
Definition: vm_core.h:843
rb_fork_ruby
rb_pid_t rb_fork_ruby(int *status)
PRI_OFFT_PREFIX
#define PRI_OFFT_PREFIX
Definition: rb_mjit_min_header-2.7.1.h:145
rb_funcallv
#define rb_funcallv(recv, mid, argc, argv)
Definition: rb_mjit_min_header-2.7.1.h:7904