Ruby  2.0.0p451(2014-02-24revision45167)
io.c
Go to the documentation of this file.
1 /**********************************************************************
2 
3  io.c -
4 
5  $Author: nagachika $
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/ruby.h"
15 #include "ruby/io.h"
16 #include "ruby/thread.h"
17 #include "dln.h"
18 #include "internal.h"
19 #include "id.h"
20 #include <ctype.h>
21 #include <errno.h>
22 #include "ruby_atomic.h"
23 
24 #define free(x) xfree(x)
25 
26 #if defined(DOSISH) || defined(__CYGWIN__)
27 #include <io.h>
28 #endif
29 
30 #include <sys/types.h>
31 #if defined HAVE_NET_SOCKET_H
32 # include <net/socket.h>
33 #elif defined HAVE_SYS_SOCKET_H
34 # ifndef __native_client__
35 # include <sys/socket.h>
36 # endif
37 #endif
38 
39 #if defined(__BOW__) || defined(__CYGWIN__) || defined(_WIN32) || defined(__EMX__) || defined(__BEOS__) || defined(__HAIKU__)
40 # define NO_SAFE_RENAME
41 #endif
42 
43 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__sun) || defined(_nec_ews)
44 # define USE_SETVBUF
45 #endif
46 
47 #ifdef __QNXNTO__
48 #include "unix.h"
49 #endif
50 
51 #include <sys/types.h>
52 #if defined(HAVE_SYS_IOCTL_H) && !defined(_WIN32)
53 #include <sys/ioctl.h>
54 #endif
55 #if defined(__native_client__) && defined(NACL_NEWLIB)
56 # include "nacl/ioctl.h"
57 #endif
58 #if defined(HAVE_FCNTL_H) || defined(_WIN32)
59 #include <fcntl.h>
60 #elif defined(HAVE_SYS_FCNTL_H)
61 #include <sys/fcntl.h>
62 #endif
63 
64 #if !HAVE_OFF_T && !defined(off_t)
65 # define off_t long
66 #endif
67 
68 #include <sys/stat.h>
69 
70 /* EMX has sys/param.h, but.. */
71 #if defined(HAVE_SYS_PARAM_H) && !(defined(__EMX__) || defined(__HIUX_MPP__))
72 # include <sys/param.h>
73 #endif
74 
75 #if !defined NOFILE
76 # define NOFILE 64
77 #endif
78 
79 #ifdef HAVE_UNISTD_H
80 #include <unistd.h>
81 #endif
82 
83 #ifdef HAVE_SYSCALL_H
84 #include <syscall.h>
85 #elif defined HAVE_SYS_SYSCALL_H
86 #include <sys/syscall.h>
87 #endif
88 
89 #if defined(__BEOS__) || defined(__HAIKU__)
90 # ifndef NOFILE
91 # define NOFILE (OPEN_MAX)
92 # endif
93 #endif
94 
95 #include "ruby/util.h"
96 
97 #ifndef O_ACCMODE
98 #define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR)
99 #endif
100 
101 #if SIZEOF_OFF_T > SIZEOF_LONG && !defined(HAVE_LONG_LONG)
102 # error off_t is bigger than long, but you have no long long...
103 #endif
104 
105 #ifndef PIPE_BUF
106 # ifdef _POSIX_PIPE_BUF
107 # define PIPE_BUF _POSIX_PIPE_BUF
108 # else
109 # define PIPE_BUF 512 /* is this ok? */
110 # endif
111 #endif
112 
113 #if defined(HAVE___SYSCALL) && (defined(__APPLE__) || defined(__OpenBSD__))
114 /* Mac OS X and OpenBSD have __syscall but don't define it in headers */
115 off_t __syscall(quad_t number, ...);
116 #endif
117 
118 #define numberof(array) (int)(sizeof(array) / sizeof((array)[0]))
119 
120 #define IO_RBUF_CAPA_MIN 8192
121 #define IO_CBUF_CAPA_MIN (128*1024)
122 #define IO_RBUF_CAPA_FOR(fptr) (NEED_READCONV(fptr) ? IO_CBUF_CAPA_MIN : IO_RBUF_CAPA_MIN)
123 #define IO_WBUF_CAPA_MIN 8192
124 
125 /* define system APIs */
126 #ifdef _WIN32
127 #undef open
128 #define open rb_w32_uopen
129 #endif
130 
136 
138 VALUE rb_deferr; /* rescue VIM plugin */
140 
145 
146 static VALUE argf;
147 
151 
152 struct argf {
154  long last_lineno; /* $. */
155  long lineno;
157  char *inplace;
158  struct rb_io_enc_t encs;
160 };
161 
163 void
165 {
166  struct stat buf;
168 
169  if (fstat(fd, &buf) != 0 && errno == EBADF) {
170  rb_bug("rb_update_max_fd: invalid fd (%d) given.", fd);
171  }
172 
173  while (max_file_descriptor < afd) {
175  }
176 }
177 
178 void
180 {
181  /* MinGW don't have F_GETFD and FD_CLOEXEC. [ruby-core:40281] */
182 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
183  int flags, flags2, ret;
184  flags = fcntl(fd, F_GETFD); /* should not fail except EBADF. */
185  if (flags == -1) {
186  rb_bug("rb_maygvl_fd_fix_cloexec: fcntl(%d, F_GETFD) failed: %s", fd, strerror(errno));
187  }
188  if (fd <= 2)
189  flags2 = flags & ~FD_CLOEXEC; /* Clear CLOEXEC for standard file descriptors: 0, 1, 2. */
190  else
191  flags2 = flags | FD_CLOEXEC; /* Set CLOEXEC for non-standard file descriptors: 3, 4, 5, ... */
192  if (flags != flags2) {
193  ret = fcntl(fd, F_SETFD, flags2);
194  if (ret == -1) {
195  rb_bug("rb_maygvl_fd_fix_cloexec: fcntl(%d, F_SETFD, %d) failed: %s", fd, flags2, strerror(errno));
196  }
197  }
198 #endif
199 }
200 
201 void
203 {
205  rb_update_max_fd(fd);
206 }
207 
208 int
209 rb_cloexec_open(const char *pathname, int flags, mode_t mode)
210 {
211  int ret;
212 #ifdef O_CLOEXEC
213  /* O_CLOEXEC is available since Linux 2.6.23. Linux 2.6.18 silently ignore it. */
214  flags |= O_CLOEXEC;
215 #elif defined O_NOINHERIT
216  flags |= O_NOINHERIT;
217 #endif
218  ret = open(pathname, flags, mode);
219  if (ret == -1) return -1;
221  return ret;
222 }
223 
224 int
225 rb_cloexec_dup(int oldfd)
226 {
227  /* Don't allocate standard file descriptors: 0, 1, 2 */
228  return rb_cloexec_fcntl_dupfd(oldfd, 3);
229 }
230 
231 int
232 rb_cloexec_dup2(int oldfd, int newfd)
233 {
234  int ret;
235 
236  /* When oldfd == newfd, dup2 succeeds but dup3 fails with EINVAL.
237  * rb_cloexec_dup2 succeeds as dup2. */
238  if (oldfd == newfd) {
239  ret = newfd;
240  }
241  else {
242 #if defined(HAVE_DUP3) && defined(O_CLOEXEC)
243  static int try_dup3 = 1;
244  if (2 < newfd && try_dup3) {
245  ret = dup3(oldfd, newfd, O_CLOEXEC);
246  if (ret != -1)
247  return ret;
248  /* dup3 is available since Linux 2.6.27, glibc 2.9. */
249  if (errno == ENOSYS) {
250  try_dup3 = 0;
251  ret = dup2(oldfd, newfd);
252  }
253  }
254  else {
255  ret = dup2(oldfd, newfd);
256  }
257 #else
258  ret = dup2(oldfd, newfd);
259 # ifdef _WIN32
260  if (newfd >= 0 && newfd <= 2)
261  SetStdHandle(newfd == 0 ? STD_INPUT_HANDLE : newfd == 1 ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE, (HANDLE)rb_w32_get_osfhandle(newfd));
262 # endif
263 #endif
264  if (ret == -1) return -1;
265  }
267  return ret;
268 }
269 
270 int
271 rb_cloexec_pipe(int fildes[2])
272 {
273  int ret;
274 
275 #if defined(HAVE_PIPE2)
276  static int try_pipe2 = 1;
277  if (try_pipe2) {
278  ret = pipe2(fildes, O_CLOEXEC);
279  if (ret != -1)
280  return ret;
281  /* pipe2 is available since Linux 2.6.27, glibc 2.9. */
282  if (errno == ENOSYS) {
283  try_pipe2 = 0;
284  ret = pipe(fildes);
285  }
286  }
287  else {
288  ret = pipe(fildes);
289  }
290 #else
291  ret = pipe(fildes);
292 #endif
293  if (ret == -1) return -1;
294 #ifdef __CYGWIN__
295  if (ret == 0 && fildes[1] == -1) {
296  close(fildes[0]);
297  fildes[0] = -1;
298  errno = ENFILE;
299  return -1;
300  }
301 #endif
302  rb_maygvl_fd_fix_cloexec(fildes[0]);
303  rb_maygvl_fd_fix_cloexec(fildes[1]);
304  return ret;
305 }
306 
307 int
308 rb_cloexec_fcntl_dupfd(int fd, int minfd)
309 {
310  int ret;
311 
312 #if defined(HAVE_FCNTL) && defined(F_DUPFD_CLOEXEC) && defined(F_DUPFD)
313  static int try_dupfd_cloexec = 1;
314  if (try_dupfd_cloexec) {
315  ret = fcntl(fd, F_DUPFD_CLOEXEC, minfd);
316  if (ret != -1) {
317  if (ret <= 2)
319  return ret;
320  }
321  /* F_DUPFD_CLOEXEC is available since Linux 2.6.24. Linux 2.6.18 fails with EINVAL */
322  if (errno == EINVAL) {
323  ret = fcntl(fd, F_DUPFD, minfd);
324  if (ret != -1) {
325  try_dupfd_cloexec = 0;
326  }
327  }
328  }
329  else {
330  ret = fcntl(fd, F_DUPFD, minfd);
331  }
332 #elif defined(HAVE_FCNTL) && defined(F_DUPFD)
333  ret = fcntl(fd, F_DUPFD, minfd);
334 #elif defined(HAVE_DUP)
335  ret = dup(fd);
336  if (ret != -1 && ret < minfd) {
337  const int prev_fd = ret;
338  ret = rb_cloexec_fcntl_dupfd(fd, minfd);
339  close(prev_fd);
340  }
341  return ret;
342 #else
343 # error "dup() or fcntl(F_DUPFD) must be supported."
344 #endif
345  if (ret == -1) return -1;
347  return ret;
348 }
349 
350 #define argf_of(obj) (*(struct argf *)DATA_PTR(obj))
351 #define ARGF argf_of(argf)
352 
353 #ifdef _STDIO_USES_IOSTREAM /* GNU libc */
354 # ifdef _IO_fpos_t
355 # define STDIO_READ_DATA_PENDING(fp) ((fp)->_IO_read_ptr != (fp)->_IO_read_end)
356 # else
357 # define STDIO_READ_DATA_PENDING(fp) ((fp)->_gptr < (fp)->_egptr)
358 # endif
359 #elif defined(FILE_COUNT)
360 # define STDIO_READ_DATA_PENDING(fp) ((fp)->FILE_COUNT > 0)
361 #elif defined(FILE_READEND)
362 # define STDIO_READ_DATA_PENDING(fp) ((fp)->FILE_READPTR < (fp)->FILE_READEND)
363 #elif defined(__BEOS__) || defined(__HAIKU__)
364 # define STDIO_READ_DATA_PENDING(fp) ((fp)->_state._eof == 0)
365 #else
366 # define STDIO_READ_DATA_PENDING(fp) (!feof(fp))
367 #endif
368 
369 #define GetWriteIO(io) rb_io_get_write_io(io)
370 
371 #define READ_DATA_PENDING(fptr) ((fptr)->rbuf.len)
372 #define READ_DATA_PENDING_COUNT(fptr) ((fptr)->rbuf.len)
373 #define READ_DATA_PENDING_PTR(fptr) ((fptr)->rbuf.ptr+(fptr)->rbuf.off)
374 #define READ_DATA_BUFFERED(fptr) READ_DATA_PENDING(fptr)
375 
376 #define READ_CHAR_PENDING(fptr) ((fptr)->cbuf.len)
377 #define READ_CHAR_PENDING_COUNT(fptr) ((fptr)->cbuf.len)
378 #define READ_CHAR_PENDING_PTR(fptr) ((fptr)->cbuf.ptr+(fptr)->cbuf.off)
379 
380 #if defined(_WIN32)
381 #define WAIT_FD_IN_WIN32(fptr) \
382  (rb_w32_io_cancelable_p((fptr)->fd) ? 0 : rb_thread_wait_fd((fptr)->fd))
383 #else
384 #define WAIT_FD_IN_WIN32(fptr)
385 #endif
386 
387 #define READ_CHECK(fptr) do {\
388  if (!READ_DATA_PENDING(fptr)) {\
389  WAIT_FD_IN_WIN32(fptr);\
390  rb_io_check_closed(fptr);\
391  }\
392 } while(0)
393 
394 #ifndef S_ISSOCK
395 # ifdef _S_ISSOCK
396 # define S_ISSOCK(m) _S_ISSOCK(m)
397 # else
398 # ifdef _S_IFSOCK
399 # define S_ISSOCK(m) (((m) & S_IFMT) == _S_IFSOCK)
400 # else
401 # ifdef S_IFSOCK
402 # define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
403 # endif
404 # endif
405 # endif
406 #endif
407 
408 #define rb_sys_fail_path(path) rb_sys_fail_str(path)
409 
410 static int io_fflush(rb_io_t *);
411 static rb_io_t *flush_before_seek(rb_io_t *fptr);
412 
413 #define NEED_NEWLINE_DECORATOR_ON_READ(fptr) ((fptr)->mode & FMODE_TEXTMODE)
414 #define NEED_NEWLINE_DECORATOR_ON_WRITE(fptr) ((fptr)->mode & FMODE_TEXTMODE)
415 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
416 /* Windows */
417 # define DEFAULT_TEXTMODE FMODE_TEXTMODE
418 # define TEXTMODE_NEWLINE_DECORATOR_ON_WRITE ECONV_CRLF_NEWLINE_DECORATOR
419 /*
420  * CRLF newline is set as default newline decorator.
421  * If only CRLF newline conversion is needed, we use binary IO process
422  * with OS's text mode for IO performance improvement.
423  * If encoding conversion is needed or a user sets text mode, we use encoding
424  * conversion IO process and universal newline decorator by default.
425  */
426 #define NEED_READCONV(fptr) ((fptr)->encs.enc2 != NULL || (fptr)->encs.ecflags & ~ECONV_CRLF_NEWLINE_DECORATOR)
427 #define NEED_WRITECONV(fptr) (((fptr)->encs.enc != NULL && (fptr)->encs.enc != rb_ascii8bit_encoding()) || ((fptr)->encs.ecflags & ((ECONV_DECORATOR_MASK & ~ECONV_CRLF_NEWLINE_DECORATOR)|ECONV_STATEFUL_DECORATOR_MASK)))
428 #define SET_BINARY_MODE(fptr) setmode((fptr)->fd, O_BINARY)
429 
430 #define NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr) do {\
431  if (NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {\
432  if (((fptr)->mode & FMODE_READABLE) &&\
433  !((fptr)->encs.ecflags & ECONV_NEWLINE_DECORATOR_MASK)) {\
434  setmode((fptr)->fd, O_BINARY);\
435  }\
436  else {\
437  setmode((fptr)->fd, O_TEXT);\
438  }\
439  }\
440 } while(0)
441 
442 #define SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags) do {\
443  if ((enc2) && ((ecflags) & ECONV_DEFAULT_NEWLINE_DECORATOR)) {\
444  (ecflags) |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;\
445  }\
446 } while(0)
447 
448 /*
449  * IO unread with taking care of removed '\r' in text mode.
450  */
451 static void
452 io_unread(rb_io_t *fptr)
453 {
454  off_t r, pos;
455  ssize_t read_size;
456  long i;
457  long newlines = 0;
458  long extra_max;
459  char *p;
460  char *buf;
461 
462  rb_io_check_closed(fptr);
463  if (fptr->rbuf.len == 0 || fptr->mode & FMODE_DUPLEX) {
464  return;
465  }
466 
467  errno = 0;
468  if (!rb_w32_fd_is_text(fptr->fd)) {
469  r = lseek(fptr->fd, -fptr->rbuf.len, SEEK_CUR);
470  if (r < 0 && errno) {
471  if (errno == ESPIPE)
472  fptr->mode |= FMODE_DUPLEX;
473  return;
474  }
475 
476  fptr->rbuf.off = 0;
477  fptr->rbuf.len = 0;
478  return;
479  }
480 
481  pos = lseek(fptr->fd, 0, SEEK_CUR);
482  if (pos < 0 && errno) {
483  if (errno == ESPIPE)
484  fptr->mode |= FMODE_DUPLEX;
485  return;
486  }
487 
488  /* add extra offset for removed '\r' in rbuf */
489  extra_max = (long)(pos - fptr->rbuf.len);
490  p = fptr->rbuf.ptr + fptr->rbuf.off;
491 
492  /* if the end of rbuf is '\r', rbuf doesn't have '\r' within rbuf.len */
493  if (*(fptr->rbuf.ptr + fptr->rbuf.capa - 1) == '\r') {
494  newlines++;
495  }
496 
497  for (i = 0; i < fptr->rbuf.len; i++) {
498  if (*p == '\n') newlines++;
499  if (extra_max == newlines) break;
500  p++;
501  }
502 
503  buf = ALLOC_N(char, fptr->rbuf.len + newlines);
504  while (newlines >= 0) {
505  r = lseek(fptr->fd, pos - fptr->rbuf.len - newlines, SEEK_SET);
506  if (newlines == 0) break;
507  if (r < 0) {
508  newlines--;
509  continue;
510  }
511  read_size = _read(fptr->fd, buf, fptr->rbuf.len + newlines);
512  if (read_size < 0) {
513  free(buf);
514  rb_sys_fail_path(fptr->pathv);
515  }
516  if (read_size == fptr->rbuf.len) {
517  lseek(fptr->fd, r, SEEK_SET);
518  break;
519  }
520  else {
521  newlines--;
522  }
523  }
524  free(buf);
525  fptr->rbuf.off = 0;
526  fptr->rbuf.len = 0;
527  return;
528 }
529 
530 /*
531  * We use io_seek to back cursor position when changing mode from text to binary,
532  * but stdin and pipe cannot seek back. Stdin and pipe read should use encoding
533  * conversion for working properly with mode change.
534  *
535  * Return previous translation mode.
536  */
537 static inline int
538 set_binary_mode_with_seek_cur(rb_io_t *fptr)
539 {
540  if (!rb_w32_fd_is_text(fptr->fd)) return O_BINARY;
541 
542  if (fptr->rbuf.len == 0 || fptr->mode & FMODE_DUPLEX) {
543  return setmode(fptr->fd, O_BINARY);
544  }
545  flush_before_seek(fptr);
546  return setmode(fptr->fd, O_BINARY);
547 }
548 #define SET_BINARY_MODE_WITH_SEEK_CUR(fptr) set_binary_mode_with_seek_cur(fptr)
549 
550 #else
551 /* Unix */
552 # define DEFAULT_TEXTMODE 0
553 #define NEED_READCONV(fptr) ((fptr)->encs.enc2 != NULL || NEED_NEWLINE_DECORATOR_ON_READ(fptr))
554 #define NEED_WRITECONV(fptr) (((fptr)->encs.enc != NULL && (fptr)->encs.enc != rb_ascii8bit_encoding()) || NEED_NEWLINE_DECORATOR_ON_WRITE(fptr) || ((fptr)->encs.ecflags & (ECONV_DECORATOR_MASK|ECONV_STATEFUL_DECORATOR_MASK)))
555 #define SET_BINARY_MODE(fptr) (void)(fptr)
556 #define NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr) (void)(fptr)
557 #define SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags) ((void)(enc2), (void)(ecflags))
558 #define SET_BINARY_MODE_WITH_SEEK_CUR(fptr) (void)(fptr)
559 #endif
560 
561 #if !defined HAVE_SHUTDOWN && !defined shutdown
562 #define shutdown(a,b) 0
563 #endif
564 
565 #if defined(_WIN32)
566 #define is_socket(fd, path) rb_w32_is_socket(fd)
567 #elif !defined(S_ISSOCK)
568 #define is_socket(fd, path) 0
569 #else
570 static int
571 is_socket(int fd, VALUE path)
572 {
573  struct stat sbuf;
574  if (fstat(fd, &sbuf) < 0)
575  rb_sys_fail_path(path);
576  return S_ISSOCK(sbuf.st_mode);
577 }
578 #endif
579 
580 void
582 {
583  rb_raise(rb_eEOFError, "end of file reached");
584 }
585 
586 VALUE
588 {
589  if (!OBJ_UNTRUSTED(io) && rb_safe_level() >= 4)
590  rb_raise(rb_eSecurityError, "Insecure: operation on trusted IO");
591  rb_check_frozen(io);
592  return io;
593 }
594 
595 void
597 {
598  if (!fptr) {
599  rb_raise(rb_eIOError, "uninitialized stream");
600  }
601 }
602 
603 void
605 {
607  if (fptr->fd < 0) {
608  rb_raise(rb_eIOError, "closed stream");
609  }
610 }
611 
612 
613 VALUE
615 {
616  return rb_convert_type(io, T_FILE, "IO", "to_io");
617 }
618 
619 VALUE
621 {
622  return rb_check_convert_type(io, T_FILE, "IO", "to_io");
623 }
624 
625 VALUE
627 {
628  VALUE write_io;
629  rb_io_check_initialized(RFILE(io)->fptr);
630  write_io = RFILE(io)->fptr->tied_io_for_writing;
631  if (write_io) {
632  return write_io;
633  }
634  return io;
635 }
636 
637 VALUE
639 {
640  VALUE write_io;
641  rb_io_check_initialized(RFILE(io)->fptr);
642  if (!RTEST(w)) {
643  w = 0;
644  }
645  else {
646  GetWriteIO(w);
647  }
648  write_io = RFILE(io)->fptr->tied_io_for_writing;
649  RFILE(io)->fptr->tied_io_for_writing = w;
650  return write_io ? write_io : Qnil;
651 }
652 
653 /*
654  * call-seq:
655  * IO.try_convert(obj) -> io or nil
656  *
657  * Try to convert <i>obj</i> into an IO, using to_io method.
658  * Returns converted IO or nil if <i>obj</i> cannot be converted
659  * for any reason.
660  *
661  * IO.try_convert(STDOUT) #=> STDOUT
662  * IO.try_convert("STDOUT") #=> nil
663  *
664  * require 'zlib'
665  * f = open("/tmp/zz.gz") #=> #<File:/tmp/zz.gz>
666  * z = Zlib::GzipReader.open(f) #=> #<Zlib::GzipReader:0x81d8744>
667  * IO.try_convert(z) #=> #<File:/tmp/zz.gz>
668  *
669  */
670 static VALUE
672 {
673  return rb_io_check_io(io);
674 }
675 
676 #if !(defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32))
677 static void
679 {
680  off_t r;
681  rb_io_check_closed(fptr);
682  if (fptr->rbuf.len == 0 || fptr->mode & FMODE_DUPLEX)
683  return;
684  /* xxx: target position may be negative if buffer is filled by ungetc */
685  errno = 0;
686  r = lseek(fptr->fd, -fptr->rbuf.len, SEEK_CUR);
687  if (r < 0 && errno) {
688  if (errno == ESPIPE)
689  fptr->mode |= FMODE_DUPLEX;
690  return;
691  }
692  fptr->rbuf.off = 0;
693  fptr->rbuf.len = 0;
694  return;
695 }
696 #endif
697 
698 static rb_encoding *io_input_encoding(rb_io_t *fptr);
699 
700 static void
702 {
703  long len = RSTRING_LEN(str);
704 
705  if (fptr->rbuf.ptr == NULL) {
706  const int min_capa = IO_RBUF_CAPA_FOR(fptr);
707  fptr->rbuf.off = 0;
708  fptr->rbuf.len = 0;
709 #if SIZEOF_LONG > SIZEOF_INT
710  if (len > INT_MAX)
711  rb_raise(rb_eIOError, "ungetbyte failed");
712 #endif
713  if (len > min_capa)
714  fptr->rbuf.capa = (int)len;
715  else
716  fptr->rbuf.capa = min_capa;
717  fptr->rbuf.ptr = ALLOC_N(char, fptr->rbuf.capa);
718  }
719  if (fptr->rbuf.capa < len + fptr->rbuf.len) {
720  rb_raise(rb_eIOError, "ungetbyte failed");
721  }
722  if (fptr->rbuf.off < len) {
723  MEMMOVE(fptr->rbuf.ptr+fptr->rbuf.capa-fptr->rbuf.len,
724  fptr->rbuf.ptr+fptr->rbuf.off,
725  char, fptr->rbuf.len);
726  fptr->rbuf.off = fptr->rbuf.capa-fptr->rbuf.len;
727  }
728  fptr->rbuf.off-=(int)len;
729  fptr->rbuf.len+=(int)len;
730  MEMMOVE(fptr->rbuf.ptr+fptr->rbuf.off, RSTRING_PTR(str), char, len);
731 }
732 
733 static rb_io_t *
735 {
736  if (io_fflush(fptr) < 0)
737  rb_sys_fail(0);
738  io_unread(fptr);
739  errno = 0;
740  return fptr;
741 }
742 
743 #define io_seek(fptr, ofs, whence) (errno = 0, lseek(flush_before_seek(fptr)->fd, (ofs), (whence)))
744 #define io_tell(fptr) lseek(flush_before_seek(fptr)->fd, 0, SEEK_CUR)
745 
746 #ifndef SEEK_CUR
747 # define SEEK_SET 0
748 # define SEEK_CUR 1
749 # define SEEK_END 2
750 #endif
751 
752 void
754 {
755  rb_io_check_closed(fptr);
756  if (!(fptr->mode & FMODE_READABLE)) {
757  rb_raise(rb_eIOError, "not opened for reading");
758  }
759  if (fptr->wbuf.len) {
760  if (io_fflush(fptr) < 0)
761  rb_sys_fail(0);
762  }
763  if (fptr->tied_io_for_writing) {
764  rb_io_t *wfptr;
765  GetOpenFile(fptr->tied_io_for_writing, wfptr);
766  if (io_fflush(wfptr) < 0)
767  rb_sys_fail(0);
768  }
769 }
770 
771 void
773 {
775  if (READ_CHAR_PENDING(fptr)) {
776  rb_raise(rb_eIOError, "byte oriented read for character buffered IO");
777  }
778 }
779 
780 void
782 {
784 }
785 
786 static rb_encoding*
788 {
789  if (fptr->encs.enc) {
790  return fptr->encs.enc;
791  }
793 }
794 
795 static rb_encoding*
797 {
798  if (fptr->encs.enc2) {
799  return fptr->encs.enc2;
800  }
801  return io_read_encoding(fptr);
802 }
803 
804 void
806 {
807  rb_io_check_closed(fptr);
808  if (!(fptr->mode & FMODE_WRITABLE)) {
809  rb_raise(rb_eIOError, "not opened for writing");
810  }
811  if (fptr->rbuf.len) {
812  io_unread(fptr);
813  }
814 }
815 
816 int
818 {
819  /* This function is used for bytes and chars. Confusing. */
820  if (READ_CHAR_PENDING(fptr))
821  return 1; /* should raise? */
822  return READ_DATA_PENDING(fptr);
823 }
824 
825 void
827 {
828  if (!STDIO_READ_DATA_PENDING(fp)) {
830  }
831 }
832 
833 void
835 {
836  if (!READ_DATA_PENDING(fptr)) {
837  rb_thread_wait_fd(fptr->fd);
838  }
839  return;
840 }
841 
842 static int
843 ruby_dup(int orig)
844 {
845  int fd;
846 
847  fd = rb_cloexec_dup(orig);
848  if (fd < 0) {
849  if (errno == EMFILE || errno == ENFILE || errno == ENOMEM) {
850  rb_gc();
851  fd = rb_cloexec_dup(orig);
852  }
853  if (fd < 0) {
854  rb_sys_fail(0);
855  }
856  }
857  rb_update_max_fd(fd);
858  return fd;
859 }
860 
861 static VALUE
863 {
864  NEWOBJ_OF(io, struct RFile, klass, T_FILE);
865 
866  io->fptr = 0;
867 
868  return (VALUE)io;
869 }
870 
871 #ifndef S_ISREG
872 # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
873 #endif
874 
875 static int
877 {
878 #if defined(HAVE_FCNTL) && defined(F_GETFL) && defined(O_NONBLOCK)
879  int r;
880 #endif
881 
882  if (!(fptr->mode & FMODE_WSPLIT_INITIALIZED)) {
883  struct stat buf;
884  if (fstat(fptr->fd, &buf) == 0 &&
885  !S_ISREG(buf.st_mode)
886 #if defined(HAVE_FCNTL) && defined(F_GETFL) && defined(O_NONBLOCK)
887  && (r = fcntl(fptr->fd, F_GETFL)) != -1 &&
888  !(r & O_NONBLOCK)
889 #endif
890  ) {
891  fptr->mode |= FMODE_WSPLIT;
892  }
894  }
895  return fptr->mode & FMODE_WSPLIT;
896 }
897 
899  int fd;
900  void *buf;
901  size_t capa;
902 };
903 
905  int fd;
906  const void *buf;
907  size_t capa;
908 };
909 
910 static VALUE
912 {
913  struct io_internal_read_struct *iis = ptr;
914  return read(iis->fd, iis->buf, iis->capa);
915 }
916 
917 static VALUE
919 {
920  struct io_internal_write_struct *iis = ptr;
921  return write(iis->fd, iis->buf, iis->capa);
922 }
923 
924 static void*
926 {
927  struct io_internal_write_struct *iis = ptr;
928  return (void*)(intptr_t)write(iis->fd, iis->buf, iis->capa);
929 }
930 
931 static ssize_t
932 rb_read_internal(int fd, void *buf, size_t count)
933 {
934  struct io_internal_read_struct iis;
935  iis.fd = fd;
936  iis.buf = buf;
937  iis.capa = count;
938 
939  return (ssize_t)rb_thread_io_blocking_region(internal_read_func, &iis, fd);
940 }
941 
942 static ssize_t
943 rb_write_internal(int fd, const void *buf, size_t count)
944 {
945  struct io_internal_write_struct iis;
946  iis.fd = fd;
947  iis.buf = buf;
948  iis.capa = count;
949 
950  return (ssize_t)rb_thread_io_blocking_region(internal_write_func, &iis, fd);
951 }
952 
953 static ssize_t
954 rb_write_internal2(int fd, const void *buf, size_t count)
955 {
956  struct io_internal_write_struct iis;
957  iis.fd = fd;
958  iis.buf = buf;
959  iis.capa = count;
960 
962  RUBY_UBF_IO, NULL);
963 }
964 
965 static long
967 {
968  if (PIPE_BUF < l &&
969  !rb_thread_alone() &&
970  wsplit_p(fptr)) {
971  l = PIPE_BUF;
972  }
973  return l;
974 }
975 
976 static VALUE
978 {
979  rb_io_t *fptr = arg;
980  long l = io_writable_length(fptr, fptr->wbuf.len);
981  ssize_t r = write(fptr->fd, fptr->wbuf.ptr+fptr->wbuf.off, (size_t)l);
982 
983  if (fptr->wbuf.len <= r) {
984  fptr->wbuf.off = 0;
985  fptr->wbuf.len = 0;
986  return 0;
987  }
988  if (0 <= r) {
989  fptr->wbuf.off += (int)r;
990  fptr->wbuf.len -= (int)r;
991  errno = EAGAIN;
992  }
993  return (VALUE)-1;
994 }
995 
996 static void*
998 {
1000 
1001  /*
1002  * rb_thread_call_without_gvl2 uses 0 as interrupted.
1003  * So, we need to avoid to use 0.
1004  */
1005  return !result ? (void*)1 : (void*)result;
1006 }
1007 
1008 static VALUE
1010 {
1011  rb_io_t *fptr = (rb_io_t *)arg;
1013 }
1014 
1015 static VALUE
1017 {
1018  rb_io_t *fptr = (rb_io_t *)arg;
1019  VALUE ret;
1020 
1022  RUBY_UBF_IO, NULL);
1023 
1024  if (!ret) {
1025  /* pending async interrupt is there. */
1026  errno = EAGAIN;
1027  return -1;
1028  } else if (ret == 1) {
1029  return 0;
1030  } else
1031  return ret;
1032 }
1033 
1034 static inline int
1036 {
1037  if (fptr->write_lock) {
1038  if (rb_mutex_owned_p(fptr->write_lock))
1039  return (int)io_flush_buffer_async2((VALUE)fptr);
1040  else
1041  return (int)rb_mutex_synchronize(fptr->write_lock, io_flush_buffer_async2, (VALUE)fptr);
1042  }
1043  else {
1044  return (int)io_flush_buffer_async((VALUE)fptr);
1045  }
1046 }
1047 
1048 static int
1050 {
1051  rb_io_check_closed(fptr);
1052  if (fptr->wbuf.len == 0)
1053  return 0;
1054  rb_io_check_closed(fptr);
1055  while (fptr->wbuf.len > 0 && io_flush_buffer(fptr) != 0) {
1056  if (!rb_io_wait_writable(fptr->fd))
1057  return -1;
1058  rb_io_check_closed(fptr);
1059  }
1060  return 0;
1061 }
1062 
1063 int
1065 {
1066  if (f < 0) {
1067  rb_raise(rb_eIOError, "closed stream");
1068  }
1069  switch (errno) {
1070  case EINTR:
1071 #if defined(ERESTART)
1072  case ERESTART:
1073 #endif
1075  return TRUE;
1076 
1077  case EAGAIN:
1078 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
1079  case EWOULDBLOCK:
1080 #endif
1081  rb_thread_wait_fd(f);
1082  return TRUE;
1083 
1084  default:
1085  return FALSE;
1086  }
1087 }
1088 
1089 int
1091 {
1092  if (f < 0) {
1093  rb_raise(rb_eIOError, "closed stream");
1094  }
1095  switch (errno) {
1096  case EINTR:
1097 #if defined(ERESTART)
1098  case ERESTART:
1099 #endif
1100  /*
1101  * In old Linux, several special files under /proc and /sys don't handle
1102  * select properly. Thus we need avoid to call if don't use O_NONBLOCK.
1103  * Otherwise, we face nasty hang up. Sigh.
1104  * e.g. http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=31b07093c44a7a442394d44423e21d783f5523b8
1105  * http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=31b07093c44a7a442394d44423e21d783f5523b8
1106  * In EINTR case, we only need to call RUBY_VM_CHECK_INTS_BLOCKING().
1107  * Then rb_thread_check_ints() is enough.
1108  */
1110  return TRUE;
1111 
1112  case EAGAIN:
1113 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
1114  case EWOULDBLOCK:
1115 #endif
1117  return TRUE;
1118 
1119  default:
1120  return FALSE;
1121  }
1122 }
1123 
1124 static void
1126 {
1127  if (!fptr->writeconv_initialized) {
1128  const char *senc, *denc;
1129  rb_encoding *enc;
1130  int ecflags;
1131  VALUE ecopts;
1132 
1133  fptr->writeconv_initialized = 1;
1134 
1135  ecflags = fptr->encs.ecflags & ~ECONV_NEWLINE_DECORATOR_READ_MASK;
1136  ecopts = fptr->encs.ecopts;
1137 
1138  if (!fptr->encs.enc || (fptr->encs.enc == rb_ascii8bit_encoding() && !fptr->encs.enc2)) {
1139  /* no encoding conversion */
1140  fptr->writeconv_pre_ecflags = 0;
1141  fptr->writeconv_pre_ecopts = Qnil;
1142  fptr->writeconv = rb_econv_open_opts("", "", ecflags, ecopts);
1143  if (!fptr->writeconv)
1144  rb_exc_raise(rb_econv_open_exc("", "", ecflags));
1145  fptr->writeconv_asciicompat = Qnil;
1146  }
1147  else {
1148  enc = fptr->encs.enc2 ? fptr->encs.enc2 : fptr->encs.enc;
1150  if (!senc && !(fptr->encs.ecflags & ECONV_STATEFUL_DECORATOR_MASK)) {
1151  /* single conversion */
1152  fptr->writeconv_pre_ecflags = ecflags;
1153  fptr->writeconv_pre_ecopts = ecopts;
1154  fptr->writeconv = NULL;
1155  fptr->writeconv_asciicompat = Qnil;
1156  }
1157  else {
1158  /* double conversion */
1160  fptr->writeconv_pre_ecopts = ecopts;
1161  if (senc) {
1162  denc = rb_enc_name(enc);
1163  fptr->writeconv_asciicompat = rb_str_new2(senc);
1164  }
1165  else {
1166  senc = denc = "";
1168  }
1170  ecopts = fptr->encs.ecopts;
1171  fptr->writeconv = rb_econv_open_opts(senc, denc, ecflags, ecopts);
1172  if (!fptr->writeconv)
1173  rb_exc_raise(rb_econv_open_exc(senc, denc, ecflags));
1174  }
1175  }
1176  }
1177 }
1178 
1179 /* writing functions */
1183  const char *ptr;
1184  long length;
1185 };
1186 
1187 struct write_arg {
1190  int nosync;
1191 };
1192 
1193 static VALUE
1195 {
1196  struct binwrite_arg *p = (struct binwrite_arg *)arg;
1197  long l = io_writable_length(p->fptr, p->length);
1198  return rb_write_internal2(p->fptr->fd, p->ptr, l);
1199 }
1200 
1201 static long
1202 io_binwrite(VALUE str, const char *ptr, long len, rb_io_t *fptr, int nosync)
1203 {
1204  long n, r, offset = 0;
1205 
1206  /* don't write anything if current thread has a pending interrupt. */
1208 
1209  if ((n = len) <= 0) return n;
1210  if (fptr->wbuf.ptr == NULL && !(!nosync && (fptr->mode & FMODE_SYNC))) {
1211  fptr->wbuf.off = 0;
1212  fptr->wbuf.len = 0;
1213  fptr->wbuf.capa = IO_WBUF_CAPA_MIN;
1214  fptr->wbuf.ptr = ALLOC_N(char, fptr->wbuf.capa);
1215  fptr->write_lock = rb_mutex_new();
1216  rb_mutex_allow_trap(fptr->write_lock, 1);
1217  }
1218  if ((!nosync && (fptr->mode & (FMODE_SYNC|FMODE_TTY))) ||
1219  (fptr->wbuf.ptr && fptr->wbuf.capa <= fptr->wbuf.len + len)) {
1220  struct binwrite_arg arg;
1221 
1222  /*
1223  * xxx: use writev to avoid double write if available
1224  * writev may help avoid context switch between "a" and "\n" in
1225  * STDERR.puts "a" [ruby-dev:25080] (rebroken since native threads
1226  * introduced in 1.9)
1227  */
1228  if (fptr->wbuf.len && fptr->wbuf.len+len <= fptr->wbuf.capa) {
1229  if (fptr->wbuf.capa < fptr->wbuf.off+fptr->wbuf.len+len) {
1230  MEMMOVE(fptr->wbuf.ptr, fptr->wbuf.ptr+fptr->wbuf.off, char, fptr->wbuf.len);
1231  fptr->wbuf.off = 0;
1232  }
1233  MEMMOVE(fptr->wbuf.ptr+fptr->wbuf.off+fptr->wbuf.len, ptr+offset, char, len);
1234  fptr->wbuf.len += (int)len;
1235  n = 0;
1236  }
1237  if (io_fflush(fptr) < 0)
1238  return -1L;
1239  if (n == 0)
1240  return len;
1241 
1242  rb_io_check_closed(fptr);
1243  arg.fptr = fptr;
1244  arg.str = str;
1245  retry:
1246  arg.ptr = ptr + offset;
1247  arg.length = n;
1248  if (fptr->write_lock) {
1250  }
1251  else {
1252  long l = io_writable_length(fptr, n);
1253  r = rb_write_internal(fptr->fd, ptr+offset, l);
1254  }
1255  /* xxx: other threads may modify given string. */
1256  if (r == n) return len;
1257  if (0 <= r) {
1258  offset += r;
1259  n -= r;
1260  errno = EAGAIN;
1261  }
1262  if (rb_io_wait_writable(fptr->fd)) {
1263  rb_io_check_closed(fptr);
1264  if (offset < len)
1265  goto retry;
1266  }
1267  return -1L;
1268  }
1269 
1270  if (fptr->wbuf.off) {
1271  if (fptr->wbuf.len)
1272  MEMMOVE(fptr->wbuf.ptr, fptr->wbuf.ptr+fptr->wbuf.off, char, fptr->wbuf.len);
1273  fptr->wbuf.off = 0;
1274  }
1275  MEMMOVE(fptr->wbuf.ptr+fptr->wbuf.off+fptr->wbuf.len, ptr+offset, char, len);
1276  fptr->wbuf.len += (int)len;
1277  return len;
1278 }
1279 
1280 # define MODE_BTMODE(a,b,c) ((fmode & FMODE_BINMODE) ? (b) : \
1281  (fmode & FMODE_TEXTMODE) ? (c) : (a))
1282 static VALUE
1284 {
1285  if (NEED_WRITECONV(fptr)) {
1286  VALUE common_encoding = Qnil;
1287  SET_BINARY_MODE(fptr);
1288 
1289  make_writeconv(fptr);
1290 
1291  if (fptr->writeconv) {
1292 #define fmode (fptr->mode)
1293  if (!NIL_P(fptr->writeconv_asciicompat))
1294  common_encoding = fptr->writeconv_asciicompat;
1295  else if (MODE_BTMODE(DEFAULT_TEXTMODE,0,1) && !rb_enc_asciicompat(rb_enc_get(str))) {
1296  rb_raise(rb_eArgError, "ASCII incompatible string written for text mode IO without encoding conversion: %s",
1297  rb_enc_name(rb_enc_get(str)));
1298  }
1299 #undef fmode
1300  }
1301  else {
1302  if (fptr->encs.enc2)
1303  common_encoding = rb_enc_from_encoding(fptr->encs.enc2);
1304  else if (fptr->encs.enc != rb_ascii8bit_encoding())
1305  common_encoding = rb_enc_from_encoding(fptr->encs.enc);
1306  }
1307 
1308  if (!NIL_P(common_encoding)) {
1309  str = rb_str_encode(str, common_encoding,
1311  }
1312 
1313  if (fptr->writeconv) {
1315  }
1316  }
1317 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
1318 #define fmode (fptr->mode)
1319  else if (MODE_BTMODE(DEFAULT_TEXTMODE,0,1)) {
1320  if ((fptr->mode & FMODE_READABLE) &&
1322  setmode(fptr->fd, O_BINARY);
1323  }
1324  else {
1325  setmode(fptr->fd, O_TEXT);
1326  }
1327  if (!rb_enc_asciicompat(rb_enc_get(str))) {
1328  rb_raise(rb_eArgError, "ASCII incompatible string written for text mode IO without encoding conversion: %s",
1329  rb_enc_name(rb_enc_get(str)));
1330  }
1331  }
1332 #undef fmode
1333 #endif
1334  return str;
1335 }
1336 
1337 static long
1338 io_fwrite(VALUE str, rb_io_t *fptr, int nosync)
1339 {
1340 #ifdef _WIN32
1341  if (fptr->mode & FMODE_TTY) {
1342  long len = rb_w32_write_console(str, fptr->fd);
1343  if (len > 0) return len;
1344  }
1345 #endif
1346  str = do_writeconv(str, fptr);
1347  return io_binwrite(str, RSTRING_PTR(str), RSTRING_LEN(str),
1348  fptr, nosync);
1349 }
1350 
1351 ssize_t
1352 rb_io_bufwrite(VALUE io, const void *buf, size_t size)
1353 {
1354  rb_io_t *fptr;
1355 
1356  GetOpenFile(io, fptr);
1357  rb_io_check_writable(fptr);
1358  return (ssize_t)io_binwrite(0, buf, (long)size, fptr, 0);
1359 }
1360 
1361 static VALUE
1362 io_write(VALUE io, VALUE str, int nosync)
1363 {
1364  rb_io_t *fptr;
1365  long n;
1366  VALUE tmp;
1367 
1368  rb_secure(4);
1369  io = GetWriteIO(io);
1370  str = rb_obj_as_string(str);
1371  tmp = rb_io_check_io(io);
1372  if (NIL_P(tmp)) {
1373  /* port is not IO, call write method for it. */
1374  return rb_funcall(io, id_write, 1, str);
1375  }
1376  io = tmp;
1377  if (RSTRING_LEN(str) == 0) return INT2FIX(0);
1378 
1379  str = rb_str_new_frozen(str);
1380 
1381  GetOpenFile(io, fptr);
1382  rb_io_check_writable(fptr);
1383 
1384  n = io_fwrite(str, fptr, nosync);
1385  if (n == -1L) rb_sys_fail_path(fptr->pathv);
1386 
1387  return LONG2FIX(n);
1388 }
1389 
1390 /*
1391  * call-seq:
1392  * ios.write(string) -> integer
1393  *
1394  * Writes the given string to <em>ios</em>. The stream must be opened
1395  * for writing. If the argument is not a string, it will be converted
1396  * to a string using <code>to_s</code>. Returns the number of bytes
1397  * written.
1398  *
1399  * count = $stdout.write("This is a test\n")
1400  * puts "That was #{count} bytes of data"
1401  *
1402  * <em>produces:</em>
1403  *
1404  * This is a test
1405  * That was 15 bytes of data
1406  */
1407 
1408 static VALUE
1410 {
1411  return io_write(io, str, 0);
1412 }
1413 
1414 VALUE
1416 {
1417  return rb_funcall(io, id_write, 1, str);
1418 }
1419 
1420 /*
1421  * call-seq:
1422  * ios << obj -> ios
1423  *
1424  * String Output---Writes <i>obj</i> to <em>ios</em>.
1425  * <i>obj</i> will be converted to a string using
1426  * <code>to_s</code>.
1427  *
1428  * $stdout << "Hello " << "world!\n"
1429  *
1430  * <em>produces:</em>
1431  *
1432  * Hello world!
1433  */
1434 
1435 
1436 VALUE
1438 {
1439  rb_io_write(io, str);
1440  return io;
1441 }
1442 
1443 #ifdef HAVE_FSYNC
1444 static VALUE
1445 nogvl_fsync(void *ptr)
1446 {
1447  rb_io_t *fptr = ptr;
1448 
1449  return (VALUE)fsync(fptr->fd);
1450 }
1451 #endif
1452 
1453 /*
1454  * call-seq:
1455  * ios.flush -> ios
1456  *
1457  * Flushes any buffered data within <em>ios</em> to the underlying
1458  * operating system (note that this is Ruby internal buffering only;
1459  * the OS may buffer the data as well).
1460  *
1461  * $stdout.print "no newline"
1462  * $stdout.flush
1463  *
1464  * <em>produces:</em>
1465  *
1466  * no newline
1467  */
1468 
1469 VALUE
1471 {
1472  rb_io_t *fptr;
1473 
1474  if (!RB_TYPE_P(io, T_FILE)) {
1475  return rb_funcall(io, id_flush, 0);
1476  }
1477 
1478  io = GetWriteIO(io);
1479  GetOpenFile(io, fptr);
1480 
1481  if (fptr->mode & FMODE_WRITABLE) {
1482  if (io_fflush(fptr) < 0)
1483  rb_sys_fail(0);
1484 #ifdef _WIN32
1485  if (GetFileType((HANDLE)rb_w32_get_osfhandle(fptr->fd)) == FILE_TYPE_DISK) {
1486  rb_thread_io_blocking_region(nogvl_fsync, fptr, fptr->fd);
1487  }
1488 #endif
1489  }
1490  if (fptr->mode & FMODE_READABLE) {
1491  io_unread(fptr);
1492  }
1493 
1494  return io;
1495 }
1496 
1497 /*
1498  * call-seq:
1499  * ios.pos -> integer
1500  * ios.tell -> integer
1501  *
1502  * Returns the current offset (in bytes) of <em>ios</em>.
1503  *
1504  * f = File.new("testfile")
1505  * f.pos #=> 0
1506  * f.gets #=> "This is line one\n"
1507  * f.pos #=> 17
1508  */
1509 
1510 static VALUE
1512 {
1513  rb_io_t *fptr;
1514  off_t pos;
1515 
1516  GetOpenFile(io, fptr);
1517  pos = io_tell(fptr);
1518  if (pos < 0 && errno) rb_sys_fail_path(fptr->pathv);
1519  pos -= fptr->rbuf.len;
1520  return OFFT2NUM(pos);
1521 }
1522 
1523 static VALUE
1524 rb_io_seek(VALUE io, VALUE offset, int whence)
1525 {
1526  rb_io_t *fptr;
1527  off_t pos;
1528 
1529  pos = NUM2OFFT(offset);
1530  GetOpenFile(io, fptr);
1531  pos = io_seek(fptr, pos, whence);
1532  if (pos < 0 && errno) rb_sys_fail_path(fptr->pathv);
1533 
1534  return INT2FIX(0);
1535 }
1536 
1537 /*
1538  * call-seq:
1539  * ios.seek(amount, whence=IO::SEEK_SET) -> 0
1540  *
1541  * Seeks to a given offset <i>anInteger</i> in the stream according to
1542  * the value of <i>whence</i>:
1543  *
1544  * IO::SEEK_CUR | Seeks to _amount_ plus current position
1545  * --------------+----------------------------------------------------
1546  * IO::SEEK_END | Seeks to _amount_ plus end of stream (you probably
1547  * | want a negative value for _amount_)
1548  * --------------+----------------------------------------------------
1549  * IO::SEEK_SET | Seeks to the absolute location given by _amount_
1550  *
1551  * Example:
1552  *
1553  * f = File.new("testfile")
1554  * f.seek(-13, IO::SEEK_END) #=> 0
1555  * f.readline #=> "And so on...\n"
1556  */
1557 
1558 static VALUE
1560 {
1561  VALUE offset, ptrname;
1562  int whence = SEEK_SET;
1563 
1564  if (rb_scan_args(argc, argv, "11", &offset, &ptrname) == 2) {
1565  whence = NUM2INT(ptrname);
1566  }
1567 
1568  return rb_io_seek(io, offset, whence);
1569 }
1570 
1571 /*
1572  * call-seq:
1573  * ios.pos = integer -> integer
1574  *
1575  * Seeks to the given position (in bytes) in <em>ios</em>.
1576  * It is not guranteed that seeking to the right position when <em>ios</em>
1577  * is textmode.
1578  *
1579  * f = File.new("testfile")
1580  * f.pos = 17
1581  * f.gets #=> "This is line two\n"
1582  */
1583 
1584 static VALUE
1586 {
1587  rb_io_t *fptr;
1588  off_t pos;
1589 
1590  pos = NUM2OFFT(offset);
1591  GetOpenFile(io, fptr);
1592  pos = io_seek(fptr, pos, SEEK_SET);
1593  if (pos < 0 && errno) rb_sys_fail_path(fptr->pathv);
1594 
1595  return OFFT2NUM(pos);
1596 }
1597 
1598 static void clear_readconv(rb_io_t *fptr);
1599 
1600 /*
1601  * call-seq:
1602  * ios.rewind -> 0
1603  *
1604  * Positions <em>ios</em> to the beginning of input, resetting
1605  * <code>lineno</code> to zero.
1606  *
1607  * f = File.new("testfile")
1608  * f.readline #=> "This is line one\n"
1609  * f.rewind #=> 0
1610  * f.lineno #=> 0
1611  * f.readline #=> "This is line one\n"
1612  *
1613  * Note that it cannot be used with streams such as pipes, ttys, and sockets.
1614  */
1615 
1616 static VALUE
1618 {
1619  rb_io_t *fptr;
1620 
1621  GetOpenFile(io, fptr);
1622  if (io_seek(fptr, 0L, 0) < 0 && errno) rb_sys_fail_path(fptr->pathv);
1623 #ifdef _WIN32
1624  if (GetFileType((HANDLE)rb_w32_get_osfhandle(fptr->fd)) == FILE_TYPE_DISK) {
1625  fsync(fptr->fd);
1626  }
1627 #endif
1628  if (io == ARGF.current_file) {
1629  ARGF.lineno -= fptr->lineno;
1630  }
1631  fptr->lineno = 0;
1632  if (fptr->readconv) {
1633  clear_readconv(fptr);
1634  }
1635 
1636  return INT2FIX(0);
1637 }
1638 
1639 static int
1641 {
1642  ssize_t r;
1643 
1644  if (fptr->rbuf.ptr == NULL) {
1645  fptr->rbuf.off = 0;
1646  fptr->rbuf.len = 0;
1647  fptr->rbuf.capa = IO_RBUF_CAPA_FOR(fptr);
1648  fptr->rbuf.ptr = ALLOC_N(char, fptr->rbuf.capa);
1649 #ifdef _WIN32
1650  fptr->rbuf.capa--;
1651 #endif
1652  }
1653  if (fptr->rbuf.len == 0) {
1654  retry:
1655  {
1656  r = rb_read_internal(fptr->fd, fptr->rbuf.ptr, fptr->rbuf.capa);
1657  }
1658  if (r < 0) {
1659  if (rb_io_wait_readable(fptr->fd))
1660  goto retry;
1661  rb_sys_fail_path(fptr->pathv);
1662  }
1663  fptr->rbuf.off = 0;
1664  fptr->rbuf.len = (int)r; /* r should be <= rbuf_capa */
1665  if (r == 0)
1666  return -1; /* EOF */
1667  }
1668  return 0;
1669 }
1670 
1671 /*
1672  * call-seq:
1673  * ios.eof -> true or false
1674  * ios.eof? -> true or false
1675  *
1676  * Returns true if <em>ios</em> is at end of file that means
1677  * there are no more data to read.
1678  * The stream must be opened for reading or an <code>IOError</code> will be
1679  * raised.
1680  *
1681  * f = File.new("testfile")
1682  * dummy = f.readlines
1683  * f.eof #=> true
1684  *
1685  * If <em>ios</em> is a stream such as pipe or socket, <code>IO#eof?</code>
1686  * blocks until the other end sends some data or closes it.
1687  *
1688  * r, w = IO.pipe
1689  * Thread.new { sleep 1; w.close }
1690  * r.eof? #=> true after 1 second blocking
1691  *
1692  * r, w = IO.pipe
1693  * Thread.new { sleep 1; w.puts "a" }
1694  * r.eof? #=> false after 1 second blocking
1695  *
1696  * r, w = IO.pipe
1697  * r.eof? # blocks forever
1698  *
1699  * Note that <code>IO#eof?</code> reads data to the input byte buffer.
1700  * So <code>IO#sysread</code> may not behave as you intend with
1701  * <code>IO#eof?</code>, unless you call <code>IO#rewind</code>
1702  * first (which is not available for some streams).
1703  */
1704 
1705 VALUE
1707 {
1708  rb_io_t *fptr;
1709 
1710  GetOpenFile(io, fptr);
1712 
1713  if (READ_CHAR_PENDING(fptr)) return Qfalse;
1714  if (READ_DATA_PENDING(fptr)) return Qfalse;
1715  READ_CHECK(fptr);
1716 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
1717  if (!NEED_READCONV(fptr) && NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {
1718  return eof(fptr->fd) ? Qtrue : Qfalse;
1719  }
1720 #endif
1721  if (io_fillbuf(fptr) < 0) {
1722  return Qtrue;
1723  }
1724  return Qfalse;
1725 }
1726 
1727 /*
1728  * call-seq:
1729  * ios.sync -> true or false
1730  *
1731  * Returns the current ``sync mode'' of <em>ios</em>. When sync mode is
1732  * true, all output is immediately flushed to the underlying operating
1733  * system and is not buffered by Ruby internally. See also
1734  * <code>IO#fsync</code>.
1735  *
1736  * f = File.new("testfile")
1737  * f.sync #=> false
1738  */
1739 
1740 static VALUE
1742 {
1743  rb_io_t *fptr;
1744 
1745  io = GetWriteIO(io);
1746  GetOpenFile(io, fptr);
1747  return (fptr->mode & FMODE_SYNC) ? Qtrue : Qfalse;
1748 }
1749 
1750 #ifdef HAVE_FSYNC
1751 
1752 /*
1753  * call-seq:
1754  * ios.sync = boolean -> boolean
1755  *
1756  * Sets the ``sync mode'' to <code>true</code> or <code>false</code>.
1757  * When sync mode is true, all output is immediately flushed to the
1758  * underlying operating system and is not buffered internally. Returns
1759  * the new state. See also <code>IO#fsync</code>.
1760  *
1761  * f = File.new("testfile")
1762  * f.sync = true
1763  *
1764  * <em>(produces no output)</em>
1765  */
1766 
1767 static VALUE
1768 rb_io_set_sync(VALUE io, VALUE sync)
1769 {
1770  rb_io_t *fptr;
1771 
1772  io = GetWriteIO(io);
1773  GetOpenFile(io, fptr);
1774  if (RTEST(sync)) {
1775  fptr->mode |= FMODE_SYNC;
1776  }
1777  else {
1778  fptr->mode &= ~FMODE_SYNC;
1779  }
1780  return sync;
1781 }
1782 
1783 /*
1784  * call-seq:
1785  * ios.fsync -> 0 or nil
1786  *
1787  * Immediately writes all buffered data in <em>ios</em> to disk.
1788  * Note that <code>fsync</code> differs from
1789  * using <code>IO#sync=</code>. The latter ensures that data is flushed
1790  * from Ruby's buffers, but does not guarantee that the underlying
1791  * operating system actually writes it to disk.
1792  *
1793  * <code>NotImplementedError</code> is raised
1794  * if the underlying operating system does not support <em>fsync(2)</em>.
1795  */
1796 
1797 static VALUE
1798 rb_io_fsync(VALUE io)
1799 {
1800  rb_io_t *fptr;
1801 
1802  io = GetWriteIO(io);
1803  GetOpenFile(io, fptr);
1804 
1805  if (io_fflush(fptr) < 0)
1806  rb_sys_fail(0);
1807 # ifndef _WIN32 /* already called in io_fflush() */
1808  if ((int)rb_thread_io_blocking_region(nogvl_fsync, fptr, fptr->fd) < 0)
1809  rb_sys_fail_path(fptr->pathv);
1810 # endif
1811  return INT2FIX(0);
1812 }
1813 #else
1814 # define rb_io_fsync rb_f_notimplement
1815 # define rb_io_sync rb_f_notimplement
1816 static VALUE
1818 {
1819  rb_notimplement();
1820  UNREACHABLE;
1821 }
1822 #endif
1823 
1824 #ifdef HAVE_FDATASYNC
1825 static VALUE
1826 nogvl_fdatasync(void *ptr)
1827 {
1828  rb_io_t *fptr = ptr;
1829 
1830  return (VALUE)fdatasync(fptr->fd);
1831 }
1832 
1833 /*
1834  * call-seq:
1835  * ios.fdatasync -> 0 or nil
1836  *
1837  * Immediately writes all buffered data in <em>ios</em> to disk.
1838  *
1839  * If the underlying operating system does not support <em>fdatasync(2)</em>,
1840  * <code>IO#fsync</code> is called instead (which might raise a
1841  * <code>NotImplementedError</code>).
1842  */
1843 
1844 static VALUE
1846 {
1847  rb_io_t *fptr;
1848 
1849  io = GetWriteIO(io);
1850  GetOpenFile(io, fptr);
1851 
1852  if (io_fflush(fptr) < 0)
1853  rb_sys_fail(0);
1854 
1855  if ((int)rb_thread_io_blocking_region(nogvl_fdatasync, fptr, fptr->fd) == 0)
1856  return INT2FIX(0);
1857 
1858  /* fall back */
1859  return rb_io_fsync(io);
1860 }
1861 #else
1862 #define rb_io_fdatasync rb_io_fsync
1863 #endif
1864 
1865 /*
1866  * call-seq:
1867  * ios.fileno -> fixnum
1868  * ios.to_i -> fixnum
1869  *
1870  * Returns an integer representing the numeric file descriptor for
1871  * <em>ios</em>.
1872  *
1873  * $stdin.fileno #=> 0
1874  * $stdout.fileno #=> 1
1875  */
1876 
1877 static VALUE
1879 {
1880  rb_io_t *fptr;
1881  int fd;
1882 
1883  GetOpenFile(io, fptr);
1884  fd = fptr->fd;
1885  return INT2FIX(fd);
1886 }
1887 
1888 
1889 /*
1890  * call-seq:
1891  * ios.pid -> fixnum
1892  *
1893  * Returns the process ID of a child process associated with
1894  * <em>ios</em>. This will be set by <code>IO.popen</code>.
1895  *
1896  * pipe = IO.popen("-")
1897  * if pipe
1898  * $stderr.puts "In parent, child pid is #{pipe.pid}"
1899  * else
1900  * $stderr.puts "In child, pid is #{$$}"
1901  * end
1902  *
1903  * <em>produces:</em>
1904  *
1905  * In child, pid is 26209
1906  * In parent, child pid is 26209
1907  */
1908 
1909 static VALUE
1911 {
1912  rb_io_t *fptr;
1913 
1914  GetOpenFile(io, fptr);
1915  if (!fptr->pid)
1916  return Qnil;
1917  return PIDT2NUM(fptr->pid);
1918 }
1919 
1920 
1921 /*
1922  * call-seq:
1923  * ios.inspect -> string
1924  *
1925  * Return a string describing this IO object.
1926  */
1927 
1928 static VALUE
1930 {
1931  rb_io_t *fptr;
1932  VALUE result;
1933  static const char closed[] = " (closed)";
1934 
1935  fptr = RFILE(rb_io_taint_check(obj))->fptr;
1936  if (!fptr) return rb_any_to_s(obj);
1937  result = rb_str_new_cstr("#<");
1938  rb_str_append(result, rb_class_name(CLASS_OF(obj)));
1939  rb_str_cat2(result, ":");
1940  if (NIL_P(fptr->pathv)) {
1941  if (fptr->fd < 0) {
1942  rb_str_cat(result, closed+1, strlen(closed)-1);
1943  }
1944  else {
1945  rb_str_catf(result, "fd %d", fptr->fd);
1946  }
1947  }
1948  else {
1949  rb_str_append(result, fptr->pathv);
1950  if (fptr->fd < 0) {
1951  rb_str_cat(result, closed, strlen(closed));
1952  }
1953  }
1954  return rb_str_cat2(result, ">");
1955 }
1956 
1957 /*
1958  * call-seq:
1959  * ios.to_io -> ios
1960  *
1961  * Returns <em>ios</em>.
1962  */
1963 
1964 static VALUE
1966 {
1967  return io;
1968 }
1969 
1970 /* reading functions */
1971 static long
1972 read_buffered_data(char *ptr, long len, rb_io_t *fptr)
1973 {
1974  int n;
1975 
1976  n = READ_DATA_PENDING_COUNT(fptr);
1977  if (n <= 0) return 0;
1978  if (n > len) n = (int)len;
1979  MEMMOVE(ptr, fptr->rbuf.ptr+fptr->rbuf.off, char, n);
1980  fptr->rbuf.off += n;
1981  fptr->rbuf.len -= n;
1982  return n;
1983 }
1984 
1985 static long
1986 io_bufread(char *ptr, long len, rb_io_t *fptr)
1987 {
1988  long offset = 0;
1989  long n = len;
1990  long c;
1991 
1992  if (READ_DATA_PENDING(fptr) == 0) {
1993  while (n > 0) {
1994  again:
1995  c = rb_read_internal(fptr->fd, ptr+offset, n);
1996  if (c == 0) break;
1997  if (c < 0) {
1998  if (rb_io_wait_readable(fptr->fd))
1999  goto again;
2000  return -1;
2001  }
2002  offset += c;
2003  if ((n -= c) <= 0) break;
2004  }
2005  return len - n;
2006  }
2007 
2008  while (n > 0) {
2009  c = read_buffered_data(ptr+offset, n, fptr);
2010  if (c > 0) {
2011  offset += c;
2012  if ((n -= c) <= 0) break;
2013  }
2014  rb_io_check_closed(fptr);
2015  if (io_fillbuf(fptr) < 0) {
2016  break;
2017  }
2018  }
2019  return len - n;
2020 }
2021 
2022 static void io_setstrbuf(VALUE *str, long len);
2023 
2024 struct bufread_arg {
2025  char *str_ptr;
2026  long len;
2028 };
2029 
2030 static VALUE
2032 {
2033  struct bufread_arg *p = (struct bufread_arg *)arg;
2034  p->len = io_bufread(p->str_ptr, p->len, p->fptr);
2035  return Qundef;
2036 }
2037 
2038 static long
2039 io_fread(VALUE str, long offset, long size, rb_io_t *fptr)
2040 {
2041  long len;
2042  struct bufread_arg arg;
2043 
2044  io_setstrbuf(&str, offset + size);
2045  arg.str_ptr = RSTRING_PTR(str) + offset;
2046  arg.len = size;
2047  arg.fptr = fptr;
2049  len = arg.len;
2050  if (len < 0) rb_sys_fail_path(fptr->pathv);
2051  return len;
2052 }
2053 
2054 ssize_t
2055 rb_io_bufread(VALUE io, void *buf, size_t size)
2056 {
2057  rb_io_t *fptr;
2058 
2059  GetOpenFile(io, fptr);
2060  rb_io_check_readable(fptr);
2061  return (ssize_t)io_bufread(buf, (long)size, fptr);
2062 }
2063 
2064 #define SMALLBUF 100
2065 
2066 static long
2068 {
2069  struct stat st;
2070  off_t siz = READ_DATA_PENDING_COUNT(fptr);
2071  off_t pos;
2072 
2073  if (fstat(fptr->fd, &st) == 0 && S_ISREG(st.st_mode)
2074 #if defined(__BEOS__) || defined(__HAIKU__)
2075  && (st.st_dev > 3)
2076 #endif
2077  )
2078  {
2079  if (io_fflush(fptr) < 0)
2080  rb_sys_fail(0);
2081  pos = lseek(fptr->fd, 0, SEEK_CUR);
2082  if (st.st_size >= pos && pos >= 0) {
2083  siz += st.st_size - pos;
2084  if (siz > LONG_MAX) {
2085  rb_raise(rb_eIOError, "file too big for single read");
2086  }
2087  }
2088  }
2089  else {
2090  siz += BUFSIZ;
2091  }
2092  return (long)siz;
2093 }
2094 
2095 static VALUE
2097 {
2098  OBJ_TAINT(str);
2099  rb_enc_associate(str, io_read_encoding(fptr));
2100  return str;
2101 }
2102 
2103 static void
2105 {
2106  if (!fptr->readconv) {
2107  int ecflags;
2108  VALUE ecopts;
2109  const char *sname, *dname;
2110  ecflags = fptr->encs.ecflags & ~ECONV_NEWLINE_DECORATOR_WRITE_MASK;
2111  ecopts = fptr->encs.ecopts;
2112  if (fptr->encs.enc2) {
2113  sname = rb_enc_name(fptr->encs.enc2);
2114  dname = rb_enc_name(fptr->encs.enc);
2115  }
2116  else {
2117  sname = dname = "";
2118  }
2119  fptr->readconv = rb_econv_open_opts(sname, dname, ecflags, ecopts);
2120  if (!fptr->readconv)
2121  rb_exc_raise(rb_econv_open_exc(sname, dname, ecflags));
2122  fptr->cbuf.off = 0;
2123  fptr->cbuf.len = 0;
2124  if (size < IO_CBUF_CAPA_MIN) size = IO_CBUF_CAPA_MIN;
2125  fptr->cbuf.capa = size;
2126  fptr->cbuf.ptr = ALLOC_N(char, fptr->cbuf.capa);
2127  }
2128 }
2129 
2130 #define MORE_CHAR_SUSPENDED Qtrue
2131 #define MORE_CHAR_FINISHED Qnil
2132 static VALUE
2133 fill_cbuf(rb_io_t *fptr, int ec_flags)
2134 {
2135  const unsigned char *ss, *sp, *se;
2136  unsigned char *ds, *dp, *de;
2137  rb_econv_result_t res;
2138  int putbackable;
2139  int cbuf_len0;
2140  VALUE exc;
2141 
2142  ec_flags |= ECONV_PARTIAL_INPUT;
2143 
2144  if (fptr->cbuf.len == fptr->cbuf.capa)
2145  return MORE_CHAR_SUSPENDED; /* cbuf full */
2146  if (fptr->cbuf.len == 0)
2147  fptr->cbuf.off = 0;
2148  else if (fptr->cbuf.off + fptr->cbuf.len == fptr->cbuf.capa) {
2149  memmove(fptr->cbuf.ptr, fptr->cbuf.ptr+fptr->cbuf.off, fptr->cbuf.len);
2150  fptr->cbuf.off = 0;
2151  }
2152 
2153  cbuf_len0 = fptr->cbuf.len;
2154 
2155  while (1) {
2156  ss = sp = (const unsigned char *)fptr->rbuf.ptr + fptr->rbuf.off;
2157  se = sp + fptr->rbuf.len;
2158  ds = dp = (unsigned char *)fptr->cbuf.ptr + fptr->cbuf.off + fptr->cbuf.len;
2159  de = (unsigned char *)fptr->cbuf.ptr + fptr->cbuf.capa;
2160  res = rb_econv_convert(fptr->readconv, &sp, se, &dp, de, ec_flags);
2161  fptr->rbuf.off += (int)(sp - ss);
2162  fptr->rbuf.len -= (int)(sp - ss);
2163  fptr->cbuf.len += (int)(dp - ds);
2164 
2165  putbackable = rb_econv_putbackable(fptr->readconv);
2166  if (putbackable) {
2167  rb_econv_putback(fptr->readconv, (unsigned char *)fptr->rbuf.ptr + fptr->rbuf.off - putbackable, putbackable);
2168  fptr->rbuf.off -= putbackable;
2169  fptr->rbuf.len += putbackable;
2170  }
2171 
2172  exc = rb_econv_make_exception(fptr->readconv);
2173  if (!NIL_P(exc))
2174  return exc;
2175 
2176  if (cbuf_len0 != fptr->cbuf.len)
2177  return MORE_CHAR_SUSPENDED;
2178 
2179  if (res == econv_finished) {
2180  return MORE_CHAR_FINISHED;
2181  }
2182 
2183  if (res == econv_source_buffer_empty) {
2184  if (fptr->rbuf.len == 0) {
2185  READ_CHECK(fptr);
2186  if (io_fillbuf(fptr) == -1) {
2187  if (!fptr->readconv) {
2188  return MORE_CHAR_FINISHED;
2189  }
2190  ds = dp = (unsigned char *)fptr->cbuf.ptr + fptr->cbuf.off + fptr->cbuf.len;
2191  de = (unsigned char *)fptr->cbuf.ptr + fptr->cbuf.capa;
2192  res = rb_econv_convert(fptr->readconv, NULL, NULL, &dp, de, 0);
2193  fptr->cbuf.len += (int)(dp - ds);
2195  break;
2196  }
2197  }
2198  }
2199  }
2200  if (cbuf_len0 != fptr->cbuf.len)
2201  return MORE_CHAR_SUSPENDED;
2202 
2203  return MORE_CHAR_FINISHED;
2204 }
2205 
2206 static VALUE
2208 {
2209  VALUE v;
2210  v = fill_cbuf(fptr, ECONV_AFTER_OUTPUT);
2211  if (v != MORE_CHAR_SUSPENDED && v != MORE_CHAR_FINISHED)
2212  rb_exc_raise(v);
2213  return v;
2214 }
2215 
2216 static VALUE
2217 io_shift_cbuf(rb_io_t *fptr, int len, VALUE *strp)
2218 {
2219  VALUE str = Qnil;
2220  if (strp) {
2221  str = *strp;
2222  if (NIL_P(str)) {
2223  *strp = str = rb_str_new(fptr->cbuf.ptr+fptr->cbuf.off, len);
2224  }
2225  else {
2226  rb_str_cat(str, fptr->cbuf.ptr+fptr->cbuf.off, len);
2227  }
2228  OBJ_TAINT(str);
2229  rb_enc_associate(str, fptr->encs.enc);
2230  }
2231  fptr->cbuf.off += len;
2232  fptr->cbuf.len -= len;
2233  /* xxx: set coderange */
2234  if (fptr->cbuf.len == 0)
2235  fptr->cbuf.off = 0;
2236  else if (fptr->cbuf.capa/2 < fptr->cbuf.off) {
2237  memmove(fptr->cbuf.ptr, fptr->cbuf.ptr+fptr->cbuf.off, fptr->cbuf.len);
2238  fptr->cbuf.off = 0;
2239  }
2240  return str;
2241 }
2242 
2243 static void
2244 io_setstrbuf(VALUE *str, long len)
2245 {
2246 #ifdef _WIN32
2247  len = (len + 1) & ~1L; /* round up for wide char */
2248 #endif
2249  if (NIL_P(*str)) {
2250  *str = rb_str_new(0, 0);
2251  }
2252  else {
2253  VALUE s = StringValue(*str);
2254  long clen = RSTRING_LEN(s);
2255  if (clen >= len) {
2256  if (clen != len) {
2257  rb_str_modify(s);
2258  rb_str_set_len(s, len);
2259  }
2260  return;
2261  }
2262  len -= clen;
2263  }
2264  rb_str_modify_expand(*str, len);
2265 }
2266 
2267 static void
2269 {
2270  if (RSTRING_LEN(str) != n) {
2271  rb_str_modify(str);
2272  rb_str_set_len(str, n);
2273  }
2274 }
2275 
2276 static VALUE
2277 read_all(rb_io_t *fptr, long siz, VALUE str)
2278 {
2279  long bytes;
2280  long n;
2281  long pos;
2282  rb_encoding *enc;
2283  int cr;
2284 
2285  if (NEED_READCONV(fptr)) {
2286  SET_BINARY_MODE(fptr);
2287  io_setstrbuf(&str,0);
2288  make_readconv(fptr, 0);
2289  while (1) {
2290  VALUE v;
2291  if (fptr->cbuf.len) {
2292  io_shift_cbuf(fptr, fptr->cbuf.len, &str);
2293  }
2294  v = fill_cbuf(fptr, 0);
2295  if (v != MORE_CHAR_SUSPENDED && v != MORE_CHAR_FINISHED) {
2296  if (fptr->cbuf.len) {
2297  io_shift_cbuf(fptr, fptr->cbuf.len, &str);
2298  }
2299  rb_exc_raise(v);
2300  }
2301  if (v == MORE_CHAR_FINISHED) {
2302  clear_readconv(fptr);
2303  return io_enc_str(str, fptr);
2304  }
2305  }
2306  }
2307 
2309  bytes = 0;
2310  pos = 0;
2311 
2312  enc = io_read_encoding(fptr);
2313  cr = 0;
2314 
2315  if (siz == 0) siz = BUFSIZ;
2316  io_setstrbuf(&str,siz);
2317  for (;;) {
2318  READ_CHECK(fptr);
2319  n = io_fread(str, bytes, siz - bytes, fptr);
2320  if (n == 0 && bytes == 0) {
2321  rb_str_set_len(str, 0);
2322  break;
2323  }
2324  bytes += n;
2325  rb_str_set_len(str, bytes);
2326  if (cr != ENC_CODERANGE_BROKEN)
2327  pos += rb_str_coderange_scan_restartable(RSTRING_PTR(str) + pos, RSTRING_PTR(str) + bytes, enc, &cr);
2328  if (bytes < siz) break;
2329  siz += BUFSIZ;
2330  rb_str_modify_expand(str, BUFSIZ);
2331  }
2332  str = io_enc_str(str, fptr);
2333  ENC_CODERANGE_SET(str, cr);
2334  return str;
2335 }
2336 
2337 void
2339 {
2340  int oflags;
2341 #ifdef F_GETFL
2342  oflags = fcntl(fptr->fd, F_GETFL);
2343  if (oflags == -1) {
2344  rb_sys_fail_path(fptr->pathv);
2345  }
2346 #else
2347  oflags = 0;
2348 #endif
2349  if ((oflags & O_NONBLOCK) == 0) {
2350  oflags |= O_NONBLOCK;
2351  if (fcntl(fptr->fd, F_SETFL, oflags) == -1) {
2352  rb_sys_fail_path(fptr->pathv);
2353  }
2354  }
2355 }
2356 
2358  int fd;
2359  char *str_ptr;
2360  long len;
2361 };
2362 
2363 static VALUE
2365 {
2366  struct read_internal_arg *p = (struct read_internal_arg *)arg;
2367  p->len = rb_read_internal(p->fd, p->str_ptr, p->len);
2368  return Qundef;
2369 }
2370 
2371 static VALUE
2372 io_getpartial(int argc, VALUE *argv, VALUE io, int nonblock)
2373 {
2374  rb_io_t *fptr;
2375  VALUE length, str;
2376  long n, len;
2377  struct read_internal_arg arg;
2378 
2379  rb_scan_args(argc, argv, "11", &length, &str);
2380 
2381  if ((len = NUM2LONG(length)) < 0) {
2382  rb_raise(rb_eArgError, "negative length %ld given", len);
2383  }
2384 
2385  io_setstrbuf(&str,len);
2386  OBJ_TAINT(str);
2387 
2388  GetOpenFile(io, fptr);
2390 
2391  if (len == 0)
2392  return str;
2393 
2394  if (!nonblock)
2395  READ_CHECK(fptr);
2396  n = read_buffered_data(RSTRING_PTR(str), len, fptr);
2397  if (n <= 0) {
2398  again:
2399  if (nonblock) {
2400  rb_io_set_nonblock(fptr);
2401  }
2402  io_setstrbuf(&str, len);
2403  arg.fd = fptr->fd;
2404  arg.str_ptr = RSTRING_PTR(str);
2405  arg.len = len;
2407  n = arg.len;
2408  if (n < 0) {
2409  if (!nonblock && rb_io_wait_readable(fptr->fd))
2410  goto again;
2411  if (nonblock && (errno == EWOULDBLOCK || errno == EAGAIN))
2412  rb_mod_sys_fail(rb_mWaitReadable, "read would block");
2413  rb_sys_fail_path(fptr->pathv);
2414  }
2415  }
2416  io_set_read_length(str, n);
2417 
2418  if (n == 0)
2419  return Qnil;
2420  else
2421  return str;
2422 }
2423 
2424 /*
2425  * call-seq:
2426  * ios.readpartial(maxlen) -> string
2427  * ios.readpartial(maxlen, outbuf) -> outbuf
2428  *
2429  * Reads at most <i>maxlen</i> bytes from the I/O stream.
2430  * It blocks only if <em>ios</em> has no data immediately available.
2431  * It doesn't block if some data available.
2432  * If the optional <i>outbuf</i> argument is present,
2433  * it must reference a String, which will receive the data.
2434  * The <i>outbuf</i> will contain only the received data after the method call
2435  * even if it is not empty at the beginning.
2436  * It raises <code>EOFError</code> on end of file.
2437  *
2438  * readpartial is designed for streams such as pipe, socket, tty, etc.
2439  * It blocks only when no data immediately available.
2440  * This means that it blocks only when following all conditions hold.
2441  * * the byte buffer in the IO object is empty.
2442  * * the content of the stream is empty.
2443  * * the stream is not reached to EOF.
2444  *
2445  * When readpartial blocks, it waits data or EOF on the stream.
2446  * If some data is reached, readpartial returns with the data.
2447  * If EOF is reached, readpartial raises EOFError.
2448  *
2449  * When readpartial doesn't blocks, it returns or raises immediately.
2450  * If the byte buffer is not empty, it returns the data in the buffer.
2451  * Otherwise if the stream has some content,
2452  * it returns the data in the stream.
2453  * Otherwise if the stream is reached to EOF, it raises EOFError.
2454  *
2455  * r, w = IO.pipe # buffer pipe content
2456  * w << "abc" # "" "abc".
2457  * r.readpartial(4096) #=> "abc" "" ""
2458  * r.readpartial(4096) # blocks because buffer and pipe is empty.
2459  *
2460  * r, w = IO.pipe # buffer pipe content
2461  * w << "abc" # "" "abc"
2462  * w.close # "" "abc" EOF
2463  * r.readpartial(4096) #=> "abc" "" EOF
2464  * r.readpartial(4096) # raises EOFError
2465  *
2466  * r, w = IO.pipe # buffer pipe content
2467  * w << "abc\ndef\n" # "" "abc\ndef\n"
2468  * r.gets #=> "abc\n" "def\n" ""
2469  * w << "ghi\n" # "def\n" "ghi\n"
2470  * r.readpartial(4096) #=> "def\n" "" "ghi\n"
2471  * r.readpartial(4096) #=> "ghi\n" "" ""
2472  *
2473  * Note that readpartial behaves similar to sysread.
2474  * The differences are:
2475  * * If the byte buffer is not empty, read from the byte buffer instead of "sysread for buffered IO (IOError)".
2476  * * It doesn't cause Errno::EWOULDBLOCK and Errno::EINTR. When readpartial meets EWOULDBLOCK and EINTR by read system call, readpartial retry the system call.
2477  *
2478  * The later means that readpartial is nonblocking-flag insensitive.
2479  * It blocks on the situation IO#sysread causes Errno::EWOULDBLOCK as if the fd is blocking mode.
2480  *
2481  */
2482 
2483 static VALUE
2485 {
2486  VALUE ret;
2487 
2488  ret = io_getpartial(argc, argv, io, 0);
2489  if (NIL_P(ret))
2490  rb_eof_error();
2491  return ret;
2492 }
2493 
2494 /*
2495  * call-seq:
2496  * ios.read_nonblock(maxlen) -> string
2497  * ios.read_nonblock(maxlen, outbuf) -> outbuf
2498  *
2499  * Reads at most <i>maxlen</i> bytes from <em>ios</em> using
2500  * the read(2) system call after O_NONBLOCK is set for
2501  * the underlying file descriptor.
2502  *
2503  * If the optional <i>outbuf</i> argument is present,
2504  * it must reference a String, which will receive the data.
2505  * The <i>outbuf</i> will contain only the received data after the method call
2506  * even if it is not empty at the beginning.
2507  *
2508  * read_nonblock just calls the read(2) system call.
2509  * It causes all errors the read(2) system call causes: Errno::EWOULDBLOCK, Errno::EINTR, etc.
2510  * The caller should care such errors.
2511  *
2512  * If the exception is Errno::EWOULDBLOCK or Errno::AGAIN,
2513  * it is extended by IO::WaitReadable.
2514  * So IO::WaitReadable can be used to rescue the exceptions for retrying read_nonblock.
2515  *
2516  * read_nonblock causes EOFError on EOF.
2517  *
2518  * If the read byte buffer is not empty,
2519  * read_nonblock reads from the buffer like readpartial.
2520  * In this case, the read(2) system call is not called.
2521  *
2522  * When read_nonblock raises an exception kind of IO::WaitReadable,
2523  * read_nonblock should not be called
2524  * until io is readable for avoiding busy loop.
2525  * This can be done as follows.
2526  *
2527  * # emulates blocking read (readpartial).
2528  * begin
2529  * result = io.read_nonblock(maxlen)
2530  * rescue IO::WaitReadable
2531  * IO.select([io])
2532  * retry
2533  * end
2534  *
2535  * Although IO#read_nonblock doesn't raise IO::WaitWritable.
2536  * OpenSSL::Buffering#read_nonblock can raise IO::WaitWritable.
2537  * If IO and SSL should be used polymorphically,
2538  * IO::WaitWritable should be rescued too.
2539  * See the document of OpenSSL::Buffering#read_nonblock for sample code.
2540  *
2541  * Note that this method is identical to readpartial
2542  * except the non-blocking flag is set.
2543  */
2544 
2545 static VALUE
2547 {
2548  VALUE ret;
2549 
2550  ret = io_getpartial(argc, argv, io, 1);
2551  if (NIL_P(ret))
2552  rb_eof_error();
2553  return ret;
2554 }
2555 
2556 /*
2557  * call-seq:
2558  * ios.write_nonblock(string) -> integer
2559  *
2560  * Writes the given string to <em>ios</em> using
2561  * the write(2) system call after O_NONBLOCK is set for
2562  * the underlying file descriptor.
2563  *
2564  * It returns the number of bytes written.
2565  *
2566  * write_nonblock just calls the write(2) system call.
2567  * It causes all errors the write(2) system call causes: Errno::EWOULDBLOCK, Errno::EINTR, etc.
2568  * The result may also be smaller than string.length (partial write).
2569  * The caller should care such errors and partial write.
2570  *
2571  * If the exception is Errno::EWOULDBLOCK or Errno::AGAIN,
2572  * it is extended by IO::WaitWritable.
2573  * So IO::WaitWritable can be used to rescue the exceptions for retrying write_nonblock.
2574  *
2575  * # Creates a pipe.
2576  * r, w = IO.pipe
2577  *
2578  * # write_nonblock writes only 65536 bytes and return 65536.
2579  * # (The pipe size is 65536 bytes on this environment.)
2580  * s = "a" * 100000
2581  * p w.write_nonblock(s) #=> 65536
2582  *
2583  * # write_nonblock cannot write a byte and raise EWOULDBLOCK (EAGAIN).
2584  * p w.write_nonblock("b") # Resource temporarily unavailable (Errno::EAGAIN)
2585  *
2586  * If the write buffer is not empty, it is flushed at first.
2587  *
2588  * When write_nonblock raises an exception kind of IO::WaitWritable,
2589  * write_nonblock should not be called
2590  * until io is writable for avoiding busy loop.
2591  * This can be done as follows.
2592  *
2593  * begin
2594  * result = io.write_nonblock(string)
2595  * rescue IO::WaitWritable, Errno::EINTR
2596  * IO.select(nil, [io])
2597  * retry
2598  * end
2599  *
2600  * Note that this doesn't guarantee to write all data in string.
2601  * The length written is reported as result and it should be checked later.
2602  *
2603  * On some platforms such as Windows, write_nonblock is not supported
2604  * according to the kind of the IO object.
2605  * In such cases, write_nonblock raises <code>Errno::EBADF</code>.
2606  *
2607  */
2608 
2609 static VALUE
2611 {
2612  rb_io_t *fptr;
2613  long n;
2614 
2615  rb_secure(4);
2616  if (!RB_TYPE_P(str, T_STRING))
2617  str = rb_obj_as_string(str);
2618 
2619  io = GetWriteIO(io);
2620  GetOpenFile(io, fptr);
2621  rb_io_check_writable(fptr);
2622 
2623  if (io_fflush(fptr) < 0)
2624  rb_sys_fail(0);
2625 
2626  rb_io_set_nonblock(fptr);
2627  n = write(fptr->fd, RSTRING_PTR(str), RSTRING_LEN(str));
2628 
2629  if (n == -1) {
2630  if (errno == EWOULDBLOCK || errno == EAGAIN)
2631  rb_mod_sys_fail(rb_mWaitWritable, "write would block");
2632  rb_sys_fail_path(fptr->pathv);
2633  }
2634 
2635  return LONG2FIX(n);
2636 }
2637 
2638 /*
2639  * call-seq:
2640  * ios.read([length [, outbuf]]) -> string, outbuf, or nil
2641  *
2642  * Reads <i>length</i> bytes from the I/O stream.
2643  *
2644  * <i>length</i> must be a non-negative integer or <code>nil</code>.
2645  *
2646  * If <i>length</i> is a positive integer,
2647  * it try to read <i>length</i> bytes without any conversion (binary mode).
2648  * It returns <code>nil</code> or a string whose length is 1 to <i>length</i> bytes.
2649  * <code>nil</code> means it met EOF at beginning.
2650  * The 1 to <i>length</i>-1 bytes string means it met EOF after reading the result.
2651  * The <i>length</i> bytes string means it doesn't meet EOF.
2652  * The resulted string is always ASCII-8BIT encoding.
2653  *
2654  * If <i>length</i> is omitted or is <code>nil</code>,
2655  * it reads until EOF and the encoding conversion is applied.
2656  * It returns a string even if EOF is met at beginning.
2657  *
2658  * If <i>length</i> is zero, it returns <code>""</code>.
2659  *
2660  * If the optional <i>outbuf</i> argument is present, it must reference
2661  * a String, which will receive the data.
2662  * The <i>outbuf</i> will contain only the received data after the method call
2663  * even if it is not empty at the beginning.
2664  *
2665  * At end of file, it returns <code>nil</code> or <code>""</code>
2666  * depend on <i>length</i>.
2667  * <code><i>ios</i>.read()</code> and
2668  * <code><i>ios</i>.read(nil)</code> returns <code>""</code>.
2669  * <code><i>ios</i>.read(<i>positive-integer</i>)</code> returns <code>nil</code>.
2670  *
2671  * f = File.new("testfile")
2672  * f.read(16) #=> "This is line one"
2673  *
2674  * # reads whole file
2675  * open("file") {|f|
2676  * data = f.read # This returns a string even if the file is empty.
2677  * ...
2678  * }
2679  *
2680  * # iterate over fixed length records.
2681  * open("fixed-record-file") {|f|
2682  * while record = f.read(256)
2683  * ...
2684  * end
2685  * }
2686  *
2687  * # iterate over variable length records.
2688  * # record is prefixed by 32-bit length.
2689  * open("variable-record-file") {|f|
2690  * while len = f.read(4)
2691  * len = len.unpack("N")[0] # 32-bit length
2692  * record = f.read(len) # This returns a string even if len is 0.
2693  * end
2694  * }
2695  *
2696  * Note that this method behaves like fread() function in C.
2697  * This means it retry to invoke read(2) system call to read data with the specified length (or until EOF).
2698  * This behavior is preserved even if <i>ios</i> is non-blocking mode.
2699  * (This method is non-blocking flag insensitive as other methods.)
2700  * If you need the behavior like single read(2) system call,
2701  * consider readpartial, read_nonblock and sysread.
2702  */
2703 
2704 static VALUE
2706 {
2707  rb_io_t *fptr;
2708  long n, len;
2709  VALUE length, str;
2710 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
2711  int previous_mode;
2712 #endif
2713 
2714  rb_scan_args(argc, argv, "02", &length, &str);
2715 
2716  if (NIL_P(length)) {
2717  GetOpenFile(io, fptr);
2719  return read_all(fptr, remain_size(fptr), str);
2720  }
2721  len = NUM2LONG(length);
2722  if (len < 0) {
2723  rb_raise(rb_eArgError, "negative length %ld given", len);
2724  }
2725 
2726  io_setstrbuf(&str,len);
2727 
2728  GetOpenFile(io, fptr);
2730  if (len == 0) return str;
2731 
2732  READ_CHECK(fptr);
2733 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
2734  previous_mode = set_binary_mode_with_seek_cur(fptr);
2735 #endif
2736  n = io_fread(str, 0, len, fptr);
2737  io_set_read_length(str, n);
2738 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
2739  if (previous_mode == O_TEXT) {
2740  setmode(fptr->fd, O_TEXT);
2741  }
2742 #endif
2743  if (n == 0) return Qnil;
2744  OBJ_TAINT(str);
2745 
2746  return str;
2747 }
2748 
2749 static void
2750 rscheck(const char *rsptr, long rslen, VALUE rs)
2751 {
2752  if (!rs) return;
2753  if (RSTRING_PTR(rs) != rsptr && RSTRING_LEN(rs) != rslen)
2754  rb_raise(rb_eRuntimeError, "rs modified");
2755 }
2756 
2757 static int
2758 appendline(rb_io_t *fptr, int delim, VALUE *strp, long *lp)
2759 {
2760  VALUE str = *strp;
2761  long limit = *lp;
2762 
2763  if (NEED_READCONV(fptr)) {
2764  SET_BINARY_MODE(fptr);
2765  make_readconv(fptr, 0);
2766  do {
2767  const char *p, *e;
2768  int searchlen;
2769  if (fptr->cbuf.len) {
2770  p = fptr->cbuf.ptr+fptr->cbuf.off;
2771  searchlen = fptr->cbuf.len;
2772  if (0 < limit && limit < searchlen)
2773  searchlen = (int)limit;
2774  e = memchr(p, delim, searchlen);
2775  if (e) {
2776  int len = (int)(e-p+1);
2777  if (NIL_P(str))
2778  *strp = str = rb_str_new(p, len);
2779  else
2780  rb_str_buf_cat(str, p, len);
2781  fptr->cbuf.off += len;
2782  fptr->cbuf.len -= len;
2783  limit -= len;
2784  *lp = limit;
2785  return delim;
2786  }
2787 
2788  if (NIL_P(str))
2789  *strp = str = rb_str_new(p, searchlen);
2790  else
2791  rb_str_buf_cat(str, p, searchlen);
2792  fptr->cbuf.off += searchlen;
2793  fptr->cbuf.len -= searchlen;
2794  limit -= searchlen;
2795 
2796  if (limit == 0) {
2797  *lp = limit;
2798  return (unsigned char)RSTRING_PTR(str)[RSTRING_LEN(str)-1];
2799  }
2800  }
2801  } while (more_char(fptr) != MORE_CHAR_FINISHED);
2802  clear_readconv(fptr);
2803  *lp = limit;
2804  return EOF;
2805  }
2806 
2808  do {
2809  long pending = READ_DATA_PENDING_COUNT(fptr);
2810  if (pending > 0) {
2811  const char *p = READ_DATA_PENDING_PTR(fptr);
2812  const char *e;
2813  long last;
2814 
2815  if (limit > 0 && pending > limit) pending = limit;
2816  e = memchr(p, delim, pending);
2817  if (e) pending = e - p + 1;
2818  if (!NIL_P(str)) {
2819  last = RSTRING_LEN(str);
2820  rb_str_resize(str, last + pending);
2821  }
2822  else {
2823  last = 0;
2824  *strp = str = rb_str_buf_new(pending);
2825  rb_str_set_len(str, pending);
2826  }
2827  read_buffered_data(RSTRING_PTR(str) + last, pending, fptr); /* must not fail */
2828  limit -= pending;
2829  *lp = limit;
2830  if (e) return delim;
2831  if (limit == 0)
2832  return (unsigned char)RSTRING_PTR(str)[RSTRING_LEN(str)-1];
2833  }
2834  READ_CHECK(fptr);
2835  } while (io_fillbuf(fptr) >= 0);
2836  *lp = limit;
2837  return EOF;
2838 }
2839 
2840 static inline int
2841 swallow(rb_io_t *fptr, int term)
2842 {
2843  if (NEED_READCONV(fptr)) {
2844  rb_encoding *enc = io_read_encoding(fptr);
2845  int needconv = rb_enc_mbminlen(enc) != 1;
2846  SET_BINARY_MODE(fptr);
2847  make_readconv(fptr, 0);
2848  do {
2849  size_t cnt;
2850  while ((cnt = READ_CHAR_PENDING_COUNT(fptr)) > 0) {
2851  const char *p = READ_CHAR_PENDING_PTR(fptr);
2852  int i;
2853  if (!needconv) {
2854  if (*p != term) return TRUE;
2855  i = (int)cnt;
2856  while (--i && *++p == term);
2857  }
2858  else {
2859  const char *e = p + cnt;
2860  if (rb_enc_ascget(p, e, &i, enc) != term) return TRUE;
2861  while ((p += i) < e && rb_enc_ascget(p, e, &i, enc) == term);
2862  i = (int)(e - p);
2863  }
2864  io_shift_cbuf(fptr, (int)cnt - i, NULL);
2865  }
2866  } while (more_char(fptr) != MORE_CHAR_FINISHED);
2867  return FALSE;
2868  }
2869 
2871  do {
2872  size_t cnt;
2873  while ((cnt = READ_DATA_PENDING_COUNT(fptr)) > 0) {
2874  char buf[1024];
2875  const char *p = READ_DATA_PENDING_PTR(fptr);
2876  int i;
2877  if (cnt > sizeof buf) cnt = sizeof buf;
2878  if (*p != term) return TRUE;
2879  i = (int)cnt;
2880  while (--i && *++p == term);
2881  if (!read_buffered_data(buf, cnt - i, fptr)) /* must not fail */
2882  rb_sys_fail_path(fptr->pathv);
2883  }
2884  READ_CHECK(fptr);
2885  } while (io_fillbuf(fptr) == 0);
2886  return FALSE;
2887 }
2888 
2889 static VALUE
2891 {
2892  VALUE str = Qnil;
2893  int len = 0;
2894  long pos = 0;
2895  int cr = 0;
2896 
2897  for (;;) {
2898  int pending = READ_DATA_PENDING_COUNT(fptr);
2899 
2900  if (pending > 0) {
2901  const char *p = READ_DATA_PENDING_PTR(fptr);
2902  const char *e;
2903 
2904  e = memchr(p, '\n', pending);
2905  if (e) {
2906  pending = (int)(e - p + 1);
2907  }
2908  if (NIL_P(str)) {
2909  str = rb_str_new(p, pending);
2910  fptr->rbuf.off += pending;
2911  fptr->rbuf.len -= pending;
2912  }
2913  else {
2914  rb_str_resize(str, len + pending);
2915  read_buffered_data(RSTRING_PTR(str)+len, pending, fptr);
2916  }
2917  len += pending;
2918  if (cr != ENC_CODERANGE_BROKEN)
2919  pos += rb_str_coderange_scan_restartable(RSTRING_PTR(str) + pos, RSTRING_PTR(str) + len, enc, &cr);
2920  if (e) break;
2921  }
2922  READ_CHECK(fptr);
2923  if (io_fillbuf(fptr) < 0) {
2924  if (NIL_P(str)) return Qnil;
2925  break;
2926  }
2927  }
2928 
2929  str = io_enc_str(str, fptr);
2930  ENC_CODERANGE_SET(str, cr);
2931  fptr->lineno++;
2932  if (io == ARGF.current_file) {
2933  ARGF.lineno++;
2934  ARGF.last_lineno = ARGF.lineno;
2935  }
2936  else {
2937  ARGF.last_lineno = fptr->lineno;
2938  }
2939 
2940  return str;
2941 }
2942 
2943 static void
2944 prepare_getline_args(int argc, VALUE *argv, VALUE *rsp, long *limit, VALUE io)
2945 {
2946  VALUE rs = rb_rs, lim = Qnil;
2947  rb_io_t *fptr;
2948 
2949  if (argc == 1) {
2950  VALUE tmp = Qnil;
2951 
2952  if (NIL_P(argv[0]) || !NIL_P(tmp = rb_check_string_type(argv[0]))) {
2953  rs = tmp;
2954  }
2955  else {
2956  lim = argv[0];
2957  }
2958  }
2959  else if (2 <= argc) {
2960  rb_scan_args(argc, argv, "2", &rs, &lim);
2961  if (!NIL_P(rs))
2962  StringValue(rs);
2963  }
2964  if (!NIL_P(rs)) {
2965  rb_encoding *enc_rs, *enc_io;
2966 
2967  GetOpenFile(io, fptr);
2968  enc_rs = rb_enc_get(rs);
2969  enc_io = io_read_encoding(fptr);
2970  if (enc_io != enc_rs &&
2972  (RSTRING_LEN(rs) > 0 && !rb_enc_asciicompat(enc_io)))) {
2973  if (rs == rb_default_rs) {
2974  rs = rb_enc_str_new(0, 0, enc_io);
2975  rb_str_buf_cat_ascii(rs, "\n");
2976  }
2977  else {
2978  rb_raise(rb_eArgError, "encoding mismatch: %s IO with %s RS",
2979  rb_enc_name(enc_io),
2980  rb_enc_name(enc_rs));
2981  }
2982  }
2983  }
2984  *rsp = rs;
2985  *limit = NIL_P(lim) ? -1L : NUM2LONG(lim);
2986 }
2987 
2988 static VALUE
2989 rb_io_getline_1(VALUE rs, long limit, VALUE io)
2990 {
2991  VALUE str = Qnil;
2992  rb_io_t *fptr;
2993  int nolimit = 0;
2994  rb_encoding *enc;
2995 
2996  GetOpenFile(io, fptr);
2998  if (NIL_P(rs) && limit < 0) {
2999  str = read_all(fptr, 0, Qnil);
3000  if (RSTRING_LEN(str) == 0) return Qnil;
3001  }
3002  else if (limit == 0) {
3003  return rb_enc_str_new(0, 0, io_read_encoding(fptr));
3004  }
3005  else if (rs == rb_default_rs && limit < 0 && !NEED_READCONV(fptr) &&
3006  rb_enc_asciicompat(enc = io_read_encoding(fptr))) {
3008  return rb_io_getline_fast(fptr, enc, io);
3009  }
3010  else {
3011  int c, newline = -1;
3012  const char *rsptr = 0;
3013  long rslen = 0;
3014  int rspara = 0;
3015  int extra_limit = 16;
3016 
3017  SET_BINARY_MODE(fptr);
3018  enc = io_read_encoding(fptr);
3019 
3020  if (!NIL_P(rs)) {
3021  rslen = RSTRING_LEN(rs);
3022  if (rslen == 0) {
3023  rsptr = "\n\n";
3024  rslen = 2;
3025  rspara = 1;
3026  swallow(fptr, '\n');
3027  rs = 0;
3028  if (!rb_enc_asciicompat(enc)) {
3029  rs = rb_usascii_str_new(rsptr, rslen);
3030  rs = rb_str_encode(rs, rb_enc_from_encoding(enc), 0, Qnil);
3031  OBJ_FREEZE(rs);
3032  rsptr = RSTRING_PTR(rs);
3033  rslen = RSTRING_LEN(rs);
3034  }
3035  }
3036  else {
3037  rsptr = RSTRING_PTR(rs);
3038  }
3039  newline = (unsigned char)rsptr[rslen - 1];
3040  }
3041 
3042  /* MS - Optimisation */
3043  while ((c = appendline(fptr, newline, &str, &limit)) != EOF) {
3044  const char *s, *p, *pp, *e;
3045 
3046  if (c == newline) {
3047  if (RSTRING_LEN(str) < rslen) continue;
3048  s = RSTRING_PTR(str);
3049  e = s + RSTRING_LEN(str);
3050  p = e - rslen;
3051  pp = rb_enc_left_char_head(s, p, e, enc);
3052  if (pp != p) continue;
3053  if (!rspara) rscheck(rsptr, rslen, rs);
3054  if (memcmp(p, rsptr, rslen) == 0) break;
3055  }
3056  if (limit == 0) {
3057  s = RSTRING_PTR(str);
3058  p = s + RSTRING_LEN(str);
3059  pp = rb_enc_left_char_head(s, p-1, p, enc);
3060  if (extra_limit &&
3062  /* relax the limit while incomplete character.
3063  * extra_limit limits the relax length */
3064  limit = 1;
3065  extra_limit--;
3066  }
3067  else {
3068  nolimit = 1;
3069  break;
3070  }
3071  }
3072  }
3073 
3074  if (rspara) {
3075  if (c != EOF) {
3076  swallow(fptr, '\n');
3077  }
3078  }
3079  if (!NIL_P(str))
3080  str = io_enc_str(str, fptr);
3081  }
3082 
3083  if (!NIL_P(str)) {
3084  if (!nolimit) {
3085  fptr->lineno++;
3086  if (io == ARGF.current_file) {
3087  ARGF.lineno++;
3088  ARGF.last_lineno = ARGF.lineno;
3089  }
3090  else {
3091  ARGF.last_lineno = fptr->lineno;
3092  }
3093  }
3094  }
3095 
3096  return str;
3097 }
3098 
3099 static VALUE
3101 {
3102  VALUE rs;
3103  long limit;
3104 
3105  prepare_getline_args(argc, argv, &rs, &limit, io);
3106  return rb_io_getline_1(rs, limit, io);
3107 }
3108 
3109 VALUE
3111 {
3112  return rb_io_getline_1(rb_default_rs, -1, io);
3113 }
3114 
3115 /*
3116  * call-seq:
3117  * ios.gets(sep=$/) -> string or nil
3118  * ios.gets(limit) -> string or nil
3119  * ios.gets(sep, limit) -> string or nil
3120  *
3121  * Reads the next ``line'' from the I/O stream; lines are separated by
3122  * <i>sep</i>. A separator of <code>nil</code> reads the entire
3123  * contents, and a zero-length separator reads the input a paragraph at
3124  * a time (two successive newlines in the input separate paragraphs).
3125  * The stream must be opened for reading or an <code>IOError</code>
3126  * will be raised. The line read in will be returned and also assigned
3127  * to <code>$_</code>. Returns <code>nil</code> if called at end of
3128  * file. If the first argument is an integer, or optional second
3129  * argument is given, the returning string would not be longer than the
3130  * given value in bytes.
3131  *
3132  * File.new("testfile").gets #=> "This is line one\n"
3133  * $_ #=> "This is line one\n"
3134  */
3135 
3136 static VALUE
3138 {
3139  VALUE str;
3140 
3141  str = rb_io_getline(argc, argv, io);
3142  rb_lastline_set(str);
3143 
3144  return str;
3145 }
3146 
3147 /*
3148  * call-seq:
3149  * ios.lineno -> integer
3150  *
3151  * Returns the current line number in <em>ios</em>. The stream must be
3152  * opened for reading. <code>lineno</code> counts the number of times
3153  * #gets is called rather than the number of newlines encountered. The two
3154  * values will differ if #gets is called with a separator other than newline.
3155  *
3156  * Methods that use <code>$/</code> like #each, #lines and #readline will
3157  * also increment <code>lineno</code>.
3158  *
3159  * See also the <code>$.</code> variable.
3160  *
3161  * f = File.new("testfile")
3162  * f.lineno #=> 0
3163  * f.gets #=> "This is line one\n"
3164  * f.lineno #=> 1
3165  * f.gets #=> "This is line two\n"
3166  * f.lineno #=> 2
3167  */
3168 
3169 static VALUE
3171 {
3172  rb_io_t *fptr;
3173 
3174  GetOpenFile(io, fptr);
3176  return INT2NUM(fptr->lineno);
3177 }
3178 
3179 /*
3180  * call-seq:
3181  * ios.lineno = integer -> integer
3182  *
3183  * Manually sets the current line number to the given value.
3184  * <code>$.</code> is updated only on the next read.
3185  *
3186  * f = File.new("testfile")
3187  * f.gets #=> "This is line one\n"
3188  * $. #=> 1
3189  * f.lineno = 1000
3190  * f.lineno #=> 1000
3191  * $. #=> 1 # lineno of last read
3192  * f.gets #=> "This is line two\n"
3193  * $. #=> 1001 # lineno of last read
3194  */
3195 
3196 static VALUE
3198 {
3199  rb_io_t *fptr;
3200 
3201  GetOpenFile(io, fptr);
3203  fptr->lineno = NUM2INT(lineno);
3204  return lineno;
3205 }
3206 
3207 /*
3208  * call-seq:
3209  * ios.readline(sep=$/) -> string
3210  * ios.readline(limit) -> string
3211  * ios.readline(sep, limit) -> string
3212  *
3213  * Reads a line as with <code>IO#gets</code>, but raises an
3214  * <code>EOFError</code> on end of file.
3215  */
3216 
3217 static VALUE
3219 {
3220  VALUE line = rb_io_gets_m(argc, argv, io);
3221 
3222  if (NIL_P(line)) {
3223  rb_eof_error();
3224  }
3225  return line;
3226 }
3227 
3228 /*
3229  * call-seq:
3230  * ios.readlines(sep=$/) -> array
3231  * ios.readlines(limit) -> array
3232  * ios.readlines(sep, limit) -> array
3233  *
3234  * Reads all of the lines in <em>ios</em>, and returns them in
3235  * <i>anArray</i>. Lines are separated by the optional <i>sep</i>. If
3236  * <i>sep</i> is <code>nil</code>, the rest of the stream is returned
3237  * as a single record. If the first argument is an integer, or
3238  * optional second argument is given, the returning string would not be
3239  * longer than the given value in bytes. The stream must be opened for
3240  * reading or an <code>IOError</code> will be raised.
3241  *
3242  * f = File.new("testfile")
3243  * f.readlines[0] #=> "This is line one\n"
3244  */
3245 
3246 static VALUE
3248 {
3249  VALUE line, ary, rs;
3250  long limit;
3251 
3252  prepare_getline_args(argc, argv, &rs, &limit, io);
3253  if (limit == 0)
3254  rb_raise(rb_eArgError, "invalid limit: 0 for readlines");
3255  ary = rb_ary_new();
3256  while (!NIL_P(line = rb_io_getline_1(rs, limit, io))) {
3257  rb_ary_push(ary, line);
3258  }
3259  return ary;
3260 }
3261 
3262 /*
3263  * call-seq:
3264  * ios.each(sep=$/) {|line| block } -> ios
3265  * ios.each(limit) {|line| block } -> ios
3266  * ios.each(sep,limit) {|line| block } -> ios
3267  * ios.each(...) -> an_enumerator
3268  *
3269  * ios.each_line(sep=$/) {|line| block } -> ios
3270  * ios.each_line(limit) {|line| block } -> ios
3271  * ios.each_line(sep,limit) {|line| block } -> ios
3272  * ios.each_line(...) -> an_enumerator
3273  *
3274  * Executes the block for every line in <em>ios</em>, where lines are
3275  * separated by <i>sep</i>. <em>ios</em> must be opened for
3276  * reading or an <code>IOError</code> will be raised.
3277  *
3278  * If no block is given, an enumerator is returned instead.
3279  *
3280  * f = File.new("testfile")
3281  * f.each {|line| puts "#{f.lineno}: #{line}" }
3282  *
3283  * <em>produces:</em>
3284  *
3285  * 1: This is line one
3286  * 2: This is line two
3287  * 3: This is line three
3288  * 4: And so on...
3289  */
3290 
3291 static VALUE
3293 {
3294  VALUE str, rs;
3295  long limit;
3296 
3297  RETURN_ENUMERATOR(io, argc, argv);
3298  prepare_getline_args(argc, argv, &rs, &limit, io);
3299  if (limit == 0)
3300  rb_raise(rb_eArgError, "invalid limit: 0 for each_line");
3301  while (!NIL_P(str = rb_io_getline_1(rs, limit, io))) {
3302  rb_yield(str);
3303  }
3304  return io;
3305 }
3306 
3307 /*
3308  * This is a deprecated alias for <code>each_line</code>.
3309  */
3310 
3311 static VALUE
3313 {
3314  rb_warn("IO#lines is deprecated; use #each_line instead");
3315  if (!rb_block_given_p())
3316  return rb_enumeratorize(io, ID2SYM(rb_intern("each_line")), argc, argv);
3317  return rb_io_each_line(argc, argv, io);
3318 }
3319 
3320 /*
3321  * call-seq:
3322  * ios.each_byte {|byte| block } -> ios
3323  * ios.each_byte -> an_enumerator
3324  *
3325  * Calls the given block once for each byte (0..255) in <em>ios</em>,
3326  * passing the byte as an argument. The stream must be opened for
3327  * reading or an <code>IOError</code> will be raised.
3328  *
3329  * If no block is given, an enumerator is returned instead.
3330  *
3331  * f = File.new("testfile")
3332  * checksum = 0
3333  * f.each_byte {|x| checksum ^= x } #=> #<File:testfile>
3334  * checksum #=> 12
3335  */
3336 
3337 static VALUE
3339 {
3340  rb_io_t *fptr;
3341 
3342  RETURN_ENUMERATOR(io, 0, 0);
3343  GetOpenFile(io, fptr);
3344 
3345  for (;;) {
3346  while (fptr->rbuf.len > 0) {
3347  char *p = fptr->rbuf.ptr + fptr->rbuf.off++;
3348  fptr->rbuf.len--;
3349  rb_yield(INT2FIX(*p & 0xff));
3350  errno = 0;
3351  }
3353  READ_CHECK(fptr);
3354  if (io_fillbuf(fptr) < 0) {
3355  break;
3356  }
3357  }
3358  return io;
3359 }
3360 
3361 /*
3362  * This is a deprecated alias for <code>each_byte</code>.
3363  */
3364 
3365 static VALUE
3367 {
3368  rb_warn("IO#bytes is deprecated; use #each_byte instead");
3369  if (!rb_block_given_p())
3370  return rb_enumeratorize(io, ID2SYM(rb_intern("each_byte")), 0, 0);
3371  return rb_io_each_byte(io);
3372 }
3373 
3374 static VALUE
3376 {
3377  int r, n, cr = 0;
3378  VALUE str;
3379 
3380  if (NEED_READCONV(fptr)) {
3381  VALUE str = Qnil;
3382  rb_encoding *read_enc = io_read_encoding(fptr);
3383 
3384  SET_BINARY_MODE(fptr);
3385  make_readconv(fptr, 0);
3386 
3387  while (1) {
3388  if (fptr->cbuf.len) {
3389  r = rb_enc_precise_mbclen(fptr->cbuf.ptr+fptr->cbuf.off,
3390  fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
3391  read_enc);
3392  if (!MBCLEN_NEEDMORE_P(r))
3393  break;
3394  if (fptr->cbuf.len == fptr->cbuf.capa) {
3395  rb_raise(rb_eIOError, "too long character");
3396  }
3397  }
3398 
3399  if (more_char(fptr) == MORE_CHAR_FINISHED) {
3400  if (fptr->cbuf.len == 0) {
3401  clear_readconv(fptr);
3402  return Qnil;
3403  }
3404  /* return an unit of an incomplete character just before EOF */
3405  str = rb_enc_str_new(fptr->cbuf.ptr+fptr->cbuf.off, 1, read_enc);
3406  fptr->cbuf.off += 1;
3407  fptr->cbuf.len -= 1;
3408  if (fptr->cbuf.len == 0) clear_readconv(fptr);
3410  return str;
3411  }
3412  }
3413  if (MBCLEN_INVALID_P(r)) {
3414  r = rb_enc_mbclen(fptr->cbuf.ptr+fptr->cbuf.off,
3415  fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
3416  read_enc);
3417  io_shift_cbuf(fptr, r, &str);
3418  cr = ENC_CODERANGE_BROKEN;
3419  }
3420  else {
3421  io_shift_cbuf(fptr, MBCLEN_CHARFOUND_LEN(r), &str);
3422  cr = ENC_CODERANGE_VALID;
3423  if (MBCLEN_CHARFOUND_LEN(r) == 1 && rb_enc_asciicompat(read_enc) &&
3424  ISASCII(RSTRING_PTR(str)[0])) {
3425  cr = ENC_CODERANGE_7BIT;
3426  }
3427  }
3428  str = io_enc_str(str, fptr);
3429  ENC_CODERANGE_SET(str, cr);
3430  return str;
3431  }
3432 
3434  if (io_fillbuf(fptr) < 0) {
3435  return Qnil;
3436  }
3437  if (rb_enc_asciicompat(enc) && ISASCII(fptr->rbuf.ptr[fptr->rbuf.off])) {
3438  str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, 1);
3439  fptr->rbuf.off += 1;
3440  fptr->rbuf.len -= 1;
3441  cr = ENC_CODERANGE_7BIT;
3442  }
3443  else {
3444  r = rb_enc_precise_mbclen(fptr->rbuf.ptr+fptr->rbuf.off, fptr->rbuf.ptr+fptr->rbuf.off+fptr->rbuf.len, enc);
3445  if (MBCLEN_CHARFOUND_P(r) &&
3446  (n = MBCLEN_CHARFOUND_LEN(r)) <= fptr->rbuf.len) {
3447  str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, n);
3448  fptr->rbuf.off += n;
3449  fptr->rbuf.len -= n;
3450  cr = ENC_CODERANGE_VALID;
3451  }
3452  else if (MBCLEN_NEEDMORE_P(r)) {
3453  str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, fptr->rbuf.len);
3454  fptr->rbuf.len = 0;
3455  getc_needmore:
3456  if (io_fillbuf(fptr) != -1) {
3457  rb_str_cat(str, fptr->rbuf.ptr+fptr->rbuf.off, 1);
3458  fptr->rbuf.off++;
3459  fptr->rbuf.len--;
3460  r = rb_enc_precise_mbclen(RSTRING_PTR(str), RSTRING_PTR(str)+RSTRING_LEN(str), enc);
3461  if (MBCLEN_NEEDMORE_P(r)) {
3462  goto getc_needmore;
3463  }
3464  else if (MBCLEN_CHARFOUND_P(r)) {
3465  cr = ENC_CODERANGE_VALID;
3466  }
3467  }
3468  }
3469  else {
3470  str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, 1);
3471  fptr->rbuf.off++;
3472  fptr->rbuf.len--;
3473  }
3474  }
3475  if (!cr) cr = ENC_CODERANGE_BROKEN;
3476  str = io_enc_str(str, fptr);
3477  ENC_CODERANGE_SET(str, cr);
3478  return str;
3479 }
3480 
3481 /*
3482  * call-seq:
3483  * ios.each_char {|c| block } -> ios
3484  * ios.each_char -> an_enumerator
3485  *
3486  * Calls the given block once for each character in <em>ios</em>,
3487  * passing the character as an argument. The stream must be opened for
3488  * reading or an <code>IOError</code> will be raised.
3489  *
3490  * If no block is given, an enumerator is returned instead.
3491  *
3492  * f = File.new("testfile")
3493  * f.each_char {|c| print c, ' ' } #=> #<File:testfile>
3494  */
3495 
3496 static VALUE
3498 {
3499  rb_io_t *fptr;
3500  rb_encoding *enc;
3501  VALUE c;
3502 
3503  RETURN_ENUMERATOR(io, 0, 0);
3504  GetOpenFile(io, fptr);
3506 
3507  enc = io_input_encoding(fptr);
3508  READ_CHECK(fptr);
3509  while (!NIL_P(c = io_getc(fptr, enc))) {
3510  rb_yield(c);
3511  }
3512  return io;
3513 }
3514 
3515 /*
3516  * This is a deprecated alias for <code>each_char</code>.
3517  */
3518 
3519 static VALUE
3521 {
3522  rb_warn("IO#chars is deprecated; use #each_char instead");
3523  if (!rb_block_given_p())
3524  return rb_enumeratorize(io, ID2SYM(rb_intern("each_char")), 0, 0);
3525  return rb_io_each_char(io);
3526 }
3527 
3528 
3529 /*
3530  * call-seq:
3531  * ios.each_codepoint {|c| block } -> ios
3532  * ios.codepoints {|c| block } -> ios
3533  * ios.each_codepoint -> an_enumerator
3534  * ios.codepoints -> an_enumerator
3535  *
3536  * Passes the <code>Integer</code> ordinal of each character in <i>ios</i>,
3537  * passing the codepoint as an argument. The stream must be opened for
3538  * reading or an <code>IOError</code> will be raised.
3539  *
3540  * If no block is given, an enumerator is returned instead.
3541  *
3542  */
3543 
3544 static VALUE
3546 {
3547  rb_io_t *fptr;
3548  rb_encoding *enc;
3549  unsigned int c;
3550  int r, n;
3551 
3552  RETURN_ENUMERATOR(io, 0, 0);
3553  GetOpenFile(io, fptr);
3555 
3556  READ_CHECK(fptr);
3557  if (NEED_READCONV(fptr)) {
3558  SET_BINARY_MODE(fptr);
3559  for (;;) {
3560  make_readconv(fptr, 0);
3561  for (;;) {
3562  if (fptr->cbuf.len) {
3563  if (fptr->encs.enc)
3564  r = rb_enc_precise_mbclen(fptr->cbuf.ptr+fptr->cbuf.off,
3565  fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
3566  fptr->encs.enc);
3567  else
3569  if (!MBCLEN_NEEDMORE_P(r))
3570  break;
3571  if (fptr->cbuf.len == fptr->cbuf.capa) {
3572  rb_raise(rb_eIOError, "too long character");
3573  }
3574  }
3575  if (more_char(fptr) == MORE_CHAR_FINISHED) {
3576  clear_readconv(fptr);
3577  /* ignore an incomplete character before EOF */
3578  return io;
3579  }
3580  }
3581  if (MBCLEN_INVALID_P(r)) {
3582  rb_raise(rb_eArgError, "invalid byte sequence in %s",
3583  rb_enc_name(fptr->encs.enc));
3584  }
3585  n = MBCLEN_CHARFOUND_LEN(r);
3586  if (fptr->encs.enc) {
3587  c = rb_enc_codepoint(fptr->cbuf.ptr+fptr->cbuf.off,
3588  fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
3589  fptr->encs.enc);
3590  }
3591  else {
3592  c = (unsigned char)fptr->cbuf.ptr[fptr->cbuf.off];
3593  }
3594  fptr->cbuf.off += n;
3595  fptr->cbuf.len -= n;
3596  rb_yield(UINT2NUM(c));
3597  }
3598  }
3600  enc = io_input_encoding(fptr);
3601  for (;;) {
3602  if (io_fillbuf(fptr) < 0) {
3603  return io;
3604  }
3605  r = rb_enc_precise_mbclen(fptr->rbuf.ptr+fptr->rbuf.off,
3606  fptr->rbuf.ptr+fptr->rbuf.off+fptr->rbuf.len, enc);
3607  if (MBCLEN_CHARFOUND_P(r) &&
3608  (n = MBCLEN_CHARFOUND_LEN(r)) <= fptr->rbuf.len) {
3609  c = rb_enc_codepoint(fptr->rbuf.ptr+fptr->rbuf.off,
3610  fptr->rbuf.ptr+fptr->rbuf.off+fptr->rbuf.len, enc);
3611  fptr->rbuf.off += n;
3612  fptr->rbuf.len -= n;
3613  rb_yield(UINT2NUM(c));
3614  }
3615  else if (MBCLEN_INVALID_P(r)) {
3616  rb_raise(rb_eArgError, "invalid byte sequence in %s", rb_enc_name(enc));
3617  }
3618  else {
3619  continue;
3620  }
3621  }
3622  return io;
3623 }
3624 
3625 /*
3626  * This is a deprecated alias for <code>each_codepoint</code>.
3627  */
3628 
3629 static VALUE
3631 {
3632  rb_warn("IO#codepoints is deprecated; use #each_codepoint instead");
3633  if (!rb_block_given_p())
3634  return rb_enumeratorize(io, ID2SYM(rb_intern("each_codepoint")), 0, 0);
3635  return rb_io_each_codepoint(io);
3636 }
3637 
3638 
3639 /*
3640  * call-seq:
3641  * ios.getc -> string or nil
3642  *
3643  * Reads a one-character string from <em>ios</em>. Returns
3644  * <code>nil</code> if called at end of file.
3645  *
3646  * f = File.new("testfile")
3647  * f.getc #=> "h"
3648  * f.getc #=> "e"
3649  */
3650 
3651 static VALUE
3653 {
3654  rb_io_t *fptr;
3655  rb_encoding *enc;
3656 
3657  GetOpenFile(io, fptr);
3659 
3660  enc = io_input_encoding(fptr);
3661  READ_CHECK(fptr);
3662  return io_getc(fptr, enc);
3663 }
3664 
3665 /*
3666  * call-seq:
3667  * ios.readchar -> string
3668  *
3669  * Reads a one-character string from <em>ios</em>. Raises an
3670  * <code>EOFError</code> on end of file.
3671  *
3672  * f = File.new("testfile")
3673  * f.readchar #=> "h"
3674  * f.readchar #=> "e"
3675  */
3676 
3677 static VALUE
3679 {
3680  VALUE c = rb_io_getc(io);
3681 
3682  if (NIL_P(c)) {
3683  rb_eof_error();
3684  }
3685  return c;
3686 }
3687 
3688 /*
3689  * call-seq:
3690  * ios.getbyte -> fixnum or nil
3691  *
3692  * Gets the next 8-bit byte (0..255) from <em>ios</em>. Returns
3693  * <code>nil</code> if called at end of file.
3694  *
3695  * f = File.new("testfile")
3696  * f.getbyte #=> 84
3697  * f.getbyte #=> 104
3698  */
3699 
3700 VALUE
3702 {
3703  rb_io_t *fptr;
3704  int c;
3705 
3706  GetOpenFile(io, fptr);
3708  READ_CHECK(fptr);
3709  if (fptr->fd == 0 && (fptr->mode & FMODE_TTY) && RB_TYPE_P(rb_stdout, T_FILE)) {
3710  rb_io_t *ofp;
3711  GetOpenFile(rb_stdout, ofp);
3712  if (ofp->mode & FMODE_TTY) {
3714  }
3715  }
3716  if (io_fillbuf(fptr) < 0) {
3717  return Qnil;
3718  }
3719  fptr->rbuf.off++;
3720  fptr->rbuf.len--;
3721  c = (unsigned char)fptr->rbuf.ptr[fptr->rbuf.off-1];
3722  return INT2FIX(c & 0xff);
3723 }
3724 
3725 /*
3726  * call-seq:
3727  * ios.readbyte -> fixnum
3728  *
3729  * Reads a byte as with <code>IO#getbyte</code>, but raises an
3730  * <code>EOFError</code> on end of file.
3731  */
3732 
3733 static VALUE
3735 {
3736  VALUE c = rb_io_getbyte(io);
3737 
3738  if (NIL_P(c)) {
3739  rb_eof_error();
3740  }
3741  return c;
3742 }
3743 
3744 /*
3745  * call-seq:
3746  * ios.ungetbyte(string) -> nil
3747  * ios.ungetbyte(integer) -> nil
3748  *
3749  * Pushes back bytes (passed as a parameter) onto <em>ios</em>,
3750  * such that a subsequent buffered read will return it. Only one byte
3751  * may be pushed back before a subsequent read operation (that is,
3752  * you will be able to read only the last of several bytes that have been pushed
3753  * back). Has no effect with unbuffered reads (such as <code>IO#sysread</code>).
3754  *
3755  * f = File.new("testfile") #=> #<File:testfile>
3756  * b = f.getbyte #=> 0x38
3757  * f.ungetbyte(b) #=> nil
3758  * f.getbyte #=> 0x38
3759  */
3760 
3761 VALUE
3763 {
3764  rb_io_t *fptr;
3765 
3766  GetOpenFile(io, fptr);
3768  if (NIL_P(b)) return Qnil;
3769  if (FIXNUM_P(b)) {
3770  char cc = FIX2INT(b);
3771  b = rb_str_new(&cc, 1);
3772  }
3773  else {
3774  SafeStringValue(b);
3775  }
3776  io_ungetbyte(b, fptr);
3777  return Qnil;
3778 }
3779 
3780 /*
3781  * call-seq:
3782  * ios.ungetc(string) -> nil
3783  *
3784  * Pushes back one character (passed as a parameter) onto <em>ios</em>,
3785  * such that a subsequent buffered character read will return it. Only one character
3786  * may be pushed back before a subsequent read operation (that is,
3787  * you will be able to read only the last of several characters that have been pushed
3788  * back). Has no effect with unbuffered reads (such as <code>IO#sysread</code>).
3789  *
3790  * f = File.new("testfile") #=> #<File:testfile>
3791  * c = f.getc #=> "8"
3792  * f.ungetc(c) #=> nil
3793  * f.getc #=> "8"
3794  */
3795 
3796 VALUE
3798 {
3799  rb_io_t *fptr;
3800  long len;
3801 
3802  GetOpenFile(io, fptr);
3804  if (NIL_P(c)) return Qnil;
3805  if (FIXNUM_P(c)) {
3806  c = rb_enc_uint_chr(FIX2UINT(c), io_read_encoding(fptr));
3807  }
3808  else if (RB_TYPE_P(c, T_BIGNUM)) {
3809  c = rb_enc_uint_chr(NUM2UINT(c), io_read_encoding(fptr));
3810  }
3811  else {
3812  SafeStringValue(c);
3813  }
3814  if (NEED_READCONV(fptr)) {
3815  SET_BINARY_MODE(fptr);
3816  len = RSTRING_LEN(c);
3817 #if SIZEOF_LONG > SIZEOF_INT
3818  if (len > INT_MAX)
3819  rb_raise(rb_eIOError, "ungetc failed");
3820 #endif
3821  make_readconv(fptr, (int)len);
3822  if (fptr->cbuf.capa - fptr->cbuf.len < len)
3823  rb_raise(rb_eIOError, "ungetc failed");
3824  if (fptr->cbuf.off < len) {
3825  MEMMOVE(fptr->cbuf.ptr+fptr->cbuf.capa-fptr->cbuf.len,
3826  fptr->cbuf.ptr+fptr->cbuf.off,
3827  char, fptr->cbuf.len);
3828  fptr->cbuf.off = fptr->cbuf.capa-fptr->cbuf.len;
3829  }
3830  fptr->cbuf.off -= (int)len;
3831  fptr->cbuf.len += (int)len;
3832  MEMMOVE(fptr->cbuf.ptr+fptr->cbuf.off, RSTRING_PTR(c), char, len);
3833  }
3834  else {
3836  io_ungetbyte(c, fptr);
3837  }
3838  return Qnil;
3839 }
3840 
3841 /*
3842  * call-seq:
3843  * ios.isatty -> true or false
3844  * ios.tty? -> true or false
3845  *
3846  * Returns <code>true</code> if <em>ios</em> is associated with a
3847  * terminal device (tty), <code>false</code> otherwise.
3848  *
3849  * File.new("testfile").isatty #=> false
3850  * File.new("/dev/tty").isatty #=> true
3851  */
3852 
3853 static VALUE
3855 {
3856  rb_io_t *fptr;
3857 
3858  GetOpenFile(io, fptr);
3859  if (isatty(fptr->fd) == 0)
3860  return Qfalse;
3861  return Qtrue;
3862 }
3863 
3864 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
3865 /*
3866  * call-seq:
3867  * ios.close_on_exec? -> true or false
3868  *
3869  * Returns <code>true</code> if <em>ios</em> will be closed on exec.
3870  *
3871  * f = open("/dev/null")
3872  * f.close_on_exec? #=> false
3873  * f.close_on_exec = true
3874  * f.close_on_exec? #=> true
3875  * f.close_on_exec = false
3876  * f.close_on_exec? #=> false
3877  */
3878 
3879 static VALUE
3881 {
3882  rb_io_t *fptr;
3883  VALUE write_io;
3884  int fd, ret;
3885 
3886  write_io = GetWriteIO(io);
3887  if (io != write_io) {
3888  GetOpenFile(write_io, fptr);
3889  if (fptr && 0 <= (fd = fptr->fd)) {
3890  if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
3891  if (!(ret & FD_CLOEXEC)) return Qfalse;
3892  }
3893  }
3894 
3895  GetOpenFile(io, fptr);
3896  if (fptr && 0 <= (fd = fptr->fd)) {
3897  if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
3898  if (!(ret & FD_CLOEXEC)) return Qfalse;
3899  }
3900  return Qtrue;
3901 }
3902 #else
3903 #define rb_io_close_on_exec_p rb_f_notimplement
3904 #endif
3905 
3906 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
3907 /*
3908  * call-seq:
3909  * ios.close_on_exec = bool -> true or false
3910  *
3911  * Sets a close-on-exec flag.
3912  *
3913  * f = open("/dev/null")
3914  * f.close_on_exec = true
3915  * system("cat", "/proc/self/fd/#{f.fileno}") # cat: /proc/self/fd/3: No such file or directory
3916  * f.closed? #=> false
3917  *
3918  * Ruby sets close-on-exec flags of all file descriptors by default
3919  * since Ruby 2.0.0.
3920  * So you don't need to set by yourself.
3921  * Also, unsetting a close-on-exec flag can cause file descriptor leak
3922  * if another thread use fork() and exec() (via system() method for example).
3923  * If you really needs file descriptor inheritance to child process,
3924  * use spawn()'s argument such as fd=>fd.
3925  */
3926 
3927 static VALUE
3929 {
3930  int flag = RTEST(arg) ? FD_CLOEXEC : 0;
3931  rb_io_t *fptr;
3932  VALUE write_io;
3933  int fd, ret;
3934 
3935  write_io = GetWriteIO(io);
3936  if (io != write_io) {
3937  GetOpenFile(write_io, fptr);
3938  if (fptr && 0 <= (fd = fptr->fd)) {
3939  if ((ret = fcntl(fptr->fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
3940  if ((ret & FD_CLOEXEC) != flag) {
3941  ret = (ret & ~FD_CLOEXEC) | flag;
3942  ret = fcntl(fd, F_SETFD, ret);
3943  if (ret == -1) rb_sys_fail_path(fptr->pathv);
3944  }
3945  }
3946 
3947  }
3948 
3949  GetOpenFile(io, fptr);
3950  if (fptr && 0 <= (fd = fptr->fd)) {
3951  if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
3952  if ((ret & FD_CLOEXEC) != flag) {
3953  ret = (ret & ~FD_CLOEXEC) | flag;
3954  ret = fcntl(fd, F_SETFD, ret);
3955  if (ret == -1) rb_sys_fail_path(fptr->pathv);
3956  }
3957  }
3958  return Qnil;
3959 }
3960 #else
3961 #define rb_io_set_close_on_exec rb_f_notimplement
3962 #endif
3963 
3964 #define FMODE_PREP (1<<16)
3965 #define IS_PREP_STDIO(f) ((f)->mode & FMODE_PREP)
3966 #define PREP_STDIO_NAME(f) (RSTRING_PTR((f)->pathv))
3967 
3968 static VALUE
3969 finish_writeconv(rb_io_t *fptr, int noalloc)
3970 {
3971  unsigned char *ds, *dp, *de;
3972  rb_econv_result_t res;
3973 
3974  if (!fptr->wbuf.ptr) {
3975  unsigned char buf[1024];
3976  long r;
3977 
3979  while (res == econv_destination_buffer_full) {
3980  ds = dp = buf;
3981  de = buf + sizeof(buf);
3982  res = rb_econv_convert(fptr->writeconv, NULL, NULL, &dp, de, 0);
3983  while (dp-ds) {
3984  retry:
3985  if (fptr->write_lock && rb_mutex_owned_p(fptr->write_lock))
3986  r = rb_write_internal2(fptr->fd, ds, dp-ds);
3987  else
3988  r = rb_write_internal(fptr->fd, ds, dp-ds);
3989  if (r == dp-ds)
3990  break;
3991  if (0 <= r) {
3992  ds += r;
3993  }
3994  if (rb_io_wait_writable(fptr->fd)) {
3995  if (fptr->fd < 0)
3996  return noalloc ? Qtrue : rb_exc_new3(rb_eIOError, rb_str_new_cstr("closed stream"));
3997  goto retry;
3998  }
3999  return noalloc ? Qtrue : INT2NUM(errno);
4000  }
4001  if (res == econv_invalid_byte_sequence ||
4002  res == econv_incomplete_input ||
4003  res == econv_undefined_conversion) {
4004  return noalloc ? Qtrue : rb_econv_make_exception(fptr->writeconv);
4005  }
4006  }
4007 
4008  return Qnil;
4009  }
4010 
4012  while (res == econv_destination_buffer_full) {
4013  if (fptr->wbuf.len == fptr->wbuf.capa) {
4014  if (io_fflush(fptr) < 0)
4015  return noalloc ? Qtrue : INT2NUM(errno);
4016  }
4017 
4018  ds = dp = (unsigned char *)fptr->wbuf.ptr + fptr->wbuf.off + fptr->wbuf.len;
4019  de = (unsigned char *)fptr->wbuf.ptr + fptr->wbuf.capa;
4020  res = rb_econv_convert(fptr->writeconv, NULL, NULL, &dp, de, 0);
4021  fptr->wbuf.len += (int)(dp - ds);
4022  if (res == econv_invalid_byte_sequence ||
4023  res == econv_incomplete_input ||
4024  res == econv_undefined_conversion) {
4025  return noalloc ? Qtrue : rb_econv_make_exception(fptr->writeconv);
4026  }
4027  }
4028  return Qnil;
4029 }
4030 
4033  int noalloc;
4034 };
4035 
4036 static VALUE
4038 {
4039  struct finish_writeconv_arg *p = (struct finish_writeconv_arg *)arg;
4040  return finish_writeconv(p->fptr, p->noalloc);
4041 }
4042 
4043 static void*
4044 nogvl_close(void *ptr)
4045 {
4046  int *fd = ptr;
4047 
4048  return (void*)(intptr_t)close(*fd);
4049 }
4050 
4051 static int
4052 maygvl_close(int fd, int keepgvl)
4053 {
4054  if (keepgvl)
4055  return close(fd);
4056 
4057  /*
4058  * close() may block for certain file types (NFS, SO_LINGER sockets,
4059  * inotify), so let other threads run.
4060  */
4062 }
4063 
4064 static void*
4065 nogvl_fclose(void *ptr)
4066 {
4067  FILE *file = ptr;
4068 
4069  return (void*)(intptr_t)fclose(file);
4070 }
4071 
4072 static int
4073 maygvl_fclose(FILE *file, int keepgvl)
4074 {
4075  if (keepgvl)
4076  return fclose(file);
4077 
4079 }
4080 
4081 static void
4082 fptr_finalize(rb_io_t *fptr, int noraise)
4083 {
4084  VALUE err = Qnil;
4085  int fd = fptr->fd;
4086  FILE *stdio_file = fptr->stdio_file;
4087 
4088  if (fptr->writeconv) {
4089  if (fptr->write_lock && !noraise) {
4090  struct finish_writeconv_arg arg;
4091  arg.fptr = fptr;
4092  arg.noalloc = noraise;
4094  }
4095  else {
4096  err = finish_writeconv(fptr, noraise);
4097  }
4098  }
4099  if (fptr->wbuf.len) {
4100  if (noraise) {
4101  if ((int)io_flush_buffer_sync(fptr) < 0 && NIL_P(err))
4102  err = Qtrue;
4103  }
4104  else {
4105  if (io_fflush(fptr) < 0 && NIL_P(err))
4106  err = INT2NUM(errno);
4107  }
4108  }
4109 
4110  fptr->fd = -1;
4111  fptr->stdio_file = 0;
4112  fptr->mode &= ~(FMODE_READABLE|FMODE_WRITABLE);
4113 
4114  if (IS_PREP_STDIO(fptr) || fd <= 2) {
4115  /* need to keep FILE objects of stdin, stdout and stderr */
4116  }
4117  else if (stdio_file) {
4118  /* stdio_file is deallocated anyway
4119  * even if fclose failed. */
4120  if ((maygvl_fclose(stdio_file, noraise) < 0) && NIL_P(err))
4121  err = noraise ? Qtrue : INT2NUM(errno);
4122  }
4123  else if (0 <= fd) {
4124  /* fptr->fd may be closed even if close fails.
4125  * POSIX doesn't specify it.
4126  * We assumes it is closed. */
4127  if ((maygvl_close(fd, noraise) < 0) && NIL_P(err))
4128  err = noraise ? Qtrue : INT2NUM(errno);
4129  }
4130 
4131  if (!NIL_P(err) && !noraise) {
4132  switch (TYPE(err)) {
4133  case T_FIXNUM:
4134  case T_BIGNUM:
4135  errno = NUM2INT(err);
4136  rb_sys_fail_path(fptr->pathv);
4137 
4138  default:
4139  rb_exc_raise(err);
4140  }
4141  }
4142 }
4143 
4144 static void
4145 rb_io_fptr_cleanup(rb_io_t *fptr, int noraise)
4146 {
4147  if (fptr->finalize) {
4148  (*fptr->finalize)(fptr, noraise);
4149  }
4150  else {
4151  fptr_finalize(fptr, noraise);
4152  }
4153 }
4154 
4155 static void
4157 {
4158  if (fptr->readconv) {
4159  rb_econv_close(fptr->readconv);
4160  fptr->readconv = NULL;
4161  }
4162  if (fptr->cbuf.ptr) {
4163  free(fptr->cbuf.ptr);
4164  fptr->cbuf.ptr = NULL;
4165  }
4166 }
4167 
4168 static void
4170 {
4171  if (fptr->writeconv) {
4172  rb_econv_close(fptr->writeconv);
4173  fptr->writeconv = NULL;
4174  }
4175  fptr->writeconv_initialized = 0;
4176 }
4177 
4178 static void
4180 {
4181  clear_readconv(fptr);
4182  clear_writeconv(fptr);
4183 }
4184 
4185 int
4187 {
4188  if (!fptr) return 0;
4189  fptr->pathv = Qnil;
4190  if (0 <= fptr->fd)
4191  rb_io_fptr_cleanup(fptr, TRUE);
4192  fptr->write_lock = 0;
4193  if (fptr->rbuf.ptr) {
4194  free(fptr->rbuf.ptr);
4195  fptr->rbuf.ptr = 0;
4196  }
4197  if (fptr->wbuf.ptr) {
4198  free(fptr->wbuf.ptr);
4199  fptr->wbuf.ptr = 0;
4200  }
4201  clear_codeconv(fptr);
4202  free(fptr);
4203  return 1;
4204 }
4205 
4206 size_t rb_econv_memsize(rb_econv_t *);
4207 
4208 RUBY_FUNC_EXPORTED size_t
4210 {
4211  size_t size = sizeof(rb_io_t);
4212  size += fptr->rbuf.capa;
4213  size += fptr->wbuf.capa;
4214  size += fptr->cbuf.capa;
4215  if (fptr->readconv) size += rb_econv_memsize(fptr->readconv);
4216  if (fptr->writeconv) size += rb_econv_memsize(fptr->writeconv);
4217  return size;
4218 }
4219 
4220 VALUE
4222 {
4223  rb_io_t *fptr;
4224  int fd;
4225  VALUE write_io;
4226  rb_io_t *write_fptr;
4227 
4228  write_io = GetWriteIO(io);
4229  if (io != write_io) {
4230  write_fptr = RFILE(write_io)->fptr;
4231  if (write_fptr && 0 <= write_fptr->fd) {
4232  rb_io_fptr_cleanup(write_fptr, TRUE);
4233  }
4234  }
4235 
4236  fptr = RFILE(io)->fptr;
4237  if (!fptr) return Qnil;
4238  if (fptr->fd < 0) return Qnil;
4239 
4240  fd = fptr->fd;
4241  rb_thread_fd_close(fd);
4242  rb_io_fptr_cleanup(fptr, FALSE);
4243 
4244  if (fptr->pid) {
4246  rb_syswait(fptr->pid);
4247  fptr->pid = 0;
4248  }
4249 
4250  return Qnil;
4251 }
4252 
4253 /*
4254  * call-seq:
4255  * ios.close -> nil
4256  *
4257  * Closes <em>ios</em> and flushes any pending writes to the operating
4258  * system. The stream is unavailable for any further data operations;
4259  * an <code>IOError</code> is raised if such an attempt is made. I/O
4260  * streams are automatically closed when they are claimed by the
4261  * garbage collector.
4262  *
4263  * If <em>ios</em> is opened by <code>IO.popen</code>,
4264  * <code>close</code> sets <code>$?</code>.
4265  */
4266 
4267 static VALUE
4269 {
4270  if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(io)) {
4271  rb_raise(rb_eSecurityError, "Insecure: can't close");
4272  }
4273  rb_io_check_closed(RFILE(io)->fptr);
4274  rb_io_close(io);
4275  return Qnil;
4276 }
4277 
4278 static VALUE
4280 {
4281  return rb_funcall(io, rb_intern("close"), 0, 0);
4282 }
4283 
4284 static VALUE
4286 {
4287  return rb_rescue(io_call_close, io, 0, 0);
4288 }
4289 
4290 /*
4291  * call-seq:
4292  * ios.closed? -> true or false
4293  *
4294  * Returns <code>true</code> if <em>ios</em> is completely closed (for
4295  * duplex streams, both reader and writer), <code>false</code>
4296  * otherwise.
4297  *
4298  * f = File.new("testfile")
4299  * f.close #=> nil
4300  * f.closed? #=> true
4301  * f = IO.popen("/bin/sh","r+")
4302  * f.close_write #=> nil
4303  * f.closed? #=> false
4304  * f.close_read #=> nil
4305  * f.closed? #=> true
4306  */
4307 
4308 
4309 static VALUE
4311 {
4312  rb_io_t *fptr;
4313  VALUE write_io;
4314  rb_io_t *write_fptr;
4315 
4316  write_io = GetWriteIO(io);
4317  if (io != write_io) {
4318  write_fptr = RFILE(write_io)->fptr;
4319  if (write_fptr && 0 <= write_fptr->fd) {
4320  return Qfalse;
4321  }
4322  }
4323 
4324  fptr = RFILE(io)->fptr;
4326  return 0 <= fptr->fd ? Qfalse : Qtrue;
4327 }
4328 
4329 /*
4330  * call-seq:
4331  * ios.close_read -> nil
4332  *
4333  * Closes the read end of a duplex I/O stream (i.e., one that contains
4334  * both a read and a write stream, such as a pipe). Will raise an
4335  * <code>IOError</code> if the stream is not duplexed.
4336  *
4337  * f = IO.popen("/bin/sh","r+")
4338  * f.close_read
4339  * f.readlines
4340  *
4341  * <em>produces:</em>
4342  *
4343  * prog.rb:3:in `readlines': not opened for reading (IOError)
4344  * from prog.rb:3
4345  */
4346 
4347 static VALUE
4349 {
4350  rb_io_t *fptr;
4351  VALUE write_io;
4352 
4353  if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(io)) {
4354  rb_raise(rb_eSecurityError, "Insecure: can't close");
4355  }
4356  GetOpenFile(io, fptr);
4357  if (is_socket(fptr->fd, fptr->pathv)) {
4358 #ifndef SHUT_RD
4359 # define SHUT_RD 0
4360 #endif
4361  if (shutdown(fptr->fd, SHUT_RD) < 0)
4362  rb_sys_fail_path(fptr->pathv);
4363  fptr->mode &= ~FMODE_READABLE;
4364  if (!(fptr->mode & FMODE_WRITABLE))
4365  return rb_io_close(io);
4366  return Qnil;
4367  }
4368 
4369  write_io = GetWriteIO(io);
4370  if (io != write_io) {
4371  rb_io_t *wfptr;
4372  GetOpenFile(write_io, wfptr);
4373  wfptr->pid = fptr->pid;
4374  fptr->pid = 0;
4375  RFILE(io)->fptr = wfptr;
4376  /* bind to write_io temporarily to get rid of memory/fd leak */
4377  fptr->tied_io_for_writing = 0;
4378  fptr->mode &= ~FMODE_DUPLEX;
4379  RFILE(write_io)->fptr = fptr;
4380  rb_io_fptr_cleanup(fptr, FALSE);
4381  /* should not finalize fptr because another thread may be reading it */
4382  return Qnil;
4383  }
4384 
4385  if (fptr->mode & FMODE_WRITABLE) {
4386  rb_raise(rb_eIOError, "closing non-duplex IO for reading");
4387  }
4388  return rb_io_close(io);
4389 }
4390 
4391 /*
4392  * call-seq:
4393  * ios.close_write -> nil
4394  *
4395  * Closes the write end of a duplex I/O stream (i.e., one that contains
4396  * both a read and a write stream, such as a pipe). Will raise an
4397  * <code>IOError</code> if the stream is not duplexed.
4398  *
4399  * f = IO.popen("/bin/sh","r+")
4400  * f.close_write
4401  * f.print "nowhere"
4402  *
4403  * <em>produces:</em>
4404  *
4405  * prog.rb:3:in `write': not opened for writing (IOError)
4406  * from prog.rb:3:in `print'
4407  * from prog.rb:3
4408  */
4409 
4410 static VALUE
4412 {
4413  rb_io_t *fptr;
4414  VALUE write_io;
4415 
4416  if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(io)) {
4417  rb_raise(rb_eSecurityError, "Insecure: can't close");
4418  }
4419  write_io = GetWriteIO(io);
4420  GetOpenFile(write_io, fptr);
4421  if (is_socket(fptr->fd, fptr->pathv)) {
4422 #ifndef SHUT_WR
4423 # define SHUT_WR 1
4424 #endif
4425  if (shutdown(fptr->fd, SHUT_WR) < 0)
4426  rb_sys_fail_path(fptr->pathv);
4427  fptr->mode &= ~FMODE_WRITABLE;
4428  if (!(fptr->mode & FMODE_READABLE))
4429  return rb_io_close(write_io);
4430  return Qnil;
4431  }
4432 
4433  if (fptr->mode & FMODE_READABLE) {
4434  rb_raise(rb_eIOError, "closing non-duplex IO for writing");
4435  }
4436 
4437  if (io != write_io) {
4438  GetOpenFile(io, fptr);
4439  fptr->tied_io_for_writing = 0;
4440  fptr->mode &= ~FMODE_DUPLEX;
4441  }
4442  rb_io_close(write_io);
4443  return Qnil;
4444 }
4445 
4446 /*
4447  * call-seq:
4448  * ios.sysseek(offset, whence=IO::SEEK_SET) -> integer
4449  *
4450  * Seeks to a given <i>offset</i> in the stream according to the value
4451  * of <i>whence</i> (see <code>IO#seek</code> for values of
4452  * <i>whence</i>). Returns the new offset into the file.
4453  *
4454  * f = File.new("testfile")
4455  * f.sysseek(-13, IO::SEEK_END) #=> 53
4456  * f.sysread(10) #=> "And so on."
4457  */
4458 
4459 static VALUE
4461 {
4462  VALUE offset, ptrname;
4463  int whence = SEEK_SET;
4464  rb_io_t *fptr;
4465  off_t pos;
4466 
4467  if (rb_scan_args(argc, argv, "11", &offset, &ptrname) == 2) {
4468  whence = NUM2INT(ptrname);
4469  }
4470  pos = NUM2OFFT(offset);
4471  GetOpenFile(io, fptr);
4472  if ((fptr->mode & FMODE_READABLE) &&
4473  (READ_DATA_BUFFERED(fptr) || READ_CHAR_PENDING(fptr))) {
4474  rb_raise(rb_eIOError, "sysseek for buffered IO");
4475  }
4476  if ((fptr->mode & FMODE_WRITABLE) && fptr->wbuf.len) {
4477  rb_warn("sysseek for buffered IO");
4478  }
4479  errno = 0;
4480  pos = lseek(fptr->fd, pos, whence);
4481  if (pos == -1 && errno) rb_sys_fail_path(fptr->pathv);
4482 
4483  return OFFT2NUM(pos);
4484 }
4485 
4486 /*
4487  * call-seq:
4488  * ios.syswrite(string) -> integer
4489  *
4490  * Writes the given string to <em>ios</em> using a low-level write.
4491  * Returns the number of bytes written. Do not mix with other methods
4492  * that write to <em>ios</em> or you may get unpredictable results.
4493  * Raises <code>SystemCallError</code> on error.
4494  *
4495  * f = File.new("out", "w")
4496  * f.syswrite("ABCDEF") #=> 6
4497  */
4498 
4499 static VALUE
4501 {
4502  rb_io_t *fptr;
4503  long n;
4504 
4505  rb_secure(4);
4506  if (!RB_TYPE_P(str, T_STRING))
4507  str = rb_obj_as_string(str);
4508 
4509  io = GetWriteIO(io);
4510  GetOpenFile(io, fptr);
4511  rb_io_check_writable(fptr);
4512 
4513  str = rb_str_new_frozen(str);
4514 
4515  if (fptr->wbuf.len) {
4516  rb_warn("syswrite for buffered IO");
4517  }
4518 
4519  n = rb_write_internal(fptr->fd, RSTRING_PTR(str), RSTRING_LEN(str));
4520  RB_GC_GUARD(str);
4521 
4522  if (n == -1) rb_sys_fail_path(fptr->pathv);
4523 
4524  return LONG2FIX(n);
4525 }
4526 
4527 /*
4528  * call-seq:
4529  * ios.sysread(maxlen[, outbuf]) -> string
4530  *
4531  * Reads <i>maxlen</i> bytes from <em>ios</em> using a low-level
4532  * read and returns them as a string. Do not mix with other methods
4533  * that read from <em>ios</em> or you may get unpredictable results.
4534  * If the optional <i>outbuf</i> argument is present, it must reference
4535  * a String, which will receive the data.
4536  * The <i>outbuf</i> will contain only the received data after the method call
4537  * even if it is not empty at the beginning.
4538  * Raises <code>SystemCallError</code> on error and
4539  * <code>EOFError</code> at end of file.
4540  *
4541  * f = File.new("testfile")
4542  * f.sysread(16) #=> "This is line one"
4543  */
4544 
4545 static VALUE
4547 {
4548  VALUE len, str;
4549  rb_io_t *fptr;
4550  long n, ilen;
4551  struct read_internal_arg arg;
4552 
4553  rb_scan_args(argc, argv, "11", &len, &str);
4554  ilen = NUM2LONG(len);
4555 
4556  io_setstrbuf(&str,ilen);
4557  if (ilen == 0) return str;
4558 
4559  GetOpenFile(io, fptr);
4561 
4562  if (READ_DATA_BUFFERED(fptr)) {
4563  rb_raise(rb_eIOError, "sysread for buffered IO");
4564  }
4565 
4566  n = fptr->fd;
4567 
4568  /*
4569  * FIXME: removing rb_thread_wait_fd() here changes sysread semantics
4570  * on non-blocking IOs. However, it's still currently possible
4571  * for sysread to raise Errno::EAGAIN if another thread read()s
4572  * the IO after we return from rb_thread_wait_fd() but before
4573  * we call read()
4574  */
4575  rb_thread_wait_fd(fptr->fd);
4576 
4577  rb_io_check_closed(fptr);
4578 
4579  io_setstrbuf(&str, ilen);
4580  rb_str_locktmp(str);
4581  arg.fd = fptr->fd;
4582  arg.str_ptr = RSTRING_PTR(str);
4583  arg.len = ilen;
4585  n = arg.len;
4586 
4587  if (n == -1) {
4588  rb_sys_fail_path(fptr->pathv);
4589  }
4590  io_set_read_length(str, n);
4591  if (n == 0 && ilen > 0) {
4592  rb_eof_error();
4593  }
4594  OBJ_TAINT(str);
4595 
4596  return str;
4597 }
4598 
4599 VALUE
4601 {
4602  rb_io_t *fptr;
4603 
4604  GetOpenFile(io, fptr);
4605  if (fptr->readconv)
4606  rb_econv_binmode(fptr->readconv);
4607  if (fptr->writeconv)
4608  rb_econv_binmode(fptr->writeconv);
4609  fptr->mode |= FMODE_BINMODE;
4610  fptr->mode &= ~FMODE_TEXTMODE;
4612 #ifdef O_BINARY
4613  if (!fptr->readconv) {
4615  }
4616  else {
4617  setmode(fptr->fd, O_BINARY);
4618  }
4619 #endif
4620  return io;
4621 }
4622 
4623 VALUE
4625 {
4626  rb_io_t *fptr;
4627 
4628  GetOpenFile(io, fptr);
4629  if (fptr->readconv) {
4630  rb_econv_close(fptr->readconv);
4631  fptr->readconv = NULL;
4632  }
4633  if (fptr->writeconv) {
4634  rb_econv_close(fptr->writeconv);
4635  fptr->writeconv = NULL;
4636  }
4637  fptr->mode |= FMODE_BINMODE;
4638  fptr->mode &= ~FMODE_TEXTMODE;
4640 
4641  fptr->encs.enc = rb_ascii8bit_encoding();
4642  fptr->encs.enc2 = NULL;
4643  fptr->encs.ecflags = 0;
4644  fptr->encs.ecopts = Qnil;
4645  clear_codeconv(fptr);
4646 
4647  return io;
4648 }
4649 
4650 /*
4651  * call-seq:
4652  * ios.binmode -> ios
4653  *
4654  * Puts <em>ios</em> into binary mode.
4655  * Once a stream is in binary mode, it cannot be reset to nonbinary mode.
4656  *
4657  * - newline conversion disabled
4658  * - encoding conversion disabled
4659  * - content is treated as ASCII-8BIT
4660  *
4661  */
4662 
4663 static VALUE
4665 {
4666  VALUE write_io;
4667 
4669 
4670  write_io = GetWriteIO(io);
4671  if (write_io != io)
4672  rb_io_ascii8bit_binmode(write_io);
4673  return io;
4674 }
4675 
4676 /*
4677  * call-seq:
4678  * ios.binmode? -> true or false
4679  *
4680  * Returns <code>true</code> if <em>ios</em> is binmode.
4681  */
4682 static VALUE
4684 {
4685  rb_io_t *fptr;
4686  GetOpenFile(io, fptr);
4687  return fptr->mode & FMODE_BINMODE ? Qtrue : Qfalse;
4688 }
4689 
4690 static const char*
4692 {
4693  if (fmode & FMODE_APPEND) {
4694  if ((fmode & FMODE_READWRITE) == FMODE_READWRITE) {
4695  return MODE_BTMODE("a+", "ab+", "at+");
4696  }
4697  return MODE_BTMODE("a", "ab", "at");
4698  }
4699  switch (fmode & FMODE_READWRITE) {
4700  default:
4701  rb_raise(rb_eArgError, "invalid access fmode 0x%x", fmode);
4702  case FMODE_READABLE:
4703  return MODE_BTMODE("r", "rb", "rt");
4704  case FMODE_WRITABLE:
4705  return MODE_BTMODE("w", "wb", "wt");
4706  case FMODE_READWRITE:
4707  if (fmode & FMODE_CREATE) {
4708  return MODE_BTMODE("w+", "wb+", "wt+");
4709  }
4710  return MODE_BTMODE("r+", "rb+", "rt+");
4711  }
4712 }
4713 
4714 static int
4715 io_encname_bom_p(const char *name, long len)
4716 {
4717  static const char bom_prefix[] = "bom|utf-";
4718  enum {bom_prefix_len = (int)sizeof(bom_prefix) - 1};
4719  if (!len) {
4720  const char *p = strchr(name, ':');
4721  len = p ? (long)(p - name) : (long)strlen(name);
4722  }
4723  return len > bom_prefix_len && STRNCASECMP(name, bom_prefix, bom_prefix_len) == 0;
4724 }
4725 
4726 int
4727 rb_io_modestr_fmode(const char *modestr)
4728 {
4729  int fmode = 0;
4730  const char *m = modestr, *p = NULL;
4731 
4732  switch (*m++) {
4733  case 'r':
4734  fmode |= FMODE_READABLE;
4735  break;
4736  case 'w':
4738  break;
4739  case 'a':
4741  break;
4742  default:
4743  error:
4744  rb_raise(rb_eArgError, "invalid access mode %s", modestr);
4745  }
4746 
4747  while (*m) {
4748  switch (*m++) {
4749  case 'b':
4750  fmode |= FMODE_BINMODE;
4751  break;
4752  case 't':
4753  fmode |= FMODE_TEXTMODE;
4754  break;
4755  case '+':
4756  fmode |= FMODE_READWRITE;
4757  break;
4758  default:
4759  goto error;
4760  case ':':
4761  p = m;
4762  goto finished;
4763  }
4764  }
4765 
4766  finished:
4767  if ((fmode & FMODE_BINMODE) && (fmode & FMODE_TEXTMODE))
4768  goto error;
4769  if (p && io_encname_bom_p(p, 0))
4770  fmode |= FMODE_SETENC_BY_BOM;
4771 
4772  return fmode;
4773 }
4774 
4775 int
4777 {
4778  int fmode = 0;
4779 
4780  switch (oflags & (O_RDONLY|O_WRONLY|O_RDWR)) {
4781  case O_RDONLY:
4782  fmode = FMODE_READABLE;
4783  break;
4784  case O_WRONLY:
4785  fmode = FMODE_WRITABLE;
4786  break;
4787  case O_RDWR:
4788  fmode = FMODE_READWRITE;
4789  break;
4790  }
4791 
4792  if (oflags & O_APPEND) {
4793  fmode |= FMODE_APPEND;
4794  }
4795  if (oflags & O_TRUNC) {
4796  fmode |= FMODE_TRUNC;
4797  }
4798  if (oflags & O_CREAT) {
4799  fmode |= FMODE_CREATE;
4800  }
4801 #ifdef O_BINARY
4802  if (oflags & O_BINARY) {
4803  fmode |= FMODE_BINMODE;
4804  }
4805 #endif
4806 
4807  return fmode;
4808 }
4809 
4810 static int
4812 {
4813  int oflags = 0;
4814 
4815  switch (fmode & FMODE_READWRITE) {
4816  case FMODE_READABLE:
4817  oflags |= O_RDONLY;
4818  break;
4819  case FMODE_WRITABLE:
4820  oflags |= O_WRONLY;
4821  break;
4822  case FMODE_READWRITE:
4823  oflags |= O_RDWR;
4824  break;
4825  }
4826 
4827  if (fmode & FMODE_APPEND) {
4828  oflags |= O_APPEND;
4829  }
4830  if (fmode & FMODE_TRUNC) {
4831  oflags |= O_TRUNC;
4832  }
4833  if (fmode & FMODE_CREATE) {
4834  oflags |= O_CREAT;
4835  }
4836 #ifdef O_BINARY
4837  if (fmode & FMODE_BINMODE) {
4838  oflags |= O_BINARY;
4839  }
4840 #endif
4841 
4842  return oflags;
4843 }
4844 
4845 int
4846 rb_io_modestr_oflags(const char *modestr)
4847 {
4848  return rb_io_fmode_oflags(rb_io_modestr_fmode(modestr));
4849 }
4850 
4851 static const char*
4853 {
4854 #ifdef O_BINARY
4855 # define MODE_BINARY(a,b) ((oflags & O_BINARY) ? (b) : (a))
4856 #else
4857 # define MODE_BINARY(a,b) (a)
4858 #endif
4859  int accmode = oflags & (O_RDONLY|O_WRONLY|O_RDWR);
4860  if (oflags & O_APPEND) {
4861  if (accmode == O_WRONLY) {
4862  return MODE_BINARY("a", "ab");
4863  }
4864  if (accmode == O_RDWR) {
4865  return MODE_BINARY("a+", "ab+");
4866  }
4867  }
4868  switch (oflags & (O_RDONLY|O_WRONLY|O_RDWR)) {
4869  default:
4870  rb_raise(rb_eArgError, "invalid access oflags 0x%x", oflags);
4871  case O_RDONLY:
4872  return MODE_BINARY("r", "rb");
4873  case O_WRONLY:
4874  return MODE_BINARY("w", "wb");
4875  case O_RDWR:
4876  return MODE_BINARY("r+", "rb+");
4877  }
4878 }
4879 
4880 /*
4881  * Convert external/internal encodings to enc/enc2
4882  * NULL => use default encoding
4883  * Qnil => no encoding specified (internal only)
4884  */
4885 static void
4887 {
4888  int default_ext = 0;
4889 
4890  if (ext == NULL) {
4892  default_ext = 1;
4893  }
4894  if (intern == NULL && ext != rb_ascii8bit_encoding())
4895  /* If external is ASCII-8BIT, no default transcoding */
4896  intern = rb_default_internal_encoding();
4897  if (intern == NULL || intern == (rb_encoding *)Qnil ||
4898  (!(fmode & FMODE_SETENC_BY_BOM) && (intern == ext))) {
4899  /* No internal encoding => use external + no transcoding */
4900  *enc = (default_ext && intern != ext) ? NULL : ext;
4901  *enc2 = NULL;
4902  }
4903  else {
4904  *enc = intern;
4905  *enc2 = ext;
4906  }
4907 }
4908 
4909 static void
4911 {
4912  rb_warn("Unsupported encoding %s ignored", name);
4913 }
4914 
4915 static void
4916 parse_mode_enc(const char *estr, rb_encoding **enc_p, rb_encoding **enc2_p, int *fmode_p)
4917 {
4918  const char *p;
4919  char encname[ENCODING_MAXNAMELEN+1];
4920  int idx, idx2;
4921  int fmode = fmode_p ? *fmode_p : 0;
4922  rb_encoding *ext_enc, *int_enc;
4923 
4924  /* parse estr as "enc" or "enc2:enc" or "enc:-" */
4925 
4926  p = strrchr(estr, ':');
4927  if (p) {
4928  long len = (p++) - estr;
4929  if (len == 0 || len > ENCODING_MAXNAMELEN)
4930  idx = -1;
4931  else {
4932  if (io_encname_bom_p(estr, len)) {
4933  fmode |= FMODE_SETENC_BY_BOM;
4934  estr += 4;
4935  len -= 4;
4936  }
4937  memcpy(encname, estr, len);
4938  encname[len] = '\0';
4939  estr = encname;
4940  idx = rb_enc_find_index(encname);
4941  }
4942  }
4943  else {
4944  long len = strlen(estr);
4945  if (io_encname_bom_p(estr, len)) {
4946  fmode |= FMODE_SETENC_BY_BOM;
4947  estr += 4;
4948  len -= 4;
4949  memcpy(encname, estr, len);
4950  encname[len] = '\0';
4951  estr = encname;
4952  }
4953  idx = rb_enc_find_index(estr);
4954  }
4955  if (fmode_p) *fmode_p = fmode;
4956 
4957  if (idx >= 0)
4958  ext_enc = rb_enc_from_index(idx);
4959  else {
4960  if (idx != -2)
4961  unsupported_encoding(estr);
4962  ext_enc = NULL;
4963  }
4964 
4965  int_enc = NULL;
4966  if (p) {
4967  if (*p == '-' && *(p+1) == '\0') {
4968  /* Special case - "-" => no transcoding */
4969  int_enc = (rb_encoding *)Qnil;
4970  }
4971  else {
4972  idx2 = rb_enc_find_index(p);
4973  if (idx2 < 0)
4975  else if (!(fmode & FMODE_SETENC_BY_BOM) && (idx2 == idx)) {
4976  int_enc = (rb_encoding *)Qnil;
4977  }
4978  else
4979  int_enc = rb_enc_from_index(idx2);
4980  }
4981  }
4982 
4983  rb_io_ext_int_to_encs(ext_enc, int_enc, enc_p, enc2_p, fmode);
4984 }
4985 
4986 int
4987 rb_io_extract_encoding_option(VALUE opt, rb_encoding **enc_p, rb_encoding **enc2_p, int *fmode_p)
4988 {
4989  VALUE encoding=Qnil, extenc=Qundef, intenc=Qundef, tmp;
4990  int extracted = 0;
4991  rb_encoding *extencoding = NULL;
4992  rb_encoding *intencoding = NULL;
4993 
4994  if (!NIL_P(opt)) {
4995  VALUE v;
4996  v = rb_hash_lookup2(opt, sym_encoding, Qnil);
4997  if (v != Qnil) encoding = v;
4998  v = rb_hash_lookup2(opt, sym_extenc, Qundef);
4999  if (v != Qnil) extenc = v;
5000  v = rb_hash_lookup2(opt, sym_intenc, Qundef);
5001  if (v != Qundef) intenc = v;
5002  }
5003  if ((extenc != Qundef || intenc != Qundef) && !NIL_P(encoding)) {
5004  if (!NIL_P(ruby_verbose)) {
5005  int idx = rb_to_encoding_index(encoding);
5006  rb_warn("Ignoring encoding parameter '%s': %s_encoding is used",
5007  idx < 0 ? StringValueCStr(encoding) : rb_enc_name(rb_enc_from_index(idx)),
5008  extenc == Qundef ? "internal" : "external");
5009  }
5010  encoding = Qnil;
5011  }
5012  if (extenc != Qundef && !NIL_P(extenc)) {
5013  extencoding = rb_to_encoding(extenc);
5014  }
5015  if (intenc != Qundef) {
5016  if (NIL_P(intenc)) {
5017  /* internal_encoding: nil => no transcoding */
5018  intencoding = (rb_encoding *)Qnil;
5019  }
5020  else if (!NIL_P(tmp = rb_check_string_type(intenc))) {
5021  char *p = StringValueCStr(tmp);
5022 
5023  if (*p == '-' && *(p+1) == '\0') {
5024  /* Special case - "-" => no transcoding */
5025  intencoding = (rb_encoding *)Qnil;
5026  }
5027  else {
5028  intencoding = rb_to_encoding(intenc);
5029  }
5030  }
5031  else {
5032  intencoding = rb_to_encoding(intenc);
5033  }
5034  if (extencoding == intencoding) {
5035  intencoding = (rb_encoding *)Qnil;
5036  }
5037  }
5038  if (!NIL_P(encoding)) {
5039  extracted = 1;
5040  if (!NIL_P(tmp = rb_check_string_type(encoding))) {
5041  parse_mode_enc(StringValueCStr(tmp), enc_p, enc2_p, fmode_p);
5042  }
5043  else {
5044  rb_io_ext_int_to_encs(rb_to_encoding(encoding), NULL, enc_p, enc2_p, 0);
5045  }
5046  }
5047  else if (extenc != Qundef || intenc != Qundef) {
5048  extracted = 1;
5049  rb_io_ext_int_to_encs(extencoding, intencoding, enc_p, enc2_p, 0);
5050  }
5051  return extracted;
5052 }
5053 
5054 typedef struct rb_io_enc_t convconfig_t;
5055 
5056 static void
5057 validate_enc_binmode(int *fmode_p, int ecflags, rb_encoding *enc, rb_encoding *enc2)
5058 {
5059  int fmode = *fmode_p;
5060 
5061  if ((fmode & FMODE_READABLE) &&
5062  !enc2 &&
5063  !(fmode & FMODE_BINMODE) &&
5065  rb_raise(rb_eArgError, "ASCII incompatible encoding needs binmode");
5066 
5067  if (!(fmode & FMODE_BINMODE) &&
5069  fmode |= DEFAULT_TEXTMODE;
5070  *fmode_p = fmode;
5071  }
5072 #if !DEFAULT_TEXTMODE
5073  else if (!(ecflags & ECONV_NEWLINE_DECORATOR_MASK)) {
5074  fmode &= ~FMODE_TEXTMODE;
5075  *fmode_p = fmode;
5076  }
5077 #endif
5078 }
5079 
5080 static void
5082 {
5083  if (!NIL_P(opthash)) {
5084  VALUE v;
5085  v = rb_hash_aref(opthash, sym_textmode);
5086  if (!NIL_P(v)) {
5087  if (*fmode & FMODE_TEXTMODE)
5088  rb_raise(rb_eArgError, "textmode specified twice");
5089  if (RTEST(v))
5090  *fmode |= FMODE_TEXTMODE;
5091  }
5092  v = rb_hash_aref(opthash, sym_binmode);
5093  if (!NIL_P(v)) {
5094  if (*fmode & FMODE_BINMODE)
5095  rb_raise(rb_eArgError, "binmode specified twice");
5096  if (RTEST(v))
5097  *fmode |= FMODE_BINMODE;
5098  }
5099 
5100  if ((*fmode & FMODE_BINMODE) && (*fmode & FMODE_TEXTMODE))
5101  rb_raise(rb_eArgError, "both textmode and binmode specified");
5102  }
5103 }
5104 
5105 static void
5106 rb_io_extract_modeenc(VALUE *vmode_p, VALUE *vperm_p, VALUE opthash,
5107  int *oflags_p, int *fmode_p, convconfig_t *convconfig_p)
5108 {
5109  VALUE vmode;
5110  int oflags, fmode;
5111  rb_encoding *enc, *enc2;
5112  int ecflags;
5113  VALUE ecopts;
5114  int has_enc = 0, has_vmode = 0;
5115  VALUE intmode;
5116 
5117  vmode = *vmode_p;
5118 
5119  /* Set to defaults */
5120  rb_io_ext_int_to_encs(NULL, NULL, &enc, &enc2, 0);
5121 
5122  vmode_handle:
5123  if (NIL_P(vmode)) {
5124  fmode = FMODE_READABLE;
5125  oflags = O_RDONLY;
5126  }
5127  else if (!NIL_P(intmode = rb_check_to_integer(vmode, "to_int"))) {
5128  vmode = intmode;
5129  oflags = NUM2INT(intmode);
5130  fmode = rb_io_oflags_fmode(oflags);
5131  }
5132  else {
5133  const char *p;
5134 
5135  SafeStringValue(vmode);
5136  p = StringValueCStr(vmode);
5137  fmode = rb_io_modestr_fmode(p);
5138  oflags = rb_io_fmode_oflags(fmode);
5139  p = strchr(p, ':');
5140  if (p) {
5141  has_enc = 1;
5142  parse_mode_enc(p+1, &enc, &enc2, &fmode);
5143  }
5144  else {
5145  rb_encoding *e;
5146 
5147  e = (fmode & FMODE_BINMODE) ? rb_ascii8bit_encoding() : NULL;
5148  rb_io_ext_int_to_encs(e, NULL, &enc, &enc2, fmode);
5149  }
5150  }
5151 
5152  if (NIL_P(opthash)) {
5153  ecflags = (fmode & FMODE_READABLE) ?
5156 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
5157  ecflags |= (fmode & FMODE_WRITABLE) ?
5158  MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE,
5159  0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE) : 0;
5160 #endif
5162  ecopts = Qnil;
5163  }
5164  else {
5165  VALUE v;
5166  extract_binmode(opthash, &fmode);
5167  if (fmode & FMODE_BINMODE) {
5168 #ifdef O_BINARY
5169  oflags |= O_BINARY;
5170 #endif
5171  if (!has_enc)
5172  rb_io_ext_int_to_encs(rb_ascii8bit_encoding(), NULL, &enc, &enc2, fmode);
5173  }
5174 #if DEFAULT_TEXTMODE
5175  else if (NIL_P(vmode)) {
5176  fmode |= DEFAULT_TEXTMODE;
5177  }
5178 #endif
5179  if (!has_vmode) {
5180  v = rb_hash_aref(opthash, sym_mode);
5181  if (!NIL_P(v)) {
5182  if (!NIL_P(vmode)) {
5183  rb_raise(rb_eArgError, "mode specified twice");
5184  }
5185  has_vmode = 1;
5186  vmode = v;
5187  goto vmode_handle;
5188  }
5189  }
5190  v = rb_hash_aref(opthash, sym_perm);
5191  if (!NIL_P(v)) {
5192  if (vperm_p) {
5193  if (!NIL_P(*vperm_p)) {
5194  rb_raise(rb_eArgError, "perm specified twice");
5195  }
5196  *vperm_p = v;
5197  }
5198  else {
5199  /* perm no use, just ignore */
5200  }
5201  }
5202  ecflags = (fmode & FMODE_READABLE) ?
5205 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
5206  ecflags |= (fmode & FMODE_WRITABLE) ?
5207  MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE,
5208  0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE) : 0;
5209 #endif
5210 
5211  if (rb_io_extract_encoding_option(opthash, &enc, &enc2, &fmode)) {
5212  if (has_enc) {
5213  rb_raise(rb_eArgError, "encoding specified twice");
5214  }
5215  }
5217  ecflags = rb_econv_prepare_options(opthash, &ecopts, ecflags);
5218  }
5219 
5220  validate_enc_binmode(&fmode, ecflags, enc, enc2);
5221 
5222  *vmode_p = vmode;
5223 
5224  *oflags_p = oflags;
5225  *fmode_p = fmode;
5226  convconfig_p->enc = enc;
5227  convconfig_p->enc2 = enc2;
5228  convconfig_p->ecflags = ecflags;
5229  convconfig_p->ecopts = ecopts;
5230 }
5231 
5234  int oflags;
5236 };
5237 
5238 static void *
5239 sysopen_func(void *ptr)
5240 {
5241  const struct sysopen_struct *data = ptr;
5242  const char *fname = RSTRING_PTR(data->fname);
5243  return (void *)(VALUE)rb_cloexec_open(fname, data->oflags, data->perm);
5244 }
5245 
5246 static inline int
5248 {
5249  int fd;
5251  if (0 <= fd)
5252  rb_update_max_fd(fd);
5253  return fd;
5254 }
5255 
5256 static int
5258 {
5259  int fd;
5260  struct sysopen_struct data;
5261 
5262  data.fname = rb_str_encode_ospath(fname);
5263  data.oflags = oflags;
5264  data.perm = perm;
5265 
5266  fd = rb_sysopen_internal(&data);
5267  if (fd < 0) {
5268  if (errno == EMFILE || errno == ENFILE) {
5269  rb_gc();
5270  fd = rb_sysopen_internal(&data);
5271  }
5272  if (fd < 0) {
5273  rb_sys_fail_path(fname);
5274  }
5275  }
5276  return fd;
5277 }
5278 
5279 FILE *
5280 rb_fdopen(int fd, const char *modestr)
5281 {
5282  FILE *file;
5283 
5284 #if defined(__sun)
5285  errno = 0;
5286 #endif
5287  file = fdopen(fd, modestr);
5288  if (!file) {
5289  if (
5290 #if defined(__sun)
5291  errno == 0 ||
5292 #endif
5293  errno == EMFILE || errno == ENFILE) {
5294  rb_gc();
5295 #if defined(__sun)
5296  errno = 0;
5297 #endif
5298  file = fdopen(fd, modestr);
5299  }
5300  if (!file) {
5301 #ifdef _WIN32
5302  if (errno == 0) errno = EINVAL;
5303 #elif defined(__sun)
5304  if (errno == 0) errno = EMFILE;
5305 #endif
5306  rb_sys_fail(0);
5307  }
5308  }
5309 
5310  /* xxx: should be _IONBF? A buffer in FILE may have trouble. */
5311 #ifdef USE_SETVBUF
5312  if (setvbuf(file, NULL, _IOFBF, 0) != 0)
5313  rb_warn("setvbuf() can't be honoured (fd=%d)", fd);
5314 #endif
5315  return file;
5316 }
5317 
5318 static void
5320 {
5321  if (isatty(fptr->fd))
5322  fptr->mode |= FMODE_TTY|FMODE_DUPLEX;
5323 }
5324 
5326 static void io_encoding_set(rb_io_t *, VALUE, VALUE, VALUE);
5327 
5328 static int
5330 {
5331  VALUE b1, b2, b3, b4;
5332 
5333  if (NIL_P(b1 = rb_io_getbyte(io))) return 0;
5334  switch (b1) {
5335  case INT2FIX(0xEF):
5336  if (NIL_P(b2 = rb_io_getbyte(io))) break;
5337  if (b2 == INT2FIX(0xBB) && !NIL_P(b3 = rb_io_getbyte(io))) {
5338  if (b3 == INT2FIX(0xBF)) {
5339  return rb_utf8_encindex();
5340  }
5341  rb_io_ungetbyte(io, b3);
5342  }
5343  rb_io_ungetbyte(io, b2);
5344  break;
5345 
5346  case INT2FIX(0xFE):
5347  if (NIL_P(b2 = rb_io_getbyte(io))) break;
5348  if (b2 == INT2FIX(0xFF)) {
5349  return rb_enc_find_index("UTF-16BE");
5350  }
5351  rb_io_ungetbyte(io, b2);
5352  break;
5353 
5354  case INT2FIX(0xFF):
5355  if (NIL_P(b2 = rb_io_getbyte(io))) break;
5356  if (b2 == INT2FIX(0xFE)) {
5357  b3 = rb_io_getbyte(io);
5358  if (b3 == INT2FIX(0) && !NIL_P(b4 = rb_io_getbyte(io))) {
5359  if (b4 == INT2FIX(0)) {
5360  return rb_enc_find_index("UTF-32LE");
5361  }
5362  rb_io_ungetbyte(io, b4);
5363  rb_io_ungetbyte(io, b3);
5364  }
5365  else {
5366  rb_io_ungetbyte(io, b3);
5367  return rb_enc_find_index("UTF-16LE");
5368  }
5369  }
5370  rb_io_ungetbyte(io, b2);
5371  break;
5372 
5373  case INT2FIX(0):
5374  if (NIL_P(b2 = rb_io_getbyte(io))) break;
5375  if (b2 == INT2FIX(0) && !NIL_P(b3 = rb_io_getbyte(io))) {
5376  if (b3 == INT2FIX(0xFE) && !NIL_P(b4 = rb_io_getbyte(io))) {
5377  if (b4 == INT2FIX(0xFF)) {
5378  return rb_enc_find_index("UTF-32BE");
5379  }
5380  rb_io_ungetbyte(io, b4);
5381  }
5382  rb_io_ungetbyte(io, b3);
5383  }
5384  rb_io_ungetbyte(io, b2);
5385  break;
5386  }
5387  rb_io_ungetbyte(io, b1);
5388  return 0;
5389 }
5390 
5391 static void
5393 {
5394  int idx = io_strip_bom(io);
5395  rb_io_t *fptr;
5396 
5397  GetOpenFile(io, fptr);
5398  if (idx) {
5401  }
5402  else {
5403  fptr->encs.enc2 = NULL;
5404  }
5405 }
5406 
5407 static VALUE
5408 rb_file_open_generic(VALUE io, VALUE filename, int oflags, int fmode, convconfig_t *convconfig, mode_t perm)
5409 {
5410  rb_io_t *fptr;
5411  convconfig_t cc;
5412  if (!convconfig) {
5413  /* Set to default encodings */
5414  rb_io_ext_int_to_encs(NULL, NULL, &cc.enc, &cc.enc2, fmode);
5415  cc.ecflags = 0;
5416  cc.ecopts = Qnil;
5417  convconfig = &cc;
5418  }
5419  validate_enc_binmode(&fmode, convconfig->ecflags,
5420  convconfig->enc, convconfig->enc2);
5421 
5422  MakeOpenFile(io, fptr);
5423  fptr->mode = fmode;
5424  fptr->encs = *convconfig;
5425  fptr->pathv = rb_str_new_frozen(filename);
5426  fptr->fd = rb_sysopen(fptr->pathv, oflags, perm);
5427  io_check_tty(fptr);
5429 
5430  return io;
5431 }
5432 
5433 static VALUE
5434 rb_file_open_internal(VALUE io, VALUE filename, const char *modestr)
5435 {
5436  int fmode = rb_io_modestr_fmode(modestr);
5437  const char *p = strchr(modestr, ':');
5438  convconfig_t convconfig;
5439 
5440  if (p) {
5441  parse_mode_enc(p+1, &convconfig.enc, &convconfig.enc2, &fmode);
5442  }
5443  else {
5444  rb_encoding *e;
5445  /* Set to default encodings */
5446 
5447  e = (fmode & FMODE_BINMODE) ? rb_ascii8bit_encoding() : NULL;
5448  rb_io_ext_int_to_encs(e, NULL, &convconfig.enc, &convconfig.enc2, fmode);
5449  convconfig.ecflags = 0;
5450  convconfig.ecopts = Qnil;
5451  }
5452 
5453  return rb_file_open_generic(io, filename,
5454  rb_io_fmode_oflags(fmode),
5455  fmode,
5456  &convconfig,
5457  0666);
5458 }
5459 
5460 VALUE
5461 rb_file_open_str(VALUE fname, const char *modestr)
5462 {
5463  FilePathValue(fname);
5464  return rb_file_open_internal(io_alloc(rb_cFile), fname, modestr);
5465 }
5466 
5467 VALUE
5468 rb_file_open(const char *fname, const char *modestr)
5469 {
5470  return rb_file_open_internal(io_alloc(rb_cFile), rb_str_new_cstr(fname), modestr);
5471 }
5472 
5473 #if defined(__CYGWIN__) || !defined(HAVE_FORK)
5474 static struct pipe_list {
5476  struct pipe_list *next;
5477 } *pipe_list;
5478 
5479 static void
5481 {
5482  struct pipe_list *list;
5483 
5484  list = ALLOC(struct pipe_list);
5485  list->fptr = fptr;
5486  list->next = pipe_list;
5487  pipe_list = list;
5488 }
5489 
5490 static void
5492 {
5493  struct pipe_list *list = pipe_list;
5494  struct pipe_list *tmp;
5495 
5496  if (list->fptr == fptr) {
5497  pipe_list = list->next;
5498  free(list);
5499  return;
5500  }
5501 
5502  while (list->next) {
5503  if (list->next->fptr == fptr) {
5504  tmp = list->next;
5505  list->next = list->next->next;
5506  free(tmp);
5507  return;
5508  }
5509  list = list->next;
5510  }
5511 }
5512 
5513 static void
5515 {
5516  struct pipe_list *list = pipe_list;
5517  struct pipe_list *tmp;
5518 
5519  while (list) {
5520  tmp = list->next;
5521  rb_io_fptr_finalize(list->fptr);
5522  list = tmp;
5523  }
5524 }
5525 
5526 static void
5527 pipe_finalize(rb_io_t *fptr, int noraise)
5528 {
5529 #if !defined(HAVE_FORK) && !defined(_WIN32)
5530  int status = 0;
5531  if (fptr->stdio_file) {
5532  status = pclose(fptr->stdio_file);
5533  }
5534  fptr->fd = -1;
5535  fptr->stdio_file = 0;
5536  rb_last_status_set(status, fptr->pid);
5537 #else
5538  fptr_finalize(fptr, noraise);
5539 #endif
5540  pipe_del_fptr(fptr);
5541 }
5542 #endif
5543 
5544 void
5546 {
5548  fptr->mode |= FMODE_SYNC;
5549 }
5550 
5551 void
5553 {
5554  rb_io_synchronized(fptr);
5555 }
5556 
5557 int
5558 rb_pipe(int *pipes)
5559 {
5560  int ret;
5561  ret = rb_cloexec_pipe(pipes);
5562  if (ret == -1) {
5563  if (errno == EMFILE || errno == ENFILE) {
5564  rb_gc();
5565  ret = rb_cloexec_pipe(pipes);
5566  }
5567  }
5568  if (ret == 0) {
5569  rb_update_max_fd(pipes[0]);
5570  rb_update_max_fd(pipes[1]);
5571  }
5572  return ret;
5573 }
5574 
5575 #ifdef _WIN32
5576 #define HAVE_SPAWNV 1
5577 #define spawnv(mode, cmd, args) rb_w32_aspawn((mode), (cmd), (args))
5578 #define spawn(mode, cmd) rb_w32_spawn((mode), (cmd), 0)
5579 #endif
5580 
5581 #if defined(HAVE_FORK) || defined(HAVE_SPAWNV)
5582 struct popen_arg {
5583  VALUE execarg_obj;
5584  struct rb_execarg *eargp;
5585  int modef;
5586  int pair[2];
5587  int write_pair[2];
5588 };
5589 #endif
5590 
5591 #ifdef HAVE_FORK
5592 static void
5593 popen_redirect(struct popen_arg *p)
5594 {
5595  if ((p->modef & FMODE_READABLE) && (p->modef & FMODE_WRITABLE)) {
5596  close(p->write_pair[1]);
5597  if (p->write_pair[0] != 0) {
5598  dup2(p->write_pair[0], 0);
5599  close(p->write_pair[0]);
5600  }
5601  close(p->pair[0]);
5602  if (p->pair[1] != 1) {
5603  dup2(p->pair[1], 1);
5604  close(p->pair[1]);
5605  }
5606  }
5607  else if (p->modef & FMODE_READABLE) {
5608  close(p->pair[0]);
5609  if (p->pair[1] != 1) {
5610  dup2(p->pair[1], 1);
5611  close(p->pair[1]);
5612  }
5613  }
5614  else {
5615  close(p->pair[1]);
5616  if (p->pair[0] != 0) {
5617  dup2(p->pair[0], 0);
5618  close(p->pair[0]);
5619  }
5620  }
5621 }
5622 
5623 #if defined(__linux__)
5624 /* Linux /proc/self/status contains a line: "FDSize:\t<nnn>\n"
5625  * Since /proc may not be available, linux_get_maxfd is just a hint.
5626  * This function, linux_get_maxfd, must be async-signal-safe.
5627  * I.e. opendir() is not usable.
5628  *
5629  * Note that memchr() and memcmp is *not* async-signal-safe in POSIX.
5630  * However they are easy to re-implement in async-signal-safe manner.
5631  * (Also note that there is missing/memcmp.c.)
5632  */
5633 static int
5634 linux_get_maxfd(void)
5635 {
5636  int fd;
5637  char buf[4096], *p, *np, *e;
5638  ssize_t ss;
5639  fd = rb_cloexec_open("/proc/self/status", O_RDONLY|O_NOCTTY, 0);
5640  if (fd == -1) return -1;
5641  ss = read(fd, buf, sizeof(buf));
5642  if (ss == -1) goto err;
5643  p = buf;
5644  e = buf + ss;
5645  while ((int)sizeof("FDSize:\t0\n")-1 <= e-p &&
5646  (np = memchr(p, '\n', e-p)) != NULL) {
5647  if (memcmp(p, "FDSize:", sizeof("FDSize:")-1) == 0) {
5648  int fdsize;
5649  p += sizeof("FDSize:")-1;
5650  *np = '\0';
5651  fdsize = (int)ruby_strtoul(p, (char **)NULL, 10);
5652  close(fd);
5653  return fdsize;
5654  }
5655  p = np+1;
5656  }
5657  /* fall through */
5658 
5659  err:
5660  close(fd);
5661  return -1;
5662 }
5663 #endif
5664 
5665 /* This function should be async-signal-safe. */
5666 void
5667 rb_close_before_exec(int lowfd, int maxhint, VALUE noclose_fds)
5668 {
5669  int fd, ret;
5670  int max = (int)max_file_descriptor;
5671 #ifdef F_MAXFD
5672  /* F_MAXFD is available since NetBSD 2.0. */
5673  ret = fcntl(0, F_MAXFD); /* async-signal-safe */
5674  if (ret != -1)
5675  maxhint = max = ret;
5676 #elif defined(__linux__)
5677  ret = linux_get_maxfd();
5678  if (maxhint < ret)
5679  maxhint = ret;
5680  /* maxhint = max = ret; if (ret == -1) abort(); // test */
5681 #endif
5682  if (max < maxhint)
5683  max = maxhint;
5684  for (fd = lowfd; fd <= max; fd++) {
5685  if (!NIL_P(noclose_fds) &&
5686  RTEST(rb_hash_lookup(noclose_fds, INT2FIX(fd)))) /* async-signal-safe */
5687  continue;
5688  ret = fcntl(fd, F_GETFD); /* async-signal-safe */
5689  if (ret != -1 && !(ret & FD_CLOEXEC)) {
5690  fcntl(fd, F_SETFD, ret|FD_CLOEXEC); /* async-signal-safe */
5691  }
5692 #define CONTIGUOUS_CLOSED_FDS 20
5693  if (ret != -1) {
5694  if (max < fd + CONTIGUOUS_CLOSED_FDS)
5695  max = fd + CONTIGUOUS_CLOSED_FDS;
5696  }
5697  }
5698 }
5699 
5700 static int
5701 popen_exec(void *pp, char *errmsg, size_t errmsg_len)
5702 {
5703  struct popen_arg *p = (struct popen_arg*)pp;
5704 
5705  return rb_exec_async_signal_safe(p->eargp, errmsg, errmsg_len);
5706 }
5707 #endif
5708 
5709 static VALUE
5710 pipe_open(VALUE execarg_obj, const char *modestr, int fmode, convconfig_t *convconfig)
5711 {
5712  struct rb_execarg *eargp = NIL_P(execarg_obj) ? NULL : rb_execarg_get(execarg_obj);
5713  VALUE prog = eargp ? (eargp->use_shell ? eargp->invoke.sh.shell_script : eargp->invoke.cmd.command_name) : Qfalse ;
5714  rb_pid_t pid = 0;
5715  rb_io_t *fptr;
5716  VALUE port;
5717  rb_io_t *write_fptr;
5718  VALUE write_port;
5719 #if defined(HAVE_FORK)
5720  int status;
5721  char errmsg[80] = { '\0' };
5722 #endif
5723 #if defined(HAVE_FORK) || defined(HAVE_SPAWNV)
5724  struct popen_arg arg;
5725  int e = 0;
5726 #endif
5727 #if defined(HAVE_SPAWNV)
5728 # if defined(HAVE_SPAWNVE)
5729 # define DO_SPAWN(cmd, args, envp) ((args) ? \
5730  spawnve(P_NOWAIT, (cmd), (args), (envp)) : \
5731  spawne(P_NOWAIT, (cmd), (envp)))
5732 # else
5733 # define DO_SPAWN(cmd, args, envp) ((args) ? \
5734  spawnv(P_NOWAIT, (cmd), (args)) : \
5735  spawn(P_NOWAIT, (cmd)))
5736 # endif
5737 # if !defined(HAVE_FORK)
5738  char **args = NULL;
5739 # if defined(HAVE_SPAWNVE)
5740  char **envp = NULL;
5741 # endif
5742 # endif
5743 #endif
5744 #if !defined(HAVE_FORK)
5745  struct rb_execarg sarg, *sargp = &sarg;
5746 #endif
5747  FILE *fp = 0;
5748  int fd = -1;
5749  int write_fd = -1;
5750 #if !defined(HAVE_FORK)
5751  const char *cmd = 0;
5752 #if !defined(HAVE_SPAWNV)
5753  int argc;
5754  VALUE *argv;
5755 #endif
5756 
5757  if (prog)
5758  cmd = StringValueCStr(prog);
5759 #endif
5760 
5761 #if defined(HAVE_FORK) || defined(HAVE_SPAWNV)
5762  arg.execarg_obj = execarg_obj;
5763  arg.eargp = eargp;
5764  arg.modef = fmode;
5765  arg.pair[0] = arg.pair[1] = -1;
5766  arg.write_pair[0] = arg.write_pair[1] = -1;
5767 # if !defined(HAVE_FORK)
5768  if (eargp && !eargp->use_shell) {
5769  args = ARGVSTR2ARGV(eargp->invoke.cmd.argv_str);
5770  }
5771 # endif
5772  switch (fmode & (FMODE_READABLE|FMODE_WRITABLE)) {
5774  if (rb_pipe(arg.write_pair) < 0)
5775  rb_sys_fail_str(prog);
5776  if (rb_pipe(arg.pair) < 0) {
5777  int e = errno;
5778  close(arg.write_pair[0]);
5779  close(arg.write_pair[1]);
5780  errno = e;
5781  rb_sys_fail_str(prog);
5782  }
5783  if (eargp) {
5784  rb_execarg_addopt(execarg_obj, INT2FIX(0), INT2FIX(arg.write_pair[0]));
5785  rb_execarg_addopt(execarg_obj, INT2FIX(1), INT2FIX(arg.pair[1]));
5786  }
5787  break;
5788  case FMODE_READABLE:
5789  if (rb_pipe(arg.pair) < 0)
5790  rb_sys_fail_str(prog);
5791  if (eargp)
5792  rb_execarg_addopt(execarg_obj, INT2FIX(1), INT2FIX(arg.pair[1]));
5793  break;
5794  case FMODE_WRITABLE:
5795  if (rb_pipe(arg.pair) < 0)
5796  rb_sys_fail_str(prog);
5797  if (eargp)
5798  rb_execarg_addopt(execarg_obj, INT2FIX(0), INT2FIX(arg.pair[0]));
5799  break;
5800  default:
5801  rb_sys_fail_str(prog);
5802  }
5803  if (!NIL_P(execarg_obj)) {
5804  rb_execarg_fixup(execarg_obj);
5805 # if defined(HAVE_FORK)
5806  pid = rb_fork_async_signal_safe(&status, popen_exec, &arg, arg.eargp->redirect_fds, errmsg, sizeof(errmsg));
5807 # else
5808  rb_execarg_run_options(eargp, sargp, NULL, 0);
5809 # if defined(HAVE_SPAWNVE)
5810  if (eargp->envp_str) envp = (char **)RSTRING_PTR(eargp->envp_str);
5811 # endif
5812  while ((pid = DO_SPAWN(cmd, args, envp)) == -1) {
5813  /* exec failed */
5814  switch (e = errno) {
5815  case EAGAIN:
5816 # if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
5817  case EWOULDBLOCK:
5818 # endif
5819  rb_thread_sleep(1);
5820  continue;
5821  }
5822  break;
5823  }
5824  if (eargp)
5825  rb_execarg_run_options(sargp, NULL, NULL, 0);
5826 # endif
5827  }
5828  else {
5829 # if defined(HAVE_FORK)
5830  pid = rb_fork_ruby(&status);
5831  if (pid == 0) { /* child */
5832  rb_thread_atfork();
5833  popen_redirect(&arg);
5836  return Qnil;
5837  }
5838 # else
5839  rb_notimplement();
5840 # endif
5841  }
5842 
5843  /* parent */
5844  if (pid == -1) {
5845 # if defined(HAVE_FORK)
5846  e = errno;
5847 # endif
5848  close(arg.pair[0]);
5849  close(arg.pair[1]);
5851  close(arg.write_pair[0]);
5852  close(arg.write_pair[1]);
5853  }
5854  errno = e;
5855 # if defined(HAVE_FORK)
5856  if (errmsg[0])
5857  rb_sys_fail(errmsg);
5858 # endif
5859  rb_sys_fail_str(prog);
5860  }
5861  if ((fmode & FMODE_READABLE) && (fmode & FMODE_WRITABLE)) {
5862  close(arg.pair[1]);
5863  fd = arg.pair[0];
5864  close(arg.write_pair[0]);
5865  write_fd = arg.write_pair[1];
5866  }
5867  else if (fmode & FMODE_READABLE) {
5868  close(arg.pair[1]);
5869  fd = arg.pair[0];
5870  }
5871  else {
5872  close(arg.pair[0]);
5873  fd = arg.pair[1];
5874  }
5875 #else
5876  if (argc) {
5877  prog = rb_ary_join(rb_ary_new4(argc, argv), rb_str_new2(" "));
5878  cmd = StringValueCStr(prog);
5879  }
5880  if (!NIL_P(execarg_obj)) {
5881  rb_execarg_fixup(execarg_obj);
5882  rb_execarg_run_options(eargp, sargp, NULL, 0);
5883  }
5884  fp = popen(cmd, modestr);
5885  if (eargp)
5886  rb_execarg_run_options(sargp, NULL, NULL, 0);
5887  if (!fp) rb_sys_fail_path(prog);
5888  fd = fileno(fp);
5889 #endif
5890 
5891  port = io_alloc(rb_cIO);
5892  MakeOpenFile(port, fptr);
5893  fptr->fd = fd;
5894  fptr->stdio_file = fp;
5895  fptr->mode = fmode | FMODE_SYNC|FMODE_DUPLEX;
5896  if (convconfig) {
5897  fptr->encs = *convconfig;
5898 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
5901  }
5902 #endif
5903  }
5904  else {
5905  if (NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {
5907  }
5908 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
5909  if (NEED_NEWLINE_DECORATOR_ON_WRITE(fptr)) {
5910  fptr->encs.ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
5911  }
5912 #endif
5913  }
5914  fptr->pid = pid;
5915 
5916  if (0 <= write_fd) {
5917  write_port = io_alloc(rb_cIO);
5918  MakeOpenFile(write_port, write_fptr);
5919  write_fptr->fd = write_fd;
5920  write_fptr->mode = (fmode & ~FMODE_READABLE)| FMODE_SYNC|FMODE_DUPLEX;
5921  fptr->mode &= ~FMODE_WRITABLE;
5922  fptr->tied_io_for_writing = write_port;
5923  rb_ivar_set(port, rb_intern("@tied_io_for_writing"), write_port);
5924  }
5925 
5926 #if defined (__CYGWIN__) || !defined(HAVE_FORK)
5927  fptr->finalize = pipe_finalize;
5928  pipe_add_fptr(fptr);
5929 #endif
5930  return port;
5931 }
5932 
5933 static int
5935 {
5936  if (RSTRING_LEN(prog) == 1 && RSTRING_PTR(prog)[0] == '-') {
5937 #if !defined(HAVE_FORK)
5939  "fork() function is unimplemented on this machine");
5940 #else
5941  return TRUE;
5942 #endif
5943  }
5944  return FALSE;
5945 }
5946 
5947 static VALUE
5948 pipe_open_s(VALUE prog, const char *modestr, int fmode, convconfig_t *convconfig)
5949 {
5950  int argc = 1;
5951  VALUE *argv = &prog;
5952  VALUE execarg_obj = Qnil;
5953 
5954  if (!is_popen_fork(prog))
5955  execarg_obj = rb_execarg_new(argc, argv, TRUE);
5956  return pipe_open(execarg_obj, modestr, fmode, convconfig);
5957 }
5958 
5959 /*
5960  * call-seq:
5961  * IO.popen([env,] cmd, mode="r" [, opt]) -> io
5962  * IO.popen([env,] cmd, mode="r" [, opt]) {|io| block } -> obj
5963  *
5964  * Runs the specified command as a subprocess; the subprocess's
5965  * standard input and output will be connected to the returned
5966  * <code>IO</code> object.
5967  *
5968  * The PID of the started process can be obtained by IO#pid method.
5969  *
5970  * _cmd_ is a string or an array as follows.
5971  *
5972  * cmd:
5973  * "-" : fork
5974  * commandline : command line string which is passed to a shell
5975  * [env, cmdname, arg1, ..., opts] : command name and zero or more arguments (no shell)
5976  * [env, [cmdname, argv0], arg1, ..., opts] : command name, argv[0] and zero or more arguments (no shell)
5977  * (env and opts are optional.)
5978  *
5979  * If _cmd_ is a +String+ ``<code>-</code>'',
5980  * then a new instance of Ruby is started as the subprocess.
5981  *
5982  * If <i>cmd</i> is an +Array+ of +String+,
5983  * then it will be used as the subprocess's +argv+ bypassing a shell.
5984  * The array can contains a hash at first for environments and
5985  * a hash at last for options similar to <code>spawn</code>.
5986  *
5987  * The default mode for the new file object is ``r'',
5988  * but <i>mode</i> may be set to any of the modes listed in the description for class IO.
5989  * The last argument <i>opt</i> qualifies <i>mode</i>.
5990  *
5991  * # set IO encoding
5992  * IO.popen("nkf -e filename", :external_encoding=>"EUC-JP") {|nkf_io|
5993  * euc_jp_string = nkf_io.read
5994  * }
5995  *
5996  * # merge standard output and standard error using
5997  * # spawn option. See the document of Kernel.spawn.
5998  * IO.popen(["ls", "/", :err=>[:child, :out]]) {|ls_io|
5999  * ls_result_with_error = ls_io.read
6000  * }
6001  *
6002  * # spawn options can be mixed with IO options
6003  * IO.popen(["ls", "/"], :err=>[:child, :out]) {|ls_io|
6004  * ls_result_with_error = ls_io.read
6005  * }
6006  *
6007  * Raises exceptions which <code>IO.pipe</code> and
6008  * <code>Kernel.spawn</code> raise.
6009  *
6010  * If a block is given, Ruby will run the command as a child connected
6011  * to Ruby with a pipe. Ruby's end of the pipe will be passed as a
6012  * parameter to the block.
6013  * At the end of block, Ruby close the pipe and sets <code>$?</code>.
6014  * In this case <code>IO.popen</code> returns
6015  * the value of the block.
6016  *
6017  * If a block is given with a _cmd_ of ``<code>-</code>'',
6018  * the block will be run in two separate processes: once in the parent,
6019  * and once in a child. The parent process will be passed the pipe
6020  * object as a parameter to the block, the child version of the block
6021  * will be passed <code>nil</code>, and the child's standard in and
6022  * standard out will be connected to the parent through the pipe. Not
6023  * available on all platforms.
6024  *
6025  * f = IO.popen("uname")
6026  * p f.readlines
6027  * f.close
6028  * puts "Parent is #{Process.pid}"
6029  * IO.popen("date") { |f| puts f.gets }
6030  * IO.popen("-") {|f| $stderr.puts "#{Process.pid} is here, f is #{f.inspect}"}
6031  * p $?
6032  * IO.popen(%w"sed -e s|^|<foo>| -e s&$&;zot;&", "r+") {|f|
6033  * f.puts "bar"; f.close_write; puts f.gets
6034  * }
6035  *
6036  * <em>produces:</em>
6037  *
6038  * ["Linux\n"]
6039  * Parent is 21346
6040  * Thu Jan 15 22:41:19 JST 2009
6041  * 21346 is here, f is #<IO:fd 3>
6042  * 21352 is here, f is nil
6043  * #<Process::Status: pid 21352 exit 0>
6044  * <foo>bar;zot;
6045  */
6046 
6047 static VALUE
6049 {
6050  const char *modestr;
6051  VALUE pname, pmode = Qnil, port, tmp, opt = Qnil, env = Qnil, execarg_obj = Qnil;
6052  int oflags, fmode;
6053  convconfig_t convconfig;
6054 
6055  if (argc > 1 && !NIL_P(opt = rb_check_hash_type(argv[argc-1]))) --argc;
6056  if (argc > 1 && !NIL_P(env = rb_check_hash_type(argv[0]))) --argc, ++argv;
6057  switch (argc) {
6058  case 2:
6059  pmode = argv[1];
6060  case 1:
6061  pname = argv[0];
6062  break;
6063  default:
6064  {
6065  int ex = !NIL_P(opt);
6066  rb_error_arity(argc + ex, 1 + ex, 2 + ex);
6067  }
6068  }
6069 
6070  tmp = rb_check_array_type(pname);
6071  if (!NIL_P(tmp)) {
6072  long len = RARRAY_LEN(tmp);
6073 #if SIZEOF_LONG > SIZEOF_INT
6074  if (len > INT_MAX) {
6075  rb_raise(rb_eArgError, "too many arguments");
6076  }
6077 #endif
6078  tmp = rb_ary_dup(tmp);
6079  RBASIC(tmp)->klass = 0;
6080  execarg_obj = rb_execarg_new((int)len, RARRAY_PTR(tmp), FALSE);
6081  rb_ary_clear(tmp);
6082  }
6083  else {
6084  SafeStringValue(pname);
6085  execarg_obj = Qnil;
6086  if (!is_popen_fork(pname))
6087  execarg_obj = rb_execarg_new(1, &pname, TRUE);
6088  }
6089  if (!NIL_P(execarg_obj)) {
6090  if (!NIL_P(opt))
6091  opt = rb_execarg_extract_options(execarg_obj, opt);
6092  if (!NIL_P(env))
6093  rb_execarg_setenv(execarg_obj, env);
6094  }
6095  rb_io_extract_modeenc(&pmode, 0, opt, &oflags, &fmode, &convconfig);
6096  modestr = rb_io_oflags_modestr(oflags);
6097 
6098  port = pipe_open(execarg_obj, modestr, fmode, &convconfig);
6099  if (NIL_P(port)) {
6100  /* child */
6101  if (rb_block_given_p()) {
6102  rb_yield(Qnil);
6105  _exit(0);
6106  }
6107  return Qnil;
6108  }
6109  RBASIC(port)->klass = klass;
6110  if (rb_block_given_p()) {
6111  return rb_ensure(rb_yield, port, io_close, port);
6112  }
6113  return port;
6114 }
6115 
6116 static void
6118  VALUE *fname_p, int *oflags_p, int *fmode_p,
6119  convconfig_t *convconfig_p, mode_t *perm_p)
6120 {
6121  VALUE opt, fname, vmode, vperm;
6122  int oflags, fmode;
6123  mode_t perm;
6124 
6125  argc = rb_scan_args(argc, argv, "12:", &fname, &vmode, &vperm, &opt);
6126  FilePathValue(fname);
6127 
6128  rb_io_extract_modeenc(&vmode, &vperm, opt, &oflags, &fmode, convconfig_p);
6129 
6130  perm = NIL_P(vperm) ? 0666 : NUM2MODET(vperm);
6131 
6132  *fname_p = fname;
6133  *oflags_p = oflags;
6134  *fmode_p = fmode;
6135  *perm_p = perm;
6136 }
6137 
6138 static VALUE
6140 {
6141  VALUE fname;
6142  int oflags, fmode;
6143  convconfig_t convconfig;
6144  mode_t perm;
6145 
6146  rb_scan_open_args(argc, argv, &fname, &oflags, &fmode, &convconfig, &perm);
6147  rb_file_open_generic(io, fname, oflags, fmode, &convconfig, perm);
6148 
6149  return io;
6150 }
6151 
6152 
6153 /*
6154  * Document-method: File::open
6155  *
6156  * call-seq:
6157  * File.open(filename, mode="r" [, opt]) -> file
6158  * File.open(filename [, mode [, perm]] [, opt]) -> file
6159  * File.open(filename, mode="r" [, opt]) {|file| block } -> obj
6160  * File.open(filename [, mode [, perm]] [, opt]) {|file| block } -> obj
6161  *
6162  * With no associated block, <code>File.open</code> is a synonym for
6163  * File.new. If the optional code block is given, it will
6164  * be passed the opened +file+ as an argument and the File object will
6165  * automatically be closed when the block terminates. The value of the block
6166  * will be returned from <code>File.open</code>.
6167  *
6168  * If a file is being created, its initial permissions may be set using the
6169  * +perm+ parameter. See File.new for further discussion.
6170  *
6171  * See IO.new for a description of the +mode+ and +opt+ parameters.
6172  */
6173 
6174 /*
6175  * Document-method: IO::open
6176  *
6177  * call-seq:
6178  * IO.open(fd, mode="r" [, opt]) -> io
6179  * IO.open(fd, mode="r" [, opt]) { |io| block } -> obj
6180  *
6181  * With no associated block, <code>IO.open</code> is a synonym for IO.new. If
6182  * the optional code block is given, it will be passed +io+ as an argument,
6183  * and the IO object will automatically be closed when the block terminates.
6184  * In this instance, IO.open returns the value of the block.
6185  *
6186  * See IO.new for a description of the +fd+, +mode+ and +opt+ parameters.
6187  */
6188 
6189 static VALUE
6191 {
6192  VALUE io = rb_class_new_instance(argc, argv, klass);
6193 
6194  if (rb_block_given_p()) {
6195  return rb_ensure(rb_yield, io, io_close, io);
6196  }
6197 
6198  return io;
6199 }
6200 
6201 /*
6202  * call-seq:
6203  * IO.sysopen(path, [mode, [perm]]) -> fixnum
6204  *
6205  * Opens the given path, returning the underlying file descriptor as a
6206  * <code>Fixnum</code>.
6207  *
6208  * IO.sysopen("testfile") #=> 3
6209  */
6210 
6211 static VALUE
6213 {
6214  VALUE fname, vmode, vperm;
6215  VALUE intmode;
6216  int oflags, fd;
6217  mode_t perm;
6218 
6219  rb_scan_args(argc, argv, "12", &fname, &vmode, &vperm);
6220  FilePathValue(fname);
6221 
6222  if (NIL_P(vmode))
6223  oflags = O_RDONLY;
6224  else if (!NIL_P(intmode = rb_check_to_integer(vmode, "to_int")))
6225  oflags = NUM2INT(intmode);
6226  else {
6227  SafeStringValue(vmode);
6228  oflags = rb_io_modestr_oflags(StringValueCStr(vmode));
6229  }
6230  if (NIL_P(vperm)) perm = 0666;
6231  else perm = NUM2MODET(vperm);
6232 
6233  RB_GC_GUARD(fname) = rb_str_new4(fname);
6234  fd = rb_sysopen(fname, oflags, perm);
6235  return INT2NUM(fd);
6236 }
6237 
6238 static VALUE
6239 check_pipe_command(VALUE filename_or_command)
6240 {
6241  char *s = RSTRING_PTR(filename_or_command);
6242  long l = RSTRING_LEN(filename_or_command);
6243  char *e = s + l;
6244  int chlen;
6245 
6246  if (rb_enc_ascget(s, e, &chlen, rb_enc_get(filename_or_command)) == '|') {
6247  VALUE cmd = rb_str_new(s+chlen, l-chlen);
6248  OBJ_INFECT(cmd, filename_or_command);
6249  return cmd;
6250  }
6251  return Qnil;
6252 }
6253 
6254 /*
6255  * call-seq:
6256  * open(path [, mode [, perm]] [, opt]) -> io or nil
6257  * open(path [, mode [, perm]] [, opt]) {|io| block } -> obj
6258  *
6259  * Creates an IO object connected to the given stream, file, or subprocess.
6260  *
6261  * If +path+ does not start with a pipe character (<code>|</code>), treat it
6262  * as the name of a file to open using the specified mode (defaulting to
6263  * "r").
6264  *
6265  * The +mode+ is either a string or an integer. If it is an integer, it
6266  * must be bitwise-or of open(2) flags, such as File::RDWR or File::EXCL. If
6267  * it is a string, it is either "fmode", "fmode:ext_enc", or
6268  * "fmode:ext_enc:int_enc".
6269  *
6270  * See the documentation of IO.new for full documentation of the +mode+ string
6271  * directives.
6272  *
6273  * If a file is being created, its initial permissions may be set using the
6274  * +perm+ parameter. See File.new and the open(2) and chmod(2) man pages for
6275  * a description of permissions.
6276  *
6277  * If a block is specified, it will be invoked with the IO object as a
6278  * parameter, and the IO will be automatically closed when the block
6279  * terminates. The call returns the value of the block.
6280  *
6281  * If +path+ starts with a pipe character (<code>"|"</code>), a subprocess is
6282  * created, connected to the caller by a pair of pipes. The returned IO
6283  * object may be used to write to the standard input and read from the
6284  * standard output of this subprocess.
6285  *
6286  * If the command following the pipe is a single minus sign
6287  * (<code>"|-"</code>), Ruby forks, and this subprocess is connected to the
6288  * parent. If the command is not <code>"-"</code>, the subprocess runs the
6289  * command.
6290  *
6291  * When the subprocess is ruby (opened via <code>"|-"</code>), the +open+
6292  * call returns +nil+. If a block is associated with the open call, that
6293  * block will run twice --- once in the parent and once in the child.
6294  *
6295  * The block parameter will be an IO object in the parent and +nil+ in the
6296  * child. The parent's +IO+ object will be connected to the child's $stdin
6297  * and $stdout. The subprocess will be terminated at the end of the block.
6298  *
6299  * === Examples
6300  *
6301  * Reading from "testfile":
6302  *
6303  * open("testfile") do |f|
6304  * print f.gets
6305  * end
6306  *
6307  * Produces:
6308  *
6309  * This is line one
6310  *
6311  * Open a subprocess and read its output:
6312  *
6313  * cmd = open("|date")
6314  * print cmd.gets
6315  * cmd.close
6316  *
6317  * Produces:
6318  *
6319  * Wed Apr 9 08:56:31 CDT 2003
6320  *
6321  * Open a subprocess running the same Ruby program:
6322  *
6323  * f = open("|-", "w+")
6324  * if f == nil
6325  * puts "in Child"
6326  * exit
6327  * else
6328  * puts "Got: #{f.gets}"
6329  * end
6330  *
6331  * Produces:
6332  *
6333  * Got: in Child
6334  *
6335  * Open a subprocess using a block to receive the IO object:
6336  *
6337  * open "|-" do |f|
6338  * if f then
6339  * # parent process
6340  * puts "Got: #{f.gets}"
6341  * else
6342  * # child process
6343  * puts "in Child"
6344  * end
6345  * end
6346  *
6347  * Produces:
6348  *
6349  * Got: in Child
6350  */
6351 
6352 static VALUE
6354 {
6355  ID to_open = 0;
6356  int redirect = FALSE;
6357 
6358  if (argc >= 1) {
6359  CONST_ID(to_open, "to_open");
6360  if (rb_respond_to(argv[0], to_open)) {
6361  redirect = TRUE;
6362  }
6363  else {
6364  VALUE tmp = argv[0];
6365  FilePathValue(tmp);
6366  if (NIL_P(tmp)) {
6367  redirect = TRUE;
6368  }
6369  else {
6370  VALUE cmd = check_pipe_command(tmp);
6371  if (!NIL_P(cmd)) {
6372  argv[0] = cmd;
6373  return rb_io_s_popen(argc, argv, rb_cIO);
6374  }
6375  }
6376  }
6377  }
6378  if (redirect) {
6379  VALUE io = rb_funcall2(argv[0], to_open, argc-1, argv+1);
6380 
6381  if (rb_block_given_p()) {
6382  return rb_ensure(rb_yield, io, io_close, io);
6383  }
6384  return io;
6385  }
6386  return rb_io_s_open(argc, argv, rb_cFile);
6387 }
6388 
6389 static VALUE
6390 rb_io_open(VALUE filename, VALUE vmode, VALUE vperm, VALUE opt)
6391 {
6392  VALUE cmd;
6393  int oflags, fmode;
6394  convconfig_t convconfig;
6395  mode_t perm;
6396 
6397  rb_io_extract_modeenc(&vmode, &vperm, opt, &oflags, &fmode, &convconfig);
6398  perm = NIL_P(vperm) ? 0666 : NUM2MODET(vperm);
6399 
6400  if (!NIL_P(cmd = check_pipe_command(filename))) {
6401  return pipe_open_s(cmd, rb_io_oflags_modestr(oflags), fmode, &convconfig);
6402  }
6403  else {
6404  return rb_file_open_generic(io_alloc(rb_cFile), filename,
6405  oflags, fmode, &convconfig, perm);
6406  }
6407 }
6408 
6409 static VALUE
6411 {
6412  VALUE io;
6413 
6414  io = io_alloc(rb_cFile);
6415  rb_open_file(argc, argv, io);
6416  return io;
6417 }
6418 
6419 static VALUE
6421 {
6422  rb_io_t *fptr, *orig;
6423  int fd, fd2;
6424  off_t pos = 0;
6425 
6426  nfile = rb_io_get_io(nfile);
6427  if (rb_safe_level() >= 4 &&
6428  (!OBJ_UNTRUSTED(io) || !OBJ_UNTRUSTED(nfile))) {
6429  rb_raise(rb_eSecurityError, "Insecure: can't reopen");
6430  }
6431  GetOpenFile(io, fptr);
6432  GetOpenFile(nfile, orig);
6433 
6434  if (fptr == orig) return io;
6435  if (IS_PREP_STDIO(fptr)) {
6436  if ((fptr->stdio_file == stdin && !(orig->mode & FMODE_READABLE)) ||
6437  (fptr->stdio_file == stdout && !(orig->mode & FMODE_WRITABLE)) ||
6438  (fptr->stdio_file == stderr && !(orig->mode & FMODE_WRITABLE))) {
6440  "%s can't change access mode from \"%s\" to \"%s\"",
6442  rb_io_fmode_modestr(orig->mode));
6443  }
6444  }
6445  if (fptr->mode & FMODE_WRITABLE) {
6446  if (io_fflush(fptr) < 0)
6447  rb_sys_fail(0);
6448  }
6449  else {
6450  io_tell(fptr);
6451  }
6452  if (orig->mode & FMODE_READABLE) {
6453  pos = io_tell(orig);
6454  }
6455  if (orig->mode & FMODE_WRITABLE) {
6456  if (io_fflush(orig) < 0)
6457  rb_sys_fail(0);
6458  }
6459 
6460  /* copy rb_io_t structure */
6461  fptr->mode = orig->mode | (fptr->mode & FMODE_PREP);
6462  fptr->pid = orig->pid;
6463  fptr->lineno = orig->lineno;
6464  if (RTEST(orig->pathv)) fptr->pathv = orig->pathv;
6465  else if (!IS_PREP_STDIO(fptr)) fptr->pathv = Qnil;
6466  fptr->finalize = orig->finalize;
6467 #if defined (__CYGWIN__) || !defined(HAVE_FORK)
6468  if (fptr->finalize == pipe_finalize)
6469  pipe_add_fptr(fptr);
6470 #endif
6471 
6472  fd = fptr->fd;
6473  fd2 = orig->fd;
6474  if (fd != fd2) {
6475  if (IS_PREP_STDIO(fptr) || fd <= 2 || !fptr->stdio_file) {
6476  /* need to keep FILE objects of stdin, stdout and stderr */
6477  if (rb_cloexec_dup2(fd2, fd) < 0)
6478  rb_sys_fail_path(orig->pathv);
6479  rb_update_max_fd(fd);
6480  }
6481  else {
6482  fclose(fptr->stdio_file);
6483  fptr->stdio_file = 0;
6484  fptr->fd = -1;
6485  if (rb_cloexec_dup2(fd2, fd) < 0)
6486  rb_sys_fail_path(orig->pathv);
6487  rb_update_max_fd(fd);
6488  fptr->fd = fd;
6489  }
6490  rb_thread_fd_close(fd);
6491  if ((orig->mode & FMODE_READABLE) && pos >= 0) {
6492  if (io_seek(fptr, pos, SEEK_SET) < 0 && errno) {
6493  rb_sys_fail_path(fptr->pathv);
6494  }
6495  if (io_seek(orig, pos, SEEK_SET) < 0 && errno) {
6496  rb_sys_fail_path(orig->pathv);
6497  }
6498  }
6499  }
6500 
6501  if (fptr->mode & FMODE_BINMODE) {
6502  rb_io_binmode(io);
6503  }
6504 
6505  RBASIC(io)->klass = rb_obj_class(nfile);
6506  return io;
6507 }
6508 
6509 /*
6510  * call-seq:
6511  * ios.reopen(other_IO) -> ios
6512  * ios.reopen(path, mode_str) -> ios
6513  *
6514  * Reassociates <em>ios</em> with the I/O stream given in
6515  * <i>other_IO</i> or to a new stream opened on <i>path</i>. This may
6516  * dynamically change the actual class of this stream.
6517  *
6518  * f1 = File.new("testfile")
6519  * f2 = File.new("testfile")
6520  * f2.readlines[0] #=> "This is line one\n"
6521  * f2.reopen(f1) #=> #<File:testfile>
6522  * f2.readlines[0] #=> "This is line one\n"
6523  */
6524 
6525 static VALUE
6527 {
6528  VALUE fname, nmode, opt;
6529  int oflags;
6530  rb_io_t *fptr;
6531 
6532  rb_secure(4);
6533  if (rb_scan_args(argc, argv, "11:", &fname, &nmode, &opt) == 1) {
6534  VALUE tmp = rb_io_check_io(fname);
6535  if (!NIL_P(tmp)) {
6536  return io_reopen(file, tmp);
6537  }
6538  }
6539 
6540  FilePathValue(fname);
6541  rb_io_taint_check(file);
6542  fptr = RFILE(file)->fptr;
6543  if (!fptr) {
6544  fptr = RFILE(file)->fptr = ALLOC(rb_io_t);
6545  MEMZERO(fptr, rb_io_t, 1);
6546  }
6547 
6548  if (!NIL_P(nmode) || !NIL_P(opt)) {
6549  int fmode;
6550  convconfig_t convconfig;
6551 
6552  rb_io_extract_modeenc(&nmode, 0, opt, &oflags, &fmode, &convconfig);
6553  if (IS_PREP_STDIO(fptr) &&
6554  ((fptr->mode & FMODE_READWRITE) & (fmode & FMODE_READWRITE)) !=
6555  (fptr->mode & FMODE_READWRITE)) {
6557  "%s can't change access mode from \"%s\" to \"%s\"",
6559  rb_io_fmode_modestr(fmode));
6560  }
6561  fptr->mode = fmode;
6562  fptr->encs = convconfig;
6563  }
6564  else {
6565  oflags = rb_io_fmode_oflags(fptr->mode);
6566  }
6567 
6568  fptr->pathv = rb_str_new_frozen(fname);
6569  if (fptr->fd < 0) {
6570  fptr->fd = rb_sysopen(fptr->pathv, oflags, 0666);
6571  fptr->stdio_file = 0;
6572  return file;
6573  }
6574 
6575  if (fptr->mode & FMODE_WRITABLE) {
6576  if (io_fflush(fptr) < 0)
6577  rb_sys_fail(0);
6578  }
6579  fptr->rbuf.off = fptr->rbuf.len = 0;
6580 
6581  if (fptr->stdio_file) {
6582  if (freopen(RSTRING_PTR(fptr->pathv), rb_io_oflags_modestr(oflags), fptr->stdio_file) == 0) {
6583  rb_sys_fail_path(fptr->pathv);
6584  }
6585  fptr->fd = fileno(fptr->stdio_file);
6586  rb_fd_fix_cloexec(fptr->fd);
6587 #ifdef USE_SETVBUF
6588  if (setvbuf(fptr->stdio_file, NULL, _IOFBF, 0) != 0)
6589  rb_warn("setvbuf() can't be honoured for %s", RSTRING_PTR(fptr->pathv));
6590 #endif
6591  if (fptr->stdio_file == stderr) {
6592  if (setvbuf(fptr->stdio_file, NULL, _IONBF, BUFSIZ) != 0)
6593  rb_warn("setvbuf() can't be honoured for %s", RSTRING_PTR(fptr->pathv));
6594  }
6595  else if (fptr->stdio_file == stdout && isatty(fptr->fd)) {
6596  if (setvbuf(fptr->stdio_file, NULL, _IOLBF, BUFSIZ) != 0)
6597  rb_warn("setvbuf() can't be honoured for %s", RSTRING_PTR(fptr->pathv));
6598  }
6599  }
6600  else {
6601  if (close(fptr->fd) < 0)
6602  rb_sys_fail_path(fptr->pathv);
6603  fptr->fd = -1;
6604  fptr->fd = rb_sysopen(fptr->pathv, oflags, 0666);
6605  }
6606 
6607  return file;
6608 }
6609 
6610 /* :nodoc: */
6611 static VALUE
6613 {
6614  rb_io_t *fptr, *orig;
6615  int fd;
6616  VALUE write_io;
6617  off_t pos;
6618 
6619  io = rb_io_get_io(io);
6620  if (!OBJ_INIT_COPY(dest, io)) return dest;
6621  GetOpenFile(io, orig);
6622  MakeOpenFile(dest, fptr);
6623 
6624  rb_io_flush(io);
6625 
6626  /* copy rb_io_t structure */
6627  fptr->mode = orig->mode & ~FMODE_PREP;
6628  fptr->encs = orig->encs;
6629  fptr->pid = orig->pid;
6630  fptr->lineno = orig->lineno;
6631  if (!NIL_P(orig->pathv)) fptr->pathv = orig->pathv;
6632  fptr->finalize = orig->finalize;
6633 #if defined (__CYGWIN__) || !defined(HAVE_FORK)
6634  if (fptr->finalize == pipe_finalize)
6635  pipe_add_fptr(fptr);
6636 #endif
6637 
6638  fd = ruby_dup(orig->fd);
6639  fptr->fd = fd;
6640  pos = io_tell(orig);
6641  if (0 <= pos)
6642  io_seek(fptr, pos, SEEK_SET);
6643  if (fptr->mode & FMODE_BINMODE) {
6644  rb_io_binmode(dest);
6645  }
6646 
6647  write_io = GetWriteIO(io);
6648  if (io != write_io) {
6649  write_io = rb_obj_dup(write_io);
6650  fptr->tied_io_for_writing = write_io;
6651  rb_ivar_set(dest, rb_intern("@tied_io_for_writing"), write_io);
6652  }
6653 
6654  return dest;
6655 }
6656 
6657 /*
6658  * call-seq:
6659  * ios.printf(format_string [, obj, ...]) -> nil
6660  *
6661  * Formats and writes to <em>ios</em>, converting parameters under
6662  * control of the format string. See <code>Kernel#sprintf</code>
6663  * for details.
6664  */
6665 
6666 VALUE
6668 {
6669  rb_io_write(out, rb_f_sprintf(argc, argv));
6670  return Qnil;
6671 }
6672 
6673 /*
6674  * call-seq:
6675  * printf(io, string [, obj ... ]) -> nil
6676  * printf(string [, obj ... ]) -> nil
6677  *
6678  * Equivalent to:
6679  * io.write(sprintf(string, obj, ...)
6680  * or
6681  * $stdout.write(sprintf(string, obj, ...)
6682  */
6683 
6684 static VALUE
6686 {
6687  VALUE out;
6688 
6689  if (argc == 0) return Qnil;
6690  if (RB_TYPE_P(argv[0], T_STRING)) {
6691  out = rb_stdout;
6692  }
6693  else {
6694  out = argv[0];
6695  argv++;
6696  argc--;
6697  }
6698  rb_io_write(out, rb_f_sprintf(argc, argv));
6699 
6700  return Qnil;
6701 }
6702 
6703 /*
6704  * call-seq:
6705  * ios.print() -> nil
6706  * ios.print(obj, ...) -> nil
6707  *
6708  * Writes the given object(s) to <em>ios</em>. The stream must be
6709  * opened for writing. If the output field separator (<code>$,</code>)
6710  * is not <code>nil</code>, it will be inserted between each object.
6711  * If the output record separator (<code>$\</code>)
6712  * is not <code>nil</code>, it will be appended to the output. If no
6713  * arguments are given, prints <code>$_</code>. Objects that aren't
6714  * strings will be converted by calling their <code>to_s</code> method.
6715  * With no argument, prints the contents of the variable <code>$_</code>.
6716  * Returns <code>nil</code>.
6717  *
6718  * $stdout.print("This is ", 100, " percent.\n")
6719  *
6720  * <em>produces:</em>
6721  *
6722  * This is 100 percent.
6723  */
6724 
6725 VALUE
6727 {
6728  int i;
6729  VALUE line;
6730 
6731  /* if no argument given, print `$_' */
6732  if (argc == 0) {
6733  argc = 1;
6734  line = rb_lastline_get();
6735  argv = &line;
6736  }
6737  for (i=0; i<argc; i++) {
6738  if (!NIL_P(rb_output_fs) && i>0) {
6739  rb_io_write(out, rb_output_fs);
6740  }
6741  rb_io_write(out, argv[i]);
6742  }
6743  if (argc > 0 && !NIL_P(rb_output_rs)) {
6744  rb_io_write(out, rb_output_rs);
6745  }
6746 
6747  return Qnil;
6748 }
6749 
6750 /*
6751  * call-seq:
6752  * print(obj, ...) -> nil
6753  *
6754  * Prints each object in turn to <code>$stdout</code>. If the output
6755  * field separator (<code>$,</code>) is not +nil+, its
6756  * contents will appear between each field. If the output record
6757  * separator (<code>$\</code>) is not +nil+, it will be
6758  * appended to the output. If no arguments are given, prints
6759  * <code>$_</code>. Objects that aren't strings will be converted by
6760  * calling their <code>to_s</code> method.
6761  *
6762  * print "cat", [1,2,3], 99, "\n"
6763  * $, = ", "
6764  * $\ = "\n"
6765  * print "cat", [1,2,3], 99
6766  *
6767  * <em>produces:</em>
6768  *
6769  * cat12399
6770  * cat, 1, 2, 3, 99
6771  */
6772 
6773 static VALUE
6775 {
6776  rb_io_print(argc, argv, rb_stdout);
6777  return Qnil;
6778 }
6779 
6780 /*
6781  * call-seq:
6782  * ios.putc(obj) -> obj
6783  *
6784  * If <i>obj</i> is <code>Numeric</code>, write the character whose code is
6785  * the least-significant byte of <i>obj</i>, otherwise write the first byte
6786  * of the string representation of <i>obj</i> to <em>ios</em>. Note: This
6787  * method is not safe for use with multi-byte characters as it will truncate
6788  * them.
6789  *
6790  * $stdout.putc "A"
6791  * $stdout.putc 65
6792  *
6793  * <em>produces:</em>
6794  *
6795  * AA
6796  */
6797 
6798 static VALUE
6800 {
6801  VALUE str;
6802  if (RB_TYPE_P(ch, T_STRING)) {
6803  str = rb_str_substr(ch, 0, 1);
6804  }
6805  else {
6806  char c = NUM2CHR(ch);
6807  str = rb_str_new(&c, 1);
6808  }
6809  rb_io_write(io, str);
6810  return ch;
6811 }
6812 
6813 /*
6814  * call-seq:
6815  * putc(int) -> int
6816  *
6817  * Equivalent to:
6818  *
6819  * $stdout.putc(int)
6820  *
6821  * Refer to the documentation for IO#putc for important information regarding
6822  * multi-byte characters.
6823  */
6824 
6825 static VALUE
6827 {
6828  if (recv == rb_stdout) {
6829  return rb_io_putc(recv, ch);
6830  }
6831  return rb_funcall2(rb_stdout, rb_intern("putc"), 1, &ch);
6832 }
6833 
6834 
6835 static int
6837 {
6838  long len = RSTRING_LEN(str);
6839  const char *ptr = RSTRING_PTR(str);
6841  int n;
6842 
6843  if (len == 0) return 0;
6844  if ((n = rb_enc_mbminlen(enc)) == 1) {
6845  return ptr[len - 1] == c;
6846  }
6847  return rb_enc_ascget(ptr + ((len - 1) / n) * n, ptr + len, &n, enc) == c;
6848 }
6849 
6850 static VALUE
6852 {
6853  VALUE tmp;
6854  long i;
6855 
6856  if (recur) {
6857  tmp = rb_str_new2("[...]");
6858  rb_io_puts(1, &tmp, out);
6859  return Qtrue;
6860  }
6861  ary = rb_check_array_type(ary);
6862  if (NIL_P(ary)) return Qfalse;
6863  for (i=0; i<RARRAY_LEN(ary); i++) {
6864  tmp = RARRAY_PTR(ary)[i];
6865  rb_io_puts(1, &tmp, out);
6866  }
6867  return Qtrue;
6868 }
6869 
6870 /*
6871  * call-seq:
6872  * ios.puts(obj, ...) -> nil
6873  *
6874  * Writes the given objects to <em>ios</em> as with
6875  * <code>IO#print</code>. Writes a record separator (typically a
6876  * newline) after any that do not already end with a newline sequence.
6877  * If called with an array argument, writes each element on a new line.
6878  * If called without arguments, outputs a single record separator.
6879  *
6880  * $stdout.puts("this", "is", "a", "test")
6881  *
6882  * <em>produces:</em>
6883  *
6884  * this
6885  * is
6886  * a
6887  * test
6888  */
6889 
6890 VALUE
6892 {
6893  int i;
6894  VALUE line;
6895 
6896  /* if no argument given, print newline. */
6897  if (argc == 0) {
6898  rb_io_write(out, rb_default_rs);
6899  return Qnil;
6900  }
6901  for (i=0; i<argc; i++) {
6902  if (RB_TYPE_P(argv[i], T_STRING)) {
6903  line = argv[i];
6904  goto string;
6905  }
6906  if (rb_exec_recursive(io_puts_ary, argv[i], out)) {
6907  continue;
6908  }
6909  line = rb_obj_as_string(argv[i]);
6910  string:
6911  rb_io_write(out, line);
6912  if (RSTRING_LEN(line) == 0 ||
6913  !str_end_with_asciichar(line, '\n')) {
6914  rb_io_write(out, rb_default_rs);
6915  }
6916  }
6917 
6918  return Qnil;
6919 }
6920 
6921 /*
6922  * call-seq:
6923  * puts(obj, ...) -> nil
6924  *
6925  * Equivalent to
6926  *
6927  * $stdout.puts(obj, ...)
6928  */
6929 
6930 static VALUE
6932 {
6933  if (recv == rb_stdout) {
6934  return rb_io_puts(argc, argv, recv);
6935  }
6936  return rb_funcall2(rb_stdout, rb_intern("puts"), argc, argv);
6937 }
6938 
6939 void
6940 rb_p(VALUE obj) /* for debug print within C code */
6941 {
6942  VALUE str = rb_obj_as_string(rb_inspect(obj));
6943  if (RB_TYPE_P(rb_stdout, T_FILE) &&
6945  io_write(rb_stdout, str, 1);
6947  }
6948  else {
6949  rb_io_write(rb_stdout, str);
6951  }
6952 }
6953 
6954 struct rb_f_p_arg {
6955  int argc;
6957 };
6958 
6959 static VALUE
6961 {
6962  struct rb_f_p_arg *arg1 = (struct rb_f_p_arg*)arg;
6963  int argc = arg1->argc;
6964  VALUE *argv = arg1->argv;
6965  int i;
6966  VALUE ret = Qnil;
6967 
6968  for (i=0; i<argc; i++) {
6969  rb_p(argv[i]);
6970  }
6971  if (argc == 1) {
6972  ret = argv[0];
6973  }
6974  else if (argc > 1) {
6975  ret = rb_ary_new4(argc, argv);
6976  }
6977  if (RB_TYPE_P(rb_stdout, T_FILE)) {
6979  }
6980  return ret;
6981 }
6982 
6983 /*
6984  * call-seq:
6985  * p(obj) -> obj
6986  * p(obj1, obj2, ...) -> [obj, ...]
6987  * p() -> nil
6988  *
6989  * For each object, directly writes _obj_.+inspect+ followed by a
6990  * newline to the program's standard output.
6991  *
6992  * S = Struct.new(:name, :state)
6993  * s = S['dave', 'TX']
6994  * p s
6995  *
6996  * <em>produces:</em>
6997  *
6998  * #<S name="dave", state="TX">
6999  */
7000 
7001 static VALUE
7003 {
7004  struct rb_f_p_arg arg;
7005  arg.argc = argc;
7006  arg.argv = argv;
7007 
7008  return rb_uninterruptible(rb_f_p_internal, (VALUE)&arg);
7009 }
7010 
7011 /*
7012  * call-seq:
7013  * obj.display(port=$>) -> nil
7014  *
7015  * Prints <i>obj</i> on the given port (default <code>$></code>).
7016  * Equivalent to:
7017  *
7018  * def display(port=$>)
7019  * port.write self
7020  * end
7021  *
7022  * For example:
7023  *
7024  * 1.display
7025  * "cat".display
7026  * [ 4, 5, 6 ].display
7027  * puts
7028  *
7029  * <em>produces:</em>
7030  *
7031  * 1cat456
7032  */
7033 
7034 static VALUE
7036 {
7037  VALUE out;
7038 
7039  if (argc == 0) {
7040  out = rb_stdout;
7041  }
7042  else {
7043  rb_scan_args(argc, argv, "01", &out);
7044  }
7045  rb_io_write(out, self);
7046 
7047  return Qnil;
7048 }
7049 
7050 void
7051 rb_write_error2(const char *mesg, long len)
7052 {
7053  if (rb_stderr == orig_stderr || RFILE(orig_stderr)->fptr->fd < 0) {
7054  if (fwrite(mesg, sizeof(char), (size_t)len, stderr) < (size_t)len) {
7055  /* failed to write to stderr, what can we do? */
7056  return;
7057  }
7058  }
7059  else {
7060  rb_io_write(rb_stderr, rb_str_new(mesg, len));
7061  }
7062 }
7063 
7064 void
7065 rb_write_error(const char *mesg)
7066 {
7067  rb_write_error2(mesg, strlen(mesg));
7068 }
7069 
7070 void
7072 {
7073  /* a stopgap measure for the time being */
7074  if (rb_stderr == orig_stderr || RFILE(orig_stderr)->fptr->fd < 0) {
7075  size_t len = (size_t)RSTRING_LEN(mesg);
7076  if (fwrite(RSTRING_PTR(mesg), sizeof(char), len, stderr) < len) {
7077  RB_GC_GUARD(mesg);
7078  return;
7079  }
7080  }
7081  else {
7082  /* may unlock GVL, and */
7083  rb_io_write(rb_stderr, mesg);
7084  }
7085 }
7086 
7087 static void
7089 {
7090  if (!rb_respond_to(val, mid)) {
7091  rb_raise(rb_eTypeError, "%s must have %s method, %s given",
7092  rb_id2name(id), rb_id2name(mid),
7093  rb_obj_classname(val));
7094  }
7095 }
7096 
7097 static void
7098 stdout_setter(VALUE val, ID id, VALUE *variable)
7099 {
7100  must_respond_to(id_write, val, id);
7101  *variable = val;
7102 }
7103 
7104 static VALUE
7105 prep_io(int fd, int fmode, VALUE klass, const char *path)
7106 {
7107  rb_io_t *fp;
7108  VALUE io = io_alloc(klass);
7109 
7110  MakeOpenFile(io, fp);
7111  fp->fd = fd;
7112 #ifdef __CYGWIN__
7113  if (!isatty(fd)) {
7114  fmode |= FMODE_BINMODE;
7115  setmode(fd, O_BINARY);
7116  }
7117 #endif
7118  fp->mode = fmode;
7119  io_check_tty(fp);
7120  if (path) fp->pathv = rb_obj_freeze(rb_str_new_cstr(path));
7121  rb_update_max_fd(fd);
7122 
7123  return io;
7124 }
7125 
7126 VALUE
7127 rb_io_fdopen(int fd, int oflags, const char *path)
7128 {
7129  VALUE klass = rb_cIO;
7130 
7131  if (path && strcmp(path, "-")) klass = rb_cFile;
7132  return prep_io(fd, rb_io_oflags_fmode(oflags), klass, path);
7133 }
7134 
7135 static VALUE
7136 prep_stdio(FILE *f, int fmode, VALUE klass, const char *path)
7137 {
7138  rb_io_t *fptr;
7139  VALUE io = prep_io(fileno(f), fmode|FMODE_PREP|DEFAULT_TEXTMODE, klass, path);
7140 
7141  GetOpenFile(io, fptr);
7143 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
7144  fptr->encs.ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
7145  if (fmode & FMODE_READABLE) {
7147  }
7148 #endif
7149  fptr->stdio_file = f;
7150 
7151  return io;
7152 }
7153 
7154 FILE *
7156 {
7157  if (!fptr->stdio_file) {
7158  int oflags = rb_io_fmode_oflags(fptr->mode);
7159  fptr->stdio_file = rb_fdopen(fptr->fd, rb_io_oflags_modestr(oflags));
7160  }
7161  return fptr->stdio_file;
7162 }
7163 
7164 /*
7165  * call-seq:
7166  * IO.new(fd [, mode] [, opt]) -> io
7167  *
7168  * Returns a new IO object (a stream) for the given integer file descriptor
7169  * +fd+ and +mode+ string. +opt+ may be used to specify parts of +mode+ in a
7170  * more readable fashion. See also IO.sysopen and IO.for_fd.
7171  *
7172  * IO.new is called by various File and IO opening methods such as IO::open,
7173  * Kernel#open, and File::open.
7174  *
7175  * === Open Mode
7176  *
7177  * When +mode+ is an integer it must be combination of the modes defined in
7178  * File::Constants (+File::RDONLY+, +File::WRONLY | File::CREAT+). See the
7179  * open(2) man page for more information.
7180  *
7181  * When +mode+ is a string it must be in one of the following forms:
7182  *
7183  * fmode
7184  * fmode ":" ext_enc
7185  * fmode ":" ext_enc ":" int_enc
7186  * fmode ":" "BOM|UTF-*"
7187  *
7188  * +fmode+ is an IO open mode string, +ext_enc+ is the external encoding for
7189  * the IO and +int_enc+ is the internal encoding.
7190  *
7191  * ==== IO Open Mode
7192  *
7193  * Ruby allows the following open modes:
7194  *
7195  * "r" Read-only, starts at beginning of file (default mode).
7196  *
7197  * "r+" Read-write, starts at beginning of file.
7198  *
7199  * "w" Write-only, truncates existing file
7200  * to zero length or creates a new file for writing.
7201  *
7202  * "w+" Read-write, truncates existing file to zero length
7203  * or creates a new file for reading and writing.
7204  *
7205  * "a" Write-only, starts at end of file if file exists,
7206  * otherwise creates a new file for writing.
7207  *
7208  * "a+" Read-write, starts at end of file if file exists,
7209  * otherwise creates a new file for reading and
7210  * writing.
7211  *
7212  * The following modes must be used separately, and along with one or more of
7213  * the modes seen above.
7214  *
7215  * "b" Binary file mode
7216  * Suppresses EOL <-> CRLF conversion on Windows. And
7217  * sets external encoding to ASCII-8BIT unless explicitly
7218  * specified.
7219  *
7220  * "t" Text file mode
7221  *
7222  * When the open mode of original IO is read only, the mode cannot be
7223  * changed to be writable. Similarly, the open mode cannot be changed from
7224  * write only to readable.
7225  *
7226  * When such a change is attempted the error is raised in different locations
7227  * according to the platform.
7228  *
7229  * === IO Encoding
7230  *
7231  * When +ext_enc+ is specified, strings read will be tagged by the encoding
7232  * when reading, and strings output will be converted to the specified
7233  * encoding when writing.
7234  *
7235  * When +ext_enc+ and +int_enc+ are specified read strings will be converted
7236  * from +ext_enc+ to +int_enc+ upon input, and written strings will be
7237  * converted from +int_enc+ to +ext_enc+ upon output. See Encoding for
7238  * further details of transcoding on input and output.
7239  *
7240  * If "BOM|UTF-8", "BOM|UTF-16LE" or "BOM|UTF16-BE" are used, ruby checks for
7241  * a Unicode BOM in the input document to help determine the encoding. For
7242  * UTF-16 encodings the file open mode must be binary. When present, the BOM
7243  * is stripped and the external encoding from the BOM is used. When the BOM
7244  * is missing the given Unicode encoding is used as +ext_enc+. (The BOM-set
7245  * encoding option is case insensitive, so "bom|utf-8" is also valid.)
7246  *
7247  * === Options
7248  *
7249  * +opt+ can be used instead of +mode+ for improved readability. The
7250  * following keys are supported:
7251  *
7252  * :mode ::
7253  * Same as +mode+ parameter
7254  *
7255  * :\external_encoding ::
7256  * External encoding for the IO. "-" is a synonym for the default external
7257  * encoding.
7258  *
7259  * :\internal_encoding ::
7260  * Internal encoding for the IO. "-" is a synonym for the default internal
7261  * encoding.
7262  *
7263  * If the value is nil no conversion occurs.
7264  *
7265  * :encoding ::
7266  * Specifies external and internal encodings as "extern:intern".
7267  *
7268  * :textmode ::
7269  * If the value is truth value, same as "t" in argument +mode+.
7270  *
7271  * :binmode ::
7272  * If the value is truth value, same as "b" in argument +mode+.
7273  *
7274  * :autoclose ::
7275  * If the value is +false+, the +fd+ will be kept open after this IO
7276  * instance gets finalized.
7277  *
7278  * Also, +opt+ can have same keys in String#encode for controlling conversion
7279  * between the external encoding and the internal encoding.
7280  *
7281  * === Example 1
7282  *
7283  * fd = IO.sysopen("/dev/tty", "w")
7284  * a = IO.new(fd,"w")
7285  * $stderr.puts "Hello"
7286  * a.puts "World"
7287  *
7288  * Produces:
7289  *
7290  * Hello
7291  * World
7292  *
7293  * === Example 2
7294  *
7295  * require 'fcntl'
7296  *
7297  * fd = STDERR.fcntl(Fcntl::F_DUPFD)
7298  * io = IO.new(fd, mode: 'w:UTF-16LE', cr_newline: true)
7299  * io.puts "Hello, World!"
7300  *
7301  * fd = STDERR.fcntl(Fcntl::F_DUPFD)
7302  * io = IO.new(fd, mode: 'w', cr_newline: true,
7303  * external_encoding: Encoding::UTF_16LE)
7304  * io.puts "Hello, World!"
7305  *
7306  * Both of above print "Hello, World!" in UTF-16LE to standard error output
7307  * with converting EOL generated by <code>puts</code> to CR.
7308  */
7309 
7310 static VALUE
7312 {
7313  VALUE fnum, vmode;
7314  rb_io_t *fp;
7315  int fd, fmode, oflags = O_RDONLY;
7316  convconfig_t convconfig;
7317  VALUE opt;
7318 #if defined(HAVE_FCNTL) && defined(F_GETFL)
7319  int ofmode;
7320 #else
7321  struct stat st;
7322 #endif
7323 
7324  rb_secure(4);
7325 
7326  argc = rb_scan_args(argc, argv, "11:", &fnum, &vmode, &opt);
7327  rb_io_extract_modeenc(&vmode, 0, opt, &oflags, &fmode, &convconfig);
7328 
7329  fd = NUM2INT(fnum);
7330  if (rb_reserved_fd_p(fd)) {
7331  rb_raise(rb_eArgError, "The given fd is not accessible because RubyVM reserves it");
7332  }
7333 #if defined(HAVE_FCNTL) && defined(F_GETFL)
7334  oflags = fcntl(fd, F_GETFL);
7335  if (oflags == -1) rb_sys_fail(0);
7336 #else
7337  if (fstat(fd, &st) == -1) rb_sys_fail(0);
7338 #endif
7339  rb_update_max_fd(fd);
7340 #if defined(HAVE_FCNTL) && defined(F_GETFL)
7341  ofmode = rb_io_oflags_fmode(oflags);
7342  if (NIL_P(vmode)) {
7343  fmode = ofmode;
7344  }
7345  else if ((~ofmode & fmode) & FMODE_READWRITE) {
7346  VALUE error = INT2FIX(EINVAL);
7348  }
7349 #endif
7350  if (!NIL_P(opt) && rb_hash_aref(opt, sym_autoclose) == Qfalse) {
7351  fmode |= FMODE_PREP;
7352  }
7353  MakeOpenFile(io, fp);
7354  fp->fd = fd;
7355  fp->mode = fmode;
7356  fp->encs = convconfig;
7357  clear_codeconv(fp);
7358  io_check_tty(fp);
7359  if (fileno(stdin) == fd)
7360  fp->stdio_file = stdin;
7361  else if (fileno(stdout) == fd)
7362  fp->stdio_file = stdout;
7363  else if (fileno(stderr) == fd)
7364  fp->stdio_file = stderr;
7365 
7367  return io;
7368 }
7369 
7370 /*
7371  * call-seq:
7372  * File.new(filename, mode="r" [, opt]) -> file
7373  * File.new(filename [, mode [, perm]] [, opt]) -> file
7374  *
7375  * Opens the file named by +filename+ according to the given +mode+ and
7376  * returns a new File object.
7377  *
7378  * See IO.new for a description of +mode+ and +opt+.
7379  *
7380  * If a file is being created, permission bits may be given in +perm+. These
7381  * mode and permission bits are platform dependent; on Unix systems, see
7382  * open(2) and chmod(2) man pages for details.
7383  *
7384  * === Examples
7385  *
7386  * f = File.new("testfile", "r")
7387  * f = File.new("newfile", "w+")
7388  * f = File.new("newfile", File::CREAT|File::TRUNC|File::RDWR, 0644)
7389  */
7390 
7391 static VALUE
7393 {
7394  if (RFILE(io)->fptr) {
7395  rb_raise(rb_eRuntimeError, "reinitializing File");
7396  }
7397  if (0 < argc && argc < 3) {
7398  VALUE fd = rb_check_convert_type(argv[0], T_FIXNUM, "Fixnum", "to_int");
7399 
7400  if (!NIL_P(fd)) {
7401  argv[0] = fd;
7402  return rb_io_initialize(argc, argv, io);
7403  }
7404  }
7405  rb_open_file(argc, argv, io);
7406 
7407  return io;
7408 }
7409 
7410 /* :nodoc: */
7411 static VALUE
7413 {
7414  if (rb_block_given_p()) {
7415  const char *cname = rb_class2name(klass);
7416 
7417  rb_warn("%s::new() does not take block; use %s::open() instead",
7418  cname, cname);
7419  }
7420  return rb_class_new_instance(argc, argv, klass);
7421 }
7422 
7423 
7424 /*
7425  * call-seq:
7426  * IO.for_fd(fd, mode [, opt]) -> io
7427  *
7428  * Synonym for <code>IO.new</code>.
7429  *
7430  */
7431 
7432 static VALUE
7434 {
7435  VALUE io = rb_obj_alloc(klass);
7436  rb_io_initialize(argc, argv, io);
7437  return io;
7438 }
7439 
7440 /*
7441  * call-seq:
7442  * ios.autoclose? -> true or false
7443  *
7444  * Returns +true+ if the underlying file descriptor of _ios_ will be
7445  * closed automatically at its finalization, otherwise +false+.
7446  */
7447 
7448 static VALUE
7450 {
7451  rb_io_t *fptr;
7452  rb_secure(4);
7453  GetOpenFile(io, fptr);
7454  return (fptr->mode & FMODE_PREP) ? Qfalse : Qtrue;
7455 }
7456 
7457 /*
7458  * call-seq:
7459  * io.autoclose = bool -> true or false
7460  *
7461  * Sets auto-close flag.
7462  *
7463  * f = open("/dev/null")
7464  * IO.for_fd(f.fileno)
7465  * # ...
7466  * f.gets # may cause IOError
7467  *
7468  * f = open("/dev/null")
7469  * IO.for_fd(f.fileno).autoclose = true
7470  * # ...
7471  * f.gets # won't cause IOError
7472  */
7473 
7474 static VALUE
7476 {
7477  rb_io_t *fptr;
7478  rb_secure(4);
7479  GetOpenFile(io, fptr);
7480  if (!RTEST(autoclose))
7481  fptr->mode |= FMODE_PREP;
7482  else
7483  fptr->mode &= ~FMODE_PREP;
7484  return io;
7485 }
7486 
7487 static void
7488 argf_mark(void *ptr)
7489 {
7490  struct argf *p = ptr;
7491  rb_gc_mark(p->filename);
7493  rb_gc_mark(p->argv);
7494  rb_gc_mark(p->encs.ecopts);
7495 }
7496 
7497 static void
7498 argf_free(void *ptr)
7499 {
7500  struct argf *p = ptr;
7501  xfree(p->inplace);
7502  xfree(p);
7503 }
7504 
7505 static size_t
7506 argf_memsize(const void *ptr)
7507 {
7508  const struct argf *p = ptr;
7509  size_t size = sizeof(*p);
7510  if (!ptr) return 0;
7511  if (p->inplace) size += strlen(p->inplace) + 1;
7512  return size;
7513 }
7514 
7515 static const rb_data_type_t argf_type = {
7516  "ARGF",
7518 };
7519 
7520 static inline void
7521 argf_init(struct argf *p, VALUE v)
7522 {
7523  p->filename = Qnil;
7524  p->current_file = Qnil;
7525  p->lineno = 0;
7526  p->argv = v;
7527 }
7528 
7529 static VALUE
7531 {
7532  struct argf *p;
7533  VALUE argf = TypedData_Make_Struct(klass, struct argf, &argf_type, p);
7534 
7535  argf_init(p, Qnil);
7536  return argf;
7537 }
7538 
7539 #undef rb_argv
7540 
7541 /* :nodoc: */
7542 static VALUE
7544 {
7545  memset(&ARGF, 0, sizeof(ARGF));
7546  argf_init(&ARGF, argv);
7547 
7548  return argf;
7549 }
7550 
7551 /* :nodoc: */
7552 static VALUE
7554 {
7555  if (!OBJ_INIT_COPY(argf, orig)) return argf;
7556  ARGF = argf_of(orig);
7557  ARGF.argv = rb_obj_dup(ARGF.argv);
7558  if (ARGF.inplace) {
7559  const char *inplace = ARGF.inplace;
7560  ARGF.inplace = 0;
7561  ARGF.inplace = ruby_strdup(inplace);
7562  }
7563  return argf;
7564 }
7565 
7566 /*
7567  * call-seq:
7568  * ARGF.lineno = integer -> integer
7569  *
7570  * Sets the line number of +ARGF+ as a whole to the given +Integer+.
7571  *
7572  * +ARGF+ sets the line number automatically as you read data, so normally
7573  * you will not need to set it explicitly. To access the current line number
7574  * use +ARGF.lineno+.
7575  *
7576  * For example:
7577  *
7578  * ARGF.lineno #=> 0
7579  * ARGF.readline #=> "This is line 1\n"
7580  * ARGF.lineno #=> 1
7581  * ARGF.lineno = 0 #=> 0
7582  * ARGF.lineno #=> 0
7583  */
7584 static VALUE
7586 {
7587  ARGF.lineno = NUM2INT(val);
7588  ARGF.last_lineno = ARGF.lineno;
7589  return Qnil;
7590 }
7591 
7592 /*
7593  * call-seq:
7594  * ARGF.lineno -> integer
7595  *
7596  * Returns the current line number of ARGF as a whole. This value
7597  * can be set manually with +ARGF.lineno=+.
7598  *
7599  * For example:
7600  *
7601  * ARGF.lineno #=> 0
7602  * ARGF.readline #=> "This is line 1\n"
7603  * ARGF.lineno #=> 1
7604  */
7605 static VALUE
7607 {
7608  return INT2FIX(ARGF.lineno);
7609 }
7610 
7611 static VALUE
7613 {
7614  return rb_funcall3(ARGF.current_file, rb_frame_this_func(), argc, argv);
7615 }
7616 
7617 #define next_argv() argf_next_argv(argf)
7618 #define ARGF_GENERIC_INPUT_P() \
7619  (ARGF.current_file == rb_stdin && !RB_TYPE_P(ARGF.current_file, T_FILE))
7620 #define ARGF_FORWARD(argc, argv) do {\
7621  if (ARGF_GENERIC_INPUT_P())\
7622  return argf_forward((argc), (argv), argf);\
7623 } while (0)
7624 #define NEXT_ARGF_FORWARD(argc, argv) do {\
7625  if (!next_argv()) return Qnil;\
7626  ARGF_FORWARD((argc), (argv));\
7627 } while (0)
7628 
7629 static void
7631 {
7632  if (file == rb_stdin) return;
7633  if (RB_TYPE_P(file, T_FILE)) {
7634  rb_io_set_write_io(file, Qnil);
7635  }
7636  rb_funcall3(file, rb_intern("close"), 0, 0);
7637 }
7638 
7639 static int
7641 {
7642  char *fn;
7643  rb_io_t *fptr;
7644  int stdout_binmode = 0;
7645  int fmode;
7646 
7647  if (RB_TYPE_P(rb_stdout, T_FILE)) {
7648  GetOpenFile(rb_stdout, fptr);
7649  if (fptr->mode & FMODE_BINMODE)
7650  stdout_binmode = 1;
7651  }
7652 
7653  if (ARGF.init_p == 0) {
7654  if (!NIL_P(ARGF.argv) && RARRAY_LEN(ARGF.argv) > 0) {
7655  ARGF.next_p = 1;
7656  }
7657  else {
7658  ARGF.next_p = -1;
7659  }
7660  ARGF.init_p = 1;
7661  }
7662  else {
7663  if (NIL_P(ARGF.argv)) {
7664  ARGF.next_p = -1;
7665  }
7666  else if (ARGF.next_p == -1 && RARRAY_LEN(ARGF.argv) > 0) {
7667  ARGF.next_p = 1;
7668  }
7669  }
7670 
7671  if (ARGF.next_p == 1) {
7672  retry:
7673  if (RARRAY_LEN(ARGF.argv) > 0) {
7674  ARGF.filename = rb_ary_shift(ARGF.argv);
7675  fn = StringValueCStr(ARGF.filename);
7676  if (strlen(fn) == 1 && fn[0] == '-') {
7677  ARGF.current_file = rb_stdin;
7678  if (ARGF.inplace) {
7679  rb_warn("Can't do inplace edit for stdio; skipping");
7680  goto retry;
7681  }
7682  }
7683  else {
7684  VALUE write_io = Qnil;
7685  int fr = rb_sysopen(ARGF.filename, O_RDONLY, 0);
7686 
7687  if (ARGF.inplace) {
7688  struct stat st;
7689 #ifndef NO_SAFE_RENAME
7690  struct stat st2;
7691 #endif
7692  VALUE str;
7693  int fw;
7694 
7697  }
7698  fstat(fr, &st);
7699  if (*ARGF.inplace) {
7700  str = rb_str_new2(fn);
7701  rb_str_cat2(str, ARGF.inplace);
7702 #ifdef NO_SAFE_RENAME
7703  (void)close(fr);
7704  (void)unlink(RSTRING_PTR(str));
7705  if (rename(fn, RSTRING_PTR(str)) < 0) {
7706  rb_warn("Can't rename %s to %s: %s, skipping file",
7707  fn, RSTRING_PTR(str), strerror(errno));
7708  goto retry;
7709  }
7710  fr = rb_sysopen(str, O_RDONLY, 0);
7711 #else
7712  if (rename(fn, RSTRING_PTR(str)) < 0) {
7713  rb_warn("Can't rename %s to %s: %s, skipping file",
7714  fn, RSTRING_PTR(str), strerror(errno));
7715  close(fr);
7716  goto retry;
7717  }
7718 #endif
7719  }
7720  else {
7721 #ifdef NO_SAFE_RENAME
7722  rb_fatal("Can't do inplace edit without backup");
7723 #else
7724  if (unlink(fn) < 0) {
7725  rb_warn("Can't remove %s: %s, skipping file",
7726  fn, strerror(errno));
7727  close(fr);
7728  goto retry;
7729  }
7730 #endif
7731  }
7732  fw = rb_sysopen(ARGF.filename, O_WRONLY|O_CREAT|O_TRUNC, 0666);
7733 #ifndef NO_SAFE_RENAME
7734  fstat(fw, &st2);
7735 #ifdef HAVE_FCHMOD
7736  fchmod(fw, st.st_mode);
7737 #else
7738  chmod(fn, st.st_mode);
7739 #endif
7740  if (st.st_uid!=st2.st_uid || st.st_gid!=st2.st_gid) {
7741  int err;
7742 #ifdef HAVE_FCHOWN
7743  err = fchown(fw, st.st_uid, st.st_gid);
7744 #else
7745  err = chown(fn, st.st_uid, st.st_gid);
7746 #endif
7747  if (err && getuid() == 0 && st2.st_uid == 0) {
7748  const char *wkfn = RSTRING_PTR(ARGF.filename);
7749  rb_warn("Can't set owner/group of %s to same as %s: %s, skipping file",
7750  wkfn, fn, strerror(errno));
7751  (void)close(fr);
7752  (void)close(fw);
7753  (void)unlink(wkfn);
7754  goto retry;
7755  }
7756  }
7757 #endif
7758  write_io = prep_io(fw, FMODE_WRITABLE, rb_cFile, fn);
7759  rb_stdout = write_io;
7760  if (stdout_binmode) rb_io_binmode(rb_stdout);
7761  }
7762  fmode = FMODE_READABLE;
7763  if (!ARGF.binmode) {
7764  fmode |= DEFAULT_TEXTMODE;
7765  }
7766  ARGF.current_file = prep_io(fr, fmode, rb_cFile, fn);
7767  if (!NIL_P(write_io)) {
7768  rb_io_set_write_io(ARGF.current_file, write_io);
7769  }
7770  }
7771  if (ARGF.binmode) rb_io_ascii8bit_binmode(ARGF.current_file);
7772  GetOpenFile(ARGF.current_file, fptr);
7773  if (ARGF.encs.enc) {
7774  fptr->encs = ARGF.encs;
7775  clear_codeconv(fptr);
7776  }
7777  else {
7779  if (!ARGF.binmode) {
7781 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
7782  fptr->encs.ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
7783 #endif
7784  }
7785  }
7786  ARGF.next_p = 0;
7787  }
7788  else {
7789  ARGF.next_p = 1;
7790  return FALSE;
7791  }
7792  }
7793  else if (ARGF.next_p == -1) {
7794  ARGF.current_file = rb_stdin;
7795  ARGF.filename = rb_str_new2("-");
7796  if (ARGF.inplace) {
7797  rb_warn("Can't do inplace edit for stdio");
7799  }
7800  }
7801  return TRUE;
7802 }
7803 
7804 static VALUE
7806 {
7807  VALUE line;
7808  long lineno = ARGF.lineno;
7809 
7810  retry:
7811  if (!next_argv()) return Qnil;
7812  if (ARGF_GENERIC_INPUT_P()) {
7813  line = rb_funcall3(ARGF.current_file, idGets, argc, argv);
7814  }
7815  else {
7816  if (argc == 0 && rb_rs == rb_default_rs) {
7817  line = rb_io_gets(ARGF.current_file);
7818  }
7819  else {
7820  line = rb_io_getline(argc, argv, ARGF.current_file);
7821  }
7822  if (NIL_P(line) && ARGF.next_p != -1) {
7823  argf_close(ARGF.current_file);
7824  ARGF.next_p = 1;
7825  goto retry;
7826  }
7827  }
7828  if (!NIL_P(line)) {
7829  ARGF.lineno = ++lineno;
7830  ARGF.last_lineno = ARGF.lineno;
7831  }
7832  return line;
7833 }
7834 
7835 static VALUE
7837 {
7838  VALUE argf = *var;
7839  return INT2FIX(ARGF.last_lineno);
7840 }
7841 
7842 static void
7844 {
7845  VALUE argf = *var;
7846  int n = NUM2INT(val);
7847  ARGF.last_lineno = ARGF.lineno = n;
7848 }
7849 
7850 static VALUE argf_gets(int, VALUE *, VALUE);
7851 
7852 /*
7853  * call-seq:
7854  * gets(sep=$/) -> string or nil
7855  * gets(limit) -> string or nil
7856  * gets(sep,limit) -> string or nil
7857  *
7858  * Returns (and assigns to <code>$_</code>) the next line from the list
7859  * of files in +ARGV+ (or <code>$*</code>), or from standard input if
7860  * no files are present on the command line. Returns +nil+ at end of
7861  * file. The optional argument specifies the record separator. The
7862  * separator is included with the contents of each record. A separator
7863  * of +nil+ reads the entire contents, and a zero-length separator
7864  * reads the input one paragraph at a time, where paragraphs are
7865  * divided by two consecutive newlines. If the first argument is an
7866  * integer, or optional second argument is given, the returning string
7867  * would not be longer than the given value in bytes. If multiple
7868  * filenames are present in +ARGV+, +gets(nil)+ will read the contents
7869  * one file at a time.
7870  *
7871  * ARGV << "testfile"
7872  * print while gets
7873  *
7874  * <em>produces:</em>
7875  *
7876  * This is line one
7877  * This is line two
7878  * This is line three
7879  * And so on...
7880  *
7881  * The style of programming using <code>$_</code> as an implicit
7882  * parameter is gradually losing favor in the Ruby community.
7883  */
7884 
7885 static VALUE
7887 {
7888  if (recv == argf) {
7889  return argf_gets(argc, argv, argf);
7890  }
7891  return rb_funcall2(argf, idGets, argc, argv);
7892 }
7893 
7894 /*
7895  * call-seq:
7896  * ARGF.gets(sep=$/) -> string
7897  * ARGF.gets(limit) -> string
7898  * ARGF.gets(sep, limit) -> string
7899  *
7900  * Returns the next line from the current file in +ARGF+.
7901  *
7902  * By default lines are assumed to be separated by +$/+; to use a different
7903  * character as a separator, supply it as a +String+ for the _sep_ argument.
7904  *
7905  * The optional _limit_ argument specifies how many characters of each line
7906  * to return. By default all characters are returned.
7907  *
7908  */
7909 static VALUE
7911 {
7912  VALUE line;
7913 
7914  line = argf_getline(argc, argv, argf);
7915  rb_lastline_set(line);
7916 
7917  return line;
7918 }
7919 
7920 VALUE
7921 rb_gets(void)
7922 {
7923  VALUE line;
7924 
7925  if (rb_rs != rb_default_rs) {
7926  return rb_f_gets(0, 0, argf);
7927  }
7928 
7929  retry:
7930  if (!next_argv()) return Qnil;
7931  line = rb_io_gets(ARGF.current_file);
7932  if (NIL_P(line) && ARGF.next_p != -1) {
7933  rb_io_close(ARGF.current_file);
7934  ARGF.next_p = 1;
7935  goto retry;
7936  }
7937  rb_lastline_set(line);
7938  if (!NIL_P(line)) {
7939  ARGF.lineno++;
7940  ARGF.last_lineno = ARGF.lineno;
7941  }
7942 
7943  return line;
7944 }
7945 
7946 static VALUE argf_readline(int, VALUE *, VALUE);
7947 
7948 /*
7949  * call-seq:
7950  * readline(sep=$/) -> string
7951  * readline(limit) -> string
7952  * readline(sep, limit) -> string
7953  *
7954  * Equivalent to <code>Kernel::gets</code>, except
7955  * +readline+ raises +EOFError+ at end of file.
7956  */
7957 
7958 static VALUE
7960 {
7961  if (recv == argf) {
7962  return argf_readline(argc, argv, argf);
7963  }
7964  return rb_funcall2(argf, rb_intern("readline"), argc, argv);
7965 }
7966 
7967 
7968 /*
7969  * call-seq:
7970  * ARGF.readline(sep=$/) -> string
7971  * ARGF.readline(limit) -> string
7972  * ARGF.readline(sep, limit) -> string
7973  *
7974  * Returns the next line from the current file in +ARGF+.
7975  *
7976  * By default lines are assumed to be separated by +$/+; to use a different
7977  * character as a separator, supply it as a +String+ for the _sep_ argument.
7978  *
7979  * The optional _limit_ argument specifies how many characters of each line
7980  * to return. By default all characters are returned.
7981  *
7982  * An +EOFError+ is raised at the end of the file.
7983  */
7984 static VALUE
7986 {
7987  VALUE line;
7988 
7989  if (!next_argv()) rb_eof_error();
7990  ARGF_FORWARD(argc, argv);
7991  line = argf_gets(argc, argv, argf);
7992  if (NIL_P(line)) {
7993  rb_eof_error();
7994  }
7995 
7996  return line;
7997 }
7998 
7999 static VALUE argf_readlines(int, VALUE *, VALUE);
8000 
8001 /*
8002  * call-seq:
8003  * readlines(sep=$/) -> array
8004  * readlines(limit) -> array
8005  * readlines(sep,limit) -> array
8006  *
8007  * Returns an array containing the lines returned by calling
8008  * <code>Kernel.gets(<i>sep</i>)</code> until the end of file.
8009  */
8010 
8011 static VALUE
8013 {
8014  if (recv == argf) {
8015  return argf_readlines(argc, argv, argf);
8016  }
8017  return rb_funcall2(argf, rb_intern("readlines"), argc, argv);
8018 }
8019 
8020 /*
8021  * call-seq:
8022  * ARGF.readlines(sep=$/) -> array
8023  * ARGF.readlines(limit) -> array
8024  * ARGF.readlines(sep, limit) -> array
8025  *
8026  * ARGF.to_a(sep=$/) -> array
8027  * ARGF.to_a(limit) -> array
8028  * ARGF.to_a(sep, limit) -> array
8029  *
8030  * Reads +ARGF+'s current file in its entirety, returning an +Array+ of its
8031  * lines, one line per element. Lines are assumed to be separated by _sep_.
8032  *
8033  * lines = ARGF.readlines
8034  * lines[0] #=> "This is line one\n"
8035  */
8036 static VALUE
8038 {
8039  long lineno = ARGF.lineno;
8040  VALUE lines, ary;
8041 
8042  ary = rb_ary_new();
8043  while (next_argv()) {
8044  if (ARGF_GENERIC_INPUT_P()) {
8045  lines = rb_funcall3(ARGF.current_file, rb_intern("readlines"), argc, argv);
8046  }
8047  else {
8048  lines = rb_io_readlines(argc, argv, ARGF.current_file);
8049  argf_close(ARGF.current_file);
8050  }
8051  ARGF.next_p = 1;
8052  rb_ary_concat(ary, lines);
8053  ARGF.lineno = lineno + RARRAY_LEN(ary);
8054  ARGF.last_lineno = ARGF.lineno;
8055  }
8056  ARGF.init_p = 0;
8057  return ary;
8058 }
8059 
8060 /*
8061  * call-seq:
8062  * `cmd` -> string
8063  *
8064  * Returns the standard output of running _cmd_ in a subshell.
8065  * The built-in syntax <code>%x{...}</code> uses
8066  * this method. Sets <code>$?</code> to the process status.
8067  *
8068  * `date` #=> "Wed Apr 9 08:56:30 CDT 2003\n"
8069  * `ls testdir`.split[1] #=> "main.rb"
8070  * `echo oops && exit 99` #=> "oops\n"
8071  * $?.exitstatus #=> 99
8072  */
8073 
8074 static VALUE
8076 {
8077  volatile VALUE port;
8078  VALUE result;
8079  rb_io_t *fptr;
8080 
8081  SafeStringValue(str);
8083  port = pipe_open_s(str, "r", FMODE_READABLE|DEFAULT_TEXTMODE, NULL);
8084  if (NIL_P(port)) return rb_str_new(0,0);
8085 
8086  GetOpenFile(port, fptr);
8087  result = read_all(fptr, remain_size(fptr), Qnil);
8088  rb_io_close(port);
8089 
8090  return result;
8091 }
8092 
8093 #ifdef HAVE_SYS_SELECT_H
8094 #include <sys/select.h>
8095 #endif
8096 
8097 static VALUE
8098 select_internal(VALUE read, VALUE write, VALUE except, struct timeval *tp, rb_fdset_t *fds)
8099 {
8100  VALUE res, list;
8101  rb_fdset_t *rp, *wp, *ep;
8102  rb_io_t *fptr;
8103  long i;
8104  int max = 0, n;
8105  int pending = 0;
8106  struct timeval timerec;
8107 
8108  if (!NIL_P(read)) {
8109  Check_Type(read, T_ARRAY);
8110  for (i=0; i<RARRAY_LEN(read); i++) {
8111  GetOpenFile(rb_io_get_io(RARRAY_PTR(read)[i]), fptr);
8112  rb_fd_set(fptr->fd, &fds[0]);
8113  if (READ_DATA_PENDING(fptr) || READ_CHAR_PENDING(fptr)) { /* check for buffered data */
8114  pending++;
8115  rb_fd_set(fptr->fd, &fds[3]);
8116  }
8117  if (max < fptr->fd) max = fptr->fd;
8118  }
8119  if (pending) { /* no blocking if there's buffered data */
8120  timerec.tv_sec = timerec.tv_usec = 0;
8121  tp = &timerec;
8122  }
8123  rp = &fds[0];
8124  }
8125  else
8126  rp = 0;
8127 
8128  if (!NIL_P(write)) {
8129  Check_Type(write, T_ARRAY);
8130  for (i=0; i<RARRAY_LEN(write); i++) {
8131  VALUE write_io = GetWriteIO(rb_io_get_io(RARRAY_PTR(write)[i]));
8132  GetOpenFile(write_io, fptr);
8133  rb_fd_set(fptr->fd, &fds[1]);
8134  if (max < fptr->fd) max = fptr->fd;
8135  }
8136  wp = &fds[1];
8137  }
8138  else
8139  wp = 0;
8140 
8141  if (!NIL_P(except)) {
8142  Check_Type(except, T_ARRAY);
8143  for (i=0; i<RARRAY_LEN(except); i++) {
8144  VALUE io = rb_io_get_io(RARRAY_PTR(except)[i]);
8145  VALUE write_io = GetWriteIO(io);
8146  GetOpenFile(io, fptr);
8147  rb_fd_set(fptr->fd, &fds[2]);
8148  if (max < fptr->fd) max = fptr->fd;
8149  if (io != write_io) {
8150  GetOpenFile(write_io, fptr);
8151  rb_fd_set(fptr->fd, &fds[2]);
8152  if (max < fptr->fd) max = fptr->fd;
8153  }
8154  }
8155  ep = &fds[2];
8156  }
8157  else {
8158  ep = 0;
8159  }
8160 
8161  max++;
8162 
8163  n = rb_thread_fd_select(max, rp, wp, ep, tp);
8164  if (n < 0) {
8165  rb_sys_fail(0);
8166  }
8167  if (!pending && n == 0) return Qnil; /* returns nil on timeout */
8168 
8169  res = rb_ary_new2(3);
8170  rb_ary_push(res, rp?rb_ary_new():rb_ary_new2(0));
8171  rb_ary_push(res, wp?rb_ary_new():rb_ary_new2(0));
8172  rb_ary_push(res, ep?rb_ary_new():rb_ary_new2(0));
8173 
8174  if (rp) {
8175  list = RARRAY_PTR(res)[0];
8176  for (i=0; i< RARRAY_LEN(read); i++) {
8177  VALUE obj = rb_ary_entry(read, i);
8178  VALUE io = rb_io_get_io(obj);
8179  GetOpenFile(io, fptr);
8180  if (rb_fd_isset(fptr->fd, &fds[0]) ||
8181  rb_fd_isset(fptr->fd, &fds[3])) {
8182  rb_ary_push(list, obj);
8183  }
8184  }
8185  }
8186 
8187  if (wp) {
8188  list = RARRAY_PTR(res)[1];
8189  for (i=0; i< RARRAY_LEN(write); i++) {
8190  VALUE obj = rb_ary_entry(write, i);
8191  VALUE io = rb_io_get_io(obj);
8192  VALUE write_io = GetWriteIO(io);
8193  GetOpenFile(write_io, fptr);
8194  if (rb_fd_isset(fptr->fd, &fds[1])) {
8195  rb_ary_push(list, obj);
8196  }
8197  }
8198  }
8199 
8200  if (ep) {
8201  list = RARRAY_PTR(res)[2];
8202  for (i=0; i< RARRAY_LEN(except); i++) {
8203  VALUE obj = rb_ary_entry(except, i);
8204  VALUE io = rb_io_get_io(obj);
8205  VALUE write_io = GetWriteIO(io);
8206  GetOpenFile(io, fptr);
8207  if (rb_fd_isset(fptr->fd, &fds[2])) {
8208  rb_ary_push(list, obj);
8209  }
8210  else if (io != write_io) {
8211  GetOpenFile(write_io, fptr);
8212  if (rb_fd_isset(fptr->fd, &fds[2])) {
8213  rb_ary_push(list, obj);
8214  }
8215  }
8216  }
8217  }
8218 
8219  return res; /* returns an empty array on interrupt */
8220 }
8221 
8222 struct select_args {
8224  struct timeval *timeout;
8226 };
8227 
8228 static VALUE
8230 {
8231  struct select_args *p = (struct select_args *)arg;
8232 
8233  return select_internal(p->read, p->write, p->except, p->timeout, p->fdsets);
8234 }
8235 
8236 static VALUE
8238 {
8239  struct select_args *p = (struct select_args *)arg;
8240  int i;
8241 
8242  for (i = 0; i < numberof(p->fdsets); ++i)
8243  rb_fd_term(&p->fdsets[i]);
8244  return Qnil;
8245 }
8246 
8249 
8250 #ifdef HAVE_POSIX_FADVISE
8251 struct io_advise_struct {
8252  int fd;
8253  off_t offset;
8254  off_t len;
8255  int advice;
8256 };
8257 
8258 static VALUE
8259 io_advise_internal(void *arg)
8260 {
8261  struct io_advise_struct *ptr = arg;
8262  return posix_fadvise(ptr->fd, ptr->offset, ptr->len, ptr->advice);
8263 }
8264 
8265 static VALUE
8266 io_advise_sym_to_const(VALUE sym)
8267 {
8268 #ifdef POSIX_FADV_NORMAL
8269  if (sym == sym_normal)
8270  return INT2NUM(POSIX_FADV_NORMAL);
8271 #endif
8272 
8273 #ifdef POSIX_FADV_RANDOM
8274  if (sym == sym_random)
8275  return INT2NUM(POSIX_FADV_RANDOM);
8276 #endif
8277 
8278 #ifdef POSIX_FADV_SEQUENTIAL
8279  if (sym == sym_sequential)
8280  return INT2NUM(POSIX_FADV_SEQUENTIAL);
8281 #endif
8282 
8283 #ifdef POSIX_FADV_WILLNEED
8284  if (sym == sym_willneed)
8285  return INT2NUM(POSIX_FADV_WILLNEED);
8286 #endif
8287 
8288 #ifdef POSIX_FADV_DONTNEED
8289  if (sym == sym_dontneed)
8290  return INT2NUM(POSIX_FADV_DONTNEED);
8291 #endif
8292 
8293 #ifdef POSIX_FADV_NOREUSE
8294  if (sym == sym_noreuse)
8295  return INT2NUM(POSIX_FADV_NOREUSE);
8296 #endif
8297 
8298  return Qnil;
8299 }
8300 
8301 static VALUE
8302 do_io_advise(rb_io_t *fptr, VALUE advice, off_t offset, off_t len)
8303 {
8304  int rv;
8305  struct io_advise_struct ias;
8306  VALUE num_adv;
8307 
8308  num_adv = io_advise_sym_to_const(advice);
8309 
8310  /*
8311  * The platform doesn't support this hint. We don't raise exception, instead
8312  * silently ignore it. Because IO::advise is only hint.
8313  */
8314  if (NIL_P(num_adv))
8315  return Qnil;
8316 
8317  ias.fd = fptr->fd;
8318  ias.advice = NUM2INT(num_adv);
8319  ias.offset = offset;
8320  ias.len = len;
8321 
8322  rv = (int)rb_thread_io_blocking_region(io_advise_internal, &ias, fptr->fd);
8323  if (rv) {
8324  /* posix_fadvise(2) doesn't set errno. On success it returns 0; otherwise
8325  it returns the error code. */
8326  rb_syserr_fail_str(rv, fptr->pathv);
8327  }
8328 
8329  return Qnil;
8330 }
8331 
8332 #endif /* HAVE_POSIX_FADVISE */
8333 
8334 static void
8336 {
8337  if (!SYMBOL_P(advice))
8338  rb_raise(rb_eTypeError, "advice must be a Symbol");
8339 
8340  if (advice != sym_normal &&
8341  advice != sym_sequential &&
8342  advice != sym_random &&
8343  advice != sym_willneed &&
8344  advice != sym_dontneed &&
8345  advice != sym_noreuse) {
8346  VALUE symname = rb_inspect(advice);
8347  rb_raise(rb_eNotImpError, "Unsupported advice: %s",
8348  StringValuePtr(symname));
8349  }
8350 }
8351 
8352 /*
8353  * call-seq:
8354  * ios.advise(advice, offset=0, len=0) -> nil
8355  *
8356  * Announce an intention to access data from the current file in a
8357  * specific pattern. On platforms that do not support the
8358  * <em>posix_fadvise(2)</em> system call, this method is a no-op.
8359  *
8360  * _advice_ is one of the following symbols:
8361  *
8362  * * :normal - No advice to give; the default assumption for an open file.
8363  * * :sequential - The data will be accessed sequentially:
8364  * with lower offsets read before higher ones.
8365  * * :random - The data will be accessed in random order.
8366  * * :willneed - The data will be accessed in the near future.
8367  * * :dontneed - The data will not be accessed in the near future.
8368  * * :noreuse - The data will only be accessed once.
8369  *
8370  * The semantics of a piece of advice are platform-dependent. See
8371  * <em>man 2 posix_fadvise</em> for details.
8372  *
8373  * "data" means the region of the current file that begins at
8374  * _offset_ and extends for _len_ bytes. If _len_ is 0, the region
8375  * ends at the last byte of the file. By default, both _offset_ and
8376  * _len_ are 0, meaning that the advice applies to the entire file.
8377  *
8378  * If an error occurs, one of the following exceptions will be raised:
8379  *
8380  * * <code>IOError</code> - The <code>IO</code> stream is closed.
8381  * * <code>Errno::EBADF</code> - The file descriptor of the current file is
8382  invalid.
8383  * * <code>Errno::EINVAL</code> - An invalid value for _advice_ was given.
8384  * * <code>Errno::ESPIPE</code> - The file descriptor of the current
8385  * * file refers to a FIFO or pipe. (Linux raises <code>Errno::EINVAL</code>
8386  * * in this case).
8387  * * <code>TypeError</code> - Either _advice_ was not a Symbol, or one of the
8388  other arguments was not an <code>Integer</code>.
8389  * * <code>RangeError</code> - One of the arguments given was too big/small.
8390  *
8391  * This list is not exhaustive; other Errno:: exceptions are also possible.
8392  */
8393 static VALUE
8395 {
8396  VALUE advice, offset, len;
8397  off_t off, l;
8398  rb_io_t *fptr;
8399 
8400  rb_scan_args(argc, argv, "12", &advice, &offset, &len);
8401  advice_arg_check(advice);
8402 
8403  io = GetWriteIO(io);
8404  GetOpenFile(io, fptr);
8405 
8406  off = NIL_P(offset) ? 0 : NUM2OFFT(offset);
8407  l = NIL_P(len) ? 0 : NUM2OFFT(len);
8408 
8409 #ifdef HAVE_POSIX_FADVISE
8410  return do_io_advise(fptr, advice, off, l);
8411 #else
8412  ((void)off, (void)l); /* Ignore all hint */
8413  return Qnil;
8414 #endif
8415 }
8416 
8417 /*
8418  * call-seq:
8419  * IO.select(read_array
8420  * [, write_array
8421  * [, error_array
8422  * [, timeout]]]) -> array or nil
8423  *
8424  * Calls select(2) system call.
8425  * It monitors given arrays of <code>IO</code> objects, waits one or more
8426  * of <code>IO</code> objects ready for reading, are ready for writing,
8427  * and have pending exceptions respectably, and returns an array that
8428  * contains arrays of those IO objects. It will return <code>nil</code>
8429  * if optional <i>timeout</i> value is given and no <code>IO</code> object
8430  * is ready in <i>timeout</i> seconds.
8431  *
8432  * === Parameters
8433  * read_array:: an array of <code>IO</code> objects that wait until ready for read
8434  * write_array:: an array of <code>IO</code> objects that wait until ready for write
8435  * error_array:: an array of <code>IO</code> objects that wait for exceptions
8436  * timeout:: a numeric value in second
8437  *
8438  * === Example
8439  *
8440  * rp, wp = IO.pipe
8441  * mesg = "ping "
8442  * 100.times {
8443  * rs, ws, = IO.select([rp], [wp])
8444  * if r = rs[0]
8445  * ret = r.read(5)
8446  * print ret
8447  * case ret
8448  * when /ping/
8449  * mesg = "pong\n"
8450  * when /pong/
8451  * mesg = "ping "
8452  * end
8453  * end
8454  * if w = ws[0]
8455  * w.write(mesg)
8456  * end
8457  * }
8458  *
8459  * <em>produces:</em>
8460  *
8461  * ping pong
8462  * ping pong
8463  * ping pong
8464  * (snipped)
8465  * ping
8466  */
8467 
8468 static VALUE
8470 {
8471  VALUE timeout;
8472  struct select_args args;
8473  struct timeval timerec;
8474  int i;
8475 
8476  rb_scan_args(argc, argv, "13", &args.read, &args.write, &args.except, &timeout);
8477  if (NIL_P(timeout)) {
8478  args.timeout = 0;
8479  }
8480  else {
8481  timerec = rb_time_interval(timeout);
8482  args.timeout = &timerec;
8483  }
8484 
8485  for (i = 0; i < numberof(args.fdsets); ++i)
8486  rb_fd_init(&args.fdsets[i]);
8487 
8488  return rb_ensure(select_call, (VALUE)&args, select_end, (VALUE)&args);
8489 }
8490 
8491 #if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
8492  typedef unsigned long ioctl_req_t;
8493 # define NUM2IOCTLREQ(num) NUM2ULONG(num)
8494 #else
8495  typedef int ioctl_req_t;
8496 # define NUM2IOCTLREQ(num) NUM2INT(num)
8497 #endif
8498 
8499 struct ioctl_arg {
8500  int fd;
8501  ioctl_req_t cmd;
8502  long narg;
8503 };
8504 
8505 static VALUE
8506 nogvl_ioctl(void *ptr)
8507 {
8508  struct ioctl_arg *arg = ptr;
8509 
8510  return (VALUE)ioctl(arg->fd, arg->cmd, arg->narg);
8511 }
8512 
8513 static int
8514 do_ioctl(int fd, ioctl_req_t cmd, long narg)
8515 {
8516  int retval;
8517  struct ioctl_arg arg;
8518 
8519  arg.fd = fd;
8520  arg.cmd = cmd;
8521  arg.narg = narg;
8522 
8523  retval = (int)rb_thread_io_blocking_region(nogvl_ioctl, &arg, fd);
8524 
8525  return retval;
8526 }
8527 
8528 #define DEFULT_IOCTL_NARG_LEN (256)
8529 
8530 #ifdef __linux__
8531 static long
8532 linux_iocparm_len(ioctl_req_t cmd)
8533 {
8534  long len;
8535 
8536  if ((cmd & 0xFFFF0000) == 0) {
8537  /* legacy and unstructured ioctl number. */
8538  return DEFULT_IOCTL_NARG_LEN;
8539  }
8540 
8541  len = _IOC_SIZE(cmd);
8542 
8543  /* paranoia check for silly drivers which don't keep ioctl convention */
8544  if (len < DEFULT_IOCTL_NARG_LEN)
8545  len = DEFULT_IOCTL_NARG_LEN;
8546 
8547  return len;
8548 }
8549 #endif
8550 
8551 static long
8552 ioctl_narg_len(ioctl_req_t cmd)
8553 {
8554  long len;
8555 
8556 #ifdef IOCPARM_MASK
8557 #ifndef IOCPARM_LEN
8558 #define IOCPARM_LEN(x) (((x) >> 16) & IOCPARM_MASK)
8559 #endif
8560 #endif
8561 #ifdef IOCPARM_LEN
8562  len = IOCPARM_LEN(cmd); /* on BSDish systems we're safe */
8563 #elif defined(__linux__)
8564  len = linux_iocparm_len(cmd);
8565 #else
8566  /* otherwise guess at what's safe */
8567  len = DEFULT_IOCTL_NARG_LEN;
8568 #endif
8569 
8570  return len;
8571 }
8572 
8573 #ifdef HAVE_FCNTL
8574 #ifdef __linux__
8575 typedef long fcntl_arg_t;
8576 #else
8577 /* posix */
8578 typedef int fcntl_arg_t;
8579 #endif
8580 
8581 static long
8582 fcntl_narg_len(int cmd)
8583 {
8584  long len;
8585 
8586  switch (cmd) {
8587 #ifdef F_DUPFD
8588  case F_DUPFD:
8589  len = sizeof(fcntl_arg_t);
8590  break;
8591 #endif
8592 #ifdef F_DUP2FD /* bsd specific */
8593  case F_DUP2FD:
8594  len = sizeof(int);
8595  break;
8596 #endif
8597 #ifdef F_DUPFD_CLOEXEC /* linux specific */
8598  case F_DUPFD_CLOEXEC:
8599  len = sizeof(fcntl_arg_t);
8600  break;
8601 #endif
8602 #ifdef F_GETFD
8603  case F_GETFD:
8604  len = 1;
8605  break;
8606 #endif
8607 #ifdef F_SETFD
8608  case F_SETFD:
8609  len = sizeof(fcntl_arg_t);
8610  break;
8611 #endif
8612 #ifdef F_GETFL
8613  case F_GETFL:
8614  len = 1;
8615  break;
8616 #endif
8617 #ifdef F_SETFL
8618  case F_SETFL:
8619  len = sizeof(fcntl_arg_t);
8620  break;
8621 #endif
8622 #ifdef F_GETOWN
8623  case F_GETOWN:
8624  len = 1;
8625  break;
8626 #endif
8627 #ifdef F_SETOWN
8628  case F_SETOWN:
8629  len = sizeof(fcntl_arg_t);
8630  break;
8631 #endif
8632 #ifdef F_GETOWN_EX /* linux specific */
8633  case F_GETOWN_EX:
8634  len = sizeof(struct f_owner_ex);
8635  break;
8636 #endif
8637 #ifdef F_SETOWN_EX /* linux specific */
8638  case F_SETOWN_EX:
8639  len = sizeof(struct f_owner_ex);
8640  break;
8641 #endif
8642 #ifdef F_GETLK
8643  case F_GETLK:
8644  len = sizeof(struct flock);
8645  break;
8646 #endif
8647 #ifdef F_SETLK
8648  case F_SETLK:
8649  len = sizeof(struct flock);
8650  break;
8651 #endif
8652 #ifdef F_SETLKW
8653  case F_SETLKW:
8654  len = sizeof(struct flock);
8655  break;
8656 #endif
8657 #ifdef F_READAHEAD /* bsd specific */
8658  case F_READAHEAD:
8659  len = sizeof(int);
8660  break;
8661 #endif
8662 #ifdef F_RDAHEAD /* Darwin specific */
8663  case F_RDAHEAD:
8664  len = sizeof(int);
8665  break;
8666 #endif
8667 #ifdef F_GETSIG /* linux specific */
8668  case F_GETSIG:
8669  len = 1;
8670  break;
8671 #endif
8672 #ifdef F_SETSIG /* linux specific */
8673  case F_SETSIG:
8674  len = sizeof(fcntl_arg_t);
8675  break;
8676 #endif
8677 #ifdef F_GETLEASE /* linux specific */
8678  case F_GETLEASE:
8679  len = 1;
8680  break;
8681 #endif
8682 #ifdef F_SETLEASE /* linux specific */
8683  case F_SETLEASE:
8684  len = sizeof(fcntl_arg_t);
8685  break;
8686 #endif
8687 #ifdef F_NOTIFY /* linux specific */
8688  case F_NOTIFY:
8689  len = sizeof(fcntl_arg_t);
8690  break;
8691 #endif
8692 
8693  default:
8694  len = 256;
8695  break;
8696  }
8697 
8698  return len;
8699 }
8700 #else /* HAVE_FCNTL */
8701 static long
8703 {
8704  return 0;
8705 }
8706 #endif /* HAVE_FCNTL */
8707 
8708 static long
8709 setup_narg(ioctl_req_t cmd, VALUE *argp, int io_p)
8710 {
8711  long narg = 0;
8712  VALUE arg = *argp;
8713 
8714  if (NIL_P(arg) || arg == Qfalse) {
8715  narg = 0;
8716  }
8717  else if (FIXNUM_P(arg)) {
8718  narg = FIX2LONG(arg);
8719  }
8720  else if (arg == Qtrue) {
8721  narg = 1;
8722  }
8723  else {
8724  VALUE tmp = rb_check_string_type(arg);
8725 
8726  if (NIL_P(tmp)) {
8727  narg = NUM2LONG(arg);
8728  }
8729  else {
8730  long len;
8731 
8732  *argp = arg = tmp;
8733  if (io_p)
8734  len = ioctl_narg_len(cmd);
8735  else
8736  len = fcntl_narg_len((int)cmd);
8737  rb_str_modify(arg);
8738 
8739  /* expand for data + sentinel. */
8740  if (RSTRING_LEN(arg) < len+1) {
8741  rb_str_resize(arg, len+1);
8742  }
8743  /* a little sanity check here */
8744  RSTRING_PTR(arg)[RSTRING_LEN(arg) - 1] = 17;
8745  narg = (long)(SIGNED_VALUE)RSTRING_PTR(arg);
8746  }
8747  }
8748 
8749  return narg;
8750 }
8751 
8752 static VALUE
8754 {
8755  ioctl_req_t cmd = NUM2IOCTLREQ(req);
8756  rb_io_t *fptr;
8757  long narg;
8758  int retval;
8759 
8760  rb_secure(2);
8761 
8762  narg = setup_narg(cmd, &arg, 1);
8763  GetOpenFile(io, fptr);
8764  retval = do_ioctl(fptr->fd, cmd, narg);
8765  if (retval < 0) rb_sys_fail_path(fptr->pathv);
8766  if (RB_TYPE_P(arg, T_STRING)) {
8767  if (RSTRING_PTR(arg)[RSTRING_LEN(arg)-1] != 17)
8768  rb_raise(rb_eArgError, "return value overflowed string");
8769  RSTRING_PTR(arg)[RSTRING_LEN(arg)-1] = '\0';
8770  }
8771 
8772  return INT2NUM(retval);
8773 }
8774 
8775 /*
8776  * call-seq:
8777  * ios.ioctl(integer_cmd, arg) -> integer
8778  *
8779  * Provides a mechanism for issuing low-level commands to control or
8780  * query I/O devices. Arguments and results are platform dependent. If
8781  * <i>arg</i> is a number, its value is passed directly. If it is a
8782  * string, it is interpreted as a binary sequence of bytes. On Unix
8783  * platforms, see <code>ioctl(2)</code> for details. Not implemented on
8784  * all platforms.
8785  */
8786 
8787 static VALUE
8789 {
8790  VALUE req, arg;
8791 
8792  rb_scan_args(argc, argv, "11", &req, &arg);
8793  return rb_ioctl(io, req, arg);
8794 }
8795 
8796 #ifdef HAVE_FCNTL
8797 struct fcntl_arg {
8798  int fd;
8799  int cmd;
8800  long narg;
8801 };
8802 
8803 static VALUE
8804 nogvl_fcntl(void *ptr)
8805 {
8806  struct fcntl_arg *arg = ptr;
8807 
8808 #if defined(F_DUPFD)
8809  if (arg->cmd == F_DUPFD)
8810  return (VALUE)rb_cloexec_fcntl_dupfd(arg->fd, (int)arg->narg);
8811 #endif
8812  return (VALUE)fcntl(arg->fd, arg->cmd, arg->narg);
8813 }
8814 
8815 static int
8816 do_fcntl(int fd, int cmd, long narg)
8817 {
8818  int retval;
8819  struct fcntl_arg arg;
8820 
8821  arg.fd = fd;
8822  arg.cmd = cmd;
8823  arg.narg = narg;
8824 
8825  retval = (int)rb_thread_io_blocking_region(nogvl_fcntl, &arg, fd);
8826 #if defined(F_DUPFD)
8827  if (retval != -1 && cmd == F_DUPFD) {
8828  rb_update_max_fd(retval);
8829  }
8830 #endif
8831 
8832  return retval;
8833 }
8834 
8835 static VALUE
8836 rb_fcntl(VALUE io, VALUE req, VALUE arg)
8837 {
8838  int cmd = NUM2INT(req);
8839  rb_io_t *fptr;
8840  long narg;
8841  int retval;
8842 
8843  rb_secure(2);
8844 
8845  narg = setup_narg(cmd, &arg, 0);
8846  GetOpenFile(io, fptr);
8847  retval = do_fcntl(fptr->fd, cmd, narg);
8848  if (retval < 0) rb_sys_fail_path(fptr->pathv);
8849  if (RB_TYPE_P(arg, T_STRING)) {
8850  if (RSTRING_PTR(arg)[RSTRING_LEN(arg)-1] != 17)
8851  rb_raise(rb_eArgError, "return value overflowed string");
8852  RSTRING_PTR(arg)[RSTRING_LEN(arg)-1] = '\0';
8853  }
8854 
8855  if (cmd == F_SETFL) {
8856  if (narg & O_NONBLOCK) {
8857  fptr->mode |= FMODE_WSPLIT_INITIALIZED;
8858  fptr->mode &= ~FMODE_WSPLIT;
8859  }
8860  else {
8862  }
8863  }
8864 
8865  return INT2NUM(retval);
8866 }
8867 
8868 /*
8869  * call-seq:
8870  * ios.fcntl(integer_cmd, arg) -> integer
8871  *
8872  * Provides a mechanism for issuing low-level commands to control or
8873  * query file-oriented I/O streams. Arguments and results are platform
8874  * dependent. If <i>arg</i> is a number, its value is passed
8875  * directly. If it is a string, it is interpreted as a binary sequence
8876  * of bytes (<code>Array#pack</code> might be a useful way to build this
8877  * string). On Unix platforms, see <code>fcntl(2)</code> for details.
8878  * Not implemented on all platforms.
8879  */
8880 
8881 static VALUE
8882 rb_io_fcntl(int argc, VALUE *argv, VALUE io)
8883 {
8884  VALUE req, arg;
8885 
8886  rb_scan_args(argc, argv, "11", &req, &arg);
8887  return rb_fcntl(io, req, arg);
8888 }
8889 #else
8890 #define rb_io_fcntl rb_f_notimplement
8891 #endif
8892 
8893 #if defined(HAVE_SYSCALL) || defined(HAVE___SYSCALL)
8894 /*
8895  * call-seq:
8896  * syscall(num [, args...]) -> integer
8897  *
8898  * Calls the operating system function identified by _num_ and
8899  * returns the result of the function or raises SystemCallError if
8900  * it failed.
8901  *
8902  * Arguments for the function can follow _num_. They must be either
8903  * +String+ objects or +Integer+ objects. A +String+ object is passed
8904  * as a pointer to the byte sequence. An +Integer+ object is passed
8905  * as an integer whose bit size is same as a pointer.
8906  * Up to nine parameters may be passed (14 on the Atari-ST).
8907  *
8908  * The function identified by _num_ is system
8909  * dependent. On some Unix systems, the numbers may be obtained from a
8910  * header file called <code>syscall.h</code>.
8911  *
8912  * syscall 4, 1, "hello\n", 6 # '4' is write(2) on our box
8913  *
8914  * <em>produces:</em>
8915  *
8916  * hello
8917  *
8918  *
8919  * Calling +syscall+ on a platform which does not have any way to
8920  * an arbitrary system function just fails with NotImplementedError.
8921  *
8922  * Note::
8923  * +syscall+ is essentially unsafe and unportable. Feel free to shoot your foot.
8924  * DL (Fiddle) library is preferred for safer and a bit more portable programming.
8925  */
8926 
8927 static VALUE
8928 rb_f_syscall(int argc, VALUE *argv)
8929 {
8930 #ifdef atarist
8931  VALUE arg[13]; /* yes, we really need that many ! */
8932 #else
8933  VALUE arg[8];
8934 #endif
8935 #if SIZEOF_VOIDP == 8 && defined(HAVE___SYSCALL) && SIZEOF_INT != 8 /* mainly *BSD */
8936 # define SYSCALL __syscall
8937 # define NUM2SYSCALLID(x) NUM2LONG(x)
8938 # define RETVAL2NUM(x) LONG2NUM(x)
8939 # if SIZEOF_LONG == 8
8940  long num, retval = -1;
8941 # elif SIZEOF_LONG_LONG == 8
8942  long long num, retval = -1;
8943 # else
8944 # error ---->> it is asserted that __syscall takes the first argument and returns retval in 64bit signed integer. <<----
8945 # endif
8946 #elif defined(__linux__)
8947 # define SYSCALL syscall
8948 # define NUM2SYSCALLID(x) NUM2LONG(x)
8949 # define RETVAL2NUM(x) LONG2NUM(x)
8950  /*
8951  * Linux man page says, syscall(2) function prototype is below.
8952  *
8953  * int syscall(int number, ...);
8954  *
8955  * But, it's incorrect. Actual one takes and returned long. (see unistd.h)
8956  */
8957  long num, retval = -1;
8958 #else
8959 # define SYSCALL syscall
8960 # define NUM2SYSCALLID(x) NUM2INT(x)
8961 # define RETVAL2NUM(x) INT2NUM(x)
8962  int num, retval = -1;
8963 #endif
8964  int i;
8965 
8966  if (RTEST(ruby_verbose)) {
8967  rb_warning("We plan to remove a syscall function at future release. DL(Fiddle) provides safer alternative.");
8968  }
8969 
8970  rb_secure(2);
8971  if (argc == 0)
8972  rb_raise(rb_eArgError, "too few arguments for syscall");
8973  if (argc > numberof(arg))
8974  rb_raise(rb_eArgError, "too many arguments for syscall");
8975  num = NUM2SYSCALLID(argv[0]); ++argv;
8976  for (i = argc - 1; i--; ) {
8977  VALUE v = rb_check_string_type(argv[i]);
8978 
8979  if (!NIL_P(v)) {
8980  SafeStringValue(v);
8981  rb_str_modify(v);
8982  arg[i] = (VALUE)StringValueCStr(v);
8983  }
8984  else {
8985  arg[i] = (VALUE)NUM2LONG(argv[i]);
8986  }
8987  }
8988 
8989  switch (argc) {
8990  case 1:
8991  retval = SYSCALL(num);
8992  break;
8993  case 2:
8994  retval = SYSCALL(num, arg[0]);
8995  break;
8996  case 3:
8997  retval = SYSCALL(num, arg[0],arg[1]);
8998  break;
8999  case 4:
9000  retval = SYSCALL(num, arg[0],arg[1],arg[2]);
9001  break;
9002  case 5:
9003  retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3]);
9004  break;
9005  case 6:
9006  retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4]);
9007  break;
9008  case 7:
9009  retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5]);
9010  break;
9011  case 8:
9012  retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6]);
9013  break;
9014 #ifdef atarist
9015  case 9:
9016  retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
9017  arg[7]);
9018  break;
9019  case 10:
9020  retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
9021  arg[7], arg[8]);
9022  break;
9023  case 11:
9024  retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
9025  arg[7], arg[8], arg[9]);
9026  break;
9027  case 12:
9028  retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
9029  arg[7], arg[8], arg[9], arg[10]);
9030  break;
9031  case 13:
9032  retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
9033  arg[7], arg[8], arg[9], arg[10], arg[11]);
9034  break;
9035  case 14:
9036  retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],
9037  arg[7], arg[8], arg[9], arg[10], arg[11], arg[12]);
9038  break;
9039 #endif
9040  }
9041 
9042  if (retval == -1)
9043  rb_sys_fail(0);
9044  return RETVAL2NUM(retval);
9045 #undef SYSCALL
9046 #undef NUM2SYSCALLID
9047 #undef RETVAL2NUM
9048 }
9049 #else
9050 #define rb_f_syscall rb_f_notimplement
9051 #endif
9052 
9053 static VALUE
9055 {
9056  return rb_class_new_instance(2, (VALUE*)args+1, *(VALUE*)args);
9057 }
9058 
9059 static rb_encoding *
9061 {
9062  rb_encoding *enc = rb_find_encoding(v);
9063  if (!enc) unsupported_encoding(StringValueCStr(v));
9064  return enc;
9065 }
9066 
9067 static void
9069 {
9070  rb_encoding *enc, *enc2;
9071  int ecflags = fptr->encs.ecflags;
9072  VALUE ecopts, tmp;
9073 
9074  if (!NIL_P(v2)) {
9075  enc2 = find_encoding(v1);
9076  tmp = rb_check_string_type(v2);
9077  if (!NIL_P(tmp)) {
9078  if (RSTRING_LEN(tmp) == 1 && RSTRING_PTR(tmp)[0] == '-') {
9079  /* Special case - "-" => no transcoding */
9080  enc = enc2;
9081  enc2 = NULL;
9082  }
9083  else
9084  enc = find_encoding(v2);
9085  if (enc == enc2) {
9086  /* Special case - "-" => no transcoding */
9087  enc2 = NULL;
9088  }
9089  }
9090  else {
9091  enc = find_encoding(v2);
9092  if (enc == enc2) {
9093  /* Special case - "-" => no transcoding */
9094  enc2 = NULL;
9095  }
9096  }
9098  ecflags = rb_econv_prepare_options(opt, &ecopts, ecflags);
9099  }
9100  else {
9101  if (NIL_P(v1)) {
9102  /* Set to default encodings */
9103  rb_io_ext_int_to_encs(NULL, NULL, &enc, &enc2, 0);
9105  ecopts = Qnil;
9106  }
9107  else {
9108  tmp = rb_check_string_type(v1);
9109  if (!NIL_P(tmp) && rb_enc_asciicompat(rb_enc_get(tmp))) {
9110  parse_mode_enc(RSTRING_PTR(tmp), &enc, &enc2, NULL);
9112  ecflags = rb_econv_prepare_options(opt, &ecopts, ecflags);
9113  }
9114  else {
9115  rb_io_ext_int_to_encs(find_encoding(v1), NULL, &enc, &enc2, 0);
9117  ecopts = Qnil;
9118  }
9119  }
9120  }
9121  validate_enc_binmode(&fptr->mode, ecflags, enc, enc2);
9122  fptr->encs.enc = enc;
9123  fptr->encs.enc2 = enc2;
9124  fptr->encs.ecflags = ecflags;
9125  fptr->encs.ecopts = ecopts;
9126  clear_codeconv(fptr);
9127 
9128 }
9129 
9130 static VALUE
9132 {
9133  VALUE *rwp = (VALUE *)rw;
9134  return rb_ensure(io_close, rwp[0], io_close, rwp[1]);
9135 }
9136 
9137 /*
9138  * call-seq:
9139  * IO.pipe -> [read_io, write_io]
9140  * IO.pipe(ext_enc) -> [read_io, write_io]
9141  * IO.pipe("ext_enc:int_enc" [, opt]) -> [read_io, write_io]
9142  * IO.pipe(ext_enc, int_enc [, opt]) -> [read_io, write_io]
9143  *
9144  * IO.pipe(...) {|read_io, write_io| ... }
9145  *
9146  * Creates a pair of pipe endpoints (connected to each other) and
9147  * returns them as a two-element array of <code>IO</code> objects:
9148  * <code>[</code> <i>read_io</i>, <i>write_io</i> <code>]</code>.
9149  *
9150  * If a block is given, the block is called and
9151  * returns the value of the block.
9152  * <i>read_io</i> and <i>write_io</i> are sent to the block as arguments.
9153  * If read_io and write_io are not closed when the block exits, they are closed.
9154  * i.e. closing read_io and/or write_io doesn't cause an error.
9155  *
9156  * Not available on all platforms.
9157  *
9158  * If an encoding (encoding name or encoding object) is specified as an optional argument,
9159  * read string from pipe is tagged with the encoding specified.
9160  * If the argument is a colon separated two encoding names "A:B",
9161  * the read string is converted from encoding A (external encoding)
9162  * to encoding B (internal encoding), then tagged with B.
9163  * If two optional arguments are specified, those must be
9164  * encoding objects or encoding names,
9165  * and the first one is the external encoding,
9166  * and the second one is the internal encoding.
9167  * If the external encoding and the internal encoding is specified,
9168  * optional hash argument specify the conversion option.
9169  *
9170  * In the example below, the two processes close the ends of the pipe
9171  * that they are not using. This is not just a cosmetic nicety. The
9172  * read end of a pipe will not generate an end of file condition if
9173  * there are any writers with the pipe still open. In the case of the
9174  * parent process, the <code>rd.read</code> will never return if it
9175  * does not first issue a <code>wr.close</code>.
9176  *
9177  * rd, wr = IO.pipe
9178  *
9179  * if fork
9180  * wr.close
9181  * puts "Parent got: <#{rd.read}>"
9182  * rd.close
9183  * Process.wait
9184  * else
9185  * rd.close
9186  * puts "Sending message to parent"
9187  * wr.write "Hi Dad"
9188  * wr.close
9189  * end
9190  *
9191  * <em>produces:</em>
9192  *
9193  * Sending message to parent
9194  * Parent got: <Hi Dad>
9195  */
9196 
9197 static VALUE
9199 {
9200  int pipes[2], state;
9201  VALUE r, w, args[3], v1, v2;
9202  VALUE opt;
9203  rb_io_t *fptr, *fptr2;
9204  int fmode = 0;
9205  VALUE ret;
9206 
9207  argc = rb_scan_args(argc, argv, "02:", &v1, &v2, &opt);
9208  if (rb_pipe(pipes) == -1)
9209  rb_sys_fail(0);
9210 
9211  args[0] = klass;
9212  args[1] = INT2NUM(pipes[0]);
9213  args[2] = INT2FIX(O_RDONLY);
9214  r = rb_protect(io_new_instance, (VALUE)args, &state);
9215  if (state) {
9216  close(pipes[0]);
9217  close(pipes[1]);
9218  rb_jump_tag(state);
9219  }
9220  GetOpenFile(r, fptr);
9221  io_encoding_set(fptr, v1, v2, opt);
9222  args[1] = INT2NUM(pipes[1]);
9223  args[2] = INT2FIX(O_WRONLY);
9224  w = rb_protect(io_new_instance, (VALUE)args, &state);
9225  if (state) {
9226  close(pipes[1]);
9227  if (!NIL_P(r)) rb_io_close(r);
9228  rb_jump_tag(state);
9229  }
9230  GetOpenFile(w, fptr2);
9231  rb_io_synchronized(fptr2);
9232 
9233  extract_binmode(opt, &fmode);
9234 #if DEFAULT_TEXTMODE
9235  if ((fptr->mode & FMODE_TEXTMODE) && (fmode & FMODE_BINMODE)) {
9236  fptr->mode &= ~FMODE_TEXTMODE;
9237  setmode(fptr->fd, O_BINARY);
9238  }
9239 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
9242  }
9243 #endif
9244 #endif
9245  fptr->mode |= fmode;
9246 #if DEFAULT_TEXTMODE
9247  if ((fptr2->mode & FMODE_TEXTMODE) && (fmode & FMODE_BINMODE)) {
9248  fptr2->mode &= ~FMODE_TEXTMODE;
9249  setmode(fptr2->fd, O_BINARY);
9250  }
9251 #endif
9252  fptr2->mode |= fmode;
9253 
9254  ret = rb_assoc_new(r, w);
9255  if (rb_block_given_p()) {
9256  VALUE rw[2];
9257  rw[0] = r;
9258  rw[1] = w;
9259  return rb_ensure(rb_yield, ret, pipe_pair_close, (VALUE)rw);
9260  }
9261  return ret;
9262 }
9263 
9264 struct foreach_arg {
9265  int argc;
9268 };
9269 
9270 static void
9271 open_key_args(int argc, VALUE *argv, VALUE opt, struct foreach_arg *arg)
9272 {
9273  VALUE path, v;
9274 
9275  path = *argv++;
9276  argc--;
9277  FilePathValue(path);
9278  arg->io = 0;
9279  arg->argc = argc;
9280  arg->argv = argv;
9281  if (NIL_P(opt)) {
9282  arg->io = rb_io_open(path, INT2NUM(O_RDONLY), INT2FIX(0666), Qnil);
9283  return;
9284  }
9285  v = rb_hash_aref(opt, sym_open_args);
9286  if (!NIL_P(v)) {
9287  VALUE args;
9288  long n;
9289 
9290  v = rb_convert_type(v, T_ARRAY, "Array", "to_ary");
9291  n = RARRAY_LEN(v) + 1;
9292 #if SIZEOF_LONG > SIZEOF_INT
9293  if (n > INT_MAX) {
9294  rb_raise(rb_eArgError, "too many arguments");
9295  }
9296 #endif
9297  args = rb_ary_tmp_new(n);
9298  rb_ary_push(args, path);
9299  rb_ary_concat(args, v);
9300  arg->io = rb_io_open_with_args((int)n, RARRAY_PTR(args));
9301  rb_ary_clear(args); /* prevent from GC */
9302  return;
9303  }
9304  arg->io = rb_io_open(path, Qnil, Qnil, opt);
9305 }
9306 
9307 static VALUE
9309 {
9310  VALUE str;
9311 
9312  while (!NIL_P(str = rb_io_gets_m(arg->argc, arg->argv, arg->io))) {
9313  rb_yield(str);
9314  }
9315  return Qnil;
9316 }
9317 
9318 /*
9319  * call-seq:
9320  * IO.foreach(name, sep=$/ [, open_args]) {|line| block } -> nil
9321  * IO.foreach(name, limit [, open_args]) {|line| block } -> nil
9322  * IO.foreach(name, sep, limit [, open_args]) {|line| block } -> nil
9323  * IO.foreach(...) -> an_enumerator
9324  *
9325  * Executes the block for every line in the named I/O port, where lines
9326  * are separated by <em>sep</em>.
9327  *
9328  * If no block is given, an enumerator is returned instead.
9329  *
9330  * IO.foreach("testfile") {|x| print "GOT ", x }
9331  *
9332  * <em>produces:</em>
9333  *
9334  * GOT This is line one
9335  * GOT This is line two
9336  * GOT This is line three
9337  * GOT And so on...
9338  *
9339  * If the last argument is a hash, it's the keyword argument to open.
9340  * See <code>IO.read</code> for detail.
9341  *
9342  */
9343 
9344 static VALUE
9346 {
9347  VALUE opt;
9348  int orig_argc = argc;
9349  struct foreach_arg arg;
9350 
9351  argc = rb_scan_args(argc, argv, "13:", NULL, NULL, NULL, NULL, &opt);
9352  RETURN_ENUMERATOR(self, orig_argc, argv);
9353  open_key_args(argc, argv, opt, &arg);
9354  if (NIL_P(arg.io)) return Qnil;
9355  return rb_ensure(io_s_foreach, (VALUE)&arg, rb_io_close, arg.io);
9356 }
9357 
9358 static VALUE
9360 {
9361  return rb_io_readlines(arg->argc, arg->argv, arg->io);
9362 }
9363 
9364 /*
9365  * call-seq:
9366  * IO.readlines(name, sep=$/ [, open_args]) -> array
9367  * IO.readlines(name, limit [, open_args]) -> array
9368  * IO.readlines(name, sep, limit [, open_args]) -> array
9369  *
9370  * Reads the entire file specified by <i>name</i> as individual
9371  * lines, and returns those lines in an array. Lines are separated by
9372  * <i>sep</i>.
9373  *
9374  * a = IO.readlines("testfile")
9375  * a[0] #=> "This is line one\n"
9376  *
9377  * If the last argument is a hash, it's the keyword argument to open.
9378  * See <code>IO.read</code> for detail.
9379  *
9380  */
9381 
9382 static VALUE
9384 {
9385  VALUE opt;
9386  struct foreach_arg arg;
9387 
9388  argc = rb_scan_args(argc, argv, "13:", NULL, NULL, NULL, NULL, &opt);
9389  open_key_args(argc, argv, opt, &arg);
9390  if (NIL_P(arg.io)) return Qnil;
9391  return rb_ensure(io_s_readlines, (VALUE)&arg, rb_io_close, arg.io);
9392 }
9393 
9394 static VALUE
9396 {
9397  return io_read(arg->argc, arg->argv, arg->io);
9398 }
9399 
9400 struct seek_arg {
9403  int mode;
9404 };
9405 
9406 static VALUE
9408 {
9409  struct seek_arg *arg = (struct seek_arg *)argp;
9410  rb_io_binmode(arg->io);
9411  return rb_io_seek(arg->io, arg->offset, arg->mode);
9412 }
9413 
9414 /*
9415  * call-seq:
9416  * IO.read(name, [length [, offset]] ) -> string
9417  * IO.read(name, [length [, offset]], open_args) -> string
9418  *
9419  * Opens the file, optionally seeks to the given +offset+, then returns
9420  * +length+ bytes (defaulting to the rest of the file). <code>read</code>
9421  * ensures the file is closed before returning.
9422  *
9423  * If the last argument is a hash, it specifies option for internal
9424  * open(). The key would be the following. open_args: is exclusive
9425  * to others.
9426  *
9427  * encoding::
9428  * string or encoding
9429  *
9430  * specifies encoding of the read string. +encoding+ will be ignored
9431  * if length is specified.
9432  *
9433  * mode::
9434  * string
9435  *
9436  * specifies mode argument for open(). It should start with "r"
9437  * otherwise it will cause an error.
9438  *
9439  * open_args:: array of strings
9440  *
9441  * specifies arguments for open() as an array.
9442  *
9443  * Examples:
9444  *
9445  * IO.read("testfile") #=> "This is line one\nThis is line two\nThis is line three\nAnd so on...\n"
9446  * IO.read("testfile", 20) #=> "This is line one\nThi"
9447  * IO.read("testfile", 20, 10) #=> "ne one\nThis is line "
9448  */
9449 
9450 static VALUE
9452 {
9453  VALUE opt, offset;
9454  struct foreach_arg arg;
9455 
9456  argc = rb_scan_args(argc, argv, "13:", NULL, NULL, &offset, NULL, &opt);
9457  open_key_args(argc, argv, opt, &arg);
9458  if (NIL_P(arg.io)) return Qnil;
9459  if (!NIL_P(offset)) {
9460  struct seek_arg sarg;
9461  int state = 0;
9462  sarg.io = arg.io;
9463  sarg.offset = offset;
9464  sarg.mode = SEEK_SET;
9465  rb_protect(seek_before_access, (VALUE)&sarg, &state);
9466  if (state) {
9467  rb_io_close(arg.io);
9468  rb_jump_tag(state);
9469  }
9470  if (arg.argc == 2) arg.argc = 1;
9471  }
9472  return rb_ensure(io_s_read, (VALUE)&arg, rb_io_close, arg.io);
9473 }
9474 
9475 /*
9476  * call-seq:
9477  * IO.binread(name, [length [, offset]] ) -> string
9478  *
9479  * Opens the file, optionally seeks to the given <i>offset</i>, then returns
9480  * <i>length</i> bytes (defaulting to the rest of the file).
9481  * <code>binread</code> ensures the file is closed before returning.
9482  * The open mode would be "rb:ASCII-8BIT".
9483  *
9484  * IO.binread("testfile") #=> "This is line one\nThis is line two\nThis is line three\nAnd so on...\n"
9485  * IO.binread("testfile", 20) #=> "This is line one\nThi"
9486  * IO.binread("testfile", 20, 10) #=> "ne one\nThis is line "
9487  */
9488 
9489 static VALUE
9491 {
9492  VALUE offset;
9493  struct foreach_arg arg;
9494 
9495  rb_scan_args(argc, argv, "12", NULL, NULL, &offset);
9496  FilePathValue(argv[0]);
9497  arg.io = rb_io_open(argv[0], rb_str_new_cstr("rb:ASCII-8BIT"), Qnil, Qnil);
9498  if (NIL_P(arg.io)) return Qnil;
9499  arg.argv = argv+1;
9500  arg.argc = (argc > 1) ? 1 : 0;
9501  if (!NIL_P(offset)) {
9502  rb_io_seek(arg.io, offset, SEEK_SET);
9503  }
9504  return rb_ensure(io_s_read, (VALUE)&arg, rb_io_close, arg.io);
9505 }
9506 
9507 static VALUE
9509 {
9510  return io_write(arg->io,arg->str,arg->nosync);
9511 }
9512 
9513 static VALUE
9514 io_s_write(int argc, VALUE *argv, int binary)
9515 {
9516  VALUE string, offset, opt;
9517  struct foreach_arg arg;
9518  struct write_arg warg;
9519 
9520  rb_scan_args(argc, argv, "21:", NULL, &string, &offset, &opt);
9521 
9522  if (NIL_P(opt)) opt = rb_hash_new();
9523  else opt = rb_hash_dup(opt);
9524 
9525 
9526  if (NIL_P(rb_hash_aref(opt,sym_mode))) {
9527  int mode = O_WRONLY|O_CREAT;
9528 #ifdef O_BINARY
9529  if (binary) mode |= O_BINARY;
9530 #endif
9531  if (NIL_P(offset)) mode |= O_TRUNC;
9532  rb_hash_aset(opt,sym_mode,INT2NUM(mode));
9533  }
9534  open_key_args(argc,argv,opt,&arg);
9535 
9536 #ifndef O_BINARY
9537  if (binary) rb_io_binmode_m(arg.io);
9538 #endif
9539 
9540  if (NIL_P(arg.io)) return Qnil;
9541  if (!NIL_P(offset)) {
9542  struct seek_arg sarg;
9543  int state = 0;
9544  sarg.io = arg.io;
9545  sarg.offset = offset;
9546  sarg.mode = SEEK_SET;
9547  rb_protect(seek_before_access, (VALUE)&sarg, &state);
9548  if (state) {
9549  rb_io_close(arg.io);
9550  rb_jump_tag(state);
9551  }
9552  }
9553 
9554  warg.io = arg.io;
9555  warg.str = string;
9556  warg.nosync = 0;
9557 
9558  return rb_ensure(io_s_write0, (VALUE)&warg, rb_io_close, arg.io);
9559 }
9560 
9561 /*
9562  * call-seq:
9563  * IO.write(name, string, [offset] ) => fixnum
9564  * IO.write(name, string, [offset], open_args ) => fixnum
9565  *
9566  * Opens the file, optionally seeks to the given <i>offset</i>, writes
9567  * <i>string</i>, then returns the length written.
9568  * <code>write</code> ensures the file is closed before returning.
9569  * If <i>offset</i> is not given, the file is truncated. Otherwise,
9570  * it is not truncated.
9571  *
9572  * If the last argument is a hash, it specifies option for internal
9573  * open(). The key would be the following. open_args: is exclusive
9574  * to others.
9575  *
9576  * encoding: string or encoding
9577  *
9578  * specifies encoding of the read string. encoding will be ignored
9579  * if length is specified.
9580  *
9581  * mode: string
9582  *
9583  * specifies mode argument for open(). it should start with "w" or "a" or "r+"
9584  * otherwise it would cause error.
9585  *
9586  * perm: fixnum
9587  *
9588  * specifies perm argument for open().
9589  *
9590  * open_args: array
9591  *
9592  * specifies arguments for open() as an array.
9593  *
9594  * IO.write("testfile", "0123456789", 20) # => 10
9595  * # File could contain: "This is line one\nThi0123456789two\nThis is line three\nAnd so on...\n"
9596  * IO.write("testfile", "0123456789") #=> 10
9597  * # File would now read: "0123456789"
9598  */
9599 
9600 static VALUE
9602 {
9603  return io_s_write(argc, argv, 0);
9604 }
9605 
9606 /*
9607  * call-seq:
9608  * IO.binwrite(name, string, [offset] ) => fixnum
9609  * IO.binwrite(name, string, [offset], open_args ) => fixnum
9610  *
9611  * Same as <code>IO.write</code> except opening the file in binary mode
9612  * and ASCII-8BIT encoding ("wb:ASCII-8BIT").
9613  *
9614  */
9615 
9616 static VALUE
9618 {
9619  return io_s_write(argc, argv, 1);
9620 }
9621 
9625  off_t copy_length; /* (off_t)-1 if not specified */
9626  off_t src_offset; /* (off_t)-1 if not specified */
9627 
9628  int src_fd;
9629  int dst_fd;
9633  const char *syserr;
9635  const char *notimp;
9638 };
9639 
9640 static void *
9642 {
9643  VALUE th = (VALUE)arg;
9645  return NULL;
9646 }
9647 
9648 /*
9649  * returns TRUE if the preceding system call was interrupted
9650  * so we can continue. If the thread was interrupted, we
9651  * reacquire the GVL to execute interrupts before continuing.
9652  */
9653 static int
9655 {
9656  switch (errno) {
9657  case EINTR:
9658 #if defined(ERESTART)
9659  case ERESTART:
9660 #endif
9661  if (rb_thread_interrupted(stp->th)) {
9662  if (has_gvl)
9664  else
9666  }
9667  return TRUE;
9668  }
9669  return FALSE;
9670 }
9671 
9672 static int
9673 maygvl_select(int has_gvl, int n, rb_fdset_t *rfds, rb_fdset_t *wfds, rb_fdset_t *efds, struct timeval *timeout)
9674 {
9675  if (has_gvl)
9676  return rb_thread_fd_select(n, rfds, wfds, efds, timeout);
9677  else
9678  return rb_fd_select(n, rfds, wfds, efds, timeout);
9679 }
9680 
9681 static int
9683 {
9684  int ret;
9685 
9686  do {
9687  rb_fd_zero(&stp->fds);
9688  rb_fd_set(stp->src_fd, &stp->fds);
9689  ret = maygvl_select(has_gvl, rb_fd_max(&stp->fds), &stp->fds, NULL, NULL, NULL);
9690  } while (ret == -1 && maygvl_copy_stream_continue_p(has_gvl, stp));
9691 
9692  if (ret == -1) {
9693  stp->syserr = "select";
9694  stp->error_no = errno;
9695  return -1;
9696  }
9697  return 0;
9698 }
9699 
9700 static int
9702 {
9703  int ret;
9704 
9705  do {
9706  rb_fd_zero(&stp->fds);
9707  rb_fd_set(stp->dst_fd, &stp->fds);
9708  ret = rb_fd_select(rb_fd_max(&stp->fds), NULL, &stp->fds, NULL, NULL);
9709  } while (ret == -1 && maygvl_copy_stream_continue_p(0, stp));
9710 
9711  if (ret == -1) {
9712  stp->syserr = "select";
9713  stp->error_no = errno;
9714  return -1;
9715  }
9716  return 0;
9717 }
9718 
9719 #ifdef HAVE_SENDFILE
9720 
9721 # ifdef __linux__
9722 # define USE_SENDFILE
9723 
9724 # ifdef HAVE_SYS_SENDFILE_H
9725 # include <sys/sendfile.h>
9726 # endif
9727 
9728 static ssize_t
9729 simple_sendfile(int out_fd, int in_fd, off_t *offset, off_t count)
9730 {
9731  return sendfile(out_fd, in_fd, offset, (size_t)count);
9732 }
9733 
9734 # elif 0 /* defined(__FreeBSD__) || defined(__DragonFly__) */ || defined(__APPLE__)
9735 /* This runs on FreeBSD8.1 r30210, but sendfiles blocks its execution
9736  * without cpuset -l 0.
9737  */
9738 # define USE_SENDFILE
9739 
9740 # ifdef HAVE_SYS_UIO_H
9741 # include <sys/uio.h>
9742 # endif
9743 
9744 static ssize_t
9745 simple_sendfile(int out_fd, int in_fd, off_t *offset, off_t count)
9746 {
9747  int r;
9748  off_t pos = offset ? *offset : lseek(in_fd, 0, SEEK_CUR);
9749  off_t sbytes;
9750 # ifdef __APPLE__
9751  r = sendfile(in_fd, out_fd, pos, &count, NULL, 0);
9752  sbytes = count;
9753 # else
9754  r = sendfile(in_fd, out_fd, pos, (size_t)count, NULL, &sbytes, 0);
9755 # endif
9756  if (r != 0 && sbytes == 0) return -1;
9757  if (offset) {
9758  *offset += sbytes;
9759  }
9760  else {
9761  lseek(in_fd, sbytes, SEEK_CUR);
9762  }
9763  return (ssize_t)sbytes;
9764 }
9765 
9766 # endif
9767 
9768 #endif
9769 
9770 #ifdef USE_SENDFILE
9771 static int
9772 nogvl_copy_stream_sendfile(struct copy_stream_struct *stp)
9773 {
9774  struct stat src_stat, dst_stat;
9775  ssize_t ss;
9776  int ret;
9777 
9778  off_t copy_length;
9779  off_t src_offset;
9780  int use_pread;
9781 
9782  ret = fstat(stp->src_fd, &src_stat);
9783  if (ret == -1) {
9784  stp->syserr = "fstat";
9785  stp->error_no = errno;
9786  return -1;
9787  }
9788  if (!S_ISREG(src_stat.st_mode))
9789  return 0;
9790 
9791  ret = fstat(stp->dst_fd, &dst_stat);
9792  if (ret == -1) {
9793  stp->syserr = "fstat";
9794  stp->error_no = errno;
9795  return -1;
9796  }
9797  if ((dst_stat.st_mode & S_IFMT) != S_IFSOCK)
9798  return 0;
9799 
9800  src_offset = stp->src_offset;
9801  use_pread = src_offset != (off_t)-1;
9802 
9803  copy_length = stp->copy_length;
9804  if (copy_length == (off_t)-1) {
9805  if (use_pread)
9806  copy_length = src_stat.st_size - src_offset;
9807  else {
9808  off_t cur;
9809  errno = 0;
9810  cur = lseek(stp->src_fd, 0, SEEK_CUR);
9811  if (cur == (off_t)-1 && errno) {
9812  stp->syserr = "lseek";
9813  stp->error_no = errno;
9814  return -1;
9815  }
9816  copy_length = src_stat.st_size - cur;
9817  }
9818  }
9819 
9820  retry_sendfile:
9821 # if SIZEOF_OFF_T > SIZEOF_SIZE_T
9822  /* we are limited by the 32-bit ssize_t return value on 32-bit */
9823  ss = (copy_length > (off_t)SSIZE_MAX) ? SSIZE_MAX : (ssize_t)copy_length;
9824 # else
9825  ss = (ssize_t)copy_length;
9826 # endif
9827  if (use_pread) {
9828  ss = simple_sendfile(stp->dst_fd, stp->src_fd, &src_offset, ss);
9829  }
9830  else {
9831  ss = simple_sendfile(stp->dst_fd, stp->src_fd, NULL, ss);
9832  }
9833  if (0 < ss) {
9834  stp->total += ss;
9835  copy_length -= ss;
9836  if (0 < copy_length) {
9837  goto retry_sendfile;
9838  }
9839  }
9840  if (ss == -1) {
9841  if (maygvl_copy_stream_continue_p(0, stp))
9842  goto retry_sendfile;
9843  switch (errno) {
9844  case EINVAL:
9845 #ifdef ENOSYS
9846  case ENOSYS:
9847 #endif
9848  return 0;
9849  case EAGAIN:
9850 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
9851  case EWOULDBLOCK:
9852 #endif
9853 #ifndef __linux__
9854  /*
9855  * Linux requires stp->src_fd to be a mmap-able (regular) file,
9856  * select() reports regular files to always be "ready", so
9857  * there is no need to select() on it.
9858  * Other OSes may have the same limitation for sendfile() which
9859  * allow us to bypass maygvl_copy_stream_wait_read()...
9860  */
9861  if (maygvl_copy_stream_wait_read(0, stp) == -1)
9862  return -1;
9863 #endif
9864  if (nogvl_copy_stream_wait_write(stp) == -1)
9865  return -1;
9866  goto retry_sendfile;
9867  }
9868  stp->syserr = "sendfile";
9869  stp->error_no = errno;
9870  return -1;
9871  }
9872  return 1;
9873 }
9874 #endif
9875 
9876 static ssize_t
9877 maygvl_read(int has_gvl, int fd, void *buf, size_t count)
9878 {
9879  if (has_gvl)
9880  return rb_read_internal(fd, buf, count);
9881  else
9882  return read(fd, buf, count);
9883 }
9884 
9885 static ssize_t
9886 maygvl_copy_stream_read(int has_gvl, struct copy_stream_struct *stp, char *buf, size_t len, off_t offset)
9887 {
9888  ssize_t ss;
9889  retry_read:
9890  if (offset == (off_t)-1) {
9891  ss = maygvl_read(has_gvl, stp->src_fd, buf, len);
9892  }
9893  else {
9894 #ifdef HAVE_PREAD
9895  ss = pread(stp->src_fd, buf, len, offset);
9896 #else
9897  stp->notimp = "pread";
9898  return -1;
9899 #endif
9900  }
9901  if (ss == 0) {
9902  return 0;
9903  }
9904  if (ss == -1) {
9905  if (maygvl_copy_stream_continue_p(has_gvl, stp))
9906  goto retry_read;
9907  switch (errno) {
9908  case EAGAIN:
9909 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
9910  case EWOULDBLOCK:
9911 #endif
9912  if (maygvl_copy_stream_wait_read(has_gvl, stp) == -1)
9913  return -1;
9914  goto retry_read;
9915 #ifdef ENOSYS
9916  case ENOSYS:
9917 #endif
9918  stp->notimp = "pread";
9919  return -1;
9920  }
9921  stp->syserr = offset == (off_t)-1 ? "read" : "pread";
9922  stp->error_no = errno;
9923  return -1;
9924  }
9925  return ss;
9926 }
9927 
9928 static int
9929 nogvl_copy_stream_write(struct copy_stream_struct *stp, char *buf, size_t len)
9930 {
9931  ssize_t ss;
9932  int off = 0;
9933  while (len) {
9934  ss = write(stp->dst_fd, buf+off, len);
9935  if (ss == -1) {
9936  if (maygvl_copy_stream_continue_p(0, stp))
9937  continue;
9938  if (errno == EAGAIN || errno == EWOULDBLOCK) {
9939  if (nogvl_copy_stream_wait_write(stp) == -1)
9940  return -1;
9941  continue;
9942  }
9943  stp->syserr = "write";
9944  stp->error_no = errno;
9945  return -1;
9946  }
9947  off += (int)ss;
9948  len -= (int)ss;
9949  stp->total += ss;
9950  }
9951  return 0;
9952 }
9953 
9954 static void
9956 {
9957  char buf[1024*16];
9958  size_t len;
9959  ssize_t ss;
9960  int ret;
9961  off_t copy_length;
9962  int use_eof;
9963  off_t src_offset;
9964  int use_pread;
9965 
9966  copy_length = stp->copy_length;
9967  use_eof = copy_length == (off_t)-1;
9968  src_offset = stp->src_offset;
9969  use_pread = src_offset != (off_t)-1;
9970 
9971  if (use_pread && stp->close_src) {
9972  off_t r;
9973  errno = 0;
9974  r = lseek(stp->src_fd, src_offset, SEEK_SET);
9975  if (r == (off_t)-1 && errno) {
9976  stp->syserr = "lseek";
9977  stp->error_no = errno;
9978  return;
9979  }
9980  src_offset = (off_t)-1;
9981  use_pread = 0;
9982  }
9983 
9984  while (use_eof || 0 < copy_length) {
9985  if (!use_eof && copy_length < (off_t)sizeof(buf)) {
9986  len = (size_t)copy_length;
9987  }
9988  else {
9989  len = sizeof(buf);
9990  }
9991  if (use_pread) {
9992  ss = maygvl_copy_stream_read(0, stp, buf, len, src_offset);
9993  if (0 < ss)
9994  src_offset += ss;
9995  }
9996  else {
9997  ss = maygvl_copy_stream_read(0, stp, buf, len, (off_t)-1);
9998  }
9999  if (ss <= 0) /* EOF or error */
10000  return;
10001 
10002  ret = nogvl_copy_stream_write(stp, buf, ss);
10003  if (ret < 0)
10004  return;
10005 
10006  if (!use_eof)
10007  copy_length -= ss;
10008  }
10009 }
10010 
10011 static void *
10013 {
10014  struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
10015 #ifdef USE_SENDFILE
10016  int ret;
10017 #endif
10018 
10019 #ifdef USE_SENDFILE
10020  ret = nogvl_copy_stream_sendfile(stp);
10021  if (ret != 0)
10022  goto finish; /* error or success */
10023 #endif
10024 
10026 
10027 #ifdef USE_SENDFILE
10028  finish:
10029 #endif
10030  return 0;
10031 }
10032 
10033 static VALUE
10035 {
10036  struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
10037  const int buflen = 16*1024;
10038  VALUE n;
10039  VALUE buf = rb_str_buf_new(buflen);
10040  off_t rest = stp->copy_length;
10041  off_t off = stp->src_offset;
10042  ID read_method = id_readpartial;
10043 
10044  if (stp->src_fd == -1) {
10045  if (!rb_respond_to(stp->src, read_method)) {
10046  read_method = id_read;
10047  }
10048  }
10049 
10050  while (1) {
10051  long numwrote;
10052  long l;
10053  if (stp->copy_length == (off_t)-1) {
10054  l = buflen;
10055  }
10056  else {
10057  if (rest == 0)
10058  break;
10059  l = buflen < rest ? buflen : (long)rest;
10060  }
10061  if (stp->src_fd == -1) {
10062  VALUE rc = rb_funcall(stp->src, read_method, 2, INT2FIX(l), buf);
10063 
10064  if (read_method == id_read && NIL_P(rc))
10065  break;
10066  }
10067  else {
10068  ssize_t ss;
10069  rb_str_resize(buf, buflen);
10070  ss = maygvl_copy_stream_read(1, stp, RSTRING_PTR(buf), l, off);
10071  if (ss == -1)
10072  return Qnil;
10073  if (ss == 0)
10074  rb_eof_error();
10075  rb_str_resize(buf, ss);
10076  if (off != (off_t)-1)
10077  off += ss;
10078  }
10079  n = rb_io_write(stp->dst, buf);
10080  numwrote = NUM2LONG(n);
10081  stp->total += numwrote;
10082  rest -= numwrote;
10083  if (read_method == id_read && RSTRING_LEN(buf) == 0) {
10084  break;
10085  }
10086  }
10087 
10088  return Qnil;
10089 }
10090 
10091 static VALUE
10093 {
10094  if (stp->src_fd == -1 && stp->src_offset != (off_t)-1) {
10095  rb_raise(rb_eArgError, "cannot specify src_offset for non-IO");
10096  }
10098  (VALUE (*) (ANYARGS))0, (VALUE)0,
10099  rb_eEOFError, (VALUE)0);
10100  return Qnil;
10101 }
10102 
10103 static VALUE
10105 {
10106  struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
10107  VALUE src_io, dst_io;
10108  rb_io_t *src_fptr = 0, *dst_fptr = 0;
10109  int src_fd, dst_fd;
10110 
10111  stp->th = rb_thread_current();
10112 
10113  stp->total = 0;
10114 
10115  if (stp->src == argf ||
10116  !(RB_TYPE_P(stp->src, T_FILE) ||
10117  RB_TYPE_P(stp->src, T_STRING) ||
10118  rb_respond_to(stp->src, rb_intern("to_path")))) {
10119  src_fd = -1;
10120  }
10121  else {
10122  src_io = RB_TYPE_P(stp->src, T_FILE) ? stp->src : Qnil;
10123  if (NIL_P(src_io)) {
10124  VALUE args[2];
10125  int oflags = O_RDONLY;
10126 #ifdef O_NOCTTY
10127  oflags |= O_NOCTTY;
10128 #endif
10129  FilePathValue(stp->src);
10130  args[0] = stp->src;
10131  args[1] = INT2NUM(oflags);
10132  src_io = rb_class_new_instance(2, args, rb_cFile);
10133  stp->src = src_io;
10134  stp->close_src = 1;
10135  }
10136  GetOpenFile(src_io, src_fptr);
10137  rb_io_check_byte_readable(src_fptr);
10138  src_fd = src_fptr->fd;
10139  }
10140  stp->src_fd = src_fd;
10141 
10142  if (stp->dst == argf ||
10143  !(RB_TYPE_P(stp->dst, T_FILE) ||
10144  RB_TYPE_P(stp->dst, T_STRING) ||
10145  rb_respond_to(stp->dst, rb_intern("to_path")))) {
10146  dst_fd = -1;
10147  }
10148  else {
10149  dst_io = RB_TYPE_P(stp->dst, T_FILE) ? stp->dst : Qnil;
10150  if (NIL_P(dst_io)) {
10151  VALUE args[3];
10152  int oflags = O_WRONLY|O_CREAT|O_TRUNC;
10153 #ifdef O_NOCTTY
10154  oflags |= O_NOCTTY;
10155 #endif
10156  FilePathValue(stp->dst);
10157  args[0] = stp->dst;
10158  args[1] = INT2NUM(oflags);
10159  args[2] = INT2FIX(0666);
10160  dst_io = rb_class_new_instance(3, args, rb_cFile);
10161  stp->dst = dst_io;
10162  stp->close_dst = 1;
10163  }
10164  else {
10165  dst_io = GetWriteIO(dst_io);
10166  stp->dst = dst_io;
10167  }
10168  GetOpenFile(dst_io, dst_fptr);
10169  rb_io_check_writable(dst_fptr);
10170  dst_fd = dst_fptr->fd;
10171  }
10172  stp->dst_fd = dst_fd;
10173 
10174 #ifdef O_BINARY
10175  if (src_fptr)
10177  if (dst_fptr)
10178  setmode(dst_fd, O_BINARY);
10179 #endif
10180 
10181  if (stp->src_offset == (off_t)-1 && src_fptr && src_fptr->rbuf.len) {
10182  size_t len = src_fptr->rbuf.len;
10183  VALUE str;
10184  if (stp->copy_length != (off_t)-1 && stp->copy_length < (off_t)len) {
10185  len = (size_t)stp->copy_length;
10186  }
10187  str = rb_str_buf_new(len);
10188  rb_str_resize(str,len);
10189  read_buffered_data(RSTRING_PTR(str), len, src_fptr);
10190  if (dst_fptr) { /* IO or filename */
10191  if (io_binwrite(str, RSTRING_PTR(str), RSTRING_LEN(str), dst_fptr, 0) < 0)
10192  rb_sys_fail(0);
10193  }
10194  else /* others such as StringIO */
10195  rb_io_write(stp->dst, str);
10196  stp->total += len;
10197  if (stp->copy_length != (off_t)-1)
10198  stp->copy_length -= len;
10199  }
10200 
10201  if (dst_fptr && io_fflush(dst_fptr) < 0) {
10202  rb_raise(rb_eIOError, "flush failed");
10203  }
10204 
10205  if (stp->copy_length == 0)
10206  return Qnil;
10207 
10208  if (src_fd == -1 || dst_fd == -1) {
10209  return copy_stream_fallback(stp);
10210  }
10211 
10212  rb_fd_set(src_fd, &stp->fds);
10213  rb_fd_set(dst_fd, &stp->fds);
10214 
10216  return Qnil;
10217 }
10218 
10219 static VALUE
10221 {
10222  struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
10223  if (stp->close_src) {
10224  rb_io_close_m(stp->src);
10225  }
10226  if (stp->close_dst) {
10227  rb_io_close_m(stp->dst);
10228  }
10229  rb_fd_term(&stp->fds);
10230  if (stp->syserr) {
10231  errno = stp->error_no;
10232  rb_sys_fail(stp->syserr);
10233  }
10234  if (stp->notimp) {
10235  rb_raise(rb_eNotImpError, "%s() not implemented", stp->notimp);
10236  }
10237  return Qnil;
10238 }
10239 
10240 /*
10241  * call-seq:
10242  * IO.copy_stream(src, dst)
10243  * IO.copy_stream(src, dst, copy_length)
10244  * IO.copy_stream(src, dst, copy_length, src_offset)
10245  *
10246  * IO.copy_stream copies <i>src</i> to <i>dst</i>.
10247  * <i>src</i> and <i>dst</i> is either a filename or an IO.
10248  *
10249  * This method returns the number of bytes copied.
10250  *
10251  * If optional arguments are not given,
10252  * the start position of the copy is
10253  * the beginning of the filename or
10254  * the current file offset of the IO.
10255  * The end position of the copy is the end of file.
10256  *
10257  * If <i>copy_length</i> is given,
10258  * No more than <i>copy_length</i> bytes are copied.
10259  *
10260  * If <i>src_offset</i> is given,
10261  * it specifies the start position of the copy.
10262  *
10263  * When <i>src_offset</i> is specified and
10264  * <i>src</i> is an IO,
10265  * IO.copy_stream doesn't move the current file offset.
10266  *
10267  */
10268 static VALUE
10270 {
10271  VALUE src, dst, length, src_offset;
10272  struct copy_stream_struct st;
10273 
10274  MEMZERO(&st, struct copy_stream_struct, 1);
10275 
10276  rb_scan_args(argc, argv, "22", &src, &dst, &length, &src_offset);
10277 
10278  st.src = src;
10279  st.dst = dst;
10280 
10281  if (NIL_P(length))
10282  st.copy_length = (off_t)-1;
10283  else
10284  st.copy_length = NUM2OFFT(length);
10285 
10286  if (NIL_P(src_offset))
10287  st.src_offset = (off_t)-1;
10288  else
10289  st.src_offset = NUM2OFFT(src_offset);
10290 
10291  rb_fd_init(&st.fds);
10293 
10294  return OFFT2NUM(st.total);
10295 }
10296 
10297 /*
10298  * call-seq:
10299  * io.external_encoding -> encoding
10300  *
10301  * Returns the Encoding object that represents the encoding of the file.
10302  * If io is write mode and no encoding is specified, returns <code>nil</code>.
10303  */
10304 
10305 static VALUE
10307 {
10308  rb_io_t *fptr;
10309 
10310  GetOpenFile(io, fptr);
10311  if (fptr->encs.enc2) {
10312  return rb_enc_from_encoding(fptr->encs.enc2);
10313  }
10314  if (fptr->mode & FMODE_WRITABLE) {
10315  if (fptr->encs.enc)
10316  return rb_enc_from_encoding(fptr->encs.enc);
10317  return Qnil;
10318  }
10319  return rb_enc_from_encoding(io_read_encoding(fptr));
10320 }
10321 
10322 /*
10323  * call-seq:
10324  * io.internal_encoding -> encoding
10325  *
10326  * Returns the Encoding of the internal string if conversion is
10327  * specified. Otherwise returns nil.
10328  */
10329 
10330 static VALUE
10332 {
10333  rb_io_t *fptr;
10334 
10335  GetOpenFile(io, fptr);
10336  if (!fptr->encs.enc2) return Qnil;
10337  return rb_enc_from_encoding(io_read_encoding(fptr));
10338 }
10339 
10340 /*
10341  * call-seq:
10342  * io.set_encoding(ext_enc) -> io
10343  * io.set_encoding("ext_enc:int_enc") -> io
10344  * io.set_encoding(ext_enc, int_enc) -> io
10345  * io.set_encoding("ext_enc:int_enc", opt) -> io
10346  * io.set_encoding(ext_enc, int_enc, opt) -> io
10347  *
10348  * If single argument is specified, read string from io is tagged
10349  * with the encoding specified. If encoding is a colon separated two
10350  * encoding names "A:B", the read string is converted from encoding A
10351  * (external encoding) to encoding B (internal encoding), then tagged
10352  * with B. If two arguments are specified, those must be encoding
10353  * objects or encoding names, and the first one is the external encoding, and the
10354  * second one is the internal encoding.
10355  * If the external encoding and the internal encoding is specified,
10356  * optional hash argument specify the conversion option.
10357  */
10358 
10359 static VALUE
10361 {
10362  rb_io_t *fptr;
10363  VALUE v1, v2, opt;
10364 
10365  if (!RB_TYPE_P(io, T_FILE)) {
10366  return rb_funcall2(io, id_set_encoding, argc, argv);
10367  }
10368 
10369  argc = rb_scan_args(argc, argv, "11:", &v1, &v2, &opt);
10370  GetOpenFile(io, fptr);
10371  io_encoding_set(fptr, v1, v2, opt);
10372  return io;
10373 }
10374 
10375 void
10377 {
10378  extern VALUE rb_stdin, rb_stdout, rb_stderr;
10379  VALUE val = Qnil;
10380 
10381  rb_io_set_encoding(1, &val, rb_stdin);
10382  rb_io_set_encoding(1, &val, rb_stdout);
10383  rb_io_set_encoding(1, &val, rb_stderr);
10384 }
10385 
10386 /*
10387  * call-seq:
10388  * ARGF.external_encoding -> encoding
10389  *
10390  * Returns the external encoding for files read from +ARGF+ as an +Encoding+
10391  * object. The external encoding is the encoding of the text as stored in a
10392  * file. Contrast with +ARGF.internal_encoding+, which is the encoding used
10393  * to represent this text within Ruby.
10394  *
10395  * To set the external encoding use +ARGF.set_encoding+.
10396  *
10397  * For example:
10398  *
10399  * ARGF.external_encoding #=> #<Encoding:UTF-8>
10400  *
10401  */
10402 static VALUE
10404 {
10405  if (!RTEST(ARGF.current_file)) {
10407  }
10408  return rb_io_external_encoding(rb_io_check_io(ARGF.current_file));
10409 }
10410 
10411 /*
10412  * call-seq:
10413  * ARGF.internal_encoding -> encoding
10414  *
10415  * Returns the internal encoding for strings read from +ARGF+ as an
10416  * +Encoding+ object.
10417  *
10418  * If +ARGF.set_encoding+ has been called with two encoding names, the second
10419  * is returned. Otherwise, if +Encoding.default_external+ has been set, that
10420  * value is returned. Failing that, if a default external encoding was
10421  * specified on the command-line, that value is used. If the encoding is
10422  * unknown, nil is returned.
10423  */
10424 static VALUE
10426 {
10427  if (!RTEST(ARGF.current_file)) {
10429  }
10430  return rb_io_internal_encoding(rb_io_check_io(ARGF.current_file));
10431 }
10432 
10433 /*
10434  * call-seq:
10435  * ARGF.set_encoding(ext_enc) -> ARGF
10436  * ARGF.set_encoding("ext_enc:int_enc") -> ARGF
10437  * ARGF.set_encoding(ext_enc, int_enc) -> ARGF
10438  * ARGF.set_encoding("ext_enc:int_enc", opt) -> ARGF
10439  * ARGF.set_encoding(ext_enc, int_enc, opt) -> ARGF
10440  *
10441  * If single argument is specified, strings read from ARGF are tagged with
10442  * the encoding specified.
10443  *
10444  * If two encoding names separated by a colon are given, e.g. "ascii:utf-8",
10445  * the read string is converted from the first encoding (external encoding)
10446  * to the second encoding (internal encoding), then tagged with the second
10447  * encoding.
10448  *
10449  * If two arguments are specified, they must be encoding objects or encoding
10450  * names. Again, the first specifies the external encoding; the second
10451  * specifies the internal encoding.
10452  *
10453  * If the external encoding and the internal encoding are specified, the
10454  * optional +Hash+ argument can be used to adjust the conversion process. The
10455  * structure of this hash is explained in the +String#encode+ documentation.
10456  *
10457  * For example:
10458  *
10459  * ARGF.set_encoding('ascii') # Tag the input as US-ASCII text
10460  * ARGF.set_encoding(Encoding::UTF_8) # Tag the input as UTF-8 text
10461  * ARGF.set_encoding('utf-8','ascii') # Transcode the input from US-ASCII
10462  * # to UTF-8.
10463  */
10464 static VALUE
10466 {
10467  rb_io_t *fptr;
10468 
10469  if (!next_argv()) {
10470  rb_raise(rb_eArgError, "no stream to set encoding");
10471  }
10472  rb_io_set_encoding(argc, argv, ARGF.current_file);
10473  GetOpenFile(ARGF.current_file, fptr);
10474  ARGF.encs = fptr->encs;
10475  return argf;
10476 }
10477 
10478 /*
10479  * call-seq:
10480  * ARGF.tell -> Integer
10481  * ARGF.pos -> Integer
10482  *
10483  * Returns the current offset (in bytes) of the current file in +ARGF+.
10484  *
10485  * ARGF.pos #=> 0
10486  * ARGF.gets #=> "This is line one\n"
10487  * ARGF.pos #=> 17
10488  *
10489  */
10490 static VALUE
10492 {
10493  if (!next_argv()) {
10494  rb_raise(rb_eArgError, "no stream to tell");
10495  }
10496  ARGF_FORWARD(0, 0);
10497  return rb_io_tell(ARGF.current_file);
10498 }
10499 
10500 /*
10501  * call-seq:
10502  * ARGF.seek(amount, whence=IO::SEEK_SET) -> 0
10503  *
10504  * Seeks to offset _amount_ (an +Integer+) in the +ARGF+ stream according to
10505  * the value of _whence_. See +IO#seek+ for further details.
10506  */
10507 static VALUE
10509 {
10510  if (!next_argv()) {
10511  rb_raise(rb_eArgError, "no stream to seek");
10512  }
10513  ARGF_FORWARD(argc, argv);
10514  return rb_io_seek_m(argc, argv, ARGF.current_file);
10515 }
10516 
10517 /*
10518  * call-seq:
10519  * ARGF.pos = position -> Integer
10520  *
10521  * Seeks to the position given by _position_ (in bytes) in +ARGF+.
10522  *
10523  * For example:
10524  *
10525  * ARGF.pos = 17
10526  * ARGF.gets #=> "This is line two\n"
10527  */
10528 static VALUE
10530 {
10531  if (!next_argv()) {
10532  rb_raise(rb_eArgError, "no stream to set position");
10533  }
10534  ARGF_FORWARD(1, &offset);
10535  return rb_io_set_pos(ARGF.current_file, offset);
10536 }
10537 
10538 /*
10539  * call-seq:
10540  * ARGF.rewind -> 0
10541  *
10542  * Positions the current file to the beginning of input, resetting
10543  * +ARGF.lineno+ to zero.
10544  *
10545  * ARGF.readline #=> "This is line one\n"
10546  * ARGF.rewind #=> 0
10547  * ARGF.lineno #=> 0
10548  * ARGF.readline #=> "This is line one\n"
10549  */
10550 static VALUE
10552 {
10553  if (!next_argv()) {
10554  rb_raise(rb_eArgError, "no stream to rewind");
10555  }
10556  ARGF_FORWARD(0, 0);
10557  return rb_io_rewind(ARGF.current_file);
10558 }
10559 
10560 /*
10561  * call-seq:
10562  * ARGF.fileno -> fixnum
10563  * ARGF.to_i -> fixnum
10564  *
10565  * Returns an integer representing the numeric file descriptor for
10566  * the current file. Raises an +ArgumentError+ if there isn't a current file.
10567  *
10568  * ARGF.fileno #=> 3
10569  */
10570 static VALUE
10572 {
10573  if (!next_argv()) {
10574  rb_raise(rb_eArgError, "no stream");
10575  }
10576  ARGF_FORWARD(0, 0);
10577  return rb_io_fileno(ARGF.current_file);
10578 }
10579 
10580 /*
10581  * call-seq:
10582  * ARGF.to_io -> IO
10583  *
10584  * Returns an +IO+ object representing the current file. This will be a
10585  * +File+ object unless the current file is a stream such as STDIN.
10586  *
10587  * For example:
10588  *
10589  * ARGF.to_io #=> #<File:glark.txt>
10590  * ARGF.to_io #=> #<IO:<STDIN>>
10591  */
10592 static VALUE
10594 {
10595  next_argv();
10596  ARGF_FORWARD(0, 0);
10597  return ARGF.current_file;
10598 }
10599 
10600 /*
10601  * call-seq:
10602  * ARGF.eof? -> true or false
10603  * ARGF.eof -> true or false
10604  *
10605  * Returns true if the current file in +ARGF+ is at end of file, i.e. it has
10606  * no data to read. The stream must be opened for reading or an +IOError+
10607  * will be raised.
10608  *
10609  * $ echo "eof" | ruby argf.rb
10610  *
10611  * ARGF.eof? #=> false
10612  * 3.times { ARGF.readchar }
10613  * ARGF.eof? #=> false
10614  * ARGF.readchar #=> "\n"
10615  * ARGF.eof? #=> true
10616  */
10617 
10618 static VALUE
10620 {
10621  next_argv();
10622  if (RTEST(ARGF.current_file)) {
10623  if (ARGF.init_p == 0) return Qtrue;
10624  next_argv();
10625  ARGF_FORWARD(0, 0);
10626  if (rb_io_eof(ARGF.current_file)) {
10627  return Qtrue;
10628  }
10629  }
10630  return Qfalse;
10631 }
10632 
10633 /*
10634  * call-seq:
10635  * ARGF.read([length [, outbuf]]) -> string, outbuf, or nil
10636  *
10637  * Reads _length_ bytes from ARGF. The files named on the command line
10638  * are concatenated and treated as a single file by this method, so when
10639  * called without arguments the contents of this pseudo file are returned in
10640  * their entirety.
10641  *
10642  * _length_ must be a non-negative integer or nil. If it is a positive
10643  * integer, +read+ tries to read at most _length_ bytes. It returns nil
10644  * if an EOF was encountered before anything could be read. Fewer than
10645  * _length_ bytes may be returned if an EOF is encountered during the read.
10646  *
10647  * If _length_ is omitted or is _nil_, it reads until EOF. A String is
10648  * returned even if EOF is encountered before any data is read.
10649  *
10650  * If _length_ is zero, it returns _""_.
10651  *
10652  * If the optional _outbuf_ argument is present, it must reference a String,
10653  * which will receive the data.
10654  * The <i>outbuf</i> will contain only the received data after the method call
10655  * even if it is not empty at the beginning.
10656  *
10657  * For example:
10658  *
10659  * $ echo "small" > small.txt
10660  * $ echo "large" > large.txt
10661  * $ ./glark.rb small.txt large.txt
10662  *
10663  * ARGF.read #=> "small\nlarge"
10664  * ARGF.read(200) #=> "small\nlarge"
10665  * ARGF.read(2) #=> "sm"
10666  * ARGF.read(0) #=> ""
10667  *
10668  * Note that this method behaves like fread() function in C. If you need the
10669  * behavior like read(2) system call, consider +ARGF.readpartial+.
10670  */
10671 
10672 static VALUE
10674 {
10675  VALUE tmp, str, length;
10676  long len = 0;
10677 
10678  rb_scan_args(argc, argv, "02", &length, &str);
10679  if (!NIL_P(length)) {
10680  len = NUM2LONG(argv[0]);
10681  }
10682  if (!NIL_P(str)) {
10683  StringValue(str);
10684  rb_str_resize(str,0);
10685  argv[1] = Qnil;
10686  }
10687 
10688  retry:
10689  if (!next_argv()) {
10690  return str;
10691  }
10692  if (ARGF_GENERIC_INPUT_P()) {
10693  tmp = argf_forward(argc, argv, argf);
10694  }
10695  else {
10696  tmp = io_read(argc, argv, ARGF.current_file);
10697  }
10698  if (NIL_P(str)) str = tmp;
10699  else if (!NIL_P(tmp)) rb_str_append(str, tmp);
10700  if (NIL_P(tmp) || NIL_P(length)) {
10701  if (ARGF.next_p != -1) {
10702  argf_close(ARGF.current_file);
10703  ARGF.next_p = 1;
10704  goto retry;
10705  }
10706  }
10707  else if (argc >= 1) {
10708  if (RSTRING_LEN(str) < len) {
10709  len -= RSTRING_LEN(str);
10710  argv[0] = INT2NUM(len);
10711  goto retry;
10712  }
10713  }
10714  return str;
10715 }
10716 
10718  int argc;
10721 };
10722 
10723 static VALUE
10725 {
10726  struct argf_call_arg *p = (struct argf_call_arg *)arg;
10727  argf_forward(p->argc, p->argv, p->argf);
10728  return Qnil;
10729 }
10730 
10731 static VALUE argf_getpartial(int argc, VALUE *argv, VALUE argf, int nonblock);
10732 
10733 /*
10734  * call-seq:
10735  * ARGF.readpartial(maxlen) -> string
10736  * ARGF.readpartial(maxlen, outbuf) -> outbuf
10737  *
10738  * Reads at most _maxlen_ bytes from the ARGF stream. It blocks only if
10739  * +ARGF+ has no data immediately available. If the optional _outbuf_
10740  * argument is present, it must reference a String, which will receive the
10741  * data.
10742  * The <i>outbuf</i> will contain only the received data after the method call
10743  * even if it is not empty at the beginning.
10744  * It raises <code>EOFError</code> on end of file.
10745  *
10746  * +readpartial+ is designed for streams such as pipes, sockets, and ttys. It
10747  * blocks only when no data is immediately available. This means that it
10748  * blocks only when following all conditions hold:
10749  *
10750  * * The byte buffer in the +IO+ object is empty.
10751  * * The content of the stream is empty.
10752  * * The stream has not reached EOF.
10753  *
10754  * When +readpartial+ blocks, it waits for data or EOF. If some data is read,
10755  * +readpartial+ returns with the data. If EOF is reached, readpartial raises
10756  * an +EOFError+.
10757  *
10758  * When +readpartial+ doesn't block, it returns or raises immediately. If
10759  * the byte buffer is not empty, it returns the data in the buffer. Otherwise, if
10760  * the stream has some content, it returns the data in the stream. If the
10761  * stream reaches EOF an +EOFError+ is raised.
10762  */
10763 
10764 static VALUE
10766 {
10767  return argf_getpartial(argc, argv, argf, 0);
10768 }
10769 
10770 /*
10771  * call-seq:
10772  * ARGF.read_nonblock(maxlen) -> string
10773  * ARGF.read_nonblock(maxlen, outbuf) -> outbuf
10774  *
10775  * Reads at most _maxlen_ bytes from the ARGF stream in non-blocking mode.
10776  */
10777 
10778 static VALUE
10780 {
10781  return argf_getpartial(argc, argv, argf, 1);
10782 }
10783 
10784 static VALUE
10785 argf_getpartial(int argc, VALUE *argv, VALUE argf, int nonblock)
10786 {
10787  VALUE tmp, str, length;
10788 
10789  rb_scan_args(argc, argv, "11", &length, &str);
10790  if (!NIL_P(str)) {
10791  StringValue(str);
10792  argv[1] = str;
10793  }
10794 
10795  if (!next_argv()) {
10796  rb_str_resize(str, 0);
10797  rb_eof_error();
10798  }
10799  if (ARGF_GENERIC_INPUT_P()) {
10800  struct argf_call_arg arg;
10801  arg.argc = argc;
10802  arg.argv = argv;
10803  arg.argf = argf;
10804  tmp = rb_rescue2(argf_forward_call, (VALUE)&arg,
10806  }
10807  else {
10808  tmp = io_getpartial(argc, argv, ARGF.current_file, nonblock);
10809  }
10810  if (NIL_P(tmp)) {
10811  if (ARGF.next_p == -1) {
10812  rb_eof_error();
10813  }
10814  argf_close(ARGF.current_file);
10815  ARGF.next_p = 1;
10816  if (RARRAY_LEN(ARGF.argv) == 0)
10817  rb_eof_error();
10818  if (NIL_P(str))
10819  str = rb_str_new(NULL, 0);
10820  return str;
10821  }
10822  return tmp;
10823 }
10824 
10825 /*
10826  * call-seq:
10827  * ARGF.getc -> String or nil
10828  *
10829  * Reads the next character from +ARGF+ and returns it as a +String+. Returns
10830  * +nil+ at the end of the stream.
10831  *
10832  * +ARGF+ treats the files named on the command line as a single file created
10833  * by concatenating their contents. After returning the last character of the
10834  * first file, it returns the first character of the second file, and so on.
10835  *
10836  * For example:
10837  *
10838  * $ echo "foo" > file
10839  * $ ruby argf.rb file
10840  *
10841  * ARGF.getc #=> "f"
10842  * ARGF.getc #=> "o"
10843  * ARGF.getc #=> "o"
10844  * ARGF.getc #=> "\n"
10845  * ARGF.getc #=> nil
10846  * ARGF.getc #=> nil
10847  */
10848 static VALUE
10850 {
10851  VALUE ch;
10852 
10853  retry:
10854  if (!next_argv()) return Qnil;
10855  if (ARGF_GENERIC_INPUT_P()) {
10856  ch = rb_funcall3(ARGF.current_file, rb_intern("getc"), 0, 0);
10857  }
10858  else {
10859  ch = rb_io_getc(ARGF.current_file);
10860  }
10861  if (NIL_P(ch) && ARGF.next_p != -1) {
10862  argf_close(ARGF.current_file);
10863  ARGF.next_p = 1;
10864  goto retry;
10865  }
10866 
10867  return ch;
10868 }
10869 
10870 /*
10871  * call-seq:
10872  * ARGF.getbyte -> Fixnum or nil
10873  *
10874  * Gets the next 8-bit byte (0..255) from +ARGF+. Returns +nil+ if called at
10875  * the end of the stream.
10876  *
10877  * For example:
10878  *
10879  * $ echo "foo" > file
10880  * $ ruby argf.rb file
10881  *
10882  * ARGF.getbyte #=> 102
10883  * ARGF.getbyte #=> 111
10884  * ARGF.getbyte #=> 111
10885  * ARGF.getbyte #=> 10
10886  * ARGF.getbyte #=> nil
10887  */
10888 static VALUE
10890 {
10891  VALUE ch;
10892 
10893  retry:
10894  if (!next_argv()) return Qnil;
10895  if (!RB_TYPE_P(ARGF.current_file, T_FILE)) {
10896  ch = rb_funcall3(ARGF.current_file, rb_intern("getbyte"), 0, 0);
10897  }
10898  else {
10899  ch = rb_io_getbyte(ARGF.current_file);
10900  }
10901  if (NIL_P(ch) && ARGF.next_p != -1) {
10902  argf_close(ARGF.current_file);
10903  ARGF.next_p = 1;
10904  goto retry;
10905  }
10906 
10907  return ch;
10908 }
10909 
10910 /*
10911  * call-seq:
10912  * ARGF.readchar -> String or nil
10913  *
10914  * Reads the next character from +ARGF+ and returns it as a +String+. Raises
10915  * an +EOFError+ after the last character of the last file has been read.
10916  *
10917  * For example:
10918  *
10919  * $ echo "foo" > file
10920  * $ ruby argf.rb file
10921  *
10922  * ARGF.readchar #=> "f"
10923  * ARGF.readchar #=> "o"
10924  * ARGF.readchar #=> "o"
10925  * ARGF.readchar #=> "\n"
10926  * ARGF.readchar #=> end of file reached (EOFError)
10927  */
10928 static VALUE
10930 {
10931  VALUE ch;
10932 
10933  retry:
10934  if (!next_argv()) rb_eof_error();
10935  if (!RB_TYPE_P(ARGF.current_file, T_FILE)) {
10936  ch = rb_funcall3(ARGF.current_file, rb_intern("getc"), 0, 0);
10937  }
10938  else {
10939  ch = rb_io_getc(ARGF.current_file);
10940  }
10941  if (NIL_P(ch) && ARGF.next_p != -1) {
10942  argf_close(ARGF.current_file);
10943  ARGF.next_p = 1;
10944  goto retry;
10945  }
10946 
10947  return ch;
10948 }
10949 
10950 /*
10951  * call-seq:
10952  * ARGF.readbyte -> Fixnum
10953  *
10954  * Reads the next 8-bit byte from ARGF and returns it as a +Fixnum+. Raises
10955  * an +EOFError+ after the last byte of the last file has been read.
10956  *
10957  * For example:
10958  *
10959  * $ echo "foo" > file
10960  * $ ruby argf.rb file
10961  *
10962  * ARGF.readbyte #=> 102
10963  * ARGF.readbyte #=> 111
10964  * ARGF.readbyte #=> 111
10965  * ARGF.readbyte #=> 10
10966  * ARGF.readbyte #=> end of file reached (EOFError)
10967  */
10968 static VALUE
10970 {
10971  VALUE c;
10972 
10973  NEXT_ARGF_FORWARD(0, 0);
10974  c = argf_getbyte(argf);
10975  if (NIL_P(c)) {
10976  rb_eof_error();
10977  }
10978  return c;
10979 }
10980 
10981 /*
10982  * call-seq:
10983  * ARGF.each(sep=$/) {|line| block } -> ARGF
10984  * ARGF.each(sep=$/,limit) {|line| block } -> ARGF
10985  * ARGF.each(...) -> an_enumerator
10986  *
10987  * ARGF.each_line(sep=$/) {|line| block } -> ARGF
10988  * ARGF.each_line(sep=$/,limit) {|line| block } -> ARGF
10989  * ARGF.each_line(...) -> an_enumerator
10990  *
10991  * Returns an enumerator which iterates over each line (separated by _sep_,
10992  * which defaults to your platform's newline character) of each file in
10993  * +ARGV+. If a block is supplied, each line in turn will be yielded to the
10994  * block, otherwise an enumerator is returned.
10995  * The optional _limit_ argument is a +Fixnum+ specifying the maximum
10996  * length of each line; longer lines will be split according to this limit.
10997  *
10998  * This method allows you to treat the files supplied on the command line as
10999  * a single file consisting of the concatenation of each named file. After
11000  * the last line of the first file has been returned, the first line of the
11001  * second file is returned. The +ARGF.filename+ and +ARGF.lineno+ methods can
11002  * be used to determine the filename and line number, respectively, of the
11003  * current line.
11004  *
11005  * For example, the following code prints out each line of each named file
11006  * prefixed with its line number, displaying the filename once per file:
11007  *
11008  * ARGF.lines do |line|
11009  * puts ARGF.filename if ARGF.lineno == 1
11010  * puts "#{ARGF.lineno}: #{line}"
11011  * end
11012  */
11013 static VALUE
11015 {
11016  RETURN_ENUMERATOR(argf, argc, argv);
11017  for (;;) {
11018  if (!next_argv()) return argf;
11019  rb_block_call(ARGF.current_file, rb_intern("each_line"), argc, argv, 0, 0);
11020  ARGF.next_p = 1;
11021  }
11022 }
11023 
11024 /*
11025  * This is a deprecated alias for <code>each_line</code>.
11026  */
11027 
11028 static VALUE
11030 {
11031  rb_warn("ARGF#lines is deprecated; use #each_line instead");
11032  if (!rb_block_given_p())
11033  return rb_enumeratorize(argf, ID2SYM(rb_intern("each_line")), argc, argv);
11034  return argf_each_line(argc, argv, argf);
11035 }
11036 
11037 /*
11038  * call-seq:
11039  * ARGF.bytes {|byte| block } -> ARGF
11040  * ARGF.bytes -> an_enumerator
11041  *
11042  * ARGF.each_byte {|byte| block } -> ARGF
11043  * ARGF.each_byte -> an_enumerator
11044  *
11045  * Iterates over each byte of each file in +ARGV+.
11046  * A byte is returned as a +Fixnum+ in the range 0..255.
11047  *
11048  * This method allows you to treat the files supplied on the command line as
11049  * a single file consisting of the concatenation of each named file. After
11050  * the last byte of the first file has been returned, the first byte of the
11051  * second file is returned. The +ARGF.filename+ method can be used to
11052  * determine the filename of the current byte.
11053  *
11054  * If no block is given, an enumerator is returned instead.
11055  *
11056  * For example:
11057  *
11058  * ARGF.bytes.to_a #=> [35, 32, ... 95, 10]
11059  *
11060  */
11061 static VALUE
11063 {
11064  RETURN_ENUMERATOR(argf, 0, 0);
11065  for (;;) {
11066  if (!next_argv()) return argf;
11067  rb_block_call(ARGF.current_file, rb_intern("each_byte"), 0, 0, 0, 0);
11068  ARGF.next_p = 1;
11069  }
11070 }
11071 
11072 /*
11073  * This is a deprecated alias for <code>each_byte</code>.
11074  */
11075 
11076 static VALUE
11078 {
11079  rb_warn("ARGF#bytes is deprecated; use #each_byte instead");
11080  if (!rb_block_given_p())
11081  return rb_enumeratorize(argf, ID2SYM(rb_intern("each_byte")), 0, 0);
11082  return argf_each_byte(argf);
11083 }
11084 
11085 /*
11086  * call-seq:
11087  * ARGF.each_char {|char| block } -> ARGF
11088  * ARGF.each_char -> an_enumerator
11089  *
11090  * Iterates over each character of each file in +ARGF+.
11091  *
11092  * This method allows you to treat the files supplied on the command line as
11093  * a single file consisting of the concatenation of each named file. After
11094  * the last character of the first file has been returned, the first
11095  * character of the second file is returned. The +ARGF.filename+ method can
11096  * be used to determine the name of the file in which the current character
11097  * appears.
11098  *
11099  * If no block is given, an enumerator is returned instead.
11100  */
11101 static VALUE
11103 {
11104  RETURN_ENUMERATOR(argf, 0, 0);
11105  for (;;) {
11106  if (!next_argv()) return argf;
11107  rb_block_call(ARGF.current_file, rb_intern("each_char"), 0, 0, 0, 0);
11108  ARGF.next_p = 1;
11109  }
11110 }
11111 
11112 /*
11113  * This is a deprecated alias for <code>each_char</code>.
11114  */
11115 
11116 static VALUE
11118 {
11119  rb_warn("ARGF#chars is deprecated; use #each_char instead");
11120  if (!rb_block_given_p())
11121  return rb_enumeratorize(argf, ID2SYM(rb_intern("each_char")), 0, 0);
11122  return argf_each_char(argf);
11123 }
11124 
11125 /*
11126  * call-seq:
11127  * ARGF.each_codepoint {|codepoint| block } -> ARGF
11128  * ARGF.each_codepoint -> an_enumerator
11129  *
11130  * Iterates over each codepoint of each file in +ARGF+.
11131  *
11132  * This method allows you to treat the files supplied on the command line as
11133  * a single file consisting of the concatenation of each named file. After
11134  * the last codepoint of the first file has been returned, the first
11135  * codepoint of the second file is returned. The +ARGF.filename+ method can
11136  * be used to determine the name of the file in which the current codepoint
11137  * appears.
11138  *
11139  * If no block is given, an enumerator is returned instead.
11140  */
11141 static VALUE
11143 {
11144  RETURN_ENUMERATOR(argf, 0, 0);
11145  for (;;) {
11146  if (!next_argv()) return argf;
11147  rb_block_call(ARGF.current_file, rb_intern("each_codepoint"), 0, 0, 0, 0);
11148  ARGF.next_p = 1;
11149  }
11150 }
11151 
11152 /*
11153  * This is a deprecated alias for <code>each_codepoint</code>.
11154  */
11155 
11156 static VALUE
11158 {
11159  rb_warn("ARGF#codepoints is deprecated; use #each_codepoint instead");
11160  if (!rb_block_given_p())
11161  return rb_enumeratorize(argf, ID2SYM(rb_intern("each_codepoint")), 0, 0);
11162  return argf_each_codepoint(argf);
11163 }
11164 
11165 /*
11166  * call-seq:
11167  * ARGF.filename -> String
11168  * ARGF.path -> String
11169  *
11170  * Returns the current filename. "-" is returned when the current file is
11171  * STDIN.
11172  *
11173  * For example:
11174  *
11175  * $ echo "foo" > foo
11176  * $ echo "bar" > bar
11177  * $ echo "glark" > glark
11178  *
11179  * $ ruby argf.rb foo bar glark
11180  *
11181  * ARGF.filename #=> "foo"
11182  * ARGF.read(5) #=> "foo\nb"
11183  * ARGF.filename #=> "bar"
11184  * ARGF.skip
11185  * ARGF.filename #=> "glark"
11186  */
11187 static VALUE
11189 {
11190  next_argv();
11191  return ARGF.filename;
11192 }
11193 
11194 static VALUE
11196 {
11197  return argf_filename(*var);
11198 }
11199 
11200 /*
11201  * call-seq:
11202  * ARGF.file -> IO or File object
11203  *
11204  * Returns the current file as an +IO+ or +File+ object. #<IO:<STDIN>> is
11205  * returned when the current file is STDIN.
11206  *
11207  * For example:
11208  *
11209  * $ echo "foo" > foo
11210  * $ echo "bar" > bar
11211  *
11212  * $ ruby argf.rb foo bar
11213  *
11214  * ARGF.file #=> #<File:foo>
11215  * ARGF.read(5) #=> "foo\nb"
11216  * ARGF.file #=> #<File:bar>
11217  */
11218 static VALUE
11220 {
11221  next_argv();
11222  return ARGF.current_file;
11223 }
11224 
11225 /*
11226  * call-seq:
11227  * ARGF.binmode -> ARGF
11228  *
11229  * Puts +ARGF+ into binary mode. Once a stream is in binary mode, it cannot
11230  * be reset to non-binary mode. This option has the following effects:
11231  *
11232  * * Newline conversion is disabled.
11233  * * Encoding conversion is disabled.
11234  * * Content is treated as ASCII-8BIT.
11235  */
11236 static VALUE
11238 {
11239  ARGF.binmode = 1;
11240  next_argv();
11241  ARGF_FORWARD(0, 0);
11242  rb_io_ascii8bit_binmode(ARGF.current_file);
11243  return argf;
11244 }
11245 
11246 /*
11247  * call-seq:
11248  * ARGF.binmode? -> true or false
11249  *
11250  * Returns true if +ARGF+ is being read in binary mode; false otherwise. (To
11251  * enable binary mode use +ARGF.binmode+.
11252  *
11253  * For example:
11254  *
11255  * ARGF.binmode? #=> false
11256  * ARGF.binmode
11257  * ARGF.binmode? #=> true
11258  */
11259 static VALUE
11261 {
11262  return ARGF.binmode ? Qtrue : Qfalse;
11263 }
11264 
11265 /*
11266  * call-seq:
11267  * ARGF.skip -> ARGF
11268  *
11269  * Sets the current file to the next file in ARGV. If there aren't any more
11270  * files it has no effect.
11271  *
11272  * For example:
11273  *
11274  * $ ruby argf.rb foo bar
11275  * ARGF.filename #=> "foo"
11276  * ARGF.skip
11277  * ARGF.filename #=> "bar"
11278  */
11279 static VALUE
11281 {
11282  if (ARGF.init_p && ARGF.next_p == 0) {
11283  argf_close(ARGF.current_file);
11284  ARGF.next_p = 1;
11285  }
11286  return argf;
11287 }
11288 
11289 /*
11290  * call-seq:
11291  * ARGF.close -> ARGF
11292  *
11293  * Closes the current file and skips to the next in the stream. Trying to
11294  * close a file that has already been closed causes an +IOError+ to be
11295  * raised.
11296  *
11297  * For example:
11298  *
11299  * $ ruby argf.rb foo bar
11300  *
11301  * ARGF.filename #=> "foo"
11302  * ARGF.close
11303  * ARGF.filename #=> "bar"
11304  * ARGF.close
11305  * ARGF.close #=> closed stream (IOError)
11306  */
11307 static VALUE
11309 {
11310  next_argv();
11311  argf_close(ARGF.current_file);
11312  if (ARGF.next_p != -1) {
11313  ARGF.next_p = 1;
11314  }
11315  ARGF.lineno = 0;
11316  return argf;
11317 }
11318 
11319 /*
11320  * call-seq:
11321  * ARGF.closed? -> true or false
11322  *
11323  * Returns _true_ if the current file has been closed; _false_ otherwise. Use
11324  * +ARGF.close+ to actually close the current file.
11325  */
11326 static VALUE
11328 {
11329  next_argv();
11330  ARGF_FORWARD(0, 0);
11331  return rb_io_closed(ARGF.current_file);
11332 }
11333 
11334 /*
11335  * call-seq:
11336  * ARGF.to_s -> String
11337  *
11338  * Returns "ARGF".
11339  */
11340 static VALUE
11342 {
11343  return rb_str_new2("ARGF");
11344 }
11345 
11346 /*
11347  * call-seq:
11348  * ARGF.inplace_mode -> String
11349  *
11350  * Returns the file extension appended to the names of modified files under
11351  * inplace-edit mode. This value can be set using +ARGF.inplace_mode=+ or
11352  * passing the +-i+ switch to the Ruby binary.
11353  */
11354 static VALUE
11356 {
11357  if (!ARGF.inplace) return Qnil;
11358  return rb_str_new2(ARGF.inplace);
11359 }
11360 
11361 static VALUE
11362 opt_i_get(ID id, VALUE *var)
11363 {
11364  return argf_inplace_mode_get(*var);
11365 }
11366 
11367 /*
11368  * call-seq:
11369  * ARGF.inplace_mode = ext -> ARGF
11370  *
11371  * Sets the filename extension for inplace editing mode to the given String.
11372  * Each file being edited has this value appended to its filename. The
11373  * modified file is saved under this new name.
11374  *
11375  * For example:
11376  *
11377  * $ ruby argf.rb file.txt
11378  *
11379  * ARGF.inplace_mode = '.bak'
11380  * ARGF.lines do |line|
11381  * print line.sub("foo","bar")
11382  * end
11383  *
11384  * Each line of _file.txt_ has the first occurrence of "foo" replaced with
11385  * "bar", then the new line is written out to _file.txt.bak_.
11386  */
11387 static VALUE
11389 {
11390  if (rb_safe_level() >= 1 && OBJ_TAINTED(val))
11392 
11393  if (!RTEST(val)) {
11394  if (ARGF.inplace) free(ARGF.inplace);
11395  ARGF.inplace = 0;
11396  }
11397  else {
11398  StringValue(val);
11399  if (ARGF.inplace) free(ARGF.inplace);
11400  ARGF.inplace = 0;
11401  ARGF.inplace = strdup(RSTRING_PTR(val));
11402  }
11403  return argf;
11404 }
11405 
11406 static void
11408 {
11409  argf_inplace_mode_set(*var, val);
11410 }
11411 
11412 const char *
11414 {
11415  return ARGF.inplace;
11416 }
11417 
11418 void
11419 ruby_set_inplace_mode(const char *suffix)
11420 {
11421  if (ARGF.inplace) free(ARGF.inplace);
11422  ARGF.inplace = 0;
11423  if (suffix) ARGF.inplace = strdup(suffix);
11424 }
11425 
11426 /*
11427  * call-seq:
11428  * ARGF.argv -> ARGV
11429  *
11430  * Returns the +ARGV+ array, which contains the arguments passed to your
11431  * script, one per element.
11432  *
11433  * For example:
11434  *
11435  * $ ruby argf.rb -v glark.txt
11436  *
11437  * ARGF.argv #=> ["-v", "glark.txt"]
11438  *
11439  */
11440 static VALUE
11442 {
11443  return ARGF.argv;
11444 }
11445 
11446 static VALUE
11448 {
11449  return argf_argv(*var);
11450 }
11451 
11452 VALUE
11454 {
11455  return ARGF.argv;
11456 }
11457 
11458 /*
11459  * call-seq:
11460  * ARGF.to_write_io -> io
11461  *
11462  * Returns IO instance tied to _ARGF_ for writing if inplace mode is
11463  * enabled.
11464  */
11465 static VALUE
11467 {
11468  if (!RTEST(ARGF.current_file)) {
11469  rb_raise(rb_eIOError, "not opened for writing");
11470  }
11471  return GetWriteIO(ARGF.current_file);
11472 }
11473 
11474 /*
11475  * call-seq:
11476  * ARGF.write(string) -> integer
11477  *
11478  * Writes _string_ if inplace mode.
11479  */
11480 static VALUE
11482 {
11483  return rb_io_write(argf_write_io(argf), str);
11484 }
11485 
11486 /*
11487  * Document-class: IOError
11488  *
11489  * Raised when an IO operation fails.
11490  *
11491  * File.open("/etc/hosts") {|f| f << "example"}
11492  * #=> IOError: not opened for writing
11493  *
11494  * File.open("/etc/hosts") {|f| f.close; f.read }
11495  * #=> IOError: closed stream
11496  *
11497  * Note that some IO failures raise +SystemCallError+s and these are not
11498  * subclasses of IOError:
11499  *
11500  * File.open("does/not/exist")
11501  * #=> Errno::ENOENT: No such file or directory - does/not/exist
11502  */
11503 
11504 /*
11505  * Document-class: EOFError
11506  *
11507  * Raised by some IO operations when reaching the end of file. Many IO
11508  * methods exist in two forms,
11509  *
11510  * one that returns +nil+ when the end of file is reached, the other
11511  * raises EOFError +EOFError+.
11512  *
11513  * +EOFError+ is a subclass of +IOError+.
11514  *
11515  * file = File.open("/etc/hosts")
11516  * file.read
11517  * file.gets #=> nil
11518  * file.readline #=> EOFError: end of file reached
11519  */
11520 
11521 /*
11522  * Document-class: ARGF
11523  *
11524  * +ARGF+ is a stream designed for use in scripts that process files given as
11525  * command-line arguments or passed in via STDIN.
11526  *
11527  * The arguments passed to your script are stored in the +ARGV+ Array, one
11528  * argument per element. +ARGF+ assumes that any arguments that aren't
11529  * filenames have been removed from +ARGV+. For example:
11530  *
11531  * $ ruby argf.rb --verbose file1 file2
11532  *
11533  * ARGV #=> ["--verbose", "file1", "file2"]
11534  * option = ARGV.shift #=> "--verbose"
11535  * ARGV #=> ["file1", "file2"]
11536  *
11537  * You can now use +ARGF+ to work with a concatenation of each of these named
11538  * files. For instance, +ARGF.read+ will return the contents of _file1_
11539  * followed by the contents of _file2_.
11540  *
11541  * After a file in +ARGV+ has been read +ARGF+ removes it from the Array.
11542  * Thus, after all files have been read +ARGV+ will be empty.
11543  *
11544  * You can manipulate +ARGV+ yourself to control what +ARGF+ operates on. If
11545  * you remove a file from +ARGV+, it is ignored by +ARGF+; if you add files to
11546  * +ARGV+, they are treated as if they were named on the command line. For
11547  * example:
11548  *
11549  * ARGV.replace ["file1"]
11550  * ARGF.readlines # Returns the contents of file1 as an Array
11551  * ARGV #=> []
11552  * ARGV.replace ["file2", "file3"]
11553  * ARGF.read # Returns the contents of file2 and file3
11554  *
11555  * If +ARGV+ is empty, +ARGF+ acts as if it contained STDIN, i.e. the data
11556  * piped to your script. For example:
11557  *
11558  * $ echo "glark" | ruby -e 'p ARGF.read'
11559  * "glark\n"
11560  */
11561 
11562 /*
11563  * The IO class is the basis for all input and output in Ruby.
11564  * An I/O stream may be <em>duplexed</em> (that is, bidirectional), and
11565  * so may use more than one native operating system stream.
11566  *
11567  * Many of the examples in this section use the File class, the only standard
11568  * subclass of IO. The two classes are closely associated. Like the File
11569  * class, the Socket library subclasses from IO (such as TCPSocket or
11570  * UDPSocket).
11571  *
11572  * The Kernel#open method can create an IO (or File) object for these types
11573  * of arguments:
11574  *
11575  * * A plain string represents a filename suitable for the underlying
11576  * operating system.
11577  *
11578  * * A string starting with <code>"|"</code> indicates a subprocess.
11579  * The remainder of the string following the <code>"|"</code> is
11580  * invoked as a process with appropriate input/output channels
11581  * connected to it.
11582  *
11583  * * A string equal to <code>"|-"</code> will create another Ruby
11584  * instance as a subprocess.
11585  *
11586  * The IO may be opened with different file modes (read-only, write-only) and
11587  * encodings for proper conversion. See IO.new for these options. See
11588  * Kernel#open for details of the various command formats described above.
11589  *
11590  * IO.popen, the Open3 library, or Process#spawn may also be used to
11591  * communicate with subprocesses through an IO.
11592  *
11593  * Ruby will convert pathnames between different operating system
11594  * conventions if possible. For instance, on a Windows system the
11595  * filename <code>"/gumby/ruby/test.rb"</code> will be opened as
11596  * <code>"\gumby\ruby\test.rb"</code>. When specifying a Windows-style
11597  * filename in a Ruby string, remember to escape the backslashes:
11598  *
11599  * "c:\\gumby\\ruby\\test.rb"
11600  *
11601  * Our examples here will use the Unix-style forward slashes;
11602  * File::ALT_SEPARATOR can be used to get the platform-specific separator
11603  * character.
11604  *
11605  * The global constant ARGF (also accessible as $<) provides an
11606  * IO-like stream which allows access to all files mentioned on the
11607  * command line (or STDIN if no files are mentioned). ARGF#path and its alias
11608  * ARGF#filename are provided to access the name of the file currently being
11609  * read.
11610  *
11611  * == io/console
11612  *
11613  * The io/console extension provides methods for interacting with the
11614  * console. The console can be accessed from IO.console or the standard
11615  * input/output/error IO objects.
11616  *
11617  * Requiring io/console adds the following methods:
11618  *
11619  * * IO::console
11620  * * IO#raw
11621  * * IO#raw!
11622  * * IO#cooked
11623  * * IO#cooked!
11624  * * IO#getch
11625  * * IO#echo=
11626  * * IO#echo?
11627  * * IO#noecho
11628  * * IO#winsize
11629  * * IO#winsize=
11630  * * IO#iflush
11631  * * IO#ioflush
11632  * * IO#oflush
11633  *
11634  * Example:
11635  *
11636  * require 'io/console'
11637  * rows, columns = $stdin.winsize
11638  * puts "Your screen is #{columns} wide and #{rows} tall"
11639  */
11640 
11641 void
11642 Init_IO(void)
11643 {
11644 #undef rb_intern
11645 #define rb_intern(str) rb_intern_const(str)
11646 
11647  VALUE rb_cARGF;
11648 #ifdef __CYGWIN__
11649 #include <sys/cygwin.h>
11650  static struct __cygwin_perfile pf[] =
11651  {
11652  {"", O_RDONLY | O_BINARY},
11653  {"", O_WRONLY | O_BINARY},
11654  {"", O_RDWR | O_BINARY},
11655  {"", O_APPEND | O_BINARY},
11656  {NULL, 0}
11657  };
11658  cygwin_internal(CW_PERFILE, pf);
11659 #endif
11660 
11662  rb_eEOFError = rb_define_class("EOFError", rb_eIOError);
11663 
11664  id_write = rb_intern("write");
11665  id_read = rb_intern("read");
11666  id_getc = rb_intern("getc");
11667  id_flush = rb_intern("flush");
11668  id_readpartial = rb_intern("readpartial");
11669  id_set_encoding = rb_intern("set_encoding");
11670 
11671  rb_define_global_function("syscall", rb_f_syscall, -1);
11672 
11673  rb_define_global_function("open", rb_f_open, -1);
11674  rb_define_global_function("printf", rb_f_printf, -1);
11675  rb_define_global_function("print", rb_f_print, -1);
11677  rb_define_global_function("puts", rb_f_puts, -1);
11678  rb_define_global_function("gets", rb_f_gets, -1);
11679  rb_define_global_function("readline", rb_f_readline, -1);
11680  rb_define_global_function("select", rb_f_select, -1);
11681 
11682  rb_define_global_function("readlines", rb_f_readlines, -1);
11683 
11685 
11687  rb_define_method(rb_mKernel, "display", rb_obj_display, -1);
11688 
11691 
11692  rb_mWaitReadable = rb_define_module_under(rb_cIO, "WaitReadable");
11693  rb_mWaitWritable = rb_define_module_under(rb_cIO, "WaitWritable");
11694 
11695 #if 0
11696  /* This is necessary only for forcing rdoc handle File::open */
11698 #endif
11699 
11716 
11717  rb_define_method(rb_cIO, "initialize", rb_io_initialize, -1);
11718 
11719  rb_output_fs = Qnil;
11721 
11724  rb_output_rs = Qnil;
11725  OBJ_FREEZE(rb_default_rs); /* avoid modifying RS_default */
11729 
11731 
11732  rb_define_method(rb_cIO, "initialize_copy", rb_io_init_copy, 1);
11733  rb_define_method(rb_cIO, "reopen", rb_io_reopen, -1);
11734 
11735  rb_define_method(rb_cIO, "print", rb_io_print, -1);
11736  rb_define_method(rb_cIO, "putc", rb_io_putc, 1);
11737  rb_define_method(rb_cIO, "puts", rb_io_puts, -1);
11738  rb_define_method(rb_cIO, "printf", rb_io_printf, -1);
11739 
11740  rb_define_method(rb_cIO, "each", rb_io_each_line, -1);
11741  rb_define_method(rb_cIO, "each_line", rb_io_each_line, -1);
11742  rb_define_method(rb_cIO, "each_byte", rb_io_each_byte, 0);
11743  rb_define_method(rb_cIO, "each_char", rb_io_each_char, 0);
11744  rb_define_method(rb_cIO, "each_codepoint", rb_io_each_codepoint, 0);
11745  rb_define_method(rb_cIO, "lines", rb_io_lines, -1);
11746  rb_define_method(rb_cIO, "bytes", rb_io_bytes, 0);
11747  rb_define_method(rb_cIO, "chars", rb_io_chars, 0);
11748  rb_define_method(rb_cIO, "codepoints", rb_io_codepoints, 0);
11749 
11750  rb_define_method(rb_cIO, "syswrite", rb_io_syswrite, 1);
11751  rb_define_method(rb_cIO, "sysread", rb_io_sysread, -1);
11752 
11753  rb_define_method(rb_cIO, "fileno", rb_io_fileno, 0);
11754  rb_define_alias(rb_cIO, "to_i", "fileno");
11755  rb_define_method(rb_cIO, "to_io", rb_io_to_io, 0);
11756 
11757  rb_define_method(rb_cIO, "fsync", rb_io_fsync, 0);
11758  rb_define_method(rb_cIO, "fdatasync", rb_io_fdatasync, 0);
11759  rb_define_method(rb_cIO, "sync", rb_io_sync, 0);
11760  rb_define_method(rb_cIO, "sync=", rb_io_set_sync, 1);
11761 
11762  rb_define_method(rb_cIO, "lineno", rb_io_lineno, 0);
11763  rb_define_method(rb_cIO, "lineno=", rb_io_set_lineno, 1);
11764 
11765  rb_define_method(rb_cIO, "readlines", rb_io_readlines, -1);
11766 
11767  rb_define_method(rb_cIO, "read_nonblock", io_read_nonblock, -1);
11768  rb_define_method(rb_cIO, "write_nonblock", rb_io_write_nonblock, 1);
11769  rb_define_method(rb_cIO, "readpartial", io_readpartial, -1);
11770  rb_define_method(rb_cIO, "read", io_read, -1);
11771  rb_define_method(rb_cIO, "write", io_write_m, 1);
11772  rb_define_method(rb_cIO, "gets", rb_io_gets_m, -1);
11773  rb_define_method(rb_cIO, "readline", rb_io_readline, -1);
11774  rb_define_method(rb_cIO, "getc", rb_io_getc, 0);
11775  rb_define_method(rb_cIO, "getbyte", rb_io_getbyte, 0);
11776  rb_define_method(rb_cIO, "readchar", rb_io_readchar, 0);
11777  rb_define_method(rb_cIO, "readbyte", rb_io_readbyte, 0);
11778  rb_define_method(rb_cIO, "ungetbyte",rb_io_ungetbyte, 1);
11779  rb_define_method(rb_cIO, "ungetc",rb_io_ungetc, 1);
11781  rb_define_method(rb_cIO, "flush", rb_io_flush, 0);
11782  rb_define_method(rb_cIO, "tell", rb_io_tell, 0);
11783  rb_define_method(rb_cIO, "seek", rb_io_seek_m, -1);
11784  rb_define_const(rb_cIO, "SEEK_SET", INT2FIX(SEEK_SET));
11785  rb_define_const(rb_cIO, "SEEK_CUR", INT2FIX(SEEK_CUR));
11786  rb_define_const(rb_cIO, "SEEK_END", INT2FIX(SEEK_END));
11787  rb_define_method(rb_cIO, "rewind", rb_io_rewind, 0);
11788  rb_define_method(rb_cIO, "pos", rb_io_tell, 0);
11789  rb_define_method(rb_cIO, "pos=", rb_io_set_pos, 1);
11790  rb_define_method(rb_cIO, "eof", rb_io_eof, 0);
11791  rb_define_method(rb_cIO, "eof?", rb_io_eof, 0);
11792 
11793  rb_define_method(rb_cIO, "close_on_exec?", rb_io_close_on_exec_p, 0);
11794  rb_define_method(rb_cIO, "close_on_exec=", rb_io_set_close_on_exec, 1);
11795 
11796  rb_define_method(rb_cIO, "close", rb_io_close_m, 0);
11797  rb_define_method(rb_cIO, "closed?", rb_io_closed, 0);
11798  rb_define_method(rb_cIO, "close_read", rb_io_close_read, 0);
11799  rb_define_method(rb_cIO, "close_write", rb_io_close_write, 0);
11800 
11801  rb_define_method(rb_cIO, "isatty", rb_io_isatty, 0);
11802  rb_define_method(rb_cIO, "tty?", rb_io_isatty, 0);
11803  rb_define_method(rb_cIO, "binmode", rb_io_binmode_m, 0);
11804  rb_define_method(rb_cIO, "binmode?", rb_io_binmode_p, 0);
11805  rb_define_method(rb_cIO, "sysseek", rb_io_sysseek, -1);
11806  rb_define_method(rb_cIO, "advise", rb_io_advise, -1);
11807 
11808  rb_define_method(rb_cIO, "ioctl", rb_io_ioctl, -1);
11809  rb_define_method(rb_cIO, "fcntl", rb_io_fcntl, -1);
11810  rb_define_method(rb_cIO, "pid", rb_io_pid, 0);
11811  rb_define_method(rb_cIO, "inspect", rb_io_inspect, 0);
11812 
11813  rb_define_method(rb_cIO, "external_encoding", rb_io_external_encoding, 0);
11814  rb_define_method(rb_cIO, "internal_encoding", rb_io_internal_encoding, 0);
11815  rb_define_method(rb_cIO, "set_encoding", rb_io_set_encoding, -1);
11816 
11817  rb_define_method(rb_cIO, "autoclose?", rb_io_autoclose_p, 0);
11818  rb_define_method(rb_cIO, "autoclose=", rb_io_set_autoclose, 1);
11819 
11820  rb_define_variable("$stdin", &rb_stdin);
11821  rb_stdin = prep_stdio(stdin, FMODE_READABLE, rb_cIO, "<STDIN>");
11823  rb_stdout = prep_stdio(stdout, FMODE_WRITABLE, rb_cIO, "<STDOUT>");
11825  rb_stderr = prep_stdio(stderr, FMODE_WRITABLE|FMODE_SYNC, rb_cIO, "<STDERR>");
11829 
11830  /* Holds the original stdin */
11831  rb_define_global_const("STDIN", rb_stdin);
11832  /* Holds the original stdout */
11833  rb_define_global_const("STDOUT", rb_stdout);
11834  /* Holds the original stderr */
11835  rb_define_global_const("STDERR", rb_stderr);
11836 
11837 #if 0
11838  /* Hack to get rdoc to regard ARGF as a class: */
11839  rb_cARGF = rb_define_class("ARGF", rb_cObject);
11840 #endif
11841 
11842  rb_cARGF = rb_class_new(rb_cObject);
11843  rb_set_class_path(rb_cARGF, rb_cObject, "ARGF.class");
11844  rb_define_alloc_func(rb_cARGF, argf_alloc);
11845 
11846  rb_include_module(rb_cARGF, rb_mEnumerable);
11847 
11848  rb_define_method(rb_cARGF, "initialize", argf_initialize, -2);
11849  rb_define_method(rb_cARGF, "initialize_copy", argf_initialize_copy, 1);
11850  rb_define_method(rb_cARGF, "to_s", argf_to_s, 0);
11851  rb_define_alias(rb_cARGF, "inspect", "to_s");
11852  rb_define_method(rb_cARGF, "argv", argf_argv, 0);
11853 
11854  rb_define_method(rb_cARGF, "fileno", argf_fileno, 0);
11855  rb_define_method(rb_cARGF, "to_i", argf_fileno, 0);
11856  rb_define_method(rb_cARGF, "to_io", argf_to_io, 0);
11857  rb_define_method(rb_cARGF, "to_write_io", argf_write_io, 0);
11858  rb_define_method(rb_cARGF, "each", argf_each_line, -1);
11859  rb_define_method(rb_cARGF, "each_line", argf_each_line, -1);
11860  rb_define_method(rb_cARGF, "each_byte", argf_each_byte, 0);
11861  rb_define_method(rb_cARGF, "each_char", argf_each_char, 0);
11862  rb_define_method(rb_cARGF, "each_codepoint", argf_each_codepoint, 0);
11863  rb_define_method(rb_cARGF, "lines", argf_lines, -1);
11864  rb_define_method(rb_cARGF, "bytes", argf_bytes, 0);
11865  rb_define_method(rb_cARGF, "chars", argf_chars, 0);
11866  rb_define_method(rb_cARGF, "codepoints", argf_codepoints, 0);
11867 
11868  rb_define_method(rb_cARGF, "read", argf_read, -1);
11869  rb_define_method(rb_cARGF, "readpartial", argf_readpartial, -1);
11870  rb_define_method(rb_cARGF, "read_nonblock", argf_read_nonblock, -1);
11871  rb_define_method(rb_cARGF, "readlines", argf_readlines, -1);
11872  rb_define_method(rb_cARGF, "to_a", argf_readlines, -1);
11873  rb_define_method(rb_cARGF, "gets", argf_gets, -1);
11874  rb_define_method(rb_cARGF, "readline", argf_readline, -1);
11875  rb_define_method(rb_cARGF, "getc", argf_getc, 0);
11876  rb_define_method(rb_cARGF, "getbyte", argf_getbyte, 0);
11877  rb_define_method(rb_cARGF, "readchar", argf_readchar, 0);
11878  rb_define_method(rb_cARGF, "readbyte", argf_readbyte, 0);
11879  rb_define_method(rb_cARGF, "tell", argf_tell, 0);
11880  rb_define_method(rb_cARGF, "seek", argf_seek_m, -1);
11881  rb_define_method(rb_cARGF, "rewind", argf_rewind, 0);
11882  rb_define_method(rb_cARGF, "pos", argf_tell, 0);
11883  rb_define_method(rb_cARGF, "pos=", argf_set_pos, 1);
11884  rb_define_method(rb_cARGF, "eof", argf_eof, 0);
11885  rb_define_method(rb_cARGF, "eof?", argf_eof, 0);
11886  rb_define_method(rb_cARGF, "binmode", argf_binmode_m, 0);
11887  rb_define_method(rb_cARGF, "binmode?", argf_binmode_p, 0);
11888 
11889  rb_define_method(rb_cARGF, "write", argf_write, 1);
11890  rb_define_method(rb_cARGF, "print", rb_io_print, -1);
11891  rb_define_method(rb_cARGF, "putc", rb_io_putc, 1);
11892  rb_define_method(rb_cARGF, "puts", rb_io_puts, -1);
11893  rb_define_method(rb_cARGF, "printf", rb_io_printf, -1);
11894 
11895  rb_define_method(rb_cARGF, "filename", argf_filename, 0);
11896  rb_define_method(rb_cARGF, "path", argf_filename, 0);
11897  rb_define_method(rb_cARGF, "file", argf_file, 0);
11898  rb_define_method(rb_cARGF, "skip", argf_skip, 0);
11899  rb_define_method(rb_cARGF, "close", argf_close_m, 0);
11900  rb_define_method(rb_cARGF, "closed?", argf_closed, 0);
11901 
11902  rb_define_method(rb_cARGF, "lineno", argf_lineno, 0);
11903  rb_define_method(rb_cARGF, "lineno=", argf_set_lineno, 1);
11904 
11905  rb_define_method(rb_cARGF, "inplace_mode", argf_inplace_mode_get, 0);
11906  rb_define_method(rb_cARGF, "inplace_mode=", argf_inplace_mode_set, 1);
11907 
11908  rb_define_method(rb_cARGF, "external_encoding", argf_external_encoding, 0);
11909  rb_define_method(rb_cARGF, "internal_encoding", argf_internal_encoding, 0);
11910  rb_define_method(rb_cARGF, "set_encoding", argf_set_encoding, -1);
11911 
11912  argf = rb_class_new_instance(0, 0, rb_cARGF);
11913 
11915  /*
11916  * ARGF is a stream designed for use in scripts that process files given
11917  * as command-line arguments or passed in via STDIN.
11918  *
11919  * See ARGF (the class) for more details.
11920  */
11921  rb_define_global_const("ARGF", argf);
11922 
11925  ARGF.filename = rb_str_new2("-");
11926 
11929 
11930 #if defined (_WIN32) || defined(__CYGWIN__)
11931  atexit(pipe_atexit);
11932 #endif
11933 
11934  Init_File();
11935 
11936  rb_define_method(rb_cFile, "initialize", rb_file_initialize, -1);
11937 
11938  sym_mode = ID2SYM(rb_intern("mode"));
11939  sym_perm = ID2SYM(rb_intern("perm"));
11940  sym_extenc = ID2SYM(rb_intern("external_encoding"));
11941  sym_intenc = ID2SYM(rb_intern("internal_encoding"));
11942  sym_encoding = ID2SYM(rb_intern("encoding"));
11943  sym_open_args = ID2SYM(rb_intern("open_args"));
11944  sym_textmode = ID2SYM(rb_intern("textmode"));
11945  sym_binmode = ID2SYM(rb_intern("binmode"));
11946  sym_autoclose = ID2SYM(rb_intern("autoclose"));
11947  sym_normal = ID2SYM(rb_intern("normal"));
11948  sym_sequential = ID2SYM(rb_intern("sequential"));
11949  sym_random = ID2SYM(rb_intern("random"));
11950  sym_willneed = ID2SYM(rb_intern("willneed"));
11951  sym_dontneed = ID2SYM(rb_intern("dontneed"));
11952  sym_noreuse = ID2SYM(rb_intern("noreuse"));
11953 }
static VALUE argf_bytes(VALUE argf)
Definition: io.c:11077
#define ARGVSTR2ARGV(argv_str)
#define RB_TYPE_P(obj, type)
static void make_readconv(rb_io_t *fptr, int size)
Definition: io.c:2104
#define ALLOC(type)
VALUE rb_eStandardError
Definition: error.c:509
static VALUE rb_io_rewind(VALUE io)
Definition: io.c:1617
static VALUE rb_io_close_read(VALUE io)
Definition: io.c:4348
int rb_pipe(int *pipes)
Definition: io.c:5558
VALUE rb_str_locktmp_ensure(VALUE str, VALUE(*func)(VALUE), VALUE arg)
Definition: string.c:1831
static VALUE rb_obj_display(int argc, VALUE *argv, VALUE self)
Definition: io.c:7035
static int nogvl_copy_stream_wait_write(struct copy_stream_struct *stp)
Definition: io.c:9701
VALUE rb_io_getbyte(VALUE io)
Definition: io.c:3701
static long fcntl_narg_len(int cmd)
Definition: io.c:8702
static VALUE rb_io_set_lineno(VALUE io, VALUE lineno)
Definition: io.c:3197
int rb_io_wait_writable(int f)
Definition: io.c:1090
static ID id_set_encoding
Definition: io.c:148
#define FilePathValue(v)
static VALUE rb_io_open_with_args(int argc, VALUE *argv)
Definition: io.c:6410
off_t total
Definition: io.c:9632
static VALUE argf_getpartial(int argc, VALUE *argv, VALUE argf, int nonblock)
Definition: io.c:10785
VALUE argf
Definition: io.c:10720
VALUE rb_ary_new4(long n, const VALUE *elts)
Definition: array.c:451
static VALUE rb_io_set_sync(VALUE io, VALUE sync)
Definition: io.c:1817
VALUE rb_ary_entry(VALUE ary, long offset)
Definition: array.c:1101
VALUE rb_any_to_s(VALUE)
Definition: object.c:384
Definition: io.c:8499
void rb_set_class_path(VALUE, VALUE, const char *)
Definition: variable.c:308
void rb_bug(const char *fmt,...)
Definition: error.c:290
#define FALSE
Definition: nkf.h:174
int ioctl(int, int,...)
Definition: win32.c:2438
static VALUE rb_io_internal_encoding(VALUE)
Definition: io.c:10331
static VALUE rb_io_s_readlines(int argc, VALUE *argv, VALUE io)
Definition: io.c:9383
#define FMODE_READWRITE
Definition: io.h:105
#define rb_hash_lookup
Definition: tcltklib.c:268
static VALUE sym_random
Definition: io.c:8247
static VALUE rb_io_closed(VALUE io)
Definition: io.c:4310
#define SSIZE_MAX
Definition: ruby.h:298
size_t strlen(const char *)
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)
static VALUE io_enc_str(VALUE str, rb_io_t *fptr)
Definition: io.c:2096
#define OBJ_INFECT(x, s)
int i
Definition: win32ole.c:784
void rb_thread_wait_fd(int)
Definition: thread.c:3433
VALUE rb_cIO
Definition: io.c:131
VALUE rb_class_new_instance(int, VALUE *, VALUE)
Definition: object.c:1775
#define FIX2UINT(x)
void rb_io_check_writable(rb_io_t *fptr)
Definition: io.c:805
unsigned long VALUE
Definition: ripper.y:104
static VALUE sym_autoclose
Definition: io.c:150
static long setup_narg(ioctl_req_t cmd, VALUE *argp, int io_p)
Definition: io.c:8709
static VALUE sym_encoding
Definition: io.c:149
const char * rb_obj_classname(VALUE)
Definition: variable.c:396
VALUE rb_str_buf_cat_ascii(VALUE, const char *)
Definition: string.c:2082
static VALUE argf_set_pos(VALUE argf, VALUE offset)
Definition: io.c:10529
static ID id_getc
Definition: io.c:148
static VALUE rb_io_codepoints(VALUE io)
Definition: io.c:3630
int rb_io_modestr_fmode(const char *modestr)
Definition: io.c:4727
static VALUE sym_noreuse
Definition: io.c:8247
static VALUE argf_set_lineno(VALUE argf, VALUE val)
Definition: io.c:7585
VALUE rb_stderr
Definition: io.c:137
static VALUE argf_inplace_mode_get(VALUE argf)
Definition: io.c:11355
VALUE rb_file_open_str(VALUE fname, const char *modestr)
Definition: io.c:5461
static VALUE rb_f_putc(VALUE recv, VALUE ch)
Definition: io.c:6826
static VALUE argf_readpartial(int argc, VALUE *argv, VALUE argf)
Definition: io.c:10765
int count
Definition: encoding.c:51
#define ECONV_AFTER_OUTPUT
static VALUE io_call_close(VALUE io)
Definition: io.c:4279
static int max(int a, int b)
Definition: strftime.c:141
static ID id_read
Definition: io.c:148
static int io_fflush(rb_io_t *)
Definition: io.c:1049
#define ENCODING_MAXNAMELEN
rb_uid_t getuid(void)
Definition: win32.c:2392
VALUE rb_io_eof(VALUE io)
Definition: io.c:1706
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
Definition: class.c:1497
int rb_cloexec_open(const char *pathname, int flags, mode_t mode)
Definition: io.c:209
static const char * rb_io_fmode_modestr(int fmode)
Definition: io.c:4691
static void argf_init(struct argf *p, VALUE v)
Definition: io.c:7521
static VALUE rb_io_ioctl(int argc, VALUE *argv, VALUE io)
Definition: io.c:8788
static VALUE argf_inplace_mode_set(VALUE argf, VALUE val)
Definition: io.c:11388
int rb_execarg_run_options(const struct rb_execarg *e, struct rb_execarg *s, char *errmsg, size_t errmsg_buflen)
Definition: process.c:2872
int ioctl_req_t
Definition: io.c:8495
VALUE fname
Definition: io.c:5233
static VALUE pipe_open(VALUE execarg_obj, const char *modestr, int fmode, convconfig_t *convconfig)
Definition: io.c:5710
size_t rb_econv_memsize(rb_econv_t *)
Definition: transcode.c:1720
static void must_respond_to(ID mid, VALUE val, ID id)
Definition: io.c:7088
VALUE str
Definition: io.c:1182
static VALUE io_s_write(int argc, VALUE *argv, int binary)
Definition: io.c:9514
void rb_io_set_nonblock(rb_io_t *fptr)
Definition: io.c:2338
static VALUE select_call(VALUE arg)
Definition: io.c:8229
#define PIDT2NUM(v)
Definition: ruby.h:329
static VALUE argf_readbyte(VALUE argf)
Definition: io.c:10969
#define ARGF_FORWARD(argc, argv)
Definition: io.c:7620
static VALUE argf_gets(int, VALUE *, VALUE)
Definition: io.c:7910
#define rb_usascii_str_new2
struct rb_io_t rb_io_t
void rb_secure(int)
Definition: safe.c:79
#define rb_enc_codepoint(p, e, enc)
rb_fdset_t fdsets[4]
Definition: io.c:8225
rb_io_buffer_t cbuf
Definition: io.h:90
VALUE rb_io_binmode(VALUE io)
Definition: io.c:4600
void rb_syswait(rb_pid_t pid)
Definition: process.c:3639
static void argf_mark(void *ptr)
Definition: io.c:7488
VALUE ecopts
Definition: io.h:86
static VALUE io_puts_ary(VALUE ary, VALUE out, int recur)
Definition: io.c:6851
void rb_define_global_const(const char *, VALUE)
Definition: variable.c:2216
static VALUE rb_io_binmode_p(VALUE io)
Definition: io.c:4683
Definition: io.h:63
VALUE rb_str_locktmp(VALUE)
static VALUE rb_io_write_nonblock(VALUE io, VALUE str)
Definition: io.c:2610
#define rb_check_frozen(obj)
RUBY_EXTERN void * memmove(void *, const void *, size_t)
Definition: memmove.c:7
#define READ_DATA_PENDING_COUNT(fptr)
Definition: io.c:372
VALUE rb_ary_shift(VALUE ary)
Definition: array.c:929
#define rb_enc_name(enc)
char * str_ptr
Definition: io.c:2025
#define IO_WBUF_CAPA_MIN
Definition: io.c:123
#define F_DUPFD
Definition: win32.h:581
void * rb_thread_call_without_gvl2(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2)
Definition: thread.c:1319
static VALUE orig_stderr
Definition: io.c:139
static VALUE io_s_foreach(struct foreach_arg *arg)
Definition: io.c:9308
#define FMODE_WRITABLE
Definition: io.h:104
VALUE rb_hash_lookup2(VALUE, VALUE, VALUE)
Definition: hash.c:581
rb_encoding * rb_to_encoding(VALUE enc)
Definition: encoding.c:194
VALUE rb_str_new_cstr(const char *)
Definition: string.c:447
void rb_fd_fix_cloexec(int fd)
Definition: io.c:202
static int is_popen_fork(VALUE prog)
Definition: io.c:5934
#define FMODE_READABLE
Definition: io.h:103
static VALUE io_flush_buffer_async(VALUE arg)
Definition: io.c:1009
static VALUE io_binwrite_string(VALUE arg)
Definition: io.c:1194
int argc
Definition: io.c:10718
static void io_encoding_set(rb_io_t *, VALUE, VALUE, VALUE)
Definition: io.c:9068
static VALUE rb_io_syswrite(VALUE io, VALUE str)
Definition: io.c:4500
#define FMODE_WSPLIT_INITIALIZED
Definition: io.h:114
VALUE rb_enc_from_encoding(rb_encoding *encoding)
Definition: encoding.c:103
static rb_encoding * find_encoding(VALUE v)
Definition: io.c:9060
ID rb_frame_this_func(void)
Definition: eval.c:902
static VALUE argf_external_encoding(VALUE argf)
Definition: io.c:10403
SOCKET rb_w32_get_osfhandle(int)
Definition: win32.c:958
VALUE rb_obj_freeze(VALUE)
Definition: object.c:989
VALUE rb_eTypeError
Definition: error.c:511
static ID id_write
Definition: io.c:148
static VALUE sym_mode
Definition: io.c:149
void rb_define_hooked_variable(const char *, VALUE *, VALUE(*)(ANYARGS), void(*)(ANYARGS))
Definition: variable.c:575
#define OBJ_FREEZE(x)
static VALUE argf_each_line(int argc, VALUE *argv, VALUE argf)
Definition: io.c:11014
VALUE rb_obj_dup(VALUE)
Definition: object.c:338
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
VALUE rb_execarg_extract_options(VALUE execarg_obj, VALUE opthash)
Definition: process.c:1897
#define ECONV_NEWLINE_DECORATOR_MASK
#define OBJ_TAINTED(x)
#define UNREACHABLE
Definition: ruby.h:40
unsigned long ruby_strtoul(const char *str, char **endptr, int base)
Definition: util.c:106
static VALUE rb_io_close_write(VALUE io)
Definition: io.c:4411
VALUE * argv
Definition: io.c:10719
rb_encoding * rb_default_internal_encoding(void)
Definition: encoding.c:1373
static VALUE argf_filename(VALUE argf)
Definition: io.c:11188
#define RUBY_UBF_IO
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:822
static void fptr_finalize(rb_io_t *fptr, int noraise)
Definition: io.c:4082
#define rb_io_fcntl
Definition: io.c:8890
static VALUE opt_i_get(ID id, VALUE *var)
Definition: io.c:11362
int fcntl(int, int,...)
Definition: win32.c:3835
#define TYPE(x)
VALUE rb_enc_uint_chr(unsigned int code, rb_encoding *enc)
Definition: numeric.c:2423
int rb_econv_prepare_options(VALUE opthash, VALUE *ecopts, int ecflags)
Definition: transcode.c:2519
void rb_p(VALUE obj)
Definition: io.c:6940
VALUE rb_ary_tmp_new(long capa)
Definition: array.c:465
static VALUE argf_argv(VALUE argf)
Definition: io.c:11441
static int io_encname_bom_p(const char *name, long len)
Definition: io.c:4715
static VALUE rb_io_seek(VALUE io, VALUE offset, int whence)
Definition: io.c:1524
#define free(x)
Definition: io.c:24
VALUE rb_io_print(int argc, VALUE *argv, VALUE out)
Definition: io.c:6726
#define RSTRING_PTR(str)
#define CLASS_OF(v)
static VALUE rb_io_getline_fast(rb_io_t *fptr, rb_encoding *enc, VALUE io)
Definition: io.c:2890
void rb_lastline_set(VALUE)
Definition: vm.c:780
#define RFILE(obj)
#define T_ARRAY
VALUE rb_enc_str_new(const char *, long, rb_encoding *)
Definition: string.c:439
char * ptr
Definition: io.h:57
int8_t binmode
Definition: io.c:159
int writeconv_pre_ecflags
Definition: io.h:94
VALUE rb_protect(VALUE(*proc)(VALUE), VALUE data, int *state)
Definition: eval.c:771
rb_io_t * fptr
Definition: io.c:2027
#define xfree
#define MBCLEN_NEEDMORE_P(ret)
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
Definition: vm_eval.c:773
#define Qnil
static VALUE rb_io_readchar(VALUE io)
Definition: io.c:3678
static VALUE argf_write(VALUE argf, VALUE str)
Definition: io.c:11481
static int rb_sysopen_internal(struct sysopen_struct *data)
Definition: io.c:5247
#define MEMMOVE(p1, p2, type, n)
int rb_cloexec_dup2(int oldfd, int newfd)
Definition: io.c:232
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:1780
static VALUE rb_io_sysseek(int argc, VALUE *argv, VALUE io)
Definition: io.c:4460
#define PIPE_BUF
Definition: io.c:109
#define SET_BINARY_MODE_WITH_SEEK_CUR(fptr)
Definition: io.c:558
int writeconv_initialized
Definition: io.h:96
#define rb_str_new4
#define FMODE_CREATE
Definition: io.h:111
VALUE rb_enc_associate(VALUE obj, rb_encoding *enc)
Definition: encoding.c:766
VALUE rb_execarg_new(int argc, VALUE *argv, int accept_shell)
Definition: process.c:2190
VALUE rb_obj_class(VALUE)
Definition: object.c:194
#define RETURN_ENUMERATOR(obj, argc, argv)
VALUE rb_ary_clear(VALUE ary)
Definition: array.c:3220
static void pipe_add_fptr(rb_io_t *fptr)
Definition: io.c:5480
VALUE rb_str_encode_ospath(VALUE)
Definition: file.c:230
VALUE rb_class_name(VALUE)
Definition: variable.c:383
static VALUE argf_binmode_p(VALUE argf)
Definition: io.c:11260
#define NEED_WRITECONV(fptr)
Definition: io.c:554
#define rb_enc_left_char_head(s, p, e, enc)
#define T_FILE
long lineno
Definition: io.c:155
static VALUE rb_file_initialize(int argc, VALUE *argv, VALUE io)
Definition: io.c:7392
static VALUE argf_write_io(VALUE argf)
Definition: io.c:11466
#define FMODE_DUPLEX
Definition: io.h:109
#define SafeStringValue(v)
int rb_io_modestr_oflags(const char *modestr)
Definition: io.c:4846
static int ruby_dup(int orig)
Definition: io.c:843
int rb_enc_mbclen(const char *p, const char *e, rb_encoding *enc)
Definition: encoding.c:886
#define FMODE_BINMODE
Definition: io.h:106
#define STDIO_READ_DATA_PENDING(fp)
Definition: io.c:366
VALUE rb_eSecurityError
Definition: error.c:520
#define FMODE_APPEND
Definition: io.h:110
void rb_include_module(VALUE klass, VALUE module)
Definition: class.c:695
#define MORE_CHAR_FINISHED
Definition: io.c:2131
void rb_last_status_clear(void)
Definition: process.c:285
static VALUE more_char(rb_io_t *fptr)
Definition: io.c:2207
static VALUE rb_io_s_sysopen(int argc, VALUE *argv)
Definition: io.c:6212
static VALUE argf_lineno(VALUE argf)
Definition: io.c:7606
off_t copy_length
Definition: io.c:9625
#define rb_str_new2
Definition: io.c:152
static void prepare_getline_args(int argc, VALUE *argv, VALUE *rsp, long *limit, VALUE io)
Definition: io.c:2944
void rb_define_global_function(const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a global function.
Definition: class.c:1526
long tv_sec
Definition: ossl_asn1.c:17
static VALUE rb_file_open_generic(VALUE io, VALUE filename, int oflags, int fmode, convconfig_t *convconfig, mode_t perm)
Definition: io.c:5408
VALUE rb_lastline_get(void)
Definition: vm.c:774
static VALUE internal_write_func(void *ptr)
Definition: io.c:918
void rb_io_check_initialized(rb_io_t *fptr)
Definition: io.c:596
VALUE rb_str_unlocktmp(VALUE)
Definition: string.c:1821
unsigned int last
Definition: nkf.c:4310
static VALUE rb_io_each_byte(VALUE io)
Definition: io.c:3338
VALUE writeconv_pre_ecopts
Definition: io.h:95
VALUE rb_str_substr(VALUE, long, long)
Definition: string.c:1775
static void argf_close(VALUE file)
Definition: io.c:7630
static void open_key_args(int argc, VALUE *argv, VALUE opt, struct foreach_arg *arg)
Definition: io.c:9271
static VALUE argf_readchar(VALUE argf)
Definition: io.c:10929
const char * syserr
Definition: io.c:9633
void rb_update_max_fd(int fd)
Definition: io.c:164
static VALUE rb_io_external_encoding(VALUE io)
Definition: io.c:10306
#define ID2SYM(x)
static VALUE rb_f_readlines(int argc, VALUE *argv, VALUE recv)
Definition: io.c:8012
static void io_set_read_length(VALUE str, long n)
Definition: io.c:2268
static int argf_next_argv(VALUE argf)
Definition: io.c:7640
rb_encoding * enc2
Definition: io.h:84
static const rb_data_type_t argf_type
Definition: io.c:7515
static long io_fwrite(VALUE str, rb_io_t *fptr, int nosync)
Definition: io.c:1338
static VALUE rb_f_open(int argc, VALUE *argv)
Definition: io.c:6353
static VALUE argf_each_codepoint(VALUE argf)
Definition: io.c:11142
#define ENC_CODERANGE_BROKEN
RUBY_FUNC_EXPORTED size_t rb_io_memsize(const rb_io_t *fptr)
Definition: io.c:4209
VALUE rb_stdin
Definition: io.c:137
#define GetOpenFile(obj, fp)
Definition: io.h:120
VALUE rb_io_printf(int argc, VALUE *argv, VALUE out)
Definition: io.c:6667
static ssize_t rb_write_internal2(int fd, const void *buf, size_t count)
Definition: io.c:954
VALUE envp_str
Definition: ripper.y:223
VALUE rb_str_append(VALUE, VALUE)
Definition: string.c:2122
VALUE rb_str_new_frozen(VALUE)
Definition: string.c:713
int argc
Definition: io.c:6955
static VALUE nogvl_ioctl(void *ptr)
Definition: io.c:8506
static void validate_enc_binmode(int *fmode_p, int ecflags, rb_encoding *enc, rb_encoding *enc2)
Definition: io.c:5057
static VALUE rb_f_p_internal(VALUE arg)
Definition: io.c:6960
int capa
Definition: io.h:60
VALUE rb_io_ascii8bit_binmode(VALUE io)
Definition: io.c:4624
VALUE rb_f_sprintf(int, const VALUE *)
Definition: sprintf.c:433
#define io_tell(fptr)
Definition: io.c:744
static VALUE rb_io_tell(VALUE io)
Definition: io.c:1511
const char * ptr
Definition: io.c:1183
VALUE argv
Definition: io.c:156
void rb_str_modify_expand(VALUE, long)
Definition: string.c:1377
#define rb_fd_term(f)
static VALUE argf
Definition: io.c:146
static void io_check_tty(rb_io_t *fptr)
Definition: io.c:5319
#define rb_fd_max(f)
static VALUE argf_seek_m(int argc, VALUE *argv, VALUE argf)
Definition: io.c:10508
static void opt_i_set(VALUE val, ID id, VALUE *var)
Definition: io.c:11407
#define GetWriteIO(io)
Definition: io.c:369
#define ENCODING_GET(obj)
long last_lineno
Definition: io.c:154
static VALUE read_all(rb_io_t *fptr, long siz, VALUE str)
Definition: io.c:2277
int rb_io_extract_encoding_option(VALUE opt, rb_encoding **enc_p, rb_encoding **enc2_p, int *fmode_p)
Definition: io.c:4987
static void * exec_interrupts(void *arg)
Definition: io.c:9641
#define sym(x)
Definition: date_core.c:3715
VALUE rb_io_write(VALUE io, VALUE str)
Definition: io.c:1415
int mode
Definition: io.h:66
static VALUE rb_io_set_autoclose(VALUE io, VALUE autoclose)
Definition: io.c:7475
static ssize_t maygvl_read(int has_gvl, int fd, void *buf, size_t count)
Definition: io.c:9877
static rb_encoding * io_read_encoding(rb_io_t *fptr)
Definition: io.c:787
Win32OLEIDispatch * p
Definition: win32ole.c:786
static VALUE rb_io_s_popen(int argc, VALUE *argv, VALUE klass)
Definition: io.c:6048
static VALUE rb_io_lines(int argc, VALUE *argv, VALUE io)
Definition: io.c:3312
#define MEMZERO(p, type, n)
VALUE rb_enumeratorize(VALUE obj, VALUE meth, int argc, VALUE *argv)
Definition: enumerator.c:398
void rb_exc_raise(VALUE mesg)
Definition: eval.c:527
#define ECONV_ERROR_HANDLER_MASK
#define SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags)
Definition: io.c:557
int args
Definition: win32ole.c:785
#define rb_io_set_close_on_exec
Definition: io.c:3961
#define NUM2OFFT(x)
VALUE rb_io_close(VALUE io)
Definition: io.c:4221
VALUE rb_usascii_str_new(const char *, long)
Definition: string.c:431
static VALUE rb_io_sysread(int argc, VALUE *argv, VALUE io)
Definition: io.c:4546
long narg
Definition: io.c:8502
static void io_ungetbyte(VALUE str, rb_io_t *fptr)
Definition: io.c:701
ioctl_req_t cmd
Definition: io.c:8501
static VALUE rb_file_open_internal(VALUE io, VALUE filename, const char *modestr)
Definition: io.c:5434
void rb_define_readonly_variable(const char *, VALUE *)
Definition: variable.c:600
static int str_end_with_asciichar(VALUE str, int c)
Definition: io.c:6836
static VALUE argf_binmode_m(VALUE argf)
Definition: io.c:11237
#define fmode
VALUE current_file
Definition: io.c:153
#define O_CLOEXEC
rb_encoding * enc
Definition: io.h:83
int rb_to_encoding_index(VALUE enc)
Definition: encoding.c:146
rb_encoding * rb_default_external_encoding(void)
Definition: encoding.c:1288
void rb_gc(void)
Definition: gc.c:3110
void rb_maygvl_fd_fix_cloexec(int fd)
Definition: io.c:179
#define rb_fd_select(n, rfds, wfds, efds, timeout)
VALUE rb_rescue(VALUE(*b_proc)(ANYARGS), VALUE data1, VALUE(*r_proc)(ANYARGS), VALUE data2)
Definition: eval.c:763
static VALUE copy_stream_fallback_body(VALUE arg)
Definition: io.c:10034
off_t src_offset
Definition: io.c:9626
static VALUE orig_stdout
Definition: io.c:139
#define FIXNUM_P(f)
long len
Definition: io.c:2026
static VALUE argf_lines(int argc, VALUE *argv, VALUE argf)
Definition: io.c:11029
static void * nogvl_close(void *ptr)
Definition: io.c:4044
const void * buf
Definition: io.c:906
int rb_block_given_p(void)
Definition: eval.c:672
void rb_io_unbuffered(rb_io_t *fptr)
Definition: io.c:5552
void rb_write_error2(const char *mesg, long len)
Definition: io.c:7051
#define RARRAY_LEN(a)
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:1446
static VALUE argf_internal_encoding(VALUE argf)
Definition: io.c:10425
#define F_SETFL
Definition: win32.h:587
#define StringValuePtr(v)
int nosync
Definition: io.c:1190
#define val
static VALUE io_readpartial(int argc, VALUE *argv, VALUE io)
Definition: io.c:2484
static VALUE argf_getbyte(VALUE argf)
Definition: io.c:10889
#define rb_sys_fail_path(path)
Definition: io.c:408
static void stdout_setter(VALUE val, ID id, VALUE *variable)
Definition: io.c:7098
long tv_usec
Definition: ossl_asn1.c:18
VALUE rb_stdout
Definition: io.c:137
static VALUE rb_f_backquote(VALUE obj, VALUE str)
Definition: io.c:8075
VALUE rb_eRuntimeError
Definition: error.c:510
#define Qtrue
#define PREP_STDIO_NAME(f)
Definition: io.c:3966
static struct pipe_list * pipe_list
static VALUE argf_readlines(int, VALUE *, VALUE)
Definition: io.c:8037
static VALUE argf_getline(int argc, VALUE *argv, VALUE argf)
Definition: io.c:7805
#define FMODE_SETENC_BY_BOM
Definition: io.h:118
#define numberof(array)
Definition: io.c:118
return c
Definition: ripper.y:7591
VALUE rb_deferr
Definition: io.c:138
RUBY_EXTERN VALUE rb_mKernel
Definition: ripper.y:1414
static VALUE rb_io_s_binread(int argc, VALUE *argv, VALUE io)
Definition: io.c:9490
char * ruby_strdup(const char *)
Definition: util.c:456
static VALUE io_flush_buffer_sync(void *arg)
Definition: io.c:977
FILE * rb_io_stdio_file(rb_io_t *fptr)
Definition: io.c:7155
fd_set rb_fdset_t
Definition: ripper.y:326
int rb_io_oflags_fmode(int oflags)
Definition: io.c:4776
static int io_strip_bom(VALUE io)
Definition: io.c:5329
static VALUE io_s_readlines(struct foreach_arg *arg)
Definition: io.c:9359
static ssize_t maygvl_copy_stream_read(int has_gvl, struct copy_stream_struct *stp, char *buf, size_t len, off_t offset)
Definition: io.c:9886
VALUE rb_ary_new(void)
Definition: array.c:424
struct rb_execarg * rb_execarg_get(VALUE execarg_obj)
Definition: process.c:2201
#define Check_Type(v, t)
#define StringValueCStr(v)
VALUE rb_thread_io_blocking_region(rb_blocking_function_t *func, void *data1, int fd)
Definition: thread.c:1333
#define dp(v)
Definition: vm_debug.h:23
void rb_econv_binmode(rb_econv_t *ec)
Definition: transcode.c:1934
unsigned long ID
Definition: ripper.y:105
VALUE rb_io_get_write_io(VALUE io)
Definition: io.c:626
static int swallow(rb_io_t *fptr, int term)
Definition: io.c:2841
static VALUE argf_set_encoding(int argc, VALUE *argv, VALUE argf)
Definition: io.c:10465
#define ARGF_GENERIC_INPUT_P()
Definition: io.c:7618
void rb_gc_mark(VALUE)
Definition: gc.c:2600
VALUE rb_io_ungetbyte(VALUE io, VALUE b)
Definition: io.c:3762
void rb_define_const(VALUE, const char *, VALUE)
Definition: variable.c:2202
int rb_cloexec_fcntl_dupfd(int fd, int minfd)
Definition: io.c:308
static void pipe_finalize(rb_io_t *fptr, int noraise)
Definition: io.c:5527
static VALUE copy_stream_fallback(struct copy_stream_struct *stp)
Definition: io.c:10092
#define ISASCII(c)
Definition: ruby.h:1629
VALUE rb_io_flush(VALUE io)
Definition: io.c:1470
VALUE rb_str_cat2(VALUE, const char *)
Definition: string.c:1983
static VALUE sym_textmode
Definition: io.c:150
static VALUE finish_writeconv_sync(VALUE arg)
Definition: io.c:4037
static VALUE io_write(VALUE io, VALUE str, int nosync)
Definition: io.c:1362
static VALUE rb_f_puts(int argc, VALUE *argv, VALUE recv)
Definition: io.c:6931
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:499
static VALUE pipe_pair_close(VALUE rw)
Definition: io.c:9131
const char * ruby_get_inplace_mode(void)
Definition: io.c:11413
#define RSTRING_LEN(str)
static int appendline(rb_io_t *fptr, int delim, VALUE *strp, long *lp)
Definition: io.c:2758
#define FIX2INT(x)
#define INT2FIX(i)
int chown(const char *, int, int)
Definition: win32.c:4065
int fd
Definition: io.h:64
VALUE rb_check_to_integer(VALUE, const char *)
Definition: object.c:2424
static VALUE rb_io_each_line(int argc, VALUE *argv, VALUE io)
Definition: io.c:3292
#define Qfalse
#define MODE_BINARY(a, b)
int rb_io_wait_readable(int f)
Definition: io.c:1064
#define FIX2LONG(x)
int8_t next_p
Definition: io.c:159
void rb_sys_fail_str(VALUE mesg)
Definition: error.c:1905
static VALUE select_internal(VALUE read, VALUE write, VALUE except, struct timeval *tp, rb_fdset_t *fds)
Definition: io.c:8098
#define ANYARGS
void rb_last_status_set(int status, rb_pid_t pid)
Definition: process.c:276
rb_atomic_t cnt[RUBY_NSIG]
Definition: signal.c:432
static VALUE rb_io_each_char(VALUE io)
Definition: io.c:3497
#define T_STRING
VALUE rb_io_check_io(VALUE io)
Definition: io.c:620
int rb_thread_alone(void)
Definition: thread.c:2906
static VALUE argf_chars(VALUE argf)
Definition: io.c:11117
static VALUE rb_io_getline(int argc, VALUE *argv, VALUE io)
Definition: io.c:3100
VALUE str
Definition: io.c:1189
void rb_gvar_readonly_setter(VALUE val, ID id, void *data, struct rb_global_variable *gvar)
#define rb_fd_zero(f)
#define MBCLEN_CHARFOUND_P(ret)
#define rb_io_fdatasync
Definition: io.c:1862
struct rb_io_t::rb_io_enc_t encs
void Init_IO(void)
Definition: io.c:11642
void rb_close_before_exec(int lowfd, int maxhint, VALUE noclose_fds)
static void * nogvl_fclose(void *ptr)
Definition: io.c:4065
#define OBJ_INIT_COPY(obj, orig)
#define NUM2IOCTLREQ(num)
Definition: io.c:8496
int argc
Definition: ruby.c:130
#define NIL_P(v)
#define READ_DATA_PENDING(fptr)
Definition: io.c:371
VALUE writeconv_asciicompat
Definition: io.h:93
#define FMODE_TRUNC
Definition: io.h:115
static VALUE finish_writeconv(rb_io_t *fptr, int noalloc)
Definition: io.c:3969
const char * notimp
Definition: io.c:9635
VALUE rb_mutex_owned_p(VALUE self)
Definition: thread.c:4365
rb_pid_t pid
Definition: io.h:67
VALUE rb_check_hash_type(VALUE)
Definition: hash.c:461
#define LONG_MAX
Definition: ruby.h:201
#define NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr)
Definition: io.c:556
static VALUE rb_io_gets_m(int argc, VALUE *argv, VALUE io)
Definition: io.c:3137
VALUE rb_io_get_io(VALUE io)
Definition: io.c:614
#define RUBY_FUNC_EXPORTED
Definition: defines.h:184
static VALUE argf_eof(VALUE argf)
Definition: io.c:10619
int len
Definition: io.h:59
static void io_setstrbuf(VALUE *str, long len)
Definition: io.c:2244
#define ARGF
Definition: io.c:351
int err
Definition: win32.c:87
arg
Definition: ripper.y:1316
void rb_thread_check_ints(void)
Definition: thread.c:1092
static int io_flush_buffer(rb_io_t *fptr)
Definition: io.c:1035
#define argf_of(obj)
Definition: io.c:350
void Init_File(void)
Definition: file.c:5488
Definition: io.c:1187
VALUE rb_io_gets(VALUE io)
Definition: io.c:3110
int rb_cloexec_dup(int oldfd)
Definition: io.c:225
static VALUE rb_f_printf(int argc, VALUE *argv)
Definition: io.c:6685
static void rscheck(const char *rsptr, long rslen, VALUE rs)
Definition: io.c:2750
VALUE * argv
Definition: io.c:6956
void rb_str_setter(VALUE, ID, VALUE *)
Definition: string.c:7616
static int nogvl_copy_stream_write(struct copy_stream_struct *stp, char *buf, size_t len)
Definition: io.c:9929
#define ENC_CODERANGE_SET(obj, cr)
static VALUE argf_initialize(VALUE argf, VALUE argv)
Definition: io.c:7543
#define rb_f_syscall
Definition: io.c:9050
void * rb_thread_call_without_gvl(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2)
static VALUE io_getpartial(int argc, VALUE *argv, VALUE io, int nonblock)
Definition: io.c:2372
#define ATOMIC_CAS(var, oldval, newval)
Definition: ruby_atomic.h:132
static VALUE rb_io_seek_m(int argc, VALUE *argv, VALUE io)
Definition: io.c:1559
int fd
Definition: io.c:8500
#define EOF
Definition: vsnprintf.c:207
VALUE rb_str_buf_cat(VALUE, const char *, long)
Definition: string.c:1948
#define ruby_verbose
VALUE read
Definition: io.c:8223
#define rb_fd_set(n, f)
static void io_set_encoding_by_bom(VALUE io)
Definition: io.c:5392
#define DEFAULT_TEXTMODE
Definition: io.c:552
static void advice_arg_check(VALUE advice)
Definition: io.c:8335
#define IO_CBUF_CAPA_MIN
Definition: io.c:121
rb_encoding * rb_find_encoding(VALUE enc)
Definition: encoding.c:201
VALUE rb_obj_as_string(VALUE)
Definition: string.c:895
int rb_enc_ascget(const char *p, const char *e, int *len, rb_encoding *enc)
Definition: encoding.c:910
static VALUE argf_alloc(VALUE klass)
Definition: io.c:7530
#define NEXT_ARGF_FORWARD(argc, argv)
Definition: io.c:7624
VALUE rb_hash_aset(VALUE, VALUE, VALUE)
static VALUE prep_io(int fd, int fmode, VALUE klass, const char *path)
Definition: io.c:7105
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
Definition: class.c:1539
VALUE rb_yield(VALUE)
Definition: vm_eval.c:933
int rb_cloexec_pipe(int fildes[2])
Definition: io.c:271
static VALUE rb_f_gets(int argc, VALUE *argv, VALUE recv)
Definition: io.c:7886
VALUE rb_str_resize(VALUE, long)
Definition: string.c:1854
#define RTEST(v)
VALUE rb_get_argv(void)
Definition: io.c:11453
void ruby_set_inplace_mode(const char *suffix)
Definition: io.c:11419
rb_io_buffer_t wbuf
Definition: io.h:72
#define rb_enc_mbminlen(enc)
int errno
static VALUE copy_stream_body(VALUE arg)
Definition: io.c:10104
#define TRUE
Definition: nkf.h:175
void rb_thread_atfork(void)
Definition: thread.c:3845
VALUE rb_thread_current(void)
Definition: thread.c:2352
#define off_t
Definition: io.c:65
static VALUE seek_before_access(VALUE argp)
Definition: io.c:9407
#define S_ISREG(m)
Definition: io.c:872
static VALUE rb_io_set_pos(VALUE io, VALUE offset)
Definition: io.c:1585
static rb_atomic_t max_file_descriptor
Definition: io.c:162
static VALUE rb_io_init_copy(VALUE dest, VALUE io)
Definition: io.c:6612
VALUE rb_mEnumerable
Definition: enum.c:20
rb_io_t * fptr
Definition: io.c:1181
static void nogvl_copy_stream_read_write(struct copy_stream_struct *stp)
Definition: io.c:9955
#define StringValue(v)
void rb_econv_close(rb_econv_t *ec)
Definition: transcode.c:1702
static rb_encoding * io_input_encoding(rb_io_t *fptr)
Definition: io.c:796
static VALUE io_close(VALUE io)
Definition: io.c:4285
Definition: io.c:5474
#define MBCLEN_CHARFOUND_LEN(ret)
static int rb_sysopen(VALUE fname, int oflags, mode_t perm)
Definition: io.c:5257
int rb_enc_precise_mbclen(const char *p, const char *e, rb_encoding *enc)
Definition: encoding.c:898
#define IO_RBUF_CAPA_FOR(fptr)
Definition: io.c:122
static VALUE argf_rewind(VALUE argf)
Definition: io.c:10551
#define NEED_READCONV(fptr)
Definition: io.c:553
static VALUE rb_io_pid(VALUE io)
Definition: io.c:1910
void rb_fatal(const char *fmt,...)
Definition: error.c:1834
static VALUE io_s_read(struct foreach_arg *arg)
Definition: io.c:9395
VALUE rb_eSystemCallError
Definition: error.c:529
static void * io_flush_buffer_sync2(void *arg)
Definition: io.c:997
static int maygvl_copy_stream_continue_p(int has_gvl, struct copy_stream_struct *stp)
Definition: io.c:9654
static VALUE rb_io_readlines(int argc, VALUE *argv, VALUE io)
Definition: io.c:3247
long rb_str_coderange_scan_restartable(const char *, const char *, rb_encoding *, int *)
Definition: string.c:232
static VALUE rb_io_s_for_fd(int argc, VALUE *argv, VALUE klass)
Definition: io.c:7433
struct rb_io_enc_t encs
Definition: io.c:158
#define CONST_ID(var, str)
static VALUE rb_f_select(int argc, VALUE *argv, VALUE obj)
Definition: io.c:8469
static VALUE rb_io_chars(VALUE io)
Definition: io.c:3520
void rb_gc_register_mark_object(VALUE)
Definition: gc.c:2982
static int wsplit_p(rb_io_t *fptr)
Definition: io.c:876
static VALUE rb_io_s_open(int argc, VALUE *argv, VALUE klass)
Definition: io.c:6190
static VALUE rb_f_print(int argc, VALUE *argv)
Definition: io.c:6774
static void argf_lineno_setter(VALUE val, ID id, VALUE *var)
Definition: io.c:7843
#define strdup(s)
Definition: util.h:69
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1570
static VALUE argf_read_nonblock(int argc, VALUE *argv, VALUE argf)
Definition: io.c:10779
void rb_write_error_str(VALUE mesg)
Definition: io.c:7071
static VALUE argf_to_io(VALUE argf)
Definition: io.c:10593
#define NUM2UINT(x)
Definition: ripper.y:934
VALUE rb_block_call(VALUE, ID, int, VALUE *, VALUE(*)(ANYARGS), VALUE)
Definition: vm_eval.c:1130
static void io_unread(rb_io_t *fptr)
Definition: io.c:678
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:4308
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Definition: array.c:545
static void rb_scan_open_args(int argc, VALUE *argv, VALUE *fname_p, int *oflags_p, int *fmode_p, convconfig_t *convconfig_p, mode_t *perm_p)
Definition: io.c:6117
#define FMODE_WSPLIT
Definition: io.h:113
struct rb_execarg::@77::@79 cmd
union rb_execarg::@77 invoke
VALUE tied_io_for_writing
Definition: io.h:74
#define RARRAY_PTR(a)
static VALUE rb_io_close_m(VALUE io)
Definition: io.c:4268
static VALUE argf_lineno_getter(ID id, VALUE *var)
Definition: io.c:7836
static ssize_t rb_write_internal(int fd, const void *buf, size_t count)
Definition: io.c:943
int8_t init_p
Definition: io.c:159
#define FMODE_TEXTMODE
Definition: io.h:116
static 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:5106
int rb_exec_async_signal_safe(const struct rb_execarg *e, char *errmsg, size_t errmsg_buflen)
Definition: process.c:3019
#define RB_GC_GUARD(v)
#define mode_t
Definition: win32.h:100
void rb_mutex_allow_trap(VALUE self, int val)
Definition: thread.c:4555
#define T_FIXNUM
VALUE rb_mutex_synchronize(VALUE mutex, VALUE(*func)(VALUE arg), VALUE arg)
Definition: thread.c:4532
static VALUE argf_readline(int, VALUE *, VALUE)
Definition: io.c:7985
#define IS_PREP_STDIO(f)
Definition: io.c:3965
VALUE rb_str_buf_new(long)
Definition: string.c:777
static VALUE rb_io_s_binwrite(int argc, VALUE *argv, VALUE io)
Definition: io.c:9617
static VALUE result
Definition: nkf.c:40
VALUE rb_gets(void)
Definition: io.c:7921
#define ONIGENC_CONSTRUCT_MBCLEN_CHARFOUND(n)
char * strchr(char *, char)
int intptr_t
Definition: win32.h:86
static VALUE prep_stdio(FILE *f, int fmode, VALUE klass, const char *path)
Definition: io.c:7136
#define NEED_NEWLINE_DECORATOR_ON_WRITE(fptr)
Definition: io.c:414
char * str_ptr
Definition: io.c:2359
int rb_utf8_encindex(void)
Definition: encoding.c:1177
static void * internal_write_func2(void *ptr)
Definition: io.c:925
#define ECONV_STATEFUL_DECORATOR_MASK
VALUE rb_rs
Definition: io.c:142
void rb_io_synchronized(rb_io_t *fptr)
Definition: io.c:5545
VALUE rb_rescue2(VALUE(*b_proc)(ANYARGS), VALUE data1, VALUE(*r_proc)(ANYARGS), VALUE data2,...)
Definition: eval.c:701
static VALUE rb_io_s_write(int argc, VALUE *argv, VALUE io)
Definition: io.c:9601
static long io_bufread(char *ptr, long len, rb_io_t *fptr)
Definition: io.c:1986
rb_fdset_t fds
Definition: io.c:9636
rb_econv_t * rb_econv_open_opts(const char *source_encoding, const char *destination_encoding, int ecflags, VALUE ecopts)
Definition: transcode.c:2570
VALUE rb_ensure(VALUE(*b_proc)(ANYARGS), VALUE data1, VALUE(*e_proc)(ANYARGS), VALUE data2)
Definition: eval.c:804
int memcmp(const void *s1, const void *s2, size_t len)
Definition: memcmp.c:7
static VALUE argf_read(int argc, VALUE *argv, VALUE argf)
Definition: io.c:10673
VALUE rb_econv_open_exc(const char *senc, const char *denc, int ecflags)
Definition: transcode.c:2028
#define rb_fd_isset(n, f)
static int maygvl_select(int has_gvl, int n, rb_fdset_t *rfds, rb_fdset_t *wfds, rb_fdset_t *efds, struct timeval *timeout)
Definition: io.c:9673
static int maygvl_copy_stream_wait_read(int has_gvl, struct copy_stream_struct *stp)
Definition: io.c:9682
static VALUE do_writeconv(VALUE str, rb_io_t *fptr)
Definition: io.c:1283
static VALUE io_shift_cbuf(rb_io_t *fptr, int len, VALUE *strp)
Definition: io.c:2217
int rb_reserved_fd_p(int fd)
void rb_sys_fail(const char *mesg)
Definition: error.c:1899
struct rb_execarg::@77::@78 sh
static VALUE read_internal_call(VALUE arg)
Definition: io.c:2364
static VALUE sym_willneed
Definition: io.c:8247
static VALUE rb_io_autoclose_p(VALUE io)
Definition: io.c:7449
static VALUE io_write_m(VALUE io, VALUE str)
Definition: io.c:1409
void rb_jump_tag(int tag)
Definition: eval.c:666
VALUE rb_str_encode(VALUE str, VALUE to, int ecflags, VALUE ecopts)
Definition: transcode.c:2867
static VALUE rb_io_set_encoding(int argc, VALUE *argv, VALUE io)
Definition: io.c:10360
#define READ_DATA_BUFFERED(fptr)
Definition: io.c:374
#define rb_io_close_on_exec_p
Definition: io.c:3903
#define T_BIGNUM
struct timeval * timeout
Definition: io.c:8224
static VALUE bufread_call(VALUE arg)
Definition: io.c:2031
VALUE rb_define_module_under(VALUE outer, const char *name)
Definition: class.c:637
RUBY_EXTERN char * strerror(int)
Definition: strerror.c:11
rb_econv_t * readconv
Definition: io.h:89
#define ENC_CODERANGE_VALID
static VALUE argf_tell(VALUE argf)
Definition: io.c:10491
#define shutdown(a, b)
Definition: io.c:562
static VALUE argf_each_byte(VALUE argf)
Definition: io.c:11062
static size_t argf_memsize(const void *ptr)
Definition: io.c:7506
#define SEEK_END
Definition: io.c:749
RUBY_EXTERN VALUE rb_cFile
Definition: ripper.y:1437
static int do_ioctl(int fd, ioctl_req_t cmd, long narg)
Definition: io.c:8514
#define recur(fmt)
int argc
Definition: io.c:9265
const char * rb_class2name(VALUE)
Definition: variable.c:389
VALUE rb_ivar_set(VALUE, ID, VALUE)
Definition: variable.c:1128
static VALUE argf_codepoints(VALUE argf)
Definition: io.c:11157
static VALUE sym_extenc
Definition: io.c:149
VALUE write_lock
Definition: io.h:98
struct pipe_list * next
Definition: io.c:5476
static VALUE argf_filename_getter(ID id, VALUE *var)
Definition: io.c:11195
void rb_econv_check_error(rb_econv_t *ec)
Definition: transcode.c:4194
static VALUE rb_io_binmode_m(VALUE io)
Definition: io.c:4664
static VALUE sym_perm
Definition: io.c:149
static VALUE rb_io_isatty(VALUE io)
Definition: io.c:3854
void rb_str_modify(VALUE)
Definition: string.c:1369
#define NEWOBJ_OF(obj, type, klass, flags)
VALUE rb_str_cat(VALUE, const char *, long)
Definition: string.c:1964
#define ENC_CODERANGE_7BIT
rb_encoding * rb_enc_get(VALUE obj)
Definition: encoding.c:772
VALUE io
Definition: io.c:1188
struct timeval rb_time_interval(VALUE num)
Definition: time.c:2492
static VALUE io_s_write0(struct write_arg *arg)
Definition: io.c:9508
void rb_insecure_operation(void)
Definition: safe.c:101
static VALUE io_flush_buffer_async2(VALUE arg)
Definition: io.c:1016
static VALUE rb_io_lineno(VALUE io)
Definition: io.c:3170
static long io_writable_length(rb_io_t *fptr, long l)
Definition: io.c:966
static VALUE io_read(int argc, VALUE *argv, VALUE io)
Definition: io.c:2705
int size
Definition: encoding.c:52
#define f
#define NUM2LONG(x)
static void pipe_atexit(void)
Definition: io.c:5514
static VALUE io_new_instance(VALUE args)
Definition: io.c:9054
VALUE rb_mutex_new(void)
Definition: thread.c:4167
#define SYMBOL_P(x)
static VALUE rb_io_putc(VALUE io, VALUE ch)
Definition: io.c:6799
static VALUE rb_io_bytes(VALUE io)
Definition: io.c:3366
#define Qundef
int rb_method_basic_definition_p(VALUE, ID)
Definition: vm_method.c:1517
VALUE rb_exc_new3(VALUE etype, VALUE str)
Definition: error.c:548
static long io_fread(VALUE str, long offset, long size, rb_io_t *fptr)
Definition: io.c:2039
static int rb_io_fmode_oflags(int fmode)
Definition: io.c:4811
static VALUE check_pipe_command(VALUE filename_or_command)
Definition: io.c:6239
int rb_io_fptr_finalize(rb_io_t *fptr)
Definition: io.c:4186
VALUE rb_hash_dup(VALUE)
Definition: hash.c:240
VALUE rb_mWaitReadable
Definition: io.c:134
VALUE io
Definition: io.c:9267
static VALUE rb_io_s_pipe(int argc, VALUE *argv, VALUE klass)
Definition: io.c:9198
VALUE rb_io_fdopen(int fd, int oflags, const char *path)
Definition: io.c:7127
static VALUE rb_io_to_io(VALUE io)
Definition: io.c:1965
VALUE rb_eIOError
Definition: io.c:133
static VALUE rb_io_inspect(VALUE obj)
Definition: io.c:1929
int off
Definition: io.h:58
VALUE rb_funcall3(VALUE, ID, int, const VALUE *)
Calls a method.
Definition: vm_eval.c:819
void rb_mod_sys_fail(VALUE mod, const char *mesg)
Definition: error.c:1911
void rb_thread_sleep(int)
Definition: thread.c:1117
static VALUE sym_intenc
Definition: io.c:149
#define MBCLEN_INVALID_P(ret)
#define rb_intern(str)
static VALUE rb_io_s_try_convert(VALUE dummy, VALUE io)
Definition: io.c:671
void rb_thread_execute_interrupts(VALUE th)
Definition: thread.c:1975
VALUE rb_check_array_type(VALUE ary)
Definition: array.c:557
static void clear_codeconv(rb_io_t *fptr)
Definition: io.c:4179
static void rb_io_fptr_cleanup(rb_io_t *fptr, int noraise)
Definition: io.c:4145
void rb_error_arity(int argc, int min, int max)
static void parse_mode_enc(const char *estr, rb_encoding **enc_p, rb_encoding **enc2_p, int *fmode_p)
Definition: io.c:4916
#define TypedData_Make_Struct(klass, type, data_type, sval)
VALUE rb_str_catf(VALUE str, const char *format,...)
Definition: sprintf.c:1310
void rb_syserr_fail_str(int e, VALUE mesg)
Definition: error.c:1893
void * rb_thread_call_with_gvl(void *(*func)(void *), void *data1)
Definition: thread.c:1403
long rb_w32_write_console(uintptr_t, int)
Definition: win32.c:6145
#define ECONV_PARTIAL_INPUT
rb_pid_t rb_fork_ruby(int *status)
RUBY_EXTERN VALUE rb_cObject
Definition: ripper.y:1426
#define is_socket(fd, path)
Definition: io.c:568
#define ALLOC_N(type, n)
#define LONG2FIX(i)
int rb_thread_fd_select(int, rb_fdset_t *, rb_fdset_t *, rb_fdset_t *, struct timeval *)
Definition: thread.c:3490
#define RBASIC(obj)
rb_econv_result_t
Definition: ripper.y:242
static VALUE argf_each_char(VALUE argf)
Definition: io.c:11102
VALUE pathv
Definition: io.h:69
static VALUE rb_io_advise(int argc, VALUE *argv, VALUE io)
Definition: io.c:8394
#define O_NONBLOCK
Definition: win32.h:591
static VALUE rb_io_getc(VALUE io)
Definition: io.c:3652
VALUE rb_eEOFError
Definition: io.c:132
VALUE rb_econv_make_exception(rb_econv_t *ec)
Definition: transcode.c:4188
static long io_binwrite(VALUE str, const char *ptr, long len, rb_io_t *fptr, int nosync)
Definition: io.c:1202
void(* finalize)(struct rb_io_t *, int)
Definition: io.h:70
#define UINT2NUM(x)
VALUE offset
Definition: io.c:9402
#define INT2NUM(x)
int use_shell
Definition: ripper.y:210
static VALUE argf_closed(VALUE argf)
Definition: io.c:11327
struct rb_encoding_entry * list
Definition: encoding.c:50
void rb_define_variable(const char *, VALUE *)
Definition: variable.c:594
#define STRNCASECMP(s1, s2, n)
v
Definition: win32ole.c:798
#define READ_CHECK(fptr)
Definition: io.c:387
#define EWOULDBLOCK
Definition: rubysocket.h:90
static VALUE rb_io_s_read(int argc, VALUE *argv, VALUE io)
Definition: io.c:9451
int rb_respond_to(VALUE, ID)
Definition: vm_method.c:1583
#define fsync
Definition: win32.h:202
void rb_io_check_readable(rb_io_t *fptr)
Definition: io.c:781
FILE * rb_fdopen(int fd, const char *modestr)
Definition: io.c:5280
static rb_io_t * flush_before_seek(rb_io_t *fptr)
Definition: io.c:734
static VALUE rb_open_file(int argc, VALUE *argv, VALUE io)
Definition: io.c:6139
#define OFFT2NUM(v)
int rb_execarg_addopt(VALUE execarg_obj, VALUE key, VALUE val)
Definition: process.c:1606
VALUE rb_ary_dup(VALUE ary)
Definition: array.c:1778
RUBY_EXTERN int dup2(int, int)
Definition: dup2.c:27
void rb_notimplement(void)
Definition: error.c:1826
void rb_define_virtual_variable(const char *, VALUE(*)(ANYARGS), void(*)(ANYARGS))
Definition: variable.c:606
static VALUE sym_binmode
Definition: io.c:150
const char * rb_econv_asciicompat_encoding(const char *encname)
Definition: transcode.c:1786
void rb_thread_fd_close(int)
Definition: thread.c:2080
VALUE rb_ary_concat(VALUE x, VALUE y)
Definition: array.c:3382
static long remain_size(rb_io_t *fptr)
Definition: io.c:2067
VALUE rb_exec_recursive(VALUE(*)(VALUE, VALUE, int), VALUE, VALUE)
Definition: thread.c:4872
long length
Definition: io.c:1184
static VALUE argf_argv_getter(ID id, VALUE *var)
Definition: io.c:11447
rb_io_t * fptr
Definition: io.c:4032
VALUE rb_ary_join(VALUE ary, VALUE sep)
Definition: array.c:1886
VALUE rb_eNotImpError
Definition: error.c:521
int rb_atomic_t
Definition: ruby_atomic.h:120
VALUE rb_ary_new2(long capa)
Definition: array.c:417
static VALUE io_reopen(VALUE io, VALUE nfile)
Definition: io.c:6420
static void * sysopen_func(void *ptr)
Definition: io.c:5239
static VALUE rb_io_readline(int argc, VALUE *argv, VALUE io)
Definition: io.c:3218
VALUE rb_str_new(const char *, long)
Definition: string.c:425
#define FMODE_PREP
Definition: io.c:3964
#define rb_safe_level()
Definition: tcltklib.c:94
VALUE rb_io_addstr(VALUE io, VALUE str)
Definition: io.c:1437
static long ioctl_narg_len(ioctl_req_t cmd)
Definition: io.c:8552
static VALUE internal_read_func(void *ptr)
Definition: io.c:911
#define ECONV_NEWLINE_DECORATOR_READ_MASK
void rb_execarg_setenv(VALUE execarg_obj, VALUE env)
Definition: process.c:2228
int oflags
Definition: io.c:5234
static VALUE rb_io_initialize(int argc, VALUE *argv, VALUE io)
Definition: io.c:7311
static void make_writeconv(rb_io_t *fptr)
Definition: io.c:1125
VALUE rb_io_taint_check(VALUE io)
Definition: io.c:587
const char * name
Definition: nkf.c:208
#define ECONV_NEWLINE_DECORATOR_WRITE_MASK
#define rb_enc_asciicompat(enc)
#define NUM2MODET(v)
Definition: ruby.h:347
#define NUM2INT(x)
#define SIGNED_VALUE
VALUE rb_hash_new(void)
Definition: hash.c:234
VALUE rb_io_puts(int argc, VALUE *argv, VALUE out)
Definition: io.c:6891
static VALUE rb_io_readbyte(VALUE io)
Definition: io.c:3734
VALUE rb_obj_alloc(VALUE)
Definition: object.c:1721
const char * rb_id2name(ID id)
Definition: ripper.c:17058
#define READ_CHAR_PENDING_PTR(fptr)
Definition: io.c:378
#define FMODE_SYNC
Definition: io.h:107
#define FMODE_TTY
Definition: io.h:108
#define MakeOpenFile(obj, fp)
Definition: io.h:129
#define SHUT_WR
#define SHUT_RD
VALUE rb_default_rs
Definition: io.c:144
#define MORE_CHAR_SUSPENDED
Definition: io.c:2130
static VALUE sym_sequential
Definition: io.c:8247
#define rb_fd_init(f)
#define OBJ_UNTRUSTED(x)
rb_io_buffer_t rbuf
Definition: io.h:72
char * inplace
Definition: io.c:157
static VALUE rb_io_s_copy_stream(int argc, VALUE *argv, VALUE io)
Definition: io.c:10269
static void clear_writeconv(rb_io_t *fptr)
Definition: io.c:4169
struct rb_io_enc_t convconfig_t
Definition: io.c:5054
static VALUE fill_cbuf(rb_io_t *fptr, int ec_flags)
Definition: io.c:2133
VALUE rb_hash_aref(VALUE, VALUE)
Definition: hash.c:570
VALUE rb_funcall2(VALUE, ID, int, const VALUE *)
Calls a method.
Definition: vm_eval.c:804
#define NUM2CHR(x)
static VALUE rb_io_reopen(int argc, VALUE *argv, VALUE file)
Definition: io.c:6526
rb_encoding * rb_ascii8bit_encoding(void)
Definition: encoding.c:1153
static long read_buffered_data(char *ptr, long len, rb_io_t *fptr)
Definition: io.c:1972
static VALUE sym_dontneed
Definition: io.c:8247
void rb_warning(const char *fmt,...)
Definition: error.c:229
int rb_enc_find_index(const char *name)
Definition: encoding.c:635
#define rb_io_fsync
Definition: io.c:1814
#define fileno(p)
Definition: vsnprintf.c:223
static VALUE sym_open_args
Definition: io.c:149
#define ECONV_DEFAULT_NEWLINE_DECORATOR
VALUE rb_uninterruptible(VALUE(*b_proc)(ANYARGS), VALUE data)
Definition: thread.c:5202
int rb_io_read_pending(rb_io_t *fptr)
Definition: io.c:817
#define NEED_NEWLINE_DECORATOR_ON_READ(fptr)
Definition: io.c:413
FILE * stdio_file
Definition: io.h:65
static VALUE rb_io_fileno(VALUE io)
Definition: io.c:1878
ssize_t rb_io_bufread(VALUE io, void *buf, size_t size)
Definition: io.c:2055
static VALUE sym_normal
Definition: io.c:8247
#define MODE_BTMODE(a, b, c)
Definition: io.c:1280
VALUE filename
Definition: io.c:153
static ID id_readpartial
Definition: io.c:148
static VALUE rb_f_p(int argc, VALUE *argv, VALUE self)
Definition: io.c:7002
static VALUE argf_forward(int argc, VALUE *argv, VALUE argf)
Definition: io.c:7612
static VALUE pipe_open_s(VALUE prog, const char *modestr, int fmode, convconfig_t *convconfig)
Definition: io.c:5948
static VALUE rb_f_readline(int argc, VALUE *argv, VALUE recv)
Definition: io.c:7959
char rb_w32_fd_is_text(int)
Definition: win32.c:6568
#define io_seek(fptr, ofs, whence)
Definition: io.c:743
static VALUE argf_fileno(VALUE argf)
Definition: io.c:10571
VALUE write
Definition: io.c:8223
#define OBJ_TAINT(x)
static ssize_t rb_read_internal(int fd, void *buf, size_t count)
Definition: io.c:932
static VALUE argf_to_s(VALUE argf)
Definition: io.c:11341
VALUE rb_output_rs
Definition: io.c:143
static VALUE io_alloc(VALUE klass)
Definition: io.c:862
#define RUBY_METHOD_FUNC(func)
VALUE * argv
Definition: io.c:9266
#define READ_CHAR_PENDING_COUNT(fptr)
Definition: io.c:377
static VALUE rb_io_getline_1(VALUE rs, long limit, VALUE io)
Definition: io.c:2989
void rb_stdio_set_default_encoding(void)
Definition: io.c:10376
int lineno
Definition: io.h:68
VALUE rb_mWaitWritable
Definition: io.c:135
void rb_io_read_check(rb_io_t *fptr)
Definition: io.c:834
#define fstat(fd, st)
Definition: win32.h:194
static VALUE rb_ioctl(VALUE io, VALUE req, VALUE arg)
Definition: io.c:8753
#define stat(path, st)
Definition: win32.h:193
static VALUE io_read_nonblock(int argc, VALUE *argv, VALUE io)
Definition: io.c:2546
static void * nogvl_copy_stream_func(void *arg)
Definition: io.c:10012
VALUE except
Definition: io.c:8223
static const char * rb_io_oflags_modestr(int oflags)
Definition: io.c:4852
#define rb_io_sync
Definition: io.c:1815
#define DEFULT_IOCTL_NARG_LEN
Definition: io.c:8528
#define env
mode_t perm
Definition: io.c:5235
int rb_econv_putbackable(rb_econv_t *ec)
Definition: transcode.c:1742
ssize_t rb_io_bufwrite(VALUE io, const void *buf, size_t size)
Definition: io.c:1352
#define NULL
Definition: _sdbm.c:103
static VALUE argf_file(VALUE argf)
Definition: io.c:11219
static VALUE copy_stream_finalize(VALUE arg)
Definition: io.c:10220
static VALUE io_getc(rb_io_t *fptr, rb_encoding *enc)
Definition: io.c:3375
#define READ_CHAR_PENDING(fptr)
Definition: io.c:376
VALUE rb_check_string_type(VALUE)
Definition: string.c:1509
static void argf_free(void *ptr)
Definition: io.c:7498
#define READ_DATA_PENDING_PTR(fptr)
Definition: io.c:373
static void extract_binmode(VALUE opthash, int *fmode)
Definition: io.c:5081
static VALUE argf_close_m(VALUE argf)
Definition: io.c:11308
int rb_enc_str_coderange(VALUE)
Definition: string.c:327
static ID id_flush
Definition: io.c:148
static VALUE select_end(VALUE arg)
Definition: io.c:8237
static void rb_io_ext_int_to_encs(rb_encoding *ext, rb_encoding *intern, rb_encoding **enc, rb_encoding **enc2, int fmode)
Definition: io.c:4886
VALUE rb_class_new(VALUE super)
Creates a new class.
Definition: class.c:117
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1344
VALUE rb_file_open(const char *fname, const char *modestr)
Definition: io.c:5468
#define NOFILE
Definition: io.c:76
void rb_io_check_byte_readable(rb_io_t *fptr)
Definition: io.c:772
static VALUE rb_io_each_codepoint(VALUE io)
Definition: io.c:3545
static void pipe_del_fptr(rb_io_t *fptr)
Definition: io.c:5491
void rb_io_check_char_readable(rb_io_t *fptr)
Definition: io.c:753
#define next_argv()
Definition: io.c:7617
int rb_thread_fd_writable(int)
Definition: thread.c:3439
void rb_warn(const char *fmt,...)
Definition: error.c:216
static VALUE rb_io_s_foreach(int argc, VALUE *argv, VALUE self)
Definition: io.c:9345
rb_io_t * fptr
Definition: io.c:5475
void rb_econv_putback(rb_econv_t *ec, unsigned char *p, int n)
Definition: transcode.c:1753
VALUE rb_econv_str_convert(rb_econv_t *ec, VALUE src, int flags)
Definition: transcode.c:1869
#define SEEK_SET
Definition: io.c:747
VALUE rb_eArgError
Definition: error.c:512
static VALUE rb_io_open(VALUE filename, VALUE vmode, VALUE vperm, VALUE opt)
Definition: io.c:6390
VALUE rb_convert_type(VALUE, int, const char *, const char *)
Definition: object.c:2381
#define O_BINARY
Definition: _sdbm.c:89
int mode
Definition: io.c:9403
VALUE rb_check_convert_type(VALUE, int, const char *, const char *)
Definition: object.c:2394
VALUE rb_io_set_write_io(VALUE io, VALUE w)
Definition: io.c:638
static VALUE argf_initialize_copy(VALUE argf, VALUE orig)
Definition: io.c:7553
if(c== ')') lex_state
Definition: ripper.y:7588
VALUE rb_io_ungetc(VALUE io, VALUE c)
Definition: io.c:3797
VALUE rb_output_fs
Definition: io.c:141
static VALUE argf_getc(VALUE argf)
Definition: io.c:10849
#define ECONV_UNIVERSAL_NEWLINE_DECORATOR
static int maygvl_close(int fd, int keepgvl)
Definition: io.c:4052
static VALUE argf_skip(VALUE argf)
Definition: io.c:11280
void rb_io_check_closed(rb_io_t *fptr)
Definition: io.c:604
#define SEEK_CUR
Definition: io.c:748
#define SET_BINARY_MODE(fptr)
Definition: io.c:555
char * strrchr(const char *, const char)
char ** argv
Definition: ruby.c:131
VALUE io
Definition: io.c:9401
static int maygvl_fclose(FILE *file, int keepgvl)
Definition: io.c:4073
rb_econv_t * writeconv
Definition: io.h:92
static VALUE argf_forward_call(VALUE arg)
Definition: io.c:10724
void rb_read_check(FILE *fp)
Definition: io.c:826
Definition: ioctl.h:6
void rb_write_error(const char *mesg)
Definition: io.c:7065
static int io_fillbuf(rb_io_t *fptr)
Definition: io.c:1640
Definition: io.c:9400
VALUE rb_inspect(VALUE)
Definition: object.c:402
int rb_thread_interrupted(VALUE thval)
Definition: thread.c:1109
rb_encoding * rb_enc_from_index(int index)
Definition: encoding.c:548
static void unsupported_encoding(const char *name)
Definition: io.c:4910
static VALUE rb_io_s_new(int argc, VALUE *argv, VALUE klass)
Definition: io.c:7412
void rb_execarg_fixup(VALUE execarg_obj)
Definition: process.c:2254
static void clear_readconv(rb_io_t *fptr)
Definition: io.c:4156
void rb_eof_error(void)
Definition: io.c:581
void rb_str_set_len(VALUE, long)
Definition: string.c:1838