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