Ruby: io.c Source File

Ruby 3.0.5p211 (2022-11-24 revision ba5cf0f7c52d4d35cc6a173c89eda98ceffa2dcf)

io.c
Go to the documentation of this file.
1/**********************************************************************
2
3 io.c -
4
5 $Author$
6 created at: Fri Oct 15 18:08:59 JST 1993
7
8 Copyright (C) 1993-2007 Yukihiro Matsumoto
9 Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
10 Copyright (C) 2000 Information-technology Promotion Agency, Japan
11
12**********************************************************************/
13
14#include "ruby/internal/config.h"
15
16#include "internal/scheduler.h"
17
18#ifdef _WIN32
19# include "ruby/ruby.h"
20# include "ruby/io.h"
21#endif
22
23#include <ctype.h>
24#include <errno.h>
25#include <stddef.h>
26
27/* non-Linux poll may not work on all FDs */
28#if defined(HAVE_POLL)
29# if defined(__linux__)
30# define USE_POLL 1
31# endif
32# if defined(__FreeBSD_version) && __FreeBSD_version >= 1100000
33# define USE_POLL 1
34# endif
35#endif
36
37#ifndef USE_POLL
38# define USE_POLL 0
39#endif
40
41#undef free
42#define free(x) xfree(x)
43
44#if defined(DOSISH) || defined(__CYGWIN__)
45#include <io.h>
46#endif
47
48#include <sys/types.h>
49#if defined HAVE_NET_SOCKET_H
50# include <net/socket.h>
51#elif defined HAVE_SYS_SOCKET_H
52# include <sys/socket.h>
53#endif
54
55#if defined(__BOW__) || defined(__CYGWIN__) || defined(_WIN32)
56# define NO_SAFE_RENAME
57#endif
58
59#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__sun) || defined(_nec_ews)
60# define USE_SETVBUF
61#endif
62
63#ifdef __QNXNTO__
64#include <unix.h>
65#endif
66
67#include <sys/types.h>
68#if defined(HAVE_SYS_IOCTL_H) && !defined(_WIN32)
69#include <sys/ioctl.h>
70#endif
71#if defined(HAVE_FCNTL_H) || defined(_WIN32)
72#include <fcntl.h>
73#elif defined(HAVE_SYS_FCNTL_H)
74#include <sys/fcntl.h>
75#endif
76
77#if !HAVE_OFF_T && !defined(off_t)
78# define off_t long
79#endif
80
81#ifdef HAVE_SYS_TIME_H
82# include <sys/time.h>
83#endif
84
85#include <sys/stat.h>
86
87#if defined(HAVE_SYS_PARAM_H) || defined(__HIUX_MPP__)
88# include <sys/param.h>
89#endif
90
91#if !defined NOFILE
92# define NOFILE 64
93#endif
94
95#ifdef HAVE_UNISTD_H
96#include <unistd.h>
97#endif
98
99#ifdef HAVE_SYSCALL_H
100#include <syscall.h>
101#elif defined HAVE_SYS_SYSCALL_H
102#include <sys/syscall.h>
103#endif
104
105#ifdef HAVE_SYS_UIO_H
106#include <sys/uio.h>
107#endif
108
109#ifdef HAVE_SYS_WAIT_H
110# include <sys/wait.h> /* for WNOHANG on BSD */
111#endif
112
113#ifdef HAVE_COPYFILE_H
114# include <copyfile.h>
115#endif
116
117#include "ruby/internal/stdbool.h"
118#include "ccan/list/list.h"
119#include "dln.h"
120#include "encindex.h"
121#include "id.h"
122#include "internal.h"
123#include "internal/encoding.h"
124#include "internal/error.h"
125#include "internal/inits.h"
126#include "internal/io.h"
127#include "internal/numeric.h"
128#include "internal/object.h"
129#include "internal/process.h"
130#include "internal/thread.h"
131#include "internal/transcode.h"
132#include "internal/variable.h"
133#include "ruby/io.h"
134#include "ruby/thread.h"
135#include "ruby/util.h"
136#include "ruby_atomic.h"
137#include "ruby/ractor.h"
138
139#if !USE_POLL
140# include "vm_core.h"
141#endif
142
143#include "builtin.h"
144
145#ifndef O_ACCMODE
146#define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR)
147#endif
148
149#if SIZEOF_OFF_T > SIZEOF_LONG && !defined(HAVE_LONG_LONG)
150# error off_t is bigger than long, but you have no long long...
151#endif
152
153#ifndef PIPE_BUF
154# ifdef _POSIX_PIPE_BUF
155# define PIPE_BUF _POSIX_PIPE_BUF
156# else
157# define PIPE_BUF 512 /* is this ok? */
158# endif
159#endif
160
161#ifndef EWOULDBLOCK
162# define EWOULDBLOCK EAGAIN
163#endif
164
165#if defined(HAVE___SYSCALL) && (defined(__APPLE__) || defined(__OpenBSD__))
166/* Mac OS X and OpenBSD have __syscall but don't define it in headers */
167 off_t __syscall(quad_t number, ...);
168#endif
169
170#define IO_RBUF_CAPA_MIN 8192
171#define IO_CBUF_CAPA_MIN (128*1024)
172#define IO_RBUF_CAPA_FOR(fptr) (NEED_READCONV(fptr) ? IO_CBUF_CAPA_MIN : IO_RBUF_CAPA_MIN)
173#define IO_WBUF_CAPA_MIN 8192
174
175/* define system APIs */
176#ifdef _WIN32
177#undef open
178#define open rb_w32_uopen
179#undef rename
180#define rename(f, t) rb_w32_urename((f), (t))
181#endif
182
183 VALUE rb_cIO;
184 VALUE rb_eEOFError;
185 VALUE rb_eIOError;
186 VALUE rb_mWaitReadable;
187 VALUE rb_mWaitWritable;
188
189static VALUE rb_eEAGAINWaitReadable;
190static VALUE rb_eEAGAINWaitWritable;
191static VALUE rb_eEWOULDBLOCKWaitReadable;
192static VALUE rb_eEWOULDBLOCKWaitWritable;
193static VALUE rb_eEINPROGRESSWaitWritable;
194static VALUE rb_eEINPROGRESSWaitReadable;
195
196 VALUE rb_stdin, rb_stdout, rb_stderr;
197static VALUE orig_stdout, orig_stderr;
198
199 VALUE rb_output_fs;
200 VALUE rb_rs;
201 VALUE rb_output_rs;
202 VALUE rb_default_rs;
203
204static VALUE argf;
205
206static ID id_write, id_read, id_getc, id_flush, id_readpartial, id_set_encoding;
207static VALUE sym_mode, sym_perm, sym_flags, sym_extenc, sym_intenc, sym_encoding, sym_open_args;
208static VALUE sym_textmode, sym_binmode, sym_autoclose;
209static VALUE sym_SET, sym_CUR, sym_END;
210static VALUE sym_wait_readable, sym_wait_writable;
211#ifdef SEEK_DATA
212static VALUE sym_DATA;
213#endif
214#ifdef SEEK_HOLE
215static VALUE sym_HOLE;
216#endif
217
218static VALUE rb_io_initialize(int argc, VALUE *argv, VALUE io);
219static VALUE prep_io(int fd, int fmode, VALUE klass, const char *path);
220
221 struct argf {
222 VALUE filename, current_file;
223 long last_lineno; /* $. */
224 long lineno;
225 VALUE argv;
226 VALUE inplace;
227 struct rb_io_enc_t encs;
228 int8_t init_p, next_p, binmode;
229};
230
231static rb_atomic_t max_file_descriptor = NOFILE;
232void
233 rb_update_max_fd(int fd)
234{
235 rb_atomic_t afd = (rb_atomic_t)fd;
236 rb_atomic_t max_fd = max_file_descriptor;
237 int err;
238
239 if (fd < 0 || afd <= max_fd)
240 return;
241
242#if defined(HAVE_FCNTL) && defined(F_GETFL)
243 err = fcntl(fd, F_GETFL) == -1;
244#else
245 {
246 struct stat buf;
247 err = fstat(fd, &buf) != 0;
248 }
249#endif
250 if (err && errno == EBADF) {
251 rb_bug("rb_update_max_fd: invalid fd (%d) given.", fd);
252 }
253
254 while (max_fd < afd) {
255 max_fd = ATOMIC_CAS(max_file_descriptor, max_fd, afd);
256 }
257}
258
259void
260 rb_maygvl_fd_fix_cloexec(int fd)
261{
262 /* MinGW don't have F_GETFD and FD_CLOEXEC. [ruby-core:40281] */
263#if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
264 int flags, flags2, ret;
265 flags = fcntl(fd, F_GETFD); /* should not fail except EBADF. */
266 if (flags == -1) {
267 rb_bug("rb_maygvl_fd_fix_cloexec: fcntl(%d, F_GETFD) failed: %s", fd, strerror(errno));
268 }
269 if (fd <= 2)
270 flags2 = flags & ~FD_CLOEXEC; /* Clear CLOEXEC for standard file descriptors: 0, 1, 2. */
271 else
272 flags2 = flags | FD_CLOEXEC; /* Set CLOEXEC for non-standard file descriptors: 3, 4, 5, ... */
273 if (flags != flags2) {
274 ret = fcntl(fd, F_SETFD, flags2);
275 if (ret != 0) {
276 rb_bug("rb_maygvl_fd_fix_cloexec: fcntl(%d, F_SETFD, %d) failed: %s", fd, flags2, strerror(errno));
277 }
278 }
279#endif
280}
281
282void
283 rb_fd_fix_cloexec(int fd)
284{
285 rb_maygvl_fd_fix_cloexec(fd);
286 rb_update_max_fd(fd);
287}
288
289/* this is only called once */
290static int
291rb_fix_detect_o_cloexec(int fd)
292{
293#if defined(O_CLOEXEC) && defined(F_GETFD)
294 int flags = fcntl(fd, F_GETFD);
295
296 if (flags == -1)
297 rb_bug("rb_fix_detect_o_cloexec: fcntl(%d, F_GETFD) failed: %s", fd, strerror(errno));
298
299 if (flags & FD_CLOEXEC)
300 return 1;
301#endif /* fall through if O_CLOEXEC does not work: */
302 rb_maygvl_fd_fix_cloexec(fd);
303 return 0;
304}
305
306int
307 rb_cloexec_open(const char *pathname, int flags, mode_t mode)
308{
309 int ret;
310 static int o_cloexec_state = -1; /* <0: unknown, 0: ignored, >0: working */
311
312 static const int retry_interval = 0;
313 static const int retry_max_count = 10000;
314
315 int retry_count = 0;
316
317#ifdef O_CLOEXEC
318 /* O_CLOEXEC is available since Linux 2.6.23. Linux 2.6.18 silently ignore it. */
319 flags |= O_CLOEXEC;
320#elif defined O_NOINHERIT
321 flags |= O_NOINHERIT;
322#endif
323
324 while ((ret = open(pathname, flags, mode)) == -1) {
325 int e = errno;
326 if (e != EAGAIN && e != EWOULDBLOCK) break;
327 if (retry_count++ >= retry_max_count) break;
328
329 sleep(retry_interval);
330 }
331
332 if (ret < 0) return ret;
333 if (ret <= 2 || o_cloexec_state == 0) {
334 rb_maygvl_fd_fix_cloexec(ret);
335 }
336 else if (o_cloexec_state > 0) {
337 return ret;
338 }
339 else {
340 o_cloexec_state = rb_fix_detect_o_cloexec(ret);
341 }
342 return ret;
343}
344
345int
346 rb_cloexec_dup(int oldfd)
347{
348 /* Don't allocate standard file descriptors: 0, 1, 2 */
349 return rb_cloexec_fcntl_dupfd(oldfd, 3);
350}
351
352int
353 rb_cloexec_dup2(int oldfd, int newfd)
354{
355 int ret;
356
357 /* When oldfd == newfd, dup2 succeeds but dup3 fails with EINVAL.
358 * rb_cloexec_dup2 succeeds as dup2. */
359 if (oldfd == newfd) {
360 ret = newfd;
361 }
362 else {
363#if defined(HAVE_DUP3) && defined(O_CLOEXEC)
364 static int try_dup3 = 1;
365 if (2 < newfd && try_dup3) {
366 ret = dup3(oldfd, newfd, O_CLOEXEC);
367 if (ret != -1)
368 return ret;
369 /* dup3 is available since Linux 2.6.27, glibc 2.9. */
370 if (errno == ENOSYS) {
371 try_dup3 = 0;
372 ret = dup2(oldfd, newfd);
373 }
374 }
375 else {
376 ret = dup2(oldfd, newfd);
377 }
378#else
379 ret = dup2(oldfd, newfd);
380#endif
381 if (ret < 0) return ret;
382 }
383 rb_maygvl_fd_fix_cloexec(ret);
384 return ret;
385}
386
387static int
388rb_fd_set_nonblock(int fd)
389{
390#ifdef _WIN32
391 return rb_w32_set_nonblock(fd);
392#elif defined(F_GETFL)
393 int oflags = fcntl(fd, F_GETFL);
394
395 if (oflags == -1)
396 return -1;
397 if (oflags & O_NONBLOCK)
398 return 0;
399 oflags |= O_NONBLOCK;
400 return fcntl(fd, F_SETFL, oflags);
401#endif
402 return 0;
403}
404
405int
406 rb_cloexec_pipe(int descriptors[2])
407{
408#ifdef HAVE_PIPE2
409 int result = pipe2(descriptors, O_CLOEXEC | O_NONBLOCK);
410#else
411 int result = pipe(descriptors);
412#endif
413
414 if (result < 0)
415 return result;
416
417#ifdef __CYGWIN__
418 if (result == 0 && descriptors[1] == -1) {
419 close(descriptors[0]);
420 descriptors[0] = -1;
421 errno = ENFILE;
422 return -1;
423 }
424#endif
425
426#ifndef HAVE_PIPE2
427 rb_maygvl_fd_fix_cloexec(descriptors[0]);
428 rb_maygvl_fd_fix_cloexec(descriptors[1]);
429
430#ifndef _WIN32
431 rb_fd_set_nonblock(descriptors[0]);
432 rb_fd_set_nonblock(descriptors[1]);
433#endif
434#endif
435
436 return result;
437}
438
439int
440 rb_cloexec_fcntl_dupfd(int fd, int minfd)
441{
442 int ret;
443
444#if defined(HAVE_FCNTL) && defined(F_DUPFD_CLOEXEC) && defined(F_DUPFD)
445 static int try_dupfd_cloexec = 1;
446 if (try_dupfd_cloexec) {
447 ret = fcntl(fd, F_DUPFD_CLOEXEC, minfd);
448 if (ret != -1) {
449 if (ret <= 2)
450 rb_maygvl_fd_fix_cloexec(ret);
451 return ret;
452 }
453 /* F_DUPFD_CLOEXEC is available since Linux 2.6.24. Linux 2.6.18 fails with EINVAL */
454 if (errno == EINVAL) {
455 ret = fcntl(fd, F_DUPFD, minfd);
456 if (ret != -1) {
457 try_dupfd_cloexec = 0;
458 }
459 }
460 }
461 else {
462 ret = fcntl(fd, F_DUPFD, minfd);
463 }
464#elif defined(HAVE_FCNTL) && defined(F_DUPFD)
465 ret = fcntl(fd, F_DUPFD, minfd);
466#elif defined(HAVE_DUP)
467 ret = dup(fd);
468 if (ret >= 0 && ret < minfd) {
469 const int prev_fd = ret;
470 ret = rb_cloexec_fcntl_dupfd(fd, minfd);
471 close(prev_fd);
472 }
473 return ret;
474#else
475# error "dup() or fcntl(F_DUPFD) must be supported."
476#endif
477 if (ret < 0) return ret;
478 rb_maygvl_fd_fix_cloexec(ret);
479 return ret;
480}
481
482#define argf_of(obj) (*(struct argf *)DATA_PTR(obj))
483#define ARGF argf_of(argf)
484
485#define GetWriteIO(io) rb_io_get_write_io(io)
486
487#define READ_DATA_PENDING(fptr) ((fptr)->rbuf.len)
488#define READ_DATA_PENDING_COUNT(fptr) ((fptr)->rbuf.len)
489#define READ_DATA_PENDING_PTR(fptr) ((fptr)->rbuf.ptr+(fptr)->rbuf.off)
490#define READ_DATA_BUFFERED(fptr) READ_DATA_PENDING(fptr)
491
492#define READ_CHAR_PENDING(fptr) ((fptr)->cbuf.len)
493#define READ_CHAR_PENDING_COUNT(fptr) ((fptr)->cbuf.len)
494#define READ_CHAR_PENDING_PTR(fptr) ((fptr)->cbuf.ptr+(fptr)->cbuf.off)
495
496#if defined(_WIN32)
497#define WAIT_FD_IN_WIN32(fptr) \
498 (rb_w32_io_cancelable_p((fptr)->fd) ? 0 : rb_thread_wait_fd((fptr)->fd))
499#else
500#define WAIT_FD_IN_WIN32(fptr)
501#endif
502
503#define READ_CHECK(fptr) do {\
504 if (!READ_DATA_PENDING(fptr)) {\
505 WAIT_FD_IN_WIN32(fptr);\
506 rb_io_check_closed(fptr);\
507 }\
508} while(0)
509
510#ifndef S_ISSOCK
511# ifdef _S_ISSOCK
512# define S_ISSOCK(m) _S_ISSOCK(m)
513# else
514# ifdef _S_IFSOCK
515# define S_ISSOCK(m) (((m) & S_IFMT) == _S_IFSOCK)
516# else
517# ifdef S_IFSOCK
518# define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
519# endif
520# endif
521# endif
522#endif
523
524static int io_fflush(rb_io_t *);
525static rb_io_t *flush_before_seek(rb_io_t *fptr);
526
527#define FMODE_PREP (1<<16)
528#define FMODE_SIGNAL_ON_EPIPE (1<<17)
529
530#define fptr_signal_on_epipe(fptr) \
531 (((fptr)->mode & FMODE_SIGNAL_ON_EPIPE) != 0)
532
533#define fptr_set_signal_on_epipe(fptr, flag) \
534 ((flag) ? \
535 (fptr)->mode |= FMODE_SIGNAL_ON_EPIPE : \
536 (fptr)->mode &= ~FMODE_SIGNAL_ON_EPIPE)
537
538extern ID ruby_static_id_signo;
539
540 NORETURN(static void raise_on_write(rb_io_t *fptr, int e, VALUE errinfo));
541static void
542raise_on_write(rb_io_t *fptr, int e, VALUE errinfo)
543{
544#if defined EPIPE
545 if (fptr_signal_on_epipe(fptr) && (e == EPIPE)) {
546 const VALUE sig =
547# if defined SIGPIPE
548 INT2FIX(SIGPIPE) - INT2FIX(0) +
549# endif
550 INT2FIX(0);
551 rb_ivar_set(errinfo, ruby_static_id_signo, sig);
552 }
553#endif
554 rb_exc_raise(errinfo);
555}
556
557#define rb_sys_fail_on_write(fptr) \
558 do { \
559 int e = errno; \
560 raise_on_write(fptr, e, rb_syserr_new_path(e, (fptr)->pathv)); \
561 } while (0)
562
563#define NEED_NEWLINE_DECORATOR_ON_READ(fptr) ((fptr)->mode & FMODE_TEXTMODE)
564#define NEED_NEWLINE_DECORATOR_ON_WRITE(fptr) ((fptr)->mode & FMODE_TEXTMODE)
565#if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
566/* Windows */
567# define DEFAULT_TEXTMODE FMODE_TEXTMODE
568# define TEXTMODE_NEWLINE_DECORATOR_ON_WRITE ECONV_CRLF_NEWLINE_DECORATOR
569/*
570 * CRLF newline is set as default newline decorator.
571 * If only CRLF newline conversion is needed, we use binary IO process
572 * with OS's text mode for IO performance improvement.
573 * If encoding conversion is needed or a user sets text mode, we use encoding
574 * conversion IO process and universal newline decorator by default.
575 */
576#define NEED_READCONV(fptr) ((fptr)->encs.enc2 != NULL || (fptr)->encs.ecflags & ~ECONV_CRLF_NEWLINE_DECORATOR)
577#define WRITECONV_MASK ( \
578 (ECONV_DECORATOR_MASK & ~ECONV_CRLF_NEWLINE_DECORATOR)|\
579 ECONV_STATEFUL_DECORATOR_MASK|\
580 0)
581#define NEED_WRITECONV(fptr) ( \
582 ((fptr)->encs.enc != NULL && (fptr)->encs.enc != rb_ascii8bit_encoding()) || \
583 ((fptr)->encs.ecflags & WRITECONV_MASK) || \
584 0)
585#define SET_BINARY_MODE(fptr) setmode((fptr)->fd, O_BINARY)
586
587#define NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr) do {\
588 if (NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {\
589 if (((fptr)->mode & FMODE_READABLE) &&\
590 !((fptr)->encs.ecflags & ECONV_NEWLINE_DECORATOR_MASK)) {\
591 setmode((fptr)->fd, O_BINARY);\
592 }\
593 else {\
594 setmode((fptr)->fd, O_TEXT);\
595 }\
596 }\
597} while(0)
598
599#define SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags) do {\
600 if ((enc2) && ((ecflags) & ECONV_DEFAULT_NEWLINE_DECORATOR)) {\
601 (ecflags) |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;\
602 }\
603} while(0)
604
605/*
606 * IO unread with taking care of removed '\r' in text mode.
607 */
608static void
609io_unread(rb_io_t *fptr)
610{
611 off_t r, pos;
612 ssize_t read_size;
613 long i;
614 long newlines = 0;
615 long extra_max;
616 char *p;
617 char *buf;
618
619 rb_io_check_closed(fptr);
620 if (fptr->rbuf.len == 0 || fptr->mode & FMODE_DUPLEX) {
621 return;
622 }
623
624 errno = 0;
625 if (!rb_w32_fd_is_text(fptr->fd)) {
626 r = lseek(fptr->fd, -fptr->rbuf.len, SEEK_CUR);
627 if (r < 0 && errno) {
628 if (errno == ESPIPE)
629 fptr->mode |= FMODE_DUPLEX;
630 return;
631 }
632
633 fptr->rbuf.off = 0;
634 fptr->rbuf.len = 0;
635 return;
636 }
637
638 pos = lseek(fptr->fd, 0, SEEK_CUR);
639 if (pos < 0 && errno) {
640 if (errno == ESPIPE)
641 fptr->mode |= FMODE_DUPLEX;
642 return;
643 }
644
645 /* add extra offset for removed '\r' in rbuf */
646 extra_max = (long)(pos - fptr->rbuf.len);
647 p = fptr->rbuf.ptr + fptr->rbuf.off;
648
649 /* if the end of rbuf is '\r', rbuf doesn't have '\r' within rbuf.len */
650 if (*(fptr->rbuf.ptr + fptr->rbuf.capa - 1) == '\r') {
651 newlines++;
652 }
653
654 for (i = 0; i < fptr->rbuf.len; i++) {
655 if (*p == '\n') newlines++;
656 if (extra_max == newlines) break;
657 p++;
658 }
659
660 buf = ALLOC_N(char, fptr->rbuf.len + newlines);
661 while (newlines >= 0) {
662 r = lseek(fptr->fd, pos - fptr->rbuf.len - newlines, SEEK_SET);
663 if (newlines == 0) break;
664 if (r < 0) {
665 newlines--;
666 continue;
667 }
668 read_size = _read(fptr->fd, buf, fptr->rbuf.len + newlines);
669 if (read_size < 0) {
670 int e = errno;
671 free(buf);
672 rb_syserr_fail_path(e, fptr->pathv);
673 }
674 if (read_size == fptr->rbuf.len) {
675 lseek(fptr->fd, r, SEEK_SET);
676 break;
677 }
678 else {
679 newlines--;
680 }
681 }
682 free(buf);
683 fptr->rbuf.off = 0;
684 fptr->rbuf.len = 0;
685 return;
686}
687
688/*
689 * We use io_seek to back cursor position when changing mode from text to binary,
690 * but stdin and pipe cannot seek back. Stdin and pipe read should use encoding
691 * conversion for working properly with mode change.
692 *
693 * Return previous translation mode.
694 */
695static inline int
696set_binary_mode_with_seek_cur(rb_io_t *fptr)
697{
698 if (!rb_w32_fd_is_text(fptr->fd)) return O_BINARY;
699
700 if (fptr->rbuf.len == 0 || fptr->mode & FMODE_DUPLEX) {
701 return setmode(fptr->fd, O_BINARY);
702 }
703 flush_before_seek(fptr);
704 return setmode(fptr->fd, O_BINARY);
705}
706#define SET_BINARY_MODE_WITH_SEEK_CUR(fptr) set_binary_mode_with_seek_cur(fptr)
707
708#else
709/* Unix */
710# define DEFAULT_TEXTMODE 0
711#define NEED_READCONV(fptr) ((fptr)->encs.enc2 != NULL || NEED_NEWLINE_DECORATOR_ON_READ(fptr))
712#define NEED_WRITECONV(fptr) ( \
713 ((fptr)->encs.enc != NULL && (fptr)->encs.enc != rb_ascii8bit_encoding()) || \
714 NEED_NEWLINE_DECORATOR_ON_WRITE(fptr) || \
715 ((fptr)->encs.ecflags & (ECONV_DECORATOR_MASK|ECONV_STATEFUL_DECORATOR_MASK)) || \
716 0)
717#define SET_BINARY_MODE(fptr) (void)(fptr)
718#define NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr) (void)(fptr)
719#define SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags) ((void)(enc2), (void)(ecflags))
720#define SET_BINARY_MODE_WITH_SEEK_CUR(fptr) (void)(fptr)
721#endif
722
723#if !defined HAVE_SHUTDOWN && !defined shutdown
724#define shutdown(a,b) 0
725#endif
726
727#if defined(_WIN32)
728#define is_socket(fd, path) rb_w32_is_socket(fd)
729#elif !defined(S_ISSOCK)
730#define is_socket(fd, path) 0
731#else
732static int
733 is_socket(int fd, VALUE path)
734{
735 struct stat sbuf;
736 if (fstat(fd, &sbuf) < 0)
737 rb_sys_fail_path(path);
738 return S_ISSOCK(sbuf.st_mode);
739}
740#endif
741
742static const char closed_stream[] = "closed stream";
743
744static void
745io_fd_check_closed(int fd)
746{
747 if (fd < 0) {
748 rb_thread_check_ints(); /* check for ruby_error_stream_closed */
749 rb_raise(rb_eIOError, closed_stream);
750 }
751}
752
753void
754 rb_eof_error(void)
755{
756 rb_raise(rb_eEOFError, "end of file reached");
757}
758
759 VALUE
760 rb_io_taint_check(VALUE io)
761{
762 rb_check_frozen(io);
763 return io;
764}
765
766void
767 rb_io_check_initialized(rb_io_t *fptr)
768{
769 if (!fptr) {
770 rb_raise(rb_eIOError, "uninitialized stream");
771 }
772}
773
774void
775 rb_io_check_closed(rb_io_t *fptr)
776{
777 rb_io_check_initialized(fptr);
778 io_fd_check_closed(fptr->fd);
779}
780
781static rb_io_t *
782rb_io_get_fptr(VALUE io)
783{
784 rb_io_t *fptr = RFILE(io)->fptr;
785 rb_io_check_initialized(fptr);
786 return fptr;
787}
788
789 VALUE
790 rb_io_get_io(VALUE io)
791{
792 return rb_convert_type_with_id(io, T_FILE, "IO", idTo_io);
793}
794
795 VALUE
796 rb_io_check_io(VALUE io)
797{
798 return rb_check_convert_type_with_id(io, T_FILE, "IO", idTo_io);
799}
800
801 VALUE
802 rb_io_get_write_io(VALUE io)
803{
804 VALUE write_io;
805 write_io = rb_io_get_fptr(io)->tied_io_for_writing;
806 if (write_io) {
807 return write_io;
808 }
809 return io;
810}
811
812 VALUE
813 rb_io_set_write_io(VALUE io, VALUE w)
814{
815 VALUE write_io;
816 rb_io_t *fptr = rb_io_get_fptr(io);
817 if (!RTEST(w)) {
818 w = 0;
819 }
820 else {
821 GetWriteIO(w);
822 }
823 write_io = fptr->tied_io_for_writing;
824 fptr->tied_io_for_writing = w;
825 return write_io ? write_io : Qnil;
826}
827
828/*
829 * call-seq:
830 * IO.try_convert(obj) -> io or nil
831 *
832 * Try to convert <i>obj</i> into an IO, using to_io method.
833 * Returns converted IO or +nil+ if <i>obj</i> cannot be converted
834 * for any reason.
835 *
836 * IO.try_convert(STDOUT) #=> STDOUT
837 * IO.try_convert("STDOUT") #=> nil
838 *
839 * require 'zlib'
840 * f = open("/tmp/zz.gz") #=> #<File:/tmp/zz.gz>
841 * z = Zlib::GzipReader.open(f) #=> #<Zlib::GzipReader:0x81d8744>
842 * IO.try_convert(z) #=> #<File:/tmp/zz.gz>
843 *
844 */
845static VALUE
846rb_io_s_try_convert(VALUE dummy, VALUE io)
847{
848 return rb_io_check_io(io);
849}
850
851#if !(defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32))
852static void
853io_unread(rb_io_t *fptr)
854{
855 off_t r;
856 rb_io_check_closed(fptr);
857 if (fptr->rbuf.len == 0 || fptr->mode & FMODE_DUPLEX)
858 return;
859 /* xxx: target position may be negative if buffer is filled by ungetc */
860 errno = 0;
861 r = lseek(fptr->fd, -fptr->rbuf.len, SEEK_CUR);
862 if (r < 0 && errno) {
863 if (errno == ESPIPE)
864 fptr->mode |= FMODE_DUPLEX;
865 return;
866 }
867 fptr->rbuf.off = 0;
868 fptr->rbuf.len = 0;
869 return;
870}
871#endif
872
873static rb_encoding *io_input_encoding(rb_io_t *fptr);
874
875static void
876io_ungetbyte(VALUE str, rb_io_t *fptr)
877{
878 long len = RSTRING_LEN(str);
879
880 if (fptr->rbuf.ptr == NULL) {
881 const int min_capa = IO_RBUF_CAPA_FOR(fptr);
882 fptr->rbuf.off = 0;
883 fptr->rbuf.len = 0;
884#if SIZEOF_LONG > SIZEOF_INT
885 if (len > INT_MAX)
886 rb_raise(rb_eIOError, "ungetbyte failed");
887#endif
888 if (len > min_capa)
889 fptr->rbuf.capa = (int)len;
890 else
891 fptr->rbuf.capa = min_capa;
892 fptr->rbuf.ptr = ALLOC_N(char, fptr->rbuf.capa);
893 }
894 if (fptr->rbuf.capa < len + fptr->rbuf.len) {
895 rb_raise(rb_eIOError, "ungetbyte failed");
896 }
897 if (fptr->rbuf.off < len) {
898 MEMMOVE(fptr->rbuf.ptr+fptr->rbuf.capa-fptr->rbuf.len,
899 fptr->rbuf.ptr+fptr->rbuf.off,
900 char, fptr->rbuf.len);
901 fptr->rbuf.off = fptr->rbuf.capa-fptr->rbuf.len;
902 }
903 fptr->rbuf.off-=(int)len;
904 fptr->rbuf.len+=(int)len;
905 MEMMOVE(fptr->rbuf.ptr+fptr->rbuf.off, RSTRING_PTR(str), char, len);
906}
907
908static rb_io_t *
909flush_before_seek(rb_io_t *fptr)
910{
911 if (io_fflush(fptr) < 0)
912 rb_sys_fail_on_write(fptr);
913 io_unread(fptr);
914 errno = 0;
915 return fptr;
916}
917
918#define io_seek(fptr, ofs, whence) (errno = 0, lseek(flush_before_seek(fptr)->fd, (ofs), (whence)))
919#define io_tell(fptr) lseek(flush_before_seek(fptr)->fd, 0, SEEK_CUR)
920
921#ifndef SEEK_CUR
922# define SEEK_SET 0
923# define SEEK_CUR 1
924# define SEEK_END 2
925#endif
926
927void
928 rb_io_check_char_readable(rb_io_t *fptr)
929{
930 rb_io_check_closed(fptr);
931 if (!(fptr->mode & FMODE_READABLE)) {
932 rb_raise(rb_eIOError, "not opened for reading");
933 }
934 if (fptr->wbuf.len) {
935 if (io_fflush(fptr) < 0)
936 rb_sys_fail_on_write(fptr);
937 }
938 if (fptr->tied_io_for_writing) {
939 rb_io_t *wfptr;
940 GetOpenFile(fptr->tied_io_for_writing, wfptr);
941 if (io_fflush(wfptr) < 0)
942 rb_sys_fail_on_write(wfptr);
943 }
944}
945
946void
947 rb_io_check_byte_readable(rb_io_t *fptr)
948{
949 rb_io_check_char_readable(fptr);
950 if (READ_CHAR_PENDING(fptr)) {
951 rb_raise(rb_eIOError, "byte oriented read for character buffered IO");
952 }
953}
954
955void
956 rb_io_check_readable(rb_io_t *fptr)
957{
958 rb_io_check_byte_readable(fptr);
959}
960
961static rb_encoding*
962io_read_encoding(rb_io_t *fptr)
963{
964 if (fptr->encs.enc) {
965 return fptr->encs.enc;
966 }
967 return rb_default_external_encoding();
968}
969
970static rb_encoding*
971io_input_encoding(rb_io_t *fptr)
972{
973 if (fptr->encs.enc2) {
974 return fptr->encs.enc2;
975 }
976 return io_read_encoding(fptr);
977}
978
979void
980 rb_io_check_writable(rb_io_t *fptr)
981{
982 rb_io_check_closed(fptr);
983 if (!(fptr->mode & FMODE_WRITABLE)) {
984 rb_raise(rb_eIOError, "not opened for writing");
985 }
986 if (fptr->rbuf.len) {
987 io_unread(fptr);
988 }
989}
990
991int
992 rb_io_read_pending(rb_io_t *fptr)
993{
994 /* This function is used for bytes and chars. Confusing. */
995 if (READ_CHAR_PENDING(fptr))
996 return 1; /* should raise? */
997 return READ_DATA_PENDING(fptr);
998}
999
1000void
1001 rb_io_read_check(rb_io_t *fptr)
1002{
1003 if (!READ_DATA_PENDING(fptr)) {
1004 rb_thread_wait_fd(fptr->fd);
1005 }
1006 return;
1007}
1008
1009int
1010 rb_gc_for_fd(int err)
1011{
1012 if (err == EMFILE || err == ENFILE || err == ENOMEM) {
1013 rb_gc();
1014 return 1;
1015 }
1016 return 0;
1017}
1018
1019static int
1020ruby_dup(int orig)
1021{
1022 int fd;
1023
1024 fd = rb_cloexec_dup(orig);
1025 if (fd < 0) {
1026 int e = errno;
1027 if (rb_gc_for_fd(e)) {
1028 fd = rb_cloexec_dup(orig);
1029 }
1030 if (fd < 0) {
1031 rb_syserr_fail(e, 0);
1032 }
1033 }
1034 rb_update_max_fd(fd);
1035 return fd;
1036}
1037
1038static VALUE
1039io_alloc(VALUE klass)
1040{
1041 NEWOBJ_OF(io, struct RFile, klass, T_FILE);
1042
1043 io->fptr = 0;
1044
1045 return (VALUE)io;
1046}
1047
1048#ifndef S_ISREG
1049# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
1050#endif
1051
1052 struct io_internal_read_struct {
1053 VALUE th;
1054 int fd;
1055 int nonblock;
1056 void *buf;
1057 size_t capa;
1058};
1059
1060 struct io_internal_write_struct {
1061 int fd;
1062 const void *buf;
1063 size_t capa;
1064};
1065
1066#ifdef HAVE_WRITEV
1067struct io_internal_writev_struct {
1068 int fd;
1069 int iovcnt;
1070 const struct iovec *iov;
1071};
1072#endif
1073
1074static int nogvl_wait_for_single_fd(VALUE th, int fd, short events);
1075static VALUE
1076internal_read_func(void *ptr)
1077{
1078 struct io_internal_read_struct *iis = ptr;
1079 ssize_t r;
1080retry:
1081 r = read(iis->fd, iis->buf, iis->capa);
1082 if (r < 0 && !iis->nonblock) {
1083 int e = errno;
1084 if (e == EAGAIN || e == EWOULDBLOCK) {
1085 if (nogvl_wait_for_single_fd(iis->th, iis->fd, RB_WAITFD_IN) != -1) {
1086 goto retry;
1087 }
1088 errno = e;
1089 }
1090 }
1091 return r;
1092}
1093
1094#if defined __APPLE__
1095# define do_write_retry(code) do {ret = code;} while (ret == -1 && errno == EPROTOTYPE)
1096#else
1097# define do_write_retry(code) ret = code
1098#endif
1099static VALUE
1100internal_write_func(void *ptr)
1101{
1102 struct io_internal_write_struct *iis = ptr;
1103 ssize_t ret;
1104 do_write_retry(write(iis->fd, iis->buf, iis->capa));
1105 return (VALUE)ret;
1106}
1107
1108static void*
1109internal_write_func2(void *ptr)
1110{
1111 return (void*)internal_write_func(ptr);
1112}
1113
1114#ifdef HAVE_WRITEV
1115static VALUE
1116internal_writev_func(void *ptr)
1117{
1118 struct io_internal_writev_struct *iis = ptr;
1119 ssize_t ret;
1120 do_write_retry(writev(iis->fd, iis->iov, iis->iovcnt));
1121 return (VALUE)ret;
1122}
1123#endif
1124
1125static ssize_t
1126rb_read_internal(int fd, void *buf, size_t count)
1127{
1128 struct io_internal_read_struct iis = {
1129 .th = rb_thread_current(),
1130 .fd = fd,
1131 .nonblock = 0,
1132 .buf = buf,
1133 .capa = count
1134 };
1135
1136 return (ssize_t)rb_thread_io_blocking_region(internal_read_func, &iis, fd);
1137}
1138
1139static ssize_t
1140rb_write_internal(int fd, const void *buf, size_t count)
1141{
1142 struct io_internal_write_struct iis = {
1143 .fd = fd,
1144 .buf = buf,
1145 .capa = count
1146 };
1147
1148 return (ssize_t)rb_thread_io_blocking_region(internal_write_func, &iis, fd);
1149}
1150
1151static ssize_t
1152rb_write_internal2(int fd, const void *buf, size_t count)
1153{
1154 struct io_internal_write_struct iis = {
1155 .fd = fd,
1156 .buf = buf,
1157 .capa = count
1158 };
1159
1160 return (ssize_t)rb_thread_call_without_gvl2(internal_write_func2, &iis,
1161 RUBY_UBF_IO, NULL);
1162}
1163
1164#ifdef HAVE_WRITEV
1165static ssize_t
1166rb_writev_internal(int fd, const struct iovec *iov, int iovcnt)
1167{
1168 struct io_internal_writev_struct iis = {
1169 .fd = fd,
1170 .iov = iov,
1171 .iovcnt = iovcnt,
1172 };
1173
1174 return (ssize_t)rb_thread_io_blocking_region(internal_writev_func, &iis, fd);
1175}
1176#endif
1177
1178static VALUE
1179io_flush_buffer_sync(void *arg)
1180{
1181 rb_io_t *fptr = arg;
1182 long l = fptr->wbuf.len;
1183 ssize_t r = write(fptr->fd, fptr->wbuf.ptr+fptr->wbuf.off, (size_t)l);
1184
1185 if (fptr->wbuf.len <= r) {
1186 fptr->wbuf.off = 0;
1187 fptr->wbuf.len = 0;
1188 return 0;
1189 }
1190 if (0 <= r) {
1191 fptr->wbuf.off += (int)r;
1192 fptr->wbuf.len -= (int)r;
1193 errno = EAGAIN;
1194 }
1195 return (VALUE)-1;
1196}
1197
1198static void*
1199io_flush_buffer_sync2(void *arg)
1200{
1201 VALUE result = io_flush_buffer_sync(arg);
1202
1203 /*
1204 * rb_thread_call_without_gvl2 uses 0 as interrupted.
1205 * So, we need to avoid to use 0.
1206 */
1207 return !result ? (void*)1 : (void*)result;
1208}
1209
1210static VALUE
1211io_flush_buffer_async(VALUE arg)
1212{
1213 rb_io_t *fptr = (rb_io_t *)arg;
1214 return rb_thread_io_blocking_region(io_flush_buffer_sync, fptr, fptr->fd);
1215}
1216
1217static VALUE
1218io_flush_buffer_async2(VALUE arg)
1219{
1220 rb_io_t *fptr = (rb_io_t *)arg;
1221 VALUE ret;
1222
1223 ret = (VALUE)rb_thread_call_without_gvl2(io_flush_buffer_sync2, fptr, RUBY_UBF_IO, NULL);
1224
1225 if (!ret) {
1226 /* pending async interrupt is there. */
1227 errno = EAGAIN;
1228 return -1;
1229 }
1230 else if (ret == 1) {
1231 return 0;
1232 }
1233 return ret;
1234}
1235
1236static inline int
1237io_flush_buffer(rb_io_t *fptr)
1238{
1239 if (fptr->write_lock) {
1240 if (rb_mutex_owned_p(fptr->write_lock))
1241 return (int)io_flush_buffer_async2((VALUE)fptr);
1242 else
1243 return (int)rb_mutex_synchronize(fptr->write_lock, io_flush_buffer_async2, (VALUE)fptr);
1244 }
1245 else {
1246 return (int)io_flush_buffer_async((VALUE)fptr);
1247 }
1248}
1249
1250static int
1251io_fflush(rb_io_t *fptr)
1252{
1253 rb_io_check_closed(fptr);
1254 if (fptr->wbuf.len == 0)
1255 return 0;
1256 while (fptr->wbuf.len > 0 && io_flush_buffer(fptr) != 0) {
1257 if (!rb_io_wait_writable(fptr->fd))
1258 return -1;
1259 rb_io_check_closed(fptr);
1260 }
1261 return 0;
1262}
1263
1264 VALUE
1265 rb_io_wait(VALUE io, VALUE events, VALUE timeout)
1266{
1267 VALUE scheduler = rb_scheduler_current();
1268
1269 if (scheduler != Qnil) {
1270 return rb_scheduler_io_wait(scheduler, io, events, timeout);
1271 }
1272
1273 rb_io_t * fptr = NULL;
1274 RB_IO_POINTER(io, fptr);
1275
1276 struct timeval tv_storage;
1277 struct timeval *tv = NULL;
1278
1279 if (timeout != Qnil) {
1280 tv_storage = rb_time_interval(timeout);
1281 tv = &tv_storage;
1282 }
1283
1284 int ready = rb_thread_wait_for_single_fd(fptr->fd, RB_NUM2INT(events), tv);
1285
1286 if (ready < 0) {
1287 rb_sys_fail(0);
1288 }
1289
1290 // Not sure if this is necessary:
1291 rb_io_check_closed(fptr);
1292
1293 if (ready > 0) {
1294 return RB_INT2NUM(ready);
1295 } else {
1296 return Qfalse;
1297 }
1298}
1299
1300static VALUE
1301rb_io_from_fd(int fd)
1302{
1303 return prep_io(fd, FMODE_PREP, rb_cIO, NULL);
1304}
1305
1306int
1307 rb_io_wait_readable(int f)
1308{
1309 VALUE scheduler;
1310
1311 io_fd_check_closed(f);
1312
1313 scheduler = rb_scheduler_current();
1314 switch (errno) {
1315 case EINTR:
1316#if defined(ERESTART)
1317 case ERESTART:
1318#endif
1319 rb_thread_check_ints();
1320 return TRUE;
1321
1322 case EAGAIN:
1323#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
1324 case EWOULDBLOCK:
1325#endif
1326 if (scheduler != Qnil) {
1327 return RTEST(
1328 rb_scheduler_io_wait_readable(scheduler, rb_io_from_fd(f))
1329 );
1330 } else {
1331 rb_thread_wait_fd(f);
1332 }
1333 return TRUE;
1334
1335 default:
1336 return FALSE;
1337 }
1338}
1339
1340int
1341 rb_io_wait_writable(int f)
1342{
1343 VALUE scheduler;
1344
1345 io_fd_check_closed(f);
1346
1347 scheduler = rb_scheduler_current();
1348 switch (errno) {
1349 case EINTR:
1350#if defined(ERESTART)
1351 case ERESTART:
1352#endif
1353 /*
1354 * In old Linux, several special files under /proc and /sys don't handle
1355 * select properly. Thus we need avoid to call if don't use O_NONBLOCK.
1356 * Otherwise, we face nasty hang up. Sigh.
1357 * e.g. http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=31b07093c44a7a442394d44423e21d783f5523b8
1358 * http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=31b07093c44a7a442394d44423e21d783f5523b8
1359 * In EINTR case, we only need to call RUBY_VM_CHECK_INTS_BLOCKING().
1360 * Then rb_thread_check_ints() is enough.
1361 */
1362 rb_thread_check_ints();
1363 return TRUE;
1364
1365 case EAGAIN:
1366#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
1367 case EWOULDBLOCK:
1368#endif
1369 if (scheduler != Qnil) {
1370 return RTEST(
1371 rb_scheduler_io_wait_writable(scheduler, rb_io_from_fd(f))
1372 );
1373 } else {
1374 rb_thread_fd_writable(f);
1375 }
1376 return TRUE;
1377
1378 default:
1379 return FALSE;
1380 }
1381}
1382
1383int
1384 rb_wait_for_single_fd(int fd, int events, struct timeval *timeout)
1385{
1386 VALUE scheduler = rb_scheduler_current();
1387
1388 if (scheduler != Qnil) {
1389 return RTEST(
1390 rb_scheduler_io_wait(scheduler, rb_io_from_fd(fd), RB_INT2NUM(events), rb_scheduler_timeout(timeout))
1391 );
1392 }
1393
1394 return rb_thread_wait_for_single_fd(fd, events, timeout);
1395}
1396
1397static void
1398make_writeconv(rb_io_t *fptr)
1399{
1400 if (!fptr->writeconv_initialized) {
1401 const char *senc, *denc;
1402 rb_encoding *enc;
1403 int ecflags;
1404 VALUE ecopts;
1405
1406 fptr->writeconv_initialized = 1;
1407
1408 ecflags = fptr->encs.ecflags & ~ECONV_NEWLINE_DECORATOR_READ_MASK;
1409 ecopts = fptr->encs.ecopts;
1410
1411 if (!fptr->encs.enc || (fptr->encs.enc == rb_ascii8bit_encoding() && !fptr->encs.enc2)) {
1412 /* no encoding conversion */
1413 fptr->writeconv_pre_ecflags = 0;
1414 fptr->writeconv_pre_ecopts = Qnil;
1415 fptr->writeconv = rb_econv_open_opts("", "", ecflags, ecopts);
1416 if (!fptr->writeconv)
1417 rb_exc_raise(rb_econv_open_exc("", "", ecflags));
1418 fptr->writeconv_asciicompat = Qnil;
1419 }
1420 else {
1421 enc = fptr->encs.enc2 ? fptr->encs.enc2 : fptr->encs.enc;
1422 senc = rb_econv_asciicompat_encoding(rb_enc_name(enc));
1423 if (!senc && !(fptr->encs.ecflags & ECONV_STATEFUL_DECORATOR_MASK)) {
1424 /* single conversion */
1425 fptr->writeconv_pre_ecflags = ecflags;
1426 fptr->writeconv_pre_ecopts = ecopts;
1427 fptr->writeconv = NULL;
1428 fptr->writeconv_asciicompat = Qnil;
1429 }
1430 else {
1431 /* double conversion */
1432 fptr->writeconv_pre_ecflags = ecflags & ~ECONV_STATEFUL_DECORATOR_MASK;
1433 fptr->writeconv_pre_ecopts = ecopts;
1434 if (senc) {
1435 denc = rb_enc_name(enc);
1436 fptr->writeconv_asciicompat = rb_str_new2(senc);
1437 }
1438 else {
1439 senc = denc = "";
1440 fptr->writeconv_asciicompat = rb_str_new2(rb_enc_name(enc));
1441 }
1442 ecflags = fptr->encs.ecflags & (ECONV_ERROR_HANDLER_MASK|ECONV_STATEFUL_DECORATOR_MASK);
1443 ecopts = fptr->encs.ecopts;
1444 fptr->writeconv = rb_econv_open_opts(senc, denc, ecflags, ecopts);
1445 if (!fptr->writeconv)
1446 rb_exc_raise(rb_econv_open_exc(senc, denc, ecflags));
1447 }
1448 }
1449 }
1450}
1451
1452/* writing functions */
1453 struct binwrite_arg {
1454 rb_io_t *fptr;
1455 VALUE str;
1456 const char *ptr;
1457 long length;
1458};
1459
1460 struct write_arg {
1461 VALUE io;
1462 VALUE str;
1463 int nosync;
1464};
1465
1466#ifdef HAVE_WRITEV
1467static VALUE
1468io_binwrite_string(VALUE arg)
1469{
1470 struct binwrite_arg *p = (struct binwrite_arg *)arg;
1471 rb_io_t *fptr = p->fptr;
1472 long r;
1473
1474 if (fptr->wbuf.len) {
1475 struct iovec iov[2];
1476
1477 iov[0].iov_base = fptr->wbuf.ptr+fptr->wbuf.off;
1478 iov[0].iov_len = fptr->wbuf.len;
1479 iov[1].iov_base = (char *)p->ptr;
1480 iov[1].iov_len = p->length;
1481
1482 r = rb_writev_internal(fptr->fd, iov, 2);
1483
1484 if (r < 0)
1485 return r;
1486
1487 if (fptr->wbuf.len <= r) {
1488 r -= fptr->wbuf.len;
1489 fptr->wbuf.off = 0;
1490 fptr->wbuf.len = 0;
1491 }
1492 else {
1493 fptr->wbuf.off += (int)r;
1494 fptr->wbuf.len -= (int)r;
1495 r = 0L;
1496 }
1497 }
1498 else {
1499 r = rb_write_internal(fptr->fd, p->ptr, p->length);
1500 }
1501
1502 return r;
1503}
1504#else
1505static VALUE
1506io_binwrite_string(VALUE arg)
1507{
1508 struct binwrite_arg *p = (struct binwrite_arg *)arg;
1509 rb_io_t *fptr = p->fptr;
1510 long l, len;
1511
1512 l = len = p->length;
1513
1514 if (fptr->wbuf.len) {
1515 if (fptr->wbuf.len+len <= fptr->wbuf.capa) {
1516 if (fptr->wbuf.capa < fptr->wbuf.off+fptr->wbuf.len+len) {
1517 MEMMOVE(fptr->wbuf.ptr, fptr->wbuf.ptr+fptr->wbuf.off, char, fptr->wbuf.len);
1518 fptr->wbuf.off = 0;
1519 }
1520 MEMMOVE(fptr->wbuf.ptr+fptr->wbuf.off+fptr->wbuf.len, p->ptr, char, len);
1521 fptr->wbuf.len += (int)len;
1522 l = 0;
1523 }
1524 if (io_fflush(fptr) < 0)
1525 return -2L; /* fail in fflush */
1526 if (l == 0)
1527 return len;
1528 }
1529
1530 if (fptr->stdio_file != stderr && !rb_thread_fd_writable(fptr->fd))
1531 rb_io_check_closed(fptr);
1532
1533 return rb_write_internal(p->fptr->fd, p->ptr, p->length);
1534}
1535#endif
1536
1537static long
1538io_binwrite(VALUE str, const char *ptr, long len, rb_io_t *fptr, int nosync)
1539{
1540 long n, r, offset = 0;
1541
1542 /* don't write anything if current thread has a pending interrupt. */
1543 rb_thread_check_ints();
1544
1545 if ((n = len) <= 0) return n;
1546
1547 VALUE scheduler = rb_scheduler_current();
1548 if (scheduler != Qnil && rb_scheduler_supports_io_write(scheduler)) {
1549 ssize_t length = RB_NUM2SSIZE(
1550 rb_scheduler_io_write(scheduler, fptr->self, str, offset, len)
1551 );
1552
1553 if (length < 0) rb_sys_fail_path(fptr->pathv);
1554
1555 return length;
1556 }
1557
1558 if (fptr->wbuf.ptr == NULL && !(!nosync && (fptr->mode & FMODE_SYNC))) {
1559 fptr->wbuf.off = 0;
1560 fptr->wbuf.len = 0;
1561 fptr->wbuf.capa = IO_WBUF_CAPA_MIN;
1562 fptr->wbuf.ptr = ALLOC_N(char, fptr->wbuf.capa);
1563 fptr->write_lock = rb_mutex_new();
1564 rb_mutex_allow_trap(fptr->write_lock, 1);
1565 }
1566 if ((!nosync && (fptr->mode & (FMODE_SYNC|FMODE_TTY))) ||
1567 (fptr->wbuf.ptr && fptr->wbuf.capa <= fptr->wbuf.len + len)) {
1568 struct binwrite_arg arg;
1569
1570 arg.fptr = fptr;
1571 arg.str = str;
1572 retry:
1573 arg.ptr = ptr + offset;
1574 arg.length = n;
1575 if (fptr->write_lock) {
1576 r = rb_mutex_synchronize(fptr->write_lock, io_binwrite_string, (VALUE)&arg);
1577 }
1578 else {
1579 r = io_binwrite_string((VALUE)&arg);
1580 }
1581 /* xxx: other threads may modify given string. */
1582 if (r == n) return len;
1583 if (0 <= r) {
1584 offset += r;
1585 n -= r;
1586 errno = EAGAIN;
1587 }
1588 if (r == -2L)
1589 return -1L;
1590 if (rb_io_wait_writable(fptr->fd)) {
1591 rb_io_check_closed(fptr);
1592 if (offset < len)
1593 goto retry;
1594 }
1595 return -1L;
1596 }
1597
1598 if (fptr->wbuf.off) {
1599 if (fptr->wbuf.len)
1600 MEMMOVE(fptr->wbuf.ptr, fptr->wbuf.ptr+fptr->wbuf.off, char, fptr->wbuf.len);
1601 fptr->wbuf.off = 0;
1602 }
1603 MEMMOVE(fptr->wbuf.ptr+fptr->wbuf.off+fptr->wbuf.len, ptr+offset, char, len);
1604 fptr->wbuf.len += (int)len;
1605 return len;
1606}
1607
1608# define MODE_BTMODE(a,b,c) ((fmode & FMODE_BINMODE) ? (b) : \
1609 (fmode & FMODE_TEXTMODE) ? (c) : (a))
1610
1611#define MODE_BTXMODE(a, b, c, d, e, f) ((fmode & FMODE_EXCL) ? \
1612 MODE_BTMODE(d, e, f) : \
1613 MODE_BTMODE(a, b, c))
1614
1615static VALUE
1616do_writeconv(VALUE str, rb_io_t *fptr, int *converted)
1617{
1618 if (NEED_WRITECONV(fptr)) {
1619 VALUE common_encoding = Qnil;
1620 SET_BINARY_MODE(fptr);
1621
1622 make_writeconv(fptr);
1623
1624 if (fptr->writeconv) {
1625#define fmode (fptr->mode)
1626 if (!NIL_P(fptr->writeconv_asciicompat))
1627 common_encoding = fptr->writeconv_asciicompat;
1628 else if (MODE_BTMODE(DEFAULT_TEXTMODE,0,1) && !rb_enc_asciicompat(rb_enc_get(str))) {
1629 rb_raise(rb_eArgError, "ASCII incompatible string written for text mode IO without encoding conversion: %s",
1630 rb_enc_name(rb_enc_get(str)));
1631 }
1632#undef fmode
1633 }
1634 else {
1635 if (fptr->encs.enc2)
1636 common_encoding = rb_enc_from_encoding(fptr->encs.enc2);
1637 else if (fptr->encs.enc != rb_ascii8bit_encoding())
1638 common_encoding = rb_enc_from_encoding(fptr->encs.enc);
1639 }
1640
1641 if (!NIL_P(common_encoding)) {
1642 str = rb_str_encode(str, common_encoding,
1643 fptr->writeconv_pre_ecflags, fptr->writeconv_pre_ecopts);
1644 *converted = 1;
1645 }
1646
1647 if (fptr->writeconv) {
1648 str = rb_econv_str_convert(fptr->writeconv, str, ECONV_PARTIAL_INPUT);
1649 *converted = 1;
1650 }
1651 }
1652#if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
1653#define fmode (fptr->mode)
1654 else if (MODE_BTMODE(DEFAULT_TEXTMODE,0,1)) {
1655 if ((fptr->mode & FMODE_READABLE) &&
1656 !(fptr->encs.ecflags & ECONV_NEWLINE_DECORATOR_MASK)) {
1657 setmode(fptr->fd, O_BINARY);
1658 }
1659 else {
1660 setmode(fptr->fd, O_TEXT);
1661 }
1662 if (!rb_enc_asciicompat(rb_enc_get(str))) {
1663 rb_raise(rb_eArgError, "ASCII incompatible string written for text mode IO without encoding conversion: %s",
1664 rb_enc_name(rb_enc_get(str)));
1665 }
1666 }
1667#undef fmode
1668#endif
1669 return str;
1670}
1671
1672static long
1673io_fwrite(VALUE str, rb_io_t *fptr, int nosync)
1674{
1675 int converted = 0;
1676 VALUE tmp;
1677 long n, len;
1678 const char *ptr;
1679#ifdef _WIN32
1680 if (fptr->mode & FMODE_TTY) {
1681 long len = rb_w32_write_console(str, fptr->fd);
1682 if (len > 0) return len;
1683 }
1684#endif
1685 str = do_writeconv(str, fptr, &converted);
1686 if (converted)
1687 OBJ_FREEZE(str);
1688
1689 tmp = rb_str_tmp_frozen_acquire(str);
1690 RSTRING_GETMEM(tmp, ptr, len);
1691 n = io_binwrite(tmp, ptr, len, fptr, nosync);
1692 rb_str_tmp_frozen_release(str, tmp);
1693
1694 return n;
1695}
1696
1697ssize_t
1698 rb_io_bufwrite(VALUE io, const void *buf, size_t size)
1699{
1700 rb_io_t *fptr;
1701
1702 GetOpenFile(io, fptr);
1703 rb_io_check_writable(fptr);
1704 return (ssize_t)io_binwrite(0, buf, (long)size, fptr, 0);
1705}
1706
1707static VALUE
1708io_write(VALUE io, VALUE str, int nosync)
1709{
1710 rb_io_t *fptr;
1711 long n;
1712 VALUE tmp;
1713
1714 io = GetWriteIO(io);
1715 str = rb_obj_as_string(str);
1716 tmp = rb_io_check_io(io);
1717 if (NIL_P(tmp)) {
1718 /* port is not IO, call write method for it. */
1719 return rb_funcall(io, id_write, 1, str);
1720 }
1721 io = tmp;
1722 if (RSTRING_LEN(str) == 0) return INT2FIX(0);
1723
1724 GetOpenFile(io, fptr);
1725 rb_io_check_writable(fptr);
1726
1727 n = io_fwrite(str, fptr, nosync);
1728 if (n < 0L) rb_sys_fail_on_write(fptr);
1729
1730 return LONG2FIX(n);
1731}
1732
1733#ifdef HAVE_WRITEV
1734struct binwritev_arg {
1735 rb_io_t *fptr;
1736 const struct iovec *iov;
1737 int iovcnt;
1738};
1739
1740static VALUE
1741call_writev_internal(VALUE arg)
1742{
1743 struct binwritev_arg *p = (struct binwritev_arg *)arg;
1744 return rb_writev_internal(p->fptr->fd, p->iov, p->iovcnt);
1745}
1746
1747static long
1748io_binwritev(struct iovec *iov, int iovcnt, rb_io_t *fptr)
1749{
1750 int i;
1751 long r, total = 0, written_len = 0;
1752
1753 /* don't write anything if current thread has a pending interrupt. */
1754 rb_thread_check_ints();
1755
1756 if (iovcnt == 0) return 0;
1757 for (i = 1; i < iovcnt; i++) total += iov[i].iov_len;
1758
1759 if (fptr->wbuf.ptr == NULL && !(fptr->mode & FMODE_SYNC)) {
1760 fptr->wbuf.off = 0;
1761 fptr->wbuf.len = 0;
1762 fptr->wbuf.capa = IO_WBUF_CAPA_MIN;
1763 fptr->wbuf.ptr = ALLOC_N(char, fptr->wbuf.capa);
1764 fptr->write_lock = rb_mutex_new();
1765 rb_mutex_allow_trap(fptr->write_lock, 1);
1766 }
1767
1768 if (fptr->wbuf.ptr && fptr->wbuf.len) {
1769 long offset = fptr->wbuf.off + fptr->wbuf.len;
1770 if (offset + total <= fptr->wbuf.capa) {
1771 for (i = 1; i < iovcnt; i++) {
1772 memcpy(fptr->wbuf.ptr+offset, iov[i].iov_base, iov[i].iov_len);
1773 offset += iov[i].iov_len;
1774 }
1775 fptr->wbuf.len += total;
1776 return total;
1777 }
1778 else {
1779 iov[0].iov_base = fptr->wbuf.ptr + fptr->wbuf.off;
1780 iov[0].iov_len = fptr->wbuf.len;
1781 }
1782 }
1783 else {
1784 iov++;
1785 if (!--iovcnt) return 0;
1786 }
1787
1788 retry:
1789 if (fptr->write_lock) {
1790 struct binwritev_arg arg;
1791 arg.fptr = fptr;
1792 arg.iov = iov;
1793 arg.iovcnt = iovcnt;
1794 r = rb_mutex_synchronize(fptr->write_lock, call_writev_internal, (VALUE)&arg);
1795 }
1796 else {
1797 r = rb_writev_internal(fptr->fd, iov, iovcnt);
1798 }
1799
1800 if (r >= 0) {
1801 written_len += r;
1802 if (fptr->wbuf.ptr && fptr->wbuf.len) {
1803 if (written_len < fptr->wbuf.len) {
1804 fptr->wbuf.off += r;
1805 fptr->wbuf.len -= r;
1806 }
1807 else {
1808 written_len -= fptr->wbuf.len;
1809 fptr->wbuf.off = 0;
1810 fptr->wbuf.len = 0;
1811 }
1812 }
1813 if (written_len == total) return total;
1814
1815 while (r >= (ssize_t)iov->iov_len) {
1816 /* iovcnt > 0 */
1817 r -= iov->iov_len;
1818 iov->iov_len = 0;
1819 iov++;
1820 if (!--iovcnt) return total;
1821 /* defensive check: written_len should == total */
1822 }
1823 iov->iov_base = (char *)iov->iov_base + r;
1824 iov->iov_len -= r;
1825
1826 errno = EAGAIN;
1827 }
1828 if (rb_io_wait_writable(fptr->fd)) {
1829 rb_io_check_closed(fptr);
1830 goto retry;
1831 }
1832
1833 return -1L;
1834}
1835
1836static long
1837io_fwritev(int argc, const VALUE *argv, rb_io_t *fptr)
1838{
1839 int i, converted, iovcnt = argc + 1;
1840 long n;
1841 VALUE v1, v2, str, tmp, *tmp_array;
1842 struct iovec *iov;
1843
1844 iov = ALLOCV_N(struct iovec, v1, iovcnt);
1845 tmp_array = ALLOCV_N(VALUE, v2, argc);
1846
1847 for (i = 0; i < argc; i++) {
1848 str = rb_obj_as_string(argv[i]);
1849 converted = 0;
1850 str = do_writeconv(str, fptr, &converted);
1851 if (converted)
1852 OBJ_FREEZE(str);
1853
1854 tmp = rb_str_tmp_frozen_acquire(str);
1855 tmp_array[i] = tmp;
1856 /* iov[0] is reserved for buffer of fptr */
1857 iov[i+1].iov_base = RSTRING_PTR(tmp);
1858 iov[i+1].iov_len = RSTRING_LEN(tmp);
1859 }
1860
1861 n = io_binwritev(iov, iovcnt, fptr);
1862 if (v1) ALLOCV_END(v1);
1863
1864 for (i = 0; i < argc; i++) {
1865 rb_str_tmp_frozen_release(argv[i], tmp_array[i]);
1866 }
1867
1868 if (v2) ALLOCV_END(v2);
1869
1870 return n;
1871}
1872
1873static int
1874iovcnt_ok(int iovcnt)
1875{
1876#ifdef IOV_MAX
1877 return iovcnt < IOV_MAX;
1878#else /* GNU/Hurd has writev, but no IOV_MAX */
1879 return 1;
1880#endif
1881}
1882#endif /* HAVE_WRITEV */
1883
1884static VALUE
1885io_writev(int argc, const VALUE *argv, VALUE io)
1886{
1887 rb_io_t *fptr;
1888 long n;
1889 VALUE tmp, total = INT2FIX(0);
1890 int i, cnt = 1;
1891
1892 io = GetWriteIO(io);
1893 tmp = rb_io_check_io(io);
1894 if (NIL_P(tmp)) {
1895 /* port is not IO, call write method for it. */
1896 return rb_funcallv(io, id_write, argc, argv);
1897 }
1898 io = tmp;
1899
1900 GetOpenFile(io, fptr);
1901 rb_io_check_writable(fptr);
1902
1903 for (i = 0; i < argc; i += cnt) {
1904#ifdef HAVE_WRITEV
1905 if ((fptr->mode & (FMODE_SYNC|FMODE_TTY)) && iovcnt_ok(cnt = argc - i)) {
1906 n = io_fwritev(cnt, &argv[i], fptr);
1907 }
1908 else
1909#endif
1910 {
1911 cnt = 1;
1912 /* sync at last item */
1913 n = io_fwrite(rb_obj_as_string(argv[i]), fptr, (i < argc-1));
1914 }
1915 if (n < 0L) rb_sys_fail_on_write(fptr);
1916 total = rb_fix_plus(LONG2FIX(n), total);
1917 }
1918
1919 return total;
1920}
1921
1922/*
1923 * call-seq:
1924 * ios.write(string, ...) -> integer
1925 *
1926 * Writes the given strings to <em>ios</em>. The stream must be opened
1927 * for writing. Arguments that are not a string will be converted
1928 * to a string using <code>to_s</code>. Returns the number of bytes
1929 * written in total.
1930 *
1931 * count = $stdout.write("This is", " a test\n")
1932 * puts "That was #{count} bytes of data"
1933 *
1934 * <em>produces:</em>
1935 *
1936 * This is a test
1937 * That was 15 bytes of data
1938 */
1939
1940static VALUE
1941io_write_m(int argc, VALUE *argv, VALUE io)
1942{
1943 if (argc != 1) {
1944 return io_writev(argc, argv, io);
1945 }
1946 else {
1947 VALUE str = argv[0];
1948 return io_write(io, str, 0);
1949 }
1950}
1951
1952 VALUE
1953 rb_io_write(VALUE io, VALUE str)
1954{
1955 return rb_funcallv(io, id_write, 1, &str);
1956}
1957
1958static VALUE
1959rb_io_writev(VALUE io, int argc, const VALUE *argv)
1960{
1961 if (argc > 1 && rb_obj_method_arity(io, id_write) == 1) {
1962 if (io != rb_ractor_stderr() && RTEST(ruby_verbose)) {
1963 VALUE klass = CLASS_OF(io);
1964 char sep = FL_TEST(klass, FL_SINGLETON) ? (klass = io, '.') : '#';
1965 rb_category_warning(RB_WARN_CATEGORY_DEPRECATED, "%+"PRIsVALUE"%c""write is outdated interface"
1966 " which accepts just one argument",
1967 klass, sep);
1968 }
1969 do rb_io_write(io, *argv++); while (--argc);
1970 return argv[0]; /* unused right now */
1971 }
1972 return rb_funcallv(io, id_write, argc, argv);
1973}
1974
1975/*
1976 * call-seq:
1977 * ios << obj -> ios
1978 *
1979 * String Output---Writes <i>obj</i> to <em>ios</em>.
1980 * <i>obj</i> will be converted to a string using
1981 * <code>to_s</code>.
1982 *
1983 * $stdout << "Hello " << "world!\n"
1984 *
1985 * <em>produces:</em>
1986 *
1987 * Hello world!
1988 */
1989
1990
1991 VALUE
1992 rb_io_addstr(VALUE io, VALUE str)
1993{
1994 rb_io_write(io, str);
1995 return io;
1996}
1997
1998#ifdef HAVE_FSYNC
1999static VALUE
2000nogvl_fsync(void *ptr)
2001{
2002 rb_io_t *fptr = ptr;
2003
2004#ifdef _WIN32
2005 if (GetFileType((HANDLE)rb_w32_get_osfhandle(fptr->fd)) != FILE_TYPE_DISK)
2006 return 0;
2007#endif
2008 return (VALUE)fsync(fptr->fd);
2009}
2010#endif
2011
2012 VALUE
2013 rb_io_flush_raw(VALUE io, int sync)
2014{
2015 rb_io_t *fptr;
2016
2017 if (!RB_TYPE_P(io, T_FILE)) {
2018 return rb_funcall(io, id_flush, 0);
2019 }
2020
2021 io = GetWriteIO(io);
2022 GetOpenFile(io, fptr);
2023
2024 if (fptr->mode & FMODE_WRITABLE) {
2025 if (io_fflush(fptr) < 0)
2026 rb_sys_fail_on_write(fptr);
2027 }
2028 if (fptr->mode & FMODE_READABLE) {
2029 io_unread(fptr);
2030 }
2031
2032 return io;
2033}
2034
2035/*
2036 * call-seq:
2037 * ios.flush -> ios
2038 *
2039 * Flushes any buffered data within <em>ios</em> to the underlying
2040 * operating system (note that this is Ruby internal buffering only;
2041 * the OS may buffer the data as well).
2042 *
2043 * $stdout.print "no newline"
2044 * $stdout.flush
2045 *
2046 * <em>produces:</em>
2047 *
2048 * no newline
2049 */
2050
2051 VALUE
2052 rb_io_flush(VALUE io)
2053{
2054 return rb_io_flush_raw(io, 1);
2055}
2056
2057/*
2058 * call-seq:
2059 * ios.pos -> integer
2060 * ios.tell -> integer
2061 *
2062 * Returns the current offset (in bytes) of <em>ios</em>.
2063 *
2064 * f = File.new("testfile")
2065 * f.pos #=> 0
2066 * f.gets #=> "This is line one\n"
2067 * f.pos #=> 17
2068 */
2069
2070static VALUE
2071rb_io_tell(VALUE io)
2072{
2073 rb_io_t *fptr;
2074 off_t pos;
2075
2076 GetOpenFile(io, fptr);
2077 pos = io_tell(fptr);
2078 if (pos < 0 && errno) rb_sys_fail_path(fptr->pathv);
2079 pos -= fptr->rbuf.len;
2080 return OFFT2NUM(pos);
2081}
2082
2083static VALUE
2084rb_io_seek(VALUE io, VALUE offset, int whence)
2085{
2086 rb_io_t *fptr;
2087 off_t pos;
2088
2089 pos = NUM2OFFT(offset);
2090 GetOpenFile(io, fptr);
2091 pos = io_seek(fptr, pos, whence);
2092 if (pos < 0 && errno) rb_sys_fail_path(fptr->pathv);
2093
2094 return INT2FIX(0);
2095}
2096
2097static int
2098interpret_seek_whence(VALUE vwhence)
2099{
2100 if (vwhence == sym_SET)
2101 return SEEK_SET;
2102 if (vwhence == sym_CUR)
2103 return SEEK_CUR;
2104 if (vwhence == sym_END)
2105 return SEEK_END;
2106#ifdef SEEK_DATA
2107 if (vwhence == sym_DATA)
2108 return SEEK_DATA;
2109#endif
2110#ifdef SEEK_HOLE
2111 if (vwhence == sym_HOLE)
2112 return SEEK_HOLE;
2113#endif
2114 return NUM2INT(vwhence);
2115}
2116
2117/*
2118 * call-seq:
2119 * ios.seek(amount, whence=IO::SEEK_SET) -> 0
2120 *
2121 * Seeks to a given offset <i>anInteger</i> in the stream according to
2122 * the value of <i>whence</i>:
2123 *
2124 * :CUR or IO::SEEK_CUR | Seeks to _amount_ plus current position
2125 * ----------------------+--------------------------------------------------
2126 * :END or IO::SEEK_END | Seeks to _amount_ plus end of stream (you
2127 * | probably want a negative value for _amount_)
2128 * ----------------------+--------------------------------------------------
2129 * :SET or IO::SEEK_SET | Seeks to the absolute location given by _amount_
2130 *
2131 * Example:
2132 *
2133 * f = File.new("testfile")
2134 * f.seek(-13, IO::SEEK_END) #=> 0
2135 * f.readline #=> "And so on...\n"
2136 */
2137
2138static VALUE
2139rb_io_seek_m(int argc, VALUE *argv, VALUE io)
2140{
2141 VALUE offset, ptrname;
2142 int whence = SEEK_SET;
2143
2144 if (rb_scan_args(argc, argv, "11", &offset, &ptrname) == 2) {
2145 whence = interpret_seek_whence(ptrname);
2146 }
2147
2148 return rb_io_seek(io, offset, whence);
2149}
2150
2151/*
2152 * call-seq:
2153 * ios.pos = integer -> integer
2154 *
2155 * Seeks to the given position (in bytes) in <em>ios</em>.
2156 * It is not guaranteed that seeking to the right position when <em>ios</em>
2157 * is textmode.
2158 *
2159 * f = File.new("testfile")
2160 * f.pos = 17
2161 * f.gets #=> "This is line two\n"
2162 */
2163
2164static VALUE
2165rb_io_set_pos(VALUE io, VALUE offset)
2166{
2167 rb_io_t *fptr;
2168 off_t pos;
2169
2170 pos = NUM2OFFT(offset);
2171 GetOpenFile(io, fptr);
2172 pos = io_seek(fptr, pos, SEEK_SET);
2173 if (pos < 0 && errno) rb_sys_fail_path(fptr->pathv);
2174
2175 return OFFT2NUM(pos);
2176}
2177
2178static void clear_readconv(rb_io_t *fptr);
2179
2180/*
2181 * call-seq:
2182 * ios.rewind -> 0
2183 *
2184 * Positions <em>ios</em> to the beginning of input, resetting
2185 * #lineno to zero.
2186 *
2187 * f = File.new("testfile")
2188 * f.readline #=> "This is line one\n"
2189 * f.rewind #=> 0
2190 * f.lineno #=> 0
2191 * f.readline #=> "This is line one\n"
2192 *
2193 * Note that it cannot be used with streams such as pipes, ttys, and sockets.
2194 */
2195
2196static VALUE
2197rb_io_rewind(VALUE io)
2198{
2199 rb_io_t *fptr;
2200
2201 GetOpenFile(io, fptr);
2202 if (io_seek(fptr, 0L, 0) < 0 && errno) rb_sys_fail_path(fptr->pathv);
2203 if (io == ARGF.current_file) {
2204 ARGF.lineno -= fptr->lineno;
2205 }
2206 fptr->lineno = 0;
2207 if (fptr->readconv) {
2208 clear_readconv(fptr);
2209 }
2210
2211 return INT2FIX(0);
2212}
2213
2214static int
2215fptr_wait_readable(rb_io_t *fptr)
2216{
2217 int ret = rb_io_wait_readable(fptr->fd);
2218
2219 if (ret)
2220 rb_io_check_closed(fptr);
2221 return ret;
2222}
2223
2224static int
2225io_fillbuf(rb_io_t *fptr)
2226{
2227 ssize_t r;
2228
2229 if (fptr->rbuf.ptr == NULL) {
2230 fptr->rbuf.off = 0;
2231 fptr->rbuf.len = 0;
2232 fptr->rbuf.capa = IO_RBUF_CAPA_FOR(fptr);
2233 fptr->rbuf.ptr = ALLOC_N(char, fptr->rbuf.capa);
2234#ifdef _WIN32
2235 fptr->rbuf.capa--;
2236#endif
2237 }
2238 if (fptr->rbuf.len == 0) {
2239 retry:
2240 {
2241 r = rb_read_internal(fptr->fd, fptr->rbuf.ptr, fptr->rbuf.capa);
2242 }
2243 if (r < 0) {
2244 if (fptr_wait_readable(fptr))
2245 goto retry;
2246 {
2247 int e = errno;
2248 VALUE path = rb_sprintf("fd:%d ", fptr->fd);
2249 if (!NIL_P(fptr->pathv)) {
2250 rb_str_append(path, fptr->pathv);
2251 }
2252 rb_syserr_fail_path(e, path);
2253 }
2254 }
2255 if (r > 0) rb_io_check_closed(fptr);
2256 fptr->rbuf.off = 0;
2257 fptr->rbuf.len = (int)r; /* r should be <= rbuf_capa */
2258 if (r == 0)
2259 return -1; /* EOF */
2260 }
2261 return 0;
2262}
2263
2264/*
2265 * call-seq:
2266 * ios.eof -> true or false
2267 * ios.eof? -> true or false
2268 *
2269 * Returns true if <em>ios</em> is at end of file that means
2270 * there are no more data to read.
2271 * The stream must be opened for reading or an IOError will be
2272 * raised.
2273 *
2274 * f = File.new("testfile")
2275 * dummy = f.readlines
2276 * f.eof #=> true
2277 *
2278 * If <em>ios</em> is a stream such as pipe or socket, IO#eof?
2279 * blocks until the other end sends some data or closes it.
2280 *
2281 * r, w = IO.pipe
2282 * Thread.new { sleep 1; w.close }
2283 * r.eof? #=> true after 1 second blocking
2284 *
2285 * r, w = IO.pipe
2286 * Thread.new { sleep 1; w.puts "a" }
2287 * r.eof? #=> false after 1 second blocking
2288 *
2289 * r, w = IO.pipe
2290 * r.eof? # blocks forever
2291 *
2292 * Note that IO#eof? reads data to the input byte buffer. So
2293 * IO#sysread may not behave as you intend with IO#eof?, unless you
2294 * call IO#rewind first (which is not available for some streams).
2295 */
2296
2297 VALUE
2298 rb_io_eof(VALUE io)
2299{
2300 rb_io_t *fptr;
2301
2302 GetOpenFile(io, fptr);
2303 rb_io_check_char_readable(fptr);
2304
2305 if (READ_CHAR_PENDING(fptr)) return Qfalse;
2306 if (READ_DATA_PENDING(fptr)) return Qfalse;
2307 READ_CHECK(fptr);
2308#if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
2309 if (!NEED_READCONV(fptr) && NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {
2310 return eof(fptr->fd) ? Qtrue : Qfalse;
2311 }
2312#endif
2313 if (io_fillbuf(fptr) < 0) {
2314 return Qtrue;
2315 }
2316 return Qfalse;
2317}
2318
2319/*
2320 * call-seq:
2321 * ios.sync -> true or false
2322 *
2323 * Returns the current ``sync mode'' of <em>ios</em>. When sync mode is
2324 * true, all output is immediately flushed to the underlying operating
2325 * system and is not buffered by Ruby internally. See also
2326 * IO#fsync.
2327 *
2328 * f = File.new("testfile")
2329 * f.sync #=> false
2330 */
2331
2332static VALUE
2333 rb_io_sync(VALUE io)
2334{
2335 rb_io_t *fptr;
2336
2337 io = GetWriteIO(io);
2338 GetOpenFile(io, fptr);
2339 return (fptr->mode & FMODE_SYNC) ? Qtrue : Qfalse;
2340}
2341
2342#ifdef HAVE_FSYNC
2343
2344/*
2345 * call-seq:
2346 * ios.sync = boolean -> boolean
2347 *
2348 * Sets the ``sync mode'' to <code>true</code> or <code>false</code>.
2349 * When sync mode is true, all output is immediately flushed to the
2350 * underlying operating system and is not buffered internally. Returns
2351 * the new state. See also IO#fsync.
2352 *
2353 * f = File.new("testfile")
2354 * f.sync = true
2355 */
2356
2357static VALUE
2358rb_io_set_sync(VALUE io, VALUE sync)
2359{
2360 rb_io_t *fptr;
2361
2362 io = GetWriteIO(io);
2363 GetOpenFile(io, fptr);
2364 if (RTEST(sync)) {
2365 fptr->mode |= FMODE_SYNC;
2366 }
2367 else {
2368 fptr->mode &= ~FMODE_SYNC;
2369 }
2370 return sync;
2371}
2372
2373/*
2374 * call-seq:
2375 * ios.fsync -> 0 or nil
2376 *
2377 * Immediately writes all buffered data in <em>ios</em> to disk.
2378 * Note that #fsync differs from using IO#sync=. The latter ensures
2379 * that data is flushed from Ruby's buffers, but does not guarantee
2380 * that the underlying operating system actually writes it to disk.
2381 *
2382 * NotImplementedError is raised
2383 * if the underlying operating system does not support <em>fsync(2)</em>.
2384 */
2385
2386static VALUE
2387 rb_io_fsync(VALUE io)
2388{
2389 rb_io_t *fptr;
2390
2391 io = GetWriteIO(io);
2392 GetOpenFile(io, fptr);
2393
2394 if (io_fflush(fptr) < 0)
2395 rb_sys_fail_on_write(fptr);
2396 if ((int)rb_thread_io_blocking_region(nogvl_fsync, fptr, fptr->fd) < 0)
2397 rb_sys_fail_path(fptr->pathv);
2398 return INT2FIX(0);
2399}
2400#else
2401# define rb_io_fsync rb_f_notimplement
2402# define rb_io_sync rb_f_notimplement
2403static VALUE
2404rb_io_set_sync(VALUE io, VALUE sync)
2405{
2406 rb_notimplement();
2407 UNREACHABLE;
2408}
2409#endif
2410
2411#ifdef HAVE_FDATASYNC
2412static VALUE
2413nogvl_fdatasync(void *ptr)
2414{
2415 rb_io_t *fptr = ptr;
2416
2417#ifdef _WIN32
2418 if (GetFileType((HANDLE)rb_w32_get_osfhandle(fptr->fd)) != FILE_TYPE_DISK)
2419 return 0;
2420#endif
2421 return (VALUE)fdatasync(fptr->fd);
2422}
2423
2424/*
2425 * call-seq:
2426 * ios.fdatasync -> 0 or nil
2427 *
2428 * Immediately writes all buffered data in <em>ios</em> to disk.
2429 *
2430 * If the underlying operating system does not support <em>fdatasync(2)</em>,
2431 * IO#fsync is called instead (which might raise a
2432 * NotImplementedError).
2433 */
2434
2435static VALUE
2436 rb_io_fdatasync(VALUE io)
2437{
2438 rb_io_t *fptr;
2439
2440 io = GetWriteIO(io);
2441 GetOpenFile(io, fptr);
2442
2443 if (io_fflush(fptr) < 0)
2444 rb_sys_fail_on_write(fptr);
2445
2446 if ((int)rb_thread_io_blocking_region(nogvl_fdatasync, fptr, fptr->fd) == 0)
2447 return INT2FIX(0);
2448
2449 /* fall back */
2450 return rb_io_fsync(io);
2451}
2452#else
2453#define rb_io_fdatasync rb_io_fsync
2454#endif
2455
2456/*
2457 * call-seq:
2458 * ios.fileno -> integer
2459 * ios.to_i -> integer
2460 *
2461 * Returns an integer representing the numeric file descriptor for
2462 * <em>ios</em>.
2463 *
2464 * $stdin.fileno #=> 0
2465 * $stdout.fileno #=> 1
2466 */
2467
2468static VALUE
2469rb_io_fileno(VALUE io)
2470{
2471 rb_io_t *fptr = RFILE(io)->fptr;
2472 int fd;
2473
2474 rb_io_check_closed(fptr);
2475 fd = fptr->fd;
2476 return INT2FIX(fd);
2477}
2478
2479
2480/*
2481 * call-seq:
2482 * ios.pid -> integer
2483 *
2484 * Returns the process ID of a child process associated with
2485 * <em>ios</em>. This will be set by IO.popen.
2486 *
2487 * pipe = IO.popen("-")
2488 * if pipe
2489 * $stderr.puts "In parent, child pid is #{pipe.pid}"
2490 * else
2491 * $stderr.puts "In child, pid is #{$$}"
2492 * end
2493 *
2494 * <em>produces:</em>
2495 *
2496 * In child, pid is 26209
2497 * In parent, child pid is 26209
2498 */
2499
2500static VALUE
2501rb_io_pid(VALUE io)
2502{
2503 rb_io_t *fptr;
2504
2505 GetOpenFile(io, fptr);
2506 if (!fptr->pid)
2507 return Qnil;
2508 return PIDT2NUM(fptr->pid);
2509}
2510
2511
2512/*
2513 * call-seq:
2514 * ios.inspect -> string
2515 *
2516 * Return a string describing this IO object.
2517 */
2518
2519static VALUE
2520rb_io_inspect(VALUE obj)
2521{
2522 rb_io_t *fptr;
2523 VALUE result;
2524 static const char closed[] = " (closed)";
2525
2526 fptr = RFILE(obj)->fptr;
2527 if (!fptr) return rb_any_to_s(obj);
2528 result = rb_str_new_cstr("#<");
2529 rb_str_append(result, rb_class_name(CLASS_OF(obj)));
2530 rb_str_cat2(result, ":");
2531 if (NIL_P(fptr->pathv)) {
2532 if (fptr->fd < 0) {
2533 rb_str_cat(result, closed+1, strlen(closed)-1);
2534 }
2535 else {
2536 rb_str_catf(result, "fd %d", fptr->fd);
2537 }
2538 }
2539 else {
2540 rb_str_append(result, fptr->pathv);
2541 if (fptr->fd < 0) {
2542 rb_str_cat(result, closed, strlen(closed));
2543 }
2544 }
2545 return rb_str_cat2(result, ">");
2546}
2547
2548/*
2549 * call-seq:
2550 * ios.to_io -> ios
2551 *
2552 * Returns <em>ios</em>.
2553 */
2554
2555static VALUE
2556rb_io_to_io(VALUE io)
2557{
2558 return io;
2559}
2560
2561/* reading functions */
2562static long
2563read_buffered_data(char *ptr, long len, rb_io_t *fptr)
2564{
2565 int n;
2566
2567 n = READ_DATA_PENDING_COUNT(fptr);
2568 if (n <= 0) return 0;
2569 if (n > len) n = (int)len;
2570 MEMMOVE(ptr, fptr->rbuf.ptr+fptr->rbuf.off, char, n);
2571 fptr->rbuf.off += n;
2572 fptr->rbuf.len -= n;
2573 return n;
2574}
2575
2576static long
2577io_bufread(char *ptr, long len, rb_io_t *fptr)
2578{
2579 long offset = 0;
2580 long n = len;
2581 long c;
2582
2583 if (READ_DATA_PENDING(fptr) == 0) {
2584 while (n > 0) {
2585 again:
2586 c = rb_read_internal(fptr->fd, ptr+offset, n);
2587 if (c == 0) break;
2588 if (c < 0) {
2589 if (fptr_wait_readable(fptr))
2590 goto again;
2591 return -1;
2592 }
2593 offset += c;
2594 if ((n -= c) <= 0) break;
2595 }
2596 return len - n;
2597 }
2598
2599 while (n > 0) {
2600 c = read_buffered_data(ptr+offset, n, fptr);
2601 if (c > 0) {
2602 offset += c;
2603 if ((n -= c) <= 0) break;
2604 }
2605 rb_io_check_closed(fptr);
2606 if (io_fillbuf(fptr) < 0) {
2607 break;
2608 }
2609 }
2610 return len - n;
2611}
2612
2613static int io_setstrbuf(VALUE *str, long len);
2614
2615 struct bufread_arg {
2616 char *str_ptr;
2617 long len;
2618 rb_io_t *fptr;
2619};
2620
2621static VALUE
2622bufread_call(VALUE arg)
2623{
2624 struct bufread_arg *p = (struct bufread_arg *)arg;
2625 p->len = io_bufread(p->str_ptr, p->len, p->fptr);
2626 return Qundef;
2627}
2628
2629static long
2630io_fread(VALUE str, long offset, long size, rb_io_t *fptr)
2631{
2632 VALUE scheduler = rb_scheduler_current();
2633 if (scheduler != Qnil && rb_scheduler_supports_io_read(scheduler)) {
2634 ssize_t length = RB_NUM2SSIZE(
2635 rb_scheduler_io_read(scheduler, fptr->self, str, offset, size)
2636 );
2637
2638 if (length < 0) rb_sys_fail_path(fptr->pathv);
2639
2640 return length;
2641 }
2642
2643 long len;
2644 struct bufread_arg arg;
2645
2646 io_setstrbuf(&str, offset + size);
2647 arg.str_ptr = RSTRING_PTR(str) + offset;
2648 arg.len = size;
2649 arg.fptr = fptr;
2650 rb_str_locktmp_ensure(str, bufread_call, (VALUE)&arg);
2651 len = arg.len;
2652 if (len < 0) rb_sys_fail_path(fptr->pathv);
2653 return len;
2654}
2655
2656static long
2657remain_size(rb_io_t *fptr)
2658{
2659 struct stat st;
2660 off_t siz = READ_DATA_PENDING_COUNT(fptr);
2661 off_t pos;
2662
2663 if (fstat(fptr->fd, &st) == 0 && S_ISREG(st.st_mode)
2664#if defined(__HAIKU__)
2665 && (st.st_dev > 3)
2666#endif
2667 )
2668 {
2669 if (io_fflush(fptr) < 0)
2670 rb_sys_fail_on_write(fptr);
2671 pos = lseek(fptr->fd, 0, SEEK_CUR);
2672 if (st.st_size >= pos && pos >= 0) {
2673 siz += st.st_size - pos;
2674 if (siz > LONG_MAX) {
2675 rb_raise(rb_eIOError, "file too big for single read");
2676 }
2677 }
2678 }
2679 else {
2680 siz += BUFSIZ;
2681 }
2682 return (long)siz;
2683}
2684
2685static VALUE
2686io_enc_str(VALUE str, rb_io_t *fptr)
2687{
2688 rb_enc_associate(str, io_read_encoding(fptr));
2689 return str;
2690}
2691
2692static void
2693make_readconv(rb_io_t *fptr, int size)
2694{
2695 if (!fptr->readconv) {
2696 int ecflags;
2697 VALUE ecopts;
2698 const char *sname, *dname;
2699 ecflags = fptr->encs.ecflags & ~ECONV_NEWLINE_DECORATOR_WRITE_MASK;
2700 ecopts = fptr->encs.ecopts;
2701 if (fptr->encs.enc2) {
2702 sname = rb_enc_name(fptr->encs.enc2);
2703 dname = rb_enc_name(fptr->encs.enc);
2704 }
2705 else {
2706 sname = dname = "";
2707 }
2708 fptr->readconv = rb_econv_open_opts(sname, dname, ecflags, ecopts);
2709 if (!fptr->readconv)
2710 rb_exc_raise(rb_econv_open_exc(sname, dname, ecflags));
2711 fptr->cbuf.off = 0;
2712 fptr->cbuf.len = 0;
2713 if (size < IO_CBUF_CAPA_MIN) size = IO_CBUF_CAPA_MIN;
2714 fptr->cbuf.capa = size;
2715 fptr->cbuf.ptr = ALLOC_N(char, fptr->cbuf.capa);
2716 }
2717}
2718
2719#define MORE_CHAR_SUSPENDED Qtrue
2720#define MORE_CHAR_FINISHED Qnil
2721static VALUE
2722fill_cbuf(rb_io_t *fptr, int ec_flags)
2723{
2724 const unsigned char *ss, *sp, *se;
2725 unsigned char *ds, *dp, *de;
2726 rb_econv_result_t res;
2727 int putbackable;
2728 int cbuf_len0;
2729 VALUE exc;
2730
2731 ec_flags |= ECONV_PARTIAL_INPUT;
2732
2733 if (fptr->cbuf.len == fptr->cbuf.capa)
2734 return MORE_CHAR_SUSPENDED; /* cbuf full */
2735 if (fptr->cbuf.len == 0)
2736 fptr->cbuf.off = 0;
2737 else if (fptr->cbuf.off + fptr->cbuf.len == fptr->cbuf.capa) {
2738 memmove(fptr->cbuf.ptr, fptr->cbuf.ptr+fptr->cbuf.off, fptr->cbuf.len);
2739 fptr->cbuf.off = 0;
2740 }
2741
2742 cbuf_len0 = fptr->cbuf.len;
2743
2744 while (1) {
2745 ss = sp = (const unsigned char *)fptr->rbuf.ptr + fptr->rbuf.off;
2746 se = sp + fptr->rbuf.len;
2747 ds = dp = (unsigned char *)fptr->cbuf.ptr + fptr->cbuf.off + fptr->cbuf.len;
2748 de = (unsigned char *)fptr->cbuf.ptr + fptr->cbuf.capa;
2749 res = rb_econv_convert(fptr->readconv, &sp, se, &dp, de, ec_flags);
2750 fptr->rbuf.off += (int)(sp - ss);
2751 fptr->rbuf.len -= (int)(sp - ss);
2752 fptr->cbuf.len += (int)(dp - ds);
2753
2754 putbackable = rb_econv_putbackable(fptr->readconv);
2755 if (putbackable) {
2756 rb_econv_putback(fptr->readconv, (unsigned char *)fptr->rbuf.ptr + fptr->rbuf.off - putbackable, putbackable);
2757 fptr->rbuf.off -= putbackable;
2758 fptr->rbuf.len += putbackable;
2759 }
2760
2761 exc = rb_econv_make_exception(fptr->readconv);
2762 if (!NIL_P(exc))
2763 return exc;
2764
2765 if (cbuf_len0 != fptr->cbuf.len)
2766 return MORE_CHAR_SUSPENDED;
2767
2768 if (res == econv_finished) {
2769 return MORE_CHAR_FINISHED;
2770 }
2771
2772 if (res == econv_source_buffer_empty) {
2773 if (fptr->rbuf.len == 0) {
2774 READ_CHECK(fptr);
2775 if (io_fillbuf(fptr) < 0) {
2776 if (!fptr->readconv) {
2777 return MORE_CHAR_FINISHED;
2778 }
2779 ds = dp = (unsigned char *)fptr->cbuf.ptr + fptr->cbuf.off + fptr->cbuf.len;
2780 de = (unsigned char *)fptr->cbuf.ptr + fptr->cbuf.capa;
2781 res = rb_econv_convert(fptr->readconv, NULL, NULL, &dp, de, 0);
2782 fptr->cbuf.len += (int)(dp - ds);
2783 rb_econv_check_error(fptr->readconv);
2784 break;
2785 }
2786 }
2787 }
2788 }
2789 if (cbuf_len0 != fptr->cbuf.len)
2790 return MORE_CHAR_SUSPENDED;
2791
2792 return MORE_CHAR_FINISHED;
2793}
2794
2795static VALUE
2796more_char(rb_io_t *fptr)
2797{
2798 VALUE v;
2799 v = fill_cbuf(fptr, ECONV_AFTER_OUTPUT);
2800 if (v != MORE_CHAR_SUSPENDED && v != MORE_CHAR_FINISHED)
2801 rb_exc_raise(v);
2802 return v;
2803}
2804
2805static VALUE
2806io_shift_cbuf(rb_io_t *fptr, int len, VALUE *strp)
2807{
2808 VALUE str = Qnil;
2809 if (strp) {
2810 str = *strp;
2811 if (NIL_P(str)) {
2812 *strp = str = rb_str_new(fptr->cbuf.ptr+fptr->cbuf.off, len);
2813 }
2814 else {
2815 rb_str_cat(str, fptr->cbuf.ptr+fptr->cbuf.off, len);
2816 }
2817 rb_enc_associate(str, fptr->encs.enc);
2818 }
2819 fptr->cbuf.off += len;
2820 fptr->cbuf.len -= len;
2821 /* xxx: set coderange */
2822 if (fptr->cbuf.len == 0)
2823 fptr->cbuf.off = 0;
2824 else if (fptr->cbuf.capa/2 < fptr->cbuf.off) {
2825 memmove(fptr->cbuf.ptr, fptr->cbuf.ptr+fptr->cbuf.off, fptr->cbuf.len);
2826 fptr->cbuf.off = 0;
2827 }
2828 return str;
2829}
2830
2831static int
2832io_setstrbuf(VALUE *str, long len)
2833{
2834#ifdef _WIN32
2835 len = (len + 1) & ~1L; /* round up for wide char */
2836#endif
2837 if (NIL_P(*str)) {
2838 *str = rb_str_new(0, len);
2839 return TRUE;
2840 }
2841 else {
2842 VALUE s = StringValue(*str);
2843 long clen = RSTRING_LEN(s);
2844 if (clen >= len) {
2845 rb_str_modify(s);
2846 return FALSE;
2847 }
2848 len -= clen;
2849 }
2850 rb_str_modify_expand(*str, len);
2851 return FALSE;
2852}
2853
2854#define MAX_REALLOC_GAP 4096
2855static void
2856io_shrink_read_string(VALUE str, long n)
2857{
2858 if (rb_str_capacity(str) - n > MAX_REALLOC_GAP) {
2859 rb_str_resize(str, n);
2860 }
2861}
2862
2863static void
2864io_set_read_length(VALUE str, long n, int shrinkable)
2865{
2866 if (RSTRING_LEN(str) != n) {
2867 rb_str_modify(str);
2868 rb_str_set_len(str, n);
2869 if (shrinkable) io_shrink_read_string(str, n);
2870 }
2871}
2872
2873static VALUE
2874read_all(rb_io_t *fptr, long siz, VALUE str)
2875{
2876 long bytes;
2877 long n;
2878 long pos;
2879 rb_encoding *enc;
2880 int cr;
2881 int shrinkable;
2882
2883 if (NEED_READCONV(fptr)) {
2884 int first = !NIL_P(str);
2885 SET_BINARY_MODE(fptr);
2886 shrinkable = io_setstrbuf(&str,0);
2887 make_readconv(fptr, 0);
2888 while (1) {
2889 VALUE v;
2890 if (fptr->cbuf.len) {
2891 if (first) rb_str_set_len(str, first = 0);
2892 io_shift_cbuf(fptr, fptr->cbuf.len, &str);
2893 }
2894 v = fill_cbuf(fptr, 0);
2895 if (v != MORE_CHAR_SUSPENDED && v != MORE_CHAR_FINISHED) {
2896 if (fptr->cbuf.len) {
2897 if (first) rb_str_set_len(str, first = 0);
2898 io_shift_cbuf(fptr, fptr->cbuf.len, &str);
2899 }
2900 rb_exc_raise(v);
2901 }
2902 if (v == MORE_CHAR_FINISHED) {
2903 clear_readconv(fptr);
2904 if (first) rb_str_set_len(str, first = 0);
2905 if (shrinkable) io_shrink_read_string(str, RSTRING_LEN(str));
2906 return io_enc_str(str, fptr);
2907 }
2908 }
2909 }
2910
2911 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
2912 bytes = 0;
2913 pos = 0;
2914
2915 enc = io_read_encoding(fptr);
2916 cr = 0;
2917
2918 if (siz == 0) siz = BUFSIZ;
2919 shrinkable = io_setstrbuf(&str, siz);
2920 for (;;) {
2921 READ_CHECK(fptr);
2922 n = io_fread(str, bytes, siz - bytes, fptr);
2923 if (n == 0 && bytes == 0) {
2924 rb_str_set_len(str, 0);
2925 break;
2926 }
2927 bytes += n;
2928 rb_str_set_len(str, bytes);
2929 if (cr != ENC_CODERANGE_BROKEN)
2930 pos += rb_str_coderange_scan_restartable(RSTRING_PTR(str) + pos, RSTRING_PTR(str) + bytes, enc, &cr);
2931 if (bytes < siz) break;
2932 siz += BUFSIZ;
2933 rb_str_modify_expand(str, BUFSIZ);
2934 }
2935 if (shrinkable) io_shrink_read_string(str, RSTRING_LEN(str));
2936 str = io_enc_str(str, fptr);
2937 ENC_CODERANGE_SET(str, cr);
2938 return str;
2939}
2940
2941void
2942 rb_io_set_nonblock(rb_io_t *fptr)
2943{
2944 if (rb_fd_set_nonblock(fptr->fd) != 0) {
2945 rb_sys_fail_path(fptr->pathv);
2946 }
2947}
2948
2949static VALUE
2950read_internal_call(VALUE arg)
2951{
2952 struct io_internal_read_struct *iis = (struct io_internal_read_struct *)arg;
2953
2954 return rb_thread_io_blocking_region(internal_read_func, iis, iis->fd);
2955}
2956
2957static long
2958read_internal_locktmp(VALUE str, struct io_internal_read_struct *iis)
2959{
2960 return (long)rb_str_locktmp_ensure(str, read_internal_call, (VALUE)iis);
2961}
2962
2963#define no_exception_p(opts) !rb_opts_exception_p((opts), TRUE)
2964
2965static VALUE
2966io_getpartial(int argc, VALUE *argv, VALUE io, int no_exception, int nonblock)
2967{
2968 rb_io_t *fptr;
2969 VALUE length, str;
2970 long n, len;
2971 struct io_internal_read_struct iis;
2972 int shrinkable;
2973
2974 rb_scan_args(argc, argv, "11", &length, &str);
2975
2976 if ((len = NUM2LONG(length)) < 0) {
2977 rb_raise(rb_eArgError, "negative length %ld given", len);
2978 }
2979
2980 shrinkable = io_setstrbuf(&str, len);
2981
2982 GetOpenFile(io, fptr);
2983 rb_io_check_byte_readable(fptr);
2984
2985 if (len == 0) {
2986 io_set_read_length(str, 0, shrinkable);
2987 return str;
2988 }
2989
2990 if (!nonblock)
2991 READ_CHECK(fptr);
2992 n = read_buffered_data(RSTRING_PTR(str), len, fptr);
2993 if (n <= 0) {
2994 again:
2995 if (nonblock) {
2996 rb_io_set_nonblock(fptr);
2997 }
2998 io_setstrbuf(&str, len);
2999 iis.th = rb_thread_current();
3000 iis.fd = fptr->fd;
3001 iis.nonblock = nonblock;
3002 iis.buf = RSTRING_PTR(str);
3003 iis.capa = len;
3004 n = read_internal_locktmp(str, &iis);
3005 if (n < 0) {
3006 int e = errno;
3007 if (!nonblock && fptr_wait_readable(fptr))
3008 goto again;
3009 if (nonblock && (e == EWOULDBLOCK || e == EAGAIN)) {
3010 if (no_exception)
3011 return sym_wait_readable;
3012 else
3013 rb_readwrite_syserr_fail(RB_IO_WAIT_READABLE,
3014 e, "read would block");
3015 }
3016 rb_syserr_fail_path(e, fptr->pathv);
3017 }
3018 }
3019 io_set_read_length(str, n, shrinkable);
3020
3021 if (n == 0)
3022 return Qnil;
3023 else
3024 return str;
3025}
3026
3027/*
3028 * call-seq:
3029 * ios.readpartial(maxlen) -> string
3030 * ios.readpartial(maxlen, outbuf) -> outbuf
3031 *
3032 * Reads at most <i>maxlen</i> bytes from the I/O stream.
3033 * It blocks only if <em>ios</em> has no data immediately available.
3034 * It doesn't block if some data available.
3035 *
3036 * If the optional _outbuf_ argument is present,
3037 * it must reference a String, which will receive the data.
3038 * The _outbuf_ will contain only the received data after the method call
3039 * even if it is not empty at the beginning.
3040 *
3041 * It raises EOFError on end of file.
3042 *
3043 * readpartial is designed for streams such as pipe, socket, tty, etc.
3044 * It blocks only when no data immediately available.
3045 * This means that it blocks only when following all conditions hold.
3046 * * the byte buffer in the IO object is empty.
3047 * * the content of the stream is empty.
3048 * * the stream is not reached to EOF.
3049 *
3050 * When readpartial blocks, it waits data or EOF on the stream.
3051 * If some data is reached, readpartial returns with the data.
3052 * If EOF is reached, readpartial raises EOFError.
3053 *
3054 * When readpartial doesn't blocks, it returns or raises immediately.
3055 * If the byte buffer is not empty, it returns the data in the buffer.
3056 * Otherwise if the stream has some content,
3057 * it returns the data in the stream.
3058 * Otherwise if the stream is reached to EOF, it raises EOFError.
3059 *
3060 * r, w = IO.pipe # buffer pipe content
3061 * w << "abc" # "" "abc".
3062 * r.readpartial(4096) #=> "abc" "" ""
3063 * r.readpartial(4096) # blocks because buffer and pipe is empty.
3064 *
3065 * r, w = IO.pipe # buffer pipe content
3066 * w << "abc" # "" "abc"
3067 * w.close # "" "abc" EOF
3068 * r.readpartial(4096) #=> "abc" "" EOF
3069 * r.readpartial(4096) # raises EOFError
3070 *
3071 * r, w = IO.pipe # buffer pipe content
3072 * w << "abc\ndef\n" # "" "abc\ndef\n"
3073 * r.gets #=> "abc\n" "def\n" ""
3074 * w << "ghi\n" # "def\n" "ghi\n"
3075 * r.readpartial(4096) #=> "def\n" "" "ghi\n"
3076 * r.readpartial(4096) #=> "ghi\n" "" ""
3077 *
3078 * Note that readpartial behaves similar to sysread.
3079 * The differences are:
3080 * * If the byte buffer is not empty, read from the byte buffer
3081 * instead of "sysread for buffered IO (IOError)".
3082 * * It doesn't cause Errno::EWOULDBLOCK and Errno::EINTR. When
3083 * readpartial meets EWOULDBLOCK and EINTR by read system call,
3084 * readpartial retry the system call.
3085 *
3086 * The latter means that readpartial is nonblocking-flag insensitive.
3087 * It blocks on the situation IO#sysread causes Errno::EWOULDBLOCK as
3088 * if the fd is blocking mode.
3089 *
3090 */
3091
3092static VALUE
3093io_readpartial(int argc, VALUE *argv, VALUE io)
3094{
3095 VALUE ret;
3096
3097 ret = io_getpartial(argc, argv, io, Qnil, 0);
3098 if (NIL_P(ret))
3099 rb_eof_error();
3100 return ret;
3101}
3102
3103static VALUE
3104io_nonblock_eof(int no_exception)
3105{
3106 if (!no_exception) {
3107 rb_eof_error();
3108 }
3109 return Qnil;
3110}
3111
3112/* :nodoc: */
3113static VALUE
3114io_read_nonblock(rb_execution_context_t *ec, VALUE io, VALUE length, VALUE str, VALUE ex)
3115{
3116 rb_io_t *fptr;
3117 long n, len;
3118 struct io_internal_read_struct iis;
3119 int shrinkable;
3120
3121 if ((len = NUM2LONG(length)) < 0) {
3122 rb_raise(rb_eArgError, "negative length %ld given", len);
3123 }
3124
3125 shrinkable = io_setstrbuf(&str, len);
3126 rb_bool_expected(ex, "exception");
3127
3128 GetOpenFile(io, fptr);
3129 rb_io_check_byte_readable(fptr);
3130
3131 if (len == 0) {
3132 io_set_read_length(str, 0, shrinkable);
3133 return str;
3134 }
3135
3136 n = read_buffered_data(RSTRING_PTR(str), len, fptr);
3137 if (n <= 0) {
3138 rb_io_set_nonblock(fptr);
3139 shrinkable |= io_setstrbuf(&str, len);
3140 iis.fd = fptr->fd;
3141 iis.nonblock = 1;
3142 iis.buf = RSTRING_PTR(str);
3143 iis.capa = len;
3144 n = read_internal_locktmp(str, &iis);
3145 if (n < 0) {
3146 int e = errno;
3147 if ((e == EWOULDBLOCK || e == EAGAIN)) {
3148 if (!ex) return sym_wait_readable;
3149 rb_readwrite_syserr_fail(RB_IO_WAIT_READABLE,
3150 e, "read would block");
3151 }
3152 rb_syserr_fail_path(e, fptr->pathv);
3153 }
3154 }
3155 io_set_read_length(str, n, shrinkable);
3156
3157 if (n == 0) {
3158 if (!ex) return Qnil;
3159 rb_eof_error();
3160 }
3161
3162 return str;
3163}
3164
3165/* :nodoc: */
3166static VALUE
3167io_write_nonblock(rb_execution_context_t *ec, VALUE io, VALUE str, VALUE ex)
3168{
3169 rb_io_t *fptr;
3170 long n;
3171
3172 if (!RB_TYPE_P(str, T_STRING))
3173 str = rb_obj_as_string(str);
3174 rb_bool_expected(ex, "exception");
3175
3176 io = GetWriteIO(io);
3177 GetOpenFile(io, fptr);
3178 rb_io_check_writable(fptr);
3179
3180 if (io_fflush(fptr) < 0)
3181 rb_sys_fail_on_write(fptr);
3182
3183 rb_io_set_nonblock(fptr);
3184 n = write(fptr->fd, RSTRING_PTR(str), RSTRING_LEN(str));
3185 RB_GC_GUARD(str);
3186
3187 if (n < 0) {
3188 int e = errno;
3189 if (e == EWOULDBLOCK || e == EAGAIN) {
3190 if (!ex) {
3191 return sym_wait_writable;
3192 }
3193 else {
3194 rb_readwrite_syserr_fail(RB_IO_WAIT_WRITABLE, e, "write would block");
3195 }
3196 }
3197 rb_syserr_fail_path(e, fptr->pathv);
3198 }
3199
3200 return LONG2FIX(n);
3201}
3202
3203/*
3204 * call-seq:
3205 * ios.read([length [, outbuf]]) -> string, outbuf, or nil
3206 *
3207 * Reads _length_ bytes from the I/O stream.
3208 *
3209 * _length_ must be a non-negative integer or +nil+.
3210 *
3211 * If _length_ is a positive integer, +read+ tries to read
3212 * _length_ bytes without any conversion (binary mode).
3213 * It returns +nil+ if an EOF is encountered before anything can be read.
3214 * Fewer than _length_ bytes are returned if an EOF is encountered during
3215 * the read.
3216 * In the case of an integer _length_, the resulting string is always
3217 * in ASCII-8BIT encoding.
3218 *
3219 * If _length_ is omitted or is +nil+, it reads until EOF
3220 * and the encoding conversion is applied, if applicable.
3221 * A string is returned even if EOF is encountered before any data is read.
3222 *
3223 * If _length_ is zero, it returns an empty string (<code>""</code>).
3224 *
3225 * If the optional _outbuf_ argument is present,
3226 * it must reference a String, which will receive the data.
3227 * The _outbuf_ will contain only the received data after the method call
3228 * even if it is not empty at the beginning.
3229 *
3230 * When this method is called at end of file, it returns +nil+
3231 * or <code>""</code>, depending on _length_:
3232 * +read+, <code>read(nil)</code>, and <code>read(0)</code> return
3233 * <code>""</code>,
3234 * <code>read(<i>positive_integer</i>)</code> returns +nil+.
3235 *
3236 * f = File.new("testfile")
3237 * f.read(16) #=> "This is line one"
3238 *
3239 * # read whole file
3240 * open("file") do |f|
3241 * data = f.read # This returns a string even if the file is empty.
3242 * # ...
3243 * end
3244 *
3245 * # iterate over fixed length records
3246 * open("fixed-record-file") do |f|
3247 * while record = f.read(256)
3248 * # ...
3249 * end
3250 * end
3251 *
3252 * # iterate over variable length records,
3253 * # each record is prefixed by its 32-bit length
3254 * open("variable-record-file") do |f|
3255 * while len = f.read(4)
3256 * len = len.unpack("N")[0] # 32-bit length
3257 * record = f.read(len) # This returns a string even if len is 0.
3258 * end
3259 * end
3260 *
3261 * Note that this method behaves like the fread() function in C.
3262 * This means it retries to invoke read(2) system calls to read data
3263 * with the specified length (or until EOF).
3264 * This behavior is preserved even if <i>ios</i> is in non-blocking mode.
3265 * (This method is non-blocking flag insensitive as other methods.)
3266 * If you need the behavior like a single read(2) system call,
3267 * consider #readpartial, #read_nonblock, and #sysread.
3268 */
3269
3270static VALUE
3271io_read(int argc, VALUE *argv, VALUE io)
3272{
3273 rb_io_t *fptr;
3274 long n, len;
3275 VALUE length, str;
3276 int shrinkable;
3277#if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
3278 int previous_mode;
3279#endif
3280
3281 rb_scan_args(argc, argv, "02", &length, &str);
3282
3283 if (NIL_P(length)) {
3284 GetOpenFile(io, fptr);
3285 rb_io_check_char_readable(fptr);
3286 return read_all(fptr, remain_size(fptr), str);
3287 }
3288 len = NUM2LONG(length);
3289 if (len < 0) {
3290 rb_raise(rb_eArgError, "negative length %ld given", len);
3291 }
3292
3293 shrinkable = io_setstrbuf(&str,len);
3294
3295 GetOpenFile(io, fptr);
3296 rb_io_check_byte_readable(fptr);
3297 if (len == 0) {
3298 io_set_read_length(str, 0, shrinkable);
3299 return str;
3300 }
3301
3302 READ_CHECK(fptr);
3303#if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
3304 previous_mode = set_binary_mode_with_seek_cur(fptr);
3305#endif
3306 n = io_fread(str, 0, len, fptr);
3307 io_set_read_length(str, n, shrinkable);
3308#if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
3309 if (previous_mode == O_TEXT) {
3310 setmode(fptr->fd, O_TEXT);
3311 }
3312#endif
3313 if (n == 0) return Qnil;
3314
3315 return str;
3316}
3317
3318static void
3319rscheck(const char *rsptr, long rslen, VALUE rs)
3320{
3321 if (!rs) return;
3322 if (RSTRING_PTR(rs) != rsptr && RSTRING_LEN(rs) != rslen)
3323 rb_raise(rb_eRuntimeError, "rs modified");
3324}
3325
3326static int
3327appendline(rb_io_t *fptr, int delim, VALUE *strp, long *lp)
3328{
3329 VALUE str = *strp;
3330 long limit = *lp;
3331
3332 if (NEED_READCONV(fptr)) {
3333 SET_BINARY_MODE(fptr);
3334 make_readconv(fptr, 0);
3335 do {
3336 const char *p, *e;
3337 int searchlen = READ_CHAR_PENDING_COUNT(fptr);
3338 if (searchlen) {
3339 p = READ_CHAR_PENDING_PTR(fptr);
3340 if (0 < limit && limit < searchlen)
3341 searchlen = (int)limit;
3342 e = memchr(p, delim, searchlen);
3343 if (e) {
3344 int len = (int)(e-p+1);
3345 if (NIL_P(str))
3346 *strp = str = rb_str_new(p, len);
3347 else
3348 rb_str_buf_cat(str, p, len);
3349 fptr->cbuf.off += len;
3350 fptr->cbuf.len -= len;
3351 limit -= len;
3352 *lp = limit;
3353 return delim;
3354 }
3355
3356 if (NIL_P(str))
3357 *strp = str = rb_str_new(p, searchlen);
3358 else
3359 rb_str_buf_cat(str, p, searchlen);
3360 fptr->cbuf.off += searchlen;
3361 fptr->cbuf.len -= searchlen;
3362 limit -= searchlen;
3363
3364 if (limit == 0) {
3365 *lp = limit;
3366 return (unsigned char)RSTRING_PTR(str)[RSTRING_LEN(str)-1];
3367 }
3368 }
3369 } while (more_char(fptr) != MORE_CHAR_FINISHED);
3370 clear_readconv(fptr);
3371 *lp = limit;
3372 return EOF;
3373 }
3374
3375 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
3376 do {
3377 long pending = READ_DATA_PENDING_COUNT(fptr);
3378 if (pending > 0) {
3379 const char *p = READ_DATA_PENDING_PTR(fptr);
3380 const char *e;
3381 long last;
3382
3383 if (limit > 0 && pending > limit) pending = limit;
3384 e = memchr(p, delim, pending);
3385 if (e) pending = e - p + 1;
3386 if (!NIL_P(str)) {
3387 last = RSTRING_LEN(str);
3388 rb_str_resize(str, last + pending);
3389 }
3390 else {
3391 last = 0;
3392 *strp = str = rb_str_buf_new(pending);
3393 rb_str_set_len(str, pending);
3394 }
3395 read_buffered_data(RSTRING_PTR(str) + last, pending, fptr); /* must not fail */
3396 limit -= pending;
3397 *lp = limit;
3398 if (e) return delim;
3399 if (limit == 0)
3400 return (unsigned char)RSTRING_PTR(str)[RSTRING_LEN(str)-1];
3401 }
3402 READ_CHECK(fptr);
3403 } while (io_fillbuf(fptr) >= 0);
3404 *lp = limit;
3405 return EOF;
3406}
3407
3408static inline int
3409swallow(rb_io_t *fptr, int term)
3410{
3411 if (NEED_READCONV(fptr)) {
3412 rb_encoding *enc = io_read_encoding(fptr);
3413 int needconv = rb_enc_mbminlen(enc) != 1;
3414 SET_BINARY_MODE(fptr);
3415 make_readconv(fptr, 0);
3416 do {
3417 size_t cnt;
3418 while ((cnt = READ_CHAR_PENDING_COUNT(fptr)) > 0) {
3419 const char *p = READ_CHAR_PENDING_PTR(fptr);
3420 int i;
3421 if (!needconv) {
3422 if (*p != term) return TRUE;
3423 i = (int)cnt;
3424 while (--i && *++p == term);
3425 }
3426 else {
3427 const char *e = p + cnt;
3428 if (rb_enc_ascget(p, e, &i, enc) != term) return TRUE;
3429 while ((p += i) < e && rb_enc_ascget(p, e, &i, enc) == term);
3430 i = (int)(e - p);
3431 }
3432 io_shift_cbuf(fptr, (int)cnt - i, NULL);
3433 }
3434 } while (more_char(fptr) != MORE_CHAR_FINISHED);
3435 return FALSE;
3436 }
3437
3438 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
3439 do {
3440 size_t cnt;
3441 while ((cnt = READ_DATA_PENDING_COUNT(fptr)) > 0) {
3442 char buf[1024];
3443 const char *p = READ_DATA_PENDING_PTR(fptr);
3444 int i;
3445 if (cnt > sizeof buf) cnt = sizeof buf;
3446 if (*p != term) return TRUE;
3447 i = (int)cnt;
3448 while (--i && *++p == term);
3449 if (!read_buffered_data(buf, cnt - i, fptr)) /* must not fail */
3450 rb_sys_fail_path(fptr->pathv);
3451 }
3452 READ_CHECK(fptr);
3453 } while (io_fillbuf(fptr) == 0);
3454 return FALSE;
3455}
3456
3457static VALUE
3458rb_io_getline_fast(rb_io_t *fptr, rb_encoding *enc, int chomp)
3459{
3460 VALUE str = Qnil;
3461 int len = 0;
3462 long pos = 0;
3463 int cr = 0;
3464
3465 do {
3466 int pending = READ_DATA_PENDING_COUNT(fptr);
3467
3468 if (pending > 0) {
3469 const char *p = READ_DATA_PENDING_PTR(fptr);
3470 const char *e;
3471 int chomplen = 0;
3472
3473 e = memchr(p, '\n', pending);
3474 if (e) {
3475 pending = (int)(e - p + 1);
3476 if (chomp) {
3477 chomplen = (pending > 1 && *(e-1) == '\r') + 1;
3478 }
3479 }
3480 if (NIL_P(str)) {
3481 str = rb_str_new(p, pending - chomplen);
3482 fptr->rbuf.off += pending;
3483 fptr->rbuf.len -= pending;
3484 }
3485 else {
3486 rb_str_resize(str, len + pending - chomplen);
3487 read_buffered_data(RSTRING_PTR(str)+len, pending - chomplen, fptr);
3488 fptr->rbuf.off += chomplen;
3489 fptr->rbuf.len -= chomplen;
3490 if (pending == 1 && chomplen == 1 && len > 0) {
3491 if (RSTRING_PTR(str)[len-1] == '\r') {
3492 rb_str_resize(str, --len);
3493 break;
3494 }
3495 }
3496 }
3497 len += pending - chomplen;
3498 if (cr != ENC_CODERANGE_BROKEN)
3499 pos += rb_str_coderange_scan_restartable(RSTRING_PTR(str) + pos, RSTRING_PTR(str) + len, enc, &cr);
3500 if (e) break;
3501 }
3502 READ_CHECK(fptr);
3503 } while (io_fillbuf(fptr) >= 0);
3504 if (NIL_P(str)) return Qnil;
3505
3506 str = io_enc_str(str, fptr);
3507 ENC_CODERANGE_SET(str, cr);
3508 fptr->lineno++;
3509
3510 return str;
3511}
3512
3513struct getline_arg {
3514 VALUE io;
3515 VALUE rs;
3516 long limit;
3517 unsigned int chomp: 1;
3518};
3519
3520static void
3521extract_getline_opts(VALUE opts, struct getline_arg *args)
3522{
3523 int chomp = FALSE;
3524 if (!NIL_P(opts)) {
3525 static ID kwds[1];
3526 VALUE vchomp;
3527 if (!kwds[0]) {
3528 kwds[0] = rb_intern_const("chomp");
3529 }
3530 rb_get_kwargs(opts, kwds, 0, -2, &vchomp);
3531 chomp = (vchomp != Qundef) && RTEST(vchomp);
3532 }
3533 args->chomp = chomp;
3534}
3535
3536static void
3537extract_getline_args(int argc, VALUE *argv, struct getline_arg *args)
3538{
3539 VALUE rs = rb_rs, lim = Qnil;
3540
3541 if (argc == 1) {
3542 VALUE tmp = Qnil;
3543
3544 if (NIL_P(argv[0]) || !NIL_P(tmp = rb_check_string_type(argv[0]))) {
3545 rs = tmp;
3546 }
3547 else {
3548 lim = argv[0];
3549 }
3550 }
3551 else if (2 <= argc) {
3552 rs = argv[0], lim = argv[1];
3553 if (!NIL_P(rs))
3554 StringValue(rs);
3555 }
3556 args->rs = rs;
3557 args->limit = NIL_P(lim) ? -1L : NUM2LONG(lim);
3558}
3559
3560static void
3561check_getline_args(VALUE *rsp, long *limit, VALUE io)
3562{
3563 rb_io_t *fptr;
3564 VALUE rs = *rsp;
3565
3566 if (!NIL_P(rs)) {
3567 rb_encoding *enc_rs, *enc_io;
3568
3569 GetOpenFile(io, fptr);
3570 enc_rs = rb_enc_get(rs);
3571 enc_io = io_read_encoding(fptr);
3572 if (enc_io != enc_rs &&
3573 (rb_enc_str_coderange(rs) != ENC_CODERANGE_7BIT ||
3574 (RSTRING_LEN(rs) > 0 && !rb_enc_asciicompat(enc_io)))) {
3575 if (rs == rb_default_rs) {
3576 rs = rb_enc_str_new(0, 0, enc_io);
3577 rb_str_buf_cat_ascii(rs, "\n");
3578 *rsp = rs;
3579 }
3580 else {
3581 rb_raise(rb_eArgError, "encoding mismatch: %s IO with %s RS",
3582 rb_enc_name(enc_io),
3583 rb_enc_name(enc_rs));
3584 }
3585 }
3586 }
3587}
3588
3589static void
3590prepare_getline_args(int argc, VALUE *argv, struct getline_arg *args, VALUE io)
3591{
3592 VALUE opts;
3593 argc = rb_scan_args(argc, argv, "02:", NULL, NULL, &opts);
3594 extract_getline_args(argc, argv, args);
3595 extract_getline_opts(opts, args);
3596 check_getline_args(&args->rs, &args->limit, io);
3597}
3598
3599static VALUE
3600rb_io_getline_0(VALUE rs, long limit, int chomp, rb_io_t *fptr)
3601{
3602 VALUE str = Qnil;
3603 int nolimit = 0;
3604 rb_encoding *enc;
3605
3606 rb_io_check_char_readable(fptr);
3607 if (NIL_P(rs) && limit < 0) {
3608 str = read_all(fptr, 0, Qnil);
3609 if (RSTRING_LEN(str) == 0) return Qnil;
3610 if (chomp) rb_str_chomp_string(str, rb_default_rs);
3611 }
3612 else if (limit == 0) {
3613 return rb_enc_str_new(0, 0, io_read_encoding(fptr));
3614 }
3615 else if (rs == rb_default_rs && limit < 0 && !NEED_READCONV(fptr) &&
3616 rb_enc_asciicompat(enc = io_read_encoding(fptr))) {
3617 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
3618 return rb_io_getline_fast(fptr, enc, chomp);
3619 }
3620 else {
3621 int c, newline = -1;
3622 const char *rsptr = 0;
3623 long rslen = 0;
3624 int rspara = 0;
3625 int extra_limit = 16;
3626 int chomp_cr = chomp;
3627
3628 SET_BINARY_MODE(fptr);
3629 enc = io_read_encoding(fptr);
3630
3631 if (!NIL_P(rs)) {
3632 rslen = RSTRING_LEN(rs);
3633 if (rslen == 0) {
3634 rsptr = "\n\n";
3635 rslen = 2;
3636 rspara = 1;
3637 swallow(fptr, '\n');
3638 rs = 0;
3639 if (!rb_enc_asciicompat(enc)) {
3640 rs = rb_usascii_str_new(rsptr, rslen);
3641 rs = rb_str_encode(rs, rb_enc_from_encoding(enc), 0, Qnil);
3642 OBJ_FREEZE(rs);
3643 rsptr = RSTRING_PTR(rs);
3644 rslen = RSTRING_LEN(rs);
3645 }
3646 }
3647 else {
3648 rsptr = RSTRING_PTR(rs);
3649 }
3650 newline = (unsigned char)rsptr[rslen - 1];
3651 chomp_cr = chomp && rslen == 1 && newline == '\n';
3652 }
3653
3654 /* MS - Optimization */
3655 while ((c = appendline(fptr, newline, &str, &limit)) != EOF) {
3656 const char *s, *p, *pp, *e;
3657
3658 if (c == newline) {
3659 if (RSTRING_LEN(str) < rslen) continue;
3660 s = RSTRING_PTR(str);
3661 e = RSTRING_END(str);
3662 p = e - rslen;
3663 pp = rb_enc_left_char_head(s, p, e, enc);
3664 if (pp != p) continue;
3665 if (!rspara) rscheck(rsptr, rslen, rs);
3666 if (memcmp(p, rsptr, rslen) == 0) {
3667 if (chomp) {
3668 if (chomp_cr && p > s && *(p-1) == '\r') --p;
3669 rb_str_set_len(str, p - s);
3670 }
3671 break;
3672 }
3673 }
3674 if (limit == 0) {
3675 s = RSTRING_PTR(str);
3676 p = RSTRING_END(str);
3677 pp = rb_enc_left_char_head(s, p-1, p, enc);
3678 if (extra_limit &&
3679 MBCLEN_NEEDMORE_P(rb_enc_precise_mbclen(pp, p, enc))) {
3680 /* relax the limit while incomplete character.
3681 * extra_limit limits the relax length */
3682 limit = 1;
3683 extra_limit--;
3684 }
3685 else {
3686 nolimit = 1;
3687 break;
3688 }
3689 }
3690 }
3691
3692 if (rspara && c != EOF)
3693 swallow(fptr, '\n');
3694 if (!NIL_P(str))
3695 str = io_enc_str(str, fptr);
3696 }
3697
3698 if (!NIL_P(str) && !nolimit) {
3699 fptr->lineno++;
3700 }
3701
3702 return str;
3703}
3704
3705static VALUE
3706rb_io_getline_1(VALUE rs, long limit, int chomp, VALUE io)
3707{
3708 rb_io_t *fptr;
3709 int old_lineno, new_lineno;
3710 VALUE str;
3711
3712 GetOpenFile(io, fptr);
3713 old_lineno = fptr->lineno;
3714 str = rb_io_getline_0(rs, limit, chomp, fptr);
3715 if (!NIL_P(str) && (new_lineno = fptr->lineno) != old_lineno) {
3716 if (io == ARGF.current_file) {
3717 ARGF.lineno += new_lineno - old_lineno;
3718 ARGF.last_lineno = ARGF.lineno;
3719 }
3720 else {
3721 ARGF.last_lineno = new_lineno;
3722 }
3723 }
3724
3725 return str;
3726}
3727
3728static VALUE
3729rb_io_getline(int argc, VALUE *argv, VALUE io)
3730{
3731 struct getline_arg args;
3732
3733 prepare_getline_args(argc, argv, &args, io);
3734 return rb_io_getline_1(args.rs, args.limit, args.chomp, io);
3735}
3736
3737 VALUE
3738 rb_io_gets(VALUE io)
3739{
3740 return rb_io_getline_1(rb_default_rs, -1, FALSE, io);
3741}
3742
3743 VALUE
3744 rb_io_gets_internal(VALUE io)
3745{
3746 rb_io_t *fptr;
3747 GetOpenFile(io, fptr);
3748 return rb_io_getline_0(rb_default_rs, -1, FALSE, fptr);
3749}
3750
3751/*
3752 * call-seq:
3753 * ios.gets(sep=$/ [, getline_args]) -> string or nil
3754 * ios.gets(limit [, getline_args]) -> string or nil
3755 * ios.gets(sep, limit [, getline_args]) -> string or nil
3756 *
3757 * Reads the next ``line'' from the I/O stream; lines are separated by
3758 * <i>sep</i>. A separator of +nil+ reads the entire
3759 * contents, and a zero-length separator reads the input a paragraph at
3760 * a time (two successive newlines in the input separate paragraphs).
3761 * The stream must be opened for reading or an IOError will be raised.
3762 * The line read in will be returned and also assigned to
3763 * <code>$_</code>. Returns +nil+ if called at end of file. If the
3764 * first argument is an integer, or optional second argument is given,
3765 * the returning string would not be longer than the given value in
3766 * bytes.
3767 *
3768 * File.new("testfile").gets #=> "This is line one\n"
3769 * $_ #=> "This is line one\n"
3770 *
3771 * File.new("testfile").gets(4)#=> "This"
3772 *
3773 * If IO contains multibyte characters byte then <code>gets(1)</code>
3774 * returns character entirely:
3775 *
3776 * # Russian characters take 2 bytes
3777 * File.write("testfile", "\u{442 435 441 442}")
3778 * File.open("testfile") {|f|f.gets(1)} #=> "\u0442"
3779 * File.open("testfile") {|f|f.gets(2)} #=> "\u0442"
3780 * File.open("testfile") {|f|f.gets(3)} #=> "\u0442\u0435"
3781 * File.open("testfile") {|f|f.gets(4)} #=> "\u0442\u0435"
3782 */
3783
3784static VALUE
3785rb_io_gets_m(int argc, VALUE *argv, VALUE io)
3786{
3787 VALUE str;
3788
3789 str = rb_io_getline(argc, argv, io);
3790 rb_lastline_set(str);
3791
3792 return str;
3793}
3794
3795/*
3796 * call-seq:
3797 * ios.lineno -> integer
3798 *
3799 * Returns the current line number in <em>ios</em>. The stream must be
3800 * opened for reading. #lineno counts the number of times #gets is called
3801 * rather than the number of newlines encountered. The two values will
3802 * differ if #gets is called with a separator other than newline.
3803 *
3804 * Methods that use <code>$/</code> like #each, #lines and #readline will
3805 * also increment #lineno.
3806 *
3807 * See also the <code>$.</code> variable.
3808 *
3809 * f = File.new("testfile")
3810 * f.lineno #=> 0
3811 * f.gets #=> "This is line one\n"
3812 * f.lineno #=> 1
3813 * f.gets #=> "This is line two\n"
3814 * f.lineno #=> 2
3815 */
3816
3817static VALUE
3818rb_io_lineno(VALUE io)
3819{
3820 rb_io_t *fptr;
3821
3822 GetOpenFile(io, fptr);
3823 rb_io_check_char_readable(fptr);
3824 return INT2NUM(fptr->lineno);
3825}
3826
3827/*
3828 * call-seq:
3829 * ios.lineno = integer -> integer
3830 *
3831 * Manually sets the current line number to the given value.
3832 * <code>$.</code> is updated only on the next read.
3833 *
3834 * f = File.new("testfile")
3835 * f.gets #=> "This is line one\n"
3836 * $. #=> 1
3837 * f.lineno = 1000
3838 * f.lineno #=> 1000
3839 * $. #=> 1 # lineno of last read
3840 * f.gets #=> "This is line two\n"
3841 * $. #=> 1001 # lineno of last read
3842 */
3843
3844static VALUE
3845rb_io_set_lineno(VALUE io, VALUE lineno)
3846{
3847 rb_io_t *fptr;
3848
3849 GetOpenFile(io, fptr);
3850 rb_io_check_char_readable(fptr);
3851 fptr->lineno = NUM2INT(lineno);
3852 return lineno;
3853}
3854
3855/*
3856 * call-seq:
3857 * ios.readline(sep=$/ [, getline_args]) -> string
3858 * ios.readline(limit [, getline_args]) -> string
3859 * ios.readline(sep, limit [, getline_args]) -> string
3860 *
3861 * Reads a line as with IO#gets, but raises an EOFError on end of file.
3862 */
3863
3864static VALUE
3865rb_io_readline(int argc, VALUE *argv, VALUE io)
3866{
3867 VALUE line = rb_io_gets_m(argc, argv, io);
3868
3869 if (NIL_P(line)) {
3870 rb_eof_error();
3871 }
3872 return line;
3873}
3874
3875static VALUE io_readlines(const struct getline_arg *arg, VALUE io);
3876
3877/*
3878 * call-seq:
3879 * ios.readlines(sep=$/ [, getline_args]) -> array
3880 * ios.readlines(limit [, getline_args]) -> array
3881 * ios.readlines(sep, limit [, getline_args]) -> array
3882 *
3883 * Reads all of the lines in <em>ios</em>, and returns them in
3884 * an array. Lines are separated by the optional <i>sep</i>. If
3885 * <i>sep</i> is +nil+, the rest of the stream is returned
3886 * as a single record.
3887 * If the first argument is an integer, or an
3888 * optional second argument is given, the returning string would not be
3889 * longer than the given value in bytes. The stream must be opened for
3890 * reading or an IOError will be raised.
3891 *
3892 * f = File.new("testfile")
3893 * f.readlines[0] #=> "This is line one\n"
3894 *
3895 * f = File.new("testfile", chomp: true)
3896 * f.readlines[0] #=> "This is line one"
3897 *
3898 * See IO.readlines for details about getline_args.
3899 */
3900
3901static VALUE
3902rb_io_readlines(int argc, VALUE *argv, VALUE io)
3903{
3904 struct getline_arg args;
3905
3906 prepare_getline_args(argc, argv, &args, io);
3907 return io_readlines(&args, io);
3908}
3909
3910static VALUE
3911io_readlines(const struct getline_arg *arg, VALUE io)
3912{
3913 VALUE line, ary;
3914
3915 if (arg->limit == 0)
3916 rb_raise(rb_eArgError, "invalid limit: 0 for readlines");
3917 ary = rb_ary_new();
3918 while (!NIL_P(line = rb_io_getline_1(arg->rs, arg->limit, arg->chomp, io))) {
3919 rb_ary_push(ary, line);
3920 }
3921 return ary;
3922}
3923
3924/*
3925 * call-seq:
3926 * ios.each(sep=$/ [, getline_args]) {|line| block } -> ios
3927 * ios.each(limit [, getline_args]) {|line| block } -> ios
3928 * ios.each(sep, limit [, getline_args]) {|line| block } -> ios
3929 * ios.each(...) -> an_enumerator
3930 *
3931 * ios.each_line(sep=$/ [, getline_args]) {|line| block } -> ios
3932 * ios.each_line(limit [, getline_args]) {|line| block } -> ios
3933 * ios.each_line(sep, limit [, getline_args]) {|line| block } -> ios
3934 * ios.each_line(...) -> an_enumerator
3935 *
3936 * Executes the block for every line in <em>ios</em>, where lines are
3937 * separated by <i>sep</i>. <em>ios</em> must be opened for
3938 * reading or an IOError will be raised.
3939 *
3940 * If no block is given, an enumerator is returned instead.
3941 *
3942 * f = File.new("testfile")
3943 * f.each {|line| puts "#{f.lineno}: #{line}" }
3944 *
3945 * <em>produces:</em>
3946 *
3947 * 1: This is line one
3948 * 2: This is line two
3949 * 3: This is line three
3950 * 4: And so on...
3951 *
3952 * See IO.readlines for details about getline_args.
3953 */
3954
3955static VALUE
3956rb_io_each_line(int argc, VALUE *argv, VALUE io)
3957{
3958 VALUE str;
3959 struct getline_arg args;
3960
3961 RETURN_ENUMERATOR(io, argc, argv);
3962 prepare_getline_args(argc, argv, &args, io);
3963 if (args.limit == 0)
3964 rb_raise(rb_eArgError, "invalid limit: 0 for each_line");
3965 while (!NIL_P(str = rb_io_getline_1(args.rs, args.limit, args.chomp, io))) {
3966 rb_yield(str);
3967 }
3968 return io;
3969}
3970
3971/*
3972 * call-seq:
3973 * ios.each_byte {|byte| block } -> ios
3974 * ios.each_byte -> an_enumerator
3975 *
3976 * Calls the given block once for each byte (0..255) in <em>ios</em>,
3977 * passing the byte as an argument. The stream must be opened for
3978 * reading or an IOError will be raised.
3979 *
3980 * If no block is given, an enumerator is returned instead.
3981 *
3982 * f = File.new("testfile")
3983 * checksum = 0
3984 * f.each_byte {|x| checksum ^= x } #=> #<File:testfile>
3985 * checksum #=> 12
3986 */
3987
3988static VALUE
3989rb_io_each_byte(VALUE io)
3990{
3991 rb_io_t *fptr;
3992
3993 RETURN_ENUMERATOR(io, 0, 0);
3994 GetOpenFile(io, fptr);
3995
3996 do {
3997 while (fptr->rbuf.len > 0) {
3998 char *p = fptr->rbuf.ptr + fptr->rbuf.off++;
3999 fptr->rbuf.len--;
4000 rb_yield(INT2FIX(*p & 0xff));
4001 rb_io_check_byte_readable(fptr);
4002 errno = 0;
4003 }
4004 READ_CHECK(fptr);
4005 } while (io_fillbuf(fptr) >= 0);
4006 return io;
4007}
4008
4009static VALUE
4010io_getc(rb_io_t *fptr, rb_encoding *enc)
4011{
4012 int r, n, cr = 0;
4013 VALUE str;
4014
4015 if (NEED_READCONV(fptr)) {
4016 rb_encoding *read_enc = io_read_encoding(fptr);
4017
4018 str = Qnil;
4019 SET_BINARY_MODE(fptr);
4020 make_readconv(fptr, 0);
4021
4022 while (1) {
4023 if (fptr->cbuf.len) {
4024 r = rb_enc_precise_mbclen(fptr->cbuf.ptr+fptr->cbuf.off,
4025 fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
4026 read_enc);
4027 if (!MBCLEN_NEEDMORE_P(r))
4028 break;
4029 if (fptr->cbuf.len == fptr->cbuf.capa) {
4030 rb_raise(rb_eIOError, "too long character");
4031 }
4032 }
4033
4034 if (more_char(fptr) == MORE_CHAR_FINISHED) {
4035 if (fptr->cbuf.len == 0) {
4036 clear_readconv(fptr);
4037 return Qnil;
4038 }
4039 /* return an unit of an incomplete character just before EOF */
4040 str = rb_enc_str_new(fptr->cbuf.ptr+fptr->cbuf.off, 1, read_enc);
4041 fptr->cbuf.off += 1;
4042 fptr->cbuf.len -= 1;
4043 if (fptr->cbuf.len == 0) clear_readconv(fptr);
4044 ENC_CODERANGE_SET(str, ENC_CODERANGE_BROKEN);
4045 return str;
4046 }
4047 }
4048 if (MBCLEN_INVALID_P(r)) {
4049 r = rb_enc_mbclen(fptr->cbuf.ptr+fptr->cbuf.off,
4050 fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
4051 read_enc);
4052 io_shift_cbuf(fptr, r, &str);
4053 cr = ENC_CODERANGE_BROKEN;
4054 }
4055 else {
4056 io_shift_cbuf(fptr, MBCLEN_CHARFOUND_LEN(r), &str);
4057 cr = ENC_CODERANGE_VALID;
4058 if (MBCLEN_CHARFOUND_LEN(r) == 1 && rb_enc_asciicompat(read_enc) &&
4059 ISASCII(RSTRING_PTR(str)[0])) {
4060 cr = ENC_CODERANGE_7BIT;
4061 }
4062 }
4063 str = io_enc_str(str, fptr);
4064 ENC_CODERANGE_SET(str, cr);
4065 return str;
4066 }
4067
4068 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
4069 if (io_fillbuf(fptr) < 0) {
4070 return Qnil;
4071 }
4072 if (rb_enc_asciicompat(enc) && ISASCII(fptr->rbuf.ptr[fptr->rbuf.off])) {
4073 str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, 1);
4074 fptr->rbuf.off += 1;
4075 fptr->rbuf.len -= 1;
4076 cr = ENC_CODERANGE_7BIT;
4077 }
4078 else {
4079 r = rb_enc_precise_mbclen(fptr->rbuf.ptr+fptr->rbuf.off, fptr->rbuf.ptr+fptr->rbuf.off+fptr->rbuf.len, enc);
4080 if (MBCLEN_CHARFOUND_P(r) &&
4081 (n = MBCLEN_CHARFOUND_LEN(r)) <= fptr->rbuf.len) {
4082 str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, n);
4083 fptr->rbuf.off += n;
4084 fptr->rbuf.len -= n;
4085 cr = ENC_CODERANGE_VALID;
4086 }
4087 else if (MBCLEN_NEEDMORE_P(r)) {
4088 str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, fptr->rbuf.len);
4089 fptr->rbuf.len = 0;
4090 getc_needmore:
4091 if (io_fillbuf(fptr) != -1) {
4092 rb_str_cat(str, fptr->rbuf.ptr+fptr->rbuf.off, 1);
4093 fptr->rbuf.off++;
4094 fptr->rbuf.len--;
4095 r = rb_enc_precise_mbclen(RSTRING_PTR(str), RSTRING_PTR(str)+RSTRING_LEN(str), enc);
4096 if (MBCLEN_NEEDMORE_P(r)) {
4097 goto getc_needmore;
4098 }
4099 else if (MBCLEN_CHARFOUND_P(r)) {
4100 cr = ENC_CODERANGE_VALID;
4101 }
4102 }
4103 }
4104 else {
4105 str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, 1);
4106 fptr->rbuf.off++;
4107 fptr->rbuf.len--;
4108 }
4109 }
4110 if (!cr) cr = ENC_CODERANGE_BROKEN;
4111 str = io_enc_str(str, fptr);
4112 ENC_CODERANGE_SET(str, cr);
4113 return str;
4114}
4115
4116/*
4117 * call-seq:
4118 * ios.each_char {|c| block } -> ios
4119 * ios.each_char -> an_enumerator
4120 *
4121 * Calls the given block once for each character in <em>ios</em>,
4122 * passing the character as an argument. The stream must be opened for
4123 * reading or an IOError will be raised.
4124 *
4125 * If no block is given, an enumerator is returned instead.
4126 *
4127 * f = File.new("testfile")
4128 * f.each_char {|c| print c, ' ' } #=> #<File:testfile>
4129 */
4130
4131static VALUE
4132rb_io_each_char(VALUE io)
4133{
4134 rb_io_t *fptr;
4135 rb_encoding *enc;
4136 VALUE c;
4137
4138 RETURN_ENUMERATOR(io, 0, 0);
4139 GetOpenFile(io, fptr);
4140 rb_io_check_char_readable(fptr);
4141
4142 enc = io_input_encoding(fptr);
4143 READ_CHECK(fptr);
4144 while (!NIL_P(c = io_getc(fptr, enc))) {
4145 rb_yield(c);
4146 }
4147 return io;
4148}
4149
4150/*
4151 * call-seq:
4152 * ios.each_codepoint {|c| block } -> ios
4153 * ios.codepoints {|c| block } -> ios
4154 * ios.each_codepoint -> an_enumerator
4155 * ios.codepoints -> an_enumerator
4156 *
4157 * Passes the Integer ordinal of each character in <i>ios</i>,
4158 * passing the codepoint as an argument. The stream must be opened for
4159 * reading or an IOError will be raised.
4160 *
4161 * If no block is given, an enumerator is returned instead.
4162 *
4163 */
4164
4165static VALUE
4166rb_io_each_codepoint(VALUE io)
4167{
4168 rb_io_t *fptr;
4169 rb_encoding *enc;
4170 unsigned int c;
4171 int r, n;
4172
4173 RETURN_ENUMERATOR(io, 0, 0);
4174 GetOpenFile(io, fptr);
4175 rb_io_check_char_readable(fptr);
4176
4177 READ_CHECK(fptr);
4178 if (NEED_READCONV(fptr)) {
4179 SET_BINARY_MODE(fptr);
4180 r = 1; /* no invalid char yet */
4181 for (;;) {
4182 make_readconv(fptr, 0);
4183 for (;;) {
4184 if (fptr->cbuf.len) {
4185 if (fptr->encs.enc)
4186 r = rb_enc_precise_mbclen(fptr->cbuf.ptr+fptr->cbuf.off,
4187 fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
4188 fptr->encs.enc);
4189 else
4190 r = ONIGENC_CONSTRUCT_MBCLEN_CHARFOUND(1);
4191 if (!MBCLEN_NEEDMORE_P(r))
4192 break;
4193 if (fptr->cbuf.len == fptr->cbuf.capa) {
4194 rb_raise(rb_eIOError, "too long character");
4195 }
4196 }
4197 if (more_char(fptr) == MORE_CHAR_FINISHED) {
4198 clear_readconv(fptr);
4199 if (!MBCLEN_CHARFOUND_P(r)) {
4200 enc = fptr->encs.enc;
4201 goto invalid;
4202 }
4203 return io;
4204 }
4205 }
4206 if (MBCLEN_INVALID_P(r)) {
4207 enc = fptr->encs.enc;
4208 goto invalid;
4209 }
4210 n = MBCLEN_CHARFOUND_LEN(r);
4211 if (fptr->encs.enc) {
4212 c = rb_enc_codepoint(fptr->cbuf.ptr+fptr->cbuf.off,
4213 fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
4214 fptr->encs.enc);
4215 }
4216 else {
4217 c = (unsigned char)fptr->cbuf.ptr[fptr->cbuf.off];
4218 }
4219 fptr->cbuf.off += n;
4220 fptr->cbuf.len -= n;
4221 rb_yield(UINT2NUM(c));
4222 rb_io_check_byte_readable(fptr);
4223 }
4224 }
4225 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
4226 enc = io_input_encoding(fptr);
4227 while (io_fillbuf(fptr) >= 0) {
4228 r = rb_enc_precise_mbclen(fptr->rbuf.ptr+fptr->rbuf.off,
4229 fptr->rbuf.ptr+fptr->rbuf.off+fptr->rbuf.len, enc);
4230 if (MBCLEN_CHARFOUND_P(r) &&
4231 (n = MBCLEN_CHARFOUND_LEN(r)) <= fptr->rbuf.len) {
4232 c = rb_enc_codepoint(fptr->rbuf.ptr+fptr->rbuf.off,
4233 fptr->rbuf.ptr+fptr->rbuf.off+fptr->rbuf.len, enc);
4234 fptr->rbuf.off += n;
4235 fptr->rbuf.len -= n;
4236 rb_yield(UINT2NUM(c));
4237 }
4238 else if (MBCLEN_INVALID_P(r)) {
4239 goto invalid;
4240 }
4241 else if (MBCLEN_NEEDMORE_P(r)) {
4242 char cbuf[8], *p = cbuf;
4243 int more = MBCLEN_NEEDMORE_LEN(r);
4244 if (more > numberof(cbuf)) goto invalid;
4245 more += n = fptr->rbuf.len;
4246 if (more > numberof(cbuf)) goto invalid;
4247 while ((n = (int)read_buffered_data(p, more, fptr)) > 0 &&
4248 (p += n, (more -= n) > 0)) {
4249 if (io_fillbuf(fptr) < 0) goto invalid;
4250 if ((n = fptr->rbuf.len) > more) n = more;
4251 }
4252 r = rb_enc_precise_mbclen(cbuf, p, enc);
4253 if (!MBCLEN_CHARFOUND_P(r)) goto invalid;
4254 c = rb_enc_codepoint(cbuf, p, enc);
4255 rb_yield(UINT2NUM(c));
4256 }
4257 else {
4258 continue;
4259 }
4260 rb_io_check_byte_readable(fptr);
4261 }
4262 return io;
4263
4264 invalid:
4265 rb_raise(rb_eArgError, "invalid byte sequence in %s", rb_enc_name(enc));
4266 UNREACHABLE_RETURN(Qundef);
4267}
4268
4269/*
4270 * call-seq:
4271 * ios.getc -> string or nil
4272 *
4273 * Reads a one-character string from <em>ios</em>. Returns
4274 * +nil+ if called at end of file.
4275 *
4276 * f = File.new("testfile")
4277 * f.getc #=> "h"
4278 * f.getc #=> "e"
4279 */
4280
4281static VALUE
4282rb_io_getc(VALUE io)
4283{
4284 rb_io_t *fptr;
4285 rb_encoding *enc;
4286
4287 GetOpenFile(io, fptr);
4288 rb_io_check_char_readable(fptr);
4289
4290 enc = io_input_encoding(fptr);
4291 READ_CHECK(fptr);
4292 return io_getc(fptr, enc);
4293}
4294
4295/*
4296 * call-seq:
4297 * ios.readchar -> string
4298 *
4299 * Reads a one-character string from <em>ios</em>. Raises an
4300 * EOFError on end of file.
4301 *
4302 * f = File.new("testfile")
4303 * f.readchar #=> "h"
4304 * f.readchar #=> "e"
4305 */
4306
4307static VALUE
4308rb_io_readchar(VALUE io)
4309{
4310 VALUE c = rb_io_getc(io);
4311
4312 if (NIL_P(c)) {
4313 rb_eof_error();
4314 }
4315 return c;
4316}
4317
4318/*
4319 * call-seq:
4320 * ios.getbyte -> integer or nil
4321 *
4322 * Gets the next 8-bit byte (0..255) from <em>ios</em>. Returns
4323 * +nil+ if called at end of file.
4324 *
4325 * f = File.new("testfile")
4326 * f.getbyte #=> 84
4327 * f.getbyte #=> 104
4328 */
4329
4330 VALUE
4331 rb_io_getbyte(VALUE io)
4332{
4333 rb_io_t *fptr;
4334 int c;
4335
4336 GetOpenFile(io, fptr);
4337 rb_io_check_byte_readable(fptr);
4338 READ_CHECK(fptr);
4339 VALUE r_stdout = rb_ractor_stdout();
4340 if (fptr->fd == 0 && (fptr->mode & FMODE_TTY) && RB_TYPE_P(r_stdout, T_FILE)) {
4341 rb_io_t *ofp;
4342 GetOpenFile(r_stdout, ofp);
4343 if (ofp->mode & FMODE_TTY) {
4344 rb_io_flush(r_stdout);
4345 }
4346 }
4347 if (io_fillbuf(fptr) < 0) {
4348 return Qnil;
4349 }
4350 fptr->rbuf.off++;
4351 fptr->rbuf.len--;
4352 c = (unsigned char)fptr->rbuf.ptr[fptr->rbuf.off-1];
4353 return INT2FIX(c & 0xff);
4354}
4355
4356/*
4357 * call-seq:
4358 * ios.readbyte -> integer
4359 *
4360 * Reads a byte as with IO#getbyte, but raises an EOFError on end of
4361 * file.
4362 */
4363
4364static VALUE
4365rb_io_readbyte(VALUE io)
4366{
4367 VALUE c = rb_io_getbyte(io);
4368
4369 if (NIL_P(c)) {
4370 rb_eof_error();
4371 }
4372 return c;
4373}
4374
4375/*
4376 * call-seq:
4377 * ios.ungetbyte(string) -> nil
4378 * ios.ungetbyte(integer) -> nil
4379 *
4380 * Pushes back bytes (passed as a parameter) onto <em>ios</em>,
4381 * such that a subsequent buffered read will return it. Only one byte
4382 * may be pushed back before a subsequent read operation (that is,
4383 * you will be able to read only the last of several bytes that have been pushed
4384 * back). Has no effect with unbuffered reads (such as IO#sysread).
4385 *
4386 * f = File.new("testfile") #=> #<File:testfile>
4387 * b = f.getbyte #=> 0x38
4388 * f.ungetbyte(b) #=> nil
4389 * f.getbyte #=> 0x38
4390 */
4391
4392 VALUE
4393 rb_io_ungetbyte(VALUE io, VALUE b)
4394{
4395 rb_io_t *fptr;
4396
4397 GetOpenFile(io, fptr);
4398 rb_io_check_byte_readable(fptr);
4399 switch (TYPE(b)) {
4400 case T_NIL:
4401 return Qnil;
4402 case T_FIXNUM:
4403 case T_BIGNUM: ;
4404 VALUE v = rb_int_modulo(b, INT2FIX(256));
4405 unsigned char c = NUM2INT(v) & 0xFF;
4406 b = rb_str_new((const char *)&c, 1);
4407 break;
4408 default:
4409 SafeStringValue(b);
4410 }
4411 io_ungetbyte(b, fptr);
4412 return Qnil;
4413}
4414
4415/*
4416 * call-seq:
4417 * ios.ungetc(string) -> nil
4418 *
4419 * Pushes back one character (passed as a parameter) onto <em>ios</em>,
4420 * such that a subsequent buffered character read will return it. Only one character
4421 * may be pushed back before a subsequent read operation (that is,
4422 * you will be able to read only the last of several characters that have been pushed
4423 * back). Has no effect with unbuffered reads (such as IO#sysread).
4424 *
4425 * f = File.new("testfile") #=> #<File:testfile>
4426 * c = f.getc #=> "8"
4427 * f.ungetc(c) #=> nil
4428 * f.getc #=> "8"
4429 */
4430
4431 VALUE
4432 rb_io_ungetc(VALUE io, VALUE c)
4433{
4434 rb_io_t *fptr;
4435 long len;
4436
4437 GetOpenFile(io, fptr);
4438 rb_io_check_char_readable(fptr);
4439 if (FIXNUM_P(c)) {
4440 c = rb_enc_uint_chr(FIX2UINT(c), io_read_encoding(fptr));
4441 }
4442 else if (RB_TYPE_P(c, T_BIGNUM)) {
4443 c = rb_enc_uint_chr(NUM2UINT(c), io_read_encoding(fptr));
4444 }
4445 else {
4446 SafeStringValue(c);
4447 }
4448 if (NEED_READCONV(fptr)) {
4449 SET_BINARY_MODE(fptr);
4450 len = RSTRING_LEN(c);
4451#if SIZEOF_LONG > SIZEOF_INT
4452 if (len > INT_MAX)
4453 rb_raise(rb_eIOError, "ungetc failed");
4454#endif
4455 make_readconv(fptr, (int)len);
4456 if (fptr->cbuf.capa - fptr->cbuf.len < len)
4457 rb_raise(rb_eIOError, "ungetc failed");
4458 if (fptr->cbuf.off < len) {
4459 MEMMOVE(fptr->cbuf.ptr+fptr->cbuf.capa-fptr->cbuf.len,
4460 fptr->cbuf.ptr+fptr->cbuf.off,
4461 char, fptr->cbuf.len);
4462 fptr->cbuf.off = fptr->cbuf.capa-fptr->cbuf.len;
4463 }
4464 fptr->cbuf.off -= (int)len;
4465 fptr->cbuf.len += (int)len;
4466 MEMMOVE(fptr->cbuf.ptr+fptr->cbuf.off, RSTRING_PTR(c), char, len);
4467 }
4468 else {
4469 NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
4470 io_ungetbyte(c, fptr);
4471 }
4472 return Qnil;
4473}
4474
4475/*
4476 * call-seq:
4477 * ios.isatty -> true or false
4478 * ios.tty? -> true or false
4479 *
4480 * Returns <code>true</code> if <em>ios</em> is associated with a
4481 * terminal device (tty), <code>false</code> otherwise.
4482 *
4483 * File.new("testfile").isatty #=> false
4484 * File.new("/dev/tty").isatty #=> true
4485 */
4486
4487static VALUE
4488rb_io_isatty(VALUE io)
4489{
4490 rb_io_t *fptr;
4491
4492 GetOpenFile(io, fptr);
4493 if (isatty(fptr->fd) == 0)
4494 return Qfalse;
4495 return Qtrue;
4496}
4497
4498#if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
4499/*
4500 * call-seq:
4501 * ios.close_on_exec? -> true or false
4502 *
4503 * Returns <code>true</code> if <em>ios</em> will be closed on exec.
4504 *
4505 * f = open("/dev/null")
4506 * f.close_on_exec? #=> false
4507 * f.close_on_exec = true
4508 * f.close_on_exec? #=> true
4509 * f.close_on_exec = false
4510 * f.close_on_exec? #=> false
4511 */
4512
4513static VALUE
4514 rb_io_close_on_exec_p(VALUE io)
4515{
4516 rb_io_t *fptr;
4517 VALUE write_io;
4518 int fd, ret;
4519
4520 write_io = GetWriteIO(io);
4521 if (io != write_io) {
4522 GetOpenFile(write_io, fptr);
4523 if (fptr && 0 <= (fd = fptr->fd)) {
4524 if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
4525 if (!(ret & FD_CLOEXEC)) return Qfalse;
4526 }
4527 }
4528
4529 GetOpenFile(io, fptr);
4530 if (fptr && 0 <= (fd = fptr->fd)) {
4531 if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
4532 if (!(ret & FD_CLOEXEC)) return Qfalse;
4533 }
4534 return Qtrue;
4535}
4536#else
4537#define rb_io_close_on_exec_p rb_f_notimplement
4538#endif
4539
4540#if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
4541/*
4542 * call-seq:
4543 * ios.close_on_exec = bool -> true or false
4544 *
4545 * Sets a close-on-exec flag.
4546 *
4547 * f = open("/dev/null")
4548 * f.close_on_exec = true
4549 * system("cat", "/proc/self/fd/#{f.fileno}") # cat: /proc/self/fd/3: No such file or directory
4550 * f.closed? #=> false
4551 *
4552 * Ruby sets close-on-exec flags of all file descriptors by default
4553 * since Ruby 2.0.0.
4554 * So you don't need to set by yourself.
4555 * Also, unsetting a close-on-exec flag can cause file descriptor leak
4556 * if another thread use fork() and exec() (via system() method for example).
4557 * If you really needs file descriptor inheritance to child process,
4558 * use spawn()'s argument such as fd=>fd.
4559 */
4560
4561static VALUE
4562 rb_io_set_close_on_exec(VALUE io, VALUE arg)
4563{
4564 int flag = RTEST(arg) ? FD_CLOEXEC : 0;
4565 rb_io_t *fptr;
4566 VALUE write_io;
4567 int fd, ret;
4568
4569 write_io = GetWriteIO(io);
4570 if (io != write_io) {
4571 GetOpenFile(write_io, fptr);
4572 if (fptr && 0 <= (fd = fptr->fd)) {
4573 if ((ret = fcntl(fptr->fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
4574 if ((ret & FD_CLOEXEC) != flag) {
4575 ret = (ret & ~FD_CLOEXEC) | flag;
4576 ret = fcntl(fd, F_SETFD, ret);
4577 if (ret != 0) rb_sys_fail_path(fptr->pathv);
4578 }
4579 }
4580
4581 }
4582
4583 GetOpenFile(io, fptr);
4584 if (fptr && 0 <= (fd = fptr->fd)) {
4585 if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
4586 if ((ret & FD_CLOEXEC) != flag) {
4587 ret = (ret & ~FD_CLOEXEC) | flag;
4588 ret = fcntl(fd, F_SETFD, ret);
4589 if (ret != 0) rb_sys_fail_path(fptr->pathv);
4590 }
4591 }
4592 return Qnil;
4593}
4594#else
4595#define rb_io_set_close_on_exec rb_f_notimplement
4596#endif
4597
4598#define IS_PREP_STDIO(f) ((f)->mode & FMODE_PREP)
4599#define PREP_STDIO_NAME(f) (RSTRING_PTR((f)->pathv))
4600
4601static VALUE
4602finish_writeconv(rb_io_t *fptr, int noalloc)
4603{
4604 unsigned char *ds, *dp, *de;
4605 rb_econv_result_t res;
4606
4607 if (!fptr->wbuf.ptr) {
4608 unsigned char buf[1024];
4609 long r;
4610
4611 res = econv_destination_buffer_full;
4612 while (res == econv_destination_buffer_full) {
4613 ds = dp = buf;
4614 de = buf + sizeof(buf);
4615 res = rb_econv_convert(fptr->writeconv, NULL, NULL, &dp, de, 0);
4616 while (dp-ds) {
4617 retry:
4618 if (fptr->write_lock && rb_mutex_owned_p(fptr->write_lock))
4619 r = rb_write_internal2(fptr->fd, ds, dp-ds);
4620 else
4621 r = rb_write_internal(fptr->fd, ds, dp-ds);
4622 if (r == dp-ds)
4623 break;
4624 if (0 <= r) {
4625 ds += r;
4626 }
4627 if (rb_io_wait_writable(fptr->fd)) {
4628 if (fptr->fd < 0)
4629 return noalloc ? Qtrue : rb_exc_new3(rb_eIOError, rb_str_new_cstr(closed_stream));
4630 goto retry;
4631 }
4632 return noalloc ? Qtrue : INT2NUM(errno);
4633 }
4634 if (res == econv_invalid_byte_sequence ||
4635 res == econv_incomplete_input ||
4636 res == econv_undefined_conversion) {
4637 return noalloc ? Qtrue : rb_econv_make_exception(fptr->writeconv);
4638 }
4639 }
4640
4641 return Qnil;
4642 }
4643
4644 res = econv_destination_buffer_full;
4645 while (res == econv_destination_buffer_full) {
4646 if (fptr->wbuf.len == fptr->wbuf.capa) {
4647 if (io_fflush(fptr) < 0)
4648 return noalloc ? Qtrue : INT2NUM(errno);
4649 }
4650
4651 ds = dp = (unsigned char *)fptr->wbuf.ptr + fptr->wbuf.off + fptr->wbuf.len;
4652 de = (unsigned char *)fptr->wbuf.ptr + fptr->wbuf.capa;
4653 res = rb_econv_convert(fptr->writeconv, NULL, NULL, &dp, de, 0);
4654 fptr->wbuf.len += (int)(dp - ds);
4655 if (res == econv_invalid_byte_sequence ||
4656 res == econv_incomplete_input ||
4657 res == econv_undefined_conversion) {
4658 return noalloc ? Qtrue : rb_econv_make_exception(fptr->writeconv);
4659 }
4660 }
4661 return Qnil;
4662}
4663
4664 struct finish_writeconv_arg {
4665 rb_io_t *fptr;
4666 int noalloc;
4667};
4668
4669static VALUE
4670finish_writeconv_sync(VALUE arg)
4671{
4672 struct finish_writeconv_arg *p = (struct finish_writeconv_arg *)arg;
4673 return finish_writeconv(p->fptr, p->noalloc);
4674}
4675
4676static void*
4677nogvl_close(void *ptr)
4678{
4679 int *fd = ptr;
4680
4681 return (void*)(intptr_t)close(*fd);
4682}
4683
4684static int
4685maygvl_close(int fd, int keepgvl)
4686{
4687 if (keepgvl)
4688 return close(fd);
4689
4690 /*
4691 * close() may block for certain file types (NFS, SO_LINGER sockets,
4692 * inotify), so let other threads run.
4693 */
4694 return (int)(intptr_t)rb_thread_call_without_gvl(nogvl_close, &fd, RUBY_UBF_IO, 0);
4695}
4696
4697static void*
4698nogvl_fclose(void *ptr)
4699{
4700 FILE *file = ptr;
4701
4702 return (void*)(intptr_t)fclose(file);
4703}
4704
4705static int
4706maygvl_fclose(FILE *file, int keepgvl)
4707{
4708 if (keepgvl)
4709 return fclose(file);
4710
4711 return (int)(intptr_t)rb_thread_call_without_gvl(nogvl_fclose, file, RUBY_UBF_IO, 0);
4712}
4713
4714static void free_io_buffer(rb_io_buffer_t *buf);
4715static void clear_codeconv(rb_io_t *fptr);
4716
4717static void
4718fptr_finalize_flush(rb_io_t *fptr, int noraise, int keepgvl,
4719 struct list_head *busy)
4720{
4721 VALUE err = Qnil;
4722 int fd = fptr->fd;
4723 FILE *stdio_file = fptr->stdio_file;
4724 int mode = fptr->mode;
4725
4726 if (fptr->writeconv) {
4727 if (fptr->write_lock && !noraise) {
4728 struct finish_writeconv_arg arg;
4729 arg.fptr = fptr;
4730 arg.noalloc = noraise;
4731 err = rb_mutex_synchronize(fptr->write_lock, finish_writeconv_sync, (VALUE)&arg);
4732 }
4733 else {
4734 err = finish_writeconv(fptr, noraise);
4735 }
4736 }
4737 if (fptr->wbuf.len) {
4738 if (noraise) {
4739 io_flush_buffer_sync(fptr);
4740 }
4741 else {
4742 if (io_fflush(fptr) < 0 && NIL_P(err))
4743 err = INT2NUM(errno);
4744 }
4745 }
4746
4747 fptr->fd = -1;
4748 fptr->stdio_file = 0;
4749 fptr->mode &= ~(FMODE_READABLE|FMODE_WRITABLE);
4750
4751 /*
4752 * ensure waiting_fd users do not hit EBADF, wait for them
4753 * to exit before we call close().
4754 */
4755 if (busy) {
4756 do rb_thread_schedule(); while (!list_empty(busy));
4757 }
4758
4759 if (IS_PREP_STDIO(fptr) || fd <= 2) {
4760 /* need to keep FILE objects of stdin, stdout and stderr */
4761 }
4762 else if (stdio_file) {
4763 /* stdio_file is deallocated anyway
4764 * even if fclose failed. */
4765 if ((maygvl_fclose(stdio_file, noraise) < 0) && NIL_P(err))
4766 if (!noraise) err = INT2NUM(errno);
4767 }
4768 else if (0 <= fd) {
4769 /* fptr->fd may be closed even if close fails.
4770 * POSIX doesn't specify it.
4771 * We assumes it is closed. */
4772
4773
4774 keepgvl |= !(mode & FMODE_WRITABLE);
4775 keepgvl |= noraise;
4776 if ((maygvl_close(fd, keepgvl) < 0) && NIL_P(err))
4777 if (!noraise) err = INT2NUM(errno);
4778 }
4779
4780 if (!NIL_P(err) && !noraise) {
4781 if (RB_INTEGER_TYPE_P(err))
4782 rb_syserr_fail_path(NUM2INT(err), fptr->pathv);
4783 else
4784 rb_exc_raise(err);
4785 }
4786}
4787
4788static void
4789fptr_finalize(rb_io_t *fptr, int noraise)
4790{
4791 fptr_finalize_flush(fptr, noraise, FALSE, 0);
4792 free_io_buffer(&fptr->rbuf);
4793 free_io_buffer(&fptr->wbuf);
4794 clear_codeconv(fptr);
4795}
4796
4797static void
4798rb_io_fptr_cleanup(rb_io_t *fptr, int noraise)
4799{
4800 if (fptr->finalize) {
4801 (*fptr->finalize)(fptr, noraise);
4802 }
4803 else {
4804 fptr_finalize(fptr, noraise);
4805 }
4806}
4807
4808static void
4809free_io_buffer(rb_io_buffer_t *buf)
4810{
4811 if (buf->ptr) {
4812 ruby_sized_xfree(buf->ptr, (size_t)buf->capa);
4813 buf->ptr = NULL;
4814 }
4815}
4816
4817static void
4818clear_readconv(rb_io_t *fptr)
4819{
4820 if (fptr->readconv) {
4821 rb_econv_close(fptr->readconv);
4822 fptr->readconv = NULL;
4823 }
4824 free_io_buffer(&fptr->cbuf);
4825}
4826
4827static void
4828clear_writeconv(rb_io_t *fptr)
4829{
4830 if (fptr->writeconv) {
4831 rb_econv_close(fptr->writeconv);
4832 fptr->writeconv = NULL;
4833 }
4834 fptr->writeconv_initialized = 0;
4835}
4836
4837static void
4838clear_codeconv(rb_io_t *fptr)
4839{
4840 clear_readconv(fptr);
4841 clear_writeconv(fptr);
4842}
4843
4844void
4845 rb_io_fptr_finalize_internal(void *ptr)
4846{
4847 rb_io_t *fptr = ptr;
4848
4849 if (!ptr) return;
4850 fptr->pathv = Qnil;
4851 if (0 <= fptr->fd)
4852 rb_io_fptr_cleanup(fptr, TRUE);
4853 fptr->write_lock = 0;
4854 free_io_buffer(&fptr->rbuf);
4855 free_io_buffer(&fptr->wbuf);
4856 clear_codeconv(fptr);
4857 free(fptr);
4858}
4859
4860#undef rb_io_fptr_finalize
4861int
4862 rb_io_fptr_finalize(rb_io_t *fptr)
4863{
4864 if (!fptr) {
4865 return 0;
4866 }
4867 else {
4868 rb_io_fptr_finalize_internal(fptr);
4869 return 1;
4870 }
4871}
4872#define rb_io_fptr_finalize(fptr) rb_io_fptr_finalize_internal(fptr)
4873
4874RUBY_FUNC_EXPORTED size_t
4875 rb_io_memsize(const rb_io_t *fptr)
4876{
4877 size_t size = sizeof(rb_io_t);
4878 size += fptr->rbuf.capa;
4879 size += fptr->wbuf.capa;
4880 size += fptr->cbuf.capa;
4881 if (fptr->readconv) size += rb_econv_memsize(fptr->readconv);
4882 if (fptr->writeconv) size += rb_econv_memsize(fptr->writeconv);
4883 return size;
4884}
4885
4886#ifdef _WIN32
4887/* keep GVL while closing to prevent crash on Windows */
4888# define KEEPGVL TRUE
4889#else
4890# define KEEPGVL FALSE
4891#endif
4892
4893int rb_notify_fd_close(int fd, struct list_head *);
4894static rb_io_t *
4895io_close_fptr(VALUE io)
4896{
4897 rb_io_t *fptr;
4898 VALUE write_io;
4899 rb_io_t *write_fptr;
4900 struct list_head busy;
4901
4902 list_head_init(&busy);
4903 write_io = GetWriteIO(io);
4904 if (io != write_io) {
4905 write_fptr = RFILE(write_io)->fptr;
4906 if (write_fptr && 0 <= write_fptr->fd) {
4907 rb_io_fptr_cleanup(write_fptr, TRUE);
4908 }
4909 }
4910
4911 fptr = RFILE(io)->fptr;
4912 if (!fptr) return 0;
4913 if (fptr->fd < 0) return 0;
4914
4915 if (rb_notify_fd_close(fptr->fd, &busy)) {
4916 /* calls close(fptr->fd): */
4917 fptr_finalize_flush(fptr, FALSE, KEEPGVL, &busy);
4918 }
4919 rb_io_fptr_cleanup(fptr, FALSE);
4920 return fptr;
4921}
4922
4923static void
4924fptr_waitpid(rb_io_t *fptr, int nohang)
4925{
4926 int status;
4927 if (fptr->pid) {
4928 rb_last_status_clear();
4929 rb_waitpid(fptr->pid, &status, nohang ? WNOHANG : 0);
4930 fptr->pid = 0;
4931 }
4932}
4933
4934 VALUE
4935 rb_io_close(VALUE io)
4936{
4937 rb_io_t *fptr = io_close_fptr(io);
4938 if (fptr) fptr_waitpid(fptr, 0);
4939 return Qnil;
4940}
4941
4942/*
4943 * call-seq:
4944 * ios.close -> nil
4945 *
4946 * Closes <em>ios</em> and flushes any pending writes to the operating
4947 * system. The stream is unavailable for any further data operations;
4948 * an IOError is raised if such an attempt is made. I/O streams are
4949 * automatically closed when they are claimed by the garbage collector.
4950 *
4951 * If <em>ios</em> is opened by IO.popen, #close sets
4952 * <code>$?</code>.
4953 *
4954 * Calling this method on closed IO object is just ignored since Ruby 2.3.
4955 */
4956
4957static VALUE
4958rb_io_close_m(VALUE io)
4959{
4960 rb_io_t *fptr = rb_io_get_fptr(io);
4961 if (fptr->fd < 0) {
4962 return Qnil;
4963 }
4964 rb_io_close(io);
4965 return Qnil;
4966}
4967
4968static VALUE
4969io_call_close(VALUE io)
4970{
4971 rb_check_funcall(io, rb_intern("close"), 0, 0);
4972 return io;
4973}
4974
4975static VALUE
4976ignore_closed_stream(VALUE io, VALUE exc)
4977{
4978 enum {mesg_len = sizeof(closed_stream)-1};
4979 VALUE mesg = rb_attr_get(exc, idMesg);
4980 if (!RB_TYPE_P(mesg, T_STRING) ||
4981 RSTRING_LEN(mesg) != mesg_len ||
4982 memcmp(RSTRING_PTR(mesg), closed_stream, mesg_len)) {
4983 rb_exc_raise(exc);
4984 }
4985 return io;
4986}
4987
4988static VALUE
4989io_close(VALUE io)
4990{
4991 VALUE closed = rb_check_funcall(io, rb_intern("closed?"), 0, 0);
4992 if (closed != Qundef && RTEST(closed)) return io;
4993 rb_rescue2(io_call_close, io, ignore_closed_stream, io,
4994 rb_eIOError, (VALUE)0);
4995 return io;
4996}
4997
4998/*
4999 * call-seq:
5000 * ios.closed? -> true or false
5001 *
5002 * Returns <code>true</code> if <em>ios</em> is completely closed (for
5003 * duplex streams, both reader and writer), <code>false</code>
5004 * otherwise.
5005 *
5006 * f = File.new("testfile")
5007 * f.close #=> nil
5008 * f.closed? #=> true
5009 * f = IO.popen("/bin/sh","r+")
5010 * f.close_write #=> nil
5011 * f.closed? #=> false
5012 * f.close_read #=> nil
5013 * f.closed? #=> true
5014 */
5015
5016
5017static VALUE
5018rb_io_closed(VALUE io)
5019{
5020 rb_io_t *fptr;
5021 VALUE write_io;
5022 rb_io_t *write_fptr;
5023
5024 write_io = GetWriteIO(io);
5025 if (io != write_io) {
5026 write_fptr = RFILE(write_io)->fptr;
5027 if (write_fptr && 0 <= write_fptr->fd) {
5028 return Qfalse;
5029 }
5030 }
5031
5032 fptr = rb_io_get_fptr(io);
5033 return 0 <= fptr->fd ? Qfalse : Qtrue;
5034}
5035
5036/*
5037 * call-seq:
5038 * ios.close_read -> nil
5039 *
5040 * Closes the read end of a duplex I/O stream (i.e., one that contains
5041 * both a read and a write stream, such as a pipe). Will raise an
5042 * IOError if the stream is not duplexed.
5043 *
5044 * f = IO.popen("/bin/sh","r+")
5045 * f.close_read
5046 * f.readlines
5047 *
5048 * <em>produces:</em>
5049 *
5050 * prog.rb:3:in `readlines': not opened for reading (IOError)
5051 * from prog.rb:3
5052 *
5053 * Calling this method on closed IO object is just ignored since Ruby 2.3.
5054 */
5055
5056static VALUE
5057rb_io_close_read(VALUE io)
5058{
5059 rb_io_t *fptr;
5060 VALUE write_io;
5061
5062 fptr = rb_io_get_fptr(rb_io_taint_check(io));
5063 if (fptr->fd < 0) return Qnil;
5064 if (is_socket(fptr->fd, fptr->pathv)) {
5065#ifndef SHUT_RD
5066# define SHUT_RD 0
5067#endif
5068 if (shutdown(fptr->fd, SHUT_RD) < 0)
5069 rb_sys_fail_path(fptr->pathv);
5070 fptr->mode &= ~FMODE_READABLE;
5071 if (!(fptr->mode & FMODE_WRITABLE))
5072 return rb_io_close(io);
5073 return Qnil;
5074 }
5075
5076 write_io = GetWriteIO(io);
5077 if (io != write_io) {
5078 rb_io_t *wfptr;
5079 wfptr = rb_io_get_fptr(rb_io_taint_check(write_io));
5080 wfptr->pid = fptr->pid;
5081 fptr->pid = 0;
5082 RFILE(io)->fptr = wfptr;
5083 /* bind to write_io temporarily to get rid of memory/fd leak */
5084 fptr->tied_io_for_writing = 0;
5085 RFILE(write_io)->fptr = fptr;
5086 rb_io_fptr_cleanup(fptr, FALSE);
5087 /* should not finalize fptr because another thread may be reading it */
5088 return Qnil;
5089 }
5090
5091 if ((fptr->mode & (FMODE_DUPLEX|FMODE_WRITABLE)) == FMODE_WRITABLE) {
5092 rb_raise(rb_eIOError, "closing non-duplex IO for reading");
5093 }
5094 return rb_io_close(io);
5095}
5096
5097/*
5098 * call-seq:
5099 * ios.close_write -> nil
5100 *
5101 * Closes the write end of a duplex I/O stream (i.e., one that contains
5102 * both a read and a write stream, such as a pipe). Will raise an
5103 * IOError if the stream is not duplexed.
5104 *
5105 * f = IO.popen("/bin/sh","r+")
5106 * f.close_write
5107 * f.print "nowhere"
5108 *
5109 * <em>produces:</em>
5110 *
5111 * prog.rb:3:in `write': not opened for writing (IOError)
5112 * from prog.rb:3:in `print'
5113 * from prog.rb:3
5114 *
5115 * Calling this method on closed IO object is just ignored since Ruby 2.3.
5116 */
5117
5118static VALUE
5119rb_io_close_write(VALUE io)
5120{
5121 rb_io_t *fptr;
5122 VALUE write_io;
5123
5124 write_io = GetWriteIO(io);
5125 fptr = rb_io_get_fptr(rb_io_taint_check(write_io));
5126 if (fptr->fd < 0) return Qnil;
5127 if (is_socket(fptr->fd, fptr->pathv)) {
5128#ifndef SHUT_WR
5129# define SHUT_WR 1
5130#endif
5131 if (shutdown(fptr->fd, SHUT_WR) < 0)
5132 rb_sys_fail_path(fptr->pathv);
5133 fptr->mode &= ~FMODE_WRITABLE;
5134 if (!(fptr->mode & FMODE_READABLE))
5135 return rb_io_close(write_io);
5136 return Qnil;
5137 }
5138
5139 if ((fptr->mode & (FMODE_DUPLEX|FMODE_READABLE)) == FMODE_READABLE) {
5140 rb_raise(rb_eIOError, "closing non-duplex IO for writing");
5141 }
5142
5143 if (io != write_io) {
5144 fptr = rb_io_get_fptr(rb_io_taint_check(io));
5145 fptr->tied_io_for_writing = 0;
5146 }
5147 rb_io_close(write_io);
5148 return Qnil;
5149}
5150
5151/*
5152 * call-seq:
5153 * ios.sysseek(offset, whence=IO::SEEK_SET) -> integer
5154 *
5155 * Seeks to a given <i>offset</i> in the stream according to the value
5156 * of <i>whence</i> (see IO#seek for values of <i>whence</i>). Returns
5157 * the new offset into the file.
5158 *
5159 * f = File.new("testfile")
5160 * f.sysseek(-13, IO::SEEK_END) #=> 53
5161 * f.sysread(10) #=> "And so on."
5162 */
5163
5164static VALUE
5165rb_io_sysseek(int argc, VALUE *argv, VALUE io)
5166{
5167 VALUE offset, ptrname;
5168 int whence = SEEK_SET;
5169 rb_io_t *fptr;
5170 off_t pos;
5171
5172 if (rb_scan_args(argc, argv, "11", &offset, &ptrname) == 2) {
5173 whence = interpret_seek_whence(ptrname);
5174 }
5175 pos = NUM2OFFT(offset);
5176 GetOpenFile(io, fptr);
5177 if ((fptr->mode & FMODE_READABLE) &&
5178 (READ_DATA_BUFFERED(fptr) || READ_CHAR_PENDING(fptr))) {
5179 rb_raise(rb_eIOError, "sysseek for buffered IO");
5180 }
5181 if ((fptr->mode & FMODE_WRITABLE) && fptr->wbuf.len) {
5182 rb_warn("sysseek for buffered IO");
5183 }
5184 errno = 0;
5185 pos = lseek(fptr->fd, pos, whence);
5186 if (pos < 0 && errno) rb_sys_fail_path(fptr->pathv);
5187
5188 return OFFT2NUM(pos);
5189}
5190
5191/*
5192 * call-seq:
5193 * ios.syswrite(string) -> integer
5194 *
5195 * Writes the given string to <em>ios</em> using a low-level write.
5196 * Returns the number of bytes written. Do not mix with other methods
5197 * that write to <em>ios</em> or you may get unpredictable results.
5198 * Raises SystemCallError on error.
5199 *
5200 * f = File.new("out", "w")
5201 * f.syswrite("ABCDEF") #=> 6
5202 */
5203
5204static VALUE
5205rb_io_syswrite(VALUE io, VALUE str)
5206{
5207 VALUE tmp;
5208 rb_io_t *fptr;
5209 long n, len;
5210 const char *ptr;
5211
5212 if (!RB_TYPE_P(str, T_STRING))
5213 str = rb_obj_as_string(str);
5214
5215 io = GetWriteIO(io);
5216 GetOpenFile(io, fptr);
5217 rb_io_check_writable(fptr);
5218
5219 if (fptr->wbuf.len) {
5220 rb_warn("syswrite for buffered IO");
5221 }
5222
5223 tmp = rb_str_tmp_frozen_acquire(str);
5224 RSTRING_GETMEM(tmp, ptr, len);
5225 n = rb_write_internal(fptr->fd, ptr, len);
5226 if (n < 0) rb_sys_fail_path(fptr->pathv);
5227 rb_str_tmp_frozen_release(str, tmp);
5228
5229 return LONG2FIX(n);
5230}
5231
5232/*
5233 * call-seq:
5234 * ios.sysread(maxlen[, outbuf]) -> string
5235 *
5236 * Reads <i>maxlen</i> bytes from <em>ios</em> using a low-level
5237 * read and returns them as a string. Do not mix with other methods
5238 * that read from <em>ios</em> or you may get unpredictable results.
5239 *
5240 * If the optional _outbuf_ argument is present,
5241 * it must reference a String, which will receive the data.
5242 * The _outbuf_ will contain only the received data after the method call
5243 * even if it is not empty at the beginning.
5244 *
5245 * Raises SystemCallError on error and EOFError at end of file.
5246 *
5247 * f = File.new("testfile")
5248 * f.sysread(16) #=> "This is line one"
5249 */
5250
5251static VALUE
5252rb_io_sysread(int argc, VALUE *argv, VALUE io)
5253{
5254 VALUE len, str;
5255 rb_io_t *fptr;
5256 long n, ilen;
5257 struct io_internal_read_struct iis;
5258 int shrinkable;
5259
5260 rb_scan_args(argc, argv, "11", &len, &str);
5261 ilen = NUM2LONG(len);
5262
5263 shrinkable = io_setstrbuf(&str, ilen);
5264 if (ilen == 0) return str;
5265
5266 GetOpenFile(io, fptr);
5267 rb_io_check_byte_readable(fptr);
5268
5269 if (READ_DATA_BUFFERED(fptr)) {
5270 rb_raise(rb_eIOError, "sysread for buffered IO");
5271 }
5272
5273 /*
5274 * FIXME: removing rb_thread_wait_fd() here changes sysread semantics
5275 * on non-blocking IOs. However, it's still currently possible
5276 * for sysread to raise Errno::EAGAIN if another thread read()s
5277 * the IO after we return from rb_thread_wait_fd() but before
5278 * we call read()
5279 */
5280 rb_thread_wait_fd(fptr->fd);
5281
5282 rb_io_check_closed(fptr);
5283
5284 io_setstrbuf(&str, ilen);
5285 iis.fd = fptr->fd;
5286 iis.nonblock = 1; /* for historical reasons, maybe (see above) */
5287 iis.buf = RSTRING_PTR(str);
5288 iis.capa = ilen;
5289 n = read_internal_locktmp(str, &iis);
5290
5291 if (n < 0) {
5292 rb_sys_fail_path(fptr->pathv);
5293 }
5294 io_set_read_length(str, n, shrinkable);
5295 if (n == 0 && ilen > 0) {
5296 rb_eof_error();
5297 }
5298
5299 return str;
5300}
5301
5302#if defined(HAVE_PREAD) || defined(HAVE_PWRITE)
5303struct prdwr_internal_arg {
5304 int fd;
5305 void *buf;
5306 size_t count;
5307 off_t offset;
5308};
5309#endif /* HAVE_PREAD || HAVE_PWRITE */
5310
5311#if defined(HAVE_PREAD)
5312static VALUE
5313internal_pread_func(void *arg)
5314{
5315 struct prdwr_internal_arg *p = arg;
5316 return (VALUE)pread(p->fd, p->buf, p->count, p->offset);
5317}
5318
5319static VALUE
5320pread_internal_call(VALUE arg)
5321{
5322 struct prdwr_internal_arg *p = (struct prdwr_internal_arg *)arg;
5323 return rb_thread_io_blocking_region(internal_pread_func, p, p->fd);
5324}
5325
5326/*
5327 * call-seq:
5328 * ios.pread(maxlen, offset[, outbuf]) -> string
5329 *
5330 * Reads <i>maxlen</i> bytes from <em>ios</em> using the pread system call
5331 * and returns them as a string without modifying the underlying
5332 * descriptor offset. This is advantageous compared to combining IO#seek
5333 * and IO#read in that it is atomic, allowing multiple threads/process to
5334 * share the same IO object for reading the file at various locations.
5335 * This bypasses any userspace buffering of the IO layer.
5336 * If the optional <i>outbuf</i> argument is present, it must
5337 * reference a String, which will receive the data.
5338 * Raises SystemCallError on error, EOFError at end of file and
5339 * NotImplementedError if platform does not implement the system call.
5340 *
5341 * File.write("testfile", "This is line one\nThis is line two\n")
5342 * File.open("testfile") do |f|
5343 * p f.read # => "This is line one\nThis is line two\n"
5344 * p f.pread(12, 0) # => "This is line"
5345 * p f.pread(9, 8) # => "line one\n"
5346 * end
5347 */
5348static VALUE
5349 rb_io_pread(int argc, VALUE *argv, VALUE io)
5350{
5351 VALUE len, offset, str;
5352 rb_io_t *fptr;
5353 ssize_t n;
5354 struct prdwr_internal_arg arg;
5355 int shrinkable;
5356
5357 rb_scan_args(argc, argv, "21", &len, &offset, &str);
5358 arg.count = NUM2SIZET(len);
5359 arg.offset = NUM2OFFT(offset);
5360
5361 shrinkable = io_setstrbuf(&str, (long)arg.count);
5362 if (arg.count == 0) return str;
5363 arg.buf = RSTRING_PTR(str);
5364
5365 GetOpenFile(io, fptr);
5366 rb_io_check_byte_readable(fptr);
5367
5368 arg.fd = fptr->fd;
5369 rb_io_check_closed(fptr);
5370
5371 rb_str_locktmp(str);
5372 n = (ssize_t)rb_ensure(pread_internal_call, (VALUE)&arg, rb_str_unlocktmp, str);
5373
5374 if (n < 0) {
5375 rb_sys_fail_path(fptr->pathv);
5376 }
5377 io_set_read_length(str, n, shrinkable);
5378 if (n == 0 && arg.count > 0) {
5379 rb_eof_error();
5380 }
5381
5382 return str;
5383}
5384#else
5385# define rb_io_pread rb_f_notimplement
5386#endif /* HAVE_PREAD */
5387
5388#if defined(HAVE_PWRITE)
5389static VALUE
5390internal_pwrite_func(void *ptr)
5391{
5392 struct prdwr_internal_arg *arg = ptr;
5393
5394 return (VALUE)pwrite(arg->fd, arg->buf, arg->count, arg->offset);
5395}
5396
5397/*
5398 * call-seq:
5399 * ios.pwrite(string, offset) -> integer
5400 *
5401 * Writes the given string to <em>ios</em> at <i>offset</i> using pwrite()
5402 * system call. This is advantageous to combining IO#seek and IO#write
5403 * in that it is atomic, allowing multiple threads/process to share the
5404 * same IO object for reading the file at various locations.
5405 * This bypasses any userspace buffering of the IO layer.
5406 * Returns the number of bytes written.
5407 * Raises SystemCallError on error and NotImplementedError
5408 * if platform does not implement the system call.
5409 *
5410 * File.open("out", "w") do |f|
5411 * f.pwrite("ABCDEF", 3) #=> 6
5412 * end
5413 *
5414 * File.read("out") #=> "\u0000\u0000\u0000ABCDEF"
5415 */
5416static VALUE
5417 rb_io_pwrite(VALUE io, VALUE str, VALUE offset)
5418{
5419 rb_io_t *fptr;
5420 ssize_t n;
5421 struct prdwr_internal_arg arg;
5422 VALUE tmp;
5423
5424 if (!RB_TYPE_P(str, T_STRING))
5425 str = rb_obj_as_string(str);
5426
5427 arg.offset = NUM2OFFT(offset);
5428
5429 io = GetWriteIO(io);
5430 GetOpenFile(io, fptr);
5431 rb_io_check_writable(fptr);
5432 arg.fd = fptr->fd;
5433
5434 tmp = rb_str_tmp_frozen_acquire(str);
5435 arg.buf = RSTRING_PTR(tmp);
5436 arg.count = (size_t)RSTRING_LEN(tmp);
5437
5438 n = (ssize_t)rb_thread_io_blocking_region(internal_pwrite_func, &arg, fptr->fd);
5439 if (n < 0) rb_sys_fail_path(fptr->pathv);
5440 rb_str_tmp_frozen_release(str, tmp);
5441
5442 return SSIZET2NUM(n);
5443}
5444#else
5445# define rb_io_pwrite rb_f_notimplement
5446#endif /* HAVE_PWRITE */
5447
5448 VALUE
5449 rb_io_binmode(VALUE io)
5450{
5451 rb_io_t *fptr;
5452
5453 GetOpenFile(io, fptr);
5454 if (fptr->readconv)
5455 rb_econv_binmode(fptr->readconv);
5456 if (fptr->writeconv)
5457 rb_econv_binmode(fptr->writeconv);
5458 fptr->mode |= FMODE_BINMODE;
5459 fptr->mode &= ~FMODE_TEXTMODE;
5460 fptr->writeconv_pre_ecflags &= ~ECONV_NEWLINE_DECORATOR_MASK;
5461#ifdef O_BINARY
5462 if (!fptr->readconv) {
5463 SET_BINARY_MODE_WITH_SEEK_CUR(fptr);
5464 }
5465 else {
5466 setmode(fptr->fd, O_BINARY);
5467 }
5468#endif
5469 return io;
5470}
5471
5472static void
5473io_ascii8bit_binmode(rb_io_t *fptr)
5474{
5475 if (fptr->readconv) {
5476 rb_econv_close(fptr->readconv);
5477 fptr->readconv = NULL;
5478 }
5479 if (fptr->writeconv) {
5480 rb_econv_close(fptr->writeconv);
5481 fptr->writeconv = NULL;
5482 }
5483 fptr->mode |= FMODE_BINMODE;
5484 fptr->mode &= ~FMODE_TEXTMODE;
5485 SET_BINARY_MODE_WITH_SEEK_CUR(fptr);
5486
5487 fptr->encs.enc = rb_ascii8bit_encoding();
5488 fptr->encs.enc2 = NULL;
5489 fptr->encs.ecflags = 0;
5490 fptr->encs.ecopts = Qnil;
5491 clear_codeconv(fptr);
5492}
5493
5494 VALUE
5495 rb_io_ascii8bit_binmode(VALUE io)
5496{
5497 rb_io_t *fptr;
5498
5499 GetOpenFile(io, fptr);
5500 io_ascii8bit_binmode(fptr);
5501
5502 return io;
5503}
5504
5505/*
5506 * call-seq:
5507 * ios.binmode -> ios
5508 *
5509 * Puts <em>ios</em> into binary mode.
5510 * Once a stream is in binary mode, it cannot be reset to nonbinary mode.
5511 *
5512 * - newline conversion disabled
5513 * - encoding conversion disabled
5514 * - content is treated as ASCII-8BIT
5515 */
5516
5517static VALUE
5518rb_io_binmode_m(VALUE io)
5519{
5520 VALUE write_io;
5521
5522 rb_io_ascii8bit_binmode(io);
5523
5524 write_io = GetWriteIO(io);
5525 if (write_io != io)
5526 rb_io_ascii8bit_binmode(write_io);
5527 return io;
5528}
5529
5530/*
5531 * call-seq:
5532 * ios.binmode? -> true or false
5533 *
5534 * Returns <code>true</code> if <em>ios</em> is binmode.
5535 */
5536static VALUE
5537rb_io_binmode_p(VALUE io)
5538{
5539 rb_io_t *fptr;
5540 GetOpenFile(io, fptr);
5541 return fptr->mode & FMODE_BINMODE ? Qtrue : Qfalse;
5542}
5543
5544static const char*
5545rb_io_fmode_modestr(int fmode)
5546{
5547 if (fmode & FMODE_APPEND) {
5548 if ((fmode & FMODE_READWRITE) == FMODE_READWRITE) {
5549 return MODE_BTMODE("a+", "ab+", "at+");
5550 }
5551 return MODE_BTMODE("a", "ab", "at");
5552 }
5553 switch (fmode & FMODE_READWRITE) {
5554 default:
5555 rb_raise(rb_eArgError, "invalid access fmode 0x%x", fmode);
5556 case FMODE_READABLE:
5557 return MODE_BTMODE("r", "rb", "rt");
5558 case FMODE_WRITABLE:
5559 return MODE_BTXMODE("w", "wb", "wt", "wx", "wbx", "wtx");
5560 case FMODE_READWRITE:
5561 if (fmode & FMODE_CREATE) {
5562 return MODE_BTXMODE("w+", "wb+", "wt+", "w+x", "wb+x", "wt+x");
5563 }
5564 return MODE_BTMODE("r+", "rb+", "rt+");
5565 }
5566}
5567
5568static const char bom_prefix[] = "bom|";
5569static const char utf_prefix[] = "utf-";
5570 enum {bom_prefix_len = (int)sizeof(bom_prefix) - 1};
5571 enum {utf_prefix_len = (int)sizeof(utf_prefix) - 1};
5572
5573static int
5574io_encname_bom_p(const char *name, long len)
5575{
5576 return len > bom_prefix_len && STRNCASECMP(name, bom_prefix, bom_prefix_len) == 0;
5577}
5578
5579int
5580 rb_io_modestr_fmode(const char *modestr)
5581{
5582 int fmode = 0;
5583 const char *m = modestr, *p = NULL;
5584
5585 switch (*m++) {
5586 case 'r':
5587 fmode |= FMODE_READABLE;
5588 break;
5589 case 'w':
5590 fmode |= FMODE_WRITABLE | FMODE_TRUNC | FMODE_CREATE;
5591 break;
5592 case 'a':
5593 fmode |= FMODE_WRITABLE | FMODE_APPEND | FMODE_CREATE;
5594 break;
5595 default:
5596 goto error;
5597 }
5598
5599 while (*m) {
5600 switch (*m++) {
5601 case 'b':
5602 fmode |= FMODE_BINMODE;
5603 break;
5604 case 't':
5605 fmode |= FMODE_TEXTMODE;
5606 break;
5607 case '+':
5608 fmode |= FMODE_READWRITE;
5609 break;
5610 case 'x':
5611 if (modestr[0] != 'w')
5612 goto error;
5613 fmode |= FMODE_EXCL;
5614 break;
5615 default:
5616 goto error;
5617 case ':':
5618 p = strchr(m, ':');
5619 if (io_encname_bom_p(m, p ? (long)(p - m) : (long)strlen(m)))
5620 fmode |= FMODE_SETENC_BY_BOM;
5621 goto finished;
5622 }
5623 }
5624
5625 finished:
5626 if ((fmode & FMODE_BINMODE) && (fmode & FMODE_TEXTMODE))
5627 goto error;
5628
5629 return fmode;
5630
5631 error:
5632 rb_raise(rb_eArgError, "invalid access mode %s", modestr);
5633 UNREACHABLE_RETURN(Qundef);
5634}
5635
5636int
5637 rb_io_oflags_fmode(int oflags)
5638{
5639 int fmode = 0;
5640
5641 switch (oflags & O_ACCMODE) {
5642 case O_RDONLY:
5643 fmode = FMODE_READABLE;
5644 break;
5645 case O_WRONLY:
5646 fmode = FMODE_WRITABLE;
5647 break;
5648 case O_RDWR:
5649 fmode = FMODE_READWRITE;
5650 break;
5651 }
5652
5653 if (oflags & O_APPEND) {
5654 fmode |= FMODE_APPEND;
5655 }
5656 if (oflags & O_TRUNC) {
5657 fmode |= FMODE_TRUNC;
5658 }
5659 if (oflags & O_CREAT) {
5660 fmode |= FMODE_CREATE;
5661 }
5662 if (oflags & O_EXCL) {
5663 fmode |= FMODE_EXCL;
5664 }
5665#ifdef O_BINARY
5666 if (oflags & O_BINARY) {
5667 fmode |= FMODE_BINMODE;
5668 }
5669#endif
5670
5671 return fmode;
5672}
5673
5674static int
5675rb_io_fmode_oflags(int fmode)
5676{
5677 int oflags = 0;
5678
5679 switch (fmode & FMODE_READWRITE) {
5680 case FMODE_READABLE:
5681 oflags |= O_RDONLY;
5682 break;
5683 case FMODE_WRITABLE:
5684 oflags |= O_WRONLY;
5685 break;
5686 case FMODE_READWRITE:
5687 oflags |= O_RDWR;
5688 break;
5689 }
5690
5691 if (fmode & FMODE_APPEND) {
5692 oflags |= O_APPEND;
5693 }
5694 if (fmode & FMODE_TRUNC) {
5695 oflags |= O_TRUNC;
5696 }
5697 if (fmode & FMODE_CREATE) {
5698 oflags |= O_CREAT;
5699 }
5700 if (fmode & FMODE_EXCL) {
5701 oflags |= O_EXCL;
5702 }
5703#ifdef O_BINARY
5704 if (fmode & FMODE_BINMODE) {
5705 oflags |= O_BINARY;
5706 }
5707#endif
5708
5709 return oflags;
5710}
5711
5712int
5713 rb_io_modestr_oflags(const char *modestr)
5714{
5715 return rb_io_fmode_oflags(rb_io_modestr_fmode(modestr));
5716}
5717
5718static const char*
5719rb_io_oflags_modestr(int oflags)
5720{
5721#ifdef O_BINARY
5722# define MODE_BINARY(a,b) ((oflags & O_BINARY) ? (b) : (a))
5723#else
5724# define MODE_BINARY(a,b) (a)
5725#endif
5726 int accmode;
5727 if (oflags & O_EXCL) {
5728 rb_raise(rb_eArgError, "exclusive access mode is not supported");
5729 }
5730 accmode = oflags & (O_RDONLY|O_WRONLY|O_RDWR);
5731 if (oflags & O_APPEND) {
5732 if (accmode == O_WRONLY) {
5733 return MODE_BINARY("a", "ab");
5734 }
5735 if (accmode == O_RDWR) {
5736 return MODE_BINARY("a+", "ab+");
5737 }
5738 }
5739 switch (accmode) {
5740 default:
5741 rb_raise(rb_eArgError, "invalid access oflags 0x%x", oflags);
5742 case O_RDONLY:
5743 return MODE_BINARY("r", "rb");
5744 case O_WRONLY:
5745 return MODE_BINARY("w", "wb");
5746 case O_RDWR:
5747 if (oflags & O_TRUNC) {
5748 return MODE_BINARY("w+", "wb+");
5749 }
5750 return MODE_BINARY("r+", "rb+");
5751 }
5752}
5753
5754/*
5755 * Convert external/internal encodings to enc/enc2
5756 * NULL => use default encoding
5757 * Qnil => no encoding specified (internal only)
5758 */
5759static void
5760rb_io_ext_int_to_encs(rb_encoding *ext, rb_encoding *intern, rb_encoding **enc, rb_encoding **enc2, int fmode)
5761{
5762 int default_ext = 0;
5763
5764 if (ext == NULL) {
5765 ext = rb_default_external_encoding();
5766 default_ext = 1;
5767 }
5768 if (ext == rb_ascii8bit_encoding()) {
5769 /* If external is ASCII-8BIT, no transcoding */
5770 intern = NULL;
5771 }
5772 else if (intern == NULL) {
5773 intern = rb_default_internal_encoding();
5774 }
5775 if (intern == NULL || intern == (rb_encoding *)Qnil ||
5776 (!(fmode & FMODE_SETENC_BY_BOM) && (intern == ext))) {
5777 /* No internal encoding => use external + no transcoding */
5778 *enc = (default_ext && intern != ext) ? NULL : ext;
5779 *enc2 = NULL;
5780 }
5781 else {
5782 *enc = intern;
5783 *enc2 = ext;
5784 }
5785}
5786
5787static void
5788unsupported_encoding(const char *name, rb_encoding *enc)
5789{
5790 rb_enc_warn(enc, "Unsupported encoding %s ignored", name);
5791}
5792
5793static void
5794parse_mode_enc(const char *estr, rb_encoding *estr_enc,
5795 rb_encoding **enc_p, rb_encoding **enc2_p, int *fmode_p)
5796{
5797 const char *p;
5798 char encname[ENCODING_MAXNAMELEN+1];
5799 int idx, idx2;
5800 int fmode = fmode_p ? *fmode_p : 0;
5801 rb_encoding *ext_enc, *int_enc;
5802 long len;
5803
5804 /* parse estr as "enc" or "enc2:enc" or "enc:-" */
5805
5806 p = strrchr(estr, ':');
5807 len = p ? (p++ - estr) : (long)strlen(estr);
5808 if ((fmode & FMODE_SETENC_BY_BOM) || io_encname_bom_p(estr, len)) {
5809 estr += bom_prefix_len;
5810 len -= bom_prefix_len;
5811 if (!STRNCASECMP(estr, utf_prefix, utf_prefix_len)) {
5812 fmode |= FMODE_SETENC_BY_BOM;
5813 }
5814 else {
5815 rb_enc_warn(estr_enc, "BOM with non-UTF encoding %s is nonsense", estr);
5816 fmode &= ~FMODE_SETENC_BY_BOM;
5817 }
5818 }
5819 if (len == 0 || len > ENCODING_MAXNAMELEN) {
5820 idx = -1;
5821 }
5822 else {
5823 if (p) {
5824 memcpy(encname, estr, len);
5825 encname[len] = '\0';
5826 estr = encname;
5827 }
5828 idx = rb_enc_find_index(estr);
5829 }
5830 if (fmode_p) *fmode_p = fmode;
5831
5832 if (idx >= 0)
5833 ext_enc = rb_enc_from_index(idx);
5834 else {
5835 if (idx != -2)
5836 unsupported_encoding(estr, estr_enc);
5837 ext_enc = NULL;
5838 }
5839
5840 int_enc = NULL;
5841 if (p) {
5842 if (*p == '-' && *(p+1) == '\0') {
5843 /* Special case - "-" => no transcoding */
5844 int_enc = (rb_encoding *)Qnil;
5845 }
5846 else {
5847 idx2 = rb_enc_find_index(p);
5848 if (idx2 < 0)
5849 unsupported_encoding(p, estr_enc);
5850 else if (!(fmode & FMODE_SETENC_BY_BOM) && (idx2 == idx)) {
5851 int_enc = (rb_encoding *)Qnil;
5852 }
5853 else
5854 int_enc = rb_enc_from_index(idx2);
5855 }
5856 }
5857
5858 rb_io_ext_int_to_encs(ext_enc, int_enc, enc_p, enc2_p, fmode);
5859}
5860
5861int
5862 rb_io_extract_encoding_option(VALUE opt, rb_encoding **enc_p, rb_encoding **enc2_p, int *fmode_p)
5863{
5864 VALUE encoding=Qnil, extenc=Qundef, intenc=Qundef, tmp;
5865 int extracted = 0;
5866 rb_encoding *extencoding = NULL;
5867 rb_encoding *intencoding = NULL;
5868
5869 if (!NIL_P(opt)) {
5870 VALUE v;
5871 v = rb_hash_lookup2(opt, sym_encoding, Qnil);
5872 if (v != Qnil) encoding = v;
5873 v = rb_hash_lookup2(opt, sym_extenc, Qundef);
5874 if (v != Qnil) extenc = v;
5875 v = rb_hash_lookup2(opt, sym_intenc, Qundef);
5876 if (v != Qundef) intenc = v;
5877 }
5878 if ((extenc != Qundef || intenc != Qundef) && !NIL_P(encoding)) {
5879 if (!NIL_P(ruby_verbose)) {
5880 int idx = rb_to_encoding_index(encoding);
5881 if (idx >= 0) encoding = rb_enc_from_encoding(rb_enc_from_index(idx));
5882 rb_warn("Ignoring encoding parameter '%"PRIsVALUE"': %s_encoding is used",
5883 encoding, extenc == Qundef ? "internal" : "external");
5884 }
5885 encoding = Qnil;
5886 }
5887 if (extenc != Qundef && !NIL_P(extenc)) {
5888 extencoding = rb_to_encoding(extenc);
5889 }
5890 if (intenc != Qundef) {
5891 if (NIL_P(intenc)) {
5892 /* internal_encoding: nil => no transcoding */
5893 intencoding = (rb_encoding *)Qnil;
5894 }
5895 else if (!NIL_P(tmp = rb_check_string_type(intenc))) {
5896 char *p = StringValueCStr(tmp);
5897
5898 if (*p == '-' && *(p+1) == '\0') {
5899 /* Special case - "-" => no transcoding */
5900 intencoding = (rb_encoding *)Qnil;
5901 }
5902 else {
5903 intencoding = rb_to_encoding(intenc);
5904 }
5905 }
5906 else {
5907 intencoding = rb_to_encoding(intenc);
5908 }
5909 if (extencoding == intencoding) {
5910 intencoding = (rb_encoding *)Qnil;
5911 }
5912 }
5913 if (!NIL_P(encoding)) {
5914 extracted = 1;
5915 if (!NIL_P(tmp = rb_check_string_type(encoding))) {
5916 parse_mode_enc(StringValueCStr(tmp), rb_enc_get(tmp),
5917 enc_p, enc2_p, fmode_p);
5918 }
5919 else {
5920 rb_io_ext_int_to_encs(rb_to_encoding(encoding), NULL, enc_p, enc2_p, 0);
5921 }
5922 }
5923 else if (extenc != Qundef || intenc != Qundef) {
5924 extracted = 1;
5925 rb_io_ext_int_to_encs(extencoding, intencoding, enc_p, enc2_p, 0);
5926 }
5927 return extracted;
5928}
5929
5930 typedef struct rb_io_enc_t convconfig_t;
5931
5932static void
5933validate_enc_binmode(int *fmode_p, int ecflags, rb_encoding *enc, rb_encoding *enc2)
5934{
5935 int fmode = *fmode_p;
5936
5937 if ((fmode & FMODE_READABLE) &&
5938 !enc2 &&
5939 !(fmode & FMODE_BINMODE) &&
5940 !rb_enc_asciicompat(enc ? enc : rb_default_external_encoding()))
5941 rb_raise(rb_eArgError, "ASCII incompatible encoding needs binmode");
5942
5943 if ((fmode & FMODE_BINMODE) && (ecflags & ECONV_NEWLINE_DECORATOR_MASK)) {
5944 rb_raise(rb_eArgError, "newline decorator with binary mode");
5945 }
5946 if (!(fmode & FMODE_BINMODE) &&
5947 (DEFAULT_TEXTMODE || (ecflags & ECONV_NEWLINE_DECORATOR_MASK))) {
5948 fmode |= FMODE_TEXTMODE;
5949 *fmode_p = fmode;
5950 }
5951#if !DEFAULT_TEXTMODE
5952 else if (!(ecflags & ECONV_NEWLINE_DECORATOR_MASK)) {
5953 fmode &= ~FMODE_TEXTMODE;
5954 *fmode_p = fmode;
5955 }
5956#endif
5957}
5958
5959static void
5960extract_binmode(VALUE opthash, int *fmode)
5961{
5962 if (!NIL_P(opthash)) {
5963 VALUE v;
5964 v = rb_hash_aref(opthash, sym_textmode);
5965 if (!NIL_P(v)) {
5966 if (*fmode & FMODE_TEXTMODE)
5967 rb_raise(rb_eArgError, "textmode specified twice");
5968 if (*fmode & FMODE_BINMODE)
5969 rb_raise(rb_eArgError, "both textmode and binmode specified");
5970 if (RTEST(v))
5971 *fmode |= FMODE_TEXTMODE;
5972 }
5973 v = rb_hash_aref(opthash, sym_binmode);
5974 if (!NIL_P(v)) {
5975 if (*fmode & FMODE_BINMODE)
5976 rb_raise(rb_eArgError, "binmode specified twice");
5977 if (*fmode & FMODE_TEXTMODE)
5978 rb_raise(rb_eArgError, "both textmode and binmode specified");
5979 if (RTEST(v))
5980 *fmode |= FMODE_BINMODE;
5981 }
5982
5983 if ((*fmode & FMODE_BINMODE) && (*fmode & FMODE_TEXTMODE))
5984 rb_raise(rb_eArgError, "both textmode and binmode specified");
5985 }
5986}
5987
5988void
5989 rb_io_extract_modeenc(VALUE *vmode_p, VALUE *vperm_p, VALUE opthash,
5990 int *oflags_p, int *fmode_p, convconfig_t *convconfig_p)
5991{
5992 VALUE vmode;
5993 int oflags, fmode;
5994 rb_encoding *enc, *enc2;
5995 int ecflags;
5996 VALUE ecopts;
5997 int has_enc = 0, has_vmode = 0;
5998 VALUE intmode;
5999
6000 vmode = *vmode_p;
6001
6002 /* Set to defaults */
6003 rb_io_ext_int_to_encs(NULL, NULL, &enc, &enc2, 0);
6004
6005 vmode_handle:
6006 if (NIL_P(vmode)) {
6007 fmode = FMODE_READABLE;
6008 oflags = O_RDONLY;
6009 }
6010 else if (!NIL_P(intmode = rb_check_to_integer(vmode, "to_int"))) {
6011 vmode = intmode;
6012 oflags = NUM2INT(intmode);
6013 fmode = rb_io_oflags_fmode(oflags);
6014 }
6015 else {
6016 const char *p;
6017
6018 SafeStringValue(vmode);
6019 p = StringValueCStr(vmode);
6020 fmode = rb_io_modestr_fmode(p);
6021 oflags = rb_io_fmode_oflags(fmode);
6022 p = strchr(p, ':');
6023 if (p) {
6024 has_enc = 1;
6025 parse_mode_enc(p+1, rb_enc_get(vmode), &enc, &enc2, &fmode);
6026 }
6027 else {
6028 rb_encoding *e;
6029
6030 e = (fmode & FMODE_BINMODE) ? rb_ascii8bit_encoding() : NULL;
6031 rb_io_ext_int_to_encs(e, NULL, &enc, &enc2, fmode);
6032 }
6033 }
6034
6035 if (NIL_P(opthash)) {
6036 ecflags = (fmode & FMODE_READABLE) ?
6037 MODE_BTMODE(ECONV_DEFAULT_NEWLINE_DECORATOR,
6038 0, ECONV_UNIVERSAL_NEWLINE_DECORATOR) : 0;
6039#ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
6040 ecflags |= (fmode & FMODE_WRITABLE) ?
6041 MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE,
6042 0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE) : 0;
6043#endif
6044 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
6045 ecopts = Qnil;
6046 if (fmode & FMODE_BINMODE) {
6047#ifdef O_BINARY
6048 oflags |= O_BINARY;
6049#endif
6050 if (!has_enc)
6051 rb_io_ext_int_to_encs(rb_ascii8bit_encoding(), NULL, &enc, &enc2, fmode);
6052 }
6053#if DEFAULT_TEXTMODE
6054 else if (NIL_P(vmode)) {
6055 fmode |= DEFAULT_TEXTMODE;
6056 }
6057#endif
6058 }
6059 else {
6060 VALUE v;
6061 if (!has_vmode) {
6062 v = rb_hash_aref(opthash, sym_mode);
6063 if (!NIL_P(v)) {
6064 if (!NIL_P(vmode)) {
6065 rb_raise(rb_eArgError, "mode specified twice");
6066 }
6067 has_vmode = 1;
6068 vmode = v;
6069 goto vmode_handle;
6070 }
6071 }
6072 v = rb_hash_aref(opthash, sym_flags);
6073 if (!NIL_P(v)) {
6074 v = rb_to_int(v);
6075 oflags |= NUM2INT(v);
6076 vmode = INT2NUM(oflags);
6077 fmode = rb_io_oflags_fmode(oflags);
6078 }
6079 extract_binmode(opthash, &fmode);
6080 if (fmode & FMODE_BINMODE) {
6081#ifdef O_BINARY
6082 oflags |= O_BINARY;
6083#endif
6084 if (!has_enc)
6085 rb_io_ext_int_to_encs(rb_ascii8bit_encoding(), NULL, &enc, &enc2, fmode);
6086 }
6087#if DEFAULT_TEXTMODE
6088 else if (NIL_P(vmode)) {
6089 fmode |= DEFAULT_TEXTMODE;
6090 }
6091#endif
6092 v = rb_hash_aref(opthash, sym_perm);
6093 if (!NIL_P(v)) {
6094 if (vperm_p) {
6095 if (!NIL_P(*vperm_p)) {
6096 rb_raise(rb_eArgError, "perm specified twice");
6097 }
6098 *vperm_p = v;
6099 }
6100 else {
6101 /* perm no use, just ignore */
6102 }
6103 }
6104 ecflags = (fmode & FMODE_READABLE) ?
6105 MODE_BTMODE(ECONV_DEFAULT_NEWLINE_DECORATOR,
6106 0, ECONV_UNIVERSAL_NEWLINE_DECORATOR) : 0;
6107#ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
6108 ecflags |= (fmode & FMODE_WRITABLE) ?
6109 MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE,
6110 0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE) : 0;
6111#endif
6112
6113 if (rb_io_extract_encoding_option(opthash, &enc, &enc2, &fmode)) {
6114 if (has_enc) {
6115 rb_raise(rb_eArgError, "encoding specified twice");
6116 }
6117 }
6118 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
6119 ecflags = rb_econv_prepare_options(opthash, &ecopts, ecflags);
6120 }
6121
6122 validate_enc_binmode(&fmode, ecflags, enc, enc2);
6123
6124 *vmode_p = vmode;
6125
6126 *oflags_p = oflags;
6127 *fmode_p = fmode;
6128 convconfig_p->enc = enc;
6129 convconfig_p->enc2 = enc2;
6130 convconfig_p->ecflags = ecflags;
6131 convconfig_p->ecopts = ecopts;
6132}
6133
6134 struct sysopen_struct {
6135 VALUE fname;
6136 int oflags;
6137 mode_t perm;
6138};
6139
6140static void *
6141sysopen_func(void *ptr)
6142{
6143 const struct sysopen_struct *data = ptr;
6144 const char *fname = RSTRING_PTR(data->fname);
6145 return (void *)(VALUE)rb_cloexec_open(fname, data->oflags, data->perm);
6146}
6147
6148static inline int
6149rb_sysopen_internal(struct sysopen_struct *data)
6150{
6151 int fd;
6152 fd = (int)(VALUE)rb_thread_call_without_gvl(sysopen_func, data, RUBY_UBF_IO, 0);
6153 if (0 <= fd)
6154 rb_update_max_fd(fd);
6155 return fd;
6156}
6157
6158static int
6159rb_sysopen(VALUE fname, int oflags, mode_t perm)
6160{
6161 int fd;
6162 struct sysopen_struct data;
6163
6164 data.fname = rb_str_encode_ospath(fname);
6165 StringValueCStr(data.fname);
6166 data.oflags = oflags;
6167 data.perm = perm;
6168
6169 fd = rb_sysopen_internal(&data);
6170 if (fd < 0) {
6171 int e = errno;
6172 if (rb_gc_for_fd(e)) {
6173 fd = rb_sysopen_internal(&data);
6174 }
6175 if (fd < 0) {
6176 rb_syserr_fail_path(e, fname);
6177 }
6178 }
6179 return fd;
6180}
6181
6182 FILE *
6183 rb_fdopen(int fd, const char *modestr)
6184{
6185 FILE *file;
6186
6187#if defined(__sun)
6188 errno = 0;
6189#endif
6190 file = fdopen(fd, modestr);
6191 if (!file) {
6192 int e = errno;
6193#if defined(__sun)
6194 if (e == 0) {
6195 rb_gc();
6196 errno = 0;
6197 file = fdopen(fd, modestr);
6198 }
6199 else
6200#endif
6201 if (rb_gc_for_fd(e)) {
6202 file = fdopen(fd, modestr);
6203 }
6204 if (!file) {
6205#ifdef _WIN32
6206 if (e == 0) e = EINVAL;
6207#elif defined(__sun)
6208 if (e == 0) e = EMFILE;
6209#endif
6210 rb_syserr_fail(e, 0);
6211 }
6212 }
6213
6214 /* xxx: should be _IONBF? A buffer in FILE may have trouble. */
6215#ifdef USE_SETVBUF
6216 if (setvbuf(file, NULL, _IOFBF, 0) != 0)
6217 rb_warn("setvbuf() can't be honoured (fd=%d)", fd);
6218#endif
6219 return file;
6220}
6221
6222static int
6223io_check_tty(rb_io_t *fptr)
6224{
6225 int t = isatty(fptr->fd);
6226 if (t)
6227 fptr->mode |= FMODE_TTY|FMODE_DUPLEX;
6228 return t;
6229}
6230
6231static VALUE rb_io_internal_encoding(VALUE);
6232static void io_encoding_set(rb_io_t *, VALUE, VALUE, VALUE);
6233
6234static int
6235io_strip_bom(VALUE io)
6236{
6237 VALUE b1, b2, b3, b4;
6238 rb_io_t *fptr;
6239
6240 GetOpenFile(io, fptr);
6241 if (!(fptr->mode & FMODE_READABLE)) return 0;
6242 if (NIL_P(b1 = rb_io_getbyte(io))) return 0;
6243 switch (b1) {
6244 case INT2FIX(0xEF):
6245 if (NIL_P(b2 = rb_io_getbyte(io))) break;
6246 if (b2 == INT2FIX(0xBB) && !NIL_P(b3 = rb_io_getbyte(io))) {
6247 if (b3 == INT2FIX(0xBF)) {
6248 return rb_utf8_encindex();
6249 }
6250 rb_io_ungetbyte(io, b3);
6251 }
6252 rb_io_ungetbyte(io, b2);
6253 break;
6254
6255 case INT2FIX(0xFE):
6256 if (NIL_P(b2 = rb_io_getbyte(io))) break;
6257 if (b2 == INT2FIX(0xFF)) {
6258 return ENCINDEX_UTF_16BE;
6259 }
6260 rb_io_ungetbyte(io, b2);
6261 break;
6262
6263 case INT2FIX(0xFF):
6264 if (NIL_P(b2 = rb_io_getbyte(io))) break;
6265 if (b2 == INT2FIX(0xFE)) {
6266 b3 = rb_io_getbyte(io);
6267 if (b3 == INT2FIX(0) && !NIL_P(b4 = rb_io_getbyte(io))) {
6268 if (b4 == INT2FIX(0)) {
6269 return ENCINDEX_UTF_32LE;
6270 }
6271 rb_io_ungetbyte(io, b4);
6272 }
6273 rb_io_ungetbyte(io, b3);
6274 return ENCINDEX_UTF_16LE;
6275 }
6276 rb_io_ungetbyte(io, b2);
6277 break;
6278
6279 case INT2FIX(0):
6280 if (NIL_P(b2 = rb_io_getbyte(io))) break;
6281 if (b2 == INT2FIX(0) && !NIL_P(b3 = rb_io_getbyte(io))) {
6282 if (b3 == INT2FIX(0xFE) && !NIL_P(b4 = rb_io_getbyte(io))) {
6283 if (b4 == INT2FIX(0xFF)) {
6284 return ENCINDEX_UTF_32BE;
6285 }
6286 rb_io_ungetbyte(io, b4);
6287 }
6288 rb_io_ungetbyte(io, b3);
6289 }
6290 rb_io_ungetbyte(io, b2);
6291 break;
6292 }
6293 rb_io_ungetbyte(io, b1);
6294 return 0;
6295}
6296
6297static rb_encoding *
6298io_set_encoding_by_bom(VALUE io)
6299{
6300 int idx = io_strip_bom(io);
6301 rb_io_t *fptr;
6302 rb_encoding *extenc = NULL;
6303
6304 GetOpenFile(io, fptr);
6305 if (idx) {
6306 extenc = rb_enc_from_index(idx);
6307 io_encoding_set(fptr, rb_enc_from_encoding(extenc),
6308 rb_io_internal_encoding(io), Qnil);
6309 }
6310 else {
6311 fptr->encs.enc2 = NULL;
6312 }
6313 return extenc;
6314}
6315
6316static VALUE
6317rb_file_open_generic(VALUE io, VALUE filename, int oflags, int fmode,
6318 const convconfig_t *convconfig, mode_t perm)
6319{
6320 VALUE pathv;
6321 rb_io_t *fptr;
6322 convconfig_t cc;
6323 if (!convconfig) {
6324 /* Set to default encodings */
6325 rb_io_ext_int_to_encs(NULL, NULL, &cc.enc, &cc.enc2, fmode);
6326 cc.ecflags = 0;
6327 cc.ecopts = Qnil;
6328 convconfig = &cc;
6329 }
6330 validate_enc_binmode(&fmode, convconfig->ecflags,
6331 convconfig->enc, convconfig->enc2);
6332
6333 MakeOpenFile(io, fptr);
6334 fptr->mode = fmode;
6335 fptr->encs = *convconfig;
6336 pathv = rb_str_new_frozen(filename);
6337#ifdef O_TMPFILE
6338 if (!(oflags & O_TMPFILE)) {
6339 fptr->pathv = pathv;
6340 }
6341#else
6342 fptr->pathv = pathv;
6343#endif
6344 fptr->fd = rb_sysopen(pathv, oflags, perm);
6345 io_check_tty(fptr);
6346 if (fmode & FMODE_SETENC_BY_BOM) io_set_encoding_by_bom(io);
6347
6348 return io;
6349}
6350
6351static VALUE
6352rb_file_open_internal(VALUE io, VALUE filename, const char *modestr)
6353{
6354 int fmode = rb_io_modestr_fmode(modestr);
6355 const char *p = strchr(modestr, ':');
6356 convconfig_t convconfig;
6357
6358 if (p) {
6359 parse_mode_enc(p+1, rb_usascii_encoding(),
6360 &convconfig.enc, &convconfig.enc2, &fmode);
6361 convconfig.ecflags = 0;
6362 convconfig.ecopts = Qnil;
6363 }
6364 else {
6365 rb_encoding *e;
6366 /* Set to default encodings */
6367
6368 e = (fmode & FMODE_BINMODE) ? rb_ascii8bit_encoding() : NULL;
6369 rb_io_ext_int_to_encs(e, NULL, &convconfig.enc, &convconfig.enc2, fmode);
6370 convconfig.ecflags = 0;
6371 convconfig.ecopts = Qnil;
6372 }
6373
6374 return rb_file_open_generic(io, filename,
6375 rb_io_fmode_oflags(fmode),
6376 fmode,
6377 &convconfig,
6378 0666);
6379}
6380
6381 VALUE
6382 rb_file_open_str(VALUE fname, const char *modestr)
6383{
6384 FilePathValue(fname);
6385 return rb_file_open_internal(io_alloc(rb_cFile), fname, modestr);
6386}
6387
6388 VALUE
6389 rb_file_open(const char *fname, const char *modestr)
6390{
6391 return rb_file_open_internal(io_alloc(rb_cFile), rb_str_new_cstr(fname), modestr);
6392}
6393
6394#if defined(__CYGWIN__) || !defined(HAVE_WORKING_FORK)
6395static struct pipe_list {
6396 rb_io_t *fptr;
6397 struct pipe_list *next;
6398} *pipe_list;
6399
6400static void
6401pipe_add_fptr(rb_io_t *fptr)
6402{
6403 struct pipe_list *list;
6404
6405 list = ALLOC(struct pipe_list);
6406 list->fptr = fptr;
6407 list->next = pipe_list;
6408 pipe_list = list;
6409}
6410
6411static void
6412pipe_del_fptr(rb_io_t *fptr)
6413{
6414 struct pipe_list **prev = &pipe_list;
6415 struct pipe_list *tmp;
6416
6417 while ((tmp = *prev) != 0) {
6418 if (tmp->fptr == fptr) {
6419 *prev = tmp->next;
6420 free(tmp);
6421 return;
6422 }
6423 prev = &tmp->next;
6424 }
6425}
6426
6427#if defined (_WIN32) || defined(__CYGWIN__)
6428static void
6429pipe_atexit(void)
6430{
6431 struct pipe_list *list = pipe_list;
6432 struct pipe_list *tmp;
6433
6434 while (list) {
6435 tmp = list->next;
6436 rb_io_fptr_finalize(list->fptr);
6437 list = tmp;
6438 }
6439}
6440#endif
6441
6442static void
6443pipe_finalize(rb_io_t *fptr, int noraise)
6444{
6445#if !defined(HAVE_WORKING_FORK) && !defined(_WIN32)
6446 int status = 0;
6447 if (fptr->stdio_file) {
6448 status = pclose(fptr->stdio_file);
6449 }
6450 fptr->fd = -1;
6451 fptr->stdio_file = 0;
6452 rb_last_status_set(status, fptr->pid);
6453#else
6454 fptr_finalize(fptr, noraise);
6455#endif
6456 pipe_del_fptr(fptr);
6457}
6458#endif
6459
6460static void
6461fptr_copy_finalizer(rb_io_t *fptr, const rb_io_t *orig)
6462{
6463#if defined(__CYGWIN__) || !defined(HAVE_WORKING_FORK)
6464 void (*const old_finalize)(struct rb_io_t*,int) = fptr->finalize;
6465
6466 if (old_finalize == orig->finalize) return;
6467#endif
6468
6469 fptr->finalize = orig->finalize;
6470
6471#if defined(__CYGWIN__) || !defined(HAVE_WORKING_FORK)
6472 if (old_finalize != pipe_finalize) {
6473 struct pipe_list *list;
6474 for (list = pipe_list; list; list = list->next) {
6475 if (list->fptr == fptr) break;
6476 }
6477 if (!list) pipe_add_fptr(fptr);
6478 }
6479 else {
6480 pipe_del_fptr(fptr);
6481 }
6482#endif
6483}
6484
6485void
6486 rb_io_synchronized(rb_io_t *fptr)
6487{
6488 rb_io_check_initialized(fptr);
6489 fptr->mode |= FMODE_SYNC;
6490}
6491
6492void
6493rb_io_unbuffered(rb_io_t *fptr)
6494{
6495 rb_io_synchronized(fptr);
6496}
6497
6498int
6499 rb_pipe(int *pipes)
6500{
6501 int ret;
6502 ret = rb_cloexec_pipe(pipes);
6503 if (ret < 0) {
6504 if (rb_gc_for_fd(errno)) {
6505 ret = rb_cloexec_pipe(pipes);
6506 }
6507 }
6508 if (ret == 0) {
6509 rb_update_max_fd(pipes[0]);
6510 rb_update_max_fd(pipes[1]);
6511 }
6512 return ret;
6513}
6514
6515#ifdef _WIN32
6516#define HAVE_SPAWNV 1
6517#define spawnv(mode, cmd, args) rb_w32_uaspawn((mode), (cmd), (args))
6518#define spawn(mode, cmd) rb_w32_uspawn((mode), (cmd), 0)
6519#endif
6520
6521#if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
6522struct popen_arg {
6523 VALUE execarg_obj;
6524 struct rb_execarg *eargp;
6525 int modef;
6526 int pair[2];
6527 int write_pair[2];
6528};
6529#endif
6530
6531#ifdef HAVE_WORKING_FORK
6532static void
6533popen_redirect(struct popen_arg *p)
6534{
6535 if ((p->modef & FMODE_READABLE) && (p->modef & FMODE_WRITABLE)) {
6536 close(p->write_pair[1]);
6537 if (p->write_pair[0] != 0) {
6538 dup2(p->write_pair[0], 0);
6539 close(p->write_pair[0]);
6540 }
6541 close(p->pair[0]);
6542 if (p->pair[1] != 1) {
6543 dup2(p->pair[1], 1);
6544 close(p->pair[1]);
6545 }
6546 }
6547 else if (p->modef & FMODE_READABLE) {
6548 close(p->pair[0]);
6549 if (p->pair[1] != 1) {
6550 dup2(p->pair[1], 1);
6551 close(p->pair[1]);
6552 }
6553 }
6554 else {
6555 close(p->pair[1]);
6556 if (p->pair[0] != 0) {
6557 dup2(p->pair[0], 0);
6558 close(p->pair[0]);
6559 }
6560 }
6561}
6562
6563#if defined(__linux__)
6564/* Linux /proc/self/status contains a line: "FDSize:\t<nnn>\n"
6565 * Since /proc may not be available, linux_get_maxfd is just a hint.
6566 * This function, linux_get_maxfd, must be async-signal-safe.
6567 * I.e. opendir() is not usable.
6568 *
6569 * Note that memchr() and memcmp is *not* async-signal-safe in POSIX.
6570 * However they are easy to re-implement in async-signal-safe manner.
6571 * (Also note that there is missing/memcmp.c.)
6572 */
6573static int
6574linux_get_maxfd(void)
6575{
6576 int fd;
6577 char buf[4096], *p, *np, *e;
6578 ssize_t ss;
6579 fd = rb_cloexec_open("/proc/self/status", O_RDONLY|O_NOCTTY, 0);
6580 if (fd < 0) return fd;
6581 ss = read(fd, buf, sizeof(buf));
6582 if (ss < 0) goto err;
6583 p = buf;
6584 e = buf + ss;
6585 while ((int)sizeof("FDSize:\t0\n")-1 <= e-p &&
6586 (np = memchr(p, '\n', e-p)) != NULL) {
6587 if (memcmp(p, "FDSize:", sizeof("FDSize:")-1) == 0) {
6588 int fdsize;
6589 p += sizeof("FDSize:")-1;
6590 *np = '\0';
6591 fdsize = (int)ruby_strtoul(p, (char **)NULL, 10);
6592 close(fd);
6593 return fdsize;
6594 }
6595 p = np+1;
6596 }
6597 /* fall through */
6598
6599 err:
6600 close(fd);
6601 return (int)ss;
6602}
6603#endif
6604
6605/* This function should be async-signal-safe. */
6606void
6607 rb_close_before_exec(int lowfd, int maxhint, VALUE noclose_fds)
6608{
6609#if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
6610 int fd, ret;
6611 int max = (int)max_file_descriptor;
6612# ifdef F_MAXFD
6613 /* F_MAXFD is available since NetBSD 2.0. */
6614 ret = fcntl(0, F_MAXFD); /* async-signal-safe */
6615 if (ret != -1)
6616 maxhint = max = ret;
6617# elif defined(__linux__)
6618 ret = linux_get_maxfd();
6619 if (maxhint < ret)
6620 maxhint = ret;
6621 /* maxhint = max = ret; if (ret == -1) abort(); // test */
6622# endif
6623 if (max < maxhint)
6624 max = maxhint;
6625 for (fd = lowfd; fd <= max; fd++) {
6626 if (!NIL_P(noclose_fds) &&
6627 RTEST(rb_hash_lookup(noclose_fds, INT2FIX(fd)))) /* async-signal-safe */
6628 continue;
6629 ret = fcntl(fd, F_GETFD); /* async-signal-safe */
6630 if (ret != -1 && !(ret & FD_CLOEXEC)) {
6631 fcntl(fd, F_SETFD, ret|FD_CLOEXEC); /* async-signal-safe */
6632 }
6633# define CONTIGUOUS_CLOSED_FDS 20
6634 if (ret != -1) {
6635 if (max < fd + CONTIGUOUS_CLOSED_FDS)
6636 max = fd + CONTIGUOUS_CLOSED_FDS;
6637 }
6638 }
6639#endif
6640}
6641
6642static int
6643popen_exec(void *pp, char *errmsg, size_t errmsg_len)
6644{
6645 struct popen_arg *p = (struct popen_arg*)pp;
6646
6647 return rb_exec_async_signal_safe(p->eargp, errmsg, errmsg_len);
6648}
6649#endif
6650
6651#if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
6652static VALUE
6653rb_execarg_fixup_v(VALUE execarg_obj)
6654{
6655 rb_execarg_parent_start(execarg_obj);
6656 return Qnil;
6657}
6658#else
6659char *rb_execarg_commandline(const struct rb_execarg *eargp, VALUE *prog);
6660#endif
6661
6662static VALUE
6663pipe_open(VALUE execarg_obj, const char *modestr, int fmode,
6664 const convconfig_t *convconfig)
6665{
6666 struct rb_execarg *eargp = NIL_P(execarg_obj) ? NULL : rb_execarg_get(execarg_obj);
6667 VALUE prog = eargp ? (eargp->use_shell ? eargp->invoke.sh.shell_script : eargp->invoke.cmd.command_name) : Qfalse ;
6668 rb_pid_t pid = 0;
6669 rb_io_t *fptr;
6670 VALUE port;
6671 rb_io_t *write_fptr;
6672 VALUE write_port;
6673#if defined(HAVE_WORKING_FORK)
6674 int status;
6675 char errmsg[80] = { '\0' };
6676#endif
6677#if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
6678 int state;
6679 struct popen_arg arg;
6680#endif
6681 int e = 0;
6682#if defined(HAVE_SPAWNV)
6683# if defined(HAVE_SPAWNVE)
6684# define DO_SPAWN(cmd, args, envp) ((args) ? \
6685 spawnve(P_NOWAIT, (cmd), (args), (envp)) : \
6686 spawne(P_NOWAIT, (cmd), (envp)))
6687# else
6688# define DO_SPAWN(cmd, args, envp) ((args) ? \
6689 spawnv(P_NOWAIT, (cmd), (args)) : \
6690 spawn(P_NOWAIT, (cmd)))
6691# endif
6692# if !defined(HAVE_WORKING_FORK)
6693 char **args = NULL;
6694# if defined(HAVE_SPAWNVE)
6695 char **envp = NULL;
6696# endif
6697# endif
6698#endif
6699#if !defined(HAVE_WORKING_FORK)
6700 struct rb_execarg sarg, *sargp = &sarg;
6701#endif
6702 FILE *fp = 0;
6703 int fd = -1;
6704 int write_fd = -1;
6705#if !defined(HAVE_WORKING_FORK)
6706 const char *cmd = 0;
6707
6708 if (prog)
6709 cmd = StringValueCStr(prog);
6710#endif
6711
6712#if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
6713 arg.execarg_obj = execarg_obj;
6714 arg.eargp = eargp;
6715 arg.modef = fmode;
6716 arg.pair[0] = arg.pair[1] = -1;
6717 arg.write_pair[0] = arg.write_pair[1] = -1;
6718# if !defined(HAVE_WORKING_FORK)
6719 if (eargp && !eargp->use_shell) {
6720 args = ARGVSTR2ARGV(eargp->invoke.cmd.argv_str);
6721 }
6722# endif
6723 switch (fmode & (FMODE_READABLE|FMODE_WRITABLE)) {
6724 case FMODE_READABLE|FMODE_WRITABLE:
6725 if (rb_pipe(arg.write_pair) < 0)
6726 rb_sys_fail_str(prog);
6727 if (rb_pipe(arg.pair) < 0) {
6728 e = errno;
6729 close(arg.write_pair[0]);
6730 close(arg.write_pair[1]);
6731 rb_syserr_fail_str(e, prog);
6732 }
6733 if (eargp) {
6734 rb_execarg_addopt(execarg_obj, INT2FIX(0), INT2FIX(arg.write_pair[0]));
6735 rb_execarg_addopt(execarg_obj, INT2FIX(1), INT2FIX(arg.pair[1]));
6736 }
6737 break;
6738 case FMODE_READABLE:
6739 if (rb_pipe(arg.pair) < 0)
6740 rb_sys_fail_str(prog);
6741 if (eargp)
6742 rb_execarg_addopt(execarg_obj, INT2FIX(1), INT2FIX(arg.pair[1]));
6743 break;
6744 case FMODE_WRITABLE:
6745 if (rb_pipe(arg.pair) < 0)
6746 rb_sys_fail_str(prog);
6747 if (eargp)
6748 rb_execarg_addopt(execarg_obj, INT2FIX(0), INT2FIX(arg.pair[0]));
6749 break;
6750 default:
6751 rb_sys_fail_str(prog);
6752 }
6753 if (!NIL_P(execarg_obj)) {
6754 rb_protect(rb_execarg_fixup_v, execarg_obj, &state);
6755 if (state) {
6756 if (0 <= arg.write_pair[0]) close(arg.write_pair[0]);
6757 if (0 <= arg.write_pair[1]) close(arg.write_pair[1]);
6758 if (0 <= arg.pair[0]) close(arg.pair[0]);
6759 if (0 <= arg.pair[1]) close(arg.pair[1]);
6760 rb_execarg_parent_end(execarg_obj);
6761 rb_jump_tag(state);
6762 }
6763
6764# if defined(HAVE_WORKING_FORK)
6765 pid = rb_fork_async_signal_safe(&status, popen_exec, &arg, arg.eargp->redirect_fds, errmsg, sizeof(errmsg));
6766# else
6767 rb_execarg_run_options(eargp, sargp, NULL, 0);
6768# if defined(HAVE_SPAWNVE)
6769 if (eargp->envp_str) envp = (char **)RSTRING_PTR(eargp->envp_str);
6770# endif
6771 while ((pid = DO_SPAWN(cmd, args, envp)) < 0) {
6772 /* exec failed */
6773 switch (e = errno) {
6774 case EAGAIN:
6775# if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
6776 case EWOULDBLOCK:
6777# endif
6778 rb_thread_sleep(1);
6779 continue;
6780 }
6781 break;
6782 }
6783 if (eargp)
6784 rb_execarg_run_options(sargp, NULL, NULL, 0);
6785# endif
6786 rb_execarg_parent_end(execarg_obj);
6787 }
6788 else {
6789# if defined(HAVE_WORKING_FORK)
6790 pid = rb_fork_ruby(&status);
6791 if (pid == 0) { /* child */
6792 rb_thread_atfork();
6793 popen_redirect(&arg);
6794 rb_io_synchronized(RFILE(orig_stdout)->fptr);
6795 rb_io_synchronized(RFILE(orig_stderr)->fptr);
6796 return Qnil;
6797 }
6798# else
6799 rb_notimplement();
6800# endif
6801 }
6802
6803 /* parent */
6804 if (pid < 0) {
6805# if defined(HAVE_WORKING_FORK)
6806 e = errno;
6807# endif
6808 close(arg.pair[0]);
6809 close(arg.pair[1]);
6810 if ((fmode & (FMODE_READABLE|FMODE_WRITABLE)) == (FMODE_READABLE|FMODE_WRITABLE)) {
6811 close(arg.write_pair[0]);
6812 close(arg.write_pair[1]);
6813 }
6814# if defined(HAVE_WORKING_FORK)
6815 if (errmsg[0])
6816 rb_syserr_fail(e, errmsg);
6817# endif
6818 rb_syserr_fail_str(e, prog);
6819 }
6820 if ((fmode & FMODE_READABLE) && (fmode & FMODE_WRITABLE)) {
6821 close(arg.pair[1]);
6822 fd = arg.pair[0];
6823 close(arg.write_pair[0]);
6824 write_fd = arg.write_pair[1];
6825 }
6826 else if (fmode & FMODE_READABLE) {
6827 close(arg.pair[1]);
6828 fd = arg.pair[0];
6829 }
6830 else {
6831 close(arg.pair[0]);
6832 fd = arg.pair[1];
6833 }
6834#else
6835 cmd = rb_execarg_commandline(eargp, &prog);
6836 if (!NIL_P(execarg_obj)) {
6837 rb_execarg_parent_start(execarg_obj);
6838 rb_execarg_run_options(eargp, sargp, NULL, 0);
6839 }
6840 fp = popen(cmd, modestr);
6841 e = errno;
6842 if (eargp) {
6843 rb_execarg_parent_end(execarg_obj);
6844 rb_execarg_run_options(sargp, NULL, NULL, 0);
6845 }
6846 if (!fp) rb_syserr_fail_path(e, prog);
6847 fd = fileno(fp);
6848#endif
6849
6850 port = io_alloc(rb_cIO);
6851 MakeOpenFile(port, fptr);
6852 fptr->fd = fd;
6853 fptr->stdio_file = fp;
6854 fptr->mode = fmode | FMODE_SYNC|FMODE_DUPLEX;
6855 if (convconfig) {
6856 fptr->encs = *convconfig;
6857#if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
6858 if (fptr->encs.ecflags & ECONV_DEFAULT_NEWLINE_DECORATOR) {
6859 fptr->encs.ecflags |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;
6860 }
6861#endif
6862 }
6863 else {
6864 if (NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {
6865 fptr->encs.ecflags |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;
6866 }
6867#ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
6868 if (NEED_NEWLINE_DECORATOR_ON_WRITE(fptr)) {
6869 fptr->encs.ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
6870 }
6871#endif
6872 }
6873 fptr->pid = pid;
6874
6875 if (0 <= write_fd) {
6876 write_port = io_alloc(rb_cIO);
6877 MakeOpenFile(write_port, write_fptr);
6878 write_fptr->fd = write_fd;
6879 write_fptr->mode = (fmode & ~FMODE_READABLE)| FMODE_SYNC|FMODE_DUPLEX;
6880 fptr->mode &= ~FMODE_WRITABLE;
6881 fptr->tied_io_for_writing = write_port;
6882 rb_ivar_set(port, rb_intern("@tied_io_for_writing"), write_port);
6883 }
6884
6885#if defined (__CYGWIN__) || !defined(HAVE_WORKING_FORK)
6886 fptr->finalize = pipe_finalize;
6887 pipe_add_fptr(fptr);
6888#endif
6889 return port;
6890}
6891
6892static int
6893is_popen_fork(VALUE prog)
6894{
6895 if (RSTRING_LEN(prog) == 1 && RSTRING_PTR(prog)[0] == '-') {
6896#if !defined(HAVE_WORKING_FORK)
6897 rb_raise(rb_eNotImpError,
6898 "fork() function is unimplemented on this machine");
6899#else
6900 return TRUE;
6901#endif
6902 }
6903 return FALSE;
6904}
6905
6906static VALUE
6907pipe_open_s(VALUE prog, const char *modestr, int fmode,
6908 const convconfig_t *convconfig)
6909{
6910 int argc = 1;
6911 VALUE *argv = &prog;
6912 VALUE execarg_obj = Qnil;
6913
6914 if (!is_popen_fork(prog))
6915 execarg_obj = rb_execarg_new(argc, argv, TRUE, FALSE);
6916 return pipe_open(execarg_obj, modestr, fmode, convconfig);
6917}
6918
6919static VALUE
6920pipe_close(VALUE io)
6921{
6922 rb_io_t *fptr = io_close_fptr(io);
6923 if (fptr) {
6924 fptr_waitpid(fptr, rb_thread_to_be_killed(rb_thread_current()));
6925 }
6926 return Qnil;
6927}
6928
6929static VALUE popen_finish(VALUE port, VALUE klass);
6930
6931/*
6932 * call-seq:
6933 * IO.popen([env,] cmd, mode="r" [, opt]) -> io
6934 * IO.popen([env,] cmd, mode="r" [, opt]) {|io| block } -> obj
6935 *
6936 * Runs the specified command as a subprocess; the subprocess's
6937 * standard input and output will be connected to the returned
6938 * IO object.
6939 *
6940 * The PID of the started process can be obtained by IO#pid method.
6941 *
6942 * _cmd_ is a string or an array as follows.
6943 *
6944 * cmd:
6945 * "-" : fork
6946 * commandline : command line string which is passed to a shell
6947 * [env, cmdname, arg1, ..., opts] : command name and zero or more arguments (no shell)
6948 * [env, [cmdname, argv0], arg1, ..., opts] : command name, argv[0] and zero or more arguments (no shell)
6949 * (env and opts are optional.)
6950 *
6951 * If _cmd_ is a +String+ ``<code>-</code>'',
6952 * then a new instance of Ruby is started as the subprocess.
6953 *
6954 * If <i>cmd</i> is an +Array+ of +String+,
6955 * then it will be used as the subprocess's +argv+ bypassing a shell.
6956 * The array can contain a hash at first for environments and
6957 * a hash at last for options similar to #spawn.
6958 *
6959 * The default mode for the new file object is ``r'',
6960 * but <i>mode</i> may be set to any of the modes listed in the description for class IO.
6961 * The last argument <i>opt</i> qualifies <i>mode</i>.
6962 *
6963 * # set IO encoding
6964 * IO.popen("nkf -e filename", :external_encoding=>"EUC-JP") {|nkf_io|
6965 * euc_jp_string = nkf_io.read
6966 * }
6967 *
6968 * # merge standard output and standard error using
6969 * # spawn option. See the document of Kernel.spawn.
6970 * IO.popen(["ls", "/", :err=>[:child, :out]]) {|ls_io|
6971 * ls_result_with_error = ls_io.read
6972 * }
6973 *
6974 * # spawn options can be mixed with IO options
6975 * IO.popen(["ls", "/"], :err=>[:child, :out]) {|ls_io|
6976 * ls_result_with_error = ls_io.read
6977 * }
6978 *
6979 * Raises exceptions which IO.pipe and Kernel.spawn raise.
6980 *
6981 * If a block is given, Ruby will run the command as a child connected
6982 * to Ruby with a pipe. Ruby's end of the pipe will be passed as a
6983 * parameter to the block.
6984 * At the end of block, Ruby closes the pipe and sets <code>$?</code>.
6985 * In this case IO.popen returns the value of the block.
6986 *
6987 * If a block is given with a _cmd_ of ``<code>-</code>'',
6988 * the block will be run in two separate processes: once in the parent,
6989 * and once in a child. The parent process will be passed the pipe
6990 * object as a parameter to the block, the child version of the block
6991 * will be passed +nil+, and the child's standard in and
6992 * standard out will be connected to the parent through the pipe. Not
6993 * available on all platforms.
6994 *
6995 * f = IO.popen("uname")
6996 * p f.readlines
6997 * f.close
6998 * puts "Parent is #{Process.pid}"
6999 * IO.popen("date") {|f| puts f.gets }
7000 * IO.popen("-") {|f| $stderr.puts "#{Process.pid} is here, f is #{f.inspect}"}
7001 * p $?
7002 * IO.popen(%w"sed -e s|^|<foo>| -e s&$&;zot;&", "r+") {|f|
7003 * f.puts "bar"; f.close_write; puts f.gets
7004 * }
7005 *
7006 * <em>produces:</em>
7007 *
7008 * ["Linux\n"]
7009 * Parent is 21346
7010 * Thu Jan 15 22:41:19 JST 2009
7011 * 21346 is here, f is #<IO:fd 3>
7012 * 21352 is here, f is nil
7013 * #<Process::Status: pid 21352 exit 0>
7014 * <foo>bar;zot;
7015 */
7016
7017static VALUE
7018rb_io_s_popen(int argc, VALUE *argv, VALUE klass)
7019{
7020 VALUE pname, pmode = Qnil, opt = Qnil, env = Qnil;
7021
7022 if (argc > 1 && !NIL_P(opt = rb_check_hash_type(argv[argc-1]))) --argc;
7023 if (argc > 1 && !NIL_P(env = rb_check_hash_type(argv[0]))) --argc, ++argv;
7024 switch (argc) {
7025 case 2:
7026 pmode = argv[1];
7027 case 1:
7028 pname = argv[0];
7029 break;
7030 default:
7031 {
7032 int ex = !NIL_P(opt);
7033 rb_error_arity(argc + ex, 1 + ex, 2 + ex);
7034 }
7035 }
7036 return popen_finish(rb_io_popen(pname, pmode, env, opt), klass);
7037}
7038
7039 VALUE
7040 rb_io_popen(VALUE pname, VALUE pmode, VALUE env, VALUE opt)
7041{
7042 const char *modestr;
7043 VALUE tmp, execarg_obj = Qnil;
7044 int oflags, fmode;
7045 convconfig_t convconfig;
7046
7047 tmp = rb_check_array_type(pname);
7048 if (!NIL_P(tmp)) {
7049 long len = RARRAY_LEN(tmp);
7050#if SIZEOF_LONG > SIZEOF_INT
7051 if (len > INT_MAX) {
7052 rb_raise(rb_eArgError, "too many arguments");
7053 }
7054#endif
7055 execarg_obj = rb_execarg_new((int)len, RARRAY_CONST_PTR(tmp), FALSE, FALSE);
7056 RB_GC_GUARD(tmp);
7057 }
7058 else {
7059 SafeStringValue(pname);
7060 execarg_obj = Qnil;
7061 if (!is_popen_fork(pname))
7062 execarg_obj = rb_execarg_new(1, &pname, TRUE, FALSE);
7063 }
7064 if (!NIL_P(execarg_obj)) {
7065 if (!NIL_P(opt))
7066 opt = rb_execarg_extract_options(execarg_obj, opt);
7067 if (!NIL_P(env))
7068 rb_execarg_setenv(execarg_obj, env);
7069 }
7070 rb_io_extract_modeenc(&pmode, 0, opt, &oflags, &fmode, &convconfig);
7071 modestr = rb_io_oflags_modestr(oflags);
7072
7073 return pipe_open(execarg_obj, modestr, fmode, &convconfig);
7074}
7075
7076static VALUE
7077popen_finish(VALUE port, VALUE klass)
7078{
7079 if (NIL_P(port)) {
7080 /* child */
7081 if (rb_block_given_p()) {
7082 rb_yield(Qnil);
7083 rb_io_flush(rb_ractor_stdout());
7084 rb_io_flush(rb_ractor_stderr());
7085 _exit(0);
7086 }
7087 return Qnil;
7088 }
7089 RBASIC_SET_CLASS(port, klass);
7090 if (rb_block_given_p()) {
7091 return rb_ensure(rb_yield, port, pipe_close, port);
7092 }
7093 return port;
7094}
7095
7096static void
7097rb_scan_open_args(int argc, const VALUE *argv,
7098 VALUE *fname_p, int *oflags_p, int *fmode_p,
7099 convconfig_t *convconfig_p, mode_t *perm_p)
7100{
7101 VALUE opt, fname, vmode, vperm;
7102 int oflags, fmode;
7103 mode_t perm;
7104
7105 argc = rb_scan_args(argc, argv, "12:", &fname, &vmode, &vperm, &opt);
7106 FilePathValue(fname);
7107
7108 rb_io_extract_modeenc(&vmode, &vperm, opt, &oflags, &fmode, convconfig_p);
7109
7110 perm = NIL_P(vperm) ? 0666 : NUM2MODET(vperm);
7111
7112 *fname_p = fname;
7113 *oflags_p = oflags;
7114 *fmode_p = fmode;
7115 *perm_p = perm;
7116}
7117
7118static VALUE
7119rb_open_file(int argc, const VALUE *argv, VALUE io)
7120{
7121 VALUE fname;
7122 int oflags, fmode;
7123 convconfig_t convconfig;
7124 mode_t perm;
7125
7126 rb_scan_open_args(argc, argv, &fname, &oflags, &fmode, &convconfig, &perm);
7127 rb_file_open_generic(io, fname, oflags, fmode, &convconfig, perm);
7128
7129 return io;
7130}
7131
7132
7133/*
7134 * Document-method: File::open
7135 *
7136 * call-seq:
7137 * File.open(filename, mode="r" [, opt]) -> file
7138 * File.open(filename [, mode [, perm]] [, opt]) -> file
7139 * File.open(filename, mode="r" [, opt]) {|file| block } -> obj
7140 * File.open(filename [, mode [, perm]] [, opt]) {|file| block } -> obj
7141 *
7142 * With no associated block, File.open is a synonym for
7143 * File.new. If the optional code block is given, it will
7144 * be passed the opened +file+ as an argument and the File object will
7145 * automatically be closed when the block terminates. The value of the block
7146 * will be returned from File.open.
7147 *
7148 * If a file is being created, its initial permissions may be set using the
7149 * +perm+ parameter. See File.new for further discussion.
7150 *
7151 * See IO.new for a description of the +mode+ and +opt+ parameters.
7152 */
7153
7154/*
7155 * Document-method: IO::open
7156 *
7157 * call-seq:
7158 * IO.open(fd, mode="r" [, opt]) -> io
7159 * IO.open(fd, mode="r" [, opt]) {|io| block } -> obj
7160 *
7161 * With no associated block, IO.open is a synonym for IO.new. If
7162 * the optional code block is given, it will be passed +io+ as an argument,
7163 * and the IO object will automatically be closed when the block terminates.
7164 * In this instance, IO.open returns the value of the block.
7165 *
7166 * See IO.new for a description of the +fd+, +mode+ and +opt+ parameters.
7167 */
7168
7169static VALUE
7170rb_io_s_open(int argc, VALUE *argv, VALUE klass)
7171{
7172 VALUE io = rb_class_new_instance_kw(argc, argv, klass, RB_PASS_CALLED_KEYWORDS);
7173
7174 if (rb_block_given_p()) {
7175 return rb_ensure(rb_yield, io, io_close, io);
7176 }
7177
7178 return io;
7179}
7180
7181/*
7182 * call-seq:
7183 * IO.sysopen(path, [mode, [perm]]) -> integer
7184 *
7185 * Opens the given path, returning the underlying file descriptor as a
7186 * Integer.
7187 *
7188 * IO.sysopen("testfile") #=> 3
7189 */
7190
7191static VALUE
7192rb_io_s_sysopen(int argc, VALUE *argv, VALUE _)
7193{
7194 VALUE fname, vmode, vperm;
7195 VALUE intmode;
7196 int oflags, fd;
7197 mode_t perm;
7198
7199 rb_scan_args(argc, argv, "12", &fname, &vmode, &vperm);
7200 FilePathValue(fname);
7201
7202 if (NIL_P(vmode))
7203 oflags = O_RDONLY;
7204 else if (!NIL_P(intmode = rb_check_to_integer(vmode, "to_int")))
7205 oflags = NUM2INT(intmode);
7206 else {
7207 SafeStringValue(vmode);
7208 oflags = rb_io_modestr_oflags(StringValueCStr(vmode));
7209 }
7210 if (NIL_P(vperm)) perm = 0666;
7211 else perm = NUM2MODET(vperm);
7212
7213 RB_GC_GUARD(fname) = rb_str_new4(fname);
7214 fd = rb_sysopen(fname, oflags, perm);
7215 return INT2NUM(fd);
7216}
7217
7218static VALUE
7219check_pipe_command(VALUE filename_or_command)
7220{
7221 char *s = RSTRING_PTR(filename_or_command);
7222 long l = RSTRING_LEN(filename_or_command);
7223 char *e = s + l;
7224 int chlen;
7225
7226 if (rb_enc_ascget(s, e, &chlen, rb_enc_get(filename_or_command)) == '|') {
7227 VALUE cmd = rb_str_new(s+chlen, l-chlen);
7228 return cmd;
7229 }
7230 return Qnil;
7231}
7232
7233/*
7234 * call-seq:
7235 * open(path [, mode [, perm]] [, opt]) -> io or nil
7236 * open(path [, mode [, perm]] [, opt]) {|io| block } -> obj
7237 *
7238 * Creates an IO object connected to the given stream, file, or subprocess.
7239 *
7240 * If +path+ does not start with a pipe character (<code>|</code>), treat it
7241 * as the name of a file to open using the specified mode (defaulting to
7242 * "r").
7243 *
7244 * The +mode+ is either a string or an integer. If it is an integer, it
7245 * must be bitwise-or of open(2) flags, such as File::RDWR or File::EXCL. If
7246 * it is a string, it is either "fmode", "fmode:ext_enc", or
7247 * "fmode:ext_enc:int_enc".
7248 *
7249 * See the documentation of IO.new for full documentation of the +mode+ string
7250 * directives.
7251 *
7252 * If a file is being created, its initial permissions may be set using the
7253 * +perm+ parameter. See File.new and the open(2) and chmod(2) man pages for
7254 * a description of permissions.
7255 *
7256 * If a block is specified, it will be invoked with the IO object as a
7257 * parameter, and the IO will be automatically closed when the block
7258 * terminates. The call returns the value of the block.
7259 *
7260 * If +path+ starts with a pipe character (<code>"|"</code>), a subprocess is
7261 * created, connected to the caller by a pair of pipes. The returned IO
7262 * object may be used to write to the standard input and read from the
7263 * standard output of this subprocess.
7264 *
7265 * If the command following the pipe is a single minus sign
7266 * (<code>"|-"</code>), Ruby forks, and this subprocess is connected to the
7267 * parent. If the command is not <code>"-"</code>, the subprocess runs the
7268 * command.
7269 *
7270 * When the subprocess is Ruby (opened via <code>"|-"</code>), the +open+
7271 * call returns +nil+. If a block is associated with the open call, that
7272 * block will run twice --- once in the parent and once in the child.
7273 *
7274 * The block parameter will be an IO object in the parent and +nil+ in the
7275 * child. The parent's +IO+ object will be connected to the child's $stdin
7276 * and $stdout. The subprocess will be terminated at the end of the block.
7277 *
7278 * === Examples
7279 *
7280 * Reading from "testfile":
7281 *
7282 * open("testfile") do |f|
7283 * print f.gets
7284 * end
7285 *
7286 * Produces:
7287 *
7288 * This is line one
7289 *
7290 * Open a subprocess and read its output:
7291 *
7292 * cmd = open("|date")
7293 * print cmd.gets
7294 * cmd.close
7295 *
7296 * Produces:
7297 *
7298 * Wed Apr 9 08:56:31 CDT 2003
7299 *
7300 * Open a subprocess running the same Ruby program:
7301 *
7302 * f = open("|-", "w+")
7303 * if f.nil?
7304 * puts "in Child"
7305 * exit
7306 * else
7307 * puts "Got: #{f.gets}"
7308 * end
7309 *
7310 * Produces:
7311 *
7312 * Got: in Child
7313 *
7314 * Open a subprocess using a block to receive the IO object:
7315 *
7316 * open "|-" do |f|
7317 * if f then
7318 * # parent process
7319 * puts "Got: #{f.gets}"
7320 * else
7321 * # child process
7322 * puts "in Child"
7323 * end
7324 * end
7325 *
7326 * Produces:
7327 *
7328 * Got: in Child
7329 */
7330
7331static VALUE
7332rb_f_open(int argc, VALUE *argv, VALUE _)
7333{
7334 ID to_open = 0;
7335 int redirect = FALSE;
7336
7337 if (argc >= 1) {
7338 CONST_ID(to_open, "to_open");
7339 if (rb_respond_to(argv[0], to_open)) {
7340 redirect = TRUE;
7341 }
7342 else {
7343 VALUE tmp = argv[0];
7344 FilePathValue(tmp);
7345 if (NIL_P(tmp)) {
7346 redirect = TRUE;
7347 }
7348 else {
7349 VALUE cmd = check_pipe_command(tmp);
7350 if (!NIL_P(cmd)) {
7351 argv[0] = cmd;
7352 return rb_io_s_popen(argc, argv, rb_cIO);
7353 }
7354 }
7355 }
7356 }
7357 if (redirect) {
7358 VALUE io = rb_funcallv_kw(argv[0], to_open, argc-1, argv+1, RB_PASS_CALLED_KEYWORDS);
7359
7360 if (rb_block_given_p()) {
7361 return rb_ensure(rb_yield, io, io_close, io);
7362 }
7363 return io;
7364 }
7365 return rb_io_s_open(argc, argv, rb_cFile);
7366}
7367
7368static VALUE rb_io_open_generic(VALUE, VALUE, int, int, const convconfig_t *, mode_t);
7369
7370static VALUE
7371rb_io_open(VALUE io, VALUE filename, VALUE vmode, VALUE vperm, VALUE opt)
7372{
7373 int oflags, fmode;
7374 convconfig_t convconfig;
7375 mode_t perm;
7376
7377 rb_io_extract_modeenc(&vmode, &vperm, opt, &oflags, &fmode, &convconfig);
7378 perm = NIL_P(vperm) ? 0666 : NUM2MODET(vperm);
7379 return rb_io_open_generic(io, filename, oflags, fmode, &convconfig, perm);
7380}
7381
7382static VALUE
7383rb_io_open_generic(VALUE klass, VALUE filename, int oflags, int fmode,
7384 const convconfig_t *convconfig, mode_t perm)
7385{
7386 VALUE cmd;
7387 if (klass == rb_cIO && !NIL_P(cmd = check_pipe_command(filename))) {
7388 return pipe_open_s(cmd, rb_io_oflags_modestr(oflags), fmode, convconfig);
7389 }
7390 else {
7391 return rb_file_open_generic(io_alloc(klass), filename,
7392 oflags, fmode, convconfig, perm);
7393 }
7394}
7395
7396static VALUE
7397io_reopen(VALUE io, VALUE nfile)
7398{
7399 rb_io_t *fptr, *orig;
7400 int fd, fd2;
7401 off_t pos = 0;
7402
7403 nfile = rb_io_get_io(nfile);
7404 GetOpenFile(io, fptr);
7405 GetOpenFile(nfile, orig);
7406
7407 if (fptr == orig) return io;
7408 if (IS_PREP_STDIO(fptr)) {
7409 if ((fptr->stdio_file == stdin && !(orig->mode & FMODE_READABLE)) ||
7410 (fptr->stdio_file == stdout && !(orig->mode & FMODE_WRITABLE)) ||
7411 (fptr->stdio_file == stderr && !(orig->mode & FMODE_WRITABLE))) {
7412 rb_raise(rb_eArgError,
7413 "%s can't change access mode from \"%s\" to \"%s\"",
7414 PREP_STDIO_NAME(fptr), rb_io_fmode_modestr(fptr->mode),
7415 rb_io_fmode_modestr(orig->mode));
7416 }
7417 }
7418 if (fptr->mode & FMODE_WRITABLE) {
7419 if (io_fflush(fptr) < 0)
7420 rb_sys_fail_on_write(fptr);
7421 }
7422 else {
7423 flush_before_seek(fptr);
7424 }
7425 if (orig->mode & FMODE_READABLE) {
7426 pos = io_tell(orig);
7427 }
7428 if (orig->mode & FMODE_WRITABLE) {
7429 if (io_fflush(orig) < 0)
7430 rb_sys_fail_on_write(fptr);
7431 }
7432
7433 /* copy rb_io_t structure */
7434 fptr->mode = orig->mode | (fptr->mode & FMODE_PREP);
7435 fptr->pid = orig->pid;
7436 fptr->lineno = orig->lineno;
7437 if (RTEST(orig->pathv)) fptr->pathv = orig->pathv;
7438 else if (!IS_PREP_STDIO(fptr)) fptr->pathv = Qnil;
7439 fptr_copy_finalizer(fptr, orig);
7440
7441 fd = fptr->fd;
7442 fd2 = orig->fd;
7443 if (fd != fd2) {
7444 if (IS_PREP_STDIO(fptr) || fd <= 2 || !fptr->stdio_file) {
7445 /* need to keep FILE objects of stdin, stdout and stderr */
7446 if (rb_cloexec_dup2(fd2, fd) < 0)
7447 rb_sys_fail_path(orig->pathv);
7448 rb_update_max_fd(fd);
7449 }
7450 else {
7451 fclose(fptr->stdio_file);
7452 fptr->stdio_file = 0;
7453 fptr->fd = -1;
7454 if (rb_cloexec_dup2(fd2, fd) < 0)
7455 rb_sys_fail_path(orig->pathv);
7456 rb_update_max_fd(fd);
7457 fptr->fd = fd;
7458 }
7459 rb_thread_fd_close(fd);
7460 if ((orig->mode & FMODE_READABLE) && pos >= 0) {
7461 if (io_seek(fptr, pos, SEEK_SET) < 0 && errno) {
7462 rb_sys_fail_path(fptr->pathv);
7463 }
7464 if (io_seek(orig, pos, SEEK_SET) < 0 && errno) {
7465 rb_sys_fail_path(orig->pathv);
7466 }
7467 }
7468 }
7469
7470 if (fptr->mode & FMODE_BINMODE) {
7471 rb_io_binmode(io);
7472 }
7473
7474 RBASIC_SET_CLASS(io, rb_obj_class(nfile));
7475 return io;
7476}
7477
7478#ifdef _WIN32
7479int rb_freopen(VALUE fname, const char *mode, FILE *fp);
7480#else
7481static int
7482rb_freopen(VALUE fname, const char *mode, FILE *fp)
7483{
7484 if (!freopen(RSTRING_PTR(fname), mode, fp)) {
7485 RB_GC_GUARD(fname);
7486 return errno;
7487 }
7488 return 0;
7489}
7490#endif
7491
7492/*
7493 * call-seq:
7494 * ios.reopen(other_IO) -> ios
7495 * ios.reopen(path, mode [, opt]) -> ios
7496 *
7497 * Reassociates <em>ios</em> with the I/O stream given in
7498 * <i>other_IO</i> or to a new stream opened on <i>path</i>. This may
7499 * dynamically change the actual class of this stream.
7500 * The +mode+ and +opt+ parameters accept the same values as IO.open.
7501 *
7502 * f1 = File.new("testfile")
7503 * f2 = File.new("testfile")
7504 * f2.readlines[0] #=> "This is line one\n"
7505 * f2.reopen(f1) #=> #<File:testfile>
7506 * f2.readlines[0] #=> "This is line one\n"
7507 */
7508
7509static VALUE
7510rb_io_reopen(int argc, VALUE *argv, VALUE file)
7511{
7512 VALUE fname, nmode, opt;
7513 int oflags;
7514 rb_io_t *fptr;
7515
7516 if (rb_scan_args(argc, argv, "11:", &fname, &nmode, &opt) == 1) {
7517 VALUE tmp = rb_io_check_io(fname);
7518 if (!NIL_P(tmp)) {
7519 return io_reopen(file, tmp);
7520 }
7521 }
7522
7523 FilePathValue(fname);
7524 rb_io_taint_check(file);
7525 fptr = RFILE(file)->fptr;
7526 if (!fptr) {
7527 fptr = RFILE(file)->fptr = ZALLOC(rb_io_t);
7528 }
7529
7530 if (!NIL_P(nmode) || !NIL_P(opt)) {
7531 int fmode;
7532 convconfig_t convconfig;
7533
7534 rb_io_extract_modeenc(&nmode, 0, opt, &oflags, &fmode, &convconfig);
7535 if (IS_PREP_STDIO(fptr) &&
7536 ((fptr->mode & FMODE_READWRITE) & (fmode & FMODE_READWRITE)) !=
7537 (fptr->mode & FMODE_READWRITE)) {
7538 rb_raise(rb_eArgError,
7539 "%s can't change access mode from \"%s\" to \"%s\"",
7540 PREP_STDIO_NAME(fptr), rb_io_fmode_modestr(fptr->mode),
7541 rb_io_fmode_modestr(fmode));
7542 }
7543 fptr->mode = fmode;
7544 fptr->encs = convconfig;
7545 }
7546 else {
7547 oflags = rb_io_fmode_oflags(fptr->mode);
7548 }
7549
7550 fptr->pathv = fname;
7551 if (fptr->fd < 0) {
7552 fptr->fd = rb_sysopen(fptr->pathv, oflags, 0666);
7553 fptr->stdio_file = 0;
7554 return file;
7555 }
7556
7557 if (fptr->mode & FMODE_WRITABLE) {
7558 if (io_fflush(fptr) < 0)
7559 rb_sys_fail_on_write(fptr);
7560 }
7561 fptr->rbuf.off = fptr->rbuf.len = 0;
7562
7563 if (fptr->stdio_file) {
7564 int e = rb_freopen(rb_str_encode_ospath(fptr->pathv),
7565 rb_io_oflags_modestr(oflags),
7566 fptr->stdio_file);
7567 if (e) rb_syserr_fail_path(e, fptr->pathv);
7568 fptr->fd = fileno(fptr->stdio_file);
7569 rb_fd_fix_cloexec(fptr->fd);
7570#ifdef USE_SETVBUF
7571 if (setvbuf(fptr->stdio_file, NULL, _IOFBF, 0) != 0)
7572 rb_warn("setvbuf() can't be honoured for %"PRIsVALUE, fptr->pathv);
7573#endif
7574 if (fptr->stdio_file == stderr) {
7575 if (setvbuf(fptr->stdio_file, NULL, _IONBF, BUFSIZ) != 0)
7576 rb_warn("setvbuf() can't be honoured for %"PRIsVALUE, fptr->pathv);
7577 }
7578 else if (fptr->stdio_file == stdout && isatty(fptr->fd)) {
7579 if (setvbuf(fptr->stdio_file, NULL, _IOLBF, BUFSIZ) != 0)
7580 rb_warn("setvbuf() can't be honoured for %"PRIsVALUE, fptr->pathv);
7581 }
7582 }
7583 else {
7584 int tmpfd = rb_sysopen(fptr->pathv, oflags, 0666);
7585 int err = 0;
7586 if (rb_cloexec_dup2(tmpfd, fptr->fd) < 0)
7587 err = errno;
7588 (void)close(tmpfd);
7589 if (err) {
7590 rb_syserr_fail_path(err, fptr->pathv);
7591 }
7592 }
7593
7594 return file;
7595}
7596
7597/* :nodoc: */
7598static VALUE
7599rb_io_init_copy(VALUE dest, VALUE io)
7600{
7601 rb_io_t *fptr, *orig;
7602 int fd;
7603 VALUE write_io;
7604 off_t pos;
7605
7606 io = rb_io_get_io(io);
7607 if (!OBJ_INIT_COPY(dest, io)) return dest;
7608 GetOpenFile(io, orig);
7609 MakeOpenFile(dest, fptr);
7610
7611 rb_io_flush(io);
7612
7613 /* copy rb_io_t structure */
7614 fptr->mode = orig->mode & ~FMODE_PREP;
7615 fptr->encs = orig->encs;
7616 fptr->pid = orig->pid;
7617 fptr->lineno = orig->lineno;
7618 if (!NIL_P(orig->pathv)) fptr->pathv = orig->pathv;
7619 fptr_copy_finalizer(fptr, orig);
7620
7621 fd = ruby_dup(orig->fd);
7622 fptr->fd = fd;
7623 pos = io_tell(orig);
7624 if (0 <= pos)
7625 io_seek(fptr, pos, SEEK_SET);
7626 if (fptr->mode & FMODE_BINMODE) {
7627 rb_io_binmode(dest);
7628 }
7629
7630 write_io = GetWriteIO(io);
7631 if (io != write_io) {
7632 write_io = rb_obj_dup(write_io);
7633 fptr->tied_io_for_writing = write_io;
7634 rb_ivar_set(dest, rb_intern("@tied_io_for_writing"), write_io);
7635 }
7636
7637 return dest;
7638}
7639
7640/*
7641 * call-seq:
7642 * ios.printf(format_string [, obj, ...]) -> nil
7643 *
7644 * Formats and writes to <em>ios</em>, converting parameters under
7645 * control of the format string. See Kernel#sprintf for details.
7646 */
7647
7648 VALUE
7649 rb_io_printf(int argc, const VALUE *argv, VALUE out)
7650{
7651 rb_io_write(out, rb_f_sprintf(argc, argv));
7652 return Qnil;
7653}
7654
7655/*
7656 * call-seq:
7657 * printf(io, string [, obj ... ]) -> nil
7658 * printf(string [, obj ... ]) -> nil
7659 *
7660 * Equivalent to:
7661 * io.write(sprintf(string, obj, ...))
7662 * or
7663 * $stdout.write(sprintf(string, obj, ...))
7664 */
7665
7666static VALUE
7667rb_f_printf(int argc, VALUE *argv, VALUE _)
7668{
7669 VALUE out;
7670
7671 if (argc == 0) return Qnil;
7672 if (RB_TYPE_P(argv[0], T_STRING)) {
7673 out = rb_ractor_stdout();
7674 }
7675 else {
7676 out = argv[0];
7677 argv++;
7678 argc--;
7679 }
7680 rb_io_write(out, rb_f_sprintf(argc, argv));
7681
7682 return Qnil;
7683}
7684
7685static void
7686deprecated_str_setter(VALUE val, ID id, VALUE *var)
7687{
7688 rb_str_setter(val, id, &val);
7689 if (!NIL_P(val)) {
7690 rb_warn_deprecated("`%s'", NULL, rb_id2name(id));
7691 }
7692 *var = val;
7693}
7694
7695/*
7696 * call-seq:
7697 * ios.print -> nil
7698 * ios.print(obj, ...) -> nil
7699 *
7700 * Writes the given object(s) to <em>ios</em>. Returns +nil+.
7701 *
7702 * The stream must be opened for writing.
7703 * Each given object that isn't a string will be converted by calling
7704 * its <code>to_s</code> method.
7705 * When called without arguments, prints the contents of <code>$_</code>.
7706 *
7707 * If the output field separator (<code>$,</code>) is not +nil+,
7708 * it is inserted between objects.
7709 * If the output record separator (<code>$\</code>) is not +nil+,
7710 * it is appended to the output.
7711 *
7712 * $stdout.print("This is ", 100, " percent.\n")
7713 *
7714 * <em>produces:</em>
7715 *
7716 * This is 100 percent.
7717 */
7718
7719 VALUE
7720 rb_io_print(int argc, const VALUE *argv, VALUE out)
7721{
7722 int i;
7723 VALUE line;
7724
7725 /* if no argument given, print `$_' */
7726 if (argc == 0) {
7727 argc = 1;
7728 line = rb_lastline_get();
7729 argv = &line;
7730 }
7731 if (argc > 1 && !NIL_P(rb_output_fs)) {
7732 rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "$, is set to non-nil value");
7733 }
7734 for (i=0; i<argc; i++) {
7735 if (!NIL_P(rb_output_fs) && i>0) {
7736 rb_io_write(out, rb_output_fs);
7737 }
7738 rb_io_write(out, argv[i]);
7739 }
7740 if (argc > 0 && !NIL_P(rb_output_rs)) {
7741 rb_io_write(out, rb_output_rs);
7742 }
7743
7744 return Qnil;
7745}
7746
7747/*
7748 * call-seq:
7749 * print(obj, ...) -> nil
7750 *
7751 * Prints each object in turn to <code>$stdout</code>. If the output
7752 * field separator (<code>$,</code>) is not +nil+, its
7753 * contents will appear between each field. If the output record
7754 * separator (<code>$\</code>) is not +nil+, it will be
7755 * appended to the output. If no arguments are given, prints
7756 * <code>$_</code>. Objects that aren't strings will be converted by
7757 * calling their <code>to_s</code> method.
7758 *
7759 * print "cat", [1,2,3], 99, "\n"
7760 * $, = ", "
7761 * $\ = "\n"
7762 * print "cat", [1,2,3], 99
7763 *
7764 * <em>produces:</em>
7765 *
7766 * cat12399
7767 * cat, 1, 2, 3, 99
7768 */
7769
7770static VALUE
7771rb_f_print(int argc, const VALUE *argv, VALUE _)
7772{
7773 rb_io_print(argc, argv, rb_ractor_stdout());
7774 return Qnil;
7775}
7776
7777/*
7778 * call-seq:
7779 * ios.putc(obj) -> obj
7780 *
7781 * If <i>obj</i> is Numeric, write the character whose code is the
7782 * least-significant byte of <i>obj</i>. If <i>obj</i> is String,
7783 * write the first character of <i>obj</i> to <em>ios</em>. Otherwise,
7784 * raise TypeError.
7785 *
7786 * $stdout.putc "A"
7787 * $stdout.putc 65
7788 *
7789 * <em>produces:</em>
7790 *
7791 * AA
7792 */
7793
7794static VALUE
7795rb_io_putc(VALUE io, VALUE ch)
7796{
7797 VALUE str;
7798 if (RB_TYPE_P(ch, T_STRING)) {
7799 str = rb_str_substr(ch, 0, 1);
7800 }
7801 else {
7802 char c = NUM2CHR(ch);
7803 str = rb_str_new(&c, 1);
7804 }
7805 rb_io_write(io, str);
7806 return ch;
7807}
7808
7809/*
7810 * call-seq:
7811 * putc(int) -> int
7812 *
7813 * Equivalent to:
7814 *
7815 * $stdout.putc(int)
7816 *
7817 * Refer to the documentation for IO#putc for important information regarding
7818 * multi-byte characters.
7819 */
7820
7821static VALUE
7822rb_f_putc(VALUE recv, VALUE ch)
7823{
7824 VALUE r_stdout = rb_ractor_stdout();
7825 if (recv == r_stdout) {
7826 return rb_io_putc(recv, ch);
7827 }
7828 return rb_funcallv(r_stdout, rb_intern("putc"), 1, &ch);
7829}
7830
7831
7832int
7833rb_str_end_with_asciichar(VALUE str, int c)
7834{
7835 long len = RSTRING_LEN(str);
7836 const char *ptr = RSTRING_PTR(str);
7837 rb_encoding *enc = rb_enc_from_index(ENCODING_GET(str));
7838 int n;
7839
7840 if (len == 0) return 0;
7841 if ((n = rb_enc_mbminlen(enc)) == 1) {
7842 return ptr[len - 1] == c;
7843 }
7844 return rb_enc_ascget(ptr + ((len - 1) / n) * n, ptr + len, &n, enc) == c;
7845}
7846
7847static VALUE
7848io_puts_ary(VALUE ary, VALUE out, int recur)
7849{
7850 VALUE tmp;
7851 long i;
7852
7853 if (recur) {
7854 tmp = rb_str_new2("[...]");
7855 rb_io_puts(1, &tmp, out);
7856 return Qtrue;
7857 }
7858 ary = rb_check_array_type(ary);
7859 if (NIL_P(ary)) return Qfalse;
7860 for (i=0; i<RARRAY_LEN(ary); i++) {
7861 tmp = RARRAY_AREF(ary, i);
7862 rb_io_puts(1, &tmp, out);
7863 }
7864 return Qtrue;
7865}
7866
7867/*
7868 * call-seq:
7869 * ios.puts(obj, ...) -> nil
7870 *
7871 * Writes the given object(s) to <em>ios</em>.
7872 * Writes a newline after any that do not already end
7873 * with a newline sequence. Returns +nil+.
7874 *
7875 * The stream must be opened for writing.
7876 * If called with an array argument, writes each element on a new line.
7877 * Each given object that isn't a string or array will be converted
7878 * by calling its +to_s+ method.
7879 * If called without arguments, outputs a single newline.
7880 *
7881 * $stdout.puts("this", "is", ["a", "test"])
7882 *
7883 * <em>produces:</em>
7884 *
7885 * this
7886 * is
7887 * a
7888 * test
7889 *
7890 * Note that +puts+ always uses newlines and is not affected
7891 * by the output record separator (<code>$\</code>).
7892 */
7893
7894 VALUE
7895 rb_io_puts(int argc, const VALUE *argv, VALUE out)
7896{
7897 int i, n;
7898 VALUE line, args[2];
7899
7900 /* if no argument given, print newline. */
7901 if (argc == 0) {
7902 rb_io_write(out, rb_default_rs);
7903 return Qnil;
7904 }
7905 for (i=0; i<argc; i++) {
7906 if (RB_TYPE_P(argv[i], T_STRING)) {
7907 line = argv[i];
7908 goto string;
7909 }
7910 if (rb_exec_recursive(io_puts_ary, argv[i], out)) {
7911 continue;
7912 }
7913 line = rb_obj_as_string(argv[i]);
7914 string:
7915 n = 0;
7916 args[n++] = line;
7917 if (RSTRING_LEN(line) == 0 ||
7918 !rb_str_end_with_asciichar(line, '\n')) {
7919 args[n++] = rb_default_rs;
7920 }
7921 rb_io_writev(out, n, args);
7922 }
7923
7924 return Qnil;
7925}
7926
7927/*
7928 * call-seq:
7929 * puts(obj, ...) -> nil
7930 *
7931 * Equivalent to
7932 *
7933 * $stdout.puts(obj, ...)
7934 */
7935
7936static VALUE
7937rb_f_puts(int argc, VALUE *argv, VALUE recv)
7938{
7939 VALUE r_stdout = rb_ractor_stdout();
7940 if (recv == r_stdout) {
7941 return rb_io_puts(argc, argv, recv);
7942 }
7943 return rb_funcallv(r_stdout, rb_intern("puts"), argc, argv);
7944}
7945
7946static VALUE
7947rb_p_write(VALUE str)
7948{
7949 VALUE args[2];
7950 args[0] = str;
7951 args[1] = rb_default_rs;
7952 VALUE r_stdout = rb_ractor_stdout();
7953 if (RB_TYPE_P(r_stdout, T_FILE) &&
7954 rb_method_basic_definition_p(CLASS_OF(r_stdout), id_write)) {
7955 io_writev(2, args, r_stdout);
7956 }
7957 else {
7958 rb_io_writev(r_stdout, 2, args);
7959 }
7960 return Qnil;
7961}
7962
7963void
7964 rb_p(VALUE obj) /* for debug print within C code */
7965{
7966 rb_p_write(rb_obj_as_string(rb_inspect(obj)));
7967}
7968
7969static VALUE
7970rb_p_result(int argc, const VALUE *argv)
7971{
7972 VALUE ret = Qnil;
7973
7974 if (argc == 1) {
7975 ret = argv[0];
7976 }
7977 else if (argc > 1) {
7978 ret = rb_ary_new4(argc, argv);
7979 }
7980 VALUE r_stdout = rb_ractor_stdout();
7981 if (RB_TYPE_P(r_stdout, T_FILE)) {
7982 rb_io_flush(r_stdout);
7983 }
7984 return ret;
7985}
7986
7987/*
7988 * call-seq:
7989 * p(obj) -> obj
7990 * p(obj1, obj2, ...) -> [obj, ...]
7991 * p() -> nil
7992 *
7993 * For each object, directly writes _obj_.+inspect+ followed by a
7994 * newline to the program's standard output.
7995 *
7996 * S = Struct.new(:name, :state)
7997 * s = S['dave', 'TX']
7998 * p s
7999 *
8000 * <em>produces:</em>
8001 *
8002 * #<S name="dave", state="TX">
8003 */
8004
8005static VALUE
8006rb_f_p(int argc, VALUE *argv, VALUE self)
8007{
8008 int i;
8009 for (i=0; i<argc; i++) {
8010 VALUE inspected = rb_obj_as_string(rb_inspect(argv[i]));
8011 rb_uninterruptible(rb_p_write, inspected);
8012 }
8013 return rb_p_result(argc, argv);
8014}
8015
8016/*
8017 * call-seq:
8018 * obj.display(port=$>) -> nil
8019 *
8020 * Prints <i>obj</i> on the given port (default <code>$></code>).
8021 * Equivalent to:
8022 *
8023 * def display(port=$>)
8024 * port.write self
8025 * nil
8026 * end
8027 *
8028 * For example:
8029 *
8030 * 1.display
8031 * "cat".display
8032 * [ 4, 5, 6 ].display
8033 * puts
8034 *
8035 * <em>produces:</em>
8036 *
8037 * 1cat[4, 5, 6]
8038 */
8039
8040static VALUE
8041rb_obj_display(int argc, VALUE *argv, VALUE self)
8042{
8043 VALUE out;
8044
8045 out = (!rb_check_arity(argc, 0, 1) ? rb_ractor_stdout() : argv[0]);
8046 rb_io_write(out, self);
8047
8048 return Qnil;
8049}
8050
8051static int
8052rb_stderr_to_original_p(void)
8053{
8054 return (rb_ractor_stderr() == orig_stderr || RFILE(orig_stderr)->fptr->fd < 0);
8055}
8056
8057void
8058 rb_write_error2(const char *mesg, long len)
8059{
8060 if (rb_stderr_to_original_p()) {
8061#ifdef _WIN32
8062 if (isatty(fileno(stderr))) {
8063 if (rb_w32_write_console(rb_str_new(mesg, len), fileno(stderr)) > 0) return;
8064 }
8065#endif
8066 if (fwrite(mesg, sizeof(char), (size_t)len, stderr) < (size_t)len) {
8067 /* failed to write to stderr, what can we do? */
8068 return;
8069 }
8070 }
8071 else {
8072 rb_io_write(rb_ractor_stderr(), rb_str_new(mesg, len));
8073 }
8074}
8075
8076void
8077 rb_write_error(const char *mesg)
8078{
8079 rb_write_error2(mesg, strlen(mesg));
8080}
8081
8082void
8083 rb_write_error_str(VALUE mesg)
8084{
8085 /* a stopgap measure for the time being */
8086 if (rb_stderr_to_original_p()) {
8087 size_t len = (size_t)RSTRING_LEN(mesg);
8088#ifdef _WIN32
8089 if (isatty(fileno(stderr))) {
8090 if (rb_w32_write_console(mesg, fileno(stderr)) > 0) return;
8091 }
8092#endif
8093 if (fwrite(RSTRING_PTR(mesg), sizeof(char), len, stderr) < len) {
8094 RB_GC_GUARD(mesg);
8095 return;
8096 }
8097 }
8098 else {
8099 /* may unlock GVL, and */
8100 rb_io_write(rb_ractor_stderr(), mesg);
8101 }
8102}
8103
8104int
8105 rb_stderr_tty_p(void)
8106{
8107 if (rb_stderr_to_original_p())
8108 return isatty(fileno(stderr));
8109 return 0;
8110}
8111
8112static void
8113must_respond_to(ID mid, VALUE val, ID id)
8114{
8115 if (!rb_respond_to(val, mid)) {
8116 rb_raise(rb_eTypeError, "%"PRIsVALUE" must have %"PRIsVALUE" method, %"PRIsVALUE" given",
8117 rb_id2str(id), rb_id2str(mid),
8118 rb_obj_class(val));
8119 }
8120}
8121
8122static void
8123stdin_setter(VALUE val, ID id, VALUE *ptr)
8124{
8125 rb_ractor_stdin_set(val);
8126}
8127
8128static VALUE
8129stdin_getter(ID id, VALUE *ptr)
8130{
8131 return rb_ractor_stdin();
8132}
8133
8134static void
8135stdout_setter(VALUE val, ID id, VALUE *ptr)
8136{
8137 must_respond_to(id_write, val, id);
8138 rb_ractor_stdout_set(val);
8139}
8140
8141static VALUE
8142stdout_getter(ID id, VALUE *ptr)
8143{
8144 return rb_ractor_stdout();
8145}
8146
8147static void
8148stderr_setter(VALUE val, ID id, VALUE *ptr)
8149{
8150 must_respond_to(id_write, val, id);
8151 rb_ractor_stderr_set(val);
8152}
8153
8154static VALUE
8155stderr_getter(ID id, VALUE *ptr)
8156{
8157 return rb_ractor_stderr();
8158}
8159
8160static VALUE
8161prep_io(int fd, int fmode, VALUE klass, const char *path)
8162{
8163 rb_io_t *fp;
8164 VALUE io = io_alloc(klass);
8165
8166 MakeOpenFile(io, fp);
8167 fp->self = io;
8168 fp->fd = fd;
8169 fp->mode = fmode;
8170 if (!io_check_tty(fp)) {
8171#ifdef __CYGWIN__
8172 fp->mode |= FMODE_BINMODE;
8173 setmode(fd, O_BINARY);
8174#endif
8175 }
8176 if (path) fp->pathv = rb_obj_freeze(rb_str_new_cstr(path));
8177 rb_update_max_fd(fd);
8178
8179 return io;
8180}
8181
8182 VALUE
8183 rb_io_fdopen(int fd, int oflags, const char *path)
8184{
8185 VALUE klass = rb_cIO;
8186
8187 if (path && strcmp(path, "-")) klass = rb_cFile;
8188 return prep_io(fd, rb_io_oflags_fmode(oflags), klass, path);
8189}
8190
8191static VALUE
8192prep_stdio(FILE *f, int fmode, VALUE klass, const char *path)
8193{
8194 rb_io_t *fptr;
8195 VALUE io = prep_io(fileno(f), fmode|FMODE_PREP|DEFAULT_TEXTMODE, klass, path);
8196
8197 GetOpenFile(io, fptr);
8198 fptr->encs.ecflags |= ECONV_DEFAULT_NEWLINE_DECORATOR;
8199#ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
8200 fptr->encs.ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
8201 if (fmode & FMODE_READABLE) {
8202 fptr->encs.ecflags |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;
8203 }
8204#endif
8205 fptr->stdio_file = f;
8206
8207 return io;
8208}
8209
8210 VALUE
8211rb_io_prep_stdin(void)
8212{
8213 return prep_stdio(stdin, FMODE_READABLE, rb_cIO, "<STDIN>");
8214}
8215
8216 VALUE
8217rb_io_prep_stdout(void)
8218{
8219 return prep_stdio(stdout, FMODE_WRITABLE|FMODE_SIGNAL_ON_EPIPE, rb_cIO, "<STDOUT>");
8220}
8221
8222 VALUE
8223rb_io_prep_stderr(void)
8224{
8225 return prep_stdio(stderr, FMODE_WRITABLE|FMODE_SYNC, rb_cIO, "<STDERR>");
8226}
8227
8228 FILE *
8229 rb_io_stdio_file(rb_io_t *fptr)
8230{
8231 if (!fptr->stdio_file) {
8232 int oflags = rb_io_fmode_oflags(fptr->mode) & ~O_EXCL;
8233 fptr->stdio_file = rb_fdopen(fptr->fd, rb_io_oflags_modestr(oflags));
8234 }
8235 return fptr->stdio_file;
8236}
8237
8238static inline void
8239rb_io_buffer_init(rb_io_buffer_t *buf)
8240{
8241 buf->ptr = NULL;
8242 buf->off = 0;
8243 buf->len = 0;
8244 buf->capa = 0;
8245}
8246
8247static inline rb_io_t *
8248rb_io_fptr_new(void)
8249{
8250 rb_io_t *fp = ALLOC(rb_io_t);
8251 fp->self = Qnil;
8252 fp->fd = -1;
8253 fp->stdio_file = NULL;
8254 fp->mode = 0;
8255 fp->pid = 0;
8256 fp->lineno = 0;
8257 fp->pathv = Qnil;
8258 fp->finalize = 0;
8259 rb_io_buffer_init(&fp->wbuf);
8260 rb_io_buffer_init(&fp->rbuf);
8261 rb_io_buffer_init(&fp->cbuf);
8262 fp->readconv = NULL;
8263 fp->writeconv = NULL;
8264 fp->writeconv_asciicompat = Qnil;
8265 fp->writeconv_pre_ecflags = 0;
8266 fp->writeconv_pre_ecopts = Qnil;
8267 fp->writeconv_initialized = 0;
8268 fp->tied_io_for_writing = 0;
8269 fp->encs.enc = NULL;
8270 fp->encs.enc2 = NULL;
8271 fp->encs.ecflags = 0;
8272 fp->encs.ecopts = Qnil;
8273 fp->write_lock = 0;
8274 return fp;
8275}
8276
8277 rb_io_t *
8278 rb_io_make_open_file(VALUE obj)
8279{
8280 rb_io_t *fp = 0;
8281
8282 Check_Type(obj, T_FILE);
8283 if (RFILE(obj)->fptr) {
8284 rb_io_close(obj);
8285 rb_io_fptr_finalize(RFILE(obj)->fptr);
8286 RFILE(obj)->fptr = 0;
8287 }
8288 fp = rb_io_fptr_new();
8289 fp->self = obj;
8290 RFILE(obj)->fptr = fp;
8291 return fp;
8292}
8293
8294/*
8295 * call-seq:
8296 * IO.new(fd [, mode] [, opt]) -> io
8297 *
8298 * Returns a new IO object (a stream) for the given integer file descriptor
8299 * +fd+ and +mode+ string. +opt+ may be used to specify parts of +mode+ in a
8300 * more readable fashion. See also IO.sysopen and IO.for_fd.
8301 *
8302 * IO.new is called by various File and IO opening methods such as IO::open,
8303 * Kernel#open, and File::open.
8304 *
8305 * === Open Mode
8306 *
8307 * When +mode+ is an integer it must be combination of the modes defined in
8308 * File::Constants (+File::RDONLY+, <code>File::WRONLY|File::CREAT</code>).
8309 * See the open(2) man page for more information.
8310 *
8311 * When +mode+ is a string it must be in one of the following forms:
8312 *
8313 * fmode
8314 * fmode ":" ext_enc
8315 * fmode ":" ext_enc ":" int_enc
8316 * fmode ":" "BOM|UTF-*"
8317 *
8318 * +fmode+ is an IO open mode string, +ext_enc+ is the external encoding for
8319 * the IO and +int_enc+ is the internal encoding.
8320 *
8321 * ==== IO Open Mode
8322 *
8323 * Ruby allows the following open modes:
8324 *
8325 * "r" Read-only, starts at beginning of file (default mode).
8326 *
8327 * "r+" Read-write, starts at beginning of file.
8328 *
8329 * "w" Write-only, truncates existing file
8330 * to zero length or creates a new file for writing.
8331 *
8332 * "w+" Read-write, truncates existing file to zero length
8333 * or creates a new file for reading and writing.
8334 *
8335 * "a" Write-only, each write call appends data at end of file.
8336 * Creates a new file for writing if file does not exist.
8337 *
8338 * "a+" Read-write, each write call appends data at end of file.
8339 * Creates a new file for reading and writing if file does
8340 * not exist.
8341 *
8342 * The following modes must be used separately, and along with one or more of
8343 * the modes seen above.
8344 *
8345 * "b" Binary file mode
8346 * Suppresses EOL <-> CRLF conversion on Windows. And
8347 * sets external encoding to ASCII-8BIT unless explicitly
8348 * specified.
8349 *
8350 * "t" Text file mode
8351 *
8352 * The exclusive access mode ("x") can be used together with "w" to ensure
8353 * the file is created. Errno::EEXIST is raised when it already exists.
8354 * It may not be supported with all kinds of streams (e.g. pipes).
8355 *
8356 * When the open mode of original IO is read only, the mode cannot be
8357 * changed to be writable. Similarly, the open mode cannot be changed from
8358 * write only to readable.
8359 *
8360 * When such a change is attempted the error is raised in different locations
8361 * according to the platform.
8362 *
8363 * === IO Encoding
8364 *
8365 * When +ext_enc+ is specified, strings read will be tagged by the encoding
8366 * when reading, and strings output will be converted to the specified
8367 * encoding when writing.
8368 *
8369 * When +ext_enc+ and +int_enc+ are specified read strings will be converted
8370 * from +ext_enc+ to +int_enc+ upon input, and written strings will be
8371 * converted from +int_enc+ to +ext_enc+ upon output. See Encoding for
8372 * further details of transcoding on input and output.
8373 *
8374 * If "BOM|UTF-8", "BOM|UTF-16LE" or "BOM|UTF16-BE" are used, Ruby checks for
8375 * a Unicode BOM in the input document to help determine the encoding. For
8376 * UTF-16 encodings the file open mode must be binary. When present, the BOM
8377 * is stripped and the external encoding from the BOM is used. When the BOM
8378 * is missing the given Unicode encoding is used as +ext_enc+. (The BOM-set
8379 * encoding option is case insensitive, so "bom|utf-8" is also valid.)
8380 *
8381 * === Options
8382 *
8383 * +opt+ can be used instead of +mode+ for improved readability. The
8384 * following keys are supported:
8385 *
8386 * :mode ::
8387 * Same as +mode+ parameter
8388 *
8389 * :flags ::
8390 * Specifies file open flags as integer.
8391 * If +mode+ parameter is given, this parameter will be bitwise-ORed.
8392 *
8393 * :\external_encoding ::
8394 * External encoding for the IO.
8395 *
8396 * :\internal_encoding ::
8397 * Internal encoding for the IO. "-" is a synonym for the default internal
8398 * encoding.
8399 *
8400 * If the value is +nil+ no conversion occurs.
8401 *
8402 * :encoding ::
8403 * Specifies external and internal encodings as "extern:intern".
8404 *
8405 * :textmode ::
8406 * If the value is truth value, same as "t" in argument +mode+.
8407 *
8408 * :binmode ::
8409 * If the value is truth value, same as "b" in argument +mode+.
8410 *
8411 * :autoclose ::
8412 * If the value is +false+, the +fd+ will be kept open after this IO
8413 * instance gets finalized.
8414 *
8415 * Also, +opt+ can have same keys in String#encode for controlling conversion
8416 * between the external encoding and the internal encoding.
8417 *
8418 * === Example 1
8419 *
8420 * fd = IO.sysopen("/dev/tty", "w")
8421 * a = IO.new(fd,"w")
8422 * $stderr.puts "Hello"
8423 * a.puts "World"
8424 *
8425 * Produces:
8426 *
8427 * Hello
8428 * World
8429 *
8430 * === Example 2
8431 *
8432 * require 'fcntl'
8433 *
8434 * fd = STDERR.fcntl(Fcntl::F_DUPFD)
8435 * io = IO.new(fd, mode: 'w:UTF-16LE', cr_newline: true)
8436 * io.puts "Hello, World!"
8437 *
8438 * fd = STDERR.fcntl(Fcntl::F_DUPFD)
8439 * io = IO.new(fd, mode: 'w', cr_newline: true,
8440 * external_encoding: Encoding::UTF_16LE)
8441 * io.puts "Hello, World!"
8442 *
8443 * Both of above print "Hello, World!" in UTF-16LE to standard error output
8444 * with converting EOL generated by #puts to CR.
8445 */
8446
8447static VALUE
8448rb_io_initialize(int argc, VALUE *argv, VALUE io)
8449{
8450 VALUE fnum, vmode;
8451 rb_io_t *fp;
8452 int fd, fmode, oflags = O_RDONLY;
8453 convconfig_t convconfig;
8454 VALUE opt;
8455#if defined(HAVE_FCNTL) && defined(F_GETFL)
8456 int ofmode;
8457#else
8458 struct stat st;
8459#endif
8460
8461
8462 argc = rb_scan_args(argc, argv, "11:", &fnum, &vmode, &opt);
8463 rb_io_extract_modeenc(&vmode, 0, opt, &oflags, &fmode, &convconfig);
8464
8465 fd = NUM2INT(fnum);
8466 if (rb_reserved_fd_p(fd)) {
8467 rb_raise(rb_eArgError, "The given fd is not accessible because RubyVM reserves it");
8468 }
8469#if defined(HAVE_FCNTL) && defined(F_GETFL)
8470 oflags = fcntl(fd, F_GETFL);
8471 if (oflags == -1) rb_sys_fail(0);
8472#else
8473 if (fstat(fd, &st) < 0) rb_sys_fail(0);
8474#endif
8475 rb_update_max_fd(fd);
8476#if defined(HAVE_FCNTL) && defined(F_GETFL)
8477 ofmode = rb_io_oflags_fmode(oflags);
8478 if (NIL_P(vmode)) {
8479 fmode = ofmode;
8480 }
8481 else if ((~ofmode & fmode) & FMODE_READWRITE) {
8482 VALUE error = INT2FIX(EINVAL);
8483 rb_exc_raise(rb_class_new_instance(1, &error, rb_eSystemCallError));
8484 }
8485#endif
8486 if (!NIL_P(opt) && rb_hash_aref(opt, sym_autoclose) == Qfalse) {
8487 fmode |= FMODE_PREP;
8488 }
8489 MakeOpenFile(io, fp);
8490 fp->self = io;
8491 fp->fd = fd;
8492 fp->mode = fmode;
8493 fp->encs = convconfig;
8494 clear_codeconv(fp);
8495 io_check_tty(fp);
8496 if (fileno(stdin) == fd)
8497 fp->stdio_file = stdin;
8498 else if (fileno(stdout) == fd)
8499 fp->stdio_file = stdout;
8500 else if (fileno(stderr) == fd)
8501 fp->stdio_file = stderr;
8502
8503 if (fmode & FMODE_SETENC_BY_BOM) io_set_encoding_by_bom(io);
8504 return io;
8505}
8506
8507/*
8508 * call-seq:
8509 * ios.set_encoding_by_bom -> encoding or nil
8510 *
8511 * Checks if +ios+ starts with a BOM, and then consumes it and sets
8512 * the external encoding. Returns the result encoding if found, or
8513 * nil. If +ios+ is not binmode or its encoding has been set
8514 * already, an exception will be raised.
8515 *
8516 * File.write("bom.txt", "\u{FEFF}abc")
8517 * ios = File.open("bom.txt", "rb")
8518 * ios.set_encoding_by_bom #=> #<Encoding:UTF-8>
8519 *
8520 * File.write("nobom.txt", "abc")
8521 * ios = File.open("nobom.txt", "rb")
8522 * ios.set_encoding_by_bom #=> nil
8523 */
8524
8525static VALUE
8526rb_io_set_encoding_by_bom(VALUE io)
8527{
8528 rb_io_t *fptr;
8529
8530 GetOpenFile(io, fptr);
8531 if (!(fptr->mode & FMODE_BINMODE)) {
8532 rb_raise(rb_eArgError, "ASCII incompatible encoding needs binmode");
8533 }
8534 if (fptr->encs.enc2) {
8535 rb_raise(rb_eArgError, "encoding conversion is set");
8536 }
8537 else if (fptr->encs.enc && fptr->encs.enc != rb_ascii8bit_encoding()) {
8538 rb_raise(rb_eArgError, "encoding is set to %s already",
8539 rb_enc_name(fptr->encs.enc));
8540 }
8541 if (!io_set_encoding_by_bom(io)) return Qnil;
8542 return rb_enc_from_encoding(fptr->encs.enc);
8543}
8544
8545/*
8546 * call-seq:
8547 * File.new(filename, mode="r" [, opt]) -> file
8548 * File.new(filename [, mode [, perm]] [, opt]) -> file
8549 *
8550 * Opens the file named by +filename+ according to the given +mode+ and
8551 * returns a new File object.
8552 *
8553 * See IO.new for a description of +mode+ and +opt+.
8554 *
8555 * If a file is being created, permission bits may be given in +perm+. These
8556 * mode and permission bits are platform dependent; on Unix systems, see
8557 * open(2) and chmod(2) man pages for details.
8558 *
8559 * The new File object is buffered mode (or non-sync mode), unless
8560 * +filename+ is a tty.
8561 * See IO#flush, IO#fsync, IO#fdatasync, and IO#sync= about sync mode.
8562 *
8563 * === Examples
8564 *
8565 * f = File.new("testfile", "r")
8566 * f = File.new("newfile", "w+")
8567 * f = File.new("newfile", File::CREAT|File::TRUNC|File::RDWR, 0644)
8568 */
8569
8570static VALUE
8571rb_file_initialize(int argc, VALUE *argv, VALUE io)
8572{
8573 if (RFILE(io)->fptr) {
8574 rb_raise(rb_eRuntimeError, "reinitializing File");
8575 }
8576 if (0 < argc && argc < 3) {
8577 VALUE fd = rb_check_to_int(argv[0]);
8578
8579 if (!NIL_P(fd)) {
8580 argv[0] = fd;
8581 return rb_io_initialize(argc, argv, io);
8582 }
8583 }
8584 rb_open_file(argc, argv, io);
8585
8586 return io;
8587}
8588
8589/* :nodoc: */
8590static VALUE
8591rb_io_s_new(int argc, VALUE *argv, VALUE klass)
8592{
8593 if (rb_block_given_p()) {
8594 VALUE cname = rb_obj_as_string(klass);
8595
8596 rb_warn("%"PRIsVALUE"::new() does not take block; use %"PRIsVALUE"::open() instead",
8597 cname, cname);
8598 }
8599 return rb_class_new_instance_kw(argc, argv, klass, RB_PASS_CALLED_KEYWORDS);
8600}
8601
8602
8603/*
8604 * call-seq:
8605 * IO.for_fd(fd, mode [, opt]) -> io
8606 *
8607 * Synonym for IO.new.
8608 *
8609 */
8610
8611static VALUE
8612rb_io_s_for_fd(int argc, VALUE *argv, VALUE klass)
8613{
8614 VALUE io = rb_obj_alloc(klass);
8615 rb_io_initialize(argc, argv, io);
8616 return io;
8617}
8618
8619/*
8620 * call-seq:
8621 * ios.autoclose? -> true or false
8622 *
8623 * Returns +true+ if the underlying file descriptor of _ios_ will be
8624 * closed automatically at its finalization, otherwise +false+.
8625 */
8626
8627static VALUE
8628rb_io_autoclose_p(VALUE io)
8629{
8630 rb_io_t *fptr = RFILE(io)->fptr;
8631 rb_io_check_closed(fptr);
8632 return (fptr->mode & FMODE_PREP) ? Qfalse : Qtrue;
8633}
8634
8635/*
8636 * call-seq:
8637 * io.autoclose = bool -> true or false
8638 *
8639 * Sets auto-close flag.
8640 *
8641 * f = open("/dev/null")
8642 * IO.for_fd(f.fileno)
8643 * # ...
8644 * f.gets # may cause Errno::EBADF
8645 *
8646 * f = open("/dev/null")
8647 * IO.for_fd(f.fileno).autoclose = false
8648 * # ...
8649 * f.gets # won't cause Errno::EBADF
8650 */
8651
8652static VALUE
8653rb_io_set_autoclose(VALUE io, VALUE autoclose)
8654{
8655 rb_io_t *fptr;
8656 GetOpenFile(io, fptr);
8657 if (!RTEST(autoclose))
8658 fptr->mode |= FMODE_PREP;
8659 else
8660 fptr->mode &= ~FMODE_PREP;
8661 return autoclose;
8662}
8663
8664static void
8665argf_mark(void *ptr)
8666{
8667 struct argf *p = ptr;
8668 rb_gc_mark(p->filename);
8669 rb_gc_mark(p->current_file);
8670 rb_gc_mark(p->argv);
8671 rb_gc_mark(p->inplace);
8672 rb_gc_mark(p->encs.ecopts);
8673}
8674
8675static size_t
8676argf_memsize(const void *ptr)
8677{
8678 const struct argf *p = ptr;
8679 size_t size = sizeof(*p);
8680 return size;
8681}
8682
8683static const rb_data_type_t argf_type = {
8684 "ARGF",
8685 {argf_mark, RUBY_TYPED_DEFAULT_FREE, argf_memsize},
8686 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
8687};
8688
8689static inline void
8690argf_init(struct argf *p, VALUE v)
8691{
8692 p->filename = Qnil;
8693 p->current_file = Qnil;
8694 p->lineno = 0;
8695 p->argv = v;
8696}
8697
8698static VALUE
8699argf_alloc(VALUE klass)
8700{
8701 struct argf *p;
8702 VALUE argf = TypedData_Make_Struct(klass, struct argf, &argf_type, p);
8703
8704 argf_init(p, Qnil);
8705 return argf;
8706}
8707
8708#undef rb_argv
8709
8710/* :nodoc: */
8711static VALUE
8712argf_initialize(VALUE argf, VALUE argv)
8713{
8714 memset(&ARGF, 0, sizeof(ARGF));
8715 argf_init(&ARGF, argv);
8716
8717 return argf;
8718}
8719
8720/* :nodoc: */
8721static VALUE
8722argf_initialize_copy(VALUE argf, VALUE orig)
8723{
8724 if (!OBJ_INIT_COPY(argf, orig)) return argf;
8725 ARGF = argf_of(orig);
8726 ARGF.argv = rb_obj_dup(ARGF.argv);
8727 return argf;
8728}
8729
8730/*
8731 * call-seq:
8732 * ARGF.lineno = integer -> integer
8733 *
8734 * Sets the line number of +ARGF+ as a whole to the given +Integer+.
8735 *
8736 * +ARGF+ sets the line number automatically as you read data, so normally
8737 * you will not need to set it explicitly. To access the current line number
8738 * use +ARGF.lineno+.
8739 *
8740 * For example:
8741 *
8742 * ARGF.lineno #=> 0
8743 * ARGF.readline #=> "This is line 1\n"
8744 * ARGF.lineno #=> 1
8745 * ARGF.lineno = 0 #=> 0
8746 * ARGF.lineno #=> 0
8747 */
8748static VALUE
8749argf_set_lineno(VALUE argf, VALUE val)
8750{
8751 ARGF.lineno = NUM2INT(val);
8752 ARGF.last_lineno = ARGF.lineno;
8753 return Qnil;
8754}
8755
8756/*
8757 * call-seq:
8758 * ARGF.lineno -> integer
8759 *
8760 * Returns the current line number of ARGF as a whole. This value
8761 * can be set manually with +ARGF.lineno=+.
8762 *
8763 * For example:
8764 *
8765 * ARGF.lineno #=> 0
8766 * ARGF.readline #=> "This is line 1\n"
8767 * ARGF.lineno #=> 1
8768 */
8769static VALUE
8770argf_lineno(VALUE argf)
8771{
8772 return INT2FIX(ARGF.lineno);
8773}
8774
8775static VALUE
8776argf_forward(int argc, VALUE *argv, VALUE argf)
8777{
8778 return rb_funcall3(ARGF.current_file, rb_frame_this_func(), argc, argv);
8779}
8780
8781#define next_argv() argf_next_argv(argf)
8782#define ARGF_GENERIC_INPUT_P() \
8783 (ARGF.current_file == rb_stdin && !RB_TYPE_P(ARGF.current_file, T_FILE))
8784#define ARGF_FORWARD(argc, argv) do {\
8785 if (ARGF_GENERIC_INPUT_P())\
8786 return argf_forward((argc), (argv), argf);\
8787} while (0)
8788#define NEXT_ARGF_FORWARD(argc, argv) do {\
8789 if (!next_argv()) return Qnil;\
8790 ARGF_FORWARD((argc), (argv));\
8791} while (0)
8792
8793static void
8794argf_close(VALUE argf)
8795{
8796 VALUE file = ARGF.current_file;
8797 if (file == rb_stdin) return;
8798 if (RB_TYPE_P(file, T_FILE)) {
8799 rb_io_set_write_io(file, Qnil);
8800 }
8801 io_close(file);
8802 ARGF.init_p = -1;
8803}
8804
8805static int
8806argf_next_argv(VALUE argf)
8807{
8808 char *fn;
8809 rb_io_t *fptr;
8810 int stdout_binmode = 0;
8811 int fmode;
8812
8813 VALUE r_stdout = rb_ractor_stdout();
8814
8815 if (RB_TYPE_P(r_stdout, T_FILE)) {
8816 GetOpenFile(r_stdout, fptr);
8817 if (fptr->mode & FMODE_BINMODE)
8818 stdout_binmode = 1;
8819 }
8820
8821 if (ARGF.init_p == 0) {
8822 if (!NIL_P(ARGF.argv) && RARRAY_LEN(ARGF.argv) > 0) {
8823 ARGF.next_p = 1;
8824 }
8825 else {
8826 ARGF.next_p = -1;
8827 }
8828 ARGF.init_p = 1;
8829 }
8830 else {
8831 if (NIL_P(ARGF.argv)) {
8832 ARGF.next_p = -1;
8833 }
8834 else if (ARGF.next_p == -1 && RARRAY_LEN(ARGF.argv) > 0) {
8835 ARGF.next_p = 1;
8836 }
8837 }
8838
8839 if (ARGF.next_p == 1) {
8840 if (ARGF.init_p == 1) argf_close(argf);
8841 retry:
8842 if (RARRAY_LEN(ARGF.argv) > 0) {
8843 VALUE filename = rb_ary_shift(ARGF.argv);
8844 FilePathValue(filename);
8845 ARGF.filename = filename;
8846 filename = rb_str_encode_ospath(filename);
8847 fn = StringValueCStr(filename);
8848 if (RSTRING_LEN(filename) == 1 && fn[0] == '-') {
8849 ARGF.current_file = rb_stdin;
8850 if (ARGF.inplace) {
8851 rb_warn("Can't do inplace edit for stdio; skipping");
8852 goto retry;
8853 }
8854 }
8855 else {
8856 VALUE write_io = Qnil;
8857 int fr = rb_sysopen(filename, O_RDONLY, 0);
8858
8859 if (ARGF.inplace) {
8860 struct stat st;
8861#ifndef NO_SAFE_RENAME
8862 struct stat st2;
8863#endif
8864 VALUE str;
8865 int fw;
8866
8867 if (RB_TYPE_P(r_stdout, T_FILE) && r_stdout != orig_stdout) {
8868 rb_io_close(r_stdout);
8869 }
8870 fstat(fr, &st);
8871 str = filename;
8872 if (!NIL_P(ARGF.inplace)) {
8873 VALUE suffix = ARGF.inplace;
8874 str = rb_str_dup(str);
8875 if (NIL_P(rb_str_cat_conv_enc_opts(str, RSTRING_LEN(str),
8876 RSTRING_PTR(suffix), RSTRING_LEN(suffix),
8877 rb_enc_get(suffix), 0, Qnil))) {
8878 rb_str_append(str, suffix);
8879 }
8880#ifdef NO_SAFE_RENAME
8881 (void)close(fr);
8882 (void)unlink(RSTRING_PTR(str));
8883 if (rename(fn, RSTRING_PTR(str)) < 0) {
8884 rb_warn("Can't rename %"PRIsVALUE" to %"PRIsVALUE": %s, skipping file",
8885 filename, str, strerror(errno));
8886 goto retry;
8887 }
8888 fr = rb_sysopen(str, O_RDONLY, 0);
8889#else
8890 if (rename(fn, RSTRING_PTR(str)) < 0) {
8891 rb_warn("Can't rename %"PRIsVALUE" to %"PRIsVALUE": %s, skipping file",
8892 filename, str, strerror(errno));
8893 close(fr);
8894 goto retry;
8895 }
8896#endif
8897 }
8898 else {
8899#ifdef NO_SAFE_RENAME
8900 rb_fatal("Can't do inplace edit without backup");
8901#else
8902 if (unlink(fn) < 0) {
8903 rb_warn("Can't remove %"PRIsVALUE": %s, skipping file",
8904 filename, strerror(errno));
8905 close(fr);
8906 goto retry;
8907 }
8908#endif
8909 }
8910 fw = rb_sysopen(filename, O_WRONLY|O_CREAT|O_TRUNC, 0666);
8911#ifndef NO_SAFE_RENAME
8912 fstat(fw, &st2);
8913#ifdef HAVE_FCHMOD
8914 fchmod(fw, st.st_mode);
8915#else
8916 chmod(fn, st.st_mode);
8917#endif
8918 if (st.st_uid!=st2.st_uid || st.st_gid!=st2.st_gid) {
8919 int err;
8920#ifdef HAVE_FCHOWN
8921 err = fchown(fw, st.st_uid, st.st_gid);
8922#else
8923 err = chown(fn, st.st_uid, st.st_gid);
8924#endif
8925 if (err && getuid() == 0 && st2.st_uid == 0) {
8926 const char *wkfn = RSTRING_PTR(filename);
8927 rb_warn("Can't set owner/group of %"PRIsVALUE" to same as %"PRIsVALUE": %s, skipping file",
8928 filename, str, strerror(errno));
8929 (void)close(fr);
8930 (void)close(fw);
8931 (void)unlink(wkfn);
8932 goto retry;
8933 }
8934 }
8935#endif
8936 write_io = prep_io(fw, FMODE_WRITABLE, rb_cFile, fn);
8937 rb_ractor_stdout_set(write_io);
8938 if (stdout_binmode) rb_io_binmode(rb_stdout);
8939 }
8940 fmode = FMODE_READABLE;
8941 if (!ARGF.binmode) {
8942 fmode |= DEFAULT_TEXTMODE;
8943 }
8944 ARGF.current_file = prep_io(fr, fmode, rb_cFile, fn);
8945 if (!NIL_P(write_io)) {
8946 rb_io_set_write_io(ARGF.current_file, write_io);
8947 }
8948 RB_GC_GUARD(filename);
8949 }
8950 if (ARGF.binmode) rb_io_ascii8bit_binmode(ARGF.current_file);
8951 GetOpenFile(ARGF.current_file, fptr);
8952 if (ARGF.encs.enc) {
8953 fptr->encs = ARGF.encs;
8954 clear_codeconv(fptr);
8955 }
8956 else {
8957 fptr->encs.ecflags &= ~ECONV_NEWLINE_DECORATOR_MASK;
8958 if (!ARGF.binmode) {
8959 fptr->encs.ecflags |= ECONV_DEFAULT_NEWLINE_DECORATOR;
8960#ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
8961 fptr->encs.ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
8962#endif
8963 }
8964 }
8965 ARGF.next_p = 0;
8966 }
8967 else {
8968 ARGF.next_p = 1;
8969 return FALSE;
8970 }
8971 }
8972 else if (ARGF.next_p == -1) {
8973 ARGF.current_file = rb_stdin;
8974 ARGF.filename = rb_str_new2("-");
8975 if (ARGF.inplace) {
8976 rb_warn("Can't do inplace edit for stdio");
8977 rb_ractor_stdout_set(orig_stdout);
8978 }
8979 }
8980 if (ARGF.init_p == -1) ARGF.init_p = 1;
8981 return TRUE;
8982}
8983
8984static VALUE
8985argf_getline(int argc, VALUE *argv, VALUE argf)
8986{
8987 VALUE line;
8988 long lineno = ARGF.lineno;
8989
8990 retry:
8991 if (!next_argv()) return Qnil;
8992 if (ARGF_GENERIC_INPUT_P()) {
8993 line = rb_funcall3(ARGF.current_file, idGets, argc, argv);
8994 }
8995 else {
8996 if (argc == 0 && rb_rs == rb_default_rs) {
8997 line = rb_io_gets(ARGF.current_file);
8998 }
8999 else {
9000 line = rb_io_getline(argc, argv, ARGF.current_file);
9001 }
9002 if (NIL_P(line) && ARGF.next_p != -1) {
9003 argf_close(argf);
9004 ARGF.next_p = 1;
9005 goto retry;
9006 }
9007 }
9008 if (!NIL_P(line)) {
9009 ARGF.lineno = ++lineno;
9010 ARGF.last_lineno = ARGF.lineno;
9011 }
9012 return line;
9013}
9014
9015static VALUE
9016argf_lineno_getter(ID id, VALUE *var)
9017{
9018 VALUE argf = *var;
9019 return INT2FIX(ARGF.last_lineno);
9020}
9021
9022static void
9023argf_lineno_setter(VALUE val, ID id, VALUE *var)
9024{
9025 VALUE argf = *var;
9026 int n = NUM2INT(val);
9027 ARGF.last_lineno = ARGF.lineno = n;
9028}
9029
9030static VALUE argf_gets(int, VALUE *, VALUE);
9031
9032/*
9033 * call-seq:
9034 * gets(sep=$/ [, getline_args]) -> string or nil
9035 * gets(limit [, getline_args]) -> string or nil
9036 * gets(sep, limit [, getline_args]) -> string or nil
9037 *
9038 * Returns (and assigns to <code>$_</code>) the next line from the list
9039 * of files in +ARGV+ (or <code>$*</code>), or from standard input if
9040 * no files are present on the command line. Returns +nil+ at end of
9041 * file. The optional argument specifies the record separator. The
9042 * separator is included with the contents of each record. A separator
9043 * of +nil+ reads the entire contents, and a zero-length separator
9044 * reads the input one paragraph at a time, where paragraphs are
9045 * divided by two consecutive newlines. If the first argument is an
9046 * integer, or optional second argument is given, the returning string
9047 * would not be longer than the given value in bytes. If multiple
9048 * filenames are present in +ARGV+, <code>gets(nil)</code> will read
9049 * the contents one file at a time.
9050 *
9051 * ARGV << "testfile"
9052 * print while gets
9053 *
9054 * <em>produces:</em>
9055 *
9056 * This is line one
9057 * This is line two
9058 * This is line three
9059 * And so on...
9060 *
9061 * The style of programming using <code>$_</code> as an implicit
9062 * parameter is gradually losing favor in the Ruby community.
9063 */
9064
9065static VALUE
9066rb_f_gets(int argc, VALUE *argv, VALUE recv)
9067{
9068 if (recv == argf) {
9069 return argf_gets(argc, argv, argf);
9070 }
9071 return rb_funcallv(argf, idGets, argc, argv);
9072}
9073
9074/*
9075 * call-seq:
9076 * ARGF.gets(sep=$/ [, getline_args]) -> string or nil
9077 * ARGF.gets(limit [, getline_args]) -> string or nil
9078 * ARGF.gets(sep, limit [, getline_args]) -> string or nil
9079 *
9080 * Returns the next line from the current file in +ARGF+.
9081 *
9082 * By default lines are assumed to be separated by <code>$/</code>;
9083 * to use a different character as a separator, supply it as a +String+
9084 * for the _sep_ argument.
9085 *
9086 * The optional _limit_ argument specifies how many characters of each line
9087 * to return. By default all characters are returned.
9088 *
9089 * See IO.readlines for details about getline_args.
9090 *
9091 */
9092static VALUE
9093argf_gets(int argc, VALUE *argv, VALUE argf)
9094{
9095 VALUE line;
9096
9097 line = argf_getline(argc, argv, argf);
9098 rb_lastline_set(line);
9099
9100 return line;
9101}
9102
9103 VALUE
9104 rb_gets(void)
9105{
9106 VALUE line;
9107
9108 if (rb_rs != rb_default_rs) {
9109 return rb_f_gets(0, 0, argf);
9110 }
9111
9112 retry:
9113 if (!next_argv()) return Qnil;
9114 line = rb_io_gets(ARGF.current_file);
9115 if (NIL_P(line) && ARGF.next_p != -1) {
9116 rb_io_close(ARGF.current_file);
9117 ARGF.next_p = 1;
9118 goto retry;
9119 }
9120 rb_lastline_set(line);
9121 if (!NIL_P(line)) {
9122 ARGF.lineno++;
9123 ARGF.last_lineno = ARGF.lineno;
9124 }
9125
9126 return line;
9127}
9128
9129static VALUE argf_readline(int, VALUE *, VALUE);
9130
9131/*
9132 * call-seq:
9133 * readline(sep=$/) -> string
9134 * readline(limit) -> string
9135 * readline(sep, limit) -> string
9136 *
9137 * Equivalent to Kernel::gets, except
9138 * +readline+ raises +EOFError+ at end of file.
9139 */
9140
9141static VALUE
9142rb_f_readline(int argc, VALUE *argv, VALUE recv)
9143{
9144 if (recv == argf) {
9145 return argf_readline(argc, argv, argf);
9146 }
9147 return rb_funcallv(argf, rb_intern("readline"), argc, argv);
9148}
9149
9150
9151/*
9152 * call-seq:
9153 * ARGF.readline(sep=$/) -> string
9154 * ARGF.readline(limit) -> string
9155 * ARGF.readline(sep, limit) -> string
9156 *
9157 * Returns the next line from the current file in +ARGF+.
9158 *
9159 * By default lines are assumed to be separated by <code>$/</code>;
9160 * to use a different character as a separator, supply it as a +String+
9161 * for the _sep_ argument.
9162 *
9163 * The optional _limit_ argument specifies how many characters of each line
9164 * to return. By default all characters are returned.
9165 *
9166 * An +EOFError+ is raised at the end of the file.
9167 */
9168static VALUE
9169argf_readline(int argc, VALUE *argv, VALUE argf)
9170{
9171 VALUE line;
9172
9173 if (!next_argv()) rb_eof_error();
9174 ARGF_FORWARD(argc, argv);
9175 line = argf_gets(argc, argv, argf);
9176 if (NIL_P(line)) {
9177 rb_eof_error();
9178 }
9179
9180 return line;
9181}
9182
9183static VALUE argf_readlines(int, VALUE *, VALUE);
9184
9185/*
9186 * call-seq:
9187 * readlines(sep=$/) -> array
9188 * readlines(limit) -> array
9189 * readlines(sep, limit) -> array
9190 *
9191 * Returns an array containing the lines returned by calling
9192 * <code>Kernel.gets(<i>sep</i>)</code> until the end of file.
9193 */
9194
9195static VALUE
9196rb_f_readlines(int argc, VALUE *argv, VALUE recv)
9197{
9198 if (recv == argf) {
9199 return argf_readlines(argc, argv, argf);
9200 }
9201 return rb_funcallv(argf, rb_intern("readlines"), argc, argv);
9202}
9203
9204/*
9205 * call-seq:
9206 * ARGF.readlines(sep=$/) -> array
9207 * ARGF.readlines(limit) -> array
9208 * ARGF.readlines(sep, limit) -> array
9209 *
9210 * ARGF.to_a(sep=$/) -> array
9211 * ARGF.to_a(limit) -> array
9212 * ARGF.to_a(sep, limit) -> array
9213 *
9214 * Reads +ARGF+'s current file in its entirety, returning an +Array+ of its
9215 * lines, one line per element. Lines are assumed to be separated by _sep_.
9216 *
9217 * lines = ARGF.readlines
9218 * lines[0] #=> "This is line one\n"
9219 */
9220static VALUE
9221argf_readlines(int argc, VALUE *argv, VALUE argf)
9222{
9223 long lineno = ARGF.lineno;
9224 VALUE lines, ary;
9225
9226 ary = rb_ary_new();
9227 while (next_argv()) {
9228 if (ARGF_GENERIC_INPUT_P()) {
9229 lines = rb_funcall3(ARGF.current_file, rb_intern("readlines"), argc, argv);
9230 }
9231 else {
9232 lines = rb_io_readlines(argc, argv, ARGF.current_file);
9233 argf_close(argf);
9234 }
9235 ARGF.next_p = 1;
9236 rb_ary_concat(ary, lines);
9237 ARGF.lineno = lineno + RARRAY_LEN(ary);
9238 ARGF.last_lineno = ARGF.lineno;
9239 }
9240 ARGF.init_p = 0;
9241 return ary;
9242}
9243
9244/*
9245 * call-seq:
9246 * `cmd` -> string
9247 *
9248 * Returns the standard output of running _cmd_ in a subshell.
9249 * The built-in syntax <code>%x{...}</code> uses
9250 * this method. Sets <code>$?</code> to the process status.
9251 *
9252 * `date` #=> "Wed Apr 9 08:56:30 CDT 2003\n"
9253 * `ls testdir`.split[1] #=> "main.rb"
9254 * `echo oops && exit 99` #=> "oops\n"
9255 * $?.exitstatus #=> 99
9256 */
9257
9258static VALUE
9259rb_f_backquote(VALUE obj, VALUE str)
9260{
9261 VALUE port;
9262 VALUE result;
9263 rb_io_t *fptr;
9264
9265 SafeStringValue(str);
9266 rb_last_status_clear();
9267 port = pipe_open_s(str, "r", FMODE_READABLE|DEFAULT_TEXTMODE, NULL);
9268 if (NIL_P(port)) return rb_str_new(0,0);
9269
9270 GetOpenFile(port, fptr);
9271 result = read_all(fptr, remain_size(fptr), Qnil);
9272 rb_io_close(port);
9273 RFILE(port)->fptr = NULL;
9274 rb_io_fptr_finalize(fptr);
9275 rb_gc_force_recycle(port); /* also guards from premature GC */
9276
9277 return result;
9278}
9279
9280#ifdef HAVE_SYS_SELECT_H
9281#include <sys/select.h>
9282#endif
9283
9284static VALUE
9285select_internal(VALUE read, VALUE write, VALUE except, struct timeval *tp, rb_fdset_t *fds)
9286{
9287 VALUE res, list;
9288 rb_fdset_t *rp, *wp, *ep;
9289 rb_io_t *fptr;
9290 long i;
9291 int max = 0, n;
9292 int pending = 0;
9293 struct timeval timerec;
9294
9295 if (!NIL_P(read)) {
9296 Check_Type(read, T_ARRAY);
9297 for (i=0; i<RARRAY_LEN(read); i++) {
9298 GetOpenFile(rb_io_get_io(RARRAY_AREF(read, i)), fptr);
9299 rb_fd_set(fptr->fd, &fds[0]);
9300 if (READ_DATA_PENDING(fptr) || READ_CHAR_PENDING(fptr)) { /* check for buffered data */
9301 pending++;
9302 rb_fd_set(fptr->fd, &fds[3]);
9303 }
9304 if (max < fptr->fd) max = fptr->fd;
9305 }
9306 if (pending) { /* no blocking if there's buffered data */
9307 timerec.tv_sec = timerec.tv_usec = 0;
9308 tp = &timerec;
9309 }
9310 rp = &fds[0];
9311 }
9312 else
9313 rp = 0;
9314
9315 if (!NIL_P(write)) {
9316 Check_Type(write, T_ARRAY);
9317 for (i=0; i<RARRAY_LEN(write); i++) {
9318 VALUE write_io = GetWriteIO(rb_io_get_io(RARRAY_AREF(write, i)));
9319 GetOpenFile(write_io, fptr);
9320 rb_fd_set(fptr->fd, &fds[1]);
9321 if (max < fptr->fd) max = fptr->fd;
9322 }
9323 wp = &fds[1];
9324 }
9325 else
9326 wp = 0;
9327
9328 if (!NIL_P(except)) {
9329 Check_Type(except, T_ARRAY);
9330 for (i=0; i<RARRAY_LEN(except); i++) {
9331 VALUE io = rb_io_get_io(RARRAY_AREF(except, i));
9332 VALUE write_io = GetWriteIO(io);
9333 GetOpenFile(io, fptr);
9334 rb_fd_set(fptr->fd, &fds[2]);
9335 if (max < fptr->fd) max = fptr->fd;
9336 if (io != write_io) {
9337 GetOpenFile(write_io, fptr);
9338 rb_fd_set(fptr->fd, &fds[2]);
9339 if (max < fptr->fd) max = fptr->fd;
9340 }
9341 }
9342 ep = &fds[2];
9343 }
9344 else {
9345 ep = 0;
9346 }
9347
9348 max++;
9349
9350 n = rb_thread_fd_select(max, rp, wp, ep, tp);
9351 if (n < 0) {
9352 rb_sys_fail(0);
9353 }
9354 if (!pending && n == 0) return Qnil; /* returns nil on timeout */
9355
9356 res = rb_ary_new2(3);
9357 rb_ary_push(res, rp?rb_ary_new():rb_ary_new2(0));
9358 rb_ary_push(res, wp?rb_ary_new():rb_ary_new2(0));
9359 rb_ary_push(res, ep?rb_ary_new():rb_ary_new2(0));
9360
9361 if (rp) {
9362 list = RARRAY_AREF(res, 0);
9363 for (i=0; i< RARRAY_LEN(read); i++) {
9364 VALUE obj = rb_ary_entry(read, i);
9365 VALUE io = rb_io_get_io(obj);
9366 GetOpenFile(io, fptr);
9367 if (rb_fd_isset(fptr->fd, &fds[0]) ||
9368 rb_fd_isset(fptr->fd, &fds[3])) {
9369 rb_ary_push(list, obj);
9370 }
9371 }
9372 }
9373
9374 if (wp) {
9375 list = RARRAY_AREF(res, 1);
9376 for (i=0; i< RARRAY_LEN(write); i++) {
9377 VALUE obj = rb_ary_entry(write, i);
9378 VALUE io = rb_io_get_io(obj);
9379 VALUE write_io = GetWriteIO(io);
9380 GetOpenFile(write_io, fptr);
9381 if (rb_fd_isset(fptr->fd, &fds[1])) {
9382 rb_ary_push(list, obj);
9383 }
9384 }
9385 }
9386
9387 if (ep) {
9388 list = RARRAY_AREF(res, 2);
9389 for (i=0; i< RARRAY_LEN(except); i++) {
9390 VALUE obj = rb_ary_entry(except, i);
9391 VALUE io = rb_io_get_io(obj);
9392 VALUE write_io = GetWriteIO(io);
9393 GetOpenFile(io, fptr);
9394 if (rb_fd_isset(fptr->fd, &fds[2])) {
9395 rb_ary_push(list, obj);
9396 }
9397 else if (io != write_io) {
9398 GetOpenFile(write_io, fptr);
9399 if (rb_fd_isset(fptr->fd, &fds[2])) {
9400 rb_ary_push(list, obj);
9401 }
9402 }
9403 }
9404 }
9405
9406 return res; /* returns an empty array on interrupt */
9407}
9408
9409 struct select_args {
9410 VALUE read, write, except;
9411 struct timeval *timeout;
9412 rb_fdset_t fdsets[4];
9413};
9414
9415static VALUE
9416select_call(VALUE arg)
9417{
9418 struct select_args *p = (struct select_args *)arg;
9419
9420 return select_internal(p->read, p->write, p->except, p->timeout, p->fdsets);
9421}
9422
9423static VALUE
9424select_end(VALUE arg)
9425{
9426 struct select_args *p = (struct select_args *)arg;
9427 int i;
9428
9429 for (i = 0; i < numberof(p->fdsets); ++i)
9430 rb_fd_term(&p->fdsets[i]);
9431 return Qnil;
9432}
9433
9434static VALUE sym_normal, sym_sequential, sym_random,
9435 sym_willneed, sym_dontneed, sym_noreuse;
9436
9437#ifdef HAVE_POSIX_FADVISE
9438struct io_advise_struct {
9439 int fd;
9440 int advice;
9441 off_t offset;
9442 off_t len;
9443};
9444
9445static VALUE
9446io_advise_internal(void *arg)
9447{
9448 struct io_advise_struct *ptr = arg;
9449 return posix_fadvise(ptr->fd, ptr->offset, ptr->len, ptr->advice);
9450}
9451
9452static VALUE
9453io_advise_sym_to_const(VALUE sym)
9454{
9455#ifdef POSIX_FADV_NORMAL
9456 if (sym == sym_normal)
9457 return INT2NUM(POSIX_FADV_NORMAL);
9458#endif
9459
9460#ifdef POSIX_FADV_RANDOM
9461 if (sym == sym_random)
9462 return INT2NUM(POSIX_FADV_RANDOM);
9463#endif
9464
9465#ifdef POSIX_FADV_SEQUENTIAL
9466 if (sym == sym_sequential)
9467 return INT2NUM(POSIX_FADV_SEQUENTIAL);
9468#endif
9469
9470#ifdef POSIX_FADV_WILLNEED
9471 if (sym == sym_willneed)
9472 return INT2NUM(POSIX_FADV_WILLNEED);
9473#endif
9474
9475#ifdef POSIX_FADV_DONTNEED
9476 if (sym == sym_dontneed)
9477 return INT2NUM(POSIX_FADV_DONTNEED);
9478#endif
9479
9480#ifdef POSIX_FADV_NOREUSE
9481 if (sym == sym_noreuse)
9482 return INT2NUM(POSIX_FADV_NOREUSE);
9483#endif
9484
9485 return Qnil;
9486}
9487
9488static VALUE
9489do_io_advise(rb_io_t *fptr, VALUE advice, off_t offset, off_t len)
9490{
9491 int rv;
9492 struct io_advise_struct ias;
9493 VALUE num_adv;
9494
9495 num_adv = io_advise_sym_to_const(advice);
9496
9497 /*
9498 * The platform doesn't support this hint. We don't raise exception, instead
9499 * silently ignore it. Because IO::advise is only hint.
9500 */
9501 if (NIL_P(num_adv))
9502 return Qnil;
9503
9504 ias.fd = fptr->fd;
9505 ias.advice = NUM2INT(num_adv);
9506 ias.offset = offset;
9507 ias.len = len;
9508
9509 rv = (int)rb_thread_io_blocking_region(io_advise_internal, &ias, fptr->fd);
9510 if (rv && rv != ENOSYS) {
9511 /* posix_fadvise(2) doesn't set errno. On success it returns 0; otherwise
9512 it returns the error code. */
9513 VALUE message = rb_sprintf("%"PRIsVALUE" "
9514 "(%"PRI_OFFT_PREFIX"d, "
9515 "%"PRI_OFFT_PREFIX"d, "
9516 "%"PRIsVALUE")",
9517 fptr->pathv, offset, len, advice);
9518 rb_syserr_fail_str(rv, message);
9519 }
9520
9521 return Qnil;
9522}
9523
9524#endif /* HAVE_POSIX_FADVISE */
9525
9526static void
9527advice_arg_check(VALUE advice)
9528{
9529 if (!SYMBOL_P(advice))
9530 rb_raise(rb_eTypeError, "advice must be a Symbol");
9531
9532 if (advice != sym_normal &&
9533 advice != sym_sequential &&
9534 advice != sym_random &&
9535 advice != sym_willneed &&
9536 advice != sym_dontneed &&
9537 advice != sym_noreuse) {
9538 rb_raise(rb_eNotImpError, "Unsupported advice: %+"PRIsVALUE, advice);
9539 }
9540}
9541
9542/*
9543 * call-seq:
9544 * ios.advise(advice, offset=0, len=0) -> nil
9545 *
9546 * Announce an intention to access data from the current file in a
9547 * specific pattern. On platforms that do not support the
9548 * <em>posix_fadvise(2)</em> system call, this method is a no-op.
9549 *
9550 * _advice_ is one of the following symbols:
9551 *
9552 * :normal:: No advice to give; the default assumption for an open file.
9553 * :sequential:: The data will be accessed sequentially
9554 * with lower offsets read before higher ones.
9555 * :random:: The data will be accessed in random order.
9556 * :willneed:: The data will be accessed in the near future.
9557 * :dontneed:: The data will not be accessed in the near future.
9558 * :noreuse:: The data will only be accessed once.
9559 *
9560 * The semantics of a piece of advice are platform-dependent. See
9561 * <em>man 2 posix_fadvise</em> for details.
9562 *
9563 * "data" means the region of the current file that begins at
9564 * _offset_ and extends for _len_ bytes. If _len_ is 0, the region
9565 * ends at the last byte of the file. By default, both _offset_ and
9566 * _len_ are 0, meaning that the advice applies to the entire file.
9567 *
9568 * If an error occurs, one of the following exceptions will be raised:
9569 *
9570 * IOError:: The IO stream is closed.
9571 * Errno::EBADF::
9572 * The file descriptor of the current file is invalid.
9573 * Errno::EINVAL:: An invalid value for _advice_ was given.
9574 * Errno::ESPIPE::
9575 * The file descriptor of the current file refers to a FIFO or
9576 * pipe. (Linux raises Errno::EINVAL in this case).
9577 * TypeError::
9578 * Either _advice_ was not a Symbol, or one of the
9579 * other arguments was not an Integer.
9580 * RangeError:: One of the arguments given was too big/small.
9581 *
9582 * This list is not exhaustive; other Errno:: exceptions are also possible.
9583 */
9584static VALUE
9585rb_io_advise(int argc, VALUE *argv, VALUE io)
9586{
9587 VALUE advice, offset, len;
9588 off_t off, l;
9589 rb_io_t *fptr;
9590
9591 rb_scan_args(argc, argv, "12", &advice, &offset, &len);
9592 advice_arg_check(advice);
9593
9594 io = GetWriteIO(io);
9595 GetOpenFile(io, fptr);
9596
9597 off = NIL_P(offset) ? 0 : NUM2OFFT(offset);
9598 l = NIL_P(len) ? 0 : NUM2OFFT(len);
9599
9600#ifdef HAVE_POSIX_FADVISE
9601 return do_io_advise(fptr, advice, off, l);
9602#else
9603 ((void)off, (void)l); /* Ignore all hint */
9604 return Qnil;
9605#endif
9606}
9607
9608/*
9609 * call-seq:
9610 * IO.select(read_array [, write_array [, error_array [, timeout]]]) -> array or nil
9611 *
9612 * Calls select(2) system call.
9613 * It monitors given arrays of IO objects, waits until one or more of
9614 * IO objects are ready for reading, are ready for writing, and have
9615 * pending exceptions respectively, and returns an array that contains
9616 * arrays of those IO objects. It will return +nil+ if optional
9617 * <i>timeout</i> value is given and no IO object is ready in
9618 * <i>timeout</i> seconds.
9619 *
9620 * IO.select peeks the buffer of IO objects for testing readability.
9621 * If the IO buffer is not empty, IO.select immediately notifies
9622 * readability. This "peek" only happens for IO objects. It does not
9623 * happen for IO-like objects such as OpenSSL::SSL::SSLSocket.
9624 *
9625 * The best way to use IO.select is invoking it after nonblocking
9626 * methods such as #read_nonblock, #write_nonblock, etc. The methods
9627 * raise an exception which is extended by IO::WaitReadable or
9628 * IO::WaitWritable. The modules notify how the caller should wait
9629 * with IO.select. If IO::WaitReadable is raised, the caller should
9630 * wait for reading. If IO::WaitWritable is raised, the caller should
9631 * wait for writing.
9632 *
9633 * So, blocking read (#readpartial) can be emulated using
9634 * #read_nonblock and IO.select as follows:
9635 *
9636 * begin
9637 * result = io_like.read_nonblock(maxlen)
9638 * rescue IO::WaitReadable
9639 * IO.select([io_like])
9640 * retry
9641 * rescue IO::WaitWritable
9642 * IO.select(nil, [io_like])
9643 * retry
9644 * end
9645 *
9646 * Especially, the combination of nonblocking methods and IO.select is
9647 * preferred for IO like objects such as OpenSSL::SSL::SSLSocket. It
9648 * has #to_io method to return underlying IO object. IO.select calls
9649 * #to_io to obtain the file descriptor to wait.
9650 *
9651 * This means that readability notified by IO.select doesn't mean
9652 * readability from OpenSSL::SSL::SSLSocket object.
9653 *
9654 * The most likely situation is that OpenSSL::SSL::SSLSocket buffers
9655 * some data. IO.select doesn't see the buffer. So IO.select can
9656 * block when OpenSSL::SSL::SSLSocket#readpartial doesn't block.
9657 *
9658 * However, several more complicated situations exist.
9659 *
9660 * SSL is a protocol which is sequence of records.
9661 * The record consists of multiple bytes.
9662 * So, the remote side of SSL sends a partial record, IO.select
9663 * notifies readability but OpenSSL::SSL::SSLSocket cannot decrypt a
9664 * byte and OpenSSL::SSL::SSLSocket#readpartial will block.
9665 *
9666 * Also, the remote side can request SSL renegotiation which forces
9667 * the local SSL engine to write some data.
9668 * This means OpenSSL::SSL::SSLSocket#readpartial may invoke #write
9669 * system call and it can block.
9670 * In such a situation, OpenSSL::SSL::SSLSocket#read_nonblock raises
9671 * IO::WaitWritable instead of blocking.
9672 * So, the caller should wait for ready for writability as above
9673 * example.
9674 *
9675 * The combination of nonblocking methods and IO.select is also useful
9676 * for streams such as tty, pipe socket socket when multiple processes
9677 * read from a stream.
9678 *
9679 * Finally, Linux kernel developers don't guarantee that
9680 * readability of select(2) means readability of following read(2) even
9681 * for a single process.
9682 * See select(2) manual on GNU/Linux system.
9683 *
9684 * Invoking IO.select before IO#readpartial works well as usual.
9685 * However it is not the best way to use IO.select.
9686 *
9687 * The writability notified by select(2) doesn't show
9688 * how many bytes are writable.
9689 * IO#write method blocks until given whole string is written.
9690 * So, <code>IO#write(two or more bytes)</code> can block after
9691 * writability is notified by IO.select. IO#write_nonblock is required
9692 * to avoid the blocking.
9693 *
9694 * Blocking write (#write) can be emulated using #write_nonblock and
9695 * IO.select as follows: IO::WaitReadable should also be rescued for
9696 * SSL renegotiation in OpenSSL::SSL::SSLSocket.
9697 *
9698 * while 0 < string.bytesize
9699 * begin
9700 * written = io_like.write_nonblock(string)
9701 * rescue IO::WaitReadable
9702 * IO.select([io_like])
9703 * retry
9704 * rescue IO::WaitWritable
9705 * IO.select(nil, [io_like])
9706 * retry
9707 * end
9708 * string = string.byteslice(written..-1)
9709 * end
9710 *
9711 * === Parameters
9712 * read_array:: an array of IO objects that wait until ready for read
9713 * write_array:: an array of IO objects that wait until ready for write
9714 * error_array:: an array of IO objects that wait for exceptions
9715 * timeout:: a numeric value in second
9716 *
9717 * === Example
9718 *
9719 * rp, wp = IO.pipe
9720 * mesg = "ping "
9721 * 100.times {
9722 * # IO.select follows IO#read. Not the best way to use IO.select.
9723 * rs, ws, = IO.select([rp], [wp])
9724 * if r = rs[0]
9725 * ret = r.read(5)
9726 * print ret
9727 * case ret
9728 * when /ping/
9729 * mesg = "pong\n"
9730 * when /pong/
9731 * mesg = "ping "
9732 * end
9733 * end
9734 * if w = ws[0]
9735 * w.write(mesg)
9736 * end
9737 * }
9738 *
9739 * <em>produces:</em>
9740 *
9741 * ping pong
9742 * ping pong
9743 * ping pong
9744 * (snipped)
9745 * ping
9746 */
9747
9748static VALUE
9749rb_f_select(int argc, VALUE *argv, VALUE obj)
9750{
9751 VALUE timeout;
9752 struct select_args args;
9753 struct timeval timerec;
9754 int i;
9755
9756 rb_scan_args(argc, argv, "13", &args.read, &args.write, &args.except, &timeout);
9757 if (NIL_P(timeout)) {
9758 args.timeout = 0;
9759 }
9760 else {
9761 timerec = rb_time_interval(timeout);
9762 args.timeout = &timerec;
9763 }
9764
9765 for (i = 0; i < numberof(args.fdsets); ++i)
9766 rb_fd_init(&args.fdsets[i]);
9767
9768 return rb_ensure(select_call, (VALUE)&args, select_end, (VALUE)&args);
9769}
9770
9771#if (defined(__linux__) && !defined(__ANDROID__)) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
9772 typedef unsigned long ioctl_req_t;
9773# define NUM2IOCTLREQ(num) NUM2ULONG(num)
9774#else
9775 typedef int ioctl_req_t;
9776# define NUM2IOCTLREQ(num) ((int)NUM2LONG(num))
9777#endif
9778
9779#ifdef HAVE_IOCTL
9780struct ioctl_arg {
9781 int fd;
9782 ioctl_req_t cmd;
9783 long narg;
9784};
9785
9786static VALUE
9787nogvl_ioctl(void *ptr)
9788{
9789 struct ioctl_arg *arg = ptr;
9790
9791 return (VALUE)ioctl(arg->fd, arg->cmd, arg->narg);
9792}
9793
9794static int
9795do_ioctl(int fd, ioctl_req_t cmd, long narg)
9796{
9797 int retval;
9798 struct ioctl_arg arg;
9799
9800 arg.fd = fd;
9801 arg.cmd = cmd;
9802 arg.narg = narg;
9803
9804 retval = (int)rb_thread_io_blocking_region(nogvl_ioctl, &arg, fd);
9805
9806 return retval;
9807}
9808#endif
9809
9810#define DEFULT_IOCTL_NARG_LEN (256)
9811
9812#if defined(__linux__) && defined(_IOC_SIZE)
9813static long
9814linux_iocparm_len(ioctl_req_t cmd)
9815{
9816 long len;
9817
9818 if ((cmd & 0xFFFF0000) == 0) {
9819 /* legacy and unstructured ioctl number. */
9820 return DEFULT_IOCTL_NARG_LEN;
9821 }
9822
9823 len = _IOC_SIZE(cmd);
9824
9825 /* paranoia check for silly drivers which don't keep ioctl convention */
9826 if (len < DEFULT_IOCTL_NARG_LEN)
9827 len = DEFULT_IOCTL_NARG_LEN;
9828
9829 return len;
9830}
9831#endif
9832
9833static long
9834ioctl_narg_len(ioctl_req_t cmd)
9835{
9836 long len;
9837
9838#ifdef IOCPARM_MASK
9839#ifndef IOCPARM_LEN
9840#define IOCPARM_LEN(x) (((x) >> 16) & IOCPARM_MASK)
9841#endif
9842#endif
9843#ifdef IOCPARM_LEN
9844 len = IOCPARM_LEN(cmd); /* on BSDish systems we're safe */
9845#elif defined(__linux__) && defined(_IOC_SIZE)
9846 len = linux_iocparm_len(cmd);
9847#else
9848 /* otherwise guess at what's safe */
9849 len = DEFULT_IOCTL_NARG_LEN;
9850#endif
9851
9852 return len;
9853}
9854
9855#ifdef HAVE_FCNTL
9856#ifdef __linux__
9857typedef long fcntl_arg_t;
9858#else
9859/* posix */
9860typedef int fcntl_arg_t;
9861#endif
9862
9863static long
9864fcntl_narg_len(int cmd)
9865{
9866 long len;
9867
9868 switch (cmd) {
9869#ifdef F_DUPFD
9870 case F_DUPFD:
9871 len = sizeof(fcntl_arg_t);
9872 break;
9873#endif
9874#ifdef F_DUP2FD /* bsd specific */
9875 case F_DUP2FD:
9876 len = sizeof(int);
9877 break;
9878#endif
9879#ifdef F_DUPFD_CLOEXEC /* linux specific */
9880 case F_DUPFD_CLOEXEC:
9881 len = sizeof(fcntl_arg_t);
9882 break;
9883#endif
9884#ifdef F_GETFD
9885 case F_GETFD:
9886 len = 1;
9887 break;
9888#endif
9889#ifdef F_SETFD
9890 case F_SETFD:
9891 len = sizeof(fcntl_arg_t);
9892 break;
9893#endif
9894#ifdef F_GETFL
9895 case F_GETFL:
9896 len = 1;
9897 break;
9898#endif
9899#ifdef F_SETFL
9900 case F_SETFL:
9901 len = sizeof(fcntl_arg_t);
9902 break;
9903#endif
9904#ifdef F_GETOWN
9905 case F_GETOWN:
9906 len = 1;
9907 break;
9908#endif
9909#ifdef F_SETOWN
9910 case F_SETOWN:
9911 len = sizeof(fcntl_arg_t);
9912 break;
9913#endif
9914#ifdef F_GETOWN_EX /* linux specific */
9915 case F_GETOWN_EX:
9916 len = sizeof(struct f_owner_ex);
9917 break;
9918#endif
9919#ifdef F_SETOWN_EX /* linux specific */
9920 case F_SETOWN_EX:
9921 len = sizeof(struct f_owner_ex);
9922 break;
9923#endif
9924#ifdef F_GETLK
9925 case F_GETLK:
9926 len = sizeof(struct flock);
9927 break;
9928#endif
9929#ifdef F_SETLK
9930 case F_SETLK:
9931 len = sizeof(struct flock);
9932 break;
9933#endif
9934#ifdef F_SETLKW
9935 case F_SETLKW:
9936 len = sizeof(struct flock);
9937 break;
9938#endif
9939#ifdef F_READAHEAD /* bsd specific */
9940 case F_READAHEAD:
9941 len = sizeof(int);
9942 break;
9943#endif
9944#ifdef F_RDAHEAD /* Darwin specific */
9945 case F_RDAHEAD:
9946 len = sizeof(int);
9947 break;
9948#endif
9949#ifdef F_GETSIG /* linux specific */
9950 case F_GETSIG:
9951 len = 1;
9952 break;
9953#endif
9954#ifdef F_SETSIG /* linux specific */
9955 case F_SETSIG:
9956 len = sizeof(fcntl_arg_t);
9957 break;
9958#endif
9959#ifdef F_GETLEASE /* linux specific */
9960 case F_GETLEASE:
9961 len = 1;
9962 break;
9963#endif
9964#ifdef F_SETLEASE /* linux specific */
9965 case F_SETLEASE:
9966 len = sizeof(fcntl_arg_t);
9967 break;
9968#endif
9969#ifdef F_NOTIFY /* linux specific */
9970 case F_NOTIFY:
9971 len = sizeof(fcntl_arg_t);
9972 break;
9973#endif
9974
9975 default:
9976 len = 256;
9977 break;
9978 }
9979
9980 return len;
9981}
9982#else /* HAVE_FCNTL */
9983static long
9984fcntl_narg_len(int cmd)
9985{
9986 return 0;
9987}
9988#endif /* HAVE_FCNTL */
9989
9990static long
9991setup_narg(ioctl_req_t cmd, VALUE *argp, int io_p)
9992{
9993 long narg = 0;
9994 VALUE arg = *argp;
9995
9996 if (NIL_P(arg) || arg == Qfalse) {
9997 narg = 0;
9998 }
9999 else if (FIXNUM_P(arg)) {
10000 narg = FIX2LONG(arg);
10001 }
10002 else if (arg == Qtrue) {
10003 narg = 1;
10004 }
10005 else {
10006 VALUE tmp = rb_check_string_type(arg);
10007
10008 if (NIL_P(tmp)) {
10009 narg = NUM2LONG(arg);
10010 }
10011 else {
10012 char *ptr;
10013 long len, slen;
10014
10015 *argp = arg = tmp;
10016 if (io_p)
10017 len = ioctl_narg_len(cmd);
10018 else
10019 len = fcntl_narg_len((int)cmd);
10020 rb_str_modify(arg);
10021
10022 slen = RSTRING_LEN(arg);
10023 /* expand for data + sentinel. */
10024 if (slen < len+1) {
10025 rb_str_resize(arg, len+1);
10026 MEMZERO(RSTRING_PTR(arg)+slen, char, len-slen);
10027 slen = len+1;
10028 }
10029 /* a little sanity check here */
10030 ptr = RSTRING_PTR(arg);
10031 ptr[slen - 1] = 17;
10032 narg = (long)(SIGNED_VALUE)ptr;
10033 }
10034 }
10035
10036 return narg;
10037}
10038
10039#ifdef HAVE_IOCTL
10040static VALUE
10041rb_ioctl(VALUE io, VALUE req, VALUE arg)
10042{
10043 ioctl_req_t cmd = NUM2IOCTLREQ(req);
10044 rb_io_t *fptr;
10045 long narg;
10046 int retval;
10047
10048 narg = setup_narg(cmd, &arg, 1);
10049 GetOpenFile(io, fptr);
10050 retval = do_ioctl(fptr->fd, cmd, narg);
10051 if (retval < 0) rb_sys_fail_path(fptr->pathv);
10052 if (RB_TYPE_P(arg, T_STRING)) {
10053 char *ptr;
10054 long slen;
10055 RSTRING_GETMEM(arg, ptr, slen);
10056 if (ptr[slen-1] != 17)
10057 rb_raise(rb_eArgError, "return value overflowed string");
10058 ptr[slen-1] = '\0';
10059 }
10060
10061 return INT2NUM(retval);
10062}
10063
10064/*
10065 * call-seq:
10066 * ios.ioctl(integer_cmd, arg) -> integer
10067 *
10068 * Provides a mechanism for issuing low-level commands to control or
10069 * query I/O devices. Arguments and results are platform dependent. If
10070 * <i>arg</i> is a number, its value is passed directly. If it is a
10071 * string, it is interpreted as a binary sequence of bytes. On Unix
10072 * platforms, see <code>ioctl(2)</code> for details. Not implemented on
10073 * all platforms.
10074 */
10075
10076static VALUE
10077 rb_io_ioctl(int argc, VALUE *argv, VALUE io)
10078{
10079 VALUE req, arg;
10080
10081 rb_scan_args(argc, argv, "11", &req, &arg);
10082 return rb_ioctl(io, req, arg);
10083}
10084#else
10085#define rb_io_ioctl rb_f_notimplement
10086#endif
10087
10088#ifdef HAVE_FCNTL
10089struct fcntl_arg {
10090 int fd;
10091 int cmd;
10092 long narg;
10093};
10094
10095static VALUE
10096nogvl_fcntl(void *ptr)
10097{
10098 struct fcntl_arg *arg = ptr;
10099
10100#if defined(F_DUPFD)
10101 if (arg->cmd == F_DUPFD)
10102 return (VALUE)rb_cloexec_fcntl_dupfd(arg->fd, (int)arg->narg);
10103#endif
10104 return (VALUE)fcntl(arg->fd, arg->cmd, arg->narg);
10105}
10106
10107static int
10108do_fcntl(int fd, int cmd, long narg)
10109{
10110 int retval;
10111 struct fcntl_arg arg;
10112
10113 arg.fd = fd;
10114 arg.cmd = cmd;
10115 arg.narg = narg;
10116
10117 retval = (int)rb_thread_io_blocking_region(nogvl_fcntl, &arg, fd);
10118 if (retval != -1) {
10119 switch (cmd) {
10120#if defined(F_DUPFD)
10121 case F_DUPFD:
10122#endif
10123#if defined(F_DUPFD_CLOEXEC)
10124 case F_DUPFD_CLOEXEC:
10125#endif
10126 rb_update_max_fd(retval);
10127 }
10128 }
10129
10130 return retval;
10131}
10132
10133static VALUE
10134rb_fcntl(VALUE io, VALUE req, VALUE arg)
10135{
10136 int cmd = NUM2INT(req);
10137 rb_io_t *fptr;
10138 long narg;
10139 int retval;
10140
10141 narg = setup_narg(cmd, &arg, 0);
10142 GetOpenFile(io, fptr);
10143 retval = do_fcntl(fptr->fd, cmd, narg);
10144 if (retval < 0) rb_sys_fail_path(fptr->pathv);
10145 if (RB_TYPE_P(arg, T_STRING)) {
10146 char *ptr;
10147 long slen;
10148 RSTRING_GETMEM(arg, ptr, slen);
10149 if (ptr[slen-1] != 17)
10150 rb_raise(rb_eArgError, "return value overflowed string");
10151 ptr[slen-1] = '\0';
10152 }
10153
10154 return INT2NUM(retval);
10155}
10156
10157/*
10158 * call-seq:
10159 * ios.fcntl(integer_cmd, arg) -> integer
10160 *
10161 * Provides a mechanism for issuing low-level commands to control or
10162 * query file-oriented I/O streams. Arguments and results are platform
10163 * dependent. If <i>arg</i> is a number, its value is passed
10164 * directly. If it is a string, it is interpreted as a binary sequence
10165 * of bytes (Array#pack might be a useful way to build this string). On
10166 * Unix platforms, see <code>fcntl(2)</code> for details. Not
10167 * implemented on all platforms.
10168 */
10169
10170static VALUE
10171 rb_io_fcntl(int argc, VALUE *argv, VALUE io)
10172{
10173 VALUE req, arg;
10174
10175 rb_scan_args(argc, argv, "11", &req, &arg);
10176 return rb_fcntl(io, req, arg);
10177}
10178#else
10179#define rb_io_fcntl rb_f_notimplement
10180#endif
10181
10182#if defined(HAVE_SYSCALL) || defined(HAVE___SYSCALL)
10183/*
10184 * call-seq:
10185 * syscall(num [, args...]) -> integer
10186 *
10187 * Calls the operating system function identified by _num_ and
10188 * returns the result of the function or raises SystemCallError if
10189 * it failed.
10190 *
10191 * Arguments for the function can follow _num_. They must be either
10192 * +String+ objects or +Integer+ objects. A +String+ object is passed
10193 * as a pointer to the byte sequence. An +Integer+ object is passed
10194 * as an integer whose bit size is same as a pointer.
10195 * Up to nine parameters may be passed.
10196 *
10197 * The function identified by _num_ is system
10198 * dependent. On some Unix systems, the numbers may be obtained from a
10199 * header file called <code>syscall.h</code>.
10200 *
10201 * syscall 4, 1, "hello\n", 6 # '4' is write(2) on our box
10202 *
10203 * <em>produces:</em>
10204 *
10205 * hello
10206 *
10207 * Calling +syscall+ on a platform which does not have any way to
10208 * an arbitrary system function just fails with NotImplementedError.
10209 *
10210 * *Note:*
10211 * +syscall+ is essentially unsafe and unportable.
10212 * Feel free to shoot your foot.
10213 * The DL (Fiddle) library is preferred for safer and a bit
10214 * more portable programming.
10215 */
10216
10217static VALUE
10218 rb_f_syscall(int argc, VALUE *argv, VALUE _)
10219{
10220 VALUE arg[8];
10221#if SIZEOF_VOIDP == 8 && defined(HAVE___SYSCALL) && SIZEOF_INT != 8 /* mainly *BSD */
10222# define SYSCALL __syscall
10223# define NUM2SYSCALLID(x) NUM2LONG(x)
10224# define RETVAL2NUM(x) LONG2NUM(x)
10225# if SIZEOF_LONG == 8
10226 long num, retval = -1;
10227# elif SIZEOF_LONG_LONG == 8
10228 long long num, retval = -1;
10229# else
10230# error ---->> it is asserted that __syscall takes the first argument and returns retval in 64bit signed integer. <<----
10231# endif
10232#elif defined(__linux__)
10233# define SYSCALL syscall
10234# define NUM2SYSCALLID(x) NUM2LONG(x)
10235# define RETVAL2NUM(x) LONG2NUM(x)
10236 /*
10237 * Linux man page says, syscall(2) function prototype is below.
10238 *
10239 * int syscall(int number, ...);
10240 *
10241 * But, it's incorrect. Actual one takes and returned long. (see unistd.h)
10242 */
10243 long num, retval = -1;
10244#else
10245# define SYSCALL syscall
10246# define NUM2SYSCALLID(x) NUM2INT(x)
10247# define RETVAL2NUM(x) INT2NUM(x)
10248 int num, retval = -1;
10249#endif
10250 int i;
10251
10252 if (RTEST(ruby_verbose)) {
10253 rb_category_warning(RB_WARN_CATEGORY_DEPRECATED,
10254 "We plan to remove a syscall function at future release. DL(Fiddle) provides safer alternative.");
10255 }
10256
10257 if (argc == 0)
10258 rb_raise(rb_eArgError, "too few arguments for syscall");
10259 if (argc > numberof(arg))
10260 rb_raise(rb_eArgError, "too many arguments for syscall");
10261 num = NUM2SYSCALLID(argv[0]); ++argv;
10262 for (i = argc - 1; i--; ) {
10263 VALUE v = rb_check_string_type(argv[i]);
10264
10265 if (!NIL_P(v)) {
10266 SafeStringValue(v);
10267 rb_str_modify(v);
10268 arg[i] = (VALUE)StringValueCStr(v);
10269 }
10270 else {
10271 arg[i] = (VALUE)NUM2LONG(argv[i]);
10272 }
10273 }
10274
10275 switch (argc) {
10276 case 1:
10277 retval = SYSCALL(num);
10278 break;
10279 case 2:
10280 retval = SYSCALL(num, arg[0]);
10281 break;
10282 case 3:
10283 retval = SYSCALL(num, arg[0],arg[1]);
10284 break;
10285 case 4:
10286 retval = SYSCALL(num, arg[0],arg[1],arg[2]);
10287 break;
10288 case 5:
10289 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3]);
10290 break;
10291 case 6:
10292 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4]);
10293 break;
10294 case 7:
10295 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5]);
10296 break;
10297 case 8:
10298 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6]);
10299 break;
10300 }
10301
10302 if (retval == -1)
10303 rb_sys_fail(0);
10304 return RETVAL2NUM(retval);
10305#undef SYSCALL
10306#undef NUM2SYSCALLID
10307#undef RETVAL2NUM
10308}
10309#else
10310#define rb_f_syscall rb_f_notimplement
10311#endif
10312
10313static VALUE
10314io_new_instance(VALUE args)
10315{
10316 return rb_class_new_instance(2, (VALUE*)args+1, *(VALUE*)args);
10317}
10318
10319static rb_encoding *
10320find_encoding(VALUE v)
10321{
10322 rb_encoding *enc = rb_find_encoding(v);
10323 if (!enc) rb_warn("Unsupported encoding %"PRIsVALUE" ignored", v);
10324 return enc;
10325}
10326
10327static void
10328io_encoding_set(rb_io_t *fptr, VALUE v1, VALUE v2, VALUE opt)
10329{
10330 rb_encoding *enc, *enc2;
10331 int ecflags = fptr->encs.ecflags;
10332 VALUE ecopts, tmp;
10333
10334 if (!NIL_P(v2)) {
10335 enc2 = find_encoding(v1);
10336 tmp = rb_check_string_type(v2);
10337 if (!NIL_P(tmp)) {
10338 if (RSTRING_LEN(tmp) == 1 && RSTRING_PTR(tmp)[0] == '-') {
10339 /* Special case - "-" => no transcoding */
10340 enc = enc2;
10341 enc2 = NULL;
10342 }
10343 else
10344 enc = find_encoding(v2);
10345 if (enc == enc2) {
10346 /* Special case - "-" => no transcoding */
10347 enc2 = NULL;
10348 }
10349 }
10350 else {
10351 enc = find_encoding(v2);
10352 if (enc == enc2) {
10353 /* Special case - "-" => no transcoding */
10354 enc2 = NULL;
10355 }
10356 }
10357 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
10358 ecflags = rb_econv_prepare_options(opt, &ecopts, ecflags);
10359 }
10360 else {
10361 if (NIL_P(v1)) {
10362 /* Set to default encodings */
10363 rb_io_ext_int_to_encs(NULL, NULL, &enc, &enc2, 0);
10364 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
10365 ecopts = Qnil;
10366 }
10367 else {
10368 tmp = rb_check_string_type(v1);
10369 if (!NIL_P(tmp) && rb_enc_asciicompat(enc = rb_enc_get(tmp))) {
10370 parse_mode_enc(RSTRING_PTR(tmp), enc, &enc, &enc2, NULL);
10371 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
10372 ecflags = rb_econv_prepare_options(opt, &ecopts, ecflags);
10373 }
10374 else {
10375 rb_io_ext_int_to_encs(find_encoding(v1), NULL, &enc, &enc2, 0);
10376 SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags);
10377 ecopts = Qnil;
10378 }
10379 }
10380 }
10381 validate_enc_binmode(&fptr->mode, ecflags, enc, enc2);
10382 fptr->encs.enc = enc;
10383 fptr->encs.enc2 = enc2;
10384 fptr->encs.ecflags = ecflags;
10385 fptr->encs.ecopts = ecopts;
10386 clear_codeconv(fptr);
10387
10388}
10389
10390 struct io_encoding_set_args {
10391 rb_io_t *fptr;
10392 VALUE v1;
10393 VALUE v2;
10394 VALUE opt;
10395};
10396
10397static VALUE
10398io_encoding_set_v(VALUE v)
10399{
10400 struct io_encoding_set_args *arg = (struct io_encoding_set_args *)v;
10401 io_encoding_set(arg->fptr, arg->v1, arg->v2, arg->opt);
10402 return Qnil;
10403}
10404
10405static VALUE
10406pipe_pair_close(VALUE rw)
10407{
10408 VALUE *rwp = (VALUE *)rw;
10409 return rb_ensure(io_close, rwp[0], io_close, rwp[1]);
10410}
10411
10412/*
10413 * call-seq:
10414 * IO.pipe -> [read_io, write_io]
10415 * IO.pipe(ext_enc) -> [read_io, write_io]
10416 * IO.pipe("ext_enc:int_enc" [, opt]) -> [read_io, write_io]
10417 * IO.pipe(ext_enc, int_enc [, opt]) -> [read_io, write_io]
10418 *
10419 * IO.pipe(...) {|read_io, write_io| ... }
10420 *
10421 * Creates a pair of pipe endpoints (connected to each other) and
10422 * returns them as a two-element array of IO objects:
10423 * <code>[</code> <i>read_io</i>, <i>write_io</i> <code>]</code>.
10424 *
10425 * If a block is given, the block is called and
10426 * returns the value of the block.
10427 * <i>read_io</i> and <i>write_io</i> are sent to the block as arguments.
10428 * If read_io and write_io are not closed when the block exits, they are closed.
10429 * i.e. closing read_io and/or write_io doesn't cause an error.
10430 *
10431 * Not available on all platforms.
10432 *
10433 * If an encoding (encoding name or encoding object) is specified as an optional argument,
10434 * read string from pipe is tagged with the encoding specified.
10435 * If the argument is a colon separated two encoding names "A:B",
10436 * the read string is converted from encoding A (external encoding)
10437 * to encoding B (internal encoding), then tagged with B.
10438 * If two optional arguments are specified, those must be
10439 * encoding objects or encoding names,
10440 * and the first one is the external encoding,
10441 * and the second one is the internal encoding.
10442 * If the external encoding and the internal encoding is specified,
10443 * optional hash argument specify the conversion option.
10444 *
10445 * In the example below, the two processes close the ends of the pipe
10446 * that they are not using. This is not just a cosmetic nicety. The
10447 * read end of a pipe will not generate an end of file condition if
10448 * there are any writers with the pipe still open. In the case of the
10449 * parent process, the <code>rd.read</code> will never return if it
10450 * does not first issue a <code>wr.close</code>.
10451 *
10452 * rd, wr = IO.pipe
10453 *
10454 * if fork
10455 * wr.close
10456 * puts "Parent got: <#{rd.read}>"
10457 * rd.close
10458 * Process.wait
10459 * else
10460 * rd.close
10461 * puts "Sending message to parent"
10462 * wr.write "Hi Dad"
10463 * wr.close
10464 * end
10465 *
10466 * <em>produces:</em>
10467 *
10468 * Sending message to parent
10469 * Parent got: <Hi Dad>
10470 */
10471
10472static VALUE
10473rb_io_s_pipe(int argc, VALUE *argv, VALUE klass)
10474{
10475 int pipes[2], state;
10476 VALUE r, w, args[3], v1, v2;
10477 VALUE opt;
10478 rb_io_t *fptr, *fptr2;
10479 struct io_encoding_set_args ies_args;
10480 int fmode = 0;
10481 VALUE ret;
10482
10483 argc = rb_scan_args(argc, argv, "02:", &v1, &v2, &opt);
10484 if (rb_pipe(pipes) < 0)
10485 rb_sys_fail(0);
10486
10487 args[0] = klass;
10488 args[1] = INT2NUM(pipes[0]);
10489 args[2] = INT2FIX(O_RDONLY);
10490 r = rb_protect(io_new_instance, (VALUE)args, &state);
10491 if (state) {
10492 close(pipes[0]);
10493 close(pipes[1]);
10494 rb_jump_tag(state);
10495 }
10496 GetOpenFile(r, fptr);
10497
10498 ies_args.fptr = fptr;
10499 ies_args.v1 = v1;
10500 ies_args.v2 = v2;
10501 ies_args.opt = opt;
10502 rb_protect(io_encoding_set_v, (VALUE)&ies_args, &state);
10503 if (state) {
10504 close(pipes[1]);
10505 io_close(r);
10506 rb_jump_tag(state);
10507 }
10508
10509 args[1] = INT2NUM(pipes[1]);
10510 args[2] = INT2FIX(O_WRONLY);
10511 w = rb_protect(io_new_instance, (VALUE)args, &state);
10512 if (state) {
10513 close(pipes[1]);
10514 if (!NIL_P(r)) rb_io_close(r);
10515 rb_jump_tag(state);
10516 }
10517 GetOpenFile(w, fptr2);
10518 rb_io_synchronized(fptr2);
10519
10520 extract_binmode(opt, &fmode);
10521
10522 if ((fmode & FMODE_BINMODE) && v1 == Qnil) {
10523 rb_io_ascii8bit_binmode(r);
10524 rb_io_ascii8bit_binmode(w);
10525 }
10526
10527#if DEFAULT_TEXTMODE
10528 if ((fptr->mode & FMODE_TEXTMODE) && (fmode & FMODE_BINMODE)) {
10529 fptr->mode &= ~FMODE_TEXTMODE;
10530 setmode(fptr->fd, O_BINARY);
10531 }
10532#if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
10533 if (fptr->encs.ecflags & ECONV_DEFAULT_NEWLINE_DECORATOR) {
10534 fptr->encs.ecflags |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;
10535 }
10536#endif
10537#endif
10538 fptr->mode |= fmode;
10539#if DEFAULT_TEXTMODE
10540 if ((fptr2->mode & FMODE_TEXTMODE) && (fmode & FMODE_BINMODE)) {
10541 fptr2->mode &= ~FMODE_TEXTMODE;
10542 setmode(fptr2->fd, O_BINARY);
10543 }
10544#endif
10545 fptr2->mode |= fmode;
10546
10547 ret = rb_assoc_new(r, w);
10548 if (rb_block_given_p()) {
10549 VALUE rw[2];
10550 rw[0] = r;
10551 rw[1] = w;
10552 return rb_ensure(rb_yield, ret, pipe_pair_close, (VALUE)rw);
10553 }
10554 return ret;
10555}
10556
10557 struct foreach_arg {
10558 int argc;
10559 VALUE *argv;
10560 VALUE io;
10561};
10562
10563static void
10564open_key_args(VALUE klass, int argc, VALUE *argv, VALUE opt, struct foreach_arg *arg)
10565{
10566 VALUE path, v;
10567 VALUE vmode = Qnil, vperm = Qnil;
10568
10569 path = *argv++;
10570 argc--;
10571 FilePathValue(path);
10572 arg->io = 0;
10573 arg->argc = argc;
10574 arg->argv = argv;
10575 if (NIL_P(opt)) {
10576 vmode = INT2NUM(O_RDONLY);
10577 vperm = INT2FIX(0666);
10578 }
10579 else if (!NIL_P(v = rb_hash_aref(opt, sym_open_args))) {
10580 int n;
10581
10582 v = rb_to_array_type(v);
10583 n = RARRAY_LENINT(v);
10584 rb_check_arity(n, 0, 3); /* rb_io_open */
10585 rb_scan_args_kw(RB_SCAN_ARGS_LAST_HASH_KEYWORDS, n, RARRAY_CONST_PTR(v), "02:", &vmode, &vperm, &opt);
10586 }
10587 arg->io = rb_io_open(klass, path, vmode, vperm, opt);
10588}
10589
10590static VALUE
10591io_s_foreach(VALUE v)
10592{
10593 struct getline_arg *arg = (void *)v;
10594 VALUE str;
10595
10596 while (!NIL_P(str = rb_io_getline_1(arg->rs, arg->limit, arg->chomp, arg->io))) {
10597 rb_lastline_set(str);
10598 rb_yield(str);
10599 }
10600 rb_lastline_set(Qnil);
10601 return Qnil;
10602}
10603
10604/*
10605 * call-seq:
10606 * IO.foreach(name, sep=$/ [, getline_args, open_args]) {|line| block } -> nil
10607 * IO.foreach(name, limit [, getline_args, open_args]) {|line| block } -> nil
10608 * IO.foreach(name, sep, limit [, getline_args, open_args]) {|line| block } -> nil
10609 * IO.foreach(...) -> an_enumerator
10610 *
10611 * Executes the block for every line in the named I/O port, where lines
10612 * are separated by <em>sep</em>.
10613 *
10614 * If no block is given, an enumerator is returned instead.
10615 *
10616 * IO.foreach("testfile") {|x| print "GOT ", x }
10617 *
10618 * <em>produces:</em>
10619 *
10620 * GOT This is line one
10621 * GOT This is line two
10622 * GOT This is line three
10623 * GOT And so on...
10624 *
10625 * If the last argument is a hash, it's the keyword argument to open.
10626 * See IO.readlines for details about getline_args.
10627 * And see also IO.read for details about open_args.
10628 *
10629 */
10630
10631static VALUE
10632rb_io_s_foreach(int argc, VALUE *argv, VALUE self)
10633{
10634 VALUE opt;
10635 int orig_argc = argc;
10636 struct foreach_arg arg;
10637 struct getline_arg garg;
10638
10639 argc = rb_scan_args(argc, argv, "13:", NULL, NULL, NULL, NULL, &opt);
10640 RETURN_ENUMERATOR(self, orig_argc, argv);
10641 extract_getline_args(argc-1, argv+1, &garg);
10642 open_key_args(self, argc, argv, opt, &arg);
10643 if (NIL_P(arg.io)) return Qnil;
10644 extract_getline_opts(opt, &garg);
10645 check_getline_args(&garg.rs, &garg.limit, garg.io = arg.io);
10646 return rb_ensure(io_s_foreach, (VALUE)&garg, rb_io_close, arg.io);
10647}
10648
10649static VALUE
10650io_s_readlines(VALUE v)
10651{
10652 struct getline_arg *arg = (void *)v;
10653 return io_readlines(arg, arg->io);
10654}
10655
10656/*
10657 * call-seq:
10658 * IO.readlines(name, sep=$/ [, getline_args, open_args]) -> array
10659 * IO.readlines(name, limit [, getline_args, open_args]) -> array
10660 * IO.readlines(name, sep, limit [, getline_args, open_args]) -> array
10661 *
10662 * Reads the entire file specified by <i>name</i> as individual
10663 * lines, and returns those lines in an array. Lines are separated by
10664 * <i>sep</i>.
10665 *
10666 * a = IO.readlines("testfile")
10667 * a[0] #=> "This is line one\n"
10668 *
10669 * b = IO.readlines("testfile", chomp: true)
10670 * b[0] #=> "This is line one"
10671 *
10672 * If the last argument is a hash, it's the keyword argument to open.
10673 *
10674 * === Options for getline
10675 *
10676 * The options hash accepts the following keys:
10677 *
10678 * :chomp::
10679 * When the optional +chomp+ keyword argument has a true value,
10680 * <code>\n</code>, <code>\r</code>, and <code>\r\n</code>
10681 * will be removed from the end of each line.
10682 *
10683 * See also IO.read for details about open_args.
10684 */
10685
10686static VALUE
10687rb_io_s_readlines(int argc, VALUE *argv, VALUE io)
10688{
10689 VALUE opt;
10690 struct foreach_arg arg;
10691 struct getline_arg garg;
10692
10693 argc = rb_scan_args(argc, argv, "13:", NULL, NULL, NULL, NULL, &opt);
10694 extract_getline_args(argc-1, argv+1, &garg);
10695 open_key_args(io, argc, argv, opt, &arg);
10696 if (NIL_P(arg.io)) return Qnil;
10697 extract_getline_opts(opt, &garg);
10698 check_getline_args(&garg.rs, &garg.limit, garg.io = arg.io);
10699 return rb_ensure(io_s_readlines, (VALUE)&garg, rb_io_close, arg.io);
10700}
10701
10702static VALUE
10703io_s_read(VALUE v)
10704{
10705 struct foreach_arg *arg = (void *)v;
10706 return io_read(arg->argc, arg->argv, arg->io);
10707}
10708
10709 struct seek_arg {
10710 VALUE io;
10711 VALUE offset;
10712 int mode;
10713};
10714
10715static VALUE
10716seek_before_access(VALUE argp)
10717{
10718 struct seek_arg *arg = (struct seek_arg *)argp;
10719 rb_io_binmode(arg->io);
10720 return rb_io_seek(arg->io, arg->offset, arg->mode);
10721}
10722
10723/*
10724 * call-seq:
10725 * IO.read(name, [length [, offset]] [, opt] ) -> string
10726 *
10727 * Opens the file, optionally seeks to the given +offset+, then returns
10728 * +length+ bytes (defaulting to the rest of the file). #read ensures
10729 * the file is closed before returning.
10730 *
10731 * If +name+ starts with a pipe character (<code>"|"</code>), a subprocess is
10732 * created in the same way as Kernel#open, and its output is returned.
10733 *
10734 * === Options
10735 *
10736 * The options hash accepts the following keys:
10737 *
10738 * :encoding::
10739 * string or encoding
10740 *
10741 * Specifies the encoding of the read string. +:encoding+ will be ignored
10742 * if +length+ is specified. See Encoding.aliases for possible encodings.
10743 *
10744 * :mode::
10745 * string or integer
10746 *
10747 * Specifies the <i>mode</i> argument for open(). It must start
10748 * with an "r", otherwise it will cause an error.
10749 * See IO.new for the list of possible modes.
10750 *
10751 * :open_args::
10752 * array
10753 *
10754 * Specifies arguments for open() as an array. This key can not be used
10755 * in combination with either +:encoding+ or +:mode+.
10756 *
10757 * Examples:
10758 *
10759 * IO.read("testfile") #=> "This is line one\nThis is line two\nThis is line three\nAnd so on...\n"
10760 * IO.read("testfile", 20) #=> "This is line one\nThi"
10761 * IO.read("testfile", 20, 10) #=> "ne one\nThis is line "
10762 * IO.read("binfile", mode: "rb") #=> "\xF7\x00\x00\x0E\x12"
10763 */
10764
10765static VALUE
10766rb_io_s_read(int argc, VALUE *argv, VALUE io)
10767{
10768 VALUE opt, offset;
10769 struct foreach_arg arg;
10770
10771 argc = rb_scan_args(argc, argv, "13:", NULL, NULL, &offset, NULL, &opt);
10772 open_key_args(io, argc, argv, opt, &arg);
10773 if (NIL_P(arg.io)) return Qnil;
10774 if (!NIL_P(offset)) {
10775 struct seek_arg sarg;
10776 int state = 0;
10777 sarg.io = arg.io;
10778 sarg.offset = offset;
10779 sarg.mode = SEEK_SET;
10780 rb_protect(seek_before_access, (VALUE)&sarg, &state);
10781 if (state) {
10782 rb_io_close(arg.io);
10783 rb_jump_tag(state);
10784 }
10785 if (arg.argc == 2) arg.argc = 1;
10786 }
10787 return rb_ensure(io_s_read, (VALUE)&arg, rb_io_close, arg.io);
10788}
10789
10790/*
10791 * call-seq:
10792 * IO.binread(name, [length [, offset]] ) -> string
10793 *
10794 * Opens the file, optionally seeks to the given <i>offset</i>, then
10795 * returns <i>length</i> bytes (defaulting to the rest of the file).
10796 * #binread ensures the file is closed before returning. The open mode
10797 * would be <code>"rb:ASCII-8BIT"</code>.
10798 *
10799 * IO.binread("testfile") #=> "This is line one\nThis is line two\nThis is line three\nAnd so on...\n"
10800 * IO.binread("testfile", 20) #=> "This is line one\nThi"
10801 * IO.binread("testfile", 20, 10) #=> "ne one\nThis is line "
10802 */
10803
10804static VALUE
10805rb_io_s_binread(int argc, VALUE *argv, VALUE io)
10806{
10807 VALUE offset;
10808 struct foreach_arg arg;
10809 enum {
10810 fmode = FMODE_READABLE|FMODE_BINMODE,
10811 oflags = O_RDONLY
10812#ifdef O_BINARY
10813 |O_BINARY
10814#endif
10815 };
10816 convconfig_t convconfig = {NULL, NULL, 0, Qnil};
10817
10818 rb_scan_args(argc, argv, "12", NULL, NULL, &offset);
10819 FilePathValue(argv[0]);
10820 convconfig.enc = rb_ascii8bit_encoding();
10821 arg.io = rb_io_open_generic(io, argv[0], oflags, fmode, &convconfig, 0);
10822 if (NIL_P(arg.io)) return Qnil;
10823 arg.argv = argv+1;
10824 arg.argc = (argc > 1) ? 1 : 0;
10825 if (!NIL_P(offset)) {
10826 struct seek_arg sarg;
10827 int state = 0;
10828 sarg.io = arg.io;
10829 sarg.offset = offset;
10830 sarg.mode = SEEK_SET;
10831 rb_protect(seek_before_access, (VALUE)&sarg, &state);
10832 if (state) {
10833 rb_io_close(arg.io);
10834 rb_jump_tag(state);
10835 }
10836 }
10837 return rb_ensure(io_s_read, (VALUE)&arg, rb_io_close, arg.io);
10838}
10839
10840static VALUE
10841io_s_write0(VALUE v)
10842{
10843 struct write_arg *arg = (void * )v;
10844 return io_write(arg->io,arg->str,arg->nosync);
10845}
10846
10847static VALUE
10848io_s_write(int argc, VALUE *argv, VALUE klass, int binary)
10849{
10850 VALUE string, offset, opt;
10851 struct foreach_arg arg;
10852 struct write_arg warg;
10853
10854 rb_scan_args(argc, argv, "21:", NULL, &string, &offset, &opt);
10855
10856 if (NIL_P(opt)) opt = rb_hash_new();
10857 else opt = rb_hash_dup(opt);
10858
10859
10860 if (NIL_P(rb_hash_aref(opt,sym_mode))) {
10861 int mode = O_WRONLY|O_CREAT;
10862#ifdef O_BINARY
10863 if (binary) mode |= O_BINARY;
10864#endif
10865 if (NIL_P(offset)) mode |= O_TRUNC;
10866 rb_hash_aset(opt,sym_mode,INT2NUM(mode));
10867 }
10868 open_key_args(klass, argc, argv, opt, &arg);
10869
10870#ifndef O_BINARY
10871 if (binary) rb_io_binmode_m(arg.io);
10872#endif
10873
10874 if (NIL_P(arg.io)) return Qnil;
10875 if (!NIL_P(offset)) {
10876 struct seek_arg sarg;
10877 int state = 0;
10878 sarg.io = arg.io;
10879 sarg.offset = offset;
10880 sarg.mode = SEEK_SET;
10881 rb_protect(seek_before_access, (VALUE)&sarg, &state);
10882 if (state) {
10883 rb_io_close(arg.io);
10884 rb_jump_tag(state);
10885 }
10886 }
10887
10888 warg.io = arg.io;
10889 warg.str = string;
10890 warg.nosync = 0;
10891
10892 return rb_ensure(io_s_write0, (VALUE)&warg, rb_io_close, arg.io);
10893}
10894
10895/*
10896 * call-seq:
10897 * IO.write(name, string [, offset]) -> integer
10898 * IO.write(name, string [, offset] [, opt]) -> integer
10899 *
10900 * Opens the file, optionally seeks to the given <i>offset</i>, writes
10901 * <i>string</i>, then returns the length written. #write ensures the
10902 * file is closed before returning. If <i>offset</i> is not given in
10903 * write mode, the file is truncated. Otherwise, it is not truncated.
10904 *
10905 * IO.write("testfile", "0123456789", 20) #=> 10
10906 * # File could contain: "This is line one\nThi0123456789two\nThis is line three\nAnd so on...\n"
10907 * IO.write("testfile", "0123456789") #=> 10
10908 * # File would now read: "0123456789"
10909 *
10910 * If the last argument is a hash, it specifies options for the internal
10911 * open(). It accepts the following keys:
10912 *
10913 * :encoding::
10914 * string or encoding
10915 *
10916 * Specifies the encoding of the read string.
10917 * See Encoding.aliases for possible encodings.
10918 *
10919 * :mode::
10920 * string or integer
10921 *
10922 * Specifies the <i>mode</i> argument for open(). It must start
10923 * with "w", "a", or "r+", otherwise it will cause an error.
10924 * See IO.new for the list of possible modes.
10925 *
10926 * :perm::
10927 * integer
10928 *
10929 * Specifies the <i>perm</i> argument for open().
10930 *
10931 * :open_args::
10932 * array
10933 *
10934 * Specifies arguments for open() as an array.
10935 * This key can not be used in combination with other keys.
10936 */
10937
10938static VALUE
10939rb_io_s_write(int argc, VALUE *argv, VALUE io)
10940{
10941 return io_s_write(argc, argv, io, 0);
10942}
10943
10944/*
10945 * call-seq:
10946 * IO.binwrite(name, string, [offset] ) -> integer
10947 * IO.binwrite(name, string, [offset], open_args ) -> integer
10948 *
10949 * Same as IO.write except opening the file in binary mode and
10950 * ASCII-8BIT encoding (<code>"wb:ASCII-8BIT"</code>).
10951 */
10952
10953static VALUE
10954rb_io_s_binwrite(int argc, VALUE *argv, VALUE io)
10955{
10956 return io_s_write(argc, argv, io, 1);
10957}
10958
10959 struct copy_stream_struct {
10960 VALUE src;
10961 VALUE dst;
10962 off_t copy_length; /* (off_t)-1 if not specified */
10963 off_t src_offset; /* (off_t)-1 if not specified */
10964
10965 int src_fd;
10966 int dst_fd;
10967 unsigned close_src : 1;
10968 unsigned close_dst : 1;
10969 int error_no;
10970 off_t total;
10971 const char *syserr;
10972 const char *notimp;
10973 VALUE th;
10974 struct stat src_stat;
10975 struct stat dst_stat;
10976#ifdef HAVE_FCOPYFILE
10977 copyfile_state_t copyfile_state;
10978#endif
10979};
10980
10981static void *
10982exec_interrupts(void *arg)
10983{
10984 VALUE th = (VALUE)arg;
10985 rb_thread_execute_interrupts(th);
10986 return NULL;
10987}
10988
10989/*
10990 * returns TRUE if the preceding system call was interrupted
10991 * so we can continue. If the thread was interrupted, we
10992 * reacquire the GVL to execute interrupts before continuing.
10993 */
10994static int
10995maygvl_copy_stream_continue_p(int has_gvl, struct copy_stream_struct *stp)
10996{
10997 switch (errno) {
10998 case EINTR:
10999#if defined(ERESTART)
11000 case ERESTART:
11001#endif
11002 if (rb_thread_interrupted(stp->th)) {
11003 if (has_gvl)
11004 rb_thread_execute_interrupts(stp->th);
11005 else
11006 rb_thread_call_with_gvl(exec_interrupts, (void *)stp->th);
11007 }
11008 return TRUE;
11009 }
11010 return FALSE;
11011}
11012
11013 struct wait_for_single_fd {
11014 VALUE scheduler;
11015
11016 int fd;
11017 short events;
11018
11019 VALUE result;
11020};
11021
11022static void *
11023rb_thread_scheduler_wait_for_single_fd(void * _args)
11024{
11025 struct wait_for_single_fd *args = (struct wait_for_single_fd *)_args;
11026
11027 args->result = rb_scheduler_io_wait(args->scheduler, rb_io_from_fd(args->fd), INT2NUM(args->events), Qnil);
11028
11029 return NULL;
11030}
11031
11032#if USE_POLL
11033# define IOWAIT_SYSCALL "poll"
11034 STATIC_ASSERT(pollin_expected, POLLIN == RB_WAITFD_IN);
11035 STATIC_ASSERT(pollout_expected, POLLOUT == RB_WAITFD_OUT);
11036static int
11037nogvl_wait_for_single_fd(VALUE th, int fd, short events)
11038{
11039 VALUE scheduler = rb_thread_scheduler_current(th);
11040 if (scheduler != Qnil) {
11041 struct wait_for_single_fd args = {.scheduler = scheduler, .fd = fd, .events = events};
11042 rb_thread_call_with_gvl(rb_thread_scheduler_wait_for_single_fd, &args);
11043 return RTEST(args.result);
11044 }
11045
11046 struct pollfd fds;
11047
11048 fds.fd = fd;
11049 fds.events = events;
11050
11051 return poll(&fds, 1, -1);
11052}
11053#else /* !USE_POLL */
11054# define IOWAIT_SYSCALL "select"
11055static int
11056nogvl_wait_for_single_fd(VALUE th, int fd, short events)
11057{
11058 VALUE scheduler = rb_thread_scheduler_current(th);
11059 if (scheduler != Qnil) {
11060 struct wait_for_single_fd args = {.scheduler = scheduler, .fd = fd, .events = events};
11061 rb_thread_call_with_gvl(rb_thread_scheduler_wait_for_single_fd, &args);
11062 return RTEST(args.result);
11063 }
11064
11065 rb_fdset_t fds;
11066 int ret;
11067
11068 rb_fd_init(&fds);
11069 rb_fd_set(fd, &fds);
11070
11071 switch (events) {
11072 case RB_WAITFD_IN:
11073 ret = rb_fd_select(fd + 1, &fds, 0, 0, 0);
11074 break;
11075 case RB_WAITFD_OUT:
11076 ret = rb_fd_select(fd + 1, 0, &fds, 0, 0);
11077 break;
11078 default:
11079 VM_UNREACHABLE(nogvl_wait_for_single_fd);
11080 }
11081
11082 rb_fd_term(&fds);
11083 return ret;
11084}
11085#endif /* !USE_POLL */
11086
11087static int
11088maygvl_copy_stream_wait_read(int has_gvl, struct copy_stream_struct *stp)
11089{
11090 int ret;
11091
11092 do {
11093 if (has_gvl) {
11094 ret = rb_wait_for_single_fd(stp->src_fd, RB_WAITFD_IN, NULL);
11095 }
11096 else {
11097 ret = nogvl_wait_for_single_fd(stp->th, stp->src_fd, RB_WAITFD_IN);
11098 }
11099 } while (ret < 0 && maygvl_copy_stream_continue_p(has_gvl, stp));
11100
11101 if (ret < 0) {
11102 stp->syserr = IOWAIT_SYSCALL;
11103 stp->error_no = errno;
11104 return ret;
11105 }
11106 return 0;
11107}
11108
11109static int
11110nogvl_copy_stream_wait_write(struct copy_stream_struct *stp)
11111{
11112 int ret;
11113
11114 do {
11115 ret = nogvl_wait_for_single_fd(stp->th, stp->dst_fd, RB_WAITFD_OUT);
11116 } while (ret < 0 && maygvl_copy_stream_continue_p(0, stp));
11117
11118 if (ret < 0) {
11119 stp->syserr = IOWAIT_SYSCALL;
11120 stp->error_no = errno;
11121 return ret;
11122 }
11123 return 0;
11124}
11125
11126#ifdef USE_COPY_FILE_RANGE
11127
11128static ssize_t
11129simple_copy_file_range(int in_fd, off_t *in_offset, int out_fd, off_t *out_offset, size_t count, unsigned int flags)
11130{
11131#ifdef HAVE_COPY_FILE_RANGE
11132 return copy_file_range(in_fd, in_offset, out_fd, out_offset, count, flags);
11133#else
11134 return syscall(__NR_copy_file_range, in_fd, in_offset, out_fd, out_offset, count, flags);
11135#endif
11136}
11137
11138static int
11139nogvl_copy_file_range(struct copy_stream_struct *stp)
11140{
11141 ssize_t ss;
11142 off_t src_size;
11143 off_t copy_length, src_offset, *src_offset_ptr;
11144
11145 if (!S_ISREG(stp->src_stat.st_mode))
11146 return 0;
11147
11148 src_size = stp->src_stat.st_size;
11149 src_offset = stp->src_offset;
11150 if (src_offset >= (off_t)0) {
11151 src_offset_ptr = &src_offset;
11152 }
11153 else {
11154 src_offset_ptr = NULL; /* if src_offset_ptr is NULL, then bytes are read from in_fd starting from the file offset */
11155 }
11156
11157 copy_length = stp->copy_length;
11158 if (copy_length < (off_t)0) {
11159 if (src_offset < (off_t)0) {
11160 off_t current_offset;
11161 errno = 0;
11162 current_offset = lseek(stp->src_fd, 0, SEEK_CUR);
11163 if (current_offset < (off_t)0 && errno) {
11164 stp->syserr = "lseek";
11165 stp->error_no = errno;
11166 return (int)current_offset;
11167 }
11168 copy_length = src_size - current_offset;
11169 }
11170 else {
11171 copy_length = src_size - src_offset;
11172 }
11173 }
11174
11175 retry_copy_file_range:
11176# if SIZEOF_OFF_T > SIZEOF_SIZE_T
11177 /* we are limited by the 32-bit ssize_t return value on 32-bit */
11178 ss = (copy_length > (off_t)SSIZE_MAX) ? SSIZE_MAX : (ssize_t)copy_length;
11179# else
11180 ss = (ssize_t)copy_length;
11181# endif
11182 ss = simple_copy_file_range(stp->src_fd, src_offset_ptr, stp->dst_fd, NULL, ss, 0);
11183 if (0 < ss) {
11184 stp->total += ss;
11185 copy_length -= ss;
11186 if (0 < copy_length) {
11187 goto retry_copy_file_range;
11188 }
11189 }
11190 if (ss < 0) {
11191 if (maygvl_copy_stream_continue_p(0, stp)) {
11192 goto retry_copy_file_range;
11193 }
11194 switch (errno) {
11195 case EINVAL:
11196 case EPERM: /* copy_file_range(2) doesn't exist (may happen in
11197 docker container) */
11198#ifdef ENOSYS
11199 case ENOSYS:
11200#endif
11201#ifdef EXDEV
11202 case EXDEV: /* in_fd and out_fd are not on the same filesystem */
11203#endif
11204 return 0;
11205 case EAGAIN:
11206#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
11207 case EWOULDBLOCK:
11208#endif
11209 {
11210 int ret = nogvl_copy_stream_wait_write(stp);
11211 if (ret < 0) return ret;
11212 }
11213 goto retry_copy_file_range;
11214 case EBADF:
11215 {
11216 int e = errno;
11217 int flags = fcntl(stp->dst_fd, F_GETFL);
11218
11219 if (flags != -1 && flags & O_APPEND) {
11220 return 0;
11221 }
11222 errno = e;
11223 }
11224 }
11225 stp->syserr = "copy_file_range";
11226 stp->error_no = errno;
11227 return (int)ss;
11228 }
11229 return 1;
11230}
11231#endif
11232
11233#ifdef HAVE_FCOPYFILE
11234static int
11235nogvl_fcopyfile(struct copy_stream_struct *stp)
11236{
11237 off_t cur, ss = 0;
11238 const off_t src_offset = stp->src_offset;
11239 int ret;
11240
11241 if (stp->copy_length >= (off_t)0) {
11242 /* copy_length can't be specified in fcopyfile(3) */
11243 return 0;
11244 }
11245
11246 if (!S_ISREG(stp->src_stat.st_mode))
11247 return 0;
11248
11249 if (!S_ISREG(stp->dst_stat.st_mode))
11250 return 0;
11251 if (lseek(stp->dst_fd, 0, SEEK_CUR) > (off_t)0) /* if dst IO was already written */
11252 return 0;
11253 if (fcntl(stp->dst_fd, F_GETFL) & O_APPEND) {
11254 /* fcopyfile(3) appends src IO to dst IO and then truncates
11255 * dst IO to src IO's original size. */
11256 off_t end = lseek(stp->dst_fd, 0, SEEK_END);
11257 lseek(stp->dst_fd, 0, SEEK_SET);
11258 if (end > (off_t)0) return 0;
11259 }
11260
11261 if (src_offset > (off_t)0) {
11262 off_t r;
11263
11264 /* get current offset */
11265 errno = 0;
11266 cur = lseek(stp->src_fd, 0, SEEK_CUR);
11267 if (cur < (off_t)0 && errno) {
11268 stp->error_no = errno;
11269 return 1;
11270 }
11271
11272 errno = 0;
11273 r = lseek(stp->src_fd, src_offset, SEEK_SET);
11274 if (r < (off_t)0 && errno) {
11275 stp->error_no = errno;
11276 return 1;
11277 }
11278 }
11279
11280 stp->copyfile_state = copyfile_state_alloc(); /* this will be freed by copy_stream_finalize() */
11281 ret = fcopyfile(stp->src_fd, stp->dst_fd, stp->copyfile_state, COPYFILE_DATA);
11282 copyfile_state_get(stp->copyfile_state, COPYFILE_STATE_COPIED, &ss); /* get copied bytes */
11283
11284 if (ret == 0) { /* success */
11285 stp->total = ss;
11286 if (src_offset > (off_t)0) {
11287 off_t r;
11288 errno = 0;
11289 /* reset offset */
11290 r = lseek(stp->src_fd, cur, SEEK_SET);
11291 if (r < (off_t)0 && errno) {
11292 stp->error_no = errno;
11293 return 1;
11294 }
11295 }
11296 }
11297 else {
11298 switch (errno) {
11299 case ENOTSUP:
11300 case EPERM:
11301 case EINVAL:
11302 return 0;
11303 }
11304 stp->syserr = "fcopyfile";
11305 stp->error_no = errno;
11306 return (int)ret;
11307 }
11308 return 1;
11309}
11310#endif
11311
11312#ifdef HAVE_SENDFILE
11313
11314# ifdef __linux__
11315# define USE_SENDFILE
11316
11317# ifdef HAVE_SYS_SENDFILE_H
11318# include <sys/sendfile.h>
11319# endif
11320
11321static ssize_t
11322simple_sendfile(int out_fd, int in_fd, off_t *offset, off_t count)
11323{
11324 return sendfile(out_fd, in_fd, offset, (size_t)count);
11325}
11326
11327# elif 0 /* defined(__FreeBSD__) || defined(__DragonFly__) */ || defined(__APPLE__)
11328/* This runs on FreeBSD8.1 r30210, but sendfiles blocks its execution
11329 * without cpuset -l 0.
11330 */
11331# define USE_SENDFILE
11332
11333static ssize_t
11334simple_sendfile(int out_fd, int in_fd, off_t *offset, off_t count)
11335{
11336 int r;
11337 off_t pos = offset ? *offset : lseek(in_fd, 0, SEEK_CUR);
11338 off_t sbytes;
11339# ifdef __APPLE__
11340 r = sendfile(in_fd, out_fd, pos, &count, NULL, 0);
11341 sbytes = count;
11342# else
11343 r = sendfile(in_fd, out_fd, pos, (size_t)count, NULL, &sbytes, 0);
11344# endif
11345 if (r != 0 && sbytes == 0) return r;
11346 if (offset) {
11347 *offset += sbytes;
11348 }
11349 else {
11350 lseek(in_fd, sbytes, SEEK_CUR);
11351 }
11352 return (ssize_t)sbytes;
11353}
11354
11355# endif
11356
11357#endif
11358
11359#ifdef USE_SENDFILE
11360static int
11361nogvl_copy_stream_sendfile(struct copy_stream_struct *stp)
11362{
11363 ssize_t ss;
11364 off_t src_size;
11365 off_t copy_length;
11366 off_t src_offset;
11367 int use_pread;
11368
11369 if (!S_ISREG(stp->src_stat.st_mode))
11370 return 0;
11371
11372 src_size = stp->src_stat.st_size;
11373#ifndef __linux__
11374 if ((stp->dst_stat.st_mode & S_IFMT) != S_IFSOCK)
11375 return 0;
11376#endif
11377
11378 src_offset = stp->src_offset;
11379 use_pread = src_offset >= (off_t)0;
11380
11381 copy_length = stp->copy_length;
11382 if (copy_length < (off_t)0) {
11383 if (use_pread)
11384 copy_length = src_size - src_offset;
11385 else {
11386 off_t cur;
11387 errno = 0;
11388 cur = lseek(stp->src_fd, 0, SEEK_CUR);
11389 if (cur < (off_t)0 && errno) {
11390 stp->syserr = "lseek";
11391 stp->error_no = errno;
11392 return (int)cur;
11393 }
11394 copy_length = src_size - cur;
11395 }
11396 }
11397
11398 retry_sendfile:
11399# if SIZEOF_OFF_T > SIZEOF_SIZE_T
11400 /* we are limited by the 32-bit ssize_t return value on 32-bit */
11401 ss = (copy_length > (off_t)SSIZE_MAX) ? SSIZE_MAX : (ssize_t)copy_length;
11402# else
11403 ss = (ssize_t)copy_length;
11404# endif
11405 if (use_pread) {
11406 ss = simple_sendfile(stp->dst_fd, stp->src_fd, &src_offset, ss);
11407 }
11408 else {
11409 ss = simple_sendfile(stp->dst_fd, stp->src_fd, NULL, ss);
11410 }
11411 if (0 < ss) {
11412 stp->total += ss;
11413 copy_length -= ss;
11414 if (0 < copy_length) {
11415 goto retry_sendfile;
11416 }
11417 }
11418 if (ss < 0) {
11419 if (maygvl_copy_stream_continue_p(0, stp))
11420 goto retry_sendfile;
11421 switch (errno) {
11422 case EINVAL:
11423#ifdef ENOSYS
11424 case ENOSYS:
11425#endif
11426#ifdef EOPNOTSUP
11427 /* some RedHat kernels may return EOPNOTSUP on an NFS mount.
11428 see also: [Feature #16965] */
11429 case EOPNOTSUP:
11430#endif
11431 return 0;
11432 case EAGAIN:
11433#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
11434 case EWOULDBLOCK:
11435#endif
11436 {
11437 int ret;
11438#ifndef __linux__
11439 /*
11440 * Linux requires stp->src_fd to be a mmap-able (regular) file,
11441 * select() reports regular files to always be "ready", so
11442 * there is no need to select() on it.
11443 * Other OSes may have the same limitation for sendfile() which
11444 * allow us to bypass maygvl_copy_stream_wait_read()...
11445 */
11446 ret = maygvl_copy_stream_wait_read(0, stp);
11447 if (ret < 0) return ret;
11448#endif
11449 ret = nogvl_copy_stream_wait_write(stp);
11450 if (ret < 0) return ret;
11451 }
11452 goto retry_sendfile;
11453 }
11454 stp->syserr = "sendfile";
11455 stp->error_no = errno;
11456 return (int)ss;
11457 }
11458 return 1;
11459}
11460#endif
11461
11462static ssize_t
11463maygvl_read(int has_gvl, int fd, void *buf, size_t count)
11464{
11465 if (has_gvl)
11466 return rb_read_internal(fd, buf, count);
11467 else
11468 return read(fd, buf, count);
11469}
11470
11471static ssize_t
11472maygvl_copy_stream_read(int has_gvl, struct copy_stream_struct *stp, char *buf, size_t len, off_t offset)
11473{
11474 ssize_t ss;
11475 retry_read:
11476 if (offset < (off_t)0) {
11477 ss = maygvl_read(has_gvl, stp->src_fd, buf, len);
11478 }
11479 else {
11480#ifdef HAVE_PREAD
11481 ss = pread(stp->src_fd, buf, len, offset);
11482#else
11483 stp->notimp = "pread";
11484 return -1;
11485#endif
11486 }
11487 if (ss == 0) {
11488 return 0;
11489 }
11490 if (ss < 0) {
11491 if (maygvl_copy_stream_continue_p(has_gvl, stp))
11492 goto retry_read;
11493 switch (errno) {
11494 case EAGAIN:
11495#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
11496 case EWOULDBLOCK:
11497#endif
11498 {
11499 int ret = maygvl_copy_stream_wait_read(has_gvl, stp);
11500 if (ret < 0) return ret;
11501 }
11502 goto retry_read;
11503#ifdef ENOSYS
11504 case ENOSYS:
11505 stp->notimp = "pread";
11506 return ss;
11507#endif
11508 }
11509 stp->syserr = offset < (off_t)0 ? "read" : "pread";
11510 stp->error_no = errno;
11511 }
11512 return ss;
11513}
11514
11515static int
11516nogvl_copy_stream_write(struct copy_stream_struct *stp, char *buf, size_t len)
11517{
11518 ssize_t ss;
11519 int off = 0;
11520 while (len) {
11521 ss = write(stp->dst_fd, buf+off, len);
11522 if (ss < 0) {
11523 if (maygvl_copy_stream_continue_p(0, stp))
11524 continue;
11525 if (errno == EAGAIN || errno == EWOULDBLOCK) {
11526 int ret = nogvl_copy_stream_wait_write(stp);
11527 if (ret < 0) return ret;
11528 continue;
11529 }
11530 stp->syserr = "write";
11531 stp->error_no = errno;
11532 return (int)ss;
11533 }
11534 off += (int)ss;
11535 len -= (int)ss;
11536 stp->total += ss;
11537 }
11538 return 0;
11539}
11540
11541static void
11542nogvl_copy_stream_read_write(struct copy_stream_struct *stp)
11543{
11544 char buf[1024*16];
11545 size_t len;
11546 ssize_t ss;
11547 int ret;
11548 off_t copy_length;
11549 int use_eof;
11550 off_t src_offset;
11551 int use_pread;
11552
11553 copy_length = stp->copy_length;
11554 use_eof = copy_length < (off_t)0;
11555 src_offset = stp->src_offset;
11556 use_pread = src_offset >= (off_t)0;
11557
11558 if (use_pread && stp->close_src) {
11559 off_t r;
11560 errno = 0;
11561 r = lseek(stp->src_fd, src_offset, SEEK_SET);
11562 if (r < (off_t)0 && errno) {
11563 stp->syserr = "lseek";
11564 stp->error_no = errno;
11565 return;
11566 }
11567 src_offset = (off_t)-1;
11568 use_pread = 0;
11569 }
11570
11571 while (use_eof || 0 < copy_length) {
11572 if (!use_eof && copy_length < (off_t)sizeof(buf)) {
11573 len = (size_t)copy_length;
11574 }
11575 else {
11576 len = sizeof(buf);
11577 }
11578 if (use_pread) {
11579 ss = maygvl_copy_stream_read(0, stp, buf, len, src_offset);
11580 if (0 < ss)
11581 src_offset += ss;
11582 }
11583 else {
11584 ss = maygvl_copy_stream_read(0, stp, buf, len, (off_t)-1);
11585 }
11586 if (ss <= 0) /* EOF or error */
11587 return;
11588
11589 ret = nogvl_copy_stream_write(stp, buf, ss);
11590 if (ret < 0)
11591 return;
11592
11593 if (!use_eof)
11594 copy_length -= ss;
11595 }
11596}
11597
11598static void *
11599nogvl_copy_stream_func(void *arg)
11600{
11601 struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
11602#if defined(USE_SENDFILE) || defined(USE_COPY_FILE_RANGE) || defined(HAVE_FCOPYFILE)
11603 int ret;
11604#endif
11605
11606#ifdef USE_COPY_FILE_RANGE
11607 ret = nogvl_copy_file_range(stp);
11608 if (ret != 0)
11609 goto finish; /* error or success */
11610#endif
11611
11612#ifdef HAVE_FCOPYFILE
11613 ret = nogvl_fcopyfile(stp);
11614 if (ret != 0)
11615 goto finish; /* error or success */
11616#endif
11617
11618#ifdef USE_SENDFILE
11619 ret = nogvl_copy_stream_sendfile(stp);
11620 if (ret != 0)
11621 goto finish; /* error or success */
11622#endif
11623
11624 nogvl_copy_stream_read_write(stp);
11625
11626#if defined(USE_SENDFILE) || defined(USE_COPY_FILE_RANGE) || defined(HAVE_FCOPYFILE)
11627 finish:
11628#endif
11629 return 0;
11630}
11631
11632static VALUE
11633copy_stream_fallback_body(VALUE arg)
11634{
11635 struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
11636 const int buflen = 16*1024;
11637 VALUE n;
11638 VALUE buf = rb_str_buf_new(buflen);
11639 off_t rest = stp->copy_length;
11640 off_t off = stp->src_offset;
11641 ID read_method = id_readpartial;
11642
11643 if (stp->src_fd < 0) {
11644 if (!rb_respond_to(stp->src, read_method)) {
11645 read_method = id_read;
11646 }
11647 }
11648
11649 while (1) {
11650 long numwrote;
11651 long l;
11652 if (stp->copy_length < (off_t)0) {
11653 l = buflen;
11654 }
11655 else {
11656 if (rest == 0) {
11657 rb_str_resize(buf, 0);
11658 break;
11659 }
11660 l = buflen < rest ? buflen : (long)rest;
11661 }
11662 if (stp->src_fd < 0) {
11663 VALUE rc = rb_funcall(stp->src, read_method, 2, INT2FIX(l), buf);
11664
11665 if (read_method == id_read && NIL_P(rc))
11666 break;
11667 }
11668 else {
11669 ssize_t ss;
11670 rb_str_resize(buf, buflen);
11671 ss = maygvl_copy_stream_read(1, stp, RSTRING_PTR(buf), l, off);
11672 rb_str_resize(buf, ss > 0 ? ss : 0);
11673 if (ss < 0)
11674 return Qnil;
11675 if (ss == 0)
11676 rb_eof_error();
11677 if (off >= (off_t)0)
11678 off += ss;
11679 }
11680 n = rb_io_write(stp->dst, buf);
11681 numwrote = NUM2LONG(n);
11682 stp->total += numwrote;
11683 rest -= numwrote;
11684 if (read_method == id_read && RSTRING_LEN(buf) == 0) {
11685 break;
11686 }
11687 }
11688
11689 return Qnil;
11690}
11691
11692static VALUE
11693copy_stream_fallback(struct copy_stream_struct *stp)
11694{
11695 if (stp->src_fd < 0 && stp->src_offset >= (off_t)0) {
11696 rb_raise(rb_eArgError, "cannot specify src_offset for non-IO");
11697 }
11698 rb_rescue2(copy_stream_fallback_body, (VALUE)stp,
11699 (VALUE (*) (VALUE, VALUE))0, (VALUE)0,
11700 rb_eEOFError, (VALUE)0);
11701 return Qnil;
11702}
11703
11704static VALUE
11705copy_stream_body(VALUE arg)
11706{
11707 struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
11708 VALUE src_io = stp->src, dst_io = stp->dst;
11709 rb_io_t *src_fptr = 0, *dst_fptr = 0;
11710 int src_fd, dst_fd;
11711 const int common_oflags = 0
11712#ifdef O_NOCTTY
11713 | O_NOCTTY
11714#endif
11715 ;
11716
11717 stp->th = rb_thread_current();
11718
11719 stp->total = 0;
11720
11721 if (src_io == argf ||
11722 !(RB_TYPE_P(src_io, T_FILE) ||
11723 RB_TYPE_P(src_io, T_STRING) ||
11724 rb_respond_to(src_io, rb_intern("to_path")))) {
11725 src_fd = -1;
11726 }
11727 else {
11728 int stat_ret;
11729 VALUE tmp_io = rb_io_check_io(src_io);
11730 if (!NIL_P(tmp_io)) {
11731 src_io = tmp_io;
11732 }
11733 else if (!RB_TYPE_P(src_io, T_FILE)) {
11734 VALUE args[2];
11735 FilePathValue(src_io);
11736 args[0] = src_io;
11737 args[1] = INT2NUM(O_RDONLY|common_oflags);
11738 src_io = rb_class_new_instance(2, args, rb_cFile);
11739 stp->src = src_io;
11740 stp->close_src = 1;
11741 }
11742 GetOpenFile(src_io, src_fptr);
11743 rb_io_check_byte_readable(src_fptr);
11744 src_fd = src_fptr->fd;
11745
11746 stat_ret = fstat(src_fd, &stp->src_stat);
11747 if (stat_ret < 0) {
11748 stp->syserr = "fstat";
11749 stp->error_no = errno;
11750 return Qnil;
11751 }
11752 }
11753 stp->src_fd = src_fd;
11754
11755 if (dst_io == argf ||
11756 !(RB_TYPE_P(dst_io, T_FILE) ||
11757 RB_TYPE_P(dst_io, T_STRING) ||
11758 rb_respond_to(dst_io, rb_intern("to_path")))) {
11759 dst_fd = -1;
11760 }
11761 else {
11762 int stat_ret;
11763 VALUE tmp_io = rb_io_check_io(dst_io);
11764 if (!NIL_P(tmp_io)) {
11765 dst_io = GetWriteIO(tmp_io);
11766 }
11767 else if (!RB_TYPE_P(dst_io, T_FILE)) {
11768 VALUE args[3];
11769 FilePathValue(dst_io);
11770 args[0] = dst_io;
11771 args[1] = INT2NUM(O_WRONLY|O_CREAT|O_TRUNC|common_oflags);
11772 args[2] = INT2FIX(0666);
11773 dst_io = rb_class_new_instance(3, args, rb_cFile);
11774 stp->dst = dst_io;
11775 stp->close_dst = 1;
11776 }
11777 else {
11778 dst_io = GetWriteIO(dst_io);
11779 stp->dst = dst_io;
11780 }
11781 GetOpenFile(dst_io, dst_fptr);
11782 rb_io_check_writable(dst_fptr);
11783 dst_fd = dst_fptr->fd;
11784
11785 stat_ret = fstat(dst_fd, &stp->dst_stat);
11786 if (stat_ret < 0) {
11787 stp->syserr = "fstat";
11788 stp->error_no = errno;
11789 return Qnil;
11790 }
11791 }
11792 stp->dst_fd = dst_fd;
11793
11794#ifdef O_BINARY
11795 if (src_fptr)
11796 SET_BINARY_MODE_WITH_SEEK_CUR(src_fptr);
11797#endif
11798 if (dst_fptr)
11799 io_ascii8bit_binmode(dst_fptr);
11800
11801 if (stp->src_offset < (off_t)0 && src_fptr && src_fptr->rbuf.len) {
11802 size_t len = src_fptr->rbuf.len;
11803 VALUE str;
11804 if (stp->copy_length >= (off_t)0 && stp->copy_length < (off_t)len) {
11805 len = (size_t)stp->copy_length;
11806 }
11807 str = rb_str_buf_new(len);
11808 rb_str_resize(str,len);
11809 read_buffered_data(RSTRING_PTR(str), len, src_fptr);
11810 if (dst_fptr) { /* IO or filename */
11811 if (io_binwrite(str, RSTRING_PTR(str), RSTRING_LEN(str), dst_fptr, 0) < 0)
11812 rb_sys_fail_on_write(dst_fptr);
11813 }
11814 else /* others such as StringIO */
11815 rb_io_write(dst_io, str);
11816 rb_str_resize(str, 0);
11817 stp->total += len;
11818 if (stp->copy_length >= (off_t)0)
11819 stp->copy_length -= len;
11820 }
11821
11822 if (dst_fptr && io_fflush(dst_fptr) < 0) {
11823 rb_raise(rb_eIOError, "flush failed");
11824 }
11825
11826 if (stp->copy_length == 0)
11827 return Qnil;
11828
11829 if (src_fd < 0 || dst_fd < 0) {
11830 return copy_stream_fallback(stp);
11831 }
11832
11833 rb_thread_call_without_gvl(nogvl_copy_stream_func, (void*)stp, RUBY_UBF_IO, 0);
11834 return Qnil;
11835}
11836
11837static VALUE
11838copy_stream_finalize(VALUE arg)
11839{
11840 struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
11841
11842#ifdef HAVE_FCOPYFILE
11843 if (stp->copyfile_state) {
11844 copyfile_state_free(stp->copyfile_state);
11845 }
11846#endif
11847
11848 if (stp->close_src) {
11849 rb_io_close_m(stp->src);
11850 }
11851 if (stp->close_dst) {
11852 rb_io_close_m(stp->dst);
11853 }
11854 if (stp->syserr) {
11855 rb_syserr_fail(stp->error_no, stp->syserr);
11856 }
11857 if (stp->notimp) {
11858 rb_raise(rb_eNotImpError, "%s() not implemented", stp->notimp);
11859 }
11860 return Qnil;
11861}
11862
11863/*
11864 * call-seq:
11865 * IO.copy_stream(src, dst)
11866 * IO.copy_stream(src, dst, copy_length)
11867 * IO.copy_stream(src, dst, copy_length, src_offset)
11868 *
11869 * IO.copy_stream copies <i>src</i> to <i>dst</i>.
11870 * <i>src</i> and <i>dst</i> is either a filename or an IO-like object.
11871 * IO-like object for <i>src</i> should have #readpartial or #read
11872 * method. IO-like object for <i>dst</i> should have #write method.
11873 * (Specialized mechanisms, such as sendfile system call, may be used
11874 * on appropriate situation.)
11875 *
11876 * This method returns the number of bytes copied.
11877 *
11878 * If optional arguments are not given,
11879 * the start position of the copy is
11880 * the beginning of the filename or
11881 * the current file offset of the IO.
11882 * The end position of the copy is the end of file.
11883 *
11884 * If <i>copy_length</i> is given,
11885 * No more than <i>copy_length</i> bytes are copied.
11886 *
11887 * If <i>src_offset</i> is given,
11888 * it specifies the start position of the copy.
11889 *
11890 * When <i>src_offset</i> is specified and
11891 * <i>src</i> is an IO,
11892 * IO.copy_stream doesn't move the current file offset.
11893 *
11894 */
11895static VALUE
11896rb_io_s_copy_stream(int argc, VALUE *argv, VALUE io)
11897{
11898 VALUE src, dst, length, src_offset;
11899 struct copy_stream_struct st;
11900
11901 MEMZERO(&st, struct copy_stream_struct, 1);
11902
11903 rb_scan_args(argc, argv, "22", &src, &dst, &length, &src_offset);
11904
11905 st.src = src;
11906 st.dst = dst;
11907
11908 if (NIL_P(length))
11909 st.copy_length = (off_t)-1;
11910 else
11911 st.copy_length = NUM2OFFT(length);
11912
11913 if (NIL_P(src_offset))
11914 st.src_offset = (off_t)-1;
11915 else
11916 st.src_offset = NUM2OFFT(src_offset);
11917
11918 rb_ensure(copy_stream_body, (VALUE)&st, copy_stream_finalize, (VALUE)&st);
11919
11920 return OFFT2NUM(st.total);
11921}
11922
11923/*
11924 * call-seq:
11925 * io.external_encoding -> encoding
11926 *
11927 * Returns the Encoding object that represents the encoding of the file.
11928 * If _io_ is in write mode and no encoding is specified, returns +nil+.
11929 */
11930
11931static VALUE
11932rb_io_external_encoding(VALUE io)
11933{
11934 rb_io_t *fptr;
11935
11936 GetOpenFile(io, fptr);
11937 if (fptr->encs.enc2) {
11938 return rb_enc_from_encoding(fptr->encs.enc2);
11939 }
11940 if (fptr->mode & FMODE_WRITABLE) {
11941 if (fptr->encs.enc)
11942 return rb_enc_from_encoding(fptr->encs.enc);
11943 return Qnil;
11944 }
11945 return rb_enc_from_encoding(io_read_encoding(fptr));
11946}
11947
11948/*
11949 * call-seq:
11950 * io.internal_encoding -> encoding
11951 *
11952 * Returns the Encoding of the internal string if conversion is
11953 * specified. Otherwise returns +nil+.
11954 */
11955
11956static VALUE
11957rb_io_internal_encoding(VALUE io)
11958{
11959 rb_io_t *fptr;
11960
11961 GetOpenFile(io, fptr);
11962 if (!fptr->encs.enc2) return Qnil;
11963 return rb_enc_from_encoding(io_read_encoding(fptr));
11964}
11965
11966/*
11967 * call-seq:
11968 * io.set_encoding(ext_enc) -> io
11969 * io.set_encoding("ext_enc:int_enc") -> io
11970 * io.set_encoding(ext_enc, int_enc) -> io
11971 * io.set_encoding("ext_enc:int_enc", opt) -> io
11972 * io.set_encoding(ext_enc, int_enc, opt) -> io
11973 *
11974 * If single argument is specified, read string from io is tagged
11975 * with the encoding specified. If encoding is a colon separated two
11976 * encoding names "A:B", the read string is converted from encoding A
11977 * (external encoding) to encoding B (internal encoding), then tagged
11978 * with B. If two arguments are specified, those must be encoding
11979 * objects or encoding names, and the first one is the external encoding, and the
11980 * second one is the internal encoding.
11981 * If the external encoding and the internal encoding is specified,
11982 * optional hash argument specify the conversion option.
11983 */
11984
11985static VALUE
11986rb_io_set_encoding(int argc, VALUE *argv, VALUE io)
11987{
11988 rb_io_t *fptr;
11989 VALUE v1, v2, opt;
11990
11991 if (!RB_TYPE_P(io, T_FILE)) {
11992 return rb_funcallv(io, id_set_encoding, argc, argv);
11993 }
11994
11995 argc = rb_scan_args(argc, argv, "11:", &v1, &v2, &opt);
11996 GetOpenFile(io, fptr);
11997 io_encoding_set(fptr, v1, v2, opt);
11998 return io;
11999}
12000
12001void
12002 rb_stdio_set_default_encoding(void)
12003{
12004 VALUE val = Qnil;
12005
12006 rb_io_set_encoding(1, &val, rb_stdin);
12007 rb_io_set_encoding(1, &val, rb_stdout);
12008 rb_io_set_encoding(1, &val, rb_stderr);
12009}
12010
12011static inline int
12012global_argf_p(VALUE arg)
12013{
12014 return arg == argf;
12015}
12016
12017/*
12018 * call-seq:
12019 * ARGF.external_encoding -> encoding
12020 *
12021 * Returns the external encoding for files read from +ARGF+ as an +Encoding+
12022 * object. The external encoding is the encoding of the text as stored in a
12023 * file. Contrast with +ARGF.internal_encoding+, which is the encoding used
12024 * to represent this text within Ruby.
12025 *
12026 * To set the external encoding use +ARGF.set_encoding+.
12027 *
12028 * For example:
12029 *
12030 * ARGF.external_encoding #=> #<Encoding:UTF-8>
12031 *
12032 */
12033static VALUE
12034argf_external_encoding(VALUE argf)
12035{
12036 if (!RTEST(ARGF.current_file)) {
12037 return rb_enc_from_encoding(rb_default_external_encoding());
12038 }
12039 return rb_io_external_encoding(rb_io_check_io(ARGF.current_file));
12040}
12041
12042/*
12043 * call-seq:
12044 * ARGF.internal_encoding -> encoding
12045 *
12046 * Returns the internal encoding for strings read from +ARGF+ as an
12047 * +Encoding+ object.
12048 *
12049 * If +ARGF.set_encoding+ has been called with two encoding names, the second
12050 * is returned. Otherwise, if +Encoding.default_external+ has been set, that
12051 * value is returned. Failing that, if a default external encoding was
12052 * specified on the command-line, that value is used. If the encoding is
12053 * unknown, +nil+ is returned.
12054 */
12055static VALUE
12056argf_internal_encoding(VALUE argf)
12057{
12058 if (!RTEST(ARGF.current_file)) {
12059 return rb_enc_from_encoding(rb_default_external_encoding());
12060 }
12061 return rb_io_internal_encoding(rb_io_check_io(ARGF.current_file));
12062}
12063
12064/*
12065 * call-seq:
12066 * ARGF.set_encoding(ext_enc) -> ARGF
12067 * ARGF.set_encoding("ext_enc:int_enc") -> ARGF
12068 * ARGF.set_encoding(ext_enc, int_enc) -> ARGF
12069 * ARGF.set_encoding("ext_enc:int_enc", opt) -> ARGF
12070 * ARGF.set_encoding(ext_enc, int_enc, opt) -> ARGF
12071 *
12072 * If single argument is specified, strings read from ARGF are tagged with
12073 * the encoding specified.
12074 *
12075 * If two encoding names separated by a colon are given, e.g. "ascii:utf-8",
12076 * the read string is converted from the first encoding (external encoding)
12077 * to the second encoding (internal encoding), then tagged with the second
12078 * encoding.
12079 *
12080 * If two arguments are specified, they must be encoding objects or encoding
12081 * names. Again, the first specifies the external encoding; the second
12082 * specifies the internal encoding.
12083 *
12084 * If the external encoding and the internal encoding are specified, the
12085 * optional +Hash+ argument can be used to adjust the conversion process. The
12086 * structure of this hash is explained in the String#encode documentation.
12087 *
12088 * For example:
12089 *
12090 * ARGF.set_encoding('ascii') # Tag the input as US-ASCII text
12091 * ARGF.set_encoding(Encoding::UTF_8) # Tag the input as UTF-8 text
12092 * ARGF.set_encoding('utf-8','ascii') # Transcode the input from US-ASCII
12093 * # to UTF-8.
12094 */
12095static VALUE
12096argf_set_encoding(int argc, VALUE *argv, VALUE argf)
12097{
12098 rb_io_t *fptr;
12099
12100 if (!next_argv()) {
12101 rb_raise(rb_eArgError, "no stream to set encoding");
12102 }
12103 rb_io_set_encoding(argc, argv, ARGF.current_file);
12104 GetOpenFile(ARGF.current_file, fptr);
12105 ARGF.encs = fptr->encs;
12106 return argf;
12107}
12108
12109/*
12110 * call-seq:
12111 * ARGF.tell -> Integer
12112 * ARGF.pos -> Integer
12113 *
12114 * Returns the current offset (in bytes) of the current file in +ARGF+.
12115 *
12116 * ARGF.pos #=> 0
12117 * ARGF.gets #=> "This is line one\n"
12118 * ARGF.pos #=> 17
12119 *
12120 */
12121static VALUE
12122argf_tell(VALUE argf)
12123{
12124 if (!next_argv()) {
12125 rb_raise(rb_eArgError, "no stream to tell");
12126 }
12127 ARGF_FORWARD(0, 0);
12128 return rb_io_tell(ARGF.current_file);
12129}
12130
12131/*
12132 * call-seq:
12133 * ARGF.seek(amount, whence=IO::SEEK_SET) -> 0
12134 *
12135 * Seeks to offset _amount_ (an +Integer+) in the +ARGF+ stream according to
12136 * the value of _whence_. See IO#seek for further details.
12137 */
12138static VALUE
12139argf_seek_m(int argc, VALUE *argv, VALUE argf)
12140{
12141 if (!next_argv()) {
12142 rb_raise(rb_eArgError, "no stream to seek");
12143 }
12144 ARGF_FORWARD(argc, argv);
12145 return rb_io_seek_m(argc, argv, ARGF.current_file);
12146}
12147
12148/*
12149 * call-seq:
12150 * ARGF.pos = position -> Integer
12151 *
12152 * Seeks to the position given by _position_ (in bytes) in +ARGF+.
12153 *
12154 * For example:
12155 *
12156 * ARGF.pos = 17
12157 * ARGF.gets #=> "This is line two\n"
12158 */
12159static VALUE
12160argf_set_pos(VALUE argf, VALUE offset)
12161{
12162 if (!next_argv()) {
12163 rb_raise(rb_eArgError, "no stream to set position");
12164 }
12165 ARGF_FORWARD(1, &offset);
12166 return rb_io_set_pos(ARGF.current_file, offset);
12167}
12168
12169/*
12170 * call-seq:
12171 * ARGF.rewind -> 0
12172 *
12173 * Positions the current file to the beginning of input, resetting
12174 * +ARGF.lineno+ to zero.
12175 *
12176 * ARGF.readline #=> "This is line one\n"
12177 * ARGF.rewind #=> 0
12178 * ARGF.lineno #=> 0
12179 * ARGF.readline #=> "This is line one\n"
12180 */
12181static VALUE
12182argf_rewind(VALUE argf)
12183{
12184 VALUE ret;
12185 int old_lineno;
12186
12187 if (!next_argv()) {
12188 rb_raise(rb_eArgError, "no stream to rewind");
12189 }
12190 ARGF_FORWARD(0, 0);
12191 old_lineno = RFILE(ARGF.current_file)->fptr->lineno;
12192 ret = rb_io_rewind(ARGF.current_file);
12193 if (!global_argf_p(argf)) {
12194 ARGF.last_lineno = ARGF.lineno -= old_lineno;
12195 }
12196 return ret;
12197}
12198
12199/*
12200 * call-seq:
12201 * ARGF.fileno -> integer
12202 * ARGF.to_i -> integer
12203 *
12204 * Returns an integer representing the numeric file descriptor for
12205 * the current file. Raises an +ArgumentError+ if there isn't a current file.
12206 *
12207 * ARGF.fileno #=> 3
12208 */
12209static VALUE
12210argf_fileno(VALUE argf)
12211{
12212 if (!next_argv()) {
12213 rb_raise(rb_eArgError, "no stream");
12214 }
12215 ARGF_FORWARD(0, 0);
12216 return rb_io_fileno(ARGF.current_file);
12217}
12218
12219/*
12220 * call-seq:
12221 * ARGF.to_io -> IO
12222 *
12223 * Returns an +IO+ object representing the current file. This will be a
12224 * +File+ object unless the current file is a stream such as STDIN.
12225 *
12226 * For example:
12227 *
12228 * ARGF.to_io #=> #<File:glark.txt>
12229 * ARGF.to_io #=> #<IO:<STDIN>>
12230 */
12231static VALUE
12232argf_to_io(VALUE argf)
12233{
12234 next_argv();
12235 ARGF_FORWARD(0, 0);
12236 return ARGF.current_file;
12237}
12238
12239/*
12240 * call-seq:
12241 * ARGF.eof? -> true or false
12242 * ARGF.eof -> true or false
12243 *
12244 * Returns true if the current file in +ARGF+ is at end of file, i.e. it has
12245 * no data to read. The stream must be opened for reading or an +IOError+
12246 * will be raised.
12247 *
12248 * $ echo "eof" | ruby argf.rb
12249 *
12250 * ARGF.eof? #=> false
12251 * 3.times { ARGF.readchar }
12252 * ARGF.eof? #=> false
12253 * ARGF.readchar #=> "\n"
12254 * ARGF.eof? #=> true
12255 */
12256
12257static VALUE
12258argf_eof(VALUE argf)
12259{
12260 next_argv();
12261 if (RTEST(ARGF.current_file)) {
12262 if (ARGF.init_p == 0) return Qtrue;
12263 next_argv();
12264 ARGF_FORWARD(0, 0);
12265 if (rb_io_eof(ARGF.current_file)) {
12266 return Qtrue;
12267 }
12268 }
12269 return Qfalse;
12270}
12271
12272/*
12273 * call-seq:
12274 * ARGF.read([length [, outbuf]]) -> string, outbuf, or nil
12275 *
12276 * Reads _length_ bytes from ARGF. The files named on the command line
12277 * are concatenated and treated as a single file by this method, so when
12278 * called without arguments the contents of this pseudo file are returned in
12279 * their entirety.
12280 *
12281 * _length_ must be a non-negative integer or +nil+.
12282 *
12283 * If _length_ is a positive integer, +read+ tries to read
12284 * _length_ bytes without any conversion (binary mode).
12285 * It returns +nil+ if an EOF is encountered before anything can be read.
12286 * Fewer than _length_ bytes are returned if an EOF is encountered during
12287 * the read.
12288 * In the case of an integer _length_, the resulting string is always
12289 * in ASCII-8BIT encoding.
12290 *
12291 * If _length_ is omitted or is +nil+, it reads until EOF
12292 * and the encoding conversion is applied, if applicable.
12293 * A string is returned even if EOF is encountered before any data is read.
12294 *
12295 * If _length_ is zero, it returns an empty string (<code>""</code>).
12296 *
12297 * If the optional _outbuf_ argument is present,
12298 * it must reference a String, which will receive the data.
12299 * The _outbuf_ will contain only the received data after the method call
12300 * even if it is not empty at the beginning.
12301 *
12302 * For example:
12303 *
12304 * $ echo "small" > small.txt
12305 * $ echo "large" > large.txt
12306 * $ ./glark.rb small.txt large.txt
12307 *
12308 * ARGF.read #=> "small\nlarge"
12309 * ARGF.read(200) #=> "small\nlarge"
12310 * ARGF.read(2) #=> "sm"
12311 * ARGF.read(0) #=> ""
12312 *
12313 * Note that this method behaves like the fread() function in C.
12314 * This means it retries to invoke read(2) system calls to read data
12315 * with the specified length.
12316 * If you need the behavior like a single read(2) system call,
12317 * consider ARGF#readpartial or ARGF#read_nonblock.
12318 */
12319
12320static VALUE
12321argf_read(int argc, VALUE *argv, VALUE argf)
12322{
12323 VALUE tmp, str, length;
12324 long len = 0;
12325
12326 rb_scan_args(argc, argv, "02", &length, &str);
12327 if (!NIL_P(length)) {
12328 len = NUM2LONG(argv[0]);
12329 }
12330 if (!NIL_P(str)) {
12331 StringValue(str);
12332 rb_str_resize(str,0);
12333 argv[1] = Qnil;
12334 }
12335
12336 retry:
12337 if (!next_argv()) {
12338 return str;
12339 }
12340 if (ARGF_GENERIC_INPUT_P()) {
12341 tmp = argf_forward(argc, argv, argf);
12342 }
12343 else {
12344 tmp = io_read(argc, argv, ARGF.current_file);
12345 }
12346 if (NIL_P(str)) str = tmp;
12347 else if (!NIL_P(tmp)) rb_str_append(str, tmp);
12348 if (NIL_P(tmp) || NIL_P(length)) {
12349 if (ARGF.next_p != -1) {
12350 argf_close(argf);
12351 ARGF.next_p = 1;
12352 goto retry;
12353 }
12354 }
12355 else if (argc >= 1) {
12356 long slen = RSTRING_LEN(str);
12357 if (slen < len) {
12358 len -= slen;
12359 argv[0] = LONG2NUM(len);
12360 goto retry;
12361 }
12362 }
12363 return str;
12364}
12365
12366 struct argf_call_arg {
12367 int argc;
12368 VALUE *argv;
12369 VALUE argf;
12370};
12371
12372static VALUE
12373argf_forward_call(VALUE arg)
12374{
12375 struct argf_call_arg *p = (struct argf_call_arg *)arg;
12376 argf_forward(p->argc, p->argv, p->argf);
12377 return Qnil;
12378}
12379
12380static VALUE argf_getpartial(int argc, VALUE *argv, VALUE argf, VALUE opts,
12381 int nonblock);
12382
12383/*
12384 * call-seq:
12385 * ARGF.readpartial(maxlen) -> string
12386 * ARGF.readpartial(maxlen, outbuf) -> outbuf
12387 *
12388 * Reads at most _maxlen_ bytes from the ARGF stream.
12389 *
12390 * If the optional _outbuf_ argument is present,
12391 * it must reference a String, which will receive the data.
12392 * The _outbuf_ will contain only the received data after the method call
12393 * even if it is not empty at the beginning.
12394 *
12395 * It raises EOFError on end of ARGF stream.
12396 * Since ARGF stream is a concatenation of multiple files,
12397 * internally EOF is occur for each file.
12398 * ARGF.readpartial returns empty strings for EOFs except the last one and
12399 * raises EOFError for the last one.
12400 *
12401 */
12402
12403static VALUE
12404argf_readpartial(int argc, VALUE *argv, VALUE argf)
12405{
12406 return argf_getpartial(argc, argv, argf, Qnil, 0);
12407}
12408
12409/*
12410 * call-seq:
12411 * ARGF.read_nonblock(maxlen[, options]) -> string
12412 * ARGF.read_nonblock(maxlen, outbuf[, options]) -> outbuf
12413 *
12414 * Reads at most _maxlen_ bytes from the ARGF stream in non-blocking mode.
12415 */
12416
12417static VALUE
12418argf_read_nonblock(int argc, VALUE *argv, VALUE argf)
12419{
12420 VALUE opts;
12421
12422 rb_scan_args(argc, argv, "11:", NULL, NULL, &opts);
12423
12424 if (!NIL_P(opts))
12425 argc--;
12426
12427 return argf_getpartial(argc, argv, argf, opts, 1);
12428}
12429
12430static VALUE
12431argf_getpartial(int argc, VALUE *argv, VALUE argf, VALUE opts, int nonblock)
12432{
12433 VALUE tmp, str, length;
12434 int no_exception;
12435
12436 rb_scan_args(argc, argv, "11", &length, &str);
12437 if (!NIL_P(str)) {
12438 StringValue(str);
12439 argv[1] = str;
12440 }
12441 no_exception = no_exception_p(opts);
12442
12443 if (!next_argv()) {
12444 if (!NIL_P(str)) {
12445 rb_str_resize(str, 0);
12446 }
12447 rb_eof_error();
12448 }
12449 if (ARGF_GENERIC_INPUT_P()) {
12450 VALUE (*const rescue_does_nothing)(VALUE, VALUE) = 0;
12451 struct argf_call_arg arg;
12452 arg.argc = argc;
12453 arg.argv = argv;
12454 arg.argf = argf;
12455 tmp = rb_rescue2(argf_forward_call, (VALUE)&arg,
12456 rescue_does_nothing, Qnil, rb_eEOFError, (VALUE)0);
12457 }
12458 else {
12459 tmp = io_getpartial(argc, argv, ARGF.current_file, no_exception, nonblock);
12460 }
12461 if (NIL_P(tmp)) {
12462 if (ARGF.next_p == -1) {
12463 return io_nonblock_eof(no_exception);
12464 }
12465 argf_close(argf);
12466 ARGF.next_p = 1;
12467 if (RARRAY_LEN(ARGF.argv) == 0) {
12468 return io_nonblock_eof(no_exception);
12469 }
12470 if (NIL_P(str))
12471 str = rb_str_new(NULL, 0);
12472 return str;
12473 }
12474 return tmp;
12475}
12476
12477/*
12478 * call-seq:
12479 * ARGF.getc -> String or nil
12480 *
12481 * Reads the next character from +ARGF+ and returns it as a +String+. Returns
12482 * +nil+ at the end of the stream.
12483 *
12484 * +ARGF+ treats the files named on the command line as a single file created
12485 * by concatenating their contents. After returning the last character of the
12486 * first file, it returns the first character of the second file, and so on.
12487 *
12488 * For example:
12489 *
12490 * $ echo "foo" > file
12491 * $ ruby argf.rb file
12492 *
12493 * ARGF.getc #=> "f"
12494 * ARGF.getc #=> "o"
12495 * ARGF.getc #=> "o"
12496 * ARGF.getc #=> "\n"
12497 * ARGF.getc #=> nil
12498 * ARGF.getc #=> nil
12499 */
12500static VALUE
12501argf_getc(VALUE argf)
12502{
12503 VALUE ch;
12504
12505 retry:
12506 if (!next_argv()) return Qnil;
12507 if (ARGF_GENERIC_INPUT_P()) {
12508 ch = rb_funcall3(ARGF.current_file, rb_intern("getc"), 0, 0);
12509 }
12510 else {
12511 ch = rb_io_getc(ARGF.current_file);
12512 }
12513 if (NIL_P(ch) && ARGF.next_p != -1) {
12514 argf_close(argf);
12515 ARGF.next_p = 1;
12516 goto retry;
12517 }
12518
12519 return ch;
12520}
12521
12522/*
12523 * call-seq:
12524 * ARGF.getbyte -> Integer or nil
12525 *
12526 * Gets the next 8-bit byte (0..255) from +ARGF+. Returns +nil+ if called at
12527 * the end of the stream.
12528 *
12529 * For example:
12530 *
12531 * $ echo "foo" > file
12532 * $ ruby argf.rb file
12533 *
12534 * ARGF.getbyte #=> 102
12535 * ARGF.getbyte #=> 111
12536 * ARGF.getbyte #=> 111
12537 * ARGF.getbyte #=> 10
12538 * ARGF.getbyte #=> nil
12539 */
12540static VALUE
12541argf_getbyte(VALUE argf)
12542{
12543 VALUE ch;
12544
12545 retry:
12546 if (!next_argv()) return Qnil;
12547 if (!RB_TYPE_P(ARGF.current_file, T_FILE)) {
12548 ch = rb_funcall3(ARGF.current_file, rb_intern("getbyte"), 0, 0);
12549 }
12550 else {
12551 ch = rb_io_getbyte(ARGF.current_file);
12552 }
12553 if (NIL_P(ch) && ARGF.next_p != -1) {
12554 argf_close(argf);
12555 ARGF.next_p = 1;
12556 goto retry;
12557 }
12558
12559 return ch;
12560}
12561
12562/*
12563 * call-seq:
12564 * ARGF.readchar -> String or nil
12565 *
12566 * Reads the next character from +ARGF+ and returns it as a +String+. Raises
12567 * an +EOFError+ after the last character of the last file has been read.
12568 *
12569 * For example:
12570 *
12571 * $ echo "foo" > file
12572 * $ ruby argf.rb file
12573 *
12574 * ARGF.readchar #=> "f"
12575 * ARGF.readchar #=> "o"
12576 * ARGF.readchar #=> "o"
12577 * ARGF.readchar #=> "\n"
12578 * ARGF.readchar #=> end of file reached (EOFError)
12579 */
12580static VALUE
12581argf_readchar(VALUE argf)
12582{
12583 VALUE ch;
12584
12585 retry:
12586 if (!next_argv()) rb_eof_error();
12587 if (!RB_TYPE_P(ARGF.current_file, T_FILE)) {
12588 ch = rb_funcall3(ARGF.current_file, rb_intern("getc"), 0, 0);
12589 }
12590 else {
12591 ch = rb_io_getc(ARGF.current_file);
12592 }
12593 if (NIL_P(ch) && ARGF.next_p != -1) {
12594 argf_close(argf);
12595 ARGF.next_p = 1;
12596 goto retry;
12597 }
12598
12599 return ch;
12600}
12601
12602/*
12603 * call-seq:
12604 * ARGF.readbyte -> Integer
12605 *
12606 * Reads the next 8-bit byte from ARGF and returns it as an +Integer+. Raises
12607 * an +EOFError+ after the last byte of the last file has been read.
12608 *
12609 * For example:
12610 *
12611 * $ echo "foo" > file
12612 * $ ruby argf.rb file
12613 *
12614 * ARGF.readbyte #=> 102
12615 * ARGF.readbyte #=> 111
12616 * ARGF.readbyte #=> 111
12617 * ARGF.readbyte #=> 10
12618 * ARGF.readbyte #=> end of file reached (EOFError)
12619 */
12620static VALUE
12621argf_readbyte(VALUE argf)
12622{
12623 VALUE c;
12624
12625 NEXT_ARGF_FORWARD(0, 0);
12626 c = argf_getbyte(argf);
12627 if (NIL_P(c)) {
12628 rb_eof_error();
12629 }
12630 return c;
12631}
12632
12633#define FOREACH_ARGF() while (next_argv())
12634
12635static VALUE
12636argf_block_call_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, argf))
12637{
12638 const VALUE current = ARGF.current_file;
12639 rb_yield_values2(argc, argv);
12640 if (ARGF.init_p == -1 || current != ARGF.current_file) {
12641 rb_iter_break_value(Qundef);
12642 }
12643 return Qnil;
12644}
12645
12646#define ARGF_block_call(mid, argc, argv, func, argf) \
12647 rb_block_call_kw(ARGF.current_file, mid, argc, argv, \
12648 func, argf, rb_keyword_given_p())
12649
12650static void
12651argf_block_call(ID mid, int argc, VALUE *argv, VALUE argf)
12652{
12653 VALUE ret = ARGF_block_call(mid, argc, argv, argf_block_call_i, argf);
12654 if (ret != Qundef) ARGF.next_p = 1;
12655}
12656
12657static VALUE
12658argf_block_call_line_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, argf))
12659{
12660 if (!global_argf_p(argf)) {
12661 ARGF.last_lineno = ++ARGF.lineno;
12662 }
12663 return argf_block_call_i(i, argf, argc, argv, blockarg);
12664}
12665
12666static void
12667argf_block_call_line(ID mid, int argc, VALUE *argv, VALUE argf)
12668{
12669 VALUE ret = ARGF_block_call(mid, argc, argv, argf_block_call_line_i, argf);
12670 if (ret != Qundef) ARGF.next_p = 1;
12671}
12672
12673/*
12674 * call-seq:
12675 * ARGF.each(sep=$/) {|line| block } -> ARGF
12676 * ARGF.each(sep=$/, limit) {|line| block } -> ARGF
12677 * ARGF.each(...) -> an_enumerator
12678 *
12679 * ARGF.each_line(sep=$/) {|line| block } -> ARGF
12680 * ARGF.each_line(sep=$/, limit) {|line| block } -> ARGF
12681 * ARGF.each_line(...) -> an_enumerator
12682 *
12683 * Returns an enumerator which iterates over each line (separated by _sep_,
12684 * which defaults to your platform's newline character) of each file in
12685 * +ARGV+. If a block is supplied, each line in turn will be yielded to the
12686 * block, otherwise an enumerator is returned.
12687 * The optional _limit_ argument is an +Integer+ specifying the maximum
12688 * length of each line; longer lines will be split according to this limit.
12689 *
12690 * This method allows you to treat the files supplied on the command line as
12691 * a single file consisting of the concatenation of each named file. After
12692 * the last line of the first file has been returned, the first line of the
12693 * second file is returned. The +ARGF.filename+ and +ARGF.lineno+ methods can
12694 * be used to determine the filename of the current line and line number of
12695 * the whole input, respectively.
12696 *
12697 * For example, the following code prints out each line of each named file
12698 * prefixed with its line number, displaying the filename once per file:
12699 *
12700 * ARGF.each_line do |line|
12701 * puts ARGF.filename if ARGF.file.lineno == 1
12702 * puts "#{ARGF.file.lineno}: #{line}"
12703 * end
12704 *
12705 * While the following code prints only the first file's name at first, and
12706 * the contents with line number counted through all named files.
12707 *
12708 * ARGF.each_line do |line|
12709 * puts ARGF.filename if ARGF.lineno == 1
12710 * puts "#{ARGF.lineno}: #{line}"
12711 * end
12712 */
12713static VALUE
12714argf_each_line(int argc, VALUE *argv, VALUE argf)
12715{
12716 RETURN_ENUMERATOR(argf, argc, argv);
12717 FOREACH_ARGF() {
12718 argf_block_call_line(rb_intern("each_line"), argc, argv, argf);
12719 }
12720 return argf;
12721}
12722
12723/*
12724 * call-seq:
12725 * ARGF.each_byte {|byte| block } -> ARGF
12726 * ARGF.each_byte -> an_enumerator
12727 *
12728 * Iterates over each byte of each file in +ARGV+.
12729 * A byte is returned as an +Integer+ in the range 0..255.
12730 *
12731 * This method allows you to treat the files supplied on the command line as
12732 * a single file consisting of the concatenation of each named file. After
12733 * the last byte of the first file has been returned, the first byte of the
12734 * second file is returned. The +ARGF.filename+ method can be used to
12735 * determine the filename of the current byte.
12736 *
12737 * If no block is given, an enumerator is returned instead.
12738 *
12739 * For example:
12740 *
12741 * ARGF.bytes.to_a #=> [35, 32, ... 95, 10]
12742 *
12743 */
12744static VALUE
12745argf_each_byte(VALUE argf)
12746{
12747 RETURN_ENUMERATOR(argf, 0, 0);
12748 FOREACH_ARGF() {
12749 argf_block_call(rb_intern("each_byte"), 0, 0, argf);
12750 }
12751 return argf;
12752}
12753
12754/*
12755 * call-seq:
12756 * ARGF.each_char {|char| block } -> ARGF
12757 * ARGF.each_char -> an_enumerator
12758 *
12759 * Iterates over each character of each file in +ARGF+.
12760 *
12761 * This method allows you to treat the files supplied on the command line as
12762 * a single file consisting of the concatenation of each named file. After
12763 * the last character of the first file has been returned, the first
12764 * character of the second file is returned. The +ARGF.filename+ method can
12765 * be used to determine the name of the file in which the current character
12766 * appears.
12767 *
12768 * If no block is given, an enumerator is returned instead.
12769 */
12770static VALUE
12771argf_each_char(VALUE argf)
12772{
12773 RETURN_ENUMERATOR(argf, 0, 0);
12774 FOREACH_ARGF() {
12775 argf_block_call(rb_intern("each_char"), 0, 0, argf);
12776 }
12777 return argf;
12778}
12779
12780/*
12781 * call-seq:
12782 * ARGF.each_codepoint {|codepoint| block } -> ARGF
12783 * ARGF.each_codepoint -> an_enumerator
12784 *
12785 * Iterates over each codepoint of each file in +ARGF+.
12786 *
12787 * This method allows you to treat the files supplied on the command line as
12788 * a single file consisting of the concatenation of each named file. After
12789 * the last codepoint of the first file has been returned, the first
12790 * codepoint of the second file is returned. The +ARGF.filename+ method can
12791 * be used to determine the name of the file in which the current codepoint
12792 * appears.
12793 *
12794 * If no block is given, an enumerator is returned instead.
12795 */
12796static VALUE
12797argf_each_codepoint(VALUE argf)
12798{
12799 RETURN_ENUMERATOR(argf, 0, 0);
12800 FOREACH_ARGF() {
12801 argf_block_call(rb_intern("each_codepoint"), 0, 0, argf);
12802 }
12803 return argf;
12804}
12805
12806/*
12807 * call-seq:
12808 * ARGF.filename -> String
12809 * ARGF.path -> String
12810 *
12811 * Returns the current filename. "-" is returned when the current file is
12812 * STDIN.
12813 *
12814 * For example:
12815 *
12816 * $ echo "foo" > foo
12817 * $ echo "bar" > bar
12818 * $ echo "glark" > glark
12819 *
12820 * $ ruby argf.rb foo bar glark
12821 *
12822 * ARGF.filename #=> "foo"
12823 * ARGF.read(5) #=> "foo\nb"
12824 * ARGF.filename #=> "bar"
12825 * ARGF.skip
12826 * ARGF.filename #=> "glark"
12827 */
12828static VALUE
12829argf_filename(VALUE argf)
12830{
12831 next_argv();
12832 return ARGF.filename;
12833}
12834
12835static VALUE
12836argf_filename_getter(ID id, VALUE *var)
12837{
12838 return argf_filename(*var);
12839}
12840
12841/*
12842 * call-seq:
12843 * ARGF.file -> IO or File object
12844 *
12845 * Returns the current file as an +IO+ or +File+ object.
12846 * <code>$stdin</code> is returned when the current file is STDIN.
12847 *
12848 * For example:
12849 *
12850 * $ echo "foo" > foo
12851 * $ echo "bar" > bar
12852 *
12853 * $ ruby argf.rb foo bar
12854 *
12855 * ARGF.file #=> #<File:foo>
12856 * ARGF.read(5) #=> "foo\nb"
12857 * ARGF.file #=> #<File:bar>
12858 */
12859static VALUE
12860argf_file(VALUE argf)
12861{
12862 next_argv();
12863 return ARGF.current_file;
12864}
12865
12866/*
12867 * call-seq:
12868 * ARGF.binmode -> ARGF
12869 *
12870 * Puts +ARGF+ into binary mode. Once a stream is in binary mode, it cannot
12871 * be reset to non-binary mode. This option has the following effects:
12872 *
12873 * * Newline conversion is disabled.
12874 * * Encoding conversion is disabled.
12875 * * Content is treated as ASCII-8BIT.
12876 */
12877static VALUE
12878argf_binmode_m(VALUE argf)
12879{
12880 ARGF.binmode = 1;
12881 next_argv();
12882 ARGF_FORWARD(0, 0);
12883 rb_io_ascii8bit_binmode(ARGF.current_file);
12884 return argf;
12885}
12886
12887/*
12888 * call-seq:
12889 * ARGF.binmode? -> true or false
12890 *
12891 * Returns true if +ARGF+ is being read in binary mode; false otherwise.
12892 * To enable binary mode use +ARGF.binmode+.
12893 *
12894 * For example:
12895 *
12896 * ARGF.binmode? #=> false
12897 * ARGF.binmode
12898 * ARGF.binmode? #=> true
12899 */
12900static VALUE
12901argf_binmode_p(VALUE argf)
12902{
12903 return ARGF.binmode ? Qtrue : Qfalse;
12904}
12905
12906/*
12907 * call-seq:
12908 * ARGF.skip -> ARGF
12909 *
12910 * Sets the current file to the next file in ARGV. If there aren't any more
12911 * files it has no effect.
12912 *
12913 * For example:
12914 *
12915 * $ ruby argf.rb foo bar
12916 * ARGF.filename #=> "foo"
12917 * ARGF.skip
12918 * ARGF.filename #=> "bar"
12919 */
12920static VALUE
12921argf_skip(VALUE argf)
12922{
12923 if (ARGF.init_p && ARGF.next_p == 0) {
12924 argf_close(argf);
12925 ARGF.next_p = 1;
12926 }
12927 return argf;
12928}
12929
12930/*
12931 * call-seq:
12932 * ARGF.close -> ARGF
12933 *
12934 * Closes the current file and skips to the next file in ARGV. If there are
12935 * no more files to open, just closes the current file. +STDIN+ will not be
12936 * closed.
12937 *
12938 * For example:
12939 *
12940 * $ ruby argf.rb foo bar
12941 *
12942 * ARGF.filename #=> "foo"
12943 * ARGF.close
12944 * ARGF.filename #=> "bar"
12945 * ARGF.close
12946 */
12947static VALUE
12948argf_close_m(VALUE argf)
12949{
12950 next_argv();
12951 argf_close(argf);
12952 if (ARGF.next_p != -1) {
12953 ARGF.next_p = 1;
12954 }
12955 ARGF.lineno = 0;
12956 return argf;
12957}
12958
12959/*
12960 * call-seq:
12961 * ARGF.closed? -> true or false
12962 *
12963 * Returns _true_ if the current file has been closed; _false_ otherwise. Use
12964 * +ARGF.close+ to actually close the current file.
12965 */
12966static VALUE
12967argf_closed(VALUE argf)
12968{
12969 next_argv();
12970 ARGF_FORWARD(0, 0);
12971 return rb_io_closed(ARGF.current_file);
12972}
12973
12974/*
12975 * call-seq:
12976 * ARGF.to_s -> String
12977 *
12978 * Returns "ARGF".
12979 */
12980static VALUE
12981argf_to_s(VALUE argf)
12982{
12983 return rb_str_new2("ARGF");
12984}
12985
12986/*
12987 * call-seq:
12988 * ARGF.inplace_mode -> String
12989 *
12990 * Returns the file extension appended to the names of modified files under
12991 * in-place edit mode. This value can be set using +ARGF.inplace_mode=+ or
12992 * passing the +-i+ switch to the Ruby binary.
12993 */
12994static VALUE
12995argf_inplace_mode_get(VALUE argf)
12996{
12997 if (!ARGF.inplace) return Qnil;
12998 if (NIL_P(ARGF.inplace)) return rb_str_new(0, 0);
12999 return rb_str_dup(ARGF.inplace);
13000}
13001
13002static VALUE
13003opt_i_get(ID id, VALUE *var)
13004{
13005 return argf_inplace_mode_get(*var);
13006}
13007
13008/*
13009 * call-seq:
13010 * ARGF.inplace_mode = ext -> ARGF
13011 *
13012 * Sets the filename extension for in-place editing mode to the given String.
13013 * Each file being edited has this value appended to its filename. The
13014 * modified file is saved under this new name.
13015 *
13016 * For example:
13017 *
13018 * $ ruby argf.rb file.txt
13019 *
13020 * ARGF.inplace_mode = '.bak'
13021 * ARGF.each_line do |line|
13022 * print line.sub("foo","bar")
13023 * end
13024 *
13025 * Each line of _file.txt_ has the first occurrence of "foo" replaced with
13026 * "bar", then the new line is written out to _file.txt.bak_.
13027 */
13028static VALUE
13029argf_inplace_mode_set(VALUE argf, VALUE val)
13030{
13031 if (!RTEST(val)) {
13032 ARGF.inplace = Qfalse;
13033 }
13034 else if (StringValueCStr(val), !RSTRING_LEN(val)) {
13035 ARGF.inplace = Qnil;
13036 }
13037 else {
13038 ARGF.inplace = rb_str_new_frozen(val);
13039 }
13040 return argf;
13041}
13042
13043static void
13044opt_i_set(VALUE val, ID id, VALUE *var)
13045{
13046 argf_inplace_mode_set(*var, val);
13047}
13048
13049void
13050 ruby_set_inplace_mode(const char *suffix)
13051{
13052 ARGF.inplace = !suffix ? Qfalse : !*suffix ? Qnil : rb_str_new(suffix, strlen(suffix));
13053}
13054
13055/*
13056 * call-seq:
13057 * ARGF.argv -> ARGV
13058 *
13059 * Returns the +ARGV+ array, which contains the arguments passed to your
13060 * script, one per element.
13061 *
13062 * For example:
13063 *
13064 * $ ruby argf.rb -v glark.txt
13065 *
13066 * ARGF.argv #=> ["-v", "glark.txt"]
13067 *
13068 */
13069static VALUE
13070argf_argv(VALUE argf)
13071{
13072 return ARGF.argv;
13073}
13074
13075static VALUE
13076argf_argv_getter(ID id, VALUE *var)
13077{
13078 return argf_argv(*var);
13079}
13080
13081 VALUE
13082 rb_get_argv(void)
13083{
13084 return ARGF.argv;
13085}
13086
13087/*
13088 * call-seq:
13089 * ARGF.to_write_io -> io
13090 *
13091 * Returns IO instance tied to _ARGF_ for writing if inplace mode is
13092 * enabled.
13093 */
13094static VALUE
13095argf_write_io(VALUE argf)
13096{
13097 if (!RTEST(ARGF.current_file)) {
13098 rb_raise(rb_eIOError, "not opened for writing");
13099 }
13100 return GetWriteIO(ARGF.current_file);
13101}
13102
13103/*
13104 * call-seq:
13105 * ARGF.write(string) -> integer
13106 *
13107 * Writes _string_ if inplace mode.
13108 */
13109static VALUE
13110argf_write(VALUE argf, VALUE str)
13111{
13112 return rb_io_write(argf_write_io(argf), str);
13113}
13114
13115void
13116 rb_readwrite_sys_fail(enum rb_io_wait_readwrite waiting, const char *mesg)
13117{
13118 rb_readwrite_syserr_fail(waiting, errno, mesg);
13119}
13120
13121void
13122 rb_readwrite_syserr_fail(enum rb_io_wait_readwrite waiting, int n, const char *mesg)
13123{
13124 VALUE arg, c = Qnil;
13125 arg = mesg ? rb_str_new2(mesg) : Qnil;
13126 switch (waiting) {
13127 case RB_IO_WAIT_WRITABLE:
13128 switch (n) {
13129 case EAGAIN:
13130 c = rb_eEAGAINWaitWritable;
13131 break;
13132#if EAGAIN != EWOULDBLOCK
13133 case EWOULDBLOCK:
13134 c = rb_eEWOULDBLOCKWaitWritable;
13135 break;
13136#endif
13137 case EINPROGRESS:
13138 c = rb_eEINPROGRESSWaitWritable;
13139 break;
13140 default:
13141 rb_mod_syserr_fail_str(rb_mWaitWritable, n, arg);
13142 }
13143 break;
13144 case RB_IO_WAIT_READABLE:
13145 switch (n) {
13146 case EAGAIN:
13147 c = rb_eEAGAINWaitReadable;
13148 break;
13149#if EAGAIN != EWOULDBLOCK
13150 case EWOULDBLOCK:
13151 c = rb_eEWOULDBLOCKWaitReadable;
13152 break;
13153#endif
13154 case EINPROGRESS:
13155 c = rb_eEINPROGRESSWaitReadable;
13156 break;
13157 default:
13158 rb_mod_syserr_fail_str(rb_mWaitReadable, n, arg);
13159 }
13160 break;
13161 default:
13162 rb_bug("invalid read/write type passed to rb_readwrite_sys_fail: %d", waiting);
13163 }
13164 rb_exc_raise(rb_class_new_instance(1, &arg, c));
13165}
13166
13167static VALUE
13168get_LAST_READ_LINE(ID _x, VALUE *_y)
13169{
13170 return rb_lastline_get();
13171}
13172
13173static void
13174set_LAST_READ_LINE(VALUE val, ID _x, VALUE *_y)
13175{
13176 rb_lastline_set(val);
13177}
13178
13179/*
13180 * Document-class: IOError
13181 *
13182 * Raised when an IO operation fails.
13183 *
13184 * File.open("/etc/hosts") {|f| f << "example"}
13185 * #=> IOError: not opened for writing
13186 *
13187 * File.open("/etc/hosts") {|f| f.close; f.read }
13188 * #=> IOError: closed stream
13189 *
13190 * Note that some IO failures raise <code>SystemCallError</code>s
13191 * and these are not subclasses of IOError:
13192 *
13193 * File.open("does/not/exist")
13194 * #=> Errno::ENOENT: No such file or directory - does/not/exist
13195 */
13196
13197/*
13198 * Document-class: EOFError
13199 *
13200 * Raised by some IO operations when reaching the end of file. Many IO
13201 * methods exist in two forms,
13202 *
13203 * one that returns +nil+ when the end of file is reached, the other
13204 * raises +EOFError+.
13205 *
13206 * +EOFError+ is a subclass of +IOError+.
13207 *
13208 * file = File.open("/etc/hosts")
13209 * file.read
13210 * file.gets #=> nil
13211 * file.readline #=> EOFError: end of file reached
13212 */
13213
13214/*
13215 * Document-class: ARGF
13216 *
13217 * +ARGF+ is a stream designed for use in scripts that process files given as
13218 * command-line arguments or passed in via STDIN.
13219 *
13220 * The arguments passed to your script are stored in the +ARGV+ Array, one
13221 * argument per element. +ARGF+ assumes that any arguments that aren't
13222 * filenames have been removed from +ARGV+. For example:
13223 *
13224 * $ ruby argf.rb --verbose file1 file2
13225 *
13226 * ARGV #=> ["--verbose", "file1", "file2"]
13227 * option = ARGV.shift #=> "--verbose"
13228 * ARGV #=> ["file1", "file2"]
13229 *
13230 * You can now use +ARGF+ to work with a concatenation of each of these named
13231 * files. For instance, +ARGF.read+ will return the contents of _file1_
13232 * followed by the contents of _file2_.
13233 *
13234 * After a file in +ARGV+ has been read +ARGF+ removes it from the Array.
13235 * Thus, after all files have been read +ARGV+ will be empty.
13236 *
13237 * You can manipulate +ARGV+ yourself to control what +ARGF+ operates on. If
13238 * you remove a file from +ARGV+, it is ignored by +ARGF+; if you add files to
13239 * +ARGV+, they are treated as if they were named on the command line. For
13240 * example:
13241 *
13242 * ARGV.replace ["file1"]
13243 * ARGF.readlines # Returns the contents of file1 as an Array
13244 * ARGV #=> []
13245 * ARGV.replace ["file2", "file3"]
13246 * ARGF.read # Returns the contents of file2 and file3
13247 *
13248 * If +ARGV+ is empty, +ARGF+ acts as if it contained STDIN, i.e. the data
13249 * piped to your script. For example:
13250 *
13251 * $ echo "glark" | ruby -e 'p ARGF.read'
13252 * "glark\n"
13253 */
13254
13255/*
13256 * The IO class is the basis for all input and output in Ruby.
13257 * An I/O stream may be <em>duplexed</em> (that is, bidirectional), and
13258 * so may use more than one native operating system stream.
13259 *
13260 * Many of the examples in this section use the File class, the only standard
13261 * subclass of IO. The two classes are closely associated. Like the File
13262 * class, the Socket library subclasses from IO (such as TCPSocket or
13263 * UDPSocket).
13264 *
13265 * The Kernel#open method can create an IO (or File) object for these types
13266 * of arguments:
13267 *
13268 * * A plain string represents a filename suitable for the underlying
13269 * operating system.
13270 *
13271 * * A string starting with <code>"|"</code> indicates a subprocess.
13272 * The remainder of the string following the <code>"|"</code> is
13273 * invoked as a process with appropriate input/output channels
13274 * connected to it.
13275 *
13276 * * A string equal to <code>"|-"</code> will create another Ruby
13277 * instance as a subprocess.
13278 *
13279 * The IO may be opened with different file modes (read-only, write-only) and
13280 * encodings for proper conversion. See IO.new for these options. See
13281 * Kernel#open for details of the various command formats described above.
13282 *
13283 * IO.popen, the Open3 library, or Process#spawn may also be used to
13284 * communicate with subprocesses through an IO.
13285 *
13286 * Ruby will convert pathnames between different operating system
13287 * conventions if possible. For instance, on a Windows system the
13288 * filename <code>"/gumby/ruby/test.rb"</code> will be opened as
13289 * <code>"\gumby\ruby\test.rb"</code>. When specifying a Windows-style
13290 * filename in a Ruby string, remember to escape the backslashes:
13291 *
13292 * "C:\\gumby\\ruby\\test.rb"
13293 *
13294 * Our examples here will use the Unix-style forward slashes;
13295 * File::ALT_SEPARATOR can be used to get the platform-specific separator
13296 * character.
13297 *
13298 * The global constant ARGF (also accessible as <code>$<</code>) provides an
13299 * IO-like stream which allows access to all files mentioned on the
13300 * command line (or STDIN if no files are mentioned). ARGF#path and its alias
13301 * ARGF#filename are provided to access the name of the file currently being
13302 * read.
13303 *
13304 * == io/console
13305 *
13306 * The io/console extension provides methods for interacting with the
13307 * console. The console can be accessed from IO.console or the standard
13308 * input/output/error IO objects.
13309 *
13310 * Requiring io/console adds the following methods:
13311 *
13312 * * IO::console
13313 * * IO#raw
13314 * * IO#raw!
13315 * * IO#cooked
13316 * * IO#cooked!
13317 * * IO#getch
13318 * * IO#echo=
13319 * * IO#echo?
13320 * * IO#noecho
13321 * * IO#winsize
13322 * * IO#winsize=
13323 * * IO#iflush
13324 * * IO#ioflush
13325 * * IO#oflush
13326 *
13327 * Example:
13328 *
13329 * require 'io/console'
13330 * rows, columns = $stdout.winsize
13331 * puts "Your screen is #{columns} wide and #{rows} tall"
13332 */
13333
13334void
13335Init_IO(void)
13336{
13337 VALUE rb_cARGF;
13338#ifdef __CYGWIN__
13339#include <sys/cygwin.h>
13340 static struct __cygwin_perfile pf[] =
13341 {
13342 {"", O_RDONLY | O_BINARY},
13343 {"", O_WRONLY | O_BINARY},
13344 {"", O_RDWR | O_BINARY},
13345 {"", O_APPEND | O_BINARY},
13346 {NULL, 0}
13347 };
13348 cygwin_internal(CW_PERFILE, pf);
13349#endif
13350
13351 rb_eIOError = rb_define_class("IOError", rb_eStandardError);
13352 rb_eEOFError = rb_define_class("EOFError", rb_eIOError);
13353
13354 id_write = rb_intern_const("write");
13355 id_read = rb_intern_const("read");
13356 id_getc = rb_intern_const("getc");
13357 id_flush = rb_intern_const("flush");
13358 id_readpartial = rb_intern_const("readpartial");
13359 id_set_encoding = rb_intern_const("set_encoding");
13360
13361 rb_define_global_function("syscall", rb_f_syscall, -1);
13362
13363 rb_define_global_function("open", rb_f_open, -1);
13364 rb_define_global_function("printf", rb_f_printf, -1);
13365 rb_define_global_function("print", rb_f_print, -1);
13366 rb_define_global_function("putc", rb_f_putc, 1);
13367 rb_define_global_function("puts", rb_f_puts, -1);
13368 rb_define_global_function("gets", rb_f_gets, -1);
13369 rb_define_global_function("readline", rb_f_readline, -1);
13370 rb_define_global_function("select", rb_f_select, -1);
13371
13372 rb_define_global_function("readlines", rb_f_readlines, -1);
13373
13374 rb_define_global_function("`", rb_f_backquote, 1);
13375
13376 rb_define_global_function("p", rb_f_p, -1);
13377 rb_define_method(rb_mKernel, "display", rb_obj_display, -1);
13378
13379 rb_cIO = rb_define_class("IO", rb_cObject);
13380 rb_include_module(rb_cIO, rb_mEnumerable);
13381
13382 rb_define_const(rb_cIO, "READABLE", INT2NUM(RUBY_IO_READABLE));
13383 rb_define_const(rb_cIO, "WRITABLE", INT2NUM(RUBY_IO_WRITABLE));
13384 rb_define_const(rb_cIO, "PRIORITY", INT2NUM(RUBY_IO_PRIORITY));
13385
13386 /* exception to wait for reading. see IO.select. */
13387 rb_mWaitReadable = rb_define_module_under(rb_cIO, "WaitReadable");
13388 /* exception to wait for writing. see IO.select. */
13389 rb_mWaitWritable = rb_define_module_under(rb_cIO, "WaitWritable");
13390 /* exception to wait for reading by EAGAIN. see IO.select. */
13391 rb_eEAGAINWaitReadable = rb_define_class_under(rb_cIO, "EAGAINWaitReadable", rb_eEAGAIN);
13392 rb_include_module(rb_eEAGAINWaitReadable, rb_mWaitReadable);
13393 /* exception to wait for writing by EAGAIN. see IO.select. */
13394 rb_eEAGAINWaitWritable = rb_define_class_under(rb_cIO, "EAGAINWaitWritable", rb_eEAGAIN);
13395 rb_include_module(rb_eEAGAINWaitWritable, rb_mWaitWritable);
13396#if EAGAIN == EWOULDBLOCK
13397 rb_eEWOULDBLOCKWaitReadable = rb_eEAGAINWaitReadable;
13398 /* same as IO::EAGAINWaitReadable */
13399 rb_define_const(rb_cIO, "EWOULDBLOCKWaitReadable", rb_eEAGAINWaitReadable);
13400 rb_eEWOULDBLOCKWaitWritable = rb_eEAGAINWaitWritable;
13401 /* same as IO::EAGAINWaitWritable */
13402 rb_define_const(rb_cIO, "EWOULDBLOCKWaitWritable", rb_eEAGAINWaitWritable);
13403#else
13404 /* exception to wait for reading by EWOULDBLOCK. see IO.select. */
13405 rb_eEWOULDBLOCKWaitReadable = rb_define_class_under(rb_cIO, "EWOULDBLOCKWaitReadable", rb_eEWOULDBLOCK);
13406 rb_include_module(rb_eEWOULDBLOCKWaitReadable, rb_mWaitReadable);
13407 /* exception to wait for writing by EWOULDBLOCK. see IO.select. */
13408 rb_eEWOULDBLOCKWaitWritable = rb_define_class_under(rb_cIO, "EWOULDBLOCKWaitWritable", rb_eEWOULDBLOCK);
13409 rb_include_module(rb_eEWOULDBLOCKWaitWritable, rb_mWaitWritable);
13410#endif
13411 /* exception to wait for reading by EINPROGRESS. see IO.select. */
13412 rb_eEINPROGRESSWaitReadable = rb_define_class_under(rb_cIO, "EINPROGRESSWaitReadable", rb_eEINPROGRESS);
13413 rb_include_module(rb_eEINPROGRESSWaitReadable, rb_mWaitReadable);
13414 /* exception to wait for writing by EINPROGRESS. see IO.select. */
13415 rb_eEINPROGRESSWaitWritable = rb_define_class_under(rb_cIO, "EINPROGRESSWaitWritable", rb_eEINPROGRESS);
13416 rb_include_module(rb_eEINPROGRESSWaitWritable, rb_mWaitWritable);
13417
13418#if 0
13419 /* This is necessary only for forcing rdoc handle File::open */
13420 rb_define_singleton_method(rb_cFile, "open", rb_io_s_open, -1);
13421#endif
13422
13423 rb_define_alloc_func(rb_cIO, io_alloc);
13424 rb_define_singleton_method(rb_cIO, "new", rb_io_s_new, -1);
13425 rb_define_singleton_method(rb_cIO, "open", rb_io_s_open, -1);
13426 rb_define_singleton_method(rb_cIO, "sysopen", rb_io_s_sysopen, -1);
13427 rb_define_singleton_method(rb_cIO, "for_fd", rb_io_s_for_fd, -1);
13428 rb_define_singleton_method(rb_cIO, "popen", rb_io_s_popen, -1);
13429 rb_define_singleton_method(rb_cIO, "foreach", rb_io_s_foreach, -1);
13430 rb_define_singleton_method(rb_cIO, "readlines", rb_io_s_readlines, -1);
13431 rb_define_singleton_method(rb_cIO, "read", rb_io_s_read, -1);
13432 rb_define_singleton_method(rb_cIO, "binread", rb_io_s_binread, -1);
13433 rb_define_singleton_method(rb_cIO, "write", rb_io_s_write, -1);
13434 rb_define_singleton_method(rb_cIO, "binwrite", rb_io_s_binwrite, -1);
13435 rb_define_singleton_method(rb_cIO, "select", rb_f_select, -1);
13436 rb_define_singleton_method(rb_cIO, "pipe", rb_io_s_pipe, -1);
13437 rb_define_singleton_method(rb_cIO, "try_convert", rb_io_s_try_convert, 1);
13438 rb_define_singleton_method(rb_cIO, "copy_stream", rb_io_s_copy_stream, -1);
13439
13440 rb_define_method(rb_cIO, "initialize", rb_io_initialize, -1);
13441
13442 rb_output_fs = Qnil;
13443 rb_define_hooked_variable("$,", &rb_output_fs, 0, deprecated_str_setter);
13444
13445 rb_default_rs = rb_fstring_lit("\n"); /* avoid modifying RS_default */
13446 rb_gc_register_mark_object(rb_default_rs);
13447 rb_rs = rb_default_rs;
13448 rb_output_rs = Qnil;
13449 rb_define_hooked_variable("$/", &rb_rs, 0, deprecated_str_setter);
13450 rb_define_hooked_variable("$-0", &rb_rs, 0, deprecated_str_setter);
13451 rb_define_hooked_variable("$\\", &rb_output_rs, 0, deprecated_str_setter);
13452
13453 rb_define_virtual_variable("$_", get_LAST_READ_LINE, set_LAST_READ_LINE);
13454 rb_gvar_ractor_local("$_");
13455
13456 rb_define_method(rb_cIO, "initialize_copy", rb_io_init_copy, 1);
13457 rb_define_method(rb_cIO, "reopen", rb_io_reopen, -1);
13458
13459 rb_define_method(rb_cIO, "print", rb_io_print, -1);
13460 rb_define_method(rb_cIO, "putc", rb_io_putc, 1);
13461 rb_define_method(rb_cIO, "puts", rb_io_puts, -1);
13462 rb_define_method(rb_cIO, "printf", rb_io_printf, -1);
13463
13464 rb_define_method(rb_cIO, "each", rb_io_each_line, -1);
13465 rb_define_method(rb_cIO, "each_line", rb_io_each_line, -1);
13466 rb_define_method(rb_cIO, "each_byte", rb_io_each_byte, 0);
13467 rb_define_method(rb_cIO, "each_char", rb_io_each_char, 0);
13468 rb_define_method(rb_cIO, "each_codepoint", rb_io_each_codepoint, 0);
13469
13470 rb_define_method(rb_cIO, "syswrite", rb_io_syswrite, 1);
13471 rb_define_method(rb_cIO, "sysread", rb_io_sysread, -1);
13472
13473 rb_define_method(rb_cIO, "pread", rb_io_pread, -1);
13474 rb_define_method(rb_cIO, "pwrite", rb_io_pwrite, 2);
13475
13476 rb_define_method(rb_cIO, "fileno", rb_io_fileno, 0);
13477 rb_define_alias(rb_cIO, "to_i", "fileno");
13478 rb_define_method(rb_cIO, "to_io", rb_io_to_io, 0);
13479
13480 rb_define_method(rb_cIO, "fsync", rb_io_fsync, 0);
13481 rb_define_method(rb_cIO, "fdatasync", rb_io_fdatasync, 0);
13482 rb_define_method(rb_cIO, "sync", rb_io_sync, 0);
13483 rb_define_method(rb_cIO, "sync=", rb_io_set_sync, 1);
13484
13485 rb_define_method(rb_cIO, "lineno", rb_io_lineno, 0);
13486 rb_define_method(rb_cIO, "lineno=", rb_io_set_lineno, 1);
13487
13488 rb_define_method(rb_cIO, "readlines", rb_io_readlines, -1);
13489
13490 rb_define_method(rb_cIO, "readpartial", io_readpartial, -1);
13491 rb_define_method(rb_cIO, "read", io_read, -1);
13492 rb_define_method(rb_cIO, "write", io_write_m, -1);
13493 rb_define_method(rb_cIO, "gets", rb_io_gets_m, -1);
13494 rb_define_method(rb_cIO, "readline", rb_io_readline, -1);
13495 rb_define_method(rb_cIO, "getc", rb_io_getc, 0);
13496 rb_define_method(rb_cIO, "getbyte", rb_io_getbyte, 0);
13497 rb_define_method(rb_cIO, "readchar", rb_io_readchar, 0);
13498 rb_define_method(rb_cIO, "readbyte", rb_io_readbyte, 0);
13499 rb_define_method(rb_cIO, "ungetbyte",rb_io_ungetbyte, 1);
13500 rb_define_method(rb_cIO, "ungetc",rb_io_ungetc, 1);
13501 rb_define_method(rb_cIO, "<<", rb_io_addstr, 1);
13502 rb_define_method(rb_cIO, "flush", rb_io_flush, 0);
13503 rb_define_method(rb_cIO, "tell", rb_io_tell, 0);
13504 rb_define_method(rb_cIO, "seek", rb_io_seek_m, -1);
13505 /* Set I/O position from the beginning */
13506 rb_define_const(rb_cIO, "SEEK_SET", INT2FIX(SEEK_SET));
13507 /* Set I/O position from the current position */
13508 rb_define_const(rb_cIO, "SEEK_CUR", INT2FIX(SEEK_CUR));
13509 /* Set I/O position from the end */
13510 rb_define_const(rb_cIO, "SEEK_END", INT2FIX(SEEK_END));
13511#ifdef SEEK_DATA
13512 /* Set I/O position to the next location containing data */
13513 rb_define_const(rb_cIO, "SEEK_DATA", INT2FIX(SEEK_DATA));
13514#endif
13515#ifdef SEEK_HOLE
13516 /* Set I/O position to the next hole */
13517 rb_define_const(rb_cIO, "SEEK_HOLE", INT2FIX(SEEK_HOLE));
13518#endif
13519 rb_define_method(rb_cIO, "rewind", rb_io_rewind, 0);
13520 rb_define_method(rb_cIO, "pos", rb_io_tell, 0);
13521 rb_define_method(rb_cIO, "pos=", rb_io_set_pos, 1);
13522 rb_define_method(rb_cIO, "eof", rb_io_eof, 0);
13523 rb_define_method(rb_cIO, "eof?", rb_io_eof, 0);
13524
13525 rb_define_method(rb_cIO, "close_on_exec?", rb_io_close_on_exec_p, 0);
13526 rb_define_method(rb_cIO, "close_on_exec=", rb_io_set_close_on_exec, 1);
13527
13528 rb_define_method(rb_cIO, "close", rb_io_close_m, 0);
13529 rb_define_method(rb_cIO, "closed?", rb_io_closed, 0);
13530 rb_define_method(rb_cIO, "close_read", rb_io_close_read, 0);
13531 rb_define_method(rb_cIO, "close_write", rb_io_close_write, 0);
13532
13533 rb_define_method(rb_cIO, "isatty", rb_io_isatty, 0);
13534 rb_define_method(rb_cIO, "tty?", rb_io_isatty, 0);
13535 rb_define_method(rb_cIO, "binmode", rb_io_binmode_m, 0);
13536 rb_define_method(rb_cIO, "binmode?", rb_io_binmode_p, 0);
13537 rb_define_method(rb_cIO, "sysseek", rb_io_sysseek, -1);
13538 rb_define_method(rb_cIO, "advise", rb_io_advise, -1);
13539
13540 rb_define_method(rb_cIO, "ioctl", rb_io_ioctl, -1);
13541 rb_define_method(rb_cIO, "fcntl", rb_io_fcntl, -1);
13542 rb_define_method(rb_cIO, "pid", rb_io_pid, 0);
13543 rb_define_method(rb_cIO, "inspect", rb_io_inspect, 0);
13544
13545 rb_define_method(rb_cIO, "external_encoding", rb_io_external_encoding, 0);
13546 rb_define_method(rb_cIO, "internal_encoding", rb_io_internal_encoding, 0);
13547 rb_define_method(rb_cIO, "set_encoding", rb_io_set_encoding, -1);
13548 rb_define_method(rb_cIO, "set_encoding_by_bom", rb_io_set_encoding_by_bom, 0);
13549
13550 rb_define_method(rb_cIO, "autoclose?", rb_io_autoclose_p, 0);
13551 rb_define_method(rb_cIO, "autoclose=", rb_io_set_autoclose, 1);
13552
13553 rb_define_virtual_variable("$stdin", stdin_getter, stdin_setter);
13554 rb_define_virtual_variable("$stdout", stdout_getter, stdout_setter);
13555 rb_define_virtual_variable("$>", stdout_getter, stdout_setter);
13556 rb_define_virtual_variable("$stderr", stderr_getter, stderr_setter);
13557
13558 rb_gvar_ractor_local("$stdin");
13559 rb_gvar_ractor_local("$stdout");
13560 rb_gvar_ractor_local("$>");
13561 rb_gvar_ractor_local("$stderr");
13562
13563 rb_stdin = rb_io_prep_stdin();
13564 rb_stdout = rb_io_prep_stdout();
13565 rb_stderr = rb_io_prep_stderr();
13566
13567 rb_global_variable(&rb_stdin);
13568 rb_global_variable(&rb_stdout);
13569 rb_global_variable(&rb_stderr);
13570
13571 orig_stdout = rb_stdout;
13572 orig_stderr = rb_stderr;
13573
13574 /* Holds the original stdin */
13575 rb_define_global_const("STDIN", rb_stdin);
13576 /* Holds the original stdout */
13577 rb_define_global_const("STDOUT", rb_stdout);
13578 /* Holds the original stderr */
13579 rb_define_global_const("STDERR", rb_stderr);
13580
13581#if 0
13582 /* Hack to get rdoc to regard ARGF as a class: */
13583 rb_cARGF = rb_define_class("ARGF", rb_cObject);
13584#endif
13585
13586 rb_cARGF = rb_class_new(rb_cObject);
13587 rb_set_class_path(rb_cARGF, rb_cObject, "ARGF.class");
13588 rb_define_alloc_func(rb_cARGF, argf_alloc);
13589
13590 rb_include_module(rb_cARGF, rb_mEnumerable);
13591
13592 rb_define_method(rb_cARGF, "initialize", argf_initialize, -2);
13593 rb_define_method(rb_cARGF, "initialize_copy", argf_initialize_copy, 1);
13594 rb_define_method(rb_cARGF, "to_s", argf_to_s, 0);
13595 rb_define_alias(rb_cARGF, "inspect", "to_s");
13596 rb_define_method(rb_cARGF, "argv", argf_argv, 0);
13597
13598 rb_define_method(rb_cARGF, "fileno", argf_fileno, 0);
13599 rb_define_method(rb_cARGF, "to_i", argf_fileno, 0);
13600 rb_define_method(rb_cARGF, "to_io", argf_to_io, 0);
13601 rb_define_method(rb_cARGF, "to_write_io", argf_write_io, 0);
13602 rb_define_method(rb_cARGF, "each", argf_each_line, -1);
13603 rb_define_method(rb_cARGF, "each_line", argf_each_line, -1);
13604 rb_define_method(rb_cARGF, "each_byte", argf_each_byte, 0);
13605 rb_define_method(rb_cARGF, "each_char", argf_each_char, 0);
13606 rb_define_method(rb_cARGF, "each_codepoint", argf_each_codepoint, 0);
13607
13608 rb_define_method(rb_cARGF, "read", argf_read, -1);
13609 rb_define_method(rb_cARGF, "readpartial", argf_readpartial, -1);
13610 rb_define_method(rb_cARGF, "read_nonblock", argf_read_nonblock, -1);
13611 rb_define_method(rb_cARGF, "readlines", argf_readlines, -1);
13612 rb_define_method(rb_cARGF, "to_a", argf_readlines, -1);
13613 rb_define_method(rb_cARGF, "gets", argf_gets, -1);
13614 rb_define_method(rb_cARGF, "readline", argf_readline, -1);
13615 rb_define_method(rb_cARGF, "getc", argf_getc, 0);
13616 rb_define_method(rb_cARGF, "getbyte", argf_getbyte, 0);
13617 rb_define_method(rb_cARGF, "readchar", argf_readchar, 0);
13618 rb_define_method(rb_cARGF, "readbyte", argf_readbyte, 0);
13619 rb_define_method(rb_cARGF, "tell", argf_tell, 0);
13620 rb_define_method(rb_cARGF, "seek", argf_seek_m, -1);
13621 rb_define_method(rb_cARGF, "rewind", argf_rewind, 0);
13622 rb_define_method(rb_cARGF, "pos", argf_tell, 0);
13623 rb_define_method(rb_cARGF, "pos=", argf_set_pos, 1);
13624 rb_define_method(rb_cARGF, "eof", argf_eof, 0);
13625 rb_define_method(rb_cARGF, "eof?", argf_eof, 0);
13626 rb_define_method(rb_cARGF, "binmode", argf_binmode_m, 0);
13627 rb_define_method(rb_cARGF, "binmode?", argf_binmode_p, 0);
13628
13629 rb_define_method(rb_cARGF, "write", argf_write, 1);
13630 rb_define_method(rb_cARGF, "print", rb_io_print, -1);
13631 rb_define_method(rb_cARGF, "putc", rb_io_putc, 1);
13632 rb_define_method(rb_cARGF, "puts", rb_io_puts, -1);
13633 rb_define_method(rb_cARGF, "printf", rb_io_printf, -1);
13634
13635 rb_define_method(rb_cARGF, "filename", argf_filename, 0);
13636 rb_define_method(rb_cARGF, "path", argf_filename, 0);
13637 rb_define_method(rb_cARGF, "file", argf_file, 0);
13638 rb_define_method(rb_cARGF, "skip", argf_skip, 0);
13639 rb_define_method(rb_cARGF, "close", argf_close_m, 0);
13640 rb_define_method(rb_cARGF, "closed?", argf_closed, 0);
13641
13642 rb_define_method(rb_cARGF, "lineno", argf_lineno, 0);
13643 rb_define_method(rb_cARGF, "lineno=", argf_set_lineno, 1);
13644
13645 rb_define_method(rb_cARGF, "inplace_mode", argf_inplace_mode_get, 0);
13646 rb_define_method(rb_cARGF, "inplace_mode=", argf_inplace_mode_set, 1);
13647
13648 rb_define_method(rb_cARGF, "external_encoding", argf_external_encoding, 0);
13649 rb_define_method(rb_cARGF, "internal_encoding", argf_internal_encoding, 0);
13650 rb_define_method(rb_cARGF, "set_encoding", argf_set_encoding, -1);
13651
13652 argf = rb_class_new_instance(0, 0, rb_cARGF);
13653
13654 rb_define_readonly_variable("$<", &argf);
13655 /*
13656 * ARGF is a stream designed for use in scripts that process files given
13657 * as command-line arguments or passed in via STDIN.
13658 *
13659 * See ARGF (the class) for more details.
13660 */
13661 rb_define_global_const("ARGF", argf);
13662
13663 rb_define_hooked_variable("$.", &argf, argf_lineno_getter, argf_lineno_setter);
13664 rb_define_hooked_variable("$FILENAME", &argf, argf_filename_getter, rb_gvar_readonly_setter);
13665 ARGF.filename = rb_str_new2("-");
13666
13667 rb_define_hooked_variable("$-i", &argf, opt_i_get, opt_i_set);
13668 rb_gvar_ractor_local("$-i");
13669
13670 rb_define_hooked_variable("$*", &argf, argf_argv_getter, rb_gvar_readonly_setter);
13671
13672#if defined (_WIN32) || defined(__CYGWIN__)
13673 atexit(pipe_atexit);
13674#endif
13675
13676 Init_File();
13677
13678 rb_define_method(rb_cFile, "initialize", rb_file_initialize, -1);
13679
13680 sym_mode = ID2SYM(rb_intern_const("mode"));
13681 sym_perm = ID2SYM(rb_intern_const("perm"));
13682 sym_flags = ID2SYM(rb_intern_const("flags"));
13683 sym_extenc = ID2SYM(rb_intern_const("external_encoding"));
13684 sym_intenc = ID2SYM(rb_intern_const("internal_encoding"));
13685 sym_encoding = ID2SYM(rb_id_encoding());
13686 sym_open_args = ID2SYM(rb_intern_const("open_args"));
13687 sym_textmode = ID2SYM(rb_intern_const("textmode"));
13688 sym_binmode = ID2SYM(rb_intern_const("binmode"));
13689 sym_autoclose = ID2SYM(rb_intern_const("autoclose"));
13690 sym_normal = ID2SYM(rb_intern_const("normal"));
13691 sym_sequential = ID2SYM(rb_intern_const("sequential"));
13692 sym_random = ID2SYM(rb_intern_const("random"));
13693 sym_willneed = ID2SYM(rb_intern_const("willneed"));
13694 sym_dontneed = ID2SYM(rb_intern_const("dontneed"));
13695 sym_noreuse = ID2SYM(rb_intern_const("noreuse"));
13696 sym_SET = ID2SYM(rb_intern_const("SET"));
13697 sym_CUR = ID2SYM(rb_intern_const("CUR"));
13698 sym_END = ID2SYM(rb_intern_const("END"));
13699#ifdef SEEK_DATA
13700 sym_DATA = ID2SYM(rb_intern_const("DATA"));
13701#endif
13702#ifdef SEEK_HOLE
13703 sym_HOLE = ID2SYM(rb_intern_const("HOLE"));
13704#endif
13705 sym_wait_readable = ID2SYM(rb_intern_const("wait_readable"));
13706 sym_wait_writable = ID2SYM(rb_intern_const("wait_writable"));
13707}
13708
13709#include "io.rbinc"
rb_ary_shift
VALUE rb_ary_shift(VALUE ary)
Definition: array.c:1413
rb_to_array_type
VALUE rb_to_array_type(VALUE ary)
Definition: array.c:981
rb_ary_push
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:1301
rb_ary_new
VALUE rb_ary_new(void)
Definition: array.c:749
rb_ary_concat
VALUE rb_ary_concat(VALUE x, VALUE y)
Definition: array.c:4859
rb_check_array_type
VALUE rb_check_array_type(VALUE ary)
Definition: array.c:988
rb_ary_entry
VALUE rb_ary_entry(VALUE ary, long offset)
Definition: array.c:1672
rb_assoc_new
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Definition: array.c:975
L
#define L(x)
Definition: asm.h:125
NORETURN
#define NORETURN(x)
Definition: attributes.h:152
UNREACHABLE
#define UNREACHABLE
Definition: assume.h:30
UNREACHABLE_RETURN
#define UNREACHABLE_RETURN
Definition: assume.h:31
rb_category_warn
#define rb_category_warn(category,...)
Definition: bigdecimal.h:163
NUM2CHR
#define NUM2CHR
Definition: char.h:33
ctype.h
Our own, locale independent, character handling routines.
STRNCASECMP
#define STRNCASECMP
Definition: ctype.h:53
ruby_strtoul
unsigned long ruby_strtoul(const char *str, char **endptr, int base)
Definition: util.c:134
ISASCII
#define ISASCII
Definition: ctype.h:35
rb_define_method
#define rb_define_method(klass, mid, func, arity)
Defines klass#mid.
Definition: cxxanyargs.hpp:653
rb_define_singleton_method
#define rb_define_singleton_method(klass, mid, func, arity)
Defines klass.mid.
Definition: cxxanyargs.hpp:668
rb_define_global_function
#define rb_define_global_function(mid, func, arity)
Defines rb_mKernel #mid.
Definition: cxxanyargs.hpp:678
recur
#define recur(fmt)
Definition: date_strptime.c:152
ptr
struct RIMemo * ptr
Definition: debug.c:88
strchr
char * strchr(char *, char)
O_CLOEXEC
#define O_CLOEXEC
Definition: dir.c:26
dln.h
encindex.h
ENCINDEX_UTF_32BE
#define ENCINDEX_UTF_32BE
Definition: encindex.h:48
ENCINDEX_UTF_32LE
#define ENCINDEX_UTF_32LE
Definition: encindex.h:49
ENCINDEX_UTF_16BE
#define ENCINDEX_UTF_16BE
Definition: encindex.h:46
ENCINDEX_UTF_16LE
#define ENCINDEX_UTF_16LE
Definition: encindex.h:47
rb_utf8_encindex
#define rb_utf8_encindex()
Definition: encindex.h:58
rb_find_encoding
rb_encoding * rb_find_encoding(VALUE enc)
Definition: encoding.c:336
rb_enc_precise_mbclen
int rb_enc_precise_mbclen(const char *p, const char *e, rb_encoding *enc)
Definition: encoding.c:1230
rb_to_encoding_index
int rb_to_encoding_index(VALUE enc)
Definition: encoding.c:267
rb_enc_associate
VALUE rb_enc_associate(VALUE obj, rb_encoding *enc)
Definition: encoding.c:1064
rb_ascii8bit_encoding
rb_encoding * rb_ascii8bit_encoding(void)
Definition: encoding.c:1525
rb_enc_from_index
rb_encoding * rb_enc_from_index(int index)
Definition: encoding.c:414
rb_default_internal_encoding
rb_encoding * rb_default_internal_encoding(void)
Definition: encoding.c:1734
rb_enc_get
rb_encoding * rb_enc_get(VALUE obj)
Definition: encoding.c:1070
rb_default_external_encoding
rb_encoding * rb_default_external_encoding(void)
Definition: encoding.c:1647
rb_id_encoding
ID rb_id_encoding(void)
Definition: encoding.c:947
rb_enc_mbclen
int rb_enc_mbclen(const char *p, const char *e, rb_encoding *enc)
Definition: encoding.c:1218
rb_to_encoding
rb_encoding * rb_to_encoding(VALUE enc)
Definition: encoding.c:329
rb_usascii_encoding
rb_encoding * rb_usascii_encoding(void)
Definition: encoding.c:1549
rb_enc_from_encoding
VALUE rb_enc_from_encoding(rb_encoding *encoding)
Definition: encoding.c:188
rb_enc_find_index
int rb_enc_find_index(const char *name)
Definition: encoding.c:879
rb_enc_ascget
int rb_enc_ascget(const char *p, const char *e, int *len, rb_encoding *enc)
Definition: encoding.c:1242
num
big_t * num
Definition: enough.c:232
out
string_t out
Definition: enough.c:230
max
int max
Definition: enough.c:225
rb_mEnumerable
VALUE rb_mEnumerable
Definition: enum.c:27
sym
#define sym(name)
Definition: enumerator.c:4007
len
uint8_t len
Definition: escape.c:17
str
char str[HTML_ESCAPE_MAX_LEN+1]
Definition: escape.c:18
numberof
#define numberof(array)
Definition: etc.c:649
strrchr
char * strrchr(const char *, const char)
RSTRING_LEN
#define RSTRING_LEN(string)
Definition: fbuffer.h:22
RSTRING_PTR
#define RSTRING_PTR(string)
Definition: fbuffer.h:19
memcpy
#define memcpy(d, s, n)
Definition: ffi_common.h:55
O_BINARY
#define O_BINARY
rb_str_encode_ospath
VALUE rb_str_encode_ospath(VALUE path)
Definition: file.c:251
flock
int flock(int, int)
Definition: flock.c:125
rb_cFile
VALUE rb_cFile
Definition: file.c:174
Init_File
void Init_File(void)
Definition: file.c:6503
FL_SINGLETON
#define FL_SINGLETON
Definition: fl_type.h:49
PRIsVALUE
#define PRIsVALUE
Definition: function.c:10
rb_gc
void rb_gc(void)
Definition: gc.c:9497
rb_gc_force_recycle
void rb_gc_force_recycle(VALUE obj)
Definition: gc.c:7968
rb_gc_mark
void rb_gc_mark(VALUE ptr)
Definition: gc.c:6112
rb_gc_register_mark_object
void rb_gc_register_mark_object(VALUE obj)
Inform the garbage collector that object is a live Ruby object that should not be moved.
Definition: gc.c:8022
CLASS_OF
#define CLASS_OF
Definition: globals.h:153
rb_include_module
void rb_include_module(VALUE klass, VALUE module)
Definition: class.c:962
rb_define_class
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:748
rb_class_new
VALUE rb_class_new(VALUE super)
Creates a new class.
Definition: class.c:253
rb_define_class_under
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:797
rb_define_module_under
VALUE rb_define_module_under(VALUE outer, const char *name)
Definition: class.c:895
rb_frame_this_func
ID rb_frame_this_func(void)
The original name of the current method.
Definition: eval.c:1216
rb_scan_args_kw
int rb_scan_args_kw(int kw_flag, int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:2309
rb_define_alias
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
Definition: class.c:1999
rb_scan_args
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:2296
rb_block_given_p
int rb_block_given_p(void)
Determines if the current method is given a block.
Definition: eval.c:935
rb_get_kwargs
int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *values)
Definition: class.c:2085
OBJ_FREEZE
#define OBJ_FREEZE
Definition: fl_type.h:134
FL_TEST
#define FL_TEST
Definition: fl_type.h:130
rb_notimplement
void rb_notimplement(void)
Definition: error.c:2960
rb_syserr_fail
void rb_syserr_fail(int e, const char *mesg)
Definition: error.c:3029
rb_raise
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2917
rb_enc_warn
void rb_enc_warn(rb_encoding *enc, const char *fmt,...)
Definition: error.c:428
rb_rescue2
VALUE rb_rescue2(VALUE(*b_proc)(VALUE), VALUE data1, VALUE(*r_proc)(VALUE, VALUE), VALUE data2,...)
An equivalent of rescue clause.
Definition: eval.c:991
rb_eNotImpError
VALUE rb_eNotImpError
Definition: error.c:1067
rb_exc_raise
void rb_exc_raise(VALUE mesg)
Raises an exception in the current thread.
Definition: eval.c:712
rb_bug
void rb_bug(const char *fmt,...)
Definition: error.c:768
rb_eStandardError
VALUE rb_eStandardError
Definition: error.c:1054
rb_syserr_fail_str
void rb_syserr_fail_str(int e, VALUE mesg)
Definition: error.c:3035
rb_sys_fail_str
void rb_sys_fail_str(VALUE mesg)
Definition: error.c:3047
rb_eTypeError
VALUE rb_eTypeError
Definition: error.c:1057
rb_fatal
void rb_fatal(const char *fmt,...)
Definition: error.c:2968
rb_protect
VALUE rb_protect(VALUE(*proc)(VALUE), VALUE data, int *pstate)
Protects a function call from potential global escapes from the function.
Definition: eval.c:1105
rb_category_warning
void rb_category_warning(rb_warning_category_t category, const char *fmt,...)
Definition: error.c:450
rb_warn_deprecated
void rb_warn_deprecated(const char *fmt, const char *suggest,...)
Definition: error.c:480
rb_eRuntimeError
VALUE rb_eRuntimeError
Definition: error.c:1055
rb_warn
void rb_warn(const char *fmt,...)
Definition: error.c:408
rb_eArgError
VALUE rb_eArgError
Definition: error.c:1058
rb_eEAGAIN
VALUE rb_eEAGAIN
Definition: error.c:69
rb_ensure
VALUE rb_ensure(VALUE(*b_proc)(VALUE), VALUE data1, VALUE(*e_proc)(VALUE), VALUE data2)
An equivalent to ensure clause.
Definition: eval.c:1148
rb_eEINPROGRESS
VALUE rb_eEINPROGRESS
Definition: error.c:71
rb_jump_tag
void rb_jump_tag(int tag)
Continues the exception caught by rb_protect() and rb_eval_string_protect().
Definition: eval.c:921
rb_str_end_with_asciichar
int rb_str_end_with_asciichar(VALUE str, int c)
Definition: io.c:7833
rb_sys_fail
void rb_sys_fail(const char *mesg)
Definition: error.c:3041
rb_mod_syserr_fail_str
void rb_mod_syserr_fail_str(VALUE mod, int e, VALUE mesg)
Definition: error.c:3111
rb_eEWOULDBLOCK
VALUE rb_eEWOULDBLOCK
Definition: error.c:70
rb_eSystemCallError
VALUE rb_eSystemCallError
Definition: error.c:1076
rb_mKernel
VALUE rb_mKernel
Kernel module.
Definition: object.c:48
rb_check_to_int
VALUE rb_check_to_int(VALUE)
Tries to convert val into Integer.
Definition: object.c:3066
rb_cObject
VALUE rb_cObject
Object class.
Definition: object.c:49
rb_any_to_s
VALUE rb_any_to_s(VALUE)
Default implementation of #to_s.
Definition: object.c:561
rb_obj_alloc
VALUE rb_obj_alloc(VALUE)
Allocates an instance of klass.
Definition: object.c:1900
rb_class_new_instance
VALUE rb_class_new_instance(int, const VALUE *, VALUE)
Allocates and initializes an instance of klass.
Definition: object.c:1953
rb_class_new_instance_kw
VALUE rb_class_new_instance_kw(int, const VALUE *, VALUE, int)
Definition: object.c:1929
rb_bool_expected
int rb_bool_expected(VALUE, const char *)
Definition: object.c:3144
rb_obj_class
VALUE rb_obj_class(VALUE)
Definition: object.c:245
rb_obj_dup
VALUE rb_obj_dup(VALUE)
Equivalent to Object#dup in Ruby.
Definition: object.c:467
rb_inspect
VALUE rb_inspect(VALUE)
Convenient wrapper of Object::inspect.
Definition: object.c:585
rb_check_convert_type_with_id
VALUE rb_check_convert_type_with_id(VALUE, int, const char *, ID)
Definition: object.c:2987
rb_convert_type_with_id
VALUE rb_convert_type_with_id(VALUE v, int t, const char *nam, ID mid)
Definition: object.c:2944
rb_obj_freeze
VALUE rb_obj_freeze(VALUE)
Make the object unmodifiable.
Definition: object.c:1101
rb_check_to_integer
VALUE rb_check_to_integer(VALUE, const char *)
Tries to convert val into Integer.
Definition: object.c:3029
rb_to_int
VALUE rb_to_int(VALUE)
Converts val into Integer.
Definition: object.c:3051
suffix
unsigned char suffix[65536]
Definition: gun.c:164
rb_check_hash_type
VALUE rb_check_hash_type(VALUE hash)
Definition: hash.c:1860
rb_hash_lookup2
VALUE rb_hash_lookup2(VALUE hash, VALUE key, VALUE def)
Definition: hash.c:2059
rb_hash_aref
VALUE rb_hash_aref(VALUE hash, VALUE key)
Definition: hash.c:2046
rb_hash_aset
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
Definition: hash.c:2901
rb_hash_lookup
VALUE rb_hash_lookup(VALUE hash, VALUE key)
Definition: hash.c:2072
rb_hash_dup
VALUE rb_hash_dup(VALUE hash)
Definition: hash.c:1579
rb_hash_new
VALUE rb_hash_new(void)
Definition: hash.c:1538
term
const char term
Definition: id.c:37
id.h
ECONV_AFTER_OUTPUT
#define ECONV_AFTER_OUTPUT
Definition: encoding.h:407
rb_econv_prepare_options
int rb_econv_prepare_options(VALUE opthash, VALUE *ecopts, int ecflags)
Definition: transcode.c:2526
ENC_CODERANGE_7BIT
#define ENC_CODERANGE_7BIT
Definition: encoding.h:93
ENC_CODERANGE_VALID
#define ENC_CODERANGE_VALID
Definition: encoding.h:94
rb_econv_open_exc
VALUE rb_econv_open_exc(const char *senc, const char *denc, int ecflags)
Definition: transcode.c:2028
ECONV_UNIVERSAL_NEWLINE_DECORATOR
#define ECONV_UNIVERSAL_NEWLINE_DECORATOR
Definition: encoding.h:393
rb_enc_left_char_head
#define rb_enc_left_char_head(s, p, e, enc)
Definition: encoding.h:213
rb_econv_convert
rb_econv_result_t rb_econv_convert(rb_econv_t *ec, const unsigned char **source_buffer_ptr, const unsigned char *source_buffer_end, unsigned char **destination_buffer_ptr, unsigned char *destination_buffer_end, int flags)
Definition: transcode.c:1438
rb_econv_result_t
rb_econv_result_t
Definition: encoding.h:288
econv_incomplete_input
@ econv_incomplete_input
Definition: encoding.h:295
econv_finished
@ econv_finished
Definition: encoding.h:293
econv_undefined_conversion
@ econv_undefined_conversion
Definition: encoding.h:290
econv_source_buffer_empty
@ econv_source_buffer_empty
Definition: encoding.h:292
econv_destination_buffer_full
@ econv_destination_buffer_full
Definition: encoding.h:291
econv_invalid_byte_sequence
@ econv_invalid_byte_sequence
Definition: encoding.h:289
rb_econv_putbackable
int rb_econv_putbackable(rb_econv_t *ec)
Definition: transcode.c:1734
rb_enc_str_coderange
int rb_enc_str_coderange(VALUE)
Definition: string.c:725
rb_enc_uint_chr
VALUE rb_enc_uint_chr(unsigned int code, rb_encoding *enc)
Definition: numeric.c:3391
rb_enc_str_new
VALUE rb_enc_str_new(const char *, long, rb_encoding *)
Definition: string.c:857
ENCODING_MAXNAMELEN
#define ENCODING_MAXNAMELEN
Definition: encoding.h:53
rb_enc_name
#define rb_enc_name(enc)
Definition: encoding.h:168
MBCLEN_NEEDMORE_LEN
#define MBCLEN_NEEDMORE_LEN(ret)
Definition: encoding.h:186
ENCODING_GET
#define ENCODING_GET(obj)
Definition: encoding.h:51
rb_econv_asciicompat_encoding
const char * rb_econv_asciicompat_encoding(const char *encname)
Definition: transcode.c:1778
rb_econv_str_convert
VALUE rb_econv_str_convert(rb_econv_t *ec, VALUE src, int flags)
Definition: transcode.c:1869
rb_econv_open_opts
rb_econv_t * rb_econv_open_opts(const char *source_encoding, const char *destination_encoding, int ecflags, VALUE ecopts)
Definition: transcode.c:2577
MBCLEN_CHARFOUND_LEN
#define MBCLEN_CHARFOUND_LEN(ret)
Definition: encoding.h:183
rb_enc_asciicompat
#define rb_enc_asciicompat(enc)
Definition: encoding.h:236
rb_econv_binmode
void rb_econv_binmode(rb_econv_t *ec)
Definition: transcode.c:1934
rb_enc_codepoint
#define rb_enc_codepoint(p, e, enc)
Definition: encoding.h:198
rb_str_encode
VALUE rb_str_encode(VALUE str, VALUE to, int ecflags, VALUE ecopts)
Definition: transcode.c:2892
rb_econv_make_exception
VALUE rb_econv_make_exception(rb_econv_t *ec)
Definition: transcode.c:4240
MBCLEN_INVALID_P
#define MBCLEN_INVALID_P(ret)
Definition: encoding.h:184
rb_econv_check_error
void rb_econv_check_error(rb_econv_t *ec)
Definition: transcode.c:4246
ECONV_STATEFUL_DECORATOR_MASK
#define ECONV_STATEFUL_DECORATOR_MASK
Definition: encoding.h:398
MBCLEN_NEEDMORE_P
#define MBCLEN_NEEDMORE_P(ret)
Definition: encoding.h:185
rb_enc_mbminlen
#define rb_enc_mbminlen(enc)
Definition: encoding.h:171
ECONV_PARTIAL_INPUT
#define ECONV_PARTIAL_INPUT
Definition: encoding.h:406
ECONV_ERROR_HANDLER_MASK
#define ECONV_ERROR_HANDLER_MASK
Definition: encoding.h:383
ENC_CODERANGE_BROKEN
#define ENC_CODERANGE_BROKEN
Definition: encoding.h:95
rb_str_coderange_scan_restartable
long rb_str_coderange_scan_restartable(const char *, const char *, rb_encoding *, int *)
Definition: string.c:617
MBCLEN_CHARFOUND_P
#define MBCLEN_CHARFOUND_P(ret)
Definition: encoding.h:182
rb_econv_close
void rb_econv_close(rb_econv_t *ec)
Definition: transcode.c:1694
ECONV_NEWLINE_DECORATOR_MASK
#define ECONV_NEWLINE_DECORATOR_MASK
Definition: encoding.h:390
ENC_CODERANGE_SET
#define ENC_CODERANGE_SET(obj, cr)
Definition: encoding.h:99
rb_econv_putback
void rb_econv_putback(rb_econv_t *ec, unsigned char *p, int n)
Definition: transcode.c:1745
ECONV_DEFAULT_NEWLINE_DECORATOR
#define ECONV_DEFAULT_NEWLINE_DECORATOR
Definition: encoding.h:400
config.h
Thin wrapper to ruby/config.h.
RB_WARN_CATEGORY_DEPRECATED
@ RB_WARN_CATEGORY_DEPRECATED
Definition: error.h:34
ruby_verbose
#define ruby_verbose
Definition: error.h:68
rb_io_wait_readwrite
rb_io_wait_readwrite
Definition: error.h:40
rb_iter_break_value
void rb_iter_break_value(VALUE)
Definition: vm.c:1792
RB_IO_WAIT_WRITABLE
#define RB_IO_WAIT_WRITABLE
Definition: error.h:42
RB_IO_WAIT_READABLE
#define RB_IO_WAIT_READABLE
Definition: error.h:41
rb_funcallv_kw
VALUE rb_funcallv_kw(VALUE, ID, int, const VALUE *, int)
Definition: vm_eval.c:1030
rb_funcall
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
Definition: vm_eval.c:1077
rb_funcall3
#define rb_funcall3
Definition: eval.h:37
builtin.h
Defines RBIMPL_HAS_BUILTIN.
rb_ary_new4
#define rb_ary_new4
Definition: array.h:74
rb_ary_new2
#define rb_ary_new2
Definition: array.h:72
RETURN_ENUMERATOR
#define RETURN_ENUMERATOR(obj, argc, argv)
Definition: enumerator.h:74
rb_check_frozen
#define rb_check_frozen
Definition: error.h:72
rb_exc_new3
#define rb_exc_new3
Definition: error.h:31
rb_error_arity
void rb_error_arity(int, int, int)
Definition: vm_insnhelper.c:442
rb_check_arity
#define rb_check_arity
Definition: error.h:34
rb_close_before_exec
void rb_close_before_exec(int lowfd, int maxhint, VALUE noclose_fds)
rb_reserved_fd_p
int rb_reserved_fd_p(int fd)
OBJ_INIT_COPY
#define OBJ_INIT_COPY(obj, orig)
Definition: object.h:31
rb_lastline_get
VALUE rb_lastline_get(void)
Definition: vm.c:1556
rb_lastline_set
void rb_lastline_set(VALUE)
Definition: vm.c:1562
rb_obj_method_arity
int rb_obj_method_arity(VALUE, ID)
Definition: proc.c:2781
rb_waitpid
rb_pid_t rb_waitpid(rb_pid_t pid, int *status, int flags)
Definition: process.c:1443
rb_last_status_set
void rb_last_status_set(int status, rb_pid_t pid)
Definition: process.c:660
rb_str_unlocktmp
VALUE rb_str_unlocktmp(VALUE)
Definition: string.c:2825
rb_str_new2
#define rb_str_new2
Definition: string.h:276
rb_str_resize
VALUE rb_str_resize(VALUE, long)
Definition: string.c:2859
rb_str_cat2
#define rb_str_cat2
Definition: string.h:285
rb_str_new
#define rb_str_new(str, len)
Definition: string.h:213
rb_str_buf_cat
#define rb_str_buf_cat
Definition: string.h:283
rb_str_cat
VALUE rb_str_cat(VALUE, const char *, long)
Definition: string.c:2962
rb_usascii_str_new
#define rb_usascii_str_new(str, len)
Definition: string.h:224
rb_str_set_len
void rb_str_set_len(VALUE, long)
Definition: string.c:2842
rb_str_substr
VALUE rb_str_substr(VALUE, long, long)
Definition: string.c:2734
rb_str_modify
void rb_str_modify(VALUE)
Definition: string.c:2262
rb_str_buf_new
VALUE rb_str_buf_new(long)
Definition: string.c:1398
rb_check_string_type
VALUE rb_check_string_type(VALUE)
Definition: string.c:2462
rb_str_setter
rb_gvar_setter_t rb_str_setter
Definition: string.h:130
rb_str_append
VALUE rb_str_append(VALUE, VALUE)
Definition: string.c:3118
rb_str_buf_cat_ascii
VALUE rb_str_buf_cat_ascii(VALUE, const char *)
Definition: string.c:3079
rb_str_new_frozen
VALUE rb_str_new_frozen(VALUE)
Definition: string.c:1273
rb_str_modify_expand
void rb_str_modify_expand(VALUE, long)
Definition: string.c:2270
rb_str_locktmp
VALUE rb_str_locktmp(VALUE)
rb_obj_as_string
VALUE rb_obj_as_string(VALUE)
Definition: string.c:1529
rb_str_dup
VALUE rb_str_dup(VALUE)
Definition: string.c:1631
rb_str_capacity
size_t rb_str_capacity(VALUE)
Definition: string.c:773
rb_str_new_cstr
#define rb_str_new_cstr(str)
Definition: string.h:219
rb_str_new4
#define rb_str_new4
Definition: string.h:278
rb_thread_interrupted
int rb_thread_interrupted(VALUE thval)
Definition: thread.c:1594
rb_mutex_new
VALUE rb_mutex_new(void)
Definition: thread_sync.c:177
rb_thread_wait_fd
void rb_thread_wait_fd(int)
Definition: thread.c:4305
RUBY_UBF_IO
#define RUBY_UBF_IO
Definition: thread.h:64
rb_mutex_synchronize
VALUE rb_mutex_synchronize(VALUE mutex, VALUE(*func)(VALUE arg), VALUE arg)
Definition: thread_sync.c:598
rb_thread_check_ints
void rb_thread_check_ints(void)
Definition: thread.c:1577
rb_thread_fd_writable
int rb_thread_fd_writable(int)
Definition: thread.c:4311
rb_thread_atfork
void rb_thread_atfork(void)
Definition: thread.c:4830
rb_thread_current
VALUE rb_thread_current(void)
Definition: thread.c:2911
rb_thread_fd_close
void rb_thread_fd_close(int)
Definition: thread.c:2634
rb_thread_sleep
void rb_thread_sleep(int)
Definition: thread.c:1600
rb_thread_schedule
void rb_thread_schedule(void)
Definition: thread.c:1623
rb_exec_recursive
VALUE rb_exec_recursive(VALUE(*)(VALUE, VALUE, int), VALUE, VALUE)
Definition: thread.c:5360
rb_time_interval
struct timeval rb_time_interval(VALUE num)
Definition: time.c:2684
rb_class_name
VALUE rb_class_name(VALUE)
Definition: variable.c:293
rb_set_class_path
void rb_set_class_path(VALUE, VALUE, const char *)
Definition: variable.c:234
rb_attr_get
VALUE rb_attr_get(VALUE, ID)
Definition: variable.c:1242
rb_ivar_set
VALUE rb_ivar_set(VALUE, ID, VALUE)
Definition: variable.c:1493
rb_check_funcall
VALUE rb_check_funcall(VALUE, ID, int, const VALUE *)
Definition: vm_eval.c:619
rb_respond_to
int rb_respond_to(VALUE, ID)
Definition: vm_method.c:2561
rb_define_alloc_func
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
ID2SYM
#define ID2SYM
Definition: symbol.h:44
rb_id2name
const char * rb_id2name(ID)
Definition: symbol.c:944
rb_intern
ID rb_intern(const char *)
Definition: symbol.c:785
CONST_ID
#define CONST_ID
Definition: symbol.h:47
rb_define_global_const
void rb_define_global_const(const char *, VALUE)
Definition: variable.c:3162
rb_gvar_readonly_setter
rb_gvar_setter_t rb_gvar_readonly_setter
Definition: variable.h:46
rb_define_const
void rb_define_const(VALUE, const char *, VALUE)
Definition: variable.c:3150
rb_define_readonly_variable
void rb_define_readonly_variable(const char *, const VALUE *)
Definition: variable.c:587
io.h
FMODE_READABLE
#define FMODE_READABLE
Definition: io.h:105
FMODE_SETENC_BY_BOM
#define FMODE_SETENC_BY_BOM
Definition: io.h:119
FMODE_READWRITE
#define FMODE_READWRITE
Definition: io.h:107
GetOpenFile
#define GetOpenFile
Definition: io.h:125
RB_WAITFD_OUT
#define RB_WAITFD_OUT
Definition: io.h:41
FMODE_TTY
#define FMODE_TTY
Definition: io.h:110
FMODE_CREATE
#define FMODE_CREATE
Definition: io.h:113
rb_io_enc_t
struct rb_io_enc_t rb_io_enc_t
Definition: io.h:101
FMODE_WRITABLE
#define FMODE_WRITABLE
Definition: io.h:106
FMODE_APPEND
#define FMODE_APPEND
Definition: io.h:112
MakeOpenFile
#define MakeOpenFile
Definition: io.h:130
FMODE_DUPLEX
#define FMODE_DUPLEX
Definition: io.h:111
FMODE_BINMODE
#define FMODE_BINMODE
Definition: io.h:108
RB_IO_POINTER
#define RB_IO_POINTER(obj, fp)
Definition: io.h:124
RB_WAITFD_IN
#define RB_WAITFD_IN
Definition: io.h:39
FMODE_SYNC
#define FMODE_SYNC
Definition: io.h:109
FMODE_EXCL
#define FMODE_EXCL
Definition: io.h:115
FMODE_TEXTMODE
#define FMODE_TEXTMODE
Definition: io.h:117
FMODE_TRUNC
#define FMODE_TRUNC
Definition: io.h:116
rb_io_buffer_t
struct rb_io_buffer_t rb_io_buffer_t
Definition: io.h:59
RUBY_IO_READABLE
@ RUBY_IO_READABLE
Definition: io.h:45
RUBY_IO_PRIORITY
@ RUBY_IO_PRIORITY
Definition: io.h:47
RUBY_IO_WRITABLE
@ RUBY_IO_WRITABLE
Definition: io.h:46
dup2
int dup2(int, int)
Definition: dup2.c:27
strerror
char * strerror(int)
Definition: strerror.c:11
memmove
void * memmove(void *, const void *, size_t)
Definition: memmove.c:7
thread.h
rb_thread_call_with_gvl
void * rb_thread_call_with_gvl(void *(*func)(void *), void *data1)
Definition: thread.c:1892
rb_thread_call_without_gvl2
void * rb_thread_call_without_gvl2(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2)
Definition: thread.c:1801
rb_thread_call_without_gvl
void * rb_thread_call_without_gvl(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2)
util.h
inits.h
Internal header aggregating init functions.
RB_NUM2INT
#define RB_NUM2INT
Definition: int.h:38
FIX2UINT
#define FIX2UINT
Definition: int.h:42
NUM2UINT
#define NUM2UINT
Definition: int.h:45
RB_INT2NUM
#define RB_INT2NUM
Definition: int.h:37
NUM2INT
#define NUM2INT
Definition: int.h:44
INT2NUM
#define INT2NUM
Definition: int.h:43
UINT2NUM
#define UINT2NUM
Definition: int.h:46
encoding.h
Internal header for Encoding.
rb_syserr_fail_path
#define rb_syserr_fail_path(err, path)
Definition: error.h:38
rb_sys_fail_path
#define rb_sys_fail_path(path)
Definition: error.h:37
ruby_sized_xfree
#define ruby_sized_xfree
Definition: gc.h:166
io.h
Internal header for IO.
numeric.h
Internal header for Numeric.
rb_int_modulo
VALUE rb_int_modulo(VALUE x, VALUE y)
Definition: numeric.c:3873
rb_fix_plus
VALUE rb_fix_plus(VALUE x, VALUE y)
Definition: numeric.c:3591
object.h
Internal header for Object.
process.h
Internal header for Process.
rb_execarg_get
struct rb_execarg * rb_execarg_get(VALUE execarg_obj)
Definition: process.c:2837
rb_execarg_parent_end
void rb_execarg_parent_end(VALUE execarg_obj)
Definition: process.c:3082
rb_fork_ruby
rb_pid_t rb_fork_ruby(int *status)
rb_last_status_clear
void rb_last_status_clear(void)
Definition: process.c:666
rb_execarg_setenv
void rb_execarg_setenv(VALUE execarg_obj, VALUE env)
Definition: process.c:2875
rb_execarg_extract_options
VALUE rb_execarg_extract_options(VALUE execarg_obj, VALUE opthash)
Definition: process.c:2506
rb_exec_async_signal_safe
int rb_exec_async_signal_safe(const struct rb_execarg *e, char *errmsg, size_t errmsg_buflen)
Definition: process.c:3751
rb_execarg_new
VALUE rb_execarg_new(int argc, const VALUE *argv, int accept_shell, int allow_exc_opt)
Definition: process.c:2862
rb_execarg_parent_start
void rb_execarg_parent_start(VALUE execarg_obj)
Definition: process.c:3043
rb_execarg_addopt
int rb_execarg_addopt(VALUE execarg_obj, VALUE key, VALUE val)
Definition: process.c:2240
rb_execarg_run_options
int rb_execarg_run_options(const struct rb_execarg *e, struct rb_execarg *s, char *errmsg, size_t errmsg_buflen)
Definition: process.c:3622
rb_fork_async_signal_safe
rb_pid_t rb_fork_async_signal_safe(int *status, int(*chfunc)(void *, char *, size_t), void *charg, VALUE fds, char *errmsg, size_t errmsg_buflen)
STATIC_ASSERT
#define STATIC_ASSERT
Definition: static_assert.h:14
rb_str_locktmp_ensure
VALUE rb_str_locktmp_ensure(VALUE str, VALUE(*func)(VALUE), VALUE arg)
Definition: string.c:2835
rb_str_cat_conv_enc_opts
VALUE rb_str_cat_conv_enc_opts(VALUE newstr, long ofs, const char *ptr, long len, rb_encoding *from, int ecflags, VALUE ecopts)
Definition: string.c:1013
rb_fstring_lit
#define rb_fstring_lit(str)
Definition: string.h:78
rb_str_tmp_frozen_acquire
VALUE rb_str_tmp_frozen_acquire(VALUE str)
Definition: string.c:1287
rb_str_tmp_frozen_release
void rb_str_tmp_frozen_release(VALUE str, VALUE tmp)
Definition: string.c:1294
rb_str_chomp_string
VALUE rb_str_chomp_string(VALUE str, VALUE chomp)
Definition: string.c:9236
thread.h
Internal header for Thread.
rb_mutex_allow_trap
void rb_mutex_allow_trap(VALUE self, int val)
Definition: thread_sync.c:621
rb_mutex_owned_p
VALUE rb_mutex_owned_p(VALUE self)
Definition: thread_sync.c:414
rb_thread_to_be_killed
int rb_thread_to_be_killed(VALUE thread)
Definition: thread.c:2720
rb_uninterruptible
VALUE rb_uninterruptible(VALUE(*b_proc)(VALUE), VALUE data)
Definition: thread.c:5874
rb_thread_execute_interrupts
void rb_thread_execute_interrupts(VALUE th)
Definition: thread.c:2525
rb_thread_io_blocking_region
VALUE rb_thread_io_blocking_region(rb_blocking_function_t *func, void *data1, int fd)
Definition: thread.c:1815
rb_thread_wait_for_single_fd
int rb_thread_wait_for_single_fd(int fd, int events, struct timeval *timeout)
Definition: thread.c:4551
rb_gvar_ractor_local
void rb_gvar_ractor_local(const char *name)
Definition: variable.c:359
internal.h
rp
#define rp(obj)
Definition: internal.h:95
rb_funcallv
#define rb_funcallv(...)
Definition: internal.h:77
rb_method_basic_definition_p
#define rb_method_basic_definition_p(...)
Definition: internal.h:78
rb_io_fptr_finalize
#define rb_io_fptr_finalize(fptr)
Definition: io.c:4872
rb_io_gets
VALUE rb_io_gets(VALUE io)
Definition: io.c:3738
io_tell
#define io_tell(fptr)
Definition: io.c:919
rb_io_wait_writable
int rb_io_wait_writable(int f)
Definition: io.c:1341
io_seek
#define io_seek(fptr, ofs, whence)
Definition: io.c:918
rb_io_ioctl
#define rb_io_ioctl
Definition: io.c:10085
rb_io_modestr_fmode
int rb_io_modestr_fmode(const char *modestr)
Definition: io.c:5580
rb_io_taint_check
VALUE rb_io_taint_check(VALUE io)
Definition: io.c:760
rb_get_argv
VALUE rb_get_argv(void)
Definition: io.c:13082
SEEK_SET
#define SEEK_SET
Definition: io.c:922
shutdown
#define shutdown(a, b)
Definition: io.c:724
rb_io_pwrite
#define rb_io_pwrite
Definition: io.c:5445
do_write_retry
#define do_write_retry(code)
Definition: io.c:1097
rb_rs
VALUE rb_rs
Definition: io.c:200
rb_io_get_io
VALUE rb_io_get_io(VALUE io)
Definition: io.c:790
rb_io_addstr
VALUE rb_io_addstr(VALUE io, VALUE str)
Definition: io.c:1992
bom_prefix_len
@ bom_prefix_len
Definition: io.c:5570
rb_io_fptr_finalize_internal
void rb_io_fptr_finalize_internal(void *ptr)
Definition: io.c:4845
rb_io_read_check
void rb_io_read_check(rb_io_t *fptr)
Definition: io.c:1001
rb_io_modestr_oflags
int rb_io_modestr_oflags(const char *modestr)
Definition: io.c:5713
rb_readwrite_syserr_fail
void rb_readwrite_syserr_fail(enum rb_io_wait_readwrite waiting, int n, const char *mesg)
Definition: io.c:13122
rb_io_fdopen
VALUE rb_io_fdopen(int fd, int oflags, const char *path)
Definition: io.c:8183
rb_io_fcntl
#define rb_io_fcntl
Definition: io.c:10179
IO_CBUF_CAPA_MIN
#define IO_CBUF_CAPA_MIN
Definition: io.c:171
NEXT_ARGF_FORWARD
#define NEXT_ARGF_FORWARD(argc, argv)
Definition: io.c:8788
rb_io_ungetbyte
VALUE rb_io_ungetbyte(VALUE io, VALUE b)
Definition: io.c:4393
rb_io_gets_internal
VALUE rb_io_gets_internal(VALUE io)
Definition: io.c:3744
rb_io_wait_readable
int rb_io_wait_readable(int f)
Definition: io.c:1307
rb_io_getbyte
VALUE rb_io_getbyte(VALUE io)
Definition: io.c:4331
SET_BINARY_MODE_WITH_SEEK_CUR
#define SET_BINARY_MODE_WITH_SEEK_CUR(fptr)
Definition: io.c:720
ruby_set_inplace_mode
void ruby_set_inplace_mode(const char *suffix)
Definition: io.c:13050
NUM2IOCTLREQ
#define NUM2IOCTLREQ(num)
Definition: io.c:9776
rb_cloexec_dup2
int rb_cloexec_dup2(int oldfd, int newfd)
Definition: io.c:353
rb_write_error_str
void rb_write_error_str(VALUE mesg)
Definition: io.c:8083
rb_wait_for_single_fd
int rb_wait_for_single_fd(int fd, int events, struct timeval *timeout)
Definition: io.c:1384
READ_DATA_PENDING
#define READ_DATA_PENDING(fptr)
Definition: io.c:487
rb_io_check_byte_readable
void rb_io_check_byte_readable(rb_io_t *fptr)
Definition: io.c:947
rb_io_make_open_file
rb_io_t * rb_io_make_open_file(VALUE obj)
Definition: io.c:8278
rb_eIOError
VALUE rb_eIOError
Definition: io.c:185
rb_f_syscall
#define rb_f_syscall
Definition: io.c:10310
READ_DATA_PENDING_COUNT
#define READ_DATA_PENDING_COUNT(fptr)
Definition: io.c:488
rb_cIO
VALUE rb_cIO
Definition: io.c:183
argf_of
#define argf_of(obj)
Definition: io.c:482
rb_io_check_readable
void rb_io_check_readable(rb_io_t *fptr)
Definition: io.c:956
EWOULDBLOCK
#define EWOULDBLOCK
Definition: io.c:162
IO_WBUF_CAPA_MIN
#define IO_WBUF_CAPA_MIN
Definition: io.c:173
SEEK_CUR
#define SEEK_CUR
Definition: io.c:923
rb_io_close_on_exec_p
#define rb_io_close_on_exec_p
Definition: io.c:4537
O_ACCMODE
#define O_ACCMODE
Definition: io.c:146
ARGF_GENERIC_INPUT_P
#define ARGF_GENERIC_INPUT_P()
Definition: io.c:8782
rb_io_extract_encoding_option
int rb_io_extract_encoding_option(VALUE opt, rb_encoding **enc_p, rb_encoding **enc2_p, int *fmode_p)
Definition: io.c:5862
rb_maygvl_fd_fix_cloexec
void rb_maygvl_fd_fix_cloexec(int fd)
Definition: io.c:260
READ_CHAR_PENDING_PTR
#define READ_CHAR_PENDING_PTR(fptr)
Definition: io.c:494
rb_p
void rb_p(VALUE obj)
Definition: io.c:7964
FMODE_SIGNAL_ON_EPIPE
#define FMODE_SIGNAL_ON_EPIPE
Definition: io.c:528
fptr_signal_on_epipe
#define fptr_signal_on_epipe(fptr)
Definition: io.c:530
rb_eEOFError
VALUE rb_eEOFError
Definition: io.c:184
IOWAIT_SYSCALL
#define IOWAIT_SYSCALL
Definition: io.c:11054
MAX_REALLOC_GAP
#define MAX_REALLOC_GAP
Definition: io.c:2854
NEED_WRITECONV
#define NEED_WRITECONV(fptr)
Definition: io.c:712
rb_io_oflags_fmode
int rb_io_oflags_fmode(int oflags)
Definition: io.c:5637
rb_io_prep_stderr
VALUE rb_io_prep_stderr(void)
Definition: io.c:8223
MODE_BTMODE
#define MODE_BTMODE(a, b, c)
Definition: io.c:1608
no_exception_p
#define no_exception_p(opts)
Definition: io.c:2963
rb_io_prep_stdout
VALUE rb_io_prep_stdout(void)
Definition: io.c:8217
rb_update_max_fd
void rb_update_max_fd(int fd)
Definition: io.c:233
rb_fdopen
FILE * rb_fdopen(int fd, const char *modestr)
Definition: io.c:6183
rb_stdin
VALUE rb_stdin
Definition: io.c:196
rb_gc_for_fd
int rb_gc_for_fd(int err)
Definition: io.c:1010
rb_io_write
VALUE rb_io_write(VALUE io, VALUE str)
Definition: io.c:1953
NEED_NEWLINE_DECORATOR_ON_WRITE
#define NEED_NEWLINE_DECORATOR_ON_WRITE(fptr)
Definition: io.c:564
rb_sys_fail_on_write
#define rb_sys_fail_on_write(fptr)
Definition: io.c:557
rb_io_prep_stdin
VALUE rb_io_prep_stdin(void)
Definition: io.c:8211
READ_CHECK
#define READ_CHECK(fptr)
Definition: io.c:503
next_argv
#define next_argv()
Definition: io.c:8781
rb_io_puts
VALUE rb_io_puts(int argc, const VALUE *argv, VALUE out)
Definition: io.c:7895
rb_cloexec_open
int rb_cloexec_open(const char *pathname, int flags, mode_t mode)
Definition: io.c:307
KEEPGVL
#define KEEPGVL
Definition: io.c:4890
rb_io_stdio_file
FILE * rb_io_stdio_file(rb_io_t *fptr)
Definition: io.c:8229
rb_stderr
VALUE rb_stderr
Definition: io.c:196
rb_output_rs
VALUE rb_output_rs
Definition: io.c:201
PREP_STDIO_NAME
#define PREP_STDIO_NAME(f)
Definition: io.c:4599
NOFILE
#define NOFILE
Definition: io.c:92
DEFULT_IOCTL_NARG_LEN
#define DEFULT_IOCTL_NARG_LEN
Definition: io.c:9810
rb_io_eof
VALUE rb_io_eof(VALUE io)
Definition: io.c:2298
rb_io_memsize
size_t rb_io_memsize(const rb_io_t *fptr)
Definition: io.c:4875
rb_stdio_set_default_encoding
void rb_stdio_set_default_encoding(void)
Definition: io.c:12002
GetWriteIO
#define GetWriteIO(io)
Definition: io.c:485
NEED_NEWLINE_DECORATOR_ON_READ
#define NEED_NEWLINE_DECORATOR_ON_READ(fptr)
Definition: io.c:563
convconfig_t
struct rb_io_enc_t convconfig_t
Definition: io.c:5930
FMODE_PREP
#define FMODE_PREP
Definition: io.c:527
fmode
#define fmode
ARGF_FORWARD
#define ARGF_FORWARD(argc, argv)
Definition: io.c:8784
READ_DATA_PENDING_PTR
#define READ_DATA_PENDING_PTR(fptr)
Definition: io.c:489
NEED_READCONV
#define NEED_READCONV(fptr)
Definition: io.c:711
FOREACH_ARGF
#define FOREACH_ARGF()
Definition: io.c:12633
is_socket
#define is_socket(fd, path)
Definition: io.c:730
READ_CHAR_PENDING
#define READ_CHAR_PENDING(fptr)
Definition: io.c:492
rb_fd_fix_cloexec
void rb_fd_fix_cloexec(int fd)
Definition: io.c:283
rb_io_flush
VALUE rb_io_flush(VALUE io)
Definition: io.c:2052
READ_CHAR_PENDING_COUNT
#define READ_CHAR_PENDING_COUNT(fptr)
Definition: io.c:493
rb_io_check_initialized
void rb_io_check_initialized(rb_io_t *fptr)
Definition: io.c:767
rb_io_fsync
#define rb_io_fsync
Definition: io.c:2401
rb_io_ascii8bit_binmode
VALUE rb_io_ascii8bit_binmode(VALUE io)
Definition: io.c:5495
rb_io_binmode
VALUE rb_io_binmode(VALUE io)
Definition: io.c:5449
DEFAULT_TEXTMODE
#define DEFAULT_TEXTMODE
Definition: io.c:710
rb_io_check_io
VALUE rb_io_check_io(VALUE io)
Definition: io.c:796
rb_io_printf
VALUE rb_io_printf(int argc, const VALUE *argv, VALUE out)
Definition: io.c:7649
rb_io_ungetc
VALUE rb_io_ungetc(VALUE io, VALUE c)
Definition: io.c:4432
IO_RBUF_CAPA_FOR
#define IO_RBUF_CAPA_FOR(fptr)
Definition: io.c:172
rb_io_sync
#define rb_io_sync
Definition: io.c:2402
MORE_CHAR_SUSPENDED
#define MORE_CHAR_SUSPENDED
Definition: io.c:2719
rb_pipe
int rb_pipe(int *pipes)
Definition: io.c:6499
NEED_NEWLINE_DECORATOR_ON_READ_CHECK
#define NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr)
Definition: io.c:718
rb_io_unbuffered
void rb_io_unbuffered(rb_io_t *fptr)
Definition: io.c:6493
S_ISREG
#define S_ISREG(m)
Definition: io.c:1049
rb_notify_fd_close
int rb_notify_fd_close(int fd, struct list_head *)
Definition: thread.c:2607
rb_stderr_tty_p
int rb_stderr_tty_p(void)
Definition: io.c:8105
rb_gets
VALUE rb_gets(void)
Definition: io.c:9104
rb_io_bufwrite
ssize_t rb_io_bufwrite(VALUE io, const void *buf, size_t size)
Definition: io.c:1698
rb_io_flush_raw
VALUE rb_io_flush_raw(VALUE io, int sync)
Definition: io.c:2013
rb_cloexec_fcntl_dupfd
int rb_cloexec_fcntl_dupfd(int fd, int minfd)
Definition: io.c:440
rb_output_fs
VALUE rb_output_fs
Definition: io.c:199
MODE_BINARY
#define MODE_BINARY(a, b)
MODE_BTXMODE
#define MODE_BTXMODE(a, b, c, d, e, f)
Definition: io.c:1611
rb_mWaitReadable
VALUE rb_mWaitReadable
Definition: io.c:186
rb_io_check_char_readable
void rb_io_check_char_readable(rb_io_t *fptr)
Definition: io.c:928
READ_DATA_BUFFERED
#define READ_DATA_BUFFERED(fptr)
Definition: io.c:490
rb_mWaitWritable
VALUE rb_mWaitWritable
Definition: io.c:187
SET_BINARY_MODE
#define SET_BINARY_MODE(fptr)
Definition: io.c:717
ARGF_block_call
#define ARGF_block_call(mid, argc, argv, func, argf)
Definition: io.c:12646
rb_io_read_pending
int rb_io_read_pending(rb_io_t *fptr)
Definition: io.c:992
rb_io_get_write_io
VALUE rb_io_get_write_io(VALUE io)
Definition: io.c:802
SEEK_END
#define SEEK_END
Definition: io.c:924
rb_io_set_nonblock
void rb_io_set_nonblock(rb_io_t *fptr)
Definition: io.c:2942
rb_readwrite_sys_fail
void rb_readwrite_sys_fail(enum rb_io_wait_readwrite waiting, const char *mesg)
Definition: io.c:13116
ruby_static_id_signo
ID ruby_static_id_signo
Definition: eval.c:51
rb_io_popen
VALUE rb_io_popen(VALUE pname, VALUE pmode, VALUE env, VALUE opt)
Definition: io.c:7040
MORE_CHAR_FINISHED
#define MORE_CHAR_FINISHED
Definition: io.c:2720
rb_io_set_close_on_exec
#define rb_io_set_close_on_exec
Definition: io.c:4595
rb_file_open
VALUE rb_file_open(const char *fname, const char *modestr)
Definition: io.c:6389
SHUT_WR
#define SHUT_WR
rb_cloexec_pipe
int rb_cloexec_pipe(int descriptors[2])
Definition: io.c:406
rb_cloexec_dup
int rb_cloexec_dup(int oldfd)
Definition: io.c:346
rb_io_set_write_io
VALUE rb_io_set_write_io(VALUE io, VALUE w)
Definition: io.c:813
off_t
#define off_t
Definition: io.c:78
rb_file_open_str
VALUE rb_file_open_str(VALUE fname, const char *modestr)
Definition: io.c:6382
utf_prefix_len
@ utf_prefix_len
Definition: io.c:5571
rb_write_error
void rb_write_error(const char *mesg)
Definition: io.c:8077
rb_io_check_writable
void rb_io_check_writable(rb_io_t *fptr)
Definition: io.c:980
rb_io_fdatasync
#define rb_io_fdatasync
Definition: io.c:2453
IS_PREP_STDIO
#define IS_PREP_STDIO(f)
Definition: io.c:4598
SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2
#define SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags)
Definition: io.c:719
rb_execarg_commandline
char * rb_execarg_commandline(const struct rb_execarg *eargp, VALUE *prog)
Definition: process.c:4548
rb_io_print
VALUE rb_io_print(int argc, const VALUE *argv, VALUE out)
Definition: io.c:7720
rb_io_pread
#define rb_io_pread
Definition: io.c:5385
ioctl_req_t
int ioctl_req_t
Definition: io.c:9775
rb_stdout
VALUE rb_stdout
Definition: io.c:196
rb_io_check_closed
void rb_io_check_closed(rb_io_t *fptr)
Definition: io.c:775
SHUT_RD
#define SHUT_RD
rb_eof_error
void rb_eof_error(void)
Definition: io.c:754
rb_write_error2
void rb_write_error2(const char *mesg, long len)
Definition: io.c:8058
rb_io_synchronized
void rb_io_synchronized(rb_io_t *fptr)
Definition: io.c:6486
rb_io_wait
VALUE rb_io_wait(VALUE io, VALUE events, VALUE timeout)
Definition: io.c:1265
Init_IO
void Init_IO(void)
Definition: io.c:13335
ARGF
#define ARGF
Definition: io.c:483
rb_io_close
VALUE rb_io_close(VALUE io)
Definition: io.c:4935
free
#define free(x)
Definition: io.c:42
rb_default_rs
VALUE rb_default_rs
Definition: io.c:202
size
voidpf void uLong size
Definition: ioapi.h:138
filename
const char * filename
Definition: ioapi.h:137
long
typedef long(ZCALLBACK *tell_file_func) OF((voidpf opaque
offset
voidpf uLong offset
Definition: ioapi.h:144
int
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque
mode
const char int mode
Definition: ioapi.h:137
buf
voidpf void * buf
Definition: ioapi.h:138
RB_BLOCK_CALL_FUNC_ARGLIST
#define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)
Definition: iterator.h:31
rb_yield_values2
VALUE rb_yield_values2(int n, const VALUE *argv)
Definition: vm_eval.c:1375
rb_yield
VALUE rb_yield(VALUE)
Definition: vm_eval.c:1341
SSIZE_MAX
#define SSIZE_MAX
Definition: limits.h:87
LONG_MAX
#define LONG_MAX
Definition: limits.h:36
INT2FIX
#define INT2FIX
Definition: long.h:48
LONG2FIX
#define LONG2FIX
Definition: long.h:49
LONG2NUM
#define LONG2NUM
Definition: long.h:50
FIX2LONG
#define FIX2LONG
Definition: long.h:46
NUM2LONG
#define NUM2LONG
Definition: long.h:51
memcmp
int memcmp(const void *s1, const void *s2, size_t len)
Definition: memcmp.c:7
MEMZERO
#define MEMZERO(p, type, n)
Definition: memory.h:128
ALLOC_N
#define ALLOC_N
Definition: memory.h:133
RB_GC_GUARD
#define RB_GC_GUARD(v)
Definition: memory.h:91
MEMMOVE
#define MEMMOVE(p1, p2, type, n)
Definition: memory.h:130
ALLOCV_N
#define ALLOCV_N
Definition: memory.h:139
ALLOCV_END
#define ALLOCV_END
Definition: memory.h:140
NUM2MODET
#define NUM2MODET
Definition: mode_t.h:27
ruby::backward::cxxanyargs::rb_define_hooked_variable
void rb_define_hooked_variable(const char *q, VALUE *w, type *e, void_type *r)
Define a function-backended global variable.
Definition: cxxanyargs.hpp:136
ruby::backward::cxxanyargs::rb_define_virtual_variable
void rb_define_virtual_variable(const char *q, type *w, void_type *e)
Define a function-backended global variable.
Definition: cxxanyargs.hpp:73
NEWOBJ_OF
#define NEWOBJ_OF
Definition: newobj.h:35
name
const char * name
Definition: nkf.c:208
last
unsigned int last
Definition: nkf.c:4324
count
int count
Definition: nkf.c:5055
TRUE
#define TRUE
Definition: nkf.h:175
FALSE
#define FALSE
Definition: nkf.h:174
OFFT2NUM
#define OFFT2NUM
Definition: off_t.h:32
NUM2OFFT
#define NUM2OFFT
Definition: off_t.h:42
ONIGENC_CONSTRUCT_MBCLEN_CHARFOUND
#define ONIGENC_CONSTRUCT_MBCLEN_CHARFOUND(n)
Definition: onigmo.h:345
PIDT2NUM
#define PIDT2NUM
Definition: pid_t.h:27
rb_fd_isset
#define rb_fd_isset
Definition: posix.h:41
rb_fd_select
#define rb_fd_select
Definition: posix.h:43
rb_fd_init
#define rb_fd_init
Definition: posix.h:42
rb_fd_set
#define rb_fd_set
Definition: posix.h:39
rb_fd_term
#define rb_fd_term(f)
Definition: posix.h:80
RARRAY_CONST_PTR
#define RARRAY_CONST_PTR(s)
Definition: psych_emitter.c:4
RARRAY_AREF
#define RARRAY_AREF(a, i)
Definition: psych_emitter.c:7
ractor.h
rb_ractor_stdout_set
void rb_ractor_stdout_set(VALUE)
Definition: ractor.c:2172
rb_ractor_stdin_set
void rb_ractor_stdin_set(VALUE)
Definition: ractor.c:2160
rb_ractor_stderr
VALUE rb_ractor_stderr(void)
Definition: ractor.c:2148
rb_ractor_stdin
VALUE rb_ractor_stdin(void)
Definition: ractor.c:2124
rb_ractor_stdout
VALUE rb_ractor_stdout(void)
Definition: ractor.c:2136
rb_ractor_stderr_set
void rb_ractor_stderr_set(VALUE)
Definition: ractor.c:2184
RARRAY_LEN
#define RARRAY_LEN
Definition: rarray.h:52
NULL
#define NULL
Definition: regenc.h:69
RFILE
#define RFILE(obj)
Definition: rfile.h:35
SafeStringValue
#define SafeStringValue(v)
Definition: rstring.h:53
StringValue
#define StringValue(v)
Definition: rstring.h:50
RSTRING_GETMEM
#define RSTRING_GETMEM(str, ptrvar, lenvar)
Definition: rstring.h:211
StringValueCStr
#define StringValueCStr(v)
Definition: rstring.h:52
RUBY_TYPED_DEFAULT_FREE
#define RUBY_TYPED_DEFAULT_FREE
Definition: rtypeddata.h:44
RUBY_TYPED_FREE_IMMEDIATELY
@ RUBY_TYPED_FREE_IMMEDIATELY
Definition: rtypeddata.h:62
TypedData_Make_Struct
#define TypedData_Make_Struct(klass, type, data_type, sval)
Definition: rtypeddata.h:122
ruby.h
FilePathValue
#define FilePathValue(v)
Definition: ruby.h:61
argc
int argc
Definition: ruby.c:240
argv
char ** argv
Definition: ruby.c:241
ruby_atomic.h
ATOMIC_CAS
#define ATOMIC_CAS(var, oldval, newval)
Definition: ruby_atomic.h:5
RB_INTEGER_TYPE_P
#define RB_INTEGER_TYPE_P(obj)
Definition: ruby_missing.h:15
RB_SCAN_ARGS_LAST_HASH_KEYWORDS
#define RB_SCAN_ARGS_LAST_HASH_KEYWORDS
Definition: scan_args.h:45
RB_PASS_CALLED_KEYWORDS
#define RB_PASS_CALLED_KEYWORDS
Definition: scan_args.h:48
scheduler.h
Internal header for Scheduler.
rb_scheduler_io_wait_writable
VALUE rb_scheduler_io_wait_writable(VALUE scheduler, VALUE io)
Definition: scheduler.c:184
rb_scheduler_io_wait
VALUE rb_scheduler_io_wait(VALUE scheduler, VALUE io, VALUE events, VALUE timeout)
Definition: scheduler.c:172
rb_scheduler_current
VALUE rb_scheduler_current()
Definition: scheduler.c:105
rb_scheduler_timeout
VALUE rb_scheduler_timeout(struct timeval *timeout)
Definition: scheduler.c:126
rb_scheduler_supports_io_read
int rb_scheduler_supports_io_read(VALUE scheduler)
Definition: scheduler.c:190
rb_scheduler_io_wait_readable
VALUE rb_scheduler_io_wait_readable(VALUE scheduler, VALUE io)
Definition: scheduler.c:178
rb_thread_scheduler_current
VALUE rb_thread_scheduler_current(VALUE thread)
Definition: scheduler.c:110
rb_scheduler_supports_io_write
int rb_scheduler_supports_io_write(VALUE scheduler)
Definition: scheduler.c:202
rb_scheduler_io_read
VALUE rb_scheduler_io_read(VALUE scheduler, VALUE io, VALUE buffer, size_t offset, size_t length)
Definition: scheduler.c:196
rb_scheduler_io_write
VALUE rb_scheduler_io_write(VALUE scheduler, VALUE io, VALUE buffer, size_t offset, size_t length)
Definition: scheduler.c:208
rb_thread_fd_select
int rb_thread_fd_select(int, rb_fdset_t *, rb_fdset_t *, rb_fdset_t *, struct timeval *)
Definition: thread.c:4330
cnt
rb_atomic_t cnt[RUBY_NSIG]
Definition: signal.c:508
RB_NUM2SSIZE
#define RB_NUM2SSIZE
Definition: size_t.h:42
SSIZET2NUM
#define SSIZET2NUM
Definition: size_t.h:54
NUM2SIZET
#define NUM2SIZET
Definition: size_t.h:51
Qundef
#define Qundef
Definition: special_consts.h:53
Qtrue
#define Qtrue
Definition: special_consts.h:52
RTEST
#define RTEST
Definition: special_consts.h:42
Qnil
#define Qnil
Definition: special_consts.h:51
Qfalse
#define Qfalse
Definition: special_consts.h:50
NIL_P
#define NIL_P
Definition: special_consts.h:46
FIXNUM_P
#define FIXNUM_P
Definition: special_consts.h:44
f
#define f
rb_str_catf
VALUE rb_str_catf(VALUE, const char *,...)
Definition: sprintf.c:1243
rb_f_sprintf
VALUE rb_f_sprintf(int, const VALUE *)
Definition: sprintf.c:208
rb_sprintf
VALUE rb_sprintf(const char *,...)
Definition: sprintf.c:1203
_
#define _(args)
Definition: stdarg.h:31
stdbool.h
C99 shim for <stdbool.h>
strlen
size_t strlen(const char *)
rb_io_extract_modeenc
#define rb_io_extract_modeenc
Definition: stringio.c:36
__sFILE
Definition: vsnprintf.c:169
OnigEncodingTypeST
Definition: onigmo.h:160
RFile
Definition: rfile.h:30
argf_call_arg
Definition: io.c:12366
argf_call_arg::argf
VALUE argf
Definition: io.c:12369
argf_call_arg::argv
VALUE * argv
Definition: io.c:12368
argf_call_arg::argc
int argc
Definition: io.c:12367
argf
Definition: io.c:221
argf::last_lineno
long last_lineno
Definition: io.c:223
argf::encs
struct rb_io_enc_t encs
Definition: io.c:227
argf::inplace
VALUE inplace
Definition: io.c:226
argf::next_p
int8_t next_p
Definition: io.c:228
argf::filename
VALUE filename
Definition: io.c:222
argf::lineno
long lineno
Definition: io.c:224
argf::current_file
VALUE current_file
Definition: io.c:222
argf::init_p
int8_t init_p
Definition: io.c:228
argf::binmode
int8_t binmode
Definition: io.c:228
argf::argv
VALUE argv
Definition: io.c:225
binwrite_arg
Definition: io.c:1453
binwrite_arg::ptr
const char * ptr
Definition: io.c:1456
binwrite_arg::length
long length
Definition: io.c:1457
binwrite_arg::str
VALUE str
Definition: io.c:1455
binwrite_arg::fptr
rb_io_t * fptr
Definition: io.c:1454
bufread_arg
Definition: io.c:2615
bufread_arg::fptr
rb_io_t * fptr
Definition: io.c:2618
bufread_arg::len
long len
Definition: io.c:2617
bufread_arg::str_ptr
char * str_ptr
Definition: io.c:2616
copy_stream_struct
Definition: io.c:10959
copy_stream_struct::dst_fd
int dst_fd
Definition: io.c:10966
copy_stream_struct::close_src
unsigned close_src
Definition: io.c:10967
copy_stream_struct::copy_length
off_t copy_length
Definition: io.c:10962
copy_stream_struct::src_stat
struct stat src_stat
Definition: io.c:10974
copy_stream_struct::close_dst
unsigned close_dst
Definition: io.c:10968
copy_stream_struct::total
off_t total
Definition: io.c:10970
copy_stream_struct::syserr
const char * syserr
Definition: io.c:10971
copy_stream_struct::src
VALUE src
Definition: io.c:10960
copy_stream_struct::notimp
const char * notimp
Definition: io.c:10972
copy_stream_struct::dst
VALUE dst
Definition: io.c:10961
copy_stream_struct::error_no
int error_no
Definition: io.c:10969
copy_stream_struct::th
VALUE th
Definition: io.c:10973
copy_stream_struct::src_fd
int src_fd
Definition: io.c:10965
copy_stream_struct::dst_stat
struct stat dst_stat
Definition: io.c:10975
copy_stream_struct::src_offset
off_t src_offset
Definition: io.c:10963
file
Definition: gzappend.c:170
finish_writeconv_arg
Definition: io.c:4664
finish_writeconv_arg::fptr
rb_io_t * fptr
Definition: io.c:4665
finish_writeconv_arg::noalloc
int noalloc
Definition: io.c:4666
foreach_arg
Definition: io.c:10557
foreach_arg::io
VALUE io
Definition: io.c:10560
foreach_arg::argv
VALUE * argv
Definition: io.c:10559
foreach_arg::argc
int argc
Definition: io.c:10558
getline_arg
Definition: stringio.c:1117
getline_arg::chomp
unsigned int chomp
Definition: stringio.c:1120
getline_arg::rs
VALUE rs
Definition: stringio.c:1118
getline_arg::limit
long limit
Definition: stringio.c:1119
getline_arg::io
VALUE io
Definition: io.c:3514
io_encoding_set_args
Definition: io.c:10390
io_encoding_set_args::v2
VALUE v2
Definition: io.c:10393
io_encoding_set_args::opt
VALUE opt
Definition: io.c:10394
io_encoding_set_args::v1
VALUE v1
Definition: io.c:10392
io_encoding_set_args::fptr
rb_io_t * fptr
Definition: io.c:10391
io_internal_read_struct
Definition: io.c:1052
io_internal_read_struct::nonblock
int nonblock
Definition: io.c:1055
io_internal_read_struct::fd
int fd
Definition: io.c:1054
io_internal_read_struct::capa
size_t capa
Definition: io.c:1057
io_internal_read_struct::th
VALUE th
Definition: io.c:1053
io_internal_read_struct::buf
void * buf
Definition: io.c:1056
io_internal_write_struct
Definition: io.c:1060
io_internal_write_struct::fd
int fd
Definition: io.c:1061
io_internal_write_struct::capa
size_t capa
Definition: io.c:1063
io_internal_write_struct::buf
const void * buf
Definition: io.c:1062
iovec
Definition: win32.h:218
iovec::iov_base
void * iov_base
Definition: win32.h:219
iovec::iov_len
size_t iov_len
Definition: win32.h:220
rb_data_type_struct
Definition: rtypeddata.h:70
rb_execarg
Definition: process.h:30
rb_execarg::sh
struct rb_execarg::@113::@114 sh
rb_execarg::command_name
VALUE command_name
Definition: process.h:36
rb_execarg::use_shell
unsigned use_shell
Definition: process.h:46
rb_execarg::envp_str
VALUE envp_str
Definition: process.h:43
rb_execarg::shell_script
VALUE shell_script
Definition: process.h:33
rb_execarg::cmd
struct rb_execarg::@113::@115 cmd
rb_execarg::argv_str
VALUE argv_str
Definition: process.h:38
rb_execarg::invoke
union rb_execarg::@113 invoke
rb_execution_context_struct
Definition: vm_core.h:854
rb_fdset_t
Definition: largesize.h:69
rb_global_variable
Definition: variable.c:320
rb_io_t::rb_io_enc_t::ecflags
int ecflags
Definition: io.h:85
rb_io_t::rb_io_enc_t::enc
rb_encoding * enc
Definition: io.h:83
rb_io_t::rb_io_enc_t::enc2
rb_encoding * enc2
Definition: io.h:84
rb_io_t::rb_io_enc_t::ecopts
VALUE ecopts
Definition: io.h:86
rb_io_t
Definition: io.h:61
rb_io_t::fd
int fd
Definition: io.h:65
rb_io_t::encs
struct rb_io_t::rb_io_enc_t encs
rb_io_t::lineno
int lineno
Definition: io.h:68
rb_io_t::writeconv
rb_econv_t * writeconv
Definition: io.h:92
rb_io_t::pid
rb_pid_t pid
Definition: io.h:67
rb_io_t::wbuf
rb_io_buffer_t wbuf
Definition: io.h:72
rb_io_t::readconv
rb_econv_t * readconv
Definition: io.h:89
rb_io_t::writeconv_asciicompat
VALUE writeconv_asciicompat
Definition: io.h:93
rb_io_t::stdio_file
FILE * stdio_file
Definition: io.h:64
rb_io_t::writeconv_initialized
int writeconv_initialized
Definition: io.h:94
rb_io_t::pathv
VALUE pathv
Definition: io.h:69
rb_io_t::mode
int mode
Definition: io.h:66
rb_io_t::writeconv_pre_ecflags
int writeconv_pre_ecflags
Definition: io.h:95
rb_io_t::write_lock
VALUE write_lock
Definition: io.h:98
rb_io_t::cbuf
rb_io_buffer_t cbuf
Definition: io.h:90
rb_io_t::self
VALUE self
Definition: io.h:62
rb_io_t::writeconv_pre_ecopts
VALUE writeconv_pre_ecopts
Definition: io.h:96
rb_io_t::tied_io_for_writing
VALUE tied_io_for_writing
Definition: io.h:74
rb_io_t::finalize
void(* finalize)(struct rb_io_t *, int)
Definition: io.h:70
rb_io_t::rbuf
rb_io_buffer_t rbuf
Definition: io.h:72
seek_arg
Definition: io.c:10709
seek_arg::io
VALUE io
Definition: io.c:10710
seek_arg::mode
int mode
Definition: io.c:10712
seek_arg::offset
VALUE offset
Definition: io.c:10711
select_args
Definition: io.c:9409
select_args::fdsets
rb_fdset_t fdsets[4]
Definition: io.c:9412
select_args::timeout
struct timeval * timeout
Definition: io.c:9411
select_args::write
VALUE write
Definition: io.c:9410
select_args::read
VALUE read
Definition: io.c:9410
select_args::except
VALUE except
Definition: io.c:9410
state
Definition: blast.c:41
sysopen_struct
Definition: io.c:6134
sysopen_struct::perm
mode_t perm
Definition: io.c:6137
sysopen_struct::oflags
int oflags
Definition: io.c:6136
sysopen_struct::fname
VALUE fname
Definition: io.c:6135
timeval
Definition: missing.h:51
wait_for_single_fd
Definition: io.c:11013
wait_for_single_fd::fd
int fd
Definition: io.c:11016
wait_for_single_fd::events
short events
Definition: io.c:11017
wait_for_single_fd::scheduler
VALUE scheduler
Definition: io.c:11014
wait_for_single_fd::result
VALUE result
Definition: io.c:11019
write_arg
Definition: io.c:1460
write_arg::str
VALUE str
Definition: io.c:1462
write_arg::nosync
int nosync
Definition: io.c:1463
write_arg::io
VALUE io
Definition: io.c:1461
t
#define t
Definition: symbol.c:253
transcode.h
Internal header for Encoding::Converter.
rb_econv_memsize
size_t rb_econv_memsize(rb_econv_t *)
Definition: transcode.c:1712
error
void error(const char *msg)
Definition: untgz.c:593
prog
char * prog
Definition: untgz.c:125
ALLOC
#define ALLOC(size)
Definition: unzip.c:112
VALUE
unsigned long VALUE
Definition: value.h:38
SIGNED_VALUE
#define SIGNED_VALUE
Definition: value.h:40
ID
unsigned long ID
Definition: value.h:39
TYPE
#define TYPE(_)
Definition: value_type.h:105
T_FILE
#define T_FILE
Definition: value_type.h:61
T_STRING
#define T_STRING
Definition: value_type.h:77
T_NIL
#define T_NIL
Definition: value_type.h:71
T_BIGNUM
#define T_BIGNUM
Definition: value_type.h:56
T_FIXNUM
#define T_FIXNUM
Definition: value_type.h:62
T_ARRAY
#define T_ARRAY
Definition: value_type.h:55
SYMBOL_P
#define SYMBOL_P
Definition: value_type.h:87
rb_id2str
#define rb_id2str(id)
Definition: vm_backtrace.c:30
vm_core.h
VM_UNREACHABLE
#define VM_UNREACHABLE(func)
Definition: vm_core.h:62
dp
#define dp(v)
Definition: vm_debug.h:20
EOF
#define EOF
Definition: vsnprintf.c:203
fileno
#define fileno(p)
Definition: vsnprintf.c:219
ioctl_arg
#define ioctl_arg
Definition: wait.c:33
fchmod
int fchmod(int fd, int mode)
Definition: win32.c:7713
err
int err
Definition: win32.c:142
env
#define env
rb_w32_write_console
long rb_w32_write_console(uintptr_t, int)
Definition: win32.c:7300
intptr_t
int intptr_t
Definition: win32.h:90
stat
#define stat
Definition: win32.h:195
rb_w32_get_osfhandle
SOCKET rb_w32_get_osfhandle(int)
Definition: win32.c:1115
rb_w32_fd_is_text
char rb_w32_fd_is_text(int)
Definition: win32.c:7831
getuid
rb_uid_t getuid(void)
Definition: win32.c:2821
O_NONBLOCK
#define O_NONBLOCK
Definition: win32.h:584
EINPROGRESS
#define EINPROGRESS
Definition: win32.h:471
FD_CLOEXEC
#define FD_CLOEXEC
Definition: win32.h:583
fstat
#define fstat(fd, st)
Definition: win32.h:202
fcntl
int fcntl(int, int,...)
Definition: win32.c:4338
F_DUPFD
#define F_DUPFD
Definition: win32.h:575
rb_w32_set_nonblock
int rb_w32_set_nonblock(int)
Definition: win32.c:4446
F_GETFD
#define F_GETFD
Definition: win32.h:576
chown
int chown(const char *, int, int)
Definition: win32.c:4819
F_SETFD
#define F_SETFD
Definition: win32.h:577
mode_t
#define mode_t
Definition: win32.h:119
fsync
#define fsync
Definition: win32.h:209
ioctl
int ioctl(int, int,...)
Definition: win32.c:2867
off_t
#define off_t
Definition: win32.h:194
F_SETFL
#define F_SETFL
Definition: win32.h:581
F_DUPFD_CLOEXEC
#define F_DUPFD_CLOEXEC
Definition: win32.h:582
WNOHANG
#define WNOHANG
Definition: win32.h:128
if
if((ID)(DISPID) nameid !=nameid)
Definition: win32ole.c:357
write
int write(ozstream &zs, const T *x, Items items)
Definition: zstream.h:264
read
int read(izstream &zs, T *x, Items items)
Definition: zstream.h:115
ZALLOC
#define ZALLOC(strm, items, size)
Definition: zutil.h:266
fdopen
#define fdopen(fd, type)
Definition: zutil.h:181