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