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