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