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
, count
);
1138 if (result
!= Qundef
) {
1139 ssize_t length
= rb_fiber_scheduler_io_result_apply(result
);
1141 if (length
< 0) rb_sys_fail_path(fptr
->pathv
);
1147 struct io_internal_read_struct iis
= {
1148 .th
= rb_thread_current(),
1155 return (ssize_t
)rb_thread_io_blocking_region(internal_read_func
, &iis
, fptr
->fd
);
1159 rb_write_internal(rb_io_t
*fptr
, const void *buf
, size_t count
)
1161 VALUE scheduler
= rb_fiber_scheduler_current();
1162 if (scheduler
!= Qnil
) {
1163 VALUE result
= rb_fiber_scheduler_io_write_memory(scheduler
, fptr
->self
, buf
, count
, 0);
1165 if (result
!= Qundef
) {
1166 return rb_fiber_scheduler_io_result_apply(result
);
1170 struct io_internal_write_struct iis
= {
1176 if (fptr
->write_lock
&& rb_mutex_owned_p(fptr
->write_lock
))
1177 return (ssize_t
)rb_thread_call_without_gvl2(internal_write_func2
, &iis
, RUBY_UBF_IO
, NULL
);
1179 return (ssize_t
)rb_thread_io_blocking_region(internal_write_func
, &iis
, fptr
->fd
);
1184 rb_writev_internal(rb_io_t
*fptr
, const struct iovec
*iov
, int iovcnt
)
1186 VALUE scheduler
= rb_fiber_scheduler_current();
1187 if (scheduler
!= Qnil
) {
1188 for (int i
= 0; i
< iovcnt
; i
+= 1) {
1189 VALUE result
= rb_fiber_scheduler_io_write_memory(scheduler
, fptr
->self
, iov
[i
].iov_base
, iov
[i
].iov_len
, 0);
1191 if (result
!= Qundef
) {
1192 return rb_fiber_scheduler_io_result_apply(result
);
1197 struct io_internal_writev_struct iis
= {
1203 return (ssize_t
)rb_thread_io_blocking_region(internal_writev_func
, &iis
, fptr
->fd
);
1208 io_flush_buffer_sync(void *arg
)
1210 rb_io_t
*fptr
= arg
;
1211 long l
= fptr
->wbuf
.len
;
1212 ssize_t r
= write(fptr
->fd
, fptr
->wbuf
.ptr
+fptr
->wbuf
.off
, (size_t)l
);
1214 if (fptr
->wbuf
.len
<= r
) {
1220 fptr
->wbuf
.off
+= (int)r
;
1221 fptr
->wbuf
.len
-= (int)r
;
1228 io_flush_buffer_sync2(void *arg
)
1230 VALUE result
= io_flush_buffer_sync(arg
);
1233 * rb_thread_call_without_gvl2 uses 0 as interrupted.
1234 * So, we need to avoid to use 0.
1236 return !result
? (void*)1 : (void*)result
;
1240 io_flush_buffer_async(VALUE arg
)
1242 rb_io_t
*fptr
= (rb_io_t
*)arg
;
1243 return rb_thread_io_blocking_region(io_flush_buffer_sync
, fptr
, fptr
->fd
);
1247 io_flush_buffer_async2(VALUE arg
)
1249 rb_io_t
*fptr
= (rb_io_t
*)arg
;
1252 ret
= (VALUE
)rb_thread_call_without_gvl2(io_flush_buffer_sync2
, fptr
, RUBY_UBF_IO
, NULL
);
1255 /* pending async interrupt is there. */
1259 else if (ret
== 1) {
1266 io_flush_buffer(rb_io_t
*fptr
)
1268 if (fptr
->write_lock
) {
1269 if (rb_mutex_owned_p(fptr
->write_lock
))
1270 return (int)io_flush_buffer_async2((VALUE
)fptr
);
1272 return (int)rb_mutex_synchronize(fptr
->write_lock
, io_flush_buffer_async2
, (VALUE
)fptr
);
1275 return (int)io_flush_buffer_async((VALUE
)fptr
);
1280 io_fflush(rb_io_t
*fptr
)
1282 rb_io_check_closed(fptr
);
1284 if (fptr
->wbuf
.len
== 0)
1287 while (fptr
->wbuf
.len
> 0 && io_flush_buffer(fptr
) != 0) {
1288 if (!rb_io_maybe_wait_writable(errno
, fptr
->self
, Qnil
))
1291 rb_io_check_closed(fptr
);
1298 rb_io_wait(VALUE io
, VALUE events
, VALUE timeout
)
1300 VALUE scheduler
= rb_fiber_scheduler_current();
1302 if (scheduler
!= Qnil
) {
1303 return rb_fiber_scheduler_io_wait(scheduler
, io
, events
, timeout
);
1306 rb_io_t
* fptr
= NULL
;
1307 RB_IO_POINTER(io
, fptr
);
1309 struct timeval tv_storage
;
1310 struct timeval
*tv
= NULL
;
1312 if (timeout
!= Qnil
) {
1313 tv_storage
= rb_time_interval(timeout
);
1317 int ready
= rb_thread_wait_for_single_fd(fptr
->fd
, RB_NUM2INT(events
), tv
);
1323 // Not sure if this is necessary:
1324 rb_io_check_closed(fptr
);
1327 return RB_INT2NUM(ready
);
1337 return prep_io(fd
, FMODE_PREP
, rb_cIO
, NULL
);
1341 io_wait_for_single_fd(int fd
, int events
, struct timeval
*timeout
)
1343 VALUE scheduler
= rb_fiber_scheduler_current();
1345 if (scheduler
!= Qnil
) {
1347 rb_fiber_scheduler_io_wait(scheduler
, io_from_fd(fd
), RB_INT2NUM(events
), rb_fiber_scheduler_make_timeout(timeout
))
1351 return rb_thread_wait_for_single_fd(fd
, events
, timeout
);
1355 rb_io_wait_readable(int f
)
1357 io_fd_check_closed(f
);
1359 VALUE scheduler
= rb_fiber_scheduler_current();
1363 #if defined(ERESTART)
1366 rb_thread_check_ints();
1370 #if EWOULDBLOCK != EAGAIN
1373 if (scheduler
!= Qnil
) {
1375 rb_fiber_scheduler_io_wait_readable(scheduler
, io_from_fd(f
))
1379 io_wait_for_single_fd(f
, RUBY_IO_READABLE
, NULL
);
1389 rb_io_wait_writable(int f
)
1391 io_fd_check_closed(f
);
1393 VALUE scheduler
= rb_fiber_scheduler_current();
1397 #if defined(ERESTART)
1401 * In old Linux, several special files under /proc and /sys don't handle
1402 * select properly. Thus we need avoid to call if don't use O_NONBLOCK.
1403 * Otherwise, we face nasty hang up. Sigh.
1404 * e.g. http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=31b07093c44a7a442394d44423e21d783f5523b8
1405 * http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=31b07093c44a7a442394d44423e21d783f5523b8
1406 * In EINTR case, we only need to call RUBY_VM_CHECK_INTS_BLOCKING().
1407 * Then rb_thread_check_ints() is enough.
1409 rb_thread_check_ints();
1413 #if EWOULDBLOCK != EAGAIN
1416 if (scheduler
!= Qnil
) {
1418 rb_fiber_scheduler_io_wait_writable(scheduler
, io_from_fd(f
))
1422 io_wait_for_single_fd(f
, RUBY_IO_WRITABLE
, NULL
);
1432 rb_wait_for_single_fd(int fd
, int events
, struct timeval
*timeout
)
1434 return io_wait_for_single_fd(fd
, events
, timeout
);
1438 rb_thread_wait_fd(int fd
)
1440 return rb_wait_for_single_fd(fd
, RUBY_IO_READABLE
, NULL
);
1444 rb_thread_fd_writable(int fd
)
1446 return rb_wait_for_single_fd(fd
, RUBY_IO_WRITABLE
, NULL
);
1450 rb_io_maybe_wait(int error
, VALUE io
, VALUE events
, VALUE timeout
)
1452 // fptr->fd can be set to -1 at any time by another thread when the GVL is
1453 // released. Many code, e.g. `io_bufread` didn't check this correctly and
1454 // instead relies on `read(-1) -> -1` which causes this code path. We then
1455 // check here whether the IO was in fact closed. Probably it's better to
1456 // check that `fptr->fd != -1` before using it in syscall.
1457 rb_io_check_closed(RFILE(io
)->fptr
);
1460 // In old Linux, several special files under /proc and /sys don't handle
1461 // select properly. Thus we need avoid to call if don't use O_NONBLOCK.
1462 // Otherwise, we face nasty hang up. Sigh.
1463 // e.g. http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=31b07093c44a7a442394d44423e21d783f5523b8
1464 // http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=31b07093c44a7a442394d44423e21d783f5523b8
1465 // In EINTR case, we only need to call RUBY_VM_CHECK_INTS_BLOCKING().
1466 // Then rb_thread_check_ints() is enough.
1468 #if defined(ERESTART)
1471 // We might have pending interrupts since the previous syscall was interrupted:
1472 rb_thread_check_ints();
1474 // The operation was interrupted, so retry it immediately:
1478 #if EWOULDBLOCK != EAGAIN
1481 // The operation would block, so wait for the specified events:
1482 return rb_io_wait(io
, events
, timeout
);
1485 // Non-specific error, no event is ready:
1491 rb_io_maybe_wait_readable(int error
, VALUE io
, VALUE timeout
)
1493 VALUE result
= rb_io_maybe_wait(error
, io
, RB_INT2NUM(RUBY_IO_READABLE
), timeout
);
1495 if (RTEST(result
)) {
1496 return RB_NUM2INT(result
);
1504 rb_io_maybe_wait_writable(int error
, VALUE io
, VALUE timeout
)
1506 VALUE result
= rb_io_maybe_wait(error
, io
, RB_INT2NUM(RUBY_IO_WRITABLE
), timeout
);
1508 if (RTEST(result
)) {
1509 return RB_NUM2INT(result
);
1517 make_writeconv(rb_io_t
*fptr
)
1519 if (!fptr
->writeconv_initialized
) {
1520 const char *senc
, *denc
;
1525 fptr
->writeconv_initialized
= 1;
1527 ecflags
= fptr
->encs
.ecflags
& ~ECONV_NEWLINE_DECORATOR_READ_MASK
;
1528 ecopts
= fptr
->encs
.ecopts
;
1530 if (!fptr
->encs
.enc
|| (fptr
->encs
.enc
== rb_ascii8bit_encoding() && !fptr
->encs
.enc2
)) {
1531 /* no encoding conversion */
1532 fptr
->writeconv_pre_ecflags
= 0;
1533 fptr
->writeconv_pre_ecopts
= Qnil
;
1534 fptr
->writeconv
= rb_econv_open_opts("", "", ecflags
, ecopts
);
1535 if (!fptr
->writeconv
)
1536 rb_exc_raise(rb_econv_open_exc("", "", ecflags
));
1537 fptr
->writeconv_asciicompat
= Qnil
;
1540 enc
= fptr
->encs
.enc2
? fptr
->encs
.enc2
: fptr
->encs
.enc
;
1541 senc
= rb_econv_asciicompat_encoding(rb_enc_name(enc
));
1542 if (!senc
&& !(fptr
->encs
.ecflags
& ECONV_STATEFUL_DECORATOR_MASK
)) {
1543 /* single conversion */
1544 fptr
->writeconv_pre_ecflags
= ecflags
;
1545 fptr
->writeconv_pre_ecopts
= ecopts
;
1546 fptr
->writeconv
= NULL
;
1547 fptr
->writeconv_asciicompat
= Qnil
;
1550 /* double conversion */
1551 fptr
->writeconv_pre_ecflags
= ecflags
& ~ECONV_STATEFUL_DECORATOR_MASK
;
1552 fptr
->writeconv_pre_ecopts
= ecopts
;
1554 denc
= rb_enc_name(enc
);
1555 fptr
->writeconv_asciicompat
= rb_str_new2(senc
);
1559 fptr
->writeconv_asciicompat
= rb_str_new2(rb_enc_name(enc
));
1561 ecflags
= fptr
->encs
.ecflags
& (ECONV_ERROR_HANDLER_MASK
|ECONV_STATEFUL_DECORATOR_MASK
);
1562 ecopts
= fptr
->encs
.ecopts
;
1563 fptr
->writeconv
= rb_econv_open_opts(senc
, denc
, ecflags
, ecopts
);
1564 if (!fptr
->writeconv
)
1565 rb_exc_raise(rb_econv_open_exc(senc
, denc
, ecflags
));
1571 /* writing functions */
1572 struct binwrite_arg
{
1587 io_binwrite_string(VALUE arg
)
1589 struct binwrite_arg
*p
= (struct binwrite_arg
*)arg
;
1590 rb_io_t
*fptr
= p
->fptr
;
1593 if (fptr
->wbuf
.len
) {
1594 struct iovec iov
[2];
1596 iov
[0].iov_base
= fptr
->wbuf
.ptr
+fptr
->wbuf
.off
;
1597 iov
[0].iov_len
= fptr
->wbuf
.len
;
1598 iov
[1].iov_base
= (char *)p
->ptr
;
1599 iov
[1].iov_len
= p
->length
;
1601 r
= rb_writev_internal(fptr
, iov
, 2);
1606 if (fptr
->wbuf
.len
<= r
) {
1607 r
-= fptr
->wbuf
.len
;
1612 fptr
->wbuf
.off
+= (int)r
;
1613 fptr
->wbuf
.len
-= (int)r
;
1618 r
= rb_write_internal(fptr
, p
->ptr
, p
->length
);
1625 io_binwrite_string(VALUE arg
)
1627 struct binwrite_arg
*p
= (struct binwrite_arg
*)arg
;
1628 rb_io_t
*fptr
= p
->fptr
;
1631 l
= len
= p
->length
;
1633 if (fptr
->wbuf
.len
) {
1634 if (fptr
->wbuf
.len
+len
<= fptr
->wbuf
.capa
) {
1635 if (fptr
->wbuf
.capa
< fptr
->wbuf
.off
+fptr
->wbuf
.len
+len
) {
1636 MEMMOVE(fptr
->wbuf
.ptr
, fptr
->wbuf
.ptr
+fptr
->wbuf
.off
, char, fptr
->wbuf
.len
);
1639 MEMMOVE(fptr
->wbuf
.ptr
+fptr
->wbuf
.off
+fptr
->wbuf
.len
, p
->ptr
, char, len
);
1640 fptr
->wbuf
.len
+= (int)len
;
1643 if (io_fflush(fptr
) < 0)
1644 return -2L; /* fail in fflush */
1649 return rb_write_internal(p
->fptr
, p
->ptr
, p
->length
);
1654 io_binwrite(VALUE str
, const char *ptr
, long len
, rb_io_t
*fptr
, int nosync
)
1656 long n
, r
, offset
= 0;
1658 /* don't write anything if current thread has a pending interrupt. */
1659 rb_thread_check_ints();
1661 if ((n
= len
) <= 0) return n
;
1663 if (fptr
->wbuf
.ptr
== NULL
&& !(!nosync
&& (fptr
->mode
& FMODE_SYNC
))) {
1666 fptr
->wbuf
.capa
= IO_WBUF_CAPA_MIN
;
1667 fptr
->wbuf
.ptr
= ALLOC_N(char, fptr
->wbuf
.capa
);
1668 fptr
->write_lock
= rb_mutex_new();
1669 rb_mutex_allow_trap(fptr
->write_lock
, 1);
1672 if ((!nosync
&& (fptr
->mode
& (FMODE_SYNC
|FMODE_TTY
))) ||
1673 (fptr
->wbuf
.ptr
&& fptr
->wbuf
.capa
<= fptr
->wbuf
.len
+ len
)) {
1674 struct binwrite_arg arg
;
1679 arg
.ptr
= ptr
+ offset
;
1682 if (fptr
->write_lock
) {
1683 r
= rb_mutex_synchronize(fptr
->write_lock
, io_binwrite_string
, (VALUE
)&arg
);
1686 r
= io_binwrite_string((VALUE
)&arg
);
1689 /* xxx: other threads may modify given string. */
1690 if (r
== n
) return len
;
1699 if (rb_io_maybe_wait_writable(errno
, fptr
->self
, Qnil
)) {
1700 rb_io_check_closed(fptr
);
1709 if (fptr
->wbuf
.off
) {
1711 MEMMOVE(fptr
->wbuf
.ptr
, fptr
->wbuf
.ptr
+fptr
->wbuf
.off
, char, fptr
->wbuf
.len
);
1715 MEMMOVE(fptr
->wbuf
.ptr
+fptr
->wbuf
.off
+fptr
->wbuf
.len
, ptr
+offset
, char, len
);
1716 fptr
->wbuf
.len
+= (int)len
;
1721 # define MODE_BTMODE(a,b,c) ((fmode & FMODE_BINMODE) ? (b) : \
1722 (fmode & FMODE_TEXTMODE) ? (c) : (a))
1724 #define MODE_BTXMODE(a, b, c, d, e, f) ((fmode & FMODE_EXCL) ? \
1725 MODE_BTMODE(d, e, f) : \
1726 MODE_BTMODE(a, b, c))
1729 do_writeconv(VALUE str
, rb_io_t
*fptr
, int *converted
)
1731 if (NEED_WRITECONV(fptr
)) {
1732 VALUE common_encoding
= Qnil
;
1733 SET_BINARY_MODE(fptr
);
1735 make_writeconv(fptr
);
1737 if (fptr
->writeconv
) {
1738 #define fmode (fptr->mode)
1739 if (!NIL_P(fptr
->writeconv_asciicompat
))
1740 common_encoding
= fptr
->writeconv_asciicompat
;
1741 else if (MODE_BTMODE(DEFAULT_TEXTMODE
,0,1) && !rb_enc_asciicompat(rb_enc_get(str
))) {
1742 rb_raise(rb_eArgError
, "ASCII incompatible string written for text mode IO without encoding conversion: %s",
1743 rb_enc_name(rb_enc_get(str
)));
1748 if (fptr
->encs
.enc2
)
1749 common_encoding
= rb_enc_from_encoding(fptr
->encs
.enc2
);
1750 else if (fptr
->encs
.enc
!= rb_ascii8bit_encoding())
1751 common_encoding
= rb_enc_from_encoding(fptr
->encs
.enc
);
1754 if (!NIL_P(common_encoding
)) {
1755 str
= rb_str_encode(str
, common_encoding
,
1756 fptr
->writeconv_pre_ecflags
, fptr
->writeconv_pre_ecopts
);
1760 if (fptr
->writeconv
) {
1761 str
= rb_econv_str_convert(fptr
->writeconv
, str
, ECONV_PARTIAL_INPUT
);
1765 #if RUBY_CRLF_ENVIRONMENT
1766 #define fmode (fptr->mode)
1767 else if (MODE_BTMODE(DEFAULT_TEXTMODE
,0,1)) {
1768 if ((fptr
->mode
& FMODE_READABLE
) &&
1769 !(fptr
->encs
.ecflags
& ECONV_NEWLINE_DECORATOR_MASK
)) {
1770 setmode(fptr
->fd
, O_BINARY
);
1773 setmode(fptr
->fd
, O_TEXT
);
1775 if (!rb_enc_asciicompat(rb_enc_get(str
))) {
1776 rb_raise(rb_eArgError
, "ASCII incompatible string written for text mode IO without encoding conversion: %s",
1777 rb_enc_name(rb_enc_get(str
)));
1786 io_fwrite(VALUE str
, rb_io_t
*fptr
, int nosync
)
1793 if (fptr
->mode
& FMODE_TTY
) {
1794 long len
= rb_w32_write_console(str
, fptr
->fd
);
1795 if (len
> 0) return len
;
1798 str
= do_writeconv(str
, fptr
, &converted
);
1802 tmp
= rb_str_tmp_frozen_acquire(str
);
1803 RSTRING_GETMEM(tmp
, ptr
, len
);
1804 n
= io_binwrite(tmp
, ptr
, len
, fptr
, nosync
);
1805 rb_str_tmp_frozen_release(str
, tmp
);
1811 rb_io_bufwrite(VALUE io
, const void *buf
, size_t size
)
1815 GetOpenFile(io
, fptr
);
1816 rb_io_check_writable(fptr
);
1817 return (ssize_t
)io_binwrite(0, buf
, (long)size
, fptr
, 0);
1821 io_write(VALUE io
, VALUE str
, int nosync
)
1827 io
= GetWriteIO(io
);
1828 str
= rb_obj_as_string(str
);
1829 tmp
= rb_io_check_io(io
);
1831 /* port is not IO, call write method for it. */
1832 return rb_funcall(io
, id_write
, 1, str
);
1835 if (RSTRING_LEN(str
) == 0) return INT2FIX(0);
1837 GetOpenFile(io
, fptr
);
1838 rb_io_check_writable(fptr
);
1840 n
= io_fwrite(str
, fptr
, nosync
);
1841 if (n
< 0L) rb_sys_fail_on_write(fptr
);
1847 struct binwritev_arg
{
1849 const struct iovec
*iov
;
1854 call_writev_internal(VALUE arg
)
1856 struct binwritev_arg
*p
= (struct binwritev_arg
*)arg
;
1857 return rb_writev_internal(p
->fptr
, p
->iov
, p
->iovcnt
);
1861 io_binwritev(struct iovec
*iov
, int iovcnt
, rb_io_t
*fptr
)
1864 long r
, total
= 0, written_len
= 0;
1866 /* don't write anything if current thread has a pending interrupt. */
1867 rb_thread_check_ints();
1869 if (iovcnt
== 0) return 0;
1870 for (i
= 1; i
< iovcnt
; i
++) total
+= iov
[i
].iov_len
;
1872 if (fptr
->wbuf
.ptr
== NULL
&& !(fptr
->mode
& FMODE_SYNC
)) {
1875 fptr
->wbuf
.capa
= IO_WBUF_CAPA_MIN
;
1876 fptr
->wbuf
.ptr
= ALLOC_N(char, fptr
->wbuf
.capa
);
1877 fptr
->write_lock
= rb_mutex_new();
1878 rb_mutex_allow_trap(fptr
->write_lock
, 1);
1881 if (fptr
->wbuf
.ptr
&& fptr
->wbuf
.len
) {
1882 long offset
= fptr
->wbuf
.off
+ fptr
->wbuf
.len
;
1883 if (offset
+ total
<= fptr
->wbuf
.capa
) {
1884 for (i
= 1; i
< iovcnt
; i
++) {
1885 memcpy(fptr
->wbuf
.ptr
+offset
, iov
[i
].iov_base
, iov
[i
].iov_len
);
1886 offset
+= iov
[i
].iov_len
;
1888 fptr
->wbuf
.len
+= total
;
1892 iov
[0].iov_base
= fptr
->wbuf
.ptr
+ fptr
->wbuf
.off
;
1893 iov
[0].iov_len
= fptr
->wbuf
.len
;
1898 if (!--iovcnt
) return 0;
1902 if (fptr
->write_lock
) {
1903 struct binwritev_arg arg
;
1906 arg
.iovcnt
= iovcnt
;
1907 r
= rb_mutex_synchronize(fptr
->write_lock
, call_writev_internal
, (VALUE
)&arg
);
1910 r
= rb_writev_internal(fptr
, iov
, iovcnt
);
1915 if (fptr
->wbuf
.ptr
&& fptr
->wbuf
.len
) {
1916 if (written_len
< fptr
->wbuf
.len
) {
1917 fptr
->wbuf
.off
+= r
;
1918 fptr
->wbuf
.len
-= r
;
1921 written_len
-= fptr
->wbuf
.len
;
1926 if (written_len
== total
) return total
;
1928 while (r
>= (ssize_t
)iov
->iov_len
) {
1933 if (!--iovcnt
) return total
;
1934 /* defensive check: written_len should == total */
1936 iov
->iov_base
= (char *)iov
->iov_base
+ r
;
1941 if (rb_io_maybe_wait_writable(errno
, fptr
->self
, Qnil
)) {
1942 rb_io_check_closed(fptr
);
1950 io_fwritev(int argc
, const VALUE
*argv
, rb_io_t
*fptr
)
1952 int i
, converted
, iovcnt
= argc
+ 1;
1954 VALUE v1
, v2
, str
, tmp
, *tmp_array
;
1957 iov
= ALLOCV_N(struct iovec
, v1
, iovcnt
);
1958 tmp_array
= ALLOCV_N(VALUE
, v2
, argc
);
1960 for (i
= 0; i
< argc
; i
++) {
1961 str
= rb_obj_as_string(argv
[i
]);
1963 str
= do_writeconv(str
, fptr
, &converted
);
1967 tmp
= rb_str_tmp_frozen_acquire(str
);
1969 /* iov[0] is reserved for buffer of fptr */
1970 iov
[i
+1].iov_base
= RSTRING_PTR(tmp
);
1971 iov
[i
+1].iov_len
= RSTRING_LEN(tmp
);
1974 n
= io_binwritev(iov
, iovcnt
, fptr
);
1975 if (v1
) ALLOCV_END(v1
);
1977 for (i
= 0; i
< argc
; i
++) {
1978 rb_str_tmp_frozen_release(argv
[i
], tmp_array
[i
]);
1981 if (v2
) ALLOCV_END(v2
);
1987 iovcnt_ok(int iovcnt
)
1990 return iovcnt
< IOV_MAX
;
1991 #else /* GNU/Hurd has writev, but no IOV_MAX */
1995 #endif /* HAVE_WRITEV */
1998 io_writev(int argc
, const VALUE
*argv
, VALUE io
)
2002 VALUE tmp
, total
= INT2FIX(0);
2005 io
= GetWriteIO(io
);
2006 tmp
= rb_io_check_io(io
);
2008 /* port is not IO, call write method for it. */
2009 return rb_funcallv(io
, id_write
, argc
, argv
);
2013 GetOpenFile(io
, fptr
);
2014 rb_io_check_writable(fptr
);
2016 for (i
= 0; i
< argc
; i
+= cnt
) {
2018 if ((fptr
->mode
& (FMODE_SYNC
|FMODE_TTY
)) && iovcnt_ok(cnt
= argc
- i
)) {
2019 n
= io_fwritev(cnt
, &argv
[i
], fptr
);
2025 /* sync at last item */
2026 n
= io_fwrite(rb_obj_as_string(argv
[i
]), fptr
, (i
< argc
-1));
2028 if (n
< 0L) rb_sys_fail_on_write(fptr
);
2029 total
= rb_fix_plus(LONG2FIX(n
), total
);
2037 * write(*objects) -> integer
2039 * Writes each of the given +objects+ to +self+,
2040 * which must be opened for writing (see {Modes}[#class-IO-label-Modes]);
2041 * returns the total number bytes written;
2042 * each of +objects+ that is not a string is converted via method +to_s+:
2044 * $stdout.write('Hello', ', ', 'World!', "\n") # => 14
2045 * $stdout.write('foo', :bar, 2, "\n") # => 8
2055 io_write_m(int argc
, VALUE
*argv
, VALUE io
)
2058 return io_writev(argc
, argv
, io
);
2061 VALUE str
= argv
[0];
2062 return io_write(io
, str
, 0);
2067 rb_io_write(VALUE io
, VALUE str
)
2069 return rb_funcallv(io
, id_write
, 1, &str
);
2073 rb_io_writev(VALUE io
, int argc
, const VALUE
*argv
)
2075 if (argc
> 1 && rb_obj_method_arity(io
, id_write
) == 1) {
2076 if (io
!= rb_ractor_stderr() && RTEST(ruby_verbose
)) {
2077 VALUE klass
= CLASS_OF(io
);
2078 char sep
= FL_TEST(klass
, FL_SINGLETON
) ? (klass
= io
, '.') : '#';
2079 rb_category_warning(RB_WARN_CATEGORY_DEPRECATED
, "%+"PRIsVALUE
"%c""write is outdated interface"
2080 " which accepts just one argument",
2083 do rb_io_write(io
, *argv
++); while (--argc
);
2084 return argv
[0]; /* unused right now */
2086 return rb_funcallv(io
, id_write
, argc
, argv
);
2091 * self << object -> self
2093 * Writes the given +object+ to +self+,
2094 * which must be opened for writing (see {Modes}[#class-IO-label-Modes]);
2096 * if +object+ is not a string, it is converted via method +to_s+:
2098 * $stdout << 'Hello' << ', ' << 'World!' << "\n"
2099 * $stdout << 'foo' << :bar << 2 << "\n"
2110 rb_io_addstr(VALUE io
, VALUE str
)
2112 rb_io_write(io
, str
);
2118 nogvl_fsync(void *ptr
)
2120 rb_io_t
*fptr
= ptr
;
2123 if (GetFileType((HANDLE
)rb_w32_get_osfhandle(fptr
->fd
)) != FILE_TYPE_DISK
)
2126 return (VALUE
)fsync(fptr
->fd
);
2131 rb_io_flush_raw(VALUE io
, int sync
)
2135 if (!RB_TYPE_P(io
, T_FILE
)) {
2136 return rb_funcall(io
, id_flush
, 0);
2139 io
= GetWriteIO(io
);
2140 GetOpenFile(io
, fptr
);
2142 if (fptr
->mode
& FMODE_WRITABLE
) {
2143 if (io_fflush(fptr
) < 0)
2144 rb_sys_fail_on_write(fptr
);
2146 if (fptr
->mode
& FMODE_READABLE
) {
2157 * Flushes data buffered in +self+ to the operating system
2158 * (but does not necessarily flush data buffered in the operating system):
2160 * $stdout.print 'no newline' # Not necessarily flushed.
2161 * $stdout.flush # Flushed.
2166 rb_io_flush(VALUE io
)
2168 return rb_io_flush_raw(io
, 1);
2175 * Returns the current position (in bytes) in +self+
2176 * (see {Position}[#class-IO-label-Position]):
2178 * f = File.new('t.txt')
2180 * f.readline # => "This is line one.\n"
2183 * Related: IO#pos=, IO#seek.
2185 * IO#pos is an alias for IO#tell.
2190 rb_io_tell(VALUE io
)
2195 GetOpenFile(io
, fptr
);
2196 pos
= io_tell(fptr
);
2197 if (pos
< 0 && errno
) rb_sys_fail_path(fptr
->pathv
);
2198 pos
-= fptr
->rbuf
.len
;
2199 return OFFT2NUM(pos
);
2203 rb_io_seek(VALUE io
, VALUE offset
, int whence
)
2208 pos
= NUM2OFFT(offset
);
2209 GetOpenFile(io
, fptr
);
2210 pos
= io_seek(fptr
, pos
, whence
);
2211 if (pos
< 0 && errno
) rb_sys_fail_path(fptr
->pathv
);
2217 interpret_seek_whence(VALUE vwhence
)
2219 if (vwhence
== sym_SET
)
2221 if (vwhence
== sym_CUR
)
2223 if (vwhence
== sym_END
)
2226 if (vwhence
== sym_DATA
)
2230 if (vwhence
== sym_HOLE
)
2233 return NUM2INT(vwhence
);
2238 * seek(offset, whence = IO::SEEK_SET) -> 0
2240 * Seeks to the position given by integer +offset+
2241 * (see {Position}[#class-IO-label-Position])
2242 * and constant +whence+, which is one of:
2244 * - +:CUR+ or <tt>IO::SEEK_CUR</tt>:
2245 * Repositions the stream to its current position plus the given +offset+:
2247 * f = File.open('t.txt')
2249 * f.seek(20, :CUR) # => 0
2251 * f.seek(-10, :CUR) # => 0
2254 * - +:END+ or <tt>IO::SEEK_END</tt>:
2255 * Repositions the stream to its end plus the given +offset+:
2257 * f = File.open('t.txt')
2259 * f.seek(0, :END) # => 0 # Repositions to stream end.
2261 * f.seek(-20, :END) # => 0
2263 * f.seek(-40, :END) # => 0
2266 * - +:SET+ or <tt>IO:SEEK_SET</tt>:
2267 * Repositions the stream to the given +offset+:
2269 * f = File.open('t.txt')
2271 * f.seek(20, :SET) # => 0
2273 * f.seek(40, :SET) # => 0
2276 * Related: IO#pos=, IO#tell.
2281 rb_io_seek_m(int argc
, VALUE
*argv
, VALUE io
)
2283 VALUE offset
, ptrname
;
2284 int whence
= SEEK_SET
;
2286 if (rb_scan_args(argc
, argv
, "11", &offset
, &ptrname
) == 2) {
2287 whence
= interpret_seek_whence(ptrname
);
2290 return rb_io_seek(io
, offset
, whence
);
2295 * pos = new_position -> new_position
2297 * Seeks to the given +new_position+ (in bytes);
2298 * see {Position}[#class-IO-label-Position]:
2300 * f = File.open('t.txt')
2302 * f.pos = 20 # => 20
2305 * Related: IO#seek, IO#tell.
2310 rb_io_set_pos(VALUE io
, VALUE offset
)
2315 pos
= NUM2OFFT(offset
);
2316 GetOpenFile(io
, fptr
);
2317 pos
= io_seek(fptr
, pos
, SEEK_SET
);
2318 if (pos
< 0 && errno
) rb_sys_fail_path(fptr
->pathv
);
2320 return OFFT2NUM(pos
);
2323 static void clear_readconv(rb_io_t
*fptr
);
2329 * Repositions the stream to its beginning,
2330 * setting both the position and the line number to zero;
2331 * see {Position}[#class-IO-label-Position]
2332 * and {Line Number}[#class-IO-label-Line+Number]:
2334 * f = File.open('t.txt')
2337 * f.readline # => "This is line one.\n"
2344 * Note that this method cannot be used with streams such as pipes, ttys, and sockets.
2349 rb_io_rewind(VALUE io
)
2353 GetOpenFile(io
, fptr
);
2354 if (io_seek(fptr
, 0L, 0) < 0 && errno
) rb_sys_fail_path(fptr
->pathv
);
2355 if (io
== ARGF
.current_file
) {
2356 ARGF
.lineno
-= fptr
->lineno
;
2359 if (fptr
->readconv
) {
2360 clear_readconv(fptr
);
2367 fptr_wait_readable(rb_io_t
*fptr
)
2369 int ret
= rb_io_maybe_wait_readable(errno
, fptr
->self
, Qnil
);
2372 rb_io_check_closed(fptr
);
2378 io_fillbuf(rb_io_t
*fptr
)
2382 if (fptr
->rbuf
.ptr
== NULL
) {
2385 fptr
->rbuf
.capa
= IO_RBUF_CAPA_FOR(fptr
);
2386 fptr
->rbuf
.ptr
= ALLOC_N(char, fptr
->rbuf
.capa
);
2391 if (fptr
->rbuf
.len
== 0) {
2393 r
= rb_read_internal(fptr
, fptr
->rbuf
.ptr
, fptr
->rbuf
.capa
);
2396 if (fptr_wait_readable(fptr
))
2400 VALUE path
= rb_sprintf("fd:%d ", fptr
->fd
);
2401 if (!NIL_P(fptr
->pathv
)) {
2402 rb_str_append(path
, fptr
->pathv
);
2405 rb_syserr_fail_path(e
, path
);
2407 if (r
> 0) rb_io_check_closed(fptr
);
2409 fptr
->rbuf
.len
= (int)r
; /* r should be <= rbuf_capa */
2411 return -1; /* EOF */
2418 * eof -> true or false
2420 * Returns +true+ if the stream is positioned at its end, +false+ otherwise;
2421 * see {Position}[#class-IO-label-Position]:
2423 * f = File.open('t.txt')
2425 * f.seek(0, :END) # => 0
2428 * Raises an exception unless the stream is opened for reading;
2429 * see {Mode}[#class-IO-label-Mode].
2431 * If +self+ is a stream such as pipe or socket, this method
2432 * blocks until the other end sends some data or closes it:
2435 * Thread.new { sleep 1; w.close }
2436 * r.eof? # => true # After 1-second wait.
2439 * Thread.new { sleep 1; w.puts "a" }
2440 * r.eof? # => false # After 1-second wait.
2443 * r.eof? # blocks forever
2445 * Note that this method reads data to the input byte buffer. So
2446 * IO#sysread may not behave as you intend with IO#eof?, unless you
2447 * call IO#rewind first (which is not available for some streams).
2449 * I#eof? is an alias for IO#eof.
2458 GetOpenFile(io
, fptr
);
2459 rb_io_check_char_readable(fptr
);
2461 if (READ_CHAR_PENDING(fptr
)) return Qfalse
;
2462 if (READ_DATA_PENDING(fptr
)) return Qfalse
;
2464 #if RUBY_CRLF_ENVIRONMENT
2465 if (!NEED_READCONV(fptr
) && NEED_NEWLINE_DECORATOR_ON_READ(fptr
)) {
2466 return RBOOL(eof(fptr
->fd
));;
2469 return RBOOL(io_fillbuf(fptr
) < 0);
2474 * sync -> true or false
2476 * Returns the current sync mode of the stream.
2477 * When sync mode is true, all output is immediately flushed to the underlying
2478 * operating system and is not buffered by Ruby internally. See also #fsync.
2480 * f = File.open('t.tmp', 'w')
2488 rb_io_sync(VALUE io
)
2492 io
= GetWriteIO(io
);
2493 GetOpenFile(io
, fptr
);
2494 return RBOOL(fptr
->mode
& FMODE_SYNC
);
2501 * sync = boolean -> boolean
2503 * Sets the _sync_ _mode_ for the stream to the given value;
2504 * returns the given value.
2506 * Values for the sync mode:
2508 * - +true+: All output is immediately flushed to the
2509 * underlying operating system and is not buffered internally.
2510 * - +false+: Output may be buffered internally.
2514 * f = File.open('t.tmp', 'w')
2519 * Related: IO#fsync.
2524 rb_io_set_sync(VALUE io
, VALUE sync
)
2528 io
= GetWriteIO(io
);
2529 GetOpenFile(io
, fptr
);
2531 fptr
->mode
|= FMODE_SYNC
;
2534 fptr
->mode
&= ~FMODE_SYNC
;
2543 * Immediately writes to disk all data buffered in the stream,
2544 * via the operating system's <tt>fsync(2)</tt>.
2546 * Note this difference:
2548 * - IO#sync=: Ensures that data is flushed from the stream's internal buffers,
2549 * but does not guarantee that the operating system actually writes the data to disk.
2550 * - IO#fsync: Ensures both that data is flushed from internal buffers,
2551 * and that data is written to disk.
2553 * Raises an exception if the operating system does not support <tt>fsync(2)</tt>.
2558 rb_io_fsync(VALUE io
)
2562 io
= GetWriteIO(io
);
2563 GetOpenFile(io
, fptr
);
2565 if (io_fflush(fptr
) < 0)
2566 rb_sys_fail_on_write(fptr
);
2567 if ((int)rb_thread_io_blocking_region(nogvl_fsync
, fptr
, fptr
->fd
) < 0)
2568 rb_sys_fail_path(fptr
->pathv
);
2572 # define rb_io_fsync rb_f_notimplement
2573 # define rb_io_sync rb_f_notimplement
2575 rb_io_set_sync(VALUE io
, VALUE sync
)
2582 #ifdef HAVE_FDATASYNC
2584 nogvl_fdatasync(void *ptr
)
2586 rb_io_t
*fptr
= ptr
;
2589 if (GetFileType((HANDLE
)rb_w32_get_osfhandle(fptr
->fd
)) != FILE_TYPE_DISK
)
2592 return (VALUE
)fdatasync(fptr
->fd
);
2599 * Immediately writes to disk all data buffered in the stream,
2600 * via the operating system's: <tt>fdatasync(2)</tt>, if supported,
2601 * otherwise via <tt>fsync(2)</tt>, if supported;
2602 * otherwise raises an exception.
2607 rb_io_fdatasync(VALUE io
)
2611 io
= GetWriteIO(io
);
2612 GetOpenFile(io
, fptr
);
2614 if (io_fflush(fptr
) < 0)
2615 rb_sys_fail_on_write(fptr
);
2617 if ((int)rb_thread_io_blocking_region(nogvl_fdatasync
, fptr
, fptr
->fd
) == 0)
2621 return rb_io_fsync(io
);
2624 #define rb_io_fdatasync rb_io_fsync
2631 * Returns the integer file descriptor for the stream:
2633 * $stdin.fileno # => 0
2634 * $stdout.fileno # => 1
2635 * $stderr.fileno # => 2
2636 * File.open('t.txt').fileno # => 10
2638 * IO#to_i is an alias for IO#fileno.
2643 rb_io_fileno(VALUE io
)
2645 rb_io_t
*fptr
= RFILE(io
)->fptr
;
2648 rb_io_check_closed(fptr
);
2654 rb_io_descriptor(VALUE io
)
2656 if (RB_TYPE_P(io
, T_FILE
)) {
2657 rb_io_t
*fptr
= RFILE(io
)->fptr
;
2658 rb_io_check_closed(fptr
);
2662 return RB_NUM2INT(rb_funcall(io
, id_fileno
, 0));
2668 * pid -> integer or nil
2670 * Returns the process ID of a child process associated with the stream,
2671 * which will have been set by IO#popen, or +nil+ if the stream was not
2672 * created by IO#popen:
2674 * pipe = IO.popen("-")
2676 * $stderr.puts "In parent, child pid is #{pipe.pid}"
2678 * $stderr.puts "In child, pid is #{$$}"
2683 * In child, pid is 26209
2684 * In parent, child pid is 26209
2693 GetOpenFile(io
, fptr
);
2696 return PIDT2NUM(fptr
->pid
);
2704 * Returns a string representation of +self+:
2706 * f = File.open('t.txt')
2707 * f.inspect # => "#<File:t.txt>"
2712 rb_io_inspect(VALUE obj
)
2716 static const char closed
[] = " (closed)";
2718 fptr
= RFILE(obj
)->fptr
;
2719 if (!fptr
) return rb_any_to_s(obj
);
2720 result
= rb_str_new_cstr("#<");
2721 rb_str_append(result
, rb_class_name(CLASS_OF(obj
)));
2722 rb_str_cat2(result
, ":");
2723 if (NIL_P(fptr
->pathv
)) {
2725 rb_str_cat(result
, closed
+1, strlen(closed
)-1);
2728 rb_str_catf(result
, "fd %d", fptr
->fd
);
2732 rb_str_append(result
, fptr
->pathv
);
2734 rb_str_cat(result
, closed
, strlen(closed
));
2737 return rb_str_cat2(result
, ">");
2749 rb_io_to_io(VALUE io
)
2754 /* reading functions */
2756 read_buffered_data(char *ptr
, long len
, rb_io_t
*fptr
)
2760 n
= READ_DATA_PENDING_COUNT(fptr
);
2761 if (n
<= 0) return 0;
2762 if (n
> len
) n
= (int)len
;
2763 MEMMOVE(ptr
, fptr
->rbuf
.ptr
+fptr
->rbuf
.off
, char, n
);
2764 fptr
->rbuf
.off
+= n
;
2765 fptr
->rbuf
.len
-= n
;
2770 io_bufread(char *ptr
, long len
, rb_io_t
*fptr
)
2776 if (READ_DATA_PENDING(fptr
) == 0) {
2779 rb_io_check_closed(fptr
);
2780 c
= rb_read_internal(fptr
, ptr
+offset
, n
);
2783 if (fptr_wait_readable(fptr
))
2788 if ((n
-= c
) <= 0) break;
2794 c
= read_buffered_data(ptr
+offset
, n
, fptr
);
2797 if ((n
-= c
) <= 0) break;
2799 rb_io_check_closed(fptr
);
2800 if (io_fillbuf(fptr
) < 0) {
2807 static int io_setstrbuf(VALUE
*str
, long len
);
2809 struct bufread_arg
{
2816 bufread_call(VALUE arg
)
2818 struct bufread_arg
*p
= (struct bufread_arg
*)arg
;
2819 p
->len
= io_bufread(p
->str_ptr
, p
->len
, p
->fptr
);
2824 io_fread(VALUE str
, long offset
, long size
, rb_io_t
*fptr
)
2827 struct bufread_arg arg
;
2829 io_setstrbuf(&str
, offset
+ size
);
2830 arg
.str_ptr
= RSTRING_PTR(str
) + offset
;
2833 rb_str_locktmp_ensure(str
, bufread_call
, (VALUE
)&arg
);
2835 if (len
< 0) rb_sys_fail_path(fptr
->pathv
);
2840 remain_size(rb_io_t
*fptr
)
2843 off_t siz
= READ_DATA_PENDING_COUNT(fptr
);
2846 if (fstat(fptr
->fd
, &st
) == 0 && S_ISREG(st
.st_mode
)
2847 #if defined(__HAIKU__)
2852 if (io_fflush(fptr
) < 0)
2853 rb_sys_fail_on_write(fptr
);
2854 pos
= lseek(fptr
->fd
, 0, SEEK_CUR
);
2855 if (st
.st_size
>= pos
&& pos
>= 0) {
2856 siz
+= st
.st_size
- pos
;
2857 if (siz
> LONG_MAX
) {
2858 rb_raise(rb_eIOError
, "file too big for single read");
2869 io_enc_str(VALUE str
, rb_io_t
*fptr
)
2871 rb_enc_associate(str
, io_read_encoding(fptr
));
2876 make_readconv(rb_io_t
*fptr
, int size
)
2878 if (!fptr
->readconv
) {
2881 const char *sname
, *dname
;
2882 ecflags
= fptr
->encs
.ecflags
& ~ECONV_NEWLINE_DECORATOR_WRITE_MASK
;
2883 ecopts
= fptr
->encs
.ecopts
;
2884 if (fptr
->encs
.enc2
) {
2885 sname
= rb_enc_name(fptr
->encs
.enc2
);
2886 dname
= rb_enc_name(fptr
->encs
.enc
);
2891 fptr
->readconv
= rb_econv_open_opts(sname
, dname
, ecflags
, ecopts
);
2892 if (!fptr
->readconv
)
2893 rb_exc_raise(rb_econv_open_exc(sname
, dname
, ecflags
));
2896 if (size
< IO_CBUF_CAPA_MIN
) size
= IO_CBUF_CAPA_MIN
;
2897 fptr
->cbuf
.capa
= size
;
2898 fptr
->cbuf
.ptr
= ALLOC_N(char, fptr
->cbuf
.capa
);
2902 #define MORE_CHAR_SUSPENDED Qtrue
2903 #define MORE_CHAR_FINISHED Qnil
2905 fill_cbuf(rb_io_t
*fptr
, int ec_flags
)
2907 const unsigned char *ss
, *sp
, *se
;
2908 unsigned char *ds
, *dp
, *de
;
2909 rb_econv_result_t res
;
2914 ec_flags
|= ECONV_PARTIAL_INPUT
;
2916 if (fptr
->cbuf
.len
== fptr
->cbuf
.capa
)
2917 return MORE_CHAR_SUSPENDED
; /* cbuf full */
2918 if (fptr
->cbuf
.len
== 0)
2920 else if (fptr
->cbuf
.off
+ fptr
->cbuf
.len
== fptr
->cbuf
.capa
) {
2921 memmove(fptr
->cbuf
.ptr
, fptr
->cbuf
.ptr
+fptr
->cbuf
.off
, fptr
->cbuf
.len
);
2925 cbuf_len0
= fptr
->cbuf
.len
;
2928 ss
= sp
= (const unsigned char *)fptr
->rbuf
.ptr
+ fptr
->rbuf
.off
;
2929 se
= sp
+ fptr
->rbuf
.len
;
2930 ds
= dp
= (unsigned char *)fptr
->cbuf
.ptr
+ fptr
->cbuf
.off
+ fptr
->cbuf
.len
;
2931 de
= (unsigned char *)fptr
->cbuf
.ptr
+ fptr
->cbuf
.capa
;
2932 res
= rb_econv_convert(fptr
->readconv
, &sp
, se
, &dp
, de
, ec_flags
);
2933 fptr
->rbuf
.off
+= (int)(sp
- ss
);
2934 fptr
->rbuf
.len
-= (int)(sp
- ss
);
2935 fptr
->cbuf
.len
+= (int)(dp
- ds
);
2937 putbackable
= rb_econv_putbackable(fptr
->readconv
);
2939 rb_econv_putback(fptr
->readconv
, (unsigned char *)fptr
->rbuf
.ptr
+ fptr
->rbuf
.off
- putbackable
, putbackable
);
2940 fptr
->rbuf
.off
-= putbackable
;
2941 fptr
->rbuf
.len
+= putbackable
;
2944 exc
= rb_econv_make_exception(fptr
->readconv
);
2948 if (cbuf_len0
!= fptr
->cbuf
.len
)
2949 return MORE_CHAR_SUSPENDED
;
2951 if (res
== econv_finished
) {
2952 return MORE_CHAR_FINISHED
;
2955 if (res
== econv_source_buffer_empty
) {
2956 if (fptr
->rbuf
.len
== 0) {
2958 if (io_fillbuf(fptr
) < 0) {
2959 if (!fptr
->readconv
) {
2960 return MORE_CHAR_FINISHED
;
2962 ds
= dp
= (unsigned char *)fptr
->cbuf
.ptr
+ fptr
->cbuf
.off
+ fptr
->cbuf
.len
;
2963 de
= (unsigned char *)fptr
->cbuf
.ptr
+ fptr
->cbuf
.capa
;
2964 res
= rb_econv_convert(fptr
->readconv
, NULL
, NULL
, &dp
, de
, 0);
2965 fptr
->cbuf
.len
+= (int)(dp
- ds
);
2966 rb_econv_check_error(fptr
->readconv
);
2972 if (cbuf_len0
!= fptr
->cbuf
.len
)
2973 return MORE_CHAR_SUSPENDED
;
2975 return MORE_CHAR_FINISHED
;
2979 more_char(rb_io_t
*fptr
)
2982 v
= fill_cbuf(fptr
, ECONV_AFTER_OUTPUT
);
2983 if (v
!= MORE_CHAR_SUSPENDED
&& v
!= MORE_CHAR_FINISHED
)
2989 io_shift_cbuf(rb_io_t
*fptr
, int len
, VALUE
*strp
)
2995 *strp
= str
= rb_str_new(fptr
->cbuf
.ptr
+fptr
->cbuf
.off
, len
);
2998 rb_str_cat(str
, fptr
->cbuf
.ptr
+fptr
->cbuf
.off
, len
);
3000 rb_enc_associate(str
, fptr
->encs
.enc
);
3002 fptr
->cbuf
.off
+= len
;
3003 fptr
->cbuf
.len
-= len
;
3004 /* xxx: set coderange */
3005 if (fptr
->cbuf
.len
== 0)
3007 else if (fptr
->cbuf
.capa
/2 < fptr
->cbuf
.off
) {
3008 memmove(fptr
->cbuf
.ptr
, fptr
->cbuf
.ptr
+fptr
->cbuf
.off
, fptr
->cbuf
.len
);
3015 io_setstrbuf(VALUE
*str
, long len
)
3018 len
= (len
+ 1) & ~1L; /* round up for wide char */
3021 *str
= rb_str_new(0, len
);
3025 VALUE s
= StringValue(*str
);
3026 long clen
= RSTRING_LEN(s
);
3033 rb_str_modify_expand(*str
, len
);
3037 #define MAX_REALLOC_GAP 4096
3039 io_shrink_read_string(VALUE str
, long n
)
3041 if (rb_str_capacity(str
) - n
> MAX_REALLOC_GAP
) {
3042 rb_str_resize(str
, n
);
3047 io_set_read_length(VALUE str
, long n
, int shrinkable
)
3049 if (RSTRING_LEN(str
) != n
) {
3051 rb_str_set_len(str
, n
);
3052 if (shrinkable
) io_shrink_read_string(str
, n
);
3057 read_all(rb_io_t
*fptr
, long siz
, VALUE str
)
3066 if (NEED_READCONV(fptr
)) {
3067 int first
= !NIL_P(str
);
3068 SET_BINARY_MODE(fptr
);
3069 shrinkable
= io_setstrbuf(&str
,0);
3070 make_readconv(fptr
, 0);
3073 if (fptr
->cbuf
.len
) {
3074 if (first
) rb_str_set_len(str
, first
= 0);
3075 io_shift_cbuf(fptr
, fptr
->cbuf
.len
, &str
);
3077 v
= fill_cbuf(fptr
, 0);
3078 if (v
!= MORE_CHAR_SUSPENDED
&& v
!= MORE_CHAR_FINISHED
) {
3079 if (fptr
->cbuf
.len
) {
3080 if (first
) rb_str_set_len(str
, first
= 0);
3081 io_shift_cbuf(fptr
, fptr
->cbuf
.len
, &str
);
3085 if (v
== MORE_CHAR_FINISHED
) {
3086 clear_readconv(fptr
);
3087 if (first
) rb_str_set_len(str
, first
= 0);
3088 if (shrinkable
) io_shrink_read_string(str
, RSTRING_LEN(str
));
3089 return io_enc_str(str
, fptr
);
3094 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr
);
3098 enc
= io_read_encoding(fptr
);
3101 if (siz
== 0) siz
= BUFSIZ
;
3102 shrinkable
= io_setstrbuf(&str
, siz
);
3105 n
= io_fread(str
, bytes
, siz
- bytes
, fptr
);
3106 if (n
== 0 && bytes
== 0) {
3107 rb_str_set_len(str
, 0);
3111 rb_str_set_len(str
, bytes
);
3112 if (cr
!= ENC_CODERANGE_BROKEN
)
3113 pos
+= rb_str_coderange_scan_restartable(RSTRING_PTR(str
) + pos
, RSTRING_PTR(str
) + bytes
, enc
, &cr
);
3114 if (bytes
< siz
) break;
3116 rb_str_modify_expand(str
, BUFSIZ
);
3118 if (shrinkable
) io_shrink_read_string(str
, RSTRING_LEN(str
));
3119 str
= io_enc_str(str
, fptr
);
3120 ENC_CODERANGE_SET(str
, cr
);
3125 rb_io_set_nonblock(rb_io_t
*fptr
)
3127 if (rb_fd_set_nonblock(fptr
->fd
) != 0) {
3128 rb_sys_fail_path(fptr
->pathv
);
3133 read_internal_call(VALUE arg
)
3135 struct io_internal_read_struct
*iis
= (struct io_internal_read_struct
*)arg
;
3137 VALUE scheduler
= rb_fiber_scheduler_current();
3138 if (scheduler
!= Qnil
) {
3139 VALUE result
= rb_fiber_scheduler_io_read_memory(scheduler
, iis
->fptr
->self
, iis
->buf
, iis
->capa
, 0);
3141 if (result
!= Qundef
) {
3142 // This is actually returned as a pseudo-VALUE and later cast to a long:
3143 return (VALUE
)rb_fiber_scheduler_io_result_apply(result
);
3147 return rb_thread_io_blocking_region(internal_read_func
, iis
, iis
->fptr
->fd
);
3151 read_internal_locktmp(VALUE str
, struct io_internal_read_struct
*iis
)
3153 return (long)rb_str_locktmp_ensure(str
, read_internal_call
, (VALUE
)iis
);
3156 #define no_exception_p(opts) !rb_opts_exception_p((opts), TRUE)
3159 io_getpartial(int argc
, VALUE
*argv
, VALUE io
, int no_exception
, int nonblock
)
3164 struct io_internal_read_struct iis
;
3167 rb_scan_args(argc
, argv
, "11", &length
, &str
);
3169 if ((len
= NUM2LONG(length
)) < 0) {
3170 rb_raise(rb_eArgError
, "negative length %ld given", len
);
3173 shrinkable
= io_setstrbuf(&str
, len
);
3175 GetOpenFile(io
, fptr
);
3176 rb_io_check_byte_readable(fptr
);
3179 io_set_read_length(str
, 0, shrinkable
);
3185 n
= read_buffered_data(RSTRING_PTR(str
), len
, fptr
);
3189 rb_io_set_nonblock(fptr
);
3191 io_setstrbuf(&str
, len
);
3192 iis
.th
= rb_thread_current();
3194 iis
.nonblock
= nonblock
;
3195 iis
.buf
= RSTRING_PTR(str
);
3197 n
= read_internal_locktmp(str
, &iis
);
3200 if (!nonblock
&& fptr_wait_readable(fptr
))
3202 if (nonblock
&& (io_again_p(e
))) {
3204 return sym_wait_readable
;
3206 rb_readwrite_syserr_fail(RB_IO_WAIT_READABLE
,
3207 e
, "read would block");
3209 rb_syserr_fail_path(e
, fptr
->pathv
);
3212 io_set_read_length(str
, n
, shrinkable
);
3222 * readpartial(maxlen) -> string
3223 * readpartial(maxlen, out_string) -> out_string
3225 * Reads up to +maxlen+ bytes from the stream;
3226 * returns a string (either a new string or the given +out_string+).
3229 * - The unchanged encoding of +out_string+, if +out_string+ is given.
3230 * - ASCII-8BIT, otherwise.
3232 * - Contains +maxlen+ bytes from the stream, if available.
3233 * - Otherwise contains all available bytes, if any available.
3234 * - Otherwise is an empty string.
3236 * With the single non-negative integer argument +maxlen+ given,
3237 * returns a new string:
3239 * f = File.new('t.txt')
3240 * f.readpartial(30) # => "This is line one.\nThis is the"
3241 * f.readpartial(30) # => " second line.\nThis is the thi"
3242 * f.readpartial(30) # => "rd line.\n"
3244 * f.readpartial(30) # Raises EOFError.
3246 * With both argument +maxlen+ and string argument +out_string+ given,
3247 * returns modified +out_string+:
3249 * f = File.new('t.txt')
3251 * f.readpartial(30, s) # => "This is line one.\nThis is the"
3253 * f.readpartial(0, s) # => ""
3255 * This method is useful for a stream such as a pipe, a socket, or a tty.
3256 * It blocks only when no data is immediately available.
3257 * This means that it blocks only when _all_ of the following are true:
3259 * - The byte buffer in the stream is empty.
3260 * - The content of the stream is empty.
3261 * - The stream is not at EOF.
3263 * When blocked, the method waits for either more data or EOF on the stream:
3265 * - If more data is read, the method returns the data.
3266 * - If EOF is reached, the method raises EOFError.
3268 * When not blocked, the method responds immediately:
3270 * - Returns data from the buffer if there is any.
3271 * - Otherwise returns data from the stream if there is any.
3272 * - Otherwise raises EOFError if the stream has reached EOF.
3274 * Note that this method is similar to sysread. The differences are:
3276 * - If the byte buffer is not empty, read from the byte buffer
3277 * instead of "sysread for buffered IO (IOError)".
3278 * - It doesn't cause Errno::EWOULDBLOCK and Errno::EINTR. When
3279 * readpartial meets EWOULDBLOCK and EINTR by read system call,
3280 * readpartial retries the system call.
3282 * The latter means that readpartial is non-blocking-flag insensitive.
3283 * It blocks on the situation IO#sysread causes Errno::EWOULDBLOCK as
3284 * if the fd is blocking mode.
3288 * # # Returned Buffer Content Pipe Content
3290 * w << 'abc' # "" "abc".
3291 * r.readpartial(4096) # => "abc" "" ""
3292 * r.readpartial(4096) # (Blocks because buffer and pipe are empty.)
3294 * # # Returned Buffer Content Pipe Content
3296 * w << 'abc' # "" "abc"
3297 * w.close # "" "abc" EOF
3298 * r.readpartial(4096) # => "abc" "" EOF
3299 * r.readpartial(4096) # raises EOFError
3301 * # # Returned Buffer Content Pipe Content
3303 * w << "abc\ndef\n" # "" "abc\ndef\n"
3304 * r.gets # => "abc\n" "def\n" ""
3305 * w << "ghi\n" # "def\n" "ghi\n"
3306 * r.readpartial(4096) # => "def\n" "" "ghi\n"
3307 * r.readpartial(4096) # => "ghi\n" "" ""
3312 io_readpartial(int argc
, VALUE
*argv
, VALUE io
)
3316 ret
= io_getpartial(argc
, argv
, io
, Qnil
, 0);
3323 io_nonblock_eof(int no_exception
)
3325 if (!no_exception
) {
3333 io_read_nonblock(rb_execution_context_t
*ec
, VALUE io
, VALUE length
, VALUE str
, VALUE ex
)
3337 struct io_internal_read_struct iis
;
3340 if ((len
= NUM2LONG(length
)) < 0) {
3341 rb_raise(rb_eArgError
, "negative length %ld given", len
);
3344 shrinkable
= io_setstrbuf(&str
, len
);
3345 rb_bool_expected(ex
, "exception");
3347 GetOpenFile(io
, fptr
);
3348 rb_io_check_byte_readable(fptr
);
3351 io_set_read_length(str
, 0, shrinkable
);
3355 n
= read_buffered_data(RSTRING_PTR(str
), len
, fptr
);
3357 rb_io_set_nonblock(fptr
);
3358 shrinkable
|= io_setstrbuf(&str
, len
);
3361 iis
.buf
= RSTRING_PTR(str
);
3363 n
= read_internal_locktmp(str
, &iis
);
3366 if (io_again_p(e
)) {
3367 if (!ex
) return sym_wait_readable
;
3368 rb_readwrite_syserr_fail(RB_IO_WAIT_READABLE
,
3369 e
, "read would block");
3371 rb_syserr_fail_path(e
, fptr
->pathv
);
3374 io_set_read_length(str
, n
, shrinkable
);
3377 if (!ex
) return Qnil
;
3386 io_write_nonblock(rb_execution_context_t
*ec
, VALUE io
, VALUE str
, VALUE ex
)
3391 if (!RB_TYPE_P(str
, T_STRING
))
3392 str
= rb_obj_as_string(str
);
3393 rb_bool_expected(ex
, "exception");
3395 io
= GetWriteIO(io
);
3396 GetOpenFile(io
, fptr
);
3397 rb_io_check_writable(fptr
);
3399 if (io_fflush(fptr
) < 0)
3400 rb_sys_fail_on_write(fptr
);
3402 rb_io_set_nonblock(fptr
);
3403 n
= write(fptr
->fd
, RSTRING_PTR(str
), RSTRING_LEN(str
));
3408 if (io_again_p(e
)) {
3410 return sym_wait_writable
;
3413 rb_readwrite_syserr_fail(RB_IO_WAIT_WRITABLE
, e
, "write would block");
3416 rb_syserr_fail_path(e
, fptr
->pathv
);
3424 * read(maxlen = nil) -> string or nil
3425 * read(maxlen = nil, out_string) -> out_string or nil
3427 * Reads bytes from the stream (in binary mode):
3429 * - If +maxlen+ is +nil+, reads all bytes.
3430 * - Otherwise reads +maxlen+ bytes, if available.
3431 * - Otherwise reads all bytes.
3433 * Returns a string (either a new string or the given +out_string+)
3434 * containing the bytes read.
3435 * The encoding of the string depends on both +maxLen+ and +out_string+:
3437 * - +maxlen+ is +nil+: uses internal encoding of +self+
3438 * (regardless of whether +out_string+ was given).
3439 * - +maxlen+ not +nil+:
3441 * - +out_string+ given: encoding of +out_string+ not modified.
3442 * - +out_string+ not given: ASCII-8BIT is used.
3444 * <b>Without Argument +out_string+</b>
3446 * When argument +out_string+ is omitted,
3447 * the returned value is a new string:
3449 * f = File.new('t.txt')
3451 * # => "This is line one.\nThis is the second line.\nThis is the third line.\n"
3453 * f.read(40) # => "This is line one.\r\nThis is the second li"
3454 * f.read(40) # => "ne.\r\nThis is the third line.\r\n"
3455 * f.read(40) # => nil
3457 * If +maxlen+ is zero, returns an empty string.
3459 * <b> With Argument +out_string+</b>
3461 * When argument +out_string+ is given,
3462 * the returned value is +out_string+, whose content is replaced:
3464 * f = File.new('t.txt')
3465 * s = 'foo' # => "foo"
3466 * f.read(nil, s) # => "This is line one.\nThis is the second line.\nThis is the third line.\n"
3467 * s # => "This is line one.\nThis is the second line.\nThis is the third line.\n"
3470 * f.read(40, s) # => "This is line one.\r\nThis is the second li"
3471 * s # => "This is line one.\r\nThis is the second li"
3473 * f.read(40, s) # => "ne.\r\nThis is the third line.\r\n"
3474 * s # => "ne.\r\nThis is the third line.\r\n"
3476 * f.read(40, s) # => nil
3479 * Note that this method behaves like the fread() function in C.
3480 * This means it retries to invoke read(2) system calls to read data
3481 * with the specified maxlen (or until EOF).
3483 * This behavior is preserved even if the stream is in non-blocking mode.
3484 * (This method is non-blocking-flag insensitive as other methods.)
3486 * If you need the behavior like a single read(2) system call,
3487 * consider #readpartial, #read_nonblock, and #sysread.
3492 io_read(int argc
, VALUE
*argv
, VALUE io
)
3498 #if RUBY_CRLF_ENVIRONMENT
3502 rb_scan_args(argc
, argv
, "02", &length
, &str
);
3504 if (NIL_P(length
)) {
3505 GetOpenFile(io
, fptr
);
3506 rb_io_check_char_readable(fptr
);
3507 return read_all(fptr
, remain_size(fptr
), str
);
3509 len
= NUM2LONG(length
);
3511 rb_raise(rb_eArgError
, "negative length %ld given", len
);
3514 shrinkable
= io_setstrbuf(&str
,len
);
3516 GetOpenFile(io
, fptr
);
3517 rb_io_check_byte_readable(fptr
);
3519 io_set_read_length(str
, 0, shrinkable
);
3524 #if RUBY_CRLF_ENVIRONMENT
3525 previous_mode
= set_binary_mode_with_seek_cur(fptr
);
3527 n
= io_fread(str
, 0, len
, fptr
);
3528 io_set_read_length(str
, n
, shrinkable
);
3529 #if RUBY_CRLF_ENVIRONMENT
3530 if (previous_mode
== O_TEXT
) {
3531 setmode(fptr
->fd
, O_TEXT
);
3534 if (n
== 0) return Qnil
;
3540 rscheck(const char *rsptr
, long rslen
, VALUE rs
)
3543 if (RSTRING_PTR(rs
) != rsptr
&& RSTRING_LEN(rs
) != rslen
)
3544 rb_raise(rb_eRuntimeError
, "rs modified");
3548 appendline(rb_io_t
*fptr
, int delim
, VALUE
*strp
, long *lp
)
3553 if (NEED_READCONV(fptr
)) {
3554 SET_BINARY_MODE(fptr
);
3555 make_readconv(fptr
, 0);
3558 int searchlen
= READ_CHAR_PENDING_COUNT(fptr
);
3560 p
= READ_CHAR_PENDING_PTR(fptr
);
3561 if (0 < limit
&& limit
< searchlen
)
3562 searchlen
= (int)limit
;
3563 e
= memchr(p
, delim
, searchlen
);
3565 int len
= (int)(e
-p
+1);
3567 *strp
= str
= rb_str_new(p
, len
);
3569 rb_str_buf_cat(str
, p
, len
);
3570 fptr
->cbuf
.off
+= len
;
3571 fptr
->cbuf
.len
-= len
;
3578 *strp
= str
= rb_str_new(p
, searchlen
);
3580 rb_str_buf_cat(str
, p
, searchlen
);
3581 fptr
->cbuf
.off
+= searchlen
;
3582 fptr
->cbuf
.len
-= searchlen
;
3587 return (unsigned char)RSTRING_PTR(str
)[RSTRING_LEN(str
)-1];
3590 } while (more_char(fptr
) != MORE_CHAR_FINISHED
);
3591 clear_readconv(fptr
);
3596 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr
);
3598 long pending
= READ_DATA_PENDING_COUNT(fptr
);
3600 const char *p
= READ_DATA_PENDING_PTR(fptr
);
3604 if (limit
> 0 && pending
> limit
) pending
= limit
;
3605 e
= memchr(p
, delim
, pending
);
3606 if (e
) pending
= e
- p
+ 1;
3608 last
= RSTRING_LEN(str
);
3609 rb_str_resize(str
, last
+ pending
);
3613 *strp
= str
= rb_str_buf_new(pending
);
3614 rb_str_set_len(str
, pending
);
3616 read_buffered_data(RSTRING_PTR(str
) + last
, pending
, fptr
); /* must not fail */
3619 if (e
) return delim
;
3621 return (unsigned char)RSTRING_PTR(str
)[RSTRING_LEN(str
)-1];
3624 } while (io_fillbuf(fptr
) >= 0);
3630 swallow(rb_io_t
*fptr
, int term
)
3632 if (NEED_READCONV(fptr
)) {
3633 rb_encoding
*enc
= io_read_encoding(fptr
);
3634 int needconv
= rb_enc_mbminlen(enc
) != 1;
3635 SET_BINARY_MODE(fptr
);
3636 make_readconv(fptr
, 0);
3639 while ((cnt
= READ_CHAR_PENDING_COUNT(fptr
)) > 0) {
3640 const char *p
= READ_CHAR_PENDING_PTR(fptr
);
3643 if (*p
!= term
) return TRUE
;
3645 while (--i
&& *++p
== term
);
3648 const char *e
= p
+ cnt
;
3649 if (rb_enc_ascget(p
, e
, &i
, enc
) != term
) return TRUE
;
3650 while ((p
+= i
) < e
&& rb_enc_ascget(p
, e
, &i
, enc
) == term
);
3653 io_shift_cbuf(fptr
, (int)cnt
- i
, NULL
);
3655 } while (more_char(fptr
) != MORE_CHAR_FINISHED
);
3659 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr
);
3662 while ((cnt
= READ_DATA_PENDING_COUNT(fptr
)) > 0) {
3664 const char *p
= READ_DATA_PENDING_PTR(fptr
);
3666 if (cnt
> sizeof buf
) cnt
= sizeof buf
;
3667 if (*p
!= term
) return TRUE
;
3669 while (--i
&& *++p
== term
);
3670 if (!read_buffered_data(buf
, cnt
- i
, fptr
)) /* must not fail */
3671 rb_sys_fail_path(fptr
->pathv
);
3674 } while (io_fillbuf(fptr
) == 0);
3679 rb_io_getline_fast(rb_io_t
*fptr
, rb_encoding
*enc
, int chomp
)
3687 int pending
= READ_DATA_PENDING_COUNT(fptr
);
3690 const char *p
= READ_DATA_PENDING_PTR(fptr
);
3694 e
= memchr(p
, '\n', pending
);
3696 pending
= (int)(e
- p
+ 1);
3698 chomplen
= (pending
> 1 && *(e
-1) == '\r') + 1;
3702 str
= rb_str_new(p
, pending
- chomplen
);
3703 fptr
->rbuf
.off
+= pending
;
3704 fptr
->rbuf
.len
-= pending
;
3707 rb_str_resize(str
, len
+ pending
- chomplen
);
3708 read_buffered_data(RSTRING_PTR(str
)+len
, pending
- chomplen
, fptr
);
3709 fptr
->rbuf
.off
+= chomplen
;
3710 fptr
->rbuf
.len
-= chomplen
;
3711 if (pending
== 1 && chomplen
== 1 && len
> 0) {
3712 if (RSTRING_PTR(str
)[len
-1] == '\r') {
3713 rb_str_resize(str
, --len
);
3718 len
+= pending
- chomplen
;
3719 if (cr
!= ENC_CODERANGE_BROKEN
)
3720 pos
+= rb_str_coderange_scan_restartable(RSTRING_PTR(str
) + pos
, RSTRING_PTR(str
) + len
, enc
, &cr
);
3724 } while (io_fillbuf(fptr
) >= 0);
3725 if (NIL_P(str
)) return Qnil
;
3727 str
= io_enc_str(str
, fptr
);
3728 ENC_CODERANGE_SET(str
, cr
);
3734 struct getline_arg
{
3738 unsigned int chomp
: 1;
3742 extract_getline_opts(VALUE opts
, struct getline_arg
*args
)
3749 kwds
[0] = rb_intern_const("chomp");
3751 rb_get_kwargs(opts
, kwds
, 0, -2, &vchomp
);
3752 chomp
= (vchomp
!= Qundef
) && RTEST(vchomp
);
3754 args
->chomp
= chomp
;
3758 extract_getline_args(int argc
, VALUE
*argv
, struct getline_arg
*args
)
3760 VALUE rs
= rb_rs
, lim
= Qnil
;
3765 if (NIL_P(argv
[0]) || !NIL_P(tmp
= rb_check_string_type(argv
[0]))) {
3772 else if (2 <= argc
) {
3773 rs
= argv
[0], lim
= argv
[1];
3778 args
->limit
= NIL_P(lim
) ? -1L : NUM2LONG(lim
);
3782 check_getline_args(VALUE
*rsp
, long *limit
, VALUE io
)
3788 rb_encoding
*enc_rs
, *enc_io
;
3790 GetOpenFile(io
, fptr
);
3791 enc_rs
= rb_enc_get(rs
);
3792 enc_io
= io_read_encoding(fptr
);
3793 if (enc_io
!= enc_rs
&&
3794 (rb_enc_str_coderange(rs
) != ENC_CODERANGE_7BIT
||
3795 (RSTRING_LEN(rs
) > 0 && !rb_enc_asciicompat(enc_io
)))) {
3796 if (rs
== rb_default_rs
) {
3797 rs
= rb_enc_str_new(0, 0, enc_io
);
3798 rb_str_buf_cat_ascii(rs
, "\n");
3802 rb_raise(rb_eArgError
, "encoding mismatch: %s IO with %s RS",
3803 rb_enc_name(enc_io
),
3804 rb_enc_name(enc_rs
));
3811 prepare_getline_args(int argc
, VALUE
*argv
, struct getline_arg
*args
, VALUE io
)
3814 argc
= rb_scan_args(argc
, argv
, "02:", NULL
, NULL
, &opts
);
3815 extract_getline_args(argc
, argv
, args
);
3816 extract_getline_opts(opts
, args
);
3817 check_getline_args(&args
->rs
, &args
->limit
, io
);
3821 rb_io_getline_0(VALUE rs
, long limit
, int chomp
, rb_io_t
*fptr
)
3827 rb_io_check_char_readable(fptr
);
3828 if (NIL_P(rs
) && limit
< 0) {
3829 str
= read_all(fptr
, 0, Qnil
);
3830 if (RSTRING_LEN(str
) == 0) return Qnil
;
3831 if (chomp
) rb_str_chomp_string(str
, rb_default_rs
);
3833 else if (limit
== 0) {
3834 return rb_enc_str_new(0, 0, io_read_encoding(fptr
));
3836 else if (rs
== rb_default_rs
&& limit
< 0 && !NEED_READCONV(fptr
) &&
3837 rb_enc_asciicompat(enc
= io_read_encoding(fptr
))) {
3838 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr
);
3839 return rb_io_getline_fast(fptr
, enc
, chomp
);
3842 int c
, newline
= -1;
3843 const char *rsptr
= 0;
3846 int extra_limit
= 16;
3847 int chomp_cr
= chomp
;
3849 SET_BINARY_MODE(fptr
);
3850 enc
= io_read_encoding(fptr
);
3853 rslen
= RSTRING_LEN(rs
);
3858 swallow(fptr
, '\n');
3860 if (!rb_enc_asciicompat(enc
)) {
3861 rs
= rb_usascii_str_new(rsptr
, rslen
);
3862 rs
= rb_str_encode(rs
, rb_enc_from_encoding(enc
), 0, Qnil
);
3864 rsptr
= RSTRING_PTR(rs
);
3865 rslen
= RSTRING_LEN(rs
);
3869 rsptr
= RSTRING_PTR(rs
);
3871 newline
= (unsigned char)rsptr
[rslen
- 1];
3872 chomp_cr
= chomp
&& rslen
== 1 && newline
== '\n';
3875 /* MS - Optimization */
3876 while ((c
= appendline(fptr
, newline
, &str
, &limit
)) != EOF
) {
3877 const char *s
, *p
, *pp
, *e
;
3880 if (RSTRING_LEN(str
) < rslen
) continue;
3881 s
= RSTRING_PTR(str
);
3882 e
= RSTRING_END(str
);
3884 pp
= rb_enc_left_char_head(s
, p
, e
, enc
);
3885 if (pp
!= p
) continue;
3886 if (!rspara
) rscheck(rsptr
, rslen
, rs
);
3887 if (memcmp(p
, rsptr
, rslen
) == 0) {
3889 if (chomp_cr
&& p
> s
&& *(p
-1) == '\r') --p
;
3890 rb_str_set_len(str
, p
- s
);
3896 s
= RSTRING_PTR(str
);
3897 p
= RSTRING_END(str
);
3898 pp
= rb_enc_left_char_head(s
, p
-1, p
, enc
);
3900 MBCLEN_NEEDMORE_P(rb_enc_precise_mbclen(pp
, p
, enc
))) {
3901 /* relax the limit while incomplete character.
3902 * extra_limit limits the relax length */
3913 if (rspara
&& c
!= EOF
)
3914 swallow(fptr
, '\n');
3916 str
= io_enc_str(str
, fptr
);
3919 if (!NIL_P(str
) && !nolimit
) {
3927 rb_io_getline_1(VALUE rs
, long limit
, int chomp
, VALUE io
)
3930 int old_lineno
, new_lineno
;
3933 GetOpenFile(io
, fptr
);
3934 old_lineno
= fptr
->lineno
;
3935 str
= rb_io_getline_0(rs
, limit
, chomp
, fptr
);
3936 if (!NIL_P(str
) && (new_lineno
= fptr
->lineno
) != old_lineno
) {
3937 if (io
== ARGF
.current_file
) {
3938 ARGF
.lineno
+= new_lineno
- old_lineno
;
3939 ARGF
.last_lineno
= ARGF
.lineno
;
3942 ARGF
.last_lineno
= new_lineno
;
3950 rb_io_getline(int argc
, VALUE
*argv
, VALUE io
)
3952 struct getline_arg args
;
3954 prepare_getline_args(argc
, argv
, &args
, io
);
3955 return rb_io_getline_1(args
.rs
, args
.limit
, args
.chomp
, io
);
3959 rb_io_gets(VALUE io
)
3961 return rb_io_getline_1(rb_default_rs
, -1, FALSE
, io
);
3965 rb_io_gets_internal(VALUE io
)
3968 GetOpenFile(io
, fptr
);
3969 return rb_io_getline_0(rb_default_rs
, -1, FALSE
, fptr
);
3974 * gets(sep = $/, **getline_opts) -> string or nil
3975 * gets(limit, **getline_opts) -> string or nil
3976 * gets(sep, limit, **getline_opts) -> string or nil
3978 * Reads and returns data from the stream;
3979 * assigns the return value to <tt>$_</tt>.
3981 * With no arguments given, returns the next line
3982 * as determined by line separator <tt>$/</tt>, or +nil+ if none:
3984 * f = File.open('t.txt')
3985 * f.gets # => "This is line one.\n"
3986 * $_ # => "This is line one.\n"
3987 * f.gets # => "This is the second line.\n"
3988 * f.gets # => "This is the third line.\n"
3991 * With string argument +sep+ given, but not argument +limit+,
3992 * returns the next line as determined by line separator +sep+,
3995 * f = File.open('t.txt')
3996 * f.gets(' is') # => "This is"
3997 * f.gets(' is') # => " line one.\nThis is"
3998 * f.gets(' is') # => " the second line.\nThis is"
3999 * f.gets(' is') # => " the third line.\n"
4000 * f.gets(' is') # => nil
4002 * Note two special values for +sep+:
4004 * - +nil+: The entire stream is read and returned.
4005 * - <tt>''</tt> (empty string): The next "paragraph" is read and returned,
4006 * the paragraph separator being two successive line separators.
4008 * With integer argument +limit+ given,
4009 * returns up to <tt>limit+1</tt> bytes:
4011 * # Text with 1-byte characters.
4012 * File.open('t.txt') {|f| f.gets(1) } # => "T"
4013 * File.open('t.txt') {|f| f.gets(2) } # => "Th"
4014 * File.open('t.txt') {|f| f.gets(3) } # => "Thi"
4015 * File.open('t.txt') {|f| f.gets(4) } # => "This"
4016 * # No more than one line.
4017 * File.open('t.txt') {|f| f.gets(17) } # => "This is line one."
4018 * File.open('t.txt') {|f| f.gets(18) } # => "This is line one.\n"
4019 * File.open('t.txt') {|f| f.gets(19) } # => "This is line one.\n"
4021 * # Text with 2-byte characters, which will not be split.
4022 * File.open('t.rus') {|f| f.gets(1).size } # => 1
4023 * File.open('t.rus') {|f| f.gets(2).size } # => 1
4024 * File.open('t.rus') {|f| f.gets(3).size } # => 2
4025 * File.open('t.rus') {|f| f.gets(4).size } # => 2
4027 * With arguments +sep+ and +limit+,
4028 * combines the two behaviors above:
4030 * - Returns the next line as determined by line separator +sep+,
4032 * - But returns no more than <tt>limit+1</tt> bytes.
4034 * For all forms above, trailing optional keyword arguments may be given;
4035 * see {Getline Options}[#class-IO-label-Getline+Options]:
4037 * f = File.open('t.txt')
4038 * # Chomp the lines.
4039 * f.gets(chomp: true) # => "This is line one."
4040 * f.gets(chomp: true) # => "This is the second line."
4041 * f.gets(chomp: true) # => "This is the third line."
4042 * f.gets(chomp: true) # => nil
4047 rb_io_gets_m(int argc
, VALUE
*argv
, VALUE io
)
4051 str
= rb_io_getline(argc
, argv
, io
);
4052 rb_lastline_set(str
);
4059 * ios.lineno -> integer
4061 * Returns the current line number in <em>ios</em>. The stream must be
4062 * opened for reading. #lineno counts the number of times #gets is called
4063 * rather than the number of newlines encountered. The two values will
4064 * differ if #gets is called with a separator other than newline.
4066 * Methods that use <code>$/</code> like #each, #lines and #readline will
4067 * also increment #lineno.
4069 * See also the <code>$.</code> variable.
4071 * f = File.new("testfile")
4073 * f.gets #=> "This is line one\n"
4075 * f.gets #=> "This is line two\n"
4080 rb_io_lineno(VALUE io
)
4084 GetOpenFile(io
, fptr
);
4085 rb_io_check_char_readable(fptr
);
4086 return INT2NUM(fptr
->lineno
);
4091 * ios.lineno = integer -> integer
4093 * Manually sets the current line number to the given value.
4094 * <code>$.</code> is updated only on the next read.
4096 * f = File.new("testfile")
4097 * f.gets #=> "This is line one\n"
4101 * $. #=> 1 # lineno of last read
4102 * f.gets #=> "This is line two\n"
4103 * $. #=> 1001 # lineno of last read
4107 rb_io_set_lineno(VALUE io
, VALUE lineno
)
4111 GetOpenFile(io
, fptr
);
4112 rb_io_check_char_readable(fptr
);
4113 fptr
->lineno
= NUM2INT(lineno
);
4119 * ios.readline(sep=$/ [, getline_args]) -> string
4120 * ios.readline(limit [, getline_args]) -> string
4121 * ios.readline(sep, limit [, getline_args]) -> string
4123 * Reads a line as with IO#gets, but raises an EOFError on end of file.
4127 rb_io_readline(int argc
, VALUE
*argv
, VALUE io
)
4129 VALUE line
= rb_io_gets_m(argc
, argv
, io
);
4137 static VALUE
io_readlines(const struct getline_arg
*arg
, VALUE io
);
4141 * ios.readlines(sep=$/ [, getline_args]) -> array
4142 * ios.readlines(limit [, getline_args]) -> array
4143 * ios.readlines(sep, limit [, getline_args]) -> array
4145 * Reads all of the lines in <em>ios</em>, and returns them in
4146 * an array. Lines are separated by the optional <i>sep</i>. If
4147 * <i>sep</i> is +nil+, the rest of the stream is returned
4148 * as a single record.
4149 * If the first argument is an integer, or an
4150 * optional second argument is given, the returning string would not be
4151 * longer than the given value in bytes. The stream must be opened for
4152 * reading or an IOError will be raised.
4154 * f = File.new("testfile")
4155 * f.readlines[0] #=> "This is line one\n"
4157 * f = File.new("testfile", chomp: true)
4158 * f.readlines[0] #=> "This is line one"
4160 * See IO.readlines for details about getline_args.
4164 rb_io_readlines(int argc
, VALUE
*argv
, VALUE io
)
4166 struct getline_arg args
;
4168 prepare_getline_args(argc
, argv
, &args
, io
);
4169 return io_readlines(&args
, io
);
4173 io_readlines(const struct getline_arg
*arg
, VALUE io
)
4177 if (arg
->limit
== 0)
4178 rb_raise(rb_eArgError
, "invalid limit: 0 for readlines");
4180 while (!NIL_P(line
= rb_io_getline_1(arg
->rs
, arg
->limit
, arg
->chomp
, io
))) {
4181 rb_ary_push(ary
, line
);
4188 * ios.each(sep=$/ [, getline_args]) {|line| block } -> ios
4189 * ios.each(limit [, getline_args]) {|line| block } -> ios
4190 * ios.each(sep, limit [, getline_args]) {|line| block } -> ios
4191 * ios.each(...) -> an_enumerator
4193 * ios.each_line(sep=$/ [, getline_args]) {|line| block } -> ios
4194 * ios.each_line(limit [, getline_args]) {|line| block } -> ios
4195 * ios.each_line(sep, limit [, getline_args]) {|line| block } -> ios
4196 * ios.each_line(...) -> an_enumerator
4198 * Executes the block for every line in <em>ios</em>, where lines are
4199 * separated by <i>sep</i>. <em>ios</em> must be opened for
4200 * reading or an IOError will be raised.
4202 * If no block is given, an enumerator is returned instead.
4204 * f = File.new("testfile")
4205 * f.each {|line| puts "#{f.lineno}: #{line}" }
4207 * <em>produces:</em>
4209 * 1: This is line one
4210 * 2: This is line two
4211 * 3: This is line three
4214 * See IO.readlines for details about getline_args.
4218 rb_io_each_line(int argc
, VALUE
*argv
, VALUE io
)
4221 struct getline_arg args
;
4223 RETURN_ENUMERATOR(io
, argc
, argv
);
4224 prepare_getline_args(argc
, argv
, &args
, io
);
4225 if (args
.limit
== 0)
4226 rb_raise(rb_eArgError
, "invalid limit: 0 for each_line");
4227 while (!NIL_P(str
= rb_io_getline_1(args
.rs
, args
.limit
, args
.chomp
, io
))) {
4235 * ios.each_byte {|byte| block } -> ios
4236 * ios.each_byte -> an_enumerator
4238 * Calls the given block once for each byte (0..255) in <em>ios</em>,
4239 * passing the byte as an argument. The stream must be opened for
4240 * reading or an IOError will be raised.
4242 * If no block is given, an enumerator is returned instead.
4244 * f = File.new("testfile")
4246 * f.each_byte {|x| checksum ^= x } #=> #<File:testfile>
4251 rb_io_each_byte(VALUE io
)
4255 RETURN_ENUMERATOR(io
, 0, 0);
4256 GetOpenFile(io
, fptr
);
4259 while (fptr
->rbuf
.len
> 0) {
4260 char *p
= fptr
->rbuf
.ptr
+ fptr
->rbuf
.off
++;
4262 rb_yield(INT2FIX(*p
& 0xff));
4263 rb_io_check_byte_readable(fptr
);
4267 } while (io_fillbuf(fptr
) >= 0);
4272 io_getc(rb_io_t
*fptr
, rb_encoding
*enc
)
4277 if (NEED_READCONV(fptr
)) {
4278 rb_encoding
*read_enc
= io_read_encoding(fptr
);
4281 SET_BINARY_MODE(fptr
);
4282 make_readconv(fptr
, 0);
4285 if (fptr
->cbuf
.len
) {
4286 r
= rb_enc_precise_mbclen(fptr
->cbuf
.ptr
+fptr
->cbuf
.off
,
4287 fptr
->cbuf
.ptr
+fptr
->cbuf
.off
+fptr
->cbuf
.len
,
4289 if (!MBCLEN_NEEDMORE_P(r
))
4291 if (fptr
->cbuf
.len
== fptr
->cbuf
.capa
) {
4292 rb_raise(rb_eIOError
, "too long character");
4296 if (more_char(fptr
) == MORE_CHAR_FINISHED
) {
4297 if (fptr
->cbuf
.len
== 0) {
4298 clear_readconv(fptr
);
4301 /* return an unit of an incomplete character just before EOF */
4302 str
= rb_enc_str_new(fptr
->cbuf
.ptr
+fptr
->cbuf
.off
, 1, read_enc
);
4303 fptr
->cbuf
.off
+= 1;
4304 fptr
->cbuf
.len
-= 1;
4305 if (fptr
->cbuf
.len
== 0) clear_readconv(fptr
);
4306 ENC_CODERANGE_SET(str
, ENC_CODERANGE_BROKEN
);
4310 if (MBCLEN_INVALID_P(r
)) {
4311 r
= rb_enc_mbclen(fptr
->cbuf
.ptr
+fptr
->cbuf
.off
,
4312 fptr
->cbuf
.ptr
+fptr
->cbuf
.off
+fptr
->cbuf
.len
,
4314 io_shift_cbuf(fptr
, r
, &str
);
4315 cr
= ENC_CODERANGE_BROKEN
;
4318 io_shift_cbuf(fptr
, MBCLEN_CHARFOUND_LEN(r
), &str
);
4319 cr
= ENC_CODERANGE_VALID
;
4320 if (MBCLEN_CHARFOUND_LEN(r
) == 1 && rb_enc_asciicompat(read_enc
) &&
4321 ISASCII(RSTRING_PTR(str
)[0])) {
4322 cr
= ENC_CODERANGE_7BIT
;
4325 str
= io_enc_str(str
, fptr
);
4326 ENC_CODERANGE_SET(str
, cr
);
4330 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr
);
4331 if (io_fillbuf(fptr
) < 0) {
4334 if (rb_enc_asciicompat(enc
) && ISASCII(fptr
->rbuf
.ptr
[fptr
->rbuf
.off
])) {
4335 str
= rb_str_new(fptr
->rbuf
.ptr
+fptr
->rbuf
.off
, 1);
4336 fptr
->rbuf
.off
+= 1;
4337 fptr
->rbuf
.len
-= 1;
4338 cr
= ENC_CODERANGE_7BIT
;
4341 r
= rb_enc_precise_mbclen(fptr
->rbuf
.ptr
+fptr
->rbuf
.off
, fptr
->rbuf
.ptr
+fptr
->rbuf
.off
+fptr
->rbuf
.len
, enc
);
4342 if (MBCLEN_CHARFOUND_P(r
) &&
4343 (n
= MBCLEN_CHARFOUND_LEN(r
)) <= fptr
->rbuf
.len
) {
4344 str
= rb_str_new(fptr
->rbuf
.ptr
+fptr
->rbuf
.off
, n
);
4345 fptr
->rbuf
.off
+= n
;
4346 fptr
->rbuf
.len
-= n
;
4347 cr
= ENC_CODERANGE_VALID
;
4349 else if (MBCLEN_NEEDMORE_P(r
)) {
4350 str
= rb_str_new(fptr
->rbuf
.ptr
+fptr
->rbuf
.off
, fptr
->rbuf
.len
);
4353 if (io_fillbuf(fptr
) != -1) {
4354 rb_str_cat(str
, fptr
->rbuf
.ptr
+fptr
->rbuf
.off
, 1);
4357 r
= rb_enc_precise_mbclen(RSTRING_PTR(str
), RSTRING_PTR(str
)+RSTRING_LEN(str
), enc
);
4358 if (MBCLEN_NEEDMORE_P(r
)) {
4361 else if (MBCLEN_CHARFOUND_P(r
)) {
4362 cr
= ENC_CODERANGE_VALID
;
4367 str
= rb_str_new(fptr
->rbuf
.ptr
+fptr
->rbuf
.off
, 1);
4372 if (!cr
) cr
= ENC_CODERANGE_BROKEN
;
4373 str
= io_enc_str(str
, fptr
);
4374 ENC_CODERANGE_SET(str
, cr
);
4380 * ios.each_char {|c| block } -> ios
4381 * ios.each_char -> an_enumerator
4383 * Calls the given block once for each character in <em>ios</em>,
4384 * passing the character as an argument. The stream must be opened for
4385 * reading or an IOError will be raised.
4387 * If no block is given, an enumerator is returned instead.
4389 * f = File.new("testfile")
4390 * f.each_char {|c| print c, ' ' } #=> #<File:testfile>
4394 rb_io_each_char(VALUE io
)
4400 RETURN_ENUMERATOR(io
, 0, 0);
4401 GetOpenFile(io
, fptr
);
4402 rb_io_check_char_readable(fptr
);
4404 enc
= io_input_encoding(fptr
);
4406 while (!NIL_P(c
= io_getc(fptr
, enc
))) {
4414 * ios.each_codepoint {|c| block } -> ios
4415 * ios.each_codepoint -> an_enumerator
4417 * Passes the Integer ordinal of each character in <i>ios</i>,
4418 * passing the codepoint as an argument. The stream must be opened for
4419 * reading or an IOError will be raised.
4421 * If no block is given, an enumerator is returned instead.
4426 rb_io_each_codepoint(VALUE io
)
4433 RETURN_ENUMERATOR(io
, 0, 0);
4434 GetOpenFile(io
, fptr
);
4435 rb_io_check_char_readable(fptr
);
4438 if (NEED_READCONV(fptr
)) {
4439 SET_BINARY_MODE(fptr
);
4440 r
= 1; /* no invalid char yet */
4442 make_readconv(fptr
, 0);
4444 if (fptr
->cbuf
.len
) {
4446 r
= rb_enc_precise_mbclen(fptr
->cbuf
.ptr
+fptr
->cbuf
.off
,
4447 fptr
->cbuf
.ptr
+fptr
->cbuf
.off
+fptr
->cbuf
.len
,
4450 r
= ONIGENC_CONSTRUCT_MBCLEN_CHARFOUND(1);
4451 if (!MBCLEN_NEEDMORE_P(r
))
4453 if (fptr
->cbuf
.len
== fptr
->cbuf
.capa
) {
4454 rb_raise(rb_eIOError
, "too long character");
4457 if (more_char(fptr
) == MORE_CHAR_FINISHED
) {
4458 clear_readconv(fptr
);
4459 if (!MBCLEN_CHARFOUND_P(r
)) {
4460 enc
= fptr
->encs
.enc
;
4466 if (MBCLEN_INVALID_P(r
)) {
4467 enc
= fptr
->encs
.enc
;
4470 n
= MBCLEN_CHARFOUND_LEN(r
);
4471 if (fptr
->encs
.enc
) {
4472 c
= rb_enc_codepoint(fptr
->cbuf
.ptr
+fptr
->cbuf
.off
,
4473 fptr
->cbuf
.ptr
+fptr
->cbuf
.off
+fptr
->cbuf
.len
,
4477 c
= (unsigned char)fptr
->cbuf
.ptr
[fptr
->cbuf
.off
];
4479 fptr
->cbuf
.off
+= n
;
4480 fptr
->cbuf
.len
-= n
;
4481 rb_yield(UINT2NUM(c
));
4482 rb_io_check_byte_readable(fptr
);
4485 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr
);
4486 enc
= io_input_encoding(fptr
);
4487 while (io_fillbuf(fptr
) >= 0) {
4488 r
= rb_enc_precise_mbclen(fptr
->rbuf
.ptr
+fptr
->rbuf
.off
,
4489 fptr
->rbuf
.ptr
+fptr
->rbuf
.off
+fptr
->rbuf
.len
, enc
);
4490 if (MBCLEN_CHARFOUND_P(r
) &&
4491 (n
= MBCLEN_CHARFOUND_LEN(r
)) <= fptr
->rbuf
.len
) {
4492 c
= rb_enc_codepoint(fptr
->rbuf
.ptr
+fptr
->rbuf
.off
,
4493 fptr
->rbuf
.ptr
+fptr
->rbuf
.off
+fptr
->rbuf
.len
, enc
);
4494 fptr
->rbuf
.off
+= n
;
4495 fptr
->rbuf
.len
-= n
;
4496 rb_yield(UINT2NUM(c
));
4498 else if (MBCLEN_INVALID_P(r
)) {
4501 else if (MBCLEN_NEEDMORE_P(r
)) {
4502 char cbuf
[8], *p
= cbuf
;
4503 int more
= MBCLEN_NEEDMORE_LEN(r
);
4504 if (more
> numberof(cbuf
)) goto invalid
;
4505 more
+= n
= fptr
->rbuf
.len
;
4506 if (more
> numberof(cbuf
)) goto invalid
;
4507 while ((n
= (int)read_buffered_data(p
, more
, fptr
)) > 0 &&
4508 (p
+= n
, (more
-= n
) > 0)) {
4509 if (io_fillbuf(fptr
) < 0) goto invalid
;
4510 if ((n
= fptr
->rbuf
.len
) > more
) n
= more
;
4512 r
= rb_enc_precise_mbclen(cbuf
, p
, enc
);
4513 if (!MBCLEN_CHARFOUND_P(r
)) goto invalid
;
4514 c
= rb_enc_codepoint(cbuf
, p
, enc
);
4515 rb_yield(UINT2NUM(c
));
4520 rb_io_check_byte_readable(fptr
);
4525 rb_raise(rb_eArgError
, "invalid byte sequence in %s", rb_enc_name(enc
));
4526 UNREACHABLE_RETURN(Qundef
);
4531 * ios.getc -> string or nil
4533 * Reads a one-character string from <em>ios</em>. Returns
4534 * +nil+ if called at end of file.
4536 * f = File.new("testfile")
4542 rb_io_getc(VALUE io
)
4547 GetOpenFile(io
, fptr
);
4548 rb_io_check_char_readable(fptr
);
4550 enc
= io_input_encoding(fptr
);
4552 return io_getc(fptr
, enc
);
4557 * ios.readchar -> string
4559 * Reads a one-character string from <em>ios</em>. Raises an
4560 * EOFError on end of file.
4562 * f = File.new("testfile")
4563 * f.readchar #=> "h"
4564 * f.readchar #=> "e"
4568 rb_io_readchar(VALUE io
)
4570 VALUE c
= rb_io_getc(io
);
4580 * ios.getbyte -> integer or nil
4582 * Gets the next 8-bit byte (0..255) from <em>ios</em>. Returns
4583 * +nil+ if called at end of file.
4585 * f = File.new("testfile")
4591 rb_io_getbyte(VALUE io
)
4596 GetOpenFile(io
, fptr
);
4597 rb_io_check_byte_readable(fptr
);
4599 VALUE r_stdout
= rb_ractor_stdout();
4600 if (fptr
->fd
== 0 && (fptr
->mode
& FMODE_TTY
) && RB_TYPE_P(r_stdout
, T_FILE
)) {
4602 GetOpenFile(r_stdout
, ofp
);
4603 if (ofp
->mode
& FMODE_TTY
) {
4604 rb_io_flush(r_stdout
);
4607 if (io_fillbuf(fptr
) < 0) {
4612 c
= (unsigned char)fptr
->rbuf
.ptr
[fptr
->rbuf
.off
-1];
4613 return INT2FIX(c
& 0xff);
4618 * ios.readbyte -> integer
4620 * Reads a byte as with IO#getbyte, but raises an EOFError on end of
4625 rb_io_readbyte(VALUE io
)
4627 VALUE c
= rb_io_getbyte(io
);
4637 * ios.ungetbyte(string) -> nil
4638 * ios.ungetbyte(integer) -> nil
4640 * Pushes back bytes (passed as a parameter) onto <em>ios</em>,
4641 * such that a subsequent buffered read will return it.
4642 * It is only guaranteed to support a single byte, and only if ungetbyte
4643 * or ungetc has not already been called on <em>ios</em> since the previous
4644 * read of at least a single byte from <em>ios</em>.
4645 * However, it can support additional bytes if there is space in the
4646 * internal buffer to allow for it.
4648 * f = File.new("testfile") #=> #<File:testfile>
4649 * b = f.getbyte #=> 0x38
4650 * f.ungetbyte(b) #=> nil
4651 * f.getbyte #=> 0x38
4653 * If given an integer, only uses the lower 8 bits of the integer as the byte
4656 * f = File.new("testfile") #=> #<File:testfile>
4657 * f.ungetbyte(0x102) #=> nil
4660 * Calling this method prepends to the existing buffer, even if the method
4661 * has already been called previously:
4663 * f = File.new("testfile") #=> #<File:testfile>
4664 * f.ungetbyte("ab") #=> nil
4665 * f.ungetbyte("cd") #=> nil
4666 * f.read(5) #=> "cdab8"
4668 * Has no effect with unbuffered reads (such as IO#sysread).
4672 rb_io_ungetbyte(VALUE io
, VALUE b
)
4676 GetOpenFile(io
, fptr
);
4677 rb_io_check_byte_readable(fptr
);
4683 VALUE v
= rb_int_modulo(b
, INT2FIX(256));
4684 unsigned char c
= NUM2INT(v
) & 0xFF;
4685 b
= rb_str_new((const char *)&c
, 1);
4690 io_ungetbyte(b
, fptr
);
4696 * ios.ungetc(integer) -> nil
4697 * ios.ungetc(string) -> nil
4699 * Pushes back characters (passed as a parameter) onto <em>ios</em>,
4700 * such that a subsequent buffered read will return it.
4701 * It is only guaranteed to support a single byte, and only if ungetbyte
4702 * or ungetc has not already been called on <em>ios</em> since the previous
4703 * read of at least a single byte from <em>ios</em>.
4704 * However, it can support additional bytes if there is space in the
4705 * internal buffer to allow for it.
4707 * f = File.new("testfile") #=> #<File:testfile>
4708 * c = f.getc #=> "8"
4709 * f.ungetc(c) #=> nil
4712 * If given an integer, the integer must represent a valid codepoint in the
4713 * external encoding of <em>ios</em>.
4715 * Calling this method prepends to the existing buffer, even if the method
4716 * has already been called previously:
4718 * f = File.new("testfile") #=> #<File:testfile>
4719 * f.ungetc("ab") #=> nil
4720 * f.ungetc("cd") #=> nil
4721 * f.read(5) #=> "cdab8"
4723 * Has no effect with unbuffered reads (such as IO#sysread).
4727 rb_io_ungetc(VALUE io
, VALUE c
)
4732 GetOpenFile(io
, fptr
);
4733 rb_io_check_char_readable(fptr
);
4735 c
= rb_enc_uint_chr(FIX2UINT(c
), io_read_encoding(fptr
));
4737 else if (RB_BIGNUM_TYPE_P(c
)) {
4738 c
= rb_enc_uint_chr(NUM2UINT(c
), io_read_encoding(fptr
));
4743 if (NEED_READCONV(fptr
)) {
4744 SET_BINARY_MODE(fptr
);
4745 len
= RSTRING_LEN(c
);
4746 #if SIZEOF_LONG > SIZEOF_INT
4748 rb_raise(rb_eIOError
, "ungetc failed");
4750 make_readconv(fptr
, (int)len
);
4751 if (fptr
->cbuf
.capa
- fptr
->cbuf
.len
< len
)
4752 rb_raise(rb_eIOError
, "ungetc failed");
4753 if (fptr
->cbuf
.off
< len
) {
4754 MEMMOVE(fptr
->cbuf
.ptr
+fptr
->cbuf
.capa
-fptr
->cbuf
.len
,
4755 fptr
->cbuf
.ptr
+fptr
->cbuf
.off
,
4756 char, fptr
->cbuf
.len
);
4757 fptr
->cbuf
.off
= fptr
->cbuf
.capa
-fptr
->cbuf
.len
;
4759 fptr
->cbuf
.off
-= (int)len
;
4760 fptr
->cbuf
.len
+= (int)len
;
4761 MEMMOVE(fptr
->cbuf
.ptr
+fptr
->cbuf
.off
, RSTRING_PTR(c
), char, len
);
4764 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr
);
4765 io_ungetbyte(c
, fptr
);
4772 * ios.isatty -> true or false
4773 * ios.tty? -> true or false
4775 * Returns <code>true</code> if <em>ios</em> is associated with a
4776 * terminal device (tty), <code>false</code> otherwise.
4778 * File.new("testfile").isatty #=> false
4779 * File.new("/dev/tty").isatty #=> true
4783 rb_io_isatty(VALUE io
)
4787 GetOpenFile(io
, fptr
);
4788 return RBOOL(isatty(fptr
->fd
) != 0);
4791 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
4794 * ios.close_on_exec? -> true or false
4796 * Returns <code>true</code> if <em>ios</em> will be closed on exec.
4798 * f = open("/dev/null")
4799 * f.close_on_exec? #=> false
4800 * f.close_on_exec = true
4801 * f.close_on_exec? #=> true
4802 * f.close_on_exec = false
4803 * f.close_on_exec? #=> false
4807 rb_io_close_on_exec_p(VALUE io
)
4813 write_io
= GetWriteIO(io
);
4814 if (io
!= write_io
) {
4815 GetOpenFile(write_io
, fptr
);
4816 if (fptr
&& 0 <= (fd
= fptr
->fd
)) {
4817 if ((ret
= fcntl(fd
, F_GETFD
)) == -1) rb_sys_fail_path(fptr
->pathv
);
4818 if (!(ret
& FD_CLOEXEC
)) return Qfalse
;
4822 GetOpenFile(io
, fptr
);
4823 if (fptr
&& 0 <= (fd
= fptr
->fd
)) {
4824 if ((ret
= fcntl(fd
, F_GETFD
)) == -1) rb_sys_fail_path(fptr
->pathv
);
4825 if (!(ret
& FD_CLOEXEC
)) return Qfalse
;
4830 #define rb_io_close_on_exec_p rb_f_notimplement
4833 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
4836 * ios.close_on_exec = bool -> true or false
4838 * Sets a close-on-exec flag.
4840 * f = open("/dev/null")
4841 * f.close_on_exec = true
4842 * system("cat", "/proc/self/fd/#{f.fileno}") # cat: /proc/self/fd/3: No such file or directory
4843 * f.closed? #=> false
4845 * Ruby sets close-on-exec flags of all file descriptors by default
4847 * So you don't need to set by yourself.
4848 * Also, unsetting a close-on-exec flag can cause file descriptor leak
4849 * if another thread use fork() and exec() (via system() method for example).
4850 * If you really needs file descriptor inheritance to child process,
4851 * use spawn()'s argument such as fd=>fd.
4855 rb_io_set_close_on_exec(VALUE io
, VALUE arg
)
4857 int flag
= RTEST(arg
) ? FD_CLOEXEC
: 0;
4862 write_io
= GetWriteIO(io
);
4863 if (io
!= write_io
) {
4864 GetOpenFile(write_io
, fptr
);
4865 if (fptr
&& 0 <= (fd
= fptr
->fd
)) {
4866 if ((ret
= fcntl(fptr
->fd
, F_GETFD
)) == -1) rb_sys_fail_path(fptr
->pathv
);
4867 if ((ret
& FD_CLOEXEC
) != flag
) {
4868 ret
= (ret
& ~FD_CLOEXEC
) | flag
;
4869 ret
= fcntl(fd
, F_SETFD
, ret
);
4870 if (ret
!= 0) rb_sys_fail_path(fptr
->pathv
);
4876 GetOpenFile(io
, fptr
);
4877 if (fptr
&& 0 <= (fd
= fptr
->fd
)) {
4878 if ((ret
= fcntl(fd
, F_GETFD
)) == -1) rb_sys_fail_path(fptr
->pathv
);
4879 if ((ret
& FD_CLOEXEC
) != flag
) {
4880 ret
= (ret
& ~FD_CLOEXEC
) | flag
;
4881 ret
= fcntl(fd
, F_SETFD
, ret
);
4882 if (ret
!= 0) rb_sys_fail_path(fptr
->pathv
);
4888 #define rb_io_set_close_on_exec rb_f_notimplement
4891 #define IS_PREP_STDIO(f) ((f)->mode & FMODE_PREP)
4892 #define PREP_STDIO_NAME(f) (RSTRING_PTR((f)->pathv))
4895 finish_writeconv(rb_io_t
*fptr
, int noalloc
)
4897 unsigned char *ds
, *dp
, *de
;
4898 rb_econv_result_t res
;
4900 if (!fptr
->wbuf
.ptr
) {
4901 unsigned char buf
[1024];
4904 res
= econv_destination_buffer_full
;
4905 while (res
== econv_destination_buffer_full
) {
4907 de
= buf
+ sizeof(buf
);
4908 res
= rb_econv_convert(fptr
->writeconv
, NULL
, NULL
, &dp
, de
, 0);
4911 r
= rb_write_internal(fptr
, ds
, dp
-ds
);
4917 if (rb_io_maybe_wait_writable(errno
, fptr
->self
, Qnil
)) {
4919 return noalloc
? Qtrue
: rb_exc_new3(rb_eIOError
, rb_str_new_cstr(closed_stream
));
4922 return noalloc
? Qtrue
: INT2NUM(errno
);
4924 if (res
== econv_invalid_byte_sequence
||
4925 res
== econv_incomplete_input
||
4926 res
== econv_undefined_conversion
) {
4927 return noalloc
? Qtrue
: rb_econv_make_exception(fptr
->writeconv
);
4934 res
= econv_destination_buffer_full
;
4935 while (res
== econv_destination_buffer_full
) {
4936 if (fptr
->wbuf
.len
== fptr
->wbuf
.capa
) {
4937 if (io_fflush(fptr
) < 0)
4938 return noalloc
? Qtrue
: INT2NUM(errno
);
4941 ds
= dp
= (unsigned char *)fptr
->wbuf
.ptr
+ fptr
->wbuf
.off
+ fptr
->wbuf
.len
;
4942 de
= (unsigned char *)fptr
->wbuf
.ptr
+ fptr
->wbuf
.capa
;
4943 res
= rb_econv_convert(fptr
->writeconv
, NULL
, NULL
, &dp
, de
, 0);
4944 fptr
->wbuf
.len
+= (int)(dp
- ds
);
4945 if (res
== econv_invalid_byte_sequence
||
4946 res
== econv_incomplete_input
||
4947 res
== econv_undefined_conversion
) {
4948 return noalloc
? Qtrue
: rb_econv_make_exception(fptr
->writeconv
);
4954 struct finish_writeconv_arg
{
4960 finish_writeconv_sync(VALUE arg
)
4962 struct finish_writeconv_arg
*p
= (struct finish_writeconv_arg
*)arg
;
4963 return finish_writeconv(p
->fptr
, p
->noalloc
);
4967 nogvl_close(void *ptr
)
4971 return (void*)(intptr_t)close(*fd
);
4975 maygvl_close(int fd
, int keepgvl
)
4981 * close() may block for certain file types (NFS, SO_LINGER sockets,
4982 * inotify), so let other threads run.
4984 return (int)(intptr_t)rb_thread_call_without_gvl(nogvl_close
, &fd
, RUBY_UBF_IO
, 0);
4988 nogvl_fclose(void *ptr
)
4992 return (void*)(intptr_t)fclose(file
);
4996 maygvl_fclose(FILE *file
, int keepgvl
)
4999 return fclose(file
);
5001 return (int)(intptr_t)rb_thread_call_without_gvl(nogvl_fclose
, file
, RUBY_UBF_IO
, 0);
5004 static void free_io_buffer(rb_io_buffer_t
*buf
);
5005 static void clear_codeconv(rb_io_t
*fptr
);
5008 fptr_finalize_flush(rb_io_t
*fptr
, int noraise
, int keepgvl
,
5009 struct list_head
*busy
)
5013 FILE *stdio_file
= fptr
->stdio_file
;
5014 int mode
= fptr
->mode
;
5016 if (fptr
->writeconv
) {
5017 if (fptr
->write_lock
&& !noraise
) {
5018 struct finish_writeconv_arg arg
;
5020 arg
.noalloc
= noraise
;
5021 err
= rb_mutex_synchronize(fptr
->write_lock
, finish_writeconv_sync
, (VALUE
)&arg
);
5024 err
= finish_writeconv(fptr
, noraise
);
5027 if (fptr
->wbuf
.len
) {
5029 io_flush_buffer_sync(fptr
);
5032 if (io_fflush(fptr
) < 0 && NIL_P(err
))
5033 err
= INT2NUM(errno
);
5039 if (IS_PREP_STDIO(fptr
) || fd
<= 2) {
5040 // Need to keep FILE objects of stdin, stdout and stderr, so we are done:
5045 fptr
->stdio_file
= 0;
5046 fptr
->mode
&= ~(FMODE_READABLE
|FMODE_WRITABLE
);
5048 // Ensure waiting_fd users do not hit EBADF.
5050 // Wait for them to exit before we call close().
5051 do rb_thread_schedule(); while (!list_empty(busy
));
5055 // if (!done && fd >= 0) {
5056 // VALUE scheduler = rb_fiber_scheduler_current();
5057 // if (scheduler != Qnil) {
5058 // VALUE result = rb_fiber_scheduler_io_close(scheduler, fptr->self);
5059 // if (result != Qundef) done = 1;
5063 if (!done
&& stdio_file
) {
5064 // stdio_file is deallocated anyway even if fclose failed.
5065 if ((maygvl_fclose(stdio_file
, noraise
) < 0) && NIL_P(err
))
5066 if (!noraise
) err
= INT2NUM(errno
);
5071 if (!done
&& fd
>= 0) {
5072 // fptr->fd may be closed even if close fails. POSIX doesn't specify it.
5073 // We assumes it is closed.
5075 keepgvl
|= !(mode
& FMODE_WRITABLE
);
5077 if ((maygvl_close(fd
, keepgvl
) < 0) && NIL_P(err
))
5078 if (!noraise
) err
= INT2NUM(errno
);
5083 if (!NIL_P(err
) && !noraise
) {
5084 if (RB_INTEGER_TYPE_P(err
))
5085 rb_syserr_fail_path(NUM2INT(err
), fptr
->pathv
);
5092 fptr_finalize(rb_io_t
*fptr
, int noraise
)
5094 fptr_finalize_flush(fptr
, noraise
, FALSE
, 0);
5095 free_io_buffer(&fptr
->rbuf
);
5096 free_io_buffer(&fptr
->wbuf
);
5097 clear_codeconv(fptr
);
5101 rb_io_fptr_cleanup(rb_io_t
*fptr
, int noraise
)
5103 if (fptr
->finalize
) {
5104 (*fptr
->finalize
)(fptr
, noraise
);
5107 fptr_finalize(fptr
, noraise
);
5112 free_io_buffer(rb_io_buffer_t
*buf
)
5115 ruby_sized_xfree(buf
->ptr
, (size_t)buf
->capa
);
5121 clear_readconv(rb_io_t
*fptr
)
5123 if (fptr
->readconv
) {
5124 rb_econv_close(fptr
->readconv
);
5125 fptr
->readconv
= NULL
;
5127 free_io_buffer(&fptr
->cbuf
);
5131 clear_writeconv(rb_io_t
*fptr
)
5133 if (fptr
->writeconv
) {
5134 rb_econv_close(fptr
->writeconv
);
5135 fptr
->writeconv
= NULL
;
5137 fptr
->writeconv_initialized
= 0;
5141 clear_codeconv(rb_io_t
*fptr
)
5143 clear_readconv(fptr
);
5144 clear_writeconv(fptr
);
5148 rb_io_fptr_finalize_internal(void *ptr
)
5150 rb_io_t
*fptr
= ptr
;
5155 rb_io_fptr_cleanup(fptr
, TRUE
);
5156 fptr
->write_lock
= 0;
5157 free_io_buffer(&fptr
->rbuf
);
5158 free_io_buffer(&fptr
->wbuf
);
5159 clear_codeconv(fptr
);
5163 #undef rb_io_fptr_finalize
5165 rb_io_fptr_finalize(rb_io_t
*fptr
)
5171 rb_io_fptr_finalize_internal(fptr
);
5175 #define rb_io_fptr_finalize(fptr) rb_io_fptr_finalize_internal(fptr)
5177 RUBY_FUNC_EXPORTED
size_t
5178 rb_io_memsize(const rb_io_t
*fptr
)
5180 size_t size
= sizeof(rb_io_t
);
5181 size
+= fptr
->rbuf
.capa
;
5182 size
+= fptr
->wbuf
.capa
;
5183 size
+= fptr
->cbuf
.capa
;
5184 if (fptr
->readconv
) size
+= rb_econv_memsize(fptr
->readconv
);
5185 if (fptr
->writeconv
) size
+= rb_econv_memsize(fptr
->writeconv
);
5190 /* keep GVL while closing to prevent crash on Windows */
5191 # define KEEPGVL TRUE
5193 # define KEEPGVL FALSE
5196 int rb_notify_fd_close(int fd
, struct list_head
*);
5198 io_close_fptr(VALUE io
)
5202 rb_io_t
*write_fptr
;
5203 struct list_head busy
;
5205 list_head_init(&busy
);
5206 write_io
= GetWriteIO(io
);
5207 if (io
!= write_io
) {
5208 write_fptr
= RFILE(write_io
)->fptr
;
5209 if (write_fptr
&& 0 <= write_fptr
->fd
) {
5210 rb_io_fptr_cleanup(write_fptr
, TRUE
);
5214 fptr
= RFILE(io
)->fptr
;
5215 if (!fptr
) return 0;
5216 if (fptr
->fd
< 0) return 0;
5218 if (rb_notify_fd_close(fptr
->fd
, &busy
)) {
5219 /* calls close(fptr->fd): */
5220 fptr_finalize_flush(fptr
, FALSE
, KEEPGVL
, &busy
);
5222 rb_io_fptr_cleanup(fptr
, FALSE
);
5227 fptr_waitpid(rb_io_t
*fptr
, int nohang
)
5231 rb_last_status_clear();
5232 rb_waitpid(fptr
->pid
, &status
, nohang
? WNOHANG
: 0);
5238 rb_io_close(VALUE io
)
5240 rb_io_t
*fptr
= io_close_fptr(io
);
5241 if (fptr
) fptr_waitpid(fptr
, 0);
5249 * Closes <em>ios</em> and flushes any pending writes to the operating
5250 * system. The stream is unavailable for any further data operations;
5251 * an IOError is raised if such an attempt is made. I/O streams are
5252 * automatically closed when they are claimed by the garbage collector.
5254 * If <em>ios</em> is opened by IO.popen, #close sets
5257 * Calling this method on closed IO object is just ignored since Ruby 2.3.
5261 rb_io_close_m(VALUE io
)
5263 rb_io_t
*fptr
= rb_io_get_fptr(io
);
5272 io_call_close(VALUE io
)
5274 rb_check_funcall(io
, rb_intern("close"), 0, 0);
5279 ignore_closed_stream(VALUE io
, VALUE exc
)
5281 enum {mesg_len
= sizeof(closed_stream
)-1};
5282 VALUE mesg
= rb_attr_get(exc
, idMesg
);
5283 if (!RB_TYPE_P(mesg
, T_STRING
) ||
5284 RSTRING_LEN(mesg
) != mesg_len
||
5285 memcmp(RSTRING_PTR(mesg
), closed_stream
, mesg_len
)) {
5294 VALUE closed
= rb_check_funcall(io
, rb_intern("closed?"), 0, 0);
5295 if (closed
!= Qundef
&& RTEST(closed
)) return io
;
5296 rb_rescue2(io_call_close
, io
, ignore_closed_stream
, io
,
5297 rb_eIOError
, (VALUE
)0);
5303 * ios.closed? -> true or false
5305 * Returns <code>true</code> if <em>ios</em> is completely closed (for
5306 * duplex streams, both reader and writer), <code>false</code>
5309 * f = File.new("testfile")
5311 * f.closed? #=> true
5312 * f = IO.popen("/bin/sh","r+")
5313 * f.close_write #=> nil
5314 * f.closed? #=> false
5315 * f.close_read #=> nil
5316 * f.closed? #=> true
5321 rb_io_closed(VALUE io
)
5325 rb_io_t
*write_fptr
;
5327 write_io
= GetWriteIO(io
);
5328 if (io
!= write_io
) {
5329 write_fptr
= RFILE(write_io
)->fptr
;
5330 if (write_fptr
&& 0 <= write_fptr
->fd
) {
5335 fptr
= rb_io_get_fptr(io
);
5336 return RBOOL(0 > fptr
->fd
);
5341 * ios.close_read -> nil
5343 * Closes the read end of a duplex I/O stream (i.e., one that contains
5344 * both a read and a write stream, such as a pipe). Will raise an
5345 * IOError if the stream is not duplexed.
5347 * f = IO.popen("/bin/sh","r+")
5351 * <em>produces:</em>
5353 * prog.rb:3:in `readlines': not opened for reading (IOError)
5356 * Calling this method on closed IO object is just ignored since Ruby 2.3.
5360 rb_io_close_read(VALUE io
)
5365 fptr
= rb_io_get_fptr(rb_io_taint_check(io
));
5366 if (fptr
->fd
< 0) return Qnil
;
5367 if (is_socket(fptr
->fd
, fptr
->pathv
)) {
5371 if (shutdown(fptr
->fd
, SHUT_RD
) < 0)
5372 rb_sys_fail_path(fptr
->pathv
);
5373 fptr
->mode
&= ~FMODE_READABLE
;
5374 if (!(fptr
->mode
& FMODE_WRITABLE
))
5375 return rb_io_close(io
);
5379 write_io
= GetWriteIO(io
);
5380 if (io
!= write_io
) {
5382 wfptr
= rb_io_get_fptr(rb_io_taint_check(write_io
));
5383 wfptr
->pid
= fptr
->pid
;
5385 RFILE(io
)->fptr
= wfptr
;
5386 /* bind to write_io temporarily to get rid of memory/fd leak */
5387 fptr
->tied_io_for_writing
= 0;
5388 RFILE(write_io
)->fptr
= fptr
;
5389 rb_io_fptr_cleanup(fptr
, FALSE
);
5390 /* should not finalize fptr because another thread may be reading it */
5394 if ((fptr
->mode
& (FMODE_DUPLEX
|FMODE_WRITABLE
)) == FMODE_WRITABLE
) {
5395 rb_raise(rb_eIOError
, "closing non-duplex IO for reading");
5397 return rb_io_close(io
);
5402 * ios.close_write -> nil
5404 * Closes the write end of a duplex I/O stream (i.e., one that contains
5405 * both a read and a write stream, such as a pipe). Will raise an
5406 * IOError if the stream is not duplexed.
5408 * f = IO.popen("/bin/sh","r+")
5412 * <em>produces:</em>
5414 * prog.rb:3:in `write': not opened for writing (IOError)
5415 * from prog.rb:3:in `print'
5418 * Calling this method on closed IO object is just ignored since Ruby 2.3.
5422 rb_io_close_write(VALUE io
)
5427 write_io
= GetWriteIO(io
);
5428 fptr
= rb_io_get_fptr(rb_io_taint_check(write_io
));
5429 if (fptr
->fd
< 0) return Qnil
;
5430 if (is_socket(fptr
->fd
, fptr
->pathv
)) {
5434 if (shutdown(fptr
->fd
, SHUT_WR
) < 0)
5435 rb_sys_fail_path(fptr
->pathv
);
5436 fptr
->mode
&= ~FMODE_WRITABLE
;
5437 if (!(fptr
->mode
& FMODE_READABLE
))
5438 return rb_io_close(write_io
);
5442 if ((fptr
->mode
& (FMODE_DUPLEX
|FMODE_READABLE
)) == FMODE_READABLE
) {
5443 rb_raise(rb_eIOError
, "closing non-duplex IO for writing");
5446 if (io
!= write_io
) {
5447 fptr
= rb_io_get_fptr(rb_io_taint_check(io
));
5448 fptr
->tied_io_for_writing
= 0;
5450 rb_io_close(write_io
);
5456 * ios.sysseek(offset, whence=IO::SEEK_SET) -> integer
5458 * Seeks to a given <i>offset</i> in the stream according to the value
5459 * of <i>whence</i> (see IO#seek for values of <i>whence</i>). Returns
5460 * the new offset into the file.
5462 * f = File.new("testfile")
5463 * f.sysseek(-13, IO::SEEK_END) #=> 53
5464 * f.sysread(10) #=> "And so on."
5468 rb_io_sysseek(int argc
, VALUE
*argv
, VALUE io
)
5470 VALUE offset
, ptrname
;
5471 int whence
= SEEK_SET
;
5475 if (rb_scan_args(argc
, argv
, "11", &offset
, &ptrname
) == 2) {
5476 whence
= interpret_seek_whence(ptrname
);
5478 pos
= NUM2OFFT(offset
);
5479 GetOpenFile(io
, fptr
);
5480 if ((fptr
->mode
& FMODE_READABLE
) &&
5481 (READ_DATA_BUFFERED(fptr
) || READ_CHAR_PENDING(fptr
))) {
5482 rb_raise(rb_eIOError
, "sysseek for buffered IO");
5484 if ((fptr
->mode
& FMODE_WRITABLE
) && fptr
->wbuf
.len
) {
5485 rb_warn("sysseek for buffered IO");
5488 pos
= lseek(fptr
->fd
, pos
, whence
);
5489 if (pos
< 0 && errno
) rb_sys_fail_path(fptr
->pathv
);
5491 return OFFT2NUM(pos
);
5496 * ios.syswrite(string) -> integer
5498 * Writes the given string to <em>ios</em> using a low-level write.
5499 * Returns the number of bytes written. Do not mix with other methods
5500 * that write to <em>ios</em> or you may get unpredictable results.
5501 * Raises SystemCallError on error.
5503 * f = File.new("out", "w")
5504 * f.syswrite("ABCDEF") #=> 6
5508 rb_io_syswrite(VALUE io
, VALUE str
)
5515 if (!RB_TYPE_P(str
, T_STRING
))
5516 str
= rb_obj_as_string(str
);
5518 io
= GetWriteIO(io
);
5519 GetOpenFile(io
, fptr
);
5520 rb_io_check_writable(fptr
);
5522 if (fptr
->wbuf
.len
) {
5523 rb_warn("syswrite for buffered IO");
5526 tmp
= rb_str_tmp_frozen_acquire(str
);
5527 RSTRING_GETMEM(tmp
, ptr
, len
);
5528 n
= rb_write_internal(fptr
, ptr
, len
);
5529 if (n
< 0) rb_sys_fail_path(fptr
->pathv
);
5530 rb_str_tmp_frozen_release(str
, tmp
);
5537 * ios.sysread(maxlen[, outbuf]) -> string
5539 * Reads <i>maxlen</i> bytes from <em>ios</em> using a low-level
5540 * read and returns them as a string. Do not mix with other methods
5541 * that read from <em>ios</em> or you may get unpredictable results.
5543 * If the optional _outbuf_ argument is present,
5544 * it must reference a String, which will receive the data.
5545 * The _outbuf_ will contain only the received data after the method call
5546 * even if it is not empty at the beginning.
5548 * Raises SystemCallError on error and EOFError at end of file.
5550 * f = File.new("testfile")
5551 * f.sysread(16) #=> "This is line one"
5555 rb_io_sysread(int argc
, VALUE
*argv
, VALUE io
)
5560 struct io_internal_read_struct iis
;
5563 rb_scan_args(argc
, argv
, "11", &len
, &str
);
5564 ilen
= NUM2LONG(len
);
5566 shrinkable
= io_setstrbuf(&str
, ilen
);
5567 if (ilen
== 0) return str
;
5569 GetOpenFile(io
, fptr
);
5570 rb_io_check_byte_readable(fptr
);
5572 if (READ_DATA_BUFFERED(fptr
)) {
5573 rb_raise(rb_eIOError
, "sysread for buffered IO");
5576 rb_io_check_closed(fptr
);
5578 io_setstrbuf(&str
, ilen
);
5579 iis
.th
= rb_thread_current();
5582 iis
.buf
= RSTRING_PTR(str
);
5584 n
= read_internal_locktmp(str
, &iis
);
5587 rb_sys_fail_path(fptr
->pathv
);
5590 io_set_read_length(str
, n
, shrinkable
);
5592 if (n
== 0 && ilen
> 0) {
5599 #if defined(HAVE_PREAD) || defined(HAVE_PWRITE)
5600 struct prdwr_internal_arg
{
5606 #endif /* HAVE_PREAD || HAVE_PWRITE */
5608 #if defined(HAVE_PREAD)
5610 internal_pread_func(void *arg
)
5612 struct prdwr_internal_arg
*p
= arg
;
5613 return (VALUE
)pread(p
->fd
, p
->buf
, p
->count
, p
->offset
);
5617 pread_internal_call(VALUE arg
)
5619 struct prdwr_internal_arg
*p
= (struct prdwr_internal_arg
*)arg
;
5620 return rb_thread_io_blocking_region(internal_pread_func
, p
, p
->fd
);
5625 * ios.pread(maxlen, offset[, outbuf]) -> string
5627 * Reads <i>maxlen</i> bytes from <em>ios</em> using the pread system call
5628 * and returns them as a string without modifying the underlying
5629 * descriptor offset. This is advantageous compared to combining IO#seek
5630 * and IO#read in that it is atomic, allowing multiple threads/process to
5631 * share the same IO object for reading the file at various locations.
5632 * This bypasses any userspace buffering of the IO layer.
5633 * If the optional <i>outbuf</i> argument is present, it must
5634 * reference a String, which will receive the data.
5635 * Raises SystemCallError on error, EOFError at end of file and
5636 * NotImplementedError if platform does not implement the system call.
5638 * File.write("testfile", "This is line one\nThis is line two\n")
5639 * File.open("testfile") do |f|
5640 * p f.read # => "This is line one\nThis is line two\n"
5641 * p f.pread(12, 0) # => "This is line"
5642 * p f.pread(9, 8) # => "line one\n"
5646 rb_io_pread(int argc
, VALUE
*argv
, VALUE io
)
5648 VALUE len
, offset
, str
;
5651 struct prdwr_internal_arg arg
;
5654 rb_scan_args(argc
, argv
, "21", &len
, &offset
, &str
);
5655 arg
.count
= NUM2SIZET(len
);
5656 arg
.offset
= NUM2OFFT(offset
);
5658 shrinkable
= io_setstrbuf(&str
, (long)arg
.count
);
5659 if (arg
.count
== 0) return str
;
5660 arg
.buf
= RSTRING_PTR(str
);
5662 GetOpenFile(io
, fptr
);
5663 rb_io_check_byte_readable(fptr
);
5666 rb_io_check_closed(fptr
);
5668 rb_str_locktmp(str
);
5669 n
= (ssize_t
)rb_ensure(pread_internal_call
, (VALUE
)&arg
, rb_str_unlocktmp
, str
);
5672 rb_sys_fail_path(fptr
->pathv
);
5674 io_set_read_length(str
, n
, shrinkable
);
5675 if (n
== 0 && arg
.count
> 0) {
5682 # define rb_io_pread rb_f_notimplement
5683 #endif /* HAVE_PREAD */
5685 #if defined(HAVE_PWRITE)
5687 internal_pwrite_func(void *ptr
)
5689 struct prdwr_internal_arg
*arg
= ptr
;
5691 return (VALUE
)pwrite(arg
->fd
, arg
->buf
, arg
->count
, arg
->offset
);
5696 * ios.pwrite(string, offset) -> integer
5698 * Writes the given string to <em>ios</em> at <i>offset</i> using pwrite()
5699 * system call. This is advantageous to combining IO#seek and IO#write
5700 * in that it is atomic, allowing multiple threads/process to share the
5701 * same IO object for reading the file at various locations.
5702 * This bypasses any userspace buffering of the IO layer.
5703 * Returns the number of bytes written.
5704 * Raises SystemCallError on error and NotImplementedError
5705 * if platform does not implement the system call.
5707 * File.open("out", "w") do |f|
5708 * f.pwrite("ABCDEF", 3) #=> 6
5711 * File.read("out") #=> "\u0000\u0000\u0000ABCDEF"
5714 rb_io_pwrite(VALUE io
, VALUE str
, VALUE offset
)
5718 struct prdwr_internal_arg arg
;
5721 if (!RB_TYPE_P(str
, T_STRING
))
5722 str
= rb_obj_as_string(str
);
5724 arg
.offset
= NUM2OFFT(offset
);
5726 io
= GetWriteIO(io
);
5727 GetOpenFile(io
, fptr
);
5728 rb_io_check_writable(fptr
);
5731 tmp
= rb_str_tmp_frozen_acquire(str
);
5732 arg
.buf
= RSTRING_PTR(tmp
);
5733 arg
.count
= (size_t)RSTRING_LEN(tmp
);
5735 n
= (ssize_t
)rb_thread_io_blocking_region(internal_pwrite_func
, &arg
, fptr
->fd
);
5736 if (n
< 0) rb_sys_fail_path(fptr
->pathv
);
5737 rb_str_tmp_frozen_release(str
, tmp
);
5739 return SSIZET2NUM(n
);
5742 # define rb_io_pwrite rb_f_notimplement
5743 #endif /* HAVE_PWRITE */
5746 rb_io_binmode(VALUE io
)
5750 GetOpenFile(io
, fptr
);
5752 rb_econv_binmode(fptr
->readconv
);
5753 if (fptr
->writeconv
)
5754 rb_econv_binmode(fptr
->writeconv
);
5755 fptr
->mode
|= FMODE_BINMODE
;
5756 fptr
->mode
&= ~FMODE_TEXTMODE
;
5757 fptr
->writeconv_pre_ecflags
&= ~ECONV_NEWLINE_DECORATOR_MASK
;
5759 if (!fptr
->readconv
) {
5760 SET_BINARY_MODE_WITH_SEEK_CUR(fptr
);
5763 setmode(fptr
->fd
, O_BINARY
);
5770 io_ascii8bit_binmode(rb_io_t
*fptr
)
5772 if (fptr
->readconv
) {
5773 rb_econv_close(fptr
->readconv
);
5774 fptr
->readconv
= NULL
;
5776 if (fptr
->writeconv
) {
5777 rb_econv_close(fptr
->writeconv
);
5778 fptr
->writeconv
= NULL
;
5780 fptr
->mode
|= FMODE_BINMODE
;
5781 fptr
->mode
&= ~FMODE_TEXTMODE
;
5782 SET_BINARY_MODE_WITH_SEEK_CUR(fptr
);
5784 fptr
->encs
.enc
= rb_ascii8bit_encoding();
5785 fptr
->encs
.enc2
= NULL
;
5786 fptr
->encs
.ecflags
= 0;
5787 fptr
->encs
.ecopts
= Qnil
;
5788 clear_codeconv(fptr
);
5792 rb_io_ascii8bit_binmode(VALUE io
)
5796 GetOpenFile(io
, fptr
);
5797 io_ascii8bit_binmode(fptr
);
5804 * ios.binmode -> ios
5806 * Puts <em>ios</em> into binary mode.
5807 * Once a stream is in binary mode, it cannot be reset to nonbinary mode.
5809 * - newline conversion disabled
5810 * - encoding conversion disabled
5811 * - content is treated as ASCII-8BIT
5815 rb_io_binmode_m(VALUE io
)
5819 rb_io_ascii8bit_binmode(io
);
5821 write_io
= GetWriteIO(io
);
5823 rb_io_ascii8bit_binmode(write_io
);
5829 * ios.binmode? -> true or false
5831 * Returns <code>true</code> if <em>ios</em> is binmode.
5834 rb_io_binmode_p(VALUE io
)
5837 GetOpenFile(io
, fptr
);
5838 return RBOOL(fptr
->mode
& FMODE_BINMODE
);
5842 rb_io_fmode_modestr(int fmode
)
5844 if (fmode
& FMODE_APPEND
) {
5845 if ((fmode
& FMODE_READWRITE
) == FMODE_READWRITE
) {
5846 return MODE_BTMODE("a+", "ab+", "at+");
5848 return MODE_BTMODE("a", "ab", "at");
5850 switch (fmode
& FMODE_READWRITE
) {
5852 rb_raise(rb_eArgError
, "invalid access fmode 0x%x", fmode
);
5853 case FMODE_READABLE
:
5854 return MODE_BTMODE("r", "rb", "rt");
5855 case FMODE_WRITABLE
:
5856 return MODE_BTXMODE("w", "wb", "wt", "wx", "wbx", "wtx");
5857 case FMODE_READWRITE
:
5858 if (fmode
& FMODE_CREATE
) {
5859 return MODE_BTXMODE("w+", "wb+", "wt+", "w+x", "wb+x", "wt+x");
5861 return MODE_BTMODE("r+", "rb+", "rt+");
5865 static const char bom_prefix
[] = "bom|";
5866 static const char utf_prefix
[] = "utf-";
5867 enum {bom_prefix_len
= (int)sizeof(bom_prefix
) - 1};
5868 enum {utf_prefix_len
= (int)sizeof(utf_prefix
) - 1};
5871 io_encname_bom_p(const char *name
, long len
)
5873 return len
> bom_prefix_len
&& STRNCASECMP(name
, bom_prefix
, bom_prefix_len
) == 0;
5877 rb_io_modestr_fmode(const char *modestr
)
5880 const char *m
= modestr
, *p
= NULL
;
5884 fmode
|= FMODE_READABLE
;
5887 fmode
|= FMODE_WRITABLE
| FMODE_TRUNC
| FMODE_CREATE
;
5890 fmode
|= FMODE_WRITABLE
| FMODE_APPEND
| FMODE_CREATE
;
5899 fmode
|= FMODE_BINMODE
;
5902 fmode
|= FMODE_TEXTMODE
;
5905 fmode
|= FMODE_READWRITE
;
5908 if (modestr
[0] != 'w')
5910 fmode
|= FMODE_EXCL
;
5916 if (io_encname_bom_p(m
, p
? (long)(p
- m
) : (long)strlen(m
)))
5917 fmode
|= FMODE_SETENC_BY_BOM
;
5923 if ((fmode
& FMODE_BINMODE
) && (fmode
& FMODE_TEXTMODE
))
5929 rb_raise(rb_eArgError
, "invalid access mode %s", modestr
);
5930 UNREACHABLE_RETURN(Qundef
);
5934 rb_io_oflags_fmode(int oflags
)
5938 switch (oflags
& O_ACCMODE
) {
5940 fmode
= FMODE_READABLE
;
5943 fmode
= FMODE_WRITABLE
;
5946 fmode
= FMODE_READWRITE
;
5950 if (oflags
& O_APPEND
) {
5951 fmode
|= FMODE_APPEND
;
5953 if (oflags
& O_TRUNC
) {
5954 fmode
|= FMODE_TRUNC
;
5956 if (oflags
& O_CREAT
) {
5957 fmode
|= FMODE_CREATE
;
5959 if (oflags
& O_EXCL
) {
5960 fmode
|= FMODE_EXCL
;
5963 if (oflags
& O_BINARY
) {
5964 fmode
|= FMODE_BINMODE
;
5972 rb_io_fmode_oflags(int fmode
)
5976 switch (fmode
& FMODE_READWRITE
) {
5977 case FMODE_READABLE
:
5980 case FMODE_WRITABLE
:
5983 case FMODE_READWRITE
:
5988 if (fmode
& FMODE_APPEND
) {
5991 if (fmode
& FMODE_TRUNC
) {
5994 if (fmode
& FMODE_CREATE
) {
5997 if (fmode
& FMODE_EXCL
) {
6001 if (fmode
& FMODE_BINMODE
) {
6010 rb_io_modestr_oflags(const char *modestr
)
6012 return rb_io_fmode_oflags(rb_io_modestr_fmode(modestr
));
6016 rb_io_oflags_modestr(int oflags
)
6019 # define MODE_BINARY(a,b) ((oflags & O_BINARY) ? (b) : (a))
6021 # define MODE_BINARY(a,b) (a)
6024 if (oflags
& O_EXCL
) {
6025 rb_raise(rb_eArgError
, "exclusive access mode is not supported");
6027 accmode
= oflags
& (O_RDONLY
|O_WRONLY
|O_RDWR
);
6028 if (oflags
& O_APPEND
) {
6029 if (accmode
== O_WRONLY
) {
6030 return MODE_BINARY("a", "ab");
6032 if (accmode
== O_RDWR
) {
6033 return MODE_BINARY("a+", "ab+");
6038 rb_raise(rb_eArgError
, "invalid access oflags 0x%x", oflags
);
6040 return MODE_BINARY("r", "rb");
6042 return MODE_BINARY("w", "wb");
6044 if (oflags
& O_TRUNC
) {
6045 return MODE_BINARY("w+", "wb+");
6047 return MODE_BINARY("r+", "rb+");
6052 * Convert external/internal encodings to enc/enc2
6053 * NULL => use default encoding
6054 * Qnil => no encoding specified (internal only)
6057 rb_io_ext_int_to_encs(rb_encoding
*ext
, rb_encoding
*intern
, rb_encoding
**enc
, rb_encoding
**enc2
, int fmode
)
6059 int default_ext
= 0;
6062 ext
= rb_default_external_encoding();
6065 if (ext
== rb_ascii8bit_encoding()) {
6066 /* If external is ASCII-8BIT, no transcoding */
6069 else if (intern
== NULL
) {
6070 intern
= rb_default_internal_encoding();
6072 if (intern
== NULL
|| intern
== (rb_encoding
*)Qnil
||
6073 (!(fmode
& FMODE_SETENC_BY_BOM
) && (intern
== ext
))) {
6074 /* No internal encoding => use external + no transcoding */
6075 *enc
= (default_ext
&& intern
!= ext
) ? NULL
: ext
;
6085 unsupported_encoding(const char *name
, rb_encoding
*enc
)
6087 rb_enc_warn(enc
, "Unsupported encoding %s ignored", name
);
6091 parse_mode_enc(const char *estr
, rb_encoding
*estr_enc
,
6092 rb_encoding
**enc_p
, rb_encoding
**enc2_p
, int *fmode_p
)
6095 char encname
[ENCODING_MAXNAMELEN
+1];
6097 int fmode
= fmode_p
? *fmode_p
: 0;
6098 rb_encoding
*ext_enc
, *int_enc
;
6101 /* parse estr as "enc" or "enc2:enc" or "enc:-" */
6103 p
= strrchr(estr
, ':');
6104 len
= p
? (p
++ - estr
) : (long)strlen(estr
);
6105 if ((fmode
& FMODE_SETENC_BY_BOM
) || io_encname_bom_p(estr
, len
)) {
6106 estr
+= bom_prefix_len
;
6107 len
-= bom_prefix_len
;
6108 if (!STRNCASECMP(estr
, utf_prefix
, utf_prefix_len
)) {
6109 fmode
|= FMODE_SETENC_BY_BOM
;
6112 rb_enc_warn(estr_enc
, "BOM with non-UTF encoding %s is nonsense", estr
);
6113 fmode
&= ~FMODE_SETENC_BY_BOM
;
6116 if (len
== 0 || len
> ENCODING_MAXNAMELEN
) {
6121 memcpy(encname
, estr
, len
);
6122 encname
[len
] = '\0';
6125 idx
= rb_enc_find_index(estr
);
6127 if (fmode_p
) *fmode_p
= fmode
;
6130 ext_enc
= rb_enc_from_index(idx
);
6133 unsupported_encoding(estr
, estr_enc
);
6139 if (*p
== '-' && *(p
+1) == '\0') {
6140 /* Special case - "-" => no transcoding */
6141 int_enc
= (rb_encoding
*)Qnil
;
6144 idx2
= rb_enc_find_index(p
);
6146 unsupported_encoding(p
, estr_enc
);
6147 else if (!(fmode
& FMODE_SETENC_BY_BOM
) && (idx2
== idx
)) {
6148 int_enc
= (rb_encoding
*)Qnil
;
6151 int_enc
= rb_enc_from_index(idx2
);
6155 rb_io_ext_int_to_encs(ext_enc
, int_enc
, enc_p
, enc2_p
, fmode
);
6159 rb_io_extract_encoding_option(VALUE opt
, rb_encoding
**enc_p
, rb_encoding
**enc2_p
, int *fmode_p
)
6161 VALUE encoding
=Qnil
, extenc
=Qundef
, intenc
=Qundef
, tmp
;
6163 rb_encoding
*extencoding
= NULL
;
6164 rb_encoding
*intencoding
= NULL
;
6168 v
= rb_hash_lookup2(opt
, sym_encoding
, Qnil
);
6169 if (v
!= Qnil
) encoding
= v
;
6170 v
= rb_hash_lookup2(opt
, sym_extenc
, Qundef
);
6171 if (v
!= Qnil
) extenc
= v
;
6172 v
= rb_hash_lookup2(opt
, sym_intenc
, Qundef
);
6173 if (v
!= Qundef
) intenc
= v
;
6175 if ((extenc
!= Qundef
|| intenc
!= Qundef
) && !NIL_P(encoding
)) {
6176 if (!NIL_P(ruby_verbose
)) {
6177 int idx
= rb_to_encoding_index(encoding
);
6178 if (idx
>= 0) encoding
= rb_enc_from_encoding(rb_enc_from_index(idx
));
6179 rb_warn("Ignoring encoding parameter '%"PRIsVALUE
"': %s_encoding is used",
6180 encoding
, extenc
== Qundef
? "internal" : "external");
6184 if (extenc
!= Qundef
&& !NIL_P(extenc
)) {
6185 extencoding
= rb_to_encoding(extenc
);
6187 if (intenc
!= Qundef
) {
6188 if (NIL_P(intenc
)) {
6189 /* internal_encoding: nil => no transcoding */
6190 intencoding
= (rb_encoding
*)Qnil
;
6192 else if (!NIL_P(tmp
= rb_check_string_type(intenc
))) {
6193 char *p
= StringValueCStr(tmp
);
6195 if (*p
== '-' && *(p
+1) == '\0') {
6196 /* Special case - "-" => no transcoding */
6197 intencoding
= (rb_encoding
*)Qnil
;
6200 intencoding
= rb_to_encoding(intenc
);
6204 intencoding
= rb_to_encoding(intenc
);
6206 if (extencoding
== intencoding
) {
6207 intencoding
= (rb_encoding
*)Qnil
;
6210 if (!NIL_P(encoding
)) {
6212 if (!NIL_P(tmp
= rb_check_string_type(encoding
))) {
6213 parse_mode_enc(StringValueCStr(tmp
), rb_enc_get(tmp
),
6214 enc_p
, enc2_p
, fmode_p
);
6217 rb_io_ext_int_to_encs(rb_to_encoding(encoding
), NULL
, enc_p
, enc2_p
, 0);
6220 else if (extenc
!= Qundef
|| intenc
!= Qundef
) {
6222 rb_io_ext_int_to_encs(extencoding
, intencoding
, enc_p
, enc2_p
, 0);
6227 typedef struct rb_io_enc_t convconfig_t
;
6230 validate_enc_binmode(int *fmode_p
, int ecflags
, rb_encoding
*enc
, rb_encoding
*enc2
)
6232 int fmode
= *fmode_p
;
6234 if ((fmode
& FMODE_READABLE
) &&
6236 !(fmode
& FMODE_BINMODE
) &&
6237 !rb_enc_asciicompat(enc
? enc
: rb_default_external_encoding()))
6238 rb_raise(rb_eArgError
, "ASCII incompatible encoding needs binmode");
6240 if ((fmode
& FMODE_BINMODE
) && (ecflags
& ECONV_NEWLINE_DECORATOR_MASK
)) {
6241 rb_raise(rb_eArgError
, "newline decorator with binary mode");
6243 if (!(fmode
& FMODE_BINMODE
) &&
6244 (DEFAULT_TEXTMODE
|| (ecflags
& ECONV_NEWLINE_DECORATOR_MASK
))) {
6245 fmode
|= FMODE_TEXTMODE
;
6248 #if !DEFAULT_TEXTMODE
6249 else if (!(ecflags
& ECONV_NEWLINE_DECORATOR_MASK
)) {
6250 fmode
&= ~FMODE_TEXTMODE
;
6257 extract_binmode(VALUE opthash
, int *fmode
)
6259 if (!NIL_P(opthash
)) {
6261 v
= rb_hash_aref(opthash
, sym_textmode
);
6263 if (*fmode
& FMODE_TEXTMODE
)
6264 rb_raise(rb_eArgError
, "textmode specified twice");
6265 if (*fmode
& FMODE_BINMODE
)
6266 rb_raise(rb_eArgError
, "both textmode and binmode specified");
6268 *fmode
|= FMODE_TEXTMODE
;
6270 v
= rb_hash_aref(opthash
, sym_binmode
);
6272 if (*fmode
& FMODE_BINMODE
)
6273 rb_raise(rb_eArgError
, "binmode specified twice");
6274 if (*fmode
& FMODE_TEXTMODE
)
6275 rb_raise(rb_eArgError
, "both textmode and binmode specified");
6277 *fmode
|= FMODE_BINMODE
;
6280 if ((*fmode
& FMODE_BINMODE
) && (*fmode
& FMODE_TEXTMODE
))
6281 rb_raise(rb_eArgError
, "both textmode and binmode specified");
6286 rb_io_extract_modeenc(VALUE
*vmode_p
, VALUE
*vperm_p
, VALUE opthash
,
6287 int *oflags_p
, int *fmode_p
, convconfig_t
*convconfig_p
)
6291 rb_encoding
*enc
, *enc2
;
6294 int has_enc
= 0, has_vmode
= 0;
6299 /* Set to defaults */
6300 rb_io_ext_int_to_encs(NULL
, NULL
, &enc
, &enc2
, 0);
6304 fmode
= FMODE_READABLE
;
6307 else if (!NIL_P(intmode
= rb_check_to_integer(vmode
, "to_int"))) {
6309 oflags
= NUM2INT(intmode
);
6310 fmode
= rb_io_oflags_fmode(oflags
);
6315 SafeStringValue(vmode
);
6316 p
= StringValueCStr(vmode
);
6317 fmode
= rb_io_modestr_fmode(p
);
6318 oflags
= rb_io_fmode_oflags(fmode
);
6322 parse_mode_enc(p
+1, rb_enc_get(vmode
), &enc
, &enc2
, &fmode
);
6327 e
= (fmode
& FMODE_BINMODE
) ? rb_ascii8bit_encoding() : NULL
;
6328 rb_io_ext_int_to_encs(e
, NULL
, &enc
, &enc2
, fmode
);
6332 if (NIL_P(opthash
)) {
6333 ecflags
= (fmode
& FMODE_READABLE
) ?
6334 MODE_BTMODE(ECONV_DEFAULT_NEWLINE_DECORATOR
,
6335 0, ECONV_UNIVERSAL_NEWLINE_DECORATOR
) : 0;
6336 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
6337 ecflags
|= (fmode
& FMODE_WRITABLE
) ?
6338 MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
,
6339 0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
) : 0;
6341 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2
, ecflags
);
6343 if (fmode
& FMODE_BINMODE
) {
6348 rb_io_ext_int_to_encs(rb_ascii8bit_encoding(), NULL
, &enc
, &enc2
, fmode
);
6350 #if DEFAULT_TEXTMODE
6351 else if (NIL_P(vmode
)) {
6352 fmode
|= DEFAULT_TEXTMODE
;
6359 v
= rb_hash_aref(opthash
, sym_mode
);
6361 if (!NIL_P(vmode
)) {
6362 rb_raise(rb_eArgError
, "mode specified twice");
6369 v
= rb_hash_aref(opthash
, sym_flags
);
6372 oflags
|= NUM2INT(v
);
6373 vmode
= INT2NUM(oflags
);
6374 fmode
= rb_io_oflags_fmode(oflags
);
6376 extract_binmode(opthash
, &fmode
);
6377 if (fmode
& FMODE_BINMODE
) {
6382 rb_io_ext_int_to_encs(rb_ascii8bit_encoding(), NULL
, &enc
, &enc2
, fmode
);
6384 #if DEFAULT_TEXTMODE
6385 else if (NIL_P(vmode
)) {
6386 fmode
|= DEFAULT_TEXTMODE
;
6389 v
= rb_hash_aref(opthash
, sym_perm
);
6392 if (!NIL_P(*vperm_p
)) {
6393 rb_raise(rb_eArgError
, "perm specified twice");
6398 /* perm no use, just ignore */
6401 ecflags
= (fmode
& FMODE_READABLE
) ?
6402 MODE_BTMODE(ECONV_DEFAULT_NEWLINE_DECORATOR
,
6403 0, ECONV_UNIVERSAL_NEWLINE_DECORATOR
) : 0;
6404 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
6405 ecflags
|= (fmode
& FMODE_WRITABLE
) ?
6406 MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
,
6407 0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
) : 0;
6410 if (rb_io_extract_encoding_option(opthash
, &enc
, &enc2
, &fmode
)) {
6412 rb_raise(rb_eArgError
, "encoding specified twice");
6415 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2
, ecflags
);
6416 ecflags
= rb_econv_prepare_options(opthash
, &ecopts
, ecflags
);
6419 validate_enc_binmode(&fmode
, ecflags
, enc
, enc2
);
6425 convconfig_p
->enc
= enc
;
6426 convconfig_p
->enc2
= enc2
;
6427 convconfig_p
->ecflags
= ecflags
;
6428 convconfig_p
->ecopts
= ecopts
;
6431 struct sysopen_struct
{
6438 sysopen_func(void *ptr
)
6440 const struct sysopen_struct
*data
= ptr
;
6441 const char *fname
= RSTRING_PTR(data
->fname
);
6442 return (void *)(VALUE
)rb_cloexec_open(fname
, data
->oflags
, data
->perm
);
6446 rb_sysopen_internal(struct sysopen_struct
*data
)
6449 fd
= (int)(VALUE
)rb_thread_call_without_gvl(sysopen_func
, data
, RUBY_UBF_IO
, 0);
6451 rb_update_max_fd(fd
);
6456 rb_sysopen(VALUE fname
, int oflags
, mode_t perm
)
6459 struct sysopen_struct data
;
6461 data
.fname
= rb_str_encode_ospath(fname
);
6462 StringValueCStr(data
.fname
);
6463 data
.oflags
= oflags
;
6466 fd
= rb_sysopen_internal(&data
);
6469 if (rb_gc_for_fd(e
)) {
6470 fd
= rb_sysopen_internal(&data
);
6473 rb_syserr_fail_path(e
, fname
);
6480 rb_fdopen(int fd
, const char *modestr
)
6487 file
= fdopen(fd
, modestr
);
6494 file
= fdopen(fd
, modestr
);
6498 if (rb_gc_for_fd(e
)) {
6499 file
= fdopen(fd
, modestr
);
6503 if (e
== 0) e
= EINVAL
;
6504 #elif defined(__sun)
6505 if (e
== 0) e
= EMFILE
;
6507 rb_syserr_fail(e
, 0);
6511 /* xxx: should be _IONBF? A buffer in FILE may have trouble. */
6513 if (setvbuf(file
, NULL
, _IOFBF
, 0) != 0)
6514 rb_warn("setvbuf() can't be honoured (fd=%d)", fd
);
6520 io_check_tty(rb_io_t
*fptr
)
6522 int t
= isatty(fptr
->fd
);
6524 fptr
->mode
|= FMODE_TTY
|FMODE_DUPLEX
;
6528 static VALUE
rb_io_internal_encoding(VALUE
);
6529 static void io_encoding_set(rb_io_t
*, VALUE
, VALUE
, VALUE
);
6532 io_strip_bom(VALUE io
)
6534 VALUE b1
, b2
, b3
, b4
;
6537 GetOpenFile(io
, fptr
);
6538 if (!(fptr
->mode
& FMODE_READABLE
)) return 0;
6539 if (NIL_P(b1
= rb_io_getbyte(io
))) return 0;
6542 if (NIL_P(b2
= rb_io_getbyte(io
))) break;
6543 if (b2
== INT2FIX(0xBB) && !NIL_P(b3
= rb_io_getbyte(io
))) {
6544 if (b3
== INT2FIX(0xBF)) {
6545 return rb_utf8_encindex();
6547 rb_io_ungetbyte(io
, b3
);
6549 rb_io_ungetbyte(io
, b2
);
6553 if (NIL_P(b2
= rb_io_getbyte(io
))) break;
6554 if (b2
== INT2FIX(0xFF)) {
6555 return ENCINDEX_UTF_16BE
;
6557 rb_io_ungetbyte(io
, b2
);
6561 if (NIL_P(b2
= rb_io_getbyte(io
))) break;
6562 if (b2
== INT2FIX(0xFE)) {
6563 b3
= rb_io_getbyte(io
);
6564 if (b3
== INT2FIX(0) && !NIL_P(b4
= rb_io_getbyte(io
))) {
6565 if (b4
== INT2FIX(0)) {
6566 return ENCINDEX_UTF_32LE
;
6568 rb_io_ungetbyte(io
, b4
);
6570 rb_io_ungetbyte(io
, b3
);
6571 return ENCINDEX_UTF_16LE
;
6573 rb_io_ungetbyte(io
, b2
);
6577 if (NIL_P(b2
= rb_io_getbyte(io
))) break;
6578 if (b2
== INT2FIX(0) && !NIL_P(b3
= rb_io_getbyte(io
))) {
6579 if (b3
== INT2FIX(0xFE) && !NIL_P(b4
= rb_io_getbyte(io
))) {
6580 if (b4
== INT2FIX(0xFF)) {
6581 return ENCINDEX_UTF_32BE
;
6583 rb_io_ungetbyte(io
, b4
);
6585 rb_io_ungetbyte(io
, b3
);
6587 rb_io_ungetbyte(io
, b2
);
6590 rb_io_ungetbyte(io
, b1
);
6594 static rb_encoding
*
6595 io_set_encoding_by_bom(VALUE io
)
6597 int idx
= io_strip_bom(io
);
6599 rb_encoding
*extenc
= NULL
;
6601 GetOpenFile(io
, fptr
);
6603 extenc
= rb_enc_from_index(idx
);
6604 io_encoding_set(fptr
, rb_enc_from_encoding(extenc
),
6605 rb_io_internal_encoding(io
), Qnil
);
6608 fptr
->encs
.enc2
= NULL
;
6614 rb_file_open_generic(VALUE io
, VALUE filename
, int oflags
, int fmode
,
6615 const convconfig_t
*convconfig
, mode_t perm
)
6621 /* Set to default encodings */
6622 rb_io_ext_int_to_encs(NULL
, NULL
, &cc
.enc
, &cc
.enc2
, fmode
);
6627 validate_enc_binmode(&fmode
, convconfig
->ecflags
,
6628 convconfig
->enc
, convconfig
->enc2
);
6630 MakeOpenFile(io
, fptr
);
6632 fptr
->encs
= *convconfig
;
6633 pathv
= rb_str_new_frozen(filename
);
6635 if (!(oflags
& O_TMPFILE
)) {
6636 fptr
->pathv
= pathv
;
6639 fptr
->pathv
= pathv
;
6641 fptr
->fd
= rb_sysopen(pathv
, oflags
, perm
);
6643 if (fmode
& FMODE_SETENC_BY_BOM
) io_set_encoding_by_bom(io
);
6649 rb_file_open_internal(VALUE io
, VALUE filename
, const char *modestr
)
6651 int fmode
= rb_io_modestr_fmode(modestr
);
6652 const char *p
= strchr(modestr
, ':');
6653 convconfig_t convconfig
;
6656 parse_mode_enc(p
+1, rb_usascii_encoding(),
6657 &convconfig
.enc
, &convconfig
.enc2
, &fmode
);
6658 convconfig
.ecflags
= 0;
6659 convconfig
.ecopts
= Qnil
;
6663 /* Set to default encodings */
6665 e
= (fmode
& FMODE_BINMODE
) ? rb_ascii8bit_encoding() : NULL
;
6666 rb_io_ext_int_to_encs(e
, NULL
, &convconfig
.enc
, &convconfig
.enc2
, fmode
);
6667 convconfig
.ecflags
= 0;
6668 convconfig
.ecopts
= Qnil
;
6671 return rb_file_open_generic(io
, filename
,
6672 rb_io_fmode_oflags(fmode
),
6679 rb_file_open_str(VALUE fname
, const char *modestr
)
6681 FilePathValue(fname
);
6682 return rb_file_open_internal(io_alloc(rb_cFile
), fname
, modestr
);
6686 rb_file_open(const char *fname
, const char *modestr
)
6688 return rb_file_open_internal(io_alloc(rb_cFile
), rb_str_new_cstr(fname
), modestr
);
6691 #if defined(__CYGWIN__) || !defined(HAVE_WORKING_FORK)
6692 static struct pipe_list
{
6694 struct pipe_list
*next
;
6698 pipe_add_fptr(rb_io_t
*fptr
)
6700 struct pipe_list
*list
;
6702 list
= ALLOC(struct pipe_list
);
6704 list
->next
= pipe_list
;
6709 pipe_del_fptr(rb_io_t
*fptr
)
6711 struct pipe_list
**prev
= &pipe_list
;
6712 struct pipe_list
*tmp
;
6714 while ((tmp
= *prev
) != 0) {
6715 if (tmp
->fptr
== fptr
) {
6724 #if defined (_WIN32) || defined(__CYGWIN__)
6728 struct pipe_list
*list
= pipe_list
;
6729 struct pipe_list
*tmp
;
6733 rb_io_fptr_finalize(list
->fptr
);
6740 pipe_finalize(rb_io_t
*fptr
, int noraise
)
6742 #if !defined(HAVE_WORKING_FORK) && !defined(_WIN32)
6744 if (fptr
->stdio_file
) {
6745 status
= pclose(fptr
->stdio_file
);
6748 fptr
->stdio_file
= 0;
6749 rb_last_status_set(status
, fptr
->pid
);
6751 fptr_finalize(fptr
, noraise
);
6753 pipe_del_fptr(fptr
);
6758 fptr_copy_finalizer(rb_io_t
*fptr
, const rb_io_t
*orig
)
6760 #if defined(__CYGWIN__) || !defined(HAVE_WORKING_FORK)
6761 void (*const old_finalize
)(struct rb_io_t
*,int) = fptr
->finalize
;
6763 if (old_finalize
== orig
->finalize
) return;
6766 fptr
->finalize
= orig
->finalize
;
6768 #if defined(__CYGWIN__) || !defined(HAVE_WORKING_FORK)
6769 if (old_finalize
!= pipe_finalize
) {
6770 struct pipe_list
*list
;
6771 for (list
= pipe_list
; list
; list
= list
->next
) {
6772 if (list
->fptr
== fptr
) break;
6774 if (!list
) pipe_add_fptr(fptr
);
6777 pipe_del_fptr(fptr
);
6783 rb_io_synchronized(rb_io_t
*fptr
)
6785 rb_io_check_initialized(fptr
);
6786 fptr
->mode
|= FMODE_SYNC
;
6790 rb_io_unbuffered(rb_io_t
*fptr
)
6792 rb_io_synchronized(fptr
);
6799 ret
= rb_cloexec_pipe(pipes
);
6801 if (rb_gc_for_fd(errno
)) {
6802 ret
= rb_cloexec_pipe(pipes
);
6806 rb_update_max_fd(pipes
[0]);
6807 rb_update_max_fd(pipes
[1]);
6813 #define HAVE_SPAWNV 1
6814 #define spawnv(mode, cmd, args) rb_w32_uaspawn((mode), (cmd), (args))
6815 #define spawn(mode, cmd) rb_w32_uspawn((mode), (cmd), 0)
6818 #if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
6821 struct rb_execarg
*eargp
;
6828 #ifdef HAVE_WORKING_FORK
6829 # ifndef __EMSCRIPTEN__
6831 popen_redirect(struct popen_arg
*p
)
6833 if ((p
->modef
& FMODE_READABLE
) && (p
->modef
& FMODE_WRITABLE
)) {
6834 close(p
->write_pair
[1]);
6835 if (p
->write_pair
[0] != 0) {
6836 dup2(p
->write_pair
[0], 0);
6837 close(p
->write_pair
[0]);
6840 if (p
->pair
[1] != 1) {
6841 dup2(p
->pair
[1], 1);
6845 else if (p
->modef
& FMODE_READABLE
) {
6847 if (p
->pair
[1] != 1) {
6848 dup2(p
->pair
[1], 1);
6854 if (p
->pair
[0] != 0) {
6855 dup2(p
->pair
[0], 0);
6862 #if defined(__linux__)
6863 /* Linux /proc/self/status contains a line: "FDSize:\t<nnn>\n"
6864 * Since /proc may not be available, linux_get_maxfd is just a hint.
6865 * This function, linux_get_maxfd, must be async-signal-safe.
6866 * I.e. opendir() is not usable.
6868 * Note that memchr() and memcmp is *not* async-signal-safe in POSIX.
6869 * However they are easy to re-implement in async-signal-safe manner.
6870 * (Also note that there is missing/memcmp.c.)
6873 linux_get_maxfd(void)
6876 char buf
[4096], *p
, *np
, *e
;
6878 fd
= rb_cloexec_open("/proc/self/status", O_RDONLY
|O_NOCTTY
, 0);
6879 if (fd
< 0) return fd
;
6880 ss
= read(fd
, buf
, sizeof(buf
));
6881 if (ss
< 0) goto err
;
6884 while ((int)sizeof("FDSize:\t0\n")-1 <= e
-p
&&
6885 (np
= memchr(p
, '\n', e
-p
)) != NULL
) {
6886 if (memcmp(p
, "FDSize:", sizeof("FDSize:")-1) == 0) {
6888 p
+= sizeof("FDSize:")-1;
6890 fdsize
= (int)ruby_strtoul(p
, (char **)NULL
, 10);
6904 /* This function should be async-signal-safe. */
6906 rb_close_before_exec(int lowfd
, int maxhint
, VALUE noclose_fds
)
6908 #if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
6910 int max
= (int)max_file_descriptor
;
6912 /* F_MAXFD is available since NetBSD 2.0. */
6913 ret
= fcntl(0, F_MAXFD
); /* async-signal-safe */
6915 maxhint
= max
= ret
;
6916 # elif defined(__linux__)
6917 ret
= linux_get_maxfd();
6920 /* maxhint = max = ret; if (ret == -1) abort(); // test */
6924 for (fd
= lowfd
; fd
<= max
; fd
++) {
6925 if (!NIL_P(noclose_fds
) &&
6926 RTEST(rb_hash_lookup(noclose_fds
, INT2FIX(fd
)))) /* async-signal-safe */
6928 ret
= fcntl(fd
, F_GETFD
); /* async-signal-safe */
6929 if (ret
!= -1 && !(ret
& FD_CLOEXEC
)) {
6930 fcntl(fd
, F_SETFD
, ret
|FD_CLOEXEC
); /* async-signal-safe */
6932 # define CONTIGUOUS_CLOSED_FDS 20
6934 if (max
< fd
+ CONTIGUOUS_CLOSED_FDS
)
6935 max
= fd
+ CONTIGUOUS_CLOSED_FDS
;
6941 # ifndef __EMSCRIPTEN__
6943 popen_exec(void *pp
, char *errmsg
, size_t errmsg_len
)
6945 struct popen_arg
*p
= (struct popen_arg
*)pp
;
6947 return rb_exec_async_signal_safe(p
->eargp
, errmsg
, errmsg_len
);
6952 #if (defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)) && !defined __EMSCRIPTEN__
6954 rb_execarg_fixup_v(VALUE execarg_obj
)
6956 rb_execarg_parent_start(execarg_obj
);
6960 char *rb_execarg_commandline(const struct rb_execarg
*eargp
, VALUE
*prog
);
6963 #ifndef __EMSCRIPTEN__
6965 pipe_open(VALUE execarg_obj
, const char *modestr
, int fmode
,
6966 const convconfig_t
*convconfig
)
6968 struct rb_execarg
*eargp
= NIL_P(execarg_obj
) ? NULL
: rb_execarg_get(execarg_obj
);
6969 VALUE prog
= eargp
? (eargp
->use_shell
? eargp
->invoke
.sh
.shell_script
: eargp
->invoke
.cmd
.command_name
) : Qfalse
;
6973 rb_io_t
*write_fptr
;
6975 #if defined(HAVE_WORKING_FORK)
6977 char errmsg
[80] = { '\0' };
6979 #if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
6981 struct popen_arg arg
;
6984 #if defined(HAVE_SPAWNV)
6985 # if defined(HAVE_SPAWNVE)
6986 # define DO_SPAWN(cmd, args, envp) ((args) ? \
6987 spawnve(P_NOWAIT, (cmd), (args), (envp)) : \
6988 spawne(P_NOWAIT, (cmd), (envp)))
6990 # define DO_SPAWN(cmd, args, envp) ((args) ? \
6991 spawnv(P_NOWAIT, (cmd), (args)) : \
6992 spawn(P_NOWAIT, (cmd)))
6994 # if !defined(HAVE_WORKING_FORK)
6996 # if defined(HAVE_SPAWNVE)
7001 #if !defined(HAVE_WORKING_FORK)
7002 struct rb_execarg sarg
, *sargp
= &sarg
;
7007 #if !defined(HAVE_WORKING_FORK)
7008 const char *cmd
= 0;
7011 cmd
= StringValueCStr(prog
);
7014 #if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
7015 arg
.execarg_obj
= execarg_obj
;
7018 arg
.pair
[0] = arg
.pair
[1] = -1;
7019 arg
.write_pair
[0] = arg
.write_pair
[1] = -1;
7020 # if !defined(HAVE_WORKING_FORK)
7021 if (eargp
&& !eargp
->use_shell
) {
7022 args
= ARGVSTR2ARGV(eargp
->invoke
.cmd
.argv_str
);
7025 switch (fmode
& (FMODE_READABLE
|FMODE_WRITABLE
)) {
7026 case FMODE_READABLE
|FMODE_WRITABLE
:
7027 if (rb_pipe(arg
.write_pair
) < 0)
7028 rb_sys_fail_str(prog
);
7029 if (rb_pipe(arg
.pair
) < 0) {
7031 close(arg
.write_pair
[0]);
7032 close(arg
.write_pair
[1]);
7033 rb_syserr_fail_str(e
, prog
);
7036 rb_execarg_addopt(execarg_obj
, INT2FIX(0), INT2FIX(arg
.write_pair
[0]));
7037 rb_execarg_addopt(execarg_obj
, INT2FIX(1), INT2FIX(arg
.pair
[1]));
7040 case FMODE_READABLE
:
7041 if (rb_pipe(arg
.pair
) < 0)
7042 rb_sys_fail_str(prog
);
7044 rb_execarg_addopt(execarg_obj
, INT2FIX(1), INT2FIX(arg
.pair
[1]));
7046 case FMODE_WRITABLE
:
7047 if (rb_pipe(arg
.pair
) < 0)
7048 rb_sys_fail_str(prog
);
7050 rb_execarg_addopt(execarg_obj
, INT2FIX(0), INT2FIX(arg
.pair
[0]));
7053 rb_sys_fail_str(prog
);
7055 if (!NIL_P(execarg_obj
)) {
7056 rb_protect(rb_execarg_fixup_v
, execarg_obj
, &state
);
7058 if (0 <= arg
.write_pair
[0]) close(arg
.write_pair
[0]);
7059 if (0 <= arg
.write_pair
[1]) close(arg
.write_pair
[1]);
7060 if (0 <= arg
.pair
[0]) close(arg
.pair
[0]);
7061 if (0 <= arg
.pair
[1]) close(arg
.pair
[1]);
7062 rb_execarg_parent_end(execarg_obj
);
7066 # if defined(HAVE_WORKING_FORK)
7067 pid
= rb_fork_async_signal_safe(&status
, popen_exec
, &arg
, arg
.eargp
->redirect_fds
, errmsg
, sizeof(errmsg
));
7069 rb_execarg_run_options(eargp
, sargp
, NULL
, 0);
7070 # if defined(HAVE_SPAWNVE)
7071 if (eargp
->envp_str
) envp
= (char **)RSTRING_PTR(eargp
->envp_str
);
7073 while ((pid
= DO_SPAWN(cmd
, args
, envp
)) < 0) {
7075 switch (e
= errno
) {
7077 # if EWOULDBLOCK != EAGAIN
7086 rb_execarg_run_options(sargp
, NULL
, NULL
, 0);
7088 rb_execarg_parent_end(execarg_obj
);
7091 # if defined(HAVE_WORKING_FORK)
7092 pid
= rb_call_proc__fork();
7093 if (pid
== 0) { /* child */
7094 popen_redirect(&arg
);
7095 rb_io_synchronized(RFILE(orig_stdout
)->fptr
);
7096 rb_io_synchronized(RFILE(orig_stderr
)->fptr
);
7106 # if defined(HAVE_WORKING_FORK)
7111 if ((fmode
& (FMODE_READABLE
|FMODE_WRITABLE
)) == (FMODE_READABLE
|FMODE_WRITABLE
)) {
7112 close(arg
.write_pair
[0]);
7113 close(arg
.write_pair
[1]);
7115 # if defined(HAVE_WORKING_FORK)
7117 rb_syserr_fail(e
, errmsg
);
7119 rb_syserr_fail_str(e
, prog
);
7121 if ((fmode
& FMODE_READABLE
) && (fmode
& FMODE_WRITABLE
)) {
7124 close(arg
.write_pair
[0]);
7125 write_fd
= arg
.write_pair
[1];
7127 else if (fmode
& FMODE_READABLE
) {
7136 cmd
= rb_execarg_commandline(eargp
, &prog
);
7137 if (!NIL_P(execarg_obj
)) {
7138 rb_execarg_parent_start(execarg_obj
);
7139 rb_execarg_run_options(eargp
, sargp
, NULL
, 0);
7141 fp
= popen(cmd
, modestr
);
7144 rb_execarg_parent_end(execarg_obj
);
7145 rb_execarg_run_options(sargp
, NULL
, NULL
, 0);
7147 if (!fp
) rb_syserr_fail_path(e
, prog
);
7151 port
= io_alloc(rb_cIO
);
7152 MakeOpenFile(port
, fptr
);
7154 fptr
->stdio_file
= fp
;
7155 fptr
->mode
= fmode
| FMODE_SYNC
|FMODE_DUPLEX
;
7157 fptr
->encs
= *convconfig
;
7158 #if RUBY_CRLF_ENVIRONMENT
7159 if (fptr
->encs
.ecflags
& ECONV_DEFAULT_NEWLINE_DECORATOR
) {
7160 fptr
->encs
.ecflags
|= ECONV_UNIVERSAL_NEWLINE_DECORATOR
;
7165 if (NEED_NEWLINE_DECORATOR_ON_READ(fptr
)) {
7166 fptr
->encs
.ecflags
|= ECONV_UNIVERSAL_NEWLINE_DECORATOR
;
7168 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
7169 if (NEED_NEWLINE_DECORATOR_ON_WRITE(fptr
)) {
7170 fptr
->encs
.ecflags
|= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
;
7176 if (0 <= write_fd
) {
7177 write_port
= io_alloc(rb_cIO
);
7178 MakeOpenFile(write_port
, write_fptr
);
7179 write_fptr
->fd
= write_fd
;
7180 write_fptr
->mode
= (fmode
& ~FMODE_READABLE
)| FMODE_SYNC
|FMODE_DUPLEX
;
7181 fptr
->mode
&= ~FMODE_WRITABLE
;
7182 fptr
->tied_io_for_writing
= write_port
;
7183 rb_ivar_set(port
, rb_intern("@tied_io_for_writing"), write_port
);
7186 #if defined (__CYGWIN__) || !defined(HAVE_WORKING_FORK)
7187 fptr
->finalize
= pipe_finalize
;
7188 pipe_add_fptr(fptr
);
7194 pipe_open(VALUE execarg_obj
, const char *modestr
, int fmode
,
7195 const convconfig_t
*convconfig
)
7197 rb_raise(rb_eNotImpError
, "popen() is not available");
7202 is_popen_fork(VALUE prog
)
7204 if (RSTRING_LEN(prog
) == 1 && RSTRING_PTR(prog
)[0] == '-') {
7205 #if !defined(HAVE_WORKING_FORK)
7206 rb_raise(rb_eNotImpError
,
7207 "fork() function is unimplemented on this machine");
7216 pipe_open_s(VALUE prog
, const char *modestr
, int fmode
,
7217 const convconfig_t
*convconfig
)
7220 VALUE
*argv
= &prog
;
7221 VALUE execarg_obj
= Qnil
;
7223 if (!is_popen_fork(prog
))
7224 execarg_obj
= rb_execarg_new(argc
, argv
, TRUE
, FALSE
);
7225 return pipe_open(execarg_obj
, modestr
, fmode
, convconfig
);
7229 pipe_close(VALUE io
)
7231 rb_io_t
*fptr
= io_close_fptr(io
);
7233 fptr_waitpid(fptr
, rb_thread_to_be_killed(rb_thread_current()));
7238 static VALUE
popen_finish(VALUE port
, VALUE klass
);
7242 * IO.popen([env,] cmd, mode="r" [, opt]) -> io
7243 * IO.popen([env,] cmd, mode="r" [, opt]) {|io| block } -> obj
7245 * Runs the specified command as a subprocess; the subprocess's
7246 * standard input and output will be connected to the returned
7249 * The PID of the started process can be obtained by IO#pid method.
7251 * _cmd_ is a string or an array as follows.
7255 * commandline : command line string which is passed to a shell
7256 * [env, cmdname, arg1, ..., opts] : command name and zero or more arguments (no shell)
7257 * [env, [cmdname, argv0], arg1, ..., opts] : command name, argv[0] and zero or more arguments (no shell)
7258 * (env and opts are optional.)
7260 * If _cmd_ is a +String+ ``<code>-</code>'',
7261 * then a new instance of Ruby is started as the subprocess.
7263 * If <i>cmd</i> is an +Array+ of +String+,
7264 * then it will be used as the subprocess's +argv+ bypassing a shell.
7265 * The array can contain a hash at first for environments and
7266 * a hash at last for options similar to #spawn.
7268 * The default mode for the new file object is ``r'',
7269 * but <i>mode</i> may be set to any of the modes listed in the description for class IO.
7270 * The last argument <i>opt</i> qualifies <i>mode</i>.
7273 * IO.popen("nkf -e filename", :external_encoding=>"EUC-JP") {|nkf_io|
7274 * euc_jp_string = nkf_io.read
7277 * # merge standard output and standard error using
7278 * # spawn option. See the document of Kernel.spawn.
7279 * IO.popen(["ls", "/", :err=>[:child, :out]]) {|ls_io|
7280 * ls_result_with_error = ls_io.read
7283 * # spawn options can be mixed with IO options
7284 * IO.popen(["ls", "/"], :err=>[:child, :out]) {|ls_io|
7285 * ls_result_with_error = ls_io.read
7288 * Raises exceptions which IO.pipe and Kernel.spawn raise.
7290 * If a block is given, Ruby will run the command as a child connected
7291 * to Ruby with a pipe. Ruby's end of the pipe will be passed as a
7292 * parameter to the block.
7293 * At the end of block, Ruby closes the pipe and sets <code>$?</code>.
7294 * In this case IO.popen returns the value of the block.
7296 * If a block is given with a _cmd_ of ``<code>-</code>'',
7297 * the block will be run in two separate processes: once in the parent,
7298 * and once in a child. The parent process will be passed the pipe
7299 * object as a parameter to the block, the child version of the block
7300 * will be passed +nil+, and the child's standard in and
7301 * standard out will be connected to the parent through the pipe. Not
7302 * available on all platforms.
7304 * f = IO.popen("uname")
7307 * puts "Parent is #{Process.pid}"
7308 * IO.popen("date") {|f| puts f.gets }
7309 * IO.popen("-") {|f| $stderr.puts "#{Process.pid} is here, f is #{f.inspect}"}
7311 * IO.popen(%w"sed -e s|^|<foo>| -e s&$&;zot;&", "r+") {|f|
7312 * f.puts "bar"; f.close_write; puts f.gets
7315 * <em>produces:</em>
7319 * Thu Jan 15 22:41:19 JST 2009
7320 * 21346 is here, f is #<IO:fd 3>
7321 * 21352 is here, f is nil
7322 * #<Process::Status: pid 21352 exit 0>
7327 rb_io_s_popen(int argc
, VALUE
*argv
, VALUE klass
)
7329 VALUE pname
, pmode
= Qnil
, opt
= Qnil
, env
= Qnil
;
7331 if (argc
> 1 && !NIL_P(opt
= rb_check_hash_type(argv
[argc
-1]))) --argc
;
7332 if (argc
> 1 && !NIL_P(env
= rb_check_hash_type(argv
[0]))) --argc
, ++argv
;
7341 int ex
= !NIL_P(opt
);
7342 rb_error_arity(argc
+ ex
, 1 + ex
, 2 + ex
);
7345 return popen_finish(rb_io_popen(pname
, pmode
, env
, opt
), klass
);
7349 rb_io_popen(VALUE pname
, VALUE pmode
, VALUE env
, VALUE opt
)
7351 const char *modestr
;
7352 VALUE tmp
, execarg_obj
= Qnil
;
7354 convconfig_t convconfig
;
7356 tmp
= rb_check_array_type(pname
);
7358 long len
= RARRAY_LEN(tmp
);
7359 #if SIZEOF_LONG > SIZEOF_INT
7360 if (len
> INT_MAX
) {
7361 rb_raise(rb_eArgError
, "too many arguments");
7364 execarg_obj
= rb_execarg_new((int)len
, RARRAY_CONST_PTR(tmp
), FALSE
, FALSE
);
7368 SafeStringValue(pname
);
7370 if (!is_popen_fork(pname
))
7371 execarg_obj
= rb_execarg_new(1, &pname
, TRUE
, FALSE
);
7373 if (!NIL_P(execarg_obj
)) {
7375 opt
= rb_execarg_extract_options(execarg_obj
, opt
);
7377 rb_execarg_setenv(execarg_obj
, env
);
7379 rb_io_extract_modeenc(&pmode
, 0, opt
, &oflags
, &fmode
, &convconfig
);
7380 modestr
= rb_io_oflags_modestr(oflags
);
7382 return pipe_open(execarg_obj
, modestr
, fmode
, &convconfig
);
7386 popen_finish(VALUE port
, VALUE klass
)
7390 if (rb_block_given_p()) {
7392 rb_io_flush(rb_ractor_stdout());
7393 rb_io_flush(rb_ractor_stderr());
7398 RBASIC_SET_CLASS(port
, klass
);
7399 if (rb_block_given_p()) {
7400 return rb_ensure(rb_yield
, port
, pipe_close
, port
);
7406 rb_scan_open_args(int argc
, const VALUE
*argv
,
7407 VALUE
*fname_p
, int *oflags_p
, int *fmode_p
,
7408 convconfig_t
*convconfig_p
, mode_t
*perm_p
)
7410 VALUE opt
, fname
, vmode
, vperm
;
7414 argc
= rb_scan_args(argc
, argv
, "12:", &fname
, &vmode
, &vperm
, &opt
);
7415 FilePathValue(fname
);
7417 rb_io_extract_modeenc(&vmode
, &vperm
, opt
, &oflags
, &fmode
, convconfig_p
);
7419 perm
= NIL_P(vperm
) ? 0666 : NUM2MODET(vperm
);
7428 rb_open_file(int argc
, const VALUE
*argv
, VALUE io
)
7432 convconfig_t convconfig
;
7435 rb_scan_open_args(argc
, argv
, &fname
, &oflags
, &fmode
, &convconfig
, &perm
);
7436 rb_file_open_generic(io
, fname
, oflags
, fmode
, &convconfig
, perm
);
7443 * Document-method: File::open
7446 * File.open(filename, mode="r" [, opt]) -> file
7447 * File.open(filename [, mode [, perm]] [, opt]) -> file
7448 * File.open(filename, mode="r" [, opt]) {|file| block } -> obj
7449 * File.open(filename [, mode [, perm]] [, opt]) {|file| block } -> obj
7451 * With no associated block, File.open is a synonym for
7452 * File.new. If the optional code block is given, it will
7453 * be passed the opened +file+ as an argument and the File object will
7454 * automatically be closed when the block terminates. The value of the block
7455 * will be returned from File.open.
7457 * If a file is being created, its initial permissions may be set using the
7458 * +perm+ parameter. See File.new for further discussion.
7460 * See IO.new for a description of the +mode+ and +opt+ parameters.
7464 * Document-method: IO::open
7467 * IO.open(fd, mode="r" [, opt]) -> io
7468 * IO.open(fd, mode="r" [, opt]) {|io| block } -> obj
7470 * With no associated block, IO.open is a synonym for IO.new. If
7471 * the optional code block is given, it will be passed +io+ as an argument,
7472 * and the IO object will automatically be closed when the block terminates.
7473 * In this instance, IO.open returns the value of the block.
7475 * See IO.new for a description of the +fd+, +mode+ and +opt+ parameters.
7479 rb_io_s_open(int argc
, VALUE
*argv
, VALUE klass
)
7481 VALUE io
= rb_class_new_instance_kw(argc
, argv
, klass
, RB_PASS_CALLED_KEYWORDS
);
7483 if (rb_block_given_p()) {
7484 return rb_ensure(rb_yield
, io
, io_close
, io
);
7492 * IO.sysopen(path, [mode, [perm]]) -> integer
7494 * Opens the given path, returning the underlying file descriptor as a
7497 * IO.sysopen("testfile") #=> 3
7501 rb_io_s_sysopen(int argc
, VALUE
*argv
, VALUE _
)
7503 VALUE fname
, vmode
, vperm
;
7508 rb_scan_args(argc
, argv
, "12", &fname
, &vmode
, &vperm
);
7509 FilePathValue(fname
);
7513 else if (!NIL_P(intmode
= rb_check_to_integer(vmode
, "to_int")))
7514 oflags
= NUM2INT(intmode
);
7516 SafeStringValue(vmode
);
7517 oflags
= rb_io_modestr_oflags(StringValueCStr(vmode
));
7519 if (NIL_P(vperm
)) perm
= 0666;
7520 else perm
= NUM2MODET(vperm
);
7522 RB_GC_GUARD(fname
) = rb_str_new4(fname
);
7523 fd
= rb_sysopen(fname
, oflags
, perm
);
7528 check_pipe_command(VALUE filename_or_command
)
7530 char *s
= RSTRING_PTR(filename_or_command
);
7531 long l
= RSTRING_LEN(filename_or_command
);
7535 if (rb_enc_ascget(s
, e
, &chlen
, rb_enc_get(filename_or_command
)) == '|') {
7536 VALUE cmd
= rb_str_new(s
+chlen
, l
-chlen
);
7544 * open(path [, mode [, perm]] [, opt]) -> io or nil
7545 * open(path [, mode [, perm]] [, opt]) {|io| block } -> obj
7547 * Creates an IO object connected to the given stream, file, or subprocess.
7549 * If +path+ does not start with a pipe character (<code>|</code>), treat it
7550 * as the name of a file to open using the specified mode (defaulting to
7553 * The +mode+ is either a string or an integer. If it is an integer, it
7554 * must be bitwise-or of open(2) flags, such as File::RDWR or File::EXCL. If
7555 * it is a string, it is either "fmode", "fmode:ext_enc", or
7556 * "fmode:ext_enc:int_enc".
7558 * See the documentation of IO.new for full documentation of the +mode+ string
7561 * If a file is being created, its initial permissions may be set using the
7562 * +perm+ parameter. See File.new and the open(2) and chmod(2) man pages for
7563 * a description of permissions.
7565 * If a block is specified, it will be invoked with the IO object as a
7566 * parameter, and the IO will be automatically closed when the block
7567 * terminates. The call returns the value of the block.
7569 * If +path+ starts with a pipe character (<code>"|"</code>), a subprocess is
7570 * created, connected to the caller by a pair of pipes. The returned IO
7571 * object may be used to write to the standard input and read from the
7572 * standard output of this subprocess.
7574 * If the command following the pipe is a single minus sign
7575 * (<code>"|-"</code>), Ruby forks, and this subprocess is connected to the
7576 * parent. If the command is not <code>"-"</code>, the subprocess runs the
7577 * command. Note that the command may be processed by shell if it contains
7578 * shell metacharacters.
7580 * When the subprocess is Ruby (opened via <code>"|-"</code>), the +open+
7581 * call returns +nil+. If a block is associated with the open call, that
7582 * block will run twice --- once in the parent and once in the child.
7584 * The block parameter will be an IO object in the parent and +nil+ in the
7585 * child. The parent's +IO+ object will be connected to the child's $stdin
7586 * and $stdout. The subprocess will be terminated at the end of the block.
7590 * Reading from "testfile":
7592 * open("testfile") do |f|
7600 * Open a subprocess and read its output:
7602 * cmd = open("|date")
7608 * Wed Apr 9 08:56:31 CDT 2003
7610 * Open a subprocess running the same Ruby program:
7612 * f = open("|-", "w+")
7617 * puts "Got: #{f.gets}"
7624 * Open a subprocess using a block to receive the IO object:
7629 * puts "Got: #{f.gets}"
7642 rb_f_open(int argc
, VALUE
*argv
, VALUE _
)
7645 int redirect
= FALSE
;
7648 CONST_ID(to_open
, "to_open");
7649 if (rb_respond_to(argv
[0], to_open
)) {
7653 VALUE tmp
= argv
[0];
7659 VALUE cmd
= check_pipe_command(tmp
);
7662 return rb_io_s_popen(argc
, argv
, rb_cIO
);
7668 VALUE io
= rb_funcallv_kw(argv
[0], to_open
, argc
-1, argv
+1, RB_PASS_CALLED_KEYWORDS
);
7670 if (rb_block_given_p()) {
7671 return rb_ensure(rb_yield
, io
, io_close
, io
);
7675 return rb_io_s_open(argc
, argv
, rb_cFile
);
7678 static VALUE
rb_io_open_generic(VALUE
, VALUE
, int, int, const convconfig_t
*, mode_t
);
7681 rb_io_open(VALUE io
, VALUE filename
, VALUE vmode
, VALUE vperm
, VALUE opt
)
7684 convconfig_t convconfig
;
7687 rb_io_extract_modeenc(&vmode
, &vperm
, opt
, &oflags
, &fmode
, &convconfig
);
7688 perm
= NIL_P(vperm
) ? 0666 : NUM2MODET(vperm
);
7689 return rb_io_open_generic(io
, filename
, oflags
, fmode
, &convconfig
, perm
);
7693 rb_io_open_generic(VALUE klass
, VALUE filename
, int oflags
, int fmode
,
7694 const convconfig_t
*convconfig
, mode_t perm
)
7697 if (klass
== rb_cIO
&& !NIL_P(cmd
= check_pipe_command(filename
))) {
7698 return pipe_open_s(cmd
, rb_io_oflags_modestr(oflags
), fmode
, convconfig
);
7701 return rb_file_open_generic(io_alloc(klass
), filename
,
7702 oflags
, fmode
, convconfig
, perm
);
7707 io_reopen(VALUE io
, VALUE nfile
)
7709 rb_io_t
*fptr
, *orig
;
7713 nfile
= rb_io_get_io(nfile
);
7714 GetOpenFile(io
, fptr
);
7715 GetOpenFile(nfile
, orig
);
7717 if (fptr
== orig
) return io
;
7718 if (IS_PREP_STDIO(fptr
)) {
7719 if ((fptr
->stdio_file
== stdin
&& !(orig
->mode
& FMODE_READABLE
)) ||
7720 (fptr
->stdio_file
== stdout
&& !(orig
->mode
& FMODE_WRITABLE
)) ||
7721 (fptr
->stdio_file
== stderr
&& !(orig
->mode
& FMODE_WRITABLE
))) {
7722 rb_raise(rb_eArgError
,
7723 "%s can't change access mode from \"%s\" to \"%s\"",
7724 PREP_STDIO_NAME(fptr
), rb_io_fmode_modestr(fptr
->mode
),
7725 rb_io_fmode_modestr(orig
->mode
));
7728 if (fptr
->mode
& FMODE_WRITABLE
) {
7729 if (io_fflush(fptr
) < 0)
7730 rb_sys_fail_on_write(fptr
);
7733 flush_before_seek(fptr
);
7735 if (orig
->mode
& FMODE_READABLE
) {
7736 pos
= io_tell(orig
);
7738 if (orig
->mode
& FMODE_WRITABLE
) {
7739 if (io_fflush(orig
) < 0)
7740 rb_sys_fail_on_write(fptr
);
7743 /* copy rb_io_t structure */
7744 fptr
->mode
= orig
->mode
| (fptr
->mode
& FMODE_PREP
);
7745 fptr
->pid
= orig
->pid
;
7746 fptr
->lineno
= orig
->lineno
;
7747 if (RTEST(orig
->pathv
)) fptr
->pathv
= orig
->pathv
;
7748 else if (!IS_PREP_STDIO(fptr
)) fptr
->pathv
= Qnil
;
7749 fptr_copy_finalizer(fptr
, orig
);
7754 if (IS_PREP_STDIO(fptr
) || fd
<= 2 || !fptr
->stdio_file
) {
7755 /* need to keep FILE objects of stdin, stdout and stderr */
7756 if (rb_cloexec_dup2(fd2
, fd
) < 0)
7757 rb_sys_fail_path(orig
->pathv
);
7758 rb_update_max_fd(fd
);
7761 fclose(fptr
->stdio_file
);
7762 fptr
->stdio_file
= 0;
7764 if (rb_cloexec_dup2(fd2
, fd
) < 0)
7765 rb_sys_fail_path(orig
->pathv
);
7766 rb_update_max_fd(fd
);
7769 rb_thread_fd_close(fd
);
7770 if ((orig
->mode
& FMODE_READABLE
) && pos
>= 0) {
7771 if (io_seek(fptr
, pos
, SEEK_SET
) < 0 && errno
) {
7772 rb_sys_fail_path(fptr
->pathv
);
7774 if (io_seek(orig
, pos
, SEEK_SET
) < 0 && errno
) {
7775 rb_sys_fail_path(orig
->pathv
);
7780 if (fptr
->mode
& FMODE_BINMODE
) {
7784 RBASIC_SET_CLASS(io
, rb_obj_class(nfile
));
7789 int rb_freopen(VALUE fname
, const char *mode
, FILE *fp
);
7792 rb_freopen(VALUE fname
, const char *mode
, FILE *fp
)
7794 if (!freopen(RSTRING_PTR(fname
), mode
, fp
)) {
7804 * ios.reopen(other_IO) -> ios
7805 * ios.reopen(path, mode [, opt]) -> ios
7807 * Reassociates <em>ios</em> with the I/O stream given in
7808 * <i>other_IO</i> or to a new stream opened on <i>path</i>. This may
7809 * dynamically change the actual class of this stream.
7810 * The +mode+ and +opt+ parameters accept the same values as IO.open.
7812 * f1 = File.new("testfile")
7813 * f2 = File.new("testfile")
7814 * f2.readlines[0] #=> "This is line one\n"
7815 * f2.reopen(f1) #=> #<File:testfile>
7816 * f2.readlines[0] #=> "This is line one\n"
7820 rb_io_reopen(int argc
, VALUE
*argv
, VALUE file
)
7822 VALUE fname
, nmode
, opt
;
7826 if (rb_scan_args(argc
, argv
, "11:", &fname
, &nmode
, &opt
) == 1) {
7827 VALUE tmp
= rb_io_check_io(fname
);
7829 return io_reopen(file
, tmp
);
7833 FilePathValue(fname
);
7834 rb_io_taint_check(file
);
7835 fptr
= RFILE(file
)->fptr
;
7837 fptr
= RFILE(file
)->fptr
= ZALLOC(rb_io_t
);
7840 if (!NIL_P(nmode
) || !NIL_P(opt
)) {
7842 convconfig_t convconfig
;
7844 rb_io_extract_modeenc(&nmode
, 0, opt
, &oflags
, &fmode
, &convconfig
);
7845 if (IS_PREP_STDIO(fptr
) &&
7846 ((fptr
->mode
& FMODE_READWRITE
) & (fmode
& FMODE_READWRITE
)) !=
7847 (fptr
->mode
& FMODE_READWRITE
)) {
7848 rb_raise(rb_eArgError
,
7849 "%s can't change access mode from \"%s\" to \"%s\"",
7850 PREP_STDIO_NAME(fptr
), rb_io_fmode_modestr(fptr
->mode
),
7851 rb_io_fmode_modestr(fmode
));
7854 fptr
->encs
= convconfig
;
7857 oflags
= rb_io_fmode_oflags(fptr
->mode
);
7860 fptr
->pathv
= fname
;
7862 fptr
->fd
= rb_sysopen(fptr
->pathv
, oflags
, 0666);
7863 fptr
->stdio_file
= 0;
7867 if (fptr
->mode
& FMODE_WRITABLE
) {
7868 if (io_fflush(fptr
) < 0)
7869 rb_sys_fail_on_write(fptr
);
7871 fptr
->rbuf
.off
= fptr
->rbuf
.len
= 0;
7873 if (fptr
->stdio_file
) {
7874 int e
= rb_freopen(rb_str_encode_ospath(fptr
->pathv
),
7875 rb_io_oflags_modestr(oflags
),
7877 if (e
) rb_syserr_fail_path(e
, fptr
->pathv
);
7878 fptr
->fd
= fileno(fptr
->stdio_file
);
7879 rb_fd_fix_cloexec(fptr
->fd
);
7881 if (setvbuf(fptr
->stdio_file
, NULL
, _IOFBF
, 0) != 0)
7882 rb_warn("setvbuf() can't be honoured for %"PRIsVALUE
, fptr
->pathv
);
7884 if (fptr
->stdio_file
== stderr
) {
7885 if (setvbuf(fptr
->stdio_file
, NULL
, _IONBF
, BUFSIZ
) != 0)
7886 rb_warn("setvbuf() can't be honoured for %"PRIsVALUE
, fptr
->pathv
);
7888 else if (fptr
->stdio_file
== stdout
&& isatty(fptr
->fd
)) {
7889 if (setvbuf(fptr
->stdio_file
, NULL
, _IOLBF
, BUFSIZ
) != 0)
7890 rb_warn("setvbuf() can't be honoured for %"PRIsVALUE
, fptr
->pathv
);
7894 int tmpfd
= rb_sysopen(fptr
->pathv
, oflags
, 0666);
7896 if (rb_cloexec_dup2(tmpfd
, fptr
->fd
) < 0)
7900 rb_syserr_fail_path(err
, fptr
->pathv
);
7909 rb_io_init_copy(VALUE dest
, VALUE io
)
7911 rb_io_t
*fptr
, *orig
;
7916 io
= rb_io_get_io(io
);
7917 if (!OBJ_INIT_COPY(dest
, io
)) return dest
;
7918 GetOpenFile(io
, orig
);
7919 MakeOpenFile(dest
, fptr
);
7923 /* copy rb_io_t structure */
7924 fptr
->mode
= orig
->mode
& ~FMODE_PREP
;
7925 fptr
->encs
= orig
->encs
;
7926 fptr
->pid
= orig
->pid
;
7927 fptr
->lineno
= orig
->lineno
;
7928 if (!NIL_P(orig
->pathv
)) fptr
->pathv
= orig
->pathv
;
7929 fptr_copy_finalizer(fptr
, orig
);
7931 fd
= ruby_dup(orig
->fd
);
7933 pos
= io_tell(orig
);
7935 io_seek(fptr
, pos
, SEEK_SET
);
7936 if (fptr
->mode
& FMODE_BINMODE
) {
7937 rb_io_binmode(dest
);
7940 write_io
= GetWriteIO(io
);
7941 if (io
!= write_io
) {
7942 write_io
= rb_obj_dup(write_io
);
7943 fptr
->tied_io_for_writing
= write_io
;
7944 rb_ivar_set(dest
, rb_intern("@tied_io_for_writing"), write_io
);
7952 * ios.printf(format_string [, obj, ...]) -> nil
7954 * Formats and writes to <em>ios</em>, converting parameters under
7955 * control of the format string. See Kernel#sprintf for details.
7959 rb_io_printf(int argc
, const VALUE
*argv
, VALUE out
)
7961 rb_io_write(out
, rb_f_sprintf(argc
, argv
));
7967 * printf(io, string [, obj ... ]) -> nil
7968 * printf(string [, obj ... ]) -> nil
7971 * io.write(sprintf(string, obj, ...))
7973 * $stdout.write(sprintf(string, obj, ...))
7977 rb_f_printf(int argc
, VALUE
*argv
, VALUE _
)
7981 if (argc
== 0) return Qnil
;
7982 if (RB_TYPE_P(argv
[0], T_STRING
)) {
7983 out
= rb_ractor_stdout();
7990 rb_io_write(out
, rb_f_sprintf(argc
, argv
));
7996 deprecated_str_setter(VALUE val
, ID id
, VALUE
*var
)
7998 rb_str_setter(val
, id
, &val
);
8000 rb_warn_deprecated("`%s'", NULL
, rb_id2name(id
));
8008 * ios.print(obj, ...) -> nil
8010 * Writes the given object(s) to <em>ios</em>. Returns +nil+.
8012 * The stream must be opened for writing.
8013 * Each given object that isn't a string will be converted by calling
8014 * its <code>to_s</code> method.
8015 * When called without arguments, prints the contents of <code>$_</code>.
8017 * If the output field separator (<code>$,</code>) is not +nil+,
8018 * it is inserted between objects.
8019 * If the output record separator (<code>$\\</code>) is not +nil+,
8020 * it is appended to the output.
8022 * $stdout.print("This is ", 100, " percent.\n")
8024 * <em>produces:</em>
8026 * This is 100 percent.
8030 rb_io_print(int argc
, const VALUE
*argv
, VALUE out
)
8035 /* if no argument given, print `$_' */
8038 line
= rb_lastline_get();
8041 if (argc
> 1 && !NIL_P(rb_output_fs
)) {
8042 rb_category_warn(RB_WARN_CATEGORY_DEPRECATED
, "$, is set to non-nil value");
8044 for (i
=0; i
<argc
; i
++) {
8045 if (!NIL_P(rb_output_fs
) && i
>0) {
8046 rb_io_write(out
, rb_output_fs
);
8048 rb_io_write(out
, argv
[i
]);
8050 if (argc
> 0 && !NIL_P(rb_output_rs
)) {
8051 rb_io_write(out
, rb_output_rs
);
8059 * print(obj, ...) -> nil
8061 * Prints each object in turn to <code>$stdout</code>. If the output
8062 * field separator (<code>$,</code>) is not +nil+, its
8063 * contents will appear between each field. If the output record
8064 * separator (<code>$\\</code>) is not +nil+, it will be
8065 * appended to the output. If no arguments are given, prints
8066 * <code>$_</code>. Objects that aren't strings will be converted by
8067 * calling their <code>to_s</code> method.
8069 * print "cat", [1,2,3], 99, "\n"
8072 * print "cat", [1,2,3], 99
8074 * <em>produces:</em>
8081 rb_f_print(int argc
, const VALUE
*argv
, VALUE _
)
8083 rb_io_print(argc
, argv
, rb_ractor_stdout());
8089 * ios.putc(obj) -> obj
8091 * If <i>obj</i> is Numeric, write the character whose code is the
8092 * least-significant byte of <i>obj</i>. If <i>obj</i> is String,
8093 * write the first character of <i>obj</i> to <em>ios</em>. Otherwise,
8099 * <em>produces:</em>
8105 rb_io_putc(VALUE io
, VALUE ch
)
8108 if (RB_TYPE_P(ch
, T_STRING
)) {
8109 str
= rb_str_substr(ch
, 0, 1);
8112 char c
= NUM2CHR(ch
);
8113 str
= rb_str_new(&c
, 1);
8115 rb_io_write(io
, str
);
8119 #define forward(obj, id, argc, argv) \
8120 rb_funcallv_kw(obj, id, argc, argv, RB_PASS_CALLED_KEYWORDS)
8121 #define forward_public(obj, id, argc, argv) \
8122 rb_funcallv_public_kw(obj, id, argc, argv, RB_PASS_CALLED_KEYWORDS)
8123 #define forward_current(id, argc, argv) \
8124 forward_public(ARGF.current_file, id, argc, argv)
8134 * Refer to the documentation for IO#putc for important information regarding
8135 * multi-byte characters.
8139 rb_f_putc(VALUE recv
, VALUE ch
)
8141 VALUE r_stdout
= rb_ractor_stdout();
8142 if (recv
== r_stdout
) {
8143 return rb_io_putc(recv
, ch
);
8145 return forward(r_stdout
, rb_intern("putc"), 1, &ch
);
8150 rb_str_end_with_asciichar(VALUE str
, int c
)
8152 long len
= RSTRING_LEN(str
);
8153 const char *ptr
= RSTRING_PTR(str
);
8154 rb_encoding
*enc
= rb_enc_from_index(ENCODING_GET(str
));
8157 if (len
== 0) return 0;
8158 if ((n
= rb_enc_mbminlen(enc
)) == 1) {
8159 return ptr
[len
- 1] == c
;
8161 return rb_enc_ascget(ptr
+ ((len
- 1) / n
) * n
, ptr
+ len
, &n
, enc
) == c
;
8165 io_puts_ary(VALUE ary
, VALUE out
, int recur
)
8171 tmp
= rb_str_new2("[...]");
8172 rb_io_puts(1, &tmp
, out
);
8175 ary
= rb_check_array_type(ary
);
8176 if (NIL_P(ary
)) return Qfalse
;
8177 for (i
=0; i
<RARRAY_LEN(ary
); i
++) {
8178 tmp
= RARRAY_AREF(ary
, i
);
8179 rb_io_puts(1, &tmp
, out
);
8186 * ios.puts(obj, ...) -> nil
8188 * Writes the given object(s) to <em>ios</em>.
8189 * Writes a newline after any that do not already end
8190 * with a newline sequence. Returns +nil+.
8192 * The stream must be opened for writing.
8193 * If called with an array argument, writes each element on a new line.
8194 * Each given object that isn't a string or array will be converted
8195 * by calling its +to_s+ method.
8196 * If called without arguments, outputs a single newline.
8198 * $stdout.puts("this", "is", ["a", "test"])
8200 * <em>produces:</em>
8207 * Note that +puts+ always uses newlines and is not affected
8208 * by the output record separator (<code>$\\</code>).
8212 rb_io_puts(int argc
, const VALUE
*argv
, VALUE out
)
8215 VALUE line
, args
[2];
8217 /* if no argument given, print newline. */
8219 rb_io_write(out
, rb_default_rs
);
8222 for (i
=0; i
<argc
; i
++) {
8223 if (RB_TYPE_P(argv
[i
], T_STRING
)) {
8227 if (rb_exec_recursive(io_puts_ary
, argv
[i
], out
)) {
8230 line
= rb_obj_as_string(argv
[i
]);
8234 if (RSTRING_LEN(line
) == 0 ||
8235 !rb_str_end_with_asciichar(line
, '\n')) {
8236 args
[n
++] = rb_default_rs
;
8238 rb_io_writev(out
, n
, args
);
8246 * puts(obj, ...) -> nil
8250 * $stdout.puts(obj, ...)
8254 rb_f_puts(int argc
, VALUE
*argv
, VALUE recv
)
8256 VALUE r_stdout
= rb_ractor_stdout();
8257 if (recv
== r_stdout
) {
8258 return rb_io_puts(argc
, argv
, recv
);
8260 return forward(r_stdout
, rb_intern("puts"), argc
, argv
);
8264 rb_p_write(VALUE str
)
8268 args
[1] = rb_default_rs
;
8269 VALUE r_stdout
= rb_ractor_stdout();
8270 if (RB_TYPE_P(r_stdout
, T_FILE
) &&
8271 rb_method_basic_definition_p(CLASS_OF(r_stdout
), id_write
)) {
8272 io_writev(2, args
, r_stdout
);
8275 rb_io_writev(r_stdout
, 2, args
);
8281 rb_p(VALUE obj
) /* for debug print within C code */
8283 rb_p_write(rb_obj_as_string(rb_inspect(obj
)));
8287 rb_p_result(int argc
, const VALUE
*argv
)
8294 else if (argc
> 1) {
8295 ret
= rb_ary_new4(argc
, argv
);
8297 VALUE r_stdout
= rb_ractor_stdout();
8298 if (RB_TYPE_P(r_stdout
, T_FILE
)) {
8299 rb_io_flush(r_stdout
);
8307 * p(obj1, obj2, ...) -> [obj, ...]
8310 * For each object, directly writes _obj_.+inspect+ followed by a
8311 * newline to the program's standard output.
8313 * S = Struct.new(:name, :state)
8314 * s = S['dave', 'TX']
8317 * <em>produces:</em>
8319 * #<S name="dave", state="TX">
8323 rb_f_p(int argc
, VALUE
*argv
, VALUE self
)
8326 for (i
=0; i
<argc
; i
++) {
8327 VALUE inspected
= rb_obj_as_string(rb_inspect(argv
[i
]));
8328 rb_uninterruptible(rb_p_write
, inspected
);
8330 return rb_p_result(argc
, argv
);
8335 * obj.display(port=$>) -> nil
8337 * Prints <i>obj</i> on the given port (default <code>$></code>).
8340 * def display(port=$>)
8349 * [ 4, 5, 6 ].display
8352 * <em>produces:</em>
8358 rb_obj_display(int argc
, VALUE
*argv
, VALUE self
)
8362 out
= (!rb_check_arity(argc
, 0, 1) ? rb_ractor_stdout() : argv
[0]);
8363 rb_io_write(out
, self
);
8369 rb_stderr_to_original_p(VALUE err
)
8371 return (err
== orig_stderr
|| RFILE(orig_stderr
)->fptr
->fd
< 0);
8375 rb_write_error2(const char *mesg
, long len
)
8377 VALUE out
= rb_ractor_stderr();
8378 if (rb_stderr_to_original_p(out
)) {
8380 if (isatty(fileno(stderr
))) {
8381 if (rb_w32_write_console(rb_str_new(mesg
, len
), fileno(stderr
)) > 0) return;
8384 if (fwrite(mesg
, sizeof(char), (size_t)len
, stderr
) < (size_t)len
) {
8385 /* failed to write to stderr, what can we do? */
8390 rb_io_write(out
, rb_str_new(mesg
, len
));
8395 rb_write_error(const char *mesg
)
8397 rb_write_error2(mesg
, strlen(mesg
));
8401 rb_write_error_str(VALUE mesg
)
8403 VALUE out
= rb_ractor_stderr();
8404 /* a stopgap measure for the time being */
8405 if (rb_stderr_to_original_p(out
)) {
8406 size_t len
= (size_t)RSTRING_LEN(mesg
);
8408 if (isatty(fileno(stderr
))) {
8409 if (rb_w32_write_console(mesg
, fileno(stderr
)) > 0) return;
8412 if (fwrite(RSTRING_PTR(mesg
), sizeof(char), len
, stderr
) < len
) {
8418 /* may unlock GVL, and */
8419 rb_io_write(out
, mesg
);
8424 rb_stderr_tty_p(void)
8426 if (rb_stderr_to_original_p(rb_ractor_stderr()))
8427 return isatty(fileno(stderr
));
8432 must_respond_to(ID mid
, VALUE val
, ID id
)
8434 if (!rb_respond_to(val
, mid
)) {
8435 rb_raise(rb_eTypeError
, "%"PRIsVALUE
" must have %"PRIsVALUE
" method, %"PRIsVALUE
" given",
8436 rb_id2str(id
), rb_id2str(mid
),
8442 stdin_setter(VALUE val
, ID id
, VALUE
*ptr
)
8444 rb_ractor_stdin_set(val
);
8448 stdin_getter(ID id
, VALUE
*ptr
)
8450 return rb_ractor_stdin();
8454 stdout_setter(VALUE val
, ID id
, VALUE
*ptr
)
8456 must_respond_to(id_write
, val
, id
);
8457 rb_ractor_stdout_set(val
);
8461 stdout_getter(ID id
, VALUE
*ptr
)
8463 return rb_ractor_stdout();
8467 stderr_setter(VALUE val
, ID id
, VALUE
*ptr
)
8469 must_respond_to(id_write
, val
, id
);
8470 rb_ractor_stderr_set(val
);
8474 stderr_getter(ID id
, VALUE
*ptr
)
8476 return rb_ractor_stderr();
8480 prep_io(int fd
, int fmode
, VALUE klass
, const char *path
)
8483 VALUE io
= io_alloc(klass
);
8485 MakeOpenFile(io
, fp
);
8489 if (!io_check_tty(fp
)) {
8491 fp
->mode
|= FMODE_BINMODE
;
8492 setmode(fd
, O_BINARY
);
8495 if (path
) fp
->pathv
= rb_obj_freeze(rb_str_new_cstr(path
));
8496 rb_update_max_fd(fd
);
8502 rb_io_fdopen(int fd
, int oflags
, const char *path
)
8504 VALUE klass
= rb_cIO
;
8506 if (path
&& strcmp(path
, "-")) klass
= rb_cFile
;
8507 return prep_io(fd
, rb_io_oflags_fmode(oflags
), klass
, path
);
8511 prep_stdio(FILE *f
, int fmode
, VALUE klass
, const char *path
)
8514 VALUE io
= prep_io(fileno(f
), fmode
|FMODE_PREP
|DEFAULT_TEXTMODE
, klass
, path
);
8516 GetOpenFile(io
, fptr
);
8517 fptr
->encs
.ecflags
|= ECONV_DEFAULT_NEWLINE_DECORATOR
;
8518 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
8519 fptr
->encs
.ecflags
|= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
;
8520 if (fmode
& FMODE_READABLE
) {
8521 fptr
->encs
.ecflags
|= ECONV_UNIVERSAL_NEWLINE_DECORATOR
;
8524 fptr
->stdio_file
= f
;
8530 rb_io_prep_stdin(void)
8532 return prep_stdio(stdin
, FMODE_READABLE
, rb_cIO
, "<STDIN>");
8536 rb_io_prep_stdout(void)
8538 return prep_stdio(stdout
, FMODE_WRITABLE
|FMODE_SIGNAL_ON_EPIPE
, rb_cIO
, "<STDOUT>");
8542 rb_io_prep_stderr(void)
8544 return prep_stdio(stderr
, FMODE_WRITABLE
|FMODE_SYNC
, rb_cIO
, "<STDERR>");
8548 rb_io_stdio_file(rb_io_t
*fptr
)
8550 if (!fptr
->stdio_file
) {
8551 int oflags
= rb_io_fmode_oflags(fptr
->mode
) & ~O_EXCL
;
8552 fptr
->stdio_file
= rb_fdopen(fptr
->fd
, rb_io_oflags_modestr(oflags
));
8554 return fptr
->stdio_file
;
8558 rb_io_buffer_init(rb_io_buffer_t
*buf
)
8566 static inline rb_io_t
*
8567 rb_io_fptr_new(void)
8569 rb_io_t
*fp
= ALLOC(rb_io_t
);
8572 fp
->stdio_file
= NULL
;
8578 rb_io_buffer_init(&fp
->wbuf
);
8579 rb_io_buffer_init(&fp
->rbuf
);
8580 rb_io_buffer_init(&fp
->cbuf
);
8581 fp
->readconv
= NULL
;
8582 fp
->writeconv
= NULL
;
8583 fp
->writeconv_asciicompat
= Qnil
;
8584 fp
->writeconv_pre_ecflags
= 0;
8585 fp
->writeconv_pre_ecopts
= Qnil
;
8586 fp
->writeconv_initialized
= 0;
8587 fp
->tied_io_for_writing
= 0;
8588 fp
->encs
.enc
= NULL
;
8589 fp
->encs
.enc2
= NULL
;
8590 fp
->encs
.ecflags
= 0;
8591 fp
->encs
.ecopts
= Qnil
;
8597 rb_io_make_open_file(VALUE obj
)
8601 Check_Type(obj
, T_FILE
);
8602 if (RFILE(obj
)->fptr
) {
8604 rb_io_fptr_finalize(RFILE(obj
)->fptr
);
8605 RFILE(obj
)->fptr
= 0;
8607 fp
= rb_io_fptr_new();
8609 RFILE(obj
)->fptr
= fp
;
8615 * IO.new(fd [, mode] [, opt]) -> io
8617 * Returns a new IO object (a stream) for the given integer file descriptor
8618 * +fd+ and +mode+ string. +opt+ may be used to specify parts of +mode+ in a
8619 * more readable fashion. See also IO.sysopen and IO.for_fd.
8621 * IO.new is called by various File and IO opening methods such as IO::open,
8622 * Kernel#open, and File::open.
8626 * When +mode+ is an integer it must be combination of the modes defined in
8627 * File::Constants (+File::RDONLY+, <code>File::WRONLY|File::CREAT</code>).
8628 * See the open(2) man page for more information.
8630 * When +mode+ is a string it must be in one of the following forms:
8634 * fmode ":" ext_enc ":" int_enc
8635 * fmode ":" "BOM|UTF-*"
8637 * +fmode+ is an IO open mode string, +ext_enc+ is the external encoding for
8638 * the IO and +int_enc+ is the internal encoding.
8642 * Ruby allows the following open modes:
8644 * "r" Read-only, starts at beginning of file (default mode).
8646 * "r+" Read-write, starts at beginning of file.
8648 * "w" Write-only, truncates existing file
8649 * to zero length or creates a new file for writing.
8651 * "w+" Read-write, truncates existing file to zero length
8652 * or creates a new file for reading and writing.
8654 * "a" Write-only, each write call appends data at end of file.
8655 * Creates a new file for writing if file does not exist.
8657 * "a+" Read-write, each write call appends data at end of file.
8658 * Creates a new file for reading and writing if file does
8661 * The following modes must be used separately, and along with one or more of
8662 * the modes seen above.
8664 * "b" Binary file mode
8665 * Suppresses EOL <-> CRLF conversion on Windows. And
8666 * sets external encoding to ASCII-8BIT unless explicitly
8669 * "t" Text file mode
8671 * The exclusive access mode ("x") can be used together with "w" to ensure
8672 * the file is created. Errno::EEXIST is raised when it already exists.
8673 * It may not be supported with all kinds of streams (e.g. pipes).
8675 * When the open mode of original IO is read only, the mode cannot be
8676 * changed to be writable. Similarly, the open mode cannot be changed from
8677 * write only to readable.
8679 * When such a change is attempted the error is raised in different locations
8680 * according to the platform.
8684 * When +ext_enc+ is specified, strings read will be tagged by the encoding
8685 * when reading, and strings output will be converted to the specified
8686 * encoding when writing.
8688 * When +ext_enc+ and +int_enc+ are specified read strings will be converted
8689 * from +ext_enc+ to +int_enc+ upon input, and written strings will be
8690 * converted from +int_enc+ to +ext_enc+ upon output. See Encoding for
8691 * further details of transcoding on input and output.
8693 * If "BOM|UTF-8", "BOM|UTF-16LE" or "BOM|UTF16-BE" are used, Ruby checks for
8694 * a Unicode BOM in the input document to help determine the encoding. For
8695 * UTF-16 encodings the file open mode must be binary. When present, the BOM
8696 * is stripped and the external encoding from the BOM is used. When the BOM
8697 * is missing the given Unicode encoding is used as +ext_enc+. (The BOM-set
8698 * encoding option is case insensitive, so "bom|utf-8" is also valid.)
8702 * +opt+ can be used instead of +mode+ for improved readability. The
8703 * following keys are supported:
8706 * Same as +mode+ parameter
8709 * Specifies file open flags as integer.
8710 * If +mode+ parameter is given, this parameter will be bitwise-ORed.
8712 * :\external_encoding ::
8713 * External encoding for the IO.
8715 * :\internal_encoding ::
8716 * Internal encoding for the IO. "-" is a synonym for the default internal
8719 * If the value is +nil+ no conversion occurs.
8722 * Specifies external and internal encodings as "extern:intern".
8725 * If the value is truth value, same as "t" in argument +mode+.
8728 * If the value is truth value, same as "b" in argument +mode+.
8731 * If the value is +false+, the +fd+ will be kept open after this IO
8732 * instance gets finalized.
8734 * Also, +opt+ can have same keys in String#encode for controlling conversion
8735 * between the external encoding and the internal encoding.
8739 * fd = IO.sysopen("/dev/tty", "w")
8740 * a = IO.new(fd,"w")
8741 * $stderr.puts "Hello"
8753 * fd = STDERR.fcntl(Fcntl::F_DUPFD)
8754 * io = IO.new(fd, mode: 'w:UTF-16LE', cr_newline: true)
8755 * io.puts "Hello, World!"
8757 * fd = STDERR.fcntl(Fcntl::F_DUPFD)
8758 * io = IO.new(fd, mode: 'w', cr_newline: true,
8759 * external_encoding: Encoding::UTF_16LE)
8760 * io.puts "Hello, World!"
8762 * Both of above print "Hello, World!" in UTF-16LE to standard error output
8763 * with converting EOL generated by #puts to CR.
8767 rb_io_initialize(int argc
, VALUE
*argv
, VALUE io
)
8771 int fd
, fmode
, oflags
= O_RDONLY
;
8772 convconfig_t convconfig
;
8774 #if defined(HAVE_FCNTL) && defined(F_GETFL)
8781 argc
= rb_scan_args(argc
, argv
, "11:", &fnum
, &vmode
, &opt
);
8782 rb_io_extract_modeenc(&vmode
, 0, opt
, &oflags
, &fmode
, &convconfig
);
8785 if (rb_reserved_fd_p(fd
)) {
8786 rb_raise(rb_eArgError
, "The given fd is not accessible because RubyVM reserves it");
8788 #if defined(HAVE_FCNTL) && defined(F_GETFL)
8789 oflags
= fcntl(fd
, F_GETFL
);
8790 if (oflags
== -1) rb_sys_fail(0);
8792 if (fstat(fd
, &st
) < 0) rb_sys_fail(0);
8794 rb_update_max_fd(fd
);
8795 #if defined(HAVE_FCNTL) && defined(F_GETFL)
8796 ofmode
= rb_io_oflags_fmode(oflags
);
8800 else if ((~ofmode
& fmode
) & FMODE_READWRITE
) {
8801 VALUE error
= INT2FIX(EINVAL
);
8802 rb_exc_raise(rb_class_new_instance(1, &error
, rb_eSystemCallError
));
8805 if (!NIL_P(opt
) && rb_hash_aref(opt
, sym_autoclose
) == Qfalse
) {
8806 fmode
|= FMODE_PREP
;
8808 MakeOpenFile(io
, fp
);
8812 fp
->encs
= convconfig
;
8815 if (fileno(stdin
) == fd
)
8816 fp
->stdio_file
= stdin
;
8817 else if (fileno(stdout
) == fd
)
8818 fp
->stdio_file
= stdout
;
8819 else if (fileno(stderr
) == fd
)
8820 fp
->stdio_file
= stderr
;
8822 if (fmode
& FMODE_SETENC_BY_BOM
) io_set_encoding_by_bom(io
);
8828 * ios.set_encoding_by_bom -> encoding or nil
8830 * Checks if +ios+ starts with a BOM, and then consumes it and sets
8831 * the external encoding. Returns the result encoding if found, or
8832 * nil. If +ios+ is not binmode or its encoding has been set
8833 * already, an exception will be raised.
8835 * File.write("bom.txt", "\u{FEFF}abc")
8836 * ios = File.open("bom.txt", "rb")
8837 * ios.set_encoding_by_bom #=> #<Encoding:UTF-8>
8839 * File.write("nobom.txt", "abc")
8840 * ios = File.open("nobom.txt", "rb")
8841 * ios.set_encoding_by_bom #=> nil
8845 rb_io_set_encoding_by_bom(VALUE io
)
8849 GetOpenFile(io
, fptr
);
8850 if (!(fptr
->mode
& FMODE_BINMODE
)) {
8851 rb_raise(rb_eArgError
, "ASCII incompatible encoding needs binmode");
8853 if (fptr
->encs
.enc2
) {
8854 rb_raise(rb_eArgError
, "encoding conversion is set");
8856 else if (fptr
->encs
.enc
&& fptr
->encs
.enc
!= rb_ascii8bit_encoding()) {
8857 rb_raise(rb_eArgError
, "encoding is set to %s already",
8858 rb_enc_name(fptr
->encs
.enc
));
8860 if (!io_set_encoding_by_bom(io
)) return Qnil
;
8861 return rb_enc_from_encoding(fptr
->encs
.enc
);
8866 * File.new(filename, mode="r" [, opt]) -> file
8867 * File.new(filename [, mode [, perm]] [, opt]) -> file
8869 * Opens the file named by +filename+ according to the given +mode+ and
8870 * returns a new File object.
8872 * See IO.new for a description of +mode+ and +opt+.
8874 * If a file is being created, permission bits may be given in +perm+. These
8875 * mode and permission bits are platform dependent; on Unix systems, see
8876 * open(2) and chmod(2) man pages for details.
8878 * The new File object is buffered mode (or non-sync mode), unless
8879 * +filename+ is a tty.
8880 * See IO#flush, IO#fsync, IO#fdatasync, and IO#sync= about sync mode.
8884 * f = File.new("testfile", "r")
8885 * f = File.new("newfile", "w+")
8886 * f = File.new("newfile", File::CREAT|File::TRUNC|File::RDWR, 0644)
8890 rb_file_initialize(int argc
, VALUE
*argv
, VALUE io
)
8892 if (RFILE(io
)->fptr
) {
8893 rb_raise(rb_eRuntimeError
, "reinitializing File");
8895 if (0 < argc
&& argc
< 3) {
8896 VALUE fd
= rb_check_to_int(argv
[0]);
8900 return rb_io_initialize(argc
, argv
, io
);
8903 rb_open_file(argc
, argv
, io
);
8910 rb_io_s_new(int argc
, VALUE
*argv
, VALUE klass
)
8912 if (rb_block_given_p()) {
8913 VALUE cname
= rb_obj_as_string(klass
);
8915 rb_warn("%"PRIsVALUE
"::new() does not take block; use %"PRIsVALUE
"::open() instead",
8918 return rb_class_new_instance_kw(argc
, argv
, klass
, RB_PASS_CALLED_KEYWORDS
);
8924 * IO.for_fd(fd, mode [, opt]) -> io
8926 * Synonym for IO.new.
8931 rb_io_s_for_fd(int argc
, VALUE
*argv
, VALUE klass
)
8933 VALUE io
= rb_obj_alloc(klass
);
8934 rb_io_initialize(argc
, argv
, io
);
8940 * ios.autoclose? -> true or false
8942 * Returns +true+ if the underlying file descriptor of _ios_ will be
8943 * closed automatically at its finalization, otherwise +false+.
8947 rb_io_autoclose_p(VALUE io
)
8949 rb_io_t
*fptr
= RFILE(io
)->fptr
;
8950 rb_io_check_closed(fptr
);
8951 return (fptr
->mode
& FMODE_PREP
) ? Qfalse
: Qtrue
;
8956 * io.autoclose = bool -> true or false
8958 * Sets auto-close flag.
8960 * f = open("/dev/null")
8961 * IO.for_fd(f.fileno)
8963 * f.gets # may cause Errno::EBADF
8965 * f = open("/dev/null")
8966 * IO.for_fd(f.fileno).autoclose = false
8968 * f.gets # won't cause Errno::EBADF
8972 rb_io_set_autoclose(VALUE io
, VALUE autoclose
)
8975 GetOpenFile(io
, fptr
);
8976 if (!RTEST(autoclose
))
8977 fptr
->mode
|= FMODE_PREP
;
8979 fptr
->mode
&= ~FMODE_PREP
;
8984 argf_mark(void *ptr
)
8986 struct argf
*p
= ptr
;
8987 rb_gc_mark(p
->filename
);
8988 rb_gc_mark(p
->current_file
);
8989 rb_gc_mark(p
->argv
);
8990 rb_gc_mark(p
->inplace
);
8991 rb_gc_mark(p
->encs
.ecopts
);
8995 argf_memsize(const void *ptr
)
8997 const struct argf
*p
= ptr
;
8998 size_t size
= sizeof(*p
);
9002 static const rb_data_type_t argf_type
= {
9004 {argf_mark
, RUBY_TYPED_DEFAULT_FREE
, argf_memsize
},
9005 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
9009 argf_init(struct argf
*p
, VALUE v
)
9012 p
->current_file
= Qnil
;
9018 argf_alloc(VALUE klass
)
9021 VALUE argf
= TypedData_Make_Struct(klass
, struct argf
, &argf_type
, p
);
9031 argf_initialize(VALUE argf
, VALUE argv
)
9033 memset(&ARGF
, 0, sizeof(ARGF
));
9034 argf_init(&ARGF
, argv
);
9041 argf_initialize_copy(VALUE argf
, VALUE orig
)
9043 if (!OBJ_INIT_COPY(argf
, orig
)) return argf
;
9044 ARGF
= argf_of(orig
);
9045 ARGF
.argv
= rb_obj_dup(ARGF
.argv
);
9051 * ARGF.lineno = integer -> integer
9053 * Sets the line number of +ARGF+ as a whole to the given +Integer+.
9055 * +ARGF+ sets the line number automatically as you read data, so normally
9056 * you will not need to set it explicitly. To access the current line number
9057 * use +ARGF.lineno+.
9062 * ARGF.readline #=> "This is line 1\n"
9064 * ARGF.lineno = 0 #=> 0
9068 argf_set_lineno(VALUE argf
, VALUE val
)
9070 ARGF
.lineno
= NUM2INT(val
);
9071 ARGF
.last_lineno
= ARGF
.lineno
;
9077 * ARGF.lineno -> integer
9079 * Returns the current line number of ARGF as a whole. This value
9080 * can be set manually with +ARGF.lineno=+.
9085 * ARGF.readline #=> "This is line 1\n"
9089 argf_lineno(VALUE argf
)
9091 return INT2FIX(ARGF
.lineno
);
9095 argf_forward(int argc
, VALUE
*argv
, VALUE argf
)
9097 return forward_current(rb_frame_this_func(), argc
, argv
);
9100 #define next_argv() argf_next_argv(argf)
9101 #define ARGF_GENERIC_INPUT_P() \
9102 (ARGF.current_file == rb_stdin && !RB_TYPE_P(ARGF.current_file, T_FILE))
9103 #define ARGF_FORWARD(argc, argv) do {\
9104 if (ARGF_GENERIC_INPUT_P())\
9105 return argf_forward((argc), (argv), argf);\
9107 #define NEXT_ARGF_FORWARD(argc, argv) do {\
9108 if (!next_argv()) return Qnil;\
9109 ARGF_FORWARD((argc), (argv));\
9113 argf_close(VALUE argf
)
9115 VALUE file
= ARGF
.current_file
;
9116 if (file
== rb_stdin
) return;
9117 if (RB_TYPE_P(file
, T_FILE
)) {
9118 rb_io_set_write_io(file
, Qnil
);
9125 argf_next_argv(VALUE argf
)
9129 int stdout_binmode
= 0;
9132 VALUE r_stdout
= rb_ractor_stdout();
9134 if (RB_TYPE_P(r_stdout
, T_FILE
)) {
9135 GetOpenFile(r_stdout
, fptr
);
9136 if (fptr
->mode
& FMODE_BINMODE
)
9140 if (ARGF
.init_p
== 0) {
9141 if (!NIL_P(ARGF
.argv
) && RARRAY_LEN(ARGF
.argv
) > 0) {
9150 if (NIL_P(ARGF
.argv
)) {
9153 else if (ARGF
.next_p
== -1 && RARRAY_LEN(ARGF
.argv
) > 0) {
9158 if (ARGF
.next_p
== 1) {
9159 if (ARGF
.init_p
== 1) argf_close(argf
);
9161 if (RARRAY_LEN(ARGF
.argv
) > 0) {
9162 VALUE filename
= rb_ary_shift(ARGF
.argv
);
9163 FilePathValue(filename
);
9164 ARGF
.filename
= filename
;
9165 filename
= rb_str_encode_ospath(filename
);
9166 fn
= StringValueCStr(filename
);
9167 if (RSTRING_LEN(filename
) == 1 && fn
[0] == '-') {
9168 ARGF
.current_file
= rb_stdin
;
9170 rb_warn("Can't do inplace edit for stdio; skipping");
9175 VALUE write_io
= Qnil
;
9176 int fr
= rb_sysopen(filename
, O_RDONLY
, 0);
9180 #ifndef NO_SAFE_RENAME
9186 if (RB_TYPE_P(r_stdout
, T_FILE
) && r_stdout
!= orig_stdout
) {
9187 rb_io_close(r_stdout
);
9191 if (!NIL_P(ARGF
.inplace
)) {
9192 VALUE suffix
= ARGF
.inplace
;
9193 str
= rb_str_dup(str
);
9194 if (NIL_P(rb_str_cat_conv_enc_opts(str
, RSTRING_LEN(str
),
9195 RSTRING_PTR(suffix
), RSTRING_LEN(suffix
),
9196 rb_enc_get(suffix
), 0, Qnil
))) {
9197 rb_str_append(str
, suffix
);
9199 #ifdef NO_SAFE_RENAME
9201 (void)unlink(RSTRING_PTR(str
));
9202 if (rename(fn
, RSTRING_PTR(str
)) < 0) {
9203 rb_warn("Can't rename %"PRIsVALUE
" to %"PRIsVALUE
": %s, skipping file",
9204 filename
, str
, strerror(errno
));
9207 fr
= rb_sysopen(str
, O_RDONLY
, 0);
9209 if (rename(fn
, RSTRING_PTR(str
)) < 0) {
9210 rb_warn("Can't rename %"PRIsVALUE
" to %"PRIsVALUE
": %s, skipping file",
9211 filename
, str
, strerror(errno
));
9218 #ifdef NO_SAFE_RENAME
9219 rb_fatal("Can't do inplace edit without backup");
9221 if (unlink(fn
) < 0) {
9222 rb_warn("Can't remove %"PRIsVALUE
": %s, skipping file",
9223 filename
, strerror(errno
));
9229 fw
= rb_sysopen(filename
, O_WRONLY
|O_CREAT
|O_TRUNC
, 0666);
9230 #ifndef NO_SAFE_RENAME
9233 fchmod(fw
, st
.st_mode
);
9235 chmod(fn
, st
.st_mode
);
9237 if (st
.st_uid
!=st2
.st_uid
|| st
.st_gid
!=st2
.st_gid
) {
9240 err
= fchown(fw
, st
.st_uid
, st
.st_gid
);
9242 err
= chown(fn
, st
.st_uid
, st
.st_gid
);
9244 if (err
&& getuid() == 0 && st2
.st_uid
== 0) {
9245 const char *wkfn
= RSTRING_PTR(filename
);
9246 rb_warn("Can't set owner/group of %"PRIsVALUE
" to same as %"PRIsVALUE
": %s, skipping file",
9247 filename
, str
, strerror(errno
));
9255 write_io
= prep_io(fw
, FMODE_WRITABLE
, rb_cFile
, fn
);
9256 rb_ractor_stdout_set(write_io
);
9257 if (stdout_binmode
) rb_io_binmode(rb_stdout
);
9259 fmode
= FMODE_READABLE
;
9260 if (!ARGF
.binmode
) {
9261 fmode
|= DEFAULT_TEXTMODE
;
9263 ARGF
.current_file
= prep_io(fr
, fmode
, rb_cFile
, fn
);
9264 if (!NIL_P(write_io
)) {
9265 rb_io_set_write_io(ARGF
.current_file
, write_io
);
9267 RB_GC_GUARD(filename
);
9269 if (ARGF
.binmode
) rb_io_ascii8bit_binmode(ARGF
.current_file
);
9270 GetOpenFile(ARGF
.current_file
, fptr
);
9271 if (ARGF
.encs
.enc
) {
9272 fptr
->encs
= ARGF
.encs
;
9273 clear_codeconv(fptr
);
9276 fptr
->encs
.ecflags
&= ~ECONV_NEWLINE_DECORATOR_MASK
;
9277 if (!ARGF
.binmode
) {
9278 fptr
->encs
.ecflags
|= ECONV_DEFAULT_NEWLINE_DECORATOR
;
9279 #ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
9280 fptr
->encs
.ecflags
|= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
;
9291 else if (ARGF
.next_p
== -1) {
9292 ARGF
.current_file
= rb_stdin
;
9293 ARGF
.filename
= rb_str_new2("-");
9295 rb_warn("Can't do inplace edit for stdio");
9296 rb_ractor_stdout_set(orig_stdout
);
9299 if (ARGF
.init_p
== -1) ARGF
.init_p
= 1;
9304 argf_getline(int argc
, VALUE
*argv
, VALUE argf
)
9307 long lineno
= ARGF
.lineno
;
9310 if (!next_argv()) return Qnil
;
9311 if (ARGF_GENERIC_INPUT_P()) {
9312 line
= forward_current(idGets
, argc
, argv
);
9315 if (argc
== 0 && rb_rs
== rb_default_rs
) {
9316 line
= rb_io_gets(ARGF
.current_file
);
9319 line
= rb_io_getline(argc
, argv
, ARGF
.current_file
);
9321 if (NIL_P(line
) && ARGF
.next_p
!= -1) {
9328 ARGF
.lineno
= ++lineno
;
9329 ARGF
.last_lineno
= ARGF
.lineno
;
9335 argf_lineno_getter(ID id
, VALUE
*var
)
9338 return INT2FIX(ARGF
.last_lineno
);
9342 argf_lineno_setter(VALUE val
, ID id
, VALUE
*var
)
9345 int n
= NUM2INT(val
);
9346 ARGF
.last_lineno
= ARGF
.lineno
= n
;
9349 static VALUE
argf_gets(int, VALUE
*, VALUE
);
9353 * gets(sep=$/ [, getline_args]) -> string or nil
9354 * gets(limit [, getline_args]) -> string or nil
9355 * gets(sep, limit [, getline_args]) -> string or nil
9357 * Returns (and assigns to <code>$_</code>) the next line from the list
9358 * of files in +ARGV+ (or <code>$*</code>), or from standard input if
9359 * no files are present on the command line. Returns +nil+ at end of
9360 * file. The optional argument specifies the record separator. The
9361 * separator is included with the contents of each record. A separator
9362 * of +nil+ reads the entire contents, and a zero-length separator
9363 * reads the input one paragraph at a time, where paragraphs are
9364 * divided by two consecutive newlines. If the first argument is an
9365 * integer, or optional second argument is given, the returning string
9366 * would not be longer than the given value in bytes. If multiple
9367 * filenames are present in +ARGV+, <code>gets(nil)</code> will read
9368 * the contents one file at a time.
9370 * ARGV << "testfile"
9373 * <em>produces:</em>
9377 * This is line three
9380 * The style of programming using <code>$_</code> as an implicit
9381 * parameter is gradually losing favor in the Ruby community.
9385 rb_f_gets(int argc
, VALUE
*argv
, VALUE recv
)
9388 return argf_gets(argc
, argv
, argf
);
9390 return forward(argf
, idGets
, argc
, argv
);
9395 * ARGF.gets(sep=$/ [, getline_args]) -> string or nil
9396 * ARGF.gets(limit [, getline_args]) -> string or nil
9397 * ARGF.gets(sep, limit [, getline_args]) -> string or nil
9399 * Returns the next line from the current file in +ARGF+.
9401 * By default lines are assumed to be separated by <code>$/</code>;
9402 * to use a different character as a separator, supply it as a +String+
9403 * for the _sep_ argument.
9405 * The optional _limit_ argument specifies how many characters of each line
9406 * to return. By default all characters are returned.
9408 * See IO.readlines for details about getline_args.
9412 argf_gets(int argc
, VALUE
*argv
, VALUE argf
)
9416 line
= argf_getline(argc
, argv
, argf
);
9417 rb_lastline_set(line
);
9427 if (rb_rs
!= rb_default_rs
) {
9428 return rb_f_gets(0, 0, argf
);
9432 if (!next_argv()) return Qnil
;
9433 line
= rb_io_gets(ARGF
.current_file
);
9434 if (NIL_P(line
) && ARGF
.next_p
!= -1) {
9435 rb_io_close(ARGF
.current_file
);
9439 rb_lastline_set(line
);
9442 ARGF
.last_lineno
= ARGF
.lineno
;
9448 static VALUE
argf_readline(int, VALUE
*, VALUE
);
9452 * readline(sep=$/) -> string
9453 * readline(limit) -> string
9454 * readline(sep, limit) -> string
9456 * Equivalent to Kernel::gets, except
9457 * +readline+ raises +EOFError+ at end of file.
9461 rb_f_readline(int argc
, VALUE
*argv
, VALUE recv
)
9464 return argf_readline(argc
, argv
, argf
);
9466 return forward(argf
, rb_intern("readline"), argc
, argv
);
9472 * ARGF.readline(sep=$/) -> string
9473 * ARGF.readline(limit) -> string
9474 * ARGF.readline(sep, limit) -> string
9476 * Returns the next line from the current file in +ARGF+.
9478 * By default lines are assumed to be separated by <code>$/</code>;
9479 * to use a different character as a separator, supply it as a +String+
9480 * for the _sep_ argument.
9482 * The optional _limit_ argument specifies how many characters of each line
9483 * to return. By default all characters are returned.
9485 * An +EOFError+ is raised at the end of the file.
9488 argf_readline(int argc
, VALUE
*argv
, VALUE argf
)
9492 if (!next_argv()) rb_eof_error();
9493 ARGF_FORWARD(argc
, argv
);
9494 line
= argf_gets(argc
, argv
, argf
);
9502 static VALUE
argf_readlines(int, VALUE
*, VALUE
);
9506 * readlines(sep=$/) -> array
9507 * readlines(limit) -> array
9508 * readlines(sep, limit) -> array
9510 * Returns an array containing the lines returned by calling
9511 * <code>Kernel.gets(<i>sep</i>)</code> until the end of file.
9515 rb_f_readlines(int argc
, VALUE
*argv
, VALUE recv
)
9518 return argf_readlines(argc
, argv
, argf
);
9520 return forward(argf
, rb_intern("readlines"), argc
, argv
);
9525 * ARGF.readlines(sep=$/) -> array
9526 * ARGF.readlines(limit) -> array
9527 * ARGF.readlines(sep, limit) -> array
9529 * ARGF.to_a(sep=$/) -> array
9530 * ARGF.to_a(limit) -> array
9531 * ARGF.to_a(sep, limit) -> array
9533 * Reads +ARGF+'s current file in its entirety, returning an +Array+ of its
9534 * lines, one line per element. Lines are assumed to be separated by _sep_.
9536 * lines = ARGF.readlines
9537 * lines[0] #=> "This is line one\n"
9540 argf_readlines(int argc
, VALUE
*argv
, VALUE argf
)
9542 long lineno
= ARGF
.lineno
;
9546 while (next_argv()) {
9547 if (ARGF_GENERIC_INPUT_P()) {
9548 lines
= forward_current(rb_intern("readlines"), argc
, argv
);
9551 lines
= rb_io_readlines(argc
, argv
, ARGF
.current_file
);
9555 rb_ary_concat(ary
, lines
);
9556 ARGF
.lineno
= lineno
+ RARRAY_LEN(ary
);
9557 ARGF
.last_lineno
= ARGF
.lineno
;
9567 * Returns the standard output of running _cmd_ in a subshell.
9568 * The built-in syntax <code>%x{...}</code> uses
9569 * this method. Sets <code>$?</code> to the process status.
9571 * `date` #=> "Wed Apr 9 08:56:30 CDT 2003\n"
9572 * `ls testdir`.split[1] #=> "main.rb"
9573 * `echo oops && exit 99` #=> "oops\n"
9574 * $?.exitstatus #=> 99
9578 rb_f_backquote(VALUE obj
, VALUE str
)
9584 SafeStringValue(str
);
9585 rb_last_status_clear();
9586 port
= pipe_open_s(str
, "r", FMODE_READABLE
|DEFAULT_TEXTMODE
, NULL
);
9587 if (NIL_P(port
)) return rb_str_new(0,0);
9589 GetOpenFile(port
, fptr
);
9590 result
= read_all(fptr
, remain_size(fptr
), Qnil
);
9592 RFILE(port
)->fptr
= NULL
;
9593 rb_io_fptr_finalize(fptr
);
9599 #ifdef HAVE_SYS_SELECT_H
9600 #include <sys/select.h>
9604 select_internal(VALUE read
, VALUE write
, VALUE except
, struct timeval
*tp
, rb_fdset_t
*fds
)
9607 rb_fdset_t
*rp
, *wp
, *ep
;
9612 struct timeval timerec
;
9615 Check_Type(read
, T_ARRAY
);
9616 for (i
=0; i
<RARRAY_LEN(read
); i
++) {
9617 GetOpenFile(rb_io_get_io(RARRAY_AREF(read
, i
)), fptr
);
9618 rb_fd_set(fptr
->fd
, &fds
[0]);
9619 if (READ_DATA_PENDING(fptr
) || READ_CHAR_PENDING(fptr
)) { /* check for buffered data */
9621 rb_fd_set(fptr
->fd
, &fds
[3]);
9623 if (max
< fptr
->fd
) max
= fptr
->fd
;
9625 if (pending
) { /* no blocking if there's buffered data */
9626 timerec
.tv_sec
= timerec
.tv_usec
= 0;
9634 if (!NIL_P(write
)) {
9635 Check_Type(write
, T_ARRAY
);
9636 for (i
=0; i
<RARRAY_LEN(write
); i
++) {
9637 VALUE write_io
= GetWriteIO(rb_io_get_io(RARRAY_AREF(write
, i
)));
9638 GetOpenFile(write_io
, fptr
);
9639 rb_fd_set(fptr
->fd
, &fds
[1]);
9640 if (max
< fptr
->fd
) max
= fptr
->fd
;
9647 if (!NIL_P(except
)) {
9648 Check_Type(except
, T_ARRAY
);
9649 for (i
=0; i
<RARRAY_LEN(except
); i
++) {
9650 VALUE io
= rb_io_get_io(RARRAY_AREF(except
, i
));
9651 VALUE write_io
= GetWriteIO(io
);
9652 GetOpenFile(io
, fptr
);
9653 rb_fd_set(fptr
->fd
, &fds
[2]);
9654 if (max
< fptr
->fd
) max
= fptr
->fd
;
9655 if (io
!= write_io
) {
9656 GetOpenFile(write_io
, fptr
);
9657 rb_fd_set(fptr
->fd
, &fds
[2]);
9658 if (max
< fptr
->fd
) max
= fptr
->fd
;
9669 n
= rb_thread_fd_select(max
, rp
, wp
, ep
, tp
);
9673 if (!pending
&& n
== 0) return Qnil
; /* returns nil on timeout */
9675 res
= rb_ary_new2(3);
9676 rb_ary_push(res
, rp
?rb_ary_new():rb_ary_new2(0));
9677 rb_ary_push(res
, wp
?rb_ary_new():rb_ary_new2(0));
9678 rb_ary_push(res
, ep
?rb_ary_new():rb_ary_new2(0));
9681 list
= RARRAY_AREF(res
, 0);
9682 for (i
=0; i
< RARRAY_LEN(read
); i
++) {
9683 VALUE obj
= rb_ary_entry(read
, i
);
9684 VALUE io
= rb_io_get_io(obj
);
9685 GetOpenFile(io
, fptr
);
9686 if (rb_fd_isset(fptr
->fd
, &fds
[0]) ||
9687 rb_fd_isset(fptr
->fd
, &fds
[3])) {
9688 rb_ary_push(list
, obj
);
9694 list
= RARRAY_AREF(res
, 1);
9695 for (i
=0; i
< RARRAY_LEN(write
); i
++) {
9696 VALUE obj
= rb_ary_entry(write
, i
);
9697 VALUE io
= rb_io_get_io(obj
);
9698 VALUE write_io
= GetWriteIO(io
);
9699 GetOpenFile(write_io
, fptr
);
9700 if (rb_fd_isset(fptr
->fd
, &fds
[1])) {
9701 rb_ary_push(list
, obj
);
9707 list
= RARRAY_AREF(res
, 2);
9708 for (i
=0; i
< RARRAY_LEN(except
); i
++) {
9709 VALUE obj
= rb_ary_entry(except
, i
);
9710 VALUE io
= rb_io_get_io(obj
);
9711 VALUE write_io
= GetWriteIO(io
);
9712 GetOpenFile(io
, fptr
);
9713 if (rb_fd_isset(fptr
->fd
, &fds
[2])) {
9714 rb_ary_push(list
, obj
);
9716 else if (io
!= write_io
) {
9717 GetOpenFile(write_io
, fptr
);
9718 if (rb_fd_isset(fptr
->fd
, &fds
[2])) {
9719 rb_ary_push(list
, obj
);
9725 return res
; /* returns an empty array on interrupt */
9728 struct select_args
{
9729 VALUE read
, write
, except
;
9730 struct timeval
*timeout
;
9731 rb_fdset_t fdsets
[4];
9735 select_call(VALUE arg
)
9737 struct select_args
*p
= (struct select_args
*)arg
;
9739 return select_internal(p
->read
, p
->write
, p
->except
, p
->timeout
, p
->fdsets
);
9743 select_end(VALUE arg
)
9745 struct select_args
*p
= (struct select_args
*)arg
;
9748 for (i
= 0; i
< numberof(p
->fdsets
); ++i
)
9749 rb_fd_term(&p
->fdsets
[i
]);
9753 static VALUE sym_normal
, sym_sequential
, sym_random
,
9754 sym_willneed
, sym_dontneed
, sym_noreuse
;
9756 #ifdef HAVE_POSIX_FADVISE
9757 struct io_advise_struct
{
9765 io_advise_internal(void *arg
)
9767 struct io_advise_struct
*ptr
= arg
;
9768 return posix_fadvise(ptr
->fd
, ptr
->offset
, ptr
->len
, ptr
->advice
);
9772 io_advise_sym_to_const(VALUE sym
)
9774 #ifdef POSIX_FADV_NORMAL
9775 if (sym
== sym_normal
)
9776 return INT2NUM(POSIX_FADV_NORMAL
);
9779 #ifdef POSIX_FADV_RANDOM
9780 if (sym
== sym_random
)
9781 return INT2NUM(POSIX_FADV_RANDOM
);
9784 #ifdef POSIX_FADV_SEQUENTIAL
9785 if (sym
== sym_sequential
)
9786 return INT2NUM(POSIX_FADV_SEQUENTIAL
);
9789 #ifdef POSIX_FADV_WILLNEED
9790 if (sym
== sym_willneed
)
9791 return INT2NUM(POSIX_FADV_WILLNEED
);
9794 #ifdef POSIX_FADV_DONTNEED
9795 if (sym
== sym_dontneed
)
9796 return INT2NUM(POSIX_FADV_DONTNEED
);
9799 #ifdef POSIX_FADV_NOREUSE
9800 if (sym
== sym_noreuse
)
9801 return INT2NUM(POSIX_FADV_NOREUSE
);
9808 do_io_advise(rb_io_t
*fptr
, VALUE advice
, off_t offset
, off_t len
)
9811 struct io_advise_struct ias
;
9814 num_adv
= io_advise_sym_to_const(advice
);
9817 * The platform doesn't support this hint. We don't raise exception, instead
9818 * silently ignore it. Because IO::advise is only hint.
9824 ias
.advice
= NUM2INT(num_adv
);
9825 ias
.offset
= offset
;
9828 rv
= (int)rb_thread_io_blocking_region(io_advise_internal
, &ias
, fptr
->fd
);
9829 if (rv
&& rv
!= ENOSYS
) {
9830 /* posix_fadvise(2) doesn't set errno. On success it returns 0; otherwise
9831 it returns the error code. */
9832 VALUE message
= rb_sprintf("%"PRIsVALUE
" "
9833 "(%"PRI_OFFT_PREFIX
"d, "
9834 "%"PRI_OFFT_PREFIX
"d, "
9836 fptr
->pathv
, offset
, len
, advice
);
9837 rb_syserr_fail_str(rv
, message
);
9843 #endif /* HAVE_POSIX_FADVISE */
9846 advice_arg_check(VALUE advice
)
9848 if (!SYMBOL_P(advice
))
9849 rb_raise(rb_eTypeError
, "advice must be a Symbol");
9851 if (advice
!= sym_normal
&&
9852 advice
!= sym_sequential
&&
9853 advice
!= sym_random
&&
9854 advice
!= sym_willneed
&&
9855 advice
!= sym_dontneed
&&
9856 advice
!= sym_noreuse
) {
9857 rb_raise(rb_eNotImpError
, "Unsupported advice: %+"PRIsVALUE
, advice
);
9863 * ios.advise(advice, offset=0, len=0) -> nil
9865 * Announce an intention to access data from the current file in a
9866 * specific pattern. On platforms that do not support the
9867 * <em>posix_fadvise(2)</em> system call, this method is a no-op.
9869 * _advice_ is one of the following symbols:
9871 * :normal:: No advice to give; the default assumption for an open file.
9872 * :sequential:: The data will be accessed sequentially
9873 * with lower offsets read before higher ones.
9874 * :random:: The data will be accessed in random order.
9875 * :willneed:: The data will be accessed in the near future.
9876 * :dontneed:: The data will not be accessed in the near future.
9877 * :noreuse:: The data will only be accessed once.
9879 * The semantics of a piece of advice are platform-dependent. See
9880 * <em>man 2 posix_fadvise</em> for details.
9882 * "data" means the region of the current file that begins at
9883 * _offset_ and extends for _len_ bytes. If _len_ is 0, the region
9884 * ends at the last byte of the file. By default, both _offset_ and
9885 * _len_ are 0, meaning that the advice applies to the entire file.
9887 * If an error occurs, one of the following exceptions will be raised:
9889 * IOError:: The IO stream is closed.
9891 * The file descriptor of the current file is invalid.
9892 * Errno::EINVAL:: An invalid value for _advice_ was given.
9894 * The file descriptor of the current file refers to a FIFO or
9895 * pipe. (Linux raises Errno::EINVAL in this case).
9897 * Either _advice_ was not a Symbol, or one of the
9898 * other arguments was not an Integer.
9899 * RangeError:: One of the arguments given was too big/small.
9901 * This list is not exhaustive; other Errno:: exceptions are also possible.
9904 rb_io_advise(int argc
, VALUE
*argv
, VALUE io
)
9906 VALUE advice
, offset
, len
;
9910 rb_scan_args(argc
, argv
, "12", &advice
, &offset
, &len
);
9911 advice_arg_check(advice
);
9913 io
= GetWriteIO(io
);
9914 GetOpenFile(io
, fptr
);
9916 off
= NIL_P(offset
) ? 0 : NUM2OFFT(offset
);
9917 l
= NIL_P(len
) ? 0 : NUM2OFFT(len
);
9919 #ifdef HAVE_POSIX_FADVISE
9920 return do_io_advise(fptr
, advice
, off
, l
);
9922 ((void)off
, (void)l
); /* Ignore all hint */
9929 * IO.select(read_array [, write_array [, error_array [, timeout]]]) -> array or nil
9931 * Calls select(2) system call.
9932 * It monitors given arrays of IO objects, waits until one or more of
9933 * IO objects are ready for reading, are ready for writing, and have
9934 * pending exceptions respectively, and returns an array that contains
9935 * arrays of those IO objects. It will return +nil+ if optional
9936 * <i>timeout</i> value is given and no IO object is ready in
9937 * <i>timeout</i> seconds.
9939 * IO.select peeks the buffer of IO objects for testing readability.
9940 * If the IO buffer is not empty, IO.select immediately notifies
9941 * readability. This "peek" only happens for IO objects. It does not
9942 * happen for IO-like objects such as OpenSSL::SSL::SSLSocket.
9944 * The best way to use IO.select is invoking it after nonblocking
9945 * methods such as #read_nonblock, #write_nonblock, etc. The methods
9946 * raise an exception which is extended by IO::WaitReadable or
9947 * IO::WaitWritable. The modules notify how the caller should wait
9948 * with IO.select. If IO::WaitReadable is raised, the caller should
9949 * wait for reading. If IO::WaitWritable is raised, the caller should
9952 * So, blocking read (#readpartial) can be emulated using
9953 * #read_nonblock and IO.select as follows:
9956 * result = io_like.read_nonblock(maxlen)
9957 * rescue IO::WaitReadable
9958 * IO.select([io_like])
9960 * rescue IO::WaitWritable
9961 * IO.select(nil, [io_like])
9965 * Especially, the combination of nonblocking methods and IO.select is
9966 * preferred for IO like objects such as OpenSSL::SSL::SSLSocket. It
9967 * has #to_io method to return underlying IO object. IO.select calls
9968 * #to_io to obtain the file descriptor to wait.
9970 * This means that readability notified by IO.select doesn't mean
9971 * readability from OpenSSL::SSL::SSLSocket object.
9973 * The most likely situation is that OpenSSL::SSL::SSLSocket buffers
9974 * some data. IO.select doesn't see the buffer. So IO.select can
9975 * block when OpenSSL::SSL::SSLSocket#readpartial doesn't block.
9977 * However, several more complicated situations exist.
9979 * SSL is a protocol which is sequence of records.
9980 * The record consists of multiple bytes.
9981 * So, the remote side of SSL sends a partial record, IO.select
9982 * notifies readability but OpenSSL::SSL::SSLSocket cannot decrypt a
9983 * byte and OpenSSL::SSL::SSLSocket#readpartial will block.
9985 * Also, the remote side can request SSL renegotiation which forces
9986 * the local SSL engine to write some data.
9987 * This means OpenSSL::SSL::SSLSocket#readpartial may invoke #write
9988 * system call and it can block.
9989 * In such a situation, OpenSSL::SSL::SSLSocket#read_nonblock raises
9990 * IO::WaitWritable instead of blocking.
9991 * So, the caller should wait for ready for writability as above
9994 * The combination of nonblocking methods and IO.select is also useful
9995 * for streams such as tty, pipe socket socket when multiple processes
9996 * read from a stream.
9998 * Finally, Linux kernel developers don't guarantee that
9999 * readability of select(2) means readability of following read(2) even
10000 * for a single process.
10001 * See select(2) manual on GNU/Linux system.
10003 * Invoking IO.select before IO#readpartial works well as usual.
10004 * However it is not the best way to use IO.select.
10006 * The writability notified by select(2) doesn't show
10007 * how many bytes are writable.
10008 * IO#write method blocks until given whole string is written.
10009 * So, <code>IO#write(two or more bytes)</code> can block after
10010 * writability is notified by IO.select. IO#write_nonblock is required
10011 * to avoid the blocking.
10013 * Blocking write (#write) can be emulated using #write_nonblock and
10014 * IO.select as follows: IO::WaitReadable should also be rescued for
10015 * SSL renegotiation in OpenSSL::SSL::SSLSocket.
10017 * while 0 < string.bytesize
10019 * written = io_like.write_nonblock(string)
10020 * rescue IO::WaitReadable
10021 * IO.select([io_like])
10023 * rescue IO::WaitWritable
10024 * IO.select(nil, [io_like])
10027 * string = string.byteslice(written..-1)
10031 * read_array:: an array of IO objects that wait until ready for read
10032 * write_array:: an array of IO objects that wait until ready for write
10033 * error_array:: an array of IO objects that wait for exceptions
10034 * timeout:: a numeric value in second
10041 * # IO.select follows IO#read. Not the best way to use IO.select.
10042 * rs, ws, = IO.select([rp], [wp])
10058 * <em>produces:</em>
10068 rb_f_select(int argc
, VALUE
*argv
, VALUE obj
)
10071 struct select_args args
;
10072 struct timeval timerec
;
10075 rb_scan_args(argc
, argv
, "13", &args
.read
, &args
.write
, &args
.except
, &timeout
);
10076 if (NIL_P(timeout
)) {
10080 timerec
= rb_time_interval(timeout
);
10081 args
.timeout
= &timerec
;
10084 for (i
= 0; i
< numberof(args
.fdsets
); ++i
)
10085 rb_fd_init(&args
.fdsets
[i
]);
10087 return rb_ensure(select_call
, (VALUE
)&args
, select_end
, (VALUE
)&args
);
10090 #ifdef IOCTL_REQ_TYPE
10091 typedef IOCTL_REQ_TYPE ioctl_req_t
;
10093 typedef int ioctl_req_t
;
10094 # define NUM2IOCTLREQ(num) ((int)NUM2LONG(num))
10105 nogvl_ioctl(void *ptr
)
10107 struct ioctl_arg
*arg
= ptr
;
10109 return (VALUE
)ioctl(arg
->fd
, arg
->cmd
, arg
->narg
);
10113 do_ioctl(int fd
, ioctl_req_t cmd
, long narg
)
10116 struct ioctl_arg arg
;
10122 retval
= (int)rb_thread_io_blocking_region(nogvl_ioctl
, &arg
, fd
);
10128 #define DEFAULT_IOCTL_NARG_LEN (256)
10130 #if defined(__linux__) && defined(_IOC_SIZE)
10132 linux_iocparm_len(ioctl_req_t cmd
)
10136 if ((cmd
& 0xFFFF0000) == 0) {
10137 /* legacy and unstructured ioctl number. */
10138 return DEFAULT_IOCTL_NARG_LEN
;
10141 len
= _IOC_SIZE(cmd
);
10143 /* paranoia check for silly drivers which don't keep ioctl convention */
10144 if (len
< DEFAULT_IOCTL_NARG_LEN
)
10145 len
= DEFAULT_IOCTL_NARG_LEN
;
10152 ioctl_narg_len(ioctl_req_t cmd
)
10156 #ifdef IOCPARM_MASK
10157 #ifndef IOCPARM_LEN
10158 #define IOCPARM_LEN(x) (((x) >> 16) & IOCPARM_MASK)
10162 len
= IOCPARM_LEN(cmd
); /* on BSDish systems we're safe */
10163 #elif defined(__linux__) && defined(_IOC_SIZE)
10164 len
= linux_iocparm_len(cmd
);
10166 /* otherwise guess at what's safe */
10167 len
= DEFAULT_IOCTL_NARG_LEN
;
10175 typedef long fcntl_arg_t
;
10178 typedef int fcntl_arg_t
;
10182 fcntl_narg_len(ioctl_req_t cmd
)
10189 len
= sizeof(fcntl_arg_t
);
10192 #ifdef F_DUP2FD /* bsd specific */
10197 #ifdef F_DUPFD_CLOEXEC /* linux specific */
10198 case F_DUPFD_CLOEXEC
:
10199 len
= sizeof(fcntl_arg_t
);
10209 len
= sizeof(fcntl_arg_t
);
10219 len
= sizeof(fcntl_arg_t
);
10229 len
= sizeof(fcntl_arg_t
);
10232 #ifdef F_GETOWN_EX /* linux specific */
10234 len
= sizeof(struct f_owner_ex
);
10237 #ifdef F_SETOWN_EX /* linux specific */
10239 len
= sizeof(struct f_owner_ex
);
10244 len
= sizeof(struct flock
);
10249 len
= sizeof(struct flock
);
10254 len
= sizeof(struct flock
);
10257 #ifdef F_READAHEAD /* bsd specific */
10262 #ifdef F_RDAHEAD /* Darwin specific */
10267 #ifdef F_GETSIG /* linux specific */
10272 #ifdef F_SETSIG /* linux specific */
10274 len
= sizeof(fcntl_arg_t
);
10277 #ifdef F_GETLEASE /* linux specific */
10282 #ifdef F_SETLEASE /* linux specific */
10284 len
= sizeof(fcntl_arg_t
);
10287 #ifdef F_NOTIFY /* linux specific */
10289 len
= sizeof(fcntl_arg_t
);
10300 #else /* HAVE_FCNTL */
10302 fcntl_narg_len(ioctl_req_t cmd
)
10306 #endif /* HAVE_FCNTL */
10308 #define NARG_SENTINEL 17
10311 setup_narg(ioctl_req_t cmd
, VALUE
*argp
, long (*narg_len
)(ioctl_req_t
))
10319 else if (FIXNUM_P(arg
)) {
10320 narg
= FIX2LONG(arg
);
10322 else if (arg
== Qtrue
) {
10326 VALUE tmp
= rb_check_string_type(arg
);
10329 narg
= NUM2LONG(arg
);
10336 len
= narg_len(cmd
);
10337 rb_str_modify(arg
);
10339 slen
= RSTRING_LEN(arg
);
10340 /* expand for data + sentinel. */
10341 if (slen
< len
+1) {
10342 rb_str_resize(arg
, len
+1);
10343 MEMZERO(RSTRING_PTR(arg
)+slen
, char, len
-slen
);
10346 /* a little sanity check here */
10347 ptr
= RSTRING_PTR(arg
);
10348 ptr
[slen
- 1] = NARG_SENTINEL
;
10349 narg
= (long)(SIGNED_VALUE
)ptr
;
10357 finish_narg(int retval
, VALUE arg
, const rb_io_t
*fptr
)
10359 if (retval
< 0) rb_sys_fail_path(fptr
->pathv
);
10360 if (RB_TYPE_P(arg
, T_STRING
)) {
10363 RSTRING_GETMEM(arg
, ptr
, slen
);
10364 if (ptr
[slen
-1] != NARG_SENTINEL
)
10365 rb_raise(rb_eArgError
, "return value overflowed string");
10366 ptr
[slen
-1] = '\0';
10369 return INT2NUM(retval
);
10374 rb_ioctl(VALUE io
, VALUE req
, VALUE arg
)
10376 ioctl_req_t cmd
= NUM2IOCTLREQ(req
);
10381 narg
= setup_narg(cmd
, &arg
, ioctl_narg_len
);
10382 GetOpenFile(io
, fptr
);
10383 retval
= do_ioctl(fptr
->fd
, cmd
, narg
);
10384 return finish_narg(retval
, arg
, fptr
);
10389 * ios.ioctl(integer_cmd, arg) -> integer
10391 * Provides a mechanism for issuing low-level commands to control or
10392 * query I/O devices. Arguments and results are platform dependent. If
10393 * <i>arg</i> is a number, its value is passed directly. If it is a
10394 * string, it is interpreted as a binary sequence of bytes. On Unix
10395 * platforms, see <code>ioctl(2)</code> for details. Not implemented on
10400 rb_io_ioctl(int argc
, VALUE
*argv
, VALUE io
)
10404 rb_scan_args(argc
, argv
, "11", &req
, &arg
);
10405 return rb_ioctl(io
, req
, arg
);
10408 #define rb_io_ioctl rb_f_notimplement
10419 nogvl_fcntl(void *ptr
)
10421 struct fcntl_arg
*arg
= ptr
;
10423 #if defined(F_DUPFD)
10424 if (arg
->cmd
== F_DUPFD
)
10425 return (VALUE
)rb_cloexec_fcntl_dupfd(arg
->fd
, (int)arg
->narg
);
10427 return (VALUE
)fcntl(arg
->fd
, arg
->cmd
, arg
->narg
);
10431 do_fcntl(int fd
, int cmd
, long narg
)
10434 struct fcntl_arg arg
;
10440 retval
= (int)rb_thread_io_blocking_region(nogvl_fcntl
, &arg
, fd
);
10441 if (retval
!= -1) {
10443 #if defined(F_DUPFD)
10446 #if defined(F_DUPFD_CLOEXEC)
10447 case F_DUPFD_CLOEXEC
:
10449 rb_update_max_fd(retval
);
10457 rb_fcntl(VALUE io
, VALUE req
, VALUE arg
)
10459 int cmd
= NUM2INT(req
);
10464 narg
= setup_narg(cmd
, &arg
, fcntl_narg_len
);
10465 GetOpenFile(io
, fptr
);
10466 retval
= do_fcntl(fptr
->fd
, cmd
, narg
);
10467 return finish_narg(retval
, arg
, fptr
);
10472 * ios.fcntl(integer_cmd, arg) -> integer
10474 * Provides a mechanism for issuing low-level commands to control or
10475 * query file-oriented I/O streams. Arguments and results are platform
10476 * dependent. If <i>arg</i> is a number, its value is passed
10477 * directly. If it is a string, it is interpreted as a binary sequence
10478 * of bytes (Array#pack might be a useful way to build this string). On
10479 * Unix platforms, see <code>fcntl(2)</code> for details. Not
10480 * implemented on all platforms.
10484 rb_io_fcntl(int argc
, VALUE
*argv
, VALUE io
)
10488 rb_scan_args(argc
, argv
, "11", &req
, &arg
);
10489 return rb_fcntl(io
, req
, arg
);
10492 #define rb_io_fcntl rb_f_notimplement
10495 #if defined(HAVE_SYSCALL) || defined(HAVE___SYSCALL)
10498 * syscall(num [, args...]) -> integer
10500 * Calls the operating system function identified by _num_ and
10501 * returns the result of the function or raises SystemCallError if
10504 * Arguments for the function can follow _num_. They must be either
10505 * +String+ objects or +Integer+ objects. A +String+ object is passed
10506 * as a pointer to the byte sequence. An +Integer+ object is passed
10507 * as an integer whose bit size is the same as a pointer.
10508 * Up to nine parameters may be passed.
10510 * The function identified by _num_ is system
10511 * dependent. On some Unix systems, the numbers may be obtained from a
10512 * header file called <code>syscall.h</code>.
10514 * syscall 4, 1, "hello\n", 6 # '4' is write(2) on our box
10516 * <em>produces:</em>
10520 * Calling +syscall+ on a platform which does not have any way to
10521 * an arbitrary system function just fails with NotImplementedError.
10524 * +syscall+ is essentially unsafe and unportable.
10525 * Feel free to shoot your foot.
10526 * The DL (Fiddle) library is preferred for safer and a bit
10527 * more portable programming.
10531 rb_f_syscall(int argc
, VALUE
*argv
, VALUE _
)
10534 #if SIZEOF_VOIDP == 8 && defined(HAVE___SYSCALL) && SIZEOF_INT != 8 /* mainly *BSD */
10535 # define SYSCALL __syscall
10536 # define NUM2SYSCALLID(x) NUM2LONG(x)
10537 # define RETVAL2NUM(x) LONG2NUM(x)
10538 # if SIZEOF_LONG == 8
10539 long num
, retval
= -1;
10540 # elif SIZEOF_LONG_LONG == 8
10541 long long num
, retval
= -1;
10543 # error ---->> it is asserted that __syscall takes the first argument and returns retval in 64bit signed integer. <<----
10545 #elif defined(__linux__)
10546 # define SYSCALL syscall
10547 # define NUM2SYSCALLID(x) NUM2LONG(x)
10548 # define RETVAL2NUM(x) LONG2NUM(x)
10550 * Linux man page says, syscall(2) function prototype is below.
10552 * int syscall(int number, ...);
10554 * But, it's incorrect. Actual one takes and returned long. (see unistd.h)
10556 long num
, retval
= -1;
10558 # define SYSCALL syscall
10559 # define NUM2SYSCALLID(x) NUM2INT(x)
10560 # define RETVAL2NUM(x) INT2NUM(x)
10561 int num
, retval
= -1;
10565 if (RTEST(ruby_verbose
)) {
10566 rb_category_warning(RB_WARN_CATEGORY_DEPRECATED
,
10567 "We plan to remove a syscall function at future release. DL(Fiddle) provides safer alternative.");
10571 rb_raise(rb_eArgError
, "too few arguments for syscall");
10572 if (argc
> numberof(arg
))
10573 rb_raise(rb_eArgError
, "too many arguments for syscall");
10574 num
= NUM2SYSCALLID(argv
[0]); ++argv
;
10575 for (i
= argc
- 1; i
--; ) {
10576 VALUE v
= rb_check_string_type(argv
[i
]);
10579 SafeStringValue(v
);
10581 arg
[i
] = (VALUE
)StringValueCStr(v
);
10584 arg
[i
] = (VALUE
)NUM2LONG(argv
[i
]);
10590 retval
= SYSCALL(num
);
10593 retval
= SYSCALL(num
, arg
[0]);
10596 retval
= SYSCALL(num
, arg
[0],arg
[1]);
10599 retval
= SYSCALL(num
, arg
[0],arg
[1],arg
[2]);
10602 retval
= SYSCALL(num
, arg
[0],arg
[1],arg
[2],arg
[3]);
10605 retval
= SYSCALL(num
, arg
[0],arg
[1],arg
[2],arg
[3],arg
[4]);
10608 retval
= SYSCALL(num
, arg
[0],arg
[1],arg
[2],arg
[3],arg
[4],arg
[5]);
10611 retval
= SYSCALL(num
, arg
[0],arg
[1],arg
[2],arg
[3],arg
[4],arg
[5],arg
[6]);
10617 return RETVAL2NUM(retval
);
10619 #undef NUM2SYSCALLID
10623 #define rb_f_syscall rb_f_notimplement
10627 io_new_instance(VALUE args
)
10629 return rb_class_new_instance(2, (VALUE
*)args
+1, *(VALUE
*)args
);
10632 static rb_encoding
*
10633 find_encoding(VALUE v
)
10635 rb_encoding
*enc
= rb_find_encoding(v
);
10636 if (!enc
) rb_warn("Unsupported encoding %"PRIsVALUE
" ignored", v
);
10641 io_encoding_set(rb_io_t
*fptr
, VALUE v1
, VALUE v2
, VALUE opt
)
10643 rb_encoding
*enc
, *enc2
;
10644 int ecflags
= fptr
->encs
.ecflags
;
10648 enc2
= find_encoding(v1
);
10649 tmp
= rb_check_string_type(v2
);
10651 if (RSTRING_LEN(tmp
) == 1 && RSTRING_PTR(tmp
)[0] == '-') {
10652 /* Special case - "-" => no transcoding */
10657 enc
= find_encoding(v2
);
10659 /* Special case - "-" => no transcoding */
10664 enc
= find_encoding(v2
);
10666 /* Special case - "-" => no transcoding */
10670 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2
, ecflags
);
10671 ecflags
= rb_econv_prepare_options(opt
, &ecopts
, ecflags
);
10675 /* Set to default encodings */
10676 rb_io_ext_int_to_encs(NULL
, NULL
, &enc
, &enc2
, 0);
10677 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2
, ecflags
);
10681 tmp
= rb_check_string_type(v1
);
10682 if (!NIL_P(tmp
) && rb_enc_asciicompat(enc
= rb_enc_get(tmp
))) {
10683 parse_mode_enc(RSTRING_PTR(tmp
), enc
, &enc
, &enc2
, NULL
);
10684 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2
, ecflags
);
10685 ecflags
= rb_econv_prepare_options(opt
, &ecopts
, ecflags
);
10688 rb_io_ext_int_to_encs(find_encoding(v1
), NULL
, &enc
, &enc2
, 0);
10689 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2
, ecflags
);
10694 validate_enc_binmode(&fptr
->mode
, ecflags
, enc
, enc2
);
10695 fptr
->encs
.enc
= enc
;
10696 fptr
->encs
.enc2
= enc2
;
10697 fptr
->encs
.ecflags
= ecflags
;
10698 fptr
->encs
.ecopts
= ecopts
;
10699 clear_codeconv(fptr
);
10703 struct io_encoding_set_args
{
10711 io_encoding_set_v(VALUE v
)
10713 struct io_encoding_set_args
*arg
= (struct io_encoding_set_args
*)v
;
10714 io_encoding_set(arg
->fptr
, arg
->v1
, arg
->v2
, arg
->opt
);
10719 pipe_pair_close(VALUE rw
)
10721 VALUE
*rwp
= (VALUE
*)rw
;
10722 return rb_ensure(io_close
, rwp
[0], io_close
, rwp
[1]);
10727 * IO.pipe -> [read_io, write_io]
10728 * IO.pipe(ext_enc) -> [read_io, write_io]
10729 * IO.pipe("ext_enc:int_enc" [, opt]) -> [read_io, write_io]
10730 * IO.pipe(ext_enc, int_enc [, opt]) -> [read_io, write_io]
10732 * IO.pipe(...) {|read_io, write_io| ... }
10734 * Creates a pair of pipe endpoints (connected to each other) and
10735 * returns them as a two-element array of IO objects:
10736 * <code>[</code> <i>read_io</i>, <i>write_io</i> <code>]</code>.
10738 * If a block is given, the block is called and
10739 * returns the value of the block.
10740 * <i>read_io</i> and <i>write_io</i> are sent to the block as arguments.
10741 * If read_io and write_io are not closed when the block exits, they are closed.
10742 * i.e. closing read_io and/or write_io doesn't cause an error.
10744 * Not available on all platforms.
10746 * If an encoding (encoding name or encoding object) is specified as an optional argument,
10747 * read string from pipe is tagged with the encoding specified.
10748 * If the argument is a colon separated two encoding names "A:B",
10749 * the read string is converted from encoding A (external encoding)
10750 * to encoding B (internal encoding), then tagged with B.
10751 * If two optional arguments are specified, those must be
10752 * encoding objects or encoding names,
10753 * and the first one is the external encoding,
10754 * and the second one is the internal encoding.
10755 * If the external encoding and the internal encoding is specified,
10756 * optional hash argument specify the conversion option.
10758 * In the example below, the two processes close the ends of the pipe
10759 * that they are not using. This is not just a cosmetic nicety. The
10760 * read end of a pipe will not generate an end of file condition if
10761 * there are any writers with the pipe still open. In the case of the
10762 * parent process, the <code>rd.read</code> will never return if it
10763 * does not first issue a <code>wr.close</code>.
10769 * puts "Parent got: <#{rd.read}>"
10774 * puts "Sending message to parent"
10775 * wr.write "Hi Dad"
10779 * <em>produces:</em>
10781 * Sending message to parent
10782 * Parent got: <Hi Dad>
10786 rb_io_s_pipe(int argc
, VALUE
*argv
, VALUE klass
)
10788 int pipes
[2], state
;
10789 VALUE r
, w
, args
[3], v1
, v2
;
10791 rb_io_t
*fptr
, *fptr2
;
10792 struct io_encoding_set_args ies_args
;
10796 argc
= rb_scan_args(argc
, argv
, "02:", &v1
, &v2
, &opt
);
10797 if (rb_pipe(pipes
) < 0)
10801 args
[1] = INT2NUM(pipes
[0]);
10802 args
[2] = INT2FIX(O_RDONLY
);
10803 r
= rb_protect(io_new_instance
, (VALUE
)args
, &state
);
10807 rb_jump_tag(state
);
10809 GetOpenFile(r
, fptr
);
10811 ies_args
.fptr
= fptr
;
10814 ies_args
.opt
= opt
;
10815 rb_protect(io_encoding_set_v
, (VALUE
)&ies_args
, &state
);
10819 rb_jump_tag(state
);
10822 args
[1] = INT2NUM(pipes
[1]);
10823 args
[2] = INT2FIX(O_WRONLY
);
10824 w
= rb_protect(io_new_instance
, (VALUE
)args
, &state
);
10827 if (!NIL_P(r
)) rb_io_close(r
);
10828 rb_jump_tag(state
);
10830 GetOpenFile(w
, fptr2
);
10831 rb_io_synchronized(fptr2
);
10833 extract_binmode(opt
, &fmode
);
10835 if ((fmode
& FMODE_BINMODE
) && NIL_P(v1
)) {
10836 rb_io_ascii8bit_binmode(r
);
10837 rb_io_ascii8bit_binmode(w
);
10840 #if DEFAULT_TEXTMODE
10841 if ((fptr
->mode
& FMODE_TEXTMODE
) && (fmode
& FMODE_BINMODE
)) {
10842 fptr
->mode
&= ~FMODE_TEXTMODE
;
10843 setmode(fptr
->fd
, O_BINARY
);
10845 #if RUBY_CRLF_ENVIRONMENT
10846 if (fptr
->encs
.ecflags
& ECONV_DEFAULT_NEWLINE_DECORATOR
) {
10847 fptr
->encs
.ecflags
|= ECONV_UNIVERSAL_NEWLINE_DECORATOR
;
10851 fptr
->mode
|= fmode
;
10852 #if DEFAULT_TEXTMODE
10853 if ((fptr2
->mode
& FMODE_TEXTMODE
) && (fmode
& FMODE_BINMODE
)) {
10854 fptr2
->mode
&= ~FMODE_TEXTMODE
;
10855 setmode(fptr2
->fd
, O_BINARY
);
10858 fptr2
->mode
|= fmode
;
10860 ret
= rb_assoc_new(r
, w
);
10861 if (rb_block_given_p()) {
10865 return rb_ensure(rb_yield
, ret
, pipe_pair_close
, (VALUE
)rw
);
10870 struct foreach_arg
{
10877 open_key_args(VALUE klass
, int argc
, VALUE
*argv
, VALUE opt
, struct foreach_arg
*arg
)
10880 VALUE vmode
= Qnil
, vperm
= Qnil
;
10884 FilePathValue(path
);
10889 vmode
= INT2NUM(O_RDONLY
);
10890 vperm
= INT2FIX(0666);
10892 else if (!NIL_P(v
= rb_hash_aref(opt
, sym_open_args
))) {
10895 v
= rb_to_array_type(v
);
10896 n
= RARRAY_LENINT(v
);
10897 rb_check_arity(n
, 0, 3); /* rb_io_open */
10898 rb_scan_args_kw(RB_SCAN_ARGS_LAST_HASH_KEYWORDS
, n
, RARRAY_CONST_PTR(v
), "02:", &vmode
, &vperm
, &opt
);
10900 arg
->io
= rb_io_open(klass
, path
, vmode
, vperm
, opt
);
10904 io_s_foreach(VALUE v
)
10906 struct getline_arg
*arg
= (void *)v
;
10909 while (!NIL_P(str
= rb_io_getline_1(arg
->rs
, arg
->limit
, arg
->chomp
, arg
->io
))) {
10910 rb_lastline_set(str
);
10913 rb_lastline_set(Qnil
);
10919 * IO.foreach(name, sep=$/ [, getline_args, open_args]) {|line| block } -> nil
10920 * IO.foreach(name, limit [, getline_args, open_args]) {|line| block } -> nil
10921 * IO.foreach(name, sep, limit [, getline_args, open_args]) {|line| block } -> nil
10922 * IO.foreach(...) -> an_enumerator
10923 * File.foreach(name, sep=$/ [, getline_args, open_args]) {|line| block } -> nil
10924 * File.foreach(name, limit [, getline_args, open_args]) {|line| block } -> nil
10925 * File.foreach(name, sep, limit [, getline_args, open_args]) {|line| block } -> nil
10926 * File.foreach(...) -> an_enumerator
10928 * Executes the block for every line in the named I/O port, where lines
10929 * are separated by <em>sep</em>.
10931 * If no block is given, an enumerator is returned instead.
10933 * If +name+ starts with a pipe character (<code>"|"</code>) and the receiver
10934 * is the IO class, a subprocess is created in the same way as Kernel#open,
10935 * and its output is returned.
10936 * Consider to use File.foreach to disable the behavior of subprocess invocation.
10938 * File.foreach("testfile") {|x| print "GOT ", x }
10939 * IO.foreach("| cat testfile") {|x| print "GOT ", x }
10941 * <em>produces:</em>
10943 * GOT This is line one
10944 * GOT This is line two
10945 * GOT This is line three
10948 * If the last argument is a hash, it's the keyword argument to open.
10949 * See IO.readlines for details about getline_args.
10950 * And see also IO.read for details about open_args.
10955 rb_io_s_foreach(int argc
, VALUE
*argv
, VALUE self
)
10958 int orig_argc
= argc
;
10959 struct foreach_arg arg
;
10960 struct getline_arg garg
;
10962 argc
= rb_scan_args(argc
, argv
, "13:", NULL
, NULL
, NULL
, NULL
, &opt
);
10963 RETURN_ENUMERATOR(self
, orig_argc
, argv
);
10964 extract_getline_args(argc
-1, argv
+1, &garg
);
10965 open_key_args(self
, argc
, argv
, opt
, &arg
);
10966 if (NIL_P(arg
.io
)) return Qnil
;
10967 extract_getline_opts(opt
, &garg
);
10968 check_getline_args(&garg
.rs
, &garg
.limit
, garg
.io
= arg
.io
);
10969 return rb_ensure(io_s_foreach
, (VALUE
)&garg
, rb_io_close
, arg
.io
);
10973 io_s_readlines(VALUE v
)
10975 struct getline_arg
*arg
= (void *)v
;
10976 return io_readlines(arg
, arg
->io
);
10981 * IO.readlines(name, sep=$/ [, getline_args, open_args]) -> array
10982 * IO.readlines(name, limit [, getline_args, open_args]) -> array
10983 * IO.readlines(name, sep, limit [, getline_args, open_args]) -> array
10984 * File.readlines(name, sep=$/ [, getline_args, open_args]) -> array
10985 * File.readlines(name, limit [, getline_args, open_args]) -> array
10986 * File.readlines(name, sep, limit [, getline_args, open_args]) -> array
10988 * Reads the entire file specified by <i>name</i> as individual
10989 * lines, and returns those lines in an array. Lines are separated by
10992 * If +name+ starts with a pipe character (<code>"|"</code>) and the receiver
10993 * is the IO class, a subprocess is created in the same way as Kernel#open,
10994 * and its output is returned.
10995 * Consider to use File.readlines to disable the behavior of subprocess invocation.
10997 * a = File.readlines("testfile")
10998 * a[0] #=> "This is line one\n"
11000 * b = File.readlines("testfile", chomp: true)
11001 * b[0] #=> "This is line one"
11003 * IO.readlines("|ls -a") #=> [".\n", "..\n", ...]
11005 * If the last argument is a hash, it's the keyword argument to open.
11007 * === Options for getline
11009 * The options hash accepts the following keys:
11012 * When the optional +chomp+ keyword argument has a true value,
11013 * <code>\n</code>, <code>\r</code>, and <code>\r\n</code>
11014 * will be removed from the end of each line.
11016 * See also IO.read for details about +name+ and open_args.
11020 rb_io_s_readlines(int argc
, VALUE
*argv
, VALUE io
)
11023 struct foreach_arg arg
;
11024 struct getline_arg garg
;
11026 argc
= rb_scan_args(argc
, argv
, "13:", NULL
, NULL
, NULL
, NULL
, &opt
);
11027 extract_getline_args(argc
-1, argv
+1, &garg
);
11028 open_key_args(io
, argc
, argv
, opt
, &arg
);
11029 if (NIL_P(arg
.io
)) return Qnil
;
11030 extract_getline_opts(opt
, &garg
);
11031 check_getline_args(&garg
.rs
, &garg
.limit
, garg
.io
= arg
.io
);
11032 return rb_ensure(io_s_readlines
, (VALUE
)&garg
, rb_io_close
, arg
.io
);
11038 struct foreach_arg
*arg
= (void *)v
;
11039 return io_read(arg
->argc
, arg
->argv
, arg
->io
);
11049 seek_before_access(VALUE argp
)
11051 struct seek_arg
*arg
= (struct seek_arg
*)argp
;
11052 rb_io_binmode(arg
->io
);
11053 return rb_io_seek(arg
->io
, arg
->offset
, arg
->mode
);
11058 * IO.read(name, [length [, offset]] [, opt]) -> string
11059 * File.read(name, [length [, offset]] [, opt]) -> string
11061 * Opens the file, optionally seeks to the given +offset+, then returns
11062 * +length+ bytes (defaulting to the rest of the file). #read ensures
11063 * the file is closed before returning.
11065 * If +name+ starts with a pipe character (<code>"|"</code>) and the receiver
11066 * is the IO class, a subprocess is created in the same way as Kernel#open,
11067 * and its output is returned.
11068 * Consider to use File.read to disable the behavior of subprocess invocation.
11072 * The options hash accepts the following keys:
11075 * string or encoding
11077 * Specifies the encoding of the read string. +:encoding+ will be ignored
11078 * if +length+ is specified. See Encoding.aliases for possible encodings.
11081 * string or integer
11083 * Specifies the <i>mode</i> argument for open(). It must start
11084 * with an "r", otherwise it will cause an error.
11085 * See IO.new for the list of possible modes.
11090 * Specifies arguments for open() as an array. This key can not be used
11091 * in combination with either +:encoding+ or +:mode+.
11095 * File.read("testfile") #=> "This is line one\nThis is line two\nThis is line three\nAnd so on...\n"
11096 * File.read("testfile", 20) #=> "This is line one\nThi"
11097 * File.read("testfile", 20, 10) #=> "ne one\nThis is line "
11098 * File.read("binfile", mode: "rb") #=> "\xF7\x00\x00\x0E\x12"
11099 * IO.read("|ls -a") #=> ".\n..\n"...
11103 rb_io_s_read(int argc
, VALUE
*argv
, VALUE io
)
11106 struct foreach_arg arg
;
11108 argc
= rb_scan_args(argc
, argv
, "13:", NULL
, NULL
, &offset
, NULL
, &opt
);
11109 open_key_args(io
, argc
, argv
, opt
, &arg
);
11110 if (NIL_P(arg
.io
)) return Qnil
;
11111 if (!NIL_P(offset
)) {
11112 struct seek_arg sarg
;
11115 sarg
.offset
= offset
;
11116 sarg
.mode
= SEEK_SET
;
11117 rb_protect(seek_before_access
, (VALUE
)&sarg
, &state
);
11119 rb_io_close(arg
.io
);
11120 rb_jump_tag(state
);
11122 if (arg
.argc
== 2) arg
.argc
= 1;
11124 return rb_ensure(io_s_read
, (VALUE
)&arg
, rb_io_close
, arg
.io
);
11129 * IO.binread(name, [length [, offset]]) -> string
11130 * File.binread(name, [length [, offset]]) -> string
11132 * Opens the file, optionally seeks to the given <i>offset</i>, then
11133 * returns <i>length</i> bytes (defaulting to the rest of the file).
11134 * #binread ensures the file is closed before returning. The open mode
11135 * would be <code>"rb:ASCII-8BIT"</code>.
11137 * If +name+ starts with a pipe character (<code>"|"</code>) and the receiver
11138 * is the IO class, a subprocess is created in the same way as Kernel#open,
11139 * and its output is returned.
11140 * Consider to use File.binread to disable the behavior of subprocess invocation.
11142 * File.binread("testfile") #=> "This is line one\nThis is line two\nThis is line three\nAnd so on...\n"
11143 * File.binread("testfile", 20) #=> "This is line one\nThi"
11144 * File.binread("testfile", 20, 10) #=> "ne one\nThis is line "
11145 * IO.binread("| cat testfile") #=> "This is line one\nThis is line two\nThis is line three\nAnd so on...\n"
11147 * See also IO.read for details about +name+ and open_args.
11151 rb_io_s_binread(int argc
, VALUE
*argv
, VALUE io
)
11154 struct foreach_arg arg
;
11156 fmode
= FMODE_READABLE
|FMODE_BINMODE
,
11162 convconfig_t convconfig
= {NULL
, NULL
, 0, Qnil
};
11164 rb_scan_args(argc
, argv
, "12", NULL
, NULL
, &offset
);
11165 FilePathValue(argv
[0]);
11166 convconfig
.enc
= rb_ascii8bit_encoding();
11167 arg
.io
= rb_io_open_generic(io
, argv
[0], oflags
, fmode
, &convconfig
, 0);
11168 if (NIL_P(arg
.io
)) return Qnil
;
11170 arg
.argc
= (argc
> 1) ? 1 : 0;
11171 if (!NIL_P(offset
)) {
11172 struct seek_arg sarg
;
11175 sarg
.offset
= offset
;
11176 sarg
.mode
= SEEK_SET
;
11177 rb_protect(seek_before_access
, (VALUE
)&sarg
, &state
);
11179 rb_io_close(arg
.io
);
11180 rb_jump_tag(state
);
11183 return rb_ensure(io_s_read
, (VALUE
)&arg
, rb_io_close
, arg
.io
);
11187 io_s_write0(VALUE v
)
11189 struct write_arg
*arg
= (void *)v
;
11190 return io_write(arg
->io
,arg
->str
,arg
->nosync
);
11194 io_s_write(int argc
, VALUE
*argv
, VALUE klass
, int binary
)
11196 VALUE string
, offset
, opt
;
11197 struct foreach_arg arg
;
11198 struct write_arg warg
;
11200 rb_scan_args(argc
, argv
, "21:", NULL
, &string
, &offset
, &opt
);
11202 if (NIL_P(opt
)) opt
= rb_hash_new();
11203 else opt
= rb_hash_dup(opt
);
11206 if (NIL_P(rb_hash_aref(opt
,sym_mode
))) {
11207 int mode
= O_WRONLY
|O_CREAT
;
11209 if (binary
) mode
|= O_BINARY
;
11211 if (NIL_P(offset
)) mode
|= O_TRUNC
;
11212 rb_hash_aset(opt
,sym_mode
,INT2NUM(mode
));
11214 open_key_args(klass
, argc
, argv
, opt
, &arg
);
11217 if (binary
) rb_io_binmode_m(arg
.io
);
11220 if (NIL_P(arg
.io
)) return Qnil
;
11221 if (!NIL_P(offset
)) {
11222 struct seek_arg sarg
;
11225 sarg
.offset
= offset
;
11226 sarg
.mode
= SEEK_SET
;
11227 rb_protect(seek_before_access
, (VALUE
)&sarg
, &state
);
11229 rb_io_close(arg
.io
);
11230 rb_jump_tag(state
);
11238 return rb_ensure(io_s_write0
, (VALUE
)&warg
, rb_io_close
, arg
.io
);
11243 * IO.write(name, string [, offset]) -> integer
11244 * IO.write(name, string [, offset] [, opt]) -> integer
11245 * File.write(name, string [, offset]) -> integer
11246 * File.write(name, string [, offset] [, opt]) -> integer
11248 * Opens the file, optionally seeks to the given <i>offset</i>, writes
11249 * <i>string</i>, then returns the length written. #write ensures the
11250 * file is closed before returning. If <i>offset</i> is not given in
11251 * write mode, the file is truncated. Otherwise, it is not truncated.
11253 * If +name+ starts with a pipe character (<code>"|"</code>) and the receiver
11254 * is the IO class, a subprocess is created in the same way as Kernel#open,
11255 * and its output is returned.
11256 * Consider to use File.write to disable the behavior of subprocess invocation.
11258 * File.write("testfile", "0123456789", 20) #=> 10
11259 * # File could contain: "This is line one\nThi0123456789two\nThis is line three\nAnd so on...\n"
11260 * File.write("testfile", "0123456789") #=> 10
11261 * # File would now read: "0123456789"
11262 * IO.write("|tr a-z A-Z", "abc") #=> 3
11263 * # Prints "ABC" to the standard output
11265 * If the last argument is a hash, it specifies options for the internal
11266 * open(). It accepts the following keys:
11269 * string or encoding
11271 * Specifies the encoding of the read string.
11272 * See Encoding.aliases for possible encodings.
11275 * string or integer
11277 * Specifies the <i>mode</i> argument for open(). It must start
11278 * with "w", "a", or "r+", otherwise it will cause an error.
11279 * See IO.new for the list of possible modes.
11284 * Specifies the <i>perm</i> argument for open().
11289 * Specifies arguments for open() as an array.
11290 * This key can not be used in combination with other keys.
11292 * See also IO.read for details about +name+ and open_args.
11296 rb_io_s_write(int argc
, VALUE
*argv
, VALUE io
)
11298 return io_s_write(argc
, argv
, io
, 0);
11303 * IO.binwrite(name, string, [offset]) -> integer
11304 * IO.binwrite(name, string, [offset], open_args) -> integer
11305 * File.binwrite(name, string, [offset]) -> integer
11306 * File.binwrite(name, string, [offset], open_args) -> integer
11308 * Same as IO.write except opening the file in binary mode and
11309 * ASCII-8BIT encoding (<code>"wb:ASCII-8BIT"</code>).
11311 * If +name+ starts with a pipe character (<code>"|"</code>) and the receiver
11312 * is the IO class, a subprocess is created in the same way as Kernel#open,
11313 * and its output is returned.
11314 * Consider to use File.binwrite to disable the behavior of subprocess invocation.
11316 * See also IO.read for details about +name+ and open_args.
11320 rb_io_s_binwrite(int argc
, VALUE
*argv
, VALUE io
)
11322 return io_s_write(argc
, argv
, io
, 1);
11325 struct copy_stream_struct
{
11328 off_t copy_length
; /* (off_t)-1 if not specified */
11329 off_t src_offset
; /* (off_t)-1 if not specified */
11333 unsigned close_src
: 1;
11334 unsigned close_dst
: 1;
11337 const char *syserr
;
11338 const char *notimp
;
11340 struct stat src_stat
;
11341 struct stat dst_stat
;
11342 #ifdef HAVE_FCOPYFILE
11343 copyfile_state_t copyfile_state
;
11348 exec_interrupts(void *arg
)
11350 VALUE th
= (VALUE
)arg
;
11351 rb_thread_execute_interrupts(th
);
11356 * returns TRUE if the preceding system call was interrupted
11357 * so we can continue. If the thread was interrupted, we
11358 * reacquire the GVL to execute interrupts before continuing.
11361 maygvl_copy_stream_continue_p(int has_gvl
, struct copy_stream_struct
*stp
)
11365 #if defined(ERESTART)
11368 if (rb_thread_interrupted(stp
->th
)) {
11370 rb_thread_execute_interrupts(stp
->th
);
11372 rb_thread_call_with_gvl(exec_interrupts
, (void *)stp
->th
);
11379 struct wait_for_single_fd
{
11389 rb_thread_fiber_scheduler_wait_for(void * _args
)
11391 struct wait_for_single_fd
*args
= (struct wait_for_single_fd
*)_args
;
11393 args
->result
= rb_fiber_scheduler_io_wait(args
->scheduler
, args
->fptr
->self
, INT2NUM(args
->events
), Qnil
);
11399 # define IOWAIT_SYSCALL "poll"
11400 STATIC_ASSERT(pollin_expected
, POLLIN
== RB_WAITFD_IN
);
11401 STATIC_ASSERT(pollout_expected
, POLLOUT
== RB_WAITFD_OUT
);
11403 nogvl_wait_for(VALUE th
, rb_io_t
*fptr
, short events
)
11405 VALUE scheduler
= rb_fiber_scheduler_current_for_thread(th
);
11406 if (scheduler
!= Qnil
) {
11407 struct wait_for_single_fd args
= {.scheduler
= scheduler
, .fptr
= fptr
, .events
= events
};
11408 rb_thread_call_with_gvl(rb_thread_fiber_scheduler_wait_for
, &args
);
11409 return RTEST(args
.result
);
11413 if (fd
== -1) return 0;
11418 fds
.events
= events
;
11420 return poll(&fds
, 1, -1);
11422 #else /* !USE_POLL */
11423 # define IOWAIT_SYSCALL "select"
11425 nogvl_wait_for(VALUE th
, rb_io_t
*fptr
, short events
)
11427 VALUE scheduler
= rb_fiber_scheduler_current_for_thread(th
);
11428 if (scheduler
!= Qnil
) {
11429 struct wait_for_single_fd args
= {.scheduler
= scheduler
, .fptr
= fptr
, .events
= events
};
11430 rb_thread_call_with_gvl(rb_thread_fiber_scheduler_wait_for
, &args
);
11431 return RTEST(args
.result
);
11435 if (fd
== -1) return 0;
11441 rb_fd_set(fd
, &fds
);
11445 ret
= rb_fd_select(fd
+ 1, &fds
, 0, 0, 0);
11447 case RB_WAITFD_OUT
:
11448 ret
= rb_fd_select(fd
+ 1, 0, &fds
, 0, 0);
11451 VM_UNREACHABLE(nogvl_wait_for
);
11457 #endif /* !USE_POLL */
11460 maygvl_copy_stream_wait_read(int has_gvl
, struct copy_stream_struct
*stp
)
11466 ret
= RB_NUM2INT(rb_io_wait(stp
->src
, RB_INT2NUM(RUBY_IO_READABLE
), Qnil
));
11469 ret
= nogvl_wait_for(stp
->th
, stp
->src_fptr
, RB_WAITFD_IN
);
11471 } while (ret
< 0 && maygvl_copy_stream_continue_p(has_gvl
, stp
));
11474 stp
->syserr
= IOWAIT_SYSCALL
;
11475 stp
->error_no
= errno
;
11482 nogvl_copy_stream_wait_write(struct copy_stream_struct
*stp
)
11487 ret
= nogvl_wait_for(stp
->th
, stp
->dst_fptr
, RB_WAITFD_OUT
);
11488 } while (ret
< 0 && maygvl_copy_stream_continue_p(0, stp
));
11491 stp
->syserr
= IOWAIT_SYSCALL
;
11492 stp
->error_no
= errno
;
11498 #ifdef USE_COPY_FILE_RANGE
11501 simple_copy_file_range(int in_fd
, off_t
*in_offset
, int out_fd
, off_t
*out_offset
, size_t count
, unsigned int flags
)
11503 #ifdef HAVE_COPY_FILE_RANGE
11504 return copy_file_range(in_fd
, in_offset
, out_fd
, out_offset
, count
, flags
);
11506 return syscall(__NR_copy_file_range
, in_fd
, in_offset
, out_fd
, out_offset
, count
, flags
);
11511 nogvl_copy_file_range(struct copy_stream_struct
*stp
)
11515 off_t copy_length
, src_offset
, *src_offset_ptr
;
11517 if (!S_ISREG(stp
->src_stat
.st_mode
))
11520 src_size
= stp
->src_stat
.st_size
;
11521 src_offset
= stp
->src_offset
;
11522 if (src_offset
>= (off_t
)0) {
11523 src_offset_ptr
= &src_offset
;
11526 src_offset_ptr
= NULL
; /* if src_offset_ptr is NULL, then bytes are read from in_fd starting from the file offset */
11529 copy_length
= stp
->copy_length
;
11530 if (copy_length
< (off_t
)0) {
11531 if (src_offset
< (off_t
)0) {
11532 off_t current_offset
;
11534 current_offset
= lseek(stp
->src_fptr
->fd
, 0, SEEK_CUR
);
11535 if (current_offset
< (off_t
)0 && errno
) {
11536 stp
->syserr
= "lseek";
11537 stp
->error_no
= errno
;
11538 return (int)current_offset
;
11540 copy_length
= src_size
- current_offset
;
11543 copy_length
= src_size
- src_offset
;
11547 retry_copy_file_range
:
11548 # if SIZEOF_OFF_T > SIZEOF_SIZE_T
11549 /* we are limited by the 32-bit ssize_t return value on 32-bit */
11550 ss
= (copy_length
> (off_t
)SSIZE_MAX
) ? SSIZE_MAX
: (ssize_t
)copy_length
;
11552 ss
= (ssize_t
)copy_length
;
11554 ss
= simple_copy_file_range(stp
->src_fptr
->fd
, src_offset_ptr
, stp
->dst_fptr
->fd
, NULL
, ss
, 0);
11558 if (0 < copy_length
) {
11559 goto retry_copy_file_range
;
11563 if (maygvl_copy_stream_continue_p(0, stp
)) {
11564 goto retry_copy_file_range
;
11568 case EPERM
: /* copy_file_range(2) doesn't exist (may happen in
11569 docker container) */
11574 case EXDEV
: /* in_fd and out_fd are not on the same filesystem */
11578 #if EWOULDBLOCK != EAGAIN
11582 int ret
= nogvl_copy_stream_wait_write(stp
);
11583 if (ret
< 0) return ret
;
11585 goto retry_copy_file_range
;
11589 int flags
= fcntl(stp
->dst_fptr
->fd
, F_GETFL
);
11591 if (flags
!= -1 && flags
& O_APPEND
) {
11597 stp
->syserr
= "copy_file_range";
11598 stp
->error_no
= errno
;
11605 #ifdef HAVE_FCOPYFILE
11607 nogvl_fcopyfile(struct copy_stream_struct
*stp
)
11610 const off_t src_offset
= stp
->src_offset
;
11613 if (stp
->copy_length
>= (off_t
)0) {
11614 /* copy_length can't be specified in fcopyfile(3) */
11618 if (!S_ISREG(stp
->src_stat
.st_mode
))
11621 if (!S_ISREG(stp
->dst_stat
.st_mode
))
11623 if (lseek(stp
->dst_fptr
->fd
, 0, SEEK_CUR
) > (off_t
)0) /* if dst IO was already written */
11625 if (fcntl(stp
->dst_fptr
->fd
, F_GETFL
) & O_APPEND
) {
11626 /* fcopyfile(3) appends src IO to dst IO and then truncates
11627 * dst IO to src IO's original size. */
11628 off_t end
= lseek(stp
->dst_fptr
->fd
, 0, SEEK_END
);
11629 lseek(stp
->dst_fptr
->fd
, 0, SEEK_SET
);
11630 if (end
> (off_t
)0) return 0;
11633 if (src_offset
> (off_t
)0) {
11636 /* get current offset */
11638 cur
= lseek(stp
->src_fptr
->fd
, 0, SEEK_CUR
);
11639 if (cur
< (off_t
)0 && errno
) {
11640 stp
->error_no
= errno
;
11645 r
= lseek(stp
->src_fptr
->fd
, src_offset
, SEEK_SET
);
11646 if (r
< (off_t
)0 && errno
) {
11647 stp
->error_no
= errno
;
11652 stp
->copyfile_state
= copyfile_state_alloc(); /* this will be freed by copy_stream_finalize() */
11653 ret
= fcopyfile(stp
->src_fptr
->fd
, stp
->dst_fptr
->fd
, stp
->copyfile_state
, COPYFILE_DATA
);
11654 copyfile_state_get(stp
->copyfile_state
, COPYFILE_STATE_COPIED
, &ss
); /* get copied bytes */
11656 if (ret
== 0) { /* success */
11658 if (src_offset
> (off_t
)0) {
11662 r
= lseek(stp
->src_fptr
->fd
, cur
, SEEK_SET
);
11663 if (r
< (off_t
)0 && errno
) {
11664 stp
->error_no
= errno
;
11676 stp
->syserr
= "fcopyfile";
11677 stp
->error_no
= errno
;
11684 #ifdef HAVE_SENDFILE
11687 # define USE_SENDFILE
11689 # ifdef HAVE_SYS_SENDFILE_H
11690 # include <sys/sendfile.h>
11694 simple_sendfile(int out_fd
, int in_fd
, off_t
*offset
, off_t count
)
11696 return sendfile(out_fd
, in_fd
, offset
, (size_t)count
);
11699 # elif 0 /* defined(__FreeBSD__) || defined(__DragonFly__) */ || defined(__APPLE__)
11700 /* This runs on FreeBSD8.1 r30210, but sendfiles blocks its execution
11701 * without cpuset -l 0.
11703 # define USE_SENDFILE
11706 simple_sendfile(int out_fd
, int in_fd
, off_t
*offset
, off_t count
)
11709 off_t pos
= offset
? *offset
: lseek(in_fd
, 0, SEEK_CUR
);
11712 r
= sendfile(in_fd
, out_fd
, pos
, &count
, NULL
, 0);
11715 r
= sendfile(in_fd
, out_fd
, pos
, (size_t)count
, NULL
, &sbytes
, 0);
11717 if (r
!= 0 && sbytes
== 0) return r
;
11722 lseek(in_fd
, sbytes
, SEEK_CUR
);
11724 return (ssize_t
)sbytes
;
11731 #ifdef USE_SENDFILE
11733 nogvl_copy_stream_sendfile(struct copy_stream_struct
*stp
)
11741 if (!S_ISREG(stp
->src_stat
.st_mode
))
11744 src_size
= stp
->src_stat
.st_size
;
11746 if ((stp
->dst_stat
.st_mode
& S_IFMT
) != S_IFSOCK
)
11750 src_offset
= stp
->src_offset
;
11751 use_pread
= src_offset
>= (off_t
)0;
11753 copy_length
= stp
->copy_length
;
11754 if (copy_length
< (off_t
)0) {
11756 copy_length
= src_size
- src_offset
;
11760 cur
= lseek(stp
->src_fptr
->fd
, 0, SEEK_CUR
);
11761 if (cur
< (off_t
)0 && errno
) {
11762 stp
->syserr
= "lseek";
11763 stp
->error_no
= errno
;
11766 copy_length
= src_size
- cur
;
11771 # if SIZEOF_OFF_T > SIZEOF_SIZE_T
11772 /* we are limited by the 32-bit ssize_t return value on 32-bit */
11773 ss
= (copy_length
> (off_t
)SSIZE_MAX
) ? SSIZE_MAX
: (ssize_t
)copy_length
;
11775 ss
= (ssize_t
)copy_length
;
11778 ss
= simple_sendfile(stp
->dst_fptr
->fd
, stp
->src_fptr
->fd
, &src_offset
, ss
);
11781 ss
= simple_sendfile(stp
->dst_fptr
->fd
, stp
->src_fptr
->fd
, NULL
, ss
);
11786 if (0 < copy_length
) {
11787 goto retry_sendfile
;
11791 if (maygvl_copy_stream_continue_p(0, stp
))
11792 goto retry_sendfile
;
11799 /* some RedHat kernels may return EOPNOTSUP on an NFS mount.
11800 see also: [Feature #16965] */
11805 #if EWOULDBLOCK != EAGAIN
11812 * Linux requires stp->src_fptr->fd to be a mmap-able (regular) file,
11813 * select() reports regular files to always be "ready", so
11814 * there is no need to select() on it.
11815 * Other OSes may have the same limitation for sendfile() which
11816 * allow us to bypass maygvl_copy_stream_wait_read()...
11818 ret
= maygvl_copy_stream_wait_read(0, stp
);
11819 if (ret
< 0) return ret
;
11821 ret
= nogvl_copy_stream_wait_write(stp
);
11822 if (ret
< 0) return ret
;
11824 goto retry_sendfile
;
11826 stp
->syserr
= "sendfile";
11827 stp
->error_no
= errno
;
11835 maygvl_read(int has_gvl
, rb_io_t
*fptr
, void *buf
, size_t count
)
11838 return rb_read_internal(fptr
, buf
, count
);
11840 return read(fptr
->fd
, buf
, count
);
11844 maygvl_copy_stream_read(int has_gvl
, struct copy_stream_struct
*stp
, char *buf
, size_t len
, off_t offset
)
11848 if (offset
< (off_t
)0) {
11849 ss
= maygvl_read(has_gvl
, stp
->src_fptr
, buf
, len
);
11853 ss
= pread(stp
->src_fptr
->fd
, buf
, len
, offset
);
11855 stp
->notimp
= "pread";
11863 if (maygvl_copy_stream_continue_p(has_gvl
, stp
))
11867 #if EWOULDBLOCK != EAGAIN
11871 int ret
= maygvl_copy_stream_wait_read(has_gvl
, stp
);
11872 if (ret
< 0) return ret
;
11877 stp
->notimp
= "pread";
11881 stp
->syserr
= offset
< (off_t
)0 ? "read" : "pread";
11882 stp
->error_no
= errno
;
11888 nogvl_copy_stream_write(struct copy_stream_struct
*stp
, char *buf
, size_t len
)
11893 ss
= write(stp
->dst_fptr
->fd
, buf
+off
, len
);
11895 if (maygvl_copy_stream_continue_p(0, stp
))
11897 if (io_again_p(errno
)) {
11898 int ret
= nogvl_copy_stream_wait_write(stp
);
11899 if (ret
< 0) return ret
;
11902 stp
->syserr
= "write";
11903 stp
->error_no
= errno
;
11914 nogvl_copy_stream_read_write(struct copy_stream_struct
*stp
)
11925 copy_length
= stp
->copy_length
;
11926 use_eof
= copy_length
< (off_t
)0;
11927 src_offset
= stp
->src_offset
;
11928 use_pread
= src_offset
>= (off_t
)0;
11930 if (use_pread
&& stp
->close_src
) {
11933 r
= lseek(stp
->src_fptr
->fd
, src_offset
, SEEK_SET
);
11934 if (r
< (off_t
)0 && errno
) {
11935 stp
->syserr
= "lseek";
11936 stp
->error_no
= errno
;
11939 src_offset
= (off_t
)-1;
11943 while (use_eof
|| 0 < copy_length
) {
11944 if (!use_eof
&& copy_length
< (off_t
)sizeof(buf
)) {
11945 len
= (size_t)copy_length
;
11951 ss
= maygvl_copy_stream_read(0, stp
, buf
, len
, src_offset
);
11956 ss
= maygvl_copy_stream_read(0, stp
, buf
, len
, (off_t
)-1);
11958 if (ss
<= 0) /* EOF or error */
11961 ret
= nogvl_copy_stream_write(stp
, buf
, ss
);
11971 nogvl_copy_stream_func(void *arg
)
11973 struct copy_stream_struct
*stp
= (struct copy_stream_struct
*)arg
;
11974 #if defined(USE_SENDFILE) || defined(USE_COPY_FILE_RANGE) || defined(HAVE_FCOPYFILE)
11978 #ifdef USE_COPY_FILE_RANGE
11979 ret
= nogvl_copy_file_range(stp
);
11981 goto finish
; /* error or success */
11984 #ifdef HAVE_FCOPYFILE
11985 ret
= nogvl_fcopyfile(stp
);
11987 goto finish
; /* error or success */
11990 #ifdef USE_SENDFILE
11991 ret
= nogvl_copy_stream_sendfile(stp
);
11993 goto finish
; /* error or success */
11996 nogvl_copy_stream_read_write(stp
);
11998 #if defined(USE_SENDFILE) || defined(USE_COPY_FILE_RANGE) || defined(HAVE_FCOPYFILE)
12005 copy_stream_fallback_body(VALUE arg
)
12007 struct copy_stream_struct
*stp
= (struct copy_stream_struct
*)arg
;
12008 const int buflen
= 16*1024;
12010 VALUE buf
= rb_str_buf_new(buflen
);
12011 off_t rest
= stp
->copy_length
;
12012 off_t off
= stp
->src_offset
;
12013 ID read_method
= id_readpartial
;
12015 if (!stp
->src_fptr
) {
12016 if (!rb_respond_to(stp
->src
, read_method
)) {
12017 read_method
= id_read
;
12024 if (stp
->copy_length
< (off_t
)0) {
12029 rb_str_resize(buf
, 0);
12032 l
= buflen
< rest
? buflen
: (long)rest
;
12034 if (!stp
->src_fptr
) {
12035 VALUE rc
= rb_funcall(stp
->src
, read_method
, 2, INT2FIX(l
), buf
);
12037 if (read_method
== id_read
&& NIL_P(rc
))
12042 rb_str_resize(buf
, buflen
);
12043 ss
= maygvl_copy_stream_read(1, stp
, RSTRING_PTR(buf
), l
, off
);
12044 rb_str_resize(buf
, ss
> 0 ? ss
: 0);
12049 if (off
>= (off_t
)0)
12052 n
= rb_io_write(stp
->dst
, buf
);
12053 numwrote
= NUM2LONG(n
);
12054 stp
->total
+= numwrote
;
12056 if (read_method
== id_read
&& RSTRING_LEN(buf
) == 0) {
12065 copy_stream_fallback(struct copy_stream_struct
*stp
)
12067 if (!stp
->src_fptr
&& stp
->src_offset
>= (off_t
)0) {
12068 rb_raise(rb_eArgError
, "cannot specify src_offset for non-IO");
12070 rb_rescue2(copy_stream_fallback_body
, (VALUE
)stp
,
12071 (VALUE (*) (VALUE
, VALUE
))0, (VALUE
)0,
12072 rb_eEOFError
, (VALUE
)0);
12077 copy_stream_body(VALUE arg
)
12079 struct copy_stream_struct
*stp
= (struct copy_stream_struct
*)arg
;
12080 VALUE src_io
= stp
->src
, dst_io
= stp
->dst
;
12081 const int common_oflags
= 0
12087 stp
->th
= rb_thread_current();
12091 if (src_io
== argf
||
12092 !(RB_TYPE_P(src_io
, T_FILE
) ||
12093 RB_TYPE_P(src_io
, T_STRING
) ||
12094 rb_respond_to(src_io
, rb_intern("to_path")))) {
12095 stp
->src_fptr
= NULL
;
12099 VALUE tmp_io
= rb_io_check_io(src_io
);
12100 if (!NIL_P(tmp_io
)) {
12103 else if (!RB_TYPE_P(src_io
, T_FILE
)) {
12105 FilePathValue(src_io
);
12107 args
[1] = INT2NUM(O_RDONLY
|common_oflags
);
12108 src_io
= rb_class_new_instance(2, args
, rb_cFile
);
12110 stp
->close_src
= 1;
12112 RB_IO_POINTER(src_io
, stp
->src_fptr
);
12113 rb_io_check_byte_readable(stp
->src_fptr
);
12115 stat_ret
= fstat(stp
->src_fptr
->fd
, &stp
->src_stat
);
12116 if (stat_ret
< 0) {
12117 stp
->syserr
= "fstat";
12118 stp
->error_no
= errno
;
12123 if (dst_io
== argf
||
12124 !(RB_TYPE_P(dst_io
, T_FILE
) ||
12125 RB_TYPE_P(dst_io
, T_STRING
) ||
12126 rb_respond_to(dst_io
, rb_intern("to_path")))) {
12127 stp
->dst_fptr
= NULL
;
12131 VALUE tmp_io
= rb_io_check_io(dst_io
);
12132 if (!NIL_P(tmp_io
)) {
12133 dst_io
= GetWriteIO(tmp_io
);
12135 else if (!RB_TYPE_P(dst_io
, T_FILE
)) {
12137 FilePathValue(dst_io
);
12139 args
[1] = INT2NUM(O_WRONLY
|O_CREAT
|O_TRUNC
|common_oflags
);
12140 args
[2] = INT2FIX(0666);
12141 dst_io
= rb_class_new_instance(3, args
, rb_cFile
);
12143 stp
->close_dst
= 1;
12146 dst_io
= GetWriteIO(dst_io
);
12149 RB_IO_POINTER(dst_io
, stp
->dst_fptr
);
12150 rb_io_check_writable(stp
->dst_fptr
);
12152 stat_ret
= fstat(stp
->dst_fptr
->fd
, &stp
->dst_stat
);
12153 if (stat_ret
< 0) {
12154 stp
->syserr
= "fstat";
12155 stp
->error_no
= errno
;
12162 SET_BINARY_MODE_WITH_SEEK_CUR(stp
->src_fptr
);
12165 io_ascii8bit_binmode(stp
->dst_fptr
);
12167 if (stp
->src_offset
< (off_t
)0 && stp
->src_fptr
&& stp
->src_fptr
->rbuf
.len
) {
12168 size_t len
= stp
->src_fptr
->rbuf
.len
;
12170 if (stp
->copy_length
>= (off_t
)0 && stp
->copy_length
< (off_t
)len
) {
12171 len
= (size_t)stp
->copy_length
;
12173 str
= rb_str_buf_new(len
);
12174 rb_str_resize(str
,len
);
12175 read_buffered_data(RSTRING_PTR(str
), len
, stp
->src_fptr
);
12176 if (stp
->dst_fptr
) { /* IO or filename */
12177 if (io_binwrite(str
, RSTRING_PTR(str
), RSTRING_LEN(str
), stp
->dst_fptr
, 0) < 0)
12178 rb_sys_fail_on_write(stp
->dst_fptr
);
12180 else /* others such as StringIO */
12181 rb_io_write(dst_io
, str
);
12182 rb_str_resize(str
, 0);
12184 if (stp
->copy_length
>= (off_t
)0)
12185 stp
->copy_length
-= len
;
12188 if (stp
->dst_fptr
&& io_fflush(stp
->dst_fptr
) < 0) {
12189 rb_raise(rb_eIOError
, "flush failed");
12192 if (stp
->copy_length
== 0)
12195 if (stp
->src_fptr
== NULL
|| stp
->dst_fptr
== NULL
) {
12196 return copy_stream_fallback(stp
);
12199 rb_thread_call_without_gvl(nogvl_copy_stream_func
, (void*)stp
, RUBY_UBF_IO
, 0);
12204 copy_stream_finalize(VALUE arg
)
12206 struct copy_stream_struct
*stp
= (struct copy_stream_struct
*)arg
;
12208 #ifdef HAVE_FCOPYFILE
12209 if (stp
->copyfile_state
) {
12210 copyfile_state_free(stp
->copyfile_state
);
12214 if (stp
->close_src
) {
12215 rb_io_close_m(stp
->src
);
12217 if (stp
->close_dst
) {
12218 rb_io_close_m(stp
->dst
);
12221 rb_syserr_fail(stp
->error_no
, stp
->syserr
);
12224 rb_raise(rb_eNotImpError
, "%s() not implemented", stp
->notimp
);
12231 * IO.copy_stream(src, dst)
12232 * IO.copy_stream(src, dst, copy_length)
12233 * IO.copy_stream(src, dst, copy_length, src_offset)
12235 * IO.copy_stream copies <i>src</i> to <i>dst</i>.
12236 * <i>src</i> and <i>dst</i> is either a filename or an IO-like object.
12237 * IO-like object for <i>src</i> should have #readpartial or #read
12238 * method. IO-like object for <i>dst</i> should have #write method.
12239 * (Specialized mechanisms, such as sendfile system call, may be used
12240 * on appropriate situation.)
12242 * This method returns the number of bytes copied.
12244 * If optional arguments are not given,
12245 * the start position of the copy is
12246 * the beginning of the filename or
12247 * the current file offset of the IO.
12248 * The end position of the copy is the end of file.
12250 * If <i>copy_length</i> is given,
12251 * No more than <i>copy_length</i> bytes are copied.
12253 * If <i>src_offset</i> is given,
12254 * it specifies the start position of the copy.
12256 * When <i>src_offset</i> is specified and
12257 * <i>src</i> is an IO,
12258 * IO.copy_stream doesn't move the current file offset.
12262 rb_io_s_copy_stream(int argc
, VALUE
*argv
, VALUE io
)
12264 VALUE src
, dst
, length
, src_offset
;
12265 struct copy_stream_struct st
;
12267 MEMZERO(&st
, struct copy_stream_struct
, 1);
12269 rb_scan_args(argc
, argv
, "22", &src
, &dst
, &length
, &src_offset
);
12274 st
.src_fptr
= NULL
;
12275 st
.dst_fptr
= NULL
;
12278 st
.copy_length
= (off_t
)-1;
12280 st
.copy_length
= NUM2OFFT(length
);
12282 if (NIL_P(src_offset
))
12283 st
.src_offset
= (off_t
)-1;
12285 st
.src_offset
= NUM2OFFT(src_offset
);
12287 rb_ensure(copy_stream_body
, (VALUE
)&st
, copy_stream_finalize
, (VALUE
)&st
);
12289 return OFFT2NUM(st
.total
);
12294 * io.external_encoding -> encoding
12296 * Returns the Encoding object that represents the encoding of the file.
12297 * If _io_ is in write mode and no encoding is specified, returns +nil+.
12301 rb_io_external_encoding(VALUE io
)
12303 rb_io_t
*fptr
= RFILE(rb_io_taint_check(io
))->fptr
;
12305 if (fptr
->encs
.enc2
) {
12306 return rb_enc_from_encoding(fptr
->encs
.enc2
);
12308 if (fptr
->mode
& FMODE_WRITABLE
) {
12309 if (fptr
->encs
.enc
)
12310 return rb_enc_from_encoding(fptr
->encs
.enc
);
12313 return rb_enc_from_encoding(io_read_encoding(fptr
));
12318 * io.internal_encoding -> encoding
12320 * Returns the Encoding of the internal string if conversion is
12321 * specified. Otherwise returns +nil+.
12325 rb_io_internal_encoding(VALUE io
)
12327 rb_io_t
*fptr
= RFILE(rb_io_taint_check(io
))->fptr
;
12329 if (!fptr
->encs
.enc2
) return Qnil
;
12330 return rb_enc_from_encoding(io_read_encoding(fptr
));
12335 * io.set_encoding(ext_enc) -> io
12336 * io.set_encoding("ext_enc:int_enc") -> io
12337 * io.set_encoding(ext_enc, int_enc) -> io
12338 * io.set_encoding("ext_enc:int_enc", opt) -> io
12339 * io.set_encoding(ext_enc, int_enc, opt) -> io
12341 * If single argument is specified, read string from io is tagged
12342 * with the encoding specified. If encoding is a colon separated two
12343 * encoding names "A:B", the read string is converted from encoding A
12344 * (external encoding) to encoding B (internal encoding), then tagged
12345 * with B. If two arguments are specified, those must be encoding
12346 * objects or encoding names, and the first one is the external encoding, and the
12347 * second one is the internal encoding.
12348 * If the external encoding and the internal encoding is specified,
12349 * optional hash argument specify the conversion option.
12353 rb_io_set_encoding(int argc
, VALUE
*argv
, VALUE io
)
12358 if (!RB_TYPE_P(io
, T_FILE
)) {
12359 return forward(io
, id_set_encoding
, argc
, argv
);
12362 argc
= rb_scan_args(argc
, argv
, "11:", &v1
, &v2
, &opt
);
12363 GetOpenFile(io
, fptr
);
12364 io_encoding_set(fptr
, v1
, v2
, opt
);
12369 rb_stdio_set_default_encoding(void)
12374 if (isatty(fileno(stdin
))) {
12375 rb_encoding
*external
= rb_locale_encoding();
12376 rb_encoding
*internal
= rb_default_internal_encoding();
12377 if (!internal
) internal
= rb_default_external_encoding();
12378 io_encoding_set(RFILE(rb_stdin
)->fptr
,
12379 rb_enc_from_encoding(external
),
12380 rb_enc_from_encoding(internal
),
12385 rb_io_set_encoding(1, &val
, rb_stdin
);
12386 rb_io_set_encoding(1, &val
, rb_stdout
);
12387 rb_io_set_encoding(1, &val
, rb_stderr
);
12391 global_argf_p(VALUE arg
)
12393 return arg
== argf
;
12398 * ARGF.external_encoding -> encoding
12400 * Returns the external encoding for files read from +ARGF+ as an +Encoding+
12401 * object. The external encoding is the encoding of the text as stored in a
12402 * file. Contrast with +ARGF.internal_encoding+, which is the encoding used
12403 * to represent this text within Ruby.
12405 * To set the external encoding use +ARGF.set_encoding+.
12409 * ARGF.external_encoding #=> #<Encoding:UTF-8>
12413 argf_external_encoding(VALUE argf
)
12415 if (!RTEST(ARGF
.current_file
)) {
12416 return rb_enc_from_encoding(rb_default_external_encoding());
12418 return rb_io_external_encoding(rb_io_check_io(ARGF
.current_file
));
12423 * ARGF.internal_encoding -> encoding
12425 * Returns the internal encoding for strings read from +ARGF+ as an
12426 * +Encoding+ object.
12428 * If +ARGF.set_encoding+ has been called with two encoding names, the second
12429 * is returned. Otherwise, if +Encoding.default_external+ has been set, that
12430 * value is returned. Failing that, if a default external encoding was
12431 * specified on the command-line, that value is used. If the encoding is
12432 * unknown, +nil+ is returned.
12435 argf_internal_encoding(VALUE argf
)
12437 if (!RTEST(ARGF
.current_file
)) {
12438 return rb_enc_from_encoding(rb_default_external_encoding());
12440 return rb_io_internal_encoding(rb_io_check_io(ARGF
.current_file
));
12445 * ARGF.set_encoding(ext_enc) -> ARGF
12446 * ARGF.set_encoding("ext_enc:int_enc") -> ARGF
12447 * ARGF.set_encoding(ext_enc, int_enc) -> ARGF
12448 * ARGF.set_encoding("ext_enc:int_enc", opt) -> ARGF
12449 * ARGF.set_encoding(ext_enc, int_enc, opt) -> ARGF
12451 * If single argument is specified, strings read from ARGF are tagged with
12452 * the encoding specified.
12454 * If two encoding names separated by a colon are given, e.g. "ascii:utf-8",
12455 * the read string is converted from the first encoding (external encoding)
12456 * to the second encoding (internal encoding), then tagged with the second
12459 * If two arguments are specified, they must be encoding objects or encoding
12460 * names. Again, the first specifies the external encoding; the second
12461 * specifies the internal encoding.
12463 * If the external encoding and the internal encoding are specified, the
12464 * optional +Hash+ argument can be used to adjust the conversion process. The
12465 * structure of this hash is explained in the String#encode documentation.
12469 * ARGF.set_encoding('ascii') # Tag the input as US-ASCII text
12470 * ARGF.set_encoding(Encoding::UTF_8) # Tag the input as UTF-8 text
12471 * ARGF.set_encoding('utf-8','ascii') # Transcode the input from US-ASCII
12475 argf_set_encoding(int argc
, VALUE
*argv
, VALUE argf
)
12479 if (!next_argv()) {
12480 rb_raise(rb_eArgError
, "no stream to set encoding");
12482 rb_io_set_encoding(argc
, argv
, ARGF
.current_file
);
12483 GetOpenFile(ARGF
.current_file
, fptr
);
12484 ARGF
.encs
= fptr
->encs
;
12490 * ARGF.tell -> Integer
12491 * ARGF.pos -> Integer
12493 * Returns the current offset (in bytes) of the current file in +ARGF+.
12496 * ARGF.gets #=> "This is line one\n"
12501 argf_tell(VALUE argf
)
12503 if (!next_argv()) {
12504 rb_raise(rb_eArgError
, "no stream to tell");
12506 ARGF_FORWARD(0, 0);
12507 return rb_io_tell(ARGF
.current_file
);
12512 * ARGF.seek(amount, whence=IO::SEEK_SET) -> 0
12514 * Seeks to offset _amount_ (an +Integer+) in the +ARGF+ stream according to
12515 * the value of _whence_. See IO#seek for further details.
12518 argf_seek_m(int argc
, VALUE
*argv
, VALUE argf
)
12520 if (!next_argv()) {
12521 rb_raise(rb_eArgError
, "no stream to seek");
12523 ARGF_FORWARD(argc
, argv
);
12524 return rb_io_seek_m(argc
, argv
, ARGF
.current_file
);
12529 * ARGF.pos = position -> Integer
12531 * Seeks to the position given by _position_ (in bytes) in +ARGF+.
12536 * ARGF.gets #=> "This is line two\n"
12539 argf_set_pos(VALUE argf
, VALUE offset
)
12541 if (!next_argv()) {
12542 rb_raise(rb_eArgError
, "no stream to set position");
12544 ARGF_FORWARD(1, &offset
);
12545 return rb_io_set_pos(ARGF
.current_file
, offset
);
12552 * Positions the current file to the beginning of input, resetting
12553 * +ARGF.lineno+ to zero.
12555 * ARGF.readline #=> "This is line one\n"
12556 * ARGF.rewind #=> 0
12557 * ARGF.lineno #=> 0
12558 * ARGF.readline #=> "This is line one\n"
12561 argf_rewind(VALUE argf
)
12566 if (!next_argv()) {
12567 rb_raise(rb_eArgError
, "no stream to rewind");
12569 ARGF_FORWARD(0, 0);
12570 old_lineno
= RFILE(ARGF
.current_file
)->fptr
->lineno
;
12571 ret
= rb_io_rewind(ARGF
.current_file
);
12572 if (!global_argf_p(argf
)) {
12573 ARGF
.last_lineno
= ARGF
.lineno
-= old_lineno
;
12580 * ARGF.fileno -> integer
12581 * ARGF.to_i -> integer
12583 * Returns an integer representing the numeric file descriptor for
12584 * the current file. Raises an +ArgumentError+ if there isn't a current file.
12586 * ARGF.fileno #=> 3
12589 argf_fileno(VALUE argf
)
12591 if (!next_argv()) {
12592 rb_raise(rb_eArgError
, "no stream");
12594 ARGF_FORWARD(0, 0);
12595 return rb_io_fileno(ARGF
.current_file
);
12602 * Returns an +IO+ object representing the current file. This will be a
12603 * +File+ object unless the current file is a stream such as STDIN.
12607 * ARGF.to_io #=> #<File:glark.txt>
12608 * ARGF.to_io #=> #<IO:<STDIN>>
12611 argf_to_io(VALUE argf
)
12614 ARGF_FORWARD(0, 0);
12615 return ARGF
.current_file
;
12620 * ARGF.eof? -> true or false
12621 * ARGF.eof -> true or false
12623 * Returns true if the current file in +ARGF+ is at end of file, i.e. it has
12624 * no data to read. The stream must be opened for reading or an +IOError+
12627 * $ echo "eof" | ruby argf.rb
12629 * ARGF.eof? #=> false
12630 * 3.times { ARGF.readchar }
12631 * ARGF.eof? #=> false
12632 * ARGF.readchar #=> "\n"
12633 * ARGF.eof? #=> true
12637 argf_eof(VALUE argf
)
12640 if (RTEST(ARGF
.current_file
)) {
12641 if (ARGF
.init_p
== 0) return Qtrue
;
12643 ARGF_FORWARD(0, 0);
12644 if (rb_io_eof(ARGF
.current_file
)) {
12653 * ARGF.read([length [, outbuf]]) -> string, outbuf, or nil
12655 * Reads _length_ bytes from ARGF. The files named on the command line
12656 * are concatenated and treated as a single file by this method, so when
12657 * called without arguments the contents of this pseudo file are returned in
12660 * _length_ must be a non-negative integer or +nil+.
12662 * If _length_ is a positive integer, +read+ tries to read
12663 * _length_ bytes without any conversion (binary mode).
12664 * It returns +nil+ if an EOF is encountered before anything can be read.
12665 * Fewer than _length_ bytes are returned if an EOF is encountered during
12667 * In the case of an integer _length_, the resulting string is always
12668 * in ASCII-8BIT encoding.
12670 * If _length_ is omitted or is +nil+, it reads until EOF
12671 * and the encoding conversion is applied, if applicable.
12672 * A string is returned even if EOF is encountered before any data is read.
12674 * If _length_ is zero, it returns an empty string (<code>""</code>).
12676 * If the optional _outbuf_ argument is present,
12677 * it must reference a String, which will receive the data.
12678 * The _outbuf_ will contain only the received data after the method call
12679 * even if it is not empty at the beginning.
12683 * $ echo "small" > small.txt
12684 * $ echo "large" > large.txt
12685 * $ ./glark.rb small.txt large.txt
12687 * ARGF.read #=> "small\nlarge"
12688 * ARGF.read(200) #=> "small\nlarge"
12689 * ARGF.read(2) #=> "sm"
12690 * ARGF.read(0) #=> ""
12692 * Note that this method behaves like the fread() function in C.
12693 * This means it retries to invoke read(2) system calls to read data
12694 * with the specified length.
12695 * If you need the behavior like a single read(2) system call,
12696 * consider ARGF#readpartial or ARGF#read_nonblock.
12700 argf_read(int argc
, VALUE
*argv
, VALUE argf
)
12702 VALUE tmp
, str
, length
;
12705 rb_scan_args(argc
, argv
, "02", &length
, &str
);
12706 if (!NIL_P(length
)) {
12707 len
= NUM2LONG(argv
[0]);
12711 rb_str_resize(str
,0);
12716 if (!next_argv()) {
12719 if (ARGF_GENERIC_INPUT_P()) {
12720 tmp
= argf_forward(argc
, argv
, argf
);
12723 tmp
= io_read(argc
, argv
, ARGF
.current_file
);
12725 if (NIL_P(str
)) str
= tmp
;
12726 else if (!NIL_P(tmp
)) rb_str_append(str
, tmp
);
12727 if (NIL_P(tmp
) || NIL_P(length
)) {
12728 if (ARGF
.next_p
!= -1) {
12734 else if (argc
>= 1) {
12735 long slen
= RSTRING_LEN(str
);
12737 argv
[0] = LONG2NUM(len
- slen
);
12744 struct argf_call_arg
{
12751 argf_forward_call(VALUE arg
)
12753 struct argf_call_arg
*p
= (struct argf_call_arg
*)arg
;
12754 argf_forward(p
->argc
, p
->argv
, p
->argf
);
12758 static VALUE
argf_getpartial(int argc
, VALUE
*argv
, VALUE argf
, VALUE opts
,
12763 * ARGF.readpartial(maxlen) -> string
12764 * ARGF.readpartial(maxlen, outbuf) -> outbuf
12766 * Reads at most _maxlen_ bytes from the ARGF stream.
12768 * If the optional _outbuf_ argument is present,
12769 * it must reference a String, which will receive the data.
12770 * The _outbuf_ will contain only the received data after the method call
12771 * even if it is not empty at the beginning.
12773 * It raises EOFError on end of ARGF stream.
12774 * Since ARGF stream is a concatenation of multiple files,
12775 * internally EOF is occur for each file.
12776 * ARGF.readpartial returns empty strings for EOFs except the last one and
12777 * raises EOFError for the last one.
12782 argf_readpartial(int argc
, VALUE
*argv
, VALUE argf
)
12784 return argf_getpartial(argc
, argv
, argf
, Qnil
, 0);
12789 * ARGF.read_nonblock(maxlen[, options]) -> string
12790 * ARGF.read_nonblock(maxlen, outbuf[, options]) -> outbuf
12792 * Reads at most _maxlen_ bytes from the ARGF stream in non-blocking mode.
12796 argf_read_nonblock(int argc
, VALUE
*argv
, VALUE argf
)
12800 rb_scan_args(argc
, argv
, "11:", NULL
, NULL
, &opts
);
12805 return argf_getpartial(argc
, argv
, argf
, opts
, 1);
12809 argf_getpartial(int argc
, VALUE
*argv
, VALUE argf
, VALUE opts
, int nonblock
)
12811 VALUE tmp
, str
, length
;
12814 rb_scan_args(argc
, argv
, "11", &length
, &str
);
12819 no_exception
= no_exception_p(opts
);
12821 if (!next_argv()) {
12823 rb_str_resize(str
, 0);
12827 if (ARGF_GENERIC_INPUT_P()) {
12828 VALUE (*const rescue_does_nothing
)(VALUE
, VALUE
) = 0;
12829 struct argf_call_arg arg
;
12833 tmp
= rb_rescue2(argf_forward_call
, (VALUE
)&arg
,
12834 rescue_does_nothing
, Qnil
, rb_eEOFError
, (VALUE
)0);
12837 tmp
= io_getpartial(argc
, argv
, ARGF
.current_file
, no_exception
, nonblock
);
12840 if (ARGF
.next_p
== -1) {
12841 return io_nonblock_eof(no_exception
);
12845 if (RARRAY_LEN(ARGF
.argv
) == 0) {
12846 return io_nonblock_eof(no_exception
);
12849 str
= rb_str_new(NULL
, 0);
12857 * ARGF.getc -> String or nil
12859 * Reads the next character from +ARGF+ and returns it as a +String+. Returns
12860 * +nil+ at the end of the stream.
12862 * +ARGF+ treats the files named on the command line as a single file created
12863 * by concatenating their contents. After returning the last character of the
12864 * first file, it returns the first character of the second file, and so on.
12868 * $ echo "foo" > file
12869 * $ ruby argf.rb file
12871 * ARGF.getc #=> "f"
12872 * ARGF.getc #=> "o"
12873 * ARGF.getc #=> "o"
12874 * ARGF.getc #=> "\n"
12875 * ARGF.getc #=> nil
12876 * ARGF.getc #=> nil
12879 argf_getc(VALUE argf
)
12884 if (!next_argv()) return Qnil
;
12885 if (ARGF_GENERIC_INPUT_P()) {
12886 ch
= forward_current(rb_intern("getc"), 0, 0);
12889 ch
= rb_io_getc(ARGF
.current_file
);
12891 if (NIL_P(ch
) && ARGF
.next_p
!= -1) {
12902 * ARGF.getbyte -> Integer or nil
12904 * Gets the next 8-bit byte (0..255) from +ARGF+. Returns +nil+ if called at
12905 * the end of the stream.
12909 * $ echo "foo" > file
12910 * $ ruby argf.rb file
12912 * ARGF.getbyte #=> 102
12913 * ARGF.getbyte #=> 111
12914 * ARGF.getbyte #=> 111
12915 * ARGF.getbyte #=> 10
12916 * ARGF.getbyte #=> nil
12919 argf_getbyte(VALUE argf
)
12924 if (!next_argv()) return Qnil
;
12925 if (!RB_TYPE_P(ARGF
.current_file
, T_FILE
)) {
12926 ch
= forward_current(rb_intern("getbyte"), 0, 0);
12929 ch
= rb_io_getbyte(ARGF
.current_file
);
12931 if (NIL_P(ch
) && ARGF
.next_p
!= -1) {
12942 * ARGF.readchar -> String or nil
12944 * Reads the next character from +ARGF+ and returns it as a +String+. Raises
12945 * an +EOFError+ after the last character of the last file has been read.
12949 * $ echo "foo" > file
12950 * $ ruby argf.rb file
12952 * ARGF.readchar #=> "f"
12953 * ARGF.readchar #=> "o"
12954 * ARGF.readchar #=> "o"
12955 * ARGF.readchar #=> "\n"
12956 * ARGF.readchar #=> end of file reached (EOFError)
12959 argf_readchar(VALUE argf
)
12964 if (!next_argv()) rb_eof_error();
12965 if (!RB_TYPE_P(ARGF
.current_file
, T_FILE
)) {
12966 ch
= forward_current(rb_intern("getc"), 0, 0);
12969 ch
= rb_io_getc(ARGF
.current_file
);
12971 if (NIL_P(ch
) && ARGF
.next_p
!= -1) {
12982 * ARGF.readbyte -> Integer
12984 * Reads the next 8-bit byte from ARGF and returns it as an +Integer+. Raises
12985 * an +EOFError+ after the last byte of the last file has been read.
12989 * $ echo "foo" > file
12990 * $ ruby argf.rb file
12992 * ARGF.readbyte #=> 102
12993 * ARGF.readbyte #=> 111
12994 * ARGF.readbyte #=> 111
12995 * ARGF.readbyte #=> 10
12996 * ARGF.readbyte #=> end of file reached (EOFError)
12999 argf_readbyte(VALUE argf
)
13003 NEXT_ARGF_FORWARD(0, 0);
13004 c
= argf_getbyte(argf
);
13011 #define FOREACH_ARGF() while (next_argv())
13014 argf_block_call_i(RB_BLOCK_CALL_FUNC_ARGLIST(i
, argf
))
13016 const VALUE current
= ARGF
.current_file
;
13017 rb_yield_values2(argc
, argv
);
13018 if (ARGF
.init_p
== -1 || current
!= ARGF
.current_file
) {
13019 rb_iter_break_value(Qundef
);
13024 #define ARGF_block_call(mid, argc, argv, func, argf) \
13025 rb_block_call_kw(ARGF.current_file, mid, argc, argv, \
13026 func, argf, rb_keyword_given_p())
13029 argf_block_call(ID mid
, int argc
, VALUE
*argv
, VALUE argf
)
13031 VALUE ret
= ARGF_block_call(mid
, argc
, argv
, argf_block_call_i
, argf
);
13032 if (ret
!= Qundef
) ARGF
.next_p
= 1;
13036 argf_block_call_line_i(RB_BLOCK_CALL_FUNC_ARGLIST(i
, argf
))
13038 if (!global_argf_p(argf
)) {
13039 ARGF
.last_lineno
= ++ARGF
.lineno
;
13041 return argf_block_call_i(i
, argf
, argc
, argv
, blockarg
);
13045 argf_block_call_line(ID mid
, int argc
, VALUE
*argv
, VALUE argf
)
13047 VALUE ret
= ARGF_block_call(mid
, argc
, argv
, argf_block_call_line_i
, argf
);
13048 if (ret
!= Qundef
) ARGF
.next_p
= 1;
13053 * ARGF.each(sep=$/) {|line| block } -> ARGF
13054 * ARGF.each(sep=$/, limit) {|line| block } -> ARGF
13055 * ARGF.each(...) -> an_enumerator
13057 * ARGF.each_line(sep=$/) {|line| block } -> ARGF
13058 * ARGF.each_line(sep=$/, limit) {|line| block } -> ARGF
13059 * ARGF.each_line(...) -> an_enumerator
13061 * Returns an enumerator which iterates over each line (separated by _sep_,
13062 * which defaults to your platform's newline character) of each file in
13063 * +ARGV+. If a block is supplied, each line in turn will be yielded to the
13064 * block, otherwise an enumerator is returned.
13065 * The optional _limit_ argument is an +Integer+ specifying the maximum
13066 * length of each line; longer lines will be split according to this limit.
13068 * This method allows you to treat the files supplied on the command line as
13069 * a single file consisting of the concatenation of each named file. After
13070 * the last line of the first file has been returned, the first line of the
13071 * second file is returned. The +ARGF.filename+ and +ARGF.lineno+ methods can
13072 * be used to determine the filename of the current line and line number of
13073 * the whole input, respectively.
13075 * For example, the following code prints out each line of each named file
13076 * prefixed with its line number, displaying the filename once per file:
13078 * ARGF.each_line do |line|
13079 * puts ARGF.filename if ARGF.file.lineno == 1
13080 * puts "#{ARGF.file.lineno}: #{line}"
13083 * While the following code prints only the first file's name at first, and
13084 * the contents with line number counted through all named files.
13086 * ARGF.each_line do |line|
13087 * puts ARGF.filename if ARGF.lineno == 1
13088 * puts "#{ARGF.lineno}: #{line}"
13092 argf_each_line(int argc
, VALUE
*argv
, VALUE argf
)
13094 RETURN_ENUMERATOR(argf
, argc
, argv
);
13096 argf_block_call_line(rb_intern("each_line"), argc
, argv
, argf
);
13103 * ARGF.each_byte {|byte| block } -> ARGF
13104 * ARGF.each_byte -> an_enumerator
13106 * Iterates over each byte of each file in +ARGV+.
13107 * A byte is returned as an +Integer+ in the range 0..255.
13109 * This method allows you to treat the files supplied on the command line as
13110 * a single file consisting of the concatenation of each named file. After
13111 * the last byte of the first file has been returned, the first byte of the
13112 * second file is returned. The +ARGF.filename+ method can be used to
13113 * determine the filename of the current byte.
13115 * If no block is given, an enumerator is returned instead.
13119 * ARGF.bytes.to_a #=> [35, 32, ... 95, 10]
13123 argf_each_byte(VALUE argf
)
13125 RETURN_ENUMERATOR(argf
, 0, 0);
13127 argf_block_call(rb_intern("each_byte"), 0, 0, argf
);
13134 * ARGF.each_char {|char| block } -> ARGF
13135 * ARGF.each_char -> an_enumerator
13137 * Iterates over each character of each file in +ARGF+.
13139 * This method allows you to treat the files supplied on the command line as
13140 * a single file consisting of the concatenation of each named file. After
13141 * the last character of the first file has been returned, the first
13142 * character of the second file is returned. The +ARGF.filename+ method can
13143 * be used to determine the name of the file in which the current character
13146 * If no block is given, an enumerator is returned instead.
13149 argf_each_char(VALUE argf
)
13151 RETURN_ENUMERATOR(argf
, 0, 0);
13153 argf_block_call(rb_intern("each_char"), 0, 0, argf
);
13160 * ARGF.each_codepoint {|codepoint| block } -> ARGF
13161 * ARGF.each_codepoint -> an_enumerator
13163 * Iterates over each codepoint of each file in +ARGF+.
13165 * This method allows you to treat the files supplied on the command line as
13166 * a single file consisting of the concatenation of each named file. After
13167 * the last codepoint of the first file has been returned, the first
13168 * codepoint of the second file is returned. The +ARGF.filename+ method can
13169 * be used to determine the name of the file in which the current codepoint
13172 * If no block is given, an enumerator is returned instead.
13175 argf_each_codepoint(VALUE argf
)
13177 RETURN_ENUMERATOR(argf
, 0, 0);
13179 argf_block_call(rb_intern("each_codepoint"), 0, 0, argf
);
13186 * ARGF.filename -> String
13187 * ARGF.path -> String
13189 * Returns the current filename. "-" is returned when the current file is
13194 * $ echo "foo" > foo
13195 * $ echo "bar" > bar
13196 * $ echo "glark" > glark
13198 * $ ruby argf.rb foo bar glark
13200 * ARGF.filename #=> "foo"
13201 * ARGF.read(5) #=> "foo\nb"
13202 * ARGF.filename #=> "bar"
13204 * ARGF.filename #=> "glark"
13207 argf_filename(VALUE argf
)
13210 return ARGF
.filename
;
13214 argf_filename_getter(ID id
, VALUE
*var
)
13216 return argf_filename(*var
);
13221 * ARGF.file -> IO or File object
13223 * Returns the current file as an +IO+ or +File+ object.
13224 * <code>$stdin</code> is returned when the current file is STDIN.
13228 * $ echo "foo" > foo
13229 * $ echo "bar" > bar
13231 * $ ruby argf.rb foo bar
13233 * ARGF.file #=> #<File:foo>
13234 * ARGF.read(5) #=> "foo\nb"
13235 * ARGF.file #=> #<File:bar>
13238 argf_file(VALUE argf
)
13241 return ARGF
.current_file
;
13246 * ARGF.binmode -> ARGF
13248 * Puts +ARGF+ into binary mode. Once a stream is in binary mode, it cannot
13249 * be reset to non-binary mode. This option has the following effects:
13251 * * Newline conversion is disabled.
13252 * * Encoding conversion is disabled.
13253 * * Content is treated as ASCII-8BIT.
13256 argf_binmode_m(VALUE argf
)
13260 ARGF_FORWARD(0, 0);
13261 rb_io_ascii8bit_binmode(ARGF
.current_file
);
13267 * ARGF.binmode? -> true or false
13269 * Returns true if +ARGF+ is being read in binary mode; false otherwise.
13270 * To enable binary mode use +ARGF.binmode+.
13274 * ARGF.binmode? #=> false
13276 * ARGF.binmode? #=> true
13279 argf_binmode_p(VALUE argf
)
13281 return RBOOL(ARGF
.binmode
);
13286 * ARGF.skip -> ARGF
13288 * Sets the current file to the next file in ARGV. If there aren't any more
13289 * files it has no effect.
13293 * $ ruby argf.rb foo bar
13294 * ARGF.filename #=> "foo"
13296 * ARGF.filename #=> "bar"
13299 argf_skip(VALUE argf
)
13301 if (ARGF
.init_p
&& ARGF
.next_p
== 0) {
13310 * ARGF.close -> ARGF
13312 * Closes the current file and skips to the next file in ARGV. If there are
13313 * no more files to open, just closes the current file. +STDIN+ will not be
13318 * $ ruby argf.rb foo bar
13320 * ARGF.filename #=> "foo"
13322 * ARGF.filename #=> "bar"
13326 argf_close_m(VALUE argf
)
13330 if (ARGF
.next_p
!= -1) {
13339 * ARGF.closed? -> true or false
13341 * Returns _true_ if the current file has been closed; _false_ otherwise. Use
13342 * +ARGF.close+ to actually close the current file.
13345 argf_closed(VALUE argf
)
13348 ARGF_FORWARD(0, 0);
13349 return rb_io_closed(ARGF
.current_file
);
13354 * ARGF.to_s -> String
13359 argf_to_s(VALUE argf
)
13361 return rb_str_new2("ARGF");
13366 * ARGF.inplace_mode -> String
13368 * Returns the file extension appended to the names of modified files under
13369 * in-place edit mode. This value can be set using +ARGF.inplace_mode=+ or
13370 * passing the +-i+ switch to the Ruby binary.
13373 argf_inplace_mode_get(VALUE argf
)
13375 if (!ARGF
.inplace
) return Qnil
;
13376 if (NIL_P(ARGF
.inplace
)) return rb_str_new(0, 0);
13377 return rb_str_dup(ARGF
.inplace
);
13381 opt_i_get(ID id
, VALUE
*var
)
13383 return argf_inplace_mode_get(*var
);
13388 * ARGF.inplace_mode = ext -> ARGF
13390 * Sets the filename extension for in-place editing mode to the given String.
13391 * Each file being edited has this value appended to its filename. The
13392 * modified file is saved under this new name.
13396 * $ ruby argf.rb file.txt
13398 * ARGF.inplace_mode = '.bak'
13399 * ARGF.each_line do |line|
13400 * print line.sub("foo","bar")
13403 * Each line of _file.txt_ has the first occurrence of "foo" replaced with
13404 * "bar", then the new line is written out to _file.txt.bak_.
13407 argf_inplace_mode_set(VALUE argf
, VALUE val
)
13410 ARGF
.inplace
= Qfalse
;
13412 else if (StringValueCStr(val
), !RSTRING_LEN(val
)) {
13413 ARGF
.inplace
= Qnil
;
13416 ARGF
.inplace
= rb_str_new_frozen(val
);
13422 opt_i_set(VALUE val
, ID id
, VALUE
*var
)
13424 argf_inplace_mode_set(*var
, val
);
13428 ruby_set_inplace_mode(const char *suffix
)
13430 ARGF
.inplace
= !suffix
? Qfalse
: !*suffix
? Qnil
: rb_str_new(suffix
, strlen(suffix
));
13435 * ARGF.argv -> ARGV
13437 * Returns the +ARGV+ array, which contains the arguments passed to your
13438 * script, one per element.
13442 * $ ruby argf.rb -v glark.txt
13444 * ARGF.argv #=> ["-v", "glark.txt"]
13448 argf_argv(VALUE argf
)
13454 argf_argv_getter(ID id
, VALUE
*var
)
13456 return argf_argv(*var
);
13467 * ARGF.to_write_io -> io
13469 * Returns IO instance tied to _ARGF_ for writing if inplace mode is
13473 argf_write_io(VALUE argf
)
13475 if (!RTEST(ARGF
.current_file
)) {
13476 rb_raise(rb_eIOError
, "not opened for writing");
13478 return GetWriteIO(ARGF
.current_file
);
13483 * ARGF.write(string) -> integer
13485 * Writes _string_ if inplace mode.
13488 argf_write(VALUE argf
, VALUE str
)
13490 return rb_io_write(argf_write_io(argf
), str
);
13494 rb_readwrite_sys_fail(enum rb_io_wait_readwrite waiting
, const char *mesg
)
13496 rb_readwrite_syserr_fail(waiting
, errno
, mesg
);
13500 rb_readwrite_syserr_fail(enum rb_io_wait_readwrite waiting
, int n
, const char *mesg
)
13502 VALUE arg
, c
= Qnil
;
13503 arg
= mesg
? rb_str_new2(mesg
) : Qnil
;
13505 case RB_IO_WAIT_WRITABLE
:
13508 c
= rb_eEAGAINWaitWritable
;
13510 #if EAGAIN != EWOULDBLOCK
13512 c
= rb_eEWOULDBLOCKWaitWritable
;
13516 c
= rb_eEINPROGRESSWaitWritable
;
13519 rb_mod_syserr_fail_str(rb_mWaitWritable
, n
, arg
);
13522 case RB_IO_WAIT_READABLE
:
13525 c
= rb_eEAGAINWaitReadable
;
13527 #if EAGAIN != EWOULDBLOCK
13529 c
= rb_eEWOULDBLOCKWaitReadable
;
13533 c
= rb_eEINPROGRESSWaitReadable
;
13536 rb_mod_syserr_fail_str(rb_mWaitReadable
, n
, arg
);
13540 rb_bug("invalid read/write type passed to rb_readwrite_sys_fail: %d", waiting
);
13542 rb_exc_raise(rb_class_new_instance(1, &arg
, c
));
13546 get_LAST_READ_LINE(ID _x
, VALUE
*_y
)
13548 return rb_lastline_get();
13552 set_LAST_READ_LINE(VALUE val
, ID _x
, VALUE
*_y
)
13554 rb_lastline_set(val
);
13558 * Document-class: IOError
13560 * Raised when an IO operation fails.
13562 * File.open("/etc/hosts") {|f| f << "example"}
13563 * #=> IOError: not opened for writing
13565 * File.open("/etc/hosts") {|f| f.close; f.read }
13566 * #=> IOError: closed stream
13568 * Note that some IO failures raise <code>SystemCallError</code>s
13569 * and these are not subclasses of IOError:
13571 * File.open("does/not/exist")
13572 * #=> Errno::ENOENT: No such file or directory - does/not/exist
13576 * Document-class: EOFError
13578 * Raised by some IO operations when reaching the end of file. Many IO
13579 * methods exist in two forms,
13581 * one that returns +nil+ when the end of file is reached, the other
13582 * raises +EOFError+.
13584 * +EOFError+ is a subclass of +IOError+.
13586 * file = File.open("/etc/hosts")
13588 * file.gets #=> nil
13589 * file.readline #=> EOFError: end of file reached
13593 * Document-class: ARGF
13595 * +ARGF+ is a stream designed for use in scripts that process files given as
13596 * command-line arguments or passed in via STDIN.
13598 * The arguments passed to your script are stored in the +ARGV+ Array, one
13599 * argument per element. +ARGF+ assumes that any arguments that aren't
13600 * filenames have been removed from +ARGV+. For example:
13602 * $ ruby argf.rb --verbose file1 file2
13604 * ARGV #=> ["--verbose", "file1", "file2"]
13605 * option = ARGV.shift #=> "--verbose"
13606 * ARGV #=> ["file1", "file2"]
13608 * You can now use +ARGF+ to work with a concatenation of each of these named
13609 * files. For instance, +ARGF.read+ will return the contents of _file1_
13610 * followed by the contents of _file2_.
13612 * After a file in +ARGV+ has been read +ARGF+ removes it from the Array.
13613 * Thus, after all files have been read +ARGV+ will be empty.
13615 * You can manipulate +ARGV+ yourself to control what +ARGF+ operates on. If
13616 * you remove a file from +ARGV+, it is ignored by +ARGF+; if you add files to
13617 * +ARGV+, they are treated as if they were named on the command line. For
13620 * ARGV.replace ["file1"]
13621 * ARGF.readlines # Returns the contents of file1 as an Array
13623 * ARGV.replace ["file2", "file3"]
13624 * ARGF.read # Returns the contents of file2 and file3
13626 * If +ARGV+ is empty, +ARGF+ acts as if it contained STDIN, i.e. the data
13627 * piped to your script. For example:
13629 * $ echo "glark" | ruby -e 'p ARGF.read'
13634 * The IO class is the basis for all input and output in Ruby.
13635 * An I/O stream may be <em>duplexed</em> (that is, bidirectional), and
13636 * so may use more than one native operating system stream.
13638 * Many of the examples in this section use the File class, the only standard
13639 * subclass of IO. The two classes are closely associated. Like the File
13640 * class, the Socket library subclasses from IO (such as TCPSocket or
13643 * The Kernel#open method can create an IO (or File) object for these types
13646 * * A plain string represents a filename suitable for the underlying
13647 * operating system.
13649 * * A string starting with <code>"|"</code> indicates a subprocess.
13650 * The remainder of the string following the <code>"|"</code> is
13651 * invoked as a process with appropriate input/output channels
13654 * * A string equal to <code>"|-"</code> will create another Ruby
13655 * instance as a subprocess.
13657 * The IO may be opened with different file modes (read-only, write-only) and
13658 * encodings for proper conversion. See IO.new for these options. See
13659 * Kernel#open for details of the various command formats described above.
13661 * IO.popen, the Open3 library, or Process#spawn may also be used to
13662 * communicate with subprocesses through an IO.
13664 * Ruby will convert pathnames between different operating system
13665 * conventions if possible. For instance, on a Windows system the
13666 * filename <code>"/gumby/ruby/test.rb"</code> will be opened as
13667 * <code>"\gumby\ruby\test.rb"</code>. When specifying a Windows-style
13668 * filename in a Ruby string, remember to escape the backslashes:
13670 * "C:\\gumby\\ruby\\test.rb"
13672 * Our examples here will use the Unix-style forward slashes;
13673 * File::ALT_SEPARATOR can be used to get the platform-specific separator
13676 * The global constant ARGF (also accessible as <code>$<</code>) provides an
13677 * IO-like stream which allows access to all files mentioned on the
13678 * command line (or STDIN if no files are mentioned). ARGF#path and its alias
13679 * ARGF#filename are provided to access the name of the file currently being
13684 * The io/console extension provides methods for interacting with the
13685 * console. The console can be accessed from IO.console or the standard
13686 * input/output/error IO objects.
13688 * Requiring io/console adds the following methods:
13707 * require 'io/console'
13708 * rows, columns = $stdout.winsize
13709 * puts "Your screen is #{columns} wide and #{rows} tall"
13713 * Many examples here use these filenames and their corresponding files:
13715 * - <tt>t.txt</tt>: A text-only file that is assumed to exist via:
13718 * This is line one.
13719 * This is the second line.
13720 * This is the third line.
13722 * File.write('t.txt', text)
13724 * - <tt>t.dat</tt>: A data file that is assumed to exist via:
13726 * data = "\u9990\u9991\u9992\u9993\u9994"
13727 * f = File.open('t.dat', 'wb:UTF-16')
13731 * - <tt>t.rus</tt>: A Russian-language text file that is assumed to exist via:
13733 * File.write('t.rus', "\u{442 435 441 442}")
13735 * - <tt>t.tmp</tt>: A file that is assumed _not_ to exist.
13739 * A number of \IO method calls must or may specify a _mode_ for the stream;
13740 * the mode determines how stream is to be accessible, including:
13742 * - Whether the stream is to be read-only, write-only, or read-write.
13743 * - Whether the stream is positioned at its beginning or its end.
13744 * - Whether the stream treats data as text-only or binary.
13745 * - The external and internal encodings.
13747 * === Mode Specified as an \Integer
13749 * When +mode+ is an integer it must be one or more (combined by bitwise OR (<tt>|</tt>)
13750 * of the modes defined in File::Constants:
13752 * - +File::RDONLY+: Open for reading only.
13753 * - +File::WRONLY+: Open for writing only.
13754 * - +File::RDWR+: Open for reading and writing.
13755 * - +File::APPEND+: Open for appending only.
13756 * - +File::CREAT+: Create file if it does not exist.
13757 * - +File::EXCL+: Raise an exception if +File::CREAT+ is given and the file exists.
13761 * File.new('t.txt', File::RDONLY)
13762 * File.new('t.tmp', File::RDWR | File::CREAT | File::EXCL)
13764 * Note: Method IO#set_encoding does not allow the mode to be specified as an integer.
13766 * === Mode Specified As a \String
13768 * When +mode+ is a string it must begin with one of the following:
13770 * - <tt>'r'</tt>: Read-only stream, positioned at the beginning;
13771 * the stream cannot be changed to writable.
13772 * - <tt>'w'</tt>: Write-only stream, positioned at the beginning;
13773 * the stream cannot be changed to readable.
13774 * - <tt>'a'</tt>: Write-only stream, positioned at the end;
13775 * every write appends to the end;
13776 * the stream cannot be changed to readable.
13777 * - <tt>'r+'</tt>: Read-write stream, positioned at the beginning.
13778 * - <tt>'w+'</tt>: Read-write stream, positioned at the end.
13779 * - <tt>'a+'</tt>: Read-write stream, positioned at the end.
13781 * For a writable file stream (that is, any except read-only),
13782 * the file is truncated to zero if it exists,
13783 * and is created if it does not exist.
13787 * File.open('t.txt', 'r')
13788 * File.open('t.tmp', 'w')
13790 * Either of the following may be suffixed to any of the above:
13792 * - <tt>'t'</tt>: Text data; sets the default external encoding to +Encoding::UTF_8+;
13793 * on Windows, enables conversion between EOL and CRLF.
13794 * - <tt>'b'</tt>: Binary data; sets the default external encoding to +Encoding::ASCII_8BIT+;
13795 * on Windows, suppresses conversion between EOL and CRLF.
13797 * If neither is given, the stream defaults to text data.
13801 * File.open('t.txt', 'rt')
13802 * File.open('t.dat', 'rb')
13804 * The following may be suffixed to any writable mode above:
13806 * - <tt>'x'</tt>: Creates the file if it does not exist;
13807 * raises an exception if the file exists.
13811 * File.open('t.tmp', 'wx')
13813 * Finally, the mode string may specify encodings --
13814 * either external encoding only or both external and internal encodings --
13815 * by appending one or both encoding names, separated by colons:
13817 * f = File.new('t.dat', 'rb')
13818 * f.external_encoding # => #<Encoding:ASCII-8BIT>
13819 * f.internal_encoding # => nil
13820 * f = File.new('t.dat', 'rb:UTF-16')
13821 * f.external_encoding # => #<Encoding:UTF-16 (dummy)>
13822 * f.internal_encoding # => nil
13823 * f = File.new('t.dat', 'rb:UTF-16:UTF-16')
13824 * f.external_encoding # => #<Encoding:UTF-16 (dummy)>
13825 * f.internal_encoding # => #<Encoding:UTF-16>
13827 * The numerous encoding names are available in array Encoding.name_list:
13829 * Encoding.name_list.size # => 175
13830 * Encoding.name_list.take(3) # => ["ASCII-8BIT", "UTF-8", "US-ASCII"]
13834 * When the external encoding is set,
13835 * strings read are tagged by that encoding
13836 * when reading, and strings written are converted to that
13837 * encoding when writing.
13839 * When both external and internal encodings are set,
13840 * strings read are converted from external to internal encoding,
13841 * and strings written are converted from internal to external encoding.
13842 * For further details about transcoding input and output, see Encoding.
13844 * If the external encoding is <tt>'BOM|UTF-8'</tt>, <tt>'BOM|UTF-16LE'</tt>
13845 * or <tt>'BOM|UTF16-BE'</tt>, Ruby checks for
13846 * a Unicode BOM in the input document to help determine the encoding. For
13847 * UTF-16 encodings the file open mode must be binary.
13848 * If the BOM is found, it is stripped and the external encoding from the BOM is used.
13850 * Note that the BOM-style encoding option is case insensitive,
13851 * so 'bom|utf-8' is also valid.)
13855 * A number of \IO methods accept an optional parameter +opts+,
13856 * which determines how a new stream is to be opened:
13858 * - +:mode+: Stream mode.
13859 * - +:flags+: \Integer file open flags;
13860 * If +mode+ is also given, the two are bitwise-ORed.
13861 * - +:external_encoding+: External encoding for the stream.
13862 * - +:internal_encoding+: Internal encoding for the stream.
13863 * <tt>'-'</tt> is a synonym for the default internal encoding.
13864 * If the value is +nil+ no conversion occurs.
13865 * - +:encoding+: Specifies external and internal encodings as <tt>'extern:intern'</tt>.
13866 * - +:textmode+: If a truthy value, specifies the mode as text-only, binary otherwise.
13867 * - +:binmode+: If a truthy value, specifies the mode as binary, text-only otherwise.
13868 * - +:autoclose+: If a truthy value, specifies that the +fd+ will close
13869 * when the stream closes; otherwise it remains open.
13871 * Also available are the options offered in String#encode,
13872 * which may control conversion between external internal encoding.
13874 * == Getline Options
13876 * A number of \IO methods accept optional keyword arguments
13877 * that determine how a stream is to be treated:
13879 * - +:chomp+: If +true+, line separators are omitted; default is +false+.
13883 * An \IO stream has a _position_, which is the non-negative integer offset
13884 * (in bytes) in the stream where the next read or write will occur.
13886 * Note that a text stream may have multi-byte characters,
13887 * so a text stream whose position is +n+ (_bytes_) may not have +n+ _characters_
13888 * preceding the current position -- there may be fewer.
13890 * A new stream is initially positioned:
13892 * - At the beginning (position +0+)
13893 * if its mode is <tt>'r'</tt>, <tt>'w'</tt>, or <tt>'r+'</tt>.
13894 * - At the end (position <tt>self.size</tt>)
13895 * if its mode is <tt>'a'</tt>, <tt>'w+'</tt>, or <tt>'a+'</tt>.
13897 * Methods to query the position:
13899 * - IO#tell and its alias IO#pos return the position for an open stream.
13900 * - IO#eof? and its alias IO#eof return whether the position is at the end
13901 * of a readable stream.
13903 * Reading from a stream usually changes its position:
13905 * f = File.open('t.txt')
13907 * f.readline # => "This is line one.\n"
13909 * f.readline # => "This is the second line.\n"
13911 * f.eof? # => false
13912 * f.readline # => "Here's the third line.\n"
13916 * Writing to a stream usually changes its position:
13918 * f = File.open('t.tmp', 'w')
13920 * f.write('foo') # => 3
13922 * f.write('bar') # => 3
13926 * Iterating over a stream usually changes its position:
13928 * f = File.open('t.txt')
13930 * p "position=#{f.pos} eof?=#{f.eof?} line=#{line}"
13935 * "position=19 eof?=false line=This is line one.\n"
13936 * "position=45 eof?=false line=This is the second line.\n"
13937 * "position=70 eof?=true line=This is the third line.\n"
13939 * The position may also be changed by certain other methods:
13941 * - IO#pos= and IO#seek change the position to a specified offset.
13942 * - IO#rewind changes the position to the beginning.
13946 * A readable \IO stream has a _line_ _number_,
13947 * which is the non-negative integer line number
13948 * in the stream where the next read will occur.
13950 * A new stream is initially has line number +0+.
13952 * \Method IO#lineno returns the line number.
13954 * Reading lines from a stream usually changes its line number:
13956 * f = File.open('t.txt', 'r')
13958 * f.readline # => "This is line one.\n"
13960 * f.readline # => "This is the second line.\n"
13962 * f.readline # => "Here's the third line.\n"
13966 * Iterating over lines in a stream usually changes its line number:
13968 * f = File.open('t.txt')
13969 * f.each_line do |line|
13970 * p "position=#{f.pos} eof?=#{f.eof?} line=#{line}"
13975 * "position=19 eof?=false line=This is line one.\n"
13976 * "position=45 eof?=false line=This is the second line.\n"
13977 * "position=70 eof?=true line=This is the third line.\n"
13981 * First, what's elsewhere. \Class \IO:
13983 * - Inherits from {class Object}[Object.html#class-Object-label-What-27s+Here].
13984 * - Includes {module Enumerable}[Enumerable.html#module-Enumerable-label-What-27s+Here],
13985 * which provides dozens of additional methods.
13987 * Here, class \IO provides methods that are useful for:
13989 * - {Creating}[#class-IO-label-Creating]
13990 * - {Reading}[#class-IO-label-Reading]
13991 * - {Writing}[#class-IO-label-Writing]
13992 * - {Positioning}[#class-IO-label-Positioning]
13993 * - {Iterating}[#class-IO-label-Iterating]
13994 * - {Settings}[#class-IO-label-Settings]
13995 * - {Querying}[#class-IO-label-Querying]
13996 * - {Buffering}[#class-IO-label-Buffering]
13997 * - {Low-Level Access}[#class-IO-label-Low-Level+Access]
13998 * - {Other}[#class-IO-label-Other]
14002 * - ::new (aliased as ::for_fd):: Creates and returns a new \IO object for the given
14003 * integer file descriptor.
14004 * - ::open:: Creates a new \IO object.
14005 * - ::pipe:: Creates a connected pair of reader and writer \IO objects.
14006 * - ::popen:: Creates an \IO object to interact with a subprocess.
14007 * - ::select:: Selects which given \IO instances are ready for reading,
14008 * writing, or have pending exceptions.
14012 * - ::binread:: Returns a binary string with all or a subset of bytes
14013 * from the given file.
14014 * - ::read:: Returns a string with all or a subset of bytes from the given file.
14015 * - ::readlines:: Returns an array of strings, which are the lines from the given file.
14016 * - #getbyte:: Returns the next 8-bit byte read from +self+ as an integer.
14017 * - #getc:: Returns the next character read from +self+ as a string.
14018 * - #gets:: Returns the line read from +self+.
14019 * - #pread:: Returns all or the next _n_ bytes read from +self+,
14020 * not updating the receiver's offset.
14021 * - #read:: Returns all remaining or the next _n_ bytes read from +self+
14023 * - #read_nonblock:: the next _n_ bytes read from +self+ for a given _n_,
14024 * in non-block mode.
14025 * - #readbyte:: Returns the next byte read from +self+;
14026 * same as #getbyte, but raises an exception on end-of-file.
14027 * - #readchar:: Returns the next character read from +self+;
14028 * same as #getc, but raises an exception on end-of-file.
14029 * - #readline:: Returns the next line read from +self+;
14030 * same as #getline, but raises an exception of end-of-file.
14031 * - #readlines:: Returns an array of all lines read read from +self+.
14032 * - #readpartial:: Returns up to the given number of bytes from +self+.
14036 * - ::binwrite:: Writes the given string to the file at the given filepath,
14038 * - ::write:: Writes the given string to +self+.
14039 * - {::<<}[#method-i-3C-3C]:: Appends the given string to +self+.
14040 * - #print:: Prints last read line or given objects to +self+.
14041 * - #printf:: Writes to +self+ based on the given format string and objects.
14042 * - #putc:: Writes a character to +self+.
14043 * - #puts:: Writes lines to +self+, making sure line ends with a newline.
14044 * - #pwrite:: Writes the given string at the given offset,
14045 * not updating the receiver's offset.
14046 * - #write:: Writes one or more given strings to +self+.
14047 * - #write_nonblock:: Writes one or more given strings to +self+ in non-blocking mode.
14051 * - #lineno:: Returns the current line number in +self+.
14052 * - #lineno=:: Sets the line number is +self+.
14053 * - #pos (aliased as #tell):: Returns the current byte offset in +self+.
14054 * - #pos=:: Sets the byte offset in +self+.
14055 * - #reopen:: Reassociates +self+ with a new or existing \IO stream.
14056 * - #rewind:: Positions +self+ to the beginning of input.
14057 * - #seek:: Sets the offset for +self+ relative to given position.
14061 * - ::foreach:: Yields each line of given file to the block.
14062 * - #each (aliased as #each_line):: Calls the given block
14063 * with each successive line in +self+.
14064 * - #each_byte:: Calls the given block with each successive byte in +self+
14066 * - #each_char:: Calls the given block with each successive character in +self+
14068 * - #each_codepoint:: Calls the given block with each successive codepoint in +self+
14073 * - #autoclose=:: Sets whether +self+ auto-closes.
14074 * - #binmode:: Sets +self+ to binary mode.
14075 * - #close:: Closes +self+.
14076 * - #close_on_exec=:: Sets the close-on-exec flag.
14077 * - #close_read:: Closes +self+ for reading.
14078 * - #close_write:: Closes +self+ for writing.
14079 * - #set_encoding:: Sets the encoding for +self+.
14080 * - #set_encoding_by_bom:: Sets the encoding for +self+, based on its
14081 * Unicode byte-order-mark.
14082 * - #sync=:: Sets the sync-mode to the given value.
14086 * - #autoclose?:: Returns whether +self+ auto-closes.
14087 * - #binmode?:: Returns whether +self+ is in binary mode.
14088 * - #close_on_exec?:: Returns the close-on-exec flag for +self+.
14089 * - #closed?:: Returns whether +self+ is closed.
14090 * - #eof? (aliased as #eof):: Returns whether +self+ is at end-of-file.
14091 * - #external_encoding:: Returns the external encoding object for +self+.
14092 * - #fileno (aliased as #to_i):: Returns the integer file descriptor for +self+
14093 * - #internal_encoding:: Returns the internal encoding object for +self+.
14094 * - #pid:: Returns the process ID of a child process associated with +self+,
14095 * if +self+ was created by ::popen.
14096 * - #stat:: Returns the File::Stat object containing status information for +self+.
14097 * - #sync:: Returns whether +self+ is in sync-mode.
14098 * - #tty (aliased as #isatty):: Returns whether +self+ is a terminal.
14102 * - #fdatasync:: Immediately writes all buffered data in +self+ to disk.
14103 * - #flush:: Flushes any buffered data within +self+ to the underlying
14104 * operating system.
14105 * - #fsync:: Immediately writes all buffered data and attributes in +self+ to disk.
14106 * - #ungetbyte:: Prepends buffer for +self+ with given integer byte or string.
14107 * - #ungetc:: Prepends buffer for +self+ with given string.
14109 * === Low-Level Access
14111 * - ::sysopen:: Opens the file given by its path,
14112 * returning the integer file descriptor.
14113 * - #advise:: Announces the intention to access data from +self+ in a specific way.
14114 * - #fcntl:: Passes a low-level command to the file specified
14115 * by the given file descriptor.
14116 * - #ioctl:: Passes a low-level command to the device specified
14117 * by the given file descriptor.
14118 * - #sysread:: Returns up to the next _n_ bytes read from self using a low-level read.
14119 * - #sysseek:: Sets the offset for +self+.
14120 * - #syswrite:: Writes the given string to +self+ using a low-level write.
14124 * - ::copy_stream:: Copies data from a source to a destination,
14125 * each of which is a filepath or an \IO-like object.
14126 * - ::try_convert:: Returns a new \IO object resulting from converting
14127 * the given object.
14128 * - #inspect:: Returns the string representation of +self+.
14137 #include <sys/cygwin.h>
14138 static struct __cygwin_perfile pf
[] =
14140 {"", O_RDONLY
| O_BINARY
},
14141 {"", O_WRONLY
| O_BINARY
},
14142 {"", O_RDWR
| O_BINARY
},
14143 {"", O_APPEND
| O_BINARY
},
14146 cygwin_internal(CW_PERFILE
, pf
);
14149 rb_eIOError
= rb_define_class("IOError", rb_eStandardError
);
14150 rb_eEOFError
= rb_define_class("EOFError", rb_eIOError
);
14152 id_write
= rb_intern_const("write");
14153 id_read
= rb_intern_const("read");
14154 id_getc
= rb_intern_const("getc");
14155 id_flush
= rb_intern_const("flush");
14156 id_readpartial
= rb_intern_const("readpartial");
14157 id_set_encoding
= rb_intern_const("set_encoding");
14158 id_fileno
= rb_intern_const("fileno");
14160 rb_define_global_function("syscall", rb_f_syscall
, -1);
14162 rb_define_global_function("open", rb_f_open
, -1);
14163 rb_define_global_function("printf", rb_f_printf
, -1);
14164 rb_define_global_function("print", rb_f_print
, -1);
14165 rb_define_global_function("putc", rb_f_putc
, 1);
14166 rb_define_global_function("puts", rb_f_puts
, -1);
14167 rb_define_global_function("gets", rb_f_gets
, -1);
14168 rb_define_global_function("readline", rb_f_readline
, -1);
14169 rb_define_global_function("select", rb_f_select
, -1);
14171 rb_define_global_function("readlines", rb_f_readlines
, -1);
14173 rb_define_global_function("`", rb_f_backquote
, 1);
14175 rb_define_global_function("p", rb_f_p
, -1);
14176 rb_define_method(rb_mKernel
, "display", rb_obj_display
, -1);
14178 rb_cIO
= rb_define_class("IO", rb_cObject
);
14179 rb_include_module(rb_cIO
, rb_mEnumerable
);
14181 rb_define_const(rb_cIO
, "READABLE", INT2NUM(RUBY_IO_READABLE
));
14182 rb_define_const(rb_cIO
, "WRITABLE", INT2NUM(RUBY_IO_WRITABLE
));
14183 rb_define_const(rb_cIO
, "PRIORITY", INT2NUM(RUBY_IO_PRIORITY
));
14185 /* exception to wait for reading. see IO.select. */
14186 rb_mWaitReadable
= rb_define_module_under(rb_cIO
, "WaitReadable");
14187 /* exception to wait for writing. see IO.select. */
14188 rb_mWaitWritable
= rb_define_module_under(rb_cIO
, "WaitWritable");
14189 /* exception to wait for reading by EAGAIN. see IO.select. */
14190 rb_eEAGAINWaitReadable
= rb_define_class_under(rb_cIO
, "EAGAINWaitReadable", rb_eEAGAIN
);
14191 rb_include_module(rb_eEAGAINWaitReadable
, rb_mWaitReadable
);
14192 /* exception to wait for writing by EAGAIN. see IO.select. */
14193 rb_eEAGAINWaitWritable
= rb_define_class_under(rb_cIO
, "EAGAINWaitWritable", rb_eEAGAIN
);
14194 rb_include_module(rb_eEAGAINWaitWritable
, rb_mWaitWritable
);
14195 #if EAGAIN == EWOULDBLOCK
14196 rb_eEWOULDBLOCKWaitReadable
= rb_eEAGAINWaitReadable
;
14197 /* same as IO::EAGAINWaitReadable */
14198 rb_define_const(rb_cIO
, "EWOULDBLOCKWaitReadable", rb_eEAGAINWaitReadable
);
14199 rb_eEWOULDBLOCKWaitWritable
= rb_eEAGAINWaitWritable
;
14200 /* same as IO::EAGAINWaitWritable */
14201 rb_define_const(rb_cIO
, "EWOULDBLOCKWaitWritable", rb_eEAGAINWaitWritable
);
14203 /* exception to wait for reading by EWOULDBLOCK. see IO.select. */
14204 rb_eEWOULDBLOCKWaitReadable
= rb_define_class_under(rb_cIO
, "EWOULDBLOCKWaitReadable", rb_eEWOULDBLOCK
);
14205 rb_include_module(rb_eEWOULDBLOCKWaitReadable
, rb_mWaitReadable
);
14206 /* exception to wait for writing by EWOULDBLOCK. see IO.select. */
14207 rb_eEWOULDBLOCKWaitWritable
= rb_define_class_under(rb_cIO
, "EWOULDBLOCKWaitWritable", rb_eEWOULDBLOCK
);
14208 rb_include_module(rb_eEWOULDBLOCKWaitWritable
, rb_mWaitWritable
);
14210 /* exception to wait for reading by EINPROGRESS. see IO.select. */
14211 rb_eEINPROGRESSWaitReadable
= rb_define_class_under(rb_cIO
, "EINPROGRESSWaitReadable", rb_eEINPROGRESS
);
14212 rb_include_module(rb_eEINPROGRESSWaitReadable
, rb_mWaitReadable
);
14213 /* exception to wait for writing by EINPROGRESS. see IO.select. */
14214 rb_eEINPROGRESSWaitWritable
= rb_define_class_under(rb_cIO
, "EINPROGRESSWaitWritable", rb_eEINPROGRESS
);
14215 rb_include_module(rb_eEINPROGRESSWaitWritable
, rb_mWaitWritable
);
14218 /* This is necessary only for forcing rdoc handle File::open */
14219 rb_define_singleton_method(rb_cFile
, "open", rb_io_s_open
, -1);
14222 rb_define_alloc_func(rb_cIO
, io_alloc
);
14223 rb_define_singleton_method(rb_cIO
, "new", rb_io_s_new
, -1);
14224 rb_define_singleton_method(rb_cIO
, "open", rb_io_s_open
, -1);
14225 rb_define_singleton_method(rb_cIO
, "sysopen", rb_io_s_sysopen
, -1);
14226 rb_define_singleton_method(rb_cIO
, "for_fd", rb_io_s_for_fd
, -1);
14227 rb_define_singleton_method(rb_cIO
, "popen", rb_io_s_popen
, -1);
14228 rb_define_singleton_method(rb_cIO
, "foreach", rb_io_s_foreach
, -1);
14229 rb_define_singleton_method(rb_cIO
, "readlines", rb_io_s_readlines
, -1);
14230 rb_define_singleton_method(rb_cIO
, "read", rb_io_s_read
, -1);
14231 rb_define_singleton_method(rb_cIO
, "binread", rb_io_s_binread
, -1);
14232 rb_define_singleton_method(rb_cIO
, "write", rb_io_s_write
, -1);
14233 rb_define_singleton_method(rb_cIO
, "binwrite", rb_io_s_binwrite
, -1);
14234 rb_define_singleton_method(rb_cIO
, "select", rb_f_select
, -1);
14235 rb_define_singleton_method(rb_cIO
, "pipe", rb_io_s_pipe
, -1);
14236 rb_define_singleton_method(rb_cIO
, "try_convert", rb_io_s_try_convert
, 1);
14237 rb_define_singleton_method(rb_cIO
, "copy_stream", rb_io_s_copy_stream
, -1);
14239 rb_define_method(rb_cIO
, "initialize", rb_io_initialize
, -1);
14241 rb_output_fs
= Qnil
;
14242 rb_define_hooked_variable("$,", &rb_output_fs
, 0, deprecated_str_setter
);
14244 rb_default_rs
= rb_fstring_lit("\n"); /* avoid modifying RS_default */
14245 rb_gc_register_mark_object(rb_default_rs
);
14246 rb_rs
= rb_default_rs
;
14247 rb_output_rs
= Qnil
;
14248 rb_define_hooked_variable("$/", &rb_rs
, 0, deprecated_str_setter
);
14249 rb_define_hooked_variable("$-0", &rb_rs
, 0, deprecated_str_setter
);
14250 rb_define_hooked_variable("$\\", &rb_output_rs
, 0, deprecated_str_setter
);
14252 rb_define_virtual_variable("$_", get_LAST_READ_LINE
, set_LAST_READ_LINE
);
14253 rb_gvar_ractor_local("$_");
14255 rb_define_method(rb_cIO
, "initialize_copy", rb_io_init_copy
, 1);
14256 rb_define_method(rb_cIO
, "reopen", rb_io_reopen
, -1);
14258 rb_define_method(rb_cIO
, "print", rb_io_print
, -1);
14259 rb_define_method(rb_cIO
, "putc", rb_io_putc
, 1);
14260 rb_define_method(rb_cIO
, "puts", rb_io_puts
, -1);
14261 rb_define_method(rb_cIO
, "printf", rb_io_printf
, -1);
14263 rb_define_method(rb_cIO
, "each", rb_io_each_line
, -1);
14264 rb_define_method(rb_cIO
, "each_line", rb_io_each_line
, -1);
14265 rb_define_method(rb_cIO
, "each_byte", rb_io_each_byte
, 0);
14266 rb_define_method(rb_cIO
, "each_char", rb_io_each_char
, 0);
14267 rb_define_method(rb_cIO
, "each_codepoint", rb_io_each_codepoint
, 0);
14269 rb_define_method(rb_cIO
, "syswrite", rb_io_syswrite
, 1);
14270 rb_define_method(rb_cIO
, "sysread", rb_io_sysread
, -1);
14272 rb_define_method(rb_cIO
, "pread", rb_io_pread
, -1);
14273 rb_define_method(rb_cIO
, "pwrite", rb_io_pwrite
, 2);
14275 rb_define_method(rb_cIO
, "fileno", rb_io_fileno
, 0);
14276 rb_define_alias(rb_cIO
, "to_i", "fileno");
14277 rb_define_method(rb_cIO
, "to_io", rb_io_to_io
, 0);
14279 rb_define_method(rb_cIO
, "fsync", rb_io_fsync
, 0);
14280 rb_define_method(rb_cIO
, "fdatasync", rb_io_fdatasync
, 0);
14281 rb_define_method(rb_cIO
, "sync", rb_io_sync
, 0);
14282 rb_define_method(rb_cIO
, "sync=", rb_io_set_sync
, 1);
14284 rb_define_method(rb_cIO
, "lineno", rb_io_lineno
, 0);
14285 rb_define_method(rb_cIO
, "lineno=", rb_io_set_lineno
, 1);
14287 rb_define_method(rb_cIO
, "readlines", rb_io_readlines
, -1);
14289 rb_define_method(rb_cIO
, "readpartial", io_readpartial
, -1);
14290 rb_define_method(rb_cIO
, "read", io_read
, -1);
14291 rb_define_method(rb_cIO
, "write", io_write_m
, -1);
14292 rb_define_method(rb_cIO
, "gets", rb_io_gets_m
, -1);
14293 rb_define_method(rb_cIO
, "readline", rb_io_readline
, -1);
14294 rb_define_method(rb_cIO
, "getc", rb_io_getc
, 0);
14295 rb_define_method(rb_cIO
, "getbyte", rb_io_getbyte
, 0);
14296 rb_define_method(rb_cIO
, "readchar", rb_io_readchar
, 0);
14297 rb_define_method(rb_cIO
, "readbyte", rb_io_readbyte
, 0);
14298 rb_define_method(rb_cIO
, "ungetbyte",rb_io_ungetbyte
, 1);
14299 rb_define_method(rb_cIO
, "ungetc",rb_io_ungetc
, 1);
14300 rb_define_method(rb_cIO
, "<<", rb_io_addstr
, 1);
14301 rb_define_method(rb_cIO
, "flush", rb_io_flush
, 0);
14302 rb_define_method(rb_cIO
, "tell", rb_io_tell
, 0);
14303 rb_define_method(rb_cIO
, "seek", rb_io_seek_m
, -1);
14304 /* Set I/O position from the beginning */
14305 rb_define_const(rb_cIO
, "SEEK_SET", INT2FIX(SEEK_SET
));
14306 /* Set I/O position from the current position */
14307 rb_define_const(rb_cIO
, "SEEK_CUR", INT2FIX(SEEK_CUR
));
14308 /* Set I/O position from the end */
14309 rb_define_const(rb_cIO
, "SEEK_END", INT2FIX(SEEK_END
));
14311 /* Set I/O position to the next location containing data */
14312 rb_define_const(rb_cIO
, "SEEK_DATA", INT2FIX(SEEK_DATA
));
14315 /* Set I/O position to the next hole */
14316 rb_define_const(rb_cIO
, "SEEK_HOLE", INT2FIX(SEEK_HOLE
));
14318 rb_define_method(rb_cIO
, "rewind", rb_io_rewind
, 0);
14319 rb_define_method(rb_cIO
, "pos", rb_io_tell
, 0);
14320 rb_define_method(rb_cIO
, "pos=", rb_io_set_pos
, 1);
14321 rb_define_method(rb_cIO
, "eof", rb_io_eof
, 0);
14322 rb_define_method(rb_cIO
, "eof?", rb_io_eof
, 0);
14324 rb_define_method(rb_cIO
, "close_on_exec?", rb_io_close_on_exec_p
, 0);
14325 rb_define_method(rb_cIO
, "close_on_exec=", rb_io_set_close_on_exec
, 1);
14327 rb_define_method(rb_cIO
, "close", rb_io_close_m
, 0);
14328 rb_define_method(rb_cIO
, "closed?", rb_io_closed
, 0);
14329 rb_define_method(rb_cIO
, "close_read", rb_io_close_read
, 0);
14330 rb_define_method(rb_cIO
, "close_write", rb_io_close_write
, 0);
14332 rb_define_method(rb_cIO
, "isatty", rb_io_isatty
, 0);
14333 rb_define_method(rb_cIO
, "tty?", rb_io_isatty
, 0);
14334 rb_define_method(rb_cIO
, "binmode", rb_io_binmode_m
, 0);
14335 rb_define_method(rb_cIO
, "binmode?", rb_io_binmode_p
, 0);
14336 rb_define_method(rb_cIO
, "sysseek", rb_io_sysseek
, -1);
14337 rb_define_method(rb_cIO
, "advise", rb_io_advise
, -1);
14339 rb_define_method(rb_cIO
, "ioctl", rb_io_ioctl
, -1);
14340 rb_define_method(rb_cIO
, "fcntl", rb_io_fcntl
, -1);
14341 rb_define_method(rb_cIO
, "pid", rb_io_pid
, 0);
14342 rb_define_method(rb_cIO
, "inspect", rb_io_inspect
, 0);
14344 rb_define_method(rb_cIO
, "external_encoding", rb_io_external_encoding
, 0);
14345 rb_define_method(rb_cIO
, "internal_encoding", rb_io_internal_encoding
, 0);
14346 rb_define_method(rb_cIO
, "set_encoding", rb_io_set_encoding
, -1);
14347 rb_define_method(rb_cIO
, "set_encoding_by_bom", rb_io_set_encoding_by_bom
, 0);
14349 rb_define_method(rb_cIO
, "autoclose?", rb_io_autoclose_p
, 0);
14350 rb_define_method(rb_cIO
, "autoclose=", rb_io_set_autoclose
, 1);
14352 rb_define_virtual_variable("$stdin", stdin_getter
, stdin_setter
);
14353 rb_define_virtual_variable("$stdout", stdout_getter
, stdout_setter
);
14354 rb_define_virtual_variable("$>", stdout_getter
, stdout_setter
);
14355 rb_define_virtual_variable("$stderr", stderr_getter
, stderr_setter
);
14357 rb_gvar_ractor_local("$stdin");
14358 rb_gvar_ractor_local("$stdout");
14359 rb_gvar_ractor_local("$>");
14360 rb_gvar_ractor_local("$stderr");
14362 rb_stdin
= rb_io_prep_stdin();
14363 rb_stdout
= rb_io_prep_stdout();
14364 rb_stderr
= rb_io_prep_stderr();
14366 rb_global_variable(&rb_stdin
);
14367 rb_global_variable(&rb_stdout
);
14368 rb_global_variable(&rb_stderr
);
14370 orig_stdout
= rb_stdout
;
14371 orig_stderr
= rb_stderr
;
14373 /* Holds the original stdin */
14374 rb_define_global_const("STDIN", rb_stdin
);
14375 /* Holds the original stdout */
14376 rb_define_global_const("STDOUT", rb_stdout
);
14377 /* Holds the original stderr */
14378 rb_define_global_const("STDERR", rb_stderr
);
14381 /* Hack to get rdoc to regard ARGF as a class: */
14382 rb_cARGF
= rb_define_class("ARGF", rb_cObject
);
14385 rb_cARGF
= rb_class_new(rb_cObject
);
14386 rb_set_class_path(rb_cARGF
, rb_cObject
, "ARGF.class");
14387 rb_define_alloc_func(rb_cARGF
, argf_alloc
);
14389 rb_include_module(rb_cARGF
, rb_mEnumerable
);
14391 rb_define_method(rb_cARGF
, "initialize", argf_initialize
, -2);
14392 rb_define_method(rb_cARGF
, "initialize_copy", argf_initialize_copy
, 1);
14393 rb_define_method(rb_cARGF
, "to_s", argf_to_s
, 0);
14394 rb_define_alias(rb_cARGF
, "inspect", "to_s");
14395 rb_define_method(rb_cARGF
, "argv", argf_argv
, 0);
14397 rb_define_method(rb_cARGF
, "fileno", argf_fileno
, 0);
14398 rb_define_method(rb_cARGF
, "to_i", argf_fileno
, 0);
14399 rb_define_method(rb_cARGF
, "to_io", argf_to_io
, 0);
14400 rb_define_method(rb_cARGF
, "to_write_io", argf_write_io
, 0);
14401 rb_define_method(rb_cARGF
, "each", argf_each_line
, -1);
14402 rb_define_method(rb_cARGF
, "each_line", argf_each_line
, -1);
14403 rb_define_method(rb_cARGF
, "each_byte", argf_each_byte
, 0);
14404 rb_define_method(rb_cARGF
, "each_char", argf_each_char
, 0);
14405 rb_define_method(rb_cARGF
, "each_codepoint", argf_each_codepoint
, 0);
14407 rb_define_method(rb_cARGF
, "read", argf_read
, -1);
14408 rb_define_method(rb_cARGF
, "readpartial", argf_readpartial
, -1);
14409 rb_define_method(rb_cARGF
, "read_nonblock", argf_read_nonblock
, -1);
14410 rb_define_method(rb_cARGF
, "readlines", argf_readlines
, -1);
14411 rb_define_method(rb_cARGF
, "to_a", argf_readlines
, -1);
14412 rb_define_method(rb_cARGF
, "gets", argf_gets
, -1);
14413 rb_define_method(rb_cARGF
, "readline", argf_readline
, -1);
14414 rb_define_method(rb_cARGF
, "getc", argf_getc
, 0);
14415 rb_define_method(rb_cARGF
, "getbyte", argf_getbyte
, 0);
14416 rb_define_method(rb_cARGF
, "readchar", argf_readchar
, 0);
14417 rb_define_method(rb_cARGF
, "readbyte", argf_readbyte
, 0);
14418 rb_define_method(rb_cARGF
, "tell", argf_tell
, 0);
14419 rb_define_method(rb_cARGF
, "seek", argf_seek_m
, -1);
14420 rb_define_method(rb_cARGF
, "rewind", argf_rewind
, 0);
14421 rb_define_method(rb_cARGF
, "pos", argf_tell
, 0);
14422 rb_define_method(rb_cARGF
, "pos=", argf_set_pos
, 1);
14423 rb_define_method(rb_cARGF
, "eof", argf_eof
, 0);
14424 rb_define_method(rb_cARGF
, "eof?", argf_eof
, 0);
14425 rb_define_method(rb_cARGF
, "binmode", argf_binmode_m
, 0);
14426 rb_define_method(rb_cARGF
, "binmode?", argf_binmode_p
, 0);
14428 rb_define_method(rb_cARGF
, "write", argf_write
, 1);
14429 rb_define_method(rb_cARGF
, "print", rb_io_print
, -1);
14430 rb_define_method(rb_cARGF
, "putc", rb_io_putc
, 1);
14431 rb_define_method(rb_cARGF
, "puts", rb_io_puts
, -1);
14432 rb_define_method(rb_cARGF
, "printf", rb_io_printf
, -1);
14434 rb_define_method(rb_cARGF
, "filename", argf_filename
, 0);
14435 rb_define_method(rb_cARGF
, "path", argf_filename
, 0);
14436 rb_define_method(rb_cARGF
, "file", argf_file
, 0);
14437 rb_define_method(rb_cARGF
, "skip", argf_skip
, 0);
14438 rb_define_method(rb_cARGF
, "close", argf_close_m
, 0);
14439 rb_define_method(rb_cARGF
, "closed?", argf_closed
, 0);
14441 rb_define_method(rb_cARGF
, "lineno", argf_lineno
, 0);
14442 rb_define_method(rb_cARGF
, "lineno=", argf_set_lineno
, 1);
14444 rb_define_method(rb_cARGF
, "inplace_mode", argf_inplace_mode_get
, 0);
14445 rb_define_method(rb_cARGF
, "inplace_mode=", argf_inplace_mode_set
, 1);
14447 rb_define_method(rb_cARGF
, "external_encoding", argf_external_encoding
, 0);
14448 rb_define_method(rb_cARGF
, "internal_encoding", argf_internal_encoding
, 0);
14449 rb_define_method(rb_cARGF
, "set_encoding", argf_set_encoding
, -1);
14451 argf
= rb_class_new_instance(0, 0, rb_cARGF
);
14453 rb_define_readonly_variable("$<", &argf
);
14455 * ARGF is a stream designed for use in scripts that process files given
14456 * as command-line arguments or passed in via STDIN.
14458 * See ARGF (the class) for more details.
14460 rb_define_global_const("ARGF", argf
);
14462 rb_define_hooked_variable("$.", &argf
, argf_lineno_getter
, argf_lineno_setter
);
14463 rb_define_hooked_variable("$FILENAME", &argf
, argf_filename_getter
, rb_gvar_readonly_setter
);
14464 ARGF
.filename
= rb_str_new2("-");
14466 rb_define_hooked_variable("$-i", &argf
, opt_i_get
, opt_i_set
);
14467 rb_gvar_ractor_local("$-i");
14469 rb_define_hooked_variable("$*", &argf
, argf_argv_getter
, rb_gvar_readonly_setter
);
14471 #if defined (_WIN32) || defined(__CYGWIN__)
14472 atexit(pipe_atexit
);
14477 rb_define_method(rb_cFile
, "initialize", rb_file_initialize
, -1);
14479 sym_mode
= ID2SYM(rb_intern_const("mode"));
14480 sym_perm
= ID2SYM(rb_intern_const("perm"));
14481 sym_flags
= ID2SYM(rb_intern_const("flags"));
14482 sym_extenc
= ID2SYM(rb_intern_const("external_encoding"));
14483 sym_intenc
= ID2SYM(rb_intern_const("internal_encoding"));
14484 sym_encoding
= ID2SYM(rb_id_encoding());
14485 sym_open_args
= ID2SYM(rb_intern_const("open_args"));
14486 sym_textmode
= ID2SYM(rb_intern_const("textmode"));
14487 sym_binmode
= ID2SYM(rb_intern_const("binmode"));
14488 sym_autoclose
= ID2SYM(rb_intern_const("autoclose"));
14489 sym_normal
= ID2SYM(rb_intern_const("normal"));
14490 sym_sequential
= ID2SYM(rb_intern_const("sequential"));
14491 sym_random
= ID2SYM(rb_intern_const("random"));
14492 sym_willneed
= ID2SYM(rb_intern_const("willneed"));
14493 sym_dontneed
= ID2SYM(rb_intern_const("dontneed"));
14494 sym_noreuse
= ID2SYM(rb_intern_const("noreuse"));
14495 sym_SET
= ID2SYM(rb_intern_const("SET"));
14496 sym_CUR
= ID2SYM(rb_intern_const("CUR"));
14497 sym_END
= ID2SYM(rb_intern_const("END"));
14499 sym_DATA
= ID2SYM(rb_intern_const("DATA"));
14502 sym_HOLE
= ID2SYM(rb_intern_const("HOLE"));
14504 sym_wait_readable
= ID2SYM(rb_intern_const("wait_readable"));
14505 sym_wait_writable
= ID2SYM(rb_intern_const("wait_writable"));
14508 #include "io.rbinc"