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"
20 # include "ruby/ruby.h"
28 /* non-Linux poll may not work on all FDs */
29 #if defined(HAVE_POLL)
30 # if defined(__linux__)
33 # if defined(__FreeBSD_version) && __FreeBSD_version >= 1100000
43 #define free(x) xfree(x)
45 #if defined(DOSISH) || defined(__CYGWIN__)
49 #include <sys/types.h>
50 #if defined HAVE_NET_SOCKET_H
51 # include <net/socket.h>
52 #elif defined HAVE_SYS_SOCKET_H
53 # include <sys/socket.h>
56 #if defined(__BOW__) || defined(__CYGWIN__) || defined(_WIN32)
57 # define NO_SAFE_RENAME
60 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__sun) || defined(_nec_ews)
68 #include <sys/types.h>
69 #if defined(HAVE_SYS_IOCTL_H) && !defined(_WIN32)
70 #include <sys/ioctl.h>
72 #if defined(HAVE_FCNTL_H) || defined(_WIN32)
74 #elif defined(HAVE_SYS_FCNTL_H)
75 #include <sys/fcntl.h>
78 #if !HAVE_OFF_T && !defined(off_t)
82 #ifdef HAVE_SYS_TIME_H
83 # include <sys/time.h>
88 #if defined(HAVE_SYS_PARAM_H) || defined(__HIUX_MPP__)
89 # include <sys/param.h>
100 #ifdef HAVE_SYSCALL_H
102 #elif defined HAVE_SYS_SYSCALL_H
103 #include <sys/syscall.h>
106 #ifdef HAVE_SYS_UIO_H
110 #ifdef HAVE_SYS_WAIT_H
111 # include <sys/wait.h> /* for WNOHANG on BSD */
114 #ifdef HAVE_COPYFILE_H
115 # include <copyfile.h>
118 #include "ruby/internal/stdbool.h"
119 #include "ccan/list/list.h"
121 #include "encindex.h"
123 #include "internal.h"
124 #include "internal/encoding.h"
125 #include "internal/error.h"
126 #include "internal/inits.h"
127 #include "internal/io.h"
128 #include "internal/numeric.h"
129 #include "internal/object.h"
130 #include "internal/process.h"
131 #include "internal/thread.h"
132 #include "internal/transcode.h"
133 #include "internal/variable.h"
135 #include "ruby/io/buffer.h"
136 #include "ruby/thread.h"
137 #include "ruby/util.h"
138 #include "ruby_atomic.h"
139 #include "ruby/ractor.h"
142 # include "vm_core.h"
148 #define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR)
151 #if SIZEOF_OFF_T > SIZEOF_LONG && !defined(HAVE_LONG_LONG)
152 # error off_t is bigger than long, but you have no long long...
156 # ifdef _POSIX_PIPE_BUF
157 # define PIPE_BUF _POSIX_PIPE_BUF
159 # define PIPE_BUF 512 /* is this ok? */
164 # define EWOULDBLOCK EAGAIN
167 #if defined(HAVE___SYSCALL) && (defined(__APPLE__) || defined(__OpenBSD__))
168 /* Mac OS X and OpenBSD have __syscall but don't define it in headers */
169 off_t
__syscall(quad_t number
, ...);
172 #define IO_RBUF_CAPA_MIN 8192
173 #define IO_CBUF_CAPA_MIN (128*1024)
174 #define IO_RBUF_CAPA_FOR(fptr) (NEED_READCONV(fptr) ? IO_CBUF_CAPA_MIN : IO_RBUF_CAPA_MIN)
175 #define IO_WBUF_CAPA_MIN 8192
177 /* define system APIs */
180 #define open rb_w32_uopen
182 #define rename(f, t) rb_w32_urename((f), (t))
188 VALUE rb_mWaitReadable
;
189 VALUE rb_mWaitWritable
;
191 static VALUE rb_eEAGAINWaitReadable
;
192 static VALUE rb_eEAGAINWaitWritable
;
193 static VALUE rb_eEWOULDBLOCKWaitReadable
;
194 static VALUE rb_eEWOULDBLOCKWaitWritable
;
195 static VALUE rb_eEINPROGRESSWaitWritable
;
196 static VALUE rb_eEINPROGRESSWaitReadable
;
198 VALUE rb_stdin
, rb_stdout
, rb_stderr
;
199 static VALUE orig_stdout
, orig_stderr
;
208 static ID id_write
, id_read
, id_getc
, id_flush
, id_readpartial
, id_set_encoding
, id_fileno
;
209 static VALUE sym_mode
, sym_perm
, sym_flags
, sym_extenc
, sym_intenc
, sym_encoding
, sym_open_args
;
210 static VALUE sym_textmode
, sym_binmode
, sym_autoclose
;
211 static VALUE sym_SET
, sym_CUR
, sym_END
;
212 static VALUE sym_wait_readable
, sym_wait_writable
;
214 static VALUE sym_DATA
;
217 static VALUE sym_HOLE
;
220 static VALUE
prep_io(int fd
, int fmode
, VALUE klass
, const char *path
);
223 VALUE filename
, current_file
;
224 long last_lineno
; /* $. */
228 struct rb_io_enc_t encs
;
229 int8_t init_p
, next_p
, binmode
;
232 static rb_atomic_t max_file_descriptor
= NOFILE
;
234 rb_update_max_fd(int fd
)
236 rb_atomic_t afd
= (rb_atomic_t
)fd
;
237 rb_atomic_t max_fd
= max_file_descriptor
;
240 if (fd
< 0 || afd
<= max_fd
)
243 #if defined(HAVE_FCNTL) && defined(F_GETFL)
244 err
= fcntl(fd
, F_GETFL
) == -1;
248 err
= fstat(fd
, &buf
) != 0;
251 if (err
&& errno
== EBADF
) {
252 rb_bug("rb_update_max_fd: invalid fd (%d) given.", fd
);
255 while (max_fd
< afd
) {
256 max_fd
= ATOMIC_CAS(max_file_descriptor
, max_fd
, afd
);
261 rb_maygvl_fd_fix_cloexec(int fd
)
263 /* MinGW don't have F_GETFD and FD_CLOEXEC. [ruby-core:40281] */
264 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
265 int flags
, flags2
, ret
;
266 flags
= fcntl(fd
, F_GETFD
); /* should not fail except EBADF. */
268 rb_bug("rb_maygvl_fd_fix_cloexec: fcntl(%d, F_GETFD) failed: %s", fd
, strerror(errno
));
271 flags2
= flags
& ~FD_CLOEXEC
; /* Clear CLOEXEC for standard file descriptors: 0, 1, 2. */
273 flags2
= flags
| FD_CLOEXEC
; /* Set CLOEXEC for non-standard file descriptors: 3, 4, 5, ... */
274 if (flags
!= flags2
) {
275 ret
= fcntl(fd
, F_SETFD
, flags2
);
277 rb_bug("rb_maygvl_fd_fix_cloexec: fcntl(%d, F_SETFD, %d) failed: %s", fd
, flags2
, strerror(errno
));
284 rb_fd_fix_cloexec(int fd
)
286 rb_maygvl_fd_fix_cloexec(fd
);
287 rb_update_max_fd(fd
);
290 /* this is only called once */
292 rb_fix_detect_o_cloexec(int fd
)
294 #if defined(O_CLOEXEC) && defined(F_GETFD)
295 int flags
= fcntl(fd
, F_GETFD
);
298 rb_bug("rb_fix_detect_o_cloexec: fcntl(%d, F_GETFD) failed: %s", fd
, strerror(errno
));
300 if (flags
& FD_CLOEXEC
)
302 #endif /* fall through if O_CLOEXEC does not work: */
303 rb_maygvl_fd_fix_cloexec(fd
);
310 return (e
== EWOULDBLOCK
) || (e
== EAGAIN
);
314 rb_cloexec_open(const char *pathname
, int flags
, mode_t mode
)
317 static int o_cloexec_state
= -1; /* <0: unknown, 0: ignored, >0: working */
319 static const int retry_interval
= 0;
320 static const int retry_max_count
= 10000;
325 /* O_CLOEXEC is available since Linux 2.6.23. Linux 2.6.18 silently ignore it. */
327 #elif defined O_NOINHERIT
328 flags
|= O_NOINHERIT
;
331 while ((ret
= open(pathname
, flags
, mode
)) == -1) {
333 if (!io_again_p(e
)) break;
334 if (retry_count
++ >= retry_max_count
) break;
336 sleep(retry_interval
);
339 if (ret
< 0) return ret
;
340 if (ret
<= 2 || o_cloexec_state
== 0) {
341 rb_maygvl_fd_fix_cloexec(ret
);
343 else if (o_cloexec_state
> 0) {
347 o_cloexec_state
= rb_fix_detect_o_cloexec(ret
);
353 rb_cloexec_dup(int oldfd
)
355 /* Don't allocate standard file descriptors: 0, 1, 2 */
356 return rb_cloexec_fcntl_dupfd(oldfd
, 3);
360 rb_cloexec_dup2(int oldfd
, int newfd
)
364 /* When oldfd == newfd, dup2 succeeds but dup3 fails with EINVAL.
365 * rb_cloexec_dup2 succeeds as dup2. */
366 if (oldfd
== newfd
) {
370 #if defined(HAVE_DUP3) && defined(O_CLOEXEC)
371 static int try_dup3
= 1;
372 if (2 < newfd
&& try_dup3
) {
373 ret
= dup3(oldfd
, newfd
, O_CLOEXEC
);
376 /* dup3 is available since Linux 2.6.27, glibc 2.9. */
377 if (errno
== ENOSYS
) {
379 ret
= dup2(oldfd
, newfd
);
383 ret
= dup2(oldfd
, newfd
);
386 ret
= dup2(oldfd
, newfd
);
388 if (ret
< 0) return ret
;
390 rb_maygvl_fd_fix_cloexec(ret
);
395 rb_fd_set_nonblock(int fd
)
398 return rb_w32_set_nonblock(fd
);
399 #elif defined(F_GETFL)
400 int oflags
= fcntl(fd
, F_GETFL
);
404 if (oflags
& O_NONBLOCK
)
406 oflags
|= O_NONBLOCK
;
407 return fcntl(fd
, F_SETFL
, oflags
);
413 rb_cloexec_pipe(int descriptors
[2])
416 int result
= pipe2(descriptors
, O_CLOEXEC
| O_NONBLOCK
);
418 int result
= pipe(descriptors
);
425 if (result
== 0 && descriptors
[1] == -1) {
426 close(descriptors
[0]);
434 rb_maygvl_fd_fix_cloexec(descriptors
[0]);
435 rb_maygvl_fd_fix_cloexec(descriptors
[1]);
438 rb_fd_set_nonblock(descriptors
[0]);
439 rb_fd_set_nonblock(descriptors
[1]);
447 rb_cloexec_fcntl_dupfd(int fd
, int minfd
)
451 #if defined(HAVE_FCNTL) && defined(F_DUPFD_CLOEXEC) && defined(F_DUPFD)
452 static int try_dupfd_cloexec
= 1;
453 if (try_dupfd_cloexec
) {
454 ret
= fcntl(fd
, F_DUPFD_CLOEXEC
, minfd
);
457 rb_maygvl_fd_fix_cloexec(ret
);
460 /* F_DUPFD_CLOEXEC is available since Linux 2.6.24. Linux 2.6.18 fails with EINVAL */
461 if (errno
== EINVAL
) {
462 ret
= fcntl(fd
, F_DUPFD
, minfd
);
464 try_dupfd_cloexec
= 0;
469 ret
= fcntl(fd
, F_DUPFD
, minfd
);
471 #elif defined(HAVE_FCNTL) && defined(F_DUPFD)
472 ret
= fcntl(fd
, F_DUPFD
, minfd
);
475 if (ret
>= 0 && ret
< minfd
) {
476 const int prev_fd
= ret
;
477 ret
= rb_cloexec_fcntl_dupfd(fd
, minfd
);
482 if (ret
< 0) return ret
;
483 rb_maygvl_fd_fix_cloexec(ret
);
487 #define argf_of(obj) (*(struct argf *)DATA_PTR(obj))
488 #define ARGF argf_of(argf)
490 #define GetWriteIO(io) rb_io_get_write_io(io)
492 #define READ_DATA_PENDING(fptr) ((fptr)->rbuf.len)
493 #define READ_DATA_PENDING_COUNT(fptr) ((fptr)->rbuf.len)
494 #define READ_DATA_PENDING_PTR(fptr) ((fptr)->rbuf.ptr+(fptr)->rbuf.off)
495 #define READ_DATA_BUFFERED(fptr) READ_DATA_PENDING(fptr)
497 #define READ_CHAR_PENDING(fptr) ((fptr)->cbuf.len)
498 #define READ_CHAR_PENDING_COUNT(fptr) ((fptr)->cbuf.len)
499 #define READ_CHAR_PENDING_PTR(fptr) ((fptr)->cbuf.ptr+(fptr)->cbuf.off)
502 #define WAIT_FD_IN_WIN32(fptr) \
503 (rb_w32_io_cancelable_p((fptr)->fd) ? Qnil : rb_io_wait(fptr->self, RB_INT2NUM(RUBY_IO_READABLE), Qnil))
505 #define WAIT_FD_IN_WIN32(fptr)
508 #define READ_CHECK(fptr) do {\
509 if (!READ_DATA_PENDING(fptr)) {\
510 WAIT_FD_IN_WIN32(fptr);\
511 rb_io_check_closed(fptr);\
517 # define S_ISSOCK(m) _S_ISSOCK(m)
520 # define S_ISSOCK(m) (((m) & S_IFMT) == _S_IFSOCK)
523 # define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
529 static int io_fflush(rb_io_t
*);
530 static rb_io_t
*flush_before_seek(rb_io_t
*fptr
);
532 #define FMODE_PREP (1<<16)
533 #define FMODE_SIGNAL_ON_EPIPE (1<<17)
535 #define fptr_signal_on_epipe(fptr) \
536 (((fptr)->mode & FMODE_SIGNAL_ON_EPIPE) != 0)
538 #define fptr_set_signal_on_epipe(fptr, flag) \
540 (fptr)->mode |= FMODE_SIGNAL_ON_EPIPE : \
541 (fptr)->mode &= ~FMODE_SIGNAL_ON_EPIPE)
543 extern ID ruby_static_id_signo
;
545 NORETURN(static void raise_on_write(rb_io_t
*fptr
, int e
, VALUE errinfo
));
547 raise_on_write(rb_io_t
*fptr
, int e
, VALUE errinfo
)
550 if (fptr_signal_on_epipe(fptr
) && (e
== EPIPE
)) {
553 INT2FIX(SIGPIPE
) - INT2FIX(0) +
556 rb_ivar_set(errinfo
, ruby_static_id_signo
, sig
);
559 rb_exc_raise(errinfo
);
562 #define rb_sys_fail_on_write(fptr) \
565 raise_on_write(fptr, e, rb_syserr_new_path(e, (fptr)->pathv)); \
568 #define NEED_NEWLINE_DECORATOR_ON_READ(fptr) ((fptr)->mode & FMODE_TEXTMODE)
569 #define NEED_NEWLINE_DECORATOR_ON_WRITE(fptr) ((fptr)->mode & FMODE_TEXTMODE)
570 #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
571 # define RUBY_CRLF_ENVIRONMENT 1
573 # define RUBY_CRLF_ENVIRONMENT 0
576 #if RUBY_CRLF_ENVIRONMENT
578 # define DEFAULT_TEXTMODE FMODE_TEXTMODE
579 # define TEXTMODE_NEWLINE_DECORATOR_ON_WRITE ECONV_CRLF_NEWLINE_DECORATOR
581 * CRLF newline is set as default newline decorator.
582 * If only CRLF newline conversion is needed, we use binary IO process
583 * with OS's text mode for IO performance improvement.
584 * If encoding conversion is needed or a user sets text mode, we use encoding
585 * conversion IO process and universal newline decorator by default.
587 #define NEED_READCONV(fptr) ((fptr)->encs.enc2 != NULL || (fptr)->encs.ecflags & ~ECONV_CRLF_NEWLINE_DECORATOR)
588 #define WRITECONV_MASK ( \
589 (ECONV_DECORATOR_MASK & ~ECONV_CRLF_NEWLINE_DECORATOR)|\
590 ECONV_STATEFUL_DECORATOR_MASK|\
592 #define NEED_WRITECONV(fptr) ( \
593 ((fptr)->encs.enc != NULL && (fptr)->encs.enc != rb_ascii8bit_encoding()) || \
594 ((fptr)->encs.ecflags & WRITECONV_MASK) || \
596 #define SET_BINARY_MODE(fptr) setmode((fptr)->fd, O_BINARY)
598 #define NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr) do {\
599 if (NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {\
600 if (((fptr)->mode & FMODE_READABLE) &&\
601 !((fptr)->encs.ecflags & ECONV_NEWLINE_DECORATOR_MASK)) {\
602 setmode((fptr)->fd, O_BINARY);\
605 setmode((fptr)->fd, O_TEXT);\
610 #define SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags) do {\
611 if ((enc2) && ((ecflags) & ECONV_DEFAULT_NEWLINE_DECORATOR)) {\
612 (ecflags) |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;\
617 * IO unread with taking care of removed '\r' in text mode.
620 io_unread(rb_io_t
*fptr
)
630 rb_io_check_closed(fptr
);
631 if (fptr
->rbuf
.len
== 0 || fptr
->mode
& FMODE_DUPLEX
) {
636 if (!rb_w32_fd_is_text(fptr
->fd
)) {
637 r
= lseek(fptr
->fd
, -fptr
->rbuf
.len
, SEEK_CUR
);
638 if (r
< 0 && errno
) {
640 fptr
->mode
|= FMODE_DUPLEX
;
649 pos
= lseek(fptr
->fd
, 0, SEEK_CUR
);
650 if (pos
< 0 && errno
) {
652 fptr
->mode
|= FMODE_DUPLEX
;
656 /* add extra offset for removed '\r' in rbuf */
657 extra_max
= (long)(pos
- fptr
->rbuf
.len
);
658 p
= fptr
->rbuf
.ptr
+ fptr
->rbuf
.off
;
660 /* if the end of rbuf is '\r', rbuf doesn't have '\r' within rbuf.len */
661 if (*(fptr
->rbuf
.ptr
+ fptr
->rbuf
.capa
- 1) == '\r') {
665 for (i
= 0; i
< fptr
->rbuf
.len
; i
++) {
666 if (*p
== '\n') newlines
++;
667 if (extra_max
== newlines
) break;
671 buf
= ALLOC_N(char, fptr
->rbuf
.len
+ newlines
);
672 while (newlines
>= 0) {
673 r
= lseek(fptr
->fd
, pos
- fptr
->rbuf
.len
- newlines
, SEEK_SET
);
674 if (newlines
== 0) break;
679 read_size
= _read(fptr
->fd
, buf
, fptr
->rbuf
.len
+ newlines
);
683 rb_syserr_fail_path(e
, fptr
->pathv
);
685 if (read_size
== fptr
->rbuf
.len
) {
686 lseek(fptr
->fd
, r
, SEEK_SET
);
700 * We use io_seek to back cursor position when changing mode from text to binary,
701 * but stdin and pipe cannot seek back. Stdin and pipe read should use encoding
702 * conversion for working properly with mode change.
704 * Return previous translation mode.
707 set_binary_mode_with_seek_cur(rb_io_t
*fptr
)
709 if (!rb_w32_fd_is_text(fptr
->fd
)) return O_BINARY
;
711 if (fptr
->rbuf
.len
== 0 || fptr
->mode
& FMODE_DUPLEX
) {
712 return setmode(fptr
->fd
, O_BINARY
);
714 flush_before_seek(fptr
);
715 return setmode(fptr
->fd
, O_BINARY
);
717 #define SET_BINARY_MODE_WITH_SEEK_CUR(fptr) set_binary_mode_with_seek_cur(fptr)
721 # define DEFAULT_TEXTMODE 0
722 #define NEED_READCONV(fptr) ((fptr)->encs.enc2 != NULL || NEED_NEWLINE_DECORATOR_ON_READ(fptr))
723 #define NEED_WRITECONV(fptr) ( \
724 ((fptr)->encs.enc != NULL && (fptr)->encs.enc != rb_ascii8bit_encoding()) || \
725 NEED_NEWLINE_DECORATOR_ON_WRITE(fptr) || \
726 ((fptr)->encs.ecflags & (ECONV_DECORATOR_MASK|ECONV_STATEFUL_DECORATOR_MASK)) || \
728 #define SET_BINARY_MODE(fptr) (void)(fptr)
729 #define NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr) (void)(fptr)
730 #define SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags) ((void)(enc2), (void)(ecflags))
731 #define SET_BINARY_MODE_WITH_SEEK_CUR(fptr) (void)(fptr)
734 #if !defined HAVE_SHUTDOWN && !defined shutdown
735 #define shutdown(a,b) 0
739 #define is_socket(fd, path) rb_w32_is_socket(fd)
740 #elif !defined(S_ISSOCK)
741 #define is_socket(fd, path) 0
744 is_socket(int fd
, VALUE path
)
747 if (fstat(fd
, &sbuf
) < 0)
748 rb_sys_fail_path(path
);
749 return S_ISSOCK(sbuf
.st_mode
);
753 static const char closed_stream
[] = "closed stream";
756 io_fd_check_closed(int fd
)
759 rb_thread_check_ints(); /* check for ruby_error_stream_closed */
760 rb_raise(rb_eIOError
, closed_stream
);
767 rb_raise(rb_eEOFError
, "end of file reached");
771 rb_io_taint_check(VALUE io
)
778 rb_io_check_initialized(rb_io_t
*fptr
)
781 rb_raise(rb_eIOError
, "uninitialized stream");
786 rb_io_check_closed(rb_io_t
*fptr
)
788 rb_io_check_initialized(fptr
);
789 io_fd_check_closed(fptr
->fd
);
793 rb_io_get_fptr(VALUE io
)
795 rb_io_t
*fptr
= RFILE(io
)->fptr
;
796 rb_io_check_initialized(fptr
);
801 rb_io_get_io(VALUE io
)
803 return rb_convert_type_with_id(io
, T_FILE
, "IO", idTo_io
);
807 rb_io_check_io(VALUE io
)
809 return rb_check_convert_type_with_id(io
, T_FILE
, "IO", idTo_io
);
813 rb_io_get_write_io(VALUE io
)
816 write_io
= rb_io_get_fptr(io
)->tied_io_for_writing
;
824 rb_io_set_write_io(VALUE io
, VALUE w
)
827 rb_io_t
*fptr
= rb_io_get_fptr(io
);
834 write_io
= fptr
->tied_io_for_writing
;
835 fptr
->tied_io_for_writing
= w
;
836 return write_io
? write_io
: Qnil
;
841 * IO.try_convert(object) -> new_io or nil
843 * Attempts to convert +object+ into an \IO object via method +to_io+;
844 * returns the new \IO object if successful, or +nil+ otherwise:
846 * IO.try_convert(STDOUT) # => #<IO:<STDOUT>>
847 * IO.try_convert(ARGF) # => #<IO:<STDIN>>
848 * IO.try_convert('STDOUT') # => nil
852 rb_io_s_try_convert(VALUE dummy
, VALUE io
)
854 return rb_io_check_io(io
);
857 #if !RUBY_CRLF_ENVIRONMENT
859 io_unread(rb_io_t
*fptr
)
862 rb_io_check_closed(fptr
);
863 if (fptr
->rbuf
.len
== 0 || fptr
->mode
& FMODE_DUPLEX
)
865 /* xxx: target position may be negative if buffer is filled by ungetc */
867 r
= lseek(fptr
->fd
, -fptr
->rbuf
.len
, SEEK_CUR
);
868 if (r
< 0 && errno
) {
870 fptr
->mode
|= FMODE_DUPLEX
;
879 static rb_encoding
*io_input_encoding(rb_io_t
*fptr
);
882 io_ungetbyte(VALUE str
, rb_io_t
*fptr
)
884 long len
= RSTRING_LEN(str
);
886 if (fptr
->rbuf
.ptr
== NULL
) {
887 const int min_capa
= IO_RBUF_CAPA_FOR(fptr
);
890 #if SIZEOF_LONG > SIZEOF_INT
892 rb_raise(rb_eIOError
, "ungetbyte failed");
895 fptr
->rbuf
.capa
= (int)len
;
897 fptr
->rbuf
.capa
= min_capa
;
898 fptr
->rbuf
.ptr
= ALLOC_N(char, fptr
->rbuf
.capa
);
900 if (fptr
->rbuf
.capa
< len
+ fptr
->rbuf
.len
) {
901 rb_raise(rb_eIOError
, "ungetbyte failed");
903 if (fptr
->rbuf
.off
< len
) {
904 MEMMOVE(fptr
->rbuf
.ptr
+fptr
->rbuf
.capa
-fptr
->rbuf
.len
,
905 fptr
->rbuf
.ptr
+fptr
->rbuf
.off
,
906 char, fptr
->rbuf
.len
);
907 fptr
->rbuf
.off
= fptr
->rbuf
.capa
-fptr
->rbuf
.len
;
909 fptr
->rbuf
.off
-=(int)len
;
910 fptr
->rbuf
.len
+=(int)len
;
911 MEMMOVE(fptr
->rbuf
.ptr
+fptr
->rbuf
.off
, RSTRING_PTR(str
), char, len
);
915 flush_before_seek(rb_io_t
*fptr
)
917 if (io_fflush(fptr
) < 0)
918 rb_sys_fail_on_write(fptr
);
924 #define io_seek(fptr, ofs, whence) (errno = 0, lseek(flush_before_seek(fptr)->fd, (ofs), (whence)))
925 #define io_tell(fptr) lseek(flush_before_seek(fptr)->fd, 0, SEEK_CUR)
934 rb_io_check_char_readable(rb_io_t
*fptr
)
936 rb_io_check_closed(fptr
);
937 if (!(fptr
->mode
& FMODE_READABLE
)) {
938 rb_raise(rb_eIOError
, "not opened for reading");
940 if (fptr
->wbuf
.len
) {
941 if (io_fflush(fptr
) < 0)
942 rb_sys_fail_on_write(fptr
);
944 if (fptr
->tied_io_for_writing
) {
946 GetOpenFile(fptr
->tied_io_for_writing
, wfptr
);
947 if (io_fflush(wfptr
) < 0)
948 rb_sys_fail_on_write(wfptr
);
953 rb_io_check_byte_readable(rb_io_t
*fptr
)
955 rb_io_check_char_readable(fptr
);
956 if (READ_CHAR_PENDING(fptr
)) {
957 rb_raise(rb_eIOError
, "byte oriented read for character buffered IO");
962 rb_io_check_readable(rb_io_t
*fptr
)
964 rb_io_check_byte_readable(fptr
);
968 io_read_encoding(rb_io_t
*fptr
)
970 if (fptr
->encs
.enc
) {
971 return fptr
->encs
.enc
;
973 return rb_default_external_encoding();
977 io_input_encoding(rb_io_t
*fptr
)
979 if (fptr
->encs
.enc2
) {
980 return fptr
->encs
.enc2
;
982 return io_read_encoding(fptr
);
986 rb_io_check_writable(rb_io_t
*fptr
)
988 rb_io_check_closed(fptr
);
989 if (!(fptr
->mode
& FMODE_WRITABLE
)) {
990 rb_raise(rb_eIOError
, "not opened for writing");
992 if (fptr
->rbuf
.len
) {
998 rb_io_read_pending(rb_io_t
*fptr
)
1000 /* This function is used for bytes and chars. Confusing. */
1001 if (READ_CHAR_PENDING(fptr
))
1002 return 1; /* should raise? */
1003 return READ_DATA_PENDING(fptr
);
1007 rb_io_read_check(rb_io_t
*fptr
)
1009 if (!READ_DATA_PENDING(fptr
)) {
1010 rb_io_wait(fptr
->self
, RB_INT2NUM(RUBY_IO_READABLE
), Qnil
);
1016 rb_gc_for_fd(int err
)
1018 if (err
== EMFILE
|| err
== ENFILE
|| err
== ENOMEM
) {
1030 fd
= rb_cloexec_dup(orig
);
1033 if (rb_gc_for_fd(e
)) {
1034 fd
= rb_cloexec_dup(orig
);
1037 rb_syserr_fail(e
, 0);
1040 rb_update_max_fd(fd
);
1045 io_alloc(VALUE klass
)
1047 NEWOBJ_OF(io
, struct RFile
, klass
, T_FILE
);
1055 # define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
1058 struct io_internal_read_struct
{
1066 struct io_internal_write_struct
{
1073 struct io_internal_writev_struct
{
1076 const struct iovec
*iov
;
1080 static int nogvl_wait_for(VALUE th
, rb_io_t
*fptr
, short events
);
1082 internal_read_func(void *ptr
)
1084 struct io_internal_read_struct
*iis
= ptr
;
1087 r
= read(iis
->fptr
->fd
, iis
->buf
, iis
->capa
);
1088 if (r
< 0 && !iis
->nonblock
) {
1090 if (io_again_p(e
)) {
1091 if (nogvl_wait_for(iis
->th
, iis
->fptr
, RB_WAITFD_IN
) != -1) {
1100 #if defined __APPLE__
1101 # define do_write_retry(code) do {ret = code;} while (ret == -1 && errno == EPROTOTYPE)
1103 # define do_write_retry(code) ret = code
1106 internal_write_func(void *ptr
)
1108 struct io_internal_write_struct
*iis
= ptr
;
1110 do_write_retry(write(iis
->fd
, iis
->buf
, iis
->capa
));
1115 internal_write_func2(void *ptr
)
1117 return (void*)internal_write_func(ptr
);
1122 internal_writev_func(void *ptr
)
1124 struct io_internal_writev_struct
*iis
= ptr
;
1126 do_write_retry(writev(iis
->fd
, iis
->iov
, iis
->iovcnt
));
1132 rb_read_internal(rb_io_t
*fptr
, void *buf
, size_t count
)
1134 VALUE scheduler
= rb_fiber_scheduler_current();
1135 if (scheduler
!= Qnil
) {
1136 VALUE result
= rb_fiber_scheduler_io_read_memory(scheduler
, fptr
->self
, buf
, count
, 0);
1138 if (result
!= Qundef
) {
1139 return rb_fiber_scheduler_io_result_apply(result
);
1143 struct io_internal_read_struct iis
= {
1144 .th
= rb_thread_current(),
1151 return (ssize_t
)rb_thread_io_blocking_region(internal_read_func
, &iis
, fptr
->fd
);
1155 rb_write_internal(rb_io_t
*fptr
, const void *buf
, size_t count
)
1157 VALUE scheduler
= rb_fiber_scheduler_current();
1158 if (scheduler
!= Qnil
) {
1159 VALUE result
= rb_fiber_scheduler_io_write_memory(scheduler
, fptr
->self
, buf
, count
, 0);
1161 if (result
!= Qundef
) {
1162 return rb_fiber_scheduler_io_result_apply(result
);
1166 struct io_internal_write_struct iis
= {
1172 if (fptr
->write_lock
&& rb_mutex_owned_p(fptr
->write_lock
))
1173 return (ssize_t
)rb_thread_call_without_gvl2(internal_write_func2
, &iis
, RUBY_UBF_IO
, NULL
);
1175 return (ssize_t
)rb_thread_io_blocking_region(internal_write_func
, &iis
, fptr
->fd
);
1180 rb_writev_internal(rb_io_t
*fptr
, const struct iovec
*iov
, int iovcnt
)
1182 VALUE scheduler
= rb_fiber_scheduler_current();
1183 if (scheduler
!= Qnil
) {
1184 for (int i
= 0; i
< iovcnt
; i
+= 1) {
1185 VALUE result
= rb_fiber_scheduler_io_write_memory(scheduler
, fptr
->self
, iov
[i
].iov_base
, iov
[i
].iov_len
, 0);
1187 if (result
!= Qundef
) {
1188 return rb_fiber_scheduler_io_result_apply(result
);
1193 struct io_internal_writev_struct iis
= {
1199 return (ssize_t
)rb_thread_io_blocking_region(internal_writev_func
, &iis
, fptr
->fd
);
1204 io_flush_buffer_sync(void *arg
)
1206 rb_io_t
*fptr
= arg
;
1207 long l
= fptr
->wbuf
.len
;
1208 ssize_t r
= write(fptr
->fd
, fptr
->wbuf
.ptr
+fptr
->wbuf
.off
, (size_t)l
);
1210 if (fptr
->wbuf
.len
<= r
) {
1216 fptr
->wbuf
.off
+= (int)r
;
1217 fptr
->wbuf
.len
-= (int)r
;
1224 io_flush_buffer_sync2(void *arg
)
1226 VALUE result
= io_flush_buffer_sync(arg
);
1229 * rb_thread_call_without_gvl2 uses 0 as interrupted.
1230 * So, we need to avoid to use 0.
1232 return !result
? (void*)1 : (void*)result
;
1236 io_flush_buffer_async(VALUE arg
)
1238 rb_io_t
*fptr
= (rb_io_t
*)arg
;
1239 return rb_thread_io_blocking_region(io_flush_buffer_sync
, fptr
, fptr
->fd
);
1243 io_flush_buffer_async2(VALUE arg
)
1245 rb_io_t
*fptr
= (rb_io_t
*)arg
;
1248 ret
= (VALUE
)rb_thread_call_without_gvl2(io_flush_buffer_sync2
, fptr
, RUBY_UBF_IO
, NULL
);
1251 /* pending async interrupt is there. */
1255 else if (ret
== 1) {
1262 io_flush_buffer(rb_io_t
*fptr
)
1264 if (fptr
->write_lock
) {
1265 if (rb_mutex_owned_p(fptr
->write_lock
))
1266 return (int)io_flush_buffer_async2((VALUE
)fptr
);
1268 return (int)rb_mutex_synchronize(fptr
->write_lock
, io_flush_buffer_async2
, (VALUE
)fptr
);
1271 return (int)io_flush_buffer_async((VALUE
)fptr
);
1276 io_fflush(rb_io_t
*fptr
)
1278 rb_io_check_closed(fptr
);
1280 if (fptr
->wbuf
.len
== 0)
1283 while (fptr
->wbuf
.len
> 0 && io_flush_buffer(fptr
) != 0) {
1284 if (!rb_io_maybe_wait_writable(errno
, fptr
->self
, Qnil
))
1287 rb_io_check_closed(fptr
);
1294 rb_io_wait(VALUE io
, VALUE events
, VALUE timeout
)
1296 VALUE scheduler
= rb_fiber_scheduler_current();
1298 if (scheduler
!= Qnil
) {
1299 return rb_fiber_scheduler_io_wait(scheduler
, io
, events
, timeout
);
1302 rb_io_t
* fptr
= NULL
;
1303 RB_IO_POINTER(io
, fptr
);
1305 struct timeval tv_storage
;
1306 struct timeval
*tv
= NULL
;
1308 if (timeout
!= Qnil
) {
1309 tv_storage
= rb_time_interval(timeout
);
1313 int ready
= rb_thread_wait_for_single_fd(fptr
->fd
, RB_NUM2INT(events
), tv
);
1319 // Not sure if this is necessary:
1320 rb_io_check_closed(fptr
);
1323 return RB_INT2NUM(ready
);
1333 return prep_io(fd
, FMODE_PREP
, rb_cIO
, NULL
);
1337 io_wait_for_single_fd(int fd
, int events
, struct timeval
*timeout
)
1339 VALUE scheduler
= rb_fiber_scheduler_current();
1341 if (scheduler
!= Qnil
) {
1343 rb_fiber_scheduler_io_wait(scheduler
, io_from_fd(fd
), RB_INT2NUM(events
), rb_fiber_scheduler_make_timeout(timeout
))
1347 return rb_thread_wait_for_single_fd(fd
, events
, timeout
);
1351 rb_io_wait_readable(int f
)
1353 io_fd_check_closed(f
);
1355 VALUE scheduler
= rb_fiber_scheduler_current();
1359 #if defined(ERESTART)
1362 rb_thread_check_ints();
1366 #if EWOULDBLOCK != EAGAIN
1369 if (scheduler
!= Qnil
) {
1371 rb_fiber_scheduler_io_wait_readable(scheduler
, io_from_fd(f
))
1375 io_wait_for_single_fd(f
, RUBY_IO_READABLE
, NULL
);
1385 rb_io_wait_writable(int f
)
1387 io_fd_check_closed(f
);
1389 VALUE scheduler
= rb_fiber_scheduler_current();
1393 #if defined(ERESTART)
1397 * In old Linux, several special files under /proc and /sys don't handle
1398 * select properly. Thus we need avoid to call if don't use O_NONBLOCK.
1399 * Otherwise, we face nasty hang up. Sigh.
1400 * e.g. http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=31b07093c44a7a442394d44423e21d783f5523b8
1401 * http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=31b07093c44a7a442394d44423e21d783f5523b8
1402 * In EINTR case, we only need to call RUBY_VM_CHECK_INTS_BLOCKING().
1403 * Then rb_thread_check_ints() is enough.
1405 rb_thread_check_ints();
1409 #if EWOULDBLOCK != EAGAIN
1412 if (scheduler
!= Qnil
) {
1414 rb_fiber_scheduler_io_wait_writable(scheduler
, io_from_fd(f
))
1418 io_wait_for_single_fd(f
, RUBY_IO_WRITABLE
, NULL
);
1428 rb_wait_for_single_fd(int fd
, int events
, struct timeval
*timeout
)
1430 return io_wait_for_single_fd(fd
, events
, timeout
);
1434 rb_thread_wait_fd(int fd
)
1436 return rb_wait_for_single_fd(fd
, RUBY_IO_READABLE
, NULL
);
1440 rb_thread_fd_writable(int fd
)
1442 return rb_wait_for_single_fd(fd
, RUBY_IO_WRITABLE
, NULL
);
1446 rb_io_maybe_wait(int error
, VALUE io
, VALUE events
, VALUE timeout
)
1448 // fptr->fd can be set to -1 at any time by another thread when the GVL is
1449 // released. Many code, e.g. `io_bufread` didn't check this correctly and
1450 // instead relies on `read(-1) -> -1` which causes this code path. We then
1451 // check here whether the IO was in fact closed. Probably it's better to
1452 // check that `fptr->fd != -1` before using it in syscall.
1453 rb_io_check_closed(RFILE(io
)->fptr
);
1456 // In old Linux, several special files under /proc and /sys don't handle
1457 // select properly. Thus we need avoid to call if don't use O_NONBLOCK.
1458 // Otherwise, we face nasty hang up. Sigh.
1459 // e.g. http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=31b07093c44a7a442394d44423e21d783f5523b8
1460 // http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=31b07093c44a7a442394d44423e21d783f5523b8
1461 // In EINTR case, we only need to call RUBY_VM_CHECK_INTS_BLOCKING().
1462 // Then rb_thread_check_ints() is enough.
1464 #if defined(ERESTART)
1467 // We might have pending interrupts since the previous syscall was interrupted:
1468 rb_thread_check_ints();
1470 // The operation was interrupted, so retry it immediately:
1474 #if EWOULDBLOCK != EAGAIN
1477 // The operation would block, so wait for the specified events:
1478 return rb_io_wait(io
, events
, timeout
);
1481 // Non-specific error, no event is ready:
1487 rb_io_maybe_wait_readable(int error
, VALUE io
, VALUE timeout
)
1489 VALUE result
= rb_io_maybe_wait(error
, io
, RB_INT2NUM(RUBY_IO_READABLE
), timeout
);
1491 if (RTEST(result
)) {
1492 return RB_NUM2INT(result
);
1500 rb_io_maybe_wait_writable(int error
, VALUE io
, VALUE timeout
)
1502 VALUE result
= rb_io_maybe_wait(error
, io
, RB_INT2NUM(RUBY_IO_WRITABLE
), timeout
);
1504 if (RTEST(result
)) {
1505 return RB_NUM2INT(result
);
1513 make_writeconv(rb_io_t
*fptr
)
1515 if (!fptr
->writeconv_initialized
) {
1516 const char *senc
, *denc
;
1521 fptr
->writeconv_initialized
= 1;
1523 ecflags
= fptr
->encs
.ecflags
& ~ECONV_NEWLINE_DECORATOR_READ_MASK
;
1524 ecopts
= fptr
->encs
.ecopts
;
1526 if (!fptr
->encs
.enc
|| (fptr
->encs
.enc
== rb_ascii8bit_encoding() && !fptr
->encs
.enc2
)) {
1527 /* no encoding conversion */
1528 fptr
->writeconv_pre_ecflags
= 0;
1529 fptr
->writeconv_pre_ecopts
= Qnil
;
1530 fptr
->writeconv
= rb_econv_open_opts("", "", ecflags
, ecopts
);
1531 if (!fptr
->writeconv
)
1532 rb_exc_raise(rb_econv_open_exc("", "", ecflags
));
1533 fptr
->writeconv_asciicompat
= Qnil
;
1536 enc
= fptr
->encs
.enc2
? fptr
->encs
.enc2
: fptr
->encs
.enc
;
1537 senc
= rb_econv_asciicompat_encoding(rb_enc_name(enc
));
1538 if (!senc
&& !(fptr
->encs
.ecflags
& ECONV_STATEFUL_DECORATOR_MASK
)) {
1539 /* single conversion */
1540 fptr
->writeconv_pre_ecflags
= ecflags
;
1541 fptr
->writeconv_pre_ecopts
= ecopts
;
1542 fptr
->writeconv
= NULL
;
1543 fptr
->writeconv_asciicompat
= Qnil
;
1546 /* double conversion */
1547 fptr
->writeconv_pre_ecflags
= ecflags
& ~ECONV_STATEFUL_DECORATOR_MASK
;
1548 fptr
->writeconv_pre_ecopts
= ecopts
;
1550 denc
= rb_enc_name(enc
);
1551 fptr
->writeconv_asciicompat
= rb_str_new2(senc
);
1555 fptr
->writeconv_asciicompat
= rb_str_new2(rb_enc_name(enc
));
1557 ecflags
= fptr
->encs
.ecflags
& (ECONV_ERROR_HANDLER_MASK
|ECONV_STATEFUL_DECORATOR_MASK
);
1558 ecopts
= fptr
->encs
.ecopts
;
1559 fptr
->writeconv
= rb_econv_open_opts(senc
, denc
, ecflags
, ecopts
);
1560 if (!fptr
->writeconv
)
1561 rb_exc_raise(rb_econv_open_exc(senc
, denc
, ecflags
));
1567 /* writing functions */
1568 struct binwrite_arg
{
1583 io_binwrite_string(VALUE arg
)
1585 struct binwrite_arg
*p
= (struct binwrite_arg
*)arg
;
1586 rb_io_t
*fptr
= p
->fptr
;
1589 if (fptr
->wbuf
.len
) {
1590 struct iovec iov
[2];
1592 iov
[0].iov_base
= fptr
->wbuf
.ptr
+fptr
->wbuf
.off
;
1593 iov
[0].iov_len
= fptr
->wbuf
.len
;
1594 iov
[1].iov_base
= (char *)p
->ptr
;
1595 iov
[1].iov_len
= p
->length
;
1597 r
= rb_writev_internal(fptr
, iov
, 2);
1602 if (fptr
->wbuf
.len
<= r
) {
1603 r
-= fptr
->wbuf
.len
;
1608 fptr
->wbuf
.off
+= (int)r
;
1609 fptr
->wbuf
.len
-= (int)r
;
1614 r
= rb_write_internal(fptr
, p
->ptr
, p
->length
);
1621 io_binwrite_string(VALUE arg
)
1623 struct binwrite_arg
*p
= (struct binwrite_arg
*)arg
;
1624 rb_io_t
*fptr
= p
->fptr
;
1627 l
= len
= p
->length
;
1629 if (fptr
->wbuf
.len
) {
1630 if (fptr
->wbuf
.len
+len
<= fptr
->wbuf
.capa
) {
1631 if (fptr
->wbuf
.capa
< fptr
->wbuf
.off
+fptr
->wbuf
.len
+len
) {
1632 MEMMOVE(fptr
->wbuf
.ptr
, fptr
->wbuf
.ptr
+fptr
->wbuf
.off
, char, fptr
->wbuf
.len
);
1635 MEMMOVE(fptr
->wbuf
.ptr
+fptr
->wbuf
.off
+fptr
->wbuf
.len
, p
->ptr
, char, len
);
1636 fptr
->wbuf
.len
+= (int)len
;
1639 if (io_fflush(fptr
) < 0)
1640 return -2L; /* fail in fflush */
1645 return rb_write_internal(p
->fptr
, p
->ptr
, p
->length
);
1650 io_binwrite(VALUE str
, const char *ptr
, long len
, rb_io_t
*fptr
, int nosync
)
1652 long n
, r
, offset
= 0;
1654 /* don't write anything if current thread has a pending interrupt. */
1655 rb_thread_check_ints();
1657 if ((n
= len
) <= 0) return n
;
1659 if (fptr
->wbuf
.ptr
== NULL
&& !(!nosync
&& (fptr
->mode
& FMODE_SYNC
))) {
1662 fptr
->wbuf
.capa
= IO_WBUF_CAPA_MIN
;
1663 fptr
->wbuf
.ptr
= ALLOC_N(char, fptr
->wbuf
.capa
);
1664 fptr
->write_lock
= rb_mutex_new();
1665 rb_mutex_allow_trap(fptr
->write_lock
, 1);
1668 if ((!nosync
&& (fptr
->mode
& (FMODE_SYNC
|FMODE_TTY
))) ||
1669 (fptr
->wbuf
.ptr
&& fptr
->wbuf
.capa
<= fptr
->wbuf
.len
+ len
)) {
1670 struct binwrite_arg arg
;
1675 arg
.ptr
= ptr
+ offset
;
1678 if (fptr
->write_lock
) {
1679 r
= rb_mutex_synchronize(fptr
->write_lock
, io_binwrite_string
, (VALUE
)&arg
);
1682 r
= io_binwrite_string((VALUE
)&arg
);
1685 /* xxx: other threads may modify given string. */
1686 if (r
== n
) return len
;
1695 if (rb_io_maybe_wait_writable(errno
, fptr
->self
, Qnil
)) {
1696 rb_io_check_closed(fptr
);
1705 if (fptr
->wbuf
.off
) {
1707 MEMMOVE(fptr
->wbuf
.ptr
, fptr
->wbuf
.ptr
+fptr
->wbuf
.off
, char, fptr
->wbuf
.len
);
1711 MEMMOVE(fptr
->wbuf
.ptr
+fptr
->wbuf
.off
+fptr
->wbuf
.len
, ptr
+offset
, char, len
);
1712 fptr
->wbuf
.len
+= (int)len
;
1717 # define MODE_BTMODE(a,b,c) ((fmode & FMODE_BINMODE) ? (b) : \
1718 (fmode & FMODE_TEXTMODE) ? (c) : (a))
1720 #define MODE_BTXMODE(a, b, c, d, e, f) ((fmode & FMODE_EXCL) ? \
1721 MODE_BTMODE(d, e, f) : \
1722 MODE_BTMODE(a, b, c))
1725 do_writeconv(VALUE str
, rb_io_t
*fptr
, int *converted
)
1727 if (NEED_WRITECONV(fptr
)) {
1728 VALUE common_encoding
= Qnil
;
1729 SET_BINARY_MODE(fptr
);
1731 make_writeconv(fptr
);
1733 if (fptr
->writeconv
) {
1734 #define fmode (fptr->mode)
1735 if (!NIL_P(fptr
->writeconv_asciicompat
))
1736 common_encoding
= fptr
->writeconv_asciicompat
;
1737 else if (MODE_BTMODE(DEFAULT_TEXTMODE
,0,1) && !rb_enc_asciicompat(rb_enc_get(str
))) {
1738 rb_raise(rb_eArgError
, "ASCII incompatible string written for text mode IO without encoding conversion: %s",
1739 rb_enc_name(rb_enc_get(str
)));
1744 if (fptr
->encs
.enc2
)
1745 common_encoding
= rb_enc_from_encoding(fptr
->encs
.enc2
);
1746 else if (fptr
->encs
.enc
!= rb_ascii8bit_encoding())
1747 common_encoding
= rb_enc_from_encoding(fptr
->encs
.enc
);
1750 if (!NIL_P(common_encoding
)) {
1751 str
= rb_str_encode(str
, common_encoding
,
1752 fptr
->writeconv_pre_ecflags
, fptr
->writeconv_pre_ecopts
);
1756 if (fptr
->writeconv
) {
1757 str
= rb_econv_str_convert(fptr
->writeconv
, str
, ECONV_PARTIAL_INPUT
);
1761 #if RUBY_CRLF_ENVIRONMENT
1762 #define fmode (fptr->mode)
1763 else if (MODE_BTMODE(DEFAULT_TEXTMODE
,0,1)) {
1764 if ((fptr
->mode
& FMODE_READABLE
) &&
1765 !(fptr
->encs
.ecflags
& ECONV_NEWLINE_DECORATOR_MASK
)) {
1766 setmode(fptr
->fd
, O_BINARY
);
1769 setmode(fptr
->fd
, O_TEXT
);
1771 if (!rb_enc_asciicompat(rb_enc_get(str
))) {
1772 rb_raise(rb_eArgError
, "ASCII incompatible string written for text mode IO without encoding conversion: %s",
1773 rb_enc_name(rb_enc_get(str
)));
1782 io_fwrite(VALUE str
, rb_io_t
*fptr
, int nosync
)
1789 if (fptr
->mode
& FMODE_TTY
) {
1790 long len
= rb_w32_write_console(str
, fptr
->fd
);
1791 if (len
> 0) return len
;
1794 str
= do_writeconv(str
, fptr
, &converted
);
1798 tmp
= rb_str_tmp_frozen_acquire(str
);
1799 RSTRING_GETMEM(tmp
, ptr
, len
);
1800 n
= io_binwrite(tmp
, ptr
, len
, fptr
, nosync
);
1801 rb_str_tmp_frozen_release(str
, tmp
);
1807 rb_io_bufwrite(VALUE io
, const void *buf
, size_t size
)
1811 GetOpenFile(io
, fptr
);
1812 rb_io_check_writable(fptr
);
1813 return (ssize_t
)io_binwrite(0, buf
, (long)size
, fptr
, 0);
1817 io_write(VALUE io
, VALUE str
, int nosync
)
1823 io
= GetWriteIO(io
);
1824 str
= rb_obj_as_string(str
);
1825 tmp
= rb_io_check_io(io
);
1827 /* port is not IO, call write method for it. */
1828 return rb_funcall(io
, id_write
, 1, str
);
1831 if (RSTRING_LEN(str
) == 0) return INT2FIX(0);
1833 GetOpenFile(io
, fptr
);
1834 rb_io_check_writable(fptr
);
1836 n
= io_fwrite(str
, fptr
, nosync
);
1837 if (n
< 0L) rb_sys_fail_on_write(fptr
);
1843 struct binwritev_arg
{
1845 const struct iovec
*iov
;
1850 call_writev_internal(VALUE arg
)
1852 struct binwritev_arg
*p
= (struct binwritev_arg
*)arg
;
1853 return rb_writev_internal(p
->fptr
, p
->iov
, p
->iovcnt
);
1857 io_binwritev(struct iovec
*iov
, int iovcnt
, rb_io_t
*fptr
)
1860 long r
, total
= 0, written_len
= 0;
1862 /* don't write anything if current thread has a pending interrupt. */
1863 rb_thread_check_ints();
1865 if (iovcnt
== 0) return 0;
1866 for (i
= 1; i
< iovcnt
; i
++) total
+= iov
[i
].iov_len
;
1868 if (fptr
->wbuf
.ptr
== NULL
&& !(fptr
->mode
& FMODE_SYNC
)) {
1871 fptr
->wbuf
.capa
= IO_WBUF_CAPA_MIN
;
1872 fptr
->wbuf
.ptr
= ALLOC_N(char, fptr
->wbuf
.capa
);
1873 fptr
->write_lock
= rb_mutex_new();
1874 rb_mutex_allow_trap(fptr
->write_lock
, 1);
1877 if (fptr
->wbuf
.ptr
&& fptr
->wbuf
.len
) {
1878 long offset
= fptr
->wbuf
.off
+ fptr
->wbuf
.len
;
1879 if (offset
+ total
<= fptr
->wbuf
.capa
) {
1880 for (i
= 1; i
< iovcnt
; i
++) {
1881 memcpy(fptr
->wbuf
.ptr
+offset
, iov
[i
].iov_base
, iov
[i
].iov_len
);
1882 offset
+= iov
[i
].iov_len
;
1884 fptr
->wbuf
.len
+= total
;
1888 iov
[0].iov_base
= fptr
->wbuf
.ptr
+ fptr
->wbuf
.off
;
1889 iov
[0].iov_len
= fptr
->wbuf
.len
;
1894 if (!--iovcnt
) return 0;
1898 if (fptr
->write_lock
) {
1899 struct binwritev_arg arg
;
1902 arg
.iovcnt
= iovcnt
;
1903 r
= rb_mutex_synchronize(fptr
->write_lock
, call_writev_internal
, (VALUE
)&arg
);
1906 r
= rb_writev_internal(fptr
, iov
, iovcnt
);
1911 if (fptr
->wbuf
.ptr
&& fptr
->wbuf
.len
) {
1912 if (written_len
< fptr
->wbuf
.len
) {
1913 fptr
->wbuf
.off
+= r
;
1914 fptr
->wbuf
.len
-= r
;
1917 written_len
-= fptr
->wbuf
.len
;
1922 if (written_len
== total
) return total
;
1924 while (r
>= (ssize_t
)iov
->iov_len
) {
1929 if (!--iovcnt
) return total
;
1930 /* defensive check: written_len should == total */
1932 iov
->iov_base
= (char *)iov
->iov_base
+ r
;
1937 if (rb_io_maybe_wait_writable(errno
, fptr
->self
, Qnil
)) {
1938 rb_io_check_closed(fptr
);
1946 io_fwritev(int argc
, const VALUE
*argv
, rb_io_t
*fptr
)
1948 int i
, converted
, iovcnt
= argc
+ 1;
1950 VALUE v1
, v2
, str
, tmp
, *tmp_array
;
1953 iov
= ALLOCV_N(struct iovec
, v1
, iovcnt
);
1954 tmp_array
= ALLOCV_N(VALUE
, v2
, argc
);
1956 for (i
= 0; i
< argc
; i
++) {
1957 str
= rb_obj_as_string(argv
[i
]);
1959 str
= do_writeconv(str
, fptr
, &converted
);
1963 tmp
= rb_str_tmp_frozen_acquire(str
);
1965 /* iov[0] is reserved for buffer of fptr */
1966 iov
[i
+1].iov_base
= RSTRING_PTR(tmp
);
1967 iov
[i
+1].iov_len
= RSTRING_LEN(tmp
);
1970 n
= io_binwritev(iov
, iovcnt
, fptr
);
1971 if (v1
) ALLOCV_END(v1
);
1973 for (i
= 0; i
< argc
; i
++) {
1974 rb_str_tmp_frozen_release(argv
[i
], tmp_array
[i
]);
1977 if (v2
) ALLOCV_END(v2
);
1983 iovcnt_ok(int iovcnt
)
1986 return iovcnt
< IOV_MAX
;
1987 #else /* GNU/Hurd has writev, but no IOV_MAX */
1991 #endif /* HAVE_WRITEV */
1994 io_writev(int argc
, const VALUE
*argv
, VALUE io
)
1998 VALUE tmp
, total
= INT2FIX(0);
2001 io
= GetWriteIO(io
);
2002 tmp
= rb_io_check_io(io
);
2004 /* port is not IO, call write method for it. */
2005 return rb_funcallv(io
, id_write
, argc
, argv
);
2009 GetOpenFile(io
, fptr
);
2010 rb_io_check_writable(fptr
);
2012 for (i
= 0; i
< argc
; i
+= cnt
) {
2014 if ((fptr
->mode
& (FMODE_SYNC
|FMODE_TTY
)) && iovcnt_ok(cnt
= argc
- i
)) {
2015 n
= io_fwritev(cnt
, &argv
[i
], fptr
);
2021 /* sync at last item */
2022 n
= io_fwrite(rb_obj_as_string(argv
[i
]), fptr
, (i
< argc
-1));
2024 if (n
< 0L) rb_sys_fail_on_write(fptr
);
2025 total
= rb_fix_plus(LONG2FIX(n
), total
);
2033 * write(*objects) -> integer
2035 * Writes each of the given +objects+ to +self+,
2036 * which must be opened for writing (see {Modes}[#class-IO-label-Modes]);
2037 * returns the total number bytes written;
2038 * each of +objects+ that is not a string is converted via method +to_s+:
2040 * $stdout.write('Hello', ', ', 'World!', "\n") # => 14
2041 * $stdout.write('foo', :bar, 2, "\n") # => 8
2051 io_write_m(int argc
, VALUE
*argv
, VALUE io
)
2054 return io_writev(argc
, argv
, io
);
2057 VALUE str
= argv
[0];
2058 return io_write(io
, str
, 0);
2063 rb_io_write(VALUE io
, VALUE str
)
2065 return rb_funcallv(io
, id_write
, 1, &str
);
2069 rb_io_writev(VALUE io
, int argc
, const VALUE
*argv
)
2071 if (argc
> 1 && rb_obj_method_arity(io
, id_write
) == 1) {
2072 if (io
!= rb_ractor_stderr() && RTEST(ruby_verbose
)) {
2073 VALUE klass
= CLASS_OF(io
);
2074 char sep
= FL_TEST(klass
, FL_SINGLETON
) ? (klass
= io
, '.') : '#';
2075 rb_category_warning(RB_WARN_CATEGORY_DEPRECATED
, "%+"PRIsVALUE
"%c""write is outdated interface"
2076 " which accepts just one argument",
2079 do rb_io_write(io
, *argv
++); while (--argc
);
2080 return argv
[0]; /* unused right now */
2082 return rb_funcallv(io
, id_write
, argc
, argv
);
2087 * self << object -> self
2089 * Writes the given +object+ to +self+,
2090 * which must be opened for writing (see {Modes}[#class-IO-label-Modes]);
2092 * if +object+ is not a string, it is converted via method +to_s+:
2094 * $stdout << 'Hello' << ', ' << 'World!' << "\n"
2095 * $stdout << 'foo' << :bar << 2 << "\n"
2106 rb_io_addstr(VALUE io
, VALUE str
)
2108 rb_io_write(io
, str
);
2114 nogvl_fsync(void *ptr
)
2116 rb_io_t
*fptr
= ptr
;
2119 if (GetFileType((HANDLE
)rb_w32_get_osfhandle(fptr
->fd
)) != FILE_TYPE_DISK
)
2122 return (VALUE
)fsync(fptr
->fd
);
2127 rb_io_flush_raw(VALUE io
, int sync
)
2131 if (!RB_TYPE_P(io
, T_FILE
)) {
2132 return rb_funcall(io
, id_flush
, 0);
2135 io
= GetWriteIO(io
);
2136 GetOpenFile(io
, fptr
);
2138 if (fptr
->mode
& FMODE_WRITABLE
) {
2139 if (io_fflush(fptr
) < 0)
2140 rb_sys_fail_on_write(fptr
);
2142 if (fptr
->mode
& FMODE_READABLE
) {
2153 * Flushes data buffered in +self+ to the operating system
2154 * (but does not necessarily flush data buffered in the operating system):
2156 * $stdout.print 'no newline' # Not necessarily flushed.
2157 * $stdout.flush # Flushed.
2162 rb_io_flush(VALUE io
)
2164 return rb_io_flush_raw(io
, 1);
2171 * Returns the current position (in bytes) in +self+
2172 * (see {Position}[#class-IO-label-Position]):
2174 * f = File.open('t.txt')
2176 * f.gets # => "First line\n"
2179 * Related: IO#pos=, IO#seek.
2181 * IO#pos is an alias for IO#tell.
2186 rb_io_tell(VALUE io
)
2191 GetOpenFile(io
, fptr
);
2192 pos
= io_tell(fptr
);
2193 if (pos
< 0 && errno
) rb_sys_fail_path(fptr
->pathv
);
2194 pos
-= fptr
->rbuf
.len
;
2195 return OFFT2NUM(pos
);
2199 rb_io_seek(VALUE io
, VALUE offset
, int whence
)
2204 pos
= NUM2OFFT(offset
);
2205 GetOpenFile(io
, fptr
);
2206 pos
= io_seek(fptr
, pos
, whence
);
2207 if (pos
< 0 && errno
) rb_sys_fail_path(fptr
->pathv
);
2213 interpret_seek_whence(VALUE vwhence
)
2215 if (vwhence
== sym_SET
)
2217 if (vwhence
== sym_CUR
)
2219 if (vwhence
== sym_END
)
2222 if (vwhence
== sym_DATA
)
2226 if (vwhence
== sym_HOLE
)
2229 return NUM2INT(vwhence
);
2234 * seek(offset, whence = IO::SEEK_SET) -> 0
2236 * Seeks to the position given by integer +offset+
2237 * (see {Position}[#class-IO-label-Position])
2238 * and constant +whence+, which is one of:
2240 * - +:CUR+ or <tt>IO::SEEK_CUR</tt>:
2241 * Repositions the stream to its current position plus the given +offset+:
2243 * f = File.open('t.txt')
2245 * f.seek(20, :CUR) # => 0
2247 * f.seek(-10, :CUR) # => 0
2250 * - +:END+ or <tt>IO::SEEK_END</tt>:
2251 * Repositions the stream to its end plus the given +offset+:
2253 * f = File.open('t.txt')
2255 * f.seek(0, :END) # => 0 # Repositions to stream end.
2257 * f.seek(-20, :END) # => 0
2259 * f.seek(-40, :END) # => 0
2262 * - +:SET+ or <tt>IO:SEEK_SET</tt>:
2263 * Repositions the stream to the given +offset+:
2265 * f = File.open('t.txt')
2267 * f.seek(20, :SET) # => 0
2269 * f.seek(40, :SET) # => 0
2272 * Related: IO#pos=, IO#tell.
2277 rb_io_seek_m(int argc
, VALUE
*argv
, VALUE io
)
2279 VALUE offset
, ptrname
;
2280 int whence
= SEEK_SET
;
2282 if (rb_scan_args(argc
, argv
, "11", &offset
, &ptrname
) == 2) {
2283 whence
= interpret_seek_whence(ptrname
);
2286 return rb_io_seek(io
, offset
, whence
);
2291 * pos = new_position -> new_position
2293 * Seeks to the given +new_position+ (in bytes);
2294 * see {Position}[#class-IO-label-Position]:
2296 * f = File.open('t.txt')
2298 * f.pos = 20 # => 20
2301 * Related: IO#seek, IO#tell.
2306 rb_io_set_pos(VALUE io
, VALUE offset
)
2311 pos
= NUM2OFFT(offset
);
2312 GetOpenFile(io
, fptr
);
2313 pos
= io_seek(fptr
, pos
, SEEK_SET
);
2314 if (pos
< 0 && errno
) rb_sys_fail_path(fptr
->pathv
);
2316 return OFFT2NUM(pos
);
2319 static void clear_readconv(rb_io_t
*fptr
);
2325 * Repositions the stream to its beginning,
2326 * setting both the position and the line number to zero;
2327 * see {Position}[#class-IO-label-Position]
2328 * and {Line Number}[#class-IO-label-Line+Number]:
2330 * f = File.open('t.txt')
2333 * f.gets # => "First line\n"
2340 * Note that this method cannot be used with streams such as pipes, ttys, and sockets.
2345 rb_io_rewind(VALUE io
)
2349 GetOpenFile(io
, fptr
);
2350 if (io_seek(fptr
, 0L, 0) < 0 && errno
) rb_sys_fail_path(fptr
->pathv
);
2351 if (io
== ARGF
.current_file
) {
2352 ARGF
.lineno
-= fptr
->lineno
;
2355 if (fptr
->readconv
) {
2356 clear_readconv(fptr
);
2363 fptr_wait_readable(rb_io_t
*fptr
)
2365 int ret
= rb_io_maybe_wait_readable(errno
, fptr
->self
, Qnil
);
2368 rb_io_check_closed(fptr
);
2374 io_fillbuf(rb_io_t
*fptr
)
2378 if (fptr
->rbuf
.ptr
== NULL
) {
2381 fptr
->rbuf
.capa
= IO_RBUF_CAPA_FOR(fptr
);
2382 fptr
->rbuf
.ptr
= ALLOC_N(char, fptr
->rbuf
.capa
);
2387 if (fptr
->rbuf
.len
== 0) {
2389 r
= rb_read_internal(fptr
, fptr
->rbuf
.ptr
, fptr
->rbuf
.capa
);
2392 if (fptr_wait_readable(fptr
))
2396 VALUE path
= rb_sprintf("fd:%d ", fptr
->fd
);
2397 if (!NIL_P(fptr
->pathv
)) {
2398 rb_str_append(path
, fptr
->pathv
);
2401 rb_syserr_fail_path(e
, path
);
2403 if (r
> 0) rb_io_check_closed(fptr
);
2405 fptr
->rbuf
.len
= (int)r
; /* r should be <= rbuf_capa */
2407 return -1; /* EOF */
2414 * eof -> true or false
2416 * Returns +true+ if the stream is positioned at its end, +false+ otherwise;
2417 * see {Position}[#class-IO-label-Position]:
2419 * f = File.open('t.txt')
2421 * f.seek(0, :END) # => 0
2424 * Raises an exception unless the stream is opened for reading;
2425 * see {Mode}[#class-IO-label-Mode].
2427 * If +self+ is a stream such as pipe or socket, this method
2428 * blocks until the other end sends some data or closes it:
2431 * Thread.new { sleep 1; w.close }
2432 * r.eof? # => true # After 1-second wait.
2435 * Thread.new { sleep 1; w.puts "a" }
2436 * r.eof? # => false # After 1-second wait.
2439 * r.eof? # blocks forever
2441 * Note that this method reads data to the input byte buffer. So
2442 * IO#sysread may not behave as you intend with IO#eof?, unless you
2443 * call IO#rewind first (which is not available for some streams).
2445 * I#eof? is an alias for IO#eof.
2454 GetOpenFile(io
, fptr
);
2455 rb_io_check_char_readable(fptr
);
2457 if (READ_CHAR_PENDING(fptr
)) return Qfalse
;
2458 if (READ_DATA_PENDING(fptr
)) return Qfalse
;
2460 #if RUBY_CRLF_ENVIRONMENT
2461 if (!NEED_READCONV(fptr
) && NEED_NEWLINE_DECORATOR_ON_READ(fptr
)) {
2462 return RBOOL(eof(fptr
->fd
));;
2465 return RBOOL(io_fillbuf(fptr
) < 0);
2470 * sync -> true or false
2472 * Returns the current sync mode of the stream.
2473 * When sync mode is true, all output is immediately flushed to the underlying
2474 * operating system and is not buffered by Ruby internally. See also #fsync.
2476 * f = File.open('t.tmp', 'w')
2484 rb_io_sync(VALUE io
)
2488 io
= GetWriteIO(io
);
2489 GetOpenFile(io
, fptr
);
2490 return RBOOL(fptr
->mode
& FMODE_SYNC
);
2497 * sync = boolean -> boolean
2499 * Sets the _sync_ _mode_ for the stream to the given value;
2500 * returns the given value.
2502 * Values for the sync mode:
2504 * - +true+: All output is immediately flushed to the
2505 * underlying operating system and is not buffered internally.
2506 * - +false+: Output may be buffered internally.
2510 * f = File.open('t.tmp', 'w')
2515 * Related: IO#fsync.
2520 rb_io_set_sync(VALUE io
, VALUE sync
)
2524 io
= GetWriteIO(io
);
2525 GetOpenFile(io
, fptr
);
2527 fptr
->mode
|= FMODE_SYNC
;
2530 fptr
->mode
&= ~FMODE_SYNC
;
2539 * Immediately writes to disk all data buffered in the stream,
2540 * via the operating system's <tt>fsync(2)</tt>.
2542 * Note this difference:
2544 * - IO#sync=: Ensures that data is flushed from the stream's internal buffers,
2545 * but does not guarantee that the operating system actually writes the data to disk.
2546 * - IO#fsync: Ensures both that data is flushed from internal buffers,
2547 * and that data is written to disk.
2549 * Raises an exception if the operating system does not support <tt>fsync(2)</tt>.
2554 rb_io_fsync(VALUE io
)
2558 io
= GetWriteIO(io
);
2559 GetOpenFile(io
, fptr
);
2561 if (io_fflush(fptr
) < 0)
2562 rb_sys_fail_on_write(fptr
);
2563 if ((int)rb_thread_io_blocking_region(nogvl_fsync
, fptr
, fptr
->fd
) < 0)
2564 rb_sys_fail_path(fptr
->pathv
);
2568 # define rb_io_fsync rb_f_notimplement
2569 # define rb_io_sync rb_f_notimplement
2571 rb_io_set_sync(VALUE io
, VALUE sync
)
2578 #ifdef HAVE_FDATASYNC
2580 nogvl_fdatasync(void *ptr
)
2582 rb_io_t
*fptr
= ptr
;
2585 if (GetFileType((HANDLE
)rb_w32_get_osfhandle(fptr
->fd
)) != FILE_TYPE_DISK
)
2588 return (VALUE
)fdatasync(fptr
->fd
);
2595 * Immediately writes to disk all data buffered in the stream,
2596 * via the operating system's: <tt>fdatasync(2)</tt>, if supported,
2597 * otherwise via <tt>fsync(2)</tt>, if supported;
2598 * otherwise raises an exception.
2603 rb_io_fdatasync(VALUE io
)
2607 io
= GetWriteIO(io
);
2608 GetOpenFile(io
, fptr
);
2610 if (io_fflush(fptr
) < 0)
2611 rb_sys_fail_on_write(fptr
);
2613 if ((int)rb_thread_io_blocking_region(nogvl_fdatasync
, fptr
, fptr
->fd
) == 0)
2617 return rb_io_fsync(io
);
2620 #define rb_io_fdatasync rb_io_fsync
2627 * Returns the integer file descriptor for the stream:
2629 * $stdin.fileno # => 0
2630 * $stdout.fileno # => 1
2631 * $stderr.fileno # => 2
2632 * File.open('t.txt').fileno # => 10
2634 * IO#to_i is an alias for IO#fileno.
2639 rb_io_fileno(VALUE io
)
2641 rb_io_t
*fptr
= RFILE(io
)->fptr
;
2644 rb_io_check_closed(fptr
);
2650 rb_io_descriptor(VALUE io
)
2652 if (RB_TYPE_P(io
, T_FILE
)) {
2653 rb_io_t
*fptr
= RFILE(io
)->fptr
;
2654 rb_io_check_closed(fptr
);
2658 return RB_NUM2INT(rb_funcall(io
, id_fileno
, 0));
2664 * pid -> integer or nil
2666 * Returns the process ID of a child process associated with the stream,
2667 * which will have been set by IO#popen, or +nil+ if the stream was not
2668 * created by IO#popen:
2670 * pipe = IO.popen("-")
2672 * $stderr.puts "In parent, child pid is #{pipe.pid}"
2674 * $stderr.puts "In child, pid is #{$$}"
2679 * In child, pid is 26209
2680 * In parent, child pid is 26209
2689 GetOpenFile(io
, fptr
);
2692 return PIDT2NUM(fptr
->pid
);
2700 * Returns a string representation of +self+:
2702 * f = File.open('t.txt')
2703 * f.inspect # => "#<File:t.txt>"
2708 rb_io_inspect(VALUE obj
)
2712 static const char closed
[] = " (closed)";
2714 fptr
= RFILE(obj
)->fptr
;
2715 if (!fptr
) return rb_any_to_s(obj
);
2716 result
= rb_str_new_cstr("#<");
2717 rb_str_append(result
, rb_class_name(CLASS_OF(obj
)));
2718 rb_str_cat2(result
, ":");
2719 if (NIL_P(fptr
->pathv
)) {
2721 rb_str_cat(result
, closed
+1, strlen(closed
)-1);
2724 rb_str_catf(result
, "fd %d", fptr
->fd
);
2728 rb_str_append(result
, fptr
->pathv
);
2730 rb_str_cat(result
, closed
, strlen(closed
));
2733 return rb_str_cat2(result
, ">");
2745 rb_io_to_io(VALUE io
)
2750 /* reading functions */
2752 read_buffered_data(char *ptr
, long len
, rb_io_t
*fptr
)
2756 n
= READ_DATA_PENDING_COUNT(fptr
);
2757 if (n
<= 0) return 0;
2758 if (n
> len
) n
= (int)len
;
2759 MEMMOVE(ptr
, fptr
->rbuf
.ptr
+fptr
->rbuf
.off
, char, n
);
2760 fptr
->rbuf
.off
+= n
;
2761 fptr
->rbuf
.len
-= n
;
2766 io_bufread(char *ptr
, long len
, rb_io_t
*fptr
)
2772 if (READ_DATA_PENDING(fptr
) == 0) {
2775 rb_io_check_closed(fptr
);
2776 c
= rb_read_internal(fptr
, ptr
+offset
, n
);
2779 if (fptr_wait_readable(fptr
))
2784 if ((n
-= c
) <= 0) break;
2790 c
= read_buffered_data(ptr
+offset
, n
, fptr
);
2793 if ((n
-= c
) <= 0) break;
2795 rb_io_check_closed(fptr
);
2796 if (io_fillbuf(fptr
) < 0) {
2803 static int io_setstrbuf(VALUE
*str
, long len
);
2805 struct bufread_arg
{
2812 bufread_call(VALUE arg
)
2814 struct bufread_arg
*p
= (struct bufread_arg
*)arg
;
2815 p
->len
= io_bufread(p
->str_ptr
, p
->len
, p
->fptr
);
2820 io_fread(VALUE str
, long offset
, long size
, rb_io_t
*fptr
)
2823 struct bufread_arg arg
;
2825 io_setstrbuf(&str
, offset
+ size
);
2826 arg
.str_ptr
= RSTRING_PTR(str
) + offset
;
2829 rb_str_locktmp_ensure(str
, bufread_call
, (VALUE
)&arg
);
2831 if (len
< 0) rb_sys_fail_path(fptr
->pathv
);
2836 remain_size(rb_io_t
*fptr
)
2839 off_t siz
= READ_DATA_PENDING_COUNT(fptr
);
2842 if (fstat(fptr
->fd
, &st
) == 0 && S_ISREG(st
.st_mode
)
2843 #if defined(__HAIKU__)
2848 if (io_fflush(fptr
) < 0)
2849 rb_sys_fail_on_write(fptr
);
2850 pos
= lseek(fptr
->fd
, 0, SEEK_CUR
);
2851 if (st
.st_size
>= pos
&& pos
>= 0) {
2852 siz
+= st
.st_size
- pos
;
2853 if (siz
> LONG_MAX
) {
2854 rb_raise(rb_eIOError
, "file too big for single read");
2865 io_enc_str(VALUE str
, rb_io_t
*fptr
)
2867 rb_enc_associate(str
, io_read_encoding(fptr
));
2872 make_readconv(rb_io_t
*fptr
, int size
)
2874 if (!fptr
->readconv
) {
2877 const char *sname
, *dname
;
2878 ecflags
= fptr
->encs
.ecflags
& ~ECONV_NEWLINE_DECORATOR_WRITE_MASK
;
2879 ecopts
= fptr
->encs
.ecopts
;
2880 if (fptr
->encs
.enc2
) {
2881 sname
= rb_enc_name(fptr
->encs
.enc2
);
2882 dname
= rb_enc_name(fptr
->encs
.enc
);
2887 fptr
->readconv
= rb_econv_open_opts(sname
, dname
, ecflags
, ecopts
);
2888 if (!fptr
->readconv
)
2889 rb_exc_raise(rb_econv_open_exc(sname
, dname
, ecflags
));
2892 if (size
< IO_CBUF_CAPA_MIN
) size
= IO_CBUF_CAPA_MIN
;
2893 fptr
->cbuf
.capa
= size
;
2894 fptr
->cbuf
.ptr
= ALLOC_N(char, fptr
->cbuf
.capa
);
2898 #define MORE_CHAR_SUSPENDED Qtrue
2899 #define MORE_CHAR_FINISHED Qnil
2901 fill_cbuf(rb_io_t
*fptr
, int ec_flags
)
2903 const unsigned char *ss
, *sp
, *se
;
2904 unsigned char *ds
, *dp
, *de
;
2905 rb_econv_result_t res
;
2910 ec_flags
|= ECONV_PARTIAL_INPUT
;
2912 if (fptr
->cbuf
.len
== fptr
->cbuf
.capa
)
2913 return MORE_CHAR_SUSPENDED
; /* cbuf full */
2914 if (fptr
->cbuf
.len
== 0)
2916 else if (fptr
->cbuf
.off
+ fptr
->cbuf
.len
== fptr
->cbuf
.capa
) {
2917 memmove(fptr
->cbuf
.ptr
, fptr
->cbuf
.ptr
+fptr
->cbuf
.off
, fptr
->cbuf
.len
);
2921 cbuf_len0
= fptr
->cbuf
.len
;
2924 ss
= sp
= (const unsigned char *)fptr
->rbuf
.ptr
+ fptr
->rbuf
.off
;
2925 se
= sp
+ fptr
->rbuf
.len
;
2926 ds
= dp
= (unsigned char *)fptr
->cbuf
.ptr
+ fptr
->cbuf
.off
+ fptr
->cbuf
.len
;
2927 de
= (unsigned char *)fptr
->cbuf
.ptr
+ fptr
->cbuf
.capa
;
2928 res
= rb_econv_convert(fptr
->readconv
, &sp
, se
, &dp
, de
, ec_flags
);
2929 fptr
->rbuf
.off
+= (int)(sp
- ss
);
2930 fptr
->rbuf
.len
-= (int)(sp
- ss
);
2931 fptr
->cbuf
.len
+= (int)(dp
- ds
);
2933 putbackable
= rb_econv_putbackable(fptr
->readconv
);
2935 rb_econv_putback(fptr
->readconv
, (unsigned char *)fptr
->rbuf
.ptr
+ fptr
->rbuf
.off
- putbackable
, putbackable
);
2936 fptr
->rbuf
.off
-= putbackable
;
2937 fptr
->rbuf
.len
+= putbackable
;
2940 exc
= rb_econv_make_exception(fptr
->readconv
);
2944 if (cbuf_len0
!= fptr
->cbuf
.len
)
2945 return MORE_CHAR_SUSPENDED
;
2947 if (res
== econv_finished
) {
2948 return MORE_CHAR_FINISHED
;
2951 if (res
== econv_source_buffer_empty
) {
2952 if (fptr
->rbuf
.len
== 0) {
2954 if (io_fillbuf(fptr
) < 0) {
2955 if (!fptr
->readconv
) {
2956 return MORE_CHAR_FINISHED
;
2958 ds
= dp
= (unsigned char *)fptr
->cbuf
.ptr
+ fptr
->cbuf
.off
+ fptr
->cbuf
.len
;
2959 de
= (unsigned char *)fptr
->cbuf
.ptr
+ fptr
->cbuf
.capa
;
2960 res
= rb_econv_convert(fptr
->readconv
, NULL
, NULL
, &dp
, de
, 0);
2961 fptr
->cbuf
.len
+= (int)(dp
- ds
);
2962 rb_econv_check_error(fptr
->readconv
);
2968 if (cbuf_len0
!= fptr
->cbuf
.len
)
2969 return MORE_CHAR_SUSPENDED
;
2971 return MORE_CHAR_FINISHED
;
2975 more_char(rb_io_t
*fptr
)
2978 v
= fill_cbuf(fptr
, ECONV_AFTER_OUTPUT
);
2979 if (v
!= MORE_CHAR_SUSPENDED
&& v
!= MORE_CHAR_FINISHED
)
2985 io_shift_cbuf(rb_io_t
*fptr
, int len
, VALUE
*strp
)
2991 *strp
= str
= rb_str_new(fptr
->cbuf
.ptr
+fptr
->cbuf
.off
, len
);
2994 rb_str_cat(str
, fptr
->cbuf
.ptr
+fptr
->cbuf
.off
, len
);
2996 rb_enc_associate(str
, fptr
->encs
.enc
);
2998 fptr
->cbuf
.off
+= len
;
2999 fptr
->cbuf
.len
-= len
;
3000 /* xxx: set coderange */
3001 if (fptr
->cbuf
.len
== 0)
3003 else if (fptr
->cbuf
.capa
/2 < fptr
->cbuf
.off
) {
3004 memmove(fptr
->cbuf
.ptr
, fptr
->cbuf
.ptr
+fptr
->cbuf
.off
, fptr
->cbuf
.len
);
3011 io_setstrbuf(VALUE
*str
, long len
)
3014 len
= (len
+ 1) & ~1L; /* round up for wide char */
3017 *str
= rb_str_new(0, len
);
3021 VALUE s
= StringValue(*str
);
3022 long clen
= RSTRING_LEN(s
);
3029 rb_str_modify_expand(*str
, len
);
3033 #define MAX_REALLOC_GAP 4096
3035 io_shrink_read_string(VALUE str
, long n
)
3037 if (rb_str_capacity(str
) - n
> MAX_REALLOC_GAP
) {
3038 rb_str_resize(str
, n
);
3043 io_set_read_length(VALUE str
, long n
, int shrinkable
)
3045 if (RSTRING_LEN(str
) != n
) {
3047 rb_str_set_len(str
, n
);
3048 if (shrinkable
) io_shrink_read_string(str
, n
);
3053 read_all(rb_io_t
*fptr
, long siz
, VALUE str
)
3062 if (NEED_READCONV(fptr
)) {
3063 int first
= !NIL_P(str
);
3064 SET_BINARY_MODE(fptr
);
3065 shrinkable
= io_setstrbuf(&str
,0);
3066 make_readconv(fptr
, 0);
3069 if (fptr
->cbuf
.len
) {
3070 if (first
) rb_str_set_len(str
, first
= 0);
3071 io_shift_cbuf(fptr
, fptr
->cbuf
.len
, &str
);
3073 v
= fill_cbuf(fptr
, 0);
3074 if (v
!= MORE_CHAR_SUSPENDED
&& v
!= MORE_CHAR_FINISHED
) {
3075 if (fptr
->cbuf
.len
) {
3076 if (first
) rb_str_set_len(str
, first
= 0);
3077 io_shift_cbuf(fptr
, fptr
->cbuf
.len
, &str
);
3081 if (v
== MORE_CHAR_FINISHED
) {
3082 clear_readconv(fptr
);
3083 if (first
) rb_str_set_len(str
, first
= 0);
3084 if (shrinkable
) io_shrink_read_string(str
, RSTRING_LEN(str
));
3085 return io_enc_str(str
, fptr
);
3090 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr
);
3094 enc
= io_read_encoding(fptr
);
3097 if (siz
== 0) siz
= BUFSIZ
;
3098 shrinkable
= io_setstrbuf(&str
, siz
);
3101 n
= io_fread(str
, bytes
, siz
- bytes
, fptr
);
3102 if (n
== 0 && bytes
== 0) {
3103 rb_str_set_len(str
, 0);
3107 rb_str_set_len(str
, bytes
);
3108 if (cr
!= ENC_CODERANGE_BROKEN
)
3109 pos
+= rb_str_coderange_scan_restartable(RSTRING_PTR(str
) + pos
, RSTRING_PTR(str
) + bytes
, enc
, &cr
);
3110 if (bytes
< siz
) break;
3112 rb_str_modify_expand(str
, BUFSIZ
);
3114 if (shrinkable
) io_shrink_read_string(str
, RSTRING_LEN(str
));
3115 str
= io_enc_str(str
, fptr
);
3116 ENC_CODERANGE_SET(str
, cr
);
3121 rb_io_set_nonblock(rb_io_t
*fptr
)
3123 if (rb_fd_set_nonblock(fptr
->fd
) != 0) {
3124 rb_sys_fail_path(fptr
->pathv
);
3129 read_internal_call(VALUE arg
)
3131 struct io_internal_read_struct
*iis
= (struct io_internal_read_struct
*)arg
;
3133 VALUE scheduler
= rb_fiber_scheduler_current();
3134 if (scheduler
!= Qnil
) {
3135 VALUE result
= rb_fiber_scheduler_io_read_memory(scheduler
, iis
->fptr
->self
, iis
->buf
, iis
->capa
, 0);
3137 if (result
!= Qundef
) {
3138 // This is actually returned as a pseudo-VALUE and later cast to a long:
3139 return (VALUE
)rb_fiber_scheduler_io_result_apply(result
);
3143 return rb_thread_io_blocking_region(internal_read_func
, iis
, iis
->fptr
->fd
);
3147 read_internal_locktmp(VALUE str
, struct io_internal_read_struct
*iis
)
3149 return (long)rb_str_locktmp_ensure(str
, read_internal_call
, (VALUE
)iis
);
3152 #define no_exception_p(opts) !rb_opts_exception_p((opts), TRUE)
3155 io_getpartial(int argc
, VALUE
*argv
, VALUE io
, int no_exception
, int nonblock
)
3160 struct io_internal_read_struct iis
;
3163 rb_scan_args(argc
, argv
, "11", &length
, &str
);
3165 if ((len
= NUM2LONG(length
)) < 0) {
3166 rb_raise(rb_eArgError
, "negative length %ld given", len
);
3169 shrinkable
= io_setstrbuf(&str
, len
);
3171 GetOpenFile(io
, fptr
);
3172 rb_io_check_byte_readable(fptr
);
3175 io_set_read_length(str
, 0, shrinkable
);
3181 n
= read_buffered_data(RSTRING_PTR(str
), len
, fptr
);
3185 rb_io_set_nonblock(fptr
);
3187 io_setstrbuf(&str
, len
);
3188 iis
.th
= rb_thread_current();
3190 iis
.nonblock
= nonblock
;
3191 iis
.buf
= RSTRING_PTR(str
);
3193 n
= read_internal_locktmp(str
, &iis
);
3196 if (!nonblock
&& fptr_wait_readable(fptr
))
3198 if (nonblock
&& (io_again_p(e
))) {
3200 return sym_wait_readable
;
3202 rb_readwrite_syserr_fail(RB_IO_WAIT_READABLE
,
3203 e
, "read would block");
3205 rb_syserr_fail_path(e
, fptr
->pathv
);
3208 io_set_read_length(str
, n
, shrinkable
);
3218 * readpartial(maxlen) -> string
3219 * readpartial(maxlen, out_string) -> out_string
3221 * Reads up to +maxlen+ bytes from the stream;
3222 * returns a string (either a new string or the given +out_string+).
3225 * - The unchanged encoding of +out_string+, if +out_string+ is given.
3226 * - ASCII-8BIT, otherwise.
3228 * - Contains +maxlen+ bytes from the stream, if available.
3229 * - Otherwise contains all available bytes, if any available.
3230 * - Otherwise is an empty string.
3232 * With the single non-negative integer argument +maxlen+ given,
3233 * returns a new string:
3235 * f = File.new('t.txt')
3236 * f.readpartial(20) # => "First line\nSecond l"
3237 * f.readpartial(20) # => "ine\n\nFourth line\n"
3238 * f.readpartial(20) # => "Fifth line\n"
3239 * f.readpartial(20) # Raises EOFError.
3241 * With both argument +maxlen+ and string argument +out_string+ given,
3242 * returns modified +out_string+:
3244 * f = File.new('t.txt')
3246 * f.readpartial(20, s) # => "First line\nSecond l"
3248 * f.readpartial(0, s) # => ""
3250 * This method is useful for a stream such as a pipe, a socket, or a tty.
3251 * It blocks only when no data is immediately available.
3252 * This means that it blocks only when _all_ of the following are true:
3254 * - The byte buffer in the stream is empty.
3255 * - The content of the stream is empty.
3256 * - The stream is not at EOF.
3258 * When blocked, the method waits for either more data or EOF on the stream:
3260 * - If more data is read, the method returns the data.
3261 * - If EOF is reached, the method raises EOFError.
3263 * When not blocked, the method responds immediately:
3265 * - Returns data from the buffer if there is any.
3266 * - Otherwise returns data from the stream if there is any.
3267 * - Otherwise raises EOFError if the stream has reached EOF.
3269 * Note that this method is similar to sysread. The differences are:
3271 * - If the byte buffer is not empty, read from the byte buffer
3272 * instead of "sysread for buffered IO (IOError)".
3273 * - It doesn't cause Errno::EWOULDBLOCK and Errno::EINTR. When
3274 * readpartial meets EWOULDBLOCK and EINTR by read system call,
3275 * readpartial retries the system call.
3277 * The latter means that readpartial is non-blocking-flag insensitive.
3278 * It blocks on the situation IO#sysread causes Errno::EWOULDBLOCK as
3279 * if the fd is blocking mode.
3283 * # # Returned Buffer Content Pipe Content
3285 * w << 'abc' # "" "abc".
3286 * r.readpartial(4096) # => "abc" "" ""
3287 * r.readpartial(4096) # (Blocks because buffer and pipe are empty.)
3289 * # # Returned Buffer Content Pipe Content
3291 * w << 'abc' # "" "abc"
3292 * w.close # "" "abc" EOF
3293 * r.readpartial(4096) # => "abc" "" EOF
3294 * r.readpartial(4096) # raises EOFError
3296 * # # Returned Buffer Content Pipe Content
3298 * w << "abc\ndef\n" # "" "abc\ndef\n"
3299 * r.gets # => "abc\n" "def\n" ""
3300 * w << "ghi\n" # "def\n" "ghi\n"
3301 * r.readpartial(4096) # => "def\n" "" "ghi\n"
3302 * r.readpartial(4096) # => "ghi\n" "" ""
3307 io_readpartial(int argc
, VALUE
*argv
, VALUE io
)
3311 ret
= io_getpartial(argc
, argv
, io
, Qnil
, 0);
3318 io_nonblock_eof(int no_exception
)
3320 if (!no_exception
) {
3328 io_read_nonblock(rb_execution_context_t
*ec
, VALUE io
, VALUE length
, VALUE str
, VALUE ex
)
3332 struct io_internal_read_struct iis
;
3335 if ((len
= NUM2LONG(length
)) < 0) {
3336 rb_raise(rb_eArgError
, "negative length %ld given", len
);
3339 shrinkable
= io_setstrbuf(&str
, len
);
3340 rb_bool_expected(ex
, "exception");
3342 GetOpenFile(io
, fptr
);
3343 rb_io_check_byte_readable(fptr
);
3346 io_set_read_length(str
, 0, shrinkable
);
3350 n
= read_buffered_data(RSTRING_PTR(str
), len
, fptr
);
3352 rb_io_set_nonblock(fptr
);
3353 shrinkable
|= io_setstrbuf(&str
, len
);
3356 iis
.buf
= RSTRING_PTR(str
);
3358 n
= read_internal_locktmp(str
, &iis
);
3361 if (io_again_p(e
)) {
3362 if (!ex
) return sym_wait_readable
;
3363 rb_readwrite_syserr_fail(RB_IO_WAIT_READABLE
,
3364 e
, "read would block");
3366 rb_syserr_fail_path(e
, fptr
->pathv
);
3369 io_set_read_length(str
, n
, shrinkable
);
3372 if (!ex
) return Qnil
;
3381 io_write_nonblock(rb_execution_context_t
*ec
, VALUE io
, VALUE str
, VALUE ex
)
3386 if (!RB_TYPE_P(str
, T_STRING
))
3387 str
= rb_obj_as_string(str
);
3388 rb_bool_expected(ex
, "exception");
3390 io
= GetWriteIO(io
);
3391 GetOpenFile(io
, fptr
);
3392 rb_io_check_writable(fptr
);
3394 if (io_fflush(fptr
) < 0)
3395 rb_sys_fail_on_write(fptr
);
3397 rb_io_set_nonblock(fptr
);
3398 n
= write(fptr
->fd
, RSTRING_PTR(str
), RSTRING_LEN(str
));
3403 if (io_again_p(e
)) {
3405 return sym_wait_writable
;
3408 rb_readwrite_syserr_fail(RB_IO_WAIT_WRITABLE
, e
, "write would block");
3411 rb_syserr_fail_path(e
, fptr
->pathv
);
3419 * read(maxlen = nil) -> string or nil
3420 * read(maxlen = nil, out_string) -> out_string or nil
3422 * Reads bytes from the stream (in binary mode):
3424 * - If +maxlen+ is +nil+, reads all bytes.
3425 * - Otherwise reads +maxlen+ bytes, if available.
3426 * - Otherwise reads all bytes.
3428 * Returns a string (either a new string or the given +out_string+)
3429 * containing the bytes read.
3430 * The encoding of the string depends on both +maxLen+ and +out_string+:
3432 * - +maxlen+ is +nil+: uses internal encoding of +self+
3433 * (regardless of whether +out_string+ was given).
3434 * - +maxlen+ not +nil+:
3436 * - +out_string+ given: encoding of +out_string+ not modified.
3437 * - +out_string+ not given: ASCII-8BIT is used.
3439 * <b>Without Argument +out_string+</b>
3441 * When argument +out_string+ is omitted,
3442 * the returned value is a new string:
3444 * f = File.new('t.txt')
3446 * # => "First line\nSecond line\n\nFourth line\nFifth line\n"
3448 * f.read(30) # => "First line\r\nSecond line\r\n\r\nFou"
3449 * f.read(30) # => "rth line\r\nFifth line\r\n"
3450 * f.read(30) # => nil
3452 * If +maxlen+ is zero, returns an empty string.
3454 * <b> With Argument +out_string+</b>
3456 * When argument +out_string+ is given,
3457 * the returned value is +out_string+, whose content is replaced:
3459 * f = File.new('t.txt')
3460 * s = 'foo' # => "foo"
3461 * f.read(nil, s) # => "First line\nSecond line\n\nFourth line\nFifth line\n"
3462 * s # => "First line\nSecond line\n\nFourth line\nFifth line\n"
3465 * f.read(30, s) # => "First line\r\nSecond line\r\n\r\nFou"
3466 * s # => "First line\r\nSecond line\r\n\r\nFou"
3468 * f.read(30, s) # => "rth line\r\nFifth line\r\n"
3469 * s # => "rth line\r\nFifth line\r\n"
3471 * f.read(30, s) # => nil
3474 * Note that this method behaves like the fread() function in C.
3475 * This means it retries to invoke read(2) system calls to read data
3476 * with the specified maxlen (or until EOF).
3478 * This behavior is preserved even if the stream is in non-blocking mode.
3479 * (This method is non-blocking-flag insensitive as other methods.)
3481 * If you need the behavior like a single read(2) system call,
3482 * consider #readpartial, #read_nonblock, and #sysread.
3487 io_read(int argc
, VALUE
*argv
, VALUE io
)
3493 #if RUBY_CRLF_ENVIRONMENT
3497 rb_scan_args(argc
, argv
, "02", &length
, &str
);
3499 if (NIL_P(length
)) {
3500 GetOpenFile(io
, fptr
);
3501 rb_io_check_char_readable(fptr
);
3502 return read_all(fptr
, remain_size(fptr
), str
);
3504 len
= NUM2LONG(length
);
3506 rb_raise(rb_eArgError
, "negative length %ld given", len
);
3509 shrinkable
= io_setstrbuf(&str
,len
);
3511 GetOpenFile(io
, fptr
);
3512 rb_io_check_byte_readable(fptr
);
3514 io_set_read_length(str
, 0, shrinkable
);
3519 #if RUBY_CRLF_ENVIRONMENT
3520 previous_mode
= set_binary_mode_with_seek_cur(fptr
);
3522 n
= io_fread(str
, 0, len
, fptr
);
3523 io_set_read_length(str
, n
, shrinkable
);
3524 #if RUBY_CRLF_ENVIRONMENT
3525 if (previous_mode
== O_TEXT
) {
3526 setmode(fptr
->fd
, O_TEXT
);
3529 if (n
== 0) return Qnil
;
3535 rscheck(const char *rsptr
, long rslen
, VALUE rs
)
3538 if (RSTRING_PTR(rs
) != rsptr
&& RSTRING_LEN(rs
) != rslen
)
3539 rb_raise(rb_eRuntimeError
, "rs modified");
3543 appendline(rb_io_t
*fptr
, int delim
, VALUE
*strp
, long *lp
)
3548 if (NEED_READCONV(fptr
)) {
3549 SET_BINARY_MODE(fptr
);
3550 make_readconv(fptr
, 0);
3553 int searchlen
= READ_CHAR_PENDING_COUNT(fptr
);
3555 p
= READ_CHAR_PENDING_PTR(fptr
);
3556 if (0 < limit
&& limit
< searchlen
)
3557 searchlen
= (int)limit
;
3558 e
= memchr(p
, delim
, searchlen
);
3560 int len
= (int)(e
-p
+1);
3562 *strp
= str
= rb_str_new(p
, len
);
3564 rb_str_buf_cat(str
, p
, len
);
3565 fptr
->cbuf
.off
+= len
;
3566 fptr
->cbuf
.len
-= len
;
3573 *strp
= str
= rb_str_new(p
, searchlen
);
3575 rb_str_buf_cat(str
, p
, searchlen
);
3576 fptr
->cbuf
.off
+= searchlen
;
3577 fptr
->cbuf
.len
-= searchlen
;
3582 return (unsigned char)RSTRING_PTR(str
)[RSTRING_LEN(str
)-1];
3585 } while (more_char(fptr
) != MORE_CHAR_FINISHED
);
3586 clear_readconv(fptr
);
3591 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr
);
3593 long pending
= READ_DATA_PENDING_COUNT(fptr
);
3595 const char *p
= READ_DATA_PENDING_PTR(fptr
);
3599 if (limit
> 0 && pending
> limit
) pending
= limit
;
3600 e
= memchr(p
, delim
, pending
);
3601 if (e
) pending
= e
- p
+ 1;
3603 last
= RSTRING_LEN(str
);
3604 rb_str_resize(str
, last
+ pending
);
3608 *strp
= str
= rb_str_buf_new(pending
);
3609 rb_str_set_len(str
, pending
);
3611 read_buffered_data(RSTRING_PTR(str
) + last
, pending
, fptr
); /* must not fail */
3614 if (e
) return delim
;
3616 return (unsigned char)RSTRING_PTR(str
)[RSTRING_LEN(str
)-1];
3619 } while (io_fillbuf(fptr
) >= 0);
3625 swallow(rb_io_t
*fptr
, int term
)
3627 if (NEED_READCONV(fptr
)) {
3628 rb_encoding
*enc
= io_read_encoding(fptr
);
3629 int needconv
= rb_enc_mbminlen(enc
) != 1;
3630 SET_BINARY_MODE(fptr
);
3631 make_readconv(fptr
, 0);
3634 while ((cnt
= READ_CHAR_PENDING_COUNT(fptr
)) > 0) {
3635 const char *p
= READ_CHAR_PENDING_PTR(fptr
);
3638 if (*p
!= term
) return TRUE
;
3640 while (--i
&& *++p
== term
);
3643 const char *e
= p
+ cnt
;
3644 if (rb_enc_ascget(p
, e
, &i
, enc
) != term
) return TRUE
;
3645 while ((p
+= i
) < e
&& rb_enc_ascget(p
, e
, &i
, enc
) == term
);
3648 io_shift_cbuf(fptr
, (int)cnt
- i
, NULL
);
3650 } while (more_char(fptr
) != MORE_CHAR_FINISHED
);
3654 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr
);
3657 while ((cnt
= READ_DATA_PENDING_COUNT(fptr
)) > 0) {
3659 const char *p
= READ_DATA_PENDING_PTR(fptr
);
3661 if (cnt
> sizeof buf
) cnt
= sizeof buf
;
3662 if (*p
!= term
) return TRUE
;
3664 while (--i
&& *++p
== term
);
3665 if (!read_buffered_data(buf
, cnt
- i
, fptr
)) /* must not fail */
3666 rb_sys_fail_path(fptr
->pathv
);
3669 } while (io_fillbuf(fptr
) == 0);
3674 rb_io_getline_fast(rb_io_t
*fptr
, rb_encoding
*enc
, int chomp
)
3682 int pending
= READ_DATA_PENDING_COUNT(fptr
);
3685 const char *p
= READ_DATA_PENDING_PTR(fptr
);
3689 e
= memchr(p
, '\n', pending
);
3691 pending
= (int)(e
- p
+ 1);
3693 chomplen
= (pending
> 1 && *(e
-1) == '\r') + 1;
3697 str
= rb_str_new(p
, pending
- chomplen
);
3698 fptr
->rbuf
.off
+= pending
;
3699 fptr
->rbuf
.len
-= pending
;
3702 rb_str_resize(str
, len
+ pending
- chomplen
);
3703 read_buffered_data(RSTRING_PTR(str
)+len
, pending
- chomplen
, fptr
);
3704 fptr
->rbuf
.off
+= chomplen
;
3705 fptr
->rbuf
.len
-= chomplen
;
3706 if (pending
== 1 && chomplen
== 1 && len
> 0) {
3707 if (RSTRING_PTR(str
)[len
-1] == '\r') {
3708 rb_str_resize(str
, --len
);
3713 len
+= pending
- chomplen
;
3714 if (cr
!= ENC_CODERANGE_BROKEN
)
3715 pos
+= rb_str_coderange_scan_restartable(RSTRING_PTR(str
) + pos
, RSTRING_PTR(str
) + len
, enc
, &cr
);
3719 } while (io_fillbuf(fptr
) >= 0);
3720 if (NIL_P(str
)) return Qnil
;
3722 str
= io_enc_str(str
, fptr
);
3723 ENC_CODERANGE_SET(str
, cr
);
3729 struct getline_arg
{
3733 unsigned int chomp
: 1;
3737 extract_getline_opts(VALUE opts
, struct getline_arg
*args
)
3744 kwds
[0] = rb_intern_const("chomp");
3746 rb_get_kwargs(opts
, kwds
, 0, -2, &vchomp
);
3747 chomp
= (vchomp
!= Qundef
) && RTEST(vchomp
);
3749 args
->chomp
= chomp
;
3753 extract_getline_args(int argc
, VALUE
*argv
, struct getline_arg
*args
)
3755 VALUE rs
= rb_rs
, lim
= Qnil
;
3760 if (NIL_P(argv
[0]) || !NIL_P(tmp
= rb_check_string_type(argv
[0]))) {
3767 else if (2 <= argc
) {
3768 rs
= argv
[0], lim
= argv
[1];
3773 args
->limit
= NIL_P(lim
) ? -1L : NUM2LONG(lim
);
3777 check_getline_args(VALUE
*rsp
, long *limit
, VALUE io
)
3783 rb_encoding
*enc_rs
, *enc_io
;
3785 GetOpenFile(io
, fptr
);
3786 enc_rs
= rb_enc_get(rs
);
3787 enc_io
= io_read_encoding(fptr
);
3788 if (enc_io
!= enc_rs
&&
3789 (rb_enc_str_coderange(rs
) != ENC_CODERANGE_7BIT
||
3790 (RSTRING_LEN(rs
) > 0 && !rb_enc_asciicompat(enc_io
)))) {
3791 if (rs
== rb_default_rs
) {
3792 rs
= rb_enc_str_new(0, 0, enc_io
);
3793 rb_str_buf_cat_ascii(rs
, "\n");
3797 rb_raise(rb_eArgError
, "encoding mismatch: %s IO with %s RS",
3798 rb_enc_name(enc_io
),
3799 rb_enc_name(enc_rs
));
3806 prepare_getline_args(int argc
, VALUE
*argv
, struct getline_arg
*args
, VALUE io
)
3809 argc
= rb_scan_args(argc
, argv
, "02:", NULL
, NULL
, &opts
);
3810 extract_getline_args(argc
, argv
, args
);
3811 extract_getline_opts(opts
, args
);
3812 check_getline_args(&args
->rs
, &args
->limit
, io
);
3816 rb_io_getline_0(VALUE rs
, long limit
, int chomp
, rb_io_t
*fptr
)
3822 rb_io_check_char_readable(fptr
);
3823 if (NIL_P(rs
) && limit
< 0) {
3824 str
= read_all(fptr
, 0, Qnil
);
3825 if (RSTRING_LEN(str
) == 0) return Qnil
;
3826 if (chomp
) rb_str_chomp_string(str
, rb_default_rs
);
3828 else if (limit
== 0) {
3829 return rb_enc_str_new(0, 0, io_read_encoding(fptr
));
3831 else if (rs
== rb_default_rs
&& limit
< 0 && !NEED_READCONV(fptr
) &&
3832 rb_enc_asciicompat(enc
= io_read_encoding(fptr
))) {
3833 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr
);
3834 return rb_io_getline_fast(fptr
, enc
, chomp
);
3837 int c
, newline
= -1;
3838 const char *rsptr
= 0;
3841 int extra_limit
= 16;
3842 int chomp_cr
= chomp
;
3844 SET_BINARY_MODE(fptr
);
3845 enc
= io_read_encoding(fptr
);
3848 rslen
= RSTRING_LEN(rs
);
3853 swallow(fptr
, '\n');
3855 if (!rb_enc_asciicompat(enc
)) {
3856 rs
= rb_usascii_str_new(rsptr
, rslen
);
3857 rs
= rb_str_encode(rs
, rb_enc_from_encoding(enc
), 0, Qnil
);
3859 rsptr
= RSTRING_PTR(rs
);
3860 rslen
= RSTRING_LEN(rs
);
3864 rsptr
= RSTRING_PTR(rs
);
3866 newline
= (unsigned char)rsptr
[rslen
- 1];
3867 chomp_cr
= chomp
&& rslen
== 1 && newline
== '\n';
3870 /* MS - Optimization */
3871 while ((c
= appendline(fptr
, newline
, &str
, &limit
)) != EOF
) {
3872 const char *s
, *p
, *pp
, *e
;
3875 if (RSTRING_LEN(str
) < rslen
) continue;
3876 s
= RSTRING_PTR(str
);
3877 e
= RSTRING_END(str
);
3879 pp
= rb_enc_left_char_head(s
, p
, e
, enc
);
3880 if (pp
!= p
) continue;
3881 if (!rspara
) rscheck(rsptr
, rslen
, rs
);
3882 if (memcmp(p
, rsptr
, rslen
) == 0) {
3884 if (chomp_cr
&& p
> s
&& *(p
-1) == '\r') --p
;
3885 rb_str_set_len(str
, p
- s
);
3891 s
= RSTRING_PTR(str
);
3892 p
= RSTRING_END(str
);
3893 pp
= rb_enc_left_char_head(s
, p
-1, p
, enc
);
3895 MBCLEN_NEEDMORE_P(rb_enc_precise_mbclen(pp
, p
, enc
))) {
3896 /* relax the limit while incomplete character.
3897 * extra_limit limits the relax length */
3908 if (rspara
&& c
!= EOF
)
3909 swallow(fptr
, '\n');
3911 str
= io_enc_str(str
, fptr
);
3914 if (!NIL_P(str
) && !nolimit
) {
3922 rb_io_getline_1(VALUE rs
, long limit
, int chomp
, VALUE io
)
3925 int old_lineno
, new_lineno
;
3928 GetOpenFile(io
, fptr
);
3929 old_lineno
= fptr
->lineno
;
3930 str
= rb_io_getline_0(rs
, limit
, chomp
, fptr
);
3931 if (!NIL_P(str
) && (new_lineno
= fptr
->lineno
) != old_lineno
) {
3932 if (io
== ARGF
.current_file
) {
3933 ARGF
.lineno
+= new_lineno
- old_lineno
;
3934 ARGF
.last_lineno
= ARGF
.lineno
;
3937 ARGF
.last_lineno
= new_lineno
;
3945 rb_io_getline(int argc
, VALUE
*argv
, VALUE io
)
3947 struct getline_arg args
;
3949 prepare_getline_args(argc
, argv
, &args
, io
);
3950 return rb_io_getline_1(args
.rs
, args
.limit
, args
.chomp
, io
);
3954 rb_io_gets(VALUE io
)
3956 return rb_io_getline_1(rb_default_rs
, -1, FALSE
, io
);
3960 rb_io_gets_internal(VALUE io
)
3963 GetOpenFile(io
, fptr
);
3964 return rb_io_getline_0(rb_default_rs
, -1, FALSE
, fptr
);
3969 * gets(sep = $/, **getline_opts) -> string or nil
3970 * gets(limit, **getline_opts) -> string or nil
3971 * gets(sep, limit, **getline_opts) -> string or nil
3973 * Reads and returns a line from the stream
3974 * (see {Lines}[#class-IO-label-Lines])
3975 * assigns the return value to <tt>$_</tt>.
3977 * With no arguments given, returns the next line
3978 * as determined by line separator <tt>$/</tt>, or +nil+ if none:
3980 * f = File.open('t.txt')
3981 * f.gets # => "First line\n"
3982 * $_ # => "First line\n"
3984 * f.gets # => "Fourth line\n"
3985 * f.gets # => "Fifth line\n"
3988 * With only string argument +sep+ given,
3989 * returns the next line as determined by line separator +sep+,
3991 * see {Line Separator}[#class-IO-label-Line+Separator]:
3993 * f = File.new('t.txt')
3994 * f.gets('l') # => "First l"
3995 * f.gets('li') # => "ine\nSecond li"
3996 * f.gets('lin') # => "ne\n\nFourth lin"
3999 * The two special values for +sep+ are honored:
4001 * f = File.new('t.txt')
4003 * f.gets(nil) # => "First line\nSecond line\n\nFourth line\nFifth line\n"
4005 * # Get paragraph (up to two line separators).
4006 * f.gets('') # => "First line\nSecond line\n\n"
4008 * With only integer argument +limit+ given,
4009 * returns up to <tt>limit+1</tt> bytes;
4010 * see {Line Limit}}[#class-IO-label-Line+Limit]:
4012 * # No more than one line.
4013 * File.open('t.txt') {|f| f.gets(10) } # => "First line"
4014 * File.open('t.txt') {|f| f.gets(11) } # => "First line\n"
4015 * File.open('t.txt') {|f| f.gets(12) } # => "First line\n"
4017 * For all forms above, trailing optional keyword arguments may be given;
4018 * see {Getline Options}[#class-IO-label-Getline+Options]:
4020 * f = File.open('t.txt')
4021 * # Chomp the lines.
4022 * f.gets(chomp: true) # => "First line"
4023 * f.gets(chomp: true) # => "Second line"
4024 * f.gets(chomp: true) # => ""
4025 * f.gets(chomp: true) # => "Fourth line"
4026 * f.gets(chomp: true) # => "Fifth line"
4027 * f.gets(chomp: true) # => nil
4032 rb_io_gets_m(int argc
, VALUE
*argv
, VALUE io
)
4036 str
= rb_io_getline(argc
, argv
, io
);
4037 rb_lastline_set(str
);
4044 * ios.lineno -> integer
4046 * Returns the current line number in <em>ios</em>. The stream must be
4047 * opened for reading. #lineno counts the number of times #gets is called
4048 * rather than the number of newlines encountered. The two values will
4049 * differ if #gets is called with a separator other than newline.
4051 * Methods that use <code>$/</code> like #each, #lines and #readline will
4052 * also increment #lineno.
4054 * See also the <code>$.</code> variable.
4056 * f = File.new("testfile")
4058 * f.gets #=> "This is line one\n"
4060 * f.gets #=> "This is line two\n"
4065 rb_io_lineno(VALUE io
)
4069 GetOpenFile(io
, fptr
);
4070 rb_io_check_char_readable(fptr
);
4071 return INT2NUM(fptr
->lineno
);
4076 * ios.lineno = integer -> integer
4078 * Manually sets the current line number to the given value.
4079 * <code>$.</code> is updated only on the next read.
4081 * f = File.new("testfile")
4082 * f.gets #=> "This is line one\n"
4086 * $. #=> 1 # lineno of last read
4087 * f.gets #=> "This is line two\n"
4088 * $. #=> 1001 # lineno of last read
4092 rb_io_set_lineno(VALUE io
, VALUE lineno
)
4096 GetOpenFile(io
, fptr
);
4097 rb_io_check_char_readable(fptr
);
4098 fptr
->lineno
= NUM2INT(lineno
);
4104 * ios.readline(sep=$/ [, getline_args]) -> string
4105 * ios.readline(limit [, getline_args]) -> string
4106 * ios.readline(sep, limit [, getline_args]) -> string
4108 * Reads a line as with IO#gets, but raises an EOFError on end of file.
4112 rb_io_readline(int argc
, VALUE
*argv
, VALUE io
)
4114 VALUE line
= rb_io_gets_m(argc
, argv
, io
);
4122 static VALUE
io_readlines(const struct getline_arg
*arg
, VALUE io
);
4126 * ios.readlines(sep=$/ [, getline_args]) -> array
4127 * ios.readlines(limit [, getline_args]) -> array
4128 * ios.readlines(sep, limit [, getline_args]) -> array
4130 * Reads all of the lines in <em>ios</em>, and returns them in
4131 * an array. Lines are separated by the optional <i>sep</i>. If
4132 * <i>sep</i> is +nil+, the rest of the stream is returned
4133 * as a single record.
4134 * If the first argument is an integer, or an
4135 * optional second argument is given, the returning string would not be
4136 * longer than the given value in bytes. The stream must be opened for
4137 * reading or an IOError will be raised.
4139 * f = File.new("testfile")
4140 * f.readlines[0] #=> "This is line one\n"
4142 * f = File.new("testfile", chomp: true)
4143 * f.readlines[0] #=> "This is line one"
4145 * See IO.readlines for details about getline_args.
4149 rb_io_readlines(int argc
, VALUE
*argv
, VALUE io
)
4151 struct getline_arg args
;
4153 prepare_getline_args(argc
, argv
, &args
, io
);
4154 return io_readlines(&args
, io
);
4158 io_readlines(const struct getline_arg
*arg
, VALUE io
)
4162 if (arg
->limit
== 0)
4163 rb_raise(rb_eArgError
, "invalid limit: 0 for readlines");
4165 while (!NIL_P(line
= rb_io_getline_1(arg
->rs
, arg
->limit
, arg
->chomp
, io
))) {
4166 rb_ary_push(ary
, line
);
4173 * ios.each(sep=$/ [, getline_args]) {|line| block } -> ios
4174 * ios.each(limit [, getline_args]) {|line| block } -> ios
4175 * ios.each(sep, limit [, getline_args]) {|line| block } -> ios
4176 * ios.each(...) -> an_enumerator
4178 * ios.each_line(sep=$/ [, getline_args]) {|line| block } -> ios
4179 * ios.each_line(limit [, getline_args]) {|line| block } -> ios
4180 * ios.each_line(sep, limit [, getline_args]) {|line| block } -> ios
4181 * ios.each_line(...) -> an_enumerator
4183 * Executes the block for every line in <em>ios</em>, where lines are
4184 * separated by <i>sep</i>. <em>ios</em> must be opened for
4185 * reading or an IOError will be raised.
4187 * If no block is given, an enumerator is returned instead.
4189 * f = File.new("testfile")
4190 * f.each {|line| puts "#{f.lineno}: #{line}" }
4192 * <em>produces:</em>
4194 * 1: This is line one
4195 * 2: This is line two
4196 * 3: This is line three
4199 * See IO.readlines for details about getline_args.
4203 rb_io_each_line(int argc
, VALUE
*argv
, VALUE io
)
4206 struct getline_arg args
;
4208 RETURN_ENUMERATOR(io
, argc
, argv
);
4209 prepare_getline_args(argc
, argv
, &args
, io
);
4210 if (args
.limit
== 0)
4211 rb_raise(rb_eArgError
, "invalid limit: 0 for each_line");
4212 while (!NIL_P(str
= rb_io_getline_1(args
.rs
, args
.limit
, args
.chomp
, io
))) {
4220 * ios.each_byte {|byte| block } -> ios
4221 * ios.each_byte -> an_enumerator
4223 * Calls the given block once for each byte (0..255) in <em>ios</em>,
4224 * passing the byte as an argument. The stream must be opened for
4225 * reading or an IOError will be raised.
4227 * If no block is given, an enumerator is returned instead.
4229 * f = File.new("testfile")
4231 * f.each_byte {|x| checksum ^= x } #=> #<File:testfile>
4236 rb_io_each_byte(VALUE io
)
4240 RETURN_ENUMERATOR(io
, 0, 0);
4241 GetOpenFile(io
, fptr
);
4244 while (fptr
->rbuf
.len
> 0) {
4245 char *p
= fptr
->rbuf
.ptr
+ fptr
->rbuf
.off
++;
4247 rb_yield(INT2FIX(*p
& 0xff));
4248 rb_io_check_byte_readable(fptr
);
4252 } while (io_fillbuf(fptr
) >= 0);
4257 io_getc(rb_io_t
*fptr
, rb_encoding
*enc
)
4262 if (NEED_READCONV(fptr
)) {
4263 rb_encoding
*read_enc
= io_read_encoding(fptr
);
4266 SET_BINARY_MODE(fptr
);
4267 make_readconv(fptr
, 0);
4270 if (fptr
->cbuf
.len
) {
4271 r
= rb_enc_precise_mbclen(fptr
->cbuf
.ptr
+fptr
->cbuf
.off
,
4272 fptr
->cbuf
.ptr
+fptr
->cbuf
.off
+fptr
->cbuf
.len
,
4274 if (!MBCLEN_NEEDMORE_P(r
))
4276 if (fptr
->cbuf
.len
== fptr
->cbuf
.capa
) {
4277 rb_raise(rb_eIOError
, "too long character");
4281 if (more_char(fptr
) == MORE_CHAR_FINISHED
) {
4282 if (fptr
->cbuf
.len
== 0) {
4283 clear_readconv(fptr
);
4286 /* return an unit of an incomplete character just before EOF */
4287 str
= rb_enc_str_new(fptr
->cbuf
.ptr
+fptr
->cbuf
.off
, 1, read_enc
);
4288 fptr
->cbuf
.off
+= 1;
4289 fptr
->cbuf
.len
-= 1;
4290 if (fptr
->cbuf
.len
== 0) clear_readconv(fptr
);
4291 ENC_CODERANGE_SET(str
, ENC_CODERANGE_BROKEN
);
4295 if (MBCLEN_INVALID_P(r
)) {
4296 r
= rb_enc_mbclen(fptr
->cbuf
.ptr
+fptr
->cbuf
.off
,
4297 fptr
->cbuf
.ptr
+fptr
->cbuf
.off
+fptr
->cbuf
.len
,
4299 io_shift_cbuf(fptr
, r
, &str
);
4300 cr
= ENC_CODERANGE_BROKEN
;
4303 io_shift_cbuf(fptr
, MBCLEN_CHARFOUND_LEN(r
), &str
);
4304 cr
= ENC_CODERANGE_VALID
;
4305 if (MBCLEN_CHARFOUND_LEN(r
) == 1 && rb_enc_asciicompat(read_enc
) &&
4306 ISASCII(RSTRING_PTR(str
)[0])) {
4307 cr
= ENC_CODERANGE_7BIT
;
4310 str
= io_enc_str(str
, fptr
);
4311 ENC_CODERANGE_SET(str
, cr
);
4315 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr
);
4316 if (io_fillbuf(fptr
) < 0) {
4319 if (rb_enc_asciicompat(enc
) && ISASCII(fptr
->rbuf
.ptr
[fptr
->rbuf
.off
])) {
4320 str
= rb_str_new(fptr
->rbuf
.ptr
+fptr
->rbuf
.off
, 1);
4321 fptr
->rbuf
.off
+= 1;
4322 fptr
->rbuf
.len
-= 1;
4323 cr
= ENC_CODERANGE_7BIT
;
4326 r
= rb_enc_precise_mbclen(fptr
->rbuf
.ptr
+fptr
->rbuf
.off
, fptr
->rbuf
.ptr
+fptr
->rbuf
.off
+fptr
->rbuf
.len
, enc
);
4327 if (MBCLEN_CHARFOUND_P(r
) &&
4328 (n
= MBCLEN_CHARFOUND_LEN(r
)) <= fptr
->rbuf
.len
) {
4329 str
= rb_str_new(fptr
->rbuf
.ptr
+fptr
->rbuf
.off
, n
);
4330 fptr
->rbuf
.off
+= n
;
4331 fptr
->rbuf
.len
-= n
;
4332 cr
= ENC_CODERANGE_VALID
;
4334 else if (MBCLEN_NEEDMORE_P(r
)) {
4335 str
= rb_str_new(fptr
->rbuf
.ptr
+fptr
->rbuf
.off
, fptr
->rbuf
.len
);
4338 if (io_fillbuf(fptr
) != -1) {
4339 rb_str_cat(str
, fptr
->rbuf
.ptr
+fptr
->rbuf
.off
, 1);
4342 r
= rb_enc_precise_mbclen(RSTRING_PTR(str
), RSTRING_PTR(str
)+RSTRING_LEN(str
), enc
);
4343 if (MBCLEN_NEEDMORE_P(r
)) {
4346 else if (MBCLEN_CHARFOUND_P(r
)) {
4347 cr
= ENC_CODERANGE_VALID
;
4352 str
= rb_str_new(fptr
->rbuf
.ptr
+fptr
->rbuf
.off
, 1);
4357 if (!cr
) cr
= ENC_CODERANGE_BROKEN
;
4358 str
= io_enc_str(str
, fptr
);
4359 ENC_CODERANGE_SET(str
, cr
);
4365 * ios.each_char {|c| block } -> ios
4366 * ios.each_char -> an_enumerator
4368 * Calls the given block once for each character in <em>ios</em>,
4369 * passing the character as an argument. The stream must be opened for
4370 * reading or an IOError will be raised.
4372 * If no block is given, an enumerator is returned instead.
4374 * f = File.new("testfile")
4375 * f.each_char {|c| print c, ' ' } #=> #<File:testfile>
4379 rb_io_each_char(VALUE io
)
4385 RETURN_ENUMERATOR(io
, 0, 0);
4386 GetOpenFile(io
, fptr
);
4387 rb_io_check_char_readable(fptr
);
4389 enc
= io_input_encoding(fptr
);
4391 while (!NIL_P(c
= io_getc(fptr
, enc
))) {
4399 * ios.each_codepoint {|c| block } -> ios
4400 * ios.each_codepoint -> an_enumerator
4402 * Passes the Integer ordinal of each character in <i>ios</i>,
4403 * passing the codepoint as an argument. The stream must be opened for
4404 * reading or an IOError will be raised.
4406 * If no block is given, an enumerator is returned instead.
4411 rb_io_each_codepoint(VALUE io
)
4418 RETURN_ENUMERATOR(io
, 0, 0);
4419 GetOpenFile(io
, fptr
);
4420 rb_io_check_char_readable(fptr
);
4423 if (NEED_READCONV(fptr
)) {
4424 SET_BINARY_MODE(fptr
);
4425 r
= 1; /* no invalid char yet */
4427 make_readconv(fptr
, 0);
4429 if (fptr
->cbuf
.len
) {
4431 r
= rb_enc_precise_mbclen(fptr
->cbuf
.ptr
+fptr
->cbuf
.off
,
4432 fptr
->cbuf
.ptr
+fptr
->cbuf
.off
+fptr
->cbuf
.len
,
4435 r
= ONIGENC_CONSTRUCT_MBCLEN_CHARFOUND(1);
4436 if (!MBCLEN_NEEDMORE_P(r
))
4438 if (fptr
->cbuf
.len
== fptr
->cbuf
.capa
) {
4439 rb_raise(rb_eIOError
, "too long character");
4442 if (more_char(fptr
) == MORE_CHAR_FINISHED
) {
4443 clear_readconv(fptr
);
4444 if (!MBCLEN_CHARFOUND_P(r
)) {
4445 enc
= fptr
->encs
.enc
;
4451 if (MBCLEN_INVALID_P(r
)) {
4452 enc
= fptr
->encs
.enc
;
4455 n
= MBCLEN_CHARFOUND_LEN(r
);
4456 if (fptr
->encs
.enc
) {
4457 c
= rb_enc_codepoint(fptr
->cbuf
.ptr
+fptr
->cbuf
.off
,
4458 fptr
->cbuf
.ptr
+fptr
->cbuf
.off
+fptr
->cbuf
.len
,
4462 c
= (unsigned char)fptr
->cbuf
.ptr
[fptr
->cbuf
.off
];
4464 fptr
->cbuf
.off
+= n
;
4465 fptr
->cbuf
.len
-= n
;
4466 rb_yield(UINT2NUM(c
));
4467 rb_io_check_byte_readable(fptr
);
4470 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr
);
4471 enc
= io_input_encoding(fptr
);
4472 while (io_fillbuf(fptr
) >= 0) {
4473 r
= rb_enc_precise_mbclen(fptr
->rbuf
.ptr
+fptr
->rbuf
.off
,
4474 fptr
->rbuf
.ptr
+fptr
->rbuf
.off
+fptr
->rbuf
.len
, enc
);
4475 if (MBCLEN_CHARFOUND_P(r
) &&
4476 (n
= MBCLEN_CHARFOUND_LEN(r
)) <= fptr
->rbuf
.len
) {
4477 c
= rb_enc_codepoint(fptr
->rbuf
.ptr
+fptr
->rbuf
.off
,
4478 fptr
->rbuf
.ptr
+fptr
->rbuf
.off
+fptr
->rbuf
.len
, enc
);
4479 fptr
->rbuf
.off
+= n
;
4480 fptr
->rbuf
.len
-= n
;
4481 rb_yield(UINT2NUM(c
));
4483 else if (MBCLEN_INVALID_P(r
)) {
4486 else if (MBCLEN_NEEDMORE_P(r
)) {
4487 char cbuf
[8], *p
= cbuf
;
4488 int more
= MBCLEN_NEEDMORE_LEN(r
);
4489 if (more
> numberof(cbuf
)) goto invalid
;
4490 more
+= n
= fptr
->rbuf
.len
;
4491 if (more
> numberof(cbuf
)) goto invalid
;
4492 while ((n
= (int)read_buffered_data(p
, more
, fptr
)) > 0 &&
4493 (p
+= n
, (more
-= n
) > 0)) {
4494 if (io_fillbuf(fptr
) < 0) goto invalid
;
4495 if ((n
= fptr
->rbuf
.len
) > more
) n
= more
;
4497 r
= rb_enc_precise_mbclen(cbuf
, p
, enc
);
4498 if (!MBCLEN_CHARFOUND_P(r
)) goto invalid
;
4499 c
= rb_enc_codepoint(cbuf
, p
, enc
);
4500 rb_yield(UINT2NUM(c
));
4505 rb_io_check_byte_readable(fptr
);
4510 rb_raise(rb_eArgError
, "invalid byte sequence in %s", rb_enc_name(enc
));
4511 UNREACHABLE_RETURN(Qundef
);
4516 * ios.getc -> string or nil
4518 * Reads a one-character string from <em>ios</em>. Returns
4519 * +nil+ if called at end of file.
4521 * f = File.new("testfile")
4527 rb_io_getc(VALUE io
)
4532 GetOpenFile(io
, fptr
);
4533 rb_io_check_char_readable(fptr
);
4535 enc
= io_input_encoding(fptr
);
4537 return io_getc(fptr
, enc
);
4542 * ios.readchar -> string
4544 * Reads a one-character string from <em>ios</em>. Raises an
4545 * EOFError on end of file.
4547 * f = File.new("testfile")
4548 * f.readchar #=> "h"
4549 * f.readchar #=> "e"
4553 rb_io_readchar(VALUE io
)
4555 VALUE c
= rb_io_getc(io
);
4565 * ios.getbyte -> integer or nil
4567 * Gets the next 8-bit byte (0..255) from <em>ios</em>. Returns
4568 * +nil+ if called at end of file.
4570 * f = File.new("testfile")
4576 rb_io_getbyte(VALUE io
)
4581 GetOpenFile(io
, fptr
);
4582 rb_io_check_byte_readable(fptr
);
4584 VALUE r_stdout
= rb_ractor_stdout();
4585 if (fptr
->fd
== 0 && (fptr
->mode
& FMODE_TTY
) && RB_TYPE_P(r_stdout
, T_FILE
)) {
4587 GetOpenFile(r_stdout
, ofp
);
4588 if (ofp
->mode
& FMODE_TTY
) {
4589 rb_io_flush(r_stdout
);
4592 if (io_fillbuf(fptr
) < 0) {
4597 c
= (unsigned char)fptr
->rbuf
.ptr
[fptr
->rbuf
.off
-1];
4598 return INT2FIX(c
& 0xff);
4603 * ios.readbyte -> integer
4605 * Reads a byte as with IO#getbyte, but raises an EOFError on end of
4610 rb_io_readbyte(VALUE io
)
4612 VALUE c
= rb_io_getbyte(io
);
4622 * ios.ungetbyte(string) -> nil
4623 * ios.ungetbyte(integer) -> nil
4625 * Pushes back bytes (passed as a parameter) onto <em>ios</em>,
4626 * such that a subsequent buffered read will return it.
4627 * It is only guaranteed to support a single byte, and only if ungetbyte
4628 * or ungetc has not already been called on <em>ios</em> since the previous
4629 * read of at least a single byte from <em>ios</em>.
4630 * However, it can support additional bytes if there is space in the
4631 * internal buffer to allow for it.
4633 * f = File.new("testfile") #=> #<File:testfile>
4634 * b = f.getbyte #=> 0x38
4635 * f.ungetbyte(b) #=> nil
4636 * f.getbyte #=> 0x38
4638 * If given an integer, only uses the lower 8 bits of the integer as the byte
4641 * f = File.new("testfile") #=> #<File:testfile>
4642 * f.ungetbyte(0x102) #=> nil
4645 * Calling this method prepends to the existing buffer, even if the method
4646 * has already been called previously:
4648 * f = File.new("testfile") #=> #<File:testfile>
4649 * f.ungetbyte("ab") #=> nil
4650 * f.ungetbyte("cd") #=> nil
4651 * f.read(5) #=> "cdab8"
4653 * Has no effect with unbuffered reads (such as IO#sysread).
4657 rb_io_ungetbyte(VALUE io
, VALUE b
)
4661 GetOpenFile(io
, fptr
);
4662 rb_io_check_byte_readable(fptr
);
4668 VALUE v
= rb_int_modulo(b
, INT2FIX(256));
4669 unsigned char c
= NUM2INT(v
) & 0xFF;
4670 b
= rb_str_new((const char *)&c
, 1);
4675 io_ungetbyte(b
, fptr
);
4681 * ios.ungetc(integer) -> nil
4682 * ios.ungetc(string) -> nil
4684 * Pushes back characters (passed as a parameter) onto <em>ios</em>,
4685 * such that a subsequent buffered read will return it.
4686 * It is only guaranteed to support a single byte, and only if ungetbyte
4687 * or ungetc has not already been called on <em>ios</em> since the previous
4688 * read of at least a single byte from <em>ios</em>.
4689 * However, it can support additional bytes if there is space in the
4690 * internal buffer to allow for it.
4692 * f = File.new("testfile") #=> #<File:testfile>
4693 * c = f.getc #=> "8"
4694 * f.ungetc(c) #=> nil
4697 * If given an integer, the integer must represent a valid codepoint in the
4698 * external encoding of <em>ios</em>.
4700 * Calling this method prepends to the existing buffer, even if the method
4701 * has already been called previously:
4703 * f = File.new("testfile") #=> #<File:testfile>
4704 * f.ungetc("ab") #=> nil
4705 * f.ungetc("cd") #=> nil
4706 * f.read(5) #=> "cdab8"
4708 * Has no effect with unbuffered reads (such as IO#sysread).
4712 rb_io_ungetc(VALUE io
, VALUE c
)
4717 GetOpenFile(io
, fptr
);
4718 rb_io_check_char_readable(fptr
);
4720 c
= rb_enc_uint_chr(FIX2UINT(c
), io_read_encoding(fptr
));
4722 else if (RB_BIGNUM_TYPE_P(c
)) {
4723 c
= rb_enc_uint_chr(NUM2UINT(c
), io_read_encoding(fptr
));
4728 if (NEED_READCONV(fptr
)) {
4729 SET_BINARY_MODE(fptr
);
4730 len
= RSTRING_LEN(c
);
4731 #if SIZEOF_LONG > SIZEOF_INT
4733 rb_raise(rb_eIOError
, "ungetc failed");
4735 make_readconv(fptr
, (int)len
);
4736 if (fptr
->cbuf
.capa
- fptr
->cbuf
.len
< len
)
4737 rb_raise(rb_eIOError
, "ungetc failed");
4738 if (fptr
->cbuf
.off
< len
) {
4739 MEMMOVE(fptr
->cbuf
.ptr
+fptr
->cbuf
.capa
-fptr
->cbuf
.len
,
4740 fptr
->cbuf
.ptr
+fptr
->cbuf
.off
,
4741 char, fptr
->cbuf
.len
);
4742 fptr
->cbuf
.off
= fptr
->cbuf
.capa
-fptr
->cbuf
.len
;
4744 fptr
->cbuf
.off
-= (int)len
;
4745 fptr
->cbuf
.len
+= (int)len
;
4746 MEMMOVE(fptr
->cbuf
.ptr
+fptr
->cbuf
.off
, RSTRING_PTR(c
), char, len
);
4749 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr
);
4750 io_ungetbyte(c
, fptr
);
4757 * ios.isatty -> true or false
4758 * ios.tty? -> true or false
4760 * Returns <code>true</code> if <em>ios</em> is associated with a
4761 * terminal device (tty), <code>false</code> otherwise.
4763 * File.new("testfile").isatty #=> false
4764 * File.new("/dev/tty").isatty #=> true
4768 rb_io_isatty(VALUE io
)
4772 GetOpenFile(io
, fptr
);
4773 return RBOOL(isatty(fptr
->fd
) != 0);
4776 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
4779 * ios.close_on_exec? -> true or false
4781 * Returns <code>true</code> if <em>ios</em> will be closed on exec.
4783 * f = open("/dev/null")
4784 * f.close_on_exec? #=> false
4785 * f.close_on_exec = true
4786 * f.close_on_exec? #=> true
4787 * f.close_on_exec = false
4788 * f.close_on_exec? #=> false
4792 rb_io_close_on_exec_p(VALUE io
)
4798 write_io
= GetWriteIO(io
);
4799 if (io
!= write_io
) {
4800 GetOpenFile(write_io
, fptr
);
4801 if (fptr
&& 0 <= (fd
= fptr
->fd
)) {
4802 if ((ret
= fcntl(fd
, F_GETFD
)) == -1) rb_sys_fail_path(fptr
->pathv
);
4803 if (!(ret
& FD_CLOEXEC
)) return Qfalse
;
4807 GetOpenFile(io
, fptr
);
4808 if (fptr
&& 0 <= (fd
= fptr
->fd
)) {
4809 if ((ret
= fcntl(fd
, F_GETFD
)) == -1) rb_sys_fail_path(fptr
->pathv
);
4810 if (!(ret
& FD_CLOEXEC
)) return Qfalse
;
4815 #define rb_io_close_on_exec_p rb_f_notimplement
4818 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
4821 * ios.close_on_exec = bool -> true or false
4823 * Sets a close-on-exec flag.
4825 * f = open("/dev/null")
4826 * f.close_on_exec = true
4827 * system("cat", "/proc/self/fd/#{f.fileno}") # cat: /proc/self/fd/3: No such file or directory
4828 * f.closed? #=> false
4830 * Ruby sets close-on-exec flags of all file descriptors by default
4832 * So you don't need to set by yourself.
4833 * Also, unsetting a close-on-exec flag can cause file descriptor leak
4834 * if another thread use fork() and exec() (via system() method for example).
4835 * If you really needs file descriptor inheritance to child process,
4836 * use spawn()'s argument such as fd=>fd.
4840 rb_io_set_close_on_exec(VALUE io
, VALUE arg
)
4842 int flag
= RTEST(arg
) ? FD_CLOEXEC
: 0;
4847 write_io
= GetWriteIO(io
);
4848 if (io
!= write_io
) {
4849 GetOpenFile(write_io
, fptr
);
4850 if (fptr
&& 0 <= (fd
= fptr
->fd
)) {
4851 if ((ret
= fcntl(fptr
->fd
, F_GETFD
)) == -1) rb_sys_fail_path(fptr
->pathv
);
4852 if ((ret
& FD_CLOEXEC
) != flag
) {
4853 ret
= (ret
& ~FD_CLOEXEC
) | flag
;
4854 ret
= fcntl(fd
, F_SETFD
, ret
);
4855 if (ret
!= 0) rb_sys_fail_path(fptr
->pathv
);
4861 GetOpenFile(io
, fptr
);
4862 if (fptr
&& 0 <= (fd
= fptr
->fd
)) {
4863 if ((ret
= fcntl(fd
, F_GETFD
)) == -1) rb_sys_fail_path(fptr
->pathv
);
4864 if ((ret
& FD_CLOEXEC
) != flag
) {
4865 ret
= (ret
& ~FD_CLOEXEC
) | flag
;
4866 ret
= fcntl(fd
, F_SETFD
, ret
);
4867 if (ret
!= 0) rb_sys_fail_path(fptr
->pathv
);
4873 #define rb_io_set_close_on_exec rb_f_notimplement
4876 #define IS_PREP_STDIO(f) ((f)->mode & FMODE_PREP)
4877 #define PREP_STDIO_NAME(f) (RSTRING_PTR((f)->pathv))
4880 finish_writeconv(rb_io_t
*fptr
, int noalloc
)
4882 unsigned char *ds
, *dp
, *de
;
4883 rb_econv_result_t res
;
4885 if (!fptr
->wbuf
.ptr
) {
4886 unsigned char buf
[1024];
4889 res
= econv_destination_buffer_full
;
4890 while (res
== econv_destination_buffer_full
) {
4892 de
= buf
+ sizeof(buf
);
4893 res
= rb_econv_convert(fptr
->writeconv
, NULL
, NULL
, &dp
, de
, 0);
4896 r
= rb_write_internal(fptr
, ds
, dp
-ds
);
4902 if (rb_io_maybe_wait_writable(errno
, fptr
->self
, Qnil
)) {
4904 return noalloc
? Qtrue
: rb_exc_new3(rb_eIOError
, rb_str_new_cstr(closed_stream
));
4907 return noalloc
? Qtrue
: INT2NUM(errno
);
4909 if (res
== econv_invalid_byte_sequence
||
4910 res
== econv_incomplete_input
||
4911 res
== econv_undefined_conversion
) {
4912 return noalloc
? Qtrue
: rb_econv_make_exception(fptr
->writeconv
);
4919 res
= econv_destination_buffer_full
;
4920 while (res
== econv_destination_buffer_full
) {
4921 if (fptr
->wbuf
.len
== fptr
->wbuf
.capa
) {
4922 if (io_fflush(fptr
) < 0)
4923 return noalloc
? Qtrue
: INT2NUM(errno
);
4926 ds
= dp
= (unsigned char *)fptr
->wbuf
.ptr
+ fptr
->wbuf
.off
+ fptr
->wbuf
.len
;
4927 de
= (unsigned char *)fptr
->wbuf
.ptr
+ fptr
->wbuf
.capa
;
4928 res
= rb_econv_convert(fptr
->writeconv
, NULL
, NULL
, &dp
, de
, 0);
4929 fptr
->wbuf
.len
+= (int)(dp
- ds
);
4930 if (res
== econv_invalid_byte_sequence
||
4931 res
== econv_incomplete_input
||
4932 res
== econv_undefined_conversion
) {
4933 return noalloc
? Qtrue
: rb_econv_make_exception(fptr
->writeconv
);
4939 struct finish_writeconv_arg
{
4945 finish_writeconv_sync(VALUE arg
)
4947 struct finish_writeconv_arg
*p
= (struct finish_writeconv_arg
*)arg
;
4948 return finish_writeconv(p
->fptr
, p
->noalloc
);
4952 nogvl_close(void *ptr
)
4956 return (void*)(intptr_t)close(*fd
);
4960 maygvl_close(int fd
, int keepgvl
)
4966 * close() may block for certain file types (NFS, SO_LINGER sockets,
4967 * inotify), so let other threads run.
4969 return (int)(intptr_t)rb_thread_call_without_gvl(nogvl_close
, &fd
, RUBY_UBF_IO
, 0);
4973 nogvl_fclose(void *ptr
)
4977 return (void*)(intptr_t)fclose(file
);
4981 maygvl_fclose(FILE *file
, int keepgvl
)
4984 return fclose(file
);
4986 return (int)(intptr_t)rb_thread_call_without_gvl(nogvl_fclose
, file
, RUBY_UBF_IO
, 0);
4989 static void free_io_buffer(rb_io_buffer_t
*buf
);
4990 static void clear_codeconv(rb_io_t
*fptr
);
4993 fptr_finalize_flush(rb_io_t
*fptr
, int noraise
, int keepgvl
,
4994 struct list_head
*busy
)
4998 FILE *stdio_file
= fptr
->stdio_file
;
4999 int mode
= fptr
->mode
;
5001 if (fptr
->writeconv
) {
5002 if (fptr
->write_lock
&& !noraise
) {
5003 struct finish_writeconv_arg arg
;
5005 arg
.noalloc
= noraise
;
5006 err
= rb_mutex_synchronize(fptr
->write_lock
, finish_writeconv_sync
, (VALUE
)&arg
);
5009 err
= finish_writeconv(fptr
, noraise
);
5012 if (fptr
->wbuf
.len
) {
5014 io_flush_buffer_sync(fptr
);
5017 if (io_fflush(fptr
) < 0 && NIL_P(err
))
5018 err
= INT2NUM(errno
);
5024 if (IS_PREP_STDIO(fptr
) || fd
<= 2) {
5025 // Need to keep FILE objects of stdin, stdout and stderr, so we are done:
5030 fptr
->stdio_file
= 0;
5031 fptr
->mode
&= ~(FMODE_READABLE
|FMODE_WRITABLE
);
5033 // Ensure waiting_fd users do not hit EBADF.
5035 // Wait for them to exit before we call close().
5036 do rb_thread_schedule(); while (!list_empty(busy
));
5040 // if (!done && fd >= 0) {
5041 // VALUE scheduler = rb_fiber_scheduler_current();
5042 // if (scheduler != Qnil) {
5043 // VALUE result = rb_fiber_scheduler_io_close(scheduler, fptr->self);
5044 // if (result != Qundef) done = 1;
5048 if (!done
&& stdio_file
) {
5049 // stdio_file is deallocated anyway even if fclose failed.
5050 if ((maygvl_fclose(stdio_file
, noraise
) < 0) && NIL_P(err
))
5051 if (!noraise
) err
= INT2NUM(errno
);
5056 if (!done
&& fd
>= 0) {
5057 // fptr->fd may be closed even if close fails. POSIX doesn't specify it.
5058 // We assumes it is closed.
5060 keepgvl
|= !(mode
& FMODE_WRITABLE
);
5062 if ((maygvl_close(fd
, keepgvl
) < 0) && NIL_P(err
))
5063 if (!noraise
) err
= INT2NUM(errno
);
5068 if (!NIL_P(err
) && !noraise
) {
5069 if (RB_INTEGER_TYPE_P(err
))
5070 rb_syserr_fail_path(NUM2INT(err
), fptr
->pathv
);
5077 fptr_finalize(rb_io_t
*fptr
, int noraise
)
5079 fptr_finalize_flush(fptr
, noraise
, FALSE
, 0);
5080 free_io_buffer(&fptr
->rbuf
);
5081 free_io_buffer(&fptr
->wbuf
);
5082 clear_codeconv(fptr
);
5086 rb_io_fptr_cleanup(rb_io_t
*fptr
, int noraise
)
5088 if (fptr
->finalize
) {
5089 (*fptr
->finalize
)(fptr
, noraise
);
5092 fptr_finalize(fptr
, noraise
);
5097 free_io_buffer(rb_io_buffer_t
*buf
)
5100 ruby_sized_xfree(buf
->ptr
, (size_t)buf
->capa
);
5106 clear_readconv(rb_io_t
*fptr
)
5108 if (fptr
->readconv
) {
5109 rb_econv_close(fptr
->readconv
);
5110 fptr
->readconv
= NULL
;
5112 free_io_buffer(&fptr
->cbuf
);
5116 clear_writeconv(rb_io_t
*fptr
)
5118 if (fptr
->writeconv
) {
5119 rb_econv_close(fptr
->writeconv
);
5120 fptr
->writeconv
= NULL
;
5122 fptr
->writeconv_initialized
= 0;
5126 clear_codeconv(rb_io_t
*fptr
)
5128 clear_readconv(fptr
);
5129 clear_writeconv(fptr
);
5133 rb_io_fptr_finalize_internal(void *ptr
)
5135 rb_io_t
*fptr
= ptr
;
5140 rb_io_fptr_cleanup(fptr
, TRUE
);
5141 fptr
->write_lock
= 0;
5142 free_io_buffer(&fptr
->rbuf
);
5143 free_io_buffer(&fptr
->wbuf
);
5144 clear_codeconv(fptr
);
5148 #undef rb_io_fptr_finalize
5150 rb_io_fptr_finalize(rb_io_t
*fptr
)
5156 rb_io_fptr_finalize_internal(fptr
);
5160 #define rb_io_fptr_finalize(fptr) rb_io_fptr_finalize_internal(fptr)
5162 RUBY_FUNC_EXPORTED
size_t
5163 rb_io_memsize(const rb_io_t
*fptr
)
5165 size_t size
= sizeof(rb_io_t
);
5166 size
+= fptr
->rbuf
.capa
;
5167 size
+= fptr
->wbuf
.capa
;
5168 size
+= fptr
->cbuf
.capa
;
5169 if (fptr
->readconv
) size
+= rb_econv_memsize(fptr
->readconv
);
5170 if (fptr
->writeconv
) size
+= rb_econv_memsize(fptr
->writeconv
);
5175 /* keep GVL while closing to prevent crash on Windows */
5176 # define KEEPGVL TRUE
5178 # define KEEPGVL FALSE
5181 int rb_notify_fd_close(int fd
, struct list_head
*);
5183 io_close_fptr(VALUE io
)
5187 rb_io_t
*write_fptr
;
5188 struct list_head busy
;
5190 list_head_init(&busy
);
5191 write_io
= GetWriteIO(io
);
5192 if (io
!= write_io
) {
5193 write_fptr
= RFILE(write_io
)->fptr
;
5194 if (write_fptr
&& 0 <= write_fptr
->fd
) {
5195 rb_io_fptr_cleanup(write_fptr
, TRUE
);
5199 fptr
= RFILE(io
)->fptr
;
5200 if (!fptr
) return 0;
5201 if (fptr
->fd
< 0) return 0;
5203 if (rb_notify_fd_close(fptr
->fd
, &busy
)) {
5204 /* calls close(fptr->fd): */
5205 fptr_finalize_flush(fptr
, FALSE
, KEEPGVL
, &busy
);
5207 rb_io_fptr_cleanup(fptr
, FALSE
);
5212 fptr_waitpid(rb_io_t
*fptr
, int nohang
)
5216 rb_last_status_clear();
5217 rb_waitpid(fptr
->pid
, &status
, nohang
? WNOHANG
: 0);
5223 rb_io_close(VALUE io
)
5225 rb_io_t
*fptr
= io_close_fptr(io
);
5226 if (fptr
) fptr_waitpid(fptr
, 0);
5234 * Closes <em>ios</em> and flushes any pending writes to the operating
5235 * system. The stream is unavailable for any further data operations;
5236 * an IOError is raised if such an attempt is made. I/O streams are
5237 * automatically closed when they are claimed by the garbage collector.
5239 * If <em>ios</em> is opened by IO.popen, #close sets
5242 * Calling this method on closed IO object is just ignored since Ruby 2.3.
5246 rb_io_close_m(VALUE io
)
5248 rb_io_t
*fptr
= rb_io_get_fptr(io
);
5257 io_call_close(VALUE io
)
5259 rb_check_funcall(io
, rb_intern("close"), 0, 0);
5264 ignore_closed_stream(VALUE io
, VALUE exc
)
5266 enum {mesg_len
= sizeof(closed_stream
)-1};
5267 VALUE mesg
= rb_attr_get(exc
, idMesg
);
5268 if (!RB_TYPE_P(mesg
, T_STRING
) ||
5269 RSTRING_LEN(mesg
) != mesg_len
||
5270 memcmp(RSTRING_PTR(mesg
), closed_stream
, mesg_len
)) {
5279 VALUE closed
= rb_check_funcall(io
, rb_intern("closed?"), 0, 0);
5280 if (closed
!= Qundef
&& RTEST(closed
)) return io
;
5281 rb_rescue2(io_call_close
, io
, ignore_closed_stream
, io
,
5282 rb_eIOError
, (VALUE
)0);
5288 * ios.closed? -> true or false
5290 * Returns <code>true</code> if <em>ios</em> is completely closed (for
5291 * duplex streams, both reader and writer), <code>false</code>
5294 * f = File.new("testfile")
5296 * f.closed? #=> true
5297 * f = IO.popen("/bin/sh","r+")
5298 * f.close_write #=> nil
5299 * f.closed? #=> false
5300 * f.close_read #=> nil
5301 * f.closed? #=> true
5306 rb_io_closed(VALUE io
)
5310 rb_io_t
*write_fptr
;
5312 write_io
= GetWriteIO(io
);
5313 if (io
!= write_io
) {
5314 write_fptr
= RFILE(write_io
)->fptr
;
5315 if (write_fptr
&& 0 <= write_fptr
->fd
) {
5320 fptr
= rb_io_get_fptr(io
);
5321 return RBOOL(0 > fptr
->fd
);
5326 * ios.close_read -> nil
5328 * Closes the read end of a duplex I/O stream (i.e., one that contains
5329 * both a read and a write stream, such as a pipe). Will raise an
5330 * IOError if the stream is not duplexed.
5332 * f = IO.popen("/bin/sh","r+")
5336 * <em>produces:</em>
5338 * prog.rb:3:in `readlines': not opened for reading (IOError)
5341 * Calling this method on closed IO object is just ignored since Ruby 2.3.
5345 rb_io_close_read(VALUE io
)
5350 fptr
= rb_io_get_fptr(rb_io_taint_check(io
));
5351 if (fptr
->fd
< 0) return Qnil
;
5352 if (is_socket(fptr
->fd
, fptr
->pathv
)) {
5356 if (shutdown(fptr
->fd
, SHUT_RD
) < 0)
5357 rb_sys_fail_path(fptr
->pathv
);
5358 fptr
->mode
&= ~FMODE_READABLE
;
5359 if (!(fptr
->mode
& FMODE_WRITABLE
))
5360 return rb_io_close(io
);
5364 write_io
= GetWriteIO(io
);
5365 if (io
!= write_io
) {
5367 wfptr
= rb_io_get_fptr(rb_io_taint_check(write_io
));
5368 wfptr
->pid
= fptr
->pid
;
5370 RFILE(io
)->fptr
= wfptr
;
5371 /* bind to write_io temporarily to get rid of memory/fd leak */
5372 fptr
->tied_io_for_writing
= 0;
5373 RFILE(write_io
)->fptr
= fptr
;
5374 rb_io_fptr_cleanup(fptr
, FALSE
);
5375 /* should not finalize fptr because another thread may be reading it */
5379 if ((fptr
->mode
& (FMODE_DUPLEX
|FMODE_WRITABLE
)) == FMODE_WRITABLE
) {
5380 rb_raise(rb_eIOError
, "closing non-duplex IO for reading");
5382 return rb_io_close(io
);
5387 * ios.close_write -> nil
5389 * Closes the write end of a duplex I/O stream (i.e., one that contains
5390 * both a read and a write stream, such as a pipe). Will raise an
5391 * IOError if the stream is not duplexed.
5393 * f = IO.popen("/bin/sh","r+")
5397 * <em>produces:</em>
5399 * prog.rb:3:in `write': not opened for writing (IOError)
5400 * from prog.rb:3:in `print'
5403 * Calling this method on closed IO object is just ignored since Ruby 2.3.
5407 rb_io_close_write(VALUE io
)
5412 write_io
= GetWriteIO(io
);
5413 fptr
= rb_io_get_fptr(rb_io_taint_check(write_io
));
5414 if (fptr
->fd
< 0) return Qnil
;
5415 if (is_socket(fptr
->fd
, fptr
->pathv
)) {
5419 if (shutdown(fptr
->fd
, SHUT_WR
) < 0)
5420 rb_sys_fail_path(fptr
->pathv
);
5421 fptr
->mode
&= ~FMODE_WRITABLE
;
5422 if (!(fptr
->mode
& FMODE_READABLE
))
5423 return rb_io_close(write_io
);
5427 if ((fptr
->mode
& (FMODE_DUPLEX
|FMODE_READABLE
)) == FMODE_READABLE
) {
5428 rb_raise(rb_eIOError
, "closing non-duplex IO for writing");
5431 if (io
!= write_io
) {
5432 fptr
= rb_io_get_fptr(rb_io_taint_check(io
));
5433 fptr
->tied_io_for_writing
= 0;
5435 rb_io_close(write_io
);
5441 * ios.sysseek(offset, whence=IO::SEEK_SET) -> integer
5443 * Seeks to a given <i>offset</i> in the stream according to the value
5444 * of <i>whence</i> (see IO#seek for values of <i>whence</i>). Returns
5445 * the new offset into the file.
5447 * f = File.new("testfile")
5448 * f.sysseek(-13, IO::SEEK_END) #=> 53
5449 * f.sysread(10) #=> "And so on."
5453 rb_io_sysseek(int argc
, VALUE
*argv
, VALUE io
)
5455 VALUE offset
, ptrname
;
5456 int whence
= SEEK_SET
;
5460 if (rb_scan_args(argc
, argv
, "11", &offset
, &ptrname
) == 2) {
5461 whence
= interpret_seek_whence(ptrname
);
5463 pos
= NUM2OFFT(offset
);
5464 GetOpenFile(io
, fptr
);
5465 if ((fptr
->mode
& FMODE_READABLE
) &&
5466 (READ_DATA_BUFFERED(fptr
) || READ_CHAR_PENDING(fptr
))) {
5467 rb_raise(rb_eIOError
, "sysseek for buffered IO");
5469 if ((fptr
->mode
& FMODE_WRITABLE
) && fptr
->wbuf
.len
) {
5470 rb_warn("sysseek for buffered IO");
5473 pos
= lseek(fptr
->fd
, pos
, whence
);
5474 if (pos
< 0 && errno
) rb_sys_fail_path(fptr
->pathv
);
5476 return OFFT2NUM(pos
);
5481 * ios.syswrite(string) -> integer
5483 * Writes the given string to <em>ios</em> using a low-level write.
5484 * Returns the number of bytes written. Do not mix with other methods
5485 * that write to <em>ios</em> or you may get unpredictable results.
5486 * Raises SystemCallError on error.
5488 * f = File.new("out", "w")
5489 * f.syswrite("ABCDEF") #=> 6
5493 rb_io_syswrite(VALUE io
, VALUE str
)
5500 if (!RB_TYPE_P(str
, T_STRING
))
5501 str
= rb_obj_as_string(str
);
5503 io
= GetWriteIO(io
);
5504 GetOpenFile(io
, fptr
);
5505 rb_io_check_writable(fptr
);
5507 if (fptr
->wbuf
.len
) {
5508 rb_warn("syswrite for buffered IO");
5511 tmp
= rb_str_tmp_frozen_acquire(str
);
5512 RSTRING_GETMEM(tmp
, ptr
, len
);
5513 n
= rb_write_internal(fptr
, ptr
, len
);
5514 if (n
< 0) rb_sys_fail_path(fptr
->pathv
);
5515 rb_str_tmp_frozen_release(str
, tmp
);
5522 * ios.sysread(maxlen[, outbuf]) -> string
5524 * Reads <i>maxlen</i> bytes from <em>ios</em> using a low-level
5525 * read and returns them as a string. Do not mix with other methods
5526 * that read from <em>ios</em> or you may get unpredictable results.
5528 * If the optional _outbuf_ argument is present,
5529 * it must reference a String, which will receive the data.
5530 * The _outbuf_ will contain only the received data after the method call
5531 * even if it is not empty at the beginning.
5533 * Raises SystemCallError on error and EOFError at end of file.
5535 * f = File.new("testfile")
5536 * f.sysread(16) #=> "This is line one"
5540 rb_io_sysread(int argc
, VALUE
*argv
, VALUE io
)
5545 struct io_internal_read_struct iis
;
5548 rb_scan_args(argc
, argv
, "11", &len
, &str
);
5549 ilen
= NUM2LONG(len
);
5551 shrinkable
= io_setstrbuf(&str
, ilen
);
5552 if (ilen
== 0) return str
;
5554 GetOpenFile(io
, fptr
);
5555 rb_io_check_byte_readable(fptr
);
5557 if (READ_DATA_BUFFERED(fptr
)) {
5558 rb_raise(rb_eIOError
, "sysread for buffered IO");
5561 rb_io_check_closed(fptr
);
5563 io_setstrbuf(&str
, ilen
);
5564 iis
.th
= rb_thread_current();
5567 iis
.buf
= RSTRING_PTR(str
);
5569 n
= read_internal_locktmp(str
, &iis
);
5572 rb_sys_fail_path(fptr
->pathv
);
5575 io_set_read_length(str
, n
, shrinkable
);
5577 if (n
== 0 && ilen
> 0) {
5584 #if defined(HAVE_PREAD) || defined(HAVE_PWRITE)
5585 struct prdwr_internal_arg
{
5591 #endif /* HAVE_PREAD || HAVE_PWRITE */
5593 #if defined(HAVE_PREAD)
5595 internal_pread_func(void *arg
)
5597 struct prdwr_internal_arg
*p
= arg
;
5598 return (VALUE
)pread(p
->fd
, p
->buf
, p
->count
, p
->offset
);
5602 pread_internal_call(VALUE arg
)
5604 struct prdwr_internal_arg
*p
= (struct prdwr_internal_arg
*)arg
;
5605 return rb_thread_io_blocking_region(internal_pread_func
, p
, p
->fd
);
5610 * ios.pread(maxlen, offset[, outbuf]) -> string
5612 * Reads <i>maxlen</i> bytes from <em>ios</em> using the pread system call
5613 * and returns them as a string without modifying the underlying
5614 * descriptor offset. This is advantageous compared to combining IO#seek
5615 * and IO#read in that it is atomic, allowing multiple threads/process to
5616 * share the same IO object for reading the file at various locations.
5617 * This bypasses any userspace buffering of the IO layer.
5618 * If the optional <i>outbuf</i> argument is present, it must
5619 * reference a String, which will receive the data.
5620 * Raises SystemCallError on error, EOFError at end of file and
5621 * NotImplementedError if platform does not implement the system call.
5623 * File.write("testfile", "This is line one\nThis is line two\n")
5624 * File.open("testfile") do |f|
5625 * p f.read # => "This is line one\nThis is line two\n"
5626 * p f.pread(12, 0) # => "This is line"
5627 * p f.pread(9, 8) # => "line one\n"
5631 rb_io_pread(int argc
, VALUE
*argv
, VALUE io
)
5633 VALUE len
, offset
, str
;
5636 struct prdwr_internal_arg arg
;
5639 rb_scan_args(argc
, argv
, "21", &len
, &offset
, &str
);
5640 arg
.count
= NUM2SIZET(len
);
5641 arg
.offset
= NUM2OFFT(offset
);
5643 shrinkable
= io_setstrbuf(&str
, (long)arg
.count
);
5644 if (arg
.count
== 0) return str
;
5645 arg
.buf
= RSTRING_PTR(str
);
5647 GetOpenFile(io
, fptr
);
5648 rb_io_check_byte_readable(fptr
);
5651 rb_io_check_closed(fptr
);
5653 rb_str_locktmp(str
);
5654 n
= (ssize_t
)rb_ensure(pread_internal_call
, (VALUE
)&arg
, rb_str_unlocktmp
, str
);
5657 rb_sys_fail_path(fptr
->pathv
);
5659 io_set_read_length(str
, n
, shrinkable
);
5660 if (n
== 0 && arg
.count
> 0) {
5667 # define rb_io_pread rb_f_notimplement
5668 #endif /* HAVE_PREAD */
5670 #if defined(HAVE_PWRITE)
5672 internal_pwrite_func(void *ptr
)
5674 struct prdwr_internal_arg
*arg
= ptr
;
5676 return (VALUE
)pwrite(arg
->fd
, arg
->buf
, arg
->count
, arg
->offset
);
5681 * ios.pwrite(string, offset) -> integer
5683 * Writes the given string to <em>ios</em> at <i>offset</i> using pwrite()
5684 * system call. This is advantageous to combining IO#seek and IO#write
5685 * in that it is atomic, allowing multiple threads/process to share the
5686 * same IO object for reading the file at various locations.
5687 * This bypasses any userspace buffering of the IO layer.
5688 * Returns the number of bytes written.
5689 * Raises SystemCallError on error and NotImplementedError
5690 * if platform does not implement the system call.
5692 * File.open("out", "w") do |f|
5693 * f.pwrite("ABCDEF", 3) #=> 6
5696 * File.read("out") #=> "\u0000\u0000\u0000ABCDEF"
5699 rb_io_pwrite(VALUE io
, VALUE str
, VALUE offset
)
5703 struct prdwr_internal_arg arg
;
5706 if (!RB_TYPE_P(str
, T_STRING
))
5707 str
= rb_obj_as_string(str
);
5709 arg
.offset
= NUM2OFFT(offset
);
5711 io
= GetWriteIO(io
);
5712 GetOpenFile(io
, fptr
);
5713 rb_io_check_writable(fptr
);
5716 tmp
= rb_str_tmp_frozen_acquire(str
);
5717 arg
.buf
= RSTRING_PTR(tmp
);
5718 arg
.count
= (size_t)RSTRING_LEN(tmp
);
5720 n
= (ssize_t
)rb_thread_io_blocking_region(internal_pwrite_func
, &arg
, fptr
->fd
);
5721 if (n
< 0) rb_sys_fail_path(fptr
->pathv
);
5722 rb_str_tmp_frozen_release(str
, tmp
);
5724 return SSIZET2NUM(n
);
5727 # define rb_io_pwrite rb_f_notimplement
5728 #endif /* HAVE_PWRITE */
5731 rb_io_binmode(VALUE io
)
5735 GetOpenFile(io
, fptr
);
5737 rb_econv_binmode(fptr
->readconv
);
5738 if (fptr
->writeconv
)
5739 rb_econv_binmode(fptr
->writeconv
);
5740 fptr
->mode
|= FMODE_BINMODE
;
5741 fptr
->mode
&= ~FMODE_TEXTMODE
;
5742 fptr
->writeconv_pre_ecflags
&= ~ECONV_NEWLINE_DECORATOR_MASK
;
5744 if (!fptr
->readconv
) {
5745 SET_BINARY_MODE_WITH_SEEK_CUR(fptr
);
5748 setmode(fptr
->fd
, O_BINARY
);
5755 io_ascii8bit_binmode(rb_io_t
*fptr
)
5757 if (fptr
->readconv
) {
5758 rb_econv_close(fptr
->readconv
);
5759 fptr
->readconv
= NULL
;
5761 if (fptr
->writeconv
) {
5762 rb_econv_close(fptr
->writeconv
);
5763 fptr
->writeconv
= NULL
;
5765 fptr
->mode
|= FMODE_BINMODE
;
5766 fptr
->mode
&= ~FMODE_TEXTMODE
;
5767 SET_BINARY_MODE_WITH_SEEK_CUR(fptr
);
5769 fptr
->encs
.enc
= rb_ascii8bit_encoding();
5770 fptr
->encs
.enc2
= NULL
;
5771 fptr
->encs
.ecflags
= 0;
5772 fptr
->encs
.ecopts
= Qnil
;
5773 clear_codeconv(fptr
);
5777 rb_io_ascii8bit_binmode(VALUE io
)
5781 GetOpenFile(io
, fptr
);
5782 io_ascii8bit_binmode(fptr
);
5789 * ios.binmode -> ios
5791 * Puts <em>ios</em> into binary mode.
5792 * Once a stream is in binary mode, it cannot be reset to nonbinary mode.
5794 * - newline conversion disabled
5795 * - encoding conversion disabled
5796 * - content is treated as ASCII-8BIT
5800 rb_io_binmode_m(VALUE io
)
5804 rb_io_ascii8bit_binmode(io
);
5806 write_io
= GetWriteIO(io
);
5808 rb_io_ascii8bit_binmode(write_io
);
5814 * ios.binmode? -> true or false
5816 * Returns <code>true</code> if <em>ios</em> is binmode.
5819 rb_io_binmode_p(VALUE io
)
5822 GetOpenFile(io
, fptr
);
5823 return RBOOL(fptr
->mode
& FMODE_BINMODE
);
5827 rb_io_fmode_modestr(int fmode
)
5829 if (fmode
& FMODE_APPEND
) {
5830 if ((fmode
& FMODE_READWRITE
) == FMODE_READWRITE
) {
5831 return MODE_BTMODE("a+", "ab+", "at+");
5833 return MODE_BTMODE("a", "ab", "at");
5835 switch (fmode
& FMODE_READWRITE
) {
5837 rb_raise(rb_eArgError
, "invalid access fmode 0x%x", fmode
);
5838 case FMODE_READABLE
:
5839 return MODE_BTMODE("r", "rb", "rt");
5840 case FMODE_WRITABLE
:
5841 return MODE_BTXMODE("w", "wb", "wt", "wx", "wbx", "wtx");
5842 case FMODE_READWRITE
:
5843 if (fmode
& FMODE_CREATE
) {
5844 return MODE_BTXMODE("w+", "wb+", "wt+", "w+x", "wb+x", "wt+x");
5846 return MODE_BTMODE("r+", "rb+", "rt+");
5850 static const char bom_prefix
[] = "bom|";
5851 static const char utf_prefix
[] = "utf-";
5852 enum {bom_prefix_len
= (int)sizeof(bom_prefix
) - 1};
5853 enum {utf_prefix_len
= (int)sizeof(utf_prefix
) - 1};
5856 io_encname_bom_p(const char *name
, long len
)
5858 return len
> bom_prefix_len
&& STRNCASECMP(name
, bom_prefix
, bom_prefix_len
) == 0;
5862 rb_io_modestr_fmode(const char *modestr
)
5865 const char *m
= modestr
, *p
= NULL
;
5869 fmode
|= FMODE_READABLE
;
5872 fmode
|= FMODE_WRITABLE
| FMODE_TRUNC
| FMODE_CREATE
;
5875 fmode
|= FMODE_WRITABLE
| FMODE_APPEND
| FMODE_CREATE
;
5884 fmode
|= FMODE_BINMODE
;
5887 fmode
|= FMODE_TEXTMODE
;
5890 fmode
|= FMODE_READWRITE
;
5893 if (modestr
[0] != 'w')
5895 fmode
|= FMODE_EXCL
;
5901 if (io_encname_bom_p(m
, p
? (long)(p
- m
) : (long)strlen(m
)))
5902 fmode
|= FMODE_SETENC_BY_BOM
;
5908 if ((fmode
& FMODE_BINMODE
) && (fmode
& FMODE_TEXTMODE
))
5914 rb_raise(rb_eArgError
, "invalid access mode %s", modestr
);
5915 UNREACHABLE_RETURN(Qundef
);
5919 rb_io_oflags_fmode(int oflags
)
5923 switch (oflags
& O_ACCMODE
) {
5925 fmode
= FMODE_READABLE
;
5928 fmode
= FMODE_WRITABLE
;
5931 fmode
= FMODE_READWRITE
;
5935 if (oflags
& O_APPEND
) {
5936 fmode
|= FMODE_APPEND
;
5938 if (oflags
& O_TRUNC
) {
5939 fmode
|= FMODE_TRUNC
;
5941 if (oflags
& O_CREAT
) {
5942 fmode
|= FMODE_CREATE
;
5944 if (oflags
& O_EXCL
) {
5945 fmode
|= FMODE_EXCL
;
5948 if (oflags
& O_BINARY
) {
5949 fmode
|= FMODE_BINMODE
;
5957 rb_io_fmode_oflags(int fmode
)
5961 switch (fmode
& FMODE_READWRITE
) {
5962 case FMODE_READABLE
:
5965 case FMODE_WRITABLE
:
5968 case FMODE_READWRITE
:
5973 if (fmode
& FMODE_APPEND
) {
5976 if (fmode
& FMODE_TRUNC
) {
5979 if (fmode
& FMODE_CREATE
) {
5982 if (fmode
& FMODE_EXCL
) {
5986 if (fmode
& FMODE_BINMODE
) {
5995 rb_io_modestr_oflags(const char *modestr
)
5997 return rb_io_fmode_oflags(rb_io_modestr_fmode(modestr
));
6001 rb_io_oflags_modestr(int oflags
)
6004 # define MODE_BINARY(a,b) ((oflags & O_BINARY) ? (b) : (a))
6006 # define MODE_BINARY(a,b) (a)
6009 if (oflags
& O_EXCL
) {
6010 rb_raise(rb_eArgError
, "exclusive access mode is not supported");
6012 accmode
= oflags
& (O_RDONLY
|O_WRONLY
|O_RDWR
);
6013 if (oflags
& O_APPEND
) {
6014 if (accmode
== O_WRONLY
) {
6015 return MODE_BINARY("a", "ab");
6017 if (accmode
== O_RDWR
) {
6018 return MODE_BINARY("a+", "ab+");
6023 rb_raise(rb_eArgError
, "invalid access oflags 0x%x", oflags
);
6025 return MODE_BINARY("r", "rb");
6027 return MODE_BINARY("w", "wb");
6029 if (oflags
& O_TRUNC
) {
6030 return MODE_BINARY("w+", "wb+");
6032 return MODE_BINARY("r+", "rb+");
6037 * Convert external/internal encodings to enc/enc2
6038 * NULL => use default encoding
6039 * Qnil => no encoding specified (internal only)
6042 rb_io_ext_int_to_encs(rb_encoding
*ext
, rb_encoding
*intern
, rb_encoding
**enc
, rb_encoding
**enc2
, int fmode
)
6044 int default_ext
= 0;
6047 ext
= rb_default_external_encoding();
6050 if (ext
== rb_ascii8bit_encoding()) {
6051 /* If external is ASCII-8BIT, no transcoding */
6054 else if (intern
== NULL
) {
6055 intern
= rb_default_internal_encoding();
6057 if (intern
== NULL
|| intern
== (rb_encoding
*)Qnil
||
6058 (!(fmode
& FMODE_SETENC_BY_BOM
) && (intern
== ext
))) {
6059 /* No internal encoding => use external + no transcoding */
6060 *enc
= (default_ext
&& intern
!= ext
) ? NULL
: ext
;
6070 unsupported_encoding(const char *name
, rb_encoding
*enc
)
6072 rb_enc_warn(enc
, "Unsupported encoding %s ignored", name
);
6076 parse_mode_enc(const char *estr
, rb_encoding
*estr_enc
,
6077 rb_encoding
**enc_p
, rb_encoding
**enc2_p
, int *fmode_p
)
6080 char encname
[ENCODING_MAXNAMELEN
+1];
6082 int fmode
= fmode_p
? *fmode_p
: 0;
6083 rb_encoding
*ext_enc
, *int_enc
;
6086 /* parse estr as "enc" or "enc2:enc" or "enc:-" */
6088 p
= strrchr(estr
, ':');
6089 len
= p
? (p
++ - estr
) : (long)strlen(estr
);
6090 if ((fmode
& FMODE_SETENC_BY_BOM
) || io_encname_bom_p(estr
, len
)) {
6091 estr
+= bom_prefix_len
;
6092 len
-= bom_prefix_len
;
6093 if (!STRNCASECMP(estr
, utf_prefix
, utf_prefix_len
)) {
6094 fmode
|= FMODE_SETENC_BY_BOM
;
6097 rb_enc_warn(estr_enc
, "BOM with non-UTF encoding %s is nonsense", estr
);
6098 fmode
&= ~FMODE_SETENC_BY_BOM
;
6101 if (len
== 0 || len
> ENCODING_MAXNAMELEN
) {
6106 memcpy(encname
, estr
, len
);
6107 encname
[len
] = '\0';
6110 idx
= rb_enc_find_index(estr
);
6112 if (fmode_p
) *fmode_p
= fmode
;
6115 ext_enc
= rb_enc_from_index(idx
);
6118 unsupported_encoding(estr
, estr_enc
);
6124 if (*p
== '-' && *(p
+1) == '\0') {
6125 /* Special case - "-" => no transcoding */
6126 int_enc
= (rb_encoding
*)Qnil
;
6129 idx2
= rb_enc_find_index(p
);
6131 unsupported_encoding(p
, estr_enc
);
6132 else if (!(fmode
& FMODE_SETENC_BY_BOM
) && (idx2
== idx
)) {
6133 int_enc
= (rb_encoding
*)Qnil
;
6136 int_enc
= rb_enc_from_index(idx2
);
6140 rb_io_ext_int_to_encs(ext_enc
, int_enc
, enc_p
, enc2_p
, fmode
);
6144 rb_io_extract_encoding_option(VALUE opt
, rb_encoding
**enc_p
, rb_encoding
**enc2_p
, int *fmode_p
)
6146 VALUE encoding
=Qnil
, extenc
=Qundef
, intenc
=Qundef
, tmp
;
6148 rb_encoding
*extencoding
= NULL
;
6149 rb_encoding
*intencoding
= NULL
;
6153 v
= rb_hash_lookup2(opt
, sym_encoding
, Qnil
);
6154 if (v
!= Qnil
) encoding
= v
;
6155 v
= rb_hash_lookup2(opt
, sym_extenc
, Qundef
);
6156 if (v
!= Qnil
) extenc
= v
;
6157 v
= rb_hash_lookup2(opt
, sym_intenc
, Qundef
);
6158 if (v
!= Qundef
) intenc
= v
;
6160 if ((extenc
!= Qundef
|| intenc
!= Qundef
) && !NIL_P(encoding
)) {
6161 if (!NIL_P(ruby_verbose
)) {
6162 int idx
= rb_to_encoding_index(encoding
);
6163 if (idx
>= 0) encoding
= rb_enc_from_encoding(rb_enc_from_index(idx
));
6164 rb_warn("Ignoring encoding parameter '%"PRIsVALUE
"': %s_encoding is used",
6165 encoding
, extenc
== Qundef
? "internal" : "external");
6169 if (extenc
!= Qundef
&& !NIL_P(extenc
)) {
6170 extencoding
= rb_to_encoding(extenc
);
6172 if (intenc
!= Qundef
) {
6173 if (NIL_P(intenc
)) {
6174 /* internal_encoding: nil => no transcoding */
6175 intencoding
= (rb_encoding
*)Qnil
;
6177 else if (!NIL_P(tmp
= rb_check_string_type(intenc
))) {
6178 char *p
= StringValueCStr(tmp
);
6180 if (*p
== '-' && *(p
+1) == '\0') {
6181 /* Special case - "-" => no transcoding */
6182 intencoding
= (rb_encoding
*)Qnil
;
6185 intencoding
= rb_to_encoding(intenc
);
6189 intencoding
= rb_to_encoding(intenc
);
6191 if (extencoding
== intencoding
) {
6192 intencoding
= (rb_encoding
*)Qnil
;
6195 if (!NIL_P(encoding
)) {
6197 if (!NIL_P(tmp
= rb_check_string_type(encoding
))) {
6198 parse_mode_enc(StringValueCStr(tmp
), rb_enc_get(tmp
),
6199 enc_p
, enc2_p
, fmode_p
);
6202 rb_io_ext_int_to_encs(rb_to_encoding(encoding
), NULL
, enc_p
, enc2_p
, 0);
6205 else if (extenc
!= Qundef
|| intenc
!= Qundef
) {
6207 rb_io_ext_int_to_encs(extencoding
, intencoding
, enc_p
, enc2_p
, 0);
6212 typedef struct rb_io_enc_t convconfig_t
;
6215 validate_enc_binmode(int *fmode_p
, int ecflags
, rb_encoding
*enc
, rb_encoding
*enc2
)
6217 int fmode
= *fmode_p
;
6219 if ((fmode
& FMODE_READABLE
) &&
6221 !(fmode
& FMODE_BINMODE
) &&
6222 !rb_enc_asciicompat(enc
? enc
: rb_default_external_encoding()))
6223 rb_raise(rb_eArgError
, "ASCII incompatible encoding needs binmode");
6225 if ((fmode
& FMODE_BINMODE
) && (ecflags
& ECONV_NEWLINE_DECORATOR_MASK
)) {
6226 rb_raise(rb_eArgError
, "newline decorator with binary mode");
6228 if (!(fmode
& FMODE_BINMODE
) &&
6229 (DEFAULT_TEXTMODE
|| (ecflags
& ECONV_NEWLINE_DECORATOR_MASK
))) {
6230 fmode
|= FMODE_TEXTMODE
;
6233 #if !DEFAULT_TEXTMODE
6234 else if (!(ecflags
& ECONV_NEWLINE_DECORATOR_MASK
)) {
6235 fmode
&= ~FMODE_TEXTMODE
;
6242 extract_binmode(VALUE opthash
, int *fmode
)
6244 if (!NIL_P(opthash
)) {
6246 v
= rb_hash_aref(opthash
, sym_textmode
);
6248 if (*fmode
& FMODE_TEXTMODE
)
6249 rb_raise(rb_eArgError
, "textmode specified twice");
6250 if (*fmode
& FMODE_BINMODE
)
6251 rb_raise(rb_eArgError
, "both textmode and binmode specified");
6253 *fmode
|= FMODE_TEXTMODE
;
6255 v
= rb_hash_aref(opthash
, sym_binmode
);
6257 if (*fmode
& FMODE_BINMODE
)
6258 rb_raise(rb_eArgError
, "binmode specified twice");
6259 if (*fmode
& FMODE_TEXTMODE
)
6260 rb_raise(rb_eArgError
, "both textmode and binmode specified");
6262 *fmode
|= FMODE_BINMODE
;
6265 if ((*fmode
& FMODE_BINMODE
) && (*fmode
& FMODE_TEXTMODE
))
6266 rb_raise(rb_eArgError
, "both textmode and binmode specified");
6271 rb_io_extract_modeenc(VALUE
*vmode_p
, VALUE
*vperm_p
, VALUE opthash
,
6272 int *oflags_p
, int *fmode_p
, convconfig_t
*convconfig_p
)
6276 rb_encoding
*enc
, *enc2
;
6279 int has_enc
= 0, has_vmode
= 0;
6284 /* Set to defaults */
6285 rb_io_ext_int_to_encs(NULL
, NULL
, &enc
, &enc2
, 0);
6289 fmode
= FMODE_READABLE
;
6292 else if (!NIL_P(intmode
= rb_check_to_integer(vmode
, "to_int"))) {
6294 oflags
= NUM2INT(intmode
);
6295 fmode
= rb_io_oflags_fmode(oflags
);
6300 SafeStringValue(vmode
);
6301 p
= StringValueCStr(vmode
);
6302 fmode
= rb_io_modestr_fmode(p
);
6303 oflags
= rb_io_fmode_oflags(fmode
);
6307 parse_mode_enc(p
+1, rb_enc_get(vmode
), &enc
, &enc2
, &fmode
);
6312 e
= (fmode
& FMODE_BINMODE
) ? rb_ascii8bit_encoding() : NULL
;
6313 rb_io_ext_int_to_encs(e
, NULL
, &enc
, &enc2
, fmode
);
6317 if (NIL_P(opthash
)) {
6318 ecflags
= (fmode
& FMODE_READABLE
) ?
6319 MODE_BTMODE(ECONV_DEFAULT_NEWLINE_DECORATOR
,
6320 0, ECONV_UNIVERSAL_NEWLINE_DECORATOR
) : 0;
6321 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
6322 ecflags
|= (fmode
& FMODE_WRITABLE
) ?
6323 MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
,
6324 0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
) : 0;
6326 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2
, ecflags
);
6328 if (fmode
& FMODE_BINMODE
) {
6333 rb_io_ext_int_to_encs(rb_ascii8bit_encoding(), NULL
, &enc
, &enc2
, fmode
);
6335 #if DEFAULT_TEXTMODE
6336 else if (NIL_P(vmode
)) {
6337 fmode
|= DEFAULT_TEXTMODE
;
6344 v
= rb_hash_aref(opthash
, sym_mode
);
6346 if (!NIL_P(vmode
)) {
6347 rb_raise(rb_eArgError
, "mode specified twice");
6354 v
= rb_hash_aref(opthash
, sym_flags
);
6357 oflags
|= NUM2INT(v
);
6358 vmode
= INT2NUM(oflags
);
6359 fmode
= rb_io_oflags_fmode(oflags
);
6361 extract_binmode(opthash
, &fmode
);
6362 if (fmode
& FMODE_BINMODE
) {
6367 rb_io_ext_int_to_encs(rb_ascii8bit_encoding(), NULL
, &enc
, &enc2
, fmode
);
6369 #if DEFAULT_TEXTMODE
6370 else if (NIL_P(vmode
)) {
6371 fmode
|= DEFAULT_TEXTMODE
;
6374 v
= rb_hash_aref(opthash
, sym_perm
);
6377 if (!NIL_P(*vperm_p
)) {
6378 rb_raise(rb_eArgError
, "perm specified twice");
6383 /* perm no use, just ignore */
6386 ecflags
= (fmode
& FMODE_READABLE
) ?
6387 MODE_BTMODE(ECONV_DEFAULT_NEWLINE_DECORATOR
,
6388 0, ECONV_UNIVERSAL_NEWLINE_DECORATOR
) : 0;
6389 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
6390 ecflags
|= (fmode
& FMODE_WRITABLE
) ?
6391 MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
,
6392 0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
) : 0;
6395 if (rb_io_extract_encoding_option(opthash
, &enc
, &enc2
, &fmode
)) {
6397 rb_raise(rb_eArgError
, "encoding specified twice");
6400 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2
, ecflags
);
6401 ecflags
= rb_econv_prepare_options(opthash
, &ecopts
, ecflags
);
6404 validate_enc_binmode(&fmode
, ecflags
, enc
, enc2
);
6410 convconfig_p
->enc
= enc
;
6411 convconfig_p
->enc2
= enc2
;
6412 convconfig_p
->ecflags
= ecflags
;
6413 convconfig_p
->ecopts
= ecopts
;
6416 struct sysopen_struct
{
6423 sysopen_func(void *ptr
)
6425 const struct sysopen_struct
*data
= ptr
;
6426 const char *fname
= RSTRING_PTR(data
->fname
);
6427 return (void *)(VALUE
)rb_cloexec_open(fname
, data
->oflags
, data
->perm
);
6431 rb_sysopen_internal(struct sysopen_struct
*data
)
6434 fd
= (int)(VALUE
)rb_thread_call_without_gvl(sysopen_func
, data
, RUBY_UBF_IO
, 0);
6436 rb_update_max_fd(fd
);
6441 rb_sysopen(VALUE fname
, int oflags
, mode_t perm
)
6444 struct sysopen_struct data
;
6446 data
.fname
= rb_str_encode_ospath(fname
);
6447 StringValueCStr(data
.fname
);
6448 data
.oflags
= oflags
;
6451 fd
= rb_sysopen_internal(&data
);
6454 if (rb_gc_for_fd(e
)) {
6455 fd
= rb_sysopen_internal(&data
);
6458 rb_syserr_fail_path(e
, fname
);
6465 rb_fdopen(int fd
, const char *modestr
)
6472 file
= fdopen(fd
, modestr
);
6479 file
= fdopen(fd
, modestr
);
6483 if (rb_gc_for_fd(e
)) {
6484 file
= fdopen(fd
, modestr
);
6488 if (e
== 0) e
= EINVAL
;
6489 #elif defined(__sun)
6490 if (e
== 0) e
= EMFILE
;
6492 rb_syserr_fail(e
, 0);
6496 /* xxx: should be _IONBF? A buffer in FILE may have trouble. */
6498 if (setvbuf(file
, NULL
, _IOFBF
, 0) != 0)
6499 rb_warn("setvbuf() can't be honoured (fd=%d)", fd
);
6505 io_check_tty(rb_io_t
*fptr
)
6507 int t
= isatty(fptr
->fd
);
6509 fptr
->mode
|= FMODE_TTY
|FMODE_DUPLEX
;
6513 static VALUE
rb_io_internal_encoding(VALUE
);
6514 static void io_encoding_set(rb_io_t
*, VALUE
, VALUE
, VALUE
);
6517 io_strip_bom(VALUE io
)
6519 VALUE b1
, b2
, b3
, b4
;
6522 GetOpenFile(io
, fptr
);
6523 if (!(fptr
->mode
& FMODE_READABLE
)) return 0;
6524 if (NIL_P(b1
= rb_io_getbyte(io
))) return 0;
6527 if (NIL_P(b2
= rb_io_getbyte(io
))) break;
6528 if (b2
== INT2FIX(0xBB) && !NIL_P(b3
= rb_io_getbyte(io
))) {
6529 if (b3
== INT2FIX(0xBF)) {
6530 return rb_utf8_encindex();
6532 rb_io_ungetbyte(io
, b3
);
6534 rb_io_ungetbyte(io
, b2
);
6538 if (NIL_P(b2
= rb_io_getbyte(io
))) break;
6539 if (b2
== INT2FIX(0xFF)) {
6540 return ENCINDEX_UTF_16BE
;
6542 rb_io_ungetbyte(io
, b2
);
6546 if (NIL_P(b2
= rb_io_getbyte(io
))) break;
6547 if (b2
== INT2FIX(0xFE)) {
6548 b3
= rb_io_getbyte(io
);
6549 if (b3
== INT2FIX(0) && !NIL_P(b4
= rb_io_getbyte(io
))) {
6550 if (b4
== INT2FIX(0)) {
6551 return ENCINDEX_UTF_32LE
;
6553 rb_io_ungetbyte(io
, b4
);
6555 rb_io_ungetbyte(io
, b3
);
6556 return ENCINDEX_UTF_16LE
;
6558 rb_io_ungetbyte(io
, b2
);
6562 if (NIL_P(b2
= rb_io_getbyte(io
))) break;
6563 if (b2
== INT2FIX(0) && !NIL_P(b3
= rb_io_getbyte(io
))) {
6564 if (b3
== INT2FIX(0xFE) && !NIL_P(b4
= rb_io_getbyte(io
))) {
6565 if (b4
== INT2FIX(0xFF)) {
6566 return ENCINDEX_UTF_32BE
;
6568 rb_io_ungetbyte(io
, b4
);
6570 rb_io_ungetbyte(io
, b3
);
6572 rb_io_ungetbyte(io
, b2
);
6575 rb_io_ungetbyte(io
, b1
);
6579 static rb_encoding
*
6580 io_set_encoding_by_bom(VALUE io
)
6582 int idx
= io_strip_bom(io
);
6584 rb_encoding
*extenc
= NULL
;
6586 GetOpenFile(io
, fptr
);
6588 extenc
= rb_enc_from_index(idx
);
6589 io_encoding_set(fptr
, rb_enc_from_encoding(extenc
),
6590 rb_io_internal_encoding(io
), Qnil
);
6593 fptr
->encs
.enc2
= NULL
;
6599 rb_file_open_generic(VALUE io
, VALUE filename
, int oflags
, int fmode
,
6600 const convconfig_t
*convconfig
, mode_t perm
)
6606 /* Set to default encodings */
6607 rb_io_ext_int_to_encs(NULL
, NULL
, &cc
.enc
, &cc
.enc2
, fmode
);
6612 validate_enc_binmode(&fmode
, convconfig
->ecflags
,
6613 convconfig
->enc
, convconfig
->enc2
);
6615 MakeOpenFile(io
, fptr
);
6617 fptr
->encs
= *convconfig
;
6618 pathv
= rb_str_new_frozen(filename
);
6620 if (!(oflags
& O_TMPFILE
)) {
6621 fptr
->pathv
= pathv
;
6624 fptr
->pathv
= pathv
;
6626 fptr
->fd
= rb_sysopen(pathv
, oflags
, perm
);
6628 if (fmode
& FMODE_SETENC_BY_BOM
) io_set_encoding_by_bom(io
);
6634 rb_file_open_internal(VALUE io
, VALUE filename
, const char *modestr
)
6636 int fmode
= rb_io_modestr_fmode(modestr
);
6637 const char *p
= strchr(modestr
, ':');
6638 convconfig_t convconfig
;
6641 parse_mode_enc(p
+1, rb_usascii_encoding(),
6642 &convconfig
.enc
, &convconfig
.enc2
, &fmode
);
6643 convconfig
.ecflags
= 0;
6644 convconfig
.ecopts
= Qnil
;
6648 /* Set to default encodings */
6650 e
= (fmode
& FMODE_BINMODE
) ? rb_ascii8bit_encoding() : NULL
;
6651 rb_io_ext_int_to_encs(e
, NULL
, &convconfig
.enc
, &convconfig
.enc2
, fmode
);
6652 convconfig
.ecflags
= 0;
6653 convconfig
.ecopts
= Qnil
;
6656 return rb_file_open_generic(io
, filename
,
6657 rb_io_fmode_oflags(fmode
),
6664 rb_file_open_str(VALUE fname
, const char *modestr
)
6666 FilePathValue(fname
);
6667 return rb_file_open_internal(io_alloc(rb_cFile
), fname
, modestr
);
6671 rb_file_open(const char *fname
, const char *modestr
)
6673 return rb_file_open_internal(io_alloc(rb_cFile
), rb_str_new_cstr(fname
), modestr
);
6676 #if defined(__CYGWIN__) || !defined(HAVE_WORKING_FORK)
6677 static struct pipe_list
{
6679 struct pipe_list
*next
;
6683 pipe_add_fptr(rb_io_t
*fptr
)
6685 struct pipe_list
*list
;
6687 list
= ALLOC(struct pipe_list
);
6689 list
->next
= pipe_list
;
6694 pipe_del_fptr(rb_io_t
*fptr
)
6696 struct pipe_list
**prev
= &pipe_list
;
6697 struct pipe_list
*tmp
;
6699 while ((tmp
= *prev
) != 0) {
6700 if (tmp
->fptr
== fptr
) {
6709 #if defined (_WIN32) || defined(__CYGWIN__)
6713 struct pipe_list
*list
= pipe_list
;
6714 struct pipe_list
*tmp
;
6718 rb_io_fptr_finalize(list
->fptr
);
6725 pipe_finalize(rb_io_t
*fptr
, int noraise
)
6727 #if !defined(HAVE_WORKING_FORK) && !defined(_WIN32)
6729 if (fptr
->stdio_file
) {
6730 status
= pclose(fptr
->stdio_file
);
6733 fptr
->stdio_file
= 0;
6734 rb_last_status_set(status
, fptr
->pid
);
6736 fptr_finalize(fptr
, noraise
);
6738 pipe_del_fptr(fptr
);
6743 fptr_copy_finalizer(rb_io_t
*fptr
, const rb_io_t
*orig
)
6745 #if defined(__CYGWIN__) || !defined(HAVE_WORKING_FORK)
6746 void (*const old_finalize
)(struct rb_io_t
*,int) = fptr
->finalize
;
6748 if (old_finalize
== orig
->finalize
) return;
6751 fptr
->finalize
= orig
->finalize
;
6753 #if defined(__CYGWIN__) || !defined(HAVE_WORKING_FORK)
6754 if (old_finalize
!= pipe_finalize
) {
6755 struct pipe_list
*list
;
6756 for (list
= pipe_list
; list
; list
= list
->next
) {
6757 if (list
->fptr
== fptr
) break;
6759 if (!list
) pipe_add_fptr(fptr
);
6762 pipe_del_fptr(fptr
);
6768 rb_io_synchronized(rb_io_t
*fptr
)
6770 rb_io_check_initialized(fptr
);
6771 fptr
->mode
|= FMODE_SYNC
;
6775 rb_io_unbuffered(rb_io_t
*fptr
)
6777 rb_io_synchronized(fptr
);
6784 ret
= rb_cloexec_pipe(pipes
);
6786 if (rb_gc_for_fd(errno
)) {
6787 ret
= rb_cloexec_pipe(pipes
);
6791 rb_update_max_fd(pipes
[0]);
6792 rb_update_max_fd(pipes
[1]);
6798 #define HAVE_SPAWNV 1
6799 #define spawnv(mode, cmd, args) rb_w32_uaspawn((mode), (cmd), (args))
6800 #define spawn(mode, cmd) rb_w32_uspawn((mode), (cmd), 0)
6803 #if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
6806 struct rb_execarg
*eargp
;
6813 #ifdef HAVE_WORKING_FORK
6814 # ifndef __EMSCRIPTEN__
6816 popen_redirect(struct popen_arg
*p
)
6818 if ((p
->modef
& FMODE_READABLE
) && (p
->modef
& FMODE_WRITABLE
)) {
6819 close(p
->write_pair
[1]);
6820 if (p
->write_pair
[0] != 0) {
6821 dup2(p
->write_pair
[0], 0);
6822 close(p
->write_pair
[0]);
6825 if (p
->pair
[1] != 1) {
6826 dup2(p
->pair
[1], 1);
6830 else if (p
->modef
& FMODE_READABLE
) {
6832 if (p
->pair
[1] != 1) {
6833 dup2(p
->pair
[1], 1);
6839 if (p
->pair
[0] != 0) {
6840 dup2(p
->pair
[0], 0);
6847 #if defined(__linux__)
6848 /* Linux /proc/self/status contains a line: "FDSize:\t<nnn>\n"
6849 * Since /proc may not be available, linux_get_maxfd is just a hint.
6850 * This function, linux_get_maxfd, must be async-signal-safe.
6851 * I.e. opendir() is not usable.
6853 * Note that memchr() and memcmp is *not* async-signal-safe in POSIX.
6854 * However they are easy to re-implement in async-signal-safe manner.
6855 * (Also note that there is missing/memcmp.c.)
6858 linux_get_maxfd(void)
6861 char buf
[4096], *p
, *np
, *e
;
6863 fd
= rb_cloexec_open("/proc/self/status", O_RDONLY
|O_NOCTTY
, 0);
6864 if (fd
< 0) return fd
;
6865 ss
= read(fd
, buf
, sizeof(buf
));
6866 if (ss
< 0) goto err
;
6869 while ((int)sizeof("FDSize:\t0\n")-1 <= e
-p
&&
6870 (np
= memchr(p
, '\n', e
-p
)) != NULL
) {
6871 if (memcmp(p
, "FDSize:", sizeof("FDSize:")-1) == 0) {
6873 p
+= sizeof("FDSize:")-1;
6875 fdsize
= (int)ruby_strtoul(p
, (char **)NULL
, 10);
6889 /* This function should be async-signal-safe. */
6891 rb_close_before_exec(int lowfd
, int maxhint
, VALUE noclose_fds
)
6893 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
6895 int max
= (int)max_file_descriptor
;
6897 /* F_MAXFD is available since NetBSD 2.0. */
6898 ret
= fcntl(0, F_MAXFD
); /* async-signal-safe */
6900 maxhint
= max
= ret
;
6901 # elif defined(__linux__)
6902 ret
= linux_get_maxfd();
6905 /* maxhint = max = ret; if (ret == -1) abort(); // test */
6909 for (fd
= lowfd
; fd
<= max
; fd
++) {
6910 if (!NIL_P(noclose_fds
) &&
6911 RTEST(rb_hash_lookup(noclose_fds
, INT2FIX(fd
)))) /* async-signal-safe */
6913 ret
= fcntl(fd
, F_GETFD
); /* async-signal-safe */
6914 if (ret
!= -1 && !(ret
& FD_CLOEXEC
)) {
6915 fcntl(fd
, F_SETFD
, ret
|FD_CLOEXEC
); /* async-signal-safe */
6917 # define CONTIGUOUS_CLOSED_FDS 20
6919 if (max
< fd
+ CONTIGUOUS_CLOSED_FDS
)
6920 max
= fd
+ CONTIGUOUS_CLOSED_FDS
;
6926 # ifndef __EMSCRIPTEN__
6928 popen_exec(void *pp
, char *errmsg
, size_t errmsg_len
)
6930 struct popen_arg
*p
= (struct popen_arg
*)pp
;
6932 return rb_exec_async_signal_safe(p
->eargp
, errmsg
, errmsg_len
);
6937 #if (defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)) && !defined __EMSCRIPTEN__
6939 rb_execarg_fixup_v(VALUE execarg_obj
)
6941 rb_execarg_parent_start(execarg_obj
);
6945 char *rb_execarg_commandline(const struct rb_execarg
*eargp
, VALUE
*prog
);
6948 #ifndef __EMSCRIPTEN__
6950 pipe_open(VALUE execarg_obj
, const char *modestr
, int fmode
,
6951 const convconfig_t
*convconfig
)
6953 struct rb_execarg
*eargp
= NIL_P(execarg_obj
) ? NULL
: rb_execarg_get(execarg_obj
);
6954 VALUE prog
= eargp
? (eargp
->use_shell
? eargp
->invoke
.sh
.shell_script
: eargp
->invoke
.cmd
.command_name
) : Qfalse
;
6958 rb_io_t
*write_fptr
;
6960 #if defined(HAVE_WORKING_FORK)
6962 char errmsg
[80] = { '\0' };
6964 #if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
6966 struct popen_arg arg
;
6969 #if defined(HAVE_SPAWNV)
6970 # if defined(HAVE_SPAWNVE)
6971 # define DO_SPAWN(cmd, args, envp) ((args) ? \
6972 spawnve(P_NOWAIT, (cmd), (args), (envp)) : \
6973 spawne(P_NOWAIT, (cmd), (envp)))
6975 # define DO_SPAWN(cmd, args, envp) ((args) ? \
6976 spawnv(P_NOWAIT, (cmd), (args)) : \
6977 spawn(P_NOWAIT, (cmd)))
6979 # if !defined(HAVE_WORKING_FORK)
6981 # if defined(HAVE_SPAWNVE)
6986 #if !defined(HAVE_WORKING_FORK)
6987 struct rb_execarg sarg
, *sargp
= &sarg
;
6992 #if !defined(HAVE_WORKING_FORK)
6993 const char *cmd
= 0;
6996 cmd
= StringValueCStr(prog
);
6999 #if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
7000 arg
.execarg_obj
= execarg_obj
;
7003 arg
.pair
[0] = arg
.pair
[1] = -1;
7004 arg
.write_pair
[0] = arg
.write_pair
[1] = -1;
7005 # if !defined(HAVE_WORKING_FORK)
7006 if (eargp
&& !eargp
->use_shell
) {
7007 args
= ARGVSTR2ARGV(eargp
->invoke
.cmd
.argv_str
);
7010 switch (fmode
& (FMODE_READABLE
|FMODE_WRITABLE
)) {
7011 case FMODE_READABLE
|FMODE_WRITABLE
:
7012 if (rb_pipe(arg
.write_pair
) < 0)
7013 rb_sys_fail_str(prog
);
7014 if (rb_pipe(arg
.pair
) < 0) {
7016 close(arg
.write_pair
[0]);
7017 close(arg
.write_pair
[1]);
7018 rb_syserr_fail_str(e
, prog
);
7021 rb_execarg_addopt(execarg_obj
, INT2FIX(0), INT2FIX(arg
.write_pair
[0]));
7022 rb_execarg_addopt(execarg_obj
, INT2FIX(1), INT2FIX(arg
.pair
[1]));
7025 case FMODE_READABLE
:
7026 if (rb_pipe(arg
.pair
) < 0)
7027 rb_sys_fail_str(prog
);
7029 rb_execarg_addopt(execarg_obj
, INT2FIX(1), INT2FIX(arg
.pair
[1]));
7031 case FMODE_WRITABLE
:
7032 if (rb_pipe(arg
.pair
) < 0)
7033 rb_sys_fail_str(prog
);
7035 rb_execarg_addopt(execarg_obj
, INT2FIX(0), INT2FIX(arg
.pair
[0]));
7038 rb_sys_fail_str(prog
);
7040 if (!NIL_P(execarg_obj
)) {
7041 rb_protect(rb_execarg_fixup_v
, execarg_obj
, &state
);
7043 if (0 <= arg
.write_pair
[0]) close(arg
.write_pair
[0]);
7044 if (0 <= arg
.write_pair
[1]) close(arg
.write_pair
[1]);
7045 if (0 <= arg
.pair
[0]) close(arg
.pair
[0]);
7046 if (0 <= arg
.pair
[1]) close(arg
.pair
[1]);
7047 rb_execarg_parent_end(execarg_obj
);
7051 # if defined(HAVE_WORKING_FORK)
7052 pid
= rb_fork_async_signal_safe(&status
, popen_exec
, &arg
, arg
.eargp
->redirect_fds
, errmsg
, sizeof(errmsg
));
7054 rb_execarg_run_options(eargp
, sargp
, NULL
, 0);
7055 # if defined(HAVE_SPAWNVE)
7056 if (eargp
->envp_str
) envp
= (char **)RSTRING_PTR(eargp
->envp_str
);
7058 while ((pid
= DO_SPAWN(cmd
, args
, envp
)) < 0) {
7060 switch (e
= errno
) {
7062 # if EWOULDBLOCK != EAGAIN
7071 rb_execarg_run_options(sargp
, NULL
, NULL
, 0);
7073 rb_execarg_parent_end(execarg_obj
);
7076 # if defined(HAVE_WORKING_FORK)
7077 pid
= rb_call_proc__fork();
7078 if (pid
== 0) { /* child */
7079 popen_redirect(&arg
);
7080 rb_io_synchronized(RFILE(orig_stdout
)->fptr
);
7081 rb_io_synchronized(RFILE(orig_stderr
)->fptr
);
7091 # if defined(HAVE_WORKING_FORK)
7096 if ((fmode
& (FMODE_READABLE
|FMODE_WRITABLE
)) == (FMODE_READABLE
|FMODE_WRITABLE
)) {
7097 close(arg
.write_pair
[0]);
7098 close(arg
.write_pair
[1]);
7100 # if defined(HAVE_WORKING_FORK)
7102 rb_syserr_fail(e
, errmsg
);
7104 rb_syserr_fail_str(e
, prog
);
7106 if ((fmode
& FMODE_READABLE
) && (fmode
& FMODE_WRITABLE
)) {
7109 close(arg
.write_pair
[0]);
7110 write_fd
= arg
.write_pair
[1];
7112 else if (fmode
& FMODE_READABLE
) {
7121 cmd
= rb_execarg_commandline(eargp
, &prog
);
7122 if (!NIL_P(execarg_obj
)) {
7123 rb_execarg_parent_start(execarg_obj
);
7124 rb_execarg_run_options(eargp
, sargp
, NULL
, 0);
7126 fp
= popen(cmd
, modestr
);
7129 rb_execarg_parent_end(execarg_obj
);
7130 rb_execarg_run_options(sargp
, NULL
, NULL
, 0);
7132 if (!fp
) rb_syserr_fail_path(e
, prog
);
7136 port
= io_alloc(rb_cIO
);
7137 MakeOpenFile(port
, fptr
);
7139 fptr
->stdio_file
= fp
;
7140 fptr
->mode
= fmode
| FMODE_SYNC
|FMODE_DUPLEX
;
7142 fptr
->encs
= *convconfig
;
7143 #if RUBY_CRLF_ENVIRONMENT
7144 if (fptr
->encs
.ecflags
& ECONV_DEFAULT_NEWLINE_DECORATOR
) {
7145 fptr
->encs
.ecflags
|= ECONV_UNIVERSAL_NEWLINE_DECORATOR
;
7150 if (NEED_NEWLINE_DECORATOR_ON_READ(fptr
)) {
7151 fptr
->encs
.ecflags
|= ECONV_UNIVERSAL_NEWLINE_DECORATOR
;
7153 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
7154 if (NEED_NEWLINE_DECORATOR_ON_WRITE(fptr
)) {
7155 fptr
->encs
.ecflags
|= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
;
7161 if (0 <= write_fd
) {
7162 write_port
= io_alloc(rb_cIO
);
7163 MakeOpenFile(write_port
, write_fptr
);
7164 write_fptr
->fd
= write_fd
;
7165 write_fptr
->mode
= (fmode
& ~FMODE_READABLE
)| FMODE_SYNC
|FMODE_DUPLEX
;
7166 fptr
->mode
&= ~FMODE_WRITABLE
;
7167 fptr
->tied_io_for_writing
= write_port
;
7168 rb_ivar_set(port
, rb_intern("@tied_io_for_writing"), write_port
);
7171 #if defined (__CYGWIN__) || !defined(HAVE_WORKING_FORK)
7172 fptr
->finalize
= pipe_finalize
;
7173 pipe_add_fptr(fptr
);
7179 pipe_open(VALUE execarg_obj
, const char *modestr
, int fmode
,
7180 const convconfig_t
*convconfig
)
7182 rb_raise(rb_eNotImpError
, "popen() is not available");
7187 is_popen_fork(VALUE prog
)
7189 if (RSTRING_LEN(prog
) == 1 && RSTRING_PTR(prog
)[0] == '-') {
7190 #if !defined(HAVE_WORKING_FORK)
7191 rb_raise(rb_eNotImpError
,
7192 "fork() function is unimplemented on this machine");
7201 pipe_open_s(VALUE prog
, const char *modestr
, int fmode
,
7202 const convconfig_t
*convconfig
)
7205 VALUE
*argv
= &prog
;
7206 VALUE execarg_obj
= Qnil
;
7208 if (!is_popen_fork(prog
))
7209 execarg_obj
= rb_execarg_new(argc
, argv
, TRUE
, FALSE
);
7210 return pipe_open(execarg_obj
, modestr
, fmode
, convconfig
);
7214 pipe_close(VALUE io
)
7216 rb_io_t
*fptr
= io_close_fptr(io
);
7218 fptr_waitpid(fptr
, rb_thread_to_be_killed(rb_thread_current()));
7223 static VALUE
popen_finish(VALUE port
, VALUE klass
);
7227 * IO.popen([env,] cmd, mode="r" [, opt]) -> io
7228 * IO.popen([env,] cmd, mode="r" [, opt]) {|io| block } -> obj
7230 * Runs the specified command as a subprocess; the subprocess's
7231 * standard input and output will be connected to the returned
7234 * The PID of the started process can be obtained by IO#pid method.
7236 * _cmd_ is a string or an array as follows.
7240 * commandline : command line string which is passed to a shell
7241 * [env, cmdname, arg1, ..., opts] : command name and zero or more arguments (no shell)
7242 * [env, [cmdname, argv0], arg1, ..., opts] : command name, argv[0] and zero or more arguments (no shell)
7243 * (env and opts are optional.)
7245 * If _cmd_ is a +String+ ``<code>-</code>'',
7246 * then a new instance of Ruby is started as the subprocess.
7248 * If <i>cmd</i> is an +Array+ of +String+,
7249 * then it will be used as the subprocess's +argv+ bypassing a shell.
7250 * The array can contain a hash at first for environments and
7251 * a hash at last for options similar to #spawn.
7253 * The default mode for the new file object is ``r'',
7254 * but <i>mode</i> may be set to any of the modes listed in the description for class IO.
7255 * The last argument <i>opt</i> qualifies <i>mode</i>.
7258 * IO.popen("nkf -e filename", :external_encoding=>"EUC-JP") {|nkf_io|
7259 * euc_jp_string = nkf_io.read
7262 * # merge standard output and standard error using
7263 * # spawn option. See the document of Kernel.spawn.
7264 * IO.popen(["ls", "/", :err=>[:child, :out]]) {|ls_io|
7265 * ls_result_with_error = ls_io.read
7268 * # spawn options can be mixed with IO options
7269 * IO.popen(["ls", "/"], :err=>[:child, :out]) {|ls_io|
7270 * ls_result_with_error = ls_io.read
7273 * Raises exceptions which IO.pipe and Kernel.spawn raise.
7275 * If a block is given, Ruby will run the command as a child connected
7276 * to Ruby with a pipe. Ruby's end of the pipe will be passed as a
7277 * parameter to the block.
7278 * At the end of block, Ruby closes the pipe and sets <code>$?</code>.
7279 * In this case IO.popen returns the value of the block.
7281 * If a block is given with a _cmd_ of ``<code>-</code>'',
7282 * the block will be run in two separate processes: once in the parent,
7283 * and once in a child. The parent process will be passed the pipe
7284 * object as a parameter to the block, the child version of the block
7285 * will be passed +nil+, and the child's standard in and
7286 * standard out will be connected to the parent through the pipe. Not
7287 * available on all platforms.
7289 * f = IO.popen("uname")
7292 * puts "Parent is #{Process.pid}"
7293 * IO.popen("date") {|f| puts f.gets }
7294 * IO.popen("-") {|f| $stderr.puts "#{Process.pid} is here, f is #{f.inspect}"}
7296 * IO.popen(%w"sed -e s|^|<foo>| -e s&$&;zot;&", "r+") {|f|
7297 * f.puts "bar"; f.close_write; puts f.gets
7300 * <em>produces:</em>
7304 * Thu Jan 15 22:41:19 JST 2009
7305 * 21346 is here, f is #<IO:fd 3>
7306 * 21352 is here, f is nil
7307 * #<Process::Status: pid 21352 exit 0>
7312 rb_io_s_popen(int argc
, VALUE
*argv
, VALUE klass
)
7314 VALUE pname
, pmode
= Qnil
, opt
= Qnil
, env
= Qnil
;
7316 if (argc
> 1 && !NIL_P(opt
= rb_check_hash_type(argv
[argc
-1]))) --argc
;
7317 if (argc
> 1 && !NIL_P(env
= rb_check_hash_type(argv
[0]))) --argc
, ++argv
;
7326 int ex
= !NIL_P(opt
);
7327 rb_error_arity(argc
+ ex
, 1 + ex
, 2 + ex
);
7330 return popen_finish(rb_io_popen(pname
, pmode
, env
, opt
), klass
);
7334 rb_io_popen(VALUE pname
, VALUE pmode
, VALUE env
, VALUE opt
)
7336 const char *modestr
;
7337 VALUE tmp
, execarg_obj
= Qnil
;
7339 convconfig_t convconfig
;
7341 tmp
= rb_check_array_type(pname
);
7343 long len
= RARRAY_LEN(tmp
);
7344 #if SIZEOF_LONG > SIZEOF_INT
7345 if (len
> INT_MAX
) {
7346 rb_raise(rb_eArgError
, "too many arguments");
7349 execarg_obj
= rb_execarg_new((int)len
, RARRAY_CONST_PTR(tmp
), FALSE
, FALSE
);
7353 SafeStringValue(pname
);
7355 if (!is_popen_fork(pname
))
7356 execarg_obj
= rb_execarg_new(1, &pname
, TRUE
, FALSE
);
7358 if (!NIL_P(execarg_obj
)) {
7360 opt
= rb_execarg_extract_options(execarg_obj
, opt
);
7362 rb_execarg_setenv(execarg_obj
, env
);
7364 rb_io_extract_modeenc(&pmode
, 0, opt
, &oflags
, &fmode
, &convconfig
);
7365 modestr
= rb_io_oflags_modestr(oflags
);
7367 return pipe_open(execarg_obj
, modestr
, fmode
, &convconfig
);
7371 popen_finish(VALUE port
, VALUE klass
)
7375 if (rb_block_given_p()) {
7377 rb_io_flush(rb_ractor_stdout());
7378 rb_io_flush(rb_ractor_stderr());
7383 RBASIC_SET_CLASS(port
, klass
);
7384 if (rb_block_given_p()) {
7385 return rb_ensure(rb_yield
, port
, pipe_close
, port
);
7391 rb_scan_open_args(int argc
, const VALUE
*argv
,
7392 VALUE
*fname_p
, int *oflags_p
, int *fmode_p
,
7393 convconfig_t
*convconfig_p
, mode_t
*perm_p
)
7395 VALUE opt
, fname
, vmode
, vperm
;
7399 argc
= rb_scan_args(argc
, argv
, "12:", &fname
, &vmode
, &vperm
, &opt
);
7400 FilePathValue(fname
);
7402 rb_io_extract_modeenc(&vmode
, &vperm
, opt
, &oflags
, &fmode
, convconfig_p
);
7404 perm
= NIL_P(vperm
) ? 0666 : NUM2MODET(vperm
);
7413 rb_open_file(int argc
, const VALUE
*argv
, VALUE io
)
7417 convconfig_t convconfig
;
7420 rb_scan_open_args(argc
, argv
, &fname
, &oflags
, &fmode
, &convconfig
, &perm
);
7421 rb_file_open_generic(io
, fname
, oflags
, fmode
, &convconfig
, perm
);
7428 * Document-method: File::open
7431 * File.open(filename, mode="r" [, opt]) -> file
7432 * File.open(filename [, mode [, perm]] [, opt]) -> file
7433 * File.open(filename, mode="r" [, opt]) {|file| block } -> obj
7434 * File.open(filename [, mode [, perm]] [, opt]) {|file| block } -> obj
7436 * With no associated block, File.open is a synonym for
7437 * File.new. If the optional code block is given, it will
7438 * be passed the opened +file+ as an argument and the File object will
7439 * automatically be closed when the block terminates. The value of the block
7440 * will be returned from File.open.
7442 * If a file is being created, its initial permissions may be set using the
7443 * +perm+ parameter. See File.new for further discussion.
7445 * See IO.new for a description of the +mode+ and +opt+ parameters.
7449 * Document-method: IO::open
7452 * IO.open(fd, mode="r" [, opt]) -> io
7453 * IO.open(fd, mode="r" [, opt]) {|io| block } -> obj
7455 * With no associated block, IO.open is a synonym for IO.new. If
7456 * the optional code block is given, it will be passed +io+ as an argument,
7457 * and the IO object will automatically be closed when the block terminates.
7458 * In this instance, IO.open returns the value of the block.
7460 * See IO.new for a description of the +fd+, +mode+ and +opt+ parameters.
7464 rb_io_s_open(int argc
, VALUE
*argv
, VALUE klass
)
7466 VALUE io
= rb_class_new_instance_kw(argc
, argv
, klass
, RB_PASS_CALLED_KEYWORDS
);
7468 if (rb_block_given_p()) {
7469 return rb_ensure(rb_yield
, io
, io_close
, io
);
7477 * IO.sysopen(path, [mode, [perm]]) -> integer
7479 * Opens the given path, returning the underlying file descriptor as a
7482 * IO.sysopen("testfile") #=> 3
7486 rb_io_s_sysopen(int argc
, VALUE
*argv
, VALUE _
)
7488 VALUE fname
, vmode
, vperm
;
7493 rb_scan_args(argc
, argv
, "12", &fname
, &vmode
, &vperm
);
7494 FilePathValue(fname
);
7498 else if (!NIL_P(intmode
= rb_check_to_integer(vmode
, "to_int")))
7499 oflags
= NUM2INT(intmode
);
7501 SafeStringValue(vmode
);
7502 oflags
= rb_io_modestr_oflags(StringValueCStr(vmode
));
7504 if (NIL_P(vperm
)) perm
= 0666;
7505 else perm
= NUM2MODET(vperm
);
7507 RB_GC_GUARD(fname
) = rb_str_new4(fname
);
7508 fd
= rb_sysopen(fname
, oflags
, perm
);
7513 check_pipe_command(VALUE filename_or_command
)
7515 char *s
= RSTRING_PTR(filename_or_command
);
7516 long l
= RSTRING_LEN(filename_or_command
);
7520 if (rb_enc_ascget(s
, e
, &chlen
, rb_enc_get(filename_or_command
)) == '|') {
7521 VALUE cmd
= rb_str_new(s
+chlen
, l
-chlen
);
7529 * open(path [, mode [, perm]] [, opt]) -> io or nil
7530 * open(path [, mode [, perm]] [, opt]) {|io| block } -> obj
7532 * Creates an IO object connected to the given stream, file, or subprocess.
7534 * If +path+ does not start with a pipe character (<code>|</code>), treat it
7535 * as the name of a file to open using the specified mode (defaulting to
7538 * The +mode+ is either a string or an integer. If it is an integer, it
7539 * must be bitwise-or of open(2) flags, such as File::RDWR or File::EXCL. If
7540 * it is a string, it is either "fmode", "fmode:ext_enc", or
7541 * "fmode:ext_enc:int_enc".
7543 * See the documentation of IO.new for full documentation of the +mode+ string
7546 * If a file is being created, its initial permissions may be set using the
7547 * +perm+ parameter. See File.new and the open(2) and chmod(2) man pages for
7548 * a description of permissions.
7550 * If a block is specified, it will be invoked with the IO object as a
7551 * parameter, and the IO will be automatically closed when the block
7552 * terminates. The call returns the value of the block.
7554 * If +path+ starts with a pipe character (<code>"|"</code>), a subprocess is
7555 * created, connected to the caller by a pair of pipes. The returned IO
7556 * object may be used to write to the standard input and read from the
7557 * standard output of this subprocess.
7559 * If the command following the pipe is a single minus sign
7560 * (<code>"|-"</code>), Ruby forks, and this subprocess is connected to the
7561 * parent. If the command is not <code>"-"</code>, the subprocess runs the
7562 * command. Note that the command may be processed by shell if it contains
7563 * shell metacharacters.
7565 * When the subprocess is Ruby (opened via <code>"|-"</code>), the +open+
7566 * call returns +nil+. If a block is associated with the open call, that
7567 * block will run twice --- once in the parent and once in the child.
7569 * The block parameter will be an IO object in the parent and +nil+ in the
7570 * child. The parent's +IO+ object will be connected to the child's $stdin
7571 * and $stdout. The subprocess will be terminated at the end of the block.
7575 * Reading from "testfile":
7577 * open("testfile") do |f|
7585 * Open a subprocess and read its output:
7587 * cmd = open("|date")
7593 * Wed Apr 9 08:56:31 CDT 2003
7595 * Open a subprocess running the same Ruby program:
7597 * f = open("|-", "w+")
7602 * puts "Got: #{f.gets}"
7609 * Open a subprocess using a block to receive the IO object:
7614 * puts "Got: #{f.gets}"
7627 rb_f_open(int argc
, VALUE
*argv
, VALUE _
)
7630 int redirect
= FALSE
;
7633 CONST_ID(to_open
, "to_open");
7634 if (rb_respond_to(argv
[0], to_open
)) {
7638 VALUE tmp
= argv
[0];
7644 VALUE cmd
= check_pipe_command(tmp
);
7647 return rb_io_s_popen(argc
, argv
, rb_cIO
);
7653 VALUE io
= rb_funcallv_kw(argv
[0], to_open
, argc
-1, argv
+1, RB_PASS_CALLED_KEYWORDS
);
7655 if (rb_block_given_p()) {
7656 return rb_ensure(rb_yield
, io
, io_close
, io
);
7660 return rb_io_s_open(argc
, argv
, rb_cFile
);
7663 static VALUE
rb_io_open_generic(VALUE
, VALUE
, int, int, const convconfig_t
*, mode_t
);
7666 rb_io_open(VALUE io
, VALUE filename
, VALUE vmode
, VALUE vperm
, VALUE opt
)
7669 convconfig_t convconfig
;
7672 rb_io_extract_modeenc(&vmode
, &vperm
, opt
, &oflags
, &fmode
, &convconfig
);
7673 perm
= NIL_P(vperm
) ? 0666 : NUM2MODET(vperm
);
7674 return rb_io_open_generic(io
, filename
, oflags
, fmode
, &convconfig
, perm
);
7678 rb_io_open_generic(VALUE klass
, VALUE filename
, int oflags
, int fmode
,
7679 const convconfig_t
*convconfig
, mode_t perm
)
7682 if (klass
== rb_cIO
&& !NIL_P(cmd
= check_pipe_command(filename
))) {
7683 return pipe_open_s(cmd
, rb_io_oflags_modestr(oflags
), fmode
, convconfig
);
7686 return rb_file_open_generic(io_alloc(klass
), filename
,
7687 oflags
, fmode
, convconfig
, perm
);
7692 io_reopen(VALUE io
, VALUE nfile
)
7694 rb_io_t
*fptr
, *orig
;
7698 nfile
= rb_io_get_io(nfile
);
7699 GetOpenFile(io
, fptr
);
7700 GetOpenFile(nfile
, orig
);
7702 if (fptr
== orig
) return io
;
7703 if (IS_PREP_STDIO(fptr
)) {
7704 if ((fptr
->stdio_file
== stdin
&& !(orig
->mode
& FMODE_READABLE
)) ||
7705 (fptr
->stdio_file
== stdout
&& !(orig
->mode
& FMODE_WRITABLE
)) ||
7706 (fptr
->stdio_file
== stderr
&& !(orig
->mode
& FMODE_WRITABLE
))) {
7707 rb_raise(rb_eArgError
,
7708 "%s can't change access mode from \"%s\" to \"%s\"",
7709 PREP_STDIO_NAME(fptr
), rb_io_fmode_modestr(fptr
->mode
),
7710 rb_io_fmode_modestr(orig
->mode
));
7713 if (fptr
->mode
& FMODE_WRITABLE
) {
7714 if (io_fflush(fptr
) < 0)
7715 rb_sys_fail_on_write(fptr
);
7718 flush_before_seek(fptr
);
7720 if (orig
->mode
& FMODE_READABLE
) {
7721 pos
= io_tell(orig
);
7723 if (orig
->mode
& FMODE_WRITABLE
) {
7724 if (io_fflush(orig
) < 0)
7725 rb_sys_fail_on_write(fptr
);
7728 /* copy rb_io_t structure */
7729 fptr
->mode
= orig
->mode
| (fptr
->mode
& FMODE_PREP
);
7730 fptr
->pid
= orig
->pid
;
7731 fptr
->lineno
= orig
->lineno
;
7732 if (RTEST(orig
->pathv
)) fptr
->pathv
= orig
->pathv
;
7733 else if (!IS_PREP_STDIO(fptr
)) fptr
->pathv
= Qnil
;
7734 fptr_copy_finalizer(fptr
, orig
);
7739 if (IS_PREP_STDIO(fptr
) || fd
<= 2 || !fptr
->stdio_file
) {
7740 /* need to keep FILE objects of stdin, stdout and stderr */
7741 if (rb_cloexec_dup2(fd2
, fd
) < 0)
7742 rb_sys_fail_path(orig
->pathv
);
7743 rb_update_max_fd(fd
);
7746 fclose(fptr
->stdio_file
);
7747 fptr
->stdio_file
= 0;
7749 if (rb_cloexec_dup2(fd2
, fd
) < 0)
7750 rb_sys_fail_path(orig
->pathv
);
7751 rb_update_max_fd(fd
);
7754 rb_thread_fd_close(fd
);
7755 if ((orig
->mode
& FMODE_READABLE
) && pos
>= 0) {
7756 if (io_seek(fptr
, pos
, SEEK_SET
) < 0 && errno
) {
7757 rb_sys_fail_path(fptr
->pathv
);
7759 if (io_seek(orig
, pos
, SEEK_SET
) < 0 && errno
) {
7760 rb_sys_fail_path(orig
->pathv
);
7765 if (fptr
->mode
& FMODE_BINMODE
) {
7769 RBASIC_SET_CLASS(io
, rb_obj_class(nfile
));
7774 int rb_freopen(VALUE fname
, const char *mode
, FILE *fp
);
7777 rb_freopen(VALUE fname
, const char *mode
, FILE *fp
)
7779 if (!freopen(RSTRING_PTR(fname
), mode
, fp
)) {
7789 * ios.reopen(other_IO) -> ios
7790 * ios.reopen(path, mode [, opt]) -> ios
7792 * Reassociates <em>ios</em> with the I/O stream given in
7793 * <i>other_IO</i> or to a new stream opened on <i>path</i>. This may
7794 * dynamically change the actual class of this stream.
7795 * The +mode+ and +opt+ parameters accept the same values as IO.open.
7797 * f1 = File.new("testfile")
7798 * f2 = File.new("testfile")
7799 * f2.readlines[0] #=> "This is line one\n"
7800 * f2.reopen(f1) #=> #<File:testfile>
7801 * f2.readlines[0] #=> "This is line one\n"
7805 rb_io_reopen(int argc
, VALUE
*argv
, VALUE file
)
7807 VALUE fname
, nmode
, opt
;
7811 if (rb_scan_args(argc
, argv
, "11:", &fname
, &nmode
, &opt
) == 1) {
7812 VALUE tmp
= rb_io_check_io(fname
);
7814 return io_reopen(file
, tmp
);
7818 FilePathValue(fname
);
7819 rb_io_taint_check(file
);
7820 fptr
= RFILE(file
)->fptr
;
7822 fptr
= RFILE(file
)->fptr
= ZALLOC(rb_io_t
);
7825 if (!NIL_P(nmode
) || !NIL_P(opt
)) {
7827 convconfig_t convconfig
;
7829 rb_io_extract_modeenc(&nmode
, 0, opt
, &oflags
, &fmode
, &convconfig
);
7830 if (IS_PREP_STDIO(fptr
) &&
7831 ((fptr
->mode
& FMODE_READWRITE
) & (fmode
& FMODE_READWRITE
)) !=
7832 (fptr
->mode
& FMODE_READWRITE
)) {
7833 rb_raise(rb_eArgError
,
7834 "%s can't change access mode from \"%s\" to \"%s\"",
7835 PREP_STDIO_NAME(fptr
), rb_io_fmode_modestr(fptr
->mode
),
7836 rb_io_fmode_modestr(fmode
));
7839 fptr
->encs
= convconfig
;
7842 oflags
= rb_io_fmode_oflags(fptr
->mode
);
7845 fptr
->pathv
= fname
;
7847 fptr
->fd
= rb_sysopen(fptr
->pathv
, oflags
, 0666);
7848 fptr
->stdio_file
= 0;
7852 if (fptr
->mode
& FMODE_WRITABLE
) {
7853 if (io_fflush(fptr
) < 0)
7854 rb_sys_fail_on_write(fptr
);
7856 fptr
->rbuf
.off
= fptr
->rbuf
.len
= 0;
7858 if (fptr
->stdio_file
) {
7859 int e
= rb_freopen(rb_str_encode_ospath(fptr
->pathv
),
7860 rb_io_oflags_modestr(oflags
),
7862 if (e
) rb_syserr_fail_path(e
, fptr
->pathv
);
7863 fptr
->fd
= fileno(fptr
->stdio_file
);
7864 rb_fd_fix_cloexec(fptr
->fd
);
7866 if (setvbuf(fptr
->stdio_file
, NULL
, _IOFBF
, 0) != 0)
7867 rb_warn("setvbuf() can't be honoured for %"PRIsVALUE
, fptr
->pathv
);
7869 if (fptr
->stdio_file
== stderr
) {
7870 if (setvbuf(fptr
->stdio_file
, NULL
, _IONBF
, BUFSIZ
) != 0)
7871 rb_warn("setvbuf() can't be honoured for %"PRIsVALUE
, fptr
->pathv
);
7873 else if (fptr
->stdio_file
== stdout
&& isatty(fptr
->fd
)) {
7874 if (setvbuf(fptr
->stdio_file
, NULL
, _IOLBF
, BUFSIZ
) != 0)
7875 rb_warn("setvbuf() can't be honoured for %"PRIsVALUE
, fptr
->pathv
);
7879 int tmpfd
= rb_sysopen(fptr
->pathv
, oflags
, 0666);
7881 if (rb_cloexec_dup2(tmpfd
, fptr
->fd
) < 0)
7885 rb_syserr_fail_path(err
, fptr
->pathv
);
7894 rb_io_init_copy(VALUE dest
, VALUE io
)
7896 rb_io_t
*fptr
, *orig
;
7901 io
= rb_io_get_io(io
);
7902 if (!OBJ_INIT_COPY(dest
, io
)) return dest
;
7903 GetOpenFile(io
, orig
);
7904 MakeOpenFile(dest
, fptr
);
7908 /* copy rb_io_t structure */
7909 fptr
->mode
= orig
->mode
& ~FMODE_PREP
;
7910 fptr
->encs
= orig
->encs
;
7911 fptr
->pid
= orig
->pid
;
7912 fptr
->lineno
= orig
->lineno
;
7913 if (!NIL_P(orig
->pathv
)) fptr
->pathv
= orig
->pathv
;
7914 fptr_copy_finalizer(fptr
, orig
);
7916 fd
= ruby_dup(orig
->fd
);
7918 pos
= io_tell(orig
);
7920 io_seek(fptr
, pos
, SEEK_SET
);
7921 if (fptr
->mode
& FMODE_BINMODE
) {
7922 rb_io_binmode(dest
);
7925 write_io
= GetWriteIO(io
);
7926 if (io
!= write_io
) {
7927 write_io
= rb_obj_dup(write_io
);
7928 fptr
->tied_io_for_writing
= write_io
;
7929 rb_ivar_set(dest
, rb_intern("@tied_io_for_writing"), write_io
);
7937 * ios.printf(format_string [, obj, ...]) -> nil
7939 * Formats and writes to <em>ios</em>, converting parameters under
7940 * control of the format string. See Kernel#sprintf for details.
7944 rb_io_printf(int argc
, const VALUE
*argv
, VALUE out
)
7946 rb_io_write(out
, rb_f_sprintf(argc
, argv
));
7952 * printf(io, string [, obj ... ]) -> nil
7953 * printf(string [, obj ... ]) -> nil
7956 * io.write(sprintf(string, obj, ...))
7958 * $stdout.write(sprintf(string, obj, ...))
7962 rb_f_printf(int argc
, VALUE
*argv
, VALUE _
)
7966 if (argc
== 0) return Qnil
;
7967 if (RB_TYPE_P(argv
[0], T_STRING
)) {
7968 out
= rb_ractor_stdout();
7975 rb_io_write(out
, rb_f_sprintf(argc
, argv
));
7981 deprecated_str_setter(VALUE val
, ID id
, VALUE
*var
)
7983 rb_str_setter(val
, id
, &val
);
7985 rb_warn_deprecated("`%s'", NULL
, rb_id2name(id
));
7993 * ios.print(obj, ...) -> nil
7995 * Writes the given object(s) to <em>ios</em>. Returns +nil+.
7997 * The stream must be opened for writing.
7998 * Each given object that isn't a string will be converted by calling
7999 * its <code>to_s</code> method.
8000 * When called without arguments, prints the contents of <code>$_</code>.
8002 * If the output field separator (<code>$,</code>) is not +nil+,
8003 * it is inserted between objects.
8004 * If the output record separator (<code>$\\</code>) is not +nil+,
8005 * it is appended to the output.
8007 * $stdout.print("This is ", 100, " percent.\n")
8009 * <em>produces:</em>
8011 * This is 100 percent.
8015 rb_io_print(int argc
, const VALUE
*argv
, VALUE out
)
8020 /* if no argument given, print `$_' */
8023 line
= rb_lastline_get();
8026 if (argc
> 1 && !NIL_P(rb_output_fs
)) {
8027 rb_category_warn(RB_WARN_CATEGORY_DEPRECATED
, "$, is set to non-nil value");
8029 for (i
=0; i
<argc
; i
++) {
8030 if (!NIL_P(rb_output_fs
) && i
>0) {
8031 rb_io_write(out
, rb_output_fs
);
8033 rb_io_write(out
, argv
[i
]);
8035 if (argc
> 0 && !NIL_P(rb_output_rs
)) {
8036 rb_io_write(out
, rb_output_rs
);
8044 * print(obj, ...) -> nil
8046 * Prints each object in turn to <code>$stdout</code>. If the output
8047 * field separator (<code>$,</code>) is not +nil+, its
8048 * contents will appear between each field. If the output record
8049 * separator (<code>$\\</code>) is not +nil+, it will be
8050 * appended to the output. If no arguments are given, prints
8051 * <code>$_</code>. Objects that aren't strings will be converted by
8052 * calling their <code>to_s</code> method.
8054 * print "cat", [1,2,3], 99, "\n"
8057 * print "cat", [1,2,3], 99
8059 * <em>produces:</em>
8066 rb_f_print(int argc
, const VALUE
*argv
, VALUE _
)
8068 rb_io_print(argc
, argv
, rb_ractor_stdout());
8074 * ios.putc(obj) -> obj
8076 * If <i>obj</i> is Numeric, write the character whose code is the
8077 * least-significant byte of <i>obj</i>. If <i>obj</i> is String,
8078 * write the first character of <i>obj</i> to <em>ios</em>. Otherwise,
8084 * <em>produces:</em>
8090 rb_io_putc(VALUE io
, VALUE ch
)
8093 if (RB_TYPE_P(ch
, T_STRING
)) {
8094 str
= rb_str_substr(ch
, 0, 1);
8097 char c
= NUM2CHR(ch
);
8098 str
= rb_str_new(&c
, 1);
8100 rb_io_write(io
, str
);
8104 #define forward(obj, id, argc, argv) \
8105 rb_funcallv_kw(obj, id, argc, argv, RB_PASS_CALLED_KEYWORDS)
8106 #define forward_public(obj, id, argc, argv) \
8107 rb_funcallv_public_kw(obj, id, argc, argv, RB_PASS_CALLED_KEYWORDS)
8108 #define forward_current(id, argc, argv) \
8109 forward_public(ARGF.current_file, id, argc, argv)
8119 * Refer to the documentation for IO#putc for important information regarding
8120 * multi-byte characters.
8124 rb_f_putc(VALUE recv
, VALUE ch
)
8126 VALUE r_stdout
= rb_ractor_stdout();
8127 if (recv
== r_stdout
) {
8128 return rb_io_putc(recv
, ch
);
8130 return forward(r_stdout
, rb_intern("putc"), 1, &ch
);
8135 rb_str_end_with_asciichar(VALUE str
, int c
)
8137 long len
= RSTRING_LEN(str
);
8138 const char *ptr
= RSTRING_PTR(str
);
8139 rb_encoding
*enc
= rb_enc_from_index(ENCODING_GET(str
));
8142 if (len
== 0) return 0;
8143 if ((n
= rb_enc_mbminlen(enc
)) == 1) {
8144 return ptr
[len
- 1] == c
;
8146 return rb_enc_ascget(ptr
+ ((len
- 1) / n
) * n
, ptr
+ len
, &n
, enc
) == c
;
8150 io_puts_ary(VALUE ary
, VALUE out
, int recur
)
8156 tmp
= rb_str_new2("[...]");
8157 rb_io_puts(1, &tmp
, out
);
8160 ary
= rb_check_array_type(ary
);
8161 if (NIL_P(ary
)) return Qfalse
;
8162 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
8163 tmp
= RARRAY_AREF(ary
, i
);
8164 rb_io_puts(1, &tmp
, out
);
8171 * ios.puts(obj, ...) -> nil
8173 * Writes the given object(s) to <em>ios</em>.
8174 * Writes a newline after any that do not already end
8175 * with a newline sequence. Returns +nil+.
8177 * The stream must be opened for writing.
8178 * If called with an array argument, writes each element on a new line.
8179 * Each given object that isn't a string or array will be converted
8180 * by calling its +to_s+ method.
8181 * If called without arguments, outputs a single newline.
8183 * $stdout.puts("this", "is", ["a", "test"])
8185 * <em>produces:</em>
8192 * Note that +puts+ always uses newlines and is not affected
8193 * by the output record separator (<code>$\\</code>).
8197 rb_io_puts(int argc
, const VALUE
*argv
, VALUE out
)
8200 VALUE line
, args
[2];
8202 /* if no argument given, print newline. */
8204 rb_io_write(out
, rb_default_rs
);
8207 for (i
=0; i
<argc
; i
++) {
8208 if (RB_TYPE_P(argv
[i
], T_STRING
)) {
8212 if (rb_exec_recursive(io_puts_ary
, argv
[i
], out
)) {
8215 line
= rb_obj_as_string(argv
[i
]);
8219 if (RSTRING_LEN(line
) == 0 ||
8220 !rb_str_end_with_asciichar(line
, '\n')) {
8221 args
[n
++] = rb_default_rs
;
8223 rb_io_writev(out
, n
, args
);
8231 * puts(obj, ...) -> nil
8235 * $stdout.puts(obj, ...)
8239 rb_f_puts(int argc
, VALUE
*argv
, VALUE recv
)
8241 VALUE r_stdout
= rb_ractor_stdout();
8242 if (recv
== r_stdout
) {
8243 return rb_io_puts(argc
, argv
, recv
);
8245 return forward(r_stdout
, rb_intern("puts"), argc
, argv
);
8249 rb_p_write(VALUE str
)
8253 args
[1] = rb_default_rs
;
8254 VALUE r_stdout
= rb_ractor_stdout();
8255 if (RB_TYPE_P(r_stdout
, T_FILE
) &&
8256 rb_method_basic_definition_p(CLASS_OF(r_stdout
), id_write
)) {
8257 io_writev(2, args
, r_stdout
);
8260 rb_io_writev(r_stdout
, 2, args
);
8266 rb_p(VALUE obj
) /* for debug print within C code */
8268 rb_p_write(rb_obj_as_string(rb_inspect(obj
)));
8272 rb_p_result(int argc
, const VALUE
*argv
)
8279 else if (argc
> 1) {
8280 ret
= rb_ary_new4(argc
, argv
);
8282 VALUE r_stdout
= rb_ractor_stdout();
8283 if (RB_TYPE_P(r_stdout
, T_FILE
)) {
8284 rb_io_flush(r_stdout
);
8292 * p(obj1, obj2, ...) -> [obj, ...]
8295 * For each object, directly writes _obj_.+inspect+ followed by a
8296 * newline to the program's standard output.
8298 * S = Struct.new(:name, :state)
8299 * s = S['dave', 'TX']
8302 * <em>produces:</em>
8304 * #<S name="dave", state="TX">
8308 rb_f_p(int argc
, VALUE
*argv
, VALUE self
)
8311 for (i
=0; i
<argc
; i
++) {
8312 VALUE inspected
= rb_obj_as_string(rb_inspect(argv
[i
]));
8313 rb_uninterruptible(rb_p_write
, inspected
);
8315 return rb_p_result(argc
, argv
);
8320 * obj.display(port=$>) -> nil
8322 * Prints <i>obj</i> on the given port (default <code>$></code>).
8325 * def display(port=$>)
8334 * [ 4, 5, 6 ].display
8337 * <em>produces:</em>
8343 rb_obj_display(int argc
, VALUE
*argv
, VALUE self
)
8347 out
= (!rb_check_arity(argc
, 0, 1) ? rb_ractor_stdout() : argv
[0]);
8348 rb_io_write(out
, self
);
8354 rb_stderr_to_original_p(VALUE err
)
8356 return (err
== orig_stderr
|| RFILE(orig_stderr
)->fptr
->fd
< 0);
8360 rb_write_error2(const char *mesg
, long len
)
8362 VALUE out
= rb_ractor_stderr();
8363 if (rb_stderr_to_original_p(out
)) {
8365 if (isatty(fileno(stderr
))) {
8366 if (rb_w32_write_console(rb_str_new(mesg
, len
), fileno(stderr
)) > 0) return;
8369 if (fwrite(mesg
, sizeof(char), (size_t)len
, stderr
) < (size_t)len
) {
8370 /* failed to write to stderr, what can we do? */
8375 rb_io_write(out
, rb_str_new(mesg
, len
));
8380 rb_write_error(const char *mesg
)
8382 rb_write_error2(mesg
, strlen(mesg
));
8386 rb_write_error_str(VALUE mesg
)
8388 VALUE out
= rb_ractor_stderr();
8389 /* a stopgap measure for the time being */
8390 if (rb_stderr_to_original_p(out
)) {
8391 size_t len
= (size_t)RSTRING_LEN(mesg
);
8393 if (isatty(fileno(stderr
))) {
8394 if (rb_w32_write_console(mesg
, fileno(stderr
)) > 0) return;
8397 if (fwrite(RSTRING_PTR(mesg
), sizeof(char), len
, stderr
) < len
) {
8403 /* may unlock GVL, and */
8404 rb_io_write(out
, mesg
);
8409 rb_stderr_tty_p(void)
8411 if (rb_stderr_to_original_p(rb_ractor_stderr()))
8412 return isatty(fileno(stderr
));
8417 must_respond_to(ID mid
, VALUE val
, ID id
)
8419 if (!rb_respond_to(val
, mid
)) {
8420 rb_raise(rb_eTypeError
, "%"PRIsVALUE
" must have %"PRIsVALUE
" method, %"PRIsVALUE
" given",
8421 rb_id2str(id
), rb_id2str(mid
),
8427 stdin_setter(VALUE val
, ID id
, VALUE
*ptr
)
8429 rb_ractor_stdin_set(val
);
8433 stdin_getter(ID id
, VALUE
*ptr
)
8435 return rb_ractor_stdin();
8439 stdout_setter(VALUE val
, ID id
, VALUE
*ptr
)
8441 must_respond_to(id_write
, val
, id
);
8442 rb_ractor_stdout_set(val
);
8446 stdout_getter(ID id
, VALUE
*ptr
)
8448 return rb_ractor_stdout();
8452 stderr_setter(VALUE val
, ID id
, VALUE
*ptr
)
8454 must_respond_to(id_write
, val
, id
);
8455 rb_ractor_stderr_set(val
);
8459 stderr_getter(ID id
, VALUE
*ptr
)
8461 return rb_ractor_stderr();
8465 prep_io(int fd
, int fmode
, VALUE klass
, const char *path
)
8468 VALUE io
= io_alloc(klass
);
8470 MakeOpenFile(io
, fp
);
8474 if (!io_check_tty(fp
)) {
8476 fp
->mode
|= FMODE_BINMODE
;
8477 setmode(fd
, O_BINARY
);
8480 if (path
) fp
->pathv
= rb_obj_freeze(rb_str_new_cstr(path
));
8481 rb_update_max_fd(fd
);
8487 rb_io_fdopen(int fd
, int oflags
, const char *path
)
8489 VALUE klass
= rb_cIO
;
8491 if (path
&& strcmp(path
, "-")) klass
= rb_cFile
;
8492 return prep_io(fd
, rb_io_oflags_fmode(oflags
), klass
, path
);
8496 prep_stdio(FILE *f
, int fmode
, VALUE klass
, const char *path
)
8499 VALUE io
= prep_io(fileno(f
), fmode
|FMODE_PREP
|DEFAULT_TEXTMODE
, klass
, path
);
8501 GetOpenFile(io
, fptr
);
8502 fptr
->encs
.ecflags
|= ECONV_DEFAULT_NEWLINE_DECORATOR
;
8503 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
8504 fptr
->encs
.ecflags
|= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
;
8505 if (fmode
& FMODE_READABLE
) {
8506 fptr
->encs
.ecflags
|= ECONV_UNIVERSAL_NEWLINE_DECORATOR
;
8509 fptr
->stdio_file
= f
;
8515 rb_io_prep_stdin(void)
8517 return prep_stdio(stdin
, FMODE_READABLE
, rb_cIO
, "<STDIN>");
8521 rb_io_prep_stdout(void)
8523 return prep_stdio(stdout
, FMODE_WRITABLE
|FMODE_SIGNAL_ON_EPIPE
, rb_cIO
, "<STDOUT>");
8527 rb_io_prep_stderr(void)
8529 return prep_stdio(stderr
, FMODE_WRITABLE
|FMODE_SYNC
, rb_cIO
, "<STDERR>");
8533 rb_io_stdio_file(rb_io_t
*fptr
)
8535 if (!fptr
->stdio_file
) {
8536 int oflags
= rb_io_fmode_oflags(fptr
->mode
) & ~O_EXCL
;
8537 fptr
->stdio_file
= rb_fdopen(fptr
->fd
, rb_io_oflags_modestr(oflags
));
8539 return fptr
->stdio_file
;
8543 rb_io_buffer_init(rb_io_buffer_t
*buf
)
8551 static inline rb_io_t
*
8552 rb_io_fptr_new(void)
8554 rb_io_t
*fp
= ALLOC(rb_io_t
);
8557 fp
->stdio_file
= NULL
;
8563 rb_io_buffer_init(&fp
->wbuf
);
8564 rb_io_buffer_init(&fp
->rbuf
);
8565 rb_io_buffer_init(&fp
->cbuf
);
8566 fp
->readconv
= NULL
;
8567 fp
->writeconv
= NULL
;
8568 fp
->writeconv_asciicompat
= Qnil
;
8569 fp
->writeconv_pre_ecflags
= 0;
8570 fp
->writeconv_pre_ecopts
= Qnil
;
8571 fp
->writeconv_initialized
= 0;
8572 fp
->tied_io_for_writing
= 0;
8573 fp
->encs
.enc
= NULL
;
8574 fp
->encs
.enc2
= NULL
;
8575 fp
->encs
.ecflags
= 0;
8576 fp
->encs
.ecopts
= Qnil
;
8582 rb_io_make_open_file(VALUE obj
)
8586 Check_Type(obj
, T_FILE
);
8587 if (RFILE(obj
)->fptr
) {
8589 rb_io_fptr_finalize(RFILE(obj
)->fptr
);
8590 RFILE(obj
)->fptr
= 0;
8592 fp
= rb_io_fptr_new();
8594 RFILE(obj
)->fptr
= fp
;
8600 * IO.new(fd [, mode] [, opt]) -> io
8602 * Returns a new IO object (a stream) for the given integer file descriptor
8603 * +fd+ and +mode+ string. +opt+ may be used to specify parts of +mode+ in a
8604 * more readable fashion. See also IO.sysopen and IO.for_fd.
8606 * IO.new is called by various File and IO opening methods such as IO::open,
8607 * Kernel#open, and File::open.
8611 * When +mode+ is an integer it must be combination of the modes defined in
8612 * File::Constants (+File::RDONLY+, <code>File::WRONLY|File::CREAT</code>).
8613 * See the open(2) man page for more information.
8615 * When +mode+ is a string it must be in one of the following forms:
8619 * fmode ":" ext_enc ":" int_enc
8620 * fmode ":" "BOM|UTF-*"
8622 * +fmode+ is an IO open mode string, +ext_enc+ is the external encoding for
8623 * the IO and +int_enc+ is the internal encoding.
8627 * Ruby allows the following open modes:
8629 * "r" Read-only, starts at beginning of file (default mode).
8631 * "r+" Read-write, starts at beginning of file.
8633 * "w" Write-only, truncates existing file
8634 * to zero length or creates a new file for writing.
8636 * "w+" Read-write, truncates existing file to zero length
8637 * or creates a new file for reading and writing.
8639 * "a" Write-only, each write call appends data at end of file.
8640 * Creates a new file for writing if file does not exist.
8642 * "a+" Read-write, each write call appends data at end of file.
8643 * Creates a new file for reading and writing if file does
8646 * The following modes must be used separately, and along with one or more of
8647 * the modes seen above.
8649 * "b" Binary file mode
8650 * Suppresses EOL <-> CRLF conversion on Windows. And
8651 * sets external encoding to ASCII-8BIT unless explicitly
8654 * "t" Text file mode
8656 * The exclusive access mode ("x") can be used together with "w" to ensure
8657 * the file is created. Errno::EEXIST is raised when it already exists.
8658 * It may not be supported with all kinds of streams (e.g. pipes).
8660 * When the open mode of original IO is read only, the mode cannot be
8661 * changed to be writable. Similarly, the open mode cannot be changed from
8662 * write only to readable.
8664 * When such a change is attempted the error is raised in different locations
8665 * according to the platform.
8669 * When +ext_enc+ is specified, strings read will be tagged by the encoding
8670 * when reading, and strings output will be converted to the specified
8671 * encoding when writing.
8673 * When +ext_enc+ and +int_enc+ are specified read strings will be converted
8674 * from +ext_enc+ to +int_enc+ upon input, and written strings will be
8675 * converted from +int_enc+ to +ext_enc+ upon output. See Encoding for
8676 * further details of transcoding on input and output.
8678 * If "BOM|UTF-8", "BOM|UTF-16LE" or "BOM|UTF16-BE" are used, Ruby checks for
8679 * a Unicode BOM in the input document to help determine the encoding. For
8680 * UTF-16 encodings the file open mode must be binary. When present, the BOM
8681 * is stripped and the external encoding from the BOM is used. When the BOM
8682 * is missing the given Unicode encoding is used as +ext_enc+. (The BOM-set
8683 * encoding option is case insensitive, so "bom|utf-8" is also valid.)
8687 * +opt+ can be used instead of +mode+ for improved readability. The
8688 * following keys are supported:
8691 * Same as +mode+ parameter
8694 * Specifies file open flags as integer.
8695 * If +mode+ parameter is given, this parameter will be bitwise-ORed.
8697 * :\external_encoding ::
8698 * External encoding for the IO.
8700 * :\internal_encoding ::
8701 * Internal encoding for the IO. "-" is a synonym for the default internal
8704 * If the value is +nil+ no conversion occurs.
8707 * Specifies external and internal encodings as "extern:intern".
8710 * If the value is truth value, same as "t" in argument +mode+.
8713 * If the value is truth value, same as "b" in argument +mode+.
8716 * If the value is +false+, the +fd+ will be kept open after this IO
8717 * instance gets finalized.
8719 * Also, +opt+ can have same keys in String#encode for controlling conversion
8720 * between the external encoding and the internal encoding.
8724 * fd = IO.sysopen("/dev/tty", "w")
8725 * a = IO.new(fd,"w")
8726 * $stderr.puts "Hello"
8738 * fd = STDERR.fcntl(Fcntl::F_DUPFD)
8739 * io = IO.new(fd, mode: 'w:UTF-16LE', cr_newline: true)
8740 * io.puts "Hello, World!"
8742 * fd = STDERR.fcntl(Fcntl::F_DUPFD)
8743 * io = IO.new(fd, mode: 'w', cr_newline: true,
8744 * external_encoding: Encoding::UTF_16LE)
8745 * io.puts "Hello, World!"
8747 * Both of above print "Hello, World!" in UTF-16LE to standard error output
8748 * with converting EOL generated by #puts to CR.
8752 rb_io_initialize(int argc
, VALUE
*argv
, VALUE io
)
8756 int fd
, fmode
, oflags
= O_RDONLY
;
8757 convconfig_t convconfig
;
8759 #if defined(HAVE_FCNTL) && defined(F_GETFL)
8766 argc
= rb_scan_args(argc
, argv
, "11:", &fnum
, &vmode
, &opt
);
8767 rb_io_extract_modeenc(&vmode
, 0, opt
, &oflags
, &fmode
, &convconfig
);
8770 if (rb_reserved_fd_p(fd
)) {
8771 rb_raise(rb_eArgError
, "The given fd is not accessible because RubyVM reserves it");
8773 #if defined(HAVE_FCNTL) && defined(F_GETFL)
8774 oflags
= fcntl(fd
, F_GETFL
);
8775 if (oflags
== -1) rb_sys_fail(0);
8777 if (fstat(fd
, &st
) < 0) rb_sys_fail(0);
8779 rb_update_max_fd(fd
);
8780 #if defined(HAVE_FCNTL) && defined(F_GETFL)
8781 ofmode
= rb_io_oflags_fmode(oflags
);
8785 else if ((~ofmode
& fmode
) & FMODE_READWRITE
) {
8786 VALUE error
= INT2FIX(EINVAL
);
8787 rb_exc_raise(rb_class_new_instance(1, &error
, rb_eSystemCallError
));
8790 if (!NIL_P(opt
) && rb_hash_aref(opt
, sym_autoclose
) == Qfalse
) {
8791 fmode
|= FMODE_PREP
;
8793 MakeOpenFile(io
, fp
);
8797 fp
->encs
= convconfig
;
8800 if (fileno(stdin
) == fd
)
8801 fp
->stdio_file
= stdin
;
8802 else if (fileno(stdout
) == fd
)
8803 fp
->stdio_file
= stdout
;
8804 else if (fileno(stderr
) == fd
)
8805 fp
->stdio_file
= stderr
;
8807 if (fmode
& FMODE_SETENC_BY_BOM
) io_set_encoding_by_bom(io
);
8813 * ios.set_encoding_by_bom -> encoding or nil
8815 * Checks if +ios+ starts with a BOM, and then consumes it and sets
8816 * the external encoding. Returns the result encoding if found, or
8817 * nil. If +ios+ is not binmode or its encoding has been set
8818 * already, an exception will be raised.
8820 * File.write("bom.txt", "\u{FEFF}abc")
8821 * ios = File.open("bom.txt", "rb")
8822 * ios.set_encoding_by_bom #=> #<Encoding:UTF-8>
8824 * File.write("nobom.txt", "abc")
8825 * ios = File.open("nobom.txt", "rb")
8826 * ios.set_encoding_by_bom #=> nil
8830 rb_io_set_encoding_by_bom(VALUE io
)
8834 GetOpenFile(io
, fptr
);
8835 if (!(fptr
->mode
& FMODE_BINMODE
)) {
8836 rb_raise(rb_eArgError
, "ASCII incompatible encoding needs binmode");
8838 if (fptr
->encs
.enc2
) {
8839 rb_raise(rb_eArgError
, "encoding conversion is set");
8841 else if (fptr
->encs
.enc
&& fptr
->encs
.enc
!= rb_ascii8bit_encoding()) {
8842 rb_raise(rb_eArgError
, "encoding is set to %s already",
8843 rb_enc_name(fptr
->encs
.enc
));
8845 if (!io_set_encoding_by_bom(io
)) return Qnil
;
8846 return rb_enc_from_encoding(fptr
->encs
.enc
);
8851 * File.new(filename, mode="r" [, opt]) -> file
8852 * File.new(filename [, mode [, perm]] [, opt]) -> file
8854 * Opens the file named by +filename+ according to the given +mode+ and
8855 * returns a new File object.
8857 * See IO.new for a description of +mode+ and +opt+.
8859 * If a file is being created, permission bits may be given in +perm+. These
8860 * mode and permission bits are platform dependent; on Unix systems, see
8861 * open(2) and chmod(2) man pages for details.
8863 * The new File object is buffered mode (or non-sync mode), unless
8864 * +filename+ is a tty.
8865 * See IO#flush, IO#fsync, IO#fdatasync, and IO#sync= about sync mode.
8869 * f = File.new("testfile", "r")
8870 * f = File.new("newfile", "w+")
8871 * f = File.new("newfile", File::CREAT|File::TRUNC|File::RDWR, 0644)
8875 rb_file_initialize(int argc
, VALUE
*argv
, VALUE io
)
8877 if (RFILE(io
)->fptr
) {
8878 rb_raise(rb_eRuntimeError
, "reinitializing File");
8880 if (0 < argc
&& argc
< 3) {
8881 VALUE fd
= rb_check_to_int(argv
[0]);
8885 return rb_io_initialize(argc
, argv
, io
);
8888 rb_open_file(argc
, argv
, io
);
8895 rb_io_s_new(int argc
, VALUE
*argv
, VALUE klass
)
8897 if (rb_block_given_p()) {
8898 VALUE cname
= rb_obj_as_string(klass
);
8900 rb_warn("%"PRIsVALUE
"::new() does not take block; use %"PRIsVALUE
"::open() instead",
8903 return rb_class_new_instance_kw(argc
, argv
, klass
, RB_PASS_CALLED_KEYWORDS
);
8909 * IO.for_fd(fd, mode [, opt]) -> io
8911 * Synonym for IO.new.
8916 rb_io_s_for_fd(int argc
, VALUE
*argv
, VALUE klass
)
8918 VALUE io
= rb_obj_alloc(klass
);
8919 rb_io_initialize(argc
, argv
, io
);
8925 * ios.autoclose? -> true or false
8927 * Returns +true+ if the underlying file descriptor of _ios_ will be
8928 * closed automatically at its finalization, otherwise +false+.
8932 rb_io_autoclose_p(VALUE io
)
8934 rb_io_t
*fptr
= RFILE(io
)->fptr
;
8935 rb_io_check_closed(fptr
);
8936 return RBOOL(!(fptr
->mode
& FMODE_PREP
));
8941 * io.autoclose = bool -> true or false
8943 * Sets auto-close flag.
8945 * f = open("/dev/null")
8946 * IO.for_fd(f.fileno)
8948 * f.gets # may cause Errno::EBADF
8950 * f = open("/dev/null")
8951 * IO.for_fd(f.fileno).autoclose = false
8953 * f.gets # won't cause Errno::EBADF
8957 rb_io_set_autoclose(VALUE io
, VALUE autoclose
)
8960 GetOpenFile(io
, fptr
);
8961 if (!RTEST(autoclose
))
8962 fptr
->mode
|= FMODE_PREP
;
8964 fptr
->mode
&= ~FMODE_PREP
;
8969 argf_mark(void *ptr
)
8971 struct argf
*p
= ptr
;
8972 rb_gc_mark(p
->filename
);
8973 rb_gc_mark(p
->current_file
);
8974 rb_gc_mark(p
->argv
);
8975 rb_gc_mark(p
->inplace
);
8976 rb_gc_mark(p
->encs
.ecopts
);
8980 argf_memsize(const void *ptr
)
8982 const struct argf
*p
= ptr
;
8983 size_t size
= sizeof(*p
);
8987 static const rb_data_type_t argf_type
= {
8989 {argf_mark
, RUBY_TYPED_DEFAULT_FREE
, argf_memsize
},
8990 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
8994 argf_init(struct argf
*p
, VALUE v
)
8997 p
->current_file
= Qnil
;
9003 argf_alloc(VALUE klass
)
9006 VALUE argf
= TypedData_Make_Struct(klass
, struct argf
, &argf_type
, p
);
9016 argf_initialize(VALUE argf
, VALUE argv
)
9018 memset(&ARGF
, 0, sizeof(ARGF
));
9019 argf_init(&ARGF
, argv
);
9026 argf_initialize_copy(VALUE argf
, VALUE orig
)
9028 if (!OBJ_INIT_COPY(argf
, orig
)) return argf
;
9029 ARGF
= argf_of(orig
);
9030 ARGF
.argv
= rb_obj_dup(ARGF
.argv
);
9036 * ARGF.lineno = integer -> integer
9038 * Sets the line number of +ARGF+ as a whole to the given +Integer+.
9040 * +ARGF+ sets the line number automatically as you read data, so normally
9041 * you will not need to set it explicitly. To access the current line number
9042 * use +ARGF.lineno+.
9047 * ARGF.readline #=> "This is line 1\n"
9049 * ARGF.lineno = 0 #=> 0
9053 argf_set_lineno(VALUE argf
, VALUE val
)
9055 ARGF
.lineno
= NUM2INT(val
);
9056 ARGF
.last_lineno
= ARGF
.lineno
;
9062 * ARGF.lineno -> integer
9064 * Returns the current line number of ARGF as a whole. This value
9065 * can be set manually with +ARGF.lineno=+.
9070 * ARGF.readline #=> "This is line 1\n"
9074 argf_lineno(VALUE argf
)
9076 return INT2FIX(ARGF
.lineno
);
9080 argf_forward(int argc
, VALUE
*argv
, VALUE argf
)
9082 return forward_current(rb_frame_this_func(), argc
, argv
);
9085 #define next_argv() argf_next_argv(argf)
9086 #define ARGF_GENERIC_INPUT_P() \
9087 (ARGF.current_file == rb_stdin && !RB_TYPE_P(ARGF.current_file, T_FILE))
9088 #define ARGF_FORWARD(argc, argv) do {\
9089 if (ARGF_GENERIC_INPUT_P())\
9090 return argf_forward((argc), (argv), argf);\
9092 #define NEXT_ARGF_FORWARD(argc, argv) do {\
9093 if (!next_argv()) return Qnil;\
9094 ARGF_FORWARD((argc), (argv));\
9098 argf_close(VALUE argf
)
9100 VALUE file
= ARGF
.current_file
;
9101 if (file
== rb_stdin
) return;
9102 if (RB_TYPE_P(file
, T_FILE
)) {
9103 rb_io_set_write_io(file
, Qnil
);
9110 argf_next_argv(VALUE argf
)
9114 int stdout_binmode
= 0;
9117 VALUE r_stdout
= rb_ractor_stdout();
9119 if (RB_TYPE_P(r_stdout
, T_FILE
)) {
9120 GetOpenFile(r_stdout
, fptr
);
9121 if (fptr
->mode
& FMODE_BINMODE
)
9125 if (ARGF
.init_p
== 0) {
9126 if (!NIL_P(ARGF
.argv
) && RARRAY_LEN(ARGF
.argv
) > 0) {
9135 if (NIL_P(ARGF
.argv
)) {
9138 else if (ARGF
.next_p
== -1 && RARRAY_LEN(ARGF
.argv
) > 0) {
9143 if (ARGF
.next_p
== 1) {
9144 if (ARGF
.init_p
== 1) argf_close(argf
);
9146 if (RARRAY_LEN(ARGF
.argv
) > 0) {
9147 VALUE filename
= rb_ary_shift(ARGF
.argv
);
9148 FilePathValue(filename
);
9149 ARGF
.filename
= filename
;
9150 filename
= rb_str_encode_ospath(filename
);
9151 fn
= StringValueCStr(filename
);
9152 if (RSTRING_LEN(filename
) == 1 && fn
[0] == '-') {
9153 ARGF
.current_file
= rb_stdin
;
9155 rb_warn("Can't do inplace edit for stdio; skipping");
9160 VALUE write_io
= Qnil
;
9161 int fr
= rb_sysopen(filename
, O_RDONLY
, 0);
9165 #ifndef NO_SAFE_RENAME
9171 if (RB_TYPE_P(r_stdout
, T_FILE
) && r_stdout
!= orig_stdout
) {
9172 rb_io_close(r_stdout
);
9176 if (!NIL_P(ARGF
.inplace
)) {
9177 VALUE suffix
= ARGF
.inplace
;
9178 str
= rb_str_dup(str
);
9179 if (NIL_P(rb_str_cat_conv_enc_opts(str
, RSTRING_LEN(str
),
9180 RSTRING_PTR(suffix
), RSTRING_LEN(suffix
),
9181 rb_enc_get(suffix
), 0, Qnil
))) {
9182 rb_str_append(str
, suffix
);
9184 #ifdef NO_SAFE_RENAME
9186 (void)unlink(RSTRING_PTR(str
));
9187 if (rename(fn
, RSTRING_PTR(str
)) < 0) {
9188 rb_warn("Can't rename %"PRIsVALUE
" to %"PRIsVALUE
": %s, skipping file",
9189 filename
, str
, strerror(errno
));
9192 fr
= rb_sysopen(str
, O_RDONLY
, 0);
9194 if (rename(fn
, RSTRING_PTR(str
)) < 0) {
9195 rb_warn("Can't rename %"PRIsVALUE
" to %"PRIsVALUE
": %s, skipping file",
9196 filename
, str
, strerror(errno
));
9203 #ifdef NO_SAFE_RENAME
9204 rb_fatal("Can't do inplace edit without backup");
9206 if (unlink(fn
) < 0) {
9207 rb_warn("Can't remove %"PRIsVALUE
": %s, skipping file",
9208 filename
, strerror(errno
));
9214 fw
= rb_sysopen(filename
, O_WRONLY
|O_CREAT
|O_TRUNC
, 0666);
9215 #ifndef NO_SAFE_RENAME
9218 fchmod(fw
, st
.st_mode
);
9220 chmod(fn
, st
.st_mode
);
9222 if (st
.st_uid
!=st2
.st_uid
|| st
.st_gid
!=st2
.st_gid
) {
9225 err
= fchown(fw
, st
.st_uid
, st
.st_gid
);
9227 err
= chown(fn
, st
.st_uid
, st
.st_gid
);
9229 if (err
&& getuid() == 0 && st2
.st_uid
== 0) {
9230 const char *wkfn
= RSTRING_PTR(filename
);
9231 rb_warn("Can't set owner/group of %"PRIsVALUE
" to same as %"PRIsVALUE
": %s, skipping file",
9232 filename
, str
, strerror(errno
));
9240 write_io
= prep_io(fw
, FMODE_WRITABLE
, rb_cFile
, fn
);
9241 rb_ractor_stdout_set(write_io
);
9242 if (stdout_binmode
) rb_io_binmode(rb_stdout
);
9244 fmode
= FMODE_READABLE
;
9245 if (!ARGF
.binmode
) {
9246 fmode
|= DEFAULT_TEXTMODE
;
9248 ARGF
.current_file
= prep_io(fr
, fmode
, rb_cFile
, fn
);
9249 if (!NIL_P(write_io
)) {
9250 rb_io_set_write_io(ARGF
.current_file
, write_io
);
9252 RB_GC_GUARD(filename
);
9254 if (ARGF
.binmode
) rb_io_ascii8bit_binmode(ARGF
.current_file
);
9255 GetOpenFile(ARGF
.current_file
, fptr
);
9256 if (ARGF
.encs
.enc
) {
9257 fptr
->encs
= ARGF
.encs
;
9258 clear_codeconv(fptr
);
9261 fptr
->encs
.ecflags
&= ~ECONV_NEWLINE_DECORATOR_MASK
;
9262 if (!ARGF
.binmode
) {
9263 fptr
->encs
.ecflags
|= ECONV_DEFAULT_NEWLINE_DECORATOR
;
9264 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
9265 fptr
->encs
.ecflags
|= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
;
9276 else if (ARGF
.next_p
== -1) {
9277 ARGF
.current_file
= rb_stdin
;
9278 ARGF
.filename
= rb_str_new2("-");
9280 rb_warn("Can't do inplace edit for stdio");
9281 rb_ractor_stdout_set(orig_stdout
);
9284 if (ARGF
.init_p
== -1) ARGF
.init_p
= 1;
9289 argf_getline(int argc
, VALUE
*argv
, VALUE argf
)
9292 long lineno
= ARGF
.lineno
;
9295 if (!next_argv()) return Qnil
;
9296 if (ARGF_GENERIC_INPUT_P()) {
9297 line
= forward_current(idGets
, argc
, argv
);
9300 if (argc
== 0 && rb_rs
== rb_default_rs
) {
9301 line
= rb_io_gets(ARGF
.current_file
);
9304 line
= rb_io_getline(argc
, argv
, ARGF
.current_file
);
9306 if (NIL_P(line
) && ARGF
.next_p
!= -1) {
9313 ARGF
.lineno
= ++lineno
;
9314 ARGF
.last_lineno
= ARGF
.lineno
;
9320 argf_lineno_getter(ID id
, VALUE
*var
)
9323 return INT2FIX(ARGF
.last_lineno
);
9327 argf_lineno_setter(VALUE val
, ID id
, VALUE
*var
)
9330 int n
= NUM2INT(val
);
9331 ARGF
.last_lineno
= ARGF
.lineno
= n
;
9334 static VALUE
argf_gets(int, VALUE
*, VALUE
);
9338 * gets(sep=$/ [, getline_args]) -> string or nil
9339 * gets(limit [, getline_args]) -> string or nil
9340 * gets(sep, limit [, getline_args]) -> string or nil
9342 * Returns (and assigns to <code>$_</code>) the next line from the list
9343 * of files in +ARGV+ (or <code>$*</code>), or from standard input if
9344 * no files are present on the command line. Returns +nil+ at end of
9345 * file. The optional argument specifies the record separator. The
9346 * separator is included with the contents of each record. A separator
9347 * of +nil+ reads the entire contents, and a zero-length separator
9348 * reads the input one paragraph at a time, where paragraphs are
9349 * divided by two consecutive newlines. If the first argument is an
9350 * integer, or optional second argument is given, the returning string
9351 * would not be longer than the given value in bytes. If multiple
9352 * filenames are present in +ARGV+, <code>gets(nil)</code> will read
9353 * the contents one file at a time.
9355 * ARGV << "testfile"
9358 * <em>produces:</em>
9362 * This is line three
9365 * The style of programming using <code>$_</code> as an implicit
9366 * parameter is gradually losing favor in the Ruby community.
9370 rb_f_gets(int argc
, VALUE
*argv
, VALUE recv
)
9373 return argf_gets(argc
, argv
, argf
);
9375 return forward(argf
, idGets
, argc
, argv
);
9380 * ARGF.gets(sep=$/ [, getline_args]) -> string or nil
9381 * ARGF.gets(limit [, getline_args]) -> string or nil
9382 * ARGF.gets(sep, limit [, getline_args]) -> string or nil
9384 * Returns the next line from the current file in +ARGF+.
9386 * By default lines are assumed to be separated by <code>$/</code>;
9387 * to use a different character as a separator, supply it as a +String+
9388 * for the _sep_ argument.
9390 * The optional _limit_ argument specifies how many characters of each line
9391 * to return. By default all characters are returned.
9393 * See IO.readlines for details about getline_args.
9397 argf_gets(int argc
, VALUE
*argv
, VALUE argf
)
9401 line
= argf_getline(argc
, argv
, argf
);
9402 rb_lastline_set(line
);
9412 if (rb_rs
!= rb_default_rs
) {
9413 return rb_f_gets(0, 0, argf
);
9417 if (!next_argv()) return Qnil
;
9418 line
= rb_io_gets(ARGF
.current_file
);
9419 if (NIL_P(line
) && ARGF
.next_p
!= -1) {
9420 rb_io_close(ARGF
.current_file
);
9424 rb_lastline_set(line
);
9427 ARGF
.last_lineno
= ARGF
.lineno
;
9433 static VALUE
argf_readline(int, VALUE
*, VALUE
);
9437 * readline(sep=$/) -> string
9438 * readline(limit) -> string
9439 * readline(sep, limit) -> string
9441 * Equivalent to Kernel::gets, except
9442 * +readline+ raises +EOFError+ at end of file.
9446 rb_f_readline(int argc
, VALUE
*argv
, VALUE recv
)
9449 return argf_readline(argc
, argv
, argf
);
9451 return forward(argf
, rb_intern("readline"), argc
, argv
);
9457 * ARGF.readline(sep=$/) -> string
9458 * ARGF.readline(limit) -> string
9459 * ARGF.readline(sep, limit) -> string
9461 * Returns the next line from the current file in +ARGF+.
9463 * By default lines are assumed to be separated by <code>$/</code>;
9464 * to use a different character as a separator, supply it as a +String+
9465 * for the _sep_ argument.
9467 * The optional _limit_ argument specifies how many characters of each line
9468 * to return. By default all characters are returned.
9470 * An +EOFError+ is raised at the end of the file.
9473 argf_readline(int argc
, VALUE
*argv
, VALUE argf
)
9477 if (!next_argv()) rb_eof_error();
9478 ARGF_FORWARD(argc
, argv
);
9479 line
= argf_gets(argc
, argv
, argf
);
9487 static VALUE
argf_readlines(int, VALUE
*, VALUE
);
9491 * readlines(sep=$/) -> array
9492 * readlines(limit) -> array
9493 * readlines(sep, limit) -> array
9495 * Returns an array containing the lines returned by calling
9496 * <code>Kernel.gets(<i>sep</i>)</code> until the end of file.
9500 rb_f_readlines(int argc
, VALUE
*argv
, VALUE recv
)
9503 return argf_readlines(argc
, argv
, argf
);
9505 return forward(argf
, rb_intern("readlines"), argc
, argv
);
9510 * ARGF.readlines(sep=$/) -> array
9511 * ARGF.readlines(limit) -> array
9512 * ARGF.readlines(sep, limit) -> array
9514 * ARGF.to_a(sep=$/) -> array
9515 * ARGF.to_a(limit) -> array
9516 * ARGF.to_a(sep, limit) -> array
9518 * Reads +ARGF+'s current file in its entirety, returning an +Array+ of its
9519 * lines, one line per element. Lines are assumed to be separated by _sep_.
9521 * lines = ARGF.readlines
9522 * lines[0] #=> "This is line one\n"
9525 argf_readlines(int argc
, VALUE
*argv
, VALUE argf
)
9527 long lineno
= ARGF
.lineno
;
9531 while (next_argv()) {
9532 if (ARGF_GENERIC_INPUT_P()) {
9533 lines
= forward_current(rb_intern("readlines"), argc
, argv
);
9536 lines
= rb_io_readlines(argc
, argv
, ARGF
.current_file
);
9540 rb_ary_concat(ary
, lines
);
9541 ARGF
.lineno
= lineno
+ RARRAY_LEN(ary
);
9542 ARGF
.last_lineno
= ARGF
.lineno
;
9552 * Returns the standard output of running _cmd_ in a subshell.
9553 * The built-in syntax <code>%x{...}</code> uses
9554 * this method. Sets <code>$?</code> to the process status.
9556 * `date` #=> "Wed Apr 9 08:56:30 CDT 2003\n"
9557 * `ls testdir`.split[1] #=> "main.rb"
9558 * `echo oops && exit 99` #=> "oops\n"
9559 * $?.exitstatus #=> 99
9563 rb_f_backquote(VALUE obj
, VALUE str
)
9569 SafeStringValue(str
);
9570 rb_last_status_clear();
9571 port
= pipe_open_s(str
, "r", FMODE_READABLE
|DEFAULT_TEXTMODE
, NULL
);
9572 if (NIL_P(port
)) return rb_str_new(0,0);
9574 GetOpenFile(port
, fptr
);
9575 result
= read_all(fptr
, remain_size(fptr
), Qnil
);
9577 RFILE(port
)->fptr
= NULL
;
9578 rb_io_fptr_finalize(fptr
);
9584 #ifdef HAVE_SYS_SELECT_H
9585 #include <sys/select.h>
9589 select_internal(VALUE read
, VALUE write
, VALUE except
, struct timeval
*tp
, rb_fdset_t
*fds
)
9592 rb_fdset_t
*rp
, *wp
, *ep
;
9597 struct timeval timerec
;
9600 Check_Type(read
, T_ARRAY
);
9601 for (i
=0; i
<RARRAY_LEN(read
); i
++) {
9602 GetOpenFile(rb_io_get_io(RARRAY_AREF(read
, i
)), fptr
);
9603 rb_fd_set(fptr
->fd
, &fds
[0]);
9604 if (READ_DATA_PENDING(fptr
) || READ_CHAR_PENDING(fptr
)) { /* check for buffered data */
9606 rb_fd_set(fptr
->fd
, &fds
[3]);
9608 if (max
< fptr
->fd
) max
= fptr
->fd
;
9610 if (pending
) { /* no blocking if there's buffered data */
9611 timerec
.tv_sec
= timerec
.tv_usec
= 0;
9619 if (!NIL_P(write
)) {
9620 Check_Type(write
, T_ARRAY
);
9621 for (i
=0; i
<RARRAY_LEN(write
); i
++) {
9622 VALUE write_io
= GetWriteIO(rb_io_get_io(RARRAY_AREF(write
, i
)));
9623 GetOpenFile(write_io
, fptr
);
9624 rb_fd_set(fptr
->fd
, &fds
[1]);
9625 if (max
< fptr
->fd
) max
= fptr
->fd
;
9632 if (!NIL_P(except
)) {
9633 Check_Type(except
, T_ARRAY
);
9634 for (i
=0; i
<RARRAY_LEN(except
); i
++) {
9635 VALUE io
= rb_io_get_io(RARRAY_AREF(except
, i
));
9636 VALUE write_io
= GetWriteIO(io
);
9637 GetOpenFile(io
, fptr
);
9638 rb_fd_set(fptr
->fd
, &fds
[2]);
9639 if (max
< fptr
->fd
) max
= fptr
->fd
;
9640 if (io
!= write_io
) {
9641 GetOpenFile(write_io
, fptr
);
9642 rb_fd_set(fptr
->fd
, &fds
[2]);
9643 if (max
< fptr
->fd
) max
= fptr
->fd
;
9654 n
= rb_thread_fd_select(max
, rp
, wp
, ep
, tp
);
9658 if (!pending
&& n
== 0) return Qnil
; /* returns nil on timeout */
9660 res
= rb_ary_new2(3);
9661 rb_ary_push(res
, rp
?rb_ary_new():rb_ary_new2(0));
9662 rb_ary_push(res
, wp
?rb_ary_new():rb_ary_new2(0));
9663 rb_ary_push(res
, ep
?rb_ary_new():rb_ary_new2(0));
9666 list
= RARRAY_AREF(res
, 0);
9667 for (i
=0; i
< RARRAY_LEN(read
); i
++) {
9668 VALUE obj
= rb_ary_entry(read
, i
);
9669 VALUE io
= rb_io_get_io(obj
);
9670 GetOpenFile(io
, fptr
);
9671 if (rb_fd_isset(fptr
->fd
, &fds
[0]) ||
9672 rb_fd_isset(fptr
->fd
, &fds
[3])) {
9673 rb_ary_push(list
, obj
);
9679 list
= RARRAY_AREF(res
, 1);
9680 for (i
=0; i
< RARRAY_LEN(write
); i
++) {
9681 VALUE obj
= rb_ary_entry(write
, i
);
9682 VALUE io
= rb_io_get_io(obj
);
9683 VALUE write_io
= GetWriteIO(io
);
9684 GetOpenFile(write_io
, fptr
);
9685 if (rb_fd_isset(fptr
->fd
, &fds
[1])) {
9686 rb_ary_push(list
, obj
);
9692 list
= RARRAY_AREF(res
, 2);
9693 for (i
=0; i
< RARRAY_LEN(except
); i
++) {
9694 VALUE obj
= rb_ary_entry(except
, i
);
9695 VALUE io
= rb_io_get_io(obj
);
9696 VALUE write_io
= GetWriteIO(io
);
9697 GetOpenFile(io
, fptr
);
9698 if (rb_fd_isset(fptr
->fd
, &fds
[2])) {
9699 rb_ary_push(list
, obj
);
9701 else if (io
!= write_io
) {
9702 GetOpenFile(write_io
, fptr
);
9703 if (rb_fd_isset(fptr
->fd
, &fds
[2])) {
9704 rb_ary_push(list
, obj
);
9710 return res
; /* returns an empty array on interrupt */
9713 struct select_args
{
9714 VALUE read
, write
, except
;
9715 struct timeval
*timeout
;
9716 rb_fdset_t fdsets
[4];
9720 select_call(VALUE arg
)
9722 struct select_args
*p
= (struct select_args
*)arg
;
9724 return select_internal(p
->read
, p
->write
, p
->except
, p
->timeout
, p
->fdsets
);
9728 select_end(VALUE arg
)
9730 struct select_args
*p
= (struct select_args
*)arg
;
9733 for (i
= 0; i
< numberof(p
->fdsets
); ++i
)
9734 rb_fd_term(&p
->fdsets
[i
]);
9738 static VALUE sym_normal
, sym_sequential
, sym_random
,
9739 sym_willneed
, sym_dontneed
, sym_noreuse
;
9741 #ifdef HAVE_POSIX_FADVISE
9742 struct io_advise_struct
{
9750 io_advise_internal(void *arg
)
9752 struct io_advise_struct
*ptr
= arg
;
9753 return posix_fadvise(ptr
->fd
, ptr
->offset
, ptr
->len
, ptr
->advice
);
9757 io_advise_sym_to_const(VALUE sym
)
9759 #ifdef POSIX_FADV_NORMAL
9760 if (sym
== sym_normal
)
9761 return INT2NUM(POSIX_FADV_NORMAL
);
9764 #ifdef POSIX_FADV_RANDOM
9765 if (sym
== sym_random
)
9766 return INT2NUM(POSIX_FADV_RANDOM
);
9769 #ifdef POSIX_FADV_SEQUENTIAL
9770 if (sym
== sym_sequential
)
9771 return INT2NUM(POSIX_FADV_SEQUENTIAL
);
9774 #ifdef POSIX_FADV_WILLNEED
9775 if (sym
== sym_willneed
)
9776 return INT2NUM(POSIX_FADV_WILLNEED
);
9779 #ifdef POSIX_FADV_DONTNEED
9780 if (sym
== sym_dontneed
)
9781 return INT2NUM(POSIX_FADV_DONTNEED
);
9784 #ifdef POSIX_FADV_NOREUSE
9785 if (sym
== sym_noreuse
)
9786 return INT2NUM(POSIX_FADV_NOREUSE
);
9793 do_io_advise(rb_io_t
*fptr
, VALUE advice
, off_t offset
, off_t len
)
9796 struct io_advise_struct ias
;
9799 num_adv
= io_advise_sym_to_const(advice
);
9802 * The platform doesn't support this hint. We don't raise exception, instead
9803 * silently ignore it. Because IO::advise is only hint.
9809 ias
.advice
= NUM2INT(num_adv
);
9810 ias
.offset
= offset
;
9813 rv
= (int)rb_thread_io_blocking_region(io_advise_internal
, &ias
, fptr
->fd
);
9814 if (rv
&& rv
!= ENOSYS
) {
9815 /* posix_fadvise(2) doesn't set errno. On success it returns 0; otherwise
9816 it returns the error code. */
9817 VALUE message
= rb_sprintf("%"PRIsVALUE
" "
9818 "(%"PRI_OFFT_PREFIX
"d, "
9819 "%"PRI_OFFT_PREFIX
"d, "
9821 fptr
->pathv
, offset
, len
, advice
);
9822 rb_syserr_fail_str(rv
, message
);
9828 #endif /* HAVE_POSIX_FADVISE */
9831 advice_arg_check(VALUE advice
)
9833 if (!SYMBOL_P(advice
))
9834 rb_raise(rb_eTypeError
, "advice must be a Symbol");
9836 if (advice
!= sym_normal
&&
9837 advice
!= sym_sequential
&&
9838 advice
!= sym_random
&&
9839 advice
!= sym_willneed
&&
9840 advice
!= sym_dontneed
&&
9841 advice
!= sym_noreuse
) {
9842 rb_raise(rb_eNotImpError
, "Unsupported advice: %+"PRIsVALUE
, advice
);
9848 * ios.advise(advice, offset=0, len=0) -> nil
9850 * Announce an intention to access data from the current file in a
9851 * specific pattern. On platforms that do not support the
9852 * <em>posix_fadvise(2)</em> system call, this method is a no-op.
9854 * _advice_ is one of the following symbols:
9856 * :normal:: No advice to give; the default assumption for an open file.
9857 * :sequential:: The data will be accessed sequentially
9858 * with lower offsets read before higher ones.
9859 * :random:: The data will be accessed in random order.
9860 * :willneed:: The data will be accessed in the near future.
9861 * :dontneed:: The data will not be accessed in the near future.
9862 * :noreuse:: The data will only be accessed once.
9864 * The semantics of a piece of advice are platform-dependent. See
9865 * <em>man 2 posix_fadvise</em> for details.
9867 * "data" means the region of the current file that begins at
9868 * _offset_ and extends for _len_ bytes. If _len_ is 0, the region
9869 * ends at the last byte of the file. By default, both _offset_ and
9870 * _len_ are 0, meaning that the advice applies to the entire file.
9872 * If an error occurs, one of the following exceptions will be raised:
9874 * IOError:: The IO stream is closed.
9876 * The file descriptor of the current file is invalid.
9877 * Errno::EINVAL:: An invalid value for _advice_ was given.
9879 * The file descriptor of the current file refers to a FIFO or
9880 * pipe. (Linux raises Errno::EINVAL in this case).
9882 * Either _advice_ was not a Symbol, or one of the
9883 * other arguments was not an Integer.
9884 * RangeError:: One of the arguments given was too big/small.
9886 * This list is not exhaustive; other Errno:: exceptions are also possible.
9889 rb_io_advise(int argc
, VALUE
*argv
, VALUE io
)
9891 VALUE advice
, offset
, len
;
9895 rb_scan_args(argc
, argv
, "12", &advice
, &offset
, &len
);
9896 advice_arg_check(advice
);
9898 io
= GetWriteIO(io
);
9899 GetOpenFile(io
, fptr
);
9901 off
= NIL_P(offset
) ? 0 : NUM2OFFT(offset
);
9902 l
= NIL_P(len
) ? 0 : NUM2OFFT(len
);
9904 #ifdef HAVE_POSIX_FADVISE
9905 return do_io_advise(fptr
, advice
, off
, l
);
9907 ((void)off
, (void)l
); /* Ignore all hint */
9914 * IO.select(read_array [, write_array [, error_array [, timeout]]]) -> array or nil
9916 * Calls select(2) system call.
9917 * It monitors given arrays of IO objects, waits until one or more of
9918 * IO objects are ready for reading, are ready for writing, and have
9919 * pending exceptions respectively, and returns an array that contains
9920 * arrays of those IO objects. It will return +nil+ if optional
9921 * <i>timeout</i> value is given and no IO object is ready in
9922 * <i>timeout</i> seconds.
9924 * IO.select peeks the buffer of IO objects for testing readability.
9925 * If the IO buffer is not empty, IO.select immediately notifies
9926 * readability. This "peek" only happens for IO objects. It does not
9927 * happen for IO-like objects such as OpenSSL::SSL::SSLSocket.
9929 * The best way to use IO.select is invoking it after nonblocking
9930 * methods such as #read_nonblock, #write_nonblock, etc. The methods
9931 * raise an exception which is extended by IO::WaitReadable or
9932 * IO::WaitWritable. The modules notify how the caller should wait
9933 * with IO.select. If IO::WaitReadable is raised, the caller should
9934 * wait for reading. If IO::WaitWritable is raised, the caller should
9937 * So, blocking read (#readpartial) can be emulated using
9938 * #read_nonblock and IO.select as follows:
9941 * result = io_like.read_nonblock(maxlen)
9942 * rescue IO::WaitReadable
9943 * IO.select([io_like])
9945 * rescue IO::WaitWritable
9946 * IO.select(nil, [io_like])
9950 * Especially, the combination of nonblocking methods and IO.select is
9951 * preferred for IO like objects such as OpenSSL::SSL::SSLSocket. It
9952 * has #to_io method to return underlying IO object. IO.select calls
9953 * #to_io to obtain the file descriptor to wait.
9955 * This means that readability notified by IO.select doesn't mean
9956 * readability from OpenSSL::SSL::SSLSocket object.
9958 * The most likely situation is that OpenSSL::SSL::SSLSocket buffers
9959 * some data. IO.select doesn't see the buffer. So IO.select can
9960 * block when OpenSSL::SSL::SSLSocket#readpartial doesn't block.
9962 * However, several more complicated situations exist.
9964 * SSL is a protocol which is sequence of records.
9965 * The record consists of multiple bytes.
9966 * So, the remote side of SSL sends a partial record, IO.select
9967 * notifies readability but OpenSSL::SSL::SSLSocket cannot decrypt a
9968 * byte and OpenSSL::SSL::SSLSocket#readpartial will block.
9970 * Also, the remote side can request SSL renegotiation which forces
9971 * the local SSL engine to write some data.
9972 * This means OpenSSL::SSL::SSLSocket#readpartial may invoke #write
9973 * system call and it can block.
9974 * In such a situation, OpenSSL::SSL::SSLSocket#read_nonblock raises
9975 * IO::WaitWritable instead of blocking.
9976 * So, the caller should wait for ready for writability as above
9979 * The combination of nonblocking methods and IO.select is also useful
9980 * for streams such as tty, pipe socket socket when multiple processes
9981 * read from a stream.
9983 * Finally, Linux kernel developers don't guarantee that
9984 * readability of select(2) means readability of following read(2) even
9985 * for a single process.
9986 * See select(2) manual on GNU/Linux system.
9988 * Invoking IO.select before IO#readpartial works well as usual.
9989 * However it is not the best way to use IO.select.
9991 * The writability notified by select(2) doesn't show
9992 * how many bytes are writable.
9993 * IO#write method blocks until given whole string is written.
9994 * So, <code>IO#write(two or more bytes)</code> can block after
9995 * writability is notified by IO.select. IO#write_nonblock is required
9996 * to avoid the blocking.
9998 * Blocking write (#write) can be emulated using #write_nonblock and
9999 * IO.select as follows: IO::WaitReadable should also be rescued for
10000 * SSL renegotiation in OpenSSL::SSL::SSLSocket.
10002 * while 0 < string.bytesize
10004 * written = io_like.write_nonblock(string)
10005 * rescue IO::WaitReadable
10006 * IO.select([io_like])
10008 * rescue IO::WaitWritable
10009 * IO.select(nil, [io_like])
10012 * string = string.byteslice(written..-1)
10016 * read_array:: an array of IO objects that wait until ready for read
10017 * write_array:: an array of IO objects that wait until ready for write
10018 * error_array:: an array of IO objects that wait for exceptions
10019 * timeout:: a numeric value in second
10026 * # IO.select follows IO#read. Not the best way to use IO.select.
10027 * rs, ws, = IO.select([rp], [wp])
10043 * <em>produces:</em>
10053 rb_f_select(int argc
, VALUE
*argv
, VALUE obj
)
10056 struct select_args args
;
10057 struct timeval timerec
;
10060 rb_scan_args(argc
, argv
, "13", &args
.read
, &args
.write
, &args
.except
, &timeout
);
10061 if (NIL_P(timeout
)) {
10065 timerec
= rb_time_interval(timeout
);
10066 args
.timeout
= &timerec
;
10069 for (i
= 0; i
< numberof(args
.fdsets
); ++i
)
10070 rb_fd_init(&args
.fdsets
[i
]);
10072 return rb_ensure(select_call
, (VALUE
)&args
, select_end
, (VALUE
)&args
);
10075 #ifdef IOCTL_REQ_TYPE
10076 typedef IOCTL_REQ_TYPE ioctl_req_t
;
10078 typedef int ioctl_req_t
;
10079 # define NUM2IOCTLREQ(num) ((int)NUM2LONG(num))
10090 nogvl_ioctl(void *ptr
)
10092 struct ioctl_arg
*arg
= ptr
;
10094 return (VALUE
)ioctl(arg
->fd
, arg
->cmd
, arg
->narg
);
10098 do_ioctl(int fd
, ioctl_req_t cmd
, long narg
)
10101 struct ioctl_arg arg
;
10107 retval
= (int)rb_thread_io_blocking_region(nogvl_ioctl
, &arg
, fd
);
10113 #define DEFAULT_IOCTL_NARG_LEN (256)
10115 #if defined(__linux__) && defined(_IOC_SIZE)
10117 linux_iocparm_len(ioctl_req_t cmd
)
10121 if ((cmd
& 0xFFFF0000) == 0) {
10122 /* legacy and unstructured ioctl number. */
10123 return DEFAULT_IOCTL_NARG_LEN
;
10126 len
= _IOC_SIZE(cmd
);
10128 /* paranoia check for silly drivers which don't keep ioctl convention */
10129 if (len
< DEFAULT_IOCTL_NARG_LEN
)
10130 len
= DEFAULT_IOCTL_NARG_LEN
;
10138 ioctl_narg_len(ioctl_req_t cmd
)
10142 #ifdef IOCPARM_MASK
10143 #ifndef IOCPARM_LEN
10144 #define IOCPARM_LEN(x) (((x) >> 16) & IOCPARM_MASK)
10148 len
= IOCPARM_LEN(cmd
); /* on BSDish systems we're safe */
10149 #elif defined(__linux__) && defined(_IOC_SIZE)
10150 len
= linux_iocparm_len(cmd
);
10152 /* otherwise guess at what's safe */
10153 len
= DEFAULT_IOCTL_NARG_LEN
;
10162 typedef long fcntl_arg_t
;
10165 typedef int fcntl_arg_t
;
10169 fcntl_narg_len(ioctl_req_t cmd
)
10176 len
= sizeof(fcntl_arg_t
);
10179 #ifdef F_DUP2FD /* bsd specific */
10184 #ifdef F_DUPFD_CLOEXEC /* linux specific */
10185 case F_DUPFD_CLOEXEC
:
10186 len
= sizeof(fcntl_arg_t
);
10196 len
= sizeof(fcntl_arg_t
);
10206 len
= sizeof(fcntl_arg_t
);
10216 len
= sizeof(fcntl_arg_t
);
10219 #ifdef F_GETOWN_EX /* linux specific */
10221 len
= sizeof(struct f_owner_ex
);
10224 #ifdef F_SETOWN_EX /* linux specific */
10226 len
= sizeof(struct f_owner_ex
);
10231 len
= sizeof(struct flock
);
10236 len
= sizeof(struct flock
);
10241 len
= sizeof(struct flock
);
10244 #ifdef F_READAHEAD /* bsd specific */
10249 #ifdef F_RDAHEAD /* Darwin specific */
10254 #ifdef F_GETSIG /* linux specific */
10259 #ifdef F_SETSIG /* linux specific */
10261 len
= sizeof(fcntl_arg_t
);
10264 #ifdef F_GETLEASE /* linux specific */
10269 #ifdef F_SETLEASE /* linux specific */
10271 len
= sizeof(fcntl_arg_t
);
10274 #ifdef F_NOTIFY /* linux specific */
10276 len
= sizeof(fcntl_arg_t
);
10287 #else /* HAVE_FCNTL */
10289 fcntl_narg_len(ioctl_req_t cmd
)
10293 #endif /* HAVE_FCNTL */
10295 #define NARG_SENTINEL 17
10298 setup_narg(ioctl_req_t cmd
, VALUE
*argp
, long (*narg_len
)(ioctl_req_t
))
10306 else if (FIXNUM_P(arg
)) {
10307 narg
= FIX2LONG(arg
);
10309 else if (arg
== Qtrue
) {
10313 VALUE tmp
= rb_check_string_type(arg
);
10316 narg
= NUM2LONG(arg
);
10323 len
= narg_len(cmd
);
10324 rb_str_modify(arg
);
10326 slen
= RSTRING_LEN(arg
);
10327 /* expand for data + sentinel. */
10328 if (slen
< len
+1) {
10329 rb_str_resize(arg
, len
+1);
10330 MEMZERO(RSTRING_PTR(arg
)+slen
, char, len
-slen
);
10333 /* a little sanity check here */
10334 ptr
= RSTRING_PTR(arg
);
10335 ptr
[slen
- 1] = NARG_SENTINEL
;
10336 narg
= (long)(SIGNED_VALUE
)ptr
;
10344 finish_narg(int retval
, VALUE arg
, const rb_io_t
*fptr
)
10346 if (retval
< 0) rb_sys_fail_path(fptr
->pathv
);
10347 if (RB_TYPE_P(arg
, T_STRING
)) {
10350 RSTRING_GETMEM(arg
, ptr
, slen
);
10351 if (ptr
[slen
-1] != NARG_SENTINEL
)
10352 rb_raise(rb_eArgError
, "return value overflowed string");
10353 ptr
[slen
-1] = '\0';
10356 return INT2NUM(retval
);
10361 rb_ioctl(VALUE io
, VALUE req
, VALUE arg
)
10363 ioctl_req_t cmd
= NUM2IOCTLREQ(req
);
10368 narg
= setup_narg(cmd
, &arg
, ioctl_narg_len
);
10369 GetOpenFile(io
, fptr
);
10370 retval
= do_ioctl(fptr
->fd
, cmd
, narg
);
10371 return finish_narg(retval
, arg
, fptr
);
10376 * ios.ioctl(integer_cmd, arg) -> integer
10378 * Provides a mechanism for issuing low-level commands to control or
10379 * query I/O devices. Arguments and results are platform dependent. If
10380 * <i>arg</i> is a number, its value is passed directly. If it is a
10381 * string, it is interpreted as a binary sequence of bytes. On Unix
10382 * platforms, see <code>ioctl(2)</code> for details. Not implemented on
10387 rb_io_ioctl(int argc
, VALUE
*argv
, VALUE io
)
10391 rb_scan_args(argc
, argv
, "11", &req
, &arg
);
10392 return rb_ioctl(io
, req
, arg
);
10395 #define rb_io_ioctl rb_f_notimplement
10406 nogvl_fcntl(void *ptr
)
10408 struct fcntl_arg
*arg
= ptr
;
10410 #if defined(F_DUPFD)
10411 if (arg
->cmd
== F_DUPFD
)
10412 return (VALUE
)rb_cloexec_fcntl_dupfd(arg
->fd
, (int)arg
->narg
);
10414 return (VALUE
)fcntl(arg
->fd
, arg
->cmd
, arg
->narg
);
10418 do_fcntl(int fd
, int cmd
, long narg
)
10421 struct fcntl_arg arg
;
10427 retval
= (int)rb_thread_io_blocking_region(nogvl_fcntl
, &arg
, fd
);
10428 if (retval
!= -1) {
10430 #if defined(F_DUPFD)
10433 #if defined(F_DUPFD_CLOEXEC)
10434 case F_DUPFD_CLOEXEC
:
10436 rb_update_max_fd(retval
);
10444 rb_fcntl(VALUE io
, VALUE req
, VALUE arg
)
10446 int cmd
= NUM2INT(req
);
10451 narg
= setup_narg(cmd
, &arg
, fcntl_narg_len
);
10452 GetOpenFile(io
, fptr
);
10453 retval
= do_fcntl(fptr
->fd
, cmd
, narg
);
10454 return finish_narg(retval
, arg
, fptr
);
10459 * ios.fcntl(integer_cmd, arg) -> integer
10461 * Provides a mechanism for issuing low-level commands to control or
10462 * query file-oriented I/O streams. Arguments and results are platform
10463 * dependent. If <i>arg</i> is a number, its value is passed
10464 * directly. If it is a string, it is interpreted as a binary sequence
10465 * of bytes (Array#pack might be a useful way to build this string). On
10466 * Unix platforms, see <code>fcntl(2)</code> for details. Not
10467 * implemented on all platforms.
10471 rb_io_fcntl(int argc
, VALUE
*argv
, VALUE io
)
10475 rb_scan_args(argc
, argv
, "11", &req
, &arg
);
10476 return rb_fcntl(io
, req
, arg
);
10479 #define rb_io_fcntl rb_f_notimplement
10482 #if defined(HAVE_SYSCALL) || defined(HAVE___SYSCALL)
10485 * syscall(num [, args...]) -> integer
10487 * Calls the operating system function identified by _num_ and
10488 * returns the result of the function or raises SystemCallError if
10491 * Arguments for the function can follow _num_. They must be either
10492 * +String+ objects or +Integer+ objects. A +String+ object is passed
10493 * as a pointer to the byte sequence. An +Integer+ object is passed
10494 * as an integer whose bit size is the same as a pointer.
10495 * Up to nine parameters may be passed.
10497 * The function identified by _num_ is system
10498 * dependent. On some Unix systems, the numbers may be obtained from a
10499 * header file called <code>syscall.h</code>.
10501 * syscall 4, 1, "hello\n", 6 # '4' is write(2) on our box
10503 * <em>produces:</em>
10507 * Calling +syscall+ on a platform which does not have any way to
10508 * an arbitrary system function just fails with NotImplementedError.
10511 * +syscall+ is essentially unsafe and unportable.
10512 * Feel free to shoot your foot.
10513 * The DL (Fiddle) library is preferred for safer and a bit
10514 * more portable programming.
10518 rb_f_syscall(int argc
, VALUE
*argv
, VALUE _
)
10521 #if SIZEOF_VOIDP == 8 && defined(HAVE___SYSCALL) && SIZEOF_INT != 8 /* mainly *BSD */
10522 # define SYSCALL __syscall
10523 # define NUM2SYSCALLID(x) NUM2LONG(x)
10524 # define RETVAL2NUM(x) LONG2NUM(x)
10525 # if SIZEOF_LONG == 8
10526 long num
, retval
= -1;
10527 # elif SIZEOF_LONG_LONG == 8
10528 long long num
, retval
= -1;
10530 # error ---->> it is asserted that __syscall takes the first argument and returns retval in 64bit signed integer. <<----
10532 #elif defined(__linux__)
10533 # define SYSCALL syscall
10534 # define NUM2SYSCALLID(x) NUM2LONG(x)
10535 # define RETVAL2NUM(x) LONG2NUM(x)
10537 * Linux man page says, syscall(2) function prototype is below.
10539 * int syscall(int number, ...);
10541 * But, it's incorrect. Actual one takes and returned long. (see unistd.h)
10543 long num
, retval
= -1;
10545 # define SYSCALL syscall
10546 # define NUM2SYSCALLID(x) NUM2INT(x)
10547 # define RETVAL2NUM(x) INT2NUM(x)
10548 int num
, retval
= -1;
10552 if (RTEST(ruby_verbose
)) {
10553 rb_category_warning(RB_WARN_CATEGORY_DEPRECATED
,
10554 "We plan to remove a syscall function at future release. DL(Fiddle) provides safer alternative.");
10558 rb_raise(rb_eArgError
, "too few arguments for syscall");
10559 if (argc
> numberof(arg
))
10560 rb_raise(rb_eArgError
, "too many arguments for syscall");
10561 num
= NUM2SYSCALLID(argv
[0]); ++argv
;
10562 for (i
= argc
- 1; i
--; ) {
10563 VALUE v
= rb_check_string_type(argv
[i
]);
10566 SafeStringValue(v
);
10568 arg
[i
] = (VALUE
)StringValueCStr(v
);
10571 arg
[i
] = (VALUE
)NUM2LONG(argv
[i
]);
10577 retval
= SYSCALL(num
);
10580 retval
= SYSCALL(num
, arg
[0]);
10583 retval
= SYSCALL(num
, arg
[0],arg
[1]);
10586 retval
= SYSCALL(num
, arg
[0],arg
[1],arg
[2]);
10589 retval
= SYSCALL(num
, arg
[0],arg
[1],arg
[2],arg
[3]);
10592 retval
= SYSCALL(num
, arg
[0],arg
[1],arg
[2],arg
[3],arg
[4]);
10595 retval
= SYSCALL(num
, arg
[0],arg
[1],arg
[2],arg
[3],arg
[4],arg
[5]);
10598 retval
= SYSCALL(num
, arg
[0],arg
[1],arg
[2],arg
[3],arg
[4],arg
[5],arg
[6]);
10604 return RETVAL2NUM(retval
);
10606 #undef NUM2SYSCALLID
10610 #define rb_f_syscall rb_f_notimplement
10614 io_new_instance(VALUE args
)
10616 return rb_class_new_instance(2, (VALUE
*)args
+1, *(VALUE
*)args
);
10619 static rb_encoding
*
10620 find_encoding(VALUE v
)
10622 rb_encoding
*enc
= rb_find_encoding(v
);
10623 if (!enc
) rb_warn("Unsupported encoding %"PRIsVALUE
" ignored", v
);
10628 io_encoding_set(rb_io_t
*fptr
, VALUE v1
, VALUE v2
, VALUE opt
)
10630 rb_encoding
*enc
, *enc2
;
10631 int ecflags
= fptr
->encs
.ecflags
;
10635 enc2
= find_encoding(v1
);
10636 tmp
= rb_check_string_type(v2
);
10638 if (RSTRING_LEN(tmp
) == 1 && RSTRING_PTR(tmp
)[0] == '-') {
10639 /* Special case - "-" => no transcoding */
10644 enc
= find_encoding(v2
);
10646 /* Special case - "-" => no transcoding */
10651 enc
= find_encoding(v2
);
10653 /* Special case - "-" => no transcoding */
10657 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2
, ecflags
);
10658 ecflags
= rb_econv_prepare_options(opt
, &ecopts
, ecflags
);
10662 /* Set to default encodings */
10663 rb_io_ext_int_to_encs(NULL
, NULL
, &enc
, &enc2
, 0);
10664 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2
, ecflags
);
10668 tmp
= rb_check_string_type(v1
);
10669 if (!NIL_P(tmp
) && rb_enc_asciicompat(enc
= rb_enc_get(tmp
))) {
10670 parse_mode_enc(RSTRING_PTR(tmp
), enc
, &enc
, &enc2
, NULL
);
10671 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2
, ecflags
);
10672 ecflags
= rb_econv_prepare_options(opt
, &ecopts
, ecflags
);
10675 rb_io_ext_int_to_encs(find_encoding(v1
), NULL
, &enc
, &enc2
, 0);
10676 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2
, ecflags
);
10681 validate_enc_binmode(&fptr
->mode
, ecflags
, enc
, enc2
);
10682 fptr
->encs
.enc
= enc
;
10683 fptr
->encs
.enc2
= enc2
;
10684 fptr
->encs
.ecflags
= ecflags
;
10685 fptr
->encs
.ecopts
= ecopts
;
10686 clear_codeconv(fptr
);
10690 struct io_encoding_set_args
{
10698 io_encoding_set_v(VALUE v
)
10700 struct io_encoding_set_args
*arg
= (struct io_encoding_set_args
*)v
;
10701 io_encoding_set(arg
->fptr
, arg
->v1
, arg
->v2
, arg
->opt
);
10706 pipe_pair_close(VALUE rw
)
10708 VALUE
*rwp
= (VALUE
*)rw
;
10709 return rb_ensure(io_close
, rwp
[0], io_close
, rwp
[1]);
10714 * IO.pipe -> [read_io, write_io]
10715 * IO.pipe(ext_enc) -> [read_io, write_io]
10716 * IO.pipe("ext_enc:int_enc" [, opt]) -> [read_io, write_io]
10717 * IO.pipe(ext_enc, int_enc [, opt]) -> [read_io, write_io]
10719 * IO.pipe(...) {|read_io, write_io| ... }
10721 * Creates a pair of pipe endpoints (connected to each other) and
10722 * returns them as a two-element array of IO objects:
10723 * <code>[</code> <i>read_io</i>, <i>write_io</i> <code>]</code>.
10725 * If a block is given, the block is called and
10726 * returns the value of the block.
10727 * <i>read_io</i> and <i>write_io</i> are sent to the block as arguments.
10728 * If read_io and write_io are not closed when the block exits, they are closed.
10729 * i.e. closing read_io and/or write_io doesn't cause an error.
10731 * Not available on all platforms.
10733 * If an encoding (encoding name or encoding object) is specified as an optional argument,
10734 * read string from pipe is tagged with the encoding specified.
10735 * If the argument is a colon separated two encoding names "A:B",
10736 * the read string is converted from encoding A (external encoding)
10737 * to encoding B (internal encoding), then tagged with B.
10738 * If two optional arguments are specified, those must be
10739 * encoding objects or encoding names,
10740 * and the first one is the external encoding,
10741 * and the second one is the internal encoding.
10742 * If the external encoding and the internal encoding is specified,
10743 * optional hash argument specify the conversion option.
10745 * In the example below, the two processes close the ends of the pipe
10746 * that they are not using. This is not just a cosmetic nicety. The
10747 * read end of a pipe will not generate an end of file condition if
10748 * there are any writers with the pipe still open. In the case of the
10749 * parent process, the <code>rd.read</code> will never return if it
10750 * does not first issue a <code>wr.close</code>.
10756 * puts "Parent got: <#{rd.read}>"
10761 * puts "Sending message to parent"
10762 * wr.write "Hi Dad"
10766 * <em>produces:</em>
10768 * Sending message to parent
10769 * Parent got: <Hi Dad>
10773 rb_io_s_pipe(int argc
, VALUE
*argv
, VALUE klass
)
10775 int pipes
[2], state
;
10776 VALUE r
, w
, args
[3], v1
, v2
;
10778 rb_io_t
*fptr
, *fptr2
;
10779 struct io_encoding_set_args ies_args
;
10783 argc
= rb_scan_args(argc
, argv
, "02:", &v1
, &v2
, &opt
);
10784 if (rb_pipe(pipes
) < 0)
10788 args
[1] = INT2NUM(pipes
[0]);
10789 args
[2] = INT2FIX(O_RDONLY
);
10790 r
= rb_protect(io_new_instance
, (VALUE
)args
, &state
);
10794 rb_jump_tag(state
);
10796 GetOpenFile(r
, fptr
);
10798 ies_args
.fptr
= fptr
;
10801 ies_args
.opt
= opt
;
10802 rb_protect(io_encoding_set_v
, (VALUE
)&ies_args
, &state
);
10806 rb_jump_tag(state
);
10809 args
[1] = INT2NUM(pipes
[1]);
10810 args
[2] = INT2FIX(O_WRONLY
);
10811 w
= rb_protect(io_new_instance
, (VALUE
)args
, &state
);
10814 if (!NIL_P(r
)) rb_io_close(r
);
10815 rb_jump_tag(state
);
10817 GetOpenFile(w
, fptr2
);
10818 rb_io_synchronized(fptr2
);
10820 extract_binmode(opt
, &fmode
);
10822 if ((fmode
& FMODE_BINMODE
) && NIL_P(v1
)) {
10823 rb_io_ascii8bit_binmode(r
);
10824 rb_io_ascii8bit_binmode(w
);
10827 #if DEFAULT_TEXTMODE
10828 if ((fptr
->mode
& FMODE_TEXTMODE
) && (fmode
& FMODE_BINMODE
)) {
10829 fptr
->mode
&= ~FMODE_TEXTMODE
;
10830 setmode(fptr
->fd
, O_BINARY
);
10832 #if RUBY_CRLF_ENVIRONMENT
10833 if (fptr
->encs
.ecflags
& ECONV_DEFAULT_NEWLINE_DECORATOR
) {
10834 fptr
->encs
.ecflags
|= ECONV_UNIVERSAL_NEWLINE_DECORATOR
;
10838 fptr
->mode
|= fmode
;
10839 #if DEFAULT_TEXTMODE
10840 if ((fptr2
->mode
& FMODE_TEXTMODE
) && (fmode
& FMODE_BINMODE
)) {
10841 fptr2
->mode
&= ~FMODE_TEXTMODE
;
10842 setmode(fptr2
->fd
, O_BINARY
);
10845 fptr2
->mode
|= fmode
;
10847 ret
= rb_assoc_new(r
, w
);
10848 if (rb_block_given_p()) {
10852 return rb_ensure(rb_yield
, ret
, pipe_pair_close
, (VALUE
)rw
);
10857 struct foreach_arg
{
10864 open_key_args(VALUE klass
, int argc
, VALUE
*argv
, VALUE opt
, struct foreach_arg
*arg
)
10867 VALUE vmode
= Qnil
, vperm
= Qnil
;
10871 FilePathValue(path
);
10876 vmode
= INT2NUM(O_RDONLY
);
10877 vperm
= INT2FIX(0666);
10879 else if (!NIL_P(v
= rb_hash_aref(opt
, sym_open_args
))) {
10882 v
= rb_to_array_type(v
);
10883 n
= RARRAY_LENINT(v
);
10884 rb_check_arity(n
, 0, 3); /* rb_io_open */
10885 rb_scan_args_kw(RB_SCAN_ARGS_LAST_HASH_KEYWORDS
, n
, RARRAY_CONST_PTR(v
), "02:", &vmode
, &vperm
, &opt
);
10887 arg
->io
= rb_io_open(klass
, path
, vmode
, vperm
, opt
);
10891 io_s_foreach(VALUE v
)
10893 struct getline_arg
*arg
= (void *)v
;
10896 while (!NIL_P(str
= rb_io_getline_1(arg
->rs
, arg
->limit
, arg
->chomp
, arg
->io
))) {
10897 rb_lastline_set(str
);
10900 rb_lastline_set(Qnil
);
10906 * IO.foreach(name, sep=$/ [, getline_args, open_args]) {|line| block } -> nil
10907 * IO.foreach(name, limit [, getline_args, open_args]) {|line| block } -> nil
10908 * IO.foreach(name, sep, limit [, getline_args, open_args]) {|line| block } -> nil
10909 * IO.foreach(...) -> an_enumerator
10910 * File.foreach(name, sep=$/ [, getline_args, open_args]) {|line| block } -> nil
10911 * File.foreach(name, limit [, getline_args, open_args]) {|line| block } -> nil
10912 * File.foreach(name, sep, limit [, getline_args, open_args]) {|line| block } -> nil
10913 * File.foreach(...) -> an_enumerator
10915 * Executes the block for every line in the named I/O port, where lines
10916 * are separated by <em>sep</em>.
10918 * If no block is given, an enumerator is returned instead.
10920 * If +name+ starts with a pipe character (<code>"|"</code>) and the receiver
10921 * is the IO class, a subprocess is created in the same way as Kernel#open,
10922 * and its output is returned.
10923 * Consider to use File.foreach to disable the behavior of subprocess invocation.
10925 * File.foreach("testfile") {|x| print "GOT ", x }
10926 * IO.foreach("| cat testfile") {|x| print "GOT ", x }
10928 * <em>produces:</em>
10930 * GOT This is line one
10931 * GOT This is line two
10932 * GOT This is line three
10935 * If the last argument is a hash, it's the keyword argument to open.
10936 * See IO.readlines for details about getline_args.
10937 * And see also IO.read for details about open_args.
10942 rb_io_s_foreach(int argc
, VALUE
*argv
, VALUE self
)
10945 int orig_argc
= argc
;
10946 struct foreach_arg arg
;
10947 struct getline_arg garg
;
10949 argc
= rb_scan_args(argc
, argv
, "13:", NULL
, NULL
, NULL
, NULL
, &opt
);
10950 RETURN_ENUMERATOR(self
, orig_argc
, argv
);
10951 extract_getline_args(argc
-1, argv
+1, &garg
);
10952 open_key_args(self
, argc
, argv
, opt
, &arg
);
10953 if (NIL_P(arg
.io
)) return Qnil
;
10954 extract_getline_opts(opt
, &garg
);
10955 check_getline_args(&garg
.rs
, &garg
.limit
, garg
.io
= arg
.io
);
10956 return rb_ensure(io_s_foreach
, (VALUE
)&garg
, rb_io_close
, arg
.io
);
10960 io_s_readlines(VALUE v
)
10962 struct getline_arg
*arg
= (void *)v
;
10963 return io_readlines(arg
, arg
->io
);
10968 * IO.readlines(name, sep=$/ [, getline_args, open_args]) -> array
10969 * IO.readlines(name, limit [, getline_args, open_args]) -> array
10970 * IO.readlines(name, sep, limit [, getline_args, open_args]) -> array
10971 * File.readlines(name, sep=$/ [, getline_args, open_args]) -> array
10972 * File.readlines(name, limit [, getline_args, open_args]) -> array
10973 * File.readlines(name, sep, limit [, getline_args, open_args]) -> array
10975 * Reads the entire file specified by <i>name</i> as individual
10976 * lines, and returns those lines in an array. Lines are separated by
10979 * If +name+ starts with a pipe character (<code>"|"</code>) and the receiver
10980 * is the IO class, a subprocess is created in the same way as Kernel#open,
10981 * and its output is returned.
10982 * Consider to use File.readlines to disable the behavior of subprocess invocation.
10984 * a = File.readlines("testfile")
10985 * a[0] #=> "This is line one\n"
10987 * b = File.readlines("testfile", chomp: true)
10988 * b[0] #=> "This is line one"
10990 * IO.readlines("|ls -a") #=> [".\n", "..\n", ...]
10992 * If the last argument is a hash, it's the keyword argument to open.
10994 * === Options for getline
10996 * The options hash accepts the following keys:
10999 * When the optional +chomp+ keyword argument has a true value,
11000 * <code>\n</code>, <code>\r</code>, and <code>\r\n</code>
11001 * will be removed from the end of each line.
11003 * See also IO.read for details about +name+ and open_args.
11007 rb_io_s_readlines(int argc
, VALUE
*argv
, VALUE io
)
11010 struct foreach_arg arg
;
11011 struct getline_arg garg
;
11013 argc
= rb_scan_args(argc
, argv
, "13:", NULL
, NULL
, NULL
, NULL
, &opt
);
11014 extract_getline_args(argc
-1, argv
+1, &garg
);
11015 open_key_args(io
, argc
, argv
, opt
, &arg
);
11016 if (NIL_P(arg
.io
)) return Qnil
;
11017 extract_getline_opts(opt
, &garg
);
11018 check_getline_args(&garg
.rs
, &garg
.limit
, garg
.io
= arg
.io
);
11019 return rb_ensure(io_s_readlines
, (VALUE
)&garg
, rb_io_close
, arg
.io
);
11025 struct foreach_arg
*arg
= (void *)v
;
11026 return io_read(arg
->argc
, arg
->argv
, arg
->io
);
11036 seek_before_access(VALUE argp
)
11038 struct seek_arg
*arg
= (struct seek_arg
*)argp
;
11039 rb_io_binmode(arg
->io
);
11040 return rb_io_seek(arg
->io
, arg
->offset
, arg
->mode
);
11045 * IO.read(name, [length [, offset]] [, opt]) -> string
11046 * File.read(name, [length [, offset]] [, opt]) -> string
11048 * Opens the file, optionally seeks to the given +offset+, then returns
11049 * +length+ bytes (defaulting to the rest of the file). #read ensures
11050 * the file is closed before returning.
11052 * If +name+ starts with a pipe character (<code>"|"</code>) and the receiver
11053 * is the IO class, a subprocess is created in the same way as Kernel#open,
11054 * and its output is returned.
11055 * Consider to use File.read to disable the behavior of subprocess invocation.
11059 * The options hash accepts the following keys:
11062 * string or encoding
11064 * Specifies the encoding of the read string. +:encoding+ will be ignored
11065 * if +length+ is specified. See Encoding.aliases for possible encodings.
11068 * string or integer
11070 * Specifies the <i>mode</i> argument for open(). It must start
11071 * with an "r", otherwise it will cause an error.
11072 * See IO.new for the list of possible modes.
11077 * Specifies arguments for open() as an array. This key can not be used
11078 * in combination with either +:encoding+ or +:mode+.
11082 * File.read("testfile") #=> "This is line one\nThis is line two\nThis is line three\nAnd so on...\n"
11083 * File.read("testfile", 20) #=> "This is line one\nThi"
11084 * File.read("testfile", 20, 10) #=> "ne one\nThis is line "
11085 * File.read("binfile", mode: "rb") #=> "\xF7\x00\x00\x0E\x12"
11086 * IO.read("|ls -a") #=> ".\n..\n"...
11090 rb_io_s_read(int argc
, VALUE
*argv
, VALUE io
)
11093 struct foreach_arg arg
;
11095 argc
= rb_scan_args(argc
, argv
, "13:", NULL
, NULL
, &offset
, NULL
, &opt
);
11096 open_key_args(io
, argc
, argv
, opt
, &arg
);
11097 if (NIL_P(arg
.io
)) return Qnil
;
11098 if (!NIL_P(offset
)) {
11099 struct seek_arg sarg
;
11102 sarg
.offset
= offset
;
11103 sarg
.mode
= SEEK_SET
;
11104 rb_protect(seek_before_access
, (VALUE
)&sarg
, &state
);
11106 rb_io_close(arg
.io
);
11107 rb_jump_tag(state
);
11109 if (arg
.argc
== 2) arg
.argc
= 1;
11111 return rb_ensure(io_s_read
, (VALUE
)&arg
, rb_io_close
, arg
.io
);
11116 * IO.binread(name, [length [, offset]]) -> string
11117 * File.binread(name, [length [, offset]]) -> string
11119 * Opens the file, optionally seeks to the given <i>offset</i>, then
11120 * returns <i>length</i> bytes (defaulting to the rest of the file).
11121 * #binread ensures the file is closed before returning. The open mode
11122 * would be <code>"rb:ASCII-8BIT"</code>.
11124 * If +name+ starts with a pipe character (<code>"|"</code>) and the receiver
11125 * is the IO class, a subprocess is created in the same way as Kernel#open,
11126 * and its output is returned.
11127 * Consider to use File.binread to disable the behavior of subprocess invocation.
11129 * File.binread("testfile") #=> "This is line one\nThis is line two\nThis is line three\nAnd so on...\n"
11130 * File.binread("testfile", 20) #=> "This is line one\nThi"
11131 * File.binread("testfile", 20, 10) #=> "ne one\nThis is line "
11132 * IO.binread("| cat testfile") #=> "This is line one\nThis is line two\nThis is line three\nAnd so on...\n"
11134 * See also IO.read for details about +name+ and open_args.
11138 rb_io_s_binread(int argc
, VALUE
*argv
, VALUE io
)
11141 struct foreach_arg arg
;
11143 fmode
= FMODE_READABLE
|FMODE_BINMODE
,
11149 convconfig_t convconfig
= {NULL
, NULL
, 0, Qnil
};
11151 rb_scan_args(argc
, argv
, "12", NULL
, NULL
, &offset
);
11152 FilePathValue(argv
[0]);
11153 convconfig
.enc
= rb_ascii8bit_encoding();
11154 arg
.io
= rb_io_open_generic(io
, argv
[0], oflags
, fmode
, &convconfig
, 0);
11155 if (NIL_P(arg
.io
)) return Qnil
;
11157 arg
.argc
= (argc
> 1) ? 1 : 0;
11158 if (!NIL_P(offset
)) {
11159 struct seek_arg sarg
;
11162 sarg
.offset
= offset
;
11163 sarg
.mode
= SEEK_SET
;
11164 rb_protect(seek_before_access
, (VALUE
)&sarg
, &state
);
11166 rb_io_close(arg
.io
);
11167 rb_jump_tag(state
);
11170 return rb_ensure(io_s_read
, (VALUE
)&arg
, rb_io_close
, arg
.io
);
11174 io_s_write0(VALUE v
)
11176 struct write_arg
*arg
= (void *)v
;
11177 return io_write(arg
->io
,arg
->str
,arg
->nosync
);
11181 io_s_write(int argc
, VALUE
*argv
, VALUE klass
, int binary
)
11183 VALUE string
, offset
, opt
;
11184 struct foreach_arg arg
;
11185 struct write_arg warg
;
11187 rb_scan_args(argc
, argv
, "21:", NULL
, &string
, &offset
, &opt
);
11189 if (NIL_P(opt
)) opt
= rb_hash_new();
11190 else opt
= rb_hash_dup(opt
);
11193 if (NIL_P(rb_hash_aref(opt
,sym_mode
))) {
11194 int mode
= O_WRONLY
|O_CREAT
;
11196 if (binary
) mode
|= O_BINARY
;
11198 if (NIL_P(offset
)) mode
|= O_TRUNC
;
11199 rb_hash_aset(opt
,sym_mode
,INT2NUM(mode
));
11201 open_key_args(klass
, argc
, argv
, opt
, &arg
);
11204 if (binary
) rb_io_binmode_m(arg
.io
);
11207 if (NIL_P(arg
.io
)) return Qnil
;
11208 if (!NIL_P(offset
)) {
11209 struct seek_arg sarg
;
11212 sarg
.offset
= offset
;
11213 sarg
.mode
= SEEK_SET
;
11214 rb_protect(seek_before_access
, (VALUE
)&sarg
, &state
);
11216 rb_io_close(arg
.io
);
11217 rb_jump_tag(state
);
11225 return rb_ensure(io_s_write0
, (VALUE
)&warg
, rb_io_close
, arg
.io
);
11230 * IO.write(name, string [, offset]) -> integer
11231 * IO.write(name, string [, offset] [, opt]) -> integer
11232 * File.write(name, string [, offset]) -> integer
11233 * File.write(name, string [, offset] [, opt]) -> integer
11235 * Opens the file, optionally seeks to the given <i>offset</i>, writes
11236 * <i>string</i>, then returns the length written. #write ensures the
11237 * file is closed before returning. If <i>offset</i> is not given in
11238 * write mode, the file is truncated. Otherwise, it is not truncated.
11240 * If +name+ starts with a pipe character (<code>"|"</code>) and the receiver
11241 * is the IO class, a subprocess is created in the same way as Kernel#open,
11242 * and its output is returned.
11243 * Consider to use File.write to disable the behavior of subprocess invocation.
11245 * File.write("testfile", "0123456789", 20) #=> 10
11246 * # File could contain: "This is line one\nThi0123456789two\nThis is line three\nAnd so on...\n"
11247 * File.write("testfile", "0123456789") #=> 10
11248 * # File would now read: "0123456789"
11249 * IO.write("|tr a-z A-Z", "abc") #=> 3
11250 * # Prints "ABC" to the standard output
11252 * If the last argument is a hash, it specifies options for the internal
11253 * open(). It accepts the following keys:
11256 * string or encoding
11258 * Specifies the encoding of the read string.
11259 * See Encoding.aliases for possible encodings.
11262 * string or integer
11264 * Specifies the <i>mode</i> argument for open(). It must start
11265 * with "w", "a", or "r+", otherwise it will cause an error.
11266 * See IO.new for the list of possible modes.
11271 * Specifies the <i>perm</i> argument for open().
11276 * Specifies arguments for open() as an array.
11277 * This key can not be used in combination with other keys.
11279 * See also IO.read for details about +name+ and open_args.
11283 rb_io_s_write(int argc
, VALUE
*argv
, VALUE io
)
11285 return io_s_write(argc
, argv
, io
, 0);
11290 * IO.binwrite(name, string, [offset]) -> integer
11291 * IO.binwrite(name, string, [offset], open_args) -> integer
11292 * File.binwrite(name, string, [offset]) -> integer
11293 * File.binwrite(name, string, [offset], open_args) -> integer
11295 * Same as IO.write except opening the file in binary mode and
11296 * ASCII-8BIT encoding (<code>"wb:ASCII-8BIT"</code>).
11298 * If +name+ starts with a pipe character (<code>"|"</code>) and the receiver
11299 * is the IO class, a subprocess is created in the same way as Kernel#open,
11300 * and its output is returned.
11301 * Consider to use File.binwrite to disable the behavior of subprocess invocation.
11303 * See also IO.read for details about +name+ and open_args.
11307 rb_io_s_binwrite(int argc
, VALUE
*argv
, VALUE io
)
11309 return io_s_write(argc
, argv
, io
, 1);
11312 struct copy_stream_struct
{
11315 off_t copy_length
; /* (off_t)-1 if not specified */
11316 off_t src_offset
; /* (off_t)-1 if not specified */
11320 unsigned close_src
: 1;
11321 unsigned close_dst
: 1;
11324 const char *syserr
;
11325 const char *notimp
;
11327 struct stat src_stat
;
11328 struct stat dst_stat
;
11329 #ifdef HAVE_FCOPYFILE
11330 copyfile_state_t copyfile_state
;
11335 exec_interrupts(void *arg
)
11337 VALUE th
= (VALUE
)arg
;
11338 rb_thread_execute_interrupts(th
);
11343 * returns TRUE if the preceding system call was interrupted
11344 * so we can continue. If the thread was interrupted, we
11345 * reacquire the GVL to execute interrupts before continuing.
11348 maygvl_copy_stream_continue_p(int has_gvl
, struct copy_stream_struct
*stp
)
11352 #if defined(ERESTART)
11355 if (rb_thread_interrupted(stp
->th
)) {
11357 rb_thread_execute_interrupts(stp
->th
);
11359 rb_thread_call_with_gvl(exec_interrupts
, (void *)stp
->th
);
11366 struct wait_for_single_fd
{
11376 rb_thread_fiber_scheduler_wait_for(void * _args
)
11378 struct wait_for_single_fd
*args
= (struct wait_for_single_fd
*)_args
;
11380 args
->result
= rb_fiber_scheduler_io_wait(args
->scheduler
, args
->fptr
->self
, INT2NUM(args
->events
), Qnil
);
11386 # define IOWAIT_SYSCALL "poll"
11387 STATIC_ASSERT(pollin_expected
, POLLIN
== RB_WAITFD_IN
);
11388 STATIC_ASSERT(pollout_expected
, POLLOUT
== RB_WAITFD_OUT
);
11390 nogvl_wait_for(VALUE th
, rb_io_t
*fptr
, short events
)
11392 VALUE scheduler
= rb_fiber_scheduler_current_for_thread(th
);
11393 if (scheduler
!= Qnil
) {
11394 struct wait_for_single_fd args
= {.scheduler
= scheduler
, .fptr
= fptr
, .events
= events
};
11395 rb_thread_call_with_gvl(rb_thread_fiber_scheduler_wait_for
, &args
);
11396 return RTEST(args
.result
);
11400 if (fd
== -1) return 0;
11405 fds
.events
= events
;
11407 return poll(&fds
, 1, -1);
11409 #else /* !USE_POLL */
11410 # define IOWAIT_SYSCALL "select"
11412 nogvl_wait_for(VALUE th
, rb_io_t
*fptr
, short events
)
11414 VALUE scheduler
= rb_fiber_scheduler_current_for_thread(th
);
11415 if (scheduler
!= Qnil
) {
11416 struct wait_for_single_fd args
= {.scheduler
= scheduler
, .fptr
= fptr
, .events
= events
};
11417 rb_thread_call_with_gvl(rb_thread_fiber_scheduler_wait_for
, &args
);
11418 return RTEST(args
.result
);
11422 if (fd
== -1) return 0;
11428 rb_fd_set(fd
, &fds
);
11432 ret
= rb_fd_select(fd
+ 1, &fds
, 0, 0, 0);
11434 case RB_WAITFD_OUT
:
11435 ret
= rb_fd_select(fd
+ 1, 0, &fds
, 0, 0);
11438 VM_UNREACHABLE(nogvl_wait_for
);
11444 #endif /* !USE_POLL */
11447 maygvl_copy_stream_wait_read(int has_gvl
, struct copy_stream_struct
*stp
)
11453 ret
= RB_NUM2INT(rb_io_wait(stp
->src
, RB_INT2NUM(RUBY_IO_READABLE
), Qnil
));
11456 ret
= nogvl_wait_for(stp
->th
, stp
->src_fptr
, RB_WAITFD_IN
);
11458 } while (ret
< 0 && maygvl_copy_stream_continue_p(has_gvl
, stp
));
11461 stp
->syserr
= IOWAIT_SYSCALL
;
11462 stp
->error_no
= errno
;
11469 nogvl_copy_stream_wait_write(struct copy_stream_struct
*stp
)
11474 ret
= nogvl_wait_for(stp
->th
, stp
->dst_fptr
, RB_WAITFD_OUT
);
11475 } while (ret
< 0 && maygvl_copy_stream_continue_p(0, stp
));
11478 stp
->syserr
= IOWAIT_SYSCALL
;
11479 stp
->error_no
= errno
;
11485 #ifdef USE_COPY_FILE_RANGE
11488 simple_copy_file_range(int in_fd
, off_t
*in_offset
, int out_fd
, off_t
*out_offset
, size_t count
, unsigned int flags
)
11490 #ifdef HAVE_COPY_FILE_RANGE
11491 return copy_file_range(in_fd
, in_offset
, out_fd
, out_offset
, count
, flags
);
11493 return syscall(__NR_copy_file_range
, in_fd
, in_offset
, out_fd
, out_offset
, count
, flags
);
11498 nogvl_copy_file_range(struct copy_stream_struct
*stp
)
11502 off_t copy_length
, src_offset
, *src_offset_ptr
;
11504 if (!S_ISREG(stp
->src_stat
.st_mode
))
11507 src_size
= stp
->src_stat
.st_size
;
11508 src_offset
= stp
->src_offset
;
11509 if (src_offset
>= (off_t
)0) {
11510 src_offset_ptr
= &src_offset
;
11513 src_offset_ptr
= NULL
; /* if src_offset_ptr is NULL, then bytes are read from in_fd starting from the file offset */
11516 copy_length
= stp
->copy_length
;
11517 if (copy_length
< (off_t
)0) {
11518 if (src_offset
< (off_t
)0) {
11519 off_t current_offset
;
11521 current_offset
= lseek(stp
->src_fptr
->fd
, 0, SEEK_CUR
);
11522 if (current_offset
< (off_t
)0 && errno
) {
11523 stp
->syserr
= "lseek";
11524 stp
->error_no
= errno
;
11525 return (int)current_offset
;
11527 copy_length
= src_size
- current_offset
;
11530 copy_length
= src_size
- src_offset
;
11534 retry_copy_file_range
:
11535 # if SIZEOF_OFF_T > SIZEOF_SIZE_T
11536 /* we are limited by the 32-bit ssize_t return value on 32-bit */
11537 ss
= (copy_length
> (off_t
)SSIZE_MAX
) ? SSIZE_MAX
: (ssize_t
)copy_length
;
11539 ss
= (ssize_t
)copy_length
;
11541 ss
= simple_copy_file_range(stp
->src_fptr
->fd
, src_offset_ptr
, stp
->dst_fptr
->fd
, NULL
, ss
, 0);
11545 if (0 < copy_length
) {
11546 goto retry_copy_file_range
;
11550 if (maygvl_copy_stream_continue_p(0, stp
)) {
11551 goto retry_copy_file_range
;
11555 case EPERM
: /* copy_file_range(2) doesn't exist (may happen in
11556 docker container) */
11561 case EXDEV
: /* in_fd and out_fd are not on the same filesystem */
11565 #if EWOULDBLOCK != EAGAIN
11569 int ret
= nogvl_copy_stream_wait_write(stp
);
11570 if (ret
< 0) return ret
;
11572 goto retry_copy_file_range
;
11576 int flags
= fcntl(stp
->dst_fptr
->fd
, F_GETFL
);
11578 if (flags
!= -1 && flags
& O_APPEND
) {
11584 stp
->syserr
= "copy_file_range";
11585 stp
->error_no
= errno
;
11592 #ifdef HAVE_FCOPYFILE
11594 nogvl_fcopyfile(struct copy_stream_struct
*stp
)
11597 const off_t src_offset
= stp
->src_offset
;
11600 if (stp
->copy_length
>= (off_t
)0) {
11601 /* copy_length can't be specified in fcopyfile(3) */
11605 if (!S_ISREG(stp
->src_stat
.st_mode
))
11608 if (!S_ISREG(stp
->dst_stat
.st_mode
))
11610 if (lseek(stp
->dst_fptr
->fd
, 0, SEEK_CUR
) > (off_t
)0) /* if dst IO was already written */
11612 if (fcntl(stp
->dst_fptr
->fd
, F_GETFL
) & O_APPEND
) {
11613 /* fcopyfile(3) appends src IO to dst IO and then truncates
11614 * dst IO to src IO's original size. */
11615 off_t end
= lseek(stp
->dst_fptr
->fd
, 0, SEEK_END
);
11616 lseek(stp
->dst_fptr
->fd
, 0, SEEK_SET
);
11617 if (end
> (off_t
)0) return 0;
11620 if (src_offset
> (off_t
)0) {
11623 /* get current offset */
11625 cur
= lseek(stp
->src_fptr
->fd
, 0, SEEK_CUR
);
11626 if (cur
< (off_t
)0 && errno
) {
11627 stp
->error_no
= errno
;
11632 r
= lseek(stp
->src_fptr
->fd
, src_offset
, SEEK_SET
);
11633 if (r
< (off_t
)0 && errno
) {
11634 stp
->error_no
= errno
;
11639 stp
->copyfile_state
= copyfile_state_alloc(); /* this will be freed by copy_stream_finalize() */
11640 ret
= fcopyfile(stp
->src_fptr
->fd
, stp
->dst_fptr
->fd
, stp
->copyfile_state
, COPYFILE_DATA
);
11641 copyfile_state_get(stp
->copyfile_state
, COPYFILE_STATE_COPIED
, &ss
); /* get copied bytes */
11643 if (ret
== 0) { /* success */
11645 if (src_offset
> (off_t
)0) {
11649 r
= lseek(stp
->src_fptr
->fd
, cur
, SEEK_SET
);
11650 if (r
< (off_t
)0 && errno
) {
11651 stp
->error_no
= errno
;
11663 stp
->syserr
= "fcopyfile";
11664 stp
->error_no
= errno
;
11671 #ifdef HAVE_SENDFILE
11674 # define USE_SENDFILE
11676 # ifdef HAVE_SYS_SENDFILE_H
11677 # include <sys/sendfile.h>
11681 simple_sendfile(int out_fd
, int in_fd
, off_t
*offset
, off_t count
)
11683 return sendfile(out_fd
, in_fd
, offset
, (size_t)count
);
11686 # elif 0 /* defined(__FreeBSD__) || defined(__DragonFly__) */ || defined(__APPLE__)
11687 /* This runs on FreeBSD8.1 r30210, but sendfiles blocks its execution
11688 * without cpuset -l 0.
11690 # define USE_SENDFILE
11693 simple_sendfile(int out_fd
, int in_fd
, off_t
*offset
, off_t count
)
11696 off_t pos
= offset
? *offset
: lseek(in_fd
, 0, SEEK_CUR
);
11699 r
= sendfile(in_fd
, out_fd
, pos
, &count
, NULL
, 0);
11702 r
= sendfile(in_fd
, out_fd
, pos
, (size_t)count
, NULL
, &sbytes
, 0);
11704 if (r
!= 0 && sbytes
== 0) return r
;
11709 lseek(in_fd
, sbytes
, SEEK_CUR
);
11711 return (ssize_t
)sbytes
;
11718 #ifdef USE_SENDFILE
11720 nogvl_copy_stream_sendfile(struct copy_stream_struct
*stp
)
11728 if (!S_ISREG(stp
->src_stat
.st_mode
))
11731 src_size
= stp
->src_stat
.st_size
;
11733 if ((stp
->dst_stat
.st_mode
& S_IFMT
) != S_IFSOCK
)
11737 src_offset
= stp
->src_offset
;
11738 use_pread
= src_offset
>= (off_t
)0;
11740 copy_length
= stp
->copy_length
;
11741 if (copy_length
< (off_t
)0) {
11743 copy_length
= src_size
- src_offset
;
11747 cur
= lseek(stp
->src_fptr
->fd
, 0, SEEK_CUR
);
11748 if (cur
< (off_t
)0 && errno
) {
11749 stp
->syserr
= "lseek";
11750 stp
->error_no
= errno
;
11753 copy_length
= src_size
- cur
;
11758 # if SIZEOF_OFF_T > SIZEOF_SIZE_T
11759 /* we are limited by the 32-bit ssize_t return value on 32-bit */
11760 ss
= (copy_length
> (off_t
)SSIZE_MAX
) ? SSIZE_MAX
: (ssize_t
)copy_length
;
11762 ss
= (ssize_t
)copy_length
;
11765 ss
= simple_sendfile(stp
->dst_fptr
->fd
, stp
->src_fptr
->fd
, &src_offset
, ss
);
11768 ss
= simple_sendfile(stp
->dst_fptr
->fd
, stp
->src_fptr
->fd
, NULL
, ss
);
11773 if (0 < copy_length
) {
11774 goto retry_sendfile
;
11778 if (maygvl_copy_stream_continue_p(0, stp
))
11779 goto retry_sendfile
;
11786 /* some RedHat kernels may return EOPNOTSUP on an NFS mount.
11787 see also: [Feature #16965] */
11792 #if EWOULDBLOCK != EAGAIN
11799 * Linux requires stp->src_fptr->fd to be a mmap-able (regular) file,
11800 * select() reports regular files to always be "ready", so
11801 * there is no need to select() on it.
11802 * Other OSes may have the same limitation for sendfile() which
11803 * allow us to bypass maygvl_copy_stream_wait_read()...
11805 ret
= maygvl_copy_stream_wait_read(0, stp
);
11806 if (ret
< 0) return ret
;
11808 ret
= nogvl_copy_stream_wait_write(stp
);
11809 if (ret
< 0) return ret
;
11811 goto retry_sendfile
;
11813 stp
->syserr
= "sendfile";
11814 stp
->error_no
= errno
;
11822 maygvl_read(int has_gvl
, rb_io_t
*fptr
, void *buf
, size_t count
)
11825 return rb_read_internal(fptr
, buf
, count
);
11827 return read(fptr
->fd
, buf
, count
);
11831 maygvl_copy_stream_read(int has_gvl
, struct copy_stream_struct
*stp
, char *buf
, size_t len
, off_t offset
)
11835 if (offset
< (off_t
)0) {
11836 ss
= maygvl_read(has_gvl
, stp
->src_fptr
, buf
, len
);
11840 ss
= pread(stp
->src_fptr
->fd
, buf
, len
, offset
);
11842 stp
->notimp
= "pread";
11850 if (maygvl_copy_stream_continue_p(has_gvl
, stp
))
11854 #if EWOULDBLOCK != EAGAIN
11858 int ret
= maygvl_copy_stream_wait_read(has_gvl
, stp
);
11859 if (ret
< 0) return ret
;
11864 stp
->notimp
= "pread";
11868 stp
->syserr
= offset
< (off_t
)0 ? "read" : "pread";
11869 stp
->error_no
= errno
;
11875 nogvl_copy_stream_write(struct copy_stream_struct
*stp
, char *buf
, size_t len
)
11880 ss
= write(stp
->dst_fptr
->fd
, buf
+off
, len
);
11882 if (maygvl_copy_stream_continue_p(0, stp
))
11884 if (io_again_p(errno
)) {
11885 int ret
= nogvl_copy_stream_wait_write(stp
);
11886 if (ret
< 0) return ret
;
11889 stp
->syserr
= "write";
11890 stp
->error_no
= errno
;
11901 nogvl_copy_stream_read_write(struct copy_stream_struct
*stp
)
11912 copy_length
= stp
->copy_length
;
11913 use_eof
= copy_length
< (off_t
)0;
11914 src_offset
= stp
->src_offset
;
11915 use_pread
= src_offset
>= (off_t
)0;
11917 if (use_pread
&& stp
->close_src
) {
11920 r
= lseek(stp
->src_fptr
->fd
, src_offset
, SEEK_SET
);
11921 if (r
< (off_t
)0 && errno
) {
11922 stp
->syserr
= "lseek";
11923 stp
->error_no
= errno
;
11926 src_offset
= (off_t
)-1;
11930 while (use_eof
|| 0 < copy_length
) {
11931 if (!use_eof
&& copy_length
< (off_t
)sizeof(buf
)) {
11932 len
= (size_t)copy_length
;
11938 ss
= maygvl_copy_stream_read(0, stp
, buf
, len
, src_offset
);
11943 ss
= maygvl_copy_stream_read(0, stp
, buf
, len
, (off_t
)-1);
11945 if (ss
<= 0) /* EOF or error */
11948 ret
= nogvl_copy_stream_write(stp
, buf
, ss
);
11958 nogvl_copy_stream_func(void *arg
)
11960 struct copy_stream_struct
*stp
= (struct copy_stream_struct
*)arg
;
11961 #if defined(USE_SENDFILE) || defined(USE_COPY_FILE_RANGE) || defined(HAVE_FCOPYFILE)
11965 #ifdef USE_COPY_FILE_RANGE
11966 ret
= nogvl_copy_file_range(stp
);
11968 goto finish
; /* error or success */
11971 #ifdef HAVE_FCOPYFILE
11972 ret
= nogvl_fcopyfile(stp
);
11974 goto finish
; /* error or success */
11977 #ifdef USE_SENDFILE
11978 ret
= nogvl_copy_stream_sendfile(stp
);
11980 goto finish
; /* error or success */
11983 nogvl_copy_stream_read_write(stp
);
11985 #if defined(USE_SENDFILE) || defined(USE_COPY_FILE_RANGE) || defined(HAVE_FCOPYFILE)
11992 copy_stream_fallback_body(VALUE arg
)
11994 struct copy_stream_struct
*stp
= (struct copy_stream_struct
*)arg
;
11995 const int buflen
= 16*1024;
11997 VALUE buf
= rb_str_buf_new(buflen
);
11998 off_t rest
= stp
->copy_length
;
11999 off_t off
= stp
->src_offset
;
12000 ID read_method
= id_readpartial
;
12002 if (!stp
->src_fptr
) {
12003 if (!rb_respond_to(stp
->src
, read_method
)) {
12004 read_method
= id_read
;
12011 if (stp
->copy_length
< (off_t
)0) {
12016 rb_str_resize(buf
, 0);
12019 l
= buflen
< rest
? buflen
: (long)rest
;
12021 if (!stp
->src_fptr
) {
12022 VALUE rc
= rb_funcall(stp
->src
, read_method
, 2, INT2FIX(l
), buf
);
12024 if (read_method
== id_read
&& NIL_P(rc
))
12029 rb_str_resize(buf
, buflen
);
12030 ss
= maygvl_copy_stream_read(1, stp
, RSTRING_PTR(buf
), l
, off
);
12031 rb_str_resize(buf
, ss
> 0 ? ss
: 0);
12036 if (off
>= (off_t
)0)
12039 n
= rb_io_write(stp
->dst
, buf
);
12040 numwrote
= NUM2LONG(n
);
12041 stp
->total
+= numwrote
;
12043 if (read_method
== id_read
&& RSTRING_LEN(buf
) == 0) {
12052 copy_stream_fallback(struct copy_stream_struct
*stp
)
12054 if (!stp
->src_fptr
&& stp
->src_offset
>= (off_t
)0) {
12055 rb_raise(rb_eArgError
, "cannot specify src_offset for non-IO");
12057 rb_rescue2(copy_stream_fallback_body
, (VALUE
)stp
,
12058 (VALUE (*) (VALUE
, VALUE
))0, (VALUE
)0,
12059 rb_eEOFError
, (VALUE
)0);
12064 copy_stream_body(VALUE arg
)
12066 struct copy_stream_struct
*stp
= (struct copy_stream_struct
*)arg
;
12067 VALUE src_io
= stp
->src
, dst_io
= stp
->dst
;
12068 const int common_oflags
= 0
12074 stp
->th
= rb_thread_current();
12078 if (src_io
== argf
||
12079 !(RB_TYPE_P(src_io
, T_FILE
) ||
12080 RB_TYPE_P(src_io
, T_STRING
) ||
12081 rb_respond_to(src_io
, rb_intern("to_path")))) {
12082 stp
->src_fptr
= NULL
;
12086 VALUE tmp_io
= rb_io_check_io(src_io
);
12087 if (!NIL_P(tmp_io
)) {
12090 else if (!RB_TYPE_P(src_io
, T_FILE
)) {
12092 FilePathValue(src_io
);
12094 args
[1] = INT2NUM(O_RDONLY
|common_oflags
);
12095 src_io
= rb_class_new_instance(2, args
, rb_cFile
);
12097 stp
->close_src
= 1;
12099 RB_IO_POINTER(src_io
, stp
->src_fptr
);
12100 rb_io_check_byte_readable(stp
->src_fptr
);
12102 stat_ret
= fstat(stp
->src_fptr
->fd
, &stp
->src_stat
);
12103 if (stat_ret
< 0) {
12104 stp
->syserr
= "fstat";
12105 stp
->error_no
= errno
;
12110 if (dst_io
== argf
||
12111 !(RB_TYPE_P(dst_io
, T_FILE
) ||
12112 RB_TYPE_P(dst_io
, T_STRING
) ||
12113 rb_respond_to(dst_io
, rb_intern("to_path")))) {
12114 stp
->dst_fptr
= NULL
;
12118 VALUE tmp_io
= rb_io_check_io(dst_io
);
12119 if (!NIL_P(tmp_io
)) {
12120 dst_io
= GetWriteIO(tmp_io
);
12122 else if (!RB_TYPE_P(dst_io
, T_FILE
)) {
12124 FilePathValue(dst_io
);
12126 args
[1] = INT2NUM(O_WRONLY
|O_CREAT
|O_TRUNC
|common_oflags
);
12127 args
[2] = INT2FIX(0666);
12128 dst_io
= rb_class_new_instance(3, args
, rb_cFile
);
12130 stp
->close_dst
= 1;
12133 dst_io
= GetWriteIO(dst_io
);
12136 RB_IO_POINTER(dst_io
, stp
->dst_fptr
);
12137 rb_io_check_writable(stp
->dst_fptr
);
12139 stat_ret
= fstat(stp
->dst_fptr
->fd
, &stp
->dst_stat
);
12140 if (stat_ret
< 0) {
12141 stp
->syserr
= "fstat";
12142 stp
->error_no
= errno
;
12149 SET_BINARY_MODE_WITH_SEEK_CUR(stp
->src_fptr
);
12152 io_ascii8bit_binmode(stp
->dst_fptr
);
12154 if (stp
->src_offset
< (off_t
)0 && stp
->src_fptr
&& stp
->src_fptr
->rbuf
.len
) {
12155 size_t len
= stp
->src_fptr
->rbuf
.len
;
12157 if (stp
->copy_length
>= (off_t
)0 && stp
->copy_length
< (off_t
)len
) {
12158 len
= (size_t)stp
->copy_length
;
12160 str
= rb_str_buf_new(len
);
12161 rb_str_resize(str
,len
);
12162 read_buffered_data(RSTRING_PTR(str
), len
, stp
->src_fptr
);
12163 if (stp
->dst_fptr
) { /* IO or filename */
12164 if (io_binwrite(str
, RSTRING_PTR(str
), RSTRING_LEN(str
), stp
->dst_fptr
, 0) < 0)
12165 rb_sys_fail_on_write(stp
->dst_fptr
);
12167 else /* others such as StringIO */
12168 rb_io_write(dst_io
, str
);
12169 rb_str_resize(str
, 0);
12171 if (stp
->copy_length
>= (off_t
)0)
12172 stp
->copy_length
-= len
;
12175 if (stp
->dst_fptr
&& io_fflush(stp
->dst_fptr
) < 0) {
12176 rb_raise(rb_eIOError
, "flush failed");
12179 if (stp
->copy_length
== 0)
12182 if (stp
->src_fptr
== NULL
|| stp
->dst_fptr
== NULL
) {
12183 return copy_stream_fallback(stp
);
12186 rb_thread_call_without_gvl(nogvl_copy_stream_func
, (void*)stp
, RUBY_UBF_IO
, 0);
12191 copy_stream_finalize(VALUE arg
)
12193 struct copy_stream_struct
*stp
= (struct copy_stream_struct
*)arg
;
12195 #ifdef HAVE_FCOPYFILE
12196 if (stp
->copyfile_state
) {
12197 copyfile_state_free(stp
->copyfile_state
);
12201 if (stp
->close_src
) {
12202 rb_io_close_m(stp
->src
);
12204 if (stp
->close_dst
) {
12205 rb_io_close_m(stp
->dst
);
12208 rb_syserr_fail(stp
->error_no
, stp
->syserr
);
12211 rb_raise(rb_eNotImpError
, "%s() not implemented", stp
->notimp
);
12218 * IO.copy_stream(src, dst)
12219 * IO.copy_stream(src, dst, copy_length)
12220 * IO.copy_stream(src, dst, copy_length, src_offset)
12222 * IO.copy_stream copies <i>src</i> to <i>dst</i>.
12223 * <i>src</i> and <i>dst</i> is either a filename or an IO-like object.
12224 * IO-like object for <i>src</i> should have #readpartial or #read
12225 * method. IO-like object for <i>dst</i> should have #write method.
12226 * (Specialized mechanisms, such as sendfile system call, may be used
12227 * on appropriate situation.)
12229 * This method returns the number of bytes copied.
12231 * If optional arguments are not given,
12232 * the start position of the copy is
12233 * the beginning of the filename or
12234 * the current file offset of the IO.
12235 * The end position of the copy is the end of file.
12237 * If <i>copy_length</i> is given,
12238 * No more than <i>copy_length</i> bytes are copied.
12240 * If <i>src_offset</i> is given,
12241 * it specifies the start position of the copy.
12243 * When <i>src_offset</i> is specified and
12244 * <i>src</i> is an IO,
12245 * IO.copy_stream doesn't move the current file offset.
12249 rb_io_s_copy_stream(int argc
, VALUE
*argv
, VALUE io
)
12251 VALUE src
, dst
, length
, src_offset
;
12252 struct copy_stream_struct st
;
12254 MEMZERO(&st
, struct copy_stream_struct
, 1);
12256 rb_scan_args(argc
, argv
, "22", &src
, &dst
, &length
, &src_offset
);
12261 st
.src_fptr
= NULL
;
12262 st
.dst_fptr
= NULL
;
12265 st
.copy_length
= (off_t
)-1;
12267 st
.copy_length
= NUM2OFFT(length
);
12269 if (NIL_P(src_offset
))
12270 st
.src_offset
= (off_t
)-1;
12272 st
.src_offset
= NUM2OFFT(src_offset
);
12274 rb_ensure(copy_stream_body
, (VALUE
)&st
, copy_stream_finalize
, (VALUE
)&st
);
12276 return OFFT2NUM(st
.total
);
12281 * io.external_encoding -> encoding
12283 * Returns the Encoding object that represents the encoding of the file.
12284 * If _io_ is in write mode and no encoding is specified, returns +nil+.
12288 rb_io_external_encoding(VALUE io
)
12290 rb_io_t
*fptr
= RFILE(rb_io_taint_check(io
))->fptr
;
12292 if (fptr
->encs
.enc2
) {
12293 return rb_enc_from_encoding(fptr
->encs
.enc2
);
12295 if (fptr
->mode
& FMODE_WRITABLE
) {
12296 if (fptr
->encs
.enc
)
12297 return rb_enc_from_encoding(fptr
->encs
.enc
);
12300 return rb_enc_from_encoding(io_read_encoding(fptr
));
12305 * io.internal_encoding -> encoding
12307 * Returns the Encoding of the internal string if conversion is
12308 * specified. Otherwise returns +nil+.
12312 rb_io_internal_encoding(VALUE io
)
12314 rb_io_t
*fptr
= RFILE(rb_io_taint_check(io
))->fptr
;
12316 if (!fptr
->encs
.enc2
) return Qnil
;
12317 return rb_enc_from_encoding(io_read_encoding(fptr
));
12322 * io.set_encoding(ext_enc) -> io
12323 * io.set_encoding("ext_enc:int_enc") -> io
12324 * io.set_encoding(ext_enc, int_enc) -> io
12325 * io.set_encoding("ext_enc:int_enc", opt) -> io
12326 * io.set_encoding(ext_enc, int_enc, opt) -> io
12328 * If single argument is specified, read string from io is tagged
12329 * with the encoding specified. If encoding is a colon separated two
12330 * encoding names "A:B", the read string is converted from encoding A
12331 * (external encoding) to encoding B (internal encoding), then tagged
12332 * with B. If two arguments are specified, those must be encoding
12333 * objects or encoding names, and the first one is the external encoding, and the
12334 * second one is the internal encoding.
12335 * If the external encoding and the internal encoding is specified,
12336 * optional hash argument specify the conversion option.
12340 rb_io_set_encoding(int argc
, VALUE
*argv
, VALUE io
)
12345 if (!RB_TYPE_P(io
, T_FILE
)) {
12346 return forward(io
, id_set_encoding
, argc
, argv
);
12349 argc
= rb_scan_args(argc
, argv
, "11:", &v1
, &v2
, &opt
);
12350 GetOpenFile(io
, fptr
);
12351 io_encoding_set(fptr
, v1
, v2
, opt
);
12356 rb_stdio_set_default_encoding(void)
12361 if (isatty(fileno(stdin
))) {
12362 rb_encoding
*external
= rb_locale_encoding();
12363 rb_encoding
*internal
= rb_default_internal_encoding();
12364 if (!internal
) internal
= rb_default_external_encoding();
12365 io_encoding_set(RFILE(rb_stdin
)->fptr
,
12366 rb_enc_from_encoding(external
),
12367 rb_enc_from_encoding(internal
),
12372 rb_io_set_encoding(1, &val
, rb_stdin
);
12373 rb_io_set_encoding(1, &val
, rb_stdout
);
12374 rb_io_set_encoding(1, &val
, rb_stderr
);
12378 global_argf_p(VALUE arg
)
12380 return arg
== argf
;
12385 * ARGF.external_encoding -> encoding
12387 * Returns the external encoding for files read from +ARGF+ as an +Encoding+
12388 * object. The external encoding is the encoding of the text as stored in a
12389 * file. Contrast with +ARGF.internal_encoding+, which is the encoding used
12390 * to represent this text within Ruby.
12392 * To set the external encoding use +ARGF.set_encoding+.
12396 * ARGF.external_encoding #=> #<Encoding:UTF-8>
12400 argf_external_encoding(VALUE argf
)
12402 if (!RTEST(ARGF
.current_file
)) {
12403 return rb_enc_from_encoding(rb_default_external_encoding());
12405 return rb_io_external_encoding(rb_io_check_io(ARGF
.current_file
));
12410 * ARGF.internal_encoding -> encoding
12412 * Returns the internal encoding for strings read from +ARGF+ as an
12413 * +Encoding+ object.
12415 * If +ARGF.set_encoding+ has been called with two encoding names, the second
12416 * is returned. Otherwise, if +Encoding.default_external+ has been set, that
12417 * value is returned. Failing that, if a default external encoding was
12418 * specified on the command-line, that value is used. If the encoding is
12419 * unknown, +nil+ is returned.
12422 argf_internal_encoding(VALUE argf
)
12424 if (!RTEST(ARGF
.current_file
)) {
12425 return rb_enc_from_encoding(rb_default_external_encoding());
12427 return rb_io_internal_encoding(rb_io_check_io(ARGF
.current_file
));
12432 * ARGF.set_encoding(ext_enc) -> ARGF
12433 * ARGF.set_encoding("ext_enc:int_enc") -> ARGF
12434 * ARGF.set_encoding(ext_enc, int_enc) -> ARGF
12435 * ARGF.set_encoding("ext_enc:int_enc", opt) -> ARGF
12436 * ARGF.set_encoding(ext_enc, int_enc, opt) -> ARGF
12438 * If single argument is specified, strings read from ARGF are tagged with
12439 * the encoding specified.
12441 * If two encoding names separated by a colon are given, e.g. "ascii:utf-8",
12442 * the read string is converted from the first encoding (external encoding)
12443 * to the second encoding (internal encoding), then tagged with the second
12446 * If two arguments are specified, they must be encoding objects or encoding
12447 * names. Again, the first specifies the external encoding; the second
12448 * specifies the internal encoding.
12450 * If the external encoding and the internal encoding are specified, the
12451 * optional +Hash+ argument can be used to adjust the conversion process. The
12452 * structure of this hash is explained in the String#encode documentation.
12456 * ARGF.set_encoding('ascii') # Tag the input as US-ASCII text
12457 * ARGF.set_encoding(Encoding::UTF_8) # Tag the input as UTF-8 text
12458 * ARGF.set_encoding('utf-8','ascii') # Transcode the input from US-ASCII
12462 argf_set_encoding(int argc
, VALUE
*argv
, VALUE argf
)
12466 if (!next_argv()) {
12467 rb_raise(rb_eArgError
, "no stream to set encoding");
12469 rb_io_set_encoding(argc
, argv
, ARGF
.current_file
);
12470 GetOpenFile(ARGF
.current_file
, fptr
);
12471 ARGF
.encs
= fptr
->encs
;
12477 * ARGF.tell -> Integer
12478 * ARGF.pos -> Integer
12480 * Returns the current offset (in bytes) of the current file in +ARGF+.
12483 * ARGF.gets #=> "This is line one\n"
12488 argf_tell(VALUE argf
)
12490 if (!next_argv()) {
12491 rb_raise(rb_eArgError
, "no stream to tell");
12493 ARGF_FORWARD(0, 0);
12494 return rb_io_tell(ARGF
.current_file
);
12499 * ARGF.seek(amount, whence=IO::SEEK_SET) -> 0
12501 * Seeks to offset _amount_ (an +Integer+) in the +ARGF+ stream according to
12502 * the value of _whence_. See IO#seek for further details.
12505 argf_seek_m(int argc
, VALUE
*argv
, VALUE argf
)
12507 if (!next_argv()) {
12508 rb_raise(rb_eArgError
, "no stream to seek");
12510 ARGF_FORWARD(argc
, argv
);
12511 return rb_io_seek_m(argc
, argv
, ARGF
.current_file
);
12516 * ARGF.pos = position -> Integer
12518 * Seeks to the position given by _position_ (in bytes) in +ARGF+.
12523 * ARGF.gets #=> "This is line two\n"
12526 argf_set_pos(VALUE argf
, VALUE offset
)
12528 if (!next_argv()) {
12529 rb_raise(rb_eArgError
, "no stream to set position");
12531 ARGF_FORWARD(1, &offset
);
12532 return rb_io_set_pos(ARGF
.current_file
, offset
);
12539 * Positions the current file to the beginning of input, resetting
12540 * +ARGF.lineno+ to zero.
12542 * ARGF.readline #=> "This is line one\n"
12543 * ARGF.rewind #=> 0
12544 * ARGF.lineno #=> 0
12545 * ARGF.readline #=> "This is line one\n"
12548 argf_rewind(VALUE argf
)
12553 if (!next_argv()) {
12554 rb_raise(rb_eArgError
, "no stream to rewind");
12556 ARGF_FORWARD(0, 0);
12557 old_lineno
= RFILE(ARGF
.current_file
)->fptr
->lineno
;
12558 ret
= rb_io_rewind(ARGF
.current_file
);
12559 if (!global_argf_p(argf
)) {
12560 ARGF
.last_lineno
= ARGF
.lineno
-= old_lineno
;
12567 * ARGF.fileno -> integer
12568 * ARGF.to_i -> integer
12570 * Returns an integer representing the numeric file descriptor for
12571 * the current file. Raises an +ArgumentError+ if there isn't a current file.
12573 * ARGF.fileno #=> 3
12576 argf_fileno(VALUE argf
)
12578 if (!next_argv()) {
12579 rb_raise(rb_eArgError
, "no stream");
12581 ARGF_FORWARD(0, 0);
12582 return rb_io_fileno(ARGF
.current_file
);
12589 * Returns an +IO+ object representing the current file. This will be a
12590 * +File+ object unless the current file is a stream such as STDIN.
12594 * ARGF.to_io #=> #<File:glark.txt>
12595 * ARGF.to_io #=> #<IO:<STDIN>>
12598 argf_to_io(VALUE argf
)
12601 ARGF_FORWARD(0, 0);
12602 return ARGF
.current_file
;
12607 * ARGF.eof? -> true or false
12608 * ARGF.eof -> true or false
12610 * Returns true if the current file in +ARGF+ is at end of file, i.e. it has
12611 * no data to read. The stream must be opened for reading or an +IOError+
12614 * $ echo "eof" | ruby argf.rb
12616 * ARGF.eof? #=> false
12617 * 3.times { ARGF.readchar }
12618 * ARGF.eof? #=> false
12619 * ARGF.readchar #=> "\n"
12620 * ARGF.eof? #=> true
12624 argf_eof(VALUE argf
)
12627 if (RTEST(ARGF
.current_file
)) {
12628 if (ARGF
.init_p
== 0) return Qtrue
;
12630 ARGF_FORWARD(0, 0);
12631 if (rb_io_eof(ARGF
.current_file
)) {
12640 * ARGF.read([length [, outbuf]]) -> string, outbuf, or nil
12642 * Reads _length_ bytes from ARGF. The files named on the command line
12643 * are concatenated and treated as a single file by this method, so when
12644 * called without arguments the contents of this pseudo file are returned in
12647 * _length_ must be a non-negative integer or +nil+.
12649 * If _length_ is a positive integer, +read+ tries to read
12650 * _length_ bytes without any conversion (binary mode).
12651 * It returns +nil+ if an EOF is encountered before anything can be read.
12652 * Fewer than _length_ bytes are returned if an EOF is encountered during
12654 * In the case of an integer _length_, the resulting string is always
12655 * in ASCII-8BIT encoding.
12657 * If _length_ is omitted or is +nil+, it reads until EOF
12658 * and the encoding conversion is applied, if applicable.
12659 * A string is returned even if EOF is encountered before any data is read.
12661 * If _length_ is zero, it returns an empty string (<code>""</code>).
12663 * If the optional _outbuf_ argument is present,
12664 * it must reference a String, which will receive the data.
12665 * The _outbuf_ will contain only the received data after the method call
12666 * even if it is not empty at the beginning.
12670 * $ echo "small" > small.txt
12671 * $ echo "large" > large.txt
12672 * $ ./glark.rb small.txt large.txt
12674 * ARGF.read #=> "small\nlarge"
12675 * ARGF.read(200) #=> "small\nlarge"
12676 * ARGF.read(2) #=> "sm"
12677 * ARGF.read(0) #=> ""
12679 * Note that this method behaves like the fread() function in C.
12680 * This means it retries to invoke read(2) system calls to read data
12681 * with the specified length.
12682 * If you need the behavior like a single read(2) system call,
12683 * consider ARGF#readpartial or ARGF#read_nonblock.
12687 argf_read(int argc
, VALUE
*argv
, VALUE argf
)
12689 VALUE tmp
, str
, length
;
12692 rb_scan_args(argc
, argv
, "02", &length
, &str
);
12693 if (!NIL_P(length
)) {
12694 len
= NUM2LONG(argv
[0]);
12698 rb_str_resize(str
,0);
12703 if (!next_argv()) {
12706 if (ARGF_GENERIC_INPUT_P()) {
12707 tmp
= argf_forward(argc
, argv
, argf
);
12710 tmp
= io_read(argc
, argv
, ARGF
.current_file
);
12712 if (NIL_P(str
)) str
= tmp
;
12713 else if (!NIL_P(tmp
)) rb_str_append(str
, tmp
);
12714 if (NIL_P(tmp
) || NIL_P(length
)) {
12715 if (ARGF
.next_p
!= -1) {
12721 else if (argc
>= 1) {
12722 long slen
= RSTRING_LEN(str
);
12724 argv
[0] = LONG2NUM(len
- slen
);
12731 struct argf_call_arg
{
12738 argf_forward_call(VALUE arg
)
12740 struct argf_call_arg
*p
= (struct argf_call_arg
*)arg
;
12741 argf_forward(p
->argc
, p
->argv
, p
->argf
);
12745 static VALUE
argf_getpartial(int argc
, VALUE
*argv
, VALUE argf
, VALUE opts
,
12750 * ARGF.readpartial(maxlen) -> string
12751 * ARGF.readpartial(maxlen, outbuf) -> outbuf
12753 * Reads at most _maxlen_ bytes from the ARGF stream.
12755 * If the optional _outbuf_ argument is present,
12756 * it must reference a String, which will receive the data.
12757 * The _outbuf_ will contain only the received data after the method call
12758 * even if it is not empty at the beginning.
12760 * It raises EOFError on end of ARGF stream.
12761 * Since ARGF stream is a concatenation of multiple files,
12762 * internally EOF is occur for each file.
12763 * ARGF.readpartial returns empty strings for EOFs except the last one and
12764 * raises EOFError for the last one.
12769 argf_readpartial(int argc
, VALUE
*argv
, VALUE argf
)
12771 return argf_getpartial(argc
, argv
, argf
, Qnil
, 0);
12776 * ARGF.read_nonblock(maxlen[, options]) -> string
12777 * ARGF.read_nonblock(maxlen, outbuf[, options]) -> outbuf
12779 * Reads at most _maxlen_ bytes from the ARGF stream in non-blocking mode.
12783 argf_read_nonblock(int argc
, VALUE
*argv
, VALUE argf
)
12787 rb_scan_args(argc
, argv
, "11:", NULL
, NULL
, &opts
);
12792 return argf_getpartial(argc
, argv
, argf
, opts
, 1);
12796 argf_getpartial(int argc
, VALUE
*argv
, VALUE argf
, VALUE opts
, int nonblock
)
12798 VALUE tmp
, str
, length
;
12801 rb_scan_args(argc
, argv
, "11", &length
, &str
);
12806 no_exception
= no_exception_p(opts
);
12808 if (!next_argv()) {
12810 rb_str_resize(str
, 0);
12814 if (ARGF_GENERIC_INPUT_P()) {
12815 VALUE (*const rescue_does_nothing
)(VALUE
, VALUE
) = 0;
12816 struct argf_call_arg arg
;
12820 tmp
= rb_rescue2(argf_forward_call
, (VALUE
)&arg
,
12821 rescue_does_nothing
, Qnil
, rb_eEOFError
, (VALUE
)0);
12824 tmp
= io_getpartial(argc
, argv
, ARGF
.current_file
, no_exception
, nonblock
);
12827 if (ARGF
.next_p
== -1) {
12828 return io_nonblock_eof(no_exception
);
12832 if (RARRAY_LEN(ARGF
.argv
) == 0) {
12833 return io_nonblock_eof(no_exception
);
12836 str
= rb_str_new(NULL
, 0);
12844 * ARGF.getc -> String or nil
12846 * Reads the next character from +ARGF+ and returns it as a +String+. Returns
12847 * +nil+ at the end of the stream.
12849 * +ARGF+ treats the files named on the command line as a single file created
12850 * by concatenating their contents. After returning the last character of the
12851 * first file, it returns the first character of the second file, and so on.
12855 * $ echo "foo" > file
12856 * $ ruby argf.rb file
12858 * ARGF.getc #=> "f"
12859 * ARGF.getc #=> "o"
12860 * ARGF.getc #=> "o"
12861 * ARGF.getc #=> "\n"
12862 * ARGF.getc #=> nil
12863 * ARGF.getc #=> nil
12866 argf_getc(VALUE argf
)
12871 if (!next_argv()) return Qnil
;
12872 if (ARGF_GENERIC_INPUT_P()) {
12873 ch
= forward_current(rb_intern("getc"), 0, 0);
12876 ch
= rb_io_getc(ARGF
.current_file
);
12878 if (NIL_P(ch
) && ARGF
.next_p
!= -1) {
12889 * ARGF.getbyte -> Integer or nil
12891 * Gets the next 8-bit byte (0..255) from +ARGF+. Returns +nil+ if called at
12892 * the end of the stream.
12896 * $ echo "foo" > file
12897 * $ ruby argf.rb file
12899 * ARGF.getbyte #=> 102
12900 * ARGF.getbyte #=> 111
12901 * ARGF.getbyte #=> 111
12902 * ARGF.getbyte #=> 10
12903 * ARGF.getbyte #=> nil
12906 argf_getbyte(VALUE argf
)
12911 if (!next_argv()) return Qnil
;
12912 if (!RB_TYPE_P(ARGF
.current_file
, T_FILE
)) {
12913 ch
= forward_current(rb_intern("getbyte"), 0, 0);
12916 ch
= rb_io_getbyte(ARGF
.current_file
);
12918 if (NIL_P(ch
) && ARGF
.next_p
!= -1) {
12929 * ARGF.readchar -> String or nil
12931 * Reads the next character from +ARGF+ and returns it as a +String+. Raises
12932 * an +EOFError+ after the last character of the last file has been read.
12936 * $ echo "foo" > file
12937 * $ ruby argf.rb file
12939 * ARGF.readchar #=> "f"
12940 * ARGF.readchar #=> "o"
12941 * ARGF.readchar #=> "o"
12942 * ARGF.readchar #=> "\n"
12943 * ARGF.readchar #=> end of file reached (EOFError)
12946 argf_readchar(VALUE argf
)
12951 if (!next_argv()) rb_eof_error();
12952 if (!RB_TYPE_P(ARGF
.current_file
, T_FILE
)) {
12953 ch
= forward_current(rb_intern("getc"), 0, 0);
12956 ch
= rb_io_getc(ARGF
.current_file
);
12958 if (NIL_P(ch
) && ARGF
.next_p
!= -1) {
12969 * ARGF.readbyte -> Integer
12971 * Reads the next 8-bit byte from ARGF and returns it as an +Integer+. Raises
12972 * an +EOFError+ after the last byte of the last file has been read.
12976 * $ echo "foo" > file
12977 * $ ruby argf.rb file
12979 * ARGF.readbyte #=> 102
12980 * ARGF.readbyte #=> 111
12981 * ARGF.readbyte #=> 111
12982 * ARGF.readbyte #=> 10
12983 * ARGF.readbyte #=> end of file reached (EOFError)
12986 argf_readbyte(VALUE argf
)
12990 NEXT_ARGF_FORWARD(0, 0);
12991 c
= argf_getbyte(argf
);
12998 #define FOREACH_ARGF() while (next_argv())
13001 argf_block_call_i(RB_BLOCK_CALL_FUNC_ARGLIST(i
, argf
))
13003 const VALUE current
= ARGF
.current_file
;
13004 rb_yield_values2(argc
, argv
);
13005 if (ARGF
.init_p
== -1 || current
!= ARGF
.current_file
) {
13006 rb_iter_break_value(Qundef
);
13011 #define ARGF_block_call(mid, argc, argv, func, argf) \
13012 rb_block_call_kw(ARGF.current_file, mid, argc, argv, \
13013 func, argf, rb_keyword_given_p())
13016 argf_block_call(ID mid
, int argc
, VALUE
*argv
, VALUE argf
)
13018 VALUE ret
= ARGF_block_call(mid
, argc
, argv
, argf_block_call_i
, argf
);
13019 if (ret
!= Qundef
) ARGF
.next_p
= 1;
13023 argf_block_call_line_i(RB_BLOCK_CALL_FUNC_ARGLIST(i
, argf
))
13025 if (!global_argf_p(argf
)) {
13026 ARGF
.last_lineno
= ++ARGF
.lineno
;
13028 return argf_block_call_i(i
, argf
, argc
, argv
, blockarg
);
13032 argf_block_call_line(ID mid
, int argc
, VALUE
*argv
, VALUE argf
)
13034 VALUE ret
= ARGF_block_call(mid
, argc
, argv
, argf_block_call_line_i
, argf
);
13035 if (ret
!= Qundef
) ARGF
.next_p
= 1;
13040 * ARGF.each(sep=$/) {|line| block } -> ARGF
13041 * ARGF.each(sep=$/, limit) {|line| block } -> ARGF
13042 * ARGF.each(...) -> an_enumerator
13044 * ARGF.each_line(sep=$/) {|line| block } -> ARGF
13045 * ARGF.each_line(sep=$/, limit) {|line| block } -> ARGF
13046 * ARGF.each_line(...) -> an_enumerator
13048 * Returns an enumerator which iterates over each line (separated by _sep_,
13049 * which defaults to your platform's newline character) of each file in
13050 * +ARGV+. If a block is supplied, each line in turn will be yielded to the
13051 * block, otherwise an enumerator is returned.
13052 * The optional _limit_ argument is an +Integer+ specifying the maximum
13053 * length of each line; longer lines will be split according to this limit.
13055 * This method allows you to treat the files supplied on the command line as
13056 * a single file consisting of the concatenation of each named file. After
13057 * the last line of the first file has been returned, the first line of the
13058 * second file is returned. The +ARGF.filename+ and +ARGF.lineno+ methods can
13059 * be used to determine the filename of the current line and line number of
13060 * the whole input, respectively.
13062 * For example, the following code prints out each line of each named file
13063 * prefixed with its line number, displaying the filename once per file:
13065 * ARGF.each_line do |line|
13066 * puts ARGF.filename if ARGF.file.lineno == 1
13067 * puts "#{ARGF.file.lineno}: #{line}"
13070 * While the following code prints only the first file's name at first, and
13071 * the contents with line number counted through all named files.
13073 * ARGF.each_line do |line|
13074 * puts ARGF.filename if ARGF.lineno == 1
13075 * puts "#{ARGF.lineno}: #{line}"
13079 argf_each_line(int argc
, VALUE
*argv
, VALUE argf
)
13081 RETURN_ENUMERATOR(argf
, argc
, argv
);
13083 argf_block_call_line(rb_intern("each_line"), argc
, argv
, argf
);
13090 * ARGF.each_byte {|byte| block } -> ARGF
13091 * ARGF.each_byte -> an_enumerator
13093 * Iterates over each byte of each file in +ARGV+.
13094 * A byte is returned as an +Integer+ in the range 0..255.
13096 * This method allows you to treat the files supplied on the command line as
13097 * a single file consisting of the concatenation of each named file. After
13098 * the last byte of the first file has been returned, the first byte of the
13099 * second file is returned. The +ARGF.filename+ method can be used to
13100 * determine the filename of the current byte.
13102 * If no block is given, an enumerator is returned instead.
13106 * ARGF.bytes.to_a #=> [35, 32, ... 95, 10]
13110 argf_each_byte(VALUE argf
)
13112 RETURN_ENUMERATOR(argf
, 0, 0);
13114 argf_block_call(rb_intern("each_byte"), 0, 0, argf
);
13121 * ARGF.each_char {|char| block } -> ARGF
13122 * ARGF.each_char -> an_enumerator
13124 * Iterates over each character of each file in +ARGF+.
13126 * This method allows you to treat the files supplied on the command line as
13127 * a single file consisting of the concatenation of each named file. After
13128 * the last character of the first file has been returned, the first
13129 * character of the second file is returned. The +ARGF.filename+ method can
13130 * be used to determine the name of the file in which the current character
13133 * If no block is given, an enumerator is returned instead.
13136 argf_each_char(VALUE argf
)
13138 RETURN_ENUMERATOR(argf
, 0, 0);
13140 argf_block_call(rb_intern("each_char"), 0, 0, argf
);
13147 * ARGF.each_codepoint {|codepoint| block } -> ARGF
13148 * ARGF.each_codepoint -> an_enumerator
13150 * Iterates over each codepoint of each file in +ARGF+.
13152 * This method allows you to treat the files supplied on the command line as
13153 * a single file consisting of the concatenation of each named file. After
13154 * the last codepoint of the first file has been returned, the first
13155 * codepoint of the second file is returned. The +ARGF.filename+ method can
13156 * be used to determine the name of the file in which the current codepoint
13159 * If no block is given, an enumerator is returned instead.
13162 argf_each_codepoint(VALUE argf
)
13164 RETURN_ENUMERATOR(argf
, 0, 0);
13166 argf_block_call(rb_intern("each_codepoint"), 0, 0, argf
);
13173 * ARGF.filename -> String
13174 * ARGF.path -> String
13176 * Returns the current filename. "-" is returned when the current file is
13181 * $ echo "foo" > foo
13182 * $ echo "bar" > bar
13183 * $ echo "glark" > glark
13185 * $ ruby argf.rb foo bar glark
13187 * ARGF.filename #=> "foo"
13188 * ARGF.read(5) #=> "foo\nb"
13189 * ARGF.filename #=> "bar"
13191 * ARGF.filename #=> "glark"
13194 argf_filename(VALUE argf
)
13197 return ARGF
.filename
;
13201 argf_filename_getter(ID id
, VALUE
*var
)
13203 return argf_filename(*var
);
13208 * ARGF.file -> IO or File object
13210 * Returns the current file as an +IO+ or +File+ object.
13211 * <code>$stdin</code> is returned when the current file is STDIN.
13215 * $ echo "foo" > foo
13216 * $ echo "bar" > bar
13218 * $ ruby argf.rb foo bar
13220 * ARGF.file #=> #<File:foo>
13221 * ARGF.read(5) #=> "foo\nb"
13222 * ARGF.file #=> #<File:bar>
13225 argf_file(VALUE argf
)
13228 return ARGF
.current_file
;
13233 * ARGF.binmode -> ARGF
13235 * Puts +ARGF+ into binary mode. Once a stream is in binary mode, it cannot
13236 * be reset to non-binary mode. This option has the following effects:
13238 * * Newline conversion is disabled.
13239 * * Encoding conversion is disabled.
13240 * * Content is treated as ASCII-8BIT.
13243 argf_binmode_m(VALUE argf
)
13247 ARGF_FORWARD(0, 0);
13248 rb_io_ascii8bit_binmode(ARGF
.current_file
);
13254 * ARGF.binmode? -> true or false
13256 * Returns true if +ARGF+ is being read in binary mode; false otherwise.
13257 * To enable binary mode use +ARGF.binmode+.
13261 * ARGF.binmode? #=> false
13263 * ARGF.binmode? #=> true
13266 argf_binmode_p(VALUE argf
)
13268 return RBOOL(ARGF
.binmode
);
13273 * ARGF.skip -> ARGF
13275 * Sets the current file to the next file in ARGV. If there aren't any more
13276 * files it has no effect.
13280 * $ ruby argf.rb foo bar
13281 * ARGF.filename #=> "foo"
13283 * ARGF.filename #=> "bar"
13286 argf_skip(VALUE argf
)
13288 if (ARGF
.init_p
&& ARGF
.next_p
== 0) {
13297 * ARGF.close -> ARGF
13299 * Closes the current file and skips to the next file in ARGV. If there are
13300 * no more files to open, just closes the current file. +STDIN+ will not be
13305 * $ ruby argf.rb foo bar
13307 * ARGF.filename #=> "foo"
13309 * ARGF.filename #=> "bar"
13313 argf_close_m(VALUE argf
)
13317 if (ARGF
.next_p
!= -1) {
13326 * ARGF.closed? -> true or false
13328 * Returns _true_ if the current file has been closed; _false_ otherwise. Use
13329 * +ARGF.close+ to actually close the current file.
13332 argf_closed(VALUE argf
)
13335 ARGF_FORWARD(0, 0);
13336 return rb_io_closed(ARGF
.current_file
);
13341 * ARGF.to_s -> String
13346 argf_to_s(VALUE argf
)
13348 return rb_str_new2("ARGF");
13353 * ARGF.inplace_mode -> String
13355 * Returns the file extension appended to the names of modified files under
13356 * in-place edit mode. This value can be set using +ARGF.inplace_mode=+ or
13357 * passing the +-i+ switch to the Ruby binary.
13360 argf_inplace_mode_get(VALUE argf
)
13362 if (!ARGF
.inplace
) return Qnil
;
13363 if (NIL_P(ARGF
.inplace
)) return rb_str_new(0, 0);
13364 return rb_str_dup(ARGF
.inplace
);
13368 opt_i_get(ID id
, VALUE
*var
)
13370 return argf_inplace_mode_get(*var
);
13375 * ARGF.inplace_mode = ext -> ARGF
13377 * Sets the filename extension for in-place editing mode to the given String.
13378 * Each file being edited has this value appended to its filename. The
13379 * modified file is saved under this new name.
13383 * $ ruby argf.rb file.txt
13385 * ARGF.inplace_mode = '.bak'
13386 * ARGF.each_line do |line|
13387 * print line.sub("foo","bar")
13390 * Each line of _file.txt_ has the first occurrence of "foo" replaced with
13391 * "bar", then the new line is written out to _file.txt.bak_.
13394 argf_inplace_mode_set(VALUE argf
, VALUE val
)
13397 ARGF
.inplace
= Qfalse
;
13399 else if (StringValueCStr(val
), !RSTRING_LEN(val
)) {
13400 ARGF
.inplace
= Qnil
;
13403 ARGF
.inplace
= rb_str_new_frozen(val
);
13409 opt_i_set(VALUE val
, ID id
, VALUE
*var
)
13411 argf_inplace_mode_set(*var
, val
);
13415 ruby_set_inplace_mode(const char *suffix
)
13417 ARGF
.inplace
= !suffix
? Qfalse
: !*suffix
? Qnil
: rb_str_new(suffix
, strlen(suffix
));
13422 * ARGF.argv -> ARGV
13424 * Returns the +ARGV+ array, which contains the arguments passed to your
13425 * script, one per element.
13429 * $ ruby argf.rb -v glark.txt
13431 * ARGF.argv #=> ["-v", "glark.txt"]
13435 argf_argv(VALUE argf
)
13441 argf_argv_getter(ID id
, VALUE
*var
)
13443 return argf_argv(*var
);
13454 * ARGF.to_write_io -> io
13456 * Returns IO instance tied to _ARGF_ for writing if inplace mode is
13460 argf_write_io(VALUE argf
)
13462 if (!RTEST(ARGF
.current_file
)) {
13463 rb_raise(rb_eIOError
, "not opened for writing");
13465 return GetWriteIO(ARGF
.current_file
);
13470 * ARGF.write(string) -> integer
13472 * Writes _string_ if inplace mode.
13475 argf_write(VALUE argf
, VALUE str
)
13477 return rb_io_write(argf_write_io(argf
), str
);
13481 rb_readwrite_sys_fail(enum rb_io_wait_readwrite waiting
, const char *mesg
)
13483 rb_readwrite_syserr_fail(waiting
, errno
, mesg
);
13487 rb_readwrite_syserr_fail(enum rb_io_wait_readwrite waiting
, int n
, const char *mesg
)
13489 VALUE arg
, c
= Qnil
;
13490 arg
= mesg
? rb_str_new2(mesg
) : Qnil
;
13492 case RB_IO_WAIT_WRITABLE
:
13495 c
= rb_eEAGAINWaitWritable
;
13497 #if EAGAIN != EWOULDBLOCK
13499 c
= rb_eEWOULDBLOCKWaitWritable
;
13503 c
= rb_eEINPROGRESSWaitWritable
;
13506 rb_mod_syserr_fail_str(rb_mWaitWritable
, n
, arg
);
13509 case RB_IO_WAIT_READABLE
:
13512 c
= rb_eEAGAINWaitReadable
;
13514 #if EAGAIN != EWOULDBLOCK
13516 c
= rb_eEWOULDBLOCKWaitReadable
;
13520 c
= rb_eEINPROGRESSWaitReadable
;
13523 rb_mod_syserr_fail_str(rb_mWaitReadable
, n
, arg
);
13527 rb_bug("invalid read/write type passed to rb_readwrite_sys_fail: %d", waiting
);
13529 rb_exc_raise(rb_class_new_instance(1, &arg
, c
));
13533 get_LAST_READ_LINE(ID _x
, VALUE
*_y
)
13535 return rb_lastline_get();
13539 set_LAST_READ_LINE(VALUE val
, ID _x
, VALUE
*_y
)
13541 rb_lastline_set(val
);
13545 * Document-class: IOError
13547 * Raised when an IO operation fails.
13549 * File.open("/etc/hosts") {|f| f << "example"}
13550 * #=> IOError: not opened for writing
13552 * File.open("/etc/hosts") {|f| f.close; f.read }
13553 * #=> IOError: closed stream
13555 * Note that some IO failures raise <code>SystemCallError</code>s
13556 * and these are not subclasses of IOError:
13558 * File.open("does/not/exist")
13559 * #=> Errno::ENOENT: No such file or directory - does/not/exist
13563 * Document-class: EOFError
13565 * Raised by some IO operations when reaching the end of file. Many IO
13566 * methods exist in two forms,
13568 * one that returns +nil+ when the end of file is reached, the other
13569 * raises +EOFError+.
13571 * +EOFError+ is a subclass of +IOError+.
13573 * file = File.open("/etc/hosts")
13575 * file.gets #=> nil
13576 * file.readline #=> EOFError: end of file reached
13580 * Document-class: ARGF
13582 * +ARGF+ is a stream designed for use in scripts that process files given as
13583 * command-line arguments or passed in via STDIN.
13585 * The arguments passed to your script are stored in the +ARGV+ Array, one
13586 * argument per element. +ARGF+ assumes that any arguments that aren't
13587 * filenames have been removed from +ARGV+. For example:
13589 * $ ruby argf.rb --verbose file1 file2
13591 * ARGV #=> ["--verbose", "file1", "file2"]
13592 * option = ARGV.shift #=> "--verbose"
13593 * ARGV #=> ["file1", "file2"]
13595 * You can now use +ARGF+ to work with a concatenation of each of these named
13596 * files. For instance, +ARGF.read+ will return the contents of _file1_
13597 * followed by the contents of _file2_.
13599 * After a file in +ARGV+ has been read +ARGF+ removes it from the Array.
13600 * Thus, after all files have been read +ARGV+ will be empty.
13602 * You can manipulate +ARGV+ yourself to control what +ARGF+ operates on. If
13603 * you remove a file from +ARGV+, it is ignored by +ARGF+; if you add files to
13604 * +ARGV+, they are treated as if they were named on the command line. For
13607 * ARGV.replace ["file1"]
13608 * ARGF.readlines # Returns the contents of file1 as an Array
13610 * ARGV.replace ["file2", "file3"]
13611 * ARGF.read # Returns the contents of file2 and file3
13613 * If +ARGV+ is empty, +ARGF+ acts as if it contained STDIN, i.e. the data
13614 * piped to your script. For example:
13616 * $ echo "glark" | ruby -e 'p ARGF.read'
13621 * The IO class is the basis for all input and output in Ruby.
13622 * An I/O stream may be <em>duplexed</em> (that is, bidirectional), and
13623 * so may use more than one native operating system stream.
13625 * Many of the examples in this section use the File class, the only standard
13626 * subclass of IO. The two classes are closely associated. Like the File
13627 * class, the Socket library subclasses from IO (such as TCPSocket or
13630 * The Kernel#open method can create an IO (or File) object for these types
13633 * * A plain string represents a filename suitable for the underlying
13634 * operating system.
13636 * * A string starting with <code>"|"</code> indicates a subprocess.
13637 * The remainder of the string following the <code>"|"</code> is
13638 * invoked as a process with appropriate input/output channels
13641 * * A string equal to <code>"|-"</code> will create another Ruby
13642 * instance as a subprocess.
13644 * The IO may be opened with different file modes (read-only, write-only) and
13645 * encodings for proper conversion. See IO.new for these options. See
13646 * Kernel#open for details of the various command formats described above.
13648 * IO.popen, the Open3 library, or Process#spawn may also be used to
13649 * communicate with subprocesses through an IO.
13651 * Ruby will convert pathnames between different operating system
13652 * conventions if possible. For instance, on a Windows system the
13653 * filename <code>"/gumby/ruby/test.rb"</code> will be opened as
13654 * <code>"\gumby\ruby\test.rb"</code>. When specifying a Windows-style
13655 * filename in a Ruby string, remember to escape the backslashes:
13657 * "C:\\gumby\\ruby\\test.rb"
13659 * Our examples here will use the Unix-style forward slashes;
13660 * File::ALT_SEPARATOR can be used to get the platform-specific separator
13663 * The global constant ARGF (also accessible as <code>$<</code>) provides an
13664 * IO-like stream which allows access to all files mentioned on the
13665 * command line (or STDIN if no files are mentioned). ARGF#path and its alias
13666 * ARGF#filename are provided to access the name of the file currently being
13671 * The io/console extension provides methods for interacting with the
13672 * console. The console can be accessed from IO.console or the standard
13673 * input/output/error IO objects.
13675 * Requiring io/console adds the following methods:
13694 * require 'io/console'
13695 * rows, columns = $stdout.winsize
13696 * puts "Your screen is #{columns} wide and #{rows} tall"
13700 * Many examples here use these filenames and their corresponding files:
13702 * - <tt>t.txt</tt>: A text-only file that is assumed to exist via:
13711 * File.write('t.txt', text)
13713 * - <tt>t.dat</tt>: A data file that is assumed to exist via:
13715 * data = "\u9990\u9991\u9992\u9993\u9994"
13716 * f = File.open('t.dat', 'wb:UTF-16')
13720 * - <tt>t.rus</tt>: A Russian-language text file that is assumed to exist via:
13722 * File.write('t.rus', "\u{442 435 441 442}")
13724 * - <tt>t.tmp</tt>: A file that is assumed _not_ to exist.
13728 * A number of \IO method calls must or may specify a _mode_ for the stream;
13729 * the mode determines how stream is to be accessible, including:
13731 * - Whether the stream is to be read-only, write-only, or read-write.
13732 * - Whether the stream is positioned at its beginning or its end.
13733 * - Whether the stream treats data as text-only or binary.
13734 * - The external and internal encodings.
13736 * === Mode Specified as an \Integer
13738 * When +mode+ is an integer it must be one or more (combined by bitwise OR (<tt>|</tt>)
13739 * of the modes defined in File::Constants:
13741 * - +File::RDONLY+: Open for reading only.
13742 * - +File::WRONLY+: Open for writing only.
13743 * - +File::RDWR+: Open for reading and writing.
13744 * - +File::APPEND+: Open for appending only.
13745 * - +File::CREAT+: Create file if it does not exist.
13746 * - +File::EXCL+: Raise an exception if +File::CREAT+ is given and the file exists.
13750 * File.new('t.txt', File::RDONLY)
13751 * File.new('t.tmp', File::RDWR | File::CREAT | File::EXCL)
13753 * Note: Method IO#set_encoding does not allow the mode to be specified as an integer.
13755 * === Mode Specified As a \String
13757 * When +mode+ is a string it must begin with one of the following:
13759 * - <tt>'r'</tt>: Read-only stream, positioned at the beginning;
13760 * the stream cannot be changed to writable.
13761 * - <tt>'w'</tt>: Write-only stream, positioned at the beginning;
13762 * the stream cannot be changed to readable.
13763 * - <tt>'a'</tt>: Write-only stream, positioned at the end;
13764 * every write appends to the end;
13765 * the stream cannot be changed to readable.
13766 * - <tt>'r+'</tt>: Read-write stream, positioned at the beginning.
13767 * - <tt>'w+'</tt>: Read-write stream, positioned at the end.
13768 * - <tt>'a+'</tt>: Read-write stream, positioned at the end.
13770 * For a writable file stream (that is, any except read-only),
13771 * the file is truncated to zero if it exists,
13772 * and is created if it does not exist.
13776 * File.open('t.txt', 'r')
13777 * File.open('t.tmp', 'w')
13779 * Either of the following may be suffixed to any of the above:
13781 * - <tt>'t'</tt>: Text data; sets the default external encoding to +Encoding::UTF_8+;
13782 * on Windows, enables conversion between EOL and CRLF.
13783 * - <tt>'b'</tt>: Binary data; sets the default external encoding to +Encoding::ASCII_8BIT+;
13784 * on Windows, suppresses conversion between EOL and CRLF.
13786 * If neither is given, the stream defaults to text data.
13790 * File.open('t.txt', 'rt')
13791 * File.open('t.dat', 'rb')
13793 * The following may be suffixed to any writable mode above:
13795 * - <tt>'x'</tt>: Creates the file if it does not exist;
13796 * raises an exception if the file exists.
13800 * File.open('t.tmp', 'wx')
13802 * Finally, the mode string may specify encodings --
13803 * either external encoding only or both external and internal encodings --
13804 * by appending one or both encoding names, separated by colons:
13806 * f = File.new('t.dat', 'rb')
13807 * f.external_encoding # => #<Encoding:ASCII-8BIT>
13808 * f.internal_encoding # => nil
13809 * f = File.new('t.dat', 'rb:UTF-16')
13810 * f.external_encoding # => #<Encoding:UTF-16 (dummy)>
13811 * f.internal_encoding # => nil
13812 * f = File.new('t.dat', 'rb:UTF-16:UTF-16')
13813 * f.external_encoding # => #<Encoding:UTF-16 (dummy)>
13814 * f.internal_encoding # => #<Encoding:UTF-16>
13816 * The numerous encoding names are available in array Encoding.name_list:
13818 * Encoding.name_list.size # => 175
13819 * Encoding.name_list.take(3) # => ["ASCII-8BIT", "UTF-8", "US-ASCII"]
13823 * When the external encoding is set,
13824 * strings read are tagged by that encoding
13825 * when reading, and strings written are converted to that
13826 * encoding when writing.
13828 * When both external and internal encodings are set,
13829 * strings read are converted from external to internal encoding,
13830 * and strings written are converted from internal to external encoding.
13831 * For further details about transcoding input and output, see Encoding.
13833 * If the external encoding is <tt>'BOM|UTF-8'</tt>, <tt>'BOM|UTF-16LE'</tt>
13834 * or <tt>'BOM|UTF16-BE'</tt>, Ruby checks for
13835 * a Unicode BOM in the input document to help determine the encoding. For
13836 * UTF-16 encodings the file open mode must be binary.
13837 * If the BOM is found, it is stripped and the external encoding from the BOM is used.
13839 * Note that the BOM-style encoding option is case insensitive,
13840 * so 'bom|utf-8' is also valid.)
13844 * A number of \IO methods accept optional keyword arguments
13845 * that determine how a new stream is to be opened:
13847 * - +:mode+: Stream mode.
13848 * - +:flags+: \Integer file open flags;
13849 * If +mode+ is also given, the two are bitwise-ORed.
13850 * - +:external_encoding+: External encoding for the stream.
13851 * - +:internal_encoding+: Internal encoding for the stream.
13852 * <tt>'-'</tt> is a synonym for the default internal encoding.
13853 * If the value is +nil+ no conversion occurs.
13854 * - +:encoding+: Specifies external and internal encodings as <tt>'extern:intern'</tt>.
13855 * - +:textmode+: If a truthy value, specifies the mode as text-only, binary otherwise.
13856 * - +:binmode+: If a truthy value, specifies the mode as binary, text-only otherwise.
13857 * - +:autoclose+: If a truthy value, specifies that the +fd+ will close
13858 * when the stream closes; otherwise it remains open.
13860 * Also available are the options offered in String#encode,
13861 * which may control conversion between external internal encoding.
13863 * == Getline Options
13865 * A number of \IO methods accept optional keyword arguments
13866 * that determine how a stream is to be treated:
13868 * - +:chomp+: If +true+, line separators are omitted; default is +false+.
13872 * An \IO stream has a _position_, which is the non-negative integer offset
13873 * (in bytes) in the stream where the next read or write will occur.
13875 * Note that a text stream may have multi-byte characters,
13876 * so a text stream whose position is +n+ (_bytes_) may not have +n+ _characters_
13877 * preceding the current position -- there may be fewer.
13879 * A new stream is initially positioned:
13881 * - At the beginning (position +0+)
13882 * if its mode is <tt>'r'</tt>, <tt>'w'</tt>, or <tt>'r+'</tt>.
13883 * - At the end (position <tt>self.size</tt>)
13884 * if its mode is <tt>'a'</tt>, <tt>'w+'</tt>, or <tt>'a+'</tt>.
13886 * Methods to query the position:
13888 * - IO#tell and its alias IO#pos return the position for an open stream.
13889 * - IO#eof? and its alias IO#eof return whether the position is at the end
13890 * of a readable stream.
13892 * Reading from a stream usually changes its position:
13894 * f = File.open('t.txt')
13896 * f.readline # => "This is line one.\n"
13898 * f.readline # => "This is the second line.\n"
13900 * f.eof? # => false
13901 * f.readline # => "Here's the third line.\n"
13905 * Writing to a stream usually changes its position:
13907 * f = File.open('t.tmp', 'w')
13909 * f.write('foo') # => 3
13911 * f.write('bar') # => 3
13915 * Iterating over a stream usually changes its position:
13917 * f = File.open('t.txt')
13919 * p "position=#{f.pos} eof?=#{f.eof?} line=#{line}"
13924 * "position=19 eof?=false line=This is line one.\n"
13925 * "position=45 eof?=false line=This is the second line.\n"
13926 * "position=70 eof?=true line=This is the third line.\n"
13928 * The position may also be changed by certain other methods:
13930 * - IO#pos= and IO#seek change the position to a specified offset.
13931 * - IO#rewind changes the position to the beginning.
13935 * Some reader methods in \IO are line-oriented;
13936 * such a method reads one or more lines,
13937 * which are separated by an implicit or explicit line separator.
13939 * These methods include:
13947 * Each of these methods may be called with:
13949 * - An optional line separator, +sep+.
13950 * - An optional line-size limit, +limit+.
13951 * - Both +sep+ and +limit+.
13953 * === Line Separator
13955 * The default line separator is the given by the global variable <tt>$/</tt>,
13956 * whose value is often <tt>"\n"</tt>.
13957 * The line to be read next is all data from the current position
13958 * to the next line separator:
13960 * f = File.open('t.txt')
13961 * f.gets # => "First line\n"
13962 * f.gets # => "Second line\n"
13964 * f.gets # => "Fourth line\n"
13965 * f.gets # => "Fifth line\n"
13967 * You can specify a different line separator:
13969 * f = File.new('t.txt')
13970 * f.gets('l') # => "First l"
13971 * f.gets('li') # => "ine\nSecond li"
13972 * f.gets('lin') # => "ne\n\nFourth lin"
13973 * f.gets # => "e\n"
13975 * There are two special line separators:
13977 * - +nil+: The entire stream is read into a single string:
13979 * f = File.new('t.txt')
13980 * f.gets(nil) # => "First line\nSecond line\n\nFourth line\nFifth line\n"
13982 * - <tt>''</tt> (the empty string): The next "paragraph" is read
13983 * (paragraphs being separated by two consecutive line separators):
13985 * f = File.new('t.txt')
13986 * f.gets('') # => "First line\nSecond line\n\n"
13987 * f.gets('') # => "Fourth line\nFifth line\n"
13991 * The line to be read may be further defined by an optional argument +limit+,
13992 * which specifies that the line may not be (much) longer than the given limit;
13993 * a multi-byte character will not be split, and so a line may be slightly longer
13994 * than the given limit.
13996 * If +limit+ is not given, the line is determined only by +sep+.
13998 * # Text with 1-byte characters.
13999 * File.open('t.txt') {|f| f.gets(1) } # => "F"
14000 * File.open('t.txt') {|f| f.gets(2) } # => "Fi"
14001 * File.open('t.txt') {|f| f.gets(3) } # => "Fir"
14002 * File.open('t.txt') {|f| f.gets(4) } # => "Firs"
14003 * # No more than one line.
14004 * File.open('t.txt') {|f| f.gets(10) } # => "First line"
14005 * File.open('t.txt') {|f| f.gets(11) } # => "First line\n"
14006 * File.open('t.txt') {|f| f.gets(12) } # => "First line\n"
14008 * # Text with 2-byte characters, which will not be split.
14009 * File.open('t.rus') {|f| f.gets(1).size } # => 1
14010 * File.open('t.rus') {|f| f.gets(2).size } # => 1
14011 * File.open('t.rus') {|f| f.gets(3).size } # => 2
14012 * File.open('t.rus') {|f| f.gets(4).size } # => 2
14014 * With arguments +sep+ and +limit+,
14015 * combines the two behaviors:
14017 * - Returns the next line as determined by line separator +sep+,
14018 * or +nil+ if none.
14019 * - But returns no more bytes than are allowed by the limit.
14023 * A readable \IO stream has a _line_ _number_,
14024 * which is the non-negative integer line number
14025 * in the stream where the next read will occur.
14027 * A new stream is initially has line number +0+.
14029 * \Method IO#lineno returns the line number.
14031 * Reading lines from a stream usually changes its line number:
14033 * f = File.open('t.txt', 'r')
14035 * f.readline # => "This is line one.\n"
14037 * f.readline # => "This is the second line.\n"
14039 * f.readline # => "Here's the third line.\n"
14043 * Iterating over lines in a stream usually changes its line number:
14045 * f = File.open('t.txt')
14046 * f.each_line do |line|
14047 * p "position=#{f.pos} eof?=#{f.eof?} line=#{line}"
14052 * "position=19 eof?=false line=This is line one.\n"
14053 * "position=45 eof?=false line=This is the second line.\n"
14054 * "position=70 eof?=true line=This is the third line.\n"
14058 * First, what's elsewhere. \Class \IO:
14060 * - Inherits from {class Object}[Object.html#class-Object-label-What-27s+Here].
14061 * - Includes {module Enumerable}[Enumerable.html#module-Enumerable-label-What-27s+Here],
14062 * which provides dozens of additional methods.
14064 * Here, class \IO provides methods that are useful for:
14066 * - {Creating}[#class-IO-label-Creating]
14067 * - {Reading}[#class-IO-label-Reading]
14068 * - {Writing}[#class-IO-label-Writing]
14069 * - {Positioning}[#class-IO-label-Positioning]
14070 * - {Iterating}[#class-IO-label-Iterating]
14071 * - {Settings}[#class-IO-label-Settings]
14072 * - {Querying}[#class-IO-label-Querying]
14073 * - {Buffering}[#class-IO-label-Buffering]
14074 * - {Low-Level Access}[#class-IO-label-Low-Level+Access]
14075 * - {Other}[#class-IO-label-Other]
14079 * - ::new (aliased as ::for_fd):: Creates and returns a new \IO object for the given
14080 * integer file descriptor.
14081 * - ::open:: Creates a new \IO object.
14082 * - ::pipe:: Creates a connected pair of reader and writer \IO objects.
14083 * - ::popen:: Creates an \IO object to interact with a subprocess.
14084 * - ::select:: Selects which given \IO instances are ready for reading,
14085 * writing, or have pending exceptions.
14089 * - ::binread:: Returns a binary string with all or a subset of bytes
14090 * from the given file.
14091 * - ::read:: Returns a string with all or a subset of bytes from the given file.
14092 * - ::readlines:: Returns an array of strings, which are the lines from the given file.
14093 * - #getbyte:: Returns the next 8-bit byte read from +self+ as an integer.
14094 * - #getc:: Returns the next character read from +self+ as a string.
14095 * - #gets:: Returns the line read from +self+.
14096 * - #pread:: Returns all or the next _n_ bytes read from +self+,
14097 * not updating the receiver's offset.
14098 * - #read:: Returns all remaining or the next _n_ bytes read from +self+
14100 * - #read_nonblock:: the next _n_ bytes read from +self+ for a given _n_,
14101 * in non-block mode.
14102 * - #readbyte:: Returns the next byte read from +self+;
14103 * same as #getbyte, but raises an exception on end-of-file.
14104 * - #readchar:: Returns the next character read from +self+;
14105 * same as #getc, but raises an exception on end-of-file.
14106 * - #readline:: Returns the next line read from +self+;
14107 * same as #getline, but raises an exception of end-of-file.
14108 * - #readlines:: Returns an array of all lines read read from +self+.
14109 * - #readpartial:: Returns up to the given number of bytes from +self+.
14113 * - ::binwrite:: Writes the given string to the file at the given filepath,
14115 * - ::write:: Writes the given string to +self+.
14116 * - {::<<}[#method-i-3C-3C]:: Appends the given string to +self+.
14117 * - #print:: Prints last read line or given objects to +self+.
14118 * - #printf:: Writes to +self+ based on the given format string and objects.
14119 * - #putc:: Writes a character to +self+.
14120 * - #puts:: Writes lines to +self+, making sure line ends with a newline.
14121 * - #pwrite:: Writes the given string at the given offset,
14122 * not updating the receiver's offset.
14123 * - #write:: Writes one or more given strings to +self+.
14124 * - #write_nonblock:: Writes one or more given strings to +self+ in non-blocking mode.
14128 * - #lineno:: Returns the current line number in +self+.
14129 * - #lineno=:: Sets the line number is +self+.
14130 * - #pos (aliased as #tell):: Returns the current byte offset in +self+.
14131 * - #pos=:: Sets the byte offset in +self+.
14132 * - #reopen:: Reassociates +self+ with a new or existing \IO stream.
14133 * - #rewind:: Positions +self+ to the beginning of input.
14134 * - #seek:: Sets the offset for +self+ relative to given position.
14138 * - ::foreach:: Yields each line of given file to the block.
14139 * - #each (aliased as #each_line):: Calls the given block
14140 * with each successive line in +self+.
14141 * - #each_byte:: Calls the given block with each successive byte in +self+
14143 * - #each_char:: Calls the given block with each successive character in +self+
14145 * - #each_codepoint:: Calls the given block with each successive codepoint in +self+
14150 * - #autoclose=:: Sets whether +self+ auto-closes.
14151 * - #binmode:: Sets +self+ to binary mode.
14152 * - #close:: Closes +self+.
14153 * - #close_on_exec=:: Sets the close-on-exec flag.
14154 * - #close_read:: Closes +self+ for reading.
14155 * - #close_write:: Closes +self+ for writing.
14156 * - #set_encoding:: Sets the encoding for +self+.
14157 * - #set_encoding_by_bom:: Sets the encoding for +self+, based on its
14158 * Unicode byte-order-mark.
14159 * - #sync=:: Sets the sync-mode to the given value.
14163 * - #autoclose?:: Returns whether +self+ auto-closes.
14164 * - #binmode?:: Returns whether +self+ is in binary mode.
14165 * - #close_on_exec?:: Returns the close-on-exec flag for +self+.
14166 * - #closed?:: Returns whether +self+ is closed.
14167 * - #eof? (aliased as #eof):: Returns whether +self+ is at end-of-file.
14168 * - #external_encoding:: Returns the external encoding object for +self+.
14169 * - #fileno (aliased as #to_i):: Returns the integer file descriptor for +self+
14170 * - #internal_encoding:: Returns the internal encoding object for +self+.
14171 * - #pid:: Returns the process ID of a child process associated with +self+,
14172 * if +self+ was created by ::popen.
14173 * - #stat:: Returns the File::Stat object containing status information for +self+.
14174 * - #sync:: Returns whether +self+ is in sync-mode.
14175 * - #tty (aliased as #isatty):: Returns whether +self+ is a terminal.
14179 * - #fdatasync:: Immediately writes all buffered data in +self+ to disk.
14180 * - #flush:: Flushes any buffered data within +self+ to the underlying
14181 * operating system.
14182 * - #fsync:: Immediately writes all buffered data and attributes in +self+ to disk.
14183 * - #ungetbyte:: Prepends buffer for +self+ with given integer byte or string.
14184 * - #ungetc:: Prepends buffer for +self+ with given string.
14186 * === Low-Level Access
14188 * - ::sysopen:: Opens the file given by its path,
14189 * returning the integer file descriptor.
14190 * - #advise:: Announces the intention to access data from +self+ in a specific way.
14191 * - #fcntl:: Passes a low-level command to the file specified
14192 * by the given file descriptor.
14193 * - #ioctl:: Passes a low-level command to the device specified
14194 * by the given file descriptor.
14195 * - #sysread:: Returns up to the next _n_ bytes read from self using a low-level read.
14196 * - #sysseek:: Sets the offset for +self+.
14197 * - #syswrite:: Writes the given string to +self+ using a low-level write.
14201 * - ::copy_stream:: Copies data from a source to a destination,
14202 * each of which is a filepath or an \IO-like object.
14203 * - ::try_convert:: Returns a new \IO object resulting from converting
14204 * the given object.
14205 * - #inspect:: Returns the string representation of +self+.
14214 #include <sys/cygwin.h>
14215 static struct __cygwin_perfile pf
[] =
14217 {"", O_RDONLY
| O_BINARY
},
14218 {"", O_WRONLY
| O_BINARY
},
14219 {"", O_RDWR
| O_BINARY
},
14220 {"", O_APPEND
| O_BINARY
},
14223 cygwin_internal(CW_PERFILE
, pf
);
14226 rb_eIOError
= rb_define_class("IOError", rb_eStandardError
);
14227 rb_eEOFError
= rb_define_class("EOFError", rb_eIOError
);
14229 id_write
= rb_intern_const("write");
14230 id_read
= rb_intern_const("read");
14231 id_getc
= rb_intern_const("getc");
14232 id_flush
= rb_intern_const("flush");
14233 id_readpartial
= rb_intern_const("readpartial");
14234 id_set_encoding
= rb_intern_const("set_encoding");
14235 id_fileno
= rb_intern_const("fileno");
14237 rb_define_global_function("syscall", rb_f_syscall
, -1);
14239 rb_define_global_function("open", rb_f_open
, -1);
14240 rb_define_global_function("printf", rb_f_printf
, -1);
14241 rb_define_global_function("print", rb_f_print
, -1);
14242 rb_define_global_function("putc", rb_f_putc
, 1);
14243 rb_define_global_function("puts", rb_f_puts
, -1);
14244 rb_define_global_function("gets", rb_f_gets
, -1);
14245 rb_define_global_function("readline", rb_f_readline
, -1);
14246 rb_define_global_function("select", rb_f_select
, -1);
14248 rb_define_global_function("readlines", rb_f_readlines
, -1);
14250 rb_define_global_function("`", rb_f_backquote
, 1);
14252 rb_define_global_function("p", rb_f_p
, -1);
14253 rb_define_method(rb_mKernel
, "display", rb_obj_display
, -1);
14255 rb_cIO
= rb_define_class("IO", rb_cObject
);
14256 rb_include_module(rb_cIO
, rb_mEnumerable
);
14258 rb_define_const(rb_cIO
, "READABLE", INT2NUM(RUBY_IO_READABLE
));
14259 rb_define_const(rb_cIO
, "WRITABLE", INT2NUM(RUBY_IO_WRITABLE
));
14260 rb_define_const(rb_cIO
, "PRIORITY", INT2NUM(RUBY_IO_PRIORITY
));
14262 /* exception to wait for reading. see IO.select. */
14263 rb_mWaitReadable
= rb_define_module_under(rb_cIO
, "WaitReadable");
14264 /* exception to wait for writing. see IO.select. */
14265 rb_mWaitWritable
= rb_define_module_under(rb_cIO
, "WaitWritable");
14266 /* exception to wait for reading by EAGAIN. see IO.select. */
14267 rb_eEAGAINWaitReadable
= rb_define_class_under(rb_cIO
, "EAGAINWaitReadable", rb_eEAGAIN
);
14268 rb_include_module(rb_eEAGAINWaitReadable
, rb_mWaitReadable
);
14269 /* exception to wait for writing by EAGAIN. see IO.select. */
14270 rb_eEAGAINWaitWritable
= rb_define_class_under(rb_cIO
, "EAGAINWaitWritable", rb_eEAGAIN
);
14271 rb_include_module(rb_eEAGAINWaitWritable
, rb_mWaitWritable
);
14272 #if EAGAIN == EWOULDBLOCK
14273 rb_eEWOULDBLOCKWaitReadable
= rb_eEAGAINWaitReadable
;
14274 /* same as IO::EAGAINWaitReadable */
14275 rb_define_const(rb_cIO
, "EWOULDBLOCKWaitReadable", rb_eEAGAINWaitReadable
);
14276 rb_eEWOULDBLOCKWaitWritable
= rb_eEAGAINWaitWritable
;
14277 /* same as IO::EAGAINWaitWritable */
14278 rb_define_const(rb_cIO
, "EWOULDBLOCKWaitWritable", rb_eEAGAINWaitWritable
);
14280 /* exception to wait for reading by EWOULDBLOCK. see IO.select. */
14281 rb_eEWOULDBLOCKWaitReadable
= rb_define_class_under(rb_cIO
, "EWOULDBLOCKWaitReadable", rb_eEWOULDBLOCK
);
14282 rb_include_module(rb_eEWOULDBLOCKWaitReadable
, rb_mWaitReadable
);
14283 /* exception to wait for writing by EWOULDBLOCK. see IO.select. */
14284 rb_eEWOULDBLOCKWaitWritable
= rb_define_class_under(rb_cIO
, "EWOULDBLOCKWaitWritable", rb_eEWOULDBLOCK
);
14285 rb_include_module(rb_eEWOULDBLOCKWaitWritable
, rb_mWaitWritable
);
14287 /* exception to wait for reading by EINPROGRESS. see IO.select. */
14288 rb_eEINPROGRESSWaitReadable
= rb_define_class_under(rb_cIO
, "EINPROGRESSWaitReadable", rb_eEINPROGRESS
);
14289 rb_include_module(rb_eEINPROGRESSWaitReadable
, rb_mWaitReadable
);
14290 /* exception to wait for writing by EINPROGRESS. see IO.select. */
14291 rb_eEINPROGRESSWaitWritable
= rb_define_class_under(rb_cIO
, "EINPROGRESSWaitWritable", rb_eEINPROGRESS
);
14292 rb_include_module(rb_eEINPROGRESSWaitWritable
, rb_mWaitWritable
);
14295 /* This is necessary only for forcing rdoc handle File::open */
14296 rb_define_singleton_method(rb_cFile
, "open", rb_io_s_open
, -1);
14299 rb_define_alloc_func(rb_cIO
, io_alloc
);
14300 rb_define_singleton_method(rb_cIO
, "new", rb_io_s_new
, -1);
14301 rb_define_singleton_method(rb_cIO
, "open", rb_io_s_open
, -1);
14302 rb_define_singleton_method(rb_cIO
, "sysopen", rb_io_s_sysopen
, -1);
14303 rb_define_singleton_method(rb_cIO
, "for_fd", rb_io_s_for_fd
, -1);
14304 rb_define_singleton_method(rb_cIO
, "popen", rb_io_s_popen
, -1);
14305 rb_define_singleton_method(rb_cIO
, "foreach", rb_io_s_foreach
, -1);
14306 rb_define_singleton_method(rb_cIO
, "readlines", rb_io_s_readlines
, -1);
14307 rb_define_singleton_method(rb_cIO
, "read", rb_io_s_read
, -1);
14308 rb_define_singleton_method(rb_cIO
, "binread", rb_io_s_binread
, -1);
14309 rb_define_singleton_method(rb_cIO
, "write", rb_io_s_write
, -1);
14310 rb_define_singleton_method(rb_cIO
, "binwrite", rb_io_s_binwrite
, -1);
14311 rb_define_singleton_method(rb_cIO
, "select", rb_f_select
, -1);
14312 rb_define_singleton_method(rb_cIO
, "pipe", rb_io_s_pipe
, -1);
14313 rb_define_singleton_method(rb_cIO
, "try_convert", rb_io_s_try_convert
, 1);
14314 rb_define_singleton_method(rb_cIO
, "copy_stream", rb_io_s_copy_stream
, -1);
14316 rb_define_method(rb_cIO
, "initialize", rb_io_initialize
, -1);
14318 rb_output_fs
= Qnil
;
14319 rb_define_hooked_variable("$,", &rb_output_fs
, 0, deprecated_str_setter
);
14321 rb_default_rs
= rb_fstring_lit("\n"); /* avoid modifying RS_default */
14322 rb_gc_register_mark_object(rb_default_rs
);
14323 rb_rs
= rb_default_rs
;
14324 rb_output_rs
= Qnil
;
14325 rb_define_hooked_variable("$/", &rb_rs
, 0, deprecated_str_setter
);
14326 rb_define_hooked_variable("$-0", &rb_rs
, 0, deprecated_str_setter
);
14327 rb_define_hooked_variable("$\\", &rb_output_rs
, 0, deprecated_str_setter
);
14329 rb_define_virtual_variable("$_", get_LAST_READ_LINE
, set_LAST_READ_LINE
);
14330 rb_gvar_ractor_local("$_");
14332 rb_define_method(rb_cIO
, "initialize_copy", rb_io_init_copy
, 1);
14333 rb_define_method(rb_cIO
, "reopen", rb_io_reopen
, -1);
14335 rb_define_method(rb_cIO
, "print", rb_io_print
, -1);
14336 rb_define_method(rb_cIO
, "putc", rb_io_putc
, 1);
14337 rb_define_method(rb_cIO
, "puts", rb_io_puts
, -1);
14338 rb_define_method(rb_cIO
, "printf", rb_io_printf
, -1);
14340 rb_define_method(rb_cIO
, "each", rb_io_each_line
, -1);
14341 rb_define_method(rb_cIO
, "each_line", rb_io_each_line
, -1);
14342 rb_define_method(rb_cIO
, "each_byte", rb_io_each_byte
, 0);
14343 rb_define_method(rb_cIO
, "each_char", rb_io_each_char
, 0);
14344 rb_define_method(rb_cIO
, "each_codepoint", rb_io_each_codepoint
, 0);
14346 rb_define_method(rb_cIO
, "syswrite", rb_io_syswrite
, 1);
14347 rb_define_method(rb_cIO
, "sysread", rb_io_sysread
, -1);
14349 rb_define_method(rb_cIO
, "pread", rb_io_pread
, -1);
14350 rb_define_method(rb_cIO
, "pwrite", rb_io_pwrite
, 2);
14352 rb_define_method(rb_cIO
, "fileno", rb_io_fileno
, 0);
14353 rb_define_alias(rb_cIO
, "to_i", "fileno");
14354 rb_define_method(rb_cIO
, "to_io", rb_io_to_io
, 0);
14356 rb_define_method(rb_cIO
, "fsync", rb_io_fsync
, 0);
14357 rb_define_method(rb_cIO
, "fdatasync", rb_io_fdatasync
, 0);
14358 rb_define_method(rb_cIO
, "sync", rb_io_sync
, 0);
14359 rb_define_method(rb_cIO
, "sync=", rb_io_set_sync
, 1);
14361 rb_define_method(rb_cIO
, "lineno", rb_io_lineno
, 0);
14362 rb_define_method(rb_cIO
, "lineno=", rb_io_set_lineno
, 1);
14364 rb_define_method(rb_cIO
, "readlines", rb_io_readlines
, -1);
14366 rb_define_method(rb_cIO
, "readpartial", io_readpartial
, -1);
14367 rb_define_method(rb_cIO
, "read", io_read
, -1);
14368 rb_define_method(rb_cIO
, "write", io_write_m
, -1);
14369 rb_define_method(rb_cIO
, "gets", rb_io_gets_m
, -1);
14370 rb_define_method(rb_cIO
, "readline", rb_io_readline
, -1);
14371 rb_define_method(rb_cIO
, "getc", rb_io_getc
, 0);
14372 rb_define_method(rb_cIO
, "getbyte", rb_io_getbyte
, 0);
14373 rb_define_method(rb_cIO
, "readchar", rb_io_readchar
, 0);
14374 rb_define_method(rb_cIO
, "readbyte", rb_io_readbyte
, 0);
14375 rb_define_method(rb_cIO
, "ungetbyte",rb_io_ungetbyte
, 1);
14376 rb_define_method(rb_cIO
, "ungetc",rb_io_ungetc
, 1);
14377 rb_define_method(rb_cIO
, "<<", rb_io_addstr
, 1);
14378 rb_define_method(rb_cIO
, "flush", rb_io_flush
, 0);
14379 rb_define_method(rb_cIO
, "tell", rb_io_tell
, 0);
14380 rb_define_method(rb_cIO
, "seek", rb_io_seek_m
, -1);
14381 /* Set I/O position from the beginning */
14382 rb_define_const(rb_cIO
, "SEEK_SET", INT2FIX(SEEK_SET
));
14383 /* Set I/O position from the current position */
14384 rb_define_const(rb_cIO
, "SEEK_CUR", INT2FIX(SEEK_CUR
));
14385 /* Set I/O position from the end */
14386 rb_define_const(rb_cIO
, "SEEK_END", INT2FIX(SEEK_END
));
14388 /* Set I/O position to the next location containing data */
14389 rb_define_const(rb_cIO
, "SEEK_DATA", INT2FIX(SEEK_DATA
));
14392 /* Set I/O position to the next hole */
14393 rb_define_const(rb_cIO
, "SEEK_HOLE", INT2FIX(SEEK_HOLE
));
14395 rb_define_method(rb_cIO
, "rewind", rb_io_rewind
, 0);
14396 rb_define_method(rb_cIO
, "pos", rb_io_tell
, 0);
14397 rb_define_method(rb_cIO
, "pos=", rb_io_set_pos
, 1);
14398 rb_define_method(rb_cIO
, "eof", rb_io_eof
, 0);
14399 rb_define_method(rb_cIO
, "eof?", rb_io_eof
, 0);
14401 rb_define_method(rb_cIO
, "close_on_exec?", rb_io_close_on_exec_p
, 0);
14402 rb_define_method(rb_cIO
, "close_on_exec=", rb_io_set_close_on_exec
, 1);
14404 rb_define_method(rb_cIO
, "close", rb_io_close_m
, 0);
14405 rb_define_method(rb_cIO
, "closed?", rb_io_closed
, 0);
14406 rb_define_method(rb_cIO
, "close_read", rb_io_close_read
, 0);
14407 rb_define_method(rb_cIO
, "close_write", rb_io_close_write
, 0);
14409 rb_define_method(rb_cIO
, "isatty", rb_io_isatty
, 0);
14410 rb_define_method(rb_cIO
, "tty?", rb_io_isatty
, 0);
14411 rb_define_method(rb_cIO
, "binmode", rb_io_binmode_m
, 0);
14412 rb_define_method(rb_cIO
, "binmode?", rb_io_binmode_p
, 0);
14413 rb_define_method(rb_cIO
, "sysseek", rb_io_sysseek
, -1);
14414 rb_define_method(rb_cIO
, "advise", rb_io_advise
, -1);
14416 rb_define_method(rb_cIO
, "ioctl", rb_io_ioctl
, -1);
14417 rb_define_method(rb_cIO
, "fcntl", rb_io_fcntl
, -1);
14418 rb_define_method(rb_cIO
, "pid", rb_io_pid
, 0);
14419 rb_define_method(rb_cIO
, "inspect", rb_io_inspect
, 0);
14421 rb_define_method(rb_cIO
, "external_encoding", rb_io_external_encoding
, 0);
14422 rb_define_method(rb_cIO
, "internal_encoding", rb_io_internal_encoding
, 0);
14423 rb_define_method(rb_cIO
, "set_encoding", rb_io_set_encoding
, -1);
14424 rb_define_method(rb_cIO
, "set_encoding_by_bom", rb_io_set_encoding_by_bom
, 0);
14426 rb_define_method(rb_cIO
, "autoclose?", rb_io_autoclose_p
, 0);
14427 rb_define_method(rb_cIO
, "autoclose=", rb_io_set_autoclose
, 1);
14429 rb_define_virtual_variable("$stdin", stdin_getter
, stdin_setter
);
14430 rb_define_virtual_variable("$stdout", stdout_getter
, stdout_setter
);
14431 rb_define_virtual_variable("$>", stdout_getter
, stdout_setter
);
14432 rb_define_virtual_variable("$stderr", stderr_getter
, stderr_setter
);
14434 rb_gvar_ractor_local("$stdin");
14435 rb_gvar_ractor_local("$stdout");
14436 rb_gvar_ractor_local("$>");
14437 rb_gvar_ractor_local("$stderr");
14439 rb_stdin
= rb_io_prep_stdin();
14440 rb_stdout
= rb_io_prep_stdout();
14441 rb_stderr
= rb_io_prep_stderr();
14443 rb_global_variable(&rb_stdin
);
14444 rb_global_variable(&rb_stdout
);
14445 rb_global_variable(&rb_stderr
);
14447 orig_stdout
= rb_stdout
;
14448 orig_stderr
= rb_stderr
;
14450 /* Holds the original stdin */
14451 rb_define_global_const("STDIN", rb_stdin
);
14452 /* Holds the original stdout */
14453 rb_define_global_const("STDOUT", rb_stdout
);
14454 /* Holds the original stderr */
14455 rb_define_global_const("STDERR", rb_stderr
);
14458 /* Hack to get rdoc to regard ARGF as a class: */
14459 rb_cARGF
= rb_define_class("ARGF", rb_cObject
);
14462 rb_cARGF
= rb_class_new(rb_cObject
);
14463 rb_set_class_path(rb_cARGF
, rb_cObject
, "ARGF.class");
14464 rb_define_alloc_func(rb_cARGF
, argf_alloc
);
14466 rb_include_module(rb_cARGF
, rb_mEnumerable
);
14468 rb_define_method(rb_cARGF
, "initialize", argf_initialize
, -2);
14469 rb_define_method(rb_cARGF
, "initialize_copy", argf_initialize_copy
, 1);
14470 rb_define_method(rb_cARGF
, "to_s", argf_to_s
, 0);
14471 rb_define_alias(rb_cARGF
, "inspect", "to_s");
14472 rb_define_method(rb_cARGF
, "argv", argf_argv
, 0);
14474 rb_define_method(rb_cARGF
, "fileno", argf_fileno
, 0);
14475 rb_define_method(rb_cARGF
, "to_i", argf_fileno
, 0);
14476 rb_define_method(rb_cARGF
, "to_io", argf_to_io
, 0);
14477 rb_define_method(rb_cARGF
, "to_write_io", argf_write_io
, 0);
14478 rb_define_method(rb_cARGF
, "each", argf_each_line
, -1);
14479 rb_define_method(rb_cARGF
, "each_line", argf_each_line
, -1);
14480 rb_define_method(rb_cARGF
, "each_byte", argf_each_byte
, 0);
14481 rb_define_method(rb_cARGF
, "each_char", argf_each_char
, 0);
14482 rb_define_method(rb_cARGF
, "each_codepoint", argf_each_codepoint
, 0);
14484 rb_define_method(rb_cARGF
, "read", argf_read
, -1);
14485 rb_define_method(rb_cARGF
, "readpartial", argf_readpartial
, -1);
14486 rb_define_method(rb_cARGF
, "read_nonblock", argf_read_nonblock
, -1);
14487 rb_define_method(rb_cARGF
, "readlines", argf_readlines
, -1);
14488 rb_define_method(rb_cARGF
, "to_a", argf_readlines
, -1);
14489 rb_define_method(rb_cARGF
, "gets", argf_gets
, -1);
14490 rb_define_method(rb_cARGF
, "readline", argf_readline
, -1);
14491 rb_define_method(rb_cARGF
, "getc", argf_getc
, 0);
14492 rb_define_method(rb_cARGF
, "getbyte", argf_getbyte
, 0);
14493 rb_define_method(rb_cARGF
, "readchar", argf_readchar
, 0);
14494 rb_define_method(rb_cARGF
, "readbyte", argf_readbyte
, 0);
14495 rb_define_method(rb_cARGF
, "tell", argf_tell
, 0);
14496 rb_define_method(rb_cARGF
, "seek", argf_seek_m
, -1);
14497 rb_define_method(rb_cARGF
, "rewind", argf_rewind
, 0);
14498 rb_define_method(rb_cARGF
, "pos", argf_tell
, 0);
14499 rb_define_method(rb_cARGF
, "pos=", argf_set_pos
, 1);
14500 rb_define_method(rb_cARGF
, "eof", argf_eof
, 0);
14501 rb_define_method(rb_cARGF
, "eof?", argf_eof
, 0);
14502 rb_define_method(rb_cARGF
, "binmode", argf_binmode_m
, 0);
14503 rb_define_method(rb_cARGF
, "binmode?", argf_binmode_p
, 0);
14505 rb_define_method(rb_cARGF
, "write", argf_write
, 1);
14506 rb_define_method(rb_cARGF
, "print", rb_io_print
, -1);
14507 rb_define_method(rb_cARGF
, "putc", rb_io_putc
, 1);
14508 rb_define_method(rb_cARGF
, "puts", rb_io_puts
, -1);
14509 rb_define_method(rb_cARGF
, "printf", rb_io_printf
, -1);
14511 rb_define_method(rb_cARGF
, "filename", argf_filename
, 0);
14512 rb_define_method(rb_cARGF
, "path", argf_filename
, 0);
14513 rb_define_method(rb_cARGF
, "file", argf_file
, 0);
14514 rb_define_method(rb_cARGF
, "skip", argf_skip
, 0);
14515 rb_define_method(rb_cARGF
, "close", argf_close_m
, 0);
14516 rb_define_method(rb_cARGF
, "closed?", argf_closed
, 0);
14518 rb_define_method(rb_cARGF
, "lineno", argf_lineno
, 0);
14519 rb_define_method(rb_cARGF
, "lineno=", argf_set_lineno
, 1);
14521 rb_define_method(rb_cARGF
, "inplace_mode", argf_inplace_mode_get
, 0);
14522 rb_define_method(rb_cARGF
, "inplace_mode=", argf_inplace_mode_set
, 1);
14524 rb_define_method(rb_cARGF
, "external_encoding", argf_external_encoding
, 0);
14525 rb_define_method(rb_cARGF
, "internal_encoding", argf_internal_encoding
, 0);
14526 rb_define_method(rb_cARGF
, "set_encoding", argf_set_encoding
, -1);
14528 argf
= rb_class_new_instance(0, 0, rb_cARGF
);
14530 rb_define_readonly_variable("$<", &argf
);
14532 * ARGF is a stream designed for use in scripts that process files given
14533 * as command-line arguments or passed in via STDIN.
14535 * See ARGF (the class) for more details.
14537 rb_define_global_const("ARGF", argf
);
14539 rb_define_hooked_variable("$.", &argf
, argf_lineno_getter
, argf_lineno_setter
);
14540 rb_define_hooked_variable("$FILENAME", &argf
, argf_filename_getter
, rb_gvar_readonly_setter
);
14541 ARGF
.filename
= rb_str_new2("-");
14543 rb_define_hooked_variable("$-i", &argf
, opt_i_get
, opt_i_set
);
14544 rb_gvar_ractor_local("$-i");
14546 rb_define_hooked_variable("$*", &argf
, argf_argv_getter
, rb_gvar_readonly_setter
);
14548 #if defined (_WIN32) || defined(__CYGWIN__)
14549 atexit(pipe_atexit
);
14554 rb_define_method(rb_cFile
, "initialize", rb_file_initialize
, -1);
14556 sym_mode
= ID2SYM(rb_intern_const("mode"));
14557 sym_perm
= ID2SYM(rb_intern_const("perm"));
14558 sym_flags
= ID2SYM(rb_intern_const("flags"));
14559 sym_extenc
= ID2SYM(rb_intern_const("external_encoding"));
14560 sym_intenc
= ID2SYM(rb_intern_const("internal_encoding"));
14561 sym_encoding
= ID2SYM(rb_id_encoding());
14562 sym_open_args
= ID2SYM(rb_intern_const("open_args"));
14563 sym_textmode
= ID2SYM(rb_intern_const("textmode"));
14564 sym_binmode
= ID2SYM(rb_intern_const("binmode"));
14565 sym_autoclose
= ID2SYM(rb_intern_const("autoclose"));
14566 sym_normal
= ID2SYM(rb_intern_const("normal"));
14567 sym_sequential
= ID2SYM(rb_intern_const("sequential"));
14568 sym_random
= ID2SYM(rb_intern_const("random"));
14569 sym_willneed
= ID2SYM(rb_intern_const("willneed"));
14570 sym_dontneed
= ID2SYM(rb_intern_const("dontneed"));
14571 sym_noreuse
= ID2SYM(rb_intern_const("noreuse"));
14572 sym_SET
= ID2SYM(rb_intern_const("SET"));
14573 sym_CUR
= ID2SYM(rb_intern_const("CUR"));
14574 sym_END
= ID2SYM(rb_intern_const("END"));
14576 sym_DATA
= ID2SYM(rb_intern_const("DATA"));
14579 sym_HOLE
= ID2SYM(rb_intern_const("HOLE"));
14581 sym_wait_readable
= ID2SYM(rb_intern_const("wait_readable"));
14582 sym_wait_writable
= ID2SYM(rb_intern_const("wait_writable"));
14585 #include "io.rbinc"