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