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