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