1 /**********************************************************************
6 created at: Fri Oct 15 18:08:59 JST 1993
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
12 **********************************************************************/
14 #include "ruby/internal/config.h"
16 #include "ruby/fiber/scheduler.h"
17 #include "ruby/io/buffer.h"
23 /* non-Linux poll may not work on all FDs */
24 #if defined(HAVE_POLL)
25 # if defined(__linux__)
28 # if defined(__FreeBSD_version) && __FreeBSD_version >= 1100000
38 #define free(x) xfree(x)
40 #if defined(DOSISH) || defined(__CYGWIN__)
44 #include <sys/types.h>
45 #if defined HAVE_NET_SOCKET_H
46 # include <net/socket.h>
47 #elif defined HAVE_SYS_SOCKET_H
48 # include <sys/socket.h>
51 #if defined(__BOW__) || defined(__CYGWIN__) || defined(_WIN32)
52 # define NO_SAFE_RENAME
55 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__sun) || defined(_nec_ews)
63 #include <sys/types.h>
64 #if defined(HAVE_SYS_IOCTL_H) && !defined(_WIN32)
65 #include <sys/ioctl.h>
67 #if defined(HAVE_FCNTL_H) || defined(_WIN32)
69 #elif defined(HAVE_SYS_FCNTL_H)
70 #include <sys/fcntl.h>
73 #ifdef HAVE_SYS_TIME_H
74 # include <sys/time.h>
79 #if defined(HAVE_SYS_PARAM_H) || defined(__HIUX_MPP__)
80 # include <sys/param.h>
93 #elif defined HAVE_SYS_SYSCALL_H
94 #include <sys/syscall.h>
101 #ifdef HAVE_SYS_WAIT_H
102 # include <sys/wait.h> /* for WNOHANG on BSD */
105 #ifdef HAVE_COPYFILE_H
106 # include <copyfile.h>
109 #include "ruby/internal/stdbool.h"
110 #include "ccan/list/list.h"
112 #include "encindex.h"
114 #include "internal.h"
115 #include "internal/class.h"
116 #include "internal/encoding.h"
117 #include "internal/error.h"
118 #include "internal/inits.h"
119 #include "internal/io.h"
120 #include "internal/numeric.h"
121 #include "internal/object.h"
122 #include "internal/process.h"
123 #include "internal/thread.h"
124 #include "internal/transcode.h"
125 #include "internal/variable.h"
127 #include "ruby/io/buffer.h"
128 #include "ruby/missing.h"
129 #include "ruby/thread.h"
130 #include "ruby/util.h"
131 #include "ruby_atomic.h"
132 #include "ruby/ractor.h"
135 # include "vm_core.h"
141 #define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR)
145 # ifdef _POSIX_PIPE_BUF
146 # define PIPE_BUF _POSIX_PIPE_BUF
148 # define PIPE_BUF 512 /* is this ok? */
153 # define EWOULDBLOCK EAGAIN
156 #if defined(HAVE___SYSCALL) && (defined(__APPLE__) || defined(__OpenBSD__))
157 /* Mac OS X and OpenBSD have __syscall but don't define it in headers */
158 off_t
__syscall(quad_t number
, ...);
161 #define IO_RBUF_CAPA_MIN 8192
162 #define IO_CBUF_CAPA_MIN (128*1024)
163 #define IO_RBUF_CAPA_FOR(fptr) (NEED_READCONV(fptr) ? IO_CBUF_CAPA_MIN : IO_RBUF_CAPA_MIN)
164 #define IO_WBUF_CAPA_MIN 8192
166 #define IO_MAX_BUFFER_GROWTH 8 * 1024 * 1024 // 8MB
168 /* define system APIs */
171 #define open rb_w32_uopen
173 #define rename(f, t) rb_w32_urename((f), (t))
174 #include "win32/file.h"
180 VALUE rb_eIOTimeoutError
;
181 VALUE rb_mWaitReadable
;
182 VALUE rb_mWaitWritable
;
184 static VALUE rb_eEAGAINWaitReadable
;
185 static VALUE rb_eEAGAINWaitWritable
;
186 static VALUE rb_eEWOULDBLOCKWaitReadable
;
187 static VALUE rb_eEWOULDBLOCKWaitWritable
;
188 static VALUE rb_eEINPROGRESSWaitWritable
;
189 static VALUE rb_eEINPROGRESSWaitReadable
;
191 VALUE rb_stdin
, rb_stdout
, rb_stderr
;
192 static VALUE orig_stdout
, orig_stderr
;
201 static ID id_write
, id_read
, id_getc
, id_flush
, id_readpartial
, id_set_encoding
, id_fileno
;
202 static VALUE sym_mode
, sym_perm
, sym_flags
, sym_extenc
, sym_intenc
, sym_encoding
, sym_open_args
;
203 static VALUE sym_textmode
, sym_binmode
, sym_autoclose
;
204 static VALUE sym_SET
, sym_CUR
, sym_END
;
205 static VALUE sym_wait_readable
, sym_wait_writable
;
207 static VALUE sym_DATA
;
210 static VALUE sym_HOLE
;
213 static VALUE
prep_io(int fd
, int fmode
, VALUE klass
, const char *path
);
216 VALUE filename
, current_file
;
217 long last_lineno
; /* $. */
221 struct rb_io_encoding encs
;
222 int8_t init_p
, next_p
, binmode
;
225 static rb_atomic_t max_file_descriptor
= NOFILE
;
227 rb_update_max_fd(int fd
)
229 rb_atomic_t afd
= (rb_atomic_t
)fd
;
230 rb_atomic_t max_fd
= max_file_descriptor
;
233 if (fd
< 0 || afd
<= max_fd
)
236 #if defined(HAVE_FCNTL) && defined(F_GETFL)
237 err
= fcntl(fd
, F_GETFL
) == -1;
241 err
= fstat(fd
, &buf
) != 0;
244 if (err
&& errno
== EBADF
) {
245 rb_bug("rb_update_max_fd: invalid fd (%d) given.", fd
);
248 while (max_fd
< afd
) {
249 max_fd
= ATOMIC_CAS(max_file_descriptor
, max_fd
, afd
);
254 rb_maygvl_fd_fix_cloexec(int fd
)
256 /* MinGW don't have F_GETFD and FD_CLOEXEC. [ruby-core:40281] */
257 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
258 int flags
, flags2
, ret
;
259 flags
= fcntl(fd
, F_GETFD
); /* should not fail except EBADF. */
261 rb_bug("rb_maygvl_fd_fix_cloexec: fcntl(%d, F_GETFD) failed: %s", fd
, strerror(errno
));
264 flags2
= flags
& ~FD_CLOEXEC
; /* Clear CLOEXEC for standard file descriptors: 0, 1, 2. */
266 flags2
= flags
| FD_CLOEXEC
; /* Set CLOEXEC for non-standard file descriptors: 3, 4, 5, ... */
267 if (flags
!= flags2
) {
268 ret
= fcntl(fd
, F_SETFD
, flags2
);
270 rb_bug("rb_maygvl_fd_fix_cloexec: fcntl(%d, F_SETFD, %d) failed: %s", fd
, flags2
, strerror(errno
));
277 rb_fd_fix_cloexec(int fd
)
279 rb_maygvl_fd_fix_cloexec(fd
);
280 rb_update_max_fd(fd
);
283 /* this is only called once */
285 rb_fix_detect_o_cloexec(int fd
)
287 #if defined(O_CLOEXEC) && defined(F_GETFD)
288 int flags
= fcntl(fd
, F_GETFD
);
291 rb_bug("rb_fix_detect_o_cloexec: fcntl(%d, F_GETFD) failed: %s", fd
, strerror(errno
));
293 if (flags
& FD_CLOEXEC
)
295 #endif /* fall through if O_CLOEXEC does not work: */
296 rb_maygvl_fd_fix_cloexec(fd
);
303 return (e
== EWOULDBLOCK
) || (e
== EAGAIN
);
307 rb_cloexec_open(const char *pathname
, int flags
, mode_t mode
)
310 static int o_cloexec_state
= -1; /* <0: unknown, 0: ignored, >0: working */
312 static const int retry_interval
= 0;
313 static const int retry_max_count
= 10000;
318 /* O_CLOEXEC is available since Linux 2.6.23. Linux 2.6.18 silently ignore it. */
320 #elif defined O_NOINHERIT
321 flags
|= O_NOINHERIT
;
324 while ((ret
= open(pathname
, flags
, mode
)) == -1) {
326 if (!io_again_p(e
)) break;
327 if (retry_count
++ >= retry_max_count
) break;
329 sleep(retry_interval
);
332 if (ret
< 0) return ret
;
333 if (ret
<= 2 || o_cloexec_state
== 0) {
334 rb_maygvl_fd_fix_cloexec(ret
);
336 else if (o_cloexec_state
> 0) {
340 o_cloexec_state
= rb_fix_detect_o_cloexec(ret
);
346 rb_cloexec_dup(int oldfd
)
348 /* Don't allocate standard file descriptors: 0, 1, 2 */
349 return rb_cloexec_fcntl_dupfd(oldfd
, 3);
353 rb_cloexec_dup2(int oldfd
, int newfd
)
357 /* When oldfd == newfd, dup2 succeeds but dup3 fails with EINVAL.
358 * rb_cloexec_dup2 succeeds as dup2. */
359 if (oldfd
== newfd
) {
363 #if defined(HAVE_DUP3) && defined(O_CLOEXEC)
364 static int try_dup3
= 1;
365 if (2 < newfd
&& try_dup3
) {
366 ret
= dup3(oldfd
, newfd
, O_CLOEXEC
);
369 /* dup3 is available since Linux 2.6.27, glibc 2.9. */
370 if (errno
== ENOSYS
) {
372 ret
= dup2(oldfd
, newfd
);
376 ret
= dup2(oldfd
, newfd
);
379 ret
= dup2(oldfd
, newfd
);
381 if (ret
< 0) return ret
;
383 rb_maygvl_fd_fix_cloexec(ret
);
388 rb_fd_set_nonblock(int fd
)
391 return rb_w32_set_nonblock(fd
);
392 #elif defined(F_GETFL)
393 int oflags
= fcntl(fd
, F_GETFL
);
397 if (oflags
& O_NONBLOCK
)
399 oflags
|= O_NONBLOCK
;
400 return fcntl(fd
, F_SETFL
, oflags
);
406 rb_cloexec_pipe(int descriptors
[2])
409 int result
= pipe2(descriptors
, O_CLOEXEC
| O_NONBLOCK
);
411 int result
= pipe(descriptors
);
418 if (result
== 0 && descriptors
[1] == -1) {
419 close(descriptors
[0]);
427 rb_maygvl_fd_fix_cloexec(descriptors
[0]);
428 rb_maygvl_fd_fix_cloexec(descriptors
[1]);
431 rb_fd_set_nonblock(descriptors
[0]);
432 rb_fd_set_nonblock(descriptors
[1]);
440 rb_cloexec_fcntl_dupfd(int fd
, int minfd
)
444 #if defined(HAVE_FCNTL) && defined(F_DUPFD_CLOEXEC) && defined(F_DUPFD)
445 static int try_dupfd_cloexec
= 1;
446 if (try_dupfd_cloexec
) {
447 ret
= fcntl(fd
, F_DUPFD_CLOEXEC
, minfd
);
450 rb_maygvl_fd_fix_cloexec(ret
);
453 /* F_DUPFD_CLOEXEC is available since Linux 2.6.24. Linux 2.6.18 fails with EINVAL */
454 if (errno
== EINVAL
) {
455 ret
= fcntl(fd
, F_DUPFD
, minfd
);
457 try_dupfd_cloexec
= 0;
462 ret
= fcntl(fd
, F_DUPFD
, minfd
);
464 #elif defined(HAVE_FCNTL) && defined(F_DUPFD)
465 ret
= fcntl(fd
, F_DUPFD
, minfd
);
468 if (ret
>= 0 && ret
< minfd
) {
469 const int prev_fd
= ret
;
470 ret
= rb_cloexec_fcntl_dupfd(fd
, minfd
);
475 if (ret
< 0) return ret
;
476 rb_maygvl_fd_fix_cloexec(ret
);
480 #define argf_of(obj) (*(struct argf *)DATA_PTR(obj))
481 #define ARGF argf_of(argf)
483 #define GetWriteIO(io) rb_io_get_write_io(io)
485 #define READ_DATA_PENDING(fptr) ((fptr)->rbuf.len)
486 #define READ_DATA_PENDING_COUNT(fptr) ((fptr)->rbuf.len)
487 #define READ_DATA_PENDING_PTR(fptr) ((fptr)->rbuf.ptr+(fptr)->rbuf.off)
488 #define READ_DATA_BUFFERED(fptr) READ_DATA_PENDING(fptr)
490 #define READ_CHAR_PENDING(fptr) ((fptr)->cbuf.len)
491 #define READ_CHAR_PENDING_COUNT(fptr) ((fptr)->cbuf.len)
492 #define READ_CHAR_PENDING_PTR(fptr) ((fptr)->cbuf.ptr+(fptr)->cbuf.off)
495 #define WAIT_FD_IN_WIN32(fptr) \
496 (rb_w32_io_cancelable_p((fptr)->fd) ? Qnil : rb_io_wait(fptr->self, RB_INT2NUM(RUBY_IO_READABLE), RUBY_IO_TIMEOUT_DEFAULT))
498 #define WAIT_FD_IN_WIN32(fptr)
501 #define READ_CHECK(fptr) do {\
502 if (!READ_DATA_PENDING(fptr)) {\
503 WAIT_FD_IN_WIN32(fptr);\
504 rb_io_check_closed(fptr);\
510 # define S_ISSOCK(m) _S_ISSOCK(m)
513 # define S_ISSOCK(m) (((m) & S_IFMT) == _S_IFSOCK)
516 # define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
522 static int io_fflush(rb_io_t
*);
523 static rb_io_t
*flush_before_seek(rb_io_t
*fptr
);
525 #define FMODE_SIGNAL_ON_EPIPE (1<<17)
527 #define fptr_signal_on_epipe(fptr) \
528 (((fptr)->mode & FMODE_SIGNAL_ON_EPIPE) != 0)
530 #define fptr_set_signal_on_epipe(fptr, flag) \
532 (fptr)->mode |= FMODE_SIGNAL_ON_EPIPE : \
533 (fptr)->mode &= ~FMODE_SIGNAL_ON_EPIPE)
535 extern ID ruby_static_id_signo
;
537 NORETURN(static void rb_sys_fail_on_write(rb_io_t
*fptr
));
539 rb_sys_fail_on_write(rb_io_t
*fptr
)
542 VALUE errinfo
= rb_syserr_new_path(e
, (fptr
)->pathv
);
544 if (fptr_signal_on_epipe(fptr
) && (e
== EPIPE
)) {
547 INT2FIX(SIGPIPE
) - INT2FIX(0) +
550 rb_ivar_set(errinfo
, ruby_static_id_signo
, sig
);
553 rb_exc_raise(errinfo
);
556 #define NEED_NEWLINE_DECORATOR_ON_READ(fptr) ((fptr)->mode & FMODE_TEXTMODE)
557 #define NEED_NEWLINE_DECORATOR_ON_WRITE(fptr) ((fptr)->mode & FMODE_TEXTMODE)
558 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
559 # define RUBY_CRLF_ENVIRONMENT 1
561 # define RUBY_CRLF_ENVIRONMENT 0
564 #if RUBY_CRLF_ENVIRONMENT
566 # define DEFAULT_TEXTMODE FMODE_TEXTMODE
567 # define TEXTMODE_NEWLINE_DECORATOR_ON_WRITE ECONV_CRLF_NEWLINE_DECORATOR
569 * CRLF newline is set as default newline decorator.
570 * If only CRLF newline conversion is needed, we use binary IO process
571 * with OS's text mode for IO performance improvement.
572 * If encoding conversion is needed or a user sets text mode, we use encoding
573 * conversion IO process and universal newline decorator by default.
575 #define NEED_READCONV(fptr) ((fptr)->encs.enc2 != NULL || (fptr)->encs.ecflags & ~ECONV_CRLF_NEWLINE_DECORATOR)
576 #define WRITECONV_MASK ( \
577 (ECONV_DECORATOR_MASK & ~ECONV_CRLF_NEWLINE_DECORATOR)|\
578 ECONV_STATEFUL_DECORATOR_MASK|\
580 #define NEED_WRITECONV(fptr) ( \
581 ((fptr)->encs.enc != NULL && (fptr)->encs.enc != rb_ascii8bit_encoding()) || \
582 ((fptr)->encs.ecflags & WRITECONV_MASK) || \
584 #define SET_BINARY_MODE(fptr) setmode((fptr)->fd, O_BINARY)
586 #define NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr) do {\
587 if (NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {\
588 if (((fptr)->mode & FMODE_READABLE) &&\
589 !((fptr)->encs.ecflags & ECONV_NEWLINE_DECORATOR_MASK)) {\
590 setmode((fptr)->fd, O_BINARY);\
593 setmode((fptr)->fd, O_TEXT);\
598 #define SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags) do {\
599 if ((enc2) && ((ecflags) & ECONV_DEFAULT_NEWLINE_DECORATOR)) {\
600 (ecflags) |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;\
605 * IO unread with taking care of removed '\r' in text mode.
608 io_unread(rb_io_t
*fptr
)
618 rb_io_check_closed(fptr
);
619 if (fptr
->rbuf
.len
== 0 || fptr
->mode
& FMODE_DUPLEX
) {
624 if (!rb_w32_fd_is_text(fptr
->fd
)) {
625 r
= lseek(fptr
->fd
, -fptr
->rbuf
.len
, SEEK_CUR
);
626 if (r
< 0 && errno
) {
628 fptr
->mode
|= FMODE_DUPLEX
;
637 pos
= lseek(fptr
->fd
, 0, SEEK_CUR
);
638 if (pos
< 0 && errno
) {
640 fptr
->mode
|= FMODE_DUPLEX
;
644 /* add extra offset for removed '\r' in rbuf */
645 extra_max
= (long)(pos
- fptr
->rbuf
.len
);
646 p
= fptr
->rbuf
.ptr
+ fptr
->rbuf
.off
;
648 /* if the end of rbuf is '\r', rbuf doesn't have '\r' within rbuf.len */
649 if (*(fptr
->rbuf
.ptr
+ fptr
->rbuf
.capa
- 1) == '\r') {
653 for (i
= 0; i
< fptr
->rbuf
.len
; i
++) {
654 if (*p
== '\n') newlines
++;
655 if (extra_max
== newlines
) break;
659 buf
= ALLOC_N(char, fptr
->rbuf
.len
+ newlines
);
660 while (newlines
>= 0) {
661 r
= lseek(fptr
->fd
, pos
- fptr
->rbuf
.len
- newlines
, SEEK_SET
);
662 if (newlines
== 0) break;
667 read_size
= _read(fptr
->fd
, buf
, fptr
->rbuf
.len
+ newlines
);
671 rb_syserr_fail_path(e
, fptr
->pathv
);
673 if (read_size
== fptr
->rbuf
.len
) {
674 lseek(fptr
->fd
, r
, SEEK_SET
);
688 * We use io_seek to back cursor position when changing mode from text to binary,
689 * but stdin and pipe cannot seek back. Stdin and pipe read should use encoding
690 * conversion for working properly with mode change.
692 * Return previous translation mode.
695 set_binary_mode_with_seek_cur(rb_io_t
*fptr
)
697 if (!rb_w32_fd_is_text(fptr
->fd
)) return O_BINARY
;
699 if (fptr
->rbuf
.len
== 0 || fptr
->mode
& FMODE_DUPLEX
) {
700 return setmode(fptr
->fd
, O_BINARY
);
702 flush_before_seek(fptr
);
703 return setmode(fptr
->fd
, O_BINARY
);
705 #define SET_BINARY_MODE_WITH_SEEK_CUR(fptr) set_binary_mode_with_seek_cur(fptr)
709 # define DEFAULT_TEXTMODE 0
710 #define NEED_READCONV(fptr) ((fptr)->encs.enc2 != NULL || NEED_NEWLINE_DECORATOR_ON_READ(fptr))
711 #define NEED_WRITECONV(fptr) ( \
712 ((fptr)->encs.enc != NULL && (fptr)->encs.enc != rb_ascii8bit_encoding()) || \
713 NEED_NEWLINE_DECORATOR_ON_WRITE(fptr) || \
714 ((fptr)->encs.ecflags & (ECONV_DECORATOR_MASK|ECONV_STATEFUL_DECORATOR_MASK)) || \
716 #define SET_BINARY_MODE(fptr) (void)(fptr)
717 #define NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr) (void)(fptr)
718 #define SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags) ((void)(enc2), (void)(ecflags))
719 #define SET_BINARY_MODE_WITH_SEEK_CUR(fptr) (void)(fptr)
722 #if !defined HAVE_SHUTDOWN && !defined shutdown
723 #define shutdown(a,b) 0
727 #define is_socket(fd, path) rb_w32_is_socket(fd)
728 #elif !defined(S_ISSOCK)
729 #define is_socket(fd, path) 0
732 is_socket(int fd
, VALUE path
)
735 if (fstat(fd
, &sbuf
) < 0)
736 rb_sys_fail_path(path
);
737 return S_ISSOCK(sbuf
.st_mode
);
741 static const char closed_stream
[] = "closed stream";
744 io_fd_check_closed(int fd
)
747 rb_thread_check_ints(); /* check for ruby_error_stream_closed */
748 rb_raise(rb_eIOError
, closed_stream
);
755 rb_raise(rb_eEOFError
, "end of file reached");
759 rb_io_taint_check(VALUE io
)
766 rb_io_check_initialized(rb_io_t
*fptr
)
769 rb_raise(rb_eIOError
, "uninitialized stream");
774 rb_io_check_closed(rb_io_t
*fptr
)
776 rb_io_check_initialized(fptr
);
777 io_fd_check_closed(fptr
->fd
);
781 rb_io_get_fptr(VALUE io
)
783 rb_io_t
*fptr
= RFILE(io
)->fptr
;
784 rb_io_check_initialized(fptr
);
789 rb_io_get_io(VALUE io
)
791 return rb_convert_type_with_id(io
, T_FILE
, "IO", idTo_io
);
795 rb_io_check_io(VALUE io
)
797 return rb_check_convert_type_with_id(io
, T_FILE
, "IO", idTo_io
);
801 rb_io_get_write_io(VALUE io
)
804 write_io
= rb_io_get_fptr(io
)->tied_io_for_writing
;
812 rb_io_set_write_io(VALUE io
, VALUE w
)
815 rb_io_t
*fptr
= rb_io_get_fptr(io
);
822 write_io
= fptr
->tied_io_for_writing
;
823 fptr
->tied_io_for_writing
= w
;
824 return write_io
? write_io
: Qnil
;
829 * timeout -> duration or nil
831 * Get the internal timeout duration or nil if it was not set.
835 rb_io_timeout(VALUE self
)
837 rb_io_t
*fptr
= rb_io_get_fptr(self
);
839 return fptr
->timeout
;
844 * timeout = duration -> duration
845 * timeout = nil -> nil
847 * Sets the internal timeout to the specified duration or nil. The timeout
848 * applies to all blocking operations where possible.
850 * When the operation performs longer than the timeout set, IO::TimeoutError
853 * This affects the following methods (but is not limited to): #gets, #puts,
854 * #read, #write, #wait_readable and #wait_writable. This also affects
855 * blocking socket operations like Socket#accept and Socket#connect.
857 * Some operations like File#open and IO#close are not affected by the
858 * timeout. A timeout during a write operation may leave the IO in an
859 * inconsistent state, e.g. data was partially written. Generally speaking, a
860 * timeout is a last ditch effort to prevent an application from hanging on
861 * slow I/O operations, such as those that occur during a slowloris attack.
864 rb_io_set_timeout(VALUE self
, VALUE timeout
)
867 if (RTEST(timeout
)) {
868 rb_time_interval(timeout
);
871 rb_io_t
*fptr
= rb_io_get_fptr(self
);
873 fptr
->timeout
= timeout
;
880 * IO.try_convert(object) -> new_io or nil
882 * Attempts to convert +object+ into an \IO object via method +to_io+;
883 * returns the new \IO object if successful, or +nil+ otherwise:
885 * IO.try_convert(STDOUT) # => #<IO:<STDOUT>>
886 * IO.try_convert(ARGF) # => #<IO:<STDIN>>
887 * IO.try_convert('STDOUT') # => nil
891 rb_io_s_try_convert(VALUE dummy
, VALUE io
)
893 return rb_io_check_io(io
);
896 #if !RUBY_CRLF_ENVIRONMENT
898 io_unread(rb_io_t
*fptr
)
901 rb_io_check_closed(fptr
);
902 if (fptr
->rbuf
.len
== 0 || fptr
->mode
& FMODE_DUPLEX
)
904 /* xxx: target position may be negative if buffer is filled by ungetc */
906 r
= lseek(fptr
->fd
, -fptr
->rbuf
.len
, SEEK_CUR
);
907 if (r
< 0 && errno
) {
909 fptr
->mode
|= FMODE_DUPLEX
;
918 static rb_encoding
*io_input_encoding(rb_io_t
*fptr
);
921 io_ungetbyte(VALUE str
, rb_io_t
*fptr
)
923 long len
= RSTRING_LEN(str
);
925 if (fptr
->rbuf
.ptr
== NULL
) {
926 const int min_capa
= IO_RBUF_CAPA_FOR(fptr
);
929 #if SIZEOF_LONG > SIZEOF_INT
931 rb_raise(rb_eIOError
, "ungetbyte failed");
934 fptr
->rbuf
.capa
= (int)len
;
936 fptr
->rbuf
.capa
= min_capa
;
937 fptr
->rbuf
.ptr
= ALLOC_N(char, fptr
->rbuf
.capa
);
939 if (fptr
->rbuf
.capa
< len
+ fptr
->rbuf
.len
) {
940 rb_raise(rb_eIOError
, "ungetbyte failed");
942 if (fptr
->rbuf
.off
< len
) {
943 MEMMOVE(fptr
->rbuf
.ptr
+fptr
->rbuf
.capa
-fptr
->rbuf
.len
,
944 fptr
->rbuf
.ptr
+fptr
->rbuf
.off
,
945 char, fptr
->rbuf
.len
);
946 fptr
->rbuf
.off
= fptr
->rbuf
.capa
-fptr
->rbuf
.len
;
948 fptr
->rbuf
.off
-=(int)len
;
949 fptr
->rbuf
.len
+=(int)len
;
950 MEMMOVE(fptr
->rbuf
.ptr
+fptr
->rbuf
.off
, RSTRING_PTR(str
), char, len
);
954 flush_before_seek(rb_io_t
*fptr
)
956 if (io_fflush(fptr
) < 0)
957 rb_sys_fail_on_write(fptr
);
963 #define io_seek(fptr, ofs, whence) (errno = 0, lseek(flush_before_seek(fptr)->fd, (ofs), (whence)))
964 #define io_tell(fptr) lseek(flush_before_seek(fptr)->fd, 0, SEEK_CUR)
973 rb_io_check_char_readable(rb_io_t
*fptr
)
975 rb_io_check_closed(fptr
);
976 if (!(fptr
->mode
& FMODE_READABLE
)) {
977 rb_raise(rb_eIOError
, "not opened for reading");
979 if (fptr
->wbuf
.len
) {
980 if (io_fflush(fptr
) < 0)
981 rb_sys_fail_on_write(fptr
);
983 if (fptr
->tied_io_for_writing
) {
985 GetOpenFile(fptr
->tied_io_for_writing
, wfptr
);
986 if (io_fflush(wfptr
) < 0)
987 rb_sys_fail_on_write(wfptr
);
992 rb_io_check_byte_readable(rb_io_t
*fptr
)
994 rb_io_check_char_readable(fptr
);
995 if (READ_CHAR_PENDING(fptr
)) {
996 rb_raise(rb_eIOError
, "byte oriented read for character buffered IO");
1001 rb_io_check_readable(rb_io_t
*fptr
)
1003 rb_io_check_byte_readable(fptr
);
1007 io_read_encoding(rb_io_t
*fptr
)
1009 if (fptr
->encs
.enc
) {
1010 return fptr
->encs
.enc
;
1012 return rb_default_external_encoding();
1016 io_input_encoding(rb_io_t
*fptr
)
1018 if (fptr
->encs
.enc2
) {
1019 return fptr
->encs
.enc2
;
1021 return io_read_encoding(fptr
);
1025 rb_io_check_writable(rb_io_t
*fptr
)
1027 rb_io_check_closed(fptr
);
1028 if (!(fptr
->mode
& FMODE_WRITABLE
)) {
1029 rb_raise(rb_eIOError
, "not opened for writing");
1031 if (fptr
->rbuf
.len
) {
1037 rb_io_read_pending(rb_io_t
*fptr
)
1039 /* This function is used for bytes and chars. Confusing. */
1040 if (READ_CHAR_PENDING(fptr
))
1041 return 1; /* should raise? */
1042 return READ_DATA_PENDING(fptr
);
1046 rb_io_read_check(rb_io_t
*fptr
)
1048 if (!READ_DATA_PENDING(fptr
)) {
1049 rb_io_wait(fptr
->self
, RB_INT2NUM(RUBY_IO_READABLE
), RUBY_IO_TIMEOUT_DEFAULT
);
1055 rb_gc_for_fd(int err
)
1057 if (err
== EMFILE
|| err
== ENFILE
|| err
== ENOMEM
) {
1064 /* try `expr` upto twice while it returns false and `errno`
1065 * is to GC. Each `errno`s are available as `first_errno` and
1066 * `retried_errno` respectively */
1067 #define TRY_WITH_GC(expr) \
1068 for (int first_errno, retried_errno = 0, retried = 0; \
1071 (!rb_gc_for_fd(first_errno = errno) || !(expr)) && \
1072 (retried_errno = errno, 1)); \
1073 (void)retried_errno, retried = 1)
1080 TRY_WITH_GC((fd
= rb_cloexec_dup(orig
)) >= 0) {
1081 rb_syserr_fail(first_errno
, 0);
1083 rb_update_max_fd(fd
);
1088 io_alloc(VALUE klass
)
1090 NEWOBJ_OF(io
, struct RFile
, klass
, T_FILE
, sizeof(struct RFile
), 0);
1098 # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
1101 struct io_internal_read_struct
{
1109 struct timeval
*timeout
;
1112 struct io_internal_write_struct
{
1120 struct timeval
*timeout
;
1124 struct io_internal_writev_struct
{
1131 const struct iovec
*iov
;
1132 struct timeval
*timeout
;
1136 static int nogvl_wait_for(VALUE th
, rb_io_t
*fptr
, short events
, struct timeval
*timeout
);
1139 * Wait for the given events on the given file descriptor.
1140 * Returns -1 if an error or timeout occurred. +errno+ will be set.
1141 * Returns the event mask if an event occurred.
1144 io_internal_wait(VALUE thread
, rb_io_t
*fptr
, int error
, int events
, struct timeval
*timeout
)
1146 if (!timeout
&& rb_thread_mn_schedulable(thread
)) {
1147 RUBY_ASSERT(errno
== EWOULDBLOCK
|| errno
== EAGAIN
);
1151 int ready
= nogvl_wait_for(thread
, fptr
, events
, timeout
);
1156 else if (ready
== 0) {
1166 internal_read_func(void *ptr
)
1168 struct io_internal_read_struct
*iis
= ptr
;
1171 if (iis
->timeout
&& !iis
->nonblock
) {
1172 if (io_internal_wait(iis
->th
, iis
->fptr
, 0, RB_WAITFD_IN
, iis
->timeout
) == -1) {
1178 result
= read(iis
->fd
, iis
->buf
, iis
->capa
);
1180 if (result
< 0 && !iis
->nonblock
) {
1181 if (io_again_p(errno
)) {
1182 if (io_internal_wait(iis
->th
, iis
->fptr
, errno
, RB_WAITFD_IN
, iis
->timeout
) == -1) {
1194 #if defined __APPLE__
1195 # define do_write_retry(code) do {result = code;} while (result == -1 && errno == EPROTOTYPE)
1197 # define do_write_retry(code) result = code
1201 internal_write_func(void *ptr
)
1203 struct io_internal_write_struct
*iis
= ptr
;
1206 if (iis
->timeout
&& !iis
->nonblock
) {
1207 if (io_internal_wait(iis
->th
, iis
->fptr
, 0, RB_WAITFD_OUT
, iis
->timeout
) == -1) {
1213 do_write_retry(write(iis
->fd
, iis
->buf
, iis
->capa
));
1215 if (result
< 0 && !iis
->nonblock
) {
1217 if (io_again_p(e
)) {
1218 if (io_internal_wait(iis
->th
, iis
->fptr
, errno
, RB_WAITFD_OUT
, iis
->timeout
) == -1) {
1232 internal_writev_func(void *ptr
)
1234 struct io_internal_writev_struct
*iis
= ptr
;
1237 if (iis
->timeout
&& !iis
->nonblock
) {
1238 if (io_internal_wait(iis
->th
, iis
->fptr
, 0, RB_WAITFD_OUT
, iis
->timeout
) == -1) {
1244 do_write_retry(writev(iis
->fd
, iis
->iov
, iis
->iovcnt
));
1246 if (result
< 0 && !iis
->nonblock
) {
1247 if (io_again_p(errno
)) {
1248 if (io_internal_wait(iis
->th
, iis
->fptr
, errno
, RB_WAITFD_OUT
, iis
->timeout
) == -1) {
1262 rb_io_read_memory(rb_io_t
*fptr
, void *buf
, size_t count
)
1264 VALUE scheduler
= rb_fiber_scheduler_current();
1265 if (scheduler
!= Qnil
) {
1266 VALUE result
= rb_fiber_scheduler_io_read_memory(scheduler
, fptr
->self
, buf
, count
, 0);
1268 if (!UNDEF_P(result
)) {
1269 return rb_fiber_scheduler_io_result_apply(result
);
1273 struct io_internal_read_struct iis
= {
1274 .th
= rb_thread_current(),
1284 struct timeval timeout_storage
;
1286 if (fptr
->timeout
!= Qnil
) {
1287 timeout_storage
= rb_time_interval(fptr
->timeout
);
1288 iis
.timeout
= &timeout_storage
;
1291 return (ssize_t
)rb_thread_io_blocking_call(internal_read_func
, &iis
, fptr
->fd
, RB_WAITFD_IN
);
1295 rb_io_write_memory(rb_io_t
*fptr
, const void *buf
, size_t count
)
1297 VALUE scheduler
= rb_fiber_scheduler_current();
1298 if (scheduler
!= Qnil
) {
1299 VALUE result
= rb_fiber_scheduler_io_write_memory(scheduler
, fptr
->self
, buf
, count
, 0);
1301 if (!UNDEF_P(result
)) {
1302 return rb_fiber_scheduler_io_result_apply(result
);
1306 struct io_internal_write_struct iis
= {
1307 .th
= rb_thread_current(),
1317 struct timeval timeout_storage
;
1319 if (fptr
->timeout
!= Qnil
) {
1320 timeout_storage
= rb_time_interval(fptr
->timeout
);
1321 iis
.timeout
= &timeout_storage
;
1324 return (ssize_t
)rb_thread_io_blocking_call(internal_write_func
, &iis
, fptr
->fd
, RB_WAITFD_OUT
);
1329 rb_writev_internal(rb_io_t
*fptr
, const struct iovec
*iov
, int iovcnt
)
1331 if (!iovcnt
) return 0;
1333 VALUE scheduler
= rb_fiber_scheduler_current();
1334 if (scheduler
!= Qnil
) {
1335 // This path assumes at least one `iov`:
1336 VALUE result
= rb_fiber_scheduler_io_write_memory(scheduler
, fptr
->self
, iov
[0].iov_base
, iov
[0].iov_len
, 0);
1338 if (!UNDEF_P(result
)) {
1339 return rb_fiber_scheduler_io_result_apply(result
);
1343 struct io_internal_writev_struct iis
= {
1344 .th
= rb_thread_current(),
1354 struct timeval timeout_storage
;
1356 if (fptr
->timeout
!= Qnil
) {
1357 timeout_storage
= rb_time_interval(fptr
->timeout
);
1358 iis
.timeout
= &timeout_storage
;
1361 return (ssize_t
)rb_thread_io_blocking_call(internal_writev_func
, &iis
, fptr
->fd
, RB_WAITFD_OUT
);
1366 io_flush_buffer_sync(void *arg
)
1368 rb_io_t
*fptr
= arg
;
1369 long l
= fptr
->wbuf
.len
;
1370 ssize_t r
= write(fptr
->fd
, fptr
->wbuf
.ptr
+fptr
->wbuf
.off
, (size_t)l
);
1372 if (fptr
->wbuf
.len
<= r
) {
1379 fptr
->wbuf
.off
+= (int)r
;
1380 fptr
->wbuf
.len
-= (int)r
;
1388 io_flush_buffer_async(VALUE arg
)
1390 rb_io_t
*fptr
= (rb_io_t
*)arg
;
1391 return rb_thread_io_blocking_call(io_flush_buffer_sync
, fptr
, fptr
->fd
, RB_WAITFD_OUT
);
1395 io_flush_buffer(rb_io_t
*fptr
)
1397 if (!NIL_P(fptr
->write_lock
) && rb_mutex_owned_p(fptr
->write_lock
)) {
1398 return (int)io_flush_buffer_async((VALUE
)fptr
);
1401 return (int)rb_mutex_synchronize(fptr
->write_lock
, io_flush_buffer_async
, (VALUE
)fptr
);
1406 io_fflush(rb_io_t
*fptr
)
1408 rb_io_check_closed(fptr
);
1410 if (fptr
->wbuf
.len
== 0)
1413 while (fptr
->wbuf
.len
> 0 && io_flush_buffer(fptr
) != 0) {
1414 if (!rb_io_maybe_wait_writable(errno
, fptr
->self
, RUBY_IO_TIMEOUT_DEFAULT
))
1417 rb_io_check_closed(fptr
);
1424 rb_io_wait(VALUE io
, VALUE events
, VALUE timeout
)
1426 VALUE scheduler
= rb_fiber_scheduler_current();
1428 if (scheduler
!= Qnil
) {
1429 return rb_fiber_scheduler_io_wait(scheduler
, io
, events
, timeout
);
1432 rb_io_t
* fptr
= NULL
;
1433 RB_IO_POINTER(io
, fptr
);
1435 struct timeval tv_storage
;
1436 struct timeval
*tv
= NULL
;
1438 if (NIL_OR_UNDEF_P(timeout
)) {
1439 timeout
= fptr
->timeout
;
1442 if (timeout
!= Qnil
) {
1443 tv_storage
= rb_time_interval(timeout
);
1447 int ready
= rb_thread_wait_for_single_fd(fptr
->fd
, RB_NUM2INT(events
), tv
);
1453 // Not sure if this is necessary:
1454 rb_io_check_closed(fptr
);
1457 return RB_INT2NUM(ready
);
1467 return prep_io(fd
, FMODE_EXTERNAL
, rb_cIO
, NULL
);
1471 io_wait_for_single_fd(int fd
, int events
, struct timeval
*timeout
)
1473 VALUE scheduler
= rb_fiber_scheduler_current();
1475 if (scheduler
!= Qnil
) {
1477 rb_fiber_scheduler_io_wait(scheduler
, io_from_fd(fd
), RB_INT2NUM(events
), rb_fiber_scheduler_make_timeout(timeout
))
1481 return rb_thread_wait_for_single_fd(fd
, events
, timeout
);
1485 rb_io_wait_readable(int f
)
1487 io_fd_check_closed(f
);
1489 VALUE scheduler
= rb_fiber_scheduler_current();
1493 #if defined(ERESTART)
1496 rb_thread_check_ints();
1500 #if EWOULDBLOCK != EAGAIN
1503 if (scheduler
!= Qnil
) {
1505 rb_fiber_scheduler_io_wait_readable(scheduler
, io_from_fd(f
))
1509 io_wait_for_single_fd(f
, RUBY_IO_READABLE
, NULL
);
1519 rb_io_wait_writable(int f
)
1521 io_fd_check_closed(f
);
1523 VALUE scheduler
= rb_fiber_scheduler_current();
1527 #if defined(ERESTART)
1531 * In old Linux, several special files under /proc and /sys don't handle
1532 * select properly. Thus we need avoid to call if don't use O_NONBLOCK.
1533 * Otherwise, we face nasty hang up. Sigh.
1534 * e.g. https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=31b07093c44a7a442394d44423e21d783f5523b8
1535 * https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=31b07093c44a7a442394d44423e21d783f5523b8
1536 * In EINTR case, we only need to call RUBY_VM_CHECK_INTS_BLOCKING().
1537 * Then rb_thread_check_ints() is enough.
1539 rb_thread_check_ints();
1543 #if EWOULDBLOCK != EAGAIN
1546 if (scheduler
!= Qnil
) {
1548 rb_fiber_scheduler_io_wait_writable(scheduler
, io_from_fd(f
))
1552 io_wait_for_single_fd(f
, RUBY_IO_WRITABLE
, NULL
);
1562 rb_wait_for_single_fd(int fd
, int events
, struct timeval
*timeout
)
1564 return io_wait_for_single_fd(fd
, events
, timeout
);
1568 rb_thread_wait_fd(int fd
)
1570 return rb_wait_for_single_fd(fd
, RUBY_IO_READABLE
, NULL
);
1574 rb_thread_fd_writable(int fd
)
1576 return rb_wait_for_single_fd(fd
, RUBY_IO_WRITABLE
, NULL
);
1580 rb_io_maybe_wait(int error
, VALUE io
, VALUE events
, VALUE timeout
)
1582 // fptr->fd can be set to -1 at any time by another thread when the GVL is
1583 // released. Many code, e.g. `io_bufread` didn't check this correctly and
1584 // instead relies on `read(-1) -> -1` which causes this code path. We then
1585 // check here whether the IO was in fact closed. Probably it's better to
1586 // check that `fptr->fd != -1` before using it in syscall.
1587 rb_io_check_closed(RFILE(io
)->fptr
);
1590 // In old Linux, several special files under /proc and /sys don't handle
1591 // select properly. Thus we need avoid to call if don't use O_NONBLOCK.
1592 // Otherwise, we face nasty hang up. Sigh.
1593 // e.g. https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=31b07093c44a7a442394d44423e21d783f5523b8
1594 // https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=31b07093c44a7a442394d44423e21d783f5523b8
1595 // In EINTR case, we only need to call RUBY_VM_CHECK_INTS_BLOCKING().
1596 // Then rb_thread_check_ints() is enough.
1598 #if defined(ERESTART)
1601 // We might have pending interrupts since the previous syscall was interrupted:
1602 rb_thread_check_ints();
1604 // The operation was interrupted, so retry it immediately:
1608 #if EWOULDBLOCK != EAGAIN
1611 // The operation would block, so wait for the specified events:
1612 return rb_io_wait(io
, events
, timeout
);
1615 // Non-specific error, no event is ready:
1621 rb_io_maybe_wait_readable(int error
, VALUE io
, VALUE timeout
)
1623 VALUE result
= rb_io_maybe_wait(error
, io
, RB_INT2NUM(RUBY_IO_READABLE
), timeout
);
1625 if (RTEST(result
)) {
1626 return RB_NUM2INT(result
);
1634 rb_io_maybe_wait_writable(int error
, VALUE io
, VALUE timeout
)
1636 VALUE result
= rb_io_maybe_wait(error
, io
, RB_INT2NUM(RUBY_IO_WRITABLE
), timeout
);
1638 if (RTEST(result
)) {
1639 return RB_NUM2INT(result
);
1647 make_writeconv(rb_io_t
*fptr
)
1649 if (!fptr
->writeconv_initialized
) {
1650 const char *senc
, *denc
;
1655 fptr
->writeconv_initialized
= 1;
1657 ecflags
= fptr
->encs
.ecflags
& ~ECONV_NEWLINE_DECORATOR_READ_MASK
;
1658 ecopts
= fptr
->encs
.ecopts
;
1660 if (!fptr
->encs
.enc
|| (rb_is_ascii8bit_enc(fptr
->encs
.enc
) && !fptr
->encs
.enc2
)) {
1661 /* no encoding conversion */
1662 fptr
->writeconv_pre_ecflags
= 0;
1663 fptr
->writeconv_pre_ecopts
= Qnil
;
1664 fptr
->writeconv
= rb_econv_open_opts("", "", ecflags
, ecopts
);
1665 if (!fptr
->writeconv
)
1666 rb_exc_raise(rb_econv_open_exc("", "", ecflags
));
1667 fptr
->writeconv_asciicompat
= Qnil
;
1670 enc
= fptr
->encs
.enc2
? fptr
->encs
.enc2
: fptr
->encs
.enc
;
1671 senc
= rb_econv_asciicompat_encoding(rb_enc_name(enc
));
1672 if (!senc
&& !(fptr
->encs
.ecflags
& ECONV_STATEFUL_DECORATOR_MASK
)) {
1673 /* single conversion */
1674 fptr
->writeconv_pre_ecflags
= ecflags
;
1675 fptr
->writeconv_pre_ecopts
= ecopts
;
1676 fptr
->writeconv
= NULL
;
1677 fptr
->writeconv_asciicompat
= Qnil
;
1680 /* double conversion */
1681 fptr
->writeconv_pre_ecflags
= ecflags
& ~ECONV_STATEFUL_DECORATOR_MASK
;
1682 fptr
->writeconv_pre_ecopts
= ecopts
;
1684 denc
= rb_enc_name(enc
);
1685 fptr
->writeconv_asciicompat
= rb_str_new2(senc
);
1689 fptr
->writeconv_asciicompat
= rb_str_new2(rb_enc_name(enc
));
1691 ecflags
= fptr
->encs
.ecflags
& (ECONV_ERROR_HANDLER_MASK
|ECONV_STATEFUL_DECORATOR_MASK
);
1692 ecopts
= fptr
->encs
.ecopts
;
1693 fptr
->writeconv
= rb_econv_open_opts(senc
, denc
, ecflags
, ecopts
);
1694 if (!fptr
->writeconv
)
1695 rb_exc_raise(rb_econv_open_exc(senc
, denc
, ecflags
));
1701 /* writing functions */
1702 struct binwrite_arg
{
1716 io_binwrite_string_internal(rb_io_t
*fptr
, const char *ptr
, long length
)
1718 if (fptr
->wbuf
.len
) {
1719 struct iovec iov
[2];
1721 iov
[0].iov_base
= fptr
->wbuf
.ptr
+fptr
->wbuf
.off
;
1722 iov
[0].iov_len
= fptr
->wbuf
.len
;
1723 iov
[1].iov_base
= (void*)ptr
;
1724 iov
[1].iov_len
= length
;
1726 ssize_t result
= rb_writev_internal(fptr
, iov
, 2);
1731 if (result
>= fptr
->wbuf
.len
) {
1732 // We wrote more than the internal buffer:
1733 result
-= fptr
->wbuf
.len
;
1738 // We only wrote less data than the internal buffer:
1739 fptr
->wbuf
.off
+= (int)result
;
1740 fptr
->wbuf
.len
-= (int)result
;
1748 return rb_io_write_memory(fptr
, ptr
, length
);
1753 io_binwrite_string_internal(rb_io_t
*fptr
, const char *ptr
, long length
)
1755 long remaining
= length
;
1757 if (fptr
->wbuf
.len
) {
1758 if (fptr
->wbuf
.len
+length
<= fptr
->wbuf
.capa
) {
1759 if (fptr
->wbuf
.capa
< fptr
->wbuf
.off
+fptr
->wbuf
.len
+length
) {
1760 MEMMOVE(fptr
->wbuf
.ptr
, fptr
->wbuf
.ptr
+fptr
->wbuf
.off
, char, fptr
->wbuf
.len
);
1764 MEMMOVE(fptr
->wbuf
.ptr
+fptr
->wbuf
.off
+fptr
->wbuf
.len
, ptr
, char, length
);
1765 fptr
->wbuf
.len
+= (int)length
;
1767 // We copied the entire incoming data to the internal buffer:
1771 // Flush the internal buffer:
1772 if (io_fflush(fptr
) < 0) {
1776 // If all the data was buffered, we are done:
1777 if (remaining
== 0) {
1782 // Otherwise, we should write the data directly:
1783 return rb_io_write_memory(fptr
, ptr
, length
);
1788 io_binwrite_string(VALUE arg
)
1790 struct binwrite_arg
*p
= (struct binwrite_arg
*)arg
;
1792 const char *ptr
= p
->ptr
;
1793 size_t remaining
= p
->length
;
1796 // Write as much as possible:
1797 ssize_t result
= io_binwrite_string_internal(p
->fptr
, ptr
, remaining
);
1800 // If only the internal buffer is written, result will be zero [bytes of given data written]. This means we
1801 // should try again immediately.
1803 else if (result
> 0) {
1804 if ((size_t)result
== remaining
) break;
1806 remaining
-= result
;
1808 // Wait for it to become writable:
1809 else if (rb_io_maybe_wait_writable(errno
, p
->fptr
->self
, RUBY_IO_TIMEOUT_DEFAULT
)) {
1810 rb_io_check_closed(p
->fptr
);
1813 // The error was unrelated to waiting for it to become writable, so we fail:
1822 io_allocate_write_buffer(rb_io_t
*fptr
, int sync
)
1824 if (fptr
->wbuf
.ptr
== NULL
&& !(sync
&& (fptr
->mode
& FMODE_SYNC
))) {
1827 fptr
->wbuf
.capa
= IO_WBUF_CAPA_MIN
;
1828 fptr
->wbuf
.ptr
= ALLOC_N(char, fptr
->wbuf
.capa
);
1831 if (NIL_P(fptr
->write_lock
)) {
1832 fptr
->write_lock
= rb_mutex_new();
1833 rb_mutex_allow_trap(fptr
->write_lock
, 1);
1838 io_binwrite_requires_flush_write(rb_io_t
*fptr
, long len
, int nosync
)
1840 // If the requested operation was synchronous and the output mode is synchronous or a TTY:
1841 if (!nosync
&& (fptr
->mode
& (FMODE_SYNC
|FMODE_TTY
)))
1844 // If the amount of data we want to write exceeds the internal buffer:
1845 if (fptr
->wbuf
.ptr
&& fptr
->wbuf
.capa
<= fptr
->wbuf
.len
+ len
)
1848 // Otherwise, we can append to the internal buffer:
1853 io_binwrite(const char *ptr
, long len
, rb_io_t
*fptr
, int nosync
)
1855 if (len
<= 0) return len
;
1857 // Don't write anything if current thread has a pending interrupt:
1858 rb_thread_check_ints();
1860 io_allocate_write_buffer(fptr
, !nosync
);
1862 if (io_binwrite_requires_flush_write(fptr
, len
, nosync
)) {
1863 struct binwrite_arg arg
;
1869 if (!NIL_P(fptr
->write_lock
)) {
1870 return rb_mutex_synchronize(fptr
->write_lock
, io_binwrite_string
, (VALUE
)&arg
);
1873 return io_binwrite_string((VALUE
)&arg
);
1877 if (fptr
->wbuf
.off
) {
1879 MEMMOVE(fptr
->wbuf
.ptr
, fptr
->wbuf
.ptr
+fptr
->wbuf
.off
, char, fptr
->wbuf
.len
);
1883 MEMMOVE(fptr
->wbuf
.ptr
+fptr
->wbuf
.off
+fptr
->wbuf
.len
, ptr
, char, len
);
1884 fptr
->wbuf
.len
+= (int)len
;
1890 # define MODE_BTMODE(a,b,c) ((fmode & FMODE_BINMODE) ? (b) : \
1891 (fmode & FMODE_TEXTMODE) ? (c) : (a))
1893 #define MODE_BTXMODE(a, b, c, d, e, f) ((fmode & FMODE_EXCL) ? \
1894 MODE_BTMODE(d, e, f) : \
1895 MODE_BTMODE(a, b, c))
1898 do_writeconv(VALUE str
, rb_io_t
*fptr
, int *converted
)
1900 if (NEED_WRITECONV(fptr
)) {
1901 VALUE common_encoding
= Qnil
;
1902 SET_BINARY_MODE(fptr
);
1904 make_writeconv(fptr
);
1906 if (fptr
->writeconv
) {
1907 #define fmode (fptr->mode)
1908 if (!NIL_P(fptr
->writeconv_asciicompat
))
1909 common_encoding
= fptr
->writeconv_asciicompat
;
1910 else if (MODE_BTMODE(DEFAULT_TEXTMODE
,0,1) && !rb_enc_asciicompat(rb_enc_get(str
))) {
1911 rb_raise(rb_eArgError
, "ASCII incompatible string written for text mode IO without encoding conversion: %s",
1912 rb_enc_name(rb_enc_get(str
)));
1917 if (fptr
->encs
.enc2
)
1918 common_encoding
= rb_enc_from_encoding(fptr
->encs
.enc2
);
1919 else if (fptr
->encs
.enc
!= rb_ascii8bit_encoding())
1920 common_encoding
= rb_enc_from_encoding(fptr
->encs
.enc
);
1923 if (!NIL_P(common_encoding
)) {
1924 str
= rb_str_encode(str
, common_encoding
,
1925 fptr
->writeconv_pre_ecflags
, fptr
->writeconv_pre_ecopts
);
1929 if (fptr
->writeconv
) {
1930 str
= rb_econv_str_convert(fptr
->writeconv
, str
, ECONV_PARTIAL_INPUT
);
1934 #if RUBY_CRLF_ENVIRONMENT
1935 #define fmode (fptr->mode)
1936 else if (MODE_BTMODE(DEFAULT_TEXTMODE
,0,1)) {
1937 if ((fptr
->mode
& FMODE_READABLE
) &&
1938 !(fptr
->encs
.ecflags
& ECONV_NEWLINE_DECORATOR_MASK
)) {
1939 setmode(fptr
->fd
, O_BINARY
);
1942 setmode(fptr
->fd
, O_TEXT
);
1944 if (!rb_enc_asciicompat(rb_enc_get(str
))) {
1945 rb_raise(rb_eArgError
, "ASCII incompatible string written for text mode IO without encoding conversion: %s",
1946 rb_enc_name(rb_enc_get(str
)));
1955 io_fwrite(VALUE str
, rb_io_t
*fptr
, int nosync
)
1963 if (fptr
->mode
& FMODE_TTY
) {
1964 long len
= rb_w32_write_console(str
, fptr
->fd
);
1965 if (len
> 0) return len
;
1969 str
= do_writeconv(str
, fptr
, &converted
);
1973 tmp
= rb_str_tmp_frozen_no_embed_acquire(str
);
1974 RSTRING_GETMEM(tmp
, ptr
, len
);
1975 n
= io_binwrite(ptr
, len
, fptr
, nosync
);
1976 rb_str_tmp_frozen_release(str
, tmp
);
1982 rb_io_bufwrite(VALUE io
, const void *buf
, size_t size
)
1986 GetOpenFile(io
, fptr
);
1987 rb_io_check_writable(fptr
);
1988 return (ssize_t
)io_binwrite(buf
, (long)size
, fptr
, 0);
1992 io_write(VALUE io
, VALUE str
, int nosync
)
1998 io
= GetWriteIO(io
);
1999 str
= rb_obj_as_string(str
);
2000 tmp
= rb_io_check_io(io
);
2003 /* port is not IO, call write method for it. */
2004 return rb_funcall(io
, id_write
, 1, str
);
2008 if (RSTRING_LEN(str
) == 0) return INT2FIX(0);
2010 GetOpenFile(io
, fptr
);
2011 rb_io_check_writable(fptr
);
2013 n
= io_fwrite(str
, fptr
, nosync
);
2014 if (n
< 0L) rb_sys_fail_on_write(fptr
);
2020 struct binwritev_arg
{
2028 io_binwritev_internal(VALUE arg
)
2030 struct binwritev_arg
*p
= (struct binwritev_arg
*)arg
;
2032 size_t remaining
= p
->total
;
2035 rb_io_t
*fptr
= p
->fptr
;
2036 struct iovec
*iov
= p
->iov
;
2037 int iovcnt
= p
->iovcnt
;
2040 long result
= rb_writev_internal(fptr
, iov
, iovcnt
);
2044 if (fptr
->wbuf
.ptr
&& fptr
->wbuf
.len
) {
2045 if (offset
< (size_t)fptr
->wbuf
.len
) {
2046 fptr
->wbuf
.off
+= result
;
2047 fptr
->wbuf
.len
-= result
;
2050 offset
-= (size_t)fptr
->wbuf
.len
;
2056 if (offset
== p
->total
) {
2060 while (result
>= (ssize_t
)iov
->iov_len
) {
2062 result
-= iov
->iov_len
;
2067 // I don't believe this code path can ever occur.
2072 iov
->iov_base
= (char *)iov
->iov_base
+ result
;
2073 iov
->iov_len
-= result
;
2075 else if (rb_io_maybe_wait_writable(errno
, fptr
->self
, RUBY_IO_TIMEOUT_DEFAULT
)) {
2076 rb_io_check_closed(fptr
);
2087 io_binwritev(struct iovec
*iov
, int iovcnt
, rb_io_t
*fptr
)
2089 // Don't write anything if current thread has a pending interrupt:
2090 rb_thread_check_ints();
2092 if (iovcnt
== 0) return 0;
2095 for (int i
= 1; i
< iovcnt
; i
++) total
+= iov
[i
].iov_len
;
2097 io_allocate_write_buffer(fptr
, 1);
2099 if (fptr
->wbuf
.ptr
&& fptr
->wbuf
.len
) {
2100 // The end of the buffered data:
2101 size_t offset
= fptr
->wbuf
.off
+ fptr
->wbuf
.len
;
2103 if (offset
+ total
<= (size_t)fptr
->wbuf
.capa
) {
2104 for (int i
= 1; i
< iovcnt
; i
++) {
2105 memcpy(fptr
->wbuf
.ptr
+offset
, iov
[i
].iov_base
, iov
[i
].iov_len
);
2106 offset
+= iov
[i
].iov_len
;
2109 fptr
->wbuf
.len
+= total
;
2114 iov
[0].iov_base
= fptr
->wbuf
.ptr
+ fptr
->wbuf
.off
;
2115 iov
[0].iov_len
= fptr
->wbuf
.len
;
2119 // The first iov is reserved for the internal buffer, and it's empty.
2123 // If there are no other io vectors we are done.
2128 struct binwritev_arg arg
;
2131 arg
.iovcnt
= iovcnt
;
2134 if (!NIL_P(fptr
->write_lock
)) {
2135 return rb_mutex_synchronize(fptr
->write_lock
, io_binwritev_internal
, (VALUE
)&arg
);
2138 return io_binwritev_internal((VALUE
)&arg
);
2143 io_fwritev(int argc
, const VALUE
*argv
, rb_io_t
*fptr
)
2145 int i
, converted
, iovcnt
= argc
+ 1;
2147 VALUE v1
, v2
, str
, tmp
, *tmp_array
;
2150 iov
= ALLOCV_N(struct iovec
, v1
, iovcnt
);
2151 tmp_array
= ALLOCV_N(VALUE
, v2
, argc
);
2153 for (i
= 0; i
< argc
; i
++) {
2154 str
= rb_obj_as_string(argv
[i
]);
2156 str
= do_writeconv(str
, fptr
, &converted
);
2161 tmp
= rb_str_tmp_frozen_acquire(str
);
2164 /* iov[0] is reserved for buffer of fptr */
2165 iov
[i
+1].iov_base
= RSTRING_PTR(tmp
);
2166 iov
[i
+1].iov_len
= RSTRING_LEN(tmp
);
2169 n
= io_binwritev(iov
, iovcnt
, fptr
);
2170 if (v1
) ALLOCV_END(v1
);
2172 for (i
= 0; i
< argc
; i
++) {
2173 rb_str_tmp_frozen_release(argv
[i
], tmp_array
[i
]);
2176 if (v2
) ALLOCV_END(v2
);
2182 iovcnt_ok(int iovcnt
)
2185 return iovcnt
< IOV_MAX
;
2186 #else /* GNU/Hurd has writev, but no IOV_MAX */
2190 #endif /* HAVE_WRITEV */
2193 io_writev(int argc
, const VALUE
*argv
, VALUE io
)
2197 VALUE tmp
, total
= INT2FIX(0);
2200 io
= GetWriteIO(io
);
2201 tmp
= rb_io_check_io(io
);
2204 /* port is not IO, call write method for it. */
2205 return rb_funcallv(io
, id_write
, argc
, argv
);
2210 GetOpenFile(io
, fptr
);
2211 rb_io_check_writable(fptr
);
2213 for (i
= 0; i
< argc
; i
+= cnt
) {
2215 if ((fptr
->mode
& (FMODE_SYNC
|FMODE_TTY
)) && iovcnt_ok(cnt
= argc
- i
)) {
2216 n
= io_fwritev(cnt
, &argv
[i
], fptr
);
2222 /* sync at last item */
2223 n
= io_fwrite(rb_obj_as_string(argv
[i
]), fptr
, (i
< argc
-1));
2227 rb_sys_fail_on_write(fptr
);
2229 total
= rb_fix_plus(LONG2FIX(n
), total
);
2237 * write(*objects) -> integer
2239 * Writes each of the given +objects+ to +self+,
2240 * which must be opened for writing
2241 * (see {Access Modes}[rdoc-ref:File@Access+Modes]);
2242 * returns the total number bytes written;
2243 * each of +objects+ that is not a string is converted via method +to_s+:
2245 * $stdout.write('Hello', ', ', 'World!', "\n") # => 14
2246 * $stdout.write('foo', :bar, 2, "\n") # => 8
2257 io_write_m(int argc
, VALUE
*argv
, VALUE io
)
2260 return io_writev(argc
, argv
, io
);
2263 VALUE str
= argv
[0];
2264 return io_write(io
, str
, 0);
2269 rb_io_write(VALUE io
, VALUE str
)
2271 return rb_funcallv(io
, id_write
, 1, &str
);
2275 rb_io_writev(VALUE io
, int argc
, const VALUE
*argv
)
2277 if (argc
> 1 && rb_obj_method_arity(io
, id_write
) == 1) {
2278 if (io
!= rb_ractor_stderr() && RTEST(ruby_verbose
)) {
2279 VALUE klass
= CLASS_OF(io
);
2280 char sep
= RCLASS_SINGLETON_P(klass
) ? (klass
= io
, '.') : '#';
2281 rb_category_warning(
2282 RB_WARN_CATEGORY_DEPRECATED
, "%+"PRIsVALUE
"%c""write is outdated interface"
2283 " which accepts just one argument",
2288 do rb_io_write(io
, *argv
++); while (--argc
);
2293 return rb_funcallv(io
, id_write
, argc
, argv
);
2298 * self << object -> self
2300 * Writes the given +object+ to +self+,
2301 * which must be opened for writing (see {Access Modes}[rdoc-ref:File@Access+Modes]);
2303 * if +object+ is not a string, it is converted via method +to_s+:
2305 * $stdout << 'Hello' << ', ' << 'World!' << "\n"
2306 * $stdout << 'foo' << :bar << 2 << "\n"
2317 rb_io_addstr(VALUE io
, VALUE str
)
2319 rb_io_write(io
, str
);
2325 nogvl_fsync(void *ptr
)
2327 rb_io_t
*fptr
= ptr
;
2330 if (GetFileType((HANDLE
)rb_w32_get_osfhandle(fptr
->fd
)) != FILE_TYPE_DISK
)
2333 return (VALUE
)fsync(fptr
->fd
);
2338 rb_io_flush_raw(VALUE io
, int sync
)
2342 if (!RB_TYPE_P(io
, T_FILE
)) {
2343 return rb_funcall(io
, id_flush
, 0);
2346 io
= GetWriteIO(io
);
2347 GetOpenFile(io
, fptr
);
2349 if (fptr
->mode
& FMODE_WRITABLE
) {
2350 if (io_fflush(fptr
) < 0)
2351 rb_sys_fail_on_write(fptr
);
2353 if (fptr
->mode
& FMODE_READABLE
) {
2364 * Flushes data buffered in +self+ to the operating system
2365 * (but does not necessarily flush data buffered in the operating system):
2367 * $stdout.print 'no newline' # Not necessarily flushed.
2368 * $stdout.flush # Flushed.
2373 rb_io_flush(VALUE io
)
2375 return rb_io_flush_raw(io
, 1);
2382 * Returns the current position (in bytes) in +self+
2383 * (see {Position}[rdoc-ref:IO@Position]):
2385 * f = File.open('t.txt')
2387 * f.gets # => "First line\n"
2391 * Related: IO#pos=, IO#seek.
2395 rb_io_tell(VALUE io
)
2400 GetOpenFile(io
, fptr
);
2401 pos
= io_tell(fptr
);
2402 if (pos
< 0 && errno
) rb_sys_fail_path(fptr
->pathv
);
2403 pos
-= fptr
->rbuf
.len
;
2404 return OFFT2NUM(pos
);
2408 rb_io_seek(VALUE io
, VALUE offset
, int whence
)
2413 pos
= NUM2OFFT(offset
);
2414 GetOpenFile(io
, fptr
);
2415 pos
= io_seek(fptr
, pos
, whence
);
2416 if (pos
< 0 && errno
) rb_sys_fail_path(fptr
->pathv
);
2422 interpret_seek_whence(VALUE vwhence
)
2424 if (vwhence
== sym_SET
)
2426 if (vwhence
== sym_CUR
)
2428 if (vwhence
== sym_END
)
2431 if (vwhence
== sym_DATA
)
2435 if (vwhence
== sym_HOLE
)
2438 return NUM2INT(vwhence
);
2443 * seek(offset, whence = IO::SEEK_SET) -> 0
2445 * Seeks to the position given by integer +offset+
2446 * (see {Position}[rdoc-ref:IO@Position])
2447 * and constant +whence+, which is one of:
2449 * - +:CUR+ or <tt>IO::SEEK_CUR</tt>:
2450 * Repositions the stream to its current position plus the given +offset+:
2452 * f = File.open('t.txt')
2454 * f.seek(20, :CUR) # => 0
2456 * f.seek(-10, :CUR) # => 0
2460 * - +:END+ or <tt>IO::SEEK_END</tt>:
2461 * Repositions the stream to its end plus the given +offset+:
2463 * f = File.open('t.txt')
2465 * f.seek(0, :END) # => 0 # Repositions to stream end.
2467 * f.seek(-20, :END) # => 0
2469 * f.seek(-40, :END) # => 0
2473 * - +:SET+ or <tt>IO:SEEK_SET</tt>:
2474 * Repositions the stream to the given +offset+:
2476 * f = File.open('t.txt')
2478 * f.seek(20, :SET) # => 0
2480 * f.seek(40, :SET) # => 0
2484 * Related: IO#pos=, IO#tell.
2489 rb_io_seek_m(int argc
, VALUE
*argv
, VALUE io
)
2491 VALUE offset
, ptrname
;
2492 int whence
= SEEK_SET
;
2494 if (rb_scan_args(argc
, argv
, "11", &offset
, &ptrname
) == 2) {
2495 whence
= interpret_seek_whence(ptrname
);
2498 return rb_io_seek(io
, offset
, whence
);
2503 * pos = new_position -> new_position
2505 * Seeks to the given +new_position+ (in bytes);
2506 * see {Position}[rdoc-ref:IO@Position]:
2508 * f = File.open('t.txt')
2510 * f.pos = 20 # => 20
2514 * Related: IO#seek, IO#tell.
2519 rb_io_set_pos(VALUE io
, VALUE offset
)
2524 pos
= NUM2OFFT(offset
);
2525 GetOpenFile(io
, fptr
);
2526 pos
= io_seek(fptr
, pos
, SEEK_SET
);
2527 if (pos
< 0 && errno
) rb_sys_fail_path(fptr
->pathv
);
2529 return OFFT2NUM(pos
);
2532 static void clear_readconv(rb_io_t
*fptr
);
2538 * Repositions the stream to its beginning,
2539 * setting both the position and the line number to zero;
2540 * see {Position}[rdoc-ref:IO@Position]
2541 * and {Line Number}[rdoc-ref:IO@Line+Number]:
2543 * f = File.open('t.txt')
2546 * f.gets # => "First line\n"
2554 * Note that this method cannot be used with streams such as pipes, ttys, and sockets.
2559 rb_io_rewind(VALUE io
)
2563 GetOpenFile(io
, fptr
);
2564 if (io_seek(fptr
, 0L, 0) < 0 && errno
) rb_sys_fail_path(fptr
->pathv
);
2565 if (io
== ARGF
.current_file
) {
2566 ARGF
.lineno
-= fptr
->lineno
;
2569 if (fptr
->readconv
) {
2570 clear_readconv(fptr
);
2577 fptr_wait_readable(rb_io_t
*fptr
)
2579 int result
= rb_io_maybe_wait_readable(errno
, fptr
->self
, RUBY_IO_TIMEOUT_DEFAULT
);
2582 rb_io_check_closed(fptr
);
2588 io_fillbuf(rb_io_t
*fptr
)
2592 if (fptr
->rbuf
.ptr
== NULL
) {
2595 fptr
->rbuf
.capa
= IO_RBUF_CAPA_FOR(fptr
);
2596 fptr
->rbuf
.ptr
= ALLOC_N(char, fptr
->rbuf
.capa
);
2601 if (fptr
->rbuf
.len
== 0) {
2603 r
= rb_io_read_memory(fptr
, fptr
->rbuf
.ptr
, fptr
->rbuf
.capa
);
2606 if (fptr_wait_readable(fptr
))
2610 VALUE path
= rb_sprintf("fd:%d ", fptr
->fd
);
2611 if (!NIL_P(fptr
->pathv
)) {
2612 rb_str_append(path
, fptr
->pathv
);
2615 rb_syserr_fail_path(e
, path
);
2617 if (r
> 0) rb_io_check_closed(fptr
);
2619 fptr
->rbuf
.len
= (int)r
; /* r should be <= rbuf_capa */
2621 return -1; /* EOF */
2628 * eof -> true or false
2630 * Returns +true+ if the stream is positioned at its end, +false+ otherwise;
2631 * see {Position}[rdoc-ref:IO@Position]:
2633 * f = File.open('t.txt')
2635 * f.seek(0, :END) # => 0
2639 * Raises an exception unless the stream is opened for reading;
2640 * see {Mode}[rdoc-ref:File@Access+Modes].
2642 * If +self+ is a stream such as pipe or socket, this method
2643 * blocks until the other end sends some data or closes it:
2646 * Thread.new { sleep 1; w.close }
2647 * r.eof? # => true # After 1-second wait.
2650 * Thread.new { sleep 1; w.puts "a" }
2651 * r.eof? # => false # After 1-second wait.
2654 * r.eof? # blocks forever
2656 * Note that this method reads data to the input byte buffer. So
2657 * IO#sysread may not behave as you intend with IO#eof?, unless you
2658 * call IO#rewind first (which is not available for some streams).
2666 GetOpenFile(io
, fptr
);
2667 rb_io_check_char_readable(fptr
);
2669 if (READ_CHAR_PENDING(fptr
)) return Qfalse
;
2670 if (READ_DATA_PENDING(fptr
)) return Qfalse
;
2672 #if RUBY_CRLF_ENVIRONMENT
2673 if (!NEED_READCONV(fptr
) && NEED_NEWLINE_DECORATOR_ON_READ(fptr
)) {
2674 return RBOOL(eof(fptr
->fd
));
2677 return RBOOL(io_fillbuf(fptr
) < 0);
2682 * sync -> true or false
2684 * Returns the current sync mode of the stream.
2685 * When sync mode is true, all output is immediately flushed to the underlying
2686 * operating system and is not buffered by Ruby internally. See also #fsync.
2688 * f = File.open('t.tmp', 'w')
2697 rb_io_sync(VALUE io
)
2701 io
= GetWriteIO(io
);
2702 GetOpenFile(io
, fptr
);
2703 return RBOOL(fptr
->mode
& FMODE_SYNC
);
2710 * sync = boolean -> boolean
2712 * Sets the _sync_ _mode_ for the stream to the given value;
2713 * returns the given value.
2715 * Values for the sync mode:
2717 * - +true+: All output is immediately flushed to the
2718 * underlying operating system and is not buffered internally.
2719 * - +false+: Output may be buffered internally.
2723 * f = File.open('t.tmp', 'w')
2729 * Related: IO#fsync.
2734 rb_io_set_sync(VALUE io
, VALUE sync
)
2738 io
= GetWriteIO(io
);
2739 GetOpenFile(io
, fptr
);
2741 fptr
->mode
|= FMODE_SYNC
;
2744 fptr
->mode
&= ~FMODE_SYNC
;
2753 * Immediately writes to disk all data buffered in the stream,
2754 * via the operating system's <tt>fsync(2)</tt>.
2756 * Note this difference:
2758 * - IO#sync=: Ensures that data is flushed from the stream's internal buffers,
2759 * but does not guarantee that the operating system actually writes the data to disk.
2760 * - IO#fsync: Ensures both that data is flushed from internal buffers,
2761 * and that data is written to disk.
2763 * Raises an exception if the operating system does not support <tt>fsync(2)</tt>.
2768 rb_io_fsync(VALUE io
)
2772 io
= GetWriteIO(io
);
2773 GetOpenFile(io
, fptr
);
2775 if (io_fflush(fptr
) < 0)
2776 rb_sys_fail_on_write(fptr
);
2777 if ((int)rb_thread_io_blocking_region(nogvl_fsync
, fptr
, fptr
->fd
) < 0)
2778 rb_sys_fail_path(fptr
->pathv
);
2782 # define rb_io_fsync rb_f_notimplement
2783 # define rb_io_sync rb_f_notimplement
2785 rb_io_set_sync(VALUE io
, VALUE sync
)
2792 #ifdef HAVE_FDATASYNC
2794 nogvl_fdatasync(void *ptr
)
2796 rb_io_t
*fptr
= ptr
;
2799 if (GetFileType((HANDLE
)rb_w32_get_osfhandle(fptr
->fd
)) != FILE_TYPE_DISK
)
2802 return (VALUE
)fdatasync(fptr
->fd
);
2809 * Immediately writes to disk all data buffered in the stream,
2810 * via the operating system's: <tt>fdatasync(2)</tt>, if supported,
2811 * otherwise via <tt>fsync(2)</tt>, if supported;
2812 * otherwise raises an exception.
2817 rb_io_fdatasync(VALUE io
)
2821 io
= GetWriteIO(io
);
2822 GetOpenFile(io
, fptr
);
2824 if (io_fflush(fptr
) < 0)
2825 rb_sys_fail_on_write(fptr
);
2827 if ((int)rb_thread_io_blocking_region(nogvl_fdatasync
, fptr
, fptr
->fd
) == 0)
2831 return rb_io_fsync(io
);
2834 #define rb_io_fdatasync rb_io_fsync
2841 * Returns the integer file descriptor for the stream:
2843 * $stdin.fileno # => 0
2844 * $stdout.fileno # => 1
2845 * $stderr.fileno # => 2
2846 * File.open('t.txt').fileno # => 10
2852 rb_io_fileno(VALUE io
)
2854 rb_io_t
*fptr
= RFILE(io
)->fptr
;
2857 rb_io_check_closed(fptr
);
2863 rb_io_descriptor(VALUE io
)
2865 if (RB_TYPE_P(io
, T_FILE
)) {
2866 rb_io_t
*fptr
= RFILE(io
)->fptr
;
2867 rb_io_check_closed(fptr
);
2871 VALUE fileno
= rb_check_funcall(io
, id_fileno
, 0, NULL
);
2872 if (!UNDEF_P(fileno
)) {
2873 return RB_NUM2INT(fileno
);
2877 rb_raise(rb_eTypeError
, "expected IO or #fileno, %"PRIsVALUE
" given", rb_obj_class(io
));
2879 UNREACHABLE_RETURN(-1);
2883 rb_io_mode(VALUE io
)
2886 GetOpenFile(io
, fptr
);
2892 * pid -> integer or nil
2894 * Returns the process ID of a child process associated with the stream,
2895 * which will have been set by IO#popen, or +nil+ if the stream was not
2896 * created by IO#popen:
2898 * pipe = IO.popen("-")
2900 * $stderr.puts "In parent, child pid is #{pipe.pid}"
2902 * $stderr.puts "In child, pid is #{$$}"
2907 * In child, pid is 26209
2908 * In parent, child pid is 26209
2917 GetOpenFile(io
, fptr
);
2920 return PIDT2NUM(fptr
->pid
);
2925 * path -> string or nil
2927 * Returns the path associated with the IO, or +nil+ if there is no path
2928 * associated with the IO. It is not guaranteed that the path exists on
2931 * $stdin.path # => "<STDIN>"
2933 * File.open("testfile") {|f| f.path} # => "testfile"
2937 rb_io_path(VALUE io
)
2939 rb_io_t
*fptr
= RFILE(io
)->fptr
;
2944 return rb_obj_dup(fptr
->pathv
);
2951 * Returns a string representation of +self+:
2953 * f = File.open('t.txt')
2954 * f.inspect # => "#<File:t.txt>"
2960 rb_io_inspect(VALUE obj
)
2964 static const char closed
[] = " (closed)";
2966 fptr
= RFILE(obj
)->fptr
;
2967 if (!fptr
) return rb_any_to_s(obj
);
2968 result
= rb_str_new_cstr("#<");
2969 rb_str_append(result
, rb_class_name(CLASS_OF(obj
)));
2970 rb_str_cat2(result
, ":");
2971 if (NIL_P(fptr
->pathv
)) {
2973 rb_str_cat(result
, closed
+1, strlen(closed
)-1);
2976 rb_str_catf(result
, "fd %d", fptr
->fd
);
2980 rb_str_append(result
, fptr
->pathv
);
2982 rb_str_cat(result
, closed
, strlen(closed
));
2985 return rb_str_cat2(result
, ">");
2997 rb_io_to_io(VALUE io
)
3002 /* reading functions */
3004 read_buffered_data(char *ptr
, long len
, rb_io_t
*fptr
)
3008 n
= READ_DATA_PENDING_COUNT(fptr
);
3009 if (n
<= 0) return 0;
3010 if (n
> len
) n
= (int)len
;
3011 MEMMOVE(ptr
, fptr
->rbuf
.ptr
+fptr
->rbuf
.off
, char, n
);
3012 fptr
->rbuf
.off
+= n
;
3013 fptr
->rbuf
.len
-= n
;
3018 io_bufread(char *ptr
, long len
, rb_io_t
*fptr
)
3024 if (READ_DATA_PENDING(fptr
) == 0) {
3027 rb_io_check_closed(fptr
);
3028 c
= rb_io_read_memory(fptr
, ptr
+offset
, n
);
3031 if (fptr_wait_readable(fptr
))
3036 if ((n
-= c
) <= 0) break;
3042 c
= read_buffered_data(ptr
+offset
, n
, fptr
);
3045 if ((n
-= c
) <= 0) break;
3047 rb_io_check_closed(fptr
);
3048 if (io_fillbuf(fptr
) < 0) {
3055 static int io_setstrbuf(VALUE
*str
, long len
);
3057 struct bufread_arg
{
3064 bufread_call(VALUE arg
)
3066 struct bufread_arg
*p
= (struct bufread_arg
*)arg
;
3067 p
->len
= io_bufread(p
->str_ptr
, p
->len
, p
->fptr
);
3072 io_fread(VALUE str
, long offset
, long size
, rb_io_t
*fptr
)
3075 struct bufread_arg arg
;
3077 io_setstrbuf(&str
, offset
+ size
);
3078 arg
.str_ptr
= RSTRING_PTR(str
) + offset
;
3081 rb_str_locktmp_ensure(str
, bufread_call
, (VALUE
)&arg
);
3083 if (len
< 0) rb_sys_fail_path(fptr
->pathv
);
3088 remain_size(rb_io_t
*fptr
)
3091 rb_off_t siz
= READ_DATA_PENDING_COUNT(fptr
);
3094 if (fstat(fptr
->fd
, &st
) == 0 && S_ISREG(st
.st_mode
)
3095 #if defined(__HAIKU__)
3100 if (io_fflush(fptr
) < 0)
3101 rb_sys_fail_on_write(fptr
);
3102 pos
= lseek(fptr
->fd
, 0, SEEK_CUR
);
3103 if (st
.st_size
>= pos
&& pos
>= 0) {
3104 siz
+= st
.st_size
- pos
;
3105 if (siz
> LONG_MAX
) {
3106 rb_raise(rb_eIOError
, "file too big for single read");
3117 io_enc_str(VALUE str
, rb_io_t
*fptr
)
3119 rb_enc_associate(str
, io_read_encoding(fptr
));
3123 static rb_encoding
*io_read_encoding(rb_io_t
*fptr
);
3126 make_readconv(rb_io_t
*fptr
, int size
)
3128 if (!fptr
->readconv
) {
3131 const char *sname
, *dname
;
3132 ecflags
= fptr
->encs
.ecflags
& ~ECONV_NEWLINE_DECORATOR_WRITE_MASK
;
3133 ecopts
= fptr
->encs
.ecopts
;
3134 if (fptr
->encs
.enc2
) {
3135 sname
= rb_enc_name(fptr
->encs
.enc2
);
3136 dname
= rb_enc_name(io_read_encoding(fptr
));
3141 fptr
->readconv
= rb_econv_open_opts(sname
, dname
, ecflags
, ecopts
);
3142 if (!fptr
->readconv
)
3143 rb_exc_raise(rb_econv_open_exc(sname
, dname
, ecflags
));
3146 if (size
< IO_CBUF_CAPA_MIN
) size
= IO_CBUF_CAPA_MIN
;
3147 fptr
->cbuf
.capa
= size
;
3148 fptr
->cbuf
.ptr
= ALLOC_N(char, fptr
->cbuf
.capa
);
3152 #define MORE_CHAR_SUSPENDED Qtrue
3153 #define MORE_CHAR_FINISHED Qnil
3155 fill_cbuf(rb_io_t
*fptr
, int ec_flags
)
3157 const unsigned char *ss
, *sp
, *se
;
3158 unsigned char *ds
, *dp
, *de
;
3159 rb_econv_result_t res
;
3164 ec_flags
|= ECONV_PARTIAL_INPUT
;
3166 if (fptr
->cbuf
.len
== fptr
->cbuf
.capa
)
3167 return MORE_CHAR_SUSPENDED
; /* cbuf full */
3168 if (fptr
->cbuf
.len
== 0)
3170 else if (fptr
->cbuf
.off
+ fptr
->cbuf
.len
== fptr
->cbuf
.capa
) {
3171 memmove(fptr
->cbuf
.ptr
, fptr
->cbuf
.ptr
+fptr
->cbuf
.off
, fptr
->cbuf
.len
);
3175 cbuf_len0
= fptr
->cbuf
.len
;
3178 ss
= sp
= (const unsigned char *)fptr
->rbuf
.ptr
+ fptr
->rbuf
.off
;
3179 se
= sp
+ fptr
->rbuf
.len
;
3180 ds
= dp
= (unsigned char *)fptr
->cbuf
.ptr
+ fptr
->cbuf
.off
+ fptr
->cbuf
.len
;
3181 de
= (unsigned char *)fptr
->cbuf
.ptr
+ fptr
->cbuf
.capa
;
3182 res
= rb_econv_convert(fptr
->readconv
, &sp
, se
, &dp
, de
, ec_flags
);
3183 fptr
->rbuf
.off
+= (int)(sp
- ss
);
3184 fptr
->rbuf
.len
-= (int)(sp
- ss
);
3185 fptr
->cbuf
.len
+= (int)(dp
- ds
);
3187 putbackable
= rb_econv_putbackable(fptr
->readconv
);
3189 rb_econv_putback(fptr
->readconv
, (unsigned char *)fptr
->rbuf
.ptr
+ fptr
->rbuf
.off
- putbackable
, putbackable
);
3190 fptr
->rbuf
.off
-= putbackable
;
3191 fptr
->rbuf
.len
+= putbackable
;
3194 exc
= rb_econv_make_exception(fptr
->readconv
);
3198 if (cbuf_len0
!= fptr
->cbuf
.len
)
3199 return MORE_CHAR_SUSPENDED
;
3201 if (res
== econv_finished
) {
3202 return MORE_CHAR_FINISHED
;
3205 if (res
== econv_source_buffer_empty
) {
3206 if (fptr
->rbuf
.len
== 0) {
3208 if (io_fillbuf(fptr
) < 0) {
3209 if (!fptr
->readconv
) {
3210 return MORE_CHAR_FINISHED
;
3212 ds
= dp
= (unsigned char *)fptr
->cbuf
.ptr
+ fptr
->cbuf
.off
+ fptr
->cbuf
.len
;
3213 de
= (unsigned char *)fptr
->cbuf
.ptr
+ fptr
->cbuf
.capa
;
3214 res
= rb_econv_convert(fptr
->readconv
, NULL
, NULL
, &dp
, de
, 0);
3215 fptr
->cbuf
.len
+= (int)(dp
- ds
);
3216 rb_econv_check_error(fptr
->readconv
);
3222 if (cbuf_len0
!= fptr
->cbuf
.len
)
3223 return MORE_CHAR_SUSPENDED
;
3225 return MORE_CHAR_FINISHED
;
3229 more_char(rb_io_t
*fptr
)
3232 v
= fill_cbuf(fptr
, ECONV_AFTER_OUTPUT
);
3233 if (v
!= MORE_CHAR_SUSPENDED
&& v
!= MORE_CHAR_FINISHED
)
3239 io_shift_cbuf(rb_io_t
*fptr
, int len
, VALUE
*strp
)
3245 *strp
= str
= rb_str_new(fptr
->cbuf
.ptr
+fptr
->cbuf
.off
, len
);
3248 rb_str_cat(str
, fptr
->cbuf
.ptr
+fptr
->cbuf
.off
, len
);
3250 rb_enc_associate(str
, fptr
->encs
.enc
);
3252 fptr
->cbuf
.off
+= len
;
3253 fptr
->cbuf
.len
-= len
;
3254 /* xxx: set coderange */
3255 if (fptr
->cbuf
.len
== 0)
3257 else if (fptr
->cbuf
.capa
/2 < fptr
->cbuf
.off
) {
3258 memmove(fptr
->cbuf
.ptr
, fptr
->cbuf
.ptr
+fptr
->cbuf
.off
, fptr
->cbuf
.len
);
3265 io_setstrbuf(VALUE
*str
, long len
)
3269 len
= (len
+ 1) & ~1L; /* round up for wide char */
3272 *str
= rb_str_new(0, len
);
3276 VALUE s
= StringValue(*str
);
3279 long clen
= RSTRING_LEN(s
);
3285 if ((rb_str_capacity(*str
) - (size_t)RSTRING_LEN(*str
)) < (size_t)len
) {
3286 rb_str_modify_expand(*str
, len
);
3291 #define MAX_REALLOC_GAP 4096
3293 io_shrink_read_string(VALUE str
, long n
)
3295 if (rb_str_capacity(str
) - n
> MAX_REALLOC_GAP
) {
3296 rb_str_resize(str
, n
);
3301 io_set_read_length(VALUE str
, long n
, int shrinkable
)
3303 if (RSTRING_LEN(str
) != n
) {
3305 rb_str_set_len(str
, n
);
3306 if (shrinkable
) io_shrink_read_string(str
, n
);
3311 read_all(rb_io_t
*fptr
, long siz
, VALUE str
)
3320 if (NEED_READCONV(fptr
)) {
3321 int first
= !NIL_P(str
);
3322 SET_BINARY_MODE(fptr
);
3323 shrinkable
= io_setstrbuf(&str
,0);
3324 make_readconv(fptr
, 0);
3327 if (fptr
->cbuf
.len
) {
3328 if (first
) rb_str_set_len(str
, first
= 0);
3329 io_shift_cbuf(fptr
, fptr
->cbuf
.len
, &str
);
3331 v
= fill_cbuf(fptr
, 0);
3332 if (v
!= MORE_CHAR_SUSPENDED
&& v
!= MORE_CHAR_FINISHED
) {
3333 if (fptr
->cbuf
.len
) {
3334 if (first
) rb_str_set_len(str
, first
= 0);
3335 io_shift_cbuf(fptr
, fptr
->cbuf
.len
, &str
);
3339 if (v
== MORE_CHAR_FINISHED
) {
3340 clear_readconv(fptr
);
3341 if (first
) rb_str_set_len(str
, first
= 0);
3342 if (shrinkable
) io_shrink_read_string(str
, RSTRING_LEN(str
));
3343 return io_enc_str(str
, fptr
);
3348 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr
);
3352 enc
= io_read_encoding(fptr
);
3355 if (siz
== 0) siz
= BUFSIZ
;
3356 shrinkable
= io_setstrbuf(&str
, siz
);
3359 n
= io_fread(str
, bytes
, siz
- bytes
, fptr
);
3360 if (n
== 0 && bytes
== 0) {
3361 rb_str_set_len(str
, 0);
3365 rb_str_set_len(str
, bytes
);
3366 if (cr
!= ENC_CODERANGE_BROKEN
)
3367 pos
+= rb_str_coderange_scan_restartable(RSTRING_PTR(str
) + pos
, RSTRING_PTR(str
) + bytes
, enc
, &cr
);
3368 if (bytes
< siz
) break;
3371 size_t capa
= rb_str_capacity(str
);
3372 if (capa
< (size_t)RSTRING_LEN(str
) + BUFSIZ
) {
3373 if (capa
< BUFSIZ
) {
3376 else if (capa
> IO_MAX_BUFFER_GROWTH
) {
3377 capa
= IO_MAX_BUFFER_GROWTH
;
3379 rb_str_modify_expand(str
, capa
);
3382 if (shrinkable
) io_shrink_read_string(str
, RSTRING_LEN(str
));
3383 str
= io_enc_str(str
, fptr
);
3384 ENC_CODERANGE_SET(str
, cr
);
3389 rb_io_set_nonblock(rb_io_t
*fptr
)
3391 if (rb_fd_set_nonblock(fptr
->fd
) != 0) {
3392 rb_sys_fail_path(fptr
->pathv
);
3397 io_read_memory_call(VALUE arg
)
3399 struct io_internal_read_struct
*iis
= (struct io_internal_read_struct
*)arg
;
3401 VALUE scheduler
= rb_fiber_scheduler_current();
3402 if (scheduler
!= Qnil
) {
3403 VALUE result
= rb_fiber_scheduler_io_read_memory(scheduler
, iis
->fptr
->self
, iis
->buf
, iis
->capa
, 0);
3405 if (!UNDEF_P(result
)) {
3406 // This is actually returned as a pseudo-VALUE and later cast to a long:
3407 return (VALUE
)rb_fiber_scheduler_io_result_apply(result
);
3411 if (iis
->nonblock
) {
3412 return rb_thread_io_blocking_call(internal_read_func
, iis
, iis
->fptr
->fd
, 0);
3415 return rb_thread_io_blocking_call(internal_read_func
, iis
, iis
->fptr
->fd
, RB_WAITFD_IN
);
3420 io_read_memory_locktmp(VALUE str
, struct io_internal_read_struct
*iis
)
3422 return (long)rb_str_locktmp_ensure(str
, io_read_memory_call
, (VALUE
)iis
);
3425 #define no_exception_p(opts) !rb_opts_exception_p((opts), TRUE)
3428 io_getpartial(int argc
, VALUE
*argv
, VALUE io
, int no_exception
, int nonblock
)
3433 struct io_internal_read_struct iis
;
3436 rb_scan_args(argc
, argv
, "11", &length
, &str
);
3438 if ((len
= NUM2LONG(length
)) < 0) {
3439 rb_raise(rb_eArgError
, "negative length %ld given", len
);
3442 shrinkable
= io_setstrbuf(&str
, len
);
3444 GetOpenFile(io
, fptr
);
3445 rb_io_check_byte_readable(fptr
);
3448 io_set_read_length(str
, 0, shrinkable
);
3454 n
= read_buffered_data(RSTRING_PTR(str
), len
, fptr
);
3458 rb_io_set_nonblock(fptr
);
3460 io_setstrbuf(&str
, len
);
3461 iis
.th
= rb_thread_current();
3463 iis
.nonblock
= nonblock
;
3465 iis
.buf
= RSTRING_PTR(str
);
3468 n
= io_read_memory_locktmp(str
, &iis
);
3471 if (!nonblock
&& fptr_wait_readable(fptr
))
3473 if (nonblock
&& (io_again_p(e
))) {
3475 return sym_wait_readable
;
3477 rb_readwrite_syserr_fail(RB_IO_WAIT_READABLE
,
3478 e
, "read would block");
3480 rb_syserr_fail_path(e
, fptr
->pathv
);
3483 io_set_read_length(str
, n
, shrinkable
);
3493 * readpartial(maxlen) -> string
3494 * readpartial(maxlen, out_string) -> out_string
3496 * Reads up to +maxlen+ bytes from the stream;
3497 * returns a string (either a new string or the given +out_string+).
3500 * - The unchanged encoding of +out_string+, if +out_string+ is given.
3501 * - ASCII-8BIT, otherwise.
3503 * - Contains +maxlen+ bytes from the stream, if available.
3504 * - Otherwise contains all available bytes, if any available.
3505 * - Otherwise is an empty string.
3507 * With the single non-negative integer argument +maxlen+ given,
3508 * returns a new string:
3510 * f = File.new('t.txt')
3511 * f.readpartial(20) # => "First line\nSecond l"
3512 * f.readpartial(20) # => "ine\n\nFourth line\n"
3513 * f.readpartial(20) # => "Fifth line\n"
3514 * f.readpartial(20) # Raises EOFError.
3517 * With both argument +maxlen+ and string argument +out_string+ given,
3518 * returns modified +out_string+:
3520 * f = File.new('t.txt')
3522 * f.readpartial(20, s) # => "First line\nSecond l"
3524 * f.readpartial(0, s) # => ""
3527 * This method is useful for a stream such as a pipe, a socket, or a tty.
3528 * It blocks only when no data is immediately available.
3529 * This means that it blocks only when _all_ of the following are true:
3531 * - The byte buffer in the stream is empty.
3532 * - The content of the stream is empty.
3533 * - The stream is not at EOF.
3535 * When blocked, the method waits for either more data or EOF on the stream:
3537 * - If more data is read, the method returns the data.
3538 * - If EOF is reached, the method raises EOFError.
3540 * When not blocked, the method responds immediately:
3542 * - Returns data from the buffer if there is any.
3543 * - Otherwise returns data from the stream if there is any.
3544 * - Otherwise raises EOFError if the stream has reached EOF.
3546 * Note that this method is similar to sysread. The differences are:
3548 * - If the byte buffer is not empty, read from the byte buffer
3549 * instead of "sysread for buffered IO (IOError)".
3550 * - It doesn't cause Errno::EWOULDBLOCK and Errno::EINTR. When
3551 * readpartial meets EWOULDBLOCK and EINTR by read system call,
3552 * readpartial retries the system call.
3554 * The latter means that readpartial is non-blocking-flag insensitive.
3555 * It blocks on the situation IO#sysread causes Errno::EWOULDBLOCK as
3556 * if the fd is blocking mode.
3560 * # # Returned Buffer Content Pipe Content
3562 * w << 'abc' # "" "abc".
3563 * r.readpartial(4096) # => "abc" "" ""
3564 * r.readpartial(4096) # (Blocks because buffer and pipe are empty.)
3566 * # # Returned Buffer Content Pipe Content
3568 * w << 'abc' # "" "abc"
3569 * w.close # "" "abc" EOF
3570 * r.readpartial(4096) # => "abc" "" EOF
3571 * r.readpartial(4096) # raises EOFError
3573 * # # Returned Buffer Content Pipe Content
3575 * w << "abc\ndef\n" # "" "abc\ndef\n"
3576 * r.gets # => "abc\n" "def\n" ""
3577 * w << "ghi\n" # "def\n" "ghi\n"
3578 * r.readpartial(4096) # => "def\n" "" "ghi\n"
3579 * r.readpartial(4096) # => "ghi\n" "" ""
3584 io_readpartial(int argc
, VALUE
*argv
, VALUE io
)
3588 ret
= io_getpartial(argc
, argv
, io
, Qnil
, 0);
3595 io_nonblock_eof(int no_exception
)
3597 if (!no_exception
) {
3605 io_read_nonblock(rb_execution_context_t
*ec
, VALUE io
, VALUE length
, VALUE str
, VALUE ex
)
3609 struct io_internal_read_struct iis
;
3612 if ((len
= NUM2LONG(length
)) < 0) {
3613 rb_raise(rb_eArgError
, "negative length %ld given", len
);
3616 shrinkable
= io_setstrbuf(&str
, len
);
3617 rb_bool_expected(ex
, "exception", TRUE
);
3619 GetOpenFile(io
, fptr
);
3620 rb_io_check_byte_readable(fptr
);
3623 io_set_read_length(str
, 0, shrinkable
);
3627 n
= read_buffered_data(RSTRING_PTR(str
), len
, fptr
);
3629 rb_fd_set_nonblock(fptr
->fd
);
3630 shrinkable
|= io_setstrbuf(&str
, len
);
3634 iis
.buf
= RSTRING_PTR(str
);
3637 n
= io_read_memory_locktmp(str
, &iis
);
3640 if (io_again_p(e
)) {
3641 if (!ex
) return sym_wait_readable
;
3642 rb_readwrite_syserr_fail(RB_IO_WAIT_READABLE
,
3643 e
, "read would block");
3645 rb_syserr_fail_path(e
, fptr
->pathv
);
3648 io_set_read_length(str
, n
, shrinkable
);
3651 if (!ex
) return Qnil
;
3660 io_write_nonblock(rb_execution_context_t
*ec
, VALUE io
, VALUE str
, VALUE ex
)
3665 if (!RB_TYPE_P(str
, T_STRING
))
3666 str
= rb_obj_as_string(str
);
3667 rb_bool_expected(ex
, "exception", TRUE
);
3669 io
= GetWriteIO(io
);
3670 GetOpenFile(io
, fptr
);
3671 rb_io_check_writable(fptr
);
3673 if (io_fflush(fptr
) < 0)
3674 rb_sys_fail_on_write(fptr
);
3676 rb_fd_set_nonblock(fptr
->fd
);
3677 n
= write(fptr
->fd
, RSTRING_PTR(str
), RSTRING_LEN(str
));
3682 if (io_again_p(e
)) {
3684 return sym_wait_writable
;
3687 rb_readwrite_syserr_fail(RB_IO_WAIT_WRITABLE
, e
, "write would block");
3690 rb_syserr_fail_path(e
, fptr
->pathv
);
3698 * read(maxlen = nil, out_string = nil) -> new_string, out_string, or nil
3700 * Reads bytes from the stream; the stream must be opened for reading
3701 * (see {Access Modes}[rdoc-ref:File@Access+Modes]):
3703 * - If +maxlen+ is +nil+, reads all bytes using the stream's data mode.
3704 * - Otherwise reads up to +maxlen+ bytes in binary mode.
3706 * Returns a string (either a new string or the given +out_string+)
3707 * containing the bytes read.
3708 * The encoding of the string depends on both +maxLen+ and +out_string+:
3710 * - +maxlen+ is +nil+: uses internal encoding of +self+
3711 * (regardless of whether +out_string+ was given).
3712 * - +maxlen+ not +nil+:
3714 * - +out_string+ given: encoding of +out_string+ not modified.
3715 * - +out_string+ not given: ASCII-8BIT is used.
3717 * <b>Without Argument +out_string+</b>
3719 * When argument +out_string+ is omitted,
3720 * the returned value is a new string:
3722 * f = File.new('t.txt')
3724 * # => "First line\nSecond line\n\nFourth line\nFifth line\n"
3726 * f.read(30) # => "First line\r\nSecond line\r\n\r\nFou"
3727 * f.read(30) # => "rth line\r\nFifth line\r\n"
3728 * f.read(30) # => nil
3731 * If +maxlen+ is zero, returns an empty string.
3733 * <b> With Argument +out_string+</b>
3735 * When argument +out_string+ is given,
3736 * the returned value is +out_string+, whose content is replaced:
3738 * f = File.new('t.txt')
3739 * s = 'foo' # => "foo"
3740 * f.read(nil, s) # => "First line\nSecond line\n\nFourth line\nFifth line\n"
3741 * s # => "First line\nSecond line\n\nFourth line\nFifth line\n"
3744 * f.read(30, s) # => "First line\r\nSecond line\r\n\r\nFou"
3745 * s # => "First line\r\nSecond line\r\n\r\nFou"
3747 * f.read(30, s) # => "rth line\r\nFifth line\r\n"
3748 * s # => "rth line\r\nFifth line\r\n"
3750 * f.read(30, s) # => nil
3754 * Note that this method behaves like the fread() function in C.
3755 * This means it retries to invoke read(2) system calls to read data
3756 * with the specified maxlen (or until EOF).
3758 * This behavior is preserved even if the stream is in non-blocking mode.
3759 * (This method is non-blocking-flag insensitive as other methods.)
3761 * If you need the behavior like a single read(2) system call,
3762 * consider #readpartial, #read_nonblock, and #sysread.
3764 * Related: IO#write.
3768 io_read(int argc
, VALUE
*argv
, VALUE io
)
3774 #if RUBY_CRLF_ENVIRONMENT
3778 rb_scan_args(argc
, argv
, "02", &length
, &str
);
3780 if (NIL_P(length
)) {
3781 GetOpenFile(io
, fptr
);
3782 rb_io_check_char_readable(fptr
);
3783 return read_all(fptr
, remain_size(fptr
), str
);
3785 len
= NUM2LONG(length
);
3787 rb_raise(rb_eArgError
, "negative length %ld given", len
);
3790 shrinkable
= io_setstrbuf(&str
,len
);
3792 GetOpenFile(io
, fptr
);
3793 rb_io_check_byte_readable(fptr
);
3795 io_set_read_length(str
, 0, shrinkable
);
3800 #if RUBY_CRLF_ENVIRONMENT
3801 previous_mode
= set_binary_mode_with_seek_cur(fptr
);
3803 n
= io_fread(str
, 0, len
, fptr
);
3804 io_set_read_length(str
, n
, shrinkable
);
3805 #if RUBY_CRLF_ENVIRONMENT
3806 if (previous_mode
== O_TEXT
) {
3807 setmode(fptr
->fd
, O_TEXT
);
3810 if (n
== 0) return Qnil
;
3816 rscheck(const char *rsptr
, long rslen
, VALUE rs
)
3819 if (RSTRING_PTR(rs
) != rsptr
&& RSTRING_LEN(rs
) != rslen
)
3820 rb_raise(rb_eRuntimeError
, "rs modified");
3824 appendline(rb_io_t
*fptr
, int delim
, VALUE
*strp
, long *lp
)
3829 if (NEED_READCONV(fptr
)) {
3830 SET_BINARY_MODE(fptr
);
3831 make_readconv(fptr
, 0);
3834 int searchlen
= READ_CHAR_PENDING_COUNT(fptr
);
3836 p
= READ_CHAR_PENDING_PTR(fptr
);
3837 if (0 < limit
&& limit
< searchlen
)
3838 searchlen
= (int)limit
;
3839 e
= memchr(p
, delim
, searchlen
);
3841 int len
= (int)(e
-p
+1);
3843 *strp
= str
= rb_str_new(p
, len
);
3845 rb_str_buf_cat(str
, p
, len
);
3846 fptr
->cbuf
.off
+= len
;
3847 fptr
->cbuf
.len
-= len
;
3854 *strp
= str
= rb_str_new(p
, searchlen
);
3856 rb_str_buf_cat(str
, p
, searchlen
);
3857 fptr
->cbuf
.off
+= searchlen
;
3858 fptr
->cbuf
.len
-= searchlen
;
3863 return (unsigned char)RSTRING_PTR(str
)[RSTRING_LEN(str
)-1];
3866 } while (more_char(fptr
) != MORE_CHAR_FINISHED
);
3867 clear_readconv(fptr
);
3872 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr
);
3874 long pending
= READ_DATA_PENDING_COUNT(fptr
);
3876 const char *p
= READ_DATA_PENDING_PTR(fptr
);
3880 if (limit
> 0 && pending
> limit
) pending
= limit
;
3881 e
= memchr(p
, delim
, pending
);
3882 if (e
) pending
= e
- p
+ 1;
3884 last
= RSTRING_LEN(str
);
3885 rb_str_resize(str
, last
+ pending
);
3889 *strp
= str
= rb_str_buf_new(pending
);
3890 rb_str_set_len(str
, pending
);
3892 read_buffered_data(RSTRING_PTR(str
) + last
, pending
, fptr
); /* must not fail */
3895 if (e
) return delim
;
3897 return (unsigned char)RSTRING_PTR(str
)[RSTRING_LEN(str
)-1];
3900 } while (io_fillbuf(fptr
) >= 0);
3906 swallow(rb_io_t
*fptr
, int term
)
3908 if (NEED_READCONV(fptr
)) {
3909 rb_encoding
*enc
= io_read_encoding(fptr
);
3910 int needconv
= rb_enc_mbminlen(enc
) != 1;
3911 SET_BINARY_MODE(fptr
);
3912 make_readconv(fptr
, 0);
3915 while ((cnt
= READ_CHAR_PENDING_COUNT(fptr
)) > 0) {
3916 const char *p
= READ_CHAR_PENDING_PTR(fptr
);
3919 if (*p
!= term
) return TRUE
;
3921 while (--i
&& *++p
== term
);
3924 const char *e
= p
+ cnt
;
3925 if (rb_enc_ascget(p
, e
, &i
, enc
) != term
) return TRUE
;
3926 while ((p
+= i
) < e
&& rb_enc_ascget(p
, e
, &i
, enc
) == term
);
3929 io_shift_cbuf(fptr
, (int)cnt
- i
, NULL
);
3931 } while (more_char(fptr
) != MORE_CHAR_FINISHED
);
3935 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr
);
3938 while ((cnt
= READ_DATA_PENDING_COUNT(fptr
)) > 0) {
3940 const char *p
= READ_DATA_PENDING_PTR(fptr
);
3942 if (cnt
> sizeof buf
) cnt
= sizeof buf
;
3943 if (*p
!= term
) return TRUE
;
3945 while (--i
&& *++p
== term
);
3946 if (!read_buffered_data(buf
, cnt
- i
, fptr
)) /* must not fail */
3947 rb_sys_fail_path(fptr
->pathv
);
3950 } while (io_fillbuf(fptr
) == 0);
3955 rb_io_getline_fast(rb_io_t
*fptr
, rb_encoding
*enc
, int chomp
)
3963 int pending
= READ_DATA_PENDING_COUNT(fptr
);
3966 const char *p
= READ_DATA_PENDING_PTR(fptr
);
3970 e
= memchr(p
, '\n', pending
);
3972 pending
= (int)(e
- p
+ 1);
3974 chomplen
= (pending
> 1 && *(e
-1) == '\r') + 1;
3978 str
= rb_str_new(p
, pending
- chomplen
);
3979 fptr
->rbuf
.off
+= pending
;
3980 fptr
->rbuf
.len
-= pending
;
3983 rb_str_resize(str
, len
+ pending
- chomplen
);
3984 read_buffered_data(RSTRING_PTR(str
)+len
, pending
- chomplen
, fptr
);
3985 fptr
->rbuf
.off
+= chomplen
;
3986 fptr
->rbuf
.len
-= chomplen
;
3987 if (pending
== 1 && chomplen
== 1 && len
> 0) {
3988 if (RSTRING_PTR(str
)[len
-1] == '\r') {
3989 rb_str_resize(str
, --len
);
3994 len
+= pending
- chomplen
;
3995 if (cr
!= ENC_CODERANGE_BROKEN
)
3996 pos
+= rb_str_coderange_scan_restartable(RSTRING_PTR(str
) + pos
, RSTRING_PTR(str
) + len
, enc
, &cr
);
4000 } while (io_fillbuf(fptr
) >= 0);
4001 if (NIL_P(str
)) return Qnil
;
4003 str
= io_enc_str(str
, fptr
);
4004 ENC_CODERANGE_SET(str
, cr
);
4010 struct getline_arg
{
4014 unsigned int chomp
: 1;
4018 extract_getline_opts(VALUE opts
, struct getline_arg
*args
)
4025 kwds
[0] = rb_intern_const("chomp");
4027 rb_get_kwargs(opts
, kwds
, 0, -2, &vchomp
);
4028 chomp
= (!UNDEF_P(vchomp
)) && RTEST(vchomp
);
4030 args
->chomp
= chomp
;
4034 extract_getline_args(int argc
, VALUE
*argv
, struct getline_arg
*args
)
4036 VALUE rs
= rb_rs
, lim
= Qnil
;
4041 if (NIL_P(argv
[0]) || !NIL_P(tmp
= rb_check_string_type(argv
[0]))) {
4048 else if (2 <= argc
) {
4049 rs
= argv
[0], lim
= argv
[1];
4054 args
->limit
= NIL_P(lim
) ? -1L : NUM2LONG(lim
);
4058 check_getline_args(VALUE
*rsp
, long *limit
, VALUE io
)
4064 rb_encoding
*enc_rs
, *enc_io
;
4066 GetOpenFile(io
, fptr
);
4067 enc_rs
= rb_enc_get(rs
);
4068 enc_io
= io_read_encoding(fptr
);
4069 if (enc_io
!= enc_rs
&&
4070 (!is_ascii_string(rs
) ||
4071 (RSTRING_LEN(rs
) > 0 && !rb_enc_asciicompat(enc_io
)))) {
4072 if (rs
== rb_default_rs
) {
4073 rs
= rb_enc_str_new(0, 0, enc_io
);
4074 rb_str_buf_cat_ascii(rs
, "\n");
4078 rb_raise(rb_eArgError
, "encoding mismatch: %s IO with %s RS",
4079 rb_enc_name(enc_io
),
4080 rb_enc_name(enc_rs
));
4087 prepare_getline_args(int argc
, VALUE
*argv
, struct getline_arg
*args
, VALUE io
)
4090 argc
= rb_scan_args(argc
, argv
, "02:", NULL
, NULL
, &opts
);
4091 extract_getline_args(argc
, argv
, args
);
4092 extract_getline_opts(opts
, args
);
4093 check_getline_args(&args
->rs
, &args
->limit
, io
);
4097 rb_io_getline_0(VALUE rs
, long limit
, int chomp
, rb_io_t
*fptr
)
4103 rb_io_check_char_readable(fptr
);
4104 if (NIL_P(rs
) && limit
< 0) {
4105 str
= read_all(fptr
, 0, Qnil
);
4106 if (RSTRING_LEN(str
) == 0) return Qnil
;
4108 else if (limit
== 0) {
4109 return rb_enc_str_new(0, 0, io_read_encoding(fptr
));
4111 else if (rs
== rb_default_rs
&& limit
< 0 && !NEED_READCONV(fptr
) &&
4112 rb_enc_asciicompat(enc
= io_read_encoding(fptr
))) {
4113 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr
);
4114 return rb_io_getline_fast(fptr
, enc
, chomp
);
4117 int c
, newline
= -1;
4118 const char *rsptr
= 0;
4121 int extra_limit
= 16;
4122 int chomp_cr
= chomp
;
4124 SET_BINARY_MODE(fptr
);
4125 enc
= io_read_encoding(fptr
);
4128 rslen
= RSTRING_LEN(rs
);
4133 swallow(fptr
, '\n');
4135 if (!rb_enc_asciicompat(enc
)) {
4136 rs
= rb_usascii_str_new(rsptr
, rslen
);
4137 rs
= rb_str_encode(rs
, rb_enc_from_encoding(enc
), 0, Qnil
);
4139 rsptr
= RSTRING_PTR(rs
);
4140 rslen
= RSTRING_LEN(rs
);
4144 rsptr
= RSTRING_PTR(rs
);
4146 newline
= (unsigned char)rsptr
[rslen
- 1];
4147 chomp_cr
= chomp
&& rslen
== 1 && newline
== '\n';
4150 /* MS - Optimization */
4151 while ((c
= appendline(fptr
, newline
, &str
, &limit
)) != EOF
) {
4152 const char *s
, *p
, *pp
, *e
;
4155 if (RSTRING_LEN(str
) < rslen
) continue;
4156 s
= RSTRING_PTR(str
);
4157 e
= RSTRING_END(str
);
4159 if (!at_char_boundary(s
, p
, e
, enc
)) continue;
4160 if (!rspara
) rscheck(rsptr
, rslen
, rs
);
4161 if (memcmp(p
, rsptr
, rslen
) == 0) {
4163 if (chomp_cr
&& p
> s
&& *(p
-1) == '\r') --p
;
4164 rb_str_set_len(str
, p
- s
);
4170 s
= RSTRING_PTR(str
);
4171 p
= RSTRING_END(str
);
4172 pp
= rb_enc_left_char_head(s
, p
-1, p
, enc
);
4174 MBCLEN_NEEDMORE_P(rb_enc_precise_mbclen(pp
, p
, enc
))) {
4175 /* relax the limit while incomplete character.
4176 * extra_limit limits the relax length */
4187 if (rspara
&& c
!= EOF
)
4188 swallow(fptr
, '\n');
4190 str
= io_enc_str(str
, fptr
);
4193 if (!NIL_P(str
) && !nolimit
) {
4201 rb_io_getline_1(VALUE rs
, long limit
, int chomp
, VALUE io
)
4204 int old_lineno
, new_lineno
;
4207 GetOpenFile(io
, fptr
);
4208 old_lineno
= fptr
->lineno
;
4209 str
= rb_io_getline_0(rs
, limit
, chomp
, fptr
);
4210 if (!NIL_P(str
) && (new_lineno
= fptr
->lineno
) != old_lineno
) {
4211 if (io
== ARGF
.current_file
) {
4212 ARGF
.lineno
+= new_lineno
- old_lineno
;
4213 ARGF
.last_lineno
= ARGF
.lineno
;
4216 ARGF
.last_lineno
= new_lineno
;
4224 rb_io_getline(int argc
, VALUE
*argv
, VALUE io
)
4226 struct getline_arg args
;
4228 prepare_getline_args(argc
, argv
, &args
, io
);
4229 return rb_io_getline_1(args
.rs
, args
.limit
, args
.chomp
, io
);
4233 rb_io_gets(VALUE io
)
4235 return rb_io_getline_1(rb_default_rs
, -1, FALSE
, io
);
4239 rb_io_gets_internal(VALUE io
)
4242 GetOpenFile(io
, fptr
);
4243 return rb_io_getline_0(rb_default_rs
, -1, FALSE
, fptr
);
4248 * gets(sep = $/, chomp: false) -> string or nil
4249 * gets(limit, chomp: false) -> string or nil
4250 * gets(sep, limit, chomp: false) -> string or nil
4252 * Reads and returns a line from the stream;
4253 * assigns the return value to <tt>$_</tt>.
4254 * See {Line IO}[rdoc-ref:IO@Line+IO].
4256 * With no arguments given, returns the next line
4257 * as determined by line separator <tt>$/</tt>, or +nil+ if none:
4259 * f = File.open('t.txt')
4260 * f.gets # => "First line\n"
4261 * $_ # => "First line\n"
4263 * f.gets # => "Fourth line\n"
4264 * f.gets # => "Fifth line\n"
4268 * With only string argument +sep+ given,
4269 * returns the next line as determined by line separator +sep+,
4271 * see {Line Separator}[rdoc-ref:IO@Line+Separator]:
4273 * f = File.new('t.txt')
4274 * f.gets('l') # => "First l"
4275 * f.gets('li') # => "ine\nSecond li"
4276 * f.gets('lin') # => "ne\n\nFourth lin"
4280 * The two special values for +sep+ are honored:
4282 * f = File.new('t.txt')
4284 * f.gets(nil) # => "First line\nSecond line\n\nFourth line\nFifth line\n"
4286 * # Get paragraph (up to two line separators).
4287 * f.gets('') # => "First line\nSecond line\n\n"
4290 * With only integer argument +limit+ given,
4291 * limits the number of bytes in the line;
4292 * see {Line Limit}[rdoc-ref:IO@Line+Limit]:
4294 * # No more than one line.
4295 * File.open('t.txt') {|f| f.gets(10) } # => "First line"
4296 * File.open('t.txt') {|f| f.gets(11) } # => "First line\n"
4297 * File.open('t.txt') {|f| f.gets(12) } # => "First line\n"
4299 * With arguments +sep+ and +limit+ given,
4300 * combines the two behaviors
4301 * (see {Line Separator and Line Limit}[rdoc-ref:IO@Line+Separator+and+Line+Limit]).
4303 * Optional keyword argument +chomp+ specifies whether line separators
4304 * are to be omitted:
4306 * f = File.open('t.txt')
4307 * # Chomp the lines.
4308 * f.gets(chomp: true) # => "First line"
4309 * f.gets(chomp: true) # => "Second line"
4310 * f.gets(chomp: true) # => ""
4311 * f.gets(chomp: true) # => "Fourth line"
4312 * f.gets(chomp: true) # => "Fifth line"
4313 * f.gets(chomp: true) # => nil
4319 rb_io_gets_m(int argc
, VALUE
*argv
, VALUE io
)
4323 str
= rb_io_getline(argc
, argv
, io
);
4324 rb_lastline_set(str
);
4333 * Returns the current line number for the stream;
4334 * see {Line Number}[rdoc-ref:IO@Line+Number].
4339 rb_io_lineno(VALUE io
)
4343 GetOpenFile(io
, fptr
);
4344 rb_io_check_char_readable(fptr
);
4345 return INT2NUM(fptr
->lineno
);
4350 * lineno = integer -> integer
4352 * Sets and returns the line number for the stream;
4353 * see {Line Number}[rdoc-ref:IO@Line+Number].
4358 rb_io_set_lineno(VALUE io
, VALUE lineno
)
4362 GetOpenFile(io
, fptr
);
4363 rb_io_check_char_readable(fptr
);
4364 fptr
->lineno
= NUM2INT(lineno
);
4370 io_readline(rb_execution_context_t
*ec
, VALUE io
, VALUE sep
, VALUE lim
, VALUE chomp
)
4373 // If sep is specified, but it's not a string and not nil, then assume
4374 // it's the limit (it should be an integer)
4375 if (!NIL_P(sep
) && NIL_P(rb_check_string_type(sep
))) {
4376 // If the user has specified a non-nil / non-string value
4377 // for the separator, we assume it's the limit and set the
4378 // separator to default: rb_rs.
4388 VALUE line
= rb_io_getline_1(sep
, NIL_P(lim
) ? -1L : NUM2LONG(lim
), RTEST(chomp
), io
);
4389 rb_lastline_set_up(line
, 1);
4397 static VALUE
io_readlines(const struct getline_arg
*arg
, VALUE io
);
4401 * readlines(sep = $/, chomp: false) -> array
4402 * readlines(limit, chomp: false) -> array
4403 * readlines(sep, limit, chomp: false) -> array
4405 * Reads and returns all remaining line from the stream;
4406 * does not modify <tt>$_</tt>.
4407 * See {Line IO}[rdoc-ref:IO@Line+IO].
4409 * With no arguments given, returns lines
4410 * as determined by line separator <tt>$/</tt>, or +nil+ if none:
4412 * f = File.new('t.txt')
4414 * # => ["First line\n", "Second line\n", "\n", "Fourth line\n", "Fifth line\n"]
4415 * f.readlines # => []
4418 * With only string argument +sep+ given,
4419 * returns lines as determined by line separator +sep+,
4421 * see {Line Separator}[rdoc-ref:IO@Line+Separator]:
4423 * f = File.new('t.txt')
4425 * # => ["First li", "ne\nSecond li", "ne\n\nFourth li", "ne\nFifth li", "ne\n"]
4428 * The two special values for +sep+ are honored:
4430 * f = File.new('t.txt')
4431 * # Get all into one string.
4433 * # => ["First line\nSecond line\n\nFourth line\nFifth line\n"]
4434 * # Get paragraphs (up to two line separators).
4437 * # => ["First line\nSecond line\n\n", "Fourth line\nFifth line\n"]
4440 * With only integer argument +limit+ given,
4441 * limits the number of bytes in each line;
4442 * see {Line Limit}[rdoc-ref:IO@Line+Limit]:
4444 * f = File.new('t.txt')
4446 * # => ["First li", "ne\n", "Second l", "ine\n", "\n", "Fourth l", "ine\n", "Fifth li", "ne\n"]
4449 * With arguments +sep+ and +limit+ given,
4450 * combines the two behaviors
4451 * (see {Line Separator and Line Limit}[rdoc-ref:IO@Line+Separator+and+Line+Limit]).
4453 * Optional keyword argument +chomp+ specifies whether line separators
4454 * are to be omitted:
4456 * f = File.new('t.txt')
4457 * f.readlines(chomp: true)
4458 * # => ["First line", "Second line", "", "Fourth line", "Fifth line"]
4464 rb_io_readlines(int argc
, VALUE
*argv
, VALUE io
)
4466 struct getline_arg args
;
4468 prepare_getline_args(argc
, argv
, &args
, io
);
4469 return io_readlines(&args
, io
);
4473 io_readlines(const struct getline_arg
*arg
, VALUE io
)
4477 if (arg
->limit
== 0)
4478 rb_raise(rb_eArgError
, "invalid limit: 0 for readlines");
4480 while (!NIL_P(line
= rb_io_getline_1(arg
->rs
, arg
->limit
, arg
->chomp
, io
))) {
4481 rb_ary_push(ary
, line
);
4488 * each_line(sep = $/, chomp: false) {|line| ... } -> self
4489 * each_line(limit, chomp: false) {|line| ... } -> self
4490 * each_line(sep, limit, chomp: false) {|line| ... } -> self
4491 * each_line -> enumerator
4493 * Calls the block with each remaining line read from the stream;
4495 * Does nothing if already at end-of-stream;
4496 * See {Line IO}[rdoc-ref:IO@Line+IO].
4498 * With no arguments given, reads lines
4499 * as determined by line separator <tt>$/</tt>:
4501 * f = File.new('t.txt')
4502 * f.each_line {|line| p line }
4503 * f.each_line {|line| fail 'Cannot happen' }
4514 * With only string argument +sep+ given,
4515 * reads lines as determined by line separator +sep+;
4516 * see {Line Separator}[rdoc-ref:IO@Line+Separator]:
4518 * f = File.new('t.txt')
4519 * f.each_line('li') {|line| p line }
4530 * The two special values for +sep+ are honored:
4532 * f = File.new('t.txt')
4533 * # Get all into one string.
4534 * f.each_line(nil) {|line| p line }
4539 * "First line\nSecond line\n\nFourth line\nFifth line\n"
4542 * # Get paragraphs (up to two line separators).
4543 * f.each_line('') {|line| p line }
4547 * "First line\nSecond line\n\n"
4548 * "Fourth line\nFifth line\n"
4550 * With only integer argument +limit+ given,
4551 * limits the number of bytes in each line;
4552 * see {Line Limit}[rdoc-ref:IO@Line+Limit]:
4554 * f = File.new('t.txt')
4555 * f.each_line(8) {|line| p line }
4570 * With arguments +sep+ and +limit+ given,
4571 * combines the two behaviors
4572 * (see {Line Separator and Line Limit}[rdoc-ref:IO@Line+Separator+and+Line+Limit]).
4574 * Optional keyword argument +chomp+ specifies whether line separators
4575 * are to be omitted:
4577 * f = File.new('t.txt')
4578 * f.each_line(chomp: true) {|line| p line }
4589 * Returns an Enumerator if no block is given.
4593 rb_io_each_line(int argc
, VALUE
*argv
, VALUE io
)
4596 struct getline_arg args
;
4598 RETURN_ENUMERATOR(io
, argc
, argv
);
4599 prepare_getline_args(argc
, argv
, &args
, io
);
4600 if (args
.limit
== 0)
4601 rb_raise(rb_eArgError
, "invalid limit: 0 for each_line");
4602 while (!NIL_P(str
= rb_io_getline_1(args
.rs
, args
.limit
, args
.chomp
, io
))) {
4610 * each_byte {|byte| ... } -> self
4611 * each_byte -> enumerator
4613 * Calls the given block with each byte (0..255) in the stream; returns +self+.
4614 * See {Byte IO}[rdoc-ref:IO@Byte+IO].
4616 * f = File.new('t.rus')
4618 * f.each_byte {|b| a << b }
4619 * a # => [209, 130, 208, 181, 209, 129, 209, 130]
4622 * Returns an Enumerator if no block is given.
4624 * Related: IO#each_char, IO#each_codepoint.
4629 rb_io_each_byte(VALUE io
)
4633 RETURN_ENUMERATOR(io
, 0, 0);
4634 GetOpenFile(io
, fptr
);
4637 while (fptr
->rbuf
.len
> 0) {
4638 char *p
= fptr
->rbuf
.ptr
+ fptr
->rbuf
.off
++;
4640 rb_yield(INT2FIX(*p
& 0xff));
4641 rb_io_check_byte_readable(fptr
);
4645 } while (io_fillbuf(fptr
) >= 0);
4650 io_getc(rb_io_t
*fptr
, rb_encoding
*enc
)
4655 if (NEED_READCONV(fptr
)) {
4656 rb_encoding
*read_enc
= io_read_encoding(fptr
);
4659 SET_BINARY_MODE(fptr
);
4660 make_readconv(fptr
, 0);
4663 if (fptr
->cbuf
.len
) {
4664 r
= rb_enc_precise_mbclen(fptr
->cbuf
.ptr
+fptr
->cbuf
.off
,
4665 fptr
->cbuf
.ptr
+fptr
->cbuf
.off
+fptr
->cbuf
.len
,
4667 if (!MBCLEN_NEEDMORE_P(r
))
4669 if (fptr
->cbuf
.len
== fptr
->cbuf
.capa
) {
4670 rb_raise(rb_eIOError
, "too long character");
4674 if (more_char(fptr
) == MORE_CHAR_FINISHED
) {
4675 if (fptr
->cbuf
.len
== 0) {
4676 clear_readconv(fptr
);
4679 /* return an unit of an incomplete character just before EOF */
4680 str
= rb_enc_str_new(fptr
->cbuf
.ptr
+fptr
->cbuf
.off
, 1, read_enc
);
4681 fptr
->cbuf
.off
+= 1;
4682 fptr
->cbuf
.len
-= 1;
4683 if (fptr
->cbuf
.len
== 0) clear_readconv(fptr
);
4684 ENC_CODERANGE_SET(str
, ENC_CODERANGE_BROKEN
);
4688 if (MBCLEN_INVALID_P(r
)) {
4689 r
= rb_enc_mbclen(fptr
->cbuf
.ptr
+fptr
->cbuf
.off
,
4690 fptr
->cbuf
.ptr
+fptr
->cbuf
.off
+fptr
->cbuf
.len
,
4692 io_shift_cbuf(fptr
, r
, &str
);
4693 cr
= ENC_CODERANGE_BROKEN
;
4696 io_shift_cbuf(fptr
, MBCLEN_CHARFOUND_LEN(r
), &str
);
4697 cr
= ENC_CODERANGE_VALID
;
4698 if (MBCLEN_CHARFOUND_LEN(r
) == 1 && rb_enc_asciicompat(read_enc
) &&
4699 ISASCII(RSTRING_PTR(str
)[0])) {
4700 cr
= ENC_CODERANGE_7BIT
;
4703 str
= io_enc_str(str
, fptr
);
4704 ENC_CODERANGE_SET(str
, cr
);
4708 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr
);
4709 if (io_fillbuf(fptr
) < 0) {
4712 if (rb_enc_asciicompat(enc
) && ISASCII(fptr
->rbuf
.ptr
[fptr
->rbuf
.off
])) {
4713 str
= rb_str_new(fptr
->rbuf
.ptr
+fptr
->rbuf
.off
, 1);
4714 fptr
->rbuf
.off
+= 1;
4715 fptr
->rbuf
.len
-= 1;
4716 cr
= ENC_CODERANGE_7BIT
;
4719 r
= rb_enc_precise_mbclen(fptr
->rbuf
.ptr
+fptr
->rbuf
.off
, fptr
->rbuf
.ptr
+fptr
->rbuf
.off
+fptr
->rbuf
.len
, enc
);
4720 if (MBCLEN_CHARFOUND_P(r
) &&
4721 (n
= MBCLEN_CHARFOUND_LEN(r
)) <= fptr
->rbuf
.len
) {
4722 str
= rb_str_new(fptr
->rbuf
.ptr
+fptr
->rbuf
.off
, n
);
4723 fptr
->rbuf
.off
+= n
;
4724 fptr
->rbuf
.len
-= n
;
4725 cr
= ENC_CODERANGE_VALID
;
4727 else if (MBCLEN_NEEDMORE_P(r
)) {
4728 str
= rb_str_new(fptr
->rbuf
.ptr
+fptr
->rbuf
.off
, fptr
->rbuf
.len
);
4731 if (io_fillbuf(fptr
) != -1) {
4732 rb_str_cat(str
, fptr
->rbuf
.ptr
+fptr
->rbuf
.off
, 1);
4735 r
= rb_enc_precise_mbclen(RSTRING_PTR(str
), RSTRING_PTR(str
)+RSTRING_LEN(str
), enc
);
4736 if (MBCLEN_NEEDMORE_P(r
)) {
4739 else if (MBCLEN_CHARFOUND_P(r
)) {
4740 cr
= ENC_CODERANGE_VALID
;
4745 str
= rb_str_new(fptr
->rbuf
.ptr
+fptr
->rbuf
.off
, 1);
4750 if (!cr
) cr
= ENC_CODERANGE_BROKEN
;
4751 str
= io_enc_str(str
, fptr
);
4752 ENC_CODERANGE_SET(str
, cr
);
4758 * each_char {|c| ... } -> self
4759 * each_char -> enumerator
4761 * Calls the given block with each character in the stream; returns +self+.
4762 * See {Character IO}[rdoc-ref:IO@Character+IO].
4764 * f = File.new('t.rus')
4766 * f.each_char {|c| a << c.ord }
4767 * a # => [1090, 1077, 1089, 1090]
4770 * Returns an Enumerator if no block is given.
4772 * Related: IO#each_byte, IO#each_codepoint.
4777 rb_io_each_char(VALUE io
)
4783 RETURN_ENUMERATOR(io
, 0, 0);
4784 GetOpenFile(io
, fptr
);
4785 rb_io_check_char_readable(fptr
);
4787 enc
= io_input_encoding(fptr
);
4789 while (!NIL_P(c
= io_getc(fptr
, enc
))) {
4797 * each_codepoint {|c| ... } -> self
4798 * each_codepoint -> enumerator
4800 * Calls the given block with each codepoint in the stream; returns +self+:
4802 * f = File.new('t.rus')
4804 * f.each_codepoint {|c| a << c }
4805 * a # => [1090, 1077, 1089, 1090]
4808 * Returns an Enumerator if no block is given.
4810 * Related: IO#each_byte, IO#each_char.
4815 rb_io_each_codepoint(VALUE io
)
4822 RETURN_ENUMERATOR(io
, 0, 0);
4823 GetOpenFile(io
, fptr
);
4824 rb_io_check_char_readable(fptr
);
4827 if (NEED_READCONV(fptr
)) {
4828 SET_BINARY_MODE(fptr
);
4829 r
= 1; /* no invalid char yet */
4831 make_readconv(fptr
, 0);
4833 if (fptr
->cbuf
.len
) {
4835 r
= rb_enc_precise_mbclen(fptr
->cbuf
.ptr
+fptr
->cbuf
.off
,
4836 fptr
->cbuf
.ptr
+fptr
->cbuf
.off
+fptr
->cbuf
.len
,
4839 r
= ONIGENC_CONSTRUCT_MBCLEN_CHARFOUND(1);
4840 if (!MBCLEN_NEEDMORE_P(r
))
4842 if (fptr
->cbuf
.len
== fptr
->cbuf
.capa
) {
4843 rb_raise(rb_eIOError
, "too long character");
4846 if (more_char(fptr
) == MORE_CHAR_FINISHED
) {
4847 clear_readconv(fptr
);
4848 if (!MBCLEN_CHARFOUND_P(r
)) {
4849 enc
= fptr
->encs
.enc
;
4855 if (MBCLEN_INVALID_P(r
)) {
4856 enc
= fptr
->encs
.enc
;
4859 n
= MBCLEN_CHARFOUND_LEN(r
);
4860 if (fptr
->encs
.enc
) {
4861 c
= rb_enc_codepoint(fptr
->cbuf
.ptr
+fptr
->cbuf
.off
,
4862 fptr
->cbuf
.ptr
+fptr
->cbuf
.off
+fptr
->cbuf
.len
,
4866 c
= (unsigned char)fptr
->cbuf
.ptr
[fptr
->cbuf
.off
];
4868 fptr
->cbuf
.off
+= n
;
4869 fptr
->cbuf
.len
-= n
;
4870 rb_yield(UINT2NUM(c
));
4871 rb_io_check_byte_readable(fptr
);
4874 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr
);
4875 enc
= io_input_encoding(fptr
);
4876 while (io_fillbuf(fptr
) >= 0) {
4877 r
= rb_enc_precise_mbclen(fptr
->rbuf
.ptr
+fptr
->rbuf
.off
,
4878 fptr
->rbuf
.ptr
+fptr
->rbuf
.off
+fptr
->rbuf
.len
, enc
);
4879 if (MBCLEN_CHARFOUND_P(r
) &&
4880 (n
= MBCLEN_CHARFOUND_LEN(r
)) <= fptr
->rbuf
.len
) {
4881 c
= rb_enc_codepoint(fptr
->rbuf
.ptr
+fptr
->rbuf
.off
,
4882 fptr
->rbuf
.ptr
+fptr
->rbuf
.off
+fptr
->rbuf
.len
, enc
);
4883 fptr
->rbuf
.off
+= n
;
4884 fptr
->rbuf
.len
-= n
;
4885 rb_yield(UINT2NUM(c
));
4887 else if (MBCLEN_INVALID_P(r
)) {
4890 else if (MBCLEN_NEEDMORE_P(r
)) {
4891 char cbuf
[8], *p
= cbuf
;
4892 int more
= MBCLEN_NEEDMORE_LEN(r
);
4893 if (more
> numberof(cbuf
)) goto invalid
;
4894 more
+= n
= fptr
->rbuf
.len
;
4895 if (more
> numberof(cbuf
)) goto invalid
;
4896 while ((n
= (int)read_buffered_data(p
, more
, fptr
)) > 0 &&
4897 (p
+= n
, (more
-= n
) > 0)) {
4898 if (io_fillbuf(fptr
) < 0) goto invalid
;
4899 if ((n
= fptr
->rbuf
.len
) > more
) n
= more
;
4901 r
= rb_enc_precise_mbclen(cbuf
, p
, enc
);
4902 if (!MBCLEN_CHARFOUND_P(r
)) goto invalid
;
4903 c
= rb_enc_codepoint(cbuf
, p
, enc
);
4904 rb_yield(UINT2NUM(c
));
4909 rb_io_check_byte_readable(fptr
);
4914 rb_raise(rb_eArgError
, "invalid byte sequence in %s", rb_enc_name(enc
));
4915 UNREACHABLE_RETURN(Qundef
);
4920 * getc -> character or nil
4922 * Reads and returns the next 1-character string from the stream;
4923 * returns +nil+ if already at end-of-stream.
4924 * See {Character IO}[rdoc-ref:IO@Character+IO].
4926 * f = File.open('t.txt')
4929 * f = File.open('t.rus')
4930 * f.getc.ord # => 1090
4933 * Related: IO#readchar (may raise EOFError).
4938 rb_io_getc(VALUE io
)
4943 GetOpenFile(io
, fptr
);
4944 rb_io_check_char_readable(fptr
);
4946 enc
= io_input_encoding(fptr
);
4948 return io_getc(fptr
, enc
);
4953 * readchar -> string
4955 * Reads and returns the next 1-character string from the stream;
4956 * raises EOFError if already at end-of-stream.
4957 * See {Character IO}[rdoc-ref:IO@Character+IO].
4959 * f = File.open('t.txt')
4960 * f.readchar # => "F"
4962 * f = File.open('t.rus')
4963 * f.readchar.ord # => 1090
4966 * Related: IO#getc (will not raise EOFError).
4971 rb_io_readchar(VALUE io
)
4973 VALUE c
= rb_io_getc(io
);
4983 * getbyte -> integer or nil
4985 * Reads and returns the next byte (in range 0..255) from the stream;
4986 * returns +nil+ if already at end-of-stream.
4987 * See {Byte IO}[rdoc-ref:IO@Byte+IO].
4989 * f = File.open('t.txt')
4992 * f = File.open('t.rus')
4993 * f.getbyte # => 209
4996 * Related: IO#readbyte (may raise EOFError).
5000 rb_io_getbyte(VALUE io
)
5005 GetOpenFile(io
, fptr
);
5006 rb_io_check_byte_readable(fptr
);
5008 VALUE r_stdout
= rb_ractor_stdout();
5009 if (fptr
->fd
== 0 && (fptr
->mode
& FMODE_TTY
) && RB_TYPE_P(r_stdout
, T_FILE
)) {
5011 GetOpenFile(r_stdout
, ofp
);
5012 if (ofp
->mode
& FMODE_TTY
) {
5013 rb_io_flush(r_stdout
);
5016 if (io_fillbuf(fptr
) < 0) {
5021 c
= (unsigned char)fptr
->rbuf
.ptr
[fptr
->rbuf
.off
-1];
5022 return INT2FIX(c
& 0xff);
5027 * readbyte -> integer
5029 * Reads and returns the next byte (in range 0..255) from the stream;
5030 * raises EOFError if already at end-of-stream.
5031 * See {Byte IO}[rdoc-ref:IO@Byte+IO].
5033 * f = File.open('t.txt')
5034 * f.readbyte # => 70
5036 * f = File.open('t.rus')
5037 * f.readbyte # => 209
5040 * Related: IO#getbyte (will not raise EOFError).
5045 rb_io_readbyte(VALUE io
)
5047 VALUE c
= rb_io_getbyte(io
);
5057 * ungetbyte(integer) -> nil
5058 * ungetbyte(string) -> nil
5060 * Pushes back ("unshifts") the given data onto the stream's buffer,
5061 * placing the data so that it is next to be read; returns +nil+.
5062 * See {Byte IO}[rdoc-ref:IO@Byte+IO].
5066 * - Calling the method has no effect with unbuffered reads (such as IO#sysread).
5067 * - Calling #rewind on the stream discards the pushed-back data.
5069 * When argument +integer+ is given, uses only its low-order byte:
5071 * File.write('t.tmp', '012')
5072 * f = File.open('t.tmp')
5073 * f.ungetbyte(0x41) # => nil
5074 * f.read # => "A012"
5076 * f.ungetbyte(0x4243) # => nil
5077 * f.read # => "C012"
5080 * When argument +string+ is given, uses all bytes:
5082 * File.write('t.tmp', '012')
5083 * f = File.open('t.tmp')
5084 * f.ungetbyte('A') # => nil
5085 * f.read # => "A012"
5087 * f.ungetbyte('BCDE') # => nil
5088 * f.read # => "BCDE012"
5094 rb_io_ungetbyte(VALUE io
, VALUE b
)
5098 GetOpenFile(io
, fptr
);
5099 rb_io_check_byte_readable(fptr
);
5105 VALUE v
= rb_int_modulo(b
, INT2FIX(256));
5106 unsigned char c
= NUM2INT(v
) & 0xFF;
5107 b
= rb_str_new((const char *)&c
, 1);
5112 io_ungetbyte(b
, fptr
);
5118 * ungetc(integer) -> nil
5119 * ungetc(string) -> nil
5121 * Pushes back ("unshifts") the given data onto the stream's buffer,
5122 * placing the data so that it is next to be read; returns +nil+.
5123 * See {Character IO}[rdoc-ref:IO@Character+IO].
5127 * - Calling the method has no effect with unbuffered reads (such as IO#sysread).
5128 * - Calling #rewind on the stream discards the pushed-back data.
5130 * When argument +integer+ is given, interprets the integer as a character:
5132 * File.write('t.tmp', '012')
5133 * f = File.open('t.tmp')
5134 * f.ungetc(0x41) # => nil
5135 * f.read # => "A012"
5137 * f.ungetc(0x0442) # => nil
5138 * f.getc.ord # => 1090
5141 * When argument +string+ is given, uses all characters:
5143 * File.write('t.tmp', '012')
5144 * f = File.open('t.tmp')
5145 * f.ungetc('A') # => nil
5146 * f.read # => "A012"
5148 * f.ungetc("\u0442\u0435\u0441\u0442") # => nil
5149 * f.getc.ord # => 1090
5150 * f.getc.ord # => 1077
5151 * f.getc.ord # => 1089
5152 * f.getc.ord # => 1090
5158 rb_io_ungetc(VALUE io
, VALUE c
)
5163 GetOpenFile(io
, fptr
);
5164 rb_io_check_char_readable(fptr
);
5166 c
= rb_enc_uint_chr(FIX2UINT(c
), io_read_encoding(fptr
));
5168 else if (RB_BIGNUM_TYPE_P(c
)) {
5169 c
= rb_enc_uint_chr(NUM2UINT(c
), io_read_encoding(fptr
));
5174 if (NEED_READCONV(fptr
)) {
5175 SET_BINARY_MODE(fptr
);
5176 len
= RSTRING_LEN(c
);
5177 #if SIZEOF_LONG > SIZEOF_INT
5179 rb_raise(rb_eIOError
, "ungetc failed");
5181 make_readconv(fptr
, (int)len
);
5182 if (fptr
->cbuf
.capa
- fptr
->cbuf
.len
< len
)
5183 rb_raise(rb_eIOError
, "ungetc failed");
5184 if (fptr
->cbuf
.off
< len
) {
5185 MEMMOVE(fptr
->cbuf
.ptr
+fptr
->cbuf
.capa
-fptr
->cbuf
.len
,
5186 fptr
->cbuf
.ptr
+fptr
->cbuf
.off
,
5187 char, fptr
->cbuf
.len
);
5188 fptr
->cbuf
.off
= fptr
->cbuf
.capa
-fptr
->cbuf
.len
;
5190 fptr
->cbuf
.off
-= (int)len
;
5191 fptr
->cbuf
.len
+= (int)len
;
5192 MEMMOVE(fptr
->cbuf
.ptr
+fptr
->cbuf
.off
, RSTRING_PTR(c
), char, len
);
5195 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr
);
5196 io_ungetbyte(c
, fptr
);
5203 * isatty -> true or false
5205 * Returns +true+ if the stream is associated with a terminal device (tty),
5206 * +false+ otherwise:
5208 * f = File.new('t.txt').isatty #=> false
5210 * f = File.new('/dev/tty').isatty #=> true
5216 rb_io_isatty(VALUE io
)
5220 GetOpenFile(io
, fptr
);
5221 return RBOOL(isatty(fptr
->fd
) != 0);
5224 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
5227 * close_on_exec? -> true or false
5229 * Returns +true+ if the stream will be closed on exec, +false+ otherwise:
5231 * f = File.open('t.txt')
5232 * f.close_on_exec? # => true
5233 * f.close_on_exec = false
5234 * f.close_on_exec? # => false
5240 rb_io_close_on_exec_p(VALUE io
)
5246 write_io
= GetWriteIO(io
);
5247 if (io
!= write_io
) {
5248 GetOpenFile(write_io
, fptr
);
5249 if (fptr
&& 0 <= (fd
= fptr
->fd
)) {
5250 if ((ret
= fcntl(fd
, F_GETFD
)) == -1) rb_sys_fail_path(fptr
->pathv
);
5251 if (!(ret
& FD_CLOEXEC
)) return Qfalse
;
5255 GetOpenFile(io
, fptr
);
5256 if (fptr
&& 0 <= (fd
= fptr
->fd
)) {
5257 if ((ret
= fcntl(fd
, F_GETFD
)) == -1) rb_sys_fail_path(fptr
->pathv
);
5258 if (!(ret
& FD_CLOEXEC
)) return Qfalse
;
5263 #define rb_io_close_on_exec_p rb_f_notimplement
5266 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
5269 * self.close_on_exec = bool -> true or false
5271 * Sets a close-on-exec flag.
5273 * f = File.open(File::NULL)
5274 * f.close_on_exec = true
5275 * system("cat", "/proc/self/fd/#{f.fileno}") # cat: /proc/self/fd/3: No such file or directory
5276 * f.closed? #=> false
5278 * Ruby sets close-on-exec flags of all file descriptors by default
5280 * So you don't need to set by yourself.
5281 * Also, unsetting a close-on-exec flag can cause file descriptor leak
5282 * if another thread use fork() and exec() (via system() method for example).
5283 * If you really needs file descriptor inheritance to child process,
5284 * use spawn()'s argument such as fd=>fd.
5288 rb_io_set_close_on_exec(VALUE io
, VALUE arg
)
5290 int flag
= RTEST(arg
) ? FD_CLOEXEC
: 0;
5295 write_io
= GetWriteIO(io
);
5296 if (io
!= write_io
) {
5297 GetOpenFile(write_io
, fptr
);
5298 if (fptr
&& 0 <= (fd
= fptr
->fd
)) {
5299 if ((ret
= fcntl(fptr
->fd
, F_GETFD
)) == -1) rb_sys_fail_path(fptr
->pathv
);
5300 if ((ret
& FD_CLOEXEC
) != flag
) {
5301 ret
= (ret
& ~FD_CLOEXEC
) | flag
;
5302 ret
= fcntl(fd
, F_SETFD
, ret
);
5303 if (ret
!= 0) rb_sys_fail_path(fptr
->pathv
);
5309 GetOpenFile(io
, fptr
);
5310 if (fptr
&& 0 <= (fd
= fptr
->fd
)) {
5311 if ((ret
= fcntl(fd
, F_GETFD
)) == -1) rb_sys_fail_path(fptr
->pathv
);
5312 if ((ret
& FD_CLOEXEC
) != flag
) {
5313 ret
= (ret
& ~FD_CLOEXEC
) | flag
;
5314 ret
= fcntl(fd
, F_SETFD
, ret
);
5315 if (ret
!= 0) rb_sys_fail_path(fptr
->pathv
);
5321 #define rb_io_set_close_on_exec rb_f_notimplement
5324 #define RUBY_IO_EXTERNAL_P(f) ((f)->mode & FMODE_EXTERNAL)
5325 #define PREP_STDIO_NAME(f) (RSTRING_PTR((f)->pathv))
5328 finish_writeconv(rb_io_t
*fptr
, int noalloc
)
5330 unsigned char *ds
, *dp
, *de
;
5331 rb_econv_result_t res
;
5333 if (!fptr
->wbuf
.ptr
) {
5334 unsigned char buf
[1024];
5336 res
= econv_destination_buffer_full
;
5337 while (res
== econv_destination_buffer_full
) {
5339 de
= buf
+ sizeof(buf
);
5340 res
= rb_econv_convert(fptr
->writeconv
, NULL
, NULL
, &dp
, de
, 0);
5342 size_t remaining
= dp
-ds
;
5343 long result
= rb_io_write_memory(fptr
, ds
, remaining
);
5347 if ((size_t)result
== remaining
) break;
5349 else if (rb_io_maybe_wait_writable(errno
, fptr
->self
, RUBY_IO_TIMEOUT_DEFAULT
)) {
5351 return noalloc
? Qtrue
: rb_exc_new3(rb_eIOError
, rb_str_new_cstr(closed_stream
));
5354 return noalloc
? Qtrue
: INT2NUM(errno
);
5357 if (res
== econv_invalid_byte_sequence
||
5358 res
== econv_incomplete_input
||
5359 res
== econv_undefined_conversion
) {
5360 return noalloc
? Qtrue
: rb_econv_make_exception(fptr
->writeconv
);
5367 res
= econv_destination_buffer_full
;
5368 while (res
== econv_destination_buffer_full
) {
5369 if (fptr
->wbuf
.len
== fptr
->wbuf
.capa
) {
5370 if (io_fflush(fptr
) < 0) {
5371 return noalloc
? Qtrue
: INT2NUM(errno
);
5375 ds
= dp
= (unsigned char *)fptr
->wbuf
.ptr
+ fptr
->wbuf
.off
+ fptr
->wbuf
.len
;
5376 de
= (unsigned char *)fptr
->wbuf
.ptr
+ fptr
->wbuf
.capa
;
5377 res
= rb_econv_convert(fptr
->writeconv
, NULL
, NULL
, &dp
, de
, 0);
5378 fptr
->wbuf
.len
+= (int)(dp
- ds
);
5379 if (res
== econv_invalid_byte_sequence
||
5380 res
== econv_incomplete_input
||
5381 res
== econv_undefined_conversion
) {
5382 return noalloc
? Qtrue
: rb_econv_make_exception(fptr
->writeconv
);
5388 struct finish_writeconv_arg
{
5394 finish_writeconv_sync(VALUE arg
)
5396 struct finish_writeconv_arg
*p
= (struct finish_writeconv_arg
*)arg
;
5397 return finish_writeconv(p
->fptr
, p
->noalloc
);
5401 nogvl_close(void *ptr
)
5405 return (void*)(intptr_t)close(*fd
);
5409 maygvl_close(int fd
, int keepgvl
)
5415 * close() may block for certain file types (NFS, SO_LINGER sockets,
5416 * inotify), so let other threads run.
5418 return IO_WITHOUT_GVL_INT(nogvl_close
, &fd
);
5422 nogvl_fclose(void *ptr
)
5426 return (void*)(intptr_t)fclose(file
);
5430 maygvl_fclose(FILE *file
, int keepgvl
)
5433 return fclose(file
);
5435 return IO_WITHOUT_GVL_INT(nogvl_fclose
, file
);
5438 static void free_io_buffer(rb_io_buffer_t
*buf
);
5439 static void clear_codeconv(rb_io_t
*fptr
);
5442 fptr_finalize_flush(rb_io_t
*fptr
, int noraise
, int keepgvl
,
5443 struct rb_io_close_wait_list
*busy
)
5447 FILE *stdio_file
= fptr
->stdio_file
;
5448 int mode
= fptr
->mode
;
5450 if (fptr
->writeconv
) {
5451 if (!NIL_P(fptr
->write_lock
) && !noraise
) {
5452 struct finish_writeconv_arg arg
;
5454 arg
.noalloc
= noraise
;
5455 error
= rb_mutex_synchronize(fptr
->write_lock
, finish_writeconv_sync
, (VALUE
)&arg
);
5458 error
= finish_writeconv(fptr
, noraise
);
5461 if (fptr
->wbuf
.len
) {
5463 io_flush_buffer_sync(fptr
);
5466 if (io_fflush(fptr
) < 0 && NIL_P(error
)) {
5467 error
= INT2NUM(errno
);
5474 if (RUBY_IO_EXTERNAL_P(fptr
) || fd
<= 2) {
5475 // Need to keep FILE objects of stdin, stdout and stderr, so we are done:
5480 fptr
->stdio_file
= 0;
5481 fptr
->mode
&= ~(FMODE_READABLE
|FMODE_WRITABLE
);
5483 // Ensure waiting_fd users do not hit EBADF.
5485 // Wait for them to exit before we call close().
5486 rb_notify_fd_close_wait(busy
);
5490 // if (!done && fd >= 0) {
5491 // VALUE scheduler = rb_fiber_scheduler_current();
5492 // if (scheduler != Qnil) {
5493 // VALUE result = rb_fiber_scheduler_io_close(scheduler, fptr->self);
5494 // if (!UNDEF_P(result)) done = 1;
5498 if (!done
&& stdio_file
) {
5499 // stdio_file is deallocated anyway even if fclose failed.
5500 if ((maygvl_fclose(stdio_file
, noraise
) < 0) && NIL_P(error
)) {
5502 error
= INT2NUM(errno
);
5509 if (!done
&& fd
>= 0) {
5510 // fptr->fd may be closed even if close fails. POSIX doesn't specify it.
5511 // We assumes it is closed.
5513 keepgvl
|= !(mode
& FMODE_WRITABLE
);
5515 if ((maygvl_close(fd
, keepgvl
) < 0) && NIL_P(error
)) {
5517 error
= INT2NUM(errno
);
5524 if (!NIL_P(error
) && !noraise
) {
5525 if (RB_INTEGER_TYPE_P(error
))
5526 rb_syserr_fail_path(NUM2INT(error
), fptr
->pathv
);
5528 rb_exc_raise(error
);
5533 fptr_finalize(rb_io_t
*fptr
, int noraise
)
5535 fptr_finalize_flush(fptr
, noraise
, FALSE
, 0);
5536 free_io_buffer(&fptr
->rbuf
);
5537 free_io_buffer(&fptr
->wbuf
);
5538 clear_codeconv(fptr
);
5542 rb_io_fptr_cleanup(rb_io_t
*fptr
, int noraise
)
5544 if (fptr
->finalize
) {
5545 (*fptr
->finalize
)(fptr
, noraise
);
5548 fptr_finalize(fptr
, noraise
);
5553 free_io_buffer(rb_io_buffer_t
*buf
)
5556 ruby_sized_xfree(buf
->ptr
, (size_t)buf
->capa
);
5562 clear_readconv(rb_io_t
*fptr
)
5564 if (fptr
->readconv
) {
5565 rb_econv_close(fptr
->readconv
);
5566 fptr
->readconv
= NULL
;
5568 free_io_buffer(&fptr
->cbuf
);
5572 clear_writeconv(rb_io_t
*fptr
)
5574 if (fptr
->writeconv
) {
5575 rb_econv_close(fptr
->writeconv
);
5576 fptr
->writeconv
= NULL
;
5578 fptr
->writeconv_initialized
= 0;
5582 clear_codeconv(rb_io_t
*fptr
)
5584 clear_readconv(fptr
);
5585 clear_writeconv(fptr
);
5589 rb_io_fptr_cleanup_all(rb_io_t
*fptr
)
5593 rb_io_fptr_cleanup(fptr
, TRUE
);
5594 fptr
->write_lock
= Qnil
;
5595 free_io_buffer(&fptr
->rbuf
);
5596 free_io_buffer(&fptr
->wbuf
);
5597 clear_codeconv(fptr
);
5601 rb_io_fptr_finalize_internal(void *ptr
)
5604 rb_io_fptr_cleanup_all(ptr
);
5608 #undef rb_io_fptr_finalize
5610 rb_io_fptr_finalize(rb_io_t
*fptr
)
5616 rb_io_fptr_finalize_internal(fptr
);
5620 #define rb_io_fptr_finalize(fptr) rb_io_fptr_finalize_internal(fptr)
5623 rb_io_memsize(const rb_io_t
*fptr
)
5625 size_t size
= sizeof(rb_io_t
);
5626 size
+= fptr
->rbuf
.capa
;
5627 size
+= fptr
->wbuf
.capa
;
5628 size
+= fptr
->cbuf
.capa
;
5629 if (fptr
->readconv
) size
+= rb_econv_memsize(fptr
->readconv
);
5630 if (fptr
->writeconv
) size
+= rb_econv_memsize(fptr
->writeconv
);
5635 /* keep GVL while closing to prevent crash on Windows */
5636 # define KEEPGVL TRUE
5638 # define KEEPGVL FALSE
5642 io_close_fptr(VALUE io
)
5646 rb_io_t
*write_fptr
;
5647 struct rb_io_close_wait_list busy
;
5649 write_io
= GetWriteIO(io
);
5650 if (io
!= write_io
) {
5651 write_fptr
= RFILE(write_io
)->fptr
;
5652 if (write_fptr
&& 0 <= write_fptr
->fd
) {
5653 rb_io_fptr_cleanup(write_fptr
, TRUE
);
5657 fptr
= RFILE(io
)->fptr
;
5658 if (!fptr
) return 0;
5659 if (fptr
->fd
< 0) return 0;
5661 if (rb_notify_fd_close(fptr
->fd
, &busy
)) {
5662 /* calls close(fptr->fd): */
5663 fptr_finalize_flush(fptr
, FALSE
, KEEPGVL
, &busy
);
5665 rb_io_fptr_cleanup(fptr
, FALSE
);
5670 fptr_waitpid(rb_io_t
*fptr
, int nohang
)
5674 rb_last_status_clear();
5675 rb_waitpid(fptr
->pid
, &status
, nohang
? WNOHANG
: 0);
5681 rb_io_close(VALUE io
)
5683 rb_io_t
*fptr
= io_close_fptr(io
);
5684 if (fptr
) fptr_waitpid(fptr
, 0);
5692 * Closes the stream for both reading and writing
5693 * if open for either or both; returns +nil+.
5694 * See {Open and Closed Streams}[rdoc-ref:IO@Open+and+Closed+Streams].
5696 * If the stream is open for writing, flushes any buffered writes
5697 * to the operating system before closing.
5699 * If the stream was opened by IO.popen, sets global variable <tt>$?</tt>
5700 * (child exit status).
5704 * IO.popen('ruby', 'r+') do |pipe|
5717 * Related: IO#close_read, IO#close_write, IO#closed?.
5721 rb_io_close_m(VALUE io
)
5723 rb_io_t
*fptr
= rb_io_get_fptr(io
);
5732 io_call_close(VALUE io
)
5734 rb_check_funcall(io
, rb_intern("close"), 0, 0);
5739 ignore_closed_stream(VALUE io
, VALUE exc
)
5741 enum {mesg_len
= sizeof(closed_stream
)-1};
5742 VALUE mesg
= rb_attr_get(exc
, idMesg
);
5743 if (!RB_TYPE_P(mesg
, T_STRING
) ||
5744 RSTRING_LEN(mesg
) != mesg_len
||
5745 memcmp(RSTRING_PTR(mesg
), closed_stream
, mesg_len
)) {
5754 VALUE closed
= rb_check_funcall(io
, rb_intern("closed?"), 0, 0);
5755 if (!UNDEF_P(closed
) && RTEST(closed
)) return io
;
5756 rb_rescue2(io_call_close
, io
, ignore_closed_stream
, io
,
5757 rb_eIOError
, (VALUE
)0);
5763 * closed? -> true or false
5765 * Returns +true+ if the stream is closed for both reading and writing,
5766 * +false+ otherwise.
5767 * See {Open and Closed Streams}[rdoc-ref:IO@Open+and+Closed+Streams].
5769 * IO.popen('ruby', 'r+') do |pipe|
5783 * Related: IO#close_read, IO#close_write, IO#close.
5786 rb_io_closed_p(VALUE io
)
5790 rb_io_t
*write_fptr
;
5792 write_io
= GetWriteIO(io
);
5793 if (io
!= write_io
) {
5794 write_fptr
= RFILE(write_io
)->fptr
;
5795 if (write_fptr
&& 0 <= write_fptr
->fd
) {
5800 fptr
= rb_io_get_fptr(io
);
5801 return RBOOL(0 > fptr
->fd
);
5808 * Closes the stream for reading if open for reading;
5810 * See {Open and Closed Streams}[rdoc-ref:IO@Open+and+Closed+Streams].
5812 * If the stream was opened by IO.popen and is also closed for writing,
5813 * sets global variable <tt>$?</tt> (child exit status).
5817 * IO.popen('ruby', 'r+') do |pipe|
5833 * Related: IO#close, IO#close_write, IO#closed?.
5837 rb_io_close_read(VALUE io
)
5842 fptr
= rb_io_get_fptr(rb_io_taint_check(io
));
5843 if (fptr
->fd
< 0) return Qnil
;
5844 if (is_socket(fptr
->fd
, fptr
->pathv
)) {
5848 if (shutdown(fptr
->fd
, SHUT_RD
) < 0)
5849 rb_sys_fail_path(fptr
->pathv
);
5850 fptr
->mode
&= ~FMODE_READABLE
;
5851 if (!(fptr
->mode
& FMODE_WRITABLE
))
5852 return rb_io_close(io
);
5856 write_io
= GetWriteIO(io
);
5857 if (io
!= write_io
) {
5859 wfptr
= rb_io_get_fptr(rb_io_taint_check(write_io
));
5860 wfptr
->pid
= fptr
->pid
;
5862 RFILE(io
)->fptr
= wfptr
;
5863 /* bind to write_io temporarily to get rid of memory/fd leak */
5864 fptr
->tied_io_for_writing
= 0;
5865 RFILE(write_io
)->fptr
= fptr
;
5866 rb_io_fptr_cleanup(fptr
, FALSE
);
5867 /* should not finalize fptr because another thread may be reading it */
5871 if ((fptr
->mode
& (FMODE_DUPLEX
|FMODE_WRITABLE
)) == FMODE_WRITABLE
) {
5872 rb_raise(rb_eIOError
, "closing non-duplex IO for reading");
5874 return rb_io_close(io
);
5879 * close_write -> nil
5881 * Closes the stream for writing if open for writing;
5883 * See {Open and Closed Streams}[rdoc-ref:IO@Open+and+Closed+Streams].
5885 * Flushes any buffered writes to the operating system before closing.
5887 * If the stream was opened by IO.popen and is also closed for reading,
5888 * sets global variable <tt>$?</tt> (child exit status).
5890 * IO.popen('ruby', 'r+') do |pipe|
5906 * Related: IO#close, IO#close_read, IO#closed?.
5910 rb_io_close_write(VALUE io
)
5915 write_io
= GetWriteIO(io
);
5916 fptr
= rb_io_get_fptr(rb_io_taint_check(write_io
));
5917 if (fptr
->fd
< 0) return Qnil
;
5918 if (is_socket(fptr
->fd
, fptr
->pathv
)) {
5922 if (shutdown(fptr
->fd
, SHUT_WR
) < 0)
5923 rb_sys_fail_path(fptr
->pathv
);
5924 fptr
->mode
&= ~FMODE_WRITABLE
;
5925 if (!(fptr
->mode
& FMODE_READABLE
))
5926 return rb_io_close(write_io
);
5930 if ((fptr
->mode
& (FMODE_DUPLEX
|FMODE_READABLE
)) == FMODE_READABLE
) {
5931 rb_raise(rb_eIOError
, "closing non-duplex IO for writing");
5934 if (io
!= write_io
) {
5935 fptr
= rb_io_get_fptr(rb_io_taint_check(io
));
5936 fptr
->tied_io_for_writing
= 0;
5938 rb_io_close(write_io
);
5944 * sysseek(offset, whence = IO::SEEK_SET) -> integer
5946 * Behaves like IO#seek, except that it:
5948 * - Uses low-level system functions.
5949 * - Returns the new position.
5954 rb_io_sysseek(int argc
, VALUE
*argv
, VALUE io
)
5956 VALUE offset
, ptrname
;
5957 int whence
= SEEK_SET
;
5961 if (rb_scan_args(argc
, argv
, "11", &offset
, &ptrname
) == 2) {
5962 whence
= interpret_seek_whence(ptrname
);
5964 pos
= NUM2OFFT(offset
);
5965 GetOpenFile(io
, fptr
);
5966 if ((fptr
->mode
& FMODE_READABLE
) &&
5967 (READ_DATA_BUFFERED(fptr
) || READ_CHAR_PENDING(fptr
))) {
5968 rb_raise(rb_eIOError
, "sysseek for buffered IO");
5970 if ((fptr
->mode
& FMODE_WRITABLE
) && fptr
->wbuf
.len
) {
5971 rb_warn("sysseek for buffered IO");
5974 pos
= lseek(fptr
->fd
, pos
, whence
);
5975 if (pos
< 0 && errno
) rb_sys_fail_path(fptr
->pathv
);
5977 return OFFT2NUM(pos
);
5982 * syswrite(object) -> integer
5984 * Writes the given +object+ to self, which must be opened for writing (see Modes);
5985 * returns the number bytes written.
5986 * If +object+ is not a string is converted via method to_s:
5988 * f = File.new('t.tmp', 'w')
5989 * f.syswrite('foo') # => 3
5990 * f.syswrite(30) # => 2
5991 * f.syswrite(:foo) # => 3
5994 * This methods should not be used with other stream-writer methods.
5999 rb_io_syswrite(VALUE io
, VALUE str
)
6006 if (!RB_TYPE_P(str
, T_STRING
))
6007 str
= rb_obj_as_string(str
);
6009 io
= GetWriteIO(io
);
6010 GetOpenFile(io
, fptr
);
6011 rb_io_check_writable(fptr
);
6013 if (fptr
->wbuf
.len
) {
6014 rb_warn("syswrite for buffered IO");
6017 tmp
= rb_str_tmp_frozen_acquire(str
);
6018 RSTRING_GETMEM(tmp
, ptr
, len
);
6019 n
= rb_io_write_memory(fptr
, ptr
, len
);
6020 if (n
< 0) rb_sys_fail_path(fptr
->pathv
);
6021 rb_str_tmp_frozen_release(str
, tmp
);
6028 * sysread(maxlen) -> string
6029 * sysread(maxlen, out_string) -> string
6031 * Behaves like IO#readpartial, except that it uses low-level system functions.
6033 * This method should not be used with other stream-reader methods.
6038 rb_io_sysread(int argc
, VALUE
*argv
, VALUE io
)
6043 struct io_internal_read_struct iis
;
6046 rb_scan_args(argc
, argv
, "11", &len
, &str
);
6047 ilen
= NUM2LONG(len
);
6049 shrinkable
= io_setstrbuf(&str
, ilen
);
6050 if (ilen
== 0) return str
;
6052 GetOpenFile(io
, fptr
);
6053 rb_io_check_byte_readable(fptr
);
6055 if (READ_DATA_BUFFERED(fptr
)) {
6056 rb_raise(rb_eIOError
, "sysread for buffered IO");
6059 rb_io_check_closed(fptr
);
6061 io_setstrbuf(&str
, ilen
);
6062 iis
.th
= rb_thread_current();
6066 iis
.buf
= RSTRING_PTR(str
);
6069 n
= io_read_memory_locktmp(str
, &iis
);
6072 rb_sys_fail_path(fptr
->pathv
);
6075 io_set_read_length(str
, n
, shrinkable
);
6077 if (n
== 0 && ilen
> 0) {
6084 struct prdwr_internal_arg
{
6093 internal_pread_func(void *_arg
)
6095 struct prdwr_internal_arg
*arg
= _arg
;
6097 return (VALUE
)pread(arg
->fd
, arg
->buf
, arg
->count
, arg
->offset
);
6101 pread_internal_call(VALUE _arg
)
6103 struct prdwr_internal_arg
*arg
= (struct prdwr_internal_arg
*)_arg
;
6105 VALUE scheduler
= rb_fiber_scheduler_current();
6106 if (scheduler
!= Qnil
) {
6107 VALUE result
= rb_fiber_scheduler_io_pread_memory(scheduler
, arg
->io
, arg
->offset
, arg
->buf
, arg
->count
, 0);
6109 if (!UNDEF_P(result
)) {
6110 return rb_fiber_scheduler_io_result_apply(result
);
6114 return rb_thread_io_blocking_call(internal_pread_func
, arg
, arg
->fd
, RB_WAITFD_IN
);
6119 * pread(maxlen, offset) -> string
6120 * pread(maxlen, offset, out_string) -> string
6122 * Behaves like IO#readpartial, except that it:
6124 * - Reads at the given +offset+ (in bytes).
6125 * - Disregards, and does not modify, the stream's position
6126 * (see {Position}[rdoc-ref:IO@Position]).
6127 * - Bypasses any user space buffering in the stream.
6129 * Because this method does not disturb the stream's state
6130 * (its position, in particular), +pread+ allows multiple threads and processes
6131 * to use the same \IO object for reading at various offsets.
6133 * f = File.open('t.txt')
6134 * f.read # => "First line\nSecond line\n\nFourth line\nFifth line\n"
6136 * # Read 12 bytes at offset 0.
6137 * f.pread(12, 0) # => "First line\n"
6138 * # Read 9 bytes at offset 8.
6139 * f.pread(9, 8) # => "ne\nSecon"
6142 * Not available on some platforms.
6146 rb_io_pread(int argc
, VALUE
*argv
, VALUE io
)
6148 VALUE len
, offset
, str
;
6151 struct prdwr_internal_arg arg
= {.io
= io
};
6154 rb_scan_args(argc
, argv
, "21", &len
, &offset
, &str
);
6155 arg
.count
= NUM2SIZET(len
);
6156 arg
.offset
= NUM2OFFT(offset
);
6158 shrinkable
= io_setstrbuf(&str
, (long)arg
.count
);
6159 if (arg
.count
== 0) return str
;
6160 arg
.buf
= RSTRING_PTR(str
);
6162 GetOpenFile(io
, fptr
);
6163 rb_io_check_byte_readable(fptr
);
6166 rb_io_check_closed(fptr
);
6168 rb_str_locktmp(str
);
6169 n
= (ssize_t
)rb_ensure(pread_internal_call
, (VALUE
)&arg
, rb_str_unlocktmp
, str
);
6172 rb_sys_fail_path(fptr
->pathv
);
6174 io_set_read_length(str
, n
, shrinkable
);
6175 if (n
== 0 && arg
.count
> 0) {
6183 internal_pwrite_func(void *_arg
)
6185 struct prdwr_internal_arg
*arg
= _arg
;
6187 VALUE scheduler
= rb_fiber_scheduler_current();
6188 if (scheduler
!= Qnil
) {
6189 VALUE result
= rb_fiber_scheduler_io_pwrite_memory(scheduler
, arg
->io
, arg
->offset
, arg
->buf
, arg
->count
, 0);
6191 if (!UNDEF_P(result
)) {
6192 return rb_fiber_scheduler_io_result_apply(result
);
6197 return (VALUE
)pwrite(arg
->fd
, arg
->buf
, arg
->count
, arg
->offset
);
6202 * pwrite(object, offset) -> integer
6204 * Behaves like IO#write, except that it:
6206 * - Writes at the given +offset+ (in bytes).
6207 * - Disregards, and does not modify, the stream's position
6208 * (see {Position}[rdoc-ref:IO@Position]).
6209 * - Bypasses any user space buffering in the stream.
6211 * Because this method does not disturb the stream's state
6212 * (its position, in particular), +pwrite+ allows multiple threads and processes
6213 * to use the same \IO object for writing at various offsets.
6215 * f = File.open('t.tmp', 'w+')
6216 * # Write 6 bytes at offset 3.
6217 * f.pwrite('ABCDEF', 3) # => 6
6219 * f.read # => "\u0000\u0000\u0000ABCDEF"
6222 * Not available on some platforms.
6226 rb_io_pwrite(VALUE io
, VALUE str
, VALUE offset
)
6230 struct prdwr_internal_arg arg
= {.io
= io
};
6233 if (!RB_TYPE_P(str
, T_STRING
))
6234 str
= rb_obj_as_string(str
);
6236 arg
.offset
= NUM2OFFT(offset
);
6238 io
= GetWriteIO(io
);
6239 GetOpenFile(io
, fptr
);
6240 rb_io_check_writable(fptr
);
6243 tmp
= rb_str_tmp_frozen_acquire(str
);
6244 arg
.buf
= RSTRING_PTR(tmp
);
6245 arg
.count
= (size_t)RSTRING_LEN(tmp
);
6247 n
= (ssize_t
)rb_thread_io_blocking_call(internal_pwrite_func
, &arg
, fptr
->fd
, RB_WAITFD_OUT
);
6248 if (n
< 0) rb_sys_fail_path(fptr
->pathv
);
6249 rb_str_tmp_frozen_release(str
, tmp
);
6251 return SSIZET2NUM(n
);
6255 rb_io_binmode(VALUE io
)
6259 GetOpenFile(io
, fptr
);
6261 rb_econv_binmode(fptr
->readconv
);
6262 if (fptr
->writeconv
)
6263 rb_econv_binmode(fptr
->writeconv
);
6264 fptr
->mode
|= FMODE_BINMODE
;
6265 fptr
->mode
&= ~FMODE_TEXTMODE
;
6266 fptr
->writeconv_pre_ecflags
&= ~ECONV_NEWLINE_DECORATOR_MASK
;
6268 if (!fptr
->readconv
) {
6269 SET_BINARY_MODE_WITH_SEEK_CUR(fptr
);
6272 setmode(fptr
->fd
, O_BINARY
);
6279 io_ascii8bit_binmode(rb_io_t
*fptr
)
6281 if (fptr
->readconv
) {
6282 rb_econv_close(fptr
->readconv
);
6283 fptr
->readconv
= NULL
;
6285 if (fptr
->writeconv
) {
6286 rb_econv_close(fptr
->writeconv
);
6287 fptr
->writeconv
= NULL
;
6289 fptr
->mode
|= FMODE_BINMODE
;
6290 fptr
->mode
&= ~FMODE_TEXTMODE
;
6291 SET_BINARY_MODE_WITH_SEEK_CUR(fptr
);
6293 fptr
->encs
.enc
= rb_ascii8bit_encoding();
6294 fptr
->encs
.enc2
= NULL
;
6295 fptr
->encs
.ecflags
= 0;
6296 fptr
->encs
.ecopts
= Qnil
;
6297 clear_codeconv(fptr
);
6301 rb_io_ascii8bit_binmode(VALUE io
)
6305 GetOpenFile(io
, fptr
);
6306 io_ascii8bit_binmode(fptr
);
6315 * Sets the stream's data mode as binary
6316 * (see {Data Mode}[rdoc-ref:File@Data+Mode]).
6318 * A stream's data mode may not be changed from binary to text.
6323 rb_io_binmode_m(VALUE io
)
6327 rb_io_ascii8bit_binmode(io
);
6329 write_io
= GetWriteIO(io
);
6331 rb_io_ascii8bit_binmode(write_io
);
6337 * binmode? -> true or false
6339 * Returns +true+ if the stream is on binary mode, +false+ otherwise.
6340 * See {Data Mode}[rdoc-ref:File@Data+Mode].
6344 rb_io_binmode_p(VALUE io
)
6347 GetOpenFile(io
, fptr
);
6348 return RBOOL(fptr
->mode
& FMODE_BINMODE
);
6352 rb_io_fmode_modestr(int fmode
)
6354 if (fmode
& FMODE_APPEND
) {
6355 if ((fmode
& FMODE_READWRITE
) == FMODE_READWRITE
) {
6356 return MODE_BTMODE("a+", "ab+", "at+");
6358 return MODE_BTMODE("a", "ab", "at");
6360 switch (fmode
& FMODE_READWRITE
) {
6362 rb_raise(rb_eArgError
, "invalid access fmode 0x%x", fmode
);
6363 case FMODE_READABLE
:
6364 return MODE_BTMODE("r", "rb", "rt");
6365 case FMODE_WRITABLE
:
6366 return MODE_BTXMODE("w", "wb", "wt", "wx", "wbx", "wtx");
6367 case FMODE_READWRITE
:
6368 if (fmode
& FMODE_CREATE
) {
6369 return MODE_BTXMODE("w+", "wb+", "wt+", "w+x", "wb+x", "wt+x");
6371 return MODE_BTMODE("r+", "rb+", "rt+");
6375 static const char bom_prefix
[] = "bom|";
6376 static const char utf_prefix
[] = "utf-";
6377 enum {bom_prefix_len
= (int)sizeof(bom_prefix
) - 1};
6378 enum {utf_prefix_len
= (int)sizeof(utf_prefix
) - 1};
6381 io_encname_bom_p(const char *name
, long len
)
6383 return len
> bom_prefix_len
&& STRNCASECMP(name
, bom_prefix
, bom_prefix_len
) == 0;
6387 rb_io_modestr_fmode(const char *modestr
)
6390 const char *m
= modestr
, *p
= NULL
;
6394 fmode
|= FMODE_READABLE
;
6397 fmode
|= FMODE_WRITABLE
| FMODE_TRUNC
| FMODE_CREATE
;
6400 fmode
|= FMODE_WRITABLE
| FMODE_APPEND
| FMODE_CREATE
;
6409 fmode
|= FMODE_BINMODE
;
6412 fmode
|= FMODE_TEXTMODE
;
6415 fmode
|= FMODE_READWRITE
;
6418 if (modestr
[0] != 'w')
6420 fmode
|= FMODE_EXCL
;
6426 if (io_encname_bom_p(m
, p
? (long)(p
- m
) : (long)strlen(m
)))
6427 fmode
|= FMODE_SETENC_BY_BOM
;
6433 if ((fmode
& FMODE_BINMODE
) && (fmode
& FMODE_TEXTMODE
))
6439 rb_raise(rb_eArgError
, "invalid access mode %s", modestr
);
6440 UNREACHABLE_RETURN(Qundef
);
6444 rb_io_oflags_fmode(int oflags
)
6448 switch (oflags
& O_ACCMODE
) {
6450 fmode
= FMODE_READABLE
;
6453 fmode
= FMODE_WRITABLE
;
6456 fmode
= FMODE_READWRITE
;
6460 if (oflags
& O_APPEND
) {
6461 fmode
|= FMODE_APPEND
;
6463 if (oflags
& O_TRUNC
) {
6464 fmode
|= FMODE_TRUNC
;
6466 if (oflags
& O_CREAT
) {
6467 fmode
|= FMODE_CREATE
;
6469 if (oflags
& O_EXCL
) {
6470 fmode
|= FMODE_EXCL
;
6473 if (oflags
& O_BINARY
) {
6474 fmode
|= FMODE_BINMODE
;
6482 rb_io_fmode_oflags(int fmode
)
6486 switch (fmode
& FMODE_READWRITE
) {
6487 case FMODE_READABLE
:
6490 case FMODE_WRITABLE
:
6493 case FMODE_READWRITE
:
6498 if (fmode
& FMODE_APPEND
) {
6501 if (fmode
& FMODE_TRUNC
) {
6504 if (fmode
& FMODE_CREATE
) {
6507 if (fmode
& FMODE_EXCL
) {
6511 if (fmode
& FMODE_BINMODE
) {
6520 rb_io_modestr_oflags(const char *modestr
)
6522 return rb_io_fmode_oflags(rb_io_modestr_fmode(modestr
));
6526 rb_io_oflags_modestr(int oflags
)
6529 # define MODE_BINARY(a,b) ((oflags & O_BINARY) ? (b) : (a))
6531 # define MODE_BINARY(a,b) (a)
6534 if (oflags
& O_EXCL
) {
6535 rb_raise(rb_eArgError
, "exclusive access mode is not supported");
6537 accmode
= oflags
& (O_RDONLY
|O_WRONLY
|O_RDWR
);
6538 if (oflags
& O_APPEND
) {
6539 if (accmode
== O_WRONLY
) {
6540 return MODE_BINARY("a", "ab");
6542 if (accmode
== O_RDWR
) {
6543 return MODE_BINARY("a+", "ab+");
6548 rb_raise(rb_eArgError
, "invalid access oflags 0x%x", oflags
);
6550 return MODE_BINARY("r", "rb");
6552 return MODE_BINARY("w", "wb");
6554 if (oflags
& O_TRUNC
) {
6555 return MODE_BINARY("w+", "wb+");
6557 return MODE_BINARY("r+", "rb+");
6562 * Convert external/internal encodings to enc/enc2
6563 * NULL => use default encoding
6564 * Qnil => no encoding specified (internal only)
6567 rb_io_ext_int_to_encs(rb_encoding
*ext
, rb_encoding
*intern
, rb_encoding
**enc
, rb_encoding
**enc2
, int fmode
)
6569 int default_ext
= 0;
6572 ext
= rb_default_external_encoding();
6575 if (rb_is_ascii8bit_enc(ext
)) {
6576 /* If external is ASCII-8BIT, no transcoding */
6579 else if (intern
== NULL
) {
6580 intern
= rb_default_internal_encoding();
6582 if (intern
== NULL
|| intern
== (rb_encoding
*)Qnil
||
6583 (!(fmode
& FMODE_SETENC_BY_BOM
) && (intern
== ext
))) {
6584 /* No internal encoding => use external + no transcoding */
6585 *enc
= (default_ext
&& intern
!= ext
) ? NULL
: ext
;
6595 unsupported_encoding(const char *name
, rb_encoding
*enc
)
6597 rb_enc_warn(enc
, "Unsupported encoding %s ignored", name
);
6601 parse_mode_enc(const char *estr
, rb_encoding
*estr_enc
,
6602 rb_encoding
**enc_p
, rb_encoding
**enc2_p
, int *fmode_p
)
6605 char encname
[ENCODING_MAXNAMELEN
+1];
6607 int fmode
= fmode_p
? *fmode_p
: 0;
6608 rb_encoding
*ext_enc
, *int_enc
;
6611 /* parse estr as "enc" or "enc2:enc" or "enc:-" */
6613 p
= strrchr(estr
, ':');
6614 len
= p
? (p
++ - estr
) : (long)strlen(estr
);
6615 if ((fmode
& FMODE_SETENC_BY_BOM
) || io_encname_bom_p(estr
, len
)) {
6616 estr
+= bom_prefix_len
;
6617 len
-= bom_prefix_len
;
6618 if (!STRNCASECMP(estr
, utf_prefix
, utf_prefix_len
)) {
6619 fmode
|= FMODE_SETENC_BY_BOM
;
6622 rb_enc_warn(estr_enc
, "BOM with non-UTF encoding %s is nonsense", estr
);
6623 fmode
&= ~FMODE_SETENC_BY_BOM
;
6626 if (len
== 0 || len
> ENCODING_MAXNAMELEN
) {
6631 memcpy(encname
, estr
, len
);
6632 encname
[len
] = '\0';
6635 idx
= rb_enc_find_index(estr
);
6637 if (fmode_p
) *fmode_p
= fmode
;
6640 ext_enc
= rb_enc_from_index(idx
);
6643 unsupported_encoding(estr
, estr_enc
);
6649 if (*p
== '-' && *(p
+1) == '\0') {
6650 /* Special case - "-" => no transcoding */
6651 int_enc
= (rb_encoding
*)Qnil
;
6654 idx2
= rb_enc_find_index(p
);
6656 unsupported_encoding(p
, estr_enc
);
6657 else if (!(fmode
& FMODE_SETENC_BY_BOM
) && (idx2
== idx
)) {
6658 int_enc
= (rb_encoding
*)Qnil
;
6661 int_enc
= rb_enc_from_index(idx2
);
6665 rb_io_ext_int_to_encs(ext_enc
, int_enc
, enc_p
, enc2_p
, fmode
);
6669 rb_io_extract_encoding_option(VALUE opt
, rb_encoding
**enc_p
, rb_encoding
**enc2_p
, int *fmode_p
)
6671 VALUE encoding
=Qnil
, extenc
=Qundef
, intenc
=Qundef
, tmp
;
6673 rb_encoding
*extencoding
= NULL
;
6674 rb_encoding
*intencoding
= NULL
;
6678 v
= rb_hash_lookup2(opt
, sym_encoding
, Qnil
);
6679 if (v
!= Qnil
) encoding
= v
;
6680 v
= rb_hash_lookup2(opt
, sym_extenc
, Qundef
);
6681 if (v
!= Qnil
) extenc
= v
;
6682 v
= rb_hash_lookup2(opt
, sym_intenc
, Qundef
);
6683 if (!UNDEF_P(v
)) intenc
= v
;
6685 if ((!UNDEF_P(extenc
) || !UNDEF_P(intenc
)) && !NIL_P(encoding
)) {
6686 if (!NIL_P(ruby_verbose
)) {
6687 int idx
= rb_to_encoding_index(encoding
);
6688 if (idx
>= 0) encoding
= rb_enc_from_encoding(rb_enc_from_index(idx
));
6689 rb_warn("Ignoring encoding parameter '%"PRIsVALUE
"': %s_encoding is used",
6690 encoding
, UNDEF_P(extenc
) ? "internal" : "external");
6694 if (!UNDEF_P(extenc
) && !NIL_P(extenc
)) {
6695 extencoding
= rb_to_encoding(extenc
);
6697 if (!UNDEF_P(intenc
)) {
6698 if (NIL_P(intenc
)) {
6699 /* internal_encoding: nil => no transcoding */
6700 intencoding
= (rb_encoding
*)Qnil
;
6702 else if (!NIL_P(tmp
= rb_check_string_type(intenc
))) {
6703 char *p
= StringValueCStr(tmp
);
6705 if (*p
== '-' && *(p
+1) == '\0') {
6706 /* Special case - "-" => no transcoding */
6707 intencoding
= (rb_encoding
*)Qnil
;
6710 intencoding
= rb_to_encoding(intenc
);
6714 intencoding
= rb_to_encoding(intenc
);
6716 if (extencoding
== intencoding
) {
6717 intencoding
= (rb_encoding
*)Qnil
;
6720 if (!NIL_P(encoding
)) {
6722 if (!NIL_P(tmp
= rb_check_string_type(encoding
))) {
6723 parse_mode_enc(StringValueCStr(tmp
), rb_enc_get(tmp
),
6724 enc_p
, enc2_p
, fmode_p
);
6727 rb_io_ext_int_to_encs(rb_to_encoding(encoding
), NULL
, enc_p
, enc2_p
, 0);
6730 else if (!UNDEF_P(extenc
) || !UNDEF_P(intenc
)) {
6732 rb_io_ext_int_to_encs(extencoding
, intencoding
, enc_p
, enc2_p
, 0);
6738 validate_enc_binmode(int *fmode_p
, int ecflags
, rb_encoding
*enc
, rb_encoding
*enc2
)
6740 int fmode
= *fmode_p
;
6742 if ((fmode
& FMODE_READABLE
) &&
6744 !(fmode
& FMODE_BINMODE
) &&
6745 !rb_enc_asciicompat(enc
? enc
: rb_default_external_encoding()))
6746 rb_raise(rb_eArgError
, "ASCII incompatible encoding needs binmode");
6748 if ((fmode
& FMODE_BINMODE
) && (ecflags
& ECONV_NEWLINE_DECORATOR_MASK
)) {
6749 rb_raise(rb_eArgError
, "newline decorator with binary mode");
6751 if (!(fmode
& FMODE_BINMODE
) &&
6752 (DEFAULT_TEXTMODE
|| (ecflags
& ECONV_NEWLINE_DECORATOR_MASK
))) {
6753 fmode
|= FMODE_TEXTMODE
;
6756 #if !DEFAULT_TEXTMODE
6757 else if (!(ecflags
& ECONV_NEWLINE_DECORATOR_MASK
)) {
6758 fmode
&= ~FMODE_TEXTMODE
;
6765 extract_binmode(VALUE opthash
, int *fmode
)
6767 if (!NIL_P(opthash
)) {
6769 v
= rb_hash_aref(opthash
, sym_textmode
);
6771 if (*fmode
& FMODE_TEXTMODE
)
6772 rb_raise(rb_eArgError
, "textmode specified twice");
6773 if (*fmode
& FMODE_BINMODE
)
6774 rb_raise(rb_eArgError
, "both textmode and binmode specified");
6776 *fmode
|= FMODE_TEXTMODE
;
6778 v
= rb_hash_aref(opthash
, sym_binmode
);
6780 if (*fmode
& FMODE_BINMODE
)
6781 rb_raise(rb_eArgError
, "binmode specified twice");
6782 if (*fmode
& FMODE_TEXTMODE
)
6783 rb_raise(rb_eArgError
, "both textmode and binmode specified");
6785 *fmode
|= FMODE_BINMODE
;
6788 if ((*fmode
& FMODE_BINMODE
) && (*fmode
& FMODE_TEXTMODE
))
6789 rb_raise(rb_eArgError
, "both textmode and binmode specified");
6794 rb_io_extract_modeenc(VALUE
*vmode_p
, VALUE
*vperm_p
, VALUE opthash
,
6795 int *oflags_p
, int *fmode_p
, struct rb_io_encoding
*convconfig_p
)
6799 rb_encoding
*enc
, *enc2
;
6802 int has_enc
= 0, has_vmode
= 0;
6807 /* Set to defaults */
6808 rb_io_ext_int_to_encs(NULL
, NULL
, &enc
, &enc2
, 0);
6812 fmode
= FMODE_READABLE
;
6815 else if (!NIL_P(intmode
= rb_check_to_integer(vmode
, "to_int"))) {
6817 oflags
= NUM2INT(intmode
);
6818 fmode
= rb_io_oflags_fmode(oflags
);
6824 p
= StringValueCStr(vmode
);
6825 fmode
= rb_io_modestr_fmode(p
);
6826 oflags
= rb_io_fmode_oflags(fmode
);
6830 parse_mode_enc(p
+1, rb_enc_get(vmode
), &enc
, &enc2
, &fmode
);
6835 e
= (fmode
& FMODE_BINMODE
) ? rb_ascii8bit_encoding() : NULL
;
6836 rb_io_ext_int_to_encs(e
, NULL
, &enc
, &enc2
, fmode
);
6840 if (NIL_P(opthash
)) {
6841 ecflags
= (fmode
& FMODE_READABLE
) ?
6842 MODE_BTMODE(ECONV_DEFAULT_NEWLINE_DECORATOR
,
6843 0, ECONV_UNIVERSAL_NEWLINE_DECORATOR
) : 0;
6844 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
6845 ecflags
|= (fmode
& FMODE_WRITABLE
) ?
6846 MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
,
6847 0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
) : 0;
6849 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2
, ecflags
);
6851 if (fmode
& FMODE_BINMODE
) {
6856 rb_io_ext_int_to_encs(rb_ascii8bit_encoding(), NULL
, &enc
, &enc2
, fmode
);
6858 #if DEFAULT_TEXTMODE
6859 else if (NIL_P(vmode
)) {
6860 fmode
|= DEFAULT_TEXTMODE
;
6867 v
= rb_hash_aref(opthash
, sym_mode
);
6869 if (!NIL_P(vmode
)) {
6870 rb_raise(rb_eArgError
, "mode specified twice");
6877 v
= rb_hash_aref(opthash
, sym_flags
);
6880 oflags
|= NUM2INT(v
);
6881 vmode
= INT2NUM(oflags
);
6882 fmode
= rb_io_oflags_fmode(oflags
);
6884 extract_binmode(opthash
, &fmode
);
6885 if (fmode
& FMODE_BINMODE
) {
6890 rb_io_ext_int_to_encs(rb_ascii8bit_encoding(), NULL
, &enc
, &enc2
, fmode
);
6892 #if DEFAULT_TEXTMODE
6893 else if (NIL_P(vmode
)) {
6894 fmode
|= DEFAULT_TEXTMODE
;
6897 v
= rb_hash_aref(opthash
, sym_perm
);
6900 if (!NIL_P(*vperm_p
)) {
6901 rb_raise(rb_eArgError
, "perm specified twice");
6906 /* perm no use, just ignore */
6909 ecflags
= (fmode
& FMODE_READABLE
) ?
6910 MODE_BTMODE(ECONV_DEFAULT_NEWLINE_DECORATOR
,
6911 0, ECONV_UNIVERSAL_NEWLINE_DECORATOR
) : 0;
6912 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
6913 ecflags
|= (fmode
& FMODE_WRITABLE
) ?
6914 MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
,
6915 0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
) : 0;
6918 if (rb_io_extract_encoding_option(opthash
, &enc
, &enc2
, &fmode
)) {
6920 rb_raise(rb_eArgError
, "encoding specified twice");
6923 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2
, ecflags
);
6924 ecflags
= rb_econv_prepare_options(opthash
, &ecopts
, ecflags
);
6927 validate_enc_binmode(&fmode
, ecflags
, enc
, enc2
);
6933 convconfig_p
->enc
= enc
;
6934 convconfig_p
->enc2
= enc2
;
6935 convconfig_p
->ecflags
= ecflags
;
6936 convconfig_p
->ecopts
= ecopts
;
6939 struct sysopen_struct
{
6946 sysopen_func(void *ptr
)
6948 const struct sysopen_struct
*data
= ptr
;
6949 const char *fname
= RSTRING_PTR(data
->fname
);
6950 return (void *)(VALUE
)rb_cloexec_open(fname
, data
->oflags
, data
->perm
);
6954 rb_sysopen_internal(struct sysopen_struct
*data
)
6956 int fd
= IO_WITHOUT_GVL_INT(sysopen_func
, data
);
6958 rb_update_max_fd(fd
);
6963 rb_sysopen(VALUE fname
, int oflags
, mode_t perm
)
6966 struct sysopen_struct data
;
6968 data
.fname
= rb_str_encode_ospath(fname
);
6969 StringValueCStr(data
.fname
);
6970 data
.oflags
= oflags
;
6973 TRY_WITH_GC((fd
= rb_sysopen_internal(&data
)) >= 0) {
6974 rb_syserr_fail_path(first_errno
, fname
);
6979 static inline FILE *
6980 fdopen_internal(int fd
, const char *modestr
)
6987 file
= fdopen(fd
, modestr
);
6990 if (errno
== 0) errno
= EINVAL
;
6991 #elif defined(__sun)
6992 if (errno
== 0) errno
= EMFILE
;
6999 rb_fdopen(int fd
, const char *modestr
)
7003 TRY_WITH_GC((file
= fdopen_internal(fd
, modestr
)) != 0) {
7004 rb_syserr_fail(first_errno
, 0);
7007 /* xxx: should be _IONBF? A buffer in FILE may have trouble. */
7009 if (setvbuf(file
, NULL
, _IOFBF
, 0) != 0)
7010 rb_warn("setvbuf() can't be honoured (fd=%d)", fd
);
7016 io_check_tty(rb_io_t
*fptr
)
7018 int t
= isatty(fptr
->fd
);
7020 fptr
->mode
|= FMODE_TTY
|FMODE_DUPLEX
;
7024 static VALUE
rb_io_internal_encoding(VALUE
);
7025 static void io_encoding_set(rb_io_t
*, VALUE
, VALUE
, VALUE
);
7028 io_strip_bom(VALUE io
)
7030 VALUE b1
, b2
, b3
, b4
;
7033 GetOpenFile(io
, fptr
);
7034 if (!(fptr
->mode
& FMODE_READABLE
)) return 0;
7035 if (NIL_P(b1
= rb_io_getbyte(io
))) return 0;
7038 if (NIL_P(b2
= rb_io_getbyte(io
))) break;
7039 if (b2
== INT2FIX(0xBB) && !NIL_P(b3
= rb_io_getbyte(io
))) {
7040 if (b3
== INT2FIX(0xBF)) {
7041 return rb_utf8_encindex();
7043 rb_io_ungetbyte(io
, b3
);
7045 rb_io_ungetbyte(io
, b2
);
7049 if (NIL_P(b2
= rb_io_getbyte(io
))) break;
7050 if (b2
== INT2FIX(0xFF)) {
7051 return ENCINDEX_UTF_16BE
;
7053 rb_io_ungetbyte(io
, b2
);
7057 if (NIL_P(b2
= rb_io_getbyte(io
))) break;
7058 if (b2
== INT2FIX(0xFE)) {
7059 b3
= rb_io_getbyte(io
);
7060 if (b3
== INT2FIX(0) && !NIL_P(b4
= rb_io_getbyte(io
))) {
7061 if (b4
== INT2FIX(0)) {
7062 return ENCINDEX_UTF_32LE
;
7064 rb_io_ungetbyte(io
, b4
);
7066 rb_io_ungetbyte(io
, b3
);
7067 return ENCINDEX_UTF_16LE
;
7069 rb_io_ungetbyte(io
, b2
);
7073 if (NIL_P(b2
= rb_io_getbyte(io
))) break;
7074 if (b2
== INT2FIX(0) && !NIL_P(b3
= rb_io_getbyte(io
))) {
7075 if (b3
== INT2FIX(0xFE) && !NIL_P(b4
= rb_io_getbyte(io
))) {
7076 if (b4
== INT2FIX(0xFF)) {
7077 return ENCINDEX_UTF_32BE
;
7079 rb_io_ungetbyte(io
, b4
);
7081 rb_io_ungetbyte(io
, b3
);
7083 rb_io_ungetbyte(io
, b2
);
7086 rb_io_ungetbyte(io
, b1
);
7090 static rb_encoding
*
7091 io_set_encoding_by_bom(VALUE io
)
7093 int idx
= io_strip_bom(io
);
7095 rb_encoding
*extenc
= NULL
;
7097 GetOpenFile(io
, fptr
);
7099 extenc
= rb_enc_from_index(idx
);
7100 io_encoding_set(fptr
, rb_enc_from_encoding(extenc
),
7101 rb_io_internal_encoding(io
), Qnil
);
7104 fptr
->encs
.enc2
= NULL
;
7110 rb_file_open_generic(VALUE io
, VALUE filename
, int oflags
, int fmode
,
7111 const struct rb_io_encoding
*convconfig
, mode_t perm
)
7115 struct rb_io_encoding cc
;
7117 /* Set to default encodings */
7118 rb_io_ext_int_to_encs(NULL
, NULL
, &cc
.enc
, &cc
.enc2
, fmode
);
7123 validate_enc_binmode(&fmode
, convconfig
->ecflags
,
7124 convconfig
->enc
, convconfig
->enc2
);
7126 MakeOpenFile(io
, fptr
);
7128 fptr
->encs
= *convconfig
;
7129 pathv
= rb_str_new_frozen(filename
);
7131 if (!(oflags
& O_TMPFILE
)) {
7132 fptr
->pathv
= pathv
;
7135 fptr
->pathv
= pathv
;
7137 fptr
->fd
= rb_sysopen(pathv
, oflags
, perm
);
7139 if (fmode
& FMODE_SETENC_BY_BOM
) io_set_encoding_by_bom(io
);
7145 rb_file_open_internal(VALUE io
, VALUE filename
, const char *modestr
)
7147 int fmode
= rb_io_modestr_fmode(modestr
);
7148 const char *p
= strchr(modestr
, ':');
7149 struct rb_io_encoding convconfig
;
7152 parse_mode_enc(p
+1, rb_usascii_encoding(),
7153 &convconfig
.enc
, &convconfig
.enc2
, &fmode
);
7157 /* Set to default encodings */
7159 e
= (fmode
& FMODE_BINMODE
) ? rb_ascii8bit_encoding() : NULL
;
7160 rb_io_ext_int_to_encs(e
, NULL
, &convconfig
.enc
, &convconfig
.enc2
, fmode
);
7163 convconfig
.ecflags
= (fmode
& FMODE_READABLE
) ?
7164 MODE_BTMODE(ECONV_DEFAULT_NEWLINE_DECORATOR
,
7165 0, ECONV_UNIVERSAL_NEWLINE_DECORATOR
) : 0;
7166 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
7167 convconfig
.ecflags
|= (fmode
& FMODE_WRITABLE
) ?
7168 MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
,
7169 0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
) : 0;
7171 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(convconfig
.enc2
, convconfig
.ecflags
);
7172 convconfig
.ecopts
= Qnil
;
7174 return rb_file_open_generic(io
, filename
,
7175 rb_io_fmode_oflags(fmode
),
7182 rb_file_open_str(VALUE fname
, const char *modestr
)
7184 FilePathValue(fname
);
7185 return rb_file_open_internal(io_alloc(rb_cFile
), fname
, modestr
);
7189 rb_file_open(const char *fname
, const char *modestr
)
7191 return rb_file_open_internal(io_alloc(rb_cFile
), rb_str_new_cstr(fname
), modestr
);
7194 #if defined(__CYGWIN__) || !defined(HAVE_WORKING_FORK)
7195 static struct pipe_list
{
7197 struct pipe_list
*next
;
7201 pipe_add_fptr(rb_io_t
*fptr
)
7203 struct pipe_list
*list
;
7205 list
= ALLOC(struct pipe_list
);
7207 list
->next
= pipe_list
;
7212 pipe_del_fptr(rb_io_t
*fptr
)
7214 struct pipe_list
**prev
= &pipe_list
;
7215 struct pipe_list
*tmp
;
7217 while ((tmp
= *prev
) != 0) {
7218 if (tmp
->fptr
== fptr
) {
7227 #if defined (_WIN32) || defined(__CYGWIN__)
7231 struct pipe_list
*list
= pipe_list
;
7232 struct pipe_list
*tmp
;
7236 rb_io_fptr_finalize(list
->fptr
);
7243 pipe_finalize(rb_io_t
*fptr
, int noraise
)
7245 #if !defined(HAVE_WORKING_FORK) && !defined(_WIN32)
7247 if (fptr
->stdio_file
) {
7248 status
= pclose(fptr
->stdio_file
);
7251 fptr
->stdio_file
= 0;
7252 rb_last_status_set(status
, fptr
->pid
);
7254 fptr_finalize(fptr
, noraise
);
7256 pipe_del_fptr(fptr
);
7261 fptr_copy_finalizer(rb_io_t
*fptr
, const rb_io_t
*orig
)
7263 #if defined(__CYGWIN__) || !defined(HAVE_WORKING_FORK)
7264 void (*const old_finalize
)(struct rb_io
*,int) = fptr
->finalize
;
7266 if (old_finalize
== orig
->finalize
) return;
7269 fptr
->finalize
= orig
->finalize
;
7271 #if defined(__CYGWIN__) || !defined(HAVE_WORKING_FORK)
7272 if (old_finalize
!= pipe_finalize
) {
7273 struct pipe_list
*list
;
7274 for (list
= pipe_list
; list
; list
= list
->next
) {
7275 if (list
->fptr
== fptr
) break;
7277 if (!list
) pipe_add_fptr(fptr
);
7280 pipe_del_fptr(fptr
);
7286 rb_io_synchronized(rb_io_t
*fptr
)
7288 rb_io_check_initialized(fptr
);
7289 fptr
->mode
|= FMODE_SYNC
;
7293 rb_io_unbuffered(rb_io_t
*fptr
)
7295 rb_io_synchronized(fptr
);
7302 TRY_WITH_GC((ret
= rb_cloexec_pipe(pipes
)) >= 0);
7304 rb_update_max_fd(pipes
[0]);
7305 rb_update_max_fd(pipes
[1]);
7311 #define HAVE_SPAWNV 1
7312 #define spawnv(mode, cmd, args) rb_w32_uaspawn((mode), (cmd), (args))
7313 #define spawn(mode, cmd) rb_w32_uspawn((mode), (cmd), 0)
7316 #if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
7319 struct rb_execarg
*eargp
;
7326 #ifdef HAVE_WORKING_FORK
7327 # ifndef __EMSCRIPTEN__
7329 popen_redirect(struct popen_arg
*p
)
7331 if ((p
->modef
& FMODE_READABLE
) && (p
->modef
& FMODE_WRITABLE
)) {
7332 close(p
->write_pair
[1]);
7333 if (p
->write_pair
[0] != 0) {
7334 dup2(p
->write_pair
[0], 0);
7335 close(p
->write_pair
[0]);
7338 if (p
->pair
[1] != 1) {
7339 dup2(p
->pair
[1], 1);
7343 else if (p
->modef
& FMODE_READABLE
) {
7345 if (p
->pair
[1] != 1) {
7346 dup2(p
->pair
[1], 1);
7352 if (p
->pair
[0] != 0) {
7353 dup2(p
->pair
[0], 0);
7360 #if defined(__linux__)
7361 /* Linux /proc/self/status contains a line: "FDSize:\t<nnn>\n"
7362 * Since /proc may not be available, linux_get_maxfd is just a hint.
7363 * This function, linux_get_maxfd, must be async-signal-safe.
7364 * I.e. opendir() is not usable.
7366 * Note that memchr() and memcmp is *not* async-signal-safe in POSIX.
7367 * However they are easy to re-implement in async-signal-safe manner.
7368 * (Also note that there is missing/memcmp.c.)
7371 linux_get_maxfd(void)
7374 char buf
[4096], *p
, *np
, *e
;
7376 fd
= rb_cloexec_open("/proc/self/status", O_RDONLY
|O_NOCTTY
, 0);
7377 if (fd
< 0) return fd
;
7378 ss
= read(fd
, buf
, sizeof(buf
));
7379 if (ss
< 0) goto err
;
7382 while ((int)sizeof("FDSize:\t0\n")-1 <= e
-p
&&
7383 (np
= memchr(p
, '\n', e
-p
)) != NULL
) {
7384 if (memcmp(p
, "FDSize:", sizeof("FDSize:")-1) == 0) {
7386 p
+= sizeof("FDSize:")-1;
7388 fdsize
= (int)ruby_strtoul(p
, (char **)NULL
, 10);
7402 /* This function should be async-signal-safe. */
7404 rb_close_before_exec(int lowfd
, int maxhint
, VALUE noclose_fds
)
7406 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
7408 int max
= (int)max_file_descriptor
;
7410 /* F_MAXFD is available since NetBSD 2.0. */
7411 ret
= fcntl(0, F_MAXFD
); /* async-signal-safe */
7413 maxhint
= max
= ret
;
7414 # elif defined(__linux__)
7415 ret
= linux_get_maxfd();
7418 /* maxhint = max = ret; if (ret == -1) abort(); // test */
7422 for (fd
= lowfd
; fd
<= max
; fd
++) {
7423 if (!NIL_P(noclose_fds
) &&
7424 RTEST(rb_hash_lookup(noclose_fds
, INT2FIX(fd
)))) /* async-signal-safe */
7426 ret
= fcntl(fd
, F_GETFD
); /* async-signal-safe */
7427 if (ret
!= -1 && !(ret
& FD_CLOEXEC
)) {
7428 fcntl(fd
, F_SETFD
, ret
|FD_CLOEXEC
); /* async-signal-safe */
7430 # define CONTIGUOUS_CLOSED_FDS 20
7432 if (max
< fd
+ CONTIGUOUS_CLOSED_FDS
)
7433 max
= fd
+ CONTIGUOUS_CLOSED_FDS
;
7439 # ifndef __EMSCRIPTEN__
7441 popen_exec(void *pp
, char *errmsg
, size_t errmsg_len
)
7443 struct popen_arg
*p
= (struct popen_arg
*)pp
;
7445 return rb_exec_async_signal_safe(p
->eargp
, errmsg
, errmsg_len
);
7450 #if (defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)) && !defined __EMSCRIPTEN__
7452 rb_execarg_fixup_v(VALUE execarg_obj
)
7454 rb_execarg_parent_start(execarg_obj
);
7458 char *rb_execarg_commandline(const struct rb_execarg
*eargp
, VALUE
*prog
);
7461 #ifndef __EMSCRIPTEN__
7463 pipe_open(VALUE execarg_obj
, const char *modestr
, int fmode
,
7464 const struct rb_io_encoding
*convconfig
)
7466 struct rb_execarg
*eargp
= NIL_P(execarg_obj
) ? NULL
: rb_execarg_get(execarg_obj
);
7467 VALUE prog
= eargp
? (eargp
->use_shell
? eargp
->invoke
.sh
.shell_script
: eargp
->invoke
.cmd
.command_name
) : Qfalse
;
7471 rb_io_t
*write_fptr
;
7473 #if defined(HAVE_WORKING_FORK)
7475 char errmsg
[80] = { '\0' };
7477 #if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
7479 struct popen_arg arg
;
7482 #if defined(HAVE_SPAWNV)
7483 # if defined(HAVE_SPAWNVE)
7484 # define DO_SPAWN(cmd, args, envp) ((args) ? \
7485 spawnve(P_NOWAIT, (cmd), (args), (envp)) : \
7486 spawne(P_NOWAIT, (cmd), (envp)))
7488 # define DO_SPAWN(cmd, args, envp) ((args) ? \
7489 spawnv(P_NOWAIT, (cmd), (args)) : \
7490 spawn(P_NOWAIT, (cmd)))
7492 # if !defined(HAVE_WORKING_FORK)
7494 # if defined(HAVE_SPAWNVE)
7499 #if !defined(HAVE_WORKING_FORK)
7500 struct rb_execarg sarg
, *sargp
= &sarg
;
7505 #if !defined(HAVE_WORKING_FORK)
7506 const char *cmd
= 0;
7509 cmd
= StringValueCStr(prog
);
7512 #if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
7513 arg
.execarg_obj
= execarg_obj
;
7516 arg
.pair
[0] = arg
.pair
[1] = -1;
7517 arg
.write_pair
[0] = arg
.write_pair
[1] = -1;
7518 # if !defined(HAVE_WORKING_FORK)
7519 if (eargp
&& !eargp
->use_shell
) {
7520 args
= ARGVSTR2ARGV(eargp
->invoke
.cmd
.argv_str
);
7523 switch (fmode
& (FMODE_READABLE
|FMODE_WRITABLE
)) {
7524 case FMODE_READABLE
|FMODE_WRITABLE
:
7525 if (rb_pipe(arg
.write_pair
) < 0)
7526 rb_sys_fail_str(prog
);
7527 if (rb_pipe(arg
.pair
) < 0) {
7529 close(arg
.write_pair
[0]);
7530 close(arg
.write_pair
[1]);
7531 rb_syserr_fail_str(e
, prog
);
7534 rb_execarg_addopt(execarg_obj
, INT2FIX(0), INT2FIX(arg
.write_pair
[0]));
7535 rb_execarg_addopt(execarg_obj
, INT2FIX(1), INT2FIX(arg
.pair
[1]));
7538 case FMODE_READABLE
:
7539 if (rb_pipe(arg
.pair
) < 0)
7540 rb_sys_fail_str(prog
);
7542 rb_execarg_addopt(execarg_obj
, INT2FIX(1), INT2FIX(arg
.pair
[1]));
7544 case FMODE_WRITABLE
:
7545 if (rb_pipe(arg
.pair
) < 0)
7546 rb_sys_fail_str(prog
);
7548 rb_execarg_addopt(execarg_obj
, INT2FIX(0), INT2FIX(arg
.pair
[0]));
7551 rb_sys_fail_str(prog
);
7553 if (!NIL_P(execarg_obj
)) {
7554 rb_protect(rb_execarg_fixup_v
, execarg_obj
, &state
);
7556 if (0 <= arg
.write_pair
[0]) close(arg
.write_pair
[0]);
7557 if (0 <= arg
.write_pair
[1]) close(arg
.write_pair
[1]);
7558 if (0 <= arg
.pair
[0]) close(arg
.pair
[0]);
7559 if (0 <= arg
.pair
[1]) close(arg
.pair
[1]);
7560 rb_execarg_parent_end(execarg_obj
);
7564 # if defined(HAVE_WORKING_FORK)
7565 pid
= rb_fork_async_signal_safe(&status
, popen_exec
, &arg
, arg
.eargp
->redirect_fds
, errmsg
, sizeof(errmsg
));
7567 rb_execarg_run_options(eargp
, sargp
, NULL
, 0);
7568 # if defined(HAVE_SPAWNVE)
7569 if (eargp
->envp_str
) envp
= (char **)RSTRING_PTR(eargp
->envp_str
);
7571 while ((pid
= DO_SPAWN(cmd
, args
, envp
)) < 0) {
7573 switch (e
= errno
) {
7575 # if EWOULDBLOCK != EAGAIN
7584 rb_execarg_run_options(sargp
, NULL
, NULL
, 0);
7586 rb_execarg_parent_end(execarg_obj
);
7589 # if defined(HAVE_WORKING_FORK)
7590 pid
= rb_call_proc__fork();
7591 if (pid
== 0) { /* child */
7592 popen_redirect(&arg
);
7593 rb_io_synchronized(RFILE(orig_stdout
)->fptr
);
7594 rb_io_synchronized(RFILE(orig_stderr
)->fptr
);
7604 # if defined(HAVE_WORKING_FORK)
7609 if ((fmode
& (FMODE_READABLE
|FMODE_WRITABLE
)) == (FMODE_READABLE
|FMODE_WRITABLE
)) {
7610 close(arg
.write_pair
[0]);
7611 close(arg
.write_pair
[1]);
7613 # if defined(HAVE_WORKING_FORK)
7615 rb_syserr_fail(e
, errmsg
);
7617 rb_syserr_fail_str(e
, prog
);
7619 if ((fmode
& FMODE_READABLE
) && (fmode
& FMODE_WRITABLE
)) {
7622 close(arg
.write_pair
[0]);
7623 write_fd
= arg
.write_pair
[1];
7625 else if (fmode
& FMODE_READABLE
) {
7634 cmd
= rb_execarg_commandline(eargp
, &prog
);
7635 if (!NIL_P(execarg_obj
)) {
7636 rb_execarg_parent_start(execarg_obj
);
7637 rb_execarg_run_options(eargp
, sargp
, NULL
, 0);
7639 fp
= popen(cmd
, modestr
);
7642 rb_execarg_parent_end(execarg_obj
);
7643 rb_execarg_run_options(sargp
, NULL
, NULL
, 0);
7645 if (!fp
) rb_syserr_fail_path(e
, prog
);
7649 port
= io_alloc(rb_cIO
);
7650 MakeOpenFile(port
, fptr
);
7652 fptr
->stdio_file
= fp
;
7653 fptr
->mode
= fmode
| FMODE_SYNC
|FMODE_DUPLEX
;
7655 fptr
->encs
= *convconfig
;
7656 #if RUBY_CRLF_ENVIRONMENT
7657 if (fptr
->encs
.ecflags
& ECONV_DEFAULT_NEWLINE_DECORATOR
) {
7658 fptr
->encs
.ecflags
|= ECONV_UNIVERSAL_NEWLINE_DECORATOR
;
7663 if (NEED_NEWLINE_DECORATOR_ON_READ(fptr
)) {
7664 fptr
->encs
.ecflags
|= ECONV_UNIVERSAL_NEWLINE_DECORATOR
;
7666 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
7667 if (NEED_NEWLINE_DECORATOR_ON_WRITE(fptr
)) {
7668 fptr
->encs
.ecflags
|= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
;
7674 if (0 <= write_fd
) {
7675 write_port
= io_alloc(rb_cIO
);
7676 MakeOpenFile(write_port
, write_fptr
);
7677 write_fptr
->fd
= write_fd
;
7678 write_fptr
->mode
= (fmode
& ~FMODE_READABLE
)| FMODE_SYNC
|FMODE_DUPLEX
;
7679 fptr
->mode
&= ~FMODE_WRITABLE
;
7680 fptr
->tied_io_for_writing
= write_port
;
7681 rb_ivar_set(port
, rb_intern("@tied_io_for_writing"), write_port
);
7684 #if defined (__CYGWIN__) || !defined(HAVE_WORKING_FORK)
7685 fptr
->finalize
= pipe_finalize
;
7686 pipe_add_fptr(fptr
);
7692 pipe_open(VALUE execarg_obj
, const char *modestr
, int fmode
,
7693 const struct rb_io_encoding
*convconfig
)
7695 rb_raise(rb_eNotImpError
, "popen() is not available");
7700 is_popen_fork(VALUE prog
)
7702 if (RSTRING_LEN(prog
) == 1 && RSTRING_PTR(prog
)[0] == '-') {
7703 #if !defined(HAVE_WORKING_FORK)
7704 rb_raise(rb_eNotImpError
,
7705 "fork() function is unimplemented on this machine");
7714 pipe_open_s(VALUE prog
, const char *modestr
, int fmode
,
7715 const struct rb_io_encoding
*convconfig
)
7718 VALUE
*argv
= &prog
;
7719 VALUE execarg_obj
= Qnil
;
7721 if (!is_popen_fork(prog
))
7722 execarg_obj
= rb_execarg_new(argc
, argv
, TRUE
, FALSE
);
7723 return pipe_open(execarg_obj
, modestr
, fmode
, convconfig
);
7727 pipe_close(VALUE io
)
7729 rb_io_t
*fptr
= io_close_fptr(io
);
7731 fptr_waitpid(fptr
, rb_thread_to_be_killed(rb_thread_current()));
7736 static VALUE
popen_finish(VALUE port
, VALUE klass
);
7740 * IO.popen(env = {}, cmd, mode = 'r', **opts) -> io
7741 * IO.popen(env = {}, cmd, mode = 'r', **opts) {|io| ... } -> object
7743 * Executes the given command +cmd+ as a subprocess
7744 * whose $stdin and $stdout are connected to a new stream +io+.
7746 * This method has potential security vulnerabilities if called with untrusted input;
7747 * see {Command Injection}[rdoc-ref:command_injection.rdoc].
7749 * If no block is given, returns the new stream,
7750 * which depending on given +mode+ may be open for reading, writing, or both.
7751 * The stream should be explicitly closed (eventually) to avoid resource leaks.
7753 * If a block is given, the stream is passed to the block
7754 * (again, open for reading, writing, or both);
7755 * when the block exits, the stream is closed,
7756 * and the block's value is assigned to global variable <tt>$?</tt> and returned.
7758 * Optional argument +mode+ may be any valid \IO mode.
7759 * See {Access Modes}[rdoc-ref:File@Access+Modes].
7761 * Required argument +cmd+ determines which of the following occurs:
7763 * - The process forks.
7764 * - A specified program runs in a shell.
7765 * - A specified program runs with specified arguments.
7766 * - A specified program runs with specified arguments and a specified +argv0+.
7768 * Each of these is detailed below.
7770 * The optional hash argument +env+ specifies name/value pairs that are to be added
7771 * to the environment variables for the subprocess:
7773 * IO.popen({'FOO' => 'bar'}, 'ruby', 'r+') do |pipe|
7774 * pipe.puts 'puts ENV["FOO"]'
7779 * Optional keyword arguments +opts+ specify:
7781 * - {Open options}[rdoc-ref:IO@Open+Options].
7782 * - {Encoding options}[rdoc-ref:encodings.rdoc@Encoding+Options].
7783 * - Options for Kernel#spawn.
7785 * <b>Forked \Process</b>
7787 * When argument +cmd+ is the 1-character string <tt>'-'</tt>, causes the process to fork:
7788 * IO.popen('-') do |pipe|
7790 * $stderr.puts "In parent, child pid is #{pipe.pid}\n"
7792 * $stderr.puts "In child, pid is #{$$}\n"
7798 * In parent, child pid is 26253
7799 * In child, pid is 26253
7801 * Note that this is not supported on all platforms.
7803 * <b>Shell Subprocess</b>
7805 * When argument +cmd+ is a single string (but not <tt>'-'</tt>),
7806 * the program named +cmd+ is run as a shell command:
7808 * IO.popen('uname') do |pipe|
7818 * IO.popen('/bin/sh', 'r+') do |pipe|
7821 * $stderr.puts pipe.readlines.size
7828 * <b>Program Subprocess</b>
7830 * When argument +cmd+ is an array of strings,
7831 * the program named <tt>cmd[0]</tt> is run with all elements of +cmd+ as its arguments:
7833 * IO.popen(['du', '..', '.']) do |pipe|
7834 * $stderr.puts pipe.readlines.size
7841 * <b>Program Subprocess with <tt>argv0</tt></b>
7843 * When argument +cmd+ is an array whose first element is a 2-element string array
7844 * and whose remaining elements (if any) are strings:
7846 * - <tt>cmd[0][0]</tt> (the first string in the nested array) is the name of a program that is run.
7847 * - <tt>cmd[0][1]</tt> (the second string in the nested array) is set as the program's <tt>argv[0]</tt>.
7848 * - <tt>cmd[1..-1]</tt> (the strings in the outer array) are the program's arguments.
7850 * Example (sets <tt>$0</tt> to 'foo'):
7852 * IO.popen([['/bin/sh', 'foo'], '-c', 'echo $0']).read # => "foo\n"
7854 * <b>Some Special Examples</b>
7856 * # Set IO encoding.
7857 * IO.popen("nkf -e filename", :external_encoding=>"EUC-JP") {|nkf_io|
7858 * euc_jp_string = nkf_io.read
7861 * # Merge standard output and standard error using Kernel#spawn option. See Kernel#spawn.
7862 * IO.popen(["ls", "/", :err=>[:child, :out]]) do |io|
7863 * ls_result_with_error = io.read
7866 * # Use mixture of spawn options and IO options.
7867 * IO.popen(["ls", "/"], :err=>[:child, :out]) do |io|
7868 * ls_result_with_error = io.read
7871 * f = IO.popen("uname")
7874 * puts "Parent is #{Process.pid}"
7875 * IO.popen("date") {|f| puts f.gets }
7876 * IO.popen("-") {|f| $stderr.puts "#{Process.pid} is here, f is #{f.inspect}"}
7878 * IO.popen(%w"sed -e s|^|<foo>| -e s&$&;zot;&", "r+") {|f|
7879 * f.puts "bar"; f.close_write; puts f.gets
7882 * Output (from last section):
7886 * Thu Jan 15 22:41:19 JST 2009
7887 * 21346 is here, f is #<IO:fd 3>
7888 * 21352 is here, f is nil
7889 * #<Process::Status: pid 21352 exit 0>
7892 * Raises exceptions that IO.pipe and Kernel.spawn raise.
7897 rb_io_s_popen(int argc
, VALUE
*argv
, VALUE klass
)
7899 VALUE pname
, pmode
= Qnil
, opt
= Qnil
, env
= Qnil
;
7901 if (argc
> 1 && !NIL_P(opt
= rb_check_hash_type(argv
[argc
-1]))) --argc
;
7902 if (argc
> 1 && !NIL_P(env
= rb_check_hash_type(argv
[0]))) --argc
, ++argv
;
7911 int ex
= !NIL_P(opt
);
7912 rb_error_arity(argc
+ ex
, 1 + ex
, 2 + ex
);
7915 return popen_finish(rb_io_popen(pname
, pmode
, env
, opt
), klass
);
7919 rb_io_popen(VALUE pname
, VALUE pmode
, VALUE env
, VALUE opt
)
7921 const char *modestr
;
7922 VALUE tmp
, execarg_obj
= Qnil
;
7924 struct rb_io_encoding convconfig
;
7926 tmp
= rb_check_array_type(pname
);
7928 long len
= RARRAY_LEN(tmp
);
7929 #if SIZEOF_LONG > SIZEOF_INT
7930 if (len
> INT_MAX
) {
7931 rb_raise(rb_eArgError
, "too many arguments");
7934 execarg_obj
= rb_execarg_new((int)len
, RARRAY_CONST_PTR(tmp
), FALSE
, FALSE
);
7940 if (!is_popen_fork(pname
))
7941 execarg_obj
= rb_execarg_new(1, &pname
, TRUE
, FALSE
);
7943 if (!NIL_P(execarg_obj
)) {
7945 opt
= rb_execarg_extract_options(execarg_obj
, opt
);
7947 rb_execarg_setenv(execarg_obj
, env
);
7949 rb_io_extract_modeenc(&pmode
, 0, opt
, &oflags
, &fmode
, &convconfig
);
7950 modestr
= rb_io_oflags_modestr(oflags
);
7952 return pipe_open(execarg_obj
, modestr
, fmode
, &convconfig
);
7956 popen_finish(VALUE port
, VALUE klass
)
7960 if (rb_block_given_p()) {
7962 rb_io_flush(rb_ractor_stdout());
7963 rb_io_flush(rb_ractor_stderr());
7968 RBASIC_SET_CLASS(port
, klass
);
7969 if (rb_block_given_p()) {
7970 return rb_ensure(rb_yield
, port
, pipe_close
, port
);
7975 #if defined(HAVE_WORKING_FORK) && !defined(__EMSCRIPTEN__)
7976 struct popen_writer_arg
{
7978 struct popen_arg popen
;
7982 exec_popen_writer(void *arg
, char *errmsg
, size_t buflen
)
7984 struct popen_writer_arg
*pw
= arg
;
7985 pw
->popen
.modef
= FMODE_WRITABLE
;
7986 popen_redirect(&pw
->popen
);
7987 execv(pw
->argv
[0], pw
->argv
);
7988 strlcpy(errmsg
, strerror(errno
), buflen
);
7994 ruby_popen_writer(char *const *argv
, rb_pid_t
*pid
)
7996 #if (defined(HAVE_WORKING_FORK) && !defined(__EMSCRIPTEN__)) || defined(_WIN32)
7997 # ifdef HAVE_WORKING_FORK
7998 struct popen_writer_arg pw
;
7999 int *const write_pair
= pw
.popen
.pair
;
8004 int result
= rb_cloexec_pipe(write_pair
);
8007 # ifdef HAVE_WORKING_FORK
8010 char errmsg
[80] = {'\0'};
8011 *pid
= rb_fork_async_signal_safe(&status
, exec_popen_writer
, &pw
, Qnil
, errmsg
, sizeof(errmsg
));
8013 *pid
= rb_w32_uspawn_process(P_NOWAIT
, argv
[0], argv
, write_pair
[0], -1, -1, 0);
8014 const char *errmsg
= (*pid
< 0) ? strerror(errno
) : NULL
;
8016 close(write_pair
[0]);
8018 close(write_pair
[1]);
8019 fprintf(stderr
, "ruby_popen_writer(%s): %s\n", argv
[0], errmsg
);
8022 return fdopen(write_pair
[1], "w");
8030 rb_scan_open_args(int argc
, const VALUE
*argv
,
8031 VALUE
*fname_p
, int *oflags_p
, int *fmode_p
,
8032 struct rb_io_encoding
*convconfig_p
, mode_t
*perm_p
)
8034 VALUE opt
, fname
, vmode
, vperm
;
8038 argc
= rb_scan_args(argc
, argv
, "12:", &fname
, &vmode
, &vperm
, &opt
);
8039 FilePathValue(fname
);
8041 rb_io_extract_modeenc(&vmode
, &vperm
, opt
, &oflags
, &fmode
, convconfig_p
);
8043 perm
= NIL_P(vperm
) ? 0666 : NUM2MODET(vperm
);
8052 rb_open_file(int argc
, const VALUE
*argv
, VALUE io
)
8056 struct rb_io_encoding convconfig
;
8059 rb_scan_open_args(argc
, argv
, &fname
, &oflags
, &fmode
, &convconfig
, &perm
);
8060 rb_file_open_generic(io
, fname
, oflags
, fmode
, &convconfig
, perm
);
8066 * Document-method: File::open
8069 * File.open(path, mode = 'r', perm = 0666, **opts) -> file
8070 * File.open(path, mode = 'r', perm = 0666, **opts) {|f| ... } -> object
8072 * Creates a new File object, via File.new with the given arguments.
8074 * With no block given, returns the File object.
8076 * With a block given, calls the block with the File object
8077 * and returns the block's value.
8082 * Document-method: IO::open
8085 * IO.open(fd, mode = 'r', **opts) -> io
8086 * IO.open(fd, mode = 'r', **opts) {|io| ... } -> object
8088 * Creates a new \IO object, via IO.new with the given arguments.
8090 * With no block given, returns the \IO object.
8092 * With a block given, calls the block with the \IO object
8093 * and returns the block's value.
8098 rb_io_s_open(int argc
, VALUE
*argv
, VALUE klass
)
8100 VALUE io
= rb_class_new_instance_kw(argc
, argv
, klass
, RB_PASS_CALLED_KEYWORDS
);
8102 if (rb_block_given_p()) {
8103 return rb_ensure(rb_yield
, io
, io_close
, io
);
8111 * IO.sysopen(path, mode = 'r', perm = 0666) -> integer
8113 * Opens the file at the given path with the given mode and permissions;
8114 * returns the integer file descriptor.
8116 * If the file is to be readable, it must exist;
8117 * if the file is to be writable and does not exist,
8118 * it is created with the given permissions:
8120 * File.write('t.tmp', '') # => 0
8121 * IO.sysopen('t.tmp') # => 8
8122 * IO.sysopen('t.tmp', 'w') # => 9
8128 rb_io_s_sysopen(int argc
, VALUE
*argv
, VALUE _
)
8130 VALUE fname
, vmode
, vperm
;
8135 rb_scan_args(argc
, argv
, "12", &fname
, &vmode
, &vperm
);
8136 FilePathValue(fname
);
8140 else if (!NIL_P(intmode
= rb_check_to_integer(vmode
, "to_int")))
8141 oflags
= NUM2INT(intmode
);
8144 oflags
= rb_io_modestr_oflags(StringValueCStr(vmode
));
8146 if (NIL_P(vperm
)) perm
= 0666;
8147 else perm
= NUM2MODET(vperm
);
8149 RB_GC_GUARD(fname
) = rb_str_new4(fname
);
8150 fd
= rb_sysopen(fname
, oflags
, perm
);
8155 check_pipe_command(VALUE filename_or_command
)
8157 char *s
= RSTRING_PTR(filename_or_command
);
8158 long l
= RSTRING_LEN(filename_or_command
);
8162 if (rb_enc_ascget(s
, e
, &chlen
, rb_enc_get(filename_or_command
)) == '|') {
8163 VALUE cmd
= rb_str_new(s
+chlen
, l
-chlen
);
8171 * open(path, mode = 'r', perm = 0666, **opts) -> io or nil
8172 * open(path, mode = 'r', perm = 0666, **opts) {|io| ... } -> obj
8174 * Creates an IO object connected to the given file.
8176 * This method has potential security vulnerabilities if called with untrusted input;
8177 * see {Command Injection}[rdoc-ref:command_injection.rdoc].
8179 * With no block given, file stream is returned:
8181 * open('t.txt') # => #<File:t.txt>
8183 * With a block given, calls the block with the open file stream,
8184 * then closes the stream:
8186 * open('t.txt') {|f| p f } # => #<File:t.txt (closed)>
8192 * See File.open for details.
8197 rb_f_open(int argc
, VALUE
*argv
, VALUE _
)
8200 int redirect
= FALSE
;
8203 CONST_ID(to_open
, "to_open");
8204 if (rb_respond_to(argv
[0], to_open
)) {
8208 VALUE tmp
= argv
[0];
8214 VALUE cmd
= check_pipe_command(tmp
);
8216 // TODO: when removed in 4.0, update command_injection.rdoc
8217 rb_warn_deprecated_to_remove_at(4.0, "Calling Kernel#open with a leading '|'", "IO.popen");
8219 return rb_io_s_popen(argc
, argv
, rb_cIO
);
8225 VALUE io
= rb_funcallv_kw(argv
[0], to_open
, argc
-1, argv
+1, RB_PASS_CALLED_KEYWORDS
);
8227 if (rb_block_given_p()) {
8228 return rb_ensure(rb_yield
, io
, io_close
, io
);
8232 return rb_io_s_open(argc
, argv
, rb_cFile
);
8235 static VALUE
rb_io_open_generic(VALUE
, VALUE
, int, int, const struct rb_io_encoding
*, mode_t
);
8238 rb_io_open(VALUE io
, VALUE filename
, VALUE vmode
, VALUE vperm
, VALUE opt
)
8241 struct rb_io_encoding convconfig
;
8244 rb_io_extract_modeenc(&vmode
, &vperm
, opt
, &oflags
, &fmode
, &convconfig
);
8245 perm
= NIL_P(vperm
) ? 0666 : NUM2MODET(vperm
);
8246 return rb_io_open_generic(io
, filename
, oflags
, fmode
, &convconfig
, perm
);
8250 rb_io_open_generic(VALUE klass
, VALUE filename
, int oflags
, int fmode
,
8251 const struct rb_io_encoding
*convconfig
, mode_t perm
)
8254 if (klass
== rb_cIO
&& !NIL_P(cmd
= check_pipe_command(filename
))) {
8255 // TODO: when removed in 4.0, update command_injection.rdoc
8256 rb_warn_deprecated_to_remove_at(4.0, "IO process creation with a leading '|'", "IO.popen");
8257 return pipe_open_s(cmd
, rb_io_oflags_modestr(oflags
), fmode
, convconfig
);
8260 return rb_file_open_generic(io_alloc(klass
), filename
,
8261 oflags
, fmode
, convconfig
, perm
);
8266 io_reopen(VALUE io
, VALUE nfile
)
8268 rb_io_t
*fptr
, *orig
;
8272 nfile
= rb_io_get_io(nfile
);
8273 GetOpenFile(io
, fptr
);
8274 GetOpenFile(nfile
, orig
);
8276 if (fptr
== orig
) return io
;
8277 if (RUBY_IO_EXTERNAL_P(fptr
)) {
8278 if ((fptr
->stdio_file
== stdin
&& !(orig
->mode
& FMODE_READABLE
)) ||
8279 (fptr
->stdio_file
== stdout
&& !(orig
->mode
& FMODE_WRITABLE
)) ||
8280 (fptr
->stdio_file
== stderr
&& !(orig
->mode
& FMODE_WRITABLE
))) {
8281 rb_raise(rb_eArgError
,
8282 "%s can't change access mode from \"%s\" to \"%s\"",
8283 PREP_STDIO_NAME(fptr
), rb_io_fmode_modestr(fptr
->mode
),
8284 rb_io_fmode_modestr(orig
->mode
));
8287 if (fptr
->mode
& FMODE_WRITABLE
) {
8288 if (io_fflush(fptr
) < 0)
8289 rb_sys_fail_on_write(fptr
);
8292 flush_before_seek(fptr
);
8294 if (orig
->mode
& FMODE_READABLE
) {
8295 pos
= io_tell(orig
);
8297 if (orig
->mode
& FMODE_WRITABLE
) {
8298 if (io_fflush(orig
) < 0)
8299 rb_sys_fail_on_write(fptr
);
8302 /* copy rb_io_t structure */
8303 fptr
->mode
= orig
->mode
| (fptr
->mode
& FMODE_EXTERNAL
);
8304 fptr
->pid
= orig
->pid
;
8305 fptr
->lineno
= orig
->lineno
;
8306 if (RTEST(orig
->pathv
)) fptr
->pathv
= orig
->pathv
;
8307 else if (!RUBY_IO_EXTERNAL_P(fptr
)) fptr
->pathv
= Qnil
;
8308 fptr_copy_finalizer(fptr
, orig
);
8313 if (RUBY_IO_EXTERNAL_P(fptr
) || fd
<= 2 || !fptr
->stdio_file
) {
8314 /* need to keep FILE objects of stdin, stdout and stderr */
8315 if (rb_cloexec_dup2(fd2
, fd
) < 0)
8316 rb_sys_fail_path(orig
->pathv
);
8317 rb_update_max_fd(fd
);
8320 fclose(fptr
->stdio_file
);
8321 fptr
->stdio_file
= 0;
8323 if (rb_cloexec_dup2(fd2
, fd
) < 0)
8324 rb_sys_fail_path(orig
->pathv
);
8325 rb_update_max_fd(fd
);
8328 rb_thread_fd_close(fd
);
8329 if ((orig
->mode
& FMODE_READABLE
) && pos
>= 0) {
8330 if (io_seek(fptr
, pos
, SEEK_SET
) < 0 && errno
) {
8331 rb_sys_fail_path(fptr
->pathv
);
8333 if (io_seek(orig
, pos
, SEEK_SET
) < 0 && errno
) {
8334 rb_sys_fail_path(orig
->pathv
);
8339 if (fptr
->mode
& FMODE_BINMODE
) {
8343 RBASIC_SET_CLASS(io
, rb_obj_class(nfile
));
8348 int rb_freopen(VALUE fname
, const char *mode
, FILE *fp
);
8351 rb_freopen(VALUE fname
, const char *mode
, FILE *fp
)
8353 if (!freopen(RSTRING_PTR(fname
), mode
, fp
)) {
8363 * reopen(other_io) -> self
8364 * reopen(path, mode = 'r', **opts) -> self
8366 * Reassociates the stream with another stream,
8367 * which may be of a different class.
8368 * This method may be used to redirect an existing stream
8369 * to a new destination.
8371 * With argument +other_io+ given, reassociates with that stream:
8373 * # Redirect $stdin from a file.
8374 * f = File.open('t.txt')
8378 * # Redirect $stdout to a file.
8379 * f = File.open('t.tmp', 'w')
8383 * With argument +path+ given, reassociates with a new stream to that file path:
8385 * $stdin.reopen('t.txt')
8386 * $stdout.reopen('t.tmp', 'w')
8388 * Optional keyword arguments +opts+ specify:
8390 * - {Open Options}[rdoc-ref:IO@Open+Options].
8391 * - {Encoding options}[rdoc-ref:encodings.rdoc@Encoding+Options].
8396 rb_io_reopen(int argc
, VALUE
*argv
, VALUE file
)
8398 VALUE fname
, nmode
, opt
;
8402 if (rb_scan_args(argc
, argv
, "11:", &fname
, &nmode
, &opt
) == 1) {
8403 VALUE tmp
= rb_io_check_io(fname
);
8405 return io_reopen(file
, tmp
);
8409 FilePathValue(fname
);
8410 rb_io_taint_check(file
);
8411 fptr
= RFILE(file
)->fptr
;
8413 fptr
= RFILE(file
)->fptr
= ZALLOC(rb_io_t
);
8416 if (!NIL_P(nmode
) || !NIL_P(opt
)) {
8418 struct rb_io_encoding convconfig
;
8420 rb_io_extract_modeenc(&nmode
, 0, opt
, &oflags
, &fmode
, &convconfig
);
8421 if (RUBY_IO_EXTERNAL_P(fptr
) &&
8422 ((fptr
->mode
& FMODE_READWRITE
) & (fmode
& FMODE_READWRITE
)) !=
8423 (fptr
->mode
& FMODE_READWRITE
)) {
8424 rb_raise(rb_eArgError
,
8425 "%s can't change access mode from \"%s\" to \"%s\"",
8426 PREP_STDIO_NAME(fptr
), rb_io_fmode_modestr(fptr
->mode
),
8427 rb_io_fmode_modestr(fmode
));
8430 fptr
->encs
= convconfig
;
8433 oflags
= rb_io_fmode_oflags(fptr
->mode
);
8436 fptr
->pathv
= fname
;
8438 fptr
->fd
= rb_sysopen(fptr
->pathv
, oflags
, 0666);
8439 fptr
->stdio_file
= 0;
8443 if (fptr
->mode
& FMODE_WRITABLE
) {
8444 if (io_fflush(fptr
) < 0)
8445 rb_sys_fail_on_write(fptr
);
8447 fptr
->rbuf
.off
= fptr
->rbuf
.len
= 0;
8449 if (fptr
->stdio_file
) {
8450 int e
= rb_freopen(rb_str_encode_ospath(fptr
->pathv
),
8451 rb_io_oflags_modestr(oflags
),
8453 if (e
) rb_syserr_fail_path(e
, fptr
->pathv
);
8454 fptr
->fd
= fileno(fptr
->stdio_file
);
8455 rb_fd_fix_cloexec(fptr
->fd
);
8457 if (setvbuf(fptr
->stdio_file
, NULL
, _IOFBF
, 0) != 0)
8458 rb_warn("setvbuf() can't be honoured for %"PRIsVALUE
, fptr
->pathv
);
8460 if (fptr
->stdio_file
== stderr
) {
8461 if (setvbuf(fptr
->stdio_file
, NULL
, _IONBF
, BUFSIZ
) != 0)
8462 rb_warn("setvbuf() can't be honoured for %"PRIsVALUE
, fptr
->pathv
);
8464 else if (fptr
->stdio_file
== stdout
&& isatty(fptr
->fd
)) {
8465 if (setvbuf(fptr
->stdio_file
, NULL
, _IOLBF
, BUFSIZ
) != 0)
8466 rb_warn("setvbuf() can't be honoured for %"PRIsVALUE
, fptr
->pathv
);
8470 int tmpfd
= rb_sysopen(fptr
->pathv
, oflags
, 0666);
8472 if (rb_cloexec_dup2(tmpfd
, fptr
->fd
) < 0)
8476 rb_syserr_fail_path(err
, fptr
->pathv
);
8485 rb_io_init_copy(VALUE dest
, VALUE io
)
8487 rb_io_t
*fptr
, *orig
;
8492 io
= rb_io_get_io(io
);
8493 if (!OBJ_INIT_COPY(dest
, io
)) return dest
;
8494 GetOpenFile(io
, orig
);
8495 MakeOpenFile(dest
, fptr
);
8499 /* copy rb_io_t structure */
8500 fptr
->mode
= orig
->mode
& ~FMODE_EXTERNAL
;
8501 fptr
->encs
= orig
->encs
;
8502 fptr
->pid
= orig
->pid
;
8503 fptr
->lineno
= orig
->lineno
;
8504 fptr
->timeout
= orig
->timeout
;
8505 if (!NIL_P(orig
->pathv
)) fptr
->pathv
= orig
->pathv
;
8506 fptr_copy_finalizer(fptr
, orig
);
8508 fd
= ruby_dup(orig
->fd
);
8510 pos
= io_tell(orig
);
8512 io_seek(fptr
, pos
, SEEK_SET
);
8513 if (fptr
->mode
& FMODE_BINMODE
) {
8514 rb_io_binmode(dest
);
8517 write_io
= GetWriteIO(io
);
8518 if (io
!= write_io
) {
8519 write_io
= rb_obj_dup(write_io
);
8520 fptr
->tied_io_for_writing
= write_io
;
8521 rb_ivar_set(dest
, rb_intern("@tied_io_for_writing"), write_io
);
8529 * printf(format_string, *objects) -> nil
8531 * Formats and writes +objects+ to the stream.
8533 * For details on +format_string+, see
8534 * {Format Specifications}[rdoc-ref:format_specifications.rdoc].
8539 rb_io_printf(int argc
, const VALUE
*argv
, VALUE out
)
8541 rb_io_write(out
, rb_f_sprintf(argc
, argv
));
8547 * printf(format_string, *objects) -> nil
8548 * printf(io, format_string, *objects) -> nil
8552 * io.write(sprintf(format_string, *objects))
8554 * For details on +format_string+, see
8555 * {Format Specifications}[rdoc-ref:format_specifications.rdoc].
8557 * With the single argument +format_string+, formats +objects+ into the string,
8558 * then writes the formatted string to $stdout:
8560 * printf('%4.4d %10s %2.2f', 24, 24, 24.0)
8562 * Output (on $stdout):
8566 * With arguments +io+ and +format_string+, formats +objects+ into the string,
8567 * then writes the formatted string to +io+:
8569 * printf($stderr, '%4.4d %10s %2.2f', 24, 24, 24.0)
8571 * Output (on $stderr):
8573 * 0024 24 24.00# => nil
8575 * With no arguments, does nothing.
8580 rb_f_printf(int argc
, VALUE
*argv
, VALUE _
)
8584 if (argc
== 0) return Qnil
;
8585 if (RB_TYPE_P(argv
[0], T_STRING
)) {
8586 out
= rb_ractor_stdout();
8593 rb_io_write(out
, rb_f_sprintf(argc
, argv
));
8599 deprecated_str_setter(VALUE val
, ID id
, VALUE
*var
)
8601 rb_str_setter(val
, id
, &val
);
8603 rb_warn_deprecated("'%s'", NULL
, rb_id2name(id
));
8610 * print(*objects) -> nil
8612 * Writes the given objects to the stream; returns +nil+.
8613 * Appends the output record separator <tt>$OUTPUT_RECORD_SEPARATOR</tt>
8614 * (<tt>$\\</tt>), if it is not +nil+.
8615 * See {Line IO}[rdoc-ref:IO@Line+IO].
8617 * With argument +objects+ given, for each object:
8619 * - Converts via its method +to_s+ if not a string.
8620 * - Writes to the stream.
8621 * - If not the last object, writes the output field separator
8622 * <tt>$OUTPUT_FIELD_SEPARATOR</tt> (<tt>$,</tt>) if it is not +nil+.
8624 * With default separators:
8626 * f = File.open('t.tmp', 'w+')
8627 * objects = [0, 0.0, Rational(0, 1), Complex(0, 0), :zero, 'zero']
8628 * p $OUTPUT_RECORD_SEPARATOR
8629 * p $OUTPUT_FIELD_SEPARATOR
8639 * "00.00/10+0izerozero"
8641 * With specified separators:
8652 * "0,0.0,0/1,0+0i,zero,zero\n"
8654 * With no argument given, writes the content of <tt>$_</tt>
8655 * (which is usually the most recent user input):
8657 * f = File.open('t.tmp', 'w+')
8658 * gets # Sets $_ to the most recent user input.
8665 rb_io_print(int argc
, const VALUE
*argv
, VALUE out
)
8670 /* if no argument given, print `$_' */
8673 line
= rb_lastline_get();
8676 if (argc
> 1 && !NIL_P(rb_output_fs
)) {
8677 rb_category_warn(RB_WARN_CATEGORY_DEPRECATED
, "$, is set to non-nil value");
8679 for (i
=0; i
<argc
; i
++) {
8680 if (!NIL_P(rb_output_fs
) && i
>0) {
8681 rb_io_write(out
, rb_output_fs
);
8683 rb_io_write(out
, argv
[i
]);
8685 if (argc
> 0 && !NIL_P(rb_output_rs
)) {
8686 rb_io_write(out
, rb_output_rs
);
8694 * print(*objects) -> nil
8696 * Equivalent to <tt>$stdout.print(*objects)</tt>,
8697 * this method is the straightforward way to write to <tt>$stdout</tt>.
8699 * Writes the given objects to <tt>$stdout</tt>; returns +nil+.
8700 * Appends the output record separator <tt>$OUTPUT_RECORD_SEPARATOR</tt>
8701 * <tt>$\\</tt>), if it is not +nil+.
8703 * With argument +objects+ given, for each object:
8705 * - Converts via its method +to_s+ if not a string.
8706 * - Writes to <tt>stdout</tt>.
8707 * - If not the last object, writes the output field separator
8708 * <tt>$OUTPUT_FIELD_SEPARATOR</tt> (<tt>$,</tt> if it is not +nil+.
8710 * With default separators:
8712 * objects = [0, 0.0, Rational(0, 1), Complex(0, 0), :zero, 'zero']
8713 * $OUTPUT_RECORD_SEPARATOR
8714 * $OUTPUT_FIELD_SEPARATOR
8721 * 00.00/10+0izerozero
8723 * With specified separators:
8725 * $OUTPUT_RECORD_SEPARATOR = "\n"
8726 * $OUTPUT_FIELD_SEPARATOR = ','
8731 * 0,0.0,0/1,0+0i,zero,zero
8733 * With no argument given, writes the content of <tt>$_</tt>
8734 * (which is usually the most recent user input):
8736 * gets # Sets $_ to the most recent user input.
8737 * print # Prints $_.
8742 rb_f_print(int argc
, const VALUE
*argv
, VALUE _
)
8744 rb_io_print(argc
, argv
, rb_ractor_stdout());
8750 * putc(object) -> object
8752 * Writes a character to the stream.
8753 * See {Character IO}[rdoc-ref:IO@Character+IO].
8755 * If +object+ is numeric, converts to integer if necessary,
8756 * then writes the character whose code is the
8757 * least significant byte;
8758 * if +object+ is a string, writes the first character:
8770 rb_io_putc(VALUE io
, VALUE ch
)
8773 if (RB_TYPE_P(ch
, T_STRING
)) {
8774 str
= rb_str_substr(ch
, 0, 1);
8777 char c
= NUM2CHR(ch
);
8778 str
= rb_str_new(&c
, 1);
8780 rb_io_write(io
, str
);
8784 #define forward(obj, id, argc, argv) \
8785 rb_funcallv_kw(obj, id, argc, argv, RB_PASS_CALLED_KEYWORDS)
8786 #define forward_public(obj, id, argc, argv) \
8787 rb_funcallv_public_kw(obj, id, argc, argv, RB_PASS_CALLED_KEYWORDS)
8788 #define forward_current(id, argc, argv) \
8789 forward_public(ARGF.current_file, id, argc, argv)
8799 * See IO#putc for important information regarding multi-byte characters.
8804 rb_f_putc(VALUE recv
, VALUE ch
)
8806 VALUE r_stdout
= rb_ractor_stdout();
8807 if (recv
== r_stdout
) {
8808 return rb_io_putc(recv
, ch
);
8810 return forward(r_stdout
, rb_intern("putc"), 1, &ch
);
8815 rb_str_end_with_asciichar(VALUE str
, int c
)
8817 long len
= RSTRING_LEN(str
);
8818 const char *ptr
= RSTRING_PTR(str
);
8819 rb_encoding
*enc
= rb_enc_from_index(ENCODING_GET(str
));
8822 if (len
== 0) return 0;
8823 if ((n
= rb_enc_mbminlen(enc
)) == 1) {
8824 return ptr
[len
- 1] == c
;
8826 return rb_enc_ascget(ptr
+ ((len
- 1) / n
) * n
, ptr
+ len
, &n
, enc
) == c
;
8830 io_puts_ary(VALUE ary
, VALUE out
, int recur
)
8836 tmp
= rb_str_new2("[...]");
8837 rb_io_puts(1, &tmp
, out
);
8840 ary
= rb_check_array_type(ary
);
8841 if (NIL_P(ary
)) return Qfalse
;
8842 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
8843 tmp
= RARRAY_AREF(ary
, i
);
8844 rb_io_puts(1, &tmp
, out
);
8851 * puts(*objects) -> nil
8853 * Writes the given +objects+ to the stream, which must be open for writing;
8855 * Writes a newline after each that does not already end with a newline sequence.
8856 * If called without arguments, writes a newline.
8857 * See {Line IO}[rdoc-ref:IO@Line+IO].
8859 * Note that each added newline is the character <tt>"\n"<//tt>,
8860 * not the output record separator (<tt>$\\</tt>).
8862 * Treatment for each object:
8864 * - String: writes the string.
8865 * - Neither string nor array: writes <tt>object.to_s</tt>.
8866 * - Array: writes each element of the array; arrays may be nested.
8868 * To keep these examples brief, we define this helper method:
8870 * def show(*objects)
8871 * # Puts objects to file.
8872 * f = File.new('t.tmp', 'w+')
8874 * # Return file content.
8880 * # Strings without newlines.
8881 * show('foo', 'bar', 'baz') # => "foo\nbar\nbaz\n"
8882 * # Strings, some with newlines.
8883 * show("foo\n", 'bar', "baz\n") # => "foo\nbar\nbaz\n"
8885 * # Neither strings nor arrays:
8886 * show(0, 0.0, Rational(0, 1), Complex(9, 0), :zero)
8887 * # => "0\n0.0\n0/1\n9+0i\nzero\n"
8889 * # Array of strings.
8890 * show(['foo', "bar\n", 'baz']) # => "foo\nbar\nbaz\n"
8892 * show([[[0, 1], 2, 3], 4, 5]) # => "0\n1\n2\n3\n4\n5\n"
8897 rb_io_puts(int argc
, const VALUE
*argv
, VALUE out
)
8899 VALUE line
, args
[2];
8901 /* if no argument given, print newline. */
8903 rb_io_write(out
, rb_default_rs
);
8906 for (int i
= 0; i
< argc
; i
++) {
8907 // Convert the argument to a string:
8908 if (RB_TYPE_P(argv
[i
], T_STRING
)) {
8911 else if (rb_exec_recursive(io_puts_ary
, argv
[i
], out
)) {
8915 line
= rb_obj_as_string(argv
[i
]);
8920 if (RSTRING_LEN(line
) == 0) {
8921 args
[n
++] = rb_default_rs
;
8925 if (!rb_str_end_with_asciichar(line
, '\n')) {
8926 args
[n
++] = rb_default_rs
;
8930 rb_io_writev(out
, n
, args
);
8938 * puts(*objects) -> nil
8942 * $stdout.puts(objects)
8946 rb_f_puts(int argc
, VALUE
*argv
, VALUE recv
)
8948 VALUE r_stdout
= rb_ractor_stdout();
8949 if (recv
== r_stdout
) {
8950 return rb_io_puts(argc
, argv
, recv
);
8952 return forward(r_stdout
, rb_intern("puts"), argc
, argv
);
8956 rb_p_write(VALUE str
)
8960 args
[1] = rb_default_rs
;
8961 VALUE r_stdout
= rb_ractor_stdout();
8962 if (RB_TYPE_P(r_stdout
, T_FILE
) &&
8963 rb_method_basic_definition_p(CLASS_OF(r_stdout
), id_write
)) {
8964 io_writev(2, args
, r_stdout
);
8967 rb_io_writev(r_stdout
, 2, args
);
8973 rb_p(VALUE obj
) /* for debug print within C code */
8975 rb_p_write(rb_obj_as_string(rb_inspect(obj
)));
8979 rb_p_result(int argc
, const VALUE
*argv
)
8986 else if (argc
> 1) {
8987 ret
= rb_ary_new4(argc
, argv
);
8989 VALUE r_stdout
= rb_ractor_stdout();
8990 if (RB_TYPE_P(r_stdout
, T_FILE
)) {
8991 rb_uninterruptible(rb_io_flush
, r_stdout
);
8999 * p(*objects) -> array of objects
9002 * For each object +obj+, executes:
9004 * $stdout.write(obj.inspect, "\n")
9006 * With one object given, returns the object;
9007 * with multiple objects given, returns an array containing the objects;
9008 * with no object given, returns +nil+.
9012 * r = Range.new(0, 4)
9014 * p [r, r, r] # => [0..4, 0..4, 0..4]
9020 * [0..4, 0..4, 0..4]
9022 * Kernel#p is designed for debugging purposes.
9023 * Ruby implementations may define Kernel#p to be uninterruptible
9024 * in whole or in part.
9025 * On CRuby, Kernel#p's writing of data is uninterruptible.
9029 rb_f_p(int argc
, VALUE
*argv
, VALUE self
)
9032 for (i
=0; i
<argc
; i
++) {
9033 VALUE inspected
= rb_obj_as_string(rb_inspect(argv
[i
]));
9034 rb_uninterruptible(rb_p_write
, inspected
);
9036 return rb_p_result(argc
, argv
);
9041 * display(port = $>) -> nil
9043 * Writes +self+ on the given port:
9047 * [ 4, 5, 6 ].display
9057 rb_obj_display(int argc
, VALUE
*argv
, VALUE self
)
9061 out
= (!rb_check_arity(argc
, 0, 1) ? rb_ractor_stdout() : argv
[0]);
9062 rb_io_write(out
, self
);
9068 rb_stderr_to_original_p(VALUE err
)
9070 return (err
== orig_stderr
|| RFILE(orig_stderr
)->fptr
->fd
< 0);
9074 rb_write_error2(const char *mesg
, long len
)
9076 VALUE out
= rb_ractor_stderr();
9077 if (rb_stderr_to_original_p(out
)) {
9079 if (isatty(fileno(stderr
))) {
9080 if (rb_w32_write_console(rb_str_new(mesg
, len
), fileno(stderr
)) > 0) return;
9083 if (fwrite(mesg
, sizeof(char), (size_t)len
, stderr
) < (size_t)len
) {
9084 /* failed to write to stderr, what can we do? */
9089 rb_io_write(out
, rb_str_new(mesg
, len
));
9094 rb_write_error(const char *mesg
)
9096 rb_write_error2(mesg
, strlen(mesg
));
9100 rb_write_error_str(VALUE mesg
)
9102 VALUE out
= rb_ractor_stderr();
9103 /* a stopgap measure for the time being */
9104 if (rb_stderr_to_original_p(out
)) {
9105 size_t len
= (size_t)RSTRING_LEN(mesg
);
9107 if (isatty(fileno(stderr
))) {
9108 if (rb_w32_write_console(mesg
, fileno(stderr
)) > 0) return;
9111 if (fwrite(RSTRING_PTR(mesg
), sizeof(char), len
, stderr
) < len
) {
9117 /* may unlock GVL, and */
9118 rb_io_write(out
, mesg
);
9123 rb_stderr_tty_p(void)
9125 if (rb_stderr_to_original_p(rb_ractor_stderr()))
9126 return isatty(fileno(stderr
));
9131 must_respond_to(ID mid
, VALUE val
, ID id
)
9133 if (!rb_respond_to(val
, mid
)) {
9134 rb_raise(rb_eTypeError
, "%"PRIsVALUE
" must have %"PRIsVALUE
" method, %"PRIsVALUE
" given",
9135 rb_id2str(id
), rb_id2str(mid
),
9141 stdin_setter(VALUE val
, ID id
, VALUE
*ptr
)
9143 rb_ractor_stdin_set(val
);
9147 stdin_getter(ID id
, VALUE
*ptr
)
9149 return rb_ractor_stdin();
9153 stdout_setter(VALUE val
, ID id
, VALUE
*ptr
)
9155 must_respond_to(id_write
, val
, id
);
9156 rb_ractor_stdout_set(val
);
9160 stdout_getter(ID id
, VALUE
*ptr
)
9162 return rb_ractor_stdout();
9166 stderr_setter(VALUE val
, ID id
, VALUE
*ptr
)
9168 must_respond_to(id_write
, val
, id
);
9169 rb_ractor_stderr_set(val
);
9173 stderr_getter(ID id
, VALUE
*ptr
)
9175 return rb_ractor_stderr();
9179 allocate_and_open_new_file(VALUE klass
)
9181 VALUE self
= io_alloc(klass
);
9182 rb_io_make_open_file(self
);
9187 rb_io_open_descriptor(VALUE klass
, int descriptor
, int mode
, VALUE path
, VALUE timeout
, struct rb_io_encoding
*encoding
)
9190 VALUE self
= rb_protect(allocate_and_open_new_file
, klass
, &state
);
9192 /* if we raised an exception allocating an IO object, but the caller
9193 intended to transfer ownership of this FD to us, close the fd before
9194 raising the exception. Otherwise, we would leak a FD - the caller
9195 expects GC to close the file, but we never got around to assigning
9197 if (!(mode
& FMODE_EXTERNAL
)) {
9198 maygvl_close(descriptor
, 0);
9204 rb_io_t
*io
= RFILE(self
)->fptr
;
9206 io
->fd
= descriptor
;
9209 /* At this point, Ruby fully owns the descriptor, and will close it when
9210 the IO gets GC'd (unless FMODE_EXTERNAL was set), no matter what happens
9211 in the rest of this method. */
9218 io
->pathv
= rb_str_new_frozen(path
);
9221 io
->timeout
= timeout
;
9224 io
->encs
= *encoding
;
9227 rb_update_max_fd(descriptor
);
9233 prep_io(int fd
, int fmode
, VALUE klass
, const char *path
)
9235 VALUE path_value
= Qnil
;
9237 struct rb_io_encoding convconfig
;
9240 path_value
= rb_obj_freeze(rb_str_new_cstr(path
));
9243 e
= (fmode
& FMODE_BINMODE
) ? rb_ascii8bit_encoding() : NULL
;
9244 rb_io_ext_int_to_encs(e
, NULL
, &convconfig
.enc
, &convconfig
.enc2
, fmode
);
9245 convconfig
.ecflags
= (fmode
& FMODE_READABLE
) ?
9246 MODE_BTMODE(ECONV_DEFAULT_NEWLINE_DECORATOR
,
9247 0, ECONV_UNIVERSAL_NEWLINE_DECORATOR
) : 0;
9248 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
9249 convconfig
.ecflags
|= (fmode
& FMODE_WRITABLE
) ?
9250 MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
,
9251 0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
) : 0;
9253 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(convconfig
.enc2
, convconfig
.ecflags
);
9254 convconfig
.ecopts
= Qnil
;
9256 VALUE self
= rb_io_open_descriptor(klass
, fd
, fmode
, path_value
, Qnil
, &convconfig
);
9257 rb_io_t
*io
= RFILE(self
)->fptr
;
9259 if (!io_check_tty(io
)) {
9261 io
->mode
|= FMODE_BINMODE
;
9262 setmode(fd
, O_BINARY
);
9270 rb_io_fdopen(int fd
, int oflags
, const char *path
)
9272 VALUE klass
= rb_cIO
;
9274 if (path
&& strcmp(path
, "-")) klass
= rb_cFile
;
9275 return prep_io(fd
, rb_io_oflags_fmode(oflags
), klass
, path
);
9279 prep_stdio(FILE *f
, int fmode
, VALUE klass
, const char *path
)
9282 VALUE io
= prep_io(fileno(f
), fmode
|FMODE_EXTERNAL
|DEFAULT_TEXTMODE
, klass
, path
);
9284 GetOpenFile(io
, fptr
);
9285 fptr
->encs
.ecflags
|= ECONV_DEFAULT_NEWLINE_DECORATOR
;
9286 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
9287 fptr
->encs
.ecflags
|= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
;
9288 if (fmode
& FMODE_READABLE
) {
9289 fptr
->encs
.ecflags
|= ECONV_UNIVERSAL_NEWLINE_DECORATOR
;
9292 fptr
->stdio_file
= f
;
9298 rb_io_prep_stdin(void)
9300 return prep_stdio(stdin
, FMODE_READABLE
, rb_cIO
, "<STDIN>");
9304 rb_io_prep_stdout(void)
9306 return prep_stdio(stdout
, FMODE_WRITABLE
|FMODE_SIGNAL_ON_EPIPE
, rb_cIO
, "<STDOUT>");
9310 rb_io_prep_stderr(void)
9312 return prep_stdio(stderr
, FMODE_WRITABLE
|FMODE_SYNC
, rb_cIO
, "<STDERR>");
9316 rb_io_stdio_file(rb_io_t
*fptr
)
9318 if (!fptr
->stdio_file
) {
9319 int oflags
= rb_io_fmode_oflags(fptr
->mode
) & ~O_EXCL
;
9320 fptr
->stdio_file
= rb_fdopen(fptr
->fd
, rb_io_oflags_modestr(oflags
));
9322 return fptr
->stdio_file
;
9326 rb_io_buffer_init(struct rb_io_internal_buffer
*buf
)
9334 static inline rb_io_t
*
9335 rb_io_fptr_new(void)
9337 rb_io_t
*fp
= ALLOC(rb_io_t
);
9340 fp
->stdio_file
= NULL
;
9346 rb_io_buffer_init(&fp
->wbuf
);
9347 rb_io_buffer_init(&fp
->rbuf
);
9348 rb_io_buffer_init(&fp
->cbuf
);
9349 fp
->readconv
= NULL
;
9350 fp
->writeconv
= NULL
;
9351 fp
->writeconv_asciicompat
= Qnil
;
9352 fp
->writeconv_pre_ecflags
= 0;
9353 fp
->writeconv_pre_ecopts
= Qnil
;
9354 fp
->writeconv_initialized
= 0;
9355 fp
->tied_io_for_writing
= 0;
9356 fp
->encs
.enc
= NULL
;
9357 fp
->encs
.enc2
= NULL
;
9358 fp
->encs
.ecflags
= 0;
9359 fp
->encs
.ecopts
= Qnil
;
9360 fp
->write_lock
= Qnil
;
9366 rb_io_make_open_file(VALUE obj
)
9370 Check_Type(obj
, T_FILE
);
9371 if (RFILE(obj
)->fptr
) {
9373 rb_io_fptr_finalize(RFILE(obj
)->fptr
);
9374 RFILE(obj
)->fptr
= 0;
9376 fp
= rb_io_fptr_new();
9378 RFILE(obj
)->fptr
= fp
;
9384 * IO.new(fd, mode = 'r', **opts) -> io
9386 * Creates and returns a new \IO object (file stream) from a file descriptor.
9388 * \IO.new may be useful for interaction with low-level libraries.
9389 * For higher-level interactions, it may be simpler to create
9390 * the file stream using File.open.
9392 * Argument +fd+ must be a valid file descriptor (integer):
9395 * fd = IO.sysopen(path) # => 3
9396 * IO.new(fd) # => #<IO:fd 3>
9398 * The new \IO object does not inherit encoding
9399 * (because the integer file descriptor does not have an encoding):
9401 * fd = IO.sysopen('t.rus', 'rb')
9403 * io.external_encoding # => #<Encoding:UTF-8> # Not ASCII-8BIT.
9405 * Optional argument +mode+ (defaults to 'r') must specify a valid mode;
9406 * see {Access Modes}[rdoc-ref:File@Access+Modes]:
9408 * IO.new(fd, 'w') # => #<IO:fd 3>
9409 * IO.new(fd, File::WRONLY) # => #<IO:fd 3>
9411 * Optional keyword arguments +opts+ specify:
9413 * - {Open Options}[rdoc-ref:IO@Open+Options].
9414 * - {Encoding options}[rdoc-ref:encodings.rdoc@Encoding+Options].
9418 * IO.new(fd, internal_encoding: nil) # => #<IO:fd 3>
9419 * IO.new(fd, autoclose: true) # => #<IO:fd 3>
9424 rb_io_initialize(int argc
, VALUE
*argv
, VALUE io
)
9428 int fd
, fmode
, oflags
= O_RDONLY
;
9429 struct rb_io_encoding convconfig
;
9431 #if defined(HAVE_FCNTL) && defined(F_GETFL)
9438 argc
= rb_scan_args(argc
, argv
, "11:", &fnum
, &vmode
, &opt
);
9439 rb_io_extract_modeenc(&vmode
, 0, opt
, &oflags
, &fmode
, &convconfig
);
9442 if (rb_reserved_fd_p(fd
)) {
9443 rb_raise(rb_eArgError
, "The given fd is not accessible because RubyVM reserves it");
9445 #if defined(HAVE_FCNTL) && defined(F_GETFL)
9446 oflags
= fcntl(fd
, F_GETFL
);
9447 if (oflags
== -1) rb_sys_fail(0);
9449 if (fstat(fd
, &st
) < 0) rb_sys_fail(0);
9451 rb_update_max_fd(fd
);
9452 #if defined(HAVE_FCNTL) && defined(F_GETFL)
9453 ofmode
= rb_io_oflags_fmode(oflags
);
9457 else if ((~ofmode
& fmode
) & FMODE_READWRITE
) {
9458 VALUE error
= INT2FIX(EINVAL
);
9459 rb_exc_raise(rb_class_new_instance(1, &error
, rb_eSystemCallError
));
9465 if (rb_hash_aref(opt
, sym_autoclose
) == Qfalse
) {
9466 fmode
|= FMODE_EXTERNAL
;
9469 path
= rb_hash_aref(opt
, RB_ID2SYM(idPath
));
9472 path
= rb_str_new_frozen(path
);
9476 MakeOpenFile(io
, fp
);
9480 fp
->encs
= convconfig
;
9485 if (fileno(stdin
) == fd
)
9486 fp
->stdio_file
= stdin
;
9487 else if (fileno(stdout
) == fd
)
9488 fp
->stdio_file
= stdout
;
9489 else if (fileno(stderr
) == fd
)
9490 fp
->stdio_file
= stderr
;
9492 if (fmode
& FMODE_SETENC_BY_BOM
) io_set_encoding_by_bom(io
);
9498 * set_encoding_by_bom -> encoding or nil
9500 * If the stream begins with a BOM
9501 * ({byte order marker}[https://en.wikipedia.org/wiki/Byte_order_mark]),
9502 * consumes the BOM and sets the external encoding accordingly;
9503 * returns the result encoding if found, or +nil+ otherwise:
9505 * File.write('t.tmp', "\u{FEFF}abc")
9506 * io = File.open('t.tmp', 'rb')
9507 * io.set_encoding_by_bom # => #<Encoding:UTF-8>
9510 * File.write('t.tmp', 'abc')
9511 * io = File.open('t.tmp', 'rb')
9512 * io.set_encoding_by_bom # => nil
9515 * Raises an exception if the stream is not binmode
9516 * or its encoding has already been set.
9521 rb_io_set_encoding_by_bom(VALUE io
)
9525 GetOpenFile(io
, fptr
);
9526 if (!(fptr
->mode
& FMODE_BINMODE
)) {
9527 rb_raise(rb_eArgError
, "ASCII incompatible encoding needs binmode");
9529 if (fptr
->encs
.enc2
) {
9530 rb_raise(rb_eArgError
, "encoding conversion is set");
9532 else if (fptr
->encs
.enc
&& fptr
->encs
.enc
!= rb_ascii8bit_encoding()) {
9533 rb_raise(rb_eArgError
, "encoding is set to %s already",
9534 rb_enc_name(fptr
->encs
.enc
));
9536 if (!io_set_encoding_by_bom(io
)) return Qnil
;
9537 return rb_enc_from_encoding(fptr
->encs
.enc
);
9542 * File.new(path, mode = 'r', perm = 0666, **opts) -> file
9544 * Opens the file at the given +path+ according to the given +mode+;
9545 * creates and returns a new File object for that file.
9547 * The new File object is buffered mode (or non-sync mode), unless
9548 * +filename+ is a tty.
9549 * See IO#flush, IO#fsync, IO#fdatasync, and IO#sync=.
9551 * Argument +path+ must be a valid file path:
9553 * f = File.new('/etc/fstab')
9555 * f = File.new('t.txt')
9558 * Optional argument +mode+ (defaults to 'r') must specify a valid mode;
9559 * see {Access Modes}[rdoc-ref:File@Access+Modes]:
9561 * f = File.new('t.tmp', 'w')
9563 * f = File.new('t.tmp', File::RDONLY)
9566 * Optional argument +perm+ (defaults to 0666) must specify valid permissions
9567 * see {File Permissions}[rdoc-ref:File@File+Permissions]:
9569 * f = File.new('t.tmp', File::CREAT, 0644)
9571 * f = File.new('t.tmp', File::CREAT, 0444)
9574 * Optional keyword arguments +opts+ specify:
9576 * - {Open Options}[rdoc-ref:IO@Open+Options].
9577 * - {Encoding options}[rdoc-ref:encodings.rdoc@Encoding+Options].
9582 rb_file_initialize(int argc
, VALUE
*argv
, VALUE io
)
9584 if (RFILE(io
)->fptr
) {
9585 rb_raise(rb_eRuntimeError
, "reinitializing File");
9587 if (0 < argc
&& argc
< 3) {
9588 VALUE fd
= rb_check_to_int(argv
[0]);
9592 return rb_io_initialize(argc
, argv
, io
);
9595 rb_open_file(argc
, argv
, io
);
9602 rb_io_s_new(int argc
, VALUE
*argv
, VALUE klass
)
9604 if (rb_block_given_p()) {
9605 VALUE cname
= rb_obj_as_string(klass
);
9607 rb_warn("%"PRIsVALUE
"::new() does not take block; use %"PRIsVALUE
"::open() instead",
9610 return rb_class_new_instance_kw(argc
, argv
, klass
, RB_PASS_CALLED_KEYWORDS
);
9616 * IO.for_fd(fd, mode = 'r', **opts) -> io
9618 * Synonym for IO.new.
9623 rb_io_s_for_fd(int argc
, VALUE
*argv
, VALUE klass
)
9625 VALUE io
= rb_obj_alloc(klass
);
9626 rb_io_initialize(argc
, argv
, io
);
9632 * ios.autoclose? -> true or false
9634 * Returns +true+ if the underlying file descriptor of _ios_ will be
9635 * closed at its finalization or at calling #close, otherwise +false+.
9639 rb_io_autoclose_p(VALUE io
)
9641 rb_io_t
*fptr
= RFILE(io
)->fptr
;
9642 rb_io_check_closed(fptr
);
9643 return RBOOL(!(fptr
->mode
& FMODE_EXTERNAL
));
9648 * io.autoclose = bool -> true or false
9650 * Sets auto-close flag.
9652 * f = File.open(File::NULL)
9653 * IO.for_fd(f.fileno).close
9654 * f.gets # raises Errno::EBADF
9656 * f = File.open(File::NULL)
9657 * g = IO.for_fd(f.fileno)
9658 * g.autoclose = false
9660 * f.gets # won't cause Errno::EBADF
9664 rb_io_set_autoclose(VALUE io
, VALUE autoclose
)
9667 GetOpenFile(io
, fptr
);
9668 if (!RTEST(autoclose
))
9669 fptr
->mode
|= FMODE_EXTERNAL
;
9671 fptr
->mode
&= ~FMODE_EXTERNAL
;
9676 io_wait_event(VALUE io
, int event
, VALUE timeout
, int return_io
)
9678 VALUE result
= rb_io_wait(io
, RB_INT2NUM(event
), timeout
);
9680 if (!RB_TEST(result
)) {
9684 int mask
= RB_NUM2INT(result
);
9699 * io.wait_readable -> truthy or falsy
9700 * io.wait_readable(timeout) -> truthy or falsy
9702 * Waits until IO is readable and returns a truthy value, or a falsy
9703 * value when times out. Returns a truthy value immediately when
9704 * buffered data is available.
9708 io_wait_readable(int argc
, VALUE
*argv
, VALUE io
)
9712 RB_IO_POINTER(io
, fptr
);
9713 rb_io_check_readable(fptr
);
9715 if (rb_io_read_pending(fptr
)) return Qtrue
;
9717 rb_check_arity(argc
, 0, 1);
9718 VALUE timeout
= (argc
== 1 ? argv
[0] : Qnil
);
9720 return io_wait_event(io
, RUBY_IO_READABLE
, timeout
, 1);
9725 * io.wait_writable -> truthy or falsy
9726 * io.wait_writable(timeout) -> truthy or falsy
9728 * Waits until IO is writable and returns a truthy value or a falsy
9729 * value when times out.
9732 io_wait_writable(int argc
, VALUE
*argv
, VALUE io
)
9736 RB_IO_POINTER(io
, fptr
);
9737 rb_io_check_writable(fptr
);
9739 rb_check_arity(argc
, 0, 1);
9740 VALUE timeout
= (argc
== 1 ? argv
[0] : Qnil
);
9742 return io_wait_event(io
, RUBY_IO_WRITABLE
, timeout
, 1);
9747 * io.wait_priority -> truthy or falsy
9748 * io.wait_priority(timeout) -> truthy or falsy
9750 * Waits until IO is priority and returns a truthy value or a falsy
9751 * value when times out. Priority data is sent and received using
9752 * the Socket::MSG_OOB flag and is typically limited to streams.
9755 io_wait_priority(int argc
, VALUE
*argv
, VALUE io
)
9757 rb_io_t
*fptr
= NULL
;
9759 RB_IO_POINTER(io
, fptr
);
9760 rb_io_check_readable(fptr
);
9762 if (rb_io_read_pending(fptr
)) return Qtrue
;
9764 rb_check_arity(argc
, 0, 1);
9765 VALUE timeout
= argc
== 1 ? argv
[0] : Qnil
;
9767 return io_wait_event(io
, RUBY_IO_PRIORITY
, timeout
, 1);
9771 wait_mode_sym(VALUE mode
)
9773 if (mode
== ID2SYM(rb_intern("r"))) {
9774 return RB_WAITFD_IN
;
9776 if (mode
== ID2SYM(rb_intern("read"))) {
9777 return RB_WAITFD_IN
;
9779 if (mode
== ID2SYM(rb_intern("readable"))) {
9780 return RB_WAITFD_IN
;
9782 if (mode
== ID2SYM(rb_intern("w"))) {
9783 return RB_WAITFD_OUT
;
9785 if (mode
== ID2SYM(rb_intern("write"))) {
9786 return RB_WAITFD_OUT
;
9788 if (mode
== ID2SYM(rb_intern("writable"))) {
9789 return RB_WAITFD_OUT
;
9791 if (mode
== ID2SYM(rb_intern("rw"))) {
9792 return RB_WAITFD_IN
|RB_WAITFD_OUT
;
9794 if (mode
== ID2SYM(rb_intern("read_write"))) {
9795 return RB_WAITFD_IN
|RB_WAITFD_OUT
;
9797 if (mode
== ID2SYM(rb_intern("readable_writable"))) {
9798 return RB_WAITFD_IN
|RB_WAITFD_OUT
;
9801 rb_raise(rb_eArgError
, "unsupported mode: %"PRIsVALUE
, mode
);
9804 static inline enum rb_io_event
9805 io_event_from_value(VALUE value
)
9807 int events
= RB_NUM2INT(value
);
9809 if (events
<= 0) rb_raise(rb_eArgError
, "Events must be positive integer!");
9816 * io.wait(events, timeout) -> event mask, false or nil
9817 * io.wait(timeout = nil, mode = :read) -> self, true, or false
9819 * Waits until the IO becomes ready for the specified events and returns the
9820 * subset of events that become ready, or a falsy value when times out.
9822 * The events can be a bit mask of +IO::READABLE+, +IO::WRITABLE+ or
9825 * Returns an event mask (truthy value) immediately when buffered data is available.
9827 * Optional parameter +mode+ is one of +:read+, +:write+, or
9832 io_wait(int argc
, VALUE
*argv
, VALUE io
)
9834 VALUE timeout
= Qundef
;
9835 enum rb_io_event events
= 0;
9838 // The documented signature for this method is actually incorrect.
9839 // A single timeout is allowed in any position, and multiple symbols can be given.
9840 // Whether this is intentional or not, I don't know, and as such I consider this to
9841 // be a legacy/slow path.
9842 if (argc
!= 2 || (RB_SYMBOL_P(argv
[0]) || RB_SYMBOL_P(argv
[1]))) {
9843 // We'd prefer to return the actual mask, but this form would return the io itself:
9847 for (int i
= 0; i
< argc
; i
+= 1) {
9848 if (RB_SYMBOL_P(argv
[i
])) {
9849 events
|= wait_mode_sym(argv
[i
]);
9851 else if (UNDEF_P(timeout
)) {
9852 rb_time_interval(timeout
= argv
[i
]);
9855 rb_raise(rb_eArgError
, "timeout given more than once");
9859 if (UNDEF_P(timeout
)) timeout
= Qnil
;
9862 events
= RUBY_IO_READABLE
;
9865 else /* argc == 2 and neither are symbols */ {
9866 // This is the fast path:
9867 events
= io_event_from_value(argv
[0]);
9871 if (events
& RUBY_IO_READABLE
) {
9872 rb_io_t
*fptr
= NULL
;
9873 RB_IO_POINTER(io
, fptr
);
9875 if (rb_io_read_pending(fptr
)) {
9876 // This was the original behaviour:
9877 if (return_io
) return Qtrue
;
9878 // New behaviour always returns an event mask:
9879 else return RB_INT2NUM(RUBY_IO_READABLE
);
9883 return io_wait_event(io
, events
, timeout
, return_io
);
9887 argf_mark(void *ptr
)
9889 struct argf
*p
= ptr
;
9890 rb_gc_mark(p
->filename
);
9891 rb_gc_mark(p
->current_file
);
9892 rb_gc_mark(p
->argv
);
9893 rb_gc_mark(p
->inplace
);
9894 rb_gc_mark(p
->encs
.ecopts
);
9898 argf_memsize(const void *ptr
)
9900 const struct argf
*p
= ptr
;
9901 size_t size
= sizeof(*p
);
9905 static const rb_data_type_t argf_type
= {
9907 {argf_mark
, RUBY_TYPED_DEFAULT_FREE
, argf_memsize
},
9908 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
9912 argf_init(struct argf
*p
, VALUE v
)
9915 p
->current_file
= Qnil
;
9921 argf_alloc(VALUE klass
)
9924 VALUE argf
= TypedData_Make_Struct(klass
, struct argf
, &argf_type
, p
);
9934 argf_initialize(VALUE argf
, VALUE argv
)
9936 memset(&ARGF
, 0, sizeof(ARGF
));
9937 argf_init(&ARGF
, argv
);
9944 argf_initialize_copy(VALUE argf
, VALUE orig
)
9946 if (!OBJ_INIT_COPY(argf
, orig
)) return argf
;
9947 ARGF
= argf_of(orig
);
9948 ARGF
.argv
= rb_obj_dup(ARGF
.argv
);
9954 * ARGF.lineno = integer -> integer
9956 * Sets the line number of ARGF as a whole to the given Integer.
9958 * ARGF sets the line number automatically as you read data, so normally
9959 * you will not need to set it explicitly. To access the current line number
9965 * ARGF.readline #=> "This is line 1\n"
9967 * ARGF.lineno = 0 #=> 0
9971 argf_set_lineno(VALUE argf
, VALUE val
)
9973 ARGF
.lineno
= NUM2INT(val
);
9974 ARGF
.last_lineno
= ARGF
.lineno
;
9980 * ARGF.lineno -> integer
9982 * Returns the current line number of ARGF as a whole. This value
9983 * can be set manually with ARGF.lineno=.
9988 * ARGF.readline #=> "This is line 1\n"
9992 argf_lineno(VALUE argf
)
9994 return INT2FIX(ARGF
.lineno
);
9998 argf_forward(int argc
, VALUE
*argv
, VALUE argf
)
10000 return forward_current(rb_frame_this_func(), argc
, argv
);
10003 #define next_argv() argf_next_argv(argf)
10004 #define ARGF_GENERIC_INPUT_P() \
10005 (ARGF.current_file == rb_stdin && !RB_TYPE_P(ARGF.current_file, T_FILE))
10006 #define ARGF_FORWARD(argc, argv) do {\
10007 if (ARGF_GENERIC_INPUT_P())\
10008 return argf_forward((argc), (argv), argf);\
10010 #define NEXT_ARGF_FORWARD(argc, argv) do {\
10011 if (!next_argv()) return Qnil;\
10012 ARGF_FORWARD((argc), (argv));\
10016 argf_close(VALUE argf
)
10018 VALUE file
= ARGF
.current_file
;
10019 if (file
== rb_stdin
) return;
10020 if (RB_TYPE_P(file
, T_FILE
)) {
10021 rb_io_set_write_io(file
, Qnil
);
10028 argf_next_argv(VALUE argf
)
10032 int stdout_binmode
= 0;
10035 VALUE r_stdout
= rb_ractor_stdout();
10037 if (RB_TYPE_P(r_stdout
, T_FILE
)) {
10038 GetOpenFile(r_stdout
, fptr
);
10039 if (fptr
->mode
& FMODE_BINMODE
)
10040 stdout_binmode
= 1;
10043 if (ARGF
.init_p
== 0) {
10044 if (!NIL_P(ARGF
.argv
) && RARRAY_LEN(ARGF
.argv
) > 0) {
10053 if (NIL_P(ARGF
.argv
)) {
10056 else if (ARGF
.next_p
== -1 && RARRAY_LEN(ARGF
.argv
) > 0) {
10061 if (ARGF
.next_p
== 1) {
10062 if (ARGF
.init_p
== 1) argf_close(argf
);
10064 if (RARRAY_LEN(ARGF
.argv
) > 0) {
10065 VALUE filename
= rb_ary_shift(ARGF
.argv
);
10066 FilePathValue(filename
);
10067 ARGF
.filename
= filename
;
10068 filename
= rb_str_encode_ospath(filename
);
10069 fn
= StringValueCStr(filename
);
10070 if (RSTRING_LEN(filename
) == 1 && fn
[0] == '-') {
10071 ARGF
.current_file
= rb_stdin
;
10072 if (ARGF
.inplace
) {
10073 rb_warn("Can't do inplace edit for stdio; skipping");
10078 VALUE write_io
= Qnil
;
10079 int fr
= rb_sysopen(filename
, O_RDONLY
, 0);
10081 if (ARGF
.inplace
) {
10083 #ifndef NO_SAFE_RENAME
10089 if (RB_TYPE_P(r_stdout
, T_FILE
) && r_stdout
!= orig_stdout
) {
10090 rb_io_close(r_stdout
);
10094 if (!NIL_P(ARGF
.inplace
)) {
10095 VALUE suffix
= ARGF
.inplace
;
10096 str
= rb_str_dup(str
);
10097 if (NIL_P(rb_str_cat_conv_enc_opts(str
, RSTRING_LEN(str
),
10098 RSTRING_PTR(suffix
), RSTRING_LEN(suffix
),
10099 rb_enc_get(suffix
), 0, Qnil
))) {
10100 rb_str_append(str
, suffix
);
10102 #ifdef NO_SAFE_RENAME
10104 (void)unlink(RSTRING_PTR(str
));
10105 if (rename(fn
, RSTRING_PTR(str
)) < 0) {
10106 rb_warn("Can't rename %"PRIsVALUE
" to %"PRIsVALUE
": %s, skipping file",
10107 filename
, str
, strerror(errno
));
10110 fr
= rb_sysopen(str
, O_RDONLY
, 0);
10112 if (rename(fn
, RSTRING_PTR(str
)) < 0) {
10113 rb_warn("Can't rename %"PRIsVALUE
" to %"PRIsVALUE
": %s, skipping file",
10114 filename
, str
, strerror(errno
));
10121 #ifdef NO_SAFE_RENAME
10122 rb_fatal("Can't do inplace edit without backup");
10124 if (unlink(fn
) < 0) {
10125 rb_warn("Can't remove %"PRIsVALUE
": %s, skipping file",
10126 filename
, strerror(errno
));
10132 fw
= rb_sysopen(filename
, O_WRONLY
|O_CREAT
|O_TRUNC
, 0666);
10133 #ifndef NO_SAFE_RENAME
10136 fchmod(fw
, st
.st_mode
);
10138 chmod(fn
, st
.st_mode
);
10140 if (st
.st_uid
!=st2
.st_uid
|| st
.st_gid
!=st2
.st_gid
) {
10143 err
= fchown(fw
, st
.st_uid
, st
.st_gid
);
10145 err
= chown(fn
, st
.st_uid
, st
.st_gid
);
10147 if (err
&& getuid() == 0 && st2
.st_uid
== 0) {
10148 const char *wkfn
= RSTRING_PTR(filename
);
10149 rb_warn("Can't set owner/group of %"PRIsVALUE
" to same as %"PRIsVALUE
": %s, skipping file",
10150 filename
, str
, strerror(errno
));
10153 (void)unlink(wkfn
);
10158 write_io
= prep_io(fw
, FMODE_WRITABLE
, rb_cFile
, fn
);
10159 rb_ractor_stdout_set(write_io
);
10160 if (stdout_binmode
) rb_io_binmode(rb_stdout
);
10162 fmode
= FMODE_READABLE
;
10163 if (!ARGF
.binmode
) {
10164 fmode
|= DEFAULT_TEXTMODE
;
10166 ARGF
.current_file
= prep_io(fr
, fmode
, rb_cFile
, fn
);
10167 if (!NIL_P(write_io
)) {
10168 rb_io_set_write_io(ARGF
.current_file
, write_io
);
10170 RB_GC_GUARD(filename
);
10172 if (ARGF
.binmode
) rb_io_ascii8bit_binmode(ARGF
.current_file
);
10173 GetOpenFile(ARGF
.current_file
, fptr
);
10174 if (ARGF
.encs
.enc
) {
10175 fptr
->encs
= ARGF
.encs
;
10176 clear_codeconv(fptr
);
10179 fptr
->encs
.ecflags
&= ~ECONV_NEWLINE_DECORATOR_MASK
;
10180 if (!ARGF
.binmode
) {
10181 fptr
->encs
.ecflags
|= ECONV_DEFAULT_NEWLINE_DECORATOR
;
10182 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
10183 fptr
->encs
.ecflags
|= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
;
10194 else if (ARGF
.next_p
== -1) {
10195 ARGF
.current_file
= rb_stdin
;
10196 ARGF
.filename
= rb_str_new2("-");
10197 if (ARGF
.inplace
) {
10198 rb_warn("Can't do inplace edit for stdio");
10199 rb_ractor_stdout_set(orig_stdout
);
10202 if (ARGF
.init_p
== -1) ARGF
.init_p
= 1;
10207 argf_getline(int argc
, VALUE
*argv
, VALUE argf
)
10210 long lineno
= ARGF
.lineno
;
10213 if (!next_argv()) return Qnil
;
10214 if (ARGF_GENERIC_INPUT_P()) {
10215 line
= forward_current(idGets
, argc
, argv
);
10218 if (argc
== 0 && rb_rs
== rb_default_rs
) {
10219 line
= rb_io_gets(ARGF
.current_file
);
10222 line
= rb_io_getline(argc
, argv
, ARGF
.current_file
);
10224 if (NIL_P(line
) && ARGF
.next_p
!= -1) {
10230 if (!NIL_P(line
)) {
10231 ARGF
.lineno
= ++lineno
;
10232 ARGF
.last_lineno
= ARGF
.lineno
;
10238 argf_lineno_getter(ID id
, VALUE
*var
)
10241 return INT2FIX(ARGF
.last_lineno
);
10245 argf_lineno_setter(VALUE val
, ID id
, VALUE
*var
)
10248 int n
= NUM2INT(val
);
10249 ARGF
.last_lineno
= ARGF
.lineno
= n
;
10253 rb_reset_argf_lineno(long n
)
10255 ARGF
.last_lineno
= ARGF
.lineno
= n
;
10258 static VALUE
argf_gets(int, VALUE
*, VALUE
);
10262 * gets(sep=$/ [, getline_args]) -> string or nil
10263 * gets(limit [, getline_args]) -> string or nil
10264 * gets(sep, limit [, getline_args]) -> string or nil
10266 * Returns (and assigns to <code>$_</code>) the next line from the list
10267 * of files in +ARGV+ (or <code>$*</code>), or from standard input if
10268 * no files are present on the command line. Returns +nil+ at end of
10269 * file. The optional argument specifies the record separator. The
10270 * separator is included with the contents of each record. A separator
10271 * of +nil+ reads the entire contents, and a zero-length separator
10272 * reads the input one paragraph at a time, where paragraphs are
10273 * divided by two consecutive newlines. If the first argument is an
10274 * integer, or optional second argument is given, the returning string
10275 * would not be longer than the given value in bytes. If multiple
10276 * filenames are present in +ARGV+, <code>gets(nil)</code> will read
10277 * the contents one file at a time.
10279 * ARGV << "testfile"
10282 * <em>produces:</em>
10286 * This is line three
10289 * The style of programming using <code>$_</code> as an implicit
10290 * parameter is gradually losing favor in the Ruby community.
10294 rb_f_gets(int argc
, VALUE
*argv
, VALUE recv
)
10296 if (recv
== argf
) {
10297 return argf_gets(argc
, argv
, argf
);
10299 return forward(argf
, idGets
, argc
, argv
);
10304 * ARGF.gets(sep=$/ [, getline_args]) -> string or nil
10305 * ARGF.gets(limit [, getline_args]) -> string or nil
10306 * ARGF.gets(sep, limit [, getline_args]) -> string or nil
10308 * Returns the next line from the current file in ARGF.
10310 * By default lines are assumed to be separated by <code>$/</code>;
10311 * to use a different character as a separator, supply it as a String
10312 * for the _sep_ argument.
10314 * The optional _limit_ argument specifies how many characters of each line
10315 * to return. By default all characters are returned.
10317 * See IO.readlines for details about getline_args.
10321 argf_gets(int argc
, VALUE
*argv
, VALUE argf
)
10325 line
= argf_getline(argc
, argv
, argf
);
10326 rb_lastline_set(line
);
10336 if (rb_rs
!= rb_default_rs
) {
10337 return rb_f_gets(0, 0, argf
);
10341 if (!next_argv()) return Qnil
;
10342 line
= rb_io_gets(ARGF
.current_file
);
10343 if (NIL_P(line
) && ARGF
.next_p
!= -1) {
10344 rb_io_close(ARGF
.current_file
);
10348 rb_lastline_set(line
);
10349 if (!NIL_P(line
)) {
10351 ARGF
.last_lineno
= ARGF
.lineno
;
10357 static VALUE
argf_readline(int, VALUE
*, VALUE
);
10361 * readline(sep = $/, chomp: false) -> string
10362 * readline(limit, chomp: false) -> string
10363 * readline(sep, limit, chomp: false) -> string
10365 * Equivalent to method Kernel#gets, except that it raises an exception
10366 * if called at end-of-stream:
10368 * $ cat t.txt | ruby -e "p readlines; readline"
10369 * ["First line\n", "Second line\n", "\n", "Fourth line\n", "Fifth line\n"]
10370 * in `readline': end of file reached (EOFError)
10372 * Optional keyword argument +chomp+ specifies whether line separators
10373 * are to be omitted.
10377 rb_f_readline(int argc
, VALUE
*argv
, VALUE recv
)
10379 if (recv
== argf
) {
10380 return argf_readline(argc
, argv
, argf
);
10382 return forward(argf
, rb_intern("readline"), argc
, argv
);
10388 * ARGF.readline(sep=$/) -> string
10389 * ARGF.readline(limit) -> string
10390 * ARGF.readline(sep, limit) -> string
10392 * Returns the next line from the current file in ARGF.
10394 * By default lines are assumed to be separated by <code>$/</code>;
10395 * to use a different character as a separator, supply it as a String
10396 * for the _sep_ argument.
10398 * The optional _limit_ argument specifies how many characters of each line
10399 * to return. By default all characters are returned.
10401 * An EOFError is raised at the end of the file.
10404 argf_readline(int argc
, VALUE
*argv
, VALUE argf
)
10408 if (!next_argv()) rb_eof_error();
10409 ARGF_FORWARD(argc
, argv
);
10410 line
= argf_gets(argc
, argv
, argf
);
10418 static VALUE
argf_readlines(int, VALUE
*, VALUE
);
10422 * readlines(sep = $/, chomp: false, **enc_opts) -> array
10423 * readlines(limit, chomp: false, **enc_opts) -> array
10424 * readlines(sep, limit, chomp: false, **enc_opts) -> array
10426 * Returns an array containing the lines returned by calling
10427 * Kernel#gets until the end-of-stream is reached;
10428 * (see {Line IO}[rdoc-ref:IO@Line+IO]).
10430 * With only string argument +sep+ given,
10431 * returns the remaining lines as determined by line separator +sep+,
10432 * or +nil+ if none;
10433 * see {Line Separator}[rdoc-ref:IO@Line+Separator]:
10435 * # Default separator.
10436 * $ cat t.txt | ruby -e "p readlines"
10437 * ["First line\n", "Second line\n", "\n", "Fourth line\n", "Fifth line\n"]
10439 * # Specified separator.
10440 * $ cat t.txt | ruby -e "p readlines 'li'"
10441 * ["First li", "ne\nSecond li", "ne\n\nFourth li", "ne\nFifth li", "ne\n"]
10443 * # Get-all separator.
10444 * $ cat t.txt | ruby -e "p readlines nil"
10445 * ["First line\nSecond line\n\nFourth line\nFifth line\n"]
10447 * # Get-paragraph separator.
10448 * $ cat t.txt | ruby -e "p readlines ''"
10449 * ["First line\nSecond line\n\n", "Fourth line\nFifth line\n"]
10451 * With only integer argument +limit+ given,
10452 * limits the number of bytes in the line;
10453 * see {Line Limit}[rdoc-ref:IO@Line+Limit]:
10455 * $cat t.txt | ruby -e "p readlines 10"
10456 * ["First line", "\n", "Second lin", "e\n", "\n", "Fourth lin", "e\n", "Fifth line", "\n"]
10458 * $cat t.txt | ruby -e "p readlines 11"
10459 * ["First line\n", "Second line", "\n", "\n", "Fourth line", "\n", "Fifth line\n"]
10461 * $cat t.txt | ruby -e "p readlines 12"
10462 * ["First line\n", "Second line\n", "\n", "Fourth line\n", "Fifth line\n"]
10464 * With arguments +sep+ and +limit+ given,
10465 * combines the two behaviors
10466 * (see {Line Separator and Line Limit}[rdoc-ref:IO@Line+Separator+and+Line+Limit]).
10468 * Optional keyword argument +chomp+ specifies whether line separators
10469 * are to be omitted:
10471 * $ cat t.txt | ruby -e "p readlines(chomp: true)"
10472 * ["First line", "Second line", "", "Fourth line", "Fifth line"]
10474 * Optional keyword arguments +enc_opts+ specify encoding options;
10475 * see {Encoding options}[rdoc-ref:encodings.rdoc@Encoding+Options].
10480 rb_f_readlines(int argc
, VALUE
*argv
, VALUE recv
)
10482 if (recv
== argf
) {
10483 return argf_readlines(argc
, argv
, argf
);
10485 return forward(argf
, rb_intern("readlines"), argc
, argv
);
10490 * ARGF.readlines(sep = $/, chomp: false) -> array
10491 * ARGF.readlines(limit, chomp: false) -> array
10492 * ARGF.readlines(sep, limit, chomp: false) -> array
10494 * ARGF.to_a(sep = $/, chomp: false) -> array
10495 * ARGF.to_a(limit, chomp: false) -> array
10496 * ARGF.to_a(sep, limit, chomp: false) -> array
10498 * Reads each file in ARGF in its entirety, returning an Array containing
10499 * lines from the files. Lines are assumed to be separated by _sep_.
10501 * lines = ARGF.readlines
10502 * lines[0] #=> "This is line one\n"
10504 * See +IO.readlines+ for a full description of all options.
10507 argf_readlines(int argc
, VALUE
*argv
, VALUE argf
)
10509 long lineno
= ARGF
.lineno
;
10512 ary
= rb_ary_new();
10513 while (next_argv()) {
10514 if (ARGF_GENERIC_INPUT_P()) {
10515 lines
= forward_current(rb_intern("readlines"), argc
, argv
);
10518 lines
= rb_io_readlines(argc
, argv
, ARGF
.current_file
);
10522 rb_ary_concat(ary
, lines
);
10523 ARGF
.lineno
= lineno
+ RARRAY_LEN(ary
);
10524 ARGF
.last_lineno
= ARGF
.lineno
;
10532 * `command` -> string
10534 * Returns the <tt>$stdout</tt> output from running +command+ in a subshell;
10535 * sets global variable <tt>$?</tt> to the process status.
10537 * This method has potential security vulnerabilities if called with untrusted input;
10538 * see {Command Injection}[rdoc-ref:command_injection.rdoc].
10542 * $ `date` # => "Wed Apr 9 08:56:30 CDT 2003\n"
10543 * $ `echo oops && exit 99` # => "oops\n"
10544 * $ $? # => #<Process::Status: pid 17088 exit 99>
10545 * $ $?.status # => 99>
10547 * The built-in syntax <tt>%x{...}</tt> uses this method.
10552 rb_f_backquote(VALUE obj
, VALUE str
)
10559 rb_last_status_clear();
10560 port
= pipe_open_s(str
, "r", FMODE_READABLE
|DEFAULT_TEXTMODE
, NULL
);
10561 if (NIL_P(port
)) return rb_str_new(0,0);
10563 GetOpenFile(port
, fptr
);
10564 result
= read_all(fptr
, remain_size(fptr
), Qnil
);
10566 rb_io_fptr_cleanup_all(fptr
);
10572 #ifdef HAVE_SYS_SELECT_H
10573 #include <sys/select.h>
10577 select_internal(VALUE read
, VALUE write
, VALUE except
, struct timeval
*tp
, rb_fdset_t
*fds
)
10580 rb_fdset_t
*rp
, *wp
, *ep
;
10585 struct timeval timerec
;
10587 if (!NIL_P(read
)) {
10588 Check_Type(read
, T_ARRAY
);
10589 for (i
=0; i
<RARRAY_LEN(read
); i
++) {
10590 GetOpenFile(rb_io_get_io(RARRAY_AREF(read
, i
)), fptr
);
10591 rb_fd_set(fptr
->fd
, &fds
[0]);
10592 if (READ_DATA_PENDING(fptr
) || READ_CHAR_PENDING(fptr
)) { /* check for buffered data */
10594 rb_fd_set(fptr
->fd
, &fds
[3]);
10596 if (max
< fptr
->fd
) max
= fptr
->fd
;
10598 if (pending
) { /* no blocking if there's buffered data */
10599 timerec
.tv_sec
= timerec
.tv_usec
= 0;
10607 if (!NIL_P(write
)) {
10608 Check_Type(write
, T_ARRAY
);
10609 for (i
=0; i
<RARRAY_LEN(write
); i
++) {
10610 VALUE write_io
= GetWriteIO(rb_io_get_io(RARRAY_AREF(write
, i
)));
10611 GetOpenFile(write_io
, fptr
);
10612 rb_fd_set(fptr
->fd
, &fds
[1]);
10613 if (max
< fptr
->fd
) max
= fptr
->fd
;
10620 if (!NIL_P(except
)) {
10621 Check_Type(except
, T_ARRAY
);
10622 for (i
=0; i
<RARRAY_LEN(except
); i
++) {
10623 VALUE io
= rb_io_get_io(RARRAY_AREF(except
, i
));
10624 VALUE write_io
= GetWriteIO(io
);
10625 GetOpenFile(io
, fptr
);
10626 rb_fd_set(fptr
->fd
, &fds
[2]);
10627 if (max
< fptr
->fd
) max
= fptr
->fd
;
10628 if (io
!= write_io
) {
10629 GetOpenFile(write_io
, fptr
);
10630 rb_fd_set(fptr
->fd
, &fds
[2]);
10631 if (max
< fptr
->fd
) max
= fptr
->fd
;
10642 n
= rb_thread_fd_select(max
, rp
, wp
, ep
, tp
);
10646 if (!pending
&& n
== 0) return Qnil
; /* returns nil on timeout */
10648 res
= rb_ary_new2(3);
10649 rb_ary_push(res
, rp
?rb_ary_new():rb_ary_new2(0));
10650 rb_ary_push(res
, wp
?rb_ary_new():rb_ary_new2(0));
10651 rb_ary_push(res
, ep
?rb_ary_new():rb_ary_new2(0));
10654 list
= RARRAY_AREF(res
, 0);
10655 for (i
=0; i
< RARRAY_LEN(read
); i
++) {
10656 VALUE obj
= rb_ary_entry(read
, i
);
10657 VALUE io
= rb_io_get_io(obj
);
10658 GetOpenFile(io
, fptr
);
10659 if (rb_fd_isset(fptr
->fd
, &fds
[0]) ||
10660 rb_fd_isset(fptr
->fd
, &fds
[3])) {
10661 rb_ary_push(list
, obj
);
10667 list
= RARRAY_AREF(res
, 1);
10668 for (i
=0; i
< RARRAY_LEN(write
); i
++) {
10669 VALUE obj
= rb_ary_entry(write
, i
);
10670 VALUE io
= rb_io_get_io(obj
);
10671 VALUE write_io
= GetWriteIO(io
);
10672 GetOpenFile(write_io
, fptr
);
10673 if (rb_fd_isset(fptr
->fd
, &fds
[1])) {
10674 rb_ary_push(list
, obj
);
10680 list
= RARRAY_AREF(res
, 2);
10681 for (i
=0; i
< RARRAY_LEN(except
); i
++) {
10682 VALUE obj
= rb_ary_entry(except
, i
);
10683 VALUE io
= rb_io_get_io(obj
);
10684 VALUE write_io
= GetWriteIO(io
);
10685 GetOpenFile(io
, fptr
);
10686 if (rb_fd_isset(fptr
->fd
, &fds
[2])) {
10687 rb_ary_push(list
, obj
);
10689 else if (io
!= write_io
) {
10690 GetOpenFile(write_io
, fptr
);
10691 if (rb_fd_isset(fptr
->fd
, &fds
[2])) {
10692 rb_ary_push(list
, obj
);
10698 return res
; /* returns an empty array on interrupt */
10701 struct select_args
{
10702 VALUE read
, write
, except
;
10703 struct timeval
*timeout
;
10704 rb_fdset_t fdsets
[4];
10708 select_call(VALUE arg
)
10710 struct select_args
*p
= (struct select_args
*)arg
;
10712 return select_internal(p
->read
, p
->write
, p
->except
, p
->timeout
, p
->fdsets
);
10716 select_end(VALUE arg
)
10718 struct select_args
*p
= (struct select_args
*)arg
;
10721 for (i
= 0; i
< numberof(p
->fdsets
); ++i
)
10722 rb_fd_term(&p
->fdsets
[i
]);
10726 static VALUE sym_normal
, sym_sequential
, sym_random
,
10727 sym_willneed
, sym_dontneed
, sym_noreuse
;
10729 #ifdef HAVE_POSIX_FADVISE
10730 struct io_advise_struct
{
10738 io_advise_internal(void *arg
)
10740 struct io_advise_struct
*ptr
= arg
;
10741 return posix_fadvise(ptr
->fd
, ptr
->offset
, ptr
->len
, ptr
->advice
);
10745 io_advise_sym_to_const(VALUE sym
)
10747 #ifdef POSIX_FADV_NORMAL
10748 if (sym
== sym_normal
)
10749 return INT2NUM(POSIX_FADV_NORMAL
);
10752 #ifdef POSIX_FADV_RANDOM
10753 if (sym
== sym_random
)
10754 return INT2NUM(POSIX_FADV_RANDOM
);
10757 #ifdef POSIX_FADV_SEQUENTIAL
10758 if (sym
== sym_sequential
)
10759 return INT2NUM(POSIX_FADV_SEQUENTIAL
);
10762 #ifdef POSIX_FADV_WILLNEED
10763 if (sym
== sym_willneed
)
10764 return INT2NUM(POSIX_FADV_WILLNEED
);
10767 #ifdef POSIX_FADV_DONTNEED
10768 if (sym
== sym_dontneed
)
10769 return INT2NUM(POSIX_FADV_DONTNEED
);
10772 #ifdef POSIX_FADV_NOREUSE
10773 if (sym
== sym_noreuse
)
10774 return INT2NUM(POSIX_FADV_NOREUSE
);
10781 do_io_advise(rb_io_t
*fptr
, VALUE advice
, rb_off_t offset
, rb_off_t len
)
10784 struct io_advise_struct ias
;
10787 num_adv
= io_advise_sym_to_const(advice
);
10790 * The platform doesn't support this hint. We don't raise exception, instead
10791 * silently ignore it. Because IO::advise is only hint.
10793 if (NIL_P(num_adv
))
10797 ias
.advice
= NUM2INT(num_adv
);
10798 ias
.offset
= offset
;
10801 rv
= (int)rb_thread_io_blocking_region(io_advise_internal
, &ias
, fptr
->fd
);
10802 if (rv
&& rv
!= ENOSYS
) {
10803 /* posix_fadvise(2) doesn't set errno. On success it returns 0; otherwise
10804 it returns the error code. */
10805 VALUE message
= rb_sprintf("%"PRIsVALUE
" "
10806 "(%"PRI_OFFT_PREFIX
"d, "
10807 "%"PRI_OFFT_PREFIX
"d, "
10809 fptr
->pathv
, offset
, len
, advice
);
10810 rb_syserr_fail_str(rv
, message
);
10816 #endif /* HAVE_POSIX_FADVISE */
10819 advice_arg_check(VALUE advice
)
10821 if (!SYMBOL_P(advice
))
10822 rb_raise(rb_eTypeError
, "advice must be a Symbol");
10824 if (advice
!= sym_normal
&&
10825 advice
!= sym_sequential
&&
10826 advice
!= sym_random
&&
10827 advice
!= sym_willneed
&&
10828 advice
!= sym_dontneed
&&
10829 advice
!= sym_noreuse
) {
10830 rb_raise(rb_eNotImpError
, "Unsupported advice: %+"PRIsVALUE
, advice
);
10836 * advise(advice, offset = 0, len = 0) -> nil
10838 * Invokes Posix system call
10839 * {posix_fadvise(2)}[https://linux.die.net/man/2/posix_fadvise],
10840 * which announces an intention to access data from the current file
10841 * in a particular manner.
10843 * The arguments and results are platform-dependent.
10845 * The relevant data is specified by:
10847 * - +offset+: The offset of the first byte of data.
10848 * - +len+: The number of bytes to be accessed;
10849 * if +len+ is zero, or is larger than the number of bytes remaining,
10850 * all remaining bytes will be accessed.
10852 * Argument +advice+ is one of the following symbols:
10854 * - +:normal+: The application has no advice to give
10855 * about its access pattern for the specified data.
10856 * If no advice is given for an open file, this is the default assumption.
10857 * - +:sequential+: The application expects to access the specified data sequentially
10858 * (with lower offsets read before higher ones).
10859 * - +:random+: The specified data will be accessed in random order.
10860 * - +:noreuse+: The specified data will be accessed only once.
10861 * - +:willneed+: The specified data will be accessed in the near future.
10862 * - +:dontneed+: The specified data will not be accessed in the near future.
10864 * Not implemented on all platforms.
10868 rb_io_advise(int argc
, VALUE
*argv
, VALUE io
)
10870 VALUE advice
, offset
, len
;
10874 rb_scan_args(argc
, argv
, "12", &advice
, &offset
, &len
);
10875 advice_arg_check(advice
);
10877 io
= GetWriteIO(io
);
10878 GetOpenFile(io
, fptr
);
10880 off
= NIL_P(offset
) ? 0 : NUM2OFFT(offset
);
10881 l
= NIL_P(len
) ? 0 : NUM2OFFT(len
);
10883 #ifdef HAVE_POSIX_FADVISE
10884 return do_io_advise(fptr
, advice
, off
, l
);
10886 ((void)off
, (void)l
); /* Ignore all hint */
10893 * IO.select(read_ios, write_ios = [], error_ios = [], timeout = nil) -> array or nil
10895 * Invokes system call {select(2)}[https://linux.die.net/man/2/select],
10896 * which monitors multiple file descriptors,
10897 * waiting until one or more of the file descriptors
10898 * becomes ready for some class of I/O operation.
10900 * Not implemented on all platforms.
10902 * Each of the arguments +read_ios+, +write_ios+, and +error_ios+
10903 * is an array of IO objects.
10905 * Argument +timeout+ is an integer timeout interval in seconds.
10907 * The method monitors the \IO objects given in all three arrays,
10908 * waiting for some to be ready;
10909 * returns a 3-element array whose elements are:
10911 * - An array of the objects in +read_ios+ that are ready for reading.
10912 * - An array of the objects in +write_ios+ that are ready for writing.
10913 * - An array of the objects in +error_ios+ have pending exceptions.
10915 * If no object becomes ready within the given +timeout+, +nil+ is returned.
10917 * \IO.select peeks the buffer of \IO objects for testing readability.
10918 * If the \IO buffer is not empty, \IO.select immediately notifies
10919 * readability. This "peek" only happens for \IO objects. It does not
10920 * happen for IO-like objects such as OpenSSL::SSL::SSLSocket.
10922 * The best way to use \IO.select is invoking it after non-blocking
10923 * methods such as #read_nonblock, #write_nonblock, etc. The methods
10924 * raise an exception which is extended by IO::WaitReadable or
10925 * IO::WaitWritable. The modules notify how the caller should wait
10926 * with \IO.select. If IO::WaitReadable is raised, the caller should
10927 * wait for reading. If IO::WaitWritable is raised, the caller should
10928 * wait for writing.
10930 * So, blocking read (#readpartial) can be emulated using
10931 * #read_nonblock and \IO.select as follows:
10934 * result = io_like.read_nonblock(maxlen)
10935 * rescue IO::WaitReadable
10936 * IO.select([io_like])
10938 * rescue IO::WaitWritable
10939 * IO.select(nil, [io_like])
10943 * Especially, the combination of non-blocking methods and \IO.select is
10944 * preferred for IO like objects such as OpenSSL::SSL::SSLSocket. It
10945 * has #to_io method to return underlying IO object. IO.select calls
10946 * #to_io to obtain the file descriptor to wait.
10948 * This means that readability notified by \IO.select doesn't mean
10949 * readability from OpenSSL::SSL::SSLSocket object.
10951 * The most likely situation is that OpenSSL::SSL::SSLSocket buffers
10952 * some data. \IO.select doesn't see the buffer. So \IO.select can
10953 * block when OpenSSL::SSL::SSLSocket#readpartial doesn't block.
10955 * However, several more complicated situations exist.
10957 * SSL is a protocol which is sequence of records.
10958 * The record consists of multiple bytes.
10959 * So, the remote side of SSL sends a partial record, IO.select
10960 * notifies readability but OpenSSL::SSL::SSLSocket cannot decrypt a
10961 * byte and OpenSSL::SSL::SSLSocket#readpartial will block.
10963 * Also, the remote side can request SSL renegotiation which forces
10964 * the local SSL engine to write some data.
10965 * This means OpenSSL::SSL::SSLSocket#readpartial may invoke #write
10966 * system call and it can block.
10967 * In such a situation, OpenSSL::SSL::SSLSocket#read_nonblock raises
10968 * IO::WaitWritable instead of blocking.
10969 * So, the caller should wait for ready for writability as above
10972 * The combination of non-blocking methods and \IO.select is also useful
10973 * for streams such as tty, pipe socket socket when multiple processes
10974 * read from a stream.
10976 * Finally, Linux kernel developers don't guarantee that
10977 * readability of select(2) means readability of following read(2) even
10978 * for a single process;
10979 * see {select(2)}[https://linux.die.net/man/2/select]
10981 * Invoking \IO.select before IO#readpartial works well as usual.
10982 * However it is not the best way to use \IO.select.
10984 * The writability notified by select(2) doesn't show
10985 * how many bytes are writable.
10986 * IO#write method blocks until given whole string is written.
10987 * So, <tt>IO#write(two or more bytes)</tt> can block after
10988 * writability is notified by \IO.select. IO#write_nonblock is required
10989 * to avoid the blocking.
10991 * Blocking write (#write) can be emulated using #write_nonblock and
10992 * IO.select as follows: IO::WaitReadable should also be rescued for
10993 * SSL renegotiation in OpenSSL::SSL::SSLSocket.
10995 * while 0 < string.bytesize
10997 * written = io_like.write_nonblock(string)
10998 * rescue IO::WaitReadable
10999 * IO.select([io_like])
11001 * rescue IO::WaitWritable
11002 * IO.select(nil, [io_like])
11005 * string = string.byteslice(written..-1)
11013 * # IO.select follows IO#read. Not the best way to use IO.select.
11014 * rs, ws, = IO.select([rp], [wp])
11041 rb_f_select(int argc
, VALUE
*argv
, VALUE obj
)
11043 VALUE scheduler
= rb_fiber_scheduler_current();
11044 if (scheduler
!= Qnil
) {
11045 // It's optionally supported.
11046 VALUE result
= rb_fiber_scheduler_io_selectv(scheduler
, argc
, argv
);
11047 if (!UNDEF_P(result
)) return result
;
11051 struct select_args args
;
11052 struct timeval timerec
;
11055 rb_scan_args(argc
, argv
, "13", &args
.read
, &args
.write
, &args
.except
, &timeout
);
11056 if (NIL_P(timeout
)) {
11060 timerec
= rb_time_interval(timeout
);
11061 args
.timeout
= &timerec
;
11064 for (i
= 0; i
< numberof(args
.fdsets
); ++i
)
11065 rb_fd_init(&args
.fdsets
[i
]);
11067 return rb_ensure(select_call
, (VALUE
)&args
, select_end
, (VALUE
)&args
);
11070 #ifdef IOCTL_REQ_TYPE
11071 typedef IOCTL_REQ_TYPE ioctl_req_t
;
11073 typedef int ioctl_req_t
;
11074 # define NUM2IOCTLREQ(num) ((int)NUM2LONG(num))
11085 nogvl_ioctl(void *ptr
)
11087 struct ioctl_arg
*arg
= ptr
;
11089 return (VALUE
)ioctl(arg
->fd
, arg
->cmd
, arg
->narg
);
11093 do_ioctl(int fd
, ioctl_req_t cmd
, long narg
)
11096 struct ioctl_arg arg
;
11102 retval
= (int)rb_thread_io_blocking_region(nogvl_ioctl
, &arg
, fd
);
11108 #define DEFAULT_IOCTL_NARG_LEN (256)
11110 #if defined(__linux__) && defined(_IOC_SIZE)
11112 linux_iocparm_len(ioctl_req_t cmd
)
11116 if ((cmd
& 0xFFFF0000) == 0) {
11117 /* legacy and unstructured ioctl number. */
11118 return DEFAULT_IOCTL_NARG_LEN
;
11121 len
= _IOC_SIZE(cmd
);
11123 /* paranoia check for silly drivers which don't keep ioctl convention */
11124 if (len
< DEFAULT_IOCTL_NARG_LEN
)
11125 len
= DEFAULT_IOCTL_NARG_LEN
;
11133 ioctl_narg_len(ioctl_req_t cmd
)
11137 #ifdef IOCPARM_MASK
11138 #ifndef IOCPARM_LEN
11139 #define IOCPARM_LEN(x) (((x) >> 16) & IOCPARM_MASK)
11143 len
= IOCPARM_LEN(cmd
); /* on BSDish systems we're safe */
11144 #elif defined(__linux__) && defined(_IOC_SIZE)
11145 len
= linux_iocparm_len(cmd
);
11147 /* otherwise guess at what's safe */
11148 len
= DEFAULT_IOCTL_NARG_LEN
;
11157 typedef long fcntl_arg_t
;
11160 typedef int fcntl_arg_t
;
11164 fcntl_narg_len(ioctl_req_t cmd
)
11171 len
= sizeof(fcntl_arg_t
);
11174 #ifdef F_DUP2FD /* bsd specific */
11179 #ifdef F_DUPFD_CLOEXEC /* linux specific */
11180 case F_DUPFD_CLOEXEC
:
11181 len
= sizeof(fcntl_arg_t
);
11191 len
= sizeof(fcntl_arg_t
);
11201 len
= sizeof(fcntl_arg_t
);
11211 len
= sizeof(fcntl_arg_t
);
11214 #ifdef F_GETOWN_EX /* linux specific */
11216 len
= sizeof(struct f_owner_ex
);
11219 #ifdef F_SETOWN_EX /* linux specific */
11221 len
= sizeof(struct f_owner_ex
);
11226 len
= sizeof(struct flock
);
11231 len
= sizeof(struct flock
);
11236 len
= sizeof(struct flock
);
11239 #ifdef F_READAHEAD /* bsd specific */
11244 #ifdef F_RDAHEAD /* Darwin specific */
11249 #ifdef F_GETSIG /* linux specific */
11254 #ifdef F_SETSIG /* linux specific */
11256 len
= sizeof(fcntl_arg_t
);
11259 #ifdef F_GETLEASE /* linux specific */
11264 #ifdef F_SETLEASE /* linux specific */
11266 len
= sizeof(fcntl_arg_t
);
11269 #ifdef F_NOTIFY /* linux specific */
11271 len
= sizeof(fcntl_arg_t
);
11282 #else /* HAVE_FCNTL */
11284 fcntl_narg_len(ioctl_req_t cmd
)
11288 #endif /* HAVE_FCNTL */
11290 #define NARG_SENTINEL 17
11293 setup_narg(ioctl_req_t cmd
, VALUE
*argp
, long (*narg_len
)(ioctl_req_t
))
11301 else if (FIXNUM_P(arg
)) {
11302 narg
= FIX2LONG(arg
);
11304 else if (arg
== Qtrue
) {
11308 VALUE tmp
= rb_check_string_type(arg
);
11311 narg
= NUM2LONG(arg
);
11318 len
= narg_len(cmd
);
11319 rb_str_modify(arg
);
11321 slen
= RSTRING_LEN(arg
);
11322 /* expand for data + sentinel. */
11323 if (slen
< len
+1) {
11324 rb_str_resize(arg
, len
+1);
11325 MEMZERO(RSTRING_PTR(arg
)+slen
, char, len
-slen
);
11328 /* a little sanity check here */
11329 ptr
= RSTRING_PTR(arg
);
11330 ptr
[slen
- 1] = NARG_SENTINEL
;
11331 narg
= (long)(SIGNED_VALUE
)ptr
;
11339 finish_narg(int retval
, VALUE arg
, const rb_io_t
*fptr
)
11341 if (retval
< 0) rb_sys_fail_path(fptr
->pathv
);
11342 if (RB_TYPE_P(arg
, T_STRING
)) {
11345 RSTRING_GETMEM(arg
, ptr
, slen
);
11346 if (ptr
[slen
-1] != NARG_SENTINEL
)
11347 rb_raise(rb_eArgError
, "return value overflowed string");
11348 ptr
[slen
-1] = '\0';
11351 return INT2NUM(retval
);
11356 rb_ioctl(VALUE io
, VALUE req
, VALUE arg
)
11358 ioctl_req_t cmd
= NUM2IOCTLREQ(req
);
11363 narg
= setup_narg(cmd
, &arg
, ioctl_narg_len
);
11364 GetOpenFile(io
, fptr
);
11365 retval
= do_ioctl(fptr
->fd
, cmd
, narg
);
11366 return finish_narg(retval
, arg
, fptr
);
11371 * ioctl(integer_cmd, argument) -> integer
11373 * Invokes Posix system call {ioctl(2)}[https://linux.die.net/man/2/ioctl],
11374 * which issues a low-level command to an I/O device.
11376 * Issues a low-level command to an I/O device.
11377 * The arguments and returned value are platform-dependent.
11378 * The effect of the call is platform-dependent.
11380 * If argument +argument+ is an integer, it is passed directly;
11381 * if it is a string, it is interpreted as a binary sequence of bytes.
11383 * Not implemented on all platforms.
11388 rb_io_ioctl(int argc
, VALUE
*argv
, VALUE io
)
11392 rb_scan_args(argc
, argv
, "11", &req
, &arg
);
11393 return rb_ioctl(io
, req
, arg
);
11396 #define rb_io_ioctl rb_f_notimplement
11407 nogvl_fcntl(void *ptr
)
11409 struct fcntl_arg
*arg
= ptr
;
11411 #if defined(F_DUPFD)
11412 if (arg
->cmd
== F_DUPFD
)
11413 return (VALUE
)rb_cloexec_fcntl_dupfd(arg
->fd
, (int)arg
->narg
);
11415 return (VALUE
)fcntl(arg
->fd
, arg
->cmd
, arg
->narg
);
11419 do_fcntl(int fd
, int cmd
, long narg
)
11422 struct fcntl_arg arg
;
11428 retval
= (int)rb_thread_io_blocking_region(nogvl_fcntl
, &arg
, fd
);
11429 if (retval
!= -1) {
11431 #if defined(F_DUPFD)
11434 #if defined(F_DUPFD_CLOEXEC)
11435 case F_DUPFD_CLOEXEC
:
11437 rb_update_max_fd(retval
);
11445 rb_fcntl(VALUE io
, VALUE req
, VALUE arg
)
11447 int cmd
= NUM2INT(req
);
11452 narg
= setup_narg(cmd
, &arg
, fcntl_narg_len
);
11453 GetOpenFile(io
, fptr
);
11454 retval
= do_fcntl(fptr
->fd
, cmd
, narg
);
11455 return finish_narg(retval
, arg
, fptr
);
11460 * fcntl(integer_cmd, argument) -> integer
11462 * Invokes Posix system call {fcntl(2)}[https://linux.die.net/man/2/fcntl],
11463 * which provides a mechanism for issuing low-level commands to control or query
11464 * a file-oriented I/O stream. Arguments and results are platform
11467 * If +argument+ is a number, its value is passed directly;
11468 * if it is a string, it is interpreted as a binary sequence of bytes.
11469 * (Array#pack might be a useful way to build this string.)
11471 * Not implemented on all platforms.
11476 rb_io_fcntl(int argc
, VALUE
*argv
, VALUE io
)
11480 rb_scan_args(argc
, argv
, "11", &req
, &arg
);
11481 return rb_fcntl(io
, req
, arg
);
11484 #define rb_io_fcntl rb_f_notimplement
11487 #if defined(HAVE_SYSCALL) || defined(HAVE___SYSCALL)
11490 * syscall(integer_callno, *arguments) -> integer
11492 * Invokes Posix system call {syscall(2)}[https://linux.die.net/man/2/syscall],
11493 * which calls a specified function.
11495 * Calls the operating system function identified by +integer_callno+;
11496 * returns the result of the function or raises SystemCallError if it failed.
11497 * The effect of the call is platform-dependent.
11498 * The arguments and returned value are platform-dependent.
11500 * For each of +arguments+: if it is an integer, it is passed directly;
11501 * if it is a string, it is interpreted as a binary sequence of bytes.
11502 * There may be as many as nine such arguments.
11504 * Arguments +integer_callno+ and +argument+, as well as the returned value,
11505 * are platform-dependent.
11507 * Note: Method +syscall+ is essentially unsafe and unportable.
11508 * The DL (Fiddle) library is preferred for safer and a bit
11509 * more portable programming.
11511 * Not implemented on all platforms.
11516 rb_f_syscall(int argc
, VALUE
*argv
, VALUE _
)
11519 #if SIZEOF_VOIDP == 8 && defined(HAVE___SYSCALL) && SIZEOF_INT != 8 /* mainly *BSD */
11520 # define SYSCALL __syscall
11521 # define NUM2SYSCALLID(x) NUM2LONG(x)
11522 # define RETVAL2NUM(x) LONG2NUM(x)
11523 # if SIZEOF_LONG == 8
11524 long num
, retval
= -1;
11525 # elif SIZEOF_LONG_LONG == 8
11526 long long num
, retval
= -1;
11528 # error ---->> it is asserted that __syscall takes the first argument and returns retval in 64bit signed integer. <<----
11530 #elif defined(__linux__)
11531 # define SYSCALL syscall
11532 # define NUM2SYSCALLID(x) NUM2LONG(x)
11533 # define RETVAL2NUM(x) LONG2NUM(x)
11535 * Linux man page says, syscall(2) function prototype is below.
11537 * int syscall(int number, ...);
11539 * But, it's incorrect. Actual one takes and returned long. (see unistd.h)
11541 long num
, retval
= -1;
11543 # define SYSCALL syscall
11544 # define NUM2SYSCALLID(x) NUM2INT(x)
11545 # define RETVAL2NUM(x) INT2NUM(x)
11546 int num
, retval
= -1;
11550 if (RTEST(ruby_verbose
)) {
11551 rb_category_warning(RB_WARN_CATEGORY_DEPRECATED
,
11552 "We plan to remove a syscall function at future release. DL(Fiddle) provides safer alternative.");
11556 rb_raise(rb_eArgError
, "too few arguments for syscall");
11557 if (argc
> numberof(arg
))
11558 rb_raise(rb_eArgError
, "too many arguments for syscall");
11559 num
= NUM2SYSCALLID(argv
[0]); ++argv
;
11560 for (i
= argc
- 1; i
--; ) {
11561 VALUE v
= rb_check_string_type(argv
[i
]);
11566 arg
[i
] = (VALUE
)StringValueCStr(v
);
11569 arg
[i
] = (VALUE
)NUM2LONG(argv
[i
]);
11575 retval
= SYSCALL(num
);
11578 retval
= SYSCALL(num
, arg
[0]);
11581 retval
= SYSCALL(num
, arg
[0],arg
[1]);
11584 retval
= SYSCALL(num
, arg
[0],arg
[1],arg
[2]);
11587 retval
= SYSCALL(num
, arg
[0],arg
[1],arg
[2],arg
[3]);
11590 retval
= SYSCALL(num
, arg
[0],arg
[1],arg
[2],arg
[3],arg
[4]);
11593 retval
= SYSCALL(num
, arg
[0],arg
[1],arg
[2],arg
[3],arg
[4],arg
[5]);
11596 retval
= SYSCALL(num
, arg
[0],arg
[1],arg
[2],arg
[3],arg
[4],arg
[5],arg
[6]);
11602 return RETVAL2NUM(retval
);
11604 #undef NUM2SYSCALLID
11608 #define rb_f_syscall rb_f_notimplement
11612 io_new_instance(VALUE args
)
11614 return rb_class_new_instance(2, (VALUE
*)args
+1, *(VALUE
*)args
);
11617 static rb_encoding
*
11618 find_encoding(VALUE v
)
11620 rb_encoding
*enc
= rb_find_encoding(v
);
11621 if (!enc
) rb_warn("Unsupported encoding %"PRIsVALUE
" ignored", v
);
11626 io_encoding_set(rb_io_t
*fptr
, VALUE v1
, VALUE v2
, VALUE opt
)
11628 rb_encoding
*enc
, *enc2
;
11629 int ecflags
= fptr
->encs
.ecflags
;
11633 enc2
= find_encoding(v1
);
11634 tmp
= rb_check_string_type(v2
);
11636 if (RSTRING_LEN(tmp
) == 1 && RSTRING_PTR(tmp
)[0] == '-') {
11637 /* Special case - "-" => no transcoding */
11642 enc
= find_encoding(v2
);
11644 /* Special case - "-" => no transcoding */
11649 enc
= find_encoding(v2
);
11651 /* Special case - "-" => no transcoding */
11655 if (enc2
== rb_ascii8bit_encoding()) {
11656 /* If external is ASCII-8BIT, no transcoding */
11660 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2
, ecflags
);
11661 ecflags
= rb_econv_prepare_options(opt
, &ecopts
, ecflags
);
11665 /* Set to default encodings */
11666 rb_io_ext_int_to_encs(NULL
, NULL
, &enc
, &enc2
, 0);
11667 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2
, ecflags
);
11671 tmp
= rb_check_string_type(v1
);
11672 if (!NIL_P(tmp
) && rb_enc_asciicompat(enc
= rb_enc_get(tmp
))) {
11673 parse_mode_enc(RSTRING_PTR(tmp
), enc
, &enc
, &enc2
, NULL
);
11674 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2
, ecflags
);
11675 ecflags
= rb_econv_prepare_options(opt
, &ecopts
, ecflags
);
11678 rb_io_ext_int_to_encs(find_encoding(v1
), NULL
, &enc
, &enc2
, 0);
11679 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2
, ecflags
);
11684 validate_enc_binmode(&fptr
->mode
, ecflags
, enc
, enc2
);
11685 fptr
->encs
.enc
= enc
;
11686 fptr
->encs
.enc2
= enc2
;
11687 fptr
->encs
.ecflags
= ecflags
;
11688 fptr
->encs
.ecopts
= ecopts
;
11689 clear_codeconv(fptr
);
11693 struct io_encoding_set_args
{
11701 io_encoding_set_v(VALUE v
)
11703 struct io_encoding_set_args
*arg
= (struct io_encoding_set_args
*)v
;
11704 io_encoding_set(arg
->fptr
, arg
->v1
, arg
->v2
, arg
->opt
);
11709 pipe_pair_close(VALUE rw
)
11711 VALUE
*rwp
= (VALUE
*)rw
;
11712 return rb_ensure(io_close
, rwp
[0], io_close
, rwp
[1]);
11717 * IO.pipe(**opts) -> [read_io, write_io]
11718 * IO.pipe(enc, **opts) -> [read_io, write_io]
11719 * IO.pipe(ext_enc, int_enc, **opts) -> [read_io, write_io]
11720 * IO.pipe(**opts) {|read_io, write_io| ...} -> object
11721 * IO.pipe(enc, **opts) {|read_io, write_io| ...} -> object
11722 * IO.pipe(ext_enc, int_enc, **opts) {|read_io, write_io| ...} -> object
11724 * Creates a pair of pipe endpoints, +read_io+ and +write_io+,
11725 * connected to each other.
11727 * If argument +enc_string+ is given, it must be a string containing one of:
11729 * - The name of the encoding to be used as the external encoding.
11730 * - The colon-separated names of two encodings to be used as the external
11731 * and internal encodings.
11733 * If argument +int_enc+ is given, it must be an Encoding object
11734 * or encoding name string that specifies the internal encoding to be used;
11735 * if argument +ext_enc+ is also given, it must be an Encoding object
11736 * or encoding name string that specifies the external encoding to be used.
11738 * The string read from +read_io+ is tagged with the external encoding;
11739 * if an internal encoding is also specified, the string is converted
11740 * to, and tagged with, that encoding.
11742 * If any encoding is specified,
11743 * optional hash arguments specify the conversion option.
11745 * Optional keyword arguments +opts+ specify:
11747 * - {Open Options}[rdoc-ref:IO@Open+Options].
11748 * - {Encoding Options}[rdoc-ref:encodings.rdoc@Encoding+Options].
11750 * With no block given, returns the two endpoints in an array:
11752 * IO.pipe # => [#<IO:fd 4>, #<IO:fd 5>]
11754 * With a block given, calls the block with the two endpoints;
11755 * closes both endpoints and returns the value of the block:
11757 * IO.pipe {|read_io, write_io| p read_io; p write_io }
11764 * Not available on all platforms.
11766 * In the example below, the two processes close the ends of the pipe
11767 * that they are not using. This is not just a cosmetic nicety. The
11768 * read end of a pipe will not generate an end of file condition if
11769 * there are any writers with the pipe still open. In the case of the
11770 * parent process, the <tt>rd.read</tt> will never return if it
11771 * does not first issue a <tt>wr.close</tt>:
11777 * puts "Parent got: <#{rd.read}>"
11782 * puts 'Sending message to parent'
11783 * wr.write "Hi Dad"
11787 * <em>produces:</em>
11789 * Sending message to parent
11790 * Parent got: <Hi Dad>
11795 rb_io_s_pipe(int argc
, VALUE
*argv
, VALUE klass
)
11797 int pipes
[2], state
;
11798 VALUE r
, w
, args
[3], v1
, v2
;
11800 rb_io_t
*fptr
, *fptr2
;
11801 struct io_encoding_set_args ies_args
;
11805 argc
= rb_scan_args(argc
, argv
, "02:", &v1
, &v2
, &opt
);
11806 if (rb_pipe(pipes
) < 0)
11810 args
[1] = INT2NUM(pipes
[0]);
11811 args
[2] = INT2FIX(O_RDONLY
);
11812 r
= rb_protect(io_new_instance
, (VALUE
)args
, &state
);
11816 rb_jump_tag(state
);
11818 GetOpenFile(r
, fptr
);
11820 ies_args
.fptr
= fptr
;
11823 ies_args
.opt
= opt
;
11824 rb_protect(io_encoding_set_v
, (VALUE
)&ies_args
, &state
);
11828 rb_jump_tag(state
);
11831 args
[1] = INT2NUM(pipes
[1]);
11832 args
[2] = INT2FIX(O_WRONLY
);
11833 w
= rb_protect(io_new_instance
, (VALUE
)args
, &state
);
11836 if (!NIL_P(r
)) rb_io_close(r
);
11837 rb_jump_tag(state
);
11839 GetOpenFile(w
, fptr2
);
11840 rb_io_synchronized(fptr2
);
11842 extract_binmode(opt
, &fmode
);
11844 if ((fmode
& FMODE_BINMODE
) && NIL_P(v1
)) {
11845 rb_io_ascii8bit_binmode(r
);
11846 rb_io_ascii8bit_binmode(w
);
11849 #if DEFAULT_TEXTMODE
11850 if ((fptr
->mode
& FMODE_TEXTMODE
) && (fmode
& FMODE_BINMODE
)) {
11851 fptr
->mode
&= ~FMODE_TEXTMODE
;
11852 setmode(fptr
->fd
, O_BINARY
);
11854 #if RUBY_CRLF_ENVIRONMENT
11855 if (fptr
->encs
.ecflags
& ECONV_DEFAULT_NEWLINE_DECORATOR
) {
11856 fptr
->encs
.ecflags
|= ECONV_UNIVERSAL_NEWLINE_DECORATOR
;
11860 fptr
->mode
|= fmode
;
11861 #if DEFAULT_TEXTMODE
11862 if ((fptr2
->mode
& FMODE_TEXTMODE
) && (fmode
& FMODE_BINMODE
)) {
11863 fptr2
->mode
&= ~FMODE_TEXTMODE
;
11864 setmode(fptr2
->fd
, O_BINARY
);
11867 fptr2
->mode
|= fmode
;
11869 ret
= rb_assoc_new(r
, w
);
11870 if (rb_block_given_p()) {
11874 return rb_ensure(rb_yield
, ret
, pipe_pair_close
, (VALUE
)rw
);
11879 struct foreach_arg
{
11886 open_key_args(VALUE klass
, int argc
, VALUE
*argv
, VALUE opt
, struct foreach_arg
*arg
)
11889 VALUE vmode
= Qnil
, vperm
= Qnil
;
11893 FilePathValue(path
);
11898 vmode
= INT2NUM(O_RDONLY
);
11899 vperm
= INT2FIX(0666);
11901 else if (!NIL_P(v
= rb_hash_aref(opt
, sym_open_args
))) {
11904 v
= rb_to_array_type(v
);
11905 n
= RARRAY_LENINT(v
);
11906 rb_check_arity(n
, 0, 3); /* rb_io_open */
11907 rb_scan_args_kw(RB_SCAN_ARGS_LAST_HASH_KEYWORDS
, n
, RARRAY_CONST_PTR(v
), "02:", &vmode
, &vperm
, &opt
);
11909 arg
->io
= rb_io_open(klass
, path
, vmode
, vperm
, opt
);
11913 io_s_foreach(VALUE v
)
11915 struct getline_arg
*arg
= (void *)v
;
11918 if (arg
->limit
== 0)
11919 rb_raise(rb_eArgError
, "invalid limit: 0 for foreach");
11920 while (!NIL_P(str
= rb_io_getline_1(arg
->rs
, arg
->limit
, arg
->chomp
, arg
->io
))) {
11921 rb_lastline_set(str
);
11924 rb_lastline_set(Qnil
);
11930 * IO.foreach(path, sep = $/, **opts) {|line| block } -> nil
11931 * IO.foreach(path, limit, **opts) {|line| block } -> nil
11932 * IO.foreach(path, sep, limit, **opts) {|line| block } -> nil
11933 * IO.foreach(...) -> an_enumerator
11935 * Calls the block with each successive line read from the stream.
11937 * When called from class \IO (but not subclasses of \IO),
11938 * this method has potential security vulnerabilities if called with untrusted input;
11939 * see {Command Injection}[rdoc-ref:command_injection.rdoc].
11941 * The first argument must be a string that is the path to a file.
11943 * With only argument +path+ given, parses lines from the file at the given +path+,
11944 * as determined by the default line separator,
11945 * and calls the block with each successive line:
11947 * File.foreach('t.txt') {|line| p line }
11949 * Output: the same as above.
11951 * For both forms, command and path, the remaining arguments are the same.
11953 * With argument +sep+ given, parses lines as determined by that line separator
11954 * (see {Line Separator}[rdoc-ref:IO@Line+Separator]):
11956 * File.foreach('t.txt', 'li') {|line| p line }
11968 * File.foreach('t.txt', '') {|paragraph| p paragraph }
11972 * "First line\nSecond line\n\n"
11973 * "Third line\nFourth line\n"
11975 * With argument +limit+ given, parses lines as determined by the default
11976 * line separator and the given line-length limit
11977 * (see {Line Separator}[rdoc-ref:IO@Line+Separator] and {Line Limit}[rdoc-ref:IO@Line+Limit]):
11979 * File.foreach('t.txt', 7) {|line| p line }
11993 * With arguments +sep+ and +limit+ given,
11994 * combines the two behaviors
11995 * (see {Line Separator and Line Limit}[rdoc-ref:IO@Line+Separator+and+Line+Limit]).
11997 * Optional keyword arguments +opts+ specify:
11999 * - {Open Options}[rdoc-ref:IO@Open+Options].
12000 * - {Encoding options}[rdoc-ref:encodings.rdoc@Encoding+Options].
12001 * - {Line Options}[rdoc-ref:IO@Line+IO].
12003 * Returns an Enumerator if no block is given.
12008 rb_io_s_foreach(int argc
, VALUE
*argv
, VALUE self
)
12011 int orig_argc
= argc
;
12012 struct foreach_arg arg
;
12013 struct getline_arg garg
;
12015 argc
= rb_scan_args(argc
, argv
, "12:", NULL
, NULL
, NULL
, &opt
);
12016 RETURN_ENUMERATOR(self
, orig_argc
, argv
);
12017 extract_getline_args(argc
-1, argv
+1, &garg
);
12018 open_key_args(self
, argc
, argv
, opt
, &arg
);
12019 if (NIL_P(arg
.io
)) return Qnil
;
12020 extract_getline_opts(opt
, &garg
);
12021 check_getline_args(&garg
.rs
, &garg
.limit
, garg
.io
= arg
.io
);
12022 return rb_ensure(io_s_foreach
, (VALUE
)&garg
, rb_io_close
, arg
.io
);
12026 io_s_readlines(VALUE v
)
12028 struct getline_arg
*arg
= (void *)v
;
12029 return io_readlines(arg
, arg
->io
);
12034 * IO.readlines(path, sep = $/, **opts) -> array
12035 * IO.readlines(path, limit, **opts) -> array
12036 * IO.readlines(path, sep, limit, **opts) -> array
12038 * Returns an array of all lines read from the stream.
12040 * When called from class \IO (but not subclasses of \IO),
12041 * this method has potential security vulnerabilities if called with untrusted input;
12042 * see {Command Injection}[rdoc-ref:command_injection.rdoc].
12044 * The first argument must be a string that is the path to a file.
12046 * With only argument +path+ given, parses lines from the file at the given +path+,
12047 * as determined by the default line separator,
12048 * and returns those lines in an array:
12050 * IO.readlines('t.txt')
12051 * # => ["First line\n", "Second line\n", "\n", "Third line\n", "Fourth line\n"]
12053 * With argument +sep+ given, parses lines as determined by that line separator
12054 * (see {Line Separator}[rdoc-ref:IO@Line+Separator]):
12056 * # Ordinary separator.
12057 * IO.readlines('t.txt', 'li')
12058 * # =>["First li", "ne\nSecond li", "ne\n\nThird li", "ne\nFourth li", "ne\n"]
12059 * # Get-paragraphs separator.
12060 * IO.readlines('t.txt', '')
12061 * # => ["First line\nSecond line\n\n", "Third line\nFourth line\n"]
12062 * # Get-all separator.
12063 * IO.readlines('t.txt', nil)
12064 * # => ["First line\nSecond line\n\nThird line\nFourth line\n"]
12066 * With argument +limit+ given, parses lines as determined by the default
12067 * line separator and the given line-length limit
12068 * (see {Line Separator}[rdoc-ref:IO@Line+Separator] and {Line Limit}[rdoc-ref:IO@Line+Limit]:
12070 * IO.readlines('t.txt', 7)
12071 * # => ["First l", "ine\n", "Second ", "line\n", "\n", "Third l", "ine\n", "Fourth ", "line\n"]
12073 * With arguments +sep+ and +limit+ given,
12074 * combines the two behaviors
12075 * (see {Line Separator and Line Limit}[rdoc-ref:IO@Line+Separator+and+Line+Limit]).
12077 * Optional keyword arguments +opts+ specify:
12079 * - {Open Options}[rdoc-ref:IO@Open+Options].
12080 * - {Encoding options}[rdoc-ref:encodings.rdoc@Encoding+Options].
12081 * - {Line Options}[rdoc-ref:IO@Line+IO].
12086 rb_io_s_readlines(int argc
, VALUE
*argv
, VALUE io
)
12089 struct foreach_arg arg
;
12090 struct getline_arg garg
;
12092 argc
= rb_scan_args(argc
, argv
, "12:", NULL
, NULL
, NULL
, &opt
);
12093 extract_getline_args(argc
-1, argv
+1, &garg
);
12094 open_key_args(io
, argc
, argv
, opt
, &arg
);
12095 if (NIL_P(arg
.io
)) return Qnil
;
12096 extract_getline_opts(opt
, &garg
);
12097 check_getline_args(&garg
.rs
, &garg
.limit
, garg
.io
= arg
.io
);
12098 return rb_ensure(io_s_readlines
, (VALUE
)&garg
, rb_io_close
, arg
.io
);
12104 struct foreach_arg
*arg
= (void *)v
;
12105 return io_read(arg
->argc
, arg
->argv
, arg
->io
);
12115 seek_before_access(VALUE argp
)
12117 struct seek_arg
*arg
= (struct seek_arg
*)argp
;
12118 rb_io_binmode(arg
->io
);
12119 return rb_io_seek(arg
->io
, arg
->offset
, arg
->mode
);
12124 * IO.read(path, length = nil, offset = 0, **opts) -> string or nil
12126 * Opens the stream, reads and returns some or all of its content,
12127 * and closes the stream; returns +nil+ if no bytes were read.
12129 * When called from class \IO (but not subclasses of \IO),
12130 * this method has potential security vulnerabilities if called with untrusted input;
12131 * see {Command Injection}[rdoc-ref:command_injection.rdoc].
12133 * The first argument must be a string that is the path to a file.
12135 * With only argument +path+ given, reads in text mode and returns the entire content
12136 * of the file at the given path:
12139 * # => "First line\nSecond line\n\nThird line\nFourth line\n"
12141 * On Windows, text mode can terminate reading and leave bytes in the file
12142 * unread when encountering certain special bytes. Consider using
12143 * IO.binread if all bytes in the file should be read.
12145 * With argument +length+, returns +length+ bytes if available:
12147 * IO.read('t.txt', 7) # => "First l"
12148 * IO.read('t.txt', 700)
12149 * # => "First line\r\nSecond line\r\n\r\nFourth line\r\nFifth line\r\n"
12151 * With arguments +length+ and +offset+, returns +length+ bytes
12152 * if available, beginning at the given +offset+:
12154 * IO.read('t.txt', 10, 2) # => "rst line\nS"
12155 * IO.read('t.txt', 10, 200) # => nil
12157 * Optional keyword arguments +opts+ specify:
12159 * - {Open Options}[rdoc-ref:IO@Open+Options].
12160 * - {Encoding options}[rdoc-ref:encodings.rdoc@Encoding+Options].
12165 rb_io_s_read(int argc
, VALUE
*argv
, VALUE io
)
12169 struct foreach_arg arg
;
12171 argc
= rb_scan_args(argc
, argv
, "13:", NULL
, NULL
, &offset
, NULL
, &opt
);
12172 if (!NIL_P(offset
) && (off
= NUM2LONG(offset
)) < 0) {
12173 rb_raise(rb_eArgError
, "negative offset %ld given", off
);
12175 open_key_args(io
, argc
, argv
, opt
, &arg
);
12176 if (NIL_P(arg
.io
)) return Qnil
;
12177 if (!NIL_P(offset
)) {
12178 struct seek_arg sarg
;
12181 sarg
.offset
= offset
;
12182 sarg
.mode
= SEEK_SET
;
12183 rb_protect(seek_before_access
, (VALUE
)&sarg
, &state
);
12185 rb_io_close(arg
.io
);
12186 rb_jump_tag(state
);
12188 if (arg
.argc
== 2) arg
.argc
= 1;
12190 return rb_ensure(io_s_read
, (VALUE
)&arg
, rb_io_close
, arg
.io
);
12195 * IO.binread(path, length = nil, offset = 0) -> string or nil
12197 * Behaves like IO.read, except that the stream is opened in binary mode
12198 * with ASCII-8BIT encoding.
12200 * When called from class \IO (but not subclasses of \IO),
12201 * this method has potential security vulnerabilities if called with untrusted input;
12202 * see {Command Injection}[rdoc-ref:command_injection.rdoc].
12207 rb_io_s_binread(int argc
, VALUE
*argv
, VALUE io
)
12210 struct foreach_arg arg
;
12212 fmode
= FMODE_READABLE
|FMODE_BINMODE
,
12218 struct rb_io_encoding convconfig
= {NULL
, NULL
, 0, Qnil
};
12220 rb_scan_args(argc
, argv
, "12", NULL
, NULL
, &offset
);
12221 FilePathValue(argv
[0]);
12222 convconfig
.enc
= rb_ascii8bit_encoding();
12223 arg
.io
= rb_io_open_generic(io
, argv
[0], oflags
, fmode
, &convconfig
, 0);
12224 if (NIL_P(arg
.io
)) return Qnil
;
12226 arg
.argc
= (argc
> 1) ? 1 : 0;
12227 if (!NIL_P(offset
)) {
12228 struct seek_arg sarg
;
12231 sarg
.offset
= offset
;
12232 sarg
.mode
= SEEK_SET
;
12233 rb_protect(seek_before_access
, (VALUE
)&sarg
, &state
);
12235 rb_io_close(arg
.io
);
12236 rb_jump_tag(state
);
12239 return rb_ensure(io_s_read
, (VALUE
)&arg
, rb_io_close
, arg
.io
);
12243 io_s_write0(VALUE v
)
12245 struct write_arg
*arg
= (void *)v
;
12246 return io_write(arg
->io
,arg
->str
,arg
->nosync
);
12250 io_s_write(int argc
, VALUE
*argv
, VALUE klass
, int binary
)
12252 VALUE string
, offset
, opt
;
12253 struct foreach_arg arg
;
12254 struct write_arg warg
;
12256 rb_scan_args(argc
, argv
, "21:", NULL
, &string
, &offset
, &opt
);
12258 if (NIL_P(opt
)) opt
= rb_hash_new();
12259 else opt
= rb_hash_dup(opt
);
12262 if (NIL_P(rb_hash_aref(opt
,sym_mode
))) {
12263 int mode
= O_WRONLY
|O_CREAT
;
12265 if (binary
) mode
|= O_BINARY
;
12267 if (NIL_P(offset
)) mode
|= O_TRUNC
;
12268 rb_hash_aset(opt
,sym_mode
,INT2NUM(mode
));
12270 open_key_args(klass
, argc
, argv
, opt
, &arg
);
12273 if (binary
) rb_io_binmode_m(arg
.io
);
12276 if (NIL_P(arg
.io
)) return Qnil
;
12277 if (!NIL_P(offset
)) {
12278 struct seek_arg sarg
;
12281 sarg
.offset
= offset
;
12282 sarg
.mode
= SEEK_SET
;
12283 rb_protect(seek_before_access
, (VALUE
)&sarg
, &state
);
12285 rb_io_close(arg
.io
);
12286 rb_jump_tag(state
);
12294 return rb_ensure(io_s_write0
, (VALUE
)&warg
, rb_io_close
, arg
.io
);
12299 * IO.write(path, data, offset = 0, **opts) -> integer
12301 * Opens the stream, writes the given +data+ to it,
12302 * and closes the stream; returns the number of bytes written.
12304 * When called from class \IO (but not subclasses of \IO),
12305 * this method has potential security vulnerabilities if called with untrusted input;
12306 * see {Command Injection}[rdoc-ref:command_injection.rdoc].
12308 * The first argument must be a string that is the path to a file.
12310 * With only argument +path+ given, writes the given +data+ to the file at that path:
12312 * IO.write('t.tmp', 'abc') # => 3
12313 * File.read('t.tmp') # => "abc"
12315 * If +offset+ is zero (the default), the file is overwritten:
12317 * IO.write('t.tmp', 'A') # => 1
12318 * File.read('t.tmp') # => "A"
12320 * If +offset+ in within the file content, the file is partly overwritten:
12322 * IO.write('t.tmp', 'abcdef') # => 3
12323 * File.read('t.tmp') # => "abcdef"
12324 * # Offset within content.
12325 * IO.write('t.tmp', '012', 2) # => 3
12326 * File.read('t.tmp') # => "ab012f"
12328 * If +offset+ is outside the file content,
12329 * the file is padded with null characters <tt>"\u0000"</tt>:
12331 * IO.write('t.tmp', 'xyz', 10) # => 3
12332 * File.read('t.tmp') # => "ab012f\u0000\u0000\u0000\u0000xyz"
12334 * Optional keyword arguments +opts+ specify:
12336 * - {Open Options}[rdoc-ref:IO@Open+Options].
12337 * - {Encoding options}[rdoc-ref:encodings.rdoc@Encoding+Options].
12342 rb_io_s_write(int argc
, VALUE
*argv
, VALUE io
)
12344 return io_s_write(argc
, argv
, io
, 0);
12349 * IO.binwrite(path, string, offset = 0) -> integer
12351 * Behaves like IO.write, except that the stream is opened in binary mode
12352 * with ASCII-8BIT encoding.
12354 * When called from class \IO (but not subclasses of \IO),
12355 * this method has potential security vulnerabilities if called with untrusted input;
12356 * see {Command Injection}[rdoc-ref:command_injection.rdoc].
12361 rb_io_s_binwrite(int argc
, VALUE
*argv
, VALUE io
)
12363 return io_s_write(argc
, argv
, io
, 1);
12366 struct copy_stream_struct
{
12369 rb_off_t copy_length
; /* (rb_off_t)-1 if not specified */
12370 rb_off_t src_offset
; /* (rb_off_t)-1 if not specified */
12374 unsigned close_src
: 1;
12375 unsigned close_dst
: 1;
12378 const char *syserr
;
12379 const char *notimp
;
12381 struct stat src_stat
;
12382 struct stat dst_stat
;
12383 #ifdef HAVE_FCOPYFILE
12384 copyfile_state_t copyfile_state
;
12389 exec_interrupts(void *arg
)
12391 VALUE th
= (VALUE
)arg
;
12392 rb_thread_execute_interrupts(th
);
12397 * returns TRUE if the preceding system call was interrupted
12398 * so we can continue. If the thread was interrupted, we
12399 * reacquire the GVL to execute interrupts before continuing.
12402 maygvl_copy_stream_continue_p(int has_gvl
, struct copy_stream_struct
*stp
)
12406 #if defined(ERESTART)
12409 if (rb_thread_interrupted(stp
->th
)) {
12411 rb_thread_execute_interrupts(stp
->th
);
12413 rb_thread_call_with_gvl(exec_interrupts
, (void *)stp
->th
);
12420 struct fiber_scheduler_wait_for_arguments
{
12430 fiber_scheduler_wait_for(void * _arguments
)
12432 struct fiber_scheduler_wait_for_arguments
*arguments
= (struct fiber_scheduler_wait_for_arguments
*)_arguments
;
12434 arguments
->result
= rb_fiber_scheduler_io_wait(arguments
->scheduler
, arguments
->fptr
->self
, INT2NUM(arguments
->events
), RUBY_IO_TIMEOUT_DEFAULT
);
12440 # define IOWAIT_SYSCALL "poll"
12441 STATIC_ASSERT(pollin_expected
, POLLIN
== RB_WAITFD_IN
);
12442 STATIC_ASSERT(pollout_expected
, POLLOUT
== RB_WAITFD_OUT
);
12444 nogvl_wait_for(VALUE th
, rb_io_t
*fptr
, short events
, struct timeval
*timeout
)
12446 VALUE scheduler
= rb_fiber_scheduler_current_for_thread(th
);
12447 if (scheduler
!= Qnil
) {
12448 struct fiber_scheduler_wait_for_arguments args
= {.scheduler
= scheduler
, .fptr
= fptr
, .events
= events
};
12449 rb_thread_call_with_gvl(fiber_scheduler_wait_for
, &args
);
12450 return RTEST(args
.result
);
12454 if (fd
== -1) return 0;
12459 fds
.events
= events
;
12461 int timeout_milliseconds
= -1;
12464 timeout_milliseconds
= (int)(timeout
->tv_sec
* 1000) + (int)(timeout
->tv_usec
/ 1000);
12467 return poll(&fds
, 1, timeout_milliseconds
);
12469 #else /* !USE_POLL */
12470 # define IOWAIT_SYSCALL "select"
12472 nogvl_wait_for(VALUE th
, rb_io_t
*fptr
, short events
, struct timeval
*timeout
)
12474 VALUE scheduler
= rb_fiber_scheduler_current_for_thread(th
);
12475 if (scheduler
!= Qnil
) {
12476 struct fiber_scheduler_wait_for_arguments args
= {.scheduler
= scheduler
, .fptr
= fptr
, .events
= events
};
12477 rb_thread_call_with_gvl(fiber_scheduler_wait_for
, &args
);
12478 return RTEST(args
.result
);
12492 rb_fd_set(fd
, &fds
);
12496 ret
= rb_fd_select(fd
+ 1, &fds
, 0, 0, timeout
);
12498 case RB_WAITFD_OUT
:
12499 ret
= rb_fd_select(fd
+ 1, 0, &fds
, 0, timeout
);
12502 VM_UNREACHABLE(nogvl_wait_for
);
12507 // On timeout, this returns 0.
12510 #endif /* !USE_POLL */
12513 maygvl_copy_stream_wait_read(int has_gvl
, struct copy_stream_struct
*stp
)
12519 ret
= RB_NUM2INT(rb_io_wait(stp
->src
, RB_INT2NUM(RUBY_IO_READABLE
), Qnil
));
12522 ret
= nogvl_wait_for(stp
->th
, stp
->src_fptr
, RB_WAITFD_IN
, NULL
);
12524 } while (ret
< 0 && maygvl_copy_stream_continue_p(has_gvl
, stp
));
12527 stp
->syserr
= IOWAIT_SYSCALL
;
12528 stp
->error_no
= errno
;
12535 nogvl_copy_stream_wait_write(struct copy_stream_struct
*stp
)
12540 ret
= nogvl_wait_for(stp
->th
, stp
->dst_fptr
, RB_WAITFD_OUT
, NULL
);
12541 } while (ret
< 0 && maygvl_copy_stream_continue_p(0, stp
));
12544 stp
->syserr
= IOWAIT_SYSCALL
;
12545 stp
->error_no
= errno
;
12551 #ifdef USE_COPY_FILE_RANGE
12554 simple_copy_file_range(int in_fd
, rb_off_t
*in_offset
, int out_fd
, rb_off_t
*out_offset
, size_t count
, unsigned int flags
)
12556 #ifdef HAVE_COPY_FILE_RANGE
12557 return copy_file_range(in_fd
, in_offset
, out_fd
, out_offset
, count
, flags
);
12559 return syscall(__NR_copy_file_range
, in_fd
, in_offset
, out_fd
, out_offset
, count
, flags
);
12564 nogvl_copy_file_range(struct copy_stream_struct
*stp
)
12568 rb_off_t copy_length
, src_offset
, *src_offset_ptr
;
12570 if (!S_ISREG(stp
->src_stat
.st_mode
))
12573 src_size
= stp
->src_stat
.st_size
;
12574 src_offset
= stp
->src_offset
;
12575 if (src_offset
>= (rb_off_t
)0) {
12576 src_offset_ptr
= &src_offset
;
12579 src_offset_ptr
= NULL
; /* if src_offset_ptr is NULL, then bytes are read from in_fd starting from the file offset */
12582 copy_length
= stp
->copy_length
;
12583 if (copy_length
< (rb_off_t
)0) {
12584 if (src_offset
< (rb_off_t
)0) {
12585 rb_off_t current_offset
;
12587 current_offset
= lseek(stp
->src_fptr
->fd
, 0, SEEK_CUR
);
12588 if (current_offset
< (rb_off_t
)0 && errno
) {
12589 stp
->syserr
= "lseek";
12590 stp
->error_no
= errno
;
12591 return (int)current_offset
;
12593 copy_length
= src_size
- current_offset
;
12596 copy_length
= src_size
- src_offset
;
12600 retry_copy_file_range
:
12601 # if SIZEOF_OFF_T > SIZEOF_SIZE_T
12602 /* we are limited by the 32-bit ssize_t return value on 32-bit */
12603 ss
= (copy_length
> (rb_off_t
)SSIZE_MAX
) ? SSIZE_MAX
: (ssize_t
)copy_length
;
12605 ss
= (ssize_t
)copy_length
;
12607 ss
= simple_copy_file_range(stp
->src_fptr
->fd
, src_offset_ptr
, stp
->dst_fptr
->fd
, NULL
, ss
, 0);
12611 if (0 < copy_length
) {
12612 goto retry_copy_file_range
;
12616 if (maygvl_copy_stream_continue_p(0, stp
)) {
12617 goto retry_copy_file_range
;
12621 case EPERM
: /* copy_file_range(2) doesn't exist (may happen in
12622 docker container) */
12627 case EXDEV
: /* in_fd and out_fd are not on the same filesystem */
12631 #if EWOULDBLOCK != EAGAIN
12635 int ret
= nogvl_copy_stream_wait_write(stp
);
12636 if (ret
< 0) return ret
;
12638 goto retry_copy_file_range
;
12642 int flags
= fcntl(stp
->dst_fptr
->fd
, F_GETFL
);
12644 if (flags
!= -1 && flags
& O_APPEND
) {
12650 stp
->syserr
= "copy_file_range";
12651 stp
->error_no
= errno
;
12658 #ifdef HAVE_FCOPYFILE
12660 nogvl_fcopyfile(struct copy_stream_struct
*stp
)
12662 rb_off_t cur
, ss
= 0;
12663 const rb_off_t src_offset
= stp
->src_offset
;
12666 if (stp
->copy_length
>= (rb_off_t
)0) {
12667 /* copy_length can't be specified in fcopyfile(3) */
12671 if (!S_ISREG(stp
->src_stat
.st_mode
))
12674 if (!S_ISREG(stp
->dst_stat
.st_mode
))
12676 if (lseek(stp
->dst_fptr
->fd
, 0, SEEK_CUR
) > (rb_off_t
)0) /* if dst IO was already written */
12678 if (fcntl(stp
->dst_fptr
->fd
, F_GETFL
) & O_APPEND
) {
12679 /* fcopyfile(3) appends src IO to dst IO and then truncates
12680 * dst IO to src IO's original size. */
12681 rb_off_t end
= lseek(stp
->dst_fptr
->fd
, 0, SEEK_END
);
12682 lseek(stp
->dst_fptr
->fd
, 0, SEEK_SET
);
12683 if (end
> (rb_off_t
)0) return 0;
12686 if (src_offset
> (rb_off_t
)0) {
12689 /* get current offset */
12691 cur
= lseek(stp
->src_fptr
->fd
, 0, SEEK_CUR
);
12692 if (cur
< (rb_off_t
)0 && errno
) {
12693 stp
->error_no
= errno
;
12698 r
= lseek(stp
->src_fptr
->fd
, src_offset
, SEEK_SET
);
12699 if (r
< (rb_off_t
)0 && errno
) {
12700 stp
->error_no
= errno
;
12705 stp
->copyfile_state
= copyfile_state_alloc(); /* this will be freed by copy_stream_finalize() */
12706 ret
= fcopyfile(stp
->src_fptr
->fd
, stp
->dst_fptr
->fd
, stp
->copyfile_state
, COPYFILE_DATA
);
12707 copyfile_state_get(stp
->copyfile_state
, COPYFILE_STATE_COPIED
, &ss
); /* get copied bytes */
12709 if (ret
== 0) { /* success */
12711 if (src_offset
> (rb_off_t
)0) {
12715 r
= lseek(stp
->src_fptr
->fd
, cur
, SEEK_SET
);
12716 if (r
< (rb_off_t
)0 && errno
) {
12717 stp
->error_no
= errno
;
12729 stp
->syserr
= "fcopyfile";
12730 stp
->error_no
= errno
;
12737 #ifdef HAVE_SENDFILE
12740 # define USE_SENDFILE
12742 # ifdef HAVE_SYS_SENDFILE_H
12743 # include <sys/sendfile.h>
12747 simple_sendfile(int out_fd
, int in_fd
, rb_off_t
*offset
, rb_off_t count
)
12749 return sendfile(out_fd
, in_fd
, offset
, (size_t)count
);
12752 # elif 0 /* defined(__FreeBSD__) || defined(__DragonFly__) */ || defined(__APPLE__)
12753 /* This runs on FreeBSD8.1 r30210, but sendfiles blocks its execution
12754 * without cpuset -l 0.
12756 # define USE_SENDFILE
12759 simple_sendfile(int out_fd
, int in_fd
, rb_off_t
*offset
, rb_off_t count
)
12762 rb_off_t pos
= offset
? *offset
: lseek(in_fd
, 0, SEEK_CUR
);
12765 r
= sendfile(in_fd
, out_fd
, pos
, &count
, NULL
, 0);
12768 r
= sendfile(in_fd
, out_fd
, pos
, (size_t)count
, NULL
, &sbytes
, 0);
12770 if (r
!= 0 && sbytes
== 0) return r
;
12775 lseek(in_fd
, sbytes
, SEEK_CUR
);
12777 return (ssize_t
)sbytes
;
12784 #ifdef USE_SENDFILE
12786 nogvl_copy_stream_sendfile(struct copy_stream_struct
*stp
)
12790 rb_off_t copy_length
;
12791 rb_off_t src_offset
;
12794 if (!S_ISREG(stp
->src_stat
.st_mode
))
12797 src_size
= stp
->src_stat
.st_size
;
12799 if ((stp
->dst_stat
.st_mode
& S_IFMT
) != S_IFSOCK
)
12803 src_offset
= stp
->src_offset
;
12804 use_pread
= src_offset
>= (rb_off_t
)0;
12806 copy_length
= stp
->copy_length
;
12807 if (copy_length
< (rb_off_t
)0) {
12809 copy_length
= src_size
- src_offset
;
12813 cur
= lseek(stp
->src_fptr
->fd
, 0, SEEK_CUR
);
12814 if (cur
< (rb_off_t
)0 && errno
) {
12815 stp
->syserr
= "lseek";
12816 stp
->error_no
= errno
;
12819 copy_length
= src_size
- cur
;
12824 # if SIZEOF_OFF_T > SIZEOF_SIZE_T
12825 /* we are limited by the 32-bit ssize_t return value on 32-bit */
12826 ss
= (copy_length
> (rb_off_t
)SSIZE_MAX
) ? SSIZE_MAX
: (ssize_t
)copy_length
;
12828 ss
= (ssize_t
)copy_length
;
12831 ss
= simple_sendfile(stp
->dst_fptr
->fd
, stp
->src_fptr
->fd
, &src_offset
, ss
);
12834 ss
= simple_sendfile(stp
->dst_fptr
->fd
, stp
->src_fptr
->fd
, NULL
, ss
);
12839 if (0 < copy_length
) {
12840 goto retry_sendfile
;
12844 if (maygvl_copy_stream_continue_p(0, stp
))
12845 goto retry_sendfile
;
12852 /* some RedHat kernels may return EOPNOTSUP on an NFS mount.
12853 see also: [Feature #16965] */
12858 #if EWOULDBLOCK != EAGAIN
12865 * Linux requires stp->src_fptr->fd to be a mmap-able (regular) file,
12866 * select() reports regular files to always be "ready", so
12867 * there is no need to select() on it.
12868 * Other OSes may have the same limitation for sendfile() which
12869 * allow us to bypass maygvl_copy_stream_wait_read()...
12871 ret
= maygvl_copy_stream_wait_read(0, stp
);
12872 if (ret
< 0) return ret
;
12874 ret
= nogvl_copy_stream_wait_write(stp
);
12875 if (ret
< 0) return ret
;
12877 goto retry_sendfile
;
12879 stp
->syserr
= "sendfile";
12880 stp
->error_no
= errno
;
12888 maygvl_read(int has_gvl
, rb_io_t
*fptr
, void *buf
, size_t count
)
12891 return rb_io_read_memory(fptr
, buf
, count
);
12893 return read(fptr
->fd
, buf
, count
);
12897 maygvl_copy_stream_read(int has_gvl
, struct copy_stream_struct
*stp
, char *buf
, size_t len
, rb_off_t offset
)
12901 if (offset
< (rb_off_t
)0) {
12902 ss
= maygvl_read(has_gvl
, stp
->src_fptr
, buf
, len
);
12905 ss
= pread(stp
->src_fptr
->fd
, buf
, len
, offset
);
12911 if (maygvl_copy_stream_continue_p(has_gvl
, stp
))
12915 #if EWOULDBLOCK != EAGAIN
12919 int ret
= maygvl_copy_stream_wait_read(has_gvl
, stp
);
12920 if (ret
< 0) return ret
;
12925 stp
->notimp
= "pread";
12929 stp
->syserr
= offset
< (rb_off_t
)0 ? "read" : "pread";
12930 stp
->error_no
= errno
;
12936 nogvl_copy_stream_write(struct copy_stream_struct
*stp
, char *buf
, size_t len
)
12941 ss
= write(stp
->dst_fptr
->fd
, buf
+off
, len
);
12943 if (maygvl_copy_stream_continue_p(0, stp
))
12945 if (io_again_p(errno
)) {
12946 int ret
= nogvl_copy_stream_wait_write(stp
);
12947 if (ret
< 0) return ret
;
12950 stp
->syserr
= "write";
12951 stp
->error_no
= errno
;
12962 nogvl_copy_stream_read_write(struct copy_stream_struct
*stp
)
12968 rb_off_t copy_length
;
12969 rb_off_t src_offset
;
12973 copy_length
= stp
->copy_length
;
12974 use_eof
= copy_length
< (rb_off_t
)0;
12975 src_offset
= stp
->src_offset
;
12976 use_pread
= src_offset
>= (rb_off_t
)0;
12978 if (use_pread
&& stp
->close_src
) {
12981 r
= lseek(stp
->src_fptr
->fd
, src_offset
, SEEK_SET
);
12982 if (r
< (rb_off_t
)0 && errno
) {
12983 stp
->syserr
= "lseek";
12984 stp
->error_no
= errno
;
12987 src_offset
= (rb_off_t
)-1;
12991 while (use_eof
|| 0 < copy_length
) {
12992 if (!use_eof
&& copy_length
< (rb_off_t
)sizeof(buf
)) {
12993 len
= (size_t)copy_length
;
12999 ss
= maygvl_copy_stream_read(0, stp
, buf
, len
, src_offset
);
13004 ss
= maygvl_copy_stream_read(0, stp
, buf
, len
, (rb_off_t
)-1);
13006 if (ss
<= 0) /* EOF or error */
13009 ret
= nogvl_copy_stream_write(stp
, buf
, ss
);
13019 nogvl_copy_stream_func(void *arg
)
13021 struct copy_stream_struct
*stp
= (struct copy_stream_struct
*)arg
;
13022 #if defined(USE_SENDFILE) || defined(USE_COPY_FILE_RANGE) || defined(HAVE_FCOPYFILE)
13026 #ifdef USE_COPY_FILE_RANGE
13027 ret
= nogvl_copy_file_range(stp
);
13029 goto finish
; /* error or success */
13032 #ifdef HAVE_FCOPYFILE
13033 ret
= nogvl_fcopyfile(stp
);
13035 goto finish
; /* error or success */
13038 #ifdef USE_SENDFILE
13039 ret
= nogvl_copy_stream_sendfile(stp
);
13041 goto finish
; /* error or success */
13044 nogvl_copy_stream_read_write(stp
);
13046 #if defined(USE_SENDFILE) || defined(USE_COPY_FILE_RANGE) || defined(HAVE_FCOPYFILE)
13053 copy_stream_fallback_body(VALUE arg
)
13055 struct copy_stream_struct
*stp
= (struct copy_stream_struct
*)arg
;
13056 const int buflen
= 16*1024;
13058 VALUE buf
= rb_str_buf_new(buflen
);
13059 rb_off_t rest
= stp
->copy_length
;
13060 rb_off_t off
= stp
->src_offset
;
13061 ID read_method
= id_readpartial
;
13063 if (!stp
->src_fptr
) {
13064 if (!rb_respond_to(stp
->src
, read_method
)) {
13065 read_method
= id_read
;
13072 if (stp
->copy_length
< (rb_off_t
)0) {
13077 rb_str_resize(buf
, 0);
13080 l
= buflen
< rest
? buflen
: (long)rest
;
13082 if (!stp
->src_fptr
) {
13083 VALUE rc
= rb_funcall(stp
->src
, read_method
, 2, INT2FIX(l
), buf
);
13085 if (read_method
== id_read
&& NIL_P(rc
))
13090 rb_str_resize(buf
, buflen
);
13091 ss
= maygvl_copy_stream_read(1, stp
, RSTRING_PTR(buf
), l
, off
);
13092 rb_str_resize(buf
, ss
> 0 ? ss
: 0);
13097 if (off
>= (rb_off_t
)0)
13100 n
= rb_io_write(stp
->dst
, buf
);
13101 numwrote
= NUM2LONG(n
);
13102 stp
->total
+= numwrote
;
13104 if (read_method
== id_read
&& RSTRING_LEN(buf
) == 0) {
13113 copy_stream_fallback(struct copy_stream_struct
*stp
)
13115 if (!stp
->src_fptr
&& stp
->src_offset
>= (rb_off_t
)0) {
13116 rb_raise(rb_eArgError
, "cannot specify src_offset for non-IO");
13118 rb_rescue2(copy_stream_fallback_body
, (VALUE
)stp
,
13119 (VALUE (*) (VALUE
, VALUE
))0, (VALUE
)0,
13120 rb_eEOFError
, (VALUE
)0);
13125 copy_stream_body(VALUE arg
)
13127 struct copy_stream_struct
*stp
= (struct copy_stream_struct
*)arg
;
13128 VALUE src_io
= stp
->src
, dst_io
= stp
->dst
;
13129 const int common_oflags
= 0
13135 stp
->th
= rb_thread_current();
13139 if (src_io
== argf
||
13140 !(RB_TYPE_P(src_io
, T_FILE
) ||
13141 RB_TYPE_P(src_io
, T_STRING
) ||
13142 rb_respond_to(src_io
, rb_intern("to_path")))) {
13143 stp
->src_fptr
= NULL
;
13147 VALUE tmp_io
= rb_io_check_io(src_io
);
13148 if (!NIL_P(tmp_io
)) {
13151 else if (!RB_TYPE_P(src_io
, T_FILE
)) {
13153 FilePathValue(src_io
);
13155 args
[1] = INT2NUM(O_RDONLY
|common_oflags
);
13156 src_io
= rb_class_new_instance(2, args
, rb_cFile
);
13158 stp
->close_src
= 1;
13160 RB_IO_POINTER(src_io
, stp
->src_fptr
);
13161 rb_io_check_byte_readable(stp
->src_fptr
);
13163 stat_ret
= fstat(stp
->src_fptr
->fd
, &stp
->src_stat
);
13164 if (stat_ret
< 0) {
13165 stp
->syserr
= "fstat";
13166 stp
->error_no
= errno
;
13171 if (dst_io
== argf
||
13172 !(RB_TYPE_P(dst_io
, T_FILE
) ||
13173 RB_TYPE_P(dst_io
, T_STRING
) ||
13174 rb_respond_to(dst_io
, rb_intern("to_path")))) {
13175 stp
->dst_fptr
= NULL
;
13179 VALUE tmp_io
= rb_io_check_io(dst_io
);
13180 if (!NIL_P(tmp_io
)) {
13181 dst_io
= GetWriteIO(tmp_io
);
13183 else if (!RB_TYPE_P(dst_io
, T_FILE
)) {
13185 FilePathValue(dst_io
);
13187 args
[1] = INT2NUM(O_WRONLY
|O_CREAT
|O_TRUNC
|common_oflags
);
13188 args
[2] = INT2FIX(0666);
13189 dst_io
= rb_class_new_instance(3, args
, rb_cFile
);
13191 stp
->close_dst
= 1;
13194 dst_io
= GetWriteIO(dst_io
);
13197 RB_IO_POINTER(dst_io
, stp
->dst_fptr
);
13198 rb_io_check_writable(stp
->dst_fptr
);
13200 stat_ret
= fstat(stp
->dst_fptr
->fd
, &stp
->dst_stat
);
13201 if (stat_ret
< 0) {
13202 stp
->syserr
= "fstat";
13203 stp
->error_no
= errno
;
13210 SET_BINARY_MODE_WITH_SEEK_CUR(stp
->src_fptr
);
13213 io_ascii8bit_binmode(stp
->dst_fptr
);
13215 if (stp
->src_offset
< (rb_off_t
)0 && stp
->src_fptr
&& stp
->src_fptr
->rbuf
.len
) {
13216 size_t len
= stp
->src_fptr
->rbuf
.len
;
13218 if (stp
->copy_length
>= (rb_off_t
)0 && stp
->copy_length
< (rb_off_t
)len
) {
13219 len
= (size_t)stp
->copy_length
;
13221 str
= rb_str_buf_new(len
);
13222 rb_str_resize(str
,len
);
13223 read_buffered_data(RSTRING_PTR(str
), len
, stp
->src_fptr
);
13224 if (stp
->dst_fptr
) { /* IO or filename */
13225 if (io_binwrite(RSTRING_PTR(str
), RSTRING_LEN(str
), stp
->dst_fptr
, 0) < 0)
13226 rb_sys_fail_on_write(stp
->dst_fptr
);
13228 else /* others such as StringIO */
13229 rb_io_write(dst_io
, str
);
13230 rb_str_resize(str
, 0);
13232 if (stp
->copy_length
>= (rb_off_t
)0)
13233 stp
->copy_length
-= len
;
13236 if (stp
->dst_fptr
&& io_fflush(stp
->dst_fptr
) < 0) {
13237 rb_raise(rb_eIOError
, "flush failed");
13240 if (stp
->copy_length
== 0)
13243 if (stp
->src_fptr
== NULL
|| stp
->dst_fptr
== NULL
) {
13244 return copy_stream_fallback(stp
);
13247 IO_WITHOUT_GVL(nogvl_copy_stream_func
, stp
);
13252 copy_stream_finalize(VALUE arg
)
13254 struct copy_stream_struct
*stp
= (struct copy_stream_struct
*)arg
;
13256 #ifdef HAVE_FCOPYFILE
13257 if (stp
->copyfile_state
) {
13258 copyfile_state_free(stp
->copyfile_state
);
13262 if (stp
->close_src
) {
13263 rb_io_close_m(stp
->src
);
13265 if (stp
->close_dst
) {
13266 rb_io_close_m(stp
->dst
);
13269 rb_syserr_fail(stp
->error_no
, stp
->syserr
);
13272 rb_raise(rb_eNotImpError
, "%s() not implemented", stp
->notimp
);
13279 * IO.copy_stream(src, dst, src_length = nil, src_offset = 0) -> integer
13281 * Copies from the given +src+ to the given +dst+,
13282 * returning the number of bytes copied.
13284 * - The given +src+ must be one of the following:
13286 * - The path to a readable file, from which source data is to be read.
13287 * - An \IO-like object, opened for reading and capable of responding
13288 * to method +:readpartial+ or method +:read+.
13290 * - The given +dst+ must be one of the following:
13292 * - The path to a writable file, to which data is to be written.
13293 * - An \IO-like object, opened for writing and capable of responding
13294 * to method +:write+.
13296 * The examples here use file <tt>t.txt</tt> as source:
13298 * File.read('t.txt')
13299 * # => "First line\nSecond line\n\nThird line\nFourth line\n"
13300 * File.read('t.txt').size # => 47
13302 * If only arguments +src+ and +dst+ are given,
13303 * the entire source stream is copied:
13306 * IO.copy_stream('t.txt', 't.tmp') # => 47
13308 * # IOs (recall that a File is also an IO).
13309 * src_io = File.open('t.txt', 'r') # => #<File:t.txt>
13310 * dst_io = File.open('t.tmp', 'w') # => #<File:t.tmp>
13311 * IO.copy_stream(src_io, dst_io) # => 47
13315 * With argument +src_length+ a non-negative integer,
13316 * no more than that many bytes are copied:
13318 * IO.copy_stream('t.txt', 't.tmp', 10) # => 10
13319 * File.read('t.tmp') # => "First line"
13321 * With argument +src_offset+ also given,
13322 * the source stream is read beginning at that offset:
13324 * IO.copy_stream('t.txt', 't.tmp', 11, 11) # => 11
13325 * IO.read('t.tmp') # => "Second line"
13329 rb_io_s_copy_stream(int argc
, VALUE
*argv
, VALUE io
)
13331 VALUE src
, dst
, length
, src_offset
;
13332 struct copy_stream_struct st
;
13334 MEMZERO(&st
, struct copy_stream_struct
, 1);
13336 rb_scan_args(argc
, argv
, "22", &src
, &dst
, &length
, &src_offset
);
13341 st
.src_fptr
= NULL
;
13342 st
.dst_fptr
= NULL
;
13345 st
.copy_length
= (rb_off_t
)-1;
13347 st
.copy_length
= NUM2OFFT(length
);
13349 if (NIL_P(src_offset
))
13350 st
.src_offset
= (rb_off_t
)-1;
13352 st
.src_offset
= NUM2OFFT(src_offset
);
13354 rb_ensure(copy_stream_body
, (VALUE
)&st
, copy_stream_finalize
, (VALUE
)&st
);
13356 return OFFT2NUM(st
.total
);
13361 * external_encoding -> encoding or nil
13363 * Returns the Encoding object that represents the encoding of the stream,
13364 * or +nil+ if the stream is in write mode and no encoding is specified.
13366 * See {Encodings}[rdoc-ref:File@Encodings].
13371 rb_io_external_encoding(VALUE io
)
13373 rb_io_t
*fptr
= RFILE(rb_io_taint_check(io
))->fptr
;
13375 if (fptr
->encs
.enc2
) {
13376 return rb_enc_from_encoding(fptr
->encs
.enc2
);
13378 if (fptr
->mode
& FMODE_WRITABLE
) {
13379 if (fptr
->encs
.enc
)
13380 return rb_enc_from_encoding(fptr
->encs
.enc
);
13383 return rb_enc_from_encoding(io_read_encoding(fptr
));
13388 * internal_encoding -> encoding or nil
13390 * Returns the Encoding object that represents the encoding of the internal string,
13391 * if conversion is specified,
13392 * or +nil+ otherwise.
13394 * See {Encodings}[rdoc-ref:File@Encodings].
13399 rb_io_internal_encoding(VALUE io
)
13401 rb_io_t
*fptr
= RFILE(rb_io_taint_check(io
))->fptr
;
13403 if (!fptr
->encs
.enc2
) return Qnil
;
13404 return rb_enc_from_encoding(io_read_encoding(fptr
));
13409 * set_encoding(ext_enc) -> self
13410 * set_encoding(ext_enc, int_enc, **enc_opts) -> self
13411 * set_encoding('ext_enc:int_enc', **enc_opts) -> self
13413 * See {Encodings}[rdoc-ref:File@Encodings].
13415 * Argument +ext_enc+, if given, must be an Encoding object
13416 * or a String with the encoding name;
13417 * it is assigned as the encoding for the stream.
13419 * Argument +int_enc+, if given, must be an Encoding object
13420 * or a String with the encoding name;
13421 * it is assigned as the encoding for the internal string.
13423 * Argument <tt>'ext_enc:int_enc'</tt>, if given, is a string
13424 * containing two colon-separated encoding names;
13425 * corresponding Encoding objects are assigned as the external
13426 * and internal encodings for the stream.
13428 * If the external encoding of a string is binary/ASCII-8BIT,
13429 * the internal encoding of the string is set to nil, since no
13430 * transcoding is needed.
13432 * Optional keyword arguments +enc_opts+ specify
13433 * {Encoding options}[rdoc-ref:encodings.rdoc@Encoding+Options].
13438 rb_io_set_encoding(int argc
, VALUE
*argv
, VALUE io
)
13443 if (!RB_TYPE_P(io
, T_FILE
)) {
13444 return forward(io
, id_set_encoding
, argc
, argv
);
13447 argc
= rb_scan_args(argc
, argv
, "11:", &v1
, &v2
, &opt
);
13448 GetOpenFile(io
, fptr
);
13449 io_encoding_set(fptr
, v1
, v2
, opt
);
13454 rb_stdio_set_default_encoding(void)
13459 if (isatty(fileno(stdin
))) {
13460 rb_encoding
*external
= rb_locale_encoding();
13461 rb_encoding
*internal
= rb_default_internal_encoding();
13462 if (!internal
) internal
= rb_default_external_encoding();
13463 io_encoding_set(RFILE(rb_stdin
)->fptr
,
13464 rb_enc_from_encoding(external
),
13465 rb_enc_from_encoding(internal
),
13470 rb_io_set_encoding(1, &val
, rb_stdin
);
13471 rb_io_set_encoding(1, &val
, rb_stdout
);
13472 rb_io_set_encoding(1, &val
, rb_stderr
);
13476 global_argf_p(VALUE arg
)
13478 return arg
== argf
;
13481 typedef VALUE (*argf_encoding_func
)(VALUE io
);
13484 argf_encoding(VALUE argf
, argf_encoding_func func
)
13486 if (!RTEST(ARGF
.current_file
)) {
13487 return rb_enc_default_external();
13489 return func(rb_io_check_io(ARGF
.current_file
));
13494 * ARGF.external_encoding -> encoding
13496 * Returns the external encoding for files read from ARGF as an Encoding
13497 * object. The external encoding is the encoding of the text as stored in a
13498 * file. Contrast with ARGF.internal_encoding, which is the encoding used to
13499 * represent this text within Ruby.
13501 * To set the external encoding use ARGF.set_encoding.
13505 * ARGF.external_encoding #=> #<Encoding:UTF-8>
13509 argf_external_encoding(VALUE argf
)
13511 return argf_encoding(argf
, rb_io_external_encoding
);
13516 * ARGF.internal_encoding -> encoding
13518 * Returns the internal encoding for strings read from ARGF as an
13521 * If ARGF.set_encoding has been called with two encoding names, the second
13522 * is returned. Otherwise, if +Encoding.default_external+ has been set, that
13523 * value is returned. Failing that, if a default external encoding was
13524 * specified on the command-line, that value is used. If the encoding is
13525 * unknown, +nil+ is returned.
13528 argf_internal_encoding(VALUE argf
)
13530 return argf_encoding(argf
, rb_io_internal_encoding
);
13535 * ARGF.set_encoding(ext_enc) -> ARGF
13536 * ARGF.set_encoding("ext_enc:int_enc") -> ARGF
13537 * ARGF.set_encoding(ext_enc, int_enc) -> ARGF
13538 * ARGF.set_encoding("ext_enc:int_enc", opt) -> ARGF
13539 * ARGF.set_encoding(ext_enc, int_enc, opt) -> ARGF
13541 * If single argument is specified, strings read from ARGF are tagged with
13542 * the encoding specified.
13544 * If two encoding names separated by a colon are given, e.g. "ascii:utf-8",
13545 * the read string is converted from the first encoding (external encoding)
13546 * to the second encoding (internal encoding), then tagged with the second
13549 * If two arguments are specified, they must be encoding objects or encoding
13550 * names. Again, the first specifies the external encoding; the second
13551 * specifies the internal encoding.
13553 * If the external encoding and the internal encoding are specified, the
13554 * optional Hash argument can be used to adjust the conversion process. The
13555 * structure of this hash is explained in the String#encode documentation.
13559 * ARGF.set_encoding('ascii') # Tag the input as US-ASCII text
13560 * ARGF.set_encoding(Encoding::UTF_8) # Tag the input as UTF-8 text
13561 * ARGF.set_encoding('utf-8','ascii') # Transcode the input from US-ASCII
13565 argf_set_encoding(int argc
, VALUE
*argv
, VALUE argf
)
13569 if (!next_argv()) {
13570 rb_raise(rb_eArgError
, "no stream to set encoding");
13572 rb_io_set_encoding(argc
, argv
, ARGF
.current_file
);
13573 GetOpenFile(ARGF
.current_file
, fptr
);
13574 ARGF
.encs
= fptr
->encs
;
13580 * ARGF.tell -> Integer
13581 * ARGF.pos -> Integer
13583 * Returns the current offset (in bytes) of the current file in ARGF.
13586 * ARGF.gets #=> "This is line one\n"
13591 argf_tell(VALUE argf
)
13593 if (!next_argv()) {
13594 rb_raise(rb_eArgError
, "no stream to tell");
13596 ARGF_FORWARD(0, 0);
13597 return rb_io_tell(ARGF
.current_file
);
13602 * ARGF.seek(amount, whence=IO::SEEK_SET) -> 0
13604 * Seeks to offset _amount_ (an Integer) in the ARGF stream according to
13605 * the value of _whence_. See IO#seek for further details.
13608 argf_seek_m(int argc
, VALUE
*argv
, VALUE argf
)
13610 if (!next_argv()) {
13611 rb_raise(rb_eArgError
, "no stream to seek");
13613 ARGF_FORWARD(argc
, argv
);
13614 return rb_io_seek_m(argc
, argv
, ARGF
.current_file
);
13619 * ARGF.pos = position -> Integer
13621 * Seeks to the position given by _position_ (in bytes) in ARGF.
13626 * ARGF.gets #=> "This is line two\n"
13629 argf_set_pos(VALUE argf
, VALUE offset
)
13631 if (!next_argv()) {
13632 rb_raise(rb_eArgError
, "no stream to set position");
13634 ARGF_FORWARD(1, &offset
);
13635 return rb_io_set_pos(ARGF
.current_file
, offset
);
13642 * Positions the current file to the beginning of input, resetting
13643 * ARGF.lineno to zero.
13645 * ARGF.readline #=> "This is line one\n"
13646 * ARGF.rewind #=> 0
13647 * ARGF.lineno #=> 0
13648 * ARGF.readline #=> "This is line one\n"
13651 argf_rewind(VALUE argf
)
13656 if (!next_argv()) {
13657 rb_raise(rb_eArgError
, "no stream to rewind");
13659 ARGF_FORWARD(0, 0);
13660 old_lineno
= RFILE(ARGF
.current_file
)->fptr
->lineno
;
13661 ret
= rb_io_rewind(ARGF
.current_file
);
13662 if (!global_argf_p(argf
)) {
13663 ARGF
.last_lineno
= ARGF
.lineno
-= old_lineno
;
13670 * ARGF.fileno -> integer
13671 * ARGF.to_i -> integer
13673 * Returns an integer representing the numeric file descriptor for
13674 * the current file. Raises an ArgumentError if there isn't a current file.
13676 * ARGF.fileno #=> 3
13679 argf_fileno(VALUE argf
)
13681 if (!next_argv()) {
13682 rb_raise(rb_eArgError
, "no stream");
13684 ARGF_FORWARD(0, 0);
13685 return rb_io_fileno(ARGF
.current_file
);
13692 * Returns an IO object representing the current file. This will be a
13693 * File object unless the current file is a stream such as STDIN.
13697 * ARGF.to_io #=> #<File:glark.txt>
13698 * ARGF.to_io #=> #<IO:<STDIN>>
13701 argf_to_io(VALUE argf
)
13704 ARGF_FORWARD(0, 0);
13705 return ARGF
.current_file
;
13710 * ARGF.eof? -> true or false
13711 * ARGF.eof -> true or false
13713 * Returns true if the current file in ARGF is at end of file, i.e. it has
13714 * no data to read. The stream must be opened for reading or an IOError
13717 * $ echo "eof" | ruby argf.rb
13719 * ARGF.eof? #=> false
13720 * 3.times { ARGF.readchar }
13721 * ARGF.eof? #=> false
13722 * ARGF.readchar #=> "\n"
13723 * ARGF.eof? #=> true
13727 argf_eof(VALUE argf
)
13730 if (RTEST(ARGF
.current_file
)) {
13731 if (ARGF
.init_p
== 0) return Qtrue
;
13733 ARGF_FORWARD(0, 0);
13734 if (rb_io_eof(ARGF
.current_file
)) {
13743 * ARGF.read([length [, outbuf]]) -> string, outbuf, or nil
13745 * Reads _length_ bytes from ARGF. The files named on the command line
13746 * are concatenated and treated as a single file by this method, so when
13747 * called without arguments the contents of this pseudo file are returned in
13750 * _length_ must be a non-negative integer or +nil+.
13752 * If _length_ is a positive integer, +read+ tries to read
13753 * _length_ bytes without any conversion (binary mode).
13754 * It returns +nil+ if an EOF is encountered before anything can be read.
13755 * Fewer than _length_ bytes are returned if an EOF is encountered during
13757 * In the case of an integer _length_, the resulting string is always
13758 * in ASCII-8BIT encoding.
13760 * If _length_ is omitted or is +nil+, it reads until EOF
13761 * and the encoding conversion is applied, if applicable.
13762 * A string is returned even if EOF is encountered before any data is read.
13764 * If _length_ is zero, it returns an empty string (<code>""</code>).
13766 * If the optional _outbuf_ argument is present,
13767 * it must reference a String, which will receive the data.
13768 * The _outbuf_ will contain only the received data after the method call
13769 * even if it is not empty at the beginning.
13773 * $ echo "small" > small.txt
13774 * $ echo "large" > large.txt
13775 * $ ./glark.rb small.txt large.txt
13777 * ARGF.read #=> "small\nlarge"
13778 * ARGF.read(200) #=> "small\nlarge"
13779 * ARGF.read(2) #=> "sm"
13780 * ARGF.read(0) #=> ""
13782 * Note that this method behaves like the fread() function in C.
13783 * This means it retries to invoke read(2) system calls to read data
13784 * with the specified length.
13785 * If you need the behavior like a single read(2) system call,
13786 * consider ARGF#readpartial or ARGF#read_nonblock.
13790 argf_read(int argc
, VALUE
*argv
, VALUE argf
)
13792 VALUE tmp
, str
, length
;
13795 rb_scan_args(argc
, argv
, "02", &length
, &str
);
13796 if (!NIL_P(length
)) {
13797 len
= NUM2LONG(argv
[0]);
13801 rb_str_resize(str
,0);
13806 if (!next_argv()) {
13809 if (ARGF_GENERIC_INPUT_P()) {
13810 tmp
= argf_forward(argc
, argv
, argf
);
13813 tmp
= io_read(argc
, argv
, ARGF
.current_file
);
13815 if (NIL_P(str
)) str
= tmp
;
13816 else if (!NIL_P(tmp
)) rb_str_append(str
, tmp
);
13817 if (NIL_P(tmp
) || NIL_P(length
)) {
13818 if (ARGF
.next_p
!= -1) {
13824 else if (argc
>= 1) {
13825 long slen
= RSTRING_LEN(str
);
13827 argv
[0] = LONG2NUM(len
- slen
);
13834 struct argf_call_arg
{
13841 argf_forward_call(VALUE arg
)
13843 struct argf_call_arg
*p
= (struct argf_call_arg
*)arg
;
13844 argf_forward(p
->argc
, p
->argv
, p
->argf
);
13848 static VALUE
argf_getpartial(int argc
, VALUE
*argv
, VALUE argf
, VALUE opts
,
13853 * ARGF.readpartial(maxlen) -> string
13854 * ARGF.readpartial(maxlen, outbuf) -> outbuf
13856 * Reads at most _maxlen_ bytes from the ARGF stream.
13858 * If the optional _outbuf_ argument is present,
13859 * it must reference a String, which will receive the data.
13860 * The _outbuf_ will contain only the received data after the method call
13861 * even if it is not empty at the beginning.
13863 * It raises EOFError on end of ARGF stream.
13864 * Since ARGF stream is a concatenation of multiple files,
13865 * internally EOF is occur for each file.
13866 * ARGF.readpartial returns empty strings for EOFs except the last one and
13867 * raises EOFError for the last one.
13872 argf_readpartial(int argc
, VALUE
*argv
, VALUE argf
)
13874 return argf_getpartial(argc
, argv
, argf
, Qnil
, 0);
13879 * ARGF.read_nonblock(maxlen[, options]) -> string
13880 * ARGF.read_nonblock(maxlen, outbuf[, options]) -> outbuf
13882 * Reads at most _maxlen_ bytes from the ARGF stream in non-blocking mode.
13886 argf_read_nonblock(int argc
, VALUE
*argv
, VALUE argf
)
13890 rb_scan_args(argc
, argv
, "11:", NULL
, NULL
, &opts
);
13895 return argf_getpartial(argc
, argv
, argf
, opts
, 1);
13899 argf_getpartial(int argc
, VALUE
*argv
, VALUE argf
, VALUE opts
, int nonblock
)
13901 VALUE tmp
, str
, length
;
13904 rb_scan_args(argc
, argv
, "11", &length
, &str
);
13909 no_exception
= no_exception_p(opts
);
13911 if (!next_argv()) {
13913 rb_str_resize(str
, 0);
13917 if (ARGF_GENERIC_INPUT_P()) {
13918 VALUE (*const rescue_does_nothing
)(VALUE
, VALUE
) = 0;
13919 struct argf_call_arg arg
;
13923 tmp
= rb_rescue2(argf_forward_call
, (VALUE
)&arg
,
13924 rescue_does_nothing
, Qnil
, rb_eEOFError
, (VALUE
)0);
13927 tmp
= io_getpartial(argc
, argv
, ARGF
.current_file
, no_exception
, nonblock
);
13930 if (ARGF
.next_p
== -1) {
13931 return io_nonblock_eof(no_exception
);
13935 if (RARRAY_LEN(ARGF
.argv
) == 0) {
13936 return io_nonblock_eof(no_exception
);
13939 str
= rb_str_new(NULL
, 0);
13947 * ARGF.getc -> String or nil
13949 * Reads the next character from ARGF and returns it as a String. Returns
13950 * +nil+ at the end of the stream.
13952 * ARGF treats the files named on the command line as a single file created
13953 * by concatenating their contents. After returning the last character of the
13954 * first file, it returns the first character of the second file, and so on.
13958 * $ echo "foo" > file
13959 * $ ruby argf.rb file
13961 * ARGF.getc #=> "f"
13962 * ARGF.getc #=> "o"
13963 * ARGF.getc #=> "o"
13964 * ARGF.getc #=> "\n"
13965 * ARGF.getc #=> nil
13966 * ARGF.getc #=> nil
13969 argf_getc(VALUE argf
)
13974 if (!next_argv()) return Qnil
;
13975 if (ARGF_GENERIC_INPUT_P()) {
13976 ch
= forward_current(rb_intern("getc"), 0, 0);
13979 ch
= rb_io_getc(ARGF
.current_file
);
13981 if (NIL_P(ch
) && ARGF
.next_p
!= -1) {
13992 * ARGF.getbyte -> Integer or nil
13994 * Gets the next 8-bit byte (0..255) from ARGF. Returns +nil+ if called at
13995 * the end of the stream.
13999 * $ echo "foo" > file
14000 * $ ruby argf.rb file
14002 * ARGF.getbyte #=> 102
14003 * ARGF.getbyte #=> 111
14004 * ARGF.getbyte #=> 111
14005 * ARGF.getbyte #=> 10
14006 * ARGF.getbyte #=> nil
14009 argf_getbyte(VALUE argf
)
14014 if (!next_argv()) return Qnil
;
14015 if (!RB_TYPE_P(ARGF
.current_file
, T_FILE
)) {
14016 ch
= forward_current(rb_intern("getbyte"), 0, 0);
14019 ch
= rb_io_getbyte(ARGF
.current_file
);
14021 if (NIL_P(ch
) && ARGF
.next_p
!= -1) {
14032 * ARGF.readchar -> String or nil
14034 * Reads the next character from ARGF and returns it as a String. Raises
14035 * an EOFError after the last character of the last file has been read.
14039 * $ echo "foo" > file
14040 * $ ruby argf.rb file
14042 * ARGF.readchar #=> "f"
14043 * ARGF.readchar #=> "o"
14044 * ARGF.readchar #=> "o"
14045 * ARGF.readchar #=> "\n"
14046 * ARGF.readchar #=> end of file reached (EOFError)
14049 argf_readchar(VALUE argf
)
14054 if (!next_argv()) rb_eof_error();
14055 if (!RB_TYPE_P(ARGF
.current_file
, T_FILE
)) {
14056 ch
= forward_current(rb_intern("getc"), 0, 0);
14059 ch
= rb_io_getc(ARGF
.current_file
);
14061 if (NIL_P(ch
) && ARGF
.next_p
!= -1) {
14072 * ARGF.readbyte -> Integer
14074 * Reads the next 8-bit byte from ARGF and returns it as an Integer. Raises
14075 * an EOFError after the last byte of the last file has been read.
14079 * $ echo "foo" > file
14080 * $ ruby argf.rb file
14082 * ARGF.readbyte #=> 102
14083 * ARGF.readbyte #=> 111
14084 * ARGF.readbyte #=> 111
14085 * ARGF.readbyte #=> 10
14086 * ARGF.readbyte #=> end of file reached (EOFError)
14089 argf_readbyte(VALUE argf
)
14093 NEXT_ARGF_FORWARD(0, 0);
14094 c
= argf_getbyte(argf
);
14101 #define FOREACH_ARGF() while (next_argv())
14104 argf_block_call_i(RB_BLOCK_CALL_FUNC_ARGLIST(i
, argf
))
14106 const VALUE current
= ARGF
.current_file
;
14107 rb_yield_values2(argc
, argv
);
14108 if (ARGF
.init_p
== -1 || current
!= ARGF
.current_file
) {
14109 rb_iter_break_value(Qundef
);
14114 #define ARGF_block_call(mid, argc, argv, func, argf) \
14115 rb_block_call_kw(ARGF.current_file, mid, argc, argv, \
14116 func, argf, rb_keyword_given_p())
14119 argf_block_call(ID mid
, int argc
, VALUE
*argv
, VALUE argf
)
14121 VALUE ret
= ARGF_block_call(mid
, argc
, argv
, argf_block_call_i
, argf
);
14122 if (!UNDEF_P(ret
)) ARGF
.next_p
= 1;
14126 argf_block_call_line_i(RB_BLOCK_CALL_FUNC_ARGLIST(i
, argf
))
14128 if (!global_argf_p(argf
)) {
14129 ARGF
.last_lineno
= ++ARGF
.lineno
;
14131 return argf_block_call_i(i
, argf
, argc
, argv
, blockarg
);
14135 argf_block_call_line(ID mid
, int argc
, VALUE
*argv
, VALUE argf
)
14137 VALUE ret
= ARGF_block_call(mid
, argc
, argv
, argf_block_call_line_i
, argf
);
14138 if (!UNDEF_P(ret
)) ARGF
.next_p
= 1;
14143 * ARGF.each(sep=$/) {|line| block } -> ARGF
14144 * ARGF.each(sep=$/, limit) {|line| block } -> ARGF
14145 * ARGF.each(...) -> an_enumerator
14147 * ARGF.each_line(sep=$/) {|line| block } -> ARGF
14148 * ARGF.each_line(sep=$/, limit) {|line| block } -> ARGF
14149 * ARGF.each_line(...) -> an_enumerator
14151 * Returns an enumerator which iterates over each line (separated by _sep_,
14152 * which defaults to your platform's newline character) of each file in
14153 * +ARGV+. If a block is supplied, each line in turn will be yielded to the
14154 * block, otherwise an enumerator is returned.
14155 * The optional _limit_ argument is an Integer specifying the maximum
14156 * length of each line; longer lines will be split according to this limit.
14158 * This method allows you to treat the files supplied on the command line as
14159 * a single file consisting of the concatenation of each named file. After
14160 * the last line of the first file has been returned, the first line of the
14161 * second file is returned. The ARGF.filename and ARGF.lineno methods can be
14162 * used to determine the filename of the current line and line number of the
14163 * whole input, respectively.
14165 * For example, the following code prints out each line of each named file
14166 * prefixed with its line number, displaying the filename once per file:
14168 * ARGF.each_line do |line|
14169 * puts ARGF.filename if ARGF.file.lineno == 1
14170 * puts "#{ARGF.file.lineno}: #{line}"
14173 * While the following code prints only the first file's name at first, and
14174 * the contents with line number counted through all named files.
14176 * ARGF.each_line do |line|
14177 * puts ARGF.filename if ARGF.lineno == 1
14178 * puts "#{ARGF.lineno}: #{line}"
14182 argf_each_line(int argc
, VALUE
*argv
, VALUE argf
)
14184 RETURN_ENUMERATOR(argf
, argc
, argv
);
14186 argf_block_call_line(rb_intern("each_line"), argc
, argv
, argf
);
14193 * ARGF.each_byte {|byte| block } -> ARGF
14194 * ARGF.each_byte -> an_enumerator
14196 * Iterates over each byte of each file in +ARGV+.
14197 * A byte is returned as an Integer in the range 0..255.
14199 * This method allows you to treat the files supplied on the command line as
14200 * a single file consisting of the concatenation of each named file. After
14201 * the last byte of the first file has been returned, the first byte of the
14202 * second file is returned. The ARGF.filename method can be used to
14203 * determine the filename of the current byte.
14205 * If no block is given, an enumerator is returned instead.
14209 * ARGF.bytes.to_a #=> [35, 32, ... 95, 10]
14213 argf_each_byte(VALUE argf
)
14215 RETURN_ENUMERATOR(argf
, 0, 0);
14217 argf_block_call(rb_intern("each_byte"), 0, 0, argf
);
14224 * ARGF.each_char {|char| block } -> ARGF
14225 * ARGF.each_char -> an_enumerator
14227 * Iterates over each character of each file in ARGF.
14229 * This method allows you to treat the files supplied on the command line as
14230 * a single file consisting of the concatenation of each named file. After
14231 * the last character of the first file has been returned, the first
14232 * character of the second file is returned. The ARGF.filename method can
14233 * be used to determine the name of the file in which the current character
14236 * If no block is given, an enumerator is returned instead.
14239 argf_each_char(VALUE argf
)
14241 RETURN_ENUMERATOR(argf
, 0, 0);
14243 argf_block_call(rb_intern("each_char"), 0, 0, argf
);
14250 * ARGF.each_codepoint {|codepoint| block } -> ARGF
14251 * ARGF.each_codepoint -> an_enumerator
14253 * Iterates over each codepoint of each file in ARGF.
14255 * This method allows you to treat the files supplied on the command line as
14256 * a single file consisting of the concatenation of each named file. After
14257 * the last codepoint of the first file has been returned, the first
14258 * codepoint of the second file is returned. The ARGF.filename method can
14259 * be used to determine the name of the file in which the current codepoint
14262 * If no block is given, an enumerator is returned instead.
14265 argf_each_codepoint(VALUE argf
)
14267 RETURN_ENUMERATOR(argf
, 0, 0);
14269 argf_block_call(rb_intern("each_codepoint"), 0, 0, argf
);
14276 * ARGF.filename -> String
14277 * ARGF.path -> String
14279 * Returns the current filename. "-" is returned when the current file is
14284 * $ echo "foo" > foo
14285 * $ echo "bar" > bar
14286 * $ echo "glark" > glark
14288 * $ ruby argf.rb foo bar glark
14290 * ARGF.filename #=> "foo"
14291 * ARGF.read(5) #=> "foo\nb"
14292 * ARGF.filename #=> "bar"
14294 * ARGF.filename #=> "glark"
14297 argf_filename(VALUE argf
)
14300 return ARGF
.filename
;
14304 argf_filename_getter(ID id
, VALUE
*var
)
14306 return argf_filename(*var
);
14311 * ARGF.file -> IO or File object
14313 * Returns the current file as an IO or File object.
14314 * <code>$stdin</code> is returned when the current file is STDIN.
14318 * $ echo "foo" > foo
14319 * $ echo "bar" > bar
14321 * $ ruby argf.rb foo bar
14323 * ARGF.file #=> #<File:foo>
14324 * ARGF.read(5) #=> "foo\nb"
14325 * ARGF.file #=> #<File:bar>
14328 argf_file(VALUE argf
)
14331 return ARGF
.current_file
;
14336 * ARGF.binmode -> ARGF
14338 * Puts ARGF into binary mode. Once a stream is in binary mode, it cannot
14339 * be reset to non-binary mode. This option has the following effects:
14341 * * Newline conversion is disabled.
14342 * * Encoding conversion is disabled.
14343 * * Content is treated as ASCII-8BIT.
14346 argf_binmode_m(VALUE argf
)
14350 ARGF_FORWARD(0, 0);
14351 rb_io_ascii8bit_binmode(ARGF
.current_file
);
14357 * ARGF.binmode? -> true or false
14359 * Returns true if ARGF is being read in binary mode; false otherwise.
14360 * To enable binary mode use ARGF.binmode.
14364 * ARGF.binmode? #=> false
14366 * ARGF.binmode? #=> true
14369 argf_binmode_p(VALUE argf
)
14371 return RBOOL(ARGF
.binmode
);
14376 * ARGF.skip -> ARGF
14378 * Sets the current file to the next file in ARGV. If there aren't any more
14379 * files it has no effect.
14383 * $ ruby argf.rb foo bar
14384 * ARGF.filename #=> "foo"
14386 * ARGF.filename #=> "bar"
14389 argf_skip(VALUE argf
)
14391 if (ARGF
.init_p
&& ARGF
.next_p
== 0) {
14400 * ARGF.close -> ARGF
14402 * Closes the current file and skips to the next file in ARGV. If there are
14403 * no more files to open, just closes the current file. STDIN will not be
14408 * $ ruby argf.rb foo bar
14410 * ARGF.filename #=> "foo"
14412 * ARGF.filename #=> "bar"
14416 argf_close_m(VALUE argf
)
14420 if (ARGF
.next_p
!= -1) {
14429 * ARGF.closed? -> true or false
14431 * Returns _true_ if the current file has been closed; _false_ otherwise. Use
14432 * ARGF.close to actually close the current file.
14435 argf_closed(VALUE argf
)
14438 ARGF_FORWARD(0, 0);
14439 return rb_io_closed_p(ARGF
.current_file
);
14444 * ARGF.to_s -> String
14449 argf_to_s(VALUE argf
)
14451 return rb_str_new2("ARGF");
14456 * ARGF.inplace_mode -> String
14458 * Returns the file extension appended to the names of backup copies of
14459 * modified files under in-place edit mode. This value can be set using
14460 * ARGF.inplace_mode= or passing the +-i+ switch to the Ruby binary.
14463 argf_inplace_mode_get(VALUE argf
)
14465 if (!ARGF
.inplace
) return Qnil
;
14466 if (NIL_P(ARGF
.inplace
)) return rb_str_new(0, 0);
14467 return rb_str_dup(ARGF
.inplace
);
14471 opt_i_get(ID id
, VALUE
*var
)
14473 return argf_inplace_mode_get(*var
);
14478 * ARGF.inplace_mode = ext -> ARGF
14480 * Sets the filename extension for in-place editing mode to the given String.
14481 * The backup copy of each file being edited has this value appended to its
14486 * $ ruby argf.rb file.txt
14488 * ARGF.inplace_mode = '.bak'
14489 * ARGF.each_line do |line|
14490 * print line.sub("foo","bar")
14493 * First, _file.txt.bak_ is created as a backup copy of _file.txt_.
14494 * Then, each line of _file.txt_ has the first occurrence of "foo" replaced with
14498 argf_inplace_mode_set(VALUE argf
, VALUE val
)
14501 ARGF
.inplace
= Qfalse
;
14503 else if (StringValueCStr(val
), !RSTRING_LEN(val
)) {
14504 ARGF
.inplace
= Qnil
;
14507 ARGF
.inplace
= rb_str_new_frozen(val
);
14513 opt_i_set(VALUE val
, ID id
, VALUE
*var
)
14515 argf_inplace_mode_set(*var
, val
);
14519 ruby_set_inplace_mode(const char *suffix
)
14521 ARGF
.inplace
= !suffix
? Qfalse
: !*suffix
? Qnil
: rb_str_new(suffix
, strlen(suffix
));
14526 * ARGF.argv -> ARGV
14528 * Returns the +ARGV+ array, which contains the arguments passed to your
14529 * script, one per element.
14533 * $ ruby argf.rb -v glark.txt
14535 * ARGF.argv #=> ["-v", "glark.txt"]
14539 argf_argv(VALUE argf
)
14545 argf_argv_getter(ID id
, VALUE
*var
)
14547 return argf_argv(*var
);
14558 * ARGF.to_write_io -> io
14560 * Returns IO instance tied to _ARGF_ for writing if inplace mode is
14564 argf_write_io(VALUE argf
)
14566 if (!RTEST(ARGF
.current_file
)) {
14567 rb_raise(rb_eIOError
, "not opened for writing");
14569 return GetWriteIO(ARGF
.current_file
);
14574 * ARGF.write(*objects) -> integer
14576 * Writes each of the given +objects+ if inplace mode.
14579 argf_write(int argc
, VALUE
*argv
, VALUE argf
)
14581 return rb_io_writev(argf_write_io(argf
), argc
, argv
);
14585 rb_readwrite_sys_fail(enum rb_io_wait_readwrite waiting
, const char *mesg
)
14587 rb_readwrite_syserr_fail(waiting
, errno
, mesg
);
14591 rb_readwrite_syserr_fail(enum rb_io_wait_readwrite waiting
, int n
, const char *mesg
)
14593 VALUE arg
, c
= Qnil
;
14594 arg
= mesg
? rb_str_new2(mesg
) : Qnil
;
14596 case RB_IO_WAIT_WRITABLE
:
14599 c
= rb_eEAGAINWaitWritable
;
14601 #if EAGAIN != EWOULDBLOCK
14603 c
= rb_eEWOULDBLOCKWaitWritable
;
14607 c
= rb_eEINPROGRESSWaitWritable
;
14610 rb_mod_syserr_fail_str(rb_mWaitWritable
, n
, arg
);
14613 case RB_IO_WAIT_READABLE
:
14616 c
= rb_eEAGAINWaitReadable
;
14618 #if EAGAIN != EWOULDBLOCK
14620 c
= rb_eEWOULDBLOCKWaitReadable
;
14624 c
= rb_eEINPROGRESSWaitReadable
;
14627 rb_mod_syserr_fail_str(rb_mWaitReadable
, n
, arg
);
14631 rb_bug("invalid read/write type passed to rb_readwrite_sys_fail: %d", waiting
);
14633 rb_exc_raise(rb_class_new_instance(1, &arg
, c
));
14637 get_LAST_READ_LINE(ID _x
, VALUE
*_y
)
14639 return rb_lastline_get();
14643 set_LAST_READ_LINE(VALUE val
, ID _x
, VALUE
*_y
)
14645 rb_lastline_set(val
);
14649 * Document-class: IOError
14651 * Raised when an IO operation fails.
14653 * File.open("/etc/hosts") {|f| f << "example"}
14654 * #=> IOError: not opened for writing
14656 * File.open("/etc/hosts") {|f| f.close; f.read }
14657 * #=> IOError: closed stream
14659 * Note that some IO failures raise <code>SystemCallError</code>s
14660 * and these are not subclasses of IOError:
14662 * File.open("does/not/exist")
14663 * #=> Errno::ENOENT: No such file or directory - does/not/exist
14667 * Document-class: EOFError
14669 * Raised by some IO operations when reaching the end of file. Many IO
14670 * methods exist in two forms,
14672 * one that returns +nil+ when the end of file is reached, the other
14675 * EOFError is a subclass of IOError.
14677 * file = File.open("/etc/hosts")
14679 * file.gets #=> nil
14680 * file.readline #=> EOFError: end of file reached
14685 * Document-class: ARGF
14687 * == \ARGF and +ARGV+
14689 * The \ARGF object works with the array at global variable +ARGV+
14690 * to make <tt>$stdin</tt> and file streams available in the Ruby program:
14692 * - **ARGV** may be thought of as the <b>argument vector</b> array.
14694 * Initially, it contains the command-line arguments and options
14695 * that are passed to the Ruby program;
14696 * the program can modify that array as it likes.
14698 * - **ARGF** may be thought of as the <b>argument files</b> object.
14700 * It can access file streams and/or the <tt>$stdin</tt> stream,
14701 * based on what it finds in +ARGV+.
14702 * This provides a convenient way for the command line
14703 * to specify streams for a Ruby program to read.
14707 * \ARGF may read from _source_ streams,
14708 * which at any particular time are determined by the content of +ARGV+.
14710 * === Simplest Case
14712 * When the <i>very first</i> \ARGF read occurs with an empty +ARGV+ (<tt>[]</tt>),
14713 * the source is <tt>$stdin</tt>:
14718 * p ['ARGF.read', ARGF.read]
14720 * - Commands and outputs
14721 * (see below for the content of files +foo.txt+ and +bar.txt+):
14723 * $ echo "Open the pod bay doors, Hal." | ruby t.rb
14725 * ["ARGF.read", "Open the pod bay doors, Hal.\n"]
14727 * $ cat foo.txt bar.txt | ruby t.rb
14729 * ["ARGF.read", "Foo 0\nFoo 1\nBar 0\nBar 1\nBar 2\nBar 3\n"]
14731 * === About the Examples
14733 * Many examples here assume the existence of files +foo.txt+ and +bar.txt+:
14744 * === Sources in +ARGV+
14746 * For any \ARGF read _except_ the {simplest case}[rdoc-ref:ARGF@Simplest+Case]
14747 * (that is, _except_ for the <i>very first</i> \ARGF read with an empty +ARGV+),
14748 * the sources are found in +ARGV+.
14750 * \ARGF assumes that each element in array +ARGV+ is a potential source,
14753 * - The string path to a file that may be opened as a stream.
14754 * - The character <tt>'-'</tt>, meaning stream <tt>$stdin</tt>.
14756 * Each element that is _not_ one of these
14757 * should be removed from +ARGV+ before \ARGF accesses that source.
14759 * In the following example:
14761 * - Filepaths +foo.txt+ and +bar.txt+ may be retained as potential sources.
14762 * - Options <tt>--xyzzy</tt> and <tt>--mojo</tt> should be removed.
14768 * # Print arguments (and options, if any) found on command line.
14771 * - Command and output:
14773 * $ ruby t.rb --xyzzy --mojo foo.txt bar.txt
14774 * ["ARGV", ["--xyzzy", "--mojo", "foo.txt", "bar.txt"]]
14776 * \ARGF's stream access considers the elements of +ARGV+, left to right:
14780 * p "ARGV: #{ARGV}"
14781 * p "Line: #{ARGF.read}" # Read everything from all specified streams.
14783 * - Command and output:
14785 * $ ruby t.rb foo.txt bar.txt
14786 * "ARGV: [\"foo.txt\", \"bar.txt\"]"
14787 * "Read: Foo 0\nFoo 1\nBar 0\nBar 1\nBar 2\nBar 3\n"
14789 * Because the value at +ARGV+ is an ordinary array,
14790 * you can manipulate it to control which sources \ARGF considers:
14792 * - If you remove an element from +ARGV+, \ARGF will not consider the corresponding source.
14793 * - If you add an element to +ARGV+, \ARGF will consider the corresponding source.
14795 * Each element in +ARGV+ is removed when its corresponding source is accessed;
14796 * when all sources have been accessed, the array is empty:
14800 * until ARGV.empty? && ARGF.eof?
14801 * p "ARGV: #{ARGV}"
14802 * p "Line: #{ARGF.readline}" # Read each line from each specified stream.
14805 * - Command and output:
14807 * $ ruby t.rb foo.txt bar.txt
14808 * "ARGV: [\"foo.txt\", \"bar.txt\"]"
14810 * "ARGV: [\"bar.txt\"]"
14812 * "ARGV: [\"bar.txt\"]"
14821 * ==== Filepaths in +ARGV+
14823 * The +ARGV+ array may contain filepaths the specify sources for \ARGF reading.
14825 * This program prints what it reads from files at the paths specified
14826 * on the command line:
14831 * # Read and print all content from the specified sources.
14832 * p ['ARGF.read', ARGF.read]
14834 * - Command and output:
14836 * $ ruby t.rb foo.txt bar.txt
14837 * ["ARGV", [foo.txt, bar.txt]
14838 * ["ARGF.read", "Foo 0\nFoo 1\nBar 0\nBar 1\nBar 2\nBar 3\n"]
14840 * ==== Specifying <tt>$stdin</tt> in +ARGV+
14842 * To specify stream <tt>$stdin</tt> in +ARGV+, us the character <tt>'-'</tt>:
14847 * p ['ARGF.read', ARGF.read]
14849 * - Command and output:
14851 * $ echo "Open the pod bay doors, Hal." | ruby t.rb -
14853 * ["ARGF.read", "Open the pod bay doors, Hal.\n"]
14855 * When no character <tt>'-'</tt> is given, stream <tt>$stdin</tt> is ignored
14857 * see {Specifying $stdin in ARGV}[rdoc-ref:ARGF@Specifying+-24stdin+in+ARGV]):
14859 * - Command and output:
14861 * $ echo "Open the pod bay doors, Hal." | ruby t.rb foo.txt bar.txt
14862 * "ARGV: [\"foo.txt\", \"bar.txt\"]"
14863 * "Read: Foo 0\nFoo 1\nBar 0\nBar 1\nBar 2\nBar 3\n"
14865 * ==== Mixtures and Repetitions in +ARGV+
14867 * For an \ARGF reader, +ARGV+ may contain any mixture of filepaths
14868 * and character <tt>'-'</tt>, including repetitions.
14870 * ==== Modifications to +ARGV+
14872 * The running Ruby program may make any modifications to the +ARGV+ array;
14873 * the current value of +ARGV+ affects \ARGF reading.
14875 * ==== Empty +ARGV+
14877 * For an empty +ARGV+, an \ARGF read method either returns +nil+
14878 * or raises an exception, depending on the specific method.
14880 * === More Read Methods
14882 * As seen above, method ARGF#read reads the content of all sources
14883 * into a single string.
14884 * Other \ARGF methods provide other ways to access that content;
14887 * - Byte access: #each_byte, #getbyte, #readbyte.
14888 * - Character access: #each_char, #getc, #readchar.
14889 * - Codepoint access: #each_codepoint.
14890 * - Line access: #each_line, #gets, #readline, #readlines.
14891 * - Source access: #read, #read_nonblock, #readpartial.
14893 * === About \Enumerable
14895 * \ARGF includes module Enumerable.
14896 * Virtually all methods in \Enumerable call method <tt>#each</tt> in the including class.
14898 * <b>Note well</b>: In \ARGF, method #each returns data from the _sources_,
14899 * _not_ from +ARGV+;
14900 * therefore, for example, <tt>ARGF#entries</tt> returns an array of lines from the sources,
14901 * not an array of the strings from +ARGV+:
14906 * p ['ARGF.entries', ARGF.entries]
14908 * - Command and output:
14910 * $ ruby t.rb foo.txt bar.txt
14911 * ["ARGV", ["foo.txt", "bar.txt"]]
14912 * ["ARGF.entries", ["Foo 0\n", "Foo 1\n", "Bar 0\n", "Bar 1\n", "Bar 2\n", "Bar 3\n"]]
14916 * If <i>inplace mode</i> is in effect,
14917 * \ARGF may write to target streams,
14918 * which at any particular time are determined by the content of ARGV.
14920 * Methods about inplace mode:
14926 * Methods for writing:
14937 * An instance of class \IO (commonly called a _stream_)
14938 * represents an input/output stream in the underlying operating system.
14939 * \Class \IO is the basis for input and output in Ruby.
14941 * \Class File is the only class in the Ruby core that is a subclass of \IO.
14942 * Some classes in the Ruby standard library are also subclasses of \IO;
14943 * these include TCPSocket and UDPSocket.
14945 * The global constant ARGF (also accessible as <tt>$<</tt>)
14946 * provides an IO-like stream that allows access to all file paths
14947 * found in ARGV (or found in STDIN if ARGV is empty).
14948 * ARGF is not itself a subclass of \IO.
14950 * \Class StringIO provides an IO-like stream that handles a String.
14951 * StringIO is not itself a subclass of \IO.
14953 * Important objects based on \IO include:
14958 * - Instances of class File.
14960 * An instance of \IO may be created using:
14962 * - IO.new: returns a new \IO object for the given integer file descriptor.
14963 * - IO.open: passes a new \IO object to the given block.
14964 * - IO.popen: returns a new \IO object that is connected to the $stdin and $stdout
14965 * of a newly-launched subprocess.
14966 * - Kernel#open: Returns a new \IO object connected to a given source:
14967 * stream, file, or subprocess.
14969 * Like a File stream, an \IO stream has:
14971 * - A read/write mode, which may be read-only, write-only, or read/write;
14972 * see {Read/Write Mode}[rdoc-ref:File@Read-2FWrite+Mode].
14973 * - A data mode, which may be text-only or binary;
14974 * see {Data Mode}[rdoc-ref:File@Data+Mode].
14975 * - Internal and external encodings;
14976 * see {Encodings}[rdoc-ref:File@Encodings].
14978 * And like other \IO streams, it has:
14980 * - A position, which determines where in the stream the next
14981 * read or write is to occur;
14982 * see {Position}[rdoc-ref:IO@Position].
14983 * - A line number, which is a special, line-oriented, "position"
14984 * (different from the position mentioned above);
14985 * see {Line Number}[rdoc-ref:IO@Line+Number].
14987 * == Extension <tt>io/console</tt>
14989 * Extension <tt>io/console</tt> provides numerous methods
14990 * for interacting with the console;
14991 * requiring it adds numerous methods to class \IO.
14995 * Many examples here use these variables:
14997 * :include: doc/examples/files.rdoc
15001 * A number of \IO methods accept optional keyword arguments
15002 * that determine how a new stream is to be opened:
15004 * - +:mode+: Stream mode.
15005 * - +:flags+: Integer file open flags;
15006 * If +mode+ is also given, the two are bitwise-ORed.
15007 * - +:external_encoding+: External encoding for the stream.
15008 * - +:internal_encoding+: Internal encoding for the stream.
15009 * <tt>'-'</tt> is a synonym for the default internal encoding.
15010 * If the value is +nil+ no conversion occurs.
15011 * - +:encoding+: Specifies external and internal encodings as <tt>'extern:intern'</tt>.
15012 * - +:textmode+: If a truthy value, specifies the mode as text-only, binary otherwise.
15013 * - +:binmode+: If a truthy value, specifies the mode as binary, text-only otherwise.
15014 * - +:autoclose+: If a truthy value, specifies that the +fd+ will close
15015 * when the stream closes; otherwise it remains open.
15016 * - +:path:+ If a string value is provided, it is used in #inspect and is available as
15019 * Also available are the options offered in String#encode,
15020 * which may control conversion between external and internal encoding.
15024 * You can perform basic stream \IO with these methods,
15025 * which typically operate on multi-byte strings:
15027 * - IO#read: Reads and returns some or all of the remaining bytes from the stream.
15028 * - IO#write: Writes zero or more strings to the stream;
15029 * each given object that is not already a string is converted via +to_s+.
15033 * An \IO stream has a nonnegative integer _position_,
15034 * which is the byte offset at which the next read or write is to occur.
15035 * A new stream has position zero (and line number zero);
15036 * method +rewind+ resets the position (and line number) to zero.
15038 * The relevant methods:
15040 * - IO#tell (aliased as +#pos+): Returns the current position (in bytes) in the stream.
15041 * - IO#pos=: Sets the position of the stream to a given integer +new_position+ (in bytes).
15042 * - IO#seek: Sets the position of the stream to a given integer +offset+ (in bytes),
15043 * relative to a given position +whence+
15044 * (indicating the beginning, end, or current position).
15045 * - IO#rewind: Positions the stream at the beginning (also resetting the line number).
15047 * === Open and Closed Streams
15049 * A new \IO stream may be open for reading, open for writing, or both.
15051 * A stream is automatically closed when claimed by the garbage collector.
15053 * Attempted reading or writing on a closed stream raises an exception.
15055 * The relevant methods:
15057 * - IO#close: Closes the stream for both reading and writing.
15058 * - IO#close_read: Closes the stream for reading.
15059 * - IO#close_write: Closes the stream for writing.
15060 * - IO#closed?: Returns whether the stream is closed.
15062 * === End-of-Stream
15064 * You can query whether a stream is positioned at its end:
15066 * - IO#eof? (also aliased as +#eof+): Returns whether the stream is at end-of-stream.
15068 * You can reposition to end-of-stream by using method IO#seek:
15070 * f = File.new('t.txt')
15071 * f.eof? # => false
15076 * Or by reading all stream content (which is slower than using IO#seek):
15079 * f.eof? # => false
15080 * f.read # => "First line\nSecond line\n\nFourth line\nFifth line\n"
15085 * \Class \IO supports line-oriented
15086 * {input}[rdoc-ref:IO@Line+Input] and {output}[rdoc-ref:IO@Line+Output]
15090 * \Class \IO supports line-oriented input for
15091 * {files}[rdoc-ref:IO@File+Line+Input] and {IO streams}[rdoc-ref:IO@Stream+Line+Input]
15093 * ==== \File Line Input
15095 * You can read lines from a file using these methods:
15097 * - IO.foreach: Reads each line and passes it to the given block.
15098 * - IO.readlines: Reads and returns all lines in an array.
15100 * For each of these methods:
15102 * - You can specify {open options}[rdoc-ref:IO@Open+Options].
15103 * - Line parsing depends on the effective <i>line separator</i>;
15104 * see {Line Separator}[rdoc-ref:IO@Line+Separator].
15105 * - The length of each returned line depends on the effective <i>line limit</i>;
15106 * see {Line Limit}[rdoc-ref:IO@Line+Limit].
15108 * ==== Stream Line Input
15110 * You can read lines from an \IO stream using these methods:
15112 * - IO#each_line: Reads each remaining line, passing it to the given block.
15113 * - IO#gets: Returns the next line.
15114 * - IO#readline: Like #gets, but raises an exception at end-of-stream.
15115 * - IO#readlines: Returns all remaining lines in an array.
15117 * For each of these methods:
15119 * - Reading may begin mid-line,
15120 * depending on the stream's _position_;
15121 * see {Position}[rdoc-ref:IO@Position].
15122 * - Line parsing depends on the effective <i>line separator</i>;
15123 * see {Line Separator}[rdoc-ref:IO@Line+Separator].
15124 * - The length of each returned line depends on the effective <i>line limit</i>;
15125 * see {Line Limit}[rdoc-ref:IO@Line+Limit].
15127 * ===== Line Separator
15129 * Each of the {line input methods}[rdoc-ref:IO@Line+Input] uses a <i>line separator</i>:
15130 * the string that determines what is considered a line;
15131 * it is sometimes called the <i>input record separator</i>.
15133 * The default line separator is taken from global variable <tt>$/</tt>,
15134 * whose initial value is <tt>"\n"</tt>.
15136 * Generally, the line to be read next is all data
15137 * from the current {position}[rdoc-ref:IO@Position]
15138 * to the next line separator
15139 * (but see {Special Line Separator Values}[rdoc-ref:IO@Special+Line+Separator+Values]):
15141 * f = File.new('t.txt')
15142 * # Method gets with no sep argument returns the next line, according to $/.
15143 * f.gets # => "First line\n"
15144 * f.gets # => "Second line\n"
15146 * f.gets # => "Fourth line\n"
15147 * f.gets # => "Fifth line\n"
15150 * You can use a different line separator by passing argument +sep+:
15152 * f = File.new('t.txt')
15153 * f.gets('l') # => "First l"
15154 * f.gets('li') # => "ine\nSecond li"
15155 * f.gets('lin') # => "ne\n\nFourth lin"
15156 * f.gets # => "e\n"
15159 * Or by setting global variable <tt>$/</tt>:
15161 * f = File.new('t.txt')
15163 * f.gets # => "First l"
15164 * f.gets # => "ine\nSecond l"
15165 * f.gets # => "ine\n\nFourth l"
15168 * ===== Special Line Separator Values
15170 * Each of the {line input methods}[rdoc-ref:IO@Line+Input]
15171 * accepts two special values for parameter +sep+:
15173 * - +nil+: The entire stream is to be read ("slurped") into a single string:
15175 * f = File.new('t.txt')
15176 * f.gets(nil) # => "First line\nSecond line\n\nFourth line\nFifth line\n"
15179 * - <tt>''</tt> (the empty string): The next "paragraph" is to be read
15180 * (paragraphs being separated by two consecutive line separators):
15182 * f = File.new('t.txt')
15183 * f.gets('') # => "First line\nSecond line\n\n"
15184 * f.gets('') # => "Fourth line\nFifth line\n"
15189 * Each of the {line input methods}[rdoc-ref:IO@Line+Input]
15190 * uses an integer <i>line limit</i>,
15191 * which restricts the number of bytes that may be returned.
15192 * (A multi-byte character will not be split, and so a returned line may be slightly longer
15195 * The default limit value is <tt>-1</tt>;
15196 * any negative limit value means that there is no limit.
15198 * If there is no limit, the line is determined only by +sep+.
15200 * # Text with 1-byte characters.
15201 * File.open('t.txt') {|f| f.gets(1) } # => "F"
15202 * File.open('t.txt') {|f| f.gets(2) } # => "Fi"
15203 * File.open('t.txt') {|f| f.gets(3) } # => "Fir"
15204 * File.open('t.txt') {|f| f.gets(4) } # => "Firs"
15205 * # No more than one line.
15206 * File.open('t.txt') {|f| f.gets(10) } # => "First line"
15207 * File.open('t.txt') {|f| f.gets(11) } # => "First line\n"
15208 * File.open('t.txt') {|f| f.gets(12) } # => "First line\n"
15210 * # Text with 2-byte characters, which will not be split.
15211 * File.open('t.rus') {|f| f.gets(1).size } # => 1
15212 * File.open('t.rus') {|f| f.gets(2).size } # => 1
15213 * File.open('t.rus') {|f| f.gets(3).size } # => 2
15214 * File.open('t.rus') {|f| f.gets(4).size } # => 2
15216 * ===== Line Separator and Line Limit
15218 * With arguments +sep+ and +limit+ given, combines the two behaviors:
15220 * - Returns the next line as determined by line separator +sep+.
15221 * - But returns no more bytes than are allowed by the limit +limit+.
15225 * File.open('t.txt') {|f| f.gets('li', 20) } # => "First li"
15226 * File.open('t.txt') {|f| f.gets('li', 2) } # => "Fi"
15228 * ===== Line Number
15230 * A readable \IO stream has a non-negative integer <i>line number</i>:
15232 * - IO#lineno: Returns the line number.
15233 * - IO#lineno=: Resets and returns the line number.
15235 * Unless modified by a call to method IO#lineno=,
15236 * the line number is the number of lines read
15237 * by certain line-oriented methods,
15238 * according to the effective {line separator}[rdoc-ref:IO@Line+Separator]:
15240 * - IO.foreach: Increments the line number on each call to the block.
15241 * - IO#each_line: Increments the line number on each call to the block.
15242 * - IO#gets: Increments the line number.
15243 * - IO#readline: Increments the line number.
15244 * - IO#readlines: Increments the line number for each line read.
15246 * A new stream is initially has line number zero (and position zero);
15247 * method +rewind+ resets the line number (and position) to zero:
15249 * f = File.new('t.txt')
15251 * f.gets # => "First line\n"
15257 * Reading lines from a stream usually changes its line number:
15259 * f = File.new('t.txt', 'r')
15261 * f.readline # => "This is line one.\n"
15263 * f.readline # => "This is the second line.\n"
15265 * f.readline # => "Here's the third line.\n"
15270 * Iterating over lines in a stream usually changes its line number:
15272 * File.open('t.txt') do |f|
15273 * f.each_line do |line|
15274 * p "position=#{f.pos} eof?=#{f.eof?} lineno=#{f.lineno}"
15280 * "position=11 eof?=false lineno=1"
15281 * "position=23 eof?=false lineno=2"
15282 * "position=24 eof?=false lineno=3"
15283 * "position=36 eof?=false lineno=4"
15284 * "position=47 eof?=true lineno=5"
15286 * Unlike the stream's {position}[rdoc-ref:IO@Position],
15287 * the line number does not affect where the next read or write will occur:
15289 * f = File.new('t.txt')
15291 * f.lineno # => 1000
15292 * f.gets # => "First line\n"
15293 * f.lineno # => 1001
15296 * Associated with the line number is the global variable <tt>$.</tt>:
15298 * - When a stream is opened, <tt>$.</tt> is not set;
15299 * its value is left over from previous activity in the process:
15302 * f = File.new('t.txt')
15307 * - When a stream is read, <tt>$.</tt> is set to the line number for that stream:
15309 * f0 = File.new('t.txt')
15310 * f1 = File.new('t.dat')
15311 * f0.readlines # => ["First line\n", "Second line\n", "\n", "Fourth line\n", "Fifth line\n"]
15313 * f1.readlines # => ["\xFE\xFF\x99\x90\x99\x91\x99\x92\x99\x93\x99\x94"]
15318 * - Methods IO#rewind and IO#seek do not affect <tt>$.</tt>:
15320 * f = File.new('t.txt')
15321 * f.readlines # => ["First line\n", "Second line\n", "\n", "Fourth line\n", "Fifth line\n"]
15330 * You can write to an \IO stream line-by-line using this method:
15332 * - IO#puts: Writes objects to the stream.
15336 * You can process an \IO stream character-by-character using these methods:
15338 * - IO#getc: Reads and returns the next character from the stream.
15339 * - IO#readchar: Like #getc, but raises an exception at end-of-stream.
15340 * - IO#ungetc: Pushes back ("unshifts") a character or integer onto the stream.
15341 * - IO#putc: Writes a character to the stream.
15342 * - IO#each_char: Reads each remaining character in the stream,
15343 * passing the character to the given block.
15346 * You can process an \IO stream byte-by-byte using these methods:
15348 * - IO#getbyte: Returns the next 8-bit byte as an integer in range 0..255.
15349 * - IO#readbyte: Like #getbyte, but raises an exception if at end-of-stream.
15350 * - IO#ungetbyte: Pushes back ("unshifts") a byte back onto the stream.
15351 * - IO#each_byte: Reads each remaining byte in the stream,
15352 * passing the byte to the given block.
15356 * You can process an \IO stream codepoint-by-codepoint:
15358 * - IO#each_codepoint: Reads each remaining codepoint, passing it to the given block.
15362 * First, what's elsewhere. \Class \IO:
15364 * - Inherits from {class Object}[rdoc-ref:Object@What-27s+Here].
15365 * - Includes {module Enumerable}[rdoc-ref:Enumerable@What-27s+Here],
15366 * which provides dozens of additional methods.
15368 * Here, class \IO provides methods that are useful for:
15370 * - {Creating}[rdoc-ref:IO@Creating]
15371 * - {Reading}[rdoc-ref:IO@Reading]
15372 * - {Writing}[rdoc-ref:IO@Writing]
15373 * - {Positioning}[rdoc-ref:IO@Positioning]
15374 * - {Iterating}[rdoc-ref:IO@Iterating]
15375 * - {Settings}[rdoc-ref:IO@Settings]
15376 * - {Querying}[rdoc-ref:IO@Querying]
15377 * - {Buffering}[rdoc-ref:IO@Buffering]
15378 * - {Low-Level Access}[rdoc-ref:IO@Low-Level+Access]
15379 * - {Other}[rdoc-ref:IO@Other]
15383 * - ::new (aliased as ::for_fd): Creates and returns a new \IO object for the given
15384 * integer file descriptor.
15385 * - ::open: Creates a new \IO object.
15386 * - ::pipe: Creates a connected pair of reader and writer \IO objects.
15387 * - ::popen: Creates an \IO object to interact with a subprocess.
15388 * - ::select: Selects which given \IO instances are ready for reading,
15389 * writing, or have pending exceptions.
15393 * - ::binread: Returns a binary string with all or a subset of bytes
15394 * from the given file.
15395 * - ::read: Returns a string with all or a subset of bytes from the given file.
15396 * - ::readlines: Returns an array of strings, which are the lines from the given file.
15397 * - #getbyte: Returns the next 8-bit byte read from +self+ as an integer.
15398 * - #getc: Returns the next character read from +self+ as a string.
15399 * - #gets: Returns the line read from +self+.
15400 * - #pread: Returns all or the next _n_ bytes read from +self+,
15401 * not updating the receiver's offset.
15402 * - #read: Returns all remaining or the next _n_ bytes read from +self+
15404 * - #read_nonblock: the next _n_ bytes read from +self+ for a given _n_,
15405 * in non-block mode.
15406 * - #readbyte: Returns the next byte read from +self+;
15407 * same as #getbyte, but raises an exception on end-of-stream.
15408 * - #readchar: Returns the next character read from +self+;
15409 * same as #getc, but raises an exception on end-of-stream.
15410 * - #readline: Returns the next line read from +self+;
15411 * same as #getline, but raises an exception of end-of-stream.
15412 * - #readlines: Returns an array of all lines read read from +self+.
15413 * - #readpartial: Returns up to the given number of bytes from +self+.
15417 * - ::binwrite: Writes the given string to the file at the given filepath,
15419 * - ::write: Writes the given string to +self+.
15420 * - #<<: Appends the given string to +self+.
15421 * - #print: Prints last read line or given objects to +self+.
15422 * - #printf: Writes to +self+ based on the given format string and objects.
15423 * - #putc: Writes a character to +self+.
15424 * - #puts: Writes lines to +self+, making sure line ends with a newline.
15425 * - #pwrite: Writes the given string at the given offset,
15426 * not updating the receiver's offset.
15427 * - #write: Writes one or more given strings to +self+.
15428 * - #write_nonblock: Writes one or more given strings to +self+ in non-blocking mode.
15432 * - #lineno: Returns the current line number in +self+.
15433 * - #lineno=: Sets the line number is +self+.
15434 * - #pos (aliased as #tell): Returns the current byte offset in +self+.
15435 * - #pos=: Sets the byte offset in +self+.
15436 * - #reopen: Reassociates +self+ with a new or existing \IO stream.
15437 * - #rewind: Positions +self+ to the beginning of input.
15438 * - #seek: Sets the offset for +self+ relative to given position.
15442 * - ::foreach: Yields each line of given file to the block.
15443 * - #each (aliased as #each_line): Calls the given block
15444 * with each successive line in +self+.
15445 * - #each_byte: Calls the given block with each successive byte in +self+
15447 * - #each_char: Calls the given block with each successive character in +self+
15449 * - #each_codepoint: Calls the given block with each successive codepoint in +self+
15454 * - #autoclose=: Sets whether +self+ auto-closes.
15455 * - #binmode: Sets +self+ to binary mode.
15456 * - #close: Closes +self+.
15457 * - #close_on_exec=: Sets the close-on-exec flag.
15458 * - #close_read: Closes +self+ for reading.
15459 * - #close_write: Closes +self+ for writing.
15460 * - #set_encoding: Sets the encoding for +self+.
15461 * - #set_encoding_by_bom: Sets the encoding for +self+, based on its
15462 * Unicode byte-order-mark.
15463 * - #sync=: Sets the sync-mode to the given value.
15467 * - #autoclose?: Returns whether +self+ auto-closes.
15468 * - #binmode?: Returns whether +self+ is in binary mode.
15469 * - #close_on_exec?: Returns the close-on-exec flag for +self+.
15470 * - #closed?: Returns whether +self+ is closed.
15471 * - #eof? (aliased as #eof): Returns whether +self+ is at end-of-stream.
15472 * - #external_encoding: Returns the external encoding object for +self+.
15473 * - #fileno (aliased as #to_i): Returns the integer file descriptor for +self+
15474 * - #internal_encoding: Returns the internal encoding object for +self+.
15475 * - #pid: Returns the process ID of a child process associated with +self+,
15476 * if +self+ was created by ::popen.
15477 * - #stat: Returns the File::Stat object containing status information for +self+.
15478 * - #sync: Returns whether +self+ is in sync-mode.
15479 * - #tty? (aliased as #isatty): Returns whether +self+ is a terminal.
15483 * - #fdatasync: Immediately writes all buffered data in +self+ to disk.
15484 * - #flush: Flushes any buffered data within +self+ to the underlying
15485 * operating system.
15486 * - #fsync: Immediately writes all buffered data and attributes in +self+ to disk.
15487 * - #ungetbyte: Prepends buffer for +self+ with given integer byte or string.
15488 * - #ungetc: Prepends buffer for +self+ with given string.
15490 * === Low-Level Access
15492 * - ::sysopen: Opens the file given by its path,
15493 * returning the integer file descriptor.
15494 * - #advise: Announces the intention to access data from +self+ in a specific way.
15495 * - #fcntl: Passes a low-level command to the file specified
15496 * by the given file descriptor.
15497 * - #ioctl: Passes a low-level command to the device specified
15498 * by the given file descriptor.
15499 * - #sysread: Returns up to the next _n_ bytes read from self using a low-level read.
15500 * - #sysseek: Sets the offset for +self+.
15501 * - #syswrite: Writes the given string to +self+ using a low-level write.
15505 * - ::copy_stream: Copies data from a source to a destination,
15506 * each of which is a filepath or an \IO-like object.
15507 * - ::try_convert: Returns a new \IO object resulting from converting
15508 * the given object.
15509 * - #inspect: Returns the string representation of +self+.
15518 #include <sys/cygwin.h>
15519 static struct __cygwin_perfile pf
[] =
15521 {"", O_RDONLY
| O_BINARY
},
15522 {"", O_WRONLY
| O_BINARY
},
15523 {"", O_RDWR
| O_BINARY
},
15524 {"", O_APPEND
| O_BINARY
},
15527 cygwin_internal(CW_PERFILE
, pf
);
15530 rb_eIOError
= rb_define_class("IOError", rb_eStandardError
);
15531 rb_eEOFError
= rb_define_class("EOFError", rb_eIOError
);
15533 id_write
= rb_intern_const("write");
15534 id_read
= rb_intern_const("read");
15535 id_getc
= rb_intern_const("getc");
15536 id_flush
= rb_intern_const("flush");
15537 id_readpartial
= rb_intern_const("readpartial");
15538 id_set_encoding
= rb_intern_const("set_encoding");
15539 id_fileno
= rb_intern_const("fileno");
15541 rb_define_global_function("syscall", rb_f_syscall
, -1);
15543 rb_define_global_function("open", rb_f_open
, -1);
15544 rb_define_global_function("printf", rb_f_printf
, -1);
15545 rb_define_global_function("print", rb_f_print
, -1);
15546 rb_define_global_function("putc", rb_f_putc
, 1);
15547 rb_define_global_function("puts", rb_f_puts
, -1);
15548 rb_define_global_function("gets", rb_f_gets
, -1);
15549 rb_define_global_function("readline", rb_f_readline
, -1);
15550 rb_define_global_function("select", rb_f_select
, -1);
15552 rb_define_global_function("readlines", rb_f_readlines
, -1);
15554 rb_define_global_function("`", rb_f_backquote
, 1);
15556 rb_define_global_function("p", rb_f_p
, -1);
15557 rb_define_method(rb_mKernel
, "display", rb_obj_display
, -1);
15559 rb_cIO
= rb_define_class("IO", rb_cObject
);
15560 rb_include_module(rb_cIO
, rb_mEnumerable
);
15562 /* Can be raised by IO operations when IO#timeout= is set. */
15563 rb_eIOTimeoutError
= rb_define_class_under(rb_cIO
, "TimeoutError", rb_eIOError
);
15565 /* Readable event mask for IO#wait. */
15566 rb_define_const(rb_cIO
, "READABLE", INT2NUM(RUBY_IO_READABLE
));
15567 /* Writable event mask for IO#wait. */
15568 rb_define_const(rb_cIO
, "WRITABLE", INT2NUM(RUBY_IO_WRITABLE
));
15569 /* Priority event mask for IO#wait. */
15570 rb_define_const(rb_cIO
, "PRIORITY", INT2NUM(RUBY_IO_PRIORITY
));
15572 /* exception to wait for reading. see IO.select. */
15573 rb_mWaitReadable
= rb_define_module_under(rb_cIO
, "WaitReadable");
15574 /* exception to wait for writing. see IO.select. */
15575 rb_mWaitWritable
= rb_define_module_under(rb_cIO
, "WaitWritable");
15576 /* exception to wait for reading by EAGAIN. see IO.select. */
15577 rb_eEAGAINWaitReadable
= rb_define_class_under(rb_cIO
, "EAGAINWaitReadable", rb_eEAGAIN
);
15578 rb_include_module(rb_eEAGAINWaitReadable
, rb_mWaitReadable
);
15579 /* exception to wait for writing by EAGAIN. see IO.select. */
15580 rb_eEAGAINWaitWritable
= rb_define_class_under(rb_cIO
, "EAGAINWaitWritable", rb_eEAGAIN
);
15581 rb_include_module(rb_eEAGAINWaitWritable
, rb_mWaitWritable
);
15582 #if EAGAIN == EWOULDBLOCK
15583 rb_eEWOULDBLOCKWaitReadable
= rb_eEAGAINWaitReadable
;
15584 /* same as IO::EAGAINWaitReadable */
15585 rb_define_const(rb_cIO
, "EWOULDBLOCKWaitReadable", rb_eEAGAINWaitReadable
);
15586 rb_eEWOULDBLOCKWaitWritable
= rb_eEAGAINWaitWritable
;
15587 /* same as IO::EAGAINWaitWritable */
15588 rb_define_const(rb_cIO
, "EWOULDBLOCKWaitWritable", rb_eEAGAINWaitWritable
);
15590 /* exception to wait for reading by EWOULDBLOCK. see IO.select. */
15591 rb_eEWOULDBLOCKWaitReadable
= rb_define_class_under(rb_cIO
, "EWOULDBLOCKWaitReadable", rb_eEWOULDBLOCK
);
15592 rb_include_module(rb_eEWOULDBLOCKWaitReadable
, rb_mWaitReadable
);
15593 /* exception to wait for writing by EWOULDBLOCK. see IO.select. */
15594 rb_eEWOULDBLOCKWaitWritable
= rb_define_class_under(rb_cIO
, "EWOULDBLOCKWaitWritable", rb_eEWOULDBLOCK
);
15595 rb_include_module(rb_eEWOULDBLOCKWaitWritable
, rb_mWaitWritable
);
15597 /* exception to wait for reading by EINPROGRESS. see IO.select. */
15598 rb_eEINPROGRESSWaitReadable
= rb_define_class_under(rb_cIO
, "EINPROGRESSWaitReadable", rb_eEINPROGRESS
);
15599 rb_include_module(rb_eEINPROGRESSWaitReadable
, rb_mWaitReadable
);
15600 /* exception to wait for writing by EINPROGRESS. see IO.select. */
15601 rb_eEINPROGRESSWaitWritable
= rb_define_class_under(rb_cIO
, "EINPROGRESSWaitWritable", rb_eEINPROGRESS
);
15602 rb_include_module(rb_eEINPROGRESSWaitWritable
, rb_mWaitWritable
);
15605 /* This is necessary only for forcing rdoc handle File::open */
15606 rb_define_singleton_method(rb_cFile
, "open", rb_io_s_open
, -1);
15609 rb_define_alloc_func(rb_cIO
, io_alloc
);
15610 rb_define_singleton_method(rb_cIO
, "new", rb_io_s_new
, -1);
15611 rb_define_singleton_method(rb_cIO
, "open", rb_io_s_open
, -1);
15612 rb_define_singleton_method(rb_cIO
, "sysopen", rb_io_s_sysopen
, -1);
15613 rb_define_singleton_method(rb_cIO
, "for_fd", rb_io_s_for_fd
, -1);
15614 rb_define_singleton_method(rb_cIO
, "popen", rb_io_s_popen
, -1);
15615 rb_define_singleton_method(rb_cIO
, "foreach", rb_io_s_foreach
, -1);
15616 rb_define_singleton_method(rb_cIO
, "readlines", rb_io_s_readlines
, -1);
15617 rb_define_singleton_method(rb_cIO
, "read", rb_io_s_read
, -1);
15618 rb_define_singleton_method(rb_cIO
, "binread", rb_io_s_binread
, -1);
15619 rb_define_singleton_method(rb_cIO
, "write", rb_io_s_write
, -1);
15620 rb_define_singleton_method(rb_cIO
, "binwrite", rb_io_s_binwrite
, -1);
15621 rb_define_singleton_method(rb_cIO
, "select", rb_f_select
, -1);
15622 rb_define_singleton_method(rb_cIO
, "pipe", rb_io_s_pipe
, -1);
15623 rb_define_singleton_method(rb_cIO
, "try_convert", rb_io_s_try_convert
, 1);
15624 rb_define_singleton_method(rb_cIO
, "copy_stream", rb_io_s_copy_stream
, -1);
15626 rb_define_method(rb_cIO
, "initialize", rb_io_initialize
, -1);
15628 rb_output_fs
= Qnil
;
15629 rb_define_hooked_variable("$,", &rb_output_fs
, 0, deprecated_str_setter
);
15631 rb_default_rs
= rb_fstring_lit("\n"); /* avoid modifying RS_default */
15632 rb_vm_register_global_object(rb_default_rs
);
15633 rb_rs
= rb_default_rs
;
15634 rb_output_rs
= Qnil
;
15635 rb_define_hooked_variable("$/", &rb_rs
, 0, deprecated_str_setter
);
15636 rb_define_hooked_variable("$-0", &rb_rs
, 0, deprecated_str_setter
);
15637 rb_define_hooked_variable("$\\", &rb_output_rs
, 0, deprecated_str_setter
);
15639 rb_define_virtual_variable("$_", get_LAST_READ_LINE
, set_LAST_READ_LINE
);
15640 rb_gvar_ractor_local("$_");
15642 rb_define_method(rb_cIO
, "initialize_copy", rb_io_init_copy
, 1);
15643 rb_define_method(rb_cIO
, "reopen", rb_io_reopen
, -1);
15645 rb_define_method(rb_cIO
, "print", rb_io_print
, -1);
15646 rb_define_method(rb_cIO
, "putc", rb_io_putc
, 1);
15647 rb_define_method(rb_cIO
, "puts", rb_io_puts
, -1);
15648 rb_define_method(rb_cIO
, "printf", rb_io_printf
, -1);
15650 rb_define_method(rb_cIO
, "each", rb_io_each_line
, -1);
15651 rb_define_method(rb_cIO
, "each_line", rb_io_each_line
, -1);
15652 rb_define_method(rb_cIO
, "each_byte", rb_io_each_byte
, 0);
15653 rb_define_method(rb_cIO
, "each_char", rb_io_each_char
, 0);
15654 rb_define_method(rb_cIO
, "each_codepoint", rb_io_each_codepoint
, 0);
15656 rb_define_method(rb_cIO
, "syswrite", rb_io_syswrite
, 1);
15657 rb_define_method(rb_cIO
, "sysread", rb_io_sysread
, -1);
15659 rb_define_method(rb_cIO
, "pread", rb_io_pread
, -1);
15660 rb_define_method(rb_cIO
, "pwrite", rb_io_pwrite
, 2);
15662 rb_define_method(rb_cIO
, "fileno", rb_io_fileno
, 0);
15663 rb_define_alias(rb_cIO
, "to_i", "fileno");
15664 rb_define_method(rb_cIO
, "to_io", rb_io_to_io
, 0);
15666 rb_define_method(rb_cIO
, "timeout", rb_io_timeout
, 0);
15667 rb_define_method(rb_cIO
, "timeout=", rb_io_set_timeout
, 1);
15669 rb_define_method(rb_cIO
, "fsync", rb_io_fsync
, 0);
15670 rb_define_method(rb_cIO
, "fdatasync", rb_io_fdatasync
, 0);
15671 rb_define_method(rb_cIO
, "sync", rb_io_sync
, 0);
15672 rb_define_method(rb_cIO
, "sync=", rb_io_set_sync
, 1);
15674 rb_define_method(rb_cIO
, "lineno", rb_io_lineno
, 0);
15675 rb_define_method(rb_cIO
, "lineno=", rb_io_set_lineno
, 1);
15677 rb_define_method(rb_cIO
, "readlines", rb_io_readlines
, -1);
15679 rb_define_method(rb_cIO
, "readpartial", io_readpartial
, -1);
15680 rb_define_method(rb_cIO
, "read", io_read
, -1);
15681 rb_define_method(rb_cIO
, "write", io_write_m
, -1);
15682 rb_define_method(rb_cIO
, "gets", rb_io_gets_m
, -1);
15683 rb_define_method(rb_cIO
, "getc", rb_io_getc
, 0);
15684 rb_define_method(rb_cIO
, "getbyte", rb_io_getbyte
, 0);
15685 rb_define_method(rb_cIO
, "readchar", rb_io_readchar
, 0);
15686 rb_define_method(rb_cIO
, "readbyte", rb_io_readbyte
, 0);
15687 rb_define_method(rb_cIO
, "ungetbyte",rb_io_ungetbyte
, 1);
15688 rb_define_method(rb_cIO
, "ungetc",rb_io_ungetc
, 1);
15689 rb_define_method(rb_cIO
, "<<", rb_io_addstr
, 1);
15690 rb_define_method(rb_cIO
, "flush", rb_io_flush
, 0);
15691 rb_define_method(rb_cIO
, "tell", rb_io_tell
, 0);
15692 rb_define_method(rb_cIO
, "seek", rb_io_seek_m
, -1);
15693 /* Set I/O position from the beginning */
15694 rb_define_const(rb_cIO
, "SEEK_SET", INT2FIX(SEEK_SET
));
15695 /* Set I/O position from the current position */
15696 rb_define_const(rb_cIO
, "SEEK_CUR", INT2FIX(SEEK_CUR
));
15697 /* Set I/O position from the end */
15698 rb_define_const(rb_cIO
, "SEEK_END", INT2FIX(SEEK_END
));
15700 /* Set I/O position to the next location containing data */
15701 rb_define_const(rb_cIO
, "SEEK_DATA", INT2FIX(SEEK_DATA
));
15704 /* Set I/O position to the next hole */
15705 rb_define_const(rb_cIO
, "SEEK_HOLE", INT2FIX(SEEK_HOLE
));
15707 rb_define_method(rb_cIO
, "rewind", rb_io_rewind
, 0);
15708 rb_define_method(rb_cIO
, "pos", rb_io_tell
, 0);
15709 rb_define_method(rb_cIO
, "pos=", rb_io_set_pos
, 1);
15710 rb_define_method(rb_cIO
, "eof", rb_io_eof
, 0);
15711 rb_define_method(rb_cIO
, "eof?", rb_io_eof
, 0);
15713 rb_define_method(rb_cIO
, "close_on_exec?", rb_io_close_on_exec_p
, 0);
15714 rb_define_method(rb_cIO
, "close_on_exec=", rb_io_set_close_on_exec
, 1);
15716 rb_define_method(rb_cIO
, "close", rb_io_close_m
, 0);
15717 rb_define_method(rb_cIO
, "closed?", rb_io_closed_p
, 0);
15718 rb_define_method(rb_cIO
, "close_read", rb_io_close_read
, 0);
15719 rb_define_method(rb_cIO
, "close_write", rb_io_close_write
, 0);
15721 rb_define_method(rb_cIO
, "isatty", rb_io_isatty
, 0);
15722 rb_define_method(rb_cIO
, "tty?", rb_io_isatty
, 0);
15723 rb_define_method(rb_cIO
, "binmode", rb_io_binmode_m
, 0);
15724 rb_define_method(rb_cIO
, "binmode?", rb_io_binmode_p
, 0);
15725 rb_define_method(rb_cIO
, "sysseek", rb_io_sysseek
, -1);
15726 rb_define_method(rb_cIO
, "advise", rb_io_advise
, -1);
15728 rb_define_method(rb_cIO
, "ioctl", rb_io_ioctl
, -1);
15729 rb_define_method(rb_cIO
, "fcntl", rb_io_fcntl
, -1);
15730 rb_define_method(rb_cIO
, "pid", rb_io_pid
, 0);
15732 rb_define_method(rb_cIO
, "path", rb_io_path
, 0);
15733 rb_define_method(rb_cIO
, "to_path", rb_io_path
, 0);
15735 rb_define_method(rb_cIO
, "inspect", rb_io_inspect
, 0);
15737 rb_define_method(rb_cIO
, "external_encoding", rb_io_external_encoding
, 0);
15738 rb_define_method(rb_cIO
, "internal_encoding", rb_io_internal_encoding
, 0);
15739 rb_define_method(rb_cIO
, "set_encoding", rb_io_set_encoding
, -1);
15740 rb_define_method(rb_cIO
, "set_encoding_by_bom", rb_io_set_encoding_by_bom
, 0);
15742 rb_define_method(rb_cIO
, "autoclose?", rb_io_autoclose_p
, 0);
15743 rb_define_method(rb_cIO
, "autoclose=", rb_io_set_autoclose
, 1);
15745 rb_define_method(rb_cIO
, "wait", io_wait
, -1);
15747 rb_define_method(rb_cIO
, "wait_readable", io_wait_readable
, -1);
15748 rb_define_method(rb_cIO
, "wait_writable", io_wait_writable
, -1);
15749 rb_define_method(rb_cIO
, "wait_priority", io_wait_priority
, -1);
15751 rb_define_virtual_variable("$stdin", stdin_getter
, stdin_setter
);
15752 rb_define_virtual_variable("$stdout", stdout_getter
, stdout_setter
);
15753 rb_define_virtual_variable("$>", stdout_getter
, stdout_setter
);
15754 rb_define_virtual_variable("$stderr", stderr_getter
, stderr_setter
);
15756 rb_gvar_ractor_local("$stdin");
15757 rb_gvar_ractor_local("$stdout");
15758 rb_gvar_ractor_local("$>");
15759 rb_gvar_ractor_local("$stderr");
15761 rb_global_variable(&rb_stdin
);
15762 rb_stdin
= rb_io_prep_stdin();
15763 rb_global_variable(&rb_stdout
);
15764 rb_stdout
= rb_io_prep_stdout();
15765 rb_global_variable(&rb_stderr
);
15766 rb_stderr
= rb_io_prep_stderr();
15768 orig_stdout
= rb_stdout
;
15769 orig_stderr
= rb_stderr
;
15771 /* Holds the original stdin */
15772 rb_define_global_const("STDIN", rb_stdin
);
15773 /* Holds the original stdout */
15774 rb_define_global_const("STDOUT", rb_stdout
);
15775 /* Holds the original stderr */
15776 rb_define_global_const("STDERR", rb_stderr
);
15779 /* Hack to get rdoc to regard ARGF as a class: */
15780 rb_cARGF
= rb_define_class("ARGF", rb_cObject
);
15783 rb_cARGF
= rb_class_new(rb_cObject
);
15784 rb_set_class_path(rb_cARGF
, rb_cObject
, "ARGF.class");
15785 rb_define_alloc_func(rb_cARGF
, argf_alloc
);
15787 rb_include_module(rb_cARGF
, rb_mEnumerable
);
15789 rb_define_method(rb_cARGF
, "initialize", argf_initialize
, -2);
15790 rb_define_method(rb_cARGF
, "initialize_copy", argf_initialize_copy
, 1);
15791 rb_define_method(rb_cARGF
, "to_s", argf_to_s
, 0);
15792 rb_define_alias(rb_cARGF
, "inspect", "to_s");
15793 rb_define_method(rb_cARGF
, "argv", argf_argv
, 0);
15795 rb_define_method(rb_cARGF
, "fileno", argf_fileno
, 0);
15796 rb_define_method(rb_cARGF
, "to_i", argf_fileno
, 0);
15797 rb_define_method(rb_cARGF
, "to_io", argf_to_io
, 0);
15798 rb_define_method(rb_cARGF
, "to_write_io", argf_write_io
, 0);
15799 rb_define_method(rb_cARGF
, "each", argf_each_line
, -1);
15800 rb_define_method(rb_cARGF
, "each_line", argf_each_line
, -1);
15801 rb_define_method(rb_cARGF
, "each_byte", argf_each_byte
, 0);
15802 rb_define_method(rb_cARGF
, "each_char", argf_each_char
, 0);
15803 rb_define_method(rb_cARGF
, "each_codepoint", argf_each_codepoint
, 0);
15805 rb_define_method(rb_cARGF
, "read", argf_read
, -1);
15806 rb_define_method(rb_cARGF
, "readpartial", argf_readpartial
, -1);
15807 rb_define_method(rb_cARGF
, "read_nonblock", argf_read_nonblock
, -1);
15808 rb_define_method(rb_cARGF
, "readlines", argf_readlines
, -1);
15809 rb_define_method(rb_cARGF
, "to_a", argf_readlines
, -1);
15810 rb_define_method(rb_cARGF
, "gets", argf_gets
, -1);
15811 rb_define_method(rb_cARGF
, "readline", argf_readline
, -1);
15812 rb_define_method(rb_cARGF
, "getc", argf_getc
, 0);
15813 rb_define_method(rb_cARGF
, "getbyte", argf_getbyte
, 0);
15814 rb_define_method(rb_cARGF
, "readchar", argf_readchar
, 0);
15815 rb_define_method(rb_cARGF
, "readbyte", argf_readbyte
, 0);
15816 rb_define_method(rb_cARGF
, "tell", argf_tell
, 0);
15817 rb_define_method(rb_cARGF
, "seek", argf_seek_m
, -1);
15818 rb_define_method(rb_cARGF
, "rewind", argf_rewind
, 0);
15819 rb_define_method(rb_cARGF
, "pos", argf_tell
, 0);
15820 rb_define_method(rb_cARGF
, "pos=", argf_set_pos
, 1);
15821 rb_define_method(rb_cARGF
, "eof", argf_eof
, 0);
15822 rb_define_method(rb_cARGF
, "eof?", argf_eof
, 0);
15823 rb_define_method(rb_cARGF
, "binmode", argf_binmode_m
, 0);
15824 rb_define_method(rb_cARGF
, "binmode?", argf_binmode_p
, 0);
15826 rb_define_method(rb_cARGF
, "write", argf_write
, -1);
15827 rb_define_method(rb_cARGF
, "print", rb_io_print
, -1);
15828 rb_define_method(rb_cARGF
, "putc", rb_io_putc
, 1);
15829 rb_define_method(rb_cARGF
, "puts", rb_io_puts
, -1);
15830 rb_define_method(rb_cARGF
, "printf", rb_io_printf
, -1);
15832 rb_define_method(rb_cARGF
, "filename", argf_filename
, 0);
15833 rb_define_method(rb_cARGF
, "path", argf_filename
, 0);
15834 rb_define_method(rb_cARGF
, "file", argf_file
, 0);
15835 rb_define_method(rb_cARGF
, "skip", argf_skip
, 0);
15836 rb_define_method(rb_cARGF
, "close", argf_close_m
, 0);
15837 rb_define_method(rb_cARGF
, "closed?", argf_closed
, 0);
15839 rb_define_method(rb_cARGF
, "lineno", argf_lineno
, 0);
15840 rb_define_method(rb_cARGF
, "lineno=", argf_set_lineno
, 1);
15842 rb_define_method(rb_cARGF
, "inplace_mode", argf_inplace_mode_get
, 0);
15843 rb_define_method(rb_cARGF
, "inplace_mode=", argf_inplace_mode_set
, 1);
15845 rb_define_method(rb_cARGF
, "external_encoding", argf_external_encoding
, 0);
15846 rb_define_method(rb_cARGF
, "internal_encoding", argf_internal_encoding
, 0);
15847 rb_define_method(rb_cARGF
, "set_encoding", argf_set_encoding
, -1);
15849 argf
= rb_class_new_instance(0, 0, rb_cARGF
);
15851 rb_define_readonly_variable("$<", &argf
);
15853 * ARGF is a stream designed for use in scripts that process files given
15854 * as command-line arguments or passed in via STDIN.
15856 * See ARGF (the class) for more details.
15858 rb_define_global_const("ARGF", argf
);
15860 rb_define_hooked_variable("$.", &argf
, argf_lineno_getter
, argf_lineno_setter
);
15861 rb_define_hooked_variable("$FILENAME", &argf
, argf_filename_getter
, rb_gvar_readonly_setter
);
15862 ARGF
.filename
= rb_str_new2("-");
15864 rb_define_hooked_variable("$-i", &argf
, opt_i_get
, opt_i_set
);
15865 rb_gvar_ractor_local("$-i");
15867 rb_define_hooked_variable("$*", &argf
, argf_argv_getter
, rb_gvar_readonly_setter
);
15869 #if defined (_WIN32) || defined(__CYGWIN__)
15870 atexit(pipe_atexit
);
15875 rb_define_method(rb_cFile
, "initialize", rb_file_initialize
, -1);
15877 sym_mode
= ID2SYM(rb_intern_const("mode"));
15878 sym_perm
= ID2SYM(rb_intern_const("perm"));
15879 sym_flags
= ID2SYM(rb_intern_const("flags"));
15880 sym_extenc
= ID2SYM(rb_intern_const("external_encoding"));
15881 sym_intenc
= ID2SYM(rb_intern_const("internal_encoding"));
15882 sym_encoding
= ID2SYM(rb_id_encoding());
15883 sym_open_args
= ID2SYM(rb_intern_const("open_args"));
15884 sym_textmode
= ID2SYM(rb_intern_const("textmode"));
15885 sym_binmode
= ID2SYM(rb_intern_const("binmode"));
15886 sym_autoclose
= ID2SYM(rb_intern_const("autoclose"));
15887 sym_normal
= ID2SYM(rb_intern_const("normal"));
15888 sym_sequential
= ID2SYM(rb_intern_const("sequential"));
15889 sym_random
= ID2SYM(rb_intern_const("random"));
15890 sym_willneed
= ID2SYM(rb_intern_const("willneed"));
15891 sym_dontneed
= ID2SYM(rb_intern_const("dontneed"));
15892 sym_noreuse
= ID2SYM(rb_intern_const("noreuse"));
15893 sym_SET
= ID2SYM(rb_intern_const("SET"));
15894 sym_CUR
= ID2SYM(rb_intern_const("CUR"));
15895 sym_END
= ID2SYM(rb_intern_const("END"));
15897 sym_DATA
= ID2SYM(rb_intern_const("DATA"));
15900 sym_HOLE
= ID2SYM(rb_intern_const("HOLE"));
15902 sym_wait_readable
= ID2SYM(rb_intern_const("wait_readable"));
15903 sym_wait_writable
= ID2SYM(rb_intern_const("wait_writable"));
15906 #include "io.rbinc"