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