Ruby 2.7.7p221 (2022-11-24 revision 168ec2b1e5ad0e4688e963d9de019557c78feed9)
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/encoding.h"
15#include "ruby/io.h"
16#include "ruby/thread.h"
17#include "internal.h"
18#include "dln.h"
19#include "encindex.h"
20#include "id.h"
21#include <ctype.h>
22#include <errno.h>
23#include "ruby_atomic.h"
24#include "ccan/list/list.h"
25
26/* non-Linux poll may not work on all FDs */
27#if defined(HAVE_POLL)
28# if defined(__linux__)
29# define USE_POLL 1
30# endif
31# if defined(__FreeBSD_version) && __FreeBSD_version >= 1100000
32# define USE_POLL 1
33# endif
34#endif
35
36#ifndef USE_POLL
37# define USE_POLL 0
38#endif
39
40#if !USE_POLL
41# include "vm_core.h"
42#endif
43
44#include "builtin.h"
45
46#undef free
47#define free(x) xfree(x)
48
49#if defined(DOSISH) || defined(__CYGWIN__)
50#include <io.h>
51#endif
52
53#include <sys/types.h>
54#if defined HAVE_NET_SOCKET_H
55# include <net/socket.h>
56#elif defined HAVE_SYS_SOCKET_H
57# include <sys/socket.h>
58#endif
59
60#if defined(__BOW__) || defined(__CYGWIN__) || defined(_WIN32)
61# define NO_SAFE_RENAME
62#endif
63
64#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__sun) || defined(_nec_ews)
65# define USE_SETVBUF
66#endif
67
68#ifdef __QNXNTO__
69#include <unix.h>
70#endif
71
72#include <sys/types.h>
73#if defined(HAVE_SYS_IOCTL_H) && !defined(_WIN32)
74#include <sys/ioctl.h>
75#endif
76#if defined(HAVE_FCNTL_H) || defined(_WIN32)
77#include <fcntl.h>
78#elif defined(HAVE_SYS_FCNTL_H)
79#include <sys/fcntl.h>
80#endif
81
82#if !HAVE_OFF_T && !defined(off_t)
83# define off_t long
84#endif
85
86#ifdef HAVE_SYS_TIME_H
87# include <sys/time.h>
88#endif
89
90#include <sys/stat.h>
91
92#if defined(HAVE_SYS_PARAM_H) || defined(__HIUX_MPP__)
93# include <sys/param.h>
94#endif
95
96#if !defined NOFILE
97# define NOFILE 64
98#endif
99
100#ifdef HAVE_UNISTD_H
101#include <unistd.h>
102#endif
103
104#ifdef HAVE_SYSCALL_H
105#include <syscall.h>
106#elif defined HAVE_SYS_SYSCALL_H
107#include <sys/syscall.h>
108#endif
109
110#ifdef HAVE_SYS_UIO_H
111#include <sys/uio.h>
112#endif
113
114#ifdef HAVE_SYS_WAIT_H
115# include <sys/wait.h> /* for WNOHANG on BSD */
116#endif
117
118#ifdef HAVE_COPYFILE_H
119# include <copyfile.h>
120#endif
121
122#include "ruby/util.h"
123
124#ifndef O_ACCMODE
125#define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR)
126#endif
127
128#if SIZEOF_OFF_T > SIZEOF_LONG && !defined(HAVE_LONG_LONG)
129# error off_t is bigger than long, but you have no long long...
130#endif
131
132#ifndef PIPE_BUF
133# ifdef _POSIX_PIPE_BUF
134# define PIPE_BUF _POSIX_PIPE_BUF
135# else
136# define PIPE_BUF 512 /* is this ok? */
137# endif
138#endif
139
140#ifndef EWOULDBLOCK
141# define EWOULDBLOCK EAGAIN
142#endif
143
144#if defined(HAVE___SYSCALL) && (defined(__APPLE__) || defined(__OpenBSD__))
145/* Mac OS X and OpenBSD have __syscall but don't define it in headers */
146off_t __syscall(quad_t number, ...);
147#endif
148
149#define IO_RBUF_CAPA_MIN 8192
150#define IO_CBUF_CAPA_MIN (128*1024)
151#define IO_RBUF_CAPA_FOR(fptr) (NEED_READCONV(fptr) ? IO_CBUF_CAPA_MIN : IO_RBUF_CAPA_MIN)
152#define IO_WBUF_CAPA_MIN 8192
153
154/* define system APIs */
155#ifdef _WIN32
156#undef open
157#define open rb_w32_uopen
158#undef rename
159#define rename(f, t) rb_w32_urename((f), (t))
160#endif
161
162#if defined(_WIN32)
163# define RUBY_PIPE_NONBLOCK_DEFAULT (0)
164#elif defined(O_NONBLOCK)
165 /* disabled for [Bug #15356] (Rack::Deflater + rails) failure: */
166# define RUBY_PIPE_NONBLOCK_DEFAULT (0)
167#else /* any platforms where O_NONBLOCK does not exist? */
168# define RUBY_PIPE_NONBLOCK_DEFAULT (0)
169#endif
170
176
177static VALUE rb_eEAGAINWaitReadable;
178static VALUE rb_eEAGAINWaitWritable;
179static VALUE rb_eEWOULDBLOCKWaitReadable;
180static VALUE rb_eEWOULDBLOCKWaitWritable;
181static VALUE rb_eEINPROGRESSWaitWritable;
182static VALUE rb_eEINPROGRESSWaitReadable;
183
185static VALUE orig_stdout, orig_stderr;
186
191
192static VALUE argf;
193
194static ID id_write, id_read, id_getc, id_flush, id_readpartial, id_set_encoding;
195static VALUE sym_mode, sym_perm, sym_flags, sym_extenc, sym_intenc, sym_encoding, sym_open_args;
196static VALUE sym_textmode, sym_binmode, sym_autoclose;
197static VALUE sym_SET, sym_CUR, sym_END;
198static VALUE sym_wait_readable, sym_wait_writable;
199#ifdef SEEK_DATA
200static VALUE sym_DATA;
201#endif
202#ifdef SEEK_HOLE
203static VALUE sym_HOLE;
204#endif
205
206struct argf {
208 long last_lineno; /* $. */
209 long lineno;
214};
215
216static rb_atomic_t max_file_descriptor = NOFILE;
217void
219{
220 rb_atomic_t afd = (rb_atomic_t)fd;
221 rb_atomic_t max_fd = max_file_descriptor;
222 int err;
223
224 if (fd < 0 || afd <= max_fd)
225 return;
226
227#if defined(HAVE_FCNTL) && defined(F_GETFL)
228 err = fcntl(fd, F_GETFL) == -1;
229#else
230 {
231 struct stat buf;
232 err = fstat(fd, &buf) != 0;
233 }
234#endif
235 if (err && errno == EBADF) {
236 rb_bug("rb_update_max_fd: invalid fd (%d) given.", fd);
237 }
238
239 while (max_fd < afd) {
240 max_fd = ATOMIC_CAS(max_file_descriptor, max_fd, afd);
241 }
242}
243
244void
246{
247 /* MinGW don't have F_GETFD and FD_CLOEXEC. [ruby-core:40281] */
248#if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
249 int flags, flags2, ret;
250 flags = fcntl(fd, F_GETFD); /* should not fail except EBADF. */
251 if (flags == -1) {
252 rb_bug("rb_maygvl_fd_fix_cloexec: fcntl(%d, F_GETFD) failed: %s", fd, strerror(errno));
253 }
254 if (fd <= 2)
255 flags2 = flags & ~FD_CLOEXEC; /* Clear CLOEXEC for standard file descriptors: 0, 1, 2. */
256 else
257 flags2 = flags | FD_CLOEXEC; /* Set CLOEXEC for non-standard file descriptors: 3, 4, 5, ... */
258 if (flags != flags2) {
259 ret = fcntl(fd, F_SETFD, flags2);
260 if (ret != 0) {
261 rb_bug("rb_maygvl_fd_fix_cloexec: fcntl(%d, F_SETFD, %d) failed: %s", fd, flags2, strerror(errno));
262 }
263 }
264#endif
265}
266
267void
269{
272}
273
274/* this is only called once */
275static int
276rb_fix_detect_o_cloexec(int fd)
277{
278#if defined(O_CLOEXEC) && defined(F_GETFD)
279 int flags = fcntl(fd, F_GETFD);
280
281 if (flags == -1)
282 rb_bug("rb_fix_detect_o_cloexec: fcntl(%d, F_GETFD) failed: %s", fd, strerror(errno));
283
284 if (flags & FD_CLOEXEC)
285 return 1;
286#endif /* fall through if O_CLOEXEC does not work: */
288 return 0;
289}
290
291int
292rb_cloexec_open(const char *pathname, int flags, mode_t mode)
293{
294 int ret;
295 static int o_cloexec_state = -1; /* <0: unknown, 0: ignored, >0: working */
296
297#ifdef O_CLOEXEC
298 /* O_CLOEXEC is available since Linux 2.6.23. Linux 2.6.18 silently ignore it. */
299 flags |= O_CLOEXEC;
300#elif defined O_NOINHERIT
301 flags |= O_NOINHERIT;
302#endif
303 ret = open(pathname, flags, mode);
304 if (ret < 0) return ret;
305 if (ret <= 2 || o_cloexec_state == 0) {
307 }
308 else if (o_cloexec_state > 0) {
309 return ret;
310 }
311 else {
312 o_cloexec_state = rb_fix_detect_o_cloexec(ret);
313 }
314 return ret;
315}
316
317int
319{
320 /* Don't allocate standard file descriptors: 0, 1, 2 */
321 return rb_cloexec_fcntl_dupfd(oldfd, 3);
322}
323
324int
325rb_cloexec_dup2(int oldfd, int newfd)
326{
327 int ret;
328
329 /* When oldfd == newfd, dup2 succeeds but dup3 fails with EINVAL.
330 * rb_cloexec_dup2 succeeds as dup2. */
331 if (oldfd == newfd) {
332 ret = newfd;
333 }
334 else {
335#if defined(HAVE_DUP3) && defined(O_CLOEXEC)
336 static int try_dup3 = 1;
337 if (2 < newfd && try_dup3) {
338 ret = dup3(oldfd, newfd, O_CLOEXEC);
339 if (ret != -1)
340 return ret;
341 /* dup3 is available since Linux 2.6.27, glibc 2.9. */
342 if (errno == ENOSYS) {
343 try_dup3 = 0;
344 ret = dup2(oldfd, newfd);
345 }
346 }
347 else {
348 ret = dup2(oldfd, newfd);
349 }
350#else
351 ret = dup2(oldfd, newfd);
352#endif
353 if (ret < 0) return ret;
354 }
356 return ret;
357}
358
359static int
360rb_fd_set_nonblock(int fd)
361{
362#ifdef _WIN32
363 return rb_w32_set_nonblock(fd);
364#elif defined(F_GETFL)
365 int oflags = fcntl(fd, F_GETFL);
366
367 if (oflags == -1)
368 return -1;
369 if (oflags & O_NONBLOCK)
370 return 0;
371 oflags |= O_NONBLOCK;
372 return fcntl(fd, F_SETFL, oflags);
373#endif
374 return 0;
375}
376
377int
378rb_cloexec_pipe(int fildes[2])
379{
380 int ret;
381
382#if defined(HAVE_PIPE2)
383 static int try_pipe2 = 1;
384 if (try_pipe2) {
386 if (ret != -1)
387 return ret;
388 /* pipe2 is available since Linux 2.6.27, glibc 2.9. */
389 if (errno == ENOSYS) {
390 try_pipe2 = 0;
391 ret = pipe(fildes);
392 }
393 }
394 else {
395 ret = pipe(fildes);
396 }
397#else
398 ret = pipe(fildes);
399#endif
400 if (ret < 0) return ret;
401#ifdef __CYGWIN__
402 if (ret == 0 && fildes[1] == -1) {
403 close(fildes[0]);
404 fildes[0] = -1;
405 errno = ENFILE;
406 return -1;
407 }
408#endif
409 rb_maygvl_fd_fix_cloexec(fildes[0]);
410 rb_maygvl_fd_fix_cloexec(fildes[1]);
412 rb_fd_set_nonblock(fildes[0]);
413 rb_fd_set_nonblock(fildes[1]);
414 }
415 return ret;
416}
417
418int
419rb_cloexec_fcntl_dupfd(int fd, int minfd)
420{
421 int ret;
422
423#if defined(HAVE_FCNTL) && defined(F_DUPFD_CLOEXEC) && defined(F_DUPFD)
424 static int try_dupfd_cloexec = 1;
425 if (try_dupfd_cloexec) {
426 ret = fcntl(fd, F_DUPFD_CLOEXEC, minfd);
427 if (ret != -1) {
428 if (ret <= 2)
430 return ret;
431 }
432 /* F_DUPFD_CLOEXEC is available since Linux 2.6.24. Linux 2.6.18 fails with EINVAL */
433 if (errno == EINVAL) {
434 ret = fcntl(fd, F_DUPFD, minfd);
435 if (ret != -1) {
436 try_dupfd_cloexec = 0;
437 }
438 }
439 }
440 else {
441 ret = fcntl(fd, F_DUPFD, minfd);
442 }
443#elif defined(HAVE_FCNTL) && defined(F_DUPFD)
444 ret = fcntl(fd, F_DUPFD, minfd);
445#elif defined(HAVE_DUP)
446 ret = dup(fd);
447 if (ret >= 0 && ret < minfd) {
448 const int prev_fd = ret;
449 ret = rb_cloexec_fcntl_dupfd(fd, minfd);
450 close(prev_fd);
451 }
452 return ret;
453#else
454# error "dup() or fcntl(F_DUPFD) must be supported."
455#endif
456 if (ret < 0) return ret;
458 return ret;
459}
460
461#define argf_of(obj) (*(struct argf *)DATA_PTR(obj))
462#define ARGF argf_of(argf)
463
464#define GetWriteIO(io) rb_io_get_write_io(io)
465
466#define READ_DATA_PENDING(fptr) ((fptr)->rbuf.len)
467#define READ_DATA_PENDING_COUNT(fptr) ((fptr)->rbuf.len)
468#define READ_DATA_PENDING_PTR(fptr) ((fptr)->rbuf.ptr+(fptr)->rbuf.off)
469#define READ_DATA_BUFFERED(fptr) READ_DATA_PENDING(fptr)
470
471#define READ_CHAR_PENDING(fptr) ((fptr)->cbuf.len)
472#define READ_CHAR_PENDING_COUNT(fptr) ((fptr)->cbuf.len)
473#define READ_CHAR_PENDING_PTR(fptr) ((fptr)->cbuf.ptr+(fptr)->cbuf.off)
474
475#if defined(_WIN32)
476#define WAIT_FD_IN_WIN32(fptr) \
477 (rb_w32_io_cancelable_p((fptr)->fd) ? 0 : rb_thread_wait_fd((fptr)->fd))
478#else
479#define WAIT_FD_IN_WIN32(fptr)
480#endif
481
482#define READ_CHECK(fptr) do {\
483 if (!READ_DATA_PENDING(fptr)) {\
484 WAIT_FD_IN_WIN32(fptr);\
485 rb_io_check_closed(fptr);\
486 }\
487} while(0)
488
489#ifndef S_ISSOCK
490# ifdef _S_ISSOCK
491# define S_ISSOCK(m) _S_ISSOCK(m)
492# else
493# ifdef _S_IFSOCK
494# define S_ISSOCK(m) (((m) & S_IFMT) == _S_IFSOCK)
495# else
496# ifdef S_IFSOCK
497# define S_ISSOCK(m) (((m) & S_IFMT) == S_IFSOCK)
498# endif
499# endif
500# endif
501#endif
502
503static int io_fflush(rb_io_t *);
504static rb_io_t *flush_before_seek(rb_io_t *fptr);
505
506#define NEED_NEWLINE_DECORATOR_ON_READ(fptr) ((fptr)->mode & FMODE_TEXTMODE)
507#define NEED_NEWLINE_DECORATOR_ON_WRITE(fptr) ((fptr)->mode & FMODE_TEXTMODE)
508#if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
509/* Windows */
510# define DEFAULT_TEXTMODE FMODE_TEXTMODE
511# define TEXTMODE_NEWLINE_DECORATOR_ON_WRITE ECONV_CRLF_NEWLINE_DECORATOR
512/*
513 * CRLF newline is set as default newline decorator.
514 * If only CRLF newline conversion is needed, we use binary IO process
515 * with OS's text mode for IO performance improvement.
516 * If encoding conversion is needed or a user sets text mode, we use encoding
517 * conversion IO process and universal newline decorator by default.
518 */
519#define NEED_READCONV(fptr) ((fptr)->encs.enc2 != NULL || (fptr)->encs.ecflags & ~ECONV_CRLF_NEWLINE_DECORATOR)
520#define WRITECONV_MASK ( \
521 (ECONV_DECORATOR_MASK & ~ECONV_CRLF_NEWLINE_DECORATOR)|\
522 ECONV_STATEFUL_DECORATOR_MASK|\
523 0)
524#define NEED_WRITECONV(fptr) ( \
525 ((fptr)->encs.enc != NULL && (fptr)->encs.enc != rb_ascii8bit_encoding()) || \
526 ((fptr)->encs.ecflags & WRITECONV_MASK) || \
527 0)
528#define SET_BINARY_MODE(fptr) setmode((fptr)->fd, O_BINARY)
529
530#define NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr) do {\
531 if (NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {\
532 if (((fptr)->mode & FMODE_READABLE) &&\
533 !((fptr)->encs.ecflags & ECONV_NEWLINE_DECORATOR_MASK)) {\
534 setmode((fptr)->fd, O_BINARY);\
535 }\
536 else {\
537 setmode((fptr)->fd, O_TEXT);\
538 }\
539 }\
540} while(0)
541
542#define SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags) do {\
543 if ((enc2) && ((ecflags) & ECONV_DEFAULT_NEWLINE_DECORATOR)) {\
544 (ecflags) |= ECONV_UNIVERSAL_NEWLINE_DECORATOR;\
545 }\
546} while(0)
547
548/*
549 * IO unread with taking care of removed '\r' in text mode.
550 */
551static void
552io_unread(rb_io_t *fptr)
553{
554 off_t r, pos;
555 ssize_t read_size;
556 long i;
557 long newlines = 0;
558 long extra_max;
559 char *p;
560 char *buf;
561
562 rb_io_check_closed(fptr);
563 if (fptr->rbuf.len == 0 || fptr->mode & FMODE_DUPLEX) {
564 return;
565 }
566
567 errno = 0;
568 if (!rb_w32_fd_is_text(fptr->fd)) {
569 r = lseek(fptr->fd, -fptr->rbuf.len, SEEK_CUR);
570 if (r < 0 && errno) {
571 if (errno == ESPIPE)
572 fptr->mode |= FMODE_DUPLEX;
573 return;
574 }
575
576 fptr->rbuf.off = 0;
577 fptr->rbuf.len = 0;
578 return;
579 }
580
581 pos = lseek(fptr->fd, 0, SEEK_CUR);
582 if (pos < 0 && errno) {
583 if (errno == ESPIPE)
584 fptr->mode |= FMODE_DUPLEX;
585 return;
586 }
587
588 /* add extra offset for removed '\r' in rbuf */
589 extra_max = (long)(pos - fptr->rbuf.len);
590 p = fptr->rbuf.ptr + fptr->rbuf.off;
591
592 /* if the end of rbuf is '\r', rbuf doesn't have '\r' within rbuf.len */
593 if (*(fptr->rbuf.ptr + fptr->rbuf.capa - 1) == '\r') {
594 newlines++;
595 }
596
597 for (i = 0; i < fptr->rbuf.len; i++) {
598 if (*p == '\n') newlines++;
599 if (extra_max == newlines) break;
600 p++;
601 }
602
603 buf = ALLOC_N(char, fptr->rbuf.len + newlines);
604 while (newlines >= 0) {
605 r = lseek(fptr->fd, pos - fptr->rbuf.len - newlines, SEEK_SET);
606 if (newlines == 0) break;
607 if (r < 0) {
608 newlines--;
609 continue;
610 }
611 read_size = _read(fptr->fd, buf, fptr->rbuf.len + newlines);
612 if (read_size < 0) {
613 int e = errno;
614 free(buf);
615 rb_syserr_fail_path(e, fptr->pathv);
616 }
617 if (read_size == fptr->rbuf.len) {
618 lseek(fptr->fd, r, SEEK_SET);
619 break;
620 }
621 else {
622 newlines--;
623 }
624 }
625 free(buf);
626 fptr->rbuf.off = 0;
627 fptr->rbuf.len = 0;
628 return;
629}
630
631/*
632 * We use io_seek to back cursor position when changing mode from text to binary,
633 * but stdin and pipe cannot seek back. Stdin and pipe read should use encoding
634 * conversion for working properly with mode change.
635 *
636 * Return previous translation mode.
637 */
638static inline int
639set_binary_mode_with_seek_cur(rb_io_t *fptr)
640{
641 if (!rb_w32_fd_is_text(fptr->fd)) return O_BINARY;
642
643 if (fptr->rbuf.len == 0 || fptr->mode & FMODE_DUPLEX) {
644 return setmode(fptr->fd, O_BINARY);
645 }
646 flush_before_seek(fptr);
647 return setmode(fptr->fd, O_BINARY);
648}
649#define SET_BINARY_MODE_WITH_SEEK_CUR(fptr) set_binary_mode_with_seek_cur(fptr)
650
651#else
652/* Unix */
653# define DEFAULT_TEXTMODE 0
654#define NEED_READCONV(fptr) ((fptr)->encs.enc2 != NULL || NEED_NEWLINE_DECORATOR_ON_READ(fptr))
655#define NEED_WRITECONV(fptr) ( \
656 ((fptr)->encs.enc != NULL && (fptr)->encs.enc != rb_ascii8bit_encoding()) || \
657 NEED_NEWLINE_DECORATOR_ON_WRITE(fptr) || \
658 ((fptr)->encs.ecflags & (ECONV_DECORATOR_MASK|ECONV_STATEFUL_DECORATOR_MASK)) || \
659 0)
660#define SET_BINARY_MODE(fptr) (void)(fptr)
661#define NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr) (void)(fptr)
662#define SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags) ((void)(enc2), (void)(ecflags))
663#define SET_BINARY_MODE_WITH_SEEK_CUR(fptr) (void)(fptr)
664#endif
665
666#if !defined HAVE_SHUTDOWN && !defined shutdown
667#define shutdown(a,b) 0
668#endif
669
670#if defined(_WIN32)
671#define is_socket(fd, path) rb_w32_is_socket(fd)
672#elif !defined(S_ISSOCK)
673#define is_socket(fd, path) 0
674#else
675static int
676is_socket(int fd, VALUE path)
677{
678 struct stat sbuf;
679 if (fstat(fd, &sbuf) < 0)
681 return S_ISSOCK(sbuf.st_mode);
682}
683#endif
684
685static const char closed_stream[] = "closed stream";
686
687static void
688io_fd_check_closed(int fd)
689{
690 if (fd < 0) {
691 rb_thread_check_ints(); /* check for ruby_error_stream_closed */
692 rb_raise(rb_eIOError, closed_stream);
693 }
694}
695
696void
698{
699 rb_raise(rb_eEOFError, "end of file reached");
700}
701
702VALUE
704{
705 rb_check_frozen(io);
706 return io;
707}
708
709void
711{
712 if (!fptr) {
713 rb_raise(rb_eIOError, "uninitialized stream");
714 }
715}
716
717void
719{
721 io_fd_check_closed(fptr->fd);
722}
723
724static rb_io_t *
725rb_io_get_fptr(VALUE io)
726{
727 rb_io_t *fptr = RFILE(io)->fptr;
729 return fptr;
730}
731
732VALUE
734{
735 return rb_convert_type_with_id(io, T_FILE, "IO", idTo_io);
736}
737
738VALUE
740{
742}
743
744VALUE
746{
747 VALUE write_io;
748 write_io = rb_io_get_fptr(io)->tied_io_for_writing;
749 if (write_io) {
750 return write_io;
751 }
752 return io;
753}
754
755VALUE
757{
758 VALUE write_io;
759 rb_io_t *fptr = rb_io_get_fptr(io);
760 if (!RTEST(w)) {
761 w = 0;
762 }
763 else {
764 GetWriteIO(w);
765 }
766 write_io = fptr->tied_io_for_writing;
767 fptr->tied_io_for_writing = w;
768 return write_io ? write_io : Qnil;
769}
770
771/*
772 * call-seq:
773 * IO.try_convert(obj) -> io or nil
774 *
775 * Try to convert <i>obj</i> into an IO, using to_io method.
776 * Returns converted IO or +nil+ if <i>obj</i> cannot be converted
777 * for any reason.
778 *
779 * IO.try_convert(STDOUT) #=> STDOUT
780 * IO.try_convert("STDOUT") #=> nil
781 *
782 * require 'zlib'
783 * f = open("/tmp/zz.gz") #=> #<File:/tmp/zz.gz>
784 * z = Zlib::GzipReader.open(f) #=> #<Zlib::GzipReader:0x81d8744>
785 * IO.try_convert(z) #=> #<File:/tmp/zz.gz>
786 *
787 */
788static VALUE
789rb_io_s_try_convert(VALUE dummy, VALUE io)
790{
791 return rb_io_check_io(io);
792}
793
794#if !(defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32))
795static void
796io_unread(rb_io_t *fptr)
797{
798 off_t r;
799 rb_io_check_closed(fptr);
800 if (fptr->rbuf.len == 0 || fptr->mode & FMODE_DUPLEX)
801 return;
802 /* xxx: target position may be negative if buffer is filled by ungetc */
803 errno = 0;
804 r = lseek(fptr->fd, -fptr->rbuf.len, SEEK_CUR);
805 if (r < 0 && errno) {
806 if (errno == ESPIPE)
807 fptr->mode |= FMODE_DUPLEX;
808 return;
809 }
810 fptr->rbuf.off = 0;
811 fptr->rbuf.len = 0;
812 return;
813}
814#endif
815
816static rb_encoding *io_input_encoding(rb_io_t *fptr);
817
818static void
819io_ungetbyte(VALUE str, rb_io_t *fptr)
820{
821 long len = RSTRING_LEN(str);
822
823 if (fptr->rbuf.ptr == NULL) {
824 const int min_capa = IO_RBUF_CAPA_FOR(fptr);
825 fptr->rbuf.off = 0;
826 fptr->rbuf.len = 0;
827#if SIZEOF_LONG > SIZEOF_INT
828 if (len > INT_MAX)
829 rb_raise(rb_eIOError, "ungetbyte failed");
830#endif
831 if (len > min_capa)
832 fptr->rbuf.capa = (int)len;
833 else
834 fptr->rbuf.capa = min_capa;
835 fptr->rbuf.ptr = ALLOC_N(char, fptr->rbuf.capa);
836 }
837 if (fptr->rbuf.capa < len + fptr->rbuf.len) {
838 rb_raise(rb_eIOError, "ungetbyte failed");
839 }
840 if (fptr->rbuf.off < len) {
841 MEMMOVE(fptr->rbuf.ptr+fptr->rbuf.capa-fptr->rbuf.len,
842 fptr->rbuf.ptr+fptr->rbuf.off,
843 char, fptr->rbuf.len);
844 fptr->rbuf.off = fptr->rbuf.capa-fptr->rbuf.len;
845 }
846 fptr->rbuf.off-=(int)len;
847 fptr->rbuf.len+=(int)len;
848 MEMMOVE(fptr->rbuf.ptr+fptr->rbuf.off, RSTRING_PTR(str), char, len);
849}
850
851static rb_io_t *
852flush_before_seek(rb_io_t *fptr)
853{
854 if (io_fflush(fptr) < 0)
855 rb_sys_fail(0);
856 io_unread(fptr);
857 errno = 0;
858 return fptr;
859}
860
861#define io_seek(fptr, ofs, whence) (errno = 0, lseek(flush_before_seek(fptr)->fd, (ofs), (whence)))
862#define io_tell(fptr) lseek(flush_before_seek(fptr)->fd, 0, SEEK_CUR)
863
864#ifndef SEEK_CUR
865# define SEEK_SET 0
866# define SEEK_CUR 1
867# define SEEK_END 2
868#endif
869
870void
872{
873 rb_io_check_closed(fptr);
874 if (!(fptr->mode & FMODE_READABLE)) {
875 rb_raise(rb_eIOError, "not opened for reading");
876 }
877 if (fptr->wbuf.len) {
878 if (io_fflush(fptr) < 0)
879 rb_sys_fail(0);
880 }
881 if (fptr->tied_io_for_writing) {
882 rb_io_t *wfptr;
883 GetOpenFile(fptr->tied_io_for_writing, wfptr);
884 if (io_fflush(wfptr) < 0)
885 rb_sys_fail(0);
886 }
887}
888
889void
891{
893 if (READ_CHAR_PENDING(fptr)) {
894 rb_raise(rb_eIOError, "byte oriented read for character buffered IO");
895 }
896}
897
898void
900{
902}
903
904static rb_encoding*
905io_read_encoding(rb_io_t *fptr)
906{
907 if (fptr->encs.enc) {
908 return fptr->encs.enc;
909 }
911}
912
913static rb_encoding*
914io_input_encoding(rb_io_t *fptr)
915{
916 if (fptr->encs.enc2) {
917 return fptr->encs.enc2;
918 }
919 return io_read_encoding(fptr);
920}
921
922void
924{
925 rb_io_check_closed(fptr);
926 if (!(fptr->mode & FMODE_WRITABLE)) {
927 rb_raise(rb_eIOError, "not opened for writing");
928 }
929 if (fptr->rbuf.len) {
930 io_unread(fptr);
931 }
932}
933
934int
936{
937 /* This function is used for bytes and chars. Confusing. */
938 if (READ_CHAR_PENDING(fptr))
939 return 1; /* should raise? */
940 return READ_DATA_PENDING(fptr);
941}
942
943void
945{
946 if (!READ_DATA_PENDING(fptr)) {
947 rb_thread_wait_fd(fptr->fd);
948 }
949 return;
950}
951
952int
954{
955 if (err == EMFILE || err == ENFILE || err == ENOMEM) {
956 rb_gc();
957 return 1;
958 }
959 return 0;
960}
961
962static int
963ruby_dup(int orig)
964{
965 int fd;
966
967 fd = rb_cloexec_dup(orig);
968 if (fd < 0) {
969 int e = errno;
970 if (rb_gc_for_fd(e)) {
971 fd = rb_cloexec_dup(orig);
972 }
973 if (fd < 0) {
974 rb_syserr_fail(e, 0);
975 }
976 }
978 return fd;
979}
980
981static VALUE
982io_alloc(VALUE klass)
983{
984 NEWOBJ_OF(io, struct RFile, klass, T_FILE);
985
986 io->fptr = 0;
987
988 return (VALUE)io;
989}
990
991#ifndef S_ISREG
992# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
993#endif
994
996 int fd;
998 void *buf;
999 size_t capa;
1000};
1001
1003 int fd;
1004 const void *buf;
1005 size_t capa;
1006};
1007
1008#ifdef HAVE_WRITEV
1009struct io_internal_writev_struct {
1010 int fd;
1011 int iovcnt;
1012 const struct iovec *iov;
1013};
1014#endif
1015
1016static int nogvl_wait_for_single_fd(int fd, short events);
1017static VALUE
1018internal_read_func(void *ptr)
1019{
1020 struct io_internal_read_struct *iis = ptr;
1021 ssize_t r;
1022retry:
1023 r = read(iis->fd, iis->buf, iis->capa);
1024 if (r < 0 && !iis->nonblock) {
1025 int e = errno;
1026 if (e == EAGAIN || e == EWOULDBLOCK) {
1027 if (nogvl_wait_for_single_fd(iis->fd, RB_WAITFD_IN) != -1) {
1028 goto retry;
1029 }
1030 errno = e;
1031 }
1032 }
1033 return r;
1034}
1035
1036#if defined __APPLE__
1037# define do_write_retry(code) do {ret = code;} while (ret == -1 && errno == EPROTOTYPE)
1038#else
1039# define do_write_retry(code) ret = code
1040#endif
1041static VALUE
1042internal_write_func(void *ptr)
1043{
1044 struct io_internal_write_struct *iis = ptr;
1045 ssize_t ret;
1046 do_write_retry(write(iis->fd, iis->buf, iis->capa));
1047 return (VALUE)ret;
1048}
1049
1050static void*
1051internal_write_func2(void *ptr)
1052{
1053 return (void*)internal_write_func(ptr);
1054}
1055
1056#ifdef HAVE_WRITEV
1057static VALUE
1058internal_writev_func(void *ptr)
1059{
1060 struct io_internal_writev_struct *iis = ptr;
1061 ssize_t ret;
1062 do_write_retry(writev(iis->fd, iis->iov, iis->iovcnt));
1063 return (VALUE)ret;
1064}
1065#endif
1066
1067static ssize_t
1068rb_read_internal(int fd, void *buf, size_t count)
1069{
1070 struct io_internal_read_struct iis;
1071
1072 iis.fd = fd;
1073 iis.nonblock = 0;
1074 iis.buf = buf;
1075 iis.capa = count;
1076
1077 return (ssize_t)rb_thread_io_blocking_region(internal_read_func, &iis, fd);
1078}
1079
1080static ssize_t
1081rb_write_internal(int fd, const void *buf, size_t count)
1082{
1083 struct io_internal_write_struct iis;
1084 iis.fd = fd;
1085 iis.buf = buf;
1086 iis.capa = count;
1087
1088 return (ssize_t)rb_thread_io_blocking_region(internal_write_func, &iis, fd);
1089}
1090
1091static ssize_t
1092rb_write_internal2(int fd, const void *buf, size_t count)
1093{
1094 struct io_internal_write_struct iis;
1095 iis.fd = fd;
1096 iis.buf = buf;
1097 iis.capa = count;
1098
1099 return (ssize_t)rb_thread_call_without_gvl2(internal_write_func2, &iis,
1100 RUBY_UBF_IO, NULL);
1101}
1102
1103#ifdef HAVE_WRITEV
1104static ssize_t
1105rb_writev_internal(int fd, const struct iovec *iov, int iovcnt)
1106{
1107 struct io_internal_writev_struct iis;
1108 iis.fd = fd;
1109 iis.iov = iov;
1110 iis.iovcnt = iovcnt;
1111
1112 return (ssize_t)rb_thread_io_blocking_region(internal_writev_func, &iis, fd);
1113}
1114#endif
1115
1116static VALUE
1117io_flush_buffer_sync(void *arg)
1118{
1119 rb_io_t *fptr = arg;
1120 long l = fptr->wbuf.len;
1121 ssize_t r = write(fptr->fd, fptr->wbuf.ptr+fptr->wbuf.off, (size_t)l);
1122
1123 if (fptr->wbuf.len <= r) {
1124 fptr->wbuf.off = 0;
1125 fptr->wbuf.len = 0;
1126 return 0;
1127 }
1128 if (0 <= r) {
1129 fptr->wbuf.off += (int)r;
1130 fptr->wbuf.len -= (int)r;
1131 errno = EAGAIN;
1132 }
1133 return (VALUE)-1;
1134}
1135
1136static void*
1137io_flush_buffer_sync2(void *arg)
1138{
1139 VALUE result = io_flush_buffer_sync(arg);
1140
1141 /*
1142 * rb_thread_call_without_gvl2 uses 0 as interrupted.
1143 * So, we need to avoid to use 0.
1144 */
1145 return !result ? (void*)1 : (void*)result;
1146}
1147
1148static VALUE
1149io_flush_buffer_async(VALUE arg)
1150{
1151 rb_io_t *fptr = (rb_io_t *)arg;
1152 return rb_thread_io_blocking_region(io_flush_buffer_sync, fptr, fptr->fd);
1153}
1154
1155static VALUE
1156io_flush_buffer_async2(VALUE arg)
1157{
1158 rb_io_t *fptr = (rb_io_t *)arg;
1159 VALUE ret;
1160
1161 ret = (VALUE)rb_thread_call_without_gvl2(io_flush_buffer_sync2, fptr,
1162 RUBY_UBF_IO, NULL);
1163
1164 if (!ret) {
1165 /* pending async interrupt is there. */
1166 errno = EAGAIN;
1167 return -1;
1168 }
1169 else if (ret == 1) {
1170 return 0;
1171 }
1172 return ret;
1173}
1174
1175static inline int
1176io_flush_buffer(rb_io_t *fptr)
1177{
1178 if (fptr->write_lock) {
1179 if (rb_mutex_owned_p(fptr->write_lock))
1180 return (int)io_flush_buffer_async2((VALUE)fptr);
1181 else
1182 return (int)rb_mutex_synchronize(fptr->write_lock, io_flush_buffer_async2, (VALUE)fptr);
1183 }
1184 else {
1185 return (int)io_flush_buffer_async((VALUE)fptr);
1186 }
1187}
1188
1189static int
1190io_fflush(rb_io_t *fptr)
1191{
1192 rb_io_check_closed(fptr);
1193 if (fptr->wbuf.len == 0)
1194 return 0;
1195 while (fptr->wbuf.len > 0 && io_flush_buffer(fptr) != 0) {
1196 if (!rb_io_wait_writable(fptr->fd))
1197 return -1;
1198 rb_io_check_closed(fptr);
1199 }
1200 return 0;
1201}
1202
1203int
1205{
1206 io_fd_check_closed(f);
1207 switch (errno) {
1208 case EINTR:
1209#if defined(ERESTART)
1210 case ERESTART:
1211#endif
1213 return TRUE;
1214
1215 case EAGAIN:
1216#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
1217 case EWOULDBLOCK:
1218#endif
1220 return TRUE;
1221
1222 default:
1223 return FALSE;
1224 }
1225}
1226
1227int
1229{
1230 io_fd_check_closed(f);
1231 switch (errno) {
1232 case EINTR:
1233#if defined(ERESTART)
1234 case ERESTART:
1235#endif
1236 /*
1237 * In old Linux, several special files under /proc and /sys don't handle
1238 * select properly. Thus we need avoid to call if don't use O_NONBLOCK.
1239 * Otherwise, we face nasty hang up. Sigh.
1240 * e.g. http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=31b07093c44a7a442394d44423e21d783f5523b8
1241 * http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=31b07093c44a7a442394d44423e21d783f5523b8
1242 * In EINTR case, we only need to call RUBY_VM_CHECK_INTS_BLOCKING().
1243 * Then rb_thread_check_ints() is enough.
1244 */
1246 return TRUE;
1247
1248 case EAGAIN:
1249#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
1250 case EWOULDBLOCK:
1251#endif
1253 return TRUE;
1254
1255 default:
1256 return FALSE;
1257 }
1258}
1259
1260static void
1261make_writeconv(rb_io_t *fptr)
1262{
1263 if (!fptr->writeconv_initialized) {
1264 const char *senc, *denc;
1265 rb_encoding *enc;
1266 int ecflags;
1267 VALUE ecopts;
1268
1269 fptr->writeconv_initialized = 1;
1270
1271 ecflags = fptr->encs.ecflags & ~ECONV_NEWLINE_DECORATOR_READ_MASK;
1272 ecopts = fptr->encs.ecopts;
1273
1274 if (!fptr->encs.enc || (fptr->encs.enc == rb_ascii8bit_encoding() && !fptr->encs.enc2)) {
1275 /* no encoding conversion */
1276 fptr->writeconv_pre_ecflags = 0;
1277 fptr->writeconv_pre_ecopts = Qnil;
1278 fptr->writeconv = rb_econv_open_opts("", "", ecflags, ecopts);
1279 if (!fptr->writeconv)
1280 rb_exc_raise(rb_econv_open_exc("", "", ecflags));
1282 }
1283 else {
1284 enc = fptr->encs.enc2 ? fptr->encs.enc2 : fptr->encs.enc;
1286 if (!senc && !(fptr->encs.ecflags & ECONV_STATEFUL_DECORATOR_MASK)) {
1287 /* single conversion */
1288 fptr->writeconv_pre_ecflags = ecflags;
1289 fptr->writeconv_pre_ecopts = ecopts;
1290 fptr->writeconv = NULL;
1292 }
1293 else {
1294 /* double conversion */
1295 fptr->writeconv_pre_ecflags = ecflags & ~ECONV_STATEFUL_DECORATOR_MASK;
1296 fptr->writeconv_pre_ecopts = ecopts;
1297 if (senc) {
1298 denc = rb_enc_name(enc);
1299 fptr->writeconv_asciicompat = rb_str_new2(senc);
1300 }
1301 else {
1302 senc = denc = "";
1304 }
1306 ecopts = fptr->encs.ecopts;
1307 fptr->writeconv = rb_econv_open_opts(senc, denc, ecflags, ecopts);
1308 if (!fptr->writeconv)
1309 rb_exc_raise(rb_econv_open_exc(senc, denc, ecflags));
1310 }
1311 }
1312 }
1313}
1314
1315/* writing functions */
1319 const char *ptr;
1321};
1322
1327};
1328
1329#ifdef HAVE_WRITEV
1330static VALUE
1331io_binwrite_string(VALUE arg)
1332{
1333 struct binwrite_arg *p = (struct binwrite_arg *)arg;
1334 rb_io_t *fptr = p->fptr;
1335 long r;
1336
1337 if (fptr->wbuf.len) {
1338 struct iovec iov[2];
1339
1340 iov[0].iov_base = fptr->wbuf.ptr+fptr->wbuf.off;
1341 iov[0].iov_len = fptr->wbuf.len;
1342 iov[1].iov_base = (char *)p->ptr;
1343 iov[1].iov_len = p->length;
1344
1345 r = rb_writev_internal(fptr->fd, iov, 2);
1346
1347 if (r < 0)
1348 return r;
1349
1350 if (fptr->wbuf.len <= r) {
1351 r -= fptr->wbuf.len;
1352 fptr->wbuf.off = 0;
1353 fptr->wbuf.len = 0;
1354 }
1355 else {
1356 fptr->wbuf.off += (int)r;
1357 fptr->wbuf.len -= (int)r;
1358 r = 0L;
1359 }
1360 }
1361 else {
1362 r = rb_write_internal(fptr->fd, p->ptr, p->length);
1363 }
1364
1365 return r;
1366}
1367#else
1368static VALUE
1369io_binwrite_string(VALUE arg)
1370{
1371 struct binwrite_arg *p = (struct binwrite_arg *)arg;
1372 rb_io_t *fptr = p->fptr;
1373 long l, len;
1374
1375 l = len = p->length;
1376
1377 if (fptr->wbuf.len) {
1378 if (fptr->wbuf.len+len <= fptr->wbuf.capa) {
1379 if (fptr->wbuf.capa < fptr->wbuf.off+fptr->wbuf.len+len) {
1380 MEMMOVE(fptr->wbuf.ptr, fptr->wbuf.ptr+fptr->wbuf.off, char, fptr->wbuf.len);
1381 fptr->wbuf.off = 0;
1382 }
1383 MEMMOVE(fptr->wbuf.ptr+fptr->wbuf.off+fptr->wbuf.len, p->ptr, char, len);
1384 fptr->wbuf.len += (int)len;
1385 l = 0;
1386 }
1387 if (io_fflush(fptr) < 0)
1388 return -2L; /* fail in fflush */
1389 if (l == 0)
1390 return len;
1391 }
1392
1395
1396 return rb_write_internal(p->fptr->fd, p->ptr, p->length);
1397}
1398#endif
1399
1400static long
1401io_binwrite(VALUE str, const char *ptr, long len, rb_io_t *fptr, int nosync)
1402{
1403 long n, r, offset = 0;
1404
1405 /* don't write anything if current thread has a pending interrupt. */
1407
1408 if ((n = len) <= 0) return n;
1409 if (fptr->wbuf.ptr == NULL && !(!nosync && (fptr->mode & FMODE_SYNC))) {
1410 fptr->wbuf.off = 0;
1411 fptr->wbuf.len = 0;
1412 fptr->wbuf.capa = IO_WBUF_CAPA_MIN;
1413 fptr->wbuf.ptr = ALLOC_N(char, fptr->wbuf.capa);
1416 }
1417 if ((!nosync && (fptr->mode & (FMODE_SYNC|FMODE_TTY))) ||
1418 (fptr->wbuf.ptr && fptr->wbuf.capa <= fptr->wbuf.len + len)) {
1419 struct binwrite_arg arg;
1420
1421 arg.fptr = fptr;
1422 arg.str = str;
1423 retry:
1424 arg.ptr = ptr + offset;
1425 arg.length = n;
1426 if (fptr->write_lock) {
1427 r = rb_mutex_synchronize(fptr->write_lock, io_binwrite_string, (VALUE)&arg);
1428 }
1429 else {
1430 r = io_binwrite_string((VALUE)&arg);
1431 }
1432 /* xxx: other threads may modify given string. */
1433 if (r == n) return len;
1434 if (0 <= r) {
1435 offset += r;
1436 n -= r;
1437 errno = EAGAIN;
1438 }
1439 if (r == -2L)
1440 return -1L;
1441 if (rb_io_wait_writable(fptr->fd)) {
1443 if (offset < len)
1444 goto retry;
1445 }
1446 return -1L;
1447 }
1448
1449 if (fptr->wbuf.off) {
1450 if (fptr->wbuf.len)
1451 MEMMOVE(fptr->wbuf.ptr, fptr->wbuf.ptr+fptr->wbuf.off, char, fptr->wbuf.len);
1452 fptr->wbuf.off = 0;
1453 }
1454 MEMMOVE(fptr->wbuf.ptr+fptr->wbuf.off+fptr->wbuf.len, ptr+offset, char, len);
1455 fptr->wbuf.len += (int)len;
1456 return len;
1457}
1458
1459# define MODE_BTMODE(a,b,c) ((fmode & FMODE_BINMODE) ? (b) : \
1460 (fmode & FMODE_TEXTMODE) ? (c) : (a))
1461
1462#define MODE_BTXMODE(a, b, c, d, e, f) ((fmode & FMODE_EXCL) ? \
1463 MODE_BTMODE(d, e, f) : \
1464 MODE_BTMODE(a, b, c))
1465
1466static VALUE
1467do_writeconv(VALUE str, rb_io_t *fptr, int *converted)
1468{
1469 if (NEED_WRITECONV(fptr)) {
1470 VALUE common_encoding = Qnil;
1472
1473 make_writeconv(fptr);
1474
1475 if (fptr->writeconv) {
1476#define fmode (fptr->mode)
1478 common_encoding = fptr->writeconv_asciicompat;
1480 rb_raise(rb_eArgError, "ASCII incompatible string written for text mode IO without encoding conversion: %s",
1482 }
1483#undef fmode
1484 }
1485 else {
1486 if (fptr->encs.enc2)
1487 common_encoding = rb_enc_from_encoding(fptr->encs.enc2);
1488 else if (fptr->encs.enc != rb_ascii8bit_encoding())
1489 common_encoding = rb_enc_from_encoding(fptr->encs.enc);
1490 }
1491
1492 if (!NIL_P(common_encoding)) {
1493 str = rb_str_encode(str, common_encoding,
1495 *converted = 1;
1496 }
1497
1498 if (fptr->writeconv) {
1500 *converted = 1;
1501 }
1502 }
1503#if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
1504#define fmode (fptr->mode)
1505 else if (MODE_BTMODE(DEFAULT_TEXTMODE,0,1)) {
1506 if ((fptr->mode & FMODE_READABLE) &&
1508 setmode(fptr->fd, O_BINARY);
1509 }
1510 else {
1511 setmode(fptr->fd, O_TEXT);
1512 }
1514 rb_raise(rb_eArgError, "ASCII incompatible string written for text mode IO without encoding conversion: %s",
1516 }
1517 }
1518#undef fmode
1519#endif
1520 return str;
1521}
1522
1523static long
1524io_fwrite(VALUE str, rb_io_t *fptr, int nosync)
1525{
1526 int converted = 0;
1527 VALUE tmp;
1528 long n, len;
1529 const char *ptr;
1530#ifdef _WIN32
1531 if (fptr->mode & FMODE_TTY) {
1533 if (len > 0) return len;
1534 }
1535#endif
1536 str = do_writeconv(str, fptr, &converted);
1537 if (converted)
1538 OBJ_FREEZE(str);
1539
1541 RSTRING_GETMEM(tmp, ptr, len);
1542 n = io_binwrite(tmp, ptr, len, fptr, nosync);
1544
1545 return n;
1546}
1547
1548ssize_t
1549rb_io_bufwrite(VALUE io, const void *buf, size_t size)
1550{
1551 rb_io_t *fptr;
1552
1553 GetOpenFile(io, fptr);
1555 return (ssize_t)io_binwrite(0, buf, (long)size, fptr, 0);
1556}
1557
1558static VALUE
1559io_write(VALUE io, VALUE str, int nosync)
1560{
1561 rb_io_t *fptr;
1562 long n;
1563 VALUE tmp;
1564
1565 io = GetWriteIO(io);
1567 tmp = rb_io_check_io(io);
1568 if (NIL_P(tmp)) {
1569 /* port is not IO, call write method for it. */
1570 return rb_funcall(io, id_write, 1, str);
1571 }
1572 io = tmp;
1573 if (RSTRING_LEN(str) == 0) return INT2FIX(0);
1574
1575 GetOpenFile(io, fptr);
1577
1578 n = io_fwrite(str, fptr, nosync);
1579 if (n < 0L) rb_sys_fail_path(fptr->pathv);
1580
1581 return LONG2FIX(n);
1582}
1583
1584#ifdef HAVE_WRITEV
1585struct binwritev_arg {
1586 rb_io_t *fptr;
1587 const struct iovec *iov;
1588 int iovcnt;
1589};
1590
1591static VALUE
1592call_writev_internal(VALUE arg)
1593{
1594 struct binwritev_arg *p = (struct binwritev_arg *)arg;
1595 return rb_writev_internal(p->fptr->fd, p->iov, p->iovcnt);
1596}
1597
1598static long
1599io_binwritev(struct iovec *iov, int iovcnt, rb_io_t *fptr)
1600{
1601 int i;
1602 long r, total = 0, written_len = 0;
1603
1604 /* don't write anything if current thread has a pending interrupt. */
1606
1607 if (iovcnt == 0) return 0;
1608 for (i = 1; i < iovcnt; i++) total += iov[i].iov_len;
1609
1610 if (fptr->wbuf.ptr == NULL && !(fptr->mode & FMODE_SYNC)) {
1611 fptr->wbuf.off = 0;
1612 fptr->wbuf.len = 0;
1613 fptr->wbuf.capa = IO_WBUF_CAPA_MIN;
1614 fptr->wbuf.ptr = ALLOC_N(char, fptr->wbuf.capa);
1615 fptr->write_lock = rb_mutex_new();
1617 }
1618
1619 if (fptr->wbuf.ptr && fptr->wbuf.len) {
1620 long offset = fptr->wbuf.off + fptr->wbuf.len;
1621 if (offset + total <= fptr->wbuf.capa) {
1622 for (i = 1; i < iovcnt; i++) {
1623 memcpy(fptr->wbuf.ptr+offset, iov[i].iov_base, iov[i].iov_len);
1624 offset += iov[i].iov_len;
1625 }
1626 fptr->wbuf.len += total;
1627 return total;
1628 }
1629 else {
1630 iov[0].iov_base = fptr->wbuf.ptr + fptr->wbuf.off;
1631 iov[0].iov_len = fptr->wbuf.len;
1632 }
1633 }
1634 else {
1635 iov++;
1636 if (!--iovcnt) return 0;
1637 }
1638
1639 retry:
1640 if (fptr->write_lock) {
1641 struct binwritev_arg arg;
1642 arg.fptr = fptr;
1643 arg.iov = iov;
1644 arg.iovcnt = iovcnt;
1645 r = rb_mutex_synchronize(fptr->write_lock, call_writev_internal, (VALUE)&arg);
1646 }
1647 else {
1648 r = rb_writev_internal(fptr->fd, iov, iovcnt);
1649 }
1650
1651 if (r >= 0) {
1652 written_len += r;
1653 if (fptr->wbuf.ptr && fptr->wbuf.len) {
1654 if (written_len < fptr->wbuf.len) {
1655 fptr->wbuf.off += r;
1656 fptr->wbuf.len -= r;
1657 }
1658 else {
1659 written_len -= fptr->wbuf.len;
1660 fptr->wbuf.off = 0;
1661 fptr->wbuf.len = 0;
1662 }
1663 }
1664 if (written_len == total) return total;
1665
1666 while (r >= (ssize_t)iov->iov_len) {
1667 /* iovcnt > 0 */
1668 r -= iov->iov_len;
1669 iov->iov_len = 0;
1670 iov++;
1671 if (!--iovcnt) return total;
1672 /* defensive check: written_len should == total */
1673 }
1674 iov->iov_base = (char *)iov->iov_base + r;
1675 iov->iov_len -= r;
1676
1677 errno = EAGAIN;
1678 }
1679 if (rb_io_wait_writable(fptr->fd)) {
1680 rb_io_check_closed(fptr);
1681 goto retry;
1682 }
1683
1684 return -1L;
1685}
1686
1687static long
1688io_fwritev(int argc, VALUE *argv, rb_io_t *fptr)
1689{
1690 int i, converted, iovcnt = argc + 1;
1691 long n;
1692 VALUE v1, v2, str, tmp, *tmp_array;
1693 struct iovec *iov;
1694
1695 iov = ALLOCV_N(struct iovec, v1, iovcnt);
1696 tmp_array = ALLOCV_N(VALUE, v2, argc);
1697
1698 for (i = 0; i < argc; i++) {
1700 converted = 0;
1701 str = do_writeconv(str, fptr, &converted);
1702 if (converted)
1703 OBJ_FREEZE(str);
1704
1706 tmp_array[i] = tmp;
1707 /* iov[0] is reserved for buffer of fptr */
1708 iov[i+1].iov_base = RSTRING_PTR(tmp);
1709 iov[i+1].iov_len = RSTRING_LEN(tmp);
1710 }
1711
1712 n = io_binwritev(iov, iovcnt, fptr);
1713 if (v1) ALLOCV_END(v1);
1714
1715 for (i = 0; i < argc; i++) {
1716 rb_str_tmp_frozen_release(argv[i], tmp_array[i]);
1717 }
1718
1719 if (v2) ALLOCV_END(v2);
1720
1721 return n;
1722}
1723
1724static int
1725iovcnt_ok(int iovcnt)
1726{
1727#ifdef IOV_MAX
1728 return iovcnt < IOV_MAX;
1729#else /* GNU/Hurd has writev, but no IOV_MAX */
1730 return 1;
1731#endif
1732}
1733#endif /* HAVE_WRITEV */
1734
1735static VALUE
1736io_writev(int argc, VALUE *argv, VALUE io)
1737{
1738 rb_io_t *fptr;
1739 long n;
1740 VALUE tmp, total = INT2FIX(0);
1741 int i, cnt = 1;
1742
1743 io = GetWriteIO(io);
1744 tmp = rb_io_check_io(io);
1745 if (NIL_P(tmp)) {
1746 /* port is not IO, call write method for it. */
1747 return rb_funcallv(io, id_write, argc, argv);
1748 }
1749 io = tmp;
1750
1751 GetOpenFile(io, fptr);
1753
1754 for (i = 0; i < argc; i += cnt) {
1755#ifdef HAVE_WRITEV
1756 if ((fptr->mode & (FMODE_SYNC|FMODE_TTY)) && iovcnt_ok(cnt = argc - i)) {
1757 n = io_fwritev(cnt, &argv[i], fptr);
1758 }
1759 else
1760#endif
1761 {
1762 cnt = 1;
1763 /* sync at last item */
1764 n = io_fwrite(rb_obj_as_string(argv[i]), fptr, (i < argc-1));
1765 }
1766 if (n < 0L) rb_sys_fail_path(fptr->pathv);
1767 total = rb_fix_plus(LONG2FIX(n), total);
1768 }
1769
1770 return total;
1771}
1772
1773/*
1774 * call-seq:
1775 * ios.write(string, ...) -> integer
1776 *
1777 * Writes the given strings to <em>ios</em>. The stream must be opened
1778 * for writing. Arguments that are not a string will be converted
1779 * to a string using <code>to_s</code>. Returns the number of bytes
1780 * written in total.
1781 *
1782 * count = $stdout.write("This is", " a test\n")
1783 * puts "That was #{count} bytes of data"
1784 *
1785 * <em>produces:</em>
1786 *
1787 * This is a test
1788 * That was 15 bytes of data
1789 */
1790
1791static VALUE
1792io_write_m(int argc, VALUE *argv, VALUE io)
1793{
1794 if (argc != 1) {
1795 return io_writev(argc, argv, io);
1796 }
1797 else {
1798 VALUE str = argv[0];
1799 return io_write(io, str, 0);
1800 }
1801}
1802
1803VALUE
1805{
1806 return rb_funcallv(io, id_write, 1, &str);
1807}
1808
1809static VALUE
1810rb_io_writev(VALUE io, int argc, VALUE *argv)
1811{
1812 if (argc > 1 && rb_obj_method_arity(io, id_write) == 1) {
1813 if (io != rb_stderr && RTEST(ruby_verbose)) {
1814 VALUE klass = CLASS_OF(io);
1815 char sep = FL_TEST(klass, FL_SINGLETON) ? (klass = io, '.') : '#';
1816 rb_warning("%+"PRIsVALUE"%c""write is outdated interface"
1817 " which accepts just one argument",
1818 klass, sep);
1819 }
1820 do rb_io_write(io, *argv++); while (--argc);
1821 return argv[0]; /* unused right now */
1822 }
1823 return rb_funcallv(io, id_write, argc, argv);
1824}
1825
1826/*
1827 * call-seq:
1828 * ios << obj -> ios
1829 *
1830 * String Output---Writes <i>obj</i> to <em>ios</em>.
1831 * <i>obj</i> will be converted to a string using
1832 * <code>to_s</code>.
1833 *
1834 * $stdout << "Hello " << "world!\n"
1835 *
1836 * <em>produces:</em>
1837 *
1838 * Hello world!
1839 */
1840
1841
1842VALUE
1844{
1845 rb_io_write(io, str);
1846 return io;
1847}
1848
1849#ifdef HAVE_FSYNC
1850static VALUE
1851nogvl_fsync(void *ptr)
1852{
1853 rb_io_t *fptr = ptr;
1854
1855#ifdef _WIN32
1856 if (GetFileType((HANDLE)rb_w32_get_osfhandle(fptr->fd)) != FILE_TYPE_DISK)
1857 return 0;
1858#endif
1859 return (VALUE)fsync(fptr->fd);
1860}
1861#endif
1862
1863VALUE
1865{
1866 rb_io_t *fptr;
1867
1868 if (!RB_TYPE_P(io, T_FILE)) {
1869 return rb_funcall(io, id_flush, 0);
1870 }
1871
1872 io = GetWriteIO(io);
1873 GetOpenFile(io, fptr);
1874
1875 if (fptr->mode & FMODE_WRITABLE) {
1876 if (io_fflush(fptr) < 0)
1877 rb_sys_fail(0);
1878 }
1879 if (fptr->mode & FMODE_READABLE) {
1880 io_unread(fptr);
1881 }
1882
1883 return io;
1884}
1885
1886/*
1887 * call-seq:
1888 * ios.flush -> ios
1889 *
1890 * Flushes any buffered data within <em>ios</em> to the underlying
1891 * operating system (note that this is Ruby internal buffering only;
1892 * the OS may buffer the data as well).
1893 *
1894 * $stdout.print "no newline"
1895 * $stdout.flush
1896 *
1897 * <em>produces:</em>
1898 *
1899 * no newline
1900 */
1901
1902VALUE
1904{
1905 return rb_io_flush_raw(io, 1);
1906}
1907
1908/*
1909 * call-seq:
1910 * ios.pos -> integer
1911 * ios.tell -> integer
1912 *
1913 * Returns the current offset (in bytes) of <em>ios</em>.
1914 *
1915 * f = File.new("testfile")
1916 * f.pos #=> 0
1917 * f.gets #=> "This is line one\n"
1918 * f.pos #=> 17
1919 */
1920
1921static VALUE
1922rb_io_tell(VALUE io)
1923{
1924 rb_io_t *fptr;
1925 off_t pos;
1926
1927 GetOpenFile(io, fptr);
1928 pos = io_tell(fptr);
1929 if (pos < 0 && errno) rb_sys_fail_path(fptr->pathv);
1930 pos -= fptr->rbuf.len;
1931 return OFFT2NUM(pos);
1932}
1933
1934static VALUE
1935rb_io_seek(VALUE io, VALUE offset, int whence)
1936{
1937 rb_io_t *fptr;
1938 off_t pos;
1939
1940 pos = NUM2OFFT(offset);
1941 GetOpenFile(io, fptr);
1942 pos = io_seek(fptr, pos, whence);
1943 if (pos < 0 && errno) rb_sys_fail_path(fptr->pathv);
1944
1945 return INT2FIX(0);
1946}
1947
1948static int
1949interpret_seek_whence(VALUE vwhence)
1950{
1951 if (vwhence == sym_SET)
1952 return SEEK_SET;
1953 if (vwhence == sym_CUR)
1954 return SEEK_CUR;
1955 if (vwhence == sym_END)
1956 return SEEK_END;
1957#ifdef SEEK_DATA
1958 if (vwhence == sym_DATA)
1959 return SEEK_DATA;
1960#endif
1961#ifdef SEEK_HOLE
1962 if (vwhence == sym_HOLE)
1963 return SEEK_HOLE;
1964#endif
1965 return NUM2INT(vwhence);
1966}
1967
1968/*
1969 * call-seq:
1970 * ios.seek(amount, whence=IO::SEEK_SET) -> 0
1971 *
1972 * Seeks to a given offset <i>anInteger</i> in the stream according to
1973 * the value of <i>whence</i>:
1974 *
1975 * :CUR or IO::SEEK_CUR | Seeks to _amount_ plus current position
1976 * ----------------------+--------------------------------------------------
1977 * :END or IO::SEEK_END | Seeks to _amount_ plus end of stream (you
1978 * | probably want a negative value for _amount_)
1979 * ----------------------+--------------------------------------------------
1980 * :SET or IO::SEEK_SET | Seeks to the absolute location given by _amount_
1981 *
1982 * Example:
1983 *
1984 * f = File.new("testfile")
1985 * f.seek(-13, IO::SEEK_END) #=> 0
1986 * f.readline #=> "And so on...\n"
1987 */
1988
1989static VALUE
1990rb_io_seek_m(int argc, VALUE *argv, VALUE io)
1991{
1992 VALUE offset, ptrname;
1993 int whence = SEEK_SET;
1994
1995 if (rb_scan_args(argc, argv, "11", &offset, &ptrname) == 2) {
1996 whence = interpret_seek_whence(ptrname);
1997 }
1998
1999 return rb_io_seek(io, offset, whence);
2000}
2001
2002/*
2003 * call-seq:
2004 * ios.pos = integer -> integer
2005 *
2006 * Seeks to the given position (in bytes) in <em>ios</em>.
2007 * It is not guaranteed that seeking to the right position when <em>ios</em>
2008 * is textmode.
2009 *
2010 * f = File.new("testfile")
2011 * f.pos = 17
2012 * f.gets #=> "This is line two\n"
2013 */
2014
2015static VALUE
2016rb_io_set_pos(VALUE io, VALUE offset)
2017{
2018 rb_io_t *fptr;
2019 off_t pos;
2020
2021 pos = NUM2OFFT(offset);
2022 GetOpenFile(io, fptr);
2023 pos = io_seek(fptr, pos, SEEK_SET);
2024 if (pos < 0 && errno) rb_sys_fail_path(fptr->pathv);
2025
2026 return OFFT2NUM(pos);
2027}
2028
2029static void clear_readconv(rb_io_t *fptr);
2030
2031/*
2032 * call-seq:
2033 * ios.rewind -> 0
2034 *
2035 * Positions <em>ios</em> to the beginning of input, resetting
2036 * #lineno to zero.
2037 *
2038 * f = File.new("testfile")
2039 * f.readline #=> "This is line one\n"
2040 * f.rewind #=> 0
2041 * f.lineno #=> 0
2042 * f.readline #=> "This is line one\n"
2043 *
2044 * Note that it cannot be used with streams such as pipes, ttys, and sockets.
2045 */
2046
2047static VALUE
2048rb_io_rewind(VALUE io)
2049{
2050 rb_io_t *fptr;
2051
2052 GetOpenFile(io, fptr);
2053 if (io_seek(fptr, 0L, 0) < 0 && errno) rb_sys_fail_path(fptr->pathv);
2054 if (io == ARGF.current_file) {
2055 ARGF.lineno -= fptr->lineno;
2056 }
2057 fptr->lineno = 0;
2058 if (fptr->readconv) {
2059 clear_readconv(fptr);
2060 }
2061
2062 return INT2FIX(0);
2063}
2064
2065static int
2066fptr_wait_readable(rb_io_t *fptr)
2067{
2068 int ret = rb_io_wait_readable(fptr->fd);
2069
2070 if (ret)
2071 rb_io_check_closed(fptr);
2072 return ret;
2073}
2074
2075static int
2076io_fillbuf(rb_io_t *fptr)
2077{
2078 ssize_t r;
2079
2080 if (fptr->rbuf.ptr == NULL) {
2081 fptr->rbuf.off = 0;
2082 fptr->rbuf.len = 0;
2083 fptr->rbuf.capa = IO_RBUF_CAPA_FOR(fptr);
2084 fptr->rbuf.ptr = ALLOC_N(char, fptr->rbuf.capa);
2085#ifdef _WIN32
2086 fptr->rbuf.capa--;
2087#endif
2088 }
2089 if (fptr->rbuf.len == 0) {
2090 retry:
2091 {
2092 r = rb_read_internal(fptr->fd, fptr->rbuf.ptr, fptr->rbuf.capa);
2093 }
2094 if (r < 0) {
2095 if (fptr_wait_readable(fptr))
2096 goto retry;
2097 {
2098 int e = errno;
2099 VALUE path = rb_sprintf("fd:%d ", fptr->fd);
2100 if (!NIL_P(fptr->pathv)) {
2101 rb_str_append(path, fptr->pathv);
2102 }
2104 }
2105 }
2106 if (r > 0) rb_io_check_closed(fptr);
2107 fptr->rbuf.off = 0;
2108 fptr->rbuf.len = (int)r; /* r should be <= rbuf_capa */
2109 if (r == 0)
2110 return -1; /* EOF */
2111 }
2112 return 0;
2113}
2114
2115/*
2116 * call-seq:
2117 * ios.eof -> true or false
2118 * ios.eof? -> true or false
2119 *
2120 * Returns true if <em>ios</em> is at end of file that means
2121 * there are no more data to read.
2122 * The stream must be opened for reading or an IOError will be
2123 * raised.
2124 *
2125 * f = File.new("testfile")
2126 * dummy = f.readlines
2127 * f.eof #=> true
2128 *
2129 * If <em>ios</em> is a stream such as pipe or socket, IO#eof?
2130 * blocks until the other end sends some data or closes it.
2131 *
2132 * r, w = IO.pipe
2133 * Thread.new { sleep 1; w.close }
2134 * r.eof? #=> true after 1 second blocking
2135 *
2136 * r, w = IO.pipe
2137 * Thread.new { sleep 1; w.puts "a" }
2138 * r.eof? #=> false after 1 second blocking
2139 *
2140 * r, w = IO.pipe
2141 * r.eof? # blocks forever
2142 *
2143 * Note that IO#eof? reads data to the input byte buffer. So
2144 * IO#sysread may not behave as you intend with IO#eof?, unless you
2145 * call IO#rewind first (which is not available for some streams).
2146 */
2147
2148VALUE
2150{
2151 rb_io_t *fptr;
2152
2153 GetOpenFile(io, fptr);
2155
2156 if (READ_CHAR_PENDING(fptr)) return Qfalse;
2157 if (READ_DATA_PENDING(fptr)) return Qfalse;
2158 READ_CHECK(fptr);
2159#if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
2160 if (!NEED_READCONV(fptr) && NEED_NEWLINE_DECORATOR_ON_READ(fptr)) {
2161 return eof(fptr->fd) ? Qtrue : Qfalse;
2162 }
2163#endif
2164 if (io_fillbuf(fptr) < 0) {
2165 return Qtrue;
2166 }
2167 return Qfalse;
2168}
2169
2170/*
2171 * call-seq:
2172 * ios.sync -> true or false
2173 *
2174 * Returns the current ``sync mode'' of <em>ios</em>. When sync mode is
2175 * true, all output is immediately flushed to the underlying operating
2176 * system and is not buffered by Ruby internally. See also
2177 * IO#fsync.
2178 *
2179 * f = File.new("testfile")
2180 * f.sync #=> false
2181 */
2182
2183static VALUE
2184rb_io_sync(VALUE io)
2185{
2186 rb_io_t *fptr;
2187
2188 io = GetWriteIO(io);
2189 GetOpenFile(io, fptr);
2190 return (fptr->mode & FMODE_SYNC) ? Qtrue : Qfalse;
2191}
2192
2193#ifdef HAVE_FSYNC
2194
2195/*
2196 * call-seq:
2197 * ios.sync = boolean -> boolean
2198 *
2199 * Sets the ``sync mode'' to <code>true</code> or <code>false</code>.
2200 * When sync mode is true, all output is immediately flushed to the
2201 * underlying operating system and is not buffered internally. Returns
2202 * the new state. See also IO#fsync.
2203 *
2204 * f = File.new("testfile")
2205 * f.sync = true
2206 */
2207
2208static VALUE
2209rb_io_set_sync(VALUE io, VALUE sync)
2210{
2211 rb_io_t *fptr;
2212
2213 io = GetWriteIO(io);
2214 GetOpenFile(io, fptr);
2215 if (RTEST(sync)) {
2216 fptr->mode |= FMODE_SYNC;
2217 }
2218 else {
2219 fptr->mode &= ~FMODE_SYNC;
2220 }
2221 return sync;
2222}
2223
2224/*
2225 * call-seq:
2226 * ios.fsync -> 0 or nil
2227 *
2228 * Immediately writes all buffered data in <em>ios</em> to disk.
2229 * Note that #fsync differs from using IO#sync=. The latter ensures
2230 * that data is flushed from Ruby's buffers, but does not guarantee
2231 * that the underlying operating system actually writes it to disk.
2232 *
2233 * NotImplementedError is raised
2234 * if the underlying operating system does not support <em>fsync(2)</em>.
2235 */
2236
2237static VALUE
2239{
2240 rb_io_t *fptr;
2241
2242 io = GetWriteIO(io);
2243 GetOpenFile(io, fptr);
2244
2245 if (io_fflush(fptr) < 0)
2246 rb_sys_fail(0);
2247 if ((int)rb_thread_io_blocking_region(nogvl_fsync, fptr, fptr->fd) < 0)
2248 rb_sys_fail_path(fptr->pathv);
2249 return INT2FIX(0);
2250}
2251#else
2252# define rb_io_fsync rb_f_notimplement
2253# define rb_io_sync rb_f_notimplement
2254static VALUE
2255rb_io_set_sync(VALUE io, VALUE sync)
2256{
2259}
2260#endif
2261
2262#ifdef HAVE_FDATASYNC
2263static VALUE
2264nogvl_fdatasync(void *ptr)
2265{
2266 rb_io_t *fptr = ptr;
2267
2268#ifdef _WIN32
2269 if (GetFileType((HANDLE)rb_w32_get_osfhandle(fptr->fd)) != FILE_TYPE_DISK)
2270 return 0;
2271#endif
2272 return (VALUE)fdatasync(fptr->fd);
2273}
2274
2275/*
2276 * call-seq:
2277 * ios.fdatasync -> 0 or nil
2278 *
2279 * Immediately writes all buffered data in <em>ios</em> to disk.
2280 *
2281 * If the underlying operating system does not support <em>fdatasync(2)</em>,
2282 * IO#fsync is called instead (which might raise a
2283 * NotImplementedError).
2284 */
2285
2286static VALUE
2288{
2289 rb_io_t *fptr;
2290
2291 io = GetWriteIO(io);
2292 GetOpenFile(io, fptr);
2293
2294 if (io_fflush(fptr) < 0)
2295 rb_sys_fail(0);
2296
2297 if ((int)rb_thread_io_blocking_region(nogvl_fdatasync, fptr, fptr->fd) == 0)
2298 return INT2FIX(0);
2299
2300 /* fall back */
2301 return rb_io_fsync(io);
2302}
2303#else
2304#define rb_io_fdatasync rb_io_fsync
2305#endif
2306
2307/*
2308 * call-seq:
2309 * ios.fileno -> integer
2310 * ios.to_i -> integer
2311 *
2312 * Returns an integer representing the numeric file descriptor for
2313 * <em>ios</em>.
2314 *
2315 * $stdin.fileno #=> 0
2316 * $stdout.fileno #=> 1
2317 */
2318
2319static VALUE
2320rb_io_fileno(VALUE io)
2321{
2322 rb_io_t *fptr = RFILE(io)->fptr;
2323 int fd;
2324
2325 rb_io_check_closed(fptr);
2326 fd = fptr->fd;
2327 return INT2FIX(fd);
2328}
2329
2330
2331/*
2332 * call-seq:
2333 * ios.pid -> integer
2334 *
2335 * Returns the process ID of a child process associated with
2336 * <em>ios</em>. This will be set by IO.popen.
2337 *
2338 * pipe = IO.popen("-")
2339 * if pipe
2340 * $stderr.puts "In parent, child pid is #{pipe.pid}"
2341 * else
2342 * $stderr.puts "In child, pid is #{$$}"
2343 * end
2344 *
2345 * <em>produces:</em>
2346 *
2347 * In child, pid is 26209
2348 * In parent, child pid is 26209
2349 */
2350
2351static VALUE
2352rb_io_pid(VALUE io)
2353{
2354 rb_io_t *fptr;
2355
2356 GetOpenFile(io, fptr);
2357 if (!fptr->pid)
2358 return Qnil;
2359 return PIDT2NUM(fptr->pid);
2360}
2361
2362
2363/*
2364 * call-seq:
2365 * ios.inspect -> string
2366 *
2367 * Return a string describing this IO object.
2368 */
2369
2370static VALUE
2371rb_io_inspect(VALUE obj)
2372{
2373 rb_io_t *fptr;
2374 VALUE result;
2375 static const char closed[] = " (closed)";
2376
2377 fptr = RFILE(obj)->fptr;
2378 if (!fptr) return rb_any_to_s(obj);
2379 result = rb_str_new_cstr("#<");
2381 rb_str_cat2(result, ":");
2382 if (NIL_P(fptr->pathv)) {
2383 if (fptr->fd < 0) {
2384 rb_str_cat(result, closed+1, strlen(closed)-1);
2385 }
2386 else {
2387 rb_str_catf(result, "fd %d", fptr->fd);
2388 }
2389 }
2390 else {
2391 rb_str_append(result, fptr->pathv);
2392 if (fptr->fd < 0) {
2393 rb_str_cat(result, closed, strlen(closed));
2394 }
2395 }
2396 return rb_str_cat2(result, ">");
2397}
2398
2399/*
2400 * call-seq:
2401 * ios.to_io -> ios
2402 *
2403 * Returns <em>ios</em>.
2404 */
2405
2406static VALUE
2407rb_io_to_io(VALUE io)
2408{
2409 return io;
2410}
2411
2412/* reading functions */
2413static long
2414read_buffered_data(char *ptr, long len, rb_io_t *fptr)
2415{
2416 int n;
2417
2418 n = READ_DATA_PENDING_COUNT(fptr);
2419 if (n <= 0) return 0;
2420 if (n > len) n = (int)len;
2421 MEMMOVE(ptr, fptr->rbuf.ptr+fptr->rbuf.off, char, n);
2422 fptr->rbuf.off += n;
2423 fptr->rbuf.len -= n;
2424 return n;
2425}
2426
2427static long
2428io_bufread(char *ptr, long len, rb_io_t *fptr)
2429{
2430 long offset = 0;
2431 long n = len;
2432 long c;
2433
2434 if (READ_DATA_PENDING(fptr) == 0) {
2435 while (n > 0) {
2436 again:
2437 c = rb_read_internal(fptr->fd, ptr+offset, n);
2438 if (c == 0) break;
2439 if (c < 0) {
2440 if (fptr_wait_readable(fptr))
2441 goto again;
2442 return -1;
2443 }
2444 offset += c;
2445 if ((n -= c) <= 0) break;
2446 }
2447 return len - n;
2448 }
2449
2450 while (n > 0) {
2451 c = read_buffered_data(ptr+offset, n, fptr);
2452 if (c > 0) {
2453 offset += c;
2454 if ((n -= c) <= 0) break;
2455 }
2456 rb_io_check_closed(fptr);
2457 if (io_fillbuf(fptr) < 0) {
2458 break;
2459 }
2460 }
2461 return len - n;
2462}
2463
2464static int io_setstrbuf(VALUE *str, long len);
2465
2467 char *str_ptr;
2468 long len;
2470};
2471
2472static VALUE
2473bufread_call(VALUE arg)
2474{
2475 struct bufread_arg *p = (struct bufread_arg *)arg;
2476 p->len = io_bufread(p->str_ptr, p->len, p->fptr);
2477 return Qundef;
2478}
2479
2480static long
2481io_fread(VALUE str, long offset, long size, rb_io_t *fptr)
2482{
2483 long len;
2484 struct bufread_arg arg;
2485
2486 io_setstrbuf(&str, offset + size);
2487 arg.str_ptr = RSTRING_PTR(str) + offset;
2488 arg.len = size;
2489 arg.fptr = fptr;
2490 rb_str_locktmp_ensure(str, bufread_call, (VALUE)&arg);
2491 len = arg.len;
2492 if (len < 0) rb_sys_fail_path(fptr->pathv);
2493 return len;
2494}
2495
2496static long
2497remain_size(rb_io_t *fptr)
2498{
2499 struct stat st;
2500 off_t siz = READ_DATA_PENDING_COUNT(fptr);
2501 off_t pos;
2502
2503 if (fstat(fptr->fd, &st) == 0 && S_ISREG(st.st_mode)
2504#if defined(__HAIKU__)
2505 && (st.st_dev > 3)
2506#endif
2507 )
2508 {
2509 if (io_fflush(fptr) < 0)
2510 rb_sys_fail(0);
2511 pos = lseek(fptr->fd, 0, SEEK_CUR);
2512 if (st.st_size >= pos && pos >= 0) {
2513 siz += st.st_size - pos;
2514 if (siz > LONG_MAX) {
2515 rb_raise(rb_eIOError, "file too big for single read");
2516 }
2517 }
2518 }
2519 else {
2520 siz += BUFSIZ;
2521 }
2522 return (long)siz;
2523}
2524
2525static VALUE
2526io_enc_str(VALUE str, rb_io_t *fptr)
2527{
2528 rb_enc_associate(str, io_read_encoding(fptr));
2529 return str;
2530}
2531
2532static void
2533make_readconv(rb_io_t *fptr, int size)
2534{
2535 if (!fptr->readconv) {
2536 int ecflags;
2537 VALUE ecopts;
2538 const char *sname, *dname;
2539 ecflags = fptr->encs.ecflags & ~ECONV_NEWLINE_DECORATOR_WRITE_MASK;
2540 ecopts = fptr->encs.ecopts;
2541 if (fptr->encs.enc2) {
2542 sname = rb_enc_name(fptr->encs.enc2);
2543 dname = rb_enc_name(fptr->encs.enc);
2544 }
2545 else {
2546 sname = dname = "";
2547 }
2548 fptr->readconv = rb_econv_open_opts(sname, dname, ecflags, ecopts);
2549 if (!fptr->readconv)
2550 rb_exc_raise(rb_econv_open_exc(sname, dname, ecflags));
2551 fptr->cbuf.off = 0;
2552 fptr->cbuf.len = 0;
2554 fptr->cbuf.capa = size;
2555 fptr->cbuf.ptr = ALLOC_N(char, fptr->cbuf.capa);
2556 }
2557}
2558
2559#define MORE_CHAR_SUSPENDED Qtrue
2560#define MORE_CHAR_FINISHED Qnil
2561static VALUE
2562fill_cbuf(rb_io_t *fptr, int ec_flags)
2563{
2564 const unsigned char *ss, *sp, *se;
2565 unsigned char *ds, *dp, *de;
2567 int putbackable;
2568 int cbuf_len0;
2569 VALUE exc;
2570
2571 ec_flags |= ECONV_PARTIAL_INPUT;
2572
2573 if (fptr->cbuf.len == fptr->cbuf.capa)
2574 return MORE_CHAR_SUSPENDED; /* cbuf full */
2575 if (fptr->cbuf.len == 0)
2576 fptr->cbuf.off = 0;
2577 else if (fptr->cbuf.off + fptr->cbuf.len == fptr->cbuf.capa) {
2578 memmove(fptr->cbuf.ptr, fptr->cbuf.ptr+fptr->cbuf.off, fptr->cbuf.len);
2579 fptr->cbuf.off = 0;
2580 }
2581
2582 cbuf_len0 = fptr->cbuf.len;
2583
2584 while (1) {
2585 ss = sp = (const unsigned char *)fptr->rbuf.ptr + fptr->rbuf.off;
2586 se = sp + fptr->rbuf.len;
2587 ds = dp = (unsigned char *)fptr->cbuf.ptr + fptr->cbuf.off + fptr->cbuf.len;
2588 de = (unsigned char *)fptr->cbuf.ptr + fptr->cbuf.capa;
2589 res = rb_econv_convert(fptr->readconv, &sp, se, &dp, de, ec_flags);
2590 fptr->rbuf.off += (int)(sp - ss);
2591 fptr->rbuf.len -= (int)(sp - ss);
2592 fptr->cbuf.len += (int)(dp - ds);
2593
2594 putbackable = rb_econv_putbackable(fptr->readconv);
2595 if (putbackable) {
2596 rb_econv_putback(fptr->readconv, (unsigned char *)fptr->rbuf.ptr + fptr->rbuf.off - putbackable, putbackable);
2597 fptr->rbuf.off -= putbackable;
2598 fptr->rbuf.len += putbackable;
2599 }
2600
2602 if (!NIL_P(exc))
2603 return exc;
2604
2605 if (cbuf_len0 != fptr->cbuf.len)
2606 return MORE_CHAR_SUSPENDED;
2607
2608 if (res == econv_finished) {
2609 return MORE_CHAR_FINISHED;
2610 }
2611
2612 if (res == econv_source_buffer_empty) {
2613 if (fptr->rbuf.len == 0) {
2614 READ_CHECK(fptr);
2615 if (io_fillbuf(fptr) < 0) {
2616 if (!fptr->readconv) {
2617 return MORE_CHAR_FINISHED;
2618 }
2619 ds = dp = (unsigned char *)fptr->cbuf.ptr + fptr->cbuf.off + fptr->cbuf.len;
2620 de = (unsigned char *)fptr->cbuf.ptr + fptr->cbuf.capa;
2621 res = rb_econv_convert(fptr->readconv, NULL, NULL, &dp, de, 0);
2622 fptr->cbuf.len += (int)(dp - ds);
2624 break;
2625 }
2626 }
2627 }
2628 }
2629 if (cbuf_len0 != fptr->cbuf.len)
2630 return MORE_CHAR_SUSPENDED;
2631
2632 return MORE_CHAR_FINISHED;
2633}
2634
2635static VALUE
2636more_char(rb_io_t *fptr)
2637{
2638 VALUE v;
2639 v = fill_cbuf(fptr, ECONV_AFTER_OUTPUT);
2641 rb_exc_raise(v);
2642 return v;
2643}
2644
2645static VALUE
2646io_shift_cbuf(rb_io_t *fptr, int len, VALUE *strp)
2647{
2648 VALUE str = Qnil;
2649 if (strp) {
2650 str = *strp;
2651 if (NIL_P(str)) {
2652 *strp = str = rb_str_new(fptr->cbuf.ptr+fptr->cbuf.off, len);
2653 }
2654 else {
2655 rb_str_cat(str, fptr->cbuf.ptr+fptr->cbuf.off, len);
2656 }
2657 rb_enc_associate(str, fptr->encs.enc);
2658 }
2659 fptr->cbuf.off += len;
2660 fptr->cbuf.len -= len;
2661 /* xxx: set coderange */
2662 if (fptr->cbuf.len == 0)
2663 fptr->cbuf.off = 0;
2664 else if (fptr->cbuf.capa/2 < fptr->cbuf.off) {
2665 memmove(fptr->cbuf.ptr, fptr->cbuf.ptr+fptr->cbuf.off, fptr->cbuf.len);
2666 fptr->cbuf.off = 0;
2667 }
2668 return str;
2669}
2670
2671static int
2672io_setstrbuf(VALUE *str, long len)
2673{
2674#ifdef _WIN32
2675 len = (len + 1) & ~1L; /* round up for wide char */
2676#endif
2677 if (NIL_P(*str)) {
2678 *str = rb_str_new(0, len);
2679 return TRUE;
2680 }
2681 else {
2682 VALUE s = StringValue(*str);
2683 long clen = RSTRING_LEN(s);
2684 if (clen >= len) {
2685 rb_str_modify(s);
2686 return FALSE;
2687 }
2688 len -= clen;
2689 }
2691 return FALSE;
2692}
2693
2694#define MAX_REALLOC_GAP 4096
2695static void
2696io_shrink_read_string(VALUE str, long n)
2697{
2700 }
2701}
2702
2703static void
2704io_set_read_length(VALUE str, long n, int shrinkable)
2705{
2706 if (RSTRING_LEN(str) != n) {
2709 if (shrinkable) io_shrink_read_string(str, n);
2710 }
2711}
2712
2713static VALUE
2714read_all(rb_io_t *fptr, long siz, VALUE str)
2715{
2716 long bytes;
2717 long n;
2718 long pos;
2719 rb_encoding *enc;
2720 int cr;
2721 int shrinkable;
2722
2723 if (NEED_READCONV(fptr)) {
2724 int first = !NIL_P(str);
2725 SET_BINARY_MODE(fptr);
2726 shrinkable = io_setstrbuf(&str,0);
2727 make_readconv(fptr, 0);
2728 while (1) {
2729 VALUE v;
2730 if (fptr->cbuf.len) {
2731 if (first) rb_str_set_len(str, first = 0);
2732 io_shift_cbuf(fptr, fptr->cbuf.len, &str);
2733 }
2734 v = fill_cbuf(fptr, 0);
2736 if (fptr->cbuf.len) {
2737 if (first) rb_str_set_len(str, first = 0);
2738 io_shift_cbuf(fptr, fptr->cbuf.len, &str);
2739 }
2740 rb_exc_raise(v);
2741 }
2742 if (v == MORE_CHAR_FINISHED) {
2743 clear_readconv(fptr);
2744 if (first) rb_str_set_len(str, first = 0);
2745 if (shrinkable) io_shrink_read_string(str, RSTRING_LEN(str));
2746 return io_enc_str(str, fptr);
2747 }
2748 }
2749 }
2750
2752 bytes = 0;
2753 pos = 0;
2754
2755 enc = io_read_encoding(fptr);
2756 cr = 0;
2757
2758 if (siz == 0) siz = BUFSIZ;
2759 shrinkable = io_setstrbuf(&str, siz);
2760 for (;;) {
2761 READ_CHECK(fptr);
2762 n = io_fread(str, bytes, siz - bytes, fptr);
2763 if (n == 0 && bytes == 0) {
2764 rb_str_set_len(str, 0);
2765 break;
2766 }
2767 bytes += n;
2768 rb_str_set_len(str, bytes);
2769 if (cr != ENC_CODERANGE_BROKEN)
2770 pos += rb_str_coderange_scan_restartable(RSTRING_PTR(str) + pos, RSTRING_PTR(str) + bytes, enc, &cr);
2771 if (bytes < siz) break;
2772 siz += BUFSIZ;
2774 }
2775 if (shrinkable) io_shrink_read_string(str, RSTRING_LEN(str));
2776 str = io_enc_str(str, fptr);
2778 return str;
2779}
2780
2781void
2783{
2784 if (rb_fd_set_nonblock(fptr->fd) != 0) {
2785 rb_sys_fail_path(fptr->pathv);
2786 }
2787}
2788
2789static VALUE
2790read_internal_call(VALUE arg)
2791{
2792 struct io_internal_read_struct *iis = (struct io_internal_read_struct *)arg;
2793
2794 return rb_thread_io_blocking_region(internal_read_func, iis, iis->fd);
2795}
2796
2797static long
2798read_internal_locktmp(VALUE str, struct io_internal_read_struct *iis)
2799{
2800 return (long)rb_str_locktmp_ensure(str, read_internal_call, (VALUE)iis);
2801}
2802
2803#define no_exception_p(opts) !rb_opts_exception_p((opts), TRUE)
2804
2805static VALUE
2806io_getpartial(int argc, VALUE *argv, VALUE io, int no_exception, int nonblock)
2807{
2808 rb_io_t *fptr;
2809 VALUE length, str;
2810 long n, len;
2811 struct io_internal_read_struct iis;
2812 int shrinkable;
2813
2814 rb_scan_args(argc, argv, "11", &length, &str);
2815
2816 if ((len = NUM2LONG(length)) < 0) {
2817 rb_raise(rb_eArgError, "negative length %ld given", len);
2818 }
2819
2820 shrinkable = io_setstrbuf(&str, len);
2821
2822 GetOpenFile(io, fptr);
2824
2825 if (len == 0) {
2826 io_set_read_length(str, 0, shrinkable);
2827 return str;
2828 }
2829
2830 if (!nonblock)
2831 READ_CHECK(fptr);
2832 n = read_buffered_data(RSTRING_PTR(str), len, fptr);
2833 if (n <= 0) {
2834 again:
2835 if (nonblock) {
2836 rb_io_set_nonblock(fptr);
2837 }
2838 io_setstrbuf(&str, len);
2839 iis.fd = fptr->fd;
2840 iis.nonblock = nonblock;
2841 iis.buf = RSTRING_PTR(str);
2842 iis.capa = len;
2843 n = read_internal_locktmp(str, &iis);
2844 if (n < 0) {
2845 int e = errno;
2846 if (!nonblock && fptr_wait_readable(fptr))
2847 goto again;
2848 if (nonblock && (e == EWOULDBLOCK || e == EAGAIN)) {
2849 if (no_exception)
2850 return sym_wait_readable;
2851 else
2853 e, "read would block");
2854 }
2855 rb_syserr_fail_path(e, fptr->pathv);
2856 }
2857 }
2858 io_set_read_length(str, n, shrinkable);
2859
2860 if (n == 0)
2861 return Qnil;
2862 else
2863 return str;
2864}
2865
2866/*
2867 * call-seq:
2868 * ios.readpartial(maxlen) -> string
2869 * ios.readpartial(maxlen, outbuf) -> outbuf
2870 *
2871 * Reads at most <i>maxlen</i> bytes from the I/O stream.
2872 * It blocks only if <em>ios</em> has no data immediately available.
2873 * It doesn't block if some data available.
2874 *
2875 * If the optional _outbuf_ argument is present,
2876 * it must reference a String, which will receive the data.
2877 * The _outbuf_ will contain only the received data after the method call
2878 * even if it is not empty at the beginning.
2879 *
2880 * It raises EOFError on end of file.
2881 *
2882 * readpartial is designed for streams such as pipe, socket, tty, etc.
2883 * It blocks only when no data immediately available.
2884 * This means that it blocks only when following all conditions hold.
2885 * * the byte buffer in the IO object is empty.
2886 * * the content of the stream is empty.
2887 * * the stream is not reached to EOF.
2888 *
2889 * When readpartial blocks, it waits data or EOF on the stream.
2890 * If some data is reached, readpartial returns with the data.
2891 * If EOF is reached, readpartial raises EOFError.
2892 *
2893 * When readpartial doesn't blocks, it returns or raises immediately.
2894 * If the byte buffer is not empty, it returns the data in the buffer.
2895 * Otherwise if the stream has some content,
2896 * it returns the data in the stream.
2897 * Otherwise if the stream is reached to EOF, it raises EOFError.
2898 *
2899 * r, w = IO.pipe # buffer pipe content
2900 * w << "abc" # "" "abc".
2901 * r.readpartial(4096) #=> "abc" "" ""
2902 * r.readpartial(4096) # blocks because buffer and pipe is empty.
2903 *
2904 * r, w = IO.pipe # buffer pipe content
2905 * w << "abc" # "" "abc"
2906 * w.close # "" "abc" EOF
2907 * r.readpartial(4096) #=> "abc" "" EOF
2908 * r.readpartial(4096) # raises EOFError
2909 *
2910 * r, w = IO.pipe # buffer pipe content
2911 * w << "abc\ndef\n" # "" "abc\ndef\n"
2912 * r.gets #=> "abc\n" "def\n" ""
2913 * w << "ghi\n" # "def\n" "ghi\n"
2914 * r.readpartial(4096) #=> "def\n" "" "ghi\n"
2915 * r.readpartial(4096) #=> "ghi\n" "" ""
2916 *
2917 * Note that readpartial behaves similar to sysread.
2918 * The differences are:
2919 * * If the byte buffer is not empty, read from the byte buffer
2920 * instead of "sysread for buffered IO (IOError)".
2921 * * It doesn't cause Errno::EWOULDBLOCK and Errno::EINTR. When
2922 * readpartial meets EWOULDBLOCK and EINTR by read system call,
2923 * readpartial retry the system call.
2924 *
2925 * The latter means that readpartial is nonblocking-flag insensitive.
2926 * It blocks on the situation IO#sysread causes Errno::EWOULDBLOCK as
2927 * if the fd is blocking mode.
2928 *
2929 */
2930
2931static VALUE
2932io_readpartial(int argc, VALUE *argv, VALUE io)
2933{
2934 VALUE ret;
2935
2936 ret = io_getpartial(argc, argv, io, Qnil, 0);
2937 if (NIL_P(ret))
2938 rb_eof_error();
2939 return ret;
2940}
2941
2942static VALUE
2943io_nonblock_eof(int no_exception)
2944{
2945 if (!no_exception) {
2946 rb_eof_error();
2947 }
2948 return Qnil;
2949}
2950
2951/* :nodoc: */
2952static VALUE
2953io_read_nonblock(rb_execution_context_t *ec, VALUE io, VALUE length, VALUE str, VALUE ex)
2954{
2955 rb_io_t *fptr;
2956 long n, len;
2957 struct io_internal_read_struct iis;
2958 int shrinkable;
2959
2960 if ((len = NUM2LONG(length)) < 0) {
2961 rb_raise(rb_eArgError, "negative length %ld given", len);
2962 }
2963
2964 shrinkable = io_setstrbuf(&str, len);
2965 rb_bool_expected(ex, "exception");
2966
2967 GetOpenFile(io, fptr);
2969
2970 if (len == 0) {
2971 io_set_read_length(str, 0, shrinkable);
2972 return str;
2973 }
2974
2975 n = read_buffered_data(RSTRING_PTR(str), len, fptr);
2976 if (n <= 0) {
2977 rb_io_set_nonblock(fptr);
2978 shrinkable |= io_setstrbuf(&str, len);
2979 iis.fd = fptr->fd;
2980 iis.nonblock = 1;
2981 iis.buf = RSTRING_PTR(str);
2982 iis.capa = len;
2983 n = read_internal_locktmp(str, &iis);
2984 if (n < 0) {
2985 int e = errno;
2986 if ((e == EWOULDBLOCK || e == EAGAIN)) {
2987 if (!ex) return sym_wait_readable;
2989 e, "read would block");
2990 }
2991 rb_syserr_fail_path(e, fptr->pathv);
2992 }
2993 }
2994 io_set_read_length(str, n, shrinkable);
2995
2996 if (n == 0) {
2997 if (!ex) return Qnil;
2998 rb_eof_error();
2999 }
3000
3001 return str;
3002}
3003
3004/* :nodoc: */
3005static VALUE
3006io_write_nonblock(rb_execution_context_t *ec, VALUE io, VALUE str, VALUE ex)
3007{
3008 rb_io_t *fptr;
3009 long n;
3010
3011 if (!RB_TYPE_P(str, T_STRING))
3013 rb_bool_expected(ex, "exception");
3014
3015 io = GetWriteIO(io);
3016 GetOpenFile(io, fptr);
3018
3019 if (io_fflush(fptr) < 0)
3020 rb_sys_fail(0);
3021
3022 rb_io_set_nonblock(fptr);
3023 n = write(fptr->fd, RSTRING_PTR(str), RSTRING_LEN(str));
3025
3026 if (n < 0) {
3027 int e = errno;
3028 if (e == EWOULDBLOCK || e == EAGAIN) {
3029 if (!ex) {
3030 return sym_wait_writable;
3031 }
3032 else {
3033 rb_readwrite_syserr_fail(RB_IO_WAIT_WRITABLE, e, "write would block");
3034 }
3035 }
3036 rb_syserr_fail_path(e, fptr->pathv);
3037 }
3038
3039 return LONG2FIX(n);
3040}
3041
3042/*
3043 * call-seq:
3044 * ios.read([length [, outbuf]]) -> string, outbuf, or nil
3045 *
3046 * Reads _length_ bytes from the I/O stream.
3047 *
3048 * _length_ must be a non-negative integer or +nil+.
3049 *
3050 * If _length_ is a positive integer, +read+ tries to read
3051 * _length_ bytes without any conversion (binary mode).
3052 * It returns +nil+ if an EOF is encountered before anything can be read.
3053 * Fewer than _length_ bytes are returned if an EOF is encountered during
3054 * the read.
3055 * In the case of an integer _length_, the resulting string is always
3056 * in ASCII-8BIT encoding.
3057 *
3058 * If _length_ is omitted or is +nil+, it reads until EOF
3059 * and the encoding conversion is applied, if applicable.
3060 * A string is returned even if EOF is encountered before any data is read.
3061 *
3062 * If _length_ is zero, it returns an empty string (<code>""</code>).
3063 *
3064 * If the optional _outbuf_ argument is present,
3065 * it must reference a String, which will receive the data.
3066 * The _outbuf_ will contain only the received data after the method call
3067 * even if it is not empty at the beginning.
3068 *
3069 * When this method is called at end of file, it returns +nil+
3070 * or <code>""</code>, depending on _length_:
3071 * +read+, <code>read(nil)</code>, and <code>read(0)</code> return
3072 * <code>""</code>,
3073 * <code>read(<i>positive_integer</i>)</code> returns +nil+.
3074 *
3075 * f = File.new("testfile")
3076 * f.read(16) #=> "This is line one"
3077 *
3078 * # read whole file
3079 * open("file") do |f|
3080 * data = f.read # This returns a string even if the file is empty.
3081 * # ...
3082 * end
3083 *
3084 * # iterate over fixed length records
3085 * open("fixed-record-file") do |f|
3086 * while record = f.read(256)
3087 * # ...
3088 * end
3089 * end
3090 *
3091 * # iterate over variable length records,
3092 * # each record is prefixed by its 32-bit length
3093 * open("variable-record-file") do |f|
3094 * while len = f.read(4)
3095 * len = len.unpack("N")[0] # 32-bit length
3096 * record = f.read(len) # This returns a string even if len is 0.
3097 * end
3098 * end
3099 *
3100 * Note that this method behaves like the fread() function in C.
3101 * This means it retries to invoke read(2) system calls to read data
3102 * with the specified length (or until EOF).
3103 * This behavior is preserved even if <i>ios</i> is in non-blocking mode.
3104 * (This method is non-blocking flag insensitive as other methods.)
3105 * If you need the behavior like a single read(2) system call,
3106 * consider #readpartial, #read_nonblock, and #sysread.
3107 */
3108
3109static VALUE
3110io_read(int argc, VALUE *argv, VALUE io)
3111{
3112 rb_io_t *fptr;
3113 long n, len;
3114 VALUE length, str;
3115 int shrinkable;
3116#if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
3117 int previous_mode;
3118#endif
3119
3120 rb_scan_args(argc, argv, "02", &length, &str);
3121
3122 if (NIL_P(length)) {
3123 GetOpenFile(io, fptr);
3125 return read_all(fptr, remain_size(fptr), str);
3126 }
3127 len = NUM2LONG(length);
3128 if (len < 0) {
3129 rb_raise(rb_eArgError, "negative length %ld given", len);
3130 }
3131
3132 shrinkable = io_setstrbuf(&str,len);
3133
3134 GetOpenFile(io, fptr);
3136 if (len == 0) {
3137 io_set_read_length(str, 0, shrinkable);
3138 return str;
3139 }
3140
3141 READ_CHECK(fptr);
3142#if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
3143 previous_mode = set_binary_mode_with_seek_cur(fptr);
3144#endif
3145 n = io_fread(str, 0, len, fptr);
3146 io_set_read_length(str, n, shrinkable);
3147#if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
3148 if (previous_mode == O_TEXT) {
3149 setmode(fptr->fd, O_TEXT);
3150 }
3151#endif
3152 if (n == 0) return Qnil;
3153
3154 return str;
3155}
3156
3157static void
3158rscheck(const char *rsptr, long rslen, VALUE rs)
3159{
3160 if (!rs) return;
3161 if (RSTRING_PTR(rs) != rsptr && RSTRING_LEN(rs) != rslen)
3162 rb_raise(rb_eRuntimeError, "rs modified");
3163}
3164
3165static int
3166appendline(rb_io_t *fptr, int delim, VALUE *strp, long *lp)
3167{
3168 VALUE str = *strp;
3169 long limit = *lp;
3170
3171 if (NEED_READCONV(fptr)) {
3172 SET_BINARY_MODE(fptr);
3173 make_readconv(fptr, 0);
3174 do {
3175 const char *p, *e;
3176 int searchlen = READ_CHAR_PENDING_COUNT(fptr);
3177 if (searchlen) {
3178 p = READ_CHAR_PENDING_PTR(fptr);
3179 if (0 < limit && limit < searchlen)
3180 searchlen = (int)limit;
3181 e = memchr(p, delim, searchlen);
3182 if (e) {
3183 int len = (int)(e-p+1);
3184 if (NIL_P(str))
3185 *strp = str = rb_str_new(p, len);
3186 else
3187 rb_str_buf_cat(str, p, len);
3188 fptr->cbuf.off += len;
3189 fptr->cbuf.len -= len;
3190 limit -= len;
3191 *lp = limit;
3192 return delim;
3193 }
3194
3195 if (NIL_P(str))
3196 *strp = str = rb_str_new(p, searchlen);
3197 else
3198 rb_str_buf_cat(str, p, searchlen);
3199 fptr->cbuf.off += searchlen;
3200 fptr->cbuf.len -= searchlen;
3201 limit -= searchlen;
3202
3203 if (limit == 0) {
3204 *lp = limit;
3205 return (unsigned char)RSTRING_PTR(str)[RSTRING_LEN(str)-1];
3206 }
3207 }
3208 } while (more_char(fptr) != MORE_CHAR_FINISHED);
3209 clear_readconv(fptr);
3210 *lp = limit;
3211 return EOF;
3212 }
3213
3215 do {
3216 long pending = READ_DATA_PENDING_COUNT(fptr);
3217 if (pending > 0) {
3218 const char *p = READ_DATA_PENDING_PTR(fptr);
3219 const char *e;
3220 long last;
3221
3222 if (limit > 0 && pending > limit) pending = limit;
3223 e = memchr(p, delim, pending);
3224 if (e) pending = e - p + 1;
3225 if (!NIL_P(str)) {
3226 last = RSTRING_LEN(str);
3227 rb_str_resize(str, last + pending);
3228 }
3229 else {
3230 last = 0;
3231 *strp = str = rb_str_buf_new(pending);
3232 rb_str_set_len(str, pending);
3233 }
3234 read_buffered_data(RSTRING_PTR(str) + last, pending, fptr); /* must not fail */
3235 limit -= pending;
3236 *lp = limit;
3237 if (e) return delim;
3238 if (limit == 0)
3239 return (unsigned char)RSTRING_PTR(str)[RSTRING_LEN(str)-1];
3240 }
3241 READ_CHECK(fptr);
3242 } while (io_fillbuf(fptr) >= 0);
3243 *lp = limit;
3244 return EOF;
3245}
3246
3247static inline int
3248swallow(rb_io_t *fptr, int term)
3249{
3250 if (NEED_READCONV(fptr)) {
3251 rb_encoding *enc = io_read_encoding(fptr);
3252 int needconv = rb_enc_mbminlen(enc) != 1;
3253 SET_BINARY_MODE(fptr);
3254 make_readconv(fptr, 0);
3255 do {
3256 size_t cnt;
3257 while ((cnt = READ_CHAR_PENDING_COUNT(fptr)) > 0) {
3258 const char *p = READ_CHAR_PENDING_PTR(fptr);
3259 int i;
3260 if (!needconv) {
3261 if (*p != term) return TRUE;
3262 i = (int)cnt;
3263 while (--i && *++p == term);
3264 }
3265 else {
3266 const char *e = p + cnt;
3267 if (rb_enc_ascget(p, e, &i, enc) != term) return TRUE;
3268 while ((p += i) < e && rb_enc_ascget(p, e, &i, enc) == term);
3269 i = (int)(e - p);
3270 }
3271 io_shift_cbuf(fptr, (int)cnt - i, NULL);
3272 }
3273 } while (more_char(fptr) != MORE_CHAR_FINISHED);
3274 return FALSE;
3275 }
3276
3278 do {
3279 size_t cnt;
3280 while ((cnt = READ_DATA_PENDING_COUNT(fptr)) > 0) {
3281 char buf[1024];
3282 const char *p = READ_DATA_PENDING_PTR(fptr);
3283 int i;
3284 if (cnt > sizeof buf) cnt = sizeof buf;
3285 if (*p != term) return TRUE;
3286 i = (int)cnt;
3287 while (--i && *++p == term);
3288 if (!read_buffered_data(buf, cnt - i, fptr)) /* must not fail */
3289 rb_sys_fail_path(fptr->pathv);
3290 }
3291 READ_CHECK(fptr);
3292 } while (io_fillbuf(fptr) == 0);
3293 return FALSE;
3294}
3295
3296static VALUE
3297rb_io_getline_fast(rb_io_t *fptr, rb_encoding *enc, int chomp)
3298{
3299 VALUE str = Qnil;
3300 int len = 0;
3301 long pos = 0;
3302 int cr = 0;
3303
3304 do {
3305 int pending = READ_DATA_PENDING_COUNT(fptr);
3306
3307 if (pending > 0) {
3308 const char *p = READ_DATA_PENDING_PTR(fptr);
3309 const char *e;
3310 int chomplen = 0;
3311
3312 e = memchr(p, '\n', pending);
3313 if (e) {
3314 pending = (int)(e - p + 1);
3315 if (chomp) {
3316 chomplen = (pending > 1 && *(e-1) == '\r') + 1;
3317 }
3318 }
3319 if (NIL_P(str)) {
3320 str = rb_str_new(p, pending - chomplen);
3321 fptr->rbuf.off += pending;
3322 fptr->rbuf.len -= pending;
3323 }
3324 else {
3325 rb_str_resize(str, len + pending - chomplen);
3326 read_buffered_data(RSTRING_PTR(str)+len, pending - chomplen, fptr);
3327 fptr->rbuf.off += chomplen;
3328 fptr->rbuf.len -= chomplen;
3329 if (pending == 1 && chomplen == 1 && len > 0) {
3330 if (RSTRING_PTR(str)[len-1] == '\r') {
3331 rb_str_resize(str, --len);
3332 break;
3333 }
3334 }
3335 }
3336 len += pending - chomplen;
3337 if (cr != ENC_CODERANGE_BROKEN)
3339 if (e) break;
3340 }
3341 READ_CHECK(fptr);
3342 } while (io_fillbuf(fptr) >= 0);
3343 if (NIL_P(str)) return Qnil;
3344
3345 str = io_enc_str(str, fptr);
3347 fptr->lineno++;
3348
3349 return str;
3350}
3351
3352struct getline_arg {
3354 VALUE rs;
3355 long limit;
3356 unsigned int chomp: 1;
3357};
3358
3359static void
3360extract_getline_opts(VALUE opts, struct getline_arg *args)
3361{
3362 int chomp = FALSE;
3363 if (!NIL_P(opts)) {
3364 static ID kwds[1];
3365 VALUE vchomp;
3366 if (!kwds[0]) {
3367 kwds[0] = rb_intern_const("chomp");
3368 }
3369 rb_get_kwargs(opts, kwds, 0, -2, &vchomp);
3370 chomp = (vchomp != Qundef) && RTEST(vchomp);
3371 }
3372 args->chomp = chomp;
3373}
3374
3375static void
3376extract_getline_args(int argc, VALUE *argv, struct getline_arg *args)
3377{
3378 VALUE rs = rb_rs, lim = Qnil;
3379
3380 if (argc == 1) {
3381 VALUE tmp = Qnil;
3382
3383 if (NIL_P(argv[0]) || !NIL_P(tmp = rb_check_string_type(argv[0]))) {
3384 rs = tmp;
3385 }
3386 else {
3387 lim = argv[0];
3388 }
3389 }
3390 else if (2 <= argc) {
3391 rs = argv[0], lim = argv[1];
3392 if (!NIL_P(rs))
3393 StringValue(rs);
3394 }
3395 args->rs = rs;
3396 args->limit = NIL_P(lim) ? -1L : NUM2LONG(lim);
3397}
3398
3399static void
3400check_getline_args(VALUE *rsp, long *limit, VALUE io)
3401{
3402 rb_io_t *fptr;
3403 VALUE rs = *rsp;
3404
3405 if (!NIL_P(rs)) {
3406 rb_encoding *enc_rs, *enc_io;
3407
3408 GetOpenFile(io, fptr);
3409 enc_rs = rb_enc_get(rs);
3410 enc_io = io_read_encoding(fptr);
3411 if (enc_io != enc_rs &&
3413 (RSTRING_LEN(rs) > 0 && !rb_enc_asciicompat(enc_io)))) {
3414 if (rs == rb_default_rs) {
3415 rs = rb_enc_str_new(0, 0, enc_io);
3416 rb_str_buf_cat_ascii(rs, "\n");
3417 *rsp = rs;
3418 }
3419 else {
3420 rb_raise(rb_eArgError, "encoding mismatch: %s IO with %s RS",
3421 rb_enc_name(enc_io),
3422 rb_enc_name(enc_rs));
3423 }
3424 }
3425 }
3426}
3427
3428static void
3429prepare_getline_args(int argc, VALUE *argv, struct getline_arg *args, VALUE io)
3430{
3431 VALUE opts;
3432 argc = rb_scan_args(argc, argv, "02:", NULL, NULL, &opts);
3433 extract_getline_args(argc, argv, args);
3434 extract_getline_opts(opts, args);
3435 check_getline_args(&args->rs, &args->limit, io);
3436}
3437
3438static VALUE
3439rb_io_getline_0(VALUE rs, long limit, int chomp, rb_io_t *fptr)
3440{
3441 VALUE str = Qnil;
3442 int nolimit = 0;
3443 rb_encoding *enc;
3444
3446 if (NIL_P(rs) && limit < 0) {
3447 str = read_all(fptr, 0, Qnil);
3448 if (RSTRING_LEN(str) == 0) return Qnil;
3450 }
3451 else if (limit == 0) {
3452 return rb_enc_str_new(0, 0, io_read_encoding(fptr));
3453 }
3454 else if (rs == rb_default_rs && limit < 0 && !NEED_READCONV(fptr) &&
3455 rb_enc_asciicompat(enc = io_read_encoding(fptr))) {
3457 return rb_io_getline_fast(fptr, enc, chomp);
3458 }
3459 else {
3460 int c, newline = -1;
3461 const char *rsptr = 0;
3462 long rslen = 0;
3463 int rspara = 0;
3464 int extra_limit = 16;
3465 int chomp_cr = chomp;
3466
3467 SET_BINARY_MODE(fptr);
3468 enc = io_read_encoding(fptr);
3469
3470 if (!NIL_P(rs)) {
3471 rslen = RSTRING_LEN(rs);
3472 if (rslen == 0) {
3473 rsptr = "\n\n";
3474 rslen = 2;
3475 rspara = 1;
3476 swallow(fptr, '\n');
3477 rs = 0;
3478 if (!rb_enc_asciicompat(enc)) {
3479 rs = rb_usascii_str_new(rsptr, rslen);
3480 rs = rb_str_encode(rs, rb_enc_from_encoding(enc), 0, Qnil);
3481 OBJ_FREEZE(rs);
3482 rsptr = RSTRING_PTR(rs);
3483 rslen = RSTRING_LEN(rs);
3484 }
3485 }
3486 else {
3487 rsptr = RSTRING_PTR(rs);
3488 }
3489 newline = (unsigned char)rsptr[rslen - 1];
3490 chomp_cr = chomp && rslen == 1 && newline == '\n';
3491 }
3492
3493 /* MS - Optimization */
3494 while ((c = appendline(fptr, newline, &str, &limit)) != EOF) {
3495 const char *s, *p, *pp, *e;
3496
3497 if (c == newline) {
3498 if (RSTRING_LEN(str) < rslen) continue;
3499 s = RSTRING_PTR(str);
3500 e = RSTRING_END(str);
3501 p = e - rslen;
3502 pp = rb_enc_left_char_head(s, p, e, enc);
3503 if (pp != p) continue;
3504 if (!rspara) rscheck(rsptr, rslen, rs);
3505 if (memcmp(p, rsptr, rslen) == 0) {
3506 if (chomp) {
3507 if (chomp_cr && p > s && *(p-1) == '\r') --p;
3508 rb_str_set_len(str, p - s);
3509 }
3510 break;
3511 }
3512 }
3513 if (limit == 0) {
3514 s = RSTRING_PTR(str);
3515 p = RSTRING_END(str);
3516 pp = rb_enc_left_char_head(s, p-1, p, enc);
3517 if (extra_limit &&
3519 /* relax the limit while incomplete character.
3520 * extra_limit limits the relax length */
3521 limit = 1;
3522 extra_limit--;
3523 }
3524 else {
3525 nolimit = 1;
3526 break;
3527 }
3528 }
3529 }
3530
3531 if (rspara && c != EOF)
3532 swallow(fptr, '\n');
3533 if (!NIL_P(str))
3534 str = io_enc_str(str, fptr);
3535 }
3536
3537 if (!NIL_P(str) && !nolimit) {
3538 fptr->lineno++;
3539 }
3540
3541 return str;
3542}
3543
3544static VALUE
3545rb_io_getline_1(VALUE rs, long limit, int chomp, VALUE io)
3546{
3547 rb_io_t *fptr;
3548 int old_lineno, new_lineno;
3549 VALUE str;
3550
3551 GetOpenFile(io, fptr);
3552 old_lineno = fptr->lineno;
3553 str = rb_io_getline_0(rs, limit, chomp, fptr);
3554 if (!NIL_P(str) && (new_lineno = fptr->lineno) != old_lineno) {
3555 if (io == ARGF.current_file) {
3556 ARGF.lineno += new_lineno - old_lineno;
3557 ARGF.last_lineno = ARGF.lineno;
3558 }
3559 else {
3560 ARGF.last_lineno = new_lineno;
3561 }
3562 }
3563
3564 return str;
3565}
3566
3567static VALUE
3568rb_io_getline(int argc, VALUE *argv, VALUE io)
3569{
3570 struct getline_arg args;
3571
3572 prepare_getline_args(argc, argv, &args, io);
3573 return rb_io_getline_1(args.rs, args.limit, args.chomp, io);
3574}
3575
3576VALUE
3578{
3579 return rb_io_getline_1(rb_default_rs, -1, FALSE, io);
3580}
3581
3582VALUE
3584{
3585 rb_io_t *fptr;
3586 GetOpenFile(io, fptr);
3587 return rb_io_getline_0(rb_default_rs, -1, FALSE, fptr);
3588}
3589
3590/*
3591 * call-seq:
3592 * ios.gets(sep=$/ [, getline_args]) -> string or nil
3593 * ios.gets(limit [, getline_args]) -> string or nil
3594 * ios.gets(sep, limit [, getline_args]) -> string or nil
3595 *
3596 * Reads the next ``line'' from the I/O stream; lines are separated by
3597 * <i>sep</i>. A separator of +nil+ reads the entire
3598 * contents, and a zero-length separator reads the input a paragraph at
3599 * a time (two successive newlines in the input separate paragraphs).
3600 * The stream must be opened for reading or an IOError will be raised.
3601 * The line read in will be returned and also assigned to
3602 * <code>$_</code>. Returns +nil+ if called at end of file. If the
3603 * first argument is an integer, or optional second argument is given,
3604 * the returning string would not be longer than the given value in
3605 * bytes.
3606 *
3607 * File.new("testfile").gets #=> "This is line one\n"
3608 * $_ #=> "This is line one\n"
3609 *
3610 * File.new("testfile").gets(4)#=> "This"
3611 *
3612 * If IO contains multibyte characters byte then <code>gets(1)</code>
3613 * returns character entirely:
3614 *
3615 * # Russian characters take 2 bytes
3616 * File.write("testfile", "\u{442 435 441 442}")
3617 * File.open("testfile") {|f|f.gets(1)} #=> "\u0442"
3618 * File.open("testfile") {|f|f.gets(2)} #=> "\u0442"
3619 * File.open("testfile") {|f|f.gets(3)} #=> "\u0442\u0435"
3620 * File.open("testfile") {|f|f.gets(4)} #=> "\u0442\u0435"
3621 */
3622
3623static VALUE
3624rb_io_gets_m(int argc, VALUE *argv, VALUE io)
3625{
3626 VALUE str;
3627
3628 str = rb_io_getline(argc, argv, io);
3630
3631 return str;
3632}
3633
3634/*
3635 * call-seq:
3636 * ios.lineno -> integer
3637 *
3638 * Returns the current line number in <em>ios</em>. The stream must be
3639 * opened for reading. #lineno counts the number of times #gets is called
3640 * rather than the number of newlines encountered. The two values will
3641 * differ if #gets is called with a separator other than newline.
3642 *
3643 * Methods that use <code>$/</code> like #each, #lines and #readline will
3644 * also increment #lineno.
3645 *
3646 * See also the <code>$.</code> variable.
3647 *
3648 * f = File.new("testfile")
3649 * f.lineno #=> 0
3650 * f.gets #=> "This is line one\n"
3651 * f.lineno #=> 1
3652 * f.gets #=> "This is line two\n"
3653 * f.lineno #=> 2
3654 */
3655
3656static VALUE
3657rb_io_lineno(VALUE io)
3658{
3659 rb_io_t *fptr;
3660
3661 GetOpenFile(io, fptr);
3663 return INT2NUM(fptr->lineno);
3664}
3665
3666/*
3667 * call-seq:
3668 * ios.lineno = integer -> integer
3669 *
3670 * Manually sets the current line number to the given value.
3671 * <code>$.</code> is updated only on the next read.
3672 *
3673 * f = File.new("testfile")
3674 * f.gets #=> "This is line one\n"
3675 * $. #=> 1
3676 * f.lineno = 1000
3677 * f.lineno #=> 1000
3678 * $. #=> 1 # lineno of last read
3679 * f.gets #=> "This is line two\n"
3680 * $. #=> 1001 # lineno of last read
3681 */
3682
3683static VALUE
3684rb_io_set_lineno(VALUE io, VALUE lineno)
3685{
3686 rb_io_t *fptr;
3687
3688 GetOpenFile(io, fptr);
3690 fptr->lineno = NUM2INT(lineno);
3691 return lineno;
3692}
3693
3694/*
3695 * call-seq:
3696 * ios.readline(sep=$/ [, getline_args]) -> string
3697 * ios.readline(limit [, getline_args]) -> string
3698 * ios.readline(sep, limit [, getline_args]) -> string
3699 *
3700 * Reads a line as with IO#gets, but raises an EOFError on end of file.
3701 */
3702
3703static VALUE
3704rb_io_readline(int argc, VALUE *argv, VALUE io)
3705{
3706 VALUE line = rb_io_gets_m(argc, argv, io);
3707
3708 if (NIL_P(line)) {
3709 rb_eof_error();
3710 }
3711 return line;
3712}
3713
3714static VALUE io_readlines(const struct getline_arg *arg, VALUE io);
3715
3716/*
3717 * call-seq:
3718 * ios.readlines(sep=$/ [, getline_args]) -> array
3719 * ios.readlines(limit [, getline_args]) -> array
3720 * ios.readlines(sep, limit [, getline_args]) -> array
3721 *
3722 * Reads all of the lines in <em>ios</em>, and returns them in
3723 * an array. Lines are separated by the optional <i>sep</i>. If
3724 * <i>sep</i> is +nil+, the rest of the stream is returned
3725 * as a single record.
3726 * If the first argument is an integer, or an
3727 * optional second argument is given, the returning string would not be
3728 * longer than the given value in bytes. The stream must be opened for
3729 * reading or an IOError will be raised.
3730 *
3731 * f = File.new("testfile")
3732 * f.readlines[0] #=> "This is line one\n"
3733 *
3734 * f = File.new("testfile", chomp: true)
3735 * f.readlines[0] #=> "This is line one"
3736 *
3737 * See IO.readlines for details about getline_args.
3738 */
3739
3740static VALUE
3741rb_io_readlines(int argc, VALUE *argv, VALUE io)
3742{
3743 struct getline_arg args;
3744
3745 prepare_getline_args(argc, argv, &args, io);
3746 return io_readlines(&args, io);
3747}
3748
3749static VALUE
3750io_readlines(const struct getline_arg *arg, VALUE io)
3751{
3752 VALUE line, ary;
3753
3754 if (arg->limit == 0)
3755 rb_raise(rb_eArgError, "invalid limit: 0 for readlines");
3756 ary = rb_ary_new();
3757 while (!NIL_P(line = rb_io_getline_1(arg->rs, arg->limit, arg->chomp, io))) {
3758 rb_ary_push(ary, line);
3759 }
3760 return ary;
3761}
3762
3763/*
3764 * call-seq:
3765 * ios.each(sep=$/ [, getline_args]) {|line| block } -> ios
3766 * ios.each(limit [, getline_args]) {|line| block } -> ios
3767 * ios.each(sep, limit [, getline_args]) {|line| block } -> ios
3768 * ios.each(...) -> an_enumerator
3769 *
3770 * ios.each_line(sep=$/ [, getline_args]) {|line| block } -> ios
3771 * ios.each_line(limit [, getline_args]) {|line| block } -> ios
3772 * ios.each_line(sep, limit [, getline_args]) {|line| block } -> ios
3773 * ios.each_line(...) -> an_enumerator
3774 *
3775 * Executes the block for every line in <em>ios</em>, where lines are
3776 * separated by <i>sep</i>. <em>ios</em> must be opened for
3777 * reading or an IOError will be raised.
3778 *
3779 * If no block is given, an enumerator is returned instead.
3780 *
3781 * f = File.new("testfile")
3782 * f.each {|line| puts "#{f.lineno}: #{line}" }
3783 *
3784 * <em>produces:</em>
3785 *
3786 * 1: This is line one
3787 * 2: This is line two
3788 * 3: This is line three
3789 * 4: And so on...
3790 *
3791 * See IO.readlines for details about getline_args.
3792 */
3793
3794static VALUE
3795rb_io_each_line(int argc, VALUE *argv, VALUE io)
3796{
3797 VALUE str;
3798 struct getline_arg args;
3799
3801 prepare_getline_args(argc, argv, &args, io);
3802 if (args.limit == 0)
3803 rb_raise(rb_eArgError, "invalid limit: 0 for each_line");
3804 while (!NIL_P(str = rb_io_getline_1(args.rs, args.limit, args.chomp, io))) {
3805 rb_yield(str);
3806 }
3807 return io;
3808}
3809
3810/*
3811 * This is a deprecated alias for #each_line.
3812 */
3813
3814static VALUE
3815rb_io_lines(int argc, VALUE *argv, VALUE io)
3816{
3817 rb_warn_deprecated("IO#lines", "#each_line");
3818 if (!rb_block_given_p())
3819 return rb_enumeratorize(io, ID2SYM(rb_intern("each_line")), argc, argv);
3820 return rb_io_each_line(argc, argv, io);
3821}
3822
3823/*
3824 * call-seq:
3825 * ios.each_byte {|byte| block } -> ios
3826 * ios.each_byte -> an_enumerator
3827 *
3828 * Calls the given block once for each byte (0..255) in <em>ios</em>,
3829 * passing the byte as an argument. The stream must be opened for
3830 * reading or an IOError will be raised.
3831 *
3832 * If no block is given, an enumerator is returned instead.
3833 *
3834 * f = File.new("testfile")
3835 * checksum = 0
3836 * f.each_byte {|x| checksum ^= x } #=> #<File:testfile>
3837 * checksum #=> 12
3838 */
3839
3840static VALUE
3841rb_io_each_byte(VALUE io)
3842{
3843 rb_io_t *fptr;
3844
3845 RETURN_ENUMERATOR(io, 0, 0);
3846 GetOpenFile(io, fptr);
3847
3848 do {
3849 while (fptr->rbuf.len > 0) {
3850 char *p = fptr->rbuf.ptr + fptr->rbuf.off++;
3851 fptr->rbuf.len--;
3852 rb_yield(INT2FIX(*p & 0xff));
3853 errno = 0;
3854 }
3856 READ_CHECK(fptr);
3857 } while (io_fillbuf(fptr) >= 0);
3858 return io;
3859}
3860
3861/*
3862 * This is a deprecated alias for #each_byte.
3863 */
3864
3865static VALUE
3866rb_io_bytes(VALUE io)
3867{
3868 rb_warn_deprecated("IO#bytes", "#each_byte");
3869 if (!rb_block_given_p())
3870 return rb_enumeratorize(io, ID2SYM(rb_intern("each_byte")), 0, 0);
3871 return rb_io_each_byte(io);
3872}
3873
3874static VALUE
3875io_getc(rb_io_t *fptr, rb_encoding *enc)
3876{
3877 int r, n, cr = 0;
3878 VALUE str;
3879
3880 if (NEED_READCONV(fptr)) {
3881 rb_encoding *read_enc = io_read_encoding(fptr);
3882
3883 str = Qnil;
3884 SET_BINARY_MODE(fptr);
3885 make_readconv(fptr, 0);
3886
3887 while (1) {
3888 if (fptr->cbuf.len) {
3889 r = rb_enc_precise_mbclen(fptr->cbuf.ptr+fptr->cbuf.off,
3890 fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
3891 read_enc);
3892 if (!MBCLEN_NEEDMORE_P(r))
3893 break;
3894 if (fptr->cbuf.len == fptr->cbuf.capa) {
3895 rb_raise(rb_eIOError, "too long character");
3896 }
3897 }
3898
3899 if (more_char(fptr) == MORE_CHAR_FINISHED) {
3900 if (fptr->cbuf.len == 0) {
3901 clear_readconv(fptr);
3902 return Qnil;
3903 }
3904 /* return an unit of an incomplete character just before EOF */
3905 str = rb_enc_str_new(fptr->cbuf.ptr+fptr->cbuf.off, 1, read_enc);
3906 fptr->cbuf.off += 1;
3907 fptr->cbuf.len -= 1;
3908 if (fptr->cbuf.len == 0) clear_readconv(fptr);
3910 return str;
3911 }
3912 }
3913 if (MBCLEN_INVALID_P(r)) {
3914 r = rb_enc_mbclen(fptr->cbuf.ptr+fptr->cbuf.off,
3915 fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
3916 read_enc);
3917 io_shift_cbuf(fptr, r, &str);
3919 }
3920 else {
3921 io_shift_cbuf(fptr, MBCLEN_CHARFOUND_LEN(r), &str);
3923 if (MBCLEN_CHARFOUND_LEN(r) == 1 && rb_enc_asciicompat(read_enc) &&
3924 ISASCII(RSTRING_PTR(str)[0])) {
3925 cr = ENC_CODERANGE_7BIT;
3926 }
3927 }
3928 str = io_enc_str(str, fptr);
3930 return str;
3931 }
3932
3934 if (io_fillbuf(fptr) < 0) {
3935 return Qnil;
3936 }
3937 if (rb_enc_asciicompat(enc) && ISASCII(fptr->rbuf.ptr[fptr->rbuf.off])) {
3938 str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, 1);
3939 fptr->rbuf.off += 1;
3940 fptr->rbuf.len -= 1;
3941 cr = ENC_CODERANGE_7BIT;
3942 }
3943 else {
3944 r = rb_enc_precise_mbclen(fptr->rbuf.ptr+fptr->rbuf.off, fptr->rbuf.ptr+fptr->rbuf.off+fptr->rbuf.len, enc);
3945 if (MBCLEN_CHARFOUND_P(r) &&
3946 (n = MBCLEN_CHARFOUND_LEN(r)) <= fptr->rbuf.len) {
3947 str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, n);
3948 fptr->rbuf.off += n;
3949 fptr->rbuf.len -= n;
3951 }
3952 else if (MBCLEN_NEEDMORE_P(r)) {
3953 str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, fptr->rbuf.len);
3954 fptr->rbuf.len = 0;
3955 getc_needmore:
3956 if (io_fillbuf(fptr) != -1) {
3957 rb_str_cat(str, fptr->rbuf.ptr+fptr->rbuf.off, 1);
3958 fptr->rbuf.off++;
3959 fptr->rbuf.len--;
3961 if (MBCLEN_NEEDMORE_P(r)) {
3962 goto getc_needmore;
3963 }
3964 else if (MBCLEN_CHARFOUND_P(r)) {
3966 }
3967 }
3968 }
3969 else {
3970 str = rb_str_new(fptr->rbuf.ptr+fptr->rbuf.off, 1);
3971 fptr->rbuf.off++;
3972 fptr->rbuf.len--;
3973 }
3974 }
3975 if (!cr) cr = ENC_CODERANGE_BROKEN;
3976 str = io_enc_str(str, fptr);
3978 return str;
3979}
3980
3981/*
3982 * call-seq:
3983 * ios.each_char {|c| block } -> ios
3984 * ios.each_char -> an_enumerator
3985 *
3986 * Calls the given block once for each character in <em>ios</em>,
3987 * passing the character as an argument. The stream must be opened for
3988 * reading or an IOError will be raised.
3989 *
3990 * If no block is given, an enumerator is returned instead.
3991 *
3992 * f = File.new("testfile")
3993 * f.each_char {|c| print c, ' ' } #=> #<File:testfile>
3994 */
3995
3996static VALUE
3997rb_io_each_char(VALUE io)
3998{
3999 rb_io_t *fptr;
4000 rb_encoding *enc;
4001 VALUE c;
4002
4003 RETURN_ENUMERATOR(io, 0, 0);
4004 GetOpenFile(io, fptr);
4006
4007 enc = io_input_encoding(fptr);
4008 READ_CHECK(fptr);
4009 while (!NIL_P(c = io_getc(fptr, enc))) {
4010 rb_yield(c);
4011 }
4012 return io;
4013}
4014
4015/*
4016 * This is a deprecated alias for #each_char.
4017 */
4018
4019static VALUE
4020rb_io_chars(VALUE io)
4021{
4022 rb_warn_deprecated("IO#chars", "#each_char");
4023 if (!rb_block_given_p())
4024 return rb_enumeratorize(io, ID2SYM(rb_intern("each_char")), 0, 0);
4025 return rb_io_each_char(io);
4026}
4027
4028
4029/*
4030 * call-seq:
4031 * ios.each_codepoint {|c| block } -> ios
4032 * ios.codepoints {|c| block } -> ios
4033 * ios.each_codepoint -> an_enumerator
4034 * ios.codepoints -> an_enumerator
4035 *
4036 * Passes the Integer ordinal of each character in <i>ios</i>,
4037 * passing the codepoint as an argument. The stream must be opened for
4038 * reading or an IOError will be raised.
4039 *
4040 * If no block is given, an enumerator is returned instead.
4041 *
4042 */
4043
4044static VALUE
4045rb_io_each_codepoint(VALUE io)
4046{
4047 rb_io_t *fptr;
4048 rb_encoding *enc;
4049 unsigned int c;
4050 int r, n;
4051
4052 RETURN_ENUMERATOR(io, 0, 0);
4053 GetOpenFile(io, fptr);
4055
4056 READ_CHECK(fptr);
4057 if (NEED_READCONV(fptr)) {
4058 SET_BINARY_MODE(fptr);
4059 r = 1; /* no invalid char yet */
4060 for (;;) {
4061 make_readconv(fptr, 0);
4062 for (;;) {
4063 if (fptr->cbuf.len) {
4064 if (fptr->encs.enc)
4065 r = rb_enc_precise_mbclen(fptr->cbuf.ptr+fptr->cbuf.off,
4066 fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
4067 fptr->encs.enc);
4068 else
4070 if (!MBCLEN_NEEDMORE_P(r))
4071 break;
4072 if (fptr->cbuf.len == fptr->cbuf.capa) {
4073 rb_raise(rb_eIOError, "too long character");
4074 }
4075 }
4076 if (more_char(fptr) == MORE_CHAR_FINISHED) {
4077 clear_readconv(fptr);
4078 if (!MBCLEN_CHARFOUND_P(r)) {
4079 enc = fptr->encs.enc;
4080 goto invalid;
4081 }
4082 return io;
4083 }
4084 }
4085 if (MBCLEN_INVALID_P(r)) {
4086 enc = fptr->encs.enc;
4087 goto invalid;
4088 }
4090 if (fptr->encs.enc) {
4091 c = rb_enc_codepoint(fptr->cbuf.ptr+fptr->cbuf.off,
4092 fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
4093 fptr->encs.enc);
4094 }
4095 else {
4096 c = (unsigned char)fptr->cbuf.ptr[fptr->cbuf.off];
4097 }
4098 fptr->cbuf.off += n;
4099 fptr->cbuf.len -= n;
4100 rb_yield(UINT2NUM(c));
4101 }
4102 }
4104 enc = io_input_encoding(fptr);
4105 while (io_fillbuf(fptr) >= 0) {
4106 r = rb_enc_precise_mbclen(fptr->rbuf.ptr+fptr->rbuf.off,
4107 fptr->rbuf.ptr+fptr->rbuf.off+fptr->rbuf.len, enc);
4108 if (MBCLEN_CHARFOUND_P(r) &&
4109 (n = MBCLEN_CHARFOUND_LEN(r)) <= fptr->rbuf.len) {
4110 c = rb_enc_codepoint(fptr->rbuf.ptr+fptr->rbuf.off,
4111 fptr->rbuf.ptr+fptr->rbuf.off+fptr->rbuf.len, enc);
4112 fptr->rbuf.off += n;
4113 fptr->rbuf.len -= n;
4114 rb_yield(UINT2NUM(c));
4115 }
4116 else if (MBCLEN_INVALID_P(r)) {
4117 invalid:
4118 rb_raise(rb_eArgError, "invalid byte sequence in %s", rb_enc_name(enc));
4119 }
4120 else if (MBCLEN_NEEDMORE_P(r)) {
4121 char cbuf[8], *p = cbuf;
4122 int more = MBCLEN_NEEDMORE_LEN(r);
4123 if (more > numberof(cbuf)) goto invalid;
4124 more += n = fptr->rbuf.len;
4125 if (more > numberof(cbuf)) goto invalid;
4126 while ((n = (int)read_buffered_data(p, more, fptr)) > 0 &&
4127 (p += n, (more -= n) > 0)) {
4128 if (io_fillbuf(fptr) < 0) goto invalid;
4129 if ((n = fptr->rbuf.len) > more) n = more;
4130 }
4131 r = rb_enc_precise_mbclen(cbuf, p, enc);
4132 if (!MBCLEN_CHARFOUND_P(r)) goto invalid;
4133 c = rb_enc_codepoint(cbuf, p, enc);
4134 rb_yield(UINT2NUM(c));
4135 }
4136 else {
4137 continue;
4138 }
4139 }
4140 return io;
4141}
4142
4143/*
4144 * This is a deprecated alias for #each_codepoint.
4145 */
4146
4147static VALUE
4148rb_io_codepoints(VALUE io)
4149{
4150 rb_warn_deprecated("IO#codepoints", "#each_codepoint");
4151 if (!rb_block_given_p())
4152 return rb_enumeratorize(io, ID2SYM(rb_intern("each_codepoint")), 0, 0);
4153 return rb_io_each_codepoint(io);
4154}
4155
4156
4157/*
4158 * call-seq:
4159 * ios.getc -> string or nil
4160 *
4161 * Reads a one-character string from <em>ios</em>. Returns
4162 * +nil+ if called at end of file.
4163 *
4164 * f = File.new("testfile")
4165 * f.getc #=> "h"
4166 * f.getc #=> "e"
4167 */
4168
4169static VALUE
4170rb_io_getc(VALUE io)
4171{
4172 rb_io_t *fptr;
4173 rb_encoding *enc;
4174
4175 GetOpenFile(io, fptr);
4177
4178 enc = io_input_encoding(fptr);
4179 READ_CHECK(fptr);
4180 return io_getc(fptr, enc);
4181}
4182
4183/*
4184 * call-seq:
4185 * ios.readchar -> string
4186 *
4187 * Reads a one-character string from <em>ios</em>. Raises an
4188 * EOFError on end of file.
4189 *
4190 * f = File.new("testfile")
4191 * f.readchar #=> "h"
4192 * f.readchar #=> "e"
4193 */
4194
4195static VALUE
4196rb_io_readchar(VALUE io)
4197{
4198 VALUE c = rb_io_getc(io);
4199
4200 if (NIL_P(c)) {
4201 rb_eof_error();
4202 }
4203 return c;
4204}
4205
4206/*
4207 * call-seq:
4208 * ios.getbyte -> integer or nil
4209 *
4210 * Gets the next 8-bit byte (0..255) from <em>ios</em>. Returns
4211 * +nil+ if called at end of file.
4212 *
4213 * f = File.new("testfile")
4214 * f.getbyte #=> 84
4215 * f.getbyte #=> 104
4216 */
4217
4218VALUE
4220{
4221 rb_io_t *fptr;
4222 int c;
4223
4224 GetOpenFile(io, fptr);
4226 READ_CHECK(fptr);
4227 if (fptr->fd == 0 && (fptr->mode & FMODE_TTY) && RB_TYPE_P(rb_stdout, T_FILE)) {
4228 rb_io_t *ofp;
4229 GetOpenFile(rb_stdout, ofp);
4230 if (ofp->mode & FMODE_TTY) {
4232 }
4233 }
4234 if (io_fillbuf(fptr) < 0) {
4235 return Qnil;
4236 }
4237 fptr->rbuf.off++;
4238 fptr->rbuf.len--;
4239 c = (unsigned char)fptr->rbuf.ptr[fptr->rbuf.off-1];
4240 return INT2FIX(c & 0xff);
4241}
4242
4243/*
4244 * call-seq:
4245 * ios.readbyte -> integer
4246 *
4247 * Reads a byte as with IO#getbyte, but raises an EOFError on end of
4248 * file.
4249 */
4250
4251static VALUE
4252rb_io_readbyte(VALUE io)
4253{
4254 VALUE c = rb_io_getbyte(io);
4255
4256 if (NIL_P(c)) {
4257 rb_eof_error();
4258 }
4259 return c;
4260}
4261
4262/*
4263 * call-seq:
4264 * ios.ungetbyte(string) -> nil
4265 * ios.ungetbyte(integer) -> nil
4266 *
4267 * Pushes back bytes (passed as a parameter) onto <em>ios</em>,
4268 * such that a subsequent buffered read will return it. Only one byte
4269 * may be pushed back before a subsequent read operation (that is,
4270 * you will be able to read only the last of several bytes that have been pushed
4271 * back). Has no effect with unbuffered reads (such as IO#sysread).
4272 *
4273 * f = File.new("testfile") #=> #<File:testfile>
4274 * b = f.getbyte #=> 0x38
4275 * f.ungetbyte(b) #=> nil
4276 * f.getbyte #=> 0x38
4277 */
4278
4279VALUE
4281{
4282 rb_io_t *fptr;
4283
4284 GetOpenFile(io, fptr);
4286 switch (TYPE(b)) {
4287 case T_NIL:
4288 return Qnil;
4289 case T_FIXNUM:
4290 case T_BIGNUM: ;
4291 VALUE v = rb_int_modulo(b, INT2FIX(256));
4292 unsigned char c = NUM2INT(v) & 0xFF;
4293 b = rb_str_new((const char *)&c, 1);
4294 break;
4295 default:
4296 SafeStringValue(b);
4297 }
4298 io_ungetbyte(b, fptr);
4299 return Qnil;
4300}
4301
4302/*
4303 * call-seq:
4304 * ios.ungetc(string) -> nil
4305 *
4306 * Pushes back one character (passed as a parameter) onto <em>ios</em>,
4307 * such that a subsequent buffered character read will return it. Only one character
4308 * may be pushed back before a subsequent read operation (that is,
4309 * you will be able to read only the last of several characters that have been pushed
4310 * back). Has no effect with unbuffered reads (such as IO#sysread).
4311 *
4312 * f = File.new("testfile") #=> #<File:testfile>
4313 * c = f.getc #=> "8"
4314 * f.ungetc(c) #=> nil
4315 * f.getc #=> "8"
4316 */
4317
4318VALUE
4320{
4321 rb_io_t *fptr;
4322 long len;
4323
4324 GetOpenFile(io, fptr);
4326 if (NIL_P(c)) return Qnil;
4327 if (FIXNUM_P(c)) {
4328 c = rb_enc_uint_chr(FIX2UINT(c), io_read_encoding(fptr));
4329 }
4330 else if (RB_TYPE_P(c, T_BIGNUM)) {
4331 c = rb_enc_uint_chr(NUM2UINT(c), io_read_encoding(fptr));
4332 }
4333 else {
4334 SafeStringValue(c);
4335 }
4336 if (NEED_READCONV(fptr)) {
4337 SET_BINARY_MODE(fptr);
4338 len = RSTRING_LEN(c);
4339#if SIZEOF_LONG > SIZEOF_INT
4340 if (len > INT_MAX)
4341 rb_raise(rb_eIOError, "ungetc failed");
4342#endif
4343 make_readconv(fptr, (int)len);
4344 if (fptr->cbuf.capa - fptr->cbuf.len < len)
4345 rb_raise(rb_eIOError, "ungetc failed");
4346 if (fptr->cbuf.off < len) {
4347 MEMMOVE(fptr->cbuf.ptr+fptr->cbuf.capa-fptr->cbuf.len,
4348 fptr->cbuf.ptr+fptr->cbuf.off,
4349 char, fptr->cbuf.len);
4350 fptr->cbuf.off = fptr->cbuf.capa-fptr->cbuf.len;
4351 }
4352 fptr->cbuf.off -= (int)len;
4353 fptr->cbuf.len += (int)len;
4354 MEMMOVE(fptr->cbuf.ptr+fptr->cbuf.off, RSTRING_PTR(c), char, len);
4355 }
4356 else {
4358 io_ungetbyte(c, fptr);
4359 }
4360 return Qnil;
4361}
4362
4363/*
4364 * call-seq:
4365 * ios.isatty -> true or false
4366 * ios.tty? -> true or false
4367 *
4368 * Returns <code>true</code> if <em>ios</em> is associated with a
4369 * terminal device (tty), <code>false</code> otherwise.
4370 *
4371 * File.new("testfile").isatty #=> false
4372 * File.new("/dev/tty").isatty #=> true
4373 */
4374
4375static VALUE
4376rb_io_isatty(VALUE io)
4377{
4378 rb_io_t *fptr;
4379
4380 GetOpenFile(io, fptr);
4381 if (isatty(fptr->fd) == 0)
4382 return Qfalse;
4383 return Qtrue;
4384}
4385
4386#if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
4387/*
4388 * call-seq:
4389 * ios.close_on_exec? -> true or false
4390 *
4391 * Returns <code>true</code> if <em>ios</em> will be closed on exec.
4392 *
4393 * f = open("/dev/null")
4394 * f.close_on_exec? #=> false
4395 * f.close_on_exec = true
4396 * f.close_on_exec? #=> true
4397 * f.close_on_exec = false
4398 * f.close_on_exec? #=> false
4399 */
4400
4401static VALUE
4403{
4404 rb_io_t *fptr;
4405 VALUE write_io;
4406 int fd, ret;
4407
4408 write_io = GetWriteIO(io);
4409 if (io != write_io) {
4410 GetOpenFile(write_io, fptr);
4411 if (fptr && 0 <= (fd = fptr->fd)) {
4412 if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
4413 if (!(ret & FD_CLOEXEC)) return Qfalse;
4414 }
4415 }
4416
4417 GetOpenFile(io, fptr);
4418 if (fptr && 0 <= (fd = fptr->fd)) {
4419 if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
4420 if (!(ret & FD_CLOEXEC)) return Qfalse;
4421 }
4422 return Qtrue;
4423}
4424#else
4425#define rb_io_close_on_exec_p rb_f_notimplement
4426#endif
4427
4428#if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
4429/*
4430 * call-seq:
4431 * ios.close_on_exec = bool -> true or false
4432 *
4433 * Sets a close-on-exec flag.
4434 *
4435 * f = open("/dev/null")
4436 * f.close_on_exec = true
4437 * system("cat", "/proc/self/fd/#{f.fileno}") # cat: /proc/self/fd/3: No such file or directory
4438 * f.closed? #=> false
4439 *
4440 * Ruby sets close-on-exec flags of all file descriptors by default
4441 * since Ruby 2.0.0.
4442 * So you don't need to set by yourself.
4443 * Also, unsetting a close-on-exec flag can cause file descriptor leak
4444 * if another thread use fork() and exec() (via system() method for example).
4445 * If you really needs file descriptor inheritance to child process,
4446 * use spawn()'s argument such as fd=>fd.
4447 */
4448
4449static VALUE
4451{
4452 int flag = RTEST(arg) ? FD_CLOEXEC : 0;
4453 rb_io_t *fptr;
4454 VALUE write_io;
4455 int fd, ret;
4456
4457 write_io = GetWriteIO(io);
4458 if (io != write_io) {
4459 GetOpenFile(write_io, fptr);
4460 if (fptr && 0 <= (fd = fptr->fd)) {
4461 if ((ret = fcntl(fptr->fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
4462 if ((ret & FD_CLOEXEC) != flag) {
4463 ret = (ret & ~FD_CLOEXEC) | flag;
4464 ret = fcntl(fd, F_SETFD, ret);
4465 if (ret != 0) rb_sys_fail_path(fptr->pathv);
4466 }
4467 }
4468
4469 }
4470
4471 GetOpenFile(io, fptr);
4472 if (fptr && 0 <= (fd = fptr->fd)) {
4473 if ((ret = fcntl(fd, F_GETFD)) == -1) rb_sys_fail_path(fptr->pathv);
4474 if ((ret & FD_CLOEXEC) != flag) {
4475 ret = (ret & ~FD_CLOEXEC) | flag;
4476 ret = fcntl(fd, F_SETFD, ret);
4477 if (ret != 0) rb_sys_fail_path(fptr->pathv);
4478 }
4479 }
4480 return Qnil;
4481}
4482#else
4483#define rb_io_set_close_on_exec rb_f_notimplement
4484#endif
4485
4486#define FMODE_PREP (1<<16)
4487#define IS_PREP_STDIO(f) ((f)->mode & FMODE_PREP)
4488#define PREP_STDIO_NAME(f) (RSTRING_PTR((f)->pathv))
4489
4490static VALUE
4491finish_writeconv(rb_io_t *fptr, int noalloc)
4492{
4493 unsigned char *ds, *dp, *de;
4495
4496 if (!fptr->wbuf.ptr) {
4497 unsigned char buf[1024];
4498 long r;
4499
4501 while (res == econv_destination_buffer_full) {
4502 ds = dp = buf;
4503 de = buf + sizeof(buf);
4504 res = rb_econv_convert(fptr->writeconv, NULL, NULL, &dp, de, 0);
4505 while (dp-ds) {
4506 retry:
4507 if (fptr->write_lock && rb_mutex_owned_p(fptr->write_lock))
4508 r = rb_write_internal2(fptr->fd, ds, dp-ds);
4509 else
4510 r = rb_write_internal(fptr->fd, ds, dp-ds);
4511 if (r == dp-ds)
4512 break;
4513 if (0 <= r) {
4514 ds += r;
4515 }
4516 if (rb_io_wait_writable(fptr->fd)) {
4517 if (fptr->fd < 0)
4518 return noalloc ? Qtrue : rb_exc_new3(rb_eIOError, rb_str_new_cstr(closed_stream));
4519 goto retry;
4520 }
4521 return noalloc ? Qtrue : INT2NUM(errno);
4522 }
4523 if (res == econv_invalid_byte_sequence ||
4524 res == econv_incomplete_input ||
4526 return noalloc ? Qtrue : rb_econv_make_exception(fptr->writeconv);
4527 }
4528 }
4529
4530 return Qnil;
4531 }
4532
4534 while (res == econv_destination_buffer_full) {
4535 if (fptr->wbuf.len == fptr->wbuf.capa) {
4536 if (io_fflush(fptr) < 0)
4537 return noalloc ? Qtrue : INT2NUM(errno);
4538 }
4539
4540 ds = dp = (unsigned char *)fptr->wbuf.ptr + fptr->wbuf.off + fptr->wbuf.len;
4541 de = (unsigned char *)fptr->wbuf.ptr + fptr->wbuf.capa;
4542 res = rb_econv_convert(fptr->writeconv, NULL, NULL, &dp, de, 0);
4543 fptr->wbuf.len += (int)(dp - ds);
4544 if (res == econv_invalid_byte_sequence ||
4545 res == econv_incomplete_input ||
4547 return noalloc ? Qtrue : rb_econv_make_exception(fptr->writeconv);
4548 }
4549 }
4550 return Qnil;
4551}
4552
4556};
4557
4558static VALUE
4559finish_writeconv_sync(VALUE arg)
4560{
4561 struct finish_writeconv_arg *p = (struct finish_writeconv_arg *)arg;
4562 return finish_writeconv(p->fptr, p->noalloc);
4563}
4564
4565static void*
4566nogvl_close(void *ptr)
4567{
4568 int *fd = ptr;
4569
4570 return (void*)(intptr_t)close(*fd);
4571}
4572
4573static int
4574maygvl_close(int fd, int keepgvl)
4575{
4576 if (keepgvl)
4577 return close(fd);
4578
4579 /*
4580 * close() may block for certain file types (NFS, SO_LINGER sockets,
4581 * inotify), so let other threads run.
4582 */
4583 return (int)(intptr_t)rb_thread_call_without_gvl(nogvl_close, &fd, RUBY_UBF_IO, 0);
4584}
4585
4586static void*
4587nogvl_fclose(void *ptr)
4588{
4589 FILE *file = ptr;
4590
4591 return (void*)(intptr_t)fclose(file);
4592}
4593
4594static int
4595maygvl_fclose(FILE *file, int keepgvl)
4596{
4597 if (keepgvl)
4598 return fclose(file);
4599
4600 return (int)(intptr_t)rb_thread_call_without_gvl(nogvl_fclose, file, RUBY_UBF_IO, 0);
4601}
4602
4603static void free_io_buffer(rb_io_buffer_t *buf);
4604static void clear_codeconv(rb_io_t *fptr);
4605
4606static void
4607fptr_finalize_flush(rb_io_t *fptr, int noraise, int keepgvl,
4608 struct list_head *busy)
4609{
4610 VALUE err = Qnil;
4611 int fd = fptr->fd;
4612 FILE *stdio_file = fptr->stdio_file;
4613 int mode = fptr->mode;
4614
4615 if (fptr->writeconv) {
4616 if (fptr->write_lock && !noraise) {
4618 arg.fptr = fptr;
4619 arg.noalloc = noraise;
4620 err = rb_mutex_synchronize(fptr->write_lock, finish_writeconv_sync, (VALUE)&arg);
4621 }
4622 else {
4623 err = finish_writeconv(fptr, noraise);
4624 }
4625 }
4626 if (fptr->wbuf.len) {
4627 if (noraise) {
4628 io_flush_buffer_sync(fptr);
4629 }
4630 else {
4631 if (io_fflush(fptr) < 0 && NIL_P(err))
4632 err = INT2NUM(errno);
4633 }
4634 }
4635
4636 fptr->fd = -1;
4637 fptr->stdio_file = 0;
4639
4640 /*
4641 * ensure waiting_fd users do not hit EBADF, wait for them
4642 * to exit before we call close().
4643 */
4644 if (busy) {
4645 do rb_thread_schedule(); while (!list_empty(busy));
4646 }
4647
4648 if (IS_PREP_STDIO(fptr) || fd <= 2) {
4649 /* need to keep FILE objects of stdin, stdout and stderr */
4650 }
4651 else if (stdio_file) {
4652 /* stdio_file is deallocated anyway
4653 * even if fclose failed. */
4654 if ((maygvl_fclose(stdio_file, noraise) < 0) && NIL_P(err))
4655 if (!noraise) err = INT2NUM(errno);
4656 }
4657 else if (0 <= fd) {
4658 /* fptr->fd may be closed even if close fails.
4659 * POSIX doesn't specify it.
4660 * We assumes it is closed. */
4661
4662
4663 keepgvl |= !(mode & FMODE_WRITABLE);
4664 keepgvl |= noraise;
4665 if ((maygvl_close(fd, keepgvl) < 0) && NIL_P(err))
4666 if (!noraise) err = INT2NUM(errno);
4667 }
4668
4669 if (!NIL_P(err) && !noraise) {
4672 else
4674 }
4675}
4676
4677static void
4678fptr_finalize(rb_io_t *fptr, int noraise)
4679{
4680 fptr_finalize_flush(fptr, noraise, FALSE, 0);
4681 free_io_buffer(&fptr->rbuf);
4682 free_io_buffer(&fptr->wbuf);
4683 clear_codeconv(fptr);
4684}
4685
4686static void
4687rb_io_fptr_cleanup(rb_io_t *fptr, int noraise)
4688{
4689 if (fptr->finalize) {
4690 (*fptr->finalize)(fptr, noraise);
4691 }
4692 else {
4693 fptr_finalize(fptr, noraise);
4694 }
4695}
4696
4697static void
4698free_io_buffer(rb_io_buffer_t *buf)
4699{
4700 if (buf->ptr) {
4701 ruby_sized_xfree(buf->ptr, (size_t)buf->capa);
4702 buf->ptr = NULL;
4703 }
4704}
4705
4706static void
4707clear_readconv(rb_io_t *fptr)
4708{
4709 if (fptr->readconv) {
4711 fptr->readconv = NULL;
4712 }
4713 free_io_buffer(&fptr->cbuf);
4714}
4715
4716static void
4717clear_writeconv(rb_io_t *fptr)
4718{
4719 if (fptr->writeconv) {
4721 fptr->writeconv = NULL;
4722 }
4724}
4725
4726static void
4727clear_codeconv(rb_io_t *fptr)
4728{
4729 clear_readconv(fptr);
4730 clear_writeconv(fptr);
4731}
4732
4733void
4735{
4736 rb_io_t *fptr = ptr;
4737
4738 if (!ptr) return;
4739 fptr->pathv = Qnil;
4740 if (0 <= fptr->fd)
4741 rb_io_fptr_cleanup(fptr, TRUE);
4742 fptr->write_lock = 0;
4743 free_io_buffer(&fptr->rbuf);
4744 free_io_buffer(&fptr->wbuf);
4745 clear_codeconv(fptr);
4746 free(fptr);
4747}
4748
4749#undef rb_io_fptr_finalize
4750int
4752{
4753 if (!fptr) {
4754 return 0;
4755 }
4756 else {
4758 return 1;
4759 }
4760}
4761#define rb_io_fptr_finalize(fptr) rb_io_fptr_finalize_internal(fptr)
4762
4763RUBY_FUNC_EXPORTED size_t
4765{
4766 size_t size = sizeof(rb_io_t);
4767 size += fptr->rbuf.capa;
4768 size += fptr->wbuf.capa;
4769 size += fptr->cbuf.capa;
4772 return size;
4773}
4774
4775#ifdef _WIN32
4776/* keep GVL while closing to prevent crash on Windows */
4777# define KEEPGVL TRUE
4778#else
4779# define KEEPGVL FALSE
4780#endif
4781
4782int rb_notify_fd_close(int fd, struct list_head *);
4783static rb_io_t *
4784io_close_fptr(VALUE io)
4785{
4786 rb_io_t *fptr;
4787 VALUE write_io;
4788 rb_io_t *write_fptr;
4789 struct list_head busy;
4790
4791 list_head_init(&busy);
4792 write_io = GetWriteIO(io);
4793 if (io != write_io) {
4794 write_fptr = RFILE(write_io)->fptr;
4795 if (write_fptr && 0 <= write_fptr->fd) {
4796 rb_io_fptr_cleanup(write_fptr, TRUE);
4797 }
4798 }
4799
4800 fptr = RFILE(io)->fptr;
4801 if (!fptr) return 0;
4802 if (fptr->fd < 0) return 0;
4803
4804 if (rb_notify_fd_close(fptr->fd, &busy)) {
4805 /* calls close(fptr->fd): */
4806 fptr_finalize_flush(fptr, FALSE, KEEPGVL, &busy);
4807 }
4808 rb_io_fptr_cleanup(fptr, FALSE);
4809 return fptr;
4810}
4811
4812static void
4813fptr_waitpid(rb_io_t *fptr, int nohang)
4814{
4815 int status;
4816 if (fptr->pid) {
4818 rb_waitpid(fptr->pid, &status, nohang ? WNOHANG : 0);
4819 fptr->pid = 0;
4820 }
4821}
4822
4823VALUE
4825{
4826 rb_io_t *fptr = io_close_fptr(io);
4827 if (fptr) fptr_waitpid(fptr, 0);
4828 return Qnil;
4829}
4830
4831/*
4832 * call-seq:
4833 * ios.close -> nil
4834 *
4835 * Closes <em>ios</em> and flushes any pending writes to the operating
4836 * system. The stream is unavailable for any further data operations;
4837 * an IOError is raised if such an attempt is made. I/O streams are
4838 * automatically closed when they are claimed by the garbage collector.
4839 *
4840 * If <em>ios</em> is opened by IO.popen, #close sets
4841 * <code>$?</code>.
4842 *
4843 * Calling this method on closed IO object is just ignored since Ruby 2.3.
4844 */
4845
4846static VALUE
4847rb_io_close_m(VALUE io)
4848{
4849 rb_io_t *fptr = rb_io_get_fptr(io);
4850 if (fptr->fd < 0) {
4851 return Qnil;
4852 }
4853 rb_io_close(io);
4854 return Qnil;
4855}
4856
4857static VALUE
4858io_call_close(VALUE io)
4859{
4860 rb_check_funcall(io, rb_intern("close"), 0, 0);
4861 return io;
4862}
4863
4864static VALUE
4865ignore_closed_stream(VALUE io, VALUE exc)
4866{
4867 enum {mesg_len = sizeof(closed_stream)-1};
4868 VALUE mesg = rb_attr_get(exc, idMesg);
4869 if (!RB_TYPE_P(mesg, T_STRING) ||
4870 RSTRING_LEN(mesg) != mesg_len ||
4871 memcmp(RSTRING_PTR(mesg), closed_stream, mesg_len)) {
4873 }
4874 return io;
4875}
4876
4877static VALUE
4878io_close(VALUE io)
4879{
4880 VALUE closed = rb_check_funcall(io, rb_intern("closed?"), 0, 0);
4881 if (closed != Qundef && RTEST(closed)) return io;
4882 rb_rescue2(io_call_close, io, ignore_closed_stream, io,
4883 rb_eIOError, (VALUE)0);
4884 return io;
4885}
4886
4887/*
4888 * call-seq:
4889 * ios.closed? -> true or false
4890 *
4891 * Returns <code>true</code> if <em>ios</em> is completely closed (for
4892 * duplex streams, both reader and writer), <code>false</code>
4893 * otherwise.
4894 *
4895 * f = File.new("testfile")
4896 * f.close #=> nil
4897 * f.closed? #=> true
4898 * f = IO.popen("/bin/sh","r+")
4899 * f.close_write #=> nil
4900 * f.closed? #=> false
4901 * f.close_read #=> nil
4902 * f.closed? #=> true
4903 */
4904
4905
4906static VALUE
4907rb_io_closed(VALUE io)
4908{
4909 rb_io_t *fptr;
4910 VALUE write_io;
4911 rb_io_t *write_fptr;
4912
4913 write_io = GetWriteIO(io);
4914 if (io != write_io) {
4915 write_fptr = RFILE(write_io)->fptr;
4916 if (write_fptr && 0 <= write_fptr->fd) {
4917 return Qfalse;
4918 }
4919 }
4920
4921 fptr = rb_io_get_fptr(io);
4922 return 0 <= fptr->fd ? Qfalse : Qtrue;
4923}
4924
4925/*
4926 * call-seq:
4927 * ios.close_read -> nil
4928 *
4929 * Closes the read end of a duplex I/O stream (i.e., one that contains
4930 * both a read and a write stream, such as a pipe). Will raise an
4931 * IOError if the stream is not duplexed.
4932 *
4933 * f = IO.popen("/bin/sh","r+")
4934 * f.close_read
4935 * f.readlines
4936 *
4937 * <em>produces:</em>
4938 *
4939 * prog.rb:3:in `readlines': not opened for reading (IOError)
4940 * from prog.rb:3
4941 *
4942 * Calling this method on closed IO object is just ignored since Ruby 2.3.
4943 */
4944
4945static VALUE
4946rb_io_close_read(VALUE io)
4947{
4948 rb_io_t *fptr;
4949 VALUE write_io;
4950
4951 fptr = rb_io_get_fptr(rb_io_taint_check(io));
4952 if (fptr->fd < 0) return Qnil;
4953 if (is_socket(fptr->fd, fptr->pathv)) {
4954#ifndef SHUT_RD
4955# define SHUT_RD 0
4956#endif
4957 if (shutdown(fptr->fd, SHUT_RD) < 0)
4958 rb_sys_fail_path(fptr->pathv);
4959 fptr->mode &= ~FMODE_READABLE;
4960 if (!(fptr->mode & FMODE_WRITABLE))
4961 return rb_io_close(io);
4962 return Qnil;
4963 }
4964
4965 write_io = GetWriteIO(io);
4966 if (io != write_io) {
4967 rb_io_t *wfptr;
4968 wfptr = rb_io_get_fptr(rb_io_taint_check(write_io));
4969 wfptr->pid = fptr->pid;
4970 fptr->pid = 0;
4971 RFILE(io)->fptr = wfptr;
4972 /* bind to write_io temporarily to get rid of memory/fd leak */
4973 fptr->tied_io_for_writing = 0;
4974 RFILE(write_io)->fptr = fptr;
4975 rb_io_fptr_cleanup(fptr, FALSE);
4976 /* should not finalize fptr because another thread may be reading it */
4977 return Qnil;
4978 }
4979
4980 if ((fptr->mode & (FMODE_DUPLEX|FMODE_WRITABLE)) == FMODE_WRITABLE) {
4981 rb_raise(rb_eIOError, "closing non-duplex IO for reading");
4982 }
4983 return rb_io_close(io);
4984}
4985
4986/*
4987 * call-seq:
4988 * ios.close_write -> nil
4989 *
4990 * Closes the write end of a duplex I/O stream (i.e., one that contains
4991 * both a read and a write stream, such as a pipe). Will raise an
4992 * IOError if the stream is not duplexed.
4993 *
4994 * f = IO.popen("/bin/sh","r+")
4995 * f.close_write
4996 * f.print "nowhere"
4997 *
4998 * <em>produces:</em>
4999 *
5000 * prog.rb:3:in `write': not opened for writing (IOError)
5001 * from prog.rb:3:in `print'
5002 * from prog.rb:3
5003 *
5004 * Calling this method on closed IO object is just ignored since Ruby 2.3.
5005 */
5006
5007static VALUE
5008rb_io_close_write(VALUE io)
5009{
5010 rb_io_t *fptr;
5011 VALUE write_io;
5012
5013 write_io = GetWriteIO(io);
5014 fptr = rb_io_get_fptr(rb_io_taint_check(write_io));
5015 if (fptr->fd < 0) return Qnil;
5016 if (is_socket(fptr->fd, fptr->pathv)) {
5017#ifndef SHUT_WR
5018# define SHUT_WR 1
5019#endif
5020 if (shutdown(fptr->fd, SHUT_WR) < 0)
5021 rb_sys_fail_path(fptr->pathv);
5022 fptr->mode &= ~FMODE_WRITABLE;
5023 if (!(fptr->mode & FMODE_READABLE))
5024 return rb_io_close(write_io);
5025 return Qnil;
5026 }
5027
5028 if ((fptr->mode & (FMODE_DUPLEX|FMODE_READABLE)) == FMODE_READABLE) {
5029 rb_raise(rb_eIOError, "closing non-duplex IO for writing");
5030 }
5031
5032 if (io != write_io) {
5033 fptr = rb_io_get_fptr(rb_io_taint_check(io));
5034 fptr->tied_io_for_writing = 0;
5035 }
5036 rb_io_close(write_io);
5037 return Qnil;
5038}
5039
5040/*
5041 * call-seq:
5042 * ios.sysseek(offset, whence=IO::SEEK_SET) -> integer
5043 *
5044 * Seeks to a given <i>offset</i> in the stream according to the value
5045 * of <i>whence</i> (see IO#seek for values of <i>whence</i>). Returns
5046 * the new offset into the file.
5047 *
5048 * f = File.new("testfile")
5049 * f.sysseek(-13, IO::SEEK_END) #=> 53
5050 * f.sysread(10) #=> "And so on."
5051 */
5052
5053static VALUE
5054rb_io_sysseek(int argc, VALUE *argv, VALUE io)
5055{
5056 VALUE offset, ptrname;
5057 int whence = SEEK_SET;
5058 rb_io_t *fptr;
5059 off_t pos;
5060
5061 if (rb_scan_args(argc, argv, "11", &offset, &ptrname) == 2) {
5062 whence = interpret_seek_whence(ptrname);
5063 }
5064 pos = NUM2OFFT(offset);
5065 GetOpenFile(io, fptr);
5066 if ((fptr->mode & FMODE_READABLE) &&
5067 (READ_DATA_BUFFERED(fptr) || READ_CHAR_PENDING(fptr))) {
5068 rb_raise(rb_eIOError, "sysseek for buffered IO");
5069 }
5070 if ((fptr->mode & FMODE_WRITABLE) && fptr->wbuf.len) {
5071 rb_warn("sysseek for buffered IO");
5072 }
5073 errno = 0;
5074 pos = lseek(fptr->fd, pos, whence);
5075 if (pos < 0 && errno) rb_sys_fail_path(fptr->pathv);
5076
5077 return OFFT2NUM(pos);
5078}
5079
5080/*
5081 * call-seq:
5082 * ios.syswrite(string) -> integer
5083 *
5084 * Writes the given string to <em>ios</em> using a low-level write.
5085 * Returns the number of bytes written. Do not mix with other methods
5086 * that write to <em>ios</em> or you may get unpredictable results.
5087 * Raises SystemCallError on error.
5088 *
5089 * f = File.new("out", "w")
5090 * f.syswrite("ABCDEF") #=> 6
5091 */
5092
5093static VALUE
5094rb_io_syswrite(VALUE io, VALUE str)
5095{
5096 VALUE tmp;
5097 rb_io_t *fptr;
5098 long n, len;
5099 const char *ptr;
5100
5101 if (!RB_TYPE_P(str, T_STRING))
5103
5104 io = GetWriteIO(io);
5105 GetOpenFile(io, fptr);
5107
5108 if (fptr->wbuf.len) {
5109 rb_warn("syswrite for buffered IO");
5110 }
5111
5113 RSTRING_GETMEM(tmp, ptr, len);
5114 n = rb_write_internal(fptr->fd, ptr, len);
5115 if (n < 0) rb_sys_fail_path(fptr->pathv);
5117
5118 return LONG2FIX(n);
5119}
5120
5121/*
5122 * call-seq:
5123 * ios.sysread(maxlen[, outbuf]) -> string
5124 *
5125 * Reads <i>maxlen</i> bytes from <em>ios</em> using a low-level
5126 * read and returns them as a string. Do not mix with other methods
5127 * that read from <em>ios</em> or you may get unpredictable results.
5128 *
5129 * If the optional _outbuf_ argument is present,
5130 * it must reference a String, which will receive the data.
5131 * The _outbuf_ will contain only the received data after the method call
5132 * even if it is not empty at the beginning.
5133 *
5134 * Raises SystemCallError on error and EOFError at end of file.
5135 *
5136 * f = File.new("testfile")
5137 * f.sysread(16) #=> "This is line one"
5138 */
5139
5140static VALUE
5141rb_io_sysread(int argc, VALUE *argv, VALUE io)
5142{
5143 VALUE len, str;
5144 rb_io_t *fptr;
5145 long n, ilen;
5146 struct io_internal_read_struct iis;
5147 int shrinkable;
5148
5149 rb_scan_args(argc, argv, "11", &len, &str);
5150 ilen = NUM2LONG(len);
5151
5152 shrinkable = io_setstrbuf(&str, ilen);
5153 if (ilen == 0) return str;
5154
5155 GetOpenFile(io, fptr);
5157
5158 if (READ_DATA_BUFFERED(fptr)) {
5159 rb_raise(rb_eIOError, "sysread for buffered IO");
5160 }
5161
5162 /*
5163 * FIXME: removing rb_thread_wait_fd() here changes sysread semantics
5164 * on non-blocking IOs. However, it's still currently possible
5165 * for sysread to raise Errno::EAGAIN if another thread read()s
5166 * the IO after we return from rb_thread_wait_fd() but before
5167 * we call read()
5168 */
5169 rb_thread_wait_fd(fptr->fd);
5170
5171 rb_io_check_closed(fptr);
5172
5173 io_setstrbuf(&str, ilen);
5174 iis.fd = fptr->fd;
5175 iis.nonblock = 1; /* for historical reasons, maybe (see above) */
5176 iis.buf = RSTRING_PTR(str);
5177 iis.capa = ilen;
5178 n = read_internal_locktmp(str, &iis);
5179
5180 if (n < 0) {
5181 rb_sys_fail_path(fptr->pathv);
5182 }
5183 io_set_read_length(str, n, shrinkable);
5184 if (n == 0 && ilen > 0) {
5185 rb_eof_error();
5186 }
5187
5188 return str;
5189}
5190
5191#if defined(HAVE_PREAD) || defined(HAVE_PWRITE)
5192struct prdwr_internal_arg {
5193 int fd;
5194 void *buf;
5195 size_t count;
5196 off_t offset;
5197};
5198#endif /* HAVE_PREAD || HAVE_PWRITE */
5199
5200#if defined(HAVE_PREAD)
5201static VALUE
5202internal_pread_func(void *arg)
5203{
5204 struct prdwr_internal_arg *p = arg;
5205 return (VALUE)pread(p->fd, p->buf, p->count, p->offset);
5206}
5207
5208static VALUE
5209pread_internal_call(VALUE arg)
5210{
5211 struct prdwr_internal_arg *p = (struct prdwr_internal_arg *)arg;
5212 return rb_thread_io_blocking_region(internal_pread_func, p, p->fd);
5213}
5214
5215/*
5216 * call-seq:
5217 * ios.pread(maxlen, offset[, outbuf]) -> string
5218 *
5219 * Reads <i>maxlen</i> bytes from <em>ios</em> using the pread system call
5220 * and returns them as a string without modifying the underlying
5221 * descriptor offset. This is advantageous compared to combining IO#seek
5222 * and IO#read in that it is atomic, allowing multiple threads/process to
5223 * share the same IO object for reading the file at various locations.
5224 * This bypasses any userspace buffering of the IO layer.
5225 * If the optional <i>outbuf</i> argument is present, it must
5226 * reference a String, which will receive the data.
5227 * Raises SystemCallError on error, EOFError at end of file and
5228 * NotImplementedError if platform does not implement the system call.
5229 *
5230 * File.write("testfile", "This is line one\nThis is line two\n")
5231 * File.open("testfile") do |f|
5232 * p f.read # => "This is line one\nThis is line two\n"
5233 * p f.pread(12, 0) # => "This is line"
5234 * p f.pread(9, 8) # => "line one\n"
5235 * end
5236 */
5237static VALUE
5238rb_io_pread(int argc, VALUE *argv, VALUE io)
5239{
5240 VALUE len, offset, str;
5241 rb_io_t *fptr;
5242 ssize_t n;
5243 struct prdwr_internal_arg arg;
5244 int shrinkable;
5245
5246 rb_scan_args(argc, argv, "21", &len, &offset, &str);
5247 arg.count = NUM2SIZET(len);
5248 arg.offset = NUM2OFFT(offset);
5249
5250 shrinkable = io_setstrbuf(&str, (long)arg.count);
5251 if (arg.count == 0) return str;
5252 arg.buf = RSTRING_PTR(str);
5253
5254 GetOpenFile(io, fptr);
5256
5257 arg.fd = fptr->fd;
5258 rb_io_check_closed(fptr);
5259
5261 n = (ssize_t)rb_ensure(pread_internal_call, (VALUE)&arg, rb_str_unlocktmp, str);
5262
5263 if (n < 0) {
5264 rb_sys_fail_path(fptr->pathv);
5265 }
5266 io_set_read_length(str, n, shrinkable);
5267 if (n == 0 && arg.count > 0) {
5268 rb_eof_error();
5269 }
5270
5271 return str;
5272}
5273#else
5274# define rb_io_pread rb_f_notimplement
5275#endif /* HAVE_PREAD */
5276
5277#if defined(HAVE_PWRITE)
5278static VALUE
5279internal_pwrite_func(void *ptr)
5280{
5281 struct prdwr_internal_arg *arg = ptr;
5282
5283 return (VALUE)pwrite(arg->fd, arg->buf, arg->count, arg->offset);
5284}
5285
5286/*
5287 * call-seq:
5288 * ios.pwrite(string, offset) -> integer
5289 *
5290 * Writes the given string to <em>ios</em> at <i>offset</i> using pwrite()
5291 * system call. This is advantageous to combining IO#seek and IO#write
5292 * in that it is atomic, allowing multiple threads/process to share the
5293 * same IO object for reading the file at various locations.
5294 * This bypasses any userspace buffering of the IO layer.
5295 * Returns the number of bytes written.
5296 * Raises SystemCallError on error and NotImplementedError
5297 * if platform does not implement the system call.
5298 *
5299 * File.open("out", "w") do |f|
5300 * f.pwrite("ABCDEF", 3) #=> 6
5301 * end
5302 *
5303 * File.read("out") #=> "\u0000\u0000\u0000ABCDEF"
5304 */
5305static VALUE
5306rb_io_pwrite(VALUE io, VALUE str, VALUE offset)
5307{
5308 rb_io_t *fptr;
5309 ssize_t n;
5310 struct prdwr_internal_arg arg;
5311 VALUE tmp;
5312
5313 if (!RB_TYPE_P(str, T_STRING))
5315
5316 arg.offset = NUM2OFFT(offset);
5317
5318 io = GetWriteIO(io);
5319 GetOpenFile(io, fptr);
5321 arg.fd = fptr->fd;
5322
5324 arg.buf = RSTRING_PTR(tmp);
5325 arg.count = (size_t)RSTRING_LEN(tmp);
5326
5327 n = (ssize_t)rb_thread_io_blocking_region(internal_pwrite_func, &arg, fptr->fd);
5328 if (n < 0) rb_sys_fail_path(fptr->pathv);
5330
5331 return SSIZET2NUM(n);
5332}
5333#else
5334# define rb_io_pwrite rb_f_notimplement
5335#endif /* HAVE_PWRITE */
5336
5337VALUE
5339{
5340 rb_io_t *fptr;
5341
5342 GetOpenFile(io, fptr);
5343 if (fptr->readconv)
5345 if (fptr->writeconv)
5347 fptr->mode |= FMODE_BINMODE;
5348 fptr->mode &= ~FMODE_TEXTMODE;
5349 fptr->writeconv_pre_ecflags &= ~ECONV_NEWLINE_DECORATOR_MASK;
5350#ifdef O_BINARY
5351 if (!fptr->readconv) {
5353 }
5354 else {
5355 setmode(fptr->fd, O_BINARY);
5356 }
5357#endif
5358 return io;
5359}
5360
5361static void
5362io_ascii8bit_binmode(rb_io_t *fptr)
5363{
5364 if (fptr->readconv) {
5365 rb_econv_close(fptr->readconv);
5366 fptr->readconv = NULL;
5367 }
5368 if (fptr->writeconv) {
5370 fptr->writeconv = NULL;
5371 }
5372 fptr->mode |= FMODE_BINMODE;
5373 fptr->mode &= ~FMODE_TEXTMODE;
5375
5376 fptr->encs.enc = rb_ascii8bit_encoding();
5377 fptr->encs.enc2 = NULL;
5378 fptr->encs.ecflags = 0;
5379 fptr->encs.ecopts = Qnil;
5380 clear_codeconv(fptr);
5381}
5382
5383VALUE
5385{
5386 rb_io_t *fptr;
5387
5388 GetOpenFile(io, fptr);
5389 io_ascii8bit_binmode(fptr);
5390
5391 return io;
5392}
5393
5394/*
5395 * call-seq:
5396 * ios.binmode -> ios
5397 *
5398 * Puts <em>ios</em> into binary mode.
5399 * Once a stream is in binary mode, it cannot be reset to nonbinary mode.
5400 *
5401 * - newline conversion disabled
5402 * - encoding conversion disabled
5403 * - content is treated as ASCII-8BIT
5404 */
5405
5406static VALUE
5407rb_io_binmode_m(VALUE io)
5408{
5409 VALUE write_io;
5410
5412
5413 write_io = GetWriteIO(io);
5414 if (write_io != io)
5415 rb_io_ascii8bit_binmode(write_io);
5416 return io;
5417}
5418
5419/*
5420 * call-seq:
5421 * ios.binmode? -> true or false
5422 *
5423 * Returns <code>true</code> if <em>ios</em> is binmode.
5424 */
5425static VALUE
5426rb_io_binmode_p(VALUE io)
5427{
5428 rb_io_t *fptr;
5429 GetOpenFile(io, fptr);
5430 return fptr->mode & FMODE_BINMODE ? Qtrue : Qfalse;
5431}
5432
5433static const char*
5434rb_io_fmode_modestr(int fmode)
5435{
5436 if (fmode & FMODE_APPEND) {
5438 return MODE_BTMODE("a+", "ab+", "at+");
5439 }
5440 return MODE_BTMODE("a", "ab", "at");
5441 }
5442 switch (fmode & FMODE_READWRITE) {
5443 default:
5444 rb_raise(rb_eArgError, "invalid access fmode 0x%x", fmode);
5445 case FMODE_READABLE:
5446 return MODE_BTMODE("r", "rb", "rt");
5447 case FMODE_WRITABLE:
5448 return MODE_BTXMODE("w", "wb", "wt", "wx", "wbx", "wtx");
5449 case FMODE_READWRITE:
5450 if (fmode & FMODE_CREATE) {
5451 return MODE_BTXMODE("w+", "wb+", "wt+", "w+x", "wb+x", "wt+x");
5452 }
5453 return MODE_BTMODE("r+", "rb+", "rt+");
5454 }
5455}
5456
5457static const char bom_prefix[] = "bom|";
5458static const char utf_prefix[] = "utf-";
5459enum {bom_prefix_len = (int)sizeof(bom_prefix) - 1};
5460enum {utf_prefix_len = (int)sizeof(utf_prefix) - 1};
5461
5462static int
5463io_encname_bom_p(const char *name, long len)
5464{
5465 return len > bom_prefix_len && STRNCASECMP(name, bom_prefix, bom_prefix_len) == 0;
5466}
5467
5468int
5469rb_io_modestr_fmode(const char *modestr)
5470{
5471 int fmode = 0;
5472 const char *m = modestr, *p = NULL;
5473
5474 switch (*m++) {
5475 case 'r':
5477 break;
5478 case 'w':
5480 break;
5481 case 'a':
5483 break;
5484 default:
5485 error:
5486 rb_raise(rb_eArgError, "invalid access mode %s", modestr);
5487 }
5488
5489 while (*m) {
5490 switch (*m++) {
5491 case 'b':
5493 break;
5494 case 't':
5496 break;
5497 case '+':
5499 break;
5500 case 'x':
5501 if (modestr[0] != 'w')
5502 goto error;
5503 fmode |= FMODE_EXCL;
5504 break;
5505 default:
5506 goto error;
5507 case ':':
5508 p = strchr(m, ':');
5509 if (io_encname_bom_p(m, p ? (long)(p - m) : (long)strlen(m)))
5511 goto finished;
5512 }
5513 }
5514
5515 finished:
5516 if ((fmode & FMODE_BINMODE) && (fmode & FMODE_TEXTMODE))
5517 goto error;
5518
5519 return fmode;
5520}
5521
5522int
5524{
5525 int fmode = 0;
5526
5527 switch (oflags & O_ACCMODE) {
5528 case O_RDONLY:
5530 break;
5531 case O_WRONLY:
5533 break;
5534 case O_RDWR:
5536 break;
5537 }
5538
5539 if (oflags & O_APPEND) {
5541 }
5542 if (oflags & O_TRUNC) {
5543 fmode |= FMODE_TRUNC;
5544 }
5545 if (oflags & O_CREAT) {
5547 }
5548 if (oflags & O_EXCL) {
5549 fmode |= FMODE_EXCL;
5550 }
5551#ifdef O_BINARY
5552 if (oflags & O_BINARY) {
5554 }
5555#endif
5556
5557 return fmode;
5558}
5559
5560static int
5561rb_io_fmode_oflags(int fmode)
5562{
5563 int oflags = 0;
5564
5565 switch (fmode & FMODE_READWRITE) {
5566 case FMODE_READABLE:
5567 oflags |= O_RDONLY;
5568 break;
5569 case FMODE_WRITABLE:
5570 oflags |= O_WRONLY;
5571 break;
5572 case FMODE_READWRITE:
5573 oflags |= O_RDWR;
5574 break;
5575 }
5576
5577 if (fmode & FMODE_APPEND) {
5578 oflags |= O_APPEND;
5579 }
5580 if (fmode & FMODE_TRUNC) {
5581 oflags |= O_TRUNC;
5582 }
5583 if (fmode & FMODE_CREATE) {
5584 oflags |= O_CREAT;
5585 }
5586 if (fmode & FMODE_EXCL) {
5587 oflags |= O_EXCL;
5588 }
5589#ifdef O_BINARY
5590 if (fmode & FMODE_BINMODE) {
5591 oflags |= O_BINARY;
5592 }
5593#endif
5594
5595 return oflags;
5596}
5597
5598int
5599rb_io_modestr_oflags(const char *modestr)
5600{
5601 return rb_io_fmode_oflags(rb_io_modestr_fmode(modestr));
5602}
5603
5604static const char*
5605rb_io_oflags_modestr(int oflags)
5606{
5607#ifdef O_BINARY
5608# define MODE_BINARY(a,b) ((oflags & O_BINARY) ? (b) : (a))
5609#else
5610# define MODE_BINARY(a,b) (a)
5611#endif
5612 int accmode;
5613 if (oflags & O_EXCL) {
5614 rb_raise(rb_eArgError, "exclusive access mode is not supported");
5615 }
5616 accmode = oflags & (O_RDONLY|O_WRONLY|O_RDWR);
5617 if (oflags & O_APPEND) {
5618 if (accmode == O_WRONLY) {
5619 return MODE_BINARY("a", "ab");
5620 }
5621 if (accmode == O_RDWR) {
5622 return MODE_BINARY("a+", "ab+");
5623 }
5624 }
5625 switch (accmode) {
5626 default:
5627 rb_raise(rb_eArgError, "invalid access oflags 0x%x", oflags);
5628 case O_RDONLY:
5629 return MODE_BINARY("r", "rb");
5630 case O_WRONLY:
5631 return MODE_BINARY("w", "wb");
5632 case O_RDWR:
5633 if (oflags & O_TRUNC) {
5634 return MODE_BINARY("w+", "wb+");
5635 }
5636 return MODE_BINARY("r+", "rb+");
5637 }
5638}
5639
5640/*
5641 * Convert external/internal encodings to enc/enc2
5642 * NULL => use default encoding
5643 * Qnil => no encoding specified (internal only)
5644 */
5645static void
5646rb_io_ext_int_to_encs(rb_encoding *ext, rb_encoding *intern, rb_encoding **enc, rb_encoding **enc2, int fmode)
5647{
5648 int default_ext = 0;
5649
5650 if (ext == NULL) {
5652 default_ext = 1;
5653 }
5654 if (ext == rb_ascii8bit_encoding()) {
5655 /* If external is ASCII-8BIT, no transcoding */
5656 intern = NULL;
5657 }
5658 else if (intern == NULL) {
5660 }
5661 if (intern == NULL || intern == (rb_encoding *)Qnil ||
5662 (!(fmode & FMODE_SETENC_BY_BOM) && (intern == ext))) {
5663 /* No internal encoding => use external + no transcoding */
5664 *enc = (default_ext && intern != ext) ? NULL : ext;
5665 *enc2 = NULL;
5666 }
5667 else {
5668 *enc = intern;
5669 *enc2 = ext;
5670 }
5671}
5672
5673static void
5674unsupported_encoding(const char *name, rb_encoding *enc)
5675{
5676 rb_enc_warn(enc, "Unsupported encoding %s ignored", name);
5677}
5678
5679static void
5680parse_mode_enc(const char *estr, rb_encoding *estr_enc,
5681 rb_encoding **enc_p, rb_encoding **enc2_p, int *fmode_p)
5682{
5683 const char *p;
5684 char encname[ENCODING_MAXNAMELEN+1];
5685 int idx, idx2;
5686 int fmode = fmode_p ? *fmode_p : 0;
5687 rb_encoding *ext_enc, *int_enc;
5688 long len;
5689
5690 /* parse estr as "enc" or "enc2:enc" or "enc:-" */
5691
5692 p = strrchr(estr, ':');
5693 len = p ? (p++ - estr) : (long)strlen(estr);
5694 if ((fmode & FMODE_SETENC_BY_BOM) || io_encname_bom_p(estr, len)) {
5695 estr += bom_prefix_len;
5697 if (!STRNCASECMP(estr, utf_prefix, utf_prefix_len)) {
5699 }
5700 else {
5701 rb_enc_warn(estr_enc, "BOM with non-UTF encoding %s is nonsense", estr);
5702 fmode &= ~FMODE_SETENC_BY_BOM;
5703 }
5704 }
5705 if (len == 0 || len > ENCODING_MAXNAMELEN) {
5706 idx = -1;
5707 }
5708 else {
5709 if (p) {
5710 memcpy(encname, estr, len);
5711 encname[len] = '\0';
5712 estr = encname;
5713 }
5714 idx = rb_enc_find_index(estr);
5715 }
5716 if (fmode_p) *fmode_p = fmode;
5717
5718 if (idx >= 0)
5719 ext_enc = rb_enc_from_index(idx);
5720 else {
5721 if (idx != -2)
5722 unsupported_encoding(estr, estr_enc);
5723 ext_enc = NULL;
5724 }
5725
5726 int_enc = NULL;
5727 if (p) {
5728 if (*p == '-' && *(p+1) == '\0') {
5729 /* Special case - "-" => no transcoding */
5730 int_enc = (rb_encoding *)Qnil;
5731 }
5732 else {
5733 idx2 = rb_enc_find_index(p);
5734 if (idx2 < 0)
5735 unsupported_encoding(p, estr_enc);
5736 else if (!(fmode & FMODE_SETENC_BY_BOM) && (idx2 == idx)) {
5737 int_enc = (rb_encoding *)Qnil;
5738 }
5739 else
5740 int_enc = rb_enc_from_index(idx2);
5741 }
5742 }
5743
5744 rb_io_ext_int_to_encs(ext_enc, int_enc, enc_p, enc2_p, fmode);
5745}
5746
5747int
5748rb_io_extract_encoding_option(VALUE opt, rb_encoding **enc_p, rb_encoding **enc2_p, int *fmode_p)
5749{
5750 VALUE encoding=Qnil, extenc=Qundef, intenc=Qundef, tmp;
5751 int extracted = 0;
5752 rb_encoding *extencoding = NULL;
5753 rb_encoding *intencoding = NULL;
5754
5755 if (!NIL_P(opt)) {
5756 VALUE v;
5757 v = rb_hash_lookup2(opt, sym_encoding, Qnil);
5758 if (v != Qnil) encoding = v;
5759 v = rb_hash_lookup2(opt, sym_extenc, Qundef);
5760 if (v != Qnil) extenc = v;
5761 v = rb_hash_lookup2(opt, sym_intenc, Qundef);
5762 if (v != Qundef) intenc = v;
5763 }
5764 if ((extenc != Qundef || intenc != Qundef) && !NIL_P(encoding)) {
5765 if (!NIL_P(ruby_verbose)) {
5766 int idx = rb_to_encoding_index(encoding);
5767 if (idx >= 0) encoding = rb_enc_from_encoding(rb_enc_from_index(idx));
5768 rb_warn("Ignoring encoding parameter '%"PRIsVALUE"': %s_encoding is used",
5769 encoding, extenc == Qundef ? "internal" : "external");
5770 }
5771 encoding = Qnil;
5772 }
5773 if (extenc != Qundef && !NIL_P(extenc)) {
5774 extencoding = rb_to_encoding(extenc);
5775 }
5776 if (intenc != Qundef) {
5777 if (NIL_P(intenc)) {
5778 /* internal_encoding: nil => no transcoding */
5779 intencoding = (rb_encoding *)Qnil;
5780 }
5781 else if (!NIL_P(tmp = rb_check_string_type(intenc))) {
5782 char *p = StringValueCStr(tmp);
5783
5784 if (*p == '-' && *(p+1) == '\0') {
5785 /* Special case - "-" => no transcoding */
5786 intencoding = (rb_encoding *)Qnil;
5787 }
5788 else {
5789 intencoding = rb_to_encoding(intenc);
5790 }
5791 }
5792 else {
5793 intencoding = rb_to_encoding(intenc);
5794 }
5795 if (extencoding == intencoding) {
5796 intencoding = (rb_encoding *)Qnil;
5797 }
5798 }
5799 if (!NIL_P(encoding)) {
5800 extracted = 1;
5801 if (!NIL_P(tmp = rb_check_string_type(encoding))) {
5802 parse_mode_enc(StringValueCStr(tmp), rb_enc_get(tmp),
5803 enc_p, enc2_p, fmode_p);
5804 }
5805 else {
5806 rb_io_ext_int_to_encs(rb_to_encoding(encoding), NULL, enc_p, enc2_p, 0);
5807 }
5808 }
5809 else if (extenc != Qundef || intenc != Qundef) {
5810 extracted = 1;
5811 rb_io_ext_int_to_encs(extencoding, intencoding, enc_p, enc2_p, 0);
5812 }
5813 return extracted;
5814}
5815
5817
5818static void
5819validate_enc_binmode(int *fmode_p, int ecflags, rb_encoding *enc, rb_encoding *enc2)
5820{
5821 int fmode = *fmode_p;
5822
5823 if ((fmode & FMODE_READABLE) &&
5824 !enc2 &&
5825 !(fmode & FMODE_BINMODE) &&
5827 rb_raise(rb_eArgError, "ASCII incompatible encoding needs binmode");
5828
5829 if ((fmode & FMODE_BINMODE) && (ecflags & ECONV_NEWLINE_DECORATOR_MASK)) {
5830 rb_raise(rb_eArgError, "newline decorator with binary mode");
5831 }
5832 if (!(fmode & FMODE_BINMODE) &&
5835 *fmode_p = fmode;
5836 }
5837#if !DEFAULT_TEXTMODE
5838 else if (!(ecflags & ECONV_NEWLINE_DECORATOR_MASK)) {
5839 fmode &= ~FMODE_TEXTMODE;
5840 *fmode_p = fmode;
5841 }
5842#endif
5843}
5844
5845static void
5846extract_binmode(VALUE opthash, int *fmode)
5847{
5848 if (!NIL_P(opthash)) {
5849 VALUE v;
5850 v = rb_hash_aref(opthash, sym_textmode);
5851 if (!NIL_P(v)) {
5852 if (*fmode & FMODE_TEXTMODE)
5853 rb_raise(rb_eArgError, "textmode specified twice");
5854 if (*fmode & FMODE_BINMODE)
5855 rb_raise(rb_eArgError, "both textmode and binmode specified");
5856 if (RTEST(v))
5858 }
5859 v = rb_hash_aref(opthash, sym_binmode);
5860 if (!NIL_P(v)) {
5861 if (*fmode & FMODE_BINMODE)
5862 rb_raise(rb_eArgError, "binmode specified twice");
5863 if (*fmode & FMODE_TEXTMODE)
5864 rb_raise(rb_eArgError, "both textmode and binmode specified");
5865 if (RTEST(v))
5866 *fmode |= FMODE_BINMODE;
5867 }
5868
5869 if ((*fmode & FMODE_BINMODE) && (*fmode & FMODE_TEXTMODE))
5870 rb_raise(rb_eArgError, "both textmode and binmode specified");
5871 }
5872}
5873
5874void
5875rb_io_extract_modeenc(VALUE *vmode_p, VALUE *vperm_p, VALUE opthash,
5876 int *oflags_p, int *fmode_p, convconfig_t *convconfig_p)
5877{
5878 VALUE vmode;
5879 int oflags, fmode;
5880 rb_encoding *enc, *enc2;
5881 int ecflags;
5882 VALUE ecopts;
5883 int has_enc = 0, has_vmode = 0;
5884 VALUE intmode;
5885
5886 vmode = *vmode_p;
5887
5888 /* Set to defaults */
5889 rb_io_ext_int_to_encs(NULL, NULL, &enc, &enc2, 0);
5890
5891 vmode_handle:
5892 if (NIL_P(vmode)) {
5894 oflags = O_RDONLY;
5895 }
5896 else if (!NIL_P(intmode = rb_check_to_integer(vmode, "to_int"))) {
5897 vmode = intmode;
5898 oflags = NUM2INT(intmode);
5899 fmode = rb_io_oflags_fmode(oflags);
5900 }
5901 else {
5902 const char *p;
5903
5904 SafeStringValue(vmode);
5905 p = StringValueCStr(vmode);
5907 oflags = rb_io_fmode_oflags(fmode);
5908 p = strchr(p, ':');
5909 if (p) {
5910 has_enc = 1;
5911 parse_mode_enc(p+1, rb_enc_get(vmode), &enc, &enc2, &fmode);
5912 }
5913 else {
5914 rb_encoding *e;
5915
5917 rb_io_ext_int_to_encs(e, NULL, &enc, &enc2, fmode);
5918 }
5919 }
5920
5921 if (NIL_P(opthash)) {
5922 ecflags = (fmode & FMODE_READABLE) ?
5925#ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
5926 ecflags |= (fmode & FMODE_WRITABLE) ?
5927 MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE,
5928 0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE) : 0;
5929#endif
5931 ecopts = Qnil;
5932 }
5933 else {
5934 VALUE v;
5935 if (!has_vmode) {
5936 v = rb_hash_aref(opthash, sym_mode);
5937 if (!NIL_P(v)) {
5938 if (!NIL_P(vmode)) {
5939 rb_raise(rb_eArgError, "mode specified twice");
5940 }
5941 has_vmode = 1;
5942 vmode = v;
5943 goto vmode_handle;
5944 }
5945 }
5946 v = rb_hash_aref(opthash, sym_flags);
5947 if (!NIL_P(v)) {
5948 v = rb_to_int(v);
5949 oflags |= NUM2INT(v);
5950 vmode = INT2NUM(oflags);
5951 fmode = rb_io_oflags_fmode(oflags);
5952 }
5953 extract_binmode(opthash, &fmode);
5954 if (fmode & FMODE_BINMODE) {
5955#ifdef O_BINARY
5956 oflags |= O_BINARY;
5957#endif
5958 if (!has_enc)
5959 rb_io_ext_int_to_encs(rb_ascii8bit_encoding(), NULL, &enc, &enc2, fmode);
5960 }
5961#if DEFAULT_TEXTMODE
5962 else if (NIL_P(vmode)) {
5964 }
5965#endif
5966 v = rb_hash_aref(opthash, sym_perm);
5967 if (!NIL_P(v)) {
5968 if (vperm_p) {
5969 if (!NIL_P(*vperm_p)) {
5970 rb_raise(rb_eArgError, "perm specified twice");
5971 }
5972 *vperm_p = v;
5973 }
5974 else {
5975 /* perm no use, just ignore */
5976 }
5977 }
5978 ecflags = (fmode & FMODE_READABLE) ?
5981#ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
5982 ecflags |= (fmode & FMODE_WRITABLE) ?
5983 MODE_BTMODE(TEXTMODE_NEWLINE_DECORATOR_ON_WRITE,
5984 0, TEXTMODE_NEWLINE_DECORATOR_ON_WRITE) : 0;
5985#endif
5986
5987 if (rb_io_extract_encoding_option(opthash, &enc, &enc2, &fmode)) {
5988 if (has_enc) {
5989 rb_raise(rb_eArgError, "encoding specified twice");
5990 }
5991 }
5993 ecflags = rb_econv_prepare_options(opthash, &ecopts, ecflags);
5994 }
5995
5996 validate_enc_binmode(&fmode, ecflags, enc, enc2);
5997
5998 *vmode_p = vmode;
5999
6000 *oflags_p = oflags;
6001 *fmode_p = fmode;
6002 convconfig_p->enc = enc;
6003 convconfig_p->enc2 = enc2;
6004 convconfig_p->ecflags = ecflags;
6005 convconfig_p->ecopts = ecopts;
6006}
6007
6012};
6013
6014static void *
6015sysopen_func(void *ptr)
6016{
6017 const struct sysopen_struct *data = ptr;
6018 const char *fname = RSTRING_PTR(data->fname);
6019 return (void *)(VALUE)rb_cloexec_open(fname, data->oflags, data->perm);
6020}
6021
6022static inline int
6023rb_sysopen_internal(struct sysopen_struct *data)
6024{
6025 int fd;
6026 fd = (int)(VALUE)rb_thread_call_without_gvl(sysopen_func, data, RUBY_UBF_IO, 0);
6027 if (0 <= fd)
6028 rb_update_max_fd(fd);
6029 return fd;
6030}
6031
6032static int
6033rb_sysopen(VALUE fname, int oflags, mode_t perm)
6034{
6035 int fd;
6036 struct sysopen_struct data;
6037
6039 StringValueCStr(data.fname);
6040 data.oflags = oflags;
6041 data.perm = perm;
6042
6043 fd = rb_sysopen_internal(&data);
6044 if (fd < 0) {
6045 int e = errno;
6046 if (rb_gc_for_fd(e)) {
6047 fd = rb_sysopen_internal(&data);
6048 }
6049 if (fd < 0) {
6051 }
6052 }
6053 return fd;
6054}
6055
6056FILE *
6057rb_fdopen(int fd, const char *modestr)
6058{
6059 FILE *file;
6060
6061#if defined(__sun)
6062 errno = 0;
6063#endif
6064 file = fdopen(fd, modestr);
6065 if (!file) {
6066 int e = errno;
6067#if defined(__sun)
6068 if (e == 0) {
6069 rb_gc();
6070 errno = 0;
6071 file = fdopen(fd, modestr);
6072 }
6073 else
6074#endif
6075 if (rb_gc_for_fd(e)) {
6076 file = fdopen(fd, modestr);
6077 }
6078 if (!file) {
6079#ifdef _WIN32
6080 if (e == 0) e = EINVAL;
6081#elif defined(__sun)
6082 if (e == 0) e = EMFILE;
6083#endif
6084 rb_syserr_fail(e, 0);
6085 }
6086 }
6087
6088 /* xxx: should be _IONBF? A buffer in FILE may have trouble. */
6089#ifdef USE_SETVBUF
6090 if (setvbuf(file, NULL, _IOFBF, 0) != 0)
6091 rb_warn("setvbuf() can't be honoured (fd=%d)", fd);
6092#endif
6093 return file;
6094}
6095
6096static int
6097io_check_tty(rb_io_t *fptr)
6098{
6099 int t = isatty(fptr->fd);
6100 if (t)
6101 fptr->mode |= FMODE_TTY|FMODE_DUPLEX;
6102 return t;
6103}
6104
6105static VALUE rb_io_internal_encoding(VALUE);
6106static void io_encoding_set(rb_io_t *, VALUE, VALUE, VALUE);
6107
6108static int
6109io_strip_bom(VALUE io)
6110{
6111 VALUE b1, b2, b3, b4;
6112 rb_io_t *fptr;
6113
6114 GetOpenFile(io, fptr);
6115 if (!(fptr->mode & FMODE_READABLE)) return 0;
6116 if (NIL_P(b1 = rb_io_getbyte(io))) return 0;
6117 switch (b1) {
6118 case INT2FIX(0xEF):
6119 if (NIL_P(b2 = rb_io_getbyte(io))) break;
6120 if (b2 == INT2FIX(0xBB) && !NIL_P(b3 = rb_io_getbyte(io))) {
6121 if (b3 == INT2FIX(0xBF)) {
6122 return rb_utf8_encindex();
6123 }
6124 rb_io_ungetbyte(io, b3);
6125 }
6126 rb_io_ungetbyte(io, b2);
6127 break;
6128
6129 case INT2FIX(0xFE):
6130 if (NIL_P(b2 = rb_io_getbyte(io))) break;
6131 if (b2 == INT2FIX(0xFF)) {
6132 return ENCINDEX_UTF_16BE;
6133 }
6134 rb_io_ungetbyte(io, b2);
6135 break;
6136
6137 case INT2FIX(0xFF):
6138 if (NIL_P(b2 = rb_io_getbyte(io))) break;
6139 if (b2 == INT2FIX(0xFE)) {
6140 b3 = rb_io_getbyte(io);
6141 if (b3 == INT2FIX(0) && !NIL_P(b4 = rb_io_getbyte(io))) {
6142 if (b4 == INT2FIX(0)) {
6143 return ENCINDEX_UTF_32LE;
6144 }
6145 rb_io_ungetbyte(io, b4);
6146 }
6147 rb_io_ungetbyte(io, b3);
6148 return ENCINDEX_UTF_16LE;
6149 }
6150 rb_io_ungetbyte(io, b2);
6151 break;
6152
6153 case INT2FIX(0):
6154 if (NIL_P(b2 = rb_io_getbyte(io))) break;
6155 if (b2 == INT2FIX(0) && !NIL_P(b3 = rb_io_getbyte(io))) {
6156 if (b3 == INT2FIX(0xFE) && !NIL_P(b4 = rb_io_getbyte(io))) {
6157 if (b4 == INT2FIX(0xFF)) {
6158 return ENCINDEX_UTF_32BE;
6159 }
6160 rb_io_ungetbyte(io, b4);
6161 }
6162 rb_io_ungetbyte(io, b3);
6163 }
6164 rb_io_ungetbyte(io, b2);
6165 break;
6166 }
6167 rb_io_ungetbyte(io, b1);
6168 return 0;
6169}
6170
6171static rb_encoding *
6172io_set_encoding_by_bom(VALUE io)
6173{
6174 int idx = io_strip_bom(io);
6175 rb_io_t *fptr;
6176 rb_encoding *extenc = NULL;
6177
6178 GetOpenFile(io, fptr);
6179 if (idx) {
6180 extenc = rb_enc_from_index(idx);
6181 io_encoding_set(fptr, rb_enc_from_encoding(extenc),
6182 rb_io_internal_encoding(io), Qnil);
6183 }
6184 else {
6185 fptr->encs.enc2 = NULL;
6186 }
6187 return extenc;
6188}
6189
6190static VALUE
6191rb_file_open_generic(VALUE io, VALUE filename, int oflags, int fmode,
6192 const convconfig_t *convconfig, mode_t perm)
6193{
6194 VALUE pathv;
6195 rb_io_t *fptr;
6197 if (!convconfig) {
6198 /* Set to default encodings */
6199 rb_io_ext_int_to_encs(NULL, NULL, &cc.enc, &cc.enc2, fmode);
6200 cc.ecflags = 0;
6201 cc.ecopts = Qnil;
6202 convconfig = &cc;
6203 }
6204 validate_enc_binmode(&fmode, convconfig->ecflags,
6205 convconfig->enc, convconfig->enc2);
6206
6207 MakeOpenFile(io, fptr);
6208 fptr->mode = fmode;
6209 fptr->encs = *convconfig;
6210 pathv = rb_str_new_frozen(filename);
6211#ifdef O_TMPFILE
6212 if (!(oflags & O_TMPFILE)) {
6213 fptr->pathv = pathv;
6214 }
6215#else
6216 fptr->pathv = pathv;
6217#endif
6218 fptr->fd = rb_sysopen(pathv, oflags, perm);
6219 io_check_tty(fptr);
6220 if (fmode & FMODE_SETENC_BY_BOM) io_set_encoding_by_bom(io);
6221
6222 return io;
6223}
6224
6225static VALUE
6226rb_file_open_internal(VALUE io, VALUE filename, const char *modestr)
6227{
6228 int fmode = rb_io_modestr_fmode(modestr);
6229 const char *p = strchr(modestr, ':');
6230 convconfig_t convconfig;
6231
6232 if (p) {
6233 parse_mode_enc(p+1, rb_usascii_encoding(),
6234 &convconfig.enc, &convconfig.enc2, &fmode);
6235 convconfig.ecflags = 0;
6236 convconfig.ecopts = Qnil;
6237 }
6238 else {
6239 rb_encoding *e;
6240 /* Set to default encodings */
6241
6243 rb_io_ext_int_to_encs(e, NULL, &convconfig.enc, &convconfig.enc2, fmode);
6244 convconfig.ecflags = 0;
6245 convconfig.ecopts = Qnil;
6246 }
6247
6248 return rb_file_open_generic(io, filename,
6249 rb_io_fmode_oflags(fmode),
6250 fmode,
6251 &convconfig,
6252 0666);
6253}
6254
6255VALUE
6256rb_file_open_str(VALUE fname, const char *modestr)
6257{
6259 return rb_file_open_internal(io_alloc(rb_cFile), fname, modestr);
6260}
6261
6262VALUE
6263rb_file_open(const char *fname, const char *modestr)
6264{
6265 return rb_file_open_internal(io_alloc(rb_cFile), rb_str_new_cstr(fname), modestr);
6266}
6267
6268#if defined(__CYGWIN__) || !defined(HAVE_WORKING_FORK)
6269static struct pipe_list {
6270 rb_io_t *fptr;
6271 struct pipe_list *next;
6272} *pipe_list;
6273
6274static void
6275pipe_add_fptr(rb_io_t *fptr)
6276{
6277 struct pipe_list *list;
6278
6279 list = ALLOC(struct pipe_list);
6280 list->fptr = fptr;
6281 list->next = pipe_list;
6282 pipe_list = list;
6283}
6284
6285static void
6286pipe_del_fptr(rb_io_t *fptr)
6287{
6288 struct pipe_list **prev = &pipe_list;
6289 struct pipe_list *tmp;
6290
6291 while ((tmp = *prev) != 0) {
6292 if (tmp->fptr == fptr) {
6293 *prev = tmp->next;
6294 free(tmp);
6295 return;
6296 }
6297 prev = &tmp->next;
6298 }
6299}
6300
6301#if defined (_WIN32) || defined(__CYGWIN__)
6302static void
6303pipe_atexit(void)
6304{
6305 struct pipe_list *list = pipe_list;
6306 struct pipe_list *tmp;
6307
6308 while (list) {
6309 tmp = list->next;
6311 list = tmp;
6312 }
6313}
6314#endif
6315
6316static void
6317pipe_finalize(rb_io_t *fptr, int noraise)
6318{
6319#if !defined(HAVE_WORKING_FORK) && !defined(_WIN32)
6320 int status = 0;
6321 if (fptr->stdio_file) {
6322 status = pclose(fptr->stdio_file);
6323 }
6324 fptr->fd = -1;
6325 fptr->stdio_file = 0;
6326 rb_last_status_set(status, fptr->pid);
6327#else
6328 fptr_finalize(fptr, noraise);
6329#endif
6330 pipe_del_fptr(fptr);
6331}
6332#endif
6333
6334static void
6335fptr_copy_finalizer(rb_io_t *fptr, const rb_io_t *orig)
6336{
6337#if defined(__CYGWIN__) || !defined(HAVE_WORKING_FORK)
6338 void (*const old_finalize)(struct rb_io_t*,int) = fptr->finalize;
6339
6340 if (old_finalize == orig->finalize) return;
6341#endif
6342
6343 fptr->finalize = orig->finalize;
6344
6345#if defined(__CYGWIN__) || !defined(HAVE_WORKING_FORK)
6346 if (old_finalize != pipe_finalize) {
6347 struct pipe_list *list;
6348 for (list = pipe_list; list; list = list->next) {
6349 if (list->fptr == fptr) break;
6350 }
6351 if (!list) pipe_add_fptr(fptr);
6352 }
6353 else {
6354 pipe_del_fptr(fptr);
6355 }
6356#endif
6357}
6358
6359void
6361{
6363 fptr->mode |= FMODE_SYNC;
6364}
6365
6366void
6368{
6369 rb_io_synchronized(fptr);
6370}
6371
6372int
6373rb_pipe(int *pipes)
6374{
6375 int ret;
6376 ret = rb_cloexec_pipe(pipes);
6377 if (ret < 0) {
6378 if (rb_gc_for_fd(errno)) {
6379 ret = rb_cloexec_pipe(pipes);
6380 }
6381 }
6382 if (ret == 0) {
6383 rb_update_max_fd(pipes[0]);
6384 rb_update_max_fd(pipes[1]);
6385 }
6386 return ret;
6387}
6388
6389#ifdef _WIN32
6390#define HAVE_SPAWNV 1
6391#define spawnv(mode, cmd, args) rb_w32_uaspawn((mode), (cmd), (args))
6392#define spawn(mode, cmd) rb_w32_uspawn((mode), (cmd), 0)
6393#endif
6394
6395#if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
6396struct popen_arg {
6397 VALUE execarg_obj;
6398 struct rb_execarg *eargp;
6399 int modef;
6400 int pair[2];
6401 int write_pair[2];
6402};
6403#endif
6404
6405#ifdef HAVE_WORKING_FORK
6406static void
6407popen_redirect(struct popen_arg *p)
6408{
6409 if ((p->modef & FMODE_READABLE) && (p->modef & FMODE_WRITABLE)) {
6410 close(p->write_pair[1]);
6411 if (p->write_pair[0] != 0) {
6412 dup2(p->write_pair[0], 0);
6413 close(p->write_pair[0]);
6414 }
6415 close(p->pair[0]);
6416 if (p->pair[1] != 1) {
6417 dup2(p->pair[1], 1);
6418 close(p->pair[1]);
6419 }
6420 }
6421 else if (p->modef & FMODE_READABLE) {
6422 close(p->pair[0]);
6423 if (p->pair[1] != 1) {
6424 dup2(p->pair[1], 1);
6425 close(p->pair[1]);
6426 }
6427 }
6428 else {
6429 close(p->pair[1]);
6430 if (p->pair[0] != 0) {
6431 dup2(p->pair[0], 0);
6432 close(p->pair[0]);
6433 }
6434 }
6435}
6436
6437#if defined(__linux__)
6438/* Linux /proc/self/status contains a line: "FDSize:\t<nnn>\n"
6439 * Since /proc may not be available, linux_get_maxfd is just a hint.
6440 * This function, linux_get_maxfd, must be async-signal-safe.
6441 * I.e. opendir() is not usable.
6442 *
6443 * Note that memchr() and memcmp is *not* async-signal-safe in POSIX.
6444 * However they are easy to re-implement in async-signal-safe manner.
6445 * (Also note that there is missing/memcmp.c.)
6446 */
6447static int
6448linux_get_maxfd(void)
6449{
6450 int fd;
6451 char buf[4096], *p, *np, *e;
6452 ssize_t ss;
6453 fd = rb_cloexec_open("/proc/self/status", O_RDONLY|O_NOCTTY, 0);
6454 if (fd < 0) return fd;
6455 ss = read(fd, buf, sizeof(buf));
6456 if (ss < 0) goto err;
6457 p = buf;
6458 e = buf + ss;
6459 while ((int)sizeof("FDSize:\t0\n")-1 <= e-p &&
6460 (np = memchr(p, '\n', e-p)) != NULL) {
6461 if (memcmp(p, "FDSize:", sizeof("FDSize:")-1) == 0) {
6462 int fdsize;
6463 p += sizeof("FDSize:")-1;
6464 *np = '\0';
6465 fdsize = (int)ruby_strtoul(p, (char **)NULL, 10);
6466 close(fd);
6467 return fdsize;
6468 }
6469 p = np+1;
6470 }
6471 /* fall through */
6472
6473 err:
6474 close(fd);
6475 return (int)ss;
6476}
6477#endif
6478
6479/* This function should be async-signal-safe. */
6480void
6481rb_close_before_exec(int lowfd, int maxhint, VALUE noclose_fds)
6482{
6483#if defined(HAVE_FCNTL) && defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
6484 int fd, ret;
6485 int max = (int)max_file_descriptor;
6486# ifdef F_MAXFD
6487 /* F_MAXFD is available since NetBSD 2.0. */
6488 ret = fcntl(0, F_MAXFD); /* async-signal-safe */
6489 if (ret != -1)
6490 maxhint = max = ret;
6491# elif defined(__linux__)
6492 ret = linux_get_maxfd();
6493 if (maxhint < ret)
6494 maxhint = ret;
6495 /* maxhint = max = ret; if (ret == -1) abort(); // test */
6496# endif
6497 if (max < maxhint)
6498 max = maxhint;
6499 for (fd = lowfd; fd <= max; fd++) {
6500 if (!NIL_P(noclose_fds) &&
6501 RTEST(rb_hash_lookup(noclose_fds, INT2FIX(fd)))) /* async-signal-safe */
6502 continue;
6503 ret = fcntl(fd, F_GETFD); /* async-signal-safe */
6504 if (ret != -1 && !(ret & FD_CLOEXEC)) {
6505 fcntl(fd, F_SETFD, ret|FD_CLOEXEC); /* async-signal-safe */
6506 }
6507# define CONTIGUOUS_CLOSED_FDS 20
6508 if (ret != -1) {
6509 if (max < fd + CONTIGUOUS_CLOSED_FDS)
6510 max = fd + CONTIGUOUS_CLOSED_FDS;
6511 }
6512 }
6513#endif
6514}
6515
6516static int
6517popen_exec(void *pp, char *errmsg, size_t errmsg_len)
6518{
6519 struct popen_arg *p = (struct popen_arg*)pp;
6520
6521 return rb_exec_async_signal_safe(p->eargp, errmsg, errmsg_len);
6522}
6523#endif
6524
6525#if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
6526static VALUE
6527rb_execarg_fixup_v(VALUE execarg_obj)
6528{
6529 rb_execarg_parent_start(execarg_obj);
6530 return Qnil;
6531}
6532#else
6533char *rb_execarg_commandline(const struct rb_execarg *eargp, VALUE *prog);
6534#endif
6535
6536static VALUE
6537pipe_open(VALUE execarg_obj, const char *modestr, int fmode,
6538 const convconfig_t *convconfig)
6539{
6540 struct rb_execarg *eargp = NIL_P(execarg_obj) ? NULL : rb_execarg_get(execarg_obj);
6541 VALUE prog = eargp ? (eargp->use_shell ? eargp->invoke.sh.shell_script : eargp->invoke.cmd.command_name) : Qfalse ;
6542 rb_pid_t pid = 0;
6543 rb_io_t *fptr;
6544 VALUE port;
6545 rb_io_t *write_fptr;
6546 VALUE write_port;
6547#if defined(HAVE_WORKING_FORK)
6548 int status;
6549 char errmsg[80] = { '\0' };
6550#endif
6551#if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
6552 int state;
6553 struct popen_arg arg;
6554#endif
6555 int e = 0;
6556#if defined(HAVE_SPAWNV)
6557# if defined(HAVE_SPAWNVE)
6558# define DO_SPAWN(cmd, args, envp) ((args) ? \
6559 spawnve(P_NOWAIT, (cmd), (args), (envp)) : \
6560 spawne(P_NOWAIT, (cmd), (envp)))
6561# else
6562# define DO_SPAWN(cmd, args, envp) ((args) ? \
6563 spawnv(P_NOWAIT, (cmd), (args)) : \
6564 spawn(P_NOWAIT, (cmd)))
6565# endif
6566# if !defined(HAVE_WORKING_FORK)
6567 char **args = NULL;
6568# if defined(HAVE_SPAWNVE)
6569 char **envp = NULL;
6570# endif
6571# endif
6572#endif
6573#if !defined(HAVE_WORKING_FORK)
6574 struct rb_execarg sarg, *sargp = &sarg;
6575#endif
6576 FILE *fp = 0;
6577 int fd = -1;
6578 int write_fd = -1;
6579#if !defined(HAVE_WORKING_FORK)
6580 const char *cmd = 0;
6581
6582 if (prog)
6583 cmd = StringValueCStr(prog);
6584#endif
6585
6586#if defined(HAVE_WORKING_FORK) || defined(HAVE_SPAWNV)
6587 arg.execarg_obj = execarg_obj;
6588 arg.eargp = eargp;
6589 arg.modef = fmode;
6590 arg.pair[0] = arg.pair[1] = -1;
6591 arg.write_pair[0] = arg.write_pair[1] = -1;
6592# if !defined(HAVE_WORKING_FORK)
6593 if (eargp && !eargp->use_shell) {
6594 args = ARGVSTR2ARGV(eargp->invoke.cmd.argv_str);
6595 }
6596# endif
6597 switch (fmode & (FMODE_READABLE|FMODE_WRITABLE)) {
6599 if (rb_pipe(arg.write_pair) < 0)
6600 rb_sys_fail_str(prog);
6601 if (rb_pipe(arg.pair) < 0) {
6602 e = errno;
6603 close(arg.write_pair[0]);
6604 close(arg.write_pair[1]);
6605 rb_syserr_fail_str(e, prog);
6606 }
6607 if (eargp) {
6608 rb_execarg_addopt(execarg_obj, INT2FIX(0), INT2FIX(arg.write_pair[0]));
6609 rb_execarg_addopt(execarg_obj, INT2FIX(1), INT2FIX(arg.pair[1]));
6610 }
6611 break;
6612 case FMODE_READABLE:
6613 if (rb_pipe(arg.pair) < 0)
6614 rb_sys_fail_str(prog);
6615 if (eargp)
6616 rb_execarg_addopt(execarg_obj, INT2FIX(1), INT2FIX(arg.pair[1]));
6617 break;
6618 case FMODE_WRITABLE:
6619 if (rb_pipe(arg.pair) < 0)
6620 rb_sys_fail_str(prog);
6621 if (eargp)
6622 rb_execarg_addopt(execarg_obj, INT2FIX(0), INT2FIX(arg.pair[0]));
6623 break;
6624 default:
6625 rb_sys_fail_str(prog);
6626 }
6627 if (!NIL_P(execarg_obj)) {
6628 rb_protect(rb_execarg_fixup_v, execarg_obj, &state);
6629 if (state) {
6630 if (0 <= arg.write_pair[0]) close(arg.write_pair[0]);
6631 if (0 <= arg.write_pair[1]) close(arg.write_pair[1]);
6632 if (0 <= arg.pair[0]) close(arg.pair[0]);
6633 if (0 <= arg.pair[1]) close(arg.pair[1]);
6634 rb_execarg_parent_end(execarg_obj);
6635 rb_jump_tag(state);
6636 }
6637
6638# if defined(HAVE_WORKING_FORK)
6639 pid = rb_fork_async_signal_safe(&status, popen_exec, &arg, arg.eargp->redirect_fds, errmsg, sizeof(errmsg));
6640# else
6641 rb_execarg_run_options(eargp, sargp, NULL, 0);
6642# if defined(HAVE_SPAWNVE)
6643 if (eargp->envp_str) envp = (char **)RSTRING_PTR(eargp->envp_str);
6644# endif
6645 while ((pid = DO_SPAWN(cmd, args, envp)) < 0) {
6646 /* exec failed */
6647 switch (e = errno) {
6648 case EAGAIN:
6649# if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
6650 case EWOULDBLOCK:
6651# endif
6652 rb_thread_sleep(1);
6653 continue;
6654 }
6655 break;
6656 }
6657 if (eargp)
6658 rb_execarg_run_options(sargp, NULL, NULL, 0);
6659# endif
6660 rb_execarg_parent_end(execarg_obj);
6661 }
6662 else {
6663# if defined(HAVE_WORKING_FORK)
6664 pid = rb_fork_ruby(&status);
6665 if (pid == 0) { /* child */
6667 popen_redirect(&arg);
6668 rb_io_synchronized(RFILE(orig_stdout)->fptr);
6669 rb_io_synchronized(RFILE(orig_stderr)->fptr);
6670 return Qnil;
6671 }
6672# else
6674# endif
6675 }
6676
6677 /* parent */
6678 if (pid < 0) {
6679# if defined(HAVE_WORKING_FORK)
6680 e = errno;
6681# endif
6682 close(arg.pair[0]);
6683 close(arg.pair[1]);
6685 close(arg.write_pair[0]);
6686 close(arg.write_pair[1]);
6687 }
6688# if defined(HAVE_WORKING_FORK)
6689 if (errmsg[0])
6690 rb_syserr_fail(e, errmsg);
6691# endif
6692 rb_syserr_fail_str(e, prog);
6693 }
6694 if ((fmode & FMODE_READABLE) && (fmode & FMODE_WRITABLE)) {
6695 close(arg.pair[1]);
6696 fd = arg.pair[0];
6697 close(arg.write_pair[0]);
6698 write_fd = arg.write_pair[1];
6699 }
6700 else if (fmode & FMODE_READABLE) {
6701 close(arg.pair[1]);
6702 fd = arg.pair[0];
6703 }
6704 else {
6705 close(arg.pair[0]);
6706 fd = arg.pair[1];
6707 }
6708#else
6709 cmd = rb_execarg_commandline(eargp, &prog);
6710 if (!NIL_P(execarg_obj)) {
6711 rb_execarg_parent_start(execarg_obj);
6712 rb_execarg_run_options(eargp, sargp, NULL, 0);
6713 }
6714 fp = popen(cmd, modestr);
6715 e = errno;
6716 if (eargp) {
6717 rb_execarg_parent_end(execarg_obj);
6718 rb_execarg_run_options(sargp, NULL, NULL, 0);
6719 }
6720 if (!fp) rb_syserr_fail_path(e, prog);
6721 fd = fileno(fp);
6722#endif
6723
6724 port = io_alloc(rb_cIO);
6725 MakeOpenFile(port, fptr);
6726 fptr->fd = fd;
6727 fptr->stdio_file = fp;
6729 if (convconfig) {
6730 fptr->encs = *convconfig;
6731#if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
6734 }
6735#endif
6736 }
6737 else {
6740 }
6741#ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
6743 fptr->encs.ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
6744 }
6745#endif
6746 }
6747 fptr->pid = pid;
6748
6749 if (0 <= write_fd) {
6750 write_port = io_alloc(rb_cIO);
6751 MakeOpenFile(write_port, write_fptr);
6752 write_fptr->fd = write_fd;
6753 write_fptr->mode = (fmode & ~FMODE_READABLE)| FMODE_SYNC|FMODE_DUPLEX;
6754 fptr->mode &= ~FMODE_WRITABLE;
6755 fptr->tied_io_for_writing = write_port;
6756 rb_ivar_set(port, rb_intern("@tied_io_for_writing"), write_port);
6757 }
6758
6759#if defined (__CYGWIN__) || !defined(HAVE_WORKING_FORK)
6760 fptr->finalize = pipe_finalize;
6761 pipe_add_fptr(fptr);
6762#endif
6763 return port;
6764}
6765
6766static int
6767is_popen_fork(VALUE prog)
6768{
6769 if (RSTRING_LEN(prog) == 1 && RSTRING_PTR(prog)[0] == '-') {
6770#if !defined(HAVE_WORKING_FORK)
6772 "fork() function is unimplemented on this machine");
6773#else
6774 return TRUE;
6775#endif
6776 }
6777 return FALSE;
6778}
6779
6780static VALUE
6781pipe_open_s(VALUE prog, const char *modestr, int fmode,
6782 const convconfig_t *convconfig)
6783{
6784 int argc = 1;
6785 VALUE *argv = &prog;
6786 VALUE execarg_obj = Qnil;
6787
6788 if (!is_popen_fork(prog))
6789 execarg_obj = rb_execarg_new(argc, argv, TRUE, FALSE);
6790 return pipe_open(execarg_obj, modestr, fmode, convconfig);
6791}
6792
6793static VALUE
6794pipe_close(VALUE io)
6795{
6796 rb_io_t *fptr = io_close_fptr(io);
6797 if (fptr) {
6798 fptr_waitpid(fptr, rb_thread_to_be_killed(rb_thread_current()));
6799 }
6800 return Qnil;
6801}
6802
6803/*
6804 * call-seq:
6805 * IO.popen([env,] cmd, mode="r" [, opt]) -> io
6806 * IO.popen([env,] cmd, mode="r" [, opt]) {|io| block } -> obj
6807 *
6808 * Runs the specified command as a subprocess; the subprocess's
6809 * standard input and output will be connected to the returned
6810 * IO object.
6811 *
6812 * The PID of the started process can be obtained by IO#pid method.
6813 *
6814 * _cmd_ is a string or an array as follows.
6815 *
6816 * cmd:
6817 * "-" : fork
6818 * commandline : command line string which is passed to a shell
6819 * [env, cmdname, arg1, ..., opts] : command name and zero or more arguments (no shell)
6820 * [env, [cmdname, argv0], arg1, ..., opts] : command name, argv[0] and zero or more arguments (no shell)
6821 * (env and opts are optional.)
6822 *
6823 * If _cmd_ is a +String+ ``<code>-</code>'',
6824 * then a new instance of Ruby is started as the subprocess.
6825 *
6826 * If <i>cmd</i> is an +Array+ of +String+,
6827 * then it will be used as the subprocess's +argv+ bypassing a shell.
6828 * The array can contain a hash at first for environments and
6829 * a hash at last for options similar to #spawn.
6830 *
6831 * The default mode for the new file object is ``r'',
6832 * but <i>mode</i> may be set to any of the modes listed in the description for class IO.
6833 * The last argument <i>opt</i> qualifies <i>mode</i>.
6834 *
6835 * # set IO encoding
6836 * IO.popen("nkf -e filename", :external_encoding=>"EUC-JP") {|nkf_io|
6837 * euc_jp_string = nkf_io.read
6838 * }
6839 *
6840 * # merge standard output and standard error using
6841 * # spawn option. See the document of Kernel.spawn.
6842 * IO.popen(["ls", "/", :err=>[:child, :out]]) {|ls_io|
6843 * ls_result_with_error = ls_io.read
6844 * }
6845 *
6846 * # spawn options can be mixed with IO options
6847 * IO.popen(["ls", "/"], :err=>[:child, :out]) {|ls_io|
6848 * ls_result_with_error = ls_io.read
6849 * }
6850 *
6851 * Raises exceptions which IO.pipe and Kernel.spawn raise.
6852 *
6853 * If a block is given, Ruby will run the command as a child connected
6854 * to Ruby with a pipe. Ruby's end of the pipe will be passed as a
6855 * parameter to the block.
6856 * At the end of block, Ruby closes the pipe and sets <code>$?</code>.
6857 * In this case IO.popen returns the value of the block.
6858 *
6859 * If a block is given with a _cmd_ of ``<code>-</code>'',
6860 * the block will be run in two separate processes: once in the parent,
6861 * and once in a child. The parent process will be passed the pipe
6862 * object as a parameter to the block, the child version of the block
6863 * will be passed +nil+, and the child's standard in and
6864 * standard out will be connected to the parent through the pipe. Not
6865 * available on all platforms.
6866 *
6867 * f = IO.popen("uname")
6868 * p f.readlines
6869 * f.close
6870 * puts "Parent is #{Process.pid}"
6871 * IO.popen("date") {|f| puts f.gets }
6872 * IO.popen("-") {|f| $stderr.puts "#{Process.pid} is here, f is #{f.inspect}"}
6873 * p $?
6874 * IO.popen(%w"sed -e s|^|<foo>| -e s&$&;zot;&", "r+") {|f|
6875 * f.puts "bar"; f.close_write; puts f.gets
6876 * }
6877 *
6878 * <em>produces:</em>
6879 *
6880 * ["Linux\n"]
6881 * Parent is 21346
6882 * Thu Jan 15 22:41:19 JST 2009
6883 * 21346 is here, f is #<IO:fd 3>
6884 * 21352 is here, f is nil
6885 * #<Process::Status: pid 21352 exit 0>
6886 * <foo>bar;zot;
6887 */
6888
6889static VALUE
6890rb_io_s_popen(int argc, VALUE *argv, VALUE klass)
6891{
6892 const char *modestr;
6893 VALUE pname, pmode = Qnil, port, tmp, opt = Qnil, env = Qnil, execarg_obj = Qnil;
6894 int oflags, fmode;
6895 convconfig_t convconfig;
6896
6897 if (argc > 1 && !NIL_P(opt = rb_check_hash_type(argv[argc-1]))) --argc;
6898 if (argc > 1 && !NIL_P(env = rb_check_hash_type(argv[0]))) --argc, ++argv;
6899 switch (argc) {
6900 case 2:
6901 pmode = argv[1];
6902 case 1:
6903 pname = argv[0];
6904 break;
6905 default:
6906 {
6907 int ex = !NIL_P(opt);
6908 rb_error_arity(argc + ex, 1 + ex, 2 + ex);
6909 }
6910 }
6911
6912 tmp = rb_check_array_type(pname);
6913 if (!NIL_P(tmp)) {
6914 long len = RARRAY_LEN(tmp);
6915#if SIZEOF_LONG > SIZEOF_INT
6916 if (len > INT_MAX) {
6917 rb_raise(rb_eArgError, "too many arguments");
6918 }
6919#endif
6920 execarg_obj = rb_execarg_new((int)len, RARRAY_CONST_PTR(tmp), FALSE, FALSE);
6921 RB_GC_GUARD(tmp);
6922 }
6923 else {
6924 SafeStringValue(pname);
6925 execarg_obj = Qnil;
6926 if (!is_popen_fork(pname))
6927 execarg_obj = rb_execarg_new(1, &pname, TRUE, FALSE);
6928 }
6929 if (!NIL_P(execarg_obj)) {
6930 if (!NIL_P(opt))
6931 opt = rb_execarg_extract_options(execarg_obj, opt);
6932 if (!NIL_P(env))
6933 rb_execarg_setenv(execarg_obj, env);
6934 }
6935 rb_io_extract_modeenc(&pmode, 0, opt, &oflags, &fmode, &convconfig);
6936 modestr = rb_io_oflags_modestr(oflags);
6937
6938 port = pipe_open(execarg_obj, modestr, fmode, &convconfig);
6939 if (NIL_P(port)) {
6940 /* child */
6941 if (rb_block_given_p()) {
6942 rb_yield(Qnil);
6945 _exit(0);
6946 }
6947 return Qnil;
6948 }
6949 RBASIC_SET_CLASS(port, klass);
6950 if (rb_block_given_p()) {
6951 return rb_ensure(rb_yield, port, pipe_close, port);
6952 }
6953 return port;
6954}
6955
6956static void
6957rb_scan_open_args(int argc, const VALUE *argv,
6958 VALUE *fname_p, int *oflags_p, int *fmode_p,
6959 convconfig_t *convconfig_p, mode_t *perm_p)
6960{
6961 VALUE opt, fname, vmode, vperm;
6962 int oflags, fmode;
6963 mode_t perm;
6964
6965 argc = rb_scan_args(argc, argv, "12:", &fname, &vmode, &vperm, &opt);
6966 FilePathValue(fname);
6967
6968 rb_io_extract_modeenc(&vmode, &vperm, opt, &oflags, &fmode, convconfig_p);
6969
6970 perm = NIL_P(vperm) ? 0666 : NUM2MODET(vperm);
6971
6972 *fname_p = fname;
6973 *oflags_p = oflags;
6974 *fmode_p = fmode;
6975 *perm_p = perm;
6976}
6977
6978static VALUE
6979rb_open_file(int argc, const VALUE *argv, VALUE io)
6980{
6981 VALUE fname;
6982 int oflags, fmode;
6983 convconfig_t convconfig;
6984 mode_t perm;
6985
6986 rb_scan_open_args(argc, argv, &fname, &oflags, &fmode, &convconfig, &perm);
6987 rb_file_open_generic(io, fname, oflags, fmode, &convconfig, perm);
6988
6989 return io;
6990}
6991
6992
6993/*
6994 * Document-method: File::open
6995 *
6996 * call-seq:
6997 * File.open(filename, mode="r" [, opt]) -> file
6998 * File.open(filename [, mode [, perm]] [, opt]) -> file
6999 * File.open(filename, mode="r" [, opt]) {|file| block } -> obj
7000 * File.open(filename [, mode [, perm]] [, opt]) {|file| block } -> obj
7001 *
7002 * With no associated block, File.open is a synonym for
7003 * File.new. If the optional code block is given, it will
7004 * be passed the opened +file+ as an argument and the File object will
7005 * automatically be closed when the block terminates. The value of the block
7006 * will be returned from File.open.
7007 *
7008 * If a file is being created, its initial permissions may be set using the
7009 * +perm+ parameter. See File.new for further discussion.
7010 *
7011 * See IO.new for a description of the +mode+ and +opt+ parameters.
7012 */
7013
7014/*
7015 * Document-method: IO::open
7016 *
7017 * call-seq:
7018 * IO.open(fd, mode="r" [, opt]) -> io
7019 * IO.open(fd, mode="r" [, opt]) {|io| block } -> obj
7020 *
7021 * With no associated block, IO.open is a synonym for IO.new. If
7022 * the optional code block is given, it will be passed +io+ as an argument,
7023 * and the IO object will automatically be closed when the block terminates.
7024 * In this instance, IO.open returns the value of the block.
7025 *
7026 * See IO.new for a description of the +fd+, +mode+ and +opt+ parameters.
7027 */
7028
7029static VALUE
7030rb_io_s_open(int argc, VALUE *argv, VALUE klass)
7031{
7033
7034 if (rb_block_given_p()) {
7035 return rb_ensure(rb_yield, io, io_close, io);
7036 }
7037
7038 return io;
7039}
7040
7041/*
7042 * call-seq:
7043 * IO.sysopen(path, [mode, [perm]]) -> integer
7044 *
7045 * Opens the given path, returning the underlying file descriptor as a
7046 * Integer.
7047 *
7048 * IO.sysopen("testfile") #=> 3
7049 */
7050
7051static VALUE
7052rb_io_s_sysopen(int argc, VALUE *argv, VALUE _)
7053{
7054 VALUE fname, vmode, vperm;
7055 VALUE intmode;
7056 int oflags, fd;
7057 mode_t perm;
7058
7059 rb_scan_args(argc, argv, "12", &fname, &vmode, &vperm);
7060 FilePathValue(fname);
7061
7062 if (NIL_P(vmode))
7063 oflags = O_RDONLY;
7064 else if (!NIL_P(intmode = rb_check_to_integer(vmode, "to_int")))
7065 oflags = NUM2INT(intmode);
7066 else {
7067 SafeStringValue(vmode);
7068 oflags = rb_io_modestr_oflags(StringValueCStr(vmode));
7069 }
7070 if (NIL_P(vperm)) perm = 0666;
7071 else perm = NUM2MODET(vperm);
7072
7073 RB_GC_GUARD(fname) = rb_str_new4(fname);
7074 fd = rb_sysopen(fname, oflags, perm);
7075 return INT2NUM(fd);
7076}
7077
7078static VALUE
7079check_pipe_command(VALUE filename_or_command)
7080{
7081 char *s = RSTRING_PTR(filename_or_command);
7082 long l = RSTRING_LEN(filename_or_command);
7083 char *e = s + l;
7084 int chlen;
7085
7086 if (rb_enc_ascget(s, e, &chlen, rb_enc_get(filename_or_command)) == '|') {
7087 VALUE cmd = rb_str_new(s+chlen, l-chlen);
7088 return cmd;
7089 }
7090 return Qnil;
7091}
7092
7093/*
7094 * call-seq:
7095 * open(path [, mode [, perm]] [, opt]) -> io or nil
7096 * open(path [, mode [, perm]] [, opt]) {|io| block } -> obj
7097 *
7098 * Creates an IO object connected to the given stream, file, or subprocess.
7099 *
7100 * If +path+ does not start with a pipe character (<code>|</code>), treat it
7101 * as the name of a file to open using the specified mode (defaulting to
7102 * "r").
7103 *
7104 * The +mode+ is either a string or an integer. If it is an integer, it
7105 * must be bitwise-or of open(2) flags, such as File::RDWR or File::EXCL. If
7106 * it is a string, it is either "fmode", "fmode:ext_enc", or
7107 * "fmode:ext_enc:int_enc".
7108 *
7109 * See the documentation of IO.new for full documentation of the +mode+ string
7110 * directives.
7111 *
7112 * If a file is being created, its initial permissions may be set using the
7113 * +perm+ parameter. See File.new and the open(2) and chmod(2) man pages for
7114 * a description of permissions.
7115 *
7116 * If a block is specified, it will be invoked with the IO object as a
7117 * parameter, and the IO will be automatically closed when the block
7118 * terminates. The call returns the value of the block.
7119 *
7120 * If +path+ starts with a pipe character (<code>"|"</code>), a subprocess is
7121 * created, connected to the caller by a pair of pipes. The returned IO
7122 * object may be used to write to the standard input and read from the
7123 * standard output of this subprocess.
7124 *
7125 * If the command following the pipe is a single minus sign
7126 * (<code>"|-"</code>), Ruby forks, and this subprocess is connected to the
7127 * parent. If the command is not <code>"-"</code>, the subprocess runs the
7128 * command.
7129 *
7130 * When the subprocess is Ruby (opened via <code>"|-"</code>), the +open+
7131 * call returns +nil+. If a block is associated with the open call, that
7132 * block will run twice --- once in the parent and once in the child.
7133 *
7134 * The block parameter will be an IO object in the parent and +nil+ in the
7135 * child. The parent's +IO+ object will be connected to the child's $stdin
7136 * and $stdout. The subprocess will be terminated at the end of the block.
7137 *
7138 * === Examples
7139 *
7140 * Reading from "testfile":
7141 *
7142 * open("testfile") do |f|
7143 * print f.gets
7144 * end
7145 *
7146 * Produces:
7147 *
7148 * This is line one
7149 *
7150 * Open a subprocess and read its output:
7151 *
7152 * cmd = open("|date")
7153 * print cmd.gets
7154 * cmd.close
7155 *
7156 * Produces:
7157 *
7158 * Wed Apr 9 08:56:31 CDT 2003
7159 *
7160 * Open a subprocess running the same Ruby program:
7161 *
7162 * f = open("|-", "w+")
7163 * if f.nil?
7164 * puts "in Child"
7165 * exit
7166 * else
7167 * puts "Got: #{f.gets}"
7168 * end
7169 *
7170 * Produces:
7171 *
7172 * Got: in Child
7173 *
7174 * Open a subprocess using a block to receive the IO object:
7175 *
7176 * open "|-" do |f|
7177 * if f then
7178 * # parent process
7179 * puts "Got: #{f.gets}"
7180 * else
7181 * # child process
7182 * puts "in Child"
7183 * end
7184 * end
7185 *
7186 * Produces:
7187 *
7188 * Got: in Child
7189 */
7190
7191static VALUE
7192rb_f_open(int argc, VALUE *argv, VALUE _)
7193{
7194 ID to_open = 0;
7195 int redirect = FALSE;
7196
7197 if (argc >= 1) {
7198 CONST_ID(to_open, "to_open");
7199 if (rb_respond_to(argv[0], to_open)) {
7200 redirect = TRUE;
7201 }
7202 else {
7203 VALUE tmp = argv[0];
7204 FilePathValue(tmp);
7205 if (NIL_P(tmp)) {
7206 redirect = TRUE;
7207 }
7208 else {
7209 VALUE cmd = check_pipe_command(tmp);
7210 if (!NIL_P(cmd)) {
7211 argv[0] = cmd;
7212 return rb_io_s_popen(argc, argv, rb_cIO);
7213 }
7214 }
7215 }
7216 }
7217 if (redirect) {
7218 VALUE io = rb_funcallv_kw(argv[0], to_open, argc-1, argv+1, RB_PASS_CALLED_KEYWORDS);
7219
7220 if (rb_block_given_p()) {
7221 return rb_ensure(rb_yield, io, io_close, io);
7222 }
7223 return io;
7224 }
7225 return rb_io_s_open(argc, argv, rb_cFile);
7226}
7227
7228static VALUE rb_io_open_generic(VALUE, VALUE, int, int, const convconfig_t *, mode_t);
7229
7230static VALUE
7231rb_io_open(VALUE io, VALUE filename, VALUE vmode, VALUE vperm, VALUE opt)
7232{
7233 int oflags, fmode;
7234 convconfig_t convconfig;
7235 mode_t perm;
7236
7237 rb_io_extract_modeenc(&vmode, &vperm, opt, &oflags, &fmode, &convconfig);
7238 perm = NIL_P(vperm) ? 0666 : NUM2MODET(vperm);
7239 return rb_io_open_generic(io, filename, oflags, fmode, &convconfig, perm);
7240}
7241
7242static VALUE
7243rb_io_open_generic(VALUE klass, VALUE filename, int oflags, int fmode,
7244 const convconfig_t *convconfig, mode_t perm)
7245{
7246 VALUE cmd;
7247 if (klass == rb_cIO && !NIL_P(cmd = check_pipe_command(filename))) {
7248 return pipe_open_s(cmd, rb_io_oflags_modestr(oflags), fmode, convconfig);
7249 }
7250 else {
7251 return rb_file_open_generic(io_alloc(klass), filename,
7252 oflags, fmode, convconfig, perm);
7253 }
7254}
7255
7256static VALUE
7257io_reopen(VALUE io, VALUE nfile)
7258{
7259 rb_io_t *fptr, *orig;
7260 int fd, fd2;
7261 off_t pos = 0;
7262
7263 nfile = rb_io_get_io(nfile);
7264 GetOpenFile(io, fptr);
7265 GetOpenFile(nfile, orig);
7266
7267 if (fptr == orig) return io;
7268 if (IS_PREP_STDIO(fptr)) {
7269 if ((fptr->stdio_file == stdin && !(orig->mode & FMODE_READABLE)) ||
7270 (fptr->stdio_file == stdout && !(orig->mode & FMODE_WRITABLE)) ||
7271 (fptr->stdio_file == stderr && !(orig->mode & FMODE_WRITABLE))) {
7273 "%s can't change access mode from \"%s\" to \"%s\"",
7274 PREP_STDIO_NAME(fptr), rb_io_fmode_modestr(fptr->mode),
7275 rb_io_fmode_modestr(orig->mode));
7276 }
7277 }
7278 if (fptr->mode & FMODE_WRITABLE) {
7279 if (io_fflush(fptr) < 0)
7280 rb_sys_fail(0);
7281 }
7282 else {
7283 flush_before_seek(fptr);
7284 }
7285 if (orig->mode & FMODE_READABLE) {
7286 pos = io_tell(orig);
7287 }
7288 if (orig->mode & FMODE_WRITABLE) {
7289 if (io_fflush(orig) < 0)
7290 rb_sys_fail(0);
7291 }
7292
7293 /* copy rb_io_t structure */
7294 fptr->mode = orig->mode | (fptr->mode & FMODE_PREP);
7295 fptr->pid = orig->pid;
7296 fptr->lineno = orig->lineno;
7297 if (RTEST(orig->pathv)) fptr->pathv = orig->pathv;
7298 else if (!IS_PREP_STDIO(fptr)) fptr->pathv = Qnil;
7299 fptr_copy_finalizer(fptr, orig);
7300
7301 fd = fptr->fd;
7302 fd2 = orig->fd;
7303 if (fd != fd2) {
7304 if (IS_PREP_STDIO(fptr) || fd <= 2 || !fptr->stdio_file) {
7305 /* need to keep FILE objects of stdin, stdout and stderr */
7306 if (rb_cloexec_dup2(fd2, fd) < 0)
7307 rb_sys_fail_path(orig->pathv);
7308 rb_update_max_fd(fd);
7309 }
7310 else {
7311 fclose(fptr->stdio_file);
7312 fptr->stdio_file = 0;
7313 fptr->fd = -1;
7314 if (rb_cloexec_dup2(fd2, fd) < 0)
7315 rb_sys_fail_path(orig->pathv);
7316 rb_update_max_fd(fd);
7317 fptr->fd = fd;
7318 }
7320 if ((orig->mode & FMODE_READABLE) && pos >= 0) {
7321 if (io_seek(fptr, pos, SEEK_SET) < 0 && errno) {
7322 rb_sys_fail_path(fptr->pathv);
7323 }
7324 if (io_seek(orig, pos, SEEK_SET) < 0 && errno) {
7325 rb_sys_fail_path(orig->pathv);
7326 }
7327 }
7328 }
7329
7330 if (fptr->mode & FMODE_BINMODE) {
7331 rb_io_binmode(io);
7332 }
7333
7334 RBASIC_SET_CLASS(io, rb_obj_class(nfile));
7335 return io;
7336}
7337
7338#ifdef _WIN32
7339int rb_freopen(VALUE fname, const char *mode, FILE *fp);
7340#else
7341static int
7342rb_freopen(VALUE fname, const char *mode, FILE *fp)
7343{
7344 if (!freopen(RSTRING_PTR(fname), mode, fp)) {
7345 RB_GC_GUARD(fname);
7346 return errno;
7347 }
7348 return 0;
7349}
7350#endif
7351
7352/*
7353 * call-seq:
7354 * ios.reopen(other_IO) -> ios
7355 * ios.reopen(path, mode [, opt]) -> ios
7356 *
7357 * Reassociates <em>ios</em> with the I/O stream given in
7358 * <i>other_IO</i> or to a new stream opened on <i>path</i>. This may
7359 * dynamically change the actual class of this stream.
7360 * The +mode+ and +opt+ parameters accept the same values as IO.open.
7361 *
7362 * f1 = File.new("testfile")
7363 * f2 = File.new("testfile")
7364 * f2.readlines[0] #=> "This is line one\n"
7365 * f2.reopen(f1) #=> #<File:testfile>
7366 * f2.readlines[0] #=> "This is line one\n"
7367 */
7368
7369static VALUE
7370rb_io_reopen(int argc, VALUE *argv, VALUE file)
7371{
7372 VALUE fname, nmode, opt;
7373 int oflags;
7374 rb_io_t *fptr;
7375
7376 if (rb_scan_args(argc, argv, "11:", &fname, &nmode, &opt) == 1) {
7377 VALUE tmp = rb_io_check_io(fname);
7378 if (!NIL_P(tmp)) {
7379 return io_reopen(file, tmp);
7380 }
7381 }
7382
7383 FilePathValue(fname);
7384 rb_io_taint_check(file);
7385 fptr = RFILE(file)->fptr;
7386 if (!fptr) {
7387 fptr = RFILE(file)->fptr = ZALLOC(rb_io_t);
7388 }
7389
7390 if (!NIL_P(nmode) || !NIL_P(opt)) {
7391 int fmode;
7392 convconfig_t convconfig;
7393
7394 rb_io_extract_modeenc(&nmode, 0, opt, &oflags, &fmode, &convconfig);
7395 if (IS_PREP_STDIO(fptr) &&
7396 ((fptr->mode & FMODE_READWRITE) & (fmode & FMODE_READWRITE)) !=
7397 (fptr->mode & FMODE_READWRITE)) {
7399 "%s can't change access mode from \"%s\" to \"%s\"",
7400 PREP_STDIO_NAME(fptr), rb_io_fmode_modestr(fptr->mode),
7401 rb_io_fmode_modestr(fmode));
7402 }
7403 fptr->mode = fmode;
7404 fptr->encs = convconfig;
7405 }
7406 else {
7407 oflags = rb_io_fmode_oflags(fptr->mode);
7408 }
7409
7410 fptr->pathv = fname;
7411 if (fptr->fd < 0) {
7412 fptr->fd = rb_sysopen(fptr->pathv, oflags, 0666);
7413 fptr->stdio_file = 0;
7414 return file;
7415 }
7416
7417 if (fptr->mode & FMODE_WRITABLE) {
7418 if (io_fflush(fptr) < 0)
7419 rb_sys_fail(0);
7420 }
7421 fptr->rbuf.off = fptr->rbuf.len = 0;
7422
7423 if (fptr->stdio_file) {
7424 int e = rb_freopen(rb_str_encode_ospath(fptr->pathv),
7425 rb_io_oflags_modestr(oflags),
7426 fptr->stdio_file);
7427 if (e) rb_syserr_fail_path(e, fptr->pathv);
7428 fptr->fd = fileno(fptr->stdio_file);
7429 rb_fd_fix_cloexec(fptr->fd);
7430#ifdef USE_SETVBUF
7431 if (setvbuf(fptr->stdio_file, NULL, _IOFBF, 0) != 0)
7432 rb_warn("setvbuf() can't be honoured for %"PRIsVALUE, fptr->pathv);
7433#endif
7434 if (fptr->stdio_file == stderr) {
7435 if (setvbuf(fptr->stdio_file, NULL, _IONBF, BUFSIZ) != 0)
7436 rb_warn("setvbuf() can't be honoured for %"PRIsVALUE, fptr->pathv);
7437 }
7438 else if (fptr->stdio_file == stdout && isatty(fptr->fd)) {
7439 if (setvbuf(fptr->stdio_file, NULL, _IOLBF, BUFSIZ) != 0)
7440 rb_warn("setvbuf() can't be honoured for %"PRIsVALUE, fptr->pathv);
7441 }
7442 }
7443 else {
7444 int tmpfd = rb_sysopen(fptr->pathv, oflags, 0666);
7445 int err = 0;
7446 if (rb_cloexec_dup2(tmpfd, fptr->fd) < 0)
7447 err = errno;
7448 (void)close(tmpfd);
7449 if (err) {
7451 }
7452 }
7453
7454 return file;
7455}
7456
7457/* :nodoc: */
7458static VALUE
7459rb_io_init_copy(VALUE dest, VALUE io)
7460{
7461 rb_io_t *fptr, *orig;
7462 int fd;
7463 VALUE write_io;
7464 off_t pos;
7465
7466 io = rb_io_get_io(io);
7467 if (!OBJ_INIT_COPY(dest, io)) return dest;
7468 GetOpenFile(io, orig);
7469 MakeOpenFile(dest, fptr);
7470
7471 rb_io_flush(io);
7472
7473 /* copy rb_io_t structure */
7474 fptr->mode = orig->mode & ~FMODE_PREP;
7475 fptr->encs = orig->encs;
7476 fptr->pid = orig->pid;
7477 fptr->lineno = orig->lineno;
7478 if (!NIL_P(orig->pathv)) fptr->pathv = orig->pathv;
7479 fptr_copy_finalizer(fptr, orig);
7480
7481 fd = ruby_dup(orig->fd);
7482 fptr->fd = fd;
7483 pos = io_tell(orig);
7484 if (0 <= pos)
7485 io_seek(fptr, pos, SEEK_SET);
7486 if (fptr->mode & FMODE_BINMODE) {
7487 rb_io_binmode(dest);
7488 }
7489
7490 write_io = GetWriteIO(io);
7491 if (io != write_io) {
7492 write_io = rb_obj_dup(write_io);
7493 fptr->tied_io_for_writing = write_io;
7494 rb_ivar_set(dest, rb_intern("@tied_io_for_writing"), write_io);
7495 }
7496
7497 return dest;
7498}
7499
7500/*
7501 * call-seq:
7502 * ios.printf(format_string [, obj, ...]) -> nil
7503 *
7504 * Formats and writes to <em>ios</em>, converting parameters under
7505 * control of the format string. See Kernel#sprintf for details.
7506 */
7507
7508VALUE
7510{
7512 return Qnil;
7513}
7514
7515/*
7516 * call-seq:
7517 * printf(io, string [, obj ... ]) -> nil
7518 * printf(string [, obj ... ]) -> nil
7519 *
7520 * Equivalent to:
7521 * io.write(sprintf(string, obj, ...))
7522 * or
7523 * $stdout.write(sprintf(string, obj, ...))
7524 */
7525
7526static VALUE
7527rb_f_printf(int argc, VALUE *argv, VALUE _)
7528{
7529 VALUE out;
7530
7531 if (argc == 0) return Qnil;
7532 if (RB_TYPE_P(argv[0], T_STRING)) {
7533 out = rb_stdout;
7534 }
7535 else {
7536 out = argv[0];
7537 argv++;
7538 argc--;
7539 }
7541
7542 return Qnil;
7543}
7544
7545static void
7546rb_output_fs_setter(VALUE val, ID id, VALUE *var)
7547{
7548 rb_str_setter(val, id, &val);
7549 if (!NIL_P(val)) {
7550 rb_warn_deprecated("`$,'", NULL);
7551 }
7552 *var = val;
7553}
7554
7555/*
7556 * call-seq:
7557 * ios.print -> nil
7558 * ios.print(obj, ...) -> nil
7559 *
7560 * Writes the given object(s) to <em>ios</em>. Returns +nil+.
7561 *
7562 * The stream must be opened for writing.
7563 * Each given object that isn't a string will be converted by calling
7564 * its <code>to_s</code> method.
7565 * When called without arguments, prints the contents of <code>$_</code>.
7566 *
7567 * If the output field separator (<code>$,</code>) is not +nil+,
7568 * it is inserted between objects.
7569 * If the output record separator (<code>$\</code>) is not +nil+,
7570 * it is appended to the output.
7571 *
7572 * $stdout.print("This is ", 100, " percent.\n")
7573 *
7574 * <em>produces:</em>
7575 *
7576 * This is 100 percent.
7577 */
7578
7579VALUE
7581{
7582 int i;
7583 VALUE line;
7584
7585 /* if no argument given, print `$_' */
7586 if (argc == 0) {
7587 argc = 1;
7588 line = rb_lastline_get();
7589 argv = &line;
7590 }
7591 for (i=0; i<argc; i++) {
7592 if (!NIL_P(rb_output_fs) && i>0) {
7594 }
7595 rb_io_write(out, argv[i]);
7596 }
7597 if (argc > 0 && !NIL_P(rb_output_rs)) {
7599 }
7600
7601 return Qnil;
7602}
7603
7604/*
7605 * call-seq:
7606 * print(obj, ...) -> nil
7607 *
7608 * Prints each object in turn to <code>$stdout</code>. If the output
7609 * field separator (<code>$,</code>) is not +nil+, its
7610 * contents will appear between each field. If the output record
7611 * separator (<code>$\</code>) is not +nil+, it will be
7612 * appended to the output. If no arguments are given, prints
7613 * <code>$_</code>. Objects that aren't strings will be converted by
7614 * calling their <code>to_s</code> method.
7615 *
7616 * print "cat", [1,2,3], 99, "\n"
7617 * $, = ", "
7618 * $\ = "\n"
7619 * print "cat", [1,2,3], 99
7620 *
7621 * <em>produces:</em>
7622 *
7623 * cat12399
7624 * cat, 1, 2, 3, 99
7625 */
7626
7627static VALUE
7628rb_f_print(int argc, const VALUE *argv, VALUE _)
7629{
7631 return Qnil;
7632}
7633
7634/*
7635 * call-seq:
7636 * ios.putc(obj) -> obj
7637 *
7638 * If <i>obj</i> is Numeric, write the character whose code is the
7639 * least-significant byte of <i>obj</i>. If <i>obj</i> is String,
7640 * write the first character of <i>obj</i> to <em>ios</em>. Otherwise,
7641 * raise TypeError.
7642 *
7643 * $stdout.putc "A"
7644 * $stdout.putc 65
7645 *
7646 * <em>produces:</em>
7647 *
7648 * AA
7649 */
7650
7651static VALUE
7652rb_io_putc(VALUE io, VALUE ch)
7653{
7654 VALUE str;
7655 if (RB_TYPE_P(ch, T_STRING)) {
7656 str = rb_str_substr(ch, 0, 1);
7657 }
7658 else {
7659 char c = NUM2CHR(ch);
7660 str = rb_str_new(&c, 1);
7661 }
7662 rb_io_write(io, str);
7663 return ch;
7664}
7665
7666/*
7667 * call-seq:
7668 * putc(int) -> int
7669 *
7670 * Equivalent to:
7671 *
7672 * $stdout.putc(int)
7673 *
7674 * Refer to the documentation for IO#putc for important information regarding
7675 * multi-byte characters.
7676 */
7677
7678static VALUE
7679rb_f_putc(VALUE recv, VALUE ch)
7680{
7681 if (recv == rb_stdout) {
7682 return rb_io_putc(recv, ch);
7683 }
7684 return rb_funcallv(rb_stdout, rb_intern("putc"), 1, &ch);
7685}
7686
7687
7688int
7690{
7691 long len = RSTRING_LEN(str);
7692 const char *ptr = RSTRING_PTR(str);
7694 int n;
7695
7696 if (len == 0) return 0;
7697 if ((n = rb_enc_mbminlen(enc)) == 1) {
7698 return ptr[len - 1] == c;
7699 }
7700 return rb_enc_ascget(ptr + ((len - 1) / n) * n, ptr + len, &n, enc) == c;
7701}
7702
7703static VALUE
7704io_puts_ary(VALUE ary, VALUE out, int recur)
7705{
7706 VALUE tmp;
7707 long i;
7708
7709 if (recur) {
7710 tmp = rb_str_new2("[...]");
7711 rb_io_puts(1, &tmp, out);
7712 return Qtrue;
7713 }
7714 ary = rb_check_array_type(ary);
7715 if (NIL_P(ary)) return Qfalse;
7716 for (i=0; i<RARRAY_LEN(ary); i++) {
7717 tmp = RARRAY_AREF(ary, i);
7718 rb_io_puts(1, &tmp, out);
7719 }
7720 return Qtrue;
7721}
7722
7723/*
7724 * call-seq:
7725 * ios.puts(obj, ...) -> nil
7726 *
7727 * Writes the given object(s) to <em>ios</em>.
7728 * Writes a newline after any that do not already end
7729 * with a newline sequence. Returns +nil+.
7730 *
7731 * The stream must be opened for writing.
7732 * If called with an array argument, writes each element on a new line.
7733 * Each given object that isn't a string or array will be converted
7734 * by calling its +to_s+ method.
7735 * If called without arguments, outputs a single newline.
7736 *
7737 * $stdout.puts("this", "is", ["a", "test"])
7738 *
7739 * <em>produces:</em>
7740 *
7741 * this
7742 * is
7743 * a
7744 * test
7745 *
7746 * Note that +puts+ always uses newlines and is not affected
7747 * by the output record separator (<code>$\</code>).
7748 */
7749
7750VALUE
7751rb_io_puts(int argc, const VALUE *argv, VALUE out)
7752{
7753 int i, n;
7754 VALUE line, args[2];
7755
7756 /* if no argument given, print newline. */
7757 if (argc == 0) {
7759 return Qnil;
7760 }
7761 for (i=0; i<argc; i++) {
7762 if (RB_TYPE_P(argv[i], T_STRING)) {
7763 line = argv[i];
7764 goto string;
7765 }
7766 if (rb_exec_recursive(io_puts_ary, argv[i], out)) {
7767 continue;
7768 }
7769 line = rb_obj_as_string(argv[i]);
7770 string:
7771 n = 0;
7772 args[n++] = line;
7773 if (RSTRING_LEN(line) == 0 ||
7774 !rb_str_end_with_asciichar(line, '\n')) {
7775 args[n++] = rb_default_rs;
7776 }
7777 rb_io_writev(out, n, args);
7778 }
7779
7780 return Qnil;
7781}
7782
7783/*
7784 * call-seq:
7785 * puts(obj, ...) -> nil
7786 *
7787 * Equivalent to
7788 *
7789 * $stdout.puts(obj, ...)
7790 */
7791
7792static VALUE
7793rb_f_puts(int argc, VALUE *argv, VALUE recv)
7794{
7795 if (recv == rb_stdout) {
7796 return rb_io_puts(argc, argv, recv);
7797 }
7798 return rb_funcallv(rb_stdout, rb_intern("puts"), argc, argv);
7799}
7800
7801void
7802rb_p(VALUE obj) /* for debug print within C code */
7803{
7804 VALUE args[2];
7805 args[0] = rb_obj_as_string(rb_inspect(obj));
7806 args[1] = rb_default_rs;
7807 if (RB_TYPE_P(rb_stdout, T_FILE) &&
7809 io_writev(2, args, rb_stdout);
7810 }
7811 else {
7812 rb_io_writev(rb_stdout, 2, args);
7813 }
7814}
7815
7817 int argc;
7819};
7820
7821static VALUE
7822rb_f_p_internal(VALUE arg)
7823{
7824 struct rb_f_p_arg *arg1 = (struct rb_f_p_arg*)arg;
7825 int argc = arg1->argc;
7826 VALUE *argv = arg1->argv;
7827 int i;
7828 VALUE ret = Qnil;
7829
7830 for (i=0; i<argc; i++) {
7831 rb_p(argv[i]);
7832 }
7833 if (argc == 1) {
7834 ret = argv[0];
7835 }
7836 else if (argc > 1) {
7837 ret = rb_ary_new4(argc, argv);
7838 }
7839 if (RB_TYPE_P(rb_stdout, T_FILE)) {
7841 }
7842 return ret;
7843}
7844
7845/*
7846 * call-seq:
7847 * p(obj) -> obj
7848 * p(obj1, obj2, ...) -> [obj, ...]
7849 * p() -> nil
7850 *
7851 * For each object, directly writes _obj_.+inspect+ followed by a
7852 * newline to the program's standard output.
7853 *
7854 * S = Struct.new(:name, :state)
7855 * s = S['dave', 'TX']
7856 * p s
7857 *
7858 * <em>produces:</em>
7859 *
7860 * #<S name="dave", state="TX">
7861 */
7862
7863static VALUE
7864rb_f_p(int argc, VALUE *argv, VALUE self)
7865{
7866 struct rb_f_p_arg arg;
7867 arg.argc = argc;
7868 arg.argv = argv;
7869
7870 return rb_uninterruptible(rb_f_p_internal, (VALUE)&arg);
7871}
7872
7873/*
7874 * call-seq:
7875 * obj.display(port=$>) -> nil
7876 *
7877 * Prints <i>obj</i> on the given port (default <code>$></code>).
7878 * Equivalent to:
7879 *
7880 * def display(port=$>)
7881 * port.write self
7882 * nil
7883 * end
7884 *
7885 * For example:
7886 *
7887 * 1.display
7888 * "cat".display
7889 * [ 4, 5, 6 ].display
7890 * puts
7891 *
7892 * <em>produces:</em>
7893 *
7894 * 1cat[4, 5, 6]
7895 */
7896
7897static VALUE
7898rb_obj_display(int argc, VALUE *argv, VALUE self)
7899{
7900 VALUE out;
7901
7902 out = (!rb_check_arity(argc, 0, 1) ? rb_stdout : argv[0]);
7903 rb_io_write(out, self);
7904
7905 return Qnil;
7906}
7907
7908static int
7909rb_stderr_to_original_p(void)
7910{
7911 return (rb_stderr == orig_stderr || RFILE(orig_stderr)->fptr->fd < 0);
7912}
7913
7914void
7915rb_write_error2(const char *mesg, long len)
7916{
7917 if (rb_stderr_to_original_p()) {
7918#ifdef _WIN32
7919 if (isatty(fileno(stderr))) {
7920 if (rb_w32_write_console(rb_str_new(mesg, len), fileno(stderr)) > 0) return;
7921 }
7922#endif
7923 if (fwrite(mesg, sizeof(char), (size_t)len, stderr) < (size_t)len) {
7924 /* failed to write to stderr, what can we do? */
7925 return;
7926 }
7927 }
7928 else {
7930 }
7931}
7932
7933void
7934rb_write_error(const char *mesg)
7935{
7936 rb_write_error2(mesg, strlen(mesg));
7937}
7938
7939void
7941{
7942 /* a stopgap measure for the time being */
7943 if (rb_stderr_to_original_p()) {
7944 size_t len = (size_t)RSTRING_LEN(mesg);
7945#ifdef _WIN32
7946 if (isatty(fileno(stderr))) {
7947 if (rb_w32_write_console(mesg, fileno(stderr)) > 0) return;
7948 }
7949#endif
7950 if (fwrite(RSTRING_PTR(mesg), sizeof(char), len, stderr) < len) {
7951 RB_GC_GUARD(mesg);
7952 return;
7953 }
7954 }
7955 else {
7956 /* may unlock GVL, and */
7957 rb_io_write(rb_stderr, mesg);
7958 }
7959}
7960
7961int
7963{
7964 if (rb_stderr_to_original_p())
7965 return isatty(fileno(stderr));
7966 return 0;
7967}
7968
7969static void
7970must_respond_to(ID mid, VALUE val, ID id)
7971{
7972 if (!rb_respond_to(val, mid)) {
7973 rb_raise(rb_eTypeError, "%"PRIsVALUE" must have %"PRIsVALUE" method, %"PRIsVALUE" given",
7974 rb_id2str(id), rb_id2str(mid),
7975 rb_obj_class(val));
7976 }
7977}
7978
7979static void
7980stdout_setter(VALUE val, ID id, VALUE *variable)
7981{
7982 must_respond_to(id_write, val, id);
7983 *variable = val;
7984}
7985
7986static VALUE
7987prep_io(int fd, int fmode, VALUE klass, const char *path)
7988{
7989 rb_io_t *fp;
7990 VALUE io = io_alloc(klass);
7991
7992 MakeOpenFile(io, fp);
7993 fp->fd = fd;
7994 fp->mode = fmode;
7995 if (!io_check_tty(fp)) {
7996#ifdef __CYGWIN__
7997 fp->mode |= FMODE_BINMODE;
7998 setmode(fd, O_BINARY);
7999#endif
8000 }
8002 rb_update_max_fd(fd);
8003
8004 return io;
8005}
8006
8007VALUE
8008rb_io_fdopen(int fd, int oflags, const char *path)
8009{
8010 VALUE klass = rb_cIO;
8011
8012 if (path && strcmp(path, "-")) klass = rb_cFile;
8013 return prep_io(fd, rb_io_oflags_fmode(oflags), klass, path);
8014}
8015
8016static VALUE
8017prep_stdio(FILE *f, int fmode, VALUE klass, const char *path)
8018{
8019 rb_io_t *fptr;
8021
8022 GetOpenFile(io, fptr);
8024#ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
8025 fptr->encs.ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
8026 if (fmode & FMODE_READABLE) {
8028 }
8029#endif
8030 fptr->stdio_file = f;
8031
8032 return io;
8033}
8034
8035FILE *
8037{
8038 if (!fptr->stdio_file) {
8039 int oflags = rb_io_fmode_oflags(fptr->mode) & ~O_EXCL;
8040 fptr->stdio_file = rb_fdopen(fptr->fd, rb_io_oflags_modestr(oflags));
8041 }
8042 return fptr->stdio_file;
8043}
8044
8045static inline void
8046rb_io_buffer_init(rb_io_buffer_t *buf)
8047{
8048 buf->ptr = NULL;
8049 buf->off = 0;
8050 buf->len = 0;
8051 buf->capa = 0;
8052}
8053
8054static inline rb_io_t *
8055rb_io_fptr_new(void)
8056{
8057 rb_io_t *fp = ALLOC(rb_io_t);
8058 fp->fd = -1;
8059 fp->stdio_file = NULL;
8060 fp->mode = 0;
8061 fp->pid = 0;
8062 fp->lineno = 0;
8063 fp->pathv = Qnil;
8064 fp->finalize = 0;
8065 rb_io_buffer_init(&fp->wbuf);
8066 rb_io_buffer_init(&fp->rbuf);
8067 rb_io_buffer_init(&fp->cbuf);
8068 fp->readconv = NULL;
8069 fp->writeconv = NULL;
8071 fp->writeconv_pre_ecflags = 0;
8073 fp->writeconv_initialized = 0;
8074 fp->tied_io_for_writing = 0;
8075 fp->encs.enc = NULL;
8076 fp->encs.enc2 = NULL;
8077 fp->encs.ecflags = 0;
8078 fp->encs.ecopts = Qnil;
8079 fp->write_lock = 0;
8080 return fp;
8081}
8082
8083rb_io_t *
8085{
8086 rb_io_t *fp = 0;
8087
8089 if (RFILE(obj)->fptr) {
8092 RFILE(obj)->fptr = 0;
8093 }
8094 fp = rb_io_fptr_new();
8095 RFILE(obj)->fptr = fp;
8096 return fp;
8097}
8098
8099/*
8100 * call-seq:
8101 * IO.new(fd [, mode] [, opt]) -> io
8102 *
8103 * Returns a new IO object (a stream) for the given integer file descriptor
8104 * +fd+ and +mode+ string. +opt+ may be used to specify parts of +mode+ in a
8105 * more readable fashion. See also IO.sysopen and IO.for_fd.
8106 *
8107 * IO.new is called by various File and IO opening methods such as IO::open,
8108 * Kernel#open, and File::open.
8109 *
8110 * === Open Mode
8111 *
8112 * When +mode+ is an integer it must be combination of the modes defined in
8113 * File::Constants (+File::RDONLY+, <code>File::WRONLY|File::CREAT</code>).
8114 * See the open(2) man page for more information.
8115 *
8116 * When +mode+ is a string it must be in one of the following forms:
8117 *
8118 * fmode
8119 * fmode ":" ext_enc
8120 * fmode ":" ext_enc ":" int_enc
8121 * fmode ":" "BOM|UTF-*"
8122 *
8123 * +fmode+ is an IO open mode string, +ext_enc+ is the external encoding for
8124 * the IO and +int_enc+ is the internal encoding.
8125 *
8126 * ==== IO Open Mode
8127 *
8128 * Ruby allows the following open modes:
8129 *
8130 * "r" Read-only, starts at beginning of file (default mode).
8131 *
8132 * "r+" Read-write, starts at beginning of file.
8133 *
8134 * "w" Write-only, truncates existing file
8135 * to zero length or creates a new file for writing.
8136 *
8137 * "w+" Read-write, truncates existing file to zero length
8138 * or creates a new file for reading and writing.
8139 *
8140 * "a" Write-only, each write call appends data at end of file.
8141 * Creates a new file for writing if file does not exist.
8142 *
8143 * "a+" Read-write, each write call appends data at end of file.
8144 * Creates a new file for reading and writing if file does
8145 * not exist.
8146 *
8147 * The following modes must be used separately, and along with one or more of
8148 * the modes seen above.
8149 *
8150 * "b" Binary file mode
8151 * Suppresses EOL <-> CRLF conversion on Windows. And
8152 * sets external encoding to ASCII-8BIT unless explicitly
8153 * specified.
8154 *
8155 * "t" Text file mode
8156 *
8157 * The exclusive access mode ("x") can be used together with "w" to ensure
8158 * the file is created. Errno::EEXIST is raised when it already exists.
8159 * It may not be supported with all kinds of streams (e.g. pipes).
8160 *
8161 * When the open mode of original IO is read only, the mode cannot be
8162 * changed to be writable. Similarly, the open mode cannot be changed from
8163 * write only to readable.
8164 *
8165 * When such a change is attempted the error is raised in different locations
8166 * according to the platform.
8167 *
8168 * === IO Encoding
8169 *
8170 * When +ext_enc+ is specified, strings read will be tagged by the encoding
8171 * when reading, and strings output will be converted to the specified
8172 * encoding when writing.
8173 *
8174 * When +ext_enc+ and +int_enc+ are specified read strings will be converted
8175 * from +ext_enc+ to +int_enc+ upon input, and written strings will be
8176 * converted from +int_enc+ to +ext_enc+ upon output. See Encoding for
8177 * further details of transcoding on input and output.
8178 *
8179 * If "BOM|UTF-8", "BOM|UTF-16LE" or "BOM|UTF16-BE" are used, Ruby checks for
8180 * a Unicode BOM in the input document to help determine the encoding. For
8181 * UTF-16 encodings the file open mode must be binary. When present, the BOM
8182 * is stripped and the external encoding from the BOM is used. When the BOM
8183 * is missing the given Unicode encoding is used as +ext_enc+. (The BOM-set
8184 * encoding option is case insensitive, so "bom|utf-8" is also valid.)
8185 *
8186 * === Options
8187 *
8188 * +opt+ can be used instead of +mode+ for improved readability. The
8189 * following keys are supported:
8190 *
8191 * :mode ::
8192 * Same as +mode+ parameter
8193 *
8194 * :flags ::
8195 * Specifies file open flags as integer.
8196 * If +mode+ parameter is given, this parameter will be bitwise-ORed.
8197 *
8198 * :\external_encoding ::
8199 * External encoding for the IO.
8200 *
8201 * :\internal_encoding ::
8202 * Internal encoding for the IO. "-" is a synonym for the default internal
8203 * encoding.
8204 *
8205 * If the value is +nil+ no conversion occurs.
8206 *
8207 * :encoding ::
8208 * Specifies external and internal encodings as "extern:intern".
8209 *
8210 * :textmode ::
8211 * If the value is truth value, same as "t" in argument +mode+.
8212 *
8213 * :binmode ::
8214 * If the value is truth value, same as "b" in argument +mode+.
8215 *
8216 * :autoclose ::
8217 * If the value is +false+, the +fd+ will be kept open after this IO
8218 * instance gets finalized.
8219 *
8220 * Also, +opt+ can have same keys in String#encode for controlling conversion
8221 * between the external encoding and the internal encoding.
8222 *
8223 * === Example 1
8224 *
8225 * fd = IO.sysopen("/dev/tty", "w")
8226 * a = IO.new(fd,"w")
8227 * $stderr.puts "Hello"
8228 * a.puts "World"
8229 *
8230 * Produces:
8231 *
8232 * Hello
8233 * World
8234 *
8235 * === Example 2
8236 *
8237 * require 'fcntl'
8238 *
8239 * fd = STDERR.fcntl(Fcntl::F_DUPFD)
8240 * io = IO.new(fd, mode: 'w:UTF-16LE', cr_newline: true)
8241 * io.puts "Hello, World!"
8242 *
8243 * fd = STDERR.fcntl(Fcntl::F_DUPFD)
8244 * io = IO.new(fd, mode: 'w', cr_newline: true,
8245 * external_encoding: Encoding::UTF_16LE)
8246 * io.puts "Hello, World!"
8247 *
8248 * Both of above print "Hello, World!" in UTF-16LE to standard error output
8249 * with converting EOL generated by #puts to CR.
8250 */
8251
8252static VALUE
8253rb_io_initialize(int argc, VALUE *argv, VALUE io)
8254{
8255 VALUE fnum, vmode;
8256 rb_io_t *fp;
8257 int fd, fmode, oflags = O_RDONLY;
8258 convconfig_t convconfig;
8259 VALUE opt;
8260#if defined(HAVE_FCNTL) && defined(F_GETFL)
8261 int ofmode;
8262#else
8263 struct stat st;
8264#endif
8265
8266
8267 argc = rb_scan_args(argc, argv, "11:", &fnum, &vmode, &opt);
8268 rb_io_extract_modeenc(&vmode, 0, opt, &oflags, &fmode, &convconfig);
8269
8270 fd = NUM2INT(fnum);
8271 if (rb_reserved_fd_p(fd)) {
8272 rb_raise(rb_eArgError, "The given fd is not accessible because RubyVM reserves it");
8273 }
8274#if defined(HAVE_FCNTL) && defined(F_GETFL)
8275 oflags = fcntl(fd, F_GETFL);
8276 if (oflags == -1) rb_sys_fail(0);
8277#else
8278 if (fstat(fd, &st) < 0) rb_sys_fail(0);
8279#endif
8280 rb_update_max_fd(fd);
8281#if defined(HAVE_FCNTL) && defined(F_GETFL)
8282 ofmode = rb_io_oflags_fmode(oflags);
8283 if (NIL_P(vmode)) {
8284 fmode = ofmode;
8285 }
8286 else if ((~ofmode & fmode) & FMODE_READWRITE) {
8289 }
8290#endif
8291 if (!NIL_P(opt) && rb_hash_aref(opt, sym_autoclose) == Qfalse) {
8292 fmode |= FMODE_PREP;
8293 }
8294 MakeOpenFile(io, fp);
8295 fp->fd = fd;
8296 fp->mode = fmode;
8297 fp->encs = convconfig;
8298 clear_codeconv(fp);
8299 io_check_tty(fp);
8300 if (fileno(stdin) == fd)
8301 fp->stdio_file = stdin;
8302 else if (fileno(stdout) == fd)
8303 fp->stdio_file = stdout;
8304 else if (fileno(stderr) == fd)
8305 fp->stdio_file = stderr;
8306
8307 if (fmode & FMODE_SETENC_BY_BOM) io_set_encoding_by_bom(io);
8308 return io;
8309}
8310
8311/*
8312 * call-seq:
8313 * ios.set_encoding_by_bom -> encoding or nil
8314 *
8315 * Checks if +ios+ starts with a BOM, and then consumes it and sets
8316 * the external encoding. Returns the result encoding if found, or
8317 * nil. If +ios+ is not binmode or its encoding has been set
8318 * already, an exception will be raised.
8319 *
8320 * File.write("bom.txt", "\u{FEFF}abc")
8321 * ios = File.open("bom.txt", "rb")
8322 * ios.set_encoding_by_bom #=> #<Encoding:UTF-8>
8323 *
8324 * File.write("nobom.txt", "abc")
8325 * ios = File.open("nobom.txt", "rb")
8326 * ios.set_encoding_by_bom #=> nil
8327 */
8328
8329static VALUE
8330rb_io_set_encoding_by_bom(VALUE io)
8331{
8332 rb_io_t *fptr;
8333
8334 GetOpenFile(io, fptr);
8335 if (!(fptr->mode & FMODE_BINMODE)) {
8336 rb_raise(rb_eArgError, "ASCII incompatible encoding needs binmode");
8337 }
8338 if (fptr->encs.enc2) {
8339 rb_raise(rb_eArgError, "encoding conversion is set");
8340 }
8341 else if (fptr->encs.enc && fptr->encs.enc != rb_ascii8bit_encoding()) {
8342 rb_raise(rb_eArgError, "encoding is set to %s already",
8343 rb_enc_name(fptr->encs.enc));
8344 }
8345 if (!io_set_encoding_by_bom(io)) return Qnil;
8346 return rb_enc_from_encoding(fptr->encs.enc);
8347}
8348
8349/*
8350 * call-seq:
8351 * File.new(filename, mode="r" [, opt]) -> file
8352 * File.new(filename [, mode [, perm]] [, opt]) -> file
8353 *
8354 * Opens the file named by +filename+ according to the given +mode+ and
8355 * returns a new File object.
8356 *
8357 * See IO.new for a description of +mode+ and +opt+.
8358 *
8359 * If a file is being created, permission bits may be given in +perm+. These
8360 * mode and permission bits are platform dependent; on Unix systems, see
8361 * open(2) and chmod(2) man pages for details.
8362 *
8363 * The new File object is buffered mode (or non-sync mode), unless
8364 * +filename+ is a tty.
8365 * See IO#flush, IO#fsync, IO#fdatasync, and IO#sync= about sync mode.
8366 *
8367 * === Examples
8368 *
8369 * f = File.new("testfile", "r")
8370 * f = File.new("newfile", "w+")
8371 * f = File.new("newfile", File::CREAT|File::TRUNC|File::RDWR, 0644)
8372 */
8373
8374static VALUE
8375rb_file_initialize(int argc, VALUE *argv, VALUE io)
8376{
8377 if (RFILE(io)->fptr) {
8378 rb_raise(rb_eRuntimeError, "reinitializing File");
8379 }
8380 if (0 < argc && argc < 3) {
8381 VALUE fd = rb_check_to_int(argv[0]);
8382
8383 if (!NIL_P(fd)) {
8384 argv[0] = fd;
8385 return rb_io_initialize(argc, argv, io);
8386 }
8387 }
8388 rb_open_file(argc, argv, io);
8389
8390 return io;
8391}
8392
8393/* :nodoc: */
8394static VALUE
8395rb_io_s_new(int argc, VALUE *argv, VALUE klass)
8396{
8397 if (rb_block_given_p()) {
8398 VALUE cname = rb_obj_as_string(klass);
8399
8400 rb_warn("%"PRIsVALUE"::new() does not take block; use %"PRIsVALUE"::open() instead",
8401 cname, cname);
8402 }
8404}
8405
8406
8407/*
8408 * call-seq:
8409 * IO.for_fd(fd, mode [, opt]) -> io
8410 *
8411 * Synonym for IO.new.
8412 *
8413 */
8414
8415static VALUE
8416rb_io_s_for_fd(int argc, VALUE *argv, VALUE klass)
8417{
8418 VALUE io = rb_obj_alloc(klass);
8419 rb_io_initialize(argc, argv, io);
8420 return io;
8421}
8422
8423/*
8424 * call-seq:
8425 * ios.autoclose? -> true or false
8426 *
8427 * Returns +true+ if the underlying file descriptor of _ios_ will be
8428 * closed automatically at its finalization, otherwise +false+.
8429 */
8430
8431static VALUE
8432rb_io_autoclose_p(VALUE io)
8433{
8434 rb_io_t *fptr = RFILE(io)->fptr;
8435 rb_io_check_closed(fptr);
8436 return (fptr->mode & FMODE_PREP) ? Qfalse : Qtrue;
8437}
8438
8439/*
8440 * call-seq:
8441 * io.autoclose = bool -> true or false
8442 *
8443 * Sets auto-close flag.
8444 *
8445 * f = open("/dev/null")
8446 * IO.for_fd(f.fileno)
8447 * # ...
8448 * f.gets # may cause Errno::EBADF
8449 *
8450 * f = open("/dev/null")
8451 * IO.for_fd(f.fileno).autoclose = false
8452 * # ...
8453 * f.gets # won't cause Errno::EBADF
8454 */
8455
8456static VALUE
8457rb_io_set_autoclose(VALUE io, VALUE autoclose)
8458{
8459 rb_io_t *fptr;
8460 GetOpenFile(io, fptr);
8461 if (!RTEST(autoclose))
8462 fptr->mode |= FMODE_PREP;
8463 else
8464 fptr->mode &= ~FMODE_PREP;
8465 return autoclose;
8466}
8467
8468static void
8469argf_mark(void *ptr)
8470{
8471 struct argf *p = ptr;
8472 rb_gc_mark(p->filename);
8474 rb_gc_mark(p->argv);
8475 rb_gc_mark(p->inplace);
8476 rb_gc_mark(p->encs.ecopts);
8477}
8478
8479static size_t
8480argf_memsize(const void *ptr)
8481{
8482 const struct argf *p = ptr;
8483 size_t size = sizeof(*p);
8484 return size;
8485}
8486
8487static const rb_data_type_t argf_type = {
8488 "ARGF",
8489 {argf_mark, RUBY_TYPED_DEFAULT_FREE, argf_memsize},
8491};
8492
8493static inline void
8494argf_init(struct argf *p, VALUE v)
8495{
8496 p->filename = Qnil;
8497 p->current_file = Qnil;
8498 p->lineno = 0;
8499 p->argv = v;
8500}
8501
8502static VALUE
8503argf_alloc(VALUE klass)
8504{
8505 struct argf *p;
8506 VALUE argf = TypedData_Make_Struct(klass, struct argf, &argf_type, p);
8507
8508 argf_init(p, Qnil);
8509 return argf;
8510}
8511
8512#undef rb_argv
8513
8514/* :nodoc: */
8515static VALUE
8516argf_initialize(VALUE argf, VALUE argv)
8517{
8518 memset(&ARGF, 0, sizeof(ARGF));
8519 argf_init(&ARGF, argv);
8520
8521 return argf;
8522}
8523
8524/* :nodoc: */
8525static VALUE
8526argf_initialize_copy(VALUE argf, VALUE orig)
8527{
8528 if (!OBJ_INIT_COPY(argf, orig)) return argf;
8529 ARGF = argf_of(orig);
8530 ARGF.argv = rb_obj_dup(ARGF.argv);
8531 return argf;
8532}
8533
8534/*
8535 * call-seq:
8536 * ARGF.lineno = integer -> integer
8537 *
8538 * Sets the line number of +ARGF+ as a whole to the given +Integer+.
8539 *
8540 * +ARGF+ sets the line number automatically as you read data, so normally
8541 * you will not need to set it explicitly. To access the current line number
8542 * use +ARGF.lineno+.
8543 *
8544 * For example:
8545 *
8546 * ARGF.lineno #=> 0
8547 * ARGF.readline #=> "This is line 1\n"
8548 * ARGF.lineno #=> 1
8549 * ARGF.lineno = 0 #=> 0
8550 * ARGF.lineno #=> 0
8551 */
8552static VALUE
8553argf_set_lineno(VALUE argf, VALUE val)
8554{
8555 ARGF.lineno = NUM2INT(val);
8556 ARGF.last_lineno = ARGF.lineno;
8557 return Qnil;
8558}
8559
8560/*
8561 * call-seq:
8562 * ARGF.lineno -> integer
8563 *
8564 * Returns the current line number of ARGF as a whole. This value
8565 * can be set manually with +ARGF.lineno=+.
8566 *
8567 * For example:
8568 *
8569 * ARGF.lineno #=> 0
8570 * ARGF.readline #=> "This is line 1\n"
8571 * ARGF.lineno #=> 1
8572 */
8573static VALUE
8574argf_lineno(VALUE argf)
8575{
8576 return INT2FIX(ARGF.lineno);
8577}
8578
8579static VALUE
8580argf_forward(int argc, VALUE *argv, VALUE argf)
8581{
8582 return rb_funcall3(ARGF.current_file, rb_frame_this_func(), argc, argv);
8583}
8584
8585#define next_argv() argf_next_argv(argf)
8586#define ARGF_GENERIC_INPUT_P() \
8587 (ARGF.current_file == rb_stdin && !RB_TYPE_P(ARGF.current_file, T_FILE))
8588#define ARGF_FORWARD(argc, argv) do {\
8589 if (ARGF_GENERIC_INPUT_P())\
8590 return argf_forward((argc), (argv), argf);\
8591} while (0)
8592#define NEXT_ARGF_FORWARD(argc, argv) do {\
8593 if (!next_argv()) return Qnil;\
8594 ARGF_FORWARD((argc), (argv));\
8595} while (0)
8596
8597static void
8598argf_close(VALUE argf)
8599{
8600 VALUE file = ARGF.current_file;
8601 if (file == rb_stdin) return;
8602 if (RB_TYPE_P(file, T_FILE)) {
8603 rb_io_set_write_io(file, Qnil);
8604 }
8605 io_close(file);
8606 ARGF.init_p = -1;
8607}
8608
8609static int
8610argf_next_argv(VALUE argf)
8611{
8612 char *fn;
8613 rb_io_t *fptr;
8614 int stdout_binmode = 0;
8615 int fmode;
8616
8617 if (RB_TYPE_P(rb_stdout, T_FILE)) {
8618 GetOpenFile(rb_stdout, fptr);
8619 if (fptr->mode & FMODE_BINMODE)
8620 stdout_binmode = 1;
8621 }
8622
8623 if (ARGF.init_p == 0) {
8624 if (!NIL_P(ARGF.argv) && RARRAY_LEN(ARGF.argv) > 0) {
8625 ARGF.next_p = 1;
8626 }
8627 else {
8628 ARGF.next_p = -1;
8629 }
8630 ARGF.init_p = 1;
8631 }
8632 else {
8633 if (NIL_P(ARGF.argv)) {
8634 ARGF.next_p = -1;
8635 }
8636 else if (ARGF.next_p == -1 && RARRAY_LEN(ARGF.argv) > 0) {
8637 ARGF.next_p = 1;
8638 }
8639 }
8640
8641 if (ARGF.next_p == 1) {
8642 if (ARGF.init_p == 1) argf_close(argf);
8643 retry:
8644 if (RARRAY_LEN(ARGF.argv) > 0) {
8647 ARGF.filename = filename;
8650 if (RSTRING_LEN(filename) == 1 && fn[0] == '-') {
8651 ARGF.current_file = rb_stdin;
8652 if (ARGF.inplace) {
8653 rb_warn("Can't do inplace edit for stdio; skipping");
8654 goto retry;
8655 }
8656 }
8657 else {
8658 VALUE write_io = Qnil;
8659 int fr = rb_sysopen(filename, O_RDONLY, 0);
8660
8661 if (ARGF.inplace) {
8662 struct stat st;
8663#ifndef NO_SAFE_RENAME
8664 struct stat st2;
8665#endif
8666 VALUE str;
8667 int fw;
8668
8669 if (RB_TYPE_P(rb_stdout, T_FILE) && rb_stdout != orig_stdout) {
8671 }
8672 fstat(fr, &st);
8673 str = filename;
8674 if (!NIL_P(ARGF.inplace)) {
8675 VALUE suffix = ARGF.inplace;
8676 str = rb_str_dup(str);
8678 RSTRING_PTR(suffix), RSTRING_LEN(suffix),
8679 rb_enc_get(suffix), 0, Qnil))) {
8680 rb_str_append(str, suffix);
8681 }
8682#ifdef NO_SAFE_RENAME
8683 (void)close(fr);
8685 if (rename(fn, RSTRING_PTR(str)) < 0) {
8686 rb_warn("Can't rename %"PRIsVALUE" to %"PRIsVALUE": %s, skipping file",
8687 filename, str, strerror(errno));
8688 goto retry;
8689 }
8690 fr = rb_sysopen(str, O_RDONLY, 0);
8691#else
8692 if (rename(fn, RSTRING_PTR(str)) < 0) {
8693 rb_warn("Can't rename %"PRIsVALUE" to %"PRIsVALUE": %s, skipping file",
8694 filename, str, strerror(errno));
8695 close(fr);
8696 goto retry;
8697 }
8698#endif
8699 }
8700 else {
8701#ifdef NO_SAFE_RENAME
8702 rb_fatal("Can't do inplace edit without backup");
8703#else
8704 if (unlink(fn) < 0) {
8705 rb_warn("Can't remove %"PRIsVALUE": %s, skipping file",
8706 filename, strerror(errno));
8707 close(fr);
8708 goto retry;
8709 }
8710#endif
8711 }
8712 fw = rb_sysopen(filename, O_WRONLY|O_CREAT|O_TRUNC, 0666);
8713#ifndef NO_SAFE_RENAME
8714 fstat(fw, &st2);
8715#ifdef HAVE_FCHMOD
8716 fchmod(fw, st.st_mode);
8717#else
8718 chmod(fn, st.st_mode);
8719#endif
8720 if (st.st_uid!=st2.st_uid || st.st_gid!=st2.st_gid) {
8721 int err;
8722#ifdef HAVE_FCHOWN
8723 err = fchown(fw, st.st_uid, st.st_gid);
8724#else
8725 err = chown(fn, st.st_uid, st.st_gid);
8726#endif
8727 if (err && getuid() == 0 && st2.st_uid == 0) {
8728 const char *wkfn = RSTRING_PTR(filename);
8729 rb_warn("Can't set owner/group of %"PRIsVALUE" to same as %"PRIsVALUE": %s, skipping file",
8730 filename, str, strerror(errno));
8731 (void)close(fr);
8732 (void)close(fw);
8733 (void)unlink(wkfn);
8734 goto retry;
8735 }
8736 }
8737#endif
8738 write_io = prep_io(fw, FMODE_WRITABLE, rb_cFile, fn);
8739 rb_stdout = write_io;
8740 if (stdout_binmode) rb_io_binmode(rb_stdout);
8741 }
8743 if (!ARGF.binmode) {
8745 }
8746 ARGF.current_file = prep_io(fr, fmode, rb_cFile, fn);
8747 if (!NIL_P(write_io)) {
8748 rb_io_set_write_io(ARGF.current_file, write_io);
8749 }
8750 RB_GC_GUARD(filename);
8751 }
8752 if (ARGF.binmode) rb_io_ascii8bit_binmode(ARGF.current_file);
8753 GetOpenFile(ARGF.current_file, fptr);
8754 if (ARGF.encs.enc) {
8755 fptr->encs = ARGF.encs;
8756 clear_codeconv(fptr);
8757 }
8758 else {
8759 fptr->encs.ecflags &= ~ECONV_NEWLINE_DECORATOR_MASK;
8760 if (!ARGF.binmode) {
8762#ifdef TEXTMODE_NEWLINE_DECORATOR_ON_WRITE
8763 fptr->encs.ecflags |= TEXTMODE_NEWLINE_DECORATOR_ON_WRITE;
8764#endif
8765 }
8766 }
8767 ARGF.next_p = 0;
8768 }
8769 else {
8770 ARGF.next_p = 1;
8771 return FALSE;
8772 }
8773 }
8774 else if (ARGF.next_p == -1) {
8775 ARGF.current_file = rb_stdin;
8776 ARGF.filename = rb_str_new2("-");
8777 if (ARGF.inplace) {
8778 rb_warn("Can't do inplace edit for stdio");
8779 rb_stdout = orig_stdout;
8780 }
8781 }
8782 if (ARGF.init_p == -1) ARGF.init_p = 1;
8783 return TRUE;
8784}
8785
8786static VALUE
8787argf_getline(int argc, VALUE *argv, VALUE argf)
8788{
8789 VALUE line;
8790 long lineno = ARGF.lineno;
8791
8792 retry:
8793 if (!next_argv()) return Qnil;
8794 if (ARGF_GENERIC_INPUT_P()) {
8795 line = rb_funcall3(ARGF.current_file, idGets, argc, argv);
8796 }
8797 else {
8798 if (argc == 0 && rb_rs == rb_default_rs) {
8799 line = rb_io_gets(ARGF.current_file);
8800 }
8801 else {
8802 line = rb_io_getline(argc, argv, ARGF.current_file);
8803 }
8804 if (NIL_P(line) && ARGF.next_p != -1) {
8805 argf_close(argf);
8806 ARGF.next_p = 1;
8807 goto retry;
8808 }
8809 }
8810 if (!NIL_P(line)) {
8811 ARGF.lineno = ++lineno;
8812 ARGF.last_lineno = ARGF.lineno;
8813 }
8814 return line;
8815}
8816
8817static VALUE
8818argf_lineno_getter(ID id, VALUE *var)
8819{
8820 VALUE argf = *var;
8821 return INT2FIX(ARGF.last_lineno);
8822}
8823
8824static void
8825argf_lineno_setter(VALUE val, ID id, VALUE *var)
8826{
8827 VALUE argf = *var;
8828 int n = NUM2INT(val);
8829 ARGF.last_lineno = ARGF.lineno = n;
8830}
8831
8832static VALUE argf_gets(int, VALUE *, VALUE);
8833
8834/*
8835 * call-seq:
8836 * gets(sep=$/ [, getline_args]) -> string or nil
8837 * gets(limit [, getline_args]) -> string or nil
8838 * gets(sep, limit [, getline_args]) -> string or nil
8839 *
8840 * Returns (and assigns to <code>$_</code>) the next line from the list
8841 * of files in +ARGV+ (or <code>$*</code>), or from standard input if
8842 * no files are present on the command line. Returns +nil+ at end of
8843 * file. The optional argument specifies the record separator. The
8844 * separator is included with the contents of each record. A separator
8845 * of +nil+ reads the entire contents, and a zero-length separator
8846 * reads the input one paragraph at a time, where paragraphs are
8847 * divided by two consecutive newlines. If the first argument is an
8848 * integer, or optional second argument is given, the returning string
8849 * would not be longer than the given value in bytes. If multiple
8850 * filenames are present in +ARGV+, <code>gets(nil)</code> will read
8851 * the contents one file at a time.
8852 *
8853 * ARGV << "testfile"
8854 * print while gets
8855 *
8856 * <em>produces:</em>
8857 *
8858 * This is line one
8859 * This is line two
8860 * This is line three
8861 * And so on...
8862 *
8863 * The style of programming using <code>$_</code> as an implicit
8864 * parameter is gradually losing favor in the Ruby community.
8865 */
8866
8867static VALUE
8868rb_f_gets(int argc, VALUE *argv, VALUE recv)
8869{
8870 if (recv == argf) {
8871 return argf_gets(argc, argv, argf);
8872 }
8873 return rb_funcallv(argf, idGets, argc, argv);
8874}
8875
8876/*
8877 * call-seq:
8878 * ARGF.gets(sep=$/ [, getline_args]) -> string or nil
8879 * ARGF.gets(limit [, getline_args]) -> string or nil
8880 * ARGF.gets(sep, limit [, getline_args]) -> string or nil
8881 *
8882 * Returns the next line from the current file in +ARGF+.
8883 *
8884 * By default lines are assumed to be separated by <code>$/</code>;
8885 * to use a different character as a separator, supply it as a +String+
8886 * for the _sep_ argument.
8887 *
8888 * The optional _limit_ argument specifies how many characters of each line
8889 * to return. By default all characters are returned.
8890 *
8891 * See IO.readlines for details about getline_args.
8892 *
8893 */
8894static VALUE
8895argf_gets(int argc, VALUE *argv, VALUE argf)
8896{
8897 VALUE line;
8898
8899 line = argf_getline(argc, argv, argf);
8900 rb_lastline_set(line);
8901
8902 return line;
8903}
8904
8905VALUE
8907{
8908 VALUE line;
8909
8910 if (rb_rs != rb_default_rs) {
8911 return rb_f_gets(0, 0, argf);
8912 }
8913
8914 retry:
8915 if (!next_argv()) return Qnil;
8916 line = rb_io_gets(ARGF.current_file);
8917 if (NIL_P(line) && ARGF.next_p != -1) {
8918 rb_io_close(ARGF.current_file);
8919 ARGF.next_p = 1;
8920 goto retry;
8921 }
8922 rb_lastline_set(line);
8923 if (!NIL_P(line)) {
8924 ARGF.lineno++;
8925 ARGF.last_lineno = ARGF.lineno;
8926 }
8927
8928 return line;
8929}
8930
8931static VALUE argf_readline(int, VALUE *, VALUE);
8932
8933/*
8934 * call-seq:
8935 * readline(sep=$/) -> string
8936 * readline(limit) -> string
8937 * readline(sep, limit) -> string
8938 *
8939 * Equivalent to Kernel::gets, except
8940 * +readline+ raises +EOFError+ at end of file.
8941 */
8942
8943static VALUE
8944rb_f_readline(int argc, VALUE *argv, VALUE recv)
8945{
8946 if (recv == argf) {
8947 return argf_readline(argc, argv, argf);
8948 }
8949 return rb_funcallv(argf, rb_intern("readline"), argc, argv);
8950}
8951
8952
8953/*
8954 * call-seq:
8955 * ARGF.readline(sep=$/) -> string
8956 * ARGF.readline(limit) -> string
8957 * ARGF.readline(sep, limit) -> string
8958 *
8959 * Returns the next line from the current file in +ARGF+.
8960 *
8961 * By default lines are assumed to be separated by <code>$/</code>;
8962 * to use a different character as a separator, supply it as a +String+
8963 * for the _sep_ argument.
8964 *
8965 * The optional _limit_ argument specifies how many characters of each line
8966 * to return. By default all characters are returned.
8967 *
8968 * An +EOFError+ is raised at the end of the file.
8969 */
8970static VALUE
8971argf_readline(int argc, VALUE *argv, VALUE argf)
8972{
8973 VALUE line;
8974
8975 if (!next_argv()) rb_eof_error();
8977 line = argf_gets(argc, argv, argf);
8978 if (NIL_P(line)) {
8979 rb_eof_error();
8980 }
8981
8982 return line;
8983}
8984
8985static VALUE argf_readlines(int, VALUE *, VALUE);
8986
8987/*
8988 * call-seq:
8989 * readlines(sep=$/) -> array
8990 * readlines(limit) -> array
8991 * readlines(sep, limit) -> array
8992 *
8993 * Returns an array containing the lines returned by calling
8994 * <code>Kernel.gets(<i>sep</i>)</code> until the end of file.
8995 */
8996
8997static VALUE
8998rb_f_readlines(int argc, VALUE *argv, VALUE recv)
8999{
9000 if (recv == argf) {
9001 return argf_readlines(argc, argv, argf);
9002 }
9003 return rb_funcallv(argf, rb_intern("readlines"), argc, argv);
9004}
9005
9006/*
9007 * call-seq:
9008 * ARGF.readlines(sep=$/) -> array
9009 * ARGF.readlines(limit) -> array
9010 * ARGF.readlines(sep, limit) -> array
9011 *
9012 * ARGF.to_a(sep=$/) -> array
9013 * ARGF.to_a(limit) -> array
9014 * ARGF.to_a(sep, limit) -> array
9015 *
9016 * Reads +ARGF+'s current file in its entirety, returning an +Array+ of its
9017 * lines, one line per element. Lines are assumed to be separated by _sep_.
9018 *
9019 * lines = ARGF.readlines
9020 * lines[0] #=> "This is line one\n"
9021 */
9022static VALUE
9023argf_readlines(int argc, VALUE *argv, VALUE argf)
9024{
9025 long lineno = ARGF.lineno;
9026 VALUE lines, ary;
9027
9028 ary = rb_ary_new();
9029 while (next_argv()) {
9030 if (ARGF_GENERIC_INPUT_P()) {
9031 lines = rb_funcall3(ARGF.current_file, rb_intern("readlines"), argc, argv);
9032 }
9033 else {
9034 lines = rb_io_readlines(argc, argv, ARGF.current_file);
9035 argf_close(argf);
9036 }
9037 ARGF.next_p = 1;
9038 rb_ary_concat(ary, lines);
9039 ARGF.lineno = lineno + RARRAY_LEN(ary);
9040 ARGF.last_lineno = ARGF.lineno;
9041 }
9042 ARGF.init_p = 0;
9043 return ary;
9044}
9045
9046/*
9047 * call-seq:
9048 * `cmd` -> string
9049 *
9050 * Returns the standard output of running _cmd_ in a subshell.
9051 * The built-in syntax <code>%x{...}</code> uses
9052 * this method. Sets <code>$?</code> to the process status.
9053 *
9054 * `date` #=> "Wed Apr 9 08:56:30 CDT 2003\n"
9055 * `ls testdir`.split[1] #=> "main.rb"
9056 * `echo oops && exit 99` #=> "oops\n"
9057 * $?.exitstatus #=> 99
9058 */
9059
9060static VALUE
9061rb_f_backquote(VALUE obj, VALUE str)
9062{
9063 VALUE port;
9064 VALUE result;
9065 rb_io_t *fptr;
9066
9069 port = pipe_open_s(str, "r", FMODE_READABLE|DEFAULT_TEXTMODE, NULL);
9070 if (NIL_P(port)) return rb_str_new(0,0);
9071
9072 GetOpenFile(port, fptr);
9073 result = read_all(fptr, remain_size(fptr), Qnil);
9074 rb_io_close(port);
9075 RFILE(port)->fptr = NULL;
9076 rb_io_fptr_finalize(fptr);
9077 rb_gc_force_recycle(port); /* also guards from premature GC */
9078
9079 return result;
9080}
9081
9082#ifdef HAVE_SYS_SELECT_H
9083#include <sys/select.h>
9084#endif
9085
9086static VALUE
9087select_internal(VALUE read, VALUE write, VALUE except, struct timeval *tp, rb_fdset_t *fds)
9088{
9089 VALUE res, list;
9090 rb_fdset_t *rp, *wp, *ep;
9091 rb_io_t *fptr;
9092 long i;
9093 int max = 0, n;
9094 int pending = 0;
9095 struct timeval timerec;
9096
9097 if (!NIL_P(read)) {
9099 for (i=0; i<RARRAY_LEN(read); i++) {
9101 rb_fd_set(fptr->fd, &fds[0]);
9102 if (READ_DATA_PENDING(fptr) || READ_CHAR_PENDING(fptr)) { /* check for buffered data */
9103 pending++;
9104 rb_fd_set(fptr->fd, &fds[3]);
9105 }
9106 if (max < fptr->fd) max = fptr->fd;
9107 }
9108 if (pending) { /* no blocking if there's buffered data */
9109 timerec.tv_sec = timerec.tv_usec = 0;
9110 tp = &timerec;
9111 }
9112 rp = &fds[0];
9113 }
9114 else
9115 rp = 0;
9116
9117 if (!NIL_P(write)) {
9119 for (i=0; i<RARRAY_LEN(write); i++) {
9121 GetOpenFile(write_io, fptr);
9122 rb_fd_set(fptr->fd, &fds[1]);
9123 if (max < fptr->fd) max = fptr->fd;
9124 }
9125 wp = &fds[1];
9126 }
9127 else
9128 wp = 0;
9129
9130 if (!NIL_P(except)) {
9131 Check_Type(except, T_ARRAY);
9132 for (i=0; i<RARRAY_LEN(except); i++) {
9133 VALUE io = rb_io_get_io(RARRAY_AREF(except, i));
9134 VALUE write_io = GetWriteIO(io);
9135 GetOpenFile(io, fptr);
9136 rb_fd_set(fptr->fd, &fds[2]);
9137 if (max < fptr->fd) max = fptr->fd;
9138 if (io != write_io) {
9139 GetOpenFile(write_io, fptr);
9140 rb_fd_set(fptr->fd, &fds[2]);
9141 if (max < fptr->fd) max = fptr->fd;
9142 }
9143 }
9144 ep = &fds[2];
9145 }
9146 else {
9147 ep = 0;
9148 }
9149
9150 max++;
9151
9152 n = rb_thread_fd_select(max, rp, wp, ep, tp);
9153 if (n < 0) {
9154 rb_sys_fail(0);
9155 }
9156 if (!pending && n == 0) return Qnil; /* returns nil on timeout */
9157
9158 res = rb_ary_new2(3);
9160 rb_ary_push(res, wp?rb_ary_new():rb_ary_new2(0));
9161 rb_ary_push(res, ep?rb_ary_new():rb_ary_new2(0));
9162
9163 if (rp) {
9164 list = RARRAY_AREF(res, 0);
9165 for (i=0; i< RARRAY_LEN(read); i++) {
9167 VALUE io = rb_io_get_io(obj);
9168 GetOpenFile(io, fptr);
9169 if (rb_fd_isset(fptr->fd, &fds[0]) ||
9170 rb_fd_isset(fptr->fd, &fds[3])) {
9172 }
9173 }
9174 }
9175
9176 if (wp) {
9177 list = RARRAY_AREF(res, 1);
9178 for (i=0; i< RARRAY_LEN(write); i++) {
9180 VALUE io = rb_io_get_io(obj);
9181 VALUE write_io = GetWriteIO(io);
9182 GetOpenFile(write_io, fptr);
9183 if (rb_fd_isset(fptr->fd, &fds[1])) {
9185 }
9186 }
9187 }
9188
9189 if (ep) {
9190 list = RARRAY_AREF(res, 2);
9191 for (i=0; i< RARRAY_LEN(except); i++) {
9192 VALUE obj = rb_ary_entry(except, i);
9193 VALUE io = rb_io_get_io(obj);
9194 VALUE write_io = GetWriteIO(io);
9195 GetOpenFile(io, fptr);
9196 if (rb_fd_isset(fptr->fd, &fds[2])) {
9198 }
9199 else if (io != write_io) {
9200 GetOpenFile(write_io, fptr);
9201 if (rb_fd_isset(fptr->fd, &fds[2])) {
9203 }
9204 }
9205 }
9206 }
9207
9208 return res; /* returns an empty array on interrupt */
9209}
9210
9215};
9216
9217static VALUE
9218select_call(VALUE arg)
9219{
9220 struct select_args *p = (struct select_args *)arg;
9221
9222 return select_internal(p->read, p->write, p->except, p->timeout, p->fdsets);
9223}
9224
9225static VALUE
9226select_end(VALUE arg)
9227{
9228 struct select_args *p = (struct select_args *)arg;
9229 int i;
9230
9231 for (i = 0; i < numberof(p->fdsets); ++i)
9232 rb_fd_term(&p->fdsets[i]);
9233 return Qnil;
9234}
9235
9236static VALUE sym_normal, sym_sequential, sym_random,
9237 sym_willneed, sym_dontneed, sym_noreuse;
9238
9239#ifdef HAVE_POSIX_FADVISE
9240struct io_advise_struct {
9241 int fd;
9242 int advice;
9243 off_t offset;
9244 off_t len;
9245};
9246
9247static VALUE
9248io_advise_internal(void *arg)
9249{
9250 struct io_advise_struct *ptr = arg;
9251 return posix_fadvise(ptr->fd, ptr->offset, ptr->len, ptr->advice);
9252}
9253
9254static VALUE
9255io_advise_sym_to_const(VALUE sym)
9256{
9257#ifdef POSIX_FADV_NORMAL
9258 if (sym == sym_normal)
9259 return INT2NUM(POSIX_FADV_NORMAL);
9260#endif
9261
9262#ifdef POSIX_FADV_RANDOM
9263 if (sym == sym_random)
9264 return INT2NUM(POSIX_FADV_RANDOM);
9265#endif
9266
9267#ifdef POSIX_FADV_SEQUENTIAL
9268 if (sym == sym_sequential)
9269 return INT2NUM(POSIX_FADV_SEQUENTIAL);
9270#endif
9271
9272#ifdef POSIX_FADV_WILLNEED
9273 if (sym == sym_willneed)
9274 return INT2NUM(POSIX_FADV_WILLNEED);
9275#endif
9276
9277#ifdef POSIX_FADV_DONTNEED
9278 if (sym == sym_dontneed)
9279 return INT2NUM(POSIX_FADV_DONTNEED);
9280#endif
9281
9282#ifdef POSIX_FADV_NOREUSE
9283 if (sym == sym_noreuse)
9284 return INT2NUM(POSIX_FADV_NOREUSE);
9285#endif
9286
9287 return Qnil;
9288}
9289
9290static VALUE
9291do_io_advise(rb_io_t *fptr, VALUE advice, off_t offset, off_t len)
9292{
9293 int rv;
9294 struct io_advise_struct ias;
9295 VALUE num_adv;
9296
9297 num_adv = io_advise_sym_to_const(advice);
9298
9299 /*
9300 * The platform doesn't support this hint. We don't raise exception, instead
9301 * silently ignore it. Because IO::advise is only hint.
9302 */
9303 if (NIL_P(num_adv))
9304 return Qnil;
9305
9306 ias.fd = fptr->fd;
9307 ias.advice = NUM2INT(num_adv);
9308 ias.offset = offset;
9309 ias.len = len;
9310
9311 rv = (int)rb_thread_io_blocking_region(io_advise_internal, &ias, fptr->fd);
9312 if (rv && rv != ENOSYS) {
9313 /* posix_fadvise(2) doesn't set errno. On success it returns 0; otherwise
9314 it returns the error code. */
9315 VALUE message = rb_sprintf("%"PRIsVALUE" "
9316 "(%"PRI_OFFT_PREFIX"d, "
9317 "%"PRI_OFFT_PREFIX"d, "
9318 "%"PRIsVALUE")",
9319 fptr->pathv, offset, len, advice);
9320 rb_syserr_fail_str(rv, message);
9321 }
9322
9323 return Qnil;
9324}
9325
9326#endif /* HAVE_POSIX_FADVISE */
9327
9328static void
9329advice_arg_check(VALUE advice)
9330{
9331 if (!SYMBOL_P(advice))
9332 rb_raise(rb_eTypeError, "advice must be a Symbol");
9333
9334 if (advice != sym_normal &&
9335 advice != sym_sequential &&
9336 advice != sym_random &&
9337 advice != sym_willneed &&
9338 advice != sym_dontneed &&
9339 advice != sym_noreuse) {
9340 rb_raise(rb_eNotImpError, "Unsupported advice: %+"PRIsVALUE, advice);
9341 }
9342}
9343
9344/*
9345 * call-seq:
9346 * ios.advise(advice, offset=0, len=0) -> nil
9347 *
9348 * Announce an intention to access data from the current file in a
9349 * specific pattern. On platforms that do not support the
9350 * <em>posix_fadvise(2)</em> system call, this method is a no-op.
9351 *
9352 * _advice_ is one of the following symbols:
9353 *
9354 * :normal:: No advice to give; the default assumption for an open file.
9355 * :sequential:: The data will be accessed sequentially
9356 * with lower offsets read before higher ones.
9357 * :random:: The data will be accessed in random order.
9358 * :willneed:: The data will be accessed in the near future.
9359 * :dontneed:: The data will not be accessed in the near future.
9360 * :noreuse:: The data will only be accessed once.
9361 *
9362 * The semantics of a piece of advice are platform-dependent. See
9363 * <em>man 2 posix_fadvise</em> for details.
9364 *
9365 * "data" means the region of the current file that begins at
9366 * _offset_ and extends for _len_ bytes. If _len_ is 0, the region
9367 * ends at the last byte of the file. By default, both _offset_ and
9368 * _len_ are 0, meaning that the advice applies to the entire file.
9369 *
9370 * If an error occurs, one of the following exceptions will be raised:
9371 *
9372 * IOError:: The IO stream is closed.
9373 * Errno::EBADF::
9374 * The file descriptor of the current file is invalid.
9375 * Errno::EINVAL:: An invalid value for _advice_ was given.
9376 * Errno::ESPIPE::
9377 * The file descriptor of the current file refers to a FIFO or
9378 * pipe. (Linux raises Errno::EINVAL in this case).
9379 * TypeError::
9380 * Either _advice_ was not a Symbol, or one of the
9381 * other arguments was not an Integer.
9382 * RangeError:: One of the arguments given was too big/small.
9383 *
9384 * This list is not exhaustive; other Errno:: exceptions are also possible.
9385 */
9386static VALUE
9387rb_io_advise(int argc, VALUE *argv, VALUE io)
9388{
9389 VALUE advice, offset, len;
9390 off_t off, l;
9391 rb_io_t *fptr;
9392
9393 rb_scan_args(argc, argv, "12", &advice, &offset, &len);
9394 advice_arg_check(advice);
9395
9396 io = GetWriteIO(io);
9397 GetOpenFile(io, fptr);
9398
9399 off = NIL_P(offset) ? 0 : NUM2OFFT(offset);
9400 l = NIL_P(len) ? 0 : NUM2OFFT(len);
9401
9402#ifdef HAVE_POSIX_FADVISE
9403 return do_io_advise(fptr, advice, off, l);
9404#else
9405 ((void)off, (void)l); /* Ignore all hint */
9406 return Qnil;
9407#endif
9408}
9409
9410/*
9411 * call-seq:
9412 * IO.select(read_array [, write_array [, error_array [, timeout]]]) -> array or nil
9413 *
9414 * Calls select(2) system call.
9415 * It monitors given arrays of IO objects, waits until one or more of
9416 * IO objects are ready for reading, are ready for writing, and have
9417 * pending exceptions respectively, and returns an array that contains
9418 * arrays of those IO objects. It will return +nil+ if optional
9419 * <i>timeout</i> value is given and no IO object is ready in
9420 * <i>timeout</i> seconds.
9421 *
9422 * IO.select peeks the buffer of IO objects for testing readability.
9423 * If the IO buffer is not empty, IO.select immediately notifies
9424 * readability. This "peek" only happens for IO objects. It does not
9425 * happen for IO-like objects such as OpenSSL::SSL::SSLSocket.
9426 *
9427 * The best way to use IO.select is invoking it after nonblocking
9428 * methods such as #read_nonblock, #write_nonblock, etc. The methods
9429 * raise an exception which is extended by IO::WaitReadable or
9430 * IO::WaitWritable. The modules notify how the caller should wait
9431 * with IO.select. If IO::WaitReadable is raised, the caller should
9432 * wait for reading. If IO::WaitWritable is raised, the caller should
9433 * wait for writing.
9434 *
9435 * So, blocking read (#readpartial) can be emulated using
9436 * #read_nonblock and IO.select as follows:
9437 *
9438 * begin
9439 * result = io_like.read_nonblock(maxlen)
9440 * rescue IO::WaitReadable
9441 * IO.select([io_like])
9442 * retry
9443 * rescue IO::WaitWritable
9444 * IO.select(nil, [io_like])
9445 * retry
9446 * end
9447 *
9448 * Especially, the combination of nonblocking methods and IO.select is
9449 * preferred for IO like objects such as OpenSSL::SSL::SSLSocket. It
9450 * has #to_io method to return underlying IO object. IO.select calls
9451 * #to_io to obtain the file descriptor to wait.
9452 *
9453 * This means that readability notified by IO.select doesn't mean
9454 * readability from OpenSSL::SSL::SSLSocket object.
9455 *
9456 * The most likely situation is that OpenSSL::SSL::SSLSocket buffers
9457 * some data. IO.select doesn't see the buffer. So IO.select can
9458 * block when OpenSSL::SSL::SSLSocket#readpartial doesn't block.
9459 *
9460 * However, several more complicated situations exist.
9461 *
9462 * SSL is a protocol which is sequence of records.
9463 * The record consists of multiple bytes.
9464 * So, the remote side of SSL sends a partial record, IO.select
9465 * notifies readability but OpenSSL::SSL::SSLSocket cannot decrypt a
9466 * byte and OpenSSL::SSL::SSLSocket#readpartial will block.
9467 *
9468 * Also, the remote side can request SSL renegotiation which forces
9469 * the local SSL engine to write some data.
9470 * This means OpenSSL::SSL::SSLSocket#readpartial may invoke #write
9471 * system call and it can block.
9472 * In such a situation, OpenSSL::SSL::SSLSocket#read_nonblock raises
9473 * IO::WaitWritable instead of blocking.
9474 * So, the caller should wait for ready for writability as above
9475 * example.
9476 *
9477 * The combination of nonblocking methods and IO.select is also useful
9478 * for streams such as tty, pipe socket socket when multiple processes
9479 * read from a stream.
9480 *
9481 * Finally, Linux kernel developers don't guarantee that
9482 * readability of select(2) means readability of following read(2) even
9483 * for a single process.
9484 * See select(2) manual on GNU/Linux system.
9485 *
9486 * Invoking IO.select before IO#readpartial works well as usual.
9487 * However it is not the best way to use IO.select.
9488 *
9489 * The writability notified by select(2) doesn't show
9490 * how many bytes are writable.
9491 * IO#write method blocks until given whole string is written.
9492 * So, <code>IO#write(two or more bytes)</code> can block after
9493 * writability is notified by IO.select. IO#write_nonblock is required
9494 * to avoid the blocking.
9495 *
9496 * Blocking write (#write) can be emulated using #write_nonblock and
9497 * IO.select as follows: IO::WaitReadable should also be rescued for
9498 * SSL renegotiation in OpenSSL::SSL::SSLSocket.
9499 *
9500 * while 0 < string.bytesize
9501 * begin
9502 * written = io_like.write_nonblock(string)
9503 * rescue IO::WaitReadable
9504 * IO.select([io_like])
9505 * retry
9506 * rescue IO::WaitWritable
9507 * IO.select(nil, [io_like])
9508 * retry
9509 * end
9510 * string = string.byteslice(written..-1)
9511 * end
9512 *
9513 * === Parameters
9514 * read_array:: an array of IO objects that wait until ready for read
9515 * write_array:: an array of IO objects that wait until ready for write
9516 * error_array:: an array of IO objects that wait for exceptions
9517 * timeout:: a numeric value in second
9518 *
9519 * === Example
9520 *
9521 * rp, wp = IO.pipe
9522 * mesg = "ping "
9523 * 100.times {
9524 * # IO.select follows IO#read. Not the best way to use IO.select.
9525 * rs, ws, = IO.select([rp], [wp])
9526 * if r = rs[0]
9527 * ret = r.read(5)
9528 * print ret
9529 * case ret
9530 * when /ping/
9531 * mesg = "pong\n"
9532 * when /pong/
9533 * mesg = "ping "
9534 * end
9535 * end
9536 * if w = ws[0]
9537 * w.write(mesg)
9538 * end
9539 * }
9540 *
9541 * <em>produces:</em>
9542 *
9543 * ping pong
9544 * ping pong
9545 * ping pong
9546 * (snipped)
9547 * ping
9548 */
9549
9550static VALUE
9551rb_f_select(int argc, VALUE *argv, VALUE obj)
9552{
9553 VALUE timeout;
9554 struct select_args args;
9555 struct timeval timerec;
9556 int i;
9557
9558 rb_scan_args(argc, argv, "13", &args.read, &args.write, &args.except, &timeout);
9559 if (NIL_P(timeout)) {
9560 args.timeout = 0;
9561 }
9562 else {
9563 timerec = rb_time_interval(timeout);
9564 args.timeout = &timerec;
9565 }
9566
9567 for (i = 0; i < numberof(args.fdsets); ++i)
9568 rb_fd_init(&args.fdsets[i]);
9569
9570 return rb_ensure(select_call, (VALUE)&args, select_end, (VALUE)&args);
9571}
9572
9573#if (defined(__linux__) && !defined(__ANDROID__)) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
9574 typedef unsigned long ioctl_req_t;
9575# define NUM2IOCTLREQ(num) NUM2ULONG(num)
9576#else
9577 typedef int ioctl_req_t;
9578# define NUM2IOCTLREQ(num) ((int)NUM2LONG(num))
9579#endif
9580
9581#ifdef HAVE_IOCTL
9582struct ioctl_arg {
9583 int fd;
9584 ioctl_req_t cmd;
9585 long narg;
9586};
9587
9588static VALUE
9589nogvl_ioctl(void *ptr)
9590{
9591 struct ioctl_arg *arg = ptr;
9592
9593 return (VALUE)ioctl(arg->fd, arg->cmd, arg->narg);
9594}
9595
9596static int
9597do_ioctl(int fd, ioctl_req_t cmd, long narg)
9598{
9599 int retval;
9600 struct ioctl_arg arg;
9601
9602 arg.fd = fd;
9603 arg.cmd = cmd;
9604 arg.narg = narg;
9605
9606 retval = (int)rb_thread_io_blocking_region(nogvl_ioctl, &arg, fd);
9607
9608 return retval;
9609}
9610#endif
9611
9612#define DEFULT_IOCTL_NARG_LEN (256)
9613
9614#if defined(__linux__) && defined(_IOC_SIZE)
9615static long
9616linux_iocparm_len(ioctl_req_t cmd)
9617{
9618 long len;
9619
9620 if ((cmd & 0xFFFF0000) == 0) {
9621 /* legacy and unstructured ioctl number. */
9622 return DEFULT_IOCTL_NARG_LEN;
9623 }
9624
9625 len = _IOC_SIZE(cmd);
9626
9627 /* paranoia check for silly drivers which don't keep ioctl convention */
9630
9631 return len;
9632}
9633#endif
9634
9635static long
9636ioctl_narg_len(ioctl_req_t cmd)
9637{
9638 long len;
9639
9640#ifdef IOCPARM_MASK
9641#ifndef IOCPARM_LEN
9642#define IOCPARM_LEN(x) (((x) >> 16) & IOCPARM_MASK)
9643#endif
9644#endif
9645#ifdef IOCPARM_LEN
9646 len = IOCPARM_LEN(cmd); /* on BSDish systems we're safe */
9647#elif defined(__linux__) && defined(_IOC_SIZE)
9648 len = linux_iocparm_len(cmd);
9649#else
9650 /* otherwise guess at what's safe */
9652#endif
9653
9654 return len;
9655}
9656
9657#ifdef HAVE_FCNTL
9658#ifdef __linux__
9659typedef long fcntl_arg_t;
9660#else
9661/* posix */
9662typedef int fcntl_arg_t;
9663#endif
9664
9665static long
9666fcntl_narg_len(int cmd)
9667{
9668 long len;
9669
9670 switch (cmd) {
9671#ifdef F_DUPFD
9672 case F_DUPFD:
9673 len = sizeof(fcntl_arg_t);
9674 break;
9675#endif
9676#ifdef F_DUP2FD /* bsd specific */
9677 case F_DUP2FD:
9678 len = sizeof(int);
9679 break;
9680#endif
9681#ifdef F_DUPFD_CLOEXEC /* linux specific */
9682 case F_DUPFD_CLOEXEC:
9683 len = sizeof(fcntl_arg_t);
9684 break;
9685#endif
9686#ifdef F_GETFD
9687 case F_GETFD:
9688 len = 1;
9689 break;
9690#endif
9691#ifdef F_SETFD
9692 case F_SETFD:
9693 len = sizeof(fcntl_arg_t);
9694 break;
9695#endif
9696#ifdef F_GETFL
9697 case F_GETFL:
9698 len = 1;
9699 break;
9700#endif
9701#ifdef F_SETFL
9702 case F_SETFL:
9703 len = sizeof(fcntl_arg_t);
9704 break;
9705#endif
9706#ifdef F_GETOWN
9707 case F_GETOWN:
9708 len = 1;
9709 break;
9710#endif
9711#ifdef F_SETOWN
9712 case F_SETOWN:
9713 len = sizeof(fcntl_arg_t);
9714 break;
9715#endif
9716#ifdef F_GETOWN_EX /* linux specific */
9717 case F_GETOWN_EX:
9718 len = sizeof(struct f_owner_ex);
9719 break;
9720#endif
9721#ifdef F_SETOWN_EX /* linux specific */
9722 case F_SETOWN_EX:
9723 len = sizeof(struct f_owner_ex);
9724 break;
9725#endif
9726#ifdef F_GETLK
9727 case F_GETLK:
9728 len = sizeof(struct flock);
9729 break;
9730#endif
9731#ifdef F_SETLK
9732 case F_SETLK:
9733 len = sizeof(struct flock);
9734 break;
9735#endif
9736#ifdef F_SETLKW
9737 case F_SETLKW:
9738 len = sizeof(struct flock);
9739 break;
9740#endif
9741#ifdef F_READAHEAD /* bsd specific */
9742 case F_READAHEAD:
9743 len = sizeof(int);
9744 break;
9745#endif
9746#ifdef F_RDAHEAD /* Darwin specific */
9747 case F_RDAHEAD:
9748 len = sizeof(int);
9749 break;
9750#endif
9751#ifdef F_GETSIG /* linux specific */
9752 case F_GETSIG:
9753 len = 1;
9754 break;
9755#endif
9756#ifdef F_SETSIG /* linux specific */
9757 case F_SETSIG:
9758 len = sizeof(fcntl_arg_t);
9759 break;
9760#endif
9761#ifdef F_GETLEASE /* linux specific */
9762 case F_GETLEASE:
9763 len = 1;
9764 break;
9765#endif
9766#ifdef F_SETLEASE /* linux specific */
9767 case F_SETLEASE:
9768 len = sizeof(fcntl_arg_t);
9769 break;
9770#endif
9771#ifdef F_NOTIFY /* linux specific */
9772 case F_NOTIFY:
9773 len = sizeof(fcntl_arg_t);
9774 break;
9775#endif
9776
9777 default:
9778 len = 256;
9779 break;
9780 }
9781
9782 return len;
9783}
9784#else /* HAVE_FCNTL */
9785static long
9786fcntl_narg_len(int cmd)
9787{
9788 return 0;
9789}
9790#endif /* HAVE_FCNTL */
9791
9792static long
9793setup_narg(ioctl_req_t cmd, VALUE *argp, int io_p)
9794{
9795 long narg = 0;
9796 VALUE arg = *argp;
9797
9798 if (NIL_P(arg) || arg == Qfalse) {
9799 narg = 0;
9800 }
9801 else if (FIXNUM_P(arg)) {
9802 narg = FIX2LONG(arg);
9803 }
9804 else if (arg == Qtrue) {
9805 narg = 1;
9806 }
9807 else {
9809
9810 if (NIL_P(tmp)) {
9811 narg = NUM2LONG(arg);
9812 }
9813 else {
9814 char *ptr;
9815 long len, slen;
9816
9817 *argp = arg = tmp;
9818 if (io_p)
9819 len = ioctl_narg_len(cmd);
9820 else
9821 len = fcntl_narg_len((int)cmd);
9823
9824 slen = RSTRING_LEN(arg);
9825 /* expand for data + sentinel. */
9826 if (slen < len+1) {
9827 rb_str_resize(arg, len+1);
9828 MEMZERO(RSTRING_PTR(arg)+slen, char, len-slen);
9829 slen = len+1;
9830 }
9831 /* a little sanity check here */
9832 ptr = RSTRING_PTR(arg);
9833 ptr[slen - 1] = 17;
9834 narg = (long)(SIGNED_VALUE)ptr;
9835 }
9836 }
9837
9838 return narg;
9839}
9840
9841#ifdef HAVE_IOCTL
9842static VALUE
9843rb_ioctl(VALUE io, VALUE req, VALUE arg)
9844{
9845 ioctl_req_t cmd = NUM2IOCTLREQ(req);
9846 rb_io_t *fptr;
9847 long narg;
9848 int retval;
9849
9850 narg = setup_narg(cmd, &arg, 1);
9851 GetOpenFile(io, fptr);
9852 retval = do_ioctl(fptr->fd, cmd, narg);
9853 if (retval < 0) rb_sys_fail_path(fptr->pathv);
9854 if (RB_TYPE_P(arg, T_STRING)) {
9855 char *ptr;
9856 long slen;
9857 RSTRING_GETMEM(arg, ptr, slen);
9858 if (ptr[slen-1] != 17)
9859 rb_raise(rb_eArgError, "return value overflowed string");
9860 ptr[slen-1] = '\0';
9861 }
9862
9863 return INT2NUM(retval);
9864}
9865
9866/*
9867 * call-seq:
9868 * ios.ioctl(integer_cmd, arg) -> integer
9869 *
9870 * Provides a mechanism for issuing low-level commands to control or
9871 * query I/O devices. Arguments and results are platform dependent. If
9872 * <i>arg</i> is a number, its value is passed directly. If it is a
9873 * string, it is interpreted as a binary sequence of bytes. On Unix
9874 * platforms, see <code>ioctl(2)</code> for details. Not implemented on
9875 * all platforms.
9876 */
9877
9878static VALUE
9879rb_io_ioctl(int argc, VALUE *argv, VALUE io)
9880{
9881 VALUE req, arg;
9882
9883 rb_scan_args(argc, argv, "11", &req, &arg);
9884 return rb_ioctl(io, req, arg);
9885}
9886#else
9887#define rb_io_ioctl rb_f_notimplement
9888#endif
9889
9890#ifdef HAVE_FCNTL
9891struct fcntl_arg {
9892 int fd;
9893 int cmd;
9894 long narg;
9895};
9896
9897static VALUE
9898nogvl_fcntl(void *ptr)
9899{
9900 struct fcntl_arg *arg = ptr;
9901
9902#if defined(F_DUPFD)
9903 if (arg->cmd == F_DUPFD)
9904 return (VALUE)rb_cloexec_fcntl_dupfd(arg->fd, (int)arg->narg);
9905#endif
9906 return (VALUE)fcntl(arg->fd, arg->cmd, arg->narg);
9907}
9908
9909static int
9910do_fcntl(int fd, int cmd, long narg)
9911{
9912 int retval;
9913 struct fcntl_arg arg;
9914
9915 arg.fd = fd;
9916 arg.cmd = cmd;
9917 arg.narg = narg;
9918
9919 retval = (int)rb_thread_io_blocking_region(nogvl_fcntl, &arg, fd);
9920 if (retval != -1) {
9921 switch (cmd) {
9922#if defined(F_DUPFD)
9923 case F_DUPFD:
9924#endif
9925#if defined(F_DUPFD_CLOEXEC)
9926 case F_DUPFD_CLOEXEC:
9927#endif
9928 rb_update_max_fd(retval);
9929 }
9930 }
9931
9932 return retval;
9933}
9934
9935static VALUE
9936rb_fcntl(VALUE io, VALUE req, VALUE arg)
9937{
9938 int cmd = NUM2INT(req);
9939 rb_io_t *fptr;
9940 long narg;
9941 int retval;
9942
9943 narg = setup_narg(cmd, &arg, 0);
9944 GetOpenFile(io, fptr);
9945 retval = do_fcntl(fptr->fd, cmd, narg);
9946 if (retval < 0) rb_sys_fail_path(fptr->pathv);
9947 if (RB_TYPE_P(arg, T_STRING)) {
9948 char *ptr;
9949 long slen;
9950 RSTRING_GETMEM(arg, ptr, slen);
9951 if (ptr[slen-1] != 17)
9952 rb_raise(rb_eArgError, "return value overflowed string");
9953 ptr[slen-1] = '\0';
9954 }
9955
9956 return INT2NUM(retval);
9957}
9958
9959/*
9960 * call-seq:
9961 * ios.fcntl(integer_cmd, arg) -> integer
9962 *
9963 * Provides a mechanism for issuing low-level commands to control or
9964 * query file-oriented I/O streams. Arguments and results are platform
9965 * dependent. If <i>arg</i> is a number, its value is passed
9966 * directly. If it is a string, it is interpreted as a binary sequence
9967 * of bytes (Array#pack might be a useful way to build this string). On
9968 * Unix platforms, see <code>fcntl(2)</code> for details. Not
9969 * implemented on all platforms.
9970 */
9971
9972static VALUE
9973rb_io_fcntl(int argc, VALUE *argv, VALUE io)
9974{
9975 VALUE req, arg;
9976
9977 rb_scan_args(argc, argv, "11", &req, &arg);
9978 return rb_fcntl(io, req, arg);
9979}
9980#else
9981#define rb_io_fcntl rb_f_notimplement
9982#endif
9983
9984#if defined(HAVE_SYSCALL) || defined(HAVE___SYSCALL)
9985/*
9986 * call-seq:
9987 * syscall(num [, args...]) -> integer
9988 *
9989 * Calls the operating system function identified by _num_ and
9990 * returns the result of the function or raises SystemCallError if
9991 * it failed.
9992 *
9993 * Arguments for the function can follow _num_. They must be either
9994 * +String+ objects or +Integer+ objects. A +String+ object is passed
9995 * as a pointer to the byte sequence. An +Integer+ object is passed
9996 * as an integer whose bit size is same as a pointer.
9997 * Up to nine parameters may be passed.
9998 *
9999 * The function identified by _num_ is system
10000 * dependent. On some Unix systems, the numbers may be obtained from a
10001 * header file called <code>syscall.h</code>.
10002 *
10003 * syscall 4, 1, "hello\n", 6 # '4' is write(2) on our box
10004 *
10005 * <em>produces:</em>
10006 *
10007 * hello
10008 *
10009 * Calling +syscall+ on a platform which does not have any way to
10010 * an arbitrary system function just fails with NotImplementedError.
10011 *
10012 * *Note:*
10013 * +syscall+ is essentially unsafe and unportable.
10014 * Feel free to shoot your foot.
10015 * The DL (Fiddle) library is preferred for safer and a bit
10016 * more portable programming.
10017 */
10018
10019static VALUE
10021{
10022 VALUE arg[8];
10023#if SIZEOF_VOIDP == 8 && defined(HAVE___SYSCALL) && SIZEOF_INT != 8 /* mainly *BSD */
10024# define SYSCALL __syscall
10025# define NUM2SYSCALLID(x) NUM2LONG(x)
10026# define RETVAL2NUM(x) LONG2NUM(x)
10027# if SIZEOF_LONG == 8
10028 long num, retval = -1;
10029# elif SIZEOF_LONG_LONG == 8
10030 long long num, retval = -1;
10031# else
10032# error ---->> it is asserted that __syscall takes the first argument and returns retval in 64bit signed integer. <<----
10033# endif
10034#elif defined(__linux__)
10035# define SYSCALL syscall
10036# define NUM2SYSCALLID(x) NUM2LONG(x)
10037# define RETVAL2NUM(x) LONG2NUM(x)
10038 /*
10039 * Linux man page says, syscall(2) function prototype is below.
10040 *
10041 * int syscall(int number, ...);
10042 *
10043 * But, it's incorrect. Actual one takes and returned long. (see unistd.h)
10044 */
10045 long num, retval = -1;
10046#else
10047# define SYSCALL syscall
10048# define NUM2SYSCALLID(x) NUM2INT(x)
10049# define RETVAL2NUM(x) INT2NUM(x)
10050 int num, retval = -1;
10051#endif
10052 int i;
10053
10054 if (RTEST(ruby_verbose)) {
10055 rb_warning("We plan to remove a syscall function at future release. DL(Fiddle) provides safer alternative.");
10056 }
10057
10058 if (argc == 0)
10059 rb_raise(rb_eArgError, "too few arguments for syscall");
10060 if (argc > numberof(arg))
10061 rb_raise(rb_eArgError, "too many arguments for syscall");
10062 num = NUM2SYSCALLID(argv[0]); ++argv;
10063 for (i = argc - 1; i--; ) {
10065
10066 if (!NIL_P(v)) {
10070 }
10071 else {
10072 arg[i] = (VALUE)NUM2LONG(argv[i]);
10073 }
10074 }
10075
10076 switch (argc) {
10077 case 1:
10078 retval = SYSCALL(num);
10079 break;
10080 case 2:
10081 retval = SYSCALL(num, arg[0]);
10082 break;
10083 case 3:
10084 retval = SYSCALL(num, arg[0],arg[1]);
10085 break;
10086 case 4:
10087 retval = SYSCALL(num, arg[0],arg[1],arg[2]);
10088 break;
10089 case 5:
10090 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3]);
10091 break;
10092 case 6:
10093 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4]);
10094 break;
10095 case 7:
10096 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5]);
10097 break;
10098 case 8:
10099 retval = SYSCALL(num, arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6]);
10100 break;
10101 }
10102
10103 if (retval == -1)
10104 rb_sys_fail(0);
10105 return RETVAL2NUM(retval);
10106#undef SYSCALL
10107#undef NUM2SYSCALLID
10108#undef RETVAL2NUM
10109}
10110#else
10111#define rb_f_syscall rb_f_notimplement
10112#endif
10113
10114static VALUE
10115io_new_instance(VALUE args)
10116{
10117 return rb_class_new_instance(2, (VALUE*)args+1, *(VALUE*)args);
10118}
10119
10120static rb_encoding *
10121find_encoding(VALUE v)
10122{
10124 if (!enc) rb_warn("Unsupported encoding %"PRIsVALUE" ignored", v);
10125 return enc;
10126}
10127
10128static void
10129io_encoding_set(rb_io_t *fptr, VALUE v1, VALUE v2, VALUE opt)
10130{
10131 rb_encoding *enc, *enc2;
10132 int ecflags = fptr->encs.ecflags;
10133 VALUE ecopts, tmp;
10134
10135 if (!NIL_P(v2)) {
10136 enc2 = find_encoding(v1);
10137 tmp = rb_check_string_type(v2);
10138 if (!NIL_P(tmp)) {
10139 if (RSTRING_LEN(tmp) == 1 && RSTRING_PTR(tmp)[0] == '-') {
10140 /* Special case - "-" => no transcoding */
10141 enc = enc2;
10142 enc2 = NULL;
10143 }
10144 else
10145 enc = find_encoding(v2);
10146 if (enc == enc2) {
10147 /* Special case - "-" => no transcoding */
10148 enc2 = NULL;
10149 }
10150 }
10151 else {
10152 enc = find_encoding(v2);
10153 if (enc == enc2) {
10154 /* Special case - "-" => no transcoding */
10155 enc2 = NULL;
10156 }
10157 }
10159 ecflags = rb_econv_prepare_options(opt, &ecopts, ecflags);
10160 }
10161 else {
10162 if (NIL_P(v1)) {
10163 /* Set to default encodings */
10164 rb_io_ext_int_to_encs(NULL, NULL, &enc, &enc2, 0);
10166 ecopts = Qnil;
10167 }
10168 else {
10169 tmp = rb_check_string_type(v1);
10170 if (!NIL_P(tmp) && rb_enc_asciicompat(enc = rb_enc_get(tmp))) {
10171 parse_mode_enc(RSTRING_PTR(tmp), enc, &enc, &enc2, NULL);
10173 ecflags = rb_econv_prepare_options(opt, &ecopts, ecflags);
10174 }
10175 else {
10176 rb_io_ext_int_to_encs(find_encoding(v1), NULL, &enc, &enc2, 0);
10178 ecopts = Qnil;
10179 }
10180 }
10181 }
10182 validate_enc_binmode(&fptr->mode, ecflags, enc, enc2);
10183 fptr->encs.enc = enc;
10184 fptr->encs.enc2 = enc2;
10185 fptr->encs.ecflags = ecflags;
10186 fptr->encs.ecopts = ecopts;
10187 clear_codeconv(fptr);
10188
10189}
10190
10196};
10197
10198static VALUE
10199io_encoding_set_v(VALUE v)
10200{
10201 struct io_encoding_set_args *arg = (struct io_encoding_set_args *)v;
10202 io_encoding_set(arg->fptr, arg->v1, arg->v2, arg->opt);
10203 return Qnil;
10204}
10205
10206static VALUE
10207pipe_pair_close(VALUE rw)
10208{
10209 VALUE *rwp = (VALUE *)rw;
10210 return rb_ensure(io_close, rwp[0], io_close, rwp[1]);
10211}
10212
10213/*
10214 * call-seq:
10215 * IO.pipe -> [read_io, write_io]
10216 * IO.pipe(ext_enc) -> [read_io, write_io]
10217 * IO.pipe("ext_enc:int_enc" [, opt]) -> [read_io, write_io]
10218 * IO.pipe(ext_enc, int_enc [, opt]) -> [read_io, write_io]
10219 *
10220 * IO.pipe(...) {|read_io, write_io| ... }
10221 *
10222 * Creates a pair of pipe endpoints (connected to each other) and
10223 * returns them as a two-element array of IO objects:
10224 * <code>[</code> <i>read_io</i>, <i>write_io</i> <code>]</code>.
10225 *
10226 * If a block is given, the block is called and
10227 * returns the value of the block.
10228 * <i>read_io</i> and <i>write_io</i> are sent to the block as arguments.
10229 * If read_io and write_io are not closed when the block exits, they are closed.
10230 * i.e. closing read_io and/or write_io doesn't cause an error.
10231 *
10232 * Not available on all platforms.
10233 *
10234 * If an encoding (encoding name or encoding object) is specified as an optional argument,
10235 * read string from pipe is tagged with the encoding specified.
10236 * If the argument is a colon separated two encoding names "A:B",
10237 * the read string is converted from encoding A (external encoding)
10238 * to encoding B (internal encoding), then tagged with B.
10239 * If two optional arguments are specified, those must be
10240 * encoding objects or encoding names,
10241 * and the first one is the external encoding,
10242 * and the second one is the internal encoding.
10243 * If the external encoding and the internal encoding is specified,
10244 * optional hash argument specify the conversion option.
10245 *
10246 * In the example below, the two processes close the ends of the pipe
10247 * that they are not using. This is not just a cosmetic nicety. The
10248 * read end of a pipe will not generate an end of file condition if
10249 * there are any writers with the pipe still open. In the case of the
10250 * parent process, the <code>rd.read</code> will never return if it
10251 * does not first issue a <code>wr.close</code>.
10252 *
10253 * rd, wr = IO.pipe
10254 *
10255 * if fork
10256 * wr.close
10257 * puts "Parent got: <#{rd.read}>"
10258 * rd.close
10259 * Process.wait
10260 * else
10261 * rd.close
10262 * puts "Sending message to parent"
10263 * wr.write "Hi Dad"
10264 * wr.close
10265 * end
10266 *
10267 * <em>produces:</em>
10268 *
10269 * Sending message to parent
10270 * Parent got: <Hi Dad>
10271 */
10272
10273static VALUE
10274rb_io_s_pipe(int argc, VALUE *argv, VALUE klass)
10275{
10276 int pipes[2], state;
10277 VALUE r, w, args[3], v1, v2;
10278 VALUE opt;
10279 rb_io_t *fptr, *fptr2;
10280 struct io_encoding_set_args ies_args;
10281 int fmode = 0;
10282 VALUE ret;
10283
10284 argc = rb_scan_args(argc, argv, "02:", &v1, &v2, &opt);
10285 if (rb_pipe(pipes) < 0)
10286 rb_sys_fail(0);
10287
10288 args[0] = klass;
10289 args[1] = INT2NUM(pipes[0]);
10290 args[2] = INT2FIX(O_RDONLY);
10291 r = rb_protect(io_new_instance, (VALUE)args, &state);
10292 if (state) {
10293 close(pipes[0]);
10294 close(pipes[1]);
10295 rb_jump_tag(state);
10296 }
10297 GetOpenFile(r, fptr);
10298
10299 ies_args.fptr = fptr;
10300 ies_args.v1 = v1;
10301 ies_args.v2 = v2;
10302 ies_args.opt = opt;
10303 rb_protect(io_encoding_set_v, (VALUE)&ies_args, &state);
10304 if (state) {
10305 close(pipes[1]);
10306 io_close(r);
10307 rb_jump_tag(state);
10308 }
10309
10310 args[1] = INT2NUM(pipes[1]);
10311 args[2] = INT2FIX(O_WRONLY);
10312 w = rb_protect(io_new_instance, (VALUE)args, &state);
10313 if (state) {
10314 close(pipes[1]);
10315 if (!NIL_P(r)) rb_io_close(r);
10316 rb_jump_tag(state);
10317 }
10318 GetOpenFile(w, fptr2);
10319 rb_io_synchronized(fptr2);
10320
10321 extract_binmode(opt, &fmode);
10322
10323 if ((fmode & FMODE_BINMODE) && v1 == Qnil) {
10326 }
10327
10328#if DEFAULT_TEXTMODE
10329 if ((fptr->mode & FMODE_TEXTMODE) && (fmode & FMODE_BINMODE)) {
10330 fptr->mode &= ~FMODE_TEXTMODE;
10331 setmode(fptr->fd, O_BINARY);
10332 }
10333#if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32)
10336 }
10337#endif
10338#endif
10339 fptr->mode |= fmode;
10340#if DEFAULT_TEXTMODE
10341 if ((fptr2->mode & FMODE_TEXTMODE) && (fmode & FMODE_BINMODE)) {
10342 fptr2->mode &= ~FMODE_TEXTMODE;
10343 setmode(fptr2->fd, O_BINARY);
10344 }
10345#endif
10346 fptr2->mode |= fmode;
10347
10348 ret = rb_assoc_new(r, w);
10349 if (rb_block_given_p()) {
10350 VALUE rw[2];
10351 rw[0] = r;
10352 rw[1] = w;
10353 return rb_ensure(rb_yield, ret, pipe_pair_close, (VALUE)rw);
10354 }
10355 return ret;
10356}
10357
10359 int argc;
10362};
10363
10364static void
10365open_key_args(VALUE klass, int argc, VALUE *argv, VALUE opt, struct foreach_arg *arg)
10366{
10367 VALUE path, v;
10368 VALUE vmode = Qnil, vperm = Qnil;
10369
10370 path = *argv++;
10371 argc--;
10373 arg->io = 0;
10374 arg->argc = argc;
10375 arg->argv = argv;
10376 if (NIL_P(opt)) {
10377 vmode = INT2NUM(O_RDONLY);
10378 vperm = INT2FIX(0666);
10379 }
10380 else if (!NIL_P(v = rb_hash_aref(opt, sym_open_args))) {
10381 int n;
10382
10383 v = rb_to_array_type(v);
10384 n = RARRAY_LENINT(v);
10385 rb_check_arity(n, 0, 3); /* rb_io_open */
10386 rb_scan_args_kw(RB_SCAN_ARGS_LAST_HASH_KEYWORDS, n, RARRAY_CONST_PTR(v), "02:", &vmode, &vperm, &opt);
10387 }
10388 arg->io = rb_io_open(klass, path, vmode, vperm, opt);
10389}
10390
10391static VALUE
10392io_s_foreach(VALUE v)
10393{
10394 struct getline_arg *arg = (void *)v;
10395 VALUE str;
10396
10397 while (!NIL_P(str = rb_io_getline_1(arg->rs, arg->limit, arg->chomp, arg->io))) {
10399 rb_yield(str);
10400 }
10402 return Qnil;
10403}
10404
10405/*
10406 * call-seq:
10407 * IO.foreach(name, sep=$/ [, getline_args, open_args]) {|line| block } -> nil
10408 * IO.foreach(name, limit [, getline_args, open_args]) {|line| block } -> nil
10409 * IO.foreach(name, sep, limit [, getline_args, open_args]) {|line| block } -> nil
10410 * IO.foreach(...) -> an_enumerator
10411 *
10412 * Executes the block for every line in the named I/O port, where lines
10413 * are separated by <em>sep</em>.
10414 *
10415 * If no block is given, an enumerator is returned instead.
10416 *
10417 * IO.foreach("testfile") {|x| print "GOT ", x }
10418 *
10419 * <em>produces:</em>
10420 *
10421 * GOT This is line one
10422 * GOT This is line two
10423 * GOT This is line three
10424 * GOT And so on...
10425 *
10426 * If the last argument is a hash, it's the keyword argument to open.
10427 * See IO.readlines for details about getline_args.
10428 * And see also IO.read for details about open_args.
10429 *
10430 */
10431
10432static VALUE
10433rb_io_s_foreach(int argc, VALUE *argv, VALUE self)
10434{
10435 VALUE opt;
10436 int orig_argc = argc;
10437 struct foreach_arg arg;
10438 struct getline_arg garg;
10439
10440 argc = rb_scan_args(argc, argv, "13:", NULL, NULL, NULL, NULL, &opt);
10441 RETURN_ENUMERATOR(self, orig_argc, argv);
10442 extract_getline_args(argc-1, argv+1, &garg);
10443 open_key_args(self, argc, argv, opt, &arg);
10444 if (NIL_P(arg.io)) return Qnil;
10445 extract_getline_opts(opt, &garg);
10446 check_getline_args(&garg.rs, &garg.limit, garg.io = arg.io);
10447 return rb_ensure(io_s_foreach, (VALUE)&garg, rb_io_close, arg.io);
10448}
10449
10450static VALUE
10451io_s_readlines(VALUE v)
10452{
10453 struct getline_arg *arg = (void *)v;
10454 return io_readlines(arg, arg->io);
10455}
10456
10457/*
10458 * call-seq:
10459 * IO.readlines(name, sep=$/ [, getline_args, open_args]) -> array
10460 * IO.readlines(name, limit [, getline_args, open_args]) -> array
10461 * IO.readlines(name, sep, limit [, getline_args, open_args]) -> array
10462 *
10463 * Reads the entire file specified by <i>name</i> as individual
10464 * lines, and returns those lines in an array. Lines are separated by
10465 * <i>sep</i>.
10466 *
10467 * a = IO.readlines("testfile")
10468 * a[0] #=> "This is line one\n"
10469 *
10470 * b = IO.readlines("testfile", chomp: true)
10471 * b[0] #=> "This is line one"
10472 *
10473 * If the last argument is a hash, it's the keyword argument to open.
10474 *
10475 * === Options for getline
10476 *
10477 * The options hash accepts the following keys:
10478 *
10479 * :chomp::
10480 * When the optional +chomp+ keyword argument has a true value,
10481 * <code>\n</code>, <code>\r</code>, and <code>\r\n</code>
10482 * will be removed from the end of each line.
10483 *
10484 * See also IO.read for details about open_args.
10485 */
10486
10487static VALUE
10488rb_io_s_readlines(int argc, VALUE *argv, VALUE io)
10489{
10490 VALUE opt;
10491 struct foreach_arg arg;
10492 struct getline_arg garg;
10493
10494 argc = rb_scan_args(argc, argv, "13:", NULL, NULL, NULL, NULL, &opt);
10495 extract_getline_args(argc-1, argv+1, &garg);
10496 open_key_args(io, argc, argv, opt, &arg);
10497 if (NIL_P(arg.io)) return Qnil;
10498 extract_getline_opts(opt, &garg);
10499 check_getline_args(&garg.rs, &garg.limit, garg.io = arg.io);
10500 return rb_ensure(io_s_readlines, (VALUE)&garg, rb_io_close, arg.io);
10501}
10502
10503static VALUE
10504io_s_read(VALUE v)
10505{
10506 struct foreach_arg *arg = (void *)v;
10507 return io_read(arg->argc, arg->argv, arg->io);
10508}
10509
10510struct seek_arg {
10513 int mode;
10514};
10515
10516static VALUE
10517seek_before_access(VALUE argp)
10518{
10519 struct seek_arg *arg = (struct seek_arg *)argp;
10520 rb_io_binmode(arg->io);
10521 return rb_io_seek(arg->io, arg->offset, arg->mode);
10522}
10523
10524/*
10525 * call-seq:
10526 * IO.read(name, [length [, offset]] [, opt] ) -> string
10527 *
10528 * Opens the file, optionally seeks to the given +offset+, then returns
10529 * +length+ bytes (defaulting to the rest of the file). #read ensures
10530 * the file is closed before returning.
10531 *
10532 * If +name+ starts with a pipe character (<code>"|"</code>), a subprocess is
10533 * created in the same way as Kernel#open, and its output is returned.
10534 *
10535 * === Options
10536 *
10537 * The options hash accepts the following keys:
10538 *
10539 * :encoding::
10540 * string or encoding
10541 *
10542 * Specifies the encoding of the read string. +:encoding+ will be ignored
10543 * if +length+ is specified. See Encoding.aliases for possible encodings.
10544 *
10545 * :mode::
10546 * string or integer
10547 *
10548 * Specifies the <i>mode</i> argument for open(). It must start
10549 * with an "r", otherwise it will cause an error.
10550 * See IO.new for the list of possible modes.
10551 *
10552 * :open_args::
10553 * array
10554 *
10555 * Specifies arguments for open() as an array. This key can not be used
10556 * in combination with either +:encoding+ or +:mode+.
10557 *
10558 * Examples:
10559 *
10560 * IO.read("testfile") #=> "This is line one\nThis is line two\nThis is line three\nAnd so on...\n"
10561 * IO.read("testfile", 20) #=> "This is line one\nThi"
10562 * IO.read("testfile", 20, 10) #=> "ne one\nThis is line "
10563 * IO.read("binfile", mode: "rb") #=> "\xF7\x00\x00\x0E\x12"
10564 */
10565
10566static VALUE
10567rb_io_s_read(int argc, VALUE *argv, VALUE io)
10568{
10569 VALUE opt, offset;
10570 struct foreach_arg arg;
10571
10572 argc = rb_scan_args(argc, argv, "13:", NULL, NULL, &offset, NULL, &opt);
10573 open_key_args(io, argc, argv, opt, &arg);
10574 if (NIL_P(arg.io)) return Qnil;
10575 if (!NIL_P(offset)) {
10576 struct seek_arg sarg;
10577 int state = 0;
10578 sarg.io = arg.io;
10579 sarg.offset = offset;
10580 sarg.mode = SEEK_SET;
10581 rb_protect(seek_before_access, (VALUE)&sarg, &state);
10582 if (state) {
10583 rb_io_close(arg.io);
10584 rb_jump_tag(state);
10585 }
10586 if (arg.argc == 2) arg.argc = 1;
10587 }
10588 return rb_ensure(io_s_read, (VALUE)&arg, rb_io_close, arg.io);
10589}
10590
10591/*
10592 * call-seq:
10593 * IO.binread(name, [length [, offset]] ) -> string
10594 *
10595 * Opens the file, optionally seeks to the given <i>offset</i>, then
10596 * returns <i>length</i> bytes (defaulting to the rest of the file).
10597 * #binread ensures the file is closed before returning. The open mode
10598 * would be <code>"rb:ASCII-8BIT"</code>.
10599 *
10600 * IO.binread("testfile") #=> "This is line one\nThis is line two\nThis is line three\nAnd so on...\n"
10601 * IO.binread("testfile", 20) #=> "This is line one\nThi"
10602 * IO.binread("testfile", 20, 10) #=> "ne one\nThis is line "
10603 */
10604
10605static VALUE
10606rb_io_s_binread(int argc, VALUE *argv, VALUE io)
10607{
10608 VALUE offset;
10609 struct foreach_arg arg;
10610 enum {
10612 oflags = O_RDONLY
10613#ifdef O_BINARY
10614 |O_BINARY
10615#endif
10616 };
10617 convconfig_t convconfig = {NULL, NULL, 0, Qnil};
10618
10619 rb_scan_args(argc, argv, "12", NULL, NULL, &offset);
10620 FilePathValue(argv[0]);
10621 convconfig.enc = rb_ascii8bit_encoding();
10622 arg.io = rb_io_open_generic(io, argv[0], oflags, fmode, &convconfig, 0);
10623 if (NIL_P(arg.io)) return Qnil;
10624 arg.argv = argv+1;
10625 arg.argc = (argc > 1) ? 1 : 0;
10626 if (!NIL_P(offset)) {
10627 struct seek_arg sarg;
10628 int state = 0;
10629 sarg.io = arg.io;
10630 sarg.offset = offset;
10631 sarg.mode = SEEK_SET;
10632 rb_protect(seek_before_access, (VALUE)&sarg, &state);
10633 if (state) {
10634 rb_io_close(arg.io);
10635 rb_jump_tag(state);
10636 }
10637 }
10638 return rb_ensure(io_s_read, (VALUE)&arg, rb_io_close, arg.io);
10639}
10640
10641static VALUE
10642io_s_write0(VALUE v)
10643{
10644 struct write_arg *arg = (void * )v;
10645 return io_write(arg->io,arg->str,arg->nosync);
10646}
10647
10648static VALUE
10649io_s_write(int argc, VALUE *argv, VALUE klass, int binary)
10650{
10651 VALUE string, offset, opt;
10652 struct foreach_arg arg;
10653 struct write_arg warg;
10654
10655 rb_scan_args(argc, argv, "21:", NULL, &string, &offset, &opt);
10656
10657 if (NIL_P(opt)) opt = rb_hash_new();
10658 else opt = rb_hash_dup(opt);
10659
10660
10661 if (NIL_P(rb_hash_aref(opt,sym_mode))) {
10662 int mode = O_WRONLY|O_CREAT;
10663#ifdef O_BINARY
10664 if (binary) mode |= O_BINARY;
10665#endif
10666 if (NIL_P(offset)) mode |= O_TRUNC;
10667 rb_hash_aset(opt,sym_mode,INT2NUM(mode));
10668 }
10669 open_key_args(klass, argc, argv, opt, &arg);
10670
10671#ifndef O_BINARY
10672 if (binary) rb_io_binmode_m(arg.io);
10673#endif
10674
10675 if (NIL_P(arg.io)) return Qnil;
10676 if (!NIL_P(offset)) {
10677 struct seek_arg sarg;
10678 int state = 0;
10679 sarg.io = arg.io;
10680 sarg.offset = offset;
10681 sarg.mode = SEEK_SET;
10682 rb_protect(seek_before_access, (VALUE)&sarg, &state);
10683 if (state) {
10684 rb_io_close(arg.io);
10685 rb_jump_tag(state);
10686 }
10687 }
10688
10689 warg.io = arg.io;
10690 warg.str = string;
10691 warg.nosync = 0;
10692
10693 return rb_ensure(io_s_write0, (VALUE)&warg, rb_io_close, arg.io);
10694}
10695
10696/*
10697 * call-seq:
10698 * IO.write(name, string [, offset]) -> integer
10699 * IO.write(name, string [, offset] [, opt]) -> integer
10700 *
10701 * Opens the file, optionally seeks to the given <i>offset</i>, writes
10702 * <i>string</i>, then returns the length written. #write ensures the
10703 * file is closed before returning. If <i>offset</i> is not given in
10704 * write mode, the file is truncated. Otherwise, it is not truncated.
10705 *
10706 * IO.write("testfile", "0123456789", 20) #=> 10
10707 * # File could contain: "This is line one\nThi0123456789two\nThis is line three\nAnd so on...\n"
10708 * IO.write("testfile", "0123456789") #=> 10
10709 * # File would now read: "0123456789"
10710 *
10711 * If the last argument is a hash, it specifies options for the internal
10712 * open(). It accepts the following keys:
10713 *
10714 * :encoding::
10715 * string or encoding
10716 *
10717 * Specifies the encoding of the read string.
10718 * See Encoding.aliases for possible encodings.
10719 *
10720 * :mode::
10721 * string or integer
10722 *
10723 * Specifies the <i>mode</i> argument for open(). It must start
10724 * with "w", "a", or "r+", otherwise it will cause an error.
10725 * See IO.new for the list of possible modes.
10726 *
10727 * :perm::
10728 * integer
10729 *
10730 * Specifies the <i>perm</i> argument for open().
10731 *
10732 * :open_args::
10733 * array
10734 *
10735 * Specifies arguments for open() as an array.
10736 * This key can not be used in combination with other keys.
10737 */
10738
10739static VALUE
10740rb_io_s_write(int argc, VALUE *argv, VALUE io)
10741{
10742 return io_s_write(argc, argv, io, 0);
10743}
10744
10745/*
10746 * call-seq:
10747 * IO.binwrite(name, string, [offset] ) -> integer
10748 * IO.binwrite(name, string, [offset], open_args ) -> integer
10749 *
10750 * Same as IO.write except opening the file in binary mode and
10751 * ASCII-8BIT encoding (<code>"wb:ASCII-8BIT"</code>).
10752 */
10753
10754static VALUE
10755rb_io_s_binwrite(int argc, VALUE *argv, VALUE io)
10756{
10757 return io_s_write(argc, argv, io, 1);
10758}
10759
10763 off_t copy_length; /* (off_t)-1 if not specified */
10764 off_t src_offset; /* (off_t)-1 if not specified */
10765
10768 unsigned close_src : 1;
10769 unsigned close_dst : 1;
10772 const char *syserr;
10773 const char *notimp;
10777#ifdef HAVE_FCOPYFILE
10778 copyfile_state_t copyfile_state;
10779#endif
10780};
10781
10782static void *
10783exec_interrupts(void *arg)
10784{
10785 VALUE th = (VALUE)arg;
10787 return NULL;
10788}
10789
10790/*
10791 * returns TRUE if the preceding system call was interrupted
10792 * so we can continue. If the thread was interrupted, we
10793 * reacquire the GVL to execute interrupts before continuing.
10794 */
10795static int
10796maygvl_copy_stream_continue_p(int has_gvl, struct copy_stream_struct *stp)
10797{
10798 switch (errno) {
10799 case EINTR:
10800#if defined(ERESTART)
10801 case ERESTART:
10802#endif
10803 if (rb_thread_interrupted(stp->th)) {
10804 if (has_gvl)
10806 else
10807 rb_thread_call_with_gvl(exec_interrupts, (void *)stp->th);
10808 }
10809 return TRUE;
10810 }
10811 return FALSE;
10812}
10813
10814#if USE_POLL
10815# define IOWAIT_SYSCALL "poll"
10816STATIC_ASSERT(pollin_expected, POLLIN == RB_WAITFD_IN);
10817STATIC_ASSERT(pollout_expected, POLLOUT == RB_WAITFD_OUT);
10818static int
10819nogvl_wait_for_single_fd(int fd, short events)
10820{
10821 struct pollfd fds;
10822
10823 fds.fd = fd;
10824 fds.events = events;
10825
10826 return poll(&fds, 1, -1);
10827}
10828#else /* !USE_POLL */
10829# define IOWAIT_SYSCALL "select"
10830static int
10831nogvl_wait_for_single_fd(int fd, short events)
10832{
10833 rb_fdset_t fds;
10834 int ret;
10835
10836 rb_fd_init(&fds);
10837 rb_fd_set(fd, &fds);
10838
10839 switch (events) {
10840 case RB_WAITFD_IN:
10841 ret = rb_fd_select(fd + 1, &fds, 0, 0, 0);
10842 break;
10843 case RB_WAITFD_OUT:
10844 ret = rb_fd_select(fd + 1, 0, &fds, 0, 0);
10845 break;
10846 default:
10847 VM_UNREACHABLE(nogvl_wait_for_single_fd);
10848 }
10849
10850 rb_fd_term(&fds);
10851 return ret;
10852}
10853#endif /* !USE_POLL */
10854
10855static int
10856maygvl_copy_stream_wait_read(int has_gvl, struct copy_stream_struct *stp)
10857{
10858 int ret;
10859
10860 do {
10861 if (has_gvl) {
10863 }
10864 else {
10865 ret = nogvl_wait_for_single_fd(stp->src_fd, RB_WAITFD_IN);
10866 }
10867 } while (ret < 0 && maygvl_copy_stream_continue_p(has_gvl, stp));
10868
10869 if (ret < 0) {
10870 stp->syserr = IOWAIT_SYSCALL;
10871 stp->error_no = errno;
10872 return ret;
10873 }
10874 return 0;
10875}
10876
10877static int
10878nogvl_copy_stream_wait_write(struct copy_stream_struct *stp)
10879{
10880 int ret;
10881
10882 do {
10883 ret = nogvl_wait_for_single_fd(stp->dst_fd, RB_WAITFD_OUT);
10884 } while (ret < 0 && maygvl_copy_stream_continue_p(0, stp));
10885
10886 if (ret < 0) {
10887 stp->syserr = IOWAIT_SYSCALL;
10888 stp->error_no = errno;
10889 return ret;
10890 }
10891 return 0;
10892}
10893
10894#if defined HAVE_COPY_FILE_RANGE || (defined __linux__ && defined __NR_copy_file_range)
10895# define USE_COPY_FILE_RANGE
10896#endif
10897
10898#ifdef USE_COPY_FILE_RANGE
10899
10900static ssize_t
10901simple_copy_file_range(int in_fd, off_t *in_offset, int out_fd, off_t *out_offset, size_t count, unsigned int flags)
10902{
10903#ifdef HAVE_COPY_FILE_RANGE
10904 return copy_file_range(in_fd, in_offset, out_fd, out_offset, count, flags);
10905#else
10906 return syscall(__NR_copy_file_range, in_fd, in_offset, out_fd, out_offset, count, flags);
10907#endif
10908}
10909
10910static int
10911nogvl_copy_file_range(struct copy_stream_struct *stp)
10912{
10913 ssize_t ss;
10914 off_t src_size;
10915 off_t copy_length, src_offset, *src_offset_ptr;
10916
10917 if (!S_ISREG(stp->src_stat.st_mode))
10918 return 0;
10919
10920 src_size = stp->src_stat.st_size;
10921 src_offset = stp->src_offset;
10922 if (src_offset >= (off_t)0) {
10923 src_offset_ptr = &src_offset;
10924 }
10925 else {
10926 src_offset_ptr = NULL; /* if src_offset_ptr is NULL, then bytes are read from in_fd starting from the file offset */
10927 }
10928
10929 copy_length = stp->copy_length;
10930 if (copy_length < (off_t)0) {
10931 if (src_offset < (off_t)0) {
10932 off_t current_offset;
10933 errno = 0;
10934 current_offset = lseek(stp->src_fd, 0, SEEK_CUR);
10935 if (current_offset < (off_t)0 && errno) {
10936 stp->syserr = "lseek";
10937 stp->error_no = errno;
10938 return (int)current_offset;
10939 }
10940 copy_length = src_size - current_offset;
10941 }
10942 else {
10943 copy_length = src_size - src_offset;
10944 }
10945 }
10946
10947 retry_copy_file_range:
10948# if SIZEOF_OFF_T > SIZEOF_SIZE_T
10949 /* we are limited by the 32-bit ssize_t return value on 32-bit */
10950 ss = (copy_length > (off_t)SSIZE_MAX) ? SSIZE_MAX : (ssize_t)copy_length;
10951# else
10952 ss = (ssize_t)copy_length;
10953# endif
10954 ss = simple_copy_file_range(stp->src_fd, src_offset_ptr, stp->dst_fd, NULL, ss, 0);
10955 if (0 < ss) {
10956 stp->total += ss;
10957 copy_length -= ss;
10958 if (0 < copy_length) {
10959 goto retry_copy_file_range;
10960 }
10961 }
10962 if (ss < 0) {
10963 if (maygvl_copy_stream_continue_p(0, stp)) {
10964 goto retry_copy_file_range;
10965 }
10966 switch (errno) {
10967 case EINVAL:
10968 case EPERM: /* copy_file_range(2) doesn't exist (may happen in
10969 docker container) */
10970#ifdef ENOSYS
10971 case ENOSYS:
10972#endif
10973#ifdef EXDEV
10974 case EXDEV: /* in_fd and out_fd are not on the same filesystem */
10975#endif
10976 return 0;
10977 case EAGAIN:
10978#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
10979 case EWOULDBLOCK:
10980#endif
10981 {
10982 int ret = nogvl_copy_stream_wait_write(stp);
10983 if (ret < 0) return ret;
10984 }
10985 goto retry_copy_file_range;
10986 case EBADF:
10987 {
10988 int e = errno;
10989 int flags = fcntl(stp->dst_fd, F_GETFL);
10990
10991 if (flags != -1 && flags & O_APPEND) {
10992 return 0;
10993 }
10994 errno = e;
10995 }
10996 }
10997 stp->syserr = "copy_file_range";
10998 stp->error_no = errno;
10999 return (int)ss;
11000 }
11001 return 1;
11002}
11003#endif
11004
11005#ifdef HAVE_FCOPYFILE
11006static int
11007nogvl_fcopyfile(struct copy_stream_struct *stp)
11008{
11009 off_t cur, ss = 0;
11010 const off_t src_offset = stp->src_offset;
11011 int ret;
11012
11013 if (stp->copy_length >= (off_t)0) {
11014 /* copy_length can't be specified in fcopyfile(3) */
11015 return 0;
11016 }
11017
11018 if (!S_ISREG(stp->src_stat.st_mode))
11019 return 0;
11020
11021 if (!S_ISREG(stp->dst_stat.st_mode))
11022 return 0;
11023 if (lseek(stp->dst_fd, 0, SEEK_CUR) > (off_t)0) /* if dst IO was already written */
11024 return 0;
11025 if (fcntl(stp->dst_fd, F_GETFL) & O_APPEND) {
11026 /* fcopyfile(3) appends src IO to dst IO and then truncates
11027 * dst IO to src IO's original size. */
11028 off_t end = lseek(stp->dst_fd, 0, SEEK_END);
11029 lseek(stp->dst_fd, 0, SEEK_SET);
11030 if (end > (off_t)0) return 0;
11031 }
11032
11033 if (src_offset > (off_t)0) {
11034 off_t r;
11035
11036 /* get current offset */
11037 errno = 0;
11038 cur = lseek(stp->src_fd, 0, SEEK_CUR);
11039 if (cur < (off_t)0 && errno) {
11040 stp->error_no = errno;
11041 return 1;
11042 }
11043
11044 errno = 0;
11045 r = lseek(stp->src_fd, src_offset, SEEK_SET);
11046 if (r < (off_t)0 && errno) {
11047 stp->error_no = errno;
11048 return 1;
11049 }
11050 }
11051
11052 stp->copyfile_state = copyfile_state_alloc(); /* this will be freed by copy_stream_finalize() */
11053 ret = fcopyfile(stp->src_fd, stp->dst_fd, stp->copyfile_state, COPYFILE_DATA);
11054 copyfile_state_get(stp->copyfile_state, COPYFILE_STATE_COPIED, &ss); /* get copied bytes */
11055
11056 if (ret == 0) { /* success */
11057 stp->total = ss;
11058 if (src_offset > (off_t)0) {
11059 off_t r;
11060 errno = 0;
11061 /* reset offset */
11062 r = lseek(stp->src_fd, cur, SEEK_SET);
11063 if (r < (off_t)0 && errno) {
11064 stp->error_no = errno;
11065 return 1;
11066 }
11067 }
11068 }
11069 else {
11070 switch (errno) {
11071 case ENOTSUP:
11072 case EPERM:
11073 case EINVAL:
11074 return 0;
11075 }
11076 stp->syserr = "fcopyfile";
11077 stp->error_no = errno;
11078 return (int)ret;
11079 }
11080 return 1;
11081}
11082#endif
11083
11084#ifdef HAVE_SENDFILE
11085
11086# ifdef __linux__
11087# define USE_SENDFILE
11088
11089# ifdef HAVE_SYS_SENDFILE_H
11090# include <sys/sendfile.h>
11091# endif
11092
11093static ssize_t
11094simple_sendfile(int out_fd, int in_fd, off_t *offset, off_t count)
11095{
11096 return sendfile(out_fd, in_fd, offset, (size_t)count);
11097}
11098
11099# elif 0 /* defined(__FreeBSD__) || defined(__DragonFly__) */ || defined(__APPLE__)
11100/* This runs on FreeBSD8.1 r30210, but sendfiles blocks its execution
11101 * without cpuset -l 0.
11102 */
11103# define USE_SENDFILE
11104
11105static ssize_t
11106simple_sendfile(int out_fd, int in_fd, off_t *offset, off_t count)
11107{
11108 int r;
11109 off_t pos = offset ? *offset : lseek(in_fd, 0, SEEK_CUR);
11110 off_t sbytes;
11111# ifdef __APPLE__
11112 r = sendfile(in_fd, out_fd, pos, &count, NULL, 0);
11113 sbytes = count;
11114# else
11115 r = sendfile(in_fd, out_fd, pos, (size_t)count, NULL, &sbytes, 0);
11116# endif
11117 if (r != 0 && sbytes == 0) return r;
11118 if (offset) {
11119 *offset += sbytes;
11120 }
11121 else {
11122 lseek(in_fd, sbytes, SEEK_CUR);
11123 }
11124 return (ssize_t)sbytes;
11125}
11126
11127# endif
11128
11129#endif
11130
11131#ifdef USE_SENDFILE
11132static int
11133nogvl_copy_stream_sendfile(struct copy_stream_struct *stp)
11134{
11135 ssize_t ss;
11136 off_t src_size;
11137 off_t copy_length;
11138 off_t src_offset;
11139 int use_pread;
11140
11141 if (!S_ISREG(stp->src_stat.st_mode))
11142 return 0;
11143
11144 src_size = stp->src_stat.st_size;
11145#ifndef __linux__
11146 if ((stp->dst_stat.st_mode & S_IFMT) != S_IFSOCK)
11147 return 0;
11148#endif
11149
11150 src_offset = stp->src_offset;
11151 use_pread = src_offset >= (off_t)0;
11152
11153 copy_length = stp->copy_length;
11154 if (copy_length < (off_t)0) {
11155 if (use_pread)
11156 copy_length = src_size - src_offset;
11157 else {
11158 off_t cur;
11159 errno = 0;
11160 cur = lseek(stp->src_fd, 0, SEEK_CUR);
11161 if (cur < (off_t)0 && errno) {
11162 stp->syserr = "lseek";
11163 stp->error_no = errno;
11164 return (int)cur;
11165 }
11166 copy_length = src_size - cur;
11167 }
11168 }
11169
11170 retry_sendfile:
11171# if SIZEOF_OFF_T > SIZEOF_SIZE_T
11172 /* we are limited by the 32-bit ssize_t return value on 32-bit */
11173 ss = (copy_length > (off_t)SSIZE_MAX) ? SSIZE_MAX : (ssize_t)copy_length;
11174# else
11175 ss = (ssize_t)copy_length;
11176# endif
11177 if (use_pread) {
11178 ss = simple_sendfile(stp->dst_fd, stp->src_fd, &src_offset, ss);
11179 }
11180 else {
11181 ss = simple_sendfile(stp->dst_fd, stp->src_fd, NULL, ss);
11182 }
11183 if (0 < ss) {
11184 stp->total += ss;
11185 copy_length -= ss;
11186 if (0 < copy_length) {
11187 goto retry_sendfile;
11188 }
11189 }
11190 if (ss < 0) {
11191 if (maygvl_copy_stream_continue_p(0, stp))
11192 goto retry_sendfile;
11193 switch (errno) {
11194 case EINVAL:
11195#ifdef ENOSYS
11196 case ENOSYS:
11197#endif
11198 return 0;
11199 case EAGAIN:
11200#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
11201 case EWOULDBLOCK:
11202#endif
11203 {
11204 int ret;
11205#ifndef __linux__
11206 /*
11207 * Linux requires stp->src_fd to be a mmap-able (regular) file,
11208 * select() reports regular files to always be "ready", so
11209 * there is no need to select() on it.
11210 * Other OSes may have the same limitation for sendfile() which
11211 * allow us to bypass maygvl_copy_stream_wait_read()...
11212 */
11213 ret = maygvl_copy_stream_wait_read(0, stp);
11214 if (ret < 0) return ret;
11215#endif
11216 ret = nogvl_copy_stream_wait_write(stp);
11217 if (ret < 0) return ret;
11218 }
11219 goto retry_sendfile;
11220 }
11221 stp->syserr = "sendfile";
11222 stp->error_no = errno;
11223 return (int)ss;
11224 }
11225 return 1;
11226}
11227#endif
11228
11229static ssize_t
11230maygvl_read(int has_gvl, int fd, void *buf, size_t count)
11231{
11232 if (has_gvl)
11233 return rb_read_internal(fd, buf, count);
11234 else
11235 return read(fd, buf, count);
11236}
11237
11238static ssize_t
11239maygvl_copy_stream_read(int has_gvl, struct copy_stream_struct *stp, char *buf, size_t len, off_t offset)
11240{
11241 ssize_t ss;
11242 retry_read:
11243 if (offset < (off_t)0) {
11244 ss = maygvl_read(has_gvl, stp->src_fd, buf, len);
11245 }
11246 else {
11247#ifdef HAVE_PREAD
11248 ss = pread(stp->src_fd, buf, len, offset);
11249#else
11250 stp->notimp = "pread";
11251 return -1;
11252#endif
11253 }
11254 if (ss == 0) {
11255 return 0;
11256 }
11257 if (ss < 0) {
11258 if (maygvl_copy_stream_continue_p(has_gvl, stp))
11259 goto retry_read;
11260 switch (errno) {
11261 case EAGAIN:
11262#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
11263 case EWOULDBLOCK:
11264#endif
11265 {
11266 int ret = maygvl_copy_stream_wait_read(has_gvl, stp);
11267 if (ret < 0) return ret;
11268 }
11269 goto retry_read;
11270#ifdef ENOSYS
11271 case ENOSYS:
11272 stp->notimp = "pread";
11273 return ss;
11274#endif
11275 }
11276 stp->syserr = offset < (off_t)0 ? "read" : "pread";
11277 stp->error_no = errno;
11278 }
11279 return ss;
11280}
11281
11282static int
11283nogvl_copy_stream_write(struct copy_stream_struct *stp, char *buf, size_t len)
11284{
11285 ssize_t ss;
11286 int off = 0;
11287 while (len) {
11288 ss = write(stp->dst_fd, buf+off, len);
11289 if (ss < 0) {
11290 if (maygvl_copy_stream_continue_p(0, stp))
11291 continue;
11292 if (errno == EAGAIN || errno == EWOULDBLOCK) {
11293 int ret = nogvl_copy_stream_wait_write(stp);
11294 if (ret < 0) return ret;
11295 continue;
11296 }
11297 stp->syserr = "write";
11298 stp->error_no = errno;
11299 return (int)ss;
11300 }
11301 off += (int)ss;
11302 len -= (int)ss;
11303 stp->total += ss;
11304 }
11305 return 0;
11306}
11307
11308static void
11309nogvl_copy_stream_read_write(struct copy_stream_struct *stp)
11310{
11311 char buf[1024*16];
11312 size_t len;
11313 ssize_t ss;
11314 int ret;
11315 off_t copy_length;
11316 int use_eof;
11317 off_t src_offset;
11318 int use_pread;
11319
11320 copy_length = stp->copy_length;
11321 use_eof = copy_length < (off_t)0;
11322 src_offset = stp->src_offset;
11323 use_pread = src_offset >= (off_t)0;
11324
11325 if (use_pread && stp->close_src) {
11326 off_t r;
11327 errno = 0;
11328 r = lseek(stp->src_fd, src_offset, SEEK_SET);
11329 if (r < (off_t)0 && errno) {
11330 stp->syserr = "lseek";
11331 stp->error_no = errno;
11332 return;
11333 }
11334 src_offset = (off_t)-1;
11335 use_pread = 0;
11336 }
11337
11338 while (use_eof || 0 < copy_length) {
11339 if (!use_eof && copy_length < (off_t)sizeof(buf)) {
11340 len = (size_t)copy_length;
11341 }
11342 else {
11343 len = sizeof(buf);
11344 }
11345 if (use_pread) {
11346 ss = maygvl_copy_stream_read(0, stp, buf, len, src_offset);
11347 if (0 < ss)
11348 src_offset += ss;
11349 }
11350 else {
11351 ss = maygvl_copy_stream_read(0, stp, buf, len, (off_t)-1);
11352 }
11353 if (ss <= 0) /* EOF or error */
11354 return;
11355
11356 ret = nogvl_copy_stream_write(stp, buf, ss);
11357 if (ret < 0)
11358 return;
11359
11360 if (!use_eof)
11361 copy_length -= ss;
11362 }
11363}
11364
11365static void *
11366nogvl_copy_stream_func(void *arg)
11367{
11368 struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
11369#if defined(USE_SENDFILE) || defined(USE_COPY_FILE_RANGE) || defined(HAVE_FCOPYFILE)
11370 int ret;
11371#endif
11372
11373#ifdef USE_COPY_FILE_RANGE
11374 ret = nogvl_copy_file_range(stp);
11375 if (ret != 0)
11376 goto finish; /* error or success */
11377#endif
11378
11379#ifdef HAVE_FCOPYFILE
11380 ret = nogvl_fcopyfile(stp);
11381 if (ret != 0)
11382 goto finish; /* error or success */
11383#endif
11384
11385#ifdef USE_SENDFILE
11386 ret = nogvl_copy_stream_sendfile(stp);
11387 if (ret != 0)
11388 goto finish; /* error or success */
11389#endif
11390
11391 nogvl_copy_stream_read_write(stp);
11392
11393#if defined(USE_SENDFILE) || defined(USE_COPY_FILE_RANGE) || defined(HAVE_FCOPYFILE)
11394 finish:
11395#endif
11396 return 0;
11397}
11398
11399static VALUE
11400copy_stream_fallback_body(VALUE arg)
11401{
11402 struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
11403 const int buflen = 16*1024;
11404 VALUE n;
11405 VALUE buf = rb_str_buf_new(buflen);
11406 off_t rest = stp->copy_length;
11407 off_t off = stp->src_offset;
11408 ID read_method = id_readpartial;
11409
11410 if (stp->src_fd < 0) {
11411 if (!rb_respond_to(stp->src, read_method)) {
11412 read_method = id_read;
11413 }
11414 }
11415
11416 while (1) {
11417 long numwrote;
11418 long l;
11419 if (stp->copy_length < (off_t)0) {
11420 l = buflen;
11421 }
11422 else {
11423 if (rest == 0) {
11424 rb_str_resize(buf, 0);
11425 break;
11426 }
11427 l = buflen < rest ? buflen : (long)rest;
11428 }
11429 if (stp->src_fd < 0) {
11430 VALUE rc = rb_funcall(stp->src, read_method, 2, INT2FIX(l), buf);
11431
11432 if (read_method == id_read && NIL_P(rc))
11433 break;
11434 }
11435 else {
11436 ssize_t ss;
11437 rb_str_resize(buf, buflen);
11438 ss = maygvl_copy_stream_read(1, stp, RSTRING_PTR(buf), l, off);
11439 rb_str_resize(buf, ss > 0 ? ss : 0);
11440 if (ss < 0)
11441 return Qnil;
11442 if (ss == 0)
11443 rb_eof_error();
11444 if (off >= (off_t)0)
11445 off += ss;
11446 }
11447 n = rb_io_write(stp->dst, buf);
11448 numwrote = NUM2LONG(n);
11449 stp->total += numwrote;
11450 rest -= numwrote;
11451 if (read_method == id_read && RSTRING_LEN(buf) == 0) {
11452 break;
11453 }
11454 }
11455
11456 return Qnil;
11457}
11458
11459static VALUE
11460copy_stream_fallback(struct copy_stream_struct *stp)
11461{
11462 if (stp->src_fd < 0 && stp->src_offset >= (off_t)0) {
11463 rb_raise(rb_eArgError, "cannot specify src_offset for non-IO");
11464 }
11465 rb_rescue2(copy_stream_fallback_body, (VALUE)stp,
11466 (VALUE (*) (VALUE, VALUE))0, (VALUE)0,
11467 rb_eEOFError, (VALUE)0);
11468 return Qnil;
11469}
11470
11471static VALUE
11472copy_stream_body(VALUE arg)
11473{
11474 struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
11475 VALUE src_io = stp->src, dst_io = stp->dst;
11476 rb_io_t *src_fptr = 0, *dst_fptr = 0;
11477 int src_fd, dst_fd;
11478 const int common_oflags = 0
11479#ifdef O_NOCTTY
11480 | O_NOCTTY
11481#endif
11482 ;
11483
11484 stp->th = rb_thread_current();
11485
11486 stp->total = 0;
11487
11488 if (src_io == argf ||
11489 !(RB_TYPE_P(src_io, T_FILE) ||
11490 RB_TYPE_P(src_io, T_STRING) ||
11491 rb_respond_to(src_io, rb_intern("to_path")))) {
11492 src_fd = -1;
11493 }
11494 else {
11495 int stat_ret;
11496 VALUE tmp_io = rb_io_check_io(src_io);
11497 if (!NIL_P(tmp_io)) {
11498 src_io = tmp_io;
11499 }
11500 else if (!RB_TYPE_P(src_io, T_FILE)) {
11501 VALUE args[2];
11502 FilePathValue(src_io);
11503 args[0] = src_io;
11504 args[1] = INT2NUM(O_RDONLY|common_oflags);
11505 src_io = rb_class_new_instance(2, args, rb_cFile);
11506 stp->src = src_io;
11507 stp->close_src = 1;
11508 }
11509 GetOpenFile(src_io, src_fptr);
11510 rb_io_check_byte_readable(src_fptr);
11511 src_fd = src_fptr->fd;
11512
11513 stat_ret = fstat(src_fd, &stp->src_stat);
11514 if (stat_ret < 0) {
11515 stp->syserr = "fstat";
11516 stp->error_no = errno;
11517 return Qnil;
11518 }
11519 }
11520 stp->src_fd = src_fd;
11521
11522 if (dst_io == argf ||
11523 !(RB_TYPE_P(dst_io, T_FILE) ||
11524 RB_TYPE_P(dst_io, T_STRING) ||
11525 rb_respond_to(dst_io, rb_intern("to_path")))) {
11526 dst_fd = -1;
11527 }
11528 else {
11529 int stat_ret;
11530 VALUE tmp_io = rb_io_check_io(dst_io);
11531 if (!NIL_P(tmp_io)) {
11532 dst_io = GetWriteIO(tmp_io);
11533 }
11534 else if (!RB_TYPE_P(dst_io, T_FILE)) {
11535 VALUE args[3];
11536 FilePathValue(dst_io);
11537 args[0] = dst_io;
11538 args[1] = INT2NUM(O_WRONLY|O_CREAT|O_TRUNC|common_oflags);
11539 args[2] = INT2FIX(0666);
11540 dst_io = rb_class_new_instance(3, args, rb_cFile);
11541 stp->dst = dst_io;
11542 stp->close_dst = 1;
11543 }
11544 else {
11545 dst_io = GetWriteIO(dst_io);
11546 stp->dst = dst_io;
11547 }
11548 GetOpenFile(dst_io, dst_fptr);
11549 rb_io_check_writable(dst_fptr);
11550 dst_fd = dst_fptr->fd;
11551
11552 stat_ret = fstat(dst_fd, &stp->dst_stat);
11553 if (stat_ret < 0) {
11554 stp->syserr = "fstat";
11555 stp->error_no = errno;
11556 return Qnil;
11557 }
11558 }
11559 stp->dst_fd = dst_fd;
11560
11561#ifdef O_BINARY
11562 if (src_fptr)
11564#endif
11565 if (dst_fptr)
11566 io_ascii8bit_binmode(dst_fptr);
11567
11568 if (stp->src_offset < (off_t)0 && src_fptr && src_fptr->rbuf.len) {
11569 size_t len = src_fptr->rbuf.len;
11570 VALUE str;
11571 if (stp->copy_length >= (off_t)0 && stp->copy_length < (off_t)len) {
11572 len = (size_t)stp->copy_length;
11573 }
11576 read_buffered_data(RSTRING_PTR(str), len, src_fptr);
11577 if (dst_fptr) { /* IO or filename */
11578 if (io_binwrite(str, RSTRING_PTR(str), RSTRING_LEN(str), dst_fptr, 0) < 0)
11579 rb_sys_fail(0);
11580 }
11581 else /* others such as StringIO */
11582 rb_io_write(dst_io, str);
11583 rb_str_resize(str, 0);
11584 stp->total += len;
11585 if (stp->copy_length >= (off_t)0)
11586 stp->copy_length -= len;
11587 }
11588
11589 if (dst_fptr && io_fflush(dst_fptr) < 0) {
11590 rb_raise(rb_eIOError, "flush failed");
11591 }
11592
11593 if (stp->copy_length == 0)
11594 return Qnil;
11595
11596 if (src_fd < 0 || dst_fd < 0) {
11597 return copy_stream_fallback(stp);
11598 }
11599
11600 rb_thread_call_without_gvl(nogvl_copy_stream_func, (void*)stp, RUBY_UBF_IO, 0);
11601 return Qnil;
11602}
11603
11604static VALUE
11605copy_stream_finalize(VALUE arg)
11606{
11607 struct copy_stream_struct *stp = (struct copy_stream_struct *)arg;
11608
11609#ifdef HAVE_FCOPYFILE
11610 if (stp->copyfile_state) {
11611 copyfile_state_free(stp->copyfile_state);
11612 }
11613#endif
11614
11615 if (stp->close_src) {
11616 rb_io_close_m(stp->src);
11617 }
11618 if (stp->close_dst) {
11619 rb_io_close_m(stp->dst);
11620 }
11621 if (stp->syserr) {
11622 rb_syserr_fail(stp->error_no, stp->syserr);
11623 }
11624 if (stp->notimp) {
11625 rb_raise(rb_eNotImpError, "%s() not implemented", stp->notimp);
11626 }
11627 return Qnil;
11628}
11629
11630/*
11631 * call-seq:
11632 * IO.copy_stream(src, dst)
11633 * IO.copy_stream(src, dst, copy_length)
11634 * IO.copy_stream(src, dst, copy_length, src_offset)
11635 *
11636 * IO.copy_stream copies <i>src</i> to <i>dst</i>.
11637 * <i>src</i> and <i>dst</i> is either a filename or an IO-like object.
11638 * IO-like object for <i>src</i> should have #readpartial or #read
11639 * method. IO-like object for <i>dst</i> should have #write method.
11640 * (Specialized mechanisms, such as sendfile system call, may be used
11641 * on appropriate situation.)
11642 *
11643 * This method returns the number of bytes copied.
11644 *
11645 * If optional arguments are not given,
11646 * the start position of the copy is
11647 * the beginning of the filename or
11648 * the current file offset of the IO.
11649 * The end position of the copy is the end of file.
11650 *
11651 * If <i>copy_length</i> is given,
11652 * No more than <i>copy_length</i> bytes are copied.
11653 *
11654 * If <i>src_offset</i> is given,
11655 * it specifies the start position of the copy.
11656 *
11657 * When <i>src_offset</i> is specified and
11658 * <i>src</i> is an IO,
11659 * IO.copy_stream doesn't move the current file offset.
11660 *
11661 */
11662static VALUE
11663rb_io_s_copy_stream(int argc, VALUE *argv, VALUE io)
11664{
11665 VALUE src, dst, length, src_offset;
11666 struct copy_stream_struct st;
11667
11668 MEMZERO(&st, struct copy_stream_struct, 1);
11669
11670 rb_scan_args(argc, argv, "22", &src, &dst, &length, &src_offset);
11671
11672 st.src = src;
11673 st.dst = dst;
11674
11675 if (NIL_P(length))
11676 st.copy_length = (off_t)-1;
11677 else
11678 st.copy_length = NUM2OFFT(length);
11679
11680 if (NIL_P(src_offset))
11681 st.src_offset = (off_t)-1;
11682 else
11683 st.src_offset = NUM2OFFT(src_offset);
11684
11685 rb_ensure(copy_stream_body, (VALUE)&st, copy_stream_finalize, (VALUE)&st);
11686
11687 return OFFT2NUM(st.total);
11688}
11689
11690/*
11691 * call-seq:
11692 * io.external_encoding -> encoding
11693 *
11694 * Returns the Encoding object that represents the encoding of the file.
11695 * If _io_ is in write mode and no encoding is specified, returns +nil+.
11696 */
11697
11698static VALUE
11699rb_io_external_encoding(VALUE io)
11700{
11701 rb_io_t *fptr;
11702
11703 GetOpenFile(io, fptr);
11704 if (fptr->encs.enc2) {
11705 return rb_enc_from_encoding(fptr->encs.enc2);
11706 }
11707 if (fptr->mode & FMODE_WRITABLE) {
11708 if (fptr->encs.enc)
11709 return rb_enc_from_encoding(fptr->encs.enc);
11710 return Qnil;
11711 }
11712 return rb_enc_from_encoding(io_read_encoding(fptr));
11713}
11714
11715/*
11716 * call-seq:
11717 * io.internal_encoding -> encoding
11718 *
11719 * Returns the Encoding of the internal string if conversion is
11720 * specified. Otherwise returns +nil+.
11721 */
11722
11723static VALUE
11724rb_io_internal_encoding(VALUE io)
11725{
11726 rb_io_t *fptr;
11727
11728 GetOpenFile(io, fptr);
11729 if (!fptr->encs.enc2) return Qnil;
11730 return rb_enc_from_encoding(io_read_encoding(fptr));
11731}
11732
11733/*
11734 * call-seq:
11735 * io.set_encoding(ext_enc) -> io
11736 * io.set_encoding("ext_enc:int_enc") -> io
11737 * io.set_encoding(ext_enc, int_enc) -> io
11738 * io.set_encoding("ext_enc:int_enc", opt) -> io
11739 * io.set_encoding(ext_enc, int_enc, opt) -> io
11740 *
11741 * If single argument is specified, read string from io is tagged
11742 * with the encoding specified. If encoding is a colon separated two
11743 * encoding names "A:B", the read string is converted from encoding A
11744 * (external encoding) to encoding B (internal encoding), then tagged
11745 * with B. If two arguments are specified, those must be encoding
11746 * objects or encoding names, and the first one is the external encoding, and the
11747 * second one is the internal encoding.
11748 * If the external encoding and the internal encoding is specified,
11749 * optional hash argument specify the conversion option.
11750 */
11751
11752static VALUE
11753rb_io_set_encoding(int argc, VALUE *argv, VALUE io)
11754{
11755 rb_io_t *fptr;
11756 VALUE v1, v2, opt;
11757
11758 if (!RB_TYPE_P(io, T_FILE)) {
11759 return rb_funcallv(io, id_set_encoding, argc, argv);
11760 }
11761
11762 argc = rb_scan_args(argc, argv, "11:", &v1, &v2, &opt);
11763 GetOpenFile(io, fptr);
11764 io_encoding_set(fptr, v1, v2, opt);
11765 return io;
11766}
11767
11768void
11770{
11771 VALUE val = Qnil;
11772
11773 rb_io_set_encoding(1, &val, rb_stdin);
11774 rb_io_set_encoding(1, &val, rb_stdout);
11775 rb_io_set_encoding(1, &val, rb_stderr);
11776}
11777
11778static inline int
11779global_argf_p(VALUE arg)
11780{
11781 return arg == argf;
11782}
11783
11784/*
11785 * call-seq:
11786 * ARGF.external_encoding -> encoding
11787 *
11788 * Returns the external encoding for files read from +ARGF+ as an +Encoding+
11789 * object. The external encoding is the encoding of the text as stored in a
11790 * file. Contrast with +ARGF.internal_encoding+, which is the encoding used
11791 * to represent this text within Ruby.
11792 *
11793 * To set the external encoding use +ARGF.set_encoding+.
11794 *
11795 * For example:
11796 *
11797 * ARGF.external_encoding #=> #<Encoding:UTF-8>
11798 *
11799 */
11800static VALUE
11801argf_external_encoding(VALUE argf)
11802{
11803 if (!RTEST(ARGF.current_file)) {
11805 }
11806 return rb_io_external_encoding(rb_io_check_io(ARGF.current_file));
11807}
11808
11809/*
11810 * call-seq:
11811 * ARGF.internal_encoding -> encoding
11812 *
11813 * Returns the internal encoding for strings read from +ARGF+ as an
11814 * +Encoding+ object.
11815 *
11816 * If +ARGF.set_encoding+ has been called with two encoding names, the second
11817 * is returned. Otherwise, if +Encoding.default_external+ has been set, that
11818 * value is returned. Failing that, if a default external encoding was
11819 * specified on the command-line, that value is used. If the encoding is
11820 * unknown, +nil+ is returned.
11821 */
11822static VALUE
11823argf_internal_encoding(VALUE argf)
11824{
11825 if (!RTEST(ARGF.current_file)) {
11827 }
11828 return rb_io_internal_encoding(rb_io_check_io(ARGF.current_file));
11829}
11830
11831/*
11832 * call-seq:
11833 * ARGF.set_encoding(ext_enc) -> ARGF
11834 * ARGF.set_encoding("ext_enc:int_enc") -> ARGF
11835 * ARGF.set_encoding(ext_enc, int_enc) -> ARGF
11836 * ARGF.set_encoding("ext_enc:int_enc", opt) -> ARGF
11837 * ARGF.set_encoding(ext_enc, int_enc, opt) -> ARGF
11838 *
11839 * If single argument is specified, strings read from ARGF are tagged with
11840 * the encoding specified.
11841 *
11842 * If two encoding names separated by a colon are given, e.g. "ascii:utf-8",
11843 * the read string is converted from the first encoding (external encoding)
11844 * to the second encoding (internal encoding), then tagged with the second
11845 * encoding.
11846 *
11847 * If two arguments are specified, they must be encoding objects or encoding
11848 * names. Again, the first specifies the external encoding; the second
11849 * specifies the internal encoding.
11850 *
11851 * If the external encoding and the internal encoding are specified, the
11852 * optional +Hash+ argument can be used to adjust the conversion process. The
11853 * structure of this hash is explained in the String#encode documentation.
11854 *
11855 * For example:
11856 *
11857 * ARGF.set_encoding('ascii') # Tag the input as US-ASCII text
11858 * ARGF.set_encoding(Encoding::UTF_8) # Tag the input as UTF-8 text
11859 * ARGF.set_encoding('utf-8','ascii') # Transcode the input from US-ASCII
11860 * # to UTF-8.
11861 */
11862static VALUE
11863argf_set_encoding(int argc, VALUE *argv, VALUE argf)
11864{
11865 rb_io_t *fptr;
11866
11867 if (!next_argv()) {
11868 rb_raise(rb_eArgError, "no stream to set encoding");
11869 }
11870 rb_io_set_encoding(argc, argv, ARGF.current_file);
11871 GetOpenFile(ARGF.current_file, fptr);
11872 ARGF.encs = fptr->encs;
11873 return argf;
11874}
11875
11876/*
11877 * call-seq:
11878 * ARGF.tell -> Integer
11879 * ARGF.pos -> Integer
11880 *
11881 * Returns the current offset (in bytes) of the current file in +ARGF+.
11882 *
11883 * ARGF.pos #=> 0
11884 * ARGF.gets #=> "This is line one\n"
11885 * ARGF.pos #=> 17
11886 *
11887 */
11888static VALUE
11889argf_tell(VALUE argf)
11890{
11891 if (!next_argv()) {
11892 rb_raise(rb_eArgError, "no stream to tell");
11893 }
11894 ARGF_FORWARD(0, 0);
11895 return rb_io_tell(ARGF.current_file);
11896}
11897
11898/*
11899 * call-seq:
11900 * ARGF.seek(amount, whence=IO::SEEK_SET) -> 0
11901 *
11902 * Seeks to offset _amount_ (an +Integer+) in the +ARGF+ stream according to
11903 * the value of _whence_. See IO#seek for further details.
11904 */
11905static VALUE
11906argf_seek_m(int argc, VALUE *argv, VALUE argf)
11907{
11908 if (!next_argv()) {
11909 rb_raise(rb_eArgError, "no stream to seek");
11910 }
11912 return rb_io_seek_m(argc, argv, ARGF.current_file);
11913}
11914
11915/*
11916 * call-seq:
11917 * ARGF.pos = position -> Integer
11918 *
11919 * Seeks to the position given by _position_ (in bytes) in +ARGF+.
11920 *
11921 * For example:
11922 *
11923 * ARGF.pos = 17
11924 * ARGF.gets #=> "This is line two\n"
11925 */
11926static VALUE
11927argf_set_pos(VALUE argf, VALUE offset)
11928{
11929 if (!next_argv()) {
11930 rb_raise(rb_eArgError, "no stream to set position");
11931 }
11932 ARGF_FORWARD(1, &offset);
11933 return rb_io_set_pos(ARGF.current_file, offset);
11934}
11935
11936/*
11937 * call-seq:
11938 * ARGF.rewind -> 0
11939 *
11940 * Positions the current file to the beginning of input, resetting
11941 * +ARGF.lineno+ to zero.
11942 *
11943 * ARGF.readline #=> "This is line one\n"
11944 * ARGF.rewind #=> 0
11945 * ARGF.lineno #=> 0
11946 * ARGF.readline #=> "This is line one\n"
11947 */
11948static VALUE
11949argf_rewind(VALUE argf)
11950{
11951 VALUE ret;
11952 int old_lineno;
11953
11954 if (!next_argv()) {
11955 rb_raise(rb_eArgError, "no stream to rewind");
11956 }
11957 ARGF_FORWARD(0, 0);
11958 old_lineno = RFILE(ARGF.current_file)->fptr->lineno;
11959 ret = rb_io_rewind(ARGF.current_file);
11960 if (!global_argf_p(argf)) {
11961 ARGF.last_lineno = ARGF.lineno -= old_lineno;
11962 }
11963 return ret;
11964}
11965
11966/*
11967 * call-seq:
11968 * ARGF.fileno -> integer
11969 * ARGF.to_i -> integer
11970 *
11971 * Returns an integer representing the numeric file descriptor for
11972 * the current file. Raises an +ArgumentError+ if there isn't a current file.
11973 *
11974 * ARGF.fileno #=> 3
11975 */
11976static VALUE
11977argf_fileno(VALUE argf)
11978{
11979 if (!next_argv()) {
11980 rb_raise(rb_eArgError, "no stream");
11981 }
11982 ARGF_FORWARD(0, 0);
11983 return rb_io_fileno(ARGF.current_file);
11984}
11985
11986/*
11987 * call-seq:
11988 * ARGF.to_io -> IO
11989 *
11990 * Returns an +IO+ object representing the current file. This will be a
11991 * +File+ object unless the current file is a stream such as STDIN.
11992 *
11993 * For example:
11994 *
11995 * ARGF.to_io #=> #<File:glark.txt>
11996 * ARGF.to_io #=> #<IO:<STDIN>>
11997 */
11998static VALUE
11999argf_to_io(VALUE argf)
12000{
12001 next_argv();
12002 ARGF_FORWARD(0, 0);
12003 return ARGF.current_file;
12004}
12005
12006/*
12007 * call-seq:
12008 * ARGF.eof? -> true or false
12009 * ARGF.eof -> true or false
12010 *
12011 * Returns true if the current file in +ARGF+ is at end of file, i.e. it has
12012 * no data to read. The stream must be opened for reading or an +IOError+
12013 * will be raised.
12014 *
12015 * $ echo "eof" | ruby argf.rb
12016 *
12017 * ARGF.eof? #=> false
12018 * 3.times { ARGF.readchar }
12019 * ARGF.eof? #=> false
12020 * ARGF.readchar #=> "\n"
12021 * ARGF.eof? #=> true
12022 */
12023
12024static VALUE
12025argf_eof(VALUE argf)
12026{
12027 next_argv();
12028 if (RTEST(ARGF.current_file)) {
12029 if (ARGF.init_p == 0) return Qtrue;
12030 next_argv();
12031 ARGF_FORWARD(0, 0);
12032 if (rb_io_eof(ARGF.current_file)) {
12033 return Qtrue;
12034 }
12035 }
12036 return Qfalse;
12037}
12038
12039/*
12040 * call-seq:
12041 * ARGF.read([length [, outbuf]]) -> string, outbuf, or nil
12042 *
12043 * Reads _length_ bytes from ARGF. The files named on the command line
12044 * are concatenated and treated as a single file by this method, so when
12045 * called without arguments the contents of this pseudo file are returned in
12046 * their entirety.
12047 *
12048 * _length_ must be a non-negative integer or +nil+.
12049 *
12050 * If _length_ is a positive integer, +read+ tries to read
12051 * _length_ bytes without any conversion (binary mode).
12052 * It returns +nil+ if an EOF is encountered before anything can be read.
12053 * Fewer than _length_ bytes are returned if an EOF is encountered during
12054 * the read.
12055 * In the case of an integer _length_, the resulting string is always
12056 * in ASCII-8BIT encoding.
12057 *
12058 * If _length_ is omitted or is +nil+, it reads until EOF
12059 * and the encoding conversion is applied, if applicable.
12060 * A string is returned even if EOF is encountered before any data is read.
12061 *
12062 * If _length_ is zero, it returns an empty string (<code>""</code>).
12063 *
12064 * If the optional _outbuf_ argument is present,
12065 * it must reference a String, which will receive the data.
12066 * The _outbuf_ will contain only the received data after the method call
12067 * even if it is not empty at the beginning.
12068 *
12069 * For example:
12070 *
12071 * $ echo "small" > small.txt
12072 * $ echo "large" > large.txt
12073 * $ ./glark.rb small.txt large.txt
12074 *
12075 * ARGF.read #=> "small\nlarge"
12076 * ARGF.read(200) #=> "small\nlarge"
12077 * ARGF.read(2) #=> "sm"
12078 * ARGF.read(0) #=> ""
12079 *
12080 * Note that this method behaves like the fread() function in C.
12081 * This means it retries to invoke read(2) system calls to read data
12082 * with the specified length.
12083 * If you need the behavior like a single read(2) system call,
12084 * consider ARGF#readpartial or ARGF#read_nonblock.
12085 */
12086
12087static VALUE
12088argf_read(int argc, VALUE *argv, VALUE argf)
12089{
12090 VALUE tmp, str, length;
12091 long len = 0;
12092
12093 rb_scan_args(argc, argv, "02", &length, &str);
12094 if (!NIL_P(length)) {
12095 len = NUM2LONG(argv[0]);
12096 }
12097 if (!NIL_P(str)) {
12099 rb_str_resize(str,0);
12100 argv[1] = Qnil;
12101 }
12102
12103 retry:
12104 if (!next_argv()) {
12105 return str;
12106 }
12107 if (ARGF_GENERIC_INPUT_P()) {
12108 tmp = argf_forward(argc, argv, argf);
12109 }
12110 else {
12111 tmp = io_read(argc, argv, ARGF.current_file);
12112 }
12113 if (NIL_P(str)) str = tmp;
12114 else if (!NIL_P(tmp)) rb_str_append(str, tmp);
12115 if (NIL_P(tmp) || NIL_P(length)) {
12116 if (ARGF.next_p != -1) {
12117 argf_close(argf);
12118 ARGF.next_p = 1;
12119 goto retry;
12120 }
12121 }
12122 else if (argc >= 1) {
12123 long slen = RSTRING_LEN(str);
12124 if (slen < len) {
12125 len -= slen;
12126 argv[0] = INT2NUM(len);
12127 goto retry;
12128 }
12129 }
12130 return str;
12131}
12132
12134 int argc;
12137};
12138
12139static VALUE
12140argf_forward_call(VALUE arg)
12141{
12142 struct argf_call_arg *p = (struct argf_call_arg *)arg;
12143 argf_forward(p->argc, p->argv, p->argf);
12144 return Qnil;
12145}
12146
12147static VALUE argf_getpartial(int argc, VALUE *argv, VALUE argf, VALUE opts,
12148 int nonblock);
12149
12150/*
12151 * call-seq:
12152 * ARGF.readpartial(maxlen) -> string
12153 * ARGF.readpartial(maxlen, outbuf) -> outbuf
12154 *
12155 * Reads at most _maxlen_ bytes from the ARGF stream.
12156 *
12157 * If the optional _outbuf_ argument is present,
12158 * it must reference a String, which will receive the data.
12159 * The _outbuf_ will contain only the received data after the method call
12160 * even if it is not empty at the beginning.
12161 *
12162 * It raises EOFError on end of ARGF stream.
12163 * Since ARGF stream is a concatenation of multiple files,
12164 * internally EOF is occur for each file.
12165 * ARGF.readpartial returns empty strings for EOFs except the last one and
12166 * raises EOFError for the last one.
12167 *
12168 */
12169
12170static VALUE
12171argf_readpartial(int argc, VALUE *argv, VALUE argf)
12172{
12173 return argf_getpartial(argc, argv, argf, Qnil, 0);
12174}
12175
12176/*
12177 * call-seq:
12178 * ARGF.read_nonblock(maxlen[, options]) -> string
12179 * ARGF.read_nonblock(maxlen, outbuf[, options]) -> outbuf
12180 *
12181 * Reads at most _maxlen_ bytes from the ARGF stream in non-blocking mode.
12182 */
12183
12184static VALUE
12185argf_read_nonblock(int argc, VALUE *argv, VALUE argf)
12186{
12187 VALUE opts;
12188
12189 rb_scan_args(argc, argv, "11:", NULL, NULL, &opts);
12190
12191 if (!NIL_P(opts))
12192 argc--;
12193
12194 return argf_getpartial(argc, argv, argf, opts, 1);
12195}
12196
12197static VALUE
12198argf_getpartial(int argc, VALUE *argv, VALUE argf, VALUE opts, int nonblock)
12199{
12200 VALUE tmp, str, length;
12201 int no_exception;
12202
12203 rb_scan_args(argc, argv, "11", &length, &str);
12204 if (!NIL_P(str)) {
12206 argv[1] = str;
12207 }
12208 no_exception = no_exception_p(opts);
12209
12210 if (!next_argv()) {
12211 if (!NIL_P(str)) {
12212 rb_str_resize(str, 0);
12213 }
12214 rb_eof_error();
12215 }
12216 if (ARGF_GENERIC_INPUT_P()) {
12217 VALUE (*const rescue_does_nothing)(VALUE, VALUE) = 0;
12218 struct argf_call_arg arg;
12219 arg.argc = argc;
12220 arg.argv = argv;
12221 arg.argf = argf;
12222 tmp = rb_rescue2(argf_forward_call, (VALUE)&arg,
12223 rescue_does_nothing, Qnil, rb_eEOFError, (VALUE)0);
12224 }
12225 else {
12226 tmp = io_getpartial(argc, argv, ARGF.current_file, no_exception, nonblock);
12227 }
12228 if (NIL_P(tmp)) {
12229 if (ARGF.next_p == -1) {
12230 return io_nonblock_eof(no_exception);
12231 }
12232 argf_close(argf);
12233 ARGF.next_p = 1;
12234 if (RARRAY_LEN(ARGF.argv) == 0) {
12235 return io_nonblock_eof(no_exception);
12236 }
12237 if (NIL_P(str))
12238 str = rb_str_new(NULL, 0);
12239 return str;
12240 }
12241 return tmp;
12242}
12243
12244/*
12245 * call-seq:
12246 * ARGF.getc -> String or nil
12247 *
12248 * Reads the next character from +ARGF+ and returns it as a +String+. Returns
12249 * +nil+ at the end of the stream.
12250 *
12251 * +ARGF+ treats the files named on the command line as a single file created
12252 * by concatenating their contents. After returning the last character of the
12253 * first file, it returns the first character of the second file, and so on.
12254 *
12255 * For example:
12256 *
12257 * $ echo "foo" > file
12258 * $ ruby argf.rb file
12259 *
12260 * ARGF.getc #=> "f"
12261 * ARGF.getc #=> "o"
12262 * ARGF.getc #=> "o"
12263 * ARGF.getc #=> "\n"
12264 * ARGF.getc #=> nil
12265 * ARGF.getc #=> nil
12266 */
12267static VALUE
12268argf_getc(VALUE argf)
12269{
12270 VALUE ch;
12271
12272 retry:
12273 if (!next_argv()) return Qnil;
12274 if (ARGF_GENERIC_INPUT_P()) {
12275 ch = rb_funcall3(ARGF.current_file, rb_intern("getc"), 0, 0);
12276 }
12277 else {
12278 ch = rb_io_getc(ARGF.current_file);
12279 }
12280 if (NIL_P(ch) && ARGF.next_p != -1) {
12281 argf_close(argf);
12282 ARGF.next_p = 1;
12283 goto retry;
12284 }
12285
12286 return ch;
12287}
12288
12289/*
12290 * call-seq:
12291 * ARGF.getbyte -> Integer or nil
12292 *
12293 * Gets the next 8-bit byte (0..255) from +ARGF+. Returns +nil+ if called at
12294 * the end of the stream.
12295 *
12296 * For example:
12297 *
12298 * $ echo "foo" > file
12299 * $ ruby argf.rb file
12300 *
12301 * ARGF.getbyte #=> 102
12302 * ARGF.getbyte #=> 111
12303 * ARGF.getbyte #=> 111
12304 * ARGF.getbyte #=> 10
12305 * ARGF.getbyte #=> nil
12306 */
12307static VALUE
12308argf_getbyte(VALUE argf)
12309{
12310 VALUE ch;
12311
12312 retry:
12313 if (!next_argv()) return Qnil;
12314 if (!RB_TYPE_P(ARGF.current_file, T_FILE)) {
12315 ch = rb_funcall3(ARGF.current_file, rb_intern("getbyte"), 0, 0);
12316 }
12317 else {
12318 ch = rb_io_getbyte(ARGF.current_file);
12319 }
12320 if (NIL_P(ch) && ARGF.next_p != -1) {
12321 argf_close(argf);
12322 ARGF.next_p = 1;
12323 goto retry;
12324 }
12325
12326 return ch;
12327}
12328
12329/*
12330 * call-seq:
12331 * ARGF.readchar -> String or nil
12332 *
12333 * Reads the next character from +ARGF+ and returns it as a +String+. Raises
12334 * an +EOFError+ after the last character of the last file has been read.
12335 *
12336 * For example:
12337 *
12338 * $ echo "foo" > file
12339 * $ ruby argf.rb file
12340 *
12341 * ARGF.readchar #=> "f"
12342 * ARGF.readchar #=> "o"
12343 * ARGF.readchar #=> "o"
12344 * ARGF.readchar #=> "\n"
12345 * ARGF.readchar #=> end of file reached (EOFError)
12346 */
12347static VALUE
12348argf_readchar(VALUE argf)
12349{
12350 VALUE ch;
12351
12352 retry:
12353 if (!next_argv()) rb_eof_error();
12354 if (!RB_TYPE_P(ARGF.current_file, T_FILE)) {
12355 ch = rb_funcall3(ARGF.current_file, rb_intern("getc"), 0, 0);
12356 }
12357 else {
12358 ch = rb_io_getc(ARGF.current_file);
12359 }
12360 if (NIL_P(ch) && ARGF.next_p != -1) {
12361 argf_close(argf);
12362 ARGF.next_p = 1;
12363 goto retry;
12364 }
12365
12366 return ch;
12367}
12368
12369/*
12370 * call-seq:
12371 * ARGF.readbyte -> Integer
12372 *
12373 * Reads the next 8-bit byte from ARGF and returns it as an +Integer+. Raises
12374 * an +EOFError+ after the last byte of the last file has been read.
12375 *
12376 * For example:
12377 *
12378 * $ echo "foo" > file
12379 * $ ruby argf.rb file
12380 *
12381 * ARGF.readbyte #=> 102
12382 * ARGF.readbyte #=> 111
12383 * ARGF.readbyte #=> 111
12384 * ARGF.readbyte #=> 10
12385 * ARGF.readbyte #=> end of file reached (EOFError)
12386 */
12387static VALUE
12388argf_readbyte(VALUE argf)
12389{
12390 VALUE c;
12391
12392 NEXT_ARGF_FORWARD(0, 0);
12393 c = argf_getbyte(argf);
12394 if (NIL_P(c)) {
12395 rb_eof_error();
12396 }
12397 return c;
12398}
12399
12400#define FOREACH_ARGF() while (next_argv())
12401
12402static VALUE
12403argf_block_call_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, argf))
12404{
12405 const VALUE current = ARGF.current_file;
12407 if (ARGF.init_p == -1 || current != ARGF.current_file) {
12409 }
12410 return Qnil;
12411}
12412
12413#define ARGF_block_call(mid, argc, argv, func, argf) \
12414 rb_block_call_kw(ARGF.current_file, mid, argc, argv, \
12415 func, argf, rb_keyword_given_p())
12416
12417static void
12418argf_block_call(ID mid, int argc, VALUE *argv, VALUE argf)
12419{
12420 VALUE ret = ARGF_block_call(mid, argc, argv, argf_block_call_i, argf);
12421 if (ret != Qundef) ARGF.next_p = 1;
12422}
12423
12424static VALUE
12425argf_block_call_line_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, argf))
12426{
12427 if (!global_argf_p(argf)) {
12428 ARGF.last_lineno = ++ARGF.lineno;
12429 }
12430 return argf_block_call_i(i, argf, argc, argv, blockarg);
12431}
12432
12433static void
12434argf_block_call_line(ID mid, int argc, VALUE *argv, VALUE argf)
12435{
12436 VALUE ret = ARGF_block_call(mid, argc, argv, argf_block_call_line_i, argf);
12437 if (ret != Qundef) ARGF.next_p = 1;
12438}
12439
12440/*
12441 * call-seq:
12442 * ARGF.each(sep=$/) {|line| block } -> ARGF
12443 * ARGF.each(sep=$/, limit) {|line| block } -> ARGF
12444 * ARGF.each(...) -> an_enumerator
12445 *
12446 * ARGF.each_line(sep=$/) {|line| block } -> ARGF
12447 * ARGF.each_line(sep=$/, limit) {|line| block } -> ARGF
12448 * ARGF.each_line(...) -> an_enumerator
12449 *
12450 * Returns an enumerator which iterates over each line (separated by _sep_,
12451 * which defaults to your platform's newline character) of each file in
12452 * +ARGV+. If a block is supplied, each line in turn will be yielded to the
12453 * block, otherwise an enumerator is returned.
12454 * The optional _limit_ argument is an +Integer+ specifying the maximum
12455 * length of each line; longer lines will be split according to this limit.
12456 *
12457 * This method allows you to treat the files supplied on the command line as
12458 * a single file consisting of the concatenation of each named file. After
12459 * the last line of the first file has been returned, the first line of the
12460 * second file is returned. The +ARGF.filename+ and +ARGF.lineno+ methods can
12461 * be used to determine the filename of the current line and line number of
12462 * the whole input, respectively.
12463 *
12464 * For example, the following code prints out each line of each named file
12465 * prefixed with its line number, displaying the filename once per file:
12466 *
12467 * ARGF.each_line do |line|
12468 * puts ARGF.filename if ARGF.file.lineno == 1
12469 * puts "#{ARGF.file.lineno}: #{line}"
12470 * end
12471 *
12472 * While the following code prints only the first file's name at first, and
12473 * the contents with line number counted through all named files.
12474 *
12475 * ARGF.each_line do |line|
12476 * puts ARGF.filename if ARGF.lineno == 1
12477 * puts "#{ARGF.lineno}: #{line}"
12478 * end
12479 */
12480static VALUE
12481argf_each_line(int argc, VALUE *argv, VALUE argf)
12482{
12484 FOREACH_ARGF() {
12485 argf_block_call_line(rb_intern("each_line"), argc, argv, argf);
12486 }
12487 return argf;
12488}
12489
12490/*
12491 * This is a deprecated alias for #each_line.
12492 */
12493
12494static VALUE
12495argf_lines(int argc, VALUE *argv, VALUE argf)
12496{
12497 rb_warn_deprecated("ARGF#lines", "#each_line");
12498 if (!rb_block_given_p())
12499 return rb_enumeratorize(argf, ID2SYM(rb_intern("each_line")), argc, argv);
12500 return argf_each_line(argc, argv, argf);
12501}
12502
12503/*
12504 * call-seq:
12505 * ARGF.bytes {|byte| block } -> ARGF
12506 * ARGF.bytes -> an_enumerator
12507 *
12508 * ARGF.each_byte {|byte| block } -> ARGF
12509 * ARGF.each_byte -> an_enumerator
12510 *
12511 * Iterates over each byte of each file in +ARGV+.
12512 * A byte is returned as an +Integer+ in the range 0..255.
12513 *
12514 * This method allows you to treat the files supplied on the command line as
12515 * a single file consisting of the concatenation of each named file. After
12516 * the last byte of the first file has been returned, the first byte of the
12517 * second file is returned. The +ARGF.filename+ method can be used to
12518 * determine the filename of the current byte.
12519 *
12520 * If no block is given, an enumerator is returned instead.
12521 *
12522 * For example:
12523 *
12524 * ARGF.bytes.to_a #=> [35, 32, ... 95, 10]
12525 *
12526 */
12527static VALUE
12528argf_each_byte(VALUE argf)
12529{
12530 RETURN_ENUMERATOR(argf, 0, 0);
12531 FOREACH_ARGF() {
12532 argf_block_call(rb_intern("each_byte"), 0, 0, argf);
12533 }
12534 return argf;
12535}
12536
12537/*
12538 * This is a deprecated alias for #each_byte.
12539 */
12540
12541static VALUE
12542argf_bytes(VALUE argf)
12543{
12544 rb_warn_deprecated("ARGF#bytes", "#each_byte");
12545 if (!rb_block_given_p())
12546 return rb_enumeratorize(argf, ID2SYM(rb_intern("each_byte")), 0, 0);
12547 return argf_each_byte(argf);
12548}
12549
12550/*
12551 * call-seq:
12552 * ARGF.each_char {|char| block } -> ARGF
12553 * ARGF.each_char -> an_enumerator
12554 *
12555 * Iterates over each character of each file in +ARGF+.
12556 *
12557 * This method allows you to treat the files supplied on the command line as
12558 * a single file consisting of the concatenation of each named file. After
12559 * the last character of the first file has been returned, the first
12560 * character of the second file is returned. The +ARGF.filename+ method can
12561 * be used to determine the name of the file in which the current character
12562 * appears.
12563 *
12564 * If no block is given, an enumerator is returned instead.
12565 */
12566static VALUE
12567argf_each_char(VALUE argf)
12568{
12569 RETURN_ENUMERATOR(argf, 0, 0);
12570 FOREACH_ARGF() {
12571 argf_block_call(rb_intern("each_char"), 0, 0, argf);
12572 }
12573 return argf;
12574}
12575
12576/*
12577 * This is a deprecated alias for #each_char.
12578 */
12579
12580static VALUE
12581argf_chars(VALUE argf)
12582{
12583 rb_warn_deprecated("ARGF#chars", "#each_char");
12584 if (!rb_block_given_p())
12585 return rb_enumeratorize(argf, ID2SYM(rb_intern("each_char")), 0, 0);
12586 return argf_each_char(argf);
12587}
12588
12589/*
12590 * call-seq:
12591 * ARGF.each_codepoint {|codepoint| block } -> ARGF
12592 * ARGF.each_codepoint -> an_enumerator
12593 *
12594 * Iterates over each codepoint of each file in +ARGF+.
12595 *
12596 * This method allows you to treat the files supplied on the command line as
12597 * a single file consisting of the concatenation of each named file. After
12598 * the last codepoint of the first file has been returned, the first
12599 * codepoint of the second file is returned. The +ARGF.filename+ method can
12600 * be used to determine the name of the file in which the current codepoint
12601 * appears.
12602 *
12603 * If no block is given, an enumerator is returned instead.
12604 */
12605static VALUE
12606argf_each_codepoint(VALUE argf)
12607{
12608 RETURN_ENUMERATOR(argf, 0, 0);
12609 FOREACH_ARGF() {
12610 argf_block_call(rb_intern("each_codepoint"), 0, 0, argf);
12611 }
12612 return argf;
12613}
12614
12615/*
12616 * This is a deprecated alias for #each_codepoint.
12617 */
12618
12619static VALUE
12620argf_codepoints(VALUE argf)
12621{
12622 rb_warn_deprecated("ARGF#codepoints", "#each_codepoint");
12623 if (!rb_block_given_p())
12624 return rb_enumeratorize(argf, ID2SYM(rb_intern("each_codepoint")), 0, 0);
12625 return argf_each_codepoint(argf);
12626}
12627
12628/*
12629 * call-seq:
12630 * ARGF.filename -> String
12631 * ARGF.path -> String
12632 *
12633 * Returns the current filename. "-" is returned when the current file is
12634 * STDIN.
12635 *
12636 * For example:
12637 *
12638 * $ echo "foo" > foo
12639 * $ echo "bar" > bar
12640 * $ echo "glark" > glark
12641 *
12642 * $ ruby argf.rb foo bar glark
12643 *
12644 * ARGF.filename #=> "foo"
12645 * ARGF.read(5) #=> "foo\nb"
12646 * ARGF.filename #=> "bar"
12647 * ARGF.skip
12648 * ARGF.filename #=> "glark"
12649 */
12650static VALUE
12651argf_filename(VALUE argf)
12652{
12653 next_argv();
12654 return ARGF.filename;
12655}
12656
12657static VALUE
12658argf_filename_getter(ID id, VALUE *var)
12659{
12660 return argf_filename(*var);
12661}
12662
12663/*
12664 * call-seq:
12665 * ARGF.file -> IO or File object
12666 *
12667 * Returns the current file as an +IO+ or +File+ object.
12668 * <code>$stdin</code> is returned when the current file is STDIN.
12669 *
12670 * For example:
12671 *
12672 * $ echo "foo" > foo
12673 * $ echo "bar" > bar
12674 *
12675 * $ ruby argf.rb foo bar
12676 *
12677 * ARGF.file #=> #<File:foo>
12678 * ARGF.read(5) #=> "foo\nb"
12679 * ARGF.file #=> #<File:bar>
12680 */
12681static VALUE
12682argf_file(VALUE argf)
12683{
12684 next_argv();
12685 return ARGF.current_file;
12686}
12687
12688/*
12689 * call-seq:
12690 * ARGF.binmode -> ARGF
12691 *
12692 * Puts +ARGF+ into binary mode. Once a stream is in binary mode, it cannot
12693 * be reset to non-binary mode. This option has the following effects:
12694 *
12695 * * Newline conversion is disabled.
12696 * * Encoding conversion is disabled.
12697 * * Content is treated as ASCII-8BIT.
12698 */
12699static VALUE
12700argf_binmode_m(VALUE argf)
12701{
12702 ARGF.binmode = 1;
12703 next_argv();
12704 ARGF_FORWARD(0, 0);
12705 rb_io_ascii8bit_binmode(ARGF.current_file);
12706 return argf;
12707}
12708
12709/*
12710 * call-seq:
12711 * ARGF.binmode? -> true or false
12712 *
12713 * Returns true if +ARGF+ is being read in binary mode; false otherwise.
12714 * To enable binary mode use +ARGF.binmode+.
12715 *
12716 * For example:
12717 *
12718 * ARGF.binmode? #=> false
12719 * ARGF.binmode
12720 * ARGF.binmode? #=> true
12721 */
12722static VALUE
12723argf_binmode_p(VALUE argf)
12724{
12725 return ARGF.binmode ? Qtrue : Qfalse;
12726}
12727
12728/*
12729 * call-seq:
12730 * ARGF.skip -> ARGF
12731 *
12732 * Sets the current file to the next file in ARGV. If there aren't any more
12733 * files it has no effect.
12734 *
12735 * For example:
12736 *
12737 * $ ruby argf.rb foo bar
12738 * ARGF.filename #=> "foo"
12739 * ARGF.skip
12740 * ARGF.filename #=> "bar"
12741 */
12742static VALUE
12743argf_skip(VALUE argf)
12744{
12745 if (ARGF.init_p && ARGF.next_p == 0) {
12746 argf_close(argf);
12747 ARGF.next_p = 1;
12748 }
12749 return argf;
12750}
12751
12752/*
12753 * call-seq:
12754 * ARGF.close -> ARGF
12755 *
12756 * Closes the current file and skips to the next file in ARGV. If there are
12757 * no more files to open, just closes the current file. +STDIN+ will not be
12758 * closed.
12759 *
12760 * For example:
12761 *
12762 * $ ruby argf.rb foo bar
12763 *
12764 * ARGF.filename #=> "foo"
12765 * ARGF.close
12766 * ARGF.filename #=> "bar"
12767 * ARGF.close
12768 */
12769static VALUE
12770argf_close_m(VALUE argf)
12771{
12772 next_argv();
12773 argf_close(argf);
12774 if (ARGF.next_p != -1) {
12775 ARGF.next_p = 1;
12776 }
12777 ARGF.lineno = 0;
12778 return argf;
12779}
12780
12781/*
12782 * call-seq:
12783 * ARGF.closed? -> true or false
12784 *
12785 * Returns _true_ if the current file has been closed; _false_ otherwise. Use
12786 * +ARGF.close+ to actually close the current file.
12787 */
12788static VALUE
12789argf_closed(VALUE argf)
12790{
12791 next_argv();
12792 ARGF_FORWARD(0, 0);
12793 return rb_io_closed(ARGF.current_file);
12794}
12795
12796/*
12797 * call-seq:
12798 * ARGF.to_s -> String
12799 *
12800 * Returns "ARGF".
12801 */
12802static VALUE
12803argf_to_s(VALUE argf)
12804{
12805 return rb_str_new2("ARGF");
12806}
12807
12808/*
12809 * call-seq:
12810 * ARGF.inplace_mode -> String
12811 *
12812 * Returns the file extension appended to the names of modified files under
12813 * in-place edit mode. This value can be set using +ARGF.inplace_mode=+ or
12814 * passing the +-i+ switch to the Ruby binary.
12815 */
12816static VALUE
12817argf_inplace_mode_get(VALUE argf)
12818{
12819 if (!ARGF.inplace) return Qnil;
12820 if (NIL_P(ARGF.inplace)) return rb_str_new(0, 0);
12821 return rb_str_dup(ARGF.inplace);
12822}
12823
12824static VALUE
12825opt_i_get(ID id, VALUE *var)
12826{
12827 return argf_inplace_mode_get(*var);
12828}
12829
12830/*
12831 * call-seq:
12832 * ARGF.inplace_mode = ext -> ARGF
12833 *
12834 * Sets the filename extension for in-place editing mode to the given String.
12835 * Each file being edited has this value appended to its filename. The
12836 * modified file is saved under this new name.
12837 *
12838 * For example:
12839 *
12840 * $ ruby argf.rb file.txt
12841 *
12842 * ARGF.inplace_mode = '.bak'
12843 * ARGF.each_line do |line|
12844 * print line.sub("foo","bar")
12845 * end
12846 *
12847 * Each line of _file.txt_ has the first occurrence of "foo" replaced with
12848 * "bar", then the new line is written out to _file.txt.bak_.
12849 */
12850static VALUE
12851argf_inplace_mode_set(VALUE argf, VALUE val)
12852{
12853 if (!RTEST(val)) {
12854 ARGF.inplace = Qfalse;
12855 }
12856 else if (StringValueCStr(val), !RSTRING_LEN(val)) {
12857 ARGF.inplace = Qnil;
12858 }
12859 else {
12860 ARGF.inplace = rb_str_new_frozen(val);
12861 }
12862 return argf;
12863}
12864
12865static void
12866opt_i_set(VALUE val, ID id, VALUE *var)
12867{
12868 argf_inplace_mode_set(*var, val);
12869}
12870
12871void
12872ruby_set_inplace_mode(const char *suffix)
12873{
12874 ARGF.inplace = !suffix ? Qfalse : !*suffix ? Qnil : rb_fstring_cstr(suffix);
12875}
12876
12877/*
12878 * call-seq:
12879 * ARGF.argv -> ARGV
12880 *
12881 * Returns the +ARGV+ array, which contains the arguments passed to your
12882 * script, one per element.
12883 *
12884 * For example:
12885 *
12886 * $ ruby argf.rb -v glark.txt
12887 *
12888 * ARGF.argv #=> ["-v", "glark.txt"]
12889 *
12890 */
12891static VALUE
12892argf_argv(VALUE argf)
12893{
12894 return ARGF.argv;
12895}
12896
12897static VALUE
12898argf_argv_getter(ID id, VALUE *var)
12899{
12900 return argf_argv(*var);
12901}
12902
12903VALUE
12905{
12906 return ARGF.argv;
12907}
12908
12909/*
12910 * call-seq:
12911 * ARGF.to_write_io -> io
12912 *
12913 * Returns IO instance tied to _ARGF_ for writing if inplace mode is
12914 * enabled.
12915 */
12916static VALUE
12917argf_write_io(VALUE argf)
12918{
12919 if (!RTEST(ARGF.current_file)) {
12920 rb_raise(rb_eIOError, "not opened for writing");
12921 }
12922 return GetWriteIO(ARGF.current_file);
12923}
12924
12925/*
12926 * call-seq:
12927 * ARGF.write(string) -> integer
12928 *
12929 * Writes _string_ if inplace mode.
12930 */
12931static VALUE
12932argf_write(VALUE argf, VALUE str)
12933{
12934 return rb_io_write(argf_write_io(argf), str);
12935}
12936
12937void
12938rb_readwrite_sys_fail(enum rb_io_wait_readwrite writable, const char *mesg)
12939{
12940 rb_readwrite_syserr_fail(writable, errno, mesg);
12941}
12942
12943void
12944rb_readwrite_syserr_fail(enum rb_io_wait_readwrite writable, int n, const char *mesg)
12945{
12946 VALUE arg;
12947 arg = mesg ? rb_str_new2(mesg) : Qnil;
12948 if (writable == RB_IO_WAIT_WRITABLE) {
12949 switch (n) {
12950 case EAGAIN:
12951 rb_exc_raise(rb_class_new_instance(1, &arg, rb_eEAGAINWaitWritable));
12952 break;
12953#if EAGAIN != EWOULDBLOCK
12954 case EWOULDBLOCK:
12955 rb_exc_raise(rb_class_new_instance(1, &arg, rb_eEWOULDBLOCKWaitWritable));
12956 break;
12957#endif
12958 case EINPROGRESS:
12959 rb_exc_raise(rb_class_new_instance(1, &arg, rb_eEINPROGRESSWaitWritable));
12960 break;
12961 default:
12963 }
12964 }
12965 else if (writable == RB_IO_WAIT_READABLE) {
12966 switch (n) {
12967 case EAGAIN:
12968 rb_exc_raise(rb_class_new_instance(1, &arg, rb_eEAGAINWaitReadable));
12969 break;
12970#if EAGAIN != EWOULDBLOCK
12971 case EWOULDBLOCK:
12972 rb_exc_raise(rb_class_new_instance(1, &arg, rb_eEWOULDBLOCKWaitReadable));
12973 break;
12974#endif
12975 case EINPROGRESS:
12976 rb_exc_raise(rb_class_new_instance(1, &arg, rb_eEINPROGRESSWaitReadable));
12977 break;
12978 default:
12980 }
12981 }
12982 else {
12983 rb_bug("invalid read/write type passed to rb_readwrite_sys_fail: %d", writable);
12984 }
12985}
12986
12987static VALUE
12988get_LAST_READ_LINE(ID _x, VALUE *_y)
12989{
12990 return rb_lastline_get();
12991}
12992
12993static void
12994set_LAST_READ_LINE(VALUE val, ID _x, VALUE *_y)
12995{
12996 rb_lastline_set(val);
12997}
12998
12999/*
13000 * Document-class: IOError
13001 *
13002 * Raised when an IO operation fails.
13003 *
13004 * File.open("/etc/hosts") {|f| f << "example"}
13005 * #=> IOError: not opened for writing
13006 *
13007 * File.open("/etc/hosts") {|f| f.close; f.read }
13008 * #=> IOError: closed stream
13009 *
13010 * Note that some IO failures raise <code>SystemCallError</code>s
13011 * and these are not subclasses of IOError:
13012 *
13013 * File.open("does/not/exist")
13014 * #=> Errno::ENOENT: No such file or directory - does/not/exist
13015 */
13016
13017/*
13018 * Document-class: EOFError
13019 *
13020 * Raised by some IO operations when reaching the end of file. Many IO
13021 * methods exist in two forms,
13022 *
13023 * one that returns +nil+ when the end of file is reached, the other
13024 * raises +EOFError+.
13025 *
13026 * +EOFError+ is a subclass of +IOError+.
13027 *
13028 * file = File.open("/etc/hosts")
13029 * file.read
13030 * file.gets #=> nil
13031 * file.readline #=> EOFError: end of file reached
13032 */
13033
13034/*
13035 * Document-class: ARGF
13036 *
13037 * +ARGF+ is a stream designed for use in scripts that process files given as
13038 * command-line arguments or passed in via STDIN.
13039 *
13040 * The arguments passed to your script are stored in the +ARGV+ Array, one
13041 * argument per element. +ARGF+ assumes that any arguments that aren't
13042 * filenames have been removed from +ARGV+. For example:
13043 *
13044 * $ ruby argf.rb --verbose file1 file2
13045 *
13046 * ARGV #=> ["--verbose", "file1", "file2"]
13047 * option = ARGV.shift #=> "--verbose"
13048 * ARGV #=> ["file1", "file2"]
13049 *
13050 * You can now use +ARGF+ to work with a concatenation of each of these named
13051 * files. For instance, +ARGF.read+ will return the contents of _file1_
13052 * followed by the contents of _file2_.
13053 *
13054 * After a file in +ARGV+ has been read +ARGF+ removes it from the Array.
13055 * Thus, after all files have been read +ARGV+ will be empty.
13056 *
13057 * You can manipulate +ARGV+ yourself to control what +ARGF+ operates on. If
13058 * you remove a file from +ARGV+, it is ignored by +ARGF+; if you add files to
13059 * +ARGV+, they are treated as if they were named on the command line. For
13060 * example:
13061 *
13062 * ARGV.replace ["file1"]
13063 * ARGF.readlines # Returns the contents of file1 as an Array
13064 * ARGV #=> []
13065 * ARGV.replace ["file2", "file3"]
13066 * ARGF.read # Returns the contents of file2 and file3
13067 *
13068 * If +ARGV+ is empty, +ARGF+ acts as if it contained STDIN, i.e. the data
13069 * piped to your script. For example:
13070 *
13071 * $ echo "glark" | ruby -e 'p ARGF.read'
13072 * "glark\n"
13073 */
13074
13075/*
13076 * The IO class is the basis for all input and output in Ruby.
13077 * An I/O stream may be <em>duplexed</em> (that is, bidirectional), and
13078 * so may use more than one native operating system stream.
13079 *
13080 * Many of the examples in this section use the File class, the only standard
13081 * subclass of IO. The two classes are closely associated. Like the File
13082 * class, the Socket library subclasses from IO (such as TCPSocket or
13083 * UDPSocket).
13084 *
13085 * The Kernel#open method can create an IO (or File) object for these types
13086 * of arguments:
13087 *
13088 * * A plain string represents a filename suitable for the underlying
13089 * operating system.
13090 *
13091 * * A string starting with <code>"|"</code> indicates a subprocess.
13092 * The remainder of the string following the <code>"|"</code> is
13093 * invoked as a process with appropriate input/output channels
13094 * connected to it.
13095 *
13096 * * A string equal to <code>"|-"</code> will create another Ruby
13097 * instance as a subprocess.
13098 *
13099 * The IO may be opened with different file modes (read-only, write-only) and
13100 * encodings for proper conversion. See IO.new for these options. See
13101 * Kernel#open for details of the various command formats described above.
13102 *
13103 * IO.popen, the Open3 library, or Process#spawn may also be used to
13104 * communicate with subprocesses through an IO.
13105 *
13106 * Ruby will convert pathnames between different operating system
13107 * conventions if possible. For instance, on a Windows system the
13108 * filename <code>"/gumby/ruby/test.rb"</code> will be opened as
13109 * <code>"\gumby\ruby\test.rb"</code>. When specifying a Windows-style
13110 * filename in a Ruby string, remember to escape the backslashes:
13111 *
13112 * "C:\\gumby\\ruby\\test.rb"
13113 *
13114 * Our examples here will use the Unix-style forward slashes;
13115 * File::ALT_SEPARATOR can be used to get the platform-specific separator
13116 * character.
13117 *
13118 * The global constant ARGF (also accessible as <code>$<</code>) provides an
13119 * IO-like stream which allows access to all files mentioned on the
13120 * command line (or STDIN if no files are mentioned). ARGF#path and its alias
13121 * ARGF#filename are provided to access the name of the file currently being
13122 * read.
13123 *
13124 * == io/console
13125 *
13126 * The io/console extension provides methods for interacting with the
13127 * console. The console can be accessed from IO.console or the standard
13128 * input/output/error IO objects.
13129 *
13130 * Requiring io/console adds the following methods:
13131 *
13132 * * IO::console
13133 * * IO#raw
13134 * * IO#raw!
13135 * * IO#cooked
13136 * * IO#cooked!
13137 * * IO#getch
13138 * * IO#echo=
13139 * * IO#echo?
13140 * * IO#noecho
13141 * * IO#winsize
13142 * * IO#winsize=
13143 * * IO#iflush
13144 * * IO#ioflush
13145 * * IO#oflush
13146 *
13147 * Example:
13148 *
13149 * require 'io/console'
13150 * rows, columns = $stdout.winsize
13151 * puts "Your screen is #{columns} wide and #{rows} tall"
13152 */
13153
13154void
13156{
13157#undef rb_intern
13158#define rb_intern(str) rb_intern_const(str)
13159
13160 VALUE rb_cARGF;
13161#ifdef __CYGWIN__
13162#include <sys/cygwin.h>
13163 static struct __cygwin_perfile pf[] =
13164 {
13165 {"", O_RDONLY | O_BINARY},
13166 {"", O_WRONLY | O_BINARY},
13167 {"", O_RDWR | O_BINARY},
13168 {"", O_APPEND | O_BINARY},
13169 {NULL, 0}
13170 };
13171 cygwin_internal(CW_PERFILE, pf);
13172#endif
13173
13176
13177 id_write = rb_intern("write");
13178 id_read = rb_intern("read");
13179 id_getc = rb_intern("getc");
13180 id_flush = rb_intern("flush");
13181 id_readpartial = rb_intern("readpartial");
13182 id_set_encoding = rb_intern("set_encoding");
13183
13185
13186 rb_define_global_function("open", rb_f_open, -1);
13187 rb_define_global_function("printf", rb_f_printf, -1);
13188 rb_define_global_function("print", rb_f_print, -1);
13189 rb_define_global_function("putc", rb_f_putc, 1);
13190 rb_define_global_function("puts", rb_f_puts, -1);
13191 rb_define_global_function("gets", rb_f_gets, -1);
13192 rb_define_global_function("readline", rb_f_readline, -1);
13193 rb_define_global_function("select", rb_f_select, -1);
13194
13195 rb_define_global_function("readlines", rb_f_readlines, -1);
13196
13197 rb_define_global_function("`", rb_f_backquote, 1);
13198
13199 rb_define_global_function("p", rb_f_p, -1);
13200 rb_define_method(rb_mKernel, "display", rb_obj_display, -1);
13201
13204
13205 /* exception to wait for reading. see IO.select. */
13207 /* exception to wait for writing. see IO.select. */
13209 /* exception to wait for reading by EAGAIN. see IO.select. */
13210 rb_eEAGAINWaitReadable = rb_define_class_under(rb_cIO, "EAGAINWaitReadable", rb_eEAGAIN);
13211 rb_include_module(rb_eEAGAINWaitReadable, rb_mWaitReadable);
13212 /* exception to wait for writing by EAGAIN. see IO.select. */
13213 rb_eEAGAINWaitWritable = rb_define_class_under(rb_cIO, "EAGAINWaitWritable", rb_eEAGAIN);
13214 rb_include_module(rb_eEAGAINWaitWritable, rb_mWaitWritable);
13215#if EAGAIN == EWOULDBLOCK
13216 rb_eEWOULDBLOCKWaitReadable = rb_eEAGAINWaitReadable;
13217 /* same as IO::EAGAINWaitReadable */
13218 rb_define_const(rb_cIO, "EWOULDBLOCKWaitReadable", rb_eEAGAINWaitReadable);
13219 rb_eEWOULDBLOCKWaitWritable = rb_eEAGAINWaitWritable;
13220 /* same as IO::EAGAINWaitWritable */
13221 rb_define_const(rb_cIO, "EWOULDBLOCKWaitWritable", rb_eEAGAINWaitWritable);
13222#else
13223 /* exception to wait for reading by EWOULDBLOCK. see IO.select. */
13224 rb_eEWOULDBLOCKWaitReadable = rb_define_class_under(rb_cIO, "EWOULDBLOCKWaitReadable", rb_eEWOULDBLOCK);
13225 rb_include_module(rb_eEWOULDBLOCKWaitReadable, rb_mWaitReadable);
13226 /* exception to wait for writing by EWOULDBLOCK. see IO.select. */
13227 rb_eEWOULDBLOCKWaitWritable = rb_define_class_under(rb_cIO, "EWOULDBLOCKWaitWritable", rb_eEWOULDBLOCK);
13228 rb_include_module(rb_eEWOULDBLOCKWaitWritable, rb_mWaitWritable);
13229#endif
13230 /* exception to wait for reading by EINPROGRESS. see IO.select. */
13231 rb_eEINPROGRESSWaitReadable = rb_define_class_under(rb_cIO, "EINPROGRESSWaitReadable", rb_eEINPROGRESS);
13232 rb_include_module(rb_eEINPROGRESSWaitReadable, rb_mWaitReadable);
13233 /* exception to wait for writing by EINPROGRESS. see IO.select. */
13234 rb_eEINPROGRESSWaitWritable = rb_define_class_under(rb_cIO, "EINPROGRESSWaitWritable", rb_eEINPROGRESS);
13235 rb_include_module(rb_eEINPROGRESSWaitWritable, rb_mWaitWritable);
13236
13237#if 0
13238 /* This is necessary only for forcing rdoc handle File::open */
13239 rb_define_singleton_method(rb_cFile, "open", rb_io_s_open, -1);
13240#endif
13241
13242 rb_define_alloc_func(rb_cIO, io_alloc);
13243 rb_define_singleton_method(rb_cIO, "new", rb_io_s_new, -1);
13244 rb_define_singleton_method(rb_cIO, "open", rb_io_s_open, -1);
13245 rb_define_singleton_method(rb_cIO, "sysopen", rb_io_s_sysopen, -1);
13246 rb_define_singleton_method(rb_cIO, "for_fd", rb_io_s_for_fd, -1);
13247 rb_define_singleton_method(rb_cIO, "popen", rb_io_s_popen, -1);
13248 rb_define_singleton_method(rb_cIO, "foreach", rb_io_s_foreach, -1);
13249 rb_define_singleton_method(rb_cIO, "readlines", rb_io_s_readlines, -1);
13250 rb_define_singleton_method(rb_cIO, "read", rb_io_s_read, -1);
13251 rb_define_singleton_method(rb_cIO, "binread", rb_io_s_binread, -1);
13252 rb_define_singleton_method(rb_cIO, "write", rb_io_s_write, -1);
13253 rb_define_singleton_method(rb_cIO, "binwrite", rb_io_s_binwrite, -1);
13254 rb_define_singleton_method(rb_cIO, "select", rb_f_select, -1);
13255 rb_define_singleton_method(rb_cIO, "pipe", rb_io_s_pipe, -1);
13256 rb_define_singleton_method(rb_cIO, "try_convert", rb_io_s_try_convert, 1);
13257 rb_define_singleton_method(rb_cIO, "copy_stream", rb_io_s_copy_stream, -1);
13258
13259 rb_define_method(rb_cIO, "initialize", rb_io_initialize, -1);
13260
13262 rb_define_hooked_variable("$,", &rb_output_fs, 0, rb_output_fs_setter);
13263
13264 rb_default_rs = rb_fstring_lit("\n"); /* avoid modifying RS_default */
13271
13272 rb_define_virtual_variable("$_", get_LAST_READ_LINE, set_LAST_READ_LINE);
13273
13274 rb_define_method(rb_cIO, "initialize_copy", rb_io_init_copy, 1);
13275 rb_define_method(rb_cIO, "reopen", rb_io_reopen, -1);
13276
13277 rb_define_method(rb_cIO, "print", rb_io_print, -1);
13278 rb_define_method(rb_cIO, "putc", rb_io_putc, 1);
13279 rb_define_method(rb_cIO, "puts", rb_io_puts, -1);
13280 rb_define_method(rb_cIO, "printf", rb_io_printf, -1);
13281
13282 rb_define_method(rb_cIO, "each", rb_io_each_line, -1);
13283 rb_define_method(rb_cIO, "each_line", rb_io_each_line, -1);
13284 rb_define_method(rb_cIO, "each_byte", rb_io_each_byte, 0);
13285 rb_define_method(rb_cIO, "each_char", rb_io_each_char, 0);
13286 rb_define_method(rb_cIO, "each_codepoint", rb_io_each_codepoint, 0);
13287 rb_define_method(rb_cIO, "lines", rb_io_lines, -1);
13288 rb_define_method(rb_cIO, "bytes", rb_io_bytes, 0);
13289 rb_define_method(rb_cIO, "chars", rb_io_chars, 0);
13290 rb_define_method(rb_cIO, "codepoints", rb_io_codepoints, 0);
13291
13292 rb_define_method(rb_cIO, "syswrite", rb_io_syswrite, 1);
13293 rb_define_method(rb_cIO, "sysread", rb_io_sysread, -1);
13294
13295 rb_define_method(rb_cIO, "pread", rb_io_pread, -1);
13296 rb_define_method(rb_cIO, "pwrite", rb_io_pwrite, 2);
13297
13298 rb_define_method(rb_cIO, "fileno", rb_io_fileno, 0);
13299 rb_define_alias(rb_cIO, "to_i", "fileno");
13300 rb_define_method(rb_cIO, "to_io", rb_io_to_io, 0);
13301
13302 rb_define_method(rb_cIO, "fsync", rb_io_fsync, 0);
13303 rb_define_method(rb_cIO, "fdatasync", rb_io_fdatasync, 0);
13304 rb_define_method(rb_cIO, "sync", rb_io_sync, 0);
13305 rb_define_method(rb_cIO, "sync=", rb_io_set_sync, 1);
13306
13307 rb_define_method(rb_cIO, "lineno", rb_io_lineno, 0);
13308 rb_define_method(rb_cIO, "lineno=", rb_io_set_lineno, 1);
13309
13310 rb_define_method(rb_cIO, "readlines", rb_io_readlines, -1);
13311
13312 rb_define_method(rb_cIO, "readpartial", io_readpartial, -1);
13313 rb_define_method(rb_cIO, "read", io_read, -1);
13314 rb_define_method(rb_cIO, "write", io_write_m, -1);
13315 rb_define_method(rb_cIO, "gets", rb_io_gets_m, -1);
13316 rb_define_method(rb_cIO, "readline", rb_io_readline, -1);
13317 rb_define_method(rb_cIO, "getc", rb_io_getc, 0);
13318 rb_define_method(rb_cIO, "getbyte", rb_io_getbyte, 0);
13319 rb_define_method(rb_cIO, "readchar", rb_io_readchar, 0);
13320 rb_define_method(rb_cIO, "readbyte", rb_io_readbyte, 0);
13321 rb_define_method(rb_cIO, "ungetbyte",rb_io_ungetbyte, 1);
13322 rb_define_method(rb_cIO, "ungetc",rb_io_ungetc, 1);
13324 rb_define_method(rb_cIO, "flush", rb_io_flush, 0);
13325 rb_define_method(rb_cIO, "tell", rb_io_tell, 0);
13326 rb_define_method(rb_cIO, "seek", rb_io_seek_m, -1);
13327 /* Set I/O position from the beginning */
13328 rb_define_const(rb_cIO, "SEEK_SET", INT2FIX(SEEK_SET));
13329 /* Set I/O position from the current position */
13330 rb_define_const(rb_cIO, "SEEK_CUR", INT2FIX(SEEK_CUR));
13331 /* Set I/O position from the end */
13332 rb_define_const(rb_cIO, "SEEK_END", INT2FIX(SEEK_END));
13333#ifdef SEEK_DATA
13334 /* Set I/O position to the next location containing data */
13335 rb_define_const(rb_cIO, "SEEK_DATA", INT2FIX(SEEK_DATA));
13336#endif
13337#ifdef SEEK_HOLE
13338 /* Set I/O position to the next hole */
13339 rb_define_const(rb_cIO, "SEEK_HOLE", INT2FIX(SEEK_HOLE));
13340#endif
13341 rb_define_method(rb_cIO, "rewind", rb_io_rewind, 0);
13342 rb_define_method(rb_cIO, "pos", rb_io_tell, 0);
13343 rb_define_method(rb_cIO, "pos=", rb_io_set_pos, 1);
13344 rb_define_method(rb_cIO, "eof", rb_io_eof, 0);
13345 rb_define_method(rb_cIO, "eof?", rb_io_eof, 0);
13346
13347 rb_define_method(rb_cIO, "close_on_exec?", rb_io_close_on_exec_p, 0);
13348 rb_define_method(rb_cIO, "close_on_exec=", rb_io_set_close_on_exec, 1);
13349
13350 rb_define_method(rb_cIO, "close", rb_io_close_m, 0);
13351 rb_define_method(rb_cIO, "closed?", rb_io_closed, 0);
13352 rb_define_method(rb_cIO, "close_read", rb_io_close_read, 0);
13353 rb_define_method(rb_cIO, "close_write", rb_io_close_write, 0);
13354
13355 rb_define_method(rb_cIO, "isatty", rb_io_isatty, 0);
13356 rb_define_method(rb_cIO, "tty?", rb_io_isatty, 0);
13357 rb_define_method(rb_cIO, "binmode", rb_io_binmode_m, 0);
13358 rb_define_method(rb_cIO, "binmode?", rb_io_binmode_p, 0);
13359 rb_define_method(rb_cIO, "sysseek", rb_io_sysseek, -1);
13360 rb_define_method(rb_cIO, "advise", rb_io_advise, -1);
13361
13362 rb_define_method(rb_cIO, "ioctl", rb_io_ioctl, -1);
13363 rb_define_method(rb_cIO, "fcntl", rb_io_fcntl, -1);
13364 rb_define_method(rb_cIO, "pid", rb_io_pid, 0);
13365 rb_define_method(rb_cIO, "inspect", rb_io_inspect, 0);
13366
13367 rb_define_method(rb_cIO, "external_encoding", rb_io_external_encoding, 0);
13368 rb_define_method(rb_cIO, "internal_encoding", rb_io_internal_encoding, 0);
13369 rb_define_method(rb_cIO, "set_encoding", rb_io_set_encoding, -1);
13370 rb_define_method(rb_cIO, "set_encoding_by_bom", rb_io_set_encoding_by_bom, 0);
13371
13372 rb_define_method(rb_cIO, "autoclose?", rb_io_autoclose_p, 0);
13373 rb_define_method(rb_cIO, "autoclose=", rb_io_set_autoclose, 1);
13374
13375 rb_define_variable("$stdin", &rb_stdin);
13376 rb_stdin = prep_stdio(stdin, FMODE_READABLE, rb_cIO, "<STDIN>");
13377 rb_define_hooked_variable("$stdout", &rb_stdout, 0, stdout_setter);
13378 rb_stdout = prep_stdio(stdout, FMODE_WRITABLE, rb_cIO, "<STDOUT>");
13379 rb_define_hooked_variable("$stderr", &rb_stderr, 0, stdout_setter);
13380 rb_stderr = prep_stdio(stderr, FMODE_WRITABLE|FMODE_SYNC, rb_cIO, "<STDERR>");
13381 rb_define_hooked_variable("$>", &rb_stdout, 0, stdout_setter);
13382 orig_stdout = rb_stdout;
13383 orig_stderr = rb_stderr;
13384
13385 /* Holds the original stdin */
13387 /* Holds the original stdout */
13389 /* Holds the original stderr */
13391
13392#if 0
13393 /* Hack to get rdoc to regard ARGF as a class: */
13394 rb_cARGF = rb_define_class("ARGF", rb_cObject);
13395#endif
13396
13397 rb_cARGF = rb_class_new(rb_cObject);
13398 rb_set_class_path(rb_cARGF, rb_cObject, "ARGF.class");
13399 rb_define_alloc_func(rb_cARGF, argf_alloc);
13400
13402
13403 rb_define_method(rb_cARGF, "initialize", argf_initialize, -2);
13404 rb_define_method(rb_cARGF, "initialize_copy", argf_initialize_copy, 1);
13405 rb_define_method(rb_cARGF, "to_s", argf_to_s, 0);
13406 rb_define_alias(rb_cARGF, "inspect", "to_s");
13407 rb_define_method(rb_cARGF, "argv", argf_argv, 0);
13408
13409 rb_define_method(rb_cARGF, "fileno", argf_fileno, 0);
13410 rb_define_method(rb_cARGF, "to_i", argf_fileno, 0);
13411 rb_define_method(rb_cARGF, "to_io", argf_to_io, 0);
13412 rb_define_method(rb_cARGF, "to_write_io", argf_write_io, 0);
13413 rb_define_method(rb_cARGF, "each", argf_each_line, -1);
13414 rb_define_method(rb_cARGF, "each_line", argf_each_line, -1);
13415 rb_define_method(rb_cARGF, "each_byte", argf_each_byte, 0);
13416 rb_define_method(rb_cARGF, "each_char", argf_each_char, 0);
13417 rb_define_method(rb_cARGF, "each_codepoint", argf_each_codepoint, 0);
13418 rb_define_method(rb_cARGF, "lines", argf_lines, -1);
13419 rb_define_method(rb_cARGF, "bytes", argf_bytes, 0);
13420 rb_define_method(rb_cARGF, "chars", argf_chars, 0);
13421 rb_define_method(rb_cARGF, "codepoints", argf_codepoints, 0);
13422
13423 rb_define_method(rb_cARGF, "read", argf_read, -1);
13424 rb_define_method(rb_cARGF, "readpartial", argf_readpartial, -1);
13425 rb_define_method(rb_cARGF, "read_nonblock", argf_read_nonblock, -1);
13426 rb_define_method(rb_cARGF, "readlines", argf_readlines, -1);
13427 rb_define_method(rb_cARGF, "to_a", argf_readlines, -1);
13428 rb_define_method(rb_cARGF, "gets", argf_gets, -1);
13429 rb_define_method(rb_cARGF, "readline", argf_readline, -1);
13430 rb_define_method(rb_cARGF, "getc", argf_getc, 0);
13431 rb_define_method(rb_cARGF, "getbyte", argf_getbyte, 0);
13432 rb_define_method(rb_cARGF, "readchar", argf_readchar, 0);
13433 rb_define_method(rb_cARGF, "readbyte", argf_readbyte, 0);
13434 rb_define_method(rb_cARGF, "tell", argf_tell, 0);
13435 rb_define_method(rb_cARGF, "seek", argf_seek_m, -1);
13436 rb_define_method(rb_cARGF, "rewind", argf_rewind, 0);
13437 rb_define_method(rb_cARGF, "pos", argf_tell, 0);
13438 rb_define_method(rb_cARGF, "pos=", argf_set_pos, 1);
13439 rb_define_method(rb_cARGF, "eof", argf_eof, 0);
13440 rb_define_method(rb_cARGF, "eof?", argf_eof, 0);
13441 rb_define_method(rb_cARGF, "binmode", argf_binmode_m, 0);
13442 rb_define_method(rb_cARGF, "binmode?", argf_binmode_p, 0);
13443
13444 rb_define_method(rb_cARGF, "write", argf_write, 1);
13445 rb_define_method(rb_cARGF, "print", rb_io_print, -1);
13446 rb_define_method(rb_cARGF, "putc", rb_io_putc, 1);
13447 rb_define_method(rb_cARGF, "puts", rb_io_puts, -1);
13448 rb_define_method(rb_cARGF, "printf", rb_io_printf, -1);
13449
13450 rb_define_method(rb_cARGF, "filename", argf_filename, 0);
13451 rb_define_method(rb_cARGF, "path", argf_filename, 0);
13452 rb_define_method(rb_cARGF, "file", argf_file, 0);
13453 rb_define_method(rb_cARGF, "skip", argf_skip, 0);
13454 rb_define_method(rb_cARGF, "close", argf_close_m, 0);
13455 rb_define_method(rb_cARGF, "closed?", argf_closed, 0);
13456
13457 rb_define_method(rb_cARGF, "lineno", argf_lineno, 0);
13458 rb_define_method(rb_cARGF, "lineno=", argf_set_lineno, 1);
13459
13460 rb_define_method(rb_cARGF, "inplace_mode", argf_inplace_mode_get, 0);
13461 rb_define_method(rb_cARGF, "inplace_mode=", argf_inplace_mode_set, 1);
13462
13463 rb_define_method(rb_cARGF, "external_encoding", argf_external_encoding, 0);
13464 rb_define_method(rb_cARGF, "internal_encoding", argf_internal_encoding, 0);
13465 rb_define_method(rb_cARGF, "set_encoding", argf_set_encoding, -1);
13466
13467 argf = rb_class_new_instance(0, 0, rb_cARGF);
13468
13470 /*
13471 * ARGF is a stream designed for use in scripts that process files given
13472 * as command-line arguments or passed in via STDIN.
13473 *
13474 * See ARGF (the class) for more details.
13475 */
13477
13478 rb_define_hooked_variable("$.", &argf, argf_lineno_getter, argf_lineno_setter);
13479 rb_define_hooked_variable("$FILENAME", &argf, argf_filename_getter, rb_gvar_readonly_setter);
13480 ARGF.filename = rb_str_new2("-");
13481
13482 rb_define_hooked_variable("$-i", &argf, opt_i_get, opt_i_set);
13483 rb_define_hooked_variable("$*", &argf, argf_argv_getter, rb_gvar_readonly_setter);
13484
13485#if defined (_WIN32) || defined(__CYGWIN__)
13486 atexit(pipe_atexit);
13487#endif
13488
13489 Init_File();
13490
13491 rb_define_method(rb_cFile, "initialize", rb_file_initialize, -1);
13492
13493 sym_mode = ID2SYM(rb_intern("mode"));
13494 sym_perm = ID2SYM(rb_intern("perm"));
13495 sym_flags = ID2SYM(rb_intern("flags"));
13496 sym_extenc = ID2SYM(rb_intern("external_encoding"));
13497 sym_intenc = ID2SYM(rb_intern("internal_encoding"));
13498 sym_encoding = ID2SYM(rb_id_encoding());
13499 sym_open_args = ID2SYM(rb_intern("open_args"));
13500 sym_textmode = ID2SYM(rb_intern("textmode"));
13501 sym_binmode = ID2SYM(rb_intern("binmode"));
13502 sym_autoclose = ID2SYM(rb_intern("autoclose"));
13503 sym_normal = ID2SYM(rb_intern("normal"));
13504 sym_sequential = ID2SYM(rb_intern("sequential"));
13505 sym_random = ID2SYM(rb_intern("random"));
13506 sym_willneed = ID2SYM(rb_intern("willneed"));
13507 sym_dontneed = ID2SYM(rb_intern("dontneed"));
13508 sym_noreuse = ID2SYM(rb_intern("noreuse"));
13509 sym_SET = ID2SYM(rb_intern("SET"));
13510 sym_CUR = ID2SYM(rb_intern("CUR"));
13511 sym_END = ID2SYM(rb_intern("END"));
13512#ifdef SEEK_DATA
13513 sym_DATA = ID2SYM(rb_intern("DATA"));
13514#endif
13515#ifdef SEEK_HOLE
13516 sym_HOLE = ID2SYM(rb_intern("HOLE"));
13517#endif
13518 sym_wait_readable = ID2SYM(rb_intern("wait_readable"));
13519 sym_wait_writable = ID2SYM(rb_intern("wait_writable"));
13520}
13521
13522#include "io.rbinc"
13523
13524void
13526{
13527 load_io();
13528}
#define O_BINARY
Definition: _sdbm.c:87
int errno
#define L(x)
Definition: asm.h:125
#define sym(x)
Definition: date_core.c:3717
#define recur(fmt)
struct RIMemo * ptr
Definition: debug.c:65
#define O_CLOEXEC
Definition: dir.c:28
#define ENCINDEX_UTF_32BE
Definition: encindex.h:47
#define ENCINDEX_UTF_32LE
Definition: encindex.h:48
#define ENCINDEX_UTF_16BE
Definition: encindex.h:45
#define ENCINDEX_UTF_16LE
Definition: encindex.h:46
struct rb_encoding_entry * list
Definition: encoding.c:56
rb_encoding * rb_find_encoding(VALUE enc)
Definition: encoding.c:252
int rb_enc_precise_mbclen(const char *p, const char *e, rb_encoding *enc)
Definition: encoding.c:1032
int rb_to_encoding_index(VALUE enc)
Definition: encoding.c:197
VALUE rb_enc_associate(VALUE obj, rb_encoding *enc)
Definition: encoding.c:866
rb_encoding * rb_ascii8bit_encoding(void)
Definition: encoding.c:1316
rb_encoding * rb_enc_from_index(int index)
Definition: encoding.c:609
rb_encoding * rb_default_internal_encoding(void)
Definition: encoding.c:1512
int rb_utf8_encindex(void)
Definition: encoding.c:1334
rb_encoding * rb_enc_get(VALUE obj)
Definition: encoding.c:872
rb_encoding * rb_default_external_encoding(void)
Definition: encoding.c:1427
int rb_enc_mbclen(const char *p, const char *e, rb_encoding *enc)
Definition: encoding.c:1020
rb_encoding * rb_to_encoding(VALUE enc)
Definition: encoding.c:245
rb_encoding * rb_usascii_encoding(void)
Definition: encoding.c:1340
int count
Definition: encoding.c:57
VALUE rb_enc_from_encoding(rb_encoding *encoding)
Definition: encoding.c:116
int rb_enc_find_index(const char *name)
Definition: encoding.c:693
int rb_enc_ascget(const char *p, const char *e, int *len, rb_encoding *enc)
Definition: encoding.c:1044
#define ECONV_AFTER_OUTPUT
Definition: encoding.h:416
int rb_econv_prepare_options(VALUE opthash, VALUE *ecopts, int ecflags)
Definition: transcode.c:2510
#define ENC_CODERANGE_7BIT
Definition: encoding.h:104
#define ENC_CODERANGE_VALID
Definition: encoding.h:105
VALUE rb_econv_open_exc(const char *senc, const char *denc, int ecflags)
Definition: transcode.c:2019
#define ECONV_UNIVERSAL_NEWLINE_DECORATOR
Definition: encoding.h:402
#define rb_enc_left_char_head(s, p, e, enc)
Definition: encoding.h:222
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:1429
rb_econv_result_t
Definition: encoding.h:297
@ econv_incomplete_input
Definition: encoding.h:304
@ econv_finished
Definition: encoding.h:302
@ econv_undefined_conversion
Definition: encoding.h:299
@ econv_source_buffer_empty
Definition: encoding.h:301
@ econv_destination_buffer_full
Definition: encoding.h:300
@ econv_invalid_byte_sequence
Definition: encoding.h:298
int rb_econv_putbackable(rb_econv_t *ec)
Definition: transcode.c:1725
int rb_enc_str_coderange(VALUE)
Definition: string.c:657
VALUE rb_enc_uint_chr(unsigned int code, rb_encoding *enc)
Definition: numeric.c:3380
VALUE rb_enc_str_new(const char *, long, rb_encoding *)
Definition: string.c:796
#define ENCODING_MAXNAMELEN
Definition: encoding.h:64
#define rb_enc_name(enc)
Definition: encoding.h:177
#define MBCLEN_NEEDMORE_LEN(ret)
Definition: encoding.h:195
#define ENCODING_GET(obj)
Definition: encoding.h:62
const char * rb_econv_asciicompat_encoding(const char *encname)
Definition: transcode.c:1769
VALUE rb_econv_str_convert(rb_econv_t *ec, VALUE src, int flags)
Definition: transcode.c:1860
rb_econv_t * rb_econv_open_opts(const char *source_encoding, const char *destination_encoding, int ecflags, VALUE ecopts)
Definition: transcode.c:2561
#define MBCLEN_CHARFOUND_LEN(ret)
Definition: encoding.h:192
#define rb_enc_asciicompat(enc)
Definition: encoding.h:245
void rb_econv_binmode(rb_econv_t *ec)
Definition: transcode.c:1925
#define rb_enc_codepoint(p, e, enc)
Definition: encoding.h:207
VALUE rb_str_encode(VALUE str, VALUE to, int ecflags, VALUE ecopts)
Definition: transcode.c:2870
VALUE rb_econv_make_exception(rb_econv_t *ec)
Definition: transcode.c:4218
#define MBCLEN_INVALID_P(ret)
Definition: encoding.h:193
void rb_econv_check_error(rb_econv_t *ec)
Definition: transcode.c:4224
#define ECONV_STATEFUL_DECORATOR_MASK
Definition: encoding.h:407
#define MBCLEN_NEEDMORE_P(ret)
Definition: encoding.h:194
#define rb_enc_mbminlen(enc)
Definition: encoding.h:180
#define ECONV_PARTIAL_INPUT
Definition: encoding.h:415
#define ECONV_ERROR_HANDLER_MASK
Definition: encoding.h:392
#define ENC_CODERANGE_BROKEN
Definition: encoding.h:106
long rb_str_coderange_scan_restartable(const char *, const char *, rb_encoding *, int *)
Definition: string.c:567
#define MBCLEN_CHARFOUND_P(ret)
Definition: encoding.h:191
void rb_econv_close(rb_econv_t *ec)
Definition: transcode.c:1685
#define ECONV_NEWLINE_DECORATOR_MASK
Definition: encoding.h:399
#define ENC_CODERANGE_SET(obj, cr)
Definition: encoding.h:110
void rb_econv_putback(rb_econv_t *ec, unsigned char *p, int n)
Definition: transcode.c:1736
#define ECONV_DEFAULT_NEWLINE_DECORATOR
Definition: encoding.h:409
char str[HTML_ESCAPE_MAX_LEN+1]
Definition: escape.c:18
void rb_include_module(VALUE, VALUE)
Definition: class.c:882
VALUE rb_define_class(const char *, VALUE)
Defines a top-level class.
Definition: class.c:662
VALUE rb_class_new(VALUE)
Creates a new class.
Definition: class.c:244
VALUE rb_define_class_under(VALUE, const char *, VALUE)
Defines a class under the namespace of outer.
Definition: class.c:711
VALUE rb_define_module_under(VALUE, const char *)
Definition: class.c:810
ID rb_frame_this_func(void)
The original name of the current method.
Definition: eval.c:1183
int rb_scan_args_kw(int, int, const VALUE *, const char *,...)
Definition: class.c:2198
void rb_define_alias(VALUE, const char *, const char *)
Defines an alias of a method.
Definition: class.c:1818
int rb_block_given_p(void)
Determines if the current method is given a block.
Definition: eval.c:898
int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *)
Definition: class.c:1904
VALUE rb_mKernel
Kernel module.
Definition: ruby.h:2000
void rb_p(VALUE obj)
Definition: io.c:7802
VALUE rb_cFile
Definition: file.c:159
VALUE rb_cObject
Object class.
Definition: ruby.h:2012
VALUE rb_eEOFError
Definition: io.c:172
VALUE rb_eIOError
Definition: io.c:173
VALUE rb_mWaitWritable
Definition: io.c:175
VALUE rb_mWaitReadable
Definition: io.c:174
VALUE rb_mEnumerable
Definition: enum.c:20
VALUE rb_cIO
Definition: io.c:171
VALUE rb_stdin
Definition: io.c:184
void rb_notimplement(void)
Definition: error.c:2714
void rb_syserr_fail(int e, const char *mesg)
Definition: error.c:2783
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2671
void rb_mod_sys_fail_str(VALUE mod, VALUE mesg)
Definition: error.c:2843
void rb_enc_warn(rb_encoding *enc, const char *fmt,...)
Definition: error.c:325
VALUE rb_rescue2(VALUE(*)(VALUE), VALUE, VALUE(*)(VALUE, VALUE), VALUE,...)
An equivalent of rescue clause.
Definition: eval.c:962
VALUE rb_eNotImpError
Definition: error.c:934
void rb_exc_raise(VALUE mesg)
Raises an exception in the current thread.
Definition: eval.c:668
void rb_bug(const char *fmt,...)
Definition: error.c:636
VALUE rb_eStandardError
Definition: error.c:921
void rb_syserr_fail_str(int e, VALUE mesg)
Definition: error.c:2789
void rb_sys_fail_str(VALUE mesg)
Definition: error.c:2801
VALUE rb_eTypeError
Definition: error.c:924
void rb_fatal(const char *fmt,...)
Definition: error.c:2722
VALUE rb_protect(VALUE(*)(VALUE), VALUE, int *)
Protects a function call from potential global escapes from the function.
Definition: eval.c:1072
VALUE rb_eRuntimeError
Definition: error.c:922
void rb_warn(const char *fmt,...)
Definition: error.c:315
VALUE rb_eArgError
Definition: error.c:925
VALUE rb_eEAGAIN
Definition: error.c:54
VALUE rb_ensure(VALUE(*)(VALUE), VALUE, VALUE(*)(VALUE), VALUE)
An equivalent to ensure clause.
Definition: eval.c:1115
VALUE rb_eEINPROGRESS
Definition: error.c:56
void rb_jump_tag(int tag)
Continues the exception caught by rb_protect() and rb_eval_string_protect().
Definition: eval.c:884
int rb_str_end_with_asciichar(VALUE str, int c)
Definition: io.c:7689
void rb_sys_fail(const char *mesg)
Definition: error.c:2795
VALUE rb_eEWOULDBLOCK
Definition: error.c:55
VALUE rb_eSystemCallError
Definition: error.c:943
VALUE rb_check_to_int(VALUE)
Tries to convert val into Integer.
Definition: object.c:3036
VALUE rb_any_to_s(VALUE)
Default implementation of #to_s.
Definition: object.c:527
VALUE rb_obj_alloc(VALUE)
Allocates an instance of klass.
Definition: object.c:1895
VALUE rb_class_new_instance(int, const VALUE *, VALUE)
Allocates and initializes an instance of klass.
Definition: object.c:1955
VALUE rb_class_new_instance_kw(int, const VALUE *, VALUE, int)
Definition: object.c:1931
int rb_bool_expected(VALUE, const char *)
Definition: object.c:3112
VALUE rb_obj_class(VALUE)
Equivalent to Object#class in Ruby.
Definition: object.c:217
VALUE rb_obj_dup(VALUE)
Equivalent to Object#dup in Ruby.
Definition: object.c:420
VALUE rb_inspect(VALUE)
Convenient wrapper of Object::inspect.
Definition: object.c:551
VALUE rb_convert_type_with_id(VALUE, int, const char *, ID)
Definition: object.c:2914
VALUE rb_obj_freeze(VALUE)
Make the object unmodifiable.
Definition: object.c:1080
VALUE rb_check_to_integer(VALUE, const char *)
Tries to convert val into Integer.
Definition: object.c:2999
VALUE rb_check_convert_type_with_id(VALUE, int, const char *, ID)
Definition: object.c:2957
VALUE rb_to_int(VALUE)
Converts val into Integer.
Definition: object.c:3021
const char term
Definition: id.c:37
#define rb_io_fptr_finalize(fptr)
Definition: io.c:4761
VALUE rb_io_gets(VALUE io)
Definition: io.c:3577
#define io_tell(fptr)
Definition: io.c:862
int rb_io_wait_writable(int f)
Definition: io.c:1228
#define io_seek(fptr, ofs, whence)
Definition: io.c:861
#define rb_io_ioctl
Definition: io.c:9887
int rb_io_modestr_fmode(const char *modestr)
Definition: io.c:5469
VALUE rb_io_taint_check(VALUE io)
Definition: io.c:703
VALUE rb_get_argv(void)
Definition: io.c:12904
#define SEEK_SET
Definition: io.c:865
#define shutdown(a, b)
Definition: io.c:667
#define rb_io_pwrite
Definition: io.c:5334
#define do_write_retry(code)
Definition: io.c:1039
int rb_cloexec_pipe(int fildes[2])
Definition: io.c:378
VALUE rb_rs
Definition: io.c:188
VALUE rb_io_get_io(VALUE io)
Definition: io.c:733
VALUE rb_io_addstr(VALUE io, VALUE str)
Definition: io.c:1843
void rb_io_fptr_finalize_internal(void *ptr)
Definition: io.c:4734
void rb_io_read_check(rb_io_t *fptr)
Definition: io.c:944
int rb_io_modestr_oflags(const char *modestr)
Definition: io.c:5599
VALUE rb_io_fdopen(int fd, int oflags, const char *path)
Definition: io.c:8008
#define rb_io_fcntl
Definition: io.c:9981
#define IO_CBUF_CAPA_MIN
Definition: io.c:150
#define NEXT_ARGF_FORWARD(argc, argv)
Definition: io.c:8592
VALUE rb_io_ungetbyte(VALUE io, VALUE b)
Definition: io.c:4280
VALUE rb_io_gets_internal(VALUE io)
Definition: io.c:3583
int rb_io_wait_readable(int f)
Definition: io.c:1204
VALUE rb_io_getbyte(VALUE io)
Definition: io.c:4219
#define SET_BINARY_MODE_WITH_SEEK_CUR(fptr)
Definition: io.c:663
void ruby_set_inplace_mode(const char *suffix)
Definition: io.c:12872
#define NUM2IOCTLREQ(num)
Definition: io.c:9578
int rb_cloexec_dup2(int oldfd, int newfd)
Definition: io.c:325
void rb_readwrite_syserr_fail(enum rb_io_wait_readwrite writable, int n, const char *mesg)
Definition: io.c:12944
void rb_write_error_str(VALUE mesg)
Definition: io.c:7940
#define READ_DATA_PENDING(fptr)
Definition: io.c:466
void rb_io_check_byte_readable(rb_io_t *fptr)
Definition: io.c:890
rb_io_t * rb_io_make_open_file(VALUE obj)
Definition: io.c:8084
#define rb_f_syscall
Definition: io.c:10111
#define READ_DATA_PENDING_COUNT(fptr)
Definition: io.c:467
#define argf_of(obj)
Definition: io.c:461
void rb_io_check_readable(rb_io_t *fptr)
Definition: io.c:899
#define EWOULDBLOCK
Definition: io.c:141
#define IO_WBUF_CAPA_MIN
Definition: io.c:152
#define SEEK_CUR
Definition: io.c:866
#define rb_io_close_on_exec_p
Definition: io.c:4425
#define O_ACCMODE
Definition: io.c:125
#define ARGF_GENERIC_INPUT_P()
Definition: io.c:8586
int rb_io_extract_encoding_option(VALUE opt, rb_encoding **enc_p, rb_encoding **enc2_p, int *fmode_p)
Definition: io.c:5748
void rb_maygvl_fd_fix_cloexec(int fd)
Definition: io.c:245
#define READ_CHAR_PENDING_PTR(fptr)
Definition: io.c:473
#define IOWAIT_SYSCALL
Definition: io.c:10829
#define MAX_REALLOC_GAP
Definition: io.c:2694
#define NEED_WRITECONV(fptr)
Definition: io.c:655
int rb_io_oflags_fmode(int oflags)
Definition: io.c:5523
#define MODE_BTMODE(a, b, c)
Definition: io.c:1459
void Init_IO_nonblock(void)
Definition: io.c:13525
#define no_exception_p(opts)
Definition: io.c:2803
#define RUBY_PIPE_NONBLOCK_DEFAULT
Definition: io.c:168
void rb_update_max_fd(int fd)
Definition: io.c:218
FILE * rb_fdopen(int fd, const char *modestr)
Definition: io.c:6057
int rb_gc_for_fd(int err)
Definition: io.c:953
VALUE rb_io_write(VALUE io, VALUE str)
Definition: io.c:1804
#define NEED_NEWLINE_DECORATOR_ON_WRITE(fptr)
Definition: io.c:507
#define READ_CHECK(fptr)
Definition: io.c:482
#define next_argv()
Definition: io.c:8585
VALUE rb_io_puts(int argc, const VALUE *argv, VALUE out)
Definition: io.c:7751
@ bom_prefix_len
Definition: io.c:5459
int rb_cloexec_open(const char *pathname, int flags, mode_t mode)
Definition: io.c:292
#define KEEPGVL
Definition: io.c:4779
FILE * rb_io_stdio_file(rb_io_t *fptr)
Definition: io.c:8036
VALUE rb_stderr
Definition: io.c:184
void rb_readwrite_sys_fail(enum rb_io_wait_readwrite writable, const char *mesg)
Definition: io.c:12938
VALUE rb_output_rs
Definition: io.c:189
#define PREP_STDIO_NAME(f)
Definition: io.c:4488
#define NOFILE
Definition: io.c:97
#define DEFULT_IOCTL_NARG_LEN
Definition: io.c:9612
VALUE rb_io_eof(VALUE io)
Definition: io.c:2149
void rb_stdio_set_default_encoding(void)
Definition: io.c:11769
#define GetWriteIO(io)
Definition: io.c:464
#define NEED_NEWLINE_DECORATOR_ON_READ(fptr)
Definition: io.c:506
struct rb_io_enc_t convconfig_t
Definition: io.c:5816
#define FMODE_PREP
Definition: io.c:4486
#define fmode
#define ARGF_FORWARD(argc, argv)
Definition: io.c:8588
#define READ_DATA_PENDING_PTR(fptr)
Definition: io.c:468
#define NEED_READCONV(fptr)
Definition: io.c:654
#define FOREACH_ARGF()
Definition: io.c:12400
#define is_socket(fd, path)
Definition: io.c:673
void rb_io_extract_modeenc(VALUE *vmode_p, VALUE *vperm_p, VALUE opthash, int *oflags_p, int *fmode_p, convconfig_t *convconfig_p)
Definition: io.c:5875
#define rb_intern(str)
#define READ_CHAR_PENDING(fptr)
Definition: io.c:471
void rb_fd_fix_cloexec(int fd)
Definition: io.c:268
VALUE rb_io_flush(VALUE io)
Definition: io.c:1903
#define READ_CHAR_PENDING_COUNT(fptr)
Definition: io.c:472
void rb_io_check_initialized(rb_io_t *fptr)
Definition: io.c:710
#define rb_io_fsync
Definition: io.c:2252
VALUE rb_io_ascii8bit_binmode(VALUE io)
Definition: io.c:5384
VALUE rb_io_binmode(VALUE io)
Definition: io.c:5338
#define DEFAULT_TEXTMODE
Definition: io.c:653
VALUE rb_io_check_io(VALUE io)
Definition: io.c:739
VALUE rb_io_printf(int argc, const VALUE *argv, VALUE out)
Definition: io.c:7509
VALUE rb_io_ungetc(VALUE io, VALUE c)
Definition: io.c:4319
#define IO_RBUF_CAPA_FOR(fptr)
Definition: io.c:151
#define rb_io_sync
Definition: io.c:2253
#define MORE_CHAR_SUSPENDED
Definition: io.c:2559
int rb_pipe(int *pipes)
Definition: io.c:6373
@ utf_prefix_len
Definition: io.c:5460
#define NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr)
Definition: io.c:661
void rb_io_unbuffered(rb_io_t *fptr)
Definition: io.c:6367
#define S_ISREG(m)
Definition: io.c:992
int rb_notify_fd_close(int fd, struct list_head *)
Definition: thread.c:2363
int rb_stderr_tty_p(void)
Definition: io.c:7962
VALUE rb_gets(void)
Definition: io.c:8906
ssize_t rb_io_bufwrite(VALUE io, const void *buf, size_t size)
Definition: io.c:1549
VALUE rb_io_flush_raw(VALUE io, int sync)
Definition: io.c:1864
int rb_cloexec_fcntl_dupfd(int fd, int minfd)
Definition: io.c:419
VALUE rb_output_fs
Definition: io.c:187
#define MODE_BINARY(a, b)
#define MODE_BTXMODE(a, b, c, d, e, f)
Definition: io.c:1462
void rb_io_check_char_readable(rb_io_t *fptr)
Definition: io.c:871
#define READ_DATA_BUFFERED(fptr)
Definition: io.c:469
#define SET_BINARY_MODE(fptr)
Definition: io.c:660
#define ARGF_block_call(mid, argc, argv, func, argf)
Definition: io.c:12413
int rb_io_read_pending(rb_io_t *fptr)
Definition: io.c:935
VALUE rb_io_get_write_io(VALUE io)
Definition: io.c:745
#define SEEK_END
Definition: io.c:867
void rb_io_set_nonblock(rb_io_t *fptr)
Definition: io.c:2782
RUBY_FUNC_EXPORTED size_t rb_io_memsize(const rb_io_t *fptr)
Definition: io.c:4764
#define MORE_CHAR_FINISHED
Definition: io.c:2560
#define rb_io_set_close_on_exec
Definition: io.c:4483
VALUE rb_file_open(const char *fname, const char *modestr)
Definition: io.c:6263
#define SHUT_WR
int rb_cloexec_dup(int oldfd)
Definition: io.c:318
VALUE rb_io_set_write_io(VALUE io, VALUE w)
Definition: io.c:756
#define off_t
Definition: io.c:83
VALUE rb_file_open_str(VALUE fname, const char *modestr)
Definition: io.c:6256
void rb_write_error(const char *mesg)
Definition: io.c:7934
void rb_io_check_writable(rb_io_t *fptr)
Definition: io.c:923
#define rb_io_fdatasync
Definition: io.c:2304
#define IS_PREP_STDIO(f)
Definition: io.c:4487
#define SET_UNIVERSAL_NEWLINE_DECORATOR_IF_ENC2(enc2, ecflags)
Definition: io.c:662
char * rb_execarg_commandline(const struct rb_execarg *eargp, VALUE *prog)
Definition: process.c:4352
VALUE rb_io_print(int argc, const VALUE *argv, VALUE out)
Definition: io.c:7580
#define rb_io_pread
Definition: io.c:5274
int ioctl_req_t
Definition: io.c:9577
VALUE rb_stdout
Definition: io.c:184
void rb_io_check_closed(rb_io_t *fptr)
Definition: io.c:718
#define SHUT_RD
void rb_eof_error(void)
Definition: io.c:697
void rb_write_error2(const char *mesg, long len)
Definition: io.c:7915
void rb_io_synchronized(rb_io_t *fptr)
Definition: io.c:6360
void Init_IO(void)
Definition: io.c:13155
#define ARGF
Definition: io.c:462
VALUE rb_io_close(VALUE io)
Definition: io.c:4824
#define free(x)
Definition: io.c:47
VALUE rb_default_rs
Definition: io.c:190
#define FMODE_READABLE
Definition: io.h:108
#define FMODE_SETENC_BY_BOM
Definition: io.h:122
#define FMODE_READWRITE
Definition: io.h:110
#define RB_WAITFD_OUT
Definition: io.h:53
#define FMODE_TTY
Definition: io.h:113
#define FMODE_CREATE
Definition: io.h:116
struct rb_io_t rb_io_t
int rb_wait_for_single_fd(int fd, int events, struct timeval *tv)
Definition: thread.c:4275
struct rb_io_enc_t rb_io_enc_t
Definition: io.h:104
#define FMODE_WRITABLE
Definition: io.h:109
#define FMODE_APPEND
Definition: io.h:115
#define FMODE_DUPLEX
Definition: io.h:114
#define FMODE_BINMODE
Definition: io.h:111
#define MakeOpenFile(obj, fp)
Definition: io.h:129
#define RB_WAITFD_IN
Definition: io.h:51
#define FMODE_SYNC
Definition: io.h:112
#define GetOpenFile(obj, fp)
Definition: io.h:127
#define FMODE_EXCL
Definition: io.h:118
#define FMODE_TEXTMODE
Definition: io.h:120
#define FMODE_TRUNC
Definition: io.h:119
struct rb_io_buffer_t rb_io_buffer_t
Definition: io.h:64
const char * name
Definition: nkf.c:208
unsigned int last
Definition: nkf.c:4324
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:4322
#define ONIGENC_CONSTRUCT_MBCLEN_CHARFOUND(n)
Definition: onigmo.h:345
#define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)
VALUE rb_class_name(VALUE)
Definition: variable.c:274
#define RARRAY_LEN(a)
int pipe2(int __fildes[2], int flags)
#define OFFT2NUM(v)
VALUE rb_str_unlocktmp(VALUE)
Definition: string.c:2675
#define SafeStringValue(v)
void * memchr(const void *, int, size_t)
#define rb_str_new2
VALUE rb_hash_lookup(VALUE, VALUE)
Definition: hash.c:2063
struct rb_execarg * rb_execarg_get(VALUE execarg_obj)
Definition: process.c:2636
__off_t off_t
int fsync(int __fd)
__int8_t int8_t
#define NULL
#define FL_SINGLETON
#define rb_funcallv(recv, mid, argc, argv)
int memcmp(const void *, const void *, size_t)
Definition: memcmp.c:7
#define dp(v)
int rb_thread_interrupted(VALUE thval)
Definition: thread.c:1378
VALUE rb_str_resize(VALUE, long)
Definition: string.c:2709
#define T_FILE
#define stdout
VALUE rb_str_locktmp_ensure(VALUE str, VALUE(*func)(VALUE), VALUE arg)
Definition: string.c:2685
use StringValue() instead")))
#define RSTRING_LEN(str)
#define ESPIPE
#define _(args)
#define NEWOBJ_OF(obj, type, klass, flags)
#define RTEST(v)
void rb_define_virtual_variable(const char *, rb_gvar_getter_t *, rb_gvar_setter_t *)
Definition: variable.c:511
#define ALLOCV_END(v)
#define OBJ_INIT_COPY(obj, orig)
int dup3(int __fildes, int __fildes2, int flags)
void rb_set_class_path(VALUE, VALUE, const char *)
Definition: variable.c:218
#define FL_TEST(x, f)
enum ruby_tag_type st
#define rb_syserr_fail_path(err, path)
VALUE rb_int_modulo(VALUE x, VALUE y)
Definition: numeric.c:3891
void rb_mutex_allow_trap(VALUE self, int val)
Definition: thread_sync.c:545
#define PRI_OFFT_PREFIX
size_t strlen(const char *)
int strcmp(const char *, const char *)
size_t fwrite(const void *__restrict__, size_t _size, size_t _n, FILE *)
#define T_STRING
VALUE rb_assoc_new(VALUE, VALUE)
Definition: array.c:896
VALUE rb_mutex_new(void)
Definition: thread_sync.c:165
VALUE rb_to_array_type(VALUE obj)
Definition: array.c:902
#define IOV_MAX
VALUE rb_hash_aref(VALUE, VALUE)
Definition: hash.c:2037
#define PIDT2NUM(v)
VALUE rb_str_encode_ospath(VALUE)
Definition: file.c:236
int fstat(int __fd, struct stat *__sbuf)
#define RARRAY_LENINT(ary)
#define S_IFSOCK
int close(int __fildes)
#define EINVAL
void rb_define_global_function(const char *, VALUE(*)(), int)
#define SSIZE_MAX
ssize_t pread(int __fd, void *__buf, size_t __nbytes, off_t __offset)
#define LONG2FIX(i)
#define Qundef
uid_t getuid(void)
Definition: win32.c:2795
#define rb_str_cat2
#define rb_sys_fail_path(path)
#define EXDEV
void rb_execarg_parent_end(VALUE execarg_obj)
Definition: process.c:2883
void rb_warn_deprecated(const char *fmt, const char *suggest,...) __attribute__((format(printf
VALUE rb_enumeratorize(VALUE, VALUE, int, const VALUE *)
Definition: enumerator.c:516
#define RSTRING_END(str)
VALUE rb_mutex_owned_p(VALUE self)
Definition: thread_sync.c:345
const VALUE VALUE obj
#define rb_check_frozen(obj)
void rb_thread_wait_fd(int)
Definition: thread.c:4041
#define TYPE(x)
#define UINT2NUM(x)
#define T_NIL
#define UNREACHABLE
int fileno(FILE *)
VALUE rb_funcallv_kw(VALUE, ID, int, const VALUE *, int)
Definition: vm_eval.c:962
#define SSIZET2NUM(v)
int rb_thread_fd_select(int, rb_fdset_t *, rb_fdset_t *, rb_fdset_t *, struct timeval *)
Definition: thread.c:4066
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)
#define RSTRING_PTR(str)
void rb_gc_register_mark_object(VALUE)
Definition: gc.c:7079
const rb_iseq_t const char * error
char * strerror(int)
Definition: strerror.c:11
#define T_BIGNUM
#define RUBY_UBF_IO
#define ENOSYS
#define EINTR
#define rb_str_new(str, len)
#define NIL_P(v)
#define rb_str_buf_cat
void rb_fd_init(rb_fdset_t *)
__intptr_t intptr_t
VALUE rb_check_funcall(VALUE, ID, int, const VALUE *)
Definition: vm_eval.c:505
#define numberof(array)
#define NUM2CHR(x)
VALUE rb_str_cat(VALUE, const char *, long)
Definition: string.c:2812
#define ID2SYM(x)
char * strrchr(const char *, int)
Definition: strchr.c:20
int rename(const char *, const char *)
int rb_thread_to_be_killed(VALUE thread)
Definition: thread.c:2471
#define LONG_MAX
#define T_FIXNUM
#define RUBY_TYPED_DEFAULT_FREE
#define ENFILE
const char size_t n
#define rb_usascii_str_new(str, len)
#define ruby_verbose
#define MEMZERO(p, type, n)
int pipe(int __fildes[2])
#define rb_intern_const(str)
void rb_define_variable(const char *, VALUE *)
Definition: variable.c:499
int fchown(int __fildes, uid_t __owner, gid_t __group)
void rb_define_global_const(const char *, VALUE)
Definition: variable.c:2903
void rb_str_set_len(VALUE, long)
Definition: string.c:2692
int rb_respond_to(VALUE, ID)
Definition: vm_method.c:2207
const char const char *typedef unsigned long VALUE
VALUE rb_ary_push(VALUE, VALUE)
Definition: array.c:1195
#define stderr
int rb_obj_method_arity(VALUE, ID)
Definition: proc.c:2652
#define rb_ary_new4
VALUE rb_str_substr(VALUE, long, long)
Definition: string.c:2584
__inline__ const void *__restrict__ src
void rb_str_modify(VALUE)
Definition: string.c:2114
int fclose(FILE *)
#define EMFILE
VALUE rb_ary_concat(VALUE, VALUE)
Definition: array.c:4069
VALUE rb_hash_lookup2(VALUE, VALUE, VALUE)
Definition: hash.c:2050
VALUE rb_str_buf_new(long)
Definition: string.c:1315
VALUE rb_check_string_type(VALUE)
Definition: string.c:2314
#define FilePathValue(v)
() void(cc->call !=vm_call_general)
VALUE rb_mutex_synchronize(VALUE mutex, VALUE(*func)(VALUE arg), VALUE arg)
Definition: thread_sync.c:522
pid_t rb_fork_ruby(int *status)
#define ENOMEM
int fchmod(int __fd, mode_t __mode)
#define ARGVSTR2ARGV(argv_str)
#define rp(obj)
void rb_last_status_clear(void)
Definition: process.c:582
#define EINPROGRESS
const VALUE *pid_t rb_waitpid(pid_t pid, int *status, int flags)
VALUE rb_hash_dup(VALUE)
Definition: hash.c:1564
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
uint32_t i
void rb_execarg_setenv(VALUE execarg_obj, VALUE env)
Definition: process.c:2674
#define rb_fstring_lit(str)
#define char
#define NUM2OFFT(v)
#define BUFSIZ
#define NUM2UINT(x)
#define RSTRING_GETMEM(str, ptrvar, lenvar)
__inline__ const void *__restrict__ size_t len
VALUE rb_uninterruptible(VALUE(*b_proc)(VALUE), VALUE data)
Definition: thread.c:5553
#define S_ISSOCK(m)
VALUE rb_str_tmp_frozen_acquire(VALUE str)
Definition: string.c:1210
VALUE rb_execarg_extract_options(VALUE execarg_obj, VALUE opthash)
Definition: process.c:2307
#define ALLOC_N(type, n)
void rb_gc(void)
Definition: gc.c:8695
#define OBJ_FREEZE(x)
#define INT2NUM(x)
int dup2(int __fildes, int __fildes2)
Definition: dup2.c:27
#define STATIC_ASSERT(name, expr)
#define ZALLOC(type)
int unlink(const char *__path)
rb_gvar_setter_t rb_str_setter
int rb_exec_async_signal_safe(const struct rb_execarg *e, char *errmsg, size_t errmsg_buflen)
Definition: process.c:3551
unsigned int rb_atomic_t
void rb_define_const(VALUE, const char *, VALUE)
Definition: variable.c:2891
#define _IONBF
#define long
#define NUM2INT(x)
void rb_define_singleton_method(VALUE, const char *, VALUE(*)(), int)
#define RB_SCAN_ARGS_LAST_HASH_KEYWORDS
#define RB_GC_GUARD(v)
#define RUBY_TYPED_FREE_IMMEDIATELY
void rb_gvar_readonly_setter(VALUE v, ID id, VALUE *_)
Definition: variable.c:412
#define PRIsVALUE
void * memset(void *, int, size_t)
void rb_close_before_exec(int lowfd, int maxhint, VALUE noclose_fds)
void _exit(int __status) __attribute__((__noreturn__))
#define ENOTSUP
int pclose(FILE *)
#define rb_funcall(recv, mid, argc,...)
int VALUE v
#define rb_method_basic_definition_p(klass, mid)
VALUE rb_ary_new(void)
Definition: array.c:723
void rb_last_status_set(int status, pid_t pid)
ID rb_id_encoding(void)
Definition: encoding.c:759
#define rb_scan_args(argc, argvp, fmt,...)
#define list_empty(h)
#define rb_exc_new3
#define RB_PASS_CALLED_KEYWORDS
int rb_reserved_fd_p(int fd)
int int int int int int int int char char int int int int int int int int int char char int int int int int int int int FILE * fdopen(int, const char *)
void rb_str_tmp_frozen_release(VALUE str, VALUE tmp)
Definition: string.c:1217
unsigned long ruby_strtoul(const char *str, char **endptr, int base)
Definition: util.c:130
void rb_thread_check_ints(void)
Definition: thread.c:1361
void rb_gc_mark(VALUE)
Definition: gc.c:5228
VALUE rb_yield_values2(int n, const VALUE *argv)
Definition: vm_eval.c:1271
void rb_define_readonly_variable(const char *, const VALUE *)
Definition: variable.c:505
#define INT_MAX
int chmod(const char *__path, mode_t __mode)
#define rb_pid_t
#define ALLOCV_N(type, v, n)
VALUE rb_str_catf(VALUE, const char *,...) __attribute__((format(printf
int isatty(int __fildes)
VALUE rb_execarg_new(int argc, const VALUE *argv, int accept_shell, int allow_exc_opt)
Definition: process.c:2661
char * strchr(const char *, int)
Definition: strchr.c:8
#define CONST_ID(var, str)
void rb_execarg_parent_start(VALUE execarg_obj)
Definition: process.c:2844
void rb_fd_set(int, rb_fdset_t *)
int rb_fd_isset(int, const rb_fdset_t *)
struct timeval rb_time_interval(VALUE num)
Definition: time.c:2683
#define NUM2MODET(v)
#define NUM2SIZET(x)
#define TRUE
#define FALSE
int rb_execarg_addopt(VALUE execarg_obj, VALUE key, VALUE val)
Definition: process.c:2041
unsigned int size
#define stdin
#define Qtrue
#define MEMMOVE(p1, p2, type, n)
#define ruby_sized_xfree(ptr, size)
long unsigned int size_t
#define FIX2UINT(x)
VALUE rb_str_chomp_string(VALUE str, VALUE chomp)
Definition: string.c:8921
int dup(int __fildes)
const struct rb_call_cache * cc
#define memmove(dst, src, len)
VALUE rb_f_sprintf(int, const VALUE *)
Definition: sprintf.c:198
VALUE rb_str_append(VALUE, VALUE)
Definition: string.c:2965
#define S_IFMT
VALUE rb_str_buf_cat_ascii(VALUE, const char *)
Definition: string.c:2926
int rb_execarg_run_options(const struct rb_execarg *e, struct rb_execarg *s, char *errmsg, size_t errmsg_buflen)
Definition: process.c:3420
VALUE rb_str_new_frozen(VALUE)
Definition: string.c:1203
VALUE rb_attr_get(VALUE, ID)
Definition: variable.c:1084
int rb_thread_fd_writable(int)
Definition: thread.c:4047
int setvbuf(FILE *__restrict__, char *__restrict__, int, size_t)
#define Qnil
#define Qfalse
#define T_ARRAY
void rb_str_modify_expand(VALUE, long)
Definition: string.c:2122
void * memcpy(void *__restrict__, const void *__restrict__, size_t)
void rb_thread_atfork(void)
Definition: thread.c:4547
VALUE rb_lastline_get(void)
Definition: vm.c:1316
#define SIGNED_VALUE
VALUE rb_check_hash_type(VALUE)
Definition: hash.c:1852
VALUE rb_thread_current(void)
Definition: thread.c:2675
FILE * freopen(const char *__restrict__, const char *__restrict__, FILE *__restrict__)
#define RB_TYPE_P(obj, type)
void sync(void)
#define EBADF
#define INT2FIX(i)
VALUE rb_check_array_type(VALUE)
Definition: array.c:909
#define RB_IO_WAIT_WRITABLE
VALUE rb_str_locktmp(VALUE)
int fdatasync(int __fd)
#define ALLOC(type)
void rb_gc_force_recycle(VALUE)
Definition: gc.c:7027
#define RFILE(obj)
void rb_define_hooked_variable(const char *, VALUE *, rb_gvar_getter_t *, rb_gvar_setter_t *)
Definition: variable.c:480
#define _IOLBF
void rb_fd_term(rb_fdset_t *)
VALUE rb_obj_as_string(VALUE)
Definition: string.c:1440
#define TypedData_Make_Struct(klass, type, data_type, sval)
const VALUE * argv
VALUE rb_fix_plus(VALUE x, VALUE y)
Definition: numeric.c:3609
#define SYMBOL_P(x)
FILE * popen(const char *, const char *)
_ssize_t ssize_t
__inline__ int
VALUE rb_ary_shift(VALUE)
Definition: array.c:1294
VALUE rb_ivar_set(VALUE, ID, VALUE)
Definition: variable.c:1300
#define FIXNUM_P(f)
#define CLASS_OF(v)
void rb_thread_fd_close(int)
Definition: thread.c:2385
void rb_thread_sleep(int)
Definition: thread.c:1384
#define RETURN_ENUMERATOR(obj, argc, argv)
void rb_thread_schedule(void)
Definition: thread.c:1407
if((__builtin_expect(!!(!me), 0)))
#define Check_Type(v, t)
#define RB_INTEGER_TYPE_P(obj)
VALUE rb_hash_aset(VALUE, VALUE, VALUE)
Definition: hash.c:2852
#define rb_check_arity
#define rb_funcall3
void rb_lastline_set(VALUE)
Definition: vm.c:1322
#define RB_IO_WAIT_READABLE
#define EPERM
int atexit(void(*__func)(void))
VALUE rb_str_dup(VALUE)
Definition: string.c:1516
VALUE rb_sprintf(const char *,...) __attribute__((format(printf
VALUE rb_exec_recursive(VALUE(*)(VALUE, VALUE, int), VALUE, VALUE)
Definition: thread.c:5074
unsigned long ID
int rb_fd_select(int, rb_fdset_t *, rb_fdset_t *, rb_fdset_t *, struct timeval *)
int chown(const char *__path, uid_t __owner, gid_t __group)
VALUE rb_yield(VALUE)
Definition: vm_eval.c:1237
const char *void rb_warning(const char *,...) __attribute__((format(printf
#define rb_fstring_cstr(str)
#define RUBY_FUNC_EXPORTED
#define FIX2LONG(x)
const rb_iseq_t const VALUE exc
__mode_t mode_t
#define ATOMIC_CAS(var, oldval, newval)
#define RBASIC_SET_CLASS(obj, cls)
void rb_thread_execute_interrupts(VALUE th)
Definition: thread.c:2283
#define NUM2LONG(x)
void rb_define_method(VALUE, const char *, VALUE(*)(), int)
#define rb_ary_new2
void Init_File(void)
Definition: file.c:6496
#define RARRAY_AREF(a, i)
#define EAGAIN
VALUE rb_hash_new(void)
Definition: hash.c:1523
#define VM_UNREACHABLE(func)
ssize_t pwrite(int __fd, const void *__buf, size_t __nbytes, off_t __offset)
#define rb_str_new_cstr(str)
#define RARRAY_CONST_PTR(a)
VALUE rb_thread_io_blocking_region(rb_blocking_function_t *func, void *data1, int fd)
Definition: thread.c:1594
#define rb_str_new4
#define _IOFBF
_ssize_t write(int __fd, const void *__buf, size_t __nbyte)
#define ISASCII(c)
off_t lseek(int __fildes, off_t __offset, int __whence)
#define WNOHANG
VALUE rb_ary_entry(VALUE, long)
Definition: array.c:1512
_ssize_t read(int __fd, void *__buf, size_t __nbyte)
#define StringValueCStr(v)
#define STRNCASECMP(s1, s2, n)
unsigned long VALUE
Definition: ruby.h:102
rb_atomic_t cnt[RUBY_NSIG]
Definition: signal.c:503
#define f
size_t rb_str_capacity(VALUE str)
Definition: string.c:712
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:943
Definition: ruby.h:1134
VALUE argf
Definition: io.c:12136
VALUE * argv
Definition: io.c:12135
int argc
Definition: io.c:12134
Definition: io.c:206
long last_lineno
Definition: io.c:208
struct rb_io_enc_t encs
Definition: io.c:212
VALUE inplace
Definition: io.c:211
int8_t next_p
Definition: io.c:213
VALUE filename
Definition: io.c:207
long lineno
Definition: io.c:209
VALUE current_file
Definition: io.c:207
int8_t init_p
Definition: io.c:213
int8_t binmode
Definition: io.c:213
VALUE argv
Definition: io.c:210
const char * ptr
Definition: io.c:1319
long length
Definition: io.c:1320
VALUE str
Definition: io.c:1318
rb_io_t * fptr
Definition: io.c:1317
rb_io_t * fptr
Definition: io.c:2469
long len
Definition: io.c:2468
char * str_ptr
Definition: io.c:2467
unsigned close_src
Definition: io.c:10768
off_t copy_length
Definition: io.c:10763
struct stat src_stat
Definition: io.c:10775
unsigned close_dst
Definition: io.c:10769
const char * syserr
Definition: io.c:10772
const char * notimp
Definition: io.c:10773
struct stat dst_stat
Definition: io.c:10776
off_t src_offset
Definition: io.c:10764
rb_io_t * fptr
Definition: io.c:4554
VALUE io
Definition: io.c:10361
VALUE * argv
Definition: io.c:10360
int argc
Definition: io.c:10359
unsigned int chomp
Definition: stringio.c:1152
VALUE rs
Definition: stringio.c:1150
long limit
Definition: stringio.c:1151
VALUE io
Definition: io.c:3353
rb_io_t * fptr
Definition: io.c:10192
const void * buf
Definition: io.c:1004
Definition: win32.h:225
void * iov_base
Definition: win32.h:226
size_t iov_len
Definition: win32.h:227
struct rb_execarg::@34::@36 cmd
union rb_execarg::@34 invoke
struct rb_execarg::@34::@35 sh
int argc
Definition: io.c:7817
VALUE * argv
Definition: io.c:7818
rb_encoding * enc
Definition: io.h:86
rb_encoding * enc2
Definition: io.h:87
VALUE ecopts
Definition: io.h:89
Definition: io.h:66
int fd
Definition: io.h:68
struct rb_io_t::rb_io_enc_t encs
int lineno
Definition: io.h:71
rb_econv_t * writeconv
Definition: io.h:95
rb_pid_t pid
Definition: io.h:70
rb_io_buffer_t wbuf
Definition: io.h:75
rb_econv_t * readconv
Definition: io.h:92
VALUE writeconv_asciicompat
Definition: io.h:96
FILE * stdio_file
Definition: io.h:67
int writeconv_initialized
Definition: io.h:97
VALUE pathv
Definition: io.h:72
int mode
Definition: io.h:69
int writeconv_pre_ecflags
Definition: io.h:98
VALUE write_lock
Definition: io.h:101
rb_io_buffer_t cbuf
Definition: io.h:93
VALUE writeconv_pre_ecopts
Definition: io.h:99
VALUE tied_io_for_writing
Definition: io.h:77
void(* finalize)(struct rb_io_t *, int)
Definition: io.h:73
rb_io_buffer_t rbuf
Definition: io.h:75
Definition: io.c:10510
VALUE io
Definition: io.c:10511
int mode
Definition: io.c:10513
VALUE offset
Definition: io.c:10512
rb_fdset_t fdsets[4]
Definition: io.c:9214
struct timeval * timeout
Definition: io.c:9213
VALUE write
Definition: io.c:9212
VALUE read
Definition: io.c:9212
VALUE except
Definition: io.c:9212
mode_t perm
Definition: io.c:6011
int oflags
Definition: io.c:6010
VALUE fname
Definition: io.c:6009
Definition: io.c:1323
VALUE str
Definition: io.c:1325
int nosync
Definition: io.c:1326
VALUE io
Definition: io.c:1324
RUBY_SYMBOL_EXPORT_BEGIN void * rb_thread_call_with_gvl(void *(*func)(void *), void *data1)
Definition: thread.c:1661
void * rb_thread_call_without_gvl2(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2)
Definition: thread.c:1580
void * rb_thread_call_without_gvl(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2)
size_t rb_econv_memsize(rb_econv_t *ec)
Definition: transcode.c:1703
void rb_iter_break_value(VALUE val)
Definition: vm.c:1552
#define rb_id2str(id)
Definition: vm_backtrace.c:30
MJIT_STATIC void rb_error_arity(int argc, int min, int max)
#define ioctl_arg
Definition: wait.c:32
int rb_freopen(VALUE fname, const char *mode, FILE *file)
Definition: file.c:693
#define env
long rb_w32_write_console(uintptr_t, int)
Definition: win32.c:7265
SOCKET rb_w32_get_osfhandle(int)
Definition: win32.c:1108
char rb_w32_fd_is_text(int)
Definition: win32.c:7796
#define O_NONBLOCK
Definition: win32.h:611
#define FD_CLOEXEC
Definition: win32.h:610
int fcntl(int, int,...)
Definition: win32.c:4312
#define F_DUPFD
Definition: win32.h:602
int rb_w32_set_nonblock(int)
Definition: win32.c:4420
#define F_GETFD
Definition: win32.h:603
#define F_SETFD
Definition: win32.h:604
int ioctl(int, int,...)
Definition: win32.c:2841
#define F_SETFL
Definition: win32.h:608
#define F_DUPFD_CLOEXEC
Definition: win32.h:609